GIT d38b69689c349f35502b92e20dafb30c62d49d63 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git commit d38b69689c349f35502b92e20dafb30c62d49d63 Author: Linus Torvalds Date: Mon Jun 26 16:59:26 2006 -0700 Revert "kbuild: fix make -rR breakage" This reverts commit e5c44fd88c146755da6941d047de4d97651404a9. Thanks to Daniel Ritz and Michal Piotrowski for noticing the problem. Daniel says: "[The] reason is a recent change that made modules always shows as module.mod. it breaks modprobe and probably many scripts..besides lsmod looking horrible stuff like this in modprobe.conf: install pcmcia_core /sbin/modprobe --ignore-install pcmcia_core; /sbin/modprobe pcmcia makes modprobe fork/exec endlessly calling itself...until oom interrupts it" Signed-off-by: Linus Torvalds commit f964c303fe33b0d2ee563349bc8bea4d57d7a265 Author: Ben Dooks Date: Mon Jun 26 22:51:08 2006 +0100 [ARM] 3657/1: S3C24XX: Documentation update of Overview.txt Patch from Ben Dooks Update the list of supported devices, and remove the changelog. Add SMDK2413 information.-- Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 18555656de7268c7af77ea2b99a2fc984e7a23fb Author: Russell King Date: Mon Jun 26 22:50:21 2006 +0100 [ARM] Update mach-types Usual mach-types update. Signed-off-by: Russell King commit 3fb5a9891dbb553dda96783dbc0dc4e77cbb2529 Author: Adrian Bunk Date: Tue May 16 17:26:41 2006 +0200 [PATCH] fs/ocfs2/dlm/: cleanups This patch #if 0's the no longer used dlm_dump_lock_resources(). Since this makes dlmdebug.h empty, this patch also removes this header. Additionally, the needlessly global dlm_is_node_recovered() is made static. Signed-off-by: Adrian Bunk Signed-off-by: Mark Fasheh commit 43dee336c903fae15783b90983dfdedd2c7ffefc Author: Mark Fasheh Date: Mon May 1 14:56:57 2006 -0700 ocfs2: fix compiler warnings in dlm_convert_lock_handler() We need to cast to unsigned long long. Signed-off-by: Mark Fasheh commit 8a9343fa24d8d3fcb189bed2b7afcf4b8a8c1c8d Author: Mark Fasheh Date: Mon May 1 14:55:10 2006 -0700 ocfs2: dlm_print_one_mle() needs to be defined Fixes compile breakage. Signed-off-by: Mark Fasheh commit 0032abd674a606c3cf2d9961c8119f5d72c411d0 Author: Kurt Hackel Date: Mon May 1 14:39:57 2006 -0700 ocfs2: remove whitespace in dlmunlock.c Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 3156d267016627fe427a6b0d4ed8a9678557e91e Author: Kurt Hackel Date: Mon May 1 14:39:29 2006 -0700 ocfs2: move dlm work to a private work queue The work that is done can block for long periods of time and so is not appropriate for keventd. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 495ac96e638cb0ad33baa7113531d742bfb328d4 Author: Kurt Hackel Date: Mon May 1 14:34:08 2006 -0700 ocfs2: fix incorrect error returns Use DLM_REJECTED instead of DLM_RECOVERING. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 3b3b84a892d37ba336391e411eb5f8b013b9a669 Author: Kurt Hackel Date: Mon May 1 14:31:37 2006 -0700 ocfs2: tune down some noisy messages during dlm recovery Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 56a7c104bc91b4a5f970d7372ebb04eebc633c68 Author: Kurt Hackel Date: Mon May 1 14:30:39 2006 -0700 ocfs2: display message before waiting for recovery to complete Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 44a7f1d063bbe45773353903f36d9d88fb73d82a Author: Kurt Hackel Date: Mon May 1 14:29:59 2006 -0700 ocfs2: mlog in dlm_convert_lock_handler() should be ML_ERROR Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit b220532a71adf65d45c3aa8a284bfa7ec57957bd Author: Kurt Hackel Date: Mon May 1 14:29:28 2006 -0700 ocfs2: retry operations when a lock is marked in recovery Before checking for a nonexistent lock, make sure the lockres is not marked RECOVERING. The caller will just retry and the state should be fixed up when recovery completes. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit f85cd47a5825b77a146bad6870b2ddcf08415c13 Author: Kurt Hackel Date: Mon May 1 14:27:41 2006 -0700 ocfs2: use cond_resched() in dlm_thread() yield() does not yield. cond_resched() does. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit ad8100e0d20e0123def9f83c040b68c96c8638f0 Author: Kurt Hackel Date: Mon May 1 14:25:21 2006 -0700 ocfs2: use GFP_NOFS in some dlm operations Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit b7084ab538ac2bd71ce494cf1cbbea9fe9db2c07 Author: Kurt Hackel Date: Mon May 1 13:54:07 2006 -0700 ocfs2: wait for recovery when starting lock mastery Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit c27069e6cfa242a3b84eb3442934c6fe51ee9066 Author: Kurt Hackel Date: Mon May 1 13:51:49 2006 -0700 ocfs2: continue recovery when a dead node is encountered Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 67a187412baa84dfff2d423961d86663b7fc7d3c Author: Kurt Hackel Date: Mon May 1 13:50:12 2006 -0700 ocfs2: remove unneccesary spin_unlock() in dlm_remaster_locks() Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 6a41321121ee2af33b8ac55c87657603df480b25 Author: Kurt Hackel Date: Mon May 1 13:49:20 2006 -0700 ocfs2: dlm_remaster_locks() should never exit without completing We cannot restart recovery. Once we begin to recover a node, keep the state of the recovery intact and follow through, regardless of any other node deaths that may occur. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit c8df412e1c746dd21094966d04b3a79aad0f4d08 Author: Kurt Hackel Date: Mon May 1 13:47:50 2006 -0700 ocfs2: special case recovery lock in dlmlock_remote() If the previous master of the recovery lock dies, let calc_usage take it down completely and let the caller completely redo the dlmlock() call. Otherwise, there will never be an opportunity to re-master the lockres and recovery wont be able to progress. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 36407488b1cbc4d84bc2bd14e03f3f9b768090d9 Author: Kurt Hackel Date: Mon May 1 13:32:27 2006 -0700 ocfs2: pending mastery asserts and migrations should block each other Use the existing structure for blocking migrations when ASTs are pending to achieve the same result. If we can catch the assert before it goes on the wire, just cancel it and let the migration continue. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit c87a9ae7059f718bf1bb87a702fcbef535e32111 Author: Kurt Hackel Date: Mon May 1 13:30:49 2006 -0700 ocfs2: temporarily disable automatic lock migration Now we never change the owner of a lock resource until unmount or node death. This will be re-enabled once some issues in the algorithm used have been resolved. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 2abaf97e62e51fdd09d5a46703b3b680f24bdd8b Author: Kurt Hackel Date: Mon May 1 13:27:10 2006 -0700 ocfs2: do not unconditionally purge the lockres in dlmlock_remote() In dlmlock_remote(), do not call purge_lockres until the lock resource actually changes. otherwise, the mastery info on the lockres will go away underneath the caller. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit aa087b84977173395c0e3a1e0c1773314958f277 Author: Kurt Hackel Date: Mon May 1 12:02:07 2006 -0700 ocfs2: increase backoff before waiting for recovery When mastering non-recovery lock resources, additional time was frequently needed to allow the disk heartbeat to catch up with the network timeout. the recovery lock resource is time critical and avoids this path. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit f42a100b2272bc5cb44fb2aa03526b436b1d6833 Author: Kurt Hackel Date: Mon May 1 11:53:33 2006 -0700 ocfs2: have dlm_pre_master_reco_lockres() ignore dead nodes Recovery will spin in dlm_pre_master_reco_lockres if we do not ignore timed-out network responses from dead nodes. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 6ff06a93916b3f95e83c346f7530cf2f5c68ae0c Author: Kurt Hackel Date: Mon May 1 11:51:45 2006 -0700 ocfs2: give the dlm dirty list a reference on the lockres Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit e7e69eb38946ebef86e27442d01514fcf9c854ee Author: Kurt Hackel Date: Mon May 1 11:49:52 2006 -0700 ocfs2: teach dlm_restart_lock_mastery() to wait on recovery Change behavior of dlm_restart_lock_mastery() when a node goes down. Dump all responses that have been collected and start over. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit e4eb03681a8313168d99c2f93175331a898a2c16 Author: Kurt Hackel Date: Mon May 1 11:46:59 2006 -0700 ocfs2: gracefully handle stale create_lock messages. This is an error on the sending side, so gracefully error out on the receiving end. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit ccd8b1f916bc5e4b2156f03ccd3546be7f65f6b3 Author: Kurt Hackel Date: Mon May 1 11:32:14 2006 -0700 ocfs2: update lvb immediately during recovery Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 588e00902b06528c476eed38019dba4a087def01 Author: Kurt Hackel Date: Mon May 1 11:22:06 2006 -0700 ocfs2: do not send master requests to localhost Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 8b2198097ae6a5b54ed92345989ec343070f916b Author: Kurt Hackel Date: Mon May 1 11:16:45 2006 -0700 ocfs2: purge lockres' sooner Immediately purge a lockress that the local node is not the master of. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 343e26a4007d14c2154c1d13d1209797dce5c535 Author: Kurt Hackel Date: Mon May 1 11:15:04 2006 -0700 ocfs2: dump mismatching migrated lvbs before BUG() Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 466d1a4591c4e1bc3affd5c0cf3df5ad20338fb9 Author: Kurt Hackel Date: Mon May 1 11:11:13 2006 -0700 ocfs2: make dlm recovery finalization 2 stage Makes it easier for the recovery process to deal with node death. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 69d72b066cc5971318d9e29e34289b74cf8a9d22 Author: Kurt Hackel Date: Mon May 1 10:57:51 2006 -0700 ocfs2: dlm recovery / lockres reference count fix Take a reference on lockres structures while they are on the recovery list. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit a9ee4c8a67b962db0208addf0e32935aa571af6b Author: Kurt Hackel Date: Thu Apr 27 19:26:15 2006 -0700 ocfs2: better error handling during assert master message handle errors during lock assert master by either killing self or other node Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit a7f90d83ea8dc8b0999ab7c1c0539af9a6ed69d2 Author: Kurt Hackel Date: Thu Apr 27 19:24:21 2006 -0700 ocfs2: dump lockres info before we BUG() on a bad reference Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit c0a8520c7333dd62624683772f31864c7f9c46d9 Author: Mark Fasheh Date: Thu Apr 27 19:07:45 2006 -0700 ocfs2: do LVB puts in place Don't wait until the AST will be fired to do the LVB copy into the lock resource. Signed-off-by: Mark Fasheh commit aa85235427992b8d3040297d9174d69dd1d8a675 Author: Kurt Hackel Date: Thu Apr 27 19:04:49 2006 -0700 ocfs2: mle ref count debugging Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit dc2ed195dda848c8e4b24f3f0e1952fa74f74f6b Author: Kurt Hackel Date: Thu Apr 27 19:03:18 2006 -0700 ocfs2: allow for an assert message during lock mastery Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 2d1a868c563f07c07c681836d273d69efb7c5ad8 Author: Kurt Hackel Date: Thu Apr 27 19:01:35 2006 -0700 ocfs2: take mle reference during migration Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 41b8c8a101ba77f59d9a4b3cac6c846cb8a34840 Author: Kurt Hackel Date: Thu Apr 27 19:00:26 2006 -0700 ocfs2: properly initialize the mle structure Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit da01ad05528bf6f6bcb286329b14225a71713325 Author: Kurt Hackel Date: Thu Apr 27 18:53:04 2006 -0700 ocfs2: detach mle from heartbeat events Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit a2bf04774bf4aa0a75036c1e92e3d2fd1cce2aff Author: Kurt Hackel Date: Thu Apr 27 18:51:26 2006 -0700 ocfs2: mle ref counting fixes Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 958837197e6415009cba0f31bbb5aacdb936ef09 Author: Kurt Hackel Date: Thu Apr 27 18:47:41 2006 -0700 ocfs2: better mle debugging Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit d6dea6e9732f5319b723e14f7adbc5f99cd69aec Author: Kurt Hackel Date: Thu Apr 27 18:08:51 2006 -0700 ocfs2: clean up recovery related messages Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 29c0fa0f56f20b4512f65b0f3e55bc8af50485b7 Author: Kurt Hackel Date: Thu Apr 27 18:06:58 2006 -0700 ocfs2: handle network errors during recovery Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit c3187ce5e335cf8e06391236cc1ad7d1b1e193ed Author: Kurt Hackel Date: Thu Apr 27 18:05:41 2006 -0700 ocfs2: only recover one dead node at a time Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit ab27eb6f47092923a92f7c164dcf9be3b76f3944 Author: Kurt Hackel Date: Thu Apr 27 18:03:49 2006 -0700 ocfs2: Better tracking for recovery state changes Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 8bc674cb4834fb25206b7f7f5e37fe571aa76b34 Author: Kurt Hackel Date: Thu Apr 27 18:02:10 2006 -0700 ocfs2: Fix empty lvb check The check for an empty lvb should check the entire buffer not just the first byte. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit aba9aac78817d88aa2b223f1aedf1e9815ae97b8 Author: Kurt Hackel Date: Thu Apr 27 18:00:21 2006 -0700 ocfs2: fix inverted logic in dlm_is_node_dead Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 2580a580e029f9a59a66cd230b1fd7e2d9ee339d Author: Kurt Hackel Date: Thu Apr 27 17:59:46 2006 -0700 ocfs2: recheck lockres master before sending an unlock request. Recovery may have happened and it may now be mastered locally. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 8d79d088e88198d5456861ee9e6a8226dcd08799 Author: Kurt Hackel Date: Thu Apr 27 17:58:23 2006 -0700 ocfs2: add a small delay after a failed migration Otherwise we risk starving other threads. Signed-off-by: Kurt Hackel Signed-off-by: Mark Fasheh commit 685f1adb3872d904e08e22fab699f34432d5068a Author: Mark Fasheh Date: Thu Mar 23 11:23:29 2006 -0800 ocfs2: silence a compile warning in dlm_alloc_pagevec() Reported by Andrew Morton. Signed-off-by: Mark Fasheh commit c8f33b6e86af74ee7b800f57cac7b3c8559318fe Author: Joel Becker Date: Thu Mar 16 17:40:37 2006 -0800 [PATCH] ocfs2: Alloc at least a page for the DLM hash The OCFS2 DLM allocates a number of pages for a hash to lookup locks. There was a bug where a PAGE_SIZE bigger than the hash size (eg, 64K pages) would result in zero pages allocated. Signed-off-by: Joel Becker Signed-off-by: Mark Fasheh commit 03d864c02c3ea803b1718940ac6953a257182d7a Author: Daniel Phillips Date: Fri Mar 10 18:08:16 2006 -0800 ocfs2: allocate lockres hash pages in an array This allows us to have a hash table greater than a single page which greatly improves dlm performance on some tests. Signed-off-by: Daniel Phillips Signed-off-by: Mark Fasheh commit 95c4f581d6551de55cf5b8693db98b01ce07021b Author: Mark Fasheh Date: Fri Mar 10 13:44:00 2006 -0800 ocfs2: inline dlm_lockres_get() It's called on every lookup so this might help performance a bit. Signed-off-by: Mark Fasheh commit 4198985f7ae119a23f83503a692dd822bd574080 Author: Daniel Phillips Date: Fri Mar 10 13:31:47 2006 -0800 [PATCH] Clean up ocfs2 hash probe and make it faster Signed-Off-By: Daniel Phillips Signed-off-by: Mark Fasheh commit a3d3329159ea76bae0b3b8680691a1c3ecf5801f Author: Mark Fasheh Date: Thu Mar 9 17:55:56 2006 -0800 ocfs2: calculate lockid hash values outside of the spinlock Fixes a performance bug - pointed out by Andrew. Signed-off-by: Mark Fasheh commit 65c491d833a06fd0d1383297590772c75d28155c Author: Mark Fasheh Date: Mon Mar 6 15:36:17 2006 -0800 ocfs2: move lockres qstr next to hlist_node structure Gains us a bit of performance on loads which heavily hit the lockres hash. Patch suggested by Daniel Phillips . Signed-off-by: Mark Fasheh commit a09ab7e2fcd22f0490a270bb310536c651d53cb9 Author: mark gross Date: Fri Jun 23 15:13:07 2006 -0700 [PATCH] type-oh bug in tlclk.c Mark Bellon found a bug in my tlclk driver. Thanks! I botch the register mask for store_received_ref_clk3a. See http://download.intel.com/design/network/manuals/30412001.pdf tables 124 and 136 for details. Signed-off-by: Mark Gross Signed-off-by: Linus Torvalds commit 916d15445f4ad2a9018e5451760734f36083be77 Author: Karsten Keil Date: Mon Jun 26 20:21:01 2006 +0200 [PATCH] fix processing of the last byte in isdn_readbchan_tty() The changes in the tty handling contain a bug while accessing the last byte in the skb. Since special sequence for control of DTMF and FAX via ttyI* devices handled via this path, these services do not work anymore. Signed-off-by: Karsten Keil Signed-off-by: Linus Torvalds commit 5fd571cbc13db113bda26c20673e1ec54bfd26b4 Author: Eric Sesterhenn Date: Wed Jun 21 20:56:26 2006 +0200 [PATCH] Array overrun in drivers/infiniband/core/cma.c This was spotted by coverity #id 1300. Since the array has only four elements, we should just use those four. Signed-off-by: Eric Sesterhenn Acked-by: Sean Hefty Signed-off-by: Linus Torvalds commit 09c0dc68625c06f5b1e786aad0d5369b592179e6 Author: Linus Torvalds Date: Mon Jun 26 11:55:42 2006 -0700 Revert "[PATCH] kthread: update loop.c to use kthread" This reverts commit c7b2eff059fcc2d1b7085ee3d84b79fd657a537b. Hugh Dickins explains: "It seems too little tested: "losetup -d /dev/loop0" fails with EINVAL because nothing sets lo_thread; but even when you patch loop_thread() to set lo->lo_thread = current, it can't survive more than a few dozen iterations of the loop below (with a tmpfs mounted on /tst): j=0 cp /dev/zero /tst while : do let j=j+1 echo "Doing pass $j" losetup /dev/loop0 /tst/zero mkfs -t ext2 -b 1024 /dev/loop0 >/dev/null 2>&1 mount -t ext2 /dev/loop0 /mnt umount /mnt losetup -d /dev/loop0 done it collapses with failed ioctl then BUG_ON(!bio). I think the original lo_done completion was more subtle and safe than the kthread conversion has allowed for." Signed-off-by: Linus Torvalds commit 6e58f5c9a841e59233c5997df082e93329ea61e0 Author: Ben Dooks Date: Mon Jun 26 19:46:39 2006 +0100 [ARM] 3656/1: S3C2412: Add S3C2412 and S3C2413 documenation Patch from Ben Dooks Add some basic documentation about the support for the S3C2412 and S3C2413 CPUs-- Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 954b36d48b495afed2880320750858a2eae312c9 Author: Greg Ungerer Date: Mon Jun 26 16:33:15 2006 +1000 [PATCH] m68knommu: use configurable RAM setup page_offset.h Remove board specific base RAM conditionals from page_offset.h With the Kconfig time configurable RAM setup none of this is required. It is all based on the Kconfig (CONFIG_RAMBASE) option now. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 12ddae3348def8808fb755b23225b18fc4adfbe3 Author: Greg Ungerer Date: Mon Jun 26 16:33:09 2006 +1000 [PATCH] m68knommu: use configurable RAM setup in start up code Change to using a configurable RAM setup in startup code. This cleans up the whole RAM base/sizing issue, and removes a lot of board specific code. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 73e2fba8dc1e0a686073a5183be1a99e9285d2ac Author: Greg Ungerer Date: Mon Jun 26 16:33:05 2006 +1000 [PATCH] m68knommu: use configurable RAM setup in linker script Remove the fixed RAM configurations for each board type from the linker script. Replace with simple defines usng the flexible RAM configuration options. This cleans out of lot of board specific munging of addresses. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 63e413d19db0018e443a43c6c7a482993edf79cf Author: Greg Ungerer Date: Mon Jun 26 16:32:59 2006 +1000 [PATCH] m68knommu: create configurable RAM setup Reworked the way RAM regions are defined. Instead of coding all the variations for each board type we now just configure RAM base and size in the usual Kconfig setup. This much simplifies the code, and makes it a lot more flexible when setting up new boards or board varients. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit d2f386d7c182c1420f797093d67bb09a7251f113 Author: Greg Ungerer Date: Mon Jun 26 16:34:09 2006 +1000 [PATCH] m68knommu: remove unused vars from generic 68328 start code Clean out unused variable definitions from 68328 start up code. Also use a more appropriate start address for the case of relocating the kernel code to RAM (from ROM/flash). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 2ae9cb6bd4c23616b229b135ea57a93a6a24e13a Author: Greg Ungerer Date: Mon Jun 26 16:34:04 2006 +1000 [PATCH] m68knommu: remove __ramvec from 68328/pilot start code __ramvec has been removed from the linker script. The vector base address is defined as a configurable option, use that. Remove its use from the 68328/pilot startup code. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 8501a2fbe762b21d2504ed3aca3b52be61b5e6e4 Author: Eric Sandeen Date: Mon Jun 26 14:00:08 2006 +0200 [PATCH] x86_64: x86_64 stack usage debugging Applies to git & 2.6.17-rc6 after CONFIG_DEBUG_STACKOVERFLOW patch uses same stack-zeroing mechanism as on i386 to discover maximum stack excursions. Signed-off-by: Eric Sandeen Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 4961f10e2205d0ededa291e12ec634efc58aa93c Author: Eric Sandeen Date: Mon Jun 26 14:00:05 2006 +0200 [PATCH] x86_64: (resend) x86_64 stack overflow debugging Take two, now without spurious whitespace :( Applies to git & 2.6.17-rc6 CONFIG_DEBUG_STACKOVERFLOW existed for x86_64 in 2.4, but seems to have gone AWOL in 2.6. I've pretty much just copied this over from the 2.4 code, with appropriate tweaks for the 2.6 kernel, plus a bugfix. I'd personally rather see it printed out the way other arches do it, i.e. bytes-remaining-until-overflow, rather than having to do the subtraction yourself. Also, only 128 bytes remaining seems awfully late to issue a warning. But I'll start here :) Signed-off-by: Eric Sandeen Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit a4cffb6444c327677f901323ecf1a13d6bd2df3f Author: Christian Kujau Date: Mon Jun 26 14:00:02 2006 +0200 [PATCH] x86_64: msi_apic.c build fix CC drivers/pci/msi-apic.o In file included from include/asm/msi.h:11, from drivers/pci/msi.h:71, from drivers/pci/msi-apic.c:8: include/asm/smp.h:103: error: syntax error before '->' token akpm: nasty. It appears to be static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask) conflicting with include/asm-x86_64/mach_apic.h's #define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid) And I don't know which patch in rc4-mm1 triggered this. Fixing this in the .c file seems wrong. Including asm/smp.h instead of linux/smp.h seems wrong too. Need that .config. Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 0080e667550db5ae8c9318181500c413b99ff164 Author: Venkatesh Pallipadi Date: Mon Jun 26 13:59:59 2006 +0200 [PATCH] x86_64: i386/x86-64 Add nmi watchdog support for new Intel CPUs Intel now has support for Architectural Performance Monitoring Counters ( Refer to IA-32 Intel Architecture Software Developer's Manual http://www.intel.com/design/pentium4/manuals/253669.htm ). This feature is present starting from Intel Core Duo and Intel Core Solo processors. What this means is, the performance monitoring counters and some performance monitoring events are now defined in an architectural way (using cpuid). And there will be no need to check for family/model etc for these architectural events. Below is the patch to use this performance counters in nmi watchdog driver. Patch handles both i386 and x86-64 kernels. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit e77deacb7b078156fcadf27b838a4ce1a65eda04 Author: Keith Owens Date: Mon Jun 26 13:59:56 2006 +0200 [PATCH] x86_64: Avoid broadcasting NMI IPIs On some i386/x86_64 systems, sending an NMI IPI as a broadcast will reset the system. This seems to be a BIOS bug which affects machines where one or more cpus are not under OS control. It occurs on HT systems with a version of the OS that is not compiled without HT support. It also occurs when a system is booted with max_cpus=n where 2 <= n < cpus known to the BIOS. The fix is to always send NMI IPI as a mask instead of as a broadcast. Signed-off-by: Keith Owens Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 704fc59e1d056de80beaf30174bc8e0b1682efbb Author: Siddha, Suresh B Date: Mon Jun 26 13:59:53 2006 +0200 [PATCH] x86_64: fix apic error on bootup Appended patch fixes the "APIC error on CPUX: 00(40)" observed during bootup. From SDM Vol-3A "Valid Interrupt Vectors" section: "When an illegal vector value (0-15) is written to an LVT entry and the delivery mode is Fixed, the APIC may signal an illegal vector error, with out regard to whether the mask bit is set or whether an interrupt is actually seen on input." Signed-off-by: Suresh Siddha Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 03fdc2c277afdbd217eccd1ce0cfeff77ebd8b77 Author: Chuck Ebbert <76306.1226@compuserve.com> Date: Mon Jun 26 13:59:50 2006 +0200 [PATCH] x86_64: enlarge window for stack growth Allow stack growth so the 'enter' instruction works. Also fixes problem in compat_sys_kexec_load() which could allocate more than 128 bytes using compat_alloc_user_space(). Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 6bfa9bb5195c68f75bd3937e4d77cb0bfe852d0d Author: Andi Kleen Date: Mon Jun 26 13:59:47 2006 +0200 [PATCH] x86_64: Minor string functions optimizations - Use tail call from clear_user to __clear_user to save some code size - Use standard memcpy for forward memmove Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 2ee60e17896c65da1df5780d3196c050bccb7d10 Author: Andi Kleen Date: Mon Jun 26 13:59:44 2006 +0200 [PATCH] x86_64: Move export symbols to their C functions Only exports for assembler files are left in x8664_ksyms.c Originally inspired by a patch from Al Viro Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 45486f81c9aa07218b73a38cbcf62ffa66e99088 Author: Keith Owens Date: Mon Jun 26 13:59:41 2006 +0200 [PATCH] x86_64: Standardize i386/x86_64 handling of NMI_VECTOR x86_64 and i386 behave inconsistently when sending an IPI on vector 2 (NMI_VECTOR). Make both behave the same, so IPI 2 is sent as NMI. The crash code was abusing send_IPI_allbutself() by passing a code instead of a vector, it only worked because crash knew about the internal code of send_IPI_allbutself(). Change crash to use NMI_VECTOR instead, and remove the comment about how crash was abusing the function. This patch is a pre-requisite for fixing the problem where sending an IPI as NMI would reboot some Dell Xeon systems. I cannot fix that problem while crash continus to abuse send_IPI_allbutself(). It also removes the inconsistency between i386 and x86_64 for NMI_VECTOR. That will simplify all the RAS code that needs to bring all the cpus to a clean stop, even when one or more cpus are spinning disabled. Signed-off-by: Keith Owens Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 9c63f8738734eb7e6d3f76ca03186f16ef88edf5 Author: Piotr Kaczuba Date: Mon Jun 26 13:59:38 2006 +0200 [PATCH] x86_64: Fix modular pc speaker It turned out that the following change is needed when the speaker is compiled as a module. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit d39159c27fe1375bb7773d364213b1047265022c Author: Adrian Bunk Date: Mon Jun 26 13:59:35 2006 +0200 [PATCH] x86_64: remove sys32_ni_syscall() This patch removes the no longer used sys32_ni_syscall() Signed-off-by: Adrian Bunk Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 409f89e0efcfea1a8b25f9c4a050c0cf1f1cb87c Author: Sergey Vlasov Date: Mon Jun 26 13:59:32 2006 +0200 [PATCH] x86_64: Do not use -ffunction-sections for modules Currently CONFIG_REORDER uses -ffunction-sections for all code; however, creating a separate section for each function is not useful for modules and just adds bloat. Moving this option from CFLAGS to CFLAGS_KERNEL shrinks module object files (e.g., the module tree for a kernel built with most drivers as modules shrinked from 54M to 46M), and decreases the number of sysfs files in /sys/module/*/sections/ directories. Signed-off-by: Sergey Vlasov Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 899ced0dd9457b9c349663ca4cb4ec09167728a6 Author: Andreas Mohr Date: Mon Jun 26 13:59:29 2006 +0200 [PATCH] x86_64: Add cpu_relax to apic_wait_icr_idle This one is adding a cpu_relax() that already existed in the i386 version. Signed-off-by: Andreas Mohr Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit cab093b9d4b40c71c6261a11ba8f1ca027e09008 Author: Jan Beulich Date: Mon Jun 26 13:59:26 2006 +0200 [PATCH] x86_64: adjust kstack_depth_to_print default Defaulting to a value not evenly divisible by four makes little sense, as four values are displayed per line (and hence the rest of the line would otherwise be wasted). Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit bdbdaa791fb5b97ba5b3124c7593ffe308e2afef Author: Jan Beulich Date: Mon Jun 26 13:59:23 2006 +0200 [PATCH] i386/x86-64: adjust /proc/interrupts column headings With (significantly) more than 10 CPUs online, the column headings drifted off the positions of the column contents with growing CPU numbers. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit da5311258d2afb96fc592c8b11e818facfa46dc3 Author: Andi Kleen Date: Mon Jun 26 13:59:20 2006 +0200 [PATCH] x86_64: Fix race in cpu_local_* on preemptible kernels When a process changes CPUs while doing the non atomic cpu_local_* operations it might operate on the local_t of a different CPUs. Fix that by disabling preemption. Pointed out by Christopher Lameter Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 75bd665cc9f4d0f67164d9145e446ae554d4ed3f Author: Andi Kleen Date: Mon Jun 26 13:59:17 2006 +0200 [PATCH] x86_64: Fix fast check in safe_smp_processor_id The APIC ID returned by hard_smp_processor_id can be beyond NR_CPUS and then overflow the x86_cpu_to_apic[] array. Add a check for overflow. If it happens then the slow loop below will catch. Bug pointed out by Doug Thompson Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit e42f94373764d825e2c0464092738f66f5d3effb Author: Rohit Seth Date: Mon Jun 26 13:59:14 2006 +0200 [PATCH] x86_64: x86_64 setup.c - printing cmp related boottime information Getting phys_proc_id and cpu_core_id information to be printed at boot time for AMD processors. Also matching the Node related boot time information that gets printed for Intel and AMD processors for NUMA configurations. Signed-off-by: Rohit Seth Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 495ab9c045e1b0e5c82951b762257fe1c9d81564 Author: Andi Kleen Date: Mon Jun 26 13:59:11 2006 +0200 [PATCH] i386/x86-64/ia64: Move polling flag into thread_info_status During some profiling I noticed that default_idle causes a lot of memory traffic. I think that is caused by the atomic operations to clear/set the polling flag in thread_info. There is actually no reason to make this atomic - only the idle thread does it to itself, other CPUs only read it. So I moved it into ti->status. Converted i386/x86-64/ia64 for now because that was the easiest way to fix ACPI which also manipulates these flags in its idle function. Cc: Nick Piggin Cc: Tony Luck Cc: Len Brown Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit d9005b52de7bc9b20afa93e06d3e15843bafc12f Author: Andi Kleen Date: Mon Jun 26 13:59:08 2006 +0200 [PATCH] x86_64: Remove bogus RED-PEN comment in signal.c No red zone possible/needed on the alternative stack. It caused confusion. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 8fa3d6fc5e952300c26490167a93bf502de03a99 Author: Andrew Morton Date: Mon Jun 26 13:59:05 2006 +0200 [PATCH] x86_64: check_addr() cleanups - Use DMA_32BIT_MASK - Use %z for size_t - 80-cols Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 5f51e139d8b29116779044f26f84cceae34c31a4 Author: Jan Beulich Date: Mon Jun 26 13:59:02 2006 +0200 [PATCH] x86_64: miscellaneous mm/init.c fixes - fix an off-by-one error in phys_pmd_init() - prevent phys_pmd_init() from removing mappings established earlier - fix the direct mapping early printk to in fact show the end of the range - remove an apparently orphan comment Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit b633237e9c1b91b86c431c5d41266b47408b4642 Author: Andi Kleen Date: Mon Jun 26 13:58:59 2006 +0200 [PATCH] x86_64: Mark mce_amd cpu notifier __cpuinit/__cpuinitdata Cc: Jacob Shin Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 2903ee85ce462d66955b800a0c48e26e51de0aae Author: Jacob Shin Date: Mon Jun 26 13:58:56 2006 +0200 [PATCH] x86_64: mce_amd cleanup Clean up mce_amd.c for readability and remove code no longer needed. Signed-off-by: Jacob Shin Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 95268664390b19962ed41a3506c5bc8149db71e8 Author: Jacob Shin Date: Mon Jun 26 13:58:53 2006 +0200 [PATCH] x86_64: mce_amd support for family 0x10 processors Add support for mce threshold registers found in future AMD family 0x10 processors. Backwards compatible with family 0xF hardware. AK: fixed build on !SMP Signed-off-by: Jacob Shin Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit fff2e89f11dd9b9b45e9212bc543154ca3d028a1 Author: Jacob Shin Date: Mon Jun 26 13:58:50 2006 +0200 [PATCH] x86_64: mce_amd relocate sysfs files Get rid of /sys/devices/system/threshold directory and move mce_amd thresholding files into the machine sysfs directory -- /sys/devices/system/machinecheck. AK: Fixed warning Signed-off-by: Jacob Shin Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 17fc14ff1bdbc393e1cf4f6fd1e1e53d72ab9fe5 Author: Jacob Shin Date: Mon Jun 26 13:58:47 2006 +0200 [PATCH] x86_64: apic support for extended apic interrupt Add support for extended APIC LVT found in future AMD processors. Signed-off-by: Jacob Shin Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit c38bfdc85aae0c6d1458269c0e063c2f4a116711 Author: Andi Kleen Date: Mon Jun 26 13:58:44 2006 +0200 [PATCH] x86_64: Move VM86 config into arch/i386/Kconfig Architecture specific configs like this have no business at all in init/Kconfig. This prevents it from being set on x86-64 Pointed out by H.Peter Anvin Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit bf660254e0d430e5d991e432d5dad8d6714828f6 Author: Andi Kleen Date: Mon Jun 26 13:58:41 2006 +0200 [PATCH] i386/x86-64: Fix isoimage when syslinux is in /usr/share It's like this on SUSE systems. Cc: hpa@zytor.com Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 2f82bde472184f989283c173c1eb95bab455a774 Author: Vojtech Pavlik Date: Mon Jun 26 13:58:38 2006 +0200 [PATCH] x86_64: Update copyright in time.c Update my copyright dates in arch/x86-64/kernel/time.c Signed-off-by: Vojtech Pavlik Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit b2df3ddb68fc02e3bae78b7adaeca8561d02ea6d Author: Vojtech Pavlik Date: Mon Jun 26 13:58:35 2006 +0200 [PATCH] x86_64: Explain why HPET T0_CMP register is written twice After writing the CFG register, the first value written to the T0_CMP register is the value at which next interrupt should be triggered, every value after that sets the period of the interrupt. For that reason, the code needs to write the value twice - to set both the phase and period. [AK: I had already figured it out by myself, but it's still useful to have a comment for this.] Signed-off-by: Vojtech Pavlik Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 4221133845f81ab4428c79a89e37be2c87624c1a Author: Vojtech Pavlik Date: Mon Jun 26 13:58:32 2006 +0200 [PATCH] x86_64: Make use of the *PER* constants in time.c This patch makes use of the newly added conversion constants in time.h to x86-64 time.c. The code gets significantly easier to understand. Signed-off-by: Vojtech Pavlik Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit e30db3e69948dafb616d121e52c8d62d38dab68c Author: Vojtech Pavlik Date: Mon Jun 26 13:58:29 2006 +0200 [PATCH] x86_64: Remove hack to manually enable HPET on AMD8111 southbridges Remove #ifdefed code to manually enable HPET on AMD8111, where the BIOS doesn't have ACPI HPET tables and doesn't enable it for us. Signed-off-by: Vojtech Pavlik Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 7b0e85012581a9a8b12a8191d365716bf3ca3d3c Author: Vojtech Pavlik Date: Mon Jun 26 13:58:26 2006 +0200 [PATCH] x86_64: Add X86_FEATURE_RDTSCP, fix rdtscp in /proc/cpuinfo This patch adds the X86_FEATURE_RDTSCP #define, so that kernel code can check for the feature easily and also fixes the location of the "rdtscp" string in the cpuinfo tables. Signed-off-by: Vojtech Pavlik Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit f8bf3c65a962530821fa9a9b4bad43d8c7e13574 Author: Vojtech Pavlik Date: Mon Jun 26 13:58:23 2006 +0200 [PATCH] x86_64: Rename oem_force_hpet_timer to apic_is_clustered_box Rename oem_force_hpet_timer to apic_is_clustered_box, to give the function a better fitting name - it really isn't at all about HPET. Signed-off-by: Vojtech Pavlik Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 05ebb76109f302b949e745724bbf0f0634dba43f Author: Vojtech Pavlik Date: Mon Jun 26 13:58:20 2006 +0200 [PATCH] x86_64: Add useful constants to time.h In timekeeping code, one often does need to use conversion constants. Naming these leads to code that's easier to understand, showing the reader between which units the conversion is made. Signed-off-by: Vojtech Pavlik Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit f3fa8ebc25129bb69929e20b0c84049c39029d8d Author: Rohit Seth Date: Mon Jun 26 13:58:17 2006 +0200 [PATCH] x86_64: moving phys_proc_id and cpu_core_id to cpuinfo_x86 Most of the fields of cpuinfo are defined in cpuinfo_x86 structure. This patch moves the phys_proc_id and cpu_core_id for each processor to cpuinfo_x86 structure as well. Signed-off-by: Rohit Seth Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit e465058d55a88feb4c7ecabe63eea7ea7147e206 Author: Jon Mason Date: Mon Jun 26 13:58:14 2006 +0200 [PATCH] x86_64: Calgary IOMMU - Calgary specific bits This patch hooks Calgary into the build, the x86-64 IOMMU initialization paths, and introduces the Calgary specific bits. The implementation draws inspiration from both PPC (which has support for the same chip but requires firmware support which we don't have on x86-64) and gart. Calgary is different from gart in that it support a translation table per PHB, as opposed to the single gart aperture. Changes from previous version: * Addition of boot-time disablement for bus-level translation/isolation (e.g, enable userspace DMA for things like X) * Usage of newer IOMMU abstraction functions Signed-off-by: Muli Ben-Yehuda Signed-off-by: Jon Mason Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 0dc243ae10c8309c170a3af9f1adad1924a9f217 Author: Jon Mason Date: Mon Jun 26 13:58:11 2006 +0200 [PATCH] x86_64: Calgary IOMMU - IOMMU abstractions This patch creates a new interface for IOMMUs by adding a centralized location for IOMMU allocation (for translation tables/apertures) and IOMMU initialization. In creating these, code was moved around for abstraction, uniformity, and consiceness. Take note of the move of the iommu_setup bootarg parsing code to __setup. This is enabled by moving back the location of the aperture allocation/detection to mem init (which while ugly, was already the location of the swiotlb_init). While a slight departure from the previous patch, I belive this provides the true intention of the previous versions of the patch which changed this code. It also makes the addition of the upcoming calgary code much cleaner than previous patches. [AK: Removed one broken change. iommu_setup still has to be called early] Signed-off-by: Muli Ben-Yehuda Signed-off-by: Jon Mason Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit a3c042a0f022dade8e02bf6c9be5d2379d7e133c Author: Jon Mason Date: Mon Jun 26 13:58:08 2006 +0200 [PATCH] x86_64: Calgary IOMMU - move valid_dma_direction into the callers Based on Andi Kleen's comments on the original Calgary patch, move valid_dma_direction into the calling functions. Signed-off-by: Muli Ben-Yehuda Signed-off-by: Jon Mason Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 8d4f6b93a4aaa6b56b600cd1165c971f4395e4b3 Author: Jon Mason Date: Mon Jun 26 13:58:05 2006 +0200 [PATCH] x86_64: Calgary IOMMU - introduce iommu_detected swiotlb relies on the gart specific iommu_aperture variable to know if we discovered a hardware IOMMU before swiotlb initialization. Introduce iommu_detected to do the same thing, but in a HW IOMMU neutral manner, in preparation for adding the Calgary HW IOMMU. Signed-Off-By: Muli Ben-Yehuda Signed-Off-By: Jon Mason Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 2bbc419f9d51b44f3fdeea12c5b786bdace82b8e Author: Rohit Seth Date: Mon Jun 26 13:58:02 2006 +0200 [PATCH] x86_64: Change assembly to use regular cpuid_count macro Minor cleanup patch: Replacing the asm statement with cpuid_count macro(which already provides the same functionality). Signed-off-by: Rohit Seth Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 46d13a384bc695ec61458e5dcbac1eee6d623a9b Author: Jan Beulich Date: Mon Jun 26 13:57:59 2006 +0200 [PATCH] x86_64: use halt() instead of raw inline assembly Use abstractions whenever possible. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit d2ae5b5f6afd3c4caaf82444102a4372135cb994 Author: Andi Kleen Date: Mon Jun 26 13:57:56 2006 +0200 [PATCH] x86_64: Get rid of pud_offset_k / __pud_offset_k pud_offset_k() equivalent to pud_offset() now. Pointed out by Jan Beulich Similar for __pud_offset_ok, which needs a small change in the callers. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit b79c4df714ff190f7149d3d5a86278bdc25a90ec Author: Carl-Daniel Hailfinger Date: Mon Jun 26 13:57:53 2006 +0200 [PATCH] i386/x86-64: Consolidate arch/{i386,x86_64}/boot/compressed/misc.c Clean up arch/{i386,x86_64}/boot/compressed/misc.c a bit to reduce their differences. Should have zero effect on code generation. Signed-off-by: Carl-Daniel Hailfinger Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 83f4fcce7fdd213bd570b899862c3838871f8cf7 Author: Jan Beulich Date: Mon Jun 26 13:57:50 2006 +0200 [PATCH] x86_64: allow unwinder to build without module support Add proper conditionals to be able to build with CONFIG_MODULES=n. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit c33bd9aac0597eeedaaa01ea5aafe456894b2f2b Author: Jan Beulich Date: Mon Jun 26 13:57:47 2006 +0200 [PATCH] i386/x86-64: fall back to old-style call trace if no unwinding If no unwinding is possible at all for a certain exception instance, fall back to the old style call trace instead of not showing any trace at all. Also, allow setting the stack trace mode at the command line. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit fe7cacc1c25e286872b878c5d46880b620cd1e2d Author: Jan Beulich Date: Mon Jun 26 13:57:44 2006 +0200 [PATCH] i386: reliable stack trace support i386 entry.S To increase the usefulness of reliable stack unwinding, this adds CFI unwind annotations to many low-level i386 routines. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 176a2718f408ce92788b29127050b04dfd6e4f68 Author: Jan Beulich Date: Mon Jun 26 13:57:41 2006 +0200 [PATCH] i386: reliable stack trace support (i386) These are the i386-specific pieces to enable reliable stack traces. This is going to be even more useful once CFI annotations get added to he assembly code, namely to entry.S. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit dffead4e421e289c8434351400d24fd35723e874 Author: Jan Beulich Date: Mon Jun 26 13:57:38 2006 +0200 [PATCH] x86_64: reliable stack trace support (x86-64 syscall Adjust the CFA offset for 64- and 32-bit syscall entries so that the five slots pre-subtracted from the stack pointer do not appear to reside outside of the current frame. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 1de9c3f67ec6fddfb85325bab551f4094f55f410 Author: Jan Beulich Date: Mon Jun 26 13:57:35 2006 +0200 [PATCH] x86_64: reliable stack trace support (x86-64 IRQ stack Change the switching to/from the IRQ stack so that unwind annotations can be added for it without requiring CFA expressions. AK: I cleaned it up a bit, making it unconditional and removing the obsolete DEBUG_INFO full frame code. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit b538ed278b80641ee6d7b75497d5e14de1bb1137 Author: Jan Beulich Date: Mon Jun 26 13:57:32 2006 +0200 [PATCH] x86_64: reliable stack trace support (x86-64) These are the x86_64-specific pieces to enable reliable stack traces. The only restriction with this is that it currently cannot unwind across the interrupt->normal stack boundary, as that transition is lacking proper annotation. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 4552d5dc08b79868829b4be8951b29b07284753f Author: Jan Beulich Date: Mon Jun 26 13:57:28 2006 +0200 [PATCH] x86_64: reliable stack trace support These are the generic bits needed to enable reliable stack traces based on Dwarf2-like (.eh_frame) unwind information. Subsequent patches will enable x86-64 and i386 to make use of this. Thanks to Andi Kleen and Ingo Molnar, who pointed out several possibilities for improvement. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 2b28592b07223d7fc0691ce3fe57d495dc9cbe3a Author: bibo,mao Date: Mon Jun 26 13:57:25 2006 +0200 [PATCH] x86_64: x86_86 msi miss one entry handler In x86_64 architecture, if device driver with msi function gets 0xee vector by assign_irq_vector() function, system will crash if this interrupt happens. It is because 0xee interrupt entry is empty. This patch modifies this. This patch is based on 2.6.17-rc6. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit a813ce432f27c4f5011c7b5ac9d2bbbfeb41d9a7 Author: Andi Kleen Date: Mon Jun 26 13:57:22 2006 +0200 [PATCH] x86_64: Rename IOMMU option, fix help and mark option embedded. - Rename the GART_IOMMU option to IOMMU to make clear it's not just for AMD - Rewrite the help text to better emphatise this fact - Make it an embedded option because too many people get it wrong. To my astonishment I discovered the aacraid driver tests this symbol directly. This looks quite broken to me - it's an internal implementation detail of the PCI DMA API. Can the maintainer please clarify what this test was intended to do? Cc: linux-scsi@vger.kernel.org Cc: alan@redhat.com Cc: markh@osdl.org Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 4d9bc79cd28b779610d9590b3a96a28a0f64a25a Author: Andi Kleen Date: Mon Jun 26 13:57:19 2006 +0200 [PATCH] x86_64: Make sure is_compat_task works early Previously it would only work in the first 32bit system call, not during early process setup. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 26a3c49cec96ffb9cfcc30dfa0cd05ccc25dcb3a Author: Ingo Molnar Date: Mon Jun 26 13:57:16 2006 +0200 [PATCH] x86_64: fix vector_lock deadlock in io_apic.c Fix a potential deadlock scenario introduced by io_apic.c's new vector_lock on i386 and x86_64. Found by the locking correctness validator. The patch was boot-tested on x86. For details of the deadlock scenario, see the validator output: ====================================================== [ BUG: hard-safe -> hard-unsafe lock order detected! ] ------------------------------------------------------ idle/1 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: (msi_lock){....}, at: [] startup_msi_irq_wo_maskbit+0x10/0x35 and this task is already holding: (&irq_desc[i].lock){++..}, at: [] probe_irq_on+0x36/0x107 which would create a new lock dependency: (&irq_desc[i].lock){++..} -> (msi_lock){....} but this new dependency connects a hard-irq-safe lock: (&irq_desc[i].lock){++..} ... which became hard-irq-safe at: [] lockdep_acquire+0x68/0x84 [] _spin_lock+0x21/0x2f [] __do_IRQ+0x3d/0x113 [] do_IRQ+0x8c/0xad to a hard-irq-unsafe lock: (vector_lock){--..} ... which became hard-irq-unsafe at: ... [] lockdep_acquire+0x68/0x84 [] _spin_lock+0x21/0x2f [] assign_irq_vector+0x34/0xc8 [] setup_IO_APIC+0x45a/0xcff [] smp_prepare_cpus+0x5ea/0x8aa [] init+0x32/0x2cb [] kernel_thread_helper+0x5/0xb which could potentially lead to deadlocks! other info that might help us debug this: 3 locks held by idle/1: #0: (port_mutex){--..}, at: [] uart_add_one_port+0x61/0x289 #1: (&state->mutex){--..}, at: [] uart_add_one_port+0x73/0x289 #2: (&irq_desc[i].lock){++..}, at: [] probe_irq_on+0x36/0x107 the hard-irq-safe lock's dependencies: -> (&irq_desc[i].lock){++..} ops: 9861 { initial-use at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] setup_irq+0x9b/0x14d [] time_init_hook+0xf/0x11 [] time_init+0x44/0x46 [] start_kernel+0x191/0x38f [] 0xc0100210 in-hardirq-W at: [] lockdep_acquire+0x68/0x84 [] _spin_lock+0x21/0x2f [] __do_IRQ+0x3d/0x113 [] do_IRQ+0x8c/0xad in-softirq-W at: [] lockdep_acquire+0x68/0x84 [] _spin_lock+0x21/0x2f [] __do_IRQ+0x3d/0x113 [] do_IRQ+0x8c/0xad } ... key at: [] irq_desc_lock_type+0x0/0x20 -> (i8259A_lock){++..} ops: 5149 { initial-use at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] init_8259A+0x11/0x8f [] init_ISA_irqs+0x12/0x4d [] pre_intr_init_hook+0x8/0xa [] init_IRQ+0xe/0x65 [] start_kernel+0x178/0x38f [] 0xc0100210 in-hardirq-W at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] mask_and_ack_8259A+0x1b/0xcc [] __do_IRQ+0x4f/0x113 [] do_IRQ+0x8c/0xad in-softirq-W at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] mask_and_ack_8259A+0x1b/0xcc [] __do_IRQ+0x4f/0x113 [] do_IRQ+0x8c/0xad } ... key at: [] i8259A_lock+0x14/0x40 ... acquired at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] enable_8259A_irq+0x10/0x47 [] startup_8259A_irq+0x8/0xc [] setup_irq+0xe4/0x14d [] time_init_hook+0xf/0x11 [] time_init+0x44/0x46 [] start_kernel+0x191/0x38f [] 0xc0100210 -> (ioapic_lock){+...} ops: 122 { initial-use at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] io_apic_get_version+0x16/0x55 [] mp_register_ioapic+0xc6/0x127 [] acpi_parse_ioapic+0x2d/0x39 [] acpi_table_parse_madt_family+0xb4/0x100 [] acpi_table_parse_madt+0x16/0x18 [] acpi_boot_init+0x132/0x251 [] setup_arch+0xd36/0xe37 [] start_kernel+0x66/0x38f [] 0xc0100210 in-hardirq-W at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] mask_IO_APIC_irq+0x11/0x31 [] ack_edge_ioapic_vector+0x31/0x41 [] __do_IRQ+0x4f/0x113 [] do_IRQ+0x8c/0xad } ... key at: [] ioapic_lock+0x14/0x3c -> (i8259A_lock){++..} ops: 5149 { initial-use at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] init_8259A+0x11/0x8f [] init_ISA_irqs+0x12/0x4d [] pre_intr_init_hook+0x8/0xa [] init_IRQ+0xe/0x65 [] start_kernel+0x178/0x38f [] 0xc0100210 in-hardirq-W at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] mask_and_ack_8259A+0x1b/0xcc [] __do_IRQ+0x4f/0x113 [] do_IRQ+0x8c/0xad in-softirq-W at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] mask_and_ack_8259A+0x1b/0xcc [] __do_IRQ+0x4f/0x113 [] do_IRQ+0x8c/0xad } ... key at: [] i8259A_lock+0x14/0x40 ... acquired at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] disable_8259A_irq+0x10/0x47 [] startup_edge_ioapic_vector+0x31/0x58 [] setup_irq+0xe4/0x14d [] request_irq+0xda/0xf9 [] rtc_init+0x6a/0x1a7 [] init+0x14a/0x2cb [] kernel_thread_helper+0x5/0xb ... acquired at: [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] mask_IO_APIC_irq+0x11/0x31 [] ack_edge_ioapic_vector+0x31/0x41 [] __do_IRQ+0x4f/0x113 [] do_IRQ+0x8c/0xad the hard-irq-unsafe lock's dependencies: -> (vector_lock){--..} ops: 31 { initial-use at: [] lockdep_acquire+0x68/0x84 [] _spin_lock+0x21/0x2f [] assign_irq_vector+0x34/0xc8 [] setup_IO_APIC+0x45a/0xcff [] smp_prepare_cpus+0x5ea/0x8aa [] init+0x32/0x2cb [] kernel_thread_helper+0x5/0xb softirq-on-W at: [] lockdep_acquire+0x68/0x84 [] _spin_lock+0x21/0x2f [] assign_irq_vector+0x34/0xc8 [] setup_IO_APIC+0x45a/0xcff [] smp_prepare_cpus+0x5ea/0x8aa [] init+0x32/0x2cb [] kernel_thread_helper+0x5/0xb hardirq-on-W at: [] lockdep_acquire+0x68/0x84 [] _spin_lock+0x21/0x2f [] assign_irq_vector+0x34/0xc8 [] setup_IO_APIC+0x45a/0xcff [] smp_prepare_cpus+0x5ea/0x8aa [] init+0x32/0x2cb [] kernel_thread_helper+0x5/0xb } ... key at: [] vector_lock+0x14/0x3c stack backtrace: [] show_trace+0xd/0xf [] dump_stack+0x17/0x19 [] check_usage+0x1f6/0x203 [] __lockdep_acquire+0x8c2/0xaa5 [] lockdep_acquire+0x68/0x84 [] _spin_lock_irqsave+0x2a/0x3a [] startup_msi_irq_wo_maskbit+0x10/0x35 [] probe_irq_on+0x44/0x107 [] serial8250_config_port+0x84b/0x986 [] uart_add_one_port+0x105/0x289 [] serial8250_init+0xc3/0x10a [] init+0x14a/0x2cb [] kernel_thread_helper+0x5/0xb Signed-off-by: Ingo Molnar Cc: Jan Beulich Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 357c2b9056df447390b7df3e49960a4c609a89a9 Author: Jon Mason Date: Mon Jun 26 13:57:13 2006 +0200 [PATCH] x86_64: remove unused gart header file include/asm-x86_64/gart-mapping.h is only ever used in arch/x86_64/kernel/setup.c and none of its contents are referenced. Looks to be leftover cruft not removed in the dma_ops patch. Signed-off-by: Jon Mason Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 08cd36570e47176c7b6bd3e80125aa46c4638097 Author: Andi Kleen Date: Mon Jun 26 13:57:10 2006 +0200 [PATCH] x86_64: Optimize bitmap_weight for small bitmaps Use inline code bitmaps <= BITS_PER_LONG in bitmap_weight. This gives _much_ better code. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 5282aab87a8be3f5e6c36a4c2ee4b71852def1bb Author: Andi Kleen Date: Mon Jun 26 13:57:07 2006 +0200 [PATCH] x86_64: Remove ia32_sys_call_table export It was originally added for 2.4 oprofile, but 2.6 oprofile doesn't need that anymore. Shouldn't be any use in tree anymore and it doesn't make much sense to export the ia32 syscalls when the main syscalls are not exported. I think Adrian Bunk asked for removing it several times. Also included hunk from Adrian to remove the .globl ia32_sys_call_table Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 5c0f80fab3724aa44b3352d88155fe0eaae0e54a Author: Andi Kleen Date: Mon Jun 26 13:57:04 2006 +0200 [PATCH] x86_64: Remove long obsolete CVS Early development of x86-64 Linux was in CVS, but that hasn't been the case for a long time now. Remove the obsolete $Id$s. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 3e4ff115740c28dea463561aa1405a3c0de0d2d0 Author: Don Zickus Date: Mon Jun 26 13:57:01 2006 +0200 [PATCH] x86_64: nmi watchdog header cleanup Misc header cleanup for nmi watchdog. Signed-off-by: Don Zickus Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 14118c3cdd46d72e503ee2f727b11d881f72f755 Author: Ingo Molnar Date: Mon Jun 26 13:56:58 2006 +0200 [PATCH] x86_64: fix unlikely profiling & vsyscalls on x86_64 fix unlikely profiling in vsyscalls ... Signed-off-by: Ingo Molnar Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 4b787e0b831c71c6b09902b66575dadb2260a7c8 Author: Jan Beulich Date: Mon Jun 26 13:56:55 2006 +0200 [PATCH] x86_64: add END()/ENDPROC() annotations to entry.S Since END()/ENDPROC() are now available, add respective annotations to x86_64's entry.S. This should help debugging activities. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit bebfa1013eee1d91b3242e5801cc8fbdfaf148ec Author: Andi Kleen Date: Mon Jun 26 13:56:52 2006 +0200 [PATCH] x86_64: Add compat_printk and sysctl to turn off compat layer warnings Sometimes e.g. with crashme the compat layer warnings can be noisy. Add a way to turn them off by gating all output through compat_printk that checks a global sysctl. The default is not changed. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit f201611fcecdfa825471dc425ee007997228fae4 Author: Andi Kleen Date: Mon Jun 26 13:56:49 2006 +0200 [PATCH] x86_64: Use -ENODEV in IOMMU initialization Fix initcall at 0xffffffff806c5b89: pci_iommu_init+0x0/0x53c(): returned with error code -1 Return -ENODEV instead when the IOMMU is not used. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 6ebcc00e95fa78218a048a88d8d5ee491aa7d6d0 Author: Jan Beulich Date: Mon Jun 26 13:56:46 2006 +0200 [PATCH] i386/x86-64: simplify ioapic_register_intr() Simplify (remove duplication of) code in ioapic_register_intr(). Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 0a1ad60d7a7eb433095bc1b2c8b475f3f278f61d Author: Jan Beulich Date: Mon Jun 26 13:56:43 2006 +0200 [PATCH] x86_64: serialize assign_irq_vector() use of static variables Since assign_irq_vector() can be called at runtime, its access of static variables should be protected by a lock. Signed-off-by: Jan Beulich Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit a32073bffc656ca4bde6002b6cf7c1a8e0e22712 Author: Andi Kleen Date: Mon Jun 26 13:56:40 2006 +0200 [PATCH] x86_64: Clean and enhance up K8 northbridge access code - Factor out the duplicated access/cache code into a single file * Shared between i386/x86-64. - Share flush code between AGP and IOMMU * Fix a bug: AGP didn't wait for end of flush before - Drop 8 northbridges limit and allocate dynamically - Add lock to serialize AGP and IOMMU GART flushes - Add PCI ID for next AMD northbridge - Random related cleanups The old K8 NUMA discovery code is unchanged. New systems should all use SRAT for this. Cc: "Navin Boppuri" Cc: Dave Jones Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 7c2d9cd218916276e52a5dae827b84a159fe5c96 Author: Jon Mason Date: Mon Jun 26 13:56:37 2006 +0200 [PATCH] x86_64: trivial gart clean-up A trivial change to have gart_unmap_sg call gart_unmap_single directly, instead of bouncing through the dma_unmap_single wrapper in dma-mapping.h. This change required moving the gart_unmap_single above gart_unmap_sg, and under gart_map_single (which seems a more logical place that its current location IMHO). Signed-off-by: Jon Mason Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit f0f2d6536e3515b5b1b7ae97dc8f176860c8c2ce Author: Andi Kleen Date: Mon Jun 26 13:56:34 2006 +0200 [PATCH] x86_64: Implement compat functions for PTRACE_SETSIGINFO/GETSIGINFO Previously we would just silently provide 64 bit services for this to 32bit processes. I also added all the other cases explicitely to the ptrace compat wrapper to make sure this doesn't happen again. And removed one bogus check in the wrapper. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit f5adc9c79d3a15478c0028139c54453ff3900488 Author: Mike Waychison Date: Mon Jun 26 13:56:31 2006 +0200 [PATCH] x86_64: iommu_gart_bitmap search to cross next_bit Allow search for a contiguous block of iommu space to cross the next_bit marker if we have already committed ourselves to flushing the gart. There shouldn't be any reason why we'd restrict the search. Signed-off-by: Mike Waychison Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit ed0a893fc8866baf116323acbcd883a3cc4a36a3 Author: Andi Kleen Date: Mon Jun 26 13:56:28 2006 +0200 [PATCH] x86_64: Remove bogus comment in topology.h Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 3c5846470c30580bbcb4d5f2339f75a2c88cfe6e Author: Ingo Molnar Date: Mon Jun 26 13:56:25 2006 +0200 [PATCH] x86_64: x86_64-enable-large-bzImage.patch enable large bzImages on x86_64. (fix is from x86's build.c) Using this patch i have successfully built and booted an allyesconfig 13MB+ bzImage on x86_64 too: $ size64 vmlinux text data bss dec hex filename 23444831 8202642 3439360 35086833 21761f1 vmlinux -rw-rw-r-- 1 mingo mingo 13121740 Apr 19 09:32 arch/x86_64/boot/bzImage Signed-off-by: Ingo Molnar Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 0c90bb87730613709e65c03c86d614e31a675d4f Author: Andi Kleen Date: Mon Jun 26 13:56:22 2006 +0200 [PATCH] x86_64: Remove most of ia32_unistd.h It's only needed for three system calls, no need to maintain a full list forever. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 9f2036f3e280ef1df072c5b2ca115a0e766c1d10 Author: Jon Mason Date: Mon Jun 26 13:56:19 2006 +0200 [PATCH] x86_64: pci-dma.c clean-up - trivial Replace hard coded DMA masks with #defines from include/linux/dma-mapping.h Signed-off-by: Jon Mason Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit d167a51877e94dda73dd656c51f363502309f713 Author: Gerd Hoffmann Date: Mon Jun 26 13:56:16 2006 +0200 [PATCH] x86_64: x86_64 version of the smp alternative patch. Changes are largely identical to the i386 version: * alternative #define are moved to the new alternative.h file. * one new elf section with pointers to the lock prefixes which can be nop'ed out for non-smp. * two new elf sections simliar to the "classic" alternatives to replace SMP code with simpler UP code. * fixup headers to use alternative.h instead of defining their own LOCK / LOCK_PREFIX macros. The patch reuses the i386 version of the alternatives code to avoid code duplication. The code in alternatives.c was shuffled around a bit to reduce the number of #ifdefs needed. It also got some tweaks needed for x86_64 (vsyscall page handling) and new features (noreplacement option which was x86_64 only up to now). Debug printk's are changed from compile-time to runtime. Loosely based on a early version from Bastian Blank Signed-off-by: Gerd Hoffmann Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 240cd6a80642da528bfa382ec2ae4e3cb8991ea7 Author: Andi Kleen Date: Mon Jun 26 13:56:13 2006 +0200 [PATCH] i386/x86-64: Emulate CPUID4 on AMD Intel systems report the cache level data from CPUID 4 in sysfs. Add a CPUID 4 emulation for AMD CPUs to report the same information for them. This allows programs to read this information in a uniform way. The AMD way to report this is less flexible so some assumptions are hardcoded (e.g. no L3) Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit faee9a5dc9d8399cc3b1b8e18b6d7ff7b17f1af1 Author: Andi Kleen Date: Mon Jun 26 13:56:10 2006 +0200 [PATCH] i386/x86-64: Use new official CPUID to get APICID/core split on AMD platforms Previously the apicid<->coreid split was computed based on the max number of cores. Now use a new CPUID AMD defined for that. On most systems right now it should be 0 and the old method will be used. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 79121ea9f098934850347eeed3857ffd836810c3 Author: Andi Kleen Date: Mon Jun 26 13:56:07 2006 +0200 [PATCH] x86_64: Use __always_inline for __inline_memcpy Inspired from i386 changes Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 0f4fdb7fba0b3ec66df39d0e743e701404161fb8 Author: ravikiran thirumalai Date: Mon Jun 26 13:56:04 2006 +0200 [PATCH] x86_64: Use local APIC ID from local APIC instead of CPUID vSMPowered systems use apic_cluster too. Forcing apic_physflat works on these systems too, but only if we change phys_pkg_id to use hard_smp_prcoessor_id() instead of cpuid_ebx. I am guessing other multichassi cluster systems would need this too. Signed-off-by: ravikiran thirumalai Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 7c393e7b95bceafcefd5357afdda9f5047b6aa69 Author: Andi Kleen Date: Mon Jun 26 13:56:01 2006 +0200 [PATCH] x86_64: Update defconfig Enable some hwmon drivers as modules and tulip and stack unwinding Kernel image should be somewhat bigger now because of the unwind information being included, but you'll get exact backtraces for that. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds commit 2e2d0dcc1bd7ca7c26ea5e29efb7f34bbd564f1c Author: olecom@mail.ru Date: Mon Jun 26 19:05:40 2006 +0200 typo fixes Signed-off-by: Adrian Bunk commit b78709cfd4387c15a9894748bcada8a4ca75c561 Author: Peter Williams Date: Mon Jun 26 16:58:00 2006 +1000 [PATCH] sched: fix SCHED_FIFO bug in sys_sched_rr_get_interval() The introduction of SCHED_BATCH scheduling class with a value of 3 means that the expression (p->policy & SCHED_FIFO) will return true if policy is SCHED_BATCH or SCHED_FIFO. Unfortunately, this expression is used in sys_sched_rr_get_interval() and in the absence of a comment to say that this is intentional I presume that it is unintentional and erroneous. The fix is to change the expression to (p->policy == SCHED_FIFO). Acked-by: Ingo Molnar Signed-off-by: Linus Torvalds commit f274afc9933e5fd5987a4a2a5f02687958f8ba65 Author: Jesper Juhl Date: Mon Jun 26 19:01:01 2006 +0200 Clean up 'inline is not at beginning' warnings for usb storage Usually we don't care much about 'gcc -W' warnings, but some of us do build kernels that way to look for problems, and then the fewer warnings we have to wade through the better. Especially when they are very easy and non-intrusive to clean up. Which is the case for the following warnings spewed by drivers/usb/storage/usb.h : drivers/usb/storage/usb.h:163: warning: `inline' is not at beginning of +declaration drivers/usb/storage/usb.h:166: warning: `inline' is not at beginning of +declaration There's also some precedence for cleaning up these warnings. I've had a few patches merged in the past that remove exactly this class of warnings. Signed-off-by: Jesper Juhl Signed-off-by: Adrian Bunk commit 2139a7fbf3effd8cad505871e3a3c308780ada32 Author: H. Peter Anvin Date: Mon Jun 26 00:28:02 2006 -0700 [PATCH] initramfs overwrite fix This patch ensures that initramfs overwrites work correctly, even when dealing with device nodes of different types. Furthermore, when replacing a file which already exists, we must make very certain that we truncate the existing file. Signed-off-by: H. Peter Anvin Cc: Michael Neuling Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 05381954243de2348def8e338ca23fb40a0a721d Author: Adrian Bunk Date: Mon Jun 26 00:28:01 2006 -0700 [PATCH] drivers/md/md.c: make code static Make needlessly global code static. Signed-off-by: Adrian Bunk Cc: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f655675b3fe09c4d0506d357527fe07544623009 Author: NeilBrown Date: Mon Jun 26 00:28:01 2006 -0700 [PATCH] md: Allow the write_mostly flag to be set via sysfs It appears in /sys/mdX/md/dev-YYY/state and can be set or cleared by writing 'writemostly' or '-writemostly' respectively. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a94213b1fa7b26dcc271bf4b4f9eebf1f1af33a2 Author: NeilBrown Date: Mon Jun 26 00:28:00 2006 -0700 [PATCH] md: Allow resync_start to be set and queried via sysfs Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d4dbd0250ea1d24bb3d2d13559432fa069d795e2 Author: NeilBrown Date: Mon Jun 26 00:27:59 2006 -0700 [PATCH] md: Allow raid 'layout' to be read and set via sysfs Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 45dc2de1e53a29f898b81326b8a16e6192d52e4e Author: NeilBrown Date: Mon Jun 26 00:27:58 2006 -0700 [PATCH] md: Allow rdev state to be set via sysfs The md/dev-XXX/state file can now be written: "faulty" simulates an error on the device "remove" removes the device from the array (if it is not busy) Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9e653b6342c94016f5cc9937061ef99e9c4b4045 Author: NeilBrown Date: Mon Jun 26 00:27:58 2006 -0700 [PATCH] md: Set/get state of array via sysfs This allows the state of an md/array to be directly controlled via sysfs and adds the ability to stop and array without tearing it down. Array states/settings: clear No devices, no size, no level Equivalent to STOP_ARRAY ioctl inactive May have some settings, but array is not active all IO results in error When written, doesn't tear down array, but just stops it suspended (not supported yet) All IO requests will block. The array can be reconfigured. Writing this, if accepted, will block until array is quiescent readonly no resync can happen. no superblocks get written. write requests fail read-auto like readonly, but behaves like 'clean' on a write request. clean - no pending writes, but otherwise active. When written to inactive array, starts without resync If a write request arrives then if metadata is known, mark 'dirty' and switch to 'active'. if not known, block and switch to write-pending If written to an active array that has pending writes, then fails. active fully active: IO and resync can be happening. When written to inactive array, starts with resync write-pending (not supported yet) clean, but writes are blocked waiting for 'active' to be written. active-idle like active, but no writes have been seen for a while (100msec). Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 42543769142d2375f2b5f8fc9cac999f84bd4c4c Author: NeilBrown Date: Mon Jun 26 00:27:57 2006 -0700 [PATCH] md: Don't write dirty/clean update to spares - leave them alone - record the 'event' count on each individual device (they might sometimes be slightly different now) - add a new value for 'sb_dirty': '3' means that the super block only needs to be updated to record a clean<->dirty transition. - Prefer odd event numbers for dirty states and even numbers for clean states - Using all the above, don't update the superblock on a spare device if the update is just doing a clean-dirty transition. To accomodate this, a transition from dirty back to clean might now decrement the events counter if nothing else has changed. The net effect of this is that spare drives will not see any IO requests during normal running of the array, so they can go to sleep if that is what they want to do. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 07d84d109d8beedd68df9da2e4e9f25c8217e7fb Author: NeilBrown Date: Mon Jun 26 00:27:56 2006 -0700 [PATCH] md: Allow re-add to work on array without bitmaps When an array has a bitmap, a device can be removed and re-added and only blocks changes since the removal (as recorded in the bitmap) will be resynced. It should be possible to do a similar thing to arrays without bitmaps. i.e. if a device is removed and re-added and *no* changes have been made in the interim, then the add should not require a resync. This patch allows that option. This means that when assembling an array one device at a time (e.g. during device discovery) the array can be enabled read-only as soon as enough devices are available, but extra devices can still be added without causing a resync. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3285edf152cefff482f95ceb90b1bd46ac169df1 Author: NeilBrown Date: Mon Jun 26 00:27:55 2006 -0700 [PATCH] md: Fix bug that stops raid5 resync from happening As data_disks is *less* than raid_disks, the current test here is obviously wrong. And as the difference is already available in conf->max_degraded, it makes much more sense to use that. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b3cc9ec76ba44d010f4c820c4608b91aaf28a0b9 Author: akpm@osdl.org Date: Mon Jun 26 00:27:54 2006 -0700 [PATCH] md: Fix Kconfig error RAID5 recently changed to RAID456 Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4d2554d045497d1be3204cf67385f966f01cc9bd Author: Justin Piszcz Date: Mon Jun 26 00:27:50 2006 -0700 [PATCH] md: md Kconfig speeling feex I was experimenting with Linux SW raid today and found a spelling error when reading the help menus... (and fly spell found more). Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8838832830d2c6c28ae2db93188ae90652eb7fc2 Author: NeilBrown Date: Mon Jun 26 00:27:50 2006 -0700 [PATCH] md: Calculate correct array size for raid10 in new offset mode The size calculation made assumtion which the new offset mode didn't follow. This gets the size right in all cases. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ce25c31bdd3b39266debd86a7732007e05983a67 Author: NeilBrown Date: Mon Jun 26 00:27:49 2006 -0700 [PATCH] md: Change md/bitmap file handling to use bmap to file blocks-fix Fix problems with new bmap based access to bitmap files. 1/ When not using a file based bitmap, attach a NULL list of buffers to each page so the common free_buffer routine can cope. 2/ Use submit_bh to read as well as write, rather than vfs_read. This makes read and write more symetric. 3/ sync the file before reading, to ensure that the page cache has no dirty pages that might get written out later. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d785a06a0b9d0cd86b3cc1bf8e236e62af7b47ed Author: NeilBrown Date: Mon Jun 26 00:27:48 2006 -0700 [PATCH] md/bitmap: change md/bitmap file handling to use bmap to file blocks If md is asked to store a bitmap in a file, it tries to hold onto the page cache pages for that file, manipulate them directly, and call a cocktail of operations to write the file out. I don't believe this is a supportable approach. This patch changes the approach to use the same approach as swap files. i.e. bmap is used to enumerate all the block address of parts of the file and we write directly to those blocks of the device. swapfile only uses parts of the file that provide a full pages at contiguous addresses. We don't have that luxury so we have to cope with pages that are non-contiguous in storage. To handle this we attach buffers to each page, and store the addresses in those buffers. With this approach the pagecache may contain data which is inconsistent with what is on disk. To alleviate the problems this can cause, md invalidates the pagecache when releasing the file. If the file is to be examined while the array is active (a non-critical but occasionally useful function), O_DIRECT io must be used. And new version of mdadm will have support for this. This approach simplifies a lot of code: - we no longer need to keep a list of pages which we need to wait for, as the b_endio function can keep track of how many outstanding writes there are. This saves a mempool. - -EAGAIN returns from write_page are no longer possible (not sure if they ever were actually). Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit acc55e220166a5ad898e66ad6153fd62eaaac76d Author: NeilBrown Date: Mon Jun 26 00:27:47 2006 -0700 [PATCH] md/bitmap: tidy up i_writecount handling in md/bitmap md/bitmap modifies i_writecount of a bitmap file to make sure that no-one else writes to it. The reverting of the change is sometimes done twice, and there is one error path where it is omitted. This patch tidies that up. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0cdd02cabd86b5d547f882005e23a93929f0ace9 Author: NeilBrown Date: Mon Jun 26 00:27:47 2006 -0700 [PATCH] md/bitmap: remove dead code from md/bitmap bitmap_active is never called, and the BITMAP_ACTIVE flag is never users or tested, so discard them both. Also remove some out-of-date 'todo' comments. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a647e4bc5ce697e25ff50d2e22de68a581b1ed38 Author: NeilBrown Date: Mon Jun 26 00:27:46 2006 -0700 [PATCH] md/bitmap: remove unnecessary page reference manipulations from md/bitmap code md/bitmap gets a collection of pages representing the bitmap when it initialises the bitmap, and puts all the references when discarding the bitmap. It also occasionally takes extra references without any good reason, and sometimes drops them ... though it doesn't always drop them, which can result in a memory leak. This patch removes the unnecessary 'get_page' calls, and the corresponding 'put_page' calls. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e16b68b6e456a61b895a198baf5aa473cf2a32bf Author: NeilBrown Date: Mon Jun 26 00:27:45 2006 -0700 [PATCH] md/bitmap: use set_bit etc for bitmap page attributes In particular, this means that we use 4 bits per page instead of a whole unsigned long. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ec7a3197f4777eff5039251d0e08a031b3372d6c Author: NeilBrown Date: Mon Jun 26 00:27:45 2006 -0700 [PATCH] md/bitmap: cleaner separation of page attribute handlers in md/bitmap md/bitmap has some attributes per-page. Handling of these attributes in largely abstracted in set_page_attr and clear_page_attr. However get_page_attr exposes the format used to store them. So prior to changing that format, introduce test_page_attr instead of get_page_attr, and make appropriate usage changes. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0b79ccf0cdd9f59e5f99017e1a5d23da336544b2 Author: NeilBrown Date: Mon Jun 26 00:27:44 2006 -0700 [PATCH] md/bitmap: remove bitmap writeback daemon md/bitmap currently has a separate thread to wait for writes to the bitmap file to complete (as we cannot get a callback on that action). However this isn't needed as bitmap_unplug is called from process context and waits for the writeback thread to do it's work. The same result can be achieved by doing the waiting directly in bitmap_unplug. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d7375ab324971e7acbea9f02a0269ae7348f4147 Author: NeilBrown Date: Mon Jun 26 00:27:43 2006 -0700 [PATCH] md/bitmap: fix online removal of file-backed bitmaps When "mdadm --grow /dev/mdX --bitmap=none" is used to remove a filebacked bitmap, the bitmap was disconnected from the array, but the file wasn't closed (until the array was stopped). The file also wasn't closed if adding the bitmap file failed. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 52c03291a832d86c093996d0491a326de4a6b79b Author: NeilBrown Date: Mon Jun 26 00:27:43 2006 -0700 [PATCH] md: split reshape portion of raid5 sync_request into a separate function ... as raid5 sync_request is WAY too big. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5e56341d029f0c2cf31e78dc01d4c861ba4d6a5e Author: Adrian Bunk Date: Mon Jun 26 00:27:42 2006 -0700 [PATCH] md: make md_print_devices() static This patch makes the needlessly global md_print_devices() static. Signed-off-by: Adrian Bunk Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c93983bf517c100a31e40ef087e19bd3d7aa2d28 Author: NeilBrown Date: Mon Jun 26 00:27:41 2006 -0700 [PATCH] md: support stripe/offset mode in raid10 The "industry standard" DDF format allows for a stripe/offset layout where data is duplicated on different stripes. e.g. A B C D D A B C E F G H H E F G (columns are drives, rows are stripes, LETTERS are chunks of data). This is similar to raid10's 'far' mode, but not quite the same. So enhance 'far' mode with a 'far/offset' option which follows the layout of DDFs stripe/offset. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7c7546ccf6463edbeee8d9aac6de7be1cd80d08a Author: NeilBrown Date: Mon Jun 26 00:27:41 2006 -0700 [PATCH] md: allow a linear array to have drives added while active Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5fd6c1dce06ec24ef3de20fe0c7ecf2ba9fe5ef9 Author: NeilBrown Date: Mon Jun 26 00:27:40 2006 -0700 [PATCH] md: allow checkpoint of recovery with version-1 superblock For a while we have had checkpointing of resync. The version-1 superblock allows recovery to be checkpointed as well, and this patch implements that. Due to early carelessness we need to add a feature flag to signal that the recovery_offset field is in use, otherwise older kernels would assume that a partially recovered array is in fact fully recovered. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a8a55c387da28d67d98f56e4f5021462cb61f7a6 Author: NeilBrown Date: Mon Jun 26 00:27:39 2006 -0700 [PATCH] md: remove nuisance message at shutdown At shutdown, we switch all arrays to read-only, which creates a message for every instantiated array, even those which aren't actually active. So remove the message for non-active arrays. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 16a53ecc35f2a80dc285be2e769768847d89ca37 Author: NeilBrown Date: Mon Jun 26 00:27:38 2006 -0700 [PATCH] md: merge raid5 and raid6 code There is a lot of commonality between raid5.c and raid6main.c. This patches merges both into one module called raid456. This saves a lot of code, and paves the way for online raid5->raid6 migrations. There is still duplication, e.g. between handle_stripe5 and handle_stripe6. This will probably be cleaned up later. Cc: "H. Peter Anvin" Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 16f17b39f385212b73278a76d482cdcaaebe6c02 Author: NeilBrown Date: Mon Jun 26 00:27:37 2006 -0700 [PATCH] md: increase the delay before marking metadata clean, and make it configurable When a md array has been idle (no writes) for 20msecs it is marked as 'clean'. This delay turns out to be too short for some real workloads. So increase it to 200msec (the time to update the metadata should be a tiny fraction of that) and make it sysfs-configurable. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9443a1d1f72c688646278c06d0a9a3c79e895325 Author: NeilBrown Date: Mon Jun 26 00:27:37 2006 -0700 [PATCH] md: remove useless ioctl warning This warning was slightly useful back in 2.2 days, but is more an annoyance now. It makes it awkward to add new ioctls (that we we are likely to do that in the current climate, but it is possible). Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8932c2e0dcae52e73430878fd8a7a7800176eada Author: NeilBrown Date: Mon Jun 26 00:27:36 2006 -0700 [PATCH] md: remove arbitrary limit on chunk size The largest chunk size the code can support without substantial surgery is 2^30 bytes, so make that the limit instead of an arbitrary 4Meg. Some day, the 'chunksize' should change to a sector-shift instead of a byte-count. Then no limit would be needed. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c70810b327a247d12805554d0aa4605e257effb8 Author: NeilBrown Date: Mon Jun 26 00:27:35 2006 -0700 [PATCH] md: reformat code in raid1_end_write_request to avoid goto A recent change made this goto unnecessary, so reformat the code to make it clearer what is happening. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 72d9486169a2a8353e022813185ba2f32d7dde69 Author: Alasdair G Kergon Date: Mon Jun 26 00:27:35 2006 -0700 [PATCH] dm: improve error message consistency Tidy device-mapper error messages to include context information automatically. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5c6bd75d06db512515a3781aa97e42df2faf0815 Author: Alasdair G Kergon Date: Mon Jun 26 00:27:34 2006 -0700 [PATCH] dm: prevent removal if open If you misuse the device-mapper interface (or there's a bug in your userspace tools) it's possible to end up with 'unlinked' mapped devices that cannot be removed until you reboot (along with uninterruptible processes). This patch prevents you from removing a device that is still open. It introduces dm_lock_for_deletion() which is called when a device is about to be removed to ensure that nothing has it open and nothing further can open it. It uses a private open_count for this which also lets us remove one of the problematic bdget_disk() calls elsewhere. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c2ade42dd35466d90aa6fc7cc717f396e165492f Author: David Teigland Date: Mon Jun 26 00:27:33 2006 -0700 [PATCH] dm: create error table Add a library function dm_create_error_table() to create a table that rejects any I/O sent to a device with EIO. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 17b2f66f2a39a4e4d1ed456f35ee3bb598e41d35 Author: Alasdair G Kergon Date: Mon Jun 26 00:27:33 2006 -0700 [PATCH] dm: add exports Move definitions of core device-mapper functions for manipulating mapped devices and their tables to advertising their availability for use elsewhere in the kernel. Protect the contents of device-mapper.h with ifdef __KERNEL__. And throw in a few formatting clean-ups and extra comments. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2b06cfff12f0f87c4bc4d4c4dd76997e72c360ba Author: Alasdair G Kergon Date: Mon Jun 26 00:27:32 2006 -0700 [PATCH] dm: consolidate creation functions Merge dm_create() and dm_create_with_minor() by introducing the special value DM_ANY_MINOR to request the allocation of the next available minor number. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 814d68629b40e863997fa0eea459be4cc99a06cc Author: David Teigland Date: Mon Jun 26 00:27:31 2006 -0700 [PATCH] dm table split_args: handle no input Return sense if dm_split_args is called with a NULL input parameter. Signed-off-by: David Teigland Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ce503f59ae899c3e75a8a1cf46f2d44c0c5b5c7c Author: Jonathan Brassow Date: Mon Jun 26 00:27:30 2006 -0700 [PATCH] dm kcopyd: error accumulation fix kcopyd should accumulate errors - otherwise I/O failures may be ignored unintentionally. And invert 'success' (used in a future patch), using a more intuitive !(read_err || write_err). Signed-off-by: Jonathan Brassow Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8a835f11bce68ed990533e49b5dedb00bee46d71 Author: Alasdair G Kergon Date: Mon Jun 26 00:27:30 2006 -0700 [PATCH] dm mirror log: sync_count fix When a mirror is reduced in size, clear the part of the bitmap that is no longer used. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 29121bd0b00ebb9524971a583fea4a2f7afe8041 Author: Alasdair G Kergon Date: Mon Jun 26 00:27:29 2006 -0700 [PATCH] dm mirror log: bitset_size fix Fix the 'sizeof' in the region log bitmap size calculation: it's uint32_t, not unsigned long - this breaks on some archs. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b7cca195c4cc051210f3e60a859b779ca833a2e4 Author: Alasdair G Kergon Date: Mon Jun 26 00:27:29 2006 -0700 [PATCH] dm mirror log: refactor context Refactor the code that creates the core and disk log contexts to avoid the repeated allocation of clean_bits introduced by the last patch. Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 702ca6f0be9ef95087ee2c9f31e6517492554483 Author: Kevin Corry Date: Mon Jun 26 00:27:28 2006 -0700 [PATCH] dm mirror log: sector size fix On-disk logs for dm-mirror devices are currently hard-coded to use 512 byte hard-sector-sizes. This patch fixes dm-log so it will work with devices with non-512-byte hard-sector-sizes. To maintain full compatibility, instead of moving the clean-bits bitset to a bitset, and enlarges the disk-header buffer to encompass both the header and the bitset. The I/O routines for the bitset are removed, and the I/O routines for the disk-header now also read/write the bitset. Signed-off-by: Kevin Corry Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 143535396c7ebd9395a931a000b3963f457712b8 Author: Milan Broz Date: Mon Jun 26 00:27:27 2006 -0700 [PATCH] dm table: get_target: fix last index The table is indexed from 0, so an index equal to t->num_targets should be rejected. (There is no code in the current tree that would exercise this bug.) Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e4c8b3ba34cc1aeab451c7a5cc843c5fd62cbe3d Author: Neil Brown Date: Mon Jun 26 00:27:26 2006 -0700 [PATCH] dm: mirror sector offset fix The device-mapper core does not perform any remapping of bios before passing them to the targets. If a particular mapping begins part-way into a device, targets obtain the sector relative to the start of the mapping by subtracting ti->begin. The dm-raid1 target didn't do this everywhere: this patch fixes it, taking care to subtract ti->begin exactly once for each bio. [akpm: too late for 2.6.17 - suitable for 2.6.17.x after it has settled] Signed-off-by: Neil Brown Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f0b04115368ff383654a3bd26baf8f4be5e81132 Author: Jeff Mahoney Date: Mon Jun 26 00:27:25 2006 -0700 [PATCH] dm: fix block device initialisation In alloc_dev(), we register the device with the block layer and then continue to initialize the device. But register_disk() makes the device available to be opened before we have completed initialising it. This patch moves the final bits of the initialization above the disk registration. [akpm: too late for 2.6.17 - suitable for 2.6.17.x after it has settled] Signed-off-by: Jeff Mahoney Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 10da4f795f965f22039aa2930b6f80964aad3ee5 Author: Jeff Mahoney Date: Mon Jun 26 00:27:25 2006 -0700 [PATCH] dm: add module ref counting The reference counting on dm-mod is zero if no mapped devices are open. This is incorrect, and can lead to an oops if the module is unloaded while mapped devices exist. This patch claims a reference to the module whenever a device is created, and drops it again when the device is freed. Devices must be removed before dm-mod is unloaded. [akpm: too late for 2.6.17 - suitable for 2.6.17.x after it has settled] Signed-off-by: Jeff Mahoney Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7ec75f254742766eb729f1d1024a5b4e6692fc5f Author: Jeff Mahoney Date: Mon Jun 26 00:27:24 2006 -0700 [PATCH] dm: fix mapped device ref counting To avoid races, _minor_lock must be held while changing mapped device reference counts. There are a few paths where a mapped_device pointer is returned before a reference is taken. This patch fixes them. [akpm: too late for 2.6.17 - suitable for 2.6.17.x after it has settled] Signed-off-by: Jeff Mahoney Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit fba9f90e568e17c326257ee293207b75880b39d6 Author: Jeff Mahoney Date: Mon Jun 26 00:27:23 2006 -0700 [PATCH] dm: add DMF_FREEING There is a chicken and egg problem between the block layer and dm in which the gendisk associated with a mapping keeps a reference-less pointer to the mapped_device. This patch uses a new flag DMF_FREEING to indicate when the mapped_device is no longer valid. This is checked to prevent any attempt to open the device from succeeding while the device is being destroyed. [akpm: too late for 2.6.17 - suitable for 2.6.17.x after it has settled] Signed-off-by: Jeff Mahoney Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f32c10b09940cffc3620ce111315ec44343fd3ca Author: Jeff Mahoney Date: Mon Jun 26 00:27:22 2006 -0700 [PATCH] dm: change minor_lock to spinlock While removing a device, another another thread might attempt to resurrect it. This patch replaces the _minor_lock mutex with a spinlock and uses atomic_dec_and_lock() to serialize reference counting in dm_put(). [akpm: too late for 2.6.17 - suitable for 2.6.17.x after it has settled] Signed-off-by: Jeff Mahoney Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 62f75c2f3244553b1290447abd1f1e6b1144d3e9 Author: Jeff Mahoney Date: Mon Jun 26 00:27:21 2006 -0700 [PATCH] dm: move idr_pre_get idr_pre_get() can sleep while allocating memory. The next patch will change _minor_lock into a spinlock, so this patch moves idr_pre_get() outside the lock in preparation. [akpm: too late for 2.6.17 - suitable for 2.6.17.x after it has settled] Signed-off-by: Jeff Mahoney Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ba61fdd17d73ddb5c892a9f12383c6c560a20d56 Author: Jeff Mahoney Date: Mon Jun 26 00:27:21 2006 -0700 [PATCH] dm: fix idr minor allocation One part of the system can attempt to use a mapped device before another has finished initialising it or while it is being freed. This patch introduces a place holder value, MINOR_ALLOCED, to mark the minor as allocated but in a state where it can't be used, such as mid-allocation or mid-free. At the end of the initialization, it replaces the place holder with the pointer to the mapped_device, making it available to the rest of the dm subsystem. [akpm: too late for 2.6.17 - suitable for 2.6.17.x after it has settled] Signed-off-by: Jeff Mahoney Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5806f07cd2c32920d5105e0f9ff3117338f34eec Author: Jeff Mahoney Date: Mon Jun 26 00:27:19 2006 -0700 [PATCH] lib: add idr_replace This patch adds idr_replace() to replace an existing pointer in a single operation. Device-mapper will use this to update the pointer it stored against a given id. Signed-off-by: Jeff Mahoney Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c51c2752491e5e771de6c8861a85ba46752d7888 Author: Alasdair G Kergon Date: Mon Jun 26 00:27:18 2006 -0700 [PATCH] dm snapshot: unify chunk_size Persistent snapshots currently store a private copy of the chunk size. Userspace also supplies the chunk size when loading a snapshot. Ensure consistency by only storing the chunk_size in one place instead of two. Currently the two sizes will differ if the chunk size supplied by userspace does not match the chunk size an existing snapshot actually uses. Amongst other problems, this causes an incorrect 'percentage full' to be reported. The patch ensures consistency by only storing the chunk_size in one place, removing it from struct pstore. Some initialisation is delayed until the correct chunk_size is known. If read_header() discovers that the wrong chunk size was supplied, the 'area' buffer (which the header already got read into) is reinitialised to the correct size. [akpm: too late for 2.6.17 - suitable for 2.6.17.x after it has settled] Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b877a96409a3a99f2ce27b3c6473c9b28298ac7c Author: Antonino A. Daplas Date: Mon Jun 26 00:27:17 2006 -0700 [PATCH] VT binding: Make sticon support binding Do not mark sticon_startup() as __init Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2aea875da2b7e403b13dd05a9dc80665f39d85e4 Author: Antonino A. Daplas Date: Mon Jun 26 00:27:16 2006 -0700 [PATCH] VT binding: Make promcon support binding Do not mark promcon_startup() and promcon_init_unimap() as __init Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e86bb8acc0fdca82d22d12d46ef5482ecc408b26 Author: Antonino A. Daplas Date: Mon Jun 26 00:27:15 2006 -0700 [PATCH] VT binding: Make newport_con support binding - move register ioremap from newport_startup() to newport_console_init() - fonts are freed multiple times, do it only once Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ac08dae816d3ea5160bb3e8420e87c03bf42224b Author: Antonino A. Daplas Date: Mon Jun 26 00:27:15 2006 -0700 [PATCH] VT binding: Make mdacon support binding Do not mark mdacon_startup __init. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6690075d0b97837aca533b92715e6357ad6de279 Author: Antonino A. Daplas Date: Mon Jun 26 00:27:14 2006 -0700 [PATCH] VT binding: Update documentation Update Documentation/fb/fbcon.txt and Documentatin/console/console.txt to reflect the following changes: 1. sysfs attributes are relocated to /sys/class/vtconsole 2. feature is selectable in Kconfig 3. add sample scripts to fbcon.txt Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5bd42536b395944a1134baa3624b2e0cff6ac7bf Author: Antonino A. Daplas Date: Mon Jun 26 00:27:13 2006 -0700 [PATCH] VT binding: Do not create a device file for class device 'fbcon' The class device "fbcon" does not need to be a device file. Do not create one by passing a major and minor number of zero to class_device_create()/destroy(). Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 13ae66458971b4967350765a8bfaf2a636442e5f Author: Antonino A. Daplas Date: Mon Jun 26 00:27:12 2006 -0700 [PATCH] VT binding: Make VT binding a Kconfig option To enable this feature, CONFIG_VT_HW_CONSOLE_BINDING must be set to 'y'. This feature will default to 'n' to minimize users accidentally corrupting their virtual terminals. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6db4063c5b72b46e9793b0f141a7a3984ac6facf Author: Antonino A. Daplas Date: Mon Jun 26 00:27:12 2006 -0700 [PATCH] VT binding: Add sysfs control to the VT layer Add sysfs control to the VT layer. A new sysfs class, 'vtconsole', and class devices 'vtcon[n]' are added. Each class device file has the following attributes: /sys/class/vtconsole/vtcon[n]/name - read-only attribute showing the name of the current backend /sys/class/vtconsole/vtcon[n]/bind - read/write attribute where: 0 - backend is unbound/unbind backend from the VT layer 1 - backend is bound/bind backend to the VT layer In addition, if any of the consoles are in KD_GRAPHICS mode, binding and unbinding will not succeed. KD_GRAPHICS mode usually indicates that the underlying console hardware is used for other purposes other than displaying text (ie X). This feature should prevent binding/unbinding from interfering with a graphics application using the VT. [akpm@osdl.org: warning fixes] Signed-off-by: Antonino Daplas Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 79062a0d396272f5b103d5223f3c96c58fd27451 Author: Antonino A. Daplas Date: Mon Jun 26 00:27:11 2006 -0700 [PATCH] VT binding: Add new doc file describing the feature This newly added file will: - Describe the characteristics of 2 general types of console drivers - How to use the sysfs to unbind and bind console drivers - Uses for this feature Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 418d1ce61839251004fee6525f58a4581a75239e Author: Antonino A. Daplas Date: Mon Jun 26 00:27:10 2006 -0700 [PATCH] VT binding: fbcon: Update documentation Update Documentation/fb/fbcon.txt to reflect the following changes: 1. Simple illustration of the binding of the console down to individual framebuffer drivers 2. Usage of userspace tools to help with recovery of text console 3. How to use the attributes in /sys/class/tty/console to unload fbcon and the framebuffer drivers Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e614b18dcedb247ce6f848e623cdf2336df2b476 Author: Antonino A. Daplas Date: Mon Jun 26 00:27:09 2006 -0700 [PATCH] VT binding: Update fbcon to support binding The control for binding/unbinding is moved from fbcon to the console layer. Thus the fbcon sysfs attributes, attach and detach, are also gone. 1. Add a notifier event that tells fbcon if a framebuffer driver has been unregistered. If no registered driver remains, fbcon will unregister itself from the console layer. 2. Replaced calls to give_up_console() with unregister_con_driver(). 3. Still use take_over_console() instead of register_con_driver() to maintain compatibility 4. Respect the parameter first_fb_vc and last_fb_vc instead of using 0 and MAX_NR_CONSOLES - 1. These parameters are settable by the user. 5. When fbcon is completely unbound from the console layer, fbcon will also release (iow, decrement module reference counts to zero) all fbdev drivers. In other words, a bind or unbind request from the console layer will propagate down to the framebuffer drivers. 6. If fbcon is not bound to the console, it will ignore all notifier events (except driver registration and unregistration) and all sysfs requests. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3e795de7631b2366d7301182c8d91f6d2911467b Author: Antonino A. Daplas Date: Mon Jun 26 00:27:08 2006 -0700 [PATCH] VT binding: Add binding/unbinding support for the VT console The framebuffer console is now able to dynamically bind and unbind from the VT console layer. Due to the way the VT console layer works, the drivers themselves decide when to bind or unbind. However, it was decided that binding must be controlled, not by the drivers themselves, but by the VT console layer. With this, dynamic binding is possible for all VT console drivers, not just fbcon. Thus, the VT console layer will impose the following to all VT console drivers: - all registered VT console drivers will be entered in a private list - drivers can register themselves to the VT console layer, but they cannot decide when to bind or unbind. (Exception: To maintain backwards compatibility, take_over_console() will automatically bind the driver after registration.) - drivers can remove themselves from the list by unregistering from the VT console layer. A prerequisite for unregistration is that the driver must not be bound. The following functions are new in the vt.c: register_con_driver() - public function, this function adds the VT console driver to an internal list maintained by the VT console bind_con_driver() - private function, it binds the driver to the console take_over_console() is changed to call register_con_driver() followed by a bind_con_driver(). This is the only time drivers can decide when to bind to the VT layer. This is to maintain backwards compatibility. unbind_con_driver() - private function, it unbinds the driver from its console. The vacated consoles will be taken over by the default boot console driver. unregister_con_driver() - public function, removes the driver from the internal list maintained by the VT console. It will only succeed if the driver is currently unbound. con_is_bound() checks if the driver is currently bound or not give_up_console() is just a wrapper to unregister_con_driver(). There are also 3 additional functions meant to be called only by the tty layer for sysfs control: vt_bind() - calls bind_con_driver() vt_unbind() - calls unbind_con_driver() vt_show_drivers() - shows the list of registered drivers Most VT console drivers will continue to work as is, but might have problems when unbinding or binding which should be fixable with minimal changes. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a4a73e1f0283850edc143d28502c1c517c6ab49c Author: Antonino A. Daplas Date: Mon Jun 26 00:27:07 2006 -0700 [PATCH] Detaching fbcon: update documentation Update Documentation/fb/fbcon.txt on the following: 1. sysfs attributes are now located in class/graphics/fbcon 2. instructions on how to attach, detach and/or unload fbcon Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5428b04405af1bb441aa8aabd314e48b870bc58e Author: Antonino A. Daplas Date: Mon Jun 26 00:27:06 2006 -0700 [PATCH] Detaching fbcon: add capability to attach/detach fbcon Add the ability to detach and attach the framebuffer console to and from the vt layer. This is done by echo'ing any value to sysfs attributes located in class/graphics/fbcon. The two attributes are: attach - bind fbcon to the vt layer detach - unbind fbcon from the vt layer Once fbcon is detached from the vt layer, fbcon can be unloaded if compiled as a module. This feature is quite useful for developers who work on the framebuffer or console subsystem. This is also useful for users who want to go to text mode or graphics mode without having to reboot. Directly unloading the fbcon module is not possible because the vt layer increments the module reference count for all bound consoles. Detaching fbcon decrements the module reference count to zero so unloading becomes possible. Detaching fbcon may interfere with X and/or DRM. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e55186fe5fad31962d0ea5ef267bf0c23d98abd4 Author: Antonino A. Daplas Date: Mon Jun 26 00:27:05 2006 -0700 [PATCH] Detaching fbcon: clean up exit code To detach fbcon, it must also clean up all resources it allocated. This was never done before because fbcon cannot be unloaded. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9a17917671d407d37bf23a527aa55acca3cb4735 Author: Antonino A. Daplas Date: Mon Jun 26 00:27:05 2006 -0700 [PATCH] Detaching fbcon: sdd sysfs class device entry for fbcon In order for this feature to work, an interface will be needed. The most appropriate is sysfs. However, the framebuffer console has no sysfs entry yet. This will create a sysfs class device entry for fbcon under /sys/class/graphics. Add a class_device entry 'fbcon' under class 'graphics'. Console-specific attributes which where previously under class/graphics/fb[x] are moved to class/graphics/fbcon. These attributes, 'con_rotate' and 'con_rotate_all', are also renamed to 'rotate' and 'rotate_all' respectively. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a06630f3e7fb29f2524e1d7b009eb8b5a278ba23 Author: Antonino A. Daplas Date: Mon Jun 26 00:27:04 2006 -0700 [PATCH] Detaching fbcon: remove calls to pci_disable_device() Detaching fbcon allows individual drivers to be unloaded. However several drivers call pci_disable_device() upon exit. This function will disable the BAR's which will kill VGA text mode and/or affect X/DRM. To prevent this, remove calls to pci_disable_device() from several drivers. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1c8ce271fe707d26b7bca4e490067fe65694b363 Author: Antonino A. Daplas Date: Mon Jun 26 00:27:03 2006 -0700 [PATCH] Detaching fbcon: fix give_up_console() To allow for detaching fbcon, it must be able to give up the console. However, the function give_up_console() is plain broken. It just sets the entries in the console driver map to NULL, it leaves the vt layer without a console driver, and does not decrement the module reference count. Calling give_up_console() is guaranteed to hang the machine.. To fix this problem, ensure that the virtual consoles are not left dangling without a driver. All systems have a default boot driver (either vgacon or dummycon) which is never unloaded. For those vt's that lost their driver, the default boot driver is reassigned back to them. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 50ec42edd9784fad6a37b05be03064ea24098db6 Author: Antonino A. Daplas Date: Mon Jun 26 00:27:02 2006 -0700 [PATCH] Detaching fbcon: fix vgacon to allow retaking of the console One of the limitations of the framebuffer console system is its inablity to unload or detach itself from the console layer. And once it loads, it also locks in framebuffer drivers preventing their unload. Although the con2fbmap utility does provide a means to unload individual drivers, it requires that at least one framebuffer driver is loaded for use by fbcon. With this change, it is possible to detach fbcon from the console layer. If it is detached, it will reattach the boot console driver (which is permanently loaded) back to the console layer so the system can continue to work. As a consequence, fbcon will also decrement its reference count of individual framebuffer drivers, allowing all of these drivers to be unloaded even if fbcon is still loaded. Unless you use drivers that restores the display to text mode (rivafb and i810fb, for example), detaching fbcon does require assistance from userspace tools (ie, vbetools) for text mode to be restored completely. Without the help of these tools, fbcon will leave the VGA console corrupted. The methods that can be used will be described in Documentation/fb/fbcon.txt. Because the vt layer also increments the module reference count for each console driver, fbcon cannot be directly unloaded. It must be detached first prior to unload. Similarly, fbcon can be reattached to the console layer without having to reload the module. A nice feature if fbcon is compiled statically. Attaching and detaching fbcon is done via sysfs attributes. A class device entry for fbcon is created in /sys/class/graphics. The two attributes that controls this feature are detach and attach. Two other attributes that are piggybacked under /sys/class/graphics/fb[n] that are fbcon-specific, 'con_rotate' and 'con_rotate_all' are moved to fbcon. They are renamed as 'rotate' and 'rotate_all' respectively. Overall, this feature is a great help for developers working in the framebuffer or console layer. There is not need to continually reboot the kernel for every small change. It is also useful for regular users who wants to choose between a graphical console or a text console without having to reboot. Example usage for x86: /* start in text mode */ modprobe xxxfb modprobe fbcon /* graphical mode with fbcon using xxxfb */ echo 1 > /sys/class/graphics/fbcon/detach /* back to text mode, will produce corrupt display unless vbetool is used */ rmmod xxxfb modprobe yyyfb /* back to graphical mode with fbcon using yyyfb */ Before trying out this feature, please read Documentation/fb/fbcon.txt. This patch: In order for fbcon to detach itself from the console layer, vgacon, which is a boot console driver, must be fixed so it can retake the console multiple times, not just during init. The following needs to be done: - remove __init from the vgacon_startup, this is called again by take_over_console(). - vc->rows and vc->cols are set manually by vgacon during init. After init, vc_resize() can be used - make sure the scrollback_buffer is not reallocated Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9dac73a4ec2c0a791bbfc6630dc4629ce11e68b9 Author: Daniel R Thompson Date: Mon Jun 26 00:27:00 2006 -0700 [PATCH] fbdev: tag by scantype in sysfs Modify the sysfs description of a video mode such that modes are tagged with their scan type, (p)rogessive, (i)nterlaced, (d)ouble scan. For example, U:1920x1080i-50. This is useful to disambiguate some of the 'consumer' video timings found in CEA-861 (especially those for EDTV). Signed-off-by: Daniel R Thompson Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 90b4f9aca4d124d114e02bbb3d1d4f3d1d47138f Author: Edgar Hucek Date: Mon Jun 26 00:26:59 2006 -0700 [PATCH] imacfb: Add Intel-based Macintosh Framebuffer Support This patch adds a new framebuffer driver for the Intel Based macs. This framebuffer is needed when booting from EFI to get something out the box. [akpm: note: doesn't support modular building] [akpm@osdl.org: cleanups] Signed-off-by: Edgar Hucek Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1a8c9795290361cef232fd54f425a57d143108a8 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:58 2006 -0700 [PATCH] atyfb: Fix section warnings Fix the following warning: WARNING: drivers/video/aty/atyfb.o - Section mismatch: reference to .init.text:aty_init_cursor from .text between 'aty_init' (at offset 0x241d) and 'atyfb_blank' Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9b27915b6aa33b5fbc17beb8c7d5d0b662419018 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:57 2006 -0700 [PATCH] macmodes: Fix section warning Fix the following warning: WARNING: drivers/video/macmodes.o - Section mismatch: reference to .init.text:mac_find_mode from __ksymtab after '__ksymtab_mac_find_mode' (at offset 0x10) Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f837e6f73fe3f04594dad9829df6c7baa5b64a85 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:56 2006 -0700 [PATCH] fbdev: Fix logo rotation if width != height Logo drawing crashes or produces a corrupt display if the logo width and height are not equal. The dimensions are transposed prior to the actual rotation and the width is used instead of the height in the actual rotation code. These produce a corrupt image. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4efefd1d8ea4eaf71bacc4f71fa017c202fa67ec Author: Christian Trefzer Date: Mon Jun 26 00:26:55 2006 -0700 [PATCH] neofb: fix unblank logic interfering with lid toggled backlight This is a fix for the most annoying problem that remained with neofb: After "setterm -powersave powerdown" the console blanker will disable the backlight after the given timeout expires. If this happens after the lid has been shut, we read "LCD off" from the register and store that in the driver. Once the lid is opened, the backlight turns on, but any key press that would awaken the blanked console will switch the backlight off again. The workaround so far was to use the "display config toggle" Fn key combo - once if no external display is attached, otherwise as often as required to restore the desired display setup. The following patch fixes the issue at least for the LCD-only case, with no external monitor attached. Other display setup permutations are pending further testing, but so far I can guarantee at least no negative change in behaviour, if any at all. Signed-off-by: Christian Trefzer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit dc1c43e972c95b82416cc87258dbc037d6de5923 Author: Arnaldo Carvalho de Melo Date: Mon Jun 26 00:26:51 2006 -0700 [PATCH] skeletonfb: remove duplicate module init, exit, license lines Signed-off-by: Arnaldo Carvalho de Melo Acked-by: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f77f50ca1a236ae213d1b9cef4ac042090c98ae6 Author: Rodolfo Giometti Date: Mon Jun 26 00:26:49 2006 -0700 [PATCH] au1100fb: add power management support Add power management support [akpm@osdl.org: cleanup] Signed-off-by: Rodolfo Giometti Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 137a8899b1dba82b54463811844995a33b21ca39 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:49 2006 -0700 [PATCH] backlight: Fix Kconfig dependency CONFIG_FB = m and CONFIG_{BACKLIGHT:LCD}_CLASS_DEVICE = y is possible resulting in link errors. Fix by making backlight and lcd class also depend on FB Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6931a764e1cff26c59be23fbde94cd51fe96bf42 Author: Arnaud Patard Date: Mon Jun 26 00:26:45 2006 -0700 [PATCH] s3c2410fb: Fix resume regs.lcdcon1 was not updated on suspend. The result was a garbaged display on resume. This bug was first noticed by Christer Weinigel. This patch is a modified version of the one he sent to me. Signed-off-by: Arnaud Patard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c72755b3bdcf551dcfb1d061c8f09fc243e28f49 Author: Adrian Bunk Date: Mon Jun 26 00:26:45 2006 -0700 [PATCH] fbdev: Remove unused exports This patch removes the following unused EXPORT_SYMBOL's: - fbcvt.c: fb_find_mode_cvt - fbmem.c: fb_con_duit - fbmem.c: fb_new_modelist - macmodes.c: mac_var_to_vmode - modedb.c: fb_delete_videomode - modedb.c: fb_destroy_modelist Signed-off-by: Adrian Bunk Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 17cc6281c12b26425209c58e3d8825a9568db3cc Author: Antonino A. Daplas Date: Mon Jun 26 00:26:44 2006 -0700 [PATCH] fbdev: Coverity Bug 90 It's a false positive, but let's suppress it anyway. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8126a044f9e686f4ecf95e32fd89ad1dd48b4183 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:43 2006 -0700 [PATCH] fbdev: Coverity Bug 85 It's a false positive, but let's suppress it anyway. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0fa67f84f445e8c567f8a189f2262dd9f8334bc1 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:43 2006 -0700 [PATCH] atyfb: Fix dead code Coverity Bug 68: Fix dead code Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4ee1acce49d616e0e3fbff76fa1dea0c7350535d Author: David Hollister Date: Mon Jun 26 00:26:41 2006 -0700 [PATCH] vt: Delay the update of the visible console Delay the update of the visible framebuffer console until all other consoles have been initialized in order to avoid losing information. This only seems to be a problem with modules, not with built-in drivers. Signed-off-by: David Hollister Signed-off-by: Jordan Crouse Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6dbde380ca525bbfedd65e11402f345e1d64cba9 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:41 2006 -0700 [PATCH] vesafb: Prefer VGA registers over PMI - As per VESA specs, use the VGA registers to set the palette if the mode is VGA compatible. Otherwise, use the protected mode interface. - Make pmi_setpal default to 1 Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 313ca22f0bfab792adeb447146d9cb86536c64d3 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:40 2006 -0700 [PATCH] vesafb: Fix return code of vesafb_setcolreg If the hardware palette cannot be accessed, make vesafb_setcolreg return a nonzero value. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f71689e4139a91c98cc476240aca40bd091d4538 Author: Dennis Munsie Date: Mon Jun 26 00:26:39 2006 -0700 [PATCH] fbdev: Add 1366x768 (WXGA) mode to mode database Adds 1366x768 @ 60Hz to drivers/video/modedb.c. Signed-off-by: Dennis Munsie Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit fe610671d7a88e363e8cebcb7e2f32078b0151ce Author: Antonino A. Daplas Date: Mon Jun 26 00:26:38 2006 -0700 [PATCH] nvidiafb: Add support for Geforce 6100 and related chipsets Add support for Geforce 6100 and related chipsets (PCI device id 0x024x) Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ba70710e59c701734aad524bc441b3400700e94b Author: Antonino A. Daplas Date: Mon Jun 26 00:26:37 2006 -0700 [PATCH] fbdev: Firmware EDID fixes - make firmware edid independent from framebuffer (No need to choose framebuffer just to disable this option - enable this option in X86_64 - check if VBE/DDC function is implemented before calling actual function Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 026fbe16c29848648599df9967b98250a6b86916 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:36 2006 -0700 [PATCH] savagefb: Whitespace cleanup Whitespace cleanup Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0c683dbfc017e52e632853b33981be1a49276ba6 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:36 2006 -0700 [PATCH] fbdev: Static pseudocolor with depth less than 4 does exist A static pseudocolor visual with depth less than 4 does exist, so let's not accidentally upscale the depth with this configuration Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ae6d3218760f3cc28192de1f7ff594be744495b4 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:35 2006 -0700 [PATCH] vga16fb: Update platform code Update platform code to dynamically allocate the platform device Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 20cecf6a6ade62e3a721eb31540f22126df7462b Author: Antonino A. Daplas Date: Mon Jun 26 00:26:34 2006 -0700 [PATCH] vfb: Update platform code Update platform code to dynamically allocate the platform device Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 103edf024b98ff6a1feef9c43886f39b00c5753d Author: Antonino A. Daplas Date: Mon Jun 26 00:26:33 2006 -0700 [PATCH] vesafb: Update platform code Update platform code to dynamically allocate the platform device Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 673681c1b575a73159606ae3c4498de851596489 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:33 2006 -0700 [PATCH] epson1355fb: Update platform code Update platform code to dynamically allocate the platform device Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7914cb27eebed4868bac01a28f550ea966fb422e Author: Antonino A. Daplas Date: Mon Jun 26 00:26:32 2006 -0700 [PATCH] atyfb: Set correct acceleration flags Set the appropriate acceleration flags so fbcon can choose the optimal scrolling mode. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 58221097a8d8aa2151a70cbf749977998bb3d815 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:31 2006 -0700 [PATCH] atyfb: Remove unneeded calls to wait_for_idle The drawing functions of atyfb is unecessary syncing the GPU which is affecting performance. Remove the calls, any direct access by fbcon to the framebuffer will always be preceeded by a call to atyfb_sync(). Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 72c24cc51aef31219f2e258b4dcb68e09399e040 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:31 2006 -0700 [PATCH] atyfb: Fix hardware cursor handling Fix image and color handling in atyfb_cursor() - In the 2-bit scheme of the cursor image, just set the first bit to be always zero (turn off transparency and/or XOR), and just do the masking manually - The cursor color is converted into 32-bit RGBA8888 using struct fb_cmap. Each component in the cmap is u16 in size, so mask the upper 8 bits. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8eec4981080dc9dcf8fd5931a947c6f066ee0be6 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:30 2006 -0700 [PATCH] nvidiafb: Revise pci_device_id table nVidia is churning out chipsets like there's no tomorrow. And even though the pci_device_id table now has numerous entries, it is still not guaranteed that all supported devices are included or will be included. Fortunately, nvidiafb has chipset detection logic built in. So, change the contents of the pci_device_id table so it will capture all nVidia devices of the display class. Unsupported chipsets will then be filtered out by nvidiafb's detection logic. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3007683144b2d53008363f5a7b36a78c53710db4 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:29 2006 -0700 [PATCH] fbdev: More accurate sync range extrapolation The EDID block should specify the display's operating limits (vertical and horizontal sync ranges, and maximum dot clock). If not given by the EDID block, the ranges are extrapolated from the modelist. However, the computation used is only a rough approximation, and the resulting values may not reflect the actual capability of the display. This problem is frequently encountered when the EDID block has a single entry, the single mode entry will fail validation. To prevent this, calculate the values based on the same method used in fb_validate_mode(). Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 22f4a00fd5207a107fb81984f7b4cc09e5047b45 Author: Adrian Bunk Date: Mon Jun 26 00:26:28 2006 -0700 [PATCH] fbdev: Remove duplicate #include's Remove unneeded duplicate #include's of the same header file. In the case of fbmon.c linux/pci.h is now #include'd unconditional, but this should be safe. Signed-off-by: Adrian Bunk Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 31c5cdba69c3c6e9bb1aaf15870f5c23402267e0 Author: Adrian Bunk Date: Mon Jun 26 00:26:28 2006 -0700 [PATCH] fbdev: cleanup the CONFIG_VIDEO_SELECT mess We had three (sic) VIDEO_SELECT options: - two in drivers/video/Kconfig - one in drivers/video/console/Kconfig This patch removes the two options in drivers/video/Kconfig and also removes the unneeded usage in drivers/video/sis/sis_main.c . Signed-off-by: Adrian Bunk Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e4423781850025726b6c4e24ba3d93c7ff9cd826 Author: Richard Purdie Date: Mon Jun 26 00:26:27 2006 -0700 [PATCH] backlight: LOCOMO Backlight Driver updates Add backlight intensity control to the LOCOMO lcd/backlight driver using the backlight class and add basic power management support. This is a reimplementation and improvement of patches by John Lenz and Pavel Machek Signed-off-by: Richard Purdie Signed-off-by: Antonino Daplas Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f8020dc560fde089becc05de1d0ada1f7f46dc51 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:24 2006 -0700 [PATCH] savagefb: Add state save and_restore hooks Reported by: Rich (Bugzilla Bug 6417) "if savage driver is used in x.org together with savagefb, it results in seriously garbled and distorted screen - coupled with severe slowdowns." This bug is the result of Xorg unable to handle savagefb altering the hardware which results in X failing to start properly and/or failed console switching. Add savagefb_state_save and savagefb_state_restore. These hooks will only save and restore the extended VGA registers. Standard VGA registers will be left alone. This is enough to make savagefb play nicely with the latest Xorg savage driver, and perhaps with savage DRI. (Transient screen artifacts may appear before X loads and during console switches). (Unfortunately, blanking the screen also leaves Xorg in a blanked state, so I have to unblank the screen before Xorg loads. So I doubt if the transient screen artifacts will be completely invisible but hopefully it will only be for a shorter duration (not much).) [akpm@osdl.org: cleanups] Signed-off-by: Antonino Daplas Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2356614b08bf8769790c4f1f55c83d95f802bc51 Author: Antonino A. Daplas Date: Mon Jun 26 00:26:23 2006 -0700 [PATCH] savagefb: Allocate space for current and saved register states Allocate space for 2 register states: 'current' for the current state of the hardware, and 'saved', to be used for restoring the hardware to a sane state. This is in preparation for the addition of state save and restore hooks to make savagefb work together with the latest Xorg savage driver. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1ba70a019599b4fa3e091c6dbc4a04e2c607eea3 Author: Tobias Oed Date: Mon Jun 26 00:26:19 2006 -0700 [PATCH] Remove code that has long been commented out from pdc20265_old Signed-off-by: Tobias Oed Acked-by: Alan Cox Cc: Bartlomiej Zolnierkiewicz Cc: Sergei Shtylyov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit fb4ece268bfebaa9f8084b3aa854b56867935724 Author: Tobias Oed Date: Mon Jun 26 00:26:18 2006 -0700 [PATCH] pdc202xx_old depends on CONFIG_BLK_DEV_IDEDMA The driver pdc202xx_old requires CONFIG_BLK_DEV_IDEDMA, so it's always defined Signed-off-by: Tobias Oed Acked-by: Alan Cox Cc: Bartlomiej Zolnierkiewicz Cc: Sergei Shtylyov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3d1c1cc962cebaae6a70fd89a0adb29ad10a2a12 Author: Ingo Molnar Date: Mon Jun 26 00:26:17 2006 -0700 [PATCH] fix IDE deadlock in error reporting code Michal Piotrowski reported the following validator assert: hdd: set_drive_speed_status: status=0x51 { DriveReady SeekComplete Error } hdd: set_drive_speed_status: error=0xb4 { AbortedCommand LastFailedSense=0x0b } ============================ [ BUG: illegal lock usage! ] ---------------------------- illegal {in-hardirq-W} -> {hardirq-on-W} usage. hdparm/1821 [HC0[0]:SC0[0]:HE1:SE1] takes: (ide_lock){++..}, at: [] ide_dump_opcode+0x13/0x9b [...] stack backtrace: [] show_trace+0x1b/0x20 [] dump_stack+0x1f/0x24 [] print_usage_bug+0x1a5/0x1b1 [] mark_lock+0x2ca/0x4f7 [] __lockdep_acquire+0x47e/0xaa4 [] lockdep_acquire+0x67/0x7f [] _spin_lock+0x24/0x32 [] ide_dump_opcode+0x13/0x9b [] ide_dump_status+0x4a6/0x4cc [] ide_config_drive_speed+0x32a/0x33a [] piix_tune_chipset+0x2ed/0x2f8 [] piix_config_drive_xfer_rate+0x61/0xb5 [] set_using_dma+0x2f/0x60 [] ide_write_setting+0x4a/0xc3 [] generic_ide_ioctl+0x8a/0x47f [] idecd_ioctl+0xfd/0x133 [ide_cd] [] blkdev_driver_ioctl+0x4b/0x5f [] blkdev_ioctl+0x770/0x7bd [] block_ioctl+0x1f/0x21 [] do_ioctl+0x27/0x6e [] vfs_ioctl+0x26a/0x280 [] sys_ioctl+0x4d/0x7e [] sysenter_past_esp+0x63/0xa1 in ide_dump_opcode() takes the ide_lock in an irq-unsafe manner, i.e. this function expects to be called with irqs disabled. But ide_dump_ata[pi]_status() doesnt do that - it enables interrupts specifically. That is a no-no - what guarantees that another IDE port couldnt generate an IDE interrupt while we are dumping this error? The fix is to turn the irq-enabling in these functions into irq-disabling. Signed-off-by: Ingo Molnar Cc: Michal Piotrowski Cc: Alan Cox Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8b6ebe016bf68fc9b3f3f2ce79c1918b0808481c Author: Sergei Shtylyov Date: Mon Jun 26 00:26:16 2006 -0700 [PATCH] ide: pdc202xx_old: remove the obsolete busproc Remove the busproc from pdc202xx_old.c because: - it handles the obsolete HDIO_TRISTATE_HWIF ioctl instead of the modern HDIO_SET_BUSSTATE, so treats its argument wrong; - I don't think that tristating both channels is good idea (probably can't be done otherwise since there seems to be only single bit controlling this). Signed-off-by: Sergei Shtylyov Cc: Bartlomiej Zolnierkiewicz Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 17c1033d331a430ce631805e15215e63b4cce764 Author: Sergei Shtylyov Date: Mon Jun 26 00:26:15 2006 -0700 [PATCH] ide: actually honor drive's minimum PIO/DMA cycle times The function ide_timing_compute() fails to *actually* take drive's specified minimum PIO/DMA cycle times into account -- when doing this, it calls ide_timing_merge() on the 'struct ide_timing' argument which contains garbage at the moment, and then ultimately destroys the read cycle time by quantizing the ide_timing[] entry, instead of copying from that entry to the argument structure, and only then doing a merge/quantize. Cc: Bartlomiej Zolnierkiewicz Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 178184b60979992508130741f16499c360bc9c9a Author: Al Boldi Date: Mon Jun 26 00:26:13 2006 -0700 [PATCH] ide-io: increase timeout value to allow for slave wakeup During an STR resume cycle, the ide master disk times-out when there is also a slave present (especially CD). Increasing the timeout in ide-io from 10,000 to 100,000 fixes this problem. Acked-by: Alan Cox Cc: Bartlomiej Zolnierkiewicz Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4fb0f76d8cf4f7a3ffc36dd5e1bc8ca977b68824 Author: Alan Cox Date: Mon Jun 26 00:26:12 2006 -0700 [PATCH] Fix IDE locking error This bit us a few kernels ago, and for some reason never made it's way upstream. https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=144743 Kernel panic - not syncing: drivers/ide/pci/piix.c:231: spin_lock(drivers/ide/ide.c:c03cef28) already locked by driver/ide/ide-iops.c/1153. Signed-off-by: Dave Jones Cc: Bartlomiej Zolnierkiewicz Cc: Dave Jones Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b5cdccf841d7d29fb96e03de5a64ed395e0fde61 Author: Tobias Oed Date: Mon Jun 26 00:26:11 2006 -0700 [PATCH] ide: pdc202xx_old.c: remove unneeded tuneproc() call Remove a call to hwif->tuneproc() on the error path of config_chipset_for_dma(), as its single caller (pdc202xx_config_drive_xfer_rate()) will do the call in that case. Signed-off-by: Tobias Oed Cc: Bartlomiej Zolnierkiewicz Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cf2dfbfbf4c5cb489ea12defd85a484307b955b8 Author: Oleg Nesterov Date: Mon Jun 26 00:26:10 2006 -0700 [PATCH] coredump: copy_process: don't check SIGNAL_GROUP_EXIT After the previous patch SIGNAL_GROUP_EXIT implies a pending SIGKILL, we can remove this check from copy_process() because we already checked !signal_pending(). Signed-off-by: Oleg Nesterov Cc: Roland McGrath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5debfa6da5b06954bc79fe8deed0d1062c58dcec Author: Oleg Nesterov Date: Mon Jun 26 00:26:09 2006 -0700 [PATCH] coredump: shutdown current process first This patch optimizes zap_threads() for the case when there are no ->mm users except the current's thread group. In that case we can avoid 'for_each_process()' loop. It also adds a useful invariant: SIGNAL_GROUP_EXIT (if checked under ->siglock) always implies that all threads (except may be current) have pending SIGKILL. Signed-off-by: Oleg Nesterov Cc: Roland McGrath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit dcf560c59330945a231d5e52f95dfedde4e32c9d Author: Oleg Nesterov Date: Mon Jun 26 00:26:08 2006 -0700 [PATCH] coredump: some code relocations This is a preparation for the next patch. No functional changes. Basically, this patch moves '->flags & SIGNAL_GROUP_EXIT' check into zap_threads(), and 'complete(vfork_done)' into coredump_wait outside of ->mmap_sem protected area. Signed-off-by: Oleg Nesterov Cc: Roland McGrath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7b1c6154fa8bb937e0b1b4f2adbb315d70270f10 Author: Oleg Nesterov Date: Mon Jun 26 00:26:08 2006 -0700 [PATCH] coredump: don't take tasklist_lock This patch removes tasklist_lock from zap_threads(). This is safe wrt: do_exit: The caller holds mm->mmap_sem. This means that task which shares the same ->mm can't pass exit_mm(), so it can't be unhashed from init_task.tasks or ->thread_group lists. fork: None of sub-threads can fork after zap_process(leader). All processes which were created before this point should be visible to zap_threads() because copy_process() adds the new process to the tail of init_task.tasks list, and ->siglock lock/unlock provides a memory barrier. de_thread: It does list_replace_rcu(&leader->tasks, ¤t->tasks). So zap_threads() will see either old or new leader, it does not matter. However, it can change p->sighand, so we should use lock_task_sighand() in zap_process(). Signed-off-by: Oleg Nesterov Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d5f70c00ad24cd1158d3678b44ff969b4c971d49 Author: Oleg Nesterov Date: Mon Jun 26 00:26:07 2006 -0700 [PATCH] coredump: kill ptrace related stuff With this patch zap_process() sets SIGNAL_GROUP_EXIT while sending SIGKILL to the thread group. This means that a TASK_TRACED task 1. Will be awakened by signal_wake_up(1) 2. Can't sleep again via ptrace_notify() 3. Can't go to do_signal_stop() after return from ptrace_stop() in get_signal_to_deliver() So we can remove all ptrace related stuff from coredump path. Signed-off-by: Oleg Nesterov Cc: "Eric W. Biederman" Cc: Roland McGrath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 281de339ceb822ca6c04d4373ecb9a45c1890ce4 Author: Oleg Nesterov Date: Mon Jun 26 00:26:06 2006 -0700 [PATCH] coredump: speedup SIGKILL sending With this patch a thread group is killed atomically under ->siglock. This is faster because we can use sigaddset() instead of force_sig_info() and this is used in further patches. Signed-off-by: Oleg Nesterov Cc: "Eric W. Biederman" Acked-by: Roland McGrath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit aceecc041217b35df753d1ed6e25bd17c0c558d8 Author: Oleg Nesterov Date: Mon Jun 26 00:26:05 2006 -0700 [PATCH] coredump: optimize ->mm users traversal zap_threads() iterates over all threads to find those ones which share current->mm. All threads in the thread group share the same ->mm, so we can skip entire thread group if it has another ->mm. This patch shifts the killing of thread group into the newly added zap_process() function. This looks as unnecessary complication, but it is used in further patches. Signed-off-by: Oleg Nesterov Cc: "Eric W. Biederman" Acked-by: Roland McGrath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2ceb8693ef63ae3d154ce1a05d275f2bb20a5e4c Author: Oleg Nesterov Date: Mon Jun 26 00:26:04 2006 -0700 [PATCH] de_thread: fix lockless do_each_thread We should keep the value of old_leader->tasks.next in de_thread, otherwise we can't do for_each_process/do_each_thread without tasklist_lock held. Signed-off-by: Oleg Nesterov Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 42c3e03ef6b298813557cdb997bd6db619cd65a2 Author: Eric Paris Date: Mon Jun 26 00:26:03 2006 -0700 [PATCH] SELinux: Add sockcreate node to procattr API Below is a patch to add a new /proc/self/attr/sockcreate A process may write a context into this interface and all subsequent sockets created will be labeled with that context. This is the same idea as the fscreate interface where a process can specify the label of a file about to be created. At this time one envisioned user of this will be xinetd. It will be able to better label sockets for the actual services. At this time all sockets take the label of the creating process, so all xinitd sockets would just be labeled the same. I tested this by creating a tcp sender and listener. The sender was able to write to this new proc file and then create sockets with the specified label. I am able to be sure the new label was used since the avc denial messages kicked out by the kernel included both the new security permission setsockcreate and all the socket denials were for the new label, not the label of the running process. Signed-off-by: Eric Paris Signed-off-by: James Morris Cc: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c1df7fb88a011b39ea722ac00975c5b8a803261b Author: Oleg Nesterov Date: Mon Jun 26 00:26:02 2006 -0700 [PATCH] cleanup next_tid() Try to make next_tid() a bit more readable and deletes unnecessary "pid_alive(pos)" check. Signed-off-by: Oleg Nesterov Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a872ff0cb2218dc9688b990c5ccda064dc40946b Author: Oleg Nesterov Date: Mon Jun 26 00:26:01 2006 -0700 [PATCH] simplify/fix first_tid() first_tid: /* If nr exceeds the number of threads there is nothing todo */ if (nr) { if (nr >= get_nr_threads(leader)) goto done; } This is not reliable: sub-threads can exit after this check, so the 'for' loop below can overlap and proc_task_readdir() can return an already filldir'ed dirents. for (; pos && pid_alive(pos); pos = next_thread(pos)) { if (--nr > 0) continue; Off-by-one error, will return 'leader' when nr == 1. This patch tries to fix these problems and simplify the code. Signed-off-by: Oleg Nesterov Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cc288738c9ae3c64d3c50b86604044d1f6d22941 Author: Eric W. Biederman Date: Mon Jun 26 00:26:01 2006 -0700 [PATCH] proc: Remove tasklist_lock from proc_task_readdir. This is just like my previous removal of tasklist_lock from first_tgid, and next_tgid. It simply had to wait until it was rcu safe to walk the thread list. This should be the last instance of the tasklist_lock in proc. So user processes should not be able to influence the tasklist lock hold times. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit df26c40e567356caeefe2861311e19c54444d917 Author: Eric W. Biederman Date: Mon Jun 26 00:25:59 2006 -0700 [PATCH] proc: Cleanup proc_fd_access_allowed In process of getting proc_fd_access_allowed to work it has developed a few warts. In particular the special case that always allows introspection and the special case to allow inspection of kernel threads. The special case for introspection is needed for /proc/self/mem. The special case for kernel threads really should be overridable by security modules. So consolidate these checks into ptrace.c:may_attach(). The check to always allow introspection is trivial. The check to allow access to kernel threads, and zombies is a little trickier. mem_read and mem_write already verify an mm exists so it isn't needed twice. proc_fd_access_allowed only doesn't want a check to verify task->mm exits, s it prevents all access to kernel threads. So just move the task->mm check into ptrace_attach where it is needed for practical reasons. I did a quick audit and none of the security modules in the kernel seem to care if they are passed a task without an mm into security_ptrace. So the above move should be safe and it allows security modules to come up with more restrictive policy. Signed-off-by: Eric W. Biederman Cc: Stephen Smalley Cc: Chris Wright Cc: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 778c1144771f0064b6f51bee865cceb0d996f2f9 Author: Eric W. Biederman Date: Mon Jun 26 00:25:58 2006 -0700 [PATCH] proc: Use sane permission checks on the /proc//fd/ symlinks Since 2.2 we have been doing a chroot check to see if it is appropriate to return a read or follow one of these magic symlinks. The chroot check was asking a question about the visibility of files to the calling process and it was actually checking the destination process, and not the files themselves. That test was clearly bogus. In my first pass through I simply fixed the test to check the visibility of the files themselves. That naive approach to fixing the permissions was too strict and resulted in cases where a task could not even see all of it's file descriptors. What has disturbed me about relaxing this check is that file descriptors are per-process private things, and they are occasionaly used a user space capability tokens. Looking a little farther into the symlink path on /proc I did find userid checks and a check for capability (CAP_DAC_OVERRIDE) so there were permissions checking this. But I was still concerned about privacy. Besides /proc there is only one other way to find out this kind of information, and that is ptrace. ptrace has been around for a long time and it has a well established security model. So after thinking about it I finally realized that the permission checks that make sense are the permission checks applied to ptrace_attach. The checks are simple per process, and won't cause nasty surprises for people coming from less capable unices. Unfortunately there is one case that the current ptrace_attach test does not cover: Zombies and kernel threads. Single stepping those kinds of processes is impossible. Being able to see which file descriptors are open on these tasks is important to lsof, fuser and friends. So for these special processes I made the rule you can't find out unless you have CAP_SYS_PTRACE. These proc permission checks should now conform to the principle of least surprise. As well as using much less code to implement :) Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5b0c1dd38b66e2dd0cf655aa845e341b50b93ddd Author: Eric W. Biederman Date: Mon Jun 26 00:25:57 2006 -0700 [PATCH] proc: optimize proc_check_dentry_visible The code doesn't need to sleep to when making this check so I can just do the comparison and not worry about the reference counts. TODO: While looking at this I realized that my original cleanup did not push the permission check far enough down into the stack. The call of proc_check_dentry_visible needs to move out of the generic proc readlink/follow link code and into the individual get_link instances. Otherwise the shared resources checks are not quite correct (shared files_struct does not require a shared fs_struct), and there are races with unshare. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 13b41b09491e5d75e8027dca1ee78f5e073bc4c0 Author: Eric W. Biederman Date: Mon Jun 26 00:25:56 2006 -0700 [PATCH] proc: Use struct pid not struct task_ref Incrementally update my proc-dont-lock-task_structs-indefinitely patches so that they work with struct pid instead of struct task_ref. Mostly this is a straight 1-1 substitution. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 99f895518368252ba862cc15ce4eb98ebbe1bec6 Author: Eric W. Biederman Date: Mon Jun 26 00:25:55 2006 -0700 [PATCH] proc: don't lock task_structs indefinitely Every inode in /proc holds a reference to a struct task_struct. If a directory or file is opened and remains open after the the task exits this pinning continues. With 8K stacks on a 32bit machine the amount pinned per file descriptor is about 10K. Normally I would figure a reasonable per user process limit is about 100 processes. With 80 processes, with a 1000 file descriptors each I can trigger the 00M killer on a 32bit kernel, because I have pinned about 800MB of useless data. This patch replaces the struct task_struct pointer with a pointer to a struct task_ref which has a struct task_struct pointer. The so the pinning of dead tasks does not happen. The code now has to contend with the fact that the task may now exit at any time. Which is a little but not muh more complicated. With this change it takes about 1000 processes each opening up 1000 file descriptors before I can trigger the OOM killer. Much better. [mlp@google.com: task_mmu small fixes] Signed-off-by: Eric W. Biederman Cc: Trond Myklebust Cc: Paul Jackson Cc: Oleg Nesterov Cc: Albert Cahalan Signed-off-by: Prasanna Meda Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8578cea7509cbdec25b31d08b48a92fcc3b1a9e3 Author: Eric W. Biederman Date: Mon Jun 26 00:25:54 2006 -0700 [PATCH] proc: make PROC_NUMBUF the buffer size for holding integers as strings Currently in /proc at several different places we define buffers to hold a process id, or a file descriptor . In most of them we use either a hard coded number or a different define. Modify them all to use PROC_NUMBUF, so the code has a chance of being maintained. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9cc8cbc7f8b7bc3db48bf6d59a731af728e786ce Author: Eric W. Biederman Date: Mon Jun 26 00:25:52 2006 -0700 [PATCH] simply fix first_tgid Like the bug Oleg spotted in first_tid there was also a small off by one error in first_tgid, when a seek was done on the /proc directory. This fixes that and changes the code structure to make it a little more obvious what is going on. Signed-off-by: Eric W. Biederman Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit de7587343bfebc186995ad294e3de0da382eb9bc Author: Eric W. Biederman Date: Mon Jun 26 00:25:51 2006 -0700 [PATCH] proc: Remove tasklist_lock from proc_pid_lookup() and proc_task_lookup() Since we no longer need the tasklist_lock for get_task_struct the lookup methods no longer need the tasklist_lock. This just depends on my previous patch that makes get_task_struct() rcu safe. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 454cc105ef690f2a0ba7c6b194d55666b4e918ce Author: Eric W. Biederman Date: Mon Jun 26 00:25:51 2006 -0700 [PATCH] proc: Remove tasklist_lock from proc_pid_readdir We don't need the tasklist_lock to safely iterate through processes anymore. This depends on my previous to task patches that make get_task_struct rcu safe, and that make next_task() rcu safe. I haven't gotten first_tid/next_tid yet only because next_thread is missing an rcu_dereference. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0bc58a910220be3446eedc8e77fd45c0a16d8f25 Author: Eric W. Biederman Date: Mon Jun 26 00:25:50 2006 -0700 [PATCH] proc: refactor reading directories of tasks There are a couple of problems this patch addresses. - /proc//task currently does not work correctly if you stop reading in the middle of a directory. - /proc/ currently requires a full pass through the task list with the tasklist lock held, to determine there are no more processes to read. - The hand rolled integer to string conversion does not properly running out of buffer space. - We seem to be batching reading of pids from the tasklist without reason, and complicating the logic of the code. This patch addresses that by changing how tasks are processed. A first_ function is built that handles restarts, and a next_ function is built that just advances to the next task. first_ when it detects a restart usually uses find_task_by_pid. If that doesn't work because there has been a seek on the directory, or we have already given a complete directory listing, it first checks the number tasks of that type, and only if we are under that count does it walk through all of the tasks to find the one we are interested in. The code that fills in the directory is simpler because there is only a single for loop. The hand rolled integer to string conversion is replaced by snprintf which should handle the the out of buffer case correctly. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cd6a3ce9ec040c0b56ea92a81ff710417798c559 Author: Eric W. Biederman Date: Mon Jun 26 00:25:49 2006 -0700 [PATCH] proc: Close the race of a process dying durning lookup proc_lookup and task exiting are not synchronized, although some of the previous code may have suggested that. Every time before we reuse a dentry namei.c calls d_op->derevalidate which prevents us from reusing a stale dcache entry. Unfortunately it does not prevent us from returning a stale dcache entry. This race has been explicitly plugged in proc_pid_lookup but there is nothing to confine it to just that proc lookup function. So to prevent the race I call revalidate explictily in all of the proc lookup functions after I call d_add, and report an error if the revalidate does not succeed. Years ago Al Viro did something similar but those changes got lost in the churn. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 48e6484d49020dba3578ad117b461e8a391e8f0f Author: Eric W. Biederman Date: Mon Jun 26 00:25:48 2006 -0700 [PATCH] proc: Rewrite the proc dentry flush on exit optimization To keep the dcache from filling up with dead /proc entries we flush them on process exit. However over the years that code has gotten hairy with a dentry_pointer and a lock in task_struct and misdocumented as a correctness feature. I have rewritten this code to look and see if we have a corresponding entry in the dcache and if so flush it on process exit. This removes the extra fields in the task_struct and allows me to trivially handle the case of a /proc//task/ entry as well as the current /proc/ entries. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 662795deb854b31501e0ffb42b7f0cce802c134a Author: Eric W. Biederman Date: Mon Jun 26 00:25:48 2006 -0700 [PATCH] proc: Move proc_maps_operations into task_mmu.c All of the functions for proc_maps_operations are already defined in task_mmu.c so move the operations structure to keep the functionality together. Since task_nommu.c implements a dummy version of /proc//maps give it a simplified version of proc_maps_operations that it can modify to best suit its needs. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6e66b52bf587f0dd9a8e0a581b9570e5c1969e33 Author: Eric W. Biederman Date: Mon Jun 26 00:25:47 2006 -0700 [PATCH] proc: Fix the link count for /proc//task Use getattr to get an accurate link count when needed. This is cheaper and more accurate than trying to derive it by walking the thread list of a process. Especially as it happens when needed stat instead of at readdir time. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0f2fe20f55c85f26efaf14feeb69c7c2eb3f7a75 Author: Eric W. Biederman Date: Mon Jun 26 00:25:46 2006 -0700 [PATCH] proc: Properly filter out files that are not visible to a process Long ago and far away in 2.2 we started checking to ensure the files we displayed in /proc were visible to the current process. It was an unsophisticated time and no one was worried about functions full of FIXMES in a stable kernel. As time passed the function became sacred and was enshrined in the shrine of how things have always been. The fixes came in but only to keep the function working no one really remembering or documenting why we did things that way. The intent and the functionality make a lot of sense. Don't let /proc be an access point for files a process can see no other way. The implementation however is completely wrong. We are currently checking the root directories of the two processes, we are not checking the actual file descriptors themselves. We are strangely checking with a permission method instead of just when we use the data. This patch fixes the logic to actually check the file descriptors and make a note that implementing a permission method for this part of /proc almost certainly indicates a bug in the reasoning. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 22c2c5d75e6ad4b9ac41269476b32ba8c9fe263f Author: Eric W. Biederman Date: Mon Jun 26 00:25:45 2006 -0700 [PATCH] proc: Kill proc_mem_inode_operations The inode operations only exist to support the proc_permission function. Currently mem_read and mem_write have all the same permission checks as ptrace. The fs check makes no sense in this context, and we can trivially get around it by calling ptrace. So simply the code by killing the strange weird case. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 68602066c3327fa340899609d715781eda423751 Author: Eric W. Biederman Date: Mon Jun 26 00:25:45 2006 -0700 [PATCH] proc: Remove bogus proc_task_permission First we can access every /proc//task/ directory as /proc/ so proc_task_permission is not usefully limiting visibility. Second having related filesystems information should have nothing to do with process visibility. kill does not implement any checks like that. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit aed7a6c476d90660ac5af860158407ae9fe61c68 Author: Eric W. Biederman Date: Mon Jun 26 00:25:44 2006 -0700 [PATCH] proc: Replace proc_inode.type with proc_inode.fd The sole renaming use of proc_inode.type is to discover the file descriptor number, so just store the file descriptor number and don't wory about processing this field. This removes any /proc limits on the maximum number of file descriptors, and clears the path to make the hard coded /proc inode numbers go away. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 87bfbf679ffb1e95dd9ada694f66aafc4bfa5959 Author: Eric W. Biederman Date: Mon Jun 26 00:25:43 2006 -0700 [PATCH] proc: Simplify the ownership rules for /proc Currently in /proc if the task is dumpable all of files are owned by the tasks effective users. Otherwise the files are owned by root. Unless it is the /proc// or /proc//task/ directory in that case we always make the directory owned by the effective user. However the special case for directories is pointless except as a way to read the effective user, because the permissions on both of those directories are world readable, and executable. /proc//status provides a much better way to read a processes effecitve userid, so it is silly to try to provide that on the directory. So this patch simplifies the code by removing a pointless special case and gets us one step closer to being able to remove the hard coded /proc inode numbers. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 167965495153ba9829d0a34b6800dbf5d94de8c8 Author: Eric W. Biederman Date: Mon Jun 26 00:25:42 2006 -0700 [PATCH] proc: Remove unnecessary and misleading assignments from proc_pid_make_inode The removed fields are already set by proc_alloc_inode. Initializing them in proc_alloc_inode implies they need it for proper cleanup. At least ei->pde was not set on all paths making it look like proc_alloc_inode was buggy. So just remove the redundant assignments. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ff9724a3f7a69f7b443c05981f84e28017c2fc5a Author: Eric W. Biederman Date: Mon Jun 26 00:25:42 2006 -0700 [PATCH] proc: Remove useless BKL in proc_pid_readlink We already call everything except do_proc_readlink outside of the BKL in proc_pid_followlink, and there appears to be nothing in do_proc_readlink that needs any special protection. So remove this leftover from one of the BKL cleanup efforts. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5634708b5fce807bdf2091cfafc2fb24d791f0c8 Author: Eric W. Biederman Date: Mon Jun 26 00:25:40 2006 -0700 [PATCH] proc: Fix the .. inode number on /proc//fd Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f05e15b59467d97c30fbffed80db9e00b73d640b Author: Herbert Xu Date: Mon Jun 26 00:25:39 2006 -0700 [PATCH] nfsd kconfig: select things at the closest tristate instead of bool I noticed recently that my CONFIG_CRYPTO_MD5 turned into a y again instead of m. It turns out that CONFIG_NFSD_V4 is selecting it to be y even though I've chosen to compile nfsd as a module. In general when we have a bool sitting under a tristate it is better to select things you need from the tristate rather than the bool since that allows the things you select to be modules. The following patch does it for nfsd. Signed-off-by: Herbert Xu Cc: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5024ad4af69b3570e18d312786dc46318a1bad1a Author: Hansjoerg Lipp Date: Mon Jun 26 00:25:35 2006 -0700 [PATCH] i4l: Gigaset drivers: add IOCTLs to compat_ioctl.h Add the IOCTLs of the Gigaset drivers to compat_ioctl.h in order to make them available for 32 bit programs on 64 bit platforms. Please merge. Signed-off-by: Hansjoerg Lipp Acked-by: Tilman Schmidt Cc: Karsten Keil Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 698e3ed9d4f47286134f66ea333b6679b29e59e4 Author: Tilman Schmidt Date: Mon Jun 26 00:25:34 2006 -0700 [PATCH] isdn4linux: Gigaset driver cleanup The following patch to the common part of the Siemens Gigaset driver prevents it from trying to send the +++ break sequence if the device has been disconnected, and removes a couple of assignments which didn't have any effect. Signed-off-by: Tilman Schmidt Acked-by: Hansjoerg Lipp Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 06163f86349f0b39948a86d21b2db0d53e47fd8c Author: Tilman Schmidt Date: Mon Jun 26 00:25:33 2006 -0700 [PATCH] isdn4linux: Gigaset base driver: improve error recovery The following patch to the Siemens Gigaset base driver adds graceful recovery for some frequently encountered error conditions, by retrying failed control requests (eg. stalled control pipe), and by closing and reopening the AT command channel when it appears to be stuck. Signed-off-by: Tilman Schmidt Acked-by: Hansjoerg Lipp Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9f13fae2479ed2e2801d538d6a22309123c704f6 Author: Eric Sesterhenn Date: Mon Jun 26 00:25:32 2006 -0700 [PATCH] Fix typo in drivers/isdn/hisax/q931.c This fixes coverity bug #517. Since IESIZE is greater than IESIZE_NI1 we might run past the end of ielist_ni1. This fixes it by using the proper IESIZE_NI1 define. Signed-off-by: Eric Sesterhenn Acked-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6aa65472d18703064898eefb5eb58f7ecd0d8912 Author: Michael Buesch Date: Mon Jun 26 00:25:30 2006 -0700 [PATCH] CAPI crash / race condition I am getting more or less reproducible crashes from the CAPI subsystem using the fcdsl driver: Unable to handle kernel NULL pointer dereference at virtual address 00000010 printing eip: c39bbca4 *pde = 00000000 Oops: 0000 [#1] Modules linked in: netconsole capi capifs 3c59x mii fcdsl kernelcapi uhci_hcd usbcore ide_cd cdrom CPU: 0 EIP: 0060:[] Tainted: P VLI EFLAGS: 00010202 (2.6.16.11 #3) EIP is at handle_minor_send+0x17a/0x241 [capi] eax: c24abbc0 ebx: c0b4c980 ecx: 00000010 edx: 00000010 esi: c1679140 edi: c2783016 ebp: 0000c28d esp: c0327e24 ds: 007b es: 007b ss: 0068 Process swapper (pid: 0, threadinfo=c0326000 task=c02e1300) Stack: <0>000005b4 c1679180 00000000 c28d0000 c1ce04e0 c2f69654 c221604e c1679140 c39bc19a 00000038 c20c0400 c075c560 c1f2f800 00000000 c01dc9b5 c1e96a40 c075c560 c2ed64c0 c1e96a40 c01dcd3b c2fb94e8 c075c560 c0327f00 c1e96a40 Call Trace: [] capinc_tty_write+0xda/0xf3 [capi] [] ppp_sync_push+0x52/0xfe [] ppp_sync_send+0x1f5/0x204 [] ppp_push+0x3e/0x9c [] ppp_xmit_process+0x422/0x4cc [] ppp_start_xmit+0x1c1/0x1f6 [] qdisc_restart+0xa7/0x135 [] dev_queue_xmit+0xba/0x19e [] ip_output+0x1eb/0x236 [] ip_forward+0x1c1/0x21a [] ip_rcv+0x38e/0x3ea [] netif_receive_skb+0x166/0x195 [] process_backlog+0x6d/0xd2 [] net_rx_action+0x6a/0xff [] __do_softirq+0x35/0x7d [] do_softirq+0x22/0x26 [] do_IRQ+0x1e/0x25 [] common_interrupt+0x1a/0x20 [] default_idle+0x2b/0x53 [] cpu_idle+0x39/0x4e [] start_kernel+0x20b/0x20d Code: c0 e8 b3 b6 77 fc 85 c0 75 10 68 d8 c8 9b c3 e8 82 3d 75 fc 8b 43 60 5a eb 50 8d 56 50 c7 00 00 00 00 00 66 89 68 04 eb 02 89 ca <8b> 0a 85 c9 75 f8 89 02 89 da ff 46 54 8b 46 10 e8 30 79 fd ff <0>Kernel panic - not syncing: Fatal exception in interrupt That oops took me to the "ackqueue" implementation in capi.c. The crash occured in capincci_add_ack() (auto-inlined by the compiler). I read the code a bit and finally decided to replace the custom linked list implementation (struct capiminor->ackqueue) by a struct list_head. That did not solve the crash, but produced the following interresting oops: Unable to handle kernel paging request at virtual address 00200200 printing eip: c39bb1f5 *pde = 00000000 Oops: 0002 [#1] Modules linked in: netconsole capi capifs 3c59x mii fcdsl kernelcapi uhci_hcd usbcore ide_cd cdrom CPU: 0 EIP: 0060:[] Tainted: P VLI EFLAGS: 00010246 (2.6.16.11 #3) EIP is at capiminor_del_ack+0x18/0x49 [capi] eax: 00200200 ebx: c18d41a0 ecx: c1385620 edx: 00100100 esi: 0000d147 edi: 00001103 ebp: 0000d147 esp: c1093f3c ds: 007b es: 007b ss: 0068 Process events/0 (pid: 3, threadinfo=c1092000 task=c1089030) Stack: <0>c2a17580 c18d41a0 c39bbd16 00000038 c18d41e0 00000000 d147c640 c29e0b68 c29e0b90 00000212 c29e0b68 c39932b2 c29e0bb0 c10736a0 c0119ef0 c399326c c10736a8 c10736a0 c10736b0 c0119f93 c011a06e 00000001 00000000 00000000 Call Trace: [] handle_minor_send+0x1af/0x241 [capi] [] recv_handler+0x46/0x5f [kernelcapi] [] run_workqueue+0x5e/0x8d [] recv_handler+0x0/0x5f [kernelcapi] [] worker_thread+0x0/0x10b [] worker_thread+0xdb/0x10b [] default_wake_function+0x0/0xc [] kthread+0x90/0xbc [] kthread+0x0/0xbc [] kernel_thread_helper+0x5/0xb Code: 7e 02 89 ee 89 f0 5a f7 d0 c1 f8 1f 5b 21 f0 5e 5f 5d c3 56 53 8b 48 50 89 d6 89 c3 8b 11 eb 2f 66 39 71 08 75 25 8b 41 04 8b 11 <89> 10 89 42 04 c7 01 00 01 10 00 89 c8 c7 41 04 00 02 20 00 e8 The interresting part of it is the "virtual address 00200200", which is LIST_POISON2. I thought about some race condition, but as this is an UP system, it leads to questions on how it can happen. If we look at EFLAGS: 00010202, we see that interrupts are enabled at the time of the crash (eflags & 0x200). Finally, I don't understand all the capi code, but I think that handle_minor_send() is racing somehow against capi_recv_message(), which call both capiminor_del_ack(). So if an IRQ occurs in the middle of capiminor_del_ack() and another instance of it is invoked, it leads to linked list corruption. I came up with the following patch. With this, I could not reproduce the crash anymore. Clearly, this is not the correct fix for the issue. As this seems to be some locking issue, there might be more locking issues in that code. For example, doesn't the whole struct capiminor have to be locked somehow? Cc: Carsten Paeth Cc: Kai Germaschewski Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e6f47f978bcd5413fff610613b18e9e0eab9bc1b Author: Anil S Keshavamurthy Date: Mon Jun 26 00:25:29 2006 -0700 [PATCH] Notify page fault call chain With this patch Kprobes now registers for page fault notifications only when their is an active probe registered. Once all the active probes are unregistered their is no need to be notified of page faults and kprobes unregisters itself from the page fault notifications. Hence we will have ZERO side effects when no probes are active. Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3d5631e0631a11633c649bc995a6537ec21b67b4 Author: Anil S Keshavamurthy Date: Mon Jun 26 00:25:28 2006 -0700 [PATCH] Kprobes registers for notify page fault Kprobes now registers for page fault notifications. Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d98f8f05188b45168db43df8ddc9feeb0b1cd512 Author: Anil S Keshavamurthy Date: Mon Jun 26 00:25:27 2006 -0700 [PATCH] Notify page fault call chain for sparc64 Overloading of page fault notification with the notify_die() has performance issues(since the only interested components for page fault is kprobes and/or kdb) and hence this patch introduces the new notifier call chain exclusively for page fault notifications their by avoiding notifying unnecessary components in the do_page_fault() code path. Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4f9e87c0454059e80f3811f95ad9f40ed28c69a2 Author: Anil S Keshavamurthy Date: Mon Jun 26 00:25:27 2006 -0700 [PATCH] Notify page fault call chain for powerpc Overloading of page fault notification with the notify_die() has performance issues(since the only interested components for page fault is kprobes and/or kdb) and hence this patch introduces the new notifier call chain exclusively for page fault notifications their by avoiding notifying unnecessary components in the do_page_fault() code path. Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ae9a5b85655d7133ab8e7c99b742ef20c8dbb7d2 Author: Anil S Keshavamurthy Date: Mon Jun 26 00:25:26 2006 -0700 [PATCH] Notify page fault call chain for ia64 Overloading of page fault notification with the notify_die() has performance issues(since the only interested components for page fault is kprobes and/or kdb) and hence this patch introduces the new notifier call chain exclusively for page fault notifications their by avoiding notifying unnecessary components in the do_page_fault() code path. Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b71b5b652852db1b499d22aaabed8f5043acafad Author: Anil S Keshavamurthy Date: Mon Jun 26 00:25:25 2006 -0700 [PATCH] Notify page fault call chain for i386 Overloading of page fault notification with the notify_die() has performance issues(since the only interested components for page fault is kprobes and/or kdb) and hence this patch introduces the new notifier call chain exclusively for page fault notifications their by avoiding notifying unnecessary components in the do_page_fault() code path. Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1bd858a507937cef6e8ca5efc6820a5744e73683 Author: Anil S Keshavamurthy Date: Mon Jun 26 00:25:25 2006 -0700 [PATCH] Notify page fault call chain for x86_64 Currently in the do_page_fault() code path, we call notify_die(DIE_PAGE_FAULT, ...) to notify the page fault. Since notify_die() is highly overloaded, this page fault notification is currently being sent to all the components registered with register_die_notification() which uses the same die_chain to loop for all the registered components which is unnecessary. In order to optimize the do_page_fault() code path, this critical page fault notification is now moved to different call chain and the test results showed great improvements. And the kprobes which is interested in this notifications, now registers onto this new call chain only when it need to, i.e Kprobes now registers for page fault notification only when their are an active probes and unregisters from this page fault notification when no probes are active. I have incorporated all the feedback given by Ananth and Keith and everyone, and thanks for all the review feedback. This patch: Overloading of page fault notification with the notify_die() has performance issues(since the only interested components for page fault is kprobes and/or kdb) and hence this patch introduces the new notifier call chain exclusively for page fault notifications their by avoiding notifying unnecessary components in the do_page_fault() code path. Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 36721656776f177280ccb50477a02e86e6444292 Author: mao, bibo Date: Mon Jun 26 00:25:22 2006 -0700 [PATCH] Kprobe: multi kprobe posthandler for booster If there are multi kprobes on the same probepoint, there will be one extra aggr_kprobe on the head of kprobe list. The aggr_kprobe has aggr_post_handler/aggr_break_handler whether the other kprobe post_hander/break_handler is NULL or not. This patch modifies this, only when there is one or more kprobe in the list whose post_handler is not NULL, post_handler of aggr_kprobe will be set as aggr_post_handler. [soshima@redhat.com: !CONFIG_PREEMPT fix] Signed-off-by: bibo, mao Cc: Masami Hiramatsu Cc: Ananth N Mavinakayanahalli Cc: "Keshavamurthy, Anil S" Cc: Prasanna S Panchamukhi Cc: Jim Keniston Cc: Yumiko Sugita Cc: Hideo Aoki Signed-off-by: Satoshi Oshima Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 585deacaca3e7bfc63580623f0344d1fa9c47f11 Author: Masami Hiramatsu Date: Mon Jun 26 00:25:19 2006 -0700 [PATCH] kprobe: boost 2byte-opcodes on i386 Previous kprobe-booster patch has not handled any 2byte opcodes and prefixes. I checked whole IA32 opcode map and classified it. This patch enables kprobe to boost those 2byte opcodes and prefixes. Signed-off-by: Masami Hiramatsu Cc: Ananth N Mavinakayanahalli Cc: "Keshavamurthy, Anil S" Cc: Prasanna S Panchamukhi Cc: Jim Keniston Cc: Yumiko Sugita Cc: Satoshi Oshima Cc: Hideo Aoki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6ae7440e6b7a46f4c119c60580aa9384c1b463f7 Author: Jim Cromie Date: Mon Jun 26 00:25:19 2006 -0700 [PATCH] GTOD: add scx200 HRT clocksource Add a GTOD clocksource driver based on the Geode SCx200's Hi-Res Timer. Signed-off-by: Jim Cromie Cc: Roman Zippel Cc: john stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 19923c190e0932bf0ac1e1d06a48f5c3678dd0de Author: Roman Zippel Date: Mon Jun 26 00:25:18 2006 -0700 [PATCH] fix and optimize clock source update This fixes the clock source updates in update_wall_time() to correctly track the time coming in via current_tick_length(). Optimize the fast paths to be as short as possible to keep the overhead low. Signed-off-by: Roman Zippel Acked-by: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6415ce9a922a1446e7ee0ac9b016082232ebe373 Author: john stultz Date: Mon Jun 26 00:25:16 2006 -0700 [PATCH] time: fix time going backward w/ clock=pit Here is the PIT fix against the TOD patches that Tim pointed out. Many thanks to Tim for hunting this down. Cc: Tim Mann Signed-off-by: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7f9f303aa33c7acc7b4aa9ebea25cbd990bc707b Author: Jim Cromie Date: Mon Jun 26 00:25:15 2006 -0700 [PATCH] generic-time: add macro to simplify/hide mask constants Add a CLOCKSOURCE_MASK macro to simplify initializing the mask for a struct clocksource, and use it to replace literal mask constants in the various clocksource drivers. Signed-off-by: Jim Cromie Acked-by: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7d622d4794490cef933c20e4a6279e43e03fafad Author: Andreas Mohr Date: Mon Jun 26 00:25:14 2006 -0700 [PATCH] make pmtmr_ioport __read_mostly - written on init only, accessed for every timer read --> __read_mostly - fix broken sentence Signed-off-by: Andreas Mohr Cc: john stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a275254975a29c51929ee175b92ac471ac2a0043 Author: john stultz Date: Mon Jun 26 00:25:14 2006 -0700 [PATCH] time: rename clocksource functions As suggested by Roman Zippel, change clocksource functions to use clocksource_xyz rather then xyz_clocksource to avoid polluting the namespace. Signed-off-by: John Stultz Cc: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5d0cf410e94b1f1ff852c3f210d22cc6c5a27ffa Author: john stultz Date: Mon Jun 26 00:25:12 2006 -0700 [PATCH] Time: i386 Clocksource Drivers Implement the time sources for i386 (acpi_pm, cyclone, hpet, pit, and tsc). With this patch, the conversion of the i386 arch to the generic timekeeping code should be complete. The patch should be fairly straight forward, only adding the new clocksources. [hirofumi@mail.parknet.co.jp: acpi_pm cleanup] Signed-off-by: John Stultz Signed-off-by: Adrian Bunk Signed-off-by: Paul Mundt Signed-off-by: John Stultz Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 61743fe445213b87fb55a389c8d073785323ca3e Author: john stultz Date: Mon Jun 26 00:25:12 2006 -0700 [PATCH] Time: i386 Conversion - part 4: Remove Old timer_opts Code Remove the old timers/timer_opts infrastructure which has been disabled. It is a fairly straightforward set of deletions Note that this does not provide any i386 clocksources, so you will only have the jiffies clocksource. To get full replacements for the code being removed here, the timeofday-clocks-i386 patch will be needed. Signed-off-by: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6f84fa2f3edc8902cfed02cd510c7c58334bb9bd Author: john stultz Date: Mon Jun 26 00:25:11 2006 -0700 [PATCH] Time: i386 Conversion - part 3: Enable Generic Timekeeping This converts the i386 arch to use the generic timeofday subsystem. It enabled the GENERIC_TIME option, disables the timer_opts code and other arch specific timekeeping code and reworks the delay code. While this patch enables the generic timekeeping, please note that this patch does not provide any i386 clocksource. Thus only the jiffies clocksource will be available. To get full replacements for the code being disabled here, the timeofday-clocks-i386 patch will needed. Signed-off-by: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 539eb11e6e904f2cd4f62908cc5e44d724879721 Author: john stultz Date: Mon Jun 26 00:25:10 2006 -0700 [PATCH] Time: i386 Conversion - part 2: Rework TSC Support As part of the i386 conversion to the generic timekeeping infrastructure, this introduces a new tsc.c file. The code in this file replaces the TSC initialization, management and access code currently in timer_tsc.c (which will be removed) that we want to preserve. The code also introduces the following functionality: o tsc_khz: like cpu_khz but stores the TSC frequency on systems that do not change TSC frequency w/ CPU frequency o check/mark_tsc_unstable: accessor/modifier flag for TSC timekeeping usability o minor cleanups to calibration math. This patch also includes a one line __cpuinitdata fix from Zwane Mwaikambo. Signed-off-by: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8d016ef1380a2a9a5ca5742ede04334199868f82 Author: john stultz Date: Mon Jun 26 00:25:09 2006 -0700 [PATCH] Time: i386 Conversion - part 1: Move timer_pit.c to i8253.c A simple cleanup for the i386 arch in preparation of moving to the generic timeofday infrastructure. It simply moves the PIT initialization code, locks, and other code we want to keep from some code from timer_pit.c (which will be removed) to i8253.c. Signed-off-by: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ede65f3926a284f07765b94d6d9fd10d63791174 Author: Andrew Morton Date: Mon Jun 26 00:25:09 2006 -0700 [PATCH] hangcheck: remove monotomic_clock on x86 John's about to nuke x86's monotonic clock without grepping for it first. The patch lamely borrows the ppc64 code for x86. hangcheck-timer shouldn't be doing it this way a) HAVE_MONOTONIC should be CONFIG_MONOTONIC_CLOCK and it should be defined in arch/xxx/Kconfig. b) That ifdef tangle shouldn't be in hangcheck-timer.c. It should be using arch-provided helper functions, which CONFIG_MONOTONIC_CLOCK-enabling architectures implement in arch/something.c Cc: john stultz Acked-by: Joel Becker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cf3c769b4b0dd1146da84d5cf045dcfe53bd0f13 Author: john stultz Date: Mon Jun 26 00:25:08 2006 -0700 [PATCH] Time: Introduce arch generic time accessors Introduces clocksource switching code and the arch generic time accessor functions that use the clocksource infrastructure. Signed-off-by: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5eb6d20533d14a432df714520939a6181e28f099 Author: john stultz Date: Mon Jun 26 00:25:07 2006 -0700 [PATCH] Time: Use clocksource abstraction for NTP adjustments Instead of incrementing xtime by tick_nsec + ntp adjustments, use the clocksource abstraction to increment and scale time. Using the clocksource abstraction allows other clocksources to be used consistently in the face of late or lost ticks, while preserving the existing behavior via the jiffies clocksource. This removes the need to keep time_phase adjustments as we just use the current_tick_length() function as the NTP interface and accumulate time using shifted nanoseconds. The basics of this design was by Roman Zippel, however it is my own interpretation and implementation, so the credit should go to him and the blame to me. Signed-off-by: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 260a42309b31cbc54eb4b6b85649e412bcad053f Author: john stultz Date: Mon Jun 26 00:25:07 2006 -0700 [PATCH] Time: Let user request precision from current_tick_length() Change the current_tick_length() function so it takes an argument which specifies how much precision to return in shifted nanoseconds. This provides a simple way to convert between NTPs internal nanoseconds shifted by (SHIFT_SCALE - 10) to other shifted nanosecond units that are used by the clocksource abstraction. Signed-off-by: John Stultz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ad596171ed635c51a9eef829187af100cbf8dcf7 Author: john stultz Date: Mon Jun 26 00:25:06 2006 -0700 [PATCH] Time: Use clocksource infrastructure for update_wall_time Modify the update_wall_time function so it increments time using the clocksource abstraction instead of jiffies. Since the only clocksource driver currently provided is the jiffies clocksource, this should result in no functional change. Additionally, a timekeeping_init and timekeeping_resume function has been added to initialize and maintain some of the new timekeping state. [hirofumi@mail.parknet.co.jp: fixlet] Signed-off-by: John Stultz Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 734efb467b31e56c2f9430590a9aa867ecf3eea1 Author: john stultz Date: Mon Jun 26 00:25:05 2006 -0700 [PATCH] Time: Clocksource Infrastructure This introduces the clocksource management infrastructure. A clocksource is a driver-like architecture generic abstraction of a free-running counter. This code defines the clocksource structure, and provides management code for registering, selecting, accessing and scaling clocksources. Additionally, this includes the trivial jiffies clocksource, a lowest common denominator clocksource, provided mainly for use as an example. [hirofumi@mail.parknet.co.jp: Don't enable IRQ too early] Signed-off-by: John Stultz Signed-off-by: Ingo Molnar Signed-off-by: Paul Mundt Signed-off-by: John Stultz Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ade1a29e168ba08b699a418ff5e762315fa33f70 Author: Badari Pulavarty Date: Mon Jun 26 00:25:04 2006 -0700 [PATCH] ext3: Add "-o bh" option This patch adds "-o bh" option to force use of buffer_heads. This option is needed when we make "nobh" as default - and if we run into problems. Signed-off-by: Badari Pulavarty Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 71c0cd7042672fce2463d82183d20bfb574f4cb5 Author: Michael Buesch Date: Mon Jun 26 00:25:04 2006 -0700 [PATCH] Add bcm43xx HW RNG support Signed-off-by: Michael Buesch Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ebc915ad26d881ddcafbe4e0975203d23289f36f Author: Michael Buesch Date: Mon Jun 26 00:25:03 2006 -0700 [PATCH] Add TI OMAP CPU family HW RNG driver Signed-off-by: Michael Buesch Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d7174bcb919c15b295271e37c3f65c716710715c Author: Michael Buesch Date: Mon Jun 26 00:25:02 2006 -0700 [PATCH] Add ixp4xx HW RNG driver Signed-off-by: Michael Buesch Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 13523363577d49b9af3cad06fcb757126bedc61b Author: Michael Buesch Date: Mon Jun 26 00:25:02 2006 -0700 [PATCH] Add VIA HW RNG driver Signed-off-by: Michael Buesch Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ef5d862734b84239e0140319a95fb0bbff5ef394 Author: Michael Buesch Date: Mon Jun 26 00:25:01 2006 -0700 [PATCH] Add Geode HW RNG driver Signed-off-by: Michael Buesch Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 96d63c0297ccfd6d9059c614b3f5555d9441a2b3 Author: Michael Buesch Date: Mon Jun 26 00:25:00 2006 -0700 [PATCH] Add AMD HW RNG driver Signed-off-by: Michael Buesch Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ca644bd5039566725b7c71a559e65ea91b7abfb5 Author: Michael Buesch Date: Mon Jun 26 00:24:59 2006 -0700 [PATCH] Add Intel HW RNG driver Signed-off-by: Michael Buesch Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 844dd05fec172d98b0dacecd9b9e9f6595204c13 Author: Michael Buesch Date: Mon Jun 26 00:24:59 2006 -0700 [PATCH] Add new generic HW RNG core Signed-off-by: Michael Buesch Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 59f5d35f83738bf07e66f8cdcff32a433df804a3 Author: Michael Buesch Date: Mon Jun 26 00:24:58 2006 -0700 [PATCH] Remove old HW RNG support This patch series replaces the old non-generic Hardware Random Number Generator support by a fully generic RNG API. This makes it possible to register additional RNGs from modules. With this patch series applied, Laptops with a bcm43xx chip (PowerBook) have a HW RNG available now. Additionally two new RNG drivers are added for the "ixp4xx" and "omap" devices. (Written by Deepak Saxena). This patch series includes the old patches by Deepak Saxena. The old x86-rng driver has beed split. The userspace RNG daemon can later be updated to select the RNG through /sys/class/misc/hw_random/ for convenience. For now it is sufficient to use cat and echo -n on the sysfs attributes. Signed-off-by: Michael Buesch Acked-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9637f28f8b9facff53b00bea6b5d27c9b150b422 Author: Alexey Dobriyan Date: Mon Jun 26 00:24:57 2006 -0700 [PATCH] reiserfs: remove reiserfs_aio_write() Signed-off-by: Alexey Dobriyan Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4eb582cf1fbd7b9e5f466e3718a59c957e75254e Author: Michael LeMay Date: Mon Jun 26 00:24:57 2006 -0700 [PATCH] keys: add a way to store the appropriate context for newly-created keys Add a /proc//attr/keycreate entry that stores the appropriate context for newly-created keys. Modify the selinux_key_alloc hook to make use of the new entry. Update the flask headers to include a new "setkeycreate" permission for processes. Update the flask headers to include a new "create" permission for keys. Use the create permission to restrict which SIDs each task can assign to newly-created keys. Add a new parameter to the security hook "security_key_alloc" to indicate whether it is being invoked by the kernel, or from userspace. If it is being invoked by the kernel, the security hook should never fail. Update the documentation to reflect these changes. Signed-off-by: Michael LeMay Signed-off-by: James Morris Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 06ec7be557a1259611d6093a00463c42650dc71a Author: Michael LeMay Date: Mon Jun 26 00:24:56 2006 -0700 [PATCH] keys: restrict contents of /proc/keys to Viewable keys Restrict /proc/keys such that only those keys to which the current task is granted View permission are presented. The documentation is also updated to reflect these changes. Signed-off-by: Michael LeMay Signed-off-by: James Morris Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e51f6d343789a4f0a2a7587ad7ec7746969d5c1c Author: Michael LeMay Date: Mon Jun 26 00:24:54 2006 -0700 [PATCH] keys: allocate key serial numbers randomly Cause key_alloc_serial() to generate key serial numbers randomly rather than in linear sequence. Using an linear sequence permits a covert communication channel to be established, in which one process can communicate with another by creating or not creating new keys within a certain timeframe. The second process can probe for the expected next key serial number and judge its existence by the error returned. This is a problem as the serial number namespace is globally shared between all tasks, regardless of their context. For more information on this topic, this old TCSEC guide is recommended: http://www.radium.ncsc.mil/tpep/library/rainbow/NCSC-TG-030.html Signed-off-by: Michael LeMay Signed-off-by: James Morris Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5801649d8b83e7cb9b15839761bdee594653c294 Author: Fredrik Tolf Date: Mon Jun 26 00:24:51 2006 -0700 [PATCH] keys: let keyctl_chown() change a key's owner Let keyctl_chown() change a key's owner, including attempting to transfer the quota burden to the new user. Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 31204ed925b067d2bb65adb89501656f8274a32a Author: David Howells Date: Mon Jun 26 00:24:51 2006 -0700 [PATCH] keys: discard the contents of a key on revocation Cause the keys linked to a keyring to be unlinked from it when revoked and it causes the data attached to a user-defined key to be discarded when revoked. This frees up most of the quota a key occupied at that point, rather than waiting for the key to actually be destroyed. Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7e047ef5fe2d52e83020e856b1bf2556a6a2ce98 Author: David Howells Date: Mon Jun 26 00:24:50 2006 -0700 [PATCH] keys: sort out key quota system Add the ability for key creation to overrun the user's quota in some circumstances - notably when a session keyring is created and assigned to a process that didn't previously have one. This means it's still possible to log in, should PAM require the creation of a new session keyring, and fix an overburdened key quota. Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f116629d03655adaf7832b93b03c99391d09d4a7 Author: Akinobu Mita Date: Mon Jun 26 00:24:46 2006 -0700 [PATCH] fs: use list_move() This patch converts the combination of list_del(A) and list_add(A, B) to list_move(A, B) under fs/. Cc: Ian Kent Acked-by: Joel Becker Cc: Neil Brown Cc: Hans Reiser Cc: Urban Widmark Acked-by: David Howells Acked-by: Mark Fasheh Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 179e09172ab663b8587ecc46bb18a56a770304a9 Author: Akinobu Mita Date: Mon Jun 26 00:24:41 2006 -0700 [PATCH] drivers: use list_move() This patch converts the combination of list_del(A) and list_add(A, B) to list_move(A, B) under drivers/. Acked-by: Corey Minyard Cc: Ben Collins Acked-by: Roland Dreier Cc: Alasdair Kergon Cc: Gerd Knorr Cc: Paul Mackerras Cc: Frank Pavlic Acked-by: Matthew Wilcox Cc: Andrew Vasquez Cc: Mikael Starvik Cc: Greg Kroah-Hartman Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a842ef297fd91b1b93f2aa5898d2efd19e95f6a5 Author: Akinobu Mita Date: Mon Jun 26 00:24:40 2006 -0700 [PATCH] net/rxrpc: use list_move() This patch converts the combination of list_del(A) and list_add(A, B) to list_move(A, B) under net/rxrpc. Acked-by: David Howells Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1bfba4e8ea0e555e3a0296051517d96253660ccc Author: Akinobu Mita Date: Mon Jun 26 00:24:40 2006 -0700 [PATCH] core: use list_move() This patch converts the combination of list_del(A) and list_add(A, B) to list_move(A, B). Cc: Greg Kroah-Hartman Cc: Ram Pai Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a7addcea6ac7c0e9733a48cda06ca0880f116a48 Author: Akinobu Mita Date: Mon Jun 26 00:24:39 2006 -0700 [PATCH] arch: use list_move() This patch converts the combination of list_del(A) and list_add(A, B) to list_move(A, B) under arch/. Cc: Geert Uytterhoeven Cc: "David S. Miller" Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8e13059a37252c45ab7173a0e4bac05e4a444ab6 Author: Akinobu Mita Date: Mon Jun 26 00:24:37 2006 -0700 [PATCH] use list_add_tail() instead of list_add() This patch converts list_add(A, B.prev) to list_add_tail(A, &B) for readability. Acked-by: Karsten Keil Cc: Jan Harkes Acked-by: Jan Kara AOLed-by: David Woodhouse Cc: Sridhar Samudrala Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 38e13929c391e6964b00840b765ed601a3377d33 Author: Alan Cox Date: Mon Jun 26 00:24:36 2006 -0700 [PATCH] Correct tty doc This method died some time ago, so kill the doc for it. Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d2be8ee53856c3c510d4d38f534979747db65d96 Author: Fredrik Roubert Date: Mon Jun 26 00:24:35 2006 -0700 [PATCH] fix magic sysrq on strange keyboards Magic sysrq fails to work on many keyboards, particulary most of notebook keyboards. This patch fixes it. The idea is quite simple: Discard the SysRq break code if Alt is still being held down. This way the broken keyboard can send the break code (or the user with a normal keyboard can release the SysRq key) and the kernel waits until the next key is pressed or the Alt key is released. Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0c6856f702732d3cfc33eb59303e998ad6961de8 Author: Markus Armbruster Date: Mon Jun 26 00:24:34 2006 -0700 [PATCH] oprofile: Fix unnecessary cleverness nmi_create_files() in arch/i386/oprofile/nmi_int.c depends on model->num_counters (number of performance counters) being less than 10. While this is currently the case, it's too clever by half. Other archs aren't quite as clever: they assume 100. I suggest to normalize them all to 1000. Cc: Philippe Elie Cc: John Levon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 57136ca6d57359c7f21a9bbb4a5a0a61eeb53f2b Author: Jesper Juhl Date: Mon Jun 26 00:24:33 2006 -0700 [PATCH] Bluetooth: fix potential NULL ptr deref in dtl1_cs.c::dtl1_hci_send_frame() There's a problem in drivers/bluetooth/dtl1_cs.c::dtl1_hci_send_frame() If bt_skb_alloc() returns NULL, then skb_reserve(s, NSHL); will cause a NULL pointer deref - ouch. If we can't allocate the resources we require we need to tell the caller by returning -ENOMEM. Found by the coverity checker as bug #409 Signed-off-by: Jesper Juhl Acked-by: Marcel Holtmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 81615b624a45621b758380ec45d750483eae281d Author: Ingo Molnar Date: Mon Jun 26 00:24:32 2006 -0700 [PATCH] Convert kernel/cpu.c to mutexes Convert kernel/cpu.c from semaphore to mutex. I've reviewed all lock_cpu_hotplug() critical sections, and they all seem to fit mutex semantics. Signed-off-by: Ingo Molnar Cc: Rusty Russell Cc: Ashok Raj Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1fb00c6cbd8356f43b46322742f3c01c2a1f02da Author: Ingo Molnar Date: Mon Jun 26 00:24:31 2006 -0700 [PATCH] work around ppc64 bootup bug by making mutex-debugging save/restore irqs It seems ppc64 wants to lock mutexes in early bootup code, with interrupts disabled, and they expect interrupts to stay disabled, else they crash. Work around this bug by making mutex debugging variants save/restore irq flags. Signed-off-by: Ingo Molnar Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 20c5426f8155a89b6df06325f9b278f5052b8c7e Author: Andrew Morton Date: Mon Jun 26 00:24:30 2006 -0700 [PATCH] fix "USB: move to " Update this driver for recent header file movement. Cc: David Brownell Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2efe55a9cec8418f0e0cde3dc3787a42fddc4411 Author: Tobias Klauser Date: Mon Jun 26 18:57:34 2006 +0200 Storage class should be first Storage class should be before const Signed-off-by: Tobias Klauser Signed-off-by: Adrian Bunk commit b184a4c9a4e542890265b4cdd3ff7908f4adc9c4 Author: Lennert Buytenhek Date: Mon Jun 26 17:48:29 2006 +0100 [ARM] 3654/1: add ajeco 1arm sbc support Patch from Lennert Buytenhek This patch adds support for the Ajeco 1ARM Single Board Computer, a VME form factor SBC based on the Atmel AT91 SoC, with 64M RAM, seven serial ports, three ethernet ports, IDE, CF, USB host and device, and S-Video/VGA out.-- Signed-off-by: Lennert Buytenhek Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 48a1204c462985378e02b4c5129901f3dbc93f80 Author: Egry Gabor Date: Mon Jun 26 18:47:15 2006 +0200 i386: Trivial typo fixes Trivial typo fixes in Kconfig files (i386). Signed-off-by: Egry Gabor Signed-off-by: Adrian Bunk commit bc940c40c6473cb40178458e2c74aea6b45aac03 Author: Matthew Martin Date: Mon Jun 26 18:43:54 2006 +0200 ixj: make ixj_set_tone_off() static Signed-off-by: Matthew Martin Signed-off-by: Alexey Dobriyan Signed-off-by: Adrian Bunk commit d6e05edc59ecd79e8badf440c0d295a979bdfa3e Author: Andreas Mohr Date: Mon Jun 26 18:35:02 2006 +0200 spelling fixes acquired (aquired) contiguous (contigious) successful (succesful, succesfull) surprise (suprise) whether (weather) some other misspellings Signed-off-by: Andreas Mohr Signed-off-by: Adrian Bunk commit f18190bd3407554ba6df30a1927e07e6cba93e56 Author: Lee Revell Date: Mon Jun 26 18:30:00 2006 +0200 fix paniced->panicked typos In a testament to the utter simplicity and logic of the English language ;-), I found a single correct use - in kernel/panic.c - and 10-15 incorrect ones. Signed-Off-By: Lee Revell Signed-off-by: Adrian Bunk commit a0ebb3ffd6c195011f7e4abdfc40f98342d36ce2 Author: Michael Hayes Date: Mon Jun 26 18:27:35 2006 +0200 Spelling fixes for Documentation/atomic_ops.txt Spelling and typo fixes for Documentation/atomic_ops.txt Signed-off-by: Adrian Bunk commit 0ecbf4b5fc38479ba29149455d56c11a23b131c0 Author: Adrian Bunk Date: Mon Jun 26 18:21:37 2006 +0200 move acknowledgment for Mark Adler to CREDITS The place in the documentation of the Linux kernel to acknowledge contributions is the CREDITS file. Give Mark Adler an entry there instead of including a string in the kernel image. Signed-off-by: Adrian Bunk commit bdca3f202dbeaca2fcc4fb47219476286c999b0d Author: Adrian Bunk Date: Mon Jun 26 18:19:23 2006 +0200 remove the bouncing email address of David Campbell This patch removes a bouncing email address from the kernel sources. Signed-off-by: Adrian Bunk commit cfc736564fd01ee008d746913b1bbb90e3eb1f99 Author: Ingo Molnar Date: Mon Jun 26 15:26:13 2006 +0100 [ARM] fix drivers/mfd/ucb1x00-core.c IRQ probing bug While reviewing the IRQ autoprobing code i found the attached buglet. probe_irq_on()/off() calls must always be in pairs, because the generic IRQ code uses a global semaphore to serialize all autoprobing activites. (which does make sense) The ARM code's probe_irq_*() implementation does not do this, but if this driver is ever used on another platform, this bug might bite. (It probably does not trigger in practice, because a zero probing mask returned should be rare - but still.) Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Russell King commit b07076e6173a2593e369c3375f07c1cd7d78c36f Author: Ben Collins Date: Mon Jun 26 15:24:36 2006 +0100 [SERIAL] 8250_pnp: add support for other Wacom tablets http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=6a242b6c279af7805a6cca8f39dbc5bfe1f78cd1 Signed-off-by: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Russell King commit cd701aa27e4cfab5c99c7da13d404b1f3a0aecfb Author: Ben Dooks Date: Mon Jun 26 15:12:58 2006 +0100 [ARM] 3651/1: S3C24XX: Make arch list more detailed Patch from Ben Dooks Add the rest of the supported S3C24XX family to the configuration selection for ARCH_S3C2410. This should try and make it clearer for people trying to find the S3C2440 or freinds where they can be found.-- Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 28c68e3450a19930d12e1798950d62e09f447ae1 Author: Ben Dooks Date: Mon Jun 26 15:12:57 2006 +0100 [ARM] 3650/1: S3C2412: Update s3c2410_defconfig Patch from Ben Dooks Add SMDK2413 to the list of the machines being built for ARCH_S3C2410, thus ensursing our all machines build has an representitive of the S3C2412/S3C2413 CPU series-- Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 52c5ceceb145fad10b9996ce414dadcb6b02d959 Author: Ben Dooks Date: Mon Jun 26 15:12:56 2006 +0100 [ARM] 3649/1: S3C24XX: Fix capitalisation of CPU on SMDK2440 Patch from Ben Dooks Make CPU uppercase on the SMDK2440 KConfig entries-- Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 33f40b3b023b9f00b40ecfb3a39286de13516b33 Author: Andrew Morton Date: Sun Jun 25 17:48:22 2006 -0300 V4L/DVB (4227): Update this driver for recent header file movement. Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit 8cbde94be34f95c01515ba19ce32bcd51ab3949e Author: Hans Verkuil Date: Sat Jun 24 14:36:02 2006 -0300 V4L/DVB (4223): Add V4L2_CID_MPEG_STREAM_VBI_FMT control V4L2_CID_MPEG_STREAM_VBI_FMT controls if and how VBI data is embedded in an MPEG stream. Currently only one format is supported: the format designed for the ivtv driver. This should be extended with new standard formats (such as defined for DVB) in the future. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 4f725cb3fa46fabe7fd7c7175fa77e12616bfdb8 Author: Hans Verkuil Date: Sat Jun 24 09:47:56 2006 -0300 V4L/DVB (4222): Always switch tuner mode when calling VIDIOC_S_FREQUENCY. Fixes the weird and incorrect condition in VIDIOC_S_FREQUENCY. The tuner should always be switched to the mode specified in the v4l2_frequency struct. Much simpler and also corresponding to the v4l2 specification. The old condition made it impossible to switch from radio to analog tv mode using VIDIOC_S_FREQUENCY. Instead the (tv) frequency would be given to the radio tuner. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 91a972910df042a0a308b2ffd3aa6fd42b0242e3 Author: Hans Verkuil Date: Sat Jun 24 09:26:43 2006 -0300 V4L/DVB (4221): Add HM12 YUV format define. HM12 is a YUV 4:1:1 format used by the cx2341x MPEG encoder/decoder for the raw YUV input/output. The Y and UV planes are broken up in 16x16 macroblocks and each macroblock is transmitted in turn (row by row). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 61391e0446e97bea44d93bd1624e5b32d3cc8474 Author: Tim Kaiser Date: Sun Jun 25 09:14:07 2006 -0300 V4L/DVB (4219): Av7110: analog sound output of DVB-C rev 2.3 Added support for the msp34x5 audio dac. Analog sound output of Technotrend DVB-C 2300 (aka Hauppauge Nexus-CA) works now. Signed-off-by: Tim Kaiser Signed-off-by: Marco Schluessler Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab commit 4a4edcca22bf46622f34db74a876a7eb91d95865 Author: Manu Abraham Date: Sun Jun 25 05:46:26 2006 -0300 V4L/DVB (4217): Fix a misplaced closing bracket/else, which caused swzigzag not to be called Thanks to Oliver Endriss for spotting this. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 7670d73266d37d18ded5b328db2804c9a7ab7921 Author: Michael Krufky Date: Sat Jun 24 21:05:12 2006 -0300 V4L/DVB (4215): Make VIDEO_CX88_BLACKBIRD a separate build option This patch creates a new Kconfig menu option, entitled, "Blackbird MPEG encoder support (cx2388x + cx23416)" so that the cx88-blackbird mpeg encoder module can be chosen separately. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 3446807d6e9ccf4b21476b0b143d35fcc964be4b Author: Michael Krufky Date: Sat Jun 24 20:47:21 2006 -0300 V4L/DVB (4214): Make VIDEO_CX2341X a selectable build option The cx2341x mpeg encoder module is used by cx88-blackbird, pvrusb2 and the external ivtv driver. This patch allows for cx2341x to be selected without having to also select cx88-blackbird. This will be needed to build the external ivtv driver or the standalone pvrusb2 driver against kernel 2.6.18 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit dff47bf21be002b3f0a6562d368474c41971b448 Author: Adrian Bunk Date: Sat Jun 24 19:25:43 2006 -0300 V4L/DVB (4213): Cx88: cleanups remove the following unused hooks: - cx88-blackbird.c: cx88_ioctl_hook() - cx88-blackbird.c: cx88_ioctl_translator() make the following needlessly global functions static: - cx88-tvaudio.c: cx88_detect_nicam() remove the following unused EXPORT_SYMBOL's: - cx88-cards.c: cx88_bcount - cx88-cards.c: cx88_subids - cx88-cards.c: cx88_idcount - cx88-cards.c: cx88_card_list - cx88-cards.c: cx88_card_setup - cx88-core.c: cx88_start_audio_dma - cx88-core.c: cx88_stop_audio_dma - cx88-i2c.c: cx88_i2c_init Signed-off-by: Adrian Bunk Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit d772bd03bc38794c84811be9d2537c225e08c9b8 Author: Manu Abraham Date: Sat Jun 24 11:18:58 2006 -0300 V4L/DVB (4211): Fix an Oops for all fe that have get_frontend_algo == NULL Thanks to Johannes Stezenbach for pointing it out Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit b9d0a25a484a90c1d60b974d115eff2fe580ce16 Author: Herbert Xu Date: Sat Jun 10 18:06:34 2006 +1000 [CRYPTO] tcrypt: Forbid tcrypt from being built-in It makes no sense to build tcrypt into the kernel. In fact, now that the driver init function's return status is being checked, it is in fact harmful to do so. Signed-off-by: Herbert Xu commit e90b1a2be6010acf01673b0625cfbf18240f7744 Author: Herbert Xu Date: Fri Jun 2 08:42:25 2006 +1000 [CRYPTO] aes: Add wrappers for assembly routines The wrapper routines are required when asmlinkage differs from the usual calling convention. So we need to have them. However, by rearranging the parameters, they will get optimised away to a single jump for most people. Signed-off-by: Herbert Xu commit e805792851bcb0bb42f0c8a352be64564c13e374 Author: Michal Ludvig Date: Tue May 30 22:04:19 2006 +1000 [CRYPTO] tcrypt: Speed benchmark support for digest algorithms This patch adds speed tests (benchmarks) for digest algorithms. Tests are run with different buffer sizes (16 bytes, ... 8 kBytes) and with each buffer multiple tests are run with different update() sizes (e.g. hash 64 bytes buffer in four 16 byte updates). There is no correctness checking of the result and all tests and algorithms use the same input buffer. Signed-off-by: Michal Ludvig Signed-off-by: Herbert Xu commit 14fdf477a7e3ff54f8e67fe506dd2677a36c56e4 Author: Michal Ludvig Date: Tue May 30 14:49:38 2006 +1000 [CRYPTO] tcrypt: Return -EAGAIN from module_init() Intentionaly return -EAGAIN from module_init() to ensure it doesn't stay loaded in the kernel. The module does all its work from init() and doesn't offer any runtime functionality => we don't need it in the memory, do we? Signed-off-by: Michal Ludvig Signed-off-by: Herbert Xu commit 996e2523cc347cc98237d2da3454aedc779fdcba Author: Herbert Xu Date: Sun May 21 11:57:20 2006 +1000 [CRYPTO] api: Allow replacement when registering new algorithms We already allow asynchronous removal of existing algorithm modules. By allowing the replacement of existing algorithms, we can replace algorithms without having to wait for for all existing users to complete. Signed-off-by: Herbert Xu commit d913ea0d6b6a48dd6eed8fc5e299b8b10e049186 Author: Herbert Xu Date: Sun May 21 08:45:26 2006 +1000 [CRYPTO] api: Removed const from cra_name/cra_driver_name We do need to change these names now and even more so in future with instantiated algorithms. So let's stop lying to the compiler and get rid of the const modifiers. Signed-off-by: Herbert Xu commit c7fc05992afcf1d63d6d5fb6142c8d39094dbca9 Author: Herbert Xu Date: Wed May 24 13:02:26 2006 +1000 [CRYPTO] api: Added cra_init/cra_exit This patch adds the hooks cra_init/cra_exit which are called during a tfm's construction and destruction respectively. This will be used by the instances to allocate child tfm's. For now this lets us get rid of the coa_init/coa_exit functions which are used for exactly that purpose (unlike the dia_init function which is called for each transaction). In fact the coa_exit path is currently buggy as it may get called twice when an error is encountered during initialisation. Signed-off-by: Herbert Xu commit 110bf1c0e932615cbe43a8af8a07bc3750ae4295 Author: Michal Ludvig Date: Mon May 22 08:28:06 2006 +1000 [CRYPTO] api: Fixed incorrect passing of context instead of tfm Fix a few omissions in passing TFM instead of CTX to algorithms. Signed-off-by: Michal Ludvig Signed-off-by: Herbert Xu commit 82062c72cd643c99a9e1c231270acbab986fd23f Author: Herbert Xu Date: Tue May 16 22:20:34 2006 +1000 [CRYPTO] padlock: Rearrange context structure to reduce code size i386 assembly has more compact instructions for accessing 7-bit offsets. So by moving the large members to the end of the structure we can save quite a bit of code size. This patch shaves about 10% or 300 bytes off the padlock-aes file. Signed-off-by: Herbert Xu commit 6c2bb98bc33ae33c7a33a133a4cd5a06395fece5 Author: Herbert Xu Date: Tue May 16 22:09:29 2006 +1000 [CRYPTO] all: Pass tfm instead of ctx to algorithms Up until now algorithms have been happy to get a context pointer since they know everything that's in the tfm already (e.g., alignment, block size). However, once we have parameterised algorithms, such information will be specific to each tfm. So the algorithm API needs to be changed to pass the tfm structure instead of the context pointer. This patch is basically a text substitution. The only tricky bit is the assembly routines that need to get the context pointer offset through asm-offsets.h. Signed-off-by: Herbert Xu commit 43600106e32809a4dead79fec67a63e9860e3d5d Author: Herbert Xu Date: Tue May 16 22:06:54 2006 +1000 [CRYPTO] digest: Remove unnecessary zeroing during init Various digest algorithms operate one block at a time and therefore keep a temporary buffer of partial blocks. This buffer does not need to be initialised since there is a counter which indicates what is and isn't valid in it. Signed-off-by: Herbert Xu commit 8b55ba0303bb59c34fab8e015634018780491614 Author: Herbert Xu Date: Sun May 14 11:00:39 2006 +1000 [CRYPTO] aes-i586: Get rid of useless function wrappers The wrappers aes_encrypt/aes_decrypt simply reverse the order of the function arguments. It's just as easy to get the actual assembly code to read them in the opposite order. Signed-off-by: Herbert Xu commit e1147d8f47eb8fef93f98a30858192145137d2b2 Author: Atsushi Nemoto Date: Mon Apr 10 08:42:35 2006 +1000 [CRYPTO] digest: Add alignment handling Some hash modules load/store data words directly. The digest layer should pass properly aligned buffer to update()/final() method. This patch also add cra_alignmask to some hash modules. Signed-off-by: Atsushi Nemoto Signed-off-by: Herbert Xu commit d00e708cef16442cabaf23f653baf924f5d66e83 Author: Atsushi Nemoto Date: Thu Apr 6 03:26:01 2006 +1000 [CRYPTO] khazad: Use 32-bit reads on key On 64-bit platform, reading 64-bit keys (which is supposed to be 32-bit aligned) at a time will result in unaligned access. Signed-off-by: Atsushi Nemoto Signed-off-by: Herbert Xu commit 8070b2b1ecbeb5437c92c33b4dcea1d8d80399ee Author: David S. Miller Date: Mon Jun 26 00:10:46 2006 -0700 [IOAT]: Do not dereference THIS_MODULE directly to set unsafe. Use the __unsafe() macro instead. Noticed by Miles Lane. Signed-off-by: David S. Miller commit 52383678a8ac80e6679f94f60c897f9292e0e8b9 Author: Ralf Baechle Date: Mon Jun 26 00:05:23 2006 -0700 [NETROM]: Fix possible null pointer dereference. If in nr_link_failed the neighbour list is non-empty but the node list is empty we'll end dereferencing a in a NULL pointer. This fixes coverity 362. Signed-off-by: Ralf Baechle Signed-off-by: David S. Miller commit 068c6e98bc7ec4419299b38cd40be26ebf4bdeda Author: Neil Horman Date: Mon Jun 26 00:04:27 2006 -0700 [NET] netpoll: break recursive loop in netpoll rx path The netpoll system currently has a rx to tx path via: netpoll_rx __netpoll_rx arp_reply netpoll_send_skb dev->hard_start_tx This rx->tx loop places network drivers at risk of inadvertently causing a deadlock or BUG halt by recursively trying to acquire a spinlock that is used in both their rx and tx paths (this problem was origionally reported to me in the 3c59x driver, which shares a spinlock between the boomerang_interrupt and boomerang_start_xmit routines). This patch breaks this loop, by queueing arp frames, so that they can be responded to after all receive operations have been completed. Tested by myself and the reported with successful results. Specifically it was tested with netdump. Heres the BZ with details: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=194055 Signed-off-by: Neil Horman Acked-by: Matt Mackall Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit 8834807b43200b1658b49d3b779e74a4f77e4ffb Author: Jeremy Fitzhardinge Date: Mon Jun 26 00:03:40 2006 -0700 [NET] netpoll: don't spin forever sending to stopped queues When transmitting a skb in netpoll_send_skb(), only retry a limited number of times if the device queue is stopped. Signed-off-by: Jeremy Fitzhardinge Acked-by: Matt Mackall Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit d83561a4d67863b4aa297e8f598823dd4dfe855e Author: Ben Collins Date: Mon Jun 26 00:02:47 2006 -0700 [IRDA]: add some IBM think pads [UBUNTU:nsc-ircc] Add some IBM think pads Add Thinkpad T60/X60/Z60/T43/R52 Infrared driver support. http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=7b8d2713435a9fb69719a282ba75e117f3f76a5b Signed-off-by: Ben Collins Signed-off-by: Andrew Morton commit 1e4fd51e2c830f2a10c9b143986757d8ea35b0fc Author: Andrew Morton Date: Mon Jun 26 00:01:58 2006 -0700 [ATM]: atm/mpc.c warning fix net/atm/mpc.c: In function 'MPOA_res_reply_rcvd': net/atm/mpc.c:1116: warning: unused variable 'ip' Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit f72b948dcbb8558d639214536c2ace1b0760f41d Author: Phil Oester Date: Mon Jun 26 00:00:57 2006 -0700 [NET]: skb_find_text ignores to argument skb_find_text takes a "to" argument which is supposed to limit how far into the skb it will search for the given text. At present, it seems to ignore that argument on the first skb, and instead return a match even if the text occurs beyond the limit. Patch below fixes this, after adjusting for the "from" starting point. This consequently fixes the netfilter string match's "--to" handling, which currently is broken. Signed-off-by: Phil Oester Signed-off-by: David S. Miller commit 6048126440dcb3ba01316f961465c0ff5a255dd1 Author: Adrian Bunk Date: Sun Jun 25 23:58:10 2006 -0700 [NET]: make net/core/dev.c:netdev_nit static netdev_nit can now become static. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller commit f54d9e8d7f7dd60f26157c12acda3fc94fcd9ab7 Author: Michael Chan Date: Sun Jun 25 23:57:04 2006 -0700 [NET]: Fix GSO problems in dev_hard_start_xmit() Fix 2 problems in dev_hard_start_xmit(): 1. nskb->next needs to link back to skb->next if hard_start_xmit() returns non-zero. 2. Since the total number of GSO fragments may exceed MAX_SKB_FRAGS + 1, it needs to stop transmitting if the netif_queue is stopped. Signed-off-by: Michael Chan Acked-by: Herbert Xu Signed-off-by: David S. Miller commit 0718bcc09b3597c51e87f265c72135a4928d3c0b Author: Herbert Xu Date: Sun Jun 25 23:55:46 2006 -0700 [NET]: Fix CHECKSUM_HW GSO problems. Fix checksum problems in the GSO code path for CHECKSUM_HW packets. The ipv4 TCP pseudo header checksum has to be adjusted for GSO segmented packets. The adjustment is needed because the length field in the pseudo-header changes. However, because we have the inequality oldlen > newlen, we know that delta = (u16)~oldlen + newlen is still a 16-bit quantity. This also means that htonl(delta) + th->check still fits in 32 bits. Therefore we don't have to use csum_add on this operations. This is based on a patch by Michael Chan . Signed-off-by: Herbert Xu Acked-by: Michael Chan Signed-off-by: David S. Miller commit 3ba07e65b288f00cc4d2420f1da46309b1cb5a0c Author: Allan Stephens Date: Sun Jun 25 23:53:47 2006 -0700 [TIPC]: Fix incorrect correction to discovery timer frequency computation. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 65f51ef0971f01d64027cb3bca2c5827fb5b19cb Author: Allan Stephens Date: Sun Jun 25 23:53:20 2006 -0700 [TIPC]: Get rid of dynamically allocated arrays in broadcast code. This change improves an earlier change which replaced the large local variable arrays used during broadcasting with dynamically allocated arrays. The temporary arrays are now incoprorated into the multicast link data structure. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 5392d646886d8f1ae01be69c10600b8df5284c41 Author: Allan Stephens Date: Sun Jun 25 23:52:50 2006 -0700 [TIPC]: Fixed link switchover bugs Incorporates several related fixes: - switchover now occurs when switching from an active link to a standby link - failure of a standby link no longer initiates switchover - links now display correct # of received packtes following reactivation Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit a10bd924a421e0e5d5bb9640735b9317b8e473b5 Author: Allan Stephens Date: Sun Jun 25 23:52:17 2006 -0700 [TIPC]: Enhanced & cleaned up system messages; fixed 2 obscure memory leaks. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit f131072c3da84e70a0f65d71b3a3f6611c6a22bc Author: Allan Stephens Date: Sun Jun 25 23:51:37 2006 -0700 [TIPC]: First phase of assert() cleanup This also contains enhancements to simplify comparisons in name table publication removal algorithm and to simplify name table sanity checking when shutting down TIPC. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit e100ae92a68c55e7ba287866c20fe1b0ad4fcdee Author: Allan Stephens Date: Sun Jun 25 23:51:08 2006 -0700 [TIPC]: Disallow config operations that aren't supported in certain modes. This change provides user-friendly feedback when TIPC is unable to perform certain configuration operations that don't work properly in certain modes. (In particular, any reconfiguration request that would temporarily take TIPC from network mode to standalone mode, or from standalone mode to not running mode, is disallowed.) Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit c33d53b23589d9133af85effefbaa619853eb7f0 Author: Allan Stephens Date: Sun Jun 25 23:50:30 2006 -0700 [TIPC]: Fixed memory leak in tipc_link_send() when destination is unreachable Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit a75bf874278d8318ffe11043f3acb9b281fa911a Author: Allan Stephens Date: Sun Jun 25 23:50:01 2006 -0700 [TIPC]: Added missing warning for out-of-memory condition Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit a7513528cd0deeb62624c229c21054472ec976e6 Author: Allan Stephens Date: Sun Jun 25 23:49:33 2006 -0700 [TIPC]: Withdrawing all names from nameless port now returns success, not error Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 51f9cc1ff8aa0866ff8fb3c06be4c64b5edbb2e8 Author: Allan Stephens Date: Sun Jun 25 23:49:06 2006 -0700 [TIPC]: Optimized argument validation done by connect(). Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit a3b0a5a9d004002a9cf9cf7a9d10cf1447a73d2b Author: Allan Stephens Date: Sun Jun 25 23:48:22 2006 -0700 [TIPC]: Simplify code for returning partial success of stream send request. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 4b087b28a629cc9388e42fdccdcd929deaa7ac81 Author: Allan Stephens Date: Sun Jun 25 23:47:44 2006 -0700 [TIPC]: recvmsg() now returns TIPC ancillary data using correct level (SOL_TIPC) Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 499786516fc12791223f075d682a45ea1129eb04 Author: Allan Stephens Date: Sun Jun 25 23:47:18 2006 -0700 [TIPC]: Improved performance of error checking during socket creation. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 1303e8f173a8a5000ee6e2fba876fec9474ed1f6 Author: Allan Stephens Date: Sun Jun 25 23:46:50 2006 -0700 [TIPC]: Stream socket send indicates partial success if data partially sent. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit bdd94789d2348e20d13c1d5e477c8cf830dd204b Author: Allan Stephens Date: Sun Jun 25 23:45:53 2006 -0700 [TIPC]: Connected send now checks socket state when retrying congested send. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 3546c7508d7e97fd855f8ac37afdd09622fa5ce1 Author: Allan Stephens Date: Sun Jun 25 23:45:24 2006 -0700 [TIPC]: Can now return destination name of form {0,x,y} via ancillary data. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 3388007bc4d662e50c2c01a7fb1fa2c31cea98ad Author: Allan Stephens Date: Sun Jun 25 23:44:57 2006 -0700 [TIPC]: Implied connect now saves dest name for retrieval as ancillary data. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 6b384de853c9f05e5e6da6c95edb475b96dd2cc1 Author: Allan Stephens Date: Sun Jun 25 23:44:27 2006 -0700 [TIPC]: Fixed connect() to detect a dest address that is missing or too short. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit e9024f0f79c3f847a793d6a16bf4fefc6d7a4649 Author: Allan Stephens Date: Sun Jun 25 23:43:57 2006 -0700 [TIPC]: Non-operation-affecting corrections to comments & function definitions. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 687a25f1cdfc6ee1f2f60f299dbd294908eb0d59 Author: Allan Stephens Date: Sun Jun 25 23:43:21 2006 -0700 [TIPC]: Validate entire interface name when locating bearer to enable. This fix prevents a bearer from being enabled using the wrong interface. For example, specifying "eth:eth14" might enable "eth:eth1" by mistake. Signed-off-by: Allan Stephens Signed-off-by: Per Liden commit a592ea6362a967a49eb4b5d1cd36b78d8f180622 Author: Allan Stephens Date: Sun Jun 25 23:42:47 2006 -0700 [TIPC]: Added support for MODULE_VERSION capability. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 8b1f0a92e98a67e1e69aa37d538f8956d1640cba Author: Allan Stephens Date: Sun Jun 25 23:42:19 2006 -0700 [TIPC]: Fix misleading comment in buf_discard() routine. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 70cb23477019b8739d23ead223539c7e6dfc509c Author: Allan Stephens Date: Sun Jun 25 23:41:47 2006 -0700 [TIPC]: Fixed privilege checking typo in dest_name_check(). This patch originated by Stephane Ouellette . Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 3ac90216abc7d39e694533aec2805efeb06bf8ac Author: Eric Sesterhenn Date: Sun Jun 25 23:41:15 2006 -0700 [TIPC] Fix for NULL pointer dereference This fixes a bug spotted by the coverity checker, bug id #366. If (mod(seqno - prev) != 1) we set buf to NULL, dereference it in the for case, and set it to whatever value happes to be at adress 0+next, if it happens to be non-zero, we even stay in the loop. It seems that the author intended to break there. Signed-off-by: Eric Sesterhenn Signed-off-by: Per Liden Signed-off-by: David S. Miller commit a4e0927902508a5f7f04be56d3c3e1b174481705 Author: Allan Stephens Date: Sun Jun 25 23:40:35 2006 -0700 [TIPC]: Allow compilation when CONFIG_TIPC_DEBUG is not set. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit d356eeba8e34786621d85468e5176052813a3059 Author: Allan Stephens Date: Sun Jun 25 23:40:01 2006 -0700 [TIPC]: Multicast link failure now resets all links to "nacking" node. This fix prevents node from crashing. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 260082471ed3f6d751e9767e5a278d4e495d83f7 Author: Allan Stephens Date: Sun Jun 25 23:39:31 2006 -0700 [TIPC]: Links now validate destination node specified by incoming messages. This fix prevents link flopping and name table inconsistency problems arising when a node is assigned a different value than it used previously. (Changing the value causes other nodes to have two link endpoints sending to the same MAC address using two different destination values, requiring the receiving node to filter out the unwanted messages.) Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 9688243b635ecede23fe4492ba23f36439398095 Author: Allan Stephens Date: Sun Jun 25 23:38:58 2006 -0700 [TIPC]: Allow ports to receive multicast messages through native API. This fix prevents a kernel panic if an application mistakenly sends a multicast message to TIPC's topology service or configuration service. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 49384507896ee26e67266cebef6b6a9f2e31081c Author: Allan Stephens Date: Sun Jun 25 23:38:29 2006 -0700 [TIPC]: Corrected potential misuse of tipc_media_addr structure. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 2535ec50b7a51833ff65dc97ca85e1155d4090f8 Author: Allan Stephens Date: Sun Jun 25 23:38:00 2006 -0700 [TIPC]: Use correct upper bound when validating network zone number. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 9ab230f82f404e534387dda6067072291441a34d Author: Allan Stephens Date: Sun Jun 25 23:37:24 2006 -0700 [TIPC]: Prevent name table corruption if no room for new publication Now exits cleanly if attempt to allocate larger array of subsequences fails, without losing track of pointer to existing array. Signed-off-by: Allan Stephens Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 5e3c8854c1898828ffb0141d4ac4e6190aa9eb4e Author: Jon Maloy Date: Sun Jun 25 23:36:43 2006 -0700 [TIPC] Improved tolerance to promiscuous mode interface Signed-off-by: Jon Maloy Signed-off-by: Per Liden Signed-off-by: David S. Miller commit 749805dc10e955b0170573061f9522a6a21cbae0 Author: David S. Miller Date: Sun Jun 25 23:24:24 2006 -0700 [SPARC]: Add iomap interfaces. Signed-off-by: David S. Miller commit 8e48aec714f1faf581949f23ae0e3d6e2317433b Author: David S. Miller Date: Sun Jun 25 23:19:30 2006 -0700 [OPENPROM]: Rewrite driver to use in-kernel device tree. Signed-off-by: David S. Miller commit 3d824a46b7210ea3b0a13ab0d0fbd7f6e2e91ddf Author: David S. Miller Date: Sun Jun 25 23:19:14 2006 -0700 [OPENPROMFS]: Rewrite using in-kernel device tree and seq_file. We lose property writing functionality for the time being, but that will be easy to add back. The code and framework is so much simpler now. Signed-off-by: David S. Miller commit 87b385da1f5a5f4a12a28e00fe597bcde8d6fea3 Author: David S. Miller Date: Sun Jun 25 23:18:57 2006 -0700 [SPARC]: Add unique device_node IDs and a ".node" property. Signed-off-by: David S. Miller commit fb7cd9d9acfb52dc1b9fbd5079445e4732667bbc Author: David S. Miller Date: Sun Jun 25 23:18:36 2006 -0700 [SPARC]: Add of_set_property() interface. Signed-off-by: David S. Miller commit dda9beb41414035de230e78cb53416f3e551295a Author: David S. Miller Date: Sun Jun 25 02:08:47 2006 -0700 [SPARC64]: Export auxio_register to modules. Signed-off-by: David S. Miller commit 36321426e320c2c6bc2f8a1587d6f4d695fca84c Author: David S. Miller Date: Sun Jun 25 02:07:52 2006 -0700 [SPARC64]: Add missing interfaces to dma-mapping.h Signed-off-by: David S. Miller commit 987c74fcb7a4479a04c44745098089785c16f5fe Author: David S. Miller Date: Sun Jun 25 01:34:43 2006 -0700 [SPARC64]: Export _PAGE_IE to modules. Signed-off-by: David S. Miller commit 350559961593a9680244b22b32733a49e21f25d6 Author: David S. Miller Date: Sun Jun 25 01:32:25 2006 -0700 [SPARC64]: Allow floppy driver to build modular. Signed-off-by: David S. Miller commit 698539187aee83ea6843e29875dde70b473f8bc1 Author: David S. Miller Date: Sun Jun 25 01:21:38 2006 -0700 [SPARC]: Export x_bus_type to modules. Signed-off-by: David S. Miller commit 95b0ce9d6d95819e65a7456261a0a5573b65ef1c Author: David S. Miller Date: Sun Jun 25 00:17:11 2006 -0700 [RIOWATCHDOG]: Fix the build. Signed-off-by: David S. Miller commit 1715f5ef0db94d12d9131d5afa9134e26f77529f Author: David S. Miller Date: Sun Jun 25 00:11:21 2006 -0700 [CPWATCHDOG]: Fix the build. Signed-off-by: David S. Miller commit 09ec431476aa6efca436faf1e1aaadb4fa283972 Author: David S. Miller Date: Sun Jun 25 00:04:43 2006 -0700 [PARPORT] sunbpp: Fix typo. Signed-off-by: David S. Miller commit 29f7ac7ecc853037cd7273f1fa35b1d996f8234a Author: David S. Miller Date: Sat Jun 24 23:27:00 2006 -0700 [MTD] sun_uflash: Port to new EBUS device layer. Signed-off-by: David S. Miller commit e2e8115b54aa6f159ac3dfec8d3d23b0af5fbfa0 Author: Jesper Juhl Date: Mon Jun 26 01:59:52 2006 -0400 Input: iforce - remove some pointless casts The 'private' member of struct input_dev is a void*, so no need to cast it when assigning it to a struct iforce* variable. Signed-off-by: Jesper Juhl Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov commit b0c9ad8e0ff154f8c4730b8c4383f49b846c97c4 Author: Pozsar Balazs Date: Mon Jun 26 01:56:08 2006 -0400 Input: psmouse - add support for Intellimouse 4.0 Add support for the H-Wheel present on Microsoft Intellimouse 4.0 (AKA "tilt mouse") Signed-off-by: Pozsar Balazs Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov commit 0ae051a19092d36112b5ba60ff8b5df7a5d5d23b Author: Dmitry Torokhov Date: Mon Jun 26 01:52:34 2006 -0400 Input: atkbd - fix HANGEUL/HANJA keys Make atkbd report HANGEUL/HANJA keys by default and use correct scan codes for these keys (they were swapped). Also make sure their scancodes reported as EV_MSC/MSC_SCAN events. Signed-off-by: Dmitry Torokhov commit b9ab58dd8e771d30df110c56e785db1ae5e073df Author: Jerome Pinot Date: Mon Jun 26 01:51:23 2006 -0400 Input: fix misspelling of Hangeul key Fix a mispelling of the korean alphabet name in the input subsystem. See http://en.wikipedia.org/wiki/Hangeul#Names for more details. KEY_HANGUEL left to not break people Signed-off-by: Jerome Pinot Signed-off-by: Dmitry Torokhov commit 9e8e30a0cc0ccb43773d14d8b8b84bcc585e9cc1 Author: Johannes Berg Date: Mon Jun 26 01:49:55 2006 -0400 Input: via-pmu - add input device support Add an input device for the button and lid switch so that userspace gets notified about the user pressing them via the standard input layer. Signed-off-by: Johannes Berg Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov commit ca56fe07f46e1c174b544e714be183f1476fecea Author: Dmitry Torokhov Date: Mon Jun 26 01:49:21 2006 -0400 Input: rearrange exports New style is to mark symbol as exported right after its definition. Signed-off-by: Dmitry Torokhov commit 1e0afb288e56d469ca1c583342bb9782d49333c6 Author: Dmitry Torokhov Date: Mon Jun 26 01:48:47 2006 -0400 Input: fix formatting to better follow CodingStyle Signed-off-by: Dmitry Torokhov commit f60d2b111cd55c335c2b70e50d66a612d2b10856 Author: Dmitry Torokhov Date: Mon Jun 26 01:48:36 2006 -0400 Input: reset name, phys and uniq when unregistering Name, phys and uniq are quite often constant strings in moules implementing particular input device. If a module unregisters input device and then gets unloaded, the device could still be present in memory (pinned via sysfs), but aforementioned members would point to some random memory. Set them all to NULL when unregistering so sysfs handlers won't try dereferencing them. Signed-off-by: Dmitry Torokhov commit 8a3cf456adbde8317a15fc038cfe82c630512f2e Author: Richard Purdie Date: Mon Jun 26 01:48:21 2006 -0400 Input: return correct size when reading modalias attribute Signed-off-by: Richard Purdie Signed-off-by: Dmitry Torokhov commit 62f7caf9273e3596aab1ec399b5c1e02cfb390da Author: Dmitry Torokhov Date: Mon Jun 26 01:47:56 2006 -0400 Input: change my e-mail address in MAINTAINERS file Signed-off-by: Dmitry Torokhov commit ea08c6faa0a8dc93b016663de55e49822ed0b33f Author: Dmitry Torokhov Date: Mon Jun 26 01:46:17 2006 -0400 Input: fix potential overflows in driver/input/keyboard Change all sprintfs into snprintfs to make sure we won't stomp on data adjacent to our buffers. Signed-off-by: Dmitry Torokhov commit a21466cc77b25dc2afd1292c79c7fc8fd454a1a7 Author: Dmitry Torokhov Date: Mon Jun 26 01:46:04 2006 -0400 Input: fix potential overflows in driver/input/touchscreen Change all sprintfs into snprintfs to make sure we won't stomp on data adjacent to our buffers. Signed-off-by: Dmitry Torokhov commit 10ca4c0a622a942e55dc8a6d57ebd441089c9e38 Author: Dmitry Torokhov Date: Mon Jun 26 01:45:48 2006 -0400 Input: fix potential overflows in driver/input/joystick Change all sprintfs into snprintfs to make sure we won't stomp on data adjacent to our buffers. Signed-off-by: Dmitry Torokhov commit 08ffce4560e0133e10634b0dd85eecee11257a1c Author: Dmitry Torokhov Date: Mon Jun 26 01:45:10 2006 -0400 Input: fix potential overflows in driver/input/mouse Change all sprintfs into snprintfs to make sure we won't stomp on data adjacent to our buffers. Noticed by Wouter Paesen Signed-off-by: Dmitry Torokhov commit fcc18e83e1f6fd9fa6b333735bf0fcd530655511 Author: Malcolm Parsons Date: Mon Jun 26 11:49:41 2006 +1000 [PATCH] uclinux: use PER_LINUX_32BIT in binfmt_flat binfmt_flat.c calls set_personality with PER_LINUX as the personality. On the arm architecture this results in the program running in 26bit usermode. PER_LINUX_32BIT should be used instead. This doesn't affect other architectures that use binfmt_flat. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 091487772c3312f3de599d99ca1d73395b54ed61 Author: Greg Ungerer Date: Mon Jun 26 11:47:35 2006 +1000 [PATCH] m68knommu: make enable_irq() macro statement Change enable_irq() macro to be a statement, not expression. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit afd1b836a0dfadeba43ec2167646ac7d428fb800 Author: Greg Ungerer Date: Mon Jun 26 11:43:35 2006 +1000 [PATCH] m68knommu: fix ColdFire 5249 PLL set Fix PLL setting for the Coldfire 5249 CPU. This brings it into line with the new style frequency configuration of m68knommu parts. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 1b1a9bd2777878c5ff0091e8742364c78341be71 Author: Greg Ungerer Date: Mon Jun 26 11:40:44 2006 +1000 [PATCH] m68knommu: ColdFire cache flush fixups Fix flush code for the ColdFire 5206/5206e/5272 cases. Add support for the new ColdFire 532x CPU family Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 623f523cc05c35a385c04fde2114925f5954192b Author: Philippe De Muyter Date: Mon Jun 26 11:37:57 2006 +1000 [PATCH] m68knommu: improve syscall entry and fix strace Here is a patch to the system call handling for 5307/5272/etc to: - fix the strace support (one tested the wrong bit) - make all system calls a little bit faster by inlining set_esp0 and supporting ENOSYS out of the critical path. - remove extraneous spaces Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 7bf9a37d8df1e7db82784117d28bb98da5f53f2f Author: Greg Ungerer Date: Mon Jun 26 11:01:32 2006 +1000 [PATCH] m68knommu: force stack alignment on ColdFire This patch solve a bug triggered by execvp (this function use calloc to store the argument list and gcc 3.4.x align the stack to word, not to dword). This situation aren't related to signal handling and all 2.6.x have the bug. On ColdFire targets we must force the stack to be aligned. Original patch from Andrea Tarani , Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 31f4fde38c5027ca05941db4a05c163d6314278e Author: Greg Ungerer Date: Mon Jun 26 10:58:09 2006 +1000 [PATCH] m68knommu: configurable frequency selection header Remove list of fixed clock frequency options used for configuring master clock, and make field an int. Much more flexible this way, no need to add more options for every new used freqency. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit e648cd2688547516f86709b1d00ad4f8b618d635 Author: Greg Ungerer Date: Mon Jun 26 10:55:36 2006 +1000 [PATCH] m68knommu: configurable frequency selection Remove list of fixed clock frequency options used for configuring master clock, and make field an int. Much more flexible this way, no need to add more options for every new used freqency. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 04860bd22f2892cb01b1d3232c656fa1e843090e Author: Greg Ungerer Date: Mon Jun 26 10:47:13 2006 +1000 [PATCH] m68knommu: configure support for Avnet5282 board Add support for the AVNET 5282 board. Patch submitted by Daniel Alomar . Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 5d36f8eb387eb38cd8224de721f6edb8697450af Author: Greg Ungerer Date: Mon Jun 26 10:45:45 2006 +1000 [PATCH] m68knommu: ColdFire 532x CPU configure support Add configure support for the new Freescale 532x family of CPUs. Patch submitted by Matt Waddel . Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 3448097fccdce4ea8f0fcad4f37f502a8cd72e68 Author: Linus Torvalds Date: Sun Jun 25 18:41:00 2006 -0700 Revert "swsusp special saveable pages support" commits This reverts commits 3e3318dee0878d42ed62a19c292a2ac284135db3 [PATCH] swsusp: x86_64 mark special saveable/unsaveable pages b6370d96e09944c6e3ae8d5743ca8a8ab1f79f6c [PATCH] swsusp: i386 mark special saveable/unsaveable pages ce4ab0012b32c1a4a1d6e934aeb73bf3151c48d9 [PATCH] swsusp: add architecture special saveable pages support because not only do they apparently cause page faults on x86, the infrastructure doesn't compile on powerpc. Signed-off-by: Linus Torvalds commit 5503967307f3fa443f5770a4df5ea4fbe9fb3917 Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: ColdFire 532x CPU platform build support Add build support for the new Freescale 532x CPU platforms. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit f3dd71209472b93340c1a940cc832c2712307b3e Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: add ColdFire 532x UART address support Add support for the UART addressing on the new Freescale M532x CPU family. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit f7399c3d96d852ae2105f51de766a50b9b021b18 Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: add ColdFire 532x timer build support Add build support for new Freescale M532x CPU family timer. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 7877d01e8ea205e047fa308e20e5e05c58952b1a Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: cleanup setup.c A cleanup of m68knommu/kernel/setup.c : - No need to initialize global pointers to NULL, they will have that value automatically, and they eat up space in my data segment image in FLASH. - Remove get_cpuinfo. It has been replaced by show_cpuinfo. Signed-off-by: Philippe De Muyter Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit bb28632c0d651f26dddf99afb7d7703e8e0ce293 Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: check DEBUG defined arch code Don't rely on DEBUG having a value, check for it being defined. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 6f57622a32e6bdc0a585c8be6f25bb8e75a3ff9e Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: include ColdFire 532x register definitions Include the ColdFire 532x support when including ColdFire peripharp support definitions. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit df8fbe1e7f250b157c5815a005a9650548315d1f Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: add ColdFire 532x cache init Add cache init support for the new ColdFire 532x CPU family. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 76aa698f331475147825ae135eae98bfd457825b Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: 532x UART support ColdFire serial driver support for the new 532x CPU family UARTs. Patch submitted by Matt Waddel . Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 7c99df64f0be6763bf5079560ccd96911c231b7b Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: ColdFire 532x register definitions Register definitions for the new Freescale 532x Coldfire CPU family. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 3196cf83ad410d9549e78f69aa45db75540334b7 Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: ColdFire 532x CPU startup code Add kernel startup code for the new Freescale 532x CPU family. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit b671b653da35cd38897c7b19e9baed64e7a9e1a1 Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: read/write register access for PIT timer Modify the m68knommu/ColdFire PIT timer code to use register offsets with raw_read/raw_write access, instead of a mapped struct. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 2082b477dc7e9d5b3f773a36aae2dbc55b4263c2 Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: remove use of rom_length Remove use of rom_length. It serves not real purpose, and when we move to new stye RAM configuration it will not be needed. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 36a248fadf96cd78c6b344442046db5b85cf9a70 Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: switch arch config name to CONFIG_M68K Switch to naming the architecture config options for the m68knommu branch as "M68K", dropping "M68KNOMMU". The CONFIG_MMU separates the 2 now, and the m68knommu branch is still strictly speaking an M68K (including the ColdFire parts). Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 0b7ac8e479f311f8ef15fbea3f849dded9f3ccd9 Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: read/write register access for ColdFire core timer Modify the m68knommu/ColdFire core timer code to use register offsets with raw_read/raw_write access, instead of a mapped struct. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit c88b36e2c828c78c51e90002351f9d9068b75dec Author: Greg Ungerer Date: Mon Jun 26 10:33:10 2006 +1000 [PATCH] m68knommu: 532x FEC eth struct map Specify the struct mapping used on the new Freescale 532x CPU family's FEC ethernet core. Patch submitted by Matt Waddel . Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds commit 73b6af8a21184f2178a7219eb4d64ea5a71aedf9 Author: Al Viro Date: Sun Jun 25 16:42:33 2006 -0700 [PATCH] spufs: update ->flush method proto Signed-off-by: Al Viro Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1e788f8d1ad71fea99a763114eae73c3ad55bc30 Author: Alexey Dobriyan Date: Sun Jun 25 16:42:33 2006 -0700 [PATCH] xfs: update ->flush method proto Signed-off-by: Alexey Dobriyan Cc: Nathan Scott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 689391210a4a8a1bf35119f87c51b3e01ef549e6 Author: Milan Svoboda Date: Sun Jun 25 22:12:12 2006 +0100 [ARM] 3612/1: make pci bus optional for ixp4xx platform Patch from Milan Svoboda IXP4XX platform can happily live without pci bus. This patch modifies Kconfig to support this option and modifies Makefile so pci only files are compiled only when pci is really selected. Patch is tested and ixdp465 runs fine with or without the pci bus.-- Signed-off-by: Milan Svoboda Signed-off-by: Deepak Saxena Signed-off-by: Russell King commit f36f44de721db44b4c2944133c3c5c2e06f633f0 Author: Linus Torvalds Date: Sun Jun 25 12:30:33 2006 -0700 Fix NFS2 compile error Trond had apparently merged the same patch twice, causing a duplicate include of the "internal.h" file, with resulting obvious confusion. Tssk. I'm the only one allowed to send out trees that don't even compile! Who does this Trond guy think he is? Signed-off-by: Linus Torvalds commit a5d157e0675ac11188a8d429a062b1938bb2d353 Author: Björn Steinbrink Date: Sun Jun 25 16:24:40 2006 +0200 [PATCH] i386: Fix softirq accounting with 4K stacks Copy the softirq bits in preempt_count from the current context into the hardirq context when using 4K stacks to make the softirq_count macro work correctly and thereby fix softirq cpu time accounting. Signed-off-by: Björn Steinbrink Acked-by: Arjan van de Ven Signed-off-by: Linus Torvalds commit 72cf2709bf8e0410800f118c4298bfbf8715b303 Author: Linus Torvalds Date: Sun Jun 25 10:04:15 2006 -0700 Fix PM_TRACE dependency: works only on 32-bit x86 for now Not that x86-64 and other architecture support should be difficult to add (trivial fixups to the data format and add the proper linker script entry). Signed-off-by: Linus Torvalds commit 1eec00565d849ceda67f425e089c3233e3ef2ca2 Author: Sonny Rao Date: Sun Jun 25 05:49:34 2006 -0700 [PATCH] fix race in idr code I ran into a bug where the kernel died in the idr code: cpu 0x1d: Vector: 300 (Data Access) at [c000000b7096f710] pc: c0000000001f8984: .idr_get_new_above_int+0x140/0x330 lr: c0000000001f89b4: .idr_get_new_above_int+0x170/0x330 sp: c000000b7096f990 msr: 800000000000b032 dar: 0 dsisr: 40010000 current = 0xc000000b70d43830 paca = 0xc000000000556900 pid = 2022, comm = hwup 1d:mon> t [c000000b7096f990] c0000000000d2ad8 .expand_files+0x2e8/0x364 (unreliable) [c000000b7096faa0] c0000000001f8bf8 .idr_get_new_above+0x18/0x68 [c000000b7096fb20] c00000000002a054 .init_new_context+0x5c/0xf0 [c000000b7096fbc0] c000000000049dc8 .copy_process+0x91c/0x1404 [c000000b7096fcd0] c00000000004a988 .do_fork+0xd8/0x224 [c000000b7096fdc0] c00000000000ebdc .sys_clone+0x5c/0x74 [c000000b7096fe30] c000000000008950 .ppc_clone+0x8/0xc commit a45219483e2894af3c07f959cbd4edb4575b4f8c Author: Jan Engelhardt Date: Sun Jun 25 05:49:33 2006 -0700 [PATCH] update-devices.txt Update Documentation/devices.txt with a new version from the LANANA site http://www.lanana.org/docs/device-list/devices-2.6+.txt Signed-off-by: Jan Engelhardt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f58a1ebb22f128fccfeafb2b18557c87741cd627 Author: Hua Zhong Date: Sun Jun 25 05:49:32 2006 -0700 [PATCH] remove unlikely(sb) in prune_dcache likely profiling shows that the following is a miss. After boot: [+- ] Type | # True | # False | Function:Filename@Line +unlikely | 1074| 0 prune_dcache()@:fs/dcache.c@409 After a bonnie++ run: +unlikely | 66716| 19584 prune_dcache()@:fs/dcache.c@409 So remove it. Signed-off-by: Hua Zhong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d84a84775bba661d5a3fd06757bbb419381937f3 Author: Alexey Dobriyan Date: Sun Jun 25 05:49:32 2006 -0700 [PATCH] Fix "biovec-(256)" in /proc/slabinfo Stringify does what it was told to do. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 00212fef814612245ed0261cbac8426d0c9a31a5 Author: Amul Shah Date: Sun Jun 25 05:49:31 2006 -0700 [PATCH] Fix kdump Crash Kernel boot memory reservation for NUMA machines This patch will fix a boot memory reservation bug that trashes memory on the ES7000 when loading the kdump crash kernel. The code in arch/x86_64/kernel/setup.c to reserve boot memory for the crash kernel uses the non-numa aware "reserve_bootmem" function instead of the NUMA aware "reserve_bootmem_generic". I checked to make sure that no other function was using "reserve_bootmem" and found none, except the ones that had NUMA ifdef'ed out. I have tested this patch only on an ES7000 with NUMA on and off (numa=off) in a single (non-NUMA) and multi-cell (NUMA) configurations. Signed-off-by: Amul Shah Looks-good-to: Vivek Goyal Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cc13ad6217018833e590a0e2ef5937aa16162d34 Author: Heiko Carstens Date: Sun Jun 25 05:49:30 2006 -0700 [PATCH] s390: setup.c cleanup + build fix Cleanup & fix 31 bit compilation: CC arch/s390/kernel/setup.o arch/s390/kernel/setup.c:83: error: initializer element is not computable at load time arch/s390/kernel/setup.c:83: error: (near initialization for 'code_resource.start') Not sure which patch in the -mm tree breaks this, but since this can be considered a cleanup it can be merged anyway. Cc: Martin Schwidefsky Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit bb12b76e2d795431fa9fd306eb274c69e5054dc7 Author: Domen Puncer Date: Sun Jun 25 05:49:29 2006 -0700 [PATCH] au1xxx: oss sound support for au1200 au1550 ac97 driver works fine on au1200 too. Comments at the top of file state this code is GPL, so lets mark it as GPL too. Signed-off-by: Domen Puncer Signed-off-by: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7d469722779c9fe0b415163e8fe837440f9c70dc Author: Randy Dunlap Date: Sun Jun 25 05:49:29 2006 -0700 [PATCH] parport: add to kernel-doc Add parport interfaces to kernel-doc template. Small doc. cleanups in 2 parport source files. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5e37ed37b1a70a65185736fbec543ca4ad64a673 Author: Domen Puncer Date: Sun Jun 25 05:49:27 2006 -0700 [PATCH] au1550_ac97: spin_unlock in error path Error paths didn't spin_unlock. Signed-off-by: Domen Puncer Signed-off-by: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7d93a1a53a72aa704a8fef6e0fb4f6c6cd6aa07a Author: Evgeniy Dushistov Date: Sun Jun 25 05:49:27 2006 -0700 [PATCH] ext2: cleanup: put_page and comment fix Things which force me think a little: why so? Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 77787bfb44da6e6166af088226707aeccee27968 Author: KaiGai Kohei Date: Sun Jun 25 05:49:26 2006 -0700 [PATCH] pacct: none-delayed process accounting accumulation In current 2.6.17 implementation, signal_struct refered from task_struct is used for per-process data structure. The pacct facility also uses it as a per-process data structure to store stime, utime, minflt, majflt. But those members are saved in __exit_signal(). It's too late. For example, if some threads exits at same time, pacct facility has a possibility to drop accountings for a part of those threads. (see, the following 'The results of original 2.6.17 kernel') I think accounting information should be completely collected into the per-process data structure before writing out an accounting record. This patch fixes this matter. Accumulation of stime, utime, minflt and majflt are done before generating accounting record. [mingo@elte.hu: fix acct_collect() siglock bug found by lockdep] Signed-off-by: KaiGai Kohei Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f6ec29a42d7ac3b309a9cef179b686d23986ab98 Author: KaiGai Kohei Date: Sun Jun 25 05:49:25 2006 -0700 [PATCH] pacct: avoidance to refer the last thread as a representation of the process When pacct facility generate an 'ac_flag' field in accounting record, it refers a task_struct of the thread which died last in the process. But any other task_structs are ignored. Therefore, pacct facility drops ASU flag even if root-privilege operations are used by any other threads except the last one. In addition, AFORK flag is always set when the thread of group-leader didn't die last, although this process has called execve() after fork(). We have a same matter in ac_exitcode. The recorded ac_exitcode is an exit code of the last thread in the process. There is a possibility this exitcode is not the group leader's one. commit 0e4648141af02331f21aabcd34940c70f09a2d04 Author: KaiGai Kohei Date: Sun Jun 25 05:49:24 2006 -0700 [PATCH] pacct: add pacct_struct to fix some pacct bugs. The pacct facility need an i/o operation when an accounting record is generated. There is a possibility to wake OOM killer up. If OOM killer is activated, it kills some processes to make them release process memory regions. But acct_process() is called in the killed processes context before calling exit_mm(), so those processes cannot release own memory. In the results, any processes stop in this point and it finally cause a system stall. commit 6bc392741d661eb84be503d1fdf14b6746615e4c Author: David Howells Date: Sun Jun 25 05:49:22 2006 -0700 [PATCH] Corrections to memory barrier doc Apply some small corrections to the memory barrier document, as contributed by: Christoph Lameter Kirill Smelkov Randy Dunlap Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6f84be84b4cde72fa2a2f0d10ac284a31e923200 Author: Paul Fulghum Date: Sun Jun 25 05:49:22 2006 -0700 [PATCH] synclink_gt: add GT2 adapter support Add support for SyncLink GT2 adapter to driver. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 294dad05311416718c2a172738e1ca4071449877 Author: Paul Fulghum Date: Sun Jun 25 05:49:21 2006 -0700 [PATCH] fix synclink_gt diagnostics error reporting Fix diagnostics error reporting that was being overwritten by incorrect use of return codes from individual diagnostic functions. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 04b374d0f5a97761b91a0c3ff6d10f80abd206b0 Author: Paul Fulghum Date: Sun Jun 25 05:49:21 2006 -0700 [PATCH] add synclink_gt crc return feature Add ability to return HDLC CRC to user application. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 643f3319b9132c768081ce94f938a29139a16de9 Author: Paul Fulghum Date: Sun Jun 25 05:49:20 2006 -0700 [PATCH] add synclink_gt custom hdlc idle Add custom HDLC idle pattern feature. It allows the user to specify an arbitrary 8 or 16 bit repeating pattern on the transmit data pin between HDLC frames. In most cases the idle pattern is continuous ones or flags as supported by off the shelf synchronous controllers and defined in the ISO3309 standard. Some applications (radio/satellite modems, connections to legacy military hardware) require non-standard patterns. Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ed6a209024c23dbb39bfaa7361eb0b9c3fcc2b93 Author: Andrew Morton Date: Sun Jun 25 05:49:19 2006 -0700 [PATCH] irda-usb printk fix drivers/net/irda/irda-usb.c: In function 'stir421x_patch_device': drivers/net/irda/irda-usb.c:1108: warning: format '%u' expects type 'unsigned int', but argument 4 has type 'size_t' Cc: Greg KH Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9e37bd301ee130598fa1406c1281caa159473bf8 Author: Randy Dunlap Date: Sun Jun 25 05:49:19 2006 -0700 [PATCH] kthread: move kernel-doc and put it into DocBook Move kthread API kernel-doc from kthread.h to kthread.c & fix it. Add kthread API to kernel-api DocBook. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b0ef371e3f9fa3b2571058be366a6780827ec0bf Author: Randy Dunlap Date: Sun Jun 25 05:49:18 2006 -0700 [PATCH] DMI: cleanup kernel-doc, add to DocBook Add DMI interface functions to a new Firmware Interfaces chapter in the kernel-api DocBook. Clean up kernel-doc in drivers/firmware/dmi_scan.c. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e905914f96e11862b130dd229f73045dad9a34e8 Author: Jeremy Fitzhardinge Date: Sun Jun 25 05:49:17 2006 -0700 [PATCH] Implement kasprintf Implement kasprintf, a kernel version of asprintf. This allocates the memory required for the formatted string, including the trailing '\0'. Returns NULL on allocation failure. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f796937a062c7aeb44cd0e75e1586c8543634a7d Author: Jeremy Fitzhardinge Date: Sun Jun 25 05:49:17 2006 -0700 [PATCH] Fix bounds check in vsnprintf, to allow for a 0 size and NULL buffer This change allows callers to use a 0-byte buffer and a NULL buffer pointer with vsnprintf, so it can be used to determine how large the resulting formatted string will be. Previously the code effectively treated a size of 0 as a size of 4G (on 32-bit systems), with other checks preventing it from actually trying to emit the string - but the terminal \0 would still be written, which would crash if the buffer is NULL. This change changes the boundary check so that 'end' points to the putative location of the terminal '\0', which is only written if size > 0. vsnprintf still allows the buffer size to be set very large, to allow unbounded buffer sizes (to implement sprintf, etc). [akpm@osdl.org: fix long-vs-longlong confusion] Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 891c668b90ded38cec36f0852c4983573597170d Author: Atsushi Nemoto Date: Sun Jun 25 05:49:15 2006 -0700 [PATCH] LED: add LED heartbeat trigger Add an LED trigger acts like a heart beat. This can be used as a replacement of CONFIG_HEARTBEAT code exists in some arch's timer code. Signed-off-by: Atsushi Nemoto Acked-by: Richard Purdie Cc: "Nish Aravamudan" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit fa9799e33d362aeca4555cd6318735bab1c04d16 Author: Randy Dunlap Date: Sun Jun 25 05:49:15 2006 -0700 [PATCH] ktime/hrtimer: fix kernel-doc comments Fix kernel-doc formatting in ktime.h and hrtimer.[ch] files. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9dc65576d67dc45e529062e41ca34066e02f03e5 Author: Randy Dunlap Date: Sun Jun 25 05:49:14 2006 -0700 [PATCH] reed-solomon: fix kernel-doc comments Fix kernel-doc formatting in Reed-Solomon code. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c51d3dac321df417d59a47574caa7ab61b30d447 Author: Randy Dunlap Date: Sun Jun 25 05:49:14 2006 -0700 [PATCH] kernel-doc: use Members for struct fields consistently kernel-doc struct fields should be consistently called "Members", not "Arguments", so switch man-mode output to use "Members" like all of the other formats do. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ecfb251a95dfca6ca0dba63414e9c91fcbb92335 Author: Randy Dunlap Date: Sun Jun 25 05:49:13 2006 -0700 [PATCH] kernel-doc: don't use XML escapes in text or man output mode For kernel-doc output modes of text and man, do not use XML escapes for less-than, greater-than, and ampersand characters. I.e., leave the text and man output clean and readable. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cc44a817f65f9b4651643d334f6351b6d1f5e6c2 Author: Paul Fulghum Date: Sun Jun 25 05:49:12 2006 -0700 [PATCH] fix memory leak in rocketport rp_do_receive Fix memory leak caused by incorrect use of tty buffer facility. tty buffers are allocated but never processed by call to tty_flip_buffer_push so they accumulate on the full buffer list. Current code uses the buffers as a temporary storage for data before passing it directly to the line discipline. Signed-off-by: Paul Fulghum Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 45c9b11a1d07770cabb48cb0f7960a77650ffc64 Author: Ulrich Drepper Date: Sun Jun 25 05:49:11 2006 -0700 [PATCH] Implement AT_SYMLINK_FOLLOW flag for linkat When the linkat() syscall was added the flag parameter was added in the last minute but it wasn't used so far. The following patch should change that. My tests show that this is all that's needed. If OLDNAME is a symlink setting the flag causes linkat to follow the symlink and create a hardlink with the target. This is actually the behavior POSIX demands for link() as well but Linux wisely does not do this. With this flag (which will most likely be in the next POSIX revision) the programmer can choose the behavior, defaulting to the safe variant. As a side effect it is now possible to implement a POSIX-compliant link(2) function for those who are interested. touch file ln -s file symlink linkat(fd, "symlink", fd, "newlink", 0) -> newlink is hardlink of symlink linkat(fd, "symlink", fd, "newlink", AT_SYMLINK_FOLLOW) -> newlink is hardlink of file The value of AT_SYMLINK_FOLLOW is determined by the definition we already use in glibc. Signed-off-by: Ulrich Drepper Acked-by: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 584e1236bbcdfec3f64c751908b8b4fe868c2d20 Author: Yoichi Yuasa Date: Sun Jun 25 05:49:11 2006 -0700 [PATCH] add "select GPIO_VR41XX" for TANBAC_TB0229 TANBAC_TB0229 requires GPIO_VR41XX. This patch adds "select GPIO_VR41XX" for TANBAC_TB0229. Signed-off-by: Yoichi Yuasa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit fc75cdfa5b43ac4d3232b490800cd35063adafd3 Author: Heiko Carstens Date: Sun Jun 25 05:49:10 2006 -0700 [PATCH] cpu hotplug: fix CPU_UP_CANCEL handling If a cpu hotplug callback fails on CPU_UP_PREPARE, all callbacks will be called with CPU_UP_CANCELED. A few of these callbacks assume that on CPU_UP_PREPARE a pointer to task has been stored in a percpu array. This assumption is not true if CPU_UP_PREPARE fails and the following calls to kthread_bind() in CPU_UP_CANCELED will cause an addressing exception because of passing a NULL pointer. Signed-off-by: Heiko Carstens Cc: Ashok Raj Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 04a3446c90137a473837288b04b517b19dc67a0d Author: Frode Isaksen Date: Sun Jun 25 05:49:09 2006 -0700 [PATCH] fs: sys_poll with timeout -1 bug fix If you do a poll() call with timeout -1, the wait will be a big number (depending on HZ) instead of infinite wait, since -1 is passed to the msecs_to_jiffies function. Signed-off-by: Frode Isaksen Acked-by: Nishanth Aravamudan Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8bdd1d1250d55afe403ac4affa6ccc5f9e60468f Author: Serge E. Hallyn Date: Sun Jun 25 05:49:08 2006 -0700 [PATCH] kthread: convert stop_machine into a kthread - Update stop_machine.c to spawn stop_machine as kthreads rather than the deprecated kernel_threads. - Update stop_machine to use the more efficient kthread_bind() before running task in place of set_cpus_allowed() after. [akpm@osdl.org: remove now-wrong set_cpus_allowed()] Signed-off-by: Serge E. Hallyn Cc: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2b943cf09d75c0dfbfd22548988df48f6c24c727 Author: Al Viro Date: Sun Jun 25 05:49:08 2006 -0700 [PATCH] fix %s in affs_fill_super() %s is only valid if array is known to contain NUL or precision is given and does not exceed the size of array. Signed-off-by: Al Viro Cc: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f82ccdb992d694f46b28f0478f62468260f45607 Author: Bjorn Helgaas Date: Sun Jun 25 05:49:07 2006 -0700 [PATCH] CCISS: tidy up product table indentation Make each one fit on a line so it's easier to read. I re-ordered COMPAQ_CISSC/0x4091, which was out of order. I double-checked these, but it would be good if you'd also check them to make sure I didn't miss any. Signed-off-by: Bjorn Helgaas Cc: Jeff Garzik Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7c8328355609be6d229e1a5e016a0115e9328b83 Author: Bjorn Helgaas Date: Sun Jun 25 05:49:06 2006 -0700 [PATCH] CCISS: run through Lindent cciss is full of inconsistent style ("for (" vs. "for(", lines that end with whitespace, lines beginning with a mix of spaces & tabs, etc). This patch changes only whitespace. Signed-off-by: Bjorn Helgaas Acked-by: Jeff Garzik Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e2019b58fac87b93c04d9efc08324a28fd23d601 Author: Bjorn Helgaas Date: Sun Jun 25 05:49:05 2006 -0700 [PATCH] CCISS: remove parens around return values Typical Linux style is "return -EINVAL", not "return(-EINVAL)". Signed-off-by: Bjorn Helgaas Acked-by: Jeff Garzik Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d14c4ab58c77c9a03b716c28f230ef944b08dc34 Author: Bjorn Helgaas Date: Sun Jun 25 05:49:04 2006 -0700 [PATCH] CCISS: fix a few spelling errors Fix a few spelling errors. Signed-off-by: Bjorn Helgaas Acked-by: Jeff Garzik Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5e8621e8bdc2460da516d5f1a5c71d3467ded5d2 Author: Bjorn Helgaas Date: Sun Jun 25 05:49:03 2006 -0700 [PATCH] CCISS: use ARRAY_SIZE without intermediates It's easier to verify loop bounds if the array name is mentioned the for() statement that steps through the array. Signed-off-by: Bjorn Helgaas Acked-by: Jeff Garzik Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 40aabb5815723551e7c92dd08ed3ea82ec000ccd Author: Bjorn Helgaas Date: Sun Jun 25 05:49:03 2006 -0700 [PATCH] CCISS: announce cciss%d devices with PCI address/IRQ/DAC info We already print "cciss: using DAC cycles" or similar for every adapter found: why not just identify the device we're talking about and include other useful information? Jeff Garzik : Although this patch is correct, I would consider using dev_printk() rather than referencing pci_name() in printk() arguments. Signed-off-by: Bjorn Helgaas Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4e570309e80f7c7a532fe0074e74df26ff8ef5d2 Author: Bjorn Helgaas Date: Sun Jun 25 05:49:02 2006 -0700 [PATCH] CCISS: request all PCI resources We should call pci_request_regions() to claim all resources the device decodes. Previously, we claimed only the I/O port range. Signed-off-by: Bjorn Helgaas Acked-by: Jeff Garzik Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c33ac89bc7d697e23ce09ddae73e0ece5f65ad48 Author: Bjorn Helgaas Date: Sun Jun 25 05:49:01 2006 -0700 [PATCH] CCISS: disable device when returning failure If something fails after we call pci_enable_device(), we should call pci_disable_device() before returning the failure. Signed-off-by: Bjorn Helgaas Acked-by: Jeff Garzik Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e7b69055820a221d7da29092fd553fd7cd6a97d1 Author: Rob Landley Date: Sun Jun 25 05:49:00 2006 -0700 [PATCH] Initramfs docs update New section on creating an external initramfs image using cpio (with script), a warning about bad advice in the cpio man page, a bit of debugging advice (hello world and rdinit=/bin/sh), and a few minor tweaks to other parts of it. Signed-off-by: Rob Landley Cc: "H. Peter Anvin" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit fa366ad5d7fe05abaae44a1cd216348669e42ef8 Author: Serge E. Hallyn Date: Sun Jun 25 05:49:00 2006 -0700 [PATCH] kthread: convert smbiod Update smbiod to use kthread instead of deprecated kernel_thread. [akpm@osdl.org: cleanup] Signed-off-by: Serge E. Hallyn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c7b2eff059fcc2d1b7085ee3d84b79fd657a537b Author: Serge E. Hallyn Date: Sun Jun 25 05:48:59 2006 -0700 [PATCH] kthread: update loop.c to use kthread Update loop.c to use a kthread instead of a deprecated kernel_thread for loop devices. [akpm@osdl.org: don't change the thread's name] Signed-off-by: Serge E. Hallyn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2f72100c01dd31d769097c58874e8ab1e70b2518 Author: Randy Dunlap Date: Sun Jun 25 05:48:59 2006 -0700 [PATCH] kernel-doc for lib/crc*.c Make kernel-doc corrections & additions to lib/crc*.c. Add crc functions to kernel-api.tmpl in DocBook. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 28e83baac20e3fe624af89a55eb06c2a7cab6828 Author: Randy Dunlap Date: Sun Jun 25 05:48:58 2006 -0700 [PATCH] kernel-doc for lib/cmdline.c Add a new chapter for kernel-lib functions to kernel-api.tmpl. Add lib/cmdline.c to the new kernel-lib chapter. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6e1907ffdc694023712b5e6516933a29e1be954f Author: Randy Dunlap Date: Sun Jun 25 05:48:57 2006 -0700 [PATCH] kernel-doc for lib/bitmap.c Make corrections/fixes to kernel-doc in lib/bitmap.c and include it in DocBook template. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 099a71d99578a53bdf5f383c55e4095f1c59410c Author: Eric Sesterhenn Date: Sun Jun 25 05:48:57 2006 -0700 [PATCH] Remove needless checks in fs/9p/vfs_inode.c coverity found two needless checks in vfs_inode.c (cid #1165 and #1164) In both cases inode is always NULL when we goto error; either because it is still initialized to NULL or is set to NULL explicitly. This patch simply removes these checks to save some code. Signed-off-by: Eric Sesterhenn Acked-by: Eric Van Hensbergen Cc: Ron Minnich Cc: Latchesar Ionkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 18cddac3d17781d9cbc109522d70ab021c846e2b Author: Randy Dunlap Date: Sun Jun 25 05:48:56 2006 -0700 [PATCH] ide-floppy: fix debug-only syntax error Fix debug-only printk syntax error. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 850622dfaf3d62907c96707773e0f8e84b3c0c06 Author: Randy Dunlap Date: Sun Jun 25 05:48:55 2006 -0700 [PATCH] kernel-doc: warn on malformed function docs. When the verbose (-v) option is used with scripts/kernel-doc, this option reports when the kernel-doc format is malformed and apparently contains function description lines before function parameters. In these cases, the kernel-doc script will print something like: Warning(filemap.c:335): contents before sections I have fixed the problems in mm/filemap.c and added lots of kernel-doc to that file (posted to the linux-mm mailing list Mon. 2006-June-12). The real goal (as requested by Andrew Morton) is to allow the short function description to be more than one line long. This patch is both a kernel-doc checker and a tool en route to that goal. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9c8ef5614da22666e339b125263d315cfaa89109 Author: Miklos Szeredi Date: Sun Jun 25 05:48:55 2006 -0700 [PATCH] fuse: scramble lock owner ID VFS uses current->files pointer as lock owner ID, and it wouldn't be prudent to expose this value to userspace. So scramble it with XTEA using a per connection random key, known only to the kernel. Only one direction needs to be implemented, since the ID is never sent in the reverse direction. The XTEA algorithm is implemented inline since it's simple enough to do so, and this adds less complexity than if the crypto API were used. Thanks to Jesper Juhl for the idea. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a4d27e75ffb7b8ecb7eed0c7db0df975525f3fd7 Author: Miklos Szeredi Date: Sun Jun 25 05:48:54 2006 -0700 [PATCH] fuse: add request interruption Add synchronous request interruption. This is needed for file locking operations which have to be interruptible. However filesystem may implement interruptibility of other operations (e.g. like NFS 'intr' mount option). Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f9a2842e5612b93fa20a624a8baa6c2a7ecea504 Author: Miklos Szeredi Date: Sun Jun 25 05:48:53 2006 -0700 [PATCH] fuse: rename the interrupted flag Rename the 'interrupted' flag to 'aborted', since it indicates exactly that, and next patch will introduce an 'interrupted' flag for a Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 33649c91a3df57c1090a657637d44b896de367e7 Author: Miklos Szeredi Date: Sun Jun 25 05:48:52 2006 -0700 [PATCH] fuse: ensure FLUSH reaches userspace All POSIX locks owned by the current task are removed on close(). If the FLUSH request resulting initiated by close() fails to reach userspace, there might be locks remaining, which cannot be removed. The only reason it could fail, is if allocating the request fails. In this case use the request reserved for RELEASE, or if that is currently used by another FLUSH, wait for it to become available. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7142125937e1482ad3ae4366594c6586153dfc86 Author: Miklos Szeredi Date: Sun Jun 25 05:48:52 2006 -0700 [PATCH] fuse: add POSIX file locking support This patch adds POSIX file locking support to the fuse interface. This implementation doesn't keep any locking state in kernel. Unlocking on close() is handled by the FLUSH message, which now contains the lock owner id. Mandatory locking is not supported. The filesystem may enfoce mandatory locking in userspace if needed. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit bafa96541b250a7051e3fbc5de6e8369daf8ffec Author: Miklos Szeredi Date: Sun Jun 25 05:48:51 2006 -0700 [PATCH] fuse: add control filesystem Add a control filesystem to fuse, replacing the attributes currently exported through sysfs. An empty directory '/sys/fs/fuse/connections' is still created in sysfs, and mounting the control filesystem here provides backward compatibility. Advantages of the control filesystem over the previous solution: - allows the object directory and the attributes to be owned by the filesystem owner, hence letting unpriviled users abort the filesystem connection - does not suffer from module unload race [akpm@osdl.org: fix this fs for recent dhowells depredations] [akpm@osdl.org: fix 64-bit printk warnings] Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 51eb01e73599efb88c6c20b1c226d20309a75450 Author: Miklos Szeredi Date: Sun Jun 25 05:48:50 2006 -0700 [PATCH] fuse: no backgrounding on interrupt Don't put requests into the background when a fatal interrupt occurs while the request is in userspace. This removes a major wart from the implementation. Backgrounding of requests was introduced to allow breaking of deadlocks. However now the same can be achieved by aborting the filesystem through the 'abort' sysfs attribute. This is a change in the interface, but should not cause problems, since these kinds of deadlocks never happen during normal operation. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3e8c54fad89144b8d63cc41619f363df1ec7cc42 Author: Jan Engelhardt Date: Sun Jun 25 05:48:49 2006 -0700 [PATCH] fuse: use MISC_MAJOR The following patches add POSIX file locking to the fuse interface. Additional changes ralated to this are: - asynchronous interrupt of requests by SIGKILL no longer supported - separate control filesystem, instead of using sysfs objects - add support for synchronously interrupting requests Details are documented in Documentation/filesystems/fuse.txt throughout the patches. This patch: Have fuse.h use MISC_MAJOR rather than a hardcoded '10'. Signed-off-by: Jan Engelhardt Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2b94895b9281976cf2a0f2f89bf41ee219742235 Author: David Howells Date: Sun Jun 25 05:48:49 2006 -0700 [PATCH] Another couple of alterations to the memory barrier doc Make another couple of alterations to the memory barrier document following suggestions by Alan Stern and in co-operation with Paul McKenney: (*) Rework the point of introduction of memory barriers and the description of what they are to reiterate why they're needed. (*) Modify a statement about the use of data dependency barriers to note that other barriers can be used instead (as they imply DD-barriers). Signed-off-by: David Howells Acked-By: Paul E. McKenney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 326f28e9ec4b2619c2fd410593fc95fcb0ba6b41 Author: Eric Sesterhenn Date: Sun Jun 25 05:48:48 2006 -0700 [PATCH] More !tty cleanups in drivers/char Another bunch of checks in the char drivers .put_char() and .write() routines, where tty can never be NULL. This patch removes these checks to save some code. Coverity choked at those with the following bug ids: isicom.c 767, 766 specialix.c 773, 774 synclink_cs.c 779, 781 synclink_gt.c 784, 785 synclinkmp.c 784, 785 Signed-off-by: Eric Sesterhenn Cc: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit fa791f5bdfa026a9abe1b48934943fd39f1e300b Author: Niels Kristian Bech Jensen Date: Sun Jun 25 05:48:47 2006 -0700 [PATCH] Update contact information in CREDITS Update my contact information in CREDITS. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f9022f66336b8ad680884d4810f1c421fff899e3 Author: Ian Kent Date: Sun Jun 25 05:48:47 2006 -0700 [PATCH] autofs4: need to invalidate children on tree mount expire I've found a case where invalid dentrys in a mount tree, waiting to be cleaned up by d_invalidate, prevent the expected expire. In this case dentrys created during a lookup for which a mount fails or has no entry in the mount map contribute to the d_count of the parent dentry. These dentrys may not be invalidated prior to comparing the interanl usage count of valid autofs dentrys against the dentry d_count which makes a mount tree appear busy so it doesn't expire. Signed-off-by: Ian Kent Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a2f20c7c274b6241767330c902b3111b9326d901 Author: Eric Sesterhenn Date: Sun Jun 25 05:48:46 2006 -0700 [PATCH] Clean up char/esp.c coverity choked at another two !tty checks, in places where tty can never be NULL. Since it removes some code we should remove these checks. (Coverity ids #763,#762) Signed-off-by Eric Sesterhenn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 969dd061d81d9e2bc7f954859452ac81cc639711 Author: Eric Sesterhenn Date: Sun Jun 25 05:48:45 2006 -0700 [PATCH] Cyclades Cleanup coverity choked at two !tty checks, in places where tty can never be NULL. Since it removes some code we should remove these checks. (Coverity ids #763,#762) [akpm@osdl.org: even cleaner!] Signed-off-by: Eric Sesterhenn Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2aa92581fb13e04e1440e5041b412cc06c782e0e Author: Anton Blanchard Date: Sun Jun 25 05:48:44 2006 -0700 [PATCH] Link error when futexes are disabled on 64bit architectures If futexes are disabled we fail to link on ppc64. Signed-off-by: Anton Blanchard Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 165d6c78ee24127dde5c750b2af0a239f9c11d1a Author: Paul E. McKenney Date: Sun Jun 25 05:48:44 2006 -0700 [PATCH] RCU documentation: self-limiting updates and call_rcu() An update to the RCU documentation calling out the self-limiting-update-rate advantages of synchronize_rcu(), and describing how to use call_rcu() in a way that results in self-limiting updates. Self-limiting updates are important to avoiding RCU-induced OOM in face of denial-of-service attacks. Signed-off-by: Paul E. McKenney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 76d42bd96984832c4ea8bc8cbd74e496ac31409e Author: Wu Fengguang Date: Sun Jun 25 05:48:43 2006 -0700 [PATCH] readahead: backoff on I/O error Backoff readahead size exponentially on I/O error. Michael Tokarev described the problem as: [QUOTE] Suppose there's a CD-rom with a scratch/etc, one sector is unreadable. In order to "fix" it, one have to read it and write to another CD-rom, or something.. or just ignore the error (if it's just a skip in a video stream). Let's assume the unreadable block is number U. But current behavior is just insane. An application requests block number N, which is before U. Kernel tries to read-ahead blocks N..U. Cdrom drive tries to read it, re-read it.. for some time. Finally, when all the N..U-1 blocks are read, kernel returns block number N (as requested) to an application, successefully. Now an app requests block number N+1, and kernel tries to read blocks N+1..U+1. Retrying again as in previous step. And so on, up to when an app requests block number U-1. And when, finally, it requests block U, it receives read error. So, kernel currentry tries to re-read the same failing block as many times as the current readahead value (256 (times?) by default). This whole process already killed my cdrom drive (I posted about it to LKML several months ago) - literally, the drive has fried, and does not work anymore. Ofcourse that problem was a bug in firmware (or whatever) of the drive *too*, but.. main problem with that is current readahead logic as described above. [/QUOTE] Which was confirmed by Jens Axboe : [QUOTE] For ide-cd, it tends do only end the first part of the request on a medium error. So you may see a lot of repeats :/ [/QUOTE] With this patch, retries are expected to be reduced from, say, 256, to 5. [akpm@osdl.org: cleanups] Signed-off-by: Wu Fengguang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 78dbe706e22f54bce61571ad837238382e1ba5f9 Author: David Woodhouse Date: Sun Jun 25 05:48:41 2006 -0700 [PATCH] R3964: fix GFP_KERNEL allocations in timer function In the error case, add_msg() gets called from timer functions, so should be using GFP_ATOMIC instead of GFP_KERNEL. Ref: http://bugzilla.kernel.org/show_bug.cgi?id=6659. Thanks to Christian Werner for reporting, and for the initial fix. Signed-off-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c836043e708d50bb301479d0db8e0dc77d4f52ca Author: Randy Dunlap Date: Sun Jun 25 05:48:40 2006 -0700 [PATCH] advansys section fixes Priority: not critical. Mark 3 functions __init. Saves a little memory. This makes these functions' calls to AdvWaitEEPCmd() (which is __init) be clean (i.e., eliminates text -> init -> text call chain). Fix multiple section mismatch warnings: WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet3550EEPConfig' (at offset 0x7a22) and 'AdvSet38C0800EEPConfig' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet3550EEPConfig' (at offset 0x7a4e) and 'AdvSet38C0800EEPConfig' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet3550EEPConfig' (at offset 0x7a79) and 'AdvSet38C0800EEPConfig' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet3550EEPConfig' (at offset 0x7aa2) and 'AdvSet38C0800EEPConfig' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet3550EEPConfig' (at offset 0x7abb) and 'AdvSet38C0800EEPConfig' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet38C0800EEPConfig' (at offset 0x7ae0) and 'AdvSet38C1600EEPConfig' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet38C0800EEPConfig' (at offset 0x7b0c) and 'AdvSet38C1600EEPConfig' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet38C0800EEPConfig' (at offset 0x7b37) and 'AdvSet38C1600EEPConfig' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet38C0800EEPConfig' (at offset 0x7b60) and 'AdvSet38C1600EEPConfig' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet38C0800EEPConfig' (at offset 0x7b79) and 'AdvSet38C1600EEPConfig' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet38C1600EEPConfig' (at offset 0x7b9e) and 'AdvExeScsiQueue' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet38C1600EEPConfig' (at offset 0x7bca) and 'AdvExeScsiQueue' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet38C1600EEPConfig' (at offset 0x7bf5) and 'AdvExeScsiQueue' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet38C1600EEPConfig' (at offset 0x7c1e) and 'AdvExeScsiQueue' WARNING: drivers/scsi/advansys.o - Section mismatch: reference to .init.text: from .text between 'AdvSet38C1600EEPConfig' (at offset 0x7c37) and 'AdvExeScsiQueue' Signed-off-by: Randy Dunlap Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 673e321cf9a12ecc2d6ce683fa9105f3443c1cbd Author: Randy Dunlap Date: Sun Jun 25 05:48:39 2006 -0700 [PATCH] char/ip2: more section fixes (replacement) Priority: tossup. In theory some of these (previously) __init functions could be called after init, but that problem has not been observed AFAIK. There were 2 cases of cleanup_module() (module_exit) calling __init functions (clear_requested_irq() & have_requested_irq()). These are more serious, but still not observed AFAIK. Fix sections mismatch: WARNING: drivers/char/ip2/ip2main.o - Section mismatch: reference to .init.text: from .text between 'cleanup_module' (at offset 0x228b) and 'ip2_loadmain' WARNING: drivers/char/ip2/ip2main.o - Section mismatch: reference to .init.text: from .text between 'cleanup_module' (at offset 0x22ae) and 'ip2_loadmain' WARNING: drivers/char/ip2/ip2main.o - Section mismatch: reference to .init.text: from .text between 'ip2_loadmain' (at offset 0x2501) and 'set_irq' WARNING: drivers/char/ip2/ip2main.o - Section mismatch: reference to .init.text: from .text between 'ip2_loadmain' (at offset 0x25de) and 'set_irq' WARNING: drivers/char/ip2/ip2main.o - Section mismatch: reference to .init.text: from .text between 'ip2_loadmain' (at offset 0x2698) and 'set_irq' WARNING: drivers/char/ip2/ip2main.o - Section mismatch: reference to .init.text: from .text between 'ip2_loadmain' (at offset 0x2922) and 'set_irq' WARNING: drivers/char/ip2/ip2main.o - Section mismatch: reference to .init.text: from .text between 'ip2_loadmain' (at offset 0x299e) and 'set_irq' Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cad2af5eb7470f9a0b85498f5ffac894e3cdcd27 Author: Randy Dunlap Date: Sun Jun 25 05:48:38 2006 -0700 [PATCH] cdrom/mcdx: section fixes Priority: not critical. Make __mcdx_init() __init and static. Saves a little memory. Fix section mismatch warning and make the function static while there: WARNING: drivers/cdrom/mcdx.o - Section mismatch: reference to .init.text: from .text between 'init_module' (at offset 0x8be) and 'mcdx_transfer' Signed-off-by: Randy Dunlap Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 474ab45a1f7de888df63da86b46785fe19d7fbe7 Author: Randy Dunlap Date: Sun Jun 25 05:48:38 2006 -0700 [PATCH] trident fb section fixes Priority: not critical. Change 3 functions from __init to __devinit. Could be an init/probe problem in theory, but not observed, so not high priority IMO. Fix section mismatch warnings: WARNING: drivers/video/tridentfb.o - Section mismatch: reference to .init.text: from .text between 'trident_pci_probe' (at offset 0x1aad) and 'trident_pci_remove' WARNING: drivers/video/tridentfb.o - Section mismatch: reference to .init.text: from .text between 'trident_pci_probe' (at offset 0x1b22) and 'trident_pci_remove' WARNING: drivers/video/tridentfb.o - Section mismatch: reference to .init.text: from .text between 'trident_pci_probe' (at offset 0x1b31) and 'trident_pci_remove' Signed-off-by: Randy Dunlap Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 96ebb92840b6bbb2e2fd8ad6b2b55d9cd76a06a0 Author: Randy Dunlap Date: Sun Jun 25 05:48:37 2006 -0700 [PATCH] wan/sdla section fixes netdev->set_config can be called at any time, so these references to __initdata would be a real problem. However, problem has not been observed AFAIK. Fix section mismatch warnings: WARNING: drivers/net/wan/sdla.o - Section mismatch: reference to .init.data: from .text between 'sdla_set_config' (at offset 0x1b8e) and 'sdla_stats' WARNING: drivers/net/wan/sdla.o - Section mismatch: reference to .init.data: from .text between 'sdla_set_config' (at offset 0x1e76) and 'sdla_stats' Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6e656be899993f450a765056cdc8d87e58906508 Author: Peter Staubach Date: Sun Jun 25 05:48:36 2006 -0700 [PATCH] ftruncate does not always update m/ctime In the course of trying to track down a bug where a file mtime was not being updated correctly, it was discovered that the m/ctime updates were not quite being handled correctly for ftruncate() calls. Quoth SUSv3: open(2): If O_TRUNC is set and the file did previously exist, upon successful completion, open() shall mark for update the st_ctime and st_mtime fields of the file. truncate(2): Upon successful completion, if the file size is changed, this function shall mark for update the st_ctime and st_mtime fields of the file, and the S_ISUID and S_ISGID bits of the file mode may be cleared. ftruncate(2): Upon successful completion, if fildes refers to a regular file, the ftruncate() function shall mark for update the st_ctime and st_mtime fields of the file and the S_ISUID and S_ISGID bits of the file mode may be cleared. If the ftruncate() function is unsuccessful, the file is unaffected. The open(O_TRUNC) and truncate cases were being handled correctly, but the ftruncate case was being handled like the truncate case. The semantics of truncate and ftruncate don't quite match, so ftruncate needs to be handled slightly differently. The attached patch addresses this issue for ftruncate(2). My thanx to Stephen Tweedie and Trond Myklebust for their help in understanding the situation and semantics. Signed-off-by: Peter Staubach Cc: "Stephen C. Tweedie" Cc: Trond Myklebust Cc: Al Viro Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 838cd153a5250a79a302f6c5d68a4794b70c4ccb Author: akpm@osdl.org Date: Sun Jun 25 05:48:35 2006 -0700 [PATCH] N32 sigset and __COMPAT_ENDIAN_SWAP__ I'm testing glibc on MIPS64, little-endian, N32, O32 and N64 multilibs. Among the NPTL test failures seen are some arising from sigsuspend problems for N32: it blocks the wrong signals, so SIGCANCEL (SIGRTMIN) is blocked despite glibc's carefully excluding it from sets of signals to block. Specifically, testing suggests it blocks signal N^32 instead of signal N, so (in the example tested) blocking SIGUSR1 (17) blocks signal 49 instead. glibc's sigset_t uses an array of unsigned long, as does the kernel. In both cases, signal N+1 is represented as (1UL << (N % (8 * sizeof (unsigned long)))) in word number (N / (8 * sizeof (unsigned long))). Thus the N32 glibc uses an array of 32-bit words and the N64 kernel uses an array of 64-bit words. For little-endian, the layout is the same, with signals 1-32 in the first 4 bytes, signals 33-64 in the second, etc.; for big-endian, userspace has that layout while in the kernel each 8 bytes have the two halves swapped from the userspace layout. The N32 sigsuspend syscall uses sigset_from_compat to convert the userspace sigset to kernel format. If __COMPAT_ENDIAN_SWAP__ is *not* set, this uses logic of the form set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 ) to convert the userspace sigset to a kernel one. This looks correct to me for both big and little endian, given that in userspace compat->sig[1] will represent signals 33-64, and so will the high 32 bits of set->sig[0] in the kernel. If however __COMPAT_ENDIAN_SWAP__ *is* set, as it is for __MIPSEL__, it uses set->sig[0] = compat->sig[1] | (((long)compat->sig[0]) << 32 ); which seems incorrect for both big and little endian, and would explain the observed symptoms. This code is the only use of __COMPAT_ENDIAN_SWAP__, so if incorrect then that macro serves no purpose, in which case something like the following patch would seem appropriate to remove it. Signed-off-by: Joseph Myers Signed-off-by: Ralf Baechle Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 92eeccd8badbfebe12383b6e5326b27dc707601d Author: Johann Lombardi Date: Sun Jun 25 05:48:33 2006 -0700 [PATCH] ext3: cleanup dead code in ext3_add_entry() The variables nlen and rlen are defined/initialized but not used in ext3_add_entry(). Signed-off-by: Johann Lombardi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0710d36a0fd5db3176369397f0fc49db32a63507 Author: Florin Malita Date: Sun Jun 25 05:48:31 2006 -0700 [PATCH] 9pfs: missing result check in v9fs_vfs_readlink() and v9fs_vfs_link() __getname() may fail and return NULL (as pointed out by Coverity 437 & 1220). Signed-off-by: Florin Malita Acked-by: Eric Van Hensbergen Cc: Cc: Latchesar Ionkov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit eab03ac7bd3e0da99eb9dc068772a85a5e3f3577 Author: Stephen Hemminger Date: Sun Jun 25 05:48:31 2006 -0700 [PATCH] Get rid of /proc/sys/proc The table is empty, why does it still exist? Signed-off-by: Stephen Hemminger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8ad2914d9cc55be651ef3bd676981a72c9001a47 Author: Randy Dunlap Date: Sun Jun 25 05:48:29 2006 -0700 [PATCH] checkstack: print module names Finding "init_module" high stack usage problems is challenging when there are over 1600 "init_module" functions in the kernel tree, so make checkstack.pl print out the filename where the stack usage occurs. This is useful for code built as loadable modules. For built-in code, it just prints the kernel image file name, like "vmlinux". Examples: (before patch:) 0x0000000d callback: 1928 0xffffffff81678c09 huft_build: 1560 0x0018 init_module: 1512 (after patch:) 0x0000000d callback [divacapi]: 1928 0xffffffff81678c09 huft_build [vmlinux]: 1560 0x0018 init_module [hdaps]: 1512 Also change one if-series to use elsif to cut down on unneeded tests. Signed-off-by: Randy Dunlap Acked-by: Joern Engel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5ec3e4b7aefbb8613b27ec4449fa8f9916ab9099 Author: Atsushi Nemoto Date: Sun Jun 25 05:48:29 2006 -0700 [PATCH] RTC: add rtc-ds1742 driver Add an RTC driver for the Dallas DS1742 RTC chip. [akpm@osdl.org: cleanups, compile fix] Signed-off-by: Atsushi Nemoto Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9bf5b4f5f53707aee5813f373279d03920ba6f65 Author: Atsushi Nemoto Date: Sun Jun 25 05:48:28 2006 -0700 [PATCH] RTC: add rtc-ds1553 driver Add an RTC driver for the Dallas DS1553 RTC chip. [akpm@osdl.org: cleanups, compile fix] Signed-off-by: Atsushi Nemoto Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e7a8bb12c24af8e3e4bdf18a7484699acc9dbedb Author: Andrew Morton Date: Sun Jun 25 05:48:27 2006 -0700 [PATCH] at91rm9200-rtc-driver-tidy - whitespace fixes (80-col display) - one unneeded cast of void* Cc: Andrew Victor Cc: Alessandro Zummo Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 788b1fc619a31ebdbadd3a8863631f59a4bd2944 Author: Andrew Victor Date: Sun Jun 25 05:48:27 2006 -0700 [PATCH] AT91RM9200 RTC driver Adds support for the RTC integrated in the Atmel AT91RM9200 SoC. Driver was originally written for 2.4 by Rick Bronson. Then converted to 2.6 ARM RTC API by Steven Scholz. Now converted to the RTC class model. Signed-off-by: Andrew Victor Signed-off-by: Alessandro Zummo Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8232212e0b4ee4eb3e407f5a9b098f6377820164 Author: Andrew Victor Date: Sun Jun 25 05:48:25 2006 -0700 [PATCH] RTC: Add rtc_year_days() to calculate tm_yday RTC: Add exported function rtc_year_days() to calculate the tm_yday value. Signed-off-by: Andrew Victor Signed-off-by: Alessandro Zummo Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 362600fe60fd18a25b4de8ec544b9e24e77e1484 Author: Raphael Assenat Date: Sun Jun 25 05:48:24 2006 -0700 [PATCH] Add v3020 RTC support This patch adds support for the v3020 RTC from EM Microelectronic. The v3020 RTC is designed to be connected on a bus using only one data bit. Since any data bit may be used, it is necessary to specify this to the driver by passing a struct v3020_platform_data pointer (see include/linux/rtc-v3020.h) to the driver. Part of the following code comes from the kernel patchs produced by Compulab for their products. The original file (available here: http://raph.people.8d.com/misc/emv3020.c) was released under the terms of the GPL license. [akpm@osdl.org: cleanups] Signed-off-by: Raphael Assenat Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9be05b57bd9152b7c26b1599b87aeb42a102f0cf Author: Jean Delvare Date: Sun Jun 25 05:48:23 2006 -0700 [PATCH] rtc: small documentation update Rtc driver documentation update * Mention the max-user-freq control file. * Add missing header in example code. Signed-off-by: Jean Delvare Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8e12ecc2b5a4521a338d7681e7d5547080fc6f71 Author: Raphael Assenat Date: Sun Jun 25 05:48:23 2006 -0700 [PATCH] Add max6902 RTC support Add support for the MAX6902 SPI RTC chip. Tested on a pxa2xx cpu. The compulab code comes from the kernel patch the produce for their cn-x255 board. (inside a zip file on the http://www.compulab.co.il/x255/html/x255-developer.htm) The original file (drivers/char/max6902.c) was GPL, which is of course an appropriate licence: /* * max6902.c * * Driver for MAX6902 RTC * * Copyright (C) 2004 Compulab Ltd. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * */ For reference, you can get the original file here: http://raph.people.8d.com/misc/max6902.c [akpm@osdl.org: cleanups] Signed-off-by: Raphael Assenat Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 110d693d5898649da606cd6e5f6af4d7f70a405f Author: Alessandro Zummo Date: Sun Jun 25 05:48:20 2006 -0700 [PATCH] rtc subsystem: add capability checks Centralize CAP_SYS_XXX checks to avoid duplicate code and missing checks in the drivers. Signed-off-by: Alessandro Zummo Cc: Richard Purdie Cc: Yoichi Yuasa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 56f10c634e145d75e45b56a73f59fb6dff1caa8e Author: Alessandro Zummo Date: Sun Jun 25 05:48:20 2006 -0700 [PATCH] rtc subsystem, fix capability checks in kernel interface Remove commented capability checks and add some others. Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9c0c570576d02000063e28faadcce8c07396755d Author: G. Liakhovetski Date: Sun Jun 25 05:48:18 2006 -0700 [PATCH] drivers/acorn/char/pcf8583.[hc] vs. RTC subsystem A port of the driver for the pcf8583 i2c rtc controller to the generic RTC framework by Alessandro Zummo. Based on drivers/acorn/char/{pcf8583.[hc],i2c.c}. Hopefully, acorn can be converted too to use this driver in the future. Signed-off-by: G. Liakhovetski Signed-off-by: Alessandro Zummo Cc: Russell King Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 655066c3835e7b51794c4d56f042eb78b5a79f53 Author: Atsushi Nemoto Date: Sun Jun 25 05:48:17 2006 -0700 [PATCH] RTC: rtc-dev UIE emulation Import genrtc's RTC UIE emulation (CONFIG_GEN_RTC_X) to rtc-dev driver with slight adjustments/refinements. This makes UIE-less rtc drivers work better with programs doing read/poll on /dev/rtc, such as hwclock. This emulation should not harm rtc drivers with UIE support, since rtc_dev_ioctl() calls underlaying rtc driver's ioctl() first. Signed-off-by: Atsushi Nemoto Acked-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1abb0dc92d706e8c73c7a62ca813738fe2259a7f Author: David Brownell Date: Sun Jun 25 05:48:17 2006 -0700 [PATCH] "RTC-framework" driver for DS1307 and similar RTC chips This is an "RTC-framework" driver for DS1307 and similar RTC chips, It should be a full replacement for the existing ds1337.c driver (using the older RTC glue), giving a net increase in the number of RTC chips that work out-of-the-box. There's a whole cluster of RTCs that are very similar, but the 1337 driver was a bit too picky to work with most of them. Still no support for RTC alarm IRQs (on chips that support them). Signed-off-by: David Brownell Signed-off-by: James Chapman Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3eecd1dc57971b2beff699b3704058866c25dedc Author: Jesper Juhl Date: Sun Jun 25 05:48:16 2006 -0700 [PATCH] Correct sa'K' description in sysrq.txt sysrq SAK is described as being something you should mistake for SAK from c2 compliant systems - whoops. What's meant is that it should *not* be mistaken as such. Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3b9c04106b70e46803c69d13d5da32f6129fa76d Author: Jan Engelhardt Date: Sun Jun 25 05:48:15 2006 -0700 [PATCH] printk time parameter Currently, enabling/disabling printk timestamps is only possible through reboot (bootparam) or recompile. I normally do not run with timestamps (since syslog handles that in a good manner), but for measuring small kernel delays (e.g. irq probing - see parport thread) I needed subsecond precision, but then again, just for some minutes rather than all kernel messages to come. The following patch adds a module_param() with which the timestamps can be en-/disabled in a live system through /sys/modules/printk/parameters/printk_time. Signed-off-by: Jan Engelhardt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e5dcd90b53d601a04482db9800336a0ccf190880 Author: Wu Fengguang Date: Sun Jun 25 05:48:14 2006 -0700 [PATCH] radixtree: normalize radix_tree_tag_get() return value In radix_tree_tag_get(), return normalized value of 0/1, as indicated by its comment. Signed-off-by: Wu Fengguang Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3419b23a919698f75944d3e0d97eb1d9c51e4bb6 Author: Davide Libenzi Date: Sun Jun 25 05:48:14 2006 -0700 [PATCH] epoll: use unlocked wqueue operations A few days ago Arjan signaled a lockdep red flag on epoll locks, and precisely between the epoll's device structure lock (->lock) and the wait queue head lock (->lock). Like I explained in another email, and directly to Arjan, this can't happen in reality because of the explicit check at eventpoll.c:592, that does not allow to drop an epoll fd inside the same epoll fd. Since lockdep is working on per-structure locks, it will never be able to know of policies enforced in other parts of the code. It was decided time ago of having the ability to drop epoll fds inside other epoll fds, that triggers a very trick wakeup operations (due to possibly reentrant callback-driven wakeups) handled by the ep_poll_safewake() function. While looking again at the code though, I noticed that all the operations done on the epoll's main structure wait queue head (->wq) are already protected by the epoll lock (->lock), so that locked-style functions can be used to manipulate the ->wq member. This makes both a lock-acquire save, and lockdep happy. Running totalmess on my dual opteron for a while did not reveal any problem so far: http://www.xmailserver.org/totalmess.c Signed-off-by: Davide Libenzi Cc: Arjan van de Ven Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4ad3bcf3146aa12f41262bb5dd1d9f1778e085b1 Author: Alexey Dobriyan Date: Sun Jun 25 05:48:13 2006 -0700 [PATCH] nbd: endian annotations Signed-off-by: Alexey Dobriyan Cc: Paul Clements Cc: Jens Axboe Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 21730eed11de42f22afcbd43f450a1872a0b5ea1 Author: Valerie Henson Date: Sun Jun 25 05:48:12 2006 -0700 [PATCH] Make EXT2_DEBUG work again This patch makes EXT2_DEBUG work again. Due to lack of proper include file, EXT2_DEBUG was undefined in bitmap.c and ext2_count_free() is left out. Moved to balloc.c and removed bitmap.c entirely. Second, debug versions of ext2_count_free_{inodes/blocks} reacquires superblock lock. Moved lock into callers. Signed-off-by: Val Henson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 42225a359aa8094242651191ad0ac9c338503d81 Author: Alexey Dobriyan Date: Sun Jun 25 05:48:11 2006 -0700 [PATCH] emu10k1: mark midi_spinlock as used Why is it marked unused when in fact it's used? Signed-off-by: Alexey Dobriyan Cc: Ingo Molnar Cc: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9de9adb615bddbdb786273c41ec3c03837e32fa5 Author: Andrew Morton Date: Sun Jun 25 05:48:10 2006 -0700 [PATCH] for_each_cpu_mask() warning fix On UP, this: cpumask_t mask = node_to_cpumask(numa_node_id()); for_each_cpu_mask(cpu, mask) does this: mm/readahead.c: In function `node_readahead_aging': mm/readahead.c:850: warning: unused variable `mask' which is unpleasantly fixed by this: Acked-by: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit eab98702afa567927c9b052499b43acad2f25a1c Author: H. Peter Anvin Date: Sun Jun 25 05:48:10 2006 -0700 [PATCH] Make sysctl obligatory except under CONFIG_EMBEDDED Make makes sysctl non-optional unless EMBEDDED is set. There are a number of interfaces exposed via sysctl, enough that it has to be considered core kernel functionality at this point. Signed-off-by: H. Peter Anvin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 74bb6a09b2e1e69d91eb6069eb4a7f0c06b84812 Author: Ingo Molnar Date: Sun Jun 25 05:48:09 2006 -0700 [PATCH] introduce WARN_ON_ONCE(cond) Add WARN_ON_ONCE(cond) to print once-per-bootup messages. [rostedt@goodmis.org: improve code generation] Signed-off-by: Ingo Molnar Signed-off-by: Arjan van de Ven Signed-off-by: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 69755652c92106855b4b096b7c2935b59e6252c6 Author: H. Peter Anvin Date: Sun Jun 25 05:48:08 2006 -0700 [PATCH] Make procfs obligatory except under CONFIG_EMBEDDED Make procfs non-optional unless EMBEDDED is set, just like sysfs. procfs is already de facto required for a large subset of Linux functionality. Signed-off-by: H. Peter Anvin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit bd40cddae2211950c81c41f25a818189f80fd0b5 Author: Randy Dunlap Date: Sun Jun 25 05:48:08 2006 -0700 [PATCH] kernel-doc: mm/readhead fixup Put short function description for read_cache_pages() on one line as needed by kernel-doc. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 43d23f9039fc810ecd621f1e4f9d578eadce058a Author: Mingming Cao Date: Sun Jun 25 05:48:07 2006 -0700 [PATCH] ext3_fsblk_t: the rest of in-kernel filesystem blocks conversion Convert the ext3 in-kernel filesystem blocks to ext3_fsblk_t. Convert the rest of all unsigned long type in-kernel filesystem blocks to ext3_fsblk_t, and replace the printk format string respondingly. Signed-off-by: Mingming Cao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1c2bf374a4b8c2e1a3e6ff3a64fb67272a8cd2e2 Author: Mingming Cao Date: Sun Jun 25 05:48:06 2006 -0700 [PATCH] ext3_fsblk_t: filesystem, group blocks and bug fixes Some of the in-kernel ext3 block variable type are treated as signed 4 bytes int type, thus limited ext3 filesystem to 8TB (4kblock size based). While trying to fix them, it seems quite confusing in the ext3 code where some blocks are filesystem-wide blocks, some are group relative offsets that need to be signed value (as -1 has special meaning). So it seem saner to define two types of physical blocks: one is filesystem wide blocks, another is group-relative blocks. The following patches clarify these two types of blocks in the ext3 code, and fix the type bugs which limit current 32 bit ext3 filesystem limit to 8TB. With this series of patches and the percpu counter data type changes in the mm tree, we are able to extend exts filesystem limit to 16TB. This work is also a pre-request for the recent >32 bit ext3 work, and makes the kernel to able to address 48 bit ext3 block a lot easier: Simply redefine ext3_fsblk_t from unsigned long to sector_t and redefine the format string for ext3 filesystem block corresponding. Two RFC with a series patches have been posted to ext2-devel list and have been reviewed and discussed: http://marc.theaimsgroup.com/?l=ext2-devel&m=114722190816690&w=2 http://marc.theaimsgroup.com/?l=ext2-devel&m=114784919525942&w=2 Patches are tested on both 32 bit machine and 64 bit machine, <8TB ext3 and >8TB ext3 filesystem(with the latest to be released e2fsprogs-1.39). Tests includes overnight fsx, tiobench, dbench and fsstress. This patch: Defines ext3_fsblk_t and ext3_grpblk_t, and the printk format string for filesystem wide blocks. This patch classifies all block group relative blocks, and ext3_fsblk_t blocks occurs in the same function where used to be confusing before. Also include kernel bug fixes for filesystem wide in-kernel block variables. There are some fileystem wide blocks are treated as int/unsigned int type in the kernel currently, especially in ext3 block allocation and reservation code. This patch fixed those bugs by converting those variables to ext3_fsblk_t(unsigned long) type. Signed-off-by: Mingming Cao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cedfb178ada245b6c52a654936b34d7996e26a1d Author: Randy Dunlap Date: Sun Jun 25 05:48:05 2006 -0700 [PATCH] megaraid_mbox: fix section mismatch warnings Fix section warning: WARNING: drivers/scsi/megaraid/megaraid_mbox.o - Section mismatch: reference to .init.text: from .text between 'megaraid_probe_one' (at offset 0x171e) and 'megaraid_queue_command' Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b9bcf9c117b0a39f7e59c9682a7b32a9253c0544 Author: Randy.Dunlap Date: Sun Jun 25 05:48:05 2006 -0700 [PATCH] wd7000: fix section mismatch warnings From: Randy Dunlap Fix section mismatch in wd7000 driver: WARNING: drivers/scsi/wd7000.o - Section mismatch: reference to .init.text: from .text after 'wd7000_detect' (at offset 0xa5d) WARNING: drivers/scsi/wd7000.o - Section mismatch: reference to .init.text: from .text after 'wd7000_detect' (at offset 0xab6) WARNING: drivers/scsi/wd7000.o - Section mismatch: reference to .init.text: from .text after 'wd7000_detect' (at offset 0xb67 Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ad4063b0b2ffd7c8359b62c830e88152fc39ab20 Author: Ben Dooks Date: Sun Jun 25 05:48:03 2006 -0700 [PATCH] AX88796 parallel port driver Driver for the simple parallel port interface on the Asix AX88796 chip on an platform_bus. [akpm@osdl.org: x86_64 build fix] Signed-off-by: Ben Dooks Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 11e64757f9fb32f13f51596bbf01988f42fca764 Author: Matt Helsley Date: Sun Jun 25 05:48:03 2006 -0700 [PATCH] Remove unecessary NULL check in kernel/acct.c copy_process() appears to be the only caller of acct_clear_integrals() and does not pass in NULL task pointers. Remove the unecessary check. Signed-off-by: Matt Helsley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7c12d81134b130ccd4c286b434ca48c4cda71a2f Author: NeilBrown Date: Sun Jun 25 05:48:02 2006 -0700 [PATCH] Make copy_from_user_inatomic NOT zero the tail on i386 As described in a previous patch and documented in mm/filemap.h, copy_from_user_inatomic* shouldn't zero out the tail of the buffer after an incomplete copy. This patch implements that change for i386. For the _nocache version, a new __copy_user_intel_nocache is defined similar to copy_user_zeroio_intel_nocache, and this is ultimately used for the copy. For the regular version, __copy_from_user_ll_nozero is defined which uses __copy_user and __copy_user_intel - the later needs casts to reposition the __user annotations. If copy_from_user_atomic is given a constant length of 1, 2, or 4, then we do still zero the destintion on failure. This didn't seem worth the effort of fixing as the places where it is used really don't care. Signed-off-by: Neil Brown Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Ralf Baechle Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 01408c4939479ec46c15aa7ef6e2406be50eeeca Author: NeilBrown Date: Sun Jun 25 05:47:58 2006 -0700 [PATCH] Prepare for __copy_from_user_inatomic to not zero missed bytes The problem is that when we write to a file, the copy from userspace to pagecache is first done with preemption disabled, so if the source address is not immediately available the copy fails *and* *zeros* *the* *destination*. This is a problem because a concurrent read (which admittedly is an odd thing to do) might see zeros rather that was there before the write, or what was there after, or some mixture of the two (any of these being a reasonable thing to see). If the copy did fail, it will immediately be retried with preemption re-enabled so any transient problem with accessing the source won't cause an error. The first copying does not need to zero any uncopied bytes, and doing so causes the problem. It uses copy_from_user_atomic rather than copy_from_user so the simple expedient is to change copy_from_user_atomic to *not* zero out bytes on failure. The first of these two patches prepares for the change by fixing two places which assume copy_from_user_atomic does zero the tail. The two usages are very similar pieces of code which copy from a userspace iovec into one or more page-cache pages. These are changed to remove the assumption. The second patch changes __copy_from_user_inatomic* to not zero the tail. Once these are accepted, I will look at similar patches of other architectures where this is important (ppc, mips and sparc being the ones I can find). This patch: There is a problem with __copy_from_user_inatomic zeroing the tail of the buffer in the case of an error. As it is called in atomic context, the error may be transient, so it results in zeros being written where maybe they shouldn't be. In the usage in filemap, this opens a window for a well timed read to see data (zeros) which is not consistent with any ordering of reads and writes. Most cases where __copy_from_user_inatomic is called, a failure results in __copy_from_user being called immediately. As long as the latter zeros the tail, the former doesn't need to. However in *copy_from_user_iovec implementations (in both filemap and ntfs/file), it is assumed that copy_from_user_inatomic will zero the tail. This patch removes that assumption, so that after this patch it will be safe for copy_from_user_inatomic to not zero the tail. This patch also adds some commentary to filemap.h and asm-i386/uaccess.h. After this patch, all architectures that might disable preempt when kmap_atomic is called need to have their __copy_from_user_inatomic* "fixed". This includes - powerpc - i386 - mips - sparc Signed-off-by: Neil Brown Cc: David Howells Cc: Anton Altaparmakov Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Ralf Baechle Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5f507d9e05b4dbfee34f3d967623ad3fbf0f28b3 Author: Andreas Mohr Date: Sun Jun 25 05:47:57 2006 -0700 [PATCH] constify libcrc32c table constify a medium-large CRC code table. Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3b364b8d584b94777f8446a943b3c65e75e758f8 Author: Andreas Mohr Date: Sun Jun 25 05:47:56 2006 -0700 [PATCH] constify parts of kernel/power/ Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 43b0bc00fdbf2f1503a57f0c2c1338438c5d2805 Author: Chris Wright Date: Sun Jun 25 05:47:55 2006 -0700 [PATCH] cpuset: remove extra cpuset_zone_allowed check in __alloc_pages This is redundant with check in wakeup_kswapd. Signed-off-by: Chris Wright Acked-by: Paul Jackson Acked-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit dc851a0fd2736e8dc3e90bd990cb911a0013da67 Author: David Wilder Date: Sun Jun 25 05:47:55 2006 -0700 [PATCH] Updated kdump documentation Cc: Vivek Goyal Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8ea2c2ecfcc1f31eaba8d1995b2e734ba821806a Author: Jesper Juhl Date: Sun Jun 25 05:47:54 2006 -0700 [PATCH] moxa: partial CodingStyle cleanup & spelling fixes Do a *partial* CodingStyle cleanup, correct some spelling in printk()'s && convert C++ comments to C comments - in moxa driver. Signed-off-by: Jesper Juhl Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8a7f7c9307962ffdf81561ec8742fde1fad9fe10 Author: Jesper Juhl Date: Sun Jun 25 05:47:53 2006 -0700 [PATCH] moxa: remove pointless check of 'tty' argument vs NULL Remove pointless check of 'tty' argument vs NULL from moxa driver. Signed-off-by: Jesper Juhl Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 56e139f62bd7b82430cfcf01fcbd42e1d84fb738 Author: Jesper Juhl Date: Sun Jun 25 05:47:52 2006 -0700 [PATCH] moxa: remove pointless casts Signed-off-by: Jesper Juhl Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d2e5b13c4a7c68fdbcf389c9fffc12cfa2c185af Author: Theodore Ts'o Date: Sun Jun 25 05:47:52 2006 -0700 [PATCH] ext3: remove inconsistent space before exclamation point in mount code This was reported as Debian bug #336604. Signed-off-by: "Theodore Ts'o" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e8f1c6227a0bc9b1e3a7e87cd31f650a909f647f Author: Theodore Ts'o Date: Sun Jun 25 05:47:51 2006 -0700 [PATCH] ext3: fix memory leak when the journal file is corrupted Signed-off-by: "Theodore Ts'o" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f16fdadba28add689b567cf03c21dd6dec8e43be Author: Theodore Ts'o Date: Sun Jun 25 05:47:50 2006 -0700 [PATCH] ext2: clean up dead code from mount code The variable i is guaranteed to be the same as db_count given the previous for loop. So get rid of it since it's dead code. Signed-off-by: "Theodore Ts'o" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit fcd5df35882b128ef3e160fab3074e6fe7ae501b Author: Mingming Cao Date: Sun Jun 25 05:47:50 2006 -0700 [PATCH] Avoid disk sector_t overflow for >2TB ext3 filesystem If ext3 filesystem is larger than 2TB, and sector_t is a u32 (i.e. CONFIG_LBD not defined in the kernel), the calculation of the disk sector will overflow. Add check at ext3_fill_super() and ext3_group_extend() to prevent mount/remount/resize >2TB ext3 filesystem if sector_t size is 4 bytes. Verified this patch on a 32 bit platform without CONFIG_LBD defined (sector_t is 32 bits long), mount refuse to mount a 10TB ext3. Signed-off-by: Mingming Cao Acked-by: Andreas Dilger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b61367732fc273977cc3fb85c272ce1a7bb1f533 Author: Andrew Morton Date: Sun Jun 25 05:47:49 2006 -0700 [PATCH] schedule_on_each_cpu(): reduce kmalloc() size schedule_on_each_cpu() presently does a large kmalloc - 96 kbytes on 1024 CPU 64-bit. Rework it so that we do one 8192-byte allocation and then a pile of tiny ones, via alloc_percpu(). This has a much higher chance of success (100% in the current VM). This also has the effect of reducing the memory requirements from NR_CPUS*n to num_possible_cpus()*n. Cc: Christoph Lameter Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 232acbcf5304c29f5bb03b0dddeaefd0f98ef45e Author: Randy Dunlap Date: Sun Jun 25 05:47:48 2006 -0700 [PATCH] kernel-doc: script cleanups Fix indentation. Quote a brace '{' so that vi won't be fooled by it. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 05189497d10c715bf41c05fb2fd89aa2cf7602f1 Author: Randy Dunlap Date: Sun Jun 25 05:47:47 2006 -0700 [PATCH] kernel-doc: drop leading space in sections Drop leading space of kernel-doc section contents. "Section" data (contents) are split from the section header (e.g., Note: below is a section header: * Note: list_empty on entry does not return true after this, the entry is * in an undefined state. ). Currently the data/contents begins with a space and is left that way, which causes it to look bad when printed (in text mode; see example below), so just remove the leading space. Note: list_empty on entry does not return true after this, the entry is in an undefined state. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5d18639a833e9f034b055dcbb16a980be627f475 Author: Chris Wedgwood Date: Sun Jun 25 05:47:46 2006 -0700 [PATCH] EDD isn't EXPERIMENTAL anymore Lots of people use this. Apparently RH has for over 18 months so lets drop EXPERIMENTAL. Signed-off-by: Chris Wedgwood Cc: Matt Domsch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d616e09ab33aa4d013a93c9b393efd5cebf78521 Author: Andrew Morton Date: Sun Jun 25 05:47:46 2006 -0700 [PATCH] pdflush: handle resume wakeups pdflush is carefully designed to ensure that all wakeups have some corresponding work to do - if a woken-up pdflush thread discovers that it hasn't been given any work to do then this is considered an error. That all broke when swsusp came along - because a timer-delivered wakeup to a frozen pdflush thread will just get lost. This causes the pdflush thread to get lost as well: the writeback timer is supposed to be re-armed by pdflush in process context, but pdflush doesn't execute the callout which does this. Fix that up by ignoring the return value from try_to_freeze(): jsut proceed, see if we have any work pending and only go back to sleep if that is not the case. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit bc64863814b14a4f75884746e68d3bf9f96b3559 Author: Andrew Morton Date: Sun Jun 25 05:47:45 2006 -0700 [PATCH] cpqarray section fix WARNING: drivers/block/cpqarray.o - Section mismatch: reference to .init.text: from .text between 'cpqarray_register_ctlr' (at offset 0xe98) and 'alloc_cpqarray_hba' WARNING: drivers/block/cpqarray.o - Section mismatch: reference to .init.text: from .text between 'cpqarray_register_ctlr' (at offset 0xe9c) and 'alloc_cpqarray_hba' Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit dbe217af3be08346f4b1abb885c2d9ec29c98fac Author: Alan Cox Date: Sun Jun 25 05:47:44 2006 -0700 [PATCH] IDE CD end-of media error fix This is a patch from Alan that fixes a real ide-cd.c regression causing bogus "Media Check" failures for perfectly valid Fedora install ISOs, on certain CD-ROM drives. This is a forward port to 2.6.16 (from RHEL) of the minimal changes for the end of media problem. It may not be sufficient for some controllers (promise notably) and it does not touch the locking so the error path locking is as horked as in mainstream. From: Ingo Molnar I have ported the patch to 2.6.17-rc4 and tested it by provoking end-of-media IO errors with an unaligned ISO image. Unlike the vanilla kernel, the patched kernel interpreted the error condition correctly with 512 byte granularity: hdc: command error: status=0x51 { DriveReady SeekComplete Error } hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 } ide: failed opcode was: unknown ATAPI device hdc: Error: Illegal request -- (Sense key=0x05) Illegal mode for this track or incompatible medium -- (asc=0x64, ascq=0x00) The failed "Read 10" packet command was: "28 00 00 04 fb 78 00 00 06 00 00 00 00 00 00 00 " end_request: I/O error, dev hdc, sector 1306080 Buffer I/O error on device hdc, logical block 163260 Buffer I/O error on device hdc, logical block 163261 Buffer I/O error on device hdc, logical block 163262 the unpatched kernel produces an incorrect error dump: hdc: command error: status=0x51 { DriveReady SeekComplete Error } hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 } ide: failed opcode was: unknown end_request: I/O error, dev hdc, sector 1306080 Buffer I/O error on device hdc, logical block 163260 hdc: command error: status=0x51 { DriveReady SeekComplete Error } hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 } ide: failed opcode was: unknown end_request: I/O error, dev hdc, sector 1306088 Buffer I/O error on device hdc, logical block 163261 hdc: command error: status=0x51 { DriveReady SeekComplete Error } hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 } ide: failed opcode was: unknown end_request: I/O error, dev hdc, sector 1306096 Buffer I/O error on device hdc, logical block 163262 I do not have the right type of CD-ROM drive to reproduce the end-of-media data corruption bug myself, but this same patch in RHEL solved it. Signed-off-by: Ingo Molnar Cc: Alan Cox Cc: Bartlomiej Zolnierkiewicz Cc: Jens Axboe Cc: Matt Mackall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8e3a67a99231f9f3f476bc3449e93c9a6a17f2e0 Author: Randy Dunlap Date: Sun Jun 25 05:47:43 2006 -0700 [PATCH] list.h doc: change "counter" to "cursor" Use loop "cursor" instead of loop "counter" for list iterator descriptions. They are not counters, they are pointers or positions. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit fe96e57d77481c8c1b6b0381d7e086870ac394fa Author: Randy Dunlap Date: Sun Jun 25 05:47:42 2006 -0700 [PATCH] fix list.h kernel-doc kernel-doc: Put all short function descriptions on one line or if they are too long, omit the short description & add a Description: section for them. Change some list iterator descriptions to use "current" point instead of "existing" point. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit dbf492d6c1a1bf5a8bda40274f479119f4c42ca4 Author: Pavel Machek Date: Sun Jun 25 05:47:42 2006 -0700 [PATCH] nbd: kill obsolete changelog, add GPL nbd abuses file header as a changelog (and obsolete one, too), and fails to mention GPL. This fixes it. Signed-off-by: Pavel Machek Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 83cc5ed3c4c65fc4c3729a5cec2111ede1ebf85e Author: Adrian Bunk Date: Sun Jun 25 05:47:41 2006 -0700 [PATCH] kernel/sys.c: cleanups - proper prototypes for the following functions: - ctrl_alt_del() (in include/linux/reboot.h) - getrusage() (in include/linux/resource.h) - make the following needlessly global functions static: - kernel_restart_prepare() - kernel_kexec() [akpm@osdl.org: compile fix] Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 76a8ad293912cd2f01eca075d80cd0ddec30c627 Author: Michael Ellerman Date: Sun Jun 25 05:47:40 2006 -0700 [PATCH] Make printk work for really early debugging Currently printk is no use for early debugging because it refuses to actually print anything to the console unless cpu_online(smp_processor_id()) is true. The stated explanation is that console drivers may require per-cpu resources, or otherwise barf, because the system is not yet setup correctly. Fair enough. However some console drivers might be quite happy running early during boot, in fact we have one, and so it'd be nice if printk understood that. So I added a flag (which I would have called CON_BOOT, but that's taken) called CON_ANYTIME, which indicates that a console is happy to be called anytime, even if the cpu is not yet online. Tested on a Power 5 machine, with both a CON_ANYTIME driver and a bogus console driver that BUG()s if called while offline. No problems AFAICT. Built for i386 UP & SMP. Signed-off-by: Michael Ellerman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8ae6e163c1b637e1cb125613726ffbd31ca44fdf Author: Deepak Saxena Date: Sun Jun 25 05:47:38 2006 -0700 [PATCH] Add driver for ARM AMBA PL031 RTC Add a driver for the ARM PL031 RTC found on some ARM SOCs. The driver is fairly trivial as the RTC only provides a read/write and alarm capability. [akpm@osdl.org: compile fix] Signed-off-by: Deepak Acked-by: Alessandro Zummo Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit dcd96379613a3cbe87c30e1c20122ecdcdf3a4b8 Author: Daniel Walker Date: Sun Jun 25 05:47:37 2006 -0700 [PATCH] idetape gcc 4.1 warning fix In both the read and write cases it will return an error if copy_{from/to}_user faults. However, I let the driver try to read/write as much as it can just as it normally would , then finally it returns an error if there was one. This was the most straight forward way to handle the error , since there isn't a clear way to clean up the buffers on error . I moved retval in idetape_chrdev_write() down into the actual code blocks since it's really once used there, and it conflicted with my ret variable. Fixes the following warning, drivers/ide/ide-tape.c: In function ‘idetape_copy_stage_from_user’: drivers/ide/ide-tape.c:2662: warning: ignoring return value of ‘copy_from_user’, declared with attribute warn_unused_result drivers/ide/ide-tape.c: In function ‘idetape_copy_stage_to_user’: drivers/ide/ide-tape.c:2689: warning: ignoring return value of ‘copy_to_user’, declared with attribute warn_unused_result Signed-off-by: Daniel Walker Cc: Alan Cox Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a04ee14636fa339c4609766bd6173629d4f9026e Author: Jan Engelhardt Date: Sun Jun 25 05:47:36 2006 -0700 [PATCH] openpromfs: factorize out "Move" "common code" out to PTR_NOD, which does the conversion from private pointer to node number. This is to reduce potential casting/conversion errors due to redundancy. (The naming PTR_NOD follows PTR_ERR, turning a pointer into xyz.) [akpm@osdl.org: cleanups] Signed-off-by: Jan Engelhardt Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 515decdccf81cfbf5273d7f0085aea954ecd26c4 Author: Jan Engelhardt Date: Sun Jun 25 05:47:35 2006 -0700 [PATCH] openpromfs: remove unnecessary casts Remove unnecessary casts in fs/openpromfs/inode.c Signed-off-by: Jan Engelhardt Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0928d68056fa25456830b1de9f0ee89bc37447cd Author: Jan Engelhardt Date: Sun Jun 25 05:47:35 2006 -0700 [PATCH] openpromfs: fix missing NUL tchars is not '\0'-terminated so the strtoul may run into problems. Fix that. Also make tchars as big as a long in hexadecimal form would take rather than just 16. Signed-off-by: Jan Engelhardt Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2e6113908fe76a06295cb243f1f2f0eea055b0c2 Author: Adrian Bunk Date: Sun Jun 25 05:47:34 2006 -0700 [PATCH] drivers/char/applicom.c: proper module_{init,exit} Convert the driver to use module_{init,exit}. Signed-off-by: Adrian Bunk Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 59cc185ada89245204c658ebcf64422968736672 Author: Markus Armbruster Date: Sun Jun 25 05:47:33 2006 -0700 [PATCH] oprofile: convert from semaphores to mutexes Signed-off-by: Markus Armbruster Cc: Philippe Elie Cc: John Levon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a2926b1449bcc3d348e2228114b04869dc2f3986 Author: Andrew Morton Date: Sun Jun 25 05:47:32 2006 -0700 [PATCH] msnd section fix WARNING: sound/oss/msnd.o - Section mismatch: reference to .init.text:msnd_register from __ksymtab between '__ksymtab_msnd_register' (at offset 0x0) and '__ksymtab_msnd_unregister' This symbol is exported. It'll oops if the driver is nonmodular and the caller is modular. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 138bb68ac9d49b0ea7eeecb3a245dc4e20f181da Author: Adrian Bunk Date: Sun Jun 25 05:47:32 2006 -0700 [PATCH] fs/ufs/inode.c: make 2 functions static Make two needlessly global functions static. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 098d5af7be694c66af44093f7217da3d22af1057 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:31 2006 -0700 [PATCH] ufs: ubh_ll_rw_block cleanup In ufs code there is function: ubh_ll_rw_block, it has parameter how many ufs_buffer_head it should handle, but it always called with "1" on the place of this parameter. This patch removes unused parameter of "ubh_ll_wr_block". Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ee3ffd6c126323693b3b32a71a1f1acfce30bd66 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:30 2006 -0700 [PATCH] ufs: make fsck -f happy ufs super block contains some statistic about file systems, like amount of directories, free blocks, inodes and so on. UFS1 hold this information in one location and uses 32bit integers for such information, UFS2 hold statistic in another location and uses 64bit integers. There is transition variant, if UFS1 has type 44BSD and flags field in super block has some special value this mean that we work with statistic like UFS2 does. and this also means that nobody care about old(UFS1) statistic. So if start fsck against such file system, after usage linux ufs driver, it found error: at now only UFS1 like statistic is updated. This patch should fix this. Also it contains some minor cleanup: CodingSytle and remove unused variables. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 577a82752f95a5680d7c14569ffd3fd630d9fb22 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:30 2006 -0700 [PATCH] ufs: fsync implementation Presently ufs doesn't support "fsync", this make some applications unhappy, for example vim. This patch fixes this situation. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 647b7e87b56f594daf648f44abfbeeb5eb6a9457 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:29 2006 -0700 [PATCH] ufs: one way to access super block Super block of UFS usually has size >512, because of fragment size may be 512, this cause some problems. Currently, there are two methods to work with ufs super block: 1) split structure which describes ufs super blocks into structures with size <=512 2) use one structure which describes ufs super block, and hope that array of "buffer_head" which holds "super block", has such construction: bh[n]->b_data + bh[n]->b_size == bh[n + 1]->b_data The second variant may cause some problems in the future, and usage of two variants cause unnecessary code duplication. This patch remove the second variant. Also patch contains some CodingStyle fixes. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f391475812ba39afa322c835217ffe936f5e754a Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:28 2006 -0700 [PATCH] ufs: missed brelse and wrong baseblk This patch fixes two bugs, which introduced by previous patches: 1) Missed "brelse" 2) Sometimes "baseblk" may be wrongly calculated, if i_size is equal to zero, which lead infinite cycle in "mpage_writepages". Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 96710b29e05f3b470bc4206366021b56e28d5208 Author: Andrew Morton Date: Sun Jun 25 05:47:28 2006 -0700 [PATCH] ufs: printk warning fixes fs/ufs/super.c: In function `ufs_print_super_stuff': fs/ufs/super.c:103: warning: unsigned int format, different type arg (arg 2) fs/ufs/super.c: In function `ufs2_print_super_stuff': fs/ufs/super.c:147: warning: unsigned int format, different type arg (arg 2) fs/ufs/super.c: In function `ufs_print_cylinder_stuff': fs/ufs/super.c:175: warning: unsigned int format, different type arg (arg 2) Cc: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 022a6dc5f461a30615bcd1687569abeee7ef8ba2 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:27 2006 -0700 [PATCH] ufs: zero metadata Presently if we allocate several "metadata" blocks (pointers to indirect blocks for example), we fill with zeroes only the first block. This cause some problems in "truncate" function. Also this patch remove some unused arguments from several functions and add comments. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2e006393ba5b599d9c43f94f8d8989e68131433e Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:26 2006 -0700 [PATCH] ufs: unlock_super without lock ufs_free_blocks function looks now in so way: if (err) goto failed; lock_super(); failed: unlock_super(); So if error happen we'll unlock not locked super. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 50aa4eb0b978f4a0283471c776ed812269ac8af5 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:26 2006 -0700 [PATCH] ufs: i_blocks wrong count At now UFS code uses DQUOT_* mechanism, but it also update inode->i_blocks manually, this cause wrong i_blocks value. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit dd187a2603d9904ddc410441348f0cfc558a5233 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:25 2006 -0700 [PATCH] ufs: little directory lookup optimization This patch make little optimization of ufs_find_entry like "ext2" does. Save number of page and reuse it again in the next call. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit abf5d15fd2e52517dd56a17a846d5a1f900b7db4 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:24 2006 -0700 [PATCH] ufs: easy debug Currently to turn on debug mode "user" has to edit ~10 files, to turn off he has to do it again. This patch introduce such changes: 1)turn on(off) debug messages via ".config" 2)remove unnecessary duplication of code 3)make "UFSD" macros more similar to function 4)fix some compiler warnings Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5afb3145c9a733166174e1f5a07c46410b5c4091 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:24 2006 -0700 [PATCH] ufs: Unmark CONFIG_UFS_FS_WRITE as BROKEN To find new bugs, I suggest revert this patch: http://lkml.org/lkml/2006/1/31/275 in -mm tree. So others can test "write support" of UFS. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3e41f597b1595479e4a1b2e6b17b3542120ef165 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:23 2006 -0700 [PATCH] ufs: not usual amounts of fragments per block The writing to UFS file system with block/fragment!=8 may cause bogus behaviour. The problem in "ufs_bitmap_search" function, which doesn't work correctly in "block/fragment!=8" case. The idea is stolen from BSD code. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9695ef16ed4e00b59303f39f9a4a422a2c6a3b89 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:22 2006 -0700 [PATCH] ufs: wrong type cast There are two ugly macros in ufs code: #define UCPI_UBH ((struct ufs_buffer_head *)ucpi) #define USPI_UBH ((struct ufs_buffer_head *)uspi) when uspi looks like struct { struct ufs_buffer_head ; } and USPI_UBH has some sence, ucpi looks like struct { struct not_ufs_buffer_head; } To prevent bugs in future, this patch convert macros to inline function and fix "ucpi" structure. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b71034e5e67d1577424cebe7bbb7d0ce134a4cd8 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:22 2006 -0700 [PATCH] ufs: directory and page cache: from blocks to pages Change function in fs/ufs/dir.c and fs/ufs/namei.c to work with pages instead of straight work with blocks. It fixed such bugs: * for i in `seq 1 1000`; do touch $i; done - crash system * mkdir create directory without "." and ".." entries Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 826843a347cc8fd596a4c73d3fbdf04a1f130b8a Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:21 2006 -0700 [PATCH] ufs: directory and page cache: install aops This series of patches finished "bugs fixing" mentioned here http://lkml.org/lkml/2006/1/31/275 . The main bugs: * for i in `seq 1 1000`; do touch $i; done - crash system * mkdir create directory without "." and ".." entries The suggested solution is work with page cache instead of straight work with blocks. Such solution has following advantages * reduce code size and its complexity * some global locks go away * fix bugs The most part of code is stolen from ext2, because of it has similar directory structure. Patches testes with UFS1 and UFS2 file systems. This patch installs i_mapping->a_ops for directory inodes and removes some duplicated code. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6ef4d6bf86a82965896eaa1a189177239ec2bbab Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:20 2006 -0700 [PATCH] ufs: change block number on the fly First of all some necessary notes about UFS by it self: To avoid waste of disk space the tail of file consists not from blocks (which is ordinary big enough, 16K usually), it consists from fragments(which is ordinary 2K). When file is growing its tail occupy 1 fragment, 2 fragments... At some stage decision to allocate whole block is made and all fragments are moved to one block. How this situation was handled before: ufs_prepare_write ->block_prepare_write ->ufs_getfrag_block ->... ->ufs_new_fragments: bh = sb_bread bh->b_blocknr = result + i; mark_buffer_dirty (bh); This is wrong solution, because: - it didn't take into consideration that there is another cache: "inode page cache" - because of sb_getblk uses not b_blocknr, (it uses page->index) to find certain block, this breaks sb_getblk. How this situation is handled now: we go though all "page inode cache", if there are no such page in cache we load it into cache, and change b_blocknr. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c9a27b5dca52bbd0955e065e49e56eb313d02c34 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:19 2006 -0700 [PATCH] ufs: right block allocation * After block allocation, we map it on the same "address" as 8 others blocks * We nullify block several times: once in ufs/block.c and once in block_*write_full_page, and use different "caches" for this. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2061df0f89201c0abeb4c17d343309c9fae5b861 Author: Evgeniy Dushistov Date: Sun Jun 25 05:47:18 2006 -0700 [PATCH] ufs: ufs_trunc_indirect: infinite cycle Currently, ufs write support have two sets of problems: work with files and work with directories. This series of patches should solve the first problem. This patch is similar to http://lkml.org/lkml/2006/1/17/61 this patch complements it. The situation the same: in ufs_trunc_(not direct), we read block, check if count of links to it is equal to one, if so we finish cycle, if not continue. Because of "count of links" always >=2 this operation cause infinite cycle and hang up the kernel. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a9adb8dbcd7a337620862106f8c17aeb5e7278c7 Author: Jesper Juhl Date: Sun Jun 25 05:47:17 2006 -0700 [PATCH] pnp: card_probe(): fix memory leak We can leak `clink' if drv->probe == 0. Signed-off-by: Jesper Juhl Cc: Adam Belay Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 552c03483e49a69312c9e7384fda9282c991880a Author: Cliff Wickman Date: Sun Jun 25 05:47:16 2006 -0700 [PATCH] fs/freevxfs: cleanup of spelling errors Fix of some spelling errors in fs/freevxfs error messages and comments Signed-off-by: Cliff Wickman Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit bbb1747d4e44ce49acc73daa8d66e5f6bd546f1b Author: Alan Stern Date: Sun Jun 25 05:47:15 2006 -0700 [PATCH] Allow raw_notifier callouts to unregister themselves Since raw_notifier chains don't benefit from any centralized locking protections, they shouldn't suffer from the associated limitations. Under some circumstances it might make sense for a raw_notifier callout routine to unregister itself from the notifier chain. This patch (as678) changes the notifier core to allow for such things. Signed-off-by: Alan Stern Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit bfe5d834195b3089b8846577311340376cc0f450 Author: Paul Mackerras Date: Sun Jun 25 05:47:14 2006 -0700 [PATCH] Define __raw_get_cpu_var and use it There are several instances of per_cpu(foo, raw_smp_processor_id()), which is semantically equivalent to __get_cpu_var(foo) but without the warning that smp_processor_id() can give if CONFIG_DEBUG_PREEMPT is enabled. For those architectures with optimized per-cpu implementations, namely ia64, powerpc, s390, sparc64 and x86_64, per_cpu() turns into more and slower code than __get_cpu_var(), so it would be preferable to use __get_cpu_var on those platforms. This defines a __raw_get_cpu_var(x) macro which turns into per_cpu(x, raw_smp_processor_id()) on architectures that use the generic per-cpu implementation, and turns into __get_cpu_var(x) on the architectures that have an optimized per-cpu implementation. Signed-off-by: Paul Mackerras Acked-by: David S. Miller Acked-by: Ingo Molnar Acked-by: Martin Schwidefsky Cc: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6ceab8a936c302c0cea2bfe55617c76e2f5746fa Author: Matt Mackall Date: Sun Jun 25 05:47:13 2006 -0700 [PATCH] random: remove redundant SA_SAMPLE_RANDOM from touchscreen drivers The core input layer is already calling add_input_randomness. Signed-off-by: Matt Mackall Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0f41a53a6699209216327cd4b506711610ad24c5 Author: Matt Mackall Date: Sun Jun 25 05:47:12 2006 -0700 [PATCH] random: change cpqarray to use add_disk_randomness Disk devices should use add_disk_randomness rather than SA_SAMPLE_RANDOM Signed-off-by: Matt Mackall Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8bd0b97e95d378df57938d4773ad674194278ac1 Author: Matt Mackall Date: Sun Jun 25 05:47:11 2006 -0700 [PATCH] random: make CCISS use add_disk_randomness Disk devices should use the add_disk_randomness API rather than SA_SAMPLE_RANDOM. Signed-off-by: Matt Mackall Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit afedfd016a78ea1b678886ab6236acbc7650fcfb Author: Matt Mackall Date: Sun Jun 25 05:47:11 2006 -0700 [PATCH] random: remove SA_SAMPLE_RANDOM from floppy driver The floppy driver is already calling add_disk_randomness as it should, so this was redundant. Signed-off-by: Matt Mackall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 51849738cf3af4d2c43a657e811a89e7f69eccc2 Author: Rob Landley Date: Sun Jun 25 05:47:10 2006 -0700 [PATCH] bloat-o-meter: gcc-4 fix Upgrade scripts/bloat-o-meter to handle the names gcc 4 gives static symbols. Signed-off-by: Rob Landley Signed-off-by: Matt Mackall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f867d2a2e5f3f0ce6356f452cc27b70d577de7c7 Author: Jesper Juhl Date: Sun Jun 25 05:47:09 2006 -0700 [PATCH] ensure NULL deref can't possibly happen in is_exported() If CONFIG_KALLSYMS is defined and if it should happen that is_exported() is given a NULL 'mod' and lookup_symbol(name, __start___ksymtab, __stop___ksymtab) returns 0, then we'll end up dereferencing a NULL pointer. Signed-off-by: Jesper Juhl Cc: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5474c120aafe78ca54bf272f7a01107c42da2b21 Author: Michael Hanselmann Date: Sun Jun 25 05:47:08 2006 -0700 [PATCH] Rewritten backlight infrastructure for portable Apple computers This patch contains a total rewrite of the backlight infrastructure for portable Apple computers. Backward compatibility is retained. A sysfs interface allows userland to control the brightness with more steps than before. Userland is allowed to upload a brightness curve for different monitors, similar to Mac OS X. [akpm@osdl.org: add needed exports] Signed-off-by: Michael Hanselmann Acked-by: Benjamin Herrenschmidt Cc: Richard Purdie Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 17660bdd5c1f1a165273c1a59cb5b87670a81cc4 Author: Adrian Bunk Date: Sun Jun 25 05:47:06 2006 -0700 [PATCH] uml: remove dead declaration Became irrelevant when x86_64 unexported ia32_sys_call_table. Signed-off-by: Adrian Bunk Cc: Andi Kleen Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 200a3d352cd5e0ae8fb96bfcf8103f7b7c60645b Author: Roman Zippel Date: Sun Jun 25 05:47:06 2006 -0700 [PATCH] m68k: convert VME irq code Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ebba61d5b05ecfda388dd4c156bafdb78d398055 Author: Roman Zippel Date: Sun Jun 25 05:47:05 2006 -0700 [PATCH] m68k: convert sun3 irq code Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 77dda339e512c729bb27abd452e6632465490986 Author: Roman Zippel Date: Sun Jun 25 05:47:05 2006 -0700 [PATCH] m68k: convert q40 irq code Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9c5f4afdfbe72d5d1c814ad7286a4524d00c7b96 Author: Roman Zippel Date: Sun Jun 25 05:47:04 2006 -0700 [PATCH] m68k: convert mac irq code Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 35353bb8b869f3a0a153d0674cdafbe4f64aaa05 Author: Roman Zippel Date: Sun Jun 25 05:47:03 2006 -0700 [PATCH] m68k: convert hp300 irq code Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 734085651c9b80aa3f9e6027b156102de214a0b2 Author: Roman Zippel Date: Sun Jun 25 05:47:03 2006 -0700 [PATCH] m68k: convert atari irq code Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0aa78106c661cf6c251fd56e92f0c76a7459d244 Author: Roman Zippel Date: Sun Jun 25 05:47:02 2006 -0700 [PATCH] m68k: convert apollo irq code Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 74be8d0835f91f0f77a2f1554dfa7242f1f7b652 Author: Roman Zippel Date: Sun Jun 25 05:47:01 2006 -0700 [PATCH] m68k: convert amiga irq code Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 68387c448b7f2b3e2bfa0f606391cd3b602b1997 Author: Roman Zippel Date: Sun Jun 25 05:47:01 2006 -0700 [PATCH] m68k: convert generic irq code to irq controller Convert the generic irq code to use irq controller, this gets rid of the machine specific callbacks and gives better control over irq handling without duplicating lots of code. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b5dc7840b3ebe9c7967dd8ba73db957767009ff9 Author: Roman Zippel Date: Sun Jun 25 05:47:00 2006 -0700 [PATCH] m68k: introduce irq controller Introduce irq controller and use it to manage auto vector interrupts. Introduce setup_irq() which can be used for irq setup. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1d174cfb0f2a8967433e157bae9c2d4dcdee5324 Author: Roman Zippel Date: Sun Jun 25 05:47:00 2006 -0700 [PATCH] m68k: cleanup amiga irq numbering Fix amiga irq numbering, so they are after the generic IRQ_AUTO defines and remove the IRQ_AMIGA_AUTO defines. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4facfde9f1d7b8a61fb0017460da45e23e60115c Author: Roman Zippel Date: Sun Jun 25 05:46:59 2006 -0700 [PATCH] m68k: cleanup generic irq names Rename IRQ1..IRQ7 to IRQ_AUTO_1..IRQ_AUTO_7 and remove the duplicate defintions. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 92445eaaadc1f03f5a177ecc957bda76bf2ba8d5 Author: Roman Zippel Date: Sun Jun 25 05:46:58 2006 -0700 [PATCH] m68k: separate handler for auto and user vector interrupt Use separate entry points for auto and user vector interrupts and cleanup naming a little. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f2325ecebc5b7988fd49968bd3a660fd1594dc84 Author: Roman Zippel Date: Sun Jun 25 05:46:58 2006 -0700 [PATCH] m68k: fix show_registers() Move some of the prints in die_if_kernel() to show_registers() and call that instead of show_stack(), so show_registers() prints now similiar info as other archs. Clean up the function a little. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 742636f5bfd92ad67f4a48f4b7a2ac655797e0f3 Author: Roman Zippel Date: Sun Jun 25 05:46:57 2006 -0700 [PATCH] m68k: dma API addition Additions to dma API with some small cleanups. Signed-off-by: Richard Hirst Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b035c96b2da7258bb2bba31812b5f9dda3499f00 Author: Roman Zippel Date: Sun Jun 25 05:46:56 2006 -0700 [PATCH] m68k: Add the generic dma API functions Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3921ee21e01ac5faecda640daa6071dc8f0e29c9 Author: Roman Zippel Date: Sun Jun 25 05:46:56 2006 -0700 [PATCH] m68k: small flush_icache() cleanup Make flush_icache() an inline function and clean it up a litte. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a7b1a1a3089aaf1168e3b68a40e98532063d7811 Author: Roman Zippel Date: Sun Jun 25 05:46:55 2006 -0700 [PATCH] m68k: fix __iounmap for 030 Ignore empty pmd entry during iomap (these are the holes between the mappings). Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6bf9f755c3f30c81df17fce7d2f8dda11b9516a4 Author: Roman Zippel Date: Sun Jun 25 05:46:54 2006 -0700 [PATCH] m68k: fix constraints of the signal functions and some cleanup Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 53617825ccf3ff8a71e6efcf3dcf58885ed6f3e5 Author: Roman Zippel Date: Sun Jun 25 05:46:53 2006 -0700 [PATCH] m68k: fix uaccess.h for gcc-3.x gcc-3.x has a few problems detecting a constant parameter. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit caad3c2a15dfa2e0da8cf51a57c052372123483c Author: Chuck Ebbert <76306.1226@compuserve.com> Date: Sun Jun 25 05:46:53 2006 -0700 [PATCH] i386: cpu_relax() in crash.c and doublefault.c Add cpu_relax() to infinite loops in crash.c and doublefault.c. This is the safest change. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 186989177e627c2571a3026d39ea1433e4ddc097 Author: Andreas Mohr Date: Sun Jun 25 05:46:52 2006 -0700 [PATCH] cpu_relax(): smpboot.c Add cpu_relax() to various smpboot.c init loops. cpu_relax() always implies a barrier (according to Arjan), so remove those as well. Signed-off-by: Andreas Mohr Cc: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e75eac33b5c7f797e4b2ddcb39183cf268e26822 Author: Jeremy Fitzhardinge Date: Sun Jun 25 05:46:50 2006 -0700 [PATCH] Clean up and refactor i386 sub-architecture setup Clean up and refactor i386 sub-architecture setup. This change moves all the code from the asm-i386/mach-*/setup_arch_pre/post.h headers, into arch/i386/mach-*/setup.c. mach-*/setup_arch_pre.h is renamed to setup_arch.h, and contains only things which should be in header files. It is purely code-motion; there should be no functional changes at all. Several functions in arch/i386/kernel/setup.c needed to be made non-static so that they're visible to the code in mach-*/setup.c. asm-i386/setup.h is used to hold the prototypes for these functions. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Chris Wright Cc: Zachary Amsden Cc: Chris Wright Cc: Christian Limpach Cc: Martin Bligh Cc: James Bottomley Cc: Andrey Panin Cc: Dave Hansen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e6a1530d692d6a60cdf15dfbcfea07f5324d7b9f Author: Christoph Lameter Date: Sun Jun 25 05:46:49 2006 -0700 [PATCH] Allow migration of mlocked pages Hugh clarified the role of VM_LOCKED. So we can now implement page migration for mlocked pages. Allow the migration of mlocked pages. This means that try_to_unmap must unmap mlocked pages in the migration case. Signed-off-by: Christoph Lameter Acked-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7b2259b3e53f128c10a9fded0965e69d4a949847 Author: Christoph Lameter Date: Sun Jun 25 05:46:48 2006 -0700 [PATCH] page migration: Support a vma migration function Hooks for calling vma specific migration functions With this patch a vma may define a vma->vm_ops->migrate function. That function may perform page migration on its own (some vmas may not contain page structs and therefore cannot be handled by regular page migration. Pages in a vma may require special preparatory treatment before migration is possible etc) . Only mmap_sem is held when the migration function is called. The migrate() function gets passed two sets of nodemasks describing the source and the target of the migration. The flags parameter either contains MPOL_MF_MOVE which means that only pages used exclusively by the specified mm should be moved or MPOL_MF_MOVE_ALL which means that pages shared with other processes should also be moved. The migration function returns 0 on success or an error condition. An error condition will prevent regular page migration from occurring. On its own this patch cannot be included since there are no users for this functionality. But it seems that the uncached allocator will need this functionality at some point. Signed-off-by: Christoph Lameter Cc: Hugh Dickins Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 68402ddc677005ed1b1359bbc1f279548cfc0928 Author: Christoph Lameter Date: Sun Jun 25 05:46:47 2006 -0700 [PATCH] mm: remove VM_LOCKED before remap_pfn_range and drop VM_SHM Remove VM_LOCKED before remap_pfn range from device drivers and get rid of VM_SHM. remap_pfn_range() already sets VM_IO. There is no need to set VM_SHM since it does nothing. VM_LOCKED is of no use since the remap_pfn_range does not place pages on the LRU. The pages are therefore never subject to swap anyways. Remove all the vm_flags settings before calling remap_pfn_range. After removing all the vm_flag settings no use of VM_SHM is left. Drop it. Signed-off-by: Christoph Lameter Acked-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9f1a3cfcffaed2fbb3206179295c79ca8289f5c3 Author: Zach Brown Date: Sun Jun 25 05:46:46 2006 -0700 [PATCH] AOP_TRUNCATED_PAGE victims in read_pages() belong in the LRU AOP_TRUNCATED_PAGE victims in read_pages() belong in the LRU Nick Piggin rightly pointed out that the introduction of AOP_TRUNCATED_PAGE to read_pages() was wrong to leave A_T_P victim pages in the page cache but not put them in the LRU. Failing to do so hid them from the VM. A_T_P just means that the aop method unlocked the page rather than performing IO. It would be very rare that the page was truncated between the unlock and testing A_T_P. So we leave the pages in the LRU for likely reuse soon rather than backing them back out of the page cache. We do this by matching the behaviour before the A_T_P introduction which added pages to the LRU regardless of what ->readpage() did. This doesn't include the unrelated cleanup in Nick's initial fix which changed read_pages() to return void to match its only caller's behaviour of ignoring errors. Signed-off-by: Nick Piggin Signed-off-by: Zach Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 09a9a45dc62fef5f46a0dc98a3cefdb464cc4aaa Author: Stefan Richter Date: Sun Jun 25 05:46:44 2006 -0700 [PATCH] ieee1394: nodemgr: do not peek into struct semaphore Also revert patch "frv: ieee1394 is borken on frv", as it no longer is. Signed-off-by: Stefan Richter Cc: David Howells Cc: Jody McIntyre Cc: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit fb1bb34d45400f12e0a33f8c487b3795674908a7 Author: Andrew Morton Date: Sun Jun 25 05:46:43 2006 -0700 [PATCH] remove for_each_cpu() Convert a few stragglers over to for_each_possible_cpu(), remove for_each_cpu(). Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1e48275adc8c94c3281e646c8beb829f8e6f5bfc Author: Andrew Morton Date: Sun Jun 25 05:46:42 2006 -0700 [PATCH] more for_each_cpu() removal It's going away. I wonder if this code really meant to iterate across not-present, not-online CPUs. Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 801194e3bcf7cde163b23c6279c559e69cb4ca57 Author: Russell King Date: Sun Jun 25 12:01:48 2006 +0100 [ARM] Remove MODE_(SVC|IRQ|FIQ|USR) and DEFAULT_FIQ DEFAULT_FIQ was entirely unused. MODE_* are just redefinitions of *_MODE. Use *_MODE instead. Signed-off-by: Russell King commit 9bf2aa129a107a0e9e2a5318d35aca731ae7e666 Author: Alexey Dobriyan Date: Sun Jun 25 02:41:28 2006 -0700 nfs: remove nfs_put_link() Signed-off-by: Alexey Dobriyan Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Trond Myklebust commit 6ab86aa13045e7f6742af0b3c3c45f952f9fbb8d Author: Andrew Morton Date: Sun Jun 25 02:41:27 2006 -0700 nfs-build-fix-99 fs/built-in.o:(__param+0x20): undefined reference to `nfs_idmap_cache_timeout' fs/built-in.o:(__param+0x48): undefined reference to `nfs_callback_set_tcpport' Cc: Alexey Dobriyan Cc: Andreas Gruenbacher Cc: Andy Adamson Cc: Chuck Lever Cc: David Howells Cc: J. Bruce Fields Cc: Manoj Naik Cc: Marc Eshel Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Trond Myklebust commit d75d54147db9db5194040bd1c5022df6ba36ee48 Author: Andrew Morton Date: Sun Jun 25 02:41:26 2006 -0700 git-nfs-build-fixes Fix various problems with nfs4 disabled. And various other things. In file included from fs/nfs/inode.c:50: fs/nfs/internal.h:24: error: static declaration of 'nfs_do_refmount' follows non-static declaration include/linux/nfs_fs.h:320: error: previous declaration of 'nfs_do_refmount' was here fs/nfs/internal.h:65: warning: 'struct nfs4_fs_locations' declared inside parameter list fs/nfs/internal.h:65: warning: its scope is only this definition or declaration, which is probably not what you want fs/nfs/internal.h: In function 'nfs4_path': fs/nfs/internal.h:97: error: 'struct nfs_server' has no member named 'mnt_path' fs/nfs/inode.c: In function 'init_once': fs/nfs/inode.c:1116: error: 'struct nfs_inode' has no member named 'open_states' fs/nfs/inode.c:1116: error: 'struct nfs_inode' has no member named 'delegation' fs/nfs/inode.c:1116: error: 'struct nfs_inode' has no member named 'delegation_state' fs/nfs/inode.c:1116: error: 'struct nfs_inode' has no member named 'rwsem' distcc[26452] ERROR: compile fs/nfs/inode.c on g5/64 failed make[1]: *** [fs/nfs/inode.o] Error 1 make: *** [fs/nfs/inode.o] Error 2 make: *** Waiting for unfinished jobs.... In file included from fs/nfs/nfs3xdr.c:26: fs/nfs/internal.h:24: error: static declaration of 'nfs_do_refmount' follows non-static declaration include/linux/nfs_fs.h:320: error: previous declaration of 'nfs_do_refmount' was here fs/nfs/internal.h:65: warning: 'struct nfs4_fs_locations' declared inside parameter list fs/nfs/internal.h:65: warning: its scope is only this definition or declaration, which is probably not what you want fs/nfs/internal.h: In function 'nfs4_path': fs/nfs/internal.h:97: error: 'struct nfs_server' has no member named 'mnt_path' distcc[26486] ERROR: compile fs/nfs/nfs3xdr.c on g5/64 failed make[1]: *** [fs/nfs/nfs3xdr.o] Error 1 make: *** [fs/nfs/nfs3xdr.o] Error 2 In file included from fs/nfs/nfs3proc.c:24: fs/nfs/internal.h:24: error: static declaration of 'nfs_do_refmount' follows non-static declaration include/linux/nfs_fs.h:320: error: previous declaration of 'nfs_do_refmount' was here fs/nfs/internal.h:65: warning: 'struct nfs4_fs_locations' declared inside parameter list fs/nfs/internal.h:65: warning: its scope is only this definition or declaration, which is probably not what you want fs/nfs/internal.h: In function 'nfs4_path': fs/nfs/internal.h:97: error: 'struct nfs_server' has no member named 'mnt_path' distcc[26469] ERROR: compile fs/nfs/nfs3proc.c on bix/32 failed make[1]: *** [fs/nfs/nfs3proc.o] Error 1 make: *** [fs/nfs/nfs3proc.o] Error 2 **FAILED** Cc: Alexey Dobriyan Cc: Andreas Gruenbacher Cc: Andy Adamson Cc: Chuck Lever Cc: David Howells Cc: J. Bruce Fields Cc: Manoj Naik Cc: Marc Eshel Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Trond Myklebust commit 405040a78b33e39edf4180fc993b9608f07d3c41 Author: Russell King Date: Sun Jun 25 11:37:09 2006 +0100 [ARM] Remove save_lr/restore_pc macros As for RETINSTR/LOADREGS macros, these were for compatibility with 26-bit ARMs. No longer required, so remove them. Signed-off-by: Russell King commit 800d8b5c4b322798414100c253524aaf1bb9cb86 Author: Russell King Date: Sun Jun 25 11:31:22 2006 +0100 [ARM] Remove partial non-v6 binutils compatibility proc-v6 contains some compatibility to be able to use the V6 "cps" instruction. However, the kernel makes use of this instruction elsewhere extensively, so there's no point keeping this compatibility anymore. Signed-off-by: Russell King commit ccf01ef7aa9c6c293a1c64c27331a2ce227916ec Author: Trond Myklebust Date: Sun Jun 25 06:27:31 2006 -0400 Merge branch 'odirect' commit 1b93a71755f2b15450b3e3045dab58a633e37b18 Author: Russell King Date: Sun Jun 25 11:23:45 2006 +0100 [ARM] Remove LOADREGS macro As for RETINSTR, LOADREGS is a left-over from the 26-bit days. Remove it. Signed-off-by: Russell King commit 7999d8d7a611bee902446939952859caf1367c25 Author: Russell King Date: Sun Jun 25 11:17:23 2006 +0100 [ARM] Remove RETINSTR macro RETINSTR is a left-over from the days when we had 26-bit and 32-bit CPU support integrated into the same tree. Since this is no longer the case, we can now remove RETINSTR. Signed-off-by: Russell King commit 7477ddaa4d2d69bbcd49e12990af158dbb03f2f2 Author: Andrew Morton Date: Wed Jun 21 01:29:38 2006 -0300 V4L/DVB (4210b): git-dvb: tea575x-tuner build fix In file included from sound/i2c/other/tea575x-tuner.c:30: include/sound/tea575x-tuner.h:36: error: field 'vd' has incomplete type include/sound/tea575x-tuner.h:37: error: field 'fops' has incomplete type sound/i2c/other/tea575x-tuner.c:89: warning: 'struct inode' declared inside parameter list sound/i2c/other/tea575x-tuner.c:89: warning: its scope is only this definition or declaration, which is probably not what you want sound/i2c/other/tea575x-tuner.c: In function 'snd_tea575x_ioctl': sound/i2c/other/tea575x-tuner.c:91: warning: implicit declaration of function 'video_devdata' sound/i2c/other/tea575x-tuner.c:91: warning: initialization makes pointer from integer without a cast sound/i2c/other/tea575x-tuner.c:92: warning: implicit declaration of function 'video_get_drvdata' sound/i2c/other/tea575x-tuner.c:92: warning: initialization makes pointer from integer without a cast sound/i2c/other/tea575x-tuner.c:96: warning: implicit declaration of function '_IOR' sound/i2c/other/tea575x-tuner.c:96: error: syntax error before 'struct' sound/i2c/other/tea575x-tuner.c:99: error: 'v' undeclared (first use in this function) sound/i2c/other/tea575x-tuner.c:99: error: (Each undeclared identifier is reported only once sound/i2c/other/tea575x-tuner.c:99: error: for each function it appears in.) sound/i2c/other/tea575x-tuner.c:108: warning: implicit declaration of function 'copy_to_user' sound/i2c/other/tea575x-tuner.c:112: warning: implicit declaration of function '_IOWR' sound/i2c/other/tea575x-tuner.c:112: error: syntax error before 'struct' sound/i2c/other/tea575x-tuner.c:115: warning: implicit declaration of function 'copy_from_user' sound/i2c/other/tea575x-tuner.c: At top level: sound/i2c/other/tea575x-tuner.c:129: error: syntax error before 'case' sound/i2c/other/tea575x-tuner.c:146: warning: type defaults to 'int' in declaration of 'snd_tea575x_set_freq' sound/i2c/other/tea575x-tuner.c:146: warning: parameter names (without types) in function declaration sound/i2c/other/tea575x-tuner.c:146: error: conflicting types for 'snd_tea575x_set_freq' sound/i2c/other/tea575x-tuner.c:62: error: previous definition of 'snd_tea575x_set_freq' was here sound/i2c/other/tea575x-tuner.c:146: warning: data definition has no type or storage class sound/i2c/other/tea575x-tuner.c:147: error: syntax error before 'return' sound/i2c/other/tea575x-tuner.c:151: error: syntax error before '&' token sound/i2c/other/tea575x-tuner.c:152: error: syntax error before '.' token sound/i2c/other/tea575x-tuner.c:152: warning: type defaults to 'int' in declaration of 'strcpy' sound/i2c/other/tea575x-tuner.c:152: warning: function declaration isn't a prototype sound/i2c/other/tea575x-tuner.c:152: error: conflicting types for 'strcpy' sound/i2c/other/tea575x-tuner.c:152: warning: data definition has no type or storage class sound/i2c/other/tea575x-tuner.c: In function 'snd_tea575x_init': sound/i2c/other/tea575x-tuner.c:194: warning: implicit declaration of function 'video_set_drvdata' sound/i2c/other/tea575x-tuner.c:197: error: 'video_exclusive_open' undeclared (first use in this function) sound/i2c/other/tea575x-tuner.c:198: error: 'video_exclusive_release' undeclared (first use in this function) sound/i2c/other/tea575x-tuner.c:200: warning: implicit declaration of function 'video_register_device' sound/i2c/other/tea575x-tuner.c:200: error: 'VFL_TYPE_RADIO' undeclared (first use in this function) sound/i2c/other/tea575x-tuner.c: In function 'snd_tea575x_exit': sound/i2c/other/tea575x-tuner.c:215: warning: implicit declaration of function 'video_unregister_device' distcc[7333] ERROR: compile sound/i2c/other/tea575x-tuner.c on x/32 failed make[1]: *** [sound/i2c/other/tea575x-tuner.o] Error 1 Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit a50d913f48b21aa22d31469e953fd6428540bf5b Author: Andrew Morton Date: Wed Jun 21 01:57:39 2006 -0300 V4L/DVB (4210a): git-dvb versus matroxfb drivers/video/matrox/matroxfb_base.c: In function 'matroxfb_ioctl': drivers/video/matrox/matroxfb_base.c:1140: error: 'VIDIOC_S_CTRL_OLD' undeclared (first use in this function) drivers/video/matrox/matroxfb_base.c:1140: error: (Each undeclared identifier is reported only once drivers/video/matrox/matroxfb_base.c:1140: error: for each function it appears in.) Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit b3bd5be8d4a3502898a561e8fa43febe04b6ff50 Author: Mauro Carvalho Chehab Date: Sat Jun 24 08:20:05 2006 -0300 V4L/DVB (4209): Added some BTTV PCI IDs for newer boards Signed-off-by: Mauro Carvalho Chehab commit b57e5578f913a304e97cb66aa0044a894ca47f2f Author: Mauro Carvalho Chehab Date: Fri Jun 23 16:13:56 2006 -0300 Fixes some sync issues between V4L/DVB development and GIT Some changes didn't went ok to -git, probably due to changes at merging patches. Signed-off-by: Mauro Carvalho Chehab commit 45f87a21735804760dd7db0e2e3c609c332b15e3 Author: Michael Krufky Date: Thu Jun 22 21:47:07 2006 -0300 V4L/DVB (4206): Cx88-blackbird: always set encoder height based on tvnorm->id Removed the switch..case block in blackbird_probe for setting encoder height based on video standard. All blackbird devices can rely on tvnorm->id to retrieve this information from the cx2388x video decoder - tuner_formats should not be used to determine the encoding video standard. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 153962364dc6fa4a24571885fbe76506d8968610 Author: Mauro Carvalho Chehab Date: Fri Jun 23 16:13:56 2006 -0300 V4L/DVB (4205): Merge tda9887 module into tuner. Most uses a tda988[5/6/7] IF demodulator as part of the device. Having this as a separate stuff makes harder to configure it, since there are some tda9887 options that are tuner-dependent and should be bound into tuner-types structures. This patch merges tda9887 module into tuner. More work is required to make tuner-types to properly use it. Signed-off-by: Mauro Carvalho Chehab commit 0ccac4af1a8f22e2e96d89b9bf8766dc7286a972 Author: Hans Verkuil Date: Fri Jun 23 15:52:50 2006 -0300 V4L/DVB (4203): Explicitly set the enum values. It's better to use explicit enums. It reduces the chance of someone inserting new enums in the middle which would break things. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 45ad9f8b44b06bf1e91b4b3c338406c2233f0482 Author: Hans Verkuil Date: Wed Jun 21 17:04:13 2006 -0300 V4L/DVB (4202): allow selecting CX2341x port mode CX2341X port was always set to 'memory', but 'streaming' is also possible ivtv uses the memory (DMA) interface with the CX2341X, while pvrusb2 and cx88-blackbird use the streaming interface. This setting is now selectable by the driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 54aa9a21ca03cf41d911ada969e86f27ce58bab9 Author: Hans Verkuil Date: Mon Jun 19 18:00:06 2006 -0300 V4L/DVB (4200): Disable bitrate_mode when encoding mpeg-1. MPEG-1 always uses CBR, so make the BITRATE_MODE control inactive. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit cc7bc648690d4e6f3992cfadb18a4c7e0181e6ea Author: Hans Verkuil Date: Mon Jun 19 17:53:08 2006 -0300 V4L/DVB (4199): Add cx2341x-specific control array to cx2341x.c Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit f81cf7533b4b8411a0d2fa943adcede340dfdab6 Author: Hans Verkuil Date: Sun Jun 18 16:54:20 2006 -0300 V4L/DVB (4198): Avoid newer usages of obsoleted experimental MPEGCOMP API Put old MPEGCOMP API under #if __KERNEL__ and issue warnings when used. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 86b79d662453b0f0107d03cc939dd737d6076436 Author: Hans Verkuil Date: Sun Jun 18 16:40:10 2006 -0300 V4L/DVB (4197): Port new MPEG API to saa7134-empress with saa6752hs Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit f022156b33ffa32c26a86540fe4f6fe56cff0963 Author: Hans Verkuil Date: Sun Jun 18 16:11:06 2006 -0300 V4L/DVB (4196): Port cx88-blackbird to the new MPEG API. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 54f577b7f46f48b8bea0bd5eb8c42d711b3e006f Author: Hans Verkuil Date: Sun Jun 18 14:56:12 2006 -0300 V4L/DVB (4193): Update cx2341x fw encoding API doc. Based on recent tests it turned out that some features are not implemented. This has now been documented. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 18318e00040e0a5c783f6d79c136c2141b779dbd Author: Hans Verkuil Date: Sun Jun 18 14:49:52 2006 -0300 V4L/DVB (4192): Use control helpers for saa7115, cx25840, msp3400. Replace hardcoded control description by the standard ones supplied by v4l2-common. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 5d1a9ae6d9d7fc14b2259cd550eb87364a21190a Author: Hans Verkuil Date: Sun Jun 18 14:40:30 2006 -0300 V4L/DVB (4191): Add CX2341X MPEG encoder module. Adds the cx2341x.c module that handles the programming of the Conexant cx23415/6 MPEG encoder chip used by cx88-blackbird, pvrusb2 and ivtv. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 9cb2318b885d2039eeb3eb5394fa215046be058f Author: Hans Verkuil Date: Sun Jun 18 14:11:08 2006 -0300 V4L/DVB (4190): Add helper functions for control processing to v4l2-common. Control processing is often duplicated in the various drivers. Unfortunately, simple things like the names of controls are often different between drivers, even though it is the same controls. Adding in the new extended controls and the need for having control helper functions became apparent. Several functions have now been added to v4l2-common to do things like filling the v4l2_queryctrl and v4l2_querymenu structs, to check for valid control input and to move to the next control when enumerating over all controls. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 0597691456cf3b08974d9949e4caa830e1d3c520 Author: Hans Verkuil Date: Sun Jun 18 13:43:28 2006 -0300 V4L/DVB (4189): Add videodev support for VIDIOC_S/G/TRY_EXT_CTRLS. videodev.c copies the control list specified in struct v4l2_ext_controls to kernel space. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 4f341712120abde54d9113856e9118e6580d7061 Author: Hans Verkuil Date: Sun Jun 18 13:27:19 2006 -0300 V4L/DVB (4188): Add new MPEG control/ioctl definitions to videodev2.h The old, experimental, VIDIOC_S/G_CODEC API to pass MPEG parameters is now obsolete and is replaced by 'extended controls' which offer more flexibility and are hopefully more future proof. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 442d15d5d8ba6a39d0c883585d68503e949a2fe1 Author: Cameron Hutchinson Date: Wed Jun 21 18:45:31 2006 -0300 V4L/DVB (4186): Add support for the DNTV Live! mini DVB-T card. Signed-off-by: Cameron Hutchinson Signed-off-by: Mauro Carvalho Chehab commit ceee526617a805eea908a59fced26635634c9035 Author: Yeasah Pell Date: Wed Jun 21 18:28:13 2006 -0300 V4L/DVB (4185): Conditionally enable 5 byte diseqc commands Signed-off-by: Yeasah Pell Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 9ce8b68fc036275986f005b38660d5d1795af8e8 Author: Adrian Bunk Date: Wed Jun 21 18:06:34 2006 -0300 V4L/DVB (4184): Static variables mustn't be EXPORT_SYMBOL 'ed Signed-off-by: Adrian Bunk Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 1fd57f60f81147dc70f8249da62af48fe451f2b1 Author: Manu Abraham Date: Wed Jun 21 17:03:42 2006 -0300 V4L/DVB (4182): Comment out MMI functions for now Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 1f19456d9760431f3a888b21fff035f875ddd189 Author: Henrik Sjoberg Date: Wed Jun 21 16:33:21 2006 -0300 V4L/DVB (4181): Fix CA Info and Application Info Signed-off-by: Henrik Sjoberg Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 3e357fd8a29cbcf91badd2a6d3b8ef5d4cb05025 Author: Manu Abraham Date: Wed Jun 21 15:06:49 2006 -0300 V4L/DVB (4180): Initial go at MMI Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit cdd4208c059e01d4cdc10a538bbbebbb60aa9b9f Author: Manu Abraham Date: Wed Jun 21 10:41:45 2006 -0300 V4L/DVB (4179): VLF fixes for DCT Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 7ef53b1ab739b09a39271998ab14605769697292 Author: Manu Abraham Date: Wed Jun 21 10:41:41 2006 -0300 V4L/DVB (4178): Replace NEWTUNE with TS188 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 63ad4e445d683fc1bee748171a7fcb589546bf04 Author: Manu Abraham Date: Wed Jun 21 10:41:37 2006 -0300 V4L/DVB (4177): DCTNEW and ATSC fixes Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 77e0be12100a3d40abfa46ef54c323b6cfff41ed Author: Sigmund Augdal Helberg Date: Wed Jun 21 10:35:48 2006 -0300 V4L/DVB (4176): Bug-fix: Fix memory overflow Do not overflow kernel memory when more than BT878_MAX devices are present. Signed-off-by: Sigmund Augdal Helberg Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit b32474cb8341bb828f2c2800d5dd615b7cd02182 Author: Manu Abraham Date: Wed Jun 21 10:28:31 2006 -0300 V4L/DVB (4175): Fix a bug in tuner detection Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit de1e6ec9f21ebd65d779524b614307291228a623 Author: Manu Abraham Date: Wed Jun 21 10:28:27 2006 -0300 V4L/DVB (4174): Distinguish between STV0299 and MB86A15 based NIM's Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 9500c7b05b1a618a32d49a249c28c98bcb039e35 Author: Manu Abraham Date: Wed Jun 21 10:28:23 2006 -0300 V4L/DVB (4173): Dprintk macro beautification Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 6cd94745fb3b97fb6ecd730c0aa9d1fb4fdf9c10 Author: Sigmund Augdal Helberg Date: Wed Jun 21 10:28:19 2006 -0300 V4L/DVB (4172): Remove spurious newlines in dprintk's. Add dst(card-num) as prefix in dprintk Signed-off-by: Sigmund Augdal Helberg Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 5aef20aeff7e9b0741ecc80365a3f7416900e494 Author: Manu Abraham Date: Wed Jun 21 10:28:16 2006 -0300 V4L/DVB (4171): Fix Daughterboard detection Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 3da2f4c0c64f4267594016c7bda3cc13fe7c95fb Author: Bryan Scott Date: Wed Jun 21 10:28:12 2006 -0300 V4L/DVB (4170): ATSC typecheck bugfix Signed-off-by: Bryan Scott Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 4e7024bd3278f14fdc435e6ff11c37cee752de99 Author: Manu Abraham Date: Wed Jun 21 10:28:09 2006 -0300 V4L/DVB (4169): Add more Firmware and Tuner names Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 1da5e8d3cf561508ddbc62283e65dc079d750550 Author: Manu Abraham Date: Wed Jun 21 10:28:05 2006 -0300 V4L/DVB (4168): ATSC tuner doesn't have variable length field Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 364f255af783a105b262eae018f0cad68e186681 Author: Manu Abraham Date: Wed Jun 21 10:28:01 2006 -0300 V4L/DVB (4167): Add Board Names Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 351634d27a90a7668554452f4ba1688043aa1128 Author: Manu Abraham Date: Wed Jun 21 10:27:57 2006 -0300 V4L/DVB (4166): Fix string length Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit b633c6d6a39a1cb78091fb04f093b16bdf8cbf59 Author: Manu Abraham Date: Wed Jun 21 10:27:53 2006 -0300 V4L/DVB (4165): Add in tuner names Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 396cffd63ed460ae2544d62745fabd22296af99a Author: Manu Abraham Date: Wed Jun 21 10:27:49 2006 -0300 V4L/DVB (4164): Add DVB-S specific demod names Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 1c4e7339e55af69bad55eb9a8f9d5b03a552020b Author: Manu Abraham Date: Wed Jun 21 10:27:46 2006 -0300 V4L/DVB (4163): Initialize ATSC frontend Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit c65f1c57094273144c614dc9f199c5decf7d27db Author: Manu Abraham Date: Wed Jun 21 10:27:40 2006 -0300 V4L/DVB (4162): Explicit defining of type is not necessary with MULTI_FE Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit cdd393ccbf99c0465b1db0b3f5a5687fb1340250 Author: Manu Abraham Date: Wed Jun 21 10:27:36 2006 -0300 V4L/DVB (4161): Utilize the device specific algorithm callbacks Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 0249ef16fa1eb4a85411d0e1b6e6a906e26ed1ac Author: Manu Abraham Date: Wed Jun 21 10:27:31 2006 -0300 V4L/DVB (4160): Use device specific algorithms Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 8cfba6301c3c7e0d3332e237b99fefc0db001163 Author: Manu Abraham Date: Wed Jun 21 10:27:26 2006 -0300 V4L/DVB (4159): Implement tuning algorithm as a module parameter Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 2e506a0faff0caa62e4c9531611684ff61cf1ca4 Author: Manu Abraham Date: Wed Jun 21 10:27:20 2006 -0300 V4L/DVB (4158): Make ASIC RESET Conditional Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit ed3d1065a4aa7b1e8e5d35ece0eeeafa5bfa6bd1 Author: Manu Abraham Date: Wed Jun 21 10:27:15 2006 -0300 V4L/DVB (4157): Add support for VP-3250 ATSC card Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit bc7386ba43c4e06e1fdf150c37ea6cbd778fb00c Author: Manu Abraham Date: Wed Jun 21 10:27:05 2006 -0300 V4L/DVB (4156): Add basic ATSC support to DST Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 4821fb1d8447a5786ea12c861b4ab5f69d400bfa Author: Manu Abraham Date: Wed Jun 21 10:27:00 2006 -0300 V4L/DVB (4155): ATSC frontend support Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit bafefc0cf8e4b34fbb159ea2e2aef2358ebff935 Author: Jesper Juhl Date: Fri Jun 23 13:27:36 2006 -0300 V4L/DVB (4154): Fix use-after-free bug in cpia2 driver The coverity checker detected a use-after-free error in drivers/media/video/cpia2/cpia2_v4l.c::cpia2_close() (coverity error #1281). What happens is that we lock cam->busy_lock, then proceed to free resources, and in the case of (--cam->open_count == 0) we finish off by doing a kfree(cam) and then at the end of the function we do a mutex_unlock(&cam->busy_lock) which will explode since it'll dereference the free'd `cam' : ... mutex_lock(&cam->busy_lock); ... if (--cam->open_count == 0) { ... if (!cam->present) { video_unregister_device(dev); kfree(cam); } } mutex_unlock(&cam->busy_lock); <--- PROBLEM, cam no longer around. ... Since this only happens in the case of open_count going down to zero I don't see a problem with just releasing the mutex after unregistering the device and just before the kfree(). In this case there is nothing around that we can race against; we are in the release method, open_count is zero, (!cam->present) and the device has just been unregistered, so letting go of the mutex at this point looks safe to me. Patch below to implement that solution. Acked-by: Randy Dunlap Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit 7597e8e71f897449a26d5a32eedc09f8e76ae52a Author: Michael Krufky Date: Thu Jun 22 23:13:06 2006 -0300 V4L/DVB (4150): Cx88: clear EN_I2SIN_ENABLE bit for ASUS PVR-416 to enable audio clear EN_I2SIN_ENABLE bit for ASUS PVR-416 to enable audio streaming in both raw video and blackbird mpeg encoder modes. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit ec675bce403b46570e6ab93eb9a226e966de1010 Author: Dave Jones Date: Fri Jun 23 09:01:42 2006 -0300 V4L/DVB (4149): Fix up funky logic in dvb Signed-off-by: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit c18cb01ca139716a39f4fb92286b6096e8b3f968 Author: Mauro Carvalho Chehab Date: Fri Jun 23 07:05:22 2006 -0300 V4L/DVB (4148): Fix userbits debug prints Previously, it were showing the pointer value, instead of the setted bits. Signed-off-by: Mauro Carvalho Chehab commit b20c3cf0c225df1445fa220de175b8d9bc1c3659 Author: Adrian Bunk Date: Fri Jun 23 06:49:34 2006 -0300 V4L/DVB (4147): Drivers/media/video/pwc/: make code static This patch makes the following needlessly global code static: - pwc-ctrl.c: pwc_get_leds() - pwc_preferred_compression Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit dc46ace15e50cb8af3f3072c00aaf3429770b0e2 Author: Adrian Bunk Date: Fri Jun 23 06:42:44 2006 -0300 V4L/DVB (4146): Drivers/media/video/vivi.c: make 2 functions static Make two needlessly global functions static. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit 65271bff0fb11557d04d389df728d12dfba75dc3 Author: Michael Krufky Date: Wed Jun 21 16:04:33 2006 -0300 V4L/DVB (4144): Cx88: add support for FusionHDTV 3 Gold (original revision) Add support for FusionHDTV 3 Gold (original revision), using the card definition for FusionHDTV3 Gold-Q Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 1138ead47c4cb367cdb8fe6e41724eac0aa3a60b Author: Michael Krufky Date: Mon Jun 19 09:54:00 2006 -0300 V4L/DVB (4135): Cx88-tvaudio.c must #include Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit b63535f4058eca81b64485c885610008784d2bb0 Author: Ricardo Cerqueira Date: Sun Jun 18 00:21:49 2006 -0300 V4L/DVB (4132): Don't kill cx88 DMA sound on channel change There's a call at cx88-tvaudio to reset DMA sound on channel change; that call was killing cx88-alsa whenever the channel was changed, resulting in no sound. Remove those calls if cx88-alsa is selected to be compiled. Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab commit 0f4b56807b443927600112c1351a181ce664929c Author: Ricardo Cerqueira Date: Sun Jun 18 00:19:22 2006 -0300 V4L/DVB (4131): Fix cx88-alsa vs IRQ remote conflict cx88-alsa was resetting the card on load, causing the IRQ IR handler to go away (maybe others, too). There's no actual need to reset the card, though, so that line was removed Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab commit c2eaa68f7950ef51ce480766bc11eb8b3c20c90a Author: Ricardo Cerqueira Date: Sun Jun 18 00:17:35 2006 -0300 V4L/DVB (4130): Fix card cx88 #50 remote There was an unmasked bit in the keycodes that was causing random behaviour (the code could be N or N+1). Masked that bit now. Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab commit 8ca4deb259f17a9a209030baa36aca39ec03ceaf Author: Michael Krufky Date: Tue Jun 20 15:56:02 2006 -0300 V4L/DVB (4124): Kconfig: fix description for saa7115 module This Kconfig description is incorrect, due to a previous merge a while back. CONFIG_SAA711X builds module saa7115, which is the newer module, and is not obsoleted. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 87057d29f84b031f2e84ac78be5caa51a96f678e Author: Mac Michaels Date: Tue Jun 20 09:18:13 2006 -0300 V4L/DVB (4122): Lgdt330x: fix missing line in VSB snr decoding logic - fix missing line in VSB snr decoding logic for lgdt3303 Signed-off-by: Mac Michaels Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit cebdd4136d704f9afeb67e9685dfd398a6a2e655 Author: Michael Krufky Date: Tue Jun 20 09:17:48 2006 -0300 V4L/DVB (4121): Update cardlist documentation Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 5e2fb0824a5aa42c8d1b1b177ab287e84685be39 Author: Mauro Carvalho Chehab Date: Tue Jun 20 15:03:19 2006 -0300 V4L/DVB (4120): Ovcamship position at Kconfig changed Ovcamship is used only on some USB webcams (OV511 and W9968CF) Bettet to leave this item just after those webcams. Signed-off-by: Mauro Carvalho Chehab commit 657de3cd32285831a56f9f96deb85c64205c42fc Author: Trent Piepho Date: Tue Jun 20 00:30:57 2006 -0300 V4L/DVB (4118): Whitespace cleanups Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab commit f49ba8d7cd252eac19004e2ebe18dfffe548c2c3 Author: Zac Bowling Date: Mon Jun 19 19:49:20 2006 -0300 V4L/DVB (4115): Saa7134 card (LifeView3000 NTSC) Add detection for the LifeView3000 NTSC model (right now the PAL version is the only one in there, which is sort of annoying for me living in the US and all.. sigh...) This is one of those things that I like to classify "as a works for me so take it or leave it" :-) . Not that worried because its an $18 video capture card that didn't look it was selling to well in the US, but then again who knows. The documentation needs updating too I bet but its behind anyways usually to what is in the code. Signed-off-by: Zac Bowling Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit 4ceb04e1b1cf724b6ed805955adfbbdfa8a3d436 Author: Mauro Carvalho Chehab Date: Sat Jun 17 08:52:30 2006 -0300 V4L/DVB (4112): Fix: videodev.c were cleaning the pointer, not the values Signed-off-by: Mauro Carvalho Chehab commit 35a303b1d788623939756136d85aecccf2d82686 Author: Jose Alberto Reguero Date: Sat Jun 17 08:05:41 2006 -0300 V4L/DVB (4110): Small bug in saa7127.c Fix wrong wss debug info. Signed-off-by: Jose Alberto Reguero Signed-off-by: Mauro Carvalho Chehab commit 89a58c83f8f1056583f30c4d4258b1fec39bb0e2 Author: Mauro Carvalho Chehab Date: Sat Jun 17 07:57:03 2006 -0300 V4L/DVB (4108): Fixes some userspace dependencies at V4L2 public api header Make life easier for distro guys, by removing the need of including at the userspace header. Also, linux/compiler.h is not needed at userspace. Signed-off-by: Mauro Carvalho Chehab commit 5dab71b1e85356fdd7cbc29d338ca6c0bd0e4e49 Author: Trent Piepho Date: Sat Jun 17 07:48:03 2006 -0300 V4L/DVB (4106): Fix problems with AV7110 firmware building Fix missing $() on variable name in dvb/ttpci/Makefile Fix AV7110 firmware dependencies so that parallel builds work correctly. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab commit 81e47e33add6874dc0ee094bd2a672241cbba829 Author: Trent Piepho Date: Tue Jun 20 01:26:39 2006 -0300 V4L/DVB (4105): Remove uneeded prototype Uneeded extern prototype is removed, as the function is prototyped at media/v4l2-common.h. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab commit 44f7f2b363a33e20ba9812e4a5c16fa7cc07a3ee Author: Trent Piepho Date: Sat Jun 17 07:46:31 2006 -0300 V4L/DVB (4104): Default "yes", no. default y, yes. The Kernel config programs expect 'default y' and don't understand 'default "yes"'. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab commit 0f102910de010bb877cb6b37557b4e7b98b1039d Author: Michael Krufky Date: Mon Jun 12 14:18:26 2006 -0300 V4L/DVB (4099): Cx88-dvb: clean up long linewraps This patch splits up dvb_pll_attach and isl6421_attach function calls such that the lines do not exceed 80 columns. This patch is purely cosmetic, with no functional change at all. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit c2af3cd68e0680a659166d0cecc24afb93b2000e Author: Michael Krufky Date: Mon Jun 12 14:06:22 2006 -0300 V4L/DVB (4098): Cx88: #ifdef cleanups - moved CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL frontend_attach code up to share the #ifdef block with CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 66dd0fccbdbb77db897dd5870a67cb8022899adc Author: Michael Krufky Date: Mon Jun 12 13:41:47 2006 -0300 V4L/DVB (4097): Cx88: add support for DViCO FusionHDTV DVB-T Dual PCI based on zl10353 This patch adds support for a newer version of this device using the zl10353 frontend instead of the mt352 frontend. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit fd174c67253505d6af4a32c6e3d7ec8cbaed320d Author: Michael Krufky Date: Mon Jun 12 13:40:37 2006 -0300 V4L/DVB (4096): CinergyT2: whitespace cleanup Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit c9ce394017162a90d79a4abc99eed3c7b2aed606 Author: Michael Krufky Date: Sun Jun 11 04:24:31 2006 -0300 V4L/DVB (4094): Cxusb: add support for DViCO FusionHDTV DVB-T Dual USB based on zl10353 This patch adds support for a newer version of this device using the zl10353 frontend instead of the mt352 frontend. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit f14ac0bc455a255c48f9110080e8889c6d65cec2 Author: Jelle Foks Date: Thu Mar 9 17:44:07 2006 -0300 V4L/DVB (3426): PATCH cx88-mpeg: cx8802_restart_queue() for blackbird Fixes "cx8802_restart_queue: queue is empty" storm in syslog Signed-off-by: Jelle Foks Signed-off-by: Mauro Carvalho Chehab commit 774dd5d9bdcbfe2efb3425e8a0be0b4d01a65c26 Author: Dyks, Axel (XL) Date: Sun Jun 11 17:14:35 2006 -0300 V4L/DVB (4090): Fix cinergyt2_poll() to allow non-blocking IO on frontend cinergyt2_poll()" shouldn't return (POLLIN | POLLRDNORM | POLLPRI) when there are no pending events. User space programs that do non-bocking IO using "select()" and/or "poll()" would otherwise produce high system load. Acked-by: Andreas Oberritter Signed-off-by: Axel Dyks Acked-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab commit be4f451975c6514a9e12451c2ae2ce91d5673b06 Author: Ricardo Cerqueira Date: Thu Jun 8 17:36:17 2006 -0300 V4L/DVB (4088): Fixes for card cx88 #50 The description of the card has been updated to it's full name/model. The tuner has also been switched to a more compatible one (radio wasn't working, now it is) Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab commit 2ed64eb9e7b4cf27055f78a7bd2ccf33a912d0cd Author: Mauro Carvalho Chehab Date: Thu Jun 8 17:16:46 2006 -0300 V4L/DVB (4086): There were a cross-reference on cpia and cpia_pp/cpia_usb Those cross-references were generating an error: *** Warning: "cpia_pp_init" [/home/v4l/master/v4l/cpia.ko] undefined! *** Warning: "cpia_usb/_init" [/home/v4l/master/v4l/cpia.ko] undefined! Signed-off-by: Mauro Carvalho Chehab commit 60110ce2b2ce74d8a49a4600ce58ba0b44f82800 Author: Lothar Englisch Date: Tue Jun 6 16:13:46 2006 -0300 V4L/DVB (4073): Support for new version of Satelco EasyWatch DVB-S light This patch adds support for Satelco EasyWatch DVB-S light card, a clone of the KNC 1, with PCI subsystem ID 1894:001e Signed-off-by: Lothar Englisch Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 47ee2f387961cf300ffebfd56faa3a5823586c8b Author: Michael Krufky Date: Tue Jun 6 15:51:38 2006 -0300 V4L/DVB (4072): Cx88: whitespace cleanup Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 845f16abad37e2a255ac1c167375f6588502f93f Author: Eric Sesterhenn Date: Tue Jun 6 11:20:08 2006 -0300 V4L/DVB (4070): Zoran strncpy() fix The zoran driver uses strncpy() in an unsafe way. This patch uses the proper sizeof()-1 size parameter. Since all strncpy() targets are initialised with memset() the trailing '\0' is already set. Where std->name was the target for the strncpy() we overwrote 8 Bytes of the std structure with zeros. Signed-off-by: Eric Sesterhenn Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit 5e87efa3b29c105f81fea785babafb098e4e046d Author: Mauro Carvalho Chehab Date: Mon Jun 5 10:26:32 2006 -0300 V4L/DVB (4068): Removed all references to kernel stuff from videodev.h and videodev2.h The videodev.h and videodev2.h describe the public API for V4L and V4L2. It shouldn't have there any kernel-specific stuff. Those were moved to v4l2-dev.h. This patch removes some uneeded headers and include v4l2-common.h on all V4L driver. This header includes device implementation of V4L2 API provided on v4l2-dev.h as well as V4L2 internal ioctls that provides connections between master driver and its i2c devices. Signed-off-by: Mauro Carvalho Chehab commit 839e4a4acb90fd34e3f6765bef6fe03ee82dbc58 Author: Mauro Carvalho Chehab Date: Sun Jun 4 12:15:55 2006 -0300 V4L/DVB (4067): Fixed cx25840 to work with PAL/M Sub-carrier frequency for PAL/M is slicely different than NTSC/M. Without this patch, colors don't work on PAL/M. Setting method also improved to allow other video standards to be included. Signed-off-by: Mauro Carvalho Chehab commit c820cc45366377a84a5f66066db4e16b7a6e5b8c Author: Mauro Carvalho Chehab Date: Sun Jun 4 10:34:12 2006 -0300 V4L/DVB (4066): Vivi.c were ported to the newer videodev2 format. Several common handling codes were removed. Maybe even more stuff may be handled at common infrastructure. Signed-off-by: Mauro Carvalho Chehab commit 401998fa96fe18b057af3f906527196522dd2d9d Author: Mauro Carvalho Chehab Date: Sun Jun 4 10:06:18 2006 -0300 V4L/DVB (4065): Several improvements at videodev.c Videodev now is capable of better handling V4L2 api, by processing V4L2 ioctls and using callbacks to the driver. The drivers should be migrated to the newer way and the older one will be obsoleted soon. Signed-off-by: Mauro Carvalho Chehab commit 7565ab082de88ec274283d6b83980144e520a2fc Author: Mauro Carvalho Chehab Date: Sun Jun 4 09:11:13 2006 -0300 V4L/DVB (4064): No drivers should use VIDIOC_*_OLD V4L core functions handle VIDIOC_*_OLD older ioctls. Signed-off-by: Mauro Carvalho Chehab commit dd00b1e02081b4b543dac3619cc9c7f26c4bced4 Author: Adrian Bunk Date: Mon May 29 12:31:44 2006 -0300 V4L/DVB (4060): Make dvb/b2c2/flexcop-fe-tuner.c:alps_tdee4_stv0297_tuner_set_params() static This patch makes the needlessly global alps_tdee4_stv0297_tuner_set_params() static. Signed-off-by: Adrian Bunk Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 52398efcfa77aeb7e95ef99c9edadd909eb562a5 Author: Michael Krufky Date: Fri May 26 02:13:15 2006 -0300 V4L/DVB (4058): Bttv: add autodetection support for Osprey 230 - use eeprom data to detect Osprey 230 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 2de873e630b9385c6cd5896753335c5bf4829f0c Author: Malcolm Valentine Date: Mon May 29 13:56:24 2006 -0300 V4L/DVB (4057): Cx88: IR remote support for DTV2000H Adds support for the Y0400052 remote supplied with this card. In addition to adding a number of buttons to the current winfast definition, it enables all the keys currently masked out with #ifdef 0. It is supplied separately as it remaps two keys from the current definition, The teletext button now sends KEY_TEXT instead of KEY_SUBTITLE, as that keycode is used by the subtitle button. KEY_BACK was changed to KEY_LAST to group it with KEY_NEXT. Other then that the keys don't overlap, so this should support several different versions of the Leadtek remotes. Signed-off-by: Malcolm Valentine Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 4bd6e9d968af68c73bee92bd93cd56937e2e80d8 Author: Malcolm Valentine Date: Mon May 29 13:51:59 2006 -0300 V4L/DVB (4056): Cx88: Add basic support for Leadtek Winfast DTV2000H card Add DVB-T and PAL-G television support for Winfast DTV2000H Signed-off-by: Malcolm Valentine Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit bc53f78306a70d58e26f93d40ce19e61297cc18f Author: Michael Krufky Date: Sun May 28 01:43:35 2006 -0300 V4L/DVB (4053): KWorld HardwareMpegTV XPert: enable s-video/composite video inputs - Enabled s-video and composite video inputs. - Updated comments to reflect the current support for this card. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 741b5bb6498e09178f14a3a5b2cc46e9970f46ed Author: Mauro Carvalho Chehab Date: Sun May 28 15:45:54 2006 -0300 V4L/DVB (4052): Wrong syntax: instead of bool, it was written boolean Signed-off-by: Mauro Carvalho Chehab commit 3e3bf277f1d2487307227e2c5329763cf3af44bc Author: Christopher Neufeld Date: Wed May 24 10:16:45 2006 -0300 V4L/DVB (4050): Add NTSC sliced VBI support to the cx25840 module. NTSC sliced VBI support by Christopher Neufeld with additional fixes by Hans Verkuil . Signed-off-by: Christopher Neufeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 88ca8ed0b7f2f04a055ff3c389f398ba3ad3d27d Author: Scott Alfter Date: Sat May 20 16:04:31 2006 -0300 V4L/DVB (4048): Add support for the Texas Instruments TLV320AIC23B audio codec Signed-off-by: Scott Alfter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit a22f1cbc2d3acd99986e96092109f6ced0f0022e Author: Randy Dunlap Date: Fri May 26 10:32:13 2006 -0300 V4L/DVB (4047): Doc. sources: expose video4linux/ Documentation/video4linux/: Expose example and tool source files in the Documentation/ directory in their own files instead of being buried (almost hidden) in readme/txt files. This will make them more visible/usable to users who may need to use them, to developers who may need to test with them, and to janitors who would update them if they were more visible. Also, if any of these possibly should not be in the kernel tree at all, it will be clearer that they are here and we can discuss if they should be removed. Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab commit c003d467bd71a7da22554e0d812a646ab58abea5 Author: David Mosberger-Tang Date: Fri May 26 10:28:13 2006 -0300 V4L/DVB (4046): Trivial videodev2.h patch linux/videodev2.h uses types such as __u8 but it fails to include . Within the kernel, that's not a problem because already includes . However, there are user apps that try to include videodev2.h (e.g., ekiga) and at least on ia64, it causes compilation failures since doesn't get included for any other reason, leaving __u8 etc. undefined. The attached patch fixes the problem for me. Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit dea74869f3c62b0b7addd67017b22b394e942aac Author: Patrick Boettcher Date: Sun May 14 05:01:31 2006 -0300 V4L/DVB (4028): Change dvb_frontend_ops to be a real field instead of a pointer field inside dvb_frontend The dvb_frontend_ops is a pointer inside dvb_frontend. That's why every demod-driver is having a field of dvb_frontend_ops in its private-state-struct and using the reference for filling the pointer-field in dvb_frontend. - It saves at least two lines of code per demod-driver, - reduces object size (one less dereference per frontend_ops-access), - be coherent with dvb_tuner_ops, - makes it a little bit easier for newbies to understand how it works and - avoids stupid mistakes because you would have to copy the dvb_frontend_ops always, before you could assign the static pointer directly, which was dangerous. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab commit 332bed5fc25ab0eb84215ecd89a4acd48219eee0 Author: Patrick Boettcher Date: Sun May 14 04:49:00 2006 -0300 V4L/DVB (4027): Fixes after dvb_tuner_ops-conversion Some of the dvb_tuner_ops-pointer were set before having a dvb_frontend creating. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab commit 2938d7800f2ea2f8ad88d5b241cbda868875e965 Author: Michael Krufky Date: Tue May 23 18:39:29 2006 -0300 V4L/DVB (4043): Miropcm20: fix sub-optimal header inclusion for sound/oss/aci.h Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 6e2040900467f3a80a3be558c7094ff022fb8cb4 Author: Michael Krufky Date: Tue May 23 17:41:31 2006 -0300 V4L/DVB (4042): Documentation: whitespace cleanup Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 680543c5d2756ad3496f8ef197ba8825b78d6840 Author: Ricardo Cerqueira Date: Mon May 22 07:44:02 2006 -0300 V4L/DVB (4038): New cx88 card #50: NPG Tech RealTV Added support for a new cx88 card, including it's remote Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab commit d6144028af6b151018c50c160e794a4d7f686333 Author: Mauro Carvalho Chehab Date: Fri May 19 13:08:09 2006 -0300 V4L/DVB (4036): Fix some compilation warnings Signed-off-by: Mauro Carvalho Chehab commit 0463f12c5cdc3d5577002826c302471b95b2532c Author: Andrew de Quincey Date: Tue May 16 17:22:02 2006 -0300 V4L/DVB (4032): Fix Pinnacle 300i I had broken the mt352 tuning when a non-directly connected PLL was used - uncommon, but this is what is used on the pinnacle card. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 976e3483799ce5f718753d67454378d46500f0da Author: Patrick Boettcher Date: Sun May 14 13:29:48 2006 -0300 V4L/DVB (4030): Minor code cleanup on the genpix-module Minor code cleanup on the genpix-module. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab commit 9bbe076f364aa7ba8c2e49e417a76d628ffb164c Author: Alan Nisota Date: Sun May 14 13:23:56 2006 -0300 V4L/DVB (4029): [PATCH] Genpix 8PSK->USB driver (Take 2) This is a patch which includes support for the GENPIX 8PSK->USB module. The board supports QPSK, BPSK and 8PSK decoding (though I don't think it will be DVB-S2 compliant) With the following patch, the boad is equivalent to a budget card (no CA Module) The patch which adds 8psk suppot will follow, but is seperate, as it requires DVB-S2 support More info on the board can be found at www.genpix-electronics.com (and they host the requisite firmwares there as well) Signed off by: Alan Nisota Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab commit 6daa4f86e9a01da6296f4c2bf40f8180a22718a8 Author: Ricardo Cerqueira Date: Thu May 18 12:19:57 2006 -0300 V4L/DVB (4026): Bttv-gpio-irq is no longer used, remove it This functionality was used when remote control input for BTTV was handled by a standalone module, to hook some functions of that module into the main bttv core. Since that module is now extinct, this can go away Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab commit b93eedb62e358588c5e595b07fb85efa1f597a9f Author: Sylvain Pasche Date: Sat Mar 25 23:14:42 2006 -0300 V4L/DVB (4023): Subject: Pinnacle PCTV grey remote control support This adds support for the older (?) Pinnacle PCTV remotes (with all buttons colored in grey). There's no autodetection for the type of remote, though; saa7134 defaults to the colored one, to use the grey remote the "pinnacle_remote=1" option must be passed to the saa7134 module Signed-off-by: Sylvain Pasche Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab commit e48a9c6283c1ca2565167f0b4bce4d0be7f49fae Author: jayakumar.video@gmail.com Date: Wed May 17 15:01:07 2006 -0300 V4L/DVB (4018): Usbvideo/quickcam_messenger driver v4l Adds a usbvideo driver for the Logitech Quickcam Messenger USB webcam. Signed-off-by: Jaya Kumar Signed-off-by: Mauro Carvalho Chehab commit a31246220c4681387799d435ee1d48e65db6d5f6 Author: Angelo Marconi Date: Tue May 9 18:27:48 2006 -0300 V4L/DVB (4016): Cx88-blackbird: add support for ProLink Pixelview Playtv@P7000 - Add support for ProLink Pixelview Playtv@P7000 Raw video and MPEG encoded video confirmed to work properly. SVideo, Composite and FM inputs are untested - disabled for now. Signed-off-by: Angelo Marconi Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 8397703ee0cc9ca27df5c058f60c4d4f1dc69595 Author: Trent Piepho Date: Fri May 12 20:36:24 2006 -0300 V4L/DVB (4014): Remove the spagetti code gotos that aren't useful Some code had pointless gotos that just didn't make any sense. They didn't make the code smaller, or faster, or easier to understand. Signed-off-by: Trent Piepho Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 19b7ad314897cf4a2122208c6b9a372c50308c19 Author: Per Dalén Date: Fri May 12 20:31:51 2006 -0300 V4L/DVB (4013): Change the sweeprate for TT C1500 using QAM64 This patch changes the sweeprate for TT C1500 using QAM64. It has been proven to work using QAM64 at a SRate of 6875 for the two Signed-off-by: Mauro Carvalho Chehab commit cd20ca9f194323c74ecccf15a3f5ff6c44effe69 Author: Andrew de Quincey Date: Fri May 12 20:31:51 2006 -0300 V4L/DVB (4012): Fix cx24123 diseqc Rework diseqc support to be more in line with the other demod drivers. Fix Nova-S-Plus/Nova-SE2 diseqc. Cleanup API. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 9a10655ffa20b596fd162b1c96301f3bed752918 Author: Andrew de Quincey Date: Fri May 12 20:31:51 2006 -0300 V4L/DVB (4011): Fix PLL refactoring breakage to WinTV NOVA T USB 2 driver The calls to set the pll ops were in the wrong place - moved them. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 2e2aef7d5a8ac9d1c9b2c07a9fc96a7908d51d72 Author: Hans Verkuil Date: Sat Apr 29 12:26:46 2006 -0300 V4L/DVB (4008): Audio soft reset improvements The soft reset (de)assert commands where not at the right place. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit c0c044a71f3d0a0a73c954b389cbc4b55ed4c2ba Author: Hans Verkuil Date: Sat Apr 29 12:11:18 2006 -0300 V4L/DVB (4006): Stop/start microcontroller when changing sampling frequency Stop/start microcontroller when changing sampling frequency to prevent tinny audio. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit e2b8cf4ced47465b24d6fe911714827475fb0412 Author: Hans Verkuil Date: Sat Apr 22 10:22:46 2006 -0300 V4L/DVB (4005): Add support for the cx25836/7 video decoder. Signed-off-by: Scott Alfter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 3eb731705556b643df2cbae1bc98976335451548 Author: Trent Piepho Date: Tue May 23 23:54:44 2006 -0300 V4L/DVB (4002): Adjust VBI offset to match value reported in VBI format The actual offset of the start of VBI data is incorrectly documented for both the cx2388x and bt8x8. For the cx2388x, it appears to be about 220 to 224 + VBI_V_DEL*2. The driver has been incorrectly reporting an offset of 244. This patch adjusts VBI_V_DEL to 10, so that the offset of 244 is correct. This is the same offset as the bttv driver, and expected by some software. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab commit 419ac5d466db4dba3eb6bd79ffe993b4a4e81b4f Author: Michael Schimek Date: Mon May 22 10:32:11 2006 -0300 V4L/DVB (4001): Cx88 NTSC VBI fixes VBI (Closed Caption, CC) capturing never worked in NTSC mode with the cx88 driver. They were tested with libzvbi and a patched version of tvtime. Signed-off-by: Michael H. Schimek Signed-off-by: Mauro Carvalho Chehab commit 7f2c8a9c5377bf48dcf1d1df7df11a3ef442c505 Author: Christoph Pfister Date: Mon May 22 10:32:09 2006 -0300 V4L/DVB (3996): Make the table static Signed-off-by: Christoph Pfister Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit cbee936f472d2d7fb42bb595acf8c451cdb73759 Author: Manu Abraham Date: Mon May 22 10:32:08 2006 -0300 V4L/DVB (3995): Add missing include Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit fc066478605330d929a90101be02efa2822f3cc0 Author: Michael Krufky Date: Mon May 22 10:32:05 2006 -0300 V4L/DVB (3991): Cx88: add autodetection for another Twinhan VP-3054 board. Added autodetection for PCI subsystem id 1822:0019 to use the card definition for CX88_BOARD_DNTV_LIVE_DVB_T_PRO Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit da22d0e758bf011be5921421bf490ce69c387784 Author: Christoph Pfister Date: Mon May 22 10:32:04 2006 -0300 V4L/DVB (3988): Add math routines required by DVB demods Signed-off-by: Christoph Pfister Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab commit 5c1208ba457a1668c81868060c08496a2d053be0 Author: Andrew de Quincey Date: Mon May 22 10:32:02 2006 -0300 V4L/DVB (3984): Fix CI interface on KNC1 DVBT and DVBC cards These cards need special handling for CI - reinitialising the frontend device when the CI module is reset. Additionally the tda10021 needs to be set into a different transport stream mode when a CI module is present. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 48c35756a762e2d569dfd9ab2f24d1b63ea657b9 Author: Michael Krufky Date: Mon May 22 10:32:00 2006 -0300 V4L/DVB (3982): Cx88-blackbird: use encoder firmware filename defined in cx2341x.h Since the filename of the cx23416 encoder firmware image is defined in cx2341x.h, we don't need to explicitly define it in cx88-blackbird.c anymore. This changeset removes BLACKBIRD_FIRM_ENC_FILENAME, replacing all occurrances with CX2341X_FIRM_ENC_FILENAME. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 2544bf2d619d09b564fbdd451fe4b1ba798f9c03 Author: Valentin Zagura Date: Mon May 22 10:31:59 2006 -0300 V4L/DVB (3973): Cx88-blackbird: pause the encoder during frequency change Added code to cx88-blackbird.c to treat the VIDIOC_S_FREQUENCY ioctl to stop mpeg stream before changing the frequency and restart it after. It seems that the mpeg stream needs to be paused while changing the channel frequency, otherwise the mpeg encoder enters into a bad state, producing artifacts. Signed-off-by: Valentin Zagura Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 07f640f0ddd72e6158fca7f0694dbaf95cee4d2c Author: Mauro Carvalho Chehab Date: Mon May 22 10:31:57 2006 -0300 V4L/DVB (3973a): Return value is ssize_t This patch fix a difference between v4l/dvb tree and kernel tree. Signed-off-by: Mauro Carvalho Chehab commit 861018a6a9b55ca1a5bf8cd0ff2d47944ce88827 Author: Michael Krufky Date: Mon May 22 10:31:55 2006 -0300 V4L/DVB (3971): Cx88-blackbird: use standard filename for cx23416 firmware cx88-blackbird uses the same encoder firmware for the cx23416 chip that is used by ivtv and pvrusb2. This patch alters the driver to expect the cx23416 encoder firmware to be located in the file, "v4l-cx2341x-enc.fw", instead of using "blackbird-fw-enc.bin" Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 855dbada9b551d12a63754b92f67e34c113adf34 Author: Michael Krufky Date: Mon May 22 10:31:54 2006 -0300 V4L/DVB (3970): Cx88-blackbird: use firmware api commands defined in cx2341x.h This patch removes all of the BLACKBIRD_API #define's, instead using the equivalent CX2341X_ENC #define's in cx2341x.h Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit d762052e1eafd95f3b4622e1990f40dfd0d45b0f Author: Mauro Carvalho Chehab Date: Mon May 22 10:31:52 2006 -0300 V4L/DVB (3968): Fix checking logic for a broken xawtv version moved from if to ifndef. Also added such tests at gentree script. Gentree updated to its latest version. Signed-off-by: Mauro Carvalho Chehab commit f6320bd3df5964619346bac77b36d03c5a82f6fd Author: Mauro Carvalho Chehab Date: Mon May 22 10:31:50 2006 -0300 V4L/DVB (3968a): Remove compatibility check for I2C_PEC Signed-off-by: Mauro Carvalho Chehab commit 7923dee035ec81f6e4ad696e3edddbdd34d37873 Author: akpm@osdl.org Date: Mon May 22 10:31:49 2006 -0300 V4L/DVB (3967): Pwc-dec23 oops fix drivers/media/video/pwc/pwc-dec23.c: In function `pwc_dec23_decompress': drivers/media/video/pwc/pwc-dec23.c:885: warning: null argument where non-null required (arg 2) Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit 18232ca61b4c73b849850200a5e6ec40517f35ab Author: Christian Praehauser Date: Mon May 22 10:31:47 2006 -0300 V4L/DVB (3966): Core: ULE fixes and RFC4326 additions Fix some problems regarding support for Unidirectional Lightweight Encapsulation (ULE) in dvbnet.c. The original ULE code was based on a draft. In the meantime, ULE has been published in RFC 4326 (ftp://ftp.rfc-editor.org/in-notes/rfc4326.txt). With these fixes, and some additions (which are included in the patch), the decaps code should now be complient to RFC4326. Signed-off-by: Christian Praehauser Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit adcb0fa2504aac35e0ed285147b11e75a6db34c7 Author: Adrian Bunk Date: Mon May 22 10:31:42 2006 -0300 V4L/DVB (3963): Em28xx/: possible cleanups This patch contains the following possible cleanups: - make the following needlessly global functions static: - em28xx-core.c: em28xx_accumulator_set() - em28xx-core.c: em28xx_capture_area_set() - em28xx-core.c: em28xx_scaler_set() - em28xx-core.c: em28xx_isocIrq() - remove the following unused EXPORT_SYMBOL's: - em28xx-cards.c: em28xx_boards - em28xx-cards.c: em28xx_bcount - em28xx-cards.c: em28xx_id_table Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab commit a9686e0d204e3faa544434c709ccb599f8165252 Author: Andrew de Quincey Date: Mon May 22 10:31:40 2006 -0300 V4L/DVB (3935): Add missing pll gate control calls I'd missed some of these out, breaking the av7110 tuning. I then checked for more and added them in where necessary. They may not actually be necessary in all these locations, but if not, they'll simply have no effect. Add small delay to stv0299 pll gate control to fix tuning problems. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit ebfbc305bda90deadf73898493c707cce3b465e6 Author: Mauro Carvalho Chehab Date: Mon May 22 10:31:38 2006 -0300 V4L/DVB (3809c): Added cx2341x header file Date: There are several drivers now using those cx2341x registers. This patch creates a separate header for those registers. Signed-off-by: Mauro Carvalho Chehab commit 447d6fb8ccdc3a581a13fe4b5a62c384dc9fd36a Author: Mauro Carvalho Chehab Date: Mon May 22 10:31:37 2006 -0300 V4L/DVB (3809b): Added missing docs at kernel tree Date: From: Mauro Carvalho Chehab There are some docs at V4L/DVB tree that were never included at kernel. This patch includes those docs. Signed-off-by: Mauro Carvalho Chehab commit b8d4c235d50f8512bbc9d67730c24da3309b0307 Author: Thomas Kaiser Date: Thu Apr 27 21:45:20 2006 -0300 V4L/DVB (3934): Support new dvb-ttusb-budget boards with stv0297 Added config switch to stv0297 to control i2c STOP during write behaviour. Update frontend init in dvb-ttusb-budget. Enable i2c STOP on other users of stv0297. Signed-off-by: Thomas Kaiser Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 21c2858235a81ce4fa1862432eb0c98d8dbdee1e Author: Andrew de Quincey Date: Thu Apr 27 21:45:09 2006 -0300 V4L/DVB (3933): Add isl6421 module Driver for the ISL6421 LNB chip Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit d020542fdaaa69e3061e15d096f11fbc4aeeb93f Author: Andrew de Quincey Date: Thu Apr 27 21:45:01 2006 -0300 V4L/DVB (3932): Convert lnbp21 to a module Convert lnbp21.h into a linux kernel module. Fix up previous users to use it. Convert dvb-ttusb-budget to use it. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 972c3517b792520a513d0ecd897ac6719e46fe0d Author: Adrian Bunk Date: Thu Apr 27 21:06:50 2006 -0300 V4L/DVB (3931): Vivi.c: possible cleanups This patch contains the following possible cleanup: - make needlessly global functions static - remove unused #ifndef kzalloc kzalloc() #define - remove inline's from functions Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab commit 9a8e10e034b268237af77e7ce73a54251eaf9fe2 Author: Mauro Carvalho Chehab Date: Thu Apr 27 18:34:03 2006 -0300 V4L/DVB (3929): Compilation for DVB_AV7110_FIRMWARE seems to be weird Some systems use a previous config information to generate a default config. This seems to cause troubles on some systems. This patch also fixes compilation for AV7110 firmware inside V4L/DVB tree. Signed-off-by: Mauro Carvalho Chehab commit 6b3ccab75ce082f7d63a43903ebd75da4266f77e Author: Andrew de Quincey Date: Thu Apr 20 12:01:47 2006 -0300 V4L/DVB (3895): Additional frontend_init safety checks Don't try and set the tuner ops if the demod was not detected. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 159f8a6eda8c2ee359bb87bf62be70da2da14918 Author: Andrew de Quincey Date: Wed Apr 19 18:31:03 2006 -0300 V4L/DVB (3894): Fix tda10046 tuning I'd missed the i2c gate ctrl function out of the tda10046, so tuning didn't work Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit bd4956b8ec2075e965492647e0c7006a36efe5d9 Author: Andrew de Quincey Date: Tue Apr 18 21:38:49 2006 -0300 V4L/DVB (3893): Convert calls from _pllbuf() to _calc_reg() Johannes Stezenbach suggested this change - definite improvement. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit b12faeffb179e5397c7c443b0e86e447891125a6 Author: Andrew de Quincey Date: Tue Apr 18 17:47:12 2006 -0300 V4L/DVB (3888): Convert cxusb to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Attach dvb-pll where possible. Signed-off-by: Mauro Carvalho Chehab commit 56e0314d7bf56ada38f16edc44bec61741975b4d Author: Andrew de Quincey Date: Tue Apr 18 17:47:12 2006 -0300 V4L/DVB (3886): Convert flexcop-fe-tuner to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Attach dvb-pll where possible. Add pll gate control calls where appropriate. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 30fa61a5ee91bc546f9ebea70c7abda04b5b3e1e Author: Michael Krufky Date: Thu Apr 27 01:31:26 2006 -0300 V4L/DVB (3920): Dvb: rename dvb_pll_tdvs_tua6034 to dvb_pll_lg_tdvs_h06xf Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 9c26c8b169f4a7e2db9a3d5abd3ba74ea032dafd Author: Michael Krufky Date: Thu Apr 27 01:29:17 2006 -0300 V4L/DVB (3919): V4l: rename TUNER_LG_TDVS_H062F to TUNER_LG_TDVS_H06XF Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit fbe60daac4c34e39d1ca69684bcb76e62461ac21 Author: Martin Samuelsson Date: Thu Apr 27 10:17:00 2006 -0300 V4L/DVB (3916): AverMedia 6 Eyes AVS6EYES support Add support for the AverMedia 6 Eyes MJPEG card. - Updated drivers/media/video/Kconfig with AVS6EYES options. - Added CONFIG_VIDEO_ZORAN_AVS6EYES to drivers/media/video/Makefile. - Added I2C_DRIVERID_BT866 and I2C_DRIVERID_KS0127 to include/linux/i2c-id.h - Added drivers/media/video/ks0127.c, imported and modified from the Marvel project. - Added drivers/media/video/ks0127.h, imported and modified from the Marvel project. - Added drivers/media/video/bt866.c, ported from a 2.4 version by Christer Weinigel. - Added AVS6EYES to drivers/media/video/zoran_card.c - Added input_mux to all cards in drivers/media/video/zoran_card.c - Added input mux module parameter to drivers/media/video/zoran_card.c - Added AVS6EYES to card_type in drivers/media/video/zoran.h - Added input_mux to card_info in drivers/media/video/zoran.h - Upped BUZ_MAX_INPUT in drivers/media/video/zoran.h from 8 to 16, as the AVS6EYES has 10. - Updated Documentation/video4linux/Zoran with information about AVS6EYES. Signed-off-by: Martin Samuelsson Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit a87cde0bfbf0020a5d0a80f94a80fc1470546999 Author: Luca Risolia Date: Wed Apr 26 10:19:49 2006 -0300 V4L/DVB (3906): ZC0301 driver updates This is a patch fixing a small bug in zc0301_start_transfer() introduced in the ZC0301 driver v1.04. Signed-off-by: Luca Risolia Signed-off-by: Mauro Carvalho Chehab commit 81ad3428660d06f8faa45eacdf6eb0f1424cd404 Author: Michael Krufky Date: Mon Apr 24 23:21:46 2006 -0300 V4L/DVB (3900): Rename fe_lgh06xf.h to lg_h06xf.h Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit d3b9d6217e8f96d220a94bb5eebc786b62af817b Author: Andrew de Quincey Date: Tue Apr 25 05:36:19 2006 -0300 V4L/DVB (3898): Fix dvb-usb tuner code I had forgotten to rename some of the tuner functions in the refactoring. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit f6adb91c9e9b12b727cf6afb95282d759d103743 Author: Andrew de Quincey Date: Tue Apr 18 21:37:20 2006 -0300 V4L/DVB (3892): Trim documentation Trim excess documentation down to the essentials. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit f54376e275415588d5cb1c54b9edf895391efd71 Author: Andrew de Quincey Date: Tue Apr 18 17:56:10 2006 -0300 V4L/DVB (3891): Convert cx88-dvb to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Attach dvb-pll where possible. Add pll gate control calls where appropriate. Sort out the hybrid cards to work with the revamped mt352/sl10353 demods supporting external tuners. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 8dec073225b0926a26656f416a8d32573205a78f Author: Andrew de Quincey Date: Tue Apr 18 17:47:12 2006 -0300 V4L/DVB (3890): Add support for non-attached tuners to zl10353 Add no_tuner setting like in mt352. Update to use correct tuner API calls. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 4e2eccae27d13d756826533e7cd1214b5825d97c Author: Andrew de Quincey Date: Tue Apr 18 17:47:12 2006 -0300 V4L/DVB (3889): Sort out support for non-attached tuners on mt352 Make it use set_params/pllbuf as appropriate so it works with dvb_pll_attach()ed tuners. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 74aa7a29fea916cb40c98c38e885cc2087c78774 Author: Andrew de Quincey Date: Tue Apr 18 17:47:12 2006 -0300 V4L/DVB (3887): Convert bt8xx to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Attach dvb-pll where possible. Add pll gate control calls where appropriate. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 272bc4db791bc49d50d5f77f24c688be6d1907f8 Author: Andrew de Quincey Date: Tue Apr 18 17:47:12 2006 -0300 V4L/DVB (3885): Convert dvb-pll to be a refactored tuner Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Remove BUG_ON() and convert to a soft error. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit a263394b4866a89860d7b5dbcacf33a32f00d206 Author: Andrew de Quincey Date: Tue Apr 18 17:47:12 2006 -0300 V4L/DVB (3884): Convert dibusb* to refactored tuner code Hook tuner call into tuner_ops. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit aac9ee95ad655593b5b7438714be5a485dc7cb73 Author: Andrew de Quincey Date: Tue Apr 18 17:47:12 2006 -0300 V4L/DVB (3883): Convert digtv to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Add pll gate control calls where appropriate. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 2546b62ee70b2fc0e06814cfdb0ad586356d7a05 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3882): Convert dvb-usb/umt-010 to refactored tuner code Hook tuner call into tuner_ops. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit ee6a2cb65c67c3d87478469f04fd023632dca345 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3881): Convert core dvb-usb pll code to refactored tuner code Rename pll calls to appropriate tuner calls. Add pll gate control calls where appropriate. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 651b81be154ccf001890e77fbd45cdcac079e253 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3880): Convert dvb-ttusb-budget to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Add pll gate control calls where appropriate. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit a79ddae9fe993adab8d728a7a2a6a4038f0861c8 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3879): Convert saa7134-dvb to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Attach dvb-pll where possible. Add pll gate control calls where appropriate. Move europa specific code from tda1104x into card driver using ops overrides (this is how it should ebe done instead of hacking card specific code into the demod driver). Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 2d15fd2f01fc76dc6856a5c551e32e4510f2b492 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3878): Convert ttpci/budget-patch to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Add pll gate control calls where appropriate. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit e87d41c4952ceef7a9f760f38f9343d015279662 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3877): Convert ttpci/budget-av to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Add pll gate control calls where appropriate. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 0f591d409b63999ee8053df9cfbedd77bfbf3b22 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3876): Convert ttpci/budget-ci to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Add pll gate control calls where appropriate. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 067145bdd41bcb090510c73cc6ecd7b09213f038 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3875): Convert ttpci/budget to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Add pll gate control calls where appropriate. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit fa006d86716891657dc8cc9b330b546d1899a7b4 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3874): Convert ttpci/av7110 to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Add pll gate control calls where appropriate. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 4b4c9150dafda804a24885683162a898bcc564f2 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3873): Convert pluto2 to refactored tuner code Rename pll calls to appropriate tuner calls. Remove pll functions from demod structures. Hook tuner call into tuner_ops. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit c72bf909c1d65c4a95fee8c42cf47a5f5a5ff246 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3872): Convert bsbe1/bsru6 to refactored tuner code Convert to tuner_ops call API. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 02269f37727901e326adf52d61512e4f00c85597 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3871): Convert lgdt330x to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 261143ff12eadbf17d7497cd471f70cacaca9586 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3870): Convert dib3000* to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 20b14562852a0d0327b86283d7391f45aa9293ef Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3869): Convert cx24123 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit e994b8d97807536a0f02cff87058d284b29810b7 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3868): Convert zl10353 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Use standardised pllbuf call. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 605ee41c432e550a4e6a4f6fd82013b2989e36a3 Author: Andrew de Quincey Date: Tue Apr 18 17:47:11 2006 -0300 V4L/DVB (3867): Convert nxt6000 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 638a3fba39748b63bdfa391bd65144e487a02e3c Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3866): Convert nxt200x to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Standardise the calls used to retrieve tuner data. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 44d92aa7817efa8f9f80f3bde2279221890a4cd2 Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3865): Convert or51132 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove dvb-pll code - done elsewhere now. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 089e980939ae4f0ff14d1fe816885aa8f00c6e75 Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3864): Convert dvb_dummy_fe to refactored tuner code Make it call the tuner calls - in case someone wants to use it to develop a tuner without a demod. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 81d8a8da8233eb63f783eb3241805ab629b15907 Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3863): Convert cx24110 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Remove unneeded sleep function completely. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit f1e809191c6b960aef721aa6aa8a8c103039d937 Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3862): Convert tda10021 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit d1544ecb3b0589089ddb928affa7bd4255f9442e Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3861): Convert mt352 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointer from structure. Use standardised pllbuf function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit b800aae382bc3f79045ea544ad77bf03398d4443 Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3860): Convert l64871 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit a98af2246b3d0e85566b3b489ffbc8018b21b4a3 Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3859): Convert s5h1420 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 74349bef1a5b5a287721a42bec08c226b095e8b0 Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3858): Convert tda1004x to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Remove europa specific hack (moved into appropriate card driver) Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit e9f9c0d87b1d532b82618bc154246e2dba20934b Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3857): Convert sp8870 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 085542dc8611d969ef698120c98288e24d5f4f9d Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3856): Convert sp887x to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 53a8ee3e903659482e009481ab51d6a6572e6a57 Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3855): Convert stv0299 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Remove extra exported function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 66292ebee9c30e05d5df0229b2fa966883082cd3 Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3854): Convert ves1x93 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 58b119e8a94e2f734cd3e43d1225281ed2d47c11 Author: Andrew de Quincey Date: Tue Apr 18 17:47:10 2006 -0300 V4L/DVB (3853): Convert ves1820 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit d21eac0385dd11d3118ffd374451916fa413c0df Author: Andrew de Quincey Date: Tue Apr 18 17:47:09 2006 -0300 V4L/DVB (3851): Convert tda8083 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 58ac7d36179e27d82e067752b792b1cc573fc590 Author: Andrew de Quincey Date: Tue Apr 18 17:47:09 2006 -0300 V4L/DVB (3850): Convert stv0297 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Remove extra exported pll gate control function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit a81870e00bf502db2c579dcb9721adab3775ba58 Author: Andrew de Quincey Date: Tue Apr 18 17:47:09 2006 -0300 V4L/DVB (3849): Convert mt312 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 0244422220f149d2e930deab89515fd5ca9a6bdd Author: Andrew de Quincey Date: Tue Apr 18 17:47:09 2006 -0300 V4L/DVB (3848): Convert cx22702 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Remove dvb-pll support - done elsewhere now. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 5becb3b045c21001eeeec37bae0738d8ede3a882 Author: Andrew de Quincey Date: Tue Apr 18 17:47:09 2006 -0300 V4L/DVB (3847): Convert cx22700 to refactored tuner code Convert to tuner_ops calls. Remove pll function pointers from structure. Remove unneeded tuner calls. Add i2c gate control function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 7eef5dd6daecf3ee305116c9cf41ae7166270c4c Author: Andrew de Quincey Date: Tue Apr 18 17:47:09 2006 -0300 V4L/DVB (3845): DVB core changes for PLL refactoring Add tuner_ops structure. Add calls into dvb_frontend to support the new tuner architecture. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 7c25039dbb45f3e6a34dabe715107d34d298dc40 Author: Michael Krufky Date: Tue Apr 18 17:47:08 2006 -0300 V4L/DVB (3844): B2c2-flexcop: use fe_lgh06xf.h - removed duplicated tuning code for LG TDVS H061F Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 55bbcdefc525236bd6ed691456923322be4a82c7 Author: Michael Krufky Date: Tue Apr 18 17:47:08 2006 -0300 V4L/DVB (3843): Cxusb: use fe_lgh06xf.h - removed duplicated tuning code for LG TDVS H064F Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 7e557743360104cf71aab1f34df58ef5e7d0b042 Author: Michael Krufky Date: Tue Apr 18 17:47:08 2006 -0300 V4L/DVB (3842): Cx88-dvb: use fe_lgh06xf.h - removed duplicated tuning code for LG TDVS H062F/H064F Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 3d043661064b37f54e8123d17b436aea05da19d6 Author: Michael Krufky Date: Tue Apr 18 17:47:08 2006 -0300 V4L/DVB (3841): Dvb-bt8xx: use fe_lgh06xf.h - removed duplicated tuning code for LG TDVS H064F Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 8f611b87f437703b95b725afe0388e4fb9cd6587 Author: Michael Krufky Date: Tue Apr 18 17:47:08 2006 -0300 V4L/DVB (3840): Create standalone fe_lgh064f header move all pll_set functions for lg-tdvs-h06xf atsc tuners to a standalone header Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 0230185d337be9810eeaf4a873fa1fa9f7bc52bf Author: Luca Risolia Date: Mon Apr 24 11:28:23 2006 -0300 V4L/DVB (3838): ZC0301 driver updates ZC0301 driver updates: - Add support for PB-0330 image sensor - Generic documentation cleanups and updates Signed-off-by: Luca Risolia Signed-off-by: Mauro Carvalho Chehab commit 2b455db6d456ef2d44808a8377fd3bc832e08317 Author: Luc Saillard Date: Mon Apr 24 10:29:46 2006 -0300 V4L/DVB (3835): [PATCH] update pwc driver Add v4l2 compatibility Include the decompressor (legal problem has been resolv by Alan Cox) Faster decoder and easier to maintain, optimize, ... Can export to userland compressed stream Support more cameras, lot of bugs are fixed. Signed-off-by: Luc Saillard Signed-off-by: Mauro Carvalho Chehab commit d9e12f25cf538d103426946121d214dff332efbb Author: Michael Krufky Date: Sat Apr 22 16:15:11 2006 -0300 V4L/DVB (3830): Fix display name for LG TDVS-H06xF This patch fixes the display name for LG TDVS-H06xF tuners in both tuner and dvb-pll modules. Changing the names of the actual pll_desc struct and tuner definitions has been held back until after the dvb tuner refactoring gets merged. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 0b5f56d67821587495eb47014750e2ae7373d635 Author: Valentin Zagura Date: Thu Apr 20 22:56:25 2006 -0300 V4L/DVB (3827): Cx88-blackbird: clean up the buffers when closing the MPEG stream This patch cleans up the buffer queue when the MPEG stream is closed, preventing the message, 'cx8802_timeout' Signed-off-by: Valentin Zagura Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 6fe00b0ed10833a3faf18319be10620ed565bd24 Author: Adrian Bunk Date: Wed Apr 19 20:49:28 2006 -0300 V4L/DVB (3820): Drivers/media/dvb/dvb-usb/: possible cleanups - make the following needlessly global struct static: dvb-usb/cxusb.c: cxusb_mt352_config Signed-off-by: Adrian Bunk Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 01a9cd99cfd5b91ca38df74db60629d76e83cb94 Author: Michael Krufky Date: Tue Apr 18 00:22:09 2006 -0300 V4L/DVB (3817): KWorld HardwareMpegTV XPert: set encoder video standard based on tvnorm The KWorld HardwareMpegTV XPert uses a multistandard tuner, tda8290 + tda8275. Without checking the video standard in blackbird_probe, the encoder defaults to PAL, even if the incoming video stream is NTSC. This patch checks the video standard set by the cx2388x decoder, and sets the encoding height and frame accordingly. This patch is designed to only affect the KWorld HardwareMpegTV XPert. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit c344933af5a8610d71bd0d92fe43a1519ed72ed8 Author: Hans Verkuil Date: Wed Apr 19 18:50:35 2006 -0300 V4L/DVB (3814): Add support for Samsung TCPG 6121P30A PAL tuner. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 8d6cdd235d19c3bb1f86f40bf0305049c1a61955 Author: Michael Krufky Date: Sun Apr 16 13:19:24 2006 -0300 V4L/DVB (3811): Cxusb: lgh064f: set auxiliary byte in pll_set This changeset removes pll_init, and instead sets the tuner auxiliary byte in pll_set. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 3febc04d42d4a0bda64af0c929fdb871370e2a7a Author: Michael Krufky Date: Sun Apr 16 12:17:34 2006 -0300 V4L/DVB (3810): KWorld HardwareMpegTV XPert: Enable Blackbird MPEG encoder support - clear I2SIN to deliver the audio stream to the cx23416 mpeg encoder. - enable blackbird support on the KWorld HardwareMpegTV XPert Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 1b77c54ee11ebe36ce4d0fe805e50aaafa6304b4 Author: Andrew Morton Date: Thu Apr 27 12:01:18 2006 -0300 V4L/DVB (3809a): Remove compat stuff for DMX_GET_EVENT The ioctl were removed by: V4L/DVB (3727): Remove DMX_GET_EVENT and associated data structures due to the ioctl DMX_GET_EVENT has never been implemented, and also scrambling events can't be generated in a useful way by the hardware. This patch removes the corresponding entry at fs/compat_ioctl.c Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab commit 8a17ef975648ce96b6a83b872b6ff4be6fdcd2a4 Author: Michael Krufky Date: Thu Apr 13 18:43:50 2006 -0300 V4L/DVB (3807): Cx88-blackbird: fix typo BLACKBIRD_FIELD1_SAA7115 was repeated. Corrected version reads: blackbird_api_cmd(dev, BLACKBIRD_API_SET_CAPTURE_LINES, 2, 0, BLACKBIRD_FIELD1_SAA7115, BLACKBIRD_FIELD2_SAA7115 ) Thanks-to: Valentin Zagura for pointing this out. Acked-by: Hans Verkuil Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 707f813729a87e4368532e0a53349192ddabb2e1 Author: Michael Krufky Date: Thu Apr 13 17:41:52 2006 -0300 V4L/DVB (3806): Cx88-blackbird: allow proper detection of PAL vs. NTSC video standard - removed test for CX88_BOARD_HAUPPAUGE_ROSLYN prior to determining whether the video standard in use is NTSC or PAL. Acked-by: Hans Verkuil Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 473f54276a814810d4a06616b223a7d6829e1ad5 Author: Andrew de Quincey Date: Thu Apr 13 17:29:07 2006 -0300 V4L/DVB (3805): Fix KNC1 card frontend detection Since I reordered the CI/frontend detection, it turns out the frontend needs to have a GPIO set to power it on; otherwise frontend init fails. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 7a3165a1520c608f10a66588ab48275e1ce253f5 Author: Michael Krufky Date: Thu Apr 13 13:06:28 2006 -0300 V4L/DVB (3801): Cx88-tvaudio: replace 'if' with 'switch..case' This patch cleans up a potential mess that has yet to occur in the card-specific part of cx88-tvaudio.c that sets sound input from external adc. It may be a good idea to move this setting into cx88-cards.c in the future. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit b3038304c91aa710fe651c7f42568e252fc54908 Author: Valentin Zagura Date: Thu Apr 13 12:41:43 2006 -0300 V4L/DVB (3800): Cx88: added support for KWorld MCE 200 Deluxe This patch adds support for KWorld MCE 200 Deluxe. Raw video is working perfectly, MPEG capture using cx88-blackbird is also working, but the quality could be improved. svideo and radio until they can be tested also. Signed-off-by: Valentin Zagura Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 7d0dc26952fe0b49f9139f3264318abf195fe596 Author: Trent Piepho Date: Sun Apr 9 18:48:04 2006 -0300 V4L/DVB (3757): Fix alignment after the replacement from semaphore to muxex Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab commit 5d7dc8c4f667070dbc9a65e93b0e88ba9d19f22a Author: Adrian Bunk Date: Tue Apr 11 10:26:57 2006 -0300 V4L/DVB (3770): Kill drivers/media/common/saa7146_vv_ksyms.c This patch moves the EXPORT_SYMBOL's from drivers/media/common/saa7146_vv_ksyms.c to the files with the actual functions. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab commit a8558577ff5562fe52c2c493e5bbc3dcdec7ce2f Author: Uwe Bugla Date: Tue Apr 11 10:21:37 2006 -0300 V4L/DVB (3769): Fix a type error in dvb_frontend.c Signed-off-by: Uwe Bugla Signed-off-by: Mauro Carvalho Chehab commit ed7f36b6c68a18260798b16ba48ad7b22f54c2e6 Author: Uwe Bugla Date: Tue Apr 11 10:20:34 2006 -0300 V4L/DVB (3768): Fix a tab error in cx14110.c, dprintk Signed-off-by: Uwe Bugla Signed-off-by: Mauro Carvalho Chehab commit 8c99024b88b5da3a73f0575dad98527c9a278d1b Author: Michael Krufky Date: Tue Apr 11 01:46:46 2006 -0300 V4L/DVB (3765): Dvb-bt8xx: add support for DViCO FusionHDTV DVB-T Lite 2nd revision This patch adds support for the new revision of the DViCO FusionHDTV DVB-T Lite, based on the zl10353 demod instead of mt352. Both mt352 and zl10353 revisions of this card have the same PCI subsystem ID. Acked-by: Chris Pascoe Ack'd-by: Manu Abraham Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 20fe4f6599ed300ebd5ef5ef20545a1297c094fa Author: Michael Krufky Date: Mon Apr 10 09:40:40 2006 -0300 V4L/DVB (3764): Lgdt330x: update supported cards list in comments - pcHDTV HD5500 ATSC/QAM uses LG DT3303 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit d09dbf92ada861244056d914a8f68b8be99891ed Author: Andrew de Quincey Date: Mon Apr 10 09:27:37 2006 -0300 V4L/DVB (3762): Add sysfs device links to dvb devices Currently in /sys/class/dvb/dvbX.demuxY/ we have: dev uevent With the patch, we have (for a PCI DVB device): dev device -> ../../../devices/pci0000:00/0000:00:1e.0/0000:03:0d.0 uevent So userspace tools can (finally) work out which physical device a DVB adapter refers to. Previously you had to kinda look through dmesg and hope that it hadn't been dumped out of the buffer. This makes debugging a lot easier if the system has been up for a long time! This is done by adding an extra 'struct device *' parameter to dvb_register_adapter(). It will work with any kind of standard linux 'device'. Additionally, if someone has an embedded system which does things differently, they can simply supply 'NULL' and the behaviour will be as before - the link will simply not appear. Ack'd-by: Manu Abraham Acked-by: Michael Krufky Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 76d313bfea356550a614be51454d526e5090014d Author: Trent Piepho Date: Mon Apr 10 09:27:08 2006 -0300 V4L/DVB (3761): Silence some dprintk's in cx88-mpeg Changeset 395c7c4d8f0c changed several dprintks from level 1 to level 0 (always on). They generate four lines every time DMA starts, which don't containing any information with a use outside of debugging. This turns them back to level 1. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab commit 4286c6f65ec01efa8f5108cadea402ecf3b12279 Author: Mauro Carvalho Chehab Date: Sat Apr 8 16:06:16 2006 -0300 V4L/DVB (3753): Whitespace cleanups at media/radio Signed-off-by: Mauro Carvalho Chehab commit dcdda65fd5e70a698dd3d7e65762e178290284b7 Author: Andrew de Quincey Date: Thu Apr 6 10:37:56 2006 -0300 V4L/DVB (3741): Budget-core doesn't check if register adapter fails If you have more than DVB_MAX_ADAPTERS in your machine, this causes an oops. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 0dbbc0a7ce1acc3a20857f25aa656bf2f5925766 Author: Trent Piepho Date: Thu Apr 6 06:03:09 2006 -0300 V4L/DVB (3739): Add support for FE_GET_FRONTEND to or51132 frontend Adds the FE_GET_FRONTEND ioctl to the or51132 frontend. Current modulation is read from the hardware, while frequency is taken from the driver's state. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab commit e142e7c4186821f03890ff223925cdc7fc963742 Author: Michael Krufky Date: Fri Apr 7 03:24:54 2006 -0300 V4L/DVB (3736): Cx88 cleanup: move CX88_BOARD_PCHDTV_HD5500 to the end of the cards array - new cards should always be added to the end of the list. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit da215d22d82d547c5312f61ac9881ad571e67eea Author: Rusty Scott Date: Fri Apr 7 02:21:31 2006 -0300 V4L/DVB (3735): Add support for pcHDTV HD5500 ATSC/QAM Added card definitions for the pcHDTV HD5500 ATSC/QAM card Signed-off-by: Rusty Scott Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 62838084b4c4c83cd511893132e2d8da84f48813 Author: Andreas Oberritter Date: Wed Apr 5 16:36:51 2006 -0300 V4L/DVB (3727): Remove DMX_GET_EVENT and associated data structures The ioctl DMX_GET_EVENT has never been implemented. I guess no software is using it because of its lack of implementation. Future software won't use it, too, because this API doesn't make much sense the way it is: Frontend events have their own different API. Scrambling events can't be generated in a useful way by the hardware I know of. Signed-off-by: Andreas Oberritter Signed-off-by: Mauro Carvalho Chehab commit 68ef505e31bb182131c208d139c9b6da33d8d330 Author: Trent Piepho Date: Tue Apr 4 09:30:33 2006 -0300 V4L/DVB (3724): Remove a wee bit of cruft A few lines that do nothing in the or51132 frontend, removed. Signed-off-by: Trent Piepho Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 87184554722b9d06154d70a48aa63ad744ef3fa9 Author: Trent Piepho Date: Tue Apr 4 09:30:29 2006 -0300 V4L/DVB (3723): Avoid unnecessary firmware re-loads in or51132 frontend As QAM_64, QAM_256, and QAM_AUTO all use the same firmware, switching between these modulations doesn't require a firmware re-load. This also fixes a mishandled error condition, in which the firmware file is loaded into the kernel, the clock mode is changed, but then the firmware upload to the device fails. The modulation change is aborted, but the clock mode would still be changed. Signed-off-by: Trent Piepho Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 005b541f884975544594ceb8f2ff81b623500745 Author: Trent Piepho Date: Tue Apr 4 01:56:30 2006 -0300 V4L/DVB (3721): Fix spelling It's "Terrestrial" Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab commit d147ed2aa46c3cfcbfeadb5d689e80b14cf1f160 Author: Michael Krufky Date: Mon Apr 3 01:29:09 2006 -0300 V4L/DVB (3720): Fix spelling error / typo in comments Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit c3291069c2c22c3154e0809345f34ec9962d7d24 Author: Michael Krufky Date: Sun Apr 2 19:11:10 2006 -0300 V4L/DVB (3718): Removed trailing newlines Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab commit 2e7c6dc3989136844eb63e05f9e4dc6608a763c6 Author: Mauro Carvalho Chehab Date: Mon Apr 3 07:53:40 2006 -0300 V4L/DVB (3715): Change all emails to the currently used one. Signed-off-by: Mauro Carvalho Chehab commit c7c0b34c27bbf0671807e902fbfea6270c8f138d Author: Hans Verkuil Date: Sun Apr 2 13:35:00 2006 -0300 V4L/DVB (3712): Fix video input setting of em28xx, use _INT_S_VIDEO_ROUTING in tvp5150 - Use new routing input defines in em28xx-cards.c - Fix S-Video settings for tvp5150-based cards (input was copied from saa7115 based cards and worked only because S-Video was selected in the default: case) - Replace VIDIOC_S_INPUT by VIDIOC_INT_S_VIDEO_ROUTING in em28xx-video.c - Remove the now obsolete VIDIOC_S_INPUT handler in saa7115.c - Add VIDIOC_INT_G/S_VIDEO_ROUTING in tvp5150.c - Add new media/tvp5150.h with the routing defines. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit b7f8292c96463810edfecff70dd4631d47e5a36b Author: Hans Verkuil Date: Sun Apr 2 12:50:42 2006 -0300 V4L/DVB (3711): Add support for VIDIOC_INT_S_CRYSTAL_FREQ internal command. Some saa7115-based cards use a different crystal frequency and a different audio clock generation. Add a new VIDIOC_INT_S_CRYSTAL_FREQ command to be able to set these values. Also change the default APLL setting to 0. It makes no sense to have the audio clock independent from the video clock, this can lead to audio/video synchronization problems. Setting this to 0 is also consistent with the old saa7114.c source and the way the Hauppauge Windows driver sets it. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 2eb606db1134ce860cc0cbf8b533b6315d182e21 Author: Hans Verkuil Date: Sun Apr 2 08:21:02 2006 -0300 V4L/DVB (3709): Improve line-in handling - improve handling of the EXTERN input: don't start an unnecessary carrier scan - improve the LOG_STATUS output - ensure that a carrier scan is started again when switching back to the tuner. - set correct prescale for L-NICAM Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab commit 0ead09180a0620eaef761da84259262bfcf21090 Author: Trent Piepho Date: Sun Apr 2 20:40:33 2006 -0300 V4L/DVB (3708a): Clean up some cruft in or51132 frontend There is some old code in the or51133 firmware loading function that has no effect. Left a comment to in case it helps someone trying to reverse engineer the chip. Signed-off-by: Trent Piepho Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab commit 83626b01275d0228516b4d97da008328fc37c934 Author: Linus Torvalds Date: Sat Jun 24 17:47:09 2006 -0700 Revert "[PATCH] usb: drivers/usb/core/devio.c dereferences a userspace pointer" This reverts commit 786dc1d3d7333f269e17d742886eac2188a2d9cc. As Al so eloquently points out, the patch is crap. The old code was fine, the new code was bogus. It never dereferenced a user pointer, the "->" operator was to an array member, which gives the _address_ of the member (in user space), not an actual dereference at all. Signed-off-by: Linus Torvalds commit 85fe068123aa11d3477ce88c7d365e233b1f2e10 Author: Daniel Jacobowitz Date: Sat Jun 24 23:46:21 2006 +0100 [ARM] 3648/1: Update struct ucontext layout for coprocessor registers Patch from Daniel Jacobowitz In order for userspace to find saved coprocessor registers, move them from struct rt_sigframe into struct ucontext. Also allow space for glibc's sigset_t, so that userspace and kernelspace can use the same ucontext layout. Define the magic numbers for iWMMXt in the header file for easier reference. Include the size of the coprocessor data in the magic numbers. Also define magic numbers and layout for VFP, not yet saved. Signed-off-by: Daniel Jacobowitz Signed-off-by: Russell King commit 070b98bfda3d27269519067c1c67eaef695f3e0c Author: Sam Ravnborg Date: Sun Jun 25 00:07:55 2006 +0200 kbuild: trivial fixes in Makefile Signed-off-by: Sam Ravnborg commit e838db685fcfd2e9a0548ffc5cb9447e6c3c11be Author: Masatake YAMATO Date: Thu Jun 22 12:21:20 2006 +0900 kbuild: adding symbols in Kconfig and defconfig to TAGS I'm using TAGS generated from "make TAGS" to read the kernel source code. When I met a ifdef block #ifdef CONFIG_FOO ... #endif in the soruce code I would like to know the meaning CONFIG_FOO to decide whether I should read inside the ifdef block or not. meaning CONFIG_FOO is well documented in Kconfig. So it is nice if I can jump to CONFIG_FOO entry in Kconfig from "#ifdef CONFIG_FOO" with the tag jump. Here is the patch to add symbols in Kconfig and defconfig to TAGS in "make TAGS" operation. Signed-off-by: Masatake YAMATO Signed-off-by: Sam Ravnborg commit d02f40e81e003be6ddba5c176f2e40ea290c3729 Author: Linus Torvalds Date: Sat Jun 24 14:32:18 2006 -0700 Enable minimal per-device resume tracing This is the minimal resume trace code to find which device resume (if any) results in problems. Usually, you'd use the information this generates as a starting point to adding more fine-grained trace event points. Signed-off-by: Linus Torvalds commit 6803dc0ea85ad21b2cb3ec88decff5e27d7a390b Author: Sam Ravnborg Date: Sat Jun 24 23:46:54 2006 +0200 kbuild: replace abort() with exit(1) We have had no use of the coredump file for a long time. So just exit(1) and avoid coredumping. Signed-off-by: Sam Ravnborg commit eb71c87a492b7090ff9e8ac46912c480a1687e38 Author: Linus Torvalds Date: Sat Jun 24 14:27:42 2006 -0700 Add some basic resume trace facilities Considering that there isn't a lot of hw we can depend on during resume, this is about as good as it gets. This is x86-only for now, although the basic concept (and most of the code) will certainly work on almost any platform. Signed-off-by: Linus Torvalds commit 15fde6751886fd972a64ed65ba49db309919c504 Author: Andreas Gruenbacher Date: Tue May 9 20:37:30 2006 +0200 kbuild: support for %.symtypes files Here is a patch that adds a new -T option to genksyms for generating dumps of the type definition that makes up the symbol version hashes. This allows to trace modversion changes back to what caused them. The dump format is the name of the type defined, followed by its definition (which is almost C): s#list_head struct list_head { s#list_head * next , * prev ; } The s#, u#, e#, and t# prefixes stand for struct, union, enum, and typedef. The exported symbols do not define types, and thus do not have an x# prefix: nfs4_acl_get_whotype int nfs4_acl_get_whotype ( char * , t#u32 ) The symbol type defintion of a single file can be generated with: make fs/jbd/journal.symtypes If KBUILD_SYMTYPES is defined, all the *.symtypes of all object files that export symbols are generated. The single *.symtypes files can be combined into a single file after a kernel build with a script like the following: for f in $(find -name '*.symtypes' | sort); do f=${f#./} echo "/* ${f%.symtypes}.o */" cat $f echo done \ | sed -e '\:UNKNOWN:d' \ -e 's:[,;] }:}:g' \ -e 's:\([[({]\) :\1:g' \ -e 's: \([])},;]\):\1:g' \ -e 's: $::' \ $f \ | awk ' /^.#/ { if (defined[$1] == $0) { print $1 next } defined[$1] = $0 } { print } ' When the kernel ABI changes, diffing individual *.symtype files, or the combined files, against each other will show which symbol changes caused the ABI changes. This can save a tremendous amount of time. Dump the types that make up modversions Signed-off-by: Andreas Gruenbacher Signed-off-by: Sam Ravnborg commit ca195cfec9fff622a61b1b72534e73360747f735 Author: Russell King Date: Sat Jun 24 22:41:09 2006 +0100 [ARM] Add identifying number for non-rt sigframe GDB couldn't reliably tell the difference between the old and new non-rt sigframes, so provide it with a number at the beginning which will never appear in the old sigframe, and hence provide gdb with a reliable way to tell the two apart. Signed-off-by: Russell King commit 3041e47e8b08d51188b2cbdbd9c1e6f43314c8f1 Author: Roman Zippel Date: Sun Jun 18 21:09:09 2006 -0700 kbuild: fix silentoldconfig recursion kconfig-fix-config-dependencies causes this: make CC=cc KBUILD_VERBOSE=1 -C /usr/src/25 SUBDIRS=/home/akpm/NVIDIA-Linux-x86_64-1.0-8762-pkg2/usr/src/nv modules make -f /usr/src/devel/Makefile silentoldconfig make -f /usr/src/devel/Makefile silentoldconfig make -f /usr/src/devel/Makefile silentoldconfig The basic problem is if we compile external modules, config-targets isn't set which can cause recursive calls to silentoldconfig to update the kernel configuration. Bail out and ask the user to update manually. Signed-off-by: Sam Ravnborg commit ac031f26e89cc04fc7504f31ae137857eb83a051 Author: Theodore Ts'o Date: Wed Jun 21 20:53:09 2006 -0400 kbuild: add option for stripping modules while installing them Add option for stripping modules while installing them. This function adds support for stripping modules while they are being installed. CONFIG_DEBUG_KERNEL (which will probably become more popular as developers use kdump) causes the size of the installed modules to grow by a factor of 9 or so. Some kernel package systems solve this problem by stripping the debug information from /lib/modules after running "make modules_install", but that may not work for people who are installing directly into /lib/modules --- root partitions that were sized to handle 16 megs worth of modules may not be quite so happy with 145 megs of modules, so the "make modules_install" never succeeds. This patch allows such users to request modules_install to strip the modules as they are installed. Signed-off-by: "Theodore Ts'o" Signed-off-by: Sam Ravnborg commit 468d949401d729b28eed6ea5be25695c5731d3f1 Author: Al Viro Date: Fri Jun 23 23:22:43 2006 +0100 kbuild: kill some false positives from modpost Signed-off-by: Al Viro Signed-off-by: Sam Ravnborg commit c5e3003381f4e39773a1758a9eb68dff9740a56c Author: Ram Pai Date: Fri Jun 23 16:44:38 2006 -0700 kbuild: export-symbol usage report generator The following patch provides the ability to generate a report of (1) All the exported symbols and their in-kernel-module usage count (2) For each module, lists the modules and their exported symbols, on which it depends. the report can be generated by executing: perl scripts/export_report The tool warns if the modules are not build using MODVERSIONING. Signed-off-by: Ram Pai Signed-off-by: Sam Ravnborg commit e5c44fd88c146755da6941d047de4d97651404a9 Author: Sam Ravnborg Date: Sat Jun 24 22:50:18 2006 +0200 kbuild: fix make -rR breakage make failed to supply the filename when using make -rR and using $(*F) to get target filename without extension. This bug was not reproduceable in small scale but using: $(basename $(notdir $@)) fixes it with same functionality. Signed-off-by: Sam Ravnborg commit c9b949a734adef5d05cbaa0b0546b924ca517155 Author: Ben Dooks Date: Sat Jun 24 21:22:35 2006 +0100 [ARM] 3647/1: S3C24XX: add Osiris to the list of simtec pm machines Patch from Ben Dooks Enable power management for Simtec Osiris Signed-off-by: Ben Dooks Signed-off-by: Russell King commit a019f4a9a7b4ec4986918e9aefa06815cf77b714 Author: Ben Dooks Date: Sat Jun 24 21:21:37 2006 +0100 [ARM] 3645/1: S3C2412: irq support for external interrupts Patch from Ben Dooks Move the decoding of the IRQ_EXT4 and above out of the entry macro, and into an chained irq handler as the EXTINT registers move depending on the CPU being used. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 22346aea8d39372d6fd207468701e90bf546b882 Author: Ben Dooks Date: Sat Jun 24 21:21:36 2006 +0100 [ARM] 3643/1: S3C2410: Add new usb clocks Patch from Ben Dooks Make the S3C2410 use the same usb clock naming as the S3C2412 Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 66c594098db1ee885f486a684b66937e28e792b1 Author: Ben Dooks Date: Sat Jun 24 21:21:35 2006 +0100 [ARM] 3642/1: S3C24XX: Add machine SMDK2413 Patch from Ben Dooks Add basic support for the Samsung/Aiji SMDK2413 Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 44cc7c9c15124c4506da96304e5f9eb88200fc35 Author: Ben Dooks Date: Sat Jun 24 21:21:33 2006 +0100 [ARM] 3641/1: S3C2412: Fixup gpio register naming Patch from Ben Dooks The current S3C2412 has used to moving S3C24XX_ for the generic form of an register has been moved from the S3C2410. Fixup S3C2410_EXTINTx and S3C2410_EINFLTx to S3C24XX_EXTINTx and S3C24XX_EXTINTx Depends on Patch #3635/1, Patch #3640/1 Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 46491c94d39a519178ba8c6b5b5d6a839210124d Author: Ben Dooks Date: Sat Jun 24 21:21:32 2006 +0100 [ARM] 3640/1: S3C2412: Use S3C24XX_DCLKCON instead of S3C2410_DCLKCON Patch from Ben Dooks The current S3C2412 support has moved to using S3C24XX_DCLKCON unless the specific DCLKCON is required (S3C2412_DCLKCON or S3C2410_DKCLKCON) Move the few places using S3C2410_DCLKCON to S3C24XX_DCLKCON Depends on Patch #3635/1 Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 73e55cb3b3549d0174d1dadb755200938232e8d0 Author: Ben Dooks Date: Sat Jun 24 21:21:32 2006 +0100 [ARM] 3639/1: S3C2412: serial port support Patch from Ben Dooks Serial port support for the on-board UART blocks on the Samsung S3C2412 and S3C2413 UARTs. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 736855f0c748dacb624070b8d6ffffe4532cf4dc Author: Ben Dooks Date: Sat Jun 24 21:21:31 2006 +0100 [ARM] 3638/1: S3C2412: core clocks Patch from Ben Dooks Clock support for the clocks on the Samsung S3C2412 and S3C2413 SoCs. This provides clock enables and parent selection for all the standard clocks. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 513846f82829efd5bab5359bdc33509e6386fd49 Author: Ben Dooks Date: Sat Jun 24 21:21:29 2006 +0100 [ARM] 3637/1: S3C24XX: Add mpll clock, and set as fclk parent Patch from Ben Dooks Update the clocks with the MPLL clock, and use it as the parent. Also export these to the rest of arch/arm/mach-s3c2410 Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 3434d9d9fc0fec0b96ab128ee0d743b6a0d90160 Author: Ben Dooks Date: Sat Jun 24 21:21:28 2006 +0100 [ARM] 3636/1: S3C2412: Add selection of CPU_ARM926 Patch from Ben Dooks Select CONFIG_CPU_ARM926 when CONFIG_CPU_S3C2412 is selected. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 68d9ab394f06f95fd4ca612c08edf13e410fd8d0 Author: Ben Dooks Date: Sat Jun 24 21:21:27 2006 +0100 [ARM] 3635/1: S3C24XX: Add S3C2412 core cpu support Patch from Ben Dooks Add support for the Samsung S3C2412 and S3C2413 range of SoCs. This patch contains the core identification, debug macros, and basic register updates to get these to build. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit a3ff55026e59687040f00fc35680fc0e774859f4 Author: Ben Dooks Date: Sat Jun 24 21:21:26 2006 +0100 [ARM] 3633/1: S3C24XX: s3c2410 gpio bugfix - wrong pin nos Patch from Ben Dooks The s3c2410 gpio functions have a pair of bugs where the code is using the pin function definitions instead of the pin gpio numbers. Also remove the changelog Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 82b145c5a572f7fa7211dffe2097234dc91bcecc Author: Chuck Lever Date: Tue Jun 20 12:57:03 2006 -0400 NFS: alloc nfs_read/write_data as direct I/O is scheduled Re-arrange the logic in the NFS direct I/O path so that nfs_read/write_data structs are allocated just before they are scheduled, rather than allocating them all at once before we start scheduling requests. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust commit 06cf6f2ed0b19629700794727d86ed57b9c0583e Author: Chuck Lever Date: Tue Jun 20 12:56:49 2006 -0400 NFS: Eliminate nfs_get_user_pages() Neil Brown observed that the kmalloc() in nfs_get_user_pages() is more likely to fail if the I/O is large enough to require the allocation of more than a single page to keep track of all the pinned pages in the user's buffer. Instead of tracking one large page array per dreq/iocb, track pages per nfs_read/write_data, just like the cached I/O path does. An array for pages is already allocated for us by nfs_readdata_alloc() (and the write and commit equivalents). This is also required for adding support for vectored I/O to the NFS direct I/O path. The original reason to pin the user buffer and allocate all the NFS data structures before trying to schedule I/O was to ensure all needed resources are allocated on the client before starting to send requests. This reduces the chance that resource exhaustion on the client will cause a short read or write. On the other hand, for an application making very large application I/O requests, this means that it will be nearly impossible for the application to make forward progress on a resource-limited client. Thus, moving the buffer pinning functionality into the I/O scheduling loops should be good for scalability. The next patch will do the same for NFS data structure allocation. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust commit 9c93ab7dff5eb22027ab15010557bb73f9b44c99 Author: Chuck Lever Date: Tue Jun 20 12:56:31 2006 -0400 NFS: refactor nfs_direct_free_user_pages Clean-up and fix a minor bug: the logic was dirtying page cache pages on both read and write operations. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust commit 51a7bc6caec94bab256b272bffd24d00ea81c698 Author: Chuck Lever Date: Tue Jun 20 12:56:16 2006 -0400 NFS: remove user_addr, user_count, and pos from nfs_direct_req Make the user_addr, user_count, and pos parameters explicit to the scheduler routines, and remove the fields from nfs_direct_req. The iovec API will be passing in a series of these, not just one set. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust commit fedb595c66e1fbd5acafe0d43b7e95c13c936d61 Author: Chuck Lever Date: Tue Jun 20 12:55:45 2006 -0400 NFS: "open code" the NFS direct write rescheduler An NFSv3/v4 client must reschedule on-the-wire writes if the writes are UNSTABLE, and the server reboots before the client can complete a subsequent COMMIT request. To support direct asynchronous scatter-gather writes, the write rescheduler in fs/nfs/direct.c must not depend on the I/O parameters in the controlling nfs_direct_req structure. iovecs can be somewhat arbitrarily complex, so there could be an unbounded amount of information to save for a rarely encountered requirement. Refactor the direct write rescheduler so it uses information from each nfs_write_data structure to reschedule writes, instead of caching that information in the controlling nfs_direct_req structure. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust commit b1c5921c5b715c207d7fe77cd7aaafbb322f09f5 Author: Chuck Lever Date: Tue Jun 20 12:55:19 2006 -0400 NFS: Separate functions for counting outstanding NFS direct I/Os Factor out the logic that increments and decrements the outstanding I/O count. This will be a commonly used bit of code in upcoming patches. Also make this an atomic_t again, since it will be very often manipulated outside dreq->spin lock. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust commit 52e3e772a098274df3c6f5f1ad58cd7fe24089bf Author: Andrew Victor Date: Sat Jun 24 09:58:14 2006 +0100 [ARM] 3631/1: Remove legacy __mem_isa() definitions Patch from Andrew Victor Remove the remaining legacy __mem_isa() definitions for the ARM platforms. Signed-off-by: Andrew Victor Signed-off-by: Russell King commit fc8ea7a1eae3034505f70f02981d33bbc1284a86 Author: Lennert Buytenhek Date: Sat Jun 24 09:57:14 2006 +0100 [ARM] 3644/1: ixp2000: export gpio_line_config() Patch from Lennert Buytenhek Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit 1f64eb379cfc95d5f627b779685f7ac6721df322 Author: Lennert Buytenhek Date: Sat Jun 24 10:33:03 2006 +0100 [ARM] 3646/1: ep93xx: instantiate ep93xx-ohci platform device Patch from Lennert Buytenhek The ep93xx ohci bits have been merged into the gregkh-2.6 tree, which means that they will probably go upstream soon, so make the core ep93xx code instantiate an appropriate ep93xx-ohci platform device. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit 1d81eedb8f6c13c262a70b8167530ec24b09c0ff Author: Lennert Buytenhek Date: Sat Jun 24 10:33:02 2006 +0100 [ARM] 3634/1: ep93xx: initial implementation of the clk_* API Patch from Lennert Buytenhek Add an initial implementation of the clk_* API for the cirrus ep93xx to the tree. The initial implementation is somewhat minimal, with the intention of extending it as we go along. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit 3da4bd2bfc672a484d2a5df9f89b79f5e1e634dc Author: Lennert Buytenhek Date: Sat Jun 24 09:57:13 2006 +0100 [ARM] 3632/1: iwmmxt: fix up argument comment for iwmmxt_task_restore() Patch from Lennert Buytenhek Commit d6551e884cf66de072b81f8b6d23259462c40baf forgot to update the description of what goes into r2 when calling iwmmxt_task_restore(). Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit c499aeb08cb24bed60e5bfc80720597bcf1a720d Author: Dave Airlie Date: Sat Jun 24 17:37:48 2006 +1000 drm: radeon constify radeon microcode From: Tilman (DRM CVS) Signed-off-by: Dave Airlie commit 702880f24373dfb31edb0bcd997ff924d07decc3 Author: Dave Airlie Date: Sat Jun 24 17:07:34 2006 +1000 Add i915 ioctls to configure pipes for vblank interrupt. i915 vblanks can be generated from either pipe a or b, however a disabled pipe generates no interrupts. This change allows the X server to select which pipe generates vblank interrupts. From: Keith Packard via DRM CVS Signed-off-by: Dave Airlie commit d6fece051a4ef330922bfafb9d64e3e133e3a8a6 Author: Dave Airlie Date: Sat Jun 24 17:04:07 2006 +1000 drm: update radeon to 1.25 add r200 vertex program support Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, and new packet type for making it possible to address whole tcl vector space and have a larger count) From: Roland Scheidegger (DRM CVS) Signed-off-by: Dave Airlie commit f2a2279ffc0dfd27f6909184a29910e40ae7eebd Author: Dave Airlie Date: Sat Jun 24 16:55:34 2006 +1000 drm: radeon add a tcl state flush before accessing tcl vector space Do a tcl state flush before accessing tcl vector space. This fixes some more problems with flickering (bug #6637). drm may not be appropriate place for this, since doing that flush there might both be overkill and insufficient in some cases. However, it's hard to figure out when that flush is needed, so this has to suffice. There does not seem to be a performance penalty associated with it. From: Roland Scheidegger (DRM CVS) Signed-off-by: Dave Airlie commit 0fe6e2d2928e089d16ec5ed7ba634c1d60916020 Author: Al Viro Date: Fri Jun 23 06:05:39 2006 +0100 intelfb delousing ring_head is offset in card memory, not iomem pointer. Fixed, removed fuckloads of amazingly bogus casts somebody had sprinkled all over the place. Signed-off-by: Al Viro Signed-off-by: Dave Airlie commit 1812fd40725c13cf050c29791a6dd35d593eb8d8 Author: David S. Miller Date: Fri Jun 23 23:17:48 2006 -0700 [SPARC64]: Update defconfig. Signed-off-by: David S. Miller commit b5ba0740f852f4ad86ba7f21267bc77027d60703 Author: David S. Miller Date: Fri Jun 23 22:46:49 2006 -0700 [SPARC64]: Make auxio a real driver. Signed-off-by: David S. Miller commit 4f62d158a32d9f470377a7bd6dcb797b42afe5f3 Author: David S. Miller Date: Fri Jun 23 22:22:13 2006 -0700 [PARPORT] sunbpp: Convert to new SBUS device framework. Signed-off-by: David S. Miller commit 9eccf1b3121f7e407d3159908f29252887194a16 Author: David S. Miller Date: Fri Jun 23 22:12:39 2006 -0700 [Documentation]: Update probing info in sbus_drivers.txt Signed-off-by: David S. Miller commit 3d4253d9afabd6d42c33812a839ba67b8c9bbe49 Author: David S. Miller Date: Fri Jun 23 22:00:34 2006 -0700 [SCSI] qlogicpti: Convert to new SBUS device framework. Signed-off-by: David S. Miller commit 7bd5ed5dd4f12ba56c99c9b5a8838afbf121f397 Author: David S. Miller Date: Fri Jun 23 21:58:34 2006 -0700 [SCSI] esp: Fix bug in esp_remove_common. Do not try to kfree(esp), scsi_host_put() takes care of that. Signed-off-by: David S. Miller commit 96399487ad84b0d935923fe3652943159f36fb64 Author: David S. Miller Date: Fri Jun 23 21:36:46 2006 -0700 [NET] sunhme: Kill useless loop over sdevs in quattro_sbus_find(). Signed-off-by: David S. Miller commit c0442209e41b3453736ef974ee709a6ae15d99fb Author: David S. Miller Date: Fri Jun 23 21:33:44 2006 -0700 [NET] myri_sbus: Kill unused next_module struct member. Signed-off-by: David S. Miller commit a46c30fd62636d5d0f4209fed79c99c01dd58218 Author: David S. Miller Date: Fri Jun 23 21:32:48 2006 -0700 [NET] myri_sbus: Convert to new SBUS device layer. Signed-off-by: David S. Miller commit ecba38abfdaf012713b661177c2a6db12bb996c3 Author: David S. Miller Date: Fri Jun 23 21:23:01 2006 -0700 [NET] sunqe: Convert to new SBUS driver layer. Signed-off-by: David S. Miller commit 52a34c7fe43afcbcd0e1ecfdef6b3dfdb9a90180 Author: David S. Miller Date: Fri Jun 23 18:48:04 2006 -0700 [NET] sunbmac: Convert over to new SBUS device framework. Signed-off-by: David S. Miller commit c2d81e63ced3e81b8b71087b9af44da26171ba36 Author: David S. Miller Date: Fri Jun 23 18:39:40 2006 -0700 [NET] sunlance: Convert to new SBUS driver framework. Signed-off-by: David S. Miller commit 050bbb196392b9c178f82b1205a23dd2f915ee93 Author: David S. Miller Date: Fri Jun 23 18:21:02 2006 -0700 [NET] sunhme: Convert to new SBUS driver framework. And make it a real PCI driver too. Signed-off-by: David S. Miller commit 9e326acf567b605cf4177081cc7367c24ec10a66 Author: David S. Miller Date: Fri Jun 23 17:31:12 2006 -0700 [NET] sunhme: Kill __sparc__ and __sparc_v9__ ifdefs. Use CONFIG_SPARC and CONFIG_SPARC64 instead. Signed-off-by: David S. Miller commit 411aa5540536feace62c97478a8ea5dab7469377 Author: David S. Miller Date: Fri Jun 23 17:29:28 2006 -0700 [SCSI] sparc: Port esp to new SBUS driver layer. This also turns the driver into a new-style scsi driver. Signed-off-by: David S. Miller commit 69b5c4f18b2ceab3da9e854d02f8d9a2aa5b8431 Author: David S. Miller Date: Fri Jun 23 16:23:12 2006 -0700 [SOUND] sparc: Port amd7930 to new SBUS device layer. Signed-off-by: David S. Miller commit 576c352e89e57cfa6c9f493e549d10d86f60a0cf Author: David S. Miller Date: Fri Jun 23 15:55:45 2006 -0700 [SBUS]: Rewrite and plug into of_device framework. I severely apologize, I was still learning how to program in C when I wrote this stuff 10 years ago... Signed-off-by: David S. Miller commit fd5314311634245172d40ccb418d89dac91d6ad6 Author: David S. Miller Date: Fri Jun 23 15:55:17 2006 -0700 [SPARC]: Port of_device layer and make ebus use it. Signed-off-by: David S. Miller commit 942a6bdd1c4d2419a42be77ba1c964e4ba8dae9e Author: David S. Miller Date: Fri Jun 23 15:53:31 2006 -0700 [SPARC]: Port sparc64 in-kernel device tree code to sparc32. Signed-off-by: David S. Miller commit a2bd4fd17926d715a470fbe0ebe05128ba410984 Author: David S. Miller Date: Fri Jun 23 01:44:10 2006 -0700 [SPARC64]: Add of_device layer and make ebus/isa use it. Sparcspkr and power drivers are converted, to make sure it works. Eventually the SBUS device layer will use this as a sub-class. I really cannot cut loose on that bit until sparc32 is given the same infrastructure. Signed-off-by: David S. Miller commit 8cd24ed4f8031636fb5dacb04adee9e02556ecd5 Author: David S. Miller Date: Thu Jun 22 22:08:58 2006 -0700 [SPARC64]: Expand of_*() interfaces some more. Import some more stuff from powerpc. Add of_device_is_compatible(), and of_find_compatible_node(). Export some more of the other routines to modules. Signed-off-by: David S. Miller commit 92c4e22593c22eb0943b232c61c98b517081637d Author: David S. Miller Date: Thu Jun 22 20:23:56 2006 -0700 [SPARC64]: Kill unused local vars in map_prom_timers(). Signed-off-by: David S. Miller commit 25c7581bcdd11cf9b82a8ef062a10bea310cc9e9 Author: David S. Miller Date: Thu Jun 22 20:21:22 2006 -0700 [SPARC64]: Kill off some more prom_getproperty() remnants. The remaining ones occur before we have imported the device tree. Signed-off-by: David S. Miller commit 44bdef5e8f2e64ba5974b587989a829d57126bad Author: David S. Miller Date: Thu Jun 22 20:04:30 2006 -0700 [SPARC64]: Convert Cheetah memory controller driver to in-kernel PROM tree. Signed-off-by: David S. Miller commit cecc4e9222c4e2bca59834750e493eea6be97613 Author: David S. Miller Date: Thu Jun 22 19:53:24 2006 -0700 [SPARC64]: Convert central bus layer to in-kernel PROM device tree. Signed-off-by: David S. Miller commit 9c10a58ed634d98114c5717e2da761d8a63f2cd4 Author: David S. Miller Date: Thu Jun 22 19:31:11 2006 -0700 [SPARC64]: Kill ebus/isa range and interrupt mapping struct members. Unused outside of initial bus probe scan. Signed-off-by: David S. Miller commit 690c8fd31f1e35985d0f35772fde514da59ec9d1 Author: David S. Miller Date: Thu Jun 22 19:12:03 2006 -0700 [SPARC64]: Use in-kernel PROM tree for EBUS and ISA. Signed-off-by: David S. Miller commit de8d28b16f5614aeb12bb69c8f9a38578b8d3ada Author: David S. Miller Date: Thu Jun 22 16:18:54 2006 -0700 [SPARC64]: Convert sparc64 PCI layer to in-kernel device tree. One thing this change pointed out was that we really should pull the "get 'local-mac-address' property" logic into a helper function all the network drivers can call. Signed-off-by: David S. Miller commit 765b5f32730cfd2608291e679060b0391570c8b3 Author: David S. Miller Date: Thu Jun 22 00:49:15 2006 -0700 [SPARC64]: Must run smp_setup_cpu_possible_map() after paging_init() Otherwise the in-kernel PROM device tree isn't built yet, and therefore the present cpu bits don't get set properly. Signed-off-by: David S. Miller commit c2a5a46be4a1c682e18e29e67785126b7610b14d Author: David S. Miller Date: Thu Jun 22 00:01:56 2006 -0700 [SPARC64]: Fix for Niagara memory corruption. On some sun4v systems, after netboot the ethernet controller and it's DMA mappings can be left active. The net result is that the kernel can end up using memory the ethernet controller will continue to DMA into, resulting in corruption. To deal with this, we are more careful about importing IOMMU translations which OBP has left in the IO-TLB. If the mapping maps into an area the firmware claimed was free and available memory for the kernel to use, we demap instead of import that IOMMU entry. This is going to cause the network chip to take a PCI master abort on the next DMA it attempts, if it has been left going like this. All tests show that this is handled properly by the PCI layer and the e1000 drivers. Signed-off-by: David S. Miller commit 486ad10a7e1b2bb61ea9e48c4d9510f50cd74fc5 Author: David S. Miller Date: Thu Jun 22 00:00:00 2006 -0700 [SPARC64]: Minor bug fix to obp_read_memory(). If we end up zero'ing out the size of one of the entries, pop it out of the array completely because some code that examines these things cannot handle a zero length element properly. Signed-off-by: David S. Miller commit 07f8e5f358a0b7240f1dad6b3819f2fd1103f159 Author: David S. Miller Date: Wed Jun 21 23:34:02 2006 -0700 [SPARC64]: Convert cpu_find_by_*() interface to in-kernel PROM device tree. Signed-off-by: David S. Miller commit 6d307724cb6a6b8466cad4fdf13d8a409bc2433f Author: David S. Miller Date: Wed Jun 21 23:07:29 2006 -0700 [SPARC64]: Add of_getintprop_default(). This encodes a common idiomatic coding pattern used when dealing with integer properties. Signed-off-by: David S. Miller commit 6760d28bc691bb255c501c9b680f2fc1162258b2 Author: David S. Miller Date: Wed Jun 21 22:56:20 2006 -0700 [SPARC64]: Convert sun4v virtual-device layer to in-kernel PROM device tree. Signed-off-by: David S. Miller commit 27cc64c7cc9e41788e53655c717aeca2f55f2041 Author: David S. Miller Date: Wed Jun 21 22:31:08 2006 -0700 [SPARC64]: Rate limited kernel unaligned trap logging, ala IA64. Signed-off-by: David S. Miller commit 20edac8ad487b784a286c1e59cc24819cb8d3b86 Author: David S. Miller Date: Wed Jun 21 22:07:21 2006 -0700 [SPARC64]: Disable verbose PCI IRQ probing messages by default. Allow them to be enabled with "pci=irq_verbose" on the boot command line. Signed-off-by: David S. Miller commit e87dc35020bc555969810452f44bceaf8394eafa Author: David S. Miller Date: Wed Jun 21 18:18:47 2006 -0700 [SPARC64]: Use in-kernel OBP device tree for PCI controller probing. It can be pushed even further down, but this is a first step. Signed-off-by: David S. Miller commit aaf7cec2769942035985716452107fc5ba0b11f6 Author: David S. Miller Date: Wed Jun 21 16:33:54 2006 -0700 [SPARC64]: Add of_find_node_by_{name,type}(). Signed-off-by: David S. Miller commit 372b07bb5a13f8a1b8a3ce49cd76d39a79dbd3bd Author: David S. Miller Date: Wed Jun 21 15:35:28 2006 -0700 [SPARC64]: Import OBP device tree into kernel data structures. The basic framework is based on the PowerPC OF code. This code even tries to get the device addressing components correct in the full path names. Signed-off-by: David S. Miller commit 8fae097debdf8ac9b66d220ac258535ea09f3898 Author: David S. Miller Date: Tue Jun 20 15:23:28 2006 -0700 [SBUS]: Start cleaning up generic sbus support layer. In particular, move the IRQ probing out to sparc32/sparc64 arch specific code where it belongs. Signed-off-by: David S. Miller commit d384ea691fe4ea8c2dd5b9b8d9042eb181776f18 Author: Dave Jones Date: Sat Jun 24 00:33:08 2006 -0400 [PATCH] fix typo in acpi video brightness changes. Prevent possible null dereference due to misplaced ; Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds commit 236ee8c33277ab48671995f26dc68a4639936418 Author: Tony Luck Date: Fri Jun 23 13:49:25 2006 -0700 [IA64] fix ia64 build (fadt_descriptor) arch/ia64/kernel/acpi.c got forgotten when include/acpi/actbl.h got a cleanup. Signed-off-by: Tony Luck commit 95eaa5fa8eb2c345244acd5f65b200b115ae8c65 Author: Nicolas Pitre Date: Fri Jun 23 11:40:53 2006 -0400 [PATCH] fix silly ARM non-EABI build error My bad. Signed-off-by: Nicolas Pitre Signed-off-by: Linus Torvalds commit a5cf4b9a02cb9b8ac16eaafb0fcd7fd24215146e Author: Andrew Morton Date: Fri Jun 23 04:01:35 2006 -0700 [PATCH] s390_hypfs filesystem: get_sb_single() fix Update hypfs for dhowells API changes. Cc: Pekka Enberg Cc: Ingo Oeser Cc: Joern Engel Cc: Martin Schwidefsky Cc: Michael Holzheu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 138a0128c01899ee8492858a50856b90d0d9d815 Author: Andrew Morton Date: Fri Jun 23 03:31:19 2006 -0700 [PATCH] cpufreq build fix drivers/cpufreq/cpufreq_ondemand.c: In function 'do_dbs_timer': drivers/cpufreq/cpufreq_ondemand.c:374: warning: implicit declaration of function 'lock_cpu_hotplug' drivers/cpufreq/cpufreq_ondemand.c:381: warning: implicit declaration of function 'unlock_cpu_hotplug' drivers/cpufreq/cpufreq_conservative.c: In function 'do_dbs_timer': drivers/cpufreq/cpufreq_conservative.c:425: warning: implicit declaration of function 'lock_cpu_hotplug' drivers/cpufreq/cpufreq_conservative.c:432: warning: implicit declaration of function 'unlock_cpu_hotplug' Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8269730b389d4793348d521140f9c76fb1828249 Author: Andi Kleen Date: Wed Jun 21 14:48:09 2006 +0200 [BLOCK] Fix bounce limit address check Do a safer check for when to enable DMA. Currently we enable ISA DMA for cases that do not need it, resulting in OOM conditions when ZONE_DMA runs out of space. Signed-off-by: Jens Axboe commit dd67d051529387f6e44d22d1d5540ef281965fdd Author: Jens Axboe Date: Wed Jun 21 09:36:18 2006 +0200 [PATCH] rbtree: support functions used by the io schedulers They all duplicate macros to check for empty root and/or node, and clearing a node. So put those in rbtree.h. Signed-off-by: Jens Axboe commit 9e94cd4fd1812bab45237f998b3c6fa1b24023fd Author: Jens Axboe Date: Tue Jun 20 15:01:12 2006 +0200 [PATCH] splice: retrieve mapping after locking the page Otherwise we could be racing with truncate/mapping removal. Problem found/fixed by Nick Piggin , logic rewritten by me. Signed-off-by: Jens Axboe commit fd61af0384014ca29428ace7c17a978b755aeddd Author: Jens Axboe Date: Fri Jun 16 15:35:39 2006 +0200 [PATCH] cfq-iosched: rq update fixes - Remember to set ->last_sector so that the cfq_choose_req() logic works correctly. - Remove redundant call to cfq_choose_req() Signed-off-by: Jens Axboe commit caaa5f9f0a75d1dc5e812e69afdbb8720e077fd3 Author: Jens Axboe Date: Fri Jun 16 11:23:00 2006 +0200 [PATCH] cfq-iosched: many performance fixes This is a collection of patches that greatly improve CFQ performance in some circumstances. - Change the idling logic to only kick in after a request is done and we are deciding what to do. Before the idling included the request service time, so it was hard to adjust. Now it's true think/idle time. - Take advantage of TCQ/NCQ/queueing for seeky sync workloads, but keep it in control for sync and sequential (or close to) workloads. - Expire queues immediately and move on to other busy queues, if we are not going to idle after the current one finishes. - Don't rearm idle timer if there are no busy queues. Just leave the system idle. Signed-off-by: Jens Axboe commit 35e6077cb16f93517ba5a51ba849b186d2474d60 Author: Jens Axboe Date: Wed Jun 14 09:10:45 2006 +0200 [PATCH] cfq-iosched: correctly set ioprio on both targets Patch originally from Vasily Tarasov If you set io-priority of process 1 using sys_ioprio_set system call by another process 2 (like ionice do), then cfq_init_prio_data() function sets priority of process 2 (current) on queue of process 1 and clears the flag, that designates change of ioprio. So the process 1 will work like with priority of process 2. I propose not to call cfq_init_prio_data() on io-priority change, but only mark queue as queue with changed prority. Every time when new request comes cfq-scheduler checks for this flag and atomaticaly changes priority of queue to new value. Signed-off-by: Jens Axboe commit b17fd9bceb99610f6dc7998c9a4ed6b71520be2b Author: Jens Axboe Date: Mon Jun 19 10:06:48 2006 +0200 [PATCH] Make CFQ the default IO scheduler Signed-off-by: Jens Axboe commit 8f34ee75decb80007ba77bba5a7384eadff4866d Author: Jens Axboe Date: Tue Jun 13 09:02:34 2006 +0200 [PATCH] Rearrange a few struct request members This saves 8 bytes of data in 64-bit archs. Signed-off-by: Jens Axboe commit ad3caddaa1708e506f20b8e25a4a8ae586fc7d5b Author: Jens Axboe Date: Tue Jun 13 08:46:57 2006 +0200 [PATCH] Get rid of struct request request_pm_state member The IDE power management can just use the ->end_io_data member to store it's data. Signed-off-by: Jens Axboe commit b31dc66a54ad986b6b73bdc49c8efc17cbad1833 Author: Jens Axboe Date: Tue Jun 13 08:26:10 2006 +0200 [PATCH] Kill PF_SYNCWRITE flag A process flag to indicate whether we are doing sync io is incredibly ugly. It also causes performance problems when one does a lot of async io and then proceeds to sync it. Part of the io will go out as async, and the other part as sync. This causes a disconnect between the previously submitted io and the synced io. For io schedulers such as CFQ, this will cause us lost merges and suboptimal behaviour in scheduling. Remove PF_SYNCWRITE completely from the fsync/msync paths, and let the O_DIRECT path just directly indicate that the writes are sync by using WRITE_SYNC instead. Signed-off-by: Jens Axboe commit 271f18f102c789f59644bb6c53a69da1df72b2f4 Author: Jens Axboe Date: Tue Jun 13 08:08:38 2006 +0200 [PATCH] cfq-iosched: Don't set the queue batching limits We cannot update them if the user changes nr_requests, so don't set it in the first place. The gains are pretty questionable as well. The batching loss has been shown to decrease throughput. Signed-off-by: Jens Axboe commit acf421755593f7d7bd9352d57eda796c6eb4fa43 Author: Dave Jones Date: Mon Jun 12 14:20:58 2006 +0200 [PATCH] remove dead code from elevator switching We already drop the refcount in elevator_exit(), and as we're setting 'e' to NULL, we'll never take that branch anyway. Finally, as 'e' is a local var that isn't referenced afterwards, setting it to NULL is pointless. Signed-off-by: Dave Jones Signed-off-by: Jens Axboe commit fda151d9feafc0e8418f23c716587c44394fcdbf Author: Alexey Dobriyan Date: Mon Jun 5 12:09:50 2006 +0200 [PATCH] blktrace_api.h: endian annotations Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe commit a038e2536472b4dd932399b5277e65f188811de5 Author: Paolo 'Blaisorblade' Giarrusso Date: Mon Jun 5 12:09:01 2006 +0200 [PATCH] blk_start_queue() must be called with irq disabled - add warning The queue lock can be taken from interrupts so it must always be taken with irq disabling primitives. Some primitives already verify this. blk_start_queue() is called under this lock, so interrupts must be disabled. Also document this requirement clearly in blk_init_queue(), where the queue spinlock is set. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe commit bae386f7884aa3720cc7880b36a41a1d2b9c327b Author: Akinobu Mita Date: Mon Apr 24 21:12:59 2006 +0200 [PATCH] iosched: use hlist for request hashtable Use hlist instead of list_head for request hashtable in deadline-iosched and as-iosched. It also can remove the flag to know hashed or unhashed. Signed-off-by: Akinobu Mita Signed-off-by: Jens Axboe block/as-iosched.c | 45 +++++++++++++++++++-------------------------- block/deadline-iosched.c | 39 ++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 49 deletions(-) commit e83319510b04dd51a60da8a0b4ccf8b92b3ab1ad Author: Bob Copeland Date: Fri Jun 23 02:06:09 2006 -0700 [PATCH] docs: update sparse.txt with CHECK_ENDIAN Update the sparse documentation to omit the -Wbitwise flag example (as it is now passed by default), and document the kernel defines to enable endianness checking. Signed-off-by: Bob Copeland Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit eefe85ee350ece1bdf3e9a61e941d3394a528660 Author: Constantine Sapuntzakis Date: Fri Jun 23 02:06:08 2006 -0700 [PATCH] drivers/block/loop.c: don't return garbage if LOOP_SET_STATUS not called While writing a version of losetup, I ran into the problem that the loop device was returning total garbage. It turns out the problem was that this losetup was only issuing the LOOP_SET_FD ioctl and not issuing a subsequent LOOP_SET_STATUS ioctl. This losetup didn't have any special status to set, so it left out the call. The deeper cause is that loop_set_fd sets the transfer function to NULL, which causes no transfer to happen lo_do_transfer. This patch fixes the problem by setting transfer to transfer_none in loop_set_fd. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 98bd34eaf1a7d1f2ed9c4e5d3a9664d3dcdd2159 Author: Mike Miller Date: Fri Jun 23 02:06:07 2006 -0700 [PATCH] make kernel warn about incorrectly sized partitions Sometimes partitions claim to be larger than the reported capacity of a disk device. This patch makes the kernel warn about those partitions. We still permit these patitions to be used. Quoting Andries Brouwer : Case 1: The kernel is mistaken about the size of the disk. (There are commands to clip a disk to a certain capacity, there are jumpers to tell a disk that it should report a certain capacity etc. Usually this is because of BIOS bugs. In bad cases the machine will crash in the BIOS and hence fail to boot if the disk reports full capacity.) In such cases actually accessing the blocks of the partition may work fine, or may work fine after running an unclip utility. I wrote "setmax" some years ago precisely for this reason. Case 2: There was a messy partition table (maybe just a rounding error) but the actual filesystem on the partition is contained in the physical disk. Now using the filesystem goes without problem. Case 3: Both partition and filesystem extend beyond the end of the disk. In forensic or debugging situations one often uses a copy of the start of a disk. Now access beyond the end gives an expected I/O error. Signed-off-by: Mike Miller Signed-off-by: Stephen Cameron Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 125e18745f16685f69a34fd6130d47598fc4bf54 Author: Eric Sesterhenn Date: Fri Jun 23 02:06:06 2006 -0700 [PATCH] More BUG_ON conversion Signed-off-by: Eric Sesterhenn Signed-off-by: Alexey Dobriyan Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Cc: James Bottomley Acked-by: "Salyzyn, Mark" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 78ce89c92bc6eaf5933b5664bff64253a7103bd7 Author: Jan Kara Date: Fri Jun 23 02:06:05 2006 -0700 [PATCH] JBD: split checkpoint lists Split the checkpoint list of the transaction into two lists. In the first list we keep the buffers that need to be submitted for IO. In the second list are kept buffers that were already submitted and we just have to wait for the IO to complete. This should simplify a handling of checkpoint lists a bit and can eventually be also a performance gain. Signed-off-by: Jan Kara Cc: Mark Fasheh Cc: "Stephen C. Tweedie" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cdaad343b561cdeb38b0578bb038eb5e87ed5551 Author: Peter Hagervall Date: Fri Jun 23 02:06:04 2006 -0700 [PATCH] Sparse fixes for synclink_cs Mark a few non-exported functions static. Signed-off-by: Peter Hagervall Cc: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 908dcecda1d18803b5823f30e6c47d2882dc0cf1 Author: Jan Beulich Date: Fri Jun 23 02:06:00 2006 -0700 [PATCH] adjust handle_IRR_event() return type Correct the return type of handle_IRQ_event() (inconsistency noticed during Xen development), and remove redundant declarations. The return type adjustment required breaking out the definition of irqreturn_t into a separate header, in order to satisfy current include order dependencies. Signed-off-by: Jan Beulich Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Russell King Cc: Ian Molton Cc: Mikael Starvik Cc: Yoshinori Sato Cc: Hirokazu Takata Cc: Heiko Carstens Cc: Martin Schwidefsky Cc: William Lee Irwin III Cc: "David S. Miller" Cc: Miles Bader Cc: Geert Uytterhoeven Cc: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a5d6839b75ca4a29b5e0a5595914a8715e8f746d Author: Adrian Bunk Date: Fri Jun 23 02:05:59 2006 -0700 [PATCH] drivers/md/raid6algos.c: fix a NULL dereference This patch fixes a NULL dereference spotted by the Coverity checker. Signed-off-by: Adrian Bunk Cc: "H. Peter Anvin" Cc: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 226a6b84aaaf1fac7a5d41cf4e7387fd9ba895d5 Author: Randy Dunlap Date: Fri Jun 23 02:05:58 2006 -0700 [PATCH] CodingStyle: add typedefs chapter Add a chapter on typedefs, copied from an email from Linus to lkml on Feb. 3, 2006. (Subject: Re: [RFC][PATCH 1/5] Virtualization/containers: startup) Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3439dd86e34580384d3b58cf8d54a9283cd7a342 Author: Porpoise Date: Fri Jun 23 02:05:56 2006 -0700 [PATCH] When CONFIG_BASE_SMALL=1, cascade() may enter an infinite loop When CONFIG_BASE_SAMLL=1, cascade() in may enter the infinite loop. Because of CONFIG_BASE_SMALL=1(TVR_BITS=6 and TVN_BITS=4), the list base->tv5 may cascade into base->tv5. So, the kernel enters the infinite loop in the function cascade(). I created a test module to verify this bug, and a patch to fix it. #include #include #include #include #if 0 #include #else #define kdb_printf printk #endif #define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6) #define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8) #define TVN_SIZE (1 << TVN_BITS) #define TVR_SIZE (1 << TVR_BITS) #define TVN_MASK (TVN_SIZE - 1) #define TVR_MASK (TVR_SIZE - 1) #define TV_SIZE(N) (N*TVN_BITS + TVR_BITS) struct timer_list timer0; struct timer_list dummy_timer1; struct timer_list dummy_timer2; void dummy_timer_fun(unsigned long data) { } unsigned long j=0; void check_timer_base(unsigned long data) { kdb_printf("check_timer_base %08x\n",jiffies); mod_timer(&timer0,(jiffies & (~0xFFF)) + 0x1FFF); } int init_module(void) { init_timer(&timer0); timer0.data = (unsigned long)0; timer0.function = check_timer_base; mod_timer(&timer0,jiffies+1); init_timer(&dummy_timer1); dummy_timer1.data = (unsigned long)0; dummy_timer1.function = dummy_timer_fun; init_timer(&dummy_timer2); dummy_timer2.data = (unsigned long)0; dummy_timer2.function = dummy_timer_fun; j=jiffies; j&=(~((1< Cc: Matt Mackall Signed-off-by: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 626ab0e69d376fa07599af669af8ba92d58e87c1 Author: Oleg Nesterov Date: Fri Jun 23 02:05:55 2006 -0700 [PATCH] list: use list_replace_init() instead of list_splice_init() list_splice_init(list, head) does unneeded job if it is known that list_empty(head) == 1. We can use list_replace_init() instead. Signed-off-by: Oleg Nesterov Acked-by: David S. Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 54e73770357142e297c916c7865f5fca7499f69c Author: Oleg Nesterov Date: Fri Jun 23 02:05:54 2006 -0700 [PATCH] list: introduce list_replace() helper list_replace() is similar to list_replace_rcu(), but unlike list_replace_rcu() it could be used when list_empty(old) == 1 doesn't use barriers Signed-off-by: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cb259f07b1daacafac3b12ecd7f180faf7e506b0 Author: bjdouma Date: Fri Jun 23 02:05:53 2006 -0700 [PATCH] two additions to ./linux/Documentation/ioctl-number.txt Cc: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f5befceb5cfecba49fdf61f8e0eb4d453200eac9 Author: Brent Casavant Date: Fri Jun 23 02:05:52 2006 -0700 [PATCH] SGI IOC4: Detect IO card variant There are three different IO cards which an SGI IOC4 controller may find itself on. One of these variants does not bring out the IDE and serial signals, so we need to disable attaching the corresponding IOC4 subdrivers to such cards. Cleans up message clutter emitted during device probing. Signed-off-by: Brent Casavant Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 862f5f0133f1c8a179dd93adc03d43f8f7e8bac5 Author: Randy Dunlap Date: Fri Jun 23 02:05:52 2006 -0700 [PATCH] Doc: add audit & acct to DocBook Fix one audit kernel-doc description (one parameter was missing). Add audit*.c interfaces to DocBook. Add BSD accounting interfaces to DocBook. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d83015b8f62ee3fcd338f6f009051ed57f77a531 Author: Paul E. McKenney Date: Fri Jun 23 02:05:51 2006 -0700 [PATCH] Make RCU API inaccessible to non-GPL Linux kernel modules Remove synchronize_kernel() (deprecated 2-APR-2005 in http://lkml.org/lkml/2005/4/3/11) and makes the RCU API inaccessible to non-GPL Linux kernel modules (as was announced more than one year ago in http://lkml.org/lkml/2005/4/3/8). Tested on x86 and ppc64. Signed-off-by: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 55f4e8d156d23709739029afb108932ef94cac94 Author: Jes Sorensen Date: Fri Jun 23 02:05:50 2006 -0700 [PATCH] kernel/sys.c doesn't need init.h kernel/sys.c doesn't have anything in it relying on linux/init.h - remove the include. Signed-off-by: Jes Sorensen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 915a56d2394f4ef70e9cb7115a9bdad778276338 Author: Randy Dunlap Date: Fri Jun 23 02:05:49 2006 -0700 [PATCH] add Doc/SubmitChecklist Provide a checklist of techniques to aid kernel patch submitters in producing healthy patches and in lessening a burden on maintainers. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e0f23603fb2607315ce52432cc4225df410828cf Author: NeilBrown Date: Fri Jun 23 02:05:48 2006 -0700 [PATCH] Remove semi-softlockup from invalidate_mapping_pages If invalidate_mapping_pages is called to invalidate a very large mapping (e.g. a very large block device) and if the only active page in that device is near the end (or at least, at a very large index), such as, say, the superblock of an md array, and if that page happens to be locked when invalidate_mapping_pages is called, then pagevec_lookup will return this page and as it is locked, 'next' will be incremented and pagevec_lookup will be called again. and again. and again. while we count from 0 upto a very large number. We should really always set 'next' to 'page->index+1' before going around the loop again, not just if the page isn't locked. Cc: "Steinar H. Gunderson" Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 57ae2508610d50893cb3e3bbb869ff70ff724a2a Author: Andrew Morton Date: Fri Jun 23 02:05:47 2006 -0700 [PATCH] CONFIG_NET=n build fix Cc: Greg KH Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit deb0e9b234af24f4a827757fae9ff5542a3d2a12 Author: Andrew Morton Date: Fri Jun 23 02:05:46 2006 -0700 [PATCH] connector-exports Put the connector exports at the functions so people can see them in context. Cc: Evgeniy Polyakov Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 66f969d064e46e6690c3426e2af846e76fb80e83 Author: Pekka Enberg Date: Fri Jun 23 02:05:45 2006 -0700 [PATCH] ipmi: strstrip conversion Switch an open-coded strstrip() to use the new API. Acked-by: Corey Minyard Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 481fad483487ea967fe20bbc9e565d787f7bf20f Author: Pekka Enberg Date: Fri Jun 23 02:05:44 2006 -0700 [PATCH] strstrip() API Add a new strstrip() function to lib/string.c for removing leading and trailing whitespace from a string. Cc: Michael Holzheu Acked-by: Ingo Oeser Acked-by: Joern Engel Cc: Corey Minyard Signed-off-by: Pekka Enberg Acked-by: Michael Holzheu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3fa2164d03fb7af17fcfe4f8800dd754fbd99ff7 Author: Matt Helsley Date: Fri Jun 23 02:05:44 2006 -0700 [PATCH] Process Events: License Change Change the license on the process event structure passed between kernel and userspace. Signed-off-by: Matt Helsley Acked-by: Guillaume Thouvenin Acked-by: Nguyen Anh Quynh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1d31a4ea8cf7a2afc7299d1d3d8732ca54a5934e Author: Matt Helsley Date: Fri Jun 23 02:05:42 2006 -0700 [PATCH] Process Events - Header Cleanup Move connector header include to precisely where it's needed. Remove unused time.h header file as well. This was leftover from previous iterations of the process events patches. Signed-off-by: Matt Helsley Cc: Guillaume Thouvenin Cc: Nguyen Anh Quynh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 368a5fa1f28589e6b54588a139ea872d5b4b1914 Author: Hua Zhong Date: Fri Jun 23 02:05:42 2006 -0700 [PATCH] remove unlikely() in might_sleep_if() The likely() profiling tools show that __alloc_page() causes a lot of misses: ! 132 119193 __alloc_pages():mm/page_alloc.c@937 Because most __alloc_page() calls are not atomic. Signed-off-by: Hua Zhong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0216bfcffe424a5473daa4da47440881b36c1f41 Author: Mingming Cao Date: Fri Jun 23 02:05:41 2006 -0700 [PATCH] percpu counter data type changes to suppport more than 2**31 ext3 free blocks counter The percpu counter data type are changed in this set of patches to support more users like ext3 who need more than 32 bit to store the free blocks total in the filesystem. - Generic perpcu counters data type changes. The size of the global counter and local counter were explictly specified using s64 and s32. The global counter is changed from long to s64, while the local counter is changed from long to s32, so we could avoid doing 64 bit update in most cases. - Users of the percpu counters are updated to make use of the new percpu_counter_init() routine now taking an additional parameter to allow users to pass the initial value of the global counter. Signed-off-by: Mingming Cao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3cbc564024d8f174202f023e8a2991782f6a9431 Author: Ravikiran G Thirumalai Date: Fri Jun 23 02:05:40 2006 -0700 [PATCH] percpu_counters: create lib/percpu_counter.c - Move percpu_counter routines from mm/swap.c to lib/percpu_counter.c Signed-off-by: Ravikiran Thirumalai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d09042da7284a86ffbdd18695f517a71514ed598 Author: Laurent MEYER Date: Fri Jun 23 02:05:36 2006 -0700 [PATCH] fix incorrect SA_ONSTACK behaviour for 64-bit processes - When setting a sighandler using sigaction() call, if the flag SA_ONSTACK is set and no alternate stack is provided via sigaltstack(), the kernel still try to install the alternate stack. This behavior is the opposite of the one which is documented in Single Unix Specifications V3. - Also when setting an alternate stack using sigaltstack() with the flag SS_DISABLE, the kernel try to install the alternate stack on signal delivery. These two use cases makes the process crash at signal delivery. Signed-off-by: Laurent Meyer Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: David Howells Cc: Yoshinori Sato Cc: Geert Uytterhoeven Cc: Roman Zippel Cc: Kyle McMartin Cc: Paul Mundt Cc: Kazumoto Kojima Cc: Chris Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 785d55708c24c28d7646f3d1fe6c9f82fb714311 Author: Jesper Juhl Date: Fri Jun 23 02:05:35 2006 -0700 [PATCH] binflt_elf: remove more casts Remove redundant casts from NEW_AUX_ENT() arguments in fs/binfmt_elf.c Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f4e5cc2c44bf760c02875cf48c886c50ec7d2734 Author: Jesper Juhl Date: Fri Jun 23 02:05:35 2006 -0700 [PATCH] binfmt_elf: CodingStyle cleanup and remove some pointless casts Do a CodingStyle cleanup of fs/binfmt_elf.c and also remove some pointless casts of kmalloc() return values in the same file. Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 11420211b8123d0e2f71945ad022e8eec28ebfce Author: Jan Engelhardt Date: Fri Jun 23 02:05:34 2006 -0700 [PATCH] Update devices.txt Update Documentation/devices.txt with a new version from the LANANA site http://www.lanana.org/docs/device-list/devices-2.6+.txt Signed-off-by: Jan Engelhardt Cc: Torben Mathiasen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9becde79d2c5e382d955167c07017b5e34b142f0 Author: Jonathan McDowell Date: Fri Jun 23 02:05:33 2006 -0700 [PATCH] leds: Amstrad Delta LED support Use the new LED infrastructure to support the 6 LEDs present on the Amstrad Delta. [akpm@osdl.org: cleanup] Signed-off-by: Jonathan McDowell Ackde-by: Richard Purdie Cc: Ben Dooks Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 83d4e6e7fba0b2a01092f0cf14ba2e33bd1253e9 Author: Andreas Mohr Date: Fri Jun 23 02:05:32 2006 -0700 [PATCH] make noirqdebug/irqfixup __read_mostly, add (un)likely() Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e6022603b9aa7d61d20b392e69edcdbbc1789969 Author: Andrew Morton Date: Fri Jun 23 02:05:32 2006 -0700 [PATCH] ext3_clear_inode(): avoid kfree(NULL) Steven Rostedt points out that `rsv' here is usually NULL, so we should avoid calling kfree(). Also, fix up some nearby whitespace damage. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 304c4c841a31c780a45d65e389b07706babf5d36 Author: Andrew Morton Date: Fri Jun 23 02:05:31 2006 -0700 [PATCH] jbd: avoid kfree(NULL) There are a couple of places where JBD has to check to see whether an unneeded memory allocation was performed. Usually it _was_ needed, so we end up calling kfree(NULL). We can micro-optimise that by checking the pointer before calling kfree(). Thanks to Steven Rostedt for identifying this. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 22722051fb6bcbb95c895e68dad10d34a9db7e4d Author: Andreas Mohr Date: Fri Jun 23 02:05:30 2006 -0700 [PATCH] x86/powerpc make hardirq_ctx and softirq_ctx __read_mostly The hardirq_ctx and softirq_ctx variables are written to on init only, Signed-off-by: Andreas Mohr Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 89d0cf01c0aa9e8241cc3703a359ecd6abf3c28a Author: Daniel Walker Date: Fri Jun 23 02:05:29 2006 -0700 [PATCH] invert irq/migration.c brach prediction If you get to that point in the code it means that desc->move_irq is set, pending_irq_cpumask[irq] and cpu_online_map should have a value. Still pretty good chance anding those two you'll still have a value. So these two branch predictors should be inverted. Signed-off-by: Daniel Walker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d20d04bc9befbd752092b4aa42bb8254a1af0776 Author: Jesper Juhl Date: Fri Jun 23 02:05:28 2006 -0700 [PATCH] ISDN: correctly handle isdn_writebuf_stub() errors isdn_writebuf_stub() forgets to detect memory allocation and uaccess errors. And when that's fixed, if a error happens the caller will just keep on looping. So change the caller to detect the error, and to return it. Signed-off-by: Jesper Juhl Cc: Karsten Keil Signed-off-by: Tilman Schmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 94a6735cd67375029c2092e6d46f14b2721e6793 Author: Jesper Juhl Date: Fri Jun 23 02:05:27 2006 -0700 [PATCH] i4l: memory leak fix for sc_ioctl(). Fix leak of `rcvmsg' in sc_ioctl(). There are two returns in the switch in sc_ioctl (the SCIOCSTART case) that may leak `rcvmsg'. This patch fixes that by adding a kfree() call at the beginning of that case. Bug found by the coverity checker as #1098 Eric Sesterhenn send me a patch to fix the leak(s) by adding 2 kfree() calls before the returns, I changed that into just a single call at the beginning. Signed-off-by: Jesper Juhl Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2eebb1925d25cfd7e7cd2eb18ac4d4e6d189dba0 Author: Jesper Juhl Date: Fri Jun 23 02:05:26 2006 -0700 [PATCH] OSS: cs46xx cleanup and tiny bugfix Here's a patch for cs46xx that - (mostly) cleans up the cs46xx driver according to CodingStyle - removes a bunch of pointless casts - fixes a small, potential use of uninitialized variable, bug - reduces the size of the compiled code by 36 bytes - reduces the size of the source file by 1831 bytes I know I should probably have split this into bits, but since I only thought of that *after* doing all the edits, splitting it up would have been a royal pain. And since these are all pretty trivial changes I thought I'd just submit the one huge patch and hope people could live with it (if not, then just tell me and I'll split it). The bug fix that's in there may be hard to spot, so I'll point it out. It's the - int val, valsave, mapped, ret; + int val, valsave, ret; + int mapped = 0; bit. Without that change we may use `mapped' uninitialized if, in cs_ioctl, the first test of "if(state)" is false and the second "if(state)" test is true. Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9ada7340987aa24395809570840c7c6847044f52 Author: Jan Kara Date: Fri Jun 23 02:05:25 2006 -0700 [PATCH] jbd: fix BUG in journal_commit_transaction() Fix possible assertion failure in journal_commit_transaction() on jh->b_next_transaction == NULL (when we are processing BJ_Forget list and buffer is not jbddirty). !jbddirty buffers can be placed on BJ_Forget list for example by journal_forget() or by __dispose_buffer() - generally such buffer means that it has been freed by this transaction. Freed buffers should not be reallocated until the transaction has committed (that's why we have the assertion there) but they *can* be reallocated when the transaction has already been committed to disk and we are just processing the BJ_Forget list (as soon as we remove b_committed_data from the bitmap bh, ext3 will be able to reallocate buffers freed by the committing transaction). So we have to also count with the case that the buffer has been reallocated and b_next_transaction has been already set. And one more subtle point: it can happen that we manage to reallocate the buffer and also mark it jbddirty. Then we also add the freed buffer to the checkpoint list of the committing trasaction. But that should do no harm. Non-jbddirty buffers should be filed to BJ_Reserved and not BJ_Metadata list. It can actually happen that we refile such buffers during the commit phase when we reallocate in the running transaction blocks deleted in committing transaction (and that can happen if the committing transaction already wrote all the data and is just cleaning up BJ_Forget list). Signed-off-by: Jan Kara Acked-by: "Stephen C. Tweedie" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8e0a43d8fa953179505869ec28de78550246e795 Author: Ingo Molnar Date: Fri Jun 23 02:05:23 2006 -0700 [PATCH] cond_resched() might_sleep() fix add the __might_sleep() check back to cond_resched(). Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6e6672604773b9bae44d88d38afdf0763c104b1c Author: Prasanna Meda Date: Fri Jun 23 02:05:23 2006 -0700 [PATCH] dup fd error fix Set errorp in dup_fd, it will be used in sys_unshare also. Signed-off-by: Prasanna Meda Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 538c5902b81cc384e93ad3834b6d4a0b3fcb2285 Author: Jean-Luc Leger Date: Fri Jun 23 02:05:22 2006 -0700 [PATCH] clean up default value of IP_DCCP_ACKVEC Default values for boolean and tristate options can only be 'y', 'm' or 'n'. This patch removes wrong default for IP_DCCP_ACKVEC. Signed-off-by: Jean-Luc Leger Cc: Arnaldo Carvalho de Melo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5a9d6e0632b867ca71d3ee1e7e5c2365b6711031 Author: Jean-Luc Leger Date: Fri Jun 23 02:05:21 2006 -0700 [PATCH] clean up default value of USB_ISP116X_HCD, USB_SL811_HCD and USB_SL811_CS Default values for boolean and tristate options can only be 'y', 'm' or 'n'. This patch removes wrong default for USB_ISP116X_HCD, USB_SL811_HCD and USB_SL811_CS. Signed-off-by: Jean-Luc Leger Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c7a43575518702fe6829d970c3d04acd91ae5c91 Author: Jean-Luc Leger Date: Fri Jun 23 02:05:20 2006 -0700 [PATCH] clean up default value of SYSCALL_DEBUG Default values for boolean and tristate options can only be 'y', 'm' or 'n'. This patch removes wrong default for SYSCALL_DEBUG. Signed-off-by: Jean-Luc Leger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1e11d2782b2f8e86d22ad92c75b70ec8cad14dcf Author: Jean-Luc Leger Date: Fri Jun 23 02:05:19 2006 -0700 [PATCH] clean up default value of SCHED_SMT Default values for boolean and tristate options can only be 'y', 'm' or 'n'. This patch removes wrong default for SCHED_SMT. Signed-off-by: Jean-Luc Leger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 260ea1013283d8acbb451459ed1ca560c1445c20 Author: Eric W. Biederman Date: Fri Jun 23 02:05:18 2006 -0700 [PATCH] ptrace: document the locking rules After a lot of reading the code and thinking about how it behaves I have managed to figure out what the current ptrace locking rules are. The current code is in much better that it appears at first glance. The troublesome code paths are actually the code paths that violate the current rules. ptrace uses simple exclusive access as it's locking. You can only touch task->ptrace if the task is stopped and you are the ptracer, or if the task is running and are the task itself. Very simple, very easy to maintain. It just needs to be documented so people know not to touch ptrace from elsewhere. Currently we do have a few pieces of code that are in violation of this rule. Particularly the core dump code, and ptrace_attach. But so far the code looks fixable. Signed-off-by: Eric W. Biederman Cc: Oleg Nesterov Cc: Roland McGrath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4a4b69f79ba7286794765a856349e380f984a6cb Author: Vadim Lobanov Date: Fri Jun 23 02:05:16 2006 -0700 [PATCH] Poll cleanups/microoptimizations The "count" and "pt" variables are declared and modified by do_poll(), as well as accessed and written indirectly in the do_pollfd() subroutine. This patch pulls all handling of these variables into the do_poll() function, thereby eliminating the odd use of indirection in do_pollfd(). This is done by pulling the "struct pollfd" traversal loop from do_pollfd() into its only caller do_poll(). As an added bonus, the patch saves a few clock cycles, and also adds comments to make the code easier to follow. Signed-off-by: Vadim Lobanov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2da132646358c853d5caf296d079aefc69358d46 Author: Adrian Bunk Date: Fri Jun 23 02:05:15 2006 -0700 [PATCH] fs/fat/misc.c: unexport fat_sync_bhs Signed-off-by: Adrian Bunk Acked-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0ae26f1b3159f3acb21ae1e866c3c7e16edd450f Author: Andrew Morton Date: Fri Jun 23 02:05:15 2006 -0700 [PATCH] mmput() might sleep exit_aio() and exit_mmap() can sleep. But it's easy to accidentally call mmput() from inside locks. Cc: Dave Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 32797f976d62af709943aae38a9457b5a6dbcd8a Author: Domen Puncer Date: Fri Jun 23 02:05:14 2006 -0700 [PATCH] Remove CONFIG_PARPORT_ARC, drivers/parport/parport_arc.c It's wasn't referenced in Makefile since at least 2.2.8, unbuildable due to trivial typos and things like DATA_LATCH and arc_write_control() which doesn't exist. Adrian Bunk: adapted the patch to unrelated context changes Signed-off-by: Domen Puncer Signed-off-by: Alexey Dobriyan Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8d27e9084b372441dc8c9cf361a965ee58032767 Author: Xose Vazquez Perez Date: Fri Jun 23 02:05:13 2006 -0700 [PATCH] module.h: updated comments with a new license "Dual MIT/GPL" is also accepted (kernel/module.c), so updated comments. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b0904e147f7cbe4be3b4dae49ddccd627bb66f16 Author: Adrian Bunk Date: Fri Jun 23 02:05:13 2006 -0700 [PATCH] fs/locks.c: make posix_locks_deadlock() static We can now make posix_locks_deadlock() static. Signed-off-by: Adrian Bunk Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 75e1fcc0b18df0a65ab113198e9dc0e98999a08c Author: Miklos Szeredi Date: Fri Jun 23 02:05:12 2006 -0700 [PATCH] vfs: add lock owner argument to flush operation Pass the POSIX lock owner ID to the flush operation. This is useful for filesystems which don't want to store any locking state in inode->i_flock but want to handle locking/unlocking POSIX locks internally. FUSE is one such filesystem but I think it possible that some network filesystems would need this also. Also add a flag to indicate that a POSIX locking request was generated by close(), so filesystems using the above feature won't send an extra locking request in this case. Signed-off-by: Miklos Szeredi Cc: Trond Myklebust Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ff7b86b82083f24b8637dff1528c7101c18c7f39 Author: Miklos Szeredi Date: Fri Jun 23 02:05:11 2006 -0700 [PATCH] locks: clean up locks_remove_posix() locks_remove_posix() can use posix_lock_file() instead of doing the lock removal by hand. posix_lock_file() now does exacly the same. The comment about pids no longer applies, posix_lock_file() takes only the owner into account. Signed-off-by: Miklos Szeredi Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 39005d022ad221b76dc2de0ac62ef475a796433b Author: Miklos Szeredi Date: Fri Jun 23 02:05:10 2006 -0700 [PATCH] locks: don't do unnecessary allocations posix_lock_file() always allocates new locks in advance, even if it's easy to determine that no allocations will be needed. Optimize these cases: - FL_ACCESS flag is set - Unlocking the whole range Signed-off-by: Miklos Szeredi Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0d9a490abe1f69fda220f7866f6f23af41daa128 Author: Miklos Szeredi Date: Fri Jun 23 02:05:09 2006 -0700 [PATCH] locks: don't unnecessarily fail posix lock operations posix_lock_file() was too cautious, failing operations on OOM, even if they didn't actually require an allocation. This has the disadvantage, that a failing unlock on process exit could lead to a memory leak. There are two possibilites for this: - filesystem implements .lock() and calls back to posix_lock_file(). On cleanup of files_struct locks_remove_posix() is called which should remove all locks belonging to files_struct. However if filesystem calls posix_lock_file() which fails, then those locks will never be freed. - if a file is closed while a lock is blocked, then after acquiring fcntl_setlk() will undo the lock. But this unlock itself might fail on OOM, again possibly leaking the lock. The solution is to move the checking of the allocations until after it is sure that they will be needed. This will solve the above problem since unlock will always succeed unless it splits an existing region. Signed-off-by: Miklos Szeredi Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 090d2b185d8680fc26a2eaf4245d4171dcf4baf1 Author: Pekka Enberg Date: Fri Jun 23 02:05:08 2006 -0700 [PATCH] read_mapping_page for address space Add read_mapping_page() which is used for callers that pass mapping->a_ops->readpage as the filler for read_cache_page. This removes some duplication from filesystem code. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c330dda908b5a46469a997eea90b66f2f9f02b34 Author: Jeff Moyer Date: Fri Jun 23 02:05:07 2006 -0700 [PATCH] Add a sysfs file to determine if a kexec kernel is loaded Create two files in /sys/kernel, kexec_loaded and kexec_crash_loaded. Each file contains a simple boolean value indicating whether the relevant kernel has been loaded into memory. The motivation for this is geared around support. Signed-off-by: Jeff Moyer Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 24bbb1faf3f0420eb252dd0fdc1e477b1d4d73bd Author: Michael Holzheu Date: Fri Jun 23 02:05:06 2006 -0700 [PATCH] s390_hypfs filesystem On zSeries machines there exists an interface which allows the operating system to retrieve LPAR hypervisor accounting data. For example, it is possible to get usage data for physical and virtual cpus. In order to provide this information to user space programs, I implemented a new virtual Linux file system named 's390_hypfs' using the Linux 2.6 libfs framework. The name 's390_hypfs' stands for 'S390 Hypervisor Filesystem'. All the accounting information is put into different virtual files which can be accessed from user space. All data is represented as ASCII strings. When the file system is mounted the accounting information is retrieved and a file system tree is created with the attribute files containing the cpu information. The content of the files remains unchanged until a new update is made. An update can be triggered from user space through writing 'something' into a special purpose update file. We create the following directory structure: / update cpus/ type mgmtime ... hyp/ type systems/ cpus/ type mgmtime cputime onlinetime ... cpus/ ... - update: File to trigger update - cpus/: Directory for all physical cpus - cpus//: Directory for one physical cpu. - cpus//type: Type name of physical zSeries cpu. - cpus//mgmtime: Physical-LPAR-management time in microseconds. - hyp/: Directory for hypervisor information - hyp/type: Typ of hypervisor (currently only 'LPAR Hypervisor') - systems/: Directory for all LPARs - systems//: Directory for one LPAR. - systems//cpus//: Directory for the virtual cpus - systems//cpus//type: Typ of cpu. - systems//cpus//mgmtime: Accumulated number of microseconds during which a physical CPU was assigned to the logical cpu and the cpu time was consumed by the hypervisor and was not provided to the LPAR (LPAR overhead). - systems//cpus//cputime: Accumulated number of microseconds during which a physical CPU was assigned to the logical cpu and the cpu time was consumed by the LPAR. - systems//cpus//onlinetime: Accumulated number of microseconds during which the logical CPU has been online. As mount point for the filesystem /sys/hypervisor/s390 is created. The update process is triggered when writing 'something' into the 'update' file at the top level hypfs directory. You can do this e.g. with 'echo 1 > update'. During the update the whole directory structure is deleted and built up again. Cc: Pekka Enberg Cc: Ingo Oeser Cc: Joern Engel Acked-by: Martin Schwidefsky Signed-off-by: Michael Holzheu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b9e122c80cd2e10fe18678c63db4717871ed31cf Author: Jesper Juhl Date: Fri Jun 23 02:05:04 2006 -0700 [PATCH] xtensa: remove verify_area macros verify_area() is still alive on xtensa in 2.6.17-rc3-git13 It would be nice to finally be rid of that function across the board. Signed-off-by: Chris Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6f36d17a87ea9c2584aa8f649e438334bd69e32f Author: Al Viro Date: Fri Jun 23 02:05:03 2006 -0700 [PATCH] m68k: windfarm is powerpc-only, don't do it on m68k macs Signed-off-by: Al Viro Cc: Roman Zippel Cc: Geert Uytterhoeven Acked-by: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f1b5e520bb65e98d27632cd270d931838bd2a5da Author: Al Viro Date: Fri Jun 23 02:05:03 2006 -0700 [PATCH] m68k traps.c constraints Cast is not an lvalue; =r constraint wants an lvalue and really couldn't care whether it's void * or other pointer type. Signed-off-by: Al Viro Cc: Roman Zippel Cc: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit de290166552a037234bca44ed4bcbf4a4e9f5be9 Author: Jan Altenberg Date: Fri Jun 23 02:05:01 2006 -0700 [PATCH] m68k: ptrace.h typo fix Signed-off-by: Jan Altenberg Cc: Geert Uytterhoeven Cc: Greg Ungerer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d94af931af42152e34539dd4782b1724084a89fb Author: Roman Zippel Date: Fri Jun 23 02:05:00 2006 -0700 [PATCH] m68k: clean up uaccess.h This uninlines a few large functions in uaccess.h and cleans up the rest. It includes a (hopefully temporary) workaround for the broken typeof of gcc-4.1. Signed-off-by: Roman Zippel Cc: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1a23989475846547e5b7ce14e77f072894aaff54 Author: Finn Thain Date: Fri Jun 23 02:04:59 2006 -0700 [PATCH] m68k: m68k mac VIA2 fixes and cleanups Some fixes and cleanups from the linux-mac68k repo. Fix mac_esp by clearing the VIA2 SCSI IRQ flag before the SCSI IRQ handler is invoked. Also fix a race condition caused by unmasking a nubus slot IRQ then setting the relevant nubus_active bit. Signed-off-by: Finn Thain Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6d2f16a8917eb77a8b79849686159f3a5eae2501 Author: Roman Zippel Date: Fri Jun 23 02:04:59 2006 -0700 [PATCH] m68k: adjust to changed HARDIRQ_MASK Adjust entry.S to the changed HARDIRQ_MASK, add a check to prevent it from silently breaking again. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2dcf15b78d14c8d92fa1ce1be95b75e8d27ef99f Author: Roman Zippel Date: Fri Jun 23 02:04:58 2006 -0700 [PATCH] m68k: use proper defines for zone initialization MAX_NR_ZONES changed, so use correct defines now. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 882905c7ff81763a3aa3413629f7253b75587cb1 Author: Roman Zippel Date: Fri Jun 23 02:04:57 2006 -0700 [PATCH] m68k: wd33c93: extra delay The wd33c93 needs a small delay before a new command can be started. Signed-off-by: Roman Zippel Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5fa28ea42f28342ca6efaa2d23789f3fec5adff6 Author: Roman Zippel Date: Fri Jun 23 02:04:56 2006 -0700 [PATCH] m68k: restore amikbd compatibility with 2.4 Dump the extra mapping in the amikbd interrupt handler, so old Amiga keymaps work again. Amigas need a special keymap anyway, standard keymaps are not usable and recreating all keymaps is simply not worth the trouble. Signed-off-by: Roman Zippel Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cb7d390df391402c9630940d5a2ea1571fc5cde2 Author: Roman Zippel Date: Fri Jun 23 02:04:56 2006 -0700 [PATCH] m68k: print correct stack trace Pass unmodified stack argument to show_trace(). Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f6c4192e77dffbc50ee1b9a24a1063ff961aaf04 Author: Roman Zippel Date: Fri Jun 23 02:04:55 2006 -0700 [PATCH] m68k: use c99 initializer Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 98317f1271e7fd472983b013c76df6cc15fbef22 Author: Roman Zippel Date: Fri Jun 23 02:04:54 2006 -0700 [PATCH] m68k: Remove some unused definitions in zorro.h These definitions have long been superseded by asm-offsets.h Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5a232eafedc385249ef1931d186169f9eed2ad93 Author: Roman Zippel Date: Fri Jun 23 02:04:54 2006 -0700 [PATCH] m68k: cleanup unistd.h Remove long obsolete kernel syscalls, only execve is still used. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 078517e4118dc60a97c4eda127b849383eb26f8e Author: Roman Zippel Date: Fri Jun 23 02:04:53 2006 -0700 [PATCH] m68k: atyfb_base compile fix for CONFIG_PCI=n The atyfb_driver structure is only available if CONFIG_PCI is set. Signed-off-by: Roman Zippel Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2c3e0262e0cb5395fe02cdf27c229ee7414ab0c0 Author: Roman Zippel Date: Fri Jun 23 02:04:51 2006 -0700 [PATCH] m68k: completely initialize hw_regs_t in ide_setup_ports ide_setup_ports does not completely initialize the hw_regs_t structure which can cause random failures, as the structure is often on the stack. None of the callers expect a partially initialized structure, i.e. none of them do any setup of their own before calling ide_setup_ports(). Signed-off-by: Roman Zippel Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit daacf8bc0dd37a6ad3a87d1a667599e15940815e Author: Shaohua Li Date: Fri Jun 23 02:04:50 2006 -0700 [PATCH] move do_suspend_lowlevel to correct segment Move do_suspend_lowlevel to correct segment. If it is in the same hugepage with ro data, mark_rodata_ro will make it unexecutable. Signed-off-by: Shaohua Li Cc: Len Brown Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e084dbd3a995f99f5444a9046e66d93c1b92c348 Author: Pavel Machek Date: Fri Jun 23 02:04:50 2006 -0700 [PATCH] swsusp: documentation updates Update documentation a bit, add more machines to video.txt list. Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 55b2355eefc2f160246226d4d69fed431173a4d5 Author: Shaohua Li Date: Fri Jun 23 02:04:49 2006 -0700 [PATCH] don't use flush_tlb_all in suspend time flush_tlb_all uses on_each_cpu, which will disable/enable interrupt. In suspend/resume time, this will make interrupt wrongly enabled. Signed-off-by: Shaohua Li Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 968808b8956e332e556b1eae9b4f7df77518f53b Author: Rafael J. Wysocki Date: Fri Jun 23 02:04:48 2006 -0700 [PATCH] swsusp: use less memory during resume Make swsusp allocate only as much memory as needed to store the image data and metadata during resume. Without this patch swsusp additionally allocates many page frames that will conflict with the "original" locations of the image data and are considered as "unsafe", treating them as "eaten" pages (ie. allocated but unusable). The patch makes swsusp allocate as many pages as it'll need to store the data read from the image in one shot, creating a list of allocated "safe" pages, and use the observation that all pages allocated by it are marked with the PG_nosave and PG_nosave_free flags set.  Namely, when it's about to load an image page, swsusp can check whether the page frame corresponding to the "original" location of this page has been allocated (ie. if the page frame has the PG_nosave and PG_nosave_free flags set) and if so, it can load the page directly into this page frame.  Otherwise it uses an allocated "safe" page from the list to store the data that will be copied to their "original" location later on. This allows us to save many page copyings and page allocations during resume and in the future it may allow us to load images greater than 50% of the normal zone. Signed-off-by: Rafael J. Wysocki Acked-by: "Pavel Machek" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7bff24e255ee11ecbc304315a252fcbd84f9ffce Author: Adrian Bunk Date: Fri Jun 23 02:04:47 2006 -0700 [PATCH] kernel/power/snapshot.c: cleanups - make needlessly global functions static - make dummy functions static inline Signed-off-by: Adrian Bunk Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a938c356d5b007fe6d28251c0ddbf6c11d0d92b5 Author: Rafael J. Wysocki Date: Fri Jun 23 02:04:46 2006 -0700 [PATCH] swsusp: take lowmem reserves into account swsusp allocates memory from the normal zone, so it cannot use lowmem reserve pages from the lower zones. Therefore it should not count these pages as available to it. Signed-off-by: Rafael J. Wysocki Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3e3318dee0878d42ed62a19c292a2ac284135db3 Author: Shaohua Li Date: Fri Jun 23 02:04:46 2006 -0700 [PATCH] swsusp: x86_64 mark special saveable/unsaveable pages Pages (Reserved/ACPI NVS/ACPI Data) below end_pfn will be saved/restored by S4 currently. We should mark 'Reserved' pages not saveable. Pages (Reserved/ACPI NVS/ACPI Data) above end_pfn will not be saved/restored by S4 currently. We should save the 'ACPI NVS/ACPI Data' pages. Signed-off-by: Shaohua Li Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Nigel Cunningham Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b6370d96e09944c6e3ae8d5743ca8a8ab1f79f6c Author: Shaohua Li Date: Fri Jun 23 02:04:45 2006 -0700 [PATCH] swsusp: i386 mark special saveable/unsaveable pages Pages (Reserved/ACPI NVS/ACPI Data) below max_low_pfn will be saved/restored by S4 currently. We should mark 'Reserved' pages not saveable. Pages (Reserved/ACPI NVS/ACPI Data) above max_low_pfn will not be saved/restored by S4 currently. We should save the 'ACPI NVS/ACPI Data' pages. Signed-off-by: Shaohua Li Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Nigel Cunningham Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ce4ab0012b32c1a4a1d6e934aeb73bf3151c48d9 Author: Shaohua Li Date: Fri Jun 23 02:04:44 2006 -0700 [PATCH] swsusp: add architecture special saveable pages support 1. Add architecture specific pages save/restore support. Next two patches will use this to save/restore 'ACPI NVS' pages. 2. Allow reserved pages 'nosave'. This could avoid save/restore BIOS reserved pages. Signed-off-by: Shaohua Li Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: Nigel Cunningham Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 82dcaafc92fdfbe2c1d6c50b9f5e17d533caf950 Author: Mathieu Chouquet-Stringer Date: Fri Jun 23 02:04:40 2006 -0700 [PATCH] Remove duplicate symbol exports on Alpha WARNING: vmlinux: 'enable_irq' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'disable_irq' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'disable_irq_nosync' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'probe_irq_mask' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'sys_open' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'sys_read' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'strstr' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'memscan' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'memcmp' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'strnlen' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'strncmp' exported twice. Previous export was in vmlinux WARNING: vmlinux: 'strcmp' exported twice. Previous export was in vmlinux Signed-off-by: Mathieu Chouquet-Stringer Cc: Richard Henderson Cc: Ivan Kokshaysky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 30343d6c3d4e3fe961369e7be19935683e808c88 Author: Kirill Smelkov Date: Fri Jun 23 02:04:33 2006 -0700 [PATCH] x86: compile fix for asm-i386/alternatives.h compile fix: needs for 'u8' -- just look at struct alt_instr. My module includes as the first header, and as of 2.6.17 this leads to compilation errors. Signed-off-by: Kirill Smelkov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 224f611c1639cb6c134a934dae7f7b9f0ac3b540 Author: Michal Ludvig Date: Fri Jun 23 02:04:32 2006 -0700 [PATCH] x86: VIA C7 CPU flags New CPU flags for next generation of crypto engine as found in VIA C7 processors. Signed-off-by: Michal Ludvig Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7e04a1183eac3e6b3570a154c8677fd9184b51e7 Author: Chuck Ebbert <76306.1226@compuserve.com> Date: Fri Jun 23 02:04:31 2006 -0700 [PATCH] i386: extra checks in show_registers() Sometimes thread_info and task_struct get out-of-sync with each other. Printing task.thread_info in show_registers() can help spot this. And when task_struct is corrupt then task.comm can contain garbage, so only print as many characters as it can hold. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 722f4f5b2600b8930b63a096e48b878cd6e0e15a Author: Roman Zippel Date: Fri Jun 23 02:04:31 2006 -0700 [PATCH] x86: fix __range_ok constraint An immediate operand can't be the destination of the cmpl instruction, so exclude it. Signed-off-by: Roman Zippel Cc: Mattia Dongili Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6444541671bd821b950dbaafee70d65188198aa6 Author: Zachary Amsden Date: Fri Jun 23 02:04:30 2006 -0700 [PATCH] i386: don't try kprobes for v8086 mode Never allow int3 traps from V8086 mode to enter the kprobes handler. Signed-off-by: Zachary Amsden Cc: Prasanna S Panchamukhi Cc: Ananth N Mavinakayanahalli Cc: Anil S Keshavamurthy Cc: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 19964fecf25c17f865dec07ae242b1a40ea93f16 Author: Chuck Ebbert <76306.1226@compuserve.com> Date: Fri Jun 23 02:04:29 2006 -0700 [PATCH] i386: fix get_segment_eip() with vm86 segments We need to check for vm86 mode first before looking at selector privilege bits. Segment limit is always base + 64k and only the low 16 bits of EIP are significant in vm86 mode. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Cc: Andi Kleen Cc: Zachary Amsden Cc: Rohit Seth Acked-by: Ananth N Mavinakayanahalli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 110cb1d2e343443c4a4b5f7e081928aa4da90f93 Author: Andreas Mohr Date: Fri Jun 23 02:04:28 2006 -0700 [PATCH] x86: use proper defines for i8259A I/O Use proper defines instead of open-coded values. Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a0de1f0a5038a957d50893db7a0d47e385fb2915 Author: Andreas Mohr Date: Fri Jun 23 02:04:28 2006 -0700 [PATCH] x86: constify arch/i386/pci/irq.c constify structs and add one __initdata. Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9f22271898707aed2f84cc75ab3bd109173cdbbf Author: Andreas Mohr Date: Fri Jun 23 02:04:27 2006 -0700 [PATCH] make ACPI errata __read_mostly Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7b0c2d92180dbd9c7cd0c4b9bd38b06bb0f12843 Author: Andreas Mohr Date: Fri Jun 23 02:04:26 2006 -0700 [PATCH] x86: make i387 mxcsr_feature_mask __read_mostly Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cefc01130ba2bb0a81abda14b3f00fcc2e70dd43 Author: Andreas Mohr Date: Fri Jun 23 02:04:26 2006 -0700 [PATCH] x86: cyrix code CONFIG_PCI fix / add __initdata PCI code was outside of CONFIG_PCI, add __initdata at cyrix_55x0 (since accessed within __init function only). Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit acae9d32436122959667470b84da517d7b1b9c2d Author: Andreas Mohr Date: Fri Jun 23 02:04:25 2006 -0700 [PATCH] x86: make using_apic_timer __read_mostly Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 21528454f6dd18231ae20102f98aa8f51b6ec1b9 Author: Chuck Ebbert <76306.1226@compuserve.com> Date: Fri Jun 23 02:04:23 2006 -0700 [PATCH] i386: let usermode execute the "enter" instruction The i386 page fault handler does not allow enough slack when checking for userspace access below the current stack pointer. This prevents use of the enter instruction by user code. Fix this by allowing enough slack for "enter $65535,$31" to execute. Problem reported by Tomasz Malesinski Tested using this program, based on the original from Tomasz: .file "ovflow.S" .version "01.01" gcc2_compiled.: .section .rodata .LC0: .string "asdf\n" .text .align 4 .globl main .type main,@function main: nest_level=0 .rept 30 enter $0,$nest_level nest_level=nest_level+1 .endr enter $65535,$30 enter $65535,$31 addl $-12,%esp pushl $.LC0 call printf addl $16,%esp .L2: .rept 32 leave .endr ret .Lfe1: .size main,.Lfe1-main .ident "GCC: (GNU) 2.95.4 20011002 (Debian prerelease)" Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1b61b910e99059abdd54c93aa70e84e076e33d16 Author: Zhang Yanmin Date: Fri Jun 23 02:04:22 2006 -0700 [PATCH] x86: kernel irq balance doesn't work On i386, kernel irq balance doesn't work. 1) In function do_irq_balance, after kernel finds the min_loaded cpu but before calling set_pending_irq to really pin the selected_irq to the target cpu, kernel does a cpus_and with irq_affinity[selected_irq]. Later on, when the irq is acked, kernel would calls move_native_irq=>desc->handler->set_affinity to change the irq affinity. However, every function pointed by hw_interrupt_type->set_affinity(unsigned int irq, cpumask_t cpumask) always changes irq_affinity[irq] to cpumask. Next time when recalling do_irq_balance, it has to do cpu_ands again with irq_affinity[selected_irq], but irq_affinity[selected_irq] already becomes one cpu selected by the first irq balance. 2) Function balance_irq in file arch/i386/kernel/io_apic.c has the same issue. [akpm@osdl.org: cleanups] Signed-off-by: Zhang Yanmin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit afa024c3dbccf026e45121f4b9de54cda48edbea Author: Linus Torvalds Date: Fri Jun 23 02:04:21 2006 -0700 [PATCH] x86: call eisa_set_level_irq() in pbibios_lookup_irq() Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a03a3e287b119c7bcbcff1d68f81864ce33b1ad2 Author: Alexey Dobriyan Date: Fri Jun 23 02:04:20 2006 -0700 [PATCH] Don't trigger full rebuild via CONFIG_X86_MCE Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b88d4f1d390a6a232938d27d551f24cf08a2c7e0 Author: Ingo Molnar Date: Fri Jun 23 02:04:20 2006 -0700 [PATCH] i386: break out of recursion in stackframe walk If CONFIG_FRAME_POINTERS is enabled, and one does a dump_stack() during early SMP init, an infinite stackdump and a bootup hang happens: [] show_trace+0xd/0xf [] dump_stack+0x15/0x17 [] save_trace+0xc3/0xce [] mark_lock+0x8c/0x4fe [] __lockdep_acquire+0x44e/0xaa5 [] lockdep_acquire+0x68/0x84 [] _spin_lock+0x21/0x2f [] prepare_set+0xd/0x5d [] generic_set_all+0x1d/0x201 [] mtrr_ap_init+0x23/0x3b [] identify_cpu+0x2a7/0x2af [] smp_store_cpu_info+0x2f/0xb4 [] start_secondary+0xb5/0x3ec [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [] end_of_stack_stop_unwind_function+0x1/0x4 [...] Due to "end_of_stack_stop_unwind_function" recursing back to itself in the EBP stackframe-walker. So avoid this type of recursion when walking the stack . Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ba528f2854e8632c8d04ddcd45f06c47bc7188b0 Author: Jan Beulich Date: Fri Jun 23 02:04:19 2006 -0700 [PATCH] fix x86 microcode driver handling of multiple matching revisions When multiple updates matching a given CPU are found in the update file, the action taken by the microcode update driver was inappropriate: - when lower revision microcode was found before matching or higher revision one, the driver would needlessly complain that it would not downgrade the CPU - when microcode matching the currently installed revision was found before newer revision code, no update would actually take place To change this behavior, the driver now concludes about possibly updates and issues messages only when the entire input was parsed. Additionally, this adds back (in different places, and conditionalized upon a new module option) some messages removed by a previous patch. Signed-off-by: Jan Beulich Cc: "Siddha, Suresh B" Cc: Tigran Aivazian Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 27b07da7332f03a935cd13b6a6beb780bf19e7a4 Author: Alexey Dobriyan Date: Fri Jun 23 02:04:18 2006 -0700 [PATCH] Don't trigger full rebuild via CONFIG_MTRR Only drm, framebuffer, mtrr parts + misc files here and there. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 87af2ffd4ccd0e6a2ff316fd008a9bedb4a4cb66 Author: Andreas Mohr Date: Fri Jun 23 02:04:17 2006 -0700 [PATCH] i386 apm.c optimization - avoid expensive modulo (integer division) which happened since APM_MAX_EVENTS is 20 (non-power-of-2) - kill compiler warnings by initializing two variables - add __read_mostly to some important static variables that are read often (by idle loop etc.) - constify several structures Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a0b4da91f4c5710b9c20219a19e905145647b48b Author: Adrian Bunk Date: Fri Jun 23 02:04:17 2006 -0700 [PATCH] arch/i386/kernel/apic.c: make modern_apic() static Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c22ce143d15eb288543fe9873e1c5ac1c01b69a1 Author: Hiro Yoshioka Date: Fri Jun 23 02:04:16 2006 -0700 [PATCH] x86: cache pollution aware __copy_from_user_ll() Use the x86 cache-bypassing copy instructions for copy_from_user(). Some performance data are Total of GLOBAL_POWER_EVENTS (CPU cycle samples) 2.6.12.4.orig 1921587 2.6.12.4.nt 1599424 1599424/1921587=83.23% (16.77% reduction) BSQ_CACHE_REFERENCE (L3 cache miss) 2.6.12.4.orig 57427 2.6.12.4.nt 20858 20858/57427=36.32% (63.7% reduction) L3 cache miss reduction of __copy_from_user_ll samples % 37408 65.1412 vmlinux __copy_from_user_ll 23 0.1103 vmlinux __copy_user_zeroing_intel_nocache 23/37408=0.061% (99.94% reduction) Top 5 of 2.6.12.4.nt Counted GLOBAL_POWER_EVENTS events (time during which processor is not stopped) with a unit mask of 0x01 (mandatory) count 100000 samples % app name symbol name 128392 8.0274 vmlinux __copy_user_zeroing_intel_nocache 64206 4.0143 vmlinux journal_add_journal_head 59746 3.7355 vmlinux do_get_write_access 47674 2.9807 vmlinux journal_put_journal_head 46021 2.8774 vmlinux journal_dirty_metadata pattern9-0-cpu4-0-09011728/summary.out Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus unit) with a unit mask of 0x3f (multiple flags) count 3000 samples % app name symbol name 69755 4.2861 vmlinux __copy_user_zeroing_intel_nocache 55685 3.4215 vmlinux journal_add_journal_head 52371 3.2179 vmlinux __find_get_block 45504 2.7960 vmlinux journal_put_journal_head 36005 2.2123 vmlinux journal_stop pattern9-0-cpu4-0-09011744/summary.out Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus unit) with a unit mask of 0x200 (read 3rd level cache miss) count 3000 samples % app name symbol name 1147 5.4994 vmlinux journal_add_journal_head 881 4.2240 vmlinux journal_dirty_data 872 4.1809 vmlinux blk_rq_map_sg 734 3.5192 vmlinux journal_commit_transaction 617 2.9582 vmlinux radix_tree_delete pattern9-0-cpu4-0-09011731/summary.out iozone results are original 2.6.12.4 CPU time = 207.768 sec cache aware CPU time = 184.783 sec (three times run) 184.783/207.768=88.94% (11.06% reduction) original: pattern9-0-cpu4-0-08191720/iozone.out: CPU Utilization: Wall time 45.997 CPU time 64.527 CPU utilization 140.28 % pattern9-0-cpu4-0-08191741/iozone.out: CPU Utilization: Wall time 46.878 CPU time 71.933 CPU utilization 153.45 % pattern9-0-cpu4-0-08191743/iozone.out: CPU Utilization: Wall time 45.152 CPU time 71.308 CPU utilization 157.93 % cache awre: pattern9-0-cpu4-0-09011728/iozone.out: CPU Utilization: Wall time 44.842 CPU time 62.465 CPU utilization 139.30 % pattern9-0-cpu4-0-09011731/iozone.out: CPU Utilization: Wall time 44.718 CPU time 59.273 CPU utilization 132.55 % pattern9-0-cpu4-0-09011744/iozone.out: CPU Utilization: Wall time 44.367 CPU time 63.045 CPU utilization 142.10 % Signed-off-by: Hiro Yoshioka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7dbdf43cfa635ddc3701cc8d1eab07597cd731c0 Author: Yoichi Yuasa Date: Fri Jun 23 02:04:14 2006 -0700 [PATCH] mips: fix number of mremap arguments mremap syscall takes 5 arguments. Fixed by Ralf Baechle. Signed-off-by: Ralf Baechle Signed-off-by: Yoichi Yuasa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f2c780c1fdbe5008c902c2d7e37242ac5e60f0b9 Author: Sergei Shtylyov Date: Fri Jun 23 02:04:13 2006 -0700 [PATCH] Au1550/1200: add missing PSC #define's, make OSS driver use the proper ones Add missing PSC #define's required for the drivers using PSC on DBAu1550 board (also fixing Au1550 PSC3 address) and all Au1200-based boards as well. Make the OSS driver use the correct PSC definitions fo each board. Signed-off-by: Sergei Shtylyov Cc: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c52c17622e27876c2395f59cfe342497a399de41 Author: Al Viro Date: Fri Jun 23 02:04:13 2006 -0700 [PATCH] frv: clean frv unistd.h Remove _syscall invocations that aren't used in the kernel. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8ccd05670309084c2dd2003b6840a4becb5acca0 Author: Al Viro Date: Fri Jun 23 02:04:12 2006 -0700 [PATCH] frv: trivial cleanups in frv_ksyms.c Remove duplicate EXPORT_SYMBOL annotations from the FRV arch. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5e591a55576b60156ac3dbc5087660ed82646d66 Author: Al Viro Date: Fri Jun 23 02:04:11 2006 -0700 [PATCH] frv: Add missing qualifier to memcpy_fromio() prototype The memcpy_fromio() function should have a const qualifier on its source pointer. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a73df4dfdb0e01a1cbf119416a00e520a5e22306 Author: Al Viro Date: Fri Jun 23 02:04:10 2006 -0700 [PATCH] frv: ieee1394 is borken on frv The ieee1394 assumes it may make direct use of ->count in the semaphore structure. Signed-off-by: Al Viro Signed-off-by: David Howells Cc: Stefan Richter Cc: Ben Collins Cc: Jody McIntyre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7f788435568795c4cd29301bb4ccf7aff54f5051 Author: Al Viro Date: Fri Jun 23 02:04:09 2006 -0700 [PATCH] frv: NULL noise removal in frv xchg() Clean up the FRV arch's xchg() function. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ffca11104c06aff1641b9787f9e5b1099187ff83 Author: Al Viro Date: Fri Jun 23 02:04:09 2006 -0700 [PATCH] frv: initrd is grossly broken on frv (never built) The FRV arch doesn't currently support initrd, so it should be disabled automatically for the moment. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0c426f26cce71626ed39cd7b9496ea7f460ea9d0 Author: Al Viro Date: Fri Jun 23 02:04:08 2006 -0700 [PATCH] ext2 XIP won't build without MMU Disable Ext2 XIP if the kernel is configured in no-MMU mode as the former won't build. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit be2338f3ceb6d80170ebb495190d6aee79d8c7e3 Author: Al Viro Date: Fri Jun 23 02:04:07 2006 -0700 [PATCH] frv: wrong syscall The FRV arch should use fstatat64 not newfstatat. Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 576132b42647e3facd28e3148a20307fadfd9afc Author: Al Viro Date: Fri Jun 23 02:04:07 2006 -0700 [PATCH] frv: misc sparse annotations Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 53470aaa02ef3c83187f1ffe0d2cb647274fe397 Author: Al Viro Date: Fri Jun 23 02:04:06 2006 -0700 [PATCH] frv: misc __user annotations Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 530018bf3d93e04533eec9c6516e3ce8f5310e13 Author: Al Viro Date: Fri Jun 23 02:04:05 2006 -0700 [PATCH] frv: binfmt_elf_fdpic __user annotations Add __user annotations to binfmt_elf_fdpic. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7ab76d722a0d64369080ec96f0fd9fca2138e3c5 Author: Al Viro Date: Fri Jun 23 02:04:05 2006 -0700 [PATCH] frv: sysctl __user annotations Add __user annotations to FRV-specific sysctl stuff. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9e4d11f8630d5350adc5d4d65180e69991c498f8 Author: Al Viro Date: Fri Jun 23 02:04:04 2006 -0700 [PATCH] frv: signal annotations Add annotations to the FRV signal handling for sparse. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3f4cd389c3564caf1eec70957fcbd9d88c995d45 Author: Al Viro Date: Fri Jun 23 02:04:03 2006 -0700 [PATCH] frv: basic __iomem annotations Add annotations to the FRV I/O handling functions for sparse. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a8a77573c9e5345bcf6a963858745cd83c923f44 Author: Al Viro Date: Fri Jun 23 02:04:03 2006 -0700 [PATCH] frv: __user infrastructure Add general annotations to the FRV arch for sparse. Signed-off-by: Al Viro Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 86c3a7645c05a7d06b72653aa4b2bea4e7229d1b Author: David Quigley Date: Fri Jun 23 02:04:02 2006 -0700 [PATCH] SELinux: add security_task_movememory calls to mm code This patch inserts security_task_movememory hook calls into memory management code to enable security modules to mediate this operation between tasks. Since the last posting, the hook has been renamed following feedback from Christoph Lameter. Signed-off-by: David Quigley Acked-by: Stephen Smalley Signed-off-by: James Morris Cc: Andi Kleen Acked-by: Christoph Lameter Acked-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 35601547baf92d984b6e59cf3583649da04baea5 Author: David Quigley Date: Fri Jun 23 02:04:01 2006 -0700 [PATCH] SELinux: add task_movememory hook This patch adds new security hook, task_movememory, to be called when memory owened by a task is to be moved (e.g. when migrating pages to a this hook is identical to the setscheduler implementation, but a separate hook introduced to allow this check to be specialized in the future if necessary. Since the last posting, the hook has been renamed following feedback from Christoph Lameter. Signed-off-by: David Quigley Acked-by: Stephen Smalley Signed-off-by: James Morris Cc: Christoph Lameter Cc: Andi Kleen Acked-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 22fb52dd736a62e24c44c50739007496265dc38c Author: David Quigley Date: Fri Jun 23 02:04:00 2006 -0700 [PATCH] SELinux: add security hook call to mediate attach_task (kernel/cpuset.c) Add a security hook call to enable security modules to control the ability to attach a task to a cpuset. While limited control over this operation is possible via permission checks on the pseudo fs interface, those checks are not sufficient to control access to the target task, which is looked up in this function. The existing task_setscheduler hook is re-used for this operation since this falls under the same class of operations. Signed-off-by: David Quigley Acked-by: Stephen Smalley Signed-off-by: James Morris Acked-by: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e7834f8fccd791225a1cf91c2c3e740ad8e2e145 Author: David Quigley Date: Fri Jun 23 02:03:59 2006 -0700 [PATCH] SELinux: add security hooks to {get,set}affinity This patch adds LSM hooks into the setaffinity and getaffinity functions to enable security modules to control these operations between tasks with task_setscheduler and task_getscheduler LSM hooks. Signed-off-by: David Quigley Acked-by: Stephen Smalley Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 03e68060636e05989ea94bcb671ab633948f328c Author: James Morris Date: Fri Jun 23 02:03:58 2006 -0700 [PATCH] lsm: add task_setioprio hook Implement an LSM hook for setting a task's IO priority, similar to the hook for setting a tasks's nice value. A previous version of this LSM hook was included in an older version of multiadm by Jan Engelhardt, although I don't recall it being submitted upstream. Also included is the corresponding SELinux hook, which re-uses the setsched permission in the proccess class. Signed-off-by: James Morris Acked-by: Stephen Smalley Cc: Jan Engelhardt Cc: Chris Wright Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9216dfad4fc97ab639ef0885efc713f3d7a20d5b Author: Christoph Lameter Date: Fri Jun 23 02:03:57 2006 -0700 [PATCH] move_pages: fix 32 -> 64 bit compat function The definition of the third parameter is a pointer to an array of virtual addresses which give us some trouble. The existing code calculated the wrong address in the array since I used void to avoid having to specify a type. I now use the correct type "compat_uptr_t __user *" in the definition of the function in kernel/compat.c. However, I used __u32 in syscalls.h. Would have to include compat.h there in order to provide the same definition which would generate an ugly include situation. On both ia64 and x86_64 compat_uptr_t is u32. So this works although parameter declarations differ. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1b2db9fb7adc4d67d9ce7d16ce79c41ee84730fe Author: Christoph Lameter Date: Fri Jun 23 02:03:56 2006 -0700 [PATCH] sys_move_pages: 32bit support (i386, x86_64) sys_move_pages() support for 32bit (i386 plus x86_64 compat layer) Add support for move_pages() on i386 and also add the compat functions necessary to run 32 bit binaries on x86_64. Add compat_sys_move_pages to the x86_64 32bit binary layer. Note that it is not up to date so I added the missing pieces. Not sure if this is done the right way. [akpm@osdl.org: compile fix] Signed-off-by: Christoph Lameter Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b63d64a324056cf3c2f7a1a1fe8134100edbb058 Author: Christoph Lameter Date: Fri Jun 23 02:03:56 2006 -0700 [PATCH] sys_move_pages: x86_64 support sys_move_pages support for x86_64 Signed-off-by: Christoph Lameter Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 742755a1d8ce2b548428f7aacf1758b4bba50080 Author: Christoph Lameter Date: Fri Jun 23 02:03:55 2006 -0700 [PATCH] page migration: sys_move_pages(): support moving of individual pages move_pages() is used to move individual pages of a process. The function can be used to determine the location of pages and to move them onto the desired node. move_pages() returns status information for each page. long move_pages(pid, number_of_pages_to_move, addresses_of_pages[], nodes[] or NULL, status[], flags); The addresses of pages is an array of void * pointing to the pages to be moved. The nodes array contains the node numbers that the pages should be moved to. If a NULL is passed instead of an array then no pages are moved but the status array is updated. The status request may be used to determine the page state before issuing another move_pages() to move pages. The status array will contain the state of all individual page migration attempts when the function terminates. The status array is only valid if move_pages() completed successfullly. Possible page states in status[]: 0..MAX_NUMNODES The page is now on the indicated node. -ENOENT Page is not present -EACCES Page is mapped by multiple processes and can only be moved if MPOL_MF_MOVE_ALL is specified. -EPERM The page has been mlocked by a process/driver and cannot be moved. -EBUSY Page is busy and cannot be moved. Try again later. -EFAULT Invalid address (no VMA or zero page). -ENOMEM Unable to allocate memory on target node. -EIO Unable to write back page. The page must be written back in order to move it since the page is dirty and the filesystem does not provide a migration function that would allow the moving of dirty pages. -EINVAL A dirty page cannot be moved. The filesystem does not provide a migration function and has no ability to write back pages. The flags parameter indicates what types of pages to move: MPOL_MF_MOVE Move pages that are only mapped by the process. MPOL_MF_MOVE_ALL Also move pages that are mapped by multiple processes. Requires sufficient capabilities. Possible return codes from move_pages() -ENOENT No pages found that would require moving. All pages are either already on the target node, not present, had an invalid address or could not be moved because they were mapped by multiple processes. -EINVAL Flags other than MPOL_MF_MOVE(_ALL) specified or an attempt to migrate pages in a kernel thread. -EPERM MPOL_MF_MOVE_ALL specified without sufficient priviledges. or an attempt to move a process belonging to another user. -EACCES One of the target nodes is not allowed by the current cpuset. -ENODEV One of the target nodes is not online. -ESRCH Process does not exist. -E2BIG Too many pages to move. -ENOMEM Not enough memory to allocate control array. -EFAULT Parameters could not be accessed. A test program for move_pages() may be found with the patches on ftp.kernel.org:/pub/linux/kernel/people/christoph/pmig/patches-2.6.17-rc4-mm3 From: Christoph Lameter Detailed results for sys_move_pages() Pass a pointer to an integer to get_new_page() that may be used to indicate where the completion status of a migration operation should be placed. This allows sys_move_pags() to report back exactly what happened to each page. Wish there would be a better way to do this. Looks a bit hacky. Signed-off-by: Christoph Lameter Cc: Hugh Dickins Cc: Jes Sorensen Cc: KAMEZAWA Hiroyuki Cc: Lee Schermerhorn Cc: Andi Kleen Cc: Michael Kerrisk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 95a402c3847cc16f4ba03013cd01404fa0f14c2e Author: Christoph Lameter Date: Fri Jun 23 02:03:53 2006 -0700 [PATCH] page migration: use allocator function for migrate_pages() Instead of passing a list of new pages, pass a function to allocate a new page. This allows the correct placement of MPOL_INTERLEAVE pages during page migration. It also further simplifies the callers of migrate pages. migrate_pages() becomes similar to migrate_pages_to() so drop migrate_pages_to(). The batching of new page allocations becomes unnecessary. Signed-off-by: Christoph Lameter Cc: Hugh Dickins Cc: Jes Sorensen Cc: KAMEZAWA Hiroyuki Cc: Lee Schermerhorn Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit aaa994b300a172afafab47938804836b923e5ef7 Author: Christoph Lameter Date: Fri Jun 23 02:03:52 2006 -0700 [PATCH] page migration: handle freeing of pages in migrate_pages() Do not leave pages on the lists passed to migrate_pages(). Seems that we will not need any postprocessing of pages. This will simplify the handling of pages by the callers of migrate_pages(). Signed-off-by: Christoph Lameter Cc: Hugh Dickins Cc: Jes Sorensen Cc: KAMEZAWA Hiroyuki Cc: Lee Schermerhorn Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e24f0b8f76cc3dd96f36f5b6a9f020f6c3fce198 Author: Christoph Lameter Date: Fri Jun 23 02:03:51 2006 -0700 [PATCH] page migration: simplify migrate_pages() Currently migrate_pages() is mess with lots of goto. Extract two functions from migrate_pages() and get rid of the gotos. Plus we can just unconditionally set the locked bit on the new page since we are the only one holding a reference. Locking is to stop others from accessing the page once we establish references to the new page. Remove the list_del from move_to_lru in order to have finer control over list processing. [akpm@osdl.org: add debug check] Signed-off-by: Christoph Lameter Cc: Hugh Dickins Cc: Jes Sorensen Cc: KAMEZAWA Hiroyuki Cc: Lee Schermerhorn Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8f9de51a4a98ba32f839903b7d009788bc2c295d Author: Kirill Korotaev Date: Fri Jun 23 02:03:50 2006 -0700 [PATCH] printk() should not be called under zone->lock This patch fixes printk() under zone->lock in show_free_areas(). It can be unsafe to call printk() under this lock, since caller can try to allocate/free some memory and selfdeadlock on this lock. I found allocations/freeing mem both in netconsole and serial console. This issue was faced in reallity when meminfo was periodically printed for debug purposes and netconsole was used. Signed-off-by: Kirill Korotaev Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d501e62bc7796e90b0312648e23ac39490dfbf87 Author: Ralf Baechle Date: Fri Jun 23 02:03:50 2006 -0700 [PATCH] Delete unused definitions of kvaddr_to_nid Signed-off-by: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 485bb99b49a173a22a0bbf4e189465414947ecac Author: Randy Dunlap Date: Fri Jun 23 02:03:49 2006 -0700 [PATCH] kernel-doc for mm/filemap.c mm/filemap.c: - add lots of kernel-doc; - fix some typos and kernel-doc errors; - drop some blank lines between function close and EXPORT_SYMBOL(); Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 800590f523bf3bde9fa6c8e4d6763e4bf6a2c8ec Author: Paul Drynoff Date: Fri Jun 23 02:03:48 2006 -0700 [PATCH] slab: kmalloc, kzalloc comments cleanup and fix - Move comments for kmalloc to right place, currently it near __do_kmalloc - Comments for kzalloc - More detailed comments for kmalloc - Appearance of "kmalloc" and "kzalloc" man pages after "make mandocs" [rdunlap@xenotime.net: simplification] Signed-off-by: Paul Drynoff Acked-by: Randy Dunlap Cc: Pekka Enberg Cc: Manfred Spraul Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5a4d43615921575b0c8299a5407ce4836e4138fd Author: KAMEZAWA Hiroyuki Date: Fri Jun 23 02:03:47 2006 -0700 [PATCH] update vm_total_pages at memory hotadd Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit bd1e22b8e0a90f9a91e4c27db14ca15773659bf7 Author: Andrew Morton Date: Fri Jun 23 02:03:47 2006 -0700 [PATCH] initialise total_memory() earlier Initialise total_memory earlier in boot. Because if for some reason we run page reclaim early in boot, we don't want total_memory to be zero when we use it as a divisor. And rename total_memory to vm_total_pages to avoid naming clashes with architectures. Cc: Yasunori Goto Cc: KAMEZAWA Hiroyuki Cc: Martin Bligh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e0a42726794f71336ff4b26084d453dd597471ce Author: Ingo Molnar Date: Fri Jun 23 02:03:46 2006 -0700 [PATCH] mm/slab.c: fix early init assumption The SLAB bootstrap code assumes that the first two kmalloc caches created (the INDEX_AC and INDEX_L3 kmalloc caches) wont be off-slab. But due to AC and L3 structure size increase in lockdep, one of them ended up being off-slab, and subsequently crashing with: Unable to handle kernel NULL pointer dereference at 0000000000000000 RIP: [] kmem_cache_alloc+0x26/0x7d The fix is to introduce a bootstrap flag and to use it to prevent off-slab caches being created so early during bootup. (The calculation for off-slab caches is quite complex so i didnt want to complicate things with introducing yet another INDEX_ calculation, the flag approach is simpler and smaller.) Signed-off-by: Ingo Molnar Cc: Manfred Spraul Cc: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 668e0d8f1a02fd75f1c1e8142a6b08455914242c Author: Hugh Dickins Date: Fri Jun 23 02:03:45 2006 -0700 [PATCH] fix update_mmu_cache in fremap.c There are two calls to update_mmu_cache in fremap.c, both defective. The one in install_page needs to be accompanied by lazy_mmu_prot_update (some other cleanup time, move that into ia64 update_mmu_cache itself); and the one in install_file_pte should be removed since the pte is not present. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 185606fc6a120dbebffa6d06a559c20ec2b20034 Author: Hugh Dickins Date: Fri Jun 23 02:03:45 2006 -0700 [PATCH] remove unused o_flags from do_shmat Remove the unused variable o_flags from do_shmat. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 70af7c5c6492ef6ad137dbff6c4568c73edbcaf0 Author: Hugh Dickins Date: Fri Jun 23 02:03:44 2006 -0700 [PATCH] swapoff: use atomic_inc_not_zero() on mm_users Now that we have atomic_inc_not_zero, it's more elegant for try_to_unuse to use that on mm_users: doesn't actually matter at present, but safer to be sure that once mm_users has gone to 0, nothing raises it for an instant. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 9637a5efd4fbe36164c5ce7f6a0ee68b2bf22b7f Author: David Howells Date: Fri Jun 23 02:03:43 2006 -0700 [PATCH] add page_mkwrite() vm_operations method Add a new VMA operation to notify a filesystem or other driver about the MMU generating a fault because userspace attempted to write to a page mapped through a read-only PTE. This facility permits the filesystem or driver to: (*) Implement storage allocation/reservation on attempted write, and so to deal with problems such as ENOSPC more gracefully (perhaps by generating SIGBUS). (*) Delay making the page writable until the contents have been written to a backing cache. This is useful for NFS/AFS when using FS-Cache/CacheFS. It permits the filesystem to have some guarantee about the state of the cache. (*) Account and limit number of dirty pages. This is one piece of the puzzle needed to make shared writable mapping work safely in FUSE. Needed by cachefs (Or is it cachefiles? Or fscache? ). At least four other groups have stated an interest in it or a desire to use the functionality it provides: FUSE, OCFS2, NTFS and JFFS2. Also, things like EXT3 really ought to use it to deal with the case of shared-writable mmap encountering ENOSPC before we permit the page to be dirtied. From: Peter Zijlstra get_user_pages(.write=1, .force=1) can generate COW hits on read-only shared mappings, this patch traps those as mkpage_write candidates and fails to handle them the old way. Signed-off-by: David Howells Cc: Miklos Szeredi Cc: Joel Becker Cc: Mark Fasheh Cc: Anton Altaparmakov Cc: David Woodhouse Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit bd96b9eb7cfd6ab24ba244360a09980a720874d2 Author: Con Kolivas Date: Fri Jun 23 02:03:42 2006 -0700 [PATCH] mm: fix swap unused warning If CONFIG_SWAP is not defined we get: mm/vmscan.c: In function ‘remove_mapping’: mm/vmscan.c:387: warning: unused variable ‘swap’ Convert defines in swap.h into blank inline functions to fix this warning and be consistent. Signed-off-by: Con Kolivas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 30c253e6da655d73eb8bfe2adca9b8f4d82fb81e Author: Andy Whitcroft Date: Fri Jun 23 02:03:41 2006 -0700 [PATCH] sparsemem: record nid during memory present Record the node id as we mark sections for instantiation. Use this nid during instantiation to direct allocations. Signed-off-by: Andy Whitcroft Cc: Mike Kravetz Cc: Dave Hansen Cc: Mel Gorman Cc: Bob Picco Cc: Jack Steiner Cc: Yasunori Goto Cc: Martin Bligh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ddc2e812d592457747c4367fb73edcaa8e1e49ff Author: Pekka Enberg Date: Fri Jun 23 02:03:40 2006 -0700 [PATCH] slab: verify pointers before free Passing an invalid pointer to kfree() and kmem_cache_free() is likely to cause bad memory corruption or even take down the whole system because the bad pointer is likely reused immediately due to the per-CPU caches. Until now, we don't do any verification for this if CONFIG_DEBUG_SLAB is disabled. As suggested by Linus, add PageSlab check to page_to_cache() and page_to_slab() to verify pointers passed to kfree(). Also, move the stronger check from cache_free_debugcheck() to kmem_cache_free() to ensure the passed pointer actually belongs to the cache we're about to free the object. For page_to_cache() and page_to_slab(), the assertions should have virtually no extra cost (two instructions, no data cache pressure) and for kmem_cache_free() the overhead should be minimal. Signed-off-by: Pekka Enberg Cc: Manfred Spraul Cc: Christoph Lameter Cc: Linus Torvalds Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8d3c138b77f195ca0eee6fb639ae73f5ea9edb6b Author: Christoph Lameter Date: Fri Jun 23 02:03:39 2006 -0700 [PATCH] page migration: Update documentation Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 04e62a29bf157ce1edd168f2b71b533c80d13628 Author: Christoph Lameter Date: Fri Jun 23 02:03:38 2006 -0700 [PATCH] More page migration: use migration entries for file pages This implements the use of migration entries to preserve ptes of file backed pages during migration. Processes can therefore be migrated back and forth without loosing their connection to pagecache pages. Note that we implement the migration entries only for linear mappings. Nonlinear mappings still require the unmapping of the ptes for migration. And another writepage() ugliness shows up. writepage() can drop the page lock. Therefore we have to remove migration ptes before calling writepages() in order to avoid having migration entries point to unlocked pages. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 442c9137de8d769053e81d325709dca72f0b5e44 Author: Christoph Lameter Date: Fri Jun 23 02:03:38 2006 -0700 [PATCH] More page migration: do not inc/dec rss counters If we install a migration entry then the rss not really decreases since the page is just moved somewhere else. We can save ourselves the work of decrementing and later incrementing which will just eventually cause cacheline bouncing. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6c5240ae7f48c83fcaa8e24fa63e7eb09aba5651 Author: Christoph Lameter Date: Fri Jun 23 02:03:37 2006 -0700 [PATCH] Swapless page migration: modify core logic Use the migration entries for page migration This modifies the migration code to use the new migration entries. It now becomes possible to migrate anonymous pages without having to add a swap entry. We add a couple of new functions to replace migration entries with the proper ptes. We cannot take the tree_lock for migrating anonymous pages anymore. However, we know that we hold the only remaining reference to the page when the page count reaches 1. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d75a0fcda2cfc71b50e16dc89e0c32c57d427e85 Author: Christoph Lameter Date: Fri Jun 23 02:03:36 2006 -0700 [PATCH] Swapless page migration: rip out swap based logic Rip the page migration logic out. Remove all code that has to do with swapping during page migration. This also guts the ability to migrate pages to swap. No one used that so lets let it go for good. Page migration should be a bit broken after this patch. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0697212a411c1dae03c27845f2de2f3adb32c331 Author: Christoph Lameter Date: Fri Jun 23 02:03:35 2006 -0700 [PATCH] Swapless page migration: add R/W migration entries Implement read/write migration ptes We take the upper two swapfiles for the two types of migration ptes and define a series of macros in swapops.h. The VM is modified to handle the migration entries. migration entries can only be encountered when the page they are pointing to is locked. This limits the number of places one has to fix. We also check in copy_pte_range and in mprotect_pte_range() for migration ptes. We check for migration ptes in do_swap_cache and call a function that will then wait on the page lock. This allows us to effectively stop all accesses to apge. Migration entries are created by try_to_unmap if called for migration and removed by local functions in migrate.c From: Hugh Dickins Several times while testing swapless page migration (I've no NUMA, just hacking it up to migrate recklessly while running load), I've hit the BUG_ON(!PageLocked(p)) in migration_entry_to_page. This comes from an orphaned migration entry, unrelated to the current correctly locked migration, but hit by remove_anon_migration_ptes as it checks an address in each vma of the anon_vma list. Such an orphan may be left behind if an earlier migration raced with fork: copy_one_pte can duplicate a migration entry from parent to child, after remove_anon_migration_ptes has checked the child vma, but before it has removed it from the parent vma. (If the process were later to fault on this orphaned entry, it would hit the same BUG from migration_entry_wait.) This could be fixed by locking anon_vma in copy_one_pte, but we'd rather not. There's no such problem with file pages, because vma_prio_tree_add adds child vma after parent vma, and the page table locking at each end is enough to serialize. Follow that example with anon_vma: add new vmas to the tail instead of the head. (There's no corresponding problem when inserting migration entries, because a missed pte will leave the page count and mapcount high, which is allowed for. And there's no corresponding problem when migrating via swap, because a leftover swap entry will be correctly faulted. But the swapless method has no refcounting of its entries.) From: Ingo Molnar pte_unmap_unlock() takes the pte pointer as an argument. From: Hugh Dickins Several times while testing swapless page migration, gcc has tried to exec a pointer instead of a string: smells like COW mappings are not being properly write-protected on fork. The protection in copy_one_pte looks very convincing, until at last you realize that the second arg to make_migration_entry is a boolean "write", and SWP_MIGRATION_READ is 30. Anyway, it's better done like in change_pte_range, using is_write_migration_entry and make_migration_entry_read. From: Hugh Dickins Remove unnecessary obfuscation from sys_swapon's range check on swap type, which blew up causing memory corruption once swapless migration made MAX_SWAPFILES no longer 2 ^ MAX_SWAPFILES_SHIFT. Signed-off-by: Hugh Dickins Acked-by: Martin Schwidefsky Signed-off-by: Hugh Dickins Signed-off-by: Christoph Lameter Signed-off-by: Ingo Molnar From: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 8351a6e4785218a2b03c142be92926baff95ba5c Author: Christoph Lameter Date: Fri Jun 23 02:03:33 2006 -0700 [PATCH] page migration cleanup: move fallback handling into special function Move the fallback code into a new fallback function and make the function behave like any other migration function. This requires retaking the lock if pageout() drops it. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2d1db3b1170db4e8bf0531dd636742269c2cf579 Author: Christoph Lameter Date: Fri Jun 23 02:03:33 2006 -0700 [PATCH] page migration cleanup: pass "mapping" to migration functions Change handling of address spaces. Pass a pointer to the address space in which the page is migrated to all migration function. This avoids repeatedly having to retrieve the address space pointer from the page and checking it for validity. The old page mapping will change once migration has gone to a certain step, so it is less confusing to have the pointer always available. Move the setting of the mapping and index for the new page into migrate_pages(). Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c3fcf8a5daacf350f0632e1379414c01f34eeea3 Author: Christoph Lameter Date: Fri Jun 23 02:03:32 2006 -0700 [PATCH] page migration cleanup: extract try_to_unmap from migration functions Extract try_to_unmap and rename remove_references -> move_mapping try_to_unmap() may significantly change the page state by for example setting the dirty bit. It is therefore best to unmap in migrate_pages() before calling any migration functions. migrate_page_remove_references() will then only move the new page in place of the old page in the mapping. Rename the function to migrate_page_move_mapping(). This allows us to get rid of the special unmapping for the fallback path. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5b5c7120e2154239837fad5e3c7b7b781092b19c Author: Christoph Lameter Date: Fri Jun 23 02:03:29 2006 -0700 [PATCH] page migration cleanup: drop nr_refs in remove_references() Drop nr_refs parameter from migrate_page_remove_references() The nr_refs parameter is not really useful since the number of remaining references is always 1 for anonymous pages without a mapping 2 for pages with a mapping 3 for pages with a mapping and PagePrivate set. Remove the early check for the number of references since we are checking page_mapcount() earlier. Ultimately only the refcount matters after the tree_lock has been obtained. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e7340f73307abed9283d0a07570d06e228c205dd Author: Christoph Lameter Date: Fri Jun 23 02:03:29 2006 -0700 [PATCH] page migration cleanup: remove useless definitions Remove the export for migrate_page_remove_references() and migrate_page_copy() that are unlikely to be used directly by filesystems implementing migration. The export was useful when buffer_migrate_page() lived in fs/buffer.c but it has now been moved to migrate.c in the migration reorg. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1d8b85ccf1ed53a71b092fb5d807edf1ea7dabdd Author: Christoph Lameter Date: Fri Jun 23 02:03:28 2006 -0700 [PATCH] page migration cleanup: group functions Reorder functions in migrate.c. Group all migration functions for struct address_space_operations together. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7352349a19e84b28f10668eca9cbb6bbbfa9d38e Author: Christoph Lameter Date: Fri Jun 23 02:03:27 2006 -0700 [PATCH] page migration cleanup: rename "ignrefs" to "migration" migrate is a better name since it is only used by page migration. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 111ebb6e6f7bd7de6d722c5848e95621f43700d9 Author: OGAWA Hirofumi Date: Fri Jun 23 02:03:26 2006 -0700 [PATCH] writeback: fix range handling When a writeback_control's `start' and `end' fields are used to indicate a one-byte-range starting at file offset zero, the required values of .start=0,.end=0 mean that the ->writepages() implementation has no way of telling that it is being asked to perform a range request. Because we're currently overloading (start == 0 && end == 0) to mean "this is not a write-a-range request". To make all this sane, the patch changes range of writeback_control. So caller does: If it is calling ->writepages() to write pages, it sets range (range_start/end or range_cyclic) always. And if range_cyclic is true, ->writepages() thinks the range is cyclic, otherwise it just uses range_start and range_end. This patch does, - Add LLONG_MAX, LLONG_MIN, ULLONG_MAX to include/linux/kernel.h -1 is usually ok for range_end (type is long long). But, if someone did, range_end += val; range_end is "val - 1" u64val = range_end >> bits; u64val is "~(0ULL)" or something, they are wrong. So, this adds LLONG_MAX to avoid nasty things, and uses LLONG_MAX for range_end. - All callers of ->writepages() sets range_start/end or range_cyclic. - Fix updates of ->writeback_index. It seems already bit strange. If it starts at 0 and ended by check of nr_to_write, this last index may reduce chance to scan end of file. So, this updates ->writeback_index only if range_cyclic is true or whole-file is scanned. Signed-off-by: OGAWA Hirofumi Cc: Nathan Scott Cc: Anton Altaparmakov Cc: Steven French Cc: "Vladimir V. Saveliev" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4c91c3648c620003cb7b21b8858f36cd6132e168 Author: Peter Zijlstra Date: Fri Jun 23 02:03:25 2006 -0700 [PATCH] buglet in radix_tree_tag_set The comment states: 'Setting a tag on a not-present item is a BUG.' Hence if 'index' is larger than the maxindex; the item _cannot_ be presen; it should also be a BUG. Also, this allows the following statement (assume a fresh tree): radix_tree_tag_set(root, 16, 1); to fail silently, but when preceded by: radix_tree_insert(root, 32, item); it would BUG, because the height has been extended by the insert. In neither case was 16 present. Signed-off-by: Peter Zijlstra Acked-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 58ce1fd5805647a58a050bbbbd2252ea5ecb47b3 Author: Pekka Enberg Date: Fri Jun 23 02:03:24 2006 -0700 [PATCH] slab: redzone double-free detection At present our slab debugging tells us that it detected a double-free or corruption - it does not distinguish between them. Sometimes it's useful to be able to differentiate between these two types of information. Add double-free detection to redzone verification when freeing an object. As explained by Manfred, when we are freeing an object, both redzones should be RED_ACTIVE. However, if both are RED_INACTIVE, we are trying to free an object that was already free'd. Signed-off-by: Manfred Spraul Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit b344e05c585406904c70865e531e02467c4c7931 Author: Hua Zhong Date: Fri Jun 23 02:03:23 2006 -0700 [PATCH] likely cleanup: remove unlikely in sys_mprotect() With likely/unlikely profiling on my not-so-busy-typical-developmentsystem there are 5k misses vs 2k hits. So I guess we should remove the unlikely. Signed-off-by: Hua Zhong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cfd9b7df4abd3257c9e381b0e445817b26a51c0c Author: Nick Piggin Date: Fri Jun 23 02:03:22 2006 -0700 [PATCH] radix-tree: small Reduce radix tree node memory usage by about a factor of 4 for small files (< 64K). There are pointer traversal and memory usage costs for large files with dense pagecache. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 612d6c19db2fd0dc97b0fa370613ecd4a305ffc3 Author: Nick Piggin Date: Fri Jun 23 02:03:22 2006 -0700 [PATCH] radix-tree: direct data The ability to have height 0 radix trees (a direct pointer to the data item rather than going through a full node->slot) quietly disappeared with old-2.6-bkcvs commit ffee171812d51652f9ba284302d9e5c5cc14bdfd. On 64-bit machines this causes nearly 600 bytes to be used for every <= 4K file in pagecache. Re-introduce this feature, root tags stored in spare ->gfp_mask bits. Simplify radix_tree_delete's complex tag clearing arrangement (which would become even more complex) by just falling back to tag clearing functions (the pagecache radix-tree never uses this path anyway, so the icache savings will mean it's actually a speedup). On my 4GB G5, this saves 8MB RAM per kernel kernel source+object tree in pagecache. Pagecache lookup, insertion, and removal speed for small files will also be improved. This makes RCU radix tree harder, but it's worth it. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 929f97276bcf7f4a95272ed08a85339b98ba210d Author: Dean Nelson Date: Fri Jun 23 02:03:21 2006 -0700 [PATCH] change gen_pool allocator to not touch managed memory Modify the gen_pool allocator (lib/genalloc.c) to utilize a bitmap scheme instead of the buddy scheme. The purpose of this change is to eliminate the touching of the actual memory being allocated. Since the change modifies the interface, a change to the uncached allocator (arch/ia64/kernel/uncached.c) is also required. Both Andrey Volkov and Jes Sorenson have expressed a desire that the gen_pool allocator not write to the memory being managed. See the following: http://marc.theaimsgroup.com/?l=linux-kernel&m=113518602713125&w=2 http://marc.theaimsgroup.com/?l=linux-kernel&m=113533568827916&w=2 Signed-off-by: Dean Nelson Cc: Andrey Volkov Acked-by: Jes Sorensen Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 833423143c3a7c6545e409d65febd0d92deb351b Author: Nick Piggin Date: Fri Jun 23 02:03:20 2006 -0700 [PATCH] mm: introduce remap_vmalloc_range() Add remap_vmalloc_range, vmalloc_user, and vmalloc_32_user so that drivers can have a nice interface for remapping vmalloc memory. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 762834e8bf46bf41ce9034d062a7c1f8563175f3 Author: Yasunori Goto Date: Fri Jun 23 02:03:19 2006 -0700 [PATCH] Unify pxm_to_node() and node_to_pxm() Consolidate the various arch-specific implementations of pxm_to_node() and node_to_pxm() into a single generic version. Signed-off-by: Yasunori Goto Cc: "Luck, Tony" Cc: Andi Kleen Cc: Dave Hansen Cc: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d6277db4ab271862ed599da08d78961c70f00002 Author: Rafael J. Wysocki Date: Fri Jun 23 02:03:18 2006 -0700 [PATCH] swsusp: rework memory shrinker Rework the swsusp's memory shrinker in the following way: - Simplify balance_pgdat() by removing all of the swsusp-related code from it. - Make shrink_all_memory() use shrink_slab() and a new function shrink_all_zones() which calls shrink_active_list() and shrink_inactive_list() directly for each zone in a way that's optimized for suspend. In shrink_all_memory() we try to free exactly as many pages as the caller asks for, preferably in one shot, starting from easier targets.  If slab caches are huge, they are most likely to have enough pages to reclaim.  The inactive lists are next (the zones with more inactive pages go first) etc. Each time shrink_all_memory() attempts to shrink the active and inactive lists for each zone in 5 passes.  In the first pass, only the inactive lists are taken into consideration.  In the next two passes the active lists are also shrunk, but mapped pages are not reclaimed.  In the last two passes the active and inactive lists are shrunk and mapped pages are reclaimed as well. The aim of this is to alter the reclaim logic to choose the best pages to keep on resume and improve the responsiveness of the resumed system. Signed-off-by: Rafael J. Wysocki Signed-off-by: Con Kolivas Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7a7c381d25067b9a2bfe025dfcb16459daec0373 Author: Christoph Hellwig Date: Fri Jun 23 02:03:17 2006 -0700 [PATCH] slab: stop using list_for_each Use the _entry variant everywhere to clean the code up a tiny bit. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e1b6aa6f1404f162697650df2cdb6c374b1d6a5b Author: Christoph Hellwig Date: Fri Jun 23 02:03:17 2006 -0700 [PATCH] slab: clean up kmem_getpages The last ifdef addition hit the ugliness treshold on this functions, so: - rename the variable i to nr_pages so it's somewhat descriptive - remove the addr variable and do the page_address call at the very end - instead of ifdef'ing the whole alloc_pages_node call just make the __GFP_COMP addition to flags conditional - rewrite the __GFP_COMP comment to make sense Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit a43a8c39bbb493c9e93f6764b350de2e33e18e92 Author: Chen, Kenneth W Date: Fri Jun 23 02:03:15 2006 -0700 [PATCH] tightening hugetlb strict accounting Current hugetlb strict accounting for shared mapping always assume mapping starts at zero file offset and reserves pages between zero and size of the file. This assumption often reserves (or lock down) a lot more pages then necessary if application maps at none zero file offset. libhugetlbfs is one example that requires proper reservation on shared mapping starts at none zero offset. This patch extends the reservation and hugetlb strict accounting to support any arbitrary pair of (offset, len), resulting a much more robust and accurate scheme. More importantly, it won't lock down any hugetlb pages outside file mapping. Signed-off-by: Ken Chen Acked-by: Adam Litke Cc: David Gibson Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit e8f03d02080b25f53cd6bba8dc3a297803f18c01 Author: Andreas Dilger Date: Fri Jun 23 02:03:14 2006 -0700 [PATCH] reserve space for swap label Reserve space in the swap disk header for a LABEL and UUID to be specified. This has been possible with util-linux-2.12b (via e2fsprogs 1.36 libblkid), and is used by at least FC3 and later. The kernel doesn't really care about this, but the space shouldn't accidentally be used by something else either. Also make the on-disk structures be fixed-size types, instead of "int", though I don't know of any architecture in use where an "int" isn't the same size as a "__u32" (all current kernel arches have it as "unsigned int"). Signed-off-by: Andreas Dilger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6937a25cff818d32d0f9ff58a518c9ab96760aeb Author: Dave Peterson Date: Fri Jun 23 02:03:13 2006 -0700 [PATCH] mm: fix typos in comments in mm/oom_kill.c This fixes a few typos in the comments in mm/oom_kill.c. Signed-off-by: David S. Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit fadd8fbd153c12963f8fe3c9ef7f8967f286f98b Author: KAMEZAWA Hiroyuki Date: Fri Jun 23 02:03:13 2006 -0700 [PATCH] support for panic at OOM This patch adds panic_on_oom sysctl under sys.vm. When sysctl vm.panic_on_oom = 1, the kernel panics intead of killing rogue processes. And if vm.panic_on_oom is 0 the kernel will do oom_kill() in the same way as it does today. Of course, the default value is 0 and only root can modifies it. In general, oom_killer works well and kill rogue processes. So the whole system can survive. But there are environments where panic is preferable rather than kill some processes. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 67de648211fa041fe08a0c25241a4980bbb90698 Author: Andy Whitcroft Date: Fri Jun 23 02:03:12 2006 -0700 [PATCH] squash duplicate page_to_pfn and pfn_to_page We have architectures where the size of page_to_pfn and pfn_to_page are significant enough to overall image size that they wish to push them out of line. However, in the process we have grown a second copy of the implementation of each of these routines for each memory model. Share the implmentation exposing it either inline or out-of-line as required. Signed-off-by: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6811378e7d8b9aa4fca2a1ca73d24c9d67c9cb12 Author: Yasunori Goto Date: Fri Jun 23 02:03:11 2006 -0700 [PATCH] wait_table and zonelist initializing for memory hotadd: update zonelists In current code, zonelist is considered to be build once, no modification. But MemoryHotplug can add new zone/pgdat. It must be updated. This patch modifies build_all_zonelists(). By this, build_all_zonelist() can reconfig pgdat's zonelists. To update them safety, this patch use stop_machine_run(). Other cpus don't touch among updating them by using it. In old version (V2 of node hotadd), kernel updated them after zone initialization. But present_page of its new zone is still 0, because online_page() is not called yet at this time. Build_zonelists() checks present_pages to find present zone. It was too early. So, I changed it after online_pages(). Signed-off-by: Yasunori Goto Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cca448fe92246fb59efe55ba2e048ded0971a9af Author: Yasunori Goto Date: Fri Jun 23 02:03:10 2006 -0700 [PATCH] wait_table and zonelist initializing for memory hotadd: wait_table initialization Wait_table is initialized according to zone size at boot time. But, we cannot know the maixmum zone size when memory hotplug is enabled. It can be changed.... And resizing of wait_table is hard. So kernel allocate and initialzie wait_table as its maximum size. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 718127cc3170454f4aa274fdd2f1e01574fecd66 Author: Yasunori Goto Date: Fri Jun 23 02:03:10 2006 -0700 [PATCH] wait_table and zonelist initializing for memory hotadd: add return code for init_current_empty_zone When add_zone() is called against empty zone (not populated zone), we have to initialize the zone which didn't initialize at boot time. But, init_currently_empty_zone() may fail due to allocation of wait table. So, this patch is to catch its error code. Changes against wait_table is in the next patch. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 86356ab147669bd3bcb2149fd9561d1280835c24 Author: Yasunori Goto Date: Fri Jun 23 02:03:09 2006 -0700 [PATCH] wait_table and zonelist initializing for memory hotadd: change to meminit for build_zonelist Change definitions of some functions and data from __init to __meminit. These functions and data can be used after bootup by this patch to be used for hot-add codes. Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 02b694dea473ad3db1e2d1b14c1fef8fbd92e5e6 Author: Yasunori Goto Date: Fri Jun 23 02:03:08 2006 -0700 [PATCH] wait_table and zonelist initializing for memory hotadd: change name of wait_table_size() This is just to rename from wait_table_size() to wait_table_hash_nr_entries(). Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 3c5a87f476bed45616e7e543dcaea4440c77bf93 Author: Christoph Lameter Date: Fri Jun 23 02:03:08 2006 -0700 [PATCH] migration: remove unnecessary PageSwapCache checks Remove two unnecessary PageSwapCache checks. The page refcount is raised and therefore page migration cannot occur in both functions. Signed-off-by: Christoph Lameter Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4776874ff096cd410382c0eca5d75f69c9dfa58f Author: Pekka Enberg Date: Fri Jun 23 02:03:07 2006 -0700 [PATCH] slab: page mapping cleanup Clean up slab allocator page mapping a bit. The memory allocated for a slab is physically contiguous so it is okay to assume struct pages are too so kill the long-standing comment. Furthermore, rename set_slab_attr to slab_map_pages and add a comment explaining why its needed. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f886ed443fedb109e2062988bf120a531f0ec80a Author: Andrew Morton Date: Fri Jun 23 02:03:06 2006 -0700 [PATCH] PG_uncached is ia64 only As Nick points out, only ia64 uses PG_uncached. So we can push it up into the higher bits of the lower half of page->flags and make room for another flag on 32-bit machines. Cc: "Luck, Tony" Cc: Jesse Barnes Cc: Jes Sorensen Cc: Nick Piggin Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 729bd0b74ce9ac6c829109052fcd565f5c366ca5 Author: Pekka Enberg Date: Fri Jun 23 02:03:05 2006 -0700 [PATCH] slab: extract cache_free_alien from __cache_free Move alien object freeing to cache_free_alien() to reduce #ifdef clutter in __cache_free(). Signed-off-by: Pekka Enberg Acked-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4da5eda0dca9730f59f391230304526ab4bffec7 Author: Christoph Lameter Date: Fri Jun 23 02:03:04 2006 -0700 [PATCH] Page Migration: Make do_swap_page redo the fault It is better to redo the complete fault if do_swap_page() finds that the page is not in PageSwapCache() because the page migration code may have replaced the swap pte already with a pte pointing to valid memory. do_swap_page() may interpret an invalid swap entry without this patch because we do not reload the pte if we are looping back. The page migration code may already have reused the swap entry referenced by our local swp_entry. Signed-off-by: Christoph Lameter Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit cb2b95e1c6b56e3d2369d3a5f4bc97f4fa180683 Author: Andy Whitcroft Date: Fri Jun 23 02:03:01 2006 -0700 [PATCH] zone handle unaligned zone boundaries The buddy allocator has a requirement that boundaries between contigious zones occur aligned with the the MAX_ORDER ranges. Where they do not we will incorrectly merge pages cross zone boundaries. This can lead to pages from the wrong zone being handed out. Originally the buddy allocator would check that buddies were in the same zone by referencing the zone start and end page frame numbers. This was removed as it became very expensive and the buddy allocator already made the assumption that zones boundaries were aligned. It is clear that not all configurations and architectures are honouring this alignment requirement. Therefore it seems safest to reintroduce support for non-aligned zone boundaries. This patch introduces a new check when considering a page a buddy it compares the zone_table index for the two pages and refuses to merge the pages where they do not match. The zone_table index is unique for each node/zone combination when FLATMEM/DISCONTIGMEM is enabled and for each section/zone combination when SPARSEMEM is enabled (a SPARSEMEM section is at least a MAX_ORDER size). Signed-off-by: Andy Whitcroft Cc: Dave Hansen Cc: Mel Gorman Cc: Yasunori Goto Cc: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6f0419e06a3b151ab616a31accdabef41dc2d1b0 Author: KAMEZAWA Hiroyuki Date: Fri Jun 23 02:03:00 2006 -0700 [PATCH] for_each_possible_cpu: xfs for_each_cpu() actually iterates across all possible CPUs. We've had mistakes in the past where people were using for_each_cpu() where they should have been iterating across only online or present CPUs. This is inefficient and possibly buggy. We're renaming for_each_cpu() to for_each_possible_cpu() to avoid this in the future. This patch replaces for_each_cpu with for_each_possible_cpu. in xfs. Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Nathan Scott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d6938d1b2768fbf94d1091207d334ef7df786e5a Author: David Howells Date: Fri Jun 23 02:02:59 2006 -0700 [PATCH] XFS: Use the dentry passed to statfs() to limit the scope of the results Enable XFS to limit the statfs() results to the project quota covering the dentry used as a base for call. Signed-off-by: David Howells Signed-off-by: Nathan Scott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 726c334223180e3c0197cc980a432681370d4baf Author: David Howells Date: Fri Jun 23 02:02:58 2006 -0700 [PATCH] VFS: Permit filesystem to perform statfs with a known root dentry Give the statfs superblock operation a dentry pointer rather than a superblock pointer. This complements the get_sb() patch. That reduced the significance of sb->s_root, allowing NFS to place a fake root there. However, NFS does require a dentry to use as a target for the statfs operation. This permits the root in the vfsmount to be used instead. linux/mount.h has been added where necessary to make allyesconfig build successfully. Interest has also been expressed for use with the FUSE and XFS filesystems. Signed-off-by: David Howells Acked-by: Al Viro Cc: Nathan Scott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 454e2398be9b9fa30433fccc548db34d19aa9958 Author: David Howells Date: Fri Jun 23 02:02:57 2006 -0700 [PATCH] VFS: Permit filesystem to override root dentry on mount Extend the get_sb() filesystem operation to take an extra argument that permits the VFS to pass in the target vfsmount that defines the mountpoint. The filesystem is then required to manually set the superblock and root dentry pointers. For most filesystems, this should be done with simple_set_mnt() which will set the superblock pointer and then set the root dentry to the superblock's s_root (as per the old default behaviour). The get_sb() op now returns an integer as there's now no need to return the superblock pointer. This patch permits a superblock to be implicitly shared amongst several mount points, such as can be done with NFS to avoid potential inode aliasing. In such a case, simple_set_mnt() would not be called, and instead the mnt_root and mnt_sb would be set directly. The patch also makes the following changes: (*) the get_sb_*() convenience functions in the core kernel now take a vfsmount pointer argument and return an integer, so most filesystems have to change very little. (*) If one of the convenience function is not used, then get_sb() should normally call simple_set_mnt() to instantiate the vfsmount. This will always return 0, and so can be tail-called from get_sb(). (*) generic_shutdown_super() now calls shrink_dcache_sb() to clean up the dcache upon superblock destruction rather than shrink_dcache_anon(). This is required because the superblock may now have multiple trees that aren't actually bound to s_root, but that still need to be cleaned up. The currently called functions assume that the whole tree is rooted at s_root, and that anonymous dentries are not the roots of trees which results in dentries being left unculled. However, with the way NFS superblock sharing are currently set to be implemented, these assumptions are violated: the root of the filesystem is simply a dummy dentry and inode (the real inode for '/' may well be inaccessible), and all the vfsmounts are rooted on anonymous[*] dentries with child trees. [*] Anonymous until discovered from another tree. (*) The documentation has been adjusted, including the additional bit of changing ext2_* into foo_* in the documentation. [akpm@osdl.org: convert ipath_fs, do other stuff] Signed-off-by: David Howells Acked-by: Al Viro Cc: Nathan Scott Cc: Roland Dreier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 1ad5544098a69d7dc1fa508cbb17e13a7a952fd8 Author: Rachita Kothiyal Date: Fri Jun 23 02:02:56 2006 -0700 [PATCH] Fix cdrom being confused on using kdump I have seen the cdrom drive appearing confused on using kdump on certain x86_64 systems. During the booting up of the second kernel, the following message would keep flooding the console, and the booting would not proceed any further. hda: cdrom_pc_intr: The drive appears confused (ireason = 0x01) In this patch, whenever we are hitting a confused state in the interrupt handler with the DRQ set, we end the request and return ide_stopped. Using this I dont see the status error. Signed-off-by: Rachita Kothiyal Acked-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit ca6bb5d7ab22ac79f608fe6cbc6b12de6a5a19f0 Author: David Woodhouse Date: Thu Jun 22 16:07:52 2006 -0700 [NET]: Require CAP_NET_ADMIN to create tuntap devices. The tuntap driver allows an admin to create persistent devices and assign ownership of them to individual users. Unfortunately, relaxing the permissions on the /dev/net/tun device node so that they can actually use those devices will _also_ allow those users to create arbitrary new devices of their own. This patch corrects that, and adjusts the recommended permissions for the device node accordingly. Signed-off-By: David Woodhouse Signed-off-by: David S. Miller commit f4b8ea7849544114e9d3d682df4d400180854677 Author: Randy Dunlap Date: Thu Jun 22 16:00:11 2006 -0700 [NET]: fix net-core kernel-doc Warning(/var/linsrc/linux-2617-g4//include/linux/skbuff.h:304): No description found for parameter 'dma_cookie' Warning(/var/linsrc/linux-2617-g4//include/net/sock.h:1274): No description found for parameter 'copied_early' Warning(/var/linsrc/linux-2617-g4//net/core/dev.c:3309): No description found for parameter 'chan' Warning(/var/linsrc/linux-2617-g4//net/core/dev.c:3309): No description found for parameter 'event' Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller commit c8a553ad7f0bf943047943a758cf07017819cb3c Author: David Woodhouse Date: Thu Jun 22 14:28:09 2006 -0700 [TCP]: Move inclusion of to correct place in The new header shouldn't be included from the !__KERNEL__ portion of tcp.h Signed-off-by: David Woodhouse Signed-off-by: David S. Miller commit 09b8f7a93efd4b2c4ef391e2fbf076f28c6d36d6 Author: Herbert Xu Date: Thu Jun 22 03:08:03 2006 -0700 [IPSEC]: Handle GSO packets This patch segments GSO packets received by the IPsec stack. This can happen when a NIC driver injects GSO packets into the stack which are then forwarded to another host. The primary application of this is going to be Xen where its backend driver may inject GSO packets into dom0. Of course this also can be used by other virtualisation schemes such as VMWare or UML since the tap device could be modified to inject GSO packets received through splice. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit 37c3185a02d4b85fbe134bf5204535405dd2c957 Author: Herbert Xu Date: Thu Jun 22 03:07:29 2006 -0700 [NET]: Added GSO toggle This patch adds a generic segmentation offload toggle that can be turned on/off for each net device. For now it only supports in TCPv4. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit f4c50d990dcf11a296679dc05de3873783236711 Author: Herbert Xu Date: Thu Jun 22 03:02:40 2006 -0700 [NET]: Add software TSOv4 This patch adds the GSO implementation for IPv4 TCP. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit f6a78bfcb141f963187464bac838d46a81c3882a Author: Herbert Xu Date: Thu Jun 22 02:57:17 2006 -0700 [NET]: Add generic segmentation offload This patch adds the infrastructure for generic segmentation offload. The idea is to tap into the potential savings of TSO without hardware support by postponing the allocation of segmented skb's until just before the entry point into the NIC driver. The same structure can be used to support software IPv6 TSO, as well as UFO and segmentation offload for other relevant protocols, e.g., DCCP. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit 7967168cefdbc63bf332d6b1548eca7cd65ebbcc Author: Herbert Xu Date: Thu Jun 22 02:40:14 2006 -0700 [NET]: Merge TSO/UFO fields in sk_buff Having separate fields in sk_buff for TSO/UFO (tso_size/ufo_size) is not going to scale if we add any more segmentation methods (e.g., DCCP). So let's merge them. They were used to tell the protocol of a packet. This function has been subsumed by the new gso_type field. This is essentially a set of netdev feature bits (shifted by 16 bits) that are required to process a specific skb. As such it's easy to tell whether a given device can process a GSO skb: you just have to and the gso_type field and the netdev's features field. I've made gso_type a conjunction. The idea is that you have a base type (e.g., SKB_GSO_TCPV4) that can be modified further to support new features. For example, if we add a hardware TSO type that supports ECN, they would declare NETIF_F_TSO | NETIF_F_TSO_ECN. All TSO packets with CWR set would have a gso_type of SKB_GSO_TCPV4 | SKB_GSO_TCPV4_ECN while all other TSO packets would be SKB_GSO_TCPV4. This means that only the CWR packets need to be emulated in software. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit d4828d85d188dc70ed172802e798d3978bb6e29e Author: Herbert Xu Date: Thu Jun 22 02:28:18 2006 -0700 [NET]: Prevent transmission after dev_deactivate The dev_deactivate function has bit-rotted since the introduction of lockless drivers. In particular, the spin_unlock_wait call at the end has no effect on the xmit routine of lockless drivers. With a little bit of work, we can make it much more useful by providing the guarantee that when it returns, no more calls to the xmit routine of the underlying driver will be made. The idea is simple. There are two entry points in to the xmit routine. The first comes from dev_queue_xmit. That one is easily stopped by using synchronize_rcu. This works because we set the qdisc to noop_qdisc before the synchronize_rcu call. That in turn causes all subsequent packets sent to dev_queue_xmit to be dropped. The synchronize_rcu call also ensures all outstanding calls leave their critical section. The other entry point is from qdisc_run. Since we now have a bit that indicates whether it's running, all we have to do is to wait until the bit is off. I've removed the loop to wait for __LINK_STATE_SCHED to clear. This is useless because netif_wake_queue can cause it to be set again. It is also harmless because we've disarmed qdisc_run. I've also removed the spin_unlock_wait on xmit_lock because its only purpose of making sure that all outstanding xmit_lock holders have exited is also given by dev_watchdog_down. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit 5e2707fa3aed8c24075087cbaea2628725adbe55 Author: YOSHIFUJI Hideaki Date: Thu Jun 22 01:41:18 2006 -0700 [IPV6] ADDRCONF: Fix default source address selection without CONFIG_IPV6_PRIVACY We need to update hiscore.rule even if we don't enable CONFIG_IPV6_PRIVACY, because we have more less significant rule; longest match. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller commit 102128e3a27821bdcbacb10f4f2bba253f587ba4 Author: Åukasz Stelmach Date: Thu Jun 22 01:37:19 2006 -0700 [IPV6]: Fix source address selection. Two additional labels (RFC 3484, sec. 10.3) for IPv6 addreses are defined to make a distinction between global unicast addresses and Unique Local Addresses (fc00::/7, RFC 4193) and Teredo (2001::/32, RFC 4380). It is necessary to avoid attempts of connection that would either fail (eg. fec0:: to 2001:feed::) or be sub-optimal (2001:0:: to 2001:feed::). Signed-off-by: Åukasz Stelmach Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller commit 5b057c6b1a25d57edf2b4d1e956e50936480a9ff Author: Herbert Xu Date: Fri Jun 23 02:06:41 2006 -0700 [NET]: Avoid allocating skb in skb_pad First of all it is unnecessary to allocate a new skb in skb_pad since the existing one is not shared. More importantly, our hard_start_xmit interface does not allow a new skb to be allocated since that breaks requeueing. This patch uses pskb_expand_head to expand the existing skb and linearize it if needed. Actually, someone should sift through every instance of skb_pad on a non-linear skb as they do not fit the reasons why this was originally created. Incidentally, this fixes a minor bug when the skb is cloned (tcpdump, TCP, etc.). As it is skb_pad will simply write over a cloned skb. Because of the position of the write it is unlikely to cause problems but still it's best if we don't do it. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit 0dd4b21f517e138ea113db255645fbae1bf5eef3 Author: Borislav Petkov Date: Fri Jun 23 02:29:08 2006 -0400 [libata] conversion to new debug scheme, part 1 of $N The first 25% of libata-core.c converted to the new debugging scheme. Signed-off-by: (with addition of ATA_MSG_WARN to standard msg_enable by me) Signed-off-by: Jeff Garzik commit 5d9fd169c9fbdaecdc430431e59bf94ff40b93d3 Author: Greg Kroah-Hartman Date: Thu Jun 22 17:17:32 2006 -0700 [PATCH] Driver core: fix locking issues with the devices that are attached to classes Doh, that was foolish... Signed-off-by: Greg Kroah-Hartman commit 0517587e5896cef1d5f99d3b24f5f2ca15d952ad Author: Greg Kroah-Hartman Date: Thu Jun 22 13:29:52 2006 -0700 [PATCH] USB: get USB suspend to work again Yeah, it's a hack, but it is only temporary until Alan's patches reworking this area make it in. We really should not care what devices below us are doing, especially when we do not really know what type of devices they are. This patch relies on the fact that the endpoint devices do not have a driver assigned to us. Signed-off-by: Greg Kroah-Hartman commit 99ba9e093d058f6dff54f475136018e2e281d50f Author: Brian King Date: Mon Jun 12 14:54:17 2006 -0500 [PATCH] libata: Add ata_scsi_dev_disabled Separate out parts of ata_scsi_find_dev to be reused in future SAS/SATA patches. Acked-by: Jeff Garzik Signed-off-by: Brian King Signed-off-by: Jeff Garzik commit ba6a13083c1b720a47c05bee7bedbb6ef06c4611 Author: Jeff Garzik Date: Thu Jun 22 23:46:10 2006 -0400 [libata] Add host lock to struct ata_port Prepare for changes required to support SATA devices attached to SAS HBAs. For these devices we don't want to use host_set at all, since libata will not be the owner of struct scsi_host. Signed-off-by: Brian King (with slight merge modifications made by...) Signed-off-by: Jeff Garzik commit 47005f255ed126a4b48a1a2f63164fb1d83bcb0a Author: Tejun Heo Date: Mon Jun 19 18:27:23 2006 +0900 [PATCH] libata: implement per-dev EH action mask eh_info->dev_action[] Currently, the only per-dev EH action is REVALIDATE. EH used to exploit ehi->dev to do selective revalidation on a ATA bus. However, this is a bit hacky and makes it impossible to request selective revalidation from outside of EH or add another per-dev EH action. This patch adds per-dev EH action mask eh_info->dev_action[] and update EH to use this field for REVALIDATE. Note that per-dev actions can still be specified at port-level and it has the same effect of specifying the action for all devices on the port. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit bfcbb00855db21dacd3c154ea13ec3fdd98e747b Author: Brice Goglin Date: Thu Jun 22 21:12:36 2006 -0400 [PATCH] myri10ge - drop workaround pci_save_state() disabling MSI We don't need to restore the state right after saving it for later recovery since commit 99dc804d9bcc2c53f4c20c291bf4e185312a1a0c (PCI: disable msi mode in pci_disable_device) now prevents pci_save_state() from disabling MSI. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik commit 69eb887b0c2380791d33f7c07bfba88d7c5cef15 Author: Brice Goglin Date: Thu Jun 22 21:11:59 2006 -0400 [PATCH] myri10ge - drop workaround for the missing AER ext cap on nVidia CK804 We don't need to hardcode the AER capability of the nVidia CK804 chipset anymore since commit cf34a8e07f02c76f3f1232eecb681301a3d7b10b (PCI: nVidia quirk to make AER PCI-E extended capability visible) now makes sure that this cap will be available to pci_find_ext_capability(). Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik commit 39105890516b06319ffcf5ef0d0cea6c7f65bc96 Author: Gary Zambrano Date: Thu Jun 22 17:26:20 2006 -0700 [PATCH] add b44 to maintainers Add b44 to the MAINTAINERS file. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik commit 4446065a2c9b65398ceb115f4d8c256eb1bb9647 Author: Krzysztof Halasa Date: Thu Jun 22 22:29:28 2006 +0200 [PATCH] WAN: ioremap() failure checks in drivers Eric Sesterhenn found that pci200syn initialization lacks return statement in ioremap() error path (coverity bug id #195). It looks like more WAN drivers have problems with ioremap(). Signed-off-by: Krzysztof Halasa Signed-off-by: Jeff Garzik commit 4a31e348e3ecaf54c50240109ac4574b180f8840 Author: Krzysztof Halasa Date: Thu Jun 22 22:20:19 2006 +0200 [PATCH] WAN: register_hdlc_device() doesn't need dev_alloc_name() David Boggs noticed that register_hdlc_device() no longer needs to call dev_alloc_name() as it's called by register_netdev(). register_hdlc_device() is currently equivalent to register_netdev(). hdlc_setup() is now EXPORTed as per David's request. Signed-off-by: Krzysztof Halasa Signed-off-by: Jeff Garzik commit aa95abefccc25efea5c8654bc3475e8161319b94 Author: Alan Cox Date: Thu Jun 22 14:25:34 2006 +0100 [PATCH] skb_padto()-area fixes in 8390, wavelan Ar Iau, 2006-06-22 am 21:29 +1000, ysgrifennodd Herbert Xu: > Alan Cox wrote: > > > > The 8390 change (corrected version) also makes 8390.c faster so should > > be applied anyway, and the orinoco one fixes some code that isn't even > > needed and someone forgot to remove long ago. Otherwise the skb_padto > > Yeah I agree totally. However, I haven't actually seen the fixed 8390 > version being posted yet or at least not to netdev :) Ah the resounding clang of a subtle hint ;) Signed-off-by: Alan Cox - Return 8390.c to the old way of handling short packets (which is also faster) - Remove the skb_padto from orinoco. This got left in when the padding bad write patch was added and is actually not needed. This is fixing a merge error way back when. - Wavelan can also use the stack based buffer trick if you want Signed-off-by: Jeff Garzik commit c7985051dec26dc5ae2562a975a0b37b70621f3f Author: Adrian Bunk Date: Thu Jun 22 12:03:29 2006 +0200 [PATCH] make drivers/net/forcedeth.c:nv_update_pause() static This patch makes the needlessly global nv_update_pause() static. Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik commit 92aa674d721d089c440301ab95cb6be19c78727e Author: Sascha Hauer Date: Thu Jun 22 07:11:13 2006 +0200 [PATCH] network driver for Hilscher netx This is a patch for the Hilscher netx builtin ethernet ports. The netx board support was merged into 2.6.17-git2. The netx is a arm926 based SoC. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer -- drivers/net/Kconfig | 11 drivers/net/Makefile | 1 drivers/net/netx-eth.c | 516 ++++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-netx/eth.h | 27 ++ 4 files changed, 555 insertions(+) Signed-off-by: Jeff Garzik commit 3a778275626c0eb97674e92875efeba01189ce0e Author: Albert Lee Date: Thu Jun 22 13:00:25 2006 +0800 [PATCH] libata-dev: move the CDB-intr DMA blacklisting Move the DMA blacklisting of the CDB-intr devices from ata_check_atapi_dma() to ata_dma_blacklisted(), where it makes more sense. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 6d56ab936237b429366ade0d2a1540c7e41beb87 Author: Eric Sesterhenn Date: Wed Jun 21 16:17:17 2006 +0200 [PATCH] Dereference in tokenring/olympic.c hi, coverity found (bug id #225) that we might call free_netdev() with NULL argument, when alloc_trdev() fails. This patch changes the goto, so we dont call free_netdev() for dev == NULL. Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik commit a192491ad58098f2c57d2d1efe721ea0634dc0aa Author: Eric Sesterhenn Date: Wed Jun 21 16:40:24 2006 +0200 [PATCH] Array overrun in drivers/net/wireless/wavelan.c hi, this is another array overrun spotted by coverity (#id 507) we should check the index against array size before using it. Not sure why the driver doesnt use ARRAY_SIZE instead of its own macro. Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik commit 71f0737b2889b86f774a94afaf1342c2c0d61cb5 Author: Tejun Heo Date: Wed Jun 21 23:12:48 2006 +0900 [PATCH] ahci: disable NCQ support on vt8251 vt8251 chokes on NCQ commands. Two different disks from different vendors are showing the same symptom and it seems that the windows driver from via doesn't support NCQ either. Disable NCQ support on this controller for the time being. Signed-off-by: Tejun Heo Cc: Aalderd Bouwman Cc: Bastiaan Jacques Signed-off-by: Jeff Garzik commit da4f5ccf6040b998b64c60db8fa5f4ee03fdaf95 Author: Eric Sesterhenn Date: Wed Jun 21 16:10:48 2006 +0200 [PATCH] Remove useless check in drivers/net/pcmcia/xirc2ps_cs.c hi, coverity choked at this check (id #223), assuming that skb might be NULL and used anyways later. Since start_hard_xmit() always gets called with a valid skb, the check is useless and this patch removes it. Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik commit 722fdb33591bc7308a661913fb2f829128236b6f Author: Philip Craig Date: Wed Jun 21 11:33:27 2006 +1000 [PATCH] 8139cp: add ethtool eeprom support Implement the ethtool eeprom operations for the 8139cp driver. Tested on x86 and big-endian ARM. Signed-off-by: Philip Craig Signed-off-by: Jeff Garzik commit d73f1e3c3b0703e25728ce5bdda9806d6f2c576f Author: Philip Craig Date: Wed Jun 21 11:33:26 2006 +1000 [PATCH] 8139cp: fix eeprom read command length The read command for the 93C46/93C56 EEPROMS should be 3 bits plus the address. This doesn't appear to affect the operation of the read command, but similar errors for write commands do cause failures. Signed-off-by: Philip Craig Signed-off-by: Jeff Garzik commit 8fa29b23d9e0ef976dc578aab98297d4f24f70da Author: Jeff Garzik Date: Thu Jun 22 23:19:15 2006 -0400 [libata] ahci: add JMicron PCI IDs Originally contributed by Justin @ JMicron. Signed-off-by: Jeff Garzik commit fc13dcae24bfd877aeff07774c035b2b896e05ca Author: Gary Zambrano Date: Tue Jun 20 15:34:46 2006 -0700 [PATCH] b44: update b44 Kconfig entry Deleted "EXPERIMENTAL" from b44 entry in Kconfig. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik commit 4d1dabdb52ee49f24cf874b6af2cd2c9efd9444a Author: Gary Zambrano Date: Tue Jun 20 15:34:40 2006 -0700 [PATCH] b44: update version to 1.01 Update the driver version to 1.01 Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik commit 725ad800b73a71fe91bfd8859f928852de688ea0 Author: Gary Zambrano Date: Tue Jun 20 15:34:36 2006 -0700 [PATCH] b44: add wol for old nic This patch adds wol support for the older 440x nics that use pattern matching. This patch is a redo thanks to feedback from Michael Chan and Francois Romieu. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik commit 00e8b3aa1cfd7577fd4019a24f7c3980506f83f3 Author: Gary Zambrano Date: Tue Jun 20 15:34:26 2006 -0700 [PATCH] b44: add parameter This patch adds a parameter to init_hw() to not completely initialize the nic for wol. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik commit 52cafd965507b7a7bb962486539f6d7422552692 Author: Gary Zambrano Date: Tue Jun 20 15:34:23 2006 -0700 [PATCH] b44: add wol Adds wol to the driver. This is a redo of a previous patch thanks to feedback from Francois Romieu. Signed-off-by Gary Zambrano Signed-off-by: Jeff Garzik commit 47b9c3b1e6afa3c40e3ac1822cd13946567b5955 Author: Gary Zambrano Date: Tue Jun 20 15:34:15 2006 -0700 [PATCH] b44: fix manual speed/duplex/autoneg settings Fixes for speed/duplex/autoneg settings and driver settings info. This is a redo of a previous patch thanks to feedback from Jeff Garzik. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik commit c57c064994f1544a5ed2e9b319ebd0bc087ea540 Author: Jeff Garzik Date: Thu Jun 22 23:12:24 2006 -0400 [libata] sata_nv: add PCI IDs Based on a patch contributed by Andrew Chew @ NVIDIA. Signed-off-by: Jeff Garzik commit fe7fa31aa0749d7d247d21e1880f0c5aea15b158 Author: Jeff Garzik Date: Thu Jun 22 23:05:36 2006 -0400 [libata] ahci: Add NVIDIA PCI IDs. Based on a patch by Andrew Chew @ NVIDIA. Signed-off-by: Jeff Garzik commit 00e5edcbfdb7030f6cbb8d5d89fdc2848133a182 Author: Andrew Victor Date: Tue Jun 20 12:19:13 2006 +0200 [PATCH] AT91RM9200 Ethernet #4: Suspend/Resume Adds power-management (suspend/resume) support to the AT91RM9200 Ethernet driver. Patch from David Brownell. Signed-off-by: Andrew Victor Signed-off-by: Jeff Garzik commit 427d269f17fd02d192e9ae3bd93bdc07790fa02c Author: Andrew Victor Date: Tue Jun 20 12:10:57 2006 +0200 [PATCH] AT91RM9200 Ethernet #3: Cleanup Moved global ether_clk variable into controller data structure. Patch from David Brownell. Davicom 9161 PHY was being incorrectly displayed as "9196". Patch from Brian Stafford. clk_get() doesn't return NULL on error, so the return value needs to be tested with IS_ERR(). Whitespace cleanup. Signed-off-by: Andrew Victor Signed-off-by: Jeff Garzik commit ca5585ed248dc01ce918002ee9a9c9c41ae4f7c0 Author: Andrew Victor Date: Tue Jun 20 11:59:05 2006 +0200 [PATCH] AT91RM9200 Ethernet #2: MII interface Adds support for the MII ioctls via generic_mii_ioctl(). Patch from Brian Stafford. Set the mii.phy_id to the detected PHY address, otherwise ethtool cannot access PHYs other than 0. Patch from Roman Kolesnikov. Signed-off-by: Andrew Victor Signed-off-by: Jeff Garzik commit 775637df0caccc204628ebacca2b07f35c88b96b Author: Andrew Victor Date: Tue Jun 20 11:50:23 2006 +0200 [PATCH] AT91RM9200 Ethernet #1: Link poll For Ethernet PHYs that don't have an IRQ pin or boards that don't connect the IRQ pin to the processor, we enable a timer to poll the PHY's link state. Patch originally supplied by Eric Benard and Roman Kolesnikov. Signed-off-by: Andrew Victor Signed-off-by: Jeff Garzik commit d955d90b90db4b3ac2a3e56d271f372c41fb00d6 Author: Ralf Baechle Date: Sat Jun 17 18:57:39 2006 +0100 [PATCH] IP27: Really set PCI64_ATTR_VIRTUAL, not PCI64_ATTR_PREC. IOC3's homegrown DMA mapping functions that are used to optimize things a little on IP27 set the wrong bit. Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik commit 8a22dddb2a5b5834577afd9e25b5392218715611 Author: Francois Romieu Date: Fri Jun 23 00:47:06 2006 +0200 via-velocity: the link is not correctly detected when the device starts The patch fixes http://bugzilla.kernel.org/show_bug.cgi?id=6711 Signed-off-by: Roy Marples Signed-off-by: Francois Romieu commit dcc1a66a09420ccc5a22671bddc5a842f92d67e5 Author: Roman Zippel Date: Thu Jun 22 14:47:35 2006 -0700 [PATCH] x86_64: use select for GART_IOMMU to enable AGP The AGP default doesn't work well with other selects, so use a select for GART_IOMMU as well. Remove a redundant default for SWIOTLB as well. Signed-off-by: Roman Zippel Signed-off-by: Andi Kleen Cc: Andi Kleen Cc: Dave Jones Cc: Dave Airlie Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4f3865fb57a04db7cca068fed1c15badc064a302 Author: Richard Purdie Date: Thu Jun 22 14:47:34 2006 -0700 [PATCH] zlib_inflate: Upgrade library code to a recent version Upgrade the zlib_inflate implementation in the kernel from a patched version 1.1.3/4 to a patched 1.2.3. The code in the kernel is about seven years old and I noticed that the external zlib library's inflate performance was significantly faster (~50%) than the code in the kernel on ARM (and faster again on x86_32). For comparison the newer deflate code is 20% slower on ARM and 50% slower on x86_32 but gives an approx 1% compression ratio improvement. I don't consider this to be an improvement for kernel use so have no plans to change the zlib_deflate code. Various changes have been made to the zlib code in the kernel, the most significant being the extra functions/flush option used by ppp_deflate. This update reimplements the features PPP needs to ensure it continues to work. This code has been tested on ARM under both JFFS2 (with zlib compression enabled) and ppp_deflate and on x86_32. JFFS2 sees an approx. 10% real world file read speed improvement. This patch also removes ZLIB_VERSION as it no longer has a correct value. We don't need version checks anyway as the kernel's module handling will take care of that for us. This removal is also more in keeping with the zlib author's wishes (http://www.zlib.net/zlib_faq.html#faq24) and I've added something to the zlib.h header to note its a modified version. Signed-off-by: Richard Purdie Acked-by: Joern Engel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 4f1bcaf094ccc512c23e10104c05a6f8e5b7a9e4 Author: Bjorn Helgaas Date: Thu Jun 22 14:47:32 2006 -0700 [PATCH] vgacon: make VGA_MAP_MEM take size, remove extra use VGA_MAP_MEM translates to ioremap() on some architectures. It makes sense to do this to vga_vram_base, because we're going to access memory between vga_vram_base and vga_vram_end. But it doesn't really make sense to map starting at vga_vram_end, because we aren't going to access memory starting there. On ia64, which always has to be different, ioremapping vga_vram_end gives you something completely incompatible with ioremapped vga_vram_start, so vga_vram_size ends up being nonsense. As a bonus, we often know the size up front, so we can use ioremap() correctly, rather than giving it a zero size. Signed-off-by: Bjorn Helgaas Cc: "Antonino A. Daplas" Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d702ccb342e49f7591df5a87c3857c698183b0fa Author: Andrew Morton Date: Thu Jun 22 14:47:31 2006 -0700 [PATCH] prune_one_dentry() tweaks - Add description of d_lock handling to comments over prune_one_dentry(). - It has three callsites - uninline it, saving 200 bytes of text. Cc: Jan Blunck Cc: Kirill Korotaev Cc: Olaf Hering Cc: Balbir Singh Cc: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0feae5c47aabdde59cbbec32d150e17102de37f0 Author: NeilBrown Date: Thu Jun 22 14:47:28 2006 -0700 [PATCH] Fix dcache race during umount The race is that the shrink_dcache_memory shrinker could get called while a filesystem is being unmounted, and could try to prune a dentry belonging to that filesystem. If it does, then it will call in to iput on the inode while the dentry is no longer able to be found by the umounting process. If iput takes a while, generic_shutdown_super could get all the way though shrink_dcache_parent and shrink_dcache_anon and invalidate_inodes without ever waiting on this particular inode. Eventually the superblock gets freed anyway and if the iput tried to touch it (which some filesystems certainly do), it will lose. The promised "Self-destruct in 5 seconds" doesn't lead to a nice day. The race is closed by holding s_umount while calling prune_one_dentry on someone else's dentry. As a down_read_trylock is used, shrink_dcache_memory will no longer try to prune the dentry of a filesystem that is being unmounted, and unmount will not be able to start until any such active prune_one_dentry completes. This requires that prune_dcache *knows* which filesystem (if any) it is doing the prune on behalf of so that it can be careful of other filesystems. shrink_dcache_memory isn't called it on behalf of any filesystem, and so is careful of everything. shrink_dcache_anon is now passed a super_block rather than the s_anon list out of the superblock, so it can get the s_anon list itself, and can pass the superblock down to prune_dcache. If prune_dcache finds a dentry that it cannot free, it leaves it where it is (at the tail of the list) and exits, on the assumption that some other thread will be removing that dentry soon. To try to make sure that some work gets done, a limited number of dnetries which are untouchable are skipped over while choosing the dentry to work on. I believe this race was first found by Kirill Korotaev. Cc: Jan Blunck Acked-by: Kirill Korotaev Cc: Olaf Hering Acked-by: Balbir Singh Signed-off-by: Neil Brown Signed-off-by: Balbir Singh Acked-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit de047c1bcd7f7bcfbdc29eb5b439fb332594da3f Author: Ravikiran G Thirumalai Date: Thu Jun 22 14:47:26 2006 -0700 [PATCH] avoid tasklist_lock at getrusage for multithreaded case too Avoid taking tasklist_lock for at getrusage for the multithreaded case too. We don't need to take the tasklist lock for thread traversal of a process since Oleg's do-__unhash_process-under-siglock.patch and related work. Signed-off-by: Ravikiran Thirumalai Cc: Oleg Nesterov Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit c89681ed7d0e4a61d35bdc12c06c6733b718b2cb Author: Miklos Szeredi Date: Thu Jun 22 14:47:22 2006 -0700 [PATCH] remove steal_locks() This patch removes the steal_locks() function. steal_locks() doesn't work correctly with any filesystem that does it's own lock management, including NFS, CIFS, etc. In addition it has weird semantics on local filesystems in case tasks sharing file-descriptor tables are doing POSIX locking operations in parallel to execve(). The steal_locks() function has an effect on applications doing: clone(CLONE_FILES) /* in child */ lock execve lock POSIX locks acquired before execve (by "child", "parent" or any further task sharing files_struct) will after the execve be owned exclusively by "child". According to Chris Wright some LSB/LTP kind of suite triggers without the stealing behavior, but there's no known real-world application that would also fail. Apps using NPTL are not affected, since all other threads are killed before execve. Apps using LinuxThreads are only affected if they - have multiple threads during exec (LinuxThreads doesn't kill other threads, the app may do it with pthread_kill_other_threads_np()) - rely on POSIX locks being inherited across exec Both conditions are documented, but not their interaction. Apps using clone() natively are affected if they - use clone(CLONE_FILES) - rely on POSIX locks being inherited across exec The above scenarios are unlikely, but possible. If the patch is vetoed, there's a plan B, that involves mostly keeping the weird stealing semantics, but changing the way lock ownership is handled so that network and local filesystems work consistently. That would add more complexity though, so this solution seems to be preferred by most people. Signed-off-by: Miklos Szeredi Cc: Trond Myklebust Cc: Matthew Wilcox Cc: Chris Wright Cc: Christoph Hellwig Cc: Steven French Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 09d967c6f32b35eab15b45862ae16e4f06259d8e Author: OGAWA Hirofumi Date: Thu Jun 22 14:47:21 2006 -0700 [PATCH] Fix a race condition between ->i_mapping and iput() This race became a cause of oops, and can reproduce by the following. while true; do dd if=/dev/zero of=/dev/.static/dev/hdg1 bs=512 count=1000 & sync done This race condition was between __sync_single_inode() and iput(). cpu0 (fs's inode) cpu1 (bdev's inode) ----------------- ------------------- close("/dev/hda2") [...] __sync_single_inode() /* copy the bdev's ->i_mapping */ mapping = inode->i_mapping; generic_forget_inode() bdev_clear_inode() /* restre the fs's ->i_mapping */ inode->i_mapping = &inode->i_data; /* bdev's inode was freed */ destroy_inode(inode); if (wait) { /* dereference a freed bdev's mapping->host */ filemap_fdatawait(mapping); /* Oops */ Since __sync_single_inode() is only taking a ref-count of fs's inode, the another process can be close() and freeing the bdev's inode while writing fs's inode. So, __sync_signle_inode() accesses the freed ->i_mapping, oops. This patch takes a ref-count on the bdev's inode for the fs's inode before setting a ->i_mapping, and the clear_inode() of the fs's inode does iput() on the bdev's inode. So if the fs's inode is still living, bdev's inode shouldn't be freed. Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 0e5b3781591cc954037c08ef78edf7f1192d38c5 Author: Brice Goglin Date: Thu Jun 22 14:47:20 2006 -0700 [PATCH] PCI: Add PCI_CAP_ID_VNDR Add the vendor-specific extended capability PCI_CAP_ID_VNDR. It is required by the Myri-10G Ethernet driver. Signed-off-by: Brice Goglin Signed-off-by: Greg Kroah-Hartman Cc: Jeff Garzik Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit bec0e85910b95c325a008ead7c3bbe047cc39672 Author: Andrew Morton Date: Thu Jun 22 14:47:19 2006 -0700 [PATCH] myri10ge build fix Someone changed skb_linearize(). Cc: Brice Goglin Cc: "David S. Miller" Cc: Jeff Garzik Cc: Herbert Xu Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6cc0719181a7aa8883855140541e7892250e66af Author: Andrew Morton Date: Thu Jun 22 14:47:18 2006 -0700 [PATCH] suspend_console() warning fix kernel/power/main.c: In function 'suspend_prepare': kernel/power/main.c:89: warning: implicit declaration of function 'suspend_console' kernel/power/main.c: In function 'suspend_finish': kernel/power/main.c:137: warning: implicit declaration of function 'resume_console' Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 04c567d9313e4927b9835361d8ac0318ce65af6b Author: David Howells Date: Thu Jun 22 14:47:18 2006 -0700 [PATCH] Keys: Fix race between two instantiators of a key Add a revocation notification method to the key type and calls it whilst the key's semaphore is still write-locked after setting the revocation flag. The patch then uses this to maintain a reference on the task_struct of the process that calls request_key() for as long as the authorisation key remains unrevoked. This fixes a potential race between two processes both of which have assumed the authority to instantiate a key (one may have forked the other for example). The problem is that there's no locking around the check for revocation of the auth key and the use of the task_struct it points to, nor does the auth key keep a reference on the task_struct. Access to the "context" pointer in the auth key must thenceforth be done with the auth key semaphore held. The revocation method is called with the target key semaphore held write-locked and the search of the context process's keyrings is done with the auth key semaphore read-locked. The check for the revocation state of the auth key just prior to searching it is done after the auth key is read-locked for the search. This ensures that the auth key can't be revoked between the check and the search. The revocation notification method is added so that the context task_struct can be released as soon as instantiation happens rather than waiting for the auth key to be destroyed, thus avoiding the unnecessary pinning of the requesting process. Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit d720024e94de4e8b7f10ee83c532926f3ad5d708 Author: Michael LeMay Date: Thu Jun 22 14:47:17 2006 -0700 [PATCH] selinux: add hooks for key subsystem Introduce SELinux hooks to support the access key retention subsystem within the kernel. Incorporate new flask headers from a modified version of the SELinux reference policy, with support for the new security class representing retained keys. Extend the "key_alloc" security hook with a task parameter representing the intended ownership context for the key being allocated. Attach security information to root's default keyrings within the SELinux initialization routine. Has passed David's testsuite. Signed-off-by: Michael LeMay Signed-off-by: David Howells Signed-off-by: James Morris Acked-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit f893afbe1262e27e91234506f72e17716190dd2f Author: Anton Altaparmakov Date: Thu Jun 22 14:47:15 2006 -0700 [PATCH] NTFS: Critical bug fix (affects MIPS and possibly others) Many thanks to Pauline Ng for the detailed bug report and analysis! Signed-off-by: Anton Altaparmakov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 5d2170ad1092b2940138dc3ae4a944d7bf87ae9e Author: Al Viro Date: Thu Jun 22 14:47:14 2006 -0700 [PATCH] sparc build breakage rd_prompt et.al. depend on CONFIG_BLK_DEV_RAM, not CONFIG_BLK_INITRD; now that those are independent, setup.c blows with INITRD on and BLK_DEV_RAM off. Signed-off-by: Al Viro Cc: "David S. Miller" Cc: William Lee Irwin III Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 7f98a44b9d09580036da7e7f8b33e66f411cf374 Author: Jeff Dike Date: Thu Jun 22 14:47:09 2006 -0700 [PATCH] UML: fix wall_to_monotonic initialization Change a variable from unsigned to signed in order to get sign-extension when the thing is negated. Without this, uptime is horribly confused. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 02916526133aebc0b3b6c486d1b0af95221033bd Author: Ben Dooks Date: Thu Jun 22 22:57:54 2006 +0100 [ARM] 3629/1: S3C24XX: fix missing bracket in regs-dsc.h Patch from Ben Dooks Fix missing bracket in include/asm-arm/arch-s3c2410/regs-dsc.h Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 823588c18689ddd49d4643eda7654302f18a275f Author: Kevin Hilman Date: Thu Jun 22 22:27:14 2006 +0100 [ARM] 3537/1: Rework DMA-bounce locking for finer granularity Patch from Kevin Hilman This time with IRQ versions of locks. Rework also enables compatability with realtime-preemption patch. With the current locking via interrupt disabling, under RT, potentially sleeping functions can be called with interrupts disabled. Signed-off-by: Kevin Hilman Signed-off-by: Deepak Saxena Signed-off-by: Russell King commit fa3e686a34f4c33de31a128cc36def0b466bfe1a Author: Pavel Pisa Date: Thu Jun 22 22:21:03 2006 +0100 [ARM] 3601/1: i.MX/MX1 DMA error handling for signaled channels only Patch from Pavel Pisa There has been bug, that dma_err_handler() touches even channels not signaling error condition. Problem noticed by Andrea Paterniani. Signed-off-by: Pavel Pisa Signed-off-by: Russell King commit e22b04fb6b1689aee208b65966fa9fb19e098006 Author: Rod Whitby Date: Thu Jun 22 22:21:02 2006 +0100 [ARM] 3597/1: ixp4xx/nslu2: Board support for new LED subsystem Patch from Rod Whitby This patch implements NEW_LEDS support for the Linksys NSLU2. The NSLU2 has four LED indicators, which are the only form of output for an unmodified device - there is no keyboard or display on an NSLU2. For an NSLU2 which has been modified to bring out the serial port console, it is important to register that device first separately, to enable debugging of other device support. Signed-off-by: John Bowler Signed-off-by: Rod Whitby Signed-off-by: Deepak Saxena Signed-off-by: Russell King commit df6934b33c43a3ad517244935fe9c19715d9dc15 Author: Rod Whitby Date: Thu Jun 22 22:21:01 2006 +0100 [ARM] 3595/1: ixp4xx/nas100d: Board support for new LED subsystem Patch from Rod Whitby This patch implements NEW_LEDS support for the IOMega NAS100d. The NAS100d has three LED indicators, which are the only form of output for an unmodified device - there is no keyboard or display on an NAS100d. For an NAS100d which has been modified to bring out the serial port console, it is important to register that device first separately, to enable debugging of other device support. Signed-off-by: John Bowler Signed-off-by: Rod Whitby Signed-off-by: Deepak Saxena Signed-off-by: Russell King commit f606a6ff222dc7dceeb4d0e214ce4f55d9c6b0e6 Author: Nicolas Pitre Date: Thu Jun 22 22:18:45 2006 +0100 [ARM] 3626/1: ARM EABI: fix syscall restarting Patch from Nicolas Pitre The RESTARTBLOCK case currently store some code on the stack to invoke sys_restart_syscall. However this is ABI dependent and there is a mismatch with the way __NR_restart_syscall gets defined when the kernel is compiled for EABI. There is also a long standing bug in the thumb case since with OABI the __NR_restart_syscall value includes __NR_SYSCALL_BASE which should not be the case for Thumb syscalls. Credits to Yauheni Kaliuta for finding the EABI bug. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King commit 92b7eb8ffc0741f1fd5fbd5458a466d608310442 Author: Ben Dooks Date: Thu Jun 22 22:18:21 2006 +0100 [ARM] 3628/1: S3C24XX: add get_rate call to struct clk Patch from Ben Dooks Add a get_rate call to allow an given clock to over-ride the clk_get_rate() call. This provides support for clocks which rely on division of their parent to correctly report their frequency when the parent can also change. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 99c13853ffa26dd6527995b3f47548e075f201fb Author: Ben Dooks Date: Thu Jun 22 22:18:20 2006 +0100 [ARM] 3627/1: S3C24XX: split s3c2410 clocks from core clocks Patch from Ben Dooks Split the s3c2410 specific clocks from the core clock code, as part of the work to support more of the Samsung line of SoCs. The patch does not use the sysdev mechanism as the clocks are needed for the timer init, which is very early in the kernel init sequence. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit a341305e94982c66a2e94125a24b860605da9066 Author: Ben Dooks Date: Thu Jun 22 22:18:13 2006 +0100 [ARM] 3613/1: S3C2410: Add sysdev and sysclass Patch from Ben Dooks The S3C2440 and S3C2442 both have their own sysdev and sysclass for differentiating them from the currently default S3C2410. Add a sysdev for the S3C2410 as part of the work to make the code be non-dependant on the S3C2410. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 0dad31d2da706ef114bc5c21123123be2f405d5b Author: Jaroslav Kysela Date: Thu Jun 22 21:35:11 2006 +0200 [ALSA] version 1.0.12rc1 commit 607c0fbee7272be4d5455d6b29f6ffb092573eff Author: Jaroslav Kysela Date: Thu Jun 22 17:49:58 2006 +0200 [ALSA] aoa driver - Kconfig - remove spaces for SND!=n Signed-off-by: Jaroslav Kysela commit 5885492ab4fb18c155000d12f920754f7f35fbab Author: Takashi Iwai Date: Wed Jun 21 19:19:25 2006 +0200 [ALSA] hda-codec - Show EAPD and pin-detection capabilities in proc Show EAPD and pin-detection capabilities in proc files. They are often required to support the proper audio functionality. Signed-off-by: Takashi Iwai commit 45df379798b5c3b2ea937735ef04c58ce0f532a7 Author: Takashi Iwai Date: Wed Jun 21 16:37:54 2006 +0200 [ALSA] Remove nested mutexes in seq_ports.c Removed nested mutexes in the removal routine of port connections. The port is guaranteed to be offline before calling it, so no mutex is needed. Signed-off-by: Takashi Iwai commit 555fdc2e9fb2071fdd10ff1d86b8d63265d80241 Author: Takashi Iwai Date: Wed Jun 21 16:23:31 2006 +0200 [ALSA] Remove ppc/toonie.c Remove obsoleted ppc/toonie.c. The function is replaced with new snd-aoa driver. Signed-off-by: Takashi Iwai commit 55c385ad5e1f3cda887cd6a8ad69a6d74b4b9125 Author: Johannes Berg Date: Wed Jun 21 15:43:44 2006 +0200 [ALSA] snd-powermac: no longer handle anything with a layout-id property This patch removes from snd-powermac the code that check for the layout-id and instead adds code that makes it refuse loading when a layout-id property is present, nothing that snd-aoa should be used. It also removes the 'toonie' codec from snd-powermac which was only ever used on the mac mini which has a layout-id property. Signed-off-by: Johannes Berg Signed-off-by: Takashi Iwai commit f3d9478b2ce468c3115b02ecae7e975990697f15 Author: Johannes Berg Date: Wed Jun 21 15:42:43 2006 +0200 [ALSA] snd-aoa: add snd-aoa This large patch adds all of snd-aoa. Consisting of many modules, it currently replaces snd-powermac for all layout-id based machines and handles many more (for example new powerbooks and powermacs with digital output that previously couldn't be used at all). It also has support for all layout-IDs that Apple has (judging from their Info.plist file) but not all are tested. The driver currently has 2 known regressions over snd-powermac: * it doesn't handle powermac 7,2 and 7,3 * it doesn't have a DRC control on snapper-based machines I will fix those during the 2.6.18 development cycle. Signed-off-by: Johannes Berg Signed-off-by: Takashi Iwai commit 41f0cd3a0c4c6547860cf3b1c2d7968008e6c071 Author: Takashi Iwai Date: Wed Jun 21 12:14:40 2006 +0200 [ALSA] hda-codec - Use 3stack model for ASUS P5RD2-VM / P5GPL-X SE Use 3stack model as default for ASUS P5RD2-VM and P5GPL-X SE boards with AD1986A codec (ALSA bug#2103). Signed-off-by: Takashi Iwai commit 6dac9a65f05600bc29316e3cf3365236efe69041 Author: Daniel T Chen Date: Wed Jun 21 08:51:07 2006 +0200 [ALSA] HDA - Lenovo 3000 N100-07684JU - enable laptop-eapd by default Justin Sunseri reports that sound is audible on his Lenovo 3000 N100-07684JU by passing 'model=laptop-eapd' to modprobe, so this patch adds the pci ids for his sound device to patch_analog.c . This commit closes LP#39517. Alexey Parshin also confirmed the fix at http://bugs.gentoo.org/137245 TODO: Mute onboard speakers when device is plugged into the headphone jack. Muting the 'External Amplifier' mixer element while a device is plugged into the headphone jack allows sound to be played only from the headphone jack. From: Daniel T Chen Signed-off-by: Daniel T Chen Signed-off-by: Daniel Drake Signed-off-by: Jaroslav Kysela commit c4a87ef4de9860d00460dce30776f7cc17e77459 Author: Ben Williamson Date: Mon Jun 19 17:20:09 2006 +0200 [ALSA] USB midi: Remove duplicate CS_AUDIO_* #defines Removed the CS_AUDIO_* #defines, which were duplicates of the class-specific USB_DT_CS_* #defines in . Signed-off-by: Ben Williamson Signed-off-by: Takashi Iwai commit 1561f09a2f91bc258a72225f919807c9e51c8290 Author: Jaya Kumar Date: Mon Jun 19 15:06:14 2006 +0200 [ALSA] AD1888 suspend/resume fix This patch adds a write to an undocumented register, 0x60 Extended Codec Register Page in the AD1888 codec. It is neccessary in order to make suspend/resume work with the AD1888. Signed-off-by: Jaya Kumar Signed-off-by: Takashi Iwai commit 1459c7849ea24fd71e4d2e678caa1cc3fef754e2 Author: Rodolfo Giometti Date: Mon Jun 19 15:04:54 2006 +0200 [ALSA] Disable AC97 AUX and VIDEO controls for WM9705 touchscreen This patch by Rodolfo Giometti disables the AC97 AUX and VIDEO controls on the WM9705 when the touchscreen is selected as the AUX and VIDEO lines are shared with the touch controller. Changes:- o Added AC97_HAS_NO_AUX flag o Test for AC97_HAS_NO_AUX flag in snd_ac97_mixer_build() o Sets AC97_HAS_NO_VIDEO and AC97_HAS_NO_AUX in patch_wolfson05() when WM9705 touch driver is selected. Signed-off-by: Rodolfo Giometti Signed-off-by: Liam Girdwood Signed-off-by: Takashi Iwai commit 396f739e21f3b7ea9ece08bf0abf0a45693c3047 Author: Karsten Wiese Date: Mon Jun 19 13:22:52 2006 +0200 [ALSA] via82xx - Default to variable samplerate enabled for MSI K8T Neo2-FI Default to variable samplerate enabled for MSI K8T Neo2-FI No crackles here with 44100. Signed-off-by: Karsten Wiese Signed-off-by: Takashi Iwai commit d4199f01750f3fa6a5b8bacdac9bd0051fee95ef Author: Daniel T Chen Date: Fri Jun 16 16:21:54 2006 +0200 [ALSA] Add hp_only quirk for pci id [161f:2032] to via82xx http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=eae2cc78de39502595f67b7fc1f821f5963bb8ae UpstreamStatus: Not merged Christian Bjalevik reports in LP#38546 that his sound chipset requires the 'hp_only' quirk to allow him to control sound volume correctly when headphones are inserted. This patch adds the appropriate pci id to the via82xx ALSA driver so that the quirk is applied automatically, thereby removing the need for users to modify /etc/modprobe.d/alsa-base (or to unload and reload snd-via82xx with ac97_quirk=hp_only). This patch closes LP#38546. Signed-off-by: Daniel T Chen Signed-off-by: Ben Collins Signed-off-by: Takashi Iwai commit 1781a9af1d95256ed45abac4b0b87f48f64b9b87 Author: Daniel T Chen Date: Fri Jun 16 12:13:00 2006 +0200 [ALSA] sound/pci/: Add hp_only quirk for Dell D800 laptops http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=9ad787cd9670c3f3b8f3db235e84baf00a2ea526 Anders Ostling comments in Malone #41015 that his Dell D800 laptop's volume control works correctly when the hp_only quirk is passed to modprobe. This commit adds his hardware's sub{vendor,device} ids to the quirk list for the intel8x0 driver. Signed-off-by: Daniel T Chen Signed-off-by: Ben Collins Signed-off-by: Takashi Iwai commit 40a4f7a014339712a9f81b5fad99558611e99ca1 Author: Jaya Kumar Date: Tue Jun 13 12:01:14 2006 +0200 [ALSA] cs5535audio - trivial debug printk Following is a trivial patch to get more info for boards where the AC97_VENDOR_ID2 register (or others) time out. Signed-off-by: Jaya Kumar Signed-off-by: Takashi Iwai commit 63eb1e4bd2975f1d1102c1f44e4fd6fcd76f7792 Author: Jesper Juhl Date: Tue Jun 13 11:58:12 2006 +0200 [ALSA] fix potential NULL pointer deref in snd_sb8dsp_midi_interrupt() First testing if a pointer is NULL and if it is (or might be), proceeding with code that dereferences that same pointer is clearly a mistake. This happens in sound/isa/sb/sb8_midi.c::snd_sb8dsp_midi_interrupt() The patch below reworks the code so this unfortunate case doesn't happen. Also remove some blank comments. Found by the Coverity checker as bug #367 Patch is compile testted only due to lack of hardware. Signed-off-by: Jesper Juhl Signed-off-by: Takashi Iwai commit 6540dffa6ecfe0d99fb263548dcc4b35ccefe784 Author: Takashi Iwai Date: Tue Jun 13 11:57:22 2006 +0200 [ALSA] hda-codec - Add SPDIF support to Thinkpad T/X/Z60 Added IEC958 (SPDIF) output support to Thinkpad T/X/Z60 with AD1981HD codec. The spdif jack is on docking station. Also, renamed 'IEC958 Playback Route' to 'IEC958 Playback Source' to avoid the mixer name confliction with IEC958 switch. Signed-off-by: Takashi Iwai commit 70c5acbdcc7bb1651bb166f9e4b2345759a9fb18 Author: Jaya Kumar Date: Mon Jun 12 10:08:02 2006 +0200 [ALSA] ac97_codec - fix duplicate control creation in AC97 This patch conditions AC97 control creation by whether or not the codec is an AD18xx codec. This fixes the case where the default control would get created and then snd_ac97_mixer_build fails out when creation of ad18xx specific control would get attempted. This problem was found and debuged by Marcelo Tosatti. Signed-off-by: Jaya Kumar Signed-off-by: Jaroslav Kysela commit ecb594e66e740dc390a301768d89662777f1fde2 Author: Remy Bruno Date: Mon Jun 12 09:25:22 2006 +0200 [ALSA] RME HDSP - fixed proc interface (missing {}) From: Remy Bruno Signed-off-by: Jaroslav Kysela commit 58398895663f855aa32b440b164c426cfae4450c Author: James Courtier-Dutton Date: Sat Jun 10 09:16:49 2006 +0100 [ALSA] snd-ca0106: Update playback to 24bit. Fix typo is comment. Signed-off-by: James Courtier-Dutton commit 2e74eba3e2f000184ade92833c80e799af41c180 Author: Takashi Iwai Date: Fri Jun 9 15:28:07 2006 +0200 [ALSA] Fix invalid __init in ALSA ISA drivers Replaced invalid __init with __devinit in snd-sbawe and snd-opl3sa2 drivers. Signed-off-by: Takashi Iwai commit 3f3488b84c261ab3cb64b9f0b9f40b61e33edb98 Author: Randy Dunlap Date: Thu Jun 8 12:01:44 2006 +0200 [ALSA] sound/vxpocket: fix printk warning Fix printk format warning: sound/pcmcia/vx/vxp_ops.c:205: warning: format '%x' expects type 'unsigned int', but argument 5 has type 'size_t' Signed-off-by: Randy Dunlap Signed-off-by: Takashi Iwai commit 3758d4e601552a3d9066913a31ccb8dc6a25ee69 Author: Takashi Iwai Date: Wed Jun 7 18:12:31 2006 +0200 [ALSA] Remove bogus check of mmap_count in snd_pcm_release() Removed a bogus check of mmap_count in snd_pcm_release(). This is no longer true for the shared streams. Signed-off-by: Takashi Iwai commit 688956f23bdbfb1c3551bfafc819f989b36bb8ae Author: Takashi Iwai Date: Tue Jun 6 15:44:34 2006 +0200 [ALSA] Fix races in irq handler and ioremap Call ioremap before request_irq for avoiding possible races in the irq handler. Signed-off-by: Takashi Iwai Signed-off-by: Takashi Iwai commit c5533bf36b4a6629dab0e08c4951247050928853 Author: Clemens Ladisch Date: Fri Jun 2 09:15:44 2006 +0200 [ALSA] virmidi: revert erroneous removal of zero initialization The last patch that tried to remove zero initializations of static variables accidentally removed a not-quite-zero initialization too. Signed-off-by: Clemens Ladisch commit f8e9f340da753c021c071f318f97ac9046c1316a Author: Takashi Iwai Date: Thu Jun 1 21:08:53 2006 +0200 [ALSA] hda-codec - Add model entry for HP nx6320 Added a model entry for HP nx6320 with AD1981HD codec. It wasn't covered by the generic HP entry because of a hardware bug (the SSID is reversed). Signed-off-by: Takashi Iwai commit a43c4d4d7326c2894be9fd04519b109c438ee78b Author: Takashi Iwai Date: Thu Jun 1 17:16:41 2006 +0200 [ALSA] ac97 - Add Thinkpad T41p to AD1981 jack-sense blacklist Added Thinkpad T41p to the blacklist to disable HP/line jack-sensing with AD1981B. The jack-sensing is just harmful on this laptop. Signed-off-by: Takashi Iwai commit 0a50d2b2951cb7ae12726814f9a198e1c699aa0b Author: Takashi Iwai Date: Thu Jun 1 14:47:29 2006 +0200 [ALSA] Fix possible races in PCI driver removal Call free_irq() before releasing others to avoid races when shared irq is issued. Signed-off-by: Takashi Iwai commit f079c25ab8a7d223875c5bac9b23b484e4a18f88 Author: Takashi Iwai Date: Thu Jun 1 11:42:14 2006 +0200 [ALSA] hda-intel - Fix race in remove Call iounmap after free_irq to avoid invalid accesses in the shared irq. The patch is taken from https://bugzilla.novell.com/show_bug.cgi?id=167869 Signed-off-by: Takashi Iwai commit 29463dfea754b8b360f638244f002c751aaad1b0 Author: Clemens Ladisch Date: Thu Jun 1 08:33:48 2006 +0200 [ALSA] bt87x: add Voodoo TV 200 whitelist entry This adds a whitelist entry for the digital audio input of the Voodoo TV 200. Signed-off-by: Clemens Ladisch commit d20cad602fc3d92902dc3b4ed252359ab05eae0f Author: Eric Sesterhenn Date: Wed May 31 11:55:17 2006 +0200 [ALSA] NULL pointer dereference in sound/synth/emux/soundfont.c this is about coverity id #100. It seems the if statement is negated, since the else branch calls remove_info() with sflist->currsf as a parameter where it gets dereferenced. Signed-off-by: Eric Sesterhenn Signed-off-by: Takashi Iwai commit f26eb78fcfb5b76fbe6d3e740b6fedda611f8395 Author: Takashi Iwai Date: Mon May 29 19:05:28 2006 +0200 [ALSA] cmipci - Fix a typo in 'PC Speaker Playback Switch' control Fixed a typo in 'PC Speaker Playback Switch' control name. Signed-off-by: Takashi Iwai commit cf78ee2ccc96d59e602188e0e6e3fe3522b6d3f6 Author: Alan Horstmann Date: Fri May 26 17:19:34 2006 +0200 [ALSA] ice1712 - Set mpu401 info flags from _card_info To permit use, in ice1712, of the mpu401 info flags recently added to mpu401_uart, adds info_flags in snd_ice1712_card_info so that additional flags can be set, if desired.  'MPU401_INFO_INTEGRATED' is always set with the ice1712.  The flags are passed on to snd_mpu401_uart_new(). _INFO_OUTPUT is set for DMX6fire mpu2. Signed-off-by: Alan Horstmann Signed-off-by: Takashi Iwai commit 766a6c36f3a0b12e1c55dddc1df6673db6b22bfb Author: Takashi Iwai Date: Fri May 26 14:58:29 2006 +0200 [ALSA] hda-codec - Fix model for HP dc7600 Changed the assigned model for HP dc7600 with ALC260 codec to match better with the actual I/O assignment. Patch taken from ALSA bug#2157. Signed-off-by: Takashi Iwai commit c51302710546f075e65b1e70487707e8324abf2f Author: Takashi Iwai Date: Tue May 23 15:46:10 2006 +0200 [ALSA] ice1724 - Add functionality for Audiotrak Prodigy 7.1 LT This patch adds support for useable front audio channels, user controllable headphone channel and optical output. From: Anho Ki Signed-off-by: Matt Taylor Signed-off-by: Takashi Iwai commit d5a31b8b6e79145c832d530743ca80bf5f58a965 Author: Takashi Iwai Date: Tue May 23 13:30:59 2006 +0200 [ALSA] au88x0 - Fix 64bit address of MPU401 MMIO port Fix 64bit address of MPU401 MMIO port on au88x0 chip. Signed-off-by: Takashi Iwai commit 721b8a297279276699900a662fa8299232ebc0e8 Author: Alan Horstmann Date: Tue May 23 13:29:51 2006 +0200 [ALSA] ice1712 - Disable AC97 for DMX6fire Consumer AC97 is not used by the Terratec DMX6fire, but eeprom bit indicates it is; change the stored value to disable failing consumer mode. Signed-off-by: Alan Horstmann Signed-off-by: Takashi Iwai commit 302e4c2f9e2b9f07c69649782330a61c60001ac4 Author: Takashi Iwai Date: Tue May 23 13:24:30 2006 +0200 [ALSA] Change an arugment of snd_mpu401_uart_new() to bit flags Change the 5th argument of snd_mpu401_uart_new() to bit flags instead of a boolean. The argument takes bits that consist of MPU401_INFO_XXX flags. The callers that used the value 1 there are replaced with MPU401_INFO_INTEGRATED. Signed-off-by: Takashi Iwai commit 140432fd2fbe68d59fe6fcddbcd4bcd0f84e951a Author: Takashi Iwai Date: Mon May 22 14:31:57 2006 +0200 [ALSA] hdsp - Fix compilation with hdsp driver built in kernel Fixed the compilation with hdsp driver built in kernel. The traditional hwdep loader is used in this case. Signed-off-by: Takashi Iwai commit c00bd74a0dd69c4b39e4d95a20253e735616bdb9 Author: Takashi Iwai Date: Fri May 19 19:22:34 2006 +0200 [ALSA] Fix description of cs5535audio driver in ALSA-Configuration.txt Fix the description of cs5535audio driver in ALSA-Configuraiton.txt. Now it supports only single device. Signed-off-by: Takashi Iwai commit 77389b432344c811832962ca7f8181b8b3da3449 Author: Jaya Kumar Date: Fri May 19 12:04:22 2006 +0200 [ALSA] Single variables for cs5535audio As per Takashi's feedback, this is a cleanup to make cs5535audio be single device per system. The diff is against 2.6.17-rc4 with Takashi's patch adding the module_params for index, id and enable. Signed-off-by: Jaya Kumar Signed-off-by: Takashi Iwai commit 2851d963e0038c53d2175970daac4217abed7af2 Author: Takashi Iwai Date: Thu May 18 14:48:26 2006 +0200 [ALSA] mpu401_uart - Fix coding style and code clean up - fold lines and fix spaces to follow the standard style - added some comments - moved EXPORT_SYMBOL() near the definition - some code clean up Signed-off-by: Takashi Iwai commit f8c7579051763d6be275bf88a430ffb1c5234bad Author: Takashi Iwai Date: Thu May 18 14:47:03 2006 +0200 [ALSA] usbaudio - Fix a typo Fix a typo introduced by the last fix. Signed-off-by: Takashi Iwai commit c77a03551b3fd8ef6434153dfadff83ae404e526 Author: Alan Horstmann Date: Thu May 18 14:24:30 2006 +0200 [ALSA] Remove ENTER_UART from au88x0 init Remove an unnecessary ENTER_UART instruction during au88x0 init as it makes the first/subsequent midi open to fail. Signed-off-by: Alan Horstmann Signed-off-by: Takashi Iwai commit faf8d11743961c720c85be191f8a08c00e5c5d60 Author: Clemens Ladisch Date: Thu May 18 09:35:15 2006 +0200 [ALSA] usb-audio: add workaround for CSR Bluetooth Headphones (Saitek A-250) Some devices don't have the required class-specific endpoint descriptors. Instead of making this case an error, this patch makes the driver guess the endpoint attributes. Signed-off-by: Clemens Ladisch commit 474167d646cb2147b9fcd7bacf5cdf8177ed43c4 Author: Takashi Iwai Date: Wed May 17 17:17:43 2006 +0200 [ALSA] hda-codec - Fix init verbs for ALC260 hp model Use the basic init verbs for ALC260 instead of hp init verbs since hp init verbs seem incomplete and not working on some machines. Signed-off-by: Takashi Iwai commit 6581f4e74d8541dd7d579f64e94822622cbb1654 Author: Takashi Iwai Date: Wed May 17 17:14:51 2006 +0200 [ALSA] Remove zero-initialization of static variables Removed zero-initializations of static variables. A tiny optimization. Signed-off-by: Takashi Iwai commit 0fbf405c583e6ee6d7227eb938a096d0998f7e78 Author: Takashi Iwai Date: Wed May 17 17:10:35 2006 +0200 [ALSA] Fix pcm-draining of capture stream in PCM middle layer Fix the draining of PCM capture stream in the PCM middle layer. snd_pcm_drain() ignored capture streams, but it should change the state to SNDRV_PCM_DRAINING. Signed-off-by: Takashi Iwai commit 9b87819b61060a3d32d5982f5ee998c22ab8ca27 Author: Takashi Iwai Date: Wed May 17 11:26:39 2006 +0200 [ALSA] Fix description of snd-hda-intel driver in document Fixed the description of snd-hda-intel driver in ALSA-Configuration.txt document. Signed-off-by: Takashi Iwai commit 778b6e1b2da260adf3d3254aaa35bffd1eb05b42 Author: Felix Kuehling Date: Wed May 17 11:22:21 2006 +0200 [ALSA] hda - Add support for the ATI RS600 HDMI audio device Add support for the ATI RS600 HDMI audio device. It has a one-stream pure digital stereo codec that isn't handled by the generic codec support. Signed-off-by: Felix Kuehling Signed-off-by: Takashi Iwai commit e2f872608af7f3c00beaa61ff6037e3cc5a66cf1 Author: Andreas Mohr Date: Wed May 17 11:04:19 2006 +0200 [ALSA] azt3328.c: use kernel coding style Scope braces were not done the One True Kernel Way. Signed-off-by: Andreas Mohr Signed-off-by: Takashi Iwai commit 13769e3f21d6e9c59999c9bf6908278b878d05c5 Author: Andreas Mohr Date: Wed May 17 11:03:16 2006 +0200 [ALSA] azt3328.c: add 3D sound mixer switch/rename controls - add 3D sound pre-3D/post-3D switch, as seen in standard AC-97 - rename controls to shorter and more accurate strings Signed-off-by: Andreas Mohr Signed-off-by: Takashi Iwai commit ca54bde3634360afecd0dada9c59399bbe88bd32 Author: Andreas Mohr Date: Wed May 17 11:02:24 2006 +0200 [ALSA] azt3328.c: add suspend/resume support - add suspend/resume handlers - fix problem (private_data members not set) Playing a file while suspending will resume correctly with this patch, so I assume the hardware to get fully correctly reinitialized with this patch. Signed-off-by: Andreas Mohr Signed-off-by: Takashi Iwai commit 746df94898554b3d8e91d855e934852e626c701c Author: Takashi Iwai Date: Mon May 15 19:49:05 2006 +0200 [ALSA] Fix rwlock around snd_iprintf() in sound core Fixed rwlock around snd_iprintf() in sound core part. Replaced with mutex. Also, make mutex and flags static variables with addition of snd_card_locked() function (just for sound.c). Signed-off-by: Takashi Iwai commit 0defb2672d7cde8d048eec35c183da7b88adbd9e Author: Takashi Iwai Date: Thu May 11 18:12:23 2006 +0200 [ALSA] hda-codec - Fix handling of capture controls on ALC882 3/6-stack models Fixed the handling of capture controls on ALC882 3/6-stack models. Now the driver checks the availability of NID 07h. Signed-off-by: Takashi Iwai commit ed7cbe3e4175e5fe9386793fbffee786840d7e9c Author: Takashi Iwai Date: Thu May 11 11:30:10 2006 +0200 [ALSA] Remove obsolete description from ALSA-Configuration.txt Remove obsolete descriptions about the dependency on CONFIG_ISA for vxpocket and pdaudiocf drivers. Signed-off-by: Takashi Iwai commit 3206b9ca9fba8dc8d6ddd371a3ff455c67ad137f Author: Takashi Iwai Date: Wed May 10 16:33:11 2006 +0200 [ALSA] hda-codec - Add support for Sony Vaio VGN-S3HP Added the missing support for Sony Vaio VGN-S3HP with ALC260 codec. The patch taken from ALSA bug#2101. Signed-off-by: Takashi Iwai commit 2ce7fb579f842f76a0216618c105bffd334d9233 Author: Takashi Iwai Date: Wed May 10 16:24:42 2006 +0200 [ALSA] rme96 - Fix OSS full-duplex Fixed a bug in rme96 driver that the full-duplex on OSS emulation doesn't work due to the invalid period size parameter. Signed-off-by: Takashi Iwai commit 62fe78e90dc25b269362034487dc450cd8453e8c Author: Sam Revitch Date: Wed May 10 15:09:17 2006 +0200 [ALSA] hda-codec - Add support for Apple Mac Mini (early 2006) Add support for some audio quirks of the Apple Mac Mini (early 2006) Signed-off-by: Sam Revitch Signed-off-by: Takashi Iwai commit 4d1a70dad0e1c44dc0725de6de25aceead48599e Author: Raimonds Cicans Date: Fri May 5 09:49:53 2006 +0200 [ALSA] add support for SB Live! 24-Bit External remote control This patch rewrites the remote control code to use a table for the peculiarities of the various SB models, and adds support for a third model. Signed-off-by: Raimonds Cicans Signed-off-by: Clemens Ladisch commit cab5c4c97a98e46359faa52e86787c1f0ccd773c Author: Takashi Iwai Date: Thu May 4 14:36:08 2006 +0200 [ALSA] cmipci - Disable integrated mpu401 as default Enable the support of mpu401 PCI port only when mpu_port=1 module option is given, i.e. disabled as default. It turned out that the check of integrated midi port isn't perfect and caused hang-ups on some boards. Signed-off-by: Takashi Iwai commit a7306336e818fe83f08a476c91ae2616e7fb209f Author: Takashi Iwai Date: Thu May 4 11:58:43 2006 +0200 [ALSA] Fix a typo in writing-an-alsa-driver document Fixed a typo in writing-an-alsa-driver document. Signed-off-by: Takashi Iwai commit 520290e43f9880da34e542185838816c6d79a340 Author: Alan Horstmann Date: Wed May 3 17:07:29 2006 +0200 [ALSA] au88x0 - Init before create components Change the order in vortex_probe to set the card details before creating the components, meaning for example that card->shortname is available when registering the midi port. I have also added extra to card->shortname, and a line to overwrite the midi name following snd_mpu401_uart_new. Signed-off-by: Alan Horstmann Signed-off-by: Takashi Iwai commit a59524faf3a2050e14a1c9038eb006ce96025394 Author: Matt Porter Date: Wed May 3 14:08:33 2006 +0200 [ALSA] hda: add sigmatel 9227/9228/9229 ids Adds support for the 9227/9228/9229 sigmatel hda codecs. Signed-off-by: Matt Porter Signed-off-by: Takashi Iwai commit a9393d70e564e4afe0333b1e26dda48af8b9305e Author: Takashi Iwai Date: Wed May 3 11:59:03 2006 +0200 [ALSA] hda-codec - Fix mute switch on VAIO laptops with STAC7661 Fixed the master mute switch on VAIO laptops with STAC7661 codec chip. Signed-off-by: Takashi Iwai commit 1dbfd8c56bd7366d86e58b3e510a75de93e1978b Author: Takashi Iwai Date: Tue May 2 18:31:31 2006 +0200 [ALSA] cs5535audio - Add missing module_param*() and MODULE_PARM_DESC() Added missing module_param*() and MODULE_PARM_DESC() for cs5535audio driver. Signed-off-by: Takashi Iwai commit eed656493a459bbc0fdf687fa8f43f87946d8d3a Author: Takashi Iwai Date: Tue May 2 18:22:06 2006 +0200 [ALSA] Add a workaround for ASUS A6KM Added a workaround for ASUS A6KM board that requires EAPD rather than SPDIF-in. Signed-off-by: Takashi Iwai commit 886da8677d2e4e942fc8984b22bfb8da45e810ec Author: Takashi Iwai Date: Tue May 2 18:17:57 2006 +0200 [ALSA] hda-codec - Add support for LG S1 laptop Added the model entry for LG S1 laptop. Signed-off-by: Takashi Iwai commit a7b928ac5fcd8e1b5c7c69926d8845b1d0500af3 Author: Clemens Ladisch Date: Tue May 2 16:22:12 2006 +0200 [ALSA] rawmidi: add get_port_info callback for sequencer information flags Add a get_port_info callback to the snd_rawmidi_global_ops structure to allow the USB MIDI driver to supply information flags for the sequencer ports created by seq_midi. Signed-off-by: Clemens Ladisch commit 450047a78f3c35a905576e121abfbee2ccd45993 Author: Clemens Ladisch Date: Tue May 2 16:08:41 2006 +0200 [ALSA] add more sequencer port type information bits Add four new information flags SNDRV_SEQ_PORT_TYPE_HARDWARE, _SOFTWARE, _SYNTHESIZER, _PORT for sequencer ports. This makes it easier for apps like Rosegarden to make policy decisions based on the port type. Signed-off-by: Clemens Ladisch commit c97f3dd85490e51ba48782dd0c063cdade352c0d Author: Clemens Ladisch Date: Tue May 2 15:50:05 2006 +0200 [ALSA] fix port type bits Fix the port information about non-MIDI messages that had wrong values for some OPL3 and EmuX ports. Signed-off-by: Clemens Ladisch commit f4a747f155fe375231196ec3d26fcb6e3675d82f Author: Clemens Ladisch Date: Tue May 2 15:33:25 2006 +0200 [ALSA] fix a wrong lock fix a typo in the info locking code Signed-off-by: Clemens Ladisch commit 170a34605c14a90df5f4a78e0b4ca643be6ef8ba Author: Takashi Iwai Date: Fri Apr 28 15:29:15 2006 +0200 [ALSA] Fix compile warning in timer.c Fix a compile warning in timer.c due to unused variables. Signed-off-by: Takashi Iwai commit 9c323fcbc51493f79f9700cb20830d0857c72d99 Author: Takashi Iwai Date: Fri Apr 28 15:13:41 2006 +0200 [ALSA] Fix mmap_count with O_APPEND opened streams Move mmap_count to snd_pcm_substream instead of runtime struct so that multiplly opened substreams via O_APPEND can be handled correctly. Signed-off-by: Takashi Iwai commit 0df63e44c3e315ec0fe427ae62558231864108bd Author: Takashi Iwai Date: Fri Apr 28 15:13:41 2006 +0200 [ALSA] Add O_APPEND flag support to PCM Added O_APPEND flag support to PCM to enable shared substreams among multiple processes. This mechanism is used by dmix and dsnoop plugins. Signed-off-by: Takashi Iwai commit f001c3acf64b8ca18fe40af592629abb261b321e Author: Takashi Iwai Date: Fri Apr 28 15:13:41 2006 +0200 [ALSA] Insert might_sleep() in snd_iprintf() Inserted might_sleep() in snd_iprintf() for sanity check. Signed-off-by: Takashi Iwai commit d689e34b524b69c111db0b7c844d71c8e1a53b15 Author: Takashi Iwai Date: Fri Apr 28 15:13:41 2006 +0200 [ALSA] Remove spinlocks around proc prints Don't lock during showing proc read. snd_iprintf() might sleep. Signed-off-by: Takashi Iwai commit bf850204a71a97eb5a6afaf27263bb667f9cab0a Author: Takashi Iwai Date: Fri Apr 28 15:13:41 2006 +0200 [ALSA] Remove unneeded read/write_size fields in proc text ops Remove unneeded read/write_size fields in proc text ops. snd_info_set_text_ops() is fixed, too. Signed-off-by: Takashi Iwai commit 7e4eeec8a30fa9e00cac67a37ca9ddf6cbdb79c4 Author: Takashi Iwai Date: Fri Apr 28 15:13:40 2006 +0200 [ALSA] Make buffer size of proc text interface variable Make the read/write buffer size of proc text interface variable. Signed-off-by: Takashi Iwai commit 2f4ca8e5c7cf6a6f7935483d8ee4aa8b039bdd7d Author: Takashi Iwai Date: Fri Apr 28 15:13:40 2006 +0200 [ALSA] Clean up ugly hacks in pcm_lib.c Clean up ugly hacks for sync with alsa-lib code in pcm_lib.c. Also, optimize snd_pcm_hw_params_choose() with a loop. Signed-off-by: Takashi Iwai commit e88e8ae639a4908b903d9406c54e99a729b01a28 Author: Takashi Iwai Date: Fri Apr 28 15:13:40 2006 +0200 [ALSA] Move OSS-specific hw_params helper to snd-pcm-oss module Move EXPORT_SYMBOL()s to places adjacent to functions/variables. Also move OSS-specific hw_params helper functions to pcm_oss.c. Signed-off-by: Takashi Iwai commit e5e8a1d4618595ea406336da3cdbd0c6eb6f260d Author: Takashi Iwai Date: Fri Apr 28 15:13:40 2006 +0200 [ALSA] hda-codec - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai commit 57c65c116e1c03c54ac7c4bf38f2b4086d2c1a17 Author: Takashi Iwai Date: Fri Apr 28 15:13:40 2006 +0200 [ALSA] i2c - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai commit fa325eb3afc3cdaf7fba6ee3eaf05b243f5614a3 Author: Takashi Iwai Date: Fri Apr 28 15:13:40 2006 +0200 [ALSA] vx - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai commit 95ff17564b6db34cad0cd67678fb79174e77531e Author: Takashi Iwai Date: Fri Apr 28 15:13:40 2006 +0200 [ALSA] emux - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai commit cbef55f3d8e4e7efef4703c82302a0021d781483 Author: Takashi Iwai Date: Fri Apr 28 15:13:40 2006 +0200 [ALSA] trident - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai commit 2dd31deeeb238a4f40c9fc9e219dc210fcbf8765 Author: Takashi Iwai Date: Fri Apr 28 15:13:39 2006 +0200 [ALSA] emu10k1 - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai commit 4181e5fe4b27b0a049402a359a4a5d8b80308528 Author: Takashi Iwai Date: Fri Apr 28 15:13:39 2006 +0200 [ALSA] opl4 - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai commit ac19e19b3664feda8040fb9fb7885183a9eb7a80 Author: Takashi Iwai Date: Fri Apr 28 15:13:39 2006 +0200 [ALSA] opl3 - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai commit 7b09679c431ba91551a90203f7e7dadbb4c26d1b Author: Takashi Iwai Date: Fri Apr 28 15:13:39 2006 +0200 [ALSA] ac97 - Move EXPORT_SYMBOL() to adjacent to each function Move EXPORT_SYMBOL() to adjacent to each exported function/variable. Signed-off-by: Takashi Iwai commit 91715ed934fb645948ff17b6c20c6f7fd7688a70 Author: Takashi Iwai Date: Fri Apr 28 15:13:39 2006 +0200 [ALSA] Clean up EXPORT_SYMBOL()s in snd-seq module Move EXPORT_SYMBOL()s to places adjacent to functions/variables. Signed-off-by: Takashi Iwai commit c0d3fb39e9511c6fad17d059a3a50d1be33add24 Author: Takashi Iwai Date: Fri Apr 28 15:13:39 2006 +0200 [ALSA] Clean up EXPORT_SYMBOL()s in snd module Move EXPORT_SYMBOL()s to places adjacent to functions/variables. Signed-off-by: Takashi Iwai commit 9bb22e215c28204faee73dd7ac0ad98c075d6f7b Author: Takashi Iwai Date: Fri Apr 28 15:13:39 2006 +0200 [ALSA] Clean up ugly hacks in pcm_params.h Clean up ugly hacks for sync with alsa-lib in pcm_params.h. Signed-off-by: Takashi Iwai commit 9ac25594e68a4b61516e7c1140d8c0f7ef449e20 Author: Jaya Kumar Date: Fri Apr 28 14:34:49 2006 +0200 [ALSA] PM support for cs5535audio Appended is my patch adding PM support to the cs5535audio driver. I also added the ac97 quirk but it's not yet confirmed which boards need to be in the quirk list. The patch also includes some Kconfig and misc cleanup. Signed-off-by: Jaya Kumar Signed-off-by: Takashi Iwai commit 5e1b1518a53fc62d9f39a13819c849336c6d8dd4 Author: Kenneth Crudup Date: Fri Apr 28 13:03:48 2006 +0200 [ALSA] hda-codec - Add support for Sony Vaio VGN-A790 laptop Added the model entry for Sony Vaio VGN-A790 laptop with ALC260 codec. From: Kenneth Crudup Signed-off-by: Takashi Iwai commit 3bef229e4f13790402b1387ea8147906f217a766 Author: Alan Horstmann Date: Wed Apr 26 18:13:59 2006 +0200 [ALSA] ice1712 - Provides specified midi port names instead of defaults Patch provides for the ice1712 card driver to overwrite the midi port name string given by default in mpu401_uart, with one specified in snd_ice1712_card_info. Signed-off-by: Alan Horstmann Signed-off-by: Takashi Iwai commit 78fc030bdbbeebdea436f2b02a616d67e5f9bd9b Author: Alan Horstmann Date: Fri Apr 21 08:39:20 2006 +0200 [ALSA] Change seq_midi.c so client name is card, rather than port, specific Change snd_seq_midisynth_register_port() in seq_midi.c so that if a new client is created, the client name string is based on card->shortname not (port-specific) info->name. Signed-off-by: Alan Horstmann Signed-off-by: Clemens Ladisch commit 887709be9063d233eb5abef25aafcd94615b03f9 Author: Takashi Iwai Date: Tue Apr 18 13:27:31 2006 +0200 [ALSA] hda-codec - Fix a typo Fixed a typo of 'pci_subsystem' in the last changeset. Signed-off-by: Takashi Iwai commit 01686c5fce4682350849f9f2c262fcaf67ec73c3 Author: Takashi Iwai Date: Tue Apr 18 12:54:11 2006 +0200 [ALSA] hda-codec - Add Thinkpad X60/T60/Z60 support Added the support for Thinkpad X60/T60/Z60 laptops with AD1981HD codec. Signed-off-by: Takashi Iwai commit 7152447df98b3981d621224be947a2c8d77aed06 Author: Rene Herman Date: Thu Apr 13 12:58:06 2006 +0200 [ALSA] unregister platform device again if probe was unsuccessful This second one unregisters the platform device again when the probe is unsuccesful for sound/drivers, sound/arm/sa11xx-uda1341.c and sound/ppc/powermac.c. This gets them all. Signed-off-by: Rene Herman Signed-off-by: Takashi Iwai commit 79ca4f3f625e14212310f953b096e2e45110ac6b Author: Takashi Iwai Date: Wed Apr 12 12:54:55 2006 +0200 [ALSA] vxpocket - Fix a typo Fix a typo of return value from vxpocket_config(). Signed-off-by: Takashi Iwai commit d7f6f1157f73dffe0a6afd12b90557e484b7fb35 Author: James Courtier-Dutton Date: Tue Apr 11 21:47:27 2006 +0100 [ALSA] AC97: Correct Mic Boost label. Signed-off-by: James Courtier-Dutton commit be0b7b0113300c324034e94a12244c4ac3f4b354 Author: James Courtier-Dutton Date: Sun Apr 9 20:48:44 2006 +0100 [ALSA] ca0106: Fixes MSI K8N's SB Live 24 bit, no sound from line-in. Fixed bug#1331 Signed-off-by: James Courtier-Dutton commit 3969f6178b86613fd443e70d11b8848451552bdd Author: James Courtier-Dutton Date: Sun Apr 9 17:44:13 2006 +0100 [ALSA] Add p17v.h file. Signed-off-by: James Courtier-Dutton commit 21fdddea8e4cc54341d389916d0c17db8c1ca452 Author: James Courtier-Dutton Date: Sun Apr 9 17:36:39 2006 +0100 [ALSA] emu10k1: Add support for Audigy4 (not Pro) Signed-off-by: James Courtier-Dutton commit 6129daaa0d2b84c0e376b6b17b3d3740c4d1d1ca Author: James Courtier-Dutton Date: Sun Apr 9 13:01:34 2006 +0100 [ALSA] ca0106: Add analog capture controls. Signed-off-by: James Courtier-Dutton commit c6976a4eb3c9ead165de950899b45db0840b8e30 Author: Andrew Morton Date: Sun May 14 21:43:50 2006 -0700 [PATCH] w1: warning fix drivers/w1/w1.c:423: warning: long long unsigned int format, __u64 arg (arg 8) u64 is not, never has been and never will be "unsigned long long"! While we're there, fix up some code layout - it looks awful in an 80-col display. Cc: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit 30841711c88dc2d9ce31bfa3fa5479aa823804cf Author: Evgeniy Polyakov Date: Thu Apr 27 19:40:27 2006 +0400 [PATCH] w1: clean up W1_CON dependency. If w1 is not enabled, w1_con should not appear in configuration, even if no logic is turned on without w1. W1_CON should depend on W1 also. Signed-off-by: Randy Dunlap Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman commit 6a873403d387c34c4466cc81649acc8acd66874d Author: Adrian Bunk Date: Thu Apr 27 02:29:18 2006 -0700 [PATCH] drivers/w1/w1.c: fix a compile error From: Adrian Bunk drivers/w1/w1.c:197: error: static declaration of 'w1_bus_type' follows non-static declaration drivers/w1/w1.h:217: error: previous declaration of 'w1_bus_type' was here Signed-off-by: Adrian Bunk Cc: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit f621e1c78134f7cea0d2cf2c2822c917bedec516 Author: Jean-Luc Leger Date: Tue Apr 18 21:18:20 2006 -0700 [PATCH] W1: fix dependencies of W1_SLAVE_DS2433_CRC From: Jean-Luc Leger Default values for boolean and tristate options can only be 'y', 'm' or 'n'. This patch fixes dependencies of W1_SLAVE_DS2433_CRC. Signed-off-by: Jean-Luc Leger Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit 70d484bff43013e9b08f5d970b1c5941e9d98e16 Author: Evgeniy Polyakov Date: Mon Apr 24 10:46:14 2006 +0400 [PATCH] W1: possible cleanups This patch contains the following possible cleanups: - the following file did't #include the header with the prototypes for it's global functions: - w1_int.c - #if 0 the following unused global function: - w1_family.c: w1_family_get() - make the following needlessly global functions static: - w1_family.c: __w1_family_put() - w1_io.c: w1_delay() - w1_io.c: w1_touch_bit() - w1_io.c: w1_read_8() - remove the following unused EXPORT_SYMBOL's: - w1_family.c: w1_family_put - w1_family.c: w1_family_registered Signed-off-by: Adrian Bunk Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman commit 2c5bfdac33607a618d8cf1532ef235ca9eccd49e Author: Evgeniy Polyakov Date: Tue Apr 4 20:35:22 2006 +0400 [PATCH] W1: cleanups Nice cleanup spotted by Adrian Bunk, which was lost due to moving to the completely new functionality. Shame-shame-shame on me. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman commit 339f07236b481371ffb4993cf309dd1f1b3382ab Author: Andrew Morton Date: Mon Apr 3 22:51:17 2006 -0700 [PATCH] w1 exports From: Andrew Morton WARNING: "w1_read_block" [drivers/w1/slaves/w1_therm.ko] undefined! WARNING: "w1_write_8" [drivers/w1/slaves/w1_therm.ko] undefined! WARNING: "w1_reset_select_slave" [drivers/w1/slaves/w1_therm.ko] undefined! WARNING: "w1_reset_bus" [drivers/w1/slaves/w1_ds2433.ko] undefined! WARNING: "w1_write_8" [drivers/w1/slaves/w1_ds2433.ko] undefined! WARNING: "w1_read_block" [drivers/w1/slaves/w1_ds2433.ko] undefined! WARNING: "w1_write_block" [drivers/w1/slaves/w1_ds2433.ko] undefined! WARNING: "w1_reset_select_slave" [drivers/w1/slaves/w1_ds2433.ko] undefined! Cc: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit abd52a13206e02537ca1dc08fc5438c7d27bdbf1 Author: Evgeniy Polyakov Date: Mon Apr 3 12:04:27 2006 +0400 [PATCH] w1: Use mutexes instead of semaphores. Use mutexes instead of semaphores. Patch tested on x86_64 and i386 with test bus master driver. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman commit 46e07f6e5eb0e465e086b8f485f4238bd453e3e9 Author: Evgeniy Polyakov Date: Mon Apr 3 12:01:12 2006 +0400 [PATCH] w1: Make w1 connector notifications depend on connector. Make w1 connector notifications depend on connector. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman commit bb5427b5466782ba0bbf56a4ed752e08b65a5d08 Author: Evgeniy Polyakov Date: Thu Mar 23 19:11:58 2006 +0300 [PATCH] w1: netlink: Mark netlink group 1 as unused. netlink_w1 was moved to connector. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman commit b6043fcab4b2b06b9fcde4c783ab253cdc2c1129 Author: Evgeniy Polyakov Date: Thu Mar 23 19:11:58 2006 +0300 [PATCH] w1: Move w1-connector definitions into linux/include/connector.h Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman commit 12003375acd879e498c6c511faf27531296f9640 Author: Evgeniy Polyakov Date: Thu Mar 23 19:11:58 2006 +0300 [PATCH] w1: Userspace communication protocol over connector. There are three types of messages between w1 core and userspace: 1. Events. They are generated each time new master or slave device found either due to automatic or requested search. 2. Userspace commands. Includes read/write and search/alarm search comamnds. 3. Replies to userspace commands. From: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman commit 81f6075ebcf3b0800321b7d81e4845d6ad9566d8 Author: Evgeniy Polyakov Date: Thu Mar 23 19:11:58 2006 +0300 [PATCH] w1: Replace dscore and ds_w1_bridge with ds2490 driver. commit f522d2396138e68bcb9cc5650aa368a81d7f7ff0 Author: Evgeniy Polyakov Date: Thu Mar 23 19:11:58 2006 +0300 [PATCH] w1: Added default generic read/write operations. Special file in each w1 slave device's directory called "rw" is created each time new slave and no appropriate w1 family is registered. "rw" file supports read and write operations, which allows to perform almost any kind of operations. Each logical operation is a transaction in nature, which can contain several (two or one) low-level operations. Let's see how one can read EEPROM context: 1. one must write control buffer, i.e. buffer containing command byte and two byte address. At this step bus is reset and appropriate device is selected using either W1_SKIP_ROM or W1_MATCH_ROM command. Then provided control buffer is being written to the wire. 2. reading. This will issue reading eeprom response. It is possible that between 1. and 2. w1 master thread will reset bus for searching and slave device will be even removed, but in this case 0xff will be read, since no device was selected. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman commit 4941b395b3c2635a8c16d88791a789fb6ac6be43 Author: David Brownell Date: Tue Jun 13 09:47:27 2006 -0700 [PATCH] I2C: I2C controllers go into right place on sysfs I2C creates some sysfs nodes in the wrong places: not as children of parent controllers, but as their peers (!). This puts them into the right place always, instead of just when the adapter is on the platform bus. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 6af586dc58820d052aa538abef4d4d15c2a9e33e Author: Rudolf Marek Date: Mon Jun 12 22:00:53 2006 +0200 [PATCH] hwmon-vid: Add support for Intel Core and Conroe This patch adds support for two new VID codes, supporting Intel mobile Core processors and new Conroe based platforms. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit e1a8e913f97e36cc5a23a24a8b4717e84998f13c Author: Kaiwan N Billimoria Date: Mon Jun 12 22:00:05 2006 +0200 [PATCH] lm70: New hardware monitoring driver This driver implements support for the National Semiconductor LM70 temperature sensor. The LM70 temperature sensor chip supports a single temperature sensor. It communicates with a host processor (or microcontroller) via an SPI/Microwire Bus interface. Communication with the LM70 is simple: when the temperature is to be sensed, the driver accesses the LM70 using SPI communication: 16 SCLK cycles comprise the MOSI/MISO loop. At the end of the transfer, the 11-bit 2's complement digital temperature (sent via the SIO line), is available in the driver for interpretation. This driver makes use of the kernel's in-core SPI support. Signed-off-by: Kaiwan N Billimoria Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 060b2f5584bf3bbb0268c83c24d5a506780fb702 Author: Jean Delvare Date: Mon Jun 12 21:55:28 2006 +0200 [PATCH] hwmon: Fix the Kconfig header Hardware monitoring chips don't have to be on the I2C bus. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 02dd7ae2892e5ceff111d032769c78d3377df970 Author: Jean Delvare Date: Mon Jun 12 21:53:41 2006 +0200 [PATCH] i2c-i801: Merge setup function i2c-i801: Merge setup function Merge i801_setup into i801_probe, as it doesn't make much sense to have them split. This lets us handle errors better. Christopher Hellwig had been suggesting this back in March 2003 when the driver was merged. Also drop two useless debug messages (revision and base address can be obtained from lspci, procfs or sysfs.) Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 6dcc19dfbc84b2ea5428711b7a47146b5b1788bb Author: Jean Delvare Date: Mon Jun 12 21:53:02 2006 +0200 [PATCH] i2c-i801: Better pci subsystem integration i2c-i801: Better pci subsystem integration Integrate the i2c-i801 driver better with the pci subsystem, by calling pci_{enable,disable}_device and requesting the I/O region by BAR rather than direct configuration space access. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 455f332323a17446fb66ea7b2f65f2751f1a3f06 Author: Jean Delvare Date: Mon Jun 12 21:52:02 2006 +0200 [PATCH] i2c-i801: Cleanups i2c-i801: Cleanups Various cleanups to the i2c-i801 driver: * Fix documentation file and self file name references. * i801_setup can be marked __devinit. * Drop useless error local variable and label in i801_setup. * Avoid a double PCI configuration register write in some cases. * Use symbolic names for SMBHSTCFG bits. * Transmit the error code returned by i801_setup instead of forcing it to an arbitrary value. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 520e64d5c081c76b77b4ee87d241cd3e40edc43a Author: Jean Delvare Date: Mon Jun 12 21:51:20 2006 +0200 [PATCH] i2c-i801: Remove PCI function check i2c-i801: Remove PCI function check Remove the PCI function number check when probing devices. This check is redundant, each function has a separate PCI device ID, so checking for that ID is sufficient. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit d8db8f98562c1e358e42503bb920f75f15a5c6d2 Author: Jean Delvare Date: Mon Jun 12 21:50:11 2006 +0200 [PATCH] i2c-i801: Remove force_addr parameter i2c-i801: Remove force_addr parameter Remove the force_addr module parameter. It doesn't appear to ever have been needed, and PCI resources shouldn't be arbitrarily changed anyway. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 397e2f66a23469e2b8a13b764cb2d9ff2444ad5a Author: Jean Delvare Date: Mon Jun 12 21:49:36 2006 +0200 [PATCH] i2c-i801: Fix block transaction poll loops i2c-i801: Fix block transaction poll loops Two of the three poll loops have the poll and sleep swapped, causing an extra sleep to occur after the polled condition is fulfilled. In practice, this doubles the amount of sleep time for every block transaction. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 62aaa288ab0425b058fd337c5135a32e8c1aeace Author: Jean Delvare Date: Mon Jun 12 21:48:08 2006 +0200 [PATCH] scx200_acb: Documentation update Documentation update for the scx200_acb driver. Hopefully this will help future users. References: [lm-sensors] Support of i2c-nscacb (April, May 2005) http://lists.lm-sensors.org/pipermail/lm-sensors/2005-April/011756.html http://lists.lm-sensors.org/pipermail/lm-sensors/2005-May/012043.html [lm-sensors] making a geode i2c slave driver (April 2006) http://lists.lm-sensors.org/pipermail/lm-sensors/2006-April/015998.html Kernel bug #6445 http://bugzilla.kernel.org/show_bug.cgi?id=6445 Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 9917392608c6d8b8952bce9f7b5867b1e9149235 Author: Jean Delvare Date: Mon Jun 12 21:46:04 2006 +0200 [PATCH] scx200_acb: Mark scx200_acb_probe __init In i2c bus driver scx200_acb, function scx200_acb_probe can be tagged __init. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 80cd3a8769c66203d55cdf635390bdcebd742091 Author: Jordan Crouse Date: Mon Jun 12 21:44:28 2006 +0200 [PATCH] scx200_acb: Use PCI I/O resource when appropriate On the CS5535 and CS5536, the I/O resource is allocated through PCI, so use that instead of using the MSR backdoor. Signed-off-by: Jordan Crouse Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 46f5ed753fac512f73069bd07455555b41a8a06e Author: Krzysztof Halasa Date: Mon Jun 12 21:42:20 2006 +0200 [PATCH] i2c: Mark block write buffers as const The attached patch marks i2c_smbus_write_block_data() and i2c_smbus_write_i2c_block_data() buffers as const. Signed-off-by: Krzysztof Halasa Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 1ded969fb97fba33e7310ef95f0b3e3123d4d92a Author: Peter Korsgaard Date: Mon Jun 12 21:40:53 2006 +0200 [PATCH] i2c-ocores: Minor cleanups Minor cleanup to the i2c-ocores driver. Peter Korsgaard will maintain the i2c-ocores driver. Signed-off-by: Peter Korsgaard Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit b7c066044f4355d9fbe1ac45e03303b78d21e8d4 Author: Hans de Goede Date: Sun Jun 4 20:24:11 2006 +0200 [PATCH] abituguru: Fix fan detection One of my testers had a problem where the driver only saw 2 of the 4 fan sensors his uGuru has, this fixes this. -accept 0x40 (bit 6) being high as a valid fan sensor setting for all fans not just fan 1, I have a feeling this bit indicates whether or not a fan is actually connected . Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit a2392e0b907b9633c31be14ee75bb39fce348b01 Author: Hans de Goede Date: Sun Jun 4 20:23:01 2006 +0200 [PATCH] abituguru: Review fixes Fixes to the Abit uGuru driver as requested in review by Jean Delvare: - exactly calculate the sysfs_names array length using macro - use snprintf when generating names to double check that the sysfs_names array does not overflow. - use ARRAY_SIZE and / or defines to determine number of loops in for loops instead of using hardcoded values. - In abituguru_probe(), refactor the error path leaving a single call to kfree Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit f2b84bbcebfdbe4855bab532909eef6621999f9f Author: Hans de Goede Date: Sun Jun 4 20:22:24 2006 +0200 [PATCH] abituguru: New hardware monitoring driver New hardware monitoring driver for the Abit uGuru Signed-off-by: Hans de Goede Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit bed730821b74be4c7d135098842219473f7c8f2c Author: Yuan Mu Date: Sun Jun 4 20:18:45 2006 +0200 [PATCH] w83792d: Add missing data access locks Add missing data lock in w83792d driver to avoid unexpected data change. Signed-off-by: Yuan Mu Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 53e2761bb2e4ed58913c266ad13e8c10692aec1e Author: Yuan Mu Date: Sun Jun 4 20:18:05 2006 +0200 [PATCH] w83792d: Fix setting the PWM value W83792D use pwm register low 4 bits to store PWM/DC value, bit 7 is used to store fan PWM/DC mode. The store_pwm function did not convert the pwm input correctly, so it may change the fan mode when new value is set. This fix the problem. Change the "index" value of pwm*_mode and pwm* SENSOR_ATTR to simplify code. Signed-off-by: Yuan Mu Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 3dc26c600cbae8e8e7566136148aef5667e8342b Author: Jean Delvare Date: Sun Jun 4 20:13:01 2006 +0200 [PATCH] hwmon: Drop some maintainers entries I no more wish to be listed as the maintainer for the smsc47m1 and w83l785ts drivers. I have no test device, and people will fallback to me as the general hardware monitoring maintainer anyway. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 0a704681f37f8cd84fa10312728a39e9fcf2c2c5 Author: Jean Delvare Date: Sun Jun 4 20:10:55 2006 +0200 [PATCH] hwmon: Fix a typo in the hdaps driver Fix a typo in the hdaps driver. Signed-off-by: Jean Delvare Acked-by: Robert Love Signed-off-by: Greg Kroah-Hartman commit 740e06a89fb905ee1979c57442c544afe51ed21c Author: Jean Delvare Date: Mon Jun 5 20:31:20 2006 +0200 [PATCH] hwmon: Sysfs interface documentation update, 2 of 2, take 2 Reword and complete certain parts of the hwmon sysfs-interface documentation file. Hopefully this will make things clearer for new driver authors. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 057bc350992fa2ac31fcd2ff80add269bdf32a80 Author: Rudolf Marek Date: Sun Jun 4 20:03:39 2006 +0200 [PATCH] hwmon: Sysfs interface documentation update, 1 of 2 This patch cleans up hwmon sysfs documentation file, plus introduces the description of DC/PWM selection for fan speed control. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 18f98b1e3147afdb51e545cc6ff2b016c7d088a7 Author: Peter Korsgaard Date: Sun Jun 4 20:01:08 2006 +0200 [PATCH] i2c: New bus driver for the OpenCores I2C controller The following patch adds support for the OpenCores I2C controller IP core (See http://www.opencores.org/projects.cgi/web/i2c/overview). Signed-off-by: Peter Korsgaard Signed-off-by: Andrew Morton Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit aee62305345863430a937af289b9bd080a100dac Author: Jean Delvare Date: Sun Jun 4 19:59:57 2006 +0200 [PATCH] i2c: Suggest N for rare devices in Kconfig Improve the Kconfig help text of the follwing i2c drivers: * busses/i2c-pca-isa.c * chips/pcf8574.c * chips/pcf8591.c These are hard to detect and building them into the kernel results in long delays at boot. March 2006, thread "I2C_PCA_ISA causes boot delays" http://marc.theaimsgroup.com/?l=linux-kernel&m=114360399415744&w=2 April 2006, thread "i2c-related 1-minute hang during bootup" http://marc.theaimsgroup.com/?l=linux-kernel&m=114640992330721&w=2 Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 177d165d7c2ec424007d6241a93d0cb83d953c51 Author: Rudolf Marek Date: Tue Apr 25 14:24:46 2006 +0200 [PATCH] HWMON: Trim VID values to correct number of bits Following patch trims the VID value to correct number of bits for each VRM. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 0d0001dd956d4ae2c8739c2877fa660eec68ed5f Author: Jean Delvare Date: Tue Apr 25 14:23:01 2006 +0200 [PATCH] HWMON: Improve the help text for CONFIG_HWMON Improve the help text for CONFIG_HWMON to let the users know how they pick the right hardware monitoring driver(s) for their system. Also fix a couple typos in the related documentation file and improve some parts a bit. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 114cc0c0c1e98f0b8e205f91ae7b2471e0ad5325 Author: Jean Delvare Date: Tue Apr 25 14:22:14 2006 +0200 [PATCH] HWMON: lm83: Documentation update One more motherboard confirmed to have an LM83 temperature sensor chip. Thanks to Steven Hardy for reporting. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 9873964d6eb24bd0205394f9b791de9eddbcb855 Author: Charles Spirakis Date: Tue Apr 25 14:21:03 2006 +0200 [PATCH] HWMON: w83791d: New hardware monitoring driver for the Winbond W83791D Add support for the w83791d sensor chip. The w83791d hardware is somewhere between the w83781d and the w83792d and this driver code is derived from the code that supports those chips. Signed-off-by: Charles Spirakis Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 4f507ea1560805b16cf4a4359e304ae0db0c2dcb Author: Jean Delvare Date: Tue Apr 25 14:20:11 2006 +0200 [PATCH] HWMON: hdaps: Update the list of supported systems Update the list of systems supported by the hdaps driver: * Add the "ThinkPad Z60m" entry, reported by Arkadiusz Miskiewicz. * Add the "ThinkPad H" entry, reported by Frank Gevaerts for some ThinkPad R52 models (1846AQG). * Drop the "ThinkPad X41 Tablet" entry, which looks redundant to me. And a comment update for good measure. Signed-off-by: Jean Delvare Cc: Arkadiusz Miskiewicz Cc: Frank Gevaerts Signed-off-by: Greg Kroah-Hartman commit 5c7ae65899a4c5b05b6277f856018d1eeeb98907 Author: Jean Delvare Date: Tue Apr 25 14:18:16 2006 +0200 [PATCH] I2C: i2c-nforce2: Add support for the nForce4 MCP51 and MCP55 Add support for the new nForce4 MCP51 (also known as nForce 410 or 430) and nForce4 MCP55 to the i2c-nforce2 driver. Some code changes were required because the base I/O address registers have changed in these versions. Standard BARs are now being used, while the original nForce2 chips used non-standard ones. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit f9ba6c04ef1dcf16f7179b7883e9751baaac218e Author: Jean Delvare Date: Tue Apr 25 13:37:25 2006 +0200 [PATCH] I2C: i2c-piix4: Document the IBM problem more clearly Properly document on which systems the i2c-piix4 SMBus driver will refuse to load. Hopefully this will make it clearer for users, which were often wondering why their destop or server systems were detected as laptops. Closes bug #6429. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 7aadb8f943f6f8fb48962099cfba05ad0518b0ac Author: Jean Delvare Date: Tue Apr 25 13:29:26 2006 +0200 [PATCH] I2C: i2c-piix4: Fix typo in documentation Fix i2c-piix4 documentation typo. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 54aaa1ca1022d95d854315743241bb6bf59f531f Author: Rudolf Marek Date: Tue Apr 25 13:06:41 2006 +0200 [PATCH] I2C: i2c-piix4: Remove the fix_hstcfg parameter This patch removes the fix_hstcfg option from the driver and related SMBus Interrupt Select register magic because now we know what are valid values for this register. This patch updates the documentation and adds new IRQ mode check so we are sure not to miss any new "unusual" value. The PCI quirk for users of fix_hstcfg was not developed because the chipset lacks of subsystem ID registers and DMI is stated "To be filled". Impact to existing systems is minimal because the problem showed up on motherboards like 10 years back. On the other hand users of newer Serverworks and HT1000 systems won't be misleaded by the message suggesting to try the fix_hstcfg any more. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 5e9f4f2e5a02bb6908278a819952aa31fffefaa2 Author: Mark A. Greer Date: Tue Apr 25 13:04:54 2006 +0200 [PATCH] I2C: m41t00: Add support for the ST M41T81 and M41T85 This patch adds support for the ST m41t81 and m41t85 i2c rtc chips to the existing m41t00 driver. Since there is no way to reliably determine what type of rtc chip is in use, the chip type is passed in via platform_data. The i2c address and square wave frequency are passed in via platform_data as well. To accommodate the use of platform_data, a new header file include/linux/m41t00.h has been added. The m41t81 and m41t85 chips halt the updating of their time registers while they are being accessed. They resume when a stop condition exists on the i2c bus or when non-time related regs are accessed. To make the best use of that facility and to make more efficient use of the i2c bus, this patch replaces multiple i2c_smbus_xxx calls with a single i2c_transfer call. Signed-off-by: Mark A. Greer Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit e931b8d8a428f87e6ea488d2fd80007bb66b3ea8 Author: Mark A. Greer Date: Fri Mar 31 23:06:46 2006 +0200 [PATCH] i2c: cleanup m41t00 This patch does some cleanup to the m41t00 i2c/rtc driver including: - use BCD2BIN/BIN2BCD instead of BCD_TO_BIN/BIN_TO_BCD - use strlcpy instead of strncpy - some whitespace cleanup Signed-off-by: Mark A. Greer Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 02e0c5d5c2e00374b6808a42f8eea4ea9baaa216 Author: Rudolf Marek Date: Thu Mar 23 16:48:09 2006 +0100 [PATCH] i2c-piix4: Add ATI IXP200/300/400 support This patch adds the ATI IXP southbridges support to i2c-piix4, as it turned out those chips are compatible with it. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 400b48ecd95a7fac6b126042d37b7efe0202b582 Author: Jean Delvare Date: Thu Mar 23 16:46:47 2006 +0100 [PATCH] hwmon: Add sysfs interface for individual alarm files Extend the sysfs interface of hardware monitoring chips, by adding individual alarm and beep files. Contrary to the old aggregated "alarms" and "beeps" files, individual files constitute a standard way to access the status information, making it finally possible to implement a chip-independant hardware monitoring chip access library (once all drivers have been added this new interface, that is.) If future drivers need more individual files, the interface will be extended as needed at the same time these drivers are merged into the kernel tree. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 568825c8ed3c902981ce908ed5693abb3c9ddf59 Author: Jean Delvare Date: Thu Mar 23 16:40:23 2006 +0100 [PATCH] f71805f: Resource needs not be global The F71805F I/O resource structure needs not be a global variable, as the platform core allocs its own copy of it anyway. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 59ac83677f72ea2cc25b5426e7df9589aa7a5384 Author: Hartmut Rick Date: Thu Mar 23 16:37:23 2006 +0100 [PATCH] smsc47m192: New hwmon driver for SMSC LPC47M192/997 New driver (smsc47m192) which supports voltage and temperature measurement features of SMSC LPC47M192 and LPC47M997 chips. Signed-off-by: Hartmut Rick Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit a4589dbb4e2dc758d1aadb8b5d7e5a598ccb0341 Author: Jean Delvare Date: Thu Mar 23 16:30:29 2006 +0100 [PATCH] w83627ehf: Add alarms support Add alarms support for the W83627EHF/EHG hardware monitoring chip. This is based on an earlier patch from Rudolf Marek. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit cf0676fe42c8e14c4c7ed5895e2fe5d17f779b43 Author: Rudolf Marek Date: Thu Mar 23 16:25:22 2006 +0100 [PATCH] w83627ehf: Add voltage inputs support Add the voltage measuring support to W83627EHF. The code is based on the patch provided by Yuan Mu from Winbond. Signed-off-by: Yuan Mu Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 43cb7ebee2f478d3f987ad773d4e6b07fc23c631 Author: Jordan Crouse Date: Thu Mar 23 16:19:49 2006 +0100 [PATCH] lm83: Add LM82 support Add LM82 temperature sensor support (similar to the LM83, but less featureful). Signed-off-by: Jordan Crouse Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman commit 005b5e4d0c7795d2ec298c34c96cbe2c1e1902b0 Author: Uli Luckas Date: Thu Jun 22 16:49:54 2006 +0100 [ARM] 3624/1: Report true modem control line states Patch from Uli Luckas This patch removes the fake return from serial_pxa_get_mctrl. Signed-off-by: Uli Luckas I just can't remember why this return was there. Being in the first column clearly indicates it was meant to be removed. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King commit 3f1244a2f8d3892f991b662cea49b2a0b4e0c115 Author: Or Gerlitz Date: Thu May 11 10:03:30 2006 +0300 IB/iser: iSER Kconfig and Makefile Kconfig and Makefile for iSER. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier commit 6461f64ab51e6929680df064b2682004a1548290 Author: Or Gerlitz Date: Thu May 11 10:03:08 2006 +0300 IB/iser: iSER handling of memory for RDMA This file contains the processing carried over an SG list associated with a SCSI command such that it can be registered with the IB verbs. The registration produces a network virtual address (VA) and a remote access key (RKEY or STAG in iSER spec notation) which are used by the target for its RDMA operation. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier commit 1cfa0a75dbef1d5bf687aacafabb023288f6b36a Author: Or Gerlitz Date: Thu May 11 10:02:46 2006 +0300 IB/iser: iSER RDMA CM (CMA) and IB verbs interaction This file contains the low level interaction with the RDMA CM and the IB verbs, where iSER is consumer of both. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier commit e85b24b5e7de9f507c6253183d089370f37618c5 Author: Or Gerlitz Date: Thu May 11 10:02:19 2006 +0300 IB/iser: iSER initiator iSCSI PDU and TX/RX This file contains the iSER initiator processing of iSCSI PDUs - controls, commands and data-outs along with processing of TX and RX completions. It interacts with the lower level iser code doing the memory registration and and the cma and verbs calls. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier commit 65e7ae7bfc71219f13162b3bbad44e6471cd67f9 Author: Or Gerlitz Date: Thu May 11 10:00:44 2006 +0300 IB/iser: iSCSI iSER transport provider high level code This file contains the code that registeres with the iscsi transport manager and with the SCSI Mid Layer, where much of the provided functions to iSCSI and SCSI are implemented in libiscsi. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier commit 49cd5382f629bde2aee9f817cefb271106dc47ee Author: Or Gerlitz Date: Thu May 11 10:00:21 2006 +0300 IB/iser: iSCSI iSER transport provider header file iSER (iSCSI Extensions for RDMA) transport provider driver for the iSCSI initiator, whose other parts (under drivers/scsi) are scsi_transport_iscsi - the transport management module, iscsi_tcp - the TCP transport provider module and libiscsi - a kernel library (module) implementing functionality needed by both TCP and iSER transports. iSER is both a provider of the iSCSI transport api and a SCSI low level driver. This file contains internal data structures and non static service functions. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier commit 9b8efc0242777353d5d62bfaa7766ebf0b5598b4 Author: Roland Dreier Date: Thu Jun 22 07:47:27 2006 -0700 IB/uverbs: Remove unnecessary list_del()s In ib_uverbs_cleanup_ucontext(), when iterating through the lists of objects, there's no reason to do list_del() to remove the objects, since both the objects and the lists that contain them are about to be freed anyway. Since list_del() is a moderately big inline function, getting rid of this extra work saves quite a bit of .text: add/remove: 0/0 grow/shrink: 1/2 up/down: 3/-217 (-214) function old new delta ib_uverbs_comp_handler 225 228 +3 ib_uverbs_async_handler 256 255 -1 ib_uverbs_close 905 689 -216 Signed-off-by: Roland Dreier commit 183208284e3ab3816189fc0e23faf29675ce6c9f Author: Krishna Kumar Date: Thu Jun 22 07:47:27 2006 -0700 IB/uverbs: Don't free wr list when it's known to be empty In ib_uverbs_post_send(), move the "out:" label after the loop that frees the list of work requests, since the only place that jumps there is before any work requests could possibly be added to the list. This removes a compile warning: "is_ud might be used uninitialized in this function". Signed-off-by: Krishna Kumar Signed-off-by: Roland Dreier commit 8b76a68c6caafef5a91cdc80958aecaca76a8896 Author: Lennert Buytenhek Date: Thu Jun 22 10:30:56 2006 +0100 [ARM] 3620/2: ixp23xx: add uengine loader support Patch from Lennert Buytenhek This patch allows the ixp2000 uengine loader that is already in the tree to also be used on the ixp23xx. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit 744da2cb598639767ddcc90ca855771bc524fe76 Author: Lennert Buytenhek Date: Thu Jun 22 10:30:55 2006 +0100 [ARM] 3618/1: add defconfig for logicpd pxa270 card engine Patch from Lennert Buytenhek As it's slightly nontrivial to make it possible to build a single kernel image for both the mainstone and the logicpd pxa270 card engine, add a separate defconfig for the logicpd pxa270 card engine for now. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit a059e33ce67cec5e990fdec43f242d3b06c60d1a Author: Lennert Buytenhek Date: Thu Jun 22 10:30:54 2006 +0100 [ARM] 3617/1: ep93xx: fix slightly incorrect timer tick rate Patch from Lennert Buytenhek The tick rate of timers 1-3 isn't exactly 508 kHz as some parts of the relevant documentation claim, but more like 508.469 kHz (14.7456 MHz divided by 29.) Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit f869afab8f36c5f8561557f74b4b9846719092da Author: Lennert Buytenhek Date: Thu Jun 22 10:30:53 2006 +0100 [ARM] 3616/1: fix timer handler wrap logic for a number of platforms Patch from Lennert Buytenhek A couple of platforms aren't using the right comparison type in their timer interrupt handlers (as we're comparing two wrapping timestamps, we need a bmi/bpl-type comparison, not an unsigned comparison) -- this patch fixes them up. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit 84b61f6d3ad8a5761e61d83076588f64a289a574 Author: Lennert Buytenhek Date: Thu Jun 22 10:30:52 2006 +0100 [ARM] 3615/1: ixp23xx: use platform devices for physmap flash Patch from Lennert Buytenhek Now that the physmap platform device rewrite is in, make the ixp23xx boards use platform devices for physmap flash. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit 0967b5f0790cff737c86e9797cbbbdf420eb00f3 Author: Lennert Buytenhek Date: Thu Jun 22 10:30:51 2006 +0100 [ARM] 3614/1: ep93xx: use platform devices for physmap flash Patch from Lennert Buytenhek Now that the physmap platform device rewrite is in, make the ep93xx boards use platform devices for physmap flash. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit ae2a120ce50e9dc8092f9bd4d76d8c8150a12c48 Author: Vitaly Wool Date: Thu Jun 22 10:27:15 2006 +0100 [ARM] 3621/1: fix compilation breakage for pnx4008 Patch from Vitaly Wool pnx4008_defconfig fails to build: include/asm/hardware/debug-8250.S: Assembler messages: include/asm/hardware/debug-8250.S:12: Error: Macro with this name was already defined. This is due to senduart macro erroneously defined in include/asm-arm/arch-pnx4008/debug-macro.S. This patch removes it from that file. Signed-off-by: Vitaly Wool Signed-off-by: Russell King commit b741483d7d8d86d215daf2a1f77bc3d3770746a6 Author: Vitaly Wool Date: Thu Jun 22 10:26:21 2006 +0100 [ARM] 3623/1: pnx4008: move GPIO-related defines to gpio.h Patch from Vitaly Wool This patch moves GPIO-related defines and static inline funcs from include/asm-arm/arch-pnx4008/pm.h to include/asm-arm/arch-pnx4008/gpio.h. Also, some more GPIO-related defines are added to include/asm-arm/arch-pnx4008/gpio.h as they are needed for the USB host driver (coming soon...) Signed-off-by: Vitaly Wool Signed-off-by: Russell King commit e9931b5da6247c18cbf4db8e9e924c980758f41a Author: Vitaly Wool Date: Thu Jun 22 10:26:20 2006 +0100 [ARM] 3622/1: pnx4008: remove clk_use/clk_unuse Patch from Vitaly Wool clk_use/clk_unuse functions are no longer needed, so removing those from arch/arm/mach-pnx4008/clock.c. Also, the order of functions is rearranged a bit, to avoid forward declarations. Signed-off-by: Vitaly Wool Signed-off-by: Russell King commit 1a6be26d5b1a86f66ef60e5b73bae64d50873724 Author: Russell King Date: Wed Jun 21 13:51:41 2006 +0100 [ARM] Enable VFP to be built when non-VFP capable CPUs are selected Since we pass flags to the compiler to control code generation based on the least capable selected CPU, if we want to include VFP support, we must tweak the assembler flags to allow the VFP instructions. Moreover, we must not use the mrrc/mcrr versions since these will not be recognised by the assembler. We do not convert all instructions to the VFP-equivalent (yet) since binutils appears to barf on "fmrx rn, fpinst" and doesn't provide any other way (other than using the mrc equivalent) to encode this instruction - which is rather a problem when you have a VFP implementation which requires these instructions. Signed-off-by: Russell King commit d6551e884cf66de072b81f8b6d23259462c40baf Author: Russell King Date: Wed Jun 21 13:31:52 2006 +0100 [ARM] Add thread_notify infrastructure Some machine classes need to allow VFP support to be built into the kernel, but still allow the kernel to run even though VFP isn't present. Unfortunately, the kernel hard-codes VFP instructions into the thread switch, which prevents this being run-time selectable. Solve this by introducing a notifier which things such as VFP can hook into to be informed of events which affect the VFP subsystem (eg, creation and destruction of threads, switches between threads.) Signed-off-by: Russell King commit 4ec223d02f4d5f5a3129edc0e3d22550d6ac8a32 Author: Venkatesh Pallipadi Date: Wed Jun 21 15:18:34 2006 -0700 [CPUFREQ] Fix ondemand vs suspend deadlock Rootcaused the bug to a deadlock in cpufreq and ondemand. Due to non-existent ordering between cpu_hotplug lock and dbs_mutex. Basically a race condition between cpu_down() and do_dbs_timer(). cpu_down() flow: * cpu_down() call for CPU 1 * Takes hot plug lock * Calls pre down notifier * cpufreq notifier handler calls cpufreq_driver_target() which takes cpu_hotplug lock again. OK as cpu_hotplug lock is recursive in same process context * CPU 1 goes down * Calls post down notifier * cpufreq notifier handler calls ondemand event stop which takes dbs_mutex So, cpu_hotplug lock is taken before dbs_mutex in this flow. do_dbs_timer is triggerred by a periodic timer event. It first takes dbs_mutex and then takes cpu_hotplug lock in cpufreq_driver_target(). Note the reverse order here compared to above. So, if this timer event happens at right moment during cpu_down, system will deadlok. Attached patch fixes the issue for both ondemand and conservative. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones commit 43104f1da88f5335e9a45695df92a735ad550dda Author: Greg Kroah-Hartman Date: Tue Jun 20 15:14:07 2006 -0700 [PATCH] USB: only make /sys/class/usb show up when there is something in it Now /sys/class/usb is dynamically created when we have something to put in it, and removed when all devices go away. Just trying to cut down on the clutter in sysfs... Signed-off-by: Greg Kroah-Hartman commit bd00949647ddcea47ce4ea8bb2cfcfc98ebf9f2a Author: Greg Kroah-Hartman Date: Tue Jun 20 13:09:50 2006 -0700 [PATCH] USB: convert usb class devices to real devices Signed-off-by: Greg Kroah-Hartman commit c182274ffe1277f4e7c564719a696a37cacf74ea Author: Greg Kroah-Hartman Date: Mon Jun 19 23:59:31 2006 -0700 [PATCH] USB: move usb_device_class class devices to be real devices This moves the usb class devices that control the usbfs nodes to show up in the proper place in the larger device tree. No userspace changes is needed, this is compatible due to the symlinks generated by the driver core. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman commit 9bde7497e0b54178c317fac47a18be7f948dd471 Author: Greg Kroah-Hartman Date: Wed Jun 14 12:14:34 2006 -0700 [PATCH] USB: make endpoints real struct devices This will allow for us to give endpoints a major/minor to create a "usbfs2-like" way to access endpoints directly from userspace in an easier manner than the current usbfs provides us. Signed-off-by: Greg Kroah-Hartman commit 36679ea59846d8f34a48f71ca1a37671ca0ad3c5 Author: Greg Kroah-Hartman Date: Wed Jun 14 12:14:34 2006 -0700 [PATCH] USB: make usb_create_ep_files take a struct device Instead of a kobject, will make things easier in the future (don't know what I was thinking when I did this originally...) Signed-off-by: Greg Kroah-Hartman commit 84412f6291b50690febd81899e46f0f0ef7a13e0 Author: Greg Kroah-Hartman Date: Wed Jun 14 12:14:34 2006 -0700 [PATCH] USB: move the endpoint specific sysfs code to it's own file This makes it easier to modify in the future without touching anything else. Signed-off-by: Greg Kroah-Hartman commit ae0dadcf0f912cbab2ac84caa437454620bf71b2 Author: David Brownell Date: Tue Jun 13 10:04:34 2006 -0700 [PATCH] USB: move to Move to and remove some redundant includes. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 325a4af60dc945bf2da9cbcdbabb276e312b297c Author: David Brownell Date: Tue Jun 13 09:59:32 2006 -0700 [PATCH] USB: move hardware-specific to This moves header files for controller-specific platform data from to to start reducing some clutter. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit a8c28f2389942bab376e39351d27525499630248 Author: David Brownell Date: Tue Jun 13 09:57:47 2006 -0700 [PATCH] USB: move to This moves to to reduce some of the clutter of usb header files. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 7e27f18c8a37ffb95f677e4e9c3cca818a3e9eb1 Author: David Brownell Date: Tue Jun 13 09:54:40 2006 -0700 [PATCH] USB: whitespace removal from usb/gadget/ether This removes extraneous whitespace from the Ethernet/RNDIS gadget driver. It's all space-at-EOL, spaces-before-tabs, or tabs-then-spaces. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit d5681fe8110e1169902df37a8fd8bd01c2b7810e Author: Alan Stern Date: Tue Jun 13 09:59:32 2006 -0400 [PATCH] USB: unusual_devs entry for Nokia N80 Here is a patch (as720) adding an unusual_devs entry for the Nokia N80 mobile phone. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit db54a53d26322e978e66482208afabaab9cd0752 Author: Luiz Fernando N. Capitulino Date: Mon Jun 12 22:46:20 2006 -0300 [PATCH] usbserial: Fixes wrong return values. Some usbserial functions returns -EINVAL if the port doesn't exist or if it's not opened. However, the right error code for such situations is -ENODEV. Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman commit 043ea18b2e145c4c9cb3c30757a65fe0f1678a35 Author: Milan Svoboda Date: Mon May 29 03:34:00 2006 -0700 [PATCH] usb gadget: update pxa2xx_udc.c driver to fully support IXP4xx platform This patch adds IXP465 into the list of known devices and adds IXP425 and IXP465 to the list of devices that have cfr. This is not described in the hardware documentation, but without it driver won't work. Workaround (#if 1) that seemed to get rid of lost status irqs is disabled for IXP4XX as it caused freezes during testing of control messages. No lost irqs are visible on IXP4XX. Driver survived tests running over night without any visible problems. Signed-off-by: Milan Svoboda Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 44df45a09c7c20bbd641b1c30b6406d54ba7e2c8 Author: Milan Svoboda Date: Mon May 29 03:34:00 2006 -0700 [PATCH] usb gadget: fix compile errors This patch fixes compile errors when pxa2xx_udc is to be compiled for ixp4xx platform. Signed-off-by: Milan Svoboda Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 7c0642c196beb41b7770571b8a61151bdd418bbe Author: Milan Svoboda Date: Mon May 29 03:34:00 2006 -0700 [PATCH] usb gadget: allow drivers support speeds higher than full speed This patch removes limitation which prevents use of drivers that support speeds different that full speed. Signed-off-by: Milan Svoboda Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit ca094f1186ef50ef8983325072cdc4f051830f13 Author: Franck Bui-Huu Date: Wed Jun 14 10:47:18 2006 +0200 [PATCH] USB: gadget-serial: do not save/restore IRQ flags in gs_close() As pointed out by David Brownell, we know that IRQs are never blocked when calling gs_close function. So the save/restore IRQ flags are pointless. Signed-off-by: Franck Bui-Huu Signed-off-by: Greg Kroah-Hartman commit 943e1b4d60dc7acfabe2ebad31189bcb3b853688 Author: Franck Bui-Huu Date: Wed Jun 14 10:29:21 2006 +0200 [PATCH] USB: gadget-serial: fix a deadlock when closing the serial device When closing the device, the driver acquires/release twice the port lock before/after waiting for the data to be completely sent. Therefore it will dead lock. This patch fixes it and also uses the generic scheduler services for waiting for an event. Signed-off-by: Franck Bui-Huu Signed-off-by: Greg Kroah-Hartman commit b059c81af7a1759a911cfc20ce8a4bf47c435830 Author: Frank Gevaerts Date: Wed Jun 14 15:52:05 2006 +0200 [PATCH] USB Serial: clean tty fields on failed device open If either the driver's open() method or try_module_get() fails, we need to set 'tty->driver_data' and 'port->tty' to NULL in serial_open(), otherwise we'll get an OOPS in usb_device_disconnect() when the device is disconnected. Signed-off-by: Frank Gevaerts Acked-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman commit 4186c29ca199063facdda49851b4c863699687b1 Author: Matt Reimer Date: Wed Jun 7 11:46:13 2006 -0700 [PATCH] USB: trivial DEBUG message correction in gadget ether driver Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 4255e6f6d98ad092c27fa2b83ac314cbe8a0c56f Author: Oliver Bock Date: Sat Jun 10 00:42:19 2006 +0200 [PATCH] USB: new driver for Cypress CY7C63xxx mirco controllers This is a new driver for the Cypress CY7C63xxx mirco controller series. It currently supports the pre-programmed CYC63001A-PC by AK Modul-Bus GmbH. It's based on a kernel 2.4 driver (cyport) by Marcus Maul which I ported to kernel 2.6 using sysfs. I intend to support more controllers of this family (and more features) as soon as I get hold of the required IDs etc. Please see the source code's header for more information. Signed-off-by: Oliver Bock Signed-off-by: Greg Kroah-Hartman commit d9ac2cfc3aaf3bc37da4192d3edfa11d2ad2e96f Author: Pete Zaitcev Date: Mon Jun 12 20:09:39 2006 -0700 [PATCH] USB: update usbmon.txt Fix up the documentation. Apparently, I left unedited copy-paste results in examples. Also, Alan helped me to improve the most confusing parts. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit 12e72feab5d9a23107f245b0f241a2484cbb5a4e Author: Pete Zaitcev Date: Fri Jun 9 22:03:32 2006 -0700 [PATCH] USB: implement error event in usbmon Implement the "error" event in usbmon. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit 5b1c674d223eef6c6494be8be91e9e3a3054817e Author: Pete Zaitcev Date: Fri Jun 9 20:10:10 2006 -0700 [PATCH] USB: update usbmon, fix glued lines This update contains one bug fix: some lines can come out truncated, because of the safety cutoff. This happened because I forgot to update the size when status packets began to be printed. The rest is: - Comments updates - Allow snooping with pkmap on x86_64, which is cache-coherent - Enlarge event buffers (certainly we can have a couple of pages) - Add event counter First touch upon usbmon for 2.6.18. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit 4bc203d997c0dc1eada4cc9681372c2f7a456c46 Author: Pete Zaitcev Date: Tue Jun 6 18:18:33 2006 -0700 [PATCH] USB: io_edgeport touch-up Al Borchers suggested to do this in his review of my previous patch. I guess that I skipped this initially because of my visceral dislike of sizeof(data). But in this case it seems well localized. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit 34ab86e140e9810d6c5162971b6dcf01fcc0f11c Author: Timothy Sipples Date: Fri Jun 16 20:42:59 2006 +0900 [PATCH] airprime.c: add Kyocera Wireless KPC650/Passport support Adds vendor & product IDs to drivers/usb/serial/airprime.c for Kyocera Wireless KPC650/Passport EV-DO/1xRTT PC Cards. Signed-off-by: Timothy Sipples Signed-off-by: Greg Kroah-Hartman commit c5e3b741a3fec6077a480aa65ded29d79ded8898 Author: Alan Stern Date: Mon Jun 5 12:28:57 2006 -0400 [PATCH] UHCI: Improve FSBR-off timing This patch (as707) improves the FSBR operation in uhci-hcd by turning it off more quickly when it isn't needed. FSBR puts a noticeable load on a computer's PCI bus, so it should be disabled as soon as possible when it isn't in use. The patch leaves it running for only 10 ms after the last URB stops using it, on the theory that this should be long enough for a driver to submit another URB if it wants keep FSBR going. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit e323de46e83b6df2f330651907ac823f8d53308a Author: Alan Stern Date: Mon Jun 5 12:21:30 2006 -0400 [PATCH] UHCI: remove hc_inaccessible flag This patch (as706) removes the private hc_inaccessible flag from uhci-hcd. It's not needed because it conveys exactly the same information as the generic HCD_FLAG_HW_ACCESSIBLE bit. In its place goes a new flag recording whether the controller is dead. The new code allows a complete device reset to resurrect a dead controller (although usbcore doesn't yet implement such a facility). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit be3cbc5f87d4b1fbd714644b6824ce4eb229f372 Author: David Brownell Date: Mon Jun 5 12:16:39 2006 -0400 [PATCH] UHCI: various updates This patch (as705) contains a small set of updates for uhci-hcd written mostly by Dave Brownell: * Root hub suspend messages come out labeled as root hub messages; PCI messages should only come out when the pci device suspends. * Rename the reset() method to better match its init() role * Behave more like the other HCDs by returning -ESHUTDOWN for root-hub suspend/resume errors. * When an URB fails, associate the message with the usb device not the host controller (it still hides endpoint and direction) From: David Brownell Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit ae671813affd947d2f21ff8e3cd329e466ee85b2 Author: Alan Stern Date: Tue Jun 6 15:19:17 2006 -0400 [PATCH] usb-storage: unusual_devs entry for Nikon DSC D70s This patch (as704) adds an unusual_devs entry for the Nikon DSC D70s, which uses a different Product ID from the D70. It also moves the entry for the DSC E2000 up in the list, to preserve the numerical ordering. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 5c218e3b86510f9685bfae5b0d2d7cc8468056c1 Author: Rene Rebe Date: Sun Jun 4 11:39:09 2006 +0200 [PATCH] USB: Add Apple MacBook product IDs to usbhid This adds the Apple MacBook product IDs for the Fn translation to the usbhid. Signed-off-by: Rene Rebe Signed-off-by: Greg Kroah-Hartman commit dfbaa7d8a4056436b6a170625d64986ebb648486 Author: Ralf Baechle Date: Sat Jun 3 23:58:55 2006 +0100 [PATCH] USB: EHCI on non-Au1200 build fix Including ehci-au1xxx.c on a non-Au1200 Alchemy only to have it throw an error is stupid. From: Ralf Baechle Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit bfd5df3c0cf65bdf10a3a00baff036cb096140f6 Author: Chris Lund Date: Sat Jun 3 13:58:19 2006 -0700 [PATCH] USB: free allocated memory on io_edgeport startup memory failure While an Edgeport is allocating individual port structures, if kmalloc returns NULL, the serial structure is freed and -ENOMEM, but the ports allocated before the failure are not freed. This patch addresses that condition. Signed-off-by: Christopher Lund Signed-off-by: Greg Kroah-Hartman commit 14f76cc7ab75b1c9db036dcd6b247e0dcc8952be Author: Matthias Urlichs Date: Fri Jun 2 11:48:56 2006 +0200 [PATCH] USB: new devices for the Option driver This patch extends the "option" driver with a few more devices, some of which are actually connected to USB the "right" way -- as opposed to doing it via PCMCIA and OHCI. Signed-Off-By: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman commit 786dc1d3d7333f269e17d742886eac2188a2d9cc Author: Philippe Retornaz Date: Thu Jun 1 20:48:46 2006 -0700 [PATCH] usb: drivers/usb/core/devio.c dereferences a userspace pointer See http://bugzilla.kernel.org/show_bug.cgi?id=6617. This function dereference a __user pointer. Signed-off-by: Philippe Retornaz Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit 6ad07129a8ed2e13dcd7e6313c201c32bcf7cc32 Author: Alan Stern Date: Thu Jun 1 13:59:16 2006 -0400 [PATCH] usbcore: recovery from Set-Configuration failure This patch (as703) improves the error handling when a Set-Configuration request fails. The old interfaces are all unregistered before the request is sent, and if the request fails then we don't know what config the device is using. So it makes no sense to leave actconfig pointing to the old configuration with its invalid interfaces. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit df9a1f482d1252045210f50048911e2efba61e62 Author: Alan Stern Date: Thu Jun 1 13:55:28 2006 -0400 [PATCH] usbhid: use usb_reset_composite_device This patch (as702) makes usbhid use the new usb_reset_composite_device API. Now HID interfaces can coexist with other interfaces on the same device, and a reset can safely be requested by any of the drivers. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 47104b0dd32cec467574822b0dc3517b3de3f0ad Author: Alan Stern Date: Thu Jun 1 13:52:56 2006 -0400 [PATCH] usb-storage: use usb_reset_composite_device This patch (as701) modifies usb-storage to take advantage of the new usb_reset_composite_device() API. Now we will be able to safely request port resets even if other drivers are bound to a mass-storage device. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 7de18d8bf4b470752e799e219b38b6dff4b49993 Author: Alan Stern Date: Thu Jun 1 13:37:24 2006 -0400 [PATCH] USB hub: use usb_reset_composite_device This patch (as700) modifies the hub driver to take advantage of the new usb_reset_composite_device API. The existing code had special-case calls stuck into usb_reset_device, just before and after the reset. With the new version there's no need for special-case stuff; it all happens naturally in the form of pre_reset and post_reset notifications. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 79efa097e75018a2918155f343f0e08e61ee8a8c Author: Alan Stern Date: Thu Jun 1 13:33:42 2006 -0400 [PATCH] usbcore: port reset for composite devices This patch (as699) adds usb_reset_composite_device(), a routine for sending a USB port reset to a device with multiple interfaces owned by different drivers. Drivers are notified about impending and completed resets through two new methods in the usb_driver structure. The patch modifieds the usbfs ioctl code to make it use the new routine instead of usb_reset_device(). Follow-up patches will modify the hub, usb-storage, and usbhid drivers so they can utilize this new API. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit efcaa20525fde82bbb4fb8cd9e9016f6fabc6509 Author: David Brownell Date: Tue May 30 20:49:29 2006 -0700 [PATCH] USB: cdc_ether: recognize olympus r1000 (fix regression) Earlier work splitting the "usbnet" driver out into a core plus driver modules was missing a blacklist entry for the Olympus R-1000; it must not use the CDC Ethernet driver, only the "zaurus" support works with it. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit d5ce1379be9c79d4bcf201c20c5cc87bb2bc973c Author: Eric Sesterhenn Date: Thu Jun 1 20:48:45 2006 -0700 [PATCH] USB: negative index in drivers/usb/host/isp116x-hcd.c From: Eric Sesterhenn This fixes coverity Bug #390. With the following code ret = ep->branch = balance(isp116x, ep->period, ep->load); if (ret < 0) goto fail; the problem is that ret and balance are of the type int, and ep->branch is u16. so the int balance() returns gets reduced to u16 and then converted to an int again, which removes the sign. Maybe the following little c program can explain it better: commit b10cee9d035db54d0bf5a9f9fa622dcfc3f740c6 Author: Jeremy Fitzhardinge Date: Wed May 31 11:21:52 2006 -0700 [PATCH] USB: Add Sierra Wireless MC5720 ID to airprime.c Recognize the Sierra Wireless MC5720. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Greg Kroah-Hartman commit 09fd6bc8b453c9215e81911cbb6882556aa03639 Author: Stuart MacDonald Date: Wed May 31 13:28:40 2006 -0400 [PATCH] USB: Whiteheat: fix firmware spurious errors Attached patch fixes spurious errors during firmware load. Signed-off-by: Stuart MacDonald Signed-off-by: Greg Kroah-Hartman commit 069e8a65cd7970b15672825541be59218d9a8a0f Author: akpm@osdl.org Date: Fri May 26 13:17:09 2006 -0700 [PATCH] Driver for Apple Cinema Display This is a driver to control the brightness of an Apple Cinema Display over USB. It updates the local brightness value if the user presses a button on the display. Signed-off-by: Michael Hanselmann Cc: Oliver Neukum Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit eb79b4fda4654eaa7e6421ad41b0a75c7b4f0608 Author: Ian Abbott Date: Tue May 30 12:36:30 2006 +0100 [PATCH] USB: ftdi_sio: add support for Yost Engineering ServoCenter3.1 This patch adds support for Yost Engineering Inc's ServoCenter 3.1 USB product to the ftdi_sio driver's device ID table. The PID was supplied by Aaron Prose of Yost Engineering on the ftdi-usb-sio-devel list. The PID 0xE050 matches the Windows INF files for this device. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman commit 633a7ecf89587879161179ac4f5a03722626866f Author: Alan Stern Date: Tue May 30 10:21:14 2006 -0400 [PATCH] usbhid: Remove unneeded blacklist entries Now that usbhid automatically applies HID_QUIRK_NOGET to keyboards and mice, we no longer need the blacklist entries that were present for no other purpose. This patch (as698) removes them. Signed-off-by: Alan Stern Acked-by: Vojtech Pavlik Signed-off-by: Greg Kroah-Hartman commit 3f8f4a18f4f76a67fe5b80da1d3a3940e41a14a8 Author: Giridhar Pemmasani Date: Tue May 30 10:12:30 2006 -0400 [PATCH] usbcore: Fix broken RNDIS config selection RNDIS devices don't get configured owing to a typo in choose_configuration(). This patch from Giridhar Pemmasani fixes the typo. From: Giridhar Pemmasani Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 1fbe75e12f0dd567c86533e13ba2605f3ecad2e1 Author: Daniel Drake Date: Fri May 26 21:36:28 2006 +0100 [PATCH] USB: print message when device is rejected due to insufficient power 2.6.16 introduces USB power budgeting in the Linux kernel, and since then, a fair number of users have observed that some of their devices no longer work in unpowered hubs (this is not a bug, the devices claim that they need more than 100mA). The very least we can do is print an informational message to the kernel log when this happens, otherwise it is not at all clear why the device was not accepted. Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman commit 955a260829b5848fa90721678bab003234c93356 Author: David Brownell Date: Fri May 26 10:17:03 2006 -0700 [PATCH] USB: more pegasus log spamming removed Remove more log spamming from pegasus: stop talking to the device once we see ENODEV reported. It may take a while before khubd notifies us. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit b5600339cd37472455d99b39963f3106411070b6 Author: Pete Zaitcev Date: Thu May 25 20:08:50 2006 -0700 [PATCH] ub: random cleanups Remove some silly messages and cast in stone "temporary" messages which we keep around. Also, I am hesitant to remove the initialization retries without having the hardware to test (anyone who was at KS04 has a spare?) Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit 688e9fb1bbdd4e5a51b5030b7f9b1c811fd5e5e3 Author: Pete Zaitcev Date: Thu May 25 20:04:54 2006 -0700 [PATCH] ub: atomic add_disk I am taling about this: "if (disk->flags & GENHD_FL_UP) del_gendisk(disk);" If del_gendisk() undoes add_disk() like viro just said, why is it conditional? huh? add_disk() sets the damn flag So, I should not need to check ever so the above is "if I've called add_disk(), call gendisk()" which might be what you want, of course but usually you know if you'd done add_disk() on that puppy anyway In ub, nobody upstream should ever see half-constructed disks before they were passed to add_disk. To that end, only add the struct lun to the list on the path of no return. With that fix in place, we do not need to test GENHD_FL_UP. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit 2f8ad9a1b91bc6856860a2fea8b07e0c82c0ad0a Author: Pete Zaitcev Date: Wed May 24 11:04:04 2006 -0700 [PATCH] USB: rmmod pl2303 after -28 Wait for the scheduled work to finish before freeing memory, prevent oops. http://bugzilla.kernel.org/show_bug.cgi?id=6596 Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit ba47f66bd9fc451e9ce88f291e057b2f4910d01c Author: Dan Streetman Date: Wed May 24 09:39:16 2006 -0700 [PATCH] improved TT scheduling for EHCI This updates the EHCI driver by adding an improved scheduler for the transaction translators, found in USB 2.0 hubs and used for low and full speed devices. - adds periodic_tt_usecs() and some helper functions, which does the same thing that "periodic_usecs" does, except on the other side of the TT, i.e. it calculates the low/fullspeed bandwidth usage instead of highspeed. - adds a tt_available() function which is the new implementation of what tt_no_collision() does ... while tt_no_collision() ensures that each TT handles only 1 periodic transfer at a time (a very pessimistic approach) this version instead tracks bandwidth and allows each TT to handle as many transfers as will fit on each TT's downstream bus (closer to best-case). The new scheduler is selected by a config option, marked as EXPERIMENTAL so it can be tested (and more broadly reviewed) for a while until it seems safe to remove the original scheduler. Signed-off-by: Dan Streetman Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 3428cc43d23f125dcb31c981aa91535dd3c4cb0d Author: Franck Bui-Huu Date: Wed May 24 16:57:28 2006 +0200 [PATCH] usb-storage: get rid of the timer during URB submission This patch uses completion timeout instead of a timer to implement a timeout when submitting an URB. It also put the task in interruptible state instead of an uninterruptible one while waiting for the completion. Signed-off-by: Franck Bui-Huu Signed-off-by: Matthew Dharm Signed-off-by: Greg Kroah-Hartman commit 80b47853b19114dd53e83e15bf1db3e183a66824 Author: Pete Zaitcev Date: Mon May 22 22:05:17 2006 -0700 [PATCH] USB: Syntax cleanup for pl2303 (trailing backslash) Remove the silly trailing backslash. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit 6f065f70c0c1bfb0b8212438cee21e68aa155887 Author: Pete Zaitcev Date: Mon May 22 22:02:32 2006 -0700 [PATCH] USB: Improve Kconfig comment for mct_u232 Add a couple of supported devices into the help message. It's a long story... I promised this comment changed to a user long ago, so I'd like to have that promise kept. In reality though, nobody is likely to read this anyway. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit cf2c7481d2ff7f0c266de873b2fe93883e9782f9 Author: Pete Zaitcev Date: Mon May 22 21:58:49 2006 -0700 [PATCH] USB serial: encapsulate schedule_work, remove double-calling I'm going to throw schedule_work away, it's retarded. But for starters, let's have it encapsulated. Also, generic and whiteheat were both calling usb_serial_port_softint and scheduled work. Only one was necessary. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit ad93375a30334cd97a61f7076d242e1cfdb66abc Author: Pete Zaitcev Date: Mon May 22 21:49:44 2006 -0700 [PATCH] usb: io_edgeport, cleanup to unicode handling Clean up the unicode handling in io_edgeport. Make get_string size-limited. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit 9da2150f59e885d88b9eabe0a677f0fa4962f7b4 Author: Alan Stern Date: Mon May 22 16:47:13 2006 -0400 [PATCH] usbtest: report errors in iso tests This patch (as693b) makes the usbtest driver report errors in the isochronous bulk transfer tests instead of always returning 0. As an arbitrary cutoff, an error is returned if more than 10% of the packet transfers fail. It also stops a test immediately upon receiving an URB submission error. For a test harness, it's especially important to report when errors occur! Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 0ae4ea8092e1277cfca07cade7eaba5f594076c1 Author: Alan Stern Date: Mon May 22 12:27:38 2006 -0400 [PATCH] gadgetfs: fix memory leaks This patch (as692) fixes a few memory leaks in some unimportant error pathways of the gadgetfs driver. Signed-off-by: Alan Stern Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 83196b52053068f0240371ad2efd9d6ad685bbeb Author: Alan Stern Date: Mon May 22 12:26:31 2006 -0400 [PATCH] gadgetfs: fix AIO interface bugs This patch (as691) fixes a few errors in the AIO interface for the gadgetfs driver. Now requests will complete properly instead of hanging. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 212a4b4ed1ea9a969f3f967b3e3a8075ad1cb4de Author: Vitja Makarov Date: Wed May 31 00:40:06 2006 +0400 [PATCH] USB: new cp2101 device By the way I have to ask you to add new (vid,pid) pair to cp2101 driver. This device is argussoft's avr in-system programmer AS3M, http://atmel.argussoft.ru/hard.htm it's based on cp2101 chip and works pretty well with the linux driver. It could be used with argussoft's `asisp1109.exe' (http://atmel.argussoft.ru/download/software/as-tools.soft/asisp.zip) tool run under wine. Signed-off-by: Vitja Makarov Signed-off-by: Greg Kroah-Hartman commit 782a7a632e4b0581ade665e3d89ee97c8db0f441 Author: Greg Kroah-Hartman Date: Fri May 19 13:20:20 2006 -0700 [PATCH] USB: add usb_interrupt_msg() function for api completeness. Really just a wrapper around usb_bulk_msg() but now it's documented much better. Signed-off-by: Greg Kroah-Hartman commit caa2a1226741e023a103e091a7f6dce7c42e82ee Author: Franck Bui-Huu Date: Mon May 15 19:23:53 2006 +0200 [PATCH] Fix a deadlock in usbtest ctrl_complete functions acquires ctx->lock and tries to unlink all queued urbs in case of errors through usb_unlink_urb func. In its turn usb_unlink_urb calls, through the hcd driver, usb_hcd_giveback_urb which calls ctrl_complete again. At this time, ctx->lock is already taken by the same function. Signed-off-by: Franck Bui-Huu Cc: David Brownell Signed-off-by: Greg Kroah-Hartman commit c8155cc5d839838f8425dbea568fc537337176a7 Author: Alan Stern Date: Fri May 19 16:52:35 2006 -0400 [PATCH] UHCI: remove ISO TDs as they are used This patch (as690) does the same thing for ISO TDs as as680 did for non-ISO TDs: free them as they are used rather than all at once when an URB is complete. At the same time it fixes a minor buglet (I'm not aware of it ever affecting anyone): An ISO TD should be retired when its frame is over, regardless of whether or not the hardware has marked it inactive. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit caf3827a65af476c71eaeb79636869a4ab128d48 Author: Alan Stern Date: Fri May 19 16:44:55 2006 -0400 [PATCH] UHCI: store the period in the queue header This patch (as689) stores the period for periodic transfers (interrupt and ISO) in the queue header. This is necessary for proper bandwidth tracking (not yet implemented). It also makes the scheduling of ISO transfers a bit more rigorous, with checks for out-of-bounds frame numbers. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 10b8e47d6b32bfba22874354c62770cb4e42aa6c Author: Alan Stern Date: Fri May 19 16:39:52 2006 -0400 [PATCH] UHCI: fix race in ISO dequeuing This patch (as688) fixes a small race in uhci-hcd. Because ISO queues aren't controlled by queue headers, they can't be unlinked. Only individual URBs can. So whenever multiple ISO URBs are dequeued, it's necessary to make sure the hardware is done with each one. We can't assume that dequeuing the first URB will suffice to unlink the entire queue. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit c433472658b4df11bd3590a59be79194a1ff43ae Author: Alan Stern Date: Fri May 19 16:34:57 2006 -0400 [PATCH] UHCI: use integer-sized frame numbers This patch (as687) changes uhci-hcd to keep track of frame numbers as full-sized integers rather than 11-bit values. This makes them a lot easier to handle and makes it possible to schedule beyond a 2-second window, should anyone ever want to do so. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 3612242e527eb47ee4756b5350f8bdf791aa5ede Author: Micah Dowty Date: Fri May 19 11:26:24 2006 -0700 [PATCH] USB: Allow high-bandwidth isochronous packets via usbfs This patch increases an arbitrary limit on the size of individual isochronous packets submitted via usbfs. The limit is still arbitrary, but it's now large enough to support the maximum packet size used by high-bandwidth isochronous transfers. Signed-off-by: Micah Dowty Signed-off-by: Greg Kroah-Hartman commit e016683d595aacde78b9385aabd0b98c8915d885 Author: Micah Dowty Date: Fri May 19 11:20:11 2006 -0700 [PATCH] USB: Remove 4088-byte limit on usbfs control URBs This patch removes the artificial 4088-byte limit that usbfs currently places on Control transfers. The USB spec does not specify a strict limit on the size of an entire control transfer. It does, however, state that the data stage "follows the same protocol rules as bulk transfers." (USB 2, 8.5.3) The level of support for large control transfers in real host controllers varies, but it's important to support at least 4K transfers. Windows enforces a maximum control transfer size of 4K, so there exists some hardware that requires a full 4096 byte data stage. Without this patch, we fall short of that by 8 bytes on architectures with a 4K page size, and it becomes impossible to support such hardware with a user-space driver. Since any limit placed on control transfers by usbfs would be arbitrary, this patch replaces the PAGE_SIZE limit with the same arbitrary limit used by bulk transfers. Signed-off-by: Micah Dowty Signed-off-by: Greg Kroah-Hartman commit b9827e4b29edb4af1481b75efdf9ea2d8a7ffc96 Author: David Brownell Date: Tue May 16 17:33:14 2006 -0700 [PATCH] USB: correct the USB info in Documentation/power/swsusp.txt The swsusp.txt documentation harshes confusingly on USB, and this patch addresses the issue. It's harsh because it blames USB for some issues that are generic to all drivers -- especially those supporting removable media -- and it's confusing since it says that USB has the issue with "suspend" not just swsusp ... while in reality, USB doesn't have the issue when real system suspend states are used. Signed-off-by: David Brownell Acked-by: Pavel Machek Signed-off-by: Greg Kroah-Hartman commit b761d9d867bcc29e8de3e62d1d72b27e75078ca6 Author: Alan Stern Date: Fri May 12 11:41:59 2006 -0400 [PATCH] UHCI: Work around old Intel bug Some old Intel UHCI controllers have a bug that has shown up in a few systems (the PIIX3 "Neptune" chip set). Until now there has not been any simple way to work around the bug, but the lastest changes in uhci-hcd have made it easy. This patch (as684) adds the work-around. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 84afddd7ac58adad00cb0e50d0af25fcf825668b Author: Alan Stern Date: Fri May 12 11:35:45 2006 -0400 [PATCH] UHCI: Reimplement FSBR This patch (as683) re-implements Full-Speed Bandwidth Reclamation (FSBR) properly. It keeps track of which endpoint queues have advanced, and when none have advanced for a sufficiently long time, FSBR is turned off. The next TD on each of the non-moving queues is modified to generate an interrupt on completion, so that FSBR can be re-enabled as soon as the hardware starts to make some progress. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 04538a255ac8b404c20cbf15867c9829254c470f Author: Alan Stern Date: Fri May 12 11:29:04 2006 -0400 [PATCH] UHCI: Eliminate the TD-removal list This patch (as682) gets rid of the TD-removal list in uhci-hcd. It is no longer needed because now TDs are not freed until we know the hardware isn't using them. It also simplifies the code for adding and removing TDs to/from URBs. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit a0b458b64b2a3a4cb806dd5cd889bbf6c7e9d686 Author: Alan Stern Date: Fri May 12 11:23:19 2006 -0400 [PATCH] UHCI: Move code for cleaning up unlinked URBs This patch (as681) moves some code for cleaning up after unlinked URBs out of the general completion pathway into the unlinking pathway. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 59e29ed91cff90b27d393c7a3d3ac9c3fcaea7dd Author: Alan Stern Date: Fri May 12 11:19:19 2006 -0400 [PATCH] UHCI: Remove non-iso TDs as they are used This patch (as680) frees non-isochronous TDs as they are used, rather than all at once when an URB is complete. Although not a terribly important change in itself, it opens the door to a later enhancement that will reduce storage requirements by allocating only a limited number of TDs at any time for each endpoint queue. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit b1869000a60b0c72022811f24110a52d3e300b1e Author: Alan Stern Date: Fri May 12 11:14:25 2006 -0400 [PATCH] UHCI: Common result routine for Control/Bulk/Interrupt This patch (as679) combines the result routine for Control URBs with the routine for Bulk/Interrupt URBs. Along the way I eliminated the debugging printouts for Control transfers unless the debugging level is set higher than 1. I also eliminated a long-unused (#ifdef'ed-out) section that works around some buggy old APC BackUPS devices. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 0f28b55db543001d360e4319bfc3f2c4e28ba05f Author: Alan Stern Date: Mon May 15 14:49:04 2006 -0400 [PATCH] usbhid: automatically set HID_QUIRK_NOGET for keyboards and mice It seems to be relatively common for USB keyboards and mice to dislike being polled for reports. Since there's no need to poll a keyboard or a mouse, this patch (as685) automatically sets the HID_QUIRK_NOGET flag for devices that advertise themselves as either sort of device with boot protocol support. This won't cure all the problems since some devices don't support the boot protocol, but it's simple and easy and it should fix quite a few problems. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit a82e49b8aeb9f8dafdf6cf2e617c8b95bf056257 Author: Bart Massey Date: Mon May 8 14:40:13 2006 -0700 [PATCH] USB HID/HIDBP, INPUT DRIVERS: fix various usb/input/hid-input.c bugs that make Apple Mighty Mouse work poorly Transposed lines of code in drivers/usb/input/hid-input.c causes the capability bits for a new HID device to be set before quirks are applied at configuration time. When an HID event is then sent up to the input layer, it may then be discarded as irrelevant because the wrong capability bit is set. Further, the quirks for the Apple Mighty Mouse are not quite right: the horizontal scrolling needs its axis reversed, and the left and center buttons are transposed. Also, the mouse is labeled in the kernel with its earlier name (I think) of Apple PowerMouse. Steps to reproduce problem: Plug in an Apple Mighty Mouse. Note that horizontal scrolling doesn't work at all, and in fact doesn't generate any input events on /dev/input/eventN. Note also that pushing the middle button performs the right button action, and vice versa. Once you have the horizontal scrolling working, note that it is backward WRT both to vertical scrolling and to common sense. This patch maybe should be broken up, as it does address two problems. The transposed code in hidinput_configure_usage() probably creates bugs beyond just the Mighty Mouse. The rest of the patch renames POWERMOUSE to MIGHTYMOUSE everywhere (which I *believe* is correct), fixes the MIGHTYMOUSE quirk to swap the center and right mouse buttons, and adds a new quirk HID_QUIRK_INVERT_HWHEEL also assigned to the MIGHTYMOUSE with code in hidinput_hid_event() to implement it. Signed-off-by: Bart Massey Signed-off-by: Greg Kroah-Hartman commit 2775562ad2af2fc131ef7987166db6e42217528f Author: Alan Stern Date: Fri May 5 16:32:02 2006 -0400 [PATCH] USB: UHCI: fix obscure bug in enqueue() This patch (as676) fixes a small bug in uhci-hcd's enqueue routine. When an URB is unlinked or gets an error and the completion handler queues another URB for the same endpoint, the queue shouldn't be allowed to start up again until the handler returns. Not even if the new URB is the only one on its queue. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 4de7d2c231a8624a47417977be0768c5b5257c4f Author: Alan Stern Date: Fri May 5 16:26:58 2006 -0400 [PATCH] USB: UHCI: store the endpoint type in the QH structure This patch (as675) simplifies uhci-hcd slightly by storing each endpoint's type in the corresponding Queue Header structure. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 2d61bde7a0e630e1906e6478b6b2a7aeaaa8f8da Author: Alan Stern Date: Fri May 5 16:23:42 2006 -0400 [PATCH] USB: net2280: add a shutdown routine The net2280 board has an annoying habit of surviving soft reboots with interrupts enabled. This patch (as674) adds a shutdown routine to the driver so that the board can be put in a quiescent state. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit b383539e04c413e040d998aedcc120c49aa670da Author: Daniel Drake Date: Tue May 9 01:45:27 2006 +0100 [PATCH] USB: usb-storage alauda: Fix transport info mismerge Unfortunately it looks like the transport entry for this subdriver was merged into the protocol section, making this driver unusable :( Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman commit f9347c52347f24244c550871eab8ecb0fb5704d6 Author: Daniel Drake Date: Mon May 8 23:43:02 2006 +0100 [PATCH] USB shuttle_usbat: hardcode flash detection for now After some further testing with my flash device I realised that our current probe doesn't always work (e.g. when no media is inserted). Now that Peter Chubb's patch has simplified the detection of 99% of the HP CD writers out there, we have a much smaller range of hardware to work with on the shared device ID, so it should be possible to try some of the previous probe options again: we just need to find another tester with a USBAT2-based HP CD writer. This patch hardcodes the flash detection until someone comes along with one of these obscure CD drives. Note that these devices are extremely rare, so even if we can't ever find a decent probe method, at least we will be supporting almost all of the USBAT-based hardware out there. Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman commit bdcfd9e349eff9398a1d85eaa517294f493bb3c8 Author: Peter Chubb Date: Tue May 2 18:29:34 2006 +0100 [PATCH] USB: shuttle_usbat: Hardcode detection of HP CDRW devices Use USB vendor and product IDs to determine whether the attached device is a CDROM or a Flash device. Daniel Drake says that the *same* vendor and product IDs for non-HP vendor ID could be either flash or cdrom, so try to probe for them. Signed-off-by: Peter Chubb Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman commit 141804d401631f0384feabfa5fc3e2ce1321c0f0 Author: Peter Chubb Date: Tue May 2 18:30:12 2006 +0100 [PATCH] USB: shuttle_usbat: Fix handling of scatter-gather buffers I've worked out what's going wrong. The scsi layer is now much more likely to pass down scatterlists instead of plain buffers. So you have to make sure that they're handled correctly. In one of the changes along the way, usbat_write_block and friends stopped obeying the srb->use_sg flag. Anyway, with the appended patch, and the one I'm putting in the next email, it all seems to work for the HP cd4e. Of course, someone's going to have to test it with the flash drives as well.... This patch teaches the usbat_{read,write}_block functions to obey the use_sg flag in the scsi-request. Signed-off-by: Peter Chubb Signed-off-by: Daniel Drake Signed-off-by: Greg Kroah-Hartman commit 69165c29bb4db9bafead7c6574c73ce245965f3a Author: Sean Young Date: Tue May 2 11:44:43 2006 +0000 [PATCH] USB Phidget InterfaceKit: make inputs pollable and new device support Make inputs pollable using sysfs_notify and add support for the Phidget InterfaceKit 0/16/16. Various cleanups. Signed-off-by: Sean Young Signed-off-by: Daniel Saakes Signed-off-by: Greg Kroah-Hartman commit a01c4ef1cc9622fcce5c10ddb8e9e7f76206959e Author: Duncan Sands Date: Fri Apr 28 18:58:57 2006 +0200 [PATCH] USBATM: remove no-longer needed #include We #include only because needed it, but didn't #include it itself. But that's been fixed now. Signed-off-by: Duncan Sands Signed-off-by: Greg Kroah-Hartman commit fcf4830a525d37b9bd3ba60430b5729b8621062d Author: Duncan Sands Date: Fri Apr 28 18:53:45 2006 +0200 [PATCH] USBATM: remove pointless inline Remove pointless inline. Signed-off-by: Duncan Sands Signed-off-by: Greg Kroah-Hartman commit 41fea55e0382b7d59d694d8055b39aa69c793b1f Author: Pete Zaitcev Date: Fri Apr 28 20:45:49 2006 -0700 [PATCH] USB: clean out an unnecessary NULL check from ub Remove the check for NULL which makes no sense. Suggested by Al. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman commit 4489a5712b086621a6c3f669057d2996245cd3fb Author: Alan Stern Date: Thu Apr 27 15:54:22 2006 -0400 [PATCH] USB: usbcore: always turn on hub port power Some hubs claim not to support port-power switching, and right now the hub driver believes them and does not enable power to their ports. However it turns out that even though they don't actually switch power, they do ignore all events on a port until told to turn on the power! This problem has been reported by several users. This revised patch (as672b) makes the hub driver always try to turn on port power to all hubs, regardless of what the hub descriptor says. It also adds a comment explaining the need for this. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit 9effa978f1d51f6d0426ebabcf6cb32336bb3153 Author: Nicolas Boichat Date: Wed Apr 19 23:36:40 2006 +0200 [PATCH] USB: MacBook Pro touchpad support Add support for MacBook touchpad in appletouch driver. Thanks to Alex Harper for the informations. Use u16 instead of int16_t in atp_is_geyser* functions. Acked-by: Johannes Berg Acked-by: Stelian Pop Signed-off-by: Nicolas Boichat Signed-off-by: Greg Kroah-Hartman commit 73e487fdb75f8abf230968dbf73a3dc3b16808d3 Author: Guennadi Liakhovetski Date: Tue Apr 25 07:46:17 2006 +0200 [PATCH] USB console: fix disconnection issues Prevent sending further output to a USB-serial console after the dongle is disconnected, take care not to leak kref. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman commit ca85485c1f482e6625f36aceb85eaaeff4b22d79 Author: Paul Fulghum Date: Thu Apr 13 22:28:17 2006 +0200 [PATCH] USB: console: prevent ENODEV on node Prevent ENODEV on a /dev/ttyUSBx, used as a USB-serial console. From: Paul Fulghum Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman commit 57845bd104233cb75b9ab3624f7ea7662298bc27 Author: Guennadi Liakhovetski Date: Thu Apr 13 22:27:12 2006 +0200 [PATCH] USB: console: fix oops Prevent NULL dereference when used as a USB-serial console. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman commit c10746dbb39d41e5fc27badfebe61448210c426d Author: Paul Fulghum Date: Thu Apr 13 22:26:35 2006 +0200 [PATCH] USB: console: fix cr/lf issues Append Carriage-Returns after Line-Feeds, analogous to the serial driver. From: Paul Fulghum Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman commit 01cced250722d22d99c2342979490f93ca886521 Author: Kumar Gala Date: Tue Apr 11 10:07:16 2006 -0500 [PATCH] USB: allow multiple types of EHCI controllers to be built as modules In some systems we may have both a platform EHCI controller and PCI EHCI controller. Previously we couldn't build the EHCI support as a module due to conflicting module_init() calls in the code. Signed-off-by: Kumar Gala Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit df47e5330b0f5decb0a5736e9a81fff49d46d151 Author: Adrian Bunk Date: Sat Apr 15 11:17:27 2006 +0200 [PATCH] USB: sisusbvga: possible cleanups This patch contains the following possible cleanups: - make needlessly global functions static - function and struct declarations belong into header files - make SiS_VCLKData const - #if 0 the following unused global functions: - sisusb.c: sisusb_writew() - sisusb.c: sisusb_readw() - sisusb_init.c: SiSUSB_GetModeID() Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman commit 2682d27c5884550857cd96231db5b22b3acced53 Author: Arjan van de Ven Date: Tue Mar 28 01:00:21 2006 -0800 [PATCH] USB: convert the semaphores in the sisusb driver to mutexes From: Arjan van de Ven Convert the semaphores-used-as-mutex to mutexes in the sisusb video driver; this required manual checking due to the "return as locked" stuff in this driver, but the ->lock semaphore is still used as mutex in the end. Signed-off-by: Arjan van de Ven Cc: Thomas Winischhofer Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit 7327413c745c2f8e8d4b92f76759821263b095c1 Author: Eduard Warkentin Date: Thu May 18 01:13:17 2006 -0700 [PATCH] USB: added support for ASIX 88178 chipset USB Gigabit Ethernet adaptor Add support for detection and dworking with a ASIX 88178 based USB-Gigabit adaptor. With the patch, it is detected and handled correctly by the asix module. Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit f44f725f7d635e8b9786eef13f836dc1a2851495 Author: David Brownell Date: Fri May 12 19:24:34 2006 -0700 [PATCH] USB: usbnet, zaurus mtu fixup This includes an MTU fixup which could affect larger packets with newer Zaurii, described as http://bugzilla.kernel.org/show_bug.cgi?id=6286; plus minor whitespace cleanup. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 86478944eba887f149e151bacc023ae4b2d23ea6 Author: Oliver Neukum Date: Sat May 13 22:50:47 2006 +0200 [PATCH] USB: cdc-acm: add a new special case for modems with buggy firmware this fixes the "duplicated text" bug. There's a modem that cannot cope with large transfers and more than one urb in flight. This patch adds a special case to the driver. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman commit 5cd330f4f30eb154e7af9210bed42dfcd447997f Author: Henk Vergonet Date: Mon May 15 12:34:43 2006 +0200 [PATCH] USB: add YEALINK phones to the HID_QUIRK_IGNORE blacklist Keys on Yealink based phones will not function properly when using the generic HID driver. This patch prevents the generic HID code from grabbing the device before the regular yealink driver can get a grip on it. Signed-off-by: Henk Vergonet Signed-off-by: Vojtech Pavlik Signed-off-by: Greg Kroah-Hartman commit c32ba30f76eb18b3d4449072fe9c345a9574796b Author: Paul Serice Date: Wed Jun 7 10:23:38 2006 -0700 [PATCH] USB: EHCI works again on NVidia controllers with >2GB RAM From: Paul Serice The workaround in commit f7201c3dcd7799f2aa3d6ec427b194225360ecee broke. The work around requires memory for DMA transfers for some NVidia EHCI controllers to be below 2GB, but recent changes have caused some DMA memory to be allocated before the DMA mask is set. Signed-off-by: Paul Serice Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 9ba89334552b96e2127dcafb1c46ce255ecf2667 Author: Ian Wienand Date: Wed Jun 21 10:33:04 2006 +1000 [IA64] SKI Simulator boot Sorry I didn't notice earlier, but that BUG_ON triggers for me on the simulator. AFAICS the mask for itv is set in cpu_init(), which comes after sal_init(). Consequently on the simulator the itv still has its start value of zero. I've probably missed something, but I wonder why at this stage of the boot you even need to save and restore the itv? Signed-Off-By: Ian Wienand Signed-off-by: Tony Luck commit f640f94ec4f39e8a4d91d58354d3e09b28769edf Author: Mike Habeck Date: Mon Jun 19 15:38:10 2006 -0500 [IA64-SGI] fix SGI Altix tioce_bus_fixup() bug The following patch fixes a bug in the SGI Altix tioce_bus_fixup() code. ce_dre_comp_err_addr needs to be zero'd out not ~0ULL. As a result completion errors weren't being captured. Signed-off-by: Mike Habeck Signed-off-by: Tony Luck commit d270acbc24f0ce451c773c214ac0e92e95396b2f Author: Keith Owens Date: Fri Apr 7 18:08:11 2006 +1000 [IA64] Sanitize assembler code for ia64_sal_os_state struct ia64_sal_os_state has three semi-independent sections. The code in mca_asm.S assumes that these three sections are contiguous, which makes it very awkward to add new data to this structure. Remove the assumption that the sections are contiguous. Define a macro to shorten references to offsets in ia64_sal_os_state. This patch does not change the way that the code behaves. It just makes it easier to update the code in future and to add fields to ia64_sal_os_state when debugging the MCA/INIT handlers. Signed-off-by: Keith Owens Signed-off-by: Tony Luck commit b7bb575c3fa3694811a072109f4e9c2f4705d8f5 Author: Kenji Kaneshige Date: Fri Apr 28 11:50:43 2006 +0900 [IA64] Make PCI Express support selectable When I tried to use PCI Express Hotplug driver on my ia64 box, I noticed that "PCI Express support" is not even selectable on ia64. This patch makes PCI Express support selectable. Signed-off-by: Kenji Kaneshige Signed-off-by: Tony Luck commit ea95972f18481089e73368f9e62f6d70087bf4de Author: Russ Anderson Date: Wed May 10 11:09:01 2006 -0500 [IA64-SGI] Remove SN SAL error handling feature bit that is no longer needed Due to improvements in linux & SAL MCA handling, the SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV error handling features bit is no longer needed. Signed-off-by: Russ Anderson (rja@sgi.com) Signed-off-by: Tony Luck commit 65884734902c8f0b4d83293985678ab83b24ef72 Author: David Mosberger-Tang Date: Wed May 24 22:16:03 2006 -0600 [IA64] make efi_stub.S fit in 80 cols Just a trivial cleanup patch Signed-off-by: Tony Luck commit 9ed059e1551bf36092215b965838502ac21f42e4 Author: Randy Dunlap Date: Tue Jun 20 22:32:56 2006 -0700 [CPUFREQ] Fix powernow-k8 SMP kernel on UP hardware bug. Fix powernow-k8 doesn't load bug. Reference: https://launchpad.net/distros/ubuntu/+source/linux-source-2.6.15/+bug/35145 Signed-off-by: Ben Collins Signed-off-by: Dave Jones commit 491b07c98f2ac75f1a4370af76ae2403a4c579f5 Author: Jeremy Fitzhardinge Date: Wed Jun 21 13:15:48 2006 -0700 [PATCH] redirect speedstep-centrino maintainer mail to cpufreq list I haven't really maintained this driver for a while, and I'm not keeping up with the latest in Intel power management. I get a steady stream of mail which I don't really do anything useful with; the cpufreq list seems like a better destination, unless someone wants to get the mail directly. Also clean up a couple of ancient comments which don't really apply anymore (as far as I know, nobody has ever damaged a CPU with this driver). Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Dave Jones commit a1d7057727bc9e20a0a417812f538fe6b8a02c03 Author: Jack Steiner Date: Wed May 31 08:58:08 2006 -0500 [IA64-SGI] SN topology fix for large systems There is an SN bug in sn_hwperf.c that affects systems with 1024n or 1024p. The bug manifests itself 2 ways: IO interrupts are not always targeted to the nearest node, and 2) the "cat /proc/sgi_sn/sn_topology" commands fails with "cannot allocate memory". The code is using the wrong macros for validating node numbers. Signed-off-by: Jack Steiner Signed-off-by: Tony Luck commit 5eb1d63f5fc8455269c2756223b3cf3779fd2f7a Author: Alex Williamson Date: Tue Jun 6 10:36:27 2006 -0600 [IA64] sanity check reserved region usage One more trivial, stand-alone patch from the Xen/ia64 review. Sanity check usage of the reserved region numbers. Signed-off-by: Alex Williamson Signed-off-by: Tony Luck commit 120b286d3c94a4e59fdb8069d42e8d49ea468ffd Author: Alex Williamson Date: Tue Jun 6 10:23:34 2006 -0600 [IA64] add vmlinuz target This is a trivial stand-alone patch out of the Xen/ia64 patches. Add a vmlinuz build target to be more compatible with x86-ish targets. Signed-off-by: Alex Williamson Signed-off-by: Tony Luck commit a5117ba7da37deb09df5eb802dace229b3fb1e9f Author: Rene Herman Date: Tue Jun 6 23:54:02 2006 +0200 [PATCH] Driver model: add ISA bus During the recent "isa drivers using platform devices" discussion it was pointed out that (ALSA) ISA drivers ran into the problem of not having the option to fail driver load (device registration rather) upon not finding their hardware due to a probe() error not being passed up through the driver model. In the course of that, I suggested a seperate ISA bus might be best; Russell King agreed and suggested this bus could use the .match() method for the actual device discovery. The attached does this. For this old non (generically) discoverable ISA hardware only the driver itself can do discovery so as a difference with the platform_bus, this isa_bus also distributes match() up to the driver. As another difference: these devices only exist in the driver model due to the driver creating them because it might want to drive them, meaning that all device creation has been made internal as well. The usage model this provides is nice, and has been acked from the ALSA side by Takashi Iwai and Jaroslav Kysela. The ALSA driver module_init's now (for oldisa-only drivers) become: static int __init alsa_card_foo_init(void) { return isa_register_driver(&snd_foo_isa_driver, SNDRV_CARDS); } static void __exit alsa_card_foo_exit(void) { isa_unregister_driver(&snd_foo_isa_driver); } Quite like the other bus models therefore. This removes a lot of duplicated init code from the ALSA ISA drivers. The passed in isa_driver struct is the regular driver struct embedding a struct device_driver, the normal probe/remove/shutdown/suspend/resume callbacks, and as indicated that .match callback. The "SNDRV_CARDS" you see being passed in is a "unsigned int ndev" parameter, indicating how many devices to create and call our methods with. The platform_driver callbacks are called with a platform_device param; the isa_driver callbacks are being called with a "struct device *dev, unsigned int id" pair directly -- with the device creation completely internal to the bus it's much cleaner to not leak isa_dev's by passing them in at all. The id is the only thing we ever want other then the struct device * anyways, and it makes for nicer code in the callbacks as well. With this additional .match() callback ISA drivers have all options. If ALSA would want to keep the old non-load behaviour, it could stick all of the old .probe in .match, which would only keep them registered after everything was found to be present and accounted for. If it wanted the behaviour of always loading as it inadvertently did for a bit after the changeover to platform devices, it could just not provide a .match() and do everything in .probe() as before. If it, as Takashi Iwai already suggested earlier as a way of following the model from saner buses more closely, wants to load when a later bind could conceivably succeed, it could use .match() for the prerequisites (such as checking the user wants the card enabled and that port/irq/dma values have been passed in) and .probe() for everything else. This is the nicest model. To the code... This exports only two functions; isa_{,un}register_driver(). isa_register_driver() register's the struct device_driver, and then loops over the passed in ndev creating devices and registering them. This causes the bus match method to be called for them, which is: int isa_bus_match(struct device *dev, struct device_driver *driver) { struct isa_driver *isa_driver = to_isa_driver(driver); if (dev->platform_data == isa_driver) { if (!isa_driver->match || isa_driver->match(dev, to_isa_dev(dev)->id)) return 1; dev->platform_data = NULL; } return 0; } The first thing this does is check if this device is in fact one of this driver's devices by seeing if the device's platform_data pointer is set to this driver. Platform devices compare strings, but we don't need to do that with everything being internal, so isa_register_driver() abuses dev->platform_data as a isa_driver pointer which we can then check here. I believe platform_data is available for this, but if rather not, moving the isa_driver pointer to the private struct isa_dev is ofcourse fine as well. Then, if the the driver did not provide a .match, it matches. If it did, the driver match() method is called to determine a match. If it did _not_ match, dev->platform_data is reset to indicate this to isa_register_driver which can then unregister the device again. If during all this, there's any error, or no devices matched at all everything is backed out again and the error, or -ENODEV, is returned. isa_unregister_driver() just unregisters the matched devices and the driver itself. More global points/questions... - I'm introducing include/linux/isa.h. It was available but is ofcourse a somewhat generic name. Moving more isa stuff over to it in time is ofcourse fine, so can I have it please? :) - I'm using device_initcall() and added the isa.o (dependent on CONFIG_ISA) after the base driver model things in the Makefile. Will this do, or I really need to stick it in drivers/base/init.c, inside #ifdef CONFIG_ISA? It's working fine. Lastly -- I also looked, a bit, into integrating with PnP. "Old ISA" could be another pnp_protocol, but this does not seem to be a good match, largely due to the same reason platform_devices weren't -- the devices do not have a life of their own outside the driver, meaning the pnp_protocol {get,set}_resources callbacks would need to callback into driver -- which again means you first need to _have_ that driver. Even if there's clean way around that, you only end up inventing fake but valid-form PnP IDs and generally catering to the PnP layer without any practical advantages over this very simple isa_bus. The thing I also suggested earlier about the user echoing values into /sys to set up the hardware from userspace first is... well, cute, but a horrible idea from a user standpoint. Comments ofcourse appreciated. Hope it's okay. As said, the usage model is nice at least. Signed-off-by: Rene Herman commit 3e95637a48820ff8bedb33e6439def96ccff1de5 Author: Alan Stern Date: Fri Jun 16 17:10:48 2006 -0400 [PATCH] Driver Core: Make dev_info and friends print the bus name if there is no driver This patch (as721) makes dev_info and related macros print the device's bus name if the device doesn't have a driver, instead of printing just a blank. If the device isn't on a bus either... well, then it does leave a blank space. But it will be easier for someone else to change if they want. Cc: Matthew Wilcox Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman commit e9a7d305faec364ba973d6c22c9b1e802ef79204 Author: Greg Kroah-Hartman Date: Tue Jun 20 13:59:20 2006 -0700 [PATCH] Driver core: add proper symlinks for devices We need to create the "compatible" symlinks that class_devices used to create when they were in the class directories so that userspace does not know anything changed at all. Yeah, we have a lot of symlinks now, but we should be able to get rid of them in a year or two... (wishful thinking...) Signed-off-by: Greg Kroah-Hartman commit b9d9c82b4d081feb464f62dfc786c8621d09ecd2 Author: Kay Sievers Date: Thu Jun 15 15:31:56 2006 +0200 [PATCH] Driver core: add generic "subsystem" link to all devices Like the SUBSYTEM= key we find in the environment of the uevent, this creates a generic "subsystem" link in sysfs for every device. Userspace usually doesn't care at all if its a "class" or a "bus" device. This provides an unified way to determine the subsytem of a device, regardless of the way the driver core has created it. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman commit 23681e479129854305da1da32f7f1eaf635ef22c Author: Greg Kroah-Hartman Date: Wed Jun 14 12:14:34 2006 -0700 [PATCH] Driver core: allow struct device to have a dev_t This is the first step in moving class_device to being replaced by struct device. It allows struct device to export a dev_t and makes it easy to dynamically create and destroy struct device as long as they are associated with a specific class. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman commit aa49b9136e3d44cc264811d77eef4ded88456717 Author: Greg Kroah-Hartman Date: Tue Jun 20 13:59:20 2006 -0700 [PATCH] Driver core: change make_class_name() to take kobjects This is needed for a future patch for the device code to create the proper symlinks for devices that are "class devices". Signed-off-by: Greg Kroah-Hartman commit cad1e55d4d19a49c2b82b74562a6e4e555b05f38 Author: Laura Garcia Date: Tue May 23 23:22:38 2006 +0200 [PATCH] firmware_class: s/semaphores/mutexes Hi, this patch converts semaphores to mutexes for Randy's firmware_class. Signed-off-by: Laura Garcia Liebana Signed-off-by: Greg Kroah-Hartman commit fd869db6eb1ea0ffe251e53a113dbf259400f4f6 Author: David Brownell Date: Tue May 16 17:03:25 2006 -0700 [PATCH] Driver core: PM_DEBUG device suspend() messages become informative This makes the driver model PM suspend debug messages more useful, by (a) explaining what event is being sent, since not all suspend() requests mean the same thing; (b) reporting when a PM_EVENT_SUSPEND call is allowing the device to issue wakeup events. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 1e724845034eb898c97dc6636207f0a231af9432 Author: David Brownell Date: Tue May 16 17:00:08 2006 -0700 [PATCH] remove duplication from Documentation/power/devices.txt Remove a chunk of duplicated documentation text. Signed-off-by: Greg Kroah-Hartman commit 4039483fd3065920f035eed39ec59085421c0a4f Author: Michael Holzheu Date: Tue May 9 12:53:49 2006 +0200 [PATCH] Driver Core: Add /sys/hypervisor when needed To have a home for all hypervisors, this patch creates /sys/hypervisor. A new config option SYS_HYPERVISOR is introduced, which should to be set by architecture dependent hypervisors (e.g. s390 or Xen). Acked-by: Martin Schwidefsky Signed-off-by: Michael Holzheu Signed-off-by: Greg Kroah-Hartman commit e391553222211e07dfbe2f01c413b4e6d0ae32aa Author: Russell King Date: Sat May 6 08:15:26 2006 +0100 [PATCH] Driver Core: Fix platform_device_add to use device_add platform_device_add() should be using device_add() rather than device_register() - any platform device passed to platform_device_add() should have already been initialised, either by platform_device_alloc() or platform_device_register(). Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman commit 670dd90d81f60ef429cbba54ad235e9207f4d444 Author: Shaohua Li Date: Mon May 8 13:45:57 2006 +0800 [PATCH] Driver Core: Allow sysdev_class have attributes allow sysdev_class adding attribute. Next patch will use the new API to add an attribute under /sys/device/system/cpu/. Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman commit 1740757e8f94c6899705eb6f5434de9404992778 Author: Greg Kroah-Hartman Date: Tue May 2 16:59:59 2006 +0200 [PATCH] Driver Core: remove unused exports Cc: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman commit a0245f7ad5214cb00131d7cd176446e067c913dc Author: David Brownell Date: Mon May 29 10:37:33 2006 -0700 [PATCH] platform_bus learns about modalias This patch adds modalias support to platform devices, for simpler hotplug/coldplug driven driver setup. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit 05967118a6c354eaa5950429c70ad4c8daca94bf Author: David Brownell Date: Mon May 1 13:58:33 2006 -0700 [PATCH] Driver Core: CONFIG_DEBUG_PM covers drivers/base/power too The drivers/base/power PM debug messages should appear when either PM or driver model debug are enabled. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman commit b7fe4a60f3a5a428832bf5dd9388e80f0d02fc2e Author: Stephen Hemminger Date: Wed Apr 26 09:53:14 2006 -0700 [PATCH] Driver core: class_device_add needs error checks class_device_add needs to check the return value of all the setup it does. It doesn't handle out of memory well. This is not complete, probably more needs to be done. Signed-off-by: Stephen Hemminger Signed-off-by: Greg Kroah-Hartman commit 3dda4e373c7474cfe280f4270b70c1563f92a2a7 Author: Hansjoerg Lipp Date: Sat Apr 22 18:43:00 2006 +0200 [PATCH] i4l gigaset: move sysfs entry to tty class device Using the class device pointer returned by tty_register_device() with part 1 of the patch, attach the Gigaset drivers' "cidmode" sysfs entry to its tty class device, where it can be found more easily by users who do not know nor care which USB port the device is attached to. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Signed-off-by: Greg Kroah-Hartman commit 1cdcb6b43fda7424b7435dac8f80b2b5d8a48899 Author: Hansjoerg Lipp Date: Sat Apr 22 18:36:53 2006 +0200 [PATCH] TTY: return class device pointer from tty_register_device() Let tty_register_device() return a pointer to the class device it creates. This allows registrants to add their own sysfs files under the class device node. Signed-off-by: Hansjoerg Lipp Signed-off-by: Tilman Schmidt Signed-off-by: Greg Kroah-Hartman commit 53877d06d53a412d901bb323f080296c363d8b51 Author: Kay Sievers Date: Tue Apr 4 20:42:26 2006 +0200 [PATCH] Driver core: bus device event delay split bus_add_device() and send device uevents after sysfs population Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman commit 27c0ff868f2ad3c9732ce45abbb8dd7e1723931f Author: Greg Kroah-Hartman Date: Thu Apr 27 15:46:39 2006 -0700 [PATCH] CCISS: add device symlink to the block cciss block devices in sysfs Signed-off-by: Greg Kroah-Hartman commit c18f6365fdbaf30611a8822afcd7097865dcaa32 Author: Greg Kroah-Hartman Date: Thu Apr 27 14:10:12 2006 -0700 [PATCH] Add kernel<->userspace ABI stability documentation Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman commit 183bd5b3da82b80920c30c4772222df8027fc364 Author: Greg Kroah-Hartman Date: Thu May 18 10:39:21 2006 -0700 [PATCH] kobject: make people pay attention to kobject_add errors These really need to be fixed, shout it out to the world. Signed-off-by: Greg Kroah-Hartman commit cf34a8e07f02c76f3f1232eecb681301a3d7b10b Author: Brice Goglin Date: Tue Jun 13 14:35:42 2006 -0400 [PATCH] PCI: nVidia quirk to make AER PCI-E extended capability visible The nVidia CK804 PCI-E chipset supports the AER extended capability but sometimes fails to link it (with some BIOS or after a warm reboot). It makes the AER cap invisible to pci_find_ext_capability(). The patch adds a quirk to set the missing bit that controls the linking of the capability. By the way, it removes the corresponding code in the myri10ge driver. Signed-off-by: Brice Goglin Signed-off-by: Loic Prylli Signed-off-by: Greg Kroah-Hartman commit ead2bfeb7f739d2ad6e09dc1343f0da51feb7f51 Author: Chuck Ebbert <76306.1226@compuserve.com> Date: Thu Jun 15 04:41:52 2006 -0400 [PATCH] PCI: fix issues with extended conf space when MMCONFIG disabled because of e820 On 15 Jun 2006 03:45:10 +0200, Andi Kleen wrote: > Anyways I would say that if the BIOS can't get MCFG right then > it's likely not been validated on that board and shouldn't be used. According to Petr Vandrovec: ... "What is important (and checked) is address of MMCONFIG reported by MCFG table... Unfortunately code does not bother with printing that address :-( "Another problem is that code has hardcoded that MMCONFIG area is 256MB large. Unfortunately for the code PCI specification allows any power of two between 2MB and 256MB if vendor knows that such amount of busses (from 2 to 128) will be sufficient for system. With notebook it is quite possible that not full 8 bits are implemented for MMCONFIG bus number." So here is a patch. Unfortunately my system still fails the test because it doesn't reserve any part of the MMCONFIG area, but this may fix others. Booted on x86_64, only compiled on i386. x86_64 still remaps the max area (256MB) even though only 2MB is checked... but 2.6.16 had no check at all so it is still better. PCI: reduce size of x86 MMCONFIG reserved area check 1. Print the address of the MMCONFIG area when the test for that area being reserved fails. 2. Only check if the first 2MB is reserved, as that is the minimum. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Acked-by: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman commit bdee9d98d281d84718eaff6bf0dd2b6ad418b36f Author: Doug Thompson Date: Wed Jun 14 16:59:48 2006 -0700 [PATCH] PCI: Bus Parity Status sysfs interface From: Doug Thompson This patch adds the 'broken_parity_status' sysfs attribute file to a PCI device. Reading this attribute a userland program can determine if PCI device provides false positives (value of 1) in its generation of PCI Parity status, or not (value of 0). As PCI devices are found to be 'bad' in this regard, userland programs can also set the appropriate value (root access only) of a faulty device. This per device information will be used in the EDAC PCI Parity scanner code in a future patch once this interface becomes available. Signed-off-by: Doug Thompson Signed-off-by: Greg Kroah-Hartman commit acc7c2e0b73a46122ec370bf8a3aa9f19065d331 Author: Konrad Rzeszutek Date: Thu Jun 15 12:08:30 2006 -0400 [PATCH] PCI: fix memory leak in MMCONFIG error path This a bit late (yours patch was posted about a year ago), but a co-worker of spotted part of the code that looks like a memory leak. Looking at the code it seems that pci_mmcfg_config should be free-ed if MMCONFIG is above 4GB. From: Konrad Rzeszutek Signed-off-by: Greg Kroah-Hartman commit 4d15a1779dfdf7e7a111022697d3a43da1745d31 Author: Greg Kroah-Hartman Date: Tue Jun 6 16:58:25 2006 -0400 [PATCH] PCI: fix error with pci_get_device() call in the mpc85xx driver Signed-off-by: Greg Kroah-Hartman commit bd91fde952b0aa80c820857241ff1923537d2bde Author: Chris Wedgwood Date: Mon Jun 5 00:13:21 2006 -0700 [PATCH] PCI: MSI-K8T-Neo2-Fir: run only where needed Be more selective when running the MSI-K8T-Neo2Fir soundcard PCI quirk so as not to run this on hardware where it's probably not needed. Signed-off-by: Chris Wedgwood Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit d71374dafbba7ec3f67371d3b7e9f6310a588808 Author: Zhang Yanmin Date: Fri Jun 2 12:35:43 2006 +0800 [PATCH] PCI: fix race with pci_walk_bus and pci_destroy_dev pci_walk_bus has a race with pci_destroy_dev. When cb is called in pci_walk_bus, pci_destroy_dev might unlink the dev pointed by next. Later on in the next loop, pointer next becomes NULL and cause kernel panic. Below patch against 2.6.17-rc4 fixes it by changing pci_bus_lock (spin_lock) to pci_bus_sem (rw_semaphore). Signed-off-by: Zhang Yanmin Signed-off-by: Greg Kroah-Hartman commit 733a7fe12248072e1bca729c88a26298666f1956 Author: Grant Grundler Date: Thu Jun 1 11:15:59 2006 -0600 [PATCH] PCI: clean up pci documentation to be more specific On Thu, Jun 01, 2006 at 02:46:11AM -0700, Rajesh Shah wrote: > This patch assumes that pci_request_region() will always be called > after pci_enable_device() and pci_release_region() will always > be called before pci_disable_device(). We cannot make this > assumption,since it's perfectly legal to disable a device > first and then release it's regions. So, I think that patch > needs to change. Patch below clarifies comments in Documentation/pci.txt. Signed-off-by: Grant Grundler Signed-off-by: Greg Kroah-Hartman commit f7e6600d762bf7c04b48c8d9bd0ab26d04a8d11f Author: Grant Grundler Date: Wed May 31 23:35:47 2006 -0700 [PATCH] PCI: remove unneeded msi code The code is really not needed. Roland Dreier/Greg KH removed the release_mem_region() calls that were the only consumers of phys_addr: http://www.ussg.iu.edu/hypermail/linux/kernel/0503.0/1540.html patch below deletes the "dead" code. Signed-off-by: Grant Grundler Signed-off-by: Greg Kroah-Hartman commit c0da3ba0a29d70c95ed39366a1c9b849f3439fbe Author: Kimball Murray Date: Wed May 31 14:20:04 2006 -0400 [PATCH] PCI: don't move ioapics below PCI bridge A recent Stratus x86_64 platform uses a system ioapic that is a PCI device located below a PCI bridge. Other platforms like this may exist. This patch fixes a problem wherein the kernel's PCI setup code moves the ioapic to an address other than that assigned by the BIOS. It simply adds another exclusion (which already includes classless devices and host bridges) to the function pbus_assign_resources_sorted so that it will not move the ioapic. If the ioapic is moved, the fixmap mapping to it is broken, so the OS should leave it alone. From: Kimball Murray Signed-off-by: Greg Kroah-Hartman commit b209a6ee49099b7500abf024f7b6b9648b5a3eac Author: bibo,mao Date: Wed May 31 18:17:33 2006 +0800 [PATCH] PCI: cleanup unused variable about msi driver In IA64 platform, msi driver does not use irq_vector variable, and in x86 platform LAST_DEVICE_VECTOR should one before FIRST_SYSTEM_VECTOR, this patch modify this. Signed-off-by: bibo, mao Signed-off-by: Greg Kroah-Hartman commit 99dc804d9bcc2c53f4c20c291bf4e185312a1a0c Author: Shaohua Li Date: Fri May 26 10:58:27 2006 +0800 [PATCH] PCI: disable msi mode in pci_disable_device Brice said the pci_save_msi_state breaks his driver in his special usage (not in suspend/resume), as pci_save_msi_state will disable msi mode. In his usage, pci_save_state will be called at runtime, and later (after the device operates for some time and has an error) pci_restore_state will be called. In another hand, suspend/resume needs disable msi mode, as device should stop working completely. This patch try to workaround this issue. Drivers are expected call pci_disable_device in suspend time after pci_save_state. Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman commit 020d502488bebdbc1b2c2828d996f04e563f082a Author: Rajesh Shah Date: Tue May 23 10:14:36 2006 -0700 [PATCH] PCI: Allow MSI to work on kexec kernel We recently ran into a problem where the e1000 device failed to work properly on the kexec kernel. MSI was enabled for the device in the main kernel when it crashed. The e1000 driver tried to enable MSI on the kexec kernel, but the code bailed early when it found that MSI was already enabled in the hardware, even though the software state was not properly set up in the kexec'd kernel. This patch fixes the problem by moving the early return to after making sure that the software state is properly initialized. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman commit 1edab4a164b229807853682f7ff7858c11dd3481 Author: Brice Goglin Date: Tue May 23 03:05:27 2006 -0400 [PATCH] PCI: AMD 8131 MSI quirk called too late, bus_flags not inherited ? The PCI_BUS_FLAGS_NO_MSI bus flags does not appear do be inherited correctly from the amd8131 MSI quirk to its parent busses. It makes devices behind a bridge behind amd8131 try to enable MSI while the amd8131 does not support it. We fix this by looking at flags of all parent busses in pci_enable_msi() and pci_enable_msix(). By the way, also add the missing dev->no_msi check in pci_enable_msix() Signed-off-by: Brice Goglin Signed-off-by: Greg Kroah-Hartman commit 74d0a988d3aa359b6b8a8536c8cb92cce02ca5d5 Author: Brent Casavant Date: Wed May 10 01:49:14 2006 -0700 [PATCH] PCI: Move various PCI IDs to header file Move various QLogic, Vitesse, and Intel storage controller PCI IDs to the main header file. Signed-off-by: Brent Casavant Acked-by: Jes Sorensen Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit bd8481e1646d7649fa101ee57a5139b9da3c2436 Author: Doug Thompson Date: Mon May 8 17:06:09 2006 -0700 [PATCH] PCI Bus Parity Status-broken hardware attribute, EDAC foundation Currently, the EDAC (error detection and correction) modules that are in the kernel contain some features that need to be moved. After some good feedback on the PCI Parity detection code and interface (http://www.ussg.iu.edu/hypermail/linux/kernel/0603.1/0897.html) this patch ADDs an new attribute to the pci_dev structure: Namely the 'broken_parity_status' bit. When set this indicates that the respective hardware generates false positives of Parity errors. The EDAC "blacklist" solution was inferior and will be removed in a future patch. Also in this patch is a PCI quirk.c entry for an Infiniband PCI-X card which generates false positive parity errors. I am requesting comments on this AND on the possibility of a exposing this 'broken_parity_status' bit to userland via the PCI device sysfs directory for devices. This access would allow for enabling of this feature on new devices and for old devices that have their drivers updated. (SLES 9 SP3 did this on an ATI motherboard video device). There is a need to update such a PCI attribute between kernel releases. This patch just adds a storage place for the attribute and a quirk entry for a known bad PCI device. PCI Parity reaper/harvestor operations are in EDAC itself and will be refactored to use this PCI attribute instead of its own mechanisms (which are currently disabled) in the future. Signed-off-by: Doug Thompson Signed-off-by: Greg Kroah-Hartman commit 53e4d30dd666d7f83598957ee4a415eefb47c9a6 Author: Rajesh Shah Date: Wed May 3 15:27:47 2006 -0700 [PATCH] PCI: i386/x86_84: disable PCI resource decode on device disable When a PCI device is disabled via pci_disable_device(), it's still left decoding its BAR resource ranges even though its driver will have likely released those regions (and may even have unloaded). pci_enable_device() already explicitly enables BAR resource decode for the device being enabled. This patch disables resource decode for the PCI device being disabled, making it symmetric with the enable call. I saw this while doing something else, not because of a problem report. Still, seems to be the correct thing to do. Signed-off-by: Rajesh Shah Signed-off-by: Greg Kroah-Hartman commit 9c273b95808c270149e9be9e172e4ef19f5d5c98 Author: Muthu Kumar Date: Fri Apr 28 00:42:21 2006 -0700 [PATCH] PCI ACPI: Rename the functions to avoid multiple instances. There were two instances of pci_acpi_init(), one in drivers/pci/pci-acpi.c and another in arch/i386/pci/acpi.c. Rename the one in pci-acpi.c and make it consistent with other names in the same file. Signed-off-by: Muthukumar R Signed-off-by: Greg Kroah-Hartman commit a1e022b3aeacf633a6c8e8f0eb04d9c9e44b4fcd Author: Kristen Accardi Date: Fri Apr 28 11:37:38 2006 -0700 [PATCH] PCI: don't enable device if already enabled If a device is already enabled, don't bother reenabling it. Signed-off-by: Kristen Carlson Accardi Acked-By: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman commit 9f125d30487cea72542a84b4835c037163c7f3d5 Author: Arjan van de Ven Date: Sat Apr 29 10:59:08 2006 +0200 [PATCH] PCI: Add a "enable" sysfs attribute to the pci devices to allow userspace (Xorg) to enable devices without doing foul direct access This patch adds an "enable" sysfs attribute to each PCI device. When read it shows the "enabled-ness" of the device, but you can write a "0" into it to disable a device, and a "1" to enable it. This later is needed for X and other cases where userspace wants to enable the BARs on a device (typical example: to run the video bios on a secundary head). Right now X does all this "by hand" via bitbanging, that's just evil. This allows X to no longer do that but to just let the kernel do this. Signed-off-by: Arjan van de Ven CC: Peter Jones Acked-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman commit 75acfecaa031c0e1bc412cee4fe58ba49ff3406c Author: Kumar Gala Date: Mon May 1 10:43:46 2006 -0500 [PATCH] PCI: Add pci_assign_resource_fixed -- allow fixed address assignments PCI: Add pci_assign_resource_fixed -- allow fixed address assignments On some embedded systems the PCI address for hotplug devices are not only known a priori but are required to be at a given PCI address for other master in the system to be able to access. An example of such a system would be an FPGA which is setup from user space after the system has booted. The FPGA may be access by DSPs in the system and those DSPs expect the FPGA at a fixed PCI address. Added pci_assign_resource_fixed() as a way to allow assignment of the PCI devices's BARs at fixed PCI addresses. Signed-off-by: Kumar Gala Signed-off-by: Greg Kroah-Hartman commit ea28502d5d0fc624777a8a6b4d6865d282055b05 Author: Bjorn Helgaas Date: Fri Jun 9 11:28:29 2006 -0700 [PATCH] PCI: fix to pci ignore pre-set 64-bit bars on 32-bit platforms When we detect a 64-bit pre-set address in a BAR on a 32-bit platform, we disable it and treat it as if it had been unset, thus allowing the general address assignment code to assign a new address to it when the device is enabled. This can happen either if the firmware assigns 64-bit addresses; additionally, some cards have been found "in the wild" which do not come out of reset with all the BAR registers set to zero. Unfortunately, the patch that implemented this tested the low part of the address instead of the high part of the address. This patch fixes that. Signed-off-by: Bjorn Helgaas Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman commit 17d6dc8ff098cc8c57941c82f7702804302b1ea1 Author: H. Peter Anvin Date: Tue Apr 18 17:19:52 2006 -0700 [PATCH] PCI: Ignore pre-set 64-bit BARs on 32-bit platforms [pci] Ignore pre-set 64-bit BARs on 32-bit platforms Currently, Linux always rejects a device which has a pre-set 64-bit address on a 32-bit platform. On systems which do not do PCI initialization in firmware, this causes some devices which don't correctly power up with all BARs zero to fail. This patch makes the kernel automatically zero out such an address (thus treating it as if it had not been set at all, meaning it will assign an address if necessary). I have done this only for devices, not bridges. It seems potentially hazardous to do for bridges. Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman commit 83821d3f558dc651e555d62182ed0c95651f41a6 Author: Mark Maule Date: Fri Apr 14 16:03:54 2006 -0500 [PATCH] PCI: altix: msi support MSI callouts for altix. Involves a fair amount of code reorg in sn irq.c code as well as adding some extensions to the altix PCI provider abstaction. Signed-off-by: Mark Maule Signed-off-by: Greg Kroah-Hartman commit 10083072bfabc40bc47306e512c158c57cf55c2e Author: Mark Maule Date: Fri Apr 14 16:03:49 2006 -0500 [PATCH] PCI: per-platform IA64_{FIRST,LAST}_DEVICE_VECTOR definitions Abstract IA64_FIRST_DEVICE_VECTOR/IA64_LAST_DEVICE_VECTOR since SN platforms use a subset of the IA64 range. Implement this by making the above macros global variables which the platform can override in it setup code. Also add a reserve_irq_vector() routine used by SN to mark a vector's as in-use when that weren't allocated through assign_irq_vector(). Signed-off-by: Mark Maule Signed-off-by: Greg Kroah-Hartman commit fd58e55fcf5568e51da2ed54d7acd049c3fdb184 Author: Mark Maule Date: Mon Apr 10 21:17:48 2006 -0500 [PATCH] PCI: msi abstractions and support for altix Abstract portions of the MSI core for platforms that do not use standard APIC interrupt controllers. This is implemented through a new arch-specific msi setup routine, and a set of msi ops which can be set on a per platform basis. Signed-off-by: Mark Maule Signed-off-by: Greg Kroah-Hartman commit c34b4c734482dda750deb6089521f7c891b48736 Author: Brice Goglin Date: Tue May 9 10:52:09 2006 -0700 [PATCH] PCI: Add PCI_CAP_ID_VNDR Add the vendor-specific extended capability PCI_CAP_ID_VNDR. It will be used by the Myri-10G Ethernet driver (will be submitted soon). Signed-off-by: Brice Goglin Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit 2191fe3e39159e3375f4b7ec1420df149f154101 Author: Kelly Daly Date: Wed Jun 21 13:52:55 2006 +1000 [POWERPC] re-enable OProfile for iSeries, using timer interrupt This patch removes the changes from an earlier patch that disables oProfile for iSeries within the oProfile KConfig (submitted Feb 23, 2006). Checks within the arch init for iSeries, still allowing profiling for timer interrupts (using firmware_has_feature). Signed-off-by: Kelly Daly Acked-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 0bb474a48e5d1ceb8e4005c7664b548c9834a784 Author: Anton Blanchard Date: Tue Jun 20 18:47:26 2006 +1000 [POWERPC] support ibm,extended-*-frequency properties Support the ibm,extended-*-frequency properties found in recent POWER5 firmware: cpus/PowerPC,POWER5@0/clock-frequency 59aa5880 (1504336000) cpus/PowerPC,POWER5@0/ibm,extended-clock-frequency 00000000 59aa5880 cpus/PowerPC,POWER5@0/timebase-frequency 0b354b10 (188042000) cpus/PowerPC,POWER5@0/ibm,extended-timebase-frequency 00000000 0b354b10 Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit ccba051c373e342de240ba00d542dac67ae0eb7e Author: Nathan Lynch Date: Tue Jun 20 18:01:58 2006 +1000 [POWERPC] Extra sanity check in EEH code Don't dereference a device node that isn't there. A "shouldn't happen" case, but someone ran into it with a possibly misconfigured device tree. Signed-off-by: Nathan Lynch Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit d3c58fb177dc957af5cdac5ad1638d713fdb8765 Author: Anton Blanchard Date: Tue Jun 20 18:00:30 2006 +1000 [POWERPC] Dont look for class-code in pci children Looking for class-code in PCI children breaks with direct slots. Lets just count all children. Signed-off-by: Anton Blanchard Acked-by: Olof Johansson Signed-off-by: Paul Mackerras commit 1e92a550e80fef01ebcc0bcd0896109cdb986c72 Author: Anton Blanchard Date: Thu Jun 15 14:11:22 2006 +1000 [POWERPC] Fix mdelay badness on shared processor partitions On partitioned PPC64 systems where a partition is given 1/10 of a processor, we have seen mdelay() delaying for 10 times longer than it should. The reason is that the generic mdelay(n) does n delays of 1 millisecond each. However, with 1/10 of a processor, we only get a one-millisecond timeslice every 10ms. Thus each 1 millisecond delay loop ends up taking 10ms elapsed time. The solution is just to use the PPC64 udelay function, which uses the timebase to ensure that the delay is based on elapsed time rather than how much processing time the partition has been given. (Yes, the generic mdelay uses the PPC64 udelay, but the problem is that the start time gets reset every millisecond, and each time it gets reset we lose another 9ms.) Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras Acked-by: Andrew Morton commit ddf5f75a16b3e7460ffee881795aa168dffcd0cf Author: Arnd Bergmann Date: Tue Jun 20 02:30:33 2006 +0200 [POWERPC] disable floating point exceptions for init Floating point exceptions should not be enabled by default, as this setting impacts the performance on some CPUs, in particular the Cell BE. Since the bits are inherited from parent processes, the place to change the default is the thread struct used for init. glibc sets this up correctly per thread in its fesetenv function, so user space should not be impacted by this setting. None of the other common libc implementations (uClibc, dietlibc, newlib, klibc) has support for fp exceptions, so they are unlikely to be hit by this either. There is a small risk that somebody wrote their own application that manually sets the fpscr bits instead of calling fesetenv, without changing the MSR bits as well. Those programs will break with this change. It probably makes sense to change glibc in the future to be more clever about FE bits, so that when running on a CPU where this is expensive, it disables exceptions ASAP, while it keeps them enabled on CPUs where running with exceptions on is cheaper than changing the state often. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 72abd54035a3d71fd8f02596e659257e8bba16ca Author: Andreas Schwab Date: Mon Jun 19 22:45:04 2006 +0200 [POWERPC] Unify ppc syscall tables Avoid duplication of the syscall table for the cell platform. Based on an idea from David Woodhouse. Signed-off-by: Andreas Schwab Acked-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 868ea0c9256b658b14603e1ad7361b81b92ccacd Author: Mark A. Greer Date: Tue Jun 20 14:15:36 2006 -0700 [POWERPC] mpic: add support for serial mode interrupts On Tue, Jun 20, 2006 at 02:01:26PM +1000, Benjamin Herrenschmidt wrote: > On Mon, 2006-06-19 at 13:08 -0700, Mark A. Greer wrote: > > MPC10x-style interrupt controllers have a serial mode that allows > > several interrupts to be clocked in through one INT signal. > > > > This patch adds the software support for that mode. > > You hard code the clock ratio... why not add a separate call to be > called after mpic_init, > something like mpic_set_serial_int(int mpic, int enable, int > clock_ratio) ? How's this? -- MPC10x-style interrupt controllers have a serial mode that allows several interrupts to be clocked in through one INT signal. This patch adds the software support for that mode. Signed-off-by: Mark A. Greer -- arch/powerpc/sysdev/mpic.c | 20 ++++++++++++++++++++ include/asm-powerpc/mpic.h | 10 ++++++++++ 2 files changed, 30 insertions(+) -- Signed-off-by: Paul Mackerras commit 0aa8d15b01881ccaab5f2fb31eef33ced97ccb5f Author: Linas Vepstas Date: Mon Jun 19 15:07:40 2006 -0500 [POWERPC] pseries: Print PCI slot location code on failure The PCI error recovery code will printk diagnostic info when a PCI error event occurs. Change the messages to include the slot location code, which is how most sysadmins will know the device. Signed-off-by: Linas Vepstas Signed-off-by: Paul Mackerras commit 379507181a1e330d4f5b0fabe61cd43eccf09763 Author: arnd@arndb.de Date: Mon Jun 19 20:33:35 2006 +0200 [POWERPC] spufs: one more fix for 64k pages The SPU context save/restore code is currently built for a 4k page size and we provide a _shipped version of it since most people don't have the spu toolchain that is needed to rebuild that code. This patch hardcodes the data structures to a 64k page alignment, which also guarantees 4k alignment but unfortunately wastes 60k of memory per SPU context that is created in the running system. We will follow up on this with another patch to reduce that overhead or maybe redo the context save/restore logic to do this part entirely different, but for now it should make experimental systems work with either page size. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit c983294872ebccd4aacf1b8dd694ac2170feadc3 Author: arnd@arndb.de Date: Mon Jun 19 20:33:34 2006 +0200 [POWERPC] spufs: fail spu_create with invalid flags At this time, all flags are invalid. Since we are planning to actually add valid flags in the future, we better check if any were passed by the user. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit ba723fe2b2facc8d45b53701fec39aa429596759 Author: Masato Noguchi Date: Mon Jun 19 20:33:33 2006 +0200 [POWERPC] spufs: clear class2 interrupt status before wakeup SPU interrupt status must be cleared before handle it. Otherwise, kernel may drop some interrupt packet. Currently, class2 interrupt treated like: 1) call callback to wake up waiting process 2) mask raised mailbox interrupt 3) clear interrupt status I changed like: 1) mask raised mailbox interrupt 2) clear interrupt status 3) call callback to wake up waiting process Clearing status before masking will make spurious interrupt. Thus, it is necessary to hold by steps I described above, I think. Signed-off-by: Masato Noguchi Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 6e18b27bd0911d4d2495c6fdeeac0c047d915300 Author: Masato Noguchi Date: Mon Jun 19 20:33:32 2006 +0200 [POWERPC] spufs: fix Makefile for "make clean" added spu_{save,restore}_dump.h to target of 'make clean' Signed-off-by: Masato Noguchi Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 2eabbbd33ec39f690005aa186c57476598edc6b3 Author: Masato Noguchi Date: Mon Jun 19 20:33:31 2006 +0200 [POWERPC] spufs: remove stop_code from struct spu This patch remove 'stop_code' -- discarded member of struct spu. It is written at initialize and interrupt, but never read in current implementation. Signed-off-by: Masato Noguchi Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit a91942ae7ebd518006dcbeb2a1d7b147253c080e Author: Geoff Levand Date: Mon Jun 19 20:33:30 2006 +0200 [POWERPC] spufs: fix spu irq affinity setting This changes the hypervisor abstraction of setting cpu affinity to a higher level to avoid platform dependent interrupt controller routines. I replaced spu_priv1_ops:spu_int_route_set() with a new routine spu_priv1_ops:spu_cpu_affinity_set(). As a by-product, this change eliminated what looked like an existing bug in the set affinity code where spu_int_route_set() mistakenly called int_stat_get(). Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 540270d82db943855538cea5d0c790e7e669dda0 Author: Geoff Levand Date: Mon Jun 19 20:33:29 2006 +0200 [POWERPC] spufs: further abstract priv1 register access To support muti-platform binaries the spu hypervisor accessor routines must have runtime binding. I removed the existing statically linked routines in spu.h and spu_priv1_mmio.c and created new accessor routines in spu_priv1.h that operate indirectly through an ops struct spu_priv1_ops. spu_priv1_mmio.c contains the instance of the accessor routines for running on raw hardware. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit c01ea72a3b8abb7baa4291a1876b82599867035a Author: Geoff Levand Date: Mon Jun 19 20:33:28 2006 +0200 [POWERPC] spufs: split the Cell BE support into generic and platform dependant parts Creates new config variables PPC_CELL_NATIVE and PPC_IBM_CELL_BLADE. The existing CONFIG_PPC_CELL is now used to denote the generic Cell processor support. PPC_CELL = make descends into platforms/cell PPC_CELL_NATIVE = add bare metal support PPC_IBM_CELL_BLADE = add blade device drivers, etc. Also renames spu_priv1.c to spu_priv1_mmio.c. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit e46a0237fda640f02bc4cb3d9702b6ee91bfd6e4 Author: arnd@arndb.de Date: Mon Jun 19 20:33:27 2006 +0200 [POWERPC] spufs: dont try to access SPE channel 1 count The save/restore sequence for SPE contexts currently attempts to save and restore the channel count for SPE channel 1 (the SPU_WriteEventMask channel. But the CBE architecture (section 9.11.2) clearly states that this channel does not have an associated count. Hardware simply ignores the attempt to write this count, but the simulator generates a warning message. WARNING: 279721590: SPE7: Attempt to write channel count for CH 1 with no associated count is ignored. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit ecec21770d87a5035cfd210cfdb22e1935b0c4a6 Author: Jeremy Kerr Date: Mon Jun 19 20:33:26 2006 +0200 [POWERPC] spufs: use kzalloc in create_spu Clean up create_spu() a little by using kzalloc instead of kmalloc + assignments. Signed-off-by: Jeremy Kerr Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 970f1baae78ff99b7536464214d4c78dde4551e2 Author: arnd@arndb.de Date: Mon Jun 19 20:33:25 2006 +0200 [POWERPC] spufs: fix initial state of wbox file The wbox channel count of an spu is now initialized to four for the saved context. This makes it possible to write to the mailbox right away without waiting for the SPE to become scheduled first. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 7b1a701480fb17b7f78b95b257bfc90a4f949d04 Author: arnd@arndb.de Date: Mon Jun 19 20:33:24 2006 +0200 [POWERPC] spufs: add a phys-id attribute to each SPU context For performance analysis, it is often interesting to know which physical SPE a thread is currently running on, and, more importantly, if it is running at all. This patch adds a simple attribute to each SPU directory with that information. The attribute is read-only and called 'phys-id'. It contains an ascii string with the number of the physical SPU (e.g. "0x5"), or alternatively the string "0xffffffff" (32 bit -1) when it is not running at all at the time that the file is read. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 724bd80e8102ac137868b23fad2b06af65f8e168 Author: arnd@arndb.de Date: Mon Jun 19 20:33:23 2006 +0200 [POWERPC] spufs: set up correct SLB entries for 64k pages spufs currently knows only 4k pages and 16M hugetlb pages. Make it use the regular methods for deciding on the SLB bits. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 0309f02d8e1b68811e513bdd06015672d0696af5 Author: Michael Ellerman Date: Mon Jun 19 20:33:22 2006 +0200 [POWERPC] spufs: fix deadlock in spu_create error path spufs_rmdir tries to acquire the spufs root i_mutex, which is already held by spufs_create_thread. This was tracked as Bug #H9512. Signed-off-by: Michael Ellerman Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit d9379c4bcee7046182edf45eeab349334421416e Author: arnd@arndb.de Date: Mon Jun 19 20:33:21 2006 +0200 [POWERPC] spufs: restore mapping of mssync register A recent change to the way that the mfc file gets mapped made it impossible to map the SPE Multi-Source Synchronization register into user space, but that may be needed by some applications. This restores the missing functionality. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 91edfa49b97f0b0fafac5c8d5f171fc183782ce6 Author: arnd@arndb.de Date: Mon Jun 19 20:33:20 2006 +0200 [POWERPC] cell: always build spu base into the kernel The spu_base module is rather deeply intermixed with the core kernel, so it makes sense to have that built-in. This will let us extend the base in the future without having to export more core symbols just for it. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 1d64093f6627a7eef1ed0fe005463f0a5ea25a5f Author: Jeremy Kerr Date: Mon Jun 19 20:33:19 2006 +0200 [POWERPC] cell: register SPUs as sysdevs SPUs are registered as system devices, exposing attributes through sysfs. Since the sysdev includes a kref, we can remove the one in struct spu (it isn't used at the moment anyway). Currently only the interrupt source and numa node attributes are added. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 0f0f90c304b42d8ce7fc5958de894bdcff3a0ca1 Author: arnd@arndb.de Date: Mon Jun 19 20:33:18 2006 +0200 [POWERPC] cell: update defconfig Enable some of the most requested features in defconfig and refresh with the latest powerpc.git Kconfig files. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit b40feec8efbe609a3a38bca1f18d3ba4d590563a Author: arnd@arndb.de Date: Mon Jun 19 20:33:17 2006 +0200 [POWERPC] cell: fix interrupt priority handling Checking the priority field to test for irq validity is completely bogus and breaks with future external interrupt controllers. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit acf7d76827a577059636e949079021e6af6dd702 Author: Benjamin Herrenschmidt Date: Mon Jun 19 20:33:16 2006 +0200 [POWERPC] cell: add RAS support This is a first version of support for the Cell BE "Reliability, Availability and Serviceability" features. It doesn't yet handle some of the RAS interrupts (the ones described in iic_is/iic_irr), I'm still working on a proper way to expose these. They are essentially a cascaded controller by themselves (sic !) though I may just handle them locally to the iic driver. I need also to sync with David Erb on the way he hooked in the performance monitor interrupt. So that's all for 2.6.17 and I'll do more work on that with my rework of the powerpc interrupt layer that I'm hacking on at the moment. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit ef82a306b46dbedaecbb154b24d05dfab937df35 Author: Jon Loeliger Date: Sat Jun 17 17:52:55 2006 -0500 [POWERPC] Add Vitesse 8244 PHY for MPC8641 HPCN platform. Signed-off-by: Kriston Carson Signed-off-by: Xianghua Xiao Signed-off-by: Jon Loeliger Acked-by: Jeff Garzik Signed-off-by: Paul Mackerras commit 2097c7f04af7fb962ab8676ed8083f350ed885f7 Author: Jon Loeliger Date: Sat Jun 17 17:52:54 2006 -0500 [POWERPC] Document I2C_MPC option for 86xx too. The same I2C driver found on 85xx, etc., can be used for 86xx too. Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit 6b543404058a5ffdca8c48e95e0b8a69bb4bdba9 Author: Jon Loeliger Date: Sat Jun 17 17:52:51 2006 -0500 [POWERPC] Add 8641 Register space and IRQ definitions. Signed-off-by: Jeff Brown Signed-off-by: Xianghua Xiao Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit b809b3e86f39651475b30ceb1caf535071534d4d Author: Jon Loeliger Date: Sat Jun 17 17:52:48 2006 -0500 [POWERPC] Add mpc8641hpcn PCI/PCI-Express platform files. Signed-off-by: Xianghua Xiao Signed-off-by: Wei Zhang Signed-off-by: Haiying Wang Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit 4ca4b6274c30d53d22014fb6974efe2b3e52cfdc Author: Jon Loeliger Date: Sat Jun 17 17:52:45 2006 -0500 [POWERPC] Add the MPC8641 HPCN platform files. Signed-off-by: Xianghua Xiao Signed-off-by: Haiying Wang Signed-off-by: Wei Zhang Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit ee0339f205d60375c5ce1653c0dc318c6ec72668 Author: Jon Loeliger Date: Sat Jun 17 17:52:44 2006 -0500 [POWERPC] Add starting of secondary 86xx CPUs. Clear the high BATS during load_up_mmu if FTR_HAS_HIGH_BATS. Allow just a bit more time for secondary CPUs to phone home. Signed-off-by: Wei Zhang Signed-off-by: Haiying Wang Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit 9674ed38d8e4a9ce15c61b4306ef803cad0e1dc0 Author: Jon Loeliger Date: Sat Jun 17 17:52:40 2006 -0500 [POWERPC] Add 8641 CPU table entry. Signed-off-by: Wei Zhang Signed-off-by: Xianghua Xiao Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit 96abe9358becb543c21121699c711897374bcbdf Author: Jon Loeliger Date: Sat Jun 17 17:52:37 2006 -0500 [POWERPC] Add mpc8641_hpcn_defconfig config file. Signed-off-by: Jon Loeliger Signed-off-by: Haiying Wang Signed-off-by: Paul Mackerras commit c9b484b5c1201321f40b04870e8b417033b6fe76 Author: Jon Loeliger Date: Sat Jun 17 17:52:35 2006 -0500 [POWERPC] Add the mpc8641 hpcn Kconfig and Makefiles. Signed-off-by: Xianghua Xiao Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit 8a30088794ff426cd3e21557db8f3d2687ac6695 Author: Jon Loeliger Date: Sat Jun 17 17:51:09 2006 -0500 [POWERPC] Prevent duplicate lmb reservations for Device Tree blob. Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit 2198c070498850c16d65c09bc587e3f5042126ef Author: Jon Loeliger Date: Sat Jun 17 17:49:42 2006 -0500 [POWERPC] Guard L3CR references with CPU_FTR_L3CR. Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit 7932f0b82ff1db35a5ed8d5825d51cafe15fa6db Author: John Rose Date: Thu Jun 15 17:32:15 2006 -0500 [POWERPC] RTAS delay, fix module build breaks Export both news RTAS delay functions, and change the scanlog module to use the new delay functions. Signed-off-by: John Rose Signed-off-by: Paul Mackerras commit 22ae813b85df7c0b0fc7c8d6f336d6a9f566ff97 Author: Brice Goglin Date: Tue Jun 20 20:03:02 2006 -0700 [PATCH] add __iowrite64_copy Introduce __iowrite64_copy. It will be used by the Myri-10G Ethernet driver to post requests to the NIC. This driver will be submitted soon. __iowrite64_copy copies to I/O memory in units of 64 bits when possible (on 64 bit architectures). It reverts to __iowrite32_copy on 32 bit architectures. Signed-off-by: Brice Goglin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 2eec0e0842ef747027eb9181d5f50d7157184d57 Author: Cedric Le Goater Date: Mon Jun 19 21:10:44 2006 -0700 [PATCH] s390: add __raw_writeq required by __iowrite64_copy It also adds all the related quad routines. Signed-off-by: Cedric Le Goater Acked-by: Heiko Carstens Cc: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds commit 6b41fd1785f4effe2f3bd40da864415812f5b8c9 Author: Linus Torvalds Date: Tue Jun 20 19:44:03 2006 -0700 Fix up CFQ scheduler for recent rbtree node shrinkage The color is now in the low bits of the parent pointer, and initializing it to 0 happens as part of the whole memset above, so just remove the unnecessary RB_CLEAR_COLOR. Signed-off-by: Linus Torvalds commit 58dfd9c16e88b9d790e7df8f2c5b03b7887db54c Author: Herbert Xu Date: Wed Jun 21 10:53:54 2006 +1000 [FORCEDETH] Fix xmit_lock/netif_tx_lock after merge There has been an update to the forcedeth driver that added a few new uses of xmit_lock which is no longer meant to be used directly. This patch replaces them with netif_tx_lock_bh. Signed-off-by: Herbert Xu Signed-off-by: Linus Torvalds commit 905f14672e6d0552bfde954d5f7adb5f2c7a7960 Author: Russell King Date: Tue Jun 20 23:27:37 2006 +0100 [ARM] Fix tosa build error tosa.c references mdelay(), but was missing linux/delay.h Signed-off-by: Russell King commit 4af6fee18822d012a15b4c9b8992e1f2793dfe0b Author: Deepak Saxena Date: Tue Jun 20 21:30:44 2006 +0100 [ARM] 3610/1: Make reboot work on Versatile Patch from Deepak Saxena This patch makes soft reboot work on the Versatile board. Thanks to Catalin Marinas @ ARM for pointing out the proper way to do this. Signed-off-by: Deepak Saxena Signed-off-by: Russell King commit 7bc3312bef4d6f220812500c0de7868fb7625a41 Author: Thomas Gleixner Date: Tue Jun 20 20:05:05 2006 +0200 [MTD] NAND: Fix breakage all over the place Following problems are addressed: - wrong status caused early break out of nand_wait() - removed the bogus status check in nand_wait() which is a relict of the abandoned support for interrupted erase. - status check moved to the correct place in read_oob - oob support for syndrom based ecc with strange layouts - use given offset in the AUTOOOB based oob operations Partially based on a patch from Vitaly Vool Thanks to Savin Zlobec for tracking down the status problem. Signed-off-by: Thomas Gleixner commit 7e4178f90eec862affc97469118d5008bd1b5bda Author: Vitaly Wool Date: Wed Jun 7 09:34:37 2006 +0400 [PATCH] NAND: fix remaining OOB length calculation In nand_read_page_syndrome/nand_write_page_syndrome the calculation of the remaining oob length which is not used by the prepad/ecc/postpad areas is wrong. Signed-off-by: Vitaly Wool Signed-off-by: Thomas Gleixner commit b6d5ee00e397b20dc88f7ffaa6f7651b71996a5c Author: Thomas Gleixner Date: Fri Jun 16 18:10:09 2006 +0200 [MTD] NAND Fixup NDFC merge brokeness Remove the remains of a broken merge. Signed-off-by: Thomas Gleixner commit ea75ee9ab8835ece099589c729574aa8aa94c0a6 Author: Russell King Date: Tue Jun 20 19:53:16 2006 +0100 [ARM] Include asm/hardware.h not asm/arch/hardware.h Signed-off-by: Russell King commit 55c20c0af7fe7d5d09af4addfafcfe3bdc500f5d Author: Andrew Victor Date: Tue Jun 20 19:31:39 2006 +0100 [ARM] 3599/1: AT91RM9200 remove global variables Patch from Andrew Victor This patch removes some now unnecessary global variables - at91_master_clock, at91_serial_map, at91_console_port. Signed-off-by: Andrew Victor Signed-off-by: Russell King commit ec57b709c3dc2e8b7643c51fc4c3fdae42b29be2 Author: Ben Dooks Date: Tue Jun 20 19:31:06 2006 +0100 [ARM] 3609/1: S3C24XX: defconfig update for s3c2410_defconfig Patch from Ben Dooks Update s3c2410_defconfig to latest kernel with the latest patches Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 5c3fddced9f62f4b175ce400bb96b23f47626e50 Author: Andrew Victor Date: Tue Jun 20 19:30:20 2006 +0100 [ARM] 3607/1: AT91RM9200 misc fixes Patch from Andrew Victor This final patch includes some general fixes. 1. Link in pm.o if CONFIG_PM is enabled. [Should have been included in patch 3605/1]. 2. Use __raw_readl()/__raw_writel() when accessing System Peripheral registers. 3. Removed some unnecessary includes Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 907d6deb625cd7ff5fea3ef4b20dfb6c1c19c3ee Author: Andrew Victor Date: Tue Jun 20 19:30:19 2006 +0100 [ARM] 3605/1: AT91RM9200 Power Management Patch from Andrew Victor This patch adds the core Power Management support for the AT91RM9200 processor. It will support suspend-to-RAM and standby modes. The suspend-to-RAM functionality is not 100% complete. The code that needs to be execute from the internal SRAM to restore the system is outstanding. For now we just fall through to Standby mode. The AT91-specific at91_suspend_entering_slow_clock() function will eventually be replaced by clk_must_disable() once that functionality is added to mainline clock API. Patch from David Brownell. Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 6902f523a328bba5af036699b1352389c0746526 Author: Andrew Victor Date: Tue Jun 20 19:30:18 2006 +0100 [ARM] 3604/1: AT91RM9200 New boards Patch from Andrew Victor This patch adds support for an additional 4 AT91RM9200-based boards: 1. Conitec ARM&EVA [MACH_CARMEVA] (http://www.conitec.net/english/linuxboard.htm) 2. KwikByte KB920x [MACH_KB9200] (http://kwikbyte.com/KB9202_description_new.htm) 3. Embest ATEB9200 [MACH_ATEB9200] (http://www.embedinfo.com/english/product/ATEB9200.asp) 4. Sperry-Sun KAFA board [MACH_KAFA] (unknown) Signed-off-by: Andrew Victor Signed-off-by: Russell King commit d6bdbb8ef3e4a9cafc747e1444b4908f9f2f548d Author: Andrew Victor Date: Tue Jun 20 19:27:34 2006 +0100 [ARM] 3603/1: AT91RM9200 remove old files Patch from Andrew Victor This patch removes the now unnecessary include/asm-arm/arch-at91rm9200/pio.h file. The pin configuration is now handled in the platform-device setup code (arch/arm/mach-at91rm9200/devices.c). Signed-off-by: Andrew Victor Signed-off-by: Russell King commit c322e24b40b83bbdfa7c269bc0105e76a39e627f Author: Liam Girdwood Date: Tue Jun 20 19:26:42 2006 +0100 [ARM] 3606/1: PXA27x SSP Register definitions Patch from Liam Girdwood This patch adds some new PXA27x SSP port registers and also fixes the SSP slots per frame macro Changes:- o SSCR0_SlotPerFrm fixed o Added SSP port TSA, RSA, TSS and ACD registers Signed-off-by: Liam Girdwood Signed-off-by: Russell King commit e6fea6a5e30efef56dee2b8455fde0811922055b Author: Lennert Buytenhek Date: Tue Jun 20 19:26:41 2006 +0100 [ARM] 3602/1: ixp23xx: fix two typos Patch from Lennert Buytenhek Fix two typos in include/asm-arm/arch-ixp23xx. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit 4faf4e0e7d4e1935fbfc5043d3ebd8d51a3d898d Author: Lennert Buytenhek Date: Tue Jun 20 19:24:07 2006 +0100 [ARM] 3600/1: increase amba-pl010 UART_NR to 8 Patch from Lennert Buytenhek The cirrus ep93xx has 3 pl010 UARTs, while amba-pl010.c only allows for 2 by default. A while ago, I think we agreed on changing the 2 to 8, but I don't see this in 2.6.17 yet. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King commit ff7512e1a2a3504649d3716a757f43807b6d26ef Author: Al Viro Date: Tue Jun 20 03:27:27 2006 -0700 [ATM]: fix broken uses of NIPQUAD in net/atm NIPQUAD expects an l-value of type __be32, _NOT_ a pointer to __be32. Signed-off-by: Al Viro Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit 8ca84481b69513f7bf341c7dd9897023a04d7d1d Author: Al Viro Date: Tue Jun 20 03:26:14 2006 -0700 [SCTP]: sctp_unpack_cookie() fix sizeof(pointer) != sizeof(array)... Signed-off-by: Al Viro Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit 41757106b9ca7867dafb2404d618f947b4786fd7 Author: Steve Grubb Date: Mon Jun 12 07:48:28 2006 -0400 [PATCH] make set_loginuid obey audit_enabled Hi, I was doing some testing and noticed that when the audit system was disabled, I was still getting messages about the loginuid being set. The following patch makes audit_set_loginuid look at in_syscall to determine if it should create an audit event. The loginuid will continue to be set as long as there is a context. Signed-off-by: Steve Grubb Signed-off-by: Al Viro commit 9c937dcc71021f2dbf78f904f03d962dd9bcc130 Author: Amy Griffis Date: Thu Jun 8 23:19:31 2006 -0400 [PATCH] log more info for directory entry change events When an audit event involves changes to a directory entry, include a PATH record for the directory itself. A few other notable changes: - fixed audit_inode_child() hooks in fsnotify_move() - removed unused flags arg from audit_inode() - added audit log routines for logging a portion of a string Here's some sample output. before patch: type=SYSCALL msg=audit(1149821605.320:26): arch=40000003 syscall=39 success=yes exit=0 a0=bf8d3c7c a1=1ff a2=804e1b8 a3=bf8d3c7c items=1 ppid=739 pid=800 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=ttyS0 comm="mkdir" exe="/bin/mkdir" subj=root:system_r:unconfined_t:s0-s0:c0.c255 type=CWD msg=audit(1149821605.320:26): cwd="/root" type=PATH msg=audit(1149821605.320:26): item=0 name="foo" parent=164068 inode=164010 dev=03:00 mode=040755 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_t:s0 after patch: type=SYSCALL msg=audit(1149822032.332:24): arch=40000003 syscall=39 success=yes exit=0 a0=bfdd9c7c a1=1ff a2=804e1b8 a3=bfdd9c7c items=2 ppid=714 pid=777 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=ttyS0 comm="mkdir" exe="/bin/mkdir" subj=root:system_r:unconfined_t:s0-s0:c0.c255 type=CWD msg=audit(1149822032.332:24): cwd="/root" type=PATH msg=audit(1149822032.332:24): item=0 name="/root" inode=164068 dev=03:00 mode=040750 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_dir_t:s0 type=PATH msg=audit(1149822032.332:24): item=1 name="foo" inode=164010 dev=03:00 mode=040755 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_t:s0 Signed-off-by: Amy Griffis Signed-off-by: Al Viro commit 6a2bceec0ea7fdc47aef9a3f2f771c201eaabe5d Author: Amy Griffis Date: Fri Jun 2 13:16:01 2006 -0400 [PATCH] fix AUDIT_FILTER_PREPEND handling Clear AUDIT_FILTER_PREPEND flag after adding rule to list. This fixes three problems when a rule is added with the -A syntax: - auditctl displays filter list as "(null)" - the rule cannot be removed using -d - a duplicate rule can be added with -a Signed-off-by: Amy Griffis Signed-off-by: Al Viro commit 0a73dccc4fd472e65887eae6fbf4afc030541709 Author: Al Viro Date: Mon Jun 5 08:15:59 2006 -0400 [PATCH] validate rule fields' types Signed-off-by: Al Viro commit f368c07d7214a7c41dfceb76c8db473b850f0229 Author: Amy Griffis Date: Fri Apr 7 16:55:56 2006 -0400 [PATCH] audit: path-based rules In this implementation, audit registers inotify watches on the parent directories of paths specified in audit rules. When audit's inotify event handler is called, it updates any affected rules based on the filesystem event. If the parent directory is renamed, removed, or its filesystem is unmounted, audit removes all rules referencing that inotify watch. To keep things simple, this implementation limits location-based auditing to the directory entries in an existing directory. Given a path-based rule for /foo/bar/passwd, the following table applies: passwd modified -- audit event logged passwd replaced -- audit event logged, rules list updated bar renamed -- rule removed foo renamed -- untracked, meaning that the rule now applies to the new location Audit users typically want to have many rules referencing filesystem objects, which can significantly impact filtering performance. This patch also adds an inode-number-based rule hash to mitigate this situation. The patch is relative to the audit git tree: http://kernel.org/git/?p=linux/kernel/git/viro/audit-current.git;a=summary and uses the inotify kernel API: http://lkml.org/lkml/2006/6/1/145 Signed-off-by: Amy Griffis Signed-off-by: Al Viro commit 20ca73bc792be9625af184cbec36e1372611d1c3 Author: George C. Wilson Date: Wed May 24 16:09:55 2006 -0500 [PATCH] Audit of POSIX Message Queue Syscalls v.2 This patch adds audit support to POSIX message queues. It applies cleanly to the lspp.b15 branch of Al Viro's git tree. There are new auxiliary data structures, and collection and emission routines in kernel/auditsc.c. New hooks in ipc/mqueue.c collect arguments from the syscalls. I tested the patch by building the examples from the POSIX MQ library tarball. Build them -lrt, not against the old MQ library in the tarball. Here's the URL: http://www.geocities.com/wronski12/posix_ipc/libmqueue-4.41.tar.gz Do auditctl -a exit,always -S for mq_open, mq_timedsend, mq_timedreceive, mq_notify, mq_getsetattr. mq_unlink has no new hooks. Please see the corresponding userspace patch to get correct output from auditd for the new record types. [fixes folded] Signed-off-by: George Wilson Signed-off-by: Al Viro commit 8ba8e0fbe6321961f6ba04e2fd7215b37d935c83 Author: Darrel Goeddel Date: Wed May 24 09:38:25 2006 -0500 [PATCH] fix se_sen audit filter Fix a broken comparison that causes the process clearance to be checked for both se_clr and se_sen audit filters. Signed-off-by: Darrel Goeddel Signed-off-by: Al Viro commit 014149cce19c5acb19014e57a5b739b7f64e6fbf Author: Al Viro Date: Tue May 23 01:36:13 2006 -0400 [PATCH] deprecate AUDIT_POSSBILE Signed-off-by: Al Viro commit d8945bb51a2bb6623cfa36b9ff63594f46d513aa Author: Al Viro Date: Thu May 18 16:01:30 2006 -0400 [PATCH] inline more audit helpers pull checks for ->audit_context into inlined wrappers Signed-off-by: Al Viro commit e0182909297da8d38a5d473ae7bee3d0324632a1 Author: Al Viro Date: Thu May 18 08:28:02 2006 -0400 [PATCH] proc_loginuid_write() uses simple_strtoul() on non-terminated array Signed-off-by: Al Viro commit ac03221a4fdda9bfdabf99bcd129847f20fc1d80 Author: Linda Knippers Date: Tue May 16 22:03:48 2006 -0400 [PATCH] update of IPC audit record cleanup The following patch addresses most of the issues with the IPC_SET_PERM records as described in: https://www.redhat.com/archives/linux-audit/2006-May/msg00010.html and addresses the comments I received on the record field names. To summarize, I made the following changes: 1. Changed sys_msgctl() and semctl_down() so that an IPC_SET_PERM record is emitted in the failure case as well as the success case. This matches the behavior in sys_shmctl(). I could simplify the code in sys_msgctl() and semctl_down() slightly but it would mean that in some error cases we could get an IPC_SET_PERM record without an IPC record and that seemed odd. 2. No change to the IPC record type, given no feedback on the backward compatibility question. 3. Removed the qbytes field from the IPC record. It wasn't being set and when audit_ipc_obj() is called from ipcperms(), the information isn't available. If we want the information in the IPC record, more extensive changes will be necessary. Since it only applies to message queues and it isn't really permission related, it doesn't seem worth it. 4. Removed the obj field from the IPC_SET_PERM record. This means that the kern_ipc_perm argument is no longer needed. 5. Removed the spaces and renamed the IPC_SET_PERM field names. Replaced iuid and igid fields with ouid and ogid in the IPC record. I tested this with the lspp.22 kernel on an x86_64 box. I believe it applies cleanly on the latest kernel. -- ljk Signed-off-by: Linda Knippers Signed-off-by: Al Viro commit 5d136a010de3bc16fe595987feb9ef8868f064c2 Author: Serge E. Hallyn Date: Thu Apr 27 16:45:14 2006 -0500 [PATCH] minor audit updates Just a few minor proposed updates. Only the last one will actually affect behavior. The rest are just misleading code. Several AUDIT_SET functions return 'old' value, but only return value <0 is checked for. So just return 0. propagate audit_set_rate_limit and audit_set_backlog_limit error values In audit_buffer_free, the audit_freelist_count was being incremented even when we discard the return buffer, so audit_freelist_count can end up wrong. This could cause the actual freelist to shrink over time, eventually threatening to degrate audit performance. Signed-off-by: Serge E. Hallyn Signed-off-by: Al Viro commit 0a3b483e83edb6aa6d3c49db70eeb6f1cd9f6c6b Author: Amy Griffis Date: Tue May 2 15:06:01 2006 -0400 [PATCH] fix audit_krule_to_{rule,data} return values Don't return -ENOMEM when callers of these functions are checking for a NULL return. Bug noticed by Serge Hallyn. Signed-off-by: Amy Griffis Signed-off-by: Al Viro commit 3c66251e573219a0532a5a07381b2f60a412d9eb Author: Al Viro Date: Sat May 6 08:26:27 2006 -0400 [PATCH] add filtering by ppid Signed-off-by: Al Viro commit f46038ff7d23ae092d61b366332c05aab8227b48 Author: Al Viro Date: Sat May 6 08:22:52 2006 -0400 [PATCH] log ppid Signed-off-by: Al Viro commit e1396065e0489f98b35021b97907ab4edbfb24e1 Author: Al Viro Date: Thu May 25 10:19:47 2006 -0400 [PATCH] collect sid of those who send signals to auditd Signed-off-by: Al Viro commit 473ae30bc7b1dda5c5791c773f95e9424ddfead9 Author: Al Viro Date: Wed Apr 26 14:04:08 2006 -0400 [PATCH] execve argument logging Signed-off-by: Al Viro commit 9044e6bca5a4a575d3c068dfccb5651a2d6a13bc Author: Al Viro Date: Mon May 22 01:09:24 2006 -0400 [PATCH] fix deadlocks in AUDIT_LIST/AUDIT_LIST_RULES We should not send a pile of replies while holding audit_netlink_mutex since we hold the same mutex when we receive commands. As the result, we can get blocked while sending and sit there holding the mutex while auditctl is unable to send the next command and get around to receiving what we'd sent. Solution: create skb and put them into a queue instead of sending; once we are done, send what we've got on the list. The former can be done synchronously while we are handling AUDIT_LIST or AUDIT_LIST_RULES; we are holding audit_netlink_mutex at that point. The latter is done asynchronously and without messing with audit_netlink_mutex. Signed-off-by: Al Viro commit bc0f3b8ebba611291fdaa2864dbffd2d29336c64 Author: Al Viro Date: Mon May 22 01:36:34 2006 -0400 [PATCH] audit_panic() is audit-internal ... no need to provide a stub; note that extern is already gone from include/linux/audit.h Signed-off-by: Al Viro commit 0edce197db00094d04c7fb147903add814c9db67 Author: Amy Griffis Date: Thu Jun 1 13:11:07 2006 -0700 [PATCH] inotify (5/5): update kernel documentation Update kernel documentation to include a description of the inotify kernel API. Signed-off-by: Amy Griffis Acked-by: Robert Love Acked-by: John McCutchan Signed-off-by: Al Viro commit 3ca10067f7f4bfa62a1b0edc84f590261fa02d75 Author: Amy Griffis Date: Thu Jun 1 13:11:05 2006 -0700 [PATCH] inotify (4/5): allow watch removal from event handler Allow callers to remove watches from their event handler via inotify_remove_watch_locked(). This functionality can be used to achieve IN_ONESHOT-like functionality for a subset of events in the mask. Signed-off-by: Amy Griffis Acked-by: Robert Love Acked-by: John McCutchan Signed-off-by: Al Viro commit a9dc971d3fdb857a2bcd6d53238125a2cd31d5f4 Author: Amy Griffis Date: Thu Jun 1 13:11:03 2006 -0700 [PATCH] inotify (3/5): add interfaces to kernel API Add inotify_init_watch() so caller can use inotify_watch refcounts before calling inotify_add_watch(). Add inotify_find_watch() to find an existing watch for an (ih,inode) pair. This is similar to inotify_find_update_watch(), but does not update the watch's mask if one is found. Add inotify_rm_watch() to remove a watch via the watch pointer instead of the watch descriptor. Signed-off-by: Amy Griffis Acked-by: Robert Love Acked-by: John McCutchan Signed-off-by: Al Viro commit 7c29772288b7026504cfe75bfd90d40fbd1574bf Author: Amy Griffis Date: Thu Jun 1 13:11:01 2006 -0700 [PATCH] inotify (2/5): add name's inode to event handler When an inotify event includes a dentry name, also include the inode associated with that name. Signed-off-by: Amy Griffis Acked-by: Robert Love Acked-by: John McCutchan Signed-off-by: Al Viro commit 2d9048e201bfb67ba21f05e647b1286b8a4a5667 Author: Amy Griffis Date: Thu Jun 1 13:10:59 2006 -0700 [PATCH] inotify (1/5): split kernel API from userspace support The following series of patches introduces a kernel API for inotify, making it possible for kernel modules to benefit from inotify's mechanism for watching inodes. With these patches, inotify will maintain for each caller a list of watches (via an embedded struct inotify_watch), where each inotify_watch is associated with a corresponding struct inode. The caller registers an event handler and specifies for which filesystem events their event handler should be called per inotify_watch. Signed-off-by: Amy Griffis Acked-by: Robert Love Acked-by: John McCutchan Signed-off-by: Al Viro commit 90204e0b7b51e9f2a6905adca12dc331128602c7 Author: Al Viro Date: Thu Jun 1 21:39:38 2006 -0400 [PATCH] remove config.h from inotify.h Signed-off-by: Al Viro commit d7a80dad2fe19a2b8c119c8e9cba605474a75a2b Author: Tejun Heo Date: Fri Jun 16 15:00:18 2006 +0900 [PATCH] libata: convert several bmdma-style controllers to new EH, take #3 Convert sata_sis, svw, uli and vsc drivers to new EH. All the drivers used to specify ATA_FLAG_SATA_RESET to tell libata to use SATA hardreset instead of SRST. This patch makes all the converted drivers use the standard bmdma error handler which uses both SRST and SATA hardreset. All the controllers should be able to perform SRST but still needs verification. If some of the controllers can't do SRST, it will be very easy to spot as it will show up during boot probing. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 40ef1d8d48e364dce689342adfdc475aa53f4808 Author: Tejun Heo Date: Fri Jun 16 15:13:53 2006 +0900 [PATCH] sata_via: convert to new EH, take #3 Convert sata_via to new EH. vt6420 used ATA_FLAG_SRST while vt6421 used ATA_FLAG_SATA_RESET. This difference seems to be an accident rather than intended. This patch makes both flavors use ata_bmdma_error_handler() which makes use of both SRST and SATA hardreset. This behavior change is intended and if it breaks anything, it should be very easy to spot. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit c5fa46e175ccd02803031ea071060cdb01521736 Author: Jeff Garzik Date: Tue Jun 20 05:08:44 2006 -0400 [libata] sata_nv: s/spin_lock_irqsave/spin_lock/ in irq handler We don't need to use the heavier spin lock in the irq handler. It's quite possible we can do this in nv_generic_interrupt() as well, but I didn't take the time to pursue that train of thought. Signed-off-by: Jeff Garzik commit 5a44efff4f8fe8139c0c4166ad5aae5f2fa5bced Author: Tejun Heo Date: Sat Jun 17 15:49:56 2006 +0900 [PATCH] sata_nv: add hotplug support Add hotplug support. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 39f8758259868a01ecad29b4379661dd3f21881f Author: Tejun Heo Date: Sat Jun 17 15:49:56 2006 +0900 [PATCH] sata_nv: convert to new EH Convert to new EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit ada364e884eb7e60ee96e84cbce07b3c90234c9d Author: Tejun Heo Date: Sat Jun 17 15:49:56 2006 +0900 [PATCH] sata_nv: better irq handlers nf2/3 and ck804 have irq status register. Implement better irq handler for those flavors of nv. This patch makes different flavors of nv controllers use different irq handlers by using separate port_info for each flavor. This change also makes following EH and hotplug updates easier to integrate. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 27e4b2745443cef67220da9a4f5f71b1c5f72442 Author: Tejun Heo Date: Sat Jun 17 15:49:55 2006 +0900 [PATCH] sata_nv: simplify constants Simplify interrupt constants and make NFORCE3 equal to NFORCE2. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit e6faf082cd75d6dcdcf89258ddf40c6855df87a1 Author: Tejun Heo Date: Sat Jun 17 15:49:55 2006 +0900 [PATCH] sata_nv: kill struct nv_host_desc and nv_host nv_host_desc and nv_host are used to discern different generations of nv controllers. Kill those. New EH/hotplug implementation will use standard port_info/ata_port_operations for that. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 638ebcc81f40b160f5e8b161e690e9b1b9503c1e Author: Tejun Heo Date: Sat Jun 17 15:49:55 2006 +0900 [PATCH] sata_nv: kill not-working hotplug code sata_nv contained hotplug code which is mainly for demonstrating how hotplug event is handled. This patch kills the demo code in prepration for real hotplug implementation. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 612eff0e3715a6faff5ba1b74873b99e036c59fe Author: Brian Haley Date: Thu Jun 15 14:36:36 2006 -0400 [PATCH] s2io: netpoll support This adds netpoll support for things like netconsole/kgdboe to the s2io 10GbE driver. Signed-off-by: Brian Haley Signed-off-by: Jeff Garzik commit 4c5eb38af2131d867842cdd09fa83a3ed77bfd26 Author: David S. Miller Date: Tue Jun 20 01:27:08 2006 -0700 [SPARC64]: Update defconfig. Signed-off-by: David S. Miller commit c8bfcd95def89cb69a04c58e1de7995d696c8760 Author: David S. Miller Date: Tue Jun 20 01:23:56 2006 -0700 [SPARC64]: Don't double-export synchronize_irq. It is done by the generic IRQ layer now. Signed-off-by: David S. Miller commit e18e2a00efc8352c131eb8d5a460149fb5776f1c Author: David S. Miller Date: Tue Jun 20 01:23:32 2006 -0700 [SPARC64]: Move over to GENERIC_HARDIRQS. This is the long overdue conversion of sparc64 over to the generic IRQ layer. The kernel image is slightly larger, but the BSS is ~60K smaller due to the reduced size of struct ino_bucket. A lot of IRQ implementation details, including ino_bucket, were moved out of asm-sparc64/irq.h and are now private to arch/sparc64/kernel/irq.c, and most of the code in irq.c totally disappeared. One thing that's different at the moment is IRQ distribution, we do it at enable_irq() time. If the cpu mask is ALL then we round-robin using a global rotating cpu counter, else we pick the first cpu in the mask to support single cpu targetting. This is similar to what powerpc's XICS IRQ support code does. This works fine on my UP SB1000, and the SMP build goes fine and runs on that machine, but lots of testing on different setups is needed. Signed-off-by: David S. Miller commit 8047e247c899f80c33a23ad7e9e250224f0d26a5 Author: David S. Miller Date: Tue Jun 20 01:22:35 2006 -0700 [SPARC64]: Virtualize IRQ numbers. Inspired by PowerPC XICS interrupt support code. All IRQs are virtualized in order to keep NR_IRQS from needing to be too large. Interrupts on sparc64 are arbitrary 11-bit values, but we don't need to define NR_IRQS to 2048 if we virtualize the IRQs. As PCI and SBUS controller drivers build device IRQs, we divy out virtual IRQ numbers incrementally starting at 1. Zero is a special virtual IRQ used for the timer interrupt. So device drivers all see virtual IRQs, and all the normal interfaces such as request_irq(), enable_irq(), etc. translate that into a real IRQ number in order to configure the IRQ. At this point knowledge of the struct ino_bucket is almost entirely contained within arch/sparc64/kernel/irq.c There are a few small bits in the PCI controller drivers that need to be swept away before we can remove ino_bucket's definition out of asm-sparc64/irq.h and privately into kernel/irq.c Signed-off-by: David S. Miller commit 37cdcd9e82108f9b899f1631f66ade2e45738a6e Author: David S. Miller Date: Tue Jun 20 01:21:57 2006 -0700 [SPARC64]: Kill ino_bucket->pil And reuse that struct member for virt_irq, which will be used in future changesets for the implementation of mapping between real and virtual IRQ numbers. This nicely kills off a ton of SBUS and PCI controller PIL assignment code which is no longer necessary. Signed-off-by: David S. Miller commit c6387a48cf5958e43c201fc27a158c328927531a Author: David S. Miller Date: Tue Jun 20 01:21:29 2006 -0700 [SPARC]: Kill __irq_itoa(). This ugly hack was long overdue to die. It was a way to print out Sparc interrupts in a more freindly format, since IRQ numbers were arbitrary opaque 32-bit integers which vectored into PIL levels. These 32-bit integers were not necessarily in the 0-->NR_IRQS range, but the PILs they vectored to were. The idea now is that we will increase NR_IRQS a little bit and use a virtual<-->real IRQ number mapping scheme similar to PowerPC. That makes this IRQ printing hack irrelevant, and furthermore only a handful of drivers actually used __irq_itoa() making it even less useful. Signed-off-by: David S. Miller commit 6a76267f0e52d920e6bb6da75541e6116d7304da Author: David S. Miller Date: Tue Jun 20 01:20:30 2006 -0700 [SPARC64]: bp->pil can never be zero Only pil0_dummy_bucket had a pil of zero and we just killed that off, so we can delete all special case code that used bp->pil==0 as a way to identify a dummy bucket. Signed-off-by: David S. Miller commit fd0504c3217d6d1bc8f33f53fb536299cae8feda Author: David S. Miller Date: Tue Jun 20 01:20:00 2006 -0700 [SPARC64]: Send all device interrupts via one PIL. This is the first in a series of cleanups that will hopefully allow a seamless attempt at using the generic IRQ handling infrastructure in the Linux kernel. Define PIL_DEVICE_IRQ and vector all device interrupts through there. Get rid of the ugly pil0_dummy_{bucket,desc}, instead vector the timer interrupt directly to a specific handler since the timer interrupt is the only event that will be signaled on PIL 14. The irq_worklist is now in the per-cpu trap_block[]. Signed-off-by: David S. Miller commit 3185d4d2873a46ca1620d784013f285522091aa0 Author: Bob Breuer Date: Tue Jun 20 00:36:56 2006 -0700 [SPARC]: Fix iommu_flush_iotlb end address Fix the calculation of the end address when flushing iotlb entries to ram. This bug has been a cause of esp dma errors, and it affects HyperSPARC systems much worse than SuperSPARC systems. Signed-off-by: Bob Breuer Signed-off-by: David S. Miller commit 92d452f0eb10774fb7779abf876baf9dfb295e6f Author: Bob Breuer Date: Tue Jun 20 00:36:10 2006 -0700 [SPARC]: Mark smp init functions as cpuinit Fix the smp related section mismatch warnings by marking the smp init functions as cpuinit. Signed-off-by: Bob Breuer Signed-off-by: David S. Miller commit 61fc12d8e5c94176e7c2e04a2eab4c6e36d8dd41 Author: Bob Breuer Date: Tue Jun 20 00:35:13 2006 -0700 [SPARC]: Add missing rw can_lock macros Fix a link failure by adding the missing can_lock macros for the rw locks. Signed-off-by: Bob Breuer Signed-off-by: David S. Miller commit 7202fb496af235506a3c6fea836fe4c9957f730e Author: Bob Breuer Date: Tue Jun 20 00:30:31 2006 -0700 [SPARC]: Setup cpu_possible_map Setup cpu_possible_map so the secondary cpus will get started. Signed-off-by: Bob Breuer Signed-off-by: David S. Miller commit a8cbdcea341ac2f404ee81aa1c19d54aaa0416b4 Author: Bob Breuer Date: Tue Jun 20 00:28:33 2006 -0700 [SPARC]: Add topology_init() Fix a crash in SMP mode by adding the missing topology_init. Also makes /proc/cpuinfo backwards compatible with 2.4. Signed-off-by: Bob Breuer Signed-off-by: David S. Miller commit 65fd28f743be6e3e3fd8eefa9a517656636fee42 Author: David S. Miller Date: Tue Jun 20 00:07:52 2006 -0700 [SCTP]: Fix unintentional change to SCTP_ASSERT when !SCTP_DEBUG A local debugging change slipped into a previous changeset. When SCTP_DEBUG is off SCTP_ASSERT should do nothing. Signed-off-by: David S. Miller commit 48d83325b61043e3bbd24dd37b9fe433744cf330 Author: Herbert Xu Date: Mon Jun 19 23:57:59 2006 -0700 [NET]: Prevent multiple qdisc runs Having two or more qdisc_run's contend against each other is bad because it can induce packet reordering if the packets have to be requeued. It appears that this is an unintended consequence of relinquinshing the queue lock while transmitting. That in turn is needed for devices that spend a lot of time in their transmit routine. There are no advantages to be had as devices with queues are inherently single-threaded (the loopback device is not but then it doesn't have a queue). Even if you were to add a queue to a parallel virtual device (e.g., bolt a tbf filter in front of an ipip tunnel device), you would still want to process the queue in sequence to ensure that the packets are ordered correctly. The solution here is to steal a bit from net_device to prevent this. BTW, as qdisc_restart is no longer used by anyone as a module inside the kernel (IIRC it used to with netif_wake_queue), I have not exported the new __qdisc_run function. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit d6cc7f1a3b33c89c91b3dfce1ff053178893470e Author: Evgeniy Polyakov Date: Mon Jun 19 23:42:53 2006 -0700 [CONNECTOR]: Initialize subsystem earlier. Attached patch declares connector init function as subsys_init() and returns -EAGAIN in case connector is not initialized yet. Signed-off-by: Evgeniy Polyakov Signed-off-by: David S. Miller commit d3dcd4efe2ad1ad1865b2fe5c863c1ebd9482a84 Author: Patrick McHardy Date: Mon Jun 19 23:39:45 2006 -0700 [NETFILTER]: xt_sctp: fix endless loop caused by 0 chunk length Fix endless loop in the SCTP match similar to those already fixed in the SCTP conntrack helper (was CVE-2006-1527). Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 6cad647da228486f36a9794137ad459e39b02590 Author: Langsdorf, Mark Date: Thu Jun 8 10:33:19 2006 -0500 [CPUFREQ] correct powernow-k8 fid/vid masks for extended parts The fid/vid masks for parts using the extended parts are slightly incorrect and can result in incorrect fid/vid codes being applied. No instances of this problem have been reported in the field but it could be a problem with future parts. Signed-off-by: Mark Langsdorf Signed-off-by: Dave Jones commit e7bdd7a531320eb4a4a8160afbe0c7cc98ac7187 Author: Langsdorf, Mark Date: Thu Jun 8 10:30:17 2006 -0500 [CPUFREQ] Clarify powernow-k8 cpu_family statements This patch clarifies the meaning of the cpu_family if statements in the hw pstate driver patch for powernow-k8 Signed-off-by: Mark Langsdorf Signed-off-by: Dave Jones commit d8ce75324135ea7100124c1fff4ec5090a350607 Author: Nathan Scott Date: Tue Jun 20 14:53:51 2006 +1000 [XFS] Remove files from the build that are now unused. Signed-off-by: Nathan Scott commit d7b849da47a59d2be6d6aea1effb0efa91c30424 Author: Nathan Scott Date: Tue Jun 20 14:01:29 2006 +1000 [XFS] Fix a Makefile issue related to exports.o handling. Signed-off-by: Nathan Scott commit f6c2d1fa6310a71b1c2e05fc6d9ff9b91489fa0e Author: Nathan Scott Date: Tue Jun 20 13:04:51 2006 +1000 [XFS] Remove version 1 directory code. Never functioned on Linux, just pure bloat. SGI-PV: 952969 SGI-Modid: xfs-linux-melb:xfs-kern:26251a Signed-off-by: Nathan Scott commit da2f4d679c8070ba5b6a920281e495917b293aa0 Author: Nathan Scott Date: Tue Jun 20 13:01:38 2006 +1000 [XFS] Map EFSCORRUPTED to an actual error code, not just a made up one (990). Turns out some ye-olde unices used EUCLEAN as Filesystem-needs-cleaning, so now we use that too. SGI-PV: 953954 SGI-Modid: xfs-linux-melb:xfs-kern:26286a Signed-off-by: Nathan Scott commit 557240b48e2dc4f6fa878afc3fc767ad745ca7ed Author: Linus Torvalds Date: Mon Jun 19 18:16:01 2006 -0700 Add support for suspending and resuming the whole console subsystem Trying to suspend/resume with console messages flying all around is doomed to failure, when the devices that the messages are trying to go to are being shut down. Signed-off-by: Linus Torvalds commit 5603509137940f4cbc577281cee62110d4097b1b Author: Linus Torvalds Date: Mon Jun 19 18:05:09 2006 -0700 Make sure to re-enable SCI after an ACPI suspend According to the ACPI spec, it should be enabled on return from suspend, but bugs happen. Apparently especially on the Apple Intel Macs. Signed-off-by: Linus Torvalds commit 1cca0ebbb74298958dae1d1d3e7e9287c98a720c Author: Linus Torvalds Date: Mon Jun 19 18:01:27 2006 -0700 Improve SATA core suspend/resume Doing a full ata_busy_sleep() seems to get suspend and resume working fine on the Apple Mac Mini, at least. Signed-off-by: Linus Torvalds commit 67d59dfdeb21df2c16dcd478b66177e91178ecd0 Author: James Bottomley Date: Tue Jun 13 21:31:19 2006 -0500 [SCSI] 53c700: remove reliance on deprecated cmnd fields This one's quite tricky. The 53c700 uses the now deprecated fields of the command structure for saving the prior command when it does autosense. To fix this, we have to add extra fields to the LUN to accommodate a copy of the real command. Signed-off-by: James Bottomley commit 6db874fbdbedba5e15e76cc03b42f52ea70338c0 Author: James Bottomley Date: Tue Jun 13 21:40:34 2006 -0500 [SCSI] hptiop: don't use cmnd->bufflen use cmnd->request_bufflen instead. Signed-off-by: James Bottomley commit 4f2ddba39a550eba9233d9f0e8309092da0ba293 Author: HighPoint Linux Team Date: Wed Jun 14 16:50:57 2006 +0800 [SCSI] hptiop: HighPoint RocketRAID 3xxx controller driver Updates: - don't bypass SYNCHRONIZE_CACHE command - return SCSI_MLQUEUE_HOST_BUSY when no free request slots - move scsi_remove_host() to the begin of hpt_remove(), or it will not work after resources being released. Signed-off-by: HighPoint Linux Team Signed-off-by: James Bottomley commit a623e14dafe72329dd1defe36ee2cd4ff4b2e6f1 Author: Mark Haverkamp Date: Thu Jun 8 13:55:57 2006 -0700 [SCSI] aacraid: small misc. cleanups Received from Mark Salyzyn Spelling correction, orphaned comment removal & update branch name. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley commit 75c3628db75c573870379094a5f90f690ee99b76 Author: Mark Haverkamp Date: Thu Jun 8 13:55:42 2006 -0700 [SCSI] aacraid: Update supported product information Received From Mark Salyzyn Some of the cards product names changed. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley commit 9c64f9774805ba5d5ad4129899bdd822f61874e9 Author: Jan Beulich Date: Tue May 9 00:50:31 2006 -0700 [PATCH] PCI Hotplug: Fix recovery path from errors during pcie_init() Signed-off-by: Jan Beulich Cc: Kristen Accardi Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman commit 9df7fde52c33075b9f9148ee31215c03824fcc38 Author: Eric Sesterhenn Date: Thu Jun 1 11:41:44 2006 +0200 [PATCH] PCI Hotplug: fake NULL pointer dereferences in IBM Hot Plug Controller Driver Remove checks for value, since the hotplug core always provides a valid value. Signed-off-by: Eric Sesterhenn Signed-off-by: Greg Kroah-Hartman commit 99ff124d1673a1e3f19061ebc82634608d1119ed Author: Kenji Kaneshige Date: Fri May 12 11:13:50 2006 +0900 [PATCH] shpchp: Cleanup improper info messages Current SHPCHP driver shows device number of slots in info messages, but it is useless and should be replaced with slot name. This patch replaces the device number shown in the info messages with the slot name. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit ea83bc1dabdca9da643972b591259a7657459ff5 Author: Kenji Kaneshige Date: Fri May 12 11:12:23 2006 +0900 [PATCH] shpchp: Remove Unused hpc_evelnt_lock This patch removes unused hpc_event_lock. This patch has no functional change. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit f42639572680f4d69d9522f91c65e793ebeca098 Author: Kenji Kaneshige Date: Fri May 12 11:13:02 2006 +0900 [PATCH] shpchp: Cleanup interrupt polling timer This patch cleans up the interrupt polling timer code in shpchp_hpc.c. This has no functional changes. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 4085399da3c2176ba8ed64e93a2722907d41df3f Author: Kenji Kaneshige Date: Fri May 12 11:11:48 2006 +0900 [PATCH] shpchp: Cleanup SHPC commands This patch cleans up the code related to issuing SHPC commands. This patch has no functional changes. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit c4cecc1937cafd8505151452a9f7eea876a5bd9c Author: Kenji Kaneshige Date: Fri May 12 11:10:56 2006 +0900 [PATCH] shpchp: Cleanup interrupt handler This patch cleans up the interrupt handler of shpchp driver. This patch has no functional changes. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit d4fbf600666569c3921d12bdcfcfdb2cdb4fd5fb Author: Kenji Kaneshige Date: Fri May 12 11:05:59 2006 +0900 [PATCH] shpchp: Remove unnecessary hpc_ctlr_handle check This patch removes unnecessary error check for hpc_ctlr_handle. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 132066a9c84af6f5e8d893145a9c63f849143867 Author: Kenji Kaneshige Date: Fri May 12 13:39:45 2006 +0900 [PATCH] pciehp: Implement get_address callback This patch implements .get_address callback of hotplug_slot_ops for PCIEHP driver. With this patch, we can see bus address of hotplug slots as follows: # cat /sys/bus/pci/slots/0010_0000/address 0000:0a:00 Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 6e33706b191ff8687f103a86de842b690fd8fb9d Author: Kenji Kaneshige Date: Fri May 12 11:23:39 2006 +0900 [PATCH] pciehp: Add missing pci_dev_put The PCIEHP driver leaks reference counter of pci_dev structures. This patch adds missing pci_dev_put() calls to PCIEHP driver. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 56bfada3e1a25c0da6f4590a4b04c67ec10910c2 Author: Kenji Kaneshige Date: Fri May 12 11:22:24 2006 +0900 [PATCH] pciehp: Replace pci_find_slot() with pci_get_slot() This patch replaces pci_find_slot() with pci_get_slot() in PCIEHP driver. This patch enables PCI Express Hotplug on the system which has multiple PCI domains. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 466ee36b62b4b294ecf68a2eee2e18c6ff8c9be4 Author: Mike Habeck Date: Sat May 6 09:01:59 2006 -0500 [PATCH] SGI Hotplug: Incorrect power status This is a repost of a patch submitted by Prarit Bhargava on 01-19-06 that never got integrated. The get_power_status function is currently reporting a bitwise mapping of the slot if the slot is powered on. It should return 1 if powered on and 0 if powered off. Signed-off-by: Mike Habeck Signed-off-by: Greg Kroah-Hartman commit 82d5f4aaf182c306d2c2ef4d3a89d0fb8e386aa8 Author: Kenji Kaneshige Date: Wed May 3 23:42:04 2006 +0900 [PATCH] shpchp: Create shpchpd at controller probe time The workqueue thread of shpchp driver should be created only when SHPC based hotplug slots are detected on the system. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit d49f2c49c39bbd0cb2069fe11c1630c709061037 Author: Kenji Kaneshige Date: Wed May 3 23:34:17 2006 +0900 [PATCH] shpchp: Mask Global SERR and Intr at controller release time Global SERR and Interrupt should be masked at shpchp driver unload time. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit e7138723692e43b7d43578746ad21bf194847527 Author: Kenji Kaneshige Date: Tue May 2 11:12:37 2006 +0900 [PATCH] SHPC: Fix SHPC Contoller SERR-INT Register bits access Current SHPCHP driver doesn't take care of RsvdP/RsvdZ[*] bits in controller SERR-INT register. This might cause unpredicable results. This patch fixes this bug. [*] RsvdP and RsvdZ are defined in SHPC spec as follows: RsvdP - Reserved and Preserved. Register bits of this type are reserved for future use as R/W bits. The value read is undefined. Writes are ignored. Software must follow These rules when accessing RsvdP bits: - Software must ignore RsvdP bits when testing values read from these registers. - Software must not depend on RsvdP bit's ability to retain information when written - Software must always write back the value read in the RsvdP bits when writing one of these registers. RsvdZ - Reserved and Zero. Register bits of this type are reserved for future use as R/WC bits. The value read is undefined. Writes are ignored. Software must follow these rules when accessing RsvdZ bits: - Software must ignore RsvdZ bits when testing values read from these registers. - Software must not depends on a RsvdZ bit's ability to retain information when written. - Software must always write 0 to RsvdZ bits when writing one of these register. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 795eb5c4a73bee30e8c2dbb29174b329da56051c Author: Kenji Kaneshige Date: Tue May 2 11:11:54 2006 +0900 [PATCH] SHPC: Fix SHPC Logical Slot Register bits access Current SHPCHP driver doesn't take care of RsvdP/RsvdZ[*] bits in logical slot registers. This might cause unpredicable results. This patch fixes this bug. [*] RsvdP and RsvdZ are defined in SHPC spec as follows: RsvdP - Reserved and Preserved. Register bits of this type are reserved for future use as R/W bits. The value read is undefined. Writes are ignored. Software must follow These rules when accessing RsvdP bits: - Software must ignore RsvdP bits when testing values read from these registers. - Software must not depend on RsvdP bit's ability to retain information when written - Software must always write back the value read in the RsvdP bits when writing one of these registers. RsvdZ - Reserved and Zero. Register bits of this type are reserved for future use as R/WC bits. The value read is undefined. Writes are ignored. Software must follow these rules when accessing RsvdZ bits: - Software must ignore RsvdZ bits when testing values read from these registers. - Software must not depends on a RsvdZ bit's ability to retain information when written. - Software must always write 0 to RsvdZ bits when writing one of these register. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 5858759c2098c6792af1afa6d5ded94044740f9c Author: Kenji Kaneshige Date: Tue May 2 11:10:37 2006 +0900 [PATCH] SHPC: Cleanup SHPC Logical Slot Register bits access This patch cleans up the code to access bits in slot logical registers. This patch has no functional change. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 2b34da7e61383b4b7773d2d4e776e58725794347 Author: Kenji Kaneshige Date: Tue May 2 11:09:42 2006 +0900 [PATCH] SHPC: Cleanup SHPC Logical Slot Register access This patch cleans up the code to access slot logical registers. This patch has no functional changes. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 75d97c59a192ca0fe2577974dac0c16a73a377eb Author: Kenji Kaneshige Date: Tue May 2 11:08:42 2006 +0900 [PATCH] SHPC: Cleanup SHPC register access This patch cleans up the code to access SHPC working register sets. This patch has no functional changes. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 40abb96c51bbcb06785e233e96f40c35657ade83 Author: Kenji Kaneshige Date: Mon May 8 18:34:09 2006 +0900 [PATCH] pciehp: Fix programming hotplug parameters Current PCHEHP driver doesn't have any code to program hotplug parameters from firmware. So hotplug parameters are never programed at hot-add time. This patch add support for programming hotplug parameters to PCIEHP driver. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit e22b73501608901bab7ee9b1f8cb67f15e8efb7a Author: Kenji Kaneshige Date: Tue May 2 10:57:14 2006 +0900 [PATCH] acpi_pcihp: Add support for _HPX This patch adds support for _HPX (Hot Plug Parameter Extensions) defined in ACPI3.0a spec. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit aad20cabaa3d6dfa1e0ebc8fb0537a96d3518b8f Author: Kenji Kaneshige Date: Wed May 10 22:20:34 2006 +0900 [PATCH] acpi_pcihp: Remove improper error message about OSHP This patch converts the improper error message about OSHP evaluation to debug message which is displayed only when pci_hotplug.ko is loaded with debugging mode enabled. To do this, this patch adds a new module parameter "debug_acpi" to pci_hotplug.ko for enabling/disabling debug messages in acpi_pcihp.c. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 7430e34c70106a9576fc61d77604d164b187a1b7 Author: Kenji Kaneshige Date: Tue May 2 10:54:50 2006 +0900 [PATCH] acpi_pcihp: Fix programming _HPP values This patch fixes the problem that hotplug parameters are not programed when PCI cards are hot-added by ACPIPHP, SHPCHP and PCIEHP driver. The pci_dev structure being hot-added is not bound to ACPI handle, so we need to trace PCI bus tree to find ACPI handle. Signed-off-by: Kenji Kaneshige Cc: Kristen Accardi Signed-off-by: Greg Kroah-Hartman commit 2433ee2654f0ac86f7886e5a8d01bee7f3c7c6db Author: Kristen Accardi Date: Mon Apr 24 15:50:59 2006 -0700 [PATCH] pciehp: dont call pci_enable_dev Don't call pci_enable_device from pciehp because the pcie port service driver already does this. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman commit 81b26bcacd5df0f65344fb430b1bf7fe9cfbfe2a Author: Kristen Accardi Date: Tue Apr 18 14:36:43 2006 -0700 [PATCH] PCI Hotplug: don't use acpi_os_free acpi_os_free should not be used by drivers outside of acpi/*/*.c. Replace with kfree(). Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman commit cde0e5d722c77d1194f40de54a99c90afe365480 Author: MUNEDA Takahiro Date: Wed Mar 22 14:49:33 2006 +0900 [PATCH] acpiphp: turn off slot power at error case When acpiphp_enable_slot() is failed, acpiphp does not change the slot->flags. Therefore, when user tries to read power status, acpiphp_get_power_status() returns the enable status whether the slot is not really enabled. This patch fixes this BUG. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman commit c14424736e76f3d8477a41de531e6b5dcce3d5b0 Author: MUNEDA Takahiro Date: Wed Mar 22 14:49:27 2006 +0900 [PATCH] acpiphp: host and p2p hotplug I encountered the problem that when there are some hotplug slots are under the host bridge, the hotplug slots under the p2p bridge are not treated as hotpluggable. This patch fixes this BUG. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman commit 551bcb75b3d9f23348a524210ccfff26d865e425 Author: MUNEDA Takahiro Date: Wed Mar 22 14:49:20 2006 +0900 [PATCH] acpiphp: hotplug slot hotplug o hotplug slots add When the hot-added PCI device is p2p bridge, acpiphp calls find_p2p_bridge() to add hotplug slots. o hotplug slots remove When the hot-removing PCI device is p2p bridge, acpiphp calls cleanup_p2p_bridge() to remove hotplug slots. o notify handler exchange When the p2p bridge is added, acpiphp changes the notify hanlder. If no bridge device is inserted into the hotpluggable PCI slot, acpiphp installs the notify handler for function. After the p2p bridge hot-add, acpiphp has to install the notify handler for bridge. Because, the role of the handlers are not same. The hot-remove case is ditto. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman commit 92c9be95549632da09088320f202fa5c05b21ddf Author: MUNEDA Takahiro Date: Wed Mar 22 14:49:09 2006 +0900 [PATCH] acpiphp: configure _PRT - V3 Current acpiphp does not free acpi_device structs when the PCI devices are removed. When the PCI device is added, acpi_bus_add() fails because acpi_device struct has already exists. So, _PRT method does not evaluate. This patch fixes this issue. Signed-off-by: MUNEDA Takahiro Signed-off-by: Greg Kroah-Hartman commit e55dea58c5609aece6156a6cd2306b820a7794ef Author: Prarit Bhargava Date: Tue Apr 4 09:26:46 2006 -0400 [PATCH] PCI Hotplug: Tollhouse HP: SGI hotplug driver changes SGI hotplug driver changes required to support Tollhouse system PCI hotplug, and implements the PRF_HOTPLUG_SUPPORT feature bit. Signed-off-by: Prarit Bhargava Signed-off-by: Greg Kroah-Hartman commit faed568413e89f87cd60aa8b292cc4b9996bae42 Author: Richard Purdie Date: Mon Jun 19 20:46:05 2006 +0100 [ARM] 3594/1: Poodle: Add touchscreen support + other updates Patch from Richard Purdie Poodle Updates: * Update corgi_ssp to make the GPIO chip selects optional * Enable corgi_ssp for use by poodle * Add corgi touchscreen platform device for poodle * Export locomo platform device. * Set framebuffer device parent correctly Signed-off-by: Richard Purdie Signed-off-by: Russell King commit f8703dc8cb10eca7f6fe6ef364d8e106fe07f034 Author: Richard Purdie Date: Mon Jun 19 19:58:52 2006 +0100 [ARM] 3564/1: sharpsl_pm: Abstract some machine specific parameters Patch from Richard Purdie Abstract some machine specific parameters from the sharpsl_pm core into the machine specific drivers. This allows the core to support tosa/poodle. Signed-off-by: Richard Purdie Signed-off-by: Russell King commit 88660351cb6daa85baf9700f12dff3af564dc14a Author: Richard Purdie Date: Mon Jun 19 19:58:51 2006 +0100 [ARM] 3561/1: Poodle: Correct the MMC/SD power control Patch from Richard Purdie Correct the Poodle power control for the MMC/SD port. Also add write protection switch support. Signed-off-by: Richard Purdie Signed-off-by: Russell King commit 74617fb6b825ea370ae72565f7543306bc08ef6e Author: Richard Purdie Date: Mon Jun 19 19:57:12 2006 +0100 [ARM] 3593/1: Add reboot and shutdown handlers for Zaurus handhelds Patch from Richard Purdie Add functionality to allow machine specific reboot handlers on ARM. Add machine specific reboot and poweroff handlers for all PXA Zaurus models. Signed-off-by: Richard Purdie Signed-off-by: Russell King commit afefc4158f3c8529e4bb99c1dc119fd792bac220 Author: Andrew Victor Date: Mon Jun 19 19:53:19 2006 +0100 [ARM] 3592/1: AT91RM9200 Serial driver update Patch from Andrew Victor This patch includes a number of updates to the AT91RM9200 serial driver. Changes include: 1. Conversion to a platform_driver. [Ivan Kokshaysky] 2. Replaced all references to AT91RM9200 with AT91. This driver can now also be used for the AT91SAM9216. 3. Allow TIOCM_LOOP to configure local loopback mode. 4. Cleaned up the 'read_status_mask' usage and interrupt handler code. [Chip Coldwell] 5. Suspend/resume support. [David Brownell] There are a few 'unused variable' warning when compiling this - I removed the new DMA support to keep this first patch simpler. Signed-off-by: Andrew Victor Signed-off-by: Russell King commit bf1c56a3aaa67ac74bc74e631ecc2a2673597cae Author: Ben Dooks Date: Mon Jun 19 18:30:04 2006 +0100 [ARM] 3591/1: Anubis: IDE device definitions Patch from Ben Dooks Platform device definitions for the two IDE ports on the Simtec Anubis board. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 82dc0772a892f8b430a2d567c981fe47a11489c3 Author: Andrew Victor Date: Mon Jun 19 18:16:46 2006 +0100 [ARM] 3590/1: AT91RM9200 Platform devices support Patch from Andrew Victor This patch includes the structures and exported functions required for the platform-device support (added in patch 3585/1). Also adds the arch_identify() function for run-time detection of which AT91 processor the code is running on. [Original patch from Ivan Kokshaysky] Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 067bbada4cc574eaa4fa577483ecae4012049477 Author: Andrew Victor Date: Mon Jun 19 18:16:45 2006 +0100 [ARM] 3589/1: AT91RM9200 DK/EK board update Patch from Andrew Victor This patch updates the support for the Atmel DK and EK boards. The changes include: 1. Use the new at91_uart_config structure and device registration functions for the UARTs. 2. Registration of I2C and SPI platform devices. 3. The USB Device pullup line is connected to reset, so multidrive needs to be enabled on the line. [Patch from David Brownell]. Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 1723b4a34af85447684c9696af83929d2c1e8e6b Author: Atsushi Nemoto Date: Tue Jun 20 00:19:13 2006 +0900 [MIPS] Make timer interrupt frequency configurable from kconfig. Make HZ configurable. DECSTATION can select 128/256/1024 HZ, JAZZ can only select 100 HZ, others can select 100/128/250/256/1000/1024 HZ if not explicitly specified). Also remove all mach-xxx/param.h files and update all defconfigs according to current HZ value. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle commit b97b36bfd761d83f714eb1b5d6bce519794fa650 Author: Kumba Date: Sun Jun 18 02:17:08 2006 -0400 [MIPS] Correct HAL2 Kconfig description The current HAL2 Kconfig description indicates it is only used on SGI Indy systems, however all members of the Indigo2 Family have this sound card as well. Plus a minor grammatical fix is included. Signed-off-by: Joshua Kinard Signed-off-by: Ralf Baechle commit c3b1c2de2254aa4721e7e3c8d418fa9302e6acb0 Author: Kumba Date: Sun Jun 18 02:17:01 2006 -0400 [MIPS] Fix R4K cache macro names Several machines have the R4K cache macro name spelled incorrectly. Namely, they have cpu_has_4kcache defined instead of cpu_has_4k_cache. Signed-off-by: Joshua Kinard Signed-off-by: Ralf Baechle commit 2493921c284813b9f512c95d972a302cf82296cb Author: Kumba Date: Sun Jun 18 02:16:53 2006 -0400 [MIPS] Add Missing R4K Cache Macros to IP27 & IP32 Keeping in accordance with other machines, IP27 and IP32 lack a few macros. IP27 lacks cpu_has_4kex & cpu_has_4k_cache macros while IP32 lacks just the cpu_has_4k_cache macro. Signed-off-by: Joshua Kinard Signed-off-by: Ralf Baechle commit 35189fad3cb5f6e3ab66c8321928a851de0cd2b1 Author: Ralf Baechle Date: Sun Jun 18 16:39:46 2006 +0100 [MIPS] Support for the RM9000-based Basler eXcite smart camera platform. Signed-off-by: Thomas Koeller Signed-off-by: Ralf Baechle commit 355c471f2ff324c21f8a1fb8e2e242a0f2a4aa68 Author: dmitry pervushin Date: Sun May 21 14:53:06 2006 +0400 [MIPS] Support for the R5500-based NEC EMMA2RH Mark-eins board Signed-off-by: dmitry pervushin Signed-off-by: Ralf Baechle commit 4a0312fca6599299bbed944ce09278d90388a3e5 Author: Thomas Bogendoerfer Date: Tue Jun 13 13:59:01 2006 +0200 [MIPS] Support SNI RM200C SNI in big endian mode and R5000 processors. Added support for RM200C machines with big endian firmware Added support for RM200-C40 (R5000 support) Signed-off-by: Florian Lohoff Signed-off-by: Thomas Bogendoerfer Signed-off-by: Ralf Baechle commit b00f473e1af9a11454e572de1ea446eb672e700d Author: Ralf Baechle Date: Sat Jun 17 10:56:26 2006 +0100 [MIPS] SN: include asm/sn/types.h for nasid_t. Signed-off-by: Ralf Baechle commit 4fb60a4b80f9db94605c2a47807d34dfb9ae44c8 Author: Thiemo Seufer Date: Sun Jun 18 05:23:47 2006 +0100 [MIPS] Random fixes for sb1250 Random improvements for sb1250: Silence compiler warnings, a bugfix for the profiling code, and a comment typo. Signed-off-by: Thiemo Seufer Signed-off-by: Ralf Baechle commit b75d4c1d686aff4f8f9ea96b2e8908a3454a3ff3 Author: Thiemo Seufer Date: Sun Jun 18 05:17:54 2006 +0100 [MIPS] Fix bcm1480 compile Fix compilation for bcm1480, a hpt is only available on sb1250/bcm112x. Signed-off-by: Thiemo Seufer Signed-off-by: Ralf Baechle commit 470b160364db5b8096b8e557a23c97eb6612be67 Author: Ralf Baechle Date: Sun Jun 18 05:28:38 2006 +0100 [MIPS] Remove support for NEC DDB5476. As warned several times before. Signed-off-by: Ralf Baechle commit eaff3888742155bd397e45a1c3323c0173042e5b Author: Ralf Baechle Date: Sun Jun 18 04:58:57 2006 +0100 [MIPS] Remove support for NEC DDB5074. As warned several times before. Signed-off-by: Ralf Baechle commit 2925aba4223f4532e85f0c6f64584b3e0b2849c3 Author: Ralf Baechle Date: Sun Jun 18 01:32:22 2006 +0100 [MIPS] Cleanup memory managment initialization. Historically plat_mem_setup did the entire platform initialization. This was rather impractical because it meant plat_mem_setup had to get away without any kind of memory allocator. To keep old code from breaking plat_setup was just renamed to plat_setup and a second platform initialization hook for anything else was introduced. Signed-off-by: Ralf Baechle commit 7ab2dc41d15f31e9d5472e46148337b4cf7c941c Author: Ralf Baechle Date: Sat Jun 17 14:55:40 2006 +0100 [MIPS] SN: Declare bridge_pci_ops. Signed-off-by: Ralf Baechle commit 610019baddcb4c4c323c12cd44ca7f73d7145d6f Author: Ralf Baechle Date: Sat Jun 17 14:54:32 2006 +0100 [MIPS] Remove unused function alloc_pci_controller. Signed-off-by: Ralf Baechle commit 9e0c7afd0ec6e6d788df14270b2b1b8f21a384a8 Author: Ralf Baechle Date: Sat Jun 17 00:55:45 2006 +0100 [MIPS] IP27: Extract pci_ops into separate file. Signed-off-by: Ralf Baechle commit 3a11545615dedd8dd52ff110ddf6e970bfac963a Author: Ralf Baechle Date: Sat Jun 17 00:46:27 2006 +0100 [MIPS] IP27: Use symbolic constants instead of magic numbers. Signed-off-by: Ralf Baechle commit c340cc504c91cf81561ecca10ec13396ae24dcc0 Author: Yoichi Yuasa Date: Thu Jun 15 23:29:37 2006 +0900 [MIPS] vr41xx: remove unnecessay items from vr41xx/Kconfig. Remove unnecessary items from vr41xx/Kconfig. SYS_HA_CPU_VR41XX has already been selected by MACH_VR41XX. Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle commit f456acae4fe9b4504db7d75c51fba6b8db787ee2 Author: Ralf Baechle Date: Wed Jun 14 08:10:35 2006 +0100 [MIPS] IP27: Cleanup N/M mode configuration. Signed-off-by: Ralf Baechle commit 09866258612bd9f389b0d86b3a63fe98e855d3f0 Author: Ralf Baechle Date: Wed Jun 14 08:01:30 2006 +0100 [MIPS] IP27: Throw away old unused hacks. Signed-off-by: Ralf Baechle commit d9b8d0da404cf952a425d990c37c29c166eec954 Author: Ralf Baechle Date: Mon Jun 12 12:20:09 2006 +0100 [MIPS] Drop 0 definition for kern_addr_valid kern_addr_valid is currently only being used in kmem_ptr_validate which is making some vague attempt at verfying the validity of an address. Only IA-64, PARISC and x86-64 actually make some actual effort to verify the validity of the pointer. Most architecture definitions of kern_addr_valid() just define it as 1; the Alpha and CONFIG_DISCONTIGMEM on i386 and MIPS even as 0; the 0-definition will result in kmem_ptr_validate always failing which in turn will cause d_validate to always fail. d_validate's only two users are smbfs and ncpfs, so the 0 definition ended breaking those ... Signed-off-by: Ralf Baechle commit e53639d8f313974a87540015cbb0832905be6056 Author: Ralf Baechle Date: Mon Jun 12 09:13:56 2006 +0100 [MIPS] Consolidate definitions of pfn_valid in one file. Signed-off-by: Ralf Baechle commit 952fa954a61cee43de5afba91ae605e30ed2586c Author: Rodolfo Giometti Date: Mon Jun 5 17:43:10 2006 +0200 [MIPS] APM emu support Signed-off-by: Rodolfo Giometti Signed-off-by: Ralf Baechle commit aa9772e330d6c0a8a94316cb38ae8a7495885a60 Author: Ralf Baechle Date: Mon Jun 12 00:55:14 2006 +0100 [MIPS] SN: Rename SGI_SN0_N_MODE -> SGI_SN_N_MODE. It's not SN0-specific. Signed-off-by: Ralf Baechle commit bf5a312b26e9943613b765a29a8de5f4c762df11 Author: Ralf Baechle Date: Sat Jun 10 00:37:20 2006 +0100 [MIPS] SN: Move FRU header one level up; it is not SN0-specific. Signed-off-by: Ralf Baechle commit d8cb4e119f9a97f87f69a179d855f5dfc5d578c2 Author: Ralf Baechle Date: Sun Jun 11 23:03:08 2006 +0100 [MIPS] Cleanup ARCH_DISCONTIGMEM_ENABLE and NUMA configuration. IP27 configuration isn't the only NUMA system - it just happens to be the currently only supported MIPS NUMA system. So move the necessary options back into the main MIPS Kconfig file. Signed-off-by: Ralf Baechle commit 3e0ba410a5d5595c2b79ecbfb85fb2466b998680 Author: Ralf Baechle Date: Wed Jun 7 20:13:20 2006 +0100 [MIPS] IP27: Remove #if 0'ed code. Signed-off-by: Ralf Baechle commit 8f2f360da9262091153c97d756c40eabdde75f1a Author: Ralf Baechle Date: Wed Jun 7 20:10:06 2006 +0100 [MIPS] IP27: Nuke leftovers of _STANDALONE Signed-off-by: Ralf Baechle commit edc123d18397008fcd4fdf04f60e033ba1042834 Author: Ralf Baechle Date: Wed Jun 7 20:07:29 2006 +0100 [MIPS] IP27: Remove leftovers of sable support. Signed-off-by: Ralf Baechle commit 8dbd1d3e65f0281ddf9f7b8123ef81763bc2051f Author: Ralf Baechle Date: Wed Jun 7 20:04:23 2006 +0100 [MIPS] IP27: Nuke last leftovers from FRUTEST Signed-off-by: Ralf Baechle commit b383f47ec71de66dbba5f7233479783041f5096a Author: Ralf Baechle Date: Wed Jun 7 20:02:21 2006 +0100 [MIPS] IP27: Nuke last leftovers of CONFIG_SGI_IO. Signed-off-by: Ralf Baechle commit 5e46c3aefe60d1398488410a0c39b4cd87738614 Author: Ralf Baechle Date: Sun Jun 4 15:14:05 2006 -0700 [MIPS] C99-ify struct resource initialization. Signed-off-by: Ralf Baechle commit cbb306962ec4b30e03423137e22d605281a8f598 Author: Ralf Baechle Date: Sun Jun 4 00:55:21 2006 +0100 [MIPS] Remove duplicate declarations from Alchemy code. Signed-off-by: Ralf Baechle commit 1bd5e16168b58e73f7be432ba3558af9d38662cf Author: Ralf Baechle Date: Sat Jun 3 21:59:51 2006 +0100 [MIPS] Cleanup __emt() a bit. Signed-off-by: Ralf Baechle commit c0589f1ecea73e7bce09c569dca44b83e68a39b1 Author: Yoichi Yuasa Date: Wed May 31 16:00:05 2006 +0900 [MIPS] Remove unused definitions from addrspace.h. Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle commit fbd7a38ffb127da53a4c9fd0ad09e6ed937e8e3f Author: Sergei Shtylyov Date: Sun May 28 00:04:01 2006 +0400 [MIPS] arch/mips/au1000/time.c cleanup Mark au1xxx_timer_setup() __init, just because it is. Get rid of unneeded extern's (note that (*do_gettimeoffset)() is already declared by ) and an unused variable. Kill some whitespace... Signed-off-by: Sergei Shtylyov Signed-off-by: Ralf Baechle commit b0b0e13e7dd309be13ab9324e67893e62b136e44 Author: Ralf Baechle Date: Thu May 18 12:38:47 2006 +0100 [MIPS] Remove unused instances of prom_build_cpu_map. Signed-off-by: Ralf Baechle commit c583122c26ad04bb2379933dc5acc8b9479d6c67 Author: Thiemo Seufer Date: Mon May 15 18:59:34 2006 +0100 [MIPS] Qemu system shutdown support Signed-off-by: Thiemo Seufer Signed-off-by: Ralf Baechle commit eae89076e696f51762d81d6e2538c3beb59fa7bd Author: Atsushi Nemoto Date: Tue May 16 01:26:03 2006 +0900 [MIPS] Unify mips_fpu_soft_struct and mips_fpu_hard_structs. The struct mips_fpu_soft_struct and mips_fpu_hard_struct are completely same now and the kernel fpu emulator assumes that. This patch unifies them to mips_fpu_struct and get rid of mips_fpu_union. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle commit 5deee2dbf495b2693629f7e8f846483432096278 Author: Ralf Baechle Date: Mon May 15 15:08:22 2006 +0100 [MIPS] Remove prototype for non-existing function. Signed-off-by: Ralf Baechle commit a240a469649eaab03f0c4c7fbb21ea5041bf5572 Author: Mark.Zhan Date: Sat May 6 17:04:20 2006 +0800 [MIPS] Wind River 4KC PPMC Eval Board Support Support for the GT-64120-based Wind River 4KC PPMC Evaluation board. Signed-off-by: Rongkai.Zhan Signed-off-by: Ralf Baechle commit a643d2b57403dc943fd4d9a3c803addd1c6b0ddc Author: Herbert Valerio Riedel Date: Sun May 7 15:48:25 2006 +0200 [MIPS] Au1xxx: board specific irq code cleanup Convert sizeof/sizeof use to use of ARRAY_SIZE macro, and annotate irqmap structures as __initdata. Signed-off-by: Herbert Valerio Riedel Signed-off-by: Ralf Baechle commit 3c0094426f3ff37697062b940211712746419688 Author: Ralf Baechle Date: Fri Jun 16 17:10:49 2006 +0200 [MIPS] IP27: Fix collision with hardcoded interrupt number. Signed-off-by: Ralf Baechle commit 0307e8d024dffc00743fb54b9afa920a346f1adb Author: Atsushi Nemoto Date: Sun Jun 11 23:25:43 2006 +0900 [MIPS] Fix futex_atomic_op_inuser. I found that NPTL's pthread_cond_signal() does not work properly on kernels compiled by gcc 4.1.x. I suppose inline asm for __futex_atomic_op() was wrong. I suppose: 1. "=&r" constraint should be used for oldval. 2. Instead of "r" (uaddr), "=R" (*uaddr) for output and "R" (*uaddr) for input should be used. 3. "memory" should be added to the clobber list. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle commit e1701fb2e2f3c02760684e26007e3379be23b690 Author: [MIPS] James E Wilson Date: Mon Feb 27 15:04:38 2006 -0800 [PATCH] Fix BCM1480 doubled process accounting times. Running a UP kernel on a bcm1480 board, I get nonsensical timing results, like this: release@unknown:~/tmp$ time ./a.out real 0m22.906s user 0m45.792s sys 0m0.010s According to my watch, this program took 23 seconds to run, so the real time clock is OK. It is process accounting that is broken. I tracked this down to a problem with the function bcm1480_timer_interrupt in the file sibyte/bcm1480/time.c. This function calls ll_timer_interrupt for cpu0, and ll_local_timer_interrupt for all cpus. However, both of these functions do process accounting. Thus processes running on cpu0 end up with doubled times. This is very obvious in a UP kernel where all processes run on cpu0. The correct way to do this is to only call ll_local_timer interrupt if this is not cpu0. This can be seen in the mips-board/generic/time.c file, and also in the sibyte/sb1250/time.c file, both of which handle this correctly. I fixed the bcm1480/time.c file by copying over the correct code from the sb1250/time.c file. With this fix, I now get sensible results. release@unknown:~/tmp$ time ./a.out real 0m22.903s user 0m22.894s sys 0m0.006s Signed-off-by: Ralf Baechle commit 4b29f6043dbb07823a0a618fb8b35ef3ac83e759 Author: Ralf Baechle Date: Wed Jun 7 15:24:44 2006 +0100 [MIPS] Mark PNX8550 support broken. Broken in too many way for me to fix it for 2.6.17. Signed-off-by: Ralf Baechle commit 72fbfb260197a52c2bc2583f3e8f15d261d0f924 Author: Ralf Baechle Date: Wed Jun 7 13:25:37 2006 +0100 [MIPS] Fix optimization for size build. It took a while longer than on other architectures but gcc has finally started to strike us as well ... This also fixes the damage by 6edfba1b33c701108717f4e036320fc39abe1912. Signed-off-by: Ralf Baechle commit aac076f8805448a6331a526aa02cc438730ddd39 Author: Ralf Baechle Date: Wed Jun 7 12:53:17 2006 +0100 [MIPS] IP22: Fix ISA driver builds if CONFIG_EISA is selected. Signed-off-by: Ralf Baechle commit 973c789742b4dc957cd7feb96cae98988dd0cf01 Author: Yoichi Yuasa Date: Wed Jun 7 09:53:34 2006 +0900 [MIPS] Cobalt: Fix undefined reference to disable_early_printk. Signed-off-by: Yoichi Yuasa Signed-off-by: Ralf Baechle commit c138e12f3a2e0421a4c8edf02587d2d394418679 Author: Atsushi Nemoto Date: Tue May 23 00:47:41 2006 +0900 [MIPS] Fix fpu_save_double on 64-bit. > Without this fix, _save_fp() in 64-bit kernel is seriously broken. > > ffffffff8010bec0 <_save_fp>: > ffffffff8010bec0: 400d6000 mfc0 t1,c0_status > ffffffff8010bec4: 000c7140 sll t2,t0,0x5 > ffffffff8010bec8: 05c10011 bgez t2,ffffffff8010bf10 <_save_fp+0x50> > ffffffff8010becc: 00000000 nop > ffffffff8010bed0: f4810328 sdc1 $f1,808(a0) > ... Fix register usage in fpu_save_double() and make fpu_restore_double() more symmetric with fpu_save_double(). Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle commit 734996820fd02b52a3fa0fcc09bdb914934bea4c Author: Elizabeth Oldham Date: Tue Jun 6 10:57:09 2006 +0100 [MIPS] Malta: Handle byteswapping hardare bug in big endian mode. The SOC-it system controller running in big endian mode might forget byteswapping when DMAing to the last word of physical memory. Fixed by ignoring the last page of memory. Signed-off-by: Ralf Baechle commit 466e6227e6a54d9b94b50972612fe8bf0450f786 Author: Andrew Victor Date: Mon Jun 19 17:26:23 2006 +0100 [ARM] 3588/1: AT91RM9200 CSB337/637 board update Patch from Andrew Victor This patch updates the support for the Cogent CSB337 and CSB637 boards. The changes include: 1. Use the new at91_uart_config structure and device registration functions for the UARTs. 2. Registration of I2C and SPI platform devices. 3. The CSB337 board uses PB0 & PB1 (and not PB2) for the LEDs. [Patch from David Brownell] Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 82c583e3ae31ffa76d1280197274cc1e1cde3179 Author: Andrew Victor Date: Mon Jun 19 16:57:00 2006 +0100 [ARM] 3587/1: AT91RM9200 hardware headers Patch from Andrew Victor These headers define the registers and bits for the SPI (Serial Peripheral Interface), SSC (Synchronous Serial), TC (Timer/Counter) and UDP (USB Device) peripherals integrated in the AT91RM9200 processor. (They will probably also be usable for the AT91SAM9 series of SoC processors) Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 7238d7ee82d325212e83630047e9844943225118 Author: Andrew Victor Date: Mon Jun 19 16:57:00 2006 +0100 [ARM] 3586/1: AT91RM9200 header update Patch from Andrew Victor Added definition for the bits in the Chip ID register. Corrected the capitalization of AT91_RTC_AMPM register name. Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 2e83640270b4a76a3855131953c82bbc1919e589 Author: Andrew Victor Date: Mon Jun 19 16:31:55 2006 +0100 [ARM] 3585/1: AT91RM9200 Platform devices Patch from Andrew Victor This patch updates the platform device support for the AT91RM9200. The changes include: 1. USB Host device renamed to "at91_ohci" since the driver is also usable on the AT91SAM9261 processor. 2. Enabling multidrive on the USB Device's pullup pin should not be done for all boards. Moved into board-specific files. [Patch from David Brownell] 3. Move enabling of PCMCIA/Compact Flash pins out of the driver. 4. Added SPI device and resources. 5. Added Watchdog device and resources. [Patch from David Brownell] 6. Added UART device and resources. 7. The simple devices (watchdog, rtc, i2c) are now automatically registered and don't have to be registered separately in each board-specific file. [Patch from David Brownell] Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 5af29e56c221d709bdbd5fccaf190e21f290a30e Author: Russell King Date: Mon Jun 19 15:37:31 2006 +0100 [ARM] Fix badge4 build error The Badge4 PCMCIA driver was referencing structure elements which had been renamed. Fix the missing renames. Signed-off-by: Russell King commit 441ff855f3edf5d355bea30f557bbed6bcd42c6c Author: H. Peter Anvin Date: Mon Jun 19 15:35:36 2006 +0100 [ARM] Fix byte order macros for Thumb The byte order functions are visible to userspace. Unfortunately, __arch_swab32() contains an assembly instruction which is invalid when compiling for Thumb. This reverts to the C version when compiling for Thumb. Signed-off-by: H. Peter Anvin Signed-off-by: Russell King commit 5e6423871772b89120c9fb356d2eabb67fea60bd Author: Sascha Hauer Date: Mon Jun 19 15:30:21 2006 +0100 [ARM] 3577/1: netX: Default config for netx based boards Patch from Sascha Hauer This patch adds the default config file for netx based boards. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King commit 2697c5e1f799f201366d5fd7d25e96a21587f1a9 Author: Sascha Hauer Date: Mon Jun 19 15:29:45 2006 +0100 [ARM] 3576/1: netX: board support for NXEB500HMI development board Patch from Sascha Hauer This patch adds the board specific code for the Hilscher NXEB500HMI development board. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King commit af614ba072dab2940471fec1f30bd59b8272fc6b Author: Sascha Hauer Date: Mon Jun 19 15:29:44 2006 +0100 [ARM] 3575/1: netX: board support for NXDB500 development board Patch from Sascha Hauer This patch adds the board specific code for the Hilscher NXDB500 development board. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King commit 693532dcff871543639743e9c2e2b99c492f8f8d Author: Sascha Hauer Date: Mon Jun 19 15:29:43 2006 +0100 [ARM] 3574/1: netX: board support for NXDKN development board Patch from Sascha Hauer This patch adds the board specific code for the Hilscher NXDKN development board. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King commit 8e77da68a6107ee47323fec5dfb3a93ebbc809e2 Author: Sascha Hauer Date: Mon Jun 19 15:28:20 2006 +0100 [ARM] 3569/2: netX: driver for XMAC/XPEC engines Patch from Sascha Hauer The netX processors have generic network bitstream engines (XMAC/XPEC). This driver adds support for firmware loading and start, stop, reset commands. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King commit ef70cd4d247defcd7c0f789a5a98deab0afadf53 Author: Sascha Hauer Date: Mon Jun 19 15:28:19 2006 +0100 [ARM] 3568/2: netX: pointer fifo driver Patch from Sascha Hauer This patch adds support for the pointer FIFOs on netX. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King commit bb6d8c8828123e01e2ae6c9d9c4870477889fd94 Author: Sascha Hauer Date: Mon Jun 19 15:27:53 2006 +0100 [ARM] 3567/2: arm: base support for Hilscher netX Patch from Sascha Hauer This patch adds the base support for Hilscher's netX network processors. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King commit 814138ffa488824393d2f49f2720dcd197a7d4cf Author: Andrew Victor Date: Mon Jun 19 15:26:54 2006 +0100 [ARM] 3584/1: AT91RM9200 GPIO suspend/resume support Patch from Andrew Victor This patch adds suspend/resume/set_wake support for the AT91RM9200's GPIO interrupts. Original patch from David Brownell. Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 683c66bf75ce277b90d658da0c1a0bf1a55cce4c Author: Andrew Victor Date: Mon Jun 19 15:26:53 2006 +0100 [ARM] 3583/1: AT91RM9200 IRQ suspend/resume support Patch from Andrew Victor Added suspend/resume/set_wake support for the AT91RM9200's AIC interrupt controller. Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 37f2e4bc120bd784e7f69f961233e1c16b74d170 Author: Andrew Victor Date: Mon Jun 19 15:26:52 2006 +0100 [ARM] 3582/1: AT91RM9200 IRQ trigger types Patch from Andrew Victor The AIC interrupt controller's set_irq_type() can also be used for internal interrupts. IRQT_LOW and IRQT_FALLING are the only options not supported for the internal interrupts. [Original patch from Karl Olsen] Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 10e8e1fb758eed5cfb0cae1b770f842624851e7b Author: Andrew Victor Date: Mon Jun 19 15:26:51 2006 +0100 [ARM] 3581/1: AT91RM9200 Internal SRAM Patch from Andrew Victor This patch maps the AT91RM9200's internal SRAM into the virtual memory address space - just below the internal peripheral registers. Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 2a6f9902c6a799a9c0218b37e39b75690c3b9a70 Author: Andrew Victor Date: Mon Jun 19 15:26:50 2006 +0100 [ARM] 3580/1: AT91RM9200 Timer suspend/resume support Patch from Andrew Victor Added suspend/resume support for the AT91RM9200 timer. Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 963151f2471d0e6475d8b2d3a005417aec1766f7 Author: Andrew Victor Date: Mon Jun 19 15:23:41 2006 +0100 [ARM] 3579/1: AT91RM9200 Timer simplification Patch from Andrew Victor Use a global variable 'last_crtr' to store the time of the last timer tick instead of the ST_RTAR register. It's faster, frees up the ST_RTAR register for other uses, and hopefully makes the code more understandable. [Patch from Peter Menzebach] Also add the SA_TIMER flag to Timer IRQ. (It seems to be required for the realtime preempt patch). Signed-off-by: Andrew Victor Signed-off-by: Russell King commit 3095faf5295f2da9118469c925d2cfb7775ad287 Author: Sascha Hauer Date: Mon Jun 19 13:30:58 2006 +0100 [ARM] 3572/1: netX: framebuffer driver for Hilscher netX Patch from Sascha Hauer This patch adds framebuffer support for Hilscher's netX network processors. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King commit f8441e13449638e9fc3c160c35ada3b6f1f8d9c0 Author: Sascha Hauer Date: Mon Jun 19 13:29:07 2006 +0100 [ARM] 3571/1: netX: serial driver for Hilscher netX Patch from Sascha Hauer This patch adds the serial driver for Hilscher's netX network processors. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King commit ab76fb13d73488ded53c87b77b1b5e38df2acf74 Author: Sascha Hauer Date: Mon Jun 19 13:24:32 2006 +0100 [ARM] 3566/1: netX: register definitions Patch from Sascha Hauer This patch adds the register definitions for Hilscher's netX network processors. Signed-off-by: Robert Schwebel Signed-off-by: Sascha Hauer Signed-off-by: Russell King commit 91f8ed835ffb34b4108cc16eefd3303e4068bee0 Author: Andrew Victor Date: Mon Jun 19 13:20:23 2006 +0100 [ARM] 3578/1: AT91RM9200 Clock update Patch from Andrew Victor Some updates to the clock infrastructure for the AT91RM9200. 1. Hard-coded values replaced with names defined in at91rm9200_sys.h. 2. Added the four PIO clocks, which are enabled at startup. 3. At startup, disable all unused clocks. 4. Minor bugfix for usage counts associated with MCK. [Patch from David Brownell] 5. Added at91_clock_associate() function to associate device & function with a particular clock. [Patch from David Brownell] Signed-off-by: Andrew Victor Signed-off-by: Russell King commit b7408aff2d325581dcafffa5dbcc09c42ae64b5d Author: Richard Purdie Date: Mon Jun 19 13:08:39 2006 +0100 [ARM] 3563/1: LED: Set the LOCOMO LED driver default triggers Patch from Richard Purdie Set the default triggers for the LOCOMO LED driver. Signed-off-by: Richard Purdie Signed-off-by: Russell King commit b44fb7a09e6bb7d77c1b4b402591f6f953c1e51c Author: Andrew Victor Date: Mon Jun 19 13:06:05 2006 +0100 [ARM] 3565/1: AT91RM9200 MMC update Patch from Andrew Victor This patch includes code cleanups and minor fixes to the AT91RM9200 MMC driver. 1. Replace calls to DBG() with pr_debug(). 2. 'host' can never be null, so don't bother checking for that case. 3. Remove SA_SAMPLE_RANDOM from request_irq(). [Patch from Matt Mackall] 4. clk_get() doesn't return NULL on error - need to test returned value with IS_ERR(). 5. Free resources if clk_get() or request_irq() fails. Signed-off-by: Andrew Victor Signed-off-by: Russell King commit a3fd4a1b9ced850ac1a9d5bb9f8fab494d07f3fa Author: Russell King Date: Sun Jun 4 17:51:15 2006 +0100 [MMC] Convert all hosts except mmci to use data->blksz The MMC specification allows non-power of two block sizes. As such, we should not pass the log2 block size to host drivers, but instead pass the byte size. However, ARM MMCI can only work with log2 block size, so continue to pass both the log2 block size and byte block size. This means that for the moment, the byte block size must remain a power of two, but this is the first stage of removing this restriction for other hosts. Signed-off-by: Russell King commit ad3b5fb772e6a824f1ac341eb8e392eca6fc524f Author: Ben Dooks Date: Mon Jun 19 09:43:23 2006 +0100 [MTD NAND] S3C2410 driver cleanup Fix unused variables and commenting since tglx's new NAND updates Signed-off-by: Ben Dooks Signed-off-by: David Woodhouse commit d1fef3c5e16327661be6cb127d68f5be379697a5 Author: Ben Dooks Date: Mon Jun 19 09:29:38 2006 +0100 [MTD NAND] s3c24x0 board: Fix clock handling, ensure proper initialisation. Signed-off-by: Ben Dooks Signed-off-by: David Woodhouse commit 0d8fee3270f8a5e4bf95fbed3e81e21b57f8a5a0 Author: Al Viro Date: Mon Jun 19 08:41:30 2006 +1000 [XFS] Kill direct access to ->count in valusema(); all we ever use it for is check if semaphore is actually locked, which can be trivially done in portable way. Code gets more reabable, while we are at it... SGI-PV: 953915 SGI-Modid: xfs-linux-melb:xfs-kern:26274a Signed-off-by: Al Viro Signed-off-by: Nathan Scott commit a805bad5daae8d4f92ce46f467484d4867e996d4 Author: Nathan Scott Date: Mon Jun 19 08:40:27 2006 +1000 [XFS] Remove unneeded conditional code on NFS export interface related code paths. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26250a Signed-off-by: Nathan Scott commit 6fe90e6d1451a05db37b2a582410ddcb45af3606 Author: Nathan Scott Date: Mon Jun 19 08:40:12 2006 +1000 [XFS] Remove an incorrect use of unlikely() on a relatively likely code path. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26249a Signed-off-by: Nathan Scott commit 1e69dd0eb354d6f1a77098a3946b5ba57d4e3109 Author: Nathan Scott Date: Mon Jun 19 08:39:53 2006 +1000 [XFS] Push some common code out of write path into core XFS code for sharing. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26248a Signed-off-by: Nathan Scott commit 1d47bec290a6f1f366192946840efef5076d9fc7 Author: Nathan Scott Date: Mon Jun 19 08:39:16 2006 +1000 [XFS] Remove unnecessary local from open_exec dmapi path. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26247a Signed-off-by: Nathan Scott commit 96ce2385dd2817da549910001a69ac0a2762a1b9 Author: Ben Dooks Date: Sun Jun 18 23:06:41 2006 +0100 [ARM] 3559/1: S3C2442: core and serial port Patch from Ben Dooks Core support for the Samsung S3C2442, and the serial port driver update to allow the serial port blocks to be used. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 66a9b49a370baac75d90b7da9a2445997a8a9438 Author: Ben Dooks Date: Sun Jun 18 23:04:05 2006 +0100 [ARM] 3557/1: S3C24XX: centralise and cleanup uart registration Patch from Ben Dooks All the S3C24XX based devices currently have similar uart blocks, in the same location. Make the process of adding new uart blocks easier by commonising the device definitions and adding a new init function for the cpu code. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 810c894f2b27b634883723f9fee10a7cf1d0bcb4 Author: Ben Dooks Date: Sun Jun 18 22:56:37 2006 +0100 [ARM] 3558/1: SMDK24XX: LED platform devices Patch from Ben Dooks Platform devices for the LEDs on all the SMDK24XX boards Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 1046d88001e7b8819f60dece2eaf1b44bf4b4460 Author: David Woodhouse Date: Sun Jun 18 22:44:21 2006 +0100 [JFFS2] Check CRC32 on dirent and data nodes each time they're read Also, make sure dirents are marked REF_UNCHECKED when we 'discover' them through eraseblock summary. Signed-off-by: David Woodhouse commit fc6612f627c697b348a4ef64f16fb373d86dbd76 Author: David Woodhouse Date: Sun Jun 18 18:35:10 2006 +0100 [JFFS2] When retiring nextblock, allocate a node_ref for the wasted space Failing to do so makes the calculated length of the last node incorrect, when we're not using eraseblock summaries. Signed-off-by: David Woodhouse commit 9df5db80a781c1a1c67388c82f64f835093c3cc3 Author: David Brownell Date: Sun Jun 18 16:39:33 2006 +0100 [ARM] 3534/1: add spi support to lubbock platform Patch from David Brownell This adds the platform device for SSP/SPI controller, and declares the ads7846 device hooked up to it. Not all Lubbock boards appear to populate the connector needed to use this instead of the ucb1400 chip, but it can always be used as a temperature sensor. In short, this is probably most useful as an example of how to provide the configuration data used by the pxa2xx_spi driver. (Last tested against a slightly earlier version of that driver.) Signed-off-by: David Brownell Signed-off-by: Russell King commit ebc67da65fda03cbe5b4019d91229287fddd5c6e Author: Tony Lindgren Date: Sun Jun 18 16:26:58 2006 +0100 [ARM] 3554/1: ARM: Fix dyntick locking Patch from Tony Lindgren This patch fixes some dyntick locking issues on ARM as pointed out by Russell King. Signed-off-by: Tony Lindgren Signed-off-by: Russell King commit 36fe6a83b4a52276eebb929ff94896fa65d83401 Author: Ben Dooks Date: Sun Jun 18 16:21:53 2006 +0100 [ARM] 3553/1: S3C24XX: earlier print of cpu idcode info Patch from Ben Dooks Move the printk of the CPU information and IDCODE before the checking of the table entry validity to aide in debugging new cpu entries. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 68d5969378fc21d9f70c0fdbc25176a68d873922 Author: Ben Dooks Date: Sun Jun 18 16:21:52 2006 +0100 [ARM] 3552/1: S3C24XX: Move VA of GPIO for low-level debug Patch from Ben Dooks Using the low-level debug routines early in the kernel debug cause the 1:1 mapping to get into the TLB, which is not flushed until after the CPU detection process (which needs the GPIO VA). This patch moves the VA for the GPIO to the same offset as the physical offset of the UART to the GPIO. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 4833acb2e19f669ce87c439a7d91ead600d8a7c9 Author: Ben Dooks Date: Sun Jun 18 16:21:51 2006 +0100 [ARM] 3551/1: S3C24XX: PM code failes to compile with CONFIG_DCACHE_WRITETHROUGH Patch from Ben Dooks If CONFIG_CPU_DCACHE_WRITETHOUGH is set, then the S3C24XX PM code fails to compile, as there is no need to flush the D-cache, the flush function arm920_flush_kern_cache_all() is not compiled. Fix the code to not use this if the config is set. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit e2e5810f41646a400a9c6f941000db88d2ca10eb Author: Ben Dooks Date: Sun Jun 18 16:21:50 2006 +0100 [ARM] 3550/1: OSIRIS: fix serial port map for 1:1 Patch from Ben Dooks The default serial port-mapping for the Osiris has the port 2 mapped onto the first serial port, and no port1. Correct this so port 1 is port. Signed-off-by: Ben Dooks Signed-off-by: Russell King commit 45a7b9cf8e0634fa546e9e7ad29af990ab4afcf2 Author: Catalin Marinas Date: Sun Jun 18 16:21:50 2006 +0100 [ARM] 3548/1: Fix the ARMv6 CPU id in compressed/head.S Patch from Catalin Marinas This code was still using the old format for the ARMv6 CPU id and it wasn't flushing the caches on the MPCore CPU (and other ARM1176 cores). The patch changes the mask bits to cope with the new id format. Signed-off-by: Catalin Marinas Signed-off-by: Russell King commit aca6ca10974aa78adfb47291722ce851160213e4 Author: Russell King Date: Thu Jun 15 20:28:03 2006 +0100 [ARM] Gather common sigframe saving code into setup_sigframe() Gather the common sigmask savbing code inside setup_sigcontext(), and rename the function setup_sigframe(). Pass it a sigframe structure. Signed-off-by: Russell King commit 680714844fd1dcc6f03b22353103985be9d58db6 Author: Russell King Date: Thu Jun 15 20:23:02 2006 +0100 [ARM] Gather common sigframe restoration code into restore_sigframe() Gather the sigmask restoration code inside restore_sigcontext(), and rename the function restore_sigframe(). Pass it a sigframe structure. Signed-off-by: Russell King commit cb3504e8fa84870aabcf51c67e29675817e30836 Author: Russell King Date: Thu Jun 15 20:18:25 2006 +0100 [ARM] Re-use sigframe within rt_sigframe sigframe is now a contained subset of rt_sigframe, so we can start to re-use code which accesses sigframe data for both rt and non-rt signals. Signed-off-by: Russell King commit 7d4fdc19fc134f69f3711c14e63caef56aee0f2a Author: Russell King Date: Thu Jun 15 20:13:25 2006 +0100 [ARM] Merge sigcontext and sigmask members of sigframe ucontext contains both the sigcontext and sigmask structures, and is also used for rt signal contexts. Re-use this structure for non-rt signals. Signed-off-by: Russell King commit cc1a852137d6c12d50c372d61a1c5f763998536b Author: Russell King Date: Thu Jun 15 18:02:25 2006 +0100 [ARM] Replace extramask with a full copy of the sigmask There's not much point in splitting the sigmask between two different locations, so copy it entirely into a proper sigset_t. This will eventually allow rt_sigframe and sigframe to share more code. Signed-off-by: Russell King commit ce7a3fdc5c55fd01d8e2deda0daef84473644f8b Author: Russell King Date: Thu Jun 15 18:00:34 2006 +0100 [ARM] Remove rt_sigframe puc and pinfo pointers These two members appear to be surplus to requirements. Discussing this issue with glibc folk: | > Additionally, do you see any need for these weird "puc" and "pinfo" | > pointers in the kernels rt_sigframe structure? Can we kill them? | | We can kill them. I checked with Phil B. about them last week, and he | didn't remember any reason they still needed to be there. And nothing | should know where they are on the stack. Unfortunately, doing this | will upset GDB, which knows that the saved registers are 0x88 bytes | above the stack pointer on entrance to an rt signal trampoline; but, | since puc and pinfo are quite recognizable, I can adapt GDB to support | the new layout if you want to remove them. So remove them. Signed-off-by: Russell King commit 5247593c9634309d1b9f7b549495b8e5ad521688 Author: Paul Brook Date: Tue May 16 14:25:55 2006 +0100 [ARM] 3335/1: Old-abi Thumb sys_syscall broken Patch from Paul Brook The old-abi sys_syscall syscall is broken when called from Thumb mode. It assumes the syscall number is an Arm syscall number (ie. starts from __NR_OABI_SYSCALL_BASE). In thumb mode syscall numbers start from zero. The patch below fixes this by clearing the nigh bits of the syscall number instead of inverting them. Technically this means we accept some invalid syscall numbers, but I can't see how that could be a problem. The two sets of numbers far apart that unimplemented syscalls should still be rejected. Signed-off-by: Paul Brook Signed-off-by: Russell King commit 254a1564fb6f9242782f9a8e5d59a212424686e8 Author: Vitaly Wool Date: Tue May 16 11:54:38 2006 +0100 [ARM] 3467/1: [3/3] Support for Philips PNX4008 platform: defconfig Patch from Vitaly Wool This patch adds default configuration file PNX4008 ARM platform. It\'s basically the same as the previos one. Signed-off-by: Vitaly Wool Signed-off-by: Dmitry Pervushin Signed-off-by: Russell King commit 78818e477bf785391b02672d053fdbb2e111fb50 Author: Vitaly Wool Date: Tue May 16 11:54:37 2006 +0100 [ARM] 3466/1: [2/3] Support for Philips PNX4008 platform: chip support Patch from Vitaly Wool This patch adds basic chip support for PNX4008 ARM platform. It's basically the same as the previous one, but with the rmk's comments taken into account. Signed-off-by: Vitaly Wool Signed-off-by: Dmitry Pervushin Signed-off-by: Russell King commit a5a503038e71a6b7d4bd9e596ac13087274e60c7 Author: Vitaly Wool Date: Tue May 16 11:54:36 2006 +0100 [ARM] 3465/1: [1/3] Support for Philips PNX4008 platform: headers Patch from Vitaly Wool This patch adds kernel headers for PNX4008 ARM platform. It's basically the same as the previos one, but with the rmk's comments taken into account. Signed-off-by: Vitaly Wool Signed-off-by: Dmitry Pervushin Signed-off-by: Russell King commit 51cb21a9cd2e3bba8a69948794eb9480facdef45 Author: Marc Singer Date: Tue May 16 11:41:43 2006 +0100 [ARM] 3407/1: lpd7x: documetation update Patch from Marc Singer New documentation for the touchscreen controllers and LCD panels. Signed-off-by: Marc Singer Signed-off-by: Russell King commit d4adcffb6574d3414f2e39d6ca1be5eccf97ac52 Author: Marc Singer Date: Tue May 16 11:41:40 2006 +0100 [ARM] 3406/1: lpd7x: compilation fix for smc91x Patch from Marc Singer Reworking of the adaptation macros to allow driver to compile again for the lpd7x's. Also, support added for the lh79520 so it may use the smc91x. Signed-off-by: Marc Singer Signed-off-by: Russell King commit c97898614bf0ac9605333a2c99bdbcf4276a22bd Author: Marc Singer Date: Tue May 16 11:41:32 2006 +0100 [ARM] 3405/1: lpd7a40x: CPLD ssp driver Patch from Marc Singer Driver for operating SSP devices through LPD7A40X CPLD chip. This driver is used by the audio codecs. Signed-off-by: Marc Singer Signed-off-by: Russell King commit 903e2bbda92e5a14f8050154046a14230abb800b Author: Marc Singer Date: Tue May 16 11:41:30 2006 +0100 [ARM] 3404/1: lpd7a40x: AMBA CLCD support Patch from Marc Singer Board support and LCD panel configurations to integrate lh7a40x's with the amba clcd driver. Signed-off-by: Marc Singer Signed-off-by: Russell King commit 2514581eb13f778d70bdc270b8dc36bd6eaac4f8 Author: Marc Singer Date: Tue May 16 11:41:29 2006 +0100 [ARM] 3403/1: lpd7a40x: updated default configurations Patch from Marc Singer Revised default configuration files. Signed-off-by: Marc Singer Signed-off-by: Russell King commit fb62c5a7043617dd9d678beafc368b217aa28da4 Author: Marc Singer Date: Tue May 16 11:41:29 2006 +0100 [ARM] 3402/1: lpd7a40x: serial driver bug fix Patch from Marc Singer The serial driver now sets up the third UART when it is to be used. Signed-off-by: Marc Singer Signed-off-by: Russell King commit 638b266630db8d492255d340e18d46ba6ab1b057 Author: Marc Singer Date: Tue May 16 11:41:28 2006 +0100 [ARM] 3401/1: lpd7a40x: platform update Patch from Marc Singer Updates to the lpd7a40x_platform files. Includes support for new architecture, lpd7a400. Signed-off-by: Marc Singer Signed-off-by: Russell King commit 2295196c30ea686389519f699f0ccbfbc5c3b94c Author: Marc Singer Date: Tue May 16 11:41:27 2006 +0100 [ARM] 3400/1: lpd7a40x: platform headers update Patch from Marc Singer Updates to the lpd7a40x platform headers. Includes support for new architecture, lpd7a400. Signed-off-by: Marc Singer Signed-off-by: Russell King commit 14228a49913850493c7f9eb4501438c32da353f7 Author: Russell King Date: Sun Jun 18 13:00:48 2006 +0100 [SERIAL] PARPORT_SERIAL should depend on SERIAL_8250_PCI Since parport_serial uses symbols from 8250_pci, there should be a dependency between the configuration symbols for these two modules. Problem reported by Andrey Borzenkov Signed-off-by: Russell King commit 2ba72cb754bb091bb24a44e9682f7105110f7f38 Author: David Woodhouse Date: Sun Jun 18 10:22:40 2006 +0100 [JFFS2] Mark XATTR support as experimental, for now Signed-off-by: David Woodhouse commit 2abac1db3522d9f56c695d1b42e77f3e52d4c51a Author: Dave Airlie Date: Sun Jun 18 16:12:27 2006 +1000 intelfb: fixup clock calculation debugging. The debugging code for pll clocks was wrong and causing div by 0. Signed-off-by: Dave Airlie commit 47552c4e555eefe381f3d45140b59a2ea4b16486 Author: Herbert Xu Date: Sat Jun 17 23:00:20 2006 -0700 [ETHTOOL]: Fix UFO typo The function ethtool_get_ufo was referring to ETHTOOL_GTSO instead of ETHTOOL_GUFO. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit d5b9f4c083b0e3102f3101545279f623680cb3a0 Author: Neil Horman Date: Sat Jun 17 22:59:03 2006 -0700 [SCTP]: Fix persistent slowdown in sctp when a gap ack consumes rx buffer. In the event that our entire receive buffer is full with a series of chunks that represent a single gap-ack, and then we accept a chunk (or chunks) that fill in the gap between the ctsn and the first gap, we renege chunks from the end of the buffer, which effectively does nothing but move our gap to the end of our received tsn stream. This does little but move our missing tsns down stream a little, and, if the sender is sending sufficiently large retransmit frames, the result is a perpetual slowdown which can never be recovered from, since the only chunk that can be accepted to allow progress in the tsn stream necessitates that a new gap be created to make room for it. This leads to a constant need for retransmits, and subsequent receiver stalls. The fix I've come up with is to deliver the frame without reneging if we have a full receive buffer and the receiving sockets sk_receive_queue is empty(indicating that the receive buffer is being blocked by a missing tsn). Signed-off-by: Neil Horman Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller commit d7c2c9e3977e4312d093ac092761798d4d47c9e0 Author: Tsutomu Fujii Date: Sat Jun 17 22:58:28 2006 -0700 [SCTP]: Send only 1 window update SACK per message. Right now, every time we increase our rwnd by more then MTU bytes, we trigger a SACK. When processing large messages, this will generate a SACK for almost every other SCTP fragment. However since we are freeing the entire message at the same time, we might as well collapse the SACK generation to 1. Signed-off-by: Tsutomu Fujii Signed-off-by: Vlad Yasevich Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller commit 503b55fd77d11381b1950d1651d3bc782c0cc2cd Author: Sridhar Samudrala Date: Sat Jun 17 22:57:28 2006 -0700 [SCTP]: Don't do CRC32C checksum over loopback. Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller commit 4c9f5d5305a23851e67471b147e0d459a7166717 Author: Vlad Yasevich Date: Sat Jun 17 22:56:08 2006 -0700 [SCTP] Reset rtt_in_progress for the chunk when processing its sack. Signed-off-by: Vlad Yasevich Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller commit 5636bef7324f49e36f05ec8a5f6284e11b1bcca4 Author: Vlad Yasevich Date: Sat Jun 17 22:55:35 2006 -0700 [SCTP]: Reject sctp packets with broadcast addresses. Signed-off-by: Vlad Yasevich Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller commit 402d68c43326d2f0e7e2e9a9013cd4c098d9b87c Author: Vlad Yasevich Date: Sat Jun 17 22:54:51 2006 -0700 [SCTP]: Limit association max_retrans setting in setsockopt. When using ASSOCINFO socket option, we need to limit the number of maximum association retransmissions to be no greater than the sum of all the path retransmissions. This is specified in Section 7.1.2 of the SCTP socket API draft. However, we only do this if the association has multiple paths. If there is only one path, the protocol stack will use the assoc_max_retrans setting when trying to retransmit packets. Signed-off-by: Vlad Yasevich Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller commit c7ce1ae21223fe1f905feba272bc14b87994a57d Author: Tushar Gohad Date: Sat Jun 17 22:54:03 2006 -0700 [PFKEYV2]: Fix inconsistent typing in struct sadb_x_kmprivate. Signed-off-by: Tushar Gohad Signed-off-by: David S. Miller commit c5396a31b20991c856facbce18a2a56d1a14e8d0 Author: YOSHIFUJI Hideaki Date: Sat Jun 17 22:48:48 2006 -0700 [IPV6]: Sum real space for RTAs. This patch fixes RTNLGRP_IPV6_IFINFO netlink notifications. Issue pointed out by Patrick McHardy . Signed-off-by: YOSHIFUJI Hideaki Acked-by: Patrick McHardy Signed-off-by: David S. Miller commit b293acfd3133393a81bcd382eb71a210c9cf9526 Author: David S. Miller Date: Sat Jun 17 22:16:13 2006 -0700 [IRDA]: Use put_unaligned() in irlmp_do_discovery(). irda_device_info->hints[] is byte aligned but is being accessed as a u16 Based upon a patch by Luke Yang . Signed-off-by: David S. Miller commit 2c6cc0d8539f121c3c75aa3641c19b67e8723379 Author: Herbert Xu Date: Sat Jun 17 22:06:45 2006 -0700 [BRIDGE]: Add support for NETIF_F_HW_CSUM devices As it is the bridge will only ever declare NETIF_F_IP_CSUM even if all its constituent devices support NETIF_F_HW_CSUM. This patch fixes this by supporting the first one out of NETIF_F_NO_CSUM, NETIF_F_HW_CSUM, and NETIF_F_IP_CSUM that is supported by all constituent devices. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit 8648b3053bff39a7ee4c711d74268079c928a657 Author: Herbert Xu Date: Sat Jun 17 22:06:05 2006 -0700 [NET]: Add NETIF_F_GEN_CSUM and NETIF_F_ALL_CSUM The current stack treats NETIF_F_HW_CSUM and NETIF_F_NO_CSUM identically so we test for them in quite a few places. For the sake of brevity, I'm adding the macro NETIF_F_GEN_CSUM for these two. We also test the disjunct of NETIF_F_IP_CSUM and the other two in various places, for that purpose I've added NETIF_F_ALL_CSUM. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit 00b7050426da8e7e58c889c5c80a19920d2d41b3 Author: Michael Chan Date: Sat Jun 17 21:58:45 2006 -0700 [TG3]: Convert to non-LLTX Herbert Xu pointed out that it is unsafe to call netif_tx_disable() from LLTX drivers because it uses dev->xmit_lock to synchronize whereas LLTX drivers use private locks. Convert tg3 to non-LLTX to fix this issue. tg3 is a lockless driver where hard_start_xmit and tx completion handling can run concurrently under normal conditions. A tx_lock is only needed to prevent netif_stop_queue and netif_wake_queue race condtions when the queue is full. So whether we use LLTX or non-LLTX, it makes practically no difference. Signed-off-by: Michael Chan Signed-off-by: David S. Miller commit c71302d61f844f766a44e1b04258086cc41f624e Author: Michael Chan Date: Sat Jun 17 21:55:55 2006 -0700 [TG3]: Remove unnecessary tx_lock Remove tx_lock where it is unnecessary. tg3 runs lockless and so it requires interrupts to be disabled and sync'ed, netif_queue and NAPI poll to be stopped before the device can be reconfigured. After stopping everything, it is no longer necessary to get the tx_lock. Signed-off-by: Michael Chan Signed-off-by: David S. Miller commit 35089bb203f44e33b6bbb6c4de0b0708f9a48921 Author: David S. Miller Date: Tue Jun 13 22:33:04 2006 -0700 [TCP]: Add tcp_slow_start_after_idle sysctl. A lot of people have asked for a way to disable tcp_cwnd_restart(), and it seems reasonable to add a sysctl to do that. Signed-off-by: David S. Miller commit 9e1881dec9e3e8f8408551cddfda489857a7ec99 Author: Michael Chan Date: Tue Jun 13 15:04:12 2006 -0700 [BNX2]: Update version and reldate Update driver version to 1.4.42. Signed-off-by: Michael Chan Signed-off-by: David S. Miller commit c86a31f452f7dd132a1765d6d7160b0947f37b14 Author: Michael Chan Date: Tue Jun 13 15:03:47 2006 -0700 [BNX2]: Use CPU native page size Use CPU native page size to determine various ring sizes. This allows order-0 memory allocations on all systems. Added check to limit the page size to 16K since that's the maximum rx ring size that will be used. This will prevent using unnecessarily large page sizes on some architectures with large page sizes. [Suggested by David Miller] Signed-off-by: Michael Chan Signed-off-by: David S. Miller commit 7a6400cd3dbcfc3bbffcdb6dac4ffc957fb50e19 Author: Michael Chan Date: Mon Jun 12 22:22:17 2006 -0700 [BNX2]: Use compressed firmware Change bnx2_fw.h to use compressed text for all CPU images. Signed-off-by: Michael Chan Signed-off-by: David S. Miller commit fba9fe911bb4213c3de1d142fe0ee127cd361a78 Author: Michael Chan Date: Mon Jun 12 22:21:25 2006 -0700 [BNX2]: Add firmware decompression Add functions to decompress firmware before loading to the internal CPUs. Compressing the firmware reduces the driver size significantly. Added file name length sanity check in the gzip header to prevent going past the end of buffer [suggested by DaveM]. Signed-off-by: Michael Chan Signed-off-by: David S. Miller commit 160882722cb21cbe5cead55cf38a5e70fc3af63e Author: Michael Chan Date: Mon Jun 12 22:16:43 2006 -0700 [BNX2]: Allow WoL settings on new 5708 chips Allow WOL settings on 5708 B2 and newer chips that have the problem fixed. Signed-off-by: Michael Chan Signed-off-by: David S. Miller commit cea94db9b496d7fe25bbd3ebd0f24afaac2069d5 Author: Michael Chan Date: Mon Jun 12 22:16:13 2006 -0700 [BNX2]: Add an rx drop counter Add a counter for packets dropped by firmware. Signed-off-by: Michael Chan Signed-off-by: David S. Miller commit bc726a71d2799f0f8b68a17f49d86aa030f64abc Author: Luca De Cicco Date: Sun Jun 11 23:02:19 2006 -0700 [TCP] Westwood: reset RTT min after FRTO RTT_min is updated each time a timeout event occurs in order to cope with hard handovers in wireless scenarios such as UMTS. Signed-off-by: Luca De Cicco Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit b3a92eabe5b67bd207a38ae13dd51f4e08c1f6f7 Author: Luca De Cicco Date: Sun Jun 11 23:01:59 2006 -0700 [TCP] Westwood: bandwidth filter startup The bandwidth estimate filter is now initialized with the first sample in order to have better performances in the case of small file transfers. Signed-off-by: Luca De Cicco Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit b7d7a9e3c900f0733bf2aabdd41e6dbc70eae94b Author: Luca De Cicco Date: Sun Jun 11 23:01:39 2006 -0700 [TCP] Westwood: comment fixes Cleanup some comments and add more references Signed-off-by: Luca De Cicco Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit f61e29018a30c738e1298e1b13be956aa17ee17b Author: Stephen Hemminger Date: Sun Jun 11 23:01:02 2006 -0700 [TCP] Westwood: fix first sample Need to update send sequence number tracking after first ack. Rework of patch from Luca De Cicco. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit bdeb04c6d9a957ae2a51c3033414467b82b2a736 Author: Stephen Hemminger Date: Sun Jun 11 21:20:38 2006 -0700 [NET]: net.ipv4.ip_autoconfig sysctl removal The sysctl net.ipv4.ip_autoconfig is a legacy value that is not used. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit d1e100ba69131bb788e89a07b94b08f6e006725a Author: Alexey Dobriyan Date: Sun Jun 11 20:57:17 2006 -0700 [BNX2]: Endian fixes. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller commit 8ef80aef118e405f2b6505f623830e6e73224f85 Author: Nick Fedchik Date: Sun Jun 11 20:56:02 2006 -0700 [IRDA]: irda-usb.c: STIR421x cleanups This cleans the STIR421x part of the irda-usb code. We also no longer try to load all existing firmwares but only the matching one (according to the USB id we get from the dongle). Signed-off-by: Nick Fedchik Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller commit f8d596211291a8d98efa47ae0261326218f310cf Author: Alexey Dobriyan Date: Sat Jun 10 18:05:35 2006 -0700 [IPX]: Endian bug in ipxrtr_route_packet() Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller commit 3cc0e873986fe594d0e96d07259b11f755325cb2 Author: Herbert Xu Date: Fri Jun 9 16:13:38 2006 -0700 [NET]: Warn in __skb_trim if skb is paged It's better to warn and fail rather than rarely triggering BUG on paths that incorrectly call skb_trim/__skb_trim on a non-linear skb. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit b38dfee3d616ffadb58d4215e3ff9d1d7921031e Author: Herbert Xu Date: Fri Jun 9 16:13:01 2006 -0700 [NET]: skb_trim audit I found a few more spots where pskb_trim_rcsum could be used but were not. This patch changes them to use it. Also, sk_filter can get paged skb data. Therefore we must use pskb_trim instead of skb_trim. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit c8c9f9a3de2c50c876b1068dd41f9a06c5749f80 Author: Herbert Xu Date: Fri Jun 9 16:11:27 2006 -0700 [NET] ppp: Remove unnecessary pskb_may_pull In ppp_receive_nonmp_frame, we call pskb_may_pull(skb, skb->len) if the tailroom is >= 124. This is pointless because this pskb_may_pull is only needed if the skb is non-linear. However, if it is non-linear then the tailroom would be zero. So it can be safely removed. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit 364c6badde0dd62a0a38e5ed67f85d87d6665780 Author: Herbert Xu Date: Fri Jun 9 16:10:40 2006 -0700 [NET]: Clean up skb_linearize The linearisation operation doesn't need to be super-optimised. So we can replace __skb_linearize with __pskb_pull_tail which does the same thing but is more general. Also, most users of skb_linearize end up testing whether the skb is linear or not so it helps to make skb_linearize do just that. Some callers of skb_linearize also use it to copy cloned data, so it's useful to have a new function skb_linearize_cow to copy the data if it's either non-linear or cloned. Last but not least, I've removed the gfp argument since nobody uses it anymore. If it's ever needed we can easily add it back. Misc bugs fixed by this patch: * via-velocity error handling (also, no SG => no frags) Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit 932ff279a43ab7257942cddff2595acd541cc49b Author: Herbert Xu Date: Fri Jun 9 12:20:56 2006 -0700 [NET]: Add netif_tx_lock Various drivers use xmit_lock internally to synchronise with their transmission routines. They do so without setting xmit_lock_owner. This is fine as long as netpoll is not in use. With netpoll it is possible for deadlocks to occur if xmit_lock_owner isn't set. This is because if a printk occurs while xmit_lock is held and xmit_lock_owner is not set can cause netpoll to attempt to take xmit_lock recursively. While it is possible to resolve this by getting netpoll to use trylock, it is suboptimal because netpoll's sole objective is to maximise the chance of getting the printk out on the wire. So delaying or dropping the message is to be avoided as much as possible. So the only alternative is to always set xmit_lock_owner. The following patch does this by introducing the netif_tx_lock family of functions that take care of setting/unsetting xmit_lock_owner. I renamed xmit_lock to _xmit_lock to indicate that it should not be used directly. I didn't provide irq versions of the netif_tx_lock functions since xmit_lock is meant to be a BH-disabling lock. This is pretty much a straight text substitution except for a small bug fix in winbond. It currently uses netif_stop_queue/spin_unlock_wait to stop transmission. This is unsafe as an IRQ can potentially wake up the queue. So it is safer to use netif_tx_disable. The hamradio bits used spin_lock_irq but it is unnecessary as xmit_lock must never be taken in an IRQ handler. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit bf0857ea32addb6bc8b46383604b218b8ec09f19 Author: Patrick McHardy Date: Fri Jun 9 12:18:47 2006 -0700 [NETFILTER]: hashlimit match: fix random initialization hashlimit does: if (!ht->rnd) get_random_bytes(&ht->rnd, 4); ignoring that 0 is also a valid random number. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 2b2283d0302d520f08ded41c2ca17886dfbb865a Author: Patrick McHardy Date: Fri Jun 9 12:18:17 2006 -0700 [NETFILTER]: recent match: missing refcnt initialization Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit a0e889bb1bdc083dbbdb02cce9698765847b841f Author: Patrick McHardy Date: Fri Jun 9 12:17:41 2006 -0700 [NETFILTER]: recent match: fix "sleeping function called from invalid context" create_proc_entry must not be called with locks held. Use a mutex instead to protect data only changed in user context. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 4e5ab4cb85683cf77b507ba0c4d48871e1562305 Author: James Morris Date: Fri Jun 9 00:33:33 2006 -0700 [SECMARK]: Add new packet controls to SELinux Add new per-packet access controls to SELinux, replacing the old packet controls. Packets are labeled with the iptables SECMARK and CONNSECMARK targets, then security policy for the packets is enforced with these controls. To allow for a smooth transition to the new controls, the old code is still present, but not active by default. To restore previous behavior, the old controls may be activated at runtime by writing a '1' to /selinux/compat_net, and also via the kernel boot parameter selinux_compat_net. Switching between the network control models requires the security load_policy permission. The old controls will probably eventually be removed and any continued use is discouraged. With this patch, the new secmark controls for SElinux are disabled by default, so existing behavior is entirely preserved, and the user is not affected at all. It also provides a config option to enable the secmark controls by default (which can always be overridden at boot and runtime). It is also noted in the kconfig help that the user will need updated userspace if enabling secmark controls for SELinux and that they'll probably need the SECMARK and CONNMARK targets, and conntrack protocol helpers, although such decisions are beyond the scope of kernel configuration. Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit 100468e9c05c10fb6872751c1af523b996d6afa9 Author: James Morris Date: Fri Jun 9 00:32:39 2006 -0700 [SECMARK]: Add CONNSECMARK xtables target Add a new xtables target, CONNSECMARK, which is used to specify rules for copying security marks from packets to connections, and for copyying security marks back from connections to packets. This is similar to the CONNMARK target, but is more limited in scope in that it only allows copying of security marks to and from packets, as this is all it needs to do. A typical scenario would be to apply a security mark to a 'new' packet with SECMARK, then copy that to its conntrack via CONNMARK, and then restore the security mark from the connection to established and related packets on that connection. Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit 7c9728c393dceb724d66d696cfabce82151a78e5 Author: James Morris Date: Fri Jun 9 00:31:46 2006 -0700 [SECMARK]: Add secmark support to conntrack Add a secmark field to IP and NF conntracks, so that security markings on packets can be copied to their associated connections, and also copied back to packets as required. This is similar to the network mark field currently used with conntrack, although it is intended for enforcement of security policy rather than network policy. Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit 5e6874cdb8de94cd3c15d853a8ef9c6f4c305055 Author: James Morris Date: Fri Jun 9 00:30:57 2006 -0700 [SECMARK]: Add xtables SECMARK target Add a SECMARK target to xtables, allowing the admin to apply security marks to packets via both iptables and ip6tables. The target currently handles SELinux security marking, but can be extended for other purposes as needed. Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit 984bc16cc92ea3c247bf34ad667cfb95331b9d3c Author: James Morris Date: Fri Jun 9 00:29:17 2006 -0700 [SECMARK]: Add secmark support to core networking. Add a secmark field to the skbuff structure, to allow security subsystems to place security markings on network packets. This is similar to the nfmark field, except is intended for implementing security policy, rather than than networking policy. This patch was already acked in principle by Dave Miller. Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit c749b29fae74ed59c507d84025b3298202b42609 Author: James Morris Date: Fri Jun 9 00:28:25 2006 -0700 [SECMARK]: Add SELinux exports Add and export new functions to the in-kernel SELinux API in support of the new secmark-based packet controls. Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit 29a395eac4c320c570e73f0a90d8953d80da8359 Author: James Morris Date: Fri Jun 9 00:27:28 2006 -0700 [SECMARK]: Add new flask definitions to SELinux Secmark implements a new scheme for adding security markings to packets via iptables, as well as changes to SELinux to use these markings for security policy enforcement. The rationale for this scheme is explained and discussed in detail in the original threads: http://thread.gmane.org/gmane.linux.network/34927/ http://thread.gmane.org/gmane.linux.network/35244/ Examples of policy and rulesets, as well as a full archive of patches for iptables and SELinux userland, may be found at: http://people.redhat.com/jmorris/selinux/secmark/ The code has been tested with various compilation options and in several scenarios, including with 'complicated' protocols such as FTP and also with the new generic conntrack code with IPv6 connection tracking. This patch: Add support for a new object class ('packet'), and associated permissions ('send', 'recv', 'relabelto'). These are used to enforce security policy for network packets labeled with SECMARK, and for adding labeling rules. Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit 3e3ff15e6d8ba931fa9a6c7f9fe711edc77e96e5 Author: Christopher J. PeBenito Date: Fri Jun 9 00:25:03 2006 -0700 [SELINUX]: add security class for appletalk sockets Add a security class for appletalk sockets so that they can be distinguished in SELinux policy. Please apply. Signed-off-by: Stephen Smalley Acked-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit 6f68dc37759b1d6ff3b4d4a9d097605a09f8f043 Author: David S. Miller Date: Thu Jun 8 23:58:52 2006 -0700 [NET]: Fix warnings after LSM-IPSEC changes. Assignment used as truth value in xfrm_del_sa() and xfrm_get_policy(). Wrong argument type declared for security_xfrm_state_delete() when SELINUX is disabled. Signed-off-by: David S. Miller commit 9dadaa19cb11a8db38072a92a3f95deab7a797fb Author: Dave Jones Date: Thu Jun 8 23:42:09 2006 -0700 [NET]: NET_TCPPROBE Kconfig fix Just spotted this typo in a new option. Signed-off-by: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit c8c05a8eec6f1258f6d5cb71a44ee5dc1e989b63 Author: Catherine Zhang Date: Thu Jun 8 23:39:49 2006 -0700 [LSM-IPsec]: SELinux Authorize This patch contains a fix for the previous patch that adds security contexts to IPsec policies and security associations. In the previous patch, no authorization (besides the check for write permissions to SAD and SPD) is required to delete IPsec policies and security assocations with security contexts. Thus a user authorized to change SAD and SPD can bypass the IPsec policy authorization by simply deleteing policies with security contexts. To fix this security hole, an additional authorization check is added for removing security policies and security associations with security contexts. Note that if no security context is supplied on add or present on policy to be deleted, the SELinux module allows the change unconditionally. The hook is called on deletion when no context is present, which we may want to change. At present, I left it up to the module. LSM changes: The patch adds two new LSM hooks: xfrm_policy_delete and xfrm_state_delete. The new hooks are necessary to authorize deletion of IPsec policies that have security contexts. The existing hooks xfrm_policy_free and xfrm_state_free lack the context to do the authorization, so I decided to split authorization of deletion and memory management of security data, as is typical in the LSM interface. Use: The new delete hooks are checked when xfrm_policy or xfrm_state are deleted by either the xfrm_user interface (xfrm_get_policy, xfrm_del_sa) or the pfkey interface (pfkey_spddelete, pfkey_delete). SELinux changes: The new policy_delete and state_delete functions are added. Signed-off-by: Catherine Zhang Signed-off-by: Trent Jaeger Acked-by: James Morris Signed-off-by: David S. Miller commit cec6f7f39c3db7d9f6091bf2f8fc8d520f372719 Author: Andreas Schwab Date: Mon Jun 5 21:21:57 2006 -0700 [CONNECTOR]: Fix warning in cn_queue.c cn_queue.c:130: warning: value computed is not used There is no point in testing the atomic value if the result is thrown away. From Evgeniy: It was created to put implicit smp barrier, but it is not needed there. Signed-off-by: Andreas Schwab Signed-off-by: Evgeniy Polyakov Signed-off-by: David S. Miller commit f86502bfc177f69bbabbedb78ebf710579ae0e54 Author: David S. Miller Date: Mon Jun 5 21:19:24 2006 -0700 [IPV4] icmp: Kill local 'ip' arg in icmp_redirect(). It is typed wrong, and it's only assigned and used once. So just pass in iph->daddr directly which fixes both problems. Based upon a patch by Alexey Dobriyan. Signed-off-by: David S. Miller commit 6d7416535097ed0943bdae8e69c14ba43061cab1 Author: Alexey Dobriyan Date: Mon Jun 5 21:06:41 2006 -0700 [IPV4]: Right prototype of __raw_v4_lookup() All users pass 32-bit values as addresses and internally they're compared with 32-bit entities. So, change "laddr" and "raddr" types to __be32. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller commit 338fcf9886df9ad2873772197a73a57818973316 Author: Alexey Dobriyan Date: Mon Jun 5 21:04:39 2006 -0700 [IPV4] igmp: Fixup struct ip_mc_list::multiaddr type All users except two expect 32-bit big-endian value. One is of ->multiaddr = ->multiaddr variety. And last one is "%08lX". Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller commit 70df2311ee3fc607e7511873d7dade5bd17d593d Author: David S. Miller Date: Mon Jun 5 17:59:20 2006 -0700 [TCP]: Fix compile warning in tcp_probe.c The suseconds_t et al. are not necessarily any particular type on every platform, so cast to unsigned long so that we can use one printf format string and avoid warnings across the board Signed-off-by: David S. Miller commit 738980ffa658c86bd494ebb242ce8e44aff16a9e Author: Stephen Hemminger Date: Mon Jun 5 17:30:56 2006 -0700 [TCP]: Limited slow start for Highspeed TCP Implementation of RFC3742 limited slow start. Added as part of the TCP highspeed congestion control module. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit a42e9d6ce89cfd19aee9f990b7231ce697f0d00f Author: Stephen Hemminger Date: Mon Jun 5 17:30:32 2006 -0700 [TCP]: TCP Probe congestion window tracing This adds a new module for tracking TCP state variables non-intrusively using kprobes. It has a simple /proc interface that outputs one line for each packet received. A sample usage is to collect congestion window and ssthresh over time graphs. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit 72dc5b9225c53310c010b68a70ea97c8c8e24bdf Author: Stephen Hemminger Date: Mon Jun 5 17:30:08 2006 -0700 [TCP]: Minimum congestion window consolidation. Many of the TCP congestion methods all just use ssthresh as the minimum congestion window on decrease. Rather than duplicating the code, just have that be the default if that handle in the ops structure is not set. Minor behaviour change to TCP compound. It probably wants to use this (ssthresh) as lower bound, rather than ssthresh/2 because the latter causes undershoot on loss. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit a4ed25849532728effaa0665c92e08e029e41407 Author: Stephen Hemminger Date: Mon Jun 5 17:29:39 2006 -0700 [TCP]: TCP Compound quad root function The original code did a 64 bit divide directly, which won't work on 32 bit platforms. Rather than doing a 64 bit square root twice, just implement a 4th root function in one pass using Newton's method. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit f890f921040fef6a35e39d15b729af1fd1a35f29 Author: Angelo P. Castellani Date: Mon Jun 5 17:29:09 2006 -0700 [TCP]: TCP Compound congestion control TCP Compound is a sender-side only change to TCP that uses a mixed Reno/Vegas approach to calculate the cwnd. For further details look here: ftp://ftp.research.microsoft.com/pub/tr/TR-2005-86.pdf Signed-off-by: Angelo P. Castellani Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit 76f1017757aa0c308a0b83ca611c9a89ee9a79a4 Author: Bin Zhou Date: Mon Jun 5 17:28:30 2006 -0700 [TCP]: TCP Veno congestion control TCP Veno module is a new congestion control module to improve TCP performance over wireless networks. The key innovation in TCP Veno is the enhancement of TCP Reno/Sack congestion control algorithm by using the estimated state of a connection based on TCP Vegas. This scheme significantly reduces "blind" reduction of TCP window regardless of the cause of packet loss. This work is based on the research paper "TCP Veno: TCP Enhancement for Transmission over Wireless Access Networks." C. P. Fu, S. C. Liew, IEEE Journal on Selected Areas in Communication, Feb. 2003. Original paper and many latest research works on veno: http://www.ntu.edu.sg/home/ascpfu/veno/veno.html Signed-off-by: Bin Zhou Cheng Peng Fu Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit 7c106d7e782bd4805f39da30e81018f861b4b8c5 Author: Wong Hoi Sing Edison Date: Mon Jun 5 17:27:58 2006 -0700 [TCP]: TCP Low Priority congestion control TCP Low Priority is a distributed algorithm whose goal is to utilize only the excess network bandwidth as compared to the ``fair share`` of bandwidth as targeted by TCP. Available from: http://www.ece.rice.edu/~akuzma/Doc/akuzma/TCP-LP.pdf Original Author: Aleksandar Kuzmanovic See http://www-ece.rice.edu/networks/TCP-LP/ for their implementation. As of 2.6.13, Linux supports pluggable congestion control algorithms. Due to the limitation of the API, we take the following changes from the original TCP-LP implementation: o We use newReno in most core CA handling. Only add some checking within cong_avoid. o Error correcting in remote HZ, therefore remote HZ will be keeped on checking and updating. o Handling calculation of One-Way-Delay (OWD) within rtt_sample, sicne OWD have a similar meaning as RTT. Also correct the buggy formular. o Handle reaction for Early Congestion Indication (ECI) within pkts_acked, as mentioned within pseudo code. o OWD is handled in relative format, where local time stamp will in tcp_time_stamp format. Port from 2.4.19 to 2.6.16 as module by: Wong Hoi Sing Edison Hung Hing Lun Signed-off-by: Wong Hoi Sing Edison Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit 2f45c340e09242641d4f11498c3be48b35abb926 Author: Andrew Morton Date: Fri Jun 2 16:29:20 2006 -0700 [LLC]: Fix double receive of SKB. Oops fix from Stephen: remove duplicate rcv() calls. Signed-off-by: Andrew Morton Signed-off-by: David S. Miller commit c45fb1089e714146206d7e295ff337893424c874 Author: Alexey Dobriyan Date: Mon May 29 18:27:32 2006 -0700 [NETFILTER]: PPTP helper: fixup gre_keymap_lookup() return type GRE keys are 16-bit wide. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit ae5b7d8ba2c28d7d9835856fe0ca5f6ec95ea768 Author: Patrick McHardy Date: Mon May 29 18:27:09 2006 -0700 [NETFILTER]: Add SIP connection tracking helper Add SIP connection tracking helper. Originally written by Christian Hentschel , some cleanup, minor fixes and bidirectional SIP support added by myself. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit e44ab66a75e20c02193440a5e27c16c91630109b Author: Patrick McHardy Date: Mon May 29 18:26:47 2006 -0700 [NETFILTER]: H.323 helper: replace internal_net_addr parameter by routing-based heuristic Call Forwarding doesn't need to create an expectation if both peers can reach each other without our help. The internal_net_addr parameter lets the user explicitly specify a single network where this is true, but is not very flexible and even fails in the common case that calls will both be forwarded to outside parties and inside parties. Use an optional heuristic based on routing instead, the assumption is that if bpth the outgoing device and the gateway are equal, both peers can reach each other directly. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit c0d4cfd96dd0cc0dbf49435898808b5553af4822 Author: Jing Min Zhao Date: Mon May 29 18:26:27 2006 -0700 [NETFILTER]: H.323 helper: Add support for Call Forwarding Signed-off-by: Jing Min Zhao Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit c95261693467f0aeac7fafa69860ddfb02bc12f8 Author: Patrick McHardy Date: Mon May 29 18:25:58 2006 -0700 [NETFILTER]: amanda helper: convert to textsearch infrastructure When a port number within a packet is replaced by a differently sized number only the packet is resized, but not the copy of the data. Following port numbers are rewritten based on their offsets within the copy, leading to packet corruption. Convert the amanda helper to the textsearch infrastructure to avoid the copy entirely. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 7d8c50181778b6ba10c2bba9a2f22db9493bb245 Author: Patrick McHardy Date: Mon May 29 18:25:38 2006 -0700 [NETFILTER]: FTP helper: search optimization Instead of skipping search entries for the wrong direction simply index them by direction. Based on patch by Pablo Neira Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 695ecea3299dba2239d1cb4fd4d4e4c95a5b9ce7 Author: Patrick McHardy Date: Mon May 29 18:25:14 2006 -0700 [NETFILTER]: SNMP helper: fix debug module param type debug is the debug level, not a bool. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 89f2e21883b59a6ff1e64d0b4924d06b1c6101ba Author: Patrick McHardy Date: Mon May 29 18:24:58 2006 -0700 [NETFILTER]: ctnetlink: change table dumping not to require an unique ID Instead of using the ID to find out where to continue dumping, take a reference to the last entry dumped and try to continue there. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 3726add76643c715d437aceda320d319153b6113 Author: Patrick McHardy Date: Mon May 29 18:24:39 2006 -0700 [NETFILTER]: ctnetlink: fix NAT configuration The current configuration only allows to configure one manip and overloads conntrack status flags with netlink semantic. Signed-off-by: Patrick Mchardy Signed-off-by: David S. Miller commit 997ae831ade74bdaed4172b1c02060b9efd6e206 Author: Eric Leblond Date: Mon May 29 18:24:20 2006 -0700 [NETFILTER]: conntrack: add fixed timeout flag in connection tracking Add a flag in a connection status to have a non updated timeout. This permits to have connection that automatically die at a given time. Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 39a27a35c5c1b5be499a0576a35c45a011788bf8 Author: Patrick McHardy Date: Mon May 29 18:23:54 2006 -0700 [NETFILTER]: conntrack: add sysctl to disable checksumming Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 6442f1cf897643d4ca597f2f7d3464b765bae960 Author: Patrick McHardy Date: Mon May 29 18:21:53 2006 -0700 [NETFILTER]: conntrack: don't call helpers for related ICMP messages None of the existing helpers expects to get called for related ICMP packets and some even drop them if they can't parse them. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 404bdbfd242cb99ca0e9d3eb5fbb5bcd54123081 Author: Patrick McHardy Date: Mon May 29 18:21:34 2006 -0700 [NETFILTER]: recent match: replace by rewritten version Replace the unmaintainable ipt_recent match by a rewritten version that should be fully compatible. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit f3389805e53a13bd969ee1c8fc5a4137b7c6c167 Author: Patrick McHardy Date: Mon May 29 18:21:00 2006 -0700 [NETFILTER]: x_tables: add statistic match Add statistic match which is a combination of the nth and random matches. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 62b7743483b402f8fb73545d5d487ca714e82766 Author: Patrick McHardy Date: Mon May 29 18:20:32 2006 -0700 [NETFILTER]: x_tables: add quota match Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 957dc80ac30f3c4d53259fa936df807663ba54fa Author: Patrick McHardy Date: Mon May 29 18:19:56 2006 -0700 [NETFILTER]: x_tables: add SCTP/DCCP support where missing Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 3e72b2fe5b31791f976350b023b7a37ef59c02c1 Author: Patrick McHardy Date: Mon May 29 18:19:19 2006 -0700 [NETFILTER]: x_tables: remove some unnecessary casts Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller commit 73654d61e556483ad324b90989eae26b22df6ef6 Author: Herbert Xu Date: Sat May 27 23:06:33 2006 -0700 [IPSEC] xfrm: Use IPPROTO_MAX instead of 256 The size of the type_map array (256) comes from the number of IP protocols, i.e., IPPROTO_MAX. This patch is based on a suggestion from Ingo Oeser. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit 31a4ab93025719e62e7cf7ce899f71c34ecde5a0 Author: Herbert Xu Date: Sat May 27 23:06:13 2006 -0700 [IPSEC] proto: Move transport mode input path into xfrm_mode_transport Now that we have xfrm_mode objects we can move the transport mode specific input decapsulation code into xfrm_mode_transport. This removes duplicate code as well as unnecessary header movement in case of tunnel mode SAs since we will discard the original IP header immediately. This also fixes a minor bug for transport-mode ESP where the IP payload length is set to the correct value minus the header length (with extension headers for IPv6). Of course the other neat thing is that we no longer have to allocate temporary buffers to hold the IP headers for ESP and IPComp. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit b59f45d0b2878ab76f8053b0973654e6621828ee Author: Herbert Xu Date: Sat May 27 23:05:54 2006 -0700 [IPSEC] xfrm: Abstract out encapsulation modes This patch adds the structure xfrm_mode. It is meant to represent the operations carried out by transport/tunnel modes. By doing this we allow additional encapsulation modes to be added without clogging up the xfrm_input/xfrm_output paths. Candidate modes include 4-to-6 tunnel mode, 6-to-4 tunnel mode, and BEET modes. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit 546be2405be119ef55467aace45f337a16e5d424 Author: Herbert Xu Date: Sat May 27 23:03:58 2006 -0700 [IPSEC] xfrm: Undo afinfo lock proliferation The number of locks used to manage afinfo structures can easily be reduced down to one each for policy and state respectively. This is based on the observation that the write locks are only held by module insertion/removal which are very rare events so there is no need to further differentiate between the insertion of modules like ipv6 versus esp6. The removal of the read locks in xfrm4_policy.c/xfrm6_policy.c might look suspicious at first. However, after you realise that nobody ever takes the corresponding write lock you'll feel better :) As far as I can gather it's an attempt to guard against the removal of the corresponding modules. Since neither module can be unloaded at all we can leave it to whoever fixes up IPv6 unloading :) Signed-off-by: Herbert Xu Signed-off-by: David S. Miller commit 9cb3528cdbffc513eb9fb8faa45d41e397355830 Author: Michael Chan Date: Sat Jun 17 21:28:28 2006 -0700 [TG3]: update version and reldate Update version to 3.60. Signed-off-by: Michael Chan Signed-off-by: David S. Miller commit df3e6548186f0baa727cd6d3a492891854bd31f2 Author: Michael Chan Date: Fri May 26 17:48:07 2006 -0700 [TG3]: Add recovery logic when MMIOs are re-ordered Add recovery logic when we suspect that the system is re-ordering MMIOs. Re-ordered MMIOs to the send mailbox can cause bogus tx completions and hit BUG_ON() in the tx completion path. tg3 already has logic to handle re-ordered MMIOs by flushing the MMIOs that must be strictly ordered (such as the send mailbox). Determining when to enable the flush is currently a manual process of adding known chipsets to a list. The new code replaces the BUG_ON() in the tx completion path with the call to tg3_tx_recover(). It will set the TG3_FLAG_MBOX_WRITE_REORDER flag and reset the chip later in the workqueue to recover and start flushing MMIOs to the mailbox. A message to report the problem will be printed. We will then decide whether or not to add the host bridge to the list of chipsets that do re-ordering. We may add some additional code later to print the host bridge's ID so that the user can report it more easily. The assumption that re-ordering can only happen on x86 systems is also removed. Signed-off-by: Michael Chan Signed-off-by: David S. Miller commit 30b6c28d2aca4669f2e609ad5d77ea2a6cf0dd3a Author: Michael Chan Date: Fri May 26 17:44:45 2006 -0700 [TG3]: Add 5786 PCI ID Add PCI ID for BCM5786 which is a variant of 5787. Signed-off-by: Michael Chan Signed-off-by: David S. Miller commit 898b1d16f8230fb912a0c2248df685735c6ceda3 Author: Samuel Ortiz Date: Thu May 25 16:21:10 2006 -0700 [IRDA]: ali-ircc: using device model power management This patch gets rid of the old power management code and now uses the device model for the ali-ircc driver. Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller commit bc1d6937e6cf4e81a5afeae2c9cf35ffb0905ba5 Author: Christoph Hellwig Date: Thu May 25 16:20:19 2006 -0700 [IRDA]: stir4200, switching to the kthread API stir4200 uses a kernel thread for its TX/RX operations, and it is now converted to the kernel kthread API. Tested on an STIR4200 based dongle. Signed-off-by: Christoph Hellwig Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller commit c6ae522e3a50fc1ec483d7f03ece9c7a25e6de95 Author: Samuel Ortiz Date: Thu May 25 16:19:22 2006 -0700 [IRDA]: Initial support for MCS7780 based dongles The MosChip MCS7780 chipset is an IrDA USB bridge that doesn't conform with the IrDA-USB standard and thus needs its separate driver. Tested on an actual MCS7780 based dongle. Original implementation by Brian Pugh Signed-off-by: Samuel Ortiz Signed-off-by: David S. Miller commit 15986e1aadbbf40a331cddd0470bb434d156431d Author: David S. Miller Date: Thu May 25 16:11:14 2006 -0700 [TCP]: tcp_rcv_rtt_measure_ts() call in pure-ACK path is superfluous We only want to take receive RTT mesaurements for data bearing frames, here in the header prediction fast path for a pure-sender, we know that we have a pure-ACK and thus the checks in tcp_rcv_rtt_mesaure_ts() will not pass. Signed-off-by: David S. Miller commit 11dc1f36a6701b502ecb695f308aae46ede8bac6 Author: Stephen Hemminger Date: Thu May 25 16:00:12 2006 -0700 [BRIDGE]: netlink interface for link management Add basic netlink support to the Ethernet bridge. Including: * dump interfaces in bridges * monitor link status changes * change state of bridge port For some demo programs see: http://developer.osdl.org/shemminger/prototypes/brnl.tar.gz These are to allow building a daemon that does alternative implementations of Spanning Tree Protocol. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit c090971326db094ed702c1f8f2dbe04b7e3b8f27 Author: Stephen Hemminger Date: Thu May 25 15:59:33 2006 -0700 [BRIDGE]: fix module startup error handling Return address in use, if some other kernel code has the SAP. Propogate out error codes from netfilter registration and unwind. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit 9ef513bed68534110727381ab652f06756803f5a Author: Stephen Hemminger Date: Thu May 25 15:58:54 2006 -0700 [BRIDGE]: optimize conditional in forward path Small optimizations of bridge forwarding path. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit bc0e646796928918e45b6465e02616f2fe65c3c1 Author: Stephen Hemminger Date: Thu May 25 15:10:37 2006 -0700 [LLC]: add multicast support for datagrams Allow mulitcast reception of datagrams (similar to UDP). All sockets bound to the same SAP receive a clone. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit 8f182b494f87799d6ae20a1401825c516da46081 Author: Stephen Hemminger Date: Thu May 25 15:10:02 2006 -0700 [LLC]: allow applications to get copy of kernel datagrams It is legal for an application to bind to a SAP that is also being used by the kernel. This happens if the bridge module binds to the STP SAP, and the user wants to have a daemon for STP as well. It is possible to have kernel doing STP on one bridge, but let application do RSTP on another bridge. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit 23dbe7912dad6be71bb9e69cb819d05e2442d362 Author: Stephen Hemminger Date: Thu May 25 15:09:37 2006 -0700 [LLC]: use rcu_dereference on receive handler The receive hander pointer might be modified during network changes of protocol. So use rcu_dereference (only matters on alpha). Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit 29efcd2666b3a465b40aa07ef1f4d79847303e2f Author: Stephen Hemminger Date: Thu May 25 15:08:59 2006 -0700 [LLC]: allow datagram recvmsg LLC receive is broken for SOCK_DGRAM. If an application does recv() on a datagram socket and there is no data present, don't return "not connected". Instead, just do normal datagram semantics. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller commit aecbd4e45c2e469e0452ffb2c0b0d881e2815bb8 Author: Stephen Hemminger Date: Thu May 25 15:08:30 2006 -0700 [LLC]: use more efficient ether address routines Use more cache efficient Ethernet address manipulation functions in etherdevice.h. Signed-off-by: Stephen Hemminger commit 17f3ae08b6e7fd778371f2cafbd1c988a67ee343 Author: Andrew Morton Date: Thu May 25 13:26:53 2006 -0700 [I/OAT]: Do not use for_each_cpu(). for_each_cpu() is going away (and is gone in -mm). Signed-off-by: Andrew Morton Signed-off-by: Chris Leech Signed-off-by: David S. Miller commit 1a2449a87bb7606113b1aa1a9d3c3e78ef189a1c Author: Chris Leech Date: Tue May 23 18:05:53 2006 -0700 [I/OAT]: TCP recv offload to I/OAT Locks down user pages and sets up for DMA in tcp_recvmsg, then calls dma_async_try_early_copy in tcp_v4_do_rcv Signed-off-by: Chris Leech Signed-off-by: David S. Miller commit 9593782585e0cf70babe787a8463d492a68b1744 Author: Chris Leech Date: Tue May 23 18:02:55 2006 -0700 [I/OAT]: Add a sysctl for tuning the I/OAT offloaded I/O threshold Any socket recv of less than this ammount will not be offloaded Signed-off-by: Chris Leech Signed-off-by: David S. Miller commit 624d1164730d58a494cc5aa4afa37d02c41e83a7 Author: Chris Leech Date: Tue May 23 18:01:28 2006 -0700 [I/OAT]: Make sk_eat_skb I/OAT aware. Add an extra argument to sk_eat_skb, and make it move early copied packets to the async_wait_queue instead of freeing them. Signed-off-by: Chris Leech Signed-off-by: David S. Miller commit 0e4b4992b8007c6b62ec143cbbb292f98813ca11 Author: Chris Leech Date: Tue May 23 18:00:16 2006 -0700 [I/OAT]: Rename cleanup_rbuf to tcp_cleanup_rbuf and make non-static Needed to be able to call tcp_cleanup_rbuf in tcp_input.c for I/OAT Signed-off-by: Chris Leech Signed-off-by: David S. Miller commit 97fc2f0848c928c63c2ae619deee61a0b1107b69 Author: Chris Leech Date: Tue May 23 17:55:33 2006 -0700 [I/OAT]: Structure changes for TCP recv offload to I/OAT Adds an async_wait_queue and some additional fields to tcp_sock, and a dma_cookie_t to sk_buff. Signed-off-by: Chris Leech Signed-off-by: David S. Miller commit de5506e155276d385712c2aa1c2d9a27cd4ed947 Author: Chris Leech Date: Tue May 23 17:50:37 2006 -0700 [I/OAT]: Utility functions for offloading sk_buff to iovec copies Provides for pinning user space pages in memory, copying to iovecs, and copying from sk_buffs including fragmented and chained sk_buffs. Signed-off-by: Chris Leech Signed-off-by: David S. Miller commit db21733488f84a596faaad0d05430b3f51804692 Author: Chris Leech Date: Sat Jun 17 21:24:58 2006 -0700 [I/OAT]: Setup the networking subsystem as a DMA client Attempts to allocate per-CPU DMA channels Signed-off-by: Chris Leech Signed-off-by: David S. Miller commit 57c651f74cd8383df10a648e677902849de1bc0b Author: David S. Miller Date: Tue May 23 17:39:49 2006 -0700 [I/OAT]: Move PCI_DEVICE_ID_INTEL_IOAT to linux/pci_ids.h Signed-off-by: David S. Miller commit 6b00c92c4b26428cd80e966380c07103556f7b14 Author: David S. Miller Date: Tue May 23 17:37:58 2006 -0700 [I/OAT]: ioatdma.c needs linux/dma-mapping.h For DMA_*_MASK defines. Signed-off-by: David S. Miller commit 0bbd5f4e97ff9c057b385a1886b4aed1fb0300f1 Author: Chris Leech Date: Tue May 23 17:35:34 2006 -0700 [I/OAT]: Driver for the Intel(R) I/OAT DMA engine Adds a new ioatdma driver Signed-off-by: Chris Leech Signed-off-by: David S. Miller commit c13c8260da3155f2cefb63b0d1b7dcdcb405c644 Author: Chris Leech Date: Tue May 23 17:18:44 2006 -0700 [I/OAT]: DMA memcpy subsystem Provides an API for offloading memory copies to DMA devices Signed-off-by: Chris Leech Signed-off-by: David S. Miller commit 9ead190bfde2a434c74ea604382d08acb2eceef5 Author: Roland Dreier Date: Sat Jun 17 20:44:49 2006 -0700 IB/uverbs: Don't serialize with ib_uverbs_idr_mutex Currently, all userspace verbs operations that call into the kernel are serialized by ib_uverbs_idr_mutex. This can be a scalability issue for some workloads, especially for devices driven by the ipath driver, which needs to call into the kernel even for datapath operations. Fix this by adding reference counts to the userspace objects, and then converting ib_uverbs_idr_mutex into a spinlock that only protects the idrs long enough to take a reference on the object being looked up. Because remove operations may fail, we have to do a slightly funky two-step deletion, which is described in the comments at the top of uverbs_cmd.c. This also still leaves ib_uverbs_idr_lock as a single lock that is possibly subject to contention. However, the lock hold time will only be a single idr operation, so multiple threads should still be able to make progress, even if ib_uverbs_idr_lock is being ping-ponged. Surprisingly, these changes even shrink the object code: add/remove: 23/5 grow/shrink: 4/21 up/down: 633/-693 (-60) Signed-off-by: Roland Dreier commit c93b6fbaa99bb3a1552e14317296be14dde51dfb Author: Roland Dreier Date: Sat Jun 17 20:37:41 2006 -0700 IB/mthca: Make all device methods truly reentrant Documentation/infiniband/core_locking.txt says: All of the methods in struct ib_device exported by a low-level driver must be fully reentrant. The low-level driver is required to perform all synchronization necessary to maintain consistency, even if multiple function calls using the same object are run simultaneously. However, mthca's modify_qp, modify_srq and resize_cq methods are currently not reentrant. Add a mutex to the QP, SRQ and CQ structures so that these calls can be properly serialized. Signed-off-by: Roland Dreier commit c9c5d9feef86debee4d8e77a738ad86877cf371a Author: Roland Dreier Date: Sat Jun 17 20:37:41 2006 -0700 IB/mthca: Fix memory leak on modify_qp error paths Some error paths after the mthca_alloc_mailbox() call in mthca_modify_qp() just do a "return -EINVAL" without freeing the mailbox. Convert these returns to "goto out" to avoid leaking the mailbox storage. Signed-off-by: Roland Dreier commit 3463175d6ee55fdbd5cda2a03415e2068599b2b7 Author: Roland Dreier Date: Sat Jun 17 20:37:40 2006 -0700 IB/uverbs: Factor out common idr code Factor out common code for adding a userspace object to an idr into a function idr_add_uobj(). This shrinks both the source and object code: add/remove: 1/0 grow/shrink: 0/6 up/down: 57/-220 (-163) function old new delta idr_add_uobj - 57 +57 ib_uverbs_create_ah 543 512 -31 ib_uverbs_create_srq 662 630 -32 ib_uverbs_reg_mr 737 699 -38 ib_uverbs_create_cq 639 600 -39 ib_uverbs_alloc_pd 485 446 -39 ib_uverbs_create_qp 1020 979 -41 Signed-off-by: Roland Dreier commit 92b1582268e269b3a9e54e186e740396f0f2012b Author: Roland Dreier Date: Sat Jun 17 20:37:40 2006 -0700 IB/uverbs: Don't decrement usecnt on error paths In error paths when destroying an object, uverbs should not decrement associated objects' usecnt, since ib_dereg_mr(), ib_destroy_qp(), etc. already do that. Signed-off-by: Roland Dreier commit 77f76013e3ffda605b20184db5862ce1efcb6f5a Author: Ganapathi CH Date: Sat Jun 17 20:37:40 2006 -0700 IB/uverbs: Release lock on error path If ibdev->alloc_ucontext() fails then ib_uverbs_get_context() does not unlock file->mutex before returning error. Signed-off by: Ganapathi CH Signed-off-by: Roland Dreier commit ca222c6b2c48e1e0be330a55611ba394251330cb Author: Sean Hefty Date: Sat Jun 17 20:37:40 2006 -0700 IB/cm: Use address handle helpers Use new ib_init_ah_from_wc() and ib_init_ah_from_path() helper functions to clean up the IB CM. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit 6d969a471ba107d94cf03dab3c69f45b9733f500 Author: Sean Hefty Date: Sat Jun 17 20:37:39 2006 -0700 IB/sa: Add ib_init_ah_from_path() Add a call to initialize address handle attributes given a path record. This is used by the CM, and would be useful for users of UD QPs. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit 4e00d69454a8747798de11dc4eeef1edeee5ce98 Author: Sean Hefty Date: Sat Jun 17 20:37:39 2006 -0700 IB: Add ib_init_ah_from_wc() Add a function to initialize address handle attributes from a work completion. This functionality is duplicated by both verbs and the CM. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit 75af9088514432ef0c1052ba3767ceb0beb6f101 Author: Sean Hefty Date: Sat Jun 17 20:37:39 2006 -0700 IB/ucm: Get rid of duplicate P_Key parameter The P_Key is provided into a SIDR REQ in two places, once as a parameter, and again in the path record. Remove the P_Key as a parameter and always use the one given in the path record. This change has no practical effect on ABI functionality. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit 526b4caa0a48382115fa9d8f7d8caf68dbcaa2bf Author: Ishai Rabinovitz Date: Sat Jun 17 20:37:38 2006 -0700 IB/srp: Factor out common request reset code Misc cleanups in ib_srp: 1) I think that it is more efficient to move the req entries from req_list to free_list in srp_reconnect_target (rather than rebuild the free_list). (In any case this code is shorter). 2) This allows us to reuse code in srp_reset_device and srp_reconnect_target and call a new function srp_reset_req. Signed-off-by: Ishai Rabinovitz Signed-off-by: Roland Dreier commit 0c0450db31481aa01a04e7faecc93ee6841972d6 Author: Ramachandra K Date: Sat Jun 17 20:37:38 2006 -0700 IB/srp: Support SRP rev. 10 targets There has been a change in the format of port identifiers between revision 10 of the SRP specification and the current revision 16A. Revision 10 specifies port identifier format as lower 8 bytes : GUID upper 8 bytes : Extension Whereas revision 16A specifies it as lower 8 bytes : Extension upper 8 bytes : GUID There are older targets (e.g. SilverStorm Virtual Fibre Channel Bridge) which conform to revision 10 of the SRP specification. The I/O class of revision 10 is 0xFF00 and the I/O class of revision 16A is 0x0100. For supporting older targets, this patch: 1) Adds a new optional target creation parameter "io_class". Default value of io_class is 0x0100 (i.e. revision 16A) 2) Uses the correct port identifier format for targets with IO class of 0xFF00 (i.e. conforming to revision 10) Signed-off-by: Ramachandra K Signed-off-by: Roland Dreier commit 73c0996b1ca60338fa50e42acfcebd32b7636a8b Author: Ramachandra K Date: Sat Jun 17 20:37:38 2006 -0700 [SCSI] srp.h: Add I/O Class values Add enum values for I/O Class values from rev. 10 and rev. 16a SRP drafts. The values are used to detect targets that implement obsolete revisions of SRP, so that the initiator can use the old format for port identifier when connecting to them. Signed-off-by: Ramachandra K Signed-off-by: Roland Dreier commit 6c8c1aa25d213a288df381f431ce5b6a155146ec Author: Or Gerlitz Date: Sat Jun 17 20:37:37 2006 -0700 IB/fmr: Use device's max_map_map_per_fmr attribute in FMR pool. When creating a FMR pool, query the IB device and use the returned max_map_map_per_fmr attribute as for the max number of FMR remaps. If the device does not suport querying this attribute, use the original IB_FMR_MAX_REMAPS (32) default. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier commit d4cb0784fd1ea99ef3d20526811bd5608146fe60 Author: Or Gerlitz Date: Sat Jun 17 20:37:37 2006 -0700 IB/mthca: Fill in max_map_per_fmr device attribute Report the true max_map_per_fmr value from mthca_query_device(), taking into account the change in FMR remapping introduced by the Sinai performance optimization. Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier commit 6eddb5cb906ac5c9a17a1b76464eadacd88b6c92 Author: Roland Dreier Date: Sat Jun 17 20:37:37 2006 -0700 IB/ipath: Add client reregister event generation Generate a client reregister event instead of a LID change event when client reregister bit is set. Signed-off-by: Roland Dreier commit 12bbb2b7be7f5564952ebe0196623e97464b8ac5 Author: Leonid Arsh Date: Sat Jun 17 20:37:36 2006 -0700 IB/mthca: Add client reregister event generation Change the mthca snoop of MADs that set PortInfo to check if the SM has set the client reregister bit, and if it has, generate a client reregister event. If the bit is not set, just generate a LID change event as usual. Signed-off-by: Leonid Arsh Signed-off-by: Roland Dreier commit da2ab62ab5e430e6ffafc2d0e6046dcd2780f570 Author: Leonid Arsh Date: Sat Jun 17 20:37:36 2006 -0700 IB: Move struct port_info from ipath to Move ipath's struct port_info into , so that it can be used by mthca to implement client reregister support. Remove the __attribute__((packed)) because all the members of the struct are naturally aligned anyway. Signed-off-by: Leonid Arsh Signed-off-by: Roland Dreier commit 508e434123b136c96d1bf989e8d4ab0c8d7498b1 Author: Leonid Arsh Date: Sat Jun 17 20:37:36 2006 -0700 IPoIB: Handle client reregister events Handle client reregister events by treating them just like LID or SM changes -- flush all cached paths and rejoin multicast groups. Signed-off-by: Leonid Arsh Signed-off-by: Roland Dreier commit 63942c9a981ecfa2aabfb27ff1a87b88f2ee9f5b Author: Leonid Arsh Date: Sat Jun 17 20:37:35 2006 -0700 IB: Add client reregister event type Add IB_EVENT_CLIENT_REREGISTER to enum so low-level drivers can generate "client reregister" events. Signed-off-by: Leonid Arsh Signed-off-by: Roland Dreier commit 37c22a77212c13201497378cc8becc5c95d0f3f5 Author: Jack Morgenstein Date: Mon May 29 19:14:05 2006 +0300 IPoIB: Fix kernel unaligned access on ia64 Fix misaligned access faults on ia64: never cast a misaligned neighbour->ha + 4 pointer to union ib_gid type; pass a void * pointer instead. The memcpy was being optimized to use full word accesses because the compiler thought that union ib_gid is always aligned. The cast in IPOIB_GID_ARG is safe, since it is fixed to access each byte separately. Signed-off-by: Jack Morgenstein Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier commit 31c02e215700c2b704d9441f629ae87bb9aeb561 Author: Roland Dreier Date: Sat Jun 17 20:37:34 2006 -0700 IPoIB: Avoid using stale last_send counter when reaping AHs The comparisons of priv->tx_tail to ah->last_send in ipoib_free_ah() and ipoib_post_receive() are slightly unsafe, because priv->tx_lock is not held and hence a stale value of ah->last_send might be used, which would lead to freeing an AH before the driver was really done with it. The simple way to fix this is to the optimization of early free from ipoib_free_ah() and unconditionally queue AHs for reaping, and then take priv->tx_lock in __ipoib_reap_ah(). Signed-off-by: Roland Dreier commit 9874e746550fbd366484621b8838b98589bb2a15 Author: Jack Morgenstein Date: Sat Jun 17 20:37:34 2006 -0700 IB/mad: Check GID/LID when matching requests Check GID/LID for requester side when searching for request which matches received response. This is in order to guarantee uniqueness if the same TID is used when requesting via multiple source LIDs (when LMC is not zero). Use ports' cached LMC to perform the check. Further, do not perform LID check for direct-routed packets, since the permissive LID makes a proper check impossible. Signed-off-by: Jack Morgenstein Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit 6fb9cdbf2cdb2ea187e57ec2e16cc59df2adf86a Author: Jack Morgenstein Date: Sat Jun 17 20:37:34 2006 -0700 IB: Add caching of ports' LMC Add an LMC cache to struct ib_device, and add a function ib_get_cached_lmc() to query the cache. Signed-off-by: Jack Morgenstein Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit 856c256f883f027a14b546164294b4a86fea81a4 Author: Michael S. Tsirkin Date: Thu May 25 14:51:33 2006 -0700 IB/cm: remove unneeded flush_workqueue destroy_workqueue() already does flush_workqueue(). Signed-off-by: Michael S. Tsirkin Signed-off-by: Sean Hefty commit 4be10c1e6dcafec993ac4f9abfa5fdcd83728302 Author: Sean Hefty Date: Thu May 25 10:03:23 2006 -0700 IB/ucm: convert semaphore to mutex Convert semaphore in ib_ucm_file to a real mutex. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit 6bfa24fa3e189269e113197a80e12862c211b3d3 Author: Roland Dreier Date: Sat Jun 17 20:37:33 2006 -0700 IB/srp: Get rid of "Target has req_lim 0" messages It's perfectly valid for a connection to an SRP target to have a request limit of 0, so get rid of the message about it, which can spam kernel logs even with printk_ratelimit(). Keep a count of such events in a "zero_req_lim" SCSI host attribute instead, so someone who cares can look at the statistics. Signed-off-by: Roland Dreier commit b7ac4ab497e44cba75fb0e9e5afca06776518934 Author: Ishai Rabinovitz Date: Sat Jun 17 20:37:32 2006 -0700 IB/srp: Handle DREQ events from CM Handle IB_CM_DREQ_ERROR and IB_CM_DREQ_RECEIVED events from the CM, instead of just printing "Unhandled CM event". In the case of DREQ_ERROR, just ignore the event -- a TIMEWAIT_EXIT will be generated also. For DREQ_RECEIVED, send a DREP in response to shut the connection down cleanly. Signed-off-by: Ishai Rabinovitz Signed-off-by: Roland Dreier commit ac83cbaa9a41344c3adf329ede607e58d887f354 Author: Roland Dreier Date: Sat Jun 17 20:37:32 2006 -0700 IPoIB: Mention RFC numbers in documentation Now that the IETF has released RFCs covering IPoIB, give the numbers in the documentation for IPoIB. Signed-off-by: Roland Dreier commit 74b0a15b5e18e44206c98419745a472c3d28e561 Author: Vu Pham Date: Sat Jun 17 20:37:32 2006 -0700 IB/srp: Allow sg_tablesize to be adjusted Make the sg_tablesize used by SRP adjustable at module load time via a module parameter. Calculate the corresponding IU length required to support this. Signed-off-by: Vu Pham Signed-off-by: Roland Dreier commit 52fb2b50c4baa1430064c1e6c1c7df473d469df1 Author: Vu Pham Date: Sat Jun 17 20:37:31 2006 -0700 IB/srp: Allow cmd_per_lun to be set per target port Allow userspace to throttle traffic on a given connection to a target port by adding "max_cmd_per_lun=xyz" to lower the cmd_per_lun value set for that scsi_host. Signed-off-by: Vu Pham Signed-off-by: Roland Dreier commit 0c5b395239cdea4db3d9c23a5738fdaf3b9ada4c Author: Ishai Rabinovitz Date: Sat Jun 17 20:37:31 2006 -0700 IB/srp: Clean up loop in srp_remove_one() Interrupts will always be enabled in srp_remove_one(), so spin_lock_irq() can be used instead of spin_lock_irqsave(). Also, the loop takes target->scsi_host->host_lock, so target->state can just be set to SRP_TARGET_REMOVED witout testing the old value. Signed-off-by: Ishai Rabinovitz Signed-off-by: Roland Dreier commit 403a496fd4af3036c12e1f9c90a89cf846fadd35 Author: Roland Dreier Date: Sat Jun 17 20:37:31 2006 -0700 IB: Make needlessly global ib_mad_cache static Signed-off-by: Roland Dreier commit b3589fd49067bab9fe0c60430860e6befbd5ba37 Author: Matthew Wilcox Date: Sat Jun 17 20:37:30 2006 -0700 IB/srp: Change target_mutex to a spinlock The SRP driver never sleeps while holding target_mutex, and it's just used to protect some simple list operations, so hold times will be short. So just convert it to a spinlock, which is smaller and faster. Signed-off-by: Matthew Wilcox Signed-off-by: Roland Dreier commit 549c5fc2c8149498118f2494a1b6a4938ca05985 Author: Matthew Wilcox Date: Sat Jun 17 20:37:30 2006 -0700 IB/srp: Get rid of unneeded use of list_for_each_entry_safe() list_for_each_entry_safe() is used in one place where the list isn't modified. So just change it to list_for_each_entry(). Signed-off-by: Matthew Wilcox Signed-off-by: Roland Dreier commit 1962a4a1e4b3716aa836ebeb5b80c804a7f7c5ba Author: Matthew Wilcox Date: Sat Jun 17 20:37:30 2006 -0700 IB/srp: Use SCAN_WILD_CARD from SCSI headers SCAN_WILD_CARD is indeed available from , which is already included. So get rid of private hack. Signed-off-by: Matthew Wilcox Signed-off-by: Roland Dreier commit e9cd59418f049966a690372c4919e98c88bb119b Author: Roland Dreier Date: Sat Jun 17 20:37:30 2006 -0700 IB/mthca: Convert FW commands to use wait_for_completion_timeout() The kernel has had wait_for_completion_timeout() for a long time now. mthca should use it to handle FW commands timing out, instead of implementing the same thing in a much more complicated way by using wait_for_completion() along with a timer that does complete(). Signed-off-by: Roland Dreier commit f5358a172f79e3f995919224401b25637f4324f6 Author: Roland Dreier Date: Sat Jun 17 20:37:29 2006 -0700 IB/srp: Use FMRs to map gather/scatter lists Create an SRP FMR pool on HCAs that support FMRs, and use FMRs to map gather/scatter lists that have more than one entry into a single memory region that appears virtually contiguous to the SRP target (which is the RDMA initiator). This patch bails out on FMR mapping for SCSI commands where the gather/scatter list cannot be mapped into a single FMR because there are sub-page-sized entries in middle of the list. An unaligned start or end of the list is OK. Based on a patch by Vu Pham . Signed-off-by: Roland Dreier commit a26026c1221c3e78e6e9f156994c41fb74e99022 Author: Michael S. Tsirkin Date: Sat Jun 17 20:37:29 2006 -0700 IB/mthca: Remove dead code Kill some dead code in mthca_eq.c Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier commit e51060f08a61965c4dd91516d82fe90617152590 Author: Sean Hefty Date: Sat Jun 17 20:37:29 2006 -0700 IB: IP address based RDMA connection manager Kernel connection management agent over InfiniBand that connects based on IP addresses. The agent defines a generic RDMA connection abstraction to support clients wanting to connect over different RDMA devices. The agent also handles RDMA device hotplug events on behalf of clients. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit 7025fcd36bd62af2c6ca0ea3490c00b216c4d168 Author: Sean Hefty Date: Sat Jun 17 20:37:28 2006 -0700 IB: address translation to map IP toIB addresses (GIDs) Add an address translation service that maps IP addresses to InfiniBand GID addresses using IPoIB. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit a1e8733e557bb390e13aa00ef044a6022c8d0bb2 Author: Sean Hefty Date: Sat Jun 17 20:37:28 2006 -0700 [NET]: Export ip_dev_find() Export ip_dev_find() to allow locating a net_device given an IP address. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit 6e61d04f2d8c7ac4f67e1f498ed2a2a3ad8edaa3 Author: Sean Hefty Date: Sat Jun 17 20:37:28 2006 -0700 IB/cm: Match connection requests based on private data Extend matching connection requests to listens in the InfiniBand CM to include private data checks. This allows applications to listen on the same service identifier, with private data directing the request to the appropriate application. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit 6a9af2e18a5c6ebcf8283309d20ac0e9fa35e346 Author: Sean Hefty Date: Sat Jun 17 20:37:27 2006 -0700 IB: common handling for marshalling parameters to/from userspace Provide common handling for marshalling data between userspace clients and kernel InfiniBand drivers. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier commit 4e56ea794ec8636991e21942fc2e0d071ea8ee1d Author: Michael S. Tsirkin Date: Tue Jun 13 17:19:42 2006 +0300 IB/mthca: memfree completion with error FW bug workaround Memfree firmware is in rare cases reporting WQE index == base - 1 in receive completion with error, instead of (rq size - 1); base is 0 in mthca. Here is a patch to avoid kernel crash and report a correct WR id in this case. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier commit 13aa6ecb47990cfc78e20e347fdd3f1df6189426 Author: Michael S. Tsirkin Date: Mon Jun 12 16:57:51 2006 +0300 IB/mthca: restore missing PCI registers after reset mthca does not restore the following PCI-X/PCI Express registers after reset: PCI-X device: PCI-X command register PCI-X bridge: upstream and downstream split transaction registers PCI Express : PCI Express device control and link control registers This causes instability and/or bad performance on systems where one of these registers is set to a non-default value by BIOS. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier commit 3877f0b6c9f54d43e55e532404a935b90393b635 Author: David Woodhouse Date: Sun Jun 18 00:05:26 2006 +0100 [JFFS2] Don't trust node headers before the CRC is checked. Especially when summary code is used, we can have in-memory data structures referencing certain nodes without them actually being readable on the flash. Discard the nodes gracefully in that case, rather than triggering a BUG(). Signed-off-by: David Woodhouse commit 216b2f1f718d653795024a085636d063693dd9a9 Author: Uwe Zeisberger Date: Fri Jun 16 08:48:48 2006 +0200 kbuild: append -dirty for updated but uncommited changes Compare the working copy with the last commit, instead of the index. Signed-off-by: Uwe Zeisberger Acked-by: Ryan Anderson Signed-off-by: Sam Ravnborg commit 29b0c89953fee8597b4a9cbdd763c294ae0eb4c7 Author: Uwe Zeisberger Date: Fri Jun 16 08:47:57 2006 +0200 kbuild: append git revision for all untagged commits adds revision suffix for untagged commits that are reachable from a tag I'm bisecting and don't get the -g...... suffix. The reason is, that git name-rev --tags HEAD returns e.g. HEAD tags/v2.6.17-rc1^0~1067 which is currently good enough for setlocalversion to skip the suffix. This introduces a dependecy to grep -E, which should be fine. Signed-off-by: Uwe Zeisberger Acked-By: Ryan Anderson Signed-off-by: Sam Ravnborg commit 9ac545b0f7161eaf2e180acc406c1dd6fdd77686 Author: Laurent Riffard Date: Sun Jun 11 08:02:06 2006 +0200 kbuild: fix module.symvers parsing in modpost read_dump didn't split lines between module name and export type. Signed-off-by: Laurent Riffard Signed-off-by: Sam Ravnborg commit 872d83d00f67021e036d75aab3b7c6e3fc7e29ee Author: Arnaud Patard Date: Thu Apr 27 05:25:00 2006 -0400 ACPI: suppress power button event on S3 resume http://bugzilla.kernel.org/show_bug.cgi?id=6612 Note that this fix depends on a fix in ACPICA 20060608 to replace a semaphore with a spin-lock. Signed-off-by: Arnaud Patard Acked-by: "Yu, Luming" Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 785fcccd68bd4dc436f75fd4cd40e8557966c86d Author: Len Brown Date: Thu Jun 15 22:19:31 2006 -0400 ACPI: resolve merge conflict between sem2mutex and processor_perflib.c Signed-off-by: Len Brown commit 1668b19f75cb949f930814a23b74201ad6f76a53 Author: Pedro Alejandro López-Valencia Date: Thu Jun 15 22:46:44 2006 +0200 sundance: PCI ID for ip100a Patch provided by Pedro Alejandro López-Valencia in http://bugzilla.kernel.org/show_bug.cgi?id=6691 The patch is derived from IC+ GPL'ed rework of sundance driver available at http://www.icplus.com.tw/pp-IP100A.html Patch closes http://bugzilla.kernel.org/show_bug.cgi?id=5858 as well. Signed-off-by: Francois Romieu Cc: Pedro Alejandro López-Valencia commit 89c318ed3985da1271e00ad586f2dce8a6e75656 Author: Zhu Yi Date: Thu Jun 8 22:19:49 2006 -0700 [PATCH] ipw2200 locking fix Well, this is not 100% if when the card fires two consecutive interrupts. Though unlikely, it's better to protect early than seeing some "weird" bugs one day. I proposed attached patch. If you can help to test, that will be appreciated (I cannot see the lockdep warning on my box somehow). Cc: Frederik Deweerdt Cc: Arjan van de Ven Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: John W. Linville commit 7bd6b91800c996da328bd57e40e62b3f73760fbe Author: Larry Finger Date: Thu Jun 8 09:47:42 2006 -0500 [PATCH] wireless: correct dump of WPA IE In net/ieee80211/softmac/ieee80211softmac_wx.c, there is a bug that prints extended sign information whenever the byte value exceeds 0x7f. The following patch changes the printk to use a u8 cast to limit the output to 2 digits. This bug was first noticed by Dan Williams . This patch applies to the current master branch of the Linville tree. Signed-Off-By: Larry Finger Signed-off-by: John W. Linville commit 12a3768792dc27f11a5edb96e38db32bcdc5fd27 Author: Jiri Slaby Date: Mon Jun 5 22:20:07 2006 +0200 [PATCH] pci: bcm43xx avoid pci_find_device bcm43xx avoid pci_find_device Change pci_find_device to safer pci_get_device with support for more devices. Signed-off-by: Jiri Slaby Signed-off-by: John W. Linville commit 91769e7dd9cef7988dc4280f74ed168351beb5b8 Author: Michael Buesch Date: Mon Jun 5 20:24:21 2006 +0200 [PATCH] bcm43xx: preemptible periodic work Make the heavy periodic work preemptible to avoid disabling local IRQs for several msecs. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville commit 78ff56a06edc3407996173daf63e48f6b90c7062 Author: Michael Buesch Date: Mon Jun 5 20:24:10 2006 +0200 [PATCH] bcm43xx: redesign locking Redesign the bcm43xx locking. This is pre-work to get a preemptible periodic work handler. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville commit 74f4903363579d3336c294ebb11f02c8f35845ca Author: Larry Finger Date: Tue May 30 11:55:42 2006 -0500 [PATCH] wireless: Changes to ieee80211.h for user space regulatory daemon Attached are two small patches for include/net/ieee80211.h to prepare for later submission of code to implement a user-space daemon that supplies 802.11 regulatory information. The first change adds a bit indicating that 802.11h rules are to be applied to a channel. As discussed earlier in this list, a single bit is unlikely to be sufficient; however, at this time I have been unable to find any regulations implementing differences between 802.11a and 802.11h other than DFS, radar detection and passive scanning. A single bit is thus sufficient to convey to the driver that these rules should be obeyed. The second change adds comments to the freq and max_power fields of struct ieee80211_channel to indicate the units that are used. Signed-Off-By: Larry Finger Signed-off-by: John W. Linville commit 12223dabc617a4babfba4e17feb1ed88e8cfeb8f Author: Russell King Date: Thu Jun 15 13:28:52 2006 +0100 [MMC] Add (MMC) to entry in MAINTAINERS file Juha Yrjola suggests that adding the string "MMC" to the maintainers file entry will make it easier to find. Add it to the file. Signed-off-by: Russell King commit 2ba73b1d6fa62ddaa235c3c5fdf6095cae6ba748 Author: Matthias Fuchs Date: Wed Jun 14 15:35:05 2006 +0200 [POWERPC] ppc32: fix CPCI405 board support Hi, this patch brings the CPCI405 board support up to date and fixes several outstanding issues: -add bios_fixup() -enable RTC only when CONFIG_GEN_RTC defined -corrected CompactPCI interrupt map -added cpci405_early_serial_map for correct UART clocking -removed unused code Matthias Signed-off-by: Matthias Fuchs Signed-off-by: Paul Mackerras commit 4312dc76a88146c4f1d693fc4643d1df12aaf755 Author: Johannes Berg Date: Tue Jun 13 17:43:42 2006 +0200 [POWERPC] make pmf irq_client functions safe against pmf interrupts coming in This fixes the pmf irq_client functions to be safe against pmf interrupts coming in while a client is registered/unregistered. Signed-off-by: Johannes Berg Signed-off-by: Paul Mackerras commit 368a6ba5d188552aea2a668301a259164c9f355e Author: Dave C Boutcher Date: Mon Jun 12 19:49:20 2006 -0500 [POWERPC] check firmware state before suspending Currently the kernel blindly halts all the processors and calls the ibm,suspend-me rtas call. If the firmware is not in the correct state, we then re-start all the processors and return. It is much smarter to first check the firmware state, and only if it is waiting, call the ibm,suspend-me call. Signed-off-by: Paul Mackerras commit 0e4aa9c2009187fff1c999fe0aaa134c1a84f48a Author: Amos Waterland Date: Mon Jun 12 23:45:02 2006 -0400 [POWERPC] Fix builtin command line interaction with firmware It seems that prom_init's early_cmdline_parse is broken on at least Apple 970 xserves and IBM JS20 blades with SLOF. The firmware of these machines returns -1 and 1 respectively when getprop is called for the bootargs property of /chosen, causing Linux to ignore its builtin command line in favor of a null string. This patch makes Linux use its builtin command line if getprop returns an error or a null string. Signed-off-by: Amos Waterland Acked-by: Segher Boessenkool Signed-off-by: Paul Mackerras commit 6fe87675314b4b1ac7ba339e2a4ab8d739b600d6 Author: Anton Blanchard Date: Sun Jun 11 11:40:43 2006 +1000 [POWERPC] update pmac32_defconfig Some updates to the pmac32_defconfig to make it more useful: - Enable LSF (large single files) since we enable LBD (large block devices) - Enable IPSEC related options - Enable remaining raid/dm options as modules - Disable eth1394, I doubt any has that hardware and it has a nasty habit of auto loading first and skewing network device numbering - Enable dummy and tun as modules, always useful to have them around - Enable EHCI, no wonder my usb2 disk was so slow - Enable USB storage - Enable ext3 acls - Disable autofs and enable autofsv4 instead - Enable nfs v3/v4 client and server. Dont want to be left in the dark ages of pre v3 - Enable all crypto as modules, things like cryptsetup want some of them I havent enabled the BCM43xx, perhaps we should now? Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit bd19c8994a828e70b5472f0ce9df5831c6c3db84 Author: Anton Blanchard Date: Sun Jun 11 01:15:55 2006 +1000 [POWERPC] system call micro optimisation In the syscall path we currently have: crclr so mfcr r9 If we shift the crclr up we can avoid a stall on some CPUs. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 9e6e3c2c796f1e0ef335804d5c87073e365dea50 Author: Anton Blanchard Date: Sat Jun 10 23:14:51 2006 +1000 [POWERPC] Fix HV bit handling on non partitioned machines On non partitioned machines we currently set the HV bit in kernel space only. It turns out we are supposed to maintain the HV bit in both user and kernel space. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit df310656c7552ae7b8252e4b3d8e300cff164b16 Author: Anton Blanchard Date: Sat Jun 10 23:04:39 2006 +1000 [POWERPC] cleanup dma_mapping_ops For pseries IOMMU bypass I want to be able to fall back to the regular IOMMU ops. Do this by creating a dma_mapping_ops struct, and convert the others while at it. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit ca1588e71b70534e18368a46a3aad9b25dff941d Author: Anton Blanchard Date: Sat Jun 10 20:58:08 2006 +1000 [POWERPC] node local IOMMU tables Allocate IOMMU tables local to the relevant node. Signed-off-by: Anton Blanchard Acked-by: Olof Johansson Signed-off-by: Paul Mackerras commit 357518fa34d9dceda42bfc09642356a58370050d Author: Anton Blanchard Date: Sat Jun 10 20:53:06 2006 +1000 [POWERPC] pcibus_to_node fixes of_node_to_nid returns -1 if the associativity cannot be found. This means pcibus_to_cpumask has to be careful not to pass a negative index into node_to_cpumask. Since pcibus_to_node could be used a lot, and of_node_to_nid is slow (it walks a list doing strcmps), lets also cache the node in the pci_controller struct. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit f2b09c8189bc7b64a42753e98f7006b11bae1bdc Author: Anton Blanchard Date: Sat Jun 10 20:37:24 2006 +1000 [POWERPC] Update pseries defconfig pseries defconfig updates: - Enable jsm and re-enable qlogic FC drivers as modules. - Enable ocfs2, autofs4 and fuse filesystems as modules. - Enable Kprobes. - Enable ebus, binfmt_misc, sas attrs, md5 reshape, hvc rtas backend and some infiniband options. - Finally disable debug options: DEBUG_MUTEXES and DEBUG_STACK_USAGE. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 227318bbde6c8309b1d20ab46532ec2b737e1fee Author: Anton Blanchard Date: Sat Jun 10 20:32:01 2006 +1000 [POWERPC] Remove stale 64bit on 32bit kernel code Remove some stale POWER3/POWER4/970 on 32bit kernel support. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 8555a0029b1b0840237b750e55d4835a52cc719b Author: Anton Blanchard Date: Sat Jun 10 20:23:54 2006 +1000 [POWERPC] Optimise some TOC usage Micro-optimisation - add no-minimal-toc to some more arch/powerpc Makefiles. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 3a2c48cfc97f9046abbd810f1efb1aa824bcfaf1 Author: Anton Blanchard Date: Sat Jun 10 20:18:39 2006 +1000 [POWERPC] 64bit FPSCR support Forthcoming machines will extend the FPSCR to 64 bits. We already had a 64-bit save area for the FPSCR, but we need to use a new form of the mtfsf instruction. Fortunately this new form is decoded as an ordinary mtfsf by existing 64-bit processors. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 30d8caf7c625203b295a78f143820cdc3124830b Author: mostrows@watson.ibm.com Date: Fri Jun 9 09:06:12 2006 -0400 [POWERPC] Editable kernel command-line in zImage binary. zImage will set /chosen/bootargs (if it is otherwise empty) with the contents of a buffer in the section "__builtin_cmdline". This permits tools to edit zImage binaries to set the command-line eventually processed by vmlinux. -- Signed-off-by: Michal Ostrowski Signed-off-by: Paul Mackerras commit 204face4fb3ba2ca09a4073e7debc595e14c2388 Author: Jake Moilanen Date: Wed Jun 7 16:15:10 2006 -0500 [POWERPC] MSI abstraction Instead of trying to make PPC64 MSI fit in a Intel-centric MSI layer, a simple short-term solution is to hook the pci_{en/dis}able_msi() calls and make a machdep call. The rest of the MSI functions are superfluous for what is needed at this time. Many of which can have machdep calls added as needed. Ben and Michael Ellerman are looking into rewrite the MSI layer to be more generic. However, in the meantime this works as a interim solution. Signed-off-by: Jake Moilanen Signed-off-by: Paul Mackerras commit bb53bb3dcb12d79efdee3d82bff46a204af377f3 Author: Jake Moilanen Date: Wed Jun 7 16:05:46 2006 -0500 [POWERPC] Add support for PCI-Express nodes in the device tree This adds support to recognize the PCIe device_type "pciex" and made the portdrv buildable. Signed-off-by: Jake Moilanen Signed-off-by: Paul Mackerras commit 0f582bc1f2cccacd613c411fbea55873d17c3429 Author: Paul Mackerras Date: Thu Jun 15 18:03:32 2006 +1000 powerpc: Simplify push_end definition in pci_32.c The push_end macro in arch/powerpc/kernel/pci_32.c uses integer division and multiplication to achieve the effect of rounding a resource end address up and then advancing it to the end of a power-of-2 sized region. This changes it to an equivalent computation that only needs an integer add and OR. This is partly based on an earlier patch by Mel Gorman. Signed-off-by: Paul Mackerras commit bf72aeba2ffef599d1d386425c9e46b82be657cd Author: Paul Mackerras Date: Thu Jun 15 10:45:18 2006 +1000 powerpc: Use 64k pages without needing cache-inhibited large pages Some POWER5+ machines can do 64k hardware pages for normal memory but not for cache-inhibited pages. This patch lets us use 64k hardware pages for most user processes on such machines (assuming the kernel has been configured with CONFIG_PPC_64K_PAGES=y). User processes start out using 64k pages and get switched to 4k pages if they use any non-cacheable mappings. With this, we use 64k pages for the vmalloc region and 4k pages for the imalloc region. If anything creates a non-cacheable mapping in the vmalloc region, the vmalloc region will get switched to 4k pages. I don't know of any driver other than the DRM that would do this, though, and these machines don't have AGP. When a region gets switched from 64k pages to 4k pages, we do not have to clear out all the 64k HPTEs from the hash table immediately. We use the _PAGE_COMBO bit in the Linux PTE to indicate whether the page was hashed in as a 64k page or a set of 4k pages. If hash_page is trying to insert a 4k page for a Linux PTE and it sees that it has already been inserted as a 64k page, it first invalidates the 64k HPTE before inserting the 4k HPTE. The hash invalidation routines also use the _PAGE_COMBO bit, to determine whether to look for a 64k HPTE or a set of 4k HPTEs to remove. With those two changes, we can tolerate a mix of 4k and 64k HPTEs in the hash table, and they will all get removed when the address space is torn down. Signed-off-by: Paul Mackerras commit 21c8db9eff95260e543535dfc6f27164c4c0c0ff Author: David Woodhouse Date: Wed Jun 14 21:39:48 2006 +0100 [MTD] Restore MTD_ROM and MTD_RAM types Let's not attempt the abolition of mtd->type until/unless it's properly thought through. And certainly, let's not do it by halves. Signed-off-by: David Woodhouse commit 783ed81ff39d3f938a6b2efd09fbad96e41e5c1f Author: Artem B. Bityutskiy Date: Wed Jun 14 19:53:44 2006 +0400 [MTD] assume mtd->writesize is 1 for NOR flashes Signed-off-by: Artem B. Bityitskiy commit 9348f0de2d2b541b4ba64fb1f4efee9710a3d731 Author: Martin Schwidefsky Date: Wed Jun 14 14:10:51 2006 +0100 [S390] __FD_foo definitions. Make the definitions of __FD_SET, __FD_CLR and __FD_ISSET independent from asm/bitops.h and remove the macro magic that tests for __GLIBC__. Use simple C inline functions instead of set_bit, clear_bit and test_bit. Signed-off-by: Martin Schwidefsky Signed-off-by: David Woodhouse commit 4c90ece249992c7a2e3fc921e5cdb8eb92193067 Author: Bob Moore Date: Thu Jun 8 16:29:00 2006 -0400 ACPI: ACPICA 20060608 Converted the locking mutex used for the ACPI hardware to a spinlock. This change should eliminate all problems caused by attempting to acquire a semaphore at interrupt level, and it means that all ACPICA external interfaces that directly access the ACPI hardware can be safely called from interrupt level. Fixed a regression introduced in 20060526 where the ACPI device initialization could be prematurely aborted with an AE_NOT_FOUND if a device did not have an optional _INI method. Fixed an IndexField issue where a write to the Data Register should be limited in size to the AccessSize (width) of the IndexField itself. (BZ 433, Fiodor Suietov) Fixed problem reports (Valery Podrezov) integrated: - Allow store of ThermalZone objects to Debug object. http://bugzilla.kernel.org/show_bug.cgi?id=5369 http://bugzilla.kernel.org/show_bug.cgi?id=5370 Fixed problem reports (Fiodor Suietov) integrated: - acpi_get_table_header() doesn't handle multiple instances correctly (BZ 364) Removed four global mutexes that were obsolete and were no longer being used. Signed-off-by: Bob Moore Signed-off-by: Len Brown commit 4119532c95547821dbe72d6916dfa1b2148475b3 Author: Bob Moore Date: Fri May 26 16:36:00 2006 -0400 ACPI: ACPICA 20060526 Restructured, flattened, and simplified the internal interfaces for namespace object evaluation - resulting in smaller code, less CPU stack use, and fewer interfaces. (With assistance from Mikhail Kouzmich) Fixed a problem with the CopyObject operator where the first parameter was not typed correctly for the parser, interpreter, compiler, and disassembler. Caused various errors and unexpected behavior. Fixed a problem where a ShiftLeft or ShiftRight of more than 64 bits produced incorrect results with some C compilers. Since the behavior of C compilers when the shift value is larger than the datatype width is apparently not well defined, the interpreter now detects this condition and simply returns zero as expected in all such cases. (BZ 395) Fixed problem reports (Valery Podrezov) integrated: - Update String-to-Integer conversion to match ACPI 3.0A spec http://bugzilla.kernel.org/show_bug.cgi?id=5329 Allow interpreter to handle nested method declarations http://bugzilla.kernel.org/show_bug.cgi?id=5361 Fixed problem reports (Fiodor Suietov) integrated: - acpi_terminate() doesn't free debug memory allocation list objects (BZ 355) - After Core Subsystem shutdown, acpi_subsystem_status() returns AE_OK (BZ 356) - acpi_os_unmap_memory() for RSDP can be invoked inconsistently (BZ 357) - Resource Manager should return AE_TYPE for non-device objects (BZ 358) - Incomplete cleanup branch in AcpiNsEvaluateRelative (BZ 359) - Use acpi_os_free() instead of ACPI_FREE in acpi_rs_set_srs_method_data (BZ 360) - Incomplete cleanup branch in acpi_ps_parse_aml (BZ 361) - Incomplete cleanup branch in acpi_ds_delete_walk_state (BZ 362) - acpi_get_table_header returns AE_NO_ACPI_TABLES until DSDT is loaded (BZ 365) - Status of the Global Initialization Handler call not used (BZ 366) - Incorrect object parameter to Global Initialization Handler (BZ 367) Signed-off-by: Bob Moore Signed-off-by: Len Brown commit b8d35192c55fb055792ff0641408eaaec7c88988 Author: Alexey Starikovskiy Date: Fri May 5 03:23:00 2006 -0400 ACPI: execute Notify() handlers on new thread http://bugzilla.kernel.org/show_bug.cgi?id=5534 Thanks to Peter Wainwright for isolating the issue. Thanks to Andi Kleen and Bob Moore for feedback. Thanks to Richard Mace and others for testing. Updates by Konstantin Karasyov. Signed-off-by: Konstantin Karasyov Signed-off-by: Len Brown commit 958dd242b691f64ab4632b4903dbb1e16fee8269 Author: Bob Moore Date: Fri May 12 17:12:00 2006 -0400 ACPI: ACPICA 20060512 Replaced the acpi_os_queue_for_execution() with a new interface named acpi_os_execute(). The major difference is that the new interface does not have a Priority parameter, this appeared to be useless and has been replaced by a Type parameter. The Type tells the OS what type of execution is being requested, such as global lock handler, notify handler, GPE handler, etc. This allows the host to queue and execute the request as appropriate for the request type, possibly using different work queues and different priorities for the various request types. This enables fixes for multithreading deadlock problems such as http://bugzilla.kernel.org/show_bug.cgi?id=5534 (Alexey Starikovskiy and Bob Moore) Fixed a possible memory leak associated with the support for the so-called "implicit return" ACPI extension. Reported by FreeBSD (Fiodor Suietov) http://bugzilla.kernel.org/show_bug.cgi?id=6514 Fixed a problem with the Load() operator where a table load from an operation region could overwrite an internal table buffer by up to 7 bytes and cause alignment faults on IPF systems. (With assistance from Luming Yu) Signed-off-by: Bob Moore Signed-off-by: Len Brown commit b229cf92eee616c7cb5ad8cdb35a19b119f00bc8 Author: Bob Moore Date: Fri Apr 21 17:15:00 2006 -0400 ACPI: ACPICA 20060421 Removed a device initialization optimization introduced in 20051216 where the _STA method was not run unless an _INI was also present for the same device. This optimization could cause problems because it could allow _INI methods to be run within a not-present device subtree (If a not-present device had no _INI, _STA would not be run, the not-present status would not be discovered, and the children of the device would be incorrectly traversed.) Implemented a new _STA optimization where namespace subtrees that do not contain _INI are identified and ignored during device initialization. Selectively running _STA can significantly improve boot time on large machines (with assistance from Len Brown.) Implemented support for the device initialization case where the returned _STA flags indicate a device not-present but functioning. In this case, _INI is not run, but the device children are examined for presence, as per the ACPI specification. Implemented an additional change to the IndexField support in order to conform to MS behavior. The value written to the Index Register is not simply a byte offset, it is a byte offset in units of the access width of the parent Index Field. (Fiodor Suietov) Defined and deployed a new OSL interface, acpi_os_validate_address(). This interface is called during the creation of all AML operation regions, and allows the host OS to exert control over what addresses it will allow the AML code to access. Operation Regions whose addresses are disallowed will cause a runtime exception when they are actually accessed (will not affect or abort table loading.) Defined and deployed a new OSL interface, acpi_os_validate_interface(). This interface allows the host OS to match the various "optional" interface/behavior strings for the _OSI predefined control method as appropriate (with assistance from Bjorn Helgaas.) Restructured and corrected various problems in the exception handling code paths within DsCallControlMethod and DsTerminateControlMethod in dsmethod (with assistance from Takayoshi Kochi.) Modified the Linux source converter to ignore quoted string literals while converting identifiers from mixed to lower case. This will correct problems with the disassembler and other areas where such strings must not be modified. The ACPI_FUNCTION_* macros no longer require quotes around the function name. This allows the Linux source converter to convert the names, now that the converter ignores quoted strings. Signed-off-by: Bob Moore Signed-off-by: Len Brown commit 793c2388cae3fd023b3b5166354931752d42353c Author: Bob Moore Date: Fri Mar 31 00:00:00 2006 -0500 ACPI: ACPICA 20060331 Implemented header file support for the following additional ACPI tables: ASF!, BOOT, CPEP, DBGP, MCFG, SPCR, SPMI, TCPA, and WDRT. With this support, all current and known ACPI tables are now defined in the ACPICA headers and are available for use by device drivers and other software. Implemented support to allow tables that contain ACPI names with invalid characters to be loaded. Previously, this would cause the table load to fail, but since there are several known cases of such tables on existing machines, this change was made to enable ACPI support for them. Also, this matches the behavior of the Microsoft ACPI implementation. https://bugzilla.novell.com/show_bug.cgi?id=147621 Fixed a couple regressions introduced during the memory optimization in the 20060317 release. The namespace node definition required additional reorganization and an internal datatype that had been changed to 8-bit was restored to 32-bit. (Valery Podrezov) Fixed a problem where a null pointer passed to acpi_ut_delete_generic_state() could be passed through to acpi_os_release_object which is unexpected. Such null pointers are now trapped and ignored, matching the behavior of the previous implementation before the deployment of acpi_os_release_object(). (Valery Podrezov, Fiodor Suietov) Fixed a memory mapping leak during the deletion of a SystemMemory operation region where a cached memory mapping was not deleted. This became a noticeable problem for operation regions that are defined within frequently used control methods. (Dana Meyers) Reorganized the ACPI table header files into two main files: one for the ACPI tables consumed by the ACPICA core, and another for the miscellaneous ACPI tables that are consumed by the drivers and other software. The various FADT definitions were merged into one common section and three different tables (ACPI 1.0, 1.0+, and 2.0) Signed-off-by: Bob Moore Signed-off-by: Len Brown commit 61686124f47d7c4b78610346c5f8f9d8a6d46bb5 Author: Bob Moore Date: Fri Mar 17 16:44:00 2006 -0500 [ACPI] ACPICA 20060317 Implemented the use of a cache object for all internal namespace nodes. Since there are about 1000 static nodes in a typical system, this will decrease memory use for cache implementations that minimize per-allocation overhead (such as a slab allocator.) Removed the reference count mechanism for internal namespace nodes, since it was deemed unnecessary. This reduces the size of each namespace node by about 5%-10% on all platforms. Nodes are now 20 bytes for the 32-bit case, and 32 bytes for the 64-bit case. Optimized several internal data structures to reduce object size on 64-bit platforms by packing data within the 64-bit alignment. This includes the frequently used ACPI_OPERAND_OBJECT, of which there can be ~1000 static instances corresponding to the namespace objects. Added two new strings for the predefined _OSI method: "Windows 2001.1 SP1" and "Windows 2006". Split the allocation tracking mechanism out to a separate file, from utalloc.c to uttrack.c. This mechanism appears to be only useful for application-level code. Kernels may wish to not include uttrack.c in distributions. Removed all remnants of the obsolete ACPI_REPORT_* macros and the associated code. (These macros have been replaced by the ACPI_ERROR and ACPI_WARNING macros.) Signed-off-by: Bob Moore Signed-off-by: Len Brown commit bf717b11aec20965d48dea36dea3eea18a75d18c Author: Jeff Garzik Date: Tue Jun 13 20:27:03 2006 -0400 [libata] Update docs to reflect current driver API commit d7ede1aa5dfff53e76dbabac5b8087341686f662 Author: Nathan Scott Date: Tue Jun 13 16:28:11 2006 +1000 [XFS] Minor XFS documentation updates. Signed-off-by: Nathan Scott commit 31925323b1b51bb65db729e029472a8b1f635b7d Author: Paul Mackerras Date: Tue Jun 13 13:43:00 2006 +1000 powerpc: Fix some missed ppc32 mm->context.id conversions Signed-off-by: Paul Mackerras commit 7136b8073f0123918e3e50269ae021bbb09e1a81 Author: Ben Collins Date: Mon Jun 12 18:16:25 2006 -0400 eth1394: replace __constant_htons by htons ...and __constant_ntohs, __constant_ntohl, __constant_cpu_to_be32 too where possible. Htons and friends are resolved to constants in these places anyway. Also fix an endianess glitch in a log message, spotted by Alexey Dobriyan. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit 2c4b69bd7bff85ae9e8b2032179aee9c04da70ba Author: Ben Collins Date: Mon Jun 12 18:16:16 2006 -0400 ieee1394: adjust code formatting in highlevel.c Replace spaces by tabulators, wrap lines at 80 columns, delete some blank lines and superfluous braces. Collapse some if()-within-if() constructs. Replace a literal CSR address by its preprocessor constant. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit 445151932e869fd76b23bccff75ae2a600ccf3c9 Author: Ben Collins Date: Mon Jun 12 18:16:01 2006 -0400 ieee1394: hl_irqs_lock is taken in hardware interrupt context ohci1394 and pcilynx call highlevel_host_reset from their hardware interrupt handler (via hpsb_selfid_complete). Therefore all readers and writers of hl_irqs_lock have to disable interrupts. Reported by Jiri Slaby and J. A. Magallon. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit f654240f330d77eb198af4abde89131e2a0e4f90 Author: Ben Collins Date: Mon Jun 12 18:15:50 2006 -0400 ieee1394_core: switch to kthread API This gets also rid of the MODPOST warning "drivers/ieee1394/ieee1394.o - Section mismatch: reference to .exit.text: from .smp_locks after '' (at offset 0x18)". Signed-off-by: Christoph Hellwig Signed-off-by: Jody McIntyre Signed-off-by: Stefan Richter Signed-off-by: Andrew Morton Signed-off-by: Ben Collins commit dd082c670523231dc9a26dafee1dc22b57df2921 Author: Ben Collins Date: Mon Jun 12 18:15:40 2006 -0400 ieee1394: sbp2: Kconfig fix We only support x86 and ppc, due to the use of bus_to_virt() and friends. Signed-off-by: Stefan Richter Signed-off-by: Andrew Morton Signed-off-by: Ben Collins commit 6737231ead125c7cee7ce4d3a74179bdac085529 Author: Ben Collins Date: Mon Jun 12 18:15:31 2006 -0400 ieee1394: add preprocessor constant for invalid csr address Replace occurrences of the magic value ~(u64)0 for invalid CSR address spaces by a named constant for better readability. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit e269d276792684a13ab0d9acd8c024ec7d6c5f4d Author: Ben Collins Date: Mon Jun 12 18:15:20 2006 -0400 sbp2: fix deregistration of status fifo address space The proper designator of an invalid CSR address is ~(u64)0, not (u64)0. Use the correct value in initialization and deregistration. Also, scsi_id->sbp2_lun does not need to be initialized twice. (scsi_id was kzalloc'd.) Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit 02f4213fc43dbddc3a3ab9fa4d2dc2501a2d30dc Author: Ben Collins Date: Mon Jun 12 18:15:11 2006 -0400 [PATCH] eth1394: endian fixes Signed-off-by: Alexey Dobriyan Signed-off-by: Ben Collins commit b21efb59c5d317a2a972b9d66939cbfeababd982 Author: Ben Collins Date: Mon Jun 12 18:15:03 2006 -0400 Fix broken suspend/resume in ohci1394 I've been experimenting to track down the cause of suspend/resume problems on my Compaq Presario X1050 laptop: http://bugzilla.kernel.org/show_bug.cgi?id=6075 Essentially the ACPI Embedded Controller and keyboard controller would get into a bizarre, confused state after resume. I found that unloading the ohci1394 module before suspend and reloading it after resume made the problem go away. Diffing the dmesg output from resume, with and without the module loaded, I found that with the module loaded I was missing these: PM: Writing back config space on device 0000:02:00.0 at offset 1. (Was 2100080, writing 2100007) PM: Writing back config space on device 0000:02:00.0 at offset 3. (Was 0, writing 8008) PM: Writing back config space on device 0000:02:00.0 at offset 4. (Was 0, writing 90200000) PM: Writing back config space on device 0000:02:00.0 at offset 5. (Was 1, writing 2401) PM: Writing back config space on device 0000:02:00.0 at offset f. (Was 20000100, writing 2000010a) The default PCI driver performs the pci_restore_state when no driver is loaded for the device. When the ohci1394 driver is loaded, it is supposed to do this, however it appears not to do so. I created the patch below and tested it, and it appears to resolve the suspend problems I was having with the module loaded. I only added in the pci_save_state and pci_restore_state - however, though I know little of this hardware, surely the driver should really be doing more than this when suspending and resuming? Currently it does almost nothing, what if there are commands in progress, etc? Signed-off-by: Robert Hancock Cc: Jody McIntyre Cc: Ben Collins Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Ben Collins commit 05db5055b1844bf39d1429a0c43078959198cd1d Author: Ben Collins Date: Mon Jun 12 18:14:47 2006 -0400 sbp2: use __attribute__((packed)) for on-the-wire structures It seems to have worked without the attribute during all the years just because sizes of all struct members are multiples of 32 bits. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit bccbccdbf8f866a8e01967a48241db548e12adf2 Author: Ben Collins Date: Mon Jun 12 18:14:36 2006 -0400 sbp2: provide helptext for CONFIG_IEEE1394_SBP2_PHYS_DMA and mark it experimental It appears I will not get it fixed overnight. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit d0aef39f9b5941beb322924986ddee8c4903cd72 Author: Ben Collins Date: Mon Jun 12 18:14:27 2006 -0400 Update feature removal of obsolete raw1394 ISO requests. Signed-off-by: Jody McIntyre Signed-off-by: Ben Collins commit fd23ade80e2bef156aa096459c31c010dacbea1e Author: Ben Collins Date: Mon Jun 12 18:14:14 2006 -0400 sbp2: fix S800 transfers if phys_dma is off If sbp2 is forced to move data via ARM handler, the maximum packet size allowed for S800 transfers exceeds ohci1394's buffer size on platforms where PAGE_SIZE is 4096. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit 40ae6c5e88790c2558013640ca4e0a5017c54162 Author: Ben Collins Date: Mon Jun 12 18:13:49 2006 -0400 sbp2: remove ohci1394 specific constant Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit fa9b73997cc621b9a15c96f07dda26775e61ac6a Author: Ben Collins Date: Mon Jun 12 18:13:42 2006 -0400 ohci1394: make phys_dma parameter read-only Being able to switch physical DMA on and off at run time would be a nice feature but a PITA to support by highlevel drivers and userspace apps. Therefore allow it only to be set when the driver is being loaded. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit 4611ed38030a2ce3661de999c3487e5a1eed0dc0 Author: Ben Collins Date: Mon Jun 12 18:13:32 2006 -0400 ohci1394: set address range properties This patch supplies the API extension introduced by patch "ieee1394: extend lowlevel API for address range properties" with proper addresses. Like in patch ''ohci1394, sbp2: fix "scsi_add_device failed" with PL-3507 based devices'', 1 TeraByte is chosen as physical upper bound. This leaves a window for the middle address range. This choice is only relevant for adapters which actually have a programmable pysical upper bound register. (Only ALi and Fujitsu adapters are known for this. Most adapters have a fixed bound at 4 GB.) The middle address range is suitable for posted writes. AFAIK, PCILynx does not support physical DMA nor posted writes, therefore no equivalent change in the pcilynx driver is necessary. There is also a driver for GP2Lynx, although not in mainline Linux. I assume this hardware does not support these OHCI features either. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit 8aef63ff033fb0e7ba02d8e760d268eb0aafc58c Author: Ben Collins Date: Mon Jun 12 18:13:21 2006 -0400 ieee1394: extend lowlevel API for address range properties Host adapter hardware imposes certain restrictions and features on address ranges. Instead of hard-wire such ranges into the ieee1394 core or even into protocol drivers, let lowlevel drivers specify these ranges via struct hpsb_host. Patch "ohci1394: set address range properties" must be applied too, else hpsb_allocate_and_register_addrspace() won't work properly. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit 20f4578156995e95613497baf16d5b2d54921e5d Author: Ben Collins Date: Mon Jun 12 18:13:11 2006 -0400 sbp2: log number of supported concurrent logins Since this is useful information, promote it from a debug macro to a regular log message. The message appears only if the user set exclusive_login=0, therefore won't clutter the logs in normal use. Also update the comment on exclusive_login. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre Signed-off-by: Ben Collins commit fe42b05a9929e159355bde6025ae46db2ac88658 Author: Ben Collins Date: Mon Jun 12 18:12:59 2006 -0400 sbp2: remove manipulation of inquiry response This code became ineffective a few Linux releases ago and is not required anyway. Note from Christoph Hellwig: scsi_cmnd.request_buffer is always a scatterlist these days. Checking random bites into it and then mangling the data in sbp2_check_sbp2_response will cause really bad memory corruption when you're not lucky enough to have the check not trigger by luck. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit eaf88450d21fc839c3e77fa6942b8d4192bdfe53 Author: Ben Collins Date: Mon Jun 12 18:12:49 2006 -0400 ieee1394: save RAM by using a single tlabel for broadcast transactions Since broadcast transactions are already complete when the request has been sent, the same transaction label can be reused all over again, see IEEE 1394 7.3.2.5 and 6.2.4.3. Therefore we can reduce the footprint of struct hpsb_host by the size of one struct hpsb_tlabel_pool. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit 647dcb5fae0ebb5da1272ed2773df0d3f152c303 Author: Ben Collins Date: Mon Jun 12 18:12:37 2006 -0400 ieee1394: support for slow links or slow 1394b phy ports Add support for the following types of hardware: + nodes that have a link speed < PHY speed + 1394b PHYs that are less than S800 capable + 1394b/1394a adapter cable between two 1394b PHYs Also, S1600 and S3200 are now supported if IEEE1394_SPEED_MAX is raised. A probing function is added to nodemgr's config ROM fetching routine which adjusts the allowable speed if an access problem was encountered. Pros and Cons of the approach: + minimum code footprint to support this less widely used hardware + nearly no overhead for unaffected hardware - ineffective before nodemgr began to read the ROM of affected nodes - ineffective if ieee1394 is loaded with disable_nodemgr=1 The speed map CSRs which are published to the bus are not touched by the patch. Signed-off-by: Stefan Richter Cc: Hakan Ardo Cc: Calculex Cc: Robert J. Kosinski Signed-off-by: Ben Collins commit 57fdb58fa5a140bdd52cf4c4ffc30df73676f0a5 Author: Ben Collins Date: Mon Jun 12 18:12:21 2006 -0400 ieee1394/ohci1394: CycleTooLong interrupt management This patch modifies the ohci1394.c file to enable and manage the "cycle too long" interrupt. If this interrupt occurs, the "LinkControl.CycleMaster" bit of the host controller is reseted. This implies, that the host controller does not send "cycle start" packet anymore freezing then the isochronous communication. The management of the interrupt added by the patch is that when the interrupt occurs, the OHCI irq handler prints a kernel log warning and then sets the "LinkControl.CycleMaster" bit again resuming the isochronous communication. Signed-off-by: Jean-Baptiste Mur Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit 7597028a833b6bfafae0a8fbc18992a278467adf Author: Ben Collins Date: Mon Jun 12 18:12:10 2006 -0400 raw1394: fix whitespace after x86_64 compat patch Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit fa7614de60d10460a607c3ca22ea080d021c3fef Author: Ben Collins Date: Mon Jun 12 18:11:07 2006 -0400 From: Arjan van de Ven Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Cc: Ben Collins Cc: Jody McIntyre Signed-off-by: Andrew Morton Signed-off-by: Ben Collins commit 4b9a334703cf99a1a5b9f64cf9f028e3e1ae91ff Author: Ben Collins Date: Mon Jun 12 18:10:18 2006 -0400 sbp2: make TSB42AA9 workaround specific to Momobay CX-1 The workarounds are not required for DViCO Momobay FX-3A and AFAIR not for Momobay CX-2. These contain an TSB42AA9A but feature the same firmware_revision value as the older DViCO Momobay CX-1. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit ff34d3bddf2a1d7ae1e96a25e73e16042778c4c4 Author: Ben Collins Date: Mon Jun 12 17:53:31 2006 -0400 ohci1394: Remove superfluous call to free_dma_rcv_ctx, spotted by Adrian Bunk. Also remove some superfluous comments. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins commit 9bb2bcdb4b6f9a04363c8ea4cf72c592d6c7af71 Author: Ben Collins Date: Mon Jun 12 17:52:59 2006 -0400 ieee1394: speed up of dma_region_sync_for_cpu when attempting to find the 'last' part of the dma region continue the search from where we left off, instead of starting the search over. Signed-off-by: Jim Westfall Signed-off-by: Ben Collins commit f54b1bdff1b470ff4461de3a73a7ceaf3a52e10a Author: Ben Collins Date: Mon Jun 12 17:52:16 2006 -0400 video1394: be quiet When working with multiple cameras and intensive applications, our logs get flooded with video1394 information which isn't of much interest. Any objections to demoting these messages to debug messages? Signed-off-by: Daniel Drake Signed-off-by: Ben Collins commit e474c66b1c76f9755f5d6dd5bfe88ce5e0435184 Author: Andrew Morton Date: Mon Jun 12 22:10:22 2006 +0100 [MMC] sdhci truncated pointer fix On 64-bit machines, we just lost the uppermost 32 bits. Signed-off-by: Andrew Morton Signed-off-by: Russell King commit 821499a8241019be5591fad5ab925759fbcd9f32 Author: Mark Haverkamp Date: Mon Jun 12 10:53:58 2006 -0700 [SCSI] aacraid: Fix return code interpretation Received from Mark Salyzyn clear_user return is 0 for success, the code fragment is written to assume that it is the count of the number of bytes zero'd. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley commit c5943d36aebb79589ac3983eec418bbeca897573 Author: James Bottomley Date: Mon Jun 12 09:09:18 2006 -0500 [SCSI] scsi_transport_sas: fix panic in sas_free_rphy This is a hold over from the end device/expander conversion. Apparently the rphy list pointer is never initialised, so list_del() on the uninitialised pointer can panic the system Signed-off-by: James Bottomley commit f0eb62b81dd16bfc4034916418c3406ba20011e1 Author: Tejun Heo Date: Mon Jun 12 23:05:38 2006 +0900 [PATCH] libata: add host_set->next for legacy two host_sets case, take #3 For a legacy ATA controller, libata registers two separate host sets. There was no connection between the two hosts making it impossible to traverse all ports related to the controller. This patch adds host_set->next which points to the second host_set and makes ata_pci_remove_one() remove all associated host_sets. * On device removal, all ports hanging off the device are properly detached. Prior to this patch, ports on the first host_set weren't detached casuing oops on driver unloading. * On device removal, both host_sets are properly freed This will also be used by new power management code to suspend and resume all ports of a controller. host_set/port representation will be improved to handle legacy controllers better and this host_set linking will go away with it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit d01712698c7c52bc71f41192e864dccc90a1217d Author: Tejun Heo Date: Mon Jun 12 22:51:14 2006 +0900 [PATCH] libata: fix oops caused rescanning NULL sdev Depending on timing, ata_scsi_dev_rescan() might encounter a device which is enabled but not yet attached to sdev. On such cases, the original code caused oops. This patch makes ata_scsi_dev_rescan() rescan only device which are attached to sdevs. While at it, properly indent leading comment and add description about how it's synchronized with sdev attach/detach. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit d4c85325a817d3351e61c4be64b437116e8483b4 Author: Tejun Heo Date: Mon Jun 12 18:45:55 2006 +0900 [PATCH] sata_sil: update device hotplug handling, take #2 SIEN on some 3112 controllers doesn't mask SATA IRQ properly. IRQ stays asserted even after SIEN is masked and IRQ is acked. Also, even while frozen, any SATA PHY event including hardreset raises SATA IRQ. Clearing SError seems to be the only way to deassert SATA IRQ. This patch makes sil_host_intr() clear SError on SATA IRQs and ignore SATA IRQs reported while frozen so that hardreset doesn't trigger hotplug event (which ends up hardresetting again). In such cases, the port still gets re-frozen to minimize the danger of screaming interrupts. This results in one nil EH repeat on controllers with broken SIEN but other than that does no harm. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 430644312810645a6e05855db50a978df9ba3ad3 Author: Paul Mackerras Date: Mon Jun 12 18:38:21 2006 +1000 powerpc: Remove unused paca->pgdir field The pgdir field in the paca was a leftover from the dynamic VSIDs patch, and is not used in the current kernel code. This removes it. Signed-off-by: Paul Mackerras commit aeb2ecd6096182cc080d37679080c0f088dcd4a4 Author: Tejun Heo Date: Mon Jun 12 14:11:43 2006 +0900 [PATCH] libata: fast exit from EH while unloading Make EH exit fast if the port is being unloaded. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit f9be7113b56eb5d013a611d9c65e8d1d2d3f7c94 Author: Tejun Heo Date: Mon Jun 12 14:11:01 2006 +0900 [PATCH] libata: fix ATA_EH_REVALIDATE clearing ATA_EH_REVALIDATE should be cleared after all devices on the target port have been revalidated. Fix ata_eh_revalidate_and_attach() accordingly. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 551e8889509c30cda31e464e5cbe7572c4e1febd Author: Tejun Heo Date: Mon Jun 12 14:09:49 2006 +0900 [PATCH] libata: fix comment above ata_exec_internal() Add RETURNS comment above ata_exec_internal() and kill extra blank line. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 23fa9618094975f803ed0c6a44604b16747b9637 Author: Tejun Heo Date: Mon Jun 12 14:18:51 2006 +0900 [PATCH] sata_sil: add controller unplug detection in sil_interrupt() Short-circuit interrupt handling if BMDMA2 is reported as 0xffffffff indicating device removal. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 3b01b8af2414b6684051da4a1507dfacdbf24f86 Author: Jeff Garzik Date: Mon Jun 12 00:22:04 2006 -0400 libata: fix build, by adding required workqueue member to port struct commit 3057ac3c1a992ee135cbb7b7d1a12e58d81f0739 Author: zhao, forrest Date: Mon Jun 12 12:01:34 2006 +0800 [PATCH] Snoop SET FEATURES - WRITE CACHE ENABLE/DISABLE command(v5) This patch makes libata snoop 'SET FEATURES - WRITE CACHE ENABLE/DISABLE' command, executing requisite revalidation processes to update cached data. Signed-off-by: Forrest Zhao Signed-off-by: Jeff Garzik commit 39b07ce6d9f7cd4da8567baed844801e0aaa7b1a Author: Jeff Garzik Date: Sun Jun 11 23:59:44 2006 -0400 libata: more verbose request_irq() failure Suggested by Jarek P. commit 233277cad6dacca6a8e53743641cf43ef7f37c4a Author: Brian King Date: Wed Jun 7 11:25:31 2006 -0500 [PATCH] libata: Setup nbytes in ata_sg_init_one Setup nbytes in ata_sg_init_one to the total transfer length of the command. This is needed by some HBAs that need to know the total transfer length of each command. Signed-off-by: Brian King Signed-off-by: Jeff Garzik commit 0638dec01e89059c853515ab71c55fd13ba5a8ea Author: Herbert Valerio Riedel Date: Thu Jun 1 09:41:04 2006 +0200 [PATCH] net: au1000_eth: PHY framework conversion convert au1000_eth driver to use PHY framework and garbage collected functions and identifiers that became unused/obsolete in the process Signed-off-by: Herbert Valerio Riedel Signed-off-by: Jeff Garzik commit bd5d825c9434b83925a88bd30eb9eef51908a3c9 Author: Borislav Petkov Date: Sun Jun 11 23:17:01 2006 -0400 libata: Adjust initial debugging levels through preprocessor defines. Signed-off-by: Signed-off-by: Jeff Garzik commit b47725743cc53203d275ede5c54985ad92c15f42 Author: Alexey Dobriyan Date: Tue Jun 6 07:31:14 2006 +0400 [PATCH] sata_sil24: endian anotations With help from Tejun Heo. Signed-off-by: Alexey Dobriyan Signed-off-by: Jeff Garzik commit 96e672c79fb114ec38a868dc864e743205c24332 Author: Randy Dunlap Date: Sat Jun 10 13:33:48 2006 -0700 [PATCH] 3c5zz ethernet: fix section warnings Priority: not critical; makes init code discardable. Fix section mismatch warnings: WARNING: drivers/net/3c501.o - Section mismatch: reference to .init.text:el1_probe from .text between 'init_module' (at offset 0x812) and 'cleanup_module' WARNING: drivers/net/3c503.o - Section mismatch: reference to .init.text: from .text between 'init_module' (at offset 0x661) and 'cleanup_card' WARNING: drivers/net/3c505.o - Section mismatch: reference to .init.text: from .text between 'init_module' (at offset 0x228d) and 'cleanup_module' WARNING: drivers/net/3c507.o - Section mismatch: reference to .init.text:el16_probe from .text between 'init_module' (at offset 0xa99) and 'cleanup_module' WARNING: drivers/net/3c523.o - Section mismatch: reference to .init.text: from .text between 'init_module' (at offset 0x12e7) and 'cleanup_module' WARNING: drivers/net/3c527.o - Section mismatch: reference to .init.text:mc32_probe from .text between 'init_module' (at offset 0xd8d) and 'cleanup_module' Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik commit a2bd2ec8d1bef7479d26d375162963106757e8e9 Author: Randy Dunlap Date: Sat Jun 10 13:30:10 2006 -0700 [PATCH] smc ethernet: fix section mismatch warnings Priority: not critical; makes init code discardable. Removes one duplicate assignment. Fix section mismatch warnings: WARNING: drivers/net/smc-ultra.o - Section mismatch: reference to .init.text: from .text between 'init_module' (at offset 0x369) and 'cleanup_card' WARNING: drivers/net/smc-ultra32.o - Section mismatch: reference to .init.text:ultra32_probe from .text between 'init_module' (at offset 0x254) and 'cleanup_module' WARNING: drivers/net/smc9194.o - Section mismatch: reference to .init.text:smc_init from .text between 'init_module' (at offset 0x997) and 'cleanup_module' WARNING: drivers/net/smc9194.o - Section mismatch: reference to .init.data: from .data between 'smcdev.0' (at offset 0x44) and '__param_str_io' Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik commit 29f9f6d234753da97b74402f746981c63ec0b2f0 Author: Randy Dunlap Date: Sat Jun 10 13:32:12 2006 -0700 [PATCH] hp ethernet: fix section mismatches Priority: not critical; makes init code discardable. Fix section mismatch warnings: WARNING: drivers/net/hp-plus.o - Section mismatch: reference to .init.text: from .text between 'init_module' (at offset 0x387) and 'cleanup_card' WARNING: drivers/net/hp.o - Section mismatch: reference to .init.data: from .text between 'hp_init_card' (at offset 0x310) and 'init_module' WARNING: drivers/net/hp.o - Section mismatch: reference to .init.text: from .text between 'init_module' (at offset 0x367) and 'cleanup_card' Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik commit 5d1f16c6c4d64d1e4f53e277e39c0ada89f00a48 Author: Randy.Dunlap Date: Sat Jun 10 12:13:35 2006 -0700 [PATCH] Section mismatch in drivers/net/ne.o during modpost On Sat, 10 Jun 2006 14:11:42 +0200 (MEST) Mikael Pettersson wrote: > While compiling 2.6.17-rc6 for a 486 with an NE2000 ISA ethernet card, I got: > > WARNING: drivers/net/ne.o - Section mismatch: reference to .init.data:isapnp_clone_list from .text between 'init_module' (at offset 0x158) and 'ne_block_input' > WARNING: drivers/net/ne.o - Section mismatch: reference to .init.data:isapnp_clone_list from .text between 'init_module' (at offset 0x176) and 'ne_block_input' > WARNING: drivers/net/ne.o - Section mismatch: reference to .init.data:isapnp_clone_list from .text between 'init_module' (at offset 0x183) and 'ne_block_input' > WARNING: drivers/net/ne.o - Section mismatch: reference to .init.data:isapnp_clone_list from .text between 'init_module' (at offset 0x1ea) and 'ne_block_input' > WARNING: drivers/net/ne.o - Section mismatch: reference to .init.data:isapnp_clone_list from .text between 'init_module' (at offset 0x251) and 'ne_block_input' > WARNING: drivers/net/ne.o - Section mismatch: reference to .init.text: from .text between 'init_module' (at offset 0x266) and 'ne_block_input' > WARNING: drivers/net/ne.o - Section mismatch: reference to .init.text: from .text between 'init_module' (at offset 0x29b) and 'ne_block_input' > > Not sure how serious this is; the driver seems to work fine later on. Doesn't look serious. init_module() is not __init, but it calls some __init functions and touches some __initdata. BTW, I would be happy to see some consistent results from modpost section checking. I don't see all of these warnings (I see only 1) when using gcc 3.3.6. What gcc version are you using? Does that matter? (not directed at anyone in particular) Patch below fixes it for me. Please test/report. Signed-off-by: Jeff Garzik commit 282f33c98618a3877043ec9dd5ac777c5e7c117d Author: Linas Vepstas Date: Thu Jun 8 22:19:44 2006 -0700 [PATCH] e1000: prevent statistics from getting garbled during reset If a PCI bus error/fault triggers a PCI bus reset, attempts to get the ethernet packet count statistics from the hardware will fail, returning garbage data upstream. This patch skips statistics data collection if the PCI device is not on the bus. This patch presumes that an earlier patch, [PATCH] PCI Error Recovery: e1000 network device driver has already been applied. Signed-off-by: Linas Vepstas Cc: John Ronciak Cc: Jesse Brandeburg Cc: Jeff Kirsher Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik commit b89fa8b6d738d71c3a9eff584177bb7de13f33b9 Author: Andrew Morton Date: Thu Jun 8 22:19:41 2006 -0700 [PATCH] smc911x Kconfig fix In file included from drivers/net/smc911x.c:84: drivers/net/smc911x.h:46:9: warning: "SMC_USE_16BIT" is not defined drivers/net/smc911x.h:60:9: warning: "SMC_USE_32BIT" is not defined drivers/net/smc911x.h:73:10: warning: "SMC_USE_PXA_DMA" is not defined drivers/net/smc911x.c: In function `smc911x_reset': drivers/net/smc911x.c:247: warning: implicit declaration of function `SMC_inl' drivers/net/smc911x.c:249: warning: implicit declaration of function `SMC_outl' Cc: Dustin McIntire Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik commit 1049cb478783c74ca8c99ef70e7d2bf920b9335b Author: Tejun Heo Date: Thu Jun 8 22:15:42 2006 -0700 [PATCH] libata: add missing ->data_xfer for pdc_adma pdc_adma use libata-core PIO path but were left out during ->data_xfer conversion. Initialize with proper callbacks. This patch is against the current libata-dev#ALL. Controllers which implement their own PIO HSM (ahci and sil24) don't need ->data_xfer, so the above two are the only drivers which were left out during conversion. From: "Barry K. Nathan" Signed-off-by: Barry K. Nathan Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik commit c99ce7ee75db7836e2faba932affd2aadd1e942f Author: Ayaz Abdulla Date: Sat Jun 10 22:48:28 2006 -0400 [PATCH] forcedeth: new device ids This patch contains new device ids for forcedeth ethernet. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit ebe611a48378f8f5c347d86dc403a2d56c320f1c Author: Ayaz Abdulla Date: Sat Jun 10 22:48:24 2006 -0400 [PATCH] forcedeth config: version This patch bumps up the version number for config support. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit 69fe3fd7b1adac55f794cb2b34cb1c13a0b19f05 Author: Ayaz Abdulla Date: Sat Jun 10 22:48:18 2006 -0400 [PATCH] forcedeth config: module parameters This patch adds (and modifies) module parameter support. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit 9589c77a0de19c0c95370d5212eb1f9006d8abcb Author: Ayaz Abdulla Date: Sat Jun 10 22:48:13 2006 -0400 [PATCH] forcedeth config: diagnostics This patch adds support for diagnostic tests through ethtool support. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit 7a1854b7977d36360fde4e06c2d9cedcc3dd0933 Author: Ayaz Abdulla Date: Sat Jun 10 22:48:08 2006 -0400 [PATCH] forcedeth config: move functions This patch moves a few functions (no logic change) so that the next patch has these functions defined. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit 52da35789c305f6f44d0e85b294a9845c1271898 Author: Ayaz Abdulla Date: Sat Jun 10 22:48:04 2006 -0400 [PATCH] forcedeth config: statistics This patch exposes hardware statistic counters through ethtool support. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit 5ed2616f621b41d3477d4f4ae2ba0e0a0e80bdce Author: Ayaz Abdulla Date: Sat Jun 10 22:47:59 2006 -0400 [PATCH] forcedeth config: csum This patch allows for configurable rx and tx checksum offloads through ethtool support. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit c42d9df932ce3732044dc1394114380140ccffe0 Author: Ayaz Abdulla Date: Sat Jun 10 22:47:52 2006 -0400 [PATCH] forcedeth config: wol This patch fixes configuration bugs when modifying wol settings. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit f9430a015a4331ba950eba1d7661dcd876c29f3c Author: Ayaz Abdulla Date: Sat Jun 10 22:47:47 2006 -0400 [PATCH] forcedeth config: phy This patch fixes configuration bugs when modifying phy settings. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit b6d0773fa7943fd93d564056395a7ff29b81213b Author: Ayaz Abdulla Date: Sat Jun 10 22:47:42 2006 -0400 [PATCH] forcedeth config: flow control This patch allows for configurable flow control through ethtool support. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit eafa59f6bcc6e46b756198a5388d195c4f0e671a Author: Ayaz Abdulla Date: Sat Jun 10 22:47:34 2006 -0400 [PATCH] forcedeth config: ring sizes This patch allows for configurable ring size through ethtool support. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit 6a78814f6c9e35e9b4815c1973c988555212d6ef Author: Ayaz Abdulla Date: Sat Jun 10 22:47:26 2006 -0400 [PATCH] forcedeth config: tso cleanup There are a series of patches for configuration support in forcedeth and one patch for device ids. This patch is a cleanup of the a previous TSO patch. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit 6218a761bbc27acc65248c80024875bcc06d52b1 Author: Paul Mackerras Date: Sun Jun 11 14:15:17 2006 +1000 powerpc: add context.vdso_base for 32-bit too This adds a vdso_base element to the mm_context_t for 32-bit compiles (both for ARCH=powerpc and ARCH=ppc). This fixes the compile errors that have been reported in arch/powerpc/kernel/signal_32.c. Signed-off-by: Paul Mackerras commit 9a9c77dc4c4eed9dfb74080e768c0b3c9d905496 Author: Tejun Heo Date: Sun Jun 11 11:19:00 2006 +0900 [PATCH] libata: cosmetic change in struct ata_port Cosmetic change in struct ata_port. Signed-off-by: Tejun Heo commit 0a1b622ef495d8ebba9ad8982414c6661c16b604 Author: Tejun Heo Date: Sun Jun 11 11:01:38 2006 +0900 [PATCH] libata: add missing finish_wait() call in ata_port_wait_eh() Add missing finish_wait() call after wait loop in ata_port_wait_eh(). Signed-off-by: Tejun Heo commit 8d7feac3c7504425aaf61dc7d804685a6b89ee43 Author: Christoph Hellwig Date: Sat Jun 10 18:37:19 2006 +0200 [SCSI] remove RQ_SCSI_* flags The RQ_SCSI_* flags are a vestiage of a long past history. The EH code still sets them but we never make use of that information. The other users is pluto.c which never had a chance to work but needs to be kept compiling to keep Davem happy, so copy over the definition there. We could probably get rid of RQ_ACTIVE/RQ_INACTIVE aswell with some work, there's only two more or less bogus looking uses in ubd and scsi. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley commit beb40487508290f5d6565598c60a3f44261beef2 Author: Christoph Hellwig Date: Sat Jun 10 18:01:03 2006 +0200 [SCSI] remove scsi_request infrastructure With Achim patch the last user (gdth) is switched away from scsi_request so we an kill it now. Also disables some code in i2o_scsi that was broken since the sg driver stopped using scsi_requests. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley commit 1951d099dfd8fa529e86f4ac81d1a34554fbe302 Author: Michael Reed Date: Wed May 24 15:08:10 2006 -0500 [SCSI] mptfusion: change driver revision to 3.03.10 Bump driver version number to reflect addition of various fibre channel patches. Signed-off-by: Michael Reed Signed-off-by: James Bottomley commit d6be06c84da9626b10443c664ee55bda96fb3514 Author: Michael Reed Date: Wed May 24 15:07:57 2006 -0500 [SCSI] mptfc: abort of board reset leaves port dead requiring reboot The driver uses msleep_interruptible() in the code path responsible for resetting the card's ports via the lsiutil command. If a is received during the reset it can leave a port in such a state that the only way to regain its use is to reboot the system. Changing from msleep_interruptible() to msleep() corrects the problem. Signed-off-by: Michael Reed Signed-off-by: James Bottomley commit 419835e285c3e39cd62c8c8426da0aebea9cd89f Author: Michael Reed Date: Wed May 24 15:07:40 2006 -0500 [SCSI] mptfc: fix fibre channel infinite request/response loop While doing board reset testing I was able to put the system in an infinite request/response loop between the scsi layer and mptscsih_qcmd() by aborting the reset. This patch installs a "SETUP RESET" handler which calls fc_remote_port_delete() for all registered rports. This blocks the target which prevents the loop. Additionally, should the reset fail to complete, the transport will now terminate i/o to the target. Signed-off-by: Michael Reed Signed-off-by: James Bottomley commit ca2f938efe71ca48cbc689db4df8d4f04b5d8f07 Author: Michael Reed Date: Wed May 24 15:07:24 2006 -0500 [SCSI] mptfc: set fibre channel fw target missing timers to one second The fibre channel firmware provides a timer which is similar in purpose to the fibre channel transport's device loss timer. The effect of this timer is to extend the total time that a target will be missing beyond the value associated with the transport's timer. This patch changes the firmware timer to a default of one second which significantly reduces the lag between when a target goes missing and the notification of the fibre channel transport. Signed-off-by: Michael Reed Signed-off-by: James Bottomley commit 80d3ac77a84987d5132726f3d7cef342a280f7d9 Author: Michael Reed Date: Wed May 24 15:07:09 2006 -0500 [SCSI] mptfusion: move fc event/reset handling to mptfc Move fibre channel event and reset handling to mptfc. This will result in fewer changes over time that need to be applied to either mptbase.c or mptscsih.c. Signed-off-by: Michael Reed Signed-off-by: James Bottomley commit 60eef25701d25e99c991dd0f4a9f3832a0c3ad3e Author: James Bottomley Date: Sat Jun 10 10:51:23 2006 -0500 [SCSI] spi transport: don't allow dt to be set on SE or HVD buses This is really just a belt and braces test. The standards require disks to respond DT not capable on a non-LVD bus ... however, not all disks follow the standards ... Signed-off-by: James Bottomley commit b2d8bfe18578c4e50e8ba52011c9b260a1b51dac Author: James Bottomley Date: Sat Jun 10 10:49:07 2006 -0500 [SCSI] aic7xxx: expose the bus setting to sysfs Read the transciever register and display in the host transport properties. I'm still not entirely sure what this does for multiple transciever adapters (like some 160 ones) however, I suspect it displays the transciever state of the switchable bus segment. Signed-off-by: James Bottomley commit b9f051eb6cc013b90cb6062a1e2502e9c0adf0f4 Author: Arthur Othieno Date: Thu Jun 8 22:23:45 2006 -0700 [SCSI] scsi: remove Documentation/scsi/cpqfc.txt cpqfc driver flushed out with: [SCSI] remove broken driver cpqfc (commit ca61f10ab2b874b889e89d14ea09fae2dcccdca6) but somehow Documentation/scsi/cpqfc.txt managed to survive the blast. Signed-off-by: Arthur Othieno Signed-off-by: Andrew Morton Signed-off-by: James Bottomley commit 6391a11375de5e2bb1eb8481e54619761dc65d9f Author: Tobias Klauser Date: Thu Jun 8 22:23:48 2006 -0700 [SCSI] drivers/scsi: Use ARRAY_SIZE macro Use ARRAY_SIZE macro instead of sizeof(x)/sizeof(x[0]) and remove duplicates of the macro. Signed-off-by: Tobias Klauser Signed-off-by: Andrew Morton Signed-off-by: James Bottomley commit 9dc399de0840a478adb71278becf598d3ab3aacc Author: Guennadi Liakhovetski Date: Fri Jun 9 22:25:23 2006 +0200 [SCSI] Remove last page_address from dc395x.c Dynamically map scattergather buffer instead of using page_address(). Signed-off-by: Guennadi Liakhovetski Signed-off-by: James Bottomley commit ede1e6f8b43246a9796583346839669b1f4b77d4 Author: HighPoint Linux Team Date: Tue May 16 14:38:09 2006 +0800 [SCSI] hptiop: HighPoint RocketRAID 3xxx controller driver HighPoint RocketRAID 3220/3320 series 8 channel PCI-X SATA RAID Host Adapters. Fixes from original submission: Merge Andrew Morton's patches: - Provide locking for global list - Fix debug printks - uninline function with multiple callsites - coding style fixups - remove unneeded casts of void* - kfree(NULL) is legal - Don't "succeed" if register_chrdev() failed - otherwise we'll later unregister a not-registered chrdev. - Don't return from hptiop_do_ioctl() with the spinlock held. - uninline __hpt_do_ioctl() Update for Arjan van de Ven's comments: - put all asm/ includes after the linux/ ones - replace mdelay with msleep - add pci posting flush - do not set pci command reqister in map_pci_bar - do not try merging sg elements in hptiop_buildsgl() - remove unused outstandingcommands member from hba structure - remove unimplemented hptiop_abort() handler - remove typedef u32 hpt_id_t Other updates: - fix endianess Signed-off-by: HighPoint Linux Team Signed-off-by: James Bottomley commit cbd5f69b98bb5d7a0d207230bcf8fa51fca3f3cf Author: Leubner, Achim Date: Fri Jun 9 11:34:29 2006 -0700 [SCSI] remove the scsi_request interface from the gdth driver Initial pass at converting the gdth driver away from the scsi_request interface so that the request interface can be removed post 2.6.18 without breaking gdth. Based on changes from Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: James Bottomley commit 050613545b389825c1f5beb67fa2667b727f866d Author: Paul Mackerras Date: Sat Jun 10 18:17:35 2006 +1000 powerpc: Fix bug in iommu_alloc_coherent causing hang during boot In commit 8eb6c6e3b9c8bfed3d75536ab142d7694627c2e5, Christoph Hellwig made iommu_alloc_coherent able to do node-local allocations, but unfortunately got the order of the arguments to alloc_pages_node wrong. This fixes it. Signed-off-by: Paul Mackerras commit 566f81ca598f80de03e80a9a743e94b65b4e017e Author: Sam Ravnborg Date: Sat Jun 10 09:15:27 2006 +0200 kbuild: ignore make's built-in rules & variables kbuild does explicitly specify what to do in all cases, and each time make's built-in rules & variables has been used it has been a bug. So to speed up things and to avoid the hard-to-debug error situations ignore the built-in definitions. If any part of the kernel uses the built-in definitions the build will just stop there and it should be trivial to fix. Signed-off-by: Sam Ravnborg commit ff5417107b7615fcef772cabcb717f4a715ffadc Author: Nickolay Date: Fri Jun 9 21:24:14 2006 +0400 kbuild: bugfix with initramfs This patch fix double inclusion of ramfs-input. Signed-off-by: Nickolay Vinogradov Signed-off-by: Sam Ravnborg commit 6449bd621ba51ef652ac5bda632eeabbc18dd296 Author: Andrew Morton Date: Fri Jun 9 20:45:06 2006 -0700 kbuild: modpost build fix scripts/mod/modpost.c: In function `check_license': scripts/mod/modpost.c:1094: parse error before `const' scripts/mod/modpost.c:1095: `basename' undeclared (first use in this function) scripts/mod/modpost.c:1095: (Each undeclared identifier is reported only once scripts/mod/modpost.c:1095: for each function it appears in.) Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit f9068876f5ef583f8e9ebf4acd2ef5b35b113db9 Author: David Woodhouse Date: Sat Jun 10 00:53:16 2006 +0100 [MTD NAND] Fix s3c2410 NAND driver so it at least _looks_ like it compiles Fix the control bit handling so it even looks like it might work, too. Bad tglx. No biscuit. Signed-off-by: David Woodhouse commit b817f6feff4a565b08f0e699a5790b4008b8f494 Author: Sam Ravnborg Date: Fri Jun 9 21:53:55 2006 +0200 kbuild: check license compatibility when building modules Modules that uses GPL symbols can no longer be build with kbuild, the build will fail during the modpost step. When a GPL-incompatible module uses a EXPORT_SYMBOL_GPL_FUTURE symbol then warn during modpost so author are actually notified. The actual license compatibility check is shared with the kernel to make sure it is in sync. Patch originally from: Andreas Gruenbacher and Ram Pai Signed-off-by: Sam Ravnborg commit bd5cbcedf446e2f37cf2a37f533a7e1d7dff9312 Author: Ram Pai Date: Thu Jun 8 22:12:53 2006 -0700 kbuild: export-type enhancement to modpost.c This patch provides the ability to identify the export-type of each exported symbols in Module.symvers. NOTE: It updates the Module.symvers file with the additional information as shown below. 0x0f8b92af platform_device_add_resources vmlinux EXPORT_SYMBOL_GPL 0xcf7efb2a ethtool_op_set_tx_csum vmlinux EXPORT_SYMBOL Signed-off-by: Andreas Gruenbacher Signed-off-by: Ram Pai Signed-off-by: Avantika Mathur Signed-off-by: Valdis Kletnieks Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit 031ecc6de7d17752c57720a118a37e97a8454872 Author: Zach Brown Date: Thu Jun 8 22:12:37 2006 -0700 kbuild: add dependency on kernel.release to the package targets The binrpm-pkg target uses KERNELRELEASE when generated its .spec file. When binrpm-pkg was the first build target run in a tree it generated the .spec before kernel.release so the Version: tag in the .spec was empty. I don't know if this is the best fix, but binrpm-pkg works when we explicitly build kernel.release before descending into package-dir. Signed-off-by: Zach Brown Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit c30a02e022576c1b49a6c9b39ad83559167399c6 Author: Roman Zippel Date: Thu Jun 8 22:12:50 2006 -0700 kbuild: `make kernelrelease' speedup Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit 14cdd3c402bf7c66f0bcd76e290f0770a54a4b21 Author: Roman Zippel Date: Thu Jun 8 22:12:51 2006 -0700 kconfig: KCONFIG_OVERWRITECONFIG If you set KCONFIG_OVERWRITECONFIG in environment, Kconfig will not break symlinks when .config is a symlink to somewhere else. Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit 250725aa13f5c9595e5bc265ebed8471e816d8b4 Author: Randy Dunlap Date: Thu Jun 8 22:12:50 2006 -0700 kconfig: exit if no beginning filename If the beginning Kconfig file is missing, config segfaults so it might as well exit after the error message. Signed-off-by: Randy Dunlap Cc: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit e55a3e8aed99626dd9a9a6732fc0eb5b75ef29bd Author: Roman Zippel Date: Thu Jun 8 22:12:49 2006 -0700 kconfig: remove leading whitespace in menu prompts This removes all the leading whitespace kconfig now warns about. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit f001f7f89689d3226678ab3986f3a486f54aa069 Author: Roman Zippel Date: Thu Jun 8 22:12:48 2006 -0700 kconfig: warn about leading whitespace for menu prompts Kconfig does its own indentation of menu prompts, so warn about and ignore leading whitespace. Remove also a few unnecessary newlines after other warning prints. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit b65a47e1ac494777d853d7952cef611eedc22037 Author: Roman Zippel Date: Thu Jun 8 22:12:47 2006 -0700 kconfig: jump to linked menu prompt If clicking on of the links, which leads to a visible prompt, jump to it in the symbol list. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit ab45d190fd4acf0b0e5d307294ce24a90a69cc23 Author: Roman Zippel Date: Thu Jun 8 22:12:47 2006 -0700 kconfig: create links in info window Extend the expression print helper function to allow customization of the symbol output and use it to add links to the info window. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit f24ff6bf8c903bc0c645bf87fbe87f9a6d9f634f Author: Andrew Morton Date: Fri Jun 9 15:12:34 2006 +0100 [MTD] Prepare physmap for 64-bit-resources Fallout from the incoming 64-bit-resource stuff: drivers/mtd/maps/physmap.c: In function 'physmap_flash_probe': drivers/mtd/maps/physmap.c:94: warning: format '%.8lx' expects type 'long unsigned int', but argument 2 has type 'resource_size_t' drivers/mtd/maps/physmap.c:94: warning: format '%.8lx' expects type 'long unsigned int', but argument 3 has type 'resource_size_t' Cc: Vivek Goyal Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse commit 4ed0156f774cf50252e7f51032d1cc857fe86879 Author: David Woodhouse Date: Fri Jun 9 15:06:42 2006 +0100 [JFFS2] Fix more breakage caused by janitorial meddling. jffs2_zlib_exit() and free_workspaces() shouldn't be marked __exit because they get called in the error case from the init functions. Signed-off-by: David Woodhouse commit 28df955a2ad484d602314b30183ea8496a9aa34a Author: Trond Myklebust Date: Fri Jun 9 09:40:27 2006 -0400 NLM: Fix reclaim races Currently it is possible for a task to remove its locks at the same time as the NLM recovery thread is trying to recover them. This quickly leads to an Oops. Protect the locks using an rw semaphore while they are being recovered. Signed-off-by: Trond Myklebust commit 5046791417dcac1ba126b77b8062af15a2f0b8e1 Author: Trond Myklebust Date: Fri Jun 9 09:40:24 2006 -0400 NLM: sem to mutex conversion Signed-off-by: Trond Myklebust commit 3134cbec5e172c3a86e2c3ef4af34b6cfd380bfa Author: Marc Eshel Date: Fri Jun 9 09:40:20 2006 -0400 locks.c: add the fl_owner to nlm_compare_locks Add the fl_owner to NLM compare locks. Since two different client can present the same pid to the server it is not enough to distinguish locks from different clients. The fl_owner field is a pointer to the struct nlm_host which is unique for each client. Signed-off-by: Marc Eshel Signed-off-by: Trond Myklebust commit 81039f1f204a0fd2952112a240284e114f1a25e6 Author: Trond Myklebust Date: Fri Jun 9 09:34:34 2006 -0400 NFS: Display the chosen RPCSEC_GSS security flavour in /proc/mounts Signed-off-by: Trond Myklebust commit f7b422b17ee5ee4920e8ae24a6ad04bf3481ce72 Author: David Howells Date: Fri Jun 9 09:34:33 2006 -0400 NFS: Split fs/nfs/inode.c As fs/nfs/inode.c is rather large, heterogenous and unwieldy, the attached patch splits it up into a number of files: (*) fs/nfs/inode.c Strictly inode specific functions. (*) fs/nfs/super.c Superblock management functions for NFS and NFS4, normal access, clones and referrals. The NFS4 superblock functions _could_ move out into a separate conditionally compiled file, but it's probably not worth it as there're so many common bits. (*) fs/nfs/namespace.c Some namespace-specific functions have been moved here. (*) fs/nfs/nfs4namespace.c NFS4-specific namespace functions (this could be merged into the previous file). This file is conditionally compiled. (*) fs/nfs/internal.h Inter-file declarations, plus a few simple utility functions moved from fs/nfs/inode.c. Additionally, all the in-.c-file externs have been moved here, and those files they were moved from now includes this file. For the most part, the functions have not been changed, only some multiplexor functions have changed significantly. I've also: (*) Added some extra banner comments above some functions. (*) Rearranged the function order within the files to be more logical and better grouped (IMO), though someone may prefer a different order. (*) Reduced the number of #ifdefs in .c files. (*) Added missing __init and __exit directives. Signed-Off-By: David Howells commit 4e5ccf60c5aa79d325c123f47d288a068166f389 Author: Trond Myklebust Date: Fri Jun 9 09:34:32 2006 -0400 NFS: Fix typo in nfs_do_clone_mount() Doh! Signed-off-by: Trond Myklebust commit 860de07139980afe9856cc31eb5efbf321bbcea4 Author: Trond Myklebust Date: Fri Jun 9 09:34:31 2006 -0400 NFS: Fix compile errors introduced by referrals patches Signed-off-by: Trond Myklebust commit 87e4ba1a62af8e05ee3e8f8aaca622714386ffb0 Author: Trond Myklebust Date: Fri Jun 9 09:34:30 2006 -0400 NFSv4: Ensure that referral mounts bind to a reserved port Signed-off-by: Trond Myklebust commit 33a43f2802d8d7be3a9b541785c4ca9ad79e4310 Author: Andy Adamson Date: Fri Jun 9 09:34:30 2006 -0400 NFSv4: A root pathname is sent as a zero component4 Signed-off-by: Trond Myklebust commit 6b97fd3da1eab2cc490cfe884c7d4956522eaf8b Author: Manoj Naik Date: Fri Jun 9 09:34:29 2006 -0400 NFSv4: Follow a referral Respond to a moved error on NFS lookup by setting up the referral. Note: We don't actually follow the referral during lookup/getattr, but later when we detect fsid mismatch in inode revalidation (similar to the processing done for cloning submounts). Referrals will have fake attributes until they are actually followed or traversed. Signed-off-by: Manoj Naik Signed-off-by: Trond Myklebust commit 9cdb3883c38f883436a84c2353a4cf964ff890a2 Author: Manoj Naik Date: Fri Jun 9 09:34:28 2006 -0400 NFSv4: Ensure client submounts when following a referral Set up mountpoint when hitting a referral on moved error by getting fs_locations. Signed-off-by: Manoj Naik Signed-off-by: Trond Myklebust commit 61f5164cab1f6fdf06871ea9d60fe2f912184078 Author: Manoj Naik Date: Fri Jun 9 09:34:27 2006 -0400 NFS: Expand clone mounts to include other servers Signed-off-by: Manoj Naik Signed-off-by: Trond Myklebust commit c818ba43f9ca2e8214412ab5f126b1f436c35098 Author: Manoj Naik Date: Fri Jun 9 09:34:26 2006 -0400 NFSv4: Create NFSv4 transport and client Move existing code into a separate function so that it can be also used by referral code. Signed-off-by: Manoj Naik Signed-off-by: Trond Myklebust commit 830b8e33fe1900b87c8eb7ec5c646117a9f298d6 Author: Manoj Naik Date: Fri Jun 9 09:34:25 2006 -0400 NFSv4: Define an fs_locations bitmap This is (similar to getattr bitmap) but includes fs_locations and mounted_on_fileid attributes. Use this bitmap for encoding in fs_locations requests. Note: We can probably do better by requesting locations as part of fsinfo itself. Signed-off-by: Manoj Naik Signed-off-by: Trond Myklebust commit 361e624f6d8bfbeac53769603d995d47535cfd46 Author: Manoj Naik Date: Fri Jun 9 09:34:24 2006 -0400 NFSv4: GETATTR attributes on referral Per referral draft, only fs_locations, fsid, and mounted_on_fileid can be requested in a GETATTR on referrals. Signed-off-by: Manoj Naik Signed-off-by: Trond Myklebust commit 99baf625d3b9b8944920acc7c2d06079a37458c5 Author: Manoj Naik Date: Fri Jun 9 09:34:24 2006 -0400 NFSv4: Decode mounted_on_fileid attribute in getattr. It is ignored if fileid is also requested. This will be used on referrals (fs_locations). Signed-off-by: Manoj Naik Signed-off-by: Trond Myklebust commit 7aaa0b3bd4d215d9ce4d62b6c2043a63ba650f93 Author: Manoj Naik Date: Fri Jun 9 09:34:23 2006 -0400 NFSv4: convert fs-locations-components to conform to RFC3530 Use component4-style formats for decoding list of servers and pathnames in fs_locations. Signed-off-by: Manoj Naik Signed-off-by: Trond Myklebust commit 683b57b435326eb512c7305892683b6205669448 Author: Trond Myklebust Date: Fri Jun 9 09:34:22 2006 -0400 NFSv4: Implement the fs_locations function call NFSv4 allows for the fact that filesystems may be replicated across several servers or that they may be migrated to a backup server in case of failure of the primary server. fs_locations is an NFSv4 operation for retrieving information about the location of migrated and/or replicated filesystems. Based on an initial implementation by Jiaying Zhang Signed-off-by: Trond Myklebust commit 8b23ea7bedb8b45a5bb56745fa3ff11018acf04e Author: Trond Myklebust Date: Fri Jun 9 09:34:21 2006 -0400 RPC: Allow struc xdr_stream to read the page section of an xdr_buf Signed-off-by: Trond Myklebust commit 51d8fa6a109589d522c18a8e9bf3fb167a91b1bc Author: Trond Myklebust Date: Fri Jun 9 09:34:20 2006 -0400 NFS: Add timeout to submounts Make automounted partitions expire using the mark_mounts_for_expiry() function. The timeout is controlled via a sysctl. Signed-off-by: Trond Myklebust commit 55a975937d40cac582e981ddc8ed783b3dcc043c Author: Trond Myklebust Date: Fri Jun 9 09:34:19 2006 -0400 NFS: Ensure the client submounts, when it crosses a server mountpoint. Signed-off-by: Trond Myklebust commit 8b4bdcf8995dd92b23d2ec22b32aee8fbbb50e1c Author: Trond Myklebust Date: Fri Jun 9 09:34:19 2006 -0400 NFS: Store the file system "fsid" value in the NFS super block. This should enable us to detect if we are crossing a mountpoint in the case where the server is exporting "nohide" mounts. Signed-off-by: Trond Myklebust commit 8b512d9a88875affe584bb3d2a7a235f84343b9e Author: Trond Myklebust Date: Fri Jun 9 09:34:18 2006 -0400 VFS: Remove dependency of ->umount_begin() call on MNT_FORCE Allow filesystems to decide to perform pre-umount processing whether or not MNT_FORCE is set. Signed-off-by: Trond Myklebust commit 5528f911b4c43a5de5da34bcbd7e3f2a62503617 Author: Trond Myklebust Date: Fri Jun 9 09:34:17 2006 -0400 VFS: Add shrink_submounts() Allow a submount to be marked as being 'shrinkable' by means of the vfsmount->mnt_flags, and then add a function 'shrink_submounts()' which attempts to recursively unmount these submounts. Signed-off-by: Trond Myklebust commit 1f5ce9e93aa96a867f195ed45f6f77935175f12e Author: Trond Myklebust Date: Fri Jun 9 09:34:16 2006 -0400 VFS: Unexport do_kern_mount() and clean up simple_pin_fs() Replace all module uses with the new vfs_kern_mount() interface, and fix up simple_pin_fs(). Signed-off-by: Trond Myklebust commit bb4a58bf46473e3e83d84054bbc110db3a0f85e4 Author: Trond Myklebust Date: Fri Jun 9 09:34:15 2006 -0400 VFS: Add GPL_EXPORTED function vfs_kern_mount() do_kern_mount() does not allow the kernel to use private mount interfaces without exposing the same interfaces to userland. The problem is that the filesystem is referenced by name, thus meaning that it and its mount interface must be registered in the global filesystem list. vfs_kern_mount() passes the struct file_system_type as an explicit parameter in order to overcome this limitation. Signed-off-by: Trond Myklebust commit da6d503aa0a75ec44f17d985a2b500077e7f6a74 Author: Trond Myklebust Date: Thu Jun 1 17:26:35 2006 -0400 NFS: Remove nfs_delete_inode() Now that we have a real nfs_invalidate_page() to ensure that truncate_inode_pages() does the right thing when there are pending dirty pages, we can get rid of nfs_delete_inode(). Signed-off-by: Trond Myklebust commit d2ccddf042c403b146159beea438c6bfc4a445e2 Author: Trond Myklebust Date: Wed May 31 01:13:38 2006 -0400 NFS: Flesh out nfs_invalidate_page() In the case of a call to truncate_inode_pages(), we should really try to cancel any pending writes on the page. Signed-off-by: Trond Myklebust commit c04871e6345e4c6dfda564e302d7fd8c66420fd5 Author: J. Bruce Fields Date: Tue May 30 16:28:58 2006 -0400 NFSv4: remove obviously bogus comparison from decode_getacl We just set *acl_len to zero, and attrlen is unsigned, so this comparison is clearly bogus. I have no idea what I was thinking. Fixes a bug that caused getacl to fail over krb5p. Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust commit 3873bc50e2271504da45799257f69222774d9550 Author: Alexey Dobriyan Date: Sat May 27 03:31:12 2006 +0400 NFSv4: really return status from decode_recall_args() Signed-off-by: Alexey Dobriyan Signed-off-by: Trond Myklebust commit 4814f56d19137b3b9fa8e00e1d332b3683b950de Author: Andreas Gruenbacher Date: Thu May 25 01:41:03 2006 -0400 NFSv3: Client-side nfsacl caching fix Fix two errors in the client-side acl cache: First, when nfs3_proc_getacl requests only the default acl of a file and the access acl is not cached already, a NULL access acl entry is cached instead of ERR_PTR(-EAGAIN) ("not cached"). Second, update the cached acls in nfs3_proc_setacls: nfs_refresh_inode does not always invalidate the cached acls, and when it does not, the cached acls get out of sync. Signed-off-by: Andreas Gruenbacher Signed-off-by: Trond Myklebust commit 1842bfb447cea8b344fd91af97fb6d604ecb11fa Author: Trond Myklebust Date: Thu May 25 01:41:01 2006 -0400 NFS: Fix up inode revalidation accounting Currently, we are accounting for all calls to nfs_revalidate_inode(), but not to nfs_revalidate_mapping(), or nfs_lookup_verify_inode(), etc... Signed-off-by: Trond Myklebust commit 44b11874ff583b6e766a05856b04f3c492c32b84 Author: Trond Myklebust Date: Thu May 25 01:40:59 2006 -0400 NFS: Separate metadata and page cache revalidation mechanisms Separate out the function of revalidating the inode metadata, and revalidating the mapping. The former may be called by lookup(), and only really needs to check that permissions, ctime, etc haven't changed whereas the latter needs only done when we want to read data from the page cache, and may need to sync and then invalidate the mapping. Signed-off-by: Trond Myklebust commit 38478b24e37587f1c4fedf8ac070ca54f052ed28 Author: Trond Myklebust Date: Thu May 25 01:40:57 2006 -0400 NFS: More page cache revalidation fixups Whenever the directory changes, we want to make sure that we always invalidate its page cache. Fix up update_changeattr() and nfs_mark_for_revalidate() so that they do so. Signed-off-by: Trond Myklebust commit f1bb0b92ba2cdfffe6e437f7a7da53138cf08d52 Author: Trond Myklebust Date: Thu May 25 01:40:55 2006 -0400 NFS: Fix page cache revalidation Fix up a bug in the handling of NFS_INO_REVAL_PAGECACHE: make sure that nfs_update_inode() clears it when we're sure we're not racing with other updates. Signed-off-by: Trond Myklebust commit 0d0b5cb36faf7002a11736032313f06d6f3d881c Author: Chuck Lever Date: Thu May 25 01:40:53 2006 -0400 NFS: Optimize allocation of nfs_read/write_data structures Clean up use of page_array, and fix an off-by-one error noticed by Tom Talpey which causes kmalloc calls in cases where using the page_array is sufficient. Test plan: Normal client functional testing with r/wsize=32768. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust commit bf3fcf89552f24657bcfb6a9d73cd167ebb496c6 Author: Chuck Lever Date: Thu May 25 01:40:51 2006 -0400 SUNRPC: NFS_ROOT always uses the same XIDs The XID generator uses get_random_bytes to generate an initial XID. NFS_ROOT starts up before the random driver, though, so get_random_bytes doesn't set a random XID for NFS_ROOT. This causes NFS_ROOT mount points to reuse XIDs every time the client is booted. If the client boots often enough, the server will start serving old replies out of its DRC. Use net_random() instead. Test plan: I/O intensive workloads should perform well and generate no errors. Traces taken during client reboots should show that NFS_ROOT mounts use unique XIDs after every reboot. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust commit b85d88068444ae5dcb1639bcef770ccbf085dd4e Author: Chuck Lever Date: Thu May 25 01:40:49 2006 -0400 SUNRPC: select privileged port numbers at random Make the RPC client select privileged ephemeral source ports at random. This improves DRC behavior on the server by using the same port when reconnecting for the same mount point, but using a different port for fresh mounts. The Linux TCP implementation already does this for nonprivileged ports. Note that TCP sockets in TIME_WAIT will prevent quick reuse of a random ephemeral port number by leaving the port INUSE until the connection transitions out of TIME_WAIT. Test plan: Connectathon against every known server implementation using multiple mount points. Locking especially. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust commit 73a3d07c1082145a3b78407bb5252df290470c4c Author: Trond Myklebust Date: Thu May 25 01:40:47 2006 -0400 NFS: Clean up inode metadata updates Signed-off-by: Trond Myklebust commit 9d1e9232223a7f065be7f956a7b749a4cbbbe16d Author: Trond Myklebust Date: Thu May 25 01:40:46 2006 -0400 NFSv4: Some NFSv4 servers have broken behaviour for the change attribute The Linux NFSv4 server violates RFC3530 in that the change attribute is not guaranteed to be updated for every change to the inode. Our optimisation for checking whether or not the inode metadata has changed or not is broken too. Grr.... Signed-off-by: Trond Myklebust commit 1de3fc12ea085690547a54b6efa01c7348f1cebd Author: Trond Myklebust Date: Thu May 25 01:40:44 2006 -0400 NFS: Clean up and fix page zeroing when we have short reads The code that is supposed to zero the uninitialised partial pages when the server returns a short read is currently broken: it looks at the nfs_page wb_pgbase and wb_bytes fields instead of the equivalent nfs_read_data values when deciding where to start truncating the page. Also ensure that we are more careful about setting PG_uptodate before retrying a short read: the retry will change the nfs_read_data args.pgbase and args.count. Signed-off-by: Trond Myklebust commit 6b81e80049a8815dc457fec4dadb6ae535c3b988 Author: Michael Ellerman Date: Wed Jun 7 17:10:09 2006 +1000 [PATCH] powerpc: Cleanup hvc_rtas.c a little A few cleanups in hvc_rtas.c: 1. Remove unused RTASCONS_PUT_ATTEMPTS 2. Remove unused rtascons_put_delay. 3. Use i as a loop counter like everyone else on earth. 4. Remove pointless variables, eg. x = foo; if (x) return something_else; 5. Whitespace cleanups and formatting. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit b53744612f276ad20c5d7ef33ac991ec13101417 Author: Michael Ellerman Date: Wed Jun 7 17:10:03 2006 +1000 [PATCH] powerpc: Make rtas console _much_ faster Currently the hvc_rtas driver is painfully slow to use. Our "benchmark" is ls -R /etc, which spits out about 27866 characters. The theoretical maximum speed would be about 2.2 seconds, the current code takes ~50 seconds. The core of the problem is that sometimes when the tty layer asks us to push characters the firmware isn't able to handle some or all of them, and so returns an error. The current code sees this and just returns to the tty code with the buffer half sent. The khvcd thread will eventually wake up and try to push more characters, which will usually work because by then the firmware's had time to make room. But the khvcd thread only wakes up every 10 milliseconds, which isn't fast enough. So change the khvcd thread logic so that if there's an incomplete write we yield() and then immediately try writing again. Doing so makes POLL_QUICK and POLL_WRITE synonymous, so remove POLL_QUICK. With this patch our "benchmark" takes ~2.8 seconds. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit e9370ae15dc2f8ba1e1889ce26f13cda565b6ecb Author: Paul Mackerras Date: Wed Jun 7 16:15:39 2006 +1000 [PATCH] powerpc: Implement PR_[GS]ET_UNALIGN prctls for powerpc This gives the ability to control whether alignment exceptions get fixed up or reported to the process as a SIGBUS, using the existing PR_SET_UNALIGN and PR_GET_UNALIGN prctls. We do not implement the option of logging a message on alignment exceptions. Signed-off-by: Paul Mackerras commit fab5db97e44f76461f76b24adfa8ccb14d4df498 Author: Paul Mackerras Date: Wed Jun 7 16:14:40 2006 +1000 [PATCH] powerpc: Implement support for setting little-endian mode via prctl This adds the PowerPC part of the code to allow processes to change their endian mode via prctl. This also extends the alignment exception handler to be able to fix up alignment exceptions that occur in little-endian mode, both for "PowerPC" little-endian and true little-endian. We always enter signal handlers in big-endian mode -- the support for little-endian mode does not amount to the creation of a little-endian user/kernel ABI. If the signal handler returns, the endian mode is restored to what it was when the signal was delivered. We have two new kernel CPU feature bits, one for PPC little-endian and one for true little-endian. Most of the classic 32-bit processors support PPC little-endian, and this is reflected in the CPU feature table. There are two corresponding feature bits reported to userland in the AT_HWCAP aux vector entry. This is based on an earlier patch by Anton Blanchard. Signed-off-by: Paul Mackerras commit 651d765d0b2c72d33430487c8b6ef64c60cd2134 Author: Anton Blanchard Date: Wed Jun 7 16:10:19 2006 +1000 [PATCH] Add a prctl to change the endianness of a process. This new prctl is intended for changing the execution mode of the processor, on processors that support both a little-endian mode and a big-endian mode. It is intended for use by programs such as instruction set emulators (for example an x86 emulator on PowerPC), which may find it convenient to use the processor in an alternate endianness mode when executing translated instructions. Note that this does not imply the existence of a fully-fledged ABI for both endiannesses, or of compatibility code for converting system calls done in the non-native endianness mode. The program is expected to arrange for all of its system call arguments to be presented in the native endianness. Switching between big and little-endian mode will require some care in constructing the instruction sequence for the switch. Generally the instructions up to the instruction that invokes the prctl system call will have to be in the old endianness, and subsequent instructions will have to be in the new endianness. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 3b5e905ee3bd23e9311951890aba57a0dbc81ca4 Author: Benjamin Herrenschmidt Date: Wed Jun 7 12:06:20 2006 +1000 [PATCH] powerpc: Add udbg-immortal kernel option When debugging early kernel crashes that happen after console_init() and before a proper console driver takes over, we often have to go hack into udbg.c to prevent it from unregistering so we can "see" what is happening. This patch adds a kernel command line option "udbg-immortal" instead to avoid having to modify the kernel. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras commit e78dbc800c37f035d476c4fdebdf43cdecfcb731 Author: Michael Neuling Date: Thu Jun 8 14:42:34 2006 +1000 [PATCH] powerpc: oprofile support for POWER6 POWER6 moves some of the MMCRA bits and also requires some bits to be cleared each PMU interrupt. Signed-off-by: Michael Neuling Acked-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 8eb6c6e3b9c8bfed3d75536ab142d7694627c2e5 Author: Christoph Hellwig Date: Tue Jun 6 16:11:35 2006 +0200 [PATCH] powerpc: node-aware dma allocations Make sure dma_alloc_coherent allocates memory from the local node. This is important on Cell where we avoid going through the slow cpu interconnect. Note: I could only test this patch on Cell, it should be verified on some pseries machine by those that have the hardware. Signed-off-by: Christoph Hellwig Signed-off-by: Paul Mackerras commit 318facbee05417fb432603a8309a10cdb942a87b Author: Christoph Hellwig Date: Tue Jun 6 16:09:39 2006 +0200 [PATCH] powerpc: implement pcibus_to_node and pcibus_to_cpumask On 64bit powerpc we can find out what node a pci bus hangs off, so implement the topology.h macros that export this information. For 32bit this seems a little more difficult, but I don't know of 32bit powerpc NUMA machines either, so let's leave it out for now. Signed-off-by: Christoph Hellwig Signed-off-by: Paul Mackerras commit 507279db1819aacf4022e790b3fc8bc8cf56debf Author: John Rose Date: Mon Jun 5 16:31:48 2006 -0500 [PATCH] powerpc: reorg RTAS delay code This patch attempts to handle RTAS "busy" return codes in a more simple and consistent manner. Typical callers of RTAS shouldn't have to manage wait times and delay calls. This patch also changes the kernel to use msleep() rather than udelay() when a runtime delay is necessary. This will avoid CPU soft lockups for extended delay conditions. Signed-off-by: John Rose Signed-off-by: Paul Mackerras commit 4a3ecc622465dbff7404139a8ad18bf4cb99f836 Author: Andrew Morton Date: Thu Jun 1 20:36:04 2006 -0700 [PATCH] powerpc kbuild warning fix From: Andrew Morton arch/powerpc/Kconfig:339:warning: leading whitespace ignored arch/powerpc/Kconfig:347:warning: leading whitespace ignored arch/powerpc/Kconfig:357:warning: leading whitespace ignored arch/powerpc/Kconfig:373:warning: leading whitespace ignored arch/powerpc/Kconfig:382:warning: leading whitespace ignored arch/powerpc/Kconfig:394:warning: leading whitespace ignored arch/powerpc/Kconfig:842:warning: leading whitespace ignored arch/powerpc/Kconfig:847:warning: leading whitespace ignored Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras commit 87af41beb9b70f06f760fc973b793488f2825853 Author: Anton Blanchard Date: Fri May 5 05:44:26 2006 +1000 [PATCH] powerpc: add num_pmcs to 970MP cputable entry The 970MP cputable entry needs a num_pmcs entry for oprofile to work. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras commit 03ac829b0046d5769eef3dd841cec33a211db96e Author: Will Schmidt Date: Tue May 30 13:38:40 2006 -0500 [PATCH] powerpc: fix of_parse_dma_window My js20 appears to lack the ibm,#dma- properties, and boot fails with a "Kernel panic - not syncing: iommu_init_table: Can't allocate 0 bytes" message. This adds a fallback to the "#address-cells" property in case the "#ibm,dma-address-cells" property is missing. Tested on js20 and power5 lpar. Unless there is a more elegant solution... :-) Signed-off-by: Will Schmidt Signed-off-by: Paul Mackerras commit c5cf0e30bf3d8cb56758abb612827647c0a821cf Author: Benjamin Herrenschmidt Date: Tue May 30 14:14:19 2006 +1000 [PATCH] powerpc: Fix buglet with MMU hash management Our MMU hash management code would not set the "C" bit (changed bit) in the hardware PTE when updating a RO PTE into a RW PTE. That would cause the hardware to possibly to a write back to the hash table to set it on the first store access, which in addition to being a performance issue, might also hit a bug when running with native hash management (non-HV) as our code is specifically optimized for the case where no write back happens. Thus there is a very small therocial window were a hash PTE can become corrupted if that HPTE has just been upgraded to read write, a store access happens on it, and that races with another processor evicting that same slot. Since eviction (caused by an almost full hash) is extremely rare, the bug is very unlikely to happen fortunately. This fixes by allowing the updating of the protection bits in the native hash handling to also set (but not clear) the "C" bit, and, in order to also improve performances in the general case, by always setting that bit on newly inserted hash PTE so that writeback really never happens. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras commit a5bba930d802009c259e56c8d53086d96f63813b Author: Benjamin Herrenschmidt Date: Tue May 30 13:51:37 2006 +1000 [PATCH] powerpc vdso updates This patch cleans up some locking & error handling in the ppc vdso and moves the vdso base pointer from the thread struct to the mm context where it more logically belongs. It brings the powerpc implementation closer to Ingo's new x86 one and also adds an arch_vma_name() function allowing to print [vsdo] in /proc//maps if Ingo's x86 vdso patch is also applied. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras commit 98a90c02792f22afd8161f96fc9b9f0f0eb0880e Author: Renzo Davoli Date: Sun May 21 20:06:58 2006 +0200 [PATCH] powerpc: enable PPC_PTRACE_[GS]ETREGS on ppc32 I have tested PPC_PTRACE_GETREGS and PPC_PTRACE_SETREGS on umview. I do not understand why historically these tags has been defined as PPC_PTRACE_GETREGS and PPC_PTRACE_SETREGS instead of simply PTRACE_[GS]ETREGS. The other "originality" is that the address must be put into the "addr" field instead of the "data" field as stated in the manual. Signed-off-by: renzo davoli Signed-off-by: Paul Mackerras commit b190f1138b0f30fbe837b3f09fb6ffdb2fc4da24 Author: Nathan Scott Date: Fri Jun 9 17:13:15 2006 +1000 [XFS] Fix broken const use inside local suffix_strtoul routine. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26201a Signed-off-by: Nathan Scott commit 477829ef2e9e831c56c98948cfef6dfcec305c3a Author: Mandy Kirkconnell Date: Fri Jun 9 17:13:04 2006 +1000 [XFS] Fix nused counter. It's currently getting set to -1 rather than getting decremented by 1. Since nused never reaches 0, the "if (!free->hdr.nused)" check in xfs_dir2_leafn_remove() fails every time and xfs_dir2_shrink_inode() doesn't get called when it should. This causes extra blocks to be left on an empty directory and the directory in unable to be converted back to inline extent mode. SGI-PV: 951958 SGI-Modid: xfs-linux-melb:xfs-kern:211382a Signed-off-by: Mandy Kirkconnell Signed-off-by: Nathan Scott commit 421ad134583bff86c0ae068e2ddcb17f530957ab Author: Nathan Scott Date: Fri Jun 9 17:12:46 2006 +1000 [XFS] Fix mismerge of the fs_writable cleanup patch causing a freeze/thaw test hang. SGI-PV: 953563 SGI-Modid: xfs-linux-melb:xfs-kern:26182a Signed-off-by: Nathan Scott commit 4d1a2ed3d8d6e306d20f5d99a5ae12ac4c8b787b Author: Nathan Scott Date: Fri Jun 9 17:12:28 2006 +1000 [XFS] Fix up debug code so that bulkstat wont generate thousands of fsstress warnings. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26111a Signed-off-by: Nathan Scott commit a916e2bd15b7572d9e791ae2a9333f74175470cd Author: Nathan Scott Date: Fri Jun 9 17:12:17 2006 +1000 [XFS] Remove unused parameter from di2xflags routine. SGI-PV: 904192 SGI-Modid: xfs-linux-melb:xfs-kern:26110a Signed-off-by: Nathan Scott commit 34327e138481137a81a2e33060b8eb0944013801 Author: Nathan Scott Date: Fri Jun 9 17:11:55 2006 +1000 [XFS] Cleanup a missed porting conversion, and freezing. SGI-PV: 953338 SGI-Modid: xfs-linux-melb:xfs-kern:26109a Signed-off-by: Nathan Scott commit 8285fb58e75bfdb447c7a2c533ec9efdb238f966 Author: Nathan Scott Date: Fri Jun 9 17:07:12 2006 +1000 [XFS] Resolve a namespace collision on remaining vtypes for FreeBSD porters. SGI-PV: 953338 SGI-Modid: xfs-linux-melb:xfs-kern:26108a Signed-off-by: Nathan Scott commit 67fcaa73adafb19139a7cd8ab133592b6a0a0901 Author: Nathan Scott Date: Fri Jun 9 17:00:52 2006 +1000 [XFS] Resolve a namespace collision on vnode/vnodeops for FreeBSD porters. SGI-PV: 953338 SGI-Modid: xfs-linux-melb:xfs-kern:26107a Signed-off-by: Nathan Scott commit b83bd1388133e914c38bd31d69bc90143e6ab10c Author: Nathan Scott Date: Fri Jun 9 16:48:30 2006 +1000 [XFS] Resolve a namespace collision on vfs/vfsops for FreeBSD porters. SGI-PV: 9533338 SGI-Modid: xfs-linux-melb:xfs-kern:26106a Signed-off-by: Nathan Scott commit 7fc925fd6a4c24e1db879d227fc0a0f65a335aa1 Author: Roman Zippel Date: Thu Jun 8 22:12:46 2006 -0700 kconfig: finer customization via popup menus This allows to configure every symbol list and info window separately via a popup menu, these settings are also separately saved and restored. Cleanup the ConfigSettings class a bit to reduce the number of #ifdef. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit 43bf612af2d4f2615dcbf86af8206e2f40231237 Author: Roman Zippel Date: Thu Jun 8 22:12:45 2006 -0700 kconfig: Add search option for xconfig Implement a simple search request for xconfig. Currently the capabilities are rather simple (the same as menuconfig). Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit face4374e288372fba67c865eb0c92337f50d5a4 Author: Roman Zippel Date: Thu Jun 8 22:12:45 2006 -0700 kconfig: add defconfig_list/module option This makes it possible to change two options which were hardcoded sofar. 1. Any symbol can now take the role of CONFIG_MODULES 2. The more useful option is to change the list of default file names, which kconfig uses to load the base configuration if .config isn't available. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit f6a88aa86027bdecfc74ef7c6bf6c68233e86bb3 Author: Roman Zippel Date: Thu Jun 8 22:12:44 2006 -0700 kconfig: add symbol option config syntax This adds the general framework to the parser to define options for config symbols with a syntax like: config FOO option bar[="arg"] Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit f1d28fb043b325dad8944647a52b20287e59d8a1 Author: Roman Zippel Date: Thu Jun 8 22:12:43 2006 -0700 kconfig: move .kernelrelease This moves the .kernelrelease file into include/config directory. Remove its generation from the config step, if the config step doesn't leave a proper .config behind, it triggers a call to silentoldconfig. Instead its generation can be done via proper dependencies. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit 2e3646e51b2d6415549b310655df63e7e0d7a080 Author: Roman Zippel Date: Thu Jun 8 22:12:42 2006 -0700 kconfig: integrate split config into silentoldconfig Now that kconfig can load multiple configurations, it becomes simple to integrate the split config step, by simply comparing the new .config file with the old auto.conf (and then saving the new auto.conf). A nice side effect is that this saves a bit of disk space and cache, as no data needs to be read from or saved into the splitted config files anymore (e.g. include/config is now 648KB instead of 5.2MB). Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit 669bfad906522e74ee8d962801552a8c224c0d63 Author: Roman Zippel Date: Thu Jun 8 22:12:42 2006 -0700 kconfig: allow loading multiple configurations Extend conf_read_simple() so it can load multiple configurations. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit 0c1822e6991a10da6dc391f0a2e2cf5fb2e31238 Author: Roman Zippel Date: Thu Jun 8 22:12:41 2006 -0700 kconfig: allow multiple default values per symbol Extend struct symbol to allow storing multiple default values, which can be used to hold multiple configurations. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit c0e150acde52e4661675539bf5323309270f2e83 Author: Roman Zippel Date: Thu Jun 8 22:12:40 2006 -0700 kconfig: remove SYMBOL_{YES,MOD,NO} The SYMBOL_{YES,MOD,NO} are not really used anymore (they were more used be the cml1 converter), so just remove them. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit c955ccafc38e77312b4c65e5a70960080fb8a3f2 Author: Roman Zippel Date: Thu Jun 8 22:12:39 2006 -0700 kconfig: fix .config dependencies This fixes one of the worst kbuild warts left - the broken dependencies used to check and regenerate the .config file. This was done via an indirect dependency and the .config itself had an empty command, which can cause make not to reread the changed .config file. Instead of this we generate now a new file include/config/auto.conf from .config, which is used for kbuild and has the proper dependencies. It's also the main make target now for all files generated during this step (and thus replaces include/linux/autoconf.h). This also means we can now relax the syntax requirements for the .config file and we don't have to rewrite it all the time, i.e. silentoldconfig only writes .config now when it's necessary to keep it in sync with the Kconfig files and even this can be suppressed by setting the environment variable KCONFIG_NOSILENTUPDATE, so the update can (and must) be done manually. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit ddc97cacb310ad68483952e67764c4153c138ed2 Author: Roman Zippel Date: Thu Jun 8 22:12:38 2006 -0700 kconfig: improve config load/save output During loading special case the first common case (.config), be silent about it and otherwise mark it as a change that requires saving. Instead output that the file has been changed. IOW if conf does nothing (special), it's silent. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg commit 932f2c323196c214e645d5a572a1d7b562c0f93f Author: Nathan Scott Date: Fri Jun 9 15:29:58 2006 +1000 [XFS] statvfs component of directory/project quota support, code originally by Glen. SGI-PV: 932952 SGI-Modid: xfs-linux-melb:xfs-kern:26105a Signed-off-by: Nathan Scott commit b65745205fc00d8c7722ec74e9bd955f3861c7e2 Author: Nathan Scott Date: Fri Jun 9 15:29:40 2006 +1000 [XFS] Portability changes: remove prdev, stick to one diagnostic interface. SGI-PV: 953338 SGI-Modid: xfs-linux-melb:xfs-kern:26103a Signed-off-by: Nathan Scott commit 9c48876a05b6fbe41f1933fae3529c268d78cad0 Author: Nathan Scott Date: Fri Jun 9 15:29:22 2006 +1000 [XFS] Remove dead code from come bulkstat paths. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26102a Signed-off-by: Nathan Scott commit ad723875ac238137207754d2633dd9c261c71558 Author: Nathan Scott Date: Fri Jun 9 15:29:12 2006 +1000 [XFS] Fix a typo in a header file comment. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26101a Signed-off-by: Nathan Scott commit 7d4fb40ad7efe4586d1341d4731377fb4530836f Author: Nathan Scott Date: Fri Jun 9 15:27:16 2006 +1000 [XFS] Start writeout earlier (on last close) in the case where we have a truncate down followed by delayed allocation (buffered writes) - worst case scenario for the notorious NULL files problem. This reduces the window where we are exposed to that problem significantly. SGI-PV: 917976 SGI-Modid: xfs-linux-melb:xfs-kern:26100a Signed-off-by: Nathan Scott commit 59c1b082f5fff8269565039600a2ef18d48649b5 Author: Nathan Scott Date: Fri Jun 9 14:59:13 2006 +1000 [XFS] Make the pflags test/set wrappers more legible for us mere humans. SGI-PV: 953338 SGI-Modid: xfs-linux-melb:xfs-kern:26099a Signed-off-by: Nathan Scott commit e109007461cddfc80a908f0b015f4eeb485e1d85 Author: Nathan Scott Date: Fri Jun 9 14:58:48 2006 +1000 [XFS] Fix a buffer refcount leak in dir2 code on a forced shutdown. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26097a Signed-off-by: Nathan Scott commit 7d04a335b6b2d79e3742ffd28bd651204574e794 Author: Nathan Scott Date: Fri Jun 9 14:58:38 2006 +1000 [XFS] Shutdown the filesystem if all device paths have gone. Made shutdown vop flags consistent with sync vop flags declarations too. SGI-PV: 939911 SGI-Modid: xfs-linux-melb:xfs-kern:26096a Signed-off-by: Nathan Scott commit b76963fac4a17b661bad46e5a57b0f918c6f0cd1 Author: Nathan Scott Date: Fri Jun 9 14:58:20 2006 +1000 [XFS] getattr can return an error code, so propogate any from lower layers. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26095a Signed-off-by: Nathan Scott commit 3d80ede4799889ede2aa785c2511aef3e78d5bb1 Author: Nathan Scott Date: Fri Jun 9 14:57:30 2006 +1000 [XFS] Drop use of m_writeio_blocks when zeroing, its not meaningful anymore here. SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26094a Signed-off-by: Nathan Scott commit 72c93bcc6348a385416603459c2fdb4cf6c43687 Author: Ingo Molnar Date: Fri Jun 9 14:57:01 2006 +1000 [XFS] lock validator: lockdep: small xfs init_rwsem() cleanup init_rwsem() has no return value. This is not a problem if init_rwsem() is a function, but it's a problem if it's a do { ... } while (0) macro. (which lockdep introduces) SGI-PV: 904196 SGI-Modid: xfs-linux-melb:xfs-kern:26082a Signed-off-by: Ingo Molnar Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Nathan Scott commit 87c199c2a79220ac9e216e72d18a15148f84d9e0 Author: Tim Shimmin Date: Fri Jun 9 14:56:16 2006 +1000 [XFS] Over zealous with doing endian conversions. We endian converted the logged version of di_next_unlinked which is actually always stored in the correct ondisk format. This was pointed out to us by Shailendra Tripathi. And is evident in the xfs qa test of 121. SGI-PV: 953263 SGI-Modid: xfs-linux-melb:xfs-kern:26044a Signed-off-by: Tim Shimmin Signed-off-by: Nathan Scott commit 714250879ea61cdb1a39bb96fe9d934ee0c669a2 Author: David Chinner Date: Fri Jun 9 14:55:52 2006 +1000 [XFS] Stop a BUG from occurring in generic_delete_inode by preventing transaction completion from marking the inode dirty while it is being cleaned up on it's way out of the system. SGI-PV: 952967 SGI-Modid: xfs-linux-melb:xfs-kern:26040a Signed-off-by: David Chinner Signed-off-by: Nathan Scott commit 6d192a9b82212abf1e0e89da6e3a952afba7e4d6 Author: Tim Shimmin Date: Fri Jun 9 14:55:38 2006 +1000 [XFS] inode items and EFI/EFDs have different ondisk format for 32bit and 64bit kernels allow recovery to handle both versions and do the necessary decoding SGI-PV: 952214 SGI-Modid: xfs-linux-melb:xfs-kern:26011a Signed-off-by: Tim Shimmin Signed-off-by: Nathan Scott commit d210a28cd851082cec9b282443f8cc0e6fc09830 Author: Yingping Lu Date: Fri Jun 9 14:55:18 2006 +1000 [XFS] In actual allocation of file system blocks and freeing extents, the transaction within each such operation may involve multiple locking of AGF buffer. While the freeing extent function has sorted the extents based on AGF number before entering into transaction, however, when the file system space is very limited, the allocation of space would try every AGF to get space allocated, this could potentially cause out-of-order locking, thus deadlock could happen. This fix mitigates the scarce space for allocation by setting aside a few blocks without reservation, and avoid deadlock by maintaining ascending order of AGF locking. SGI-PV: 947395 SGI-Modid: xfs-linux-melb:xfs-kern:210801a Signed-off-by: Yingping Lu Signed-off-by: Nathan Scott commit d3446eac3f50dade2f09ed212b112609ee78fb33 Author: Barry Naujok Date: Fri Jun 9 14:54:19 2006 +1000 [XFS] Add degframentation exclusion support SGI-PV: 953061 SGI-Modid: xfs-linux-melb:xfs-kern:25986a Signed-off-by: Barry Naujok Signed-off-by: Nathan Scott commit fbc1462bcb421620a04eb390fc79a2615c9d01d0 Author: Nathan Scott Date: Fri Jun 9 14:52:13 2006 +1000 [XFS] Fix a noatime regression related to updating inode atime field on mmap only. SGI-PV: 952736 SGI-Modid: xfs-linux-melb:xfs-kern:25922a Signed-off-by: Nathan Scott commit ba0b92d671c36cbebd66a306790c9b66a3224d83 Author: Nathan Scott Date: Fri Jun 9 14:52:00 2006 +1000 [XFS] Fix a comment typo, originally noticed by Ming Zhang. SGI-PV: 907752 SGI-Modid: xfs-linux-melb:xfs-kern:25921a Signed-off-by: Nathan Scott commit fe6c1e7240e3a7cb600030f9c909273365d52a9d Author: Mandy Kirkconnell Date: Fri Jun 9 14:51:25 2006 +1000 [XFS] Fix size argument in kmem_free(). SGI-PV: 952291 SGI-Modid: xfs-linux-melb:xfs-kern:209807a Signed-off-by: Mandy Kirkconnell Signed-off-by: Nathan Scott commit 3f368a0d58cb8cadab298546286f94ca14220f65 Author: Olaf Weber Date: Fri Jun 9 14:51:11 2006 +1000 [XFS] Originally the ATTR_DMI flag also had the functionality of the ATTR_NOLOCK flag, but this was split off some time ago, as ATTR_DMI needed to be used separately. Two asserts were added to guard correctness of the code during the transition. These are no longer required. SGI-PV: 952145 SGI-Modid: xfs-linux-melb:xfs-kern:209633a Signed-off-by: Olaf Weber Signed-off-by: Nathan Scott commit 1d8daf06f67c8920a640eb61b30c3176ecc52405 Author: Christoph Hellwig Date: Fri Jun 9 14:50:37 2006 +1000 [XFS] endianess annotations for xfs_dir_leaf_entry_t SGI-PV: 943272 SGI-Modid: xfs-linux-melb:xfs-kern:25808a Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Nathan Scott commit 8034fff39bb9430d807375ec7a04097efba42cd2 Author: Christoph Hellwig Date: Fri Jun 9 14:50:24 2006 +1000 [XFS] endianess annotations for xfs_dir_leaf_hdr_t SGI-PV: 943272 SGI-Modid: xfs-linux-melb:xfs-kern:25807a Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Nathan Scott commit ff9901c1e7c7be06a99c59cfc3133d2316cbc957 Author: Christoph Hellwig Date: Fri Jun 9 14:48:37 2006 +1000 [XFS] endianess annotations for xfs_dir2_data_entry_t SGI-PV: 943272 SGI-Modid: xfs-linux-melb:xfs-kern:25806a Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro Signed-off-by: Nathan Scott commit 3e57ecf640428c01ba1ed8c8fc538447ada1715b Author: Olaf Weber Date: Fri Jun 9 14:48:12 2006 +1000 [XFS] Add parameters to xfs_bmapi() and xfs_bunmapi() to have them report the range spanned by modifications to the in-core extent map. Add XFS_BUNMAPI() and XFS_SWAP_EXTENTS() macros that call xfs_bunmapi() and xfs_swap_extents() via the ioops vector. Change all calls that may modify the in-core extent map for the data fork to go through the ioops vector. This allows a cache of extent map data to be kept in sync. SGI-PV: 947615 SGI-Modid: xfs-linux-melb:xfs-kern:209226a Signed-off-by: Olaf Weber Signed-off-by: Nathan Scott commit 81c246691535ee3f865fbe6804b3be1b2c159e95 Author: Andrew Morton Date: Thu Jun 1 20:19:36 2006 -0700 [AGPGART] alpha-agp warning fix drivers/char/agp/alpha-agp.c:138: warning: initialization from incompatible pointer type drivers/char/agp/alpha-agp.c:139: warning: initialization from incompatible pointer type Cc: Ivan Kokshaysky Cc: Richard Henderson Signed-off-by: Andrew Morton Signed-off-by: Dave Jones commit b07cd5181f3c8de8c28fdac7dbeec9e4220b8037 Author: Andrew Morton Date: Thu Jun 1 20:19:35 2006 -0700 [AGPGART] uninorth-agp warning fixes drivers/char/agp/uninorth-agp.c: In function `agp_uninorth_suspend': drivers/char/agp/uninorth-agp.c:332: warning: cast to pointer from integer of different size drivers/char/agp/uninorth-agp.c: In function `agp_uninorth_resume': drivers/char/agp/uninorth-agp.c:354: warning: cast from pointer to integer of different size Signed-off-by: Andrew Morton Signed-off-by: Dave Jones commit 987024ca9e11b5ea348e4014ac0e41fdee4f50f1 Author: Stephen Hemminger Date: Tue Jun 6 10:11:15 2006 -0700 [PATCH] skge: version 1.6 Update version string. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik commit 631ae320a4123898927ab1eb32ad81274a713488 Author: Stephen Hemminger Date: Tue Jun 6 10:11:14 2006 -0700 [PATCH] skge: dont allow bad hardware address from ROM Sometimes boards don't reset properly, and the address read out of the EEPROM is zero. Stop the insanity before the device gets registered. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik commit 7c442fa17eabd34301598acbca8ecb99daad6027 Author: Stephen Hemminger Date: Tue Jun 6 10:11:13 2006 -0700 [PATCH] skge: transmit complete via IRQ not NAPI The transmit side code has a number of ring problems that caused some of the Bugzilla reports. Rather than trying to fix the details, it is safer to rewrite the code that handles transmit completion and freeing. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik commit 9db96479b4e682b1bc3796873589db1f8d38a9d5 Author: Stephen Hemminger Date: Tue Jun 6 10:11:12 2006 -0700 [PATCH] skge: TX low water mark definition Consolidate all usage of ring low water mark to one value. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik commit d85b514fd9aa95d2089fa16dccc25863fb2a766c Author: Stephen Hemminger Date: Tue Jun 6 10:11:11 2006 -0700 [PATCH] skge: use workq for PHY handling Since accessing the PHY can take 100's of usecs, use a work queue to allow spinning in outside of soft/hard irq. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik commit b10c066823c97c0e40989b2048540e85f5190501 Author: Brice Goglin Date: Thu Jun 8 10:25:00 2006 -0400 [PATCH] myri10ge update The following patch updates the myri10ge to 1.0.0, with the following changes: * Switch to dma_alloc_coherent API. * Avoid PCI burst when writing the firmware on chipset with unaligned completions. * Use ethtool_op_set_tx_hw_csum instead of ethtool_op_set_tx_csum. * Include linux/dma-mapping.h to bring DMA_32/64BIT_MASK on all architectures (was missing at least on alpha). * Some typo and warning fixes. Signed-off-by: Brice Goglin Signed-off-by: Andrew J. Gallatin drivers/net/myri10ge/myri10ge.c | 57 +++++++++++++++++++----------- 1 file changed, 37 insertions(+), 20 deletions(-) Signed-off-by: Jeff Garzik commit 909252d279dd5d47e44c125558e87bb44097289f Author: Sam Ravnborg Date: Thu Jun 8 20:37:30 2006 +0200 kbuild: fix false section mismatch with ARCH=um build Ignoring references to .init.text, .exit.text from the .plt section brought the false positives down to two warnings for a defconfig build of ARCH=um on x86_64. Signed-off-by: Sam Ravnborg commit 35899c57516be6eaa42cc27151767c52d75b2979 Author: Randy Dunlap Date: Wed Jun 7 16:23:26 2006 -0700 kbuild: ignore smp_locks section warnings from init/exit code Add ".smp_locks" section to whitelist as being safe from init and exit sections. Signed-off-by: Randy Dunlap Signed-off-by: Sam Ravnborg commit 1a0f3d422bb9ac959383a5ed1a4127f5900f56a8 Author: Mike Wolf Date: Fri Jun 2 09:53:42 2006 -0500 kbuild: fix make rpm for powerpc The default target for most powerpc platforms is zImage. The zImage however is in arch/powerpc/boot and the mkspec script was set up to get the kernel from the top level of the kernel tree. This patch copies vmlinux to arch/powerpc/boot and then copies the kernel to the tmp directory so the rpm can be made. Signed-off-by: Mike Wolf Signed-off-by: Sam Ravnborg commit 9870a93d3118239fd7732a0f908e05f67b39a294 Author: Pavel Roskin Date: Thu Jun 1 21:28:50 2006 -0400 kbuild: obj-dirs is calculated incorrectly if hostprogs-y is defined When Makefile.host is included, $(obj-dirs) is subjected to the addprefix operation for the second time. Prefix only needs to be added to the newly added directories, but not to those that came from Makefile.lib. This causes the build system to create unneeded empty directories in the build tree when building in a separate directory. For instance, lib/lib/zlib_inflate is created in the build tree. Signed-off-by: Pavel Roskin Signed-off-by: Sam Ravnborg commit 6224e01dccf2543a8f8b4d825baf1510c79c2878 Author: Auke Kok Date: Thu Jun 8 11:15:35 2006 -0700 [DOC] Update bonding documentation with sysfs info Bonding documentation needed an update to include sysfs specific information. This patch adds information on how to change bonding parameters at runtime using the sysfs interface. Signed-off-by: Mitch Williams Signed-off-by: Auke Kok commit 9026729bfeb4329a4edc01f427f01af7ee0a5273 Author: Auke Kok Date: Thu Jun 8 09:30:24 2006 -0700 e1000: add PCI Error Recovery Various PCI bus errors can be signaled by newer PCI controllers. This patch adds the PCI error recovery callbacks to the intel gigabit ethernet e1000 device driver. The patch has been tested, and appears to work well. Signed-off-by: Linas Vepstas Acked-by: Jesse Brandeburg Signed-off-by: Auke Kok commit 2cc304923d87403abc103a741382b9af08b6decc Author: Auke Kok Date: Thu Jun 8 09:30:18 2006 -0700 e100: add PCI Error Recovery Various PCI bus errors can be signaled by newer PCI controllers. This patch adds the PCI error recovery callbacks to the intel ethernet e100 device driver. The patch has been tested, and appears to work well. Signed-off-by: Linas Vepstas Acked-by: Jesse Brandeburg Signed-off-by: Auke Kok commit 72109368de7aaa5d489d9ca4641f4a11a6fc7653 Author: Dennis Munsie Date: Wed Jun 7 18:53:38 2006 +1000 Removed hard coded EDID buffer size. Signed-off-by: Dennis Munsie Acked-by: Antonino Daplas Signed-off-by: Dave Airlie commit 5d5ff44fe6775ccb922fd1f7d478b2ba9ca95068 Author: Christoph Hellwig Date: Sat Jun 3 13:21:13 2006 +0200 [SCSI] fix up request buffer reference in various scsi drivers Various scsi drivers use scsi_cmnd.buffer and scsi_cmnd.bufflen in their queuecommand functions. Those fields are internal storage for the midlayer only and are used to restore the original payload after request_buffer and request_bufflen have been overwritten for EH. Using the buffer and bufflen fields means they do very broken things in error handling. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley commit e4a082c7c1f9a7b11fece6918e7ee5519b39ac46 Author: Sumant Patro Date: Tue May 30 12:03:37 2006 -0700 [SCSI] megaraid_sas: switch fw_outstanding to an atomic_t This patch( originally submitted by Christoph Hellwig) removes instance_lock and changes fw_outstanding variable data type to atomic_t. Signed-off-by: Sumant Patro Signed-off-by: James Bottomley commit f70e9c5f91f1d2d9ce79dc45221540e25b4e4ac0 Author: Mike Christie Date: Tue May 30 01:04:51 2006 -0500 [SCSI] iscsi: update version to 1.0-595 Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 3219e5294150aee7d389e19029f49b44fb6b5c9f Author: Mike Christie Date: Tue May 30 00:37:28 2006 -0500 [SCSI] iscsi: fix writepsace race We can race and misset the suspend bit if iscsi_write_space is called then iscsi_send returns with a failure indicating there is no space. To handle this this patch returns a error upwards allowing xmitworker to decide if we need to try and transmit again. For the no write space case xmitworker will not retry, and instead let iscsi_write_space queue it back up if needed (this relies on the work queue code to properly requeue us if needed). Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 040515f53c09047c76ad074dc6a280984dc84b04 Author: Mike Christie Date: Tue May 30 00:37:25 2006 -0500 [SCSI] iscsi: return task found during search from davidw@netapp.com: remove task type should return a task on success. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 994442e807782d68bb1d3ae34044f95990411a22 Author: Mike Christie Date: Tue May 30 00:37:22 2006 -0500 [SCSI] iscsi: fix run list corruption from davidw@netapp.com: We must grab the session lock when modifying the running lists. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 67a611149b2ac5f4af1e36bfffbfe3198cd3712c Author: Mike Christie Date: Tue May 30 00:37:20 2006 -0500 [SCSI] iscsi: don't switch states when just cleaning up If recovery failed or we are in recovery only overwrite the state if we are going to terminate the session or if we logged back in. STOP_CONN_SUSPEND and conn_cnt are not used. We only support a single connection session ATM, so cleanup that code while we are working around it. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 5c601d0c942f5aaf7f3cff7e08f61047d70a964e Author: Pavel Machek Date: Mon Jun 5 16:13:30 2006 -0400 [PATCH] wireless: move zd1201 where it belongs zd1201 is wifi adapter, yet it is hiding in drivers/usb/net where noone can find it. This moves Kconfig/Makefile zd1201 to the right place. Signed-off-by: Pavel Machek Signed-off-by: John W. Linville commit ff7562aaec1e68448888572033f072fc21ef2ac8 Author: Jason Lunz Date: Sun Jun 4 23:05:49 2006 +0200 [PATCH] bcm43xx: quiet down log spam from set_security The debug logging in bcm43xx_ieee80211_set_security() is pretty noisy. Make it more silent. Signed-off-by: Jason Lunz Signed-off-by: Michael Buesch Signed-off-by: John W. Linville commit c4b3d1bb3206513d7f10cd60bbac97c82624c2d3 Author: Joseph Jezak Date: Thu Jun 1 17:12:49 2006 +0100 [PATCH] softmac: unified capabilities computation This patch moves the capabilities field computation to a function for clarity and adds some previously unimplemented bits. Signed off by Joseph Jezak Signed-off-by: Daniel Drake Acked-By: Johannes Berg Signed-off-by: John W. Linville commit 6ae15df16ef3dc3f5f043e94bb2cd4aa6c7f2aa8 Author: Daniel Drake Date: Thu Jun 1 15:37:22 2006 +0100 [PATCH] softmac: Fix handling of authentication failure My router blew up earlier, but exhibited some interesting behaviour during its dying moments. It was broadcasting beacons but wouldn't respond to any authentication requests. I noticed that softmac wasn't playing nice with this, as I couldn't make it try to connect to other networks after it had timed out authenticating to my ill router. To resolve this, I modified the softmac event/notify API to pass the event code to the callback, so that callbacks being notified from IEEE80211SOFTMAC_EVENT_ANY masks can make some judgement. In this case, the ieee80211softmac_assoc callback needs to make a decision based upon whether the association passed or failed. Signed-off-by: Daniel Drake Acked-by: Johannes Berg Signed-off-by: John W. Linville commit 76ea4c7f4cd319dee35934ecab57745feae58fa5 Author: Daniel Drake Date: Thu Jun 1 15:34:26 2006 +0100 [PATCH] softmac: complete shared key authentication This patch finishes of the partially-complete shared key authentication implementation in softmac. The complication here is that we need to encrypt a management frame during the authentication process. I don't think there are any other scenarios where this would have to happen. To get around this without causing too many headaches, we decided to just use software encryption for this frame. The softmac config option now selects IEEE80211_CRYPT_WEP so that we can ensure this available. This also involved a modification to some otherwise unused ieee80211 API. Signed-off-by: Daniel Drake Acked-by: Johannes Berg Signed-off-by: John W. Linville commit 47fbe1bf3980b41d2e18e3774e8e1094f716d2d1 Author: Toralf Förster Date: Mon Jun 5 15:48:31 2006 -0400 [PATCH] ieee80211softmac_io.c: fix warning "defined but not used" Got this compiler warning and Johannes Berg wrote: Yeah, known 'bug', we have that code there but never use it. Feel free to submit a patch (to John Linville, CC netdev and softmac-dev) to remove it. Signed-off-by: Toralf Foerster Signed-off-by: John W. Linville commit 2a8063403112030f1748e207d97d4f8654754dff Author: Pavel Machek Date: Fri May 26 22:07:48 2006 +0200 [PATCH] usb wifi: zd1201 cleanups Cleanup coding style and other small stuff in zd1201. No real code changes. Signed-off-by: Pavel Machek Signed-off-by: John W. Linville commit 6ccf58ab22499139bacc683493c9fd70af55adbb Author: Dave Jones Date: Mon Jun 5 15:25:20 2006 -0400 [CPUFREQ] sets nforce2 minimum PLL divider to 2. Sets minimum PLL divider to 2. No negative impact when tested with two nForce2 based boards. Alexander Choporov reported (06/01/06) that xdiv = 1 does not work on his Abit NF7S2. Although there shouldn't be much cases that lead to xdiv = 1. (Updates also the (C) year) Signed-off-by: Sebastian Witt Signed-off-by: Dave Jones commit 2f3243aebd8df4d9eecaeca04bbff6c7dbfb2142 Author: David Woodhouse Date: Mon Jun 5 20:19:05 2006 +0100 [RBTREE] Switch rb_colour() et al to en_US spelling of 'color' for consistency Since rb_insert_color() is part of the _public_ API, while the others are purely internal, switch to be consistent with that. Signed-off-by: David Woodhouse commit 436fe7b8b4a5016ef1fcb32bff77bde84003e15d Author: Dave Jones Date: Mon Jun 5 14:03:50 2006 -0400 [CPUFREQ] Make powernow-k7 work on SMP kernels. Even though powernow-k7 doesn't work in SMP environments, it can work on an SMP configured kernel if there's only one CPU present, however recalibrate_cpu_khz was returning -EINVAL on such kernels, so we failed to init the cpufreq driver. Signed-off-by: Dave Jones commit 3cbd5b32cb625f5c0f1b1476d154fac873dd49ce Author: Anssi Hannula Date: Mon Jun 5 00:18:43 2006 -0400 Input: fix accuracy of fixp-arith.h Add the value of cos(90) = 0 to the table. This also moves the results so that sin(x) == sin(180-x) is true as expected. Signed-off-by: Anssi Hannula Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov commit fe65b97a5885a84baa103d7213754ff29e8f872f Author: Anssi Hannula Date: Mon Jun 5 00:18:21 2006 -0400 Input: iforce - use ENOSPC instead of ENOMEM Use -ENOSPC instead of -ENOMEM when the iforce device doesn't have enough free memory for the new effect. All other drivers are using -ENOSPC, so this makes the behaviour coherent. Signed-off-by: Anssi Hannula Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov commit 0f5e560e4523e15f33922de5becd024ccaaff76c Author: Andreas Mohr Date: Mon Jun 5 00:18:00 2006 -0400 Input: constify drivers/char/keyboard.c Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov commit b10eec2246690f069febd3aa9578decd5ffb3f5b Author: Jan Beulich Date: Fri Apr 28 13:47:13 2006 +0200 [CPUFREQ] cpufreq core {d,}printk adjustments Remove KERN_* suffixes from some cpufreq driver's dprintk-s. Signed-off-by: Jan Beulich Signed-off-by: Dave Jones commit 8c362a5d62c98ee117b229c3555f402e72f5c21e Author: Jan Beulich Date: Wed Apr 26 15:41:22 2006 +0200 [CPUFREQ] dprintk adjustments to cpufreq-speedstep-centrino Remove KERN_* suffixes from some Centrino cpufreq driver's dprintk-s. Signed-off-by: Jan Beulich Signed-off-by: Dave Jones commit 0fc25dd17eaea64b21612f8e2816a4695b418100 Author: Jan Beulich Date: Wed Apr 26 15:40:02 2006 +0200 [CPUFREQ] dprintk adjustments to cpufreq-nforce2 Remove KERN_* suffixes from some NForce2 cpufreq driver's dprintk-s. Signed-off-by: Jan Beulich Signed-off-by: Dave Jones commit 1f729e0660f974cec1f0f7f4fba03ea4c2c4b9a9 Author: Dave Jones Date: Sun Jun 4 19:37:58 2006 -0400 [CPUFREQ] Prepare powernow-k8 for future CPUs. Forthcoming AMD products will use a different algorithm for transitioning pstates than the current generation Opteron products do. The attached patch allows the powernow-k8 driver to work with those products. Signed-off-by: Mark Langsdorf Signed-off-by: Dave Jones commit d27317657ae18cfbc45def8f566e4c3ed1f51d74 Author: David Woodhouse Date: Sat Jun 3 00:27:53 2006 +0100 Switch to __s32 types in joystick.h instead of C99 types for consistency. The rest of the file uses these types instead of C99 types. Acked-by: Dmitry Torokhov Signed-off-by: David Woodhouse commit 3bcc86f507f5a0b6f5bfa312f37ec33711558acb Author: David Woodhouse Date: Sat Jun 3 00:25:50 2006 +0100 [JFFS2] Remove stray __exit from jffs2_compressors_exit() It's used from the initfunc in case of failure too. We could actually do with an '__initexit' for this kind of thing -- when built in to the kernel, it could do with being dropped with the init text. We _could_ actually just use __init for it, but that would break if/when we start dropping init text from modules. So let's just leave it as it was for now, and mutter a little more about random 'janitorial' fixes from people who aren't paying attention to what they're doing. Signed-off-by: David Woodhouse commit 42adb53cb36d19862a02d3087e2e3d9dab39e5fa Author: Jeremy Fitzhardinge Date: Thu Jun 1 17:41:00 2006 -0400 ACPI: Allow a WAN module enable/disable on a Thinkpad X60. The WAN (Sierra Wireless EV-DO) module is very similar to the Bluetooth module. It appears on the USB bus when enabled. It can be controlled via hot key, or directly via ACPI. This change enables direct control via ACPI. I have tested it on my Lenovo Thinkpad X60; I guess it will probably work on other Thinkpad models which come with this module installed. Signed-off-by: Jeremy Fitzhardinge Ack'd by: Borislav Deianov Signed-off-by: Len Brown commit 911cb74bb9e77e40749abc2fca6fe74d87d940f3 Author: Dave Jones Date: Thu Jun 1 11:38:28 2006 -0400 [CPUFREQ] Make acpi-cpufreq 'sticky'. This prevents annoying messages being printed when it gets loaded on a machine that doesn't have support scaling via ACPI. Signed-off-by: Dave Jones commit 7b1c6ca73aa102e9dde5098f58c523bca0f8e2c3 Author: David Woodhouse Date: Thu Jun 1 12:49:30 2006 +0100 Add to headers included for userspace in Signed-off-by: David Woodhouse Signed-off-by: Vojtech Pavlik commit 75de7d55f8e148848cadefc92140d8f083d13924 Author: Dave Jones Date: Wed May 31 16:13:14 2006 -0400 [CPUFREQ] Remove strange No-op from longrun.c ORing something with zero is meaningless. ACKed-by: Dominik Brodowski Signed-off-by: Dave Jones commit 9bf0a28c9a24e2cee5deecf89d118254374c75ba Author: Vivek Goyal Date: Thu Apr 27 02:33:13 2006 -0700 [SCSI] kdump: mpt fusion driver initialization failure fix MPT fusion driver initialization fails while second kernel is booting, after a system crash (if kdump kernel is configured). Oops message is pasted below. ***************************************************************************** Fusion MPT base driver 3.03.08 Copyright (c) 1999-2005 LSI Logic Corporation Fusion MPT SAS Host driver 3.03.08 ACPI: PCI Interrupt 0000:01:00.0[A] -> Link [LNKA] -> GSI 5 (level, low) -> IRQ 5 mptbase: Initiating ioc0 bringup BUG: unable to handle kernel paging request at virtual address 00002608 printing eip: c11782fd *pde = 00000000 Oops: 0000 [#1] Modules linked in: CPU: 0 EIP: 0060:[] Not tainted VLI EFLAGS: 00010046 (2.6.17-rc1-16M #2) EIP is at mptscsih_io_done+0x27/0x3a3 eax: c4fed000 ebx: c4fed000 ecx: 00002600 edx: 00000298 esi: c11782d6 edi: 00002600 ebp: 00000000 esp: c1332f74 ds: 007b es: 007b ss: 0068 Process swapper (pid: 0, threadinfo=c1332000 task=c128f9c0) Stack: <0>0000006c 00000020 00000298 00002600 c4fed000 c4fed000 c11782d6 0000260 0 00000000 c1172c49 c4fed000 c1305b40 00000005 00000000 c1172d75 c48877e0 c1029687 00000000 c1307fb8 00000000 c1305a00 00000001 00000000 c1307fb8 Call Trace: mptscsih_io_done+0x0/0x3a3 mpt_turbo_reply+0xbb/0xd3 mpt_interrupt+0x22/0x2b misrouted_irq+0x63/0xcb note_interrupt+0x43/0x98 __do_IRQ+0x68/0x8f do_IRQ+0x36/0x4e ======================= common_interrupt+0x1a/0x20 mwait_idle+0x1a/0x2a cpu_idle+0x40/0x5c start_kernel+0x17a/0x17c Code: 5e 5f 5d c3 55 89 cd 57 56 53 83 ec 14 89 54 24 0c 89 44 24 10 8b 90 cc 00 00 00 8b 4c 24 0c 81 c2 98 02 00 00 85 ed 89 54 24 08 <0f> b7 79 08 89 fe 74 04 0f b7 75 08 66 39 f7 75 0d 8b 44 24 0c ******************************************************************************* o Kdump capture kernel boot fails during initialization of MPT fusion driver. (LSI Logic / Symbios Logic SAS1064E PCI-Express Fusion-MPT SAS (rev 01)) o Problem is easily reproducible, if system crashed while some disk activity like cp operation was going on. o After a system crash, devices are not shutdown and capture kernel starts booting while skipping BIOS. Hence underlying device is left in operational state. In this case scsi contoller was left with interrupt line asserted reply FIFO was not empty. When driver starts initializing in the second kernel, it receives the interrupt the moment request_irq() is called. Interrupt handler, reads the message from reply FIFO and tries to access the associated message frame and panics, as in the new kernel's context that message frame is not valid at all. o In this scenario, probably we should delay the request_irq() call. First bring up the IOC, reset it if needed and then should register for irq. o I have tested the patch with SAS1064E and 53c1030 controllers. Signed-off-by: Vivek Goyal Signed-off-by: Andrew Morton Acked-by: "Moore, Eric Dean" Signed-off-by: James Bottomley commit d87fa38e70853a9607dc34a02d15cf5f149f49f2 Author: Tejun Heo Date: Wed May 31 18:28:24 2006 +0900 [PATCH] libata-hp: move ata_do_reset() to libata-eh.c With ops->probe_init() gone, no user is left in libata-core.c. Move ata_do_reset() to libata-eh.c and make it static. Signed-off-by: Tejun Heo commit 52783c5dcc8d317bc8c3e2692d366e8a305abada Author: Tejun Heo Date: Wed May 31 18:28:22 2006 +0900 [PATCH] libata-hp: killl ops->probe_reset Now that all drivers implementing new EH are converted to new probing mechanism, ops->probe_reset doesn't have any user. Kill it. Signed-off-by: Tejun Heo commit 0542925b25676543e8384edf454668f89227e905 Author: Tejun Heo Date: Wed May 31 18:28:20 2006 +0900 [PATCH] sata_sil24: convert to new probing mechanism and add hotplug support Convert to new probing mechanism and add hotplug support by enabling PORT_IRQ_PHYRDY_CHG, marking ehi for hotplug and scheduling EH on PORT_IRQ_PHYRDY_CHG or PORT_IRQ_DEV_XCHG. Sil3124/32 family of controllers don't have any mechanism to wait for the first D2H FIS after hotplug, so ATA_FLAG_SKIP_D2H_BSY is used. Signed-off-by: Tejun Heo commit 4296971dd36e2c2deae0826305f591480223af88 Author: Tejun Heo Date: Wed May 31 18:28:18 2006 +0900 [PATCH] ahci: convert to new probing mechanism and add hotplug support Convert to new probing mechanism and add hotplug support by enabling PORT_IRQ_PHYRDY, marking ehi for hotplug and scheduling EH on CONNECT/PHYRDY interrupts. Unfortunately, ahci cannot reliably wait for the first D2H FIS after hotplug. It sometimes succeeds but times out more often than not, so ATA_FLAG_SKIP_D2H_BSY is used. This patch also fixes ahci_hardreset() such that D2H Register FIS RX area is cleared before issuing COMRESET. Without this, ata_busy_sleep() after COMRESET might prematually finish if the previous TF contains DRDY && !BSY. Signed-off-by: Tejun Heo commit e573890b00426189e1e223967a2c46fb758bf06e Author: Tejun Heo Date: Wed May 31 18:28:16 2006 +0900 [PATCH] sata_sil: convert to new probing mechanism and add hotplug support Convert to new probing mechanism and add hotplug support by enabling SATA IRQ for SError.N, marking ehi for hotplug and scheduling EH on SATA IRQs. Sil3112/3512/3114 family of controllers use COMRESET as TF clearing point and can reliably wait for D2H FIS after COMRESET whether the FIS is the first D2H FIS after POR or in response to the COMRESET. Thus, setting ATA_FLAG_HRST_TO_RESUME is enough for device detection after hotplug. Signed-off-by: Tejun Heo commit ccc4672aff1861a9c80ed9e8ec11dc304b31d307 Author: Tejun Heo Date: Wed May 31 18:28:14 2006 +0900 [PATCH] ata_piix: convert ata_piix to new probing mechanism Convert ata_piix to new probing mechanism. Automatic hotplug is not supported due to hardware limitation (no PHY event interrupt), but warm plugging works. Signed-off-by: Tejun Heo commit 720ba12620ee09dce269adf4ad50958adac7bb54 Author: Tejun Heo Date: Wed May 31 18:28:13 2006 +0900 [PATCH] libata-hp: update unload-unplug Update unload unplug - driver unloading / PCI removal. This is done by ata_port_detach() which short-circuits EH, disables all devices and freezes the port. With this patch, EH and unloading/unplugging are properly synchronized. Signed-off-by: Tejun Heo commit 3e706399b03bd237d087d731d4b1b029e546b33d Author: Tejun Heo Date: Wed May 31 18:28:11 2006 +0900 [PATCH] libata-hp: implement bootplug Implement bootplug - boot probing via hotplug path. While loading, ata_host_add() simply schedules probing and invokes EH. After EH completes, ata_host_add() scans and assicates them with SCSI devices. EH path is slightly modified to handle this (e.g. no autopsy during bootplug). The SCSI part is left in ata_host_add() because it's shared with legacy path and to keep probing order as before (ATA scan all ports in host_set then attach all). Signed-off-by: Tejun Heo commit ccf68c3405fca11386004674377d951b9b18e756 Author: Tejun Heo Date: Wed May 31 18:28:09 2006 +0900 [PATCH] libata-hp: hook warmplug Hook transportt->user_scan() and hostt->slave_destroy(). Signed-off-by: Tejun Heo commit 83c47bcb3c533180a6dda78152334de50065358a Author: Tejun Heo Date: Wed May 31 18:28:07 2006 +0900 [PATCH] libata-hp: implement warmplug Implement warmplug. User-initiated unplug can be detected by hostt->slave_destroy() and plug by transportt->user_scan(). This patch only implements the two callbacks. The next function will hook them. Signed-off-by: Tejun Heo commit 580b2102327ab8444af5bde4e70b50d268a1d558 Author: Tejun Heo Date: Wed May 31 18:28:05 2006 +0900 [PATCH] libata-hp: implement SCSI part of hotplug Implement SCSI part of hotplug. This must be done in a separate context as SCSI makes use of EH during probing. SCSI scan fails silently if EH is in progress. In such cases, libata pauses briefly and retries until every device is attached. Signed-off-by: Tejun Heo commit 084fe639b81c4d418a2cf714acb0475e3713cb73 Author: Tejun Heo Date: Wed May 31 18:28:03 2006 +0900 [PATCH] libata-hp: implement hotplug Implement ATA part of hotplug. To avoid probing broken devices over and over again, disabled devices are not automatically detached. They are detached only if probing is requested for the device or the associated port is offline. Also, to avoid infinite probing loop, Each device is probed only once per EH run. As SATA PHY status is fragile, devices are detached only after it has used up its recovery chances unless explicitly requested by LLDD or user (LLDD may request direct detach if, for example, it supports cold presence detection). Signed-off-by: Tejun Heo commit 0ea035a3d1ad948096e205f08f350c03d5cea453 Author: Tejun Heo Date: Wed May 31 18:28:01 2006 +0900 [PATCH] libata-hp: implement ata_eh_detach_dev() Implement ata_eh_detach_dev(). This function is responsible for detaching an ATA device and offlining the associated SCSI device atomically so that the detached device is not accessed after ATA detach is complete. Signed-off-by: Tejun Heo commit e8e008e7b5ed8c65675cc9b3e778b8bb909f65ab Author: Tejun Heo Date: Wed May 31 18:27:59 2006 +0900 [PATCH] sata_sil24: update sil24_hardreset() Use phy debouncing instead of unconditional wait after DEV_RST and make sil24_hardreset() to request followup SRST as that's the only way to wait for !BSY. Note that the original implementation never worked - if the cached status was !BSY, ata_busy_sleep() finished immediately; otherwise, it timed out regardless of the actual device status. Signed-off-by: Tejun Heo commit 135da34573f6d3bab2976a75063f7232a4311a74 Author: Tejun Heo Date: Wed May 31 18:27:57 2006 +0900 [PATCH] sata_sil24: rename PORT_PRB to PORT_LRAM and add PORT_LRAM_SLOT_SZ PORT_PRB is a misnomer as the area also contains other stuff. Rename it to PORT_LRAM and add PORT_LRAM_SLOT_SZ. Signed-off-by: Tejun Heo commit cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0ba Author: Tejun Heo Date: Wed May 31 18:27:55 2006 +0900 [PATCH] sata_sil: new interrupt handler The DMA complete bit of these controllers reflects ATA IRQ status while no DMA command is in progress. So, we can tell whether the controller is raising an interrupt or not in deterministic manner. This patch gives sata_sil its own interrupt handler which behaves much better than the original one in terms of error detection and handling. This change is also necessary for later hotplug support. Further improvements are possible, in both 2 and 4 ports versions, we can get all status with only one readl and using custom bmdma operations can further cut down register accesses. Signed-off-by: Tejun Heo commit 20888d83687d5cb374cdb5b0afa746ab79666f4e Author: Tejun Heo Date: Wed May 31 18:27:53 2006 +0900 [PATCH] sata_sil: add new constants in preparation for new interrupt handler sata_sil is about to get a brand new interrupt handler. Add relevant constants. Signed-off-by: Tejun Heo commit 9a1004d0c11be41c83d06a67dfe74567a41ae582 Author: Tejun Heo Date: Wed May 31 18:27:52 2006 +0900 [PATCH] libata: export ata_hsm_move() ata_hsm_move() will be used by LLDDs which depend on standard PIO HSM but implement their own interrupt handlers. Signed-off-by: Tejun Heo commit 664faf09a05d74085c0b31e2c621d7647322325b Author: Tejun Heo Date: Wed May 31 18:27:50 2006 +0900 [PATCH] libata-hp-prep: implement followup softreset handling In some cases, hardreset must be followed by SRST. * some controllers can't classify with hardreset * some controllers can't wait for !BSY after hardreset (LLDD should explicitly request followup softreset by returning -EAGAIN) * (later) PM needs SRST w/ PMP==15 to operate after hardreset To handle above cases, this patch implements follow-up softreset. After a hardreset, ata_eh_reset() checks whether any of above conditions are met and do a follow-up softreset if necessary. Signed-off-by: Tejun Heo commit f5914a461eb9703773226a0813f6ffcae10c0861 Author: Tejun Heo Date: Wed May 31 18:27:48 2006 +0900 [PATCH] libata-hp-prep: add prereset() method and implement ata_std_prereset() With hotplug, every reset might be a probing reset and thus something similar to probe_init() is needed. prereset() method is called before a series of resets to a port and is the counterpart of postreset(). prereset() can tell EH to use different type of reset or skip reset by modifying ehc->i.action. This patch also implements ata_std_prereset(). Most controllers should be able to use this function directly or with some wrapping. After hotplug, different controllers need different actions to resume the PHY and detect the newly attached device. Controllers can be categorized as follows. * Controllers which can wait for the first D2H FIS after hotplug. Note that if the waiting is implemented by polling TF status, there needs to be a way to set BSY on PHY status change. It can be implemented by hardware or with the help of the driver. * Controllers which can wait for the first D2H FIS after sending COMRESET. These controllers need to issue COMRESET to wait for the first FIS. Note that the received D2H FIS could be the first D2H FIS after POR (power-on-reset) or D2H FIS in response to the COMRESET. Some controllers use COMRESET as TF status synchronization point and clear TF automatically (sata_sil). * Controllers which cannot wait for the first D2H FIS reliably. Blindly issuing SRST to spinning-up device often results in command issue failure or timeout, causing extended delay. For these controllers, ata_std_prereset() explicitly waits ATA_SPINUP_WAIT (currently 8s) to give newly attached device time to spin up, then issues reset. Note that failing to getting ready in ATA_SPINUP_WAIT is not critical. libata will retry. So, the timeout needs to be long enough to spin up most devices. LLDDs can tell ata_std_prereset() which of above action is needed with ATA_FLAG_HRST_TO_RESUME and ATA_FLAG_SKIP_D2H_BSY flags. These flags are PHY-specific property and will be moved to ata_link later. While at it, this patch unifies function typedef's such that they all have named arguments. Signed-off-by: Tejun Heo commit d7bb4cc7575929a60b0a718daa1bce87bea9a9cc Author: Tejun Heo Date: Wed May 31 18:27:46 2006 +0900 [PATCH] libata-hp-prep: implement sata_phy_debounce() With hotplug, PHY always needs to be debounced before a reset as any reset might find new devices. Extract PHY waiting code from sata_phy_resume() and extend it to include SStatus debouncing. Note that sata_phy_debounce() is superset of what used to be done inside sata_phy_resume(). Three default debounce timing parameters are defined to be used by hot/boot plug. As resume failure during probing will be properly handled as errors, timeout doesn't have to be long as before. probeinit() uses the same timeout to retain the original behavior. Signed-off-by: Tejun Heo commit a9beec95352ff675f27d74c3cb97dc258d022497 Author: Tejun Heo Date: Wed May 31 18:27:44 2006 +0900 [PATCH] libata-hp-prep: make probing related functions global Hotplug will be implemented in libata-eh.c. Make ata_dev_read_id() and ata_dev_configure() global. Signed-off-by: Tejun Heo commit 453b07accb47c5b54aa2f156ebffac63c543027b Author: Tejun Heo Date: Wed May 31 18:27:42 2006 +0900 [PATCH] libata-hp-prep: add ata_aux_wq It's best to run ATA hotplug from EH but attaching SCSI devices needs working EH. ata_aux_wq is used to give SCSI hotplug operations a separate context. Signed-off-by: Tejun Heo commit 3edebac41bab7e146578ad9e723ee7fff71c99c0 Author: Tejun Heo Date: Wed May 31 18:27:40 2006 +0900 [PATCH] libata-hp-prep: store attached SCSI device Add device persistent field dev->sdev and store the attached SCSI device. With hotplug, libata needs to know the attached SCSI device to offline and detach it, but scsi_device_lookup() cannot be used because libata will reuse SCSI ID numbers - dead but not gone devices (due to zombie opens, etc...) interfere with the lookup. dev->sdev doesn't hold reference to the SCSI device. It's cleared when the SCSI device goes away. Signed-off-by: Tejun Heo commit 5a04bf4befa8bffa012eedc3a0903c158b9131a9 Author: Tejun Heo Date: Wed May 31 18:27:38 2006 +0900 [PATCH] libata-hp-prep: implement ap->hw_sata_spd_limit Add ap->hw_sata_spd_limit and initialize it once during the boot initialization (or driver load initialization). ap->sata_spd_limit is reset to ap->hw_sata_spd_limit on hotplug. This prevents spd limits introduced by earlier devices from affecting new devices. Signed-off-by: Tejun Heo commit 315343637b988ac32d730a6a9f7bf5866838bcb0 Author: Tejun Heo Date: Wed May 31 18:27:36 2006 +0900 [PATCH] libata-hp-prep: use __ata_scsi_find_dev() Convert direct sdev -> dev lookup to __ata_scsi_find_dev(). Signed-off-by: Tejun Heo commit ab5b3a5b2d887ce63f8c6a7fcb9f5c07ca4b4d43 Author: Tejun Heo Date: Wed May 31 18:27:34 2006 +0900 [PATCH] libata-hp-prep: update ata_scsi_find_dev() and friends Separate out ata_find_dev() and __ata_scsi_find_dev() from ata_scsi_find_dev(). These will be used by later hotplug implementation. Signed-off-by: Tejun Heo commit 72fa4b742b327bd1b07985d79a61c61dbd9fd4e6 Author: Tejun Heo Date: Wed May 31 18:27:32 2006 +0900 [PATCH] libata-hp-prep: make some ata_device fields persistent Lifetimes of some fields span over device plugging/unplugging. This patch moves such persistent fields to the top of ata_device and separate them with ATA_DEVICE_CLEAR_OFFSET. Fields above the offset are initialized once during host initializatino while all other fields are cleared before hotplugging. Currently ->ap, devno and part of flags are persistent. Note that flags is partially cleared while holding host_set lock. This is to synchronize with later warm plug implementation which will record hotplug request in dev->flags. Signed-off-by: Tejun Heo commit 3ef3b43d5633d30fa3f033f62094ec2e9c5b8376 Author: Tejun Heo Date: Wed May 31 18:27:30 2006 +0900 [PATCH] libata-hp-prep: implement ata_dev_init() Move initialization of struct ata_device into ata_dev_init() in preparation for hotplug. This patch calls ata_dev_init() from ata_host_init() and thus makes no functional difference. Signed-off-by: Tejun Heo commit abdda7331d469fa965167365f011d05e226008fb Author: Tejun Heo Date: Wed May 31 18:27:29 2006 +0900 [PATCH] libata-hp-prep: add flags and eh_info/context fields for hotplug Add hotplug related flags and eh_info/context fields. Signed-off-by: Tejun Heo commit c6cf9e99d1de5ca6a08fb639bb73031ffe50d802 Author: Tejun Heo Date: Wed May 31 18:27:27 2006 +0900 [PATCH] libata: implement ata_eh_wait() Implement ata_eh_wait(). On return from this function, it's guaranteed that the EH which was pending or in progress when the function was called is complete - including the tailing part of SCSI EH. This will be used by hotplug and others to synchronize with EH. Signed-off-by: Tejun Heo commit 7395acb2c840fd4d0cacc91d6fb71440057141ab Author: Tejun Heo Date: Wed May 31 18:27:25 2006 +0900 [PATCH] libata: shift host flag constants Nudge host flag constants to make a room after ATA_FLAG_EH_PENDING. New EH flag will be added. Signed-off-by: Tejun Heo commit 20952b699035448d2277c64efc5910a31be66ed1 Author: Tejun Heo Date: Wed May 31 18:27:23 2006 +0900 [PATCH] libata: set PIO-0 after successful EH reset Set ata_device->pio_mode to XFER_PIO_0 after a successful reset. This is to keep EH resets consistent with probe resets as updated by the commit b6079ca409bf88c248992e96510dd6f610f7ed89. Note that, with soon-to-follow hotplug update, EH resets will include probe resets. Signed-off-by: Tejun Heo commit 01af2fac9ea76513e2fba689ad580f985f32a8c3 Author: Dave Jones Date: Tue May 30 18:22:07 2006 -0400 [AGPGART] Remove pointless initialisation in intel-agp Signed-off-by: Dave Jones commit 89197e34ea63d7f619dade525de8e69a15f40405 Author: Dave Jones Date: Tue May 30 18:19:39 2006 -0400 [AGPGART] Remove pointless code from agp_generic_create_gatt_table() Signed-off-by: Dave Jones commit 484944a5b002cf87b38a8f073d37afcfb8afff28 Author: Dave Jones Date: Tue May 30 18:09:31 2006 -0400 [CPUFREQ] Remove more freq_table reinitialisations. Signed-off-by: Dave Jones commit 5557976ca97c3a3002805f575a45ad354e1050ff Author: Dave Jones Date: Tue May 30 17:59:48 2006 -0400 [CPUFREQ] Fix another redundant initialisation in freq_table Signed-off-by: Dave Jones commit 355eb318018c6f44a335b0e5efb1f3bf2f1685d0 Author: Dave Jones Date: Tue May 30 17:58:41 2006 -0400 [CPUFREQ] Remove duplicate assignment in freq_table Signed-off-by: Dave Jones commit 511e9ee17099c6ebe315c0524b8b482d4767ab3d Author: Dave Jones Date: Tue May 30 17:57:14 2006 -0400 [CPUFREQ] CodingStyle nits in cpufreq_stats.c Signed-off-by: Dave Jones commit 851777b7b686c80e417fd811cdea3e5aa5305745 Author: Dave Jones Date: Tue May 30 17:55:01 2006 -0400 [CPUFREQ] Remove duplicate assignment from cpufreq-nforce2 Signed-off-by: Dave Jones commit b6571da9f328999a6bce429b5f614a3d64b926ee Author: Dave Jones Date: Tue May 30 17:50:22 2006 -0400 [CPUFREQ] Remove pointless reinitialisations in acpi-cpufreq Signed-off-by: Dave Jones commit 83844510ec9dc89a676e71d3cc28289905c2caec Author: Dave Jones Date: Tue May 30 17:43:54 2006 -0400 [CPUFREQ] Remove pointless reinitialisation from powernow-k8 This var is already set at entry to the function. Signed-off-by: Dave Jones commit 8eebf1a4c3682f71dbda3348abfcdd4d2a751fd3 Author: Dave Jones Date: Tue May 30 17:40:16 2006 -0400 [CPUFREQ] Remove redundant initialisation from longhaul. Signed-off-by: Dave Jones commit e2aa8732ac11570acddf326874a34ab684752e34 Author: Dave Jones Date: Tue May 30 17:37:15 2006 -0400 [CPUFREQ] Clean up longhaul's speed pretty-printer Getting ready to move to core cpufreq. - Use snprintf - Remove unnecessary nesting improving readability. Signed-off-by: Dave Jones commit 8cbe0169053ffa185ad349088eb0901946c14a09 Author: Dave Jones Date: Tue May 30 17:26:08 2006 -0400 [CPUFREQ] Disambiguate loop indexes in powernow-k7 This shouldn't have actually caused any problems (as we return if we 'corrupt' 'i', but it's still not very pretty. For the sake of adding another local variable, this got cleaner. Signed-off-by: Dave Jones commit 2e3f8faaa73f5065ae653a84997b5cd4d5876e1a Author: Dave Jones Date: Tue May 30 17:25:14 2006 -0400 [CPUFREQ] Typo in powernow-k8 (Also fix some horked indentation) Signed-off-by: Dave Jones commit e9482b4374e2596e6f3f1ab30c4ea469f4ac6311 Author: Joern Engel Date: Tue May 30 14:25:46 2006 +0200 [MTD] Allow alternate JFFS2 mount variant for root filesystem. With this patch, "root=mtd3" and "root=mtd:foo" work for a JFFS2 rootfs. Signed-off-by: Joern Engel commit 73c619ea0e49c9306afa7ea53c3362fbc56ffd70 Author: Joern Engel Date: Tue May 30 14:25:35 2006 +0200 [MTD] Disconnect struct mtd_info from ABI mtdchar.c direcly copied part of struct mtd_info to userspace, thereby implicitly making it part of the ABI. With this patch, struct mtd_info is independent of the ABI and can have its fields removed, reordered, etc. Signed-off-by: Joern Engel commit 92cbfdcc3661d7670b01b92b89811cd3a2412297 Author: Joern Engel Date: Tue May 30 14:25:24 2006 +0200 [MTD] replace MTD_RAM with MTD_GENERIC_TYPE Ram devices get the extra capability of MTD_NO_ERASE - not requiring an explicit erase before writing to it. Currently only mtdblock uses this capability. Rest of the patch is a simple text replacement. Signed-off-by: Joern Engel commit e369d62e92d526a7ed641e2f0b2978fb0ce366c5 Author: Joern Engel Date: Tue May 30 14:25:17 2006 +0200 [MTD] replace MTD_ROM with MTD_GENERIC_TYPE No mtd user should ever check for the device type. Instead, device features should be checked by the flags - if at all. As a first step towards type removal, change MTD_ROM into MTD_GENERIC_TYPE. Signed-off-by: Joern Engel commit e1219724be193519f20743f5500bd1eff11890d0 Author: Joern Engel Date: Tue May 30 14:25:05 2006 +0200 [MTD] remove a forgotten MTD_XIP MTD_XIP definition was removed in an earlier patch. This invocation was left by mistake. Signed-off-by: Joern Engel commit 7e9a0bb00c4ccb7a05c41b2728758d5bb3dd54fc Author: Andrew Morton Date: Tue May 30 09:06:41 2006 +0100 [MTD] Fix build warnings (and debug build error) in nand_base.c drivers/mtd/nand/nand_base.c: In function 'nand_transfer_oob': drivers/mtd/nand/nand_base.c:909: warning: comparison of distinct pointer types lacks a cast drivers/mtd/nand/nand_base.c: In function 'nand_do_read_oob': drivers/mtd/nand/nand_base.c:1097: error: 'len' undeclared (first use in this function) drivers/mtd/nand/nand_base.c:1097: error: (Each undeclared identifier is reported only once drivers/mtd/nand/nand_base.c:1097: error: for each function it appears in.) drivers/mtd/nand/nand_base.c: In function 'nand_fill_oob': drivers/mtd/nand/nand_base.c:1411: warning: comparison of distinct pointer types lacks a cast Signed-off-by: Andrew Morton Signed-off-by: Thomas Gleixner Signed-off-by: David Woodhouse commit 098a19811b483f8e047d8292641c88e776452de0 Author: David Woodhouse Date: Tue May 30 09:00:14 2006 +0100 [JFFS2] Preallocate node refs for cleanmarker in summary scan Signed-off-by: David Woodhouse commit 13ba42df4a385d7b77d7aac32b93bdcd73e6d6e1 Author: David Woodhouse Date: Tue May 30 08:59:34 2006 +0100 [JFFS2] Fix calculation of potential summary marker offset on NOR flash. Helps if we look _inside_ the buffer, rather than adding jeb->offset to it. Doh. Signed-off-by: David Woodhouse commit f1a28c02843efcfcc41982149880bac3ac180234 Author: Thomas Gleixner Date: Tue May 30 00:37:34 2006 +0200 [MTD] NAND Expose the new raw mode function and status info to userspace The raw read/write access to NAND (without ECC) has been changed in the NAND rework. Expose the new way - setting the file mode via ioctl - to userspace. Also allow to read out the ecc statistics information so userspace tools can see that bitflips happened and whether errors where correctable or not. Also expose the number of bad blocks for the partition, so nandwrite can check if the data fits into the parition before writing to it. Signed-off-by: Thomas Gleixner commit 9a1fcdfd4bee27c418424cac47abf7c049541297 Author: Thomas Gleixner Date: Mon May 29 14:56:39 2006 +0200 [MTD] NAND Signal that a bitflip was corrected by ECC Return -EUCLEAN on read when a bitflip was detected and corrected, so the clients can react and eventually copy the affected block to a spare one. Make all in kernel users aware of the change. Signed-off-by: Thomas Gleixner commit 8593fbc68b0df1168995de76d1af38eb62fd6b62 Author: Thomas Gleixner Date: Mon May 29 03:26:58 2006 +0200 [MTD] Rework the out of band handling completely Hopefully the last iteration on this! The handling of out of band data on NAND was accompanied by tons of fruitless discussions and halfarsed patches to make it work for a particular problem. Sufficiently annoyed by I all those "I know it better" mails and the resonable amount of discarded "it solves my problem" patches, I finally decided to go for the big rework. After removing the _ecc variants of mtd read/write functions the solution to satisfy the various requirements was to refactor the read/write _oob functions in mtd. The major change is that read/write_oob now takes a pointer to an operation descriptor structure "struct mtd_oob_ops".instead of having a function with at least seven arguments. read/write_oob which should probably renamed to a more descriptive name, can do the following tasks: - read/write out of band data - read/write data content and out of band data - read/write raw data content and out of band data (ecc disabled) struct mtd_oob_ops has a mode field, which determines the oob handling mode. Aside of the MTD_OOB_RAW mode, which is intended to be especially for diagnostic purposes and some internal functions e.g. bad block table creation, the other two modes are for mtd clients: MTD_OOB_PLACE puts/gets the given oob data exactly to/from the place which is described by the ooboffs and ooblen fields of the mtd_oob_ops strcuture. It's up to the caller to make sure that the byte positions are not used by the ECC placement algorithms. MTD_OOB_AUTO puts/gets the given oob data automaticaly to/from the places in the out of band area which are described by the oobfree tuples in the ecclayout data structre which is associated to the devicee. The decision whether data plus oob or oob only handling is done depends on the setting of the datbuf member of the data structure. When datbuf == NULL then the internal read/write_oob functions are selected, otherwise the read/write data routines are invoked. Tested on a few platforms with all variants. Please be aware of possible regressions for your particular device / application scenario Disclaimer: Any whining will be ignored from those who just contributed "hot air blurb" and never sat down to tackle the underlying problem of the mess in the NAND driver grown over time and the big chunk of work to fix up the existing users. The problem was not the holiness of the existing MTD interfaces. The problems was the lack of time to go for the big overhaul. It's easy to add more mess to the existing one, but it takes alot of effort to go for a real solution. Improvements and bugfixes are welcome! Signed-off-by: Thomas Gleixner commit f4a43cfcecfcaeeaa40a9dbc1d1378298c22446e Author: Thomas Gleixner Date: Sun May 28 11:01:53 2006 +0200 [MTD] Remove silly MTD_WRITE/READ macros Most of those macros are unused and the used ones just obfuscate the code. Remove them and fixup all users. Signed-off-by: Thomas Gleixner commit 5bd34c091a044d130601370c370f84b1c59f1627 Author: Thomas Gleixner Date: Sat May 27 22:16:10 2006 +0200 [MTD] NAND Replace oobinfo by ecclayout The nand_oobinfo structure is not fitting the newer error correction demands anymore. Replace it by struct nand_ecclayout and fixup the users all over the place. Keep the nand_oobinfo based ioctl for user space compability reasons. Signed-off-by: Thomas Gleixner commit ff268fb8791cf18df536113355d7184007c269d9 Author: Thomas Gleixner Date: Sat May 27 20:36:12 2006 +0200 [MTD] NAND Consolidate oobinfo handling The info structure for out of band data was copied into the mtd structure. Make it a pointer and remove the ability to set it from userspace. The position of ecc bytes is defined by the hardware and should not be changed by software. Signed-off-by: Thomas Gleixner commit 8be834f76291fdcc0614cb84926c6910b9f2ecbc Author: Thomas Gleixner Date: Sat May 27 20:05:26 2006 +0200 [MTD] NAND Fix platform structure and NDFC driver The platform structure was lacking an oobinfo field. The NDFC driver had some remains from another tree. Signed-off-by: Thomas Gleixner commit 19676ff0a64af9d75d48f17cb67bee8110f6ffbf Author: Andrew Morton Date: Mon May 29 11:33:33 2006 +0100 [MTD] Fix debug printk format warning in m25p80 SPI chip driver, again. Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse commit 33280eac704e3e156eef2fa9ed9ddf427a1c223c Author: David Woodhouse Date: Mon May 29 11:24:29 2006 +0100 [MTD] AMD Geode NAND support can depend on X86_32; we won't see it on x86_64 Signed-off-by: David Woodhouse commit 7a532c69c37dbb46bfd0276160e624f06552adfc Author: Dennis Munsie Date: Mon May 29 18:58:09 2006 +1000 intelfb: use regular modedb table instead of VESA intelfb driver -- use the regular modedb table instead of the VESA modedb table. Ideally, the 9xx stride patch should be applied first, since there are modes in the VESA table that won't work without that patch. Signed-off-by: Dennis Munsie Signed-off-by: Dave Airlie commit 56e004e5435c008728b1444b51d757da2e098976 Author: Antonino A. Daplas Date: Mon May 29 18:49:08 2006 +1000 intelfb: use firmware EDID for mode database Use firmware EDID for the driver's private mode database. Signed-off-by: Antonino Daplas Cc: Sylvain Meyer Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie commit 080a416802153dbbb20ab4f4fa1225867096d071 Author: Dave Airlie Date: Mon May 29 18:45:19 2006 +1000 Revert "intelfb driver -- use the regular modedb table instead of the VESA" This reverts 2c47430a03bbcc3c9a623a07eca5baf92c7d20c8 commit. This conflicts with a patch in -mm from Antonino reapply later. Signed-off-by: Dave Airlie commit 65eb2f97db17f6f6a92cad3aad93b531f991ebf1 Author: Eric Hustvedt Date: Mon May 29 18:38:55 2006 +1000 intelfb: int option fix Fix integer option parsing in the intelfb driver. The macro wasn't accounting for the equal sign past the option name. As a result, the vram option always returned 0. Signed-off-by: Eric Hustvedt Signed-off-by: Dennis Munsie commit ef2824073fba9def3cf122e89cc485f66dd71f70 Author: Borislav Petkov Date: Mon May 29 01:06:23 2006 -0400 libata debugging: set initial dbg value This patch sets the prerequisites for the new debugging scheme that more or less resembles Donald Becker's net driver example. This one liner doesn't change any functionality beside setting the appropriate debug level for the msg_enable control in the ata_port struct, which will be later used by the ata_msg_* macros to control the amount of debug information sent to printk. Signed-off-by: Signed-off-by: Jeff Garzik commit a6a8bef722875a95bb73e6de7da924a8d417b52c Author: David Woodhouse Date: Mon May 29 00:41:11 2006 +0100 [JFFS2] Preallocate raw_node_refs in a couple of missing places in scan Signed-off-by: David Woodhouse commit 2ebf09c2491433a499e0ae7723d04e9e810afa84 Author: David Woodhouse Date: Sun May 28 22:13:25 2006 +0100 [JFFS2] Fix oops when marking space dirty in scan, but no previous node exists. Signed-off-by: David Woodhouse commit 2b89dad0c7e3b03d45d9674ee9a7b49670df098e Author: Hannes Reinecke Date: Tue May 23 10:29:28 2006 +0200 [SCSI] audit drivers for incorrect max_id use max_id now means the maximum number of ids on the bus, which means it is one greater than the largest possible id number. Signed-off-by: James Bottomley commit 091686d3b5569d2ec76b9e6dab7f3608b6f64497 Author: Amit Arora Date: Fri May 19 16:14:50 2006 -0700 [SCSI] Return -EINVAL when "id == max_id" in scsi_scan_host_selected() The scsi_scan_host_selected() should return -EINVAL when the id is equal to the max_id. Currently it uses ">" when comparing with max_id, and hence leaves the border case when "id==max_id". The channel and lun have values valid from 0 up to, and including, max_channel or max_lun. But, the valid values for id range from 0 to max_id-1. This patch fixes the problem. Signed-off-by: Amit Arora Signed-off-by: James Bottomley commit 93ef588735973e4c35ff3707685678cdebd694a4 Author: Andreas Herrmann Date: Mon May 22 18:27:30 2006 +0200 [SCSI] zfcp: bump up version number Bump up version number, skip "4.6.0" because this might clash with zfcp version in certain distros. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley commit 338151e066084d92d89f44311e5521ef847a50b9 Author: Andreas Herrmann Date: Mon May 22 18:25:56 2006 +0200 [SCSI] zfcp: make use of fc_remote_port_delete when target port is unavailable If zfcp's port erp fails we now call fc_remote_port_delete. This helps to avoid offlined scsi devices if scsi commands time out due to path failures. When an adapter erp fails we call fc_remote_port_delete for all ports on that adapter. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley commit 75bfc2837bbcc329193d51e8b7115184b78beae0 Author: Ralph Wuerthner Date: Mon May 22 18:24:33 2006 +0200 [SCSI] zfcp: evaluate plogi payload to set maxframe_size, supported_classes of rports Signed-off-by: Ralph Wuerthner Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley commit b7a52fa7fff2309031a2f849bc489206afd2fa4a Author: Ralph Wuerthner Date: Mon May 22 18:21:28 2006 +0200 [SCSI] zfcp: print bit error threshold data human readable Replace hex dump of bit error threshold data by log message showing bit error threshold data human readable. Signed-off-by: Ralph Wuerthner Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley commit 06506d00ec1a0d7d3b1dff59185af355ce29ac0a Author: Andreas Herrmann Date: Mon May 22 18:18:19 2006 +0200 [SCSI] zfcp: (cleanup) removed superfluous macros, struct members, typedefs Removed some macros, struct members and typedefs which were unused or not necessary. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley commit ec4081c6ba4fba6a8bc12a0e93db8817ba63ce47 Author: Andreas Herrmann Date: Mon May 22 18:17:30 2006 +0200 [SCSI] zfcp: (cleanup) kmalloc/kzalloc replacement Replace kmalloc/memset by kzalloc or kcalloc. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley commit ca3271b40225a1049334766f6fb35b57a0162bd2 Author: Andreas Herrmann Date: Mon May 22 18:15:49 2006 +0200 [SCSI] zfcp: (cleanup) remove useless comments Removed some useless comments. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley commit 4a9d2d8bf989c77b54add430932fa5ed8a80dba9 Author: Andreas Herrmann Date: Mon May 22 18:14:08 2006 +0200 [SCSI] zfcp: (cleanup) shortened copyright and author information Copyright update, shortened file headers, shortened author information. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley commit 83055d46e5eddbb3574ef5e9c0d9c021bcb75c0b Author: Jay Cliburn Date: Wed May 24 00:02:51 2006 +0200 via-velocity: allow MTU size less than 1500 bytes Change the minimum allowable MTU size from 1500 bytes to 64 bytes. Signed-off-by: Jay Cliburn commit ddc58bd65ebe58c243e9f609384825df9ffd04ad Author: David Woodhouse Date: Sat May 27 13:15:16 2006 +0100 [JFFS2] Fix wbuf recovery of f->metadata->raw node. A data node might not be in the fraglist; it could be f->metadata. Signed-off-by: David Woodhouse commit f728377f6786bcdf1dbf33394360164e86f40094 Author: Dave Airlie Date: Sat May 27 18:56:02 2006 +1000 sync modesetting code with X.org Signed-off-by: Dave Airlie commit c9daa873c3a7c769821ec6c8258adf098bb0435c Author: Dave Airlie Date: Sat May 27 18:44:02 2006 +1000 intelfb: align with changes from my X driver. This just realigns the PLL calculation routines with the ones from my X.org driver. Signed-off-by: Dave Airlie commit 2c47430a03bbcc3c9a623a07eca5baf92c7d20c8 Author: Dennis Munsie Date: Sat May 27 18:33:35 2006 +1000 intelfb driver -- use the regular modedb table instead of the VESA modedb table. Ideally, the 9xx stride patch should be applied first, since there are modes in the VESA table that won't work without that patch. Signed-off-by: Dennis Munsie Signed-off-by: Dave Airlie commit 1aecb393091d3c0787f92445420d96ef58c9782a Author: Eric Hustvedt Date: Sat May 27 18:30:00 2006 +1000 Adds support for 256MB aperture on 945 chipsets to the intelfb driver and corrects calculation of stolen memory overhead. Signed-off-by: Eric Hustvedt Signed-off-by: Dennis Munsie Signed-off-by: Dave Airlie commit df7df8ab7b38ca80bbaf5ffafd401d6c739fd45f Author: Dennis Munsie Date: Sat May 27 18:17:52 2006 +1000 intelfb -- uses stride alignment of 64 on the 9xx chipsets. Signed-off-by: Dennis Munsie Signed-off-by: Dave Airlie commit 92af11cdec410f5de4e8d702d24e1672ce26a1f6 Author: Al Viro Date: Sat May 27 02:24:14 2006 -0400 [PATCH] missing readb/readw in rio Signed-off-by: Al Viro commit 0645819196b5029936cf07a8ba27860e0d45c8d9 Author: Al Viro Date: Sat May 27 02:11:12 2006 -0400 [PATCH] copy_to_user() from iomem is a bad thing Signed-off-by: Al Viro commit 6bc540e69a6376b9d58d8490f4998da9e45e2746 Author: Al Viro Date: Sat May 27 02:00:00 2006 -0400 [PATCH] forgotten swap of copyout() arguments Signed-off-by: Al Viro commit 1bf087194f01bce5b2d7b39f27d71d5f346fbf08 Author: Al Viro Date: Sat May 27 01:55:52 2006 -0400 [PATCH] handling rio MEMDUMP it copies data _from_ iomem, so it should be rio_memcpy_fromio(), not ->Copy(). Signed-off-by: Al Viro commit ae5b28a5bb1b5f5d53085a044aec69db41fd0336 Author: Al Viro Date: Sat May 27 01:48:08 2006 -0400 [PATCH] fix rio_copy_to_card() for OLDPCI case It replaced old rio_pcicopy(). That puppy did _not_ do readb() (unlike rio_memcpy_toio()) and current implementation is simply broken - readb(NULL) is never a valid thing to do. Signed-off-by: Al Viro commit bfa6b7bb35a9c8c8acae3056f2cb3364c52693d4 Author: Al Viro Date: Sat May 27 00:36:10 2006 -0400 [PATCH] uses of ->Copy() in rioroute are bogus ... there we are building a command in normal memory; it will be copied to iomem (by ->Copy()) later. Use memcpy()... Signed-off-by: Al Viro commit c7c0d0a10f6e4cea95ed84adcdd37948cac09b85 Author: Al Viro Date: Sat May 27 00:19:54 2006 -0400 [PATCH] bogus order of copy_from_user() arguments ... aka "somebody forgot to swap arguments when converting from copyin()" Signed-off-by: Al Viro commit 38d0d001b973d8c72c18524cc25ef39db85c66cd Author: Al Viro Date: Sat May 27 00:15:09 2006 -0400 [PATCH] rio ->Copy() expects the sourse as first argument ... so conversion from rio_pcicopy() to rio_copy_to_card() had broken the damn thing. Signed-off-by: Al Viro commit d886cb586f60a5ccf156392f96a39bc52db925d0 Author: Al Viro Date: Sat May 27 00:08:25 2006 -0400 [PATCH] trivial annotations in rio Signed-off-by: Al Viro commit 75e995855f45a83afdae34d50c0b3ee14fb23b7a Author: Alan Cox Date: Wed May 24 14:14:41 2006 +0100 [PATCH] libata: add pio_data_xfer_noirq Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit 622b20fcb8b42aa4c3c87c0a036f2ad0927b64bc Author: Alan Cox Date: Wed May 24 14:06:11 2006 +0100 [PATCH] PCI identifiers for the pata_via update These IDs are also used by the drivers/ide/pci changes submitted by VIA. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit de1e938e54deba5b093a3074dfafd0d11afacbe1 Author: Yoichi Yuasa Date: Thu May 25 10:24:46 2006 +0900 [PATCH] r8169: add new PCI ID Hi, This patch add new PCI ID for r8169 driver. RTL8110SBL has this PCI ID. Please aply. Yoichi Signed-off-by: Yoichi Yuasa Signed-off-by: Jeff Garzik commit f3b197ac26ed0e57989856494c495818dcc7f9ac Author: Jeff Garzik Date: Fri May 26 21:39:03 2006 -0400 [netdrvr] trim trailing whitespace: 8139*.c, epic100, forcedeth, tulip/* commit 4c0c2fd486b6598e37c77b5d81a08bc2d948aa7b Author: Ayaz Abdulla Date: Thu May 25 13:10:38 2006 -0400 [PATCH] pci_ids: add new device ids This patch adds new device ids for MCP61 and MCP65 chips. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit eb91f61b2294ccdb914df255164ada70dbbf2d58 Author: Ayaz Abdulla Date: Wed May 24 18:13:19 2006 -0400 [PATCH] forcedeth: add support for flow control This patch adds flow control support for tx and rx pause frames in forcedeth. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik commit 48cf270e45ff6ff076dd6557b38ec1068dd71809 Author: Jens Osterkamp Date: Wed May 24 23:33:11 2006 +0200 [PATCH] spidernet: replace whitespaces by tabs The original patch was using whitespaces instead of tabs. Signed-off-by: Jens Osterkamp Signed-off-by: Arnd Bergmann Signed-off-by: Jeff Garzik commit 89bad5892abca55f56d0ea713c7306d1f845ac8e Author: Albert Lee Date: Fri May 26 13:49:18 2006 +0800 [PATCH] libata: add back ->data_xfer to ata_piix.c Add back ->data_xfer and ->mode_filter to ata_piix.c. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 6082823632e40737515d03381e1ba59cfb4d4909 Author: Alexey Dobriyan Date: Tue May 23 14:52:21 2006 -0700 [PATCH] e1000: endian fixes Signed-off-by: Alexey Dobriyan Cc: "Ronciak, John" Cc: Jesse Brandeburg Acked-by: Auke Kok Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik commit ba0251fe87ea560eb377917e06ba0b5b9ab89094 Author: Thomas Gleixner Date: Sat May 27 01:02:13 2006 +0200 [MTD] NAND Consolidate references and add back default name setting We have a type pointer. Make use of it instead of the error prone nand_ids[i] reference. The NAND driver used to set default name settings from the chip ID string for the device. The feature got lost during the rework. Add it back. Signed-off-by: Thomas Gleixner commit cca3b837bbb4c984165f9f9c7c06846bc0425791 Author: Thomas Gleixner Date: Sat May 27 00:47:18 2006 +0200 [MTD] NAND simplify nand_chip_select nCE setting can be done when the first command is issued to the device. We keep the deselect functionality as it makes sense to deassert nCE when the device becomes idle. Signed-off-by: Thomas Gleixner commit 29da9cea46f65cb9488641354fe554e9ef8a3a85 Author: David Woodhouse Date: Fri May 26 23:05:44 2006 +0100 [MTD] Fix thinko in nand_write_page_hwecc() Signed-off-by: Thomas Gleixner Signed-off-by: David Woodhouse commit 9bfeb691e75b21fdaa80ffae719083200b190381 Author: David Woodhouse Date: Fri May 26 21:19:05 2006 +0100 [JFFS2] Switch to using an array of jffs2_raw_node_refs instead of a list. This allows us to drop another pointer from the struct jffs2_raw_node_ref, shrinking it to 8 bytes on 32-bit machines (if the TEST_TOTLEN) paranoia check is turned off, which will be committed soon). Signed-off-by: David Woodhouse commit f75e5097ef298c5a0aa106faa211d1afdc92dc3d Author: Thomas Gleixner Date: Fri May 26 18:52:08 2006 +0200 [MTD] NAND modularize write function Modularize the write function and reorganaize the internal buffer management. Remove obsolete chip options and fixup all affected users. Signed-off-by: Thomas Gleixner commit d3f464b5385531c4250a8b1dbd2f9ba6bbfcebb9 Author: Auke Kok Date: Fri May 26 09:38:10 2006 -0700 ixgb: update version, dates increase the year dates to 2006 and bump the version to 1.0.109-k2 Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 25a9f2f154feaf1c86e46a8fe7b9940d0b0a96f6 Author: Auke Kok Date: Fri May 26 09:36:03 2006 -0700 ixgb: remove changelog same as e1000 - remove the changelog from the driver code itself. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 25943071b40580ba24e0a111e86b4869b9f5c07c Author: Auke Kok Date: Fri May 26 09:35:57 2006 -0700 ixgb: replace netdev->priv with netdev_priv() fix netdev->priv ==> netdev_priv(netdev) Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 235949d162076832b8b9a6e30ca51876c3fa11e8 Author: Auke Kok Date: Fri May 26 09:35:52 2006 -0700 ixgb: remove inlines, allow compiler to choose deinline a few large functions as to allow the compiler to pick. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 3352a3b20ce880b17f185ad55bf27751f1c8edb9 Author: Auke Kok Date: Fri May 26 09:35:47 2006 -0700 ixgb: remove lock access in the fast path This mimics a change made in the e1000 driver that imitates a slick tg3 way of avoiding grabbing the lock around restarting the tx queue. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 3f3dc0dd2086402b684545d66bb5ece93c76330b Author: Auke Kok Date: Fri May 26 09:35:43 2006 -0700 ixgb: allocate only buffersize needed In order to help correct window size growth, use the MFS register to limit the packet sizes received and allocate only the buffer size necessary Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 989316ddfeafd0e8fb51a4d811383769ad62637a Author: Auke Kok Date: Fri May 26 09:35:38 2006 -0700 ixgb: revert an unwanted fix regarding tso/descriptors There seemed to be another bug introduced as well as a performance hit with the addtion of the sentinel descriptor workaround. Removal of this workaround appears to prevent the hang. We'll take a risk and remove it, as we had never seen the originally reported bug under linux. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 8556f0d18923495ffd15ce87089312b3d8f2414c Author: Auke Kok Date: Fri May 26 09:35:32 2006 -0700 ixgb: fix interface losing macaddr on ifdn/up user contributed fix for LAA across down/up, from tonychung00@users.sf.net. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit e59d16965ca38df91c4d9390d8eb5a62d7739589 Author: Auke Kok Date: Fri May 26 09:35:28 2006 -0700 ixgb: fix smp polling race condition Moved interrupt masking to before requesting the interrupt from the OS. Moved interrupt enable to after netif_poll_enable. This fixes a racy BUG() where polling would be running on another CPU at the same time that netif_poll_enable would run. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit e4d222ff18bca6322f032088a21e9c4a4c038b85 Author: David Woodhouse Date: Fri May 26 02:06:27 2006 +0100 [MTD] Remove PCI dependency for Geode CS553[56] NAND controller. PCI is faked on these devices by SMM traps. Don't depend on that -- check for the chipset directly instead. Signed-off-by: David Woodhouse commit a24e2513c2d03c9a92739ec6fa7e7208f792881e Author: Auke Kok Date: Thu May 25 13:24:27 2006 -0700 ixgb: increment version to 1.0.104-k4 Increment the driver version to 1.0.104-k4 Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 6b900bb4bcb6095339f8d404babd9d779bfa1ea4 Author: Auke Kok Date: Thu May 25 13:24:21 2006 -0700 ixgb: use rx copybreak/skb recycle o use rx copybreak/skb recycle Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 1dfdd7df21309e57867962020a5ccb83d00e5432 Author: Auke Kok Date: Thu May 25 13:24:17 2006 -0700 ixgb: add performance enhancements to the buffer_info struct o modify the rx refill logic and tail bump o add counter for failures Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 89291a9d5b70778e49e2563247c6c7e3efac9b14 Author: David Woodhouse Date: Thu May 25 13:30:24 2006 +0100 [JFFS2] Fix 64-bit size_t problems in XATTR code. Signed-off-by: David Woodhouse commit c5b553cc2c36f770086a37764f7a06dd615eda8f Author: David Woodhouse Date: Thu May 25 13:25:17 2006 +0100 [MTD] Fix NAND_VERIFY_WRITE case to build with tglx's recent changes Bad tglx. No biscuit. Signed-off-by: David Woodhouse commit 8546ac4f84b252fff078fab1a992c70504147914 Author: Thomas Gleixner Date: Thu May 25 13:38:45 2006 +0200 [MTD] Remove the only useless readv implementation Removing readv from struct mtd_info broke block2mtd. Remove the reference and the useless default implementation. Signed-off-by: Thomas Gleixner commit f5bbdacc41939f89d8ccb18dd79cd9b21c0cb75d Author: Thomas Gleixner Date: Thu May 25 10:07:16 2006 +0200 [MTD] NAND Modularize read function Split the core of the read function out and implement seperate handling functions for software and hardware ECC. Signed-off-by: Thomas Gleixner commit 9577f44a899cf4acb9e381c8946307b72153cd15 Author: Thomas Gleixner Date: Thu May 25 10:04:31 2006 +0200 [MTD] NAND Add read/write function pointers to struct nand_ecc_ctrl Add read/write function pointers to struct nand_ecc_ctrl to prepare the modulaization of nand_read/write functions. The current implementation handles every type of ecc mode software/hardware and all kinds of strange ecc placement schemes in one switch/if construct. Thats too complex to maintain and too inflexible to expand. Modularization will also shorten the code pathes of the read/write functions. Signed-off-by: Thomas Gleixner commit 7fac464868ec5d80019fa549b8b4516dd1dc9d5c Author: Thomas Gleixner Date: Thu May 25 09:57:31 2006 +0200 [MTD] Add ECC statistics to struct mtd_info FLASH - especially NAND FLASH - will become less reliable and bit flips more likely. Add an ECC statistics struct to struct mtd_info to keep track of this. Signed-off-by: Thomas Gleixner commit 7314e9e7d57293c58b3e10a25a8a1d9328444187 Author: Thomas Gleixner Date: Thu May 25 09:51:54 2006 +0200 [MTD] NAND Cleanup oob functions Cleanup the code in the oob related functions and make use of the new NO_READRDY flag. Signed-off-by: Thomas Gleixner commit 7a30601b3ac7b02440ffa629fd3d2cca71c1bcd8 Author: Thomas Gleixner Date: Thu May 25 09:50:16 2006 +0200 [MTD] NAND Introduce NAND_NO_READRDY option The nand driver has a superflous read ready / command delay in the read functions. This was added to handle chips which have an automatic read forward. Newer chips do not have this functionality anymore. Add this option to avoid the delay / I/O operation. Mark all large page chips with the new option flag. Signed-off-by: Thomas Gleixner commit 04bbd0eafb0c733c6c7f5d63c5098c615fe0685a Author: Thomas Gleixner Date: Thu May 25 09:45:29 2006 +0200 [MTD] NAND Initialize controller lock and wq only once The lock simplifying patch did not move the lock and waitqueue initialization into the controller allocation patch. This reinitializes waitqueue and spinlocks also for driver supplied controller stuctures. Move it into the allocation path. Signed-off-by: Thomas Gleixner commit 8b9e9fe8c6ee354aa75dc5a33e1575b21aa52084 Author: David Woodhouse Date: Thu May 25 01:53:09 2006 +0100 [JFFS2] Fix and improve debugging output during scan. Print wasted_size in scanned eraseblocks, print range correctly for summary dirent and inode entries. Signed-off-by: David Woodhouse commit 046b8b9808127d63326a33bc6298c90eaee90eeb Author: David Woodhouse Date: Thu May 25 01:50:35 2006 +0100 [JFFS2] Add 'jeb' argument to jffs2_prealloc_raw_node_refs() Preallocation of refs is shortly going to be a per-eraseblock thing, rather than per-filesystem. Add the required argument to the function. Signed-off-by: David Woodhouse commit f61579c33736476e41e296a16c0d4ead4b953187 Author: David Woodhouse Date: Thu May 25 01:42:40 2006 +0100 [JFFS2] Correctly handle wasted space before summary node. Signed-off-by: David Woodhouse commit c38c1b613d742b5fa075071568f44dc8ec9f1cb8 Author: David Woodhouse Date: Thu May 25 01:38:27 2006 +0100 [JFFS2] jffs2_free_all_node_refs() doesn't free them all. Rename it. ... to jffs2_free_jeb_node_refs() since that's what it does. Signed-off-by: David Woodhouse commit f560928baa605e8faaa3de6cc1b11ebb645e97db Author: David Woodhouse Date: Thu May 25 01:37:28 2006 +0100 [JFFS2] Allocate node_ref for wasted space when skipping to page boundary One more place where we were changing the accounting info without actually allocating a ref for the lost space... Signed-off-by: David Woodhouse commit 12efdde3139c568a59561b69865fd14f37c75603 Author: Thomas Gleixner Date: Wed May 24 22:57:09 2006 +0200 [MTD] NAND fix cmd_ctrl breakage The cmd_ctrl rework lacks some state transition flags. Signed-off-by: Thomas Gleixner commit ace4dfee56fff184e07d7248a759b574321afa8b Author: Thomas Gleixner Date: Wed May 24 12:07:37 2006 +0200 [MTD] NAND coding style and namespace cleanup Cleanup the functions which are not going to change in the next steps. Signed-off-by: Thomas Gleixner commit c7c16c8e7604a8974d48562fecf8d9c7e221fced Author: David Woodhouse Date: Wed May 24 14:24:02 2006 +0100 [JFFS2] Revert Artem's Bunkage in debug messages. Random unthinking 'cleanup' caused debug messages like this: Obsoleting node at 0x0006daf4 of len 0x3a4: <7>Dirtying If messages are continuation of an existing line, they don't need to be prefixed with KERN_DEBUG. THINK. Or you will be replaced by a small shell script. Signed-off-by: David Woodhouse commit 99988f7bbd16b861590dda4631c4db6cb17b5091 Author: David Woodhouse Date: Wed May 24 09:04:17 2006 +0100 [JFFS2] Introduce ref_next() macro for finding next physical node Another part of the preparation for switching to an array... Signed-off-by: David Woodhouse commit c9e055ac4fdbb52622437e0dbfdbc1d4897d2775 Author: Herbert Valerio Riedel Date: Sun May 7 23:22:53 2006 +0200 [PATCH] phy: new SMSC LAN83C185 PHY driver new SMSC LAN83C185 10BaseT/100BaseTX PHY driver for the PHY subsystem Signed-off-by: Herbert Valerio Riedel Signed-off-by: Jeff Garzik commit 957d2df1801865eb1e63864bc63b970aa9c460ba Author: Alan Cox Date: Tue May 23 13:18:57 2006 +0100 [PATCH] libata: Remove obsolete flag ATA_FLAG_IRQ_MASK was added when I did the original data transfer with IRQ masked bits for PIO. It has since been replaced by ->pio_data_xfer methods so should be removed so nobody uses it by mistake thinking it still works. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit 31a34fe75906ba5f61606eaed01da313f29ca4b1 Author: Alan Cox Date: Mon May 22 22:58:14 2006 +0100 [PATCH] ata_piix formatting if( spacing fix for Garzik compliant formatting Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit 0a9cb46a73abd6c45e7c986bec984eed60c417b6 Author: Jon Mason Date: Fri May 19 15:35:32 2006 -0500 [PATCH] remove powerpc bitops in favor of existing generic bitops There already exists a big endian safe bitops implementation in lib/find_next_bit.c. The code in it is 90%+ common with the powerpc specific version, so the powerpc version is redundant. This patch makes the necessary changes to use the generic bitops in powerpc, and removes the powerpc specific version. Signed-off-by: Jon Mason Signed-off-by: Paul Mackerras commit 7499bf1a4cabde789e7694b33d01a1913ae1dddf Author: Stephen Rothwell Date: Fri May 19 17:06:38 2006 +1000 [PATCH] powerpc: cleanup of iSeries flat device tree Consolidate the vio device node creation. Make some parameters const. Make a few more things __initdata. Get the device_type strings out of the device tree blob. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 72a14eafb243b1f31118ea55a7e8c2588b5ad468 Author: Stephen Rothwell Date: Fri May 19 17:04:12 2006 +1000 [PATCH] powerpc: make iSeries flattened device tree dynamic - part 2 This actually simplies things as we just figure out how much space we used at the end and adjust klimit then. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit c4e3ea2553308ba65fea582dc9a42221ef8b49e5 Author: Stephen Rothwell Date: Fri May 19 17:04:48 2006 +1000 [PATCH] powerpc: make iSeries flattened device tree dynamic First we capture all the strings from dt.c statically by noting that gcc puts them in a special section of their own. Idea from Michael Ellerman. Then we move the flattened device tree to klimit. Still to come, making the values blob grow as needed. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit c81014f603db26e1ed818decebd3b594606e20a6 Author: Stephen Rothwell Date: Fri May 19 17:00:04 2006 +1000 [PATCH] powerpc: split device tree stuff out of iseries/setup.c Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 9ceb19093b5e5f037c6b47df0607dd567283287d Author: Stephen Rothwell Date: Fri May 19 16:58:13 2006 +1000 [PATCH] powerpc: give iSeries device tree nodes better names Use the PCI class code to choose a name for the PCI device nodes and to guess a device_type. Failing that, base the name on the vendor and device ids as specified in the spec. Mark just about everything __init{data}. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 29629b2972467f6cc00427a89008c09d010074c8 Author: Stephen Rothwell Date: Fri May 19 16:55:53 2006 +1000 [PATCH] powerpc: make iSeries flat device tree stuff static Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 095eed4f8d0be13a7934031434b6e9ceddb87ff6 Author: Stephen Rothwell Date: Fri May 19 16:54:42 2006 +1000 [PATCH] powerpc: clean up iSeries PCI probe Only scan the host bridges and then use the existing pci_devs_phb_init() routine. Also fix typo in setup of reg property. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit efbd386967aaa7fcf7ffbb13e4975df1cdf04cb8 Author: Stephen Rothwell Date: Fri May 19 16:53:11 2006 +1000 [PATCH] powerpc: iSeries PCI devices can now have a devpsec attribute Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 403fac4f83bd8e089a192c542511fbeb2729a6c5 Author: Stephen Rothwell Date: Fri May 19 16:51:57 2006 +1000 [PATCH] powerpc: remove LogicalSlot from pci_dn As we now store enough information in the device_node. Also the Flags field was not used either, do remove that. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit b02527931672749d404b5f640b7e086afc37f4e0 Author: Stephen Rothwell Date: Fri May 19 16:50:39 2006 +1000 [PATCH] powerpc: remove Irq from pci_dn As we now store enough information in the device_node to allocate the irq number in pcibios_final_fixup. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 96ff6afaf1c2fdd118139095dea66c0910379780 Author: Stephen Rothwell Date: Fri May 19 16:48:47 2006 +1000 [PATCH] powerpc: remove iSeries_Global_Device_List We can now scan the list of device nodes instead. This also allows us to remove the Device_list member of struct pci_dn. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 0d177df15d12926dc2ef7c814f317f02de52ce17 Author: Stephen Rothwell Date: Fri May 19 16:46:28 2006 +1000 [PATCH] powerpc: move iSeries PCI devices to the device tree Move the probing of PCI devices to setup.c and put them all into the flattened device tree. The later probing is now done by traversing the device tree. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 66b3851a6947482987b4c05aa781a33696287648 Author: Stephen Rothwell Date: Fri May 19 16:43:58 2006 +1000 [PATCH] powerpc: reintroduce HvCallPci_configLoad32 This function was removed during iSeries cleanup but will prove useful in the following patches. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit b58b7f98670ab6dd7774b67ff1655a787321209f Author: Stephen Rothwell Date: Fri May 19 16:42:49 2006 +1000 [PATCH] powerpc: tidy up iseries/pci.c Remove some unused counters. No need to allocate iomm_table and iobar_table, which means that iomm_table_initialize is not longer needed. Use kzalloc where sensible. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1 Author: Mark Lord Date: Mon May 22 19:02:03 2006 -0400 [PATCH] sata_mv: endian annotations Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik commit a6b2c5d4754dc539a560fdf0d3fb78a14174394a Author: Alan Cox Date: Mon May 22 16:59:59 2006 +0100 [PATCH] PATCH: libata. Add ->data_xfer method We need to pass the device in order to do per device checks such as 32bit I/O enables. With the changes to include dev->ap we now don't have to add parameters however just clean them up. Also add data_xfer methods to the existing drivers except ata_piix (which is in the other block of patches). If you reject the piix one just add a data_xfer to it... Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit 8190bdb9291758f3b8c436ec1154c9923ddb57ea Author: Jeff Garzik Date: Wed May 24 01:53:39 2006 -0400 [libata] libata-scsi, sata_mv: trim trailing whitespace commit f79d409fae879d135d1aaca6d83451f2787aec07 Author: Alan Cox Date: Mon May 22 16:55:11 2006 +0100 [PATCH] libata - fix bracketing and DMA oops The upstream tree has the ATA_DFLAG_PIO bug fixed but does not have the pass throuugh bug fix Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit b6079ca409bf88c248992e96510dd6f610f7ed89 Author: Alan Cox Date: Mon May 22 16:52:06 2006 +0100 [PATCH] libata: PIO 0 Ensure the pio_mode is always setup. Don't do any setup on the controller b just ensure the mode reporting is valid to avoid tons of special cases in PATA driver code when mode switching on the fly. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit 1f3461a72619fcd70a0fcb563306c91f753b4620 Author: Albert Lee Date: Tue May 23 18:12:30 2006 +0800 [PATCH] libata: minor fix for irq-pio merge Minor fix to put the ATA_FLAG_NO_ATAPI flag back. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit d3fb4e8dddebbf7d6c0b02842c619bfd4fa199f5 Author: Jeff Garzik Date: Wed May 24 01:43:25 2006 -0400 [libata sata_promise] Add PATA cable detection. Original patch from Phillip Jordan Cleanups and fixes by me. commit 4c5c81613b0eb0dba97a8f312a2f1162f39fd47b Author: Andrew Chew Date: Thu Apr 20 15:54:26 2006 -0700 [PATCH] sata_nv: Add MCP61 support Added MCP61 SATA support to sata_nv. Signed-off-by: Jeff Garzik commit d7fbeba60b4021dfaf5d315884fbf7672b4ae87b Author: Jeff Garzik Date: Wed May 24 01:31:14 2006 -0400 [netdrvr ibmlana, ibmveth] trim trailing whitespace commit 860f242eb5340d0b0cfe243cb86b2a98f92e8b91 Author: Santiago Leon Date: Tue Apr 25 11:19:59 2006 -0500 [PATCH] ibmveth change buffer pools dynamically This patch provides a sysfs interface to change some properties of the ibmveth buffer pools (size of the buffers, number of buffers per pool, and whether a pool is active). Ethernet drivers use ethtool to provide this type of functionality. However, the buffers in the ibmveth driver can have an arbitrary size (not only regular, mini, and jumbo which are the only sizes that ethtool can change), and also ibmveth can have an arbitrary number of buffer pools Under heavy load we have seen dropped packets which obviously kills TCP performance. We have created several fixes that mitigate this issue, but we definitely need a way of changing the number of buffers for an adapter dynamically. Also, changing the size of the buffers allows users to change the MTU to something big (bigger than a jumbo frame) greatly improving performance on partition to partition transfers. The patch creates directories pool1...pool4 in the device directory in sysfs, each with files: num, size, and active (which default to the values in the mainline version). Comments and suggestions are welcome... -- Santiago A. Leon Power Linux Development IBM Linux Technology Center Signed-off-by: Jeff Garzik commit 7b32a312895c00ff03178e49db8b651ee1e48178 Author: Adrian Bunk Date: Tue May 16 17:30:50 2006 +0200 [PATCH] drivers/net/s2io.c: make bus_speed[] static On Mon, May 15, 2006 at 12:56:37AM -0700, Andrew Morton wrote: >... > Changes since 2.6.17-rc3-mm1: >... > git-netdev-all.patch >... > git trees >... This patch makes the needlessly global bus_speed[] static. Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik commit 6ed14254cb6e269030ff09bed8673473b7be0283 Author: Jeff Garzik Date: Wed May 24 00:28:37 2006 -0400 [netdrvr pcnet_cs, myri] trim trailing whitespace commit cf393ebed0abb1186c34b21f3d1d939ac2b5568a Author: Marcin Juszkiewicz Date: Tue May 23 11:15:57 2006 +0200 [PATCH] pcnet_cs: Add TRENDnet TE-CF100 ethernet adapter ID Add TRENDnet TE-CF100 ethernet adapter to pcnet_cs list. product info: "Fast Ethernet", "CF Size PC Card", "1.0", "" manfid: 0x0149, 0xc1ab Signed-off-by: Marcin Juszkiewicz drivers/net/pcmcia/pcnet_cs.c | 2 ++ 1 file changed, 2 insertions(+) Signed-off-by: Jeff Garzik commit 0da34b6dfe55810ae60db57e08e2af8a808c0a55 Author: Brice Goglin Date: Tue May 23 06:10:15 2006 -0400 [PATCH] Add Myri-10G Ethernet driver Signed-off-by: Brice Goglin Signed-off-by: Andrew J. Gallatin drivers/net/Kconfig | 17 drivers/net/Makefile | 1 drivers/net/myri10ge/Makefile | 5 drivers/net/myri10ge/myri10ge.c | 2851 +++++++++++++++ drivers/net/myri10ge/myri10ge_mcp.h | 205 + drivers/net/myri10ge/myri10ge_mcp_gen_header.h | 58 include/linux/pci_ids.h | 1 7 files changed, 3138 insertions(+) Signed-off-by: Jeff Garzik commit 3a720d726a6aa0a7cd9190f694587adf7bafdf4f Author: Brice Goglin Date: Tue May 23 06:10:01 2006 -0400 [PATCH] Revive pci_find_ext_capability This patch revives pci_find_ext_capability (has been disabled a couple month ago since it was not used anywhere. See http://lkml.org/lkml/2006/1/20/247). It will now be used by the myri10ge driver. Signed-off-by: Brice Goglin Signed-off-by: Andrew J. Gallatin drivers/pci/pci.c | 3 +-- include/linux/pci.h | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) Signed-off-by: Jeff Garzik commit 2f785402f39b96a077b6e62bf26164bfb8e0c980 Author: David Woodhouse Date: Wed May 24 02:04:45 2006 +0100 [JFFS2] Reduce visibility of raw_node_ref to upper layers of JFFS2 code. As the first step towards eliminating the ref->next_phys member and saving memory by using an _array_ of struct jffs2_raw_node_ref per eraseblock, stop the write functions from allocating their own refs; have them just _reserve_ the appropriate number instead. Then jffs2_link_node_ref() can just fill them in. Use a linked list of pre-allocated refs in the superblock, for now. Once we switch to an array, it'll just be a case of extending that array. Signed-off-by: David Woodhouse commit d470a97c70a43ffafd6e728c913254b6d6fd1219 Author: Thomas Gleixner Date: Tue May 23 23:48:57 2006 +0200 [MTD] NAND LED support cleanup Move the define out of the middle of the code and add an appropriate comment. Signed-off-by: Thomas Gleixner commit cad74f2c380411ae7bee997f3ba18834cfe313a2 Author: Thomas Gleixner Date: Tue May 23 23:28:48 2006 +0200 [MTD] NAND remove write_byte/word function from nand_chip The previous change of the command / hardware control allows to remove the write_byte/word functions completely, as their only user were nand_command and nand_command_lp. Signed-off-by: Thomas Gleixner commit 7abd3ef9875eb2afcdcd4f450680298a2983a55e Author: Thomas Gleixner Date: Tue May 23 23:25:53 2006 +0200 [MTD] Refactor NAND hwcontrol to cmd_ctrl The hwcontrol function enforced a step by step state machine for any kind of hardware chip access. Let the hardware driver know which control bits are set and inform it about a change of the control lines. Let the hardware driver write out the command and address bytes directly. This gives a peformance advantage for address bus controlled chips and simplifies the quirks in the hardware drivers. Signed-off-by: Thomas Gleixner commit 440c052d6f717495806fe2c65f3f5677c92397c7 Author: Auke Kok Date: Tue May 23 13:36:19 2006 -0700 e1000: bump version to 7.0.38-k4 Signed-off-by: Auke Kok commit fdf35d3c49be0ad99e2fd5f5f27c6c0c336a3f11 Author: Auke Kok Date: Tue May 23 13:36:14 2006 -0700 e1000: remove changelog in driver This honours the request to remove the changelog in the driver code. Signed-off-by: Auke Kok commit a1943b5a796a11ee516f5c085453d653a87ee8fe Author: Auke Kok Date: Tue May 23 13:36:10 2006 -0700 e1000: Fix date string in Makefile I forgot to update the date string in the Makefile last time. Signed-off-by: Auke Kok commit 76c224bc9fdf108ae6e97553322122f53bdbe75c Author: Auke Kok Date: Tue May 23 13:36:06 2006 -0700 e1000: remove leading and trailing whitespace. Some leading and trailing whitespace made it into the driver code here. Signed-off-by: Auke Kok commit a42a507cd3af14a2696b7c020996e48c10bf7742 Author: Auke Kok Date: Tue May 23 13:36:01 2006 -0700 e1000: remove backslash r debug printfs This removes unwanted characters in the debug output that should have never been there. Signed-off-by: Auke Kok commit c653e6351e371b33b29871e5eedf610ffb3be037 Author: Auke Kok Date: Tue May 23 13:35:57 2006 -0700 e1000: add shutdown handler back to fix WOL Someone was waaay too aggressive and removed e1000's reboot notifier instead of porting it to the new way of the shutdown handler. This change broke wake on lan. Add the shutdown handler back in using the same method as e100 uses. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok commit 3821720d51b5f304d2c33021a82c8da70f6d6ac9 Author: Thomas Gleixner Date: Tue May 23 22:33:52 2006 +0200 [MTD] Export nand_write_raw The previous _ecc removal / cleanup broke (i)nftl module usage. Export the missing symbol. Signed-off-by: Thomas Gleixner commit 85b85fee0cbb9d22b619a4981f046ca49adbc5cd Author: Thomas Gleixner Date: Tue May 23 22:03:39 2006 +0200 [MTD] Mark NAND drivers TOTO and PPChameleon broken Both drivers can not be fixed and compiled due to missing header files. Signed-off-by: Thomas Gleixner commit 777e1d4a0f3387933f668e7adc81384827975189 Author: Auke Kok Date: Tue May 23 10:35:08 2006 -0700 ixgb: increment version to 1.0.104-k2 Increment the driver version to 1.0.104-k2 Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 9b8118df486ffec2f42d43dadaceebd0561dd564 Author: Auke Kok Date: Tue May 23 10:35:04 2006 -0700 ixgb: add tx timeout counter This adds a TX timeout counter to the ethtool stats, a tx timeout debug message, and sets the timer to 5 seconds. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit ec9c3f5d3b8c4dd7340800f02eed87bdf0233e3b Author: Auke Kok Date: Tue May 23 10:34:59 2006 -0700 ixgb: use DPRINTK and msglvl, and ethtool to control it Use DPRINTK and msglvl, and ethtool to control it. Add proper names to netdev structs and mappings. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit c85fd6f0dedcec411438768bb5ebd133b1ae3347 Author: Auke Kok Date: Tue May 23 10:30:02 2006 -0700 ixgb: remove hardcoded number This adds a define for an awkward and uncommented value. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 940829e2f9d89d3caddc852bca9018cf503ea719 Author: Auke Kok Date: Tue May 23 10:29:58 2006 -0700 ixgb: add copper 10gig driver id Add support for Copper 10GbE device ID 109E Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit f017f14b3f18b38f2388e7d6e83a7f6997ee9dd6 Author: Auke Kok Date: Tue May 23 10:29:53 2006 -0700 ixgb: add NETIF_F_LLTX analogous to e1000 add NETIF_F_LLTX code like e1000 has Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 953784d66d8f621a8684d007e526ca26b12d54a1 Author: Auke Kok Date: Tue May 23 10:29:50 2006 -0700 ixgb: fix flow control Make default flow control only have *sending* of flow control packets enabled, and fix to disable / enable flow control correctly. Set flow control defaults to disable receiving flow control from the link partner, to fix the transmit fifo overlow errata Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 4de17c8c7295d32d4e112e214aa90d8f7006972f Author: Auke Kok Date: Tue May 23 10:29:46 2006 -0700 ixgb: remove duplicate code setting duplex and speed Removed duplicate code. Create ixgb_set_speed_duplex function to contain duplicate code. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 96f9c2e277768099479fbed7c3b69c294b1fadef Author: Auke Kok Date: Tue May 23 10:29:41 2006 -0700 ixgb: fix rare early tso completion Fix rare early completion when using TSO. This essentially is the e1000 fix, with code that was mostly already written. Another skb frag was also needed. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 9223a456da8ed357bf7e0b128c853e2c8bd54614 Author: Thomas Gleixner Date: Tue May 23 17:21:03 2006 +0200 [MTD] Remove read/write _ecc variants MTD clients are agnostic of FLASH which needs ECC suppport. Remove the functions and fixup the callers. Signed-off-by: Thomas Gleixner commit 2528e8cdf376d7da24647c442ec1e88c360d76ca Author: Thomas Gleixner Date: Tue May 23 16:10:00 2006 +0200 [MTD] Remove readv/readv_ecc These functions were never implemented and added only bloat to partition and concat code. Signed-off-by: Thomas Gleixner commit 9d8522df37f91621a70c5c0dbbf5bf2220b16798 Author: Thomas Gleixner Date: Tue May 23 16:06:03 2006 +0200 [MTD] Remove nand writev support NAND writev(_ecc) support is not longer necessary. Remove it. Signed-off-by: Thomas Gleixner commit 0cddd6c258b2ed3798d12619c28ed0d2b5a669bc Author: Thomas Gleixner Date: Tue May 23 15:59:58 2006 +0200 [MTD] ECC rework broke diskonchip Fix the diskonchip ecc setup. Signed-off-by: Thomas Gleixner commit 9a57d470fd4a77b9732fee97bed29c565c730af0 Author: Thomas Gleixner Date: Tue May 23 15:58:23 2006 +0200 [MTD] NAND ECC hwctl function has no return value Fix the broken prototype Signed-off-by: Thomas Gleixner commit 6dfc6d250d0b7ebaa6423c44dcd09fcfe68deabd Author: Thomas Gleixner Date: Tue May 23 12:00:46 2006 +0200 [MTD] NAND modularize ECC First step of modularizing ECC support. - Move ECC related functionality into a seperate embedded data structure - Get rid of the hardware dependend constants to simplify new ECC models Signed-off-by: Thomas Gleixner commit 7aa65bfd6793a56cc3bbce8436abbfea3a7bdd1f Author: Thomas Gleixner Date: Tue May 23 11:54:38 2006 +0200 [MTD] NAND cleanup nand_scan Seperate functionality out of nand_scan so the code is more readable. No functional change. First step of simplifying the nand driver. Signed-off-by: Thomas Gleixner commit 58dd8f2bfdcad1b219a4a92a2aadd8ea8c819f79 Author: Thomas Gleixner Date: Tue May 23 11:52:35 2006 +0200 [MTD] NAND consolidate data types The NAND driver used a mix of unsigned char, u_char amd uint8_t data types. Consolidate to uint8_t usage Signed-off-by: Thomas Gleixner commit 2c0a2bed9276ebbec5794edc07f66e21e9a1735c Author: Thomas Gleixner Date: Tue May 23 11:50:56 2006 +0200 [MTD] NAND whitespace and formatting cleanup Signed-off-by: Thomas Gleixner commit dcb0932884b801290efd80fbc37630297b98181f Author: Thomas Gleixner Date: Tue May 23 11:49:14 2006 +0200 [JFFS2] Simplify writebuffer handling The writev based write buffer implementation was far to complex as in most use cases the write buffer had to be handled anyway. Simplify the write buffer handling and use mtd->write instead. From extensive testing no performance impact has been noted. Signed-off-by: Thomas Gleixner commit ce4c61f184864991881ec789f7524f4b332eaafc Author: Thomas Gleixner Date: Tue May 23 11:43:28 2006 +0200 [MTD] Add support for NDFC NAND controller NDFC NAND Flash controller is embedded in PPC EP44x SoCs. Add platform driver based support. Signed-off-by: Thomas Gleixner commit 41796c2ea9b74cdf3bc2c368193d15b8ae8950ca Author: Thomas Gleixner Date: Tue May 23 11:38:59 2006 +0200 [MTD] Add platform support for NAND Add the data structures necessary to provide platform device support for NAND Signed-off-by: Thomas Gleixner commit a36ed2995c56d4f858ecb524a78837473e7115ae Author: Thomas Gleixner Date: Tue May 23 11:37:03 2006 +0200 [MTD] Simplify NAND locking Replace the chip lock by a the controller lock. For simple drivers a dummy controller structure is created by the scan code. This simplifies the locking algorithm in nand_get/release_chip(). Signed-off-by: Thomas Gleixner commit 819d6a32c397534c819d3c72a3947b7e7e4bec4b Author: Thomas Gleixner Date: Tue May 23 11:32:45 2006 +0200 [MTD] Improve software ECC calculation Unrolling the loops produces denser and much faster code. Add a config switch which allows to select the byte order of the resulting ecc code. The current Linux implementation has a byte swap versus the SmartMedia specification Signed-off-by: Thomas Gleixner commit 9fe4854cd1f60273f9a3ece053f4789605f58a5e Author: David Woodhouse Date: Tue May 23 00:38:06 2006 +0100 [JFFS2] Remove flash offset argument from various functions. We don't need the upper layers to deal with the physical offset. It's _always_ c->nextblock->offset + c->sector_size - c->nextblock->free_size so we might as well just let the actual write functions deal with that. Signed-off-by: David Woodhouse commit 5fa433942ba4e399f7e28764c9db4ade89e91d40 Author: Joern Engel Date: Mon May 22 23:18:29 2006 +0200 [MTD] Introduce MTD_BIT_WRITEABLE o Add a flag MTD_BIT_WRITEABLE for devices that allow single bits to be cleared. o Replace MTD_PROGRAM_REGIONS with a cleared MTD_BIT_WRITEABLE flag for STMicro and Intel Sibley flashes with internal ECC. Those flashes disallow clearing of single bits, unlike regular NOR flashes, so the new flag models their behaviour better. o Remove MTD_ECC. After the STMicro/Sibley merge, this flag is only set and never checked. Signed-off-by: Joern Engel commit c8b229de2b05c2b3e8d282ce260935a88ac030ca Author: Joern Engel Date: Mon May 22 23:18:12 2006 +0200 [MTD] Merge STMicro NOR_ECC code with Intel Sibley code In 2002, STMicro started producing NOR flashes with internal ECC protection for small blocks (8 or 16 bytes). Support for those flashes was added by me. In 2005, Intel Sibley flashes copied this strategy and Nico added support for those. Merge the code for both. Signed-off-by: Joern Engel commit 28318776a80bc3261f9af91ef79e6e38bb9f5bec Author: Joern Engel Date: Mon May 22 23:18:05 2006 +0200 [MTD] Introduce writesize At least two flashes exists that have the concept of a minimum write unit, similar to NAND pages, but no other NAND characteristics. Therefore, rename the minimum write unit to "writesize" for all flashes, including NAND. Signed-off-by: Joern Engel commit 8ca9ed5db3aea8d27989c239e8a2f79b839f1e99 Author: Joern Engel Date: Mon May 22 23:17:23 2006 +0200 [MTD] Use single flag to mark writeable devices. Two flags exist to decide whether a device is writeable or not. None of those two flags is checked for independently, so they are clearly redundant, if not an invitation to bugs. This patch removed both of them, replacing them with a single new flag. Signed-off-by: Joern Engel commit df8ccb9bf1ca360581a94c2245efb9fa613fbb29 Author: Marcin Juszkiewicz Date: Mon May 22 10:56:55 2006 +0200 [PATCH] hostap: new pcmcia IDs Add two Prism cards to hostap_cs driver. product info: "Pretec", "CompactWLAN Card 802.11b", "2.5" manfid: 0x0156, 0x0002 product info: "U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", "" manfid: 0x0156, 0x0002 Signed-off-by: Marcin Juszkiewicz Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 82464e63a0653a4d8e5c684fcb41b163e6357c6d Author: Florin Malita Date: Sun May 21 14:04:44 2006 -0700 [PATCH] orinoco: possible null pointer dereference in orinoco_rx_monitor() If the skb allocation fails, the current error path calls dev_kfree_skb_irq() with a NULL argument. Also, 'err' is not being used. Coverity CID: 275. Signed-off-by: Florin Malita Signed-off-by: Andrew Morton Signed-off-by: John W. Linville commit 987d47b71a85bd83dc40c870abee3b64f2002163 Author: David Woodhouse Date: Mon May 22 16:32:05 2006 +0100 [JFFS2] Put list of nodes in common part of ic/x_ref/x_datum structure We'll be using a proper list of nodes in the jffs2_xattr_datum and jffs2_xattr_ref structures, because the existing code to overwrite them is just broken. Put it in the common part at the front of the structure which is shared with the jffs2_inode_cache, so that the jffs2_link_node_ref() function can do the right thing. Signed-off-by: David Woodhouse commit 0eac940b8a087576c66ecf8e0f294f2ceb3b607b Author: David Woodhouse Date: Mon May 22 16:29:23 2006 +0100 [JFFS2] Add some preemptive BUG checks for XATTR code In a couple of places, we assume that what's at the end of the ->next_in_ino list is a struct jffs2_inode_cache. Let's check for that, since we expect it to change soon. Signed-off-by: David Woodhouse commit fcb7578719529898aef9edce8e409e457a1c2d15 Author: David Woodhouse Date: Mon May 22 15:23:10 2006 +0100 [JFFS2] Extend jffs2_link_node_ref() to link into per-inode list too. Let's avoid the potential for forgetting to set ref->next_in_ino, by doing it within jffs2_link_node_ref() instead. This highlights the ugliness of what we're currently doing with xattr_datum and xattr_ref structures -- we should find a nicer way of dealing with that. Signed-off-by: David Woodhouse commit a1b563d652b54647ffacb2d6edf7859d3e97a723 Author: David Woodhouse Date: Mon May 22 13:55:46 2006 +0100 [JFFS2] Initialise ref->next_in_ino when marking dirty space in wbuf flush Signed-off-by: David Woodhouse commit 3b79673cfae93d0ed63eceb058bb26aba602a278 Author: David Woodhouse Date: Mon May 22 12:15:47 2006 +0100 [JFFS2] Fix accounting error in jffs2_link_node_ref() When filing REF_OBSOLETE nodes, we'd add their size to the global 'dirty_size' count, but then to the eraseblock's 'used_size' count. That's not clever. Signed-off-by: David Woodhouse commit 06c6764b5830798c39617b24497cade90451592f Author: David Woodhouse Date: Mon May 22 11:27:14 2006 +0100 [JFFS2] Fix dummy jffs2_sum_scan_sumnode() macro for !SUMMARY case. I added an argument to the real function... Signed-off-by: David Woodhouse commit 2c23d62abb820e19c54012520f08a198c2233a85 Author: David Woodhouse Date: Sun May 21 22:51:13 2006 +0100 Move inclusion of out of user scope in asm-x86_64/mtrr.h Signed-off-by: David Woodhouse commit 615191bb1dfc6980e7c7a85225444d860d74b343 Author: David Woodhouse Date: Sun May 21 19:03:21 2006 +0100 [MTD] Account for MODULE_SYMBOL_PREFIX when requesting NOR chip driver Signed-off-by: David Woodhouse commit ecde26313076e5055dcd54d6537632275346203f Author: David Woodhouse Date: Sun May 21 18:38:51 2006 +0100 [MTD] Use symbol_request() in old DiskOnChip probe code to find actual driver The previous code wouldn't work correctly on architectures which have a non-empty MODULE_SYMBOL_PREFIX, and this version is neater if slightly less optimal in the built-in case. Signed-off-by: David Woodhouse commit 3d12c0c75db0cd85beb11c4e2d86a49cabe3cfff Author: Jonathan McDowell Date: Sun May 21 18:11:55 2006 +0100 [MTD] Add Amstrad Delta NAND support The patch below adds support for the NAND device on the Amstrad Delta. This is a 32MiB 8bit Toshiba device, with the data bus connected to the OMAP MPUIO pins and ALE, CLE, NCE, NRE, NWE and NWP all connected to the Delta's latch2 16bit latch. Signed-Off-By: Jonathan McDowell Signed-off-by: David Woodhouse commit ca89a517fa577e6f26621463d3aa4f3c3d530b1e Author: David Woodhouse Date: Sun May 21 13:29:11 2006 +0100 [JFFS2] Finally eliminate __totlen field from struct jffs2_raw_node_ref Well, almost. We'll actually keep a 'TEST_TOTLEN' macro set for now, and keep doing some paranoia checks to make sure it's all working correctly. But if TEST_TOTLEN is unset, the size of struct jffs2_raw_node_ref drops from 16 bytes to 12 on 32-bit machines. That's a saving of about half a megabyte of memory on the OLPC prototype board, with 125K or so nodes in its 512MiB of flash. Signed-off-by: David Woodhouse commit 010b06d6d07d9fa5ea6070aa72bb3e0de1761ab7 Author: David Woodhouse Date: Sun May 21 13:15:59 2006 +0100 [JFFS2] Locking issues in summary write code. We can't use jffs2_scan_dirty_space() because it doesn't do any locking; it's only for use at scan time -- hence the 'scan' in the name. Also, don't allocate refs while we have c->erase_completion_lock held. Signed-off-by: David Woodhouse commit 9167e0f811cbe28564c44a99c2f07b0ce5b368cf Author: David Woodhouse Date: Sun May 21 13:13:45 2006 +0100 [JFFS2] Remove stray kfree of summary info in XATTR code. We don't allocate this locally any more -- it's given to us and owner by our caller. Also improve the debug messages a little. Signed-off-by: David Woodhouse commit 0bcc099d6d1a7b9fa2adf7c19812e4e816915e10 Author: David Woodhouse Date: Sun May 21 13:00:54 2006 +0100 [JFFS2] File node reference for wasted space when flushing wbuf Next step in ongoing campaign to file a struct jffs2_raw_node_ref for every piece of dirty space in the system, so that __totlen can be killed off.... Signed-off-by: David Woodhouse commit b64335f2b740d6f5dbf5d3b04af30d407bf599f5 Author: David Woodhouse Date: Sun May 21 04:36:45 2006 +0100 [JFFS2] Add length argument to jffs2_add_physical_node_ref() If __totlen is going away, we need to pass the length in separately. Also stop callers from needlessly setting ref->next_phys to NULL, since that's done for them... and since that'll also be going away soon. Signed-off-by: David Woodhouse commit 49f11d40751b974f3b829f208eefa6f97a10cac8 Author: David Woodhouse Date: Sun May 21 04:00:01 2006 +0100 [JFFS2] Mark gaps in summary list as dirty space Make sure we allocate a ref for any dirty space which exists between nodes which we find in an eraseblock summary. Signed-off-by: David Woodhouse commit 25090a6b23906552cf3d204aa421f811327e1b15 Author: David Woodhouse Date: Sun May 21 03:57:56 2006 +0100 [JFFS2] Discard remaining free space when filing a dirty block in scan. The incoming ref_totlen() calculation is going to rely on the existence of nodes which cover all dirty space. We can't just tweak the accounting data any more; we have to call jffs2_scan_dirty_space() to do it. Signed-off-by: David Woodhouse commit 68270995f29f1a82b3eaab01df63ea7e721e2fa6 Author: David Woodhouse Date: Sun May 21 03:46:05 2006 +0100 [JFFS2] Introduce jffs2_scan_dirty_space() function. To eliminate the __totlen field from struct jffs2_raw_node_ref, we need to allocate nodes for dirty space instead of just tweaking the accounting data. Introduce jffs2_scan_dirty_space() in preparation for that. Signed-off-by: David Woodhouse commit 7807ef7ba2a41c05f6197381f572dd38baa6c1ce Author: David Woodhouse Date: Sun May 21 03:45:27 2006 +0100 [JFFS2] Fix summary handling of unknown but compatible nodes. For RWCOMPAT and ROCOMPAT nodes, we should still allow the mount to succeed. Just abandon the summary and fall through to the full scan. Signed-off-by: David Woodhouse commit 3560160aa26ebced1944aaa2e7e436d2a1b1bf70 Author: David Woodhouse Date: Sun May 21 01:28:05 2006 +0100 [JFFS2] Fix memory leak in scan code; improve comments. If we had to allocate extra space for the summary node, we weren't correctly freeing it when jffs2_sum_scan_sumnode() returned nonzero -- which is both the success and the failure case. Only when it returned zero, which means fall through to the full scan, were we correctly freeing the buffer. Document the meaning of those return codes while we're at it. Signed-off-by: David Woodhouse commit 6171586a7ae5198988774e8480631e8d15f65dfe Author: David Woodhouse Date: Sun May 21 00:02:06 2006 +0100 [JFFS2] Correct handling of JFFS2_FEATURE_RWCOMPAT_COPY nodes. We should preserve these when we come to garbage collect them, not let them get erased. Use jffs2_garbage_collect_pristine() for this, and make sure the summary code copes -- just refrain from writing a summary for any block which contains a node we don't understand. Signed-off-by: David Woodhouse commit fb9fbbcc9389edabb172ac1b6419c01e32046787 Author: David Woodhouse Date: Sat May 20 20:08:42 2006 +0100 [JFFS2] Correct accounting of erroneous cleanmarkers and failed summaries. It should all be counted as dirty space, not wasted and _definitely_ not unchecked. Signed-off-by: David Woodhouse commit f1f9671bd8f7d2ac6a918bad806ab5bdc0daaf4e Author: David Woodhouse Date: Sat May 20 19:45:26 2006 +0100 [JFFS2] Introduce jffs2_link_node_ref() function to reduce code duplication The same sequence of code was repeated in many places, to add a new struct jffs2_raw_node_ref to an eraseblock and adjust the space accounting accordingly. Move it out-of-line. Signed-off-by: David Woodhouse commit 1417fc44ee923418df3adadeb4846c891bba1ba5 Author: David Woodhouse Date: Sat May 20 16:20:19 2006 +0100 [JFFS2] Reduce calls to ref_totlen() in jffs2_mark_node_obsolete() We were calling ref_totlen() 18 times. Even before that becomes a real function rather than just a dereference, apparently some compilers still suck anyway. It'll _certainly_ suck after ref_totlen() becomes more complicated, so calculate it once and don't rely on CSE. Signed-off-by: David Woodhouse commit 9641b784ff82cf0a48a6c70ef9867f5fd728de67 Author: David Woodhouse Date: Sat May 20 16:13:34 2006 +0100 [JFFS2] Optimise reading of eraseblock summary nodes This improves the time to mount 512MiB of NAND flash on my OLPC prototype by about 4%. We used to read the last page of the eraseblock twice -- once to find the offset of the summary node, and again to actually _read_ the summary node. Now we read the last page only once, and read more only if we need to. We also don't allocate a new buffer just for the summary code -- we use the buffer which was already allocated for the scan. Better still, if the 'buffer' for the scan is actually just a pointer directly into NOR flash, we use that too, avoiding the memcpy() which we used to do. Signed-off-by: David Woodhouse commit 979dca3826841e5dc9170c28f20bd75ece266a9a Author: Randy Dunlap Date: Fri May 19 11:55:58 2006 -0700 [SCSI] imm: no need for unchecked_isa_dma Relax the lowmem bounce buffer requirement for imm so that any low memory page will do -- they don't need to be below the ISA 16 MB limit, just need to be mapped in low memory. Signed-off-by: Randy Dunlap Signed-off-by: James Bottomley commit 818bf493525d2a0ce3ddaefb2b78db1635596666 Author: Andrew Vasquez Date: Wed May 17 15:10:01 2006 -0700 [SCSI] qla2xxx: Update version number to 8.01.05-k2. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 21333b481159a78b5379b8ddb400efafd5857d55 Author: Andrew Vasquez Date: Wed May 17 15:09:56 2006 -0700 [SCSI] qla2xxx: Correct issue where driver improperly issued SNS commands in N2N topologies. Semantic changes in ISP24xx firmware behaviour inadvertently caused the driver to believe an F-port topology was present in an N_port-to-N_port configuration. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit d4e3e04d789ba23027c66e176b10ac7477906948 Author: Andrew Vasquez Date: Wed May 17 15:09:50 2006 -0700 [SCSI] qla2xxx: Consolidate firmware-dump handling across ISPs. Simplify and centralise buffer allocation/deallocation, as there's no point in having two memory request methods. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit cb63067a772c0149184309a1f232d62c81a93673 Author: Andrew Vasquez Date: Wed May 17 15:09:45 2006 -0700 [SCSI] qla2xxx: Consolidate "qla2xxx" string usage to a #define. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 47f5e069e4d03dda36e3a13f3e20147efd710340 Author: Andrew Vasquez Date: Wed May 17 15:09:39 2006 -0700 [SCSI] qla2xxx: Use PCI_DEVICE() for pci_device_id definition. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 441d1072040823feb4950a21094860bfddd310c0 Author: Andrew Vasquez Date: Wed May 17 15:09:34 2006 -0700 [SCSI] qla2xxx: Remove obsolete firmware-loader-module support. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 4971cd221ad3f1266b87aa0e996d082d91bac2a6 Author: Andrew Vasquez Date: Wed May 17 15:09:27 2006 -0700 [SCSI] qla2xxx: Remove unused port-type RSCN handling code. Expandind on the previous commit: commit 79f89a4296ff22f09baf538d4ff2a6d0c3097a73 Author: andrew.vasquez@qlogic.com Date: Fri Jan 13 17:05:58 2006 -0800 [SCSI] qla2xxx: Disable port-type RSCN handling via driver state-machine. and given: - the process-context requirements of the FC transport rport-APIs. - lack of port-type RSCN processing logic for ISP24xx and newer chips. it's time now to remove the state-machine logic from mainline. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 75bc4190701d3c6bdffdc21c8a9e17751de9f77a Author: Andrew Vasquez Date: Wed May 17 15:09:22 2006 -0700 [SCSI] qla2xxx: Drop unused driver cruft. - structure definitions. - structure members. - #define's. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 5341e868fb2e98090a68860a35bf4c11d7f8e5da Author: Andrew Vasquez Date: Wed May 17 15:09:16 2006 -0700 [SCSI] qla2xxx: Add support for alternate WWN NVRAM setting. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit fd0e7e4dd507cd21d714d34a1cc1a620d01e9772 Author: Andrew Vasquez Date: Wed May 17 15:09:11 2006 -0700 [SCSI] qla2xxx: Correct endianess comparisons during ISP24xx NVRAM configuration. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit ffb39f0324b56bacaabac26133143cf861d0e9f9 Author: Andrew Vasquez Date: Wed May 17 15:09:06 2006 -0700 [SCSI] qla2xxx: ABBA lock ordering fix. In qla2x00_reset_chip the driver first takes the hardware lock, and then later on takes the mbx lock. In the mailbox_command code.. it goes the other way around. Discovered with the lock validator. Cc: Ingo Molnar Cc: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit d1c61909c05ead100f855e640fba53925d0665ac Author: Andrew Vasquez Date: Wed May 17 15:09:00 2006 -0700 [SCSI] qla2xxx: Update ISP24xx firwmare loading heuristics. If firmware image is unavailable via request_firwmare(), then attempt to load the image (likely out-of-date) stored in flash memory. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit ed17c71b5d11327efd40666fd621486f964fae4f Author: Ravi Anand Date: Wed May 17 15:08:55 2006 -0700 [SCSI] qla2xxx: Use FW calculated residual count for underrun handling. With ISP24XX and ISP54XX parts. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 45aeaf1e8e4552ef82d3ff7a06e526e6d635f767 Author: Ravi Anand Date: Wed May 17 15:08:49 2006 -0700 [SCSI] qla2xxx: Add support for new flash part. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit 57680080baf3a8e289fad7f9e3c43ed58309e1eb Author: Ravi Anand Date: Wed May 17 15:08:44 2006 -0700 [SCSI] qla2xxx: Don't wait for loop transition to complete if LOOP_DEAD state is attained. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley commit e0ecae8da26d94dd878ff1d939c5aa4224df18a4 Author: Mike Christie Date: Thu May 18 20:31:43 2006 -0500 [SCSI] iscsi: update version update version Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 656cffc95f0cb8211aa75eaca249e6ff4f59ec83 Author: Mike Christie Date: Thu May 18 20:31:42 2006 -0500 [SCSI] iscsi: fix command requeues during iscsi recovery Do not flush queues then block session. This will cause commands to needlessly swing around on us and remove goofy recovery_failed field and replace with state value. And do not start recovery from within the host reset function. This causeis too many problems becuase open-iscsi was desinged to call out to userspace then have userpscae decide if we should go into recovery or kill the session. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 790f39a2d5f03623b027f340b945f135d006ceba Author: Mike Christie Date: Thu May 18 20:31:39 2006 -0500 [SCSI] iscsi: support mutiple daemons Patch from david.somayajulu@qlogic.com and cleaned up by Tomo. qla4xxx is going to have a different daemon so this patch just routes the events to the right daemon. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit ffbfe92533810bf1bb76fd275400825ef8898ed9 Author: Mike Christie Date: Thu May 18 20:31:36 2006 -0500 [SCSI] iscsi: kill dtask mempools Discovered by steven@hayter.me.uk and patch by michaelc@cs.wisc.edu The dtask mempool is reserving 261120 items per session! Since we are now sending headers with sendmsg there is no reason for the mempool and that was causing us to us carzy amounts of mem. We can preallicate a header in the r2t and task struct and reuse them Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit d36ab6f3212053b260214bc915687765e2fd1178 Author: Mike Christie Date: Thu May 18 20:31:34 2006 -0500 [SCSI] iscsi: only preallocate login buffer We only use the mtask data buffer for login tasks so we do not need to preallocate a buffer for every mtask. This saves 8 * 31 KB. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 6e458cc943dd494ac68b570418f187883e555362 Author: Mike Christie Date: Thu May 18 20:31:31 2006 -0500 [SCSI] iscsi: dont use sendpage for iscsi headers From Zhen and ported by Mike: Don't use sendpage for the headers. sendpage for the pdu headers does not seem to have a performance impact, makes life harder for mutiple data pdus to be in flight and still trips up some network cards when it is from slab mem. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 07fb75a50600c0c480b40c6d11dbc993f21bc2bc Author: Jesper Juhl Date: Sun May 14 00:39:38 2006 +0200 [SCSI] fix (unlikely) memory leak in DAC960 driver The Coverity checker found a memory leak (bug nr. 1245) in drivers/block/DAC960.c::DAC960_V2_ProcessCompletedCommand() The leak is pretty unlikely since it requires that the first of two successive kmalloc() calls fail while the second one succeeds. But it can still happen even if it's unlikely. If the first call that allocates 'PhysicalDeviceInfo' fails but the one that allocates 'InquiryUnitSerialNumber' succeeds, then we will leak the memory allocated to 'InquiryUnitSerialNumber' when the variable goes out of scope. A simple fix for this is to change the existing code that frees 'PhysicalDeviceInfo' if that one was allocated but 'InquiryUnitSerialNumber' was not, into a check for either pointer being NULL and if so just free both. This is safe since kfree() can deal with being passed a NULL pointer and it avoids the leak. While I was there I also removed the casts of the kmalloc() return value since it's pointless. I also updated the driver version since this patch changes the workings of the code (however slightly). This issue could probably be fixed a lot more elegantly, but the code is a big mess IMHO and I just took the least intrusive route to a fix that I could find instead of starting on a cleanup as well (that can come later). Please consider for inclusion. Signed-off-by: Jesper Juhl Signed-off-by: James Bottomley commit 5b9851b5511833a96fea2196971b5709ef019136 Author: Mark Haverkamp Date: Wed May 10 09:13:37 2006 -0700 [SCSI] aacraid: remove unneeded list Received From Mark Salyzyn The queue tracking is just not being used, not even for debugging. Information about outstanding commands can be acquired from the scsi structures. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley commit df3b7668715f9acfe6ff37dd886f68e46ccd677e Author: Mark Haverkamp Date: Wed May 10 09:13:11 2006 -0700 [SCSI] aacraid: sa race condition fix Received From Mark Salyzyn A race condition existed that could result in a lost completion of a command to the ppc based cards. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley commit 404d9a900b5bc83a3780ec337ca6fdcb04b766c0 Author: Mark Haverkamp Date: Wed May 10 09:12:48 2006 -0700 [SCSI] aacraid: adjustable timeouts Received From Mark Salyzyn Add the ability to adjust for unusual corner case failures. Both of these additional module parameters deal with embedded, non-intel or complicated system scenarios. Aif_timeout can be increased past the default 2 minute timeout to drop application registrations when a system has an unusually high event load resulting from continuing management requests, or simultaneous builds, or sluggish user space as a result of system load. Startup_timeout can be increased past the default 3 minute timeout to drop an adapter initialization for systems that have a very large number of targets, or slow to spin-up targets, or a complicated set of array configurations that extend the time for the firmware to declare that it is operational. This timeout would only have an affect on non-intel based systems, as the (more patient) BIOS would generally be where the startup delay would be dealt with. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley commit 3c1e0cca9469bd19590ade25f6d9f94da2710d5b Author: Mark Haverkamp Date: Wed May 10 09:12:05 2006 -0700 [SCSI] aacraid: optimize sg alloc Received From Mark Salyzyn Slight space and speed efficiency improvement. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley commit edb527ce35b0c86e72ed518af255f02e1cecb3b7 Author: Mark Haverkamp Date: Wed May 10 09:11:38 2006 -0700 [SCSI] aacraid: remove unneeded locking Received From Mark Salyzyn Since new commands to the card are quiesced, respect the changes in the SCSI error path which dropped locking around the hba reset handler and similarly drop the lock requirement in the driver's path. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley commit 6c8b44abc86a3e23dd1a22c0ee187f06bd7c7f5d Author: Andrew Morton Date: Sat May 20 10:17:21 2006 +0100 [MTD] Avoid 64-bit division in mtdconcat WARNING: "__moddi3" [drivers/mtd/mtdconcat.ko] undefined! Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse commit b74ba22f030eb7ab88f7d8954ad18ecc0ac5ce3c Author: Thomas Glanzmann Date: Fri May 12 10:00:41 2006 +0200 [PATCH] Add PCI ID for the Intel IDE Controller which is in the Intel Mac Minis shipped in first quarter 2006 Signed-off-by: Thomas Glanzmann Signed-off-by: Jeff Garzik commit f8bbfc247efb0e5fa69094614380768ce79afe17 Author: Tejun Heo Date: Fri May 19 21:07:05 2006 +0900 [PATCH] SCSI: make scsi_implement_eh() generic API for SCSI transports libata implemented a feature to schedule EH without an associated EH by manipulating shost->host_eh_scheduled in ata_scsi_schedule_eh() directly. Move this function to scsi_error.c and rename it to scsi_schedule_eh(). It is now an exported API for SCSI transports and exported via new header file drivers/scsi/scsi_transport_api.h This patch also de-export scsi_eh_wakeup() which was exported specifically for ata_scsi_schedule_eh(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit a20f33ffde8ba5fb27666aa1e228a45b7e3b8dcb Author: Tejun Heo Date: Tue May 16 12:58:24 2006 +0900 [PATCH] libata: enforce default EH actions LLDDs rely on libata that certain EH actions are automatically taken on some errors. If the port is frozen or one or more qc's have failed with HSM violation or timeout, softreset is enforced (LLDD can ask for storonger EH action at will). If any other error condition exists, libata EH always revalidates. This behavior existed in earlier revisions of new EH but lost during development process. This patch restores it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit eec4c3f317991dc85c786ffccd9c1a8620c41b18 Author: Albert Lee Date: Thu May 18 17:51:10 2006 +0800 [PATCH] libata: use qc->result_tf for temp taskfile storage Use qc->result_tf for temp taskfile storage. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 3655d1d323386e001c786af10f0a3f39f438f03b Author: Albert Lee Date: Fri May 19 11:43:04 2006 +0800 [PATCH] libata: Fix the HSM error_mask mapping (was: Re: libata-tj and SMART) Fix the HSM error_mask mapping. Changes: - Better mapping in ac_err_mask() - In HSM_ST_FIRST ans HSM_ST state, check ATA_ERR|ATA_DF and map it to AC_ERR_DEV instead of AC_ERR_HSM. - In HSM_ST_FIRST and HSM_ST state, map DRQ=1 ERR=1 to AC_ERR_HSM. - For PIO data in and DRQ=1 ERR=1, add check after the junk data block is read. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 5fc3dbc418e01345e25e96b3192a1c46051c3fdc Author: David Woodhouse Date: Sat May 20 02:41:34 2006 +0100 [MTD] Use __symbol_get() instead of symbol_get() in NOR chip probe Signed-off-by: David Woodhouse commit dcb6592d72923123e3e479134f9381e0133d7d9d Author: Andrew Morton Date: Fri May 19 18:06:34 2006 -0700 git-mtd: symbol_get() fix drivers/mtd/devices/docprobe.c: In function `DoC_Probe': drivers/mtd/devices/docprobe.c:338: warning: assignment from incompatible pointer type drivers/mtd/devices/docprobe.c:341: warning: assignment from incompatible pointer type Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse commit 8e4482fba21d15da99f39a13396d3361e810d199 Author: Ferenc Havasi Date: Fri May 19 21:00:36 2006 +0100 [JFFS2] Remove forgotten summary code Remove forgotten lines from jffs2_scan_eraseblock() which were unnecessary and may cause problem in some environments. Thanks to Alexander Belyakov . Signed-off-by: Ferenc Havasi Signed-off-by: David Woodhouse commit 4d1f3f25d9c303d1ce63b42cc94c54ac0ab2e950 Author: Jimi Xenidis Date: Thu May 18 17:03:05 2006 -0500 [PATCH] powerpc: Auto reserve of device tree blob A devtree compiler (dtc) generated devtree blob is "relocatable" and so does not contain a reserved_map entry for the blob itself. This means that if passed to Linux, Linux will not get lmb_reserve() the blob and it could be over. The following patch will explicitly reserve the "blob" as it was given to us and stops prom_init.c from creating a reserved mapping for the blob. NOTE: that the dtc/kexec should not generate the blob reservation entry. Although if they do, LMB reserver handles overlaps. Signed-off-by: Acked-by: Michael Neuling Signed-off-by: Paul Mackerras commit 1dc461f0b03fab309eb9214df1c9b586aeaf3b22 Author: Stephen Rothwell Date: Thu May 18 17:21:26 2006 +1000 [PATCH] powerpc: the iSeries vio lan driver changed device type So the IOMMU table building code needs to match. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 4c76e0bcdeac27b45d55955f073a97ff8452a42f Author: Jeremy Kerr Date: Thu May 18 18:06:37 2006 +1000 [PATCH] powerpc: pseries: Use generic dma-window parsing function Change the pseries iommu init code to use the new of_parse_dma_window() to parse the ibm,dma-window and ibm,my-dma-window properties of pci and virtual device nodes. Also, clean up vio_build_iommu_table() a little. Tested on pseries, with both vio and pci devices. Signed-off-by: Jeremy Kerr Acked-by: Olof Johansson Signed-off-by: Paul Mackerras commit d4ad66faecc4dd9f3db14e0b013741a6f867b089 Author: Jeremy Kerr Date: Thu May 18 18:05:15 2006 +1000 [PATCH] powerpc: Add of_parse_dma_window() Add a function for generic parsing of dma-window properties (ie, ibm,dma-window and ibm,my-dma-window) of pci and virtual device nodes. This function will also be used by cell. Signed-off-by: Jeremy Kerr Acked-by: Olof Johansson Signed-off-by: Paul Mackerras commit 8ae5b2801a0beb10a55a7ebd5140482e2f84c3fa Author: jimix@watson.ibm.com Date: Wed May 17 12:00:35 2006 -0400 [PATCH] powerpc: udbg_printf() formatting attribute This patch allows the compiler to catch any printf-like mismatches for udbg_printf(). After some brute force building I've only found issues with my own code and lparcfg.c It could break some developers, but IMHO that would be goodness. Signed-off-by: Jimi Xenidis Signed-off-by: Paul Mackerras commit 35dd54326e857f1648c7cc1028e8d5e1dbe04992 Author: Michael Ellerman Date: Thu May 18 11:16:11 2006 +1000 [PATCH] powerpc: Move crashkernel= handling into the kernel. This was missing a quilt ref. Signed-off-by: Paul Mackerras commit 473104134b35ce1c3ca77b738c561d6c215adc1b Author: Michael Ellerman Date: Wed May 17 18:00:49 2006 +1000 [PATCH] powerpc: Kdump header cleanup We need to know the base address of the kdump kernel even when we're not a kdump kernel, so add a #define for it. Move the logic that sets the kdump kernelbase into kdump.h instead of page.h. Rename kdump_setup() to setup_kdump_trampoline() to make it clearer what it's doing, and add an empty definition for the !CRASH_DUMP case to avoid a Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit 2babf5c2ec2f2d5de3e38d20f7df7fd815fd10c9 Author: Michael Ellerman Date: Wed May 17 18:00:46 2006 +1000 [PATCH] powerpc: Unify mem= handling We currently do mem= handling in three seperate places. And as benh pointed out I wrote two of them. Now that we parse command line parameters earlier we can clean this mess up. Moving the parsing out of prom_init means the device tree might be allocated above the memory limit. If that happens we'd have to move it. As it happens we already have logic to do that for kdump, so just genericise it. This also means we might have reserved regions above the memory limit, if we do the bootmem allocator will blow up, so we have to modify lmb_enforce_memory_limit() to truncate the reserves as well. Tested on P5 LPAR, iSeries, F50, 44p. Tested moving device tree on P5 and 44p and F50. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit 846f77b08c8301682ded5ce127c56397327a60d0 Author: Michael Ellerman Date: Wed May 17 18:00:45 2006 +1000 [PATCH] powerpc: Parse early parameters earlier Currently we have call parse_early_param() earliyish, but not really very early. In particular, it's not early enough to do things like mem=x or crashkernel=blah, which is annoying. So do it earlier. I've checked all the early param handlers, and none of them look like they should have any trouble with this. I haven't tested the booke_wdt ones though. On 32-bit we were doing the CONFIG_CMDLINE logic twice, so don't. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit 480f6f35a149802a94ad5c1a2673ed6ec8d2c158 Author: Michael Ellerman Date: Wed May 17 18:00:41 2006 +1000 [PATCH] powerpc: Make early xmon logic immune to location of early parsing Currently early_xmon() calls directly into debugger() if xmon=early is passed. This ties the invocation of early xmon to the location of parse_early_param(), which might change. Tested on P5 LPAR and F50. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit f9a6ee1afb84fd767508428ec5d1df4fb60a03ad Author: Rich Townsend Date: Mon Dec 19 23:07:00 2005 -0500 ACPI: replace spin_lock_irq with mutex for ec poll mode http://bugzilla.kernel.org/show_bug.cgi?id=5764 Signed-off-by: Luming Yu Signed-off-by: Len Brown commit 9dabbfbab312909782b26580d71e3977622fab6e Author: mostrows@watson.ibm.com Date: Mon May 15 08:51:07 2006 -0400 [PATCH] powerpc: Create /proc/rtas, /proc/ppc64/rtas if RTAS exists. Use the existence of RTAS device tree node to determine if /proc/rtas. /proc/ppc64/rtas are to be created. Using machine type is not reliable (i.e. Maple-like machines may have RTAS). Signed-off-by: Michal Ostrowski Signed-off-by: Paul Mackerras commit de0fe3b83f4bb47a0a6b47897bb3800862194016 Author: Stephen Rothwell Date: Mon May 15 13:44:01 2006 +1000 [PATCH] powerpc: update iSeries viocd and viotape device-tree Make their device_type entries more generic and their compatible entries more specific. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit dc3c9b8ca2ec15cf56d071b85f3734a07bf5f808 Author: Stephen Rothwell Date: Mon May 15 13:42:29 2006 +1000 [PATCH] powerpc: update iSeries vdevice Make it look more like the pSeries vdevice tree. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit fbabeb60ba783bf7a43858ecefc5066ac1f07162 Author: Stephen Rothwell Date: Mon May 15 13:41:22 2006 +1000 [PATCH] powerpc: update iSeries viodasd device-tree entries These devices should have device_type block and a unique compatible entry. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 07fb3f454cc9e0f656e378a6feb5bdd6cac4bd41 Author: Stephen Rothwell Date: Mon May 15 13:39:47 2006 +1000 [PATCH] powerpc: update iseries_veth device-tree information Make the device-tree information more generic and more like the pSeries virtual lan device. Also use the MAC address from the device tree. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit d6b89a196dfb03fdfbe3d574ab6773fe14a1d2c6 Author: Michael Neuling Date: Tue May 9 11:33:38 2006 -0500 [PATCH] powerpc: whitespace cleanup in reg.h In reg.h we mostly have #define but there are a few #define around. Clean these up so we use space exclusively. Signed-off-by: Michael Neuling Signed-off-by: Paul Mackerras commit 485a2d54dbc7cf939bd0c22daad74e2cf6f001d7 Author: Michael Ellerman Date: Tue May 9 16:03:51 2006 +1000 [PATCH] powerpc: Make early debugging options behave with oldconfig If you undefine all the early debugging options and then run make oldconfig, you don't get prompted to see if you want to enable any of them. This is annoying. AFAICT we can't do this just with a choice, because the choice is either optional, in which case we don't get prompted, or not in which case we _must_ select early debugging. So add a bool which controls whether we have early debugging at all, and then if that's enabled provide the choice. The extra bool will actually be useful in another patch I have lying around, so this is a win-win. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit b26f100d89c87060b561c3108582b7cb81521df8 Author: Geoff Levand Date: Fri May 19 14:24:18 2006 +1000 [PATCH] powerpc: remove do-nothing cpu setup routines Removed the do-nothing routines __setup_cpu_power3 and __setup_cpu_power4 and replaced them with a null pointer check in the caller. Also removed the Cell processor specific routine __setup_cpu_be which improperly accessed the hypervisor page size configuration at SPR HID6. Signed-off-by: Geoff Levand Signed-off-by: Paul Mackerras commit 4240545661fc0ac25122f166e96633527150300c Author: Linas Vepstas Date: Fri Apr 28 17:39:38 2006 -0500 [PATCH] powerpc/pseries: Increment fail counter in PCI recovery When a PCI device driver does not support PCI error recovery, the powerpc/pseries code takes a walk through a branch of code that resets the failure counter. Because of this, if a broken PCI card is present, the kernel will attempt to reset it an infinite number of times. (This is annoying but mostly harmless: each reset takes about 10-20 seconds, and uses almost no CPU time). This patch preserves the failure count across resets. Signed-off-by: Linas Vepstas Signed-off-by: Paul Mackerras commit aef9ab47841af45888d950baa6448072cc70bdd5 Author: David Woodhouse Date: Fri May 19 00:28:49 2006 +0100 [JFFS2] Support new device nodes Device node major/minor numbers are just stored in the payload of a single data node. Just extend that to 4 bytes and use new_encode_dev() for it. We only use the 4-byte format if we _need_ to, if !old_valid_dev(foo). This preserves backwards compatibility with older code as much as possible. If we do make devices with major or minor numbers above 255, and then mount the file system with the old code, it'll just read the first two bytes and get the numbers wrong. If it comes to garbage-collect it, it'll then write back those wrong numbers. But that's about the best we can expect. Signed-off-by: David Woodhouse commit f6a673b3f4f93c1c50e1b18f29254b0531b722a8 Author: David Woodhouse Date: Wed May 17 22:03:10 2006 +0100 [MTD] Fix printk format error in gen_probe.c Signed-off-by: David Woodhouse commit fd0e5187458041c82fea616575104698397d68d3 Author: David Woodhouse Date: Wed May 17 21:53:58 2006 +0100 [MTD] Fix mtdconcat build. We didn't introduce mtd->writesize yet. Signed-off-by: David Woodhouse commit 5d25ea7c0c77cbdba1b5f092d60d624e24dfa938 Author: Arjan van de Ven Date: Tue May 2 18:01:41 2006 +0200 [PATCH] unused exports in wireless drivers There's a bunch of unused exports in the wireless drivers; that's bad since unused exports take up quite a bit of space in total; the patch below removes them. Signed-off-by: Arjan van de Ven Signed-off-by: John W. Linville commit e8d32937d9f2022c31871ef357a4883f78da1b7f Author: Alexander Belyakov Date: Wed May 17 19:11:16 2006 +0400 MTD: mtdconcat NAND/Sibley support (rev.2) There is a second revision of "mtdconcat NAND/Sibley" patch. I hope the patch will not get damaged as I'm posting it from gmail account, thanks to Jorn. The patch adds previously missing concat_writev(), concat_writev_ecc(), concat_block_isbad(), concat_block_markbad() functions to make concatenation layer compatible with Sibley and NAND chips. Patch has been cleared from whitespaces, fixed some lines of code as requested. Also I have added code for alignment check that should support Jorn's "writesize" patch. Signed-off-by: Alexander Belyakov Signed-off-by: David Woodhouse commit ceb31db11f78935c666c50fe9c99d4560d592fde Author: Martin Michlmayr Date: Mon Mar 20 04:40:46 2006 +0000 LASAT depends on MTD_CFI The following difference was found between the mainline and linux-mips kernel. LASAT depends on MTD_CFI. Signed-off-by: Martin Michlmayr Signed-off-by: David Woodhouse commit be21ce119716f821c595552917ce7c05a3997b6b Author: Martin Michlmayr Date: Mon Mar 20 04:40:26 2006 +0000 Re-add module description for ms02-nv to Kconfig In an unrelated MTD commit, a description about the ms02-nv module got removed from Kconfig. While I personally agree with this removal, the module maintainer (Maciej W. Rozycki) would like to see it added back. In the absense of any consistency regarding Kconfig descriptions his wish should be followed. Signed-off-by: Martin Michlmayr Acked-by: Maciej W. Rozycki Signed-off-by: David Woodhouse commit 683b30c8e78ab363dc8d8c94bdb61b64d1f6f5e2 Author: Sean Young Date: Wed May 17 12:45:34 2006 +0100 [MTD] RFD FTL: Be noisier, and don't assume block without RFD magic are erased Signed-off-by: Sean Young Signed-off-by: David Woodhouse commit ae282d497d5631ce31539717131c760e3872c539 Author: Vitaly Wool Date: Wed May 17 12:34:27 2006 +0100 [MTD] generic: propagate oobavail to MTD partitions 'oobavail' parameter of mtd_info structure is now propagated to the MTD partitions Signed-off-by: Vitaly Wool Signed-off-by: David Woodhouse commit 599fb3298b70d75c12dbdc4dd30f52c5cf04ea2f Author: Sean Young Date: Wed May 17 11:47:48 2006 +0100 [PCMCIA MTD] Fix leak and crash on reboot Signed-off-by: Sean Young Signed-off-by: David Woodhouse commit c172471b78255a5cf6d05383d9ebbf0c6683167a Author: Nicolas Pitre Date: Thu Mar 30 15:52:41 2006 +0100 cfi_cmdset_0001: factorize code to wait for flash status This allows for much better abstraction and separation of the XIP and non-XIP cases with their own specific implementations. This fixes the case where a timeout was tripped on in the XIP case by the code that was meant for the non-XIP case only. This also makes for a nice code reduction. Signed-off-by: Nicolas Pitre CC: "Alexey, Korolev" Signed-off-by: David Woodhouse commit 6e7a6809c555aeb7cb98544df4d446fbd6f123ec Author: Nicolas Pitre Date: Wed Mar 29 23:31:42 2006 +0100 cfi-cmdset-0001: always update the chip status ... otherwise xip_enable() won't do the right thing. Signed-off-by: Nicolas Pitre Signed-off-by: David Woodhouse commit df54b52c411befdcf1d0989f939a49163570ad29 Author: Josh Boyer Date: Tue Dec 6 17:28:19 2005 +0000 CHIPS: Fix potential starvation in cfi_cmdset_0001 The patch below fixes a potential starvation issue that can arise when there is contention on a chip during a period when a process is currently writing to it. The starvation is avoided by conditionally rescheduling when the chip is left in a state usable by other processes. Signed-off-by: Josh Boyer Signed-off-by: Tom Gall Signed-off-by: David Woodhouse commit 3ac6c7b44560fdf2ea8865536bd52d4ff038107e Author: David Woodhouse Date: Tue May 16 23:25:37 2006 +0100 Remove struct fddi_statistics from user view in Signed-off-by: David Woodhouse commit ba9627b85fcb5ed67285ca0711f0f4d1e965746e Author: David Woodhouse Date: Tue May 16 23:03:08 2006 +0100 [JFFS2] Repack some on-medium structures. ARM is weirder than I thought. We have to pack at least the jint16_t structure, because otherwise it'll be four bytes in size. Thankfully, we can do that and _not_ pack the actual node structures, and the compiler still doesn't emit stupid code. Signed-off-by: David Woodhouse commit 35af68b53a62c98bf551aaae7be179bde248eb34 Author: Sergei Shtylyov Date: Tue May 16 20:52:06 2006 +0400 NAND: Fix NAND ECC errors on AMD Au1550 On AMD Au1550 the static bus controller fails to keep -CE asserted during chip ready delay on read commands and the NAND chip being used requires this. So, the current driver allows nand_base.c to drive -CE manually during the entire sector read. When the PCMCIA driver is enabled however, occasionally the ECC errors occur on NAND reads. This happens because the PCMCIA driver polls sockets periodically and reads one of the board's control/status regs (BCSRs) which are on the same static bus as the NAND flash, and just use another chip select (and the NOR flash also resides on that bus), so as the NAND driver forces NAND chip select asserted and the -RE signal is shared, a contention occurs on the static bus when BCSR or NOR flash is read while we're reading from NAND. So, we either can't keep interrupts enabled during the whole NAND sector read (which is hardly acceptable), or have to implement some interlocking scheme between multiple drivers (which is painful, and makes me shudder :-). There's a third way which has proven to work: to force -CE asserted only while we're waiting for a NAND chip to become ready after a read command, disabling interrupts for a maximum of 25 microseconds (according to Toshiba TC58DVM92A1FT00 datasheet -- this chip is mentioned in the board schematics); for Samsung NAND chip which seems to be actually used this delay is even less, 12 us. Signed-off-by: Konstantin Baydarov Signed-off-by: Sergei Shtylyov Signed-off-by: David Woodhouse commit b020bb7d3b3a8e3568a16eaf98c033bb9ee474eb Author: Ben Dooks Date: Tue May 16 17:31:15 2006 +0100 [MTD] Fix build warnings in RedBoot MTD partition parser. Fix build warnings from drivers/mtd/redboot.c due to use of `unsigned long` in `struct fis_image_desc` for fields being passed to swab32s() which expects __u32 * Change the entries to uint32_t to make them compatible with the swab32s() function Signed-off-by: Ben Dooks Signed-off-by: David Woodhouse commit 155285c4775b7027b01a5b744c721ae43cced798 Author: Sergei Shtylyov Date: Tue May 16 20:16:41 2006 +0400 NAND: AMD Au1550 driver reads write-only register During the last cleanup of the AMD Au1550 NAND driver the old buglet was reintroduced: as the MEM_STNDCTL register is write-only and seem to always read as 0x31, read-modify-write to it done in au1xxx_nand_init() will have the side effect of enabling -RCS0/1 pin override (via bits 4/5 of this reg.), thus possibly causing a contention on the static bus when the NOR flash (using -RCS0) or board control status registers (using -RCS2) are read. Luckily, this goes away with a first NAND access, since au1550_hwcontrol() doesn't try to read this register before writing anymore. Signed-off-by: Sergei Shtylyov Signed-off-by: David Woodhouse commit c41ff6e5f38b02ff927d0d510e28dc1392bb4690 Author: David Woodhouse Date: Tue May 16 17:05:33 2006 +0100 [JFFS2] Fix printk format in jffs2_sum_write_data() error message. fs/jffs2/summary.c: In function ‘jffs2_sum_write_data’: fs/jffs2/summary.c:658: warning: format ‘%zd’ expects type ‘signed size_t’, but argument 4 has type ‘uint32_t’ Signed-off-by: David Woodhouse commit 7d2beb135986477f53da77303356bd04329f8d0e Author: David Brownell Date: Tue May 16 16:08:10 2006 +0100 [JFFS2] Fix section mismatch warnings in JFFS2. Mark certain functions with __init and __exit appropriately. Signed-off-by: David Brownell Signed-off-by: David Woodhouse commit cead4dbc03ba6eb2e35bac04439b76a0cc2286ce Author: David Woodhouse Date: Tue May 16 13:54:50 2006 +0100 [MTD NAND] Make various initfuncs static, remove #ifdef MODULE from exitfuncs We all inherited the same error from the original NAND board driver which got copied and changed. Fix them all at once... Signed-off-by: David Woodhouse commit ce589a0328866228412ea0df2c834688da8f4700 Author: Adrian Bunk Date: Tue May 16 13:46:44 2006 +0200 drivers/mtd/devices/docprobe.c: correct #if's On Mon, May 15, 2006 at 12:56:37AM -0700, Andrew Morton wrote: >... > Changes since 2.6.17-rc3-mm1: >... > git-mtd.patch >... > git trees >... If we correct the names of the config options, the code might actually work as intended... Signed-off-by: Adrian Bunk Signed-off-by: David Woodhouse commit f41a5f804a5862e9b87cf2d4cca1d6a7db7a9e82 Author: David Woodhouse Date: Tue May 16 13:11:47 2006 +0100 [MTD] Add help text for MTD_NAND_CS553X option. Signed-off-by: David Woodhouse commit 5b5ffbc1e6d62d89747f3f59c09b2e488a7d7fce Author: Florin Malita Date: Mon May 15 23:42:31 2006 +0100 [PATCH] jffs2: memory leak in jffs2_scan_medium() If jffs2_scan_eraseblock() fails and the exit path is taken, 's' is not being deallocated. Reported by Coverity, CID: 1258. Signed-off-by: Florin Malita Signed-off-by: David Woodhouse commit 184f565210c6c8a852c53ffc070f9add61e0f331 Author: Andrew Morton Date: Mon May 15 13:45:58 2006 +0100 [JFFS2] Fix printk format in some error messages. fs/jffs2/nodelist.c: In function `check_node_data': fs/jffs2/nodelist.c:441: warning: unsigned int format, different type arg (arg 4) fs/jffs2/nodelist.c:464: warning: int format, different type arg (arg 5) Modified from Andrew's original fix because while his terminal may indeed only have eighty columns, mine only has _TWENTYFOUR_ lines. So the cosmetic fluff is perfectly OK out past column 80 where it was -- the casual reader doesn't _care_ about anything more than the fact that it goes 'if (foo) JFFS2_WARNING...', and there's no point wasting a whole line to display the tail end of the printk which nobody actually cares about. Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse commit aee10a03eb3e240bfd1a6f91e06ce82df47c5c58 Author: Tejun Heo Date: Mon May 15 21:03:56 2006 +0900 [PATCH] sata_sil24: implement NCQ support Implement NCQ support. Sil24 has 31 command slots and all of them are used for NCQ command queueing. libata guarantees that no other command is in progress when it issues an internal command, so always use tag 0 for internal commands. Signed-off-by: Tejun Heo commit 12fad3f965830d71f6454f02b2af002a64cec4d3 Author: Tejun Heo Date: Mon May 15 21:03:55 2006 +0900 [PATCH] ahci: implement NCQ suppport Implement NCQ support. Original implementation is from Jens Axboe. Signed-off-by: Tejun Heo commit a9764c2bb5b6d3c9df91f2977a2a640f55de0dc2 Author: Tejun Heo Date: Mon May 15 21:03:53 2006 +0900 [PATCH] ahci: kill pp->cmd_tbl_sg With NCQ, there are multiple sg tables, so pp->cmd_tbl_sg doesn't cut it. Directly calculate sg table address from pp->cmd_tbl. Signed-off-by: Tejun Heo commit 979db803b8fd120d4ed5216520e9d1815e18bc38 Author: Tejun Heo Date: Mon May 15 21:03:52 2006 +0900 [PATCH] ahci: add HOST_CAP_NCQ constant Add HOST_CAP_NCQ. Signed-off-by: Tejun Heo commit dd410ff12925fc49df3174b18e43598b2b2b621f Author: Tejun Heo Date: Mon May 15 21:03:50 2006 +0900 [PATCH] ahci: clean up AHCI constants in preparation for NCQ * Rename CMD_TBL_HDR to CMD_TBL_HDR_SZ as it's size not offset. * Define MAX_CMDS and CMD_SZ and use them in calculation of other constants. * Define CMD_TBL_AR_SZ as product of CMD_TBL_SZ and MAX_CMDS, and use it when calculating PRIV_DMA_SZ. * CMD_SLOT_SZ is also dependent on MAX_CMDS but hasn't been changed because I didn't want to change the value used by the original code (32 commands). Later NCQ change will bump MAX_CMDS to 32 anyway and the hard coded 32 can be changed to MAX_CMDS then. * Reorder HOST_CAP_* flags. Signed-off-by: Tejun Heo commit a6e6ce8e8dc907a2cf2b994b0ea4099423f046bf Author: Tejun Heo Date: Mon May 15 21:03:48 2006 +0900 [PATCH] libata-ncq: implement NCQ device configuration Now that all NCQ related stuff are in place, implement NCQ device configuration and bump ATA_MAX_QUEUE to 32 thus activating NCQ support. Original implementation is from Jens Axboe. Signed-off-by: Tejun Heo commit e8ee84518c159a663c07bf691ace187527380f61 Author: Tejun Heo Date: Mon May 15 21:03:46 2006 +0900 [PATCH] libata-ncq: update EH to handle NCQ Update EH to handle NCQ. ata_eh_autopsy() is updated to call ata_eh_analyze_ncq_error() which reads log page 10h on NCQ device error and updates eh_context accordingly. ata_eh_report() is updated to report SActive. Signed-off-by: Tejun Heo commit 3dc1d88193b9c65b01b64fb2dc730e486306649f Author: Tejun Heo Date: Mon May 15 21:03:45 2006 +0900 [PATCH] libata-ncq: implement NCQ command translation and exclusion This patch implements NCQ command translation and exclusion. Note that NCQ commands don't use ata_rwcmd_protocol() to choose ATA command. This is because, unlike non-NCQ RW commands, NCQ commands can only be used for NCQ protocol and FUA handling is done with a flag rather than separate command. NCQ enabled device will have queue depth larger than one but no two non-NCQ commands can be issued simultaneously, neither can a non-NCQ command and NCQ commands. This patch makes ata_scsi_translate() return SCSI_MLQUEUE_DEVICE_BUSY if such exclusion is necessary. SCSI midlayer will retry the command later. As SCSI midlayer always retries once a command completes, this doesn't incur unnecessary delays and as most commands will be NCQ ones for NCQ device, so the overhead should be negligible. Initial implementation is from Jens Axboe and using SCSI_MLQUEUE_DEVICE_BUSY for exclusion is suggested by Jeff Garzik. Signed-off-by: Tejun Heo commit dedaf2b0365ccec50714fbde0b3215e7e94fa47c Author: Tejun Heo Date: Mon May 15 21:03:43 2006 +0900 [PATCH] libata-ncq: implement ap->qc_active, ap->sactive and complete helper Add ap->qc_active and ap->sactive, mask of all active qcs and libata's view of the SActive register, respectively. Also, implement ata_qc_complete_multiple() which takes new qc_active mask and complete multiple qcs according to the mask. These will be used to track NCQ commands and complete them. The distinction between ap->qc_active and ap->sactive is also useful for later PM implementation. Signed-off-by: Tejun Heo commit 6cec4a3943bdfe46e2952bc246f17670f747be8d Author: Tejun Heo Date: Mon May 15 21:03:41 2006 +0900 [PATCH] libata-ncq: rename ap->qactive to ap->qc_allocated Rename ap->qactive to ap->qc_allocated. This is to accomodate addition of ap->qc_active, mask of active qcs. Signed-off-by: Tejun Heo commit 2115ea94a2d11fbd228b049e667ec2d3e91ca371 Author: Tejun Heo Date: Mon May 15 21:03:39 2006 +0900 [PATCH] libata-ncq: pass ata_scsi_translate() return value to SCSI midlayer ata_scsi_translate() will need to return SCSI_ML_QUEUE_DEVICE_BUSY to achieve exlusion between NCQ and non-NCQ commands or among non-NCQ commands. Pass its return value upward to SCSI midlayer. Signed-off-by: Tejun Heo commit 88e490340ea4c3a2ebc0187a4339912e2fc1a081 Author: Tejun Heo Date: Mon May 15 21:03:38 2006 +0900 [PATCH] libata-ncq: add NCQ related ATA/libata constants and macros Add NCQ related ATA/libata constants and macros. Signed-off-by: Tejun Heo commit c17ea20d9a689d7335e97e09354865cdd9f873e1 Author: Tejun Heo Date: Mon May 15 20:59:29 2006 +0900 [PATCH] libata: fix irq-pio merge * kill ata_poll_qc_complete() and implement/use ata_hsm_qc_complete() which completes qcs in new EH compliant manner from HSM * don't print error message from ata_hsm_move(). it's responsibility of EH. * kill ATA_FLAG_NOINTR usage in bmdma EH Signed-off-by: Tejun Heo commit 88ce7550c38f46c8697f53727a571bf838bee398 Author: Tejun Heo Date: Mon May 15 20:58:32 2006 +0900 [PATCH] sata_sil24: convert to new EH Convert sata_sil24 to new EH. * When port is frozen, IRQ for the port is masked. * sil24_softreset() doesn't need to mangle with IRQ mask anymore. libata ensures that the port is frozen during reset. * Only turn on interrupts which are handled by interrupt handler and EH. As we don't handle SDB notify yet, turn it off. DEV_XCHG and UNK_FIS are handled by EH and thus turned on. * sil24_softreset() usually fails to recover the port after DEV_XCHG. ATA_PORT_HARDRESET is used as recovery action for DEV_XCHG. * sil24 may be invoked without any active command. e.g. DEV_XCHG irq occuring while no qc in progress still triggers EH and will reset the port and revalidate attached device. Signed-off-by: Tejun Heo commit 2a3917a8bb40a2cb75b458da9c356e8557e8fbed Author: Tejun Heo Date: Mon May 15 20:58:30 2006 +0900 [PATCH] ahci: add PIOS interim interrupt handling During multiblock PIO, multiple PIOS interrupts are generated before qc compltion. Current code prints unnecessary message for such cases. This is exposed when new EH slows down attached device into PIO mode. Signed-off-by: Tejun Heo commit 78cd52d02fa0735949a9fa30a6b79bf02c94c250 Author: Tejun Heo Date: Mon May 15 20:58:29 2006 +0900 [PATCH] ahci: convert to new EH Convert AHCI to new EH. Unfortunately, ICH7 AHCI reacts badly if IRQ mask is diddled during operation. So, freezing is implemented by unconditionally clearing interrupt conditions while frozen. * Interrupts are categorized according to required action. e.g. Connection status or unknown FIS error requires freezing the port while TF or HBUS_DATA don't. * Only CONNECT (reflects SErr.X) interrupt is taken into account not PHYRDY (SErr.N), as CONNECT is better cue for starting EH. * AHCI may be invoked without any active command. e.g. CONNECT irq occuring while no qc in progress still triggers EH and will reset the port and revalidate attached device. Signed-off-by: Tejun Heo commit f6aae27ed002ba9c0a98aff811dbde32ce749d28 Author: Tejun Heo Date: Mon May 15 20:58:27 2006 +0900 [PATCH] sata_sil: convert to new EH Convert sata_sil to new EH. As these controllers have hardware interrupt mask and are known to have screaming interrupts issues, use hardware IRQ masking for freezing. sil_freeze() masks interrupts for the port and sil_thaw() unmasks them. As ports are automatically frozen before probing reset, there is no need to initialize interrupt masks sil_init_onde(). Remove related code. Other than freezing, sata_sil uses stock BMDMA EH routines. Signed-off-by: Tejun Heo commit 3f037db0ba043022e43e8e7266e698d4af264851 Author: Tejun Heo Date: Mon May 15 20:58:25 2006 +0900 [PATCH] ata_piix: convert to new EH ata_piix can use stock BMDMA EH routines. Convert to new EH. Signed-off-by: Tejun Heo commit 6d97dbd72da31a0e334f251fa9df4be9fab6fde2 Author: Tejun Heo Date: Mon May 15 20:58:24 2006 +0900 [PATCH] libata-eh: implement BMDMA EH Implement stock BMDMA error handling methods. Signed-off-by: Tejun Heo commit 022bdb075b9e1f224088a0b268de56268d7bc5b6 Author: Tejun Heo Date: Mon May 15 20:58:22 2006 +0900 [PATCH] libata-eh: implement new EH Implement new EH. The exported interface is ata_do_eh() which is to be called from ->error_handler and performs the following steps to recover the failed port. ata_eh_autopsy() : analyze SError/TF, determine the cause of failure and required recovery actions and record it in ap->eh_context ata_eh_report() : report the failure to user ata_eh_recover() : perform recovery actions described in ap->eh_context ata_eh_finish() : finish failed qcs LLDDs can customize error handling by modifying eh_context before calling ata_do_eh() or, if necessary, doing so inbetween each major steps by calling each step explicitly. Signed-off-by: Tejun Heo commit f3e81b19aac23c0e8c55d5961324ef7de44c23bb Author: Tejun Heo Date: Mon May 15 20:58:21 2006 +0900 [PATCH] libata-eh: implement ata_eh_info and ata_eh_context struct ata_eh_info serves as the communication channel between execution path and EH. Execution path describes detected error condition in ap->eh_info and EH recovers the port using it. To avoid missing error conditions detected during EH, EH makes its own copy of eh_info and clears it on entry allowing error info to accumulate during EH. Most EH states including EH's copy of eh_info are stored in ap->eh_context (struct ata_eh_context) which is owned by EH and thus doesn't require any synchronization to access and alter. This standardized context makes it easy to integrate various parts of EH and extend EH to handle multiple links (for PM). Signed-off-by: Tejun Heo commit 0c247c559cd70f85ba9f0764ce13ae00e20fcad8 Author: Tejun Heo Date: Mon May 15 20:58:19 2006 +0900 [PATCH] libata-eh: implement dev->ering This patch implements ata_ering and uses it to define dev->ering. ata_ering is a ring buffer which records libata errors - whether a command was for normar IO request, err_mask and timestamp. Errors are recorded per-device in dev->ering. This will be used by EH to determine recovery actions. Signed-off-by: Tejun Heo commit 9be1e979f2e1e57a091a658fa88dac266f9fd6fe Author: Tejun Heo Date: Mon May 15 20:58:17 2006 +0900 [PATCH] libata-eh: add ATA and libata flags for new EH Add ATA and libata flags to be used by new EH. Signed-off-by: Tejun Heo commit 246619da308c6910a3ae30e7e5fbf46139619efe Author: Tejun Heo Date: Mon May 15 20:58:16 2006 +0900 [PATCH] libata-eh-fw: update SCSI command completion path for new EH SCSI command completion path used to do some part of EH including printing messages and obtaining sense data. With new EH, all these are responsibilities of the EH, update SCSI command completion path to reflect this. Signed-off-by: Tejun Heo commit d95a717f579e81061830a308125c89f5858f740a Author: Tejun Heo Date: Mon May 15 20:58:14 2006 +0900 [PATCH] libata-eh-fw: update ata_exec_internal() for new EH Update ata_exec_internal() such that it uses new EH framework. ->post_internal_cmd() is always invoked regardless of completion status. Also, when ata_exec_internal() detects a timeout condition and new EH is in place, it freezes the port as timeout for normal commands would do. Note that ata_port_flush_task() is called regardless of wait_for_completion status. This is necessary as exceptions unrelated to the qc can abort the qc, in which case PIO task could still be running after the wait for completion returns. Signed-off-by: Tejun Heo commit ad9e27624479bd167dd7eac0cea4bb3ad13bc926 Author: Tejun Heo Date: Mon May 15 20:58:12 2006 +0900 [PATCH] libata-eh-fw: update ata_scsi_error() for new EH Update ata_scsi_error() for new EH. ata_scsi_error() is responsible for claiming timed out qcs and invoking ->error_handler in safe and synchronized manner. As the state of the controller is unknown if a qc has timed out, the port is frozen in such cases. Note that ata_scsi_timed_out() isn't used for new EH. This is because a timed out qc cannot be claimed by EH without freezing the port and freezing the port in ata_scsi_timed_out() results in unnecessary abortion of other active qcs. ata_scsi_timed_out() can be removed once all drivers are converted to new EH. While at it, add 'TODO: kill' comments to old EH functions. Signed-off-by: Tejun Heo commit dafadcde8d4dc5ea8c742faa7ff4403336b542b8 Author: Tejun Heo Date: Mon May 15 20:58:11 2006 +0900 [PATCH] libata-eh-fw: implement new EH scheduling from PIO PIO executes without holding host_set lock, so it cannot be synchronized using the same mechanism as interrupt driven execution. port_task framework makes sure that EH is not entered until PIO task is flushed, so PIO task can be sure the qc in progress won't go away underneath it. One thing it cannot be sure of is whether the qc has already been scheduled for EH by another exception condition while host_set lock was released. This patch makes ata_poll_qc-complete() handle such conditions properly and make it freeze the port if HSM violation is detected during PIO execution. Signed-off-by: Tejun Heo commit e318049949b07152d851dbfebbd93e560af45ebe Author: Tejun Heo Date: Mon May 15 20:58:09 2006 +0900 [PATCH] libata-eh-fw: implement freeze/thaw Freezing is performed atomic w.r.t. host_set->lock and once frozen LLDD is not allowed to access the port or any qc on it. Also, libata makes sure that no new qc gets issued to a frozen port. A frozen port is thawed after a reset operation completes successfully, so reset methods must do its job while the port is frozen. During initialization all ports get frozen before requesting IRQ, so reset methods are always invoked on a frozen port. Optional ->freeze and ->thaw operations notify LLDD that the port is being frozen and thawed, respectively. LLDD can disable/enable hardware interrupt in these callbacks if the controller's IRQ mask can be changed dynamically. If the controller doesn't allow such operation, LLDD can check for frozen state in the interrupt handler and ack/clear interrupts unconditionally while frozen. Signed-off-by: Tejun Heo commit 7b70fc039824bc7303e4007a5f758f832de56611 Author: Tejun Heo Date: Mon May 15 20:58:07 2006 +0900 [PATCH] libata-eh-fw: implement ata_port_schedule_eh() and ata_port_abort() ata_port_schedule_eh() directly schedules EH for @ap without associated qc. Once EH scheduled, no further qc is allowed and EH kicks in as soon as all currently active qc's are drained. ata_port_abort() schedules all currently active commands for EH by qc_completing them with ATA_QCFLAG_FAILED set. If ata_port_abort() doesn't find any qc to abort, it directly schedule EH using ata_port_schedule_eh(). These two functions provide ways to invoke EH for conditions which aren't directly related to any specfic qc. Signed-off-by: Tejun Heo commit f686bcb8078ac7505ec88818886c2c72639f4fc5 Author: Tejun Heo Date: Mon May 15 20:58:05 2006 +0900 [PATCH] libata-eh-fw: implement new EH scheduling via error completion There are several ways a qc can get schedule for EH in new EH. This patch implements one of them - completing a qc with ATA_QCFLAG_FAILED set or with non-zero qc->err_mask. ALL such qc's are examined by EH. New EH schedules a qc for EH from completion iff ->error_handler is implemented, qc is marked as failed or qc->err_mask is non-zero and the command is not an internal command (internal cmd is handled via ->post_internal_cmd). The EH scheduling itself is performed by asking SCSI midlayer to schedule EH for the specified scmd. For drivers implementing old-EH, nothing changes. As this change makes ata_qc_complete() rather large, it's not inlined anymore and __ata_qc_complete() is exported to other parts of libata for later use. Signed-off-by: Tejun Heo commit f69499f42caf74194df678c9c293f2ee0fe90bc3 Author: Tejun Heo Date: Mon May 15 20:58:03 2006 +0900 [PATCH] libata-eh-fw: update ata_qc_from_tag() to enforce normal/EH qc ownership New EH framework has clear distinction about who owns a qc. Every qc starts owned by normal execution path - PIO, interrupt or whatever. When an exception condition occurs which affects the qc, the qc gets scheduled for EH. Note that some events (say, link lost and regained, command timeout) may schedule qc's which are not directly related but could have been affected for EH too. Scheduling for EH is atomic w.r.t. ap->host_set->lock and once schedule for EH, normal execution path is not allowed to access the qc in whatever way. (PIO synchronization acts a bit different and will be dealt with later) This patch make ata_qc_from_tag() check whether a qc is active and owned by normal path before returning it. If conditions don't match, NULL is returned and thus access to the qc is denied. __ata_qc_from_tag() is the original ata_qc_from_tag() and is used by libata core/EH layers to access inactive/failed qc's. This change is applied only if the associated LLDD implements new EH as indicated by non-NULL ->error_handler Signed-off-by: Tejun Heo commit 2ab7db1ff1d64a2ba389d0692d532f42a15f1f72 Author: Tejun Heo Date: Mon May 15 20:58:02 2006 +0900 [PATCH] libata-eh-fw: use special reserved tag and qc for internal commands New EH may issue internal commands to recover from error while failed qc's are still hanging around. To allow such usage, reserve tag ATA_MAX_QUEUE-1 for internal command. This also makes it easy to tell whether a qc is for internal command or not. ata_tag_internal() test implements this test. To avoid breaking existing drivers, ata_exec_internal() uses ATA_TAG_INTERNAL only for drivers which implement ->error_handler. For drivers using old EH, tag 0 is used. Note that this makes ata_tag_internal() test valid only when ->error_handler is implemented. This is okay as drivers on old EH should not and does not have any reason to use ata_tag_internal(). Signed-off-by: Tejun Heo commit dc2b3515868a254b3d653d77844bff93c5d4c095 Author: Tejun Heo Date: Mon May 15 20:58:00 2006 +0900 [PATCH] libata-eh-fw: clear SError in ata_std_postreset() Clear SError in ata_std_postreset(). This is to clear SError bits which get set during reset. Signed-off-by: Tejun Heo commit 9ec957f2002bd2994be659bbc0ec28397fa251ee Author: Tejun Heo Date: Mon May 15 20:57:58 2006 +0900 [PATCH] libata-eh-fw: add flags and operations for new EH Add ATA_FLAG_EH_{PENDING|FROZEN}, ATA_ATA_QCFLAG_{FAILED|SENSE_VALID} and ops->freeze, thaw, error_handler, post_internal_cmd() for new EH. Signed-off-by: Tejun Heo commit f15a1dafed22d5037e0feea7528e1eeb28a1a7a3 Author: Tejun Heo Date: Mon May 15 20:57:56 2006 +0900 [PATCH] libata: use ATA printk helpers Use ATA printk helpers. Signed-off-by: Tejun Heo commit 61440db61fe4945ad9f7b32b4d6a22b17174aa1f Author: Tejun Heo Date: Mon May 15 20:57:55 2006 +0900 [PATCH] libata: implement ATA printk helpers Implement ata_{port|dev}_printk() which prefixes the message with proper identification string. This change is necessary for later PM support because devices and links should be identified differently depending on how they are attached. This also helps unifying device id strings. Currently, there are two forms in use (P is the port number D device number) - 'ataP(D):', and 'ataP: dev D '. These macros also make it harder to forget proper ID string (e.g. printing only port number when a device is in question). Debug message handling can be integrated into these printk macros by passing debug type and level via @lv. Signed-off-by: Tejun Heo commit 3373efd89dead4ce7818d685729e0431448357c9 Author: Tejun Heo Date: Mon May 15 20:57:53 2006 +0900 [PATCH] libata: use dev->ap Use dev->ap where possible and eliminate superflous @ap from functions and structures. Signed-off-by: Tejun Heo commit 38d87234d6c47ca487fc6344100323d5adc6f32c Author: Tejun Heo Date: Mon May 15 20:57:51 2006 +0900 [PATCH] libata: add dev->ap Add dev->ap which points back to the port the device belongs to. This makes it unnecessary to pass @ap for silly reasons (e.g. printks). Also, this change is necessary to accomodate later PM support which will introduce ATA link inbetween port and device. Signed-off-by: Tejun Heo commit a0ab51cefc95cb7756c4914603fea2b1a0f813c5 Author: Tejun Heo Date: Mon May 15 20:57:49 2006 +0900 [PATCH] libata: kill old SCR functions and sata_dev_present() Kill now unused scr_{read|write|write_flush}() and sata_dev_present(). Signed-off-by: Tejun Heo commit 81952c5497b40ae56835bd0d6537f8c6bdea07e7 Author: Tejun Heo Date: Mon May 15 20:57:47 2006 +0900 [PATCH] libata: use new SCR and on/offline functions Use new SCR and on/offline functions. Note that for LLDD which know it implements SCR callbacks, SCR functions are guaranteed to succeed and ata_port_online() == !ata_port_offline(). Signed-off-by: Tejun Heo commit 34bf21704c848fe00c516d1c8f163db08b70b137 Author: Tejun Heo Date: Mon May 15 20:57:46 2006 +0900 [PATCH] libata: implement new SCR handling and port on/offline functions Implement ata_scr_{valid|read|write|write_flush}() and ata_port_{online|offline}(). These functions replace scr_{read|write}() and sata_dev_present(). Major difference between between the new SCR functions and the old ones is that the new ones have a way to signal error to the caller. This makes handling SCR-available and SCR-unavailable cases in the same path easier. Also, it eases later PM implementation where SCR access can fail due to various reasons. ata_port_{online|offline}() functions return 1 only when they are affirmitive of the condition. e.g. if SCR is unaccessible or presence cannot be determined for other reasons, these functions return 0. So, ata_port_online() != !ata_port_offline(). This distinction is useful in many exception handling cases. Signed-off-by: Tejun Heo commit 838df6284c54447efae956fb9c243d8ba4ab0f47 Author: Tejun Heo Date: Mon May 15 20:57:44 2006 +0900 [PATCH] libata: init ap->cbl to ATA_CBL_SATA early Init ap->cbl to ATA_CBL_SATA in ata_host_init(). This is necessary for soon-to-follow SCR handling function changes. LLDDs are free to change ap->cbl during probing. Signed-off-by: Tejun Heo commit ce5f7f3d0cab82d6c16fcb64def8bfc0a3a85dd6 Author: Tejun Heo Date: Mon May 15 20:57:42 2006 +0900 [PATCH] sata_sil24: update TF image only when necessary Update TF image (pp->tf) only when necessary. Signed-off-by: Tejun Heo commit e61e067227bc76b4d9411a50d735c9d87f27b0e2 Author: Tejun Heo Date: Mon May 15 20:57:40 2006 +0900 [PATCH] libata: implement qc->result_tf Add qc->result_tf and ATA_QCFLAG_RESULT_TF. This moves the responsibility of loading result TF from post-compltion path to qc execution path. qc->result_tf is loaded if explicitly requested or the qc failsa. This allows more efficient completion implementation and correct handling of result TF for controllers which don't have global TF representation such as sil3124/32. Signed-off-by: Tejun Heo commit 96bd39ec295e49443c8b0c25a6b69fdace18780f Author: Tejun Heo Date: Mon May 15 20:57:38 2006 +0900 [PATCH] libata: remove postreset handling from ata_do_reset() Make ata_do_reset() deal only with reset. postreset is now the responsibility of the caller. This is simpler and eases later prereset addition. Signed-off-by: Tejun Heo commit 3adcebb2b59d590d572844815c906ca30477b14a Author: Tejun Heo Date: Mon May 15 20:57:37 2006 +0900 [PATCH] libata: move ->set_mode() handling into ata_set_mode() Move ->set_mode() handlng into ata_set_mode(). Signed-off-by: Tejun Heo commit fe635c7e91036282e4fd0cc5b4eebc712e43270d Author: Tejun Heo Date: Mon May 15 20:57:35 2006 +0900 [PATCH] libata: use preallocated buffers It's not a very good idea to allocate memory during EH. Use statically allocated buffer for dev->id[] and add 512byte buffer ap->sector_buf. This buffer is owned by EH (or probing) and to be used as temporary buffer for various purposes (IDENTIFY, NCQ log page 10h, PM GSCR block). Signed-off-by: Tejun Heo commit 158693031d7c58a355ec1852052a4fca75fd3bda Author: Tejun Heo Date: Mon May 15 20:57:33 2006 +0900 [PATCH] libata: hold host_set lock while finishing internal qc Hold host_set lock while finishing internal qc. Signed-off-by: Tejun Heo commit 7401abf2f44695ef44eef47d5deba1c20214a063 Author: Tejun Heo Date: Mon May 15 20:57:32 2006 +0900 [PATCH] libata: clear ap->active_tag atomically w.r.t. command completion ap->active_tag was cleared in ata_qc_free(). This left ap->active_tag dangling after ata_qc_complete(). Spurious interrupts inbetween could incorrectly access the qc. Clear active_tag in ata_qc_complete(). This change is necessary for later EH changes. Signed-off-by: Tejun Heo commit f8c2c4202d86e14ca03b7adc7ebcb30fc74b24e1 Author: Tejun Heo Date: Mon May 15 20:57:30 2006 +0900 [PATCH] libata: fix ->phy_reset class code handling in ata_bus_probe() ata_bus_probe() doesn't clear dev->class after ->phy_reset(). This can result in falsely enabled devices if probing fails. Clear dev->class to ATA_DEV_UNKNOWN after fetching it. Signed-off-by: Tejun Heo commit 6cd727b14f1a6cdcb088d1067c1ba0ba124806a7 Author: Tejun Heo Date: Mon May 15 20:57:28 2006 +0900 [PATCH] libata: kill duplicate prototypes Kill duplicate prototypes for ata_eh_qc_complete/retry() in libata.h. Signed-off-by: Tejun Heo commit e23befe9018319dc218e2e51c20ce480e6b45eeb Author: Tejun Heo Date: Mon May 15 20:57:27 2006 +0900 [PATCH] libata: unexport ata_scsi_error() While moving ata_scsi_error() from LLDD sht to libata transportt, EXPORT_SYMBOL_GPL() entry was left out. Kill it. Signed-off-by: Tejun Heo commit e4fac92ae744cd5d5c3c1774825788e6b91a5965 Author: Tejun Heo Date: Mon May 15 20:57:25 2006 +0900 [PATCH] ahci: hardreset classification fix AHCI calls ata_dev_classify() even when no device is attached which results in false class code. Fix it. Signed-off-by: Tejun Heo commit 3c567b7d1137633f3ff67cd1df94abc5fd497a85 Author: Tejun Heo Date: Mon May 15 20:57:23 2006 +0900 [PATCH] libata: rename ata_down_sata_spd_limit() and friends Rename ata_down_sata_spd_limit() and friends to sata_down_spd_limit() and likewise for simplicity & consistency. Signed-off-by: Tejun Heo commit c44078c03f018c8cc9d7463b0db4c6c7fb316792 Author: Tejun Heo Date: Mon May 15 20:57:21 2006 +0900 [PATCH] libata: silly fix in ata_scsi_start_stop_xlat() Don't directly access &qc->tf when tf == &qc->tf. Signed-off-by: Tejun Heo commit ee7863bc68fa6ad6fe7cfcc0e5ebe9efe0c0664e Author: Tejun Heo Date: Mon May 15 20:57:20 2006 +0900 [PATCH] SCSI: implement shost->host_eh_scheduled libata needs to invoke EH without scmd. This patch adds shost->host_eh_scheduled to implement such behavior. Currently the only user of this feature is libata and no general interface is defined. This patch simply adds handling for host_eh_scheduled where needed and exports scsi_eh_wakeup() to modules. The rest is upto libata. This is the result of the following discussion. http://thread.gmane.org/gmane.linux.scsi/23853/focus=9760 In short, SCSI host is not supposed to know about exceptions unrelated to specific device or command. Such exceptions should be handled by transport layer proper. However, the distinction is not essential to ATA and libata is planning to depart from SCSI, so, for the time being, libata will be using SCSI EH to handle such exceptions. Signed-off-by: Tejun Heo commit 89f48c4d67dd875cf2216d4402bf77eda41fbdd9 Author: Luben Tuikov Date: Mon May 15 20:57:18 2006 +0900 [PATCH] SCSI: Introduce scsi_req_abort_cmd (REPOST) Introduce scsi_req_abort_cmd(struct scsi_cmnd *). This function requests that SCSI Core start recovery for the command by deleting the timer and adding the command to the eh queue. It can be called by either LLDDs or SCSI Core. LLDDs who implement their own error recovery MAY ignore the timeout event if they generated scsi_req_abort_cmd. First post: http://marc.theaimsgroup.com/?l=linux-scsi&m=113833937421677&w=2 Signed-off-by: Luben Tuikov Signed-off-by: Tejun Heo commit 74ce1468128e299fe6a85e7e78e528e45e72d6d9 Author: Konstantin Karasyov Date: Mon May 8 08:32:00 2006 -0400 ACPI: create acpi_thermal_resume() http://bugzilla.kernel.org/show_bug.cgi?id=4364 Signed-off-by: Konstantin Karasyov Signed-off-by: Len Brown commit 0feabb01d93e5801d1127416a66cfc3963280bca Author: Konstantin Karasyov Date: Mon May 8 00:00:00 2006 -0400 ACPI: create acpi_fan_suspend()/acpi_fan_resume() http://bugzilla.kernel.org/show_bug.cgi?id=5000 Signed-off-by: Len Brown commit 531881d665ca011326bb466b97b07c95dee8d0a1 Author: Len Brown Date: Mon May 15 03:06:41 2006 -0400 ACPI: pass pm_message_t from acpi_device_suspend() to root_suspend() in case we want to decode it for future use in acpi_op_suspend(..., state) also, inline new 1-liner static function http://bugzilla.kernel.org/show_bug.cgi?id=5000 Signed-off-by: Len Brown commit 5b3272655a8e8a9a6e2503bc5a88fc9d9c8292a4 Author: Patrick Mochel Date: Wed May 10 10:33:00 2006 -0400 ACPI: create acpi_device_suspend()/acpi_device_resume() updated and tested by Konstantin Karasyov http://bugzilla.kernel.org/show_bug.cgi?id=5000 Signed-off-by: Patrick Mochel Signed-off-by: Konstantin Karasyov Signed-off-by: Len Brown commit 9c576ff1bc9ab42d06457e68e39c121481138562 Author: KAMEZAWA Hiroyuki Date: Thu Apr 27 05:25:00 2006 -0400 ACPI add ia64 exports to build acpi_memhotplug as a module Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 973bf491a55b825740f0d8d300b50bcd3d6fb8de Author: Yu, Luming Date: Thu Apr 27 05:25:00 2006 -0400 ACPI: fix potential memory leaks in driver/acpi/video.c acpi_video_bus_get_one_device() and other functions in driver/acpi/video.c do not release allocated memory on remove and on the error path. Signed-off-by: "Yu, Luming" Signed-off-by: Vasily Averin Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit ebd5f2ca811b75f7145fa487748f26430c584a72 Author: Andrew Morton Date: Sat May 13 22:56:00 2006 -0400 ACPI: asus_acpi_init(): propagate correct return value Cc: Bjorn Helgaas Acked-by: Francois Romieu Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 3e68fbb59b3d4e6b47b65e9928b5929e02179759 Author: David Woodhouse Date: Mon May 15 00:49:43 2006 +0100 [JFFS2] Don't pack on-medium structures, because GCC emits crappy code If we use __attribute__((packed)), GCC will _also_ assume that the structures aren't sensibly aligned, and it'll emit code to cope with that instead of straight word load/save. This can be _very_ suboptimal on architectures like ARM. Ideally, we want an attribute which just tells GCC not to do any padding, without the alignment side-effects. In the absense of that, we'll just drop the 'packed' attribute and hope that everything stays as it was (which to be fair is fairly much what we expect). And add some paranoia checks in the initialisation code, which should be optimised away completely in the normal case. Signed-off-by: David Woodhouse commit 52239da1b06ff445bf71d35e04d8ce74e4c6fe7b Author: David Woodhouse Date: Sun May 14 16:54:39 2006 +0100 [MTD NAND] Modify check for modules registering NAND devices without ->owner Make it work even with compilers which lack the wit to notice that THIS_MODULE is always non-NULL. Use #ifdef MODULE instead. It's only a temporary debugging check anyway. Signed-off-by: David Woodhouse commit 0d4e30d26a279f1b6a008a233a6835ad2af571e4 Author: David Woodhouse Date: Sun May 14 12:25:19 2006 +0100 [MTD] Clean up to fix modular build ... and also fix the multiple inclusion guard so it actually _works_ Signed-off-by: David Woodhouse commit 2f206701ae9b5c13719c2be26121b9461f05f87c Author: David Woodhouse Date: Sun May 14 11:59:20 2006 +0100 [MTD] Remove gratuitous inclusion of ARM-only header from physmap.c The physmap platform driver conversion added to physmap.c an include of asm/mach/flash.h which is 1) ARM-specific; and 2) isn't actually necessary. Remove it. Signed-off-by: Lennert Buytenhek Signed-off-by: David Woodhouse commit b6835052a6aa00536343b6d2127fc65cd814a040 Author: Andreas Mohr Date: Thu Apr 27 05:25:00 2006 -0400 ACPI: apply "__read_mostly" to processor_idle.c loop module parameters and friends make pm_idle_save, nocst and bm_history __read_mostly remove initializer from static 'first_run'. Signed-off-by: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 09047e75f69428dcfa977b326256085154068b65 Author: Vasily Averin Date: Thu Apr 27 05:25:00 2006 -0400 ACPI: fix memory leak in acpi_thermal_add() error path Signed-off-by: Vasily Averin Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 64385f2fd8bc9d8803c8d10dcd391871cb126b77 Author: Vasily Averin Date: Thu Apr 27 05:25:00 2006 -0400 ACPI: fix potential memory leak in acpi_evaluate_integer() error path Signed-off-by: Vasily Averin Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 06ea8e08ae7e7e450b6a78e7ce5e10b3c5f954ea Author: Bjorn Helgaas Date: Thu Apr 27 05:25:00 2006 -0400 ACPI: acpi_bus_unregister_driver() returns void Nobody looks at the return value, and this brings it into line with pci_unregister_driver(), etc. Also removed validation of the driver pointer passed in to register and unregister. More consistent, and we'll find bugs faster if we fault rather than returning an error that's ignored. Also makes internal functions acpi_device_unregister() and acpi_driver_detach() void, since nobody uses their returns either. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 193de0c79da580eb33a66113b62e2378fc1fb629 Author: KAMEZAWA Hiroyuki Date: Thu Apr 27 05:25:00 2006 -0400 ACPI: use for_each_possible_cpu() instead of for_each_cpu() for_each_cpu() actually iterates across all possible CPUs. We've had mistakes in the past where people were using for_each_cpu() where they should have been iterating across only online or present CPUs. This is inefficient and possibly buggy. We're renaming for_each_cpu() to for_each_possible_cpu() to avoid this in the future. Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit cf5eba53346fbfdf1b80e05ca3fd7fe2ec841077 Author: David Woodhouse Date: Sun May 14 04:06:24 2006 +0100 [JFFS2] Reduce excessive node count for syslog files. We currently get fairly poor behaviour with files which get many short writes, such as system logs. This is because we end up with many tiny data nodes, and the rbtree gets massive. None of these nodes are actually obsolete, so they are counted as 'clean' space. Eraseblocks can be entirely full of these nodes (which are REF_NORMAL instead of REF_PRISTINE), and still they count entirely towards 'used_size' and the eraseblocks can sit on the clean_list for a long time without being picked for GC. One way to alleviate this in the long term is to account REF_NORMAL space separately from REF_PRISTINE space, rather than counting them both towards used_size. Then these eraseblocks can be picked for GC and the offending nodes will be garbage collected. The short-term fix, though -- which probably makes sense even if we do eventually implement the above -- is to merge these nodes as they're written. When we write the last byte in a page, write the _whole_ page. This obsoletes the earlier nodes in the page _immediately_ and we don't even need to wait for the garbage collection to do it. Original implementation from Ferenc Havasi Signed-off-by: David Woodhouse commit 36e430951af0b0d1bdfd50ce22e70079d02646df Author: Ingo Molnar Date: Thu Apr 27 05:25:00 2006 -0400 sem2mutex: acpi, acpi_link_lock Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 415d320a2384bb80d2be98b1dfa41594e085012d Author: Len Brown Date: Sat May 13 21:35:56 2006 -0400 ACPI: delete unused acpi_bus_drivers_lock acpi_bus_drivers is protected by acpi_device_lock Signed-off-by: Len Brown commit 65c19bbd28cba587d9bd24feccf7272da18481a7 Author: Arjan van de Ven Date: Thu Apr 27 05:25:00 2006 -0400 sem2mutex: drivers/acpi/processor_perflib.c Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 151e76590f66f5406eb2e1f4270c5323f385d2e8 Author: David Woodhouse Date: Sun May 14 01:51:54 2006 +0100 [MTD] Fix legacy character sets throughout drivers/mtd, include/linux/mtd Signed-off-by: David Woodhouse commit 0f5ae3d2e9f49af55eb2a9b7cb54b4c0c2373017 Author: David Woodhouse Date: Sun May 14 01:40:50 2006 +0100 [MTD] Deal correctly with NOR chips which are smaller than the map window We used to calculate the number of chips to be zero, allocate an array of that size, then nasty things would happen when we attempt to access the first object in that zero-sized array. Now, if the number of _full_ chips that would fit into the map is zero, we allocate an array of one anyway, and then artificially reduce the total size of the resulting MTD device to fit in the map. Signed-off-by: David Woodhouse commit a6550e57f9d074511cf420bdb802ab5e56edc3bb Author: Jesper Juhl Date: Sun May 14 01:42:25 2006 +0200 mtd: fix memory leak in block2mtd_setup() There's a mem leak in drivers/mtd/devices/block2mtd.c::block2mtd_setup() We can leak 'name' allocated with kmalloc in 'parse_name' if leave via the 'parse_err' macro since it contains a return but doesn't do any freeing. Spotted by coverity checker as bug 615. Signed-off-by: Jesper Juhl Signed-off-by: David Woodhouse commit 552d9205186428a1e2a49ed577bcbba9f777af37 Author: David Woodhouse Date: Sun May 14 01:20:46 2006 +0100 [MTD] Fix module refcounting in NAND board drivers. The _board_ driver needs to be mtd->owner, and it in turn pins the nand.ko module. Fix them all to actually do that, and fix nand.ko not to overwrite it -- and also to check that the caller sets it, if the caller is a module. Signed-off-by: David Woodhouse commit 4f678a58d335291ce9213c049bbe16e6d24487ed Author: Jesper Juhl Date: Sun May 14 01:07:18 2006 +0200 mtd: fix memory leaks in phram_setup There are two code paths in drivers/mtd/devices/phram.c::phram_setup() that will leak memory. Memory is allocated to the variable 'name' with kmalloc() by the parse_name() function, but if we leave by way of the parse_err() macro, then that memory is never kfree()'d, nor is it ever used with register_device() so it won't be freed later either - leak. Found by the Coverity checker as #593 - simple fix below. Signed-off-by: Jesper Juhl Signed-off-by: David Woodhouse commit e0c7d7675331140e5186d2d1a0efce1d3877d379 Author: David Woodhouse Date: Sat May 13 18:07:53 2006 +0100 [MTD NAND] Indent all of drivers/mtd/nand/*.c. It was just too painful to deal with. Signed-off-by: David Woodhouse commit 6943f8af7d6583be57d67bba8b2644371f6a10ca Author: David Woodhouse Date: Sat May 13 16:14:26 2006 +0100 [MTD NAND] Reduce paranoia level when scanning for bad blocks on virgin chips We were scanning for 0xFF through the entire chip -- which takes a while when it's a 512MiB device as I have on my current toy. The specs only say we need to check certain bytes -- so do only that. Signed-off-by: David Woodhouse commit 21b9879bf2817aca343cdda11ade6a87f5373e74 Author: KaiGai Kohei Date: Sat May 13 15:22:29 2006 +0900 [JFFS2][XATTR] Fix obvious typo [2/2] jffs2-xattr-v5.2-02-fix_obvious_typo.patch Signed-off-by: KaiGai Kohei commit c8708a9275928cc8e77bd443cd12565dda0a3ded Author: KaiGai Kohei Date: Sat May 13 15:21:38 2006 +0900 [JFFS2][XATTR] Handling the duplicate JFFS2_NODETYPE_XATTR node cases. When jffs2_sum_process_sum_data() found a JFFS2_NODETYPE_XATTR which has duplicate xid and older version, an error was returned without appropriate process. In the result, mounting filesystem is failed. This patch fix this problem. If jffs2_setup_xattr_datum() returned -EEXIST, the caller marks this node as DIRTY_SPACE(). [1/2] jffs2-xattr-v5.2-01-fix-duplicate-xdatum.patch Signed-off-by: KaiGai Kohei commit dea80134dc4d54df52c0c59b0ba2bb5aa999bf30 Author: KaiGai Kohei Date: Sat May 13 15:20:24 2006 +0900 [JFFS2][XATTR] remove redundant pointer cast in acl.c remove redundant pointer cast in acl.c. [10/10] jffs2-xattr-v5.1-10-remove_pointer_cast.patch Signed-off-by: KaiGai Kohei commit 5a14959c0700cd389d9e7ba312e15c8e85255e1f Author: KaiGai Kohei Date: Sat May 13 15:19:36 2006 +0900 [JFFS2][XATTR] remove '__KERNEL__' from acl.h [9/10] jffs2-xattr-v5.1-09-remove__KERNEL__.patch Signed-off-by: KaiGai Kohei commit ee886b5df17f9791a72cf0afe7f6c0c079231ef8 Author: KaiGai Kohei Date: Sat May 13 15:19:03 2006 +0900 [JFFS2][XATTR] remove senseless comment remove senseless comment. [8/10] jffs2-xattr-v5.1-08-remove_senseless_comment.patch Signed-off-by: KaiGai Kohei commit 652ecc20d1f5b4fd745c185c940e5b3afb2a0711 Author: KaiGai Kohei Date: Sat May 13 15:18:27 2006 +0900 [JFFS2][XATTR] Unify each file header part with any jffs2 file. Unify each file header part with any jffs2 file. [7/10] jffs2-xattr-v5.1-07-unify_file_header.patch Signed-off-by: KaiGai Kohei commit 4470d0409bfe093abbf965dcc97e5c1450c80afb Author: KaiGai Kohei Date: Sat May 13 15:17:11 2006 +0900 [JFFS2][XATTR] '#include ' was added into xattr.h. '#include ' was added into xattr.h. because 'struct list_head' is used in this header file. [6/10] jffs2-xattr-v5.1-06-add_list.h.patch Signed-off-by: KaiGai Kohei commit 084702e00111eb9ffb6d8a5c1938b8e5423e40a8 Author: KaiGai Kohei Date: Sat May 13 15:16:13 2006 +0900 [JFFS2][XATTR] Remove jffs2_garbage_collect_xattr(c, ic) Remove jffs2_garbage_collect_xattr(c, ic). jffs2_garbage_collect_xattr_datum/ref() are called from gc.c directly. In original implementation, jffs2_garbage_collect_xattr(c, ic) returns with holding a spinlock if 'ic' is inode_cache. But it returns after releasing a spinlock if 'ic' is xattr_datum/ref. It looks so confusable behavior. Thus, this patch makes caller manage locking/unlocking. [5/10] jffs2-xattr-v5.1-05-update_xattr_gc.patch Signed-off-by: KaiGai Kohei commit 8f2b6f49c656dd4597904f8c20661d6b73cdbbeb Author: KaiGai Kohei Date: Sat May 13 15:15:07 2006 +0900 [JFFS2][XATTR] Remove 'struct list_head ilist' from jffs2_inode_cache. This patch can reduce 4-byte of memory usage per inode_cache. [4/10] jffs2-xattr-v5.1-04-remove_ilist_from_ic.patch Signed-off-by: KaiGai Kohei commit 8b0b339d46ca0105a9936e3caa3bac80b72de7a3 Author: KaiGai Kohei Date: Sat May 13 15:14:14 2006 +0900 [JFFS2][XATTR] Add a description about c->xattr_sem Add a description about the c->xattr_sem read/write semaphore into README.Locking. [3/10] jffs2-xattr-v5.1-03-append_README.Locking.patch Signed-off-by: KaiGai Kohei commit de1f72fab35d2b6215017690c6dc27b8f4aa14bc Author: KaiGai Kohei Date: Sat May 13 15:13:27 2006 +0900 [JFFS2][XATTR] remove typedef from posix_acl related definition. jffs2_acl_header, jffs2_acl_entry and jffs2_acl_entry_short were redefined with using 'struct' instead of 'typedef' in kernel implementation. [1/10] jffs2-xattr-v5.1-01-remove_typedef_kernel.patch Signed-off-by: KaiGai Kohei commit aa98d7cf59b5b0764d3502662053489585faf2fe Author: KaiGai Kohei Date: Sat May 13 15:09:47 2006 +0900 [JFFS2][XATTR] XATTR support on JFFS2 (version. 5) This attached patches provide xattr support including POSIX-ACL and SELinux support on JFFS2 (version.5). There are some significant differences from previous version posted at last December. The biggest change is addition of EBS(Erase Block Summary) support. Currently, both kernel and usermode utility (sumtool) can recognize xattr nodes which have JFFS2_NODETYPE_XATTR/_XREF nodetype. In addition, some bugs are fixed. - A potential race condition was fixed. - Unexpected fail when updating a xattr by same name/value pair was fixed. - A bug when removing xattr name/value pair was fixed. The fundamental structures (such as using two new nodetypes and exclusion mechanism by rwsem) are unchanged. But most of implementation were reviewed and updated if necessary. Espacially, we had to change several internal implementations related to load_xattr_datum() to avoid a potential race condition. [1/2] xattr_on_jffs2.kernel.version-5.patch [2/2] xattr_on_jffs2.utils.version-5.patch Signed-off-by: KaiGai Kohei Signed-off-by: David Woodhouse commit 5810452d00ae5fed7f720185d02d79ec9d15b91e Author: Len Brown Date: Sat May 13 01:12:15 2006 -0400 ACPI: silence ia64 build warning When building sim_defconfig, which does not define CONFIG_ACPI arch/ia64/kernel/acpi.c:71: warning: 'acpi_madt_rev' defined but not used really acpi.c should not be built when CONFIG_ACPI=n... Signed-off-by: Len Brown commit 9d75414b4fa7390975ef0e2b56ff40425657fe52 Author: David Woodhouse Date: Sat May 13 04:12:40 2006 +0100 [MTD NAND] Update CS553x NAND driver: Hardware ECC support, optimisations. - Implement HW ECC support, - Provide read_buf() and write_buf() routines using memcpy - Use on-flash bad block table - Fix module refcounting - Avoid read/modify/write in hwcontrol() - Minor cosmetic fixes Partly based on code and ideas from Tom Sylla Signed-off-by: David Woodhouse commit c3f8abf481c2d2b221b028f7369bc6dd39a9590e Author: David Woodhouse Date: Sat May 13 04:03:42 2006 +0100 [MTD NAND] Use vmalloc for buffer when scanning for bad blocks. These new chips have 128KiB blocks. Don't try to kmalloc that. Signed-off-by: David Woodhouse commit 4992a9e88886b0c5ebc3d27eb74d0344c873eeea Author: Egry Gábor Date: Fri May 12 17:35:02 2006 +0100 Trivial typo fixes in Kconfig files (MTD). Signed-off-by: Egry Gábor Signed-off-by: David Woodhouse commit 752870707f2818b5f0d94ca05e46cb0ffee6cbf9 Author: Kyungmin Park Date: Fri May 12 17:03:23 2006 +0300 OneNAND: fix block command typo We need to check block cmd only instead with comparing with cmd Signed-off-by: Kyungmin Park commit 493c646077ef0b8668ed71b8057f81cb7454af87 Author: Kyungmin Park Date: Fri May 12 17:03:07 2006 +0300 OneNAND: One-Time Programmable (OTP) support One Block of the NAND Flash Array memory is reserved as a One-Time Programmable Block memory area. Also, 1st Block of NAND Flash Array can be used as OTP. The OTP block can be read, programmed and locked using the same operations as any other NAND Flash Array memory block. OTP block cannot be erased. OTP block is fully-guaranteed to be a valid block. Signed-off-by: Kyungmin Park commit 3cecf69ecde22199699c4f0e609dfed2a487b674 Author: Kyungmin Park Date: Fri May 12 17:02:51 2006 +0300 OneNAND: Handle erase correctly in Double Density Package (DDP) There's erase bug in DDP. We need to add DDP select in erase Signed-off-by: Kyungmin Park commit 34c1060959b61a5bb2e97a88411446028cebfa7c Author: Kyungmin Park Date: Fri May 12 17:02:46 2006 +0300 OneNAND: Write oob area with aligned size, mtd->oobsize There's some problem with write oob in serveral platform. So we write oob with oobsize aligned (16bytes) instead of 3 bytes (from {2, 3}) Signed-off-by: Kyungmin Park commit 8e6ec69059ba0eecbb2226d3d9e45c6efe6fb82b Author: Kyungmin Park Date: Fri May 12 17:02:41 2006 +0300 OneNAND: Add write_oob verify function Signed-off-by: Jarkko Lavinen commit d9777f1c42bffff0d21cd029a2415776aa874e96 Author: Jarkko Lavinen Date: Fri May 12 17:02:35 2006 +0300 OneNand: Fix free byte positions. Some free byte positions at onenand_oob_64 were wrong. This was also reported by Christian Lehne. 3 byte slots are at 2+16*i and 2 byte slots at 14+16*i. Signed-off-by: Jarkko Lavinen commit 9c01f87db183403a4f603fe5180c57b82b54b4a1 Author: Kyungmin Park Date: Fri May 12 17:02:31 2006 +0300 OneNAND: handle byte access on BufferRAM Signed-off-by: Kyungmin Park commit 628bee6593107c466e28462f58c5fd5cd4163c7c Author: Kyungmin Park Date: Fri May 12 17:02:24 2006 +0300 OneNAND: Add touch_softlock_watchdog() Signed-off-by: Kyungmin Park commit 20ffdcb00a792073f6e620dc2c644b3c8fbab528 Author: Jesper Juhl Date: Fri May 12 11:55:51 2006 +0100 [JFFS2] Remove number of pointer dereferences in fs/jffs2/summary.c Reduce the nr. of pointer dereferences in fs/jffs2/summary.c Benefits: - micro speed optimization due to fewer pointer derefs - generated code is slightly smaller - better readability (The first two sound like a compiler problem but I'll go with the third. dwmw2). Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse commit 1867b7e3f85dc69695735ea4a4cd12027c565d89 Author: Jean-Luc Leger Date: Fri May 12 11:53:40 2006 +0100 [MTD] Fix invalid default value of CONFIG_MTD_PCMCIA_ANONYMOUS in Kconfig Default values for boolean and tristate options can only be 'y', 'm' or 'n'. This patch removes wrong default for MTD_PCMCIA_ANONYMOUS. Signed-off-by: Jean-Luc Leger Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse commit 7e59f2ccd7fc2424b2e70132ac613d16acae37da Author: Domen Puncer Date: Fri May 12 11:51:46 2006 +0100 [JFFS2] Remove obsolete histo.h This file hasn't actually been used since the very early days of JFFS2 when Arjan was playing with compression methods. It can go now. Signed-off-by: Domen Puncer Signed-off-by: Alexey Dobriyan Acked-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse commit f0ad11d060c7acf727ead8339432bdd2bfd7f868 Author: David Woodhouse Date: Fri May 12 11:40:13 2006 +0100 [MTD] Fix capitalisation in export of old doc2001.c initfunc Oops. Stupid StudlyCaps. Again. This driver is doubly-deprecated because is was subsumed into doc2000.c and _also_ we want people to start using the new NAND wrapper for these devices anyway. But ISTR there was still one person using it because something didn't work for them. Must chase that up and then I can kill this. Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse commit 179fdc3f8dec5757ddbebd95a1b493d65fa08671 Author: David Woodhouse Date: Thu May 11 22:35:28 2006 +0100 [MTD] Basic NAND driver for AMD/NatSemi CS5535/CS5536 Geode companion chip This lacks hardware ECC support and a few optimisations we're going to want fairly soon, but it works well enough to mount and use JFFS2. Signed-off-by: David Woodhouse commit 9011bff4bdc0fef1f9a782d7415c306ee61826c9 Author: Len Brown Date: Thu May 11 00:28:12 2006 -0400 ACPI: delete newly added debugging macros in processor_perflib.c Signed-off-by: Len Brown commit 2ca48a132167f9f12efba179382979aafde0ab36 Author: James Bottomley Date: Thu Apr 27 14:07:49 2006 -0500 [SCSI] fix proc_scsi_write to return "length" on success with remove-single-device case Problem spotted by: Suzuki K P A zero return on success isn't correct for filesystem write functions. They should either return negative error or the length of bytes consumed. Add code to convert our zero on success error return to return the length of bytes passed in. This fixes the following: $ echo "scsi remove-single-device 0 0 3 0" > /proc/scsi/scsi bash: echo: write error: No such device or address" Signed-off-by: James Bottomley commit b04ecae3d62edea2af49fd40ab12435b5ad8a492 Author: David Woodhouse Date: Wed May 10 16:16:13 2006 +0100 [MTD] Fix capitalisation in export of DiskOnChip Millennium initfunc Stupid StudlyCaps. Who did that? Signed-off-by: David Woodhouse commit 665b44aee34e9f2c64558df4ec01d40576e45651 Author: Mike Christie Date: Tue May 2 19:46:49 2006 -0500 [SCSI] iscsi: dequeue all buffers from queue debugged by wrwhitehead@novell.com patch and analysis by fujita.tomonori@lab.ntt.co.jp Only tcp_read_sock and recv_actor (iscsi_tcp_data_recv for us) see desc.count. It is is used just for permitting tcp_read_sock to read the portion of data in the socket. When iscsi_tcp_data_recv sees a partial header, it sets desc.count. However, it is possible that the next skb (containing the rest of the header) still does not come. So I'm not sure that this scheme is completely correct. Ideally, we should use the exact length of the data in the socket for desc.count. However, it is not so simple (see SIOCINQ in tcp_ioctl). So I think that iscsi_tcp_data_recv can just stop playing with desc.count and tell tcp_read_sock to read the all skbs. As proposed already, if iscsi_tcp_data_ready sets desc.count to non-zero, tcp_read_sock does that. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 8d2860b3c3e933304f49171770658c00ed26fd79 Author: Mike Christie Date: Tue May 2 19:46:47 2006 -0500 [SCSI] iscsi: increment expstatsn during login debugged by Ming and Rohan: The problem Ming and Rohan debugged was that during a normal session login, open-iscsi is not incrementing the exp_statsn counter. It was stuck at zero. From the RFC, it looks like if the login response PDU has a successful status then we should be incrementing that value. Also from the RFC, it looks like if when we drop a connection then reconnect, we should be using the exp_statsn from the old connection in the next relogin attempt. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit be2df72e7ec5fa5e6e1ccccab6cef97ecbb9c191 Author: Or Gerlitz Date: Tue May 2 19:46:43 2006 -0500 [SCSI] iscsi: align printks align printk output Signed-off-by: Or Gerlitz Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit ed2abc7ff19dc99c6242a70f8578a17b2ff0d0ce Author: Mike Christie Date: Tue May 2 19:46:40 2006 -0500 [SCSI] iscsi: fix manamgement task oops from patmans@us.ibm.com and michaelc@cs.wisc.edu Fix bugs when forcing a mgmt task to fail and allow session recovery to cleanup the session/connection of any running mgmt tasks. When called during the in login state. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 264faaaa12544e7914928ad57ccba21907cad56b Author: Or Gerlitz Date: Tue May 2 19:46:36 2006 -0500 [SCSI] iscsi: add transport end point callbacks add transport end point callbacks so iscsi drivers that cannot connect from userspace, like iscsi tcp, using sockets do not have to implement their own socket infrastructure. Signed-off-by: Or Gerlitz Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 32e62c636a728cb39c0b3bd191286f2ca65d4028 Author: Bjorn Helgaas Date: Fri May 5 17:19:50 2006 -0600 [IA64] rework memory attribute aliasing This closes a couple holes in our attribute aliasing avoidance scheme: - The current kernel fails mmaps of some /dev/mem MMIO regions because they don't appear in the EFI memory map. This keeps X from working on the Intel Tiger box. - The current kernel allows UC mmap of the 0-1MB region of /sys/.../legacy_mem even when the chipset doesn't support UC access. This causes an MCA when starting X on HP rx7620 and rx8620 boxes in the default configuration. There's more detail in the Documentation/ia64/aliasing.txt file this adds, but the general idea is that if a region might be covered by a granule-sized kernel identity mapping, any access via /dev/mem or mmap must use the same attribute as the identity mapping. Otherwise, we fall back to using an attribute that is supported according to the EFI memory map, or to using UC if the EFI memory map doesn't mention the region. Signed-off-by: Bjorn Helgaas Signed-off-by: Tony Luck commit 83ea4ef213628683e5a63f2987a91044ab868051 Author: David Woodhouse Date: Mon May 8 22:58:25 2006 +0100 Export cfi_cmdset_0020 and cfi_cmdset_0002 with EXPORT_SYMBOL_GPL Signed-off-by: David Woodhouse commit 6f18a022fb311f07f3b32f2c0e1b5c9477dc4439 Author: David Woodhouse Date: Mon May 8 22:40:05 2006 +0100 Finally remove the obnoxious inter_module_xxx() This was already a bad plan when I argued against adding it in the first place. Good riddance. Signed-off-by: David Woodhouse commit a15bdeef108d282e540e202fc3c3e4bdf9692074 Author: David Woodhouse Date: Mon May 8 22:35:05 2006 +0100 Remove use of inter_module_crap in NOR flash chip drivers. Signed-off-by: David Woodhouse commit 396674e58fb9d01b7768ccb8db181aea8ebead0e Author: David Woodhouse Date: Mon May 8 17:10:11 2006 +0100 Fix non-modular case for DiskOnChip probe Signed-off-by: David Woodhouse commit 80b9192ee032f919da1b6e8b305c7cc9881b0907 Author: David Woodhouse Date: Mon May 8 15:51:57 2006 +0100 Move user-visible parts of drivers/s390/crypto/z90crypt.h to include/asm-s390 Also remove Bob Burroughs' email address, since it's no longer valid. Acked-by: Eric D Rossman Signed-off-by: David Woodhouse commit 5e535429a9117b8b6219da0e0cb087f52c0c9597 Author: David Woodhouse Date: Mon May 8 14:05:05 2006 +0100 Remove inter_module_xxx() from DiskOnChip drivers. Finally putting it back how it was before Keith got at it -- yay :) Signed-off-by: David Woodhouse commit 73566edf9b91dd085ddb12033d0ea7288979dd10 Author: Lennert Buytenhek Date: Sun May 7 17:16:36 2006 +0100 [MTD] Convert physmap to platform driver After dwmw2 let me know it ought to be done, I rewrote the physmap map driver to be a platform driver. I know zilch about the driver model, so I probably botched it in some way, but I've done some tests on an ixp23xx board which uses physmap, and it all seems to work. In order to not break existing physmap users, I've added some compat code that will instantiate a platform device iff CONFIG_MTD_PHYSMAP_LEN is defined and != 0. Also, I've changed the default value for CONFIG_MTD_PHYSMAP_LEN to zero, so that people who inadvertently compile in physmap (or new, platform-style, users of physmap) don't get burned. This works pretty well -- the new physmap driver is a drop-in replacement for the old one, and works on said ixp23xx board without any code changes needed. (This should hold as long as users don't touch 'physmap_map' directly.) Once all physmap users have been converted to instantiate their own platform devices, the compat code can go. (Or we decide that we can change all the in-tree users at the same time, and never merge the compat code.) Signed-off-by: Lennert Buytenhek Signed-off-by: David Woodhouse commit c0f1fe00c3923135b2c2f443448585482da8a53e Author: David Woodhouse Date: Sat May 6 19:47:57 2006 +0100 Revert include/media changes: Mauro says those ioctls are only used in-kernel(!) Reverts commit eba7f3bdb6344adee8a3d044f405ed38f5c66c6b Signed-off-by: David Woodhouse commit 422138dd68202fbd8ca9fb0df65e92d733249374 Author: Dmitry Bazhenov Date: Fri May 5 22:46:49 2006 +0100 [JFFS2] Fix race in setting file attributes It seems like there is a potential race in the function jffs2_do_setattr() in the case when attributes of a symlink are updated. The symlink metadata is read without having f->sem locked. The following patch should fix the race. Signed-off-by: Dmitry Bazhenov Signed-off-by: David Woodhouse commit f03cc4fd927357bd4b3cea1a053b9f9d8f1731cc Author: Stefano Brivio Date: Fri May 5 03:02:25 2006 +0200 [PATCH] bcm43xx: add PCI ID for bcm4319 Add PCI ID for bcm4319. Signed-off-by: Stefano Brivio Signed-off-by: John W. Linville commit ec000ca9d4b23dfb67b70bdf72950e76728c74d9 Author: Stefano Brivio Date: Fri May 5 02:58:29 2006 +0200 [PATCH] bcm43xx: fix whitespace Fix whitespace. Signed-off-by: Stefano Brivio Signed-off-by: John W. Linville commit 8462fe3cd9ec8951871a20a4dfe36321ab075964 Author: Daniel Drake Date: Mon May 1 22:45:50 2006 +0100 [PATCH] softmac: suggest per-frame-type TX rate This patch is the first step towards rate control inside softmac. The txrates substructure has been extended to provide different fields for different types of packets (management/data, unicast/multicast). These fields are updated on association to values compatible with the access point we are associating to. Drivers can then use the new ieee80211softmac_suggest_txrate() function call when deciding which rate to transmit each frame at. This is immensely useful for ZD1211, and bcm can use it too. The user can still specify a rate through iwconfig, which is matched for all transmissions (assuming the rate they have specified is in the rate set required by the AP). At a later date, we can incorporate automatic rate management into the ieee80211softmac_recalc_txrates() function. This patch also removes the mcast_fallback field. Sam Leffler pointed out that this field is meaningless, because no driver will ever be retransmitting mcast frames (they are not acked). Signed-off-by: Daniel Drake Acked-by: Johannes Berg Signed-off-by: John W. Linville commit 461c078c9cdfc1d24a436a87daed90f18c3b0d0d Author: Pavel Roskin Date: Mon May 1 02:13:33 2006 -0400 [PATCH] orinoco: don't put PCI resource data to the network device The resource data in the network device is intended for ISA and other older busses, but not for PCI. Don't put PCI data there. Don't (ab)use the network device for keeping the IRQ number. Retire orinoco_pci_setup_netdev(), and print some minimal information to the kernel log instead, identifying the network device and the driver mostly to identify problems at startup. Scripts should rely on sysfs. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 95047dd6d00ad00e7f1f632db6b8ecaa704cfc7e Author: Pavel Roskin Date: Mon May 1 02:13:30 2006 -0400 [PATCH] orinoco: eliminate the suspend/resume functions if CONFIG_PM is unset Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 6cbaa330f1022abfc7419aaa11ee1a9291f0beb0 Author: Pavel Roskin Date: Mon May 1 02:13:28 2006 -0400 [PATCH] orinoco: simplify locking, fix error handling in PCMCIA resume Don't use flags in the spinlocks - the PCMCIA resume functions may not be called under lock. Don't ignore any errors. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 9a568da2097ad3701ca575cb6d360d56ffeee446 Author: Pavel Roskin Date: Mon May 1 02:13:26 2006 -0400 [PATCH] orinoco: report more relevant data on startup Report only the first I/O window and IRQ, and also add the driver name. The second I/O window, Vpp and configuration index are not interesting to most users. They can be found by PCMCIA debug tools if needed. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit e4f4f98efdb4619ab95eb724fd5e0c4675307cc1 Author: Pavel Roskin Date: Mon May 1 02:13:24 2006 -0400 [PATCH] orinoco: unregister network device before releasing PCMCIA resources Hardware resources should not be made available to other devices while the network device is still registered. Also remove the related debug statements. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 6274115ce9f0c87068761b2ba5b0b2f7d13c17cf Author: Adrian Bunk Date: Thu Apr 27 02:33:42 2006 -0700 [PATCH] ieee80211_wx.c: remove dead code Since sec->key_sizes[] is an u8, len can't be < 0. Spotted by the Coverity checker. Signed-off-by: Adrian Bunk Cc: "John W. Linville" Signed-off-by: Andrew Morton Signed-off-by: John W. Linville commit 6d92f83ffafe8e2ce105c3ec5696c62d6fcebcee Author: Daniel Drake Date: Mon May 1 22:23:27 2006 +0100 [PATCH] softmac: deauthentication implies deassociation The 802.11 specs state that deauthenticating also implies disassociating. This patch implements that, which improve the behaviour of SIOCSIWMLME. Signed-off-by: Daniel Drake Acked-by: Johannes Berg Signed-off-by: John W. Linville commit 0c6157a371f72b91bd9d2f72c2e65e2bde4cdf39 Author: Michal Schmidt Date: Tue May 2 23:29:55 2006 +0200 [PATCH] wireless/airo: minimal WPA awareness Running Linux 2.6.17-rc3-mm1 which has this patch included I get this interesting message: airo(eth0): WPA unsupported (only firmware versions 5.30.17 and greater support WPA. Detected 5.30.17) airo_test_wpa_capable assumes that the softSubVer part of the firmware version number is coded in BCD. Apparently, that's not true. I have firmware version 5.30.17 and cap_rid.softSubVer is 0x11==17. Signed-off-by: Michal Schmidt Signed-off-by: John W. Linville commit 7e990266c845d7f712c96013891aaf74baef198f Author: Kumar Gala Date: Fri May 5 00:02:08 2006 -0500 powerpc: provide ppc_md.panic() for both ppc32 & ppc64 Allow boards to provide a panic callback on ppc32. Moved the code to sets this up into setup-common.c so its shared between ppc32 & ppc64. Also moved do_init_bootmem prototype into setup.h. Signed-off-by: Kumar Gala commit 05f75fd3bb92d9f5eaa8620195ff77a89431f2d2 Author: David Woodhouse Date: Thu May 4 17:50:04 2006 +0100 Include and use __uXX types in Signed-off-by: David Woodhouse commit cb8c1fdc0cf703e3297499dcd1a4b20b27570a7a Author: David Woodhouse Date: Thu May 4 17:32:44 2006 +0100 Use __uXX types in , include too Signed-off-by: David Woodhouse commit de654c97861c314fd0fc0b6a6dd1bc4202e00e42 Author: David Woodhouse Date: Thu May 4 17:28:26 2006 +0100 Remove private struct dx_hash_info from public view in Signed-off-by: David Woodhouse commit 7ee7d0e3186e2ad2a872436b5a272a814ea5cb0f Author: David Woodhouse Date: Thu May 4 15:49:24 2006 +0100 Include and use __uXX types in Signed-off-by: David Woodhouse commit 5da0458900bb5f56eb5e7a7c5ed275b5eaf51762 Author: David Woodhouse Date: Thu May 4 15:07:59 2006 +0100 Use __uXX types in for struct divert_blk et al. Signed-off-by: David Woodhouse commit 5ee882f153a49098a12f6b26f153ba12a33d767a Author: David Woodhouse Date: Thu May 4 12:39:12 2006 +0100 Use __u32 for elf_addr_t in , not u32. It's user-visible. Signed-off-by: David Woodhouse commit 2c88f4a8bc4276013f7eee7824056d9cecccadb1 Author: David Woodhouse Date: Thu May 4 12:07:37 2006 +0100 Remove PPP_FCS from user view in , remove __P mess entirely Signed-off-by: David Woodhouse commit 90abbae2d35b3dc55fd39f8ab04acaf3da5cdc0a Author: David Woodhouse Date: Thu May 4 02:55:50 2006 +0100 Use __uXX types in user-visible structures in Signed-off-by: David Woodhouse commit 8e1515df578e4665b77d1e0eec3c8b041d159b23 Author: David Woodhouse Date: Thu May 4 01:42:36 2006 +0100 Don't use 'u32' in user-visible struct ip_conntrack_old_tuple. Signed-off-by: David Woodhouse commit 56b192c337ddad05dee83c9bea079f41df775990 Author: David Woodhouse Date: Thu May 4 01:18:33 2006 +0100 Use __uXX types for S390 DASD volume label definitions which are user-visible Signed-off-by: David Woodhouse commit 9a798c076fcc26f29bf9e9d350a17cdeff0a314f Author: David Woodhouse Date: Thu May 4 01:17:41 2006 +0100 S390 BIODASDREADCMB ioctl should use __u64 not u64 type. Signed-off-by: David Woodhouse commit ac12c0fc8c08a14bfa263c3a478ee82ad3e346d2 Author: David Woodhouse Date: Thu May 4 00:59:14 2006 +0100 Remove unneeded inclusion of from Signed-off-by: David Woodhouse commit eba7f3bdb6344adee8a3d044f405ed38f5c66c6b Author: David Woodhouse Date: Thu May 4 00:44:14 2006 +0100 Fix private integer types used in V4L2 ioctls. Signed-off-by: David Woodhouse commit 888855dc00c302c88663ec256bb422f4b27046f2 Author: David Woodhouse Date: Thu May 4 00:42:42 2006 +0100 Fix integer types in SNDRV_HDSP_IOCTL_GET_PEAK_RMS ioctl We should be using __u32 et al, not the kernel-private types. Signed-off-by: David Woodhouse commit 423bc7b22bdeb73efeabfcf91d8a459ac33088f1 Author: David Woodhouse Date: Thu May 4 00:41:02 2006 +0100 Restore __attribute_const__ to user-visibility in linux/compiler.h...for now Signed-off-by: David Woodhouse commit cbb9a56177b16294ed347ba7fcb1c66c8adb5dc4 Author: David Woodhouse Date: Wed May 3 13:07:27 2006 +0100 Move jffs2_fs_i.h and jffs2_fs_sb.h from include/linux/ to fs/jffs2/ Signed-off-by: David Woodhouse commit 5d3213cc8f4d6244b76ee0c4ab73a97d5d2ee956 Author: Ananda Raju Date: Fri Apr 21 19:23:26 2006 -0400 [PATCH] s2io: init/shutdown fixes Hi, The following patch contains fix related to init and shutdown of adapter as per user guide. The list of changes include 1. shutdown gracefully. 2. Need to mask/unmask interrupts in ISR required fro Xframe-E 3. Tx FIFO should be enabled after WRR calender programming Signed-off-by: Ananda Raju Signed-off-by: Jeff Garzik commit bd1034f035f3679fbc753a1368559c0b4b89f8f6 Author: Ananda Raju Date: Fri Apr 21 19:20:22 2006 -0400 [PATCH] s2io: additional stats Hi, This patch contains additional statistics counters added to s2io driver these statistics are very much usefull in debugging the driver. Signed-off-by: Ananda Raju Signed-off-by: Jeff Garzik commit c92ca04b2a21852fbc6842e8a7c6fff3ae255b30 Author: Ananda Raju Date: Fri Apr 21 19:18:03 2006 -0400 [PATCH] s2io: fixes Hi, This patch contains some of the bug fixes done for S2io driver. Following are the brief description of changes 1. Continuing with initialization if we get minimum required MSI-X vectors 2. fix for ethtool online link test fails 3. make wait_for_cmd_complete generic for all command status registers 4. Print "Device is on PCI-E bus" for Xframe-E card 5. CX4 requires additional delay after sw_reset, and requires higher value for igp 6. Fixed panic due to non-TCP and/or LLC/SNAP traffic in case of lro 7. remove legacy code for old transponder 8. SPECIAL_REG_WRITE made to use 32-bit writes irrespective of system type 9. handle link interrupt as per user guide for Xframe II 10. Wait till all interrupts hndled Signed-off-by: Ananda Raju Signed-off-by: Jeff Garzik commit 9dc737a77353920a67337aa627f7d9dae8dade05 Author: Ananda Raju Date: Fri Apr 21 19:05:41 2006 -0400 [PATCH] s2io: input parms, output messages update hi, This patch contains the modification and bug fixes with respect to input parameters and outupt dmesages. following is brief description of the changes. 1. Set default values for rx_ring_sz[0..7] and tx_fifo_len[0..7] 2. verify few basic load parameters 3. read product description from VPD 4. clean up of dmesg when driver is loaded Signed-off-by: Ananda Raju Signed-off-by: Jeff Garzik commit 863c11a91e4507c3ff44783a75a5433c8cf7700e Author: Ananda Raju Date: Fri Apr 21 19:03:13 2006 -0400 [PATCH] s2io: performance improvements hi, This patch contains all the changes that were done to improve performance of s2io driver. one line description of the changes are 1. For Non NAPI case the rx interrupt handler is being called unconditionally 2. code optimization and adding prefetch skb->data 3. Remove modulo operations in fast path 4. Enable Group Reads and set backoff interval to 0x1000 5. correct PIC_CNTL_SHARED_SPLITS macro definition, and reduce pause parameter 6. Corrected logic of identifying rx buffer level in rx_buffer_level() 7. fix DMA map and unmap done with different sizes in 1-buf mode 8. Removed forcible disabling of ERO 9. Send up the packets with transfer code = 0x5 Signed-off-by: Ananda Raju Signed-off-by: Jeff Garzik commit 4f79c3ffc6e04623711e86cf9a0e09e4aad8cb36 Author: David Woodhouse Date: Tue May 2 10:41:25 2006 +0100 Guard some of linux/compiler.h with #ifdef __KERNEL__ Signed-off-by: David Woodhouse commit aa783a8f31c79f493bd49ba926b171b79b9839fb Author: Andrew Morton Date: Mon May 1 09:41:47 2006 +0100 Update UML kernel/physmem.c to use rb_parent() accessor macro Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse commit 7d532dd50de1c0cd7d15ba06ad7261e13474fef2 Author: Lennert Buytenhek Date: Sun Apr 30 10:36:38 2006 +0200 ts72xx NAND driver The TS-72xx is a series of embedded single board computers from Technologic Systems based on the Cirrus ep93xx (arm920t based) CPU. The TS-7200 uses NOR flash, while all the other models in the series (TS-7250, TS-7260) use NAND flash -- included is a driver for the NAND flash on those boards. Signed-off-by: Lennert Buytenhek Signed-off-by: David Woodhouse commit fbbc21c6a491503e55e08e3f7c4629c1337ea1cc Author: Daniel Drake Date: Sat Apr 29 11:41:44 2006 +0100 mtd: SC520CDP should depend on MTD_CONCAT Toralf Förster found a compile error when CONFIG_MTD_SC520CDP=y and CONFIG_MTD_CONCAT=n: drivers/built-in.o: In function `init_sc520cdp': sc520cdp.c:(.init.text+0xb4de): undefined reference to `mtd_concat_create' drivers/built-in.o: In function `cleanup_sc520cdp': sc520cdp.c:(.exit.text+0x14bc): undefined reference to `mtd_concat_destroy' This patch fixes it. Signed-off-by: Daniel Drake Signed-off-by: Josh Boyer commit 5a43ee65620d628ba04deecf241b63b2410b97f2 Author: Will Schmidt Date: Wed Apr 26 11:09:46 2006 -0500 [PATCH] nvram_print_partitions cosmetic fixup This is a cosmetic fixup. When printing the nvram partition table, the first couple entries have a shorter 'index' value than the others, so table is a bit askew. This change makes the table look pretty. Tested on pseries and g5. Footnote: yes, this table is normally hidden behind a DEBUG_NVRAM #define. Signed-off-by: Will Schmidt Signed-off-by: Paul Mackerras commit c5c4591375a10f6bc1bc55d86af7764033b10367 Author: Jeremy Kerr Date: Fri Apr 28 16:37:47 2006 +0800 [PATCH] powerpc: cell: use kzalloc in alloc_spu_context() Use kzalloc when allocating a new spu context, rather than kmalloc + zeroing. Booted & tested on cell. Signed-off-by: Jeremy Kerr Signed-off-by: Paul Mackerras commit a74e5e5facb854ab4be9e0320e0f65074012df9b Author: Olof Johansson Date: Fri Apr 28 08:57:09 2006 -0500 [PATCH] powerpc iommu: minor cleanup A couple of minor renames: * The iommu_table is no longer a part of the device node structure, so devnode_table is misleading * Rename struct device *-variables to hwdev Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit bc97ce951cfb697eaac9d5b6a2fbe4544fdf1a7c Author: Olof Johansson Date: Fri Apr 28 22:51:59 2006 -0500 [PATCH] powerpc: kill union tce_entry It's been long overdue to kill the union tce_entry in the pSeries/iSeries TCE code, especially since I asked the Summit guys to do it on the code they copied from us. Also, while I was at it, I cleaned up some whitespace. Built and booted on pSeries, built on iSeries. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit c7f0e8cb5654a50986c6097b3c0cca972e406899 Author: Stephen Rothwell Date: Thu Apr 27 17:23:32 2006 +1000 [PATCH] powerpc: merge the rest of the vio code Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit dd721ffd95d5e1516380da0b254ef737582a258f Author: Stephen Rothwell Date: Thu Apr 27 17:21:46 2006 +1000 [PATCH] powerpc: use a common vio_match_device routine This requires the compatible properties having vaules that are empty strings instead of just being empty properties. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit e10fa77368dff31140451fac04d78d9f51f0f3ac Author: Stephen Rothwell Date: Thu Apr 27 17:18:21 2006 +1000 [PATCH] powerpc: use the device tree for the iSeries vio bus probe As an added bonus, since every vio_dev now has a device_node associated with it, hotplug now works. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 95a1ca6cd8e702a19ee56efae522a5816a56a205 Author: Stephen Rothwell Date: Thu Apr 27 17:09:02 2006 +1000 [PATCH] powerpc: add all the iSeries virtual devices to the device tree We do this by putting them in the flattened device tree at setup time. This required the flattened device tree blob to be made bigger. Currenly we don't do anything with these. Also make a function static. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit c3ce7e203af5d8eab7c3390fc991a1fcb152f741 Author: David Woodhouse Date: Sat Apr 29 01:53:47 2006 +0100 Sanitise ethtool.h and mii.h for userspace. They shouldn't be using 'u32' et al in structures which are used for communication with userspace. Switch to the proper types (__u32 etc). Signed-off-by: David Woodhouse commit 56142536868a2be34f261ed8fdca1610f8a73fbd Author: David Woodhouse Date: Sat Apr 29 01:51:47 2006 +0100 Remove unneeded _syscallX macros from user view in asm-*/unistd.h These aren't needed by glibc or klibc, and they're broken in some cases anyway. The uClibc folks are apparently switching over to stop using them too (now that we agreed that they should be dropped, at least). Signed-off-by: David Woodhouse commit 34c278d3913a15b64943e8c40a16b4f732cc7c59 Author: David Woodhouse Date: Sat Apr 29 01:49:06 2006 +0100 Remove 'extern int errno;' from public view in linux/unistd.h Signed-off-by: David Woodhouse commit c7afb48eb5147be9eb9789b4161462d246451ac2 Author: David Woodhouse Date: Sat Apr 29 01:48:16 2006 +0100 Remove struct input_device_id from public view in linux/input.h It uses kernel_ulong_t but can't be wrapped in __KERNEL__ because it's used from scripts/mod/file2alias.c -- but we _can_ hide it inside header manually too (and it doesn't generally exist for userspace). Signed-off-by: David Woodhouse commit 778382e08cce51b6268ca49449e5bd70c8413799 Author: David Woodhouse Date: Sat Apr 29 01:46:02 2006 +0100 Don't include in public part of linux/pci.h Signed-off-by: David Woodhouse commit acc429a517bd11fdcac9bea97d082d26231beb92 Author: David Woodhouse Date: Thu Apr 27 16:46:56 2006 +0100 linux/blkpg.h needs for __user Signed-off-by: David Woodhouse commit cd469e0cc67b74ba41daec335ea72baedb750b80 Author: David Woodhouse Date: Thu Apr 27 15:48:08 2006 +0100 Exclude asm-generic/{page,memory_model}.h from user bits of i386/x86_64 page.h Signed-off-by: David Woodhouse commit ad1588798620901c12ba86c71865150a4eb727bf Author: David Woodhouse Date: Thu Apr 27 06:57:23 2006 +0100 Add standard include guard to asm-generic/signal and use compiler.h Signed-off-by: David Woodhouse commit 274f5946dcb7c970455067be9e13a22174787592 Author: David Woodhouse Date: Thu Apr 27 04:47:10 2006 +0100 Don't include implementation details from asm-s390/ptrace.h and page.h Signed-off-by: David Woodhouse commit b7b3c76a0a21c5a98124e90c47c488f7e4166f87 Author: David Woodhouse Date: Thu Apr 27 00:12:56 2006 +0100 Sanitise linux/sched.h for userspace consumption There was a whole load of crap exposed which should have been inside the existing #ifdef __KERNEL__ part. Also hide struct sched_param for now, since glibc has its own and doesn't like being given ours (yet). Signed-off-by: David Woodhouse commit f001e47f83db18a9f202f25c0255b4d11ebe468b Author: David Woodhouse Date: Thu Apr 27 00:11:01 2006 +0100 Sanitise linux/audit.h for userspace consumption, split elf-em.h from elf.h Don't include outside __KERNEL__, and split the EM_xxx definitions out of elf.h into elf-em.h so that audit.h can include just that and not pollute the namespace any further than it needs to. Signed-off-by: David Woodhouse commit 62c4f0a2d5a188f73a94f2cb8ea0dba3e7cf0a7f Author: David Woodhouse Date: Wed Apr 26 12:56:16 2006 +0100 Don't include linux/config.h from anywhere else in include/ Signed-off-by: David Woodhouse commit 089f26d5e31b7bf42a9a8fefec08b30cd27f4b0e Author: David Woodhouse Date: Tue Apr 25 15:29:01 2006 +0100 Don't include and from linux/socket.h Signed-off-by: David Woodhouse commit d85004eb15a635b3937e91d1dbadb1d37541983c Author: David Woodhouse Date: Tue Apr 25 15:18:46 2006 +0100 Don't include private headers from user-visible part of linux/ext3_fs.h Signed-off-by: David Woodhouse commit 52a78c1cae382ff5684f3970848676de12449745 Author: David Woodhouse Date: Tue Apr 25 15:18:31 2006 +0100 Don't include private headers from user-visible part of linux/ext2_fs.h Signed-off-by: David Woodhouse commit 19b3bd667b6a4fc4c164c743492cec08d91d74a5 Author: David Woodhouse Date: Tue Apr 25 15:18:05 2006 +0100 Don't include private headers from user-visible part of linux/smb_fs.h Signed-off-by: David Woodhouse commit 1af042271f9bf7601f7ecf4d328ccde3a44d2c72 Author: David Woodhouse Date: Tue Apr 25 15:16:44 2006 +0100 Sanitise linux/sunrpc/debug.h for userspace consumption Move some inclusion of private header files and the definition of RPC_DEBUG inside the existing #ifdef __KERNEL__ Signed-off-by: David Woodhouse commit eae19a762de975e109394b1edcba6587323c7d1a Author: David Woodhouse Date: Tue Apr 25 15:14:50 2006 +0100 Don't export CONFIG_COMPAT stuff in linux/usbdevice_fs.h to userspace Signed-off-by: David Woodhouse commit 468db83658f776ec87a953778f18611301668148 Author: David Woodhouse Date: Tue Apr 25 15:00:56 2006 +0100 Don't include from user-visible part of linux/wanrouter.h Signed-off-by: David Woodhouse commit c6e82e72361db12759fdcdbfd3b598acb6b34b07 Author: David Woodhouse Date: Tue Apr 25 15:00:06 2006 +0100 Move comment in mtd-abi.h to stop confusing unifdef Currently, unifdef removes the comment which starts on the same line as the #ifdef __KERNEL__, but leaves the second line of the comment in place. Move the comment onto a separate line. Signed-off-by: David Woodhouse commit 7ab2febd4d3c6f50545cee11a116536a09748d59 Author: David Woodhouse Date: Tue Apr 25 14:55:46 2006 +0100 Don't include private headers from user-visible part of linux/signal.h Signed-off-by: David Woodhouse commit 8ffbc759a5b655feb69435c4dfa857c391f9dcc8 Author: David Woodhouse Date: Tue Apr 25 14:55:13 2006 +0100 Don't include from user-visible part of linux/sem.h Signed-off-by: David Woodhouse commit a3b6714e1744a5e841753d74aca1de5972f24e6d Author: David Woodhouse Date: Tue Apr 25 14:54:40 2006 +0100 Partially sanitise linux/sched.h for userspace consumption For now, just make sure all inclusion of private header files is done within #ifdef __KERNEL__. There'll be more to clean up later. Signed-off-by: David Woodhouse commit 98ca79d52bc34b8dfff729bc8559dbb918c9d02a Author: David Woodhouse Date: Tue Apr 25 14:52:51 2006 +0100 Don't include from user-visible part of reiserfs_xattr.h Signed-off-by: David Woodhouse commit 0409d3a332fc4347efba535a5003943f2a4aa1ca Author: David Woodhouse Date: Tue Apr 25 14:52:13 2006 +0100 Don't include private headers from user-visible parts of linux/quota.h Signed-off-by: David Woodhouse commit 997b7af2fe0810ca82a2f801a295218b51426e5a Author: David Woodhouse Date: Tue Apr 25 14:51:45 2006 +0100 Don't include private headers from user-visible parts of include/linux/nfs*.h Signed-off-by: David Woodhouse commit eacf17bdbc8e6f24fe46cd7e10fb9a657f060d08 Author: David Woodhouse Date: Tue Apr 25 14:46:09 2006 +0100 Don't include from user-visible part of linux/net.h Signed-off-by: David Woodhouse commit 77597ad663f9e2d40a89c6e27824701bb5fabb83 Author: David Woodhouse Date: Tue Apr 25 14:26:46 2006 +0100 Don't include from user-visible part of linux/msg.h Signed-off-by: David Woodhouse commit 58908d093e77224973b3f7bf54470d51949ff110 Author: David Woodhouse Date: Tue Apr 25 14:26:26 2006 +0100 Don't include private files from user-visible part of linux/ncp_fs.h Signed-off-by: David Woodhouse commit 9cdcb56636717ccb935dc66c5d56681eaa5941c1 Author: David Woodhouse Date: Tue Apr 25 14:18:07 2006 +0100 Sanitise linux/mman.h for userspace consumption It only really needs to define a few constants and include when it's used by userspace. Move the rest within #ifdef __KERNEL__ Signed-off-by: David Woodhouse commit 8e442735ae6e2e1c857fb0c746027da8d8e40a81 Author: David Woodhouse Date: Tue Apr 25 14:16:14 2006 +0100 Remove gratuitous inclusion of from linux/isdn/tpam.h Signed-off-by: David Woodhouse commit 2e0e1f9f1c478ee14fb60524024f7b730df76912 Author: David Woodhouse Date: Tue Apr 25 14:15:44 2006 +0100 Don't include from user-visible part of linux/ipmi.h Signed-off-by: David Woodhouse commit a1b9298e55d2395be4ac25de3340b6eee01c6f67 Author: David Woodhouse Date: Tue Apr 25 14:14:52 2006 +0100 Sanitise linux/i2c.h for userspace consumption It was unconditionally including a whole bunch of headers which aren't user-visible, and also exposing a lot of private internal stuff of its own. Also fix some legacy character set to UTF-8 while we're at it. Signed-off-by: David Woodhouse commit 5a570cc0a41bd316afc91ba2c7151fed70d10b31 Author: David Woodhouse Date: Tue Apr 25 14:10:40 2006 +0100 Sanitise linux/i2c-algo-ite.h for userspace consumption It doesn't need to include i2c.h, because a forward declaration of struct i2c_adapter is perfectly sufficient. And it can be inside #ifdef __KERNEL__ along with the kernel-internal structure definition. Signed-off-by: David Woodhouse commit 34186efc17025520a53a48468338003d238a77d7 Author: David Woodhouse Date: Tue Apr 25 14:07:57 2006 +0100 Include various private files only from within __KERNEL__ in genhd.h Signed-off-by: David Woodhouse commit f2999e4ea41d6ec6252d3b6d275b40d468a3c07e Author: David Woodhouse Date: Tue Apr 25 14:07:02 2006 +0100 Export only the appropriate GS_xxx flags to userspace from generic_serial.h Signed-off-by: David Woodhouse commit 25478bb26f2be1504112b764047105811a52c3cb Author: David Woodhouse Date: Tue Apr 25 13:59:30 2006 +0100 Use __KERNEL__ to hide kernel-private bits of linux/gameport.h Signed-off-by: David Woodhouse commit 72b9760b65cbe0d24e668c34c8fefb2ba417f14b Author: David Woodhouse Date: Tue Apr 25 13:58:23 2006 +0100 Don't include agp_backend.h in user-visible part of agpgart.h Signed-off-by: David Woodhouse commit a1ff0eafce81a58861534926722a70f211b04faa Author: David Woodhouse Date: Tue Apr 25 13:57:44 2006 +0100 Include from linux/acct.h only in kernel-private part. Signed-off-by: David Woodhouse commit dd02ec3ac25828d0918f5b389defe2238d015fe6 Author: David Woodhouse Date: Tue Apr 25 13:51:52 2006 +0100 Remove user-visible references to PAGE_SIZE in include/asm-powerpc/elf.h Signed-off-by: David Woodhouse commit 3c304956755fa63ee80ca51ce38078fe1c4e8818 Author: Dan Williams Date: Sat Apr 15 12:26:18 2006 -0400 [PATCH] wireless/airo: minimal WPA awareness airo cards with firmware versions of 5.30.17 and higher support WPA. This patch recognizes WPA-capable firmware versions and adds support for retrieving the WPA and RSN information elements from the card's scan results. The JOB and FLAG fields are now independent, since there was no space left in the FLAG field for FLAG_WPA_CAPABLE. Signed-off-by: matthieu castet Signed-off-by: Dan Williams Signed-off-by: John W. Linville commit 921a91ef6adffe066ce80823350b982c647033e7 Author: Johannes Berg Date: Thu Apr 20 20:02:04 2006 +0200 [PATCH] softmac: clean up event handling code This patch cleans up the event handling code in ieee80211softmac_event.c and makes the module slightly smaller by removing some strings that are not used any more and consolidating some code. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville commit 9a1771e86756212041b32d80b850cc4c8063360a Author: Johannes Berg Date: Thu Apr 20 20:02:02 2006 +0200 [PATCH] softmac: add SIOCSIWMLME This patch adds the SIOCSIWMLME wext to softmac, this functionality appears to be used by wpa_supplicant and is softmac-specific. Signed-off-by: Johannes Berg Cc: Jouni Malinen Signed-off-by: John W. Linville commit e3c5a64e7075dd066316f1685caadabcbc649427 Author: Zhu Yi Date: Thu Apr 13 17:21:13 2006 +0800 [PATCH] ipw2200: Fix wpa_supplicant association problem The new ipw2200 scan completion event feature will cause a potential event race condition in wpa_supplicant. The patch fixes this problem by move the ipw_disassociate() to the IW_AUTH_WPA_ENABLED event handling code. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 127119d50ff6e226c602ae920722897f8a0c81e2 Author: Zhu Yi Date: Thu Apr 13 17:21:06 2006 +0800 [PATCH] ipw2200: remove priv->last_noise reference priv->last_noise is not used with the exponential averaging algorithm Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 459d408768fecfd1c2d170ab073e8cfd48326b1f Author: Zhu Yi Date: Thu Apr 13 17:21:00 2006 +0800 [PATCH] ipw2200: rename CONFIG_IEEE80211_RADIOTAP to CONFIG_IPW2200_RADIOTAP Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 34f8ae467b066ab4cf90bdf85efd10e7d43f2ff0 Author: Zhu Yi Date: Thu Apr 13 17:20:54 2006 +0800 [PATCH] wireless Kconfig add IPW2200_RADIOTAP Makefile both IPW2200_RADIOTAP and IPW2200_PROMISCUOUS depend on IPW2200_MONITOR. Let IPW2200_PROMISCUOUS select IPW2200_RADIOTAP. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit e43e3c1e900ec5b6662cf1901b27975c111289bf Author: Zhu Yi Date: Thu Apr 13 17:20:45 2006 +0800 [PATCH] ipw2200: rename CONFIG_IPW_QOS to CONFIG_IPW2200_QOS Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 555fd91852880f927f131520889e1fe674ed7e7a Author: Zhu Yi Date: Thu Apr 13 17:20:40 2006 +0800 [PATCH] ipw2200: update version stamp to 1.1.2 Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit ae4af61f6d9909f3c3ab74694c06865f27c9b054 Author: Zhu Yi Date: Thu Apr 13 17:20:34 2006 +0800 [PATCH] ipw2200: version string rework Added version string fields so the version string indicates what is configured (ie, you'll see 1.1.1kpmd if you are using a GIT snapshot (Kernel.. previously -git), promiscuous (p), monitor (m), debug (d) build. Signed-off-by: James Ketrenos Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit d685b8c226727bf5db907c7241f55461e7f1f008 Author: Zhu Yi Date: Thu Apr 13 17:20:27 2006 +0800 [PATCH] ipw2200: Enable rtap interface for RF promiscuous mode while associated With this patch, a new promiscuous mode is enabled. If the module is loaded with the rtap_iface=1 module parameter, two interfaces will be created (instead of just one). The second interface is prefixed 'rtap' and provides received 802.11 frames on the current channel to user space in a radiotap header format. Example usage: % modprobe ipw2200 rtap_iface=1 % iwconfig eth1 essid MyNetwork % dhcpcd eth1 % tcpdump -i rtap0 If you do not specify 'rtap_iface=1' then the rtap interface will not be created and you will need to turn it on via: % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface You can filter out what type of information is passed to user space via the rtap_filter sysfs entry. Currently you can tell the driver to transmit just the headers (which will provide the RADIOTAP and IEEE 802.11 header but not the payload), to filter based on frame control type (Management, Control, or Data), and whether to report transmitted frames, received frames, or both. The transmit frame reporting is based on a patch by Stefan Rompf. Filters can be get and set via a sysfs interface. For example, set the filter to only send headers (0x7), don't report Tx'd frames (0x10), and don't report data frames (0x100): % echo 0x117 > /sys/bus/pci/drivers/ipw2200/*/rtap_filter All your packets are belong to us: % tethereal -n -i rtap0 Signed-off-by: James Ketrenos Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit c6c33a779dfe7aa8254be4da08c217914f1390a0 Author: Zhu Yi Date: Thu Apr 13 17:20:21 2006 +0800 [PATCH] README.ipw2200: rename CONFIG_IPW_DEBUG to CONFIG_IPW2200_DEBUG Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 0070f8c738f757c2dda521d6bc310dc2dfdbf643 Author: Zhu Yi Date: Thu Apr 13 17:20:12 2006 +0800 [PATCH] ipw2200: Fix endian issues with v3.0 fw image format This patch corrects endian issues with the v3.0 fw image format. Signed-off-by: James Ketrenos Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 455936c73337c1c9abeac8c4da1c109a0250ab68 Author: Zhu Yi Date: Thu Apr 13 17:20:05 2006 +0800 [PATCH] ipw2200: Set the 'fixed' flags in wext get_rate Signed-off-by: Jean Tourrilhes Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 61fb9ed99dc8876cb118bd9ab46b535ca8c820e8 Author: Zhu Yi Date: Thu Apr 13 17:19:55 2006 +0800 [PATCH] ipw2200: turn off signal debug log Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit d0b526b71569446aaa848cdf4cf3dd8948f0931a Author: Zhu Yi Date: Thu Apr 13 17:19:50 2006 +0800 [PATCH] ipw2200: Do not continue loading the firmware if kmalloc fails Signed-off-by: Ingo Molnar Cc: "Zhu, Yi" Signed-off-by: Andrew Morton Signed-off-by: John W. Linville commit 5dc81c3071d015a6afb4a04c1bcb6a35ec29df37 Author: Zhu Yi Date: Thu Apr 13 17:19:44 2006 +0800 [PATCH] ipw2200: fix compile warning when !CONFIG_IPW2200_DEBUG Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit d2b83e1214a8395ee18e028d4526cffe9d2eb4ad Author: Zhu Yi Date: Thu Apr 13 17:19:36 2006 +0800 [PATCH] ipw2200: add module_param support for antenna selection Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 07f02e4625e6d7ca5d4f3835aea9807fe1e0f9c5 Author: Zhu Yi Date: Thu Apr 13 17:19:25 2006 +0800 [PATCH] ipw2200: generates a scan event after a scan has completed The patch make ipw2200 generate the scan event every time a scan has completed, so that user space know when to get fresh results. Dan Williams would like to go towards this model in Network Manager rather than having to poll. Signed-off-by: Jean Tourrilhes Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit a5cf4fe65144ff2f35de37c7b58e7ab8ffd84d19 Author: Zhu Yi Date: Thu Apr 13 17:19:11 2006 +0800 [PATCH] ipw2200: Fix TX QoS enabled frames problem This patch works with the ieee80211 stack to set the correct QoS bit to the ipw2200 card. It fixed the TX failure problem for using WPA with QoS. Signed-off-by: Hong Liu Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 00d21de5c685ab450ef376acdd1b733badb6b50d Author: Zhu Yi Date: Thu Apr 13 17:19:02 2006 +0800 [PATCH] ipw2200: Exponential averaging for signal and noise Level This patch replaces sliding averaging by exponential averaging for reporting the wireless statistics for signal and noise level for ipw2200. See details from: http://www.ces.clemson.edu/linux/ipw2200_averages.shtml Signed-off-by: Bill Moss Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 45a62ab3d6f9d5963cb7c01fa76c950e42d037c2 Author: Zhu Yi Date: Thu Apr 13 17:17:54 2006 +0800 [PATCH] ieee80211: update version stamp to 1.1.13 Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 7736b5bd93765fc1db5b3b6e25200d7c4292d14b Author: Zhu Yi Date: Thu Apr 13 17:17:47 2006 +0800 [PATCH] ieee80211: replace debug IEEE80211_WARNING with each own debug macro Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 35c14b855f52c49e4f3d078b9532b056005ed321 Author: Zhu Yi Date: Thu Apr 13 17:17:35 2006 +0800 [PATCH] ieee80211: remove unnecessary CONFIG_WIRELESS_EXT checking Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 09593047d8210ca017a0b4aa0a7fb10abf12615f Author: Zhu Yi Date: Thu Apr 13 17:17:26 2006 +0800 [PATCH] ieee80211: export list of bit rates with standard WEXT procddures The patch replace the way to export the list of bit rates in scan results from IWEVCUSTOM to SIOCGIWRATE. It also removes the max_rate item exported with SIOCGIWRATE since this should be done by userspace. Signed-off-by: Jean Tourrilhes Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit 73858062b66c07d71bce47a0e4798dd3ce604590 Author: Zhu Yi Date: Thu Apr 13 17:17:17 2006 +0800 [PATCH] ieee80211: Fix TX code doesn't enable QoS when using WPA + QoS Fix ieee80211 TX code when using WPA+QOS. TKIP/CCMP will use the TID field of qos_ctl in 802.11 frame header to do encryption. We cannot ignore this field when doing host encryption and add the qos_ctl field later. Signed-off-by: Hong Liu Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit ea2841521a7e061b772d6cee03f5b23c58a58284 Author: Zhu Yi Date: Thu Apr 13 17:17:06 2006 +0800 [PATCH] ieee80211: Fix TKIP MIC calculation for QoS frames Fix TKIP MIC verification failure when receiving QoS frames from AP. Signed-off-by: Hong Liu Signed-off-by: Zhu Yi Signed-off-by: John W. Linville commit cc9357104b19b2b0377713c33d87d78518912c3d Author: Michael Buesch Date: Mon Apr 10 02:08:33 2006 +0200 [PATCH] bcm43xx: use pci_iomap() for convenience. This reduces codesize. Signed-off-by: John W. Linville commit f298a2ec62e51cc81b85a120d8fa5b9f8f5a94b1 Author: Pavel Roskin Date: Fri Apr 7 04:11:02 2006 -0400 [PATCH] orinoco: bump version to 0.15 Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit dc3437d205dcd1a195ebf795f1c54ceb638337fb Author: Pavel Roskin Date: Fri Apr 7 04:11:00 2006 -0400 [PATCH] orinoco: further comment cleanup in the PCI drivers Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit b884c872fa1917614b42a39020ffcca7fa9302b1 Author: Pavel Roskin Date: Fri Apr 7 04:10:57 2006 -0400 [PATCH] orinoco: reduce differences between PCI drivers, create orinoco_pci.h Make all Orinoco PCI drivers (orinoco_pci, orinoco_plx, orinoco_tmd and orinoco_nortel) as similar as possible. Use the best implementation of error handling, the best error messages, the best comments. Put common code to orinoco_pci.h. For now, it's suspend and resume functions and function for registering the network device. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit c6fb2e9abef894efc4870e4c1e3aa4365b830a11 Author: Pavel Roskin Date: Fri Apr 7 04:10:55 2006 -0400 [PATCH] orinoco: support PCI suspend/resume for Nortel, PLX and TMD adaptors Copy PCI suspend/resume functions from orinoco_pci.c. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 3d529962217c3fec36f53f270a37e132b9763c65 Author: Pavel Roskin Date: Fri Apr 7 04:10:53 2006 -0400 [PATCH] orinoco_pci: use pci_iomap() for resources Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit d62274b374ce41dd3a90820b124d28fec292a5b7 Author: Pavel Roskin Date: Fri Apr 7 04:10:51 2006 -0400 [PATCH] orinoco_pci: disable device and free IRQ when suspending Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 37a6c6117db3f10e1923c14dffa089b10600c4b8 Author: Pavel Roskin Date: Fri Apr 7 04:10:49 2006 -0400 [PATCH] orinoco: delay FID allocation after firmware initialization This is needed to identify the card before possible allocation problems, so that the user at least can report the firmware version that fails. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 2c1bd26035491cd0ba7e49be6ed610fc4912fef9 Author: Jiri Benc Date: Fri Apr 7 04:10:47 2006 -0400 [PATCH] orinoco: fix BAP0 offset error after several days of operation After several days of operation of Netgear MA311 card, the card becomes to seek improperly and needs reset. This patch tries to reset the card when this situation occurs. Mar 9 06:45:16 berkeley kernel: wlan0: Error -5 writing packet to BAP Mar 9 06:45:16 berkeley kernel: hermes @ f992a000: BAP0 offset error: reg=0x4044 id=0x128 offset=0x44 Mar 9 06:45:16 berkeley kernel: wlan0: Error -5 writing packet to BAP Mar 9 06:45:16 berkeley kernel: hermes @ f992a000: BAP0 offset error: reg=0x4044 id=0x128 offset=0x44 (etc.) A more detailed description of the problem can be found at https://bugzilla.novell.com/show_bug.cgi?id=154773 The same problem with different card is reported at http://sourceforge.net/mailarchive/message.php?msg_id=14597046 Signed-off-by: Jiri Benc Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit a28dc81dcd9ca9a451bfcab0a2351b0b07146759 Author: Pavel Roskin Date: Fri Apr 7 04:10:45 2006 -0400 [PATCH] orinoco: simplify 802.3 encapsulation code Use skb_pull() to strip the addresses from the original packet. Don't strip protocol bytes. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 470e2aa6dbdd2c7eb6562ae365a17a627f7070e8 Author: Pavel Roskin Date: Fri Apr 7 04:10:43 2006 -0400 [PATCH] orinoco: refactor and clean up Tx error handling The result of orinoco_xmit() can be OK, dropped packet and busy transmitter. Rename labels accordingly. Increment stats->tx_errors in one place. Increment stats->tx_dropped - nobody is doing it for us. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 8d5be088263b0d3dbb7e7959b7c403b3d026a5d3 Author: Pavel Roskin Date: Fri Apr 7 04:10:41 2006 -0400 [PATCH] orinoco: don't use any padding for Tx frames hermes_bap_pwrite() supports odd-sized packets now. There is no minimal packet size for 802.11. Also, hermes_bap_pwrite() supports odd-sized packets now. This removes all reasons to pad the Tx data. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 6b61626290900f12b7f3978f57f329da6811fb59 Author: Pavel Roskin Date: Fri Apr 7 04:10:39 2006 -0400 [PATCH] orinoco replace hermes_write_words() with hermes_write_bytes() The new function can write an odd number of bytes, thus making padding unnecessary. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit b34b867e944628418d587367276c9a82e03aba8c Author: Pavel Roskin Date: Fri Apr 7 04:10:36 2006 -0400 [PATCH] orinoco: orinoco_xmit() should only return valid symbolic constants Don't ever return -errno from orinoco_xmit() - the network layer doesn't expect it. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 30c2d3b48176279b1381b00ae86f3d01147d0915 Author: Pavel Roskin Date: Fri Apr 7 04:10:34 2006 -0400 [PATCH] orinoco: optimize Tx exception handling in orinoco When processing Tx exception, only read data until addr1. Rename hermes_tx_descriptor_802_11 to hermes_txexc_data since it's only used to Tx exceptions. Reuse existing hermes_tx_descriptor structure. Remove fields after addr1 - they are not read from the card. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 4ebe2eb0b388445d18dae34849cc6a9e7c55315f Author: Pavel Roskin Date: Fri Apr 7 04:10:32 2006 -0400 [PATCH] orinoco: Symbol card supported by spectrum_cs is LA4137, not LA4100 Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 754b1364e78db796bb3a541f6ea8dec2821c745a Author: Pavel Roskin Date: Fri Apr 7 04:10:30 2006 -0400 [PATCH] orinoco: remove debug buffer code and userspace include support Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 65b1fe7df71e7ad09e9203b6c3875781c30557e0 Author: Pavel Roskin Date: Fri Apr 7 04:10:28 2006 -0400 [PATCH] orinoco: remove tracing code, it's unused Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit 7eeae2ffadf170f954205733f511ca40df91f0b7 Author: Pavel Roskin Date: Fri Apr 7 04:10:24 2006 -0400 [PATCH] orinoco: remove underscores from little-endian field names Sparse is much better at finding endianess issues than such visual cues. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit b018779cbda646c37346433167145b4624c8979b Author: Pavel Roskin Date: Fri Apr 7 04:10:21 2006 -0400 [PATCH] orinoco: remove PCMCIA audio support, it's useless for wireless cards Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit a6e26e8ddbe8717103556ecd8ecd383de32671e4 Author: Pavel Roskin Date: Fri Apr 7 04:10:19 2006 -0400 [PATCH] orinoco: Remove useless CIS validation The PCMCIA drivers would never be loaded if the CIS were wrong. No other PCMCIA drivers validate CIS. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville commit ac325acd50013fa8f4953208cbb96504dec9b12a Author: Linas Vepstas Date: Tue Apr 18 21:05:21 2006 -0700 [PATCH] powerpc/pseries: clear PCI failure counter if no new failures The current PCI error recovery system keeps track of the number of PCI card resets, and refuses to bring a card back up if this number is too large. The goal of doing this was to avoid an infinite loop of resets if a card is obviously dead. However, if the failures are rare, but the machine has a high uptime, this mechanism might still be triggered; this is too harsh. This patch will avoids this problem by decrementing the fail count after an hour. Thus, as long as a pci card BSOD's less than 6 times an hour, it will continue to be reset indefinitely. If it's failure rate is greater than that, it will be taken off-line permanently. This patch is larger than it might otherwise be because it changes indentation by removing a pointless while-loop. The while loop is not needed, as the handler is invoked once fo each event (by schedule_work()); the loop is leftover cruft from an earlier implementation. Signed-off-by: Linas Vepstas Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras commit 4bd174fe1cca738f53cf8bb9ac3cb327b1f516ed Author: Olof Johansson Date: Tue Apr 18 11:25:53 2006 -0500 [PATCH] powerpc: Remove stale iseries global Not even the iSeries maintainer seems to have access to this legendary piranha simulator. It adds a bit of ugliness in the common time init code, and if it's no longer used we might as well be done with it and remove the bloat. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit 5e1415c3f7d3ad133edb7ce9ca90641cf0f5fe79 Author: Olof Johansson Date: Wed Apr 12 15:29:00 2006 -0500 [PATCH] powerpc: Quiet oprofile output at boot No need to always print out which performance monitoring type is used on the console at every boot. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit 90ddfebec1b450258f85d42f043cfbae450fe47e Author: Olof Johansson Date: Wed Apr 12 15:28:13 2006 -0500 [PATCH] powerpc: Quiet rtasd output at boot Most users won't really know the difference between a started RTAS daemon and a missing event-scan. Move it to debug levels. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit e884e9c5f28c747ac2c3e1056e1fd655a79e950d Author: Olof Johansson Date: Wed Apr 12 15:26:59 2006 -0500 [PATCH] powerpc: Quiet PCI init printouts Quiet some of the more debug related output from the pci probe routines. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit cc98f70557bd08f2eea7b955dd918692a655d72e Author: Olof Johansson Date: Wed Apr 12 15:26:00 2006 -0500 [PATCH] powerpc: Lack of ISA interrupts on XICS isn't dangerous This isn't really a dangerous thing any more; most systems lack ISA interrupt controllers. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit e110b281dc93e3b4587a3d0440bb7ae38daddfde Author: Olof Johansson Date: Wed Apr 12 15:25:01 2006 -0500 [PATCH] powerpc: Less verbose mem configuration output Quieten some of the debug ram config output. we already print out available memory at KERN_INFO level. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit 4baaf0cfda7279e1adaedc203d7a09e8e44597ab Author: Olof Johansson Date: Wed Apr 12 15:23:22 2006 -0500 [PATCH] powerpc: Don't print chosen idle loop at every boot No need to write out what idle loop is used on every boot. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit f98baffb82710803005c19897f1a55af91da5685 Author: Olof Johansson Date: Wed Apr 12 15:22:29 2006 -0500 [PATCH] powerpc: Quiet VETH version printk ibmveth_printk() is only used to print the driver version when the module initializes, which means on all machines as long as it's compiled in. If it's really only needed for debugging, boot with loglevel=8, or get it from dmesg instead. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit f430c02b13f00146106fedcace810e61b4493d8c Author: Olof Johansson Date: Wed Apr 12 15:21:06 2006 -0500 [PATCH] powerpc: Quiet page order output No need to always print page orders. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit 224ad80ac0de102d7bede8d36afbd5ef0a64019f Author: Olof Johansson Date: Wed Apr 12 15:20:27 2006 -0500 [PATCH] powerpc: Quiet time init output Move time_init console output to KERN_DEBUG prink level. No need to print it at every boot. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit 8b6a7b2ea2ab18d46bc9e0e76b614d8c155291ad Author: Olof Johansson Date: Wed Apr 12 15:19:50 2006 -0500 [PATCH] powerpc: Quiet HVSI boot output There's no real need to print the number of found HVSI devices on the console at every boot. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit c256f4b9598c71afd8eb0b7d3d3790a38734cf43 Author: Anton Blanchard Date: Fri Apr 7 15:23:03 2006 +1000 [PATCH] powerpc: remove io_page_mask Cleanup patch which removes the io_page_mask. It fixes the reset on some e1000 devices which is needed for clean kexec reboots. The legacy devices which broke with this patch (parallel port and PC speaker) have now been fixed in Linus' tree. Signed-off-by: Anton Blanchard Acked-by: Michael Neuling Signed-off-by: Paul Mackerras commit 81bbbe92949b069c101e13d3acbd4bc7d088cb79 Author: Haren Myneni Date: Wed Apr 5 21:10:18 2006 -0600 [PATCH] powerpc: clear IPIs on kdump In some crash scenarios, the kexec CPU is not responding to an IPI sent by secondary CPU after init thread is forked, causing the system to drop into xmon during kdump boot. This problem can be reproduced each time when the debugger is enabled and soft-reset is used to invoke kdump boot. The first CPU sends an IPI - setting the IPI priority for all secondary cpus (xics_cause_ipi()). But some CPUs will enter into the xmon via soft-reset, i.e, not executing xics_ipi_action(). Hence, IPI is not cleared. When exited from the debugger, one of these CPUs could become the primary kexec CPU. Since the IPI is not cleared, causing this issue in kdump boot. This patch clears and EOI IPI for kexec CPU as well before the kdump boot started. Signed-off-by: Haren Myneni Signed-off-by: Paul Mackerras commit d6c1a9081080c6c4658acf2a06d851feb2855933 Author: Michael Ellerman Date: Tue Apr 4 13:43:01 2006 +0200 [PATCH] powerpc: Disable and EOI interrupts in machine_crash_shutdown() We've seen several bugs caused by interrupt weirdness in the kdump kernel. Panicking from an interrupt handler means we fail to EOI the interrupt, and so the second kernel never gets that interrupt ever again. We also see hangs on JS20 where we take interrupts in the second kernel early during boot. This patch fixes both those problems, and although it adds more code to the crash path I think it is the best solution. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit ed198cb49750fd9ec564e9f1df66c10efea605f1 Author: David Woodhouse Date: Sat Apr 22 02:38:50 2006 +0100 [RBTREE] Update hrtimers to use rb_parent() accessor macro. Also switch it to use the same method of using off-tree nodes as everyone else now does -- set them to point to themselves. Signed-off-by: David Woodhouse commit e977145aeaad23d443686f2a2d5b32800d1607c5 Author: David Woodhouse Date: Fri Apr 21 23:15:39 2006 +0100 [RBTREE] Add explicit alignment to sizeof(long) for struct rb_node. Seems like a strange requirement, but allegedly it was necessary for struct address_space on CRIS, because it otherwise ended up being only byte-aligned. It's harmless enough, and easier to just do it than to prove it isn't necessary... although I really ought to dig out my etrax board and test it some time. Signed-off-by: David Woodhouse commit 55a981027fc393c86de2c4e7836c9515088a9a58 Author: David Woodhouse Date: Fri Apr 21 13:35:51 2006 +0100 [RBTREE] Merge colour and parent fields of struct rb_node. We only used a single bit for colour information, so having a whole machine word of space allocated for it was a bit wasteful. Instead, store it in the lowest bit of the 'parent' pointer, since that was always going to be aligned anyway. Signed-off-by: David Woodhouse commit 1975e59375756da4ff4e6e7d12f67485e813ace0 Author: David Woodhouse Date: Fri Apr 21 13:30:36 2006 +0100 [RBTREE] Remove dead code in rb_erase() Observe rb_erase(), when the victim node 'old' has two children so neither of the simple cases at the beginning are taken. Observe that it effectively does an 'rb_next()' operation to find the next (by value) node in the tree. That is; we go to the victim's right-hand child and then follow left-hand pointers all the way down the tree as far as we can until we find the next node 'node'. We end up with 'node' being either the same immediate right-hand child of 'old', or one of its descendants on the far left-hand side. For a start, we _know_ that 'node' has a parent. We can drop that check. We also know that if 'node's parent is 'old', then 'node' is the right-hand child of its parent. And that if 'node's parent is _not_ 'old', then 'node' is the left-hand child of its parent. So instead of checking for 'node->rb_parent == old' in one place and also checking 'node's heritage separately when we're trying to change its link from its parent, we can shuffle things around a bit and do it like this... Signed-off-by: David Woodhouse commit 21f1d5fc592e145574dede8debe9603334d08fde Author: David Woodhouse Date: Fri Apr 21 13:17:57 2006 +0100 [RBTREE] Update JFFS2 to use rb_parent() accessor macro. Signed-off-by: David Woodhouse commit c569882b2e70a0c4eac99acdb39b493549041ba1 Author: David Woodhouse Date: Fri Apr 21 13:17:24 2006 +0100 [RBTREE] Update eventpoll.c to use rb_parent() accessor macro. Signed-off-by: David Woodhouse commit fed306f2baa170220b0299198a39c6be2a91bf19 Author: David Woodhouse Date: Fri Apr 21 13:16:49 2006 +0100 [RBTREE] Update key.c to use rb_parent() accessor macro. Signed-off-by: David Woodhouse commit 52b5108ca7490c0609e4dbddd8439bc03d702c99 Author: David Woodhouse Date: Fri Apr 21 13:15:57 2006 +0100 [RBTREE] Update ext3 to use rb_parent() accessor macro. Signed-off-by: David Woodhouse commit 3db3a445308b3cee9bbbd8baa6d05081c9532da0 Author: David Woodhouse Date: Fri Apr 21 13:15:17 2006 +0100 [RBTREE] Change rbtree off-tree marking in I/O schedulers. They were abusing the rb_color field to mark nodes which weren't currently on the tree. Fix that to use the same method as eventpoll did -- setting the parent pointer to point back to itself. And use the appropriate accessor macros for setting and reading the parent. Signed-off-by: David Woodhouse commit 7fe1e133bf45b0fe70491ed3d4c5b491feff7aa8 Author: David Woodhouse Date: Fri Apr 21 13:12:44 2006 +0100 [RBTREE] Add accessor macros for colour and parent fields of rb_node This is in preparation for merging those fields into a single 'unsigned long', because using a whole machine-word for a single bit of colour information is wasteful. Signed-off-by: David Woodhouse commit bf2af2a2027e52b653882fbca840620e896ae081 Author: Bastiaan Jacques Date: Mon Apr 17 14:17:59 2006 +0200 [PATCH] ahci: add support for VIA VT8251 Adds AHCI support for the VIA VT8251. Includes a workaround for a hardware bug which requires a Command List Override before softreset. Signed-off-by: Bastiaan Jacques Signed-off-by: Jeff Garzik commit 18e37f2a979dd696e6b4495b6f2470c01ffeab6c Author: Marc Zyngier Date: Thu Apr 13 11:38:20 2006 +0200 [PATCH] netdrvr: Convert cassini to pci_iomap Folks, This patch (against 2.6.17-rc1) converts the cassini driver to the pci_iomap API that will do the right thing, so architectures like PARISC can stop screaming about illegal usage of ioremap() on non-cacheable regions. Tested on 64bit PARISC kernel. Signed-off-by: Marc Zyngier Signed-off-by: Jeff Garzik commit d5498bef6fcd8ca0e4579eeb0b0d724f20221bb1 Author: Jeff Garzik Date: Thu Apr 20 17:39:14 2006 -0400 [netdrvr smc911x] trim trailing whitespace commit 0a0c72c9118c4e63080eb409f0cfdf15808d23a4 Author: Dustin McIntire Date: Wed Apr 19 20:24:51 2006 -0700 [PATCH] RE: [PATCH 1/1] net driver: Add support for SMSC LAN911x line of ethernet chips > > The patch was badly wordwrapped. Please fix and resend. > OK, I've fixed the wrapping and removed the CONFIG_ARM restriction. I've also did my best to modify the C style to conform to the comments. I noticed that the patch is getting ignored by majordomo due to its size >100K. Should it be broken up somehow to allow posting to the lists? Signed-off-by: Dustin McIntire Signed-off-by: Jeff Garzik commit 89be0501a013737d562f56ce1c5a2ff075995b11 Author: Sergei Shtylyov Date: Wed Apr 19 22:46:21 2006 +0400 [PATCH] au1000_eth.c probe code straightened up Straighten up the AMD Au1xx0 Ethernet probing code, make it print out (and store in the 'net_device' structure) the physical address of the controller, not the KSEG1-based virtual. Make the driver also claim/release the 4-byte MAC enable registers and assign to the Ethernet ports two consecutive MAC addresses to match those that are printed on their stickers. Signed-off-by: Sergei Shtylyov Signed-off-by: Jeff Garzik commit e2fd956c670928e93208dc5d27dfdc7b51163900 Author: Johannes Berg Date: Wed Apr 19 15:39:09 2006 +1000 [PATCH] sungem: Marvell PHY suspend In a short discussion with Benjamin Herrenschmidt he mentioned that Marvell PHYs are powered down the same way as the other ones we currently handle. Thus actually do that, hopefully saving some power during suspend. Signed-off-by: Johannes Berg Acked-by: Benjamin Herrenschmidt Signed-off-by: Jeff Garzik commit d269a69fbbbb7ddd2081af7a768feac754b8357a Author: Daniele Venzano Date: Mon Apr 17 10:28:06 2006 +0200 [PATCH] Add VLAN (802.1q) support to sis900 driver The attached patch adds support for VLANs to the sis900 driver and bumps the version number. It is based on an old (2003) patch for the 2.4 series by Hamid Hashemi Golpayegani. It applies on top of 2.6.16(.5). I have one report that it works and behaves as intended. Please review and consider for inclusion. Signed-off-by: Daniele Venzano -- Signed-off-by: Jeff Garzik commit 5ad05b990062c1b7a797f0ca293f6bdde62a50d9 Author: Frank Pavlic Date: Thu Apr 13 20:19:23 2006 +0200 [PATCH] s390: remove tty support from ctc network device driver [2/2] Hi, here comes the second of the two patches ... Frank From: Peter Tiedemann [2/2]: remove ctctty.c and ctctty.h files . Signed-off-by: Frank Pavlic Signed-off-by: Jeff Garzik commit 56347a2e7287377c35c2bac2e8643bf88690425f Author: Frank Pavlic Date: Thu Apr 13 20:19:12 2006 +0200 [PATCH] s390: remove tty support from ctc network device driver [1/2] Hi jeff, after the first shot I sent to you did not apply I resend two new patches I've made today to remove tty from ctc network driver. Please apply .... Thank you ... Frank From: Peter Tiedemann [1/2]: tty support code will be removed from the ctc network device driver. Today we have a couple of alternatives which are performing much better. The second thing is that ctc should be a network device driver only. We should not mix tty and networking here. This first patch will remove the tty code from ctcmain.c . It also removes the build entry from the Makefile as well as TTY definitions from ctcmain.h. The second patch will remove two files, ctctty.c and ctctty.h. Signed-off-by: Frank Pavlic Signed-off-by: Jeff Garzik commit 169e1a2a8a789fa84254695ec6a56fc410bb19a9 Author: Andrew Morton Date: Tue Apr 18 21:09:08 2006 -0700 [SCSI] scsi_lib.c: fix warning in scsi_kmap_atomic_sg drivers/scsi/scsi_lib.c: In function `scsi_kmap_atomic_sg': drivers/scsi/scsi_lib.c:2394: warning: unsigned int format, different type arg (arg 3) drivers/scsi/scsi_lib.c:2394: warning: unsigned int format, different type arg (arg 4) Signed-off-by: Andrew Morton Signed-off-by: James Bottomley commit 954c24227318c166ec1925e1229db442e1f56f51 Author: Joern Engel Date: Tue Apr 18 21:03:08 2006 -0700 mtd: improve parameter parsing for block2mtd Expand the parameter parsing for block2mtd. It now accepts: Ki, Mi, Gi - the official prefixes for binary multiples, see http://physics.nist.gov/cuu/Units/binary.html, ki - mistake on my side and analog to "k" for decimal multiples, KiB, MiB, GiB - for people that prefer to add a "B" for byte, kiB - combination of the above. There were complaints about not accepting "k" for 1024. This has long been common practice, but is known to lead to confusion. Hence the new SI units and hence block2mtd only accepts units that cannot be confused with decimal units. Diverging from common practice doesn't always please people, even if the change is for the better. Signed-off-by: Joern Engel Cc: David Woodhouse Cc: Thomas Gleixner Signed-off-by: Andrew Morton commit 1cb5821f444cadbe94453282f9f4767cf8744a8e Author: Auke Kok Date: Tue Apr 18 12:31:04 2006 -0700 e1000: fix mismerge skb_put. Seems there was a bit of a fix needed to due a bad merge in the legacy receive path. Fixes a panic due to skb_over_panic. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok commit dc86d32ab51c4ad3086472457fb90b61249d91f5 Author: Auke Kok Date: Tue Apr 18 12:30:51 2006 -0700 e1000: fix mispatch for media type detect. Recent patch was mismerged in the miitool path. e1000_media_type_copper was being compared with the phy type instead of the media type. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok commit 373d5e71833978fe3d91264d86857762bb92cfe2 Author: Richard Purdie Date: Tue Apr 18 02:05:46 2006 +0100 JFFS2: Return an error for long filenames Return an error if a name is too long for JFFS2 rather than corrupting data. Signed-off-by: Richard Purdie commit 6e62e8c2c7b1e3387d73ecb3f7539314b7a9931e Author: Richard Purdie Date: Tue Apr 18 02:04:18 2006 +0100 MTD: Correct Poodle partition size Correct the MTD NAND partition size for Poodle (Sharp Zaurus SL-5600) Signed-off-by: Richard Purdie commit b802c0741103aa92251d536c115874d51f802ec8 Author: Thago Galesi Date: Mon Apr 17 17:38:15 2006 +0100 [PATCH] Remove unnecessary kmalloc/kfree calls in mtdchar This patch removes repeated calls to kmalloc / kfree in mtd_write / mtd_read functions, replacing them by a single kmalloc / kfree pair. Signed-off-by: Thiago Galesi Signed-off-by: David Woodhouse commit cd2866faaa0efd9af18fe4a86d129cbd99240796 Author: Jörn Engel Date: Thu Apr 13 18:55:09 2006 +0200 Remove unused MTD types Three types are never set or checked for. Remove. Signed-off-by: Jörn Engel Signed-off-by: David Woodhouse commit a6c591eda3078f92e7a3ff3db55f6841e4819fb5 Author: Jörn Engel Date: Thu Apr 13 18:54:34 2006 +0200 Remove unchecked MTD flags Several flags are set by some devices, but never checked. Remove them. Signed-off-by: Jörn Engel Signed-off-by: David Woodhouse commit af63a3bcac77d8c01f3d963bac11a6f3f9b7c473 Author: Jörn Engel Date: Thu Apr 13 18:53:55 2006 +0200 Make mtdblock_ro unconditionally readonly mtdblock_ro is by definition readonly. Remove the silly checks. Signed-off-by: Jörn Engel Signed-off-by: David Woodhouse commit 7f7c08dfdf5bc0a7c906285d9d97b932f83e8979 Author: Jörn Engel Date: Thu Apr 13 18:53:14 2006 +0200 Simplify test for RAM devices mtdblock is the only user of aggregate capabilities in mtd. This is clearly bogus and should be changed. In particular, it tries to determine whether the device in question is a piece of RAM. For every single driver that fits the current criteria, an easier test would be to check for the type being MTD_RAM. Signed-off-by: Jörn Engel Signed-off-by: David Woodhouse commit d96fb997c6174f98a2a0a98200f99ac13b053bd6 Author: David Woodhouse Date: Mon Apr 17 00:19:48 2006 +0100 [JFFS2] Fix race in post-mount node checking For a while now, we've postponed CRC-checking of data nodes to be done by the GC thread, instead of being done while the user is waiting for mount to finish. The GC thread would iterate through all the inodes on the system and check each of their data nodes. It would skip over inodes which had already been used or were already being read in by read_inode(), because their data nodes would have been examined anyway. However, we could sometimes reach the end of the for-each-inode loop and still have some unchecked space left, if an inode we'd skipped was _still_ in the process of being read. This fixes that race by actually waiting for read_inode() to finish rather than just moving on. Thanks to Ladislav Michl for coming up with a reproducible test case and helping to track it down. Signed-off-by: David Woodhouse commit c5f2e6404c65e8380c9ba80a7d58a27d2642743b Author: akpm@osdl.org Date: Sat Apr 15 00:30:24 2006 -0700 [SCSI] scsi_scan.c: fix compile warnings drivers/scsi/scsi_scan.c: In function `scsi_probe_and_add_lun': drivers/scsi/scsi_scan.c:926: warning: unused variable `vend' drivers/scsi/scsi_scan.c:926: warning: unused variable `mod' drivers/scsi/scsi_scan.c: At top level: drivers/scsi/scsi_scan.c:829: warning: `scsi_inq_str' defined but not used Fix those, tighten up the (somewhat poorly-designed) logging macro and fix some coding-style warts. Signed-off-by: Andrew Morton Signed-off-by: James Bottomley commit 99a1f9e88694b406b7c334153bacb56adfcf8388 Author: Auke Kok Date: Fri Apr 14 19:05:38 2006 -0700 {e100{,0},ixgb}: Add Auke Kok as new patch maintainer for e{100,1000} and ixgb This adds Auke Kok to the list of maintainers for the Intel NICs. Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 3d41e30aa3dde76c81ecbbf0e3a25392fcd90469 Author: Auke Kok Date: Fri Apr 14 19:05:31 2006 -0700 e1000: Version bump, contact fix, year string change Add the sourceforge project mailinglist to the contact information. Bump version to 7.0.38-k2 Update copyright string with the new year. Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 77b2aad5b4fcb6e050b64bbda158ce528f933023 Author: Auke Kok Date: Fri Apr 14 19:05:25 2006 -0700 e1000: implement more efficient tx queue locking Implement more efficient locking (avoid the lock) when checking for a stopped queue. Also don't wake the queue unless the threshold is reached to avoid queue on/off thrash. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 9e2feace1acd38d7a3b1275f7f9f8a397d09040e Author: Auke Kok Date: Fri Apr 14 19:05:18 2006 -0700 e1000: Buffer optimizations for small MTU Remove multi-descriptor support from legacy recieve path Add memory usage efficiency by using more correct size descriptors for small MTU sizes and optimize using LPE for <= 1522 byte frame sizes An extra performance fix that effected our TCP window size growth as a receiver. Set our initial buffer to be 128 bytes instead of 256 to prevent over-socket charge when truesize is computed in the stack. old way: truesize = 256 + l1 = 256 + 1460 = 1716 new way: truesize = 128 + l1 = 128 + 1460 = 1588 The magic value that we can't cross is 1648. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 6fc7a7eca70780dc1539ce68a6513f9b11891f3c Author: Auke Kok Date: Fri Apr 14 19:05:12 2006 -0700 e1000: Dead variable cleanup Removal of unused rx_dropped counter. Removed reference to E1000_CTRL_EXT_CANC which is no longer valid, replaced with E1000_CTRL_EXT_INT_TIMER_CLR Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 5d51b80f9224ca5b0ba1efc5a6348cd29b5c16b7 Author: Auke Kok Date: Fri Apr 14 19:05:06 2006 -0700 e1000: Update truesize with the length of the packet for packet split Update skb with the real packet size. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit fe7fe28ea581e090d2908a0d78a2611ae6d43e2c Author: Auke Kok Date: Fri Apr 14 19:04:59 2006 -0700 e1000: Made an adapter struct variable into a local (txb2b) Made an adapter struct variable into a local (txb2b) Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit e619d52349ab8c0044859c28ab05e4c7a410fe14 Author: Auke Kok Date: Fri Apr 14 19:04:52 2006 -0700 e1000: De-inline functions to benefit from compiler smartness De-inline functions to benefit from compiler smartness Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit 4cc15f54991caf1572e03ffc65d9986e433007e2 Author: Auke Kok Date: Fri Apr 14 19:04:46 2006 -0700 e1000: Esb2 wol link cycle bug and uninitialized registers Esb2 link didn't return after wol disable. The code previously assumed that writing reset to PHY_CTRL phy register turned the phy back on. In the ESB2 phy case that didn't occur. Add ESB2 to acquire/release_hw functions upon review it was discovered that esb2 was skipped on these functions Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit d0e027db7861ef03de0ac08494a9a61984d8f8b0 Author: Auke Kok Date: Fri Apr 14 19:04:40 2006 -0700 e1000: Remove PM warning DPRINTKs breaking 2.4.x kernels remove DPRINTKs that were printing warnings about power management on 2.4 kernels. Since we really don't react differently these printk statements are not needed. This code was originally added to fix some compile time warnings that got fixed by newer kernels. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok Signed-off-by: John Ronciak commit cdb8c2a6d848deb9eeefffff42974478fbb51b8c Author: Guennadi Liakhovetski Date: Sun Apr 2 21:57:43 2006 +0200 [SCSI] dc395x: dynamically map scatter-gather for PIO The current dc395x driver uses PIO to transfer up to 4 bytes which do not get transferred by DMA (under unclear circumstances). For this the driver uses page_address() which is broken on highmem. Apart from this the actual calculation of the virtual address is wrong (even without highmem). So, e.g., for reading it reads bytes from the driver to a wrong address and returns wrong data, I guess, for writing it would just output random data to the device. The proper fix, as suggested by many, is to dynamically map data using kmap_atomic(page, KM_BIO_SRC_IRQ) / kunmap_atomic(virt). The reason why it has not been done until now, although I've done some preliminary patches more than a year ago was that nobody interested in fixing this problem was able to reliably reproduce it. Now it changed - with the help from Sebastian Frei (CC'ed) I was able to trigger the PIO path. Thus, I was also able to test and debug it. There are 4 cases when PIO is used in dc395x - data-in / -out with and without scatter-gather. I was able to reproduce and test only data-in with and without SG. So, the data-out path is still untested, but it is also somewhat simpler than the data-in. Fredrik Roubert (also CC'ed) also had PIO triggering on his system, and in his case it was data-out without SG. It would be great if he could test the attached patch on his system, but even if he cannot, I would still request to apply the patch and just wait if anybody cries... Implementation: I put 2 new functions in scsi_lib.c and their declarations in scsi_cmnd.h. I exported them without _GPL, although, I don't feel strongly about that - not many drivers are likely to use them. But there is at least one more - I want to use them in tmscsim.c. Whether these are the right files for the functions and their declarations - not sure either. Actually, they are not scsi-specific, so, might go somewhere around other scattergather magic? They are not platform specific either, and most SG functions are defined under arch/*/... As these issues were discussed previously there were some more routines suggested to manipulate scattergather buffers, I think, some of them were needed around crypto code... So, might be a common place reasonable, like lib/scattergather.c? I am open here. Signed-off-by: James Bottomley commit 4c021dd136c0ad524e6d117296beafad2bf570c0 Author: FUJITA Tomonori Date: Fri Apr 7 19:10:03 2006 +0900 [SCSI] ibmvscsi: convert kmalloc + memset to kcalloc Convert kmalloc + memset to kcalloc in ibmvscsi Signed-off-by: FUJITA Tomonori Acked-by: Dave Boutcher Signed-off-by: James Bottomley commit 5bb0b55a3283369f1cd8ac76a6d8bda8e7a77055 Author: Mike Christie Date: Thu Apr 6 21:26:46 2006 -0500 [SCSI] iscsi: convert iscsi tcp to libiscsi This just converts iscsi_tcp to the lib Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 7996a778ff8c717cb1a7a294475c59cc8f1e9fb8 Author: Mike Christie Date: Thu Apr 6 21:13:41 2006 -0500 [SCSI] iscsi: add libiscsi There is a lot of code duplcited between iscsi_tcp and the upcoming iscsi_iser driver. This patch puts the duplicated code in a lib. There is more code to move around but this takes care of the basics. For iscsi_offload if they use the lib we will probably move some things around. For example in the queuecommand we will not assume that the LLD wants to do queue_work, but it is better to handle that later when we know for sure what iscsi_offload looks like (we could probably do this for iscsi_iser though to). Ideally I would like to get the iscsi_transports modules to a place where all they really have to do is put data on the wire, but how to do that will hopefully be more clear when we see other modules like iscsi_offload. Or maybe iscsi_offload will not use the lib and it will just be iscsi_iser and iscsi_tcp and maybe the iscsi_tcp_tgt if that is allowed in mainline. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 30a6c65236f9d26e3325cae468f330b833a3878c Author: Mike Christie Date: Thu Apr 6 21:13:39 2006 -0500 [SCSI] iscsi: fix up iscsi eh The current iscsi_tcp eh is not nicely setup for dm-multipath and performs some extra task management functions when they are not needed. The attached patch: - Fixes the TMF issues. If a session is rebuilt then we do not send aborts. - Fixes the problem where if the host reset fired, we would return SUCCESS even though we had not really done anything yet. This ends up causing problem with scsi_error.c's TUR. - If someone has turned on the userspace nop daemon code to try and detect network problems before the scsi command timeout we can now drop and clean up the session before the scsi command timesout and fires the eh speeding up the time it takes for a command to go from one patch to another. For network problems we fail the command with DID_BUS_BUSY so if failfast is set scsi_decide_disposition fails the command up to dm for it to try on another path. - And we had to add some basic iscsi session block code. Previously if we were trying to repair a session we would retrun a MLQUEUE code in the queuecommand. This worked but it was not the most efficient or pretty thing to do since it would take a while to relogin to the target. For iscsi_tcp/open-iscsi a lot of the iscsi error handler is in userspace the block code is pretty bare. We will be adding to that for qla4xxx. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit fd7255f51a13ea915099c7e488001dfbbeb05104 Author: Mike Christie Date: Thu Apr 6 21:13:36 2006 -0500 [SCSI] iscsi: add sysfs attrs for uspace sync up For iscsi boot when going from initramfs to the real root we need to stop the userpsace iscsi daemon. To later restart it iscsid needs to be able to rebuild itself and part of that process is matching a session running the kernel with the iscsid representation. To do this the attached patch adds several required iscsi values. If the LLD does not provide them becuase, login is done in userspace, then the transport class and userspace set ths up for the LLD. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit b5c7a12dc29ae0990d9e867749bdd717a3160325 Author: Mike Christie Date: Thu Apr 6 21:13:33 2006 -0500 [SCSI] iscsi: rm kernel iscsi handles usage for session and connection from hare@suse.de and michaelc@cs.wisc.edu hw iscsi like qla4xxx does not allocate a host per session and for userspace it is difficult to restart iscsid using the "iscsi handles" for the session and connection, so this patch just has the class or userspace allocate the id for the session and connection. Note: this breaks userspace and requires users to upgrade to the newest open-iscsi tools. Sorry about his but open-iscsi is still too new to say we have a stable user-kernel api and we were not good nough designers to know that other hw iscsi drivers and iscsid itself would need such changes. Actually we sorta did but at the time we did not have the HW available to us so we could only guess. Luckily, the only tools hooking into the class are the open-iscsi ones or other tools like iscsitart hook into the open-iscsi engine from userspace or prgroams like anaconda call our tools so they are not affected. Signed-off-by: Mike Christie Signed-off-by: James Bottomley commit 13f7e5acc8b329080672c13f05f252ace5b79825 Author: Kurt Garloff Date: Mon Apr 3 15:20:08 2006 +0200 [SCSI] BLIST_ATTACH_PQ3 flags Some devices report a peripheral qualifier of 3 for LUN 0; with the original code, we would still try a REPORT_LUNS scan (if SCSI level is >= 3 or if we have the BLIST_REPORTLUNS2 passed in), but NOT any sequential scan. Also, the device at LUN 0 (which is not connected according to the PQ) is not registered with the OS. Unfortunately, SANs exist that are SCSI-2 and do NOT support REPORT_LUNS, but report a unknown device with PQ 3 on LUN 0. We still need to scan them, and most probably we even need BLIST_SPARSELUN (and BLIST_LARGELUN). See the bug reference for an infamous example. This is patch 3/3: 3. Implement the blacklist flag BLIST_ATTACH_PQ3 that makes the scsi scanning code register PQ3 devices and continues scanning; only sg will attach thanks to scsi_bus_match(). Signed-off-by: Kurt Garloff Signed-off-by: James Bottomley commit 6c7154c97e20c0ea28547240dc86731c0cee1b2f Author: Kurt Garloff Date: Mon Apr 3 15:18:35 2006 +0200 [SCSI] Better log messages for PQ3 devs Some devices report a peripheral qualifier of 3 for LUN 0; with the original code, we would still try a REPORT_LUNS scan (if SCSI level is >= 3 or if we have the BLIST_REPORTLUNS2 passed in), but NOT any sequential scan. Also, the device at LUN 0 (which is not connected according to the PQ) is not registered with the OS. Unfortunately, SANs exist that are SCSI-2 and do NOT support REPORT_LUNS, but report a unknown device with PQ 3 on LUN 0. We still need to scan them, and most probably we even need BLIST_SPARSELUN (and BLIST_LARGELUN). See the bug reference for an infamous example. This patch 2/3: If a PQ3 device is found, log a message that describes the device (INQUIRY DATA and C:B:T:U tuple) and make a suggestion for blacklisting it. Signed-off-by: Kurt Garloff Signed-off-by: James Bottomley commit 4186ab1973758190916703eb8889ebe8002c5c8f Author: Kurt Garloff Date: Mon Apr 3 15:16:48 2006 +0200 [SCSI] Try LUN 1 and use bflags Some devices report a peripheral qualifier of 3 for LUN 0; with the original code, we would still try a REPORT_LUNS scan (if SCSI level is >= 3 or if we have the BLIST_REPORTLUNS2 passed in), but NOT any sequential scan. Also, the device at LUN 0 (which is not connected according to the PQ) is not registered with the OS. Unfortunately, SANs exist that are SCSI-2 and do NOT support REPORT_LUNS, but report a unknown device with PQ 3 on LUN 0. We still need to scan them, and most probably we even need BLIST_SPARSELUN (and BLIST_LARGELUN). See the bug reference for an infamous example. This is patch 1/3: If we end up in sequential scan, at least try LUN 1 for devices that reported a PQ of 3 for LUN 0. Also return blacklist flags, even for PQ3 devices. Signed-off-by: Kurt Garloff Signed-off-by: James Bottomley commit fb6a82c94a9c69adfb6b9f6ce9f84be36884e471 Author: Randy Dunlap Date: Tue Apr 11 20:12:10 2006 -0400 [PATCH] jffs2: fix printk warnings Fix printk format warnings in jffs2. Signed-off-by: Randy Dunlap Signed-off-by: David Woodhouse commit b104513c74d972f09737017394c5abc7e0a6835d Author: Randy Dunlap Date: Tue Apr 11 20:05:20 2006 -0400 [PATCH] MTD: m25p80: fix printk format warning Fix printk format warning: drivers/mtd/devices/m25p80.c:189: warning: format '%zd' expects type 'signed size_t', but argument 6 has type 'u_int32_t' Signed-off-by: Randy Dunlap Signed-off-by: David Woodhouse commit 6cc449c7d0292cb9b993f0df84fd3225e3099492 Author: Jesper Juhl Date: Tue Apr 11 19:42:44 2006 -0400 [PATCH] mtd, nettel: fix build error and implicit declaration I just hit the following error and warning : drivers/mtd/maps/nettel.c: In function `nettel_init': drivers/mtd/maps/nettel.c:418: error: `ROOT_DEV' undeclared (first use in this function) drivers/mtd/maps/nettel.c:418: error: (Each undeclared identifier is reported only once drivers/mtd/maps/nettel.c:418: error: for each function it appears in.) drivers/mtd/maps/nettel.c:418: warning: implicit declaration of function `MKDEV' make[3]: *** [drivers/mtd/maps/nettel.o] Error 1 make[2]: *** [drivers/mtd/maps] Error 2 make[1]: *** [drivers/mtd] Error 2 The patch fixes the missing ROOT_DEV declaration by including linux/root_dev.h and fixes the implicit declaration of MKDEV by including linux/kdev_t.h . Signed-off-by: Jesper Juhl Signed-off-by: David Woodhouse commit f4e9ce66c70c5d08b8a4d2c676924748c8b7550b Author: David Woodhouse Date: Tue Apr 11 19:29:07 2006 -0400 New MTD git tree in MAINTAINERS Signed-off-by: David Woodhouse commit 26ec634c31a11a003040e10b4d650495158632fd Author: Tejun Heo Date: Tue Apr 11 22:32:19 2006 +0900 [PATCH] sata_sil24: enable 64bit Enable 64bit. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit bad28a37f5e4ab1db5c5f01b77664597b02b257f Author: Tejun Heo Date: Tue Apr 11 22:32:19 2006 +0900 [PATCH] sata_sil24: fix on-memory structure byteorder Data structures residing on memory and fetched by the controller should have LE ordering. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit a5b4c47a2731f1dd685f28b79464e4442f3682ec Author: Tejun Heo Date: Tue Apr 11 22:32:19 2006 +0900 [PATCH] sata_sil24: don't do hardreset during driver initialization There's no need to perform hardreset during driver initialization. It's already done during host reset and even if the controller is in some wacky state, we now have proper hardreset to back us up. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit ecc2e2b9c97719592b3078d5a5a8666551c91115 Author: Tejun Heo Date: Tue Apr 11 22:32:19 2006 +0900 [PATCH] sata_sil24: reimplement hardreset Reimplement hardreset according to the datasheet. The old hardreset didn't reset controller status and the controller might not be ready after reset. Also, as SStatus is a bit flakey after hardreset, sata_std_hardrset() didn't use to wait long enough before proceeding. Note that as we're not depending on SStatus, DET==1 condition cannot be used to wait for link, so use shorter timeout for no device case. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 0eaa6058a6a664ce692e3dc38c6891a74ca47f59 Author: Tejun Heo Date: Tue Apr 11 22:32:19 2006 +0900 [PATCH] sata_sil24: kill 10ms sleep in softreset Nothing, not the datasheet nor the errats, says this delay is necessary and with the previous PORT_CS_INIT change, we know the controller is in good state. Kill 10ms sleep. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 2555d6c268240fb3f5f335bd62d0518025343c0f Author: Tejun Heo Date: Tue Apr 11 22:32:19 2006 +0900 [PATCH] sata_sil24: put port into known state before softresetting Make sure the controller has no pending commands and ready for command before issuing SRST. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit b5bc421c96ca56a9abaad4619da01fe0071904a2 Author: Tejun Heo Date: Tue Apr 11 22:32:19 2006 +0900 [PATCH] sata_sil24: implement sil24_init_port() Implement sil24_init_port which performs port initialization via PORT_CS_INIT. To be used later by softreset and EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 37024e8ee0d8dbcd0c2634192cb3836549db054e Author: Tejun Heo Date: Tue Apr 11 22:32:19 2006 +0900 [PATCH] sata_sil24: implement loss of completion interrupt on PCI-X errta fix SiI3124 might lose completion interrupt if completion interrupt occurs shortly after SLOT_STAT register is read for the previous completion interrupt if it is operating in PCI-X mode. This currently doesn't trigger as libata never queues more than one command, but it will with NCQ changes. This patch implements the workaround - turning on WoC and explicitly clearing interrupt. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 9466d85bb2c80b1aa169dda638b535f2f19714e4 Author: Tejun Heo Date: Tue Apr 11 22:32:18 2006 +0900 [PATCH] sata_sil24: consolidate host flags into SIL24_COMMON_FLAGS All sil24 controllers share the same host flags except for NPORTS. Consolidate them into SIL24_COMMON_FLAGS. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 7dafc3fd9a9e34e4a02ee6d141fd391ad5bdcd90 Author: Tejun Heo Date: Tue Apr 11 22:32:18 2006 +0900 [PATCH] sata_sil24: add more constants Add HOST_CTRL_* and more PORT_IRQ_* bits. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 3b9f1d0fb3fd68419ee3fa3e0833c6a05462150d Author: Tejun Heo Date: Tue Apr 11 22:32:18 2006 +0900 [PATCH] sata_sil24: rename PORT_IRQ_SDB_FIS to PORT_IRQ_SDB_NOTIFY Rename PORT_IRQ_SDB_FIS to more proper PORT_IRQ_SDB_NOTIFY. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 640088024dbf19553bb4b53d81e919cdf570f3b0 Author: Tejun Heo Date: Tue Apr 11 22:32:18 2006 +0900 [PATCH] sata_sil24: typo fix Type fix. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 499a86af41cf5a4bf811726841bbc49c0e96fd35 Author: Tejun Heo Date: Tue Apr 11 22:32:18 2006 +0900 [PATCH] libata: export ata_set_sata_spd() This will be used by LLDD hardreset implementation. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 51713d359ae274fa4dd4b199ba3a6b0c21ef99e0 Author: Tejun Heo Date: Tue Apr 11 22:26:29 2006 +0900 [PATCH] libata: cosmetic update to ata_bus_probe() Move ata_set_mode() failure handling outside of ap->ops->set_mode if clause such that it can handle ap->ops->set_mode failures after it's updated. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit ec573755fcd7975aae6b0d536dbcd74a6eed029c Author: Tejun Heo Date: Tue Apr 11 22:26:29 2006 +0900 [PATCH] libata: disable failed devices only once in ata_bus_probe() Devices which consumed all their changes used to be disabled every iteration. This causes unnecessary noise in the console output. Disable once and leave alone. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 7dd29dd629bd5a4e6d8a164a9886da01f291ecf2 Author: Tejun Heo Date: Tue Apr 11 22:22:30 2006 +0900 [PATCH] sata_sil24: use ata_wait_register() Replace hard-coded waiting loops in sata_sil24 to ata_wait_register(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 75fe18069a55c78f553643b4e3a24c6864d71d87 Author: Tejun Heo Date: Tue Apr 11 22:22:29 2006 +0900 [PATCH] ahci: use ata_wait_register() Replace ahci_poll_register() with ata_wait_register(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit c22daff41001e9ccead87179ac0547f85447139e Author: Tejun Heo Date: Tue Apr 11 22:22:29 2006 +0900 [PATCH] libata: implement ata_wait_register() As waiting for some register bits to change seems to be a common operation shared by some controllers, implement helper function ata_wait_register(). This function also takes care of register write flushing. Note that the condition is inverted, the wait is over when the masked value does NOT match @val. As we're waiting for bits to change, this test is more powerful and allows the function to be used in more places. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 643be977f9feba8c3c1e768fc06cac84596ec6f8 Author: Tejun Heo Date: Tue Apr 11 22:22:29 2006 +0900 [PATCH] sata_sil24: better error message from softreset Improve softreset error message. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 1c1d832cea1ab851a3f9b9d83245f5bc8b5b04b6 Author: Tejun Heo Date: Tue Apr 11 22:22:29 2006 +0900 [PATCH] sata_sil24: fix timeout calculation in sil24_softreset sil24_softreset calculated timeout by adding ATA_TMOUT_BOOT * HZ to jiffies; however, as ATA_TMOUT_BOOT is already in jiffies, multiplying by HZ makes the value way off. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 987d2f05b396760517eef7cba66b2f415ac484f5 Author: Tejun Heo Date: Tue Apr 11 22:16:45 2006 +0900 [PATCH] libata: make reset methods complain when they fail Make reset methods complain loud when they fail. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 2bf2cb26b2512c6a609bb152982c388329bedff6 Author: Tejun Heo Date: Tue Apr 11 22:16:45 2006 +0900 [PATCH] libata: kill @verbose from ata_reset_fn_t @verbose was added to ata_reset_fn_t because AHCI complained during probing if no device was attached to the port. However, muting failure message isn't the correct approach. Reset methods are responsible for detecting no device condition and finishing successfully. Now that AHCI softreset is fixed, kill @verbose. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit db70fef0750e5f8dbb64f9fadb333d2c7caf26a1 Author: Tejun Heo Date: Tue Apr 11 22:16:44 2006 +0900 [PATCH] libata: set default cbl in probeinit Make setting CBL type responsibility of probeinit. This allows using only ap->cbl == ATA_CBL_SATA test in all other parts. Without this, ata_down_sata_spd_limit() doesn't work during probe reset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 35bb94b116e1fd4959ef0d3187458b5820eac8c4 Author: Jeff Garzik Date: Tue Apr 11 13:12:34 2006 -0400 libata: Add helper ata_shost_to_port() commit 381544bba3ae6f2f1004b267da34f840b469033c Author: Jeff Garzik Date: Tue Apr 11 13:04:39 2006 -0400 libata: Fix EH merge difference between this branch and upstream. commit 591f0a4287d0de243493fd0c133c862e1d1f1c97 Author: Andy Fleming Date: Sun Apr 2 17:42:40 2006 -0500 Add 85xx CDS to arch/powerpc This patch adds support for 85xx CDS support to arch/powerpc Signed-off-by: Andy Fleming Signed-off-by: Kumar Gala commit c2a6585296009379e0f4eff39cdcb108b457ebf2 Author: Tejun Heo Date: Mon Apr 3 01:58:06 2006 +0900 [PATCH] ahci: do not fail softreset if PHY reports no device All softreset methods are responsible for detecting device presence and succeed softreset in such cases. AHCI didn't use to check for device presence before proceeding with softreset and this caused unnecessary reset retrials during probing. This patch adds presence detection to AHCI softreset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 95de719adc94392a95c3c4d0a2d6b8b1ea39d236 Author: Albert Lee Date: Tue Apr 4 10:57:18 2006 +0800 [PATCH] libata: convert ATAPI_ENABLE_DMADIR to module parameter Convert the ATAPI_ENABLE_DMADIR compile time option needed by some SATA-PATA bridge to runtime module parameter. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 31ce6daefe2d312e31ee06b0b3301b1cb7878c04 Author: Albert Lee Date: Mon Apr 3 18:31:44 2006 +0800 [PATCH] libata-dev: irq-pio minor fix 2 irq-pio minor fix 2: - Use qc as data for ata_pio_task(). Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 4332a771f4d2f23a6d3beff3dd5405e79775a211 Author: Albert Lee Date: Mon Apr 3 17:43:24 2006 +0800 [PATCH] libata-dev: irq-pio minor fix irq-pio minor fix: - remove the redundant hsm_task_state = HSM_ST_IDLE - add devno to printk() as done in upstream Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit e6f1f3c54974a30c65ea0b699809d12f0aa04272 Author: Bjorn Helgaas Date: Mon Apr 3 13:14:00 2006 -0400 ACPI: Don't print internal BIOS names of wakeup devices Internal BIOS names like these should be exposed to the user as little as possible: ACPI wakeup devices: C069 C0CE C1D1 C0DE C1D4 Eventually, the "wakeup" property of a device should be exported via the device tree, not by a printk of an internal BIOS name. For the hard-core, these are still available in /proc/acpi/wakeup_devices, just not printed to dmesg. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown commit 51d797474f87b375819d084f7583a2864c5656c4 Author: Dave Airlie Date: Mon Apr 3 16:19:26 2006 +1000 intelfb: some cleanups for intelfbhw Signed-off-by: Dave Airlie commit 3587c50991b96fee2d26942f380e36e4f40fad71 Author: Dave Airlie Date: Mon Apr 3 14:46:55 2006 +1000 intelfb: fixup pitch calculation like X does Signed-off-by: Dave Airlie commit 3aff13cfb8810cc228e8fdcb92103ed0b11ee38e Author: Dave Airlie Date: Fri Mar 31 17:08:52 2006 +1000 intelfb: fixup p calculation This fixes up the p calculation of p1 and p2 for the i9xx chipsets. This seems to work a lot better for lower pixel clocks.. Signed-off-by: Dave Airlie commit 46f60b8e67e6fceede851dc69cdee2d7c0de27b9 Author: Dave Airlie Date: Fri Mar 24 12:31:14 2006 +1100 This patch makes a needlessly global struct static. Signed-off-by: Adrian Bunk Signed-off-by: Dave Airlie commit 9a90603f65dd5046ddcd586158abcad7784892b6 Author: Dave Airlie Date: Thu Mar 23 21:53:05 2006 +1100 intelfb: add i945GM support Untested i945GM support just add the framework. Signed-off-by: Dave Airlie commit 8b91b0b4f2d731b92f59bc82492769a09b4955a6 Author: Dave Airlie Date: Thu Mar 23 19:23:48 2006 +1100 intelfb: fixup whitespace.. repeat after me, I must not take code from X without reformatting... Signed-off-by: Dave Airlie commit 8bb91f6a2d1db8031bfbb367df075f041d0cdfe2 Author: Dave Airlie Date: Thu Mar 23 13:06:32 2006 +1100 intelfb: add hw cursor support for i9xx This adds hw cursor support for the i9xx chipsets. Signed-off-by: Dave Airlie commit 7679f4d69296de97a7f62458cc4d1c6c884dfcfb Author: Dave Airlie Date: Thu Mar 23 12:30:05 2006 +1100 intelfb: make i915 modeset This takes the modeset and pll code from my X driver. Signed-off-by: Dave Airlie commit 9639d5ec07a490134f05ac890506a367aaf8663b Author: Dave Airlie Date: Thu Mar 23 11:23:55 2006 +1100 intelfb: add support for i945G This just adds the defines and structure for i945G Signed-off-by: Dave Airlie commit 0c187addabbaf93512902442b4a90140a21b0ddc Author: Dave Airlie Date: Thu Mar 23 11:20:08 2006 +1100 intelfb: enable on x86_64 i945G chipsets supports 64-bit. Signed-off-by: Dave Airlie commit 16109b3f4c1f2635afd32eb6d49348590de2cb25 Author: Dave Airlie Date: Mon Mar 20 21:22:09 2006 +1100 intelfb: add p divisor increments for i9xx. Signed-off-by: Dave Airlie commit 8492f081e5552ff388068f612eae6f55f7210ed4 Author: Dave Airlie Date: Mon Mar 20 20:54:12 2006 +1100 intelfb: change splitm to be brute force The old splitm didn't always work use a brute force. Signed-off-by: Dave Airlie commit d024960cff5173bef6e83c01cf9cd2763c2c0ab0 Author: Dave Airlie Date: Mon Mar 20 20:26:45 2006 +1100 intelfb: add pll index to the intelfb structure Add the pll index into the information structure, change get_chipset to take only the info structure, use plls in correct places commit 7258b11d2e9a47d2b01620622579f22906960e1a Author: Dave Airlie Date: Mon Mar 20 20:02:24 2006 +1100 intelfb: prepare for i9xx support. This code just moves the PLL min/max calculations variables into a structure, it doesn't change or add any new functionality. Signed-off-by: Dave Airlie commit af64371ada9452632c349563d688d30d94e918ba Author: Jeff Garzik Date: Sun Apr 2 20:41:36 2006 -0400 [libata] bump versions commit 4bced2d40555eebf8d685f174aa6d58ace353655 Author: Jeff Garzik Date: Sun Apr 2 20:17:48 2006 -0400 [libata] kill bogus cut-n-pasted comments in three drivers commit 6d5f9732a16a74d75f8cdba5b00557662e83f466 Author: Tejun Heo Date: Mon Apr 3 00:09:41 2006 +0900 [PATCH] libata: print SControl in SATA link status info message Now that libata mangles with SControl, it's helpful to print out SControl in link status message. Add it. Signed-off-by: Jeff Garzik commit c13b56a1130bbfacfb588de100e5a248383805a6 Author: Jeff Garzik Date: Sun Apr 2 10:34:24 2006 -0400 [libata] irq-pio: Fix merge mistake commit 1ad8e7f9eb051b040880e45337ed74bfd916ef7f Author: Tejun Heo Date: Sun Apr 2 18:51:53 2006 +0900 [PATCH] libata: make some libata-core routines extern Make libata-core routines which will be used by EH implementation extern. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit ece1d63619df010b8c4f08e43755e2a03f3b6eed Author: Tejun Heo Date: Sun Apr 2 18:51:53 2006 +0900 [PATCH] libata: separate out libata-eh.c A lot of EH codes are about to be added to libata. Separate out libata-eh.c. ata_scsi_timed_out(), ata_scsi_error(), ata_qc_timeout(), ata_eng_timeout(), ata_eh_qc_complete() and ata_eh_qc_retry() are moved. No code is changed by this patch. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 35e86b53b1a38e78ff0d70dae4aeb25f4572e433 Author: Tejun Heo Date: Sun Apr 2 18:51:53 2006 +0900 [PATCH] libata: dec scmd->retries for qcs with zero err_mask qcs might get retried because of unrelated failure. e.g. NCQ command failure causes the whole command set to be aborted. Decrement scmd->retries for such retrials to avoid unnecessarily failing commands. Note that scmd->retries will be incremented the first time. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit d69cf37d5387801914bbf5297f070c7d2ee0206f Author: Tejun Heo Date: Sun Apr 2 18:51:53 2006 +0900 [PATCH] libata: add @cdb to ata_exec_internal() Add @cdb to ata_exec_internal(). It will be used by new EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 74e6c8c394ca2126a60e97bc1142ec2d91761e9a Author: Tejun Heo Date: Sun Apr 2 18:51:53 2006 +0900 [PATCH] libata: don't read TF directly from sense generation functions TF register might not be directly accessible depending on errors. e.g. TF of failed NCQ command is in log page 10h. Make reading TF responsibility of error handlers. For the current EH, simply push TF reading into qc completion functions as they are practically part of EH. New EH will fill qc->tf with status registers before complting qcs. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 058e55e120ca59d37392f9aa753da2d9ead24505 Author: Tejun Heo Date: Sun Apr 2 18:51:53 2006 +0900 [PATCH] libata: always generate sense if qc->err_mask is non-zero Current sense generation code does not generate sense error if status register value doesn't indicate error condition. However, LLDD's may indicate errors which 't show up in status register. Completing such qc's without generating sense results in successful completion of failed commands. Invoke ata_to_sense_error() regardless of status register if qc->err_mask is not zero such that ata_to_sense_error() generates default sense error. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit c91af2c87e4048cdefcfc9f16fed8d728243c92d Author: Tejun Heo Date: Sun Apr 2 18:51:53 2006 +0900 [PATCH] libata: pass qc around intead of ap during PIO The current code passes pointer to ap around and repeatedly performs ata_qc_from_tag() to access the ongoing qc. This is unnatural and makes EH synchronization cumbersome. Make PIO codes deal with qc instead of ap. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 2719736779da2c7fbb17d3de16c817b429bfeb9c Author: Tejun Heo Date: Sun Apr 2 18:51:53 2006 +0900 [PATCH] libata: add ATA_QCFLAG_IO Add a new qc flag ATA_QCFLAG_IO. This flag gets set for normal IO commands originating from SCSI midlayer. This information will be used by EH to determine transfer speed reconfiguration. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit e8384607d4f395985e3cc5f82d75fc73efc2ecf0 Author: Tejun Heo Date: Sun Apr 2 18:51:53 2006 +0900 [PATCH] libata: clear ATA_DFLAG_PIO before setting it ata_dev_set_mode() is now responsible for managing ATA_DFLAG_PIO. Clear it before setting it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit ea1dd4e13010eb9dd5ffb4bfabbb472bc238bebb Author: Tejun Heo Date: Sun Apr 2 18:51:53 2006 +0900 [PATCH] libata: clear only affected flags during ata_dev_configure() ata_dev_configure() should not clear dynamic device flags determined elsewhere. Lower eight bits are reserved for feature flags, define ATA_DFLAG_CFG_MASK and clear only those bits before configuring device. Without this patch, ATA_DFLAG_PIO gets turned off during revalidation making PIO mode unuseable. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 198e0fed9e59461fc1890dd8b75ec72d14638873 Author: Tejun Heo Date: Sun Apr 2 18:51:52 2006 +0900 [PATCH] libata: rename ATA_FLAG_PORT_DISABLED to ATA_FLAG_DISABLED Rename ATA_FLAG_PORT_DISABLED to ATA_FLAG_DISABLED for consistency. (ATA_FLAG_* are always about ports). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 949b38af40a0b88b7267908b1554a45b97b5b737 Author: Tejun Heo Date: Sun Apr 2 18:51:52 2006 +0900 [PATCH] libata: clean up constants * Reorder ATA_DFLAG_* such that feature flags determined by ata_dev_configure() are on lower bits. Reserve lower eight bits for this purpose and allocate dynamic flags from bit 8. * Reorder ATA_FLAG_* such that feature flags determined during driver initiailization are on bits 0:15, dynamic flags on 16:23 and LLDD specific flags on 24:31. * Kill trailing white space and lower-case an one line comment for consistency. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit c43c555c3a6db7f0b55fd9b66d7ecff16e827d4e Author: Tejun Heo Date: Sun Apr 2 18:51:52 2006 +0900 [PATCH] libata: ATA_FLAG_IN_EH is not used, kill it Kill unused flag ATA_FLAG_IN_EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 5eb45c02a9944e813a0b82457607557a1f2c64b5 Author: Tejun Heo Date: Sun Apr 2 18:51:52 2006 +0900 [PATCH] libata: ata_dev_revalidate() printk update Make sure ata_dev_revalidate() complains on failures and kill revalidation failure message printed from ata_dev_set_mode(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit d63cb4a6365aa161341fc365df1edc87cd00c9c0 Author: Tejun Heo Date: Sun Apr 2 18:51:52 2006 +0900 [PATCH] libata: report device number when PIO fails Report device number on PIO failure. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 565083e1f14e7771aa6bac2d3d4aae0b08d48d78 Author: Tejun Heo Date: Sun Apr 2 17:54:47 2006 +0900 [PATCH] libata: consider disabled devices in ata_dev_xfermask() ata_bus_probe() now marks failed devices properly and leaves meaningful transfer mode masks. This patch makes ata_dev_xfermask() consider disable devices when determining PIO mode to avoid violating device selection timing. While at it, move port-wide resttriction out of device iteration loop and try to make the function look a bit prettier. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 14d2bac1877ed4e2cc940d1680db1a4f29225811 Author: Tejun Heo Date: Sun Apr 2 17:54:46 2006 +0900 [PATCH] libata: improve ata_bus_probe() Improve ata_bus_probe() such that configuration failures are handled better. Each device is given ATA_PROBE_MAX_TRIES chances, but any non-transient error (revalidation failure with -ENODEV, configuration failure with -EINVAL...) disables the device directly. Any IO error results in SATA PHY speed down and ata_set_mode() failure lowers transfer mode. The last try always puts a device into PIO-0. After each failure, the whole port is reset to make sure that the controller and all the devices are in a known and stable state. The reset also applies SATA SPD configuration if necessary. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit cf176e1aa92eb2a3faea8409e841396a66413937 Author: Tejun Heo Date: Sun Apr 2 17:54:46 2006 +0900 [PATCH] libata: implement ata_down_xfermask_limit() Implement ata_down_xfermask_limit(). This function manipulates @dev->pio/mwdma/udma_mask such that the next lower transfer mode is selected. This will be used to improve ata_bus_probe() failure handling and later by EH. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit edbabd8679a39faef67def4438c9cbccb5c05c5d Author: Tejun Heo Date: Sun Apr 2 20:55:02 2006 +0900 [PATCH] libata: add 5s sleep between resets Some devices react badly if resets are performed back-to-back. Give devices some time to breath and tell user that we're taking a nap. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 90dac02c08dabd471927f151b8393eb51e3e020e Author: Tejun Heo Date: Sun Apr 2 17:54:46 2006 +0900 [PATCH] libata: use SATA speed down in ata_drive_probe_reset() Make ata_drive_probe_reset() use SATA SPD configuration. Hardreset will be force if speed renegotiation is necessary. Also, if a hardreset fails, PHY speed is stepped down and hardreset is retried until the lowest speed is reached. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 1c3fae4d7eb121933341443c37d3bbee43c0fb68 Author: Tejun Heo Date: Sun Apr 2 20:53:28 2006 +0900 [PATCH] libata: implement ap->sata_spd_limit and helpers ap->sata_spd_limit contrains SATA PHY speed of the port. It is initialized to the configured value prior to probing thus preserving BIOS configured value. hardreset is responsible for applying SPD limit and sata_std_hardreset() is updated to do that. SATA SPD limit will be used to enhance failure handling during probing and later by EH. This patch also normalizes some comments around affected code. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 002c8054fa8d0f1afce2b0c728be32d338b9293a Author: Tejun Heo Date: Sun Apr 2 17:54:46 2006 +0900 [PATCH] libata: implement ata_dev_absent() For the time being we cannot use ata_dev_present() as it was renamed to ata_dev_enabled() but we still need presence test. Implement negation of the test. Conveniently, the negated result is needed in more places. This is suggested by Jeff Garzik. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 144c87b4e03759214c362d267e01c2905f1ab095 Author: Len Brown Date: Sun Apr 2 00:15:39 2006 -0500 ACPI: ia64 buildfix arch/ia64/hp/common/sba_iommu.c used ACPI_MEM_FREE instead of kfree() Signed-off-by: Len Brown Date: Sat Apr 1 23:45:39 2006 -0500 ACPI: ia64 buildfix Signed-off-by: Len Brown commit c12ea918ee175ceb3a258cd81f1c43e897d0c0bc Author: Ashok Raj Date: Tue Mar 28 17:04:00 2006 -0500 x86_64: Remove stale lapic definition from apicdef.h Signed-off-by: Ashok Raj Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit eefa27a93a0490902f33837ac86dbcf344b3aa29 Author: Ashok Raj Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: Allow hot-add of ejected processor acpi_eject_store() didn't trim processors, causing subsequent hot-add to fail. Signed-off-by: Ashok Raj Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit ff2fc3e9e3edb918b6c6b288485c6cb267bc865e Author: Jiri Slaby Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: EC acpi-ecdt-uid-hack On some boxes ecdt uid may be equal to 0, so do not test for uids equality, so that fake handler will be unconditionally removed to allow loading the real one. See http://bugzilla.kernel.org/show_bug.cgi?id=6111 Signed-off-by: Jiri Slaby Cc: Luming Yu Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit df42baa0d8e54df18dd9366dd7c93d6be7d5d063 Author: Ashok Raj Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: build fix for u8 cpu_index Local apic entries are only 8 bits, but it seemed to not be caught with u8 return value result in the check cpu_index >= NR_CPUS becomming always false. drivers/acpi/processor_core.c: In function `acpi_processor_get_info': drivers/acpi/processor_core.c:483: warning: comparison is always false due to limited range of data type Signed-off-by: Ashok Raj Cc: Dave Jones Cc: Kenji Kaneshige Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 200739c179c63d21804e9e8e2ced265243831579 Author: Bjorn Helgaas Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: remove __init/__exit from Asus .add()/.remove() methods Even though the devices claimed by asus_acpi.c can not be hot-plugged, the driver registration infrastructure allows the .add() and .remove() methods to be called at any time while the driver is registered. So remove __init and __exit from them. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 9224a867c497053842dc595e594ca6d32112221f Author: Bjorn Helgaas Date: Tue Mar 28 17:04:00 2006 -0500 HPET: fix ACPI memory range length handling ACPI address space descriptors contain _MIN, _MAX, and _LEN. _MIN and _MAX are the bounds within which the region can be moved (this is clarified in Table 6-38 of the ACPI 3.0 spec). We should use _LEN to determine the size of the region, not _MAX - _MIN + 1. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 459c7266d7a5c1730169258217e25fdd1b7ca854 Author: Bjorn Helgaas Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: fix memory hotplug range length handling Address space descriptors contain _MIN, _MAX, and _LEN. _MIN and _MAX are the bounds within which the region can be moved (this is clarified in Table 6-38 of the ACPI 3.0 spec). We should use _LEN to determine the size of the region, not _MAX - _MIN + 1. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 1a36561607abf1405b56a41aac2fd163429cd1f8 Author: Bjorn Helgaas Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: simplify scan.c coding No functional changes; just remove leftover, unused "buffer" and simplify control flow (no need to remember error values and goto the end, when we can simply return the value directly). Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit e4513a57ef719d3d6d1cee0ca4d9f4016aa452bb Author: Bjorn Helgaas Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: fix sonypi ACPI driver registration to unregister on failure Remove the assumption that acpi_bus_register_driver() returns the number of devices claimed. Returning the count is unreliable because devices may be hot-plugged in the future (admittedly not applicable for this driver). This also fixes a bug: if sonypi_acpi_driver was registered but found no devices, sonypi_exit() did not unregister it. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 578b333bfe8eb1360207a08a53c321822a8f40f3 Author: Bjorn Helgaas Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: update asus_acpi driver registration to unload on failure Remove the assumption that acpi_bus_register_driver() returns the number of devices claimed. Returning the count is unreliable because devices may be hot-plugged in the future (admittedly not applicable for this driver). Since the hardware for this driver is not hot-pluggable, determine whether the hardware is present by noticing calls to the .add() method. It would be better to probe the ACPI namespace for the ASUS HIDs, and load the driver only when we find one, but ACPI doesn't support that yet. I don't have an ASUS laptop to test on, but on my HP dl360, it does report the appropriate error when attempting to load the module: $ sudo insmod drivers/acpi/asus_acpi.ko insmod: error inserting 'drivers/acpi/asus_acpi.ko': -1 No such device Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 9d9f749b316ac21cb59ad3e595cbce469b409e1a Author: Bjorn Helgaas Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: make acpi_bus_register_driver() return success/failure, not device count acpi_bus_register_driver() should not return the number of devices claimed. We're not asking to find devices, we're making a driver available to devices, including hot-pluggable devices that may appear in the future. I audited all callers of acpi_bus_register_driver(), and except asus_acpi.c and sonypi.c (fixed in previous patches), all either ignore the return value or test only for failure (<0). Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit cd090eedd85256829f762677d0752a846c1b88b9 Author: Bjorn Helgaas Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: Display "ACPI" to motherboard resources in /proc/io{mem,port} Add "ACPI" to motherboard resource allocation names, so people have a clue about where to look. And remove some trailing spaces. Changes these /proc/iomem entries from this: ff5c1004-ff5c1007 : PM_TMR ff5c1008-ff5c100b : PM1a_EVT_BLK ff5c100c-ff5c100d : PM1a_CNT_BLK ff5c1010-ff5c1013 : GPE0_BLK ff5c1014-ff5c1017 : GPE1_BLK to this: ff5c1004-ff5c1007 : ACPI PM_TMR ff5c1008-ff5c100b : ACPI PM1a_EVT_BLK ff5c100c-ff5c100d : ACPI PM1a_CNT_BLK ff5c1010-ff5c1013 : ACPI GPE0_BLK ff5c1014-ff5c1017 : ACPI GPE1_BLK Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 81507ea9cfa64e9851b53e0fefebfa776eda9ecb Author: Bjorn Helgaas Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: request correct fixed hardware resource type (MMIO vs I/O port) ACPI supports fixed hardware (PM_TMR, GPE blocks, etc) in either I/O port or MMIO space, but used to always request the regions from I/O space because it didn't check the address_space_id. Sample ACPI fixed hardware in MMIO space (HP rx2600), was incorrectly reported in /proc/ioports, now reported in /proc/iomem: ff5c1004-ff5c1007 : PM_TMR ff5c1008-ff5c100b : PM1a_EVT_BLK ff5c100c-ff5c100d : PM1a_CNT_BLK ff5c1010-ff5c1013 : GPE0_BLK ff5c1014-ff5c1017 : GPE1_BLK Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 1c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2c Author: Bjorn Helgaas Date: Tue Mar 28 17:04:00 2006 -0500 PNPACPI: whitespace cleanup Tidy up whitespace. No functional change. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit b5f2490b6e3317059e87ba40d4f659d1c30afc1f Author: Bjorn Helgaas Date: Tue Mar 28 17:04:00 2006 -0500 PNPACPI: remove some code duplication Factor out the duplicated switch from pnpacpi_count_resources() and pnpacpi_type_resources(). Remove the unnecessary re-initialization of resource->type and length from all the encode functions (id and length are originally set in the pnpacpi_build_resource_template() -> pnpacpi_type_resources() path). Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 1acfb7f2b0d460ee86bdb25ad0679070ec8a5f0d Author: Bjorn Helgaas Date: Tue Mar 28 17:03:00 2006 -0500 PNPACPI: fix non-memory address space descriptor handling Fix resource_type handling for QWORD, DWORD, and WORD Address Space Descriptors. Previously we ignored the resource_type, so I/O ports and bus number ranges were incorrectly parsed as memory ranges. Sample PCI root bridge resources from HP rx2600 before this patch: # cat /sys/bus/pnp/devices/00:02/resources state = active mem 0x0-0x1f mem 0x0-0x3af mem 0x3e0-0x1fff mem 0x80000000-0x8fffffff With this patch: # cat /sys/bus/pnp/devices/00:02/resources state = active io 0x0-0x3af io 0x3e0-0x1fff mem 0x80000000-0x8fffffff mem 0x80004000000-0x80103fffffe Changes: 0x0-0x1f PCI bus number range was incorrectly reported as memory, now not reported at all 0x0-0x3af I/O port range was incorrectly reported as memory 0x3e0-0x1fff I/O port range was incorrectly reported as memory 0x80004000000-0x80103fffffe memory range wasn't reported at all because we only support PNP_MAX_MEM (4) memory resources Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 7e1f19e50371e1d148226b64c8edc77fec47fa5b Author: Andrew Morton Date: Tue Mar 28 17:03:00 2006 -0500 ACPI: UP build fix for bugzilla-5737 cpu_online_map doesn't exist if !CONFIG_SMP. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 1300124f69cafc54331bc06e968a8dd67863f989 Author: Adrian Bunk Date: Tue Mar 28 17:04:00 2006 -0500 ACPI: Kconfig: ACPI should depend on, not select PCI Otherwise, illegal configurations like X86_VOYAGER=y, PCI=y are possible. This patch also fixes the options select'ing ACPI to also select PCI. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Len Brown commit 852ee16a914fb3ada2f81e222677c04defc2f15f Author: Tejun Heo Date: Sat Apr 1 01:38:18 2006 +0900 [PATCH] libata: preserve SATA SPD setting over hard resets Don't overwrite SPD setting during hard reset. This change has the (intended) side effect of honoring the BIOS configuration. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit e82cbdb9a3791f781462c9d00e3486e8fb7e58a8 Author: Tejun Heo Date: Sat Apr 1 01:38:18 2006 +0900 [PATCH] libata: don't disable devices from ata_set_mode() When ata_set_mode() fails on a device, make ata_set_mode() return error code and pointer to the device instead of disabling it directly. This gives more control to higher level driving logic. This patch does not change the end result (configured transfer mode) although it may make libata repeat mode configuration to the peer of a failing device. Later ata_bus_probe() rewrite will make full use of this change. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 58a7ce64426394a46e80cdc9440cc1e7c195e85d Author: Krzysztof Halasa Date: Thu Mar 30 17:01:53 2006 +0200 [PATCH] Goramo PCI200SYN WAN driver subsystem ID patch Goramo finally got PCI subsystem ID for their PCI200SYN card. The attached patch adds support for it - cards with old EEPROM data will emit a warning with URL for update tool. Signed-off-by: Krzysztof Halasa Signed-off-by: Jeff Garzik commit b0348b90a4a8149e5a0df312ab7810793ba7b3a4 Author: Lennert Buytenhek Date: Tue Mar 28 17:19:50 2006 +0200 [PATCH] smc91x: add support for LogicPD PXA270 platform This patch adds support for the smc91x on the LogicPD PXA270 to the smc91x driver. Signed-off-by: Lennert Buytenhek Signed-off-by: Jeff Garzik commit eee6c32f5f114f9b9f2d94862f0dc0d3ff523864 Author: Albert Lee Date: Sat Apr 1 17:38:43 2006 +0800 [PATCH] libata-dev: handle DRQ=1 ERR=1 (revised) Handle DRQ=1 ERR=1 situation. Revised according to what IDE try_to_flush_leftover_data() does. Changes: - For ATA PIO writes and ATAPI devices, just stop the HSM and let EH handle it. - For ATA PIO reads, read only one block of junk data and then let EH handle it. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit e8e0619f68bff8f39d98c46aac85ed1d4557ccfd Author: Tejun Heo Date: Sat Apr 1 01:38:18 2006 +0900 [PATCH] libata: reorganize ata_set_mode() Merge ata_host_set_pio() and ata_host_set_dma() into ata_set_mode() and use function-level *dev to iterate over devices. This eases soon-to-follow ata_set_mode() interface change. While at it, kill an unnecessary comment and normalize others. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 4f65977df0b9a667fdcd85b95d457a220c94113f Author: Tejun Heo Date: Sat Apr 1 01:38:18 2006 +0900 [PATCH] libata: make ata_set_mode() handle no-device case properly Make ata_set_mode() return without doing anything if there is no device on the port. This is in preparation for ata_bus_probe() changes. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit e1211e3fa7fd05ff0d4f597fd37e40de8acc6784 Author: Tejun Heo Date: Sat Apr 1 01:38:18 2006 +0900 [PATCH] libata: implement ata_dev_enabled and disabled() This patch renames ata_dev_present() to ata_dev_enabled() and adds ata_dev_disabled(). This is to discern the state where a device is present but disabled from not-present state. This disctinction is necessary when configuring transfer mode because device selection timing must not be violated even if a device fails to configure. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 9974e7cc6c8b8ea796c92cdf28db93e4579a4000 Author: Tejun Heo Date: Sat Apr 1 01:38:17 2006 +0900 [PATCH] libata: convert do_probe_reset() to ata_do_reset() Make do_probe_reset() generic by pushing classification check into ata_drive_probe_reset() and rename it to ata_do_reset(). This will be used by EH reset. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 4c360c81a6f8d4253f7fc2e69852305676fdfa72 Author: Tejun Heo Date: Sat Apr 1 01:38:17 2006 +0900 [PATCH] libata: separate out ata_spd_string() Separate out ata_spd_string() from sata_print_link_status(). This will be used by SATA spd configuration routines. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 96072e699be08af8e7c33c56759582ea89088a02 Author: Tejun Heo Date: Sat Apr 1 01:38:17 2006 +0900 [PATCH] libata: make ata_bus_probe() return negative errno on failure ata_bus_probe() uses unsigned int rc to receive negative errno and returns the converted unsigned int value. Convert temporary variables to int and make ata_bus_probe() return negative errno on failure. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 5bbc53f4cfd28bf1d0e476ed23bc3a094eff718a Author: Tejun Heo Date: Sat Apr 1 01:38:17 2006 +0900 [PATCH] libata: fix ata_set_mode() return value Make ata_set_mode() return correct error value when ata_dev_set_mode() fails. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit ec7381d6bfd3e7b8d2880dd5e9d03b131b0603f6 Author: Len Brown Date: Sat Apr 1 05:12:23 2006 -0500 ACPI: inline trivial acpi_os_get_thread_id() acpi_os_get_thread_id() is used only for debugging code that is not enabled on Linux, so stub it out. Signed-off-by: Len Brown commit 8313524a0d466f451a62709aaedf988d8257b21c Author: Bob Moore Date: Tue Oct 3 00:00:00 2006 -0400 ACPI: ACPICA 20060310 Tagged all external interfaces to the subsystem with the new ACPI_EXPORT_SYMBOL macro. This macro can be defined as necessary to assist kernel integration. For Linux, the macro resolves to the EXPORT_SYMBOL macro. The default definition is NULL. Added the ACPI_THREAD_ID type for the return value from acpi_os_get_thread_id(). This allows the host to define this as necessary to simplify kernel integration. The default definition is ACPI_NATIVE_UINT. Valery Podrezov fixed two interpreter problems related to error processing, the deletion of objects, and placing invalid pointers onto the internal operator result stack. http://bugzilla.kernel.org/show_bug.cgi?id=6028 http://bugzilla.kernel.org/show_bug.cgi?id=6151 Increased the reference count threshold where a warning is emitted for large reference counts in order to eliminate unnecessary warnings on systems with large namespaces (especially 64-bit.) Increased the value from 0x400 to 0x800. Due to universal disagreement as to the meaning of the 'c' in the calloc() function, the ACPI_MEM_CALLOCATE macro has been renamed to ACPI_ALLOCATE_ZEROED so that the purpose of the interface is 'clear'. ACPI_MEM_ALLOCATE and ACPI_MEM_FREE are renamed to ACPI_ALLOCATE and ACPI_FREE. Signed-off-by: Bob Moore Signed-off-by: Len Brown commit ea936b78f46cbe089a4ac363e1682dee7d427096 Author: Bob Moore Date: Fri Feb 17 00:00:00 2006 -0500 ACPI: ACPICA 20060217 Implemented a change to the IndexField support to match the behavior of the Microsoft AML interpreter. The value written to the Index register is now a byte offset, no longer an index based upon the width of the Data register. This should fix IndexField problems seen on some machines where the Data register is not exactly one byte wide. The ACPI specification will be clarified on this point. Fixed a problem where several resource descriptor types could overrun the internal descriptor buffer due to size miscalculation: VendorShort, VendorLong, and Interrupt. This was noticed on IA64 machines, but could affect all platforms. Fixed a problem where individual resource descriptors were misaligned within the internal buffer, causing alignment faults on IA64 platforms. Signed-off-by: Bob Moore Signed-off-by: Len Brown commit 08a556db919f67e1e4d33ae8d40f7222da34d994 Author: Albert Lee Date: Fri Mar 31 13:29:04 2006 +0800 [PATCH] libata-dev: print out information for ATAPI devices with CDB interrupts print out information for ATAPI devices with CDB interrupts Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 52fc0b026e99b5d5d585095148d997d5634bbc25 Author: Bob Moore Date: Mon Oct 2 00:00:00 2006 -0400 [ACPI] ACPICA 20060210 Removed a couple of extraneous ACPI_ERROR messages that appeared during normal execution. These became apparent after the conversion from ACPI_DEBUG_PRINT. Fixed a problem where the CreateField operator could hang if the BitIndex or NumBits parameter referred to a named object. From Valery Podrezov. http://bugzilla.kernel.org/show_bug.cgi?id=5359 Fixed a problem where a DeRefOf operation on a buffer object incorrectly failed with an exception. This also fixes a couple of related RefOf and DeRefOf issues. From Valery Podrezov. http://bugzilla.kernel.org/show_bug.cgi?id=5360 http://bugzilla.kernel.org/show_bug.cgi?id=5387 http://bugzilla.kernel.org/show_bug.cgi?id=5392 Fixed a problem where the AE_BUFFER_LIMIT exception was returned instead of AE_STRING_LIMIT on an out-of-bounds Index() operation. From Valery Podrezov. http://bugzilla.kernel.org/show_bug.cgi?id=5480 Implemented a memory cleanup at the end of the execution of each iteration of an AML While() loop, preventing the accumulation of outstanding objects. From Valery Podrezov. http://bugzilla.kernel.org/show_bug.cgi?id=5427 Eliminated a chunk of duplicate code in the object resolution code. From Valery Podrezov. http://bugzilla.kernel.org/show_bug.cgi?id=5336 Fixed several warnings during the 64-bit code generation. Signed-off-by: Bob Moore Signed-off-by: Len Brown commit 46358614ed5b031797522f1020e989c959a8d8a6 Author: Len Brown Date: Fri Mar 31 02:16:19 2006 -0500 Revert "[PATCH] ACPI: fix vendor resource length computation" fixed in a different way by a subsequent ACPICA patch This reverts 35b73ceb9a7d10c81bd9e79e8485f7079ef2b40e commit. commit 6665bda76461308868bd1e52caf627f4cb29ed32 Author: Adrian Bunk Date: Sat Mar 11 10:12:00 2006 -0500 [ACPI] drivers/acpi/video.c: fix error path NULL pointer dereference The Coverity checker spotted this bug in acpi_video_device_lcd_query_levels(). Signed-off-by: Adrian Bunk Signed-off-by: Len Brown commit fdc136ccd3332938e989439c025c363f8479f3e6 Author: Dave Jones Date: Wed Mar 8 22:12:00 2006 -0500 [ACPI] fix possible acpi thermal leak in failure path Coverity: #601 Signed-off-by: Dave Jones Signed-off-by: Len Brown commit a1f9e65e2085e0a87f28a4d5a8ae43b32c087f24 Author: Len Brown Date: Wed Jan 25 23:47:36 2006 -0500 [ACPI] document cmdline acpi_os_name= This can sometimes be used to work around broken BIOS. Use "Microsoft Windows" to take the same path through the BIOS as Windows98 would. The default is "Microsoft Windows NT", which is what NT and later versions of Windows use, and is the most tested path through most BIOS. Set it to anything else, including "Linux", at your own risk, as it seems that virtually no BIOS has been tested with anything but the two options above. Note that this uses the legacy _OS interface, so we don't expect this to ever change. Signed-off-by: Len Brown commit 1fee94034917aa711fcbd4ebf4c36f7ebd9fa7d6 Author: Irwan Djajadi Date: Fri Jan 20 15:28:00 2006 -0500 [ACPI] drivers/acpi/hotkey.c: check kmalloc return value Signed-off-by: Irwan Djajadi Signed-off-by: Alexey Dobriyan Signed-off-by: Len Brown commit 0eacee585a89ce5827b572a73a024931506bef48 Author: Len Brown Date: Fri Mar 31 00:37:23 2006 -0500 ACPI: enable BIOS warning http://bugzilla.kernel.org/show_bug.cgi?id=5452 Signed-off-by: Len Brown commit 52a3220599647ba429fcbca2388ec35b850fa72f Author: Albert Lee Date: Sat Mar 25 18:18:15 2006 +0800 [PATCH] libata-dev: wait idle after reading the last data block Some CD-ROM drives are slow to clear DRQ, after the last data block is read by PIO. Use ata_wait_idle() after reading the last data block. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 71601958f73b952281f2b02e16d1f11c99ee0a8b Author: Albert Lee Date: Sat Mar 25 18:11:12 2006 +0800 [PATCH] libata-dev: fix the device err check sequence (respin) Current irq-pio checks ERR bit and stops on ERR before it does anything else. This behavior doesn't look right. The DRQ bit should take higher precedence than the ERR bit. Changes: - Let the HSM do the data transfer whenever the device asks for DRQ bit, even if the ERR bit is set. - For DRQ=1 ERR=1, don't trust the data Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 999bb6f4260f9499fdeab3f8fdcd8b9013eca39e Author: Albert Lee Date: Sat Mar 25 18:07:48 2006 +0800 [PATCH] libata-dev: irq-pio minor fixes (respin) irq-pio minor fixes for printk() and comments. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit c234fb00ea8999076728137d96603b713ad8b53f Author: Albert Lee Date: Sat Mar 25 17:58:38 2006 +0800 [PATCH] libata-dev: Make the the in_wq check as an inline function Make the the in_wq check easier to read as an inline function. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit c2bbc551615c21a4c280c797987dbb50f2701594 Author: Albert Lee Date: Sat Mar 25 17:56:55 2006 +0800 [PATCH] libata-dev: ata_check_atapi_dma() fix for ATA_FLAG_PIO_POLLING LLDDs ata_check_atapi_dma() fix for LLDDs with the ATA_FLAG_PIO_POLLING flag. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 27cdadef6dfe0d0614653919a110fc75ab1650ce Author: Albert Lee Date: Sat Mar 25 17:53:57 2006 +0800 [PATCH] libata-dev: Cleanup unused enums/functions Cleanup the following unused functions: - ata_pio_poll() - ata_pio_complete() - ata_pio_first_block() - ata_pio_block() - ata_pio_error() ap->pio_task_timeout and other enums. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit a1af37344f669d0fefa8c8a9e37eb6a7c086a2c2 Author: Albert Lee Date: Sat Mar 25 17:50:15 2006 +0800 [PATCH] libata-dev: Convert ata_pio_task() to use the new ata_hsm_move() Convert ata_pio_task() to use the new ata_hsm_move(). Changes: - refactor ata_pio_task() to poll device status register and - call the new ata_hsm_move() when device indicates it is not BSY. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit bb5cb290f095f17f88c912e3da35adf5b2d9500b Author: Albert Lee Date: Sat Mar 25 17:48:02 2006 +0800 [PATCH] libata-dev: Let ata_hsm_move() work with both irq-pio and polling pio Let ata_hsm_move() work with both irq-pio and polling pio codepath. Changes: - add a new parameter "in_wq" for polling pio - add return value "poll_next" to tell polling pio task whether the HSM is finished - merge code from ata_pio_first_block() to the HSM_ST_FIRST state. - call ata_poll_qc_complete() if called from the workqueue Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 6912ccd5a4a095d71fd7215ef2abea877c8fed6f Author: Albert Lee Date: Sat Mar 25 17:45:49 2006 +0800 [PATCH] libata-dev: Minor fix for ata_hsm_move() to work with ata_host_intr() Minor fix for ata_hsm_move() to work with ata_host_intr(). Changes: - WARN_ON() and comment fix - Make the HSM_ST_LAST device status checking more rigid. - Treat unknown HSM state as BUG(). Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit e2cec77117a6e4fcbac2601e2f7b0b3f4f5a4c84 Author: Albert Lee Date: Sat Mar 25 17:43:49 2006 +0800 [PATCH] libata-dev: Move out the HSM code from ata_host_intr() Move out the irq-pio HSM code from ata_host_intr() to the new ata_hsm_move() function verbatim. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 19d5d7309a928eb86f58b37165a2d501621ae3c0 Author: Albert Lee Date: Sat Mar 25 17:41:43 2006 +0800 [PATCH] libata-dev: Remove atapi_packet_task() atapi_packet_task() was replaced by ata_pio_task(). Remove the unused atapi_packet_task(). Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 13ee4628ce68d1e54df01cc31239c8887c59e65d Author: Albert Lee Date: Sat Mar 25 17:39:34 2006 +0800 [PATCH] libata-dev: Fix merge problem with upstream Fix merge problem with upstream. Changes: 1. add missing dev->cdb_len = 16 for ATA devices 2. use ata_pio_task instead of atapi_packet_task Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit cf2f7689f94ee02e52d5331bc1a87421a67a882c Author: Albert Lee Date: Sat Mar 25 17:37:53 2006 +0800 [PATCH] libata-dev: Remove trailing whitespaces Remove trailing whitespaces. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 9cfda2c94df61c9f859b474abe774c65a4464d0a Author: Andi Kleen Date: Mon Mar 27 02:24:32 2006 -0500 [ACPI] fix "nolapic" flag in ACPI mode Signed-off-by: Len Brown commit 84ac69e8bf9f36eb0166817373336d14fa58f5cc Author: Jeff Garzik Date: Fri Mar 24 09:27:49 2006 -0500 [libata] irq-pio: fix build breakage commit 200d5a7684cc49ef4be40e832daf3f217e70dfbb Author: Tejun Heo Date: Wed Feb 15 16:24:49 2006 +0900 [PATCH] libata: increase LBA48 max sectors to 65535 max_hw_sectors/max_sectors separation patch made into the tree, increase max_sectors to its hardware limit. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 46e202ec1feeac3cb722cd3410d62a9a00891388 Author: Jeff Garzik Date: Sat Mar 11 19:25:47 2006 -0500 libata: irq-pio build fixes commit c2956a3b0d1c17b38da369811a6ce93eb7a01a04 Author: Albert Lee Date: Fri Mar 3 10:34:05 2006 +0800 [PATCH] libata-dev: recognize WRITE_MULTI_FUA_EXT for r/w multiple Recognize ATA_CMD_WRITE_MULTI_FUA_EXT as r/w multiple commands. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit a5fd79ccd60b7c9cc0221dfaaa950933eff6af99 Author: Jeff Garzik Date: Mon Feb 20 05:21:14 2006 -0500 sata_vsc build fix commit db024d5398cd332023896caf70530564b15ec88e Author: Jeff Garzik Date: Mon Feb 13 00:23:57 2006 -0500 [libata] build fix after cdb_len move commit 587005de144acd3007b8e7f2a2a7c6add157c155 Author: Jeff Garzik Date: Sat Feb 11 18:17:32 2006 -0500 [libata irq-pio] s/assert/WARN_ON/ commit 41232d3ecac9df8eb94ff27330eb84b8baccc6b7 Author: Jeff Garzik Date: Thu Feb 9 04:52:55 2006 -0500 [libata] build fix after merging some pre-packet_task-removal code commit 332b5a52f2f96bc2d13bbe594a430318c0ee4425 Author: Albert Lee Date: Wed Feb 8 16:51:34 2006 +0800 [PATCH] libata-dev: Minor comment fix Signed-off-by: Albert Lee === Signed-off-by: Jeff Garzik commit 555a8965069b8e34292cbccc3ad8f619b96815fe Author: Albert Lee Date: Wed Feb 8 16:50:29 2006 +0800 [PATCH] libata-dev: Use new AC_ERR_* flags - Use new AC_ERR_* flags as done in Tejun's patches - In ata_qc_timeout(), replace ac_err_mask(drv_stat) with AC_ERR_TIMEOUT. This makes time out handler always report error to upper layer. Otherwise if the drv_stat looks good, libata might falsely report OK to the upper layer. Signed-off-by: Albert Lee === Signed-off-by: Jeff Garzik commit 20ea079e5883ab2b82fa5e576957f52e4e5c252c Author: Albert Lee Date: Wed Feb 8 16:48:49 2006 +0800 [PATCH] libata-dev: Use new ata_queue_pio_task() for PIO polling task - Use new ata_queue_pio_task() for PIO polling task. - Remove the unused ata_queue_packet_task() function. (irq-pio had merged the 2 queues into one.) Signed-off-by: Albert Lee === Signed-off-by: Jeff Garzik commit aef9d533da2eb7a5700a8c8700f2597c35cc50d1 Author: Albert Lee Date: Wed Feb 8 16:37:43 2006 +0800 [PATCH] libata-dev: Fix array index value in ata_rwcmd_protocol() Signed-off-by: Albert Lee === Signed-off-by: Jeff Garzik commit d52bb94d56676acd9bdac8e097257a87b4b1b2e1 Author: Venkatesh Pallipadi Date: Wed Dec 14 15:05:00 2005 -0500 Enable P-state software coordination via _PDC http://bugzilla.kernel.org/show_bug.cgi?id=5737 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown commit c52851b60cc0aaaf974ff0e49989fb698220447d Author: Venkatesh Pallipadi Date: Wed Dec 14 15:05:00 2005 -0500 P-state software coordination for speedstep-centrino http://bugzilla.kernel.org/show_bug.cgi?id=5737 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown commit 09b4d1ee881c8593bfad2a42f838d85070365c3e Author: Venkatesh Pallipadi Date: Wed Dec 14 15:05:00 2005 -0500 P-state software coordination for acpi-cpufreq http://bugzilla.kernel.org/show_bug.cgi?id=5737 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown commit 3b2d99429e3386b6e2ac949fc72486509c8bbe36 Author: Venkatesh Pallipadi Date: Wed Dec 14 15:05:00 2005 -0500 P-state software coordination for ACPI core http://bugzilla.kernel.org/show_bug.cgi?id=5737 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown commit ffd642e748c867a7339b57225b8bf8b9a0dcd9c5 Author: David Shaohua Li Date: Wed Feb 8 17:35:00 2006 -0500 [ACPI] enable SMP C-states on x86_64 http://bugzilla.kernel.org/show_bug.cgi?id=5653 Signed-off-by: David Shaohua Li Signed-off-by: Len Brown commit 000080c3499cd5037e60c08a8053efb9e48aa9c0 Author: Albert Lee Date: Mon Dec 26 16:48:00 2005 +0800 [PATCH] libata-dev: filter out noisy ATAPI error messages Changes: - Filter out ATAPI packet command error messages in ata_pio_error() - Filter out ATAPI packet command error messages in ata_host_intr() Signed-off-by: Albert Lee ====== Signed-off-by: Jeff Garzik commit a4f16610081001640ffe0314024bc31c10f69757 Author: Albert Lee Date: Mon Dec 26 16:40:53 2005 +0800 [PATCH] libata-dev: determine err_mask when error is found Changes: - Determine err_mask directly when an error is found. - Remove "qc->err_mask |= __ac_err_mask(status);" in ata_host_intr() Signed-off-by: Albert Lee ============ Signed-off-by: Jeff Garzik commit 3d0a59c02303df01848537b3bf938dc11e9a0ded Author: Jeff Garzik Date: Tue Dec 13 22:28:19 2005 -0500 [libata sata_promise] irq_pio: fix merge bug commit 278efe950988e72e2d0cea35059438fc27035d13 Author: Jeff Garzik Date: Tue Dec 6 05:01:27 2005 -0500 [libata] irq-pio: fix breakage related to err_mask merge commit d67e7ebb2a15bf0429c55f2fc1c4b02808367874 Author: Jeff Garzik Date: Fri Nov 18 11:55:00 2005 -0500 [libata sata_mv] IRQ PIO build fix commit 07f6f7d074e68d56d82e7cc5c65096033ac8dc56 Author: Albert Lee Date: Tue Nov 1 19:33:20 2005 +0800 [PATCH] libata irq-pio: add read/write multiple support - add is_multi_taskfile() to ata.h - initialize ata_device->multi_count with device identify data - use ata_pio_sectors() to support r/w multiple commands Signed-off-by: Albert Lee ======== Signed-off-by: Jeff Garzik commit fbcdd80b0d5bde06f3483b9a13f9599a0452431c Author: Albert Lee Date: Tue Nov 1 19:30:05 2005 +0800 [PATCH] libata irq-pio: eliminate unnecessary queuing in ata_pio_first_block() - change the return value of ata_pio_complete() 0 <-> 1 - add return value for ata_pio_first_block() - rename variable "qc_completed" to "has_next" in ata_pio_task() - use has_next to eliminate unnecessary queuing in ata_pio_first_block() Signed-off-by: Albert Lee ========== Signed-off-by: Jeff Garzik commit e27486db89ef04d5df1727c52362fa3d50cff241 Author: Albert Lee Date: Tue Nov 1 19:24:49 2005 +0800 [PATCH] libata irq-pio: merge the ata_dataout_task workqueue with ata_pio_task workqueue - remove ap->dataout_task from struct ata_port - let ata_pio_task() handle the HSM_ST_FIRST state. - rename ata_dataout_task() to ata_pio_first_block() - replace the ata_dataout_task workqueue with ata_pio_task workqueue Signed-off-by: Albert Lee ======== Signed-off-by: Jeff Garzik commit 467b16d4bebe8d251ca974eaa5da50b315206e9d Author: Albert Lee Date: Tue Nov 1 19:19:01 2005 +0800 [PATCH] libata irq-pio: misc fixes - ata_pio_block(): add ata_altstatus(ap) to prevent reading device status before it is valid - remove the unnecessary HSM_ST_IDLE state from ata_pio_task() - raise BUG() when unknown state is found in ata_pio_task() Signed-off-by: Albert Lee ============ Signed-off-by: Jeff Garzik commit 94ec1ef1cf29e137e5c79372e432b040c6604be6 Author: Jeff Garzik Date: Sun Oct 30 02:15:08 2005 -0500 [libata pdc_adma] fix for new irq-driven PIO code commit be697c3f137c9ed808753bbbc5d7751c6e5303fc Author: Jeff Garzik Date: Tue Oct 18 21:27:34 2005 -0400 [libata pdc_adma] update for removal of ATA_FLAG_NOINTR commit e33b9dfa3008fcaa908dc0c8c472a812c400f839 Author: Jeff Garzik Date: Sun Oct 9 09:51:46 2005 -0400 [libata irq-pio] build fix commit 91b8b3132e1870bfe3c4d3a999f13f20fc4e9726 Author: Albert Lee Date: Sun Oct 9 09:48:44 2005 -0400 [libata irq-pio] use PageHighMem() to optimize the kmap_atomic() usage as done in ide-scsi.c Signed-off-by: Albert Lee commit 083958d313f886dc7d00522f2972f90f55c40041 Author: Albert Lee Date: Sun Oct 9 09:47:31 2005 -0400 [libata irq-pio] reorganize "buf + offset" in ata_pio_sector() and __atapi_pio_bytes() - relocate DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); - buf + offset, buf - offset tidy up Signed-off-by: Albert Lee commit 7282aa4b49d08254ff1dcefdf3a2fb01b02ebbe2 Author: Albert Lee Date: Sun Oct 9 09:46:07 2005 -0400 [libata irq-pio] reorganize ata_pio_sector() and __atapi_pio_bytes() - move some code out of the kmap_atomic() / kunmap_atomic() zone - remove the redundant "do_write = (qc->tf.flags & ATA_TFLAG_WRITE);" Signed-off-by: Albert Lee commit c71c18576d0d8aa4db876c737c3c597c724cf02f Author: Albert Lee Date: Tue Oct 4 06:03:45 2005 -0400 libata: move atapi_send_cdb() and ata_dataout_task() to be near ata_pio_*() functions commit 54f00389563c80fa1de250a21256313ba01ca07d Author: Albert Lee Date: Fri Sep 30 19:14:19 2005 +0800 [PATCH] libata irq-pio: cleanup ata_qc_issue_prot() ata_qc_issue_prot(): - cleanup and let the PIO data out case always go through the ata_dataout_task() codepath. (Previously for PIO data out case, 2 code pathes were used - irq case goes through ata_data_out_task() codepath. - polling case jumps over the HSM_ST_FIRST state and goes to HSM_ST and ata_pio_task() directly.) ata_dataout_task(): - rearrange the queue_work() code to handle the PIO data out + polling case. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 86a7397cda08a65bc4f306e812c846e2437b5347 Author: Albert Lee Date: Fri Sep 30 19:11:35 2005 +0800 [PATCH] libata irq-pio: simplify if condition in ata_dataout_task() - Use if (qc->tf.protocol == ATA_PROT_PIO) instead of if(is_atapi_taskfile()) in ata_dataout_task() Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit f9997be974be40e884e9e8157ded2f2f9aed454c Author: Albert Lee Date: Fri Sep 30 19:09:31 2005 +0800 [PATCH] libata irq-pio: rename atapi_packet_task() and comments Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit c56b14d2a3e32695e13cd49b417da889da744d1c Author: Albert Lee Date: Fri Sep 30 19:07:39 2005 +0800 [PATCH] libata irq-pio: add comments and cleanup Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit e50362eccd8809a224cda5f71714a088ba37b2ab Author: Albert Lee Date: Tue Sep 27 17:39:50 2005 +0800 [PATCH] libata: interrupt driven pio for LLD libata.h: libata-core: Add ATA_FLAG_PIO_POLLING flag for LLDs that expect interrupt for command completion only. sata_nv.c: sata_vsc.c: irq handler is wrapper around ata_host_intr(), can handle PIO interrupts. sata_promise.c: sata_sx4.c: sata_qstor.c: sata_mv.c: Private irq handler. Polling mode ATA_FLAG_PIO_POLLING used for compatibility. Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik commit 312f7da2824c82800ee78d6190f12854456957af Author: Albert Lee Date: Tue Sep 27 17:38:03 2005 +0800 [PATCH] libata: interrupt driven pio for libata-core - add PIO_ST_FIRST for the state before sending ATAPI CDB or sending "ATA PIO data out" first data block. - add ATA_TFLAG_POLLING and ATA_DFLAG_CDB_INTR flags - remove the ATA_FLAG_NOINTR flag since the interrupt handler is now aware of the states - modify ata_pio_sector() and atapi_pio_bytes() to work in the interrupt context - modify the ata_host_intr() to handle PIO interrupts - modify ata_qc_issue_prot() to initialize states - atapi_packet_task() changed to handle "ATA PIO data out" first data block - support the pre-ATA4 ATAPI device which raise interrupt when ready to receive CDB Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- diff --git a/CREDITS b/CREDITS index 9bf714a..85c7c70 100644 --- a/CREDITS +++ b/CREDITS @@ -24,6 +24,11 @@ S: C. Negri 6, bl. D3 S: Iasi 6600 S: Romania +N: Mark Adler +E: madler@alumni.caltech.edu +W: http://alumnus.caltech.edu/~madler/ +D: zlib decompression + N: Monalisa Agrawal E: magrawal@nortelnetworks.com D: Basic Interphase 5575 driver with UBR and ABR support. @@ -1573,12 +1578,8 @@ S: 160 00 Praha 6 S: Czech Republic N: Niels Kristian Bech Jensen -E: nkbj@image.dk -W: http://www.image.dk/~nkbj +E: nkbj1970@hotmail.com D: Miscellaneous kernel updates and fixes. -S: Dr. Holsts Vej 34, lejl. 164 -S: DK-8230 Åbyhøj -S: Denmark N: Michael K. Johnson E: johnsonm@redhat.com diff --git a/Documentation/ABI/README b/Documentation/ABI/README new file mode 100644 index 0000000..9feaf16 --- /dev/null +++ b/Documentation/ABI/README @@ -0,0 +1,77 @@ +This directory attempts to document the ABI between the Linux kernel and +userspace, and the relative stability of these interfaces. Due to the +everchanging nature of Linux, and the differing maturity levels, these +interfaces should be used by userspace programs in different ways. + +We have four different levels of ABI stability, as shown by the four +different subdirectories in this location. Interfaces may change levels +of stability according to the rules described below. + +The different levels of stability are: + + stable/ + This directory documents the interfaces that the developer has + defined to be stable. Userspace programs are free to use these + interfaces with no restrictions, and backward compatibility for + them will be guaranteed for at least 2 years. Most interfaces + (like syscalls) are expected to never change and always be + available. + + testing/ + This directory documents interfaces that are felt to be stable, + as the main development of this interface has been completed. + The interface can be changed to add new features, but the + current interface will not break by doing this, unless grave + errors or security problems are found in them. Userspace + programs can start to rely on these interfaces, but they must be + aware of changes that can occur before these interfaces move to + be marked stable. Programs that use these interfaces are + strongly encouraged to add their name to the description of + these interfaces, so that the kernel developers can easily + notify them if any changes occur (see the description of the + layout of the files below for details on how to do this.) + + obsolete/ + This directory documents interfaces that are still remaining in + the kernel, but are marked to be removed at some later point in + time. The description of the interface will document the reason + why it is obsolete and when it can be expected to be removed. + The file Documentation/feature-removal-schedule.txt may describe + some of these interfaces, giving a schedule for when they will + be removed. + + removed/ + This directory contains a list of the old interfaces that have + been removed from the kernel. + +Every file in these directories will contain the following information: + +What: Short description of the interface +Date: Date created +KernelVersion: Kernel version this feature first showed up in. +Contact: Primary contact for this interface (may be a mailing list) +Description: Long description of the interface and how to use it. +Users: All users of this interface who wish to be notified when + it changes. This is very important for interfaces in + the "testing" stage, so that kernel developers can work + with userspace developers to ensure that things do not + break in ways that are unacceptable. It is also + important to get feedback for these interfaces to make + sure they are working in a proper way and do not need to + be changed further. + + +How things move between levels: + +Interfaces in stable may move to obsolete, as long as the proper +notification is given. + +Interfaces may be removed from obsolete and the kernel as long as the +documented amount of time has gone by. + +Interfaces in the testing state can move to the stable state when the +developers feel they are finished. They cannot be removed from the +kernel tree without going through the obsolete state first. + +It's up to the developer to place their interfaces in the category they +wish for it to start out in. diff --git a/Documentation/ABI/obsolete/devfs b/Documentation/ABI/obsolete/devfs new file mode 100644 index 0000000..b8b8739 --- /dev/null +++ b/Documentation/ABI/obsolete/devfs @@ -0,0 +1,13 @@ +What: devfs +Date: July 2005 +Contact: Greg Kroah-Hartman +Description: + devfs has been unmaintained for a number of years, has unfixable + races, contains a naming policy within the kernel that is + against the LSB, and can be replaced by using udev. + The files fs/devfs/*, include/linux/devfs_fs*.h will be removed, + along with the the assorted devfs function calls throughout the + kernel tree. + +Users: + diff --git a/Documentation/ABI/stable/syscalls b/Documentation/ABI/stable/syscalls new file mode 100644 index 0000000..c3ae3e7 --- /dev/null +++ b/Documentation/ABI/stable/syscalls @@ -0,0 +1,10 @@ +What: The kernel syscall interface +Description: + This interface matches much of the POSIX interface and is based + on it and other Unix based interfaces. It will only be added to + over time, and not have things removed from it. + + Note that this interface is different for every architecture + that Linux supports. Please see the architecture-specific + documentation for details on the syscall numbers that are to be + mapped to each syscall. diff --git a/Documentation/ABI/stable/sysfs-module b/Documentation/ABI/stable/sysfs-module new file mode 100644 index 0000000..75be431 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-module @@ -0,0 +1,30 @@ +What: /sys/module +Description: + The /sys/module tree consists of the following structure: + + /sys/module/MODULENAME + The name of the module that is in the kernel. This + module name will show up either if the module is built + directly into the kernel, or if it is loaded as a + dyanmic module. + + /sys/module/MODULENAME/parameters + This directory contains individual files that are each + individual parameters of the module that are able to be + changed at runtime. See the individual module + documentation as to the contents of these parameters and + what they accomplish. + + Note: The individual parameter names and values are not + considered stable, only the fact that they will be + placed in this location within sysfs. See the + individual driver documentation for details as to the + stability of the different parameters. + + /sys/module/MODULENAME/refcnt + If the module is able to be unloaded from the kernel, this file + will contain the current reference count of the module. + + Note: If the module is built into the kernel, or if the + CONFIG_MODULE_UNLOAD kernel configuration value is not enabled, + this file will not be present. diff --git a/Documentation/ABI/testing/sysfs-class b/Documentation/ABI/testing/sysfs-class new file mode 100644 index 0000000..4b0cb89 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class @@ -0,0 +1,16 @@ +What: /sys/class/ +Date: Febuary 2006 +Contact: Greg Kroah-Hartman +Description: + The /sys/class directory will consist of a group of + subdirectories describing individual classes of devices + in the kernel. The individual directories will consist + of either subdirectories, or symlinks to other + directories. + + All programs that use this directory tree must be able + to handle both subdirectories or symlinks in order to + work properly. + +Users: + udev diff --git a/Documentation/ABI/testing/sysfs-devices b/Documentation/ABI/testing/sysfs-devices new file mode 100644 index 0000000..6a25671 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices @@ -0,0 +1,25 @@ +What: /sys/devices +Date: February 2006 +Contact: Greg Kroah-Hartman +Description: + The /sys/devices tree contains a snapshot of the + internal state of the kernel device tree. Devices will + be added and removed dynamically as the machine runs, + and between different kernel versions, the layout of the + devices within this tree will change. + + Please do not rely on the format of this tree because of + this. If a program wishes to find different things in + the tree, please use the /sys/class structure and rely + on the symlinks there to point to the proper location + within the /sys/devices tree of the individual devices. + Or rely on the uevent messages to notify programs of + devices being added and removed from this tree to find + the location of those devices. + + Note that sometimes not all devices along the directory + chain will have emitted uevent messages, so userspace + programs must be able to handle such occurrences. + +Users: + udev diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index ce5d2c0..6d2412e 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle @@ -155,7 +155,83 @@ problem, which is called the function-gr See next chapter. - Chapter 5: Functions + Chapter 5: Typedefs + +Please don't use things like "vps_t". + +It's a _mistake_ to use typedef for structures and pointers. When you see a + + vps_t a; + +in the source, what does it mean? + +In contrast, if it says + + struct virtual_container *a; + +you can actually tell what "a" is. + +Lots of people think that typedefs "help readability". Not so. They are +useful only for: + + (a) totally opaque objects (where the typedef is actively used to _hide_ + what the object is). + + Example: "pte_t" etc. opaque objects that you can only access using + the proper accessor functions. + + NOTE! Opaqueness and "accessor functions" are not good in themselves. + The reason we have them for things like pte_t etc. is that there + really is absolutely _zero_ portably accessible information there. + + (b) Clear integer types, where the abstraction _helps_ avoid confusion + whether it is "int" or "long". + + u8/u16/u32 are perfectly fine typedefs, although they fit into + category (d) better than here. + + NOTE! Again - there needs to be a _reason_ for this. If something is + "unsigned long", then there's no reason to do + + typedef unsigned long myflags_t; + + but if there is a clear reason for why it under certain circumstances + might be an "unsigned int" and under other configurations might be + "unsigned long", then by all means go ahead and use a typedef. + + (c) when you use sparse to literally create a _new_ type for + type-checking. + + (d) New types which are identical to standard C99 types, in certain + exceptional circumstances. + + Although it would only take a short amount of time for the eyes and + brain to become accustomed to the standard types like 'uint32_t', + some people object to their use anyway. + + Therefore, the Linux-specific 'u8/u16/u32/u64' types and their + signed equivalents which are identical to standard types are + permitted -- although they are not mandatory in new code of your + own. + + When editing existing code which already uses one or the other set + of types, you should conform to the existing choices in that code. + + (e) Types safe for use in userspace. + + In certain structures which are visible to userspace, we cannot + require C99 types and cannot use the 'u32' form above. Thus, we + use __u32 and similar types in all structures which are shared + with userspace. + +Maybe there are other cases too, but the rule should basically be to NEVER +EVER use a typedef unless you can clearly match one of those rules. + +In general, a pointer, or a struct that has elements that can reasonably +be directly accessed should _never_ be a typedef. + + + Chapter 6: Functions Functions should be short and sweet, and do just one thing. They should fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24, @@ -183,7 +259,7 @@ and it gets confused. You know you're b to understand what you did 2 weeks from now. - Chapter 6: Centralized exiting of functions + Chapter 7: Centralized exiting of functions Albeit deprecated by some people, the equivalent of the goto statement is used frequently by compilers in form of the unconditional jump instruction. @@ -220,7 +296,7 @@ out: return result; } - Chapter 7: Commenting + Chapter 8: Commenting Comments are good, but there is also a danger of over-commenting. NEVER try to explain HOW your code works in a comment: it's much better to @@ -240,7 +316,7 @@ When commenting the kernel API functions See the files Documentation/kernel-doc-nano-HOWTO.txt and scripts/kernel-doc for details. - Chapter 8: You've made a mess of it + Chapter 9: You've made a mess of it That's OK, we all do. You've probably been told by your long-time Unix user helper that "GNU emacs" automatically formats the C sources for @@ -288,7 +364,7 @@ re-formatting you may want to take a loo remember: "indent" is not a fix for bad programming. - Chapter 9: Configuration-files + Chapter 10: Configuration-files For configuration options (arch/xxx/Kconfig, and all the Kconfig files), somewhat different indentation is used. @@ -313,7 +389,7 @@ support for file-systems, for instance) experimental options should be denoted (EXPERIMENTAL). - Chapter 10: Data structures + Chapter 11: Data structures Data structures that have visibility outside the single-threaded environment they are created and destroyed in should always have @@ -344,7 +420,7 @@ Remember: if another thread can find you have a reference count on it, you almost certainly have a bug. - Chapter 11: Macros, Enums and RTL + Chapter 12: Macros, Enums and RTL Names of macros defining constants and labels in enums are capitalized. @@ -399,7 +475,7 @@ The cpp manual deals with macros exhaust covers RTL which is used frequently with assembly language in the kernel. - Chapter 12: Printing kernel messages + Chapter 13: Printing kernel messages Kernel developers like to be seen as literate. Do mind the spelling of kernel messages to make a good impression. Do not use crippled @@ -410,7 +486,7 @@ Kernel messages do not have to be termin Printing numbers in parentheses (%d) adds no value and should be avoided. - Chapter 13: Allocating memory + Chapter 14: Allocating memory The kernel provides the following general purpose memory allocators: kmalloc(), kzalloc(), kcalloc(), and vmalloc(). Please refer to the API @@ -429,7 +505,7 @@ from void pointer to any other pointer t language. - Chapter 14: The inline disease + Chapter 15: The inline disease There appears to be a common misperception that gcc has a magic "make me faster" speedup option called "inline". While the use of inlines can be @@ -457,7 +533,7 @@ something it would have done anyway. - Chapter 15: References + Appendix I: References The C Programming Language, Second Edition by Brian W. Kernighan and Dennis M. Ritchie. @@ -481,4 +557,4 @@ Kernel CodingStyle, by greg@kroah.com at http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ -- -Last updated on 30 December 2005 by a community effort on LKML. +Last updated on 30 April 2006. diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index ca02e04..3630a0d 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -62,6 +62,8 @@ Internal Functions !Ikernel/exit.c !Ikernel/signal.c +!Iinclude/linux/kthread.h +!Ekernel/kthread.c Kernel objects manipulation @@ -114,9 +116,33 @@ X!Ilib/string.c + + Basic Kernel Library Functions + + + The Linux kernel provides more basic utility functions. + + + Bitmap Operations +!Elib/bitmap.c +!Ilib/bitmap.c + + + Command-line Parsing +!Elib/cmdline.c + + + CRC Functions +!Elib/crc16.c +!Elib/crc32.c +!Elib/crc-ccitt.c + + + Memory Management in Linux The Slab Cache +!Iinclude/linux/slab.h !Emm/slab.c User Space Memory Access @@ -280,12 +306,13 @@ X!Ekernel/module.c MTRR Handling !Earch/i386/kernel/cpu/mtrr/main.c + PCI Support Library !Edrivers/pci/pci.c !Edrivers/pci/pci-driver.c !Edrivers/pci/remove.c !Edrivers/pci/pci-acpi.c - !Edrivers/pci/msi.c @@ -314,6 +341,13 @@ X!Earch/i386/kernel/mca.c + + Firmware Interfaces + DMI Interfaces +!Edrivers/firmware/dmi_scan.c + + + The Device File System !Efs/devfs/base.c @@ -331,6 +365,18 @@ X!Earch/i386/kernel/mca.c !Esecurity/security.c + + Audit Interfaces +!Ekernel/audit.c +!Ikernel/auditsc.c +!Ikernel/auditfilter.c + + + + Accounting Framework +!Ikernel/acct.c + + Power Management !Ekernel/power/pm.c @@ -390,7 +436,6 @@ X!Edrivers/pnp/system.c - Block Devices !Eblock/ll_rw_blk.c @@ -401,6 +446,14 @@ X!Edrivers/pnp/system.c !Edrivers/char/misc.c + + Parallel Port Devices +!Iinclude/linux/parport.h +!Edrivers/parport/ieee1284.c +!Edrivers/parport/share.c +!Idrivers/parport/daisy.c + + Video4Linux !Edrivers/media/video/videodev.c diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl index 158ffe9..644c388 100644 --- a/Documentation/DocBook/kernel-locking.tmpl +++ b/Documentation/DocBook/kernel-locking.tmpl @@ -1590,7 +1590,7 @@ the amount of locking which needs to be Our final dilemma is this: when can we actually destroy the removed element? Remember, a reader might be stepping through - this element in the list right now: it we free this element and + this element in the list right now: if we free this element and the next pointer changes, the reader will jump off into garbage and crash. We need to wait until we know that all the readers who were traversing the list when we deleted the diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl index f869b03..e97c323 100644 --- a/Documentation/DocBook/libata.tmpl +++ b/Documentation/DocBook/libata.tmpl @@ -169,6 +169,22 @@ void (*tf_read) (struct ata_port *ap, st + PIO data read/write + +void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int); + + + +All bmdma-style drivers must implement this hook. This is the low-level +operation that actually copies the data bytes during a PIO data +transfer. +Typically the driver +will choose one of ata_pio_data_xfer_noirq(), ata_pio_data_xfer(), or +ata_mmio_data_xfer(). + + + + ATA command execute void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); @@ -204,11 +220,10 @@ command. u8 (*check_status)(struct ata_port *ap); u8 (*check_altstatus)(struct ata_port *ap); -u8 (*check_err)(struct ata_port *ap); - Reads the Status/AltStatus/Error ATA shadow register from + Reads the Status/AltStatus ATA shadow register from hardware. On some hardware, reading the Status register has the side effect of clearing the interrupt condition. Most drivers for taskfile-based hardware use @@ -269,23 +284,6 @@ void (*set_mode) (struct ata_port *ap); - Reset ATA bus - -void (*phy_reset) (struct ata_port *ap); - - - - The very first step in the probe phase. Actions vary depending - on the bus type, typically. After waking up the device and probing - for device presence (PATA and SATA), typically a soft reset - (SRST) will be performed. Drivers typically use the helper - functions ata_bus_reset() or sata_phy_reset() for this hook. - Many SATA drivers use sata_phy_reset() or call it from within - their own phy_reset() functions. - - - - Control PCI IDE BMDMA engine void (*bmdma_setup) (struct ata_queued_cmd *qc); @@ -354,16 +352,74 @@ int (*qc_issue) (struct ata_queued_cmd * - Timeout (error) handling + Exception and probe handling (EH) void (*eng_timeout) (struct ata_port *ap); +void (*phy_reset) (struct ata_port *ap); + + + +Deprecated. Use ->error_handler() instead. + + + +void (*freeze) (struct ata_port *ap); +void (*thaw) (struct ata_port *ap); + + + +ata_port_freeze() is called when HSM violations or some other +condition disrupts normal operation of the port. A frozen port +is not allowed to perform any operation until the port is +thawed, which usually follows a successful reset. + + + +The optional ->freeze() callback can be used for freezing the port +hardware-wise (e.g. mask interrupt and stop DMA engine). If a +port cannot be frozen hardware-wise, the interrupt handler +must ack and clear interrupts unconditionally while the port +is frozen. + + +The optional ->thaw() callback is called to perform the opposite of ->freeze(): +prepare the port for normal operation once again. Unmask interrupts, +start DMA engine, etc. + + + +void (*error_handler) (struct ata_port *ap); + + + +->error_handler() is a driver's hook into probe, hotplug, and recovery +and other exceptional conditions. The primary responsibility of an +implementation is to call ata_do_eh() or ata_bmdma_drive_eh() with a set +of EH hooks as arguments: + + + +'prereset' hook (may be NULL) is called during an EH reset, before any other actions +are taken. + + + +'postreset' hook (may be NULL) is called after the EH reset is performed. Based on +existing conditions, severity of the problem, and hardware capabilities, + + + +Either 'softreset' (may be NULL) or 'hardreset' (may be NULL) will be +called to perform the low-level EH reset. + + + +void (*post_internal_cmd) (struct ata_queued_cmd *qc); -This is a high level error handling function, called from the -error handling thread, when a command times out. Most newer -hardware will implement its own error handling code here. IDE BMDMA -drivers may use the helper function ata_eng_timeout(). +Perform any hardware-specific actions necessary to finish processing +after executing a probe-time or EH-time command via ata_exec_internal(). diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt index 49e27cc..1d50cf0 100644 --- a/Documentation/RCU/checklist.txt +++ b/Documentation/RCU/checklist.txt @@ -144,9 +144,47 @@ over a rather long period of time, but i whether the increased speed is worth it. 8. Although synchronize_rcu() is a bit slower than is call_rcu(), - it usually results in simpler code. So, unless update performance - is important or the updaters cannot block, synchronize_rcu() - should be used in preference to call_rcu(). + it usually results in simpler code. So, unless update + performance is critically important or the updaters cannot block, + synchronize_rcu() should be used in preference to call_rcu(). + + An especially important property of the synchronize_rcu() + primitive is that it automatically self-limits: if grace periods + are delayed for whatever reason, then the synchronize_rcu() + primitive will correspondingly delay updates. In contrast, + code using call_rcu() should explicitly limit update rate in + cases where grace periods are delayed, as failing to do so can + result in excessive realtime latencies or even OOM conditions. + + Ways of gaining this self-limiting property when using call_rcu() + include: + + a. Keeping a count of the number of data-structure elements + used by the RCU-protected data structure, including those + waiting for a grace period to elapse. Enforce a limit + on this number, stalling updates as needed to allow + previously deferred frees to complete. + + Alternatively, limit only the number awaiting deferred + free rather than the total number of elements. + + b. Limiting update rate. For example, if updates occur only + once per hour, then no explicit rate limiting is required, + unless your system is already badly broken. The dcache + subsystem takes this approach -- updates are guarded + by a global lock, limiting their rate. + + c. Trusted update -- if updates can only be done manually by + superuser or some other trusted user, then it might not + be necessary to automatically limit them. The theory + here is that superuser already has lots of ways to crash + the machine. + + d. Use call_rcu_bh() rather than call_rcu(), in order to take + advantage of call_rcu_bh()'s faster grace periods. + + e. Periodically invoke synchronize_rcu(), permitting a limited + number of updates per grace period. 9. All RCU list-traversal primitives, which include list_for_each_rcu(), list_for_each_entry_rcu(), diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index 07cb93b..4f41a60 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt @@ -184,7 +184,17 @@ synchronize_rcu() blocking, it registers a function and argument which are invoked after all ongoing RCU read-side critical sections have completed. This callback variant is particularly useful in situations where - it is illegal to block. + it is illegal to block or where update-side performance is + critically important. + + However, the call_rcu() API should not be used lightly, as use + of the synchronize_rcu() API generally results in simpler code. + In addition, the synchronize_rcu() API has the nice property + of automatically limiting update rate should grace periods + be delayed. This property results in system resilience in face + of denial-of-service attacks. Code using call_rcu() should limit + update rate in order to gain this same sort of resilience. See + checklist.txt for some approaches to limiting the update rate. rcu_assign_pointer() @@ -790,7 +800,6 @@ RCU pointer update: RCU grace period: - synchronize_kernel (deprecated) synchronize_net synchronize_sched synchronize_rcu diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist new file mode 100644 index 0000000..8230098 --- /dev/null +++ b/Documentation/SubmitChecklist @@ -0,0 +1,57 @@ +Linux Kernel patch sumbittal checklist +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Here are some basic things that developers should do if they +want to see their kernel patch submittals accepted quicker. + +These are all above and beyond the documentation that is provided +in Documentation/SubmittingPatches and elsewhere about submitting +Linux kernel patches. + + + +- Builds cleanly with applicable or modified CONFIG options =y, =m, and =n. + No gcc warnings/errors, no linker warnings/errors. + +- Passes allnoconfig, allmodconfig + +- Builds on multiple CPU arch-es by using local cross-compile tools + or something like PLM at OSDL. + +- ppc64 is a good architecture for cross-compilation checking because it + tends to use `unsigned long' for 64-bit quantities. + +- Matches kernel coding style(!) + +- Any new or modified CONFIG options don't muck up the config menu. + +- All new Kconfig options have help text. + +- Has been carefully reviewed with respect to relevant Kconfig + combinations. This is very hard to get right with testing -- + brainpower pays off here. + +- Check cleanly with sparse. + +- Use 'make checkstack' and 'make namespacecheck' and fix any + problems that they find. Note: checkstack does not point out + problems explicitly, but any one function that uses more than + 512 bytes on the stack is a candidate for change. + +- Include kernel-doc to document global kernel APIs. (Not required + for static functions, but OK there also.) Use 'make htmldocs' + or 'make mandocs' to check the kernel-doc and fix any issues. + +- Has been tested with CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, + CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, + CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_SPINLOCK_SLEEP all simultaneously + enabled. + +- Has been build- and runtime tested with and without CONFIG_SMP and + CONFIG_PREEMPT. + +- If the patch affects IO/Disk, etc: has been tested with and without + CONFIG_LBD. + + +2006-APR-27 diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt index 8c6ee68..3e46d2a 100644 --- a/Documentation/arm/Samsung-S3C24XX/Overview.txt +++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt @@ -7,11 +7,13 @@ Introduction ------------ The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported - by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 and - the S3C2440 are supported CPUs. + by the 's3c2410' architecture of ARM Linux. Currently the S3C2410, + S3C2440 and S3C2442 devices are supported. Support for the S3C2400 series is in progress. + Support for the S3C2412 and S3C2413 CPUs is being merged. + Configuration ------------- @@ -43,9 +45,18 @@ Machines Samsung's own development board, geared for PDA work. + Samsung/Aiji SMDK2412 + + The S3C2412 version of the SMDK2440. + + Samsung/Aiji SMDK2413 + + The S3C2412 version of the SMDK2440. + Samsung/Meritech SMDK2440 - The S3C2440 compatible version of the SMDK2440 + The S3C2440 compatible version of the SMDK2440, which has the + option of an S3C2440 or S3C2442 CPU module. Thorcom VR1000 @@ -211,24 +222,6 @@ Port Contributors Lucas Correia Villa Real (S3C2400 port) -Document Changes ----------------- - - 05 Sep 2004 - BJD - Added Document Changes section - 05 Sep 2004 - BJD - Added Klaus Fetscher to list of contributors - 25 Oct 2004 - BJD - Added Dimitry Andric to list of contributors - 25 Oct 2004 - BJD - Updated the MTD from the 2.6.9 merge - 21 Jan 2005 - BJD - Added rx3715, added Shannon to contributors - 10 Feb 2005 - BJD - Added Guillaume Gourat to contributors - 02 Mar 2005 - BJD - Added SMDK2440 to list of machines - 06 Mar 2005 - BJD - Added Christer Weinigel - 08 Mar 2005 - BJD - Added LCVR to list of people, updated introduction - 08 Mar 2005 - BJD - Added section on adding machines - 09 Sep 2005 - BJD - Added section on platform data - 11 Feb 2006 - BJD - Added I2C, RTC and Watchdog sections - 11 Feb 2006 - BJD - Added Osiris machine, and S3C2400 information - - Document Author --------------- diff --git a/Documentation/arm/Samsung-S3C24XX/S3C2412.txt b/Documentation/arm/Samsung-S3C24XX/S3C2412.txt new file mode 100644 index 0000000..cb82a7f --- /dev/null +++ b/Documentation/arm/Samsung-S3C24XX/S3C2412.txt @@ -0,0 +1,120 @@ + S3C2412 ARM Linux Overview + ========================== + +Introduction +------------ + + The S3C2412 is part of the S3C24XX range of ARM9 System-on-Chip CPUs + from Samsung. This part has an ARM926-EJS core, capable of running up + to 266MHz (see data-sheet for more information) + + +Clock +----- + + The core clock code provides a set of clocks to the drivers, and allows + for source selection and a number of other features. + + +Power +----- + + No support for suspend/resume to RAM in the current system. + + +DMA +--- + + No current support for DMA. + + +GPIO +---- + + There is support for setting the GPIO to input/output/special function + and reading or writing to them. + + +UART +---- + + The UART hardware is similar to the S3C2440, and is supported by the + s3c2410 driver in the drivers/serial directory. + + +NAND +---- + + The NAND hardware is similar to the S3C2440, and is supported by the + s3c2410 driver in the drivers/mtd/nand directory. + + +USB Host +-------- + + The USB hardware is similar to the S3C2410, with extended clock source + control. The OHCI portion is supported by the ohci-s3c2410 driver, and + the clock control selection is supported by the core clock code. + + +USB Device +---------- + + No current support in the kernel + + +IRQs +---- + + All the standard, and external interrupt sources are supported. The + extra sub-sources are not yet supported. + + +RTC +--- + + The RTC hardware is similar to the S3C2410, and is supported by the + s3c2410-rtc driver. + + +Watchdog +-------- + + The watchdog harware is the same as the S3C2410, and is supported by + the s3c2410_wdt driver. + + +MMC/SD/SDIO +----------- + + No current support for the MMC/SD/SDIO block. + +IIC +--- + + The IIC hardware is the same as the S3C2410, and is supported by the + i2c-s3c24xx driver. + + +IIS +--- + + No current support for the IIS interface. + + +SPI +--- + + No current support for the SPI interfaces. + + +ATA +--- + + No current support for the on-board ATA block. + + +Document Author +--------------- + +Ben Dooks, (c) 2006 Simtec Electronics diff --git a/Documentation/arm/Samsung-S3C24XX/S3C2413.txt b/Documentation/arm/Samsung-S3C24XX/S3C2413.txt new file mode 100644 index 0000000..ab2a888 --- /dev/null +++ b/Documentation/arm/Samsung-S3C24XX/S3C2413.txt @@ -0,0 +1,21 @@ + S3C2413 ARM Linux Overview + ========================== + +Introduction +------------ + + The S3C2413 is an extended version of the S3C2412, with an camera + interface and mobile DDR memory support. See the S3C2412 support + documentation for more information. + + +Camera Interface +--------------- + + This block is currently not supported. + + +Document Author +--------------- + +Ben Dooks, (c) 2006 Simtec Electronics diff --git a/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen b/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen new file mode 100644 index 0000000..1e6a23f --- /dev/null +++ b/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen @@ -0,0 +1,61 @@ +README on the ADC/Touchscreen Controller +======================================== + +The LH79524 and LH7A404 include a built-in Analog to Digital +controller (ADC) that is used to process input from a touchscreen. +The driver only implements a four-wire touch panel protocol. + +The touchscreen driver is maintenance free except for the pen-down or +touch threshold. Some resistive displays and board combinations may +require tuning of this threshold. The driver exposes some of it's +internal state in the sys filesystem. If the kernel is configured +with it, CONFIG_SYSFS, and sysfs is mounted at /sys, there will be a +directory + + /sys/devices/platform/adc-lh7.0 + +containing these files. + + -r--r--r-- 1 root root 4096 Jan 1 00:00 samples + -rw-r--r-- 1 root root 4096 Jan 1 00:00 threshold + -r--r--r-- 1 root root 4096 Jan 1 00:00 threshold_range + +The threshold is the current touch threshold. It defaults to 750 on +most targets. + + # cat threshold + 750 + +The threshold_range contains the range of valid values for the +threshold. Values outside of this range will be silently ignored. + + # cat threshold_range + 0 1023 + +To change the threshold, write a value to the threshold file. + + # echo 500 > threshold + # cat threshold + 500 + +The samples file contains the most recently sampled values from the +ADC. There are 12. Below are typical of the last sampled values when +the pen has been released. The first two and last two samples are for +detecting whether or not the pen is down. The third through sixth are +X coordinate samples. The seventh through tenth are Y coordinate +samples. + + # cat samples + 1023 1023 0 0 0 0 530 529 530 529 1023 1023 + +To determine a reasonable threshold, press on the touch panel with an +appropriate stylus and read the values from samples. + + # cat samples + 1023 676 92 103 101 102 855 919 922 922 1023 679 + +The first and eleventh samples are discarded. Thus, the important +values are the second and twelfth which are used to determine if the +pen is down. When both are below the threshold, the driver registers +that the pen is down. When either is above the threshold, it +registers then pen is up. diff --git a/Documentation/arm/Sharp-LH/LCDPanels b/Documentation/arm/Sharp-LH/LCDPanels new file mode 100644 index 0000000..fb1b21c --- /dev/null +++ b/Documentation/arm/Sharp-LH/LCDPanels @@ -0,0 +1,59 @@ +README on the LCD Panels +======================== + +Configuration options for several LCD panels, available from Logic PD, +are included in the kernel source. This README will help you +understand the configuration data and give you some guidance for +adding support for other panels if you wish. + + +lcd-panels.h +------------ + +There is no way, at present, to detect which panel is attached to the +system at runtime. Thus the kernel configuration is static. The file +arch/arm/mach-ld7a40x/lcd-panels.h (or similar) defines all of the +panel specific parameters. + +It should be possible for this data to be shared among several device +families. The current layout may be insufficiently general, but it is +amenable to improvement. + + +PIXEL_CLOCK +----------- + +The panel data sheets will give a range of acceptable pixel clocks. +The fundamental LCDCLK input frequency is divided down by a PCD +constant in field '.tim2'. It may happen that it is impossible to set +the pixel clock within this range. A clock which is too slow will +tend to flicker. For the highest quality image, set the clock as high +as possible. + + +MARGINS +------- + +These values may be difficult to glean from the panel data sheet. In +the case of the Sharp panels, the upper margin is explicitly called +out as a specific number of lines from the top of the frame. The +other values may not matter as much as the panels tend to +automatically center the image. + + +Sync Sense +---------- + +The sense of the hsync and vsync pulses may be called out in the data +sheet. On one panel, the sense of these pulses determine the height +of the visible region on the panel. Most of the Sharp panels use +negative sense sync pulses set by the TIM2_IHS and TIM2_IVS bits in +'.tim2'. + + +Pel Layout +---------- + +The Sharp color TFT panels are all configured for 16 bit direct color +modes. The amba-lcd driver sets the pel mode to 565 for 5 bits of +each red and blue and 6 bits of green. diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt index 23a1c24..2a63d56 100644 --- a/Documentation/atomic_ops.txt +++ b/Documentation/atomic_ops.txt @@ -157,13 +157,13 @@ For example, smp_mb__before_atomic_dec() smp_mb__before_atomic_dec(); atomic_dec(&obj->ref_count); -It makes sure that all memory operations preceeding the atomic_dec() +It makes sure that all memory operations preceding the atomic_dec() call are strongly ordered with respect to the atomic counter -operation. In the above example, it guarentees that the assignment of +operation. In the above example, it guarantees that the assignment of "1" to obj->dead will be globally visible to other cpus before the atomic counter decrement. -Without the explicitl smp_mb__before_atomic_dec() call, the +Without the explicit smp_mb__before_atomic_dec() call, the implementation could legally allow the atomic counter update visible to other cpus before the "obj->dead = 1;" assignment. @@ -173,11 +173,11 @@ (smp_mb__after_atomic_dec()) and around (smp_mb__{before,after}_atomic_inc()). A missing memory barrier in the cases where they are required by the -atomic_t implementation above can have disasterous results. Here is -an example, which follows a pattern occuring frequently in the Linux +atomic_t implementation above can have disastrous results. Here is +an example, which follows a pattern occurring frequently in the Linux kernel. It is the use of atomic counters to implement reference counting, and it works such that once the counter falls to zero it can -be guarenteed that no other entity can be accessing the object: +be guaranteed that no other entity can be accessing the object: static void obj_list_add(struct obj *obj) { @@ -291,9 +291,9 @@ to the size of an "unsigned long" C data size. The endianness of the bits within each "unsigned long" are the native endianness of the cpu. - void set_bit(unsigned long nr, volatils unsigned long *addr); - void clear_bit(unsigned long nr, volatils unsigned long *addr); - void change_bit(unsigned long nr, volatils unsigned long *addr); + void set_bit(unsigned long nr, volatile unsigned long *addr); + void clear_bit(unsigned long nr, volatile unsigned long *addr); + void change_bit(unsigned long nr, volatile unsigned long *addr); These routines set, clear, and change, respectively, the bit number indicated by "nr" on the bit mask pointed to by "ADDR". @@ -301,9 +301,9 @@ indicated by "nr" on the bit mask pointe They must execute atomically, yet there are no implicit memory barrier semantics required of these interfaces. - int test_and_set_bit(unsigned long nr, volatils unsigned long *addr); - int test_and_clear_bit(unsigned long nr, volatils unsigned long *addr); - int test_and_change_bit(unsigned long nr, volatils unsigned long *addr); + int test_and_set_bit(unsigned long nr, volatile unsigned long *addr); + int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr); + int test_and_change_bit(unsigned long nr, volatile unsigned long *addr); Like the above, except that these routines return a boolean which indicates whether the changed bit was set _BEFORE_ the atomic bit @@ -335,7 +335,7 @@ subsequent memory operation is made visi /* ... */; obj->killed = 1; -The implementation of test_and_set_bit() must guarentee that +The implementation of test_and_set_bit() must guarantee that "obj->dead = 1;" is visible to cpus before the atomic memory operation done by test_and_set_bit() becomes visible. Likewise, the atomic memory operation done by test_and_set_bit() must become visible before @@ -474,7 +474,7 @@ Now, as far as memory barriers go, as lo strictly orders all subsequent memory operations (including the cas()) with respect to itself, things will be fine. -Said another way, _atomic_dec_and_lock() must guarentee that +Said another way, _atomic_dec_and_lock() must guarantee that a counter dropping to zero is never made visible before the spinlock being acquired. diff --git a/Documentation/console/console.txt b/Documentation/console/console.txt new file mode 100644 index 0000000..d3e1744 --- /dev/null +++ b/Documentation/console/console.txt @@ -0,0 +1,144 @@ +Console Drivers +=============== + +The linux kernel has 2 general types of console drivers. The first type is +assigned by the kernel to all the virtual consoles during the boot process. +This type will be called 'system driver', and only one system driver is allowed +to exist. The system driver is persistent and it can never be unloaded, though +it may become inactive. + +The second type has to be explicitly loaded and unloaded. This will be called +'modular driver' by this document. Multiple modular drivers can coexist at +any time with each driver sharing the console with other drivers including +the system driver. However, modular drivers cannot take over the console +that is currently occupied by another modular driver. (Exception: Drivers that +call take_over_console() will succeed in the takeover regardless of the type +of driver occupying the consoles.) They can only take over the console that is +occupied by the system driver. In the same token, if the modular driver is +released by the console, the system driver will take over. + +Modular drivers, from the programmer's point of view, has to call: + + take_over_console() - load and bind driver to console layer + give_up_console() - unbind and unload driver + +In newer kernels, the following are also available: + + register_con_driver() + unregister_con_driver() + +If sysfs is enabled, the contents of /sys/class/vtconsole can be +examined. This shows the console backends currently registered by the +system which are named vtcon where is an integer fro 0 to 15. Thus: + + ls /sys/class/vtconsole + . .. vtcon0 vtcon1 + +Each directory in /sys/class/vtconsole has 3 files: + + ls /sys/class/vtconsole/vtcon0 + . .. bind name uevent + +What do these files signify? + + 1. bind - this is a read/write file. It shows the status of the driver if + read, or acts to bind or unbind the driver to the virtual consoles + when written to. The possible values are: + + 0 - means the driver is not bound and if echo'ed, commands the driver + to unbind + + 1 - means the driver is bound and if echo'ed, commands the driver to + bind + + 2. name - read-only file. Shows the name of the driver in this format: + + cat /sys/class/vtconsole/vtcon0/name + (S) VGA+ + + '(S)' stands for a (S)ystem driver, ie, it cannot be directly + commanded to bind or unbind + + 'VGA+' is the name of the driver + + cat /sys/class/vtconsole/vtcon1/name + (M) frame buffer device + + In this case, '(M)' stands for a (M)odular driver, one that can be + directly commanded to bind or unbind. + + 3. uevent - ignore this file + +When unbinding, the modular driver is detached first, and then the system +driver takes over the consoles vacated by the driver. Binding, on the other +hand, will bind the driver to the consoles that are currently occupied by a +system driver. + +NOTE1: Binding and binding must be selected in Kconfig. It's under: + +Device Drivers -> Character devices -> Support for binding and unbinding +console drivers + +NOTE2: If any of the virtual consoles are in KD_GRAPHICS mode, then binding or +unbinding will not succeed. An example of an application that sets the console +to KD_GRAPHICS is X. + +How useful is this feature? This is very useful for console driver +developers. By unbinding the driver from the console layer, one can unload the +driver, make changes, recompile, reload and rebind the driver without any need +for rebooting the kernel. For regular users who may want to switch from +framebuffer console to VGA console and vice versa, this feature also makes +this possible. (NOTE NOTE NOTE: Please read fbcon.txt under Documentation/fb +for more details). + +Notes for developers: +===================== + +take_over_console() is now broken up into: + + register_con_driver() + bind_con_driver() - private function + +give_up_console() is a wrapper to unregister_con_driver(), and a driver must +be fully unbound for this call to succeed. con_is_bound() will check if the +driver is bound or not. + +Guidelines for console driver writers: +===================================== + +In order for binding to and unbinding from the console to properly work, +console drivers must follow these guidelines: + +1. All drivers, except system drivers, must call either register_con_driver() + or take_over_console(). register_con_driver() will just add the driver to + the console's internal list. It won't take over the + console. take_over_console(), as it name implies, will also take over (or + bind to) the console. + +2. All resources allocated during con->con_init() must be released in + con->con_deinit(). + +3. All resources allocated in con->con_startup() must be released when the + driver, which was previously bound, becomes unbound. The console layer + does not have a complementary call to con->con_startup() so it's up to the + driver to check when it's legal to release these resources. Calling + con_is_bound() in con->con_deinit() will help. If the call returned + false(), then it's safe to release the resources. This balance has to be + ensured because con->con_startup() can be called again when a request to + rebind the driver to the console arrives. + +4. Upon exit of the driver, ensure that the driver is totally unbound. If the + condition is satisfied, then the driver must call unregister_con_driver() + or give_up_console(). + +5. unregister_con_driver() can also be called on conditions which make it + impossible for the driver to service console requests. This can happen + with the framebuffer console that suddenly lost all of its drivers. + +The current crop of console drivers should still work correctly, but binding +and unbinding them may cause problems. With minimal fixes, these drivers can +be made to work correctly. + +========================== +Antonino Daplas + diff --git a/Documentation/devices.txt b/Documentation/devices.txt index b369a8c..4aaf68f 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -3,7 +3,7 @@ Maintained by Torben Mathiasen - Last revised: 25 January 2005 + Last revised: 15 May 2006 This list is the Linux Device List, the official registry of allocated device numbers and /dev directory nodes for the Linux operating @@ -94,7 +94,6 @@ Your cooperation is appreciated. 9 = /dev/urandom Faster, less secure random number gen. 10 = /dev/aio Asyncronous I/O notification interface 11 = /dev/kmsg Writes to this come out as printk's - 12 = /dev/oldmem Access to crash dump from kexec kernel 1 block RAM disk 0 = /dev/ram0 First RAM disk 1 = /dev/ram1 Second RAM disk @@ -262,13 +261,13 @@ Your cooperation is appreciated. NOTE: These devices permit both read and write access. 7 block Loopback devices - 0 = /dev/loop0 First loopback device - 1 = /dev/loop1 Second loopback device + 0 = /dev/loop0 First loop device + 1 = /dev/loop1 Second loop device ... - The loopback devices are used to mount filesystems not + The loop devices are used to mount filesystems not associated with block devices. The binding to the - loopback devices is handled by mount(8) or losetup(8). + loop devices is handled by mount(8) or losetup(8). 8 block SCSI disk devices (0-15) 0 = /dev/sda First SCSI disk whole disk @@ -943,7 +942,7 @@ Your cooperation is appreciated. 240 = /dev/ftlp FTL on 16th Memory Technology Device Partitions are handled in the same way as for IDE - disks (see major number 3) expect that the partition + disks (see major number 3) except that the partition limit is 15 rather than 63 per disk (same as SCSI.) 45 char isdn4linux ISDN BRI driver @@ -1168,7 +1167,7 @@ Your cooperation is appreciated. The filename of the encrypted container and the passwords are sent via ioctls (using the sdmount tool) to the master node which then activates them via one of the - /dev/scramdisk/x nodes for loopback mounting (all handled + /dev/scramdisk/x nodes for loop mounting (all handled through the sdmount tool). Requested by: andy@scramdisklinux.org @@ -2538,18 +2537,32 @@ Your cooperation is appreciated. 0 = /dev/usb/lp0 First USB printer ... 15 = /dev/usb/lp15 16th USB printer - 16 = /dev/usb/mouse0 First USB mouse - ... - 31 = /dev/usb/mouse15 16th USB mouse - 32 = /dev/usb/ez0 First USB firmware loader - ... - 47 = /dev/usb/ez15 16th USB firmware loader 48 = /dev/usb/scanner0 First USB scanner ... 63 = /dev/usb/scanner15 16th USB scanner 64 = /dev/usb/rio500 Diamond Rio 500 65 = /dev/usb/usblcd USBLCD Interface (info@usblcd.de) 66 = /dev/usb/cpad0 Synaptics cPad (mouse/LCD) + 96 = /dev/usb/hiddev0 1st USB HID device + ... + 111 = /dev/usb/hiddev15 16th USB HID device + 112 = /dev/usb/auer0 1st auerswald ISDN device + ... + 127 = /dev/usb/auer15 16th auerswald ISDN device + 128 = /dev/usb/brlvgr0 First Braille Voyager device + ... + 131 = /dev/usb/brlvgr3 Fourth Braille Voyager device + 132 = /dev/usb/idmouse ID Mouse (fingerprint scanner) device + 133 = /dev/usb/sisusbvga1 First SiSUSB VGA device + ... + 140 = /dev/usb/sisusbvga8 Eigth SISUSB VGA device + 144 = /dev/usb/lcd USB LCD device + 160 = /dev/usb/legousbtower0 1st USB Legotower device + ... + 175 = /dev/usb/legousbtower15 16th USB Legotower device + 240 = /dev/usb/dabusb0 First daubusb device + ... + 243 = /dev/usb/dabusb3 Fourth dabusb device 180 block USB block devices 0 = /dev/uba First USB block device @@ -2710,6 +2723,17 @@ Your cooperation is appreciated. 1 = /dev/cpu/1/msr MSRs on CPU 1 ... +202 block Xen Virtual Block Device + 0 = /dev/xvda First Xen VBD whole disk + 16 = /dev/xvdb Second Xen VBD whole disk + 32 = /dev/xvdc Third Xen VBD whole disk + ... + 240 = /dev/xvdp Sixteenth Xen VBD whole disk + + Partitions are handled in the same way as for IDE + disks (see major number 3) except that the limit on + partitions is 15. + 203 char CPU CPUID information 0 = /dev/cpu/0/cpuid CPUID on CPU 0 1 = /dev/cpu/1/cpuid CPUID on CPU 1 @@ -2747,11 +2771,27 @@ Your cooperation is appreciated. 46 = /dev/ttyCPM0 PPC CPM (SCC or SMC) - port 0 ... 47 = /dev/ttyCPM5 PPC CPM (SCC or SMC) - port 5 - 50 = /dev/ttyIOC40 Altix serial card + 50 = /dev/ttyIOC0 Altix serial card + ... + 81 = /dev/ttyIOC31 Altix serial card + 82 = /dev/ttyVR0 NEC VR4100 series SIU + 83 = /dev/ttyVR1 NEC VR4100 series DSIU + 84 = /dev/ttyIOC84 Altix ioc4 serial card + ... + 115 = /dev/ttyIOC115 Altix ioc4 serial card + 116 = /dev/ttySIOC0 Altix ioc3 serial card + ... + 147 = /dev/ttySIOC31 Altix ioc3 serial card + 148 = /dev/ttyPSC0 PPC PSC - port 0 + ... + 153 = /dev/ttyPSC5 PPC PSC - port 5 + 154 = /dev/ttyAT0 ATMEL serial port 0 + ... + 169 = /dev/ttyAT15 ATMEL serial port 15 + 170 = /dev/ttyNX0 Hilscher netX serial port 0 ... - 81 = /dev/ttyIOC431 Altix serial card - 82 = /dev/ttyVR0 NEC VR4100 series SIU - 83 = /dev/ttyVR1 NEC VR4100 series DSIU + 185 = /dev/ttyNX15 Hilscher netX serial port 15 + 186 = /dev/ttyJ0 JTAG1 DCC protocol based serial port emulation 205 char Low-density serial ports (alternate device) 0 = /dev/culu0 Callout device for ttyLU0 @@ -2786,8 +2826,8 @@ Your cooperation is appreciated. 50 = /dev/cuioc40 Callout device for ttyIOC40 ... 81 = /dev/cuioc431 Callout device for ttyIOC431 - 82 = /dev/cuvr0 Callout device for ttyVR0 - 83 = /dev/cuvr1 Callout device for ttyVR1 + 82 = /dev/cuvr0 Callout device for ttyVR0 + 83 = /dev/cuvr1 Callout device for ttyVR1 206 char OnStream SC-x0 tape devices @@ -2897,7 +2937,6 @@ Your cooperation is appreciated. ... 196 = /dev/dvb/adapter3/video0 first video decoder of fourth card - 216 char Bluetooth RFCOMM TTY devices 0 = /dev/rfcomm0 First Bluetooth RFCOMM TTY device 1 = /dev/rfcomm1 Second Bluetooth RFCOMM TTY device @@ -3002,12 +3041,43 @@ Your cooperation is appreciated. ioctl()'s can be used to rewind the tape regardless of the device used to access it. -231 char InfiniBand MAD +231 char InfiniBand 0 = /dev/infiniband/umad0 1 = /dev/infiniband/umad1 - ... + ... + 63 = /dev/infiniband/umad63 63rd InfiniBandMad device + 64 = /dev/infiniband/issm0 First InfiniBand IsSM device + 65 = /dev/infiniband/issm1 Second InfiniBand IsSM device + ... + 127 = /dev/infiniband/issm63 63rd InfiniBand IsSM device + 128 = /dev/infiniband/uverbs0 First InfiniBand verbs device + 129 = /dev/infiniband/uverbs1 Second InfiniBand verbs device + ... + 159 = /dev/infiniband/uverbs31 31st InfiniBand verbs device + +232 char Biometric Devices + 0 = /dev/biometric/sensor0/fingerprint first fingerprint sensor on first device + 1 = /dev/biometric/sensor0/iris first iris sensor on first device + 2 = /dev/biometric/sensor0/retina first retina sensor on first device + 3 = /dev/biometric/sensor0/voiceprint first voiceprint sensor on first device + 4 = /dev/biometric/sensor0/facial first facial sensor on first device + 5 = /dev/biometric/sensor0/hand first hand sensor on first device + ... + 10 = /dev/biometric/sensor1/fingerprint first fingerprint sensor on second device + ... + 20 = /dev/biometric/sensor2/fingerprint first fingerprint sensor on third device + ... + +233 char PathScale InfiniPath interconnect + 0 = /dev/ipath Primary device for programs (any unit) + 1 = /dev/ipath0 Access specifically to unit 0 + 2 = /dev/ipath1 Access specifically to unit 1 + ... + 4 = /dev/ipath3 Access specifically to unit 3 + 129 = /dev/ipath_sma Device used by Subnet Management Agent + 130 = /dev/ipath_diag Device used by diagnostics programs -232-239 UNASSIGNED +234-239 UNASSIGNED 240-254 char LOCAL/EXPERIMENTAL USE 240-254 block LOCAL/EXPERIMENTAL USE @@ -3021,6 +3091,28 @@ Your cooperation is appreciated. This major is reserved to assist the expansion to a larger number space. No device nodes with this major should ever be created on the filesystem. + (This is probaly not true anymore, but I'll leave it + for now /Torben) + +---LARGE MAJORS!!!!!--- + +256 char Equinox SST multi-port serial boards + 0 = /dev/ttyEQ0 First serial port on first Equinox SST board + 127 = /dev/ttyEQ127 Last serial port on first Equinox SST board + 128 = /dev/ttyEQ128 First serial port on second Equinox SST board + ... + 1027 = /dev/ttyEQ1027 Last serial port on eighth Equinox SST board + +256 block Resident Flash Disk Flash Translation Layer + 0 = /dev/rfda First RFD FTL layer + 16 = /dev/rfdb Second RFD FTL layer + ... + 240 = /dev/rfdp 16th RFD FTL layer + +257 char Phoenix Technologies Cryptographic Services Driver + 0 = /dev/ptlsec Crypto Services Driver + + **** ADDITIONAL /dev DIRECTORY ENTRIES diff --git a/Documentation/driver-model/overview.txt b/Documentation/driver-model/overview.txt index ac4a7a7..2050c9f 100644 --- a/Documentation/driver-model/overview.txt +++ b/Documentation/driver-model/overview.txt @@ -18,7 +18,7 @@ Traditional driver models implemented so (sometimes just a list) for the devices they control. There wasn't any uniformity across the different bus types. -The current driver model provides a comon, uniform data model for describing +The current driver model provides a common, uniform data model for describing a bus and the devices that can appear under the bus. The unified bus model includes a set of common attributes which all busses carry, and a set of common callbacks, such as device discovery during bus probing, bus diff --git a/Documentation/fb/fbcon.txt b/Documentation/fb/fbcon.txt index 08dce0f..f373df1 100644 --- a/Documentation/fb/fbcon.txt +++ b/Documentation/fb/fbcon.txt @@ -135,10 +135,10 @@ C. Boot options The angle can be changed anytime afterwards by 'echoing' the same numbers to any one of the 2 attributes found in - /sys/class/graphics/fb{x} + /sys/class/graphics/fbcon - con_rotate - rotate the display of the active console - con_rotate_all - rotate the display of all consoles + rotate - rotate the display of the active console + rotate_all - rotate the display of all consoles Console rotation will only become available if Console Rotation Support is compiled in your kernel. @@ -148,5 +148,177 @@ C. Boot options Actually, the underlying fb driver is totally ignorant of console rotation. ---- +C. Attaching, Detaching and Unloading + +Before going on on how to attach, detach and unload the framebuffer console, an +illustration of the dependencies may help. + +The console layer, as with most subsystems, needs a driver that interfaces with +the hardware. Thus, in a VGA console: + +console ---> VGA driver ---> hardware. + +Assuming the VGA driver can be unloaded, one must first unbind the VGA driver +from the console layer before unloading the driver. The VGA driver cannot be +unloaded if it is still bound to the console layer. (See +Documentation/console/console.txt for more information). + +This is more complicated in the case of the the framebuffer console (fbcon), +because fbcon is an intermediate layer between the console and the drivers: + +console ---> fbcon ---> fbdev drivers ---> hardware + +The fbdev drivers cannot be unloaded if it's bound to fbcon, and fbcon cannot +be unloaded if it's bound to the console layer. + +So to unload the fbdev drivers, one must first unbind fbcon from the console, +then unbind the fbdev drivers from fbcon. Fortunately, unbinding fbcon from +the console layer will automatically unbind framebuffer drivers from +fbcon. Thus, there is no need to explicitly unbind the fbdev drivers from +fbcon. + +So, how do we unbind fbcon from the console? Part of the answer is in +Documentation/console/console.txt. To summarize: + +Echo a value to the bind file that represents the framebuffer console +driver. So assuming vtcon1 represents fbcon, then: + +echo 1 > sys/class/vtconsole/vtcon1/bind - attach framebuffer console to + console layer +echo 0 > sys/class/vtconsole/vtcon1/bind - detach framebuffer console from + console layer + +If fbcon is detached from the console layer, your boot console driver (which is +usually VGA text mode) will take over. A few drivers (rivafb and i810fb) will +restore VGA text mode for you. With the rest, before detaching fbcon, you +must take a few additional steps to make sure that your VGA text mode is +restored properly. The following is one of the several methods that you can do: + +1. Download or install vbetool. This utility is included with most + distributions nowadays, and is usually part of the suspend/resume tool. + +2. In your kernel configuration, ensure that CONFIG_FRAMEBUFFER_CONSOLE is set + to 'y' or 'm'. Enable one or more of your favorite framebuffer drivers. + +3. Boot into text mode and as root run: + + vbetool vbestate save > + + The above command saves the register contents of your graphics + hardware to . You need to do this step only once as + the state file can be reused. + +4. If fbcon is compiled as a module, load fbcon by doing: + + modprobe fbcon + +5. Now to detach fbcon: + + vbetool vbestate restore < && \ + echo 0 > /sys/class/vtconsole/vtcon1/bind + +6. That's it, you're back to VGA mode. And if you compiled fbcon as a module, + you can unload it by 'rmmod fbcon' + +7. To reattach fbcon: + + echo 1 > /sys/class/vtconsole/vtcon1/bind + +8. Once fbcon is unbound, all drivers registered to the system will also +become unbound. This means that fbcon and individual framebuffer drivers +can be unloaded or reloaded at will. Reloading the drivers or fbcon will +automatically bind the console, fbcon and the drivers together. Unloading +all the drivers without unloading fbcon will make it impossible for the +console to bind fbcon. + +Notes for vesafb users: +======================= + +Unfortunately, if your bootline includes a vga=xxx parameter that sets the +hardware in graphics mode, such as when loading vesafb, vgacon will not load. +Instead, vgacon will replace the default boot console with dummycon, and you +won't get any display after detaching fbcon. Your machine is still alive, so +you can reattach vesafb. However, to reattach vesafb, you need to do one of +the following: + +Variation 1: + + a. Before detaching fbcon, do + + vbetool vbemode save > # do once for each vesafb mode, + # the file can be reused + + b. Detach fbcon as in step 5. + + c. Attach fbcon + + vbetool vbestate restore < && \ + echo 1 > /sys/class/vtconsole/vtcon1/bind + +Variation 2: + + a. Before detaching fbcon, do: + echo > /sys/class/tty/console/bind + + + vbetool vbemode get + + b. Take note of the mode number + + b. Detach fbcon as in step 5. + + c. Attach fbcon: + + vbetool vbemode set && \ + echo 1 > /sys/class/vtconsole/vtcon1/bind + +Samples: +======== + +Here are 2 sample bash scripts that you can use to bind or unbind the +framebuffer console driver if you are in an X86 box: + +--------------------------------------------------------------------------- +#!/bin/bash +# Unbind fbcon + +# Change this to where your actual vgastate file is located +# Or Use VGASTATE=$1 to indicate the state file at runtime +VGASTATE=/tmp/vgastate + +# path to vbetool +VBETOOL=/usr/local/bin + + +for (( i = 0; i < 16; i++)) +do + if test -x /sys/class/vtconsole/vtcon$i; then + if [ `cat /sys/class/vtconsole/vtcon$i/name | grep -c "frame buffer"` \ + = 1 ]; then + if test -x $VBETOOL/vbetool; then + echo Unbinding vtcon$i + $VBETOOL/vbetool vbestate restore < $VGASTATE + echo 0 > /sys/class/vtconsole/vtcon$i/bind + fi + fi + fi +done + +--------------------------------------------------------------------------- +#!/bin/bash +# Bind fbcon + +for (( i = 0; i < 16; i++)) +do + if test -x /sys/class/vtconsole/vtcon$i; then + if [ `cat /sys/class/vtconsole/vtcon$i/name | grep -c "frame buffer"` \ + = 1 ]; then + echo Unbinding vtcon$i + echo 1 > /sys/class/vtconsole/vtcon$i/bind + fi + fi +done +--------------------------------------------------------------------------- + +-- Antonino Daplas diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 43ab119..027285d 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -33,27 +33,12 @@ Who: Adrian Bunk --------------------------- -What: RCU API moves to EXPORT_SYMBOL_GPL -When: April 2006 -Files: include/linux/rcupdate.h, kernel/rcupdate.c -Why: Outside of Linux, the only implementations of anything even - vaguely resembling RCU that I am aware of are in DYNIX/ptx, - VM/XA, Tornado, and K42. I do not expect anyone to port binary - drivers or kernel modules from any of these, since the first two - are owned by IBM and the last two are open-source research OSes. - So these will move to GPL after a grace period to allow - people, who might be using implementations that I am not aware - of, to adjust to this upcoming change. -Who: Paul E. McKenney - ---------------------------- - What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN -When: November 2005 +When: November 2006 Why: Deprecated in favour of the new ioctl-based rawiso interface, which is more efficient. You should really be using libraw1394 for raw1394 access anyway. -Who: Jody McIntyre +Who: Jody McIntyre --------------------------- @@ -212,15 +197,6 @@ Who: Greg Kroah-Hartman --------------------------- -What: Support for NEC DDB5074 and DDB5476 evaluation boards. -When: June 2006 -Why: Board specific code doesn't build anymore since ~2.6.0 and no - users have complained indicating there is no more need for these - boards. This should really be considered a last call. -Who: Ralf Baechle - ---------------------------- - What: USB driver API moves to EXPORT_SYMBOL_GPL When: Febuary 2008 Files: include/linux/usb.h, drivers/usb/core/driver.c diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 1045da5..d31efbb 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -99,7 +99,7 @@ prototypes: int (*sync_fs)(struct super_block *sb, int wait); void (*write_super_lockfs) (struct super_block *); void (*unlockfs) (struct super_block *); - int (*statfs) (struct super_block *, struct kstatfs *); + int (*statfs) (struct dentry *, struct kstatfs *); int (*remount_fs) (struct super_block *, int *, char *); void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); @@ -142,15 +142,16 @@ see also dquot_operations section. --------------------------- file_system_type --------------------------- prototypes: - struct super_block *(*get_sb) (struct file_system_type *, int, - const char *, void *); + struct int (*get_sb) (struct file_system_type *, int, + const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); locking rules: may block BKL get_sb yes yes kill_sb yes yes -->get_sb() returns error or a locked superblock (exclusive on ->s_umount). +->get_sb() returns error or 0 with locked superblock attached to the vfsmount +(exclusive on ->s_umount). ->kill_sb() takes a write-locked superblock, does all shutdown work on it, unlocks and drops the reference. diff --git a/Documentation/filesystems/automount-support.txt b/Documentation/filesystems/automount-support.txt index 58c65a1..7cac200 100644 --- a/Documentation/filesystems/automount-support.txt +++ b/Documentation/filesystems/automount-support.txt @@ -19,7 +19,7 @@ following procedure: (2) Have the follow_link() op do the following steps: - (a) Call do_kern_mount() to call the appropriate filesystem to set up a + (a) Call vfs_kern_mount() to call the appropriate filesystem to set up a superblock and gain a vfsmount structure representing it. (b) Copy the nameidata provided as an argument and substitute the dentry diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt index afb1335..4aecc9b 100644 --- a/Documentation/filesystems/ext3.txt +++ b/Documentation/filesystems/ext3.txt @@ -113,6 +113,14 @@ noquota grpquota usrquota +bh (*) ext3 associates buffer heads to data pages to +nobh (a) cache disk block mapping information + (b) link pages into transaction to provide + ordering guarantees. + "bh" option forces use of buffer heads. + "nobh" option tries to avoid associating buffer + heads (supported only for "writeback" mode). + Specification ============= diff --git a/Documentation/filesystems/fuse.txt b/Documentation/filesystems/fuse.txt index 33f7431..a584f05 100644 --- a/Documentation/filesystems/fuse.txt +++ b/Documentation/filesystems/fuse.txt @@ -18,6 +18,14 @@ Non-privileged mount (or user mount): user. NOTE: this is not the same as mounts allowed with the "user" option in /etc/fstab, which is not discussed here. +Filesystem connection: + + A connection between the filesystem daemon and the kernel. The + connection exists until either the daemon dies, or the filesystem is + umounted. Note that detaching (or lazy umounting) the filesystem + does _not_ break the connection, in this case it will exist until + the last reference to the filesystem is released. + Mount owner: The user who does the mounting. @@ -86,16 +94,20 @@ Mount options The default is infinite. Note that the size of read requests is limited anyway to 32 pages (which is 128kbyte on i386). -Sysfs -~~~~~ +Control filesystem +~~~~~~~~~~~~~~~~~~ + +There's a control filesystem for FUSE, which can be mounted by: -FUSE sets up the following hierarchy in sysfs: + mount -t fusectl none /sys/fs/fuse/connections - /sys/fs/fuse/connections/N/ +Mounting it under the '/sys/fs/fuse/connections' directory makes it +backwards compatible with earlier versions. -where N is an increasing number allocated to each new connection. +Under the fuse control filesystem each connection has a directory +named by a unique number. -For each connection the following attributes are defined: +For each connection the following files exist within this directory: 'waiting' @@ -110,7 +122,47 @@ For each connection the following attrib connection. This means that all waiting requests will be aborted an error returned for all aborted and new requests. -Only a privileged user may read or write these attributes. +Only the owner of the mount may read or write these files. + +Interrupting filesystem operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If a process issuing a FUSE filesystem request is interrupted, the +following will happen: + + 1) If the request is not yet sent to userspace AND the signal is + fatal (SIGKILL or unhandled fatal signal), then the request is + dequeued and returns immediately. + + 2) If the request is not yet sent to userspace AND the signal is not + fatal, then an 'interrupted' flag is set for the request. When + the request has been successfully transfered to userspace and + this flag is set, an INTERRUPT request is queued. + + 3) If the request is already sent to userspace, then an INTERRUPT + request is queued. + +INTERRUPT requests take precedence over other requests, so the +userspace filesystem will receive queued INTERRUPTs before any others. + +The userspace filesystem may ignore the INTERRUPT requests entirely, +or may honor them by sending a reply to the _original_ request, with +the error set to EINTR. + +It is also possible that there's a race between processing the +original request and it's INTERRUPT request. There are two possibilities: + + 1) The INTERRUPT request is processed before the original request is + processed + + 2) The INTERRUPT request is processed after the original request has + been answered + +If the filesystem cannot find the original request, it should wait for +some timeout and/or a number of new requests to arrive, after which it +should reply to the INTERRUPT request with an EAGAIN error. In case +1) the INTERRUPT request will be requeued. In case 2) the INTERRUPT +reply will be ignored. Aborting a filesystem connection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -139,8 +191,8 @@ the filesystem. There are several ways - Use forced umount (umount -f). Works in all cases but only if filesystem is still attached (it hasn't been lazy unmounted) - - Abort filesystem through the sysfs interface. Most powerful - method, always works. + - Abort filesystem through the FUSE control filesystem. Most + powerful method, always works. How do non-privileged mounts work? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -304,25 +356,7 @@ Scenario 1 - Simple deadlock | | for "file"] | | *DEADLOCK* -The solution for this is to allow requests to be interrupted while -they are in userspace: - - | [interrupted by signal] | - | fuse_unlink() - | | [queue req on fc->pending] - | | [wake up fc->waitq] - | | [sleep on req->waitq] - -If the filesystem daemon was single threaded, this will stop here, -since there's no other thread to dequeue and execute the request. -In this case the solution is to kill the FUSE daemon as well. If -there are multiple serving threads, you just have to kill them as -long as any remain. - -Moral: a filesystem which deadlocks, can soon find itself dead. +The solution for this is to allow the filesystem to be aborted. Scenario 2 - Tricky deadlock ---------------------------- @@ -355,24 +389,14 @@ but is caused by a pagefault. | | [lock page] | | * DEADLOCK * -Solution is again to let the the request be interrupted (not -elaborated further). - -An additional problem is that while the write buffer is being -copied to the request, the request must not be interrupted. This -is because the destination address of the copy may not be valid -after the request is interrupted. - -This is solved with doing the copy atomically, and allowing -interruption while the page(s) belonging to the write buffer are -faulted with get_user_pages(). The 'req->locked' flag indicates -when the copy is taking place, and interruption is delayed until -this flag is unset. +Solution is basically the same as above. -Scenario 3 - Tricky deadlock with asynchronous read ---------------------------------------------------- +An additional problem is that while the write buffer is being copied +to the request, the request must not be interrupted/aborted. This is +because the destination address of the copy may not be valid after the +request has returned. -The same situation as above, except thread-1 will wait on page lock -and hence it will be uninterruptible as well. The solution is to -abort the connection with forced umount (if mount is attached) or -through the abort attribute in sysfs. +This is solved with doing the copy atomically, and allowing abort +while the page(s) belonging to the write buffer are faulted with +get_user_pages(). The 'req->locked' flag indicates when the copy is +taking place, and abort is delayed until this flag is unset. diff --git a/Documentation/filesystems/inotify.txt b/Documentation/filesystems/inotify.txt index 6d50190..59a919f 100644 --- a/Documentation/filesystems/inotify.txt +++ b/Documentation/filesystems/inotify.txt @@ -69,17 +69,135 @@ Prototypes: int inotify_rm_watch (int fd, __u32 mask); -(iii) Internal Kernel Implementation +(iii) Kernel Interface -Each inotify instance is associated with an inotify_device structure. +Inotify's kernel API consists a set of functions for managing watches and an +event callback. + +To use the kernel API, you must first initialize an inotify instance with a set +of inotify_operations. You are given an opaque inotify_handle, which you use +for any further calls to inotify. + + struct inotify_handle *ih = inotify_init(my_event_handler); + +You must provide a function for processing events and a function for destroying +the inotify watch. + + void handle_event(struct inotify_watch *watch, u32 wd, u32 mask, + u32 cookie, const char *name, struct inode *inode) + + watch - the pointer to the inotify_watch that triggered this call + wd - the watch descriptor + mask - describes the event that occurred + cookie - an identifier for synchronizing events + name - the dentry name for affected files in a directory-based event + inode - the affected inode in a directory-based event + + void destroy_watch(struct inotify_watch *watch) + +You may add watches by providing a pre-allocated and initialized inotify_watch +structure and specifying the inode to watch along with an inotify event mask. +You must pin the inode during the call. You will likely wish to embed the +inotify_watch structure in a structure of your own which contains other +information about the watch. Once you add an inotify watch, it is immediately +subject to removal depending on filesystem events. You must grab a reference if +you depend on the watch hanging around after the call. + + inotify_init_watch(&my_watch->iwatch); + inotify_get_watch(&my_watch->iwatch); // optional + s32 wd = inotify_add_watch(ih, &my_watch->iwatch, inode, mask); + inotify_put_watch(&my_watch->iwatch); // optional + +You may use the watch descriptor (wd) or the address of the inotify_watch for +other inotify operations. You must not directly read or manipulate data in the +inotify_watch. Additionally, you must not call inotify_add_watch() more than +once for a given inotify_watch structure, unless you have first called either +inotify_rm_watch() or inotify_rm_wd(). + +To determine if you have already registered a watch for a given inode, you may +call inotify_find_watch(), which gives you both the wd and the watch pointer for +the inotify_watch, or an error if the watch does not exist. + + wd = inotify_find_watch(ih, inode, &watchp); + +You may use container_of() on the watch pointer to access your own data +associated with a given watch. When an existing watch is found, +inotify_find_watch() bumps the refcount before releasing its locks. You must +put that reference with: + + put_inotify_watch(watchp); + +Call inotify_find_update_watch() to update the event mask for an existing watch. +inotify_find_update_watch() returns the wd of the updated watch, or an error if +the watch does not exist. + + wd = inotify_find_update_watch(ih, inode, mask); + +An existing watch may be removed by calling either inotify_rm_watch() or +inotify_rm_wd(). + + int ret = inotify_rm_watch(ih, &my_watch->iwatch); + int ret = inotify_rm_wd(ih, wd); + +A watch may be removed while executing your event handler with the following: + + inotify_remove_watch_locked(ih, iwatch); + +Call inotify_destroy() to remove all watches from your inotify instance and +release it. If there are no outstanding references, inotify_destroy() will call +your destroy_watch op for each watch. + + inotify_destroy(ih); + +When inotify removes a watch, it sends an IN_IGNORED event to your callback. +You may use this event as an indication to free the watch memory. Note that +inotify may remove a watch due to filesystem events, as well as by your request. +If you use IN_ONESHOT, inotify will remove the watch after the first event, at +which point you may call the final inotify_put_watch. + +(iv) Kernel Interface Prototypes + + struct inotify_handle *inotify_init(struct inotify_operations *ops); + + inotify_init_watch(struct inotify_watch *watch); + + s32 inotify_add_watch(struct inotify_handle *ih, + struct inotify_watch *watch, + struct inode *inode, u32 mask); + + s32 inotify_find_watch(struct inotify_handle *ih, struct inode *inode, + struct inotify_watch **watchp); + + s32 inotify_find_update_watch(struct inotify_handle *ih, + struct inode *inode, u32 mask); + + int inotify_rm_wd(struct inotify_handle *ih, u32 wd); + + int inotify_rm_watch(struct inotify_handle *ih, + struct inotify_watch *watch); + + void inotify_remove_watch_locked(struct inotify_handle *ih, + struct inotify_watch *watch); + + void inotify_destroy(struct inotify_handle *ih); + + void get_inotify_watch(struct inotify_watch *watch); + void put_inotify_watch(struct inotify_watch *watch); + + +(v) Internal Kernel Implementation + +Each inotify instance is represented by an inotify_handle structure. +Inotify's userspace consumers also have an inotify_device which is +associated with the inotify_handle, and on which events are queued. Each watch is associated with an inotify_watch structure. Watches are chained -off of each associated device and each associated inode. +off of each associated inotify_handle and each associated inode. -See fs/inotify.c for the locking and lifetime rules. +See fs/inotify.c and fs/inotify_user.c for the locking and lifetime rules. -(iv) Rationale +(vi) Rationale Q: What is the design decision behind not tying the watch to the open fd of the watched object? @@ -145,7 +263,7 @@ A: The poor user-space interface is the file descriptor-based one that allows basic file I/O and poll/select. Obtaining the fd and managing the watches could have been done either via a device file or a family of new system calls. We decided to implement a - family of system calls because that is the preffered approach for new kernel + family of system calls because that is the preferred approach for new kernel interfaces. The only real difference was whether we wanted to use open(2) and ioctl(2) or a couple of new system calls. System calls beat ioctls. diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 2f38846..5531694 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -50,10 +50,11 @@ Turn your foo_read_super() into a functi success and negative number in case of error (-EINVAL unless you have more informative error value to report). Call it foo_fill_super(). Now declare -struct super_block foo_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +int foo_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, foo_fill_super, + mnt); } (or similar with s/bdev/nodev/ or s/bdev/single/, depending on the kind of diff --git a/Documentation/filesystems/ramfs-rootfs-initramfs.txt b/Documentation/filesystems/ramfs-rootfs-initramfs.txt index 60ab61e..25981e2 100644 --- a/Documentation/filesystems/ramfs-rootfs-initramfs.txt +++ b/Documentation/filesystems/ramfs-rootfs-initramfs.txt @@ -70,11 +70,13 @@ tmpfs mounts. See Documentation/filesys What is rootfs? --------------- -Rootfs is a special instance of ramfs, which is always present in 2.6 systems. -(It's used internally as the starting and stopping point for searches of the -kernel's doubly-linked list of mount points.) +Rootfs is a special instance of ramfs (or tmpfs, if that's enabled), which is +always present in 2.6 systems. You can't unmount rootfs for approximately the +same reason you can't kill the init process; rather than having special code +to check for and handle an empty list, it's smaller and simpler for the kernel +to just make sure certain lists can't become empty. -Most systems just mount another filesystem over it and ignore it. The +Most systems just mount another filesystem over rootfs and ignore it. The amount of space an empty instance of ramfs takes up is tiny. What is initramfs? @@ -92,14 +94,16 @@ out of that. All this differs from the old initrd in several ways: - - The old initrd was a separate file, while the initramfs archive is linked - into the linux kernel image. (The directory linux-*/usr is devoted to - generating this archive during the build.) + - The old initrd was always a separate file, while the initramfs archive is + linked into the linux kernel image. (The directory linux-*/usr is devoted + to generating this archive during the build.) - The old initrd file was a gzipped filesystem image (in some file format, - such as ext2, that had to be built into the kernel), while the new + such as ext2, that needed a driver built into the kernel), while the new initramfs archive is a gzipped cpio archive (like tar only simpler, - see cpio(1) and Documentation/early-userspace/buffer-format.txt). + see cpio(1) and Documentation/early-userspace/buffer-format.txt). The + kernel's cpio extraction code is not only extremely small, it's also + __init data that can be discarded during the boot process. - The program run by the old initrd (which was called /initrd, not /init) did some setup and then returned to the kernel, while the init program from @@ -124,13 +128,14 @@ Populating initramfs: The 2.6 kernel build process always creates a gzipped cpio format initramfs archive and links it into the resulting kernel binary. By default, this -archive is empty (consuming 134 bytes on x86). The config option -CONFIG_INITRAMFS_SOURCE (for some reason buried under devices->block devices -in menuconfig, and living in usr/Kconfig) can be used to specify a source for -the initramfs archive, which will automatically be incorporated into the -resulting binary. This option can point to an existing gzipped cpio archive, a -directory containing files to be archived, or a text file specification such -as the following example: +archive is empty (consuming 134 bytes on x86). + +The config option CONFIG_INITRAMFS_SOURCE (for some reason buried under +devices->block devices in menuconfig, and living in usr/Kconfig) can be used +to specify a source for the initramfs archive, which will automatically be +incorporated into the resulting binary. This option can point to an existing +gzipped cpio archive, a directory containing files to be archived, or a text +file specification such as the following example: dir /dev 755 0 0 nod /dev/console 644 0 0 c 5 1 @@ -146,23 +151,84 @@ as the following example: Run "usr/gen_init_cpio" (after the kernel build) to get a usage message documenting the above file format. -One advantage of the text file is that root access is not required to +One advantage of the configuration file is that root access is not required to set permissions or create device nodes in the new archive. (Note that those two example "file" entries expect to find files named "init.sh" and "busybox" in a directory called "initramfs", under the linux-2.6.* directory. See Documentation/early-userspace/README for more details.) -The kernel does not depend on external cpio tools, gen_init_cpio is created -from usr/gen_init_cpio.c which is entirely self-contained, and the kernel's -boot-time extractor is also (obviously) self-contained. However, if you _do_ -happen to have cpio installed, the following command line can extract the -generated cpio image back into its component files: +The kernel does not depend on external cpio tools. If you specify a +directory instead of a configuration file, the kernel's build infrastructure +creates a configuration file from that directory (usr/Makefile calls +scripts/gen_initramfs_list.sh), and proceeds to package up that directory +using the config file (by feeding it to usr/gen_init_cpio, which is created +from usr/gen_init_cpio.c). The kernel's build-time cpio creation code is +entirely self-contained, and the kernel's boot-time extractor is also +(obviously) self-contained. + +The one thing you might need external cpio utilities installed for is creating +or extracting your own preprepared cpio files to feed to the kernel build +(instead of a config file or directory). + +The following command line can extract a cpio image (either by the above script +or by the kernel build) back into its component files: cpio -i -d -H newc -F initramfs_data.cpio --no-absolute-filenames +The following shell script can create a prebuilt cpio archive you can +use in place of the above config file: + + #!/bin/sh + + # Copyright 2006 Rob Landley and TimeSys Corporation. + # Licensed under GPL version 2 + + if [ $# -ne 2 ] + then + echo "usage: mkinitramfs directory imagename.cpio.gz" + exit 1 + fi + + if [ -d "$1" ] + then + echo "creating $2 from $1" + (cd "$1"; find . | cpio -o -H newc | gzip) > "$2" + else + echo "First argument must be a directory" + exit 1 + fi + +Note: The cpio man page contains some bad advice that will break your initramfs +archive if you follow it. It says "A typical way to generate the list +of filenames is with the find command; you should give find the -depth option +to minimize problems with permissions on directories that are unwritable or not +searchable." Don't do this when creating initramfs.cpio.gz images, it won't +work. The Linux kernel cpio extractor won't create files in a directory that +doesn't exist, so the directory entries must go before the files that go in +those directories. The above script gets them in the right order. + +External initramfs images: +-------------------------- + +If the kernel has initrd support enabled, an external cpio.gz archive can also +be passed into a 2.6 kernel in place of an initrd. In this case, the kernel +will autodetect the type (initramfs, not initrd) and extract the external cpio +archive into rootfs before trying to run /init. + +This has the memory efficiency advantages of initramfs (no ramdisk block +device) but the separate packaging of initrd (which is nice if you have +non-GPL code you'd like to run from initramfs, without conflating it with +the GPL licensed Linux kernel binary). + +It can also be used to supplement the kernel's built-in initamfs image. The +files in the external archive will overwrite any conflicting files in +the built-in initramfs archive. Some distributors also prefer to customize +a single kernel image with task-specific initramfs images, without recompiling. + Contents of initramfs: ---------------------- +An initramfs archive is a complete self-contained root filesystem for Linux. If you don't already understand what shared libraries, devices, and paths you need to get a minimal root filesystem up and running, here are some references: @@ -176,13 +242,36 @@ code against, along with some related ut I use uClibc (http://www.uclibc.org) and busybox (http://www.busybox.net) myself. These are LGPL and GPL, respectively. (A self-contained initramfs -package is planned for the busybox 1.2 release.) +package is planned for the busybox 1.3 release.) In theory you could use glibc, but that's not well suited for small embedded uses like this. (A "hello world" program statically linked against glibc is over 400k. With uClibc it's 7k. Also note that glibc dlopens libnss to do name lookups, even when otherwise statically linked.) +A good first step is to get initramfs to run a statically linked "hello world" +program as init, and test it under an emulator like qemu (www.qemu.org) or +User Mode Linux, like so: + + cat > hello.c << EOF + #include + #include + + int main(int argc, char *argv[]) + { + printf("Hello world!\n"); + sleep(999999999); + } + EOF + gcc -static hello2.c -o init + echo init | cpio -o -H newc | gzip > test.cpio.gz + # Testing external initramfs using the initrd loading mechanism. + qemu -kernel /boot/vmlinuz -initrd test.cpio.gz /dev/zero + +When debugging a normal root filesystem, it's nice to be able to boot with +"init=/bin/sh". The initramfs equivalent is "rdinit=/bin/sh", and it's +just as useful. + Why cpio rather than tar? ------------------------- @@ -241,7 +330,7 @@ the above threads) is: Future directions: ------------------ -Today (2.6.14), initramfs is always compiled in, but not always used. The +Today (2.6.16), initramfs is always compiled in, but not always used. The kernel falls back to legacy boot code that is reached only if initramfs does not contain an /init program. The fallback is legacy code, there to ensure a smooth transition and allowing early boot functionality to gradually move to @@ -258,8 +347,9 @@ and so on. This kind of complexity (which inevitably includes policy) is rightly handled in userspace. Both klibc and busybox/uClibc are working on simple initramfs -packages to drop into a kernel build, and when standard solutions are ready -and widely deployed, the kernel's legacy early boot code will become obsolete -and a candidate for the feature removal schedule. +packages to drop into a kernel build. -But that's a while off yet. +The klibc package has now been accepted into Andrew Morton's 2.6.17-mm tree. +The kernel's current early boot code (partition detection, etc) will probably +be migrated into a default initramfs, automatically created and used by the +kernel build. diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 3a2e552..9d3aed6 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -113,8 +113,8 @@ members are defined: struct file_system_type { const char *name; int fs_flags; - struct super_block *(*get_sb) (struct file_system_type *, int, - const char *, void *); + struct int (*get_sb) (struct file_system_type *, int, + const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; @@ -211,7 +211,7 @@ struct super_operations { int (*sync_fs)(struct super_block *sb, int wait); void (*write_super_lockfs) (struct super_block *); void (*unlockfs) (struct super_block *); - int (*statfs) (struct super_block *, struct kstatfs *); + int (*statfs) (struct dentry *, struct kstatfs *); int (*remount_fs) (struct super_block *, int *, char *); void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); diff --git a/Documentation/hwmon/abituguru b/Documentation/hwmon/abituguru new file mode 100644 index 0000000..69cdb52 --- /dev/null +++ b/Documentation/hwmon/abituguru @@ -0,0 +1,59 @@ +Kernel driver abituguru +======================= + +Supported chips: + * Abit uGuru (Hardware Monitor part only) + Prefix: 'abituguru' + Addresses scanned: ISA 0x0E0 + Datasheet: Not available, this driver is based on reverse engineering. + A "Datasheet" has been written based on the reverse engineering it + should be available in the same dir as this file under the name + abituguru-datasheet. + +Authors: + Hans de Goede , + (Initial reverse engineering done by Olle Sandberg + ) + + +Module Parameters +----------------- + +* force: bool Force detection. Note this parameter only causes the + detection to be skipped, if the uGuru can't be read + the module initialization (insmod) will still fail. +* fan_sensors: int Tell the driver how many fan speed sensors there are + on your motherboard. Default: 0 (autodetect). +* pwms: int Tell the driver how many fan speed controls (fan + pwms) your motherboard has. Default: 0 (autodetect). +* verbose: int How verbose should the driver be? (0-3): + 0 normal output + 1 + verbose error reporting + 2 + sensors type probing info\n" + 3 + retryable error reporting + Default: 2 (the driver is still in the testing phase) + +Notice if you need any of the first three options above please insmod the +driver with verbose set to 3 and mail me the output of: +dmesg | grep abituguru + + +Description +----------- + +This driver supports the hardware monitoring features of the Abit uGuru chip +found on Abit uGuru featuring motherboards (most modern Abit motherboards). + +The uGuru chip in reality is a Winbond W83L950D in disguise (despite Abit +claiming it is "a new microprocessor designed by the ABIT Engineers"). +Unfortunatly this doesn't help since the W83L950D is a generic +microcontroller with a custom Abit application running on it. + +Despite Abit not releasing any information regarding the uGuru, Olle +Sandberg has managed to reverse engineer the sensor part +of the uGuru. Without his work this driver would not have been possible. + +Known Issues +------------ + +The voltage and frequency control parts of the Abit uGuru are not supported. diff --git a/Documentation/hwmon/abituguru-datasheet b/Documentation/hwmon/abituguru-datasheet new file mode 100644 index 0000000..aef5a9b --- /dev/null +++ b/Documentation/hwmon/abituguru-datasheet @@ -0,0 +1,312 @@ +uGuru datasheet +=============== + +First of all, what I know about uGuru is no fact based on any help, hints or +datasheet from Abit. The data I have got on uGuru have I assembled through +my weak knowledge in "backwards engineering". +And just for the record, you may have noticed uGuru isn't a chip developed by +Abit, as they claim it to be. It's realy just an microprocessor (uC) created by +Winbond (W83L950D). And no, reading the manual for this specific uC or +mailing Windbond for help won't give any usefull data about uGuru, as it is +the program inside the uC that is responding to calls. + +Olle Sandberg , 2005-05-25 + + +Original version by Olle Sandberg who did the heavy lifting of the initial +reverse engineering. This version has been almost fully rewritten for clarity +and extended with write support and info on more databanks, the write support +is once again reverse engineered by Olle the additional databanks have been +reverse engineered by me. I would like to express my thanks to Olle, this +document and the Linux driver could not have been written without his efforts. + +Note: because of the lack of specs only the sensors part of the uGuru is +described here and not the CPU / RAM / etc voltage & frequency control. + +Hans de Goede , 28-01-2006 + + +Detection +========= + +As far as known the uGuru is always placed at and using the (ISA) I/O-ports +0xE0 and 0xE4, so we don't have to scan any port-range, just check what the two +ports are holding for detection. We will refer to 0xE0 as CMD (command-port) +and 0xE4 as DATA because Abit refers to them with these names. + +If DATA holds 0x00 or 0x08 and CMD holds 0x00 or 0xAC an uGuru could be +present. We have to check for two different values at data-port, because +after a reboot uGuru will hold 0x00 here, but if the driver is removed and +later on attached again data-port will hold 0x08, more about this later. + +After wider testing of the Linux kernel driver some variants of the uGuru have +turned up which will hold 0x00 instead of 0xAC at the CMD port, thus we also +have to test CMD for two different values. On these uGuru's DATA will initally +hold 0x09 and will only hold 0x08 after reading CMD first, so CMD must be read +first! + +To be really sure an uGuru is present a test read of one or more register +sets should be done. + + +Reading / Writing +================= + +Addressing +---------- + +The uGuru has a number of different addressing levels. The first addressing +level we will call banks. A bank holds data for one or more sensors. The data +in a bank for a sensor is one or more bytes large. + +The number of bytes is fixed for a given bank, you should always read or write +that many bytes, reading / writing more will fail, the results when writing +less then the number of bytes for a given bank are undetermined. + +See below for all known bank addresses, numbers of sensors in that bank, +number of bytes data per sensor and contents/meaning of those bytes. + +Although both this document and the kernel driver have kept the sensor +terminoligy for the addressing within a bank this is not 100% correct, in +bank 0x24 for example the addressing within the bank selects a PWM output not +a sensor. + +Notice that some banks have both a read and a write address this is how the +uGuru determines if a read from or a write to the bank is taking place, thus +when reading you should always use the read address and when writing the +write address. The write address is always one (1) more then the read address. + + +uGuru ready +----------- + +Before you can read from or write to the uGuru you must first put the uGuru +in "ready" mode. + +To put the uGuru in ready mode first write 0x00 to DATA and then wait for DATA +to hold 0x09, DATA should read 0x09 within 250 read cycles. + +Next CMD _must_ be read and should hold 0xAC, usually CMD will hold 0xAC the +first read but sometimes it takes a while before CMD holds 0xAC and thus it +has to be read a number of times (max 50). + +After reading CMD, DATA should hold 0x08 which means that the uGuru is ready +for input. As above DATA will usually hold 0x08 the first read but not always. +This step can be skipped, but it is undetermined what happens if the uGuru has +not yet reported 0x08 at DATA and you proceed with writing a bank address. + + +Sending bank and sensor addresses to the uGuru +---------------------------------------------- + +First the uGuru must be in "ready" mode as described above, DATA should hold +0x08 indicating that the uGuru wants input, in this case the bank address. + +Next write the bank address to DATA. After the bank address has been written +wait for to DATA to hold 0x08 again indicating that it wants / is ready for +more input (max 250 reads). + +Once DATA holds 0x08 again write the sensor address to CMD. + + +Reading +------- + +First send the bank and sensor addresses as described above. +Then for each byte of data you want to read wait for DATA to hold 0x01 +which indicates that the uGuru is ready to be read (max 250 reads) and once +DATA holds 0x01 read the byte from CMD. + +Once all bytes have been read data will hold 0x09, but there is no reason to +test for this. Notice that the number of bytes is bank address dependent see +above and below. + +After completing a successfull read it is advised to put the uGuru back in +ready mode, so that it is ready for the next read / write cycle. This way +if your program / driver is unloaded and later loaded again the detection +algorithm described above will still work. + + + +Writing +------- + +First send the bank and sensor addresses as described above. +Then for each byte of data you want to write wait for DATA to hold 0x00 +which indicates that the uGuru is ready to be written (max 250 reads) and +once DATA holds 0x00 write the byte to CMD. + +Once all bytes have been written wait for DATA to hold 0x01 (max 250 reads) +don't ask why this is the way it is. + +Once DATA holds 0x01 read CMD it should hold 0xAC now. + +After completing a successfull write it is advised to put the uGuru back in +ready mode, so that it is ready for the next read / write cycle. This way +if your program / driver is unloaded and later loaded again the detection +algorithm described above will still work. + + +Gotchas +------- + +After wider testing of the Linux kernel driver some variants of the uGuru have +turned up which do not hold 0x08 at DATA within 250 reads after writing the +bank address. With these versions this happens quite frequent, using larger +timeouts doesn't help, they just go offline for a second or 2, doing some +internal callibration or whatever. Your code should be prepared to handle +this and in case of no response in this specific case just goto sleep for a +while and then retry. + + +Address Map +=========== + +Bank 0x20 Alarms (R) +-------------------- +This bank contains 0 sensors, iow the sensor address is ignored (but must be +written) just use 0. Bank 0x20 contains 3 bytes: + +Byte 0: +This byte holds the alarm flags for sensor 0-7 of Sensor Bank1, with bit 0 +corresponding to sensor 0, 1 to 1, etc. + +Byte 1: +This byte holds the alarm flags for sensor 8-15 of Sensor Bank1, with bit 0 +corresponding to sensor 8, 1 to 9, etc. + +Byte 2: +This byte holds the alarm flags for sensor 0-5 of Sensor Bank2, with bit 0 +corresponding to sensor 0, 1 to 1, etc. + + +Bank 0x21 Sensor Bank1 Values / Readings (R) +-------------------------------------------- +This bank contains 16 sensors, for each sensor it contains 1 byte. +So far the following sensors are known to be available on all motherboards: +Sensor 0 CPU temp +Sensor 1 SYS temp +Sensor 3 CPU core volt +Sensor 4 DDR volt +Sensor 10 DDR Vtt volt +Sensor 15 PWM temp + +Byte 0: +This byte holds the reading from the sensor. Sensors in Bank1 can be both +volt and temp sensors, this is motherboard specific. The uGuru however does +seem to know (be programmed with) what kindoff sensor is attached see Sensor +Bank1 Settings description. + +Volt sensors use a linear scale, a reading 0 corresponds with 0 volt and a +reading of 255 with 3494 mV. The sensors for higher voltages however are +connected through a division circuit. The currently known division circuits +in use result in ranges of: 0-4361mV, 0-6248mV or 0-14510mV. 3.3 volt sources +use the 0-4361mV range, 5 volt the 0-6248mV and 12 volt the 0-14510mV . + +Temp sensors also use a linear scale, a reading of 0 corresponds with 0 degree +Celsius and a reading of 255 with a reading of 255 degrees Celsius. + + +Bank 0x22 Sensor Bank1 Settings (R) +Bank 0x23 Sensor Bank1 Settings (W) +----------------------------------- + +This bank contains 16 sensors, for each sensor it contains 3 bytes. Each +set of 3 bytes contains the settings for the sensor with the same sensor +address in Bank 0x21 . + +Byte 0: +Alarm behaviour for the selected sensor. A 1 enables the described behaviour. +Bit 0: Give an alarm if measured temp is over the warning threshold (RW) * +Bit 1: Give an alarm if measured volt is over the max threshold (RW) ** +Bit 2: Give an alarm if measured volt is under the min threshold (RW) ** +Bit 3: Beep if alarm (RW) +Bit 4: 1 if alarm cause measured temp is over the warning threshold (R) +Bit 5: 1 if alarm cause measured volt is over the max threshold (R) +Bit 6: 1 if alarm cause measured volt is under the min threshold (R) +Bit 7: Volt sensor: Shutdown if alarm persist for more then 4 seconds (RW) + Temp sensor: Shutdown if temp is over the shutdown threshold (RW) + +* This bit is only honored/used by the uGuru if a temp sensor is connected +** This bit is only honored/used by the uGuru if a volt sensor is connected +Note with some trickery this can be used to find out what kinda sensor is +detected see the Linux kernel driver for an example with many comments on +how todo this. + +Byte 1: +Temp sensor: warning threshold (scale as bank 0x21) +Volt sensor: min threshold (scale as bank 0x21) + +Byte 2: +Temp sensor: shutdown threshold (scale as bank 0x21) +Volt sensor: max threshold (scale as bank 0x21) + + +Bank 0x24 PWM outputs for FAN's (R) +Bank 0x25 PWM outputs for FAN's (W) +----------------------------------- + +This bank contains 3 "sensors", for each sensor it contains 5 bytes. +Sensor 0 usually controls the CPU fan +Sensor 1 usually controls the NB (or chipset for single chip) fan +Sensor 2 usually controls the System fan + +Byte 0: +Flag 0x80 to enable control, Fan runs at 100% when disabled. +low nibble (temp)sensor address at bank 0x21 used for control. + +Byte 1: +0-255 = 0-12v (linear), specify voltage at which fan will rotate when under +low threshold temp (specified in byte 3) + +Byte 2: +0-255 = 0-12v (linear), specify voltage at which fan will rotate when above +high threshold temp (specified in byte 4) + +Byte 3: +Low threshold temp (scale as bank 0x21) + +byte 4: +High threshold temp (scale as bank 0x21) + + +Bank 0x26 Sensors Bank2 Values / Readings (R) +--------------------------------------------- + +This bank contains 6 sensors (AFAIK), for each sensor it contains 1 byte. +So far the following sensors are known to be available on all motherboards: +Sensor 0: CPU fan speed +Sensor 1: NB (or chipset for single chip) fan speed +Sensor 2: SYS fan speed + +Byte 0: +This byte holds the reading from the sensor. 0-255 = 0-15300 (linear) + + +Bank 0x27 Sensors Bank2 Settings (R) +Bank 0x28 Sensors Bank2 Settings (W) +------------------------------------ + +This bank contains 6 sensors (AFAIK), for each sensor it contains 2 bytes. + +Byte 0: +Alarm behaviour for the selected sensor. A 1 enables the described behaviour. +Bit 0: Give an alarm if measured rpm is under the min threshold (RW) +Bit 3: Beep if alarm (RW) +Bit 7: Shutdown if alarm persist for more then 4 seconds (RW) + +Byte 1: +min threshold (scale as bank 0x26) + + +Warning for the adventerous +=========================== + +A word of caution to those who want to experiment and see if they can figure +the voltage / clock programming out, I tried reading and only reading banks +0-0x30 with the reading code used for the sensor banks (0x20-0x28) and this +resulted in a _permanent_ reprogramming of the voltages, luckily I had the +sensors part configured so that it would shutdown my system on any out of spec +voltages which proprably safed my computer (after a reboot I managed to +immediatly enter the bios and reload the defaults). This probably means that +the read/write cycle for the non sensor part is different from the sensor part. diff --git a/Documentation/hwmon/lm70 b/Documentation/hwmon/lm70 new file mode 100644 index 0000000..2bdd3fe --- /dev/null +++ b/Documentation/hwmon/lm70 @@ -0,0 +1,31 @@ +Kernel driver lm70 +================== + +Supported chip: + * National Semiconductor LM70 + Datasheet: http://www.national.com/pf/LM/LM70.html + +Author: + Kaiwan N Billimoria + +Description +----------- + +This driver implements support for the National Semiconductor LM70 +temperature sensor. + +The LM70 temperature sensor chip supports a single temperature sensor. +It communicates with a host processor (or microcontroller) via an +SPI/Microwire Bus interface. + +Communication with the LM70 is simple: when the temperature is to be sensed, +the driver accesses the LM70 using SPI communication: 16 SCLK cycles +comprise the MOSI/MISO loop. At the end of the transfer, the 11-bit 2's +complement digital temperature (sent via the SIO line), is available in the +driver for interpretation. This driver makes use of the kernel's in-core +SPI support. + +Thanks to +--------- +Jean Delvare for mentoring the hwmon-side driver +development. diff --git a/Documentation/hwmon/lm83 b/Documentation/hwmon/lm83 index 061d9ed..f7aad14 100644 --- a/Documentation/hwmon/lm83 +++ b/Documentation/hwmon/lm83 @@ -7,6 +7,10 @@ Supported chips: Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e Datasheet: Publicly available at the National Semiconductor website http://www.national.com/pf/LM/LM83.html + * National Semiconductor LM82 + Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e + Datasheet: Publicly available at the National Semiconductor website + http://www.national.com/pf/LM/LM82.html Author: Jean Delvare @@ -15,10 +19,11 @@ Description ----------- The LM83 is a digital temperature sensor. It senses its own temperature as -well as the temperature of up to three external diodes. It is compatible -with many other devices such as the LM84 and all other ADM1021 clones. -The main difference between the LM83 and the LM84 in that the later can -only sense the temperature of one external diode. +well as the temperature of up to three external diodes. The LM82 is +a stripped down version of the LM83 that only supports one external diode. +Both are compatible with many other devices such as the LM84 and all +other ADM1021 clones. The main difference between the LM83 and the LM84 +in that the later can only sense the temperature of one external diode. Using the adm1021 driver for a LM83 should work, but only two temperatures will be reported instead of four. @@ -30,12 +35,16 @@ contact us. Note that the LM90 can easil Confirmed motherboards: SBS P014 + SBS PSL09 Unconfirmed motherboards: Gigabyte GA-8IK1100 Iwill MPX2 Soltek SL-75DRV5 +The LM82 is confirmed to have been found on most AMD Geode reference +designs and test platforms. + The driver has been successfully tested by Magnus Forsström, who I'd like to thank here. More testers will be of course welcome. diff --git a/Documentation/hwmon/smsc47m192 b/Documentation/hwmon/smsc47m192 new file mode 100644 index 0000000..45d6453 --- /dev/null +++ b/Documentation/hwmon/smsc47m192 @@ -0,0 +1,102 @@ +Kernel driver smsc47m192 +======================== + +Supported chips: + * SMSC LPC47M192 and LPC47M997 + Prefix: 'smsc47m192' + Addresses scanned: I2C 0x2c - 0x2d + Datasheet: The datasheet for LPC47M192 is publicly available from + http://www.smsc.com/ + The LPC47M997 is compatible for hardware monitoring. + +Author: Hartmut Rick + Special thanks to Jean Delvare for careful checking + of the code and many helpful comments and suggestions. + + +Description +----------- + +This driver implements support for the hardware sensor capabilities +of the SMSC LPC47M192 and LPC47M997 Super-I/O chips. + +These chips support 3 temperature channels and 8 voltage inputs +as well as CPU voltage VID input. + +They do also have fan monitoring and control capabilities, but the +these features are accessed via ISA bus and are not supported by this +driver. Use the 'smsc47m1' driver for fan monitoring and control. + +Voltages and temperatures are measured by an 8-bit ADC, the resolution +of the temperatures is 1 bit per degree C. +Voltages are scaled such that the nominal voltage corresponds to +192 counts, i.e. 3/4 of the full range. Thus the available range for +each voltage channel is 0V ... 255/192*(nominal voltage), the resolution +is 1 bit per (nominal voltage)/192. +Both voltage and temperature values are scaled by 1000, the sys files +show voltages in mV and temperatures in units of 0.001 degC. + +The +12V analog voltage input channel (in4_input) is multiplexed with +bit 4 of the encoded CPU voltage. This means that you either get +a +12V voltage measurement or a 5 bit CPU VID, but not both. +The default setting is to use the pin as 12V input, and use only 4 bit VID. +This driver assumes that the information in the configuration register +is correct, i.e. that the BIOS has updated the configuration if +the motherboard has this input wired to VID4. + +The temperature and voltage readings are updated once every 1.5 seconds. +Reading them more often repeats the same values. + + +sysfs interface +--------------- + +in0_input - +2.5V voltage input +in1_input - CPU voltage input (nominal 2.25V) +in2_input - +3.3V voltage input +in3_input - +5V voltage input +in4_input - +12V voltage input (may be missing if used as VID4) +in5_input - Vcc voltage input (nominal 3.3V) + This is the supply voltage of the sensor chip itself. +in6_input - +1.5V voltage input +in7_input - +1.8V voltage input + +in[0-7]_min, +in[0-7]_max - lower and upper alarm thresholds for in[0-7]_input reading + + All voltages are read and written in mV. + +in[0-7]_alarm - alarm flags for voltage inputs + These files read '1' in case of alarm, '0' otherwise. + +temp1_input - chip temperature measured by on-chip diode +temp[2-3]_input - temperature measured by external diodes (one of these would + typically be wired to the diode inside the CPU) + +temp[1-3]_min, +temp[1-3]_max - lower and upper alarm thresholds for temperatures + +temp[1-3]_offset - temperature offset registers + The chip adds the offsets stored in these registers to + the corresponding temperature readings. + Note that temp1 and temp2 offsets share the same register, + they cannot both be different from zero at the same time. + Writing a non-zero number to one of them will reset the other + offset to zero. + + All temperatures and offsets are read and written in + units of 0.001 degC. + +temp[1-3]_alarm - alarm flags for temperature inputs, '1' in case of alarm, + '0' otherwise. +temp[2-3]_input_fault - diode fault flags for temperature inputs 2 and 3. + A fault is detected if the two pins for the corresponding + sensor are open or shorted, or any of the two is shorted + to ground or Vcc. '1' indicates a diode fault. + +cpu0_vid - CPU voltage as received from the CPU + +vrm - CPU VID standard used for decoding CPU voltage + + The *_min, *_max, *_offset and vrm files can be read and + written, all others are read-only. diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index a0d0ab2..d1d390a 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface @@ -3,15 +3,15 @@ Naming and data format standards for sys The libsensors library offers an interface to the raw sensors data through the sysfs interface. See libsensors documentation and source for -more further information. As of writing this document, libsensors -(from lm_sensors 2.8.3) is heavily chip-dependant. Adding or updating +further information. As of writing this document, libsensors +(from lm_sensors 2.8.3) is heavily chip-dependent. Adding or updating support for any given chip requires modifying the library's code. This is because libsensors was written for the procfs interface older kernel modules were using, which wasn't standardized enough. Recent versions of libsensors (from lm_sensors 2.8.2 and later) have support for the sysfs interface, though. -The new sysfs interface was designed to be as chip-independant as +The new sysfs interface was designed to be as chip-independent as possible. Note that motherboards vary widely in the connections to sensor chips. @@ -24,7 +24,7 @@ range using external resistors. Since th can change from motherboard to motherboard, the conversions cannot be hard coded into the driver and have to be done in user space. -For this reason, even if we aim at a chip-independant libsensors, it will +For this reason, even if we aim at a chip-independent libsensors, it will still require a configuration file (e.g. /etc/sensors.conf) for proper values conversion, labeling of inputs and hiding of unused inputs. @@ -39,15 +39,16 @@ If you are developing a userspace applic this standard. Note that this standard isn't completely established yet, so it is subject -to changes, even important ones. One more reason to use the library instead -of accessing sysfs files directly. +to changes. If you are writing a new hardware monitoring driver those +features can't seem to fit in this interface, please contact us with your +extension proposal. Keep in mind that backward compatibility must be +preserved. Each chip gets its own directory in the sysfs /sys/devices tree. To -find all sensor chips, it is easier to follow the symlinks from -/sys/i2c/devices/ +find all sensor chips, it is easier to follow the device symlinks from +/sys/class/hwmon/hwmon*. -All sysfs values are fixed point numbers. To get the true value of some -of the values, you should divide by the specified value. +All sysfs values are fixed point numbers. There is only one value per file, unlike the older /proc specification. The common scheme for files naming is: _. Usual @@ -69,28 +70,40 @@ to cause an alarm) is chip-dependent. ------------------------------------------------------------------------- +[0-*] denotes any positive number starting from 0 +[1-*] denotes any positive number starting from 1 +RO read only value +RW read/write value + +Read/write values may be read-only for some chips, depending on the +hardware implementation. + +All entries are optional, and should only be created in a given driver +if the chip has the feature. + ************ * Voltages * ************ -in[0-8]_min Voltage min value. +in[0-*]_min Voltage min value. Unit: millivolt - Read/Write + RW -in[0-8]_max Voltage max value. +in[0-*]_max Voltage max value. Unit: millivolt - Read/Write + RW -in[0-8]_input Voltage input value. +in[0-*]_input Voltage input value. Unit: millivolt - Read only + RO + Voltage measured on the chip pin. Actual voltage depends on the scaling resistors on the motherboard, as recommended in the chip datasheet. This varies by chip and by motherboard. Because of this variation, values are generally NOT scaled by the chip driver, and must be done by the application. However, some drivers (notably lm87 and via686a) - do scale, with various degrees of success. + do scale, because of internal resistors built into a chip. These drivers will output the actual voltage. Typical usage: @@ -104,58 +117,72 @@ in[0-8]_input Voltage input value. in7_* varies in8_* varies -cpu[0-1]_vid CPU core reference voltage. +cpu[0-*]_vid CPU core reference voltage. Unit: millivolt - Read only. + RO Not always correct. vrm Voltage Regulator Module version number. - Read only. - Two digit number, first is major version, second is - minor version. + RW (but changing it should no more be necessary) + Originally the VRM standard version multiplied by 10, but now + an arbitrary number, as not all standards have a version + number. Affects the way the driver calculates the CPU core reference voltage from the vid pins. +Also see the Alarms section for status flags associated with voltages. + ******** * Fans * ******** -fan[1-3]_min Fan minimum value +fan[1-*]_min Fan minimum value Unit: revolution/min (RPM) - Read/Write. + RW -fan[1-3]_input Fan input value. +fan[1-*]_input Fan input value. Unit: revolution/min (RPM) - Read only. + RO -fan[1-3]_div Fan divisor. +fan[1-*]_div Fan divisor. Integer value in powers of two (1, 2, 4, 8, 16, 32, 64, 128). + RW Some chips only support values 1, 2, 4 and 8. Note that this is actually an internal clock divisor, which affects the measurable speed range, not the read value. +Also see the Alarms section for status flags associated with fans. + + ******* * PWM * ******* -pwm[1-3] Pulse width modulation fan control. +pwm[1-*] Pulse width modulation fan control. Integer value in the range 0 to 255 - Read/Write + RW 255 is max or 100%. -pwm[1-3]_enable +pwm[1-*]_enable Switch PWM on and off. Not always present even if fan*_pwm is. - 0 to turn off - 1 to turn on in manual mode - 2 to turn on in automatic mode - Read/Write + 0: turn off + 1: turn on in manual mode + 2+: turn on in automatic mode + Check individual chip documentation files for automatic mode details. + RW + +pwm[1-*]_mode + 0: DC mode + 1: PWM mode + RW pwm[1-*]_auto_channels_temp Select which temperature channels affect this PWM output in auto mode. Bitfield, 1 is temp1, 2 is temp2, 4 is temp3 etc... Which values are possible depend on the chip used. + RW pwm[1-*]_auto_point[1-*]_pwm pwm[1-*]_auto_point[1-*]_temp @@ -163,6 +190,7 @@ pwm[1-*]_auto_point[1-*]_temp_hyst Define the PWM vs temperature curve. Number of trip points is chip-dependent. Use this for chips which associate trip points to PWM output channels. + RW OR @@ -172,50 +200,57 @@ temp[1-*]_auto_point[1-*]_temp_hyst Define the PWM vs temperature curve. Number of trip points is chip-dependent. Use this for chips which associate trip points to temperature channels. + RW **************** * Temperatures * **************** -temp[1-3]_type Sensor type selection. +temp[1-*]_type Sensor type selection. Integers 1 to 4 or thermistor Beta value (typically 3435) - Read/Write. + RW 1: PII/Celeron Diode 2: 3904 transistor 3: thermal diode 4: thermistor (default/unknown Beta) Not all types are supported by all chips -temp[1-4]_max Temperature max value. - Unit: millidegree Celcius - Read/Write value. +temp[1-*]_max Temperature max value. + Unit: millidegree Celsius (or millivolt, see below) + RW -temp[1-3]_min Temperature min value. - Unit: millidegree Celcius - Read/Write value. +temp[1-*]_min Temperature min value. + Unit: millidegree Celsius + RW -temp[1-3]_max_hyst +temp[1-*]_max_hyst Temperature hysteresis value for max limit. - Unit: millidegree Celcius + Unit: millidegree Celsius Must be reported as an absolute temperature, NOT a delta from the max value. - Read/Write value. + RW -temp[1-4]_input Temperature input value. - Unit: millidegree Celcius - Read only value. +temp[1-*]_input Temperature input value. + Unit: millidegree Celsius + RO -temp[1-4]_crit Temperature critical value, typically greater than +temp[1-*]_crit Temperature critical value, typically greater than corresponding temp_max values. - Unit: millidegree Celcius - Read/Write value. + Unit: millidegree Celsius + RW -temp[1-2]_crit_hyst +temp[1-*]_crit_hyst Temperature hysteresis value for critical limit. - Unit: millidegree Celcius + Unit: millidegree Celsius Must be reported as an absolute temperature, NOT a delta from the critical value. + RW + +temp[1-4]_offset + Temperature offset which is added to the temperature reading + by the chip. + Unit: millidegree Celsius Read/Write value. If there are multiple temperature sensors, temp1_* is @@ -225,6 +260,17 @@ temp[1-2]_crit_hyst itself, for example the thermal diode inside the CPU or a thermistor nearby. +Some chips measure temperature using external thermistors and an ADC, and +report the temperature measurement as a voltage. Converting this voltage +back to a temperature (or the other way around for limits) requires +mathematical functions not available in the kernel, so the conversion +must occur in user space. For these chips, all temp* files described +above should contain values expressed in millivolt instead of millidegree +Celsius. In other words, such temperature channels are handled as voltage +channels by the driver. + +Also see the Alarms section for status flags associated with temperatures. + ************ * Currents * @@ -233,25 +279,88 @@ temp[1-2]_crit_hyst Note that no known chip provides current measurements as of writing, so this part is theoretical, so to say. -curr[1-n]_max Current max value +curr[1-*]_max Current max value Unit: milliampere - Read/Write. + RW -curr[1-n]_min Current min value. +curr[1-*]_min Current min value. Unit: milliampere - Read/Write. + RW -curr[1-n]_input Current input value +curr[1-*]_input Current input value Unit: milliampere - Read only. + RO -********* -* Other * -********* +********** +* Alarms * +********** + +Each channel or limit may have an associated alarm file, containing a +boolean value. 1 means than an alarm condition exists, 0 means no alarm. + +Usually a given chip will either use channel-related alarms, or +limit-related alarms, not both. The driver should just reflect the hardware +implementation. + +in[0-*]_alarm +fan[1-*]_alarm +temp[1-*]_alarm + Channel alarm + 0: no alarm + 1: alarm + RO + +OR + +in[0-*]_min_alarm +in[0-*]_max_alarm +fan[1-*]_min_alarm +temp[1-*]_min_alarm +temp[1-*]_max_alarm +temp[1-*]_crit_alarm + Limit alarm + 0: no alarm + 1: alarm + RO + +Each input channel may have an associated fault file. This can be used +to notify open diodes, unconnected fans etc. where the hardware +supports it. When this boolean has value 1, the measurement for that +channel should not be trusted. + +in[0-*]_input_fault +fan[1-*]_input_fault +temp[1-*]_input_fault + Input fault condition + 0: no fault occured + 1: fault condition + RO + +Some chips also offer the possibility to get beeped when an alarm occurs: + +beep_enable Master beep enable + 0: no beeps + 1: beeps + RW + +in[0-*]_beep +fan[1-*]_beep +temp[1-*]_beep + Channel beep + 0: disable + 1: enable + RW + +In theory, a chip could provide per-limit beep masking, but no such chip +was seen so far. + +Old drivers provided a different, non-standard interface to alarms and +beeps. These interface files are deprecated, but will be kept around +for compatibility reasons: alarms Alarm bitmask. - Read only. + RO Integer representation of one to four bytes. A '1' bit means an alarm. Chips should be programmed for 'comparator' mode so that @@ -259,35 +368,26 @@ alarms Alarm bitmask. if it is still valid. Generally a direct representation of a chip's internal alarm registers; there is no standard for the position - of individual bits. + of individual bits. For this reason, the use of this + interface file for new drivers is discouraged. Use + individual *_alarm and *_fault files instead. Bits are defined in kernel/include/sensors.h. -alarms_in Alarm bitmask relative to in (voltage) channels - Read only - A '1' bit means an alarm, LSB corresponds to in0 and so on - Prefered to 'alarms' for newer chips - -alarms_fan Alarm bitmask relative to fan channels - Read only - A '1' bit means an alarm, LSB corresponds to fan1 and so on - Prefered to 'alarms' for newer chips - -alarms_temp Alarm bitmask relative to temp (temperature) channels - Read only - A '1' bit means an alarm, LSB corresponds to temp1 and so on - Prefered to 'alarms' for newer chips +beep_mask Bitmask for beep. + Same format as 'alarms' with the same bit locations, + use discouraged for the same reason. Use individual + *_beep files instead. + RW -beep_enable Beep/interrupt enable - 0 to disable. - 1 to enable. - Read/Write -beep_mask Bitmask for beep. - Same format as 'alarms' with the same bit locations. - Read/Write +********* +* Other * +********* eeprom Raw EEPROM data in binary form. - Read only. + RO pec Enable or disable PEC (SMBus only) - Read/Write + 0: disable + 1: enable + RW diff --git a/Documentation/hwmon/userspace-tools b/Documentation/hwmon/userspace-tools index 2622aac..19900a8 100644 --- a/Documentation/hwmon/userspace-tools +++ b/Documentation/hwmon/userspace-tools @@ -6,31 +6,32 @@ voltages, fans speed). They are often co are also connected directly through the ISA bus. The kernel drivers make the data from the sensor chips available in the /sys -virtual filesystem. Userspace tools are then used to display or set or the -data in a more friendly manner. +virtual filesystem. Userspace tools are then used to display the measured +values or configure the chips in a more friendly manner. Lm-sensors ---------- -Core set of utilites that will allow you to obtain health information, +Core set of utilities that will allow you to obtain health information, setup monitoring limits etc. You can get them on their homepage http://www.lm-sensors.nu/ or as a package from your Linux distribution. If from website: -Get lmsensors from project web site. Please note, you need only userspace -part, so compile with "make user_install" target. +Get lm-sensors from project web site. Please note, you need only userspace +part, so compile with "make user" and install with "make user_install". General hints to get things working: 0) get lm-sensors userspace utils -1) compile all drivers in I2C section as modules in your kernel +1) compile all drivers in I2C and Hardware Monitoring sections as modules + in your kernel 2) run sensors-detect script, it will tell you what modules you need to load. 3) load them and run "sensors" command, you should see some results. 4) fix sensors.conf, labels, limits, fan divisors 5) if any more problems consult FAQ, or documentation -Other utilites --------------- +Other utilities +--------------- If you want some graphical indicators of system health look for applications like: gkrellm, ksensors, xsensors, wmtemp, wmsensors, wmgtemp, ksysguardd, diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d new file mode 100644 index 0000000..83a3836 --- /dev/null +++ b/Documentation/hwmon/w83791d @@ -0,0 +1,113 @@ +Kernel driver w83791d +===================== + +Supported chips: + * Winbond W83791D + Prefix: 'w83791d' + Addresses scanned: I2C 0x2c - 0x2f + Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791Da.pdf + +Author: Charles Spirakis + +This driver was derived from the w83781d.c and w83792d.c source files. + +Credits: + w83781d.c: + Frodo Looijaard , + Philip Edelbrock , + and Mark Studebaker + w83792d.c: + Chunhao Huang , + Rudolf Marek + +Module Parameters +----------------- + +* init boolean + (default 0) + Use 'init=1' to have the driver do extra software initializations. + The default behavior is to do the minimum initialization possible + and depend on the BIOS to properly setup the chip. If you know you + have a w83791d and you're having problems, try init=1 before trying + reset=1. + +* reset boolean + (default 0) + Use 'reset=1' to reset the chip (via index 0x40, bit 7). The default + behavior is no chip reset to preserve BIOS settings. + +* force_subclients=bus,caddr,saddr,saddr + This is used to force the i2c addresses for subclients of + a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b' + to force the subclients of chip 0x2f on bus 0 to i2c addresses + 0x4a and 0x4b. + + +Description +----------- + +This driver implements support for the Winbond W83791D chip. + +Detection of the chip can sometimes be foiled because it can be in an +internal state that allows no clean access (Bank with ID register is not +currently selected). If you know the address of the chip, use a 'force' +parameter; this will put it into a more well-behaved state first. + +The driver implements three temperature sensors, five fan rotation speed +sensors, and ten voltage sensors. + +Temperatures are measured in degrees Celsius and measurement resolution is 1 +degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when +the temperature gets higher than the Overtemperature Shutdown value; it stays +on until the temperature falls below the Hysteresis value. + +Fan rotation speeds are reported in RPM (rotations per minute). An alarm is +triggered if the rotation speed has dropped below a programmable limit. Fan +readings can be divided by a programmable divider (1, 2, 4, 8 for fan 1/2/3 +and 1, 2, 4, 8, 16, 32, 64 or 128 for fan 4/5) to give the readings more +range or accuracy. + +Voltage sensors (also known as IN sensors) report their values in millivolts. +An alarm is triggered if the voltage has crossed a programmable minimum +or maximum limit. + +Alarms are provided as output from a "realtime status register". The +following bits are defined: + +bit - alarm on: +0 - Vcore +1 - VINR0 +2 - +3.3VIN +3 - 5VDD +4 - temp1 +5 - temp2 +6 - fan1 +7 - fan2 +8 - +12VIN +9 - -12VIN +10 - -5VIN +11 - fan3 +12 - chassis +13 - temp3 +14 - VINR1 +15 - reserved +16 - tart1 +17 - tart2 +18 - tart3 +19 - VSB +20 - VBAT +21 - fan4 +22 - fan5 +23 - reserved + +When an alarm goes off, you can be warned by a beeping signal through your +computer speaker. It is possible to enable all beeping globally, or only +the beeping for some alarms. + +The driver only reads the chip values each 3 seconds; reading them more +often will do no harm, but will return 'old' values. + +W83791D TODO: +--------------- +Provide a patch for per-file alarms as discussed on the mailing list +Provide a patch for smart-fan control (still need appropriate motherboard/fans) diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 index fd4b271..e46c234 100644 --- a/Documentation/i2c/busses/i2c-i801 +++ b/Documentation/i2c/busses/i2c-i801 @@ -21,8 +21,7 @@ Authors: Module Parameters ----------------- -* force_addr: int - Forcibly enable the ICH at the given address. EXTREMELY DANGEROUS! +None. Description diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2 index d751282..cd49c42 100644 --- a/Documentation/i2c/busses/i2c-nforce2 +++ b/Documentation/i2c/busses/i2c-nforce2 @@ -7,6 +7,8 @@ Supported adapters: * nForce3 250Gb MCP 10de:00E4 * nForce4 MCP 10de:0052 * nForce4 MCP-04 10de:0034 + * nForce4 MCP51 10de:0264 + * nForce4 MCP55 10de:0368 Datasheet: not publically available, but seems to be similar to the AMD-8111 SMBus 2.0 adapter. diff --git a/Documentation/i2c/busses/i2c-ocores b/Documentation/i2c/busses/i2c-ocores new file mode 100644 index 0000000..cfcebb1 --- /dev/null +++ b/Documentation/i2c/busses/i2c-ocores @@ -0,0 +1,51 @@ +Kernel driver i2c-ocores + +Supported adapters: + * OpenCores.org I2C controller by Richard Herveille (see datasheet link) + Datasheet: http://www.opencores.org/projects.cgi/web/i2c/overview + +Author: Peter Korsgaard + +Description +----------- + +i2c-ocores is an i2c bus driver for the OpenCores.org I2C controller +IP core by Richard Herveille. + +Usage +----- + +i2c-ocores uses the platform bus, so you need to provide a struct +platform_device with the base address and interrupt number. The +dev.platform_data of the device should also point to a struct +ocores_i2c_platform_data (see linux/i2c-ocores.h) describing the +distance between registers and the input clock speed. + +E.G. something like: + +static struct resource ocores_resources[] = { + [0] = { + .start = MYI2C_BASEADDR, + .end = MYI2C_BASEADDR + 8, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MYI2C_IRQ, + .end = MYI2C_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct ocores_i2c_platform_data myi2c_data = { + .regstep = 2, /* two bytes between registers */ + .clock_khz = 50000, /* input clock of 50MHz */ +}; + +static struct platform_device myi2c = { + .name = "ocores-i2c", + .dev = { + .platform_data = &myi2c_data, + }, + .num_resources = ARRAY_SIZE(ocores_resources), + .resource = ocores_resources, +}; diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4 index a1c8f58..9214763 100644 --- a/Documentation/i2c/busses/i2c-piix4 +++ b/Documentation/i2c/busses/i2c-piix4 @@ -6,6 +6,8 @@ Supported adapters: Datasheet: Publicly available at the Intel website * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges Datasheet: Only available via NDA from ServerWorks + * ATI IXP southbridges IXP200, IXP300, IXP400 + Datasheet: Not publicly available * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge Datasheet: Publicly available at the SMSC website http://www.smsc.com @@ -21,8 +23,6 @@ Module Parameters Forcibly enable the PIIX4. DANGEROUS! * force_addr: int Forcibly enable the PIIX4 at the given address. EXTREMELY DANGEROUS! -* fix_hstcfg: int - Fix config register. Needed on some boards (Force CPCI735). Description @@ -63,10 +63,36 @@ The PIIX4E is just an new version of the The PIIX/PIIX3 does not implement an SMBus or I2C bus, so you can't use this driver on those mainboards. -The ServerWorks Southbridges, the Intel 440MX, and the Victory766 are +The ServerWorks Southbridges, the Intel 440MX, and the Victory66 are identical to the PIIX4 in I2C/SMBus support. -A few OSB4 southbridges are known to be misconfigured by the BIOS. In this -case, you have you use the fix_hstcfg module parameter. Do not use it -unless you know you have to, because in some cases it also breaks -configuration on southbridges that don't need it. +If you own Force CPCI735 motherboard or other OSB4 based systems you may need +to change the SMBus Interrupt Select register so the SMBus controller uses +the SMI mode. + +1) Use lspci command and locate the PCI device with the SMBus controller: + 00:0f.0 ISA bridge: ServerWorks OSB4 South Bridge (rev 4f) + The line may vary for different chipsets. Please consult the driver source + for all possible PCI ids (and lspci -n to match them). Lets assume the + device is located at 00:0f.0. +2) Now you just need to change the value in 0xD2 register. Get it first with + command: lspci -xxx -s 00:0f.0 + If the value is 0x3 then you need to change it to 0x1 + setpci -s 00:0f.0 d2.b=1 + +Please note that you don't need to do that in all cases, just when the SMBus is +not working properly. + + +Hardware-specific issues +------------------------ + +This driver will refuse to load on IBM systems with an Intel PIIX4 SMBus. +Some of these machines have an RFID EEPROM (24RF08) connected to the SMBus, +which can easily get corrupted due to a state machine bug. These are mostly +Thinkpad laptops, but desktop systems may also be affected. We have no list +of all affected systems, so the only safe solution was to prevent access to +the SMBus on all IBM systems (detected using DMI data.) + +For additional information, read: +http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/README.thinkpad diff --git a/Documentation/i2c/busses/scx200_acb b/Documentation/i2c/busses/scx200_acb index f50e699..7c07883 100644 --- a/Documentation/i2c/busses/scx200_acb +++ b/Documentation/i2c/busses/scx200_acb @@ -2,14 +2,31 @@ Kernel driver scx200_acb Author: Christer Weinigel +The driver supersedes the older, never merged driver named i2c-nscacb. + Module Parameters ----------------- -* base: int +* base: up to 4 ints Base addresses for the ACCESS.bus controllers on SCx200 and SC1100 devices + By default the driver uses two base addresses 0x820 and 0x840. + If you want only one base address, specify the second as 0 so as to + override this default. + Description ----------- Enable the use of the ACCESS.bus controller on the Geode SCx200 and SC1100 processors and the CS5535 and CS5536 Geode companion devices. + +Device-specific notes +--------------------- + +The SC1100 WRAP boards are known to use base addresses 0x810 and 0x820. +If the scx200_acb driver is built into the kernel, add the following +parameter to your boot command line: + scx200_acb.base=0x810,0x820 +If the scx200_acb driver is built as a module, add the following line to +the file /etc/modprobe.conf instead: + options scx200_acb base=0x810,0x820 diff --git a/Documentation/ia64/aliasing.txt b/Documentation/ia64/aliasing.txt new file mode 100644 index 0000000..38f9a52 --- /dev/null +++ b/Documentation/ia64/aliasing.txt @@ -0,0 +1,208 @@ + MEMORY ATTRIBUTE ALIASING ON IA-64 + + Bjorn Helgaas + + May 4, 2006 + + +MEMORY ATTRIBUTES + + Itanium supports several attributes for virtual memory references. + The attribute is part of the virtual translation, i.e., it is + contained in the TLB entry. The ones of most interest to the Linux + kernel are: + + WB Write-back (cacheable) + UC Uncacheable + WC Write-coalescing + + System memory typically uses the WB attribute. The UC attribute is + used for memory-mapped I/O devices. The WC attribute is uncacheable + like UC is, but writes may be delayed and combined to increase + performance for things like frame buffers. + + The Itanium architecture requires that we avoid accessing the same + page with both a cacheable mapping and an uncacheable mapping[1]. + + The design of the chipset determines which attributes are supported + on which regions of the address space. For example, some chipsets + support either WB or UC access to main memory, while others support + only WB access. + +MEMORY MAP + + Platform firmware describes the physical memory map and the + supported attributes for each region. At boot-time, the kernel uses + the EFI GetMemoryMap() interface. ACPI can also describe memory + devices and the attributes they support, but Linux/ia64 currently + doesn't use this information. + + The kernel uses the efi_memmap table returned from GetMemoryMap() to + learn the attributes supported by each region of physical address + space. Unfortunately, this table does not completely describe the + address space because some machines omit some or all of the MMIO + regions from the map. + + The kernel maintains another table, kern_memmap, which describes the + memory Linux is actually using and the attribute for each region. + This contains only system memory; it does not contain MMIO space. + + The kern_memmap table typically contains only a subset of the system + memory described by the efi_memmap. Linux/ia64 can't use all memory + in the system because of constraints imposed by the identity mapping + scheme. + + The efi_memmap table is preserved unmodified because the original + boot-time information is required for kexec. + +KERNEL IDENTITY MAPPINGS + + Linux/ia64 identity mappings are done with large pages, currently + either 16MB or 64MB, referred to as "granules." Cacheable mappings + are speculative[2], so the processor can read any location in the + page at any time, independent of the programmer's intentions. This + means that to avoid attribute aliasing, Linux can create a cacheable + identity mapping only when the entire granule supports cacheable + access. + + Therefore, kern_memmap contains only full granule-sized regions that + can referenced safely by an identity mapping. + + Uncacheable mappings are not speculative, so the processor will + generate UC accesses only to locations explicitly referenced by + software. This allows UC identity mappings to cover granules that + are only partially populated, or populated with a combination of UC + and WB regions. + +USER MAPPINGS + + User mappings are typically done with 16K or 64K pages. The smaller + page size allows more flexibility because only 16K or 64K has to be + homogeneous with respect to memory attributes. + +POTENTIAL ATTRIBUTE ALIASING CASES + + There are several ways the kernel creates new mappings: + + mmap of /dev/mem + + This uses remap_pfn_range(), which creates user mappings. These + mappings may be either WB or UC. If the region being mapped + happens to be in kern_memmap, meaning that it may also be mapped + by a kernel identity mapping, the user mapping must use the same + attribute as the kernel mapping. + + If the region is not in kern_memmap, the user mapping should use + an attribute reported as being supported in the EFI memory map. + + Since the EFI memory map does not describe MMIO on some + machines, this should use an uncacheable mapping as a fallback. + + mmap of /sys/class/pci_bus/.../legacy_mem + + This is very similar to mmap of /dev/mem, except that legacy_mem + only allows mmap of the one megabyte "legacy MMIO" area for a + specific PCI bus. Typically this is the first megabyte of + physical address space, but it may be different on machines with + several VGA devices. + + "X" uses this to access VGA frame buffers. Using legacy_mem + rather than /dev/mem allows multiple instances of X to talk to + different VGA cards. + + The /dev/mem mmap constraints apply. + + However, since this is for mapping legacy MMIO space, WB access + does not make sense. This matters on machines without legacy + VGA support: these machines may have WB memory for the entire + first megabyte (or even the entire first granule). + + On these machines, we could mmap legacy_mem as WB, which would + be safe in terms of attribute aliasing, but X has no way of + knowing that it is accessing regular memory, not a frame buffer, + so the kernel should fail the mmap rather than doing it with WB. + + read/write of /dev/mem + + This uses copy_from_user(), which implicitly uses a kernel + identity mapping. This is obviously safe for things in + kern_memmap. + + There may be corner cases of things that are not in kern_memmap, + but could be accessed this way. For example, registers in MMIO + space are not in kern_memmap, but could be accessed with a UC + mapping. This would not cause attribute aliasing. But + registers typically can be accessed only with four-byte or + eight-byte accesses, and the copy_from_user() path doesn't allow + any control over the access size, so this would be dangerous. + + ioremap() + + This returns a kernel identity mapping for use inside the + kernel. + + If the region is in kern_memmap, we should use the attribute + specified there. Otherwise, if the EFI memory map reports that + the entire granule supports WB, we should use that (granules + that are partially reserved or occupied by firmware do not appear + in kern_memmap). Otherwise, we should use a UC mapping. + +PAST PROBLEM CASES + + mmap of various MMIO regions from /dev/mem by "X" on Intel platforms + + The EFI memory map may not report these MMIO regions. + + These must be allowed so that X will work. This means that + when the EFI memory map is incomplete, every /dev/mem mmap must + succeed. It may create either WB or UC user mappings, depending + on whether the region is in kern_memmap or the EFI memory map. + + mmap of 0x0-0xA0000 /dev/mem by "hwinfo" on HP sx1000 with VGA enabled + + See https://bugzilla.novell.com/show_bug.cgi?id=140858. + + The EFI memory map reports the following attributes: + 0x00000-0x9FFFF WB only + 0xA0000-0xBFFFF UC only (VGA frame buffer) + 0xC0000-0xFFFFF WB only + + This mmap is done with user pages, not kernel identity mappings, + so it is safe to use WB mappings. + + The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000, + which will use a granule-sized UC mapping covering 0-0xFFFFF. This + granule covers some WB-only memory, but since UC is non-speculative, + the processor will never generate an uncacheable reference to the + WB-only areas unless the driver explicitly touches them. + + mmap of 0x0-0xFFFFF legacy_mem by "X" + + If the EFI memory map reports this entire range as WB, there + is no VGA MMIO hole, and the mmap should fail or be done with + a WB mapping. + + There's no easy way for X to determine whether the 0xA0000-0xBFFFF + region is a frame buffer or just memory, so I think it's best to + just fail this mmap request rather than using a WB mapping. As + far as I know, there's no need to map legacy_mem with WB + mappings. + + Otherwise, a UC mapping of the entire region is probably safe. + The VGA hole means the region will not be in kern_memmap. The + HP sx1000 chipset doesn't support UC access to the memory surrounding + the VGA hole, but X doesn't need that area anyway and should not + reference it. + + mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled + + The EFI memory map reports the following attributes: + 0x00000-0xFFFFF WB only (no VGA MMIO hole) + + This is a special case of the previous case, and the mmap should + fail for the same reason as above. + +NOTES + + [1] SDM rev 2.2, vol 2, sec 4.4.1. + [2] SDM rev 2.2, vol 2, sec 4.4.6. diff --git a/Documentation/infiniband/ipoib.txt b/Documentation/infiniband/ipoib.txt index 5c5a4cc..1870355 100644 --- a/Documentation/infiniband/ipoib.txt +++ b/Documentation/infiniband/ipoib.txt @@ -1,10 +1,10 @@ IP OVER INFINIBAND The ib_ipoib driver is an implementation of the IP over InfiniBand - protocol as specified by the latest Internet-Drafts issued by the - IETF ipoib working group. It is a "native" implementation in the - sense of setting the interface type to ARPHRD_INFINIBAND and the - hardware address length to 20 (earlier proprietary implementations + protocol as specified by RFC 4391 and 4392, issued by the IETF ipoib + working group. It is a "native" implementation in the sense of + setting the interface type to ARPHRD_INFINIBAND and the hardware + address length to 20 (earlier proprietary implementations masqueraded to the kernel as ethernet interfaces). Partitions and P_Keys @@ -53,3 +53,7 @@ References IETF IP over InfiniBand (ipoib) Working Group http://ietf.org/html.charters/ipoib-charter.html + Transmission of IP over InfiniBand (IPoIB) (RFC 4391) + http://ietf.org/rfc/rfc4391.txt + IP over InfiniBand (IPoIB) Architecture (RFC 4392) + http://ietf.org/rfc/rfc4392.txt diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt index 171a44e..1543802 100644 --- a/Documentation/ioctl-number.txt +++ b/Documentation/ioctl-number.txt @@ -85,7 +85,9 @@ Code Seq# Include File Comments 'C' all linux/soundcard.h 'D' all asm-s390/dasd.h +'E' all linux/input.h 'F' all linux/fb.h +'H' all linux/hiddev.h 'I' all linux/isdn.h 'J' 00-1F drivers/scsi/gdth_ioctl.h 'K' all linux/kd.h diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/README.gigaset index 85a64de..fa0d4cc 100644 --- a/Documentation/isdn/README.gigaset +++ b/Documentation/isdn/README.gigaset @@ -124,7 +124,8 @@ GigaSet 307x Device Driver You can use some configuration tool of your distribution to configure this "modem" or configure pppd/wvdial manually. There are some example ppp - configuration files and chat scripts in the gigaset-VERSION/ppp directory. + configuration files and chat scripts in the gigaset-VERSION/ppp directory + in the driver packages from http://sourceforge.net/projects/gigaset307x/. Please note that the USB drivers are not able to change the state of the control lines (the M105 driver can be configured to use some undocumented control requests, if you really need the control lines, though). This means @@ -164,8 +165,8 @@ GigaSet 307x Device Driver If you want both of these at once, you are out of luck. - You can also use /sys/module//parameters/cidmode for changing - the CID mode setting ( is usb_gigaset or bas_gigaset). + You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode + setting (ttyGxy is ttyGU0 or ttyGB0). 3. Troubleshooting diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index a9c00fa..14ef386 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -1123,6 +1123,14 @@ The top Makefile exports the following v $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE). The user may override this value on the command line if desired. + INSTALL_MOD_STRIP + + If this variable is specified, will cause modules to be stripped + after they are installed. If INSTALL_MOD_STRIP is '1', then the + default option --strip-debug will be used. Otherwise, + INSTALL_MOD_STRIP will used as the option(s) to the strip command. + + === 8 Makefile language The kernel Makefiles are designed to run with GNU Make. The Makefiles diff --git a/Documentation/kdump/gdbmacros.txt b/Documentation/kdump/gdbmacros.txt index dcf5580..9b9b454 100644 --- a/Documentation/kdump/gdbmacros.txt +++ b/Documentation/kdump/gdbmacros.txt @@ -175,7 +175,7 @@ end document trapinfo Run info threads and lookup pid of thread #1 'trapinfo ' will tell you by which trap & possibly - addresthe kernel paniced. + address the kernel panicked. end diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt index 212cf3c..08bafa8 100644 --- a/Documentation/kdump/kdump.txt +++ b/Documentation/kdump/kdump.txt @@ -1,155 +1,325 @@ -Documentation for kdump - the kexec-based crash dumping solution +================================================================ +Documentation for Kdump - The kexec-based Crash Dumping Solution ================================================================ -DESIGN -====== +This document includes overview, setup and installation, and analysis +information. -Kdump uses kexec to reboot to a second kernel whenever a dump needs to be -taken. This second kernel is booted with very little memory. The first kernel -reserves the section of memory that the second kernel uses. This ensures that -on-going DMA from the first kernel does not corrupt the second kernel. +Overview +======== -All the necessary information about Core image is encoded in ELF format and -stored in reserved area of memory before crash. Physical address of start of -ELF header is passed to new kernel through command line parameter elfcorehdr=. +Kdump uses kexec to quickly boot to a dump-capture kernel whenever a +dump of the system kernel's memory needs to be taken (for example, when +the system panics). The system kernel's memory image is preserved across +the reboot and is accessible to the dump-capture kernel. -On i386, the first 640 KB of physical memory is needed to boot, irrespective -of where the kernel loads. Hence, this region is backed up by kexec just before -rebooting into the new kernel. +You can use common Linux commands, such as cp and scp, to copy the +memory image to a dump file on the local disk, or across the network to +a remote system. -In the second kernel, "old memory" can be accessed in two ways. +Kdump and kexec are currently supported on the x86, x86_64, and ppc64 +architectures. -- The first one is through a /dev/oldmem device interface. A capture utility - can read the device file and write out the memory in raw format. This is raw - dump of memory and analysis/capture tool should be intelligent enough to - determine where to look for the right information. ELF headers (elfcorehdr=) - can become handy here. +When the system kernel boots, it reserves a small section of memory for +the dump-capture kernel. This ensures that ongoing Direct Memory Access +(DMA) from the system kernel does not corrupt the dump-capture kernel. +The kexec -p command loads the dump-capture kernel into this reserved +memory. -- The second interface is through /proc/vmcore. This exports the dump as an ELF - format file which can be written out using any file copy command - (cp, scp, etc). Further, gdb can be used to perform limited debugging on - the dump file. This method ensures methods ensure that there is correct - ordering of the dump pages (corresponding to the first 640 KB that has been - relocated). +On x86 machines, the first 640 KB of physical memory is needed to boot, +regardless of where the kernel loads. Therefore, kexec backs up this +region just before rebooting into the dump-capture kernel. -SETUP -===== +All of the necessary information about the system kernel's core image is +encoded in the ELF format, and stored in a reserved area of memory +before a crash. The physical address of the start of the ELF header is +passed to the dump-capture kernel through the elfcorehdr= boot +parameter. + +With the dump-capture kernel, you can access the memory image, or "old +memory," in two ways: + +- Through a /dev/oldmem device interface. A capture utility can read the + device file and write out the memory in raw format. This is a raw dump + of memory. Analysis and capture tools must be intelligent enough to + determine where to look for the right information. + +- Through /proc/vmcore. This exports the dump as an ELF-format file that + you can write out using file copy commands such as cp or scp. Further, + you can use analysis tools such as the GNU Debugger (GDB) and the Crash + tool to debug the dump file. This method ensures that the dump pages are + correctly ordered. + + +Setup and Installation +====================== + +Install kexec-tools and the Kdump patch +--------------------------------------- + +1) Login as the root user. + +2) Download the kexec-tools user-space package from the following URL: + + http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz + +3) Unpack the tarball with the tar command, as follows: + + tar xvpzf kexec-tools-1.101.tar.gz + +4) Download the latest consolidated Kdump patch from the following URL: + + http://lse.sourceforge.net/kdump/ + + (This location is being used until all the user-space Kdump patches + are integrated with the kexec-tools package.) + +5) Change to the kexec-tools-1.101 directory, as follows: + + cd kexec-tools-1.101 + +6) Apply the consolidated patch to the kexec-tools-1.101 source tree + with the patch command, as follows. (Modify the path to the downloaded + patch as necessary.) + + patch -p1 < /path-to-kdump-patch/kexec-tools-1.101-kdump.patch + +7) Configure the package, as follows: + + ./configure + +8) Compile the package, as follows: + + make + +9) Install the package, as follows: + + make install + + +Download and build the system and dump-capture kernels +------------------------------------------------------ + +Download the mainline (vanilla) kernel source code (2.6.13-rc1 or newer) +from http://www.kernel.org. Two kernels must be built: a system kernel +and a dump-capture kernel. Use the following steps to configure these +kernels with the necessary kexec and Kdump features: + +System kernel +------------- + +1) Enable "kexec system call" in "Processor type and features." + + CONFIG_KEXEC=y + +2) Enable "sysfs file system support" in "Filesystem" -> "Pseudo + filesystems." This is usually enabled by default. + + CONFIG_SYSFS=y + + Note that "sysfs file system support" might not appear in the "Pseudo + filesystems" menu if "Configure standard kernel features (for small + systems)" is not enabled in "General Setup." In this case, check the + .config file itself to ensure that sysfs is turned on, as follows: + + grep 'CONFIG_SYSFS' .config + +3) Enable "Compile the kernel with debug info" in "Kernel hacking." + + CONFIG_DEBUG_INFO=Y + + This causes the kernel to be built with debug symbols. The dump + analysis tools require a vmlinux with debug symbols in order to read + and analyze a dump file. + +4) Make and install the kernel and its modules. Update the boot loader + (such as grub, yaboot, or lilo) configuration files as necessary. + +5) Boot the system kernel with the boot parameter "crashkernel=Y@X", + where Y specifies how much memory to reserve for the dump-capture kernel + and X specifies the beginning of this reserved memory. For example, + "crashkernel=64M@16M" tells the system kernel to reserve 64 MB of memory + starting at physical address 0x01000000 for the dump-capture kernel. + + On x86 and x86_64, use "crashkernel=64M@16M". + + On ppc64, use "crashkernel=128M@32M". + + +The dump-capture kernel +----------------------- -1) Download the upstream kexec-tools userspace package from - http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz. - - Apply the latest consolidated kdump patch on top of kexec-tools-1.101 - from http://lse.sourceforge.net/kdump/. This arrangment has been made - till all the userspace patches supporting kdump are integrated with - upstream kexec-tools userspace. - -2) Download and build the appropriate (2.6.13-rc1 onwards) vanilla kernels. - Two kernels need to be built in order to get this feature working. - Following are the steps to properly configure the two kernels specific - to kexec and kdump features: - - A) First kernel or regular kernel: - ---------------------------------- - a) Enable "kexec system call" feature (in Processor type and features). - CONFIG_KEXEC=y - b) Enable "sysfs file system support" (in Pseudo filesystems). - CONFIG_SYSFS=y - c) make - d) Boot into first kernel with the command line parameter "crashkernel=Y@X". - Use appropriate values for X and Y. Y denotes how much memory to reserve - for the second kernel, and X denotes at what physical address the - reserved memory section starts. For example: "crashkernel=64M@16M". - - - B) Second kernel or dump capture kernel: - --------------------------------------- - a) For i386 architecture enable Highmem support - CONFIG_HIGHMEM=y - b) Enable "kernel crash dumps" feature (under "Processor type and features") - CONFIG_CRASH_DUMP=y - c) Make sure a suitable value for "Physical address where the kernel is - loaded" (under "Processor type and features"). By default this value - is 0x1000000 (16MB) and it should be same as X (See option d above), - e.g., 16 MB or 0x1000000. - CONFIG_PHYSICAL_START=0x1000000 - d) Enable "/proc/vmcore support" (Optional, under "Pseudo filesystems"). - CONFIG_PROC_VMCORE=y - -3) After booting to regular kernel or first kernel, load the second kernel - using the following command: - - kexec -p --args-linux --elf32-core-headers - --append="root= init 1 irqpoll maxcpus=1" - - Notes: - ====== - i) has to be a vmlinux image ie uncompressed elf image. - bzImage will not work, as of now. - ii) --args-linux has to be speicfied as if kexec it loading an elf image, - it needs to know that the arguments supplied are of linux type. - iii) By default ELF headers are stored in ELF64 format to support systems - with more than 4GB memory. Option --elf32-core-headers forces generation - of ELF32 headers. The reason for this option being, as of now gdb can - not open vmcore file with ELF64 headers on a 32 bit systems. So ELF32 - headers can be used if one has non-PAE systems and hence memory less - than 4GB. - iv) Specify "irqpoll" as command line parameter. This reduces driver - initialization failures in second kernel due to shared interrupts. - v) needs to be specified in a format corresponding to the root - device name in the output of mount command. - vi) If you have built the drivers required to mount root file system as - modules in , then, specify - --initrd=. - vii) Specify maxcpus=1 as, if during first kernel run, if panic happens on - non-boot cpus, second kernel doesn't seem to be boot up all the cpus. - The other option is to always built the second kernel without SMP - support ie CONFIG_SMP=n - -4) After successfully loading the second kernel as above, if a panic occurs - system reboots into the second kernel. A module can be written to force - the panic or "ALT-SysRq-c" can be used initiate a crash dump for testing - purposes. - -5) Once the second kernel has booted, write out the dump file using +1) Under "General setup," append "-kdump" to the current string in + "Local version." + +2) On x86, enable high memory support under "Processor type and + features": + + CONFIG_HIGHMEM64G=y + or + CONFIG_HIGHMEM4G + +3) On x86 and x86_64, disable symmetric multi-processing support + under "Processor type and features": + + CONFIG_SMP=n + (If CONFIG_SMP=y, then specify maxcpus=1 on the kernel command line + when loading the dump-capture kernel, see section "Load the Dump-capture + Kernel".) + +4) On ppc64, disable NUMA support and enable EMBEDDED support: + + CONFIG_NUMA=n + CONFIG_EMBEDDED=y + CONFIG_EEH=N for the dump-capture kernel + +5) Enable "kernel crash dumps" support under "Processor type and + features": + + CONFIG_CRASH_DUMP=y + +6) Use a suitable value for "Physical address where the kernel is + loaded" (under "Processor type and features"). This only appears when + "kernel crash dumps" is enabled. By default this value is 0x1000000 + (16MB). It should be the same as X in the "crashkernel=Y@X" boot + parameter discussed above. + + On x86 and x86_64, use "CONFIG_PHYSICAL_START=0x1000000". + + On ppc64 the value is automatically set at 32MB when + CONFIG_CRASH_DUMP is set. + +6) Optionally enable "/proc/vmcore support" under "Filesystems" -> + "Pseudo filesystems". + + CONFIG_PROC_VMCORE=y + (CONFIG_PROC_VMCORE is set by default when CONFIG_CRASH_DUMP is selected.) + +7) Make and install the kernel and its modules. DO NOT add this kernel + to the boot loader configuration files. + + +Load the Dump-capture Kernel +============================ + +After booting to the system kernel, load the dump-capture kernel using +the following command: + + kexec -p \ + --initrd= --args-linux \ + --append="root= init 1 irqpoll" + + +Notes on loading the dump-capture kernel: + +* must be a vmlinux image (that is, an + uncompressed ELF image). bzImage does not work at this time. + +* By default, the ELF headers are stored in ELF64 format to support + systems with more than 4GB memory. The --elf32-core-headers option can + be used to force the generation of ELF32 headers. This is necessary + because GDB currently cannot open vmcore files with ELF64 headers on + 32-bit systems. ELF32 headers can be used on non-PAE systems (that is, + less than 4GB of memory). + +* The "irqpoll" boot parameter reduces driver initialization failures + due to shared interrupts in the dump-capture kernel. + +* You must specify in the format corresponding to the root + device name in the output of mount command. + +* "init 1" boots the dump-capture kernel into single-user mode without + networking. If you want networking, use "init 3." + + +Kernel Panic +============ + +After successfully loading the dump-capture kernel as previously +described, the system will reboot into the dump-capture kernel if a +system crash is triggered. Trigger points are located in panic(), +die(), die_nmi() and in the sysrq handler (ALT-SysRq-c). + +The following conditions will execute a crash trigger point: + +If a hard lockup is detected and "NMI watchdog" is configured, the system +will boot into the dump-capture kernel ( die_nmi() ). + +If die() is called, and it happens to be a thread with pid 0 or 1, or die() +is called inside interrupt context or die() is called and panic_on_oops is set, +the system will boot into the dump-capture kernel. + +On powererpc systems when a soft-reset is generated, die() is called by all cpus and the system system will boot into the dump-capture kernel. + +For testing purposes, you can trigger a crash by using "ALT-SysRq-c", +"echo c > /proc/sysrq-trigger or write a module to force the panic. + +Write Out the Dump File +======================= + +After the dump-capture kernel is booted, write out the dump file with +the following command: cp /proc/vmcore - Dump memory can also be accessed as a /dev/oldmem device for a linear/raw - view. To create the device, type: +You can also access dumped memory as a /dev/oldmem device for a linear +and raw view. To create the device, use the following command: - mknod /dev/oldmem c 1 12 + mknod /dev/oldmem c 1 12 - Use "dd" with suitable options for count, bs and skip to access specific - portions of the dump. +Use the dd command with suitable options for count, bs, and skip to +access specific portions of the dump. - Entire memory: dd if=/dev/oldmem of=oldmem.001 +To see the entire memory, use the following command: + dd if=/dev/oldmem of=oldmem.001 -ANALYSIS + +Analysis ======== -Limited analysis can be done using gdb on the dump file copied out of -/proc/vmcore. Use vmlinux built with -g and run - gdb vmlinux +Before analyzing the dump image, you should reboot into a stable kernel. + +You can do limited analysis using GDB on the dump file copied out of +/proc/vmcore. Use the debug vmlinux built with -g and run the following +command: + + gdb vmlinux -Stack trace for the task on processor 0, register display, memory display -work fine. +Stack trace for the task on processor 0, register display, and memory +display work fine. -Note: gdb cannot analyse core files generated in ELF64 format for i386. +Note: GDB cannot analyze core files generated in ELF64 format for x86. +On systems with a maximum of 4GB of memory, you can generate +ELF32-format headers using the --elf32-core-headers kernel option on the +dump kernel. -Latest "crash" (crash-4.0-2.18) as available on Dave Anderson's site -http://people.redhat.com/~anderson/ works well with kdump format. +You can also use the Crash utility to analyze dump files in Kdump +format. Crash is available on Dave Anderson's site at the following URL: + http://people.redhat.com/~anderson/ + + +To Do +===== -TODO -==== -1) Provide a kernel pages filtering mechanism so that core file size is not - insane on systems having huge memory banks. -2) Relocatable kernel can help in maintaining multiple kernels for crashdump - and same kernel as the first kernel can be used to capture the dump. +1) Provide a kernel pages filtering mechanism, so core file size is not + extreme on systems with huge memory banks. +2) Relocatable kernel can help in maintaining multiple kernels for + crash_dump, and the same kernel as the system kernel can be used to + capture the dump. -CONTACT + +Contact ======= + Vivek Goyal (vgoyal@in.ibm.com) Maneesh Soni (maneesh@in.ibm.com) + + +Trademark +========= + +Linux is a trademark of Linus Torvalds in the United States, other +countries, or both. diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index b3a6187..2e352a6 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -61,6 +61,7 @@ parameter is applicable: MTD MTD support is enabled. NET Appropriate network support is enabled. NUMA NUMA support is enabled. + GENERIC_TIME The generic timeofday code is enabled. NFS Appropriate NFS support is enabled. OSS OSS sound support is enabled. PARIDE The ParIDE subsystem is enabled. @@ -147,6 +148,9 @@ running once the system is up. acpi_irq_isa= [HW,ACPI] If irq_balance, mark listed IRQs used by ISA Format: ,... + acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS + Format: To spoof as Windows 98: ="Microsoft Windows" + acpi_osi= [HW,ACPI] empty param disables _OSI acpi_serialize [HW,ACPI] force serialization of AML methods @@ -176,6 +180,11 @@ running once the system is up. override platform specific driver. See also Documentation/acpi-hotkey.txt. + acpi_pm_good [IA-32,X86-64] + Override the pmtimer bug detection: force the kernel + to assume that this machine's pmtimer latches its value + and always returns good values. + enable_timer_pin_1 [i386,x86-64] Enable PIN 1 of APIC timer Can be useful to work around chipset bugs @@ -338,10 +347,11 @@ running once the system is up. Value can be changed at runtime via /selinux/checkreqprot. - clock= [BUGS=IA-32,HW] gettimeofday timesource override. - Forces specified timesource (if avaliable) to be used - when calculating gettimeofday(). If specicified - timesource is not avalible, it defaults to PIT. + clock= [BUGS=IA-32, HW] gettimeofday clocksource override. + [Deprecated] + Forces specified clocksource (if avaliable) to be used + when calculating gettimeofday(). If specified + clocksource is not avalible, it defaults to PIT. Format: { pit | tsc | cyclone | pmtmr } disable_8254_timer @@ -1402,6 +1412,15 @@ running once the system is up. If enabled at boot time, /selinux/disable can be used later to disable prior to initial policy load. + selinux_compat_net = + [SELINUX] Set initial selinux_compat_net flag value. + Format: { "0" | "1" } + 0 -- use new secmark-based packet controls + 1 -- use legacy packet controls + Default value is 0 (preferred). + Value can be changed at runtime via + /selinux/compat_net. + serialnumber [BUGS=IA-32] sg_def_reserved_size= [SCSI] @@ -1605,6 +1624,10 @@ running once the system is up. time Show timing data prefixed to each printk message line + clocksource= [GENERIC_TIME] Override the default clocksource + Override the default clocksource and use the clocksource + with the name specified. + tipar.timeout= [HW,PPT] Set communications timeout in tenths of a second (default 15). diff --git a/Documentation/keys.txt b/Documentation/keys.txt index aaa01b0..61c0fad 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt @@ -19,6 +19,7 @@ This document has the following sections - Key overview - Key service overview - Key access permissions + - SELinux support - New procfs files - Userspace system call interface - Kernel services @@ -232,6 +233,39 @@ For changing the ownership, group ID or the key or having the sysadmin capability is sufficient. +=============== +SELINUX SUPPORT +=============== + +The security class "key" has been added to SELinux so that mandatory access +controls can be applied to keys created within various contexts. This support +is preliminary, and is likely to change quite significantly in the near future. +Currently, all of the basic permissions explained above are provided in SELinux +as well; SELinux is simply invoked after all basic permission checks have been +performed. + +The value of the file /proc/self/attr/keycreate influences the labeling of +newly-created keys. If the contents of that file correspond to an SELinux +security context, then the key will be assigned that context. Otherwise, the +key will be assigned the current context of the task that invoked the key +creation request. Tasks must be granted explicit permission to assign a +particular context to newly-created keys, using the "create" permission in the +key security class. + +The default keyrings associated with users will be labeled with the default +context of the user if and only if the login programs have been instrumented to +properly initialize keycreate during the login process. Otherwise, they will +be labeled with the context of the login program itself. + +Note, however, that the default keyrings associated with the root user are +labeled with the default kernel context, since they are created early in the +boot process, before root has a chance to log in. + +The keyrings associated with new threads are each labeled with the context of +their associated thread, and both session and process keyrings are handled +similarly. + + ================ NEW PROCFS FILES ================ @@ -241,9 +275,17 @@ about the status of the key service: (*) /proc/keys - This lists all the keys on the system, giving information about their - type, description and permissions. The payload of the key is not available - this way: + This lists the keys that are currently viewable by the task reading the + file, giving information about their type, description and permissions. + It is not possible to view the payload of the key this way, though some + information about it may be given. + + The only keys included in the list are those that grant View permission to + the reading process whether or not it possesses them. Note that LSM + security checks are still performed, and may further filter out keys that + the current process is not authorised to view. + + The contents of the file look like this: SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY 00000001 I----- 39 perm 1f3f0000 0 0 keyring _uid_ses.0: 1/4 @@ -271,7 +313,7 @@ about the status of the key service: (*) /proc/key-users This file lists the tracking data for each user that has at least one key - on the system. Such data includes quota information and statistics: + on the system. Such data includes quota information and statistics: [root@andromeda root]# cat /proc/key-users 0: 46 45/45 1/100 13/10000 @@ -935,6 +977,16 @@ The structure has a number of fields, so It is not safe to sleep in this method; the caller may hold spinlocks. + (*) void (*revoke)(struct key *key); + + This method is optional. It is called to discard part of the payload + data upon a key being revoked. The caller will have the key semaphore + write-locked. + + It is safe to sleep in this method, though care should be taken to avoid + a deadlock against the key semaphore. + + (*) void (*destroy)(struct key *key); This method is optional. It is called to discard the payload data on a key diff --git a/Documentation/md.txt b/Documentation/md.txt index 03a13c4..0668f9d 100644 --- a/Documentation/md.txt +++ b/Documentation/md.txt @@ -200,6 +200,17 @@ All md devices contain: This can be written only while the array is being assembled, not after it is started. + layout + The "layout" for the array for the particular level. This is + simply a number that is interpretted differently by different + levels. It can be written while assembling an array. + + resync_start + The point at which resync should start. If no resync is needed, + this will be a very large number. At array creation it will + default to 0, though starting the array as 'clean' will + set it much larger. + new_dev This file can be written but not read. The value written should be a block device number as major:minor. e.g. 8:0 @@ -207,6 +218,54 @@ All md devices contain: available. It will then appear at md/dev-XXX (depending on the name of the device) and further configuration is then possible. + safe_mode_delay + When an md array has seen no write requests for a certain period + of time, it will be marked as 'clean'. When another write + request arrive, the array is marked as 'dirty' before the write + commenses. This is known as 'safe_mode'. + The 'certain period' is controlled by this file which stores the + period as a number of seconds. The default is 200msec (0.200). + Writing a value of 0 disables safemode. + + array_state + This file contains a single word which describes the current + state of the array. In many cases, the state can be set by + writing the word for the desired state, however some states + cannot be explicitly set, and some transitions are not allowed. + + clear + No devices, no size, no level + Writing is equivalent to STOP_ARRAY ioctl + inactive + May have some settings, but array is not active + all IO results in error + When written, doesn't tear down array, but just stops it + suspended (not supported yet) + All IO requests will block. The array can be reconfigured. + Writing this, if accepted, will block until array is quiessent + readonly + no resync can happen. no superblocks get written. + write requests fail + read-auto + like readonly, but behaves like 'clean' on a write request. + + clean - no pending writes, but otherwise active. + When written to inactive array, starts without resync + If a write request arrives then + if metadata is known, mark 'dirty' and switch to 'active'. + if not known, block and switch to write-pending + If written to an active array that has pending writes, then fails. + active + fully active: IO and resync can be happening. + When written to inactive array, starts with resync + + write-pending + clean, but writes are blocked waiting for 'active' to be written. + + active-idle + like active, but no writes have been seen for a while (safe_mode_delay). + + sync_speed_min sync_speed_max This are similar to /proc/sys/dev/raid/speed_limit_{min,max} @@ -250,10 +309,18 @@ Each directory contains: faulty - device has been kicked from active use due to a detected fault in_sync - device is a fully in-sync member of the array + writemostly - device will only be subject to read + requests if there are no other options. + This applies only to raid1 arrays. spare - device is working, but not a full member. This includes spares that are in the process of being recoverred to This list make grow in future. + This can be written to. + Writing "faulty" simulates a failure on the device. + Writing "remove" removes the device from the array. + Writing "writemostly" sets the writemostly flag. + Writing "-writemostly" clears the writemostly flag. errors An approximate count of read errors that have been detected on diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 4710845..cf0d541 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -262,9 +262,14 @@ What is required is some way of interven CPU to restrict the order. Memory barriers are such interventions. They impose a perceived partial -ordering between the memory operations specified on either side of the barrier. -They request that the sequence of memory events generated appears to other -parts of the system as if the barrier is effective on that CPU. +ordering over the memory operations on either side of the barrier. + +Such enforcement is important because the CPUs and other devices in a system +can use a variety of tricks to improve performance - including reordering, +deferral and combination of memory operations; speculative loads; speculative +branch prediction and various types of caching. Memory barriers are used to +override or suppress these tricks, allowing the code to sanely control the +interaction of multiple CPUs and/or devices. VARIETIES OF MEMORY BARRIER @@ -282,7 +287,7 @@ Memory barriers come in four basic varie A write barrier is a partial ordering on stores only; it is not required to have any effect on loads. - A CPU can be viewed as as commiting a sequence of store operations to the + A CPU can be viewed as committing a sequence of store operations to the memory system as time progresses. All stores before a write barrier will occur in the sequence _before_ all the stores after the write barrier. @@ -413,7 +418,7 @@ There are certain things that the Linux indirect effect will be the order in which the second CPU sees the effects of the first CPU's accesses occur, but see the next point: - (*) There is no guarantee that the a CPU will see the correct order of effects + (*) There is no guarantee that a CPU will see the correct order of effects from a second CPU's accesses, even _if_ the second CPU uses a memory barrier, unless the first CPU _also_ uses a matching memory barrier (see the subsection on "SMP Barrier Pairing"). @@ -461,8 +466,8 @@ Whilst this may seem like a failure of c isn't, and this behaviour can be observed on certain real CPUs (such as the DEC Alpha). -To deal with this, a data dependency barrier must be inserted between the -address load and the data load: +To deal with this, a data dependency barrier or better must be inserted +between the address load and the data load: CPU 1 CPU 2 =============== =============== @@ -484,7 +489,7 @@ lines. The pointer P might be stored in variable B might be stored in an even-numbered cache line. Then, if the even-numbered bank of the reading CPU's cache is extremely busy while the odd-numbered bank is idle, one can see the new value of the pointer P (&B), -but the old value of the variable B (1). +but the old value of the variable B (2). Another example of where data dependency barriers might by required is where a @@ -744,7 +749,7 @@ some effectively random order, despite t : : -If, however, a read barrier were to be placed between the load of E and the +If, however, a read barrier were to be placed between the load of B and the load of A on CPU 2: CPU 1 CPU 2 @@ -1461,9 +1466,8 @@ instruction itself is complete. On a UP system - where this wouldn't be a problem - the smp_mb() is just a compiler barrier, thus making sure the compiler emits the instructions in the -right order without actually intervening in the CPU. Since there there's only -one CPU, that CPU's dependency ordering logic will take care of everything -else. +right order without actually intervening in the CPU. Since there's only one +CPU, that CPU's dependency ordering logic will take care of everything else. ATOMIC OPERATIONS @@ -1640,9 +1644,9 @@ functions: The PCI bus, amongst others, defines an I/O space concept - which on such CPUs as i386 and x86_64 cpus readily maps to the CPU's concept of I/O - space. However, it may also mapped as a virtual I/O space in the CPU's - memory map, particularly on those CPUs that don't support alternate - I/O spaces. + space. However, it may also be mapped as a virtual I/O space in the CPU's + memory map, particularly on those CPUs that don't support alternate I/O + spaces. Accesses to this space may be fully synchronous (as on i386), but intermediary bridges (such as the PCI host bridge) may not fully honour diff --git a/Documentation/networking/README.ipw2200 b/Documentation/networking/README.ipw2200 index acb30c5..4f2a40f 100644 --- a/Documentation/networking/README.ipw2200 +++ b/Documentation/networking/README.ipw2200 @@ -14,8 +14,8 @@ Copyright (C) 2004-2006, Intel Corporati README.ipw2200 -Version: 1.0.8 -Date : October 20, 2005 +Version: 1.1.2 +Date : March 30, 2006 Index @@ -103,7 +103,7 @@ file. 1.1. Overview of Features ----------------------------------------------- -The current release (1.0.8) supports the following features: +The current release (1.1.2) supports the following features: + BSS mode (Infrastructure, Managed) + IBSS mode (Ad-Hoc) @@ -247,8 +247,8 @@ and can set the contents via echo. For % cat /sys/bus/pci/drivers/ipw2200/debug_level Will report the current debug level of the driver's logging subsystem -(only available if CONFIG_IPW_DEBUG was configured when the driver was -built). +(only available if CONFIG_IPW2200_DEBUG was configured when the driver +was built). You can set the debug level via: diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index 8d8b4e5..afac780 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt @@ -1,7 +1,7 @@ Linux Ethernet Bonding Driver HOWTO - Latest update: 21 June 2005 + Latest update: 24 April 2006 Initial release : Thomas Davis Corrections, HA extensions : 2000/10/03-15 : @@ -12,6 +12,8 @@ Corrections, HA extensions : 2000/10/03- - Jay Vosburgh Reorganized and updated Feb 2005 by Jay Vosburgh +Added Sysfs information: 2006/04/24 + - Mitch Williams Introduction ============ @@ -38,61 +40,62 @@ Table of Contents 2. Bonding Driver Options 3. Configuring Bonding Devices -3.1 Configuration with sysconfig support -3.1.1 Using DHCP with sysconfig -3.1.2 Configuring Multiple Bonds with sysconfig -3.2 Configuration with initscripts support -3.2.1 Using DHCP with initscripts -3.2.2 Configuring Multiple Bonds with initscripts -3.3 Configuring Bonding Manually +3.1 Configuration with Sysconfig Support +3.1.1 Using DHCP with Sysconfig +3.1.2 Configuring Multiple Bonds with Sysconfig +3.2 Configuration with Initscripts Support +3.2.1 Using DHCP with Initscripts +3.2.2 Configuring Multiple Bonds with Initscripts +3.3 Configuring Bonding Manually with Ifenslave 3.3.1 Configuring Multiple Bonds Manually +3.4 Configuring Bonding Manually via Sysfs -5. Querying Bonding Configuration -5.1 Bonding Configuration -5.2 Network Configuration +4. Querying Bonding Configuration +4.1 Bonding Configuration +4.2 Network Configuration -6. Switch Configuration +5. Switch Configuration -7. 802.1q VLAN Support +6. 802.1q VLAN Support -8. Link Monitoring -8.1 ARP Monitor Operation -8.2 Configuring Multiple ARP Targets -8.3 MII Monitor Operation +7. Link Monitoring +7.1 ARP Monitor Operation +7.2 Configuring Multiple ARP Targets +7.3 MII Monitor Operation -9. Potential Trouble Sources -9.1 Adventures in Routing -9.2 Ethernet Device Renaming -9.3 Painfully Slow Or No Failed Link Detection By Miimon +8. Potential Trouble Sources +8.1 Adventures in Routing +8.2 Ethernet Device Renaming +8.3 Painfully Slow Or No Failed Link Detection By Miimon -10. SNMP agents +9. SNMP agents -11. Promiscuous mode +10. Promiscuous mode -12. Configuring Bonding for High Availability -12.1 High Availability in a Single Switch Topology -12.2 High Availability in a Multiple Switch Topology -12.2.1 HA Bonding Mode Selection for Multiple Switch Topology -12.2.2 HA Link Monitoring for Multiple Switch Topology +11. Configuring Bonding for High Availability +11.1 High Availability in a Single Switch Topology +11.2 High Availability in a Multiple Switch Topology +11.2.1 HA Bonding Mode Selection for Multiple Switch Topology +11.2.2 HA Link Monitoring for Multiple Switch Topology -13. Configuring Bonding for Maximum Throughput -13.1 Maximum Throughput in a Single Switch Topology -13.1.1 MT Bonding Mode Selection for Single Switch Topology -13.1.2 MT Link Monitoring for Single Switch Topology -13.2 Maximum Throughput in a Multiple Switch Topology -13.2.1 MT Bonding Mode Selection for Multiple Switch Topology -13.2.2 MT Link Monitoring for Multiple Switch Topology +12. Configuring Bonding for Maximum Throughput +12.1 Maximum Throughput in a Single Switch Topology +12.1.1 MT Bonding Mode Selection for Single Switch Topology +12.1.2 MT Link Monitoring for Single Switch Topology +12.2 Maximum Throughput in a Multiple Switch Topology +12.2.1 MT Bonding Mode Selection for Multiple Switch Topology +12.2.2 MT Link Monitoring for Multiple Switch Topology -14. Switch Behavior Issues -14.1 Link Establishment and Failover Delays -14.2 Duplicated Incoming Packets +13. Switch Behavior Issues +13.1 Link Establishment and Failover Delays +13.2 Duplicated Incoming Packets -15. Hardware Specific Considerations -15.1 IBM BladeCenter +14. Hardware Specific Considerations +14.1 IBM BladeCenter -16. Frequently Asked Questions +15. Frequently Asked Questions -17. Resources and Links +16. Resources and Links 1. Bonding Driver Installation @@ -156,6 +159,9 @@ you're trying to build it for. Some dis onwards) do not have /usr/include/linux symbolically linked to the default kernel source include directory. +SECOND IMPORTANT NOTE: + If you plan to configure bonding using sysfs, you do not need +to use ifenslave. 2. Bonding Driver Options ========================= @@ -270,7 +276,7 @@ mode In bonding version 2.6.2 or later, when a failover occurs in active-backup mode, bonding will issue one or more gratuitous ARPs on the newly active slave. - One gratutious ARP is issued for the bonding master + One gratuitous ARP is issued for the bonding master interface and each VLAN interfaces configured above it, provided that the interface has at least one IP address configured. Gratuitous ARPs issued for VLAN @@ -377,7 +383,7 @@ mode When a link is reconnected or a new slave joins the bond the receive traffic is redistributed among all active slaves in the bond by initiating ARP Replies - with the selected mac address to each of the + with the selected MAC address to each of the clients. The updelay parameter (detailed below) must be set to a value equal or greater than the switch's forwarding delay so that the ARP Replies sent to the @@ -498,11 +504,12 @@ not exist, and the layer2 policy is the 3. Configuring Bonding Devices ============================== - There are, essentially, two methods for configuring bonding: -with support from the distro's network initialization scripts, and -without. Distros generally use one of two packages for the network -initialization scripts: initscripts or sysconfig. Recent versions of -these packages have support for bonding, while older versions do not. + You can configure bonding using either your distro's network +initialization scripts, or manually using either ifenslave or the +sysfs interface. Distros generally use one of two packages for the +network initialization scripts: initscripts or sysconfig. Recent +versions of these packages have support for bonding, while older +versions do not. We will first describe the options for configuring bonding for distros using versions of initscripts and sysconfig with full or @@ -530,7 +537,7 @@ issue the command: If this returns any matches, then your initscripts or sysconfig has support for bonding. -3.1 Configuration with sysconfig support +3.1 Configuration with Sysconfig Support ---------------------------------------- This section applies to distros using a version of sysconfig @@ -538,7 +545,7 @@ with bonding support, for example, SuSE SuSE SLES 9's networking configuration system does support bonding, however, at this writing, the YaST system configuration -frontend does not provide any means to work with bonding devices. +front end does not provide any means to work with bonding devices. Bonding devices can be managed by hand, however, as follows. First, if they have not already been configured, configure the @@ -660,7 +667,7 @@ format can be found in an example ifcfg Note that the template does not document the various BONDING_ settings described above, but does describe many of the other options. -3.1.1 Using DHCP with sysconfig +3.1.1 Using DHCP with Sysconfig ------------------------------- Under sysconfig, configuring a device with BOOTPROTO='dhcp' @@ -670,7 +677,7 @@ attempt to obtain the device address fro the slave devices. Without active slaves, the DHCP requests are not sent to the network. -3.1.2 Configuring Multiple Bonds with sysconfig +3.1.2 Configuring Multiple Bonds with Sysconfig ----------------------------------------------- The sysconfig network initialization system is capable of @@ -685,7 +692,7 @@ ifcfg-bondX files. options in the ifcfg-bondX file, it is not necessary to add them to the system /etc/modules.conf or /etc/modprobe.conf configuration file. -3.2 Configuration with initscripts support +3.2 Configuration with Initscripts Support ------------------------------------------ This section applies to distros using a version of initscripts @@ -756,7 +763,7 @@ options for your configuration. will restart the networking subsystem and your bond link should be now up and running. -3.2.1 Using DHCP with initscripts +3.2.1 Using DHCP with Initscripts --------------------------------- Recent versions of initscripts (the version supplied with @@ -768,7 +775,7 @@ above, except replace the line "BOOTPROT and add a line consisting of "TYPE=Bonding". Note that the TYPE value is case sensitive. -3.2.2 Configuring Multiple Bonds with initscripts +3.2.2 Configuring Multiple Bonds with Initscripts ------------------------------------------------- At this writing, the initscripts package does not directly @@ -784,8 +791,8 @@ Fedora Core kernels, and has been seen o exhibiting this problem, it will be impossible to configure multiple bonds with differing parameters. -3.3 Configuring Bonding Manually --------------------------------- +3.3 Configuring Bonding Manually with Ifenslave +----------------------------------------------- This section applies to distros whose network initialization scripts (the sysconfig or initscripts package) do not have specific @@ -889,11 +896,139 @@ install bond1 /sbin/modprobe --ignore-in This may be repeated any number of times, specifying a new and unique name in place of bond1 for each subsequent instance. +3.4 Configuring Bonding Manually via Sysfs +------------------------------------------ + + Starting with version 3.0, Channel Bonding may be configured +via the sysfs interface. This interface allows dynamic configuration +of all bonds in the system without unloading the module. It also +allows for adding and removing bonds at runtime. Ifenslave is no +longer required, though it is still supported. + + Use of the sysfs interface allows you to use multiple bonds +with different configurations without having to reload the module. +It also allows you to use multiple, differently configured bonds when +bonding is compiled into the kernel. + + You must have the sysfs filesystem mounted to configure +bonding this way. The examples in this document assume that you +are using the standard mount point for sysfs, e.g. /sys. If your +sysfs filesystem is mounted elsewhere, you will need to adjust the +example paths accordingly. + +Creating and Destroying Bonds +----------------------------- +To add a new bond foo: +# echo +foo > /sys/class/net/bonding_masters + +To remove an existing bond bar: +# echo -bar > /sys/class/net/bonding_masters + +To show all existing bonds: +# cat /sys/class/net/bonding_masters + +NOTE: due to 4K size limitation of sysfs files, this list may be +truncated if you have more than a few hundred bonds. This is unlikely +to occur under normal operating conditions. + +Adding and Removing Slaves +-------------------------- + Interfaces may be enslaved to a bond using the file +/sys/class/net//bonding/slaves. The semantics for this file +are the same as for the bonding_masters file. + +To enslave interface eth0 to bond bond0: +# ifconfig bond0 up +# echo +eth0 > /sys/class/net/bond0/bonding/slaves + +To free slave eth0 from bond bond0: +# echo -eth0 > /sys/class/net/bond0/bonding/slaves + + NOTE: The bond must be up before slaves can be added. All +slaves are freed when the interface is brought down. + + When an interface is enslaved to a bond, symlinks between the +two are created in the sysfs filesystem. In this case, you would get +/sys/class/net/bond0/slave_eth0 pointing to /sys/class/net/eth0, and +/sys/class/net/eth0/master pointing to /sys/class/net/bond0. + + This means that you can tell quickly whether or not an +interface is enslaved by looking for the master symlink. Thus: +# echo -eth0 > /sys/class/net/eth0/master/bonding/slaves +will free eth0 from whatever bond it is enslaved to, regardless of +the name of the bond interface. + +Changing a Bond's Configuration +------------------------------- + Each bond may be configured individually by manipulating the +files located in /sys/class/net//bonding + + The names of these files correspond directly with the command- +line parameters described elsewhere in in this file, and, with the +exception of arp_ip_target, they accept the same values. To see the +current setting, simply cat the appropriate file. + + A few examples will be given here; for specific usage +guidelines for each parameter, see the appropriate section in this +document. + +To configure bond0 for balance-alb mode: +# ifconfig bond0 down +# echo 6 > /sys/class/net/bond0/bonding/mode + - or - +# echo balance-alb > /sys/class/net/bond0/bonding/mode + NOTE: The bond interface must be down before the mode can be +changed. + +To enable MII monitoring on bond0 with a 1 second interval: +# echo 1000 > /sys/class/net/bond0/bonding/miimon + NOTE: If ARP monitoring is enabled, it will disabled when MII +monitoring is enabled, and vice-versa. + +To add ARP targets: +# echo +192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target +# echo +192.168.0.101 > /sys/class/net/bond0/bonding/arp_ip_target + NOTE: up to 10 target addresses may be specified. + +To remove an ARP target: +# echo -192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target + +Example Configuration +--------------------- + We begin with the same example that is shown in section 3.3, +executed with sysfs, and without using ifenslave. + + To make a simple bond of two e100 devices (presumed to be eth0 +and eth1), and have it persist across reboots, edit the appropriate +file (/etc/init.d/boot.local or /etc/rc.d/rc.local), and add the +following: + +modprobe bonding +modprobe e100 +echo balance-alb > /sys/class/net/bond0/bonding/mode +ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up +echo 100 > /sys/class/net/bond0/bonding/miimon +echo +eth0 > /sys/class/net/bond0/bonding/slaves +echo +eth1 > /sys/class/net/bond0/bonding/slaves + + To add a second bond, with two e1000 interfaces in +active-backup mode, using ARP monitoring, add the following lines to +your init script: + +modprobe e1000 +echo +bond1 > /sys/class/net/bonding_masters +echo active-backup > /sys/class/net/bond1/bonding/mode +ifconfig bond1 192.168.2.1 netmask 255.255.255.0 up +echo +192.168.2.100 /sys/class/net/bond1/bonding/arp_ip_target +echo 2000 > /sys/class/net/bond1/bonding/arp_interval +echo +eth2 > /sys/class/net/bond1/bonding/slaves +echo +eth3 > /sys/class/net/bond1/bonding/slaves + -5. Querying Bonding Configuration +4. Querying Bonding Configuration ================================= -5.1 Bonding Configuration +4.1 Bonding Configuration ------------------------- Each bonding device has a read-only file residing in the @@ -923,7 +1058,7 @@ generally as follows: The precise format and contents will change depending upon the bonding configuration, state, and version of the bonding driver. -5.2 Network configuration +4.2 Network configuration ------------------------- The network configuration can be inspected using the ifconfig @@ -958,7 +1093,7 @@ eth1 Link encap:Ethernet HWaddr 00 collisions:0 txqueuelen:100 Interrupt:9 Base address:0x1400 -6. Switch Configuration +5. Switch Configuration ======================= For this section, "switch" refers to whatever system the @@ -991,7 +1126,7 @@ transmit policy for an EtherChannel grou with another EtherChannel group. -7. 802.1q VLAN Support +6. 802.1q VLAN Support ====================== It is possible to configure VLAN devices over a bond interface @@ -1042,7 +1177,7 @@ underlying device -- i.e. the bonding in mode, which might not be what you want. -8. Link Monitoring +7. Link Monitoring ================== The bonding driver at present supports two schemes for @@ -1053,7 +1188,7 @@ monitor. bonding driver itself, it is not possible to enable both ARP and MII monitoring simultaneously. -8.1 ARP Monitor Operation +7.1 ARP Monitor Operation ------------------------- The ARP monitor operates as its name suggests: it sends ARP @@ -1071,7 +1206,7 @@ those slaves will stay down. If network shows the ARP requests and replies on the network, then it may be that your device driver is not updating last_rx and trans_start. -8.2 Configuring Multiple ARP Targets +7.2 Configuring Multiple ARP Targets ------------------------------------ While ARP monitoring can be done with just one target, it can @@ -1094,7 +1229,7 @@ alias bond0 bonding options bond0 arp_interval=60 arp_ip_target=192.168.0.100 -8.3 MII Monitor Operation +7.3 MII Monitor Operation ------------------------- The MII monitor monitors only the carrier state of the local @@ -1120,14 +1255,14 @@ does not support or had some error in pr and ethtool requests), then the MII monitor will assume the link is up. -9. Potential Sources of Trouble +8. Potential Sources of Trouble =============================== -9.1 Adventures in Routing +8.1 Adventures in Routing ------------------------- When bonding is configured, it is important that the slave -devices not have routes that supercede routes of the master (or, +devices not have routes that supersede routes of the master (or, generally, not have routes at all). For example, suppose the bonding device bond0 has two slaves, eth0 and eth1, and the routing table is as follows: @@ -1154,11 +1289,11 @@ by the state of the routing table. The solution here is simply to insure that slaves do not have routes of their own, and if for some reason they must, those routes do -not supercede routes of their master. This should generally be the +not supersede routes of their master. This should generally be the case, but unusual configurations or errant manual or automatic static route additions may cause trouble. -9.2 Ethernet Device Renaming +8.2 Ethernet Device Renaming ---------------------------- On systems with network configuration scripts that do not @@ -1207,7 +1342,7 @@ modprobe with --ignore-install to cause place. Full documentation on this can be found in the modprobe.conf and modprobe manual pages. -9.3. Painfully Slow Or No Failed Link Detection By Miimon +8.3. Painfully Slow Or No Failed Link Detection By Miimon --------------------------------------------------------- By default, bonding enables the use_carrier option, which @@ -1235,7 +1370,7 @@ carrier state. It has no way to determi beyond other ports of a switch, or if a switch is refusing to pass traffic while still maintaining carrier on. -10. SNMP agents +9. SNMP agents =============== If running SNMP agents, the bonding driver should be loaded @@ -1281,7 +1416,7 @@ ifDescr, the association between the IP and SNMP functions such as Interface_Scan_Next will report that association. -11. Promiscuous mode +10. Promiscuous mode ==================== When running network monitoring tools, e.g., tcpdump, it is @@ -1308,7 +1443,7 @@ sending to peers that are unassigned or the active slave changes (e.g., due to a link failure), the promiscuous setting will be propagated to the new active slave. -12. Configuring Bonding for High Availability +11. Configuring Bonding for High Availability ============================================= High Availability refers to configurations that provide @@ -1318,7 +1453,7 @@ goal is to provide the maximum availabil (i.e., the network always works), even though other configurations could provide higher throughput. -12.1 High Availability in a Single Switch Topology +11.1 High Availability in a Single Switch Topology -------------------------------------------------- If two hosts (or a host and a single switch) are directly @@ -1332,7 +1467,7 @@ the load will be rebalanced across the r See Section 13, "Configuring Bonding for Maximum Throughput" for information on configuring bonding with one peer device. -12.2 High Availability in a Multiple Switch Topology +11.2 High Availability in a Multiple Switch Topology ---------------------------------------------------- With multiple switches, the configuration of bonding and the @@ -1359,7 +1494,7 @@ switches (ISL, or inter switch link), an the outside world ("port3" on each switch). There is no technical reason that this could not be extended to a third switch. -12.2.1 HA Bonding Mode Selection for Multiple Switch Topology +11.2.1 HA Bonding Mode Selection for Multiple Switch Topology ------------------------------------------------------------- In a topology such as the example above, the active-backup and @@ -1381,7 +1516,7 @@ broadcast: This mode is really a special necessary for some specific one-way traffic to reach both independent networks, then the broadcast mode may be suitable. -12.2.2 HA Link Monitoring Selection for Multiple Switch Topology +11.2.2 HA Link Monitoring Selection for Multiple Switch Topology ---------------------------------------------------------------- The choice of link monitoring ultimately depends upon your @@ -1402,10 +1537,10 @@ regardless of which switch is active, th target to query. -13. Configuring Bonding for Maximum Throughput +12. Configuring Bonding for Maximum Throughput ============================================== -13.1 Maximizing Throughput in a Single Switch Topology +12.1 Maximizing Throughput in a Single Switch Topology ------------------------------------------------------ In a single switch configuration, the best method to maximize @@ -1476,7 +1611,7 @@ destination to make load balancing decis mode is described below. -13.1.1 MT Bonding Mode Selection for Single Switch Topology +12.1.1 MT Bonding Mode Selection for Single Switch Topology ----------------------------------------------------------- This configuration is the easiest to set up and to understand, @@ -1607,7 +1742,7 @@ balance-alb: This mode is everything tha device driver must support changing the hardware address while the device is open. -13.1.2 MT Link Monitoring for Single Switch Topology +12.1.2 MT Link Monitoring for Single Switch Topology ---------------------------------------------------- The choice of link monitoring may largely depend upon which @@ -1616,7 +1751,7 @@ support the use of the ARP monitor, and the MII monitor (which does not provide as high a level of end to end assurance as the ARP monitor). -13.2 Maximum Throughput in a Multiple Switch Topology +12.2 Maximum Throughput in a Multiple Switch Topology ----------------------------------------------------- Multiple switches may be utilized to optimize for throughput @@ -1651,7 +1786,7 @@ a single 72 port switch. can be equipped with an additional network device connected to an external network; this host then additionally acts as a gateway. -13.2.1 MT Bonding Mode Selection for Multiple Switch Topology +12.2.1 MT Bonding Mode Selection for Multiple Switch Topology ------------------------------------------------------------- In actual practice, the bonding mode typically employed in @@ -1664,7 +1799,7 @@ packets has arrived). When employed in mode allows individual connections between two hosts to effectively utilize greater than one interface's bandwidth. -13.2.2 MT Link Monitoring for Multiple Switch Topology +12.2.2 MT Link Monitoring for Multiple Switch Topology ------------------------------------------------------ Again, in actual practice, the MII monitor is most often used @@ -1674,10 +1809,10 @@ advantages over the MII monitor are miti needed as the number of systems involved grows (remember that each host in the network is configured with bonding). -14. Switch Behavior Issues +13. Switch Behavior Issues ========================== -14.1 Link Establishment and Failover Delays +13.1 Link Establishment and Failover Delays ------------------------------------------- Some switches exhibit undesirable behavior with regard to the @@ -1712,7 +1847,7 @@ switches take a long time to go into bac to not activate a backup interface immediately after a link goes down. Failover may be delayed via the downdelay bonding module option. -14.2 Duplicated Incoming Packets +13.2 Duplicated Incoming Packets -------------------------------- It is not uncommon to observe a short burst of duplicated @@ -1751,14 +1886,14 @@ behavior, it can be induced by clearing most Cisco switches, the privileged command "clear mac address-table dynamic" will accomplish this). -15. Hardware Specific Considerations +14. Hardware Specific Considerations ==================================== This section contains additional information for configuring bonding on specific hardware platforms, or for interfacing bonding with particular switches or other devices. -15.1 IBM BladeCenter +14.1 IBM BladeCenter -------------------- This applies to the JS20 and similar systems. @@ -1861,7 +1996,7 @@ (either the internal Ethernet Switch Mod avoid fail-over delay issues when using bonding. -16. Frequently Asked Questions +15. Frequently Asked Questions ============================== 1. Is it SMP safe? @@ -1925,7 +2060,7 @@ not have special switch requirements, bu support specific features (described in the appropriate section under module parameters, above). - In 802.3ad mode, it works with with systems that support IEEE + In 802.3ad mode, it works with systems that support IEEE 802.3ad Dynamic Link Aggregation. Most managed and many unmanaged switches currently available support 802.3ad. diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index f12007b..d46338a 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -362,6 +362,13 @@ tcp_workaround_signed_windows - BOOLEAN not receive a window scaling option from them. Default: 0 +tcp_slow_start_after_idle - BOOLEAN + If set, provide RFC2861 behavior and time out the congestion + window after an idle period. An idle period is defined at + the current RTO. If unset, the congestion window will not + be timed out after an idle period. + Default: 1 + IP Variables: ip_local_port_range - 2 INTEGERS diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt index 3c0a5ba..847cedb 100644 --- a/Documentation/networking/netdevices.txt +++ b/Documentation/networking/netdevices.txt @@ -42,9 +42,9 @@ dev->get_stats: Context: nominally process, but don't sleep inside an rwlock dev->hard_start_xmit: - Synchronization: dev->xmit_lock spinlock. + Synchronization: netif_tx_lock spinlock. When the driver sets NETIF_F_LLTX in dev->features this will be - called without holding xmit_lock. In this case the driver + called without holding netif_tx_lock. In this case the driver has to lock by itself when needed. It is recommended to use a try lock for this and return -1 when the spin lock fails. The locking there should also properly protect against @@ -62,12 +62,12 @@ dev->hard_start_xmit: Only valid when NETIF_F_LLTX is set. dev->tx_timeout: - Synchronization: dev->xmit_lock spinlock. + Synchronization: netif_tx_lock spinlock. Context: BHs disabled Notes: netif_queue_stopped() is guaranteed true dev->set_multicast_list: - Synchronization: dev->xmit_lock spinlock. + Synchronization: netif_tx_lock spinlock. Context: BHs disabled dev->poll: diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt index 76750fb..839cbb7 100644 --- a/Documentation/networking/tuntap.txt +++ b/Documentation/networking/tuntap.txt @@ -39,10 +39,13 @@ Copyright (C) 1999-2000 Maxim Krasnyansk mknod /dev/net/tun c 10 200 Set permissions: - e.g. chmod 0700 /dev/net/tun - if you want the device only accessible by root. Giving regular users the - right to assign network devices is NOT a good idea. Users could assign - bogus network interfaces to trick firewalls or administrators. + e.g. chmod 0666 /dev/net/tun + There's no harm in allowing the device to be accessible by non-root users, + since CAP_NET_ADMIN is required for creating network devices or for + connecting to network devices which aren't owned by the user in question. + If you want to create persistent devices and give ownership of them to + unprivileged users, then you need the /dev/net/tun device to be usable by + those users. Driver module autoloading diff --git a/Documentation/pci.txt b/Documentation/pci.txt index 66bbbf1..3242e5c 100644 --- a/Documentation/pci.txt +++ b/Documentation/pci.txt @@ -213,9 +213,17 @@ have been remapped by the kernel. See Documentation/IO-mapping.txt for how to access device memory. - You still need to call request_region() for I/O regions and -request_mem_region() for memory regions to make sure nobody else is using the -same device. + The device driver needs to call pci_request_region() to make sure +no other device is already using the same resource. The driver is expected +to determine MMIO and IO Port resource availability _before_ calling +pci_enable_device(). Conversely, drivers should call pci_release_region() +_after_ calling pci_disable_device(). The idea is to prevent two devices +colliding on the same address range. + +Generic flavors of pci_request_region() are request_mem_region() +(for MMIO ranges) and request_region() (for IO Port ranges). +Use these for address resources that are not described by "normal" PCI +interfaces (e.g. BAR). All interrupt handlers should be registered with SA_SHIRQ and use the devid to map IRQs to devices (remember that all PCI interrupts are shared). diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index f987afe..fba1e05 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -135,96 +135,6 @@ # NOTIFICATION -- pretty much same as ON FREEZE -- stop DMA and interrupts, and be prepared to reinit HW from scratch. That probably means stop accepting upstream requests, the -actual policy of what to do with them beeing specific to a given -driver. It's acceptable for a network driver to just drop packets -while a block driver is expected to block the queue so no request is -lost. (Use IDE as an example on how to do that). FREEZE requires no -power state change, and it's expected for drivers to be able to -quickly transition back to operating state. - -SUSPEND -- like FREEZE, but also put hardware into low-power state. If -there's need to distinguish several levels of sleep, additional flag -is probably best way to do that. - -Transitions are only from a resumed state to a suspended state, never -between 2 suspended states. (ON -> FREEZE or ON -> SUSPEND can happen, -FREEZE -> SUSPEND or SUSPEND -> FREEZE can not). - -All events are: - -[NOTE NOTE NOTE: If you are driver author, you should not care; you -should only look at event, and ignore flags.] - -#Prepare for suspend -- userland is still running but we are going to -#enter suspend state. This gives drivers chance to load firmware from -#disk and store it in memory, or do other activities taht require -#operating userland, ability to kmalloc GFP_KERNEL, etc... All of these -#are forbiden once the suspend dance is started.. event = ON, flags = -#PREPARE_TO_SUSPEND - -Apm standby -- prepare for APM event. Quiesce devices to make life -easier for APM BIOS. event = FREEZE, flags = APM_STANDBY - -Apm suspend -- same as APM_STANDBY, but it we should probably avoid -spinning down disks. event = FREEZE, flags = APM_SUSPEND - -System halt, reboot -- quiesce devices to make life easier for BIOS. event -= FREEZE, flags = SYSTEM_HALT or SYSTEM_REBOOT - -System shutdown -- at least disks need to be spun down, or data may be -lost. Quiesce devices, just to make life easier for BIOS. event = -FREEZE, flags = SYSTEM_SHUTDOWN - -Kexec -- turn off DMAs and put hardware into some state where new -kernel can take over. event = FREEZE, flags = KEXEC - -Powerdown at end of swsusp -- very similar to SYSTEM_SHUTDOWN, except wake -may need to be enabled on some devices. This actually has at least 3 -subtypes, system can reboot, enter S4 and enter S5 at the end of -swsusp. event = FREEZE, flags = SWSUSP and one of SYSTEM_REBOOT, -SYSTEM_SHUTDOWN, SYSTEM_S4 - -Suspend to ram -- put devices into low power state. event = SUSPEND, -flags = SUSPEND_TO_RAM - -Freeze for swsusp snapshot -- stop DMA and interrupts. No need to put -devices into low power mode, but you must be able to reinitialize -device from scratch in resume method. This has two flavors, its done -once on suspending kernel, once on resuming kernel. event = FREEZE, -flags = DURING_SUSPEND or DURING_RESUME - -Device detach requested from /sys -- deinitialize device; proably same as -SYSTEM_SHUTDOWN, I do not understand this one too much. probably event -= FREEZE, flags = DEV_DETACH. - -#These are not really events sent: -# -#System fully on -- device is working normally; this is probably never -#passed to suspend() method... event = ON, flags = 0 -# -#Ready after resume -- userland is now running, again. Time to free any -#memory you ate during prepare to suspend... event = ON, flags = -#READY_AFTER_RESUME -# - - -pm_message_t meaning - -pm_message_t has two fields. event ("major"), and flags. If driver -does not know event code, it aborts the request, returning error. Some -drivers may need to deal with special cases based on the actual type -of suspend operation being done at the system level. This is why -there are flags. - -Event codes are: - -ON -- no need to do anything except special cases like broken -HW. - -# NOTIFICATION -- pretty much same as ON? - -FREEZE -- stop DMA and interrupts, and be prepared to reinit HW from -scratch. That probably means stop accepting upstream requests, the actual policy of what to do with them being specific to a given driver. It's acceptable for a network driver to just drop packets while a block driver is expected to block the queue so no request is diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index d7814a1..823b2cf 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt @@ -18,10 +18,11 @@ Some warnings, first. * * (*) suspend/resume support is needed to make it safe. * - * If you have any filesystems on USB devices mounted before suspend, + * If you have any filesystems on USB devices mounted before software suspend, * they won't be accessible after resume and you may lose data, as though - * you have unplugged the USB devices with mounted filesystems on them - * (see the FAQ below for details). + * you have unplugged the USB devices with mounted filesystems on them; + * see the FAQ below for details. (This is not true for more traditional + * power states like "standby", which normally don't turn USB off.) You need to append resume=/dev/your_swap_partition to kernel command line. Then you suspend by @@ -204,7 +205,7 @@ Q: There don't seem to be any generally distinctions between SUSPEND and FREEZE. A: Doing SUSPEND when you are asked to do FREEZE is always correct, -but it may be unneccessarily slow. If you want USB to stay simple, +but it may be unneccessarily slow. If you want your driver to stay simple, slowness may not matter to you. It can always be fixed later. For devices like disk it does matter, you do not want to spindown for @@ -349,25 +350,72 @@ Q: How do I make suspend more verbose? A: If you want to see any non-error kernel messages on the virtual terminal the kernel switches to during suspend, you have to set the -kernel console loglevel to at least 5, for example by doing - - echo 5 > /proc/sys/kernel/printk +kernel console loglevel to at least 4 (KERN_WARNING), for example by +doing + + # save the old loglevel + read LOGLEVEL DUMMY < /proc/sys/kernel/printk + # set the loglevel so we see the progress bar. + # if the level is higher than needed, we leave it alone. + if [ $LOGLEVEL -lt 5 ]; then + echo 5 > /proc/sys/kernel/printk + fi + + IMG_SZ=0 + read IMG_SZ < /sys/power/image_size + echo -n disk > /sys/power/state + RET=$? + # + # the logic here is: + # if image_size > 0 (without kernel support, IMG_SZ will be zero), + # then try again with image_size set to zero. + if [ $RET -ne 0 -a $IMG_SZ -ne 0 ]; then # try again with minimal image size + echo 0 > /sys/power/image_size + echo -n disk > /sys/power/state + RET=$? + fi + + # restore previous loglevel + echo $LOGLEVEL > /proc/sys/kernel/printk + exit $RET Q: Is this true that if I have a mounted filesystem on a USB device and I suspend to disk, I can lose data unless the filesystem has been mounted with "sync"? -A: That's right. It depends on your hardware, and it could be true even for -suspend-to-RAM. In fact, even with "-o sync" you can lose data if your -programs have information in buffers they haven't written out to disk. +A: That's right ... if you disconnect that device, you may lose data. +In fact, even with "-o sync" you can lose data if your programs have +information in buffers they haven't written out to a disk you disconnect, +or if you disconnect before the device finished saving data you wrote. -If you're lucky, your hardware will support low-power modes for USB -controllers while the system is asleep. Lots of hardware doesn't, -however. Shutting off the power to a USB controller is equivalent to -unplugging all the attached devices. +Software suspend normally powers down USB controllers, which is equivalent +to disconnecting all USB devices attached to your system. -Remember that it's always a bad idea to unplug a disk drive containing a -mounted filesystem. With USB that's true even when your system is asleep! -The safest thing is to unmount all USB-based filesystems before suspending -and remount them after resuming. +Your system might well support low-power modes for its USB controllers +while the system is asleep, maintaining the connection, using true sleep +modes like "suspend-to-RAM" or "standby". (Don't write "disk" to the +/sys/power/state file; write "standby" or "mem".) We've not seen any +hardware that can use these modes through software suspend, although in +theory some systems might support "platform" or "firmware" modes that +won't break the USB connections. +Remember that it's always a bad idea to unplug a disk drive containing a +mounted filesystem. That's true even when your system is asleep! The +safest thing is to unmount all filesystems on removable media (such USB, +Firewire, CompactFlash, MMC, external SATA, or even IDE hotplug bays) +before suspending; then remount them after resuming. + +Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were +compiled with the similar configuration files. Anyway I found that +suspend to disk (and resume) is much slower on 2.6.16 compared to +2.6.15. Any idea for why that might happen or how can I speed it up? + +A: This is because the size of the suspend image is now greater than +for 2.6.15 (by saving more data we can get more responsive system +after resume). + +There's the /sys/power/image_size knob that controls the size of the +image. If you set it to 0 (eg. by echo 0 > /sys/power/image_size as +root), the 2.6.15 behavior should be restored. If it is still too +slow, take a look at suspend.sf.net -- userland suspend is faster and +supports LZF compression to speed it up further. diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt index 43a889f..d859faa 100644 --- a/Documentation/power/video.txt +++ b/Documentation/power/video.txt @@ -90,6 +90,7 @@ Table of known working notebooks: Model hack (or "how to do it") ------------------------------------------------------------------------------ Acer Aspire 1406LC ole's late BIOS init (7), turn off DRI +Acer TM 230 s3_bios (2) Acer TM 242FX vbetool (6) Acer TM C110 video_post (8) Acer TM C300 vga=normal (only suspend on console, not in X), vbetool (6) or video_post (8) @@ -115,6 +116,7 @@ Dell D610 vga=normal and X (possibly v Dell Inspiron 4000 ??? (*) Dell Inspiron 500m ??? (*) Dell Inspiron 510m ??? +Dell Inspiron 5150 vbetool needed (6) Dell Inspiron 600m ??? (*) Dell Inspiron 8200 ??? (*) Dell Inspiron 8500 ??? (*) @@ -125,6 +127,7 @@ HP NX7000 ??? (*) HP Pavilion ZD7000 vbetool post needed, need open-source nv driver for X HP Omnibook XE3 athlon version none (1) HP Omnibook XE3GC none (1), video is S3 Savage/IX-MV +HP Omnibook XE3L-GF vbetool (6) HP Omnibook 5150 none (1), (S1 also works OK) IBM TP T20, model 2647-44G none (1), video is S3 Inc. 86C270-294 Savage/IX-MV, vesafb gets "interesting" but X work. IBM TP A31 / Type 2652-M5G s3_mode (3) [works ok with BIOS 1.04 2002-08-23, but not at all with BIOS 1.11 2004-11-05 :-(] @@ -157,6 +160,7 @@ Sony Vaio vgn-s260 X or boot-radeon can Sony Vaio vgn-S580BH vga=normal, but suspend from X. Console will be blank unless you return to X. Sony Vaio vgn-FS115B s3_bios (2),s3_mode (4) Toshiba Libretto L5 none (1) +Toshiba Libretto 100CT/110CT vbetool (6) Toshiba Portege 3020CT s3_mode (3) Toshiba Satellite 4030CDT s3_mode (3) (S1 also works OK) Toshiba Satellite 4080XCDT s3_mode (3) (S1 also works OK) diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt index 95d17b3..2a58f98 100644 --- a/Documentation/rtc.txt +++ b/Documentation/rtc.txt @@ -44,8 +44,10 @@ normal timer interrupt, which is 100Hz. Programming and/or enabling interrupt frequencies greater than 64Hz is only allowed by root. This is perhaps a bit conservative, but we don't want an evil user generating lots of IRQs on a slow 386sx-16, where it might have -a negative impact on performance. Note that the interrupt handler is only -a few lines of code to minimize any possibility of this effect. +a negative impact on performance. This 64Hz limit can be changed by writing +a different value to /proc/sys/dev/rtc/max-user-freq. Note that the +interrupt handler is only a few lines of code to minimize any possibility +of this effect. Also, if the kernel time is synchronized with an external source, the kernel will write the time back to the CMOS clock every 11 minutes. In @@ -81,6 +83,7 @@ that will be using this driver. */ #include +#include #include #include #include diff --git a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX index e7da8c3..1235483 100644 --- a/Documentation/scsi/00-INDEX +++ b/Documentation/scsi/00-INDEX @@ -30,8 +30,6 @@ aic7xxx.txt - info on driver for Adaptec controllers aic7xxx_old.txt - info on driver for Adaptec controllers, old generation -cpqfc.txt - - info on driver for Compaq Tachyon TS adapters dpti.txt - info on driver for DPT SmartRAID and Adaptec I2O RAID based adapters dtc3x80.txt diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas index 2dafa63..0a85a7e 100644 --- a/Documentation/scsi/ChangeLog.megaraid_sas +++ b/Documentation/scsi/ChangeLog.megaraid_sas @@ -1,3 +1,16 @@ + +1 Release Date : Wed Feb 03 14:31:44 PST 2006 - Sumant Patro +2 Current Version : 00.00.02.04 +3 Older Version : 00.00.02.04 + +i. Remove superflous instance_lock + + gets rid of the otherwise superflous instance_lock and avoids an unsave + unsynchronized access in the error handler. + + - Christoph Hellwig + + 1 Release Date : Wed Feb 03 14:31:44 PST 2006 - Sumant Patro 2 Current Version : 00.00.02.04 3 Older Version : 00.00.02.04 diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt index 820fd07..be55670 100644 --- a/Documentation/scsi/aacraid.txt +++ b/Documentation/scsi/aacraid.txt @@ -24,10 +24,10 @@ Supported Cards/Chipsets 9005:0285:9005:0296 Adaptec 2240S (SabreExpress) 9005:0285:9005:0290 Adaptec 2410SA (Jaguar) 9005:0285:9005:0293 Adaptec 21610SA (Corsair-16) - 9005:0285:103c:3227 Adaptec 2610SA (Bearcat) + 9005:0285:103c:3227 Adaptec 2610SA (Bearcat HP release) 9005:0285:9005:0292 Adaptec 2810SA (Corsair-8) 9005:0285:9005:0294 Adaptec Prowler - 9005:0286:9005:029d Adaptec 2420SA (Intruder) + 9005:0286:9005:029d Adaptec 2420SA (Intruder HP release) 9005:0286:9005:029c Adaptec 2620SA (Intruder) 9005:0286:9005:029b Adaptec 2820SA (Intruder) 9005:0286:9005:02a7 Adaptec 2830SA (Skyray) @@ -38,7 +38,7 @@ Supported Cards/Chipsets 9005:0285:9005:0297 Adaptec 4005SAS (AvonPark) 9005:0285:9005:0299 Adaptec 4800SAS (Marauder-X) 9005:0285:9005:029a Adaptec 4805SAS (Marauder-E) - 9005:0286:9005:02a2 Adaptec 4810SAS (Hurricane) + 9005:0286:9005:02a2 Adaptec 3800SAS (Hurricane44) 1011:0046:9005:0364 Adaptec 5400S (Mustang) 1011:0046:9005:0365 Adaptec 5400S (Mustang) 9005:0283:9005:0283 Adaptec Catapult (3210S with arc firmware) @@ -72,7 +72,7 @@ Supported Cards/Chipsets 9005:0286:9005:02a1 ICP ICP9087MA (Lancer) 9005:0286:9005:02a4 ICP ICP9085LI (Marauder-X) 9005:0286:9005:02a5 ICP ICP5085BR (Marauder-E) - 9005:0286:9005:02a3 ICP ICP5085AU (Hurricane) + 9005:0286:9005:02a3 ICP ICP5445AU (Hurricane44) 9005:0286:9005:02a6 ICP ICP9067MA (Intruder-6) 9005:0286:9005:02a9 ICP ICP5087AU (Skyray) 9005:0286:9005:02aa ICP ICP5047AU (Skyray) diff --git a/Documentation/scsi/cpqfc.txt b/Documentation/scsi/cpqfc.txt deleted file mode 100644 index dd33e61..0000000 --- a/Documentation/scsi/cpqfc.txt +++ /dev/null @@ -1,272 +0,0 @@ -Notes for CPQFCTS driver for Compaq Tachyon TS -Fibre Channel Host Bus Adapter, PCI 64-bit, 66MHz -for Linux (RH 6.1, 6.2 kernel 2.2.12-32, 2.2.14-5) -SMP tested -Tested in single and dual HBA configuration, 32 and 64bit busses, -33 and 66MHz. Only supports FC-AL. -SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc() - max of 128k bytes contiguous. - -Ver 2.5.4 Oct 03, 2002 - * fixed memcpy of sense buffer in ioctl to copy the smaller defined size -Ver 2.5.3 Aug 01, 2002 - * fix the passthru ioctl to handle the Scsi_Cmnd->request being a pointer -Ver 2.5.1 Jul 30, 2002 - * fix ioctl to pay attention to the specified LUN. -Ver 2.5.0 Nov 29, 2001 - * eliminated io_request_lock. This change makes the driver specific - to the 2.5.x kernels. - * silenced excessively noisy printks. - -Ver 2.1.2 July 23, 2002 - * initialize DumCmnd->lun in cpqfcTS_ioctl (used in fcFindLoggedInPorts as LUN index) - -Ver 2.1.1 Oct 18, 2001 - * reinitialize Cmnd->SCp.sent_command (used to identify commands as - passthrus) on calling scsi_done, since the scsi mid layer does not - use (or reinitialize) this field to prevent subsequent comands from - having it set incorrectly. - -Ver 2.1.0 Aug 27, 2001 - * Revise driver to use new kernel 2.4.x PCI DMA API, instead of - virt_to_bus(). (enables driver to work w/ ia64 systems with >2Gb RAM.) - Rework main scatter-gather code to handle cases where SG element - lengths are larger than 0x7FFFF bytes and use as many scatter - gather pages as necessary. (Steve Cameron) - * Makefile changes to bring cpqfc into line w/ rest of SCSI drivers - (thanks to Keith Owens) - -Ver 2.0.5 Aug 06, 2001 - * Reject non-existent luns in the driver rather than letting the - hardware do it. (some HW behaves differently than others in this area.) - * Changed Makefile to rely on "make dep" instead of explicit dependencies - * ifdef'ed out fibre channel analyzer triggering debug code - * fixed a jiffies wrapping issue - -Ver 2.0.4 Aug 01, 2001 - * Incorporated fix for target device reset from Steeleye - * Fixed passthrough ioctl so it doesn't hang. - * Fixed hang in launch_FCworker_thread() that occurred on some machines. - * Avoid problem when number of volumes in a single cabinet > 8 - -Ver 2.0.2 July 23, 2001 - Changed the semiphore changes so the driver would compile in 2.4.7. - This version is for 2.4.7 and beyond. - -Ver 2.0.1 May 7, 2001 - Merged version 1.3.6 fixes into version 2.0.0. - -Ver 2.0.0 May 7, 2001 - Fixed problem so spinlock is being initialized to UNLOCKED. - Fixed updated driver so it compiles in the 2.4 tree. - - Ver 1.3.6 Feb 27, 2001 - Added Target_Device_Reset function for SCSI error handling - Fixed problem with not reseting addressing mode after implicit logout - - -Ver 1.3.4 Sep 7, 2000 - Added Modinfo information - Fixed problem with statically linking the driver - -Ver 1.3.3, Aug 23, 2000 - Fixed device/function number in ioctl - -Ver 1.3.2, July 27, 2000 - Add include for Alpha compile on 2.2.14 kernel (cpq*i2c.c) - Change logic for different FCP-RSP sense_buffer location for HSG80 target - And search for Agilent Tachyon XL2 HBAs (not finished! - in test) - -Tested with -(storage): - Compaq RA-4x000, RAID firmware ver 2.40 - 2.54 - Seagate FC drives model ST39102FC, rev 0006 - Hitachi DK31CJ-72FC rev J8A8 - IBM DDYF-T18350R rev F60K - Compaq FC-SCSI bridge w/ DLT 35/70 Gb DLT (tape) -(servers): - Compaq PL-1850R - Compaq PL-6500 Xeon (400MHz) - Compaq PL-8500 (500MHz, 66MHz, 64bit PCI) - Compaq Alpha DS20 (RH 6.1) -(hubs): - Vixel Rapport 1000 (7-port "dumb") - Gadzoox Gibralter (12-port "dumb") - Gadzoox Capellix 2000, 3000 -(switches): - Brocade 2010, 2400, 2800, rev 2.0.3a (& later) - Gadzoox 3210 (Fabric blade beta) - Vixel 7100 (Fabric beta firmare - known hot plug issues) -using "qa_test" (esp. io_test script) suite modified from Unix tests. - -Installation: -make menuconfig - (select SCSI low-level, Compaq FC HBA) -make modules -make modules_install - -e.g. insmod -f cpqfc - -Due to Fabric/switch delays, driver requires 4 seconds -to initialize. If adapters are found, there will be a entries at -/proc/scsi/cpqfcTS/* - -sample contents of startup messages - -************************* - scsi_register allocating 3596 bytes for CPQFCHBA - ioremap'd Membase: c887e600 - HBA Tachyon RevId 1.2 -Allocating 119808 for 576 Exchanges @ c0dc0000 -Allocating 112904 for LinkQ @ c0c20000 (576 elements) -Allocating 110600 for TachSEST for 512 Exchanges - cpqfcTS: writing IMQ BASE 7C0000h PI 7C4000h - cpqfcTS: SEST c0e40000(virt): Wrote base E40000h @ c887e740 -cpqfcTS: New FC port 0000E8h WWN: 500507650642499D SCSI Chan/Trgt 0/0 -cpqfcTS: New FC port 0000EFh WWN: 50000E100000D5A6 SCSI Chan/Trgt 0/1 -cpqfcTS: New FC port 0000E4h WWN: 21000020370097BB SCSI Chan/Trgt 0/2 -cpqfcTS: New FC port 0000E2h WWN: 2100002037009946 SCSI Chan/Trgt 0/3 -cpqfcTS: New FC port 0000E1h WWN: 21000020370098FE SCSI Chan/Trgt 0/4 -cpqfcTS: New FC port 0000E0h WWN: 21000020370097B2 SCSI Chan/Trgt 0/5 -cpqfcTS: New FC port 0000DCh WWN: 2100002037006CC1 SCSI Chan/Trgt 0/6 -cpqfcTS: New FC port 0000DAh WWN: 21000020370059F6 SCSI Chan/Trgt 0/7 -cpqfcTS: New FC port 00000Fh WWN: 500805F1FADB0E20 SCSI Chan/Trgt 0/8 -cpqfcTS: New FC port 000008h WWN: 500805F1FADB0EBA SCSI Chan/Trgt 0/9 -cpqfcTS: New FC port 000004h WWN: 500805F1FADB1EB9 SCSI Chan/Trgt 0/10 -cpqfcTS: New FC port 000002h WWN: 500805F1FADB1ADE SCSI Chan/Trgt 0/11 -cpqfcTS: New FC port 000001h WWN: 500805F1FADBA2CA SCSI Chan/Trgt 0/12 -scsi4 : Compaq FibreChannel HBA Tachyon TS HPFC-5166A/1.2: WWN 500508B200193F50 - on PCI bus 0 device 0xa0fc irq 5 IObaseL 0x3400, MEMBASE 0xc6ef8600 -PCI bus width 32 bits, bus speed 33 MHz -FCP-SCSI Driver v1.3.0 -GBIC detected: Short-wave. LPSM 0h Monitor -scsi : 5 hosts. - Vendor: IBM Model: DDYF-T18350R Rev: F60K - Type: Direct-Access ANSI SCSI revision: 03 -Detected scsi disk sdb at scsi4, channel 0, id 0, lun 0 - Vendor: HITACHI Model: DK31CJ-72FC Rev: J8A8 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdc at scsi4, channel 0, id 1, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdd at scsi4, channel 0, id 2, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sde at scsi4, channel 0, id 3, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdf at scsi4, channel 0, id 4, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdg at scsi4, channel 0, id 5, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdh at scsi4, channel 0, id 6, lun 0 - Vendor: SEAGATE Model: ST39102FC Rev: 0006 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdi at scsi4, channel 0, id 7, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.48 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdj at scsi4, channel 0, id 8, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.48 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdk at scsi4, channel 0, id 8, lun 1 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.40 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdl at scsi4, channel 0, id 9, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.40 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdm at scsi4, channel 0, id 9, lun 1 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.54 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdn at scsi4, channel 0, id 10, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.54 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdo at scsi4, channel 0, id 11, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.54 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdp at scsi4, channel 0, id 11, lun 1 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.54 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdq at scsi4, channel 0, id 12, lun 0 - Vendor: COMPAQ Model: LOGICAL VOLUME Rev: 2.54 - Type: Direct-Access ANSI SCSI revision: 02 -Detected scsi disk sdr at scsi4, channel 0, id 12, lun 1 -resize_dma_pool: unknown device type 12 -resize_dma_pool: unknown device type 12 -SCSI device sdb: hdwr sector= 512 bytes. Sectors= 35843670 [17501 MB] [17.5 GB] - sdb: sdb1 -SCSI device sdc: hdwr sector= 512 bytes. Sectors= 144410880 [70513 MB] [70.5 GB] - sdc: sdc1 -SCSI device sdd: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sdd: sdd1 -SCSI device sde: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sde: sde1 -SCSI device sdf: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sdf: sdf1 -SCSI device sdg: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sdg: sdg1 -SCSI device sdh: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sdh: sdh1 -SCSI device sdi: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB] - sdi: sdi1 -SCSI device sdj: hdwr sector= 512 bytes. Sectors= 2056160 [1003 MB] [1.0 GB] - sdj: sdj1 -SCSI device sdk: hdwr sector= 512 bytes. Sectors= 2052736 [1002 MB] [1.0 GB] - sdk: sdk1 -SCSI device sdl: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB] - sdl: sdl1 -SCSI device sdm: hdwr sector= 512 bytes. Sectors= 8380320 [4091 MB] [4.1 GB] - sdm: sdm1 -SCSI device sdn: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB] - sdn: sdn1 -SCSI device sdo: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB] - sdo: sdo1 -SCSI device sdp: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB] - sdp: sdp1 -SCSI device sdq: hdwr sector= 512 bytes. Sectors= 2056160 [1003 MB] [1.0 GB] - sdq: sdq1 -SCSI device sdr: hdwr sector= 512 bytes. Sectors= 2052736 [1002 MB] [1.0 GB] - sdr: sdr1 - -************************* - -If a GBIC of type Short-wave, Long-wave, or Copper is detected, it will -print out; otherwise, "none" is displayed. If the cabling is correct -and a loop circuit is completed, you should see "Monitor"; otherwise, -"LoopFail" (on open circuit) or some LPSM number/state with bit 3 set. - - -ERRATA: -1. Normally, Linux Scsi queries FC devices with INQUIRY strings. All LUNs -found according to INQUIRY should get READ commands at sector 0 to find -partition table, etc. Older kernels only query the first 4 devices. Some -Linux kernels only look for one LUN per target (i.e. FC device). - -2. Physically removing a device, or a malfunctioning system which hides a -device, leads to a 30-second timeout and subsequent _abort call. -In some process contexts, this will hang the kernel (crashing the system). -Single bit errors in frames and virtually all hot plugging events are -gracefully handled with internal driver timer and Abort processing. - -3. Some SCSI drives with error conditions will not handle the 7 second timeout -in this software driver, leading to infinite retries on timed out SCSI commands. -The 7 secs balances the need to quickly recover from lost frames (esp. on sequence -initiatives) and time needed by older/slower/error-state drives in responding. -This can be easily changed in "Exchanges[].timeOut". - -4. Due to the nature of FC soft addressing, there is no assurance that the -same LUNs (drives) will have the same path (e.g. /dev/sdb1) from one boot to -next. Dynamic soft address changes (i.e. 24-bit FC port_id) are -supported during run time (e.g. due to hot plug event) by the use of WWN to -SCSI Nexus (channel/target/LUN) mapping. - -5. Compaq RA4x00 firmware version 2.54 and later supports SSP (Selective -Storage Presentation), which maps LUNs to a WWN. If RA4x00 firmware prior -2.54 (e.g. older controller) is used, or the FC HBA is replaced (another WWN -is used), logical volumes on the RA4x00 will no longer be visible. - - -Send questions/comments to: -Amy Vanzant-Hodge (fibrechannel@compaq.com) - diff --git a/Documentation/scsi/hptiop.txt b/Documentation/scsi/hptiop.txt new file mode 100644 index 0000000..d28a312 --- /dev/null +++ b/Documentation/scsi/hptiop.txt @@ -0,0 +1,92 @@ +HIGHPOINT ROCKETRAID 3xxx RAID DRIVER (hptiop) + +Controller Register Map +------------------------- + +The controller IOP is accessed via PCI BAR0. + + BAR0 offset Register + 0x10 Inbound Message Register 0 + 0x14 Inbound Message Register 1 + 0x18 Outbound Message Register 0 + 0x1C Outbound Message Register 1 + 0x20 Inbound Doorbell Register + 0x24 Inbound Interrupt Status Register + 0x28 Inbound Interrupt Mask Register + 0x30 Outbound Interrupt Status Register + 0x34 Outbound Interrupt Mask Register + 0x40 Inbound Queue Port + 0x44 Outbound Queue Port + + +I/O Request Workflow +---------------------- + +All queued requests are handled via inbound/outbound queue port. +A request packet can be allocated in either IOP or host memory. + +To send a request to the controller: + + - Get a free request packet by reading the inbound queue port or + allocate a free request in host DMA coherent memory. + + The value returned from the inbound queue port is an offset + relative to the IOP BAR0. + + Requests allocated in host memory must be aligned on 32-bytes boundary. + + - Fill the packet. + + - Post the packet to IOP by writing it to inbound queue. For requests + allocated in IOP memory, write the offset to inbound queue port. For + requests allocated in host memory, write (0x80000000|(bus_addr>>5)) + to the inbound queue port. + + - The IOP process the request. When the request is completed, it + will be put into outbound queue. An outbound interrupt will be + generated. + + For requests allocated in IOP memory, the request offset is posted to + outbound queue. + + For requests allocated in host memory, (0x80000000|(bus_addr>>5)) + is posted to the outbound queue. If IOP_REQUEST_FLAG_OUTPUT_CONTEXT + flag is set in the request, the low 32-bit context value will be + posted instead. + + - The host read the outbound queue and complete the request. + + For requests allocated in IOP memory, the host driver free the request + by writing it to the outbound queue. + +Non-queued requests (reset/flush etc) can be sent via inbound message +register 0. An outbound message with the same value indicates the completion +of an inbound message. + + +User-level Interface +--------------------- + +The driver exposes following sysfs attributes: + + NAME R/W Description + driver-version R driver version string + firmware-version R firmware version string + +The driver registers char device "hptiop" to communicate with HighPoint RAID +management software. Its ioctl routine acts as a general binary interface +between the IOP firmware and HighPoint RAID management software. New management +functions can be implemented in application/firmware without modification +in driver code. + + +----------------------------------------------------------------------------- +Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + linux@highpoint-tech.com + http://www.highpoint-tech.com diff --git a/Documentation/scsi/ppa.txt b/Documentation/scsi/ppa.txt index 0dac88d..5d9223b 100644 --- a/Documentation/scsi/ppa.txt +++ b/Documentation/scsi/ppa.txt @@ -12,5 +12,3 @@ http://www.torque.net/parport/ Email list for Linux Parport linux-parport@torque.net -Email for problems with ZIP or ZIP Plus drivers -campbell@torque.net diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 0ee2c7d..87d76a5 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -366,7 +366,9 @@ Prior to version 0.9.0rc4 options had a Module for C-Media CMI8338 and 8738 PCI sound cards. - mpu_port - 0x300,0x310,0x320,0x330, 0 = disable (default) + mpu_port - 0x300,0x310,0x320,0x330 = legacy port, + 1 = integrated PCI port, + 0 = disable (default) fm_port - 0x388 (default), 0 = disable (default) soft_ac3 - Software-conversion of raw SPDIF packets (model 033 only) (default = 1) @@ -468,7 +470,7 @@ Prior to version 0.9.0rc4 options had a Module for multifunction CS5535 companion PCI device - This module supports multiple cards. + The power-management is supported. Module snd-dt019x ----------------- @@ -707,8 +709,10 @@ Prior to version 0.9.0rc4 options had a Module snd-hda-intel -------------------- - Module for Intel HD Audio (ICH6, ICH6M, ICH7), ATI SB450, - VIA VT8251/VT8237A + Module for Intel HD Audio (ICH6, ICH6M, ESB2, ICH7, ICH8), + ATI SB450, SB600, RS600, + VIA VT8251/VT8237A, + SIS966, ULI M5461 model - force the model name position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) @@ -778,6 +782,7 @@ Prior to version 0.9.0rc4 options had a AD1981 basic 3-jack (default) hp HP nx6320 + thinkpad Lenovo Thinkpad T60/X60/Z60 AD1986A 6stack 6-jack, separate surrounds (default) @@ -1633,9 +1638,7 @@ Prior to version 0.9.0rc4 options had a About capture IBL, see the description of snd-vx222 module. - Note: the driver is build only when CONFIG_ISA is set. - - Note2: snd-vxp440 driver is merged to snd-vxpocket driver since + Note: snd-vxp440 driver is merged to snd-vxpocket driver since ALSA 1.0.10. The power-management is supported. @@ -1662,8 +1665,6 @@ Prior to version 0.9.0rc4 options had a Module for Sound Core PDAudioCF sound card. - Note: the driver is build only when CONFIG_ISA is set. - The power-management is supported. diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 1faf763..635cbb9 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -4215,7 +4215,7 @@ #endif @@ -4242,15 +4242,36 @@ #endif + The 5th argument is bitflags for additional information. When the i/o port address above is a part of the PCI i/o region, the MPU401 i/o port might have been already allocated - (reserved) by the driver itself. In such a case, pass non-zero - to the 5th argument - (integrated). Otherwise, pass 0 to it, + (reserved) by the driver itself. In such a case, pass a bit flag + MPU401_INFO_INTEGRATED, and the mpu401-uart layer will allocate the i/o ports by itself. + + When the controller supports only the input or output MIDI stream, + pass MPU401_INFO_INPUT or + MPU401_INFO_OUTPUT bitflag, respectively. + Then the rawmidi instance is created as a single stream. + + + + MPU401_INFO_MMIO bitflag is used to change + the access method to MMIO (via readb and writeb) instead of + iob and outb. In this case, you have to pass the iomapped address + to snd_mpu401_uart_new(). + + + + When MPU401_INFO_TX_IRQ is set, the output + stream isn't checked in the default interrupt handler. The driver + needs to call snd_mpu401_uart_interrupt_tx() + by itself to start processing the output stream in irq handler. + + Usually, the port address corresponds to the command port and port + 1 corresponds to the data port. If not, you may change @@ -5333,7 +5354,7 @@ #endif @@ -5394,7 +5415,6 @@ #endif c.text.write_size = 256; entry->c.text.write = my_proc_write; ]]> @@ -5402,22 +5422,6 @@ #endif - The buffer size for read is set to 1024 implicitly by - snd_info_set_text_ops(). It should suffice - in most cases (the size will be aligned to - PAGE_SIZE anyway), but if you need to handle - very large text files, you can set it explicitly, too. - - - -c.text.read_size = 65536; -]]> - - - - - For the write callback, you can use snd_info_get_line() to get a text line, and snd_info_get_str() to retrieve a string from @@ -5562,7 +5566,7 @@ #endif power status. Call snd_pcm_suspend_all() to suspend the running PCM streams. If AC97 codecs are used, call - snd_ac97_resume() for each codec. + snd_ac97_suspend() for each codec. Save the register values if necessary. Stop the hardware if necessary. Disable the PCI device by calling diff --git a/Documentation/sparc/sbus_drivers.txt b/Documentation/sparc/sbus_drivers.txt index 876195d..4b93516 100644 --- a/Documentation/sparc/sbus_drivers.txt +++ b/Documentation/sparc/sbus_drivers.txt @@ -25,42 +25,84 @@ the bits necessary to run your device. used members of this structure, and their typical usage, will be detailed below. - Here is how probing is performed by an SBUS driver -under Linux: + Here is a piece of skeleton code for perofming a device +probe in an SBUS driverunder Linux: - static void init_one_mydevice(struct sbus_dev *sdev) + static int __devinit mydevice_probe_one(struct sbus_dev *sdev) { + struct mysdevice *mp = kzalloc(sizeof(*mp), GFP_KERNEL); + + if (!mp) + return -ENODEV; + + ... + dev_set_drvdata(&sdev->ofdev.dev, mp); + return 0; ... } - static int mydevice_match(struct sbus_dev *sdev) + static int __devinit mydevice_probe(struct of_device *dev, + const struct of_device_id *match) { - if (some_criteria(sdev)) - return 1; - return 0; + struct sbus_dev *sdev = to_sbus_device(&dev->dev); + + return mydevice_probe_one(sdev); } - static void mydevice_probe(void) + static int __devexit mydevice_remove(struct of_device *dev) { - struct sbus_bus *sbus; - struct sbus_dev *sdev; + struct sbus_dev *sdev = to_sbus_device(&dev->dev); + struct mydevice *mp = dev_get_drvdata(&dev->dev); - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if (mydevice_match(sdev)) - init_one_mydevice(sdev); - } - } + return mydevice_remove_one(sdev, mp); } - All this does is walk through all SBUS devices in the -system, checks each to see if it is of the type which -your driver is written for, and if so it calls the init -routine to attach the device and prepare to drive it. + static struct of_device_id mydevice_match[] = { + { + .name = "mydevice", + }, + {}, + }; + + MODULE_DEVICE_TABLE(of, mydevice_match); - "init_one_mydevice" might do things like allocate software -state structures, map in I/O registers, place the hardware -into an initialized state, etc. + static struct of_platform_driver mydevice_driver = { + .name = "mydevice", + .match_table = mydevice_match, + .probe = mydevice_probe, + .remove = __devexit_p(mydevice_remove), + }; + + static int __init mydevice_init(void) + { + return of_register_driver(&mydevice_driver, &sbus_bus_type); + } + + static void __exit mydevice_exit(void) + { + of_unregister_driver(&mydevice_driver); + } + + module_init(mydevice_init); + module_exit(mydevice_exit); + + The mydevice_match table is a series of entries which +describes what SBUS devices your driver is meant for. In the +simplest case you specify a string for the 'name' field. Every +SBUS device with a 'name' property matching your string will +be passed one-by-one to your .probe method. + + You should store away your device private state structure +pointer in the drvdata area so that you can retrieve it later on +in your .remove method. + + Any memory allocated, registers mapped, IRQs registered, +etc. must be undone by your .remove method so that all resources +of your device are relased by the time it returns. + + You should _NOT_ use the for_each_sbus(), for_each_sbusdev(), +and for_all_sbusdev() interfaces. They are deprecated, will be +removed, and no new driver should reference them ever. Mapping and Accessing I/O Registers @@ -263,10 +305,3 @@ discussed above and plus it handles both Lance driver abuses consistent mappings for data transfer. It is a nifty trick which we do not particularly recommend... Just check it out and know that it's legal. - - Bad examples, do NOT use - - drivers/video/cgsix.c - This one uses result of sbus_ioremap as if it is an address. -This does NOT work on sparc64 and therefore is broken. We will -convert it at a later date. diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt index 3f1c546..5a311c3 100644 --- a/Documentation/sparse.txt +++ b/Documentation/sparse.txt @@ -1,5 +1,6 @@ Copyright 2004 Linus Torvalds Copyright 2004 Pavel Machek +Copyright 2006 Bob Copeland Using sparse for typechecking ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -41,15 +42,8 @@ sure that bitwise types don't get mixed vs cpu-endian vs whatever), and there the constant "0" really _is_ special. -Use - - make C=[12] CF=-Wbitwise - -or you don't get any checking at all. - - -Where to get sparse -~~~~~~~~~~~~~~~~~~~ +Getting sparse +~~~~~~~~~~~~~~ With git, you can just get it from @@ -57,7 +51,7 @@ With git, you can just get it from and DaveJ has tar-balls at - http://www.codemonkey.org.uk/projects/git-snapshots/sparse/ + http://www.codemonkey.org.uk/projects/git-snapshots/sparse/ Once you have it, just do @@ -65,8 +59,20 @@ Once you have it, just do make make install -as your regular user, and it will install sparse in your ~/bin directory. -After that, doing a kernel make with "make C=1" will run sparse on all the -C files that get recompiled, or with "make C=2" will run sparse on the -files whether they need to be recompiled or not (ie the latter is fast way -to check the whole tree if you have already built it). +as a regular user, and it will install sparse in your ~/bin directory. + +Using sparse +~~~~~~~~~~~~ + +Do a kernel make with "make C=1" to run sparse on all the C files that get +recompiled, or use "make C=2" to run sparse on the files whether they need to +be recompiled or not. The latter is a fast way to check the whole tree if you +have already built it. + +The optional make variable CF can be used to pass arguments to sparse. The +build system passes -Wbitwise to sparse automatically. To perform endianness +checks, you may define __CHECK_ENDIAN__: + + make C=2 CF="-D__CHECK_ENDIAN__" + +These checks are disabled by default as they generate a host of warnings. diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index a46c10f..2dc246a 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -29,6 +29,7 @@ Currently, these files are in /proc/sys/ - drop-caches - zone_reclaim_mode - zone_reclaim_interval +- panic_on_oom ============================================================== @@ -178,3 +179,15 @@ Time is set in seconds and set by defaul Reduce the interval if undesired off node allocations occur. However, too frequent scans will have a negative impact onoff node allocation performance. +============================================================= + +panic_on_oom + +This enables or disables panic on out-of-memory feature. If this is set to 1, +the kernel panics when out-of-memory happens. If this is set to 0, the kernel +will kill some rogue process, called oom_killer. Usually, oom_killer can kill +rogue processes and system will survive. If you want to panic the system +rather than killing rogue processes, set this to 1. + +The default value is 0. + diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index ad0bedf..e0188a2 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -115,8 +115,9 @@ trojan program is running at console and when you would try to login. It will kill all programs on given console and thus letting you make sure that the login prompt you see is actually the one from init, not some trojan program. -IMPORTANT:In its true form it is not a true SAK like the one in :IMPORTANT -IMPORTANT:c2 compliant systems, and it should be mistook as such. :IMPORTANT +IMPORTANT: In its true form it is not a true SAK like the one in a :IMPORTANT +IMPORTANT: c2 compliant system, and it should not be mistaken as :IMPORTANT +IMPORTANT: such. :IMPORTANT It seems other find it useful as (System Attention Key) which is useful when you want to exit a program that will not let you switch consoles. (For example, X or a svgalib program.) diff --git a/Documentation/tty.txt b/Documentation/tty.txt index 8ff7bc2..dab5660 100644 --- a/Documentation/tty.txt +++ b/Documentation/tty.txt @@ -80,13 +80,6 @@ receive_buf() - Hand buffers of bytes fr for processing. Semantics currently rather mysterious 8( -receive_room() - Can be called by the driver layer at any time when - the ldisc is opened. The ldisc must be able to - handle the reported amount of data at that instant. - Synchronization between active receive_buf and - receive_room calls is down to the driver not the - ldisc. Must not sleep. - write_wakeup() - May be called at any point between open and close. The TTY_DO_WRITE_WAKEUP flag indicates if a call is needed but always races versus calls. Thus the diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt index 63cb7ed..e65ec82 100644 --- a/Documentation/usb/usbmon.txt +++ b/Documentation/usb/usbmon.txt @@ -29,14 +29,13 @@ if usbmon is built into the kernel. # mount -t debugfs none_debugs /sys/kernel/debug # modprobe usbmon +# Verify that bus sockets are present. -[root@lembas zaitcev]# ls /sys/kernel/debug/usbmon +# ls /sys/kernel/debug/usbmon 1s 1t 2s 2t 3s 3t 4s 4t -[root@lembas zaitcev]# - -# ls /sys/kernel +# 2. Find which bus connects to the desired device @@ -76,7 +75,7 @@ that the file size is not excessive for * Raw text data format -The '0t' type data consists of a stream of events, such as URB submission, +The '1t' type data consists of a stream of events, such as URB submission, URB callback, submission error. Every event is a text line, which consists of whitespace separated words. The number of position of words may depend on the event type, but there is a set of words, common for all types. @@ -97,20 +96,25 @@ Here is the list of words, from left to Zi Zo Isochronous input and output Ii Io Interrupt input and output Bi Bo Bulk input and output - Device address and Endpoint number are decimal numbers with leading zeroes - or 3 and 2 positions, correspondingly. -- URB Status. This field makes no sense for submissions, but is present - to help scripts with parsing. In error case, it contains the error code. - In case of a setup packet, it contains a Setup Tag. If scripts read a number - in this field, they proceed to read Data Length. Otherwise, they read - the setup packet before reading the Data Length. + Device address and Endpoint number are 3-digit and 2-digit (respectively) + decimal numbers, with leading zeroes. +- URB Status. In most cases, this field contains a number, sometimes negative, + which represents a "status" field of the URB. This field makes no sense for + submissions, but is present anyway to help scripts with parsing. When an + error occurs, the field contains the error code. In case of a submission of + a Control packet, this field contains a Setup Tag instead of an error code. + It is easy to tell whether the Setup Tag is present because it is never a + number. Thus if scripts find a number in this field, they proceed to read + Data Length. If they find something else, like a letter, they read the setup + packet before reading the Data Length. - Setup packet, if present, consists of 5 words: one of each for bmRequestType, bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0. These words are safe to decode if Setup Tag was 's'. Otherwise, the setup packet was present, but not captured, and the fields contain filler. -- Data Length. This is the actual length in the URB. +- Data Length. For submissions, this is the requested length. For callbacks, + this is the actual length. - Data tag. The usbmon may not always capture data, even if length is nonzero. - Only if tag is '=', the data words are present. + The data words are present only if this tag is '='. - Data words follow, in big endian hexadecimal format. Notice that they are not machine words, but really just a byte stream split into words to make it easier to read. Thus, the last word may contain from one to four bytes. diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index b72706c..4efa464 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -87,7 +87,7 @@ 86 -> Osprey 101/151 w/ svid 87 -> Osprey 200/201/250/251 88 -> Osprey 200/250 [0070:ff01] - 89 -> Osprey 210/220 + 89 -> Osprey 210/220/230 90 -> Osprey 500 [0070:ff02] 91 -> Osprey 540 [0070:ff04] 92 -> Osprey 2000 [0070:ff03] @@ -111,7 +111,7 @@ 110 -> IVC-100 [ff00:a132] 111 -> IVC-120G [ff00:a182,ff01:a182,ff02:a182,ff03:a182,ff04:a182,ff05:a182,ff06:a182,ff07:a182,ff08:a182,ff09:a182,ff0a:a182,ff0b:a182,ff0c:a182,ff0d:a182,ff0e:a182,ff0f:a182] 112 -> pcHDTV HD-2000 TV [7063:2000] -113 -> Twinhan DST + clones [11bd:0026,1822:0001,270f:fc00] +113 -> Twinhan DST + clones [11bd:0026,1822:0001,270f:fc00,1822:0026] 114 -> Winfast VC100 [107d:6607] 115 -> Teppro TEV-560/InterVision IV-560 116 -> SIMUS GVC1100 [aa6a:82b2] diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 3b39a91..6cb63dd 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -15,7 +15,7 @@ 14 -> KWorld/VStream XPert DVB-T [17de:08a6] 15 -> DViCO FusionHDTV DVB-T1 [18ac:db00] 16 -> KWorld LTV883RF - 17 -> DViCO FusionHDTV 3 Gold-Q [18ac:d810] + 17 -> DViCO FusionHDTV 3 Gold-Q [18ac:d810,18ac:d800] 18 -> Hauppauge Nova-T DVB-T [0070:9002,0070:9001] 19 -> Conexant DVB-T reference design [14f1:0187] 20 -> Provideo PV259 [1540:2580] @@ -40,8 +40,13 @@ 39 -> KWorld DVB-S 100 [17de:08b2] 40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid [0070:9400,0070:9402] 41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile) [0070:9800,0070:9802] - 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025] + 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025,1822:0019] 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1] 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54] 45 -> KWorld HardwareMpegTV XPert [17de:0840] 46 -> DViCO FusionHDTV DVB-T Hybrid [18ac:db40,18ac:db44] + 47 -> pcHDTV HD5500 HDTV [7063:5500] + 48 -> Kworld MCE 200 Deluxe [17de:0841] + 49 -> PixelView PlayTV P7000 [1554:4813] + 50 -> NPG Tech Real TV FM Top 10 [14f1:0842] + 51 -> WinFast DTV2000 H [107d:665e] diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index bca5090..9068b66 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -93,3 +93,4 @@ 92 -> AVerMedia A169 B1 [1461:6360] 93 -> Medion 7134 Bridge #2 [16be:0005] 94 -> LifeView FlyDVB-T Hybrid Cardbus [5168:3306,5168:3502] + 95 -> LifeView FlyVIDEO3000 (NTSC) [5169:0138] diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 1bcdac6..44134f0 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -62,7 +62,7 @@ tuner=60 - Thomson DTT 761X (ATSC/NTSC) tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF tuner=62 - Philips TEA5767HN FM Radio tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner -tuner=64 - LG TDVS-H062F/TUA6034 +tuner=64 - LG TDVS-H06xF tuner=65 - Ymec TVF66T5-B/DFF tuner=66 - LG TALN series tuner=67 - Philips TD1316 Hybrid Tuner @@ -71,3 +71,4 @@ tuner=69 - Tena TNF 5335 and similar mod tuner=70 - Samsung TCPN 2121P30A tuner=71 - Xceive xc3028 tuner=72 - Thomson FE6600 +tuner=73 - Samsung TCPG 6121P30A diff --git a/Documentation/video4linux/CQcam.txt b/Documentation/video4linux/CQcam.txt index 464e4ce..ade8651 100644 --- a/Documentation/video4linux/CQcam.txt +++ b/Documentation/video4linux/CQcam.txt @@ -185,207 +185,10 @@ this work is documented at the video4lin 9.0 --- A sample program using v4lgrabber, -This program is a simple image grabber that will copy a frame from the +v4lgrab is a simple image grabber that will copy a frame from the first video device, /dev/video0 to standard output in portable pixmap -format (.ppm) Using this like: 'v4lgrab | convert - c-qcam.jpg' -produced this picture of me at - http://mug.sys.virginia.edu/~drf5n/extras/c-qcam.jpg - --------------------- 8< ---------------- 8< ----------------------------- - -/* Simple Video4Linux image grabber. */ -/* - * Video4Linux Driver Test/Example Framegrabbing Program - * - * Compile with: - * gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab - * Use as: - * v4lgrab >image.ppm - * - * Copyright (C) 1998-05-03, Phil Blundell - * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c - * with minor modifications (Dave Forrest, drf5n@virginia.edu). - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define FILE "/dev/video0" - -/* Stole this from tvset.c */ - -#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \ -{ \ - switch (format) \ - { \ - case VIDEO_PALETTE_GREY: \ - switch (depth) \ - { \ - case 4: \ - case 6: \ - case 8: \ - (r) = (g) = (b) = (*buf++ << 8);\ - break; \ - \ - case 16: \ - (r) = (g) = (b) = \ - *((unsigned short *) buf); \ - buf += 2; \ - break; \ - } \ - break; \ - \ - \ - case VIDEO_PALETTE_RGB565: \ - { \ - unsigned short tmp = *(unsigned short *)buf; \ - (r) = tmp&0xF800; \ - (g) = (tmp<<5)&0xFC00; \ - (b) = (tmp<<11)&0xF800; \ - buf += 2; \ - } \ - break; \ - \ - case VIDEO_PALETTE_RGB555: \ - (r) = (buf[0]&0xF8)<<8; \ - (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \ - (b) = ((buf[1] << 2 ) & 0xF8)<<8; \ - buf += 2; \ - break; \ - \ - case VIDEO_PALETTE_RGB24: \ - (r) = buf[0] << 8; (g) = buf[1] << 8; \ - (b) = buf[2] << 8; \ - buf += 3; \ - break; \ - \ - default: \ - fprintf(stderr, \ - "Format %d not yet supported\n", \ - format); \ - } \ -} - -int get_brightness_adj(unsigned char *image, long size, int *brightness) { - long i, tot = 0; - for (i=0;i= 126 && (tot/(size*3)) <= 130); -} - -int main(int argc, char ** argv) -{ - int fd = open(FILE, O_RDONLY), f; - struct video_capability cap; - struct video_window win; - struct video_picture vpic; - - unsigned char *buffer, *src; - int bpp = 24, r, g, b; - unsigned int i, src_depth; - - if (fd < 0) { - perror(FILE); - exit(1); - } - - if (ioctl(fd, VIDIOCGCAP, &cap) < 0) { - perror("VIDIOGCAP"); - fprintf(stderr, "(" FILE " not a video4linux device?)\n"); - close(fd); - exit(1); - } - - if (ioctl(fd, VIDIOCGWIN, &win) < 0) { - perror("VIDIOCGWIN"); - close(fd); - exit(1); - } - - if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) { - perror("VIDIOCGPICT"); - close(fd); - exit(1); - } - - if (cap.type & VID_TYPE_MONOCHROME) { - vpic.depth=8; - vpic.palette=VIDEO_PALETTE_GREY; /* 8bit grey */ - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - vpic.depth=6; - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - vpic.depth=4; - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - fprintf(stderr, "Unable to find a supported capture format.\n"); - close(fd); - exit(1); - } - } - } - } else { - vpic.depth=24; - vpic.palette=VIDEO_PALETTE_RGB24; - - if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { - vpic.palette=VIDEO_PALETTE_RGB565; - vpic.depth=16; - - if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { - vpic.palette=VIDEO_PALETTE_RGB555; - vpic.depth=15; - - if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { - fprintf(stderr, "Unable to find a supported capture format.\n"); - return -1; - } - } - } - } - - buffer = malloc(win.width * win.height * bpp); - if (!buffer) { - fprintf(stderr, "Out of memory.\n"); - exit(1); - } - - do { - int newbright; - read(fd, buffer, win.width * win.height * bpp); - f = get_brightness_adj(buffer, win.width * win.height, &newbright); - if (f) { - vpic.brightness += (newbright << 8); - if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { - perror("VIDIOSPICT"); - break; - } - } - } while (f); - - fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height); - - src = buffer; - - for (i = 0; i < win.width * win.height; i++) { - READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b); - fputc(r>>8, stdout); - fputc(g>>8, stdout); - fputc(b>>8, stdout); - } - - close(fd); - return 0; -} --------------------- 8< ---------------- 8< ----------------------------- +format (.ppm) To produce .jpg output, you can use it like this: +'v4lgrab | convert - c-qcam.jpg' 10.0 --- Other Information diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran index be9f21b..040a2c8 100644 --- a/Documentation/video4linux/Zoran +++ b/Documentation/video4linux/Zoran @@ -33,6 +33,21 @@ Inputs/outputs: Composite and S-video Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) Card number: 7 +AverMedia 6 Eyes AVS6EYES: +* Zoran zr36067 PCI controller +* Zoran zr36060 MJPEG codec +* Samsung ks0127 TV decoder +* Conexant bt866 TV encoder +Drivers to use: videodev, i2c-core, i2c-algo-bit, + videocodec, ks0127, bt866, zr36060, zr36067 +Inputs/outputs: Six physical inputs. 1-6 are composite, + 1-2, 3-4, 5-6 doubles as S-video, + 1-3 triples as component. + One composite output. +Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) +Card number: 8 +Not autodetected, card=8 is necessary. + Linux Media Labs LML33: * Zoran zr36067 PCI controller * Zoran zr36060 MJPEG codec @@ -192,6 +207,10 @@ Micronas vpx3220a TV decoder was introduced in 1996, is used in the DC30 and DC30+ and can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC 44, PAL 60, SECAM,NTSC Comb +Samsung ks0127 TV decoder +is used in the AVS6EYES card and +can handle: NTSC-M/N/44, PAL-M/N/B/G/H/I/D/K/L and SECAM + =========================== 1.2 What the TV encoder can do an what not @@ -221,6 +240,10 @@ ITT mse3000 TV encoder was introduced in 1991, is used in the DC10 old can generate: PAL , NTSC , SECAM +Conexant bt866 TV encoder +is used in AVS6EYES, and +can generate: NTSC/PAL, PAL­M, PAL­N + The adv717x, should be able to produce PAL N. But you find nothing PAL N specific in the registers. Seem that you have to reuse a other standard to generate PAL N, maybe it would work if you use the PAL M settings. diff --git a/Documentation/video4linux/bttv/CONTRIBUTORS b/Documentation/video4linux/bttv/CONTRIBUTORS index aef49db..8aad6dd 100644 --- a/Documentation/video4linux/bttv/CONTRIBUTORS +++ b/Documentation/video4linux/bttv/CONTRIBUTORS @@ -1,4 +1,4 @@ -Contributors to bttv: +Contributors to bttv: Michael Chu AverMedia fix and more flexible card recognition @@ -8,8 +8,8 @@ Alan Cox Chris Kleitsch Hardware I2C - -Gerd Knorr + +Gerd Knorr Radio card (ITT sound processor) bigfoot @@ -18,7 +18,7 @@ Ragnar Hojland Espinosa 8mbps +Param[0] + 0=off, 1=on diff --git a/Documentation/video4linux/cx2341x/fw-dma.txt b/Documentation/video4linux/cx2341x/fw-dma.txt new file mode 100644 index 0000000..8123e26 --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-dma.txt @@ -0,0 +1,94 @@ +This page describes the structures and procedures used by the cx2341x DMA +engine. + +Introduction +============ + +The cx2341x PCI interface is busmaster capable. This means it has a DMA +engine to efficiently transfer large volumes of data between the card and main +memory without requiring help from a CPU. Like most hardware, it must operate +on contiguous physical memory. This is difficult to come by in large quantities +on virtual memory machines. + +Therefore, it also supports a technique called "scatter-gather". The card can +transfer multiple buffers in one operation. Instead of allocating one large +contiguous buffer, the driver can allocate several smaller buffers. + +In practice, I've seen the average transfer to be roughly 80K, but transfers +above 128K were not uncommon, particularly at startup. The 128K figure is +important, because that is the largest block that the kernel can normally +allocate. Even still, 128K blocks are hard to come by, so the driver writer is +urged to choose a smaller block size and learn the scatter-gather technique. + +Mailbox #10 is reserved for DMA transfer information. + +Flow +==== + +This section describes, in general, the order of events when handling DMA +transfers. Detailed information follows this section. + +- The card raises the Encoder interrupt. +- The driver reads the transfer type, offset and size from Mailbox #10. +- The driver constructs the scatter-gather array from enough free dma buffers + to cover the size. +- The driver schedules the DMA transfer via the ScheduleDMAtoHost API call. +- The card raises the DMA Complete interrupt. +- The driver checks the DMA status register for any errors. +- The driver post-processes the newly transferred buffers. + +NOTE! It is possible that the Encoder and DMA Complete interrupts get raised +simultaneously. (End of the last, start of the next, etc.) + +Mailbox #10 +=========== + +The Flags, Command, Return Value and Timeout fields are ignored. + +Name: Mailbox #10 +Results[0]: Type: 0: MPEG. +Results[1]: Offset: The position relative to the card's memory space. +Results[2]: Size: The exact number of bytes to transfer. + +My speculation is that since the StartCapture API has a capture type of "RAW" +available, that the type field will have other values that correspond to YUV +and PCM data. + +Scatter-Gather Array +==================== + +The scatter-gather array is a contiguously allocated block of memory that +tells the card the source and destination of each data-block to transfer. +Card "addresses" are derived from the offset supplied by Mailbox #10. Host +addresses are the physical memory location of the target DMA buffer. + +Each S-G array element is a struct of three 32-bit words. The first word is +the source address, the second is the destination address. Both take up the +entire 32 bits. The lowest 16 bits of the third word is the transfer byte +count. The high-bit of the third word is the "last" flag. The last-flag tells +the card to raise the DMA_DONE interrupt. From hard personal experience, if +you forget to set this bit, the card will still "work" but the stream will +most likely get corrupted. + +The transfer count must be a multiple of 256. Therefore, the driver will need +to track how much data in the target buffer is valid and deal with it +accordingly. + +Array Element: + +- 32-bit Source Address +- 32-bit Destination Address +- 16-bit reserved (high bit is the last flag) +- 16-bit byte count + +DMA Transfer Status +=================== + +Register 0x0004 holds the DMA Transfer Status: + +Bit +4 Scatter-Gather array error +3 DMA write error +2 DMA read error +1 write completed +0 read completed diff --git a/Documentation/video4linux/cx2341x/fw-encoder-api.txt b/Documentation/video4linux/cx2341x/fw-encoder-api.txt new file mode 100644 index 0000000..001c686 --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-encoder-api.txt @@ -0,0 +1,694 @@ +Encoder firmware API description +================================ + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_PING_FW +Enum 128/0x80 +Description + Does nothing. Can be used to check if the firmware is responding. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_START_CAPTURE +Enum 129/0x81 +Description + Commences the capture of video, audio and/or VBI data. All encoding + parameters must be initialized prior to this API call. Captures frames + continuously or until a predefined number of frames have been captured. +Param[0] + Capture stream type: + 0=MPEG + 1=Raw + 2=Raw passthrough + 3=VBI + +Param[1] + Bitmask: + Bit 0 when set, captures YUV + Bit 1 when set, captures PCM audio + Bit 2 when set, captures VBI (same as param[0]=3) + Bit 3 when set, the capture destination is the decoder + (same as param[0]=2) + Bit 4 when set, the capture destination is the host + Note: this parameter is only meaningful for RAW capture type. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_STOP_CAPTURE +Enum 130/0x82 +Description + Ends a capture in progress +Param[0] + 0=stop at end of GOP (generates IRQ) + 1=stop immediate (no IRQ) +Param[1] + Stream type to stop, see param[0] of API 0x81 +Param[2] + Subtype, see param[1] of API 0x81 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_AUDIO_ID +Enum 137/0x89 +Description + Assigns the transport stream ID of the encoded audio stream +Param[0] + Audio Stream ID + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_VIDEO_ID +Enum 139/0x8B +Description + Set video transport stream ID +Param[0] + Video stream ID + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_PCR_ID +Enum 141/0x8D +Description + Assigns the transport stream ID for PCR packets +Param[0] + PCR Stream ID + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_FRAME_RATE +Enum 143/0x8F +Description + Set video frames per second. Change occurs at start of new GOP. +Param[0] + 0=30fps + 1=25fps + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_FRAME_SIZE +Enum 145/0x91 +Description + Select video stream encoding resolution. +Param[0] + Height in lines. Default 480 +Param[1] + Width in pixels. Default 720 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_BIT_RATE +Enum 149/0x95 +Description + Assign average video stream bitrate. Note on the last three params: + Param[3] and [4] seem to be always 0, param [5] doesn't seem to be used. +Param[0] + 0=variable bitrate, 1=constant bitrate +Param[1] + bitrate in bits per second +Param[2] + peak bitrate in bits per second, divided by 400 +Param[3] + Mux bitrate in bits per second, divided by 400. May be 0 (default). +Param[4] + Rate Control VBR Padding +Param[5] + VBV Buffer used by encoder + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_GOP_PROPERTIES +Enum 151/0x97 +Description + Setup the GOP structure +Param[0] + GOP size (maximum is 34) +Param[1] + Number of B frames between the I and P frame, plus 1. + For example: IBBPBBPBBPBB --> GOP size: 12, number of B frames: 2+1 = 3 + Note that GOP size must be a multiple of (B-frames + 1). + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_ASPECT_RATIO +Enum 153/0x99 +Description + Sets the encoding aspect ratio. Changes in the aspect ratio take effect + at the start of the next GOP. +Param[0] + '0000' forbidden + '0001' 1:1 square + '0010' 4:3 + '0011' 16:9 + '0100' 2.21:1 + '0101' reserved + .... + '1111' reserved + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_DNR_FILTER_MODE +Enum 155/0x9B +Description + Assign Dynamic Noise Reduction operating mode +Param[0] + Bit0: Spatial filter, set=auto, clear=manual + Bit1: Temporal filter, set=auto, clear=manual +Param[1] + Median filter: + 0=Disabled + 1=Horizontal + 2=Vertical + 3=Horiz/Vert + 4=Diagonal + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_DNR_FILTER_PROPS +Enum 157/0x9D +Description + These Dynamic Noise Reduction filter values are only meaningful when + the respective filter is set to "manual" (See API 0x9B) +Param[0] + Spatial filter: default 0, range 0:15 +Param[1] + Temporal filter: default 0, range 0:31 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_CORING_LEVELS +Enum 159/0x9F +Description + Assign Dynamic Noise Reduction median filter properties. +Param[0] + Threshold above which the luminance median filter is enabled. + Default: 0, range 0:255 +Param[1] + Threshold below which the luminance median filter is enabled. + Default: 255, range 0:255 +Param[2] + Threshold above which the chrominance median filter is enabled. + Default: 0, range 0:255 +Param[3] + Threshold below which the chrominance median filter is enabled. + Default: 255, range 0:255 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_SPATIAL_FILTER_TYPE +Enum 161/0xA1 +Description + Assign spatial prefilter parameters +Param[0] + Luminance filter + 0=Off + 1=1D Horizontal + 2=1D Vertical + 3=2D H/V Separable (default) + 4=2D Symmetric non-separable +Param[1] + Chrominance filter + 0=Off + 1=1D Horizontal (default) + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_3_2_PULLDOWN +Enum 177/0xB1 +Description + 3:2 pulldown properties +Param[0] + 0=enabled + 1=disabled + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_VBI_LINE +Enum 183/0xB7 +Description + Selects VBI line number. +Param[0] + Bits 0:4 line number + Bit 31 0=top_field, 1=bottom_field + Bits 0:31 all set specifies "all lines" +Param[1] + VBI line information features: 0=disabled, 1=enabled +Param[2] + Slicing: 0=None, 1=Closed Caption + Almost certainly not implemented. Set to 0. +Param[3] + Luminance samples in this line. + Almost certainly not implemented. Set to 0. +Param[4] + Chrominance samples in this line + Almost certainly not implemented. Set to 0. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_STREAM_TYPE +Enum 185/0xB9 +Description + Assign stream type + Note: Transport stream is not working in recent firmwares. + And in older firmwares the timestamps in the TS seem to be + unreliable. +Param[0] + 0=Program stream + 1=Transport stream + 2=MPEG1 stream + 3=PES A/V stream + 5=PES Video stream + 7=PES Audio stream + 10=DVD stream + 11=VCD stream + 12=SVCD stream + 13=DVD_S1 stream + 14=DVD_S2 stream + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_OUTPUT_PORT +Enum 187/0xBB +Description + Assign stream output port. Normally 0 when the data is copied through + the PCI bus (DMA), and 1 when the data is streamed to another chip + (pvrusb and cx88-blackbird). +Param[0] + 0=Memory (default) + 1=Streaming + 2=Serial +Param[1] + Unknown, but leaving this to 0 seems to work best. Indications are that + this might have to do with USB support, although passing anything but 0 + onl breaks things. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_AUDIO_PROPERTIES +Enum 189/0xBD +Description + Set audio stream properties, may be called while encoding is in progress. + Note: all bitfields are consistent with ISO11172 documentation except + bits 2:3 which ISO docs define as: + '11' Layer I + '10' Layer II + '01' Layer III + '00' Undefined + This discrepancy may indicate a possible error in the documentation. + Testing indicated that only Layer II is actually working, and that + the minimum bitrate should be 192 kbps. +Param[0] + Bitmask: + 0:1 '00' 44.1Khz + '01' 48Khz + '10' 32Khz + '11' reserved + + 2:3 '01'=Layer I + '10'=Layer II + + 4:7 Bitrate: + Index | Layer I | Layer II + ------+-------------+------------ + '0000' | free format | free format + '0001' | 32 kbit/s | 32 kbit/s + '0010' | 64 kbit/s | 48 kbit/s + '0011' | 96 kbit/s | 56 kbit/s + '0100' | 128 kbit/s | 64 kbit/s + '0101' | 160 kbit/s | 80 kbit/s + '0110' | 192 kbit/s | 96 kbit/s + '0111' | 224 kbit/s | 112 kbit/s + '1000' | 256 kbit/s | 128 kbit/s + '1001' | 288 kbit/s | 160 kbit/s + '1010' | 320 kbit/s | 192 kbit/s + '1011' | 352 kbit/s | 224 kbit/s + '1100' | 384 kbit/s | 256 kbit/s + '1101' | 416 kbit/s | 320 kbit/s + '1110' | 448 kbit/s | 384 kbit/s + Note: For Layer II, not all combinations of total bitrate + and mode are allowed. See ISO11172-3 3-Annex B, Table 3-B.2 + + 8:9 '00'=Stereo + '01'=JointStereo + '10'=Dual + '11'=Mono + Note: testing seems to indicate that Mono and possibly + JointStereo are not working (default to stereo). + Dual does work, though. + + 10:11 Mode Extension used in joint_stereo mode. + In Layer I and II they indicate which subbands are in + intensity_stereo. All other subbands are coded in stereo. + '00' subbands 4-31 in intensity_stereo, bound==4 + '01' subbands 8-31 in intensity_stereo, bound==8 + '10' subbands 12-31 in intensity_stereo, bound==12 + '11' subbands 16-31 in intensity_stereo, bound==16 + + 12:13 Emphasis: + '00' None + '01' 50/15uS + '10' reserved + '11' CCITT J.17 + + 14 CRC: + '0' off + '1' on + + 15 Copyright: + '0' off + '1' on + + 16 Generation: + '0' copy + '1' original + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_HALT_FW +Enum 195/0xC3 +Description + The firmware is halted and no further API calls are serviced until the + firmware is uploaded again. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_GET_VERSION +Enum 196/0xC4 +Description + Returns the version of the encoder firmware. +Result[0] + Version bitmask: + Bits 0:15 build + Bits 16:23 minor + Bits 24:31 major + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_GOP_CLOSURE +Enum 197/0xC5 +Description + Assigns the GOP open/close property. +Param[0] + 0=Open + 1=Closed + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_GET_SEQ_END +Enum 198/0xC6 +Description + Obtains the sequence end code of the encoder's buffer. When a capture + is started a number of interrupts are still generated, the last of + which will have Result[0] set to 1 and Result[1] will contain the size + of the buffer. +Result[0] + State of the transfer (1 if last buffer) +Result[1] + If Result[0] is 1, this contains the size of the last buffer, undefined + otherwise. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_PGM_INDEX_INFO +Enum 199/0xC7 +Description + Sets the Program Index Information. +Param[0] + Picture Mask: + 0=No index capture + 1=I frames + 3=I,P frames + 7=I,P,B frames +Param[1] + Elements requested (up to 400) +Result[0] + Offset in SDF memory of the table. +Result[1] + Number of allocated elements up to a maximum of Param[1] + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_VBI_CONFIG +Enum 200/0xC8 +Description + Configure VBI settings +Param[0] + Bitmap: + 0 Mode '0' Sliced, '1' Raw + 1:3 Insertion: + '000' insert in extension & user data + '001' insert in private packets + '010' separate stream and user data + '111' separate stream and private data + 8:15 Stream ID (normally 0xBD) +Param[1] + Frames per interrupt (max 8). Only valid in raw mode. +Param[2] + Total raw VBI frames. Only valid in raw mode. +Param[3] + Start codes +Param[4] + Stop codes +Param[5] + Lines per frame +Param[6] + Byte per line +Result[0] + Observed frames per interrupt in raw mode only. Rage 1 to Param[1] +Result[1] + Observed number of frames in raw mode. Range 1 to Param[2] +Result[2] + Memory offset to start or raw VBI data + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_DMA_BLOCK_SIZE +Enum 201/0xC9 +Description + Set DMA transfer block size +Param[0] + DMA transfer block size in bytes or frames. When unit is bytes, + supported block sizes are 2^7, 2^8 and 2^9 bytes. +Param[1] + Unit: 0=bytes, 1=frames + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_GET_PREV_DMA_INFO_MB_10 +Enum 202/0xCA +Description + Returns information on the previous DMA transfer in conjunction with + bit 27 of the interrupt mask. Uses mailbox 10. +Result[0] + Type of stream +Result[1] + Address Offset +Result[2] + Maximum size of transfer + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_GET_PREV_DMA_INFO_MB_9 +Enum 203/0xCB +Description + Returns information on the previous DMA transfer in conjunction with + bit 27 of the interrupt mask. Uses mailbox 9. +Result[0] + Status bits: + Bit 0 set indicates transfer complete + Bit 2 set indicates transfer error + Bit 4 set indicates linked list error +Result[1] + DMA type +Result[2] + Presentation Time Stamp bits 0..31 +Result[3] + Presentation Time Stamp bit 32 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SCHED_DMA_TO_HOST +Enum 204/0xCC +Description + Setup DMA to host operation +Param[0] + Memory address of link list +Param[1] + Length of link list (wtf: what units ???) +Param[2] + DMA type (0=MPEG) + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_INITIALIZE_INPUT +Enum 205/0xCD +Description + Initializes the video input + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_FRAME_DROP_RATE +Enum 208/0xD0 +Description + For each frame captured, skip specified number of frames. +Param[0] + Number of frames to skip + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_PAUSE_ENCODER +Enum 210/0xD2 +Description + During a pause condition, all frames are dropped instead of being encoded. +Param[0] + 0=Pause encoding + 1=Continue encoding + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_REFRESH_INPUT +Enum 211/0xD3 +Description + Refreshes the video input + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_COPYRIGHT +Enum 212/0xD4 +Description + Sets stream copyright property +Param[0] + 0=Stream is not copyrighted + 1=Stream is copyrighted + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_EVENT_NOTIFICATION +Enum 213/0xD5 +Description + Setup firmware to notify the host about a particular event. Host must + unmask the interrupt bit. +Param[0] + Event (0=refresh encoder input) +Param[1] + Notification 0=disabled 1=enabled +Param[2] + Interrupt bit +Param[3] + Mailbox slot, -1 if no mailbox required. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_NUM_VSYNC_LINES +Enum 214/0xD6 +Description + Depending on the analog video decoder used, this assigns the number + of lines for field 1 and 2. +Param[0] + Field 1 number of lines: + 0x00EF for SAA7114 + 0x00F0 for SAA7115 + 0x0105 for Micronas +Param[1] + Field 2 number of lines: + 0x00EF for SAA7114 + 0x00F0 for SAA7115 + 0x0106 for Micronas + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_PLACEHOLDER +Enum 215/0xD7 +Description + Provides a mechanism of inserting custom user data in the MPEG stream. +Param[0] + 0=extension & user data + 1=private packet with stream ID 0xBD +Param[1] + Rate at which to insert data, in units of frames (for private packet) + or GOPs (for ext. & user data) +Param[2] + Number of data DWORDs (below) to insert +Param[3] + Custom data 0 +Param[4] + Custom data 1 +Param[5] + Custom data 2 +Param[6] + Custom data 3 +Param[7] + Custom data 4 +Param[8] + Custom data 5 +Param[9] + Custom data 6 +Param[10] + Custom data 7 +Param[11] + Custom data 8 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_MUTE_VIDEO +Enum 217/0xD9 +Description + Video muting +Param[0] + Bit usage: + 0 '0'=video not muted + '1'=video muted, creates frames with the YUV color defined below + 1:7 Unused + 8:15 V chrominance information + 16:23 U chrominance information + 24:31 Y luminance information + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_MUTE_AUDIO +Enum 218/0xDA +Description + Audio muting +Param[0] + 0=audio not muted + 1=audio muted (produces silent mpeg audio stream) + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_UNKNOWN +Enum 219/0xDB +Description + Unknown API, it's used by Hauppauge though. +Param[0] + 0 This is the value Hauppauge uses, Unknown what it means. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_MISC +Enum 220/0xDC +Description + Miscellaneous actions. Not known for 100% what it does. It's really a + sort of ioctl call. The first parameter is a command number, the second + the value. +Param[0] + Command number: + 1=set initial SCR value when starting encoding. + 2=set quality mode (apparently some test setting). + 3=setup advanced VIM protection handling (supposedly only for the cx23416 + for raw YUV). + Actually it looks like this should be 0 for saa7114/5 based card and 1 + for cx25840 based cards. + 4=generate artificial PTS timestamps + 5=USB flush mode + 6=something to do with the quantization matrix + 7=set navigation pack insertion for DVD + 8=enable scene change detection (seems to be a failure) + 9=set history parameters of the video input module + 10=set input field order of VIM + 11=set quantization matrix + 12=reset audio interface + 13=set audio volume delay + 14=set audio delay + +Param[1] + Command value. diff --git a/Documentation/video4linux/cx2341x/fw-memory.txt b/Documentation/video4linux/cx2341x/fw-memory.txt new file mode 100644 index 0000000..ef0aad3 --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-memory.txt @@ -0,0 +1,141 @@ +This document describes the cx2341x memory map and documents some of the register +space. + +Warning! This information was figured out from searching through the memory and +registers, this information may not be correct and is certainly not complete, and +was not derived from anything more than searching through the memory space with +commands like: + + ivtvctl -O min=0x02000000,max=0x020000ff + +So take this as is, I'm always searching for more stuff, it's a large +register space :-). + +Memory Map +========== + +The cx2341x exposes its entire 64M memory space to the PCI host via the PCI BAR0 +(Base Address Register 0). The addresses here are offsets relative to the +address held in BAR0. + +0x00000000-0x00ffffff Encoder memory space +0x00000000-0x0003ffff Encode.rom + ???-??? MPEG buffer(s) + ???-??? Raw video capture buffer(s) + ???-??? Raw audio capture buffer(s) + ???-??? Display buffers (6 or 9) + +0x01000000-0x01ffffff Decoder memory space +0x01000000-0x0103ffff Decode.rom + ???-??? MPEG buffers(s) +0x0114b000-0x0115afff Audio.rom (deprecated?) + +0x02000000-0x0200ffff Register Space + +Registers +========= + +The registers occupy the 64k space starting at the 0x02000000 offset from BAR0. +All of these registers are 32 bits wide. + +DMA Registers 0x000-0xff: + + 0x00 - Control: + 0=reset/cancel, 1=read, 2=write, 4=stop + 0x04 - DMA status: + 1=read busy, 2=write busy, 4=read error, 8=write error, 16=link list error + 0x08 - pci DMA pointer for read link list + 0x0c - pci DMA pointer for write link list + 0x10 - read/write DMA enable: + 1=read enable, 2=write enable + 0x14 - always 0xffffffff, if set any lower instability occurs, 0x00 crashes + 0x18 - ?? + 0x1c - always 0x20 or 32, smaller values slow down DMA transactions + 0x20 - always value of 0x780a010a + 0x24-0x3c - usually just random values??? + 0x40 - Interrupt status + 0x44 - Write a bit here and shows up in Interrupt status 0x40 + 0x48 - Interrupt Mask + 0x4C - always value of 0xfffdffff, + if changed to 0xffffffff DMA write interrupts break. + 0x50 - always 0xffffffff + 0x54 - always 0xffffffff (0x4c, 0x50, 0x54 seem like interrupt masks, are + 3 processors on chip, Java ones, VPU, SPU, APU, maybe these are the + interrupt masks???). + 0x60-0x7C - random values + 0x80 - first write linked list reg, for Encoder Memory addr + 0x84 - first write linked list reg, for pci memory addr + 0x88 - first write linked list reg, for length of buffer in memory addr + (|0x80000000 or this for last link) + 0x8c-0xcc - rest of write linked list reg, 8 sets of 3 total, DMA goes here + from linked list addr in reg 0x0c, firmware must push through or + something. + 0xe0 - first (and only) read linked list reg, for pci memory addr + 0xe4 - first (and only) read linked list reg, for Decoder memory addr + 0xe8 - first (and only) read linked list reg, for length of buffer + 0xec-0xff - Nothing seems to be in these registers, 0xec-f4 are 0x00000000. + +Memory locations for Encoder Buffers 0x700-0x7ff: + +These registers show offsets of memory locations pertaining to each +buffer area used for encoding, have to shift them by <<1 first. + +0x07F8: Encoder SDRAM refresh +0x07FC: Encoder SDRAM pre-charge + +Memory locations for Decoder Buffers 0x800-0x8ff: + +These registers show offsets of memory locations pertaining to each +buffer area used for decoding, have to shift them by <<1 first. + +0x08F8: Decoder SDRAM refresh +0x08FC: Decoder SDRAM pre-charge + +Other memory locations: + +0x2800: Video Display Module control +0x2D00: AO (audio output?) control +0x2D24: Bytes Flushed +0x7000: LSB I2C write clock bit (inverted) +0x7004: LSB I2C write data bit (inverted) +0x7008: LSB I2C read clock bit +0x700c: LSB I2C read data bit +0x9008: GPIO get input state +0x900c: GPIO set output state +0x9020: GPIO direction (Bit7 (GPIO 0..7) - 0:input, 1:output) +0x9050: SPU control +0x9054: Reset HW blocks +0x9058: VPU control +0xA018: Bit6: interrupt pending? +0xA064: APU command + + +Interrupt Status Register +========================= + +The definition of the bits in the interrupt status register 0x0040, and the +interrupt mask 0x0048. If a bit is cleared in the mask, then we want our ISR to +execute. + +Bit +31 Encoder Start Capture +30 Encoder EOS +29 Encoder VBI capture +28 Encoder Video Input Module reset event +27 Encoder DMA complete +26 +25 Decoder copy protect detection event +24 Decoder audio mode change detection event +23 +22 Decoder data request +21 Decoder I-Frame? done +20 Decoder DMA complete +19 Decoder VBI re-insertion +18 Decoder DMA err (linked-list bad) + +Missing +Encoder API call completed +Decoder API call completed +Encoder API post(?) +Decoder API post(?) +Decoder VTRACE event diff --git a/Documentation/video4linux/cx2341x/fw-osd-api.txt b/Documentation/video4linux/cx2341x/fw-osd-api.txt new file mode 100644 index 0000000..da98ae3 --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-osd-api.txt @@ -0,0 +1,342 @@ +OSD firmware API description +============================ + +Note: this API is part of the decoder firmware, so it's cx23415 only. + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_FRAMEBUFFER +Enum 65/0x41 +Description + Return base and length of contiguous OSD memory. +Result[0] + OSD base address +Result[1] + OSD length + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_PIXEL_FORMAT +Enum 66/0x42 +Description + Query OSD format +Result[0] + 0=8bit index, 4=AlphaRGB 8:8:8:8 + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_PIXEL_FORMAT +Enum 67/0x43 +Description + Assign pixel format +Param[0] + 0=8bit index, 4=AlphaRGB 8:8:8:8 + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_STATE +Enum 68/0x44 +Description + Query OSD state +Result[0] + Bit 0 0=off, 1=on + Bits 1:2 alpha control + Bits 3:5 pixel format + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_STATE +Enum 69/0x45 +Description + OSD switch +Param[0] + 0=off, 1=on + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_OSD_COORDS +Enum 70/0x46 +Description + Retrieve coordinates of OSD area blended with video +Result[0] + OSD buffer address +Result[1] + Stride in pixels +Result[2] + Lines in OSD buffer +Result[3] + Horizontal offset in buffer +Result[4] + Vertical offset in buffer + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_OSD_COORDS +Enum 71/0x47 +Description + Assign the coordinates of the OSD area to blend with video +Param[0] + buffer address +Param[1] + buffer stride in pixels +Param[2] + lines in buffer +Param[3] + horizontal offset +Param[4] + vertical offset + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_SCREEN_COORDS +Enum 72/0x48 +Description + Retrieve OSD screen area coordinates +Result[0] + top left horizontal offset +Result[1] + top left vertical offset +Result[2] + bottom right hotizontal offset +Result[3] + bottom right vertical offset + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_SCREEN_COORDS +Enum 73/0x49 +Description + Assign the coordinates of the screen area to blend with video +Param[0] + top left horizontal offset +Param[1] + top left vertical offset +Param[2] + bottom left horizontal offset +Param[3] + bottom left vertical offset + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_GLOBAL_ALPHA +Enum 74/0x4A +Description + Retrieve OSD global alpha +Result[0] + global alpha: 0=off, 1=on +Result[1] + bits 0:7 global alpha + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_GLOBAL_ALPHA +Enum 75/0x4B +Description + Update global alpha +Param[0] + global alpha: 0=off, 1=on +Param[1] + global alpha (8 bits) +Param[2] + local alpha: 0=on, 1=off + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_BLEND_COORDS +Enum 78/0x4C +Description + Move start of blending area within display buffer +Param[0] + horizontal offset in buffer +Param[1] + vertical offset in buffer + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_FLICKER_STATE +Enum 79/0x4F +Description + Retrieve flicker reduction module state +Result[0] + flicker state: 0=off, 1=on + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_FLICKER_STATE +Enum 80/0x50 +Description + Set flicker reduction module state +Param[0] + State: 0=off, 1=on + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_BLT_COPY +Enum 82/0x52 +Description + BLT copy +Param[0] +'0000' zero +'0001' ~destination AND ~source +'0010' ~destination AND source +'0011' ~destination +'0100' destination AND ~source +'0101' ~source +'0110' destination XOR source +'0111' ~destination OR ~source +'1000' ~destination AND ~source +'1001' destination XNOR source +'1010' source +'1011' ~destination OR source +'1100' destination +'1101' destination OR ~source +'1110' destination OR source +'1111' one + +Param[1] + Resulting alpha blending + '01' source_alpha + '10' destination_alpha + '11' source_alpha*destination_alpha+1 + (zero if both source and destination alpha are zero) +Param[2] + '00' output_pixel = source_pixel + + '01' if source_alpha=0: + output_pixel = destination_pixel + if 256 > source_alpha > 1: + output_pixel = ((source_alpha + 1)*source_pixel + + (255 - source_alpha)*destination_pixel)/256 + + '10' if destination_alpha=0: + output_pixel = source_pixel + if 255 > destination_alpha > 0: + output_pixel = ((255 - destination_alpha)*source_pixel + + (destination_alpha + 1)*destination_pixel)/256 + + '11' if source_alpha=0: + source_temp = 0 + if source_alpha=255: + source_temp = source_pixel*256 + if 255 > source_alpha > 0: + source_temp = source_pixel*(source_alpha + 1) + if destination_alpha=0: + destination_temp = 0 + if destination_alpha=255: + destination_temp = destination_pixel*256 + if 255 > destination_alpha > 0: + destination_temp = destination_pixel*(destination_alpha + 1) + output_pixel = (source_temp + destination_temp)/256 +Param[3] + width +Param[4] + height +Param[5] + destination pixel mask +Param[6] + destination rectangle start address +Param[7] + destination stride in dwords +Param[8] + source stride in dwords +Param[9] + source rectangle start address + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_BLT_FILL +Enum 83/0x53 +Description + BLT fill color +Param[0] + Same as Param[0] on API 0x52 +Param[1] + Same as Param[1] on API 0x52 +Param[2] + Same as Param[2] on API 0x52 +Param[3] + width +Param[4] + height +Param[5] + destination pixel mask +Param[6] + destination rectangle start address +Param[7] + destination stride in dwords +Param[8] + color fill value + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_BLT_TEXT +Enum 84/0x54 +Description + BLT for 8 bit alpha text source +Param[0] + Same as Param[0] on API 0x52 +Param[1] + Same as Param[1] on API 0x52 +Param[2] + Same as Param[2] on API 0x52 +Param[3] + width +Param[4] + height +Param[5] + destination pixel mask +Param[6] + destination rectangle start address +Param[7] + destination stride in dwords +Param[8] + source stride in dwords +Param[9] + source rectangle start address +Param[10] + color fill value + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_FRAMEBUFFER_WINDOW +Enum 86/0x56 +Description + Positions the main output window on the screen. The coordinates must be + such that the entire window fits on the screen. +Param[0] + window width +Param[1] + window height +Param[2] + top left window corner horizontal offset +Param[3] + top left window corner vertical offset + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_CHROMA_KEY +Enum 96/0x60 +Description + Chroma key switch and color +Param[0] + state: 0=off, 1=on +Param[1] + color + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_ALPHA_CONTENT_INDEX +Enum 97/0x61 +Description + Retrieve alpha content index +Result[0] + alpha content index, Range 0:15 + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_ALPHA_CONTENT_INDEX +Enum 98/0x62 +Description + Assign alpha content index +Param[0] + alpha content index, range 0:15 diff --git a/Documentation/video4linux/cx2341x/fw-upload.txt b/Documentation/video4linux/cx2341x/fw-upload.txt new file mode 100644 index 0000000..60c502c --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-upload.txt @@ -0,0 +1,49 @@ +This document describes how to upload the cx2341x firmware to the card. + +How to find +=========== + +See the web pages of the various projects that uses this chip for information +on how to obtain the firmware. + +The firmware stored in a Windows driver can be detected as follows: + +- Each firmware image is 256k bytes. +- The 1st 32-bit word of the Encoder image is 0x0000da7 +- The 1st 32-bit word of the Decoder image is 0x00003a7 +- The 2nd 32-bit word of both images is 0xaa55bb66 + +How to load +=========== + +- Issue the FWapi command to stop the encoder if it is running. Wait for the + command to complete. +- Issue the FWapi command to stop the decoder if it is running. Wait for the + command to complete. +- Issue the I2C command to the digitizer to stop emitting VSYNC events. +- Issue the FWapi command to halt the encoder's firmware. +- Sleep for 10ms. +- Issue the FWapi command to halt the decoder's firmware. +- Sleep for 10ms. +- Write 0x00000000 to register 0x2800 to stop the Video Display Module. +- Write 0x00000005 to register 0x2D00 to stop the AO (audio output?). +- Write 0x00000000 to register 0xA064 to ping? the APU. +- Write 0xFFFFFFFE to register 0x9058 to stop the VPU. +- Write 0xFFFFFFFF to register 0x9054 to reset the HW blocks. +- Write 0x00000001 to register 0x9050 to stop the SPU. +- Sleep for 10ms. +- Write 0x0000001A to register 0x07FC to init the Encoder SDRAM's pre-charge. +- Write 0x80000640 to register 0x07F8 to init the Encoder SDRAM's refresh to 1us. +- Write 0x0000001A to register 0x08FC to init the Decoder SDRAM's pre-charge. +- Write 0x80000640 to register 0x08F8 to init the Decoder SDRAM's refresh to 1us. +- Sleep for 512ms. (600ms is recommended) +- Transfer the encoder's firmware image to offset 0 in Encoder memory space. +- Transfer the decoder's firmware image to offset 0 in Decoder memory space. +- Use a read-modify-write operation to Clear bit 0 of register 0x9050 to + re-enable the SPU. +- Sleep for 1 second. +- Use a read-modify-write operation to Clear bits 3 and 0 of register 0x9058 + to re-enable the VPU. +- Sleep for 1 second. +- Issue status API commands to both firmware images to verify. + diff --git a/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt b/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt new file mode 100644 index 0000000..93fec32 --- /dev/null +++ b/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt @@ -0,0 +1,54 @@ +The controls for the mux are GPIO [0,1] for source, and GPIO 2 for muting. + +GPIO0 GPIO1 + 0 0 TV Audio + 1 0 FM radio + 0 1 Line-In + 1 1 Mono tuner bypass or CD passthru (tuner specific) + +GPIO 16(i believe) is tied to the IR port (if present). + +------------------------------------------------------------------------------------ + +>From the data sheet: + Register 24'h20004 PCI Interrupt Status + bit [18] IR_SMP_INT Set when 32 input samples have been collected over + gpio[16] pin into GP_SAMPLE register. + +What's missing from the data sheet: + +Setup 4KHz sampling rate (roughly 2x oversampled; good enough for our RC5 +compat remote) +set register 0x35C050 to 0xa80a80 + +enable sampling +set register 0x35C054 to 0x5 + +Of course, enable the IRQ bit 18 in the interrupt mask register .(and +provide for a handler) + +GP_SAMPLE register is at 0x35C058 + +Bits are then right shifted into the GP_SAMPLE register at the specified +rate; you get an interrupt when a full DWORD is recieved. +You need to recover the actual RC5 bits out of the (oversampled) IR sensor +bits. (Hint: look for the 0/1and 1/0 crossings of the RC5 bi-phase data) An +actual raw RC5 code will span 2-3 DWORDS, depending on the actual alignment. + +I'm pretty sure when no IR signal is present the receiver is always in a +marking state(1); but stray light, etc can cause intermittent noise values +as well. Remember, this is a free running sample of the IR receiver state +over time, so don't assume any sample starts at any particular place. + +http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf +This data sheet (google search) seems to have a lovely description of the +RC5 basics + +http://users.pandora.be/nenya/electronics/rc5/ and more data + +http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt +and even a reference to how to decode a bi-phase data stream. + +http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm +still more info + diff --git a/Documentation/video4linux/et61x251.txt b/Documentation/video4linux/et61x251.txt index 2934028..cd584f2 100644 --- a/Documentation/video4linux/et61x251.txt +++ b/Documentation/video4linux/et61x251.txt @@ -1,9 +1,9 @@ - ET61X[12]51 PC Camera Controllers - Driver for Linux - ================================= + ET61X[12]51 PC Camera Controllers + Driver for Linux + ================================= - - Documentation - + - Documentation - Index @@ -156,46 +156,46 @@ Name: video_nr Type: short array (min = 0, max = 64) Syntax: <-1|n[,...]> Description: Specify V4L2 minor mode number: - -1 = use next available - n = use minor number n - You can specify up to 64 cameras this way. - For example: - video_nr=-1,2,-1 would assign minor number 2 to the second - registered camera and use auto for the first one and for every - other camera. + -1 = use next available + n = use minor number n + You can specify up to 64 cameras this way. + For example: + video_nr=-1,2,-1 would assign minor number 2 to the second + registered camera and use auto for the first one and for every + other camera. Default: -1 ------------------------------------------------------------------------------- Name: force_munmap Type: bool array (min = 0, max = 64) Syntax: <0|1[,...]> Description: Force the application to unmap previously mapped buffer memory - before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not - all the applications support this feature. This parameter is - specific for each detected camera. - 0 = do not force memory unmapping - 1 = force memory unmapping (save memory) + before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not + all the applications support this feature. This parameter is + specific for each detected camera. + 0 = do not force memory unmapping + 1 = force memory unmapping (save memory) Default: 0 ------------------------------------------------------------------------------- Name: frame_timeout Type: uint array (min = 0, max = 64) Syntax: Description: Timeout for a video frame in seconds. This parameter is - specific for each detected camera. This parameter can be - changed at runtime thanks to the /sys filesystem interface. + specific for each detected camera. This parameter can be + changed at runtime thanks to the /sys filesystem interface. Default: 2 ------------------------------------------------------------------------------- Name: debug Type: ushort Syntax: Description: Debugging information level, from 0 to 3: - 0 = none (use carefully) - 1 = critical errors - 2 = significant informations - 3 = more verbose messages - Level 3 is useful for testing only, when only one device - is used at the same time. It also shows some more informations - about the hardware being detected. This module parameter can be - changed at runtime thanks to the /sys filesystem interface. + 0 = none (use carefully) + 1 = critical errors + 2 = significant informations + 3 = more verbose messages + Level 3 is useful for testing only, when only one device + is used at the same time. It also shows some more informations + about the hardware being detected. This module parameter can be + changed at runtime thanks to the /sys filesystem interface. Default: 2 ------------------------------------------------------------------------------- diff --git a/Documentation/video4linux/ibmcam.txt b/Documentation/video4linux/ibmcam.txt index 4a40a2e..397a94e 100644 --- a/Documentation/video4linux/ibmcam.txt +++ b/Documentation/video4linux/ibmcam.txt @@ -21,7 +21,7 @@ Internal interface: Video For Linux (V4L Supported controls: - by V4L: Contrast, Brightness, Color, Hue - by driver options: frame rate, lighting conditions, video format, - default picture settings, sharpness. + default picture settings, sharpness. SUPPORTED CAMERAS: @@ -191,66 +191,66 @@ init_model2_sat Integer 0..255 [ init_model2_yb Integer 0..255 [0xa0] init_model2_yb=200 debug You don't need this option unless you are a developer. - If you are a developer then you will see in the code - what values do what. 0=off. + If you are a developer then you will see in the code + what values do what. 0=off. flags This is a bit mask, and you can combine any number of - bits to produce what you want. Usually you don't want - any of extra features this option provides: - - FLAGS_RETRY_VIDIOCSYNC 1 This bit allows to retry failed - VIDIOCSYNC ioctls without failing. - Will work with xawtv, will not - with xrealproducer. Default is - not set. - FLAGS_MONOCHROME 2 Activates monochrome (b/w) mode. - FLAGS_DISPLAY_HINTS 4 Shows colored pixels which have - magic meaning to developers. - FLAGS_OVERLAY_STATS 8 Shows tiny numbers on screen, - useful only for debugging. - FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers. - FLAGS_SEPARATE_FRAMES 32 Shows each frame separately, as - it was received from the camera. - Default (not set) is to mix the - preceding frame in to compensate - for occasional loss of Isoc data - on high frame rates. - FLAGS_CLEAN_FRAMES 64 Forces "cleanup" of each frame - prior to use; relevant only if - FLAGS_SEPARATE_FRAMES is set. - Default is not to clean frames, - this is a little faster but may - produce flicker if frame rate is - too high and Isoc data gets lost. - FLAGS_NO_DECODING 128 This flag turns the video stream - decoder off, and dumps the raw - Isoc data from the camera into - the reading process. Useful to - developers, but not to users. + bits to produce what you want. Usually you don't want + any of extra features this option provides: + + FLAGS_RETRY_VIDIOCSYNC 1 This bit allows to retry failed + VIDIOCSYNC ioctls without failing. + Will work with xawtv, will not + with xrealproducer. Default is + not set. + FLAGS_MONOCHROME 2 Activates monochrome (b/w) mode. + FLAGS_DISPLAY_HINTS 4 Shows colored pixels which have + magic meaning to developers. + FLAGS_OVERLAY_STATS 8 Shows tiny numbers on screen, + useful only for debugging. + FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers. + FLAGS_SEPARATE_FRAMES 32 Shows each frame separately, as + it was received from the camera. + Default (not set) is to mix the + preceding frame in to compensate + for occasional loss of Isoc data + on high frame rates. + FLAGS_CLEAN_FRAMES 64 Forces "cleanup" of each frame + prior to use; relevant only if + FLAGS_SEPARATE_FRAMES is set. + Default is not to clean frames, + this is a little faster but may + produce flicker if frame rate is + too high and Isoc data gets lost. + FLAGS_NO_DECODING 128 This flag turns the video stream + decoder off, and dumps the raw + Isoc data from the camera into + the reading process. Useful to + developers, but not to users. framerate This setting controls frame rate of the camera. This is - an approximate setting (in terms of "worst" ... "best") - because camera changes frame rate depending on amount - of light available. Setting 0 is slowest, 6 is fastest. - Beware - fast settings are very demanding and may not - work well with all video sizes. Be conservative. + an approximate setting (in terms of "worst" ... "best") + because camera changes frame rate depending on amount + of light available. Setting 0 is slowest, 6 is fastest. + Beware - fast settings are very demanding and may not + work well with all video sizes. Be conservative. hue_correction This highly optional setting allows to adjust the - hue of the image in a way slightly different from - what usual "hue" control does. Both controls affect - YUV colorspace: regular "hue" control adjusts only - U component, and this "hue_correction" option similarly - adjusts only V component. However usually it is enough - to tweak only U or V to compensate for colored light or - color temperature; this option simply allows more - complicated correction when and if it is necessary. + hue of the image in a way slightly different from + what usual "hue" control does. Both controls affect + YUV colorspace: regular "hue" control adjusts only + U component, and this "hue_correction" option similarly + adjusts only V component. However usually it is enough + to tweak only U or V to compensate for colored light or + color temperature; this option simply allows more + complicated correction when and if it is necessary. init_brightness These settings specify _initial_ values which will be init_contrast used to set up the camera. If your V4L application has init_color its own controls to adjust the picture then these init_hue controls will be used too. These options allow you to - preconfigure the camera when it gets connected, before - any V4L application connects to it. Good for webcams. + preconfigure the camera when it gets connected, before + any V4L application connects to it. Good for webcams. init_model2_rg These initial settings alter color balance of the init_model2_rg2 camera on hardware level. All four settings may be used @@ -258,47 +258,47 @@ init_model2_sat to tune the camera to sp init_model2_yb settings only apply to Model 2 cameras. lighting This option selects one of three hardware-defined - photosensitivity settings of the camera. 0=bright light, - 1=Medium (default), 2=Low light. This setting affects - frame rate: the dimmer the lighting the lower the frame - rate (because longer exposition time is needed). The - Model 2 cameras allow values more than 2 for this option, - thus enabling extremely high sensitivity at cost of frame - rate, color saturation and imaging sensor noise. + photosensitivity settings of the camera. 0=bright light, + 1=Medium (default), 2=Low light. This setting affects + frame rate: the dimmer the lighting the lower the frame + rate (because longer exposition time is needed). The + Model 2 cameras allow values more than 2 for this option, + thus enabling extremely high sensitivity at cost of frame + rate, color saturation and imaging sensor noise. sharpness This option controls smoothing (noise reduction) - made by camera. Setting 0 is most smooth, setting 6 - is most sharp. Be aware that CMOS sensor used in the - camera is pretty noisy, so if you choose 6 you will - be greeted with "snowy" image. Default is 4. Model 2 - cameras do not support this feature. + made by camera. Setting 0 is most smooth, setting 6 + is most sharp. Be aware that CMOS sensor used in the + camera is pretty noisy, so if you choose 6 you will + be greeted with "snowy" image. Default is 4. Model 2 + cameras do not support this feature. size This setting chooses one of several image sizes that are - supported by this driver. Cameras may support more, but - it's difficult to reverse-engineer all formats. - Following video sizes are supported: - - size=0 128x96 (Model 1 only) - size=1 160x120 - size=2 176x144 - size=3 320x240 (Model 2 only) - size=4 352x240 (Model 2 only) - size=5 352x288 - size=6 640x480 (Model 3 only) - - The 352x288 is the native size of the Model 1 sensor - array, so it's the best resolution the camera can - yield. The best resolution of Model 2 is 176x144, and - larger images are produced by stretching the bitmap. - Model 3 has sensor with 640x480 grid, and it works too, - but the frame rate will be exceptionally low (1-2 FPS); - it may be still OK for some applications, like security. - Choose the image size you need. The smaller image can - support faster frame rate. Default is 352x288. + supported by this driver. Cameras may support more, but + it's difficult to reverse-engineer all formats. + Following video sizes are supported: + + size=0 128x96 (Model 1 only) + size=1 160x120 + size=2 176x144 + size=3 320x240 (Model 2 only) + size=4 352x240 (Model 2 only) + size=5 352x288 + size=6 640x480 (Model 3 only) + + The 352x288 is the native size of the Model 1 sensor + array, so it's the best resolution the camera can + yield. The best resolution of Model 2 is 176x144, and + larger images are produced by stretching the bitmap. + Model 3 has sensor with 640x480 grid, and it works too, + but the frame rate will be exceptionally low (1-2 FPS); + it may be still OK for some applications, like security. + Choose the image size you need. The smaller image can + support faster frame rate. Default is 352x288. For more information and the Troubleshooting FAQ visit this URL: - http://www.linux-usb.org/ibmcam/ + http://www.linux-usb.org/ibmcam/ WHAT NEEDS TO BE DONE: diff --git a/Documentation/video4linux/ov511.txt b/Documentation/video4linux/ov511.txt index 142741e..79af610 100644 --- a/Documentation/video4linux/ov511.txt +++ b/Documentation/video4linux/ov511.txt @@ -81,7 +81,7 @@ MODULE PARAMETERS: TYPE: integer (Boolean) DEFAULT: 1 DESC: Brightness is normally under automatic control and can't be set - manually by the video app. Set to 0 for manual control. + manually by the video app. Set to 0 for manual control. NAME: autogain TYPE: integer (Boolean) @@ -97,13 +97,13 @@ MODULE PARAMETERS: TYPE: integer (0-6) DEFAULT: 3 DESC: Sets the threshold for printing debug messages. The higher the value, - the more is printed. The levels are cumulative, and are as follows: - 0=no debug messages - 1=init/detection/unload and other significant messages - 2=some warning messages - 3=config/control function calls - 4=most function calls and data parsing messages - 5=highly repetitive mesgs + the more is printed. The levels are cumulative, and are as follows: + 0=no debug messages + 1=init/detection/unload and other significant messages + 2=some warning messages + 3=config/control function calls + 4=most function calls and data parsing messages + 5=highly repetitive mesgs NAME: snapshot TYPE: integer (Boolean) @@ -116,24 +116,24 @@ MODULE PARAMETERS: TYPE: integer (1-4 for OV511, 1-31 for OV511+) DEFAULT: 1 DESC: Number of cameras allowed to stream simultaneously on a single bus. - Values higher than 1 reduce the data rate of each camera, allowing two - or more to be used at once. If you have a complicated setup involving - both OV511 and OV511+ cameras, trial-and-error may be necessary for - finding the optimum setting. + Values higher than 1 reduce the data rate of each camera, allowing two + or more to be used at once. If you have a complicated setup involving + both OV511 and OV511+ cameras, trial-and-error may be necessary for + finding the optimum setting. NAME: compress TYPE: integer (Boolean) DEFAULT: 0 DESC: Set this to 1 to turn on the camera's compression engine. This can - potentially increase the frame rate at the expense of quality, if you - have a fast CPU. You must load the proper compression module for your - camera before starting your application (ov511_decomp or ov518_decomp). + potentially increase the frame rate at the expense of quality, if you + have a fast CPU. You must load the proper compression module for your + camera before starting your application (ov511_decomp or ov518_decomp). NAME: testpat TYPE: integer (Boolean) DEFAULT: 0 DESC: This configures the camera's sensor to transmit a colored test-pattern - instead of an image. This does not work correctly yet. + instead of an image. This does not work correctly yet. NAME: dumppix TYPE: integer (0-2) diff --git a/Documentation/video4linux/sn9c102.txt b/Documentation/video4linux/sn9c102.txt index 142920b..1d20895 100644 --- a/Documentation/video4linux/sn9c102.txt +++ b/Documentation/video4linux/sn9c102.txt @@ -1,9 +1,9 @@ - SN9C10x PC Camera Controllers - Driver for Linux - ============================= + SN9C10x PC Camera Controllers + Driver for Linux + ============================= - - Documentation - + - Documentation - Index @@ -176,46 +176,46 @@ Name: video_nr Type: short array (min = 0, max = 64) Syntax: <-1|n[,...]> Description: Specify V4L2 minor mode number: - -1 = use next available - n = use minor number n - You can specify up to 64 cameras this way. - For example: - video_nr=-1,2,-1 would assign minor number 2 to the second - recognized camera and use auto for the first one and for every - other camera. + -1 = use next available + n = use minor number n + You can specify up to 64 cameras this way. + For example: + video_nr=-1,2,-1 would assign minor number 2 to the second + recognized camera and use auto for the first one and for every + other camera. Default: -1 ------------------------------------------------------------------------------- Name: force_munmap Type: bool array (min = 0, max = 64) Syntax: <0|1[,...]> Description: Force the application to unmap previously mapped buffer memory - before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not - all the applications support this feature. This parameter is - specific for each detected camera. - 0 = do not force memory unmapping - 1 = force memory unmapping (save memory) + before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not + all the applications support this feature. This parameter is + specific for each detected camera. + 0 = do not force memory unmapping + 1 = force memory unmapping (save memory) Default: 0 ------------------------------------------------------------------------------- Name: frame_timeout Type: uint array (min = 0, max = 64) Syntax: Description: Timeout for a video frame in seconds. This parameter is - specific for each detected camera. This parameter can be - changed at runtime thanks to the /sys filesystem interface. + specific for each detected camera. This parameter can be + changed at runtime thanks to the /sys filesystem interface. Default: 2 ------------------------------------------------------------------------------- Name: debug Type: ushort Syntax: Description: Debugging information level, from 0 to 3: - 0 = none (use carefully) - 1 = critical errors - 2 = significant informations - 3 = more verbose messages - Level 3 is useful for testing only, when only one device - is used. It also shows some more informations about the - hardware being detected. This parameter can be changed at - runtime thanks to the /sys filesystem interface. + 0 = none (use carefully) + 1 = critical errors + 2 = significant informations + 3 = more verbose messages + Level 3 is useful for testing only, when only one device + is used. It also shows some more informations about the + hardware being detected. This parameter can be changed at + runtime thanks to the /sys filesystem interface. Default: 2 ------------------------------------------------------------------------------- @@ -280,24 +280,24 @@ Byte # Value Description 0x04 0xC4 Frame synchronisation pattern. 0x05 0x96 Frame synchronisation pattern. 0x06 0xXX Unknown meaning. The exact value depends on the chip; - possible values are 0x00, 0x01 and 0x20. + possible values are 0x00, 0x01 and 0x20. 0x07 0xXX Variable value, whose bits are ff00uzzc, where ff is a - frame counter, u is unknown, zz is a size indicator - (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for - "compression enabled" (1 = yes, 0 = no). + frame counter, u is unknown, zz is a size indicator + (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for + "compression enabled" (1 = yes, 0 = no). 0x08 0xXX Brightness sum inside Auto-Exposure area (low-byte). 0x09 0xXX Brightness sum inside Auto-Exposure area (high-byte). - For a pure white image, this number will be equal to 500 - times the area of the specified AE area. For images - that are not pure white, the value scales down according - to relative whiteness. + For a pure white image, this number will be equal to 500 + times the area of the specified AE area. For images + that are not pure white, the value scales down according + to relative whiteness. 0x0A 0xXX Brightness sum outside Auto-Exposure area (low-byte). 0x0B 0xXX Brightness sum outside Auto-Exposure area (high-byte). - For a pure white image, this number will be equal to 125 - times the area outside of the specified AE area. For - images that are not pure white, the value scales down - according to relative whiteness. - according to relative whiteness. + For a pure white image, this number will be equal to 125 + times the area outside of the specified AE area. For + images that are not pure white, the value scales down + according to relative whiteness. + according to relative whiteness. The following bytes are used by the SN9C103 bridge only: diff --git a/Documentation/video4linux/v4lgrab.c b/Documentation/video4linux/v4lgrab.c new file mode 100644 index 0000000..079b628 --- /dev/null +++ b/Documentation/video4linux/v4lgrab.c @@ -0,0 +1,192 @@ +/* Simple Video4Linux image grabber. */ +/* + * Video4Linux Driver Test/Example Framegrabbing Program + * + * Compile with: + * gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab + * Use as: + * v4lgrab >image.ppm + * + * Copyright (C) 1998-05-03, Phil Blundell + * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c + * with minor modifications (Dave Forrest, drf5n@virginia.edu). + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define FILE "/dev/video0" + +/* Stole this from tvset.c */ + +#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \ +{ \ + switch (format) \ + { \ + case VIDEO_PALETTE_GREY: \ + switch (depth) \ + { \ + case 4: \ + case 6: \ + case 8: \ + (r) = (g) = (b) = (*buf++ << 8);\ + break; \ + \ + case 16: \ + (r) = (g) = (b) = \ + *((unsigned short *) buf); \ + buf += 2; \ + break; \ + } \ + break; \ + \ + \ + case VIDEO_PALETTE_RGB565: \ + { \ + unsigned short tmp = *(unsigned short *)buf; \ + (r) = tmp&0xF800; \ + (g) = (tmp<<5)&0xFC00; \ + (b) = (tmp<<11)&0xF800; \ + buf += 2; \ + } \ + break; \ + \ + case VIDEO_PALETTE_RGB555: \ + (r) = (buf[0]&0xF8)<<8; \ + (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \ + (b) = ((buf[1] << 2 ) & 0xF8)<<8; \ + buf += 2; \ + break; \ + \ + case VIDEO_PALETTE_RGB24: \ + (r) = buf[0] << 8; (g) = buf[1] << 8; \ + (b) = buf[2] << 8; \ + buf += 3; \ + break; \ + \ + default: \ + fprintf(stderr, \ + "Format %d not yet supported\n", \ + format); \ + } \ +} + +int get_brightness_adj(unsigned char *image, long size, int *brightness) { + long i, tot = 0; + for (i=0;i= 126 && (tot/(size*3)) <= 130); +} + +int main(int argc, char ** argv) +{ + int fd = open(FILE, O_RDONLY), f; + struct video_capability cap; + struct video_window win; + struct video_picture vpic; + + unsigned char *buffer, *src; + int bpp = 24, r, g, b; + unsigned int i, src_depth; + + if (fd < 0) { + perror(FILE); + exit(1); + } + + if (ioctl(fd, VIDIOCGCAP, &cap) < 0) { + perror("VIDIOGCAP"); + fprintf(stderr, "(" FILE " not a video4linux device?)\n"); + close(fd); + exit(1); + } + + if (ioctl(fd, VIDIOCGWIN, &win) < 0) { + perror("VIDIOCGWIN"); + close(fd); + exit(1); + } + + if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) { + perror("VIDIOCGPICT"); + close(fd); + exit(1); + } + + if (cap.type & VID_TYPE_MONOCHROME) { + vpic.depth=8; + vpic.palette=VIDEO_PALETTE_GREY; /* 8bit grey */ + if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { + vpic.depth=6; + if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { + vpic.depth=4; + if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { + fprintf(stderr, "Unable to find a supported capture format.\n"); + close(fd); + exit(1); + } + } + } + } else { + vpic.depth=24; + vpic.palette=VIDEO_PALETTE_RGB24; + + if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { + vpic.palette=VIDEO_PALETTE_RGB565; + vpic.depth=16; + + if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { + vpic.palette=VIDEO_PALETTE_RGB555; + vpic.depth=15; + + if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { + fprintf(stderr, "Unable to find a supported capture format.\n"); + return -1; + } + } + } + } + + buffer = malloc(win.width * win.height * bpp); + if (!buffer) { + fprintf(stderr, "Out of memory.\n"); + exit(1); + } + + do { + int newbright; + read(fd, buffer, win.width * win.height * bpp); + f = get_brightness_adj(buffer, win.width * win.height, &newbright); + if (f) { + vpic.brightness += (newbright << 8); + if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { + perror("VIDIOSPICT"); + break; + } + } + } while (f); + + fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height); + + src = buffer; + + for (i = 0; i < win.width * win.height; i++) { + READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b); + fputc(r>>8, stdout); + fputc(g>>8, stdout); + fputc(b>>8, stdout); + } + + close(fd); + return 0; +} diff --git a/Documentation/video4linux/w9968cf.txt b/Documentation/video4linux/w9968cf.txt index 3b704f2..0d53ce7 100644 --- a/Documentation/video4linux/w9968cf.txt +++ b/Documentation/video4linux/w9968cf.txt @@ -1,9 +1,9 @@ - W996[87]CF JPEG USB Dual Mode Camera Chip - Driver for Linux 2.6 (basic version) - ========================================= + W996[87]CF JPEG USB Dual Mode Camera Chip + Driver for Linux 2.6 (basic version) + ========================================= - - Documentation - + - Documentation - Index @@ -188,57 +188,57 @@ Name: ovmod_load Type: bool Syntax: <0|1> Description: Automatic 'ovcamchip' module loading: 0 disabled, 1 enabled. - If enabled, 'insmod' searches for the required 'ovcamchip' - module in the system, according to its configuration, and - loads that module automatically. This action is performed as - once soon as the 'w9968cf' module is loaded into memory. + If enabled, 'insmod' searches for the required 'ovcamchip' + module in the system, according to its configuration, and + loads that module automatically. This action is performed as + once soon as the 'w9968cf' module is loaded into memory. Default: 1 Note: The kernel must be compiled with the CONFIG_KMOD option - enabled for the 'ovcamchip' module to be loaded and for - this parameter to be present. + enabled for the 'ovcamchip' module to be loaded and for + this parameter to be present. ------------------------------------------------------------------------------- Name: simcams Type: int Syntax: Description: Number of cameras allowed to stream simultaneously. - n may vary from 0 to 32. + n may vary from 0 to 32. Default: 32 ------------------------------------------------------------------------------- Name: video_nr Type: int array (min = 0, max = 32) Syntax: <-1|n[,...]> Description: Specify V4L minor mode number. - -1 = use next available - n = use minor number n - You can specify up to 32 cameras this way. - For example: - video_nr=-1,2,-1 would assign minor number 2 to the second - recognized camera and use auto for the first one and for every - other camera. + -1 = use next available + n = use minor number n + You can specify up to 32 cameras this way. + For example: + video_nr=-1,2,-1 would assign minor number 2 to the second + recognized camera and use auto for the first one and for every + other camera. Default: -1 ------------------------------------------------------------------------------- Name: packet_size Type: int array (min = 0, max = 32) Syntax: Description: Specify the maximum data payload size in bytes for alternate - settings, for each device. n is scaled between 63 and 1023. + settings, for each device. n is scaled between 63 and 1023. Default: 1023 ------------------------------------------------------------------------------- Name: max_buffers Type: int array (min = 0, max = 32) Syntax: Description: For advanced users. - Specify the maximum number of video frame buffers to allocate - for each device, from 2 to 32. + Specify the maximum number of video frame buffers to allocate + for each device, from 2 to 32. Default: 2 ------------------------------------------------------------------------------- Name: double_buffer Type: bool array (min = 0, max = 32) Syntax: <0|1[,...]> Description: Hardware double buffering: 0 disabled, 1 enabled. - It should be enabled if you want smooth video output: if you - obtain out of sync. video, disable it, or try to - decrease the 'clockdiv' module parameter value. + It should be enabled if you want smooth video output: if you + obtain out of sync. video, disable it, or try to + decrease the 'clockdiv' module parameter value. Default: 1 for every device. ------------------------------------------------------------------------------- Name: clamping @@ -251,9 +251,9 @@ Name: filter_type Type: int array (min = 0, max = 32) Syntax: <0|1|2[,...]> Description: Video filter type. - 0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter. - The filter is used to reduce noise and aliasing artifacts - produced by the CCD or CMOS image sensor. + 0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter. + The filter is used to reduce noise and aliasing artifacts + produced by the CCD or CMOS image sensor. Default: 0 for every device. ------------------------------------------------------------------------------- Name: largeview @@ -266,9 +266,9 @@ Name: upscaling Type: bool array (min = 0, max = 32) Syntax: <0|1[,...]> Description: Software scaling (for non-compressed video only): - 0 disabled, 1 enabled. - Disable it if you have a slow CPU or you don't have enough - memory. + 0 disabled, 1 enabled. + Disable it if you have a slow CPU or you don't have enough + memory. Default: 0 for every device. Note: If 'w9968cf-vpp' is not present, this parameter is set to 0. ------------------------------------------------------------------------------- @@ -276,36 +276,36 @@ Name: decompression Type: int array (min = 0, max = 32) Syntax: <0|1|2[,...]> Description: Software video decompression: - 0 = disables decompression - (doesn't allow formats needing decompression). - 1 = forces decompression - (allows formats needing decompression only). - 2 = allows any permitted formats. - Formats supporting (de)compressed video are YUV422P and - YUV420P/YUV420 in any resolutions where width and height are - multiples of 16. + 0 = disables decompression + (doesn't allow formats needing decompression). + 1 = forces decompression + (allows formats needing decompression only). + 2 = allows any permitted formats. + Formats supporting (de)compressed video are YUV422P and + YUV420P/YUV420 in any resolutions where width and height are + multiples of 16. Default: 2 for every device. Note: If 'w9968cf-vpp' is not present, forcing decompression is not - allowed; in this case this parameter is set to 2. + allowed; in this case this parameter is set to 2. ------------------------------------------------------------------------------- Name: force_palette Type: int array (min = 0, max = 32) Syntax: <0|9|10|13|15|8|7|1|6|3|4|5[,...]> Description: Force picture palette. - In order: - 0 = Off - allows any of the following formats: - 9 = UYVY 16 bpp - Original video, compression disabled - 10 = YUV420 12 bpp - Original video, compression enabled - 13 = YUV422P 16 bpp - Original video, compression enabled - 15 = YUV420P 12 bpp - Original video, compression enabled - 8 = YUVY 16 bpp - Software conversion from UYVY - 7 = YUV422 16 bpp - Software conversion from UYVY - 1 = GREY 8 bpp - Software conversion from UYVY - 6 = RGB555 16 bpp - Software conversion from UYVY - 3 = RGB565 16 bpp - Software conversion from UYVY - 4 = RGB24 24 bpp - Software conversion from UYVY - 5 = RGB32 32 bpp - Software conversion from UYVY - When not 0, this parameter will override 'decompression'. + In order: + 0 = Off - allows any of the following formats: + 9 = UYVY 16 bpp - Original video, compression disabled + 10 = YUV420 12 bpp - Original video, compression enabled + 13 = YUV422P 16 bpp - Original video, compression enabled + 15 = YUV420P 12 bpp - Original video, compression enabled + 8 = YUVY 16 bpp - Software conversion from UYVY + 7 = YUV422 16 bpp - Software conversion from UYVY + 1 = GREY 8 bpp - Software conversion from UYVY + 6 = RGB555 16 bpp - Software conversion from UYVY + 3 = RGB565 16 bpp - Software conversion from UYVY + 4 = RGB24 24 bpp - Software conversion from UYVY + 5 = RGB32 32 bpp - Software conversion from UYVY + When not 0, this parameter will override 'decompression'. Default: 0 for every device. Initial palette is 9 (UYVY). Note: If 'w9968cf-vpp' is not present, this parameter is set to 9. ------------------------------------------------------------------------------- @@ -313,77 +313,77 @@ Name: force_rgb Type: bool array (min = 0, max = 32) Syntax: <0|1[,...]> Description: Read RGB video data instead of BGR: - 1 = use RGB component ordering. - 0 = use BGR component ordering. - This parameter has effect when using RGBX palettes only. + 1 = use RGB component ordering. + 0 = use BGR component ordering. + This parameter has effect when using RGBX palettes only. Default: 0 for every device. ------------------------------------------------------------------------------- Name: autobright Type: bool array (min = 0, max = 32) Syntax: <0|1[,...]> Description: Image sensor automatically changes brightness: - 0 = no, 1 = yes + 0 = no, 1 = yes Default: 0 for every device. ------------------------------------------------------------------------------- Name: autoexp Type: bool array (min = 0, max = 32) Syntax: <0|1[,...]> Description: Image sensor automatically changes exposure: - 0 = no, 1 = yes + 0 = no, 1 = yes Default: 1 for every device. ------------------------------------------------------------------------------- Name: lightfreq Type: int array (min = 0, max = 32) Syntax: <50|60[,...]> Description: Light frequency in Hz: - 50 for European and Asian lighting, 60 for American lighting. + 50 for European and Asian lighting, 60 for American lighting. Default: 50 for every device. ------------------------------------------------------------------------------- Name: bandingfilter Type: bool array (min = 0, max = 32) Syntax: <0|1[,...]> Description: Banding filter to reduce effects of fluorescent - lighting: - 0 disabled, 1 enabled. - This filter tries to reduce the pattern of horizontal - light/dark bands caused by some (usually fluorescent) lighting. + lighting: + 0 disabled, 1 enabled. + This filter tries to reduce the pattern of horizontal + light/dark bands caused by some (usually fluorescent) lighting. Default: 0 for every device. ------------------------------------------------------------------------------- Name: clockdiv Type: int array (min = 0, max = 32) Syntax: <-1|n[,...]> Description: Force pixel clock divisor to a specific value (for experts): - n may vary from 0 to 127. - -1 for automatic value. - See also the 'double_buffer' module parameter. + n may vary from 0 to 127. + -1 for automatic value. + See also the 'double_buffer' module parameter. Default: -1 for every device. ------------------------------------------------------------------------------- Name: backlight Type: bool array (min = 0, max = 32) Syntax: <0|1[,...]> Description: Objects are lit from behind: - 0 = no, 1 = yes + 0 = no, 1 = yes Default: 0 for every device. ------------------------------------------------------------------------------- Name: mirror Type: bool array (min = 0, max = 32) Syntax: <0|1[,...]> Description: Reverse image horizontally: - 0 = no, 1 = yes + 0 = no, 1 = yes Default: 0 for every device. ------------------------------------------------------------------------------- Name: monochrome Type: bool array (min = 0, max = 32) Syntax: <0|1[,...]> Description: The image sensor is monochrome: - 0 = no, 1 = yes + 0 = no, 1 = yes Default: 0 for every device. ------------------------------------------------------------------------------- Name: brightness Type: long array (min = 0, max = 32) Syntax: Description: Set picture brightness (0-65535). - This parameter has no effect if 'autobright' is enabled. + This parameter has no effect if 'autobright' is enabled. Default: 31000 for every device. ------------------------------------------------------------------------------- Name: hue @@ -414,23 +414,23 @@ Name: debug Type: int Syntax: Description: Debugging information level, from 0 to 6: - 0 = none (use carefully) - 1 = critical errors - 2 = significant informations - 3 = configuration or general messages - 4 = warnings - 5 = called functions - 6 = function internals - Level 5 and 6 are useful for testing only, when only one - device is used. + 0 = none (use carefully) + 1 = critical errors + 2 = significant informations + 3 = configuration or general messages + 4 = warnings + 5 = called functions + 6 = function internals + Level 5 and 6 are useful for testing only, when only one + device is used. Default: 2 ------------------------------------------------------------------------------- Name: specific_debug Type: bool Syntax: <0|1> Description: Enable or disable specific debugging messages: - 0 = print messages concerning every level <= 'debug' level. - 1 = print messages concerning the level indicated by 'debug'. + 0 = print messages concerning every level <= 'debug' level. + 1 = print messages concerning the level indicated by 'debug'. Default: 0 ------------------------------------------------------------------------------- diff --git a/Documentation/video4linux/zc0301.txt b/Documentation/video4linux/zc0301.txt index f55262c..f406f5e 100644 --- a/Documentation/video4linux/zc0301.txt +++ b/Documentation/video4linux/zc0301.txt @@ -1,9 +1,9 @@ - ZC0301 Image Processor and Control Chip - Driver for Linux - ======================================= + ZC0301 and ZC0301P Image Processor and Control Chip + Driver for Linux + =================================================== - - Documentation - + - Documentation - Index @@ -51,13 +51,13 @@ Foundation, Inc., 675 Mass Ave, Cambridg 4. Overview and features ======================== -This driver supports the video interface of the devices mounting the ZC0301 -Image Processor and Control Chip. +This driver supports the video interface of the devices mounting the ZC0301 or +ZC0301P Image Processors and Control Chips. The driver relies on the Video4Linux2 and USB core modules. It has been designed to run properly on SMP systems as well. -The latest version of the ZC0301 driver can be found at the following URL: +The latest version of the ZC0301[P] driver can be found at the following URL: http://www.linux-projects.org/ Some of the features of the driver are: @@ -117,7 +117,7 @@ supported by the USB Audio driver thanks And finally: - # USB Multimedia devices + # V4L USB devices # CONFIG_USB_ZC0301=m @@ -146,46 +146,46 @@ Name: video_nr Type: short array (min = 0, max = 64) Syntax: <-1|n[,...]> Description: Specify V4L2 minor mode number: - -1 = use next available - n = use minor number n - You can specify up to 64 cameras this way. - For example: - video_nr=-1,2,-1 would assign minor number 2 to the second - registered camera and use auto for the first one and for every - other camera. + -1 = use next available + n = use minor number n + You can specify up to 64 cameras this way. + For example: + video_nr=-1,2,-1 would assign minor number 2 to the second + registered camera and use auto for the first one and for every + other camera. Default: -1 ------------------------------------------------------------------------------- Name: force_munmap Type: bool array (min = 0, max = 64) Syntax: <0|1[,...]> Description: Force the application to unmap previously mapped buffer memory - before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not - all the applications support this feature. This parameter is - specific for each detected camera. - 0 = do not force memory unmapping - 1 = force memory unmapping (save memory) + before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not + all the applications support this feature. This parameter is + specific for each detected camera. + 0 = do not force memory unmapping + 1 = force memory unmapping (save memory) Default: 0 ------------------------------------------------------------------------------- Name: frame_timeout Type: uint array (min = 0, max = 64) Syntax: Description: Timeout for a video frame in seconds. This parameter is - specific for each detected camera. This parameter can be - changed at runtime thanks to the /sys filesystem interface. + specific for each detected camera. This parameter can be + changed at runtime thanks to the /sys filesystem interface. Default: 2 ------------------------------------------------------------------------------- Name: debug Type: ushort Syntax: Description: Debugging information level, from 0 to 3: - 0 = none (use carefully) - 1 = critical errors - 2 = significant informations - 3 = more verbose messages - Level 3 is useful for testing only, when only one device - is used at the same time. It also shows some more informations - about the hardware being detected. This module parameter can be - changed at runtime thanks to the /sys filesystem interface. + 0 = none (use carefully) + 1 = critical errors + 2 = significant informations + 3 = more verbose messages + Level 3 is useful for testing only, when only one device + is used at the same time. It also shows some more informations + about the hardware being detected. This module parameter can be + changed at runtime thanks to the /sys filesystem interface. Default: 2 ------------------------------------------------------------------------------- @@ -204,11 +204,25 @@ Vendor ID Product ID 0x041e 0x4017 0x041e 0x401c 0x041e 0x401e +0x041e 0x401f +0x041e 0x4022 0x041e 0x4034 0x041e 0x4035 +0x041e 0x4036 +0x041e 0x403a +0x0458 0x7007 +0x0458 0x700C +0x0458 0x700f +0x046d 0x08ae +0x055f 0xd003 +0x055f 0xd004 0x046d 0x08ae 0x0ac8 0x0301 +0x0ac8 0x301b +0x0ac8 0x303b +0x10fd 0x0128 0x10fd 0x8050 +0x10fd 0x804e The list above does not imply that all those devices work with this driver: up until now only the ones that mount the following image sensors are supported; @@ -217,6 +231,7 @@ kernel messages will always tell you whe Model Manufacturer ----- ------------ PAS202BCB PixArt Imaging, Inc. +PB-0330 Photobit Corporation 9. Notes for V4L2 application developers @@ -250,5 +265,6 @@ the fingerprint is: '88E8 F32F 7244 68BA been taken from the documentation of the ZC030x Video4Linux1 driver written by Andrew Birkett ; - The initialization values of the ZC0301 controller connected to the PAS202BCB - image sensor have been taken from the SPCA5XX driver maintained by - Michel Xhaard . + and PB-0330 image sensors have been taken from the SPCA5XX driver maintained + by Michel Xhaard ; +- Stanislav Lechev donated one camera. diff --git a/Documentation/vm/page_migration b/Documentation/vm/page_migration index 0dd4ef3..99f89aa 100644 --- a/Documentation/vm/page_migration +++ b/Documentation/vm/page_migration @@ -26,8 +26,13 @@ a process are located. See also the numa Manual migration is useful if for example the scheduler has relocated a process to a processor on a distant node. A batch scheduler or an administrator may detect the situation and move the pages of the process -nearer to the new processor. At some point in the future we may have -some mechanism in the scheduler that will automatically move the pages. +nearer to the new processor. The kernel itself does only provide +manual page migration support. Automatic page migration may be implemented +through user space processes that move pages. A special function call +"move_pages" allows the moving of individual pages within a process. +A NUMA profiler may f.e. obtain a log showing frequent off node +accesses and may use the result to move pages to more advantageous +locations. Larger installations usually partition the system using cpusets into sections of nodes. Paul Jackson has equipped cpusets with the ability to @@ -62,22 +67,14 @@ A. In kernel use of migrate_pages() It also prevents the swapper or other scans to encounter the page. -2. Generate a list of newly allocates page. These pages will contain the - contents of the pages from the first list after page migration is - complete. +2. We need to have a function of type new_page_t that can be + passed to migrate_pages(). This function should figure out + how to allocate the correct new page given the old page. 3. The migrate_pages() function is called which attempts - to do the migration. It returns the moved pages in the - list specified as the third parameter and the failed - migrations in the fourth parameter. The first parameter - will contain the pages that could still be retried. - -4. The leftover pages of various types are returned - to the LRU using putback_to_lru_pages() or otherwise - disposed of. The pages will still have the refcount as - increased by isolate_lru_pages() if putback_to_lru_pages() is not - used! The kernel may want to handle the various cases of failures in - different ways. + to do the migration. It will call the function to allocate + the new page for each page that is considered for + moving. B. How migrate_pages() works ---------------------------- @@ -93,83 +90,58 @@ Steps: 2. Insure that writeback is complete. -3. Make sure that the page has assigned swap cache entry if - it is an anonyous page. The swap cache reference is necessary - to preserve the information contain in the page table maps while - page migration occurs. - -4. Prep the new page that we want to move to. It is locked +3. Prep the new page that we want to move to. It is locked and set to not being uptodate so that all accesses to the new page immediately lock while the move is in progress. -5. All the page table references to the page are either dropped (file - backed pages) or converted to swap references (anonymous pages). - This should decrease the reference count. +4. The new page is prepped with some settings from the old page so that + accesses to the new page will discover a page with the correct settings. + +5. All the page table references to the page are converted + to migration entries or dropped (nonlinear vmas). + This decrease the mapcount of a page. If the resulting + mapcount is not zero then we do not migrate the page. + All user space processes that attempt to access the page + will now wait on the page lock. 6. The radix tree lock is taken. This will cause all processes trying - to reestablish a pte to block on the radix tree spinlock. + to access the page via the mapping to block on the radix tree spinlock. 7. The refcount of the page is examined and we back out if references remain otherwise we know that we are the only one referencing this page. 8. The radix tree is checked and if it does not contain the pointer to this - page then we back out because someone else modified the mapping first. - -9. The mapping is checked. If the mapping is gone then a truncate action may - be in progress and we back out. - -10. The new page is prepped with some settings from the old page so that - accesses to the new page will be discovered to have the correct settings. + page then we back out because someone else modified the radix tree. -11. The radix tree is changed to point to the new page. +9. The radix tree is changed to point to the new page. -12. The reference count of the old page is dropped because the radix tree - reference is gone. +10. The reference count of the old page is dropped because the radix tree + reference is gone. A reference to the new page is established because + the new page is referenced to by the radix tree. -13. The radix tree lock is dropped. With that lookups become possible again - and other processes will move from spinning on the tree lock to sleeping on - the locked new page. +11. The radix tree lock is dropped. With that lookups in the mapping + become possible again. Processes will move from spinning on the tree_lock + to sleeping on the locked new page. -14. The page contents are copied to the new page. +12. The page contents are copied to the new page. -15. The remaining page flags are copied to the new page. +13. The remaining page flags are copied to the new page. -16. The old page flags are cleared to indicate that the page does - not use any information anymore. +14. The old page flags are cleared to indicate that the page does + not provide any information anymore. -17. Queued up writeback on the new page is triggered. +15. Queued up writeback on the new page is triggered. -18. If swap pte's were generated for the page then replace them with real - ptes. This will reenable access for processes not blocked by the page lock. +16. If migration entries were page then replace them with real ptes. Doing + so will enable access for user space processes not already waiting for + the page lock. 19. The page locks are dropped from the old and new page. - Processes waiting on the page lock can continue. + Processes waiting on the page lock will redo their page faults + and will reach the new page. 20. The new page is moved to the LRU and can be scanned by the swapper etc again. -TODO list ---------- - -- Page migration requires the use of swap handles to preserve the - information of the anonymous page table entries. This means that swap - space is reserved but never used. The maximum number of swap handles used - is determined by CHUNK_SIZE (see mm/mempolicy.c) per ongoing migration. - Reservation of pages could be avoided by having a special type of swap - handle that does not require swap space and that would only track the page - references. Something like that was proposed by Marcelo Tosatti in the - past (search for migration cache on lkml or linux-mm@kvack.org). - -- Page migration unmaps ptes for file backed pages and requires page - faults to reestablish these ptes. This could be optimized by somehow - recording the references before migration and then reestablish them later. - However, there are several locking challenges that have to be overcome - before this is possible. - -- Page migration generates read ptes for anonymous pages. Dirty page - faults are required to make the pages writable again. It may be possible - to generate a pte marked dirty if it is known that the page is dirty and - that this process has the only reference to that page. - -Christoph Lameter, March 8, 2006. +Christoph Lameter, May 8, 2006. diff --git a/Documentation/w1/masters/ds2490 b/Documentation/w1/masters/ds2490 new file mode 100644 index 0000000..44a4918 --- /dev/null +++ b/Documentation/w1/masters/ds2490 @@ -0,0 +1,18 @@ +Kernel driver ds2490 +==================== + +Supported chips: + * Maxim DS2490 based + +Author: Evgeniy Polyakov + + +Description +----------- + +The Maixm/Dallas Semiconductor DS2490 is a chip +which allows to build USB <-> W1 bridges. + +DS9490(R) is a USB <-> W1 bus master device +which has 0x81 family ID integrated chip and DS2490 +low-level operational chip. diff --git a/Documentation/w1/w1.generic b/Documentation/w1/w1.generic index f937fbe..4c6509d 100644 --- a/Documentation/w1/w1.generic +++ b/Documentation/w1/w1.generic @@ -27,8 +27,19 @@ When a w1 master driver registers with t When a device is found on the bus, w1 core checks if driver for it's family is loaded. If so, the family driver is attached to the slave. -If there is no driver for the family, a simple sysfs entry is created -for the slave device. +If there is no driver for the family, default one is assigned, which allows to perform +almost any kind of operations. Each logical operation is a transaction +in nature, which can contain several (two or one) low-level operations. +Let's see how one can read EEPROM context: +1. one must write control buffer, i.e. buffer containing command byte +and two byte address. At this step bus is reset and appropriate device +is selected using either W1_SKIP_ROM or W1_MATCH_ROM command. +Then provided control buffer is being written to the wire. +2. reading. This will issue reading eeprom response. + +It is possible that between 1. and 2. w1 master thread will reset bus for searching +and slave device will be even removed, but in this case 0xff will +be read, since no device was selected. W1 device families @@ -89,4 +100,5 @@ driver - (standard) symlink name - the device name, usually the same as the directory name w1_slave - (optional) a binary file whose meaning depends on the family driver - +rw - (optional) created for slave devices which do not have + appropriate family driver. Allows to read/write binary data. diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1.netlink new file mode 100644 index 0000000..3640c7c --- /dev/null +++ b/Documentation/w1/w1.netlink @@ -0,0 +1,98 @@ +Userspace communication protocol over connector [1]. + + +Message types. +============= + +There are three types of messages between w1 core and userspace: +1. Events. They are generated each time new master or slave device found + either due to automatic or requested search. +2. Userspace commands. Includes read/write and search/alarm search comamnds. +3. Replies to userspace commands. + + +Protocol. +======== + +[struct cn_msg] - connector header. It's length field is equal to size of the attached data. +[struct w1_netlink_msg] - w1 netlink header. + __u8 type - message type. + W1_SLAVE_ADD/W1_SLAVE_REMOVE - slave add/remove events. + W1_MASTER_ADD/W1_MASTER_REMOVE - master add/remove events. + W1_MASTER_CMD - userspace command for bus master device (search/alarm search). + W1_SLAVE_CMD - userspace command for slave device (read/write/ search/alarm search + for bus master device where given slave device found). + __u8 res - reserved + __u16 len - size of attached to this header data. + union { + __u8 id; - slave unique device id + struct w1_mst { + __u32 id; - master's id. + __u32 res; - reserved + } mst; + } id; + +[strucrt w1_netlink_cmd] - command for gived master or slave device. + __u8 cmd - command opcode. + W1_CMD_READ - read command. + W1_CMD_WRITE - write command. + W1_CMD_SEARCH - search command. + W1_CMD_ALARM_SEARCH - alarm search command. + __u8 res - reserved + __u16 len - length of data for this command. + For read command data must be allocated like for write command. + __u8 data[0] - data for this command. + + +Each connector message can include one or more w1_netlink_msg with zero of more attached w1_netlink_cmd messages. + +For event messages there are no w1_netlink_cmd embedded structures, only connector header +and w1_netlink_msg strucutre with "len" field being zero and filled type (one of event types) +and id - either 8 bytes of slave unique id in host order, or master's id, which is assigned +to bus master device when it is added to w1 core. + +Currently replies to userspace commands are only generated for read command request. +One reply is generated exactly for one w1_netlink_cmd read request. +Replies are not combined when sent - i.e. typical reply messages looks like the following: +[cn_msg][w1_netlink_msg][w1_netlink_cmd] +cn_msg.len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len; +w1_netlink_msg.len = sizeof(struct w1_netlink_cmd) + cmd->len; +w1_netlink_cmd.len = cmd->len; + + +Operation steps in w1 core when new command is received. +======================================================= + +When new message (w1_netlink_msg) is received w1 core detects if it is master of slave request, +according to w1_netlink_msg.type field. +Then master or slave device is searched for. +When found, master device (requested or those one on where slave device is found) is locked. +If slave command is requested, then reset/select procedure is started to select given device. + +Then all requested in w1_netlink_msg operations are performed one by one. +If command requires reply (like read command) it is sent on command completion. + +When all commands (w1_netlink_cmd) are processed muster device is unlocked +and next w1_netlink_msg header processing started. + + +Connector [1] specific documentation. +==================================== + +Each connector message includes two u32 fields as "address". +w1 uses CN_W1_IDX and CN_W1_VAL defined in include/linux/connector.h header. +Each message also includes sequence and acknowledge numbers. +Sequence number for event messages is appropriate bus master sequence number increased with +each event message sent "through" this master. +Sequence number for userspace requests is set by userspace application. +Sequence number for reply is the same as was in request, and +acknowledge number is set to seq+1. + + +Additional documantion, source code examples. +============================================ + +1. Documentation/connector +2. http://tservice.net.ru/~s0mbre/archive/w1 +This archive includes userspace application w1d.c which +uses read/write/search commands for all master/slave devices found on the bus. diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt index f2cd6ef..6887d44 100644 --- a/Documentation/x86_64/boot-options.txt +++ b/Documentation/x86_64/boot-options.txt @@ -205,6 +205,27 @@ IOMMU pages Prereserve that many 128K pages for the software IO bounce buffering. force Force all IO through the software TLB. + calgary=[64k,128k,256k,512k,1M,2M,4M,8M] + calgary=[translate_empty_slots] + calgary=[disable=] + + 64k,...,8M - Set the size of each PCI slot's translation table + when using the Calgary IOMMU. This is the size of the translation + table itself in main memory. The smallest table, 64k, covers an IO + space of 32MB; the largest, 8MB table, can cover an IO space of + 4GB. Normally the kernel will make the right choice by itself. + + translate_empty_slots - Enable translation even on slots that have + no devices attached to them, in case a device will be hotplugged + in the future. + + disable= - Disable translation on a given PHB. For + example, the built-in graphics adapter resides on the first bridge + (PCI bus number 0); if translation (isolation) is enabled on this + bridge, X servers that access the hardware directly from user + space might stop working. Use this option if you have devices that + are accessed from userspace directly on some PCI host bridge. + Debugging oops=panic Always panic on oopses. Default is to just kill the process, diff --git a/MAINTAINERS b/MAINTAINERS index c3c5842..31a1372 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -181,6 +181,12 @@ M: bcrl@kvack.org L: linux-aio@kvack.org S: Supported +ABIT UGURU HARDWARE MONITOR DRIVER +P: Hans de Goede +M: j.w.r.degoede@hhs.nl +L: lm-sensors@lm-sensors.org +S: Maintained + ACENIC DRIVER P: Jes Sorensen M: jes@trained-monkey.org @@ -568,6 +574,12 @@ L: linuxppc-dev@ozlabs.org W: http://www.penguinppc.org/ppc64/ S: Supported +BROADCOM B44 10/100 ETHERNET DRIVER +P: Gary Zambrano +M: zambrano@broadcom.com +L: netdev@vger.kernel.org +S: Supported + BROADCOM BNX2 GIGABIT ETHERNET DRIVER P: Michael Chan M: mchan@broadcom.com @@ -1106,6 +1118,11 @@ L: lm-sensors@lm-sensors.org W: http://www.lm-sensors.nu/ S: Maintained +HARDWARE RANDOM NUMBER GENERATOR CORE +P: Michael Buesch +M: mb@bu3sch.de +S: Maintained + HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER P: Robert Love M: rlove@rlove.org @@ -1147,6 +1164,12 @@ L: linux-hams@vger.kernel.org W: http://www.nt.tuwien.ac.at/~kkudielk/Linux/ S: Maintained +HIGHPOINT ROCKETRAID 3xxx RAID DRIVER +P: HighPoint Linux Team +M: linux@highpoint-tech.com +W: http://www.highpoint-tech.com +S: Supported + HIPPI P: Jes Sorensen M: jes@trained-monkey.org @@ -1378,7 +1401,8 @@ S: Supported INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS P: Dmitry Torokhov -M: dtor_core@ameritech.net +M: dmitry.torokhov@gmail.com +M: dtor@mail.ru L: linux-input@atrey.karlin.mff.cuni.cz L: linux-joystick@atrey.karlin.mff.cuni.cz T: git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git @@ -1418,6 +1442,11 @@ P: Tigran Aivazian M: tigran@veritas.com S: Maintained +INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT +P: Deepak Saxena +M: dsaxena@plexity.net +S: Maintained + INTEL PRO/100 ETHERNET SUPPORT P: John Ronciak M: john.ronciak@intel.com @@ -1425,6 +1454,8 @@ P: Jesse Brandeburg M: jesse.brandeburg@intel.com P: Jeff Kirsher M: jeffrey.t.kirsher@intel.com +P: Auke Kok +M: auke-jan.h.kok@intel.com W: http://sourceforge.net/projects/e1000/ S: Supported @@ -1437,6 +1468,8 @@ P: Jesse Brandeburg M: jesse.brandeburg@intel.com P: Jeff Kirsher M: jeffrey.t.kirsher@intel.com +P: Auke Kok +M: auke-jan.h.kok@intel.com W: http://sourceforge.net/projects/e1000/ S: Supported @@ -1449,6 +1482,8 @@ P: John Ronciak M: john.ronciak@intel.com P: Jesse Brandeburg M: jesse.brandeburg@intel.com +P: Auke Kok +M: auke-jan.h.kok@intel.com W: http://sourceforge.net/projects/e1000/ S: Supported @@ -1837,12 +1872,12 @@ S: linux-scsi@vger.kernel.org W: http://megaraid.lsilogic.com S: Maintained -MEMORY TECHNOLOGY DEVICES +MEMORY TECHNOLOGY DEVICES (MTD) P: David Woodhouse M: dwmw2@infradead.org W: http://www.linux-mtd.infradead.org/ L: linux-mtd@lists.infradead.org -T: git kernel.org:/pub/scm/linux/kernel/git/tglx/mtd-2.6.git +T: git git://git.infradead.org/mtd-2.6.git S: Maintained MICROTEK X6 SCANNER @@ -1889,7 +1924,7 @@ L: linux-kernel@vger.kernel.org W: http://www.atnf.csiro.au/~rgooch/linux/kernel-patches.html S: Maintained -MULTIMEDIA CARD SUBSYSTEM +MULTIMEDIA CARD (MMC) SUBSYSTEM P: Russell King M: rmk+mmc@arm.linux.org.uk S: Maintained @@ -2045,6 +2080,12 @@ M: adaplas@pol.net L: linux-fbdev-devel@lists.sourceforge.net S: Maintained +OPENCORES I2C BUS DRIVER +P: Peter Korsgaard +M: jacmet@sunsite.dk +L: lm-sensors@lm-sensors.org +S: Maintained + ORACLE CLUSTER FILESYSTEM 2 (OCFS2) P: Mark Fasheh M: mark.fasheh@oracle.com @@ -2516,12 +2557,6 @@ M: thomas@winischhofer.net W: http://www.winischhofer.at/linuxsisusbvga.shtml S: Maintained -SMSC47M1 HARDWARE MONITOR DRIVER -P: Jean Delvare -M: khali@linux-fr.org -L: lm-sensors@lm-sensors.org -S: Odd Fixes - SMB FILESYSTEM P: Urban Widmark M: urban@teststation.com @@ -2701,6 +2736,11 @@ P: Christoph Hellwig M: hch@infradead.org S: Maintained +TI OMAP RANDOM NUMBER GENERATOR SUPPORT +P: Deepak Saxena +M: dsaxena@plexity.net +S: Maintained + TI PARALLEL LINK CABLE DRIVER P: Romain Lievin M: roms@lpg.ticalc.org @@ -3134,12 +3174,6 @@ L: wbsd-devel@list.drzeus.cx W: http://projects.drzeus.cx/wbsd S: Maintained -W83L785TS HARDWARE MONITOR DRIVER -P: Jean Delvare -M: khali@linux-fr.org -L: lm-sensors@lm-sensors.org -S: Odd Fixes - WATCHDOG DEVICE DRIVERS P: Wim Van Sebroeck M: wim@iguana.be @@ -3179,7 +3213,7 @@ XFS FILESYSTEM P: Silicon Graphics Inc M: xfs-masters@oss.sgi.com M: nathans@sgi.com -L: linux-xfs@oss.sgi.com +L: xfs@oss.sgi.com W: http://oss.sgi.com/projects/xfs S: Supported diff --git a/Makefile b/Makefile index 1700d3f..e9560c6 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ # To locate output files in a separate d # In both cases the working directory must be the root of the kernel src. # 1) O= # Use "make O=dir/to/store/output/files/" -# +# # 2) Set KBUILD_OUTPUT # Set the environment variable KBUILD_OUTPUT to point to the directory # where the output files shall be placed. @@ -178,18 +178,20 @@ CROSS_COMPILE ?= # Architecture as present in compile.h UTS_MACHINE := $(ARCH) +KCONFIG_CONFIG ?= .config + # SHELL used by kbuild CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ else if [ -x /bin/bash ]; then echo /bin/bash; \ else echo sh; fi ; fi) -HOSTCC = gcc -HOSTCXX = g++ -HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -HOSTCXXFLAGS = -O2 +HOSTCC = gcc +HOSTCXX = g++ +HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer +HOSTCXXFLAGS = -O2 -# Decide whether to build built-in, modular, or both. -# Normally, just do built-in. +# Decide whether to build built-in, modular, or both. +# Normally, just do built-in. KBUILD_MODULES := KBUILD_BUILTIN := 1 @@ -197,7 +199,7 @@ KBUILD_BUILTIN := 1 # If we have only "make modules", don't compile built-in objects. # When we're building modules with modversions, we need to consider # the built-in objects during the descend as well, in order to -# make sure the checksums are uptodate before we record them. +# make sure the checksums are up to date before we record them. ifeq ($(MAKECMDGOALS),modules) KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1) @@ -230,7 +232,7 @@ # cmd_cc_o_c = $(CC) $(c_f # # If $(quiet) is empty, the whole command will be printed. # If it is set to "quiet_", only the short version will be printed. -# If it is set to "silent_", nothing wil be printed at all, since +# If it is set to "silent_", nothing will be printed at all, since # the variable $(silent_cmd_cc_o_c) doesn't exist. # # A simple variant is to prefix commands with $(Q) - that's useful @@ -265,10 +267,9 @@ MAKEFLAGS += --include-dir=$(srctree) # We need some generic definitions include $(srctree)/scripts/Kbuild.include -# For maximum performance (+ possibly random breakage, uncomment -# the following) - -#MAKEFLAGS += -rR +# Do not use make's built-in rules and variables +# This increases performance and avoid hard-to-debug behavour +MAKEFLAGS += -rR # Make variables (CC, etc...) @@ -305,21 +306,21 @@ LINUXINCLUDE := -Iinclude \ CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) -CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ - -fno-strict-aliasing -fno-common -AFLAGS := -D__ASSEMBLY__ +CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ + -fno-strict-aliasing -fno-common +AFLAGS := -D__ASSEMBLY__ -# Read KERNELRELEASE from .kernelrelease (if it exists) -KERNELRELEASE = $(shell cat .kernelrelease 2> /dev/null) +# Read KERNELRELEASE from include/config/kernel.release (if it exists) +KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) -export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION \ - ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \ - CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \ - HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS +export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION +export ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC +export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE +export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS -export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE +export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE # When compiling out-of-tree modules, put MODVERDIR in the module @@ -357,12 +358,13 @@ # To make sure we do not include .config # catch them early, and hand them over to scripts/kconfig/Makefile # It is allowed to specify more targets when calling make, including # mixing *config targets and build targets. -# For example 'make oldconfig all'. +# For example 'make oldconfig all'. # Detect when mixed targets is specified, and make a second invocation # of make so .config is not included in this case either (for *config). no-dot-config-targets := clean mrproper distclean \ - cscope TAGS tags help %docs check% + cscope TAGS tags help %docs check% \ + kernelrelease kernelversion config-targets := 0 mixed-targets := 0 @@ -404,9 +406,8 @@ include $(srctree)/arch/$(ARCH)/Makefile export KBUILD_DEFCONFIG config %config: scripts_basic outputmakefile FORCE - $(Q)mkdir -p include/linux + $(Q)mkdir -p include/linux include/config $(Q)$(MAKE) $(build)=scripts/kconfig $@ - $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease else # =========================================================================== @@ -416,13 +417,11 @@ # targets and others. In general all tar ifeq ($(KBUILD_EXTMOD),) # Additional helpers built in scripts/ # Carefully list dependencies so we do not try to build scripts twice -# in parrallel +# in parallel PHONY += scripts -scripts: scripts_basic include/config/MARKER +scripts: scripts_basic include/config/auto.conf $(Q)$(MAKE) $(build)=$(@) -scripts_basic: include/linux/autoconf.h - # Objects we will link into vmlinux / subdirs we need to visit init-y := init/ drivers-y := drivers/ sound/ @@ -436,31 +435,32 @@ # In this section, we need .config # Read in dependencies to all Kconfig* files, make sure to run # oldconfig if changes are detected. --include .kconfig.d +-include include/config/auto.conf.cmd +-include include/config/auto.conf -include .config - -# If .config needs to be updated, it will be done via the dependency -# that autoconf has on .config. # To avoid any implicit rule to kick in, define an empty command -.config .kconfig.d: ; +$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ; -# If .config is newer than include/linux/autoconf.h, someone tinkered +# If .config is newer than include/config/auto.conf, someone tinkered # with it and forgot to run make oldconfig. -# If kconfig.d is missing then we are probarly in a cleaned tree so +# if auto.conf.cmd is missing then we are probably in a cleaned tree so # we execute the config step to be sure to catch updated Kconfig files -include/linux/autoconf.h: .kconfig.d .config - $(Q)mkdir -p include/linux +include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd +ifeq ($(KBUILD_EXTMOD),) $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig else + $(error kernel configuration not valid - run 'make prepare' in $(srctree) to update it) +endif + +else # Dummy target needed, because used as prerequisite -include/linux/autoconf.h: ; +include/config/auto.conf: ; endif # The all: target is the default when no target is given on the # command line. # This allow a user to issue only 'make' to build a kernel including modules -# Defaults vmlinux but it is usually overriden in the arch makefile +# Defaults vmlinux but it is usually overridden in the arch makefile all: vmlinux ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE @@ -492,11 +492,11 @@ CHECKFLAGS += $(NOSTDINC_FLAGS) # warn about C99 declaration after statement CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) -# disable pointer signedness warnings in gcc 4.0 +# disable pointer signed / unsigned warnings in gcc 4.0 CFLAGS += $(call cc-option,-Wno-pointer-sign,) # Default kernel image to build when no specific target is given. -# KBUILD_IMAGE may be overruled on the commandline or +# KBUILD_IMAGE may be overruled on the command line or # set in the environment # Also any assignments in arch/$(ARCH)/Makefile take precedence over # this default value @@ -510,12 +510,29 @@ export INSTALL_PATH ?= /boot # # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory # relocations required by build roots. This is not defined in the -# makefile but the arguement can be passed to make if needed. +# makefile but the argument can be passed to make if needed. # MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) export MODLIB +# +# INSTALL_MOD_STRIP, if defined, will cause modules to be +# stripped after they are installed. If INSTALL_MOD_STRIP is '1', then +# the default option --strip-debug will be used. Otherwise, +# INSTALL_MOD_STRIP will used as the options to the strip command. + +ifdef INSTALL_MOD_STRIP +ifeq ($(INSTALL_MOD_STRIP),1) +mod_strip_cmd = $STRIP) --strip-debug +else +mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP) +endif # INSTALL_MOD_STRIP=1 +else +mod_strip_cmd = true +endif # INSTALL_MOD_STRIP +export mod_strip_cmd + ifeq ($(KBUILD_EXTMOD),) core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ @@ -539,7 +556,7 @@ libs-y := $(libs-y1) $(libs-y2) # Build vmlinux # --------------------------------------------------------------------------- -# vmlinux is build from the objects selected by $(vmlinux-init) and +# vmlinux is built from the objects selected by $(vmlinux-init) and # $(vmlinux-main). Most are built-in.o files from top-level directories # in the kernel tree, others are specified in arch/$(ARCH)Makefile. # Ordering when linking is important, and $(vmlinux-init) must be first. @@ -590,7 +607,7 @@ quiet_cmd_vmlinux_version = GEN .ver $(MAKE) $(build)=init # Generate System.map -quiet_cmd_sysmap = SYSMAP +quiet_cmd_sysmap = SYSMAP cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap # Link of vmlinux @@ -719,7 +736,7 @@ PHONY += $(vmlinux-dirs) $(Q)$(MAKE) $(build)=$@ # Build the kernel release string -# The KERNELRELEASE is stored in a file named .kernelrelease +# The KERNELRELEASE is stored in a file named include/config/kernel.release # to be used when executing for example make install or make modules_install # # Take the contents of any files called localversion* and the config @@ -737,10 +754,10 @@ _localver = $(foreach f, $(__localver), localver = $(subst $(space),, \ $(shell cat /dev/null $(_localver)) \ $(patsubst "%",%,$(CONFIG_LOCALVERSION))) - + # If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called # and if the SCM is know a tag from the SCM is appended. -# The appended tag is determinded by the SCM used. +# The appended tag is determined by the SCM used. # # Currently, only git is supported. # Other SCMs can edit scripts/setlocalversion and add the appropriate @@ -753,9 +770,9 @@ endif localver-full = $(localver)$(localver-auto) -# Store (new) KERNELRELASE string in .kernelrelease +# Store (new) KERNELRELASE string in include/config/kernel.release kernelrelease = $(KERNELVERSION)$(localver-full) -.kernelrelease: FORCE +include/config/kernel.release: include/config/auto.conf FORCE $(Q)rm -f $@ $(Q)echo $(kernelrelease) > $@ @@ -776,10 +793,10 @@ # prepare3 is used to check if we are bu # and if so do: # 1) Check that make has not been executed in the kernel src $(srctree) # 2) Create the include2 directory, used for the second asm symlink -prepare3: .kernelrelease +prepare3: include/config/kernel.release ifneq ($(KBUILD_SRC),) @echo ' Using $(srctree) as source for kernel' - $(Q)if [ -f $(srctree)/.config ]; then \ + $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \ echo " $(srctree) is not clean, please run 'make mrproper'";\ echo " in the '$(srctree)' directory.";\ /bin/false; \ @@ -792,7 +809,7 @@ # prepare2 creates a makefile if using a prepare2: prepare3 outputmakefile prepare1: prepare2 include/linux/version.h include/asm \ - include/config/MARKER + include/config/auto.conf ifneq ($(KBUILD_MODULES),) $(Q)mkdir -p $(MODVERDIR) $(Q)rm -f $(MODVERDIR)/* @@ -806,27 +823,20 @@ prepare0: archprepare FORCE # All the preparing.. prepare prepare-all: prepare0 -# Leave this as default for preprocessing vmlinux.lds.S, which is now -# done in arch/$(ARCH)/kernel/Makefile +# Leave this as default for preprocessing vmlinux.lds.S, which is now +# done in arch/$(ARCH)/kernel/Makefile export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) -# FIXME: The asm symlink changes when $(ARCH) changes. That's -# hard to detect, but I suppose "make mrproper" is a good idea -# before switching between archs anyway. +# FIXME: The asm symlink changes when $(ARCH) changes. That's +# hard to detect, but I suppose "make mrproper" is a good idea +# before switching between archs anyway. include/asm: @echo ' SYMLINK $@ -> include/asm-$(ARCH)' $(Q)if [ ! -d include ]; then mkdir -p include; fi; @ln -fsn asm-$(ARCH) $@ -# Split autoconf.h into include/linux/config/* - -include/config/MARKER: scripts/basic/split-include include/linux/autoconf.h - @echo ' SPLIT include/linux/autoconf.h -> include/config/*' - @scripts/basic/split-include include/linux/autoconf.h include/config - @touch $@ - # Generate some files # --------------------------------------------------------------------------- @@ -846,7 +856,7 @@ define filechk_version.h ) endef -include/linux/version.h: $(srctree)/Makefile .config .kernelrelease FORCE +include/linux/version.h: $(srctree)/Makefile include/config/kernel.release FORCE $(call filechk,version.h) # --------------------------------------------------------------------------- @@ -860,7 +870,7 @@ # Modules ifdef CONFIG_MODULES -# By default, build modules as well +# By default, build modules as well all: modules @@ -942,7 +952,7 @@ # Directories & files removed with 'make MRPROPER_DIRS += include/config include2 MRPROPER_FILES += .config .config.old include/asm .version .old_version \ include/linux/autoconf.h include/linux/version.h \ - .kernelrelease Module.symvers tags TAGS cscope* + Module.symvers tags TAGS cscope* # clean - Delete most, but leave enough to build external modules # @@ -958,8 +968,9 @@ clean: archclean $(clean-dirs) $(call cmd,rmdirs) $(call cmd,rmfiles) @find . $(RCS_FIND_IGNORE) \ - \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ - -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \ + \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ + -o -name '*.symtypes' \) \ -type f -print | xargs rm -f # mrproper - Delete all generated files, including .config @@ -982,9 +993,9 @@ PHONY += distclean distclean: mrproper @find $(srctree) $(RCS_FIND_IGNORE) \ - \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ + \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ - -o -name '.*.rej' -o -size 0 \ + -o -name '.*.rej' -o -size 0 \ -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \ -type f -print | xargs rm -f @@ -994,9 +1005,9 @@ # -------------------------------------- # rpm target kept for backward compatibility package-dir := $(srctree)/scripts/package -%pkg: FORCE +%pkg: include/config/kernel.release FORCE $(Q)$(MAKE) $(build)=$(package-dir) $@ -rpm: FORCE +rpm: include/config/kernel.release FORCE $(Q)$(MAKE) $(build)=$(package-dir) $@ @@ -1077,7 +1088,7 @@ # make M=dir clean Delete all automa # make M=dir modules Make all modules in specified dir # make M=dir Same as 'make M=dir modules' # make M=dir modules_install -# Install the modules build in the module directory +# Install the modules built in the module directory # Assumes install directory is already created # We are always building modules @@ -1136,7 +1147,7 @@ clean: rm-dirs := $(MODVERDIR) clean: $(clean-dirs) $(call cmd,rmdirs) @find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \ - \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ + \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \ -type f -print | xargs rm -f @@ -1175,31 +1186,41 @@ else ALLINCLUDE_ARCHS := $(ARCH) endif else -#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behaviour. +#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behavour. ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS) endif ALLSOURCE_ARCHS := $(ARCH) -define all-sources - ( find $(__srctree) $(RCS_FIND_IGNORE) \ +define find-sources + ( find $(__srctree) $(RCS_FIND_IGNORE) \ \( -name include -o -name arch \) -prune -o \ - -name '*.[chS]' -print; \ + -name $1 -print; \ for ARCH in $(ALLSOURCE_ARCHS) ; do \ find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \ - -name '*.[chS]' -print; \ + -name $1 -print; \ done ; \ find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \ - -name '*.[chS]' -print; \ + -name $1 -print; \ find $(__srctree)include $(RCS_FIND_IGNORE) \ \( -name config -o -name 'asm-*' \) -prune \ - -o -name '*.[chS]' -print; \ + -o -name $1 -print; \ for ARCH in $(ALLINCLUDE_ARCHS) ; do \ find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \ - -name '*.[chS]' -print; \ + -name $1 -print; \ done ; \ find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \ - -name '*.[chS]' -print ) + -name $1 -print ) +endef + +define all-sources + $(call find-sources,'*.[chS]') +endef +define all-kconfigs + $(call find-sources,'Kconfig*') +endef +define all-defconfigs + $(call find-sources,'defconfig') endef quiet_cmd_cscope-file = FILELST cscope.files @@ -1219,7 +1240,13 @@ define cmd_TAGS echo "-I __initdata,__exitdata,__acquires,__releases \ -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \ --extra=+f --c-kinds=+px"`; \ - $(all-sources) | xargs etags $$ETAGSF -a + $(all-sources) | xargs etags $$ETAGSF -a; \ + if test "x$$ETAGSF" = x; then \ + $(all-kconfigs) | xargs etags -a \ + --regex='/^config[ \t]+\([a-zA-Z0-9_]+\)/\1/'; \ + $(all-defconfigs) | xargs etags -a \ + --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \ + fi endef TAGS: FORCE @@ -1259,14 +1286,14 @@ namespacecheck: endif #ifeq ($(config-targets),1) endif #ifeq ($(mixed-targets),1) -PHONY += checkstack +PHONY += checkstack kernelrelease kernelversion checkstack: $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \ $(PERL) $(src)/scripts/checkstack.pl $(ARCH) kernelrelease: - $(if $(wildcard .kernelrelease), $(Q)echo $(KERNELRELEASE), \ - $(error kernelrelease not valid - run 'make *config' to update it)) + $(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \ + $(error kernelrelease not valid - run 'make prepare' to update it)) kernelversion: @echo $(KERNELVERSION) @@ -1301,6 +1328,8 @@ endif $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) %.o: %.S prepare scripts FORCE $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.symtypes: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) # Modules / %/: prepare scripts FORCE diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 2b245ad..d3848c5 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -53,10 +53,6 @@ extern void __divqu (void); extern void __remqu (void); EXPORT_SYMBOL(alpha_mv); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); -EXPORT_SYMBOL(disable_irq_nosync); -EXPORT_SYMBOL(probe_irq_mask); EXPORT_SYMBOL(screen_info); EXPORT_SYMBOL(perf_irq); EXPORT_SYMBOL(callback_getenv); @@ -68,19 +64,13 @@ #endif /* CONFIG_ALPHA_GENERIC */ /* platform dependent support */ EXPORT_SYMBOL(strcat); -EXPORT_SYMBOL(strcmp); EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strlen); -EXPORT_SYMBOL(strncmp); EXPORT_SYMBOL(strncpy); -EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strncat); -EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(strchr); EXPORT_SYMBOL(strrchr); -EXPORT_SYMBOL(memcmp); EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(memscan); EXPORT_SYMBOL(__memcpy); EXPORT_SYMBOL(__memset); EXPORT_SYMBOL(__memsetw); @@ -122,11 +112,9 @@ EXPORT_SYMBOL(alpha_write_fp_reg_s); /* In-kernel system calls. */ EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(sys_open); EXPORT_SYMBOL(sys_dup); EXPORT_SYMBOL(sys_exit); EXPORT_SYMBOL(sys_write); -EXPORT_SYMBOL(sys_read); EXPORT_SYMBOL(sys_lseek); EXPORT_SYMBOL(execve); EXPORT_SYMBOL(sys_setsid); diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 31afe3d..e15dcf4 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -244,7 +244,7 @@ do_osf_statfs(struct dentry * dentry, st unsigned long bufsiz) { struct kstatfs linux_stat; - int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat); + int error = vfs_statfs(dentry, &linux_stat); if (!error) error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); return error; diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 2e45e86..741da09 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -375,7 +375,7 @@ give_sigsegv: static inline void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) { - if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; return (void __user *)((sp - frame_size) & -32ul); diff --git a/arch/alpha/oprofile/common.c b/arch/alpha/oprofile/common.c index ba788cf..9fc0eeb 100644 --- a/arch/alpha/oprofile/common.c +++ b/arch/alpha/oprofile/common.c @@ -112,7 +112,7 @@ op_axp_create_files(struct super_block * for (i = 0; i < model->num_counters; ++i) { struct dentry *dir; - char buf[3]; + char buf[4]; snprintf(buf, sizeof buf, "%d", i); dir = oprofilefs_mkdir(sb, root, buf); diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 08b7cc9..3d1a3fb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -93,15 +93,49 @@ choice prompt "ARM system type" default ARCH_VERSATILE +config ARCH_AAEC2000 + bool "Agilent AAEC-2000 based" + select ARM_AMBA + help + This enables support for systems based on the Agilent AAEC-2000 + +config ARCH_INTEGRATOR + bool "ARM Ltd. Integrator family" + select ARM_AMBA + select ICST525 + help + Support for ARM's Integrator platform. + +config ARCH_REALVIEW + bool "ARM Ltd. RealView family" + select ARM_AMBA + select ICST307 + help + This enables support for ARM Ltd RealView boards. + +config ARCH_VERSATILE + bool "ARM Ltd. Versatile family" + select ARM_AMBA + select ARM_VIC + select ICST307 + help + This enables support for ARM Ltd Versatile board. + +config ARCH_AT91RM9200 + bool "Atmel AT91RM9200" + help + Say Y here if you intend to run this kernel on an Atmel + AT91RM9200-based board. + config ARCH_CLPS7500 - bool "Cirrus-CL-PS7500FE" + bool "Cirrus CL-PS7500FE" select TIMER_ACORN select ISA help Support for the Cirrus Logic PS7500FE system-on-a-chip. config ARCH_CLPS711X - bool "CLPS711x/EP721x-based" + bool "Cirrus Logic CLPS711x/EP721x-based" help Support for Cirrus Logic 711x/721x based boards. @@ -135,12 +169,22 @@ config ARCH_FOOTBRIDGE Support for systems based on the DC21285 companion chip ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder. -config ARCH_INTEGRATOR - bool "Integrator" - select ARM_AMBA - select ICST525 +config ARCH_NETX + bool "Hilscher NetX based" + select ARM_VIC help - Support for ARM's Integrator platform. + This enables support for systems based on the Hilscher NetX Soc + +config ARCH_H720X + bool "Hynix HMS720x-based" + select ISA_DMA_API + help + This enables support for systems based on the Hynix HMS720x + +config ARCH_IMX + bool "IMX" + help + Support for Motorola's i.MX family of processors (MX1, MXL). config ARCH_IOP3XX bool "IOP3xx-based" @@ -178,6 +222,11 @@ config ARCH_L7200 If you have any questions or comments about the Linux kernel port to this board, send e-mail to . +config ARCH_PNX4008 + bool "Philips Nexperia PNX4008 Mobile" + help + This enables support for Philips PNX4008 mobile platform. + config ARCH_PXA bool "PXA2xx-based" select ARCH_MTD_XIP @@ -204,7 +253,7 @@ config ARCH_SA1100 Support for StrongARM 11x0 based boards. config ARCH_S3C2410 - bool "Samsung S3C2410" + bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442" help Samsung S3C2410X CPU based systems, such as the Simtec Electronics BAST (), the IPAQ 1940 or @@ -232,44 +281,6 @@ config ARCH_OMAP help Support for TI's OMAP platform (OMAP1 and OMAP2). -config ARCH_VERSATILE - bool "Versatile" - select ARM_AMBA - select ARM_VIC - select ICST307 - help - This enables support for ARM Ltd Versatile board. - -config ARCH_REALVIEW - bool "RealView" - select ARM_AMBA - select ICST307 - help - This enables support for ARM Ltd RealView boards. - -config ARCH_IMX - bool "IMX" - help - Support for Motorola's i.MX family of processors (MX1, MXL). - -config ARCH_H720X - bool "Hynix-HMS720x-based" - select ISA_DMA_API - help - This enables support for systems based on the Hynix HMS720x - -config ARCH_AAEC2000 - bool "Agilent AAEC-2000 based" - select ARM_AMBA - help - This enables support for systems based on the Agilent AAEC-2000 - -config ARCH_AT91RM9200 - bool "AT91RM9200" - help - Say Y here if you intend to run this kernel on an Atmel - AT91RM9200-based board. - endchoice source "arch/arm/mach-clps711x/Kconfig" @@ -314,6 +325,8 @@ source "arch/arm/mach-realview/Kconfig" source "arch/arm/mach-at91rm9200/Kconfig" +source "arch/arm/mach-netx/Kconfig" + # Definitions to make life easier config ARCH_ACORN bool @@ -359,7 +372,7 @@ config ISA_DMA_API bool config PCI - bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB + bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX help Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 6f8e84c..a3bbaaf 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -116,6 +116,8 @@ endif machine-$(CONFIG_ARCH_REALVIEW) := realview machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200 machine-$(CONFIG_ARCH_EP93XX) := ep93xx + machine-$(CONFIG_ARCH_PNX4008) := pnx4008 + machine-$(CONFIG_ARCH_NETX) := netx ifeq ($(CONFIG_ARCH_EBSA110),y) # This is what happens if you forget the IOCS16 line. @@ -175,7 +177,7 @@ # Update machine arch and proc symlinks # them changed. We use .arch to indicate when they were updated # last, otherwise make uses the target directory mtime. -include/asm-arm/.arch: $(wildcard include/config/arch/*.h) include/config/MARKER +include/asm-arm/.arch: $(wildcard include/config/arch/*.h) include/config/auto.conf @echo ' SYMLINK include/asm-arm/arch -> include/asm-arm/$(INCDIR)' ifneq ($(KBUILD_SRC),) $(Q)mkdir -p include/asm-arm diff --git a/arch/arm/boot/compressed/head-at91rm9200.S b/arch/arm/boot/compressed/head-at91rm9200.S index 2119ea6..d68b9ac 100644 --- a/arch/arm/boot/compressed/head-at91rm9200.S +++ b/arch/arm/boot/compressed/head-at91rm9200.S @@ -49,6 +49,24 @@ #include cmp r7, r3 beq 99f + @ Embest ATEB9200 : 923 + mov r3, #(MACH_TYPE_ATEB9200 & 0xff) + orr r3, r3, #(MACH_TYPE_ATEB9200 & 0xff00) + cmp r7, r3 + beq 99f + + @ Sperry-Sun KAFA : 662 + mov r3, #(MACH_TYPE_KAFA & 0xff) + orr r3, r3, #(MACH_TYPE_KAFA & 0xff00) + cmp r7, r3 + beq 99f + + @ Ajeco 1ARM : 1075 + mov r3, #(MACH_TYPE_ONEARM & 0xff) + orr r3, r3, #(MACH_TYPE_ONEARM & 0xff00) + cmp r7, r3 + beq 99f + @ Unknown board, use the AT91RM9200DK board @ mov r7, #MACH_TYPE_AT91RM9200 mov r7, #(MACH_TYPE_AT91RM9200DK & 0xff) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index b56f5e6..23016f6 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -605,8 +605,8 @@ proc_types: b __armv4_mmu_cache_off b __armv4_mmu_cache_flush - .word 0x00070000 @ ARMv6 - .word 0x000f0000 + .word 0x0007b000 @ ARMv6 + .word 0x0007f000 b __armv4_mmu_cache_on b __armv4_mmu_cache_off b __armv6_mmu_cache_flush diff --git a/arch/arm/boot/compressed/ll_char_wr.S b/arch/arm/boot/compressed/ll_char_wr.S index d7bbd9d..8517c86 100644 --- a/arch/arm/boot/compressed/ll_char_wr.S +++ b/arch/arm/boot/compressed/ll_char_wr.S @@ -77,7 +77,7 @@ Lrow4bpplp: subne r1, r1, #1 ldrneb r7, [r6, r1] bne Lrow4bpplp - LOADREGS(fd, sp!, {r4 - r7, pc}) + ldmfd sp!, {r4 - r7, pc} @ @ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc) @@ -105,7 +105,7 @@ Lrow8bpplp: subne r1, r1, #1 ldrneb r7, [r6, r1] bne Lrow8bpplp - LOADREGS(fd, sp!, {r4 - r7, pc}) + ldmfd sp!, {r4 - r7, pc} @ @ Smashable regs: {r0 - r3}, [r4], {r5, r6}, [r7], (r8 - fp), [ip], (sp), [lr], (pc) @@ -127,7 +127,7 @@ Lrow1bpp: strb r7, [r0], r5 mov r7, r7, lsr #8 strb r7, [r0], r5 - LOADREGS(fd, sp!, {r4 - r7, pc}) + ldmfd sp!, {r4 - r7, pc} .bss ENTRY(con_charconvtable) diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 847e3e6..e1289a2 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_SHARP_PARAM) += sharpsl_par obj-$(CONFIG_SHARPSL_PM) += sharpsl_pm.o obj-$(CONFIG_SHARP_SCOOP) += scoop.o obj-$(CONFIG_ARCH_IXP2000) += uengine.o +obj-$(CONFIG_ARCH_IXP23XX) += uengine.o diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 7971d0d..5b7c263 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -77,6 +77,8 @@ #ifdef STATS #endif struct dmabounce_pool small; struct dmabounce_pool large; + + rwlock_t lock; }; static LIST_HEAD(dmabounce_devs); @@ -116,6 +118,7 @@ alloc_safe_buffer(struct dmabounce_devic struct safe_buffer *buf; struct dmabounce_pool *pool; struct device *dev = device_info->dev; + unsigned long flags; dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n", __func__, ptr, size, dir); @@ -163,8 +166,12 @@ #ifdef STATS print_alloc_stats(device_info); #endif + write_lock_irqsave(&device_info->lock, flags); + list_add(&buf->node, &device_info->safe_buffers); + write_unlock_irqrestore(&device_info->lock, flags); + return buf; } @@ -172,22 +179,32 @@ #endif static inline struct safe_buffer * find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr) { - struct safe_buffer *b; + struct safe_buffer *b = NULL; + unsigned long flags; + + read_lock_irqsave(&device_info->lock, flags); list_for_each_entry(b, &device_info->safe_buffers, node) if (b->safe_dma_addr == safe_dma_addr) - return b; + break; - return NULL; + read_unlock_irqrestore(&device_info->lock, flags); + return b; } static inline void free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *buf) { + unsigned long flags; + dev_dbg(device_info->dev, "%s(buf=%p)\n", __func__, buf); + write_lock_irqsave(&device_info->lock, flags); + list_del(&buf->node); + write_unlock_irqrestore(&device_info->lock, flags); + if (buf->pool) dma_pool_free(buf->pool->pool, buf->safe, buf->safe_dma_addr); else @@ -396,7 +413,6 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction dir) { - unsigned long flags; dma_addr_t dma_addr; dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", @@ -404,12 +420,8 @@ dma_map_single(struct device *dev, void BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - dma_addr = map_single(dev, ptr, size, dir); - local_irq_restore(flags); - return dma_addr; } @@ -424,25 +436,18 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - unsigned long flags; - dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", __func__, (void *) dma_addr, size, dir); BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - unmap_single(dev, dma_addr, size, dir); - - local_irq_restore(flags); } int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) { - unsigned long flags; int i; dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", @@ -450,8 +455,6 @@ dma_map_sg(struct device *dev, struct sc BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - for (i = 0; i < nents; i++, sg++) { struct page *page = sg->page; unsigned int offset = sg->offset; @@ -462,8 +465,6 @@ dma_map_sg(struct device *dev, struct sc map_single(dev, ptr, length, dir); } - local_irq_restore(flags); - return nents; } @@ -471,7 +472,6 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) { - unsigned long flags; int i; dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", @@ -479,55 +479,38 @@ dma_unmap_sg(struct device *dev, struct BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - for (i = 0; i < nents; i++, sg++) { dma_addr_t dma_addr = sg->dma_address; unsigned int length = sg->length; unmap_single(dev, dma_addr, length, dir); } - - local_irq_restore(flags); } void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - unsigned long flags; - dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", __func__, (void *) dma_addr, size, dir); - local_irq_save(flags); - sync_single(dev, dma_addr, size, dir); - - local_irq_restore(flags); } void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - unsigned long flags; - dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", __func__, (void *) dma_addr, size, dir); - local_irq_save(flags); - sync_single(dev, dma_addr, size, dir); - - local_irq_restore(flags); } void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) { - unsigned long flags; int i; dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", @@ -535,23 +518,18 @@ dma_sync_sg_for_cpu(struct device *dev, BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - for (i = 0; i < nents; i++, sg++) { dma_addr_t dma_addr = sg->dma_address; unsigned int length = sg->length; sync_single(dev, dma_addr, length, dir); } - - local_irq_restore(flags); } void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) { - unsigned long flags; int i; dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", @@ -559,16 +537,12 @@ dma_sync_sg_for_device(struct device *de BUG_ON(dir == DMA_NONE); - local_irq_save(flags); - for (i = 0; i < nents; i++, sg++) { dma_addr_t dma_addr = sg->dma_address; unsigned int length = sg->length; sync_single(dev, dma_addr, length, dir); } - - local_irq_restore(flags); } static int @@ -622,6 +596,7 @@ dmabounce_register_dev(struct device *de device_info->dev = dev; INIT_LIST_HEAD(&device_info->safe_buffers); + rwlock_init(&device_info->lock); #ifdef STATS device_info->total_allocs = 0; diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index a7dc137..0dafba3 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -629,21 +629,6 @@ static int locomo_resume(struct platform #endif -#define LCM_ALC_EN 0x8000 - -void frontlight_set(struct locomo *lchip, int duty, int vr, int bpwf) -{ - unsigned long flags; - - spin_lock_irqsave(&lchip->lock, flags); - locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); - udelay(100); - locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); - locomo_writel(bpwf | LCM_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); - spin_unlock_irqrestore(&lchip->lock, flags); -} - - /** * locomo_probe - probe for a single LoCoMo chip. * @phys_addr: physical address of device. @@ -698,14 +683,10 @@ __locomo_probe(struct device *me, struct , lchip->base + LOCOMO_GPD); locomo_writel(0, lchip->base + LOCOMO_GIE); - /* FrontLight */ + /* Frontlight */ locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); - /* Same constants can be used for collie and poodle - (depending on CONFIG options in original sharp code)? */ - frontlight_set(lchip, 163, 0, 148); - /* Longtime timer */ locomo_writel(0, lchip->base + LOCOMO_LTINT); /* SPI */ @@ -1063,6 +1044,30 @@ void locomo_m62332_senddata(struct locom } /* + * Frontlight control + */ + +static struct locomo *locomo_chip_driver(struct locomo_dev *ldev); + +void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf) +{ + unsigned long flags; + struct locomo *lchip = locomo_chip_driver(dev); + + if (vr) + locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 1); + else + locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 0); + + spin_lock_irqsave(&lchip->lock, flags); + locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); + udelay(100); + locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); + locomo_writel(bpwf | LOCOMO_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); + spin_unlock_irqrestore(&lchip->lock, flags); +} + +/* * LoCoMo "Register Access Bus." * * We model this as a regular bus type, and hang devices directly diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c index 3cd8c9e..045e37e 100644 --- a/arch/arm/common/sharpsl_pm.c +++ b/arch/arm/common/sharpsl_pm.c @@ -49,13 +49,6 @@ #define SHARPSL_CHARGE_WAIT_TIME #define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */ #define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */ -#define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ -#define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ -#define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */ -#define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */ -#define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ -#define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ - /* * Prototypes */ @@ -82,12 +75,13 @@ DEFINE_LED_TRIGGER(sharpsl_charge_led_tr static int get_percentage(int voltage) { int i = sharpsl_pm.machinfo->bat_levels - 1; + int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0; struct battery_thresh *thresh; if (sharpsl_pm.charge_mode == CHRG_ON) - thresh=sharpsl_pm.machinfo->bat_levels_acin; + thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin; else - thresh=sharpsl_pm.machinfo->bat_levels_noac; + thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac; while (i > 0 && (voltage > thresh[i].voltage)) i--; @@ -131,7 +125,7 @@ static void sharpsl_battery_thread(void sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE); /* Corgi cannot confirm when battery fully charged so periodically kick! */ - if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON) + if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON) && time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_ON_TIME_INTERVAL)) schedule_work(&toggle_charger); @@ -166,11 +160,11 @@ static void sharpsl_battery_thread(void && ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) || (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) { if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) { - corgibl_limit_intensity(1); + sharpsl_pm.machinfo->backlight_limit(1); sharpsl_pm.flags |= SHARPSL_BL_LIMIT; } } else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) { - corgibl_limit_intensity(0); + sharpsl_pm.machinfo->backlight_limit(0); sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT; } @@ -418,7 +412,7 @@ static int sharpsl_check_battery_temp(vo val = get_select_val(buff); dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); - if (val > SHARPSL_CHARGE_ON_TEMP) + if (val > sharpsl_pm.machinfo->charge_on_temp) return -1; return 0; @@ -450,7 +444,7 @@ static int sharpsl_check_battery_voltage val = get_select_val(buff); dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val); - if (val < SHARPSL_CHARGE_ON_VOLT) + if (val < sharpsl_pm.machinfo->charge_on_volt) return -1; return 0; @@ -468,7 +462,7 @@ static int sharpsl_ac_check(void) temp = get_select_val(buff); dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp); - if ((temp > SHARPSL_CHARGE_ON_ACIN_HIGH) || (temp < SHARPSL_CHARGE_ON_ACIN_LOW)) { + if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) { dev_err(sharpsl_pm.dev, "Error: AC check failed.\n"); return -1; } @@ -627,8 +621,8 @@ static int sharpsl_fatal_check(void) temp = get_select_val(buff); dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT)); - if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) || - (!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT))) + if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) || + (!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt))) return -1; return 0; } diff --git a/arch/arm/common/uengine.c b/arch/arm/common/uengine.c index a1310b7..dfca596 100644 --- a/arch/arm/common/uengine.c +++ b/arch/arm/common/uengine.c @@ -18,10 +18,26 @@ #include #include #include #include -#include +#include #include #include +#if defined(CONFIG_ARCH_IXP2000) +#define IXP_UENGINE_CSR_VIRT_BASE IXP2000_UENGINE_CSR_VIRT_BASE +#define IXP_PRODUCT_ID IXP2000_PRODUCT_ID +#define IXP_MISC_CONTROL IXP2000_MISC_CONTROL +#define IXP_RESET1 IXP2000_RESET1 +#else +#if defined(CONFIG_ARCH_IXP23XX) +#define IXP_UENGINE_CSR_VIRT_BASE IXP23XX_UENGINE_CSR_VIRT_BASE +#define IXP_PRODUCT_ID IXP23XX_PRODUCT_ID +#define IXP_MISC_CONTROL IXP23XX_MISC_CONTROL +#define IXP_RESET1 IXP23XX_RESET1 +#else +#error unknown platform +#endif +#endif + #define USTORE_ADDRESS 0x000 #define USTORE_DATA_LOWER 0x004 #define USTORE_DATA_UPPER 0x008 @@ -43,7 +59,7 @@ u32 ixp2000_uengine_mask; static void *ixp2000_uengine_csr_area(int uengine) { - return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10); + return ((void *)IXP_UENGINE_CSR_VIRT_BASE) + (uengine << 10); } /* @@ -91,8 +107,13 @@ EXPORT_SYMBOL(ixp2000_uengine_csr_write) void ixp2000_uengine_reset(u32 uengine_mask) { - ixp2000_reg_wrb(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask); - ixp2000_reg_wrb(IXP2000_RESET1, 0); + u32 value; + + value = ixp2000_reg_read(IXP_RESET1) & ~ixp2000_uengine_mask; + + uengine_mask &= ixp2000_uengine_mask; + ixp2000_reg_wrb(IXP_RESET1, value | uengine_mask); + ixp2000_reg_wrb(IXP_RESET1, value); } EXPORT_SYMBOL(ixp2000_uengine_reset); @@ -235,11 +256,12 @@ static int check_ixp_type(struct ixp2000 u32 product_id; u32 rev; - product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID); + product_id = ixp2000_reg_read(IXP_PRODUCT_ID); if (((product_id >> 16) & 0x1f) != 0) return 0; switch ((product_id >> 8) & 0xff) { +#ifdef CONFIG_ARCH_IXP2000 case 0: /* IXP2800 */ if (!(c->cpu_model_bitmask & 4)) return 0; @@ -254,6 +276,14 @@ static int check_ixp_type(struct ixp2000 if (!(c->cpu_model_bitmask & 2)) return 0; break; +#endif + +#ifdef CONFIG_ARCH_IXP23XX + case 4: /* IXP23xx */ + if (!(c->cpu_model_bitmask & 0x3f0)) + return 0; + break; +#endif default: return 0; @@ -432,7 +462,8 @@ static int __init ixp2000_uengine_init(v /* * Determine number of microengines present. */ - switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) { + switch ((ixp2000_reg_read(IXP_PRODUCT_ID) >> 8) & 0x1fff) { +#ifdef CONFIG_ARCH_IXP2000 case 0: /* IXP2800 */ case 1: /* IXP2850 */ ixp2000_uengine_mask = 0x00ff00ff; @@ -441,10 +472,17 @@ static int __init ixp2000_uengine_init(v case 2: /* IXP2400 */ ixp2000_uengine_mask = 0x000f000f; break; +#endif + +#ifdef CONFIG_ARCH_IXP23XX + case 4: /* IXP23xx */ + ixp2000_uengine_mask = (*IXP23XX_EXP_CFG_FUSE >> 8) & 0xf; + break; +#endif default: printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n", - (unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID)); + (unsigned int)ixp2000_reg_read(IXP_PRODUCT_ID)); ixp2000_uengine_mask = 0x00000000; break; } @@ -457,15 +495,15 @@ static int __init ixp2000_uengine_init(v /* * Synchronise timestamp counters across all microengines. */ - value = ixp2000_reg_read(IXP2000_MISC_CONTROL); - ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value & ~0x80); + value = ixp2000_reg_read(IXP_MISC_CONTROL); + ixp2000_reg_wrb(IXP_MISC_CONTROL, value & ~0x80); for (uengine = 0; uengine < 32; uengine++) { if (ixp2000_uengine_mask & (1 << uengine)) { ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0); ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0); } } - ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value | 0x80); + ixp2000_reg_wrb(IXP_MISC_CONTROL, value | 0x80); return 0; } diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig new file mode 100644 index 0000000..69c39e0 --- /dev/null +++ b/arch/arm/configs/ateb9200_defconfig @@ -0,0 +1,1312 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc3 +# Sun May 7 16:53:18 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# + +# +# AT91RM9200 Board Type +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +# CONFIG_MACH_KB9200 is not set +CONFIG_MACH_ATEB9200=y +# CONFIG_MACH_KAFA is not set + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=m +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# +CONFIG_AT91_CF=m + +# +# Kernel Features +# +CONFIG_PREEMPT=y +CONFIG_NO_IDLE_HZ=y +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set +CONFIG_LLC=m +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +# CONFIG_IEEE80211_SOFTMAC is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLOCK is not set +CONFIG_MTD_BLOCK_RO=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_AT91_DATAFLASH=y +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_SYM53C500 is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +CONFIG_DAVICOM_PHY=y +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +# CONFIG_NET_WIRELESS_RTNETLINK is not set + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_PCMCIA_NETWAVE is not set + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set +# CONFIG_HOSTAP is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPP_MPPE is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +# CONFIG_SERIAL_AT91_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set +CONFIG_AT91_SPI=y +CONFIG_AT91_SPIDEV=y + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +CONFIG_I2C_AT91=m +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_CDCETHER=y +CONFIG_USB_NET_GL620A=y +CONFIG_USB_NET_NET1080=y +CONFIG_USB_NET_PLUSB=y +CONFIG_USB_NET_RNDIS_HOST=y +CONFIG_USB_NET_CDC_SUBSET=y +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=y +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRPRIME is not set +# CONFIG_USB_SERIAL_ANYDATA is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +CONFIG_USB_SERIAL_CP2101=m +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +CONFIG_USB_SERIAL_FTDI_SIO=m +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=m +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=m +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m + +# +# MMC/SD Card support +# +CONFIG_MMC=m +CONFIG_MMC_DEBUG=y +CONFIG_MMC_BLOCK=m +CONFIG_MMC_AT91RM9200=m + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_AT91=y +# CONFIG_RTC_DRV_TEST is not set + +# +# File systems +# +CONFIG_EXT2_FS=m +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=m +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_REISERFS_FS_XATTR is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=m +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=m +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff --git a/arch/arm/configs/carmeva_defconfig b/arch/arm/configs/carmeva_defconfig new file mode 100644 index 0000000..5ccd29a --- /dev/null +++ b/arch/arm/configs/carmeva_defconfig @@ -0,0 +1,723 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.12-rc4 +# Tue Jun 14 12:05:24 2005 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_IOMAP=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +# CONFIG_AUDIT is not set +# CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +CONFIG_MACH_CARMEVA=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# +CONFIG_ISA_DMA_API=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_SMP is not set +# CONFIG_PREEMPT is not set +# CONFIG_DISCONTIGMEM is not set +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_AT91_DATAFLASH=y +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +CONFIG_ARM_AT91_ETHER_RMII=y +# CONFIG_SMC91X is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=m +CONFIG_SERIO_SERPORT=m +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_AT91_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +CONFIG_AT91_SPI=y +CONFIG_AT91_SPIDEV=y + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +CONFIG_MMC_DEBUG=y +CONFIG_MMC_BLOCK=m +CONFIG_MMC_AT91RM9200=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set + +# +# XFS support +# +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS_FS=y +CONFIG_JFFS_FS_VERBOSE=0 +CONFIG_JFFS_PROC_FS=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_NAND=y +# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig new file mode 100644 index 0000000..51ded20 --- /dev/null +++ b/arch/arm/configs/kafa_defconfig @@ -0,0 +1,884 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc3 +# Sun May 7 16:54:53 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# + +# +# AT91RM9200 Board Type +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +# CONFIG_MACH_KB9200 is not set +# CONFIG_MACH_ATEB9200 is not set +CONFIG_MACH_KAFA=y + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_LEDS=y +# CONFIG_LEDS_TIMER is not set +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20800000,10M root=/dev/ram0 rw" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLOCK is not set +CONFIG_MTD_BLOCK_RO=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_AT91_DATAFLASH=y +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +CONFIG_DAVICOM_PHY=y +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +# CONFIG_SERIAL_AT91_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=32 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AT91_WATCHDOG=y +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set +CONFIG_AT91_SPI=y +CONFIG_AT91_SPIDEV=y + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +CONFIG_I2C_AT91=y +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_AT91=y +# CONFIG_RTC_DRV_TEST is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig new file mode 100644 index 0000000..fee4f56 --- /dev/null +++ b/arch/arm/configs/kb9202_defconfig @@ -0,0 +1,780 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.13-rc2 +# Sun Aug 14 19:26:59 2005 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y + +# +# Code maturity level options +# +# CONFIG_EXPERIMENTAL is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_SWAP is not set +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +# CONFIG_KOBJECT_UEVENT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +CONFIG_MACH_KB9200=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# +CONFIG_ISA_DMA_API=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_IDLE_HZ is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x10000000 +CONFIG_ZBOOT_ROM_BSS=0x20040000 +CONFIG_ZBOOT_ROM=y +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933" + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_MISC=y +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +CONFIG_DEBUG_DRIVER=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_AT91_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_AT91_SPI is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB=y +CONFIG_USB_DEBUG=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MICROTEK is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network Adapters +# +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set + +# +# XFS support +# +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_DEVPTS_FS_XATTR=y +# CONFIG_DEVPTS_FS_SECURITY is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_HFSPLUS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig new file mode 100644 index 0000000..d08bbe5 --- /dev/null +++ b/arch/arm/configs/lpd270_defconfig @@ -0,0 +1,963 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-git2 +# Wed Jun 21 22:20:18 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_MTD_XIP=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91RM9200 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# Intel PXA2xx Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +CONFIG_MACH_LOGICPD_PXA270=y +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_PXA_SHARPSL is not set +CONFIG_PXA27x=y +CONFIG_IWMMXT=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +CONFIG_XSCALE_PMU=y + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=64M" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_PM_LEGACY is not set +# CONFIG_PM_DEBUG is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +# CONFIG_PACKET is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +# CONFIG_MTD_CFI_I1 is not set +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_XIP is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_SHARP_SL is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_IDE_GENERIC is not set +# CONFIG_IDE_ARM is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_SMC91X=y +# CONFIG_DM9000 is not set +# CONFIG_SMC911X is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +CONFIG_FB_FIRMWARE_EDID=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_PXA=y +# CONFIG_FB_PXA_PARAMETERS is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_AC97_CODEC=y +CONFIG_SND_AC97_BUS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# ALSA ARM devices +# +CONFIG_SND_PXA2XX_PCM=y +CONFIG_SND_PXA2XX_AC97=y + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_VFAT_FS is not set +CONFIG_FAT_DEFAULT_CODEPAGE=437 +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/configs/lpd7a400_defconfig b/arch/arm/configs/lpd7a400_defconfig index 67eaa26..bf9cf9c 100644 --- a/arch/arm/configs/lpd7a400_defconfig +++ b/arch/arm/configs/lpd7a400_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-rc1-bk2 -# Mon Mar 28 00:06:33 2005 +# Linux kernel version: 2.6.12 +# Thu Nov 3 14:15:32 2005 # CONFIG_ARM=y CONFIG_MMU=y @@ -17,6 +17,7 @@ CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup @@ -36,6 +37,8 @@ CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y # CONFIG_EPOLL is not set @@ -71,6 +74,7 @@ # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7952X is not set CONFIG_ARCH_LH7A40X=y # CONFIG_ARCH_OMAP is not set # CONFIG_ARCH_VERSATILE is not set @@ -84,6 +88,7 @@ # CONFIG_MACH_KEV7A400 is not set CONFIG_MACH_LPD7A400=y # CONFIG_MACH_LPD7A404 is not set CONFIG_ARCH_LH7A400=y +CONFIG_LPD7A40X_CPLD_SSP=y # CONFIG_LH7A40X_CONTIGMEM is not set # CONFIG_LH7A40X_ONE_BANK_PER_NODE is not set @@ -110,6 +115,8 @@ # CONFIG_CPU_DCACHE_WRITETHROUGH is not # # Bus support # +CONFIG_ARM_AMBA=y +CONFIG_ISA_DMA_API=y # # PCCARD (PCMCIA/CardBus) support @@ -119,6 +126,7 @@ # CONFIG_PCCARD is not set # # Kernel Features # +# CONFIG_SMP is not set CONFIG_PREEMPT=y CONFIG_DISCONTIGMEM=y CONFIG_ALIGNMENT_TRAP=y @@ -175,7 +183,7 @@ # CONFIG_MTD_DEBUG is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set # @@ -217,7 +225,10 @@ # # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x00000000 +CONFIG_MTD_PHYSMAP_LEN=0x04000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=4 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_EDB7312 is not set @@ -254,7 +265,6 @@ # # # Block devices # -# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set @@ -288,13 +298,15 @@ # CONFIG_IDEDISK_MULTI_MODE is not set # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_POLL=y # # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y -# CONFIG_IDE_ARM is not set +CONFIG_IDE_ARM=y # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set @@ -302,7 +314,37 @@ # CONFIG_BLK_DEV_HD is not set # # SCSI device support # -# CONFIG_SCSI is not set +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +# CONFIG_BLK_DEV_SD is not set +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set # # Multi-device support (RAID and LVM) @@ -331,7 +373,6 @@ # Networking options # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -438,13 +479,10 @@ CONFIG_INPUT=y # # Userland interfaces # -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set +CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set # @@ -453,7 +491,13 @@ # # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +CONFIG_TOUCHSCREEN_ADS7843_LH7=y +CONFIG_HAS_TOUCHSCREEN_ADS7843_LH7=y # CONFIG_INPUT_MISC is not set # @@ -461,7 +505,6 @@ # Hardware I/O ports # # CONFIG_SERIO is not set # CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y # # Character devices @@ -479,6 +522,8 @@ # CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_LH7A40X=y @@ -510,7 +555,6 @@ # CONFIG_RAW_DRIVER is not set # # TPM devices # -# CONFIG_TCG_TPM is not set # # I2C support @@ -534,18 +578,73 @@ # CONFIG_DVB is not set # # Graphics support # -# CONFIG_FB is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_SOFT_CURSOR=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +CONFIG_FB_ARMCLCD=y +CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT=y +# CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02 is not set +# CONFIG_FB_ARMCLCD_SHARP_LQ64D343 is not set +# CONFIG_FB_ARMCLCD_SHARP_LQ10D368 is not set +# CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41 is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set # # Console display driver support # # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +# CONFIG_SND_RTCTIMER is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_AC97_CODEC=y + +# +# ALSA ARM devices +# +CONFIG_SND_LH7A40X_AC97=y + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set # # USB support diff --git a/arch/arm/configs/lpd7a404_defconfig b/arch/arm/configs/lpd7a404_defconfig index 208d591..3a57be3 100644 --- a/arch/arm/configs/lpd7a404_defconfig +++ b/arch/arm/configs/lpd7a404_defconfig @@ -1,52 +1,58 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-rc1-bk2 -# Mon Mar 28 00:14:08 2005 +# Linux kernel version: 2.6.16 +# Thu Mar 23 17:50:31 2006 # CONFIG_ARM=y CONFIG_MMU=y -CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_IOMAP=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -# CONFIG_HOTPLUG is not set -CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y # CONFIG_IKCONFIG_PROC is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_HOTPLUG is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y # CONFIG_EPOLL is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SHMEM=y CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set +CONFIG_OBSOLETE_INTERMODULE=y # # Loadable module support @@ -54,6 +60,23 @@ # # CONFIG_MODULES is not set # +# Block layer +# + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# # System Type # # CONFIG_ARCH_CLPS7500 is not set @@ -71,11 +94,15 @@ # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7952X is not set CONFIG_ARCH_LH7A40X=y # CONFIG_ARCH_OMAP is not set # CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_IMX is not set # CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91RM9200 is not set # # LH7A40X Implementations @@ -110,6 +137,7 @@ # CONFIG_CPU_DCACHE_WRITETHROUGH is not # # Bus support # +CONFIG_ARM_AMBA=y # # PCCARD (PCMCIA/CardBus) support @@ -120,7 +148,18 @@ # # Kernel Features # CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +# CONFIG_AEABI is not set +CONFIG_ARCH_DISCONTIGMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +CONFIG_DISCONTIGMEM_MANUAL=y +# CONFIG_SPARSEMEM_MANUAL is not set CONFIG_DISCONTIGMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_NEED_MULTIPLE_NODES=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 CONFIG_ALIGNMENT_TRAP=y # @@ -154,6 +193,84 @@ # # Power management options # # CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -168,6 +285,11 @@ # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set # +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# # Memory Technology Devices (MTD) # CONFIG_MTD=y @@ -175,7 +297,7 @@ # CONFIG_MTD_DEBUG is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set # @@ -186,6 +308,7 @@ CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set # CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set # # RAM/ROM/Flash chip drivers @@ -211,15 +334,18 @@ CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_XIP is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set # # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x00000000 +CONFIG_MTD_PHYSMAP_LEN=0x04000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=4 # CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_EDB7312 is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -243,6 +369,11 @@ # # CONFIG_MTD_NAND is not set # +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# # Parallel port support # # CONFIG_PARPORT is not set @@ -254,7 +385,6 @@ # # # Block devices # -# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set @@ -262,16 +392,7 @@ # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_UB is not set # CONFIG_BLK_DEV_RAM is not set CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_INITRAMFS_SOURCE="" # CONFIG_CDROM_PKTCDVD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -# CONFIG_IOSCHED_DEADLINE is not set -CONFIG_IOSCHED_CFQ=y # CONFIG_ATA_OVER_ETH is not set # @@ -291,12 +412,13 @@ # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_POLL=y # # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y -# CONFIG_IDE_ARM is not set +CONFIG_IDE_ARM=y # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set @@ -304,6 +426,7 @@ # CONFIG_BLK_DEV_HD is not set # # SCSI device support # +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y # CONFIG_SCSI_PROC_FS is not set @@ -315,6 +438,7 @@ # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set # CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs @@ -329,10 +453,12 @@ # # CONFIG_SCSI_SPI_ATTRS is not set # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set # # SCSI low-level drivers # +# CONFIG_ISCSI_TCP is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_DEBUG is not set @@ -344,6 +470,7 @@ # CONFIG_MD is not set # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support @@ -354,70 +481,8 @@ # I2O device support # # -# Networking support +# Network device support # -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -425,11 +490,17 @@ # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set # +# PHY device support +# +# CONFIG_PHYLIB is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y CONFIG_SMC91X=y +# CONFIG_DM9000 is not set # # Ethernet (1000 Mbit) @@ -456,6 +527,8 @@ # CONFIG_PPP is not set # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -470,10 +543,13 @@ CONFIG_INPUT=y # # Userland interfaces # -# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set +CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set # @@ -482,7 +558,13 @@ # # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +CONFIG_TOUCHSCREEN_ADC_LH7=y +CONFIG_HAS_TOUCHSCREEN_ADC_LH7=y # CONFIG_INPUT_MISC is not set # @@ -490,7 +572,6 @@ # Hardware I/O ports # # CONFIG_SERIO is not set # CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y # # Character devices @@ -508,6 +589,8 @@ # CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_LH7A40X=y @@ -533,13 +616,13 @@ # CONFIG_R3964 is not set # # Ftape, the floppy tape device driver # -# CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set # # TPM devices # # CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set # # I2C support @@ -547,10 +630,33 @@ # # CONFIG_I2C is not set # +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# # Misc devices # # +# Multimedia Capabilities Port drivers +# + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -563,18 +669,83 @@ # CONFIG_DVB is not set # # Graphics support # -# CONFIG_FB is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +CONFIG_FB_ARMCLCD=y +CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT=y +# CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02 is not set +# CONFIG_FB_ARMCLCD_SHARP_LQ64D343 is not set +# CONFIG_FB_ARMCLCD_SHARP_LQ10D368 is not set +# CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41 is not set +# CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE is not set +# CONFIG_FB_ARMCLCD_HITACHI is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set # # Console display driver support # # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +# CONFIG_SND_RTCTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_AC97_CODEC=y +CONFIG_SND_AC97_BUS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# ALSA ARM devices +# +# CONFIG_SND_ARMAACI is not set +CONFIG_SND_LH7A40X_AC97=y + +# +# USB devices +# +# CONFIG_SND_USB_AUDIO is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set # # USB support @@ -595,6 +766,7 @@ # CONFIG_USB_OTG is not set # # USB Host Controller Drivers # +# CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -603,16 +775,19 @@ # CONFIG_USB_SL811_HCD is not set # # USB Device Class drivers # -# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=y CONFIG_USB_STORAGE_DEBUG=y -# CONFIG_USB_STORAGE_RW_DETECT is not set CONFIG_USB_STORAGE_DATAFAB=y # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set @@ -621,22 +796,32 @@ # CONFIG_USB_STORAGE_USBAT is not set # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set # CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_LIBUSUAL is not set # # USB Input Devices # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set # CONFIG_HID_FF is not set # CONFIG_USB_HIDDEV is not set # CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set # CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set # CONFIG_USB_EGALAX is not set +# CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set # # USB Imaging devices @@ -686,16 +871,33 @@ # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set # -# USB ATM/DSL drivers +# USB DSL modem support # # # USB Gadget Support # -# CONFIG_USB_GADGET is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +CONFIG_USB_GADGET_LH7=y +CONFIG_USB_LH7=y +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +CONFIG_USB_ZERO=y +# CONFIG_USB_ETH is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set # # MMC/SD Card support @@ -707,6 +909,7 @@ # File systems # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set @@ -716,17 +919,17 @@ # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set - -# -# XFS support -# +# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -749,12 +952,11 @@ # Pseudo filesystems # CONFIG_PROC_FS=y CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y -# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -769,8 +971,8 @@ # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y @@ -787,12 +989,14 @@ # Network File Systems # CONFIG_NFS_FS=y CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set # CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set @@ -801,6 +1005,7 @@ # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -820,6 +1025,7 @@ # CONFIG_LDM_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set # @@ -875,19 +1081,24 @@ # # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y -CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set CONFIG_DEBUG_PREEMPT=y +CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set CONFIG_FRAME_POINTER=y +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y # CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y @@ -912,6 +1123,7 @@ # # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig new file mode 100644 index 0000000..61115a7 --- /dev/null +++ b/arch/arm/configs/netx_defconfig @@ -0,0 +1,926 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc6 +# Tue Jun 6 15:26:53 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set +CONFIG_OBSOLETE_INTERMODULE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91RM9200 is not set +CONFIG_ARCH_NETX=y + +# +# NetX Implementations +# +CONFIG_MACH_NXDKN=y +CONFIG_MACH_NXDB500=y +CONFIG_MACH_NXEB500HMI=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_ARM_VIC=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttySMX0,115200" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +CONFIG_NET_IPGRE=m +# CONFIG_NET_IPGRE_BROADCAST is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +# CONFIG_IPV6_TUNNEL is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CONNTRACK_MARK is not set +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +# CONFIG_IP_NF_H323 is not set +CONFIG_IP_NF_QUEUE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +# CONFIG_IP6_NF_QUEUE is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +CONFIG_MTD_PLATRAM=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_SMC91X is not set +CONFIG_NET_NETX=y +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_NETX=y +CONFIG_SERIAL_NETX_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_NVRAM=m +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +CONFIG_FB_FIRMWARE_EDID=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +CONFIG_FB_ARMCLCD=y +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m + +# +# RTC drivers +# +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_NETX=m +# CONFIG_RTC_DRV_TEST is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/configs/onearm_defconfig b/arch/arm/configs/onearm_defconfig new file mode 100644 index 0000000..5401c01 --- /dev/null +++ b/arch/arm/configs/onearm_defconfig @@ -0,0 +1,1053 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-git10 +# Mon Jun 26 13:45:44 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91RM9200=y +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# AT91RM9200 Implementations +# + +# +# AT91RM9200 Board Type +# +CONFIG_MACH_ONEARM=y +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +# CONFIG_MACH_KB9200 is not set +# CONFIG_MACH_ATEB9200 is not set +# CONFIG_MACH_KAFA is not set + +# +# AT91RM9200 Feature Selections +# +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# +CONFIG_AT91_CF=y + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +# CONFIG_LEDS_CPU is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x0 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=0 +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +# CONFIG_SERIAL_AT91_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AT91_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +CONFIG_USB_DEBUG=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_AT91RM9200=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_ERRORS is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y diff --git a/arch/arm/configs/pnx4008_defconfig b/arch/arm/configs/pnx4008_defconfig new file mode 100644 index 0000000..8a078d4 --- /dev/null +++ b/arch/arm/configs/pnx4008_defconfig @@ -0,0 +1,2072 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc1 +# Thu Apr 6 17:05:58 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +CONFIG_AUDIT=y +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set +CONFIG_OBSOLETE_INTERMODULE=m + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91RM9200 is not set +CONFIG_ARCH_PNX4008=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=m +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="mem=64M console=ttyS0,115200" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_MISC=m +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +CONFIG_APM=m + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=m +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=m +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +# CONFIG_IPV6_ROUTER_PREF is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +# CONFIG_IP_NF_H323 is not set +CONFIG_IP_NF_QUEUE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m + +# +# DECnet: Netfilter Configuration +# +CONFIG_DECNET_NF_GRABULATOR=m + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +# CONFIG_BRIDGE_EBT_ULOG is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +CONFIG_ATM=y +CONFIG_ATM_CLIP=y +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +# CONFIG_DECNET_ROUTER is not set +CONFIG_LLC=m +CONFIG_LLC2=m +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=y +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_X25=m +CONFIG_LAPB=m +# CONFIG_NET_DIVERT is not set +CONFIG_ECONET=m +CONFIG_ECONET_AUNUDP=y +CONFIG_ECONET_NATIVE=y +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CLK_JIFFIES=y +# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +# CONFIG_CLS_U32_PERF is not set +# CONFIG_CLS_U32_MARK is not set +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_CLS_POLICE=y +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +CONFIG_AX25=m +# CONFIG_AX25_DAMA_SLAVE is not set +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_BAYCOM_PAR=m +CONFIG_BAYCOM_EPP=m +CONFIG_YAM=m +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +CONFIG_IRDA_DEBUG=y + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +# CONFIG_TOIM3232_DONGLE is not set +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# +CONFIG_IRPORT_SIR=m + +# +# Old Serial dongle support +# +# CONFIG_DONGLE_OLD is not set + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +# CONFIG_BT_HCIBPA10X is not set +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +# CONFIG_IEEE80211_CRYPT_WEP is not set +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +# CONFIG_IEEE80211_SOFTMAC is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PHYSMAP_LEN=0x4000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_SLRAM=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLKMTD=m +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_DOCPROBE=m +CONFIG_MTD_DOCECC=m +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_DOCPROBE_ADDRESS=0 + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +# CONFIG_MTD_NAND_NANDSIM is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_PC_FIFO=y +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_ARC is not set +# CONFIG_PARPORT_GSC is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# + +# +# Block devices +# +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +# CONFIG_PARIDE_EPATC8 is not set +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=m +CONFIG_BLK_DEV_IDE=m + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=m +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +CONFIG_BLK_DEV_IDETAPE=m +CONFIG_BLK_DEV_IDEFLOPPY=m +CONFIG_BLK_DEV_IDESCSI=m +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=m +# CONFIG_IDE_ARM is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +CONFIG_SCSI_SATA=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_DEBUG=m + +# +# PCMCIA SCSI adapter support +# +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID5=m +# CONFIG_MD_RAID5_RESHAPE is not set +CONFIG_MD_RAID6=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +# CONFIG_DM_MULTIPATH is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +CONFIG_NET_POCKET=y +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +# CONFIG_NET_WIRELESS_RTNETLINK is not set + +# +# Obsolete Wireless cards support (pre-802.11) +# +CONFIG_STRIP=m +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +CONFIG_PCMCIA_RAYCS=m + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_HERMES=m +CONFIG_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +# CONFIG_PCMCIA_SPECTRUM is not set +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m +# CONFIG_HOSTAP is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m + +# +# Wan interfaces +# +CONFIG_WAN=y +CONFIG_SYNCLINK_SYNCPPP=m +CONFIG_HDLC=m +CONFIG_HDLC_RAW=y +CONFIG_HDLC_RAW_ETH=y +CONFIG_HDLC_CISCO=y +CONFIG_HDLC_FR=y +CONFIG_HDLC_PPP=y +CONFIG_HDLC_X25=y +CONFIG_DLCI=m +CONFIG_DLCI_COUNT=24 +CONFIG_DLCI_MAX=8 +CONFIG_WAN_ROUTER_DRIVERS=y +CONFIG_LAPBETHER=m +CONFIG_X25_ASY=m + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y +CONFIG_SHAPER=m +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +CONFIG_ISDN_PPP_BSDCOMP=m +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y +CONFIG_ISDN_X25=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DRV_LOOP=m +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +# CONFIG_HISAX_NO_SENDCOMPLETE is not set +# CONFIG_HISAX_NO_LLC is not set +# CONFIG_HISAX_NO_KEYPAD is not set +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_SX=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +CONFIG_HISAX_HFCUSB=m +# CONFIG_HISAX_HFC4S8S is not set +CONFIG_HISAX_HDLC=y + +# +# Active cards +# + +# +# Siemens Gigaset +# +# CONFIG_ISDN_DRV_GIGASET is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_TSDEV=m +CONFIG_INPUT_TSDEV_SCREEN_X=240 +CONFIG_INPUT_TSDEV_SCREEN_Y=320 +CONFIG_INPUT_EVDEV=m +CONFIG_INPUT_EVBUG=m + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +# CONFIG_JOYSTICK_TWIDJOY is not set +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=m +CONFIG_SERIO_PARKBD=m +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_COMPUTONE=m +CONFIG_ROCKETPORT=m +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +CONFIG_DIGIEPCA=m +CONFIG_MOXA_INTELLIO=m +CONFIG_MOXA_SMARTIO=m +# CONFIG_ISI is not set +CONFIG_SYNCLINKMP=m +CONFIG_N_HDLC=m +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +CONFIG_SX=m +CONFIG_RIO=m +CONFIG_RIO_OLDPCI=y +CONFIG_STALDRV=y +CONFIG_STALLION=m +CONFIG_ISTALLION=m + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_PRINTER=m +# CONFIG_LP_CONSOLE is not set +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_NVRAM=m +CONFIG_DTLK=m +CONFIG_R3964=m + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +CONFIG_SYNCLINK_CS=m +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +CONFIG_RAW_DRIVER=m +CONFIG_MAX_RAW_DEVS=256 + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +CONFIG_I2C_ISA=m +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_STUB=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +# CONFIG_SENSORS_PCA9539 is not set +CONFIG_SENSORS_PCF8591=m +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m + +# +# 1-wire Bus Masters +# +# CONFIG_W1_MASTER_DS9490 is not set +# CONFIG_W1_MASTER_DS2482 is not set + +# +# 1-wire Slaves +# +# CONFIG_W1_SLAVE_THERM is not set +# CONFIG_W1_SLAVE_SMEM is not set +# CONFIG_W1_SLAVE_DS2433 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +# CONFIG_SENSORS_ADM9240 is not set +CONFIG_SENSORS_ASB100=m +# CONFIG_SENSORS_ATXP1 is not set +CONFIG_SENSORS_DS1621=m +# CONFIG_SENSORS_F71805F is not set +CONFIG_SENSORS_FSCHER=m +# CONFIG_SENSORS_FSCPOS is not set +CONFIG_SENSORS_GL518SM=m +# CONFIG_SENSORS_GL520SM is not set +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +# CONFIG_SENSORS_LM92 is not set +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SMSC47M1=m +# CONFIG_SENSORS_SMSC47B397 is not set +CONFIG_SENSORS_W83781D=m +# CONFIG_SENSORS_W83792D is not set +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported USB Adapters +# +# CONFIG_DVB_USB is not set +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +# CONFIG_DVB_B2C2_FLEXCOP is not set + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +# CONFIG_DVB_CX24123 is not set +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +# CONFIG_DVB_S5H1420 is not set + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +# CONFIG_DVB_ZL10353 is not set +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terresterial DTV) frontends +# +# CONFIG_DVB_NXT200X is not set +# CONFIG_DVB_OR51211 is not set +# CONFIG_DVB_OR51132 is not set +# CONFIG_DVB_BCM3510 is not set +# CONFIG_DVB_LGDT330X is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m + +# +# ALSA ARM devices +# + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m + +# +# PCMCIA devices +# + +# +# Open Sound System +# +CONFIG_SOUND_PRIME=m +# CONFIG_OBSOLETE_OSS_DRIVER is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +CONFIG_SOUND_TVMIXER=m + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_BANDWIDTH=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_SL811_HCD=m +# CONFIG_USB_SL811_CS is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +CONFIG_USB_KBD=m +CONFIG_USB_MOUSE=m +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +# CONFIG_USB_ACECAD is not set +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_MTOUCH=m +# CONFIG_USB_ITMTOUCH is not set +CONFIG_USB_EGALAX=m +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=m +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +CONFIG_USB_NET_ZAURUS=m +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRPRIME is not set +# CONFIG_USB_SERIAL_ANYDATA is not set +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +# CONFIG_USB_SERIAL_CP2101 is not set +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +# CONFIG_USB_SERIAL_GARMIN is not set +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=m +# CONFIG_USB_SERIAL_HP4X is not set +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +# CONFIG_USB_SERIAL_TI is not set +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_LD is not set +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +# CONFIG_USB_CXACRU is not set +# CONFIG_USB_UEAGLEATM is not set +# CONFIG_USB_XUSBATM is not set + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_AT91 is not set +CONFIG_USB_GADGET_DUMMY_HCD=y +CONFIG_USB_DUMMY_HCD=m +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_DEBUG is not set +CONFIG_JFS_STATISTICS=y +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_EXPORT=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +# CONFIG_OCFS2_FS is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_QUOTA=y +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=m +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +CONFIG_ADFS_FS=m +# CONFIG_ADFS_FS_RW is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_JFFS_FS=m +CONFIG_JFFS_FS_VERBOSE=0 +CONFIG_JFFS_PROC_FS=y +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y +CONFIG_VXFS_FS=m +CONFIG_HPFS_FS=m +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +# CONFIG_NCPFS_SMALLDOS is not set +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +CONFIG_AFS_FS=m +CONFIG_RXRPC=m +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +CONFIG_ACORN_PARTITION=y +# CONFIG_ACORN_PARTITION_CUMANA is not set +# CONFIG_ACORN_PARTITION_EESOX is not set +CONFIG_ACORN_PARTITION_ICS=y +# CONFIG_ACORN_PARTITION_ADFS is not set +# CONFIG_ACORN_PARTITION_POWERTEC is not set +CONFIG_ACORN_PARTITION_RISCIX=y +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +CONFIG_ATARI_PARTITION=y +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +CONFIG_SGI_PARTITION=y +CONFIG_ULTRIX_PARTITION=y +CONFIG_SUN_PARTITION=y +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_ERRORS is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +CONFIG_SECURITY=y +# CONFIG_SECURITY_NETWORK is not set +CONFIG_SECURITY_CAPABILITIES=m +CONFIG_SECURITY_ROOTPLUG=m +CONFIG_SECURITY_SECLVL=m + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_TEST=m + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 3cec29d..f20814e 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -1,12 +1,14 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16 -# Mon Mar 20 20:36:02 2006 +# Linux kernel version: 2.6.17-git9 +# Sun Jun 25 23:56:32 2006 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 # # Code maturity level options @@ -27,6 +29,7 @@ # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_UID16=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -42,22 +45,16 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set -CONFIG_OBSOLETE_INTERMODULE=y # # Loadable module support # CONFIG_MODULES=y # CONFIG_MODULE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y @@ -65,6 +62,7 @@ CONFIG_KMOD=y # # Block layer # +# CONFIG_BLK_DEV_IO_TRACE is not set # # IO Schedulers @@ -82,17 +80,26 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # # System Type # +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91RM9200 is not set # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set # CONFIG_ARCH_IOP3XX is not set # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set @@ -100,12 +107,6 @@ CONFIG_ARCH_S3C2410=y # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_AAEC2000 is not set -# CONFIG_ARCH_AT91RM9200 is not set # # S3C24XX Implementations @@ -116,14 +117,22 @@ CONFIG_ARCH_BAST=y CONFIG_BAST_PC104_IRQ=y CONFIG_ARCH_H1940=y CONFIG_MACH_N30=y +CONFIG_MACH_SMDK=y CONFIG_ARCH_SMDK2410=y CONFIG_ARCH_S3C2440=y +CONFIG_SMDK2440_CPU2440=y +CONFIG_SMDK2440_CPU2442=y +CONFIG_MACH_SMDK2413=y CONFIG_MACH_VR1000=y CONFIG_MACH_RX3715=y CONFIG_MACH_OTOM=y CONFIG_MACH_NEXCODER_2440=y +CONFIG_S3C2410_CLOCK=y CONFIG_CPU_S3C2410=y +CONFIG_CPU_S3C2412=y +CONFIG_CPU_S3C244X=y CONFIG_CPU_S3C2440=y +CONFIG_CPU_S3C2442=y # # S3C2410 Boot @@ -146,8 +155,11 @@ # Processor Type # CONFIG_CPU_32=y CONFIG_CPU_ARM920T=y +CONFIG_CPU_ARM926T=y CONFIG_CPU_32v4=y +CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_ABRT_EV5TJ=y CONFIG_CPU_CACHE_V4WT=y CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_COPY_V4WB=y @@ -160,6 +172,7 @@ # CONFIG_ARM_THUMB is not set # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set # # Bus support @@ -207,6 +220,7 @@ # CONFIG_FPE_NWFPE=y # CONFIG_FPE_NWFPE_XP is not set # CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set # # Userspace binary formats @@ -235,6 +249,8 @@ # # CONFIG_NETDEBUG is not set # CONFIG_PACKET is not set CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -251,12 +267,18 @@ # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # @@ -311,6 +333,7 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker @@ -360,7 +383,6 @@ # CONFIG_MTD_CFI_I4 is not set # CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_CFI_AMDSTD_RETRY=0 # CONFIG_MTD_CFI_STAA is not set CONFIG_MTD_CFI_UTIL=y # CONFIG_MTD_RAM is not set @@ -385,7 +407,6 @@ # # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set # CONFIG_MTD_BLOCK2MTD is not set # @@ -400,10 +421,12 @@ # NAND Flash Device Drivers # CONFIG_MTD_NAND=y # CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set CONFIG_MTD_NAND_IDS=y CONFIG_MTD_NAND_S3C2410=y # CONFIG_MTD_NAND_S3C2410_DEBUG is not set # CONFIG_MTD_NAND_S3C2410_HWECC is not set +# CONFIG_MTD_NAND_S3C2410_CLKSTOP is not set # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_NAND_NANDSIM is not set @@ -417,8 +440,8 @@ # Parallel port support # CONFIG_PARPORT=y # CONFIG_PARPORT_PC is not set -# CONFIG_PARPORT_ARC is not set # CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set CONFIG_PARPORT_1284=y # @@ -694,7 +717,6 @@ # USB-based Watchdog Cards # # CONFIG_USBPCWATCHDOG is not set # CONFIG_NVRAM is not set -# CONFIG_RTC is not set CONFIG_S3C2410_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -728,6 +750,7 @@ # I2C Hardware Bus support # # CONFIG_I2C_ELEKTOR is not set CONFIG_I2C_ISA=m +# CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT is not set # CONFIG_I2C_PARPORT_LIGHT is not set CONFIG_I2C_S3C2410=y @@ -743,9 +766,7 @@ CONFIG_SENSORS_EEPROM=m # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -760,13 +781,13 @@ # CONFIG_SPI_MASTER is not set # # Dallas's 1-wire bus # -# CONFIG_W1 is not set # # Hardware Monitoring support # CONFIG_HWMON=y CONFIG_HWMON_VID=m +# CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -794,8 +815,10 @@ # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set @@ -807,18 +830,29 @@ # Misc devices # # -# Multimedia Capabilities Port drivers +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers # # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support @@ -828,6 +862,8 @@ CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_MACMODES is not set +CONFIG_FB_FIRMWARE_EDID=y +# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_S1D13XXX is not set @@ -863,6 +899,7 @@ # USB support # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -915,9 +952,7 @@ # CONFIG_USB_WACOM is not set # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -931,15 +966,6 @@ # # CONFIG_USB_MDC800 is not set # -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set - -# -# Video4Linux support is needed for USB Multimedia device support -# - -# # USB Network Adapters # # CONFIG_USB_CATC is not set @@ -969,10 +995,12 @@ # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set @@ -984,17 +1012,6 @@ # # USB Gadget Support # # CONFIG_USB_GADGET is not set -# CONFIG_USB_GADGET_NET2280 is not set -# CONFIG_USB_GADGET_PXA2XX is not set -# CONFIG_USB_GADGET_GOKU is not set -# CONFIG_USB_GADGET_LH7A40X is not set -# CONFIG_USB_GADGET_OMAP is not set -# CONFIG_USB_GADGET_DUMMY_HCD is not set -# CONFIG_USB_ZERO is not set -# CONFIG_USB_ETH is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set # # MMC/SD Card support @@ -1002,6 +1019,12 @@ # # CONFIG_MMC is not set # +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# # File systems # CONFIG_EXT2_FS=y @@ -1022,6 +1045,7 @@ # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -1052,7 +1076,6 @@ CONFIG_SYSFS=y # CONFIG_TMPFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -1193,6 +1216,7 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index de606df..302fc14 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -702,7 +702,6 @@ int pci_mmap_page_range(struct pci_dev * /* * Mark this as IO */ - vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); if (remap_pfn_range(vma, vma->vm_start, phys, diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index ab8e600..86c9252 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -20,6 +20,7 @@ #include #include #include #include +#include #include "entry-header.S" @@ -560,10 +561,8 @@ ENTRY(__switch_to) add ip, r1, #TI_CPU_SAVE ldr r3, [r2, #TI_TP_VALUE] stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack -#ifndef CONFIG_MMU - add r2, r2, #TI_CPU_DOMAIN -#else - ldr r6, [r2, #TI_CPU_DOMAIN]! +#ifdef CONFIG_MMU + ldr r6, [r2, #TI_CPU_DOMAIN] #endif #if __LINUX_ARM_ARCH__ >= 6 #ifdef CONFIG_CPU_32v6K @@ -585,21 +584,20 @@ #endif #ifdef CONFIG_MMU mcr p15, 0, r6, c3, c0, 0 @ Set domain register #endif -#ifdef CONFIG_VFP - @ Always disable VFP so we can lazily save/restore the old - @ state. This occurs in the context of the previous thread. - VFPFMRX r4, FPEXC - bic r4, r4, #FPEXC_ENABLE - VFPFMXR FPEXC, r4 -#endif #if defined(CONFIG_IWMMXT) bl iwmmxt_task_switch #elif defined(CONFIG_CPU_XSCALE) - add r4, r2, #40 @ cpu_context_save->extra + add r4, r2, #TI_CPU_DOMAIN + 40 @ cpu_context_save->extra ldmib r4, {r4, r5} mar acc0, r4, r5 #endif - ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously + mov r5, r0 + add r4, r2, #TI_CPU_SAVE + ldr r0, =thread_notify_head + mov r1, #THREAD_NOTIFY_SWITCH + bl atomic_notifier_call_chain + mov r0, r5 + ldmia r4, {r4 - sl, fp, sp, pc} @ Load all regs saved previously __INIT diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index dbcb11a..75af6d6 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -271,7 +271,7 @@ #undef OBSOLETE @ r8 = syscall table .type sys_syscall, #function sys_syscall: - eor scno, r0, #__NR_OABI_SYSCALL_BASE + bic scno, r0, #__NR_OABI_SYSCALL_BASE cmp scno, #__NR_syscall - __NR_SYSCALL_BASE cmpne scno, #NR_syscalls @ check range stmloia sp, {r5, r6} @ shuffle args @@ -340,7 +340,7 @@ #if PAGE_SHIFT > 12 streq r5, [sp, #4] beq do_mmap2 mov r0, #-EINVAL - RETINSTR(mov,pc, lr) + mov pc, lr #else str r5, [sp, #4] b do_mmap2 diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index adf62e5..2af7e44 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S @@ -39,7 +39,7 @@ #include __INIT .type stext, %function ENTRY(stext) - msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode + msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode @ and irqs disabled mrc p15, 0, r9, c0, c0 @ get processor id bl __lookup_processor_type @ r5=procinfo r9=cpuid diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 04f7344..330b947 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -71,7 +71,7 @@ #endif __INIT .type stext, %function ENTRY(stext) - msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode + msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode @ and irqs disabled mrc p15, 0, r9, c0, c0 @ get processor id bl __lookup_processor_type @ r5=procinfo r9=cpuid @@ -104,7 +104,7 @@ ENTRY(secondary_startup) * the processor type - there is no need to check the machine type * as it has already been validated by the primary processor. */ - msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC + msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE mrc p15, 0, r9, c0, c0 @ get processor id bl __lookup_processor_type movs r10, r5 @ invalid processor? diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 2d5896b..ec20f89 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -52,7 +52,7 @@ #include */ #define MAX_IRQ_CNT 100000 -static int noirqdebug; +static int noirqdebug __read_mostly; static volatile unsigned long irq_err_count; static DEFINE_SPINLOCK(irq_controller_lock); static LIST_HEAD(irq_pending); @@ -81,7 +81,7 @@ irqreturn_t no_action(int irq, void *dev void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { - irq_err_count += 1; + irq_err_count++; printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); } @@ -342,10 +342,10 @@ __do_irq(unsigned int irq, struct irqact #ifdef CONFIG_NO_IDLE_HZ if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) { - write_seqlock(&xtime_lock); + spin_lock(&system_timer->dyn_tick->lock); if (system_timer->dyn_tick->state & DYN_TICK_ENABLED) system_timer->dyn_tick->handler(irq, 0, regs); - write_sequnlock(&xtime_lock); + spin_unlock(&system_timer->dyn_tick->lock); } #endif diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S index 24c7b04..a3bae95 100644 --- a/arch/arm/kernel/iwmmxt.S +++ b/arch/arm/kernel/iwmmxt.S @@ -273,7 +273,7 @@ ENTRY(iwmmxt_task_restore) * * r0 = previous task_struct pointer (must be preserved) * r1 = previous thread_info pointer - * r2 = next thread_info.cpu_domain pointer (must be preserved) + * r2 = next thread_info pointer (must be preserved) * * Called only from __switch_to with task preemption disabled. * No need to care about preserving r4 and above. @@ -285,7 +285,7 @@ ENTRY(iwmmxt_task_switch) bne 1f @ yes: block them for next task ldr r5, =concan_owner - add r6, r2, #(TI_IWMMXT_STATE - TI_CPU_DOMAIN) @ get next task Concan save area + add r6, r2, #TI_IWMMXT_STATE @ get next task Concan save area ldr r5, [r5] @ get current Concan owner teq r5, r6 @ next task owns it? movne pc, lr @ no: leave Concan disabled diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 7df6e1a..e1c77ee 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -28,10 +28,12 @@ #include #include #include #include +#include #include #include #include +#include #include #include @@ -71,8 +73,36 @@ static int __init hlt_setup(char *__unus __setup("nohlt", nohlt_setup); __setup("hlt", hlt_setup); +void arm_machine_restart(char mode) +{ + /* + * Clean and disable cache, and turn off interrupts + */ + cpu_proc_fin(); + + /* + * Tell the mm system that we are going to reboot - + * we may need it to insert some 1:1 mappings so that + * soft boot works. + */ + setup_mm_for_reboot(mode); + + /* + * Now call the architecture specific reboot code. + */ + arch_reset(mode); + + /* + * Whoops - the architecture was unable to reboot. + * Tell the user! + */ + mdelay(1000); + printk("Reboot failed -- System halted\n"); + while (1); +} + /* - * The following aren't currently used. + * Function pointers to optional machine specific functions */ void (*pm_idle)(void); EXPORT_SYMBOL(pm_idle); @@ -80,6 +110,10 @@ EXPORT_SYMBOL(pm_idle); void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); +void (*arm_pm_restart)(char str) = arm_machine_restart; +EXPORT_SYMBOL_GPL(arm_pm_restart); + + /* * This is our default idle handler. We need to disable * interrupts here to ensure we don't miss a wakeup call. @@ -151,33 +185,9 @@ void machine_power_off(void) pm_power_off(); } - void machine_restart(char * __unused) { - /* - * Clean and disable cache, and turn off interrupts - */ - cpu_proc_fin(); - - /* - * Tell the mm system that we are going to reboot - - * we may need it to insert some 1:1 mappings so that - * soft boot works. - */ - setup_mm_for_reboot(reboot_mode); - - /* - * Now call the architecture specific reboot code. - */ - arch_reset(reboot_mode); - - /* - * Whoops - the architecture was unable to reboot. - * Tell the user! - */ - mdelay(1000); - printk("Reboot failed -- System halted\n"); - while (1); + arm_pm_restart(reboot_mode); } void __show_regs(struct pt_regs *regs) @@ -329,13 +339,9 @@ void exit_thread(void) { } -static void default_fp_init(union fp_state *fp) -{ - memset(fp, 0, sizeof(union fp_state)); -} +ATOMIC_NOTIFIER_HEAD(thread_notify_head); -void (*fp_init)(union fp_state *) = default_fp_init; -EXPORT_SYMBOL(fp_init); +EXPORT_SYMBOL_GPL(thread_notify_head); void flush_thread(void) { @@ -344,22 +350,21 @@ void flush_thread(void) memset(thread->used_cp, 0, sizeof(thread->used_cp)); memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); + memset(&thread->fpstate, 0, sizeof(union fp_state)); + + thread_notify(THREAD_NOTIFY_FLUSH, thread); #if defined(CONFIG_IWMMXT) iwmmxt_task_release(thread); #endif - fp_init(&thread->fpstate); -#if defined(CONFIG_VFP) - vfp_flush_thread(&thread->vfpstate); -#endif } void release_thread(struct task_struct *dead_task) { -#if defined(CONFIG_VFP) - vfp_release_thread(&task_thread_info(dead_task)->vfpstate); -#endif + struct thread_info *thread = task_thread_info(dead_task); + + thread_notify(THREAD_NOTIFY_RELEASE, thread); #if defined(CONFIG_IWMMXT) - iwmmxt_task_release(task_thread_info(dead_task)); + iwmmxt_task_release(thread); #endif } diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index a0cd0a9..1ce05ec 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -134,17 +134,6 @@ sys_sigaction(int sig, const struct old_ #ifdef CONFIG_IWMMXT -/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */ -#define IWMMXT_STORAGE_SIZE (0x98 + 8) -#define IWMMXT_MAGIC0 0x12ef842a -#define IWMMXT_MAGIC1 0x1c07ca71 - -struct iwmmxt_sigframe { - unsigned long magic0; - unsigned long magic1; - unsigned long storage[0x98/4]; -}; - static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) { char kbuf[sizeof(*frame) + 8]; @@ -152,8 +141,8 @@ static int preserve_iwmmxt_context(struc /* the iWMMXt context must be 64 bit aligned */ kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); - kframe->magic0 = IWMMXT_MAGIC0; - kframe->magic1 = IWMMXT_MAGIC1; + kframe->magic = IWMMXT_MAGIC; + kframe->size = IWMMXT_STORAGE_SIZE; iwmmxt_task_copy(current_thread_info(), &kframe->storage); return __copy_to_user(frame, kframe, sizeof(*frame)); } @@ -167,8 +156,8 @@ static int restore_iwmmxt_context(struct kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); if (__copy_from_user(kframe, frame, sizeof(*frame))) return -1; - if (kframe->magic0 != IWMMXT_MAGIC0 || - kframe->magic1 != IWMMXT_MAGIC1) + if (kframe->magic != IWMMXT_MAGIC || + kframe->size != IWMMXT_STORAGE_SIZE) return -1; iwmmxt_task_restore(current_thread_info(), &kframe->storage); return 0; @@ -177,70 +166,61 @@ static int restore_iwmmxt_context(struct #endif /* - * Auxiliary signal frame. This saves stuff like FP state. - * The layout of this structure is not part of the user ABI. - */ -struct aux_sigframe { -#ifdef CONFIG_IWMMXT - struct iwmmxt_sigframe iwmmxt; -#endif -#ifdef CONFIG_VFP - union vfp_state vfp; -#endif -}; - -/* * Do a signal return; undo the signal stack. These are aligned to 64-bit. */ struct sigframe { - struct sigcontext sc; - unsigned long extramask[_NSIG_WORDS-1]; + struct ucontext uc; unsigned long retcode[2]; - struct aux_sigframe aux __attribute__((aligned(8))); }; struct rt_sigframe { - struct siginfo __user *pinfo; - void __user *puc; struct siginfo info; - struct ucontext uc; - unsigned long retcode[2]; - struct aux_sigframe aux __attribute__((aligned(8))); + struct sigframe sig; }; -static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, - struct aux_sigframe __user *aux) +static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) { - int err = 0; + struct aux_sigframe __user *aux; + sigset_t set; + int err; - __get_user_error(regs->ARM_r0, &sc->arm_r0, err); - __get_user_error(regs->ARM_r1, &sc->arm_r1, err); - __get_user_error(regs->ARM_r2, &sc->arm_r2, err); - __get_user_error(regs->ARM_r3, &sc->arm_r3, err); - __get_user_error(regs->ARM_r4, &sc->arm_r4, err); - __get_user_error(regs->ARM_r5, &sc->arm_r5, err); - __get_user_error(regs->ARM_r6, &sc->arm_r6, err); - __get_user_error(regs->ARM_r7, &sc->arm_r7, err); - __get_user_error(regs->ARM_r8, &sc->arm_r8, err); - __get_user_error(regs->ARM_r9, &sc->arm_r9, err); - __get_user_error(regs->ARM_r10, &sc->arm_r10, err); - __get_user_error(regs->ARM_fp, &sc->arm_fp, err); - __get_user_error(regs->ARM_ip, &sc->arm_ip, err); - __get_user_error(regs->ARM_sp, &sc->arm_sp, err); - __get_user_error(regs->ARM_lr, &sc->arm_lr, err); - __get_user_error(regs->ARM_pc, &sc->arm_pc, err); - __get_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err); + err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); + if (err == 0) { + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } + + __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); + __get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err); + __get_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err); + __get_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err); + __get_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err); + __get_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err); + __get_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err); + __get_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err); + __get_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err); + __get_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err); + __get_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err); + __get_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err); + __get_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err); + __get_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err); + __get_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err); + __get_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err); + __get_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err); err |= !valid_user_regs(regs); + aux = (struct aux_sigframe __user *) sf->uc.uc_regspace; #ifdef CONFIG_IWMMXT if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) err |= restore_iwmmxt_context(&aux->iwmmxt); #endif #ifdef CONFIG_VFP // if (err == 0) -// err |= vfp_restore_state(&aux->vfp); +// err |= vfp_restore_state(&sf->aux.vfp); #endif return err; @@ -249,7 +229,6 @@ #endif asmlinkage int sys_sigreturn(struct pt_regs *regs) { struct sigframe __user *frame; - sigset_t set; /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; @@ -266,19 +245,8 @@ asmlinkage int sys_sigreturn(struct pt_r if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) goto badframe; - if (__get_user(set.sig[0], &frame->sc.oldmask) - || (_NSIG_WORDS > 1 - && __copy_from_user(&set.sig[1], &frame->extramask, - sizeof(frame->extramask)))) - goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (restore_sigcontext(regs, &frame->sc, &frame->aux)) + if (restore_sigframe(regs, frame)) goto badframe; /* Send SIGTRAP if we're single-stepping */ @@ -297,7 +265,6 @@ badframe: asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame; - sigset_t set; /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; @@ -314,19 +281,11 @@ asmlinkage int sys_rt_sigreturn(struct p if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) goto badframe; - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) - goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &frame->aux)) + if (restore_sigframe(regs, &frame->sig)) goto badframe; - if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) + if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) goto badframe; /* Send SIGTRAP if we're single-stepping */ @@ -343,42 +302,46 @@ badframe: } static int -setup_sigcontext(struct sigcontext __user *sc, struct aux_sigframe __user *aux, - struct pt_regs *regs, unsigned long mask) +setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set) { + struct aux_sigframe __user *aux; int err = 0; - __put_user_error(regs->ARM_r0, &sc->arm_r0, err); - __put_user_error(regs->ARM_r1, &sc->arm_r1, err); - __put_user_error(regs->ARM_r2, &sc->arm_r2, err); - __put_user_error(regs->ARM_r3, &sc->arm_r3, err); - __put_user_error(regs->ARM_r4, &sc->arm_r4, err); - __put_user_error(regs->ARM_r5, &sc->arm_r5, err); - __put_user_error(regs->ARM_r6, &sc->arm_r6, err); - __put_user_error(regs->ARM_r7, &sc->arm_r7, err); - __put_user_error(regs->ARM_r8, &sc->arm_r8, err); - __put_user_error(regs->ARM_r9, &sc->arm_r9, err); - __put_user_error(regs->ARM_r10, &sc->arm_r10, err); - __put_user_error(regs->ARM_fp, &sc->arm_fp, err); - __put_user_error(regs->ARM_ip, &sc->arm_ip, err); - __put_user_error(regs->ARM_sp, &sc->arm_sp, err); - __put_user_error(regs->ARM_lr, &sc->arm_lr, err); - __put_user_error(regs->ARM_pc, &sc->arm_pc, err); - __put_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err); - - __put_user_error(current->thread.trap_no, &sc->trap_no, err); - __put_user_error(current->thread.error_code, &sc->error_code, err); - __put_user_error(current->thread.address, &sc->fault_address, err); - __put_user_error(mask, &sc->oldmask, err); - + __put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); + __put_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err); + __put_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err); + __put_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err); + __put_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err); + __put_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err); + __put_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err); + __put_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err); + __put_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err); + __put_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err); + __put_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err); + __put_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err); + __put_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err); + __put_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err); + __put_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err); + __put_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err); + __put_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err); + + __put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, err); + __put_user_error(current->thread.error_code, &sf->uc.uc_mcontext.error_code, err); + __put_user_error(current->thread.address, &sf->uc.uc_mcontext.fault_address, err); + __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err); + + err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); + + aux = (struct aux_sigframe __user *) sf->uc.uc_regspace; #ifdef CONFIG_IWMMXT if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) err |= preserve_iwmmxt_context(&aux->iwmmxt); #endif #ifdef CONFIG_VFP // if (err == 0) -// err |= vfp_save_state(&aux->vfp); +// err |= vfp_save_state(&sf->aux.vfp); #endif + __put_user_error(0, &aux->end_magic, err); return err; } @@ -487,13 +450,12 @@ setup_frame(int usig, struct k_sigaction if (!frame) return 1; - err |= setup_sigcontext(&frame->sc, &frame->aux, regs, set->sig[0]); - - if (_NSIG_WORDS > 1) { - err |= __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); - } + /* + * Set uc.uc_flags to a value which sc.trap_no would never have. + */ + __put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err); + err |= setup_sigframe(frame, regs, set); if (err == 0) err = setup_return(regs, ka, frame->retcode, frame, usig); @@ -511,25 +473,20 @@ setup_rt_frame(int usig, struct k_sigact if (!frame) return 1; - __put_user_error(&frame->info, &frame->pinfo, err); - __put_user_error(&frame->uc, &frame->puc, err); err |= copy_siginfo_to_user(&frame->info, info); - __put_user_error(0, &frame->uc.uc_flags, err); - __put_user_error(NULL, &frame->uc.uc_link, err); + __put_user_error(0, &frame->sig.uc.uc_flags, err); + __put_user_error(NULL, &frame->sig.uc.uc_link, err); memset(&stack, 0, sizeof(stack)); stack.ss_sp = (void __user *)current->sas_ss_sp; stack.ss_flags = sas_ss_flags(regs->ARM_sp); stack.ss_size = current->sas_ss_size; - err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack)); - - err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->aux, - regs, set->sig[0]); - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack)); + err |= setup_sigframe(&frame->sig, regs, set); if (err == 0) - err = setup_return(regs, ka, frame->retcode, frame, usig); + err = setup_return(regs, ka, frame->sig.retcode, frame, usig); if (err == 0) { /* @@ -538,7 +495,7 @@ setup_rt_frame(int usig, struct k_sigact * -- Peter Maydell 2000-12-06 */ regs->ARM_r1 = (unsigned long)&frame->info; - regs->ARM_r2 = (unsigned long)&frame->uc; + regs->ARM_r2 = (unsigned long)&frame->sig.uc; } return err; @@ -665,17 +622,33 @@ static int do_signal(sigset_t *oldset, s if (syscall) { if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { if (thumb_mode(regs)) { - regs->ARM_r7 = __NR_restart_syscall; + regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_pc -= 2; } else { +#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) + regs->ARM_r7 = __NR_restart_syscall; + regs->ARM_pc -= 4; +#else u32 __user *usp; + u32 swival = __NR_restart_syscall; regs->ARM_sp -= 12; usp = (u32 __user *)regs->ARM_sp; + /* + * Either we supports OABI only, or we have + * EABI with the OABI compat layer enabled. + * In the later case we don't know if user + * space is EABI or not, and if not we must + * not clobber r7. Always using the OABI + * syscall solves that issue and works for + * all those cases. + */ + swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE; + put_user(regs->ARM_pc, &usp[0]); /* swi __NR_restart_syscall */ - put_user(0xef000000 | __NR_restart_syscall, &usp[1]); + put_user(0xef000000 | swival, &usp[1]); /* ldr pc, [sp], #12 */ put_user(0xe49df00c, &usp[2]); @@ -683,6 +656,7 @@ static int do_signal(sigset_t *oldset, s (unsigned long)(usp + 3)); regs->ARM_pc = regs->ARM_sp + 4; +#endif } } if (regs->ARM_r0 == -ERESTARTNOHAND || diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index d6bd435..9c12d4f 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -379,7 +379,7 @@ static int timer_dyn_tick_enable(void) int ret = -ENODEV; if (dyn_tick) { - write_seqlock_irqsave(&xtime_lock, flags); + spin_lock_irqsave(&dyn_tick->lock, flags); ret = 0; if (!(dyn_tick->state & DYN_TICK_ENABLED)) { ret = dyn_tick->enable(); @@ -387,7 +387,7 @@ static int timer_dyn_tick_enable(void) if (ret == 0) dyn_tick->state |= DYN_TICK_ENABLED; } - write_sequnlock_irqrestore(&xtime_lock, flags); + spin_unlock_irqrestore(&dyn_tick->lock, flags); } return ret; @@ -400,7 +400,7 @@ static int timer_dyn_tick_disable(void) int ret = -ENODEV; if (dyn_tick) { - write_seqlock_irqsave(&xtime_lock, flags); + spin_lock_irqsave(&dyn_tick->lock, flags); ret = 0; if (dyn_tick->state & DYN_TICK_ENABLED) { ret = dyn_tick->disable(); @@ -408,7 +408,7 @@ static int timer_dyn_tick_disable(void) if (ret == 0) dyn_tick->state &= ~DYN_TICK_ENABLED; } - write_sequnlock_irqrestore(&xtime_lock, flags); + spin_unlock_irqrestore(&dyn_tick->lock, flags); } return ret; @@ -422,15 +422,20 @@ static int timer_dyn_tick_disable(void) void timer_dyn_reprogram(void) { struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; - unsigned long next, seq; + unsigned long next, seq, flags; - if (dyn_tick && (dyn_tick->state & DYN_TICK_ENABLED)) { + if (!dyn_tick) + return; + + spin_lock_irqsave(&dyn_tick->lock, flags); + if (dyn_tick->state & DYN_TICK_ENABLED) { next = next_timer_interrupt(); do { seq = read_seqbegin(&xtime_lock); - dyn_tick->reprogram(next_timer_interrupt() - jiffies); + dyn_tick->reprogram(next - jiffies); } while (read_seqretry(&xtime_lock, seq)); } + spin_unlock_irqrestore(&dyn_tick->lock, flags); } static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) @@ -499,5 +504,10 @@ void __init time_init(void) if (system_timer->offset == NULL) system_timer->offset = dummy_gettimeoffset; system_timer->init(); + +#ifdef CONFIG_NO_IDLE_HZ + if (system_timer->dyn_tick) + system_timer->dyn_tick->lock = SPIN_LOCK_UNLOCKED; +#endif } diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S index 16153c8..058b80d 100644 --- a/arch/arm/lib/backtrace.S +++ b/arch/arm/lib/backtrace.S @@ -41,7 +41,7 @@ #else movne r0, #0 movs frame, r0 1: moveq r0, #-2 - LOADREGS(eqfd, sp!, {r4 - r8, pc}) + ldmeqfd sp!, {r4 - r8, pc} 2: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction ldr r0, [sp], #4 @@ -85,7 +85,7 @@ #else * A zero next framepointer means we're done. */ teq next, #0 - LOADREGS(eqfd, sp!, {r4 - r8, pc}) + ldmeqfd sp!, {r4 - r8, pc} /* * The next framepointer must be above the @@ -104,7 +104,7 @@ #else 1007: ldr r0, =.Lbad mov r1, frame bl printk - LOADREGS(fd, sp!, {r4 - r8, pc}) + ldmfd sp!, {r4 - r8, pc} .ltorg .previous @@ -145,7 +145,7 @@ #define stack r6 adrne r0, .Lcr blne printk mov r0, stack - LOADREGS(fd, sp!, {instr, reg, stack, r7, r8, pc}) + ldmfd sp!, {instr, reg, stack, r7, r8, pc} .Lfp: .asciz " r%d = %08X%c" .Lcr: .asciz "\n" diff --git a/arch/arm/lib/clear_user.S b/arch/arm/lib/clear_user.S index 7ff9f83..ea435ae 100644 --- a/arch/arm/lib/clear_user.S +++ b/arch/arm/lib/clear_user.S @@ -43,10 +43,10 @@ USER( strnebt r2, [r0], #1) tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1 USER( strnebt r2, [r0], #1) mov r0, #0 - LOADREGS(fd,sp!, {r1, pc}) + ldmfd sp!, {r1, pc} .section .fixup,"ax" .align 0 -9001: LOADREGS(fd,sp!, {r0, pc}) +9001: ldmfd sp!, {r0, pc} .previous diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S index 6811796..666c99c 100644 --- a/arch/arm/lib/copy_page.S +++ b/arch/arm/lib/copy_page.S @@ -43,4 +43,4 @@ ENTRY(copy_page) bgt 1b @ 1 PLD( ldmeqia r1!, {r3, r4, ip, lr} ) PLD( beq 2b ) - LOADREGS(fd, sp!, {r4, pc}) @ 3 + ldmfd sp!, {r4, pc} @ 3 diff --git a/arch/arm/lib/csumipv6.S b/arch/arm/lib/csumipv6.S index 7065a20..9621469 100644 --- a/arch/arm/lib/csumipv6.S +++ b/arch/arm/lib/csumipv6.S @@ -28,5 +28,5 @@ ENTRY(__csum_ipv6_magic) adcs r0, r0, r3 adcs r0, r0, r2 adcs r0, r0, #0 - LOADREGS(fd, sp!, {pc}) + ldmfd sp!, {pc} diff --git a/arch/arm/lib/delay.S b/arch/arm/lib/delay.S index 9183b06..930a702 100644 --- a/arch/arm/lib/delay.S +++ b/arch/arm/lib/delay.S @@ -31,7 +31,7 @@ ENTRY(__const_udelay) @ 0 <= r0 <= 0x mov r2, r2, lsr #10 @ max = 0x00007fff mul r0, r2, r0 @ max = 2^32-1 movs r0, r0, lsr #6 - RETINSTR(moveq,pc,lr) + moveq pc, lr /* * loops = r0 * HZ * loops_per_jiffy / 1000000 @@ -43,20 +43,20 @@ ENTRY(__const_udelay) @ 0 <= r0 <= 0x ENTRY(__delay) subs r0, r0, #1 #if 0 - RETINSTR(movls,pc,lr) + movls pc, lr subs r0, r0, #1 - RETINSTR(movls,pc,lr) + movls pc, lr subs r0, r0, #1 - RETINSTR(movls,pc,lr) + movls pc, lr subs r0, r0, #1 - RETINSTR(movls,pc,lr) + movls pc, lr subs r0, r0, #1 - RETINSTR(movls,pc,lr) + movls pc, lr subs r0, r0, #1 - RETINSTR(movls,pc,lr) + movls pc, lr subs r0, r0, #1 - RETINSTR(movls,pc,lr) + movls pc, lr subs r0, r0, #1 #endif bhi __delay - RETINSTR(mov,pc,lr) + mov pc, lr diff --git a/arch/arm/lib/ecard.S b/arch/arm/lib/ecard.S index fb7b602..c55aaa2 100644 --- a/arch/arm/lib/ecard.S +++ b/arch/arm/lib/ecard.S @@ -29,7 +29,7 @@ ENTRY(ecard_loader_read) CPSR2SPSR(r0) mov lr, pc mov pc, r2 - LOADREGS(fd, sp!, {r4 - r12, pc}) + ldmfd sp!, {r4 - r12, pc} @ Purpose: call an expansion card loader to reset the card @ Proto : void read_loader(int card_base, char *loader); @@ -41,5 +41,5 @@ ENTRY(ecard_loader_reset) CPSR2SPSR(r0) mov lr, pc add pc, r1, #8 - LOADREGS(fd, sp!, {r4 - r12, pc}) + ldmfd sp!, {r4 - r12, pc} diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S index 6f8e27a..a5ca024 100644 --- a/arch/arm/lib/findbit.S +++ b/arch/arm/lib/findbit.S @@ -32,7 +32,7 @@ ENTRY(_find_first_zero_bit_le) 2: cmp r2, r1 @ any more? blo 1b 3: mov r0, r1 @ no free bits - RETINSTR(mov,pc,lr) + mov pc, lr /* * Purpose : Find next 'zero' bit @@ -66,7 +66,7 @@ ENTRY(_find_first_bit_le) 2: cmp r2, r1 @ any more? blo 1b 3: mov r0, r1 @ no free bits - RETINSTR(mov,pc,lr) + mov pc, lr /* * Purpose : Find next 'one' bit @@ -98,7 +98,7 @@ ENTRY(_find_first_zero_bit_be) 2: cmp r2, r1 @ any more? blo 1b 3: mov r0, r1 @ no free bits - RETINSTR(mov,pc,lr) + mov pc, lr ENTRY(_find_next_zero_bit_be) teq r1, #0 @@ -126,7 +126,7 @@ ENTRY(_find_first_bit_be) 2: cmp r2, r1 @ any more? blo 1b 3: mov r0, r1 @ no free bits - RETINSTR(mov,pc,lr) + mov pc, lr ENTRY(_find_next_bit_be) teq r1, #0 @@ -164,5 +164,5 @@ #else addeq r2, r2, #1 mov r0, r2 #endif - RETINSTR(mov,pc,lr) + mov pc, lr diff --git a/arch/arm/lib/io-readsb.S b/arch/arm/lib/io-readsb.S index d3d8de7..fb966ad 100644 --- a/arch/arm/lib/io-readsb.S +++ b/arch/arm/lib/io-readsb.S @@ -72,7 +72,7 @@ ENTRY(__raw_readsb) bpl .Linsb_16_lp tst r2, #15 - LOADREGS(eqfd, sp!, {r4 - r6, pc}) + ldmeqfd sp!, {r4 - r6, pc} .Linsb_no_16: tst r2, #8 beq .Linsb_no_8 @@ -109,7 +109,7 @@ ENTRY(__raw_readsb) str r3, [r1], #4 .Linsb_no_4: ands r2, r2, #3 - LOADREGS(eqfd, sp!, {r4 - r6, pc}) + ldmeqfd sp!, {r4 - r6, pc} cmp r2, #2 ldrb r3, [r0] @@ -119,4 +119,4 @@ ENTRY(__raw_readsb) ldrgtb r3, [r0] strgtb r3, [r1] - LOADREGS(fd, sp!, {r4 - r6, pc}) + ldmfd sp!, {r4 - r6, pc} diff --git a/arch/arm/lib/io-readsw-armv3.S b/arch/arm/lib/io-readsw-armv3.S index 146d47c..4ef9041 100644 --- a/arch/arm/lib/io-readsw-armv3.S +++ b/arch/arm/lib/io-readsw-armv3.S @@ -28,7 +28,7 @@ #include strb r3, [r1], #1 subs r2, r2, #1 - RETINSTR(moveq, pc, lr) + moveq pc, lr ENTRY(__raw_readsw) teq r2, #0 @ do we have to check for the zero len? @@ -69,7 +69,7 @@ ENTRY(__raw_readsw) bpl .Linsw_8_lp tst r2, #7 - LOADREGS(eqfd, sp!, {r4, r5, r6, pc}) + ldmeqfd sp!, {r4, r5, r6, pc} .Lno_insw_8: tst r2, #4 beq .Lno_insw_4 @@ -102,6 +102,6 @@ ENTRY(__raw_readsw) movne r3, r3, lsr #8 strneb r3, [r1] - LOADREGS(fd, sp!, {r4, r5, r6, pc}) + ldmfd sp!, {r4, r5, r6, pc} diff --git a/arch/arm/lib/io-writesb.S b/arch/arm/lib/io-writesb.S index 08209fc..7eba2b6 100644 --- a/arch/arm/lib/io-writesb.S +++ b/arch/arm/lib/io-writesb.S @@ -64,7 +64,7 @@ ENTRY(__raw_writesb) bpl .Loutsb_16_lp tst r2, #15 - LOADREGS(eqfd, sp!, {r4, r5, pc}) + ldmeqfd sp!, {r4, r5, pc} .Loutsb_no_16: tst r2, #8 beq .Loutsb_no_8 @@ -80,7 +80,7 @@ ENTRY(__raw_writesb) outword r3 .Loutsb_no_4: ands r2, r2, #3 - LOADREGS(eqfd, sp!, {r4, r5, pc}) + ldmeqfd sp!, {r4, r5, pc} cmp r2, #2 ldrb r3, [r1], #1 @@ -90,4 +90,4 @@ ENTRY(__raw_writesb) ldrgtb r3, [r1] strgtb r3, [r0] - LOADREGS(fd, sp!, {r4, r5, pc}) + ldmfd sp!, {r4, r5, pc} diff --git a/arch/arm/lib/io-writesw-armv3.S b/arch/arm/lib/io-writesw-armv3.S index 52d62b4..1607a29 100644 --- a/arch/arm/lib/io-writesw-armv3.S +++ b/arch/arm/lib/io-writesw-armv3.S @@ -29,7 +29,7 @@ #include orr r3, r3, r3, lsl #16 str r3, [r0] subs r2, r2, #1 - RETINSTR(moveq, pc, lr) + moveq pc, lr ENTRY(__raw_writesw) teq r2, #0 @ do we have to check for the zero len? @@ -80,7 +80,7 @@ ENTRY(__raw_writesw) bpl .Loutsw_8_lp tst r2, #7 - LOADREGS(eqfd, sp!, {r4, r5, r6, pc}) + ldmeqfd sp!, {r4, r5, r6, pc} .Lno_outsw_8: tst r2, #4 beq .Lno_outsw_4 @@ -124,4 +124,4 @@ ENTRY(__raw_writesw) orrne ip, ip, ip, lsr #16 strne ip, [r0] - LOADREGS(fd, sp!, {r4, r5, r6, pc}) + ldmfd sp!, {r4, r5, r6, pc} diff --git a/arch/arm/lib/memchr.S b/arch/arm/lib/memchr.S index ac34fe5..e7ab1ea 100644 --- a/arch/arm/lib/memchr.S +++ b/arch/arm/lib/memchr.S @@ -22,4 +22,4 @@ ENTRY(memchr) bne 1b sub r0, r0, #1 2: movne r0, #0 - RETINSTR(mov,pc,lr) + mov pc, lr diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index a1795f5..95b110b 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S @@ -53,7 +53,7 @@ ENTRY(memset) stmgeia r0!, {r1, r3, ip, lr} stmgeia r0!, {r1, r3, ip, lr} bgt 2b - LOADREGS(eqfd, sp!, {pc}) @ Now <64 bytes to go. + ldmeqfd sp!, {pc} @ Now <64 bytes to go. /* * No need to correct the count; we're only testing bits from now on */ @@ -77,4 +77,4 @@ ENTRY(memset) strneb r1, [r0], #1 tst r2, #1 strneb r1, [r0], #1 - RETINSTR(mov,pc,lr) + mov pc, lr diff --git a/arch/arm/lib/memzero.S b/arch/arm/lib/memzero.S index 51ccc60..abf2508 100644 --- a/arch/arm/lib/memzero.S +++ b/arch/arm/lib/memzero.S @@ -53,7 +53,7 @@ ENTRY(__memzero) stmgeia r0!, {r2, r3, ip, lr} @ 4 stmgeia r0!, {r2, r3, ip, lr} @ 4 bgt 3b @ 1 - LOADREGS(eqfd, sp!, {pc}) @ 1/2 quick exit + ldmeqfd sp!, {pc} @ 1/2 quick exit /* * No need to correct the count; we're only testing bits from now on */ @@ -77,4 +77,4 @@ ENTRY(__memzero) strneb r2, [r0], #1 @ 1 tst r1, #1 @ 1 a byte left over strneb r2, [r0], #1 @ 1 - RETINSTR(mov,pc,lr) @ 1 + mov pc, lr @ 1 diff --git a/arch/arm/lib/strchr.S b/arch/arm/lib/strchr.S index 5b9b493..9f18d6f 100644 --- a/arch/arm/lib/strchr.S +++ b/arch/arm/lib/strchr.S @@ -23,4 +23,4 @@ ENTRY(strchr) teq r2, r1 movne r0, #0 subeq r0, r0, #1 - RETINSTR(mov,pc,lr) + mov pc, lr diff --git a/arch/arm/lib/strncpy_from_user.S b/arch/arm/lib/strncpy_from_user.S index 629cc87..35649f0 100644 --- a/arch/arm/lib/strncpy_from_user.S +++ b/arch/arm/lib/strncpy_from_user.S @@ -21,7 +21,6 @@ #include * -EFAULT on exception, or "len" if we fill the whole buffer */ ENTRY(__arch_strncpy_from_user) - save_lr mov ip, r1 1: subs r2, r2, #1 USER( ldrplbt r3, [r1], #1) @@ -31,13 +30,13 @@ USER( ldrplbt r3, [r1], #1) bne 1b sub r1, r1, #1 @ take NUL character out of count 2: sub r0, r1, ip - restore_pc + mov pc, lr .section .fixup,"ax" .align 0 9001: mov r3, #0 strb r3, [r0, #0] @ null terminate mov r0, #-EFAULT - restore_pc + mov pc, lr .previous diff --git a/arch/arm/lib/strnlen_user.S b/arch/arm/lib/strnlen_user.S index 67bcd82..3668a15 100644 --- a/arch/arm/lib/strnlen_user.S +++ b/arch/arm/lib/strnlen_user.S @@ -21,7 +21,6 @@ #include * or zero on exception, or n + 1 if too long */ ENTRY(__arch_strnlen_user) - save_lr mov r2, r0 1: USER( ldrbt r3, [r0], #1) @@ -31,10 +30,10 @@ USER( ldrbt r3, [r0], #1) bne 1b add r0, r0, #1 2: sub r0, r0, r2 - restore_pc + mov pc, lr .section .fixup,"ax" .align 0 9001: mov r0, #0 - restore_pc + mov pc, lr .previous diff --git a/arch/arm/lib/strrchr.S b/arch/arm/lib/strrchr.S index fa923f0..538df22 100644 --- a/arch/arm/lib/strrchr.S +++ b/arch/arm/lib/strrchr.S @@ -22,4 +22,4 @@ ENTRY(strrchr) teq r2, #0 bne 1b mov r0, r3 - RETINSTR(mov,pc,lr) + mov pc, lr diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S index 0cc450f..1f1545d 100644 --- a/arch/arm/lib/uaccess.S +++ b/arch/arm/lib/uaccess.S @@ -105,7 +105,7 @@ USER( strgtbt r3, [r0], #1) @ May fau movs ip, r2 bne .Lc2u_nowords .Lc2u_finished: mov r0, #0 - LOADREGS(fd,sp!,{r2, r4 - r7, pc}) + ldmfd sp!, {r2, r4 - r7, pc} .Lc2u_src_not_aligned: bic r1, r1, #3 @@ -280,7 +280,7 @@ USER( strgtbt r3, [r0], #1) @ May fau .section .fixup,"ax" .align 0 -9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc}) +9001: ldmfd sp!, {r0, r4 - r7, pc} .previous /* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n); @@ -369,7 +369,7 @@ USER( ldrgtbt r3, [r1], #1) @ May fau bne .Lcfu_nowords .Lcfu_finished: mov r0, #0 add sp, sp, #8 - LOADREGS(fd,sp!,{r4 - r7, pc}) + ldmfd sp!, {r4 - r7, pc} .Lcfu_src_not_aligned: bic r1, r1, #3 @@ -556,6 +556,6 @@ USER( ldrgtbt r3, [r1], #1) @ May fau movne r1, r4 blne __memzero mov r0, r4 - LOADREGS(fd,sp!, {r4 - r7, pc}) + ldmfd sp!, {r4 - r7, pc} .previous diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig index 4b7218f..70d402f 100644 --- a/arch/arm/mach-at91rm9200/Kconfig +++ b/arch/arm/mach-at91rm9200/Kconfig @@ -4,6 +4,12 @@ menu "AT91RM9200 Implementations" comment "AT91RM9200 Board Type" +config MACH_ONEARM + bool "Ajeco 1ARM Single Board Computer" + depends on ARCH_AT91RM9200 + help + Select this if you are using Ajeco's 1ARM Single Board Computer + config ARCH_AT91RM9200DK bool "Atmel AT91RM9200-DK Development board" depends on ARCH_AT91RM9200 @@ -40,6 +46,18 @@ config MACH_KB9200 help Select this if you are using KwikByte's KB920x board +config MACH_ATEB9200 + bool "Embest's ATEB9200" + depends on ARCH_AT91RM9200 + help + Select this if you are using Embest's ATEB9200 board + +config MACH_KAFA + bool "Sperry-Sun KAFA board" + depends on ARCH_AT91RM9200 + help + Select this if you are using Sperry-Sun's KAFA board + comment "AT91RM9200 Feature Selections" diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index ef88c41..82db957 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -7,22 +7,32 @@ obj-m := obj-n := obj- := +obj-$(CONFIG_PM) += pm.o + # Board-specific support +obj-$(CONFIG_MACH_ONEARM) += board-1arm.o obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o obj-$(CONFIG_MACH_CSB337) += board-csb337.o obj-$(CONFIG_MACH_CSB637) += board-csb637.o -#obj-$(CONFIG_MACH_CARMEVA) += board-carmeva.o -#obj-$(CONFIG_MACH_KB9200) += board-kb9202.o +obj-$(CONFIG_MACH_CARMEVA) += board-carmeva.o +obj-$(CONFIG_MACH_KB9200) += board-kb9202.o +obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o +obj-$(CONFIG_MACH_KAFA) += board-kafa.o # LEDs support led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o led-$(CONFIG_MACH_AT91RM9200EK) += leds.o led-$(CONFIG_MACH_CSB337) += leds.o led-$(CONFIG_MACH_CSB637) += leds.o -#led-$(CONFIG_MACH_KB9200) += leds.o -#led-$(CONFIG_MACH_KAFA) += leds.o +led-$(CONFIG_MACH_KB9200) += leds.o +led-$(CONFIG_MACH_KAFA) += leds.o obj-$(CONFIG_LEDS) += $(led-y) # VGA support #obj-$(CONFIG_FB_S1D13XXX) += ics1523.o + + +ifeq ($(CONFIG_PM_DEBUG),y) +CFLAGS_pm.o += -DDEBUG +endif diff --git a/arch/arm/mach-at91rm9200/board-1arm.c b/arch/arm/mach-at91rm9200/board-1arm.c new file mode 100644 index 0000000..dc79e09 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-1arm.c @@ -0,0 +1,109 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-1arm.c + * + * Copyright (C) 2005 SAN People + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + +static void __init onearm_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(PQFP_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata onearm_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 3, + .tty_map = { 4, 0, 1, -1, -1 }, /* ttyS0, ..., ttyS4 */ +}; + +static void __init onearm_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 18.432 MHz crystal */ + at91_clock_init(18432000); + + /* Setup the serial ports and console */ + at91_init_serial(&onearm_uart_config); +} + +static struct at91_eth_data __initdata onearm_eth_data = { + .phy_irq_pin = AT91_PIN_PC4, + .is_rmii = 1, +}; + +static struct at91_usbh_data __initdata onearm_usbh_data = { + .ports = 1, +}; + +static struct at91_udc_data __initdata onearm_udc_data = { + .vbus_pin = AT91_PIN_PC2, + .pullup_pin = AT91_PIN_PC3, +}; + +static void __init onearm_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&onearm_eth_data); + /* USB Host */ + at91_add_device_usbh(&onearm_usbh_data); + /* USB Device */ + at91_add_device_udc(&onearm_udc_data); +} + +MACHINE_START(ONEARM, "Ajeco 1ARM single board computer") + /* Maintainer: Lennert Buytenhek */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = onearm_map_io, + .init_irq = onearm_init_irq, + .init_machine = onearm_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c new file mode 100644 index 0000000..2c138b5 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-carmeva.c @@ -0,0 +1,131 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-carmeva.c + * + * Copyright (c) 2005 Peer Georgi + * Conitec Datasystems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + +static void __init carmeva_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(BGA_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata carmeva_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init carmeva_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 20.000 MHz crystal */ + at91_clock_init(20000000); + + /* Setup the serial ports and console */ + at91_init_serial(&carmeva_uart_config); +} + +static struct at91_eth_data __initdata carmeva_eth_data = { + .phy_irq_pin = AT91_PIN_PC4, + .is_rmii = 1, +}; + +static struct at91_usbh_data __initdata carmeva_usbh_data = { + .ports = 2, +}; + +static struct at91_udc_data __initdata carmeva_udc_data = { + .vbus_pin = AT91_PIN_PD12, + .pullup_pin = AT91_PIN_PD9, +}; + +/* FIXME: user dependend */ +// static struct at91_cf_data __initdata carmeva_cf_data = { +// .det_pin = AT91_PIN_PB0, +// .rst_pin = AT91_PIN_PC5, + // .irq_pin = ... not connected + // .vcc_pin = ... always powered +// }; + +static struct at91_mmc_data __initdata carmeva_mmc_data = { + .is_b = 0, + .wire4 = 1, +}; + +static void __init carmeva_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&carmeva_eth_data); + /* USB Host */ + at91_add_device_usbh(&carmeva_usbh_data); + /* USB Device */ + at91_add_device_udc(&carmeva_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* Compact Flash */ +// at91_add_device_cf(&carmeva_cf_data); + /* SPI */ +// at91_add_device_spi(NULL, 0); + /* MMC */ + at91_add_device_mmc(&carmeva_mmc_data); +} + +MACHINE_START(CARMEVA, "Carmeva") + /* Maintainer: Conitec Datasystems */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = carmeva_map_io, + .init_irq = carmeva_init_irq, + .init_machine = carmeva_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c index f45104c..e94645d 100644 --- a/arch/arm/mach-at91rm9200/board-csb337.c +++ b/arch/arm/mach-at91rm9200/board-csb337.c @@ -24,6 +24,7 @@ #include #include #include #include +#include #include #include @@ -34,9 +35,9 @@ #include #include #include -#include -#include +#include #include +#include #include "generic.h" @@ -54,32 +55,24 @@ static void __init csb337_init_irq(void) * 0 .. 3 = USART0 .. USART3 * 4 = DBGU */ -#define CSB337_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ -#define CSB337_SERIAL_CONSOLE 0 /* ttyS0 */ +static struct at91_uart_config __initdata csb337_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; static void __init csb337_map_io(void) { - int serial[AT91_NR_UART] = CSB337_UART_MAP; - int i; - at91rm9200_map_io(); /* Initialize clocks: 3.6864 MHz crystal */ at91_clock_init(3686400); /* Setup the LEDs */ - at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); - -#ifdef CONFIG_SERIAL_AT91 - at91_console_port = CSB337_SERIAL_CONSOLE; - memcpy(at91_serial_map, serial, sizeof(serial)); - - /* Register UARTs */ - for (i = 0; i < AT91_NR_UART; i++) { - if (serial[i] >= 0) - at91_register_uart(i, serial[i]); - } -#endif + at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1); + + /* Setup the serial ports and console */ + at91_init_serial(&csb337_uart_config); } static struct at91_eth_data __initdata csb337_eth_data = { @@ -118,17 +111,31 @@ static struct at91_mmc_data __initdata c .wp_pin = AT91_PIN_PD6, }; +static struct spi_board_info csb337_spi_devices[] = { + { /* CAN controller */ + .modalias = "sak82c900", + .chip_select = 0, + .max_speed_hz = 6 * 1000 * 1000, + }, +}; + static void __init csb337_board_init(void) { + /* Serial */ + at91_add_device_serial(); /* Ethernet */ at91_add_device_eth(&csb337_eth_data); /* USB Host */ at91_add_device_usbh(&csb337_usbh_data); /* USB Device */ at91_add_device_udc(&csb337_udc_data); + /* I2C */ + at91_add_device_i2c(); /* Compact Flash */ at91_set_gpio_input(AT91_PIN_PB22, 1); /* IOIS16 */ at91_add_device_cf(&csb337_cf_data); + /* SPI */ + at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices)); /* MMC */ at91_add_device_mmc(&csb337_mmc_data); } diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c index f2c2d6e..67d5f77 100644 --- a/arch/arm/mach-at91rm9200/board-csb637.c +++ b/arch/arm/mach-at91rm9200/board-csb637.c @@ -34,9 +34,9 @@ #include #include #include -#include -#include +#include #include +#include #include "generic.h" @@ -54,14 +54,14 @@ static void __init csb637_init_irq(void) * 0 .. 3 = USART0 .. USART3 * 4 = DBGU */ -#define CSB637_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ -#define CSB637_SERIAL_CONSOLE 0 /* ttyS0 */ +static struct at91_uart_config __initdata csb637_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; static void __init csb637_map_io(void) { - int serial[AT91_NR_UART] = CSB637_UART_MAP; - int i; - at91rm9200_map_io(); /* Initialize clocks: 3.6864 MHz crystal */ @@ -70,16 +70,8 @@ static void __init csb637_map_io(void) /* Setup the LEDs */ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); -#ifdef CONFIG_SERIAL_AT91 - at91_console_port = CSB637_SERIAL_CONSOLE; - memcpy(at91_serial_map, serial, sizeof(serial)); - - /* Register UARTs */ - for (i = 0; i < AT91_NR_UART; i++) { - if (serial[i] >= 0) - at91_register_uart(i, serial[i]); - } -#endif + /* Setup the serial ports and console */ + at91_init_serial(&csb637_uart_config); } static struct at91_eth_data __initdata csb637_eth_data = { @@ -98,12 +90,18 @@ static struct at91_udc_data __initdata c static void __init csb637_board_init(void) { + /* Serial */ + at91_add_device_serial(); /* Ethernet */ at91_add_device_eth(&csb637_eth_data); /* USB Host */ at91_add_device_usbh(&csb637_usbh_data); /* USB Device */ at91_add_device_udc(&csb637_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(NULL, 0); } MACHINE_START(CSB637, "Cogent CSB637") diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c index 2d7200e..48d7390 100644 --- a/arch/arm/mach-at91rm9200/board-dk.c +++ b/arch/arm/mach-at91rm9200/board-dk.c @@ -27,6 +27,7 @@ #include #include #include #include +#include #include #include @@ -37,9 +38,9 @@ #include #include #include -#include -#include +#include #include +#include #include "generic.h" @@ -57,14 +58,14 @@ static void __init dk_init_irq(void) * 0 .. 3 = USART0 .. USART3 * 4 = DBGU */ -#define DK_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ -#define DK_SERIAL_CONSOLE 0 /* ttyS0 */ +static struct at91_uart_config __initdata dk_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; static void __init dk_map_io(void) { - int serial[AT91_NR_UART] = DK_UART_MAP; - int i; - at91rm9200_map_io(); /* Initialize clocks: 18.432 MHz crystal */ @@ -73,16 +74,8 @@ static void __init dk_map_io(void) /* Setup the LEDs */ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); -#ifdef CONFIG_SERIAL_AT91 - at91_console_port = DK_SERIAL_CONSOLE; - memcpy(at91_serial_map, serial, sizeof(serial)); - - /* Register UARTs */ - for (i = 0; i < AT91_NR_UART; i++) { - if (at91_serial_map[i] >= 0) - at91_register_uart(i, at91_serial_map[i]); - } -#endif + /* Setup the serial ports and console */ + at91_init_serial(&dk_uart_config); } static struct at91_eth_data __initdata dk_eth_data = { @@ -111,16 +104,48 @@ static struct at91_mmc_data __initdata d .wire4 = 1, }; +static struct spi_board_info dk_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + }, + { /* UR6HCPS2-SP40 PS2-to-SPI adapter */ + .modalias = "ur6hcps2", + .chip_select = 1, + .max_speed_hz = 250 * 1000, + }, + { /* TLV1504 ADC, 4 channels, 10 bits; one is a temp sensor */ + .modalias = "tlv1504", + .chip_select = 2, + .max_speed_hz = 20 * 1000 * 1000, + }, +#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD + { /* DataFlash card */ + .modalias = "mtd_dataflash", + .chip_select = 3, + .max_speed_hz = 15 * 1000 * 1000, + } +#endif +}; + static void __init dk_board_init(void) { + /* Serial */ + at91_add_device_serial(); /* Ethernet */ at91_add_device_eth(&dk_eth_data); /* USB Host */ at91_add_device_usbh(&dk_usbh_data); /* USB Device */ at91_add_device_udc(&dk_udc_data); + at91_set_multi_drive(dk_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */ /* Compact Flash */ at91_add_device_cf(&dk_cf_data); + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(dk_spi_devices, ARRAY_SIZE(dk_spi_devices)); #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD /* DataFlash card */ at91_set_gpio_output(AT91_PIN_PB7, 0); diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c new file mode 100644 index 0000000..a3e2df9 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-eb9200.c @@ -0,0 +1,130 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-eb9200.c + * + * Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest + * by Andrew Patrikalakis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + +static void __init eb9200_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(BGA_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata eb9200_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init eb9200_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 18.432 MHz crystal */ + at91_clock_init(18432000); + + /* Setup the serial ports and console */ + at91_init_serial(&eb9200_uart_config); +} + +static struct at91_eth_data __initdata eb9200_eth_data = { + .phy_irq_pin = AT91_PIN_PC4, + .is_rmii = 1, +}; + +static struct at91_usbh_data __initdata eb9200_usbh_data = { + .ports = 2, +}; + +static struct at91_udc_data __initdata eb9200_udc_data = { + .vbus_pin = AT91_PIN_PD4, + .pullup_pin = AT91_PIN_PD5, +}; + +static struct at91_cf_data __initdata eb9200_cf_data = { + .det_pin = AT91_PIN_PB0, + .rst_pin = AT91_PIN_PC5, + // .irq_pin = ... not connected + // .vcc_pin = ... always powered +}; + +static struct at91_mmc_data __initdata eb9200_mmc_data = { + .is_b = 0, + .wire4 = 1, +}; + +static void __init eb9200_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&eb9200_eth_data); + /* USB Host */ + at91_add_device_usbh(&eb9200_usbh_data); + /* USB Device */ + at91_add_device_udc(&eb9200_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* Compact Flash */ + at91_add_device_cf(&eb9200_cf_data); + /* SPI */ + at91_add_device_spi(NULL, 0); + /* MMC */ + /* only supports 1 or 4 bit interface, not wired through to SPI */ + at91_add_device_mmc(&eb9200_mmc_data); +} + +MACHINE_START(ATEB9200, "Embest ATEB9200") + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = eb9200_map_io, + .init_irq = eb9200_init_irq, + .init_machine = eb9200_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c index 80d90f5..72202ed 100644 --- a/arch/arm/mach-at91rm9200/board-ek.c +++ b/arch/arm/mach-at91rm9200/board-ek.c @@ -27,6 +27,7 @@ #include #include #include #include +#include #include #include @@ -37,9 +38,9 @@ #include #include #include -#include -#include +#include #include +#include #include "generic.h" @@ -57,14 +58,14 @@ static void __init ek_init_irq(void) * 0 .. 3 = USART0 .. USART3 * 4 = DBGU */ -#define EK_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ -#define EK_SERIAL_CONSOLE 0 /* ttyS0 */ +static struct at91_uart_config __initdata ek_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; static void __init ek_map_io(void) { - int serial[AT91_NR_UART] = EK_UART_MAP; - int i; - at91rm9200_map_io(); /* Initialize clocks: 18.432 MHz crystal */ @@ -73,16 +74,8 @@ static void __init ek_map_io(void) /* Setup the LEDs */ at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2); -#ifdef CONFIG_SERIAL_AT91 - at91_console_port = EK_SERIAL_CONSOLE; - memcpy(at91_serial_map, serial, sizeof(serial)); - - /* Register UARTs */ - for (i = 0; i < AT91_NR_UART; i++) { - if (serial[i] >= 0) - at91_register_uart(i, serial[i]); - } -#endif + /* Setup the serial ports and console */ + at91_init_serial(&ek_uart_config); } static struct at91_eth_data __initdata ek_eth_data = { @@ -106,14 +99,36 @@ static struct at91_mmc_data __initdata e .wp_pin = AT91_PIN_PA17, }; +static struct spi_board_info ek_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + }, +#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD + { /* DataFlash card */ + .modalias = "mtd_dataflash", + .chip_select = 3, + .max_speed_hz = 15 * 1000 * 1000, + }, +#endif +}; + static void __init ek_board_init(void) { + /* Serial */ + at91_add_device_serial(); /* Ethernet */ at91_add_device_eth(&ek_eth_data); /* USB Host */ at91_add_device_usbh(&ek_usbh_data); /* USB Device */ at91_add_device_udc(&ek_udc_data); + at91_set_multi_drive(ek_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */ + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD /* DataFlash card */ at91_set_gpio_output(AT91_PIN_PB22, 0); diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c new file mode 100644 index 0000000..bf760c5 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-kafa.c @@ -0,0 +1,116 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-kafa.c + * + * Copyright (C) 2006 Sperry-Sun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + +static void __init kafa_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(PQFP_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata kafa_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 0, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init kafa_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 18.432 MHz crystal */ + at91_clock_init(18432000); + + /* Set up the LEDs */ + at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4); + + /* Setup the serial ports and console */ + at91_init_serial(&kafa_uart_config); +} + +static struct at91_eth_data __initdata kafa_eth_data = { + .phy_irq_pin = AT91_PIN_PC4, + .is_rmii = 0, +}; + +static struct at91_usbh_data __initdata kafa_usbh_data = { + .ports = 1, +}; + +static struct at91_udc_data __initdata kafa_udc_data = { + .vbus_pin = AT91_PIN_PB6, + .pullup_pin = AT91_PIN_PB7, +}; + +static void __init kafa_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&kafa_eth_data); + /* USB Host */ + at91_add_device_usbh(&kafa_usbh_data); + /* USB Device */ + at91_add_device_udc(&kafa_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(NULL, 0); +} + +MACHINE_START(KAFA, "Sperry-Sun KAFA") + /* Maintainer: Sergei Sharonov */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = kafa_map_io, + .init_irq = kafa_init_irq, + .init_machine = kafa_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c new file mode 100644 index 0000000..f06d2b5 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-kb9202.c @@ -0,0 +1,125 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-kb9202.c + * + * Copyright (c) 2005 kb_admin + * KwikByte, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + +static void __init kb9202_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(PQFP_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata kb9202_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 3, + .tty_map = { 4, 0, 1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init kb9202_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 10 MHz crystal */ + at91_clock_init(10000000); + + /* Set up the LEDs */ + at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18); + + /* Setup the serial ports and console */ + at91_init_serial(&kb9202_uart_config); +} + +static struct at91_eth_data __initdata kb9202_eth_data = { + .phy_irq_pin = AT91_PIN_PB29, + .is_rmii = 0, +}; + +static struct at91_usbh_data __initdata kb9202_usbh_data = { + .ports = 1, +}; + +static struct at91_udc_data __initdata kb9202_udc_data = { + .vbus_pin = AT91_PIN_PB24, + .pullup_pin = AT91_PIN_PB22, +}; + +static struct at91_mmc_data __initdata kb9202_mmc_data = { + .det_pin = AT91_PIN_PB2, + .is_b = 0, + .wire4 = 1, +}; + +static void __init kb9202_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&kb9202_eth_data); + /* USB Host */ + at91_add_device_usbh(&kb9202_usbh_data); + /* USB Device */ + at91_add_device_udc(&kb9202_udc_data); + /* MMC */ + at91_add_device_mmc(&kb9202_mmc_data); + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(NULL, 0); +} + +MACHINE_START(KB9200, "KB920x") + /* Maintainer: KwikByte, Inc. */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = kb9202_map_io, + .init_irq = kb9202_init_irq, + .init_machine = kb9202_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index 8b95467..edc2cc8 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c @@ -27,12 +27,10 @@ #include #include #include -#include -#include /* for master clock global */ +#include #include "generic.h" -#undef DEBUG /* * There's a lot more which can be done with clocks, including cpufreq @@ -41,7 +39,9 @@ #undef DEBUG */ struct clk { - const char *name; + const char *name; /* unique clock name */ + const char *function; /* function of the clock */ + struct device *dev; /* device associated with function */ unsigned long rate_hz; struct clk *parent; u32 pmc_mask; @@ -71,15 +71,14 @@ static struct clk clk32k = { }; static struct clk main_clk = { .name = "main", - .pmc_mask = 1 << 0, /* in PMC_SR */ - .users = 1, + .pmc_mask = AT91_PMC_MOSCS, /* in PMC_SR */ .id = 1, .primary = 1, }; static struct clk plla = { .name = "plla", .parent = &main_clk, - .pmc_mask = 1 << 1, /* in PMC_SR */ + .pmc_mask = AT91_PMC_LOCKA, /* in PMC_SR */ .id = 2, .primary = 1, .pll = 1, @@ -105,7 +104,7 @@ static void pllb_mode(struct clk *clk, i static struct clk pllb = { .name = "pllb", .parent = &main_clk, - .pmc_mask = 1 << 2, /* in PMC_SR */ + .pmc_mask = AT91_PMC_LOCKB, /* in PMC_SR */ .mode = pllb_mode, .id = 3, .primary = 1, @@ -177,8 +176,7 @@ #endif /* CONFIG_AT91_PROGRAMMABLE_CLOCK */ static struct clk mck = { .name = "mck", - .pmc_mask = 1 << 3, /* in PMC_SR */ - .users = 1, /* (must be) always on */ + .pmc_mask = AT91_PMC_MCKRDY, /* in PMC_SR */ }; static void pmc_periph_mode(struct clk *clk, int is_on) @@ -249,6 +247,30 @@ static struct clk spi_clk = { .pmc_mask = 1 << AT91_ID_SPI, .mode = pmc_periph_mode, }; +static struct clk pioA_clk = { + .name = "pioA_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOA, + .mode = pmc_periph_mode, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOB, + .mode = pmc_periph_mode, +}; +static struct clk pioC_clk = { + .name = "pioC_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOC, + .mode = pmc_periph_mode, +}; +static struct clk pioD_clk = { + .name = "pioD_clk", + .parent = &mck, + .pmc_mask = 1 << AT91_ID_PIOD, + .mode = pmc_periph_mode, +}; static struct clk *const clock_list[] = { /* four primary clocks -- MUST BE FIRST! */ @@ -279,21 +301,46 @@ #endif /* CONFIG_AT91_PROGRAMMABLE_CLOCK &udc_clk, &twi_clk, &spi_clk, + &pioA_clk, + &pioB_clk, + &pioC_clk, + &pioD_clk, // ssc0..ssc2 // tc0..tc5 + // irq0..irq6 &ohci_clk, ðer_clk, }; +/* + * Associate a particular clock with a function (eg, "uart") and device. + * The drivers can then request the same 'function' with several different + * devices and not care about which clock name to use. + */ +void __init at91_clock_associate(const char *id, struct device *dev, const char *func) +{ + struct clk *clk = clk_get(NULL, id); + + if (!dev || !clk || !IS_ERR(clk_get(dev, func))) + return; + + clk->function = func; + clk->dev = dev; +} + /* clocks are all static for now; no refcounting necessary */ struct clk *clk_get(struct device *dev, const char *id) { int i; for (i = 0; i < ARRAY_SIZE(clock_list); i++) { - if (strcmp(id, clock_list[i]->name) == 0) - return clock_list[i]; + struct clk *clk = clock_list[i]; + + if (strcmp(id, clk->name) == 0) + return clk; + if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0) + return clk; } return ERR_PTR(-ENOENT); @@ -593,6 +640,30 @@ fail: return 0; } + +/* + * Several unused clocks may be active. Turn them off. + */ +static void at91_periphclk_reset(void) +{ + unsigned long reg; + int i; + + reg = at91_sys_read(AT91_PMC_PCSR); + + for (i = 0; i < ARRAY_SIZE(clock_list); i++) { + struct clk *clk = clock_list[i]; + + if (clk->mode != pmc_periph_mode) + continue; + + if (clk->users > 0) + reg &= ~clk->pmc_mask; + } + + at91_sys_write(AT91_PMC_PCDR, reg); +} + int __init at91_clock_init(unsigned long main_clock) { unsigned tmp, freq, mckr; @@ -626,7 +697,6 @@ int __init at91_clock_init(unsigned long */ at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M; pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); - at91_sys_write(AT91_PMC_PCDR, (1 << AT91_ID_UHP) | (1 << AT91_ID_UDP)); at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP); at91_sys_write(AT91_CKGR_PLLBR, 0); at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP); @@ -640,19 +710,18 @@ int __init at91_clock_init(unsigned long */ mckr = at91_sys_read(AT91_PMC_MCKR); mck.parent = clock_list[mckr & AT91_PMC_CSS]; - mck.parent->users++; freq = mck.parent->rate_hz; freq /= (1 << ((mckr >> 2) & 3)); /* prescale */ mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */ + /* MCK and CPU clock are "always on" */ + clk_enable(&mck); + printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n", freq / 1000000, (unsigned) mck.rate_hz / 1000000, (unsigned) main_clock / 1000000, ((unsigned) main_clock % 1000000) / 1000); - /* FIXME get rid of master_clock global */ - at91_master_clock = mck.rate_hz; - #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS /* establish PCK0..PCK3 parentage */ for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) { @@ -663,19 +732,28 @@ #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS continue; pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); - parent = clock_list[pckr & 3]; + parent = clock_list[pckr & AT91_PMC_CSS]; clk->parent = parent; clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3)); + + if (clk->users == 0) { + /* not being used, so switch it off */ + at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask); + } } #else - /* disable unused clocks */ + /* disable all programmable clocks */ at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); -#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ +#endif - /* FIXME several unused clocks may still be active... provide - * a CONFIG option to turn off all unused clocks at some point - * before driver init starts. - */ + /* enable the PIO clocks */ + clk_enable(&pioA_clk); + clk_enable(&pioB_clk); + clk_enable(&pioC_clk); + clk_enable(&pioD_clk); + + /* disable all other unused peripheral clocks */ + at91_periphclk_reset(); return 0; } diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/common.c index 3848fd2..e836f85 100644 --- a/arch/arm/mach-at91rm9200/common.c +++ b/arch/arm/mach-at91rm9200/common.c @@ -16,7 +16,8 @@ #include #include #include -#include +#include +#include "generic.h" static struct map_desc at91rm9200_io_desc[] __initdata = { { @@ -94,6 +95,11 @@ static struct map_desc at91rm9200_io_des .pfn = __phys_to_pfn(AT91_BASE_TCB0), .length = SZ_16K, .type = MT_DEVICE, + }, { + .virtual = AT91_SRAM_VIRT_BASE, + .pfn = __phys_to_pfn(AT91_SRAM_BASE), + .length = AT91_SRAM_SIZE, + .type = MT_DEVICE, }, }; @@ -102,14 +108,3 @@ void __init at91rm9200_map_io(void) iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); } - -unsigned long at91_master_clock; - -EXPORT_SYMBOL(at91_master_clock); - - -int at91_serial_map[AT91_NR_UART]; -int at91_console_port; - -EXPORT_SYMBOL(at91_serial_map); -EXPORT_SYMBOL(at91_console_port); diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c index bfe47bd..1cf85d2 100644 --- a/arch/arm/mach-at91rm9200/devices.c +++ b/arch/arm/mach-at91rm9200/devices.c @@ -16,9 +16,15 @@ #include #include #include +#include #include -#include +#include +#include "generic.h" + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 /* -------------------------------------------------------------------- * USB Host @@ -28,7 +34,7 @@ #if defined(CONFIG_USB_OHCI_HCD) || defi static u64 ohci_dmamask = 0xffffffffUL; static struct at91_usbh_data usbh_data; -static struct resource at91_usbh_resource[] = { +static struct resource at91_usbh_resources[] = { [0] = { .start = AT91_UHP_BASE, .end = AT91_UHP_BASE + SZ_1M - 1, @@ -42,15 +48,15 @@ static struct resource at91_usbh_resourc }; static struct platform_device at91rm9200_usbh_device = { - .name = "at91rm9200-ohci", + .name = "at91_ohci", .id = -1, .dev = { .dma_mask = &ohci_dmamask, .coherent_dma_mask = 0xffffffff, .platform_data = &usbh_data, }, - .resource = at91_usbh_resource, - .num_resources = ARRAY_SIZE(at91_usbh_resource), + .resource = at91_usbh_resources, + .num_resources = ARRAY_SIZE(at91_usbh_resources), }; void __init at91_add_device_usbh(struct at91_usbh_data *data) @@ -74,11 +80,16 @@ #ifdef CONFIG_USB_GADGET_AT91 static struct at91_udc_data udc_data; static struct resource at91_udc_resources[] = { - { + [0] = { .start = AT91_BASE_UDP, .end = AT91_BASE_UDP + SZ_16K - 1, .flags = IORESOURCE_MEM, - } + }, + [1] = { + .start = AT91_ID_UDP, + .end = AT91_ID_UDP, + .flags = IORESOURCE_IRQ, + }, }; static struct platform_device at91rm9200_udc_device = { @@ -100,10 +111,8 @@ void __init at91_add_device_udc(struct a at91_set_gpio_input(data->vbus_pin, 0); at91_set_deglitch(data->vbus_pin, 1); } - if (data->pullup_pin) { + if (data->pullup_pin) at91_set_gpio_output(data->pullup_pin, 0); - at91_set_multi_drive(data->pullup_pin, 1); - } udc_data = *data; platform_device_register(&at91rm9200_udc_device); @@ -197,7 +206,7 @@ static struct at91_cf_data cf_data; static struct resource at91_cf_resources[] = { [0] = { .start = AT91_CF_BASE, - /* ties up CS4, CS5, and CS6 */ + /* ties up CS4, CS5 and CS6 */ .end = AT91_CF_BASE + (0x30000000 - 1), .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, }, @@ -231,6 +240,12 @@ void __init at91_add_device_cf(struct at at91_set_gpio_output(data->vcc_pin, 0); at91_set_gpio_output(data->rst_pin, 0); + /* force poweron defaults for these pins ... */ + at91_set_A_periph(AT91_PIN_PC9, 0); /* A25/CFRNW */ + at91_set_A_periph(AT91_PIN_PC10, 0); /* NCS4/CFCS */ + at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */ + at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ + cf_data = *data; platform_device_register(&at91rm9200_cf_device); } @@ -319,6 +334,7 @@ #else void __init at91_add_device_mmc(struct at91_mmc_data *data) {} #endif + /* -------------------------------------------------------------------- * NAND / SmartMedia * -------------------------------------------------------------------- */ @@ -400,22 +416,110 @@ #endif /* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE) +static u64 spi_dmamask = 0xffffffffUL; + +static struct resource at91_spi_resources[] = { + [0] = { + .start = AT91_BASE_SPI, + .end = AT91_BASE_SPI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SPI, + .end = AT91_ID_SPI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_spi_device = { + .name = "at91_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = at91_spi_resources, + .num_resources = ARRAY_SIZE(at91_spi_resources), +}; + +static const unsigned at91_spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + + at91_set_A_periph(AT91_PIN_PA0, 0); /* MISO */ + at91_set_A_periph(AT91_PIN_PA1, 0); /* MOSI */ + at91_set_A_periph(AT91_PIN_PA2, 0); /* SPCK */ + + /* Enable SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else + cs_pin = at91_spi_standard_cs[devices[i].chip_select]; + +#ifdef CONFIG_SPI_AT91_MANUAL_CS + at91_set_gpio_output(cs_pin, 1); +#else + at91_set_A_periph(cs_pin, 0); +#endif + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + at91_clock_associate("spi0_clk", &at91rm9200_spi_device.dev, "spi"); + platform_device_register(&at91rm9200_spi_device); +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- * RTC * -------------------------------------------------------------------- */ -#if defined(CONFIG_AT91_RTC) || defined(CONFIG_AT91_RTC_MODULE) +#if defined(CONFIG_RTC_DRV_AT91) || defined(CONFIG_RTC_DRV_AT91_MODULE) static struct platform_device at91rm9200_rtc_device = { .name = "at91_rtc", .id = -1, .num_resources = 0, }; -void __init at91_add_device_rtc(void) +static void __init at91_add_device_rtc(void) { platform_device_register(&at91rm9200_rtc_device); } #else -void __init at91_add_device_rtc(void) {} +static void __init at91_add_device_rtc(void) {} +#endif + + +/* -------------------------------------------------------------------- + * Watchdog + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_AT91_WATCHDOG) || defined(CONFIG_AT91_WATCHDOG_MODULE) +static struct platform_device at91rm9200_wdt_device = { + .name = "at91_wdt", + .id = -1, + .num_resources = 0, +}; + +static void __init at91_add_device_watchdog(void) +{ + platform_device_register(&at91rm9200_wdt_device); +} +#else +static void __init at91_add_device_watchdog(void) {} #endif @@ -429,13 +533,281 @@ u8 at91_leds_timer; void __init at91_init_leds(u8 cpu_led, u8 timer_led) { - at91_leds_cpu = cpu_led; - at91_leds_timer = timer_led; + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; } - #else void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} #endif +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SERIAL_AT91) +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct at91_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, /* DBGU not capable of receive DMA */ +}; + +static struct platform_device at91rm9200_dbgu_device = { + .name = "at91_usart", + .id = 0, + .dev = { + .platform_data = &dbgu_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA30, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PA31, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91_BASE_US0, + .end = AT91_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_US0, + .end = AT91_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct at91_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart0_device = { + .name = "at91_usart", + .id = 1, + .dev = { + .platform_data = &uart0_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA17, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PA18, 0); /* RXD0 */ + at91_set_A_periph(AT91_PIN_PA20, 0); /* CTS0 */ + + /* + * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21. + * We need to drive the pin manually. Default is off (RTS is active low). + */ + at91_set_gpio_output(AT91_PIN_PA21, 1); +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91_BASE_US1, + .end = AT91_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_US1, + .end = AT91_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct at91_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart1_device = { + .name = "at91_usart", + .id = 2, + .dev = { + .platform_data = &uart1_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB18, 0); /* RI1 */ + at91_set_A_periph(AT91_PIN_PB19, 0); /* DTR1 */ + at91_set_A_periph(AT91_PIN_PB20, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PB21, 0); /* RXD1 */ + at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD1 */ + at91_set_A_periph(AT91_PIN_PB24, 0); /* CTS1 */ + at91_set_A_periph(AT91_PIN_PB25, 0); /* DSR1 */ + at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91_BASE_US2, + .end = AT91_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_US2, + .end = AT91_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct at91_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart2_device = { + .name = "at91_usart", + .id = 3, + .dev = { + .platform_data = &uart2_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA22, 0); /* RXD2 */ + at91_set_A_periph(AT91_PIN_PA23, 1); /* TXD2 */ +} + +static struct resource uart3_resources[] = { + [0] = { + .start = AT91_BASE_US3, + .end = AT91_BASE_US3 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_US3, + .end = AT91_ID_US3, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct at91_uart_data uart3_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91rm9200_uart3_device = { + .name = "at91_usart", + .id = 4, + .dev = { + .platform_data = &uart3_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart3_resources, + .num_resources = ARRAY_SIZE(uart3_resources), +}; + +static inline void configure_usart3_pins(void) +{ + at91_set_B_periph(AT91_PIN_PA5, 1); /* TXD3 */ + at91_set_B_periph(AT91_PIN_PA6, 0); /* RXD3 */ +} + +struct platform_device *at91_uarts[AT91_NR_UART]; /* the UARTs to use */ +struct platform_device *at91_default_console_device; /* the serial console device */ + +void __init at91_init_serial(struct at91_uart_config *config) +{ + int i; + + /* Fill in list of supported UARTs */ + for (i = 0; i < config->nr_tty; i++) { + switch (config->tty_map[i]) { + case 0: + configure_usart0_pins(); + at91_uarts[i] = &at91rm9200_uart0_device; + at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart"); + break; + case 1: + configure_usart1_pins(); + at91_uarts[i] = &at91rm9200_uart1_device; + at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart"); + break; + case 2: + configure_usart2_pins(); + at91_uarts[i] = &at91rm9200_uart2_device; + at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart"); + break; + case 3: + configure_usart3_pins(); + at91_uarts[i] = &at91rm9200_uart3_device; + at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart"); + break; + case 4: + configure_dbgu_pins(); + at91_uarts[i] = &at91rm9200_dbgu_device; + at91_clock_associate("mck", &at91rm9200_dbgu_device.dev, "usart"); + break; + default: + continue; + } + at91_uarts[i]->id = i; /* update ID number to mapped ID */ + } + + /* Set serial console device */ + if (config->console_tty < AT91_NR_UART) + at91_default_console_device = at91_uarts[config->console_tty]; + if (!at91_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < AT91_NR_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } +} +#else +void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_add_device_serial(void) {} +#endif + + /* -------------------------------------------------------------------- */ + +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + at91_add_device_rtc(); + at91_add_device_watchdog(); + return 0; +} + +arch_initcall(at91_add_standard_devices); diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h index 9bd541e..f0d969d 100644 --- a/arch/arm/mach-at91rm9200/generic.h +++ b/arch/arm/mach-at91rm9200/generic.h @@ -16,3 +16,10 @@ extern struct sys_timer at91rm9200_timer extern void __init at91rm9200_map_io(void); extern int __init at91_clock_init(unsigned long main_clock); +struct device; +extern void __init at91_clock_associate(const char *id, struct device *dev, const char *func); + + /* Power Management */ +extern void at91_irq_suspend(void); +extern void at91_irq_resume(void); + diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 5ab4627..83c3474 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include static const u32 pio_controller_offset[4] = { @@ -213,6 +213,84 @@ EXPORT_SYMBOL(at91_get_gpio_value); /*--------------------------------------------------------------------------*/ +#ifdef CONFIG_PM + +static u32 wakeups[BGA_GPIO_BANKS]; +static u32 backups[BGA_GPIO_BANKS]; + +static int gpio_irq_set_wake(unsigned pin, unsigned state) +{ + unsigned mask = pin_to_mask(pin); + + pin -= PIN_BASE; + pin /= 32; + + if (unlikely(pin >= BGA_GPIO_BANKS)) + return -EINVAL; + + if (state) + wakeups[pin] |= mask; + else + wakeups[pin] &= ~mask; + + return 0; +} + +void at91_gpio_suspend(void) +{ + int i; + + for (i = 0; i < BGA_GPIO_BANKS; i++) { + u32 pio = pio_controller_offset[i]; + + /* + * Note: drivers should have disabled GPIO interrupts that + * aren't supposed to be wakeup sources. + * But that is not much good on ARM..... disable_irq() does + * not update the hardware immediately, so the hardware mask + * (IMR) has the wrong value (not current, too much is + * permitted). + * + * Our workaround is to disable all non-wakeup IRQs ... + * which is exactly what correct drivers asked for in the + * first place! + */ + backups[i] = at91_sys_read(pio + PIO_IMR); + at91_sys_write(pio_controller_offset[i] + PIO_IDR, backups[i]); + at91_sys_write(pio_controller_offset[i] + PIO_IER, wakeups[i]); + + if (!wakeups[i]) { + disable_irq_wake(AT91_ID_PIOA + i); + at91_sys_write(AT91_PMC_PCDR, 1 << (AT91_ID_PIOA + i)); + } else { + enable_irq_wake(AT91_ID_PIOA + i); +#ifdef CONFIG_PM_DEBUG + printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", "ABCD"[i], wakeups[i]); +#endif + } + } +} + +void at91_gpio_resume(void) +{ + int i; + + for (i = 0; i < BGA_GPIO_BANKS; i++) { + at91_sys_write(pio_controller_offset[i] + PIO_IDR, wakeups[i]); + at91_sys_write(pio_controller_offset[i] + PIO_IER, backups[i]); + } + + at91_sys_write(AT91_PMC_PCER, + (1 << AT91_ID_PIOA) + | (1 << AT91_ID_PIOB) + | (1 << AT91_ID_PIOC) + | (1 << AT91_ID_PIOD)); +} + +#else +#define gpio_irq_set_wake NULL +#endif + /* Several AIC controller irqs are dispatched through this GPIO handler. * To use any AT91_PIN_* as an externally triggered IRQ, first call @@ -252,6 +330,7 @@ static struct irqchip gpio_irqchip = { .mask = gpio_irq_mask, .unmask = gpio_irq_unmask, .set_type = gpio_irq_type, + .set_wake = gpio_irq_set_wake, }; static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs) @@ -266,6 +345,7 @@ static void gpio_irq_handler(unsigned ir /* temporarily mask (level sensitive) parent IRQ */ desc->chip->ack(irq); for (;;) { + /* reading ISR acks the pending (edge triggered) GPIO interrupt */ isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR); if (!isr) break; @@ -315,15 +395,16 @@ void __init at91_gpio_irq_setup(unsigned set_irq_chipdata(id, controller); for (i = 0; i < 32; i++, pin++) { + /* + * Can use the "simple" and not "edge" handler since it's + * shorter, and the AIC handles interupts sanely. + */ set_irq_chip(pin, &gpio_irqchip); set_irq_handler(pin, do_simple_IRQ); set_irq_flags(pin, IRQF_VALID); } set_irq_chained_handler(id, gpio_irq_handler); - - /* enable the PIO peripheral clock */ - at91_sys_write(AT91_PMC_PCER, 1 << id); } pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks); } diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c index cb62bc8..70f4d7a 100644 --- a/arch/arm/mach-at91rm9200/irq.c +++ b/arch/arm/mach-at91rm9200/irq.c @@ -92,10 +92,6 @@ static int at91rm9200_irq_type(unsigned { unsigned int smr, srctype; - /* change triggering only for FIQ and external IRQ0..IRQ6 */ - if ((irq < AT91_ID_IRQ0) && (irq != AT91_ID_FIQ)) - return -EINVAL; - switch (type) { case IRQT_HIGH: srctype = AT91_AIC_SRCTYPE_HIGH; @@ -104,9 +100,13 @@ static int at91rm9200_irq_type(unsigned srctype = AT91_AIC_SRCTYPE_RISING; break; case IRQT_LOW: + if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0)) /* only supported on external interrupts */ + return -EINVAL; srctype = AT91_AIC_SRCTYPE_LOW; break; case IRQT_FALLING: + if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0)) /* only supported on external interrupts */ + return -EINVAL; srctype = AT91_AIC_SRCTYPE_FALLING; break; default: @@ -118,11 +118,47 @@ static int at91rm9200_irq_type(unsigned return 0; } +#ifdef CONFIG_PM + +static u32 wakeups; +static u32 backups; + +static int at91rm9200_irq_set_wake(unsigned irq, unsigned value) +{ + if (unlikely(irq >= 32)) + return -EINVAL; + + if (value) + wakeups |= (1 << irq); + else + wakeups &= ~(1 << irq); + + return 0; +} + +void at91_irq_suspend(void) +{ + backups = at91_sys_read(AT91_AIC_IMR); + at91_sys_write(AT91_AIC_IDCR, backups); + at91_sys_write(AT91_AIC_IECR, wakeups); +} + +void at91_irq_resume(void) +{ + at91_sys_write(AT91_AIC_IDCR, wakeups); + at91_sys_write(AT91_AIC_IECR, backups); +} + +#else +#define at91rm9200_irq_set_wake NULL +#endif + static struct irqchip at91rm9200_irq_chip = { .ack = at91rm9200_mask_irq, .mask = at91rm9200_mask_irq, .unmask = at91rm9200_unmask_irq, .set_type = at91rm9200_irq_type, + .set_wake = at91rm9200_irq_set_wake, }; /* diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c new file mode 100644 index 0000000..47e5480 --- /dev/null +++ b/arch/arm/mach-at91rm9200/pm.c @@ -0,0 +1,225 @@ +/* + * arch/arm/mach-at91rm9200/pm.c + * AT91 Power Management + * + * Copyright (C) 2005 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "generic.h" + + +static int at91_pm_valid_state(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_ON: + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + return 1; + + default: + return 0; + } +} + + +static suspend_state_t target_state; + +/* + * Called after processes are frozen, but before we shutdown devices. + */ +static int at91_pm_prepare(suspend_state_t state) +{ + target_state = state; + return 0; +} + +/* + * Verify that all the clocks are correct before entering + * slow-clock mode. + */ +static int at91_pm_verify_clocks(void) +{ + unsigned long scsr; + int i; + + scsr = at91_sys_read(AT91_PMC_SCSR); + + /* USB must not be using PLLB */ + if ((scsr & (AT91_PMC_UHP | AT91_PMC_UDP)) != 0) { + pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); + return 0; + } + +#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS + /* PCK0..PCK3 must be disabled, or configured to use clk32k */ + for (i = 0; i < 4; i++) { + u32 css; + + if ((scsr & (AT91_PMC_PCK0 << i)) == 0) + continue; + + css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS; + if (css != AT91_PMC_CSS_SLOW) { + pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); + return 0; + } + } +#endif + + return 1; +} + +/* + * Call this from platform driver suspend() to see how deeply to suspend. + * For example, some controllers (like OHCI) need one of the PLL clocks + * in order to act as a wakeup source, and those are not available when + * going into slow clock mode. + * + * REVISIT: generalize as clk_will_be_available(clk)? Other platforms have + * the very same problem (but not using at91 main_clk), and it'd be better + * to add one generic API rather than lots of platform-specific ones. + */ +int at91_suspend_entering_slow_clock(void) +{ + return (target_state == PM_SUSPEND_MEM); +} +EXPORT_SYMBOL(at91_suspend_entering_slow_clock); + + +static void (*slow_clock)(void); + + + +static int at91_pm_enter(suspend_state_t state) +{ + at91_gpio_suspend(); + at91_irq_suspend(); + + pr_debug("AT91: PM - wake mask %08x, pm state %d\n", + /* remember all the always-wake irqs */ + (at91_sys_read(AT91_PMC_PCSR) + | (1 << AT91_ID_FIQ) + | (1 << AT91_ID_SYS) + | (1 << AT91_ID_IRQ0) + | (1 << AT91_ID_IRQ1) + | (1 << AT91_ID_IRQ2) + | (1 << AT91_ID_IRQ3) + | (1 << AT91_ID_IRQ4) + | (1 << AT91_ID_IRQ5) + | (1 << AT91_ID_IRQ6)) + & at91_sys_read(AT91_AIC_IMR), + state); + + switch (state) { + /* + * Suspend-to-RAM is like STANDBY plus slow clock mode, so + * drivers must suspend more deeply: only the master clock + * controller may be using the main oscillator. + */ + case PM_SUSPEND_MEM: + /* + * Ensure that clocks are in a valid state. + */ + if (!at91_pm_verify_clocks()) + goto error; + + /* + * Enter slow clock mode by switching over to clk32k and + * turning off the main oscillator; reverse on wakeup. + */ + if (slow_clock) { + slow_clock(); + break; + } else { + /* DEVELOPMENT ONLY */ + pr_info("AT91: PM - no slow clock mode yet ...\n"); + /* FALLTHROUGH leaving master clock alone */ + } + + /* + * STANDBY mode has *all* drivers suspended; ignores irqs not + * marked as 'wakeup' event sources; and reduces DRAM power. + * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and + * nothing fancy done with main or cpu clocks. + */ + case PM_SUSPEND_STANDBY: + /* + * NOTE: the Wait-for-Interrupt instruction needs to be + * in icache so the SDRAM stays in self-refresh mode until + * the wakeup IRQ occurs. + */ + asm("b 1f; .align 5; 1:"); + asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ + at91_sys_write(AT91_SDRAMC_SRR, 1); /* self-refresh mode */ + /* fall though to next state */ + + case PM_SUSPEND_ON: + asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */ + break; + + default: + pr_debug("AT91: PM - bogus suspend state %d\n", state); + goto error; + } + + pr_debug("AT91: PM - wakeup %08x\n", + at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR)); + +error: + target_state = PM_SUSPEND_ON; + at91_irq_resume(); + at91_gpio_resume(); + return 0; +} + + +static struct pm_ops at91_pm_ops ={ + .pm_disk_mode = 0, + .valid = at91_pm_valid_state, + .prepare = at91_pm_prepare, + .enter = at91_pm_enter, +}; + +static int __init at91_pm_init(void) +{ + printk("AT91: Power Management\n"); + +#ifdef CONFIG_AT91_PM_SLOW_CLOCK + /* REVISIT allocations of SRAM should be dynamically managed. + * FIQ handlers and other components will want SRAM/TCM too... + */ + slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K)); + memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz); +#endif + + /* Disable SDRAM low-power mode. Cannot be used with self-refresh. */ + at91_sys_write(AT91_SDRAMC_LPR, 0); + + pm_set_ops(&at91_pm_ops); + + return 0; +} +arch_initcall(at91_pm_init); diff --git a/arch/arm/mach-at91rm9200/time.c b/arch/arm/mach-at91rm9200/time.c index 7ffcf44..fc2d7d5 100644 --- a/arch/arm/mach-at91rm9200/time.c +++ b/arch/arm/mach-at91rm9200/time.c @@ -31,6 +31,8 @@ #include #include #include +static unsigned long last_crtr; + /* * The ST_CRTR is updated asynchronously to the master clock. It is therefore * necessary to read it twice (with the same value) to ensure accuracy. @@ -56,7 +58,7 @@ static unsigned long at91rm9200_gettimeo { unsigned long elapsed; - elapsed = (read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV; + elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV; return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH; } @@ -66,15 +68,12 @@ static unsigned long at91rm9200_gettimeo */ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - unsigned long rtar; - if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */ write_seqlock(&xtime_lock); - while (((read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV) >= LATCH) { + while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) { timer_tick(regs); - rtar = (at91_sys_read(AT91_ST_RTAR) + LATCH) & AT91_ST_ALMV; - at91_sys_write(AT91_ST_RTAR, rtar); + last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV; } write_sequnlock(&xtime_lock); @@ -87,10 +86,24 @@ static irqreturn_t at91rm9200_timer_inte static struct irqaction at91rm9200_timer_irq = { .name = "at91_tick", - .flags = SA_SHIRQ | SA_INTERRUPT, + .flags = SA_SHIRQ | SA_INTERRUPT | SA_TIMER, .handler = at91rm9200_timer_interrupt }; +void at91rm9200_timer_reset(void) +{ + last_crtr = 0; + + /* Real time counter incremented every 30.51758 microseconds */ + at91_sys_write(AT91_ST_RTMR, 1); + + /* Set Period Interval timer */ + at91_sys_write(AT91_ST_PIMR, LATCH); + + /* Enable Period Interval Timer interrupt */ + at91_sys_write(AT91_ST_IER, AT91_ST_PITS); +} + /* * Set up timer interrupt. */ @@ -100,28 +113,30 @@ void __init at91rm9200_timer_init(void) at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS); (void) at91_sys_read(AT91_ST_SR); /* Clear any pending interrupts */ - /* - * Make IRQs happen for the system timer. - */ + /* Make IRQs happen for the system timer */ setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq); - /* Set initial alarm to 0 */ - at91_sys_write(AT91_ST_RTAR, 0); - - /* Real time counter incremented every 30.51758 microseconds */ - at91_sys_write(AT91_ST_RTMR, 1); - - /* Set Period Interval timer */ - at91_sys_write(AT91_ST_PIMR, LATCH); - /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */ tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE; - /* Enable Period Interval Timer interrupt */ - at91_sys_write(AT91_ST_IER, AT91_ST_PITS); + /* Initialize and enable the timer interrupt */ + at91rm9200_timer_reset(); +} + +#ifdef CONFIG_PM +static void at91rm9200_timer_suspend(void) +{ + /* disable Period Interval Timer interrupt */ + at91_sys_write(AT91_ST_IDR, AT91_ST_PITS); } +#else +#define at91rm9200_timer_suspend NULL +#endif struct sys_timer at91rm9200_timer = { .init = at91rm9200_timer_init, .offset = at91rm9200_gettimeoffset, + .suspend = at91rm9200_timer_suspend, + .resume = at91rm9200_timer_reset, }; + diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile index 5393af9..05a48a2 100644 --- a/arch/arm/mach-ep93xx/Makefile +++ b/arch/arm/mach-ep93xx/Makefile @@ -1,7 +1,7 @@ # # Makefile for the linux kernel. # -obj-y := core.o +obj-y := core.o clock.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c new file mode 100644 index 0000000..08ad782 --- /dev/null +++ b/arch/arm/mach-ep93xx/clock.c @@ -0,0 +1,156 @@ +/* + * arch/arm/mach-ep93xx/clock.c + * Clock control for Cirrus EP93xx chips. + * + * Copyright (C) 2006 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +struct clk { + char *name; + unsigned long rate; + int users; + u32 enable_reg; + u32 enable_mask; +}; + +static struct clk clk_pll1 = { + .name = "pll1", +}; +static struct clk clk_f = { + .name = "fclk", +}; +static struct clk clk_h = { + .name = "hclk", +}; +static struct clk clk_p = { + .name = "pclk", +}; +static struct clk clk_pll2 = { + .name = "pll2", +}; +static struct clk clk_usb_host = { + .name = "usb_host", + .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL, + .enable_mask = EP93XX_SYSCON_CLOCK_USH_EN, +}; + + +static struct clk *clocks[] = { + &clk_pll1, + &clk_f, + &clk_h, + &clk_p, + &clk_pll2, + &clk_usb_host, +}; + +struct clk *clk_get(struct device *dev, const char *id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(clocks); i++) { + if (!strcmp(clocks[i]->name, id)) + return clocks[i]; + } + + return ERR_PTR(-ENOENT); +} + +int clk_enable(struct clk *clk) +{ + if (!clk->users++ && clk->enable_reg) { + u32 value; + + value = __raw_readl(clk->enable_reg); + __raw_writel(value | clk->enable_mask, clk->enable_reg); + } + + return 0; +} + +void clk_disable(struct clk *clk) +{ + if (!--clk->users && clk->enable_reg) { + u32 value; + + value = __raw_readl(clk->enable_reg); + __raw_writel(value & ~clk->enable_mask, clk->enable_reg); + } +} + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} + +void clk_put(struct clk *clk) +{ +} + + + +static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; +static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; +static char pclk_divisors[] = { 1, 2, 4, 8 }; + +/* + * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS + */ +static unsigned long calc_pll_rate(u32 config_word) +{ + unsigned long long rate; + int i; + + rate = 14745600; + rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */ + rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */ + do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */ + for (i = 0; i < ((config_word >> 16) & 3); i++) /* PS */ + rate >>= 1; + + return (unsigned long)rate; +} + +void ep93xx_clock_init(void) +{ + u32 value; + + value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1); + if (!(value & 0x00800000)) { /* PLL1 bypassed? */ + clk_pll1.rate = 14745600; + } else { + clk_pll1.rate = calc_pll_rate(value); + } + clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7]; + clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7]; + clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3]; + + value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2); + if (!(value & 0x00080000)) { /* PLL2 bypassed? */ + clk_pll2.rate = 14745600; + } else if (value & 0x00040000) { /* PLL2 enabled? */ + clk_pll2.rate = calc_pll_rate(value); + } else { + clk_pll2.rate = 0; + } + clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1); + + printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n", + clk_pll1.rate / 1000000, clk_pll2.rate / 1000000); + printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n", + clk_f.rate / 1000000, clk_h.rate / 1000000, + clk_p.rate / 1000000); +} diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index dcd4176..1fe73c0 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -103,7 +103,8 @@ static int ep93xx_timer_interrupt(int ir write_seqlock(&xtime_lock); __raw_writel(1, EP93XX_TIMER1_CLEAR); - while (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time + while ((signed long) + (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time) >= TIMER4_TICKS_PER_JIFFY) { last_jiffy_time += TIMER4_TICKS_PER_JIFFY; timer_tick(regs); @@ -124,7 +125,7 @@ static void __init ep93xx_timer_init(voi { /* Enable periodic HZ timer. */ __raw_writel(0x48, EP93XX_TIMER1_CONTROL); - __raw_writel((508000 / HZ) - 1, EP93XX_TIMER1_LOAD); + __raw_writel((508469 / HZ) - 1, EP93XX_TIMER1_LOAD); __raw_writel(0xc8, EP93XX_TIMER1_CONTROL); /* Enable lost jiffy timer. */ @@ -432,10 +433,37 @@ static struct platform_device ep93xx_rtc }; +static struct resource ep93xx_ohci_resources[] = { + [0] = { + .start = EP93XX_USB_PHYS_BASE, + .end = EP93XX_USB_PHYS_BASE + 0x0fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_EP93XX_USB, + .end = IRQ_EP93XX_USB, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ep93xx_ohci_device = { + .name = "ep93xx-ohci", + .id = -1, + .dev = { + .dma_mask = (void *)0xffffffff, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), + .resource = ep93xx_ohci_resources, +}; + + void __init ep93xx_init_devices(void) { unsigned int v; + ep93xx_clock_init(); + /* * Disallow access to MaverickCrunch initially. */ @@ -449,4 +477,5 @@ void __init ep93xx_init_devices(void) amba_device_register(&uart3_device, &iomem_resource); platform_device_register(&ep93xx_rtc_device); + platform_device_register(&ep93xx_ohci_device); } diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c index d18fcb1..47cc6c8 100644 --- a/arch/arm/mach-ep93xx/gesbc9312.c +++ b/arch/arm/mach-ep93xx/gesbc9312.c @@ -16,16 +16,38 @@ #include #include #include #include +#include #include +#include #include #include #include #include +static struct physmap_flash_data gesbc9312_flash_data = { + .width = 4, +}; + +static struct resource gesbc9312_flash_resource = { + .start = 0x60000000, + .end = 0x60800000, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device gesbc9312_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &gesbc9312_flash_data, + }, + .num_resources = 1, + .resource = &gesbc9312_flash_resource, +}; + static void __init gesbc9312_init_machine(void) { ep93xx_init_devices(); - physmap_configure(0x60000000, 0x00800000, 4, NULL); + platform_device_register(&gesbc9312_flash); } MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx") diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index e24566b..6e5a56c 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -16,6 +16,7 @@ #include #include #include #include +#include #include #include #include @@ -111,6 +112,26 @@ static void __init ts72xx_map_io(void) } } +static struct physmap_flash_data ts72xx_flash_data = { + .width = 1, +}; + +static struct resource ts72xx_flash_resource = { + .start = TS72XX_NOR_PHYS_BASE, + .end = TS72XX_NOR_PHYS_BASE + 0x01000000, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ts72xx_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ts72xx_flash_data, + }, + .num_resources = 1, + .resource = &ts72xx_flash_resource, +}; + static unsigned char ts72xx_rtc_readbyte(unsigned long addr) { __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE); @@ -141,7 +162,7 @@ static void __init ts72xx_init_machine(v { ep93xx_init_devices(); if (board_is_ts7200()) - physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL); + platform_device_register(&ts72xx_flash); platform_device_register(&ts72xx_rtc_device); } diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c index 4ca51dc..3657887 100644 --- a/arch/arm/mach-imx/dma.c +++ b/arch/arm/mach-imx/dma.c @@ -15,6 +15,9 @@ * Changed to support scatter gather DMA * by taking Russell's code from RiscPC * + * 2006-05-31 Pavel Pisa + * Corrected error handling code. + * */ #undef DEBUG @@ -277,7 +280,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch, int imx_dma_setup_handlers(imx_dmach_t dma_ch, void (*irq_handler) (int, void *, struct pt_regs *), - void (*err_handler) (int, void *, struct pt_regs *), + void (*err_handler) (int, void *, struct pt_regs *, int), void *data) { struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; @@ -463,43 +466,53 @@ static irqreturn_t dma_err_handler(int i int i, disr = DISR; struct imx_dma_channel *channel; unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR; + int errcode; - DISR = disr; + DISR = disr & err_mask; for (i = 0; i < IMX_DMA_CHANNELS; i++) { - channel = &imx_dma_channels[i]; - - if ((err_mask & 1 << i) && channel->name - && channel->err_handler) { - channel->err_handler(i, channel->data, regs); + if(!(err_mask & (1 << i))) continue; - } - - imx_dma_channels[i].sg = NULL; + channel = &imx_dma_channels[i]; + errcode = 0; if (DBTOSR & (1 << i)) { - printk(KERN_WARNING - "Burst timeout on channel %d (%s)\n", - i, channel->name); - DBTOSR |= (1 << i); + DBTOSR = (1 << i); + errcode |= IMX_DMA_ERR_BURST; } if (DRTOSR & (1 << i)) { - printk(KERN_WARNING - "Request timeout on channel %d (%s)\n", - i, channel->name); - DRTOSR |= (1 << i); + DRTOSR = (1 << i); + errcode |= IMX_DMA_ERR_REQUEST; } if (DSESR & (1 << i)) { - printk(KERN_WARNING - "Transfer timeout on channel %d (%s)\n", - i, channel->name); - DSESR |= (1 << i); + DSESR = (1 << i); + errcode |= IMX_DMA_ERR_TRANSFER; } if (DBOSR & (1 << i)) { - printk(KERN_WARNING - "Buffer overflow timeout on channel %d (%s)\n", - i, channel->name); - DBOSR |= (1 << i); + DBOSR = (1 << i); + errcode |= IMX_DMA_ERR_BUFFER; } + + /* + * The cleaning of @sg field would be questionable + * there, because its value can help to compute + * remaining/transfered bytes count in the handler + */ + /*imx_dma_channels[i].sg = NULL;*/ + + if (channel->name && channel->err_handler) { + channel->err_handler(i, channel->data, regs, errcode); + continue; + } + + imx_dma_channels[i].sg = NULL; + + printk(KERN_WARNING + "DMA timeout on channel %d (%s) -%s%s%s%s\n", + i, channel->name, + errcode&IMX_DMA_ERR_BURST? " burst":"", + errcode&IMX_DMA_ERR_REQUEST? " request":"", + errcode&IMX_DMA_ERR_TRANSFER? " transfer":"", + errcode&IMX_DMA_ERR_BUFFER? " buffer":""); } return IRQ_HANDLED; } diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index 6e8d504..ebe4391 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -211,7 +211,8 @@ static int ixp2000_timer_interrupt(int i /* clear timer 1 */ ixp2000_reg_wrb(IXP2000_T1_CLR, 1); - while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) { + while ((signed long)(next_jiffy_time - *missing_jiffy_timer_csr) + >= ticks_per_jiffy) { timer_tick(regs); next_jiffy_time -= ticks_per_jiffy; } @@ -301,6 +302,7 @@ void gpio_line_config(int line, int dire } local_irq_restore(flags); } +EXPORT_SYMBOL(gpio_line_config); /************************************************************************* diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c index affd1d5..051e3d7 100644 --- a/arch/arm/mach-ixp23xx/core.c +++ b/arch/arm/mach-ixp23xx/core.c @@ -334,7 +334,7 @@ void __init ixp23xx_init_irq(void) /************************************************************************* * Timer-tick functions for IXP23xx *************************************************************************/ -#define CLOCK_TICKS_PER_USEC CLOCK_TICK_RATE / (USEC_PER_SEC) +#define CLOCK_TICKS_PER_USEC (CLOCK_TICK_RATE / USEC_PER_SEC) static unsigned long next_jiffy_time; @@ -353,7 +353,7 @@ ixp23xx_timer_interrupt(int irq, void *d { /* Clear Pending Interrupt by writing '1' to it */ *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND; - while ((*IXP23XX_TIMER_CONT - next_jiffy_time) > LATCH) { + while ((signed long)(*IXP23XX_TIMER_CONT - next_jiffy_time) >= LATCH) { timer_tick(regs); next_jiffy_time += LATCH; } @@ -439,5 +439,6 @@ static struct platform_device *ixp23xx_d void __init ixp23xx_sys_init(void) { + *IXP23XX_EXP_UNIT_FUSE |= 0xf; platform_add_devices(ixp23xx_devices, ARRAY_SIZE(ixp23xx_devices)); } diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c index bf688c1..dc5e489 100644 --- a/arch/arm/mach-ixp23xx/espresso.c +++ b/arch/arm/mach-ixp23xx/espresso.c @@ -53,9 +53,29 @@ static int __init espresso_pci_init(void }; subsys_initcall(espresso_pci_init); +static struct physmap_flash_data espresso_flash_data = { + .width = 2, +}; + +static struct resource espresso_flash_resource = { + .start = 0x90000000, + .end = 0x92000000, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device espresso_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &espresso_flash_data, + }, + .num_resources = 1, + .resource = &espresso_flash_resource, +}; + static void __init espresso_init(void) { - physmap_configure(0x90000000, 0x02000000, 2, NULL); + platform_device_register(&espresso_flash); /* * Mark flash as writeable. diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c index 00146c3..535b334 100644 --- a/arch/arm/mach-ixp23xx/ixdp2351.c +++ b/arch/arm/mach-ixp23xx/ixdp2351.c @@ -298,9 +298,29 @@ static void __init ixdp2351_map_io(void) iotable_init(ixdp2351_io_desc, ARRAY_SIZE(ixdp2351_io_desc)); } +static struct physmap_flash_data ixdp2351_flash_data = { + .width = 1, +}; + +static struct resource ixdp2351_flash_resource = { + .start = 0x90000000, + .end = 0x94000000, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ixdp2351_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ixdp2351_flash_data, + }, + .num_resources = 1, + .resource = &ixdp2351_flash_resource, +}; + static void __init ixdp2351_init(void) { - physmap_configure(0x90000000, 0x04000000, 1, NULL); + platform_device_register(&ixdp2351_flash); /* * Mark flash as writeable diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c index 43c14e7..b9f5d13 100644 --- a/arch/arm/mach-ixp23xx/roadrunner.c +++ b/arch/arm/mach-ixp23xx/roadrunner.c @@ -137,9 +137,29 @@ static int __init roadrunner_pci_init(vo subsys_initcall(roadrunner_pci_init); +static struct physmap_flash_data roadrunner_flash_data = { + .width = 2, +}; + +static struct resource roadrunner_flash_resource = { + .start = 0x90000000, + .end = 0x94000000, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device roadrunner_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &roadrunner_flash_data, + }, + .num_resources = 1, + .resource = &roadrunner_flash_resource, +}; + static void __init roadrunner_init(void) { - physmap_configure(0x90000000, 0x04000000, 2, NULL); + platform_device_register(&roadrunner_flash); /* * Mark flash as writeable diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index 3b23f43..57f23b4 100644 --- a/arch/arm/mach-ixp4xx/Kconfig +++ b/arch/arm/mach-ixp4xx/Kconfig @@ -35,7 +35,6 @@ config ARCH_ADI_COYOTE config ARCH_IXDP425 bool "IXDP425" - select PCI help Say 'Y' here if you want your kernel to support Intel's IXDP425 Development Platform (Also known as Richfield). @@ -43,7 +42,6 @@ config ARCH_IXDP425 config MACH_IXDPG425 bool "IXDPG425" - select PCI help Say 'Y' here if you want your kernel to support Intel's IXDPG425 Development Platform (Also known as Montajade). @@ -51,7 +49,6 @@ config MACH_IXDPG425 config MACH_IXDP465 bool "IXDP465" - select PCI help Say 'Y' here if you want your kernel to support Intel's IXDP465 Development Platform (Also known as BMP). diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile index 5a4aaa0..640315d 100644 --- a/arch/arm/mach-ixp4xx/Makefile +++ b/arch/arm/mach-ixp4xx/Makefile @@ -2,13 +2,23 @@ # # Makefile for the linux kernel. # +obj-pci-y := +obj-pci-n := + +obj-pci-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o +obj-pci-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o +obj-pci-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o +obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o +obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-pci.o +obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o + obj-y += common.o -obj-$(CONFIG_PCI) += common-pci.o -obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o ixdp425-setup.o -obj-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o coyote-setup.o -obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o coyote-setup.o -obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o gtwx5715-setup.o -obj-$(CONFIG_MACH_NSLU2) += nslu2-pci.o nslu2-setup.o nslu2-power.o -obj-$(CONFIG_MACH_NAS100D) += nas100d-pci.o nas100d-setup.o nas100d-power.o +obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-setup.o +obj-$(CONFIG_MACH_IXDPG425) += coyote-setup.o +obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o +obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o +obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o +obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o nas100d-power.o +obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 00b761f..bf25a76 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -276,7 +276,7 @@ static irqreturn_t ixp4xx_timer_interrup /* * Catch up with the real idea of time */ - while ((*IXP4XX_OSTS - last_jiffy_time) > LATCH) { + while ((signed long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) { timer_tick(regs); last_jiffy_time += LATCH; } diff --git a/arch/arm/mach-ixp4xx/nas100d-power.c b/arch/arm/mach-ixp4xx/nas100d-power.c index 99d333d..a3745ed 100644 --- a/arch/arm/mach-ixp4xx/nas100d-power.c +++ b/arch/arm/mach-ixp4xx/nas100d-power.c @@ -20,11 +20,10 @@ #include #include #include +#include #include -extern void ctrl_alt_del(void); - static irqreturn_t nas100d_reset_handler(int irq, void *dev_id, struct pt_regs *regs) { /* Signal init to do the ctrlaltdel action, this will bypass init if diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c index a3b4c6a..9a31444 100644 --- a/arch/arm/mach-ixp4xx/nas100d-setup.c +++ b/arch/arm/mach-ixp4xx/nas100d-setup.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,36 @@ static struct platform_device nas100d_fl .resource = &nas100d_flash_resource, }; +#ifdef CONFIG_LEDS_IXP4XX +static struct resource nas100d_led_resources[] = { + { + .name = "wlan", /* green led */ + .start = 0, + .end = 0, + .flags = IXP4XX_GPIO_LOW, + }, + { + .name = "ready", /* blue power led (off is flashing!) */ + .start = 15, + .end = 15, + .flags = IXP4XX_GPIO_LOW, + }, + { + .name = "disk", /* yellow led */ + .start = 3, + .end = 3, + .flags = IXP4XX_GPIO_LOW, + }, +}; + +static struct platform_device nas100d_leds = { + .name = "IXP4XX-GPIO-LED", + .id = -1, + .num_resources = ARRAY_SIZE(nas100d_led_resources), + .resource = nas100d_led_resources, +}; +#endif + static struct ixp4xx_i2c_pins nas100d_i2c_gpio_pins = { .sda_pin = NAS100D_SDA_PIN, .scl_pin = NAS100D_SCL_PIN, @@ -95,7 +126,9 @@ static struct platform_device nas100d_ua static struct platform_device *nas100d_devices[] __initdata = { &nas100d_i2c_controller, &nas100d_flash, - &nas100d_uart, +#ifdef CONFIG_LEDS_IXP4XX + &nas100d_leds, +#endif }; static void nas100d_power_off(void) @@ -122,6 +155,12 @@ static void __init nas100d_init(void) pm_power_off = nas100d_power_off; + /* This is only useful on a modified machine, but it is valuable + * to have it first in order to see debug messages, and so that + * it does *not* get removed if platform_add_devices fails! + */ + (void)platform_device_register(&nas100d_uart); + platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices)); } diff --git a/arch/arm/mach-ixp4xx/nslu2-power.c b/arch/arm/mach-ixp4xx/nslu2-power.c index d80c362..6d38e97 100644 --- a/arch/arm/mach-ixp4xx/nslu2-power.c +++ b/arch/arm/mach-ixp4xx/nslu2-power.c @@ -20,11 +20,10 @@ #include #include #include +#include #include -extern void ctrl_alt_del(void); - static irqreturn_t nslu2_power_handler(int irq, void *dev_id, struct pt_regs *regs) { /* Signal init to do the ctrlaltdel action, this will bypass init if diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c index 55411f2..749a337 100644 --- a/arch/arm/mach-ixp4xx/nslu2-setup.c +++ b/arch/arm/mach-ixp4xx/nslu2-setup.c @@ -7,6 +7,7 @@ * Copyright (C) 2003-2004 MontaVista Software, Inc. * * Author: Mark Rakes + * Author: Rod Whitby * Maintainers: http://www.nslu2-linux.org/ * * Fixed missing init_time in MACHINE_START kas11 10/22/04 @@ -16,6 +17,7 @@ #include #include #include +#include #include #include @@ -43,6 +45,42 @@ static struct ixp4xx_i2c_pins nslu2_i2c_ .scl_pin = NSLU2_SCL_PIN, }; +#ifdef CONFIG_LEDS_IXP4XX +static struct resource nslu2_led_resources[] = { + { + .name = "ready", /* green led */ + .start = NSLU2_LED_GRN, + .end = NSLU2_LED_GRN, + .flags = IXP4XX_GPIO_HIGH, + }, + { + .name = "status", /* red led */ + .start = NSLU2_LED_RED, + .end = NSLU2_LED_RED, + .flags = IXP4XX_GPIO_HIGH, + }, + { + .name = "disk-1", + .start = NSLU2_LED_DISK1, + .end = NSLU2_LED_DISK1, + .flags = IXP4XX_GPIO_LOW, + }, + { + .name = "disk-2", + .start = NSLU2_LED_DISK2, + .end = NSLU2_LED_DISK2, + .flags = IXP4XX_GPIO_LOW, + }, +}; + +static struct platform_device nslu2_leds = { + .name = "IXP4XX-GPIO-LED", + .id = -1, + .num_resources = ARRAY_SIZE(nslu2_led_resources), + .resource = nslu2_led_resources, +}; +#endif + static struct platform_device nslu2_i2c_controller = { .name = "IXP4XX-I2C", .id = 0, @@ -102,8 +140,10 @@ static struct platform_device nslu2_uart static struct platform_device *nslu2_devices[] __initdata = { &nslu2_i2c_controller, &nslu2_flash, - &nslu2_uart, &nslu2_beeper, +#ifdef CONFIG_LEDS_IXP4XX + &nslu2_leds, +#endif }; static void nslu2_power_off(void) @@ -127,6 +167,12 @@ static void __init nslu2_init(void) pm_power_off = nslu2_power_off; + /* This is only useful on a modified machine, but it is valuable + * to have it first in order to see debug messages, and so that + * it does *not* get removed if platform_add_devices fails! + */ + (void)platform_device_register(&nslu2_uart); + platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices)); } diff --git a/arch/arm/mach-lh7a40x/Kconfig b/arch/arm/mach-lh7a40x/Kconfig index 8a17867..558a34f 100644 --- a/arch/arm/mach-lh7a40x/Kconfig +++ b/arch/arm/mach-lh7a40x/Kconfig @@ -14,6 +14,7 @@ config MACH_LPD7A400 bool "LPD7A400 Card Engine" select ARCH_LH7A400 # select IDE_POLL + select HAS_TOUCHSCREEN_ADS7843_LH7 help Say Y here if you are using Logic Product Development's LPD7A400 CardEngine. For the time being, the LPD7A400 and @@ -23,6 +24,7 @@ config MACH_LPD7A404 bool "LPD7A404 Card Engine" select ARCH_LH7A404 # select IDE_POLL + select HAS_TOUCHSCREEN_ADC_LH7 help Say Y here if you are using Logic Product Development's LPD7A404 CardEngine. For the time being, the LPD7A400 and @@ -34,6 +36,9 @@ config ARCH_LH7A400 config ARCH_LH7A404 bool +config LPD7A40X_CPLD_SSP + bool + config LH7A40X_CONTIGMEM bool "Disable NUMA Support" depends on ARCH_LH7A40X diff --git a/arch/arm/mach-lh7a40x/Makefile b/arch/arm/mach-lh7a40x/Makefile index e90512d..94b8615 100644 --- a/arch/arm/mach-lh7a40x/Makefile +++ b/arch/arm/mach-lh7a40x/Makefile @@ -4,11 +4,14 @@ # # Object file lists. -obj-y := time.o -obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o -obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o irq-lh7a400.o -obj-$(CONFIG_MACH_LPD7A404) += arch-lpd7a40x.o irq-lh7a404.o - -obj-m := -obj-n := -obj- := +obj-y := time.o clocks.o +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o +obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o irq-lh7a400.o +obj-$(CONFIG_MACH_LPD7A404) += arch-lpd7a40x.o irq-lh7a404.o +obj-$(CONFIG_LPD7A40X_CPLD_SSP) += ssp-cpld.o +obj-$(CONFIG_FB_ARMCLCD) += clcd.o + diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c index 12e2327..c0e6854 100644 --- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c +++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c @@ -23,6 +23,28 @@ #include #include "common.h" +#define CPLD_INT_NETHERNET (1<<0) +#define CPLD_INTMASK_ETHERNET (1<<2) +#if defined (CONFIG_MACH_LPD7A400) +# define CPLD_INT_NTOUCH (1<<1) +# define CPLD_INTMASK_TOUCH (1<<3) +# define CPLD_INT_PEN (1<<4) +# define CPLD_INTMASK_PEN (1<<4) +# define CPLD_INT_PIRQ (1<<4) +#endif +#define CPLD_INTMASK_CPLD (1<<7) +#define CPLD_INT_CPLD (1<<6) + +#define CPLD_CONTROL_SWINT (1<<7) /* Disable all CPLD IRQs */ +#define CPLD_CONTROL_OCMSK (1<<6) /* Mask USB1 connect IRQ */ +#define CPLD_CONTROL_PDRV (1<<5) /* PCC_nDRV high */ +#define CPLD_CONTROL_USB1C (1<<4) /* USB1 connect IRQ active */ +#define CPLD_CONTROL_USB1P (1<<3) /* USB1 power disable */ +#define CPLD_CONTROL_AWKP (1<<2) /* Auto-wakeup disabled */ +#define CPLD_CONTROL_LCD_ENABLE (1<<1) /* LCD Vee enable */ +#define CPLD_CONTROL_WRLAN_NENABLE (1<<0) /* SMC91x power disable */ + + static struct resource smc91x_resources[] = { [0] = { .start = CPLD00_PHYS, @@ -48,12 +70,12 @@ static struct platform_device smc91x_dev static struct resource lh7a40x_usbclient_resources[] = { [0] = { .start = USB_PHYS, - .end = (USB_PHYS + 0xFF), + .end = (USB_PHYS + PAGE_SIZE), .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_USBINTR, - .end = IRQ_USBINTR, + .start = IRQ_USB, + .end = IRQ_USB, .flags = IORESOURCE_IRQ, }, }; @@ -61,7 +83,8 @@ static struct resource lh7a40x_usbclient static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL; static struct platform_device lh7a40x_usbclient_device = { - .name = "lh7a40x_udc", +// .name = "lh7a40x_udc", + .name = "lh7-udc", .id = 0, .dev = { .dma_mask = &lh7a40x_usbclient_dma_mask, @@ -101,7 +124,7 @@ static struct platform_device lh7a404_us #endif -static struct platform_device *lpd7a40x_devs[] __initdata = { +static struct platform_device* lpd7a40x_devs[] __initdata = { &smc91x_device, &lh7a40x_usbclient_device, #if defined (CONFIG_ARCH_LH7A404) @@ -113,29 +136,52 @@ extern void lpd7a400_map_io (void); static void __init lpd7a40x_init (void) { - CPLD_CONTROL |= (1<<6); /* Mask USB1 connection IRQ */ +#if defined (CONFIG_MACH_LPD7A400) + CPLD_CONTROL |= 0 + | CPLD_CONTROL_SWINT /* Disable software interrupt */ + | CPLD_CONTROL_OCMSK; /* Mask USB1 connection IRQ */ CPLD_CONTROL &= ~(0 - | (1<<1) /* Disable LCD */ - | (1<<0) /* Enable WLAN */ + | CPLD_CONTROL_LCD_ENABLE /* Disable LCD */ + | CPLD_CONTROL_WRLAN_NENABLE /* Enable SMC91x */ ); +#endif + +#if defined (CONFIG_MACH_LPD7A404) + CPLD_CONTROL &= ~(0 + | CPLD_CONTROL_WRLAN_NENABLE /* Enable SMC91x */ + ); +#endif platform_add_devices (lpd7a40x_devs, ARRAY_SIZE (lpd7a40x_devs)); +#if defined (CONFIG_FB_ARMCLCD) + lh7a40x_clcd_init (); +#endif } static void lh7a40x_ack_cpld_irq (u32 irq) { - /* CPLD doesn't have ack capability */ + /* CPLD doesn't have ack capability, but some devices may */ + +#if defined (CPLD_INTMASK_TOUCH) + /* The touch control *must* mask the the interrupt because the + * interrupt bit is read by the driver to determine if the pen + * is still down. */ + if (irq == IRQ_TOUCH) + CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH; +#endif } static void lh7a40x_mask_cpld_irq (u32 irq) { switch (irq) { case IRQ_LPD7A40X_ETH_INT: - CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4; + CPLD_INTERRUPTS |= CPLD_INTMASK_ETHERNET; break; - case IRQ_LPD7A400_TS: - CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8; +#if defined (IRQ_TOUCH) + case IRQ_TOUCH: + CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH; break; +#endif } } @@ -143,11 +189,13 @@ static void lh7a40x_unmask_cpld_irq (u32 { switch (irq) { case IRQ_LPD7A40X_ETH_INT: - CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4; + CPLD_INTERRUPTS &= ~CPLD_INTMASK_ETHERNET; break; - case IRQ_LPD7A400_TS: - CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8; +#if defined (IRQ_TOUCH) + case IRQ_TOUCH: + CPLD_INTERRUPTS &= ~CPLD_INTMASK_TOUCH; break; +#endif } } @@ -164,11 +212,13 @@ static void lpd7a40x_cpld_handler (unsig desc->chip->ack (irq); - if ((mask & 0x1) == 0) /* WLAN */ + if ((mask & (1<<0)) == 0) /* WLAN */ IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT); - if ((mask & 0x2) == 0) /* Touch */ - IRQ_DISPATCH (IRQ_LPD7A400_TS); +#if defined (IRQ_TOUCH) + if ((mask & (1<<1)) == 0) /* Touch */ + IRQ_DISPATCH (IRQ_TOUCH); +#endif desc->chip->unmask (irq); /* Level-triggered need this */ } @@ -204,9 +254,21 @@ #endif /* Then, configure CPLD interrupt */ - CPLD_INTERRUPTS = 0x9c; /* Disable all CPLD interrupts */ + /* Disable all CPLD interrupts */ +#if defined (CONFIG_MACH_LPD7A400) + CPLD_INTERRUPTS = CPLD_INTMASK_TOUCH | CPLD_INTMASK_PEN + | CPLD_INTMASK_ETHERNET; + /* *** FIXME: don't know why we need 7 and 4. 7 is way wrong + and 4 is uncefined. */ + // (1<<7)|(1<<4)|(1<<3)|(1<<2); +#endif +#if defined (CONFIG_MACH_LPD7A404) + CPLD_INTERRUPTS = CPLD_INTMASK_ETHERNET; + /* *** FIXME: don't know why we need 6 and 5, neither is defined. */ + // (1<<6)|(1<<5)|(1<<3); +#endif GPIO_PFDD &= ~(1 << pinCPLD); /* Make input */ - GPIO_INTTYPE1 |= (1 << pinCPLD); /* Edge triggered */ + GPIO_INTTYPE1 &= ~(1 << pinCPLD); /* Level triggered */ GPIO_INTTYPE2 &= ~(1 << pinCPLD); /* Active low */ barrier (); GPIO_GPIOFINTEN |= (1 << pinCPLD); /* Enable */ @@ -216,7 +278,7 @@ #endif for (irq = IRQ_BOARD_START; irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) { set_irq_chip (irq, &lpd7a40x_cpld_chip); - set_irq_handler (irq, do_edge_IRQ); + set_irq_handler (irq, do_level_IRQ); set_irq_flags (irq, IRQF_VALID); } @@ -226,91 +288,109 @@ #endif lpd7a40x_cpld_handler); } -static struct map_desc lpd7a400_io_desc[] __initdata = { +static struct map_desc lpd7a40x_io_desc[] __initdata = { { - .virtual = IO_VIRT, + .virtual = IO_VIRT, .pfn = __phys_to_pfn(IO_PHYS), - .length = IO_SIZE, + .length = IO_SIZE, .type = MT_DEVICE - }, { /* Mapping added to work around chip select problems */ + }, + { /* Mapping added to work around chip select problems */ .virtual = IOBARRIER_VIRT, .pfn = __phys_to_pfn(IOBARRIER_PHYS), .length = IOBARRIER_SIZE, .type = MT_DEVICE - }, { + }, + { .virtual = CF_VIRT, .pfn = __phys_to_pfn(CF_PHYS), - .length = CF_SIZE, + .length = CF_SIZE, .type = MT_DEVICE - }, { + }, + { .virtual = CPLD02_VIRT, .pfn = __phys_to_pfn(CPLD02_PHYS), - .length = CPLD02_SIZE, + .length = CPLD02_SIZE, .type = MT_DEVICE - }, { + }, + { .virtual = CPLD06_VIRT, .pfn = __phys_to_pfn(CPLD06_PHYS), - .length = CPLD06_SIZE, + .length = CPLD06_SIZE, + .type = MT_DEVICE + }, + { + .virtual = CPLD08_VIRT, + .pfn = __phys_to_pfn(CPLD08_PHYS), + .length = CPLD08_SIZE, .type = MT_DEVICE - }, { + }, + { .virtual = CPLD08_VIRT, .pfn = __phys_to_pfn(CPLD08_PHYS), - .length = CPLD08_SIZE, + .length = CPLD08_SIZE, .type = MT_DEVICE - }, { + }, + { + .virtual = CPLD0A_VIRT, + .pfn = __phys_to_pfn(CPLD0A_PHYS), + .length = CPLD0A_SIZE, + .type = MT_DEVICE + }, + { .virtual = CPLD0C_VIRT, .pfn = __phys_to_pfn(CPLD0C_PHYS), - .length = CPLD0C_SIZE, + .length = CPLD0C_SIZE, .type = MT_DEVICE - }, { + }, + { .virtual = CPLD0E_VIRT, .pfn = __phys_to_pfn(CPLD0E_PHYS), - .length = CPLD0E_SIZE, + .length = CPLD0E_SIZE, .type = MT_DEVICE - }, { + }, + { .virtual = CPLD10_VIRT, .pfn = __phys_to_pfn(CPLD10_PHYS), - .length = CPLD10_SIZE, + .length = CPLD10_SIZE, .type = MT_DEVICE - }, { + }, + { .virtual = CPLD12_VIRT, .pfn = __phys_to_pfn(CPLD12_PHYS), - .length = CPLD12_SIZE, + .length = CPLD12_SIZE, .type = MT_DEVICE - }, { + }, + { .virtual = CPLD14_VIRT, .pfn = __phys_to_pfn(CPLD14_PHYS), - .length = CPLD14_SIZE, + .length = CPLD14_SIZE, .type = MT_DEVICE - }, { + }, + { .virtual = CPLD16_VIRT, .pfn = __phys_to_pfn(CPLD16_PHYS), - .length = CPLD16_SIZE, + .length = CPLD16_SIZE, .type = MT_DEVICE - }, { + }, + { .virtual = CPLD18_VIRT, .pfn = __phys_to_pfn(CPLD18_PHYS), - .length = CPLD18_SIZE, + .length = CPLD18_SIZE, .type = MT_DEVICE - }, { + }, + { .virtual = CPLD1A_VIRT, .pfn = __phys_to_pfn(CPLD1A_PHYS), - .length = CPLD1A_SIZE, + .length = CPLD1A_SIZE, .type = MT_DEVICE }, - /* This mapping is redundant since the smc driver performs another. */ -/* { CPLD00_VIRT, CPLD00_PHYS, CPLD00_SIZE, MT_DEVICE }, */ }; void __init -lpd7a400_map_io(void) +lpd7a40x_map_io(void) { - iotable_init (lpd7a400_io_desc, ARRAY_SIZE (lpd7a400_io_desc)); - - /* Fixup (improve) Static Memory Controller settings */ - SMC_BCR0 = 0x200039af; /* Boot Flash */ - SMC_BCR6 = 0x1000fbe0; /* CPLD */ - SMC_BCR7 = 0x1000b2c2; /* Compact Flash */ + iotable_init (lpd7a40x_io_desc, ARRAY_SIZE (lpd7a40x_io_desc)); } #ifdef CONFIG_MACH_LPD7A400 @@ -320,7 +400,7 @@ MACHINE_START (LPD7A400, "Logic Product .phys_io = 0x80000000, .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, .boot_params = 0xc0000100, - .map_io = lpd7a400_map_io, + .map_io = lpd7a40x_map_io, .init_irq = lh7a400_init_irq, .timer = &lh7a40x_timer, .init_machine = lpd7a40x_init, @@ -335,7 +415,7 @@ MACHINE_START (LPD7A404, "Logic Product .phys_io = 0x80000000, .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, .boot_params = 0xc0000100, - .map_io = lpd7a400_map_io, + .map_io = lpd7a40x_map_io, .init_irq = lh7a404_init_irq, .timer = &lh7a40x_timer, .init_machine = lpd7a40x_init, diff --git a/arch/arm/mach-lh7a40x/clcd.c b/arch/arm/mach-lh7a40x/clcd.c new file mode 100644 index 0000000..93751fe --- /dev/null +++ b/arch/arm/mach-lh7a40x/clcd.c @@ -0,0 +1,241 @@ +/* + * arch/arm/mach-lh7a40x/clcd.c + * + * Copyright (C) 2004 Marc Singer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include + +//#include +//#include +//#include + +//#include +#include +#include + +#include +#include +#include +#include + +#define HRTFTC_HRSETUP __REG(HRTFTC_PHYS + 0x00) +#define HRTFTC_HRCON __REG(HRTFTC_PHYS + 0x04) +#define HRTFTC_HRTIMING1 __REG(HRTFTC_PHYS + 0x08) +#define HRTFTC_HRTIMING2 __REG(HRTFTC_PHYS + 0x0c) + +#define ALI_SETUP __REG(ALI_PHYS + 0x00) +#define ALI_CONTROL __REG(ALI_PHYS + 0x04) +#define ALI_TIMING1 __REG(ALI_PHYS + 0x08) +#define ALI_TIMING2 __REG(ALI_PHYS + 0x0c) + +#include "lcd-panel.h" + +static void lh7a40x_clcd_disable (struct clcd_fb *fb) +{ +#if defined (CONFIG_MACH_LPD7A400) + CPLD_CONTROL &= ~(1<<1); /* Disable LCD Vee */ +#endif + +#if defined (CONFIG_MACH_LPD7A404) + GPIO_PCD &= ~(1<<3); /* Disable LCD Vee */ +#endif + +#if defined (CONFIG_ARCH_LH7A400) + HRTFTC_HRSETUP &= ~(1<<13); /* Disable HRTFT controller */ +#endif + +#if defined (CONFIG_ARCH_LH7A404) + ALI_SETUP &= ~(1<<13); /* Disable ALI */ +#endif +} + +static void lh7a40x_clcd_enable (struct clcd_fb *fb) +{ + struct clcd_panel_extra* extra + = (struct clcd_panel_extra*) fb->board_data; + +#if defined (CONFIG_MACH_LPD7A400) + CPLD_CONTROL |= (1<<1); /* Enable LCD Vee */ +#endif + +#if defined (CONFIG_MACH_LPD7A404) + GPIO_PCDD &= ~(1<<3); /* Enable LCD Vee */ + GPIO_PCD |= (1<<3); +#endif + +#if defined (CONFIG_ARCH_LH7A400) + + if (extra) { + HRTFTC_HRSETUP + = (1 << 13) + | ((fb->fb.var.xres - 1) << 4) + | 0xc + | (extra->hrmode ? 1 : 0); + HRTFTC_HRCON + = ((extra->clsen ? 1 : 0) << 1) + | ((extra->spsen ? 1 : 0) << 0); + HRTFTC_HRTIMING1 + = (extra->pcdel << 8) + | (extra->revdel << 4) + | (extra->lpdel << 0); + HRTFTC_HRTIMING2 + = (extra->spldel << 9) + | (extra->pc2del << 0); + } + else + HRTFTC_HRSETUP + = (1 << 13) + | 0xc; +#endif + +#if defined (CONFIG_ARCH_LH7A404) + + if (extra) { + ALI_SETUP + = (1 << 13) + | ((fb->fb.var.xres - 1) << 4) + | 0xc + | (extra->hrmode ? 1 : 0); + ALI_CONTROL + = ((extra->clsen ? 1 : 0) << 1) + | ((extra->spsen ? 1 : 0) << 0); + ALI_TIMING1 + = (extra->pcdel << 8) + | (extra->revdel << 4) + | (extra->lpdel << 0); + ALI_TIMING2 + = (extra->spldel << 9) + | (extra->pc2del << 0); + } + else + ALI_SETUP + = (1 << 13) + | 0xc; +#endif + +} + +#define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK) + +static int lh7a40x_clcd_setup (struct clcd_fb *fb) +{ + dma_addr_t dma; + u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres + *(lcd_panel.bpp/8)); + + fb->panel = &lcd_panel; + + /* Enforce the sync polarity defaults */ + if (!(fb->panel->tim2 & TIM2_IHS)) + fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT; + if (!(fb->panel->tim2 & TIM2_IVS)) + fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT; + +#if defined (HAS_LCD_PANEL_EXTRA) + fb->board_data = &lcd_panel_extra; +#endif + + fb->fb.screen_base + = dma_alloc_writecombine (&fb->dev->dev, len, + &dma, GFP_KERNEL); + printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n", + fb->fb.screen_base, (void*) dma, len, + (void*) io_p2v (CLCDC_PHYS)); + printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock); + + if (!fb->fb.screen_base) { + printk(KERN_ERR "CLCD: unable to map framebuffer\n"); + return -ENOMEM; + } + +#if defined (USE_RGB555) + fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */ +#endif + + fb->fb.fix.smem_start = dma; + fb->fb.fix.smem_len = len; + + /* Drive PE4 high to prevent CPLD crash */ + GPIO_PEDD |= (1<<4); + GPIO_PED |= (1<<4); + + GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */ + +// fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb); +// fb->fb.fbops->fb_set_par (&fb->fb); + + return 0; +} + +static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma) +{ + return dma_mmap_writecombine(&fb->dev->dev, vma, + fb->fb.screen_base, + fb->fb.fix.smem_start, + fb->fb.fix.smem_len); +} + +static void lh7a40x_clcd_remove (struct clcd_fb *fb) +{ + dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len, + fb->fb.screen_base, fb->fb.fix.smem_start); +} + +static struct clcd_board clcd_platform_data = { + .name = "lh7a40x FB", + .check = clcdfb_check, + .decode = clcdfb_decode, + .enable = lh7a40x_clcd_enable, + .setup = lh7a40x_clcd_setup, + .mmap = lh7a40x_clcd_mmap, + .remove = lh7a40x_clcd_remove, + .disable = lh7a40x_clcd_disable, +}; + +#define IRQ_CLCDC (IRQ_LCDINTR) + +#define AMBA_DEVICE(name,busid,base,plat,pid) \ +static struct amba_device name##_device = { \ + .dev = { \ + .coherent_dma_mask = ~0, \ + .bus_id = busid, \ + .platform_data = plat, \ + }, \ + .res = { \ + .start = base##_PHYS, \ + .end = (base##_PHYS) + (4*1024) - 1, \ + .flags = IORESOURCE_MEM, \ + }, \ + .dma_mask = ~0, \ + .irq = { IRQ_##base, }, \ + /* .dma = base##_DMA,*/ \ + .periphid = pid, \ +} + +AMBA_DEVICE(clcd, "cldc-lh7a40x", CLCDC, &clcd_platform_data, 0x41110); + +static struct amba_device *amba_devs[] __initdata = { + &clcd_device, +}; + +void __init lh7a40x_clcd_init (void) +{ + int i; + int result; + printk ("CLCD: registering amba devices\n"); + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + result = amba_device_register(d, &iomem_resource); + printk (" %d -> %d\n", i ,result); + } +} diff --git a/arch/arm/mach-lh7a40x/clocks.c b/arch/arm/mach-lh7a40x/clocks.c new file mode 100644 index 0000000..2291afe --- /dev/null +++ b/arch/arm/mach-lh7a40x/clocks.c @@ -0,0 +1,199 @@ +/* arch/arm/mach-lh7a40x/clocks.c + * + * Copyright (C) 2004 Marc Singer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +struct module; +struct icst525_params; + +struct clk { + struct list_head node; + unsigned long rate; + struct module *owner; + const char *name; +// void *data; +// const struct icst525_params *params; +// void (*setvco)(struct clk *, struct icst525_vco vco); +}; + +int clk_register(struct clk *clk); +void clk_unregister(struct clk *clk); + +/* ----- */ + +#define MAINDIV1(c) (((c) >> 7) & 0x0f) +#define MAINDIV2(c) (((c) >> 11) & 0x1f) +#define PS(c) (((c) >> 18) & 0x03) +#define PREDIV(c) (((c) >> 2) & 0x1f) +#define HCLKDIV(c) (((c) >> 0) & 0x02) +#define PCLKDIV(c) (((c) >> 16) & 0x03) + +unsigned int cpufreq_get (unsigned int cpu) /* in kHz */ +{ + return fclkfreq_get ()/1000; +} +EXPORT_SYMBOL(cpufreq_get); + +unsigned int fclkfreq_get (void) +{ + unsigned int clkset = CSC_CLKSET; + unsigned int gclk + = XTAL_IN + / (1 << PS(clkset)) + * (MAINDIV1(clkset) + 2) + / (PREDIV(clkset) + 2) + * (MAINDIV2(clkset) + 2) + ; + return gclk; +} + +unsigned int hclkfreq_get (void) +{ + unsigned int clkset = CSC_CLKSET; + unsigned int hclk = fclkfreq_get () / (HCLKDIV(clkset) + 1); + + return hclk; +} + +unsigned int pclkfreq_get (void) +{ + unsigned int clkset = CSC_CLKSET; + int pclkdiv = PCLKDIV(clkset); + unsigned int pclk; + if (pclkdiv == 0x3) + pclkdiv = 0x2; + pclk = hclkfreq_get () / (1 << pclkdiv); + + return pclk; +} + +/* ----- */ + +static LIST_HEAD(clocks); +static DECLARE_MUTEX(clocks_sem); + +struct clk *clk_get (struct device *dev, const char *id) +{ + struct clk *p; + struct clk *clk = ERR_PTR(-ENOENT); + + down (&clocks_sem); + list_for_each_entry (p, &clocks, node) { + if (strcmp (id, p->name) == 0 + && try_module_get(p->owner)) { + clk = p; + break; + } + } + up (&clocks_sem); + + return clk; +} +EXPORT_SYMBOL(clk_get); + +void clk_put (struct clk *clk) +{ + module_put(clk->owner); +} +EXPORT_SYMBOL(clk_put); + +int clk_enable (struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable (struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +int clk_use (struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_use); + +void clk_unuse (struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_unuse); + +unsigned long clk_get_rate (struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate (struct clk *clk, unsigned long rate) +{ + return rate; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate (struct clk *clk, unsigned long rate) +{ + int ret = -EIO; + return ret; +} +EXPORT_SYMBOL(clk_set_rate); + +#if 0 +/* + * These are fixed clocks. + */ +static struct clk kmi_clk = { + .name = "KMIREFCLK", + .rate = 24000000, +}; + +static struct clk uart_clk = { + .name = "UARTCLK", + .rate = 24000000, +}; + +static struct clk mmci_clk = { + .name = "MCLK", + .rate = 33000000, +}; +#endif + +static struct clk clcd_clk = { + .name = "CLCDCLK", + .rate = 0, +}; + +int clk_register (struct clk *clk) +{ + down (&clocks_sem); + list_add (&clk->node, &clocks); + up (&clocks_sem); + return 0; +} +EXPORT_SYMBOL(clk_register); + +void clk_unregister (struct clk *clk) +{ + down (&clocks_sem); + list_del (&clk->node); + up (&clocks_sem); +} +EXPORT_SYMBOL(clk_unregister); + +static int __init clk_init (void) +{ + clk_register(&clcd_clk); + return 0; +} +arch_initcall(clk_init); diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h index ea8de7e..18e8bb4 100644 --- a/arch/arm/mach-lh7a40x/common.h +++ b/arch/arm/mach-lh7a40x/common.h @@ -12,6 +12,7 @@ extern struct sys_timer lh7a40x_timer; extern void lh7a400_init_irq (void); extern void lh7a404_init_irq (void); +extern void lh7a40x_clcd_init (void); extern void lh7a40x_init_board_irq (void); #define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs) diff --git a/arch/arm/mach-lh7a40x/irq-lh7a404.c b/arch/arm/mach-lh7a40x/irq-lh7a404.c index e902e3d..2685a81 100644 --- a/arch/arm/mach-lh7a40x/irq-lh7a404.c +++ b/arch/arm/mach-lh7a40x/irq-lh7a404.c @@ -28,13 +28,17 @@ #define USE_PRIORITIES static unsigned char irq_pri_vic1[] = { #if defined (USE_PRIORITIES) -IRQ_GPIO3INTR, + IRQ_GPIO3INTR, /* CPLD */ + IRQ_DMAM2P4, IRQ_DMAM2P5, /* AC97 */ #endif }; static unsigned char irq_pri_vic2[] = { #if defined (USE_PRIORITIES) - IRQ_T3UI, IRQ_GPIO7INTR, + IRQ_T3UI, /* Timer */ + IRQ_GPIO7INTR, /* CPLD */ IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR, + IRQ_LCDINTR, /* LCD */ + IRQ_TSCINTR, /* ADC/Touchscreen */ #endif }; @@ -98,10 +102,19 @@ static struct irqchip lh7a404_gpio_vic2_ /* IRQ initialization */ +#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404) +extern void* branch_irq_lh7a400; +#endif + void __init lh7a404_init_irq (void) { int irq; +#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404) +#define NOP 0xe1a00000 /* mov r0, r0 */ + branch_irq_lh7a400 = NOP; +#endif + VIC1_INTENCLR = 0xffffffff; VIC2_INTENCLR = 0xffffffff; VIC1_INTSEL = 0; /* All IRQs */ diff --git a/arch/arm/mach-lh7a40x/lcd-panel.h b/arch/arm/mach-lh7a40x/lcd-panel.h new file mode 100644 index 0000000..4fb2efc --- /dev/null +++ b/arch/arm/mach-lh7a40x/lcd-panel.h @@ -0,0 +1,346 @@ +/* lcd-panel.h + $Id$ + + written by Marc Singer + 18 Jul 2005 + + Copyright (C) 2005 Marc Singer + + ----------- + DESCRIPTION + ----------- + + Only one panel may be defined at a time. + + The pixel clock is calculated to be no greater than the target. + + Each timing value is accompanied by a specification comment. + + UNITS/MIN/TYP/MAX + + Most of the units will be in clocks. + + USE_RGB555 + + Define this macro to configure the AMBA LCD controller to use an + RGB555 encoding for the pels instead of the normal RGB565. + + LPD9520, LPD79524, LPD7A400, LPD7A404-10, LPD7A404-11 + + These boards are best approximated by 555 for all panels. Some + can use an extra low-order bit of blue in bit 16 of the color + value, but we don't have a way to communicate this non-linear + mapping to the kernel. + +*/ + +#if !defined (__LCD_PANEL_H__) +# define __LCD_PANEL_H__ + +#if defined (MACH_LPD79520)\ + || defined (MACH_LPD79524)\ + || defined (MACH_LPD7A400)\ + || defined (MACH_LPD7A404) +# define USE_RGB555 +#endif + +struct clcd_panel_extra { + unsigned int hrmode; + unsigned int clsen; + unsigned int spsen; + unsigned int pcdel; + unsigned int revdel; + unsigned int lpdel; + unsigned int spldel; + unsigned int pc2del; +}; + +#define NS_TO_CLOCK(ns,c) ((((ns)*((c)/1000) + (1000000 - 1))/1000000)) +#define CLOCK_TO_DIV(e,c) (((c) + (e) - 1)/(e)) + +#if defined CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT + + /* Logic Product Development LCD 3.5" QVGA HRTFT -10 */ + /* Sharp PN LQ035Q7DB02 w/HRTFT controller chip */ + +#define PIX_CLOCK_TARGET (6800000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "3.5in QVGA (LQ035Q7DB02)", + .xres = 240, + .yres = 320, + .pixclock = PIX_CLOCK, + .left_margin = 16, + .right_margin = 21, + .upper_margin = 8, // line/8/8/8 + .lower_margin = 5, + .hsync_len = 61, + .vsync_len = NS_TO_CLOCK (60, PIX_CLOCK), + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IPC | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#define HAS_LCD_PANEL_EXTRA + +static struct clcd_panel_extra lcd_panel_extra = { + .hrmode = 1, + .clsen = 1, + .spsen = 1, + .pcdel = 8, + .revdel = 7, + .lpdel = 13, + .spldel = 77, + .pc2del = 208, +}; + +#endif + +#if defined CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02 + + /* Logic Product Development LCD 5.7" QVGA -10 */ + /* Sharp PN LQ057Q3DC02 */ + /* QVGA mode, V/Q=LOW */ + +/* From Sharp on 2006.1.3. I believe some of the values are incorrect + * based on the datasheet. + + Timing0 TIMING1 TIMING2 CONTROL + 0x140A0C4C 0x080504EF 0x013F380D 0x00000829 + HBP= 20 VBP= 8 BCD= 0 + HFP= 10 VFP= 5 CPL=319 + HSW= 12 VSW= 1 IOE= 0 + PPL= 19 LPP=239 IPC= 1 + IHS= 1 + IVS= 1 + ACB= 0 + CSEL= 0 + PCD= 13 + + */ + +/* The full horozontal cycle (Th) is clock/360/400/450. */ +/* The full vertical cycle (Tv) is line/251/262/280. */ + +#define PIX_CLOCK_TARGET (6300000) /* -/6.3/7 MHz */ +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "5.7in QVGA (LQ057Q3DC02)", + .xres = 320, + .yres = 240, + .pixclock = PIX_CLOCK, + .left_margin = 11, + .right_margin = 400-11-320-2, + .upper_margin = 7, // line/7/7/7 + .lower_margin = 262-7-240-2, + .hsync_len = 2, // clk/2/96/200 + .vsync_len = 2, // line/2/-/34 + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + +#if defined CONFIG_FB_ARMCLCD_SHARP_LQ64D343 + + /* Logic Product Development LCD 6.4" VGA -10 */ + /* Sharp PN LQ64D343 */ + +/* The full horozontal cycle (Th) is clock/750/800/900. */ +/* The full vertical cycle (Tv) is line/515/525/560. */ + +#define PIX_CLOCK_TARGET (28330000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "6.4in QVGA (LQ64D343)", + .xres = 640, + .yres = 480, + .pixclock = PIX_CLOCK, + .left_margin = 32, + .right_margin = 800-32-640-96, + .upper_margin = 32, // line/34/34/34 + .lower_margin = 540-32-480-2, + .hsync_len = 96, // clk/2/96/200 + .vsync_len = 2, // line/2/-/34 + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + +#if defined CONFIG_FB_ARMCLCD_SHARP_LQ10D368 + + /* Logic Product Development LCD 10.4" VGA -10 */ + /* Sharp PN LQ10D368 */ + +#define PIX_CLOCK_TARGET (28330000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "10.4in VGA (LQ10D368)", + .xres = 640, + .yres = 480, + .pixclock = PIX_CLOCK, + .left_margin = 21, + .right_margin = 15, + .upper_margin = 34, + .lower_margin = 5, + .hsync_len = 96, + .vsync_len = 16, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + +#if defined CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41 + + /* Logic Product Development LCD 12.1" SVGA -10 */ + /* Sharp PN LQ121S1DG41, was LQ121S1DG31 */ + +/* Note that with a 99993900 Hz HCLK, it is not possible to hit the + * target clock frequency range of 35MHz to 42MHz. */ + +/* If the target pixel clock is substantially lower than the panel + * spec, this is done to prevent the LCD display from glitching when + * the CPU is under load. A pixel clock higher than 25MHz + * (empirically determined) will compete with the CPU for bus cycles + * for the Ethernet chip. However, even a pixel clock of 10MHz + * competes with Compact Flash interface during some operations + * (fdisk, e2fsck). And, at that speed the display may have a visible + * flicker. */ + +/* The full horozontal cycle (Th) is clock/832/1056/1395. */ + +#define PIX_CLOCK_TARGET (20000000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "12.1in SVGA (LQ121S1DG41)", + .xres = 800, + .yres = 600, + .pixclock = PIX_CLOCK, + .left_margin = 89, // ns/5/-/(1/PIX_CLOCK)-10 + .right_margin = 1056-800-89-128, + .upper_margin = 23, // line/23/23/23 + .lower_margin = 44, + .hsync_len = 128, // clk/2/128/200 + .vsync_len = 4, // line/2/4/6 + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + +#if defined CONFIG_FB_ARMCLCD_HITACHI + + /* Hitachi*/ + /* Submitted by Michele Da Rold */ + +#define PIX_CLOCK_TARGET (49000000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "Hitachi 800x480", + .xres = 800, + .yres = 480, + .pixclock = PIX_CLOCK, + .left_margin = 88, + .right_margin = 40, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 128, + .vsync_len = 2, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IPC | TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + + +#if defined CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE + + /* AU Optotronics A070VW01 7.0 Wide Screen color Display*/ + /* Submitted by Michele Da Rold */ + +#define PIX_CLOCK_TARGET (10000000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "7.0in Wide (A070VW01)", + .xres = 480, + .yres = 234, + .pixclock = PIX_CLOCK, + .left_margin = 30, + .right_margin = 25, + .upper_margin = 14, + .lower_margin = 12, + .hsync_len = 100, + .vsync_len = 1, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IPC | TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + +#undef NS_TO_CLOCK +#undef CLOCK_TO_DIV + +#endif /* __LCD_PANEL_H__ */ diff --git a/arch/arm/mach-lh7a40x/ssp-cpld.c b/arch/arm/mach-lh7a40x/ssp-cpld.c new file mode 100644 index 0000000..a108301 --- /dev/null +++ b/arch/arm/mach-lh7a40x/ssp-cpld.c @@ -0,0 +1,343 @@ +/* arch/arm/mach-lh7a40x/ssp-cpld.c + * + * Copyright (C) 2004,2005 Marc Singer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * SSP/SPI driver for the CardEngine CPLD. + * + */ + +/* NOTES + ----- + + o *** This driver is cribbed from the 7952x implementation. + Some comments may not apply. + + o This driver contains sufficient logic to control either the + serial EEPROMs or the audio codec. It is included in the kernel + to support the codec. The EEPROMs are really the responsibility + of the boot loader and should probably be left alone. + + o The code must be augmented to cope with multiple, simultaneous + clients. + o The audio codec writes to the codec chip whenever playback + starts. + o The touchscreen driver writes to the ads chip every time it + samples. + o The audio codec must write 16 bits, but the touch chip writes + are 8 bits long. + o We need to be able to keep these configurations separate while + simultaneously active. + + */ + +#include +#include +//#include +#include +#include +//#include +#include +#include +#include + +#include +#include +#include + +#include + +//#define TALK + +#if defined (TALK) +#define PRINTK(f...) printk (f) +#else +#define PRINTK(f...) do {} while (0) +#endif + +#if defined (CONFIG_ARCH_LH7A400) +# define CPLD_SPID __REGP16(CPLD06_VIRT) /* SPI data */ +# define CPLD_SPIC __REGP16(CPLD08_VIRT) /* SPI control */ +# define CPLD_SPIC_CS_CODEC (1<<0) +# define CPLD_SPIC_CS_TOUCH (1<<1) +# define CPLD_SPIC_WRITE (0<<2) +# define CPLD_SPIC_READ (1<<2) +# define CPLD_SPIC_DONE (1<<3) /* r/o */ +# define CPLD_SPIC_LOAD (1<<4) +# define CPLD_SPIC_START (1<<4) +# define CPLD_SPIC_LOADED (1<<5) /* r/o */ +#endif + +#define CPLD_SPI __REGP16(CPLD0A_VIRT) /* SPI operation */ +#define CPLD_SPI_CS_EEPROM (1<<3) +#define CPLD_SPI_SCLK (1<<2) +#define CPLD_SPI_TX_SHIFT (1) +#define CPLD_SPI_TX (1< %2d", v & 0x1ff, (v >> 9) & 0x7f); +#endif + PRINTK ("\n"); + + if (ssp_configuration.device == DEVICE_CODEC) + select = CPLD_SPIC_CS_CODEC; + if (ssp_configuration.device == DEVICE_TOUCH) + select = CPLD_SPIC_CS_TOUCH; + if (cwrite) { + for (cwrite = (cwrite + 7)/8; cwrite-- > 0; ) { + CPLD_SPID = (v >> (8*cwrite)) & 0xff; + CPLD_SPIC = select | CPLD_SPIC_LOAD; + while (!(CPLD_SPIC & CPLD_SPIC_LOADED)) + ; + CPLD_SPIC = select; + while (!(CPLD_SPIC & CPLD_SPIC_DONE)) + ; + } + v = 0; + } + if (cread) { + mdelay (2); /* *** FIXME: required by ads7843? */ + v = 0; + for (cread = (cread + 7)/8; cread-- > 0;) { + CPLD_SPID = 0; + CPLD_SPIC = select | CPLD_SPIC_READ + | CPLD_SPIC_START; + while (!(CPLD_SPIC & CPLD_SPIC_LOADED)) + ; + CPLD_SPIC = select | CPLD_SPIC_READ; + while (!(CPLD_SPIC & CPLD_SPIC_DONE)) + ; + v = (v << 8) | CPLD_SPID; + } + } + return v; + } +#endif + + PRINTK ("spi(%d) 0x%04x -> 0x%x\r\n", ssp_configuration.device, + v & 0x1ff, (v >> 9) & 0x7f); + + enable_cs (); + + v <<= CPLD_SPI_TX_SHIFT; /* Correction for position of SPI_TX bit */ + while (cwrite--) { + CPLD_SPI + = (CPLD_SPI & ~CPLD_SPI_TX) + | ((v >> cwrite) & CPLD_SPI_TX); + udelay (T_DIS); + pulse_clock (); + } + + if (cread < 0) { + int delay = 10; + disable_cs (); + udelay (1); + enable_cs (); + + l = -1; + do { + if (CPLD_SPI & CPLD_SPI_RX) { + l = 0; + break; + } + } while (udelay (1), --delay); + } + else + /* We pulse the clock before the data to skip the leading zero. */ + while (cread-- > 0) { + pulse_clock (); + l = (l<<1) + | (((CPLD_SPI & CPLD_SPI_RX) + >> CPLD_SPI_RX_SHIFT) & 0x1); + } + + disable_cs (); + return l; +} + +static int ssp_init (void) +{ + spin_lock_init (&ssp_lock); + memset (&ssp_configuration, 0, sizeof (ssp_configuration)); + return 0; +} + + +/* ssp_chip_select + + drops the chip select line for the CPLD shift-register controlled + devices. It doesn't enable chip + +*/ + +static void ssp_chip_select (int enable) +{ +#if defined (CONFIG_MACH_LPD7A400) + int select; + + if (ssp_configuration.device == DEVICE_CODEC) + select = CPLD_SPIC_CS_CODEC; + else if (ssp_configuration.device == DEVICE_TOUCH) + select = CPLD_SPIC_CS_TOUCH; + else + return; + + if (enable) + CPLD_SPIC = select; + else + CPLD_SPIC = 0; +#endif +} + +static void ssp_acquire (void) +{ + spin_lock (&ssp_lock); +} + +static void ssp_release (void) +{ + ssp_chip_select (0); /* just in case */ + spin_unlock (&ssp_lock); +} + +static int ssp_configure (int device, int mode, int speed, + int frame_size_write, int frame_size_read) +{ + ssp_configuration.device = device; + ssp_configuration.mode = mode; + ssp_configuration.speed = speed; + ssp_configuration.frame_size_write = frame_size_write; + ssp_configuration.frame_size_read = frame_size_read; + + return 0; +} + +static int ssp_read (void) +{ + return execute_spi_command (0, 0, ssp_configuration.frame_size_read); +} + +static int ssp_write (u16 data) +{ + execute_spi_command (data, ssp_configuration.frame_size_write, 0); + return 0; +} + +static int ssp_write_read (u16 data) +{ + return execute_spi_command (data, ssp_configuration.frame_size_write, + ssp_configuration.frame_size_read); +} + +struct ssp_driver lh7a40x_cpld_ssp_driver = { + .init = ssp_init, + .acquire = ssp_acquire, + .release = ssp_release, + .configure = ssp_configure, + .chip_select = ssp_chip_select, + .read = ssp_read, + .write = ssp_write, + .write_read = ssp_write_read, +}; + + +MODULE_AUTHOR("Marc Singer"); +MODULE_DESCRIPTION("LPD7A40X CPLD SPI driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c index be377e3..ef9af37 100644 --- a/arch/arm/mach-lh7a40x/time.c +++ b/arch/arm/mach-lh7a40x/time.c @@ -1,4 +1,4 @@ -/* +/* * arch/arm/mach-lh7a40x/time.c * * Copyright (C) 2004 Logic Product Development @@ -57,7 +57,7 @@ static struct irqaction lh7a40x_timer_ir .handler = lh7a40x_timer_interrupt, }; -static void __init lh7a40x_timer_init(void) +static void __init lh7a40x_timer_init (void) { /* Stop/disable all timers */ TIMER_CONTROL1 = 0; diff --git a/arch/arm/mach-netx/Kconfig b/arch/arm/mach-netx/Kconfig new file mode 100644 index 0000000..3d90ef1 --- /dev/null +++ b/arch/arm/mach-netx/Kconfig @@ -0,0 +1,24 @@ +menu "NetX Implementations" + depends on ARCH_NETX + +config MACH_NXDKN + bool "Enable Hilscher nxdkn Eval Board support" + depends on ARCH_NETX + help + Board support for the Hilscher NetX Eval Board + +config MACH_NXDB500 + bool "Enable Hilscher nxdb500 Eval Board support" + depends on ARCH_NETX + select ARM_AMBA + help + Board support for the Hilscher nxdb500 Eval Board + +config MACH_NXEB500HMI + bool "Enable Hilscher nxeb500hmi Eval Board support" + depends on ARCH_NETX + select ARM_AMBA + help + Board support for the Hilscher nxeb500hmi Eval Board + +endmenu diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile new file mode 100644 index 0000000..18785ff --- /dev/null +++ b/arch/arm/mach-netx/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). + +# Object file lists. + +obj-y += time.o generic.o pfifo.o xc.o + +# Specific board support +obj-$(CONFIG_MACH_NXDKN) += nxdkn.o +obj-$(CONFIG_MACH_NXDB500) += nxdb500.o fb.o +obj-$(CONFIG_MACH_NXEB500HMI) += nxeb500hmi.o fb.o diff --git a/arch/arm/mach-netx/Makefile.boot b/arch/arm/mach-netx/Makefile.boot new file mode 100644 index 0000000..b81cf6a --- /dev/null +++ b/arch/arm/mach-netx/Makefile.boot @@ -0,0 +1,2 @@ + zreladdr-y := 0x80008000 + diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c new file mode 100644 index 0000000..ef0ab61 --- /dev/null +++ b/arch/arm/mach-netx/fb.c @@ -0,0 +1,114 @@ +/* + * arch/arm/mach-netx/fb.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include +#include + +struct clk {}; + +static struct clk fb_clk; + +static struct clcd_panel *netx_panel; + +void netx_clcd_enable(struct clcd_fb *fb) +{ +} + +int netx_clcd_setup(struct clcd_fb *fb) +{ + dma_addr_t dma; + + fb->panel = netx_panel; + + fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, 1024*1024, + &dma, GFP_KERNEL); + if (!fb->fb.screen_base) { + printk(KERN_ERR "CLCD: unable to map framebuffer\n"); + return -ENOMEM; + } + + fb->fb.fix.smem_start = dma; + fb->fb.fix.smem_len = 1024*1024; + + return 0; +} + +int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) +{ + return dma_mmap_writecombine(&fb->dev->dev, vma, + fb->fb.screen_base, + fb->fb.fix.smem_start, + fb->fb.fix.smem_len); +} + +void netx_clcd_remove(struct clcd_fb *fb) +{ + dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, + fb->fb.screen_base, fb->fb.fix.smem_start); +} + +void clk_disable(struct clk *clk) +{ +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} + +int clk_enable(struct clk *clk) +{ + return 0; +} + +struct clk *clk_get(struct device *dev, const char *id) +{ + return &fb_clk; +} + +void clk_put(struct clk *clk) +{ +} + +static struct amba_device fb_device = { + .dev = { + .bus_id = "fb", + .coherent_dma_mask = ~0, + }, + .res = { + .start = 0x00104000, + .end = 0x00104fff, + .flags = IORESOURCE_MEM, + }, + .irq = { NETX_IRQ_LCD, NO_IRQ }, + .periphid = 0x10112400, +}; + +int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel) +{ + netx_panel = panel; + fb_device.dev.platform_data = board; + return amba_device_register(&fb_device, &iomem_resource); +} diff --git a/arch/arm/mach-netx/fb.h b/arch/arm/mach-netx/fb.h new file mode 100644 index 0000000..4919cf3 --- /dev/null +++ b/arch/arm/mach-netx/fb.h @@ -0,0 +1,24 @@ +/* + * arch/arm/mach-netx/fb.h + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void netx_clcd_enable(struct clcd_fb *fb); +int netx_clcd_setup(struct clcd_fb *fb); +int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma); +void netx_clcd_remove(struct clcd_fb *fb); +int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel); diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c new file mode 100644 index 0000000..af0b135 --- /dev/null +++ b/arch/arm/mach-netx/generic.c @@ -0,0 +1,193 @@ +/* + * arch/arm/mach-netx/generic.c + * + * Copyright (C) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct map_desc netx_io_desc[] __initdata = { + { + .virtual = NETX_IO_VIRT, + .pfn = __phys_to_pfn(NETX_IO_PHYS), + .length = NETX_IO_SIZE, + .type = MT_DEVICE + } +}; + +void __init netx_map_io(void) +{ + iotable_init(netx_io_desc, ARRAY_SIZE(netx_io_desc)); +} + +static struct resource netx_rtc_resources[] = { + [0] = { + .start = 0x00101200, + .end = 0x00101220, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device netx_rtc_device = { + .name = "netx-rtc", + .id = 0, + .num_resources = ARRAY_SIZE(netx_rtc_resources), + .resource = netx_rtc_resources, +}; + +static struct platform_device *devices[] __initdata = { + &netx_rtc_device, +}; + +#if 0 +#define DEBUG_IRQ(fmt...) printk(fmt) +#else +#define DEBUG_IRQ(fmt...) while (0) {} +#endif + +static void +netx_hif_demux_handler(unsigned int irq_unused, struct irqdesc *desc, + struct pt_regs *regs) +{ + unsigned int irq = NETX_IRQ_HIF_CHAINED(0); + unsigned int stat; + + stat = ((readl(NETX_DPMAS_INT_EN) & + readl(NETX_DPMAS_INT_STAT)) >> 24) & 0x1f; + + desc = irq_desc + NETX_IRQ_HIF_CHAINED(0); + + while (stat) { + if (stat & 1) { + DEBUG_IRQ("handling irq %d\n", irq); + desc_handle_irq(irq, desc, regs); + } + irq++; + desc++; + stat >>= 1; + } +} + +static int +netx_hif_irq_type(unsigned int _irq, unsigned int type) +{ + unsigned int val, irq; + + val = readl(NETX_DPMAS_IF_CONF1); + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + + if (type & __IRQT_RISEDGE) { + DEBUG_IRQ("rising edges\n"); + val |= (1 << 26) << irq; + } + if (type & __IRQT_FALEDGE) { + DEBUG_IRQ("falling edges\n"); + val &= ~((1 << 26) << irq); + } + if (type & __IRQT_LOWLVL) { + DEBUG_IRQ("low level\n"); + val &= ~((1 << 26) << irq); + } + if (type & __IRQT_HIGHLVL) { + DEBUG_IRQ("high level\n"); + val |= (1 << 26) << irq; + } + + writel(val, NETX_DPMAS_IF_CONF1); + + return 0; +} + +static void +netx_hif_ack_irq(unsigned int _irq) +{ + unsigned int val, irq; + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + writel((1 << 24) << irq, NETX_DPMAS_INT_STAT); + + val = readl(NETX_DPMAS_INT_EN); + val &= ~((1 << 24) << irq); + writel(val, NETX_DPMAS_INT_EN); + + DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq); +} + +static void +netx_hif_mask_irq(unsigned int _irq) +{ + unsigned int val, irq; + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + val = readl(NETX_DPMAS_INT_EN); + val &= ~((1 << 24) << irq); + writel(val, NETX_DPMAS_INT_EN); + DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq); +} + +static void +netx_hif_unmask_irq(unsigned int _irq) +{ + unsigned int val, irq; + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + val = readl(NETX_DPMAS_INT_EN); + val |= (1 << 24) << irq; + writel(val, NETX_DPMAS_INT_EN); + DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq); +} + +static struct irqchip netx_hif_chip = { + .ack = netx_hif_ack_irq, + .mask = netx_hif_mask_irq, + .unmask = netx_hif_unmask_irq, + .set_type = netx_hif_irq_type, +}; + +void __init netx_init_irq(void) +{ + int irq; + + vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0); + + for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) { + set_irq_chip(irq, &netx_hif_chip); + set_irq_handler(irq, do_level_IRQ); + set_irq_flags(irq, IRQF_VALID); + } + + writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN); + set_irq_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler); +} + +static int __init netx_init(void) +{ + return platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +subsys_initcall(netx_init); + diff --git a/arch/arm/mach-netx/generic.h b/arch/arm/mach-netx/generic.h new file mode 100644 index 0000000..ede2d35 --- /dev/null +++ b/arch/arm/mach-netx/generic.h @@ -0,0 +1,24 @@ +/* + * arch/arm/mach-netx/generic.h + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +extern void __init netx_map_io(void); +extern void __init netx_init_irq(void); + +struct sys_timer; +extern struct sys_timer netx_timer; diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c new file mode 100644 index 0000000..e4a133d --- /dev/null +++ b/arch/arm/mach-netx/nxdb500.c @@ -0,0 +1,210 @@ +/* + * arch/arm/mach-netx/nxdb500.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "generic.h" +#include "fb.h" + +static struct clcd_panel qvga = { + .mode = { + .name = "QVGA", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 187617, + .left_margin = 6, + .right_margin = 26, + .upper_margin = 0, + .lower_margin = 6, + .hsync_len = 6, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = 16, + .cntl = CNTL_LCDTFT | CNTL_BGR, + .bpp = 16, + .grayscale = 0, +}; + +static inline int nxdb500_check(struct clcd_fb *fb, struct fb_var_screeninfo *var) +{ + var->green.length = 5; + var->green.msb_right = 0; + + return clcdfb_check(fb, var); +} + +static int nxdb500_clcd_setup(struct clcd_fb *fb) +{ + unsigned int val; + + fb->fb.var.green.length = 5; + fb->fb.var.green.msb_right = 0; + + /* enable asic control */ + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(3, NETX_SYSTEM_IOC_CR); + + val = readl(NETX_PIO_OUTPIO); + writel(val | 1, NETX_PIO_OUTPIO); + + val = readl(NETX_PIO_OEPIO); + writel(val | 1, NETX_PIO_OEPIO); + return netx_clcd_setup(fb); +} + +static struct clcd_board clcd_data = { + .name = "netX", + .check = nxdb500_check, + .decode = clcdfb_decode, + .enable = netx_clcd_enable, + .setup = nxdb500_clcd_setup, + .mmap = netx_clcd_mmap, + .remove = netx_clcd_remove, +}; + +static struct netxeth_platform_data eth0_platform_data = { + .xcno = 0, +}; + +static struct platform_device netx_eth0_device = { + .name = "netx-eth", + .id = 0, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð0_platform_data, + } +}; + +static struct netxeth_platform_data eth1_platform_data = { + .xcno = 1, +}; + +static struct platform_device netx_eth1_device = { + .name = "netx-eth", + .id = 1, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð1_platform_data, + } +}; + +static struct resource netx_uart0_resources[] = { + [0] = { + .start = 0x00100A00, + .end = 0x00100A3F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART0), + .end = (NETX_IRQ_UART0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart0_device = { + .name = "netx-uart", + .id = 0, + .num_resources = ARRAY_SIZE(netx_uart0_resources), + .resource = netx_uart0_resources, +}; + +static struct resource netx_uart1_resources[] = { + [0] = { + .start = 0x00100A40, + .end = 0x00100A7F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART1), + .end = (NETX_IRQ_UART1), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart1_device = { + .name = "netx-uart", + .id = 1, + .num_resources = ARRAY_SIZE(netx_uart1_resources), + .resource = netx_uart1_resources, +}; + +static struct resource netx_uart2_resources[] = { + [0] = { + .start = 0x00100A80, + .end = 0x00100ABF, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART2), + .end = (NETX_IRQ_UART2), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart2_device = { + .name = "netx-uart", + .id = 2, + .num_resources = ARRAY_SIZE(netx_uart2_resources), + .resource = netx_uart2_resources, +}; + +static struct platform_device *devices[] __initdata = { + &netx_eth0_device, + &netx_eth1_device, + &netx_uart0_device, + &netx_uart1_device, + &netx_uart2_device, +}; + +static void __init nxdb500_init(void) +{ + netx_fb_init(&clcd_data, &qvga); + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(NXDB500, "Hilscher nxdb500") + .phys_io = 0x00100000, + .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = netx_map_io, + .init_irq = netx_init_irq, + .timer = &netx_timer, + .init_machine = nxdb500_init, +MACHINE_END diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c new file mode 100644 index 0000000..7e26c42 --- /dev/null +++ b/arch/arm/mach-netx/nxdkn.c @@ -0,0 +1,103 @@ +/* + * arch/arm/mach-netx/nxdkn.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "generic.h" + +static struct netxeth_platform_data eth0_platform_data = { + .xcno = 0, +}; + +static struct platform_device nxdkn_eth0_device = { + .name = "netx-eth", + .id = 0, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð0_platform_data, + } +}; + +static struct netxeth_platform_data eth1_platform_data = { + .xcno = 1, +}; + +static struct platform_device nxdkn_eth1_device = { + .name = "netx-eth", + .id = 1, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð1_platform_data, + } +}; + +static struct resource netx_uart0_resources[] = { + [0] = { + .start = 0x00100A00, + .end = 0x00100A3F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART0), + .end = (NETX_IRQ_UART0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart0_device = { + .name = "netx-uart", + .id = 0, + .num_resources = ARRAY_SIZE(netx_uart0_resources), + .resource = netx_uart0_resources, +}; + +static struct platform_device *devices[] __initdata = { + &nxdkn_eth0_device, + &nxdkn_eth1_device, + &netx_uart0_device, +}; + +static void __init nxdkn_init(void) +{ + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(NXDKN, "Hilscher nxdkn") + .phys_io = 0x00100000, + .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = netx_map_io, + .init_irq = netx_init_irq, + .timer = &netx_timer, + .init_machine = nxdkn_init, +MACHINE_END diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c new file mode 100644 index 0000000..53e10a9 --- /dev/null +++ b/arch/arm/mach-netx/nxeb500hmi.c @@ -0,0 +1,187 @@ +/* + * arch/arm/mach-netx/nxeb500hmi.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "generic.h" +#include "fb.h" + +static struct clcd_panel qvga = { + .mode = { + .name = "QVGA", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 187617, + .left_margin = 6, + .right_margin = 26, + .upper_margin = 0, + .lower_margin = 6, + .hsync_len = 6, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = 16, + .cntl = CNTL_LCDTFT | CNTL_BGR, + .bpp = 16, + .grayscale = 0, +}; + +static inline int nxeb500hmi_check(struct clcd_fb *fb, struct fb_var_screeninfo *var) +{ + var->green.length = 5; + var->green.msb_right = 0; + + return clcdfb_check(fb, var); +} + +static int nxeb500hmi_clcd_setup(struct clcd_fb *fb) +{ + unsigned int val; + + fb->fb.var.green.length = 5; + fb->fb.var.green.msb_right = 0; + + /* enable asic control */ + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(3, NETX_SYSTEM_IOC_CR); + + /* GPIO 14 is used for display enable on newer boards */ + writel(9, NETX_GPIO_CFG(14)); + + val = readl(NETX_PIO_OUTPIO); + writel(val | 1, NETX_PIO_OUTPIO); + + val = readl(NETX_PIO_OEPIO); + writel(val | 1, NETX_PIO_OEPIO); + return netx_clcd_setup(fb); +} + +static struct clcd_board clcd_data = { + .name = "netX", + .check = nxeb500hmi_check, + .decode = clcdfb_decode, + .enable = netx_clcd_enable, + .setup = nxeb500hmi_clcd_setup, + .mmap = netx_clcd_mmap, + .remove = netx_clcd_remove, +}; + +static struct netxeth_platform_data eth0_platform_data = { + .xcno = 0, +}; + +static struct platform_device netx_eth0_device = { + .name = "netx-eth", + .id = 0, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð0_platform_data, + } +}; + +static struct netxeth_platform_data eth1_platform_data = { + .xcno = 1, +}; + +static struct platform_device netx_eth1_device = { + .name = "netx-eth", + .id = 1, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð1_platform_data, + } +}; + +static struct resource netx_cf_resources[] = { + [0] = { + .start = 0x20000000, + .end = 0x25ffffff, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, + }, +}; + +static struct platform_device netx_cf_device = { + .name = "netx-cf", + .id = 0, + .resource = netx_cf_resources, + .num_resources = ARRAY_SIZE(netx_cf_resources), +}; + +static struct resource netx_uart0_resources[] = { + [0] = { + .start = 0x00100A00, + .end = 0x00100A3F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART0), + .end = (NETX_IRQ_UART0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart0_device = { + .name = "netx-uart", + .id = 0, + .num_resources = ARRAY_SIZE(netx_uart0_resources), + .resource = netx_uart0_resources, +}; + +static struct platform_device *devices[] __initdata = { + &netx_eth0_device, + &netx_eth1_device, + &netx_cf_device, + &netx_uart0_device, +}; + +static void __init nxeb500hmi_init(void) +{ + netx_fb_init(&clcd_data, &qvga); + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi") + .phys_io = 0x00100000, + .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = netx_map_io, + .init_irq = netx_init_irq, + .timer = &netx_timer, + .init_machine = nxeb500hmi_init, +MACHINE_END diff --git a/arch/arm/mach-netx/pfifo.c b/arch/arm/mach-netx/pfifo.c new file mode 100644 index 0000000..44dea61 --- /dev/null +++ b/arch/arm/mach-netx/pfifo.c @@ -0,0 +1,68 @@ +/* + * arch/arm/mach-netx/pfifo.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include +#include +#include +#include + +static DEFINE_MUTEX(pfifo_lock); + +static unsigned int pfifo_used = 0; + +int pfifo_request(unsigned int pfifo_mask) +{ + int err = 0; + unsigned int val; + + mutex_lock(&pfifo_lock); + + if (pfifo_mask & pfifo_used) { + err = -EBUSY; + goto out; + } + + pfifo_used |= pfifo_mask; + + val = readl(NETX_PFIFO_RESET); + writel(val | pfifo_mask, NETX_PFIFO_RESET); + writel(val, NETX_PFIFO_RESET); + +out: + mutex_unlock(&pfifo_lock); + return err; +} + +void pfifo_free(unsigned int pfifo_mask) +{ + mutex_lock(&pfifo_lock); + pfifo_used &= ~pfifo_mask; + mutex_unlock(&pfifo_lock); +} + +EXPORT_SYMBOL(pfifo_push); +EXPORT_SYMBOL(pfifo_pop); +EXPORT_SYMBOL(pfifo_fill_level); +EXPORT_SYMBOL(pfifo_empty); +EXPORT_SYMBOL(pfifo_request); +EXPORT_SYMBOL(pfifo_free); diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c new file mode 100644 index 0000000..edfbdf4 --- /dev/null +++ b/arch/arm/mach-netx/time.c @@ -0,0 +1,88 @@ +/* + * arch/arm/mach-netx/time.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include +#include +#include +#include + +/* + * Returns number of us since last clock interrupt. Note that interrupts + * will have been disabled by do_gettimeoffset() + */ +static unsigned long netx_gettimeoffset(void) +{ + return readl(NETX_GPIO_COUNTER_CURRENT(0)) / 100; +} + +/* + * IRQ handler for the timer + */ +static irqreturn_t +netx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + write_seqlock(&xtime_lock); + + timer_tick(regs); + write_sequnlock(&xtime_lock); + + /* acknowledge interrupt */ + writel(COUNTER_BIT(0), NETX_GPIO_IRQ); + + return IRQ_HANDLED; +} + + +static struct irqaction netx_timer_irq = { + .name = "NetX Timer Tick", + .flags = SA_INTERRUPT | SA_TIMER, + .handler = netx_timer_interrupt, +}; + +/* + * Set up timer interrupt + */ +static void __init netx_timer_init(void) +{ + /* disable timer initially */ + writel(0, NETX_GPIO_COUNTER_CTRL(0)); + + /* Reset the timer value to zero */ + writel(0, NETX_GPIO_COUNTER_CURRENT(0)); + + writel(LATCH, NETX_GPIO_COUNTER_MAX(0)); + + /* acknowledge interrupt */ + writel(COUNTER_BIT(0), NETX_GPIO_IRQ); + + /* Enable the interrupt in the specific timer register and start timer */ + writel(COUNTER_BIT(0), NETX_GPIO_IRQ_ENABLE); + writel(NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN, + NETX_GPIO_COUNTER_CTRL(0)); + + setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq); +} + +struct sys_timer netx_timer = { + .init = netx_timer_init, + .offset = netx_gettimeoffset, +}; diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c new file mode 100644 index 0000000..172a058 --- /dev/null +++ b/arch/arm/mach-netx/xc.c @@ -0,0 +1,255 @@ +/* + * arch/arm/mach-netx/xc.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +static DEFINE_MUTEX(xc_lock); + +static int xc_in_use = 0; + +struct fw_desc { + unsigned int ofs; + unsigned int size; + unsigned int patch_ofs; + unsigned int patch_entries; +}; + +struct fw_header { + unsigned int magic; + unsigned int type; + unsigned int version; + unsigned int reserved[5]; + struct fw_desc fw_desc[3]; +} __attribute__ ((packed)); + +int xc_stop(struct xc *x) +{ + writel(RPU_HOLD_PC, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS); + writel(TPU_HOLD_PC, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS); + writel(XPU_HOLD_PC, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS); + return 0; +} + +int xc_start(struct xc *x) +{ + writel(0, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS); + writel(0, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS); + writel(0, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS); + return 0; +} + +int xc_running(struct xc *x) +{ + return (readl(x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS) & RPU_HOLD_PC) + || (readl(x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS) & TPU_HOLD_PC) + || (readl(x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS) & XPU_HOLD_PC) ? + 0 : 1; +} + +int xc_reset(struct xc *x) +{ + writel(0, x->xpec_base + NETX_XPEC_PC_OFS); + return 0; +} + +static int xc_check_ptr(struct xc *x, unsigned long adr, unsigned int size) +{ + if (adr >= NETX_PA_XMAC(x->no) && + adr + size < NETX_PA_XMAC(x->no) + XMAC_MEM_SIZE) + return 0; + + if (adr >= NETX_PA_XPEC(x->no) && + adr + size < NETX_PA_XPEC(x->no) + XPEC_MEM_SIZE) + return 0; + + dev_err(x->dev, "Illegal pointer in firmware found. aborting\n"); + + return -1; +} + +static int xc_patch(struct xc *x, void *patch, int count) +{ + unsigned int val, adr; + unsigned int *data = patch; + + int i; + for (i = 0; i < count; i++) { + adr = *data++; + val = *data++; + if (xc_check_ptr(x, adr, 4) < 0) + return -EINVAL; + + writel(val, (void __iomem *)io_p2v(adr)); + } + return 0; +} + +int xc_request_firmware(struct xc *x) +{ + int ret; + char name[16]; + const struct firmware *fw; + struct fw_header *head; + unsigned int size; + int i; + void *src; + unsigned long dst; + + sprintf(name, "xc%d.bin", x->no); + + ret = request_firmware(&fw, name, x->dev); + + if (ret < 0) { + dev_err(x->dev, "request_firmware failed\n"); + return ret; + } + + head = (struct fw_header *)fw->data; + if (head->magic != 0x4e657458) { + if (head->magic == 0x5874654e) { + dev_err(x->dev, + "firmware magic is 'XteN'. Endianess problems?\n"); + ret = -ENODEV; + goto exit_release_firmware; + } + dev_err(x->dev, "unrecognized firmware magic 0x%08x\n", + head->magic); + ret = -ENODEV; + goto exit_release_firmware; + } + + x->type = head->type; + x->version = head->version; + + ret = -EINVAL; + + for (i = 0; i < 3; i++) { + src = fw->data + head->fw_desc[i].ofs; + dst = *(unsigned int *)src; + src += sizeof (unsigned int); + size = head->fw_desc[i].size - sizeof (unsigned int); + + if (xc_check_ptr(x, dst, size)) + goto exit_release_firmware; + + memcpy((void *)io_p2v(dst), src, size); + + src = fw->data + head->fw_desc[i].patch_ofs; + size = head->fw_desc[i].patch_entries; + ret = xc_patch(x, src, size); + if (ret < 0) + goto exit_release_firmware; + } + + ret = 0; + + exit_release_firmware: + release_firmware(fw); + + return ret; +} + +struct xc *request_xc(int xcno, struct device *dev) +{ + struct xc *x = NULL; + + mutex_lock(&xc_lock); + + if (xcno > 3) + goto exit; + if (xc_in_use & (1 << xcno)) + goto exit; + + x = kmalloc(sizeof (struct xc), GFP_KERNEL); + if (!x) + goto exit; + + if (!request_mem_region + (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, dev->kobj.name)) + goto exit_free; + + if (!request_mem_region + (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, dev->kobj.name)) + goto exit_release_1; + + if (!request_mem_region + (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, dev->kobj.name)) + goto exit_release_2; + + x->xpec_base = (void * __iomem)io_p2v(NETX_PA_XPEC(xcno)); + x->xmac_base = (void * __iomem)io_p2v(NETX_PA_XMAC(xcno)); + x->sram_base = ioremap(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE); + if (!x->sram_base) + goto exit_release_3; + + x->irq = NETX_IRQ_XPEC(xcno); + + x->no = xcno; + x->dev = dev; + + xc_in_use |= (1 << xcno); + + goto exit; + + exit_release_3: + release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE); + exit_release_2: + release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE); + exit_release_1: + release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE); + exit_free: + kfree(x); + x = NULL; + exit: + mutex_unlock(&xc_lock); + return x; +} + +void free_xc(struct xc *x) +{ + int xcno = x->no; + + mutex_lock(&xc_lock); + + iounmap(x->sram_base); + release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE); + release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE); + release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE); + xc_in_use &= ~(1 << x->no); + kfree(x); + + mutex_unlock(&xc_lock); +} + +EXPORT_SYMBOL(free_xc); +EXPORT_SYMBOL(request_xc); +EXPORT_SYMBOL(xc_request_firmware); +EXPORT_SYMBOL(xc_reset); +EXPORT_SYMBOL(xc_running); +EXPORT_SYMBOL(xc_start); +EXPORT_SYMBOL(xc_stop); diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 6178f04..73df32a 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -84,6 +84,15 @@ static struct omap_board_config_kernel a { OMAP_TAG_UART, &ams_delta_uart_config }, }; +static struct platform_device ams_delta_led_device = { + .name = "ams-delta-led", + .id = -1 +}; + +static struct platform_device *ams_delta_devices[] __initdata = { + &ams_delta_led_device, +}; + static void __init ams_delta_init(void) { iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc)); @@ -94,6 +103,8 @@ static void __init ams_delta_init(void) /* Clear latch2 (NAND, LCD, modem enable) */ ams_delta_latch2_write(~0, 0); + + platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices)); } static void __init ams_delta_map_io(void) diff --git a/arch/arm/mach-pnx4008/Makefile b/arch/arm/mach-pnx4008/Makefile new file mode 100644 index 0000000..b457ca0 --- /dev/null +++ b/arch/arm/mach-pnx4008/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for the linux kernel. +# + +obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o +obj-m := +obj-n := +obj- := + +# Power Management +obj-$(CONFIG_PM) += pm.o sleep.o + diff --git a/arch/arm/mach-pnx4008/Makefile.boot b/arch/arm/mach-pnx4008/Makefile.boot new file mode 100644 index 0000000..44c7117 --- /dev/null +++ b/arch/arm/mach-pnx4008/Makefile.boot @@ -0,0 +1,4 @@ + zreladdr-y := 0x80008000 +params_phys-y := 0x80000100 +initrd_phys-y := 0x80800000 + diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c new file mode 100644 index 0000000..f582ed2 --- /dev/null +++ b/arch/arm/mach-pnx4008/clock.c @@ -0,0 +1,983 @@ +/* + * arch/arm/mach-pnx4008/clock.c + * + * Clock control driver for PNX4008 + * + * Authors: Vitaly Wool, Dmitry Chigirev + * Generic clock management functions are partially based on: + * linux/arch/arm/mach-omap/clock.c + * + * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "clock.h" + +/*forward declaration*/ +static struct clk per_ck; +static struct clk hclk_ck; +static struct clk ck_1MHz; +static struct clk ck_13MHz; +static struct clk ck_pll1; +static int local_set_rate(struct clk *clk, u32 rate); + +static inline void clock_lock(void) +{ + local_irq_disable(); +} + +static inline void clock_unlock(void) +{ + local_irq_enable(); +} + +static void propagate_rate(struct clk *clk) +{ + struct clk *tmp_clk; + + tmp_clk = clk; + while (tmp_clk->propagate_next) { + tmp_clk = tmp_clk->propagate_next; + local_set_rate(tmp_clk, tmp_clk->user_rate); + } +} + +static inline void clk_reg_disable(struct clk *clk) +{ + if (clk->enable_reg) + __raw_writel(__raw_readl(clk->enable_reg) & + ~(1 << clk->enable_shift), clk->enable_reg); +} + +static inline void clk_reg_enable(struct clk *clk) +{ + if (clk->enable_reg) + __raw_writel(__raw_readl(clk->enable_reg) | + (1 << clk->enable_shift), clk->enable_reg); +} + +static inline void clk_reg_disable1(struct clk *clk) +{ + if (clk->enable_reg1) + __raw_writel(__raw_readl(clk->enable_reg1) & + ~(1 << clk->enable_shift1), clk->enable_reg1); +} + +static inline void clk_reg_enable1(struct clk *clk) +{ + if (clk->enable_reg1) + __raw_writel(__raw_readl(clk->enable_reg1) | + (1 << clk->enable_shift1), clk->enable_reg1); +} + +static int clk_wait_for_pll_lock(struct clk *clk) +{ + int i; + i = 0; + while (i++ < 0xFFF && !(__raw_readl(clk->scale_reg) & 1)) ; /*wait for PLL to lock */ + + if (!(__raw_readl(clk->scale_reg) & 1)) { + printk(KERN_ERR + "%s ERROR: failed to lock, scale reg data: %x\n", + clk->name, __raw_readl(clk->scale_reg)); + return -1; + } + return 0; +} + +static int switch_to_dirty_13mhz(struct clk *clk) +{ + int i; + int ret; + u32 tmp_reg; + + ret = 0; + + if (!clk->rate) + clk_reg_enable1(clk); + + tmp_reg = __raw_readl(clk->parent_switch_reg); + /*if 13Mhz clock selected, select 13'MHz (dirty) source from OSC */ + if (!(tmp_reg & 1)) { + tmp_reg |= (1 << 1); /* Trigger switch to 13'MHz (dirty) clock */ + __raw_writel(tmp_reg, clk->parent_switch_reg); + i = 0; + while (i++ < 0xFFF && !(__raw_readl(clk->parent_switch_reg) & 1)) ; /*wait for 13'MHz selection status */ + + if (!(__raw_readl(clk->parent_switch_reg) & 1)) { + printk(KERN_ERR + "%s ERROR: failed to select 13'MHz, parent sw reg data: %x\n", + clk->name, __raw_readl(clk->parent_switch_reg)); + ret = -1; + } + } + + if (!clk->rate) + clk_reg_disable1(clk); + + return ret; +} + +static int switch_to_clean_13mhz(struct clk *clk) +{ + int i; + int ret; + u32 tmp_reg; + + ret = 0; + + if (!clk->rate) + clk_reg_enable1(clk); + + tmp_reg = __raw_readl(clk->parent_switch_reg); + /*if 13'Mhz clock selected, select 13MHz (clean) source from OSC */ + if (tmp_reg & 1) { + tmp_reg &= ~(1 << 1); /* Trigger switch to 13MHz (clean) clock */ + __raw_writel(tmp_reg, clk->parent_switch_reg); + i = 0; + while (i++ < 0xFFF && (__raw_readl(clk->parent_switch_reg) & 1)) ; /*wait for 13MHz selection status */ + + if (__raw_readl(clk->parent_switch_reg) & 1) { + printk(KERN_ERR + "%s ERROR: failed to select 13MHz, parent sw reg data: %x\n", + clk->name, __raw_readl(clk->parent_switch_reg)); + ret = -1; + } + } + + if (!clk->rate) + clk_reg_disable1(clk); + + return ret; +} + +static int set_13MHz_parent(struct clk *clk, struct clk *parent) +{ + int ret = -EINVAL; + + if (parent == &ck_13MHz) + ret = switch_to_clean_13mhz(clk); + else if (parent == &ck_pll1) + ret = switch_to_dirty_13mhz(clk); + + return ret; +} + +#define PLL160_MIN_FCCO 156000 +#define PLL160_MAX_FCCO 320000 + +/* + * Calculate pll160 settings. + * Possible input: up to 320MHz with step of clk->parent->rate. + * In PNX4008 parent rate for pll160s may be either 1 or 13MHz. + * Ignored paths: "feedback" (bit 13 set), "div-by-N". + * Setting ARM PLL4 rate to 0 will put CPU into direct run mode. + * Setting PLL5 and PLL3 rate to 0 will disable USB and DSP clock input. + * Please refer to PNX4008 IC manual for details. + */ + +static int pll160_set_rate(struct clk *clk, u32 rate) +{ + u32 tmp_reg, tmp_m, tmp_2p, i; + u32 parent_rate; + int ret = -EINVAL; + + parent_rate = clk->parent->rate; + + if (!parent_rate) + goto out; + + /* set direct run for ARM or disable output for others */ + clk_reg_disable(clk); + + /* disable source input as well (ignored for ARM) */ + clk_reg_disable1(clk); + + tmp_reg = __raw_readl(clk->scale_reg); + tmp_reg &= ~0x1ffff; /*clear all settings, power down */ + __raw_writel(tmp_reg, clk->scale_reg); + + rate -= rate % parent_rate; /*round down the input */ + + if (rate > PLL160_MAX_FCCO) + rate = PLL160_MAX_FCCO; + + if (!rate) { + clk->rate = 0; + ret = 0; + goto out; + } + + clk_reg_enable1(clk); + tmp_reg = __raw_readl(clk->scale_reg); + + if (rate == parent_rate) { + /*enter direct bypass mode */ + tmp_reg |= ((1 << 14) | (1 << 15)); + __raw_writel(tmp_reg, clk->scale_reg); + clk->rate = parent_rate; + clk_reg_enable(clk); + ret = 0; + goto out; + } + + i = 0; + for (tmp_2p = 1; tmp_2p < 16; tmp_2p <<= 1) { + if (rate * tmp_2p >= PLL160_MIN_FCCO) + break; + i++; + } + + if (tmp_2p > 1) + tmp_reg |= ((i - 1) << 11); + else + tmp_reg |= (1 << 14); /*direct mode, no divide */ + + tmp_m = rate * tmp_2p; + tmp_m /= parent_rate; + + tmp_reg |= (tmp_m - 1) << 1; /*calculate M */ + tmp_reg |= (1 << 16); /*power up PLL */ + __raw_writel(tmp_reg, clk->scale_reg); + + if (clk_wait_for_pll_lock(clk) < 0) { + clk_reg_disable(clk); + clk_reg_disable1(clk); + + tmp_reg = __raw_readl(clk->scale_reg); + tmp_reg &= ~0x1ffff; /*clear all settings, power down */ + __raw_writel(tmp_reg, clk->scale_reg); + clk->rate = 0; + ret = -EFAULT; + goto out; + } + + clk->rate = (tmp_m * parent_rate) / tmp_2p; + + if (clk->flags & RATE_PROPAGATES) + propagate_rate(clk); + + clk_reg_enable(clk); + ret = 0; + +out: + return ret; +} + +/*configure PER_CLK*/ +static int per_clk_set_rate(struct clk *clk, u32 rate) +{ + u32 tmp; + + tmp = __raw_readl(clk->scale_reg); + tmp &= ~(0x1f << 2); + tmp |= ((clk->parent->rate / clk->rate) - 1) << 2; + __raw_writel(tmp, clk->scale_reg); + clk->rate = rate; + return 0; +} + +/*configure HCLK*/ +static int hclk_set_rate(struct clk *clk, u32 rate) +{ + u32 tmp; + tmp = __raw_readl(clk->scale_reg); + tmp = tmp & ~0x3; + switch (rate) { + case 1: + break; + case 2: + tmp |= 1; + break; + case 4: + tmp |= 2; + break; + } + + __raw_writel(tmp, clk->scale_reg); + clk->rate = rate; + return 0; +} + +static u32 hclk_round_rate(struct clk *clk, u32 rate) +{ + switch (rate) { + case 1: + case 4: + return rate; + } + return 2; +} + +static u32 per_clk_round_rate(struct clk *clk, u32 rate) +{ + return CLK_RATE_13MHZ; +} + +static int on_off_set_rate(struct clk *clk, u32 rate) +{ + if (rate) { + clk_reg_enable(clk); + clk->rate = 1; + } else { + clk_reg_disable(clk); + clk->rate = 0; + } + return 0; +} + +static int on_off_inv_set_rate(struct clk *clk, u32 rate) +{ + if (rate) { + clk_reg_disable(clk); /*enable bit is inverted */ + clk->rate = 1; + } else { + clk_reg_enable(clk); + clk->rate = 0; + } + return 0; +} + +static u32 on_off_round_rate(struct clk *clk, u32 rate) +{ + return (rate ? 1 : 0); +} + +static u32 pll4_round_rate(struct clk *clk, u32 rate) +{ + if (rate > CLK_RATE_208MHZ) + rate = CLK_RATE_208MHZ; + if (rate == CLK_RATE_208MHZ && hclk_ck.user_rate == 1) + rate = CLK_RATE_208MHZ - CLK_RATE_13MHZ; + return (rate - (rate % (hclk_ck.user_rate * CLK_RATE_13MHZ))); +} + +static u32 pll3_round_rate(struct clk *clk, u32 rate) +{ + if (rate > CLK_RATE_208MHZ) + rate = CLK_RATE_208MHZ; + return (rate - rate % CLK_RATE_13MHZ); +} + +static u32 pll5_round_rate(struct clk *clk, u32 rate) +{ + return (rate ? CLK_RATE_48MHZ : 0); +} + +static u32 ck_13MHz_round_rate(struct clk *clk, u32 rate) +{ + return (rate ? CLK_RATE_13MHZ : 0); +} + +static int ck_13MHz_set_rate(struct clk *clk, u32 rate) +{ + if (rate) { + clk_reg_disable(clk); /*enable bit is inverted */ + udelay(500); + clk->rate = CLK_RATE_13MHZ; + ck_1MHz.rate = CLK_RATE_1MHZ; + } else { + clk_reg_enable(clk); + clk->rate = 0; + ck_1MHz.rate = 0; + } + return 0; +} + +static int pll1_set_rate(struct clk *clk, u32 rate) +{ +#if 0 /* doesn't work on some boards, probably a HW BUG */ + if (rate) { + clk_reg_disable(clk); /*enable bit is inverted */ + if (!clk_wait_for_pll_lock(clk)) { + clk->rate = CLK_RATE_13MHZ; + } else { + clk_reg_enable(clk); + clk->rate = 0; + } + + } else { + clk_reg_enable(clk); + clk->rate = 0; + } +#endif + return 0; +} + +/* Clock sources */ + +static struct clk osc_13MHz = { + .name = "osc_13MHz", + .flags = FIXED_RATE, + .rate = CLK_RATE_13MHZ, +}; + +static struct clk ck_13MHz = { + .name = "ck_13MHz", + .parent = &osc_13MHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &ck_13MHz_round_rate, + .set_rate = &ck_13MHz_set_rate, + .enable_reg = OSC13CTRL_REG, + .enable_shift = 0, + .rate = CLK_RATE_13MHZ, +}; + +static struct clk osc_32KHz = { + .name = "osc_32KHz", + .flags = FIXED_RATE, + .rate = CLK_RATE_32KHZ, +}; + +/*attached to PLL5*/ +static struct clk ck_1MHz = { + .name = "ck_1MHz", + .flags = FIXED_RATE | PARENT_SET_RATE, + .parent = &ck_13MHz, +}; + +/* PLL1 (397) - provides 13' MHz clock */ +static struct clk ck_pll1 = { + .name = "ck_pll1", + .parent = &osc_32KHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &ck_13MHz_round_rate, + .set_rate = &pll1_set_rate, + .enable_reg = PLLCTRL_REG, + .enable_shift = 1, + .scale_reg = PLLCTRL_REG, + .rate = CLK_RATE_13MHZ, +}; + +/* CPU/Bus PLL */ +static struct clk ck_pll4 = { + .name = "ck_pll4", + .parent = &ck_pll1, + .flags = RATE_PROPAGATES | NEEDS_INITIALIZATION, + .propagate_next = &per_ck, + .round_rate = &pll4_round_rate, + .set_rate = &pll160_set_rate, + .rate = CLK_RATE_208MHZ, + .scale_reg = HCLKPLLCTRL_REG, + .enable_reg = PWRCTRL_REG, + .enable_shift = 2, + .parent_switch_reg = SYSCLKCTRL_REG, + .set_parent = &set_13MHz_parent, +}; + +/* USB PLL */ +static struct clk ck_pll5 = { + .name = "ck_pll5", + .parent = &ck_1MHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &pll5_round_rate, + .set_rate = &pll160_set_rate, + .scale_reg = USBCTRL_REG, + .enable_reg = USBCTRL_REG, + .enable_shift = 18, + .enable_reg1 = USBCTRL_REG, + .enable_shift1 = 17, +}; + +/* XPERTTeak DSP PLL */ +static struct clk ck_pll3 = { + .name = "ck_pll3", + .parent = &ck_pll1, + .flags = NEEDS_INITIALIZATION, + .round_rate = &pll3_round_rate, + .set_rate = &pll160_set_rate, + .scale_reg = DSPPLLCTRL_REG, + .enable_reg = DSPCLKCTRL_REG, + .enable_shift = 3, + .enable_reg1 = DSPCLKCTRL_REG, + .enable_shift1 = 2, + .parent_switch_reg = DSPCLKCTRL_REG, + .set_parent = &set_13MHz_parent, +}; + +static struct clk hclk_ck = { + .name = "hclk_ck", + .parent = &ck_pll4, + .flags = PARENT_SET_RATE, + .set_rate = &hclk_set_rate, + .round_rate = &hclk_round_rate, + .scale_reg = HCLKDIVCTRL_REG, + .rate = 2, + .user_rate = 2, +}; + +static struct clk per_ck = { + .name = "per_ck", + .parent = &ck_pll4, + .flags = FIXED_RATE, + .propagate_next = &hclk_ck, + .set_rate = &per_clk_set_rate, + .round_rate = &per_clk_round_rate, + .scale_reg = HCLKDIVCTRL_REG, + .rate = CLK_RATE_13MHZ, + .user_rate = CLK_RATE_13MHZ, +}; + +static struct clk m2hclk_ck = { + .name = "m2hclk_ck", + .parent = &hclk_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_inv_set_rate, + .rate = 1, + .enable_shift = 6, + .enable_reg = PWRCTRL_REG, +}; + +static struct clk vfp9_ck = { + .name = "vfp9_ck", + .parent = &ck_pll4, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .rate = 1, + .enable_shift = 4, + .enable_reg = VFP9CLKCTRL_REG, +}; + +static struct clk keyscan_ck = { + .name = "keyscan_ck", + .parent = &osc_32KHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = KEYCLKCTRL_REG, +}; + +static struct clk touch_ck = { + .name = "touch_ck", + .parent = &osc_32KHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = TSCLKCTRL_REG, +}; + +static struct clk pwm1_ck = { + .name = "pwm1_ck", + .parent = &osc_32KHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = PWMCLKCTRL_REG, +}; + +static struct clk pwm2_ck = { + .name = "pwm2_ck", + .parent = &osc_32KHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 2, + .enable_reg = PWMCLKCTRL_REG, +}; + +static struct clk jpeg_ck = { + .name = "jpeg_ck", + .parent = &hclk_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = JPEGCLKCTRL_REG, +}; + +static struct clk ms_ck = { + .name = "ms_ck", + .parent = &ck_pll4, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 5, + .enable_reg = MSCTRL_REG, +}; + +static struct clk dum_ck = { + .name = "dum_ck", + .parent = &hclk_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = DUMCLKCTRL_REG, +}; + +static struct clk flash_ck = { + .name = "flash_ck", + .parent = &hclk_ck, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 1, /* Only MLC clock supported */ + .enable_reg = FLASHCLKCTRL_REG, +}; + +static struct clk i2c0_ck = { + .name = "i2c0_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = I2CCLKCTRL_REG, +}; + +static struct clk i2c1_ck = { + .name = "i2c1_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 1, + .enable_reg = I2CCLKCTRL_REG, +}; + +static struct clk i2c2_ck = { + .name = "i2c2_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 2, + .enable_reg = USB_OTG_CLKCTRL_REG, +}; + +static struct clk spi0_ck = { + .name = "spi0_ck", + .parent = &hclk_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = SPICTRL_REG, +}; + +static struct clk spi1_ck = { + .name = "spi1_ck", + .parent = &hclk_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 4, + .enable_reg = SPICTRL_REG, +}; + +static struct clk dma_ck = { + .name = "dma_ck", + .parent = &hclk_ck, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = DMACLKCTRL_REG, +}; + +static struct clk uart3_ck = { + .name = "uart3_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .rate = 1, + .enable_shift = 0, + .enable_reg = UARTCLKCTRL_REG, +}; + +static struct clk uart4_ck = { + .name = "uart4_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 1, + .enable_reg = UARTCLKCTRL_REG, +}; + +static struct clk uart5_ck = { + .name = "uart5_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .rate = 1, + .enable_shift = 2, + .enable_reg = UARTCLKCTRL_REG, +}; + +static struct clk uart6_ck = { + .name = "uart6_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 3, + .enable_reg = UARTCLKCTRL_REG, +}; + +/* These clocks are visible outside this module + * and can be initialized + */ +static struct clk *onchip_clks[] = { + &ck_13MHz, + &ck_pll1, + &ck_pll4, + &ck_pll5, + &ck_pll3, + &vfp9_ck, + &m2hclk_ck, + &hclk_ck, + &dma_ck, + &flash_ck, + &dum_ck, + &keyscan_ck, + &pwm1_ck, + &pwm2_ck, + &jpeg_ck, + &ms_ck, + &touch_ck, + &i2c0_ck, + &i2c1_ck, + &i2c2_ck, + &spi0_ck, + &spi1_ck, + &uart3_ck, + &uart4_ck, + &uart5_ck, + &uart6_ck, +}; + +static int local_clk_enable(struct clk *clk) +{ + int ret = 0; + + if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate + && clk->user_rate) + ret = clk->set_rate(clk, clk->user_rate); + return ret; +} + +static void local_clk_disable(struct clk *clk) +{ + if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate) + clk->set_rate(clk, 0); +} + +static void local_clk_unuse(struct clk *clk) +{ + if (clk->usecount > 0 && !(--clk->usecount)) { + local_clk_disable(clk); + if (clk->parent) + local_clk_unuse(clk->parent); + } +} + +static int local_clk_use(struct clk *clk) +{ + int ret = 0; + if (clk->usecount++ == 0) { + if (clk->parent) + ret = local_clk_use(clk->parent); + + if (ret != 0) { + clk->usecount--; + goto out; + } + + ret = local_clk_enable(clk); + + if (ret != 0 && clk->parent) { + local_clk_unuse(clk->parent); + clk->usecount--; + } + } +out: + return ret; +} + +static int local_set_rate(struct clk *clk, u32 rate) +{ + int ret = -EINVAL; + if (clk->set_rate) { + + if (clk->user_rate == clk->rate && clk->parent->rate) { + /* if clock enabled or rate not set */ + clk->user_rate = clk->round_rate(clk, rate); + ret = clk->set_rate(clk, clk->user_rate); + } else + clk->user_rate = clk->round_rate(clk, rate); + ret = 0; + } + return ret; +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EINVAL; + + if (clk->flags & FIXED_RATE) + goto out; + + clock_lock(); + if ((clk->flags & PARENT_SET_RATE) && clk->parent) { + + clk->user_rate = clk->round_rate(clk, rate); + /* parent clock needs to be refreshed + for the setting to take effect */ + } else { + ret = local_set_rate(clk, rate); + } + ret = 0; + clock_unlock(); + +out: + return ret; +} + +EXPORT_SYMBOL(clk_set_rate); + +struct clk *clk_get(struct device *dev, const char *id) +{ + struct clk *clk = ERR_PTR(-ENOENT); + struct clk **clkp; + + clock_lock(); + for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); + clkp++) { + if (strcmp(id, (*clkp)->name) == 0 + && try_module_get((*clkp)->owner)) { + clk = (*clkp); + break; + } + } + clock_unlock(); + + return clk; +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ + clock_lock(); + if (clk && !IS_ERR(clk)) + module_put(clk->owner); + clock_unlock(); +} +EXPORT_SYMBOL(clk_put); + +unsigned long clk_get_rate(struct clk *clk) +{ + unsigned long ret; + clock_lock(); + ret = clk->rate; + clock_unlock(); + return ret; +} +EXPORT_SYMBOL(clk_get_rate); + +int clk_enable(struct clk *clk) +{ + int ret = 0; + + clock_lock(); + ret = local_clk_use(clk); + clock_unlock(); + return ret; +} + +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + clock_lock(); + local_clk_unuse(clk); + clock_unlock(); +} + +EXPORT_SYMBOL(clk_disable); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + long ret; + clock_lock(); + if (clk->round_rate) + ret = clk->round_rate(clk, rate); + else + ret = clk->rate; + clock_unlock(); + return ret; +} + +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + int ret = -ENODEV; + if (!clk->set_parent) + goto out; + + clock_lock(); + ret = clk->set_parent(clk, parent); + if (!ret) + clk->parent = parent; + clock_unlock(); + +out: + return ret; +} + +EXPORT_SYMBOL(clk_set_parent); + +static int __init clk_init(void) +{ + struct clk **clkp; + + /* Disable autoclocking, as it doesn't seem to work */ + __raw_writel(0xff, AUTOCLK_CTRL); + + for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); + clkp++) { + if (((*clkp)->flags & NEEDS_INITIALIZATION) + && ((*clkp)->set_rate)) { + (*clkp)->user_rate = (*clkp)->rate; + local_set_rate((*clkp), (*clkp)->user_rate); + if ((*clkp)->set_parent) + (*clkp)->set_parent((*clkp), (*clkp)->parent); + } + pr_debug("%s: clock %s, rate %ld\n", + __FUNCTION__, (*clkp)->name, (*clkp)->rate); + } + + local_clk_use(&ck_pll4); + + /* if ck_13MHz is not used, disable it. */ + if (ck_13MHz.usecount == 0) + local_clk_disable(&ck_13MHz); + + /* Disable autoclocking */ + __raw_writeb(0xff, AUTOCLK_CTRL); + + return 0; +} + +arch_initcall(clk_init); diff --git a/arch/arm/mach-pnx4008/clock.h b/arch/arm/mach-pnx4008/clock.h new file mode 100644 index 0000000..cd58f37 --- /dev/null +++ b/arch/arm/mach-pnx4008/clock.h @@ -0,0 +1,43 @@ +/* + * arch/arm/mach-pnx4008/clock.h + * + * Clock control driver for PNX4008 - internal header file + * + * Author: Vitaly Wool + * + * 2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef __ARCH_ARM_PNX4008_CLOCK_H__ +#define __ARCH_ARM_PNX4008_CLOCK_H__ + +struct clk { + struct list_head node; + struct module *owner; + const char *name; + struct clk *parent; + struct clk *propagate_next; + u32 rate; + u32 user_rate; + s8 usecount; + u32 flags; + u32 scale_reg; + u8 enable_shift; + u32 enable_reg; + u8 enable_shift1; + u32 enable_reg1; + u32 parent_switch_reg; + u32(*round_rate) (struct clk *, u32); + int (*set_rate) (struct clk *, u32); + int (*set_parent) (struct clk * clk, struct clk * parent); +}; + +/* Flags */ +#define RATE_PROPAGATES (1<<0) +#define NEEDS_INITIALIZATION (1<<1) +#define PARENT_SET_RATE (1<<2) +#define FIXED_RATE (1<<3) + +#endif diff --git a/arch/arm/mach-pnx4008/core.c b/arch/arm/mach-pnx4008/core.c new file mode 100644 index 0000000..ba91daa --- /dev/null +++ b/arch/arm/mach-pnx4008/core.c @@ -0,0 +1,207 @@ +/* + * arch/arm/mach-pnx4008/core.c + * + * PNX4008 core startup code + * + * Authors: Vitaly Wool, Dmitry Chigirev, + * Grigory Tolstolytkin, Dmitry Pervushin + * + * Based on reference code received from Philips: + * Copyright (C) 2003 Philips Semiconductors + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +struct resource spipnx_0_resources[] = { + { + .start = PNX4008_SPI1_BASE, + .end = PNX4008_SPI1_BASE + SZ_4K, + .flags = IORESOURCE_MEM, + }, { + .start = PER_SPI1_REC_XMIT, + .flags = IORESOURCE_DMA, + }, { + .start = SPI1_INT, + .flags = IORESOURCE_IRQ, + }, { + .flags = 0, + }, +}; + +struct resource spipnx_1_resources[] = { + { + .start = PNX4008_SPI2_BASE, + .end = PNX4008_SPI2_BASE + SZ_4K, + .flags = IORESOURCE_MEM, + }, { + .start = PER_SPI2_REC_XMIT, + .flags = IORESOURCE_DMA, + }, { + .start = SPI2_INT, + .flags = IORESOURCE_IRQ, + }, { + .flags = 0, + } +}; + +static struct spi_board_info spi_board_info[] __initdata = { + { + .modalias = "m25p80", + .max_speed_hz = 1000000, + .bus_num = 1, + .chip_select = 0, + }, +}; + +static struct platform_device spipnx_1 = { + .name = "spipnx", + .id = 1, + .num_resources = ARRAY_SIZE(spipnx_0_resources), + .resource = spipnx_0_resources, + .dev = { + .coherent_dma_mask = 0xFFFFFFFF, + }, +}; + +static struct platform_device spipnx_2 = { + .name = "spipnx", + .id = 2, + .num_resources = ARRAY_SIZE(spipnx_1_resources), + .resource = spipnx_1_resources, + .dev = { + .coherent_dma_mask = 0xFFFFFFFF, + }, +}; + +static struct plat_serial8250_port platform_serial_ports[] = { + { + .membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART5_BASE)), + .mapbase = (unsigned long)PNX4008_UART5_BASE, + .irq = IIR5_INT, + .uartclk = PNX4008_UART_CLK, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST, + }, + { + .membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART3_BASE)), + .mapbase = (unsigned long)PNX4008_UART3_BASE, + .irq = IIR3_INT, + .uartclk = PNX4008_UART_CLK, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST, + }, + {} +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = &platform_serial_ports, + }, +}; + +static struct platform_device *devices[] __initdata = { + &spipnx_1, + &spipnx_2, + &serial_device, +}; + + +extern void pnx4008_uart_init(void); + +static void __init pnx4008_init(void) +{ + /*disable all START interrupt sources, + and clear all START interrupt flags */ + __raw_writel(0, START_INT_ER_REG(SE_PIN_BASE_INT)); + __raw_writel(0, START_INT_ER_REG(SE_INT_BASE_INT)); + __raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT)); + __raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT)); + + platform_add_devices(devices, ARRAY_SIZE(devices)); + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); + /* Switch on the UART clocks */ + pnx4008_uart_init(); +} + +static struct map_desc pnx4008_io_desc[] __initdata = { + { + .virtual = IO_ADDRESS(PNX4008_IRAM_BASE), + .pfn = __phys_to_pfn(PNX4008_IRAM_BASE), + .length = SZ_64K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(PNX4008_NDF_FLASH_BASE), + .pfn = __phys_to_pfn(PNX4008_NDF_FLASH_BASE), + .length = SZ_1M - SZ_128K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(PNX4008_JPEG_CONFIG_BASE), + .pfn = __phys_to_pfn(PNX4008_JPEG_CONFIG_BASE), + .length = SZ_128K * 3, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(PNX4008_DMA_CONFIG_BASE), + .pfn = __phys_to_pfn(PNX4008_DMA_CONFIG_BASE), + .length = SZ_1M, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(PNX4008_AHB2FAB_BASE), + .pfn = __phys_to_pfn(PNX4008_AHB2FAB_BASE), + .length = SZ_1M, + .type = MT_DEVICE, + }, +}; + +void __init pnx4008_map_io(void) +{ + iotable_init(pnx4008_io_desc, ARRAY_SIZE(pnx4008_io_desc)); +} + +extern struct sys_timer pnx4008_timer; + +MACHINE_START(PNX4008, "Philips PNX4008") + /* Maintainer: MontaVista Software Inc. */ + .phys_io = 0x40090000, + .io_pg_offst = (0xf4090000 >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = pnx4008_map_io, + .init_irq = pnx4008_init_irq, + .init_machine = pnx4008_init, + .timer = &pnx4008_timer, +MACHINE_END diff --git a/arch/arm/mach-pnx4008/dma.c b/arch/arm/mach-pnx4008/dma.c new file mode 100644 index 0000000..981aa9d --- /dev/null +++ b/arch/arm/mach-pnx4008/dma.c @@ -0,0 +1,1109 @@ +/* + * linux/arch/arm/mach-pnx4008/dma.c + * + * PNX4008 DMA registration and IRQ dispatching + * + * Author: Vitaly Wool + * Copyright: MontaVista Software Inc. (c) 2005 + * + * Based on the code from Nicolas Pitre + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct dma_channel { + char *name; + void (*irq_handler) (int, int, void *, struct pt_regs *); + void *data; + struct pnx4008_dma_ll *ll; + u32 ll_dma; + void *target_addr; + int target_id; +} dma_channels[MAX_DMA_CHANNELS]; + +static struct ll_pool { + void *vaddr; + void *cur; + dma_addr_t dma_addr; + int count; +} ll_pool; + +static spinlock_t ll_lock = SPIN_LOCK_UNLOCKED; + +struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t * ll_dma) +{ + struct pnx4008_dma_ll *ll = NULL; + unsigned long flags; + + spin_lock_irqsave(&ll_lock, flags); + if (ll_pool.count > 4) { /* can give one more */ + ll = *(struct pnx4008_dma_ll **) ll_pool.cur; + *ll_dma = ll_pool.dma_addr + ((void *)ll - ll_pool.vaddr); + *(void **)ll_pool.cur = **(void ***)ll_pool.cur; + memset(ll, 0, sizeof(*ll)); + ll_pool.count--; + } + spin_unlock_irqrestore(&ll_lock, flags); + + return ll; +} + +EXPORT_SYMBOL_GPL(pnx4008_alloc_ll_entry); + +void pnx4008_free_ll_entry(struct pnx4008_dma_ll * ll, dma_addr_t ll_dma) +{ + unsigned long flags; + + if (ll) { + if ((unsigned long)((long)ll - (long)ll_pool.vaddr) > 0x4000) { + printk(KERN_ERR "Trying to free entry not allocated by DMA\n"); + BUG(); + } + + if (ll->flags & DMA_BUFFER_ALLOCATED) + ll->free(ll->alloc_data); + + spin_lock_irqsave(&ll_lock, flags); + *(long *)ll = *(long *)ll_pool.cur; + *(long *)ll_pool.cur = (long)ll; + ll_pool.count++; + spin_unlock_irqrestore(&ll_lock, flags); + } +} + +EXPORT_SYMBOL_GPL(pnx4008_free_ll_entry); + +void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll * ll) +{ + struct pnx4008_dma_ll *ptr; + u32 dma; + + while (ll) { + dma = ll->next_dma; + ptr = ll->next; + pnx4008_free_ll_entry(ll, ll_dma); + + ll_dma = dma; + ll = ptr; + } +} + +EXPORT_SYMBOL_GPL(pnx4008_free_ll); + +static int dma_channels_requested = 0; + +static inline void dma_increment_usage(void) +{ + if (!dma_channels_requested++) { + struct clk *clk = clk_get(0, "dma_ck"); + if (!IS_ERR(clk)) { + clk_set_rate(clk, 1); + clk_put(clk); + } + pnx4008_config_dma(-1, -1, 1); + } +} +static inline void dma_decrement_usage(void) +{ + if (!--dma_channels_requested) { + struct clk *clk = clk_get(0, "dma_ck"); + if (!IS_ERR(clk)) { + clk_set_rate(clk, 0); + clk_put(clk); + } + pnx4008_config_dma(-1, -1, 0); + + } +} + +static spinlock_t dma_lock = SPIN_LOCK_UNLOCKED; + +static inline void pnx4008_dma_lock(void) +{ + spin_lock_irq(&dma_lock); +} + +static inline void pnx4008_dma_unlock(void) +{ + spin_unlock_irq(&dma_lock); +} + +#define VALID_CHANNEL(c) (((c) >= 0) && ((c) < MAX_DMA_CHANNELS)) + +int pnx4008_request_channel(char *name, int ch, + void (*irq_handler) (int, int, void *, + struct pt_regs *), void *data) +{ + int i, found = 0; + + /* basic sanity checks */ + if (!name || (ch != -1 && !VALID_CHANNEL(ch))) + return -EINVAL; + + pnx4008_dma_lock(); + + /* try grabbing a DMA channel with the requested priority */ + for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) { + if (!dma_channels[i].name && (ch == -1 || ch == i)) { + found = 1; + break; + } + } + + if (found) { + dma_increment_usage(); + dma_channels[i].name = name; + dma_channels[i].irq_handler = irq_handler; + dma_channels[i].data = data; + dma_channels[i].ll = NULL; + dma_channels[i].ll_dma = 0; + } else { + printk(KERN_WARNING "No more available DMA channels for %s\n", + name); + i = -ENODEV; + } + + pnx4008_dma_unlock(); + return i; +} + +EXPORT_SYMBOL_GPL(pnx4008_request_channel); + +void pnx4008_free_channel(int ch) +{ + if (!dma_channels[ch].name) { + printk(KERN_CRIT + "%s: trying to free channel %d which is already freed\n", + __FUNCTION__, ch); + return; + } + + pnx4008_dma_lock(); + pnx4008_free_ll(dma_channels[ch].ll_dma, dma_channels[ch].ll); + dma_channels[ch].ll = NULL; + dma_decrement_usage(); + + dma_channels[ch].name = NULL; + pnx4008_dma_unlock(); +} + +EXPORT_SYMBOL_GPL(pnx4008_free_channel); + +int pnx4008_config_dma(int ahb_m1_be, int ahb_m2_be, int enable) +{ + unsigned long dma_cfg = __raw_readl(DMAC_CONFIG); + + switch (ahb_m1_be) { + case 0: + dma_cfg &= ~(1 << 1); + break; + case 1: + dma_cfg |= (1 << 1); + break; + default: + break; + } + + switch (ahb_m2_be) { + case 0: + dma_cfg &= ~(1 << 2); + break; + case 1: + dma_cfg |= (1 << 2); + break; + default: + break; + } + + switch (enable) { + case 0: + dma_cfg &= ~(1 << 0); + break; + case 1: + dma_cfg |= (1 << 0); + break; + default: + break; + } + + pnx4008_dma_lock(); + __raw_writel(dma_cfg, DMAC_CONFIG); + pnx4008_dma_unlock(); + + return 0; +} + +EXPORT_SYMBOL_GPL(pnx4008_config_dma); + +int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl * ch_ctrl, + unsigned long *ctrl) +{ + int i = 0, dbsize, sbsize, err = 0; + + if (!ctrl || !ch_ctrl) { + err = -EINVAL; + goto out; + } + + *ctrl = 0; + + switch (ch_ctrl->tc_mask) { + case 0: + break; + case 1: + *ctrl |= (1 << 31); + break; + + default: + err = -EINVAL; + goto out; + } + + switch (ch_ctrl->cacheable) { + case 0: + break; + case 1: + *ctrl |= (1 << 30); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->bufferable) { + case 0: + break; + case 1: + *ctrl |= (1 << 29); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->priv_mode) { + case 0: + break; + case 1: + *ctrl |= (1 << 28); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->di) { + case 0: + break; + case 1: + *ctrl |= (1 << 27); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->si) { + case 0: + break; + case 1: + *ctrl |= (1 << 26); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->dest_ahb1) { + case 0: + break; + case 1: + *ctrl |= (1 << 25); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->src_ahb1) { + case 0: + break; + case 1: + *ctrl |= (1 << 24); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->dwidth) { + case WIDTH_BYTE: + *ctrl &= ~(7 << 21); + break; + case WIDTH_HWORD: + *ctrl &= ~(7 << 21); + *ctrl |= (1 << 21); + break; + case WIDTH_WORD: + *ctrl &= ~(7 << 21); + *ctrl |= (2 << 21); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->swidth) { + case WIDTH_BYTE: + *ctrl &= ~(7 << 18); + break; + case WIDTH_HWORD: + *ctrl &= ~(7 << 18); + *ctrl |= (1 << 18); + break; + case WIDTH_WORD: + *ctrl &= ~(7 << 18); + *ctrl |= (2 << 18); + break; + + default: + err = -EINVAL; + goto out; + } + dbsize = ch_ctrl->dbsize; + while (!(dbsize & 1)) { + i++; + dbsize >>= 1; + } + if (ch_ctrl->dbsize != 1 || i > 8 || i == 1) { + err = -EINVAL; + goto out; + } else if (i > 1) + i--; + *ctrl &= ~(7 << 15); + *ctrl |= (i << 15); + + sbsize = ch_ctrl->sbsize; + while (!(sbsize & 1)) { + i++; + sbsize >>= 1; + } + if (ch_ctrl->sbsize != 1 || i > 8 || i == 1) { + err = -EINVAL; + goto out; + } else if (i > 1) + i--; + *ctrl &= ~(7 << 12); + *ctrl |= (i << 12); + + if (ch_ctrl->tr_size > 0x7ff) { + err = -E2BIG; + goto out; + } + *ctrl &= ~0x7ff; + *ctrl |= ch_ctrl->tr_size & 0x7ff; + +out: + return err; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_pack_control); + +int pnx4008_dma_parse_control(unsigned long ctrl, + struct pnx4008_dma_ch_ctrl * ch_ctrl) +{ + int err = 0; + + if (!ch_ctrl) { + err = -EINVAL; + goto out; + } + + ch_ctrl->tr_size = ctrl & 0x7ff; + ctrl >>= 12; + + ch_ctrl->sbsize = 1 << (ctrl & 7); + if (ch_ctrl->sbsize > 1) + ch_ctrl->sbsize <<= 1; + ctrl >>= 3; + + ch_ctrl->dbsize = 1 << (ctrl & 7); + if (ch_ctrl->dbsize > 1) + ch_ctrl->dbsize <<= 1; + ctrl >>= 3; + + switch (ctrl & 7) { + case 0: + ch_ctrl->swidth = WIDTH_BYTE; + break; + case 1: + ch_ctrl->swidth = WIDTH_HWORD; + break; + case 2: + ch_ctrl->swidth = WIDTH_WORD; + break; + default: + err = -EINVAL; + goto out; + } + ctrl >>= 3; + + switch (ctrl & 7) { + case 0: + ch_ctrl->dwidth = WIDTH_BYTE; + break; + case 1: + ch_ctrl->dwidth = WIDTH_HWORD; + break; + case 2: + ch_ctrl->dwidth = WIDTH_WORD; + break; + default: + err = -EINVAL; + goto out; + } + ctrl >>= 3; + + ch_ctrl->src_ahb1 = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->dest_ahb1 = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->si = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->di = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->priv_mode = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->bufferable = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->cacheable = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->tc_mask = ctrl & 1; + +out: + return err; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_parse_control); + +int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config * ch_cfg, + unsigned long *cfg) +{ + int err = 0; + + if (!cfg || !ch_cfg) { + err = -EINVAL; + goto out; + } + + *cfg = 0; + + switch (ch_cfg->halt) { + case 0: + break; + case 1: + *cfg |= (1 << 18); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_cfg->active) { + case 0: + break; + case 1: + *cfg |= (1 << 17); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_cfg->lock) { + case 0: + break; + case 1: + *cfg |= (1 << 16); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_cfg->itc) { + case 0: + break; + case 1: + *cfg |= (1 << 15); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_cfg->ie) { + case 0: + break; + case 1: + *cfg |= (1 << 14); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_cfg->flow_cntrl) { + case FC_MEM2MEM_DMA: + *cfg &= ~(7 << 11); + break; + case FC_MEM2PER_DMA: + *cfg &= ~(7 << 11); + *cfg |= (1 << 11); + break; + case FC_PER2MEM_DMA: + *cfg &= ~(7 << 11); + *cfg |= (2 << 11); + break; + case FC_PER2PER_DMA: + *cfg &= ~(7 << 11); + *cfg |= (3 << 11); + break; + case FC_PER2PER_DPER: + *cfg &= ~(7 << 11); + *cfg |= (4 << 11); + break; + case FC_MEM2PER_PER: + *cfg &= ~(7 << 11); + *cfg |= (5 << 11); + break; + case FC_PER2MEM_PER: + *cfg &= ~(7 << 11); + *cfg |= (6 << 11); + break; + case FC_PER2PER_SPER: + *cfg |= (7 << 11); + break; + + default: + err = -EINVAL; + goto out; + } + *cfg &= ~(0x1f << 6); + *cfg |= ((ch_cfg->dest_per & 0x1f) << 6); + + *cfg &= ~(0x1f << 1); + *cfg |= ((ch_cfg->src_per & 0x1f) << 1); + +out: + return err; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_pack_config); + +int pnx4008_dma_parse_config(unsigned long cfg, + struct pnx4008_dma_ch_config * ch_cfg) +{ + int err = 0; + + if (!ch_cfg) { + err = -EINVAL; + goto out; + } + + cfg >>= 1; + + ch_cfg->src_per = cfg & 0x1f; + cfg >>= 5; + + ch_cfg->dest_per = cfg & 0x1f; + cfg >>= 5; + + switch (cfg & 7) { + case 0: + ch_cfg->flow_cntrl = FC_MEM2MEM_DMA; + break; + case 1: + ch_cfg->flow_cntrl = FC_MEM2PER_DMA; + break; + case 2: + ch_cfg->flow_cntrl = FC_PER2MEM_DMA; + break; + case 3: + ch_cfg->flow_cntrl = FC_PER2PER_DMA; + break; + case 4: + ch_cfg->flow_cntrl = FC_PER2PER_DPER; + break; + case 5: + ch_cfg->flow_cntrl = FC_MEM2PER_PER; + break; + case 6: + ch_cfg->flow_cntrl = FC_PER2MEM_PER; + break; + case 7: + ch_cfg->flow_cntrl = FC_PER2PER_SPER; + } + cfg >>= 3; + + ch_cfg->ie = cfg & 1; + cfg >>= 1; + + ch_cfg->itc = cfg & 1; + cfg >>= 1; + + ch_cfg->lock = cfg & 1; + cfg >>= 1; + + ch_cfg->active = cfg & 1; + cfg >>= 1; + + ch_cfg->halt = cfg & 1; + +out: + return err; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_parse_config); + +void pnx4008_dma_split_head_entry(struct pnx4008_dma_config * config, + struct pnx4008_dma_ch_ctrl * ctrl) +{ + int new_len = ctrl->tr_size, num_entries = 0; + int old_len = new_len; + int src_width, dest_width, count = 1; + + switch (ctrl->swidth) { + case WIDTH_BYTE: + src_width = 1; + break; + case WIDTH_HWORD: + src_width = 2; + break; + case WIDTH_WORD: + src_width = 4; + break; + default: + return; + } + + switch (ctrl->dwidth) { + case WIDTH_BYTE: + dest_width = 1; + break; + case WIDTH_HWORD: + dest_width = 2; + break; + case WIDTH_WORD: + dest_width = 4; + break; + default: + return; + } + + while (new_len > 0x7FF) { + num_entries++; + new_len = (ctrl->tr_size + num_entries) / (num_entries + 1); + } + if (num_entries != 0) { + struct pnx4008_dma_ll *ll = NULL; + config->ch_ctrl &= ~0x7ff; + config->ch_ctrl |= new_len; + if (!config->is_ll) { + config->is_ll = 1; + while (num_entries) { + if (!ll) { + config->ll = + pnx4008_alloc_ll_entry(&config-> + ll_dma); + ll = config->ll; + } else { + ll->next = + pnx4008_alloc_ll_entry(&ll-> + next_dma); + ll = ll->next; + } + + if (ctrl->si) + ll->src_addr = + config->src_addr + + src_width * new_len * count; + else + ll->src_addr = config->src_addr; + if (ctrl->di) + ll->dest_addr = + config->dest_addr + + dest_width * new_len * count; + else + ll->dest_addr = config->dest_addr; + ll->ch_ctrl = config->ch_ctrl & 0x7fffffff; + ll->next_dma = 0; + ll->next = NULL; + num_entries--; + count++; + } + } else { + struct pnx4008_dma_ll *ll_old = config->ll; + unsigned long ll_dma_old = config->ll_dma; + while (num_entries) { + if (!ll) { + config->ll = + pnx4008_alloc_ll_entry(&config-> + ll_dma); + ll = config->ll; + } else { + ll->next = + pnx4008_alloc_ll_entry(&ll-> + next_dma); + ll = ll->next; + } + + if (ctrl->si) + ll->src_addr = + config->src_addr + + src_width * new_len * count; + else + ll->src_addr = config->src_addr; + if (ctrl->di) + ll->dest_addr = + config->dest_addr + + dest_width * new_len * count; + else + ll->dest_addr = config->dest_addr; + ll->ch_ctrl = config->ch_ctrl & 0x7fffffff; + ll->next_dma = 0; + ll->next = NULL; + num_entries--; + count++; + } + ll->next_dma = ll_dma_old; + ll->next = ll_old; + } + /* adjust last length/tc */ + ll->ch_ctrl = config->ch_ctrl & (~0x7ff); + ll->ch_ctrl |= old_len - new_len * (count - 1); + config->ch_ctrl &= 0x7fffffff; + } +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_split_head_entry); + +void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll * cur_ll, + struct pnx4008_dma_ch_ctrl * ctrl) +{ + int new_len = ctrl->tr_size, num_entries = 0; + int old_len = new_len; + int src_width, dest_width, count = 1; + + switch (ctrl->swidth) { + case WIDTH_BYTE: + src_width = 1; + break; + case WIDTH_HWORD: + src_width = 2; + break; + case WIDTH_WORD: + src_width = 4; + break; + default: + return; + } + + switch (ctrl->dwidth) { + case WIDTH_BYTE: + dest_width = 1; + break; + case WIDTH_HWORD: + dest_width = 2; + break; + case WIDTH_WORD: + dest_width = 4; + break; + default: + return; + } + + while (new_len > 0x7FF) { + num_entries++; + new_len = (ctrl->tr_size + num_entries) / (num_entries + 1); + } + if (num_entries != 0) { + struct pnx4008_dma_ll *ll = NULL; + cur_ll->ch_ctrl &= ~0x7ff; + cur_ll->ch_ctrl |= new_len; + if (!cur_ll->next) { + while (num_entries) { + if (!ll) { + cur_ll->next = + pnx4008_alloc_ll_entry(&cur_ll-> + next_dma); + ll = cur_ll->next; + } else { + ll->next = + pnx4008_alloc_ll_entry(&ll-> + next_dma); + ll = ll->next; + } + + if (ctrl->si) + ll->src_addr = + cur_ll->src_addr + + src_width * new_len * count; + else + ll->src_addr = cur_ll->src_addr; + if (ctrl->di) + ll->dest_addr = + cur_ll->dest_addr + + dest_width * new_len * count; + else + ll->dest_addr = cur_ll->dest_addr; + ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff; + ll->next_dma = 0; + ll->next = NULL; + num_entries--; + count++; + } + } else { + struct pnx4008_dma_ll *ll_old = cur_ll->next; + unsigned long ll_dma_old = cur_ll->next_dma; + while (num_entries) { + if (!ll) { + cur_ll->next = + pnx4008_alloc_ll_entry(&cur_ll-> + next_dma); + ll = cur_ll->next; + } else { + ll->next = + pnx4008_alloc_ll_entry(&ll-> + next_dma); + ll = ll->next; + } + + if (ctrl->si) + ll->src_addr = + cur_ll->src_addr + + src_width * new_len * count; + else + ll->src_addr = cur_ll->src_addr; + if (ctrl->di) + ll->dest_addr = + cur_ll->dest_addr + + dest_width * new_len * count; + else + ll->dest_addr = cur_ll->dest_addr; + ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff; + ll->next_dma = 0; + ll->next = NULL; + num_entries--; + count++; + } + + ll->next_dma = ll_dma_old; + ll->next = ll_old; + } + /* adjust last length/tc */ + ll->ch_ctrl = cur_ll->ch_ctrl & (~0x7ff); + ll->ch_ctrl |= old_len - new_len * (count - 1); + cur_ll->ch_ctrl &= 0x7fffffff; + } +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_split_ll_entry); + +int pnx4008_config_channel(int ch, struct pnx4008_dma_config * config) +{ + if (!VALID_CHANNEL(ch) || !dma_channels[ch].name) + return -EINVAL; + + pnx4008_dma_lock(); + __raw_writel(config->src_addr, DMAC_Cx_SRC_ADDR(ch)); + __raw_writel(config->dest_addr, DMAC_Cx_DEST_ADDR(ch)); + + if (config->is_ll) + __raw_writel(config->ll_dma, DMAC_Cx_LLI(ch)); + else + __raw_writel(0, DMAC_Cx_LLI(ch)); + + __raw_writel(config->ch_ctrl, DMAC_Cx_CONTROL(ch)); + __raw_writel(config->ch_cfg, DMAC_Cx_CONFIG(ch)); + pnx4008_dma_unlock(); + + return 0; + +} + +EXPORT_SYMBOL_GPL(pnx4008_config_channel); + +int pnx4008_channel_get_config(int ch, struct pnx4008_dma_config * config) +{ + if (!VALID_CHANNEL(ch) || !dma_channels[ch].name || !config) + return -EINVAL; + + pnx4008_dma_lock(); + config->ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch)); + config->ch_ctrl = __raw_readl(DMAC_Cx_CONTROL(ch)); + + config->ll_dma = __raw_readl(DMAC_Cx_LLI(ch)); + config->is_ll = config->ll_dma ? 1 : 0; + + config->src_addr = __raw_readl(DMAC_Cx_SRC_ADDR(ch)); + config->dest_addr = __raw_readl(DMAC_Cx_DEST_ADDR(ch)); + pnx4008_dma_unlock(); + + return 0; +} + +EXPORT_SYMBOL_GPL(pnx4008_channel_get_config); + +int pnx4008_dma_ch_enable(int ch) +{ + unsigned long ch_cfg; + + if (!VALID_CHANNEL(ch) || !dma_channels[ch].name) + return -EINVAL; + + pnx4008_dma_lock(); + ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch)); + ch_cfg |= 1; + __raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch)); + pnx4008_dma_unlock(); + + return 0; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enable); + +int pnx4008_dma_ch_disable(int ch) +{ + unsigned long ch_cfg; + + if (!VALID_CHANNEL(ch) || !dma_channels[ch].name) + return -EINVAL; + + pnx4008_dma_lock(); + ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch)); + ch_cfg &= ~1; + __raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch)); + pnx4008_dma_unlock(); + + return 0; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_ch_disable); + +int pnx4008_dma_ch_enabled(int ch) +{ + unsigned long ch_cfg; + + if (!VALID_CHANNEL(ch) || !dma_channels[ch].name) + return -EINVAL; + + pnx4008_dma_lock(); + ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch)); + pnx4008_dma_unlock(); + + return ch_cfg & 1; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enabled); + +static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + int i; + unsigned long dint = __raw_readl(DMAC_INT_STAT); + unsigned long tcint = __raw_readl(DMAC_INT_TC_STAT); + unsigned long eint = __raw_readl(DMAC_INT_ERR_STAT); + unsigned long i_bit; + + for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) { + i_bit = 1 << i; + if (dint & i_bit) { + struct dma_channel *channel = &dma_channels[i]; + + if (channel->name && channel->irq_handler) { + int cause = 0; + + if (eint & i_bit) + cause |= DMA_ERR_INT; + if (tcint & i_bit) + cause |= DMA_TC_INT; + channel->irq_handler(i, cause, channel->data, + regs); + } else { + /* + * IRQ for an unregistered DMA channel + */ + printk(KERN_WARNING + "spurious IRQ for DMA channel %d\n", i); + } + if (tcint & i_bit) + __raw_writel(i_bit, DMAC_INT_TC_CLEAR); + if (eint & i_bit) + __raw_writel(i_bit, DMAC_INT_ERR_CLEAR); + } + } + return IRQ_HANDLED; +} + +static int __init pnx4008_dma_init(void) +{ + int ret, i; + + ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL); + if (ret) { + printk(KERN_CRIT "Wow! Can't register IRQ for DMA\n"); + goto out; + } + + ll_pool.count = 0x4000 / sizeof(struct pnx4008_dma_ll); + ll_pool.cur = ll_pool.vaddr = + dma_alloc_coherent(NULL, ll_pool.count * sizeof(struct pnx4008_dma_ll), + &ll_pool.dma_addr, GFP_KERNEL); + + if (!ll_pool.vaddr) { + ret = -ENOMEM; + free_irq(DMA_INT, NULL); + goto out; + } + + for (i = 0; i < ll_pool.count - 1; i++) { + void **addr = ll_pool.vaddr + i * sizeof(struct pnx4008_dma_ll); + *addr = (void *)addr + sizeof(struct pnx4008_dma_ll); + } + *(long *)(ll_pool.vaddr + + (ll_pool.count - 1) * sizeof(struct pnx4008_dma_ll)) = + (long)ll_pool.vaddr; + + __raw_writel(1, DMAC_CONFIG); + +out: + return ret; +} +arch_initcall(pnx4008_dma_init); diff --git a/arch/arm/mach-pnx4008/gpio.c b/arch/arm/mach-pnx4008/gpio.c new file mode 100644 index 0000000..e1ce050 --- /dev/null +++ b/arch/arm/mach-pnx4008/gpio.c @@ -0,0 +1,330 @@ +/* + * arch/arm/mach-pnx4008/gpio.c + * + * PNX4008 GPIO driver + * + * Author: Dmitry Chigirev + * + * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips: + * Copyright (c) 2005 Koninklijke Philips Electronics N.V. + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* register definitions */ +#define PIO_VA_BASE IO_ADDRESS(PNX4008_PIO_BASE) + +#define PIO_INP_STATE (0x00U) +#define PIO_OUTP_SET (0x04U) +#define PIO_OUTP_CLR (0x08U) +#define PIO_OUTP_STATE (0x0CU) +#define PIO_DRV_SET (0x10U) +#define PIO_DRV_CLR (0x14U) +#define PIO_DRV_STATE (0x18U) +#define PIO_SDINP_STATE (0x1CU) +#define PIO_SDOUTP_SET (0x20U) +#define PIO_SDOUTP_CLR (0x24U) +#define PIO_MUX_SET (0x28U) +#define PIO_MUX_CLR (0x2CU) +#define PIO_MUX_STATE (0x30U) + +static inline void gpio_lock(void) +{ + local_irq_disable(); +} + +static inline void gpio_unlock(void) +{ + local_irq_enable(); +} + +/* Inline functions */ +static inline int gpio_read_bit(u32 reg, int gpio) +{ + u32 bit, val; + int ret = -EFAULT; + + if (gpio < 0) + goto out; + + bit = GPIO_BIT(gpio); + if (bit) { + val = __raw_readl(PIO_VA_BASE + reg); + ret = (val & bit) ? 1 : 0; + } +out: + return ret; +} + +static inline int gpio_set_bit(u32 reg, int gpio) +{ + u32 bit, val; + int ret = -EFAULT; + + if (gpio < 0) + goto out; + + bit = GPIO_BIT(gpio); + if (bit) { + val = __raw_readl(PIO_VA_BASE + reg); + val |= bit; + __raw_writel(val, PIO_VA_BASE + reg); + ret = 0; + } +out: + return ret; +} + +/* Very simple access control, bitmap for allocated/free */ +static unsigned long access_map[4]; +#define INP_INDEX 0 +#define OUTP_INDEX 1 +#define GPIO_INDEX 2 +#define MUX_INDEX 3 + +/*GPIO to Input Mapping */ +static short gpio_to_inp_map[32] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 24, -1 +}; + +/*GPIO to Mux Mapping */ +static short gpio_to_mux_map[32] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0, 1, 4, 5, -1 +}; + +/*Output to Mux Mapping */ +static short outp_to_mux_map[32] = { + -1, -1, -1, 6, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 2, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; + +int pnx4008_gpio_register_pin(unsigned short pin) +{ + unsigned long bit = GPIO_BIT(pin); + int ret = -EBUSY; /* Already in use */ + + gpio_lock(); + + if (GPIO_ISBID(pin)) { + if (access_map[GPIO_INDEX] & bit) + goto out; + access_map[GPIO_INDEX] |= bit; + + } else if (GPIO_ISRAM(pin)) { + if (access_map[GPIO_INDEX] & bit) + goto out; + access_map[GPIO_INDEX] |= bit; + + } else if (GPIO_ISMUX(pin)) { + if (access_map[MUX_INDEX] & bit) + goto out; + access_map[MUX_INDEX] |= bit; + + } else if (GPIO_ISOUT(pin)) { + if (access_map[OUTP_INDEX] & bit) + goto out; + access_map[OUTP_INDEX] |= bit; + + } else if (GPIO_ISIN(pin)) { + if (access_map[INP_INDEX] & bit) + goto out; + access_map[INP_INDEX] |= bit; + } else + goto out; + ret = 0; + +out: + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_register_pin); + +int pnx4008_gpio_unregister_pin(unsigned short pin) +{ + unsigned long bit = GPIO_BIT(pin); + int ret = -EFAULT; /* Not registered */ + + gpio_lock(); + + if (GPIO_ISBID(pin)) { + if (~access_map[GPIO_INDEX] & bit) + goto out; + access_map[GPIO_INDEX] &= ~bit; + } else if (GPIO_ISRAM(pin)) { + if (~access_map[GPIO_INDEX] & bit) + goto out; + access_map[GPIO_INDEX] &= ~bit; + } else if (GPIO_ISMUX(pin)) { + if (~access_map[MUX_INDEX] & bit) + goto out; + access_map[MUX_INDEX] &= ~bit; + } else if (GPIO_ISOUT(pin)) { + if (~access_map[OUTP_INDEX] & bit) + goto out; + access_map[OUTP_INDEX] &= ~bit; + } else if (GPIO_ISIN(pin)) { + if (~access_map[INP_INDEX] & bit) + goto out; + access_map[INP_INDEX] &= ~bit; + } else + goto out; + ret = 0; + +out: + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_unregister_pin); + +unsigned long pnx4008_gpio_read_pin(unsigned short pin) +{ + unsigned long ret = -EFAULT; + int gpio = GPIO_BIT_MASK(pin); + gpio_lock(); + if (GPIO_ISOUT(pin)) { + ret = gpio_read_bit(PIO_OUTP_STATE, gpio); + } else if (GPIO_ISRAM(pin)) { + if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) { + ret = gpio_read_bit(PIO_SDINP_STATE, gpio); + } + } else if (GPIO_ISBID(pin)) { + ret = gpio_read_bit(PIO_DRV_STATE, gpio); + if (ret > 0) + ret = gpio_read_bit(PIO_OUTP_STATE, gpio); + else if (ret == 0) + ret = + gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]); + } else if (GPIO_ISIN(pin)) { + ret = gpio_read_bit(PIO_INP_STATE, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_read_pin); + +/* Write Value to output */ +int pnx4008_gpio_write_pin(unsigned short pin, int output) +{ + int gpio = GPIO_BIT_MASK(pin); + int ret = -EFAULT; + + gpio_lock(); + if (GPIO_ISOUT(pin)) { + printk( "writing '%x' to '%x'\n", + gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR ); + ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio); + } else if (GPIO_ISRAM(pin)) { + if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0) + ret = gpio_set_bit(output ? PIO_SDOUTP_SET : + PIO_SDOUTP_CLR, gpio); + } else if (GPIO_ISBID(pin)) { + if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0) + ret = gpio_set_bit(output ? PIO_OUTP_SET : + PIO_OUTP_CLR, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_write_pin); + +/* Value = 1 : Set GPIO pin as output */ +/* Value = 0 : Set GPIO pin as input */ +int pnx4008_gpio_set_pin_direction(unsigned short pin, int output) +{ + int gpio = GPIO_BIT_MASK(pin); + int ret = -EFAULT; + + gpio_lock(); + if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) { + ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction); + +/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/ +int pnx4008_gpio_read_pin_direction(unsigned short pin) +{ + int gpio = GPIO_BIT_MASK(pin); + int ret = -EFAULT; + + gpio_lock(); + if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) { + ret = gpio_read_bit(PIO_DRV_STATE, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction); + +/* Value = 1 : Set pin to muxed function */ +/* Value = 0 : Set pin as GPIO */ +int pnx4008_gpio_set_pin_mux(unsigned short pin, int output) +{ + int gpio = GPIO_BIT_MASK(pin); + int ret = -EFAULT; + + gpio_lock(); + if (GPIO_ISBID(pin)) { + ret = + gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, + gpio_to_mux_map[gpio]); + } else if (GPIO_ISOUT(pin)) { + ret = + gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, + outp_to_mux_map[gpio]); + } else if (GPIO_ISMUX(pin)) { + ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux); + +/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/ +int pnx4008_gpio_read_pin_mux(unsigned short pin) +{ + int gpio = GPIO_BIT_MASK(pin); + int ret = -EFAULT; + + gpio_lock(); + if (GPIO_ISBID(pin)) { + ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]); + } else if (GPIO_ISOUT(pin)) { + ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]); + } else if (GPIO_ISMUX(pin)) { + ret = gpio_read_bit(PIO_MUX_STATE, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux); diff --git a/arch/arm/mach-pnx4008/irq.c b/arch/arm/mach-pnx4008/irq.c new file mode 100644 index 0000000..9b0a8e0 --- /dev/null +++ b/arch/arm/mach-pnx4008/irq.c @@ -0,0 +1,121 @@ +/* + * arch/arm/mach-pnx4008/irq.c + * + * PNX4008 IRQ controller driver + * + * Author: Dmitry Chigirev + * + * Based on reference code received from Philips: + * Copyright (C) 2003 Philips Semiconductors + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static u8 pnx4008_irq_type[NR_IRQS] = PNX4008_IRQ_TYPES; + +static void pnx4008_mask_irq(unsigned int irq) +{ + __raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */ +} + +static void pnx4008_unmask_irq(unsigned int irq) +{ + __raw_writel(__raw_readl(INTC_ER(irq)) | INTC_BIT(irq), INTC_ER(irq)); /* unmask interrupt */ +} + +static void pnx4008_mask_ack_irq(unsigned int irq) +{ + __raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */ + __raw_writel(INTC_BIT(irq), INTC_SR(irq)); /* clear interrupt status */ +} + +static int pnx4008_set_irq_type(unsigned int irq, unsigned int type) +{ + switch (type) { + case IRQT_RISING: + __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */ + __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /*rising edge */ + set_irq_handler(irq, do_edge_IRQ); + break; + case IRQT_FALLING: + __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */ + __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*falling edge */ + set_irq_handler(irq, do_edge_IRQ); + break; + case IRQT_LOW: + __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */ + __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*low level */ + set_irq_handler(irq, do_level_IRQ); + break; + case IRQT_HIGH: + __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */ + __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /* high level */ + set_irq_handler(irq, do_level_IRQ); + break; + + /* IRQT_BOTHEDGE is not supported */ + default: + printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type); + return -1; + } + return 0; +} + +static struct irqchip pnx4008_irq_chip = { + .ack = pnx4008_mask_ack_irq, + .mask = pnx4008_mask_irq, + .unmask = pnx4008_unmask_irq, + .set_type = pnx4008_set_irq_type, +}; + +void __init pnx4008_init_irq(void) +{ + unsigned int i; + + /* configure and enable IRQ 0,1,30,31 (cascade interrupts) mask all others */ + pnx4008_set_irq_type(SUB1_IRQ_N, pnx4008_irq_type[SUB1_IRQ_N]); + pnx4008_set_irq_type(SUB2_IRQ_N, pnx4008_irq_type[SUB2_IRQ_N]); + pnx4008_set_irq_type(SUB1_FIQ_N, pnx4008_irq_type[SUB1_FIQ_N]); + pnx4008_set_irq_type(SUB2_FIQ_N, pnx4008_irq_type[SUB2_FIQ_N]); + + __raw_writel((1 << SUB2_FIQ_N) | (1 << SUB1_FIQ_N) | + (1 << SUB2_IRQ_N) | (1 << SUB1_IRQ_N), + INTC_ER(MAIN_BASE_INT)); + __raw_writel(0, INTC_ER(SIC1_BASE_INT)); + __raw_writel(0, INTC_ER(SIC2_BASE_INT)); + + /* configure all other IRQ's */ + for (i = 0; i < NR_IRQS; i++) { + if (i == SUB2_FIQ_N || i == SUB1_FIQ_N || + i == SUB2_IRQ_N || i == SUB1_IRQ_N) + continue; + set_irq_flags(i, IRQF_VALID); + set_irq_chip(i, &pnx4008_irq_chip); + pnx4008_set_irq_type(i, pnx4008_irq_type[i]); + } +} + diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c new file mode 100644 index 0000000..3649cd3 --- /dev/null +++ b/arch/arm/mach-pnx4008/pm.c @@ -0,0 +1,184 @@ +/* + * arch/arm/mach-pnx4008/pm.c + * + * Power Management driver for PNX4008 + * + * Authors: Vitaly Wool, Dmitry Chigirev + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define SRAM_VA IO_ADDRESS(PNX4008_IRAM_BASE) + +static void *saved_sram; + +static struct clk *pll4_clk; + +static inline void pnx4008_standby(void) +{ + void (*pnx4008_cpu_standby_ptr) (void); + + local_irq_disable(); + local_fiq_disable(); + + clk_disable(pll4_clk); + + /*saving portion of SRAM to be used by suspend function. */ + memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_standby_sz); + + /*make sure SRAM copy gets physically written into SDRAM. + SDRAM will be placed into self-refresh during power down */ + flush_cache_all(); + + /*copy suspend function into SRAM */ + memcpy((void *)SRAM_VA, pnx4008_cpu_standby, pnx4008_cpu_standby_sz); + + /*do suspend */ + pnx4008_cpu_standby_ptr = (void *)SRAM_VA; + pnx4008_cpu_standby_ptr(); + + /*restoring portion of SRAM that was used by suspend function */ + memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_standby_sz); + + clk_enable(pll4_clk); + + local_fiq_enable(); + local_irq_enable(); +} + +static inline void pnx4008_suspend(void) +{ + void (*pnx4008_cpu_suspend_ptr) (void); + + local_irq_disable(); + local_fiq_disable(); + + clk_disable(pll4_clk); + + __raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT)); + __raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT)); + + /*saving portion of SRAM to be used by suspend function. */ + memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_suspend_sz); + + /*make sure SRAM copy gets physically written into SDRAM. + SDRAM will be placed into self-refresh during power down */ + flush_cache_all(); + + /*copy suspend function into SRAM */ + memcpy((void *)SRAM_VA, pnx4008_cpu_suspend, pnx4008_cpu_suspend_sz); + + /*do suspend */ + pnx4008_cpu_suspend_ptr = (void *)SRAM_VA; + pnx4008_cpu_suspend_ptr(); + + /*restoring portion of SRAM that was used by suspend function */ + memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_suspend_sz); + + clk_enable(pll4_clk); + + local_fiq_enable(); + local_irq_enable(); +} + +static int pnx4008_pm_enter(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + pnx4008_standby(); + break; + case PM_SUSPEND_MEM: + pnx4008_suspend(); + break; + case PM_SUSPEND_DISK: + return -ENOTSUPP; + default: + return -EINVAL; + } + return 0; +} + +/* + * Called after processes are frozen, but before we shut down devices. + */ +static int pnx4008_pm_prepare(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + break; + + case PM_SUSPEND_DISK: + return -ENOTSUPP; + break; + + default: + return -EINVAL; + break; + } + return 0; +} + +/* + * Called after devices are re-setup, but before processes are thawed. + */ +static int pnx4008_pm_finish(suspend_state_t state) +{ + return 0; +} + +/* + * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. + */ +static struct pm_ops pnx4008_pm_ops = { + .prepare = pnx4008_pm_prepare, + .enter = pnx4008_pm_enter, + .finish = pnx4008_pm_finish, +}; + +static int __init pnx4008_pm_init(void) +{ + u32 sram_size_to_allocate; + + pll4_clk = clk_get(0, "ck_pll4"); + if (IS_ERR(pll4_clk)) { + printk(KERN_ERR + "PM Suspend cannot acquire ARM(PLL4) clock control\n"); + return PTR_ERR(pll4_clk); + } + + if (pnx4008_cpu_standby_sz > pnx4008_cpu_suspend_sz) + sram_size_to_allocate = pnx4008_cpu_standby_sz; + else + sram_size_to_allocate = pnx4008_cpu_suspend_sz; + + saved_sram = kmalloc(sram_size_to_allocate, GFP_ATOMIC); + if (!saved_sram) { + printk(KERN_ERR + "PM Suspend: cannot allocate memory to save portion of SRAM\n"); + clk_put(pll4_clk); + return -ENOMEM; + } + + pm_set_ops(&pnx4008_pm_ops); + return 0; +} + +late_initcall(pnx4008_pm_init); diff --git a/arch/arm/mach-pnx4008/serial.c b/arch/arm/mach-pnx4008/serial.c new file mode 100644 index 0000000..95a1b3f --- /dev/null +++ b/arch/arm/mach-pnx4008/serial.c @@ -0,0 +1,69 @@ +/* + * linux/arch/arm/mach-pnx4008/serial.c + * + * PNX4008 UART initialization + * + * Copyright: MontaVista Software Inc. (c) 2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include + +#define UART_3 0 +#define UART_4 1 +#define UART_5 2 +#define UART_6 3 +#define UART_UNKNOWN (-1) + +#define UART3_BASE_VA IO_ADDRESS(PNX4008_UART3_BASE) +#define UART4_BASE_VA IO_ADDRESS(PNX4008_UART4_BASE) +#define UART5_BASE_VA IO_ADDRESS(PNX4008_UART5_BASE) +#define UART6_BASE_VA IO_ADDRESS(PNX4008_UART6_BASE) + +#define UART_FCR_OFFSET 8 +#define UART_FIFO_SIZE 64 + +void pnx4008_uart_init(void) +{ + u32 tmp; + int i = UART_FIFO_SIZE; + + __raw_writel(0xC1, UART5_BASE_VA + UART_FCR_OFFSET); + __raw_writel(0xC1, UART3_BASE_VA + UART_FCR_OFFSET); + + /* Send a NULL to fix the UART HW bug */ + __raw_writel(0x00, UART5_BASE_VA); + __raw_writel(0x00, UART3_BASE_VA); + + while (i--) { + tmp = __raw_readl(UART5_BASE_VA); + tmp = __raw_readl(UART3_BASE_VA); + } + __raw_writel(0, UART5_BASE_VA + UART_FCR_OFFSET); + __raw_writel(0, UART3_BASE_VA + UART_FCR_OFFSET); + + /* setup wakeup interrupt */ + start_int_set_rising_edge(SE_U3_RX_INT); + start_int_ack(SE_U3_RX_INT); + start_int_umask(SE_U3_RX_INT); + + start_int_set_rising_edge(SE_U5_RX_INT); + start_int_ack(SE_U5_RX_INT); + start_int_umask(SE_U5_RX_INT); +} + diff --git a/arch/arm/mach-pnx4008/sleep.S b/arch/arm/mach-pnx4008/sleep.S new file mode 100644 index 0000000..93c802b --- /dev/null +++ b/arch/arm/mach-pnx4008/sleep.S @@ -0,0 +1,196 @@ +/* + * linux/arch/arm/mach-pnx4008/sleep.S + * + * PNX4008 support for STOP mode and SDRAM self-refresh + * + * Authors: Dmitry Chigirev, Vitaly Wool + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include + +#define PWRMAN_VA_BASE IO_ADDRESS(PNX4008_PWRMAN_BASE) +#define PWR_CTRL_REG_OFFS 0x44 + +#define SDRAM_CFG_VA_BASE IO_ADDRESS(PNX4008_SDRAM_CFG_BASE) +#define MPMC_STATUS_REG_OFFS 0x4 + + .text + +ENTRY(pnx4008_cpu_suspend) + @this function should be entered in Direct run mode. + + @ save registers on stack + stmfd sp!, {r0 - r6, lr} + + @ setup Power Manager base address in r4 + @ and put it's value in r5 + mov r4, #(PWRMAN_VA_BASE & 0xff000000) + orr r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000) + orr r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00) + orr r4, r4, #(PWRMAN_VA_BASE & 0x000000ff) + ldr r5, [r4, #PWR_CTRL_REG_OFFS] + + @ setup SDRAM controller base address in r2 + @ and put it's value in r3 + mov r2, #(SDRAM_CFG_VA_BASE & 0xff000000) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff) + ldr r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround + + @ clear SDRAM self-refresh bit latch + and r5, r5, #(~(1 << 8)) + @ clear SDRAM self-refresh bit + and r5, r5, #(~(1 << 9)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ do save current bit settings in r1 + mov r1, r5 + + @ set SDRAM self-refresh bit + orr r5, r5, #(1 << 9) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ set SDRAM self-refresh bit latch + orr r5, r5, #(1 << 8) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ clear SDRAM self-refresh bit latch + and r5, r5, #(~(1 << 8)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ clear SDRAM self-refresh bit + and r5, r5, #(~(1 << 9)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ wait for SDRAM to get into self-refresh mode +2: ldr r3, [r2, #MPMC_STATUS_REG_OFFS] + tst r3, #(1 << 2) + beq 2b + + @ to prepare SDRAM to get out of self-refresh mode after wakeup + orr r5, r5, #(1 << 7) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ do enter stop mode + orr r5, r5, #(1 << 0) + str r5, [r4, #PWR_CTRL_REG_OFFS] + nop + nop + nop + nop + nop + nop + nop + nop + nop + + @ sleeping now... + + @ coming out of STOP mode into Direct Run mode + @ clear STOP mode and SDRAM self-refresh bits + str r1, [r4, #PWR_CTRL_REG_OFFS] + + @ wait for SDRAM to get out self-refresh mode +3: ldr r3, [r2, #MPMC_STATUS_REG_OFFS] + tst r3, #5 + bne 3b + + @ restore regs and return + ldmfd sp!, {r0 - r6, pc} + +ENTRY(pnx4008_cpu_suspend_sz) + .word . - pnx4008_cpu_suspend + +ENTRY(pnx4008_cpu_standby) + @ save registers on stack + stmfd sp!, {r0 - r6, lr} + + @ setup Power Manager base address in r4 + @ and put it's value in r5 + mov r4, #(PWRMAN_VA_BASE & 0xff000000) + orr r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000) + orr r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00) + orr r4, r4, #(PWRMAN_VA_BASE & 0x000000ff) + ldr r5, [r4, #PWR_CTRL_REG_OFFS] + + @ setup SDRAM controller base address in r2 + @ and put it's value in r3 + mov r2, #(SDRAM_CFG_VA_BASE & 0xff000000) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff) + ldr r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround + + @ clear SDRAM self-refresh bit latch + and r5, r5, #(~(1 << 8)) + @ clear SDRAM self-refresh bit + and r5, r5, #(~(1 << 9)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ do save current bit settings in r1 + mov r1, r5 + + @ set SDRAM self-refresh bit + orr r5, r5, #(1 << 9) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ set SDRAM self-refresh bit latch + orr r5, r5, #(1 << 8) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ clear SDRAM self-refresh bit latch + and r5, r5, #(~(1 << 8)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ clear SDRAM self-refresh bit + and r5, r5, #(~(1 << 9)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ wait for SDRAM to get into self-refresh mode +2: ldr r3, [r2, #MPMC_STATUS_REG_OFFS] + tst r3, #(1 << 2) + beq 2b + + @ set 'get out of self-refresh mode after wakeup' bit + orr r5, r5, #(1 << 7) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + mcr p15, 0, r0, c7, c0, 4 @ kinda sleeping now... + + @ set SDRAM self-refresh bit latch + orr r5, r5, #(1 << 8) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ clear SDRAM self-refresh bit latch + and r5, r5, #(~(1 << 8)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ wait for SDRAM to get out self-refresh mode +3: ldr r3, [r2, #MPMC_STATUS_REG_OFFS] + tst r3, #5 + bne 3b + + @ restore regs and return + ldmfd sp!, {r0 - r6, pc} + +ENTRY(pnx4008_cpu_standby_sz) + .word . - pnx4008_cpu_standby + +ENTRY(pnx4008_cache_clean_invalidate) + stmfd sp!, {r0 - r6, lr} +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +#else +1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate + bne 1b +#endif + ldmfd sp!, {r0 - r6, pc} diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c new file mode 100644 index 0000000..4ce6806 --- /dev/null +++ b/arch/arm/mach-pnx4008/time.c @@ -0,0 +1,141 @@ +/* + * arch/arm/mach-pnx4008/time.c + * + * PNX4008 Timers + * + * Authors: Vitaly Wool, Dmitry Chigirev, Grigory Tolstolytkin + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/*! Note: all timers are UPCOUNTING */ + +/*! + * Returns number of us since last clock interrupt. Note that interrupts + * will have been disabled by do_gettimeoffset() + */ +static unsigned long pnx4008_gettimeoffset(void) +{ + u32 ticks_to_match = + __raw_readl(HSTIM_MATCH0) - __raw_readl(HSTIM_COUNTER); + u32 elapsed = LATCH - ticks_to_match; + return (elapsed * (tick_nsec / 1000)) / LATCH; +} + +/*! + * IRQ handler for the timer + */ +static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + if (__raw_readl(HSTIM_INT) & MATCH0_INT) { + + write_seqlock(&xtime_lock); + + do { + timer_tick(regs); + + /* + * this algorithm takes care of possible delay + * for this interrupt handling longer than a normal + * timer period + */ + __raw_writel(__raw_readl(HSTIM_MATCH0) + LATCH, + HSTIM_MATCH0); + __raw_writel(MATCH0_INT, HSTIM_INT); /* clear interrupt */ + + /* + * The goal is to keep incrementing HSTIM_MATCH0 + * register until HSTIM_MATCH0 indicates time after + * what HSTIM_COUNTER indicates. + */ + } while ((signed) + (__raw_readl(HSTIM_MATCH0) - + __raw_readl(HSTIM_COUNTER)) < 0); + + write_sequnlock(&xtime_lock); + } + + return IRQ_HANDLED; +} + +static struct irqaction pnx4008_timer_irq = { + .name = "PNX4008 Tick Timer", + .flags = SA_INTERRUPT | SA_TIMER, + .handler = pnx4008_timer_interrupt +}; + +/*! + * Set up timer and timer interrupt. + */ +static __init void pnx4008_setup_timer(void) +{ + __raw_writel(RESET_COUNT, MSTIM_CTRL); + while (__raw_readl(MSTIM_COUNTER)) ; /* wait for reset to complete. 100% guarantee event */ + __raw_writel(0, MSTIM_CTRL); /* stop the timer */ + __raw_writel(0, MSTIM_MCTRL); + + __raw_writel(RESET_COUNT, HSTIM_CTRL); + while (__raw_readl(HSTIM_COUNTER)) ; /* wait for reset to complete. 100% guarantee event */ + __raw_writel(0, HSTIM_CTRL); + __raw_writel(0, HSTIM_MCTRL); + __raw_writel(0, HSTIM_CCR); + __raw_writel(12, HSTIM_PMATCH); /* scale down to 1 MHZ */ + __raw_writel(LATCH, HSTIM_MATCH0); + __raw_writel(MR0_INT, HSTIM_MCTRL); + + setup_irq(HSTIMER_INT, &pnx4008_timer_irq); + + __raw_writel(COUNT_ENAB | DEBUG_EN, HSTIM_CTRL); /*start timer, stop when JTAG active */ +} + +/* Timer Clock Control in PM register */ +#define TIMCLK_CTRL_REG IO_ADDRESS((PNX4008_PWRMAN_BASE + 0xBC)) +#define WATCHDOG_CLK_EN 1 +#define TIMER_CLK_EN 2 /* HS and MS timers? */ + +static u32 timclk_ctrl_reg_save; + +void pnx4008_timer_suspend(void) +{ + timclk_ctrl_reg_save = __raw_readl(TIMCLK_CTRL_REG); + __raw_writel(0, TIMCLK_CTRL_REG); /* disable timers */ +} + +void pnx4008_timer_resume(void) +{ + __raw_writel(timclk_ctrl_reg_save, TIMCLK_CTRL_REG); /* enable timers */ +} + +struct sys_timer pnx4008_timer = { + .init = pnx4008_setup_timer, + .offset = pnx4008_gettimeoffset, + .suspend = pnx4008_timer_suspend, + .resume = pnx4008_timer_resume, +}; + diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 0104fd1..ea5137f 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -61,6 +61,7 @@ config MACH_POODLE bool "Enable Sharp SL-5600 (Poodle) Support" depends PXA_SHARPSL_25x select SHARP_LOCOMO + select PXA_SSP config MACH_CORGI bool "Enable Sharp SL-C700 (Corgi) Support" diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 4e8a983..1610690 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_ARCH_PXA_IDP) += idp.o obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o -obj-$(CONFIG_MACH_POODLE) += poodle.o +obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o obj-$(CONFIG_MACH_TOSA) += tosa.o # Support for blinky lights diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index d6d7260..bf6648a 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -19,6 +19,7 @@ #include #include #include #include +#include #include #include @@ -26,6 +27,7 @@ #include #include #include #include +#include #include #include @@ -310,8 +312,31 @@ static struct platform_device *devices[] &corgiled_device, }; +static void corgi_poweroff(void) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + + if (!machine_is_corgi()) + /* Green LED off tells the bootloader to halt */ + reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); + arm_machine_restart('h'); +} + +static void corgi_restart(char mode) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + + if (!machine_is_corgi()) + /* Green LED on tells the bootloader to reboot */ + set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); + arm_machine_restart('h'); +} + static void __init corgi_init(void) { + pm_power_off = corgi_poweroff; + arm_pm_restart = corgi_restart; + /* setup sleep mode values */ PWER = 0x00000002; PFER = 0x00000000; diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c index 7a1ab73..4c3de40 100644 --- a/arch/arm/mach-pxa/corgi_pm.c +++ b/arch/arm/mach-pxa/corgi_pm.c @@ -27,6 +27,13 @@ #include #include #include "sharpsl.h" +#define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ +#define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ +#define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */ +#define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */ +#define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ +#define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ + static void corgi_charger_init(void) { pxa_gpio_mode(CORGI_GPIO_ADC_TEMP_ON | GPIO_OUT); @@ -195,9 +202,16 @@ static struct sharpsl_charger_machinfo c .read_devdata = corgipm_read_devdata, .charger_wakeup = corgi_charger_wakeup, .should_wakeup = corgi_should_wakeup, - .bat_levels = 40, - .bat_levels_noac = spitz_battery_levels_noac, - .bat_levels_acin = spitz_battery_levels_acin, + .backlight_limit = corgibl_limit_intensity, + .charge_on_volt = SHARPSL_CHARGE_ON_VOLT, + .charge_on_temp = SHARPSL_CHARGE_ON_TEMP, + .charge_acin_high = SHARPSL_CHARGE_ON_ACIN_HIGH, + .charge_acin_low = SHARPSL_CHARGE_ON_ACIN_LOW, + .fatal_acin_volt = SHARPSL_FATAL_ACIN_VOLT, + .fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT, + .bat_levels = 40, + .bat_levels_noac = spitz_battery_levels_noac, + .bat_levels_acin = spitz_battery_levels_acin, .status_high_acin = 188, .status_low_acin = 178, .status_high_noac = 185, @@ -214,6 +228,9 @@ static int __devinit corgipm_init(void) if (!corgipm_device) return -ENOMEM; + if (!machine_is_corgi()) + corgi_pm_machinfo.batfull_irq = 1; + corgipm_device->dev.platform_data = &corgi_pm_machinfo; ret = platform_device_add(corgipm_device); diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c index 8a25a1c..f942131 100644 --- a/arch/arm/mach-pxa/corgi_ssp.c +++ b/arch/arm/mach-pxa/corgi_ssp.c @@ -50,12 +50,14 @@ unsigned long corgi_ssp_ads7846_putget(u unsigned long ret,flag; spin_lock_irqsave(&corgi_ssp_lock, flag); - GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); + if (ssp_machinfo->cs_ads7846 >= 0) + GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); ssp_write_word(&corgi_ssp_dev,data); ret = ssp_read_word(&corgi_ssp_dev); - GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); + if (ssp_machinfo->cs_ads7846 >= 0) + GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); spin_unlock_irqrestore(&corgi_ssp_lock, flag); return ret; @@ -68,12 +70,14 @@ unsigned long corgi_ssp_ads7846_putget(u void corgi_ssp_ads7846_lock(void) { spin_lock(&corgi_ssp_lock); - GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); + if (ssp_machinfo->cs_ads7846 >= 0) + GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); } void corgi_ssp_ads7846_unlock(void) { - GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); + if (ssp_machinfo->cs_ads7846 >= 0) + GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); spin_unlock(&corgi_ssp_lock); } @@ -110,11 +114,13 @@ unsigned long corgi_ssp_dac_put(ulong da ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), sscr1, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_lcdcon)); ssp_enable(&corgi_ssp_dev); - GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); + if (ssp_machinfo->cs_lcdcon >= 0) + GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); ssp_write_word(&corgi_ssp_dev,data); /* Read null data back from device to prevent SSP overflow */ ssp_read_word(&corgi_ssp_dev); - GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); + if (ssp_machinfo->cs_lcdcon >= 0) + GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); @@ -147,7 +153,8 @@ int corgi_ssp_max1111_get(ulong data) int voltage,voltage1,voltage2; spin_lock_irqsave(&corgi_ssp_lock, flag); - GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); + if (ssp_machinfo->cs_max1111 >= 0) + GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_max1111)); ssp_enable(&corgi_ssp_dev); @@ -169,7 +176,8 @@ int corgi_ssp_max1111_get(ulong data) ssp_disable(&corgi_ssp_dev); ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); ssp_enable(&corgi_ssp_dev); - GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); + if (ssp_machinfo->cs_max1111 >= 0) + GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); spin_unlock_irqrestore(&corgi_ssp_lock, flag); if (voltage1 & 0xc0 || voltage2 & 0x3f) @@ -196,9 +204,12 @@ static int __init corgi_ssp_probe(struct int ret; /* Chip Select - Disable All */ - pxa_gpio_mode(ssp_machinfo->cs_lcdcon | GPIO_OUT | GPIO_DFLT_HIGH); - pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH); - pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH); + if (ssp_machinfo->cs_lcdcon >= 0) + pxa_gpio_mode(ssp_machinfo->cs_lcdcon | GPIO_OUT | GPIO_DFLT_HIGH); + if (ssp_machinfo->cs_max1111 >= 0) + pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH); + if (ssp_machinfo->cs_ads7846 >= 0) + pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH); ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0); @@ -229,9 +240,12 @@ static int corgi_ssp_suspend(struct plat static int corgi_ssp_resume(struct platform_device *dev) { - GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */ - GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/ - GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ + if (ssp_machinfo->cs_lcdcon >= 0) + GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */ + if (ssp_machinfo->cs_max1111 >= 0) + GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/ + if (ssp_machinfo->cs_ads7846 >= 0) + GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state); ssp_enable(&corgi_ssp_dev); diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 3e26d7c..1ab26c6 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -22,6 +22,10 @@ #include #include #include +#include +#include +#include + #include #include #include @@ -196,6 +200,78 @@ static struct resource smc91x_resources[ }, }; +/* ADS7846 is connected through SSP ... and if your board has J5 populated, + * you can select it to replace the ucb1400 by switching the touchscreen cable + * (to J5) and poking board registers (as done below). Else it's only useful + * for the temperature sensors. + */ +static struct resource pxa_ssp_resources[] = { + [0] = { + .start = __PREG(SSCR0_P(1)), + .end = __PREG(SSCR0_P(1)) + 0x14, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_SSP, + .end = IRQ_SSP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct pxa2xx_spi_master pxa_ssp_master_info = { + .ssp_type = PXA25x_SSP, + .clock_enable = CKEN3_SSP, + .num_chipselect = 0, +}; + +static struct platform_device pxa_ssp = { + .name = "pxa2xx-spi", + .id = 1, + .resource = pxa_ssp_resources, + .num_resources = ARRAY_SIZE(pxa_ssp_resources), + .dev = { + .platform_data = &pxa_ssp_master_info, + }, +}; + +static int lubbock_ads7846_pendown_state(void) +{ + /* TS_BUSY is bit 8 in LUB_MISC_RD, but pendown is irq-only */ + return 0; +} + +static struct ads7846_platform_data ads_info = { + .model = 7846, + .vref_delay_usecs = 100, /* internal, no cap */ + .get_pendown_state = lubbock_ads7846_pendown_state, + // .x_plate_ohms = 500, /* GUESS! */ + // .y_plate_ohms = 500, /* GUESS! */ +}; + +static void ads7846_cs(u32 command) +{ + static const unsigned TS_nCS = 1 << 11; + lubbock_set_misc_wr(TS_nCS, (command == PXA2XX_CS_ASSERT) ? 0 : TS_nCS); +} + +static struct pxa2xx_spi_chip ads_hw = { + .tx_threshold = 1, + .rx_threshold = 2, + .cs_control = ads7846_cs, +}; + +static struct spi_board_info spi_board_info[] __initdata = { { + .modalias = "ads7846", + .platform_data = &ads_info, + .controller_data = &ads_hw, + .irq = LUBBOCK_BB_IRQ, + .max_speed_hz = 120000 /* max sample rate at 3V */ + * 26 /* command + data + overhead */, + .bus_num = 1, + .chip_select = 0, +}, +}; + static struct platform_device smc91x_device = { .name = "smc91x", .id = -1, @@ -272,6 +348,7 @@ static struct platform_device *devices[] &smc91x_device, &lubbock_flash_device[0], &lubbock_flash_device[1], + &pxa_ssp, }; static struct pxafb_mach_info sharp_lm8v31 __initdata = { @@ -400,6 +477,8 @@ static void __init lubbock_init(void) lubbock_flash_data[flashboot^1].name = "application-flash"; lubbock_flash_data[flashboot].name = "boot-rom"; (void) platform_add_devices(devices, ARRAY_SIZE(devices)); + + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); } static struct map_desc lubbock_io_desc[] __initdata = { @@ -416,6 +495,11 @@ static void __init lubbock_map_io(void) pxa_map_io(); iotable_init(lubbock_io_desc, ARRAY_SIZE(lubbock_io_desc)); + /* SSP data pins */ + pxa_gpio_mode(GPIO23_SCLK_MD); + pxa_gpio_mode(GPIO25_STXD_MD); + pxa_gpio_mode(GPIO26_SRXD_MD); + /* This enables the BTUART */ pxa_gpio_mode(GPIO42_BTRXD_MD); pxa_gpio_mode(GPIO43_BTTXD_MD); diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index a042473..9a9fa87 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -18,11 +18,14 @@ #include #include #include #include +#include +#include #include #include #include #include +#include #include #include @@ -34,12 +37,15 @@ #include #include #include #include +#include +#include #include #include #include #include "generic.h" +#include "sharpsl.h" static struct resource poodle_scoop_resources[] = { [0] = { @@ -117,13 +123,71 @@ static struct resource locomo_resources[ }, }; -static struct platform_device locomo_device = { +struct platform_device poodle_locomo_device = { .name = "locomo", .id = 0, .num_resources = ARRAY_SIZE(locomo_resources), .resource = locomo_resources, }; +EXPORT_SYMBOL(poodle_locomo_device); + +/* + * Poodle SSP Device + */ + +struct platform_device poodle_ssp_device = { + .name = "corgi-ssp", + .id = -1, +}; + +struct corgissp_machinfo poodle_ssp_machinfo = { + .port = 1, + .cs_lcdcon = -1, + .cs_ads7846 = -1, + .cs_max1111 = -1, + .clk_lcdcon = 2, + .clk_ads7846 = 36, + .clk_max1111 = 2, +}; + + +/* + * Poodle Touch Screen Device + */ +static struct resource poodlets_resources[] = { + [0] = { + .start = POODLE_IRQ_GPIO_TP_INT, + .end = POODLE_IRQ_GPIO_TP_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static unsigned long poodle_get_hsync_len(void) +{ + return 0; +} + +static void poodle_null_hsync(void) +{ +} + +static struct corgits_machinfo poodle_ts_machinfo = { + .get_hsync_len = poodle_get_hsync_len, + .put_hsync = poodle_null_hsync, + .wait_hsync = poodle_null_hsync, +}; + +static struct platform_device poodle_ts_device = { + .name = "corgi-ts", + .dev = { + .platform_data = &poodle_ts_machinfo, + }, + .id = -1, + .num_resources = ARRAY_SIZE(poodlets_resources), + .resource = poodlets_resources, +}; + /* * MMC/SD Device @@ -141,7 +205,9 @@ static int poodle_mci_init(struct device pxa_gpio_mode(GPIO6_MMCCLK_MD); pxa_gpio_mode(GPIO8_MMCCS0_MD); pxa_gpio_mode(POODLE_GPIO_nSD_DETECT | GPIO_IN); + pxa_gpio_mode(POODLE_GPIO_nSD_WP | GPIO_IN); pxa_gpio_mode(POODLE_GPIO_SD_PWR | GPIO_OUT); + pxa_gpio_mode(POODLE_GPIO_SD_PWR1 | GPIO_OUT); poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250); @@ -160,12 +226,22 @@ static void poodle_mci_setpower(struct d { struct pxamci_platform_data* p_d = dev->platform_data; - if (( 1 << vdd) & p_d->ocr_mask) - GPSR1 = GPIO_bit(POODLE_GPIO_SD_PWR); - else - GPCR1 = GPIO_bit(POODLE_GPIO_SD_PWR); + if (( 1 << vdd) & p_d->ocr_mask) { + GPSR(POODLE_GPIO_SD_PWR) = GPIO_bit(POODLE_GPIO_SD_PWR); + mdelay(2); + GPSR(POODLE_GPIO_SD_PWR1) = GPIO_bit(POODLE_GPIO_SD_PWR1); + } else { + GPCR(POODLE_GPIO_SD_PWR1) = GPIO_bit(POODLE_GPIO_SD_PWR1); + GPCR(POODLE_GPIO_SD_PWR) = GPIO_bit(POODLE_GPIO_SD_PWR); + } +} + +static int poodle_mci_get_ro(struct device *dev) +{ + return GPLR(POODLE_GPIO_nSD_WP) & GPIO_bit(POODLE_GPIO_nSD_WP); } + static void poodle_mci_exit(struct device *dev, void *data) { free_irq(POODLE_IRQ_GPIO_nSD_DETECT, data); @@ -174,6 +250,7 @@ static void poodle_mci_exit(struct devic static struct pxamci_platform_data poodle_mci_platform_data = { .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .init = poodle_mci_init, + .get_ro = poodle_mci_get_ro, .setpower = poodle_mci_setpower, .exit = poodle_mci_exit, }; @@ -243,14 +320,31 @@ static struct pxafb_mach_info poodle_fb_ }; static struct platform_device *devices[] __initdata = { - &locomo_device, + &poodle_locomo_device, &poodle_scoop_device, + &poodle_ssp_device, + &poodle_ts_device, }; +static void poodle_poweroff(void) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + arm_machine_restart('h'); +} + +static void poodle_restart(char mode) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + arm_machine_restart('h'); +} + static void __init poodle_init(void) { int ret = 0; + pm_power_off = poodle_poweroff; + arm_pm_restart = poodle_restart; + /* setup sleep mode values */ PWER = 0x00000002; PFER = 0x00000000; @@ -288,6 +382,7 @@ static void __init poodle_init(void) GPSR1 = 0x00000000; GPSR2 = 0x00000000; + set_pxa_fb_parent(&poodle_locomo_device.dev); set_pxa_fb_info(&poodle_fb_info); pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT); pxa_gpio_mode(POODLE_GPIO_IR_ON | GPIO_OUT); @@ -301,6 +396,7 @@ static void __init poodle_init(void) if (ret) { printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n"); } + corgi_ssp_set_machinfo(&poodle_ssp_machinfo); } static void __init fixup_poodle(struct machine_desc *desc, diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 6d402b2..0f16487 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -128,6 +128,9 @@ #define MAXCTRL_STR 1u << 7 */ int sharpsl_pm_pxa_read_max1111(int channel) { + if (machine_is_tosa()) // Ugly, better move this function into another module + return 0; + return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1 | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); } @@ -156,7 +159,7 @@ void sharpsl_pm_pxa_init(void) else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQT_FALLING); } - if (!machine_is_corgi()) + if (sharpsl_pm.machinfo->batfull_irq) { /* Register interrupt handler. */ if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, SA_INTERRUPT, "CO", sharpsl_chrg_full_isr)) { @@ -174,6 +177,6 @@ void sharpsl_pm_pxa_remove(void) if (sharpsl_pm.machinfo->gpio_fatal) free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr); - if (!machine_is_corgi()) + if (sharpsl_pm.machinfo->batfull_irq) free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr); } diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S index c986268..0650bed 100644 --- a/arch/arm/mach-pxa/sleep.S +++ b/arch/arm/mach-pxa/sleep.S @@ -189,7 +189,7 @@ #endif .data .align 5 ENTRY(pxa_cpu_resume) - mov r0, #PSR_I_BIT | PSR_F_BIT | MODE_SVC @ set SVC, irqs off + mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off msr cpsr_c, r0 ldr r0, sleep_save_sp @ stack phys addr diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 44bcb80..eb9937f 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -20,6 +20,7 @@ #include #include #include #include +#include #include #include @@ -27,6 +28,7 @@ #include #include #include #include +#include #include #include @@ -432,8 +434,31 @@ static struct platform_device *devices[] &spitzled_device, }; +static void spitz_poweroff(void) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + + pxa_gpio_mode(SPITZ_GPIO_ON_RESET | GPIO_OUT); + GPSR(SPITZ_GPIO_ON_RESET) = GPIO_bit(SPITZ_GPIO_ON_RESET); + + mdelay(1000); + arm_machine_restart('h'); +} + +static void spitz_restart(char mode) +{ + /* Bootloader magic for a reboot */ + if((MSC0 & 0xffff0000) == 0x7ff00000) + MSC0 = (MSC0 & 0xffff) | 0x7ee00000; + + spitz_poweroff(); +} + static void __init common_init(void) { + pm_power_off = spitz_poweroff; + arm_pm_restart = spitz_restart; + PMCR = 0x00; /* setup sleep mode values */ diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index 5e5bdc8..40be833 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -27,6 +27,13 @@ #include #include #include "sharpsl.h" +#define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ +#define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ +#define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */ +#define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */ +#define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ +#define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ + static int spitz_last_ac_status; static void spitz_charger_init(void) @@ -190,6 +197,7 @@ struct sharpsl_charger_machinfo spitz_pm .gpio_batlock = SPITZ_GPIO_BAT_COVER, .gpio_acin = SPITZ_GPIO_AC_IN, .gpio_batfull = SPITZ_GPIO_CHRG_FULL, + .batfull_irq = 1, .gpio_fatal = SPITZ_GPIO_FATAL_BAT, .discharge = spitz_discharge, .discharge1 = spitz_discharge1, @@ -200,6 +208,13 @@ struct sharpsl_charger_machinfo spitz_pm .read_devdata = spitzpm_read_devdata, .charger_wakeup = spitz_charger_wakeup, .should_wakeup = spitz_should_wakeup, + .backlight_limit = corgibl_limit_intensity, + .charge_on_volt = SHARPSL_CHARGE_ON_VOLT, + .charge_on_temp = SHARPSL_CHARGE_ON_TEMP, + .charge_acin_high = SHARPSL_CHARGE_ON_ACIN_HIGH, + .charge_acin_low = SHARPSL_CHARGE_ON_ACIN_LOW, + .fatal_acin_volt = SHARPSL_FATAL_ACIN_VOLT, + .fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT, .bat_levels = 40, .bat_levels_noac = spitz_battery_levels_noac, .bat_levels_acin = spitz_battery_levels_acin, diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 76c0e7f..7152bc1 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -19,12 +19,15 @@ #include #include #include #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -266,8 +269,31 @@ static struct platform_device *devices[] &tosaled_device, }; +static void tosa_poweroff(void) +{ + RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; + + pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_OUT); + GPSR(TOSA_GPIO_ON_RESET) = GPIO_bit(TOSA_GPIO_ON_RESET); + + mdelay(1000); + arm_machine_restart('h'); +} + +static void tosa_restart(char mode) +{ + /* Bootloader magic for a reboot */ + if((MSC0 & 0xffff0000) == 0x7ff00000) + MSC0 = (MSC0 & 0xffff) | 0x7ee00000; + + tosa_poweroff(); +} + static void __init tosa_init(void) { + pm_power_off = tosa_poweroff; + arm_pm_restart = tosa_restart; + pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_IN); pxa_gpio_mode(TOSA_GPIO_TC6393_INT | GPIO_IN); pxa_gpio_mode(TOSA_GPIO_USB_IN | GPIO_IN); diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 970f98d..b4171dd 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -70,6 +70,24 @@ config ARCH_S3C2440 help Say Y here if you are using the SMDK2440. +config SMDK2440_CPU2440 + bool "SMDK2440 with S3C2440 CPU module" + depends on ARCH_S3C2440 + default y if ARCH_S3C2440 + select CPU_S3C2440 + +config SMDK2440_CPU2442 + bool "SMDM2440 with S3C2442 CPU module" + depends on ARCH_S3C2440 + select CPU_S3C2442 + +config MACH_SMDK2413 + bool "SMDK2413" + select CPU_S3C2412 + select MACH_SMDK + help + Say Y here if you are using an SMDK2413 + config MACH_VR1000 bool "Thorcom VR1000" select CPU_S3C2410 @@ -102,19 +120,55 @@ config MACH_NEXCODER_2440 endmenu +config S3C2410_CLOCK + bool + help + Clock code for the S3C2410, and similar processors + config CPU_S3C2410 bool depends on ARCH_S3C2410 + select S3C2410_CLOCK help Support for S3C2410 and S3C2410A family from the S3C24XX line of Samsung Mobile CPUs. +# internal node to signify if we are only dealing with an S3C2412 + +config CPU_S3C2412_ONLY + bool + depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \ + !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412 + default y if CPU_S3C2412 + +config CPU_S3C2412 + bool + depends on ARCH_S3C2410 + help + Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line + +config CPU_S3C244X + bool + depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442) + help + Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems. + config CPU_S3C2440 bool depends on ARCH_S3C2410 + select S3C2410_CLOCK + select CPU_S3C244X help Support for S3C2440 Samsung Mobile CPU based systems. +config CPU_S3C2442 + bool + depends on ARCH_S3C2420 + select S3C2410_CLOCK + select CPU_S3C244X + help + Support for S3C2442 Samsung Mobile CPU based systems. + comment "S3C2410 Boot" config S3C2410_BOOT_WATCHDOG diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 3e5712d..0c79386 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -24,6 +24,20 @@ # Power Management support obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o +# S3C2412 support +obj-$(CONFIG_CPU_S3C2412) += s3c2412.o +obj-$(CONFIG_CPU_S3C2412) += s3c2412-clock.o + +# +# S3C244X support + +obj-$(CONFIG_CPU_S3C244X) += s3c244x.o +obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o + +# Clock control + +obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o + # S3C2440 support obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o @@ -31,6 +45,11 @@ obj-$(CONFIG_CPU_S3C2440) += s3c2440-ir obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o obj-$(CONFIG_CPU_S3C2440) += s3c2410-gpio.o +# S3C2442 support + +obj-$(CONFIG_CPU_S3C2442) += s3c2442.o +obj-$(CONFIG_CPU_S3C2442) += s3c2442-clock.o + # bast extras obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o @@ -43,6 +62,7 @@ obj-$(CONFIG_ARCH_BAST) += mach-bast.o obj-$(CONFIG_ARCH_H1940) += mach-h1940.o obj-$(CONFIG_MACH_N30) += mach-n30.o obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o +obj-$(CONFIG_MACH_SMDK2413) += mach-smdk2413.o obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index 6de713a..e13fb67 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c @@ -3,7 +3,7 @@ * Copyright (c) 2004-2005 Simtec Electronics * Ben Dooks * - * S3C2410 Clock control support + * S3C24XX Core clock control support * * Based on, and code from linux/arch/arm/mach-versatile/clock.c ** @@ -56,25 +56,6 @@ static LIST_HEAD(clocks); DEFINE_MUTEX(clocks_mutex); -/* old functions */ - -void inline s3c24xx_clk_enable(unsigned int clocks, unsigned int enable) -{ - unsigned long clkcon; - - clkcon = __raw_readl(S3C2410_CLKCON); - - if (enable) - clkcon |= clocks; - else - clkcon &= ~clocks; - - /* ensure none of the special function bits set */ - clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER); - - __raw_writel(clkcon, S3C2410_CLKCON); -} - /* enable and disable calls for use with the clk struct */ static int clk_null_enable(struct clk *clk, int enable) @@ -82,12 +63,6 @@ static int clk_null_enable(struct clk *c return 0; } -int s3c24xx_clkcon_enable(struct clk *clk, int enable) -{ - s3c24xx_clk_enable(clk->ctrlbit, enable); - return 0; -} - /* Clock API calls */ struct clk *clk_get(struct device *dev, const char *id) @@ -173,8 +148,11 @@ unsigned long clk_get_rate(struct clk *c if (clk->rate != 0) return clk->rate; - while (clk->parent != NULL && clk->rate == 0) - clk = clk->parent; + if (clk->get_rate != NULL) + return (clk->get_rate)(clk); + + if (clk->parent != NULL) + return clk_get_rate(clk->parent); return clk->rate; } @@ -233,31 +211,9 @@ EXPORT_SYMBOL(clk_set_rate); EXPORT_SYMBOL(clk_get_parent); EXPORT_SYMBOL(clk_set_parent); -/* base clock enable */ - -static int s3c24xx_upll_enable(struct clk *clk, int enable) -{ - unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); - unsigned long orig = clkslow; - - if (enable) - clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF; - else - clkslow |= S3C2410_CLKSLOW_UCLK_OFF; - - __raw_writel(clkslow, S3C2410_CLKSLOW); - - /* if we started the UPLL, then allow to settle */ - - if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF)) - udelay(200); - - return 0; -} - /* base clocks */ -static struct clk clk_xtal = { +struct clk clk_xtal = { .name = "xtal", .id = -1, .rate = 0, @@ -265,23 +221,27 @@ static struct clk clk_xtal = { .ctrlbit = 0, }; -static struct clk clk_upll = { +struct clk clk_mpll = { + .name = "mpll", + .id = -1, +}; + +struct clk clk_upll = { .name = "upll", .id = -1, .parent = NULL, - .enable = s3c24xx_upll_enable, .ctrlbit = 0, }; -static struct clk clk_f = { +struct clk clk_f = { .name = "fclk", .id = -1, .rate = 0, - .parent = NULL, + .parent = &clk_mpll, .ctrlbit = 0, }; -static struct clk clk_h = { +struct clk clk_h = { .name = "hclk", .id = -1, .rate = 0, @@ -289,7 +249,7 @@ static struct clk clk_h = { .ctrlbit = 0, }; -static struct clk clk_p = { +struct clk clk_p = { .name = "pclk", .id = -1, .rate = 0, @@ -308,14 +268,14 @@ struct clk clk_usb_bus = { static int s3c24xx_dclk_enable(struct clk *clk, int enable) { - unsigned long dclkcon = __raw_readl(S3C2410_DCLKCON); + unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON); if (enable) dclkcon |= clk->ctrlbit; else dclkcon &= ~clk->ctrlbit; - __raw_writel(dclkcon, S3C2410_DCLKCON); + __raw_writel(dclkcon, S3C24XX_DCLKCON); return 0; } @@ -334,7 +294,7 @@ static int s3c24xx_dclk_setparent(struct clk->parent = parent; - dclkcon = __raw_readl(S3C2410_DCLKCON); + dclkcon = __raw_readl(S3C24XX_DCLKCON); if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) { if (uclk) @@ -348,7 +308,7 @@ static int s3c24xx_dclk_setparent(struct dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK; } - __raw_writel(dclkcon, S3C2410_DCLKCON); + __raw_writel(dclkcon, S3C24XX_DCLKCON); return 0; } @@ -426,108 +386,6 @@ struct clk s3c24xx_uclk = { .id = -1, }; - -/* standard clock definitions */ - -static struct clk init_clocks[] = { - { - .name = "nand", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_NAND, - }, { - .name = "lcd", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_LCDC, - }, { - .name = "usb-host", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_USBH, - }, { - .name = "usb-device", - .id = -1, - .parent = &clk_h, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_USBD, - }, { - .name = "timers", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_PWMT, - }, { - .name = "sdi", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_SDI, - }, { - .name = "uart", - .id = 0, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART0, - }, { - .name = "uart", - .id = 1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART1, - }, { - .name = "uart", - .id = 2, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART2, - }, { - .name = "gpio", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_GPIO, - }, { - .name = "rtc", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_RTC, - }, { - .name = "adc", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_ADC, - }, { - .name = "i2c", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_IIC, - }, { - .name = "iis", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_IIS, - }, { - .name = "spi", - .id = -1, - .parent = &clk_p, - .enable = s3c24xx_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_SPI, - }, { - .name = "watchdog", - .id = -1, - .parent = &clk_p, - .ctrlbit = 0, - } -}; - /* initialise the clock system */ int s3c24xx_register_clock(struct clk *clk) @@ -537,14 +395,6 @@ int s3c24xx_register_clock(struct clk *c if (clk->enable == NULL) clk->enable = clk_null_enable; - /* if this is a standard clock, set the usage state */ - - if (clk->ctrlbit && clk->enable == s3c24xx_clkcon_enable) { - unsigned long clkcon = __raw_readl(S3C2410_CLKCON); - - clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0; - } - /* add to the list of available clocks */ mutex_lock(&clocks_mutex); @@ -561,44 +411,18 @@ int __init s3c24xx_setup_clocks(unsigned unsigned long hclk, unsigned long pclk) { - unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); - unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); - struct clk *clkp = init_clocks; - int ptr; - int ret; - - printk(KERN_INFO "S3C2410 Clocks, (c) 2004 Simtec Electronics\n"); + printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n"); /* initialise the main system clocks */ clk_xtal.rate = xtal; - clk_upll.rate = s3c2410_get_pll(upllcon, xtal); + clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal); + clk_mpll.rate = fclk; clk_h.rate = hclk; clk_p.rate = pclk; clk_f.rate = fclk; - /* We must be careful disabling the clocks we are not intending to - * be using at boot time, as subsytems such as the LCD which do - * their own DMA requests to the bus can cause the system to lockup - * if they where in the middle of requesting bus access. - * - * Disabling the LCD clock if the LCD is active is very dangerous, - * and therefore the bootloader should be careful to not enable - * the LCD clock if it is not needed. - */ - - mutex_lock(&clocks_mutex); - - s3c24xx_clk_enable(S3C2410_CLKCON_NAND, 0); - s3c24xx_clk_enable(S3C2410_CLKCON_USBH, 0); - s3c24xx_clk_enable(S3C2410_CLKCON_USBD, 0); - s3c24xx_clk_enable(S3C2410_CLKCON_ADC, 0); - s3c24xx_clk_enable(S3C2410_CLKCON_IIC, 0); - s3c24xx_clk_enable(S3C2410_CLKCON_SPI, 0); - - mutex_unlock(&clocks_mutex); - /* assume uart clocks are correctly setup */ /* register our clocks */ @@ -606,6 +430,9 @@ int __init s3c24xx_setup_clocks(unsigned if (s3c24xx_register_clock(&clk_xtal) < 0) printk(KERN_ERR "failed to register master xtal\n"); + if (s3c24xx_register_clock(&clk_mpll) < 0) + printk(KERN_ERR "failed to register mpll clock\n"); + if (s3c24xx_register_clock(&clk_upll) < 0) printk(KERN_ERR "failed to register upll clock\n"); @@ -618,27 +445,5 @@ int __init s3c24xx_setup_clocks(unsigned if (s3c24xx_register_clock(&clk_p) < 0) printk(KERN_ERR "failed to register cpu pclk\n"); - - if (s3c24xx_register_clock(&clk_usb_bus) < 0) - printk(KERN_ERR "failed to register usb bus clock\n"); - - /* register clocks from clock array */ - - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - } - - /* show the clock-slow value */ - - printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n", - print_mhz(xtal / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))), - (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast", - (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", - (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); - return 0; } diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h index 01bb458..7f0ea03 100644 --- a/arch/arm/mach-s3c2410/clock.h +++ b/arch/arm/mach-s3c2410/clock.h @@ -22,6 +22,7 @@ struct clk { int (*enable)(struct clk *, int enable); int (*set_rate)(struct clk *c, unsigned long rate); + unsigned long (*get_rate)(struct clk *c); unsigned long (*round_rate)(struct clk *c, unsigned long rate); int (*set_parent)(struct clk *c, struct clk *parent); }; @@ -36,6 +37,15 @@ extern struct clk s3c24xx_uclk; extern struct clk clk_usb_bus; +/* core clock support */ + +extern struct clk clk_f; +extern struct clk clk_h; +extern struct clk clk_p; +extern struct clk clk_mpll; +extern struct clk clk_upll; +extern struct clk clk_xtal; + /* exports for arch/arm/mach-s3c2410 * * Please DO NOT use these outside of arch/arm/mach-s3c2410 @@ -43,7 +53,8 @@ extern struct clk clk_usb_bus; extern struct mutex clocks_mutex; -extern int s3c24xx_clkcon_enable(struct clk *clk, int enable); +extern int s3c2410_clkcon_enable(struct clk *clk, int enable); + extern int s3c24xx_register_clock(struct clk *clk); extern int s3c24xx_setup_clocks(unsigned long xtal, diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/mach-s3c2410/common-smdk.c index c940890..a40eaa6 100644 --- a/arch/arm/mach-s3c2410/common-smdk.c +++ b/arch/arm/mach-s3c2410/common-smdk.c @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -41,6 +42,66 @@ #include "common-smdk.h" #include "devs.h" #include "pm.h" +/* LED devices */ + +static struct s3c24xx_led_platdata smdk_pdata_led4 = { + .gpio = S3C2410_GPF4, + .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, + .name = "led4", + .def_trigger = "timer", +}; + +static struct s3c24xx_led_platdata smdk_pdata_led5 = { + .gpio = S3C2410_GPF5, + .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, + .name = "led5", + .def_trigger = "nand-disk", +}; + +static struct s3c24xx_led_platdata smdk_pdata_led6 = { + .gpio = S3C2410_GPF6, + .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, + .name = "led6", +}; + +static struct s3c24xx_led_platdata smdk_pdata_led7 = { + .gpio = S3C2410_GPF7, + .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, + .name = "led7", +}; + +static struct platform_device smdk_led4 = { + .name = "s3c24xx_led", + .id = 0, + .dev = { + .platform_data = &smdk_pdata_led4, + }, +}; + +static struct platform_device smdk_led5 = { + .name = "s3c24xx_led", + .id = 1, + .dev = { + .platform_data = &smdk_pdata_led5, + }, +}; + +static struct platform_device smdk_led6 = { + .name = "s3c24xx_led", + .id = 2, + .dev = { + .platform_data = &smdk_pdata_led6, + }, +}; + +static struct platform_device smdk_led7 = { + .name = "s3c24xx_led", + .id = 3, + .dev = { + .platform_data = &smdk_pdata_led7, + }, +}; + /* NAND parititon from 2.4.18-swl5 */ static struct mtd_partition smdk_default_nand_part[] = { @@ -111,6 +172,10 @@ static struct s3c2410_platform_nand smdk static struct platform_device __initdata *smdk_devs[] = { &s3c_device_nand, + &smdk_led4, + &smdk_led5, + &smdk_led6, + &smdk_led7, }; void __init smdk_machine_init(void) diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c index 70c34fc..1c3c6ad 100644 --- a/arch/arm/mach-s3c2410/cpu.c +++ b/arch/arm/mach-s3c2410/cpu.c @@ -37,12 +37,17 @@ #include #include #include +#include #include "cpu.h" +#include "devs.h" #include "clock.h" #include "s3c2400.h" #include "s3c2410.h" +#include "s3c2412.h" +#include "s3c244x.h" #include "s3c2440.h" +#include "s3c2442.h" struct cpu_table { unsigned long idcode; @@ -58,7 +63,9 @@ struct cpu_table { static const char name_s3c2400[] = "S3C2400"; static const char name_s3c2410[] = "S3C2410"; +static const char name_s3c2412[] = "S3C2412"; static const char name_s3c2440[] = "S3C2440"; +static const char name_s3c2442[] = "S3C2442"; static const char name_s3c2410a[] = "S3C2410A"; static const char name_s3c2440a[] = "S3C2440A"; @@ -84,22 +91,40 @@ static struct cpu_table cpu_ids[] __init { .idcode = 0x32440000, .idmask = 0xffffffff, - .map_io = s3c2440_map_io, - .init_clocks = s3c2440_init_clocks, - .init_uarts = s3c2440_init_uarts, + .map_io = s3c244x_map_io, + .init_clocks = s3c244x_init_clocks, + .init_uarts = s3c244x_init_uarts, .init = s3c2440_init, .name = name_s3c2440 }, { .idcode = 0x32440001, .idmask = 0xffffffff, - .map_io = s3c2440_map_io, - .init_clocks = s3c2440_init_clocks, - .init_uarts = s3c2440_init_uarts, + .map_io = s3c244x_map_io, + .init_clocks = s3c244x_init_clocks, + .init_uarts = s3c244x_init_uarts, .init = s3c2440_init, .name = name_s3c2440a }, { + .idcode = 0x32440aaa, + .idmask = 0xffffffff, + .map_io = s3c244x_map_io, + .init_clocks = s3c244x_init_clocks, + .init_uarts = s3c244x_init_uarts, + .init = s3c2442_init, + .name = name_s3c2442 + }, + { + .idcode = 0x32412001, + .idmask = 0xffffffff, + .map_io = s3c2412_map_io, + .init_clocks = s3c2412_init_clocks, + .init_uarts = s3c2412_init_uarts, + .init = s3c2412_init, + .name = name_s3c2412, + }, + { .idcode = 0x0, /* S3C2400 doesn't have an idcode */ .idmask = 0xffffffff, .map_io = s3c2400_map_io, @@ -157,6 +182,24 @@ void s3c24xx_set_board(struct s3c24xx_bo static struct cpu_table *cpu; +static unsigned long s3c24xx_read_idcode_v5(void) +{ +#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) + return __raw_readl(S3C2412_GSTATUS1); +#else + return 1UL; /* don't look like an 2400 */ +#endif +} + +static unsigned long s3c24xx_read_idcode_v4(void) +{ +#ifndef CONFIG_CPU_S3C2400 + return __raw_readl(S3C2410_GSTATUS1); +#else + return 0UL; +#endif +} + void __init s3c24xx_init_io(struct map_desc *mach_desc, int size) { unsigned long idcode = 0x0; @@ -164,9 +207,11 @@ void __init s3c24xx_init_io(struct map_d /* initialise the io descriptors we need for initialisation */ iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); -#ifndef CONFIG_CPU_S3C2400 - idcode = __raw_readl(S3C2410_GSTATUS1); -#endif + if (cpu_architecture() >= CPU_ARCH_ARMv5) { + idcode = s3c24xx_read_idcode_v5(); + } else { + idcode = s3c24xx_read_idcode_v4(); + } cpu = s3c_lookup_cpu(idcode); @@ -175,13 +220,13 @@ #endif panic("Unknown S3C24XX CPU"); } + printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode); + if (cpu->map_io == NULL || cpu->init == NULL) { printk(KERN_ERR "CPU %s support not enabled\n", cpu->name); panic("Unsupported S3C24XX CPU"); } - printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode); - (cpu->map_io)(mach_desc, size); } @@ -208,6 +253,49 @@ void __init s3c24xx_init_clocks(int xtal (cpu->init_clocks)(xtal); } +/* uart management */ + +static int nr_uarts __initdata = 0; + +static struct s3c2410_uartcfg uart_cfgs[3]; + +/* s3c24xx_init_uartdevs + * + * copy the specified platform data and configuration into our central + * set of devices, before the data is thrown away after the init process. + * + * This also fills in the array passed to the serial driver for the + * early initialisation of the console. +*/ + +void __init s3c24xx_init_uartdevs(char *name, + struct s3c24xx_uart_resources *res, + struct s3c2410_uartcfg *cfg, int no) +{ + struct platform_device *platdev; + struct s3c2410_uartcfg *cfgptr = uart_cfgs; + struct s3c24xx_uart_resources *resp; + int uart; + + memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no); + + for (uart = 0; uart < no; uart++, cfg++, cfgptr++) { + platdev = s3c24xx_uart_src[cfgptr->hwport]; + + resp = res + cfgptr->hwport; + + s3c24xx_uart_devs[uart] = platdev; + + platdev->name = name; + platdev->resource = resp->resources; + platdev->num_resources = resp->nr_resources; + + platdev->dev.platform_data = cfgptr; + } + + nr_uarts = no; +} + void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no) { if (cpu == NULL) @@ -232,6 +320,10 @@ static int __init s3c_arch_init(void) if (ret != 0) return ret; + ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts); + if (ret != 0) + return ret; + if (board != NULL) { struct platform_device **ptr = board->devices; int i; diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h index fc10677..b0ed9d2 100644 --- a/arch/arm/mach-s3c2410/cpu.h +++ b/arch/arm/mach-s3c2410/cpu.h @@ -31,6 +31,8 @@ #endif #define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000) /* forward declaration */ +struct s3c24xx_uart_resources; +struct platform_device; struct s3c2410_uartcfg; struct map_desc; @@ -44,6 +46,10 @@ extern void s3c24xx_init_uarts(struct s3 extern void s3c24xx_init_clocks(int xtal); +extern void s3c24xx_init_uartdevs(char *name, + struct s3c24xx_uart_resources *res, + struct s3c2410_uartcfg *cfg, int no); + /* the board structure is used at first initialsation time * to get info such as the devices to register for this * board. This is done because platfrom_add_devices() cannot @@ -67,4 +73,7 @@ extern struct sys_timer s3c24xx_timer; /* system device classes */ +extern struct sysdev_class s3c2410_sysclass; +extern struct sysdev_class s3c2412_sysclass; extern struct sysdev_class s3c2440_sysclass; +extern struct sysdev_class s3c2442_sysclass; diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c index ca09ba5..ad3845e 100644 --- a/arch/arm/mach-s3c2410/devs.c +++ b/arch/arm/mach-s3c2410/devs.c @@ -38,10 +38,86 @@ #include #include #include "devs.h" +#include "cpu.h" /* Serial port registrations */ -struct platform_device *s3c24xx_uart_devs[3]; +static struct resource s3c2410_uart0_resource[] = { + [0] = { + .start = S3C2410_PA_UART0, + .end = S3C2410_PA_UART0 + 0x3fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX0, + .end = IRQ_S3CUART_ERR0, + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource s3c2410_uart1_resource[] = { + [0] = { + .start = S3C2410_PA_UART1, + .end = S3C2410_PA_UART1 + 0x3fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX1, + .end = IRQ_S3CUART_ERR1, + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource s3c2410_uart2_resource[] = { + [0] = { + .start = S3C2410_PA_UART2, + .end = S3C2410_PA_UART2 + 0x3fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX2, + .end = IRQ_S3CUART_ERR2, + .flags = IORESOURCE_IRQ, + } +}; + +struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = { + [0] = { + .resources = s3c2410_uart0_resource, + .nr_resources = ARRAY_SIZE(s3c2410_uart0_resource), + }, + [1] = { + .resources = s3c2410_uart1_resource, + .nr_resources = ARRAY_SIZE(s3c2410_uart1_resource), + }, + [2] = { + .resources = s3c2410_uart2_resource, + .nr_resources = ARRAY_SIZE(s3c2410_uart2_resource), + }, +}; + +/* yart devices */ + +static struct platform_device s3c24xx_uart_device0 = { + .id = 0, +}; + +static struct platform_device s3c24xx_uart_device1 = { + .id = 1, +}; + +static struct platform_device s3c24xx_uart_device2 = { + .id = 2, +}; + +struct platform_device *s3c24xx_uart_src[3] = { + &s3c24xx_uart_device0, + &s3c24xx_uart_device1, + &s3c24xx_uart_device2, +}; + +struct platform_device *s3c24xx_uart_devs[3] = { +}; /* USB Host Controller */ diff --git a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h index 52c4bab..fa124ed 100644 --- a/arch/arm/mach-s3c2410/devs.h +++ b/arch/arm/mach-s3c2410/devs.h @@ -17,7 +17,15 @@ #include #include +struct s3c24xx_uart_resources { + struct resource *resources; + unsigned long nr_resources; +}; + +extern struct s3c24xx_uart_resources s3c2410_uart_resources[]; + extern struct platform_device *s3c24xx_uart_devs[]; +extern struct platform_device *s3c24xx_uart_src[]; extern struct platform_device s3c_device_usb; extern struct platform_device s3c_device_lcd; diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c index 66d8c06..6822dc7 100644 --- a/arch/arm/mach-s3c2410/irq.c +++ b/arch/arm/mach-s3c2410/irq.c @@ -191,13 +191,9 @@ static struct irqchip s3c_irq_chip = { .ack = s3c_irq_ack, .mask = s3c_irq_mask, .unmask = s3c_irq_unmask, - .set_wake = s3c_irq_wake + .set_wake = s3c_irq_wake }; -/* S3C2410_EINTMASK - * S3C2410_EINTPEND - */ - static void s3c_irqext_mask(unsigned int irqno) { @@ -205,9 +201,9 @@ s3c_irqext_mask(unsigned int irqno) irqno -= EXTINT_OFF; - mask = __raw_readl(S3C2410_EINTMASK); + mask = __raw_readl(S3C24XX_EINTMASK); mask |= ( 1UL << irqno); - __raw_writel(mask, S3C2410_EINTMASK); + __raw_writel(mask, S3C24XX_EINTMASK); if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) { /* check to see if all need masking */ @@ -232,11 +228,11 @@ s3c_irqext_ack(unsigned int irqno) bit = 1UL << (irqno - EXTINT_OFF); - mask = __raw_readl(S3C2410_EINTMASK); + mask = __raw_readl(S3C24XX_EINTMASK); - __raw_writel(bit, S3C2410_EINTPEND); + __raw_writel(bit, S3C24XX_EINTPEND); - req = __raw_readl(S3C2410_EINTPEND); + req = __raw_readl(S3C24XX_EINTPEND); req &= ~mask; /* not sure if we should be acking the parent irq... */ @@ -257,9 +253,9 @@ s3c_irqext_unmask(unsigned int irqno) irqno -= EXTINT_OFF; - mask = __raw_readl(S3C2410_EINTMASK); + mask = __raw_readl(S3C24XX_EINTMASK); mask &= ~( 1UL << irqno); - __raw_writel(mask, S3C2410_EINTMASK); + __raw_writel(mask, S3C24XX_EINTMASK); s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23); } @@ -275,28 +271,28 @@ s3c_irqext_type(unsigned int irq, unsign if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3)) { gpcon_reg = S3C2410_GPFCON; - extint_reg = S3C2410_EXTINT0; + extint_reg = S3C24XX_EXTINT0; gpcon_offset = (irq - IRQ_EINT0) * 2; extint_offset = (irq - IRQ_EINT0) * 4; } else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7)) { gpcon_reg = S3C2410_GPFCON; - extint_reg = S3C2410_EXTINT0; + extint_reg = S3C24XX_EXTINT0; gpcon_offset = (irq - (EXTINT_OFF)) * 2; extint_offset = (irq - (EXTINT_OFF)) * 4; } else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15)) { gpcon_reg = S3C2410_GPGCON; - extint_reg = S3C2410_EXTINT1; + extint_reg = S3C24XX_EXTINT1; gpcon_offset = (irq - IRQ_EINT8) * 2; extint_offset = (irq - IRQ_EINT8) * 4; } else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23)) { gpcon_reg = S3C2410_GPGCON; - extint_reg = S3C2410_EXTINT2; + extint_reg = S3C24XX_EXTINT2; gpcon_offset = (irq - IRQ_EINT8) * 2; extint_offset = (irq - IRQ_EINT16) * 4; } else @@ -572,6 +568,23 @@ s3c_irq_demux_uart2(unsigned int irq, s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs); } +static void +s3c_irq_demux_extint(unsigned int irq, + struct irqdesc *desc, + struct pt_regs *regs) +{ + unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); + unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); + + eintpnd &= ~eintmsk; + + if (eintpnd) { + irq = fls(eintpnd); + irq += (IRQ_EINT4 - (4 + 1)); + + desc_handle_irq(irq, irq_desc + irq, regs); + } +} /* s3c24xx_init_irq * @@ -591,12 +604,12 @@ void __init s3c24xx_init_irq(void) last = 0; for (i = 0; i < 4; i++) { - pend = __raw_readl(S3C2410_EINTPEND); + pend = __raw_readl(S3C24XX_EINTPEND); if (pend == 0 || pend == last) break; - __raw_writel(pend, S3C2410_EINTPEND); + __raw_writel(pend, S3C24XX_EINTPEND); printk("irq: clearing pending ext status %08x\n", (int)pend); last = pend; } @@ -630,12 +643,14 @@ void __init s3c24xx_init_irq(void) irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); - for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) { + for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) { /* set all the s3c2410 internal irqs */ switch (irqno) { /* deal with the special IRQs (cascaded) */ + case IRQ_EINT4t7: + case IRQ_EINT8t23: case IRQ_UART0: case IRQ_UART1: case IRQ_UART2: @@ -659,12 +674,14 @@ void __init s3c24xx_init_irq(void) /* setup the cascade irq handlers */ + set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint); + set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint); + set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1); set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2); set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc); - /* external interrupts */ for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c index cc97fbf..4a92d6f 100644 --- a/arch/arm/mach-s3c2410/mach-anubis.c +++ b/arch/arm/mach-s3c2410/mach-anubis.c @@ -131,7 +131,7 @@ static struct s3c24xx_uart_clksrc anubis }; -static struct s3c2410_uartcfg anubis_uartcfgs[] = { +static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, @@ -239,6 +239,54 @@ static struct s3c2410_platform_nand anub .select_chip = anubis_nand_select, }; +/* IDE channels */ + +static struct resource anubis_ide0_resource[] = { + { + .start = S3C2410_CS3, + .end = S3C2410_CS3 + (8*32) - 1, + .flags = IORESOURCE_MEM, + }, { + .start = S3C2410_CS3 + (1<<26), + .end = S3C2410_CS3 + (1<<26) + (8*32) - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_IDE0, + .end = IRQ_IDE0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device anubis_device_ide0 = { + .name = "simtec-ide", + .id = 0, + .num_resources = ARRAY_SIZE(anubis_ide0_resource), + .resource = anubis_ide0_resource, +}; + +static struct resource anubis_ide1_resource[] = { + { + .start = S3C2410_CS4, + .end = S3C2410_CS4 + (8*32) - 1, + .flags = IORESOURCE_MEM, + }, { + .start = S3C2410_CS4 + (1<<26), + .end = S3C2410_CS4 + (1<<26) + (8*32) - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_IDE0, + .end = IRQ_IDE0, + .flags = IORESOURCE_IRQ, + }, +}; + + +static struct platform_device anubis_device_ide1 = { + .name = "simtec-ide", + .id = 1, + .num_resources = ARRAY_SIZE(anubis_ide1_resource), + .resource = anubis_ide1_resource, +}; /* Standard Anubis devices */ @@ -249,6 +297,8 @@ static struct platform_device *anubis_de &s3c_device_i2c, &s3c_device_rtc, &s3c_device_nand, + &anubis_device_ide0, + &anubis_device_ide1, }; static struct clk *anubis_clocks[] = { diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 995bb8a..947234d 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -208,7 +208,7 @@ static struct s3c24xx_uart_clksrc bast_s }; -static struct s3c2410_uartcfg bast_uartcfgs[] = { +static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 646a3a5..aec431b 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -72,7 +72,7 @@ #define UCON S3C2410_UCON_DEFAULT | S3C2 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE -static struct s3c2410_uartcfg h1940_uartcfgs[] = { +static struct s3c2410_uartcfg h1940_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c index 07d0950..065a1d4 100644 --- a/arch/arm/mach-s3c2410/mach-nexcoder.c +++ b/arch/arm/mach-s3c2410/mach-nexcoder.c @@ -51,7 +51,7 @@ #define UCON S3C2410_UCON_DEFAULT #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE -static struct s3c2410_uartcfg nexcoder_uartcfgs[] = { +static struct s3c2410_uartcfg nexcoder_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2410/mach-osiris.c index ae07875..858fd03 100644 --- a/arch/arm/mach-s3c2410/mach-osiris.c +++ b/arch/arm/mach-s3c2410/mach-osiris.c @@ -95,8 +95,7 @@ static struct s3c24xx_uart_clksrc osiris } }; - -static struct s3c2410_uartcfg osiris_uartcfgs[] = { +static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, @@ -107,7 +106,7 @@ static struct s3c2410_uartcfg osiris_uar .clocks_size = ARRAY_SIZE(osiris_serial_clocks) }, [1] = { - .hwport = 2, + .hwport = 1, .flags = 0, .ucon = UCON, .ulcon = ULCON, diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c index b39daed..c71673f 100644 --- a/arch/arm/mach-s3c2410/mach-otom.c +++ b/arch/arm/mach-s3c2410/mach-otom.c @@ -45,7 +45,7 @@ #define UCON S3C2410_UCON_DEFAULT #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE -static struct s3c2410_uartcfg otom11_uartcfgs[] = { +static struct s3c2410_uartcfg otom11_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c index 2db932d..25f7e9f 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c @@ -65,7 +65,7 @@ #define UCON S3C2410_UCON_DEFAULT #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE -static struct s3c2410_uartcfg smdk2410_uartcfgs[] = { +static struct s3c2410_uartcfg smdk2410_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2410/mach-smdk2413.c new file mode 100644 index 0000000..b7ef7d3 --- /dev/null +++ b/arch/arm/mach-s3c2410/mach-smdk2413.c @@ -0,0 +1,126 @@ +/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * Thanks to Dimity Andric (TomTom) and Steven Ryu (Samsung) for the + * loans of SMDK2413 to work with. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +//#include +#include +#include +#include + +#include +#include + +#include "s3c2410.h" +#include "s3c2412.h" +#include "clock.h" +#include "devs.h" +#include "cpu.h" + +#include "common-smdk.h" + +static struct map_desc smdk2413_iodesc[] __initdata = { +}; + +static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, + /* IR port */ + [2] = { + .hwport = 2, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x43, + .ufcon = 0x51, + } +}; + +static struct platform_device *smdk2413_devices[] __initdata = { + &s3c_device_usb, + //&s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_i2c, + &s3c_device_iis, +}; + +static struct s3c24xx_board smdk2413_board __initdata = { + .devices = smdk2413_devices, + .devices_count = ARRAY_SIZE(smdk2413_devices) +}; + +static void __init smdk2413_fixup(struct machine_desc *desc, + struct tag *tags, char **cmdline, + struct meminfo *mi) +{ + if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) { + mi->nr_banks=1; + mi->bank[0].start = 0x30000000; + mi->bank[0].size = SZ_64M; + mi->bank[0].node = 0; + } +} + +static void __init smdk2413_map_io(void) +{ + s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc)); + s3c24xx_init_clocks(12000000); + s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs)); + s3c24xx_set_board(&smdk2413_board); +} + +static void __init smdk2413_machine_init(void) +{ + smdk_machine_init(); +} + +MACHINE_START(S3C2413, "SMDK2413") + /* Maintainer: Ben Dooks */ + .phys_io = S3C2410_PA_UART, + .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, + .boot_params = S3C2410_SDRAM_PA + 0x100, + + .fixup = smdk2413_fixup, + .init_irq = s3c24xx_init_irq, + .map_io = smdk2413_map_io, + .init_machine = smdk2413_machine_init, + .timer = &s3c24xx_timer, +MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c index 5fffd1d..d661c6b 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2440.c +++ b/arch/arm/mach-s3c2410/mach-smdk2440.c @@ -86,7 +86,7 @@ #define UCON S3C2410_UCON_DEFAULT | S3C2 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE -static struct s3c2410_uartcfg smdk2440_uartcfgs[] = { +static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 785fc9c..d18efb2 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -166,7 +166,7 @@ static struct s3c24xx_uart_clksrc vr1000 } }; -static struct s3c2410_uartcfg vr1000_uartcfgs[] = { +static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/mach-s3c2410/pm-simtec.c index 4c7ccef..7b24456 100644 --- a/arch/arm/mach-s3c2410/pm-simtec.c +++ b/arch/arm/mach-s3c2410/pm-simtec.c @@ -48,7 +48,8 @@ static __init int pm_simtec_init(void) /* check which machine we are running on */ - if (!machine_is_bast() && !machine_is_vr1000() && !machine_is_anubis()) + if (!machine_is_bast() && !machine_is_vr1000() && + !machine_is_anubis() && !machine_is_osiris()) return 0; printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n"); diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c index fe57d96..43e9a55 100644 --- a/arch/arm/mach-s3c2410/pm.c +++ b/arch/arm/mach-s3c2410/pm.c @@ -58,7 +58,11 @@ unsigned long s3c_pm_flags; /* cache functions from arch/arm/mm/proc-arm920.S */ +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH extern void arm920_flush_kern_cache_all(void); +#else +static void arm920_flush_kern_cache_all(void) { } +#endif #define PFX "s3c24xx-pm: " diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c new file mode 100644 index 0000000..9971866 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2410-clock.c @@ -0,0 +1,271 @@ +/* linux/arch/arm/mach-s3c2410/clock.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * S3C2410,S3C2440,S3C2442 Clock control support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "clock.h" +#include "cpu.h" + +int s3c2410_clkcon_enable(struct clk *clk, int enable) +{ + unsigned int clocks = clk->ctrlbit; + unsigned long clkcon; + + clkcon = __raw_readl(S3C2410_CLKCON); + + if (enable) + clkcon |= clocks; + else + clkcon &= ~clocks; + + /* ensure none of the special function bits set */ + clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER); + + __raw_writel(clkcon, S3C2410_CLKCON); + + return 0; +} + +static int s3c2410_upll_enable(struct clk *clk, int enable) +{ + unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); + unsigned long orig = clkslow; + + if (enable) + clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF; + else + clkslow |= S3C2410_CLKSLOW_UCLK_OFF; + + __raw_writel(clkslow, S3C2410_CLKSLOW); + + /* if we started the UPLL, then allow to settle */ + + if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF)) + udelay(200); + + return 0; +} + +/* standard clock definitions */ + +static struct clk init_clocks_disable[] = { + { + .name = "nand", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_NAND, + }, { + .name = "sdi", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_SDI, + }, { + .name = "adc", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_ADC, + }, { + .name = "i2c", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_IIC, + }, { + .name = "iis", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_IIS, + }, { + .name = "spi", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_SPI, + } +}; + +static struct clk init_clocks[] = { + { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_LCDC, + }, { + .name = "gpio", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_GPIO, + }, { + .name = "usb-host", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_USBH, + }, { + .name = "usb-device", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_USBD, + }, { + .name = "timers", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_PWMT, + }, { + .name = "uart", + .id = 0, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART0, + }, { + .name = "uart", + .id = 1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART1, + }, { + .name = "uart", + .id = 2, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART2, + }, { + .name = "rtc", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_RTC, + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_p, + .ctrlbit = 0, + }, { + .name = "usb-bus-host", + .id = -1, + .parent = &clk_usb_bus, + }, { + .name = "usb-bus-gadget", + .id = -1, + .parent = &clk_usb_bus, + }, +}; + +/* s3c2410_baseclk_add() + * + * Add all the clocks used by the s3c2410 or compatible CPUs + * such as the S3C2440 and S3C2442. + * + * We cannot use a system device as we are needed before any + * of the init-calls that initialise the devices are actually + * done. +*/ + +int __init s3c2410_baseclk_add(void) +{ + unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); + unsigned long clkcon = __raw_readl(S3C2410_CLKCON); + struct clk *clkp; + struct clk *xtal; + int ret; + int ptr; + + clk_upll.enable = s3c2410_upll_enable; + + if (s3c24xx_register_clock(&clk_usb_bus) < 0) + printk(KERN_ERR "failed to register usb bus clock\n"); + + /* register clocks from clock array */ + + clkp = init_clocks; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { + /* ensure that we note the clock state */ + + clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0; + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + /* We must be careful disabling the clocks we are not intending to + * be using at boot time, as subsytems such as the LCD which do + * their own DMA requests to the bus can cause the system to lockup + * if they where in the middle of requesting bus access. + * + * Disabling the LCD clock if the LCD is active is very dangerous, + * and therefore the bootloader should be careful to not enable + * the LCD clock if it is not needed. + */ + + /* install (and disable) the clocks we do not need immediately */ + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + + s3c2410_clkcon_enable(clkp, 0); + } + + /* show the clock-slow value */ + + xtal = clk_get(NULL, "xtal"); + + printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n", + print_mhz(clk_get_rate(xtal) / + ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))), + (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast", + (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", + (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); + + return 0; +} diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c index d5e1cae..471a714 100644 --- a/arch/arm/mach-s3c2410/s3c2410-gpio.c +++ b/arch/arm/mach-s3c2410/s3c2410-gpio.c @@ -18,9 +18,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Changelog - * 15-Jan-2006 LCVR Splitted from gpio.c */ #include @@ -38,7 +35,7 @@ #include int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on, unsigned int config) { - void __iomem *reg = S3C2410_EINFLT0; + void __iomem *reg = S3C24XX_EINFLT0; unsigned long flags; unsigned long val; @@ -47,7 +44,7 @@ int s3c2410_gpio_irqfilter(unsigned int config &= 0xff; - pin -= S3C2410_GPG8_EINT16; + pin -= S3C2410_GPG8; reg += pin & ~3; local_irq_save(flags); @@ -61,10 +58,10 @@ int s3c2410_gpio_irqfilter(unsigned int /* update filter enable */ - val = __raw_readl(S3C2410_EXTINT2); + val = __raw_readl(S3C24XX_EXTINT2); val &= ~(1 << ((pin * 4) + 3)); val |= on << ((pin * 4) + 3); - __raw_writel(val, S3C2410_EXTINT2); + __raw_writel(val, S3C24XX_EXTINT2); local_irq_restore(flags); @@ -75,7 +72,7 @@ EXPORT_SYMBOL(s3c2410_gpio_irqfilter); int s3c2410_gpio_getirq(unsigned int pin) { - if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23) + if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15) return -1; /* not valid interrupts */ if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7) diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index 0a2013a..a110cff 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -27,6 +27,7 @@ #include #include #include #include +#include #include #include @@ -42,6 +43,7 @@ #include #include "s3c2410.h" #include "cpu.h" +#include "devs.h" #include "clock.h" /* Initial IO mappings */ @@ -55,93 +57,13 @@ static struct map_desc s3c2410_iodesc[] IODESC_ENT(WATCHDOG), }; -static struct resource s3c_uart0_resource[] = { - [0] = { - .start = S3C2410_PA_UART0, - .end = S3C2410_PA_UART0 + 0x3fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_S3CUART_RX0, - .end = IRQ_S3CUART_ERR0, - .flags = IORESOURCE_IRQ, - } - -}; - -static struct resource s3c_uart1_resource[] = { - [0] = { - .start = S3C2410_PA_UART1, - .end = S3C2410_PA_UART1 + 0x3fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_S3CUART_RX1, - .end = IRQ_S3CUART_ERR1, - .flags = IORESOURCE_IRQ, - } -}; - -static struct resource s3c_uart2_resource[] = { - [0] = { - .start = S3C2410_PA_UART2, - .end = S3C2410_PA_UART2 + 0x3fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_S3CUART_RX2, - .end = IRQ_S3CUART_ERR2, - .flags = IORESOURCE_IRQ, - } -}; - /* our uart devices */ -static struct platform_device s3c_uart0 = { - .name = "s3c2410-uart", - .id = 0, - .num_resources = ARRAY_SIZE(s3c_uart0_resource), - .resource = s3c_uart0_resource, -}; - - -static struct platform_device s3c_uart1 = { - .name = "s3c2410-uart", - .id = 1, - .num_resources = ARRAY_SIZE(s3c_uart1_resource), - .resource = s3c_uart1_resource, -}; - -static struct platform_device s3c_uart2 = { - .name = "s3c2410-uart", - .id = 2, - .num_resources = ARRAY_SIZE(s3c_uart2_resource), - .resource = s3c_uart2_resource, -}; - -static struct platform_device *uart_devices[] __initdata = { - &s3c_uart0, - &s3c_uart1, - &s3c_uart2 -}; - -static int s3c2410_uart_count = 0; - /* uart registration process */ void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no) { - struct platform_device *platdev; - int uart; - - for (uart = 0; uart < no; uart++, cfg++) { - platdev = uart_devices[cfg->hwport]; - - s3c24xx_uart_devs[uart] = platdev; - platdev->dev.platform_data = cfg; - } - - s3c2410_uart_count = uart; + s3c24xx_init_uartdevs("s3c2410-uart", s3c2410_uart_resources, cfg, no); } /* s3c2410_map_io @@ -187,11 +109,33 @@ void __init s3c2410_init_clocks(int xtal */ s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); + s3c2410_baseclk_add(); } +struct sysdev_class s3c2410_sysclass = { + set_kset_name("s3c2410-core"), +}; + +static struct sys_device s3c2410_sysdev = { + .cls = &s3c2410_sysclass, +}; + +/* need to register class before we actually register the device, and + * we also need to ensure that it has been initialised before any of the + * drivers even try to use it (even if not on an s3c2440 based system) + * as a driver which may support both 2410 and 2440 may try and use it. +*/ + +static int __init s3c2410_core_init(void) +{ + return sysdev_class_register(&s3c2410_sysclass); +} + +core_initcall(s3c2410_core_init); + int __init s3c2410_init(void) { printk("S3C2410: Initialising architecture\n"); - return platform_add_devices(s3c24xx_uart_devs, s3c2410_uart_count); + return sysdev_register(&s3c2410_sysdev); } diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h index 4d5312a..73f1a24 100644 --- a/arch/arm/mach-s3c2410/s3c2410.h +++ b/arch/arm/mach-s3c2410/s3c2410.h @@ -29,6 +29,8 @@ extern void s3c2410_init_uarts(struct s3 extern void s3c2410_init_clocks(int xtal); +extern int s3c2410_baseclk_add(void); + #else #define s3c2410_init_clocks NULL #define s3c2410_init_uarts NULL diff --git a/arch/arm/mach-s3c2410/s3c2412-clock.c b/arch/arm/mach-s3c2410/s3c2412-clock.c new file mode 100644 index 0000000..c95ed3e --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2412-clock.c @@ -0,0 +1,711 @@ +/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * S3C2412,S3C2413 Clock control support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "clock.h" +#include "cpu.h" + +/* We currently have to assume that the system is running + * from the XTPll input, and that all ***REFCLKs are being + * fed from it, as we cannot read the state of OM[4] from + * software. + * + * It would be possible for each board initialisation to + * set the correct muxing at initialisation +*/ + +int s3c2412_clkcon_enable(struct clk *clk, int enable) +{ + unsigned int clocks = clk->ctrlbit; + unsigned long clkcon; + + clkcon = __raw_readl(S3C2410_CLKCON); + + if (enable) + clkcon |= clocks; + else + clkcon &= ~clocks; + + __raw_writel(clkcon, S3C2410_CLKCON); + + return 0; +} + +static int s3c2412_upll_enable(struct clk *clk, int enable) +{ + unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); + unsigned long orig = upllcon; + + if (!enable) + upllcon |= S3C2412_PLLCON_OFF; + else + upllcon &= ~S3C2412_PLLCON_OFF; + + __raw_writel(upllcon, S3C2410_UPLLCON); + + /* allow ~150uS for the PLL to settle and lock */ + + if (enable && (orig & S3C2412_PLLCON_OFF)) + udelay(150); + + return 0; +} + +/* clock selections */ + +/* CPU EXTCLK input */ +static struct clk clk_ext = { + .name = "extclk", + .id = -1, +}; + +static struct clk clk_erefclk = { + .name = "erefclk", + .id = -1, +}; + +static struct clk clk_urefclk = { + .name = "urefclk", + .id = -1, +}; + +static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_urefclk) + clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL; + else if (parent == &clk_upll) + clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} + +static struct clk clk_usysclk = { + .name = "usysclk", + .id = -1, + .parent = &clk_xtal, + .set_parent = s3c2412_setparent_usysclk, +}; + +static struct clk clk_mrefclk = { + .name = "mrefclk", + .parent = &clk_xtal, + .id = -1, +}; + +static struct clk clk_mdivclk = { + .name = "mdivclk", + .parent = &clk_xtal, + .id = -1, +}; + +static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_usysclk) + clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK; + else if (parent == &clk_h) + clksrc |= S3C2412_CLKSRC_USBCLK_HCLK; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} + +static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk, + unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + int div; + + if (rate > parent_rate) + return parent_rate; + + div = parent_rate / rate; + if (div > 2) + div = 2; + + return parent_rate / div; +} + +static unsigned long s3c2412_getrate_usbsrc(struct clk *clk) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long div = __raw_readl(S3C2410_CLKDIVN); + + return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1); +} + +static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); + + rate = s3c2412_roundrate_usbsrc(clk, rate); + + if ((parent_rate / rate) == 2) + clkdivn |= S3C2412_CLKDIVN_USB48DIV; + else + clkdivn &= ~S3C2412_CLKDIVN_USB48DIV; + + __raw_writel(clkdivn, S3C2410_CLKDIVN); + return 0; +} + +static struct clk clk_usbsrc = { + .name = "usbsrc", + .id = -1, + .get_rate = s3c2412_getrate_usbsrc, + .set_rate = s3c2412_setrate_usbsrc, + .round_rate = s3c2412_roundrate_usbsrc, + .set_parent = s3c2412_setparent_usbsrc, +}; + +static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_mdivclk) + clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL; + else if (parent == &clk_upll) + clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} + +static struct clk clk_msysclk = { + .name = "msysclk", + .id = -1, + .set_parent = s3c2412_setparent_msysclk, +}; + +/* these next clocks have an divider immediately after them, + * so we can register them with their divider and leave out the + * intermediate clock stage +*/ +static unsigned long s3c2412_roundrate_clksrc(struct clk *clk, + unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + int div; + + if (rate > parent_rate) + return parent_rate; + + /* note, we remove the +/- 1 calculations as they cancel out */ + + div = (rate / parent_rate); + + if (div < 1) + div = 1; + else if (div > 16) + div = 16; + + return parent_rate / div; +} + +static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_erefclk) + clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL; + else if (parent == &clk_mpll) + clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} + +static unsigned long s3c2412_getrate_uart(struct clk *clk) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long div = __raw_readl(S3C2410_CLKDIVN); + + div &= S3C2412_CLKDIVN_UARTDIV_MASK; + div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT; + + return parent_rate / (div + 1); +} + +static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); + + rate = s3c2412_roundrate_clksrc(clk, rate); + + clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK; + clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT; + + __raw_writel(clkdivn, S3C2410_CLKDIVN); + return 0; +} + +static struct clk clk_uart = { + .name = "uartclk", + .id = -1, + .get_rate = s3c2412_getrate_uart, + .set_rate = s3c2412_setrate_uart, + .set_parent = s3c2412_setparent_uart, + .round_rate = s3c2412_roundrate_clksrc, +}; + +static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_erefclk) + clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL; + else if (parent == &clk_mpll) + clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} + +static unsigned long s3c2412_getrate_i2s(struct clk *clk) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long div = __raw_readl(S3C2410_CLKDIVN); + + div &= S3C2412_CLKDIVN_I2SDIV_MASK; + div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT; + + return parent_rate / (div + 1); +} + +static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); + + rate = s3c2412_roundrate_clksrc(clk, rate); + + clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK; + clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT; + + __raw_writel(clkdivn, S3C2410_CLKDIVN); + return 0; +} + +static struct clk clk_i2s = { + .name = "i2sclk", + .id = -1, + .get_rate = s3c2412_getrate_i2s, + .set_rate = s3c2412_setrate_i2s, + .set_parent = s3c2412_setparent_i2s, + .round_rate = s3c2412_roundrate_clksrc, +}; + +static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_usysclk) + clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK; + else if (parent == &clk_h) + clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} +static unsigned long s3c2412_getrate_cam(struct clk *clk) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long div = __raw_readl(S3C2410_CLKDIVN); + + div &= S3C2412_CLKDIVN_CAMDIV_MASK; + div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT; + + return parent_rate / (div + 1); +} + +static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); + + rate = s3c2412_roundrate_clksrc(clk, rate); + + clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK; + clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT; + + __raw_writel(clkdivn, S3C2410_CLKDIVN); + return 0; +} + +static struct clk clk_cam = { + .name = "camif-upll", /* same as 2440 name */ + .id = -1, + .get_rate = s3c2412_getrate_cam, + .set_rate = s3c2412_setrate_cam, + .set_parent = s3c2412_setparent_cam, + .round_rate = s3c2412_roundrate_clksrc, +}; + +/* standard clock definitions */ + +static struct clk init_clocks_disable[] = { + { + .name = "nand", + .id = -1, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_NAND, + }, { + .name = "sdi", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_SDI, + }, { + .name = "adc", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_ADC, + }, { + .name = "i2c", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_IIC, + }, { + .name = "iis", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_IIS, + }, { + .name = "spi", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_SPI, + } +}; + +static struct clk init_clocks[] = { + { + .name = "dma", + .id = 0, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_DMA0, + }, { + .name = "dma", + .id = 1, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_DMA1, + }, { + .name = "dma", + .id = 2, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_DMA2, + }, { + .name = "dma", + .id = 3, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_DMA3, + }, { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_LCDC, + }, { + .name = "gpio", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_GPIO, + }, { + .name = "usb-host", + .id = -1, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_USBH, + }, { + .name = "usb-device", + .id = -1, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_USBD, + }, { + .name = "timers", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_PWMT, + }, { + .name = "uart", + .id = 0, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_UART0, + }, { + .name = "uart", + .id = 1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_UART1, + }, { + .name = "uart", + .id = 2, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_UART2, + }, { + .name = "rtc", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_RTC, + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_p, + .ctrlbit = 0, + }, { + .name = "usb-bus-gadget", + .id = -1, + .parent = &clk_usb_bus, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_USB_DEV48, + }, { + .name = "usb-bus-host", + .id = -1, + .parent = &clk_usb_bus, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_USB_HOST48, + } +}; + +/* clocks to add where we need to check their parentage */ + +struct clk_init { + struct clk *clk; + unsigned int bit; + struct clk *src_0; + struct clk *src_1; +}; + +struct clk_init clks_src[] __initdata = { + { + .clk = &clk_usysclk, + .bit = S3C2412_CLKSRC_USBCLK_HCLK, + .src_0 = &clk_urefclk, + .src_1 = &clk_upll, + }, { + .clk = &clk_i2s, + .bit = S3C2412_CLKSRC_I2SCLK_MPLL, + .src_0 = &clk_erefclk, + .src_1 = &clk_mpll, + }, { + .clk = &clk_cam, + .bit = S3C2412_CLKSRC_CAMCLK_HCLK, + .src_0 = &clk_usysclk, + .src_1 = &clk_h, + }, { + .clk = &clk_msysclk, + .bit = S3C2412_CLKSRC_MSYSCLK_MPLL, + .src_0 = &clk_mdivclk, + .src_1 = &clk_mpll, + }, { + .clk = &clk_uart, + .bit = S3C2412_CLKSRC_UARTCLK_MPLL, + .src_0 = &clk_erefclk, + .src_1 = &clk_mpll, + }, { + .clk = &clk_usbsrc, + .bit = S3C2412_CLKSRC_USBCLK_HCLK, + .src_0 = &clk_usysclk, + .src_1 = &clk_h, + }, +}; + +/* s3c2412_clk_initparents + * + * Initialise the parents for the clocks that we get at start-time +*/ + +static void __init s3c2412_clk_initparents(void) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + struct clk_init *cip = clks_src; + struct clk *src; + int ptr; + int ret; + + for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) { + ret = s3c24xx_register_clock(cip->clk); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + cip->clk->name, ret); + } + + src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0; + + printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name); + clk_set_parent(cip->clk, src); + } +} + +/* clocks to add straight away */ + +struct clk *clks[] __initdata = { + &clk_ext, + &clk_usb_bus, + &clk_erefclk, + &clk_urefclk, + &clk_mrefclk, +}; + +int __init s3c2412_baseclk_add(void) +{ + unsigned long clkcon = __raw_readl(S3C2410_CLKCON); + struct clk *clkp; + int ret; + int ptr; + + clk_upll.enable = s3c2412_upll_enable; + clk_usb_bus.parent = &clk_usbsrc; + clk_usb_bus.rate = 0x0; + + s3c2412_clk_initparents(); + + for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { + clkp = clks[ptr]; + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + /* ensure usb bus clock is within correct rate of 48MHz */ + + if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) { + printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n"); + + /* for the moment, let's use the UPLL, and see if we can + * get 48MHz */ + + clk_set_parent(&clk_usysclk, &clk_upll); + clk_set_parent(&clk_usbsrc, &clk_usysclk); + clk_set_rate(&clk_usbsrc, 48*1000*1000); + } + + printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", + (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on", + print_mhz(clk_get_rate(&clk_upll)), + print_mhz(clk_get_rate(&clk_usb_bus))); + + /* register clocks from clock array */ + + clkp = init_clocks; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { + /* ensure that we note the clock state */ + + clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0; + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + /* We must be careful disabling the clocks we are not intending to + * be using at boot time, as subsytems such as the LCD which do + * their own DMA requests to the bus can cause the system to lockup + * if they where in the middle of requesting bus access. + * + * Disabling the LCD clock if the LCD is active is very dangerous, + * and therefore the bootloader should be careful to not enable + * the LCD clock if it is not needed. + */ + + /* install (and disable) the clocks we do not need immediately */ + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + + s3c2412_clkcon_enable(clkp, 0); + } + + return 0; +} diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2410/s3c2412.c new file mode 100644 index 0000000..e24ffd5 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2412.c @@ -0,0 +1,195 @@ +/* linux/arch/arm/mach-s3c2410/s3c2412.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * http://armlinux.simtec.co.uk/. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Modifications: + * 16-May-2003 BJD Created initial version + * 16-Aug-2003 BJD Fixed header files and copyright, added URL + * 05-Sep-2003 BJD Moved to kernel v2.6 + * 18-Jan-2004 BJD Added serial port configuration + * 21-Aug-2004 BJD Added new struct s3c2410_board handler + * 28-Sep-2004 BJD Updates for new serial port bits + * 04-Nov-2004 BJD Updated UART configuration process + * 10-Jan-2005 BJD Removed s3c2410_clock_tick_rate + * 13-Aug-2005 DA Removed UART from initial I/O mappings +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "s3c2412.h" +#include "cpu.h" +#include "devs.h" +#include "clock.h" +#include "pm.h" + +#ifndef CONFIG_CPU_S3C2412_ONLY +void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO; +#endif + +/* Initial IO mappings */ + +static struct map_desc s3c2412_iodesc[] __initdata = { + IODESC_ENT(CLKPWR), + IODESC_ENT(LCD), + IODESC_ENT(TIMER), + IODESC_ENT(ADC), + IODESC_ENT(WATCHDOG), +}; + +/* uart registration process */ + +void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + s3c24xx_init_uartdevs("s3c2412-uart", s3c2410_uart_resources, cfg, no); + + /* rename devices that are s3c2412/s3c2413 specific */ + s3c_device_sdi.name = "s3c2412-sdi"; + s3c_device_nand.name = "s3c2412-nand"; +} + +/* s3c2412_map_io + * + * register the standard cpu IO areas, and any passed in from the + * machine specific initialisation. +*/ + +void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size) +{ + /* move base of IO */ + + s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10; + + /* register our io-tables */ + + iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc)); + iotable_init(mach_desc, mach_size); +} + +void __init s3c2412_init_clocks(int xtal) +{ + unsigned long tmp; + unsigned long fclk; + unsigned long hclk; + unsigned long pclk; + + /* now we've got our machine bits initialised, work out what + * clocks we've got */ + + fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal*2); + + tmp = __raw_readl(S3C2410_CLKDIVN); + + /* work out clock scalings */ + + hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1); + hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1); + pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1); + + /* print brieft summary of clocks, etc */ + + printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", + print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); + + /* initialise the clocks here, to allow other things like the + * console to use them + */ + + s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); + s3c2412_baseclk_add(); +} + +/* need to register class before we actually register the device, and + * we also need to ensure that it has been initialised before any of the + * drivers even try to use it (even if not on an s3c2412 based system) + * as a driver which may support both 2410 and 2440 may try and use it. +*/ + +#ifdef CONFIG_PM +static struct sleep_save s3c2412_sleep[] = { + SAVE_ITEM(S3C2412_DSC0), + SAVE_ITEM(S3C2412_DSC1), + SAVE_ITEM(S3C2413_GPJDAT), + SAVE_ITEM(S3C2413_GPJCON), + SAVE_ITEM(S3C2413_GPJUP), + + /* save the sleep configuration anyway, just in case these + * get damaged during wakeup */ + + SAVE_ITEM(S3C2412_GPBSLPCON), + SAVE_ITEM(S3C2412_GPCSLPCON), + SAVE_ITEM(S3C2412_GPDSLPCON), + SAVE_ITEM(S3C2412_GPESLPCON), + SAVE_ITEM(S3C2412_GPFSLPCON), + SAVE_ITEM(S3C2412_GPGSLPCON), + SAVE_ITEM(S3C2412_GPHSLPCON), + SAVE_ITEM(S3C2413_GPJSLPCON), +}; + +static int s3c2412_suspend(struct sys_device *dev, pm_message_t state) +{ + s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep)); + return 0; +} + +static int s3c2412_resume(struct sys_device *dev) +{ + s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep)); + return 0; +} + +#else +#define s3c2412_suspend NULL +#define s3c2412_resume NULL +#endif + +struct sysdev_class s3c2412_sysclass = { + set_kset_name("s3c2412-core"), + .suspend = s3c2412_suspend, + .resume = s3c2412_resume +}; + +static int __init s3c2412_core_init(void) +{ + return sysdev_class_register(&s3c2412_sysclass); +} + +core_initcall(s3c2412_core_init); + +static struct sys_device s3c2412_sysdev = { + .cls = &s3c2412_sysclass, +}; + +int __init s3c2412_init(void) +{ + printk("S3C2412: Initialising architecture\n"); + + return sysdev_register(&s3c2412_sysdev); +} diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/arch/arm/mach-s3c2410/s3c2412.h new file mode 100644 index 0000000..c6e5603 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2412.h @@ -0,0 +1,29 @@ +/* arch/arm/mach-s3c2410/s3c2412.h + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * Header file for s3c2412 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifdef CONFIG_CPU_S3C2412 + +extern int s3c2412_init(void); + +extern void s3c2412_map_io(struct map_desc *mach_desc, int size); + +extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no); + +extern void s3c2412_init_clocks(int xtal); + +extern int s3c2412_baseclk_add(void); +#else +#define s3c2412_init_clocks NULL +#define s3c2412_init_uarts NULL +#define s3c2412_map_io NULL +#define s3c2412_init NULL +#endif diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c index d7a30ed..1579686 100644 --- a/arch/arm/mach-s3c2410/s3c2440-clock.c +++ b/arch/arm/mach-s3c2410/s3c2440-clock.c @@ -91,7 +91,7 @@ static int s3c2440_camif_upll_setrate(st static struct clk s3c2440_clk_cam = { .name = "camif", .id = -1, - .enable = s3c24xx_clkcon_enable, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2440_CLKCON_CAMERA, }; @@ -105,7 +105,7 @@ static struct clk s3c2440_clk_cam_upll = static struct clk s3c2440_clk_ac97 = { .name = "ac97", .id = -1, - .enable = s3c24xx_clkcon_enable, + .enable = s3c2410_clkcon_enable, .ctrlbit = S3C2440_CLKCON_CAMERA, }; diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2410/s3c2440-irq.c index 278d004..acfe387 100644 --- a/arch/arm/mach-s3c2410/s3c2440-irq.c +++ b/arch/arm/mach-s3c2410/s3c2440-irq.c @@ -100,73 +100,12 @@ static struct irqchip s3c_irq_wdtac97 = .ack = s3c_irq_wdtac97_ack, }; -/* camera irq */ - -static void s3c_irq_demux_cam(unsigned int irq, - struct irqdesc *desc, - struct pt_regs *regs) -{ - unsigned int subsrc, submsk; - struct irqdesc *mydesc; - - /* read the current pending interrupts, and the mask - * for what it is available */ - - subsrc = __raw_readl(S3C2410_SUBSRCPND); - submsk = __raw_readl(S3C2410_INTSUBMSK); - - subsrc &= ~submsk; - subsrc >>= 11; - subsrc &= 3; - - if (subsrc != 0) { - if (subsrc & 1) { - mydesc = irq_desc + IRQ_S3C2440_CAM_C; - desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs); - } - if (subsrc & 2) { - mydesc = irq_desc + IRQ_S3C2440_CAM_P; - desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs); - } - } -} - -#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0)) - -static void -s3c_irq_cam_mask(unsigned int irqno) -{ - s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11); -} - -static void -s3c_irq_cam_unmask(unsigned int irqno) -{ - s3c_irqsub_unmask(irqno, INTMSK_CAM); -} - -static void -s3c_irq_cam_ack(unsigned int irqno) -{ - s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11); -} - -static struct irqchip s3c_irq_cam = { - .mask = s3c_irq_cam_mask, - .unmask = s3c_irq_cam_unmask, - .ack = s3c_irq_cam_ack, -}; - static int s3c2440_irq_add(struct sys_device *sysdev) { unsigned int irqno; printk("S3C2440: IRQ Support\n"); - set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip); - set_irq_handler(IRQ_NFCON, do_level_IRQ); - set_irq_flags(IRQ_NFCON, IRQF_VALID); - /* add new chained handler for wdt, ac7 */ set_irq_chip(IRQ_WDT, &s3c_irq_level_chip); @@ -179,18 +118,6 @@ static int s3c2440_irq_add(struct sys_de set_irq_flags(irqno, IRQF_VALID); } - /* add chained handler for camera */ - - set_irq_chip(IRQ_CAM, &s3c_irq_level_chip); - set_irq_handler(IRQ_CAM, do_level_IRQ); - set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam); - - for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) { - set_irq_chip(irqno, &s3c_irq_cam); - set_irq_handler(irqno, do_level_IRQ); - set_irq_flags(irqno, IRQF_VALID); - } - return 0; } @@ -198,10 +125,10 @@ static struct sysdev_driver s3c2440_irq_ .add = s3c2440_irq_add, }; -static int s3c24xx_irq_driver(void) +static int s3c2440_irq_init(void) { return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver); } -arch_initcall(s3c24xx_irq_driver); +arch_initcall(s3c2440_irq_init); diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c index b7fe6d9..0ab50f4 100644 --- a/arch/arm/mach-s3c2410/s3c2440.c +++ b/arch/arm/mach-s3c2410/s3c2440.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2410/s3c2440.c * - * Copyright (c) 2004-2005 Simtec Electronics + * Copyright (c) 2004-2006 Simtec Electronics * Ben Dooks * * Samsung S3C2440 Mobile CPU support @@ -8,16 +8,6 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * - * Modifications: - * 24-Aug-2004 BJD Start of s3c2440 support - * 12-Oct-2004 BJD Moved clock info out to clock.c - * 01-Nov-2004 BJD Fixed clock build code - * 09-Nov-2004 BJD Added sysdev for power management - * 04-Nov-2004 BJD New serial registration - * 15-Nov-2004 BJD Rename the i2c device for the s3c2440 - * 14-Jan-2005 BJD Moved clock init code into seperate function - * 14-Jan-2005 BJD Removed un-used clock bits */ #include @@ -50,234 +40,20 @@ #include "devs.h" #include "cpu.h" #include "pm.h" - -static struct map_desc s3c2440_iodesc[] __initdata = { - IODESC_ENT(USBHOST), - IODESC_ENT(CLKPWR), - IODESC_ENT(LCD), - IODESC_ENT(TIMER), - IODESC_ENT(ADC), - IODESC_ENT(WATCHDOG), -}; - -static struct resource s3c_uart0_resource[] = { - [0] = { - .start = S3C2410_PA_UART0, - .end = S3C2410_PA_UART0 + 0x3fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_S3CUART_RX0, - .end = IRQ_S3CUART_ERR0, - .flags = IORESOURCE_IRQ, - } - -}; - -static struct resource s3c_uart1_resource[] = { - [0] = { - .start = S3C2410_PA_UART1, - .end = S3C2410_PA_UART1 + 0x3fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_S3CUART_RX1, - .end = IRQ_S3CUART_ERR1, - .flags = IORESOURCE_IRQ, - } -}; - -static struct resource s3c_uart2_resource[] = { - [0] = { - .start = S3C2410_PA_UART2, - .end = S3C2410_PA_UART2 + 0x3fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_S3CUART_RX2, - .end = IRQ_S3CUART_ERR2, - .flags = IORESOURCE_IRQ, - } -}; - -/* our uart devices */ - -static struct platform_device s3c_uart0 = { - .name = "s3c2440-uart", - .id = 0, - .num_resources = ARRAY_SIZE(s3c_uart0_resource), - .resource = s3c_uart0_resource, -}; - -static struct platform_device s3c_uart1 = { - .name = "s3c2440-uart", - .id = 1, - .num_resources = ARRAY_SIZE(s3c_uart1_resource), - .resource = s3c_uart1_resource, -}; - -static struct platform_device s3c_uart2 = { - .name = "s3c2440-uart", - .id = 2, - .num_resources = ARRAY_SIZE(s3c_uart2_resource), - .resource = s3c_uart2_resource, -}; - -static struct platform_device *uart_devices[] __initdata = { - &s3c_uart0, - &s3c_uart1, - &s3c_uart2 -}; - -/* uart initialisation */ - -static int __initdata s3c2440_uart_count; - -void __init s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no) -{ - struct platform_device *platdev; - int uart; - - for (uart = 0; uart < no; uart++, cfg++) { - platdev = uart_devices[cfg->hwport]; - - s3c24xx_uart_devs[uart] = platdev; - platdev->dev.platform_data = cfg; - } - - s3c2440_uart_count = uart; -} - - -#ifdef CONFIG_PM - -static struct sleep_save s3c2440_sleep[] = { - SAVE_ITEM(S3C2440_DSC0), - SAVE_ITEM(S3C2440_DSC1), - SAVE_ITEM(S3C2440_GPJDAT), - SAVE_ITEM(S3C2440_GPJCON), - SAVE_ITEM(S3C2440_GPJUP) -}; - -static int s3c2440_suspend(struct sys_device *dev, pm_message_t state) -{ - s3c2410_pm_do_save(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep)); - return 0; -} - -static int s3c2440_resume(struct sys_device *dev) -{ - s3c2410_pm_do_restore(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep)); - return 0; -} - -#else -#define s3c2440_suspend NULL -#define s3c2440_resume NULL -#endif - -struct sysdev_class s3c2440_sysclass = { - set_kset_name("s3c2440-core"), - .suspend = s3c2440_suspend, - .resume = s3c2440_resume -}; - static struct sys_device s3c2440_sysdev = { .cls = &s3c2440_sysclass, }; -void __init s3c2440_map_io(struct map_desc *mach_desc, int size) +int __init s3c2440_init(void) { - /* register our io-tables */ - - iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc)); - iotable_init(mach_desc, size); - - /* rename any peripherals used differing from the s3c2410 */ - - s3c_device_i2c.name = "s3c2440-i2c"; - s3c_device_nand.name = "s3c2440-nand"; + printk("S3C2440: Initialising architecture\n"); /* change irq for watchdog */ s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT; s3c_device_wdt.resource[1].end = IRQ_S3C2440_WDT; -} - -void __init s3c2440_init_clocks(int xtal) -{ - unsigned long clkdiv; - unsigned long camdiv; - unsigned long hclk, fclk, pclk; - int hdiv = 1; - - /* now we've got our machine bits initialised, work out what - * clocks we've got */ - - fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2; - - clkdiv = __raw_readl(S3C2410_CLKDIVN); - camdiv = __raw_readl(S3C2440_CAMDIVN); - - /* work out clock scalings */ - - switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) { - case S3C2440_CLKDIVN_HDIVN_1: - hdiv = 1; - break; - - case S3C2440_CLKDIVN_HDIVN_2: - hdiv = 2; - break; - - case S3C2440_CLKDIVN_HDIVN_4_8: - hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4; - break; - - case S3C2440_CLKDIVN_HDIVN_3_6: - hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3; - break; - } - - hclk = fclk / hdiv; - pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1); - - /* print brief summary of clocks, etc */ - - printk("S3C2440: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", - print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); - - /* initialise the clocks here, to allow other things like the - * console to use them, and to add new ones after the initialisation - */ - - s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); -} - -/* need to register class before we actually register the device, and - * we also need to ensure that it has been initialised before any of the - * drivers even try to use it (even if not on an s3c2440 based system) - * as a driver which may support both 2410 and 2440 may try and use it. -*/ - -static int __init s3c2440_core_init(void) -{ - return sysdev_class_register(&s3c2440_sysclass); -} - -core_initcall(s3c2440_core_init); - -int __init s3c2440_init(void) -{ - int ret; - - printk("S3C2440: Initialising architecture\n"); - ret = sysdev_register(&s3c2440_sysdev); - if (ret != 0) - printk(KERN_ERR "failed to register sysdev for s3c2440\n"); - else - ret = platform_add_devices(s3c24xx_uart_devs, s3c2440_uart_count); + /* register our system device for everything else */ - return ret; + return sysdev_register(&s3c2440_sysdev); } diff --git a/arch/arm/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2410/s3c2442-clock.c new file mode 100644 index 0000000..d9f54b5 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2442-clock.c @@ -0,0 +1,171 @@ +/* linux/arch/arm/mach-s3c2410/s3c2442-clock.c + * + * Copyright (c) 2004-2005 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks + * + * S3C2442 Clock support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "clock.h" +#include "cpu.h" + +/* S3C2442 extended clock support */ + +static unsigned long s3c2442_camif_upll_round(struct clk *clk, + unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + int div; + + if (rate > parent_rate) + return parent_rate; + + div = parent_rate / rate; + + if (div == 3) + return parent_rate / 3; + + /* note, we remove the +/- 1 calculations for the divisor */ + + div /= 2; + + if (div < 1) + div = 1; + else if (div > 16) + div = 16; + + return parent_rate / (div * 2); +} + +static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); + + rate = s3c2442_camif_upll_round(clk, rate); + + camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3; + + if (rate == parent_rate) { + camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL; + } else if ((parent_rate / rate) == 3) { + camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL; + camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3; + } else { + camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK; + camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL; + camdivn |= (((parent_rate / rate) / 2) - 1); + } + + __raw_writel(camdivn, S3C2440_CAMDIVN); + + return 0; +} + +/* Extra S3C2442 clocks */ + +static struct clk s3c2442_clk_cam = { + .name = "camif", + .id = -1, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2440_CLKCON_CAMERA, +}; + +static struct clk s3c2442_clk_cam_upll = { + .name = "camif-upll", + .id = -1, + .set_rate = s3c2442_camif_upll_setrate, + .round_rate = s3c2442_camif_upll_round, +}; + +static int s3c2442_clk_add(struct sys_device *sysdev) +{ + unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); + unsigned long clkdivn; + struct clk *clk_h; + struct clk *clk_p; + struct clk *clk_upll; + + printk("S3C2442: Clock Support, DVS %s\n", + (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off"); + + clk_p = clk_get(NULL, "pclk"); + clk_h = clk_get(NULL, "hclk"); + clk_upll = clk_get(NULL, "upll"); + + if (IS_ERR(clk_p) || IS_ERR(clk_h) || IS_ERR(clk_upll)) { + printk(KERN_ERR "S3C2442: Failed to get parent clocks\n"); + return -EINVAL; + } + + /* check rate of UPLL, and if it is near 96MHz, then change + * to using half the UPLL rate for the system */ + + if (clk_get_rate(clk_upll) > (94 * MHZ)) { + clk_usb_bus.rate = clk_get_rate(clk_upll) / 2; + + mutex_lock(&clocks_mutex); + + clkdivn = __raw_readl(S3C2410_CLKDIVN); + clkdivn |= S3C2440_CLKDIVN_UCLK; + __raw_writel(clkdivn, S3C2410_CLKDIVN); + + mutex_unlock(&clocks_mutex); + } + + s3c2442_clk_cam.parent = clk_h; + s3c2442_clk_cam_upll.parent = clk_upll; + + s3c24xx_register_clock(&s3c2442_clk_cam); + s3c24xx_register_clock(&s3c2442_clk_cam_upll); + + clk_disable(&s3c2442_clk_cam); + + return 0; +} + +static struct sysdev_driver s3c2442_clk_driver = { + .add = s3c2442_clk_add, +}; + +static __init int s3c2442_clk_init(void) +{ + return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver); +} + +arch_initcall(s3c2442_clk_init); diff --git a/arch/arm/mach-s3c2410/s3c2442.c b/arch/arm/mach-s3c2410/s3c2442.c new file mode 100644 index 0000000..debae24 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2442.c @@ -0,0 +1,52 @@ +/* linux/arch/arm/mach-s3c2410/s3c2440.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * Samsung S3C2442 Mobile CPU support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "s3c2442.h" +#include "clock.h" +#include "devs.h" +#include "cpu.h" +#include "pm.h" + +static struct sys_device s3c2442_sysdev = { + .cls = &s3c2442_sysclass, +}; + +int __init s3c2442_init(void) +{ + printk("S3C2442: Initialising architecture\n"); + + return sysdev_register(&s3c2442_sysdev); +} diff --git a/arch/arm/mach-s3c2410/s3c2442.h b/arch/arm/mach-s3c2410/s3c2442.h new file mode 100644 index 0000000..0ae37d2 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2442.h @@ -0,0 +1,17 @@ +/* arch/arm/mach-s3c2410/s3c2442.h + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * Header file for s3c2442 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifdef CONFIG_CPU_S3C2442 +extern int s3c2442_init(void); +#else +#define s3c2442_init NULL +#endif diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/mach-s3c2410/s3c244x-irq.c new file mode 100644 index 0000000..2aadca1 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c244x-irq.c @@ -0,0 +1,142 @@ +/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c + * + * Copyright (c) 2003,2004 Simtec Electronics + * Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Changelog: + * 25-Jul-2005 BJD Split from irq.c + * +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include "cpu.h" +#include "pm.h" +#include "irq.h" + +/* camera irq */ + +static void s3c_irq_demux_cam(unsigned int irq, + struct irqdesc *desc, + struct pt_regs *regs) +{ + unsigned int subsrc, submsk; + struct irqdesc *mydesc; + + /* read the current pending interrupts, and the mask + * for what it is available */ + + subsrc = __raw_readl(S3C2410_SUBSRCPND); + submsk = __raw_readl(S3C2410_INTSUBMSK); + + subsrc &= ~submsk; + subsrc >>= 11; + subsrc &= 3; + + if (subsrc != 0) { + if (subsrc & 1) { + mydesc = irq_desc + IRQ_S3C2440_CAM_C; + desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs); + } + if (subsrc & 2) { + mydesc = irq_desc + IRQ_S3C2440_CAM_P; + desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs); + } + } +} + +#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0)) + +static void +s3c_irq_cam_mask(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11); +} + +static void +s3c_irq_cam_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_CAM); +} + +static void +s3c_irq_cam_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11); +} + +static struct irqchip s3c_irq_cam = { + .mask = s3c_irq_cam_mask, + .unmask = s3c_irq_cam_unmask, + .ack = s3c_irq_cam_ack, +}; + +static int s3c244x_irq_add(struct sys_device *sysdev) +{ + unsigned int irqno; + + set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip); + set_irq_handler(IRQ_NFCON, do_level_IRQ); + set_irq_flags(IRQ_NFCON, IRQF_VALID); + + /* add chained handler for camera */ + + set_irq_chip(IRQ_CAM, &s3c_irq_level_chip); + set_irq_handler(IRQ_CAM, do_level_IRQ); + set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam); + + for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) { + set_irq_chip(irqno, &s3c_irq_cam); + set_irq_handler(irqno, do_level_IRQ); + set_irq_flags(irqno, IRQF_VALID); + } + + return 0; +} + +static struct sysdev_driver s3c244x_irq_driver = { + .add = s3c244x_irq_add, +}; + +static int s3c2440_irq_init(void) +{ + return sysdev_driver_register(&s3c2440_sysclass, &s3c244x_irq_driver); +} + +arch_initcall(s3c2440_irq_init); + + +static int s3c2442_irq_init(void) +{ + return sysdev_driver_register(&s3c2442_sysclass, &s3c244x_irq_driver); +} + +arch_initcall(s3c2442_irq_init); diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/mach-s3c2410/s3c244x.c new file mode 100644 index 0000000..838bc52 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c244x.c @@ -0,0 +1,184 @@ +/* linux/arch/arm/mach-s3c2410/s3c244x.c + * + * Copyright (c) 2004-2006 Simtec Electronics + * Ben Dooks + * + * Samsung S3C2440 and S3C2442 Mobile CPU support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "s3c2410.h" +#include "s3c2440.h" +#include "s3c244x.h" +#include "clock.h" +#include "devs.h" +#include "cpu.h" +#include "pm.h" + +static struct map_desc s3c244x_iodesc[] __initdata = { + IODESC_ENT(CLKPWR), + IODESC_ENT(TIMER), + IODESC_ENT(WATCHDOG), + IODESC_ENT(LCD), + IODESC_ENT(ADC), + IODESC_ENT(USBHOST), +}; + +/* uart initialisation */ + +void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no); +} + +void __init s3c244x_map_io(struct map_desc *mach_desc, int size) +{ + /* register our io-tables */ + + iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc)); + iotable_init(mach_desc, size); + + /* rename any peripherals used differing from the s3c2410 */ + + s3c_device_i2c.name = "s3c2440-i2c"; + s3c_device_nand.name = "s3c2440-nand"; +} + +void __init s3c244x_init_clocks(int xtal) +{ + unsigned long clkdiv; + unsigned long camdiv; + unsigned long hclk, fclk, pclk; + int hdiv = 1; + + /* now we've got our machine bits initialised, work out what + * clocks we've got */ + + fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2; + + clkdiv = __raw_readl(S3C2410_CLKDIVN); + camdiv = __raw_readl(S3C2440_CAMDIVN); + + /* work out clock scalings */ + + switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) { + case S3C2440_CLKDIVN_HDIVN_1: + hdiv = 1; + break; + + case S3C2440_CLKDIVN_HDIVN_2: + hdiv = 2; + break; + + case S3C2440_CLKDIVN_HDIVN_4_8: + hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4; + break; + + case S3C2440_CLKDIVN_HDIVN_3_6: + hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3; + break; + } + + hclk = fclk / hdiv; + pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1); + + /* print brief summary of clocks, etc */ + + printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", + print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); + + /* initialise the clocks here, to allow other things like the + * console to use them, and to add new ones after the initialisation + */ + + s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); + s3c2410_baseclk_add(); +} + +#ifdef CONFIG_PM + +static struct sleep_save s3c244x_sleep[] = { + SAVE_ITEM(S3C2440_DSC0), + SAVE_ITEM(S3C2440_DSC1), + SAVE_ITEM(S3C2440_GPJDAT), + SAVE_ITEM(S3C2440_GPJCON), + SAVE_ITEM(S3C2440_GPJUP) +}; + +static int s3c244x_suspend(struct sys_device *dev, pm_message_t state) +{ + s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep)); + return 0; +} + +static int s3c244x_resume(struct sys_device *dev) +{ + s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep)); + return 0; +} + +#else +#define s3c244x_suspend NULL +#define s3c244x_resume NULL +#endif + +/* Since the S3C2442 and S3C2440 share items, put both sysclasses here */ + +struct sysdev_class s3c2440_sysclass = { + set_kset_name("s3c2440-core"), + .suspend = s3c244x_suspend, + .resume = s3c244x_resume +}; + +struct sysdev_class s3c2442_sysclass = { + set_kset_name("s3c2442-core"), + .suspend = s3c244x_suspend, + .resume = s3c244x_resume +}; + +/* need to register class before we actually register the device, and + * we also need to ensure that it has been initialised before any of the + * drivers even try to use it (even if not on an s3c2440 based system) + * as a driver which may support both 2410 and 2440 may try and use it. +*/ + +static int __init s3c2440_core_init(void) +{ + return sysdev_class_register(&s3c2440_sysclass); +} + +core_initcall(s3c2440_core_init); + +static int __init s3c2442_core_init(void) +{ + return sysdev_class_register(&s3c2442_sysclass); +} + +core_initcall(s3c2442_core_init); diff --git a/arch/arm/mach-s3c2410/s3c244x.h b/arch/arm/mach-s3c2410/s3c244x.h new file mode 100644 index 0000000..3e7f5f7 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c244x.h @@ -0,0 +1,25 @@ +/* arch/arm/mach-s3c2410/s3c2440.h + * + * Copyright (c) 2004-2005 Simtec Electronics + * Ben Dooks + * + * Header file for S3C2440 and S3C2442 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) + +extern void s3c244x_map_io(struct map_desc *mach_desc, int size); + +extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no); + +extern void s3c244x_init_clocks(int xtal); + +#else +#define s3c244x_init_clocks NULL +#define s3c244x_init_uarts NULL +#define s3c244x_map_io NULL +#endif diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S index 73de2ea..dc27167 100644 --- a/arch/arm/mach-s3c2410/sleep.S +++ b/arch/arm/mach-s3c2410/sleep.S @@ -66,7 +66,9 @@ ENTRY(s3c2410_cpu_suspend) @@ flush the caches to ensure everything is back out to @@ SDRAM before the core powers down +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH bl arm920_flush_kern_cache_all +#endif @@ prepare cpu to sleep @@ -126,7 +128,7 @@ s3c2410_sleep_save_phys: */ ENTRY(s3c2410_cpu_resume) - mov r0, #PSR_I_BIT | PSR_F_BIT | MODE_SVC + mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE msr cpsr_c, r0 @@ load UART to allow us to print the two characters for diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S index 2fa1e28..5a84062 100644 --- a/arch/arm/mach-sa1100/sleep.S +++ b/arch/arm/mach-sa1100/sleep.S @@ -177,7 +177,7 @@ sa1110_sdram_controller_fix: .data .align 5 ENTRY(sa1100_cpu_resume) - mov r0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC + mov r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE msr cpsr_c, r0 @ set SVC, irqs off ldr r0, sleep_save_sp @ stack phys addr diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index c55b739..ecf5e23 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -61,9 +61,9 @@ config CPU_ARM720T # ARM920T config CPU_ARM920T - bool "Support ARM920T processor" if !ARCH_S3C2410 - depends on ARCH_EP93XX || ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200 - default y if ARCH_S3C2410 || ARCH_AT91RM9200 + bool "Support ARM920T processor" + depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200 + default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200 select CPU_32v4 select CPU_ABRT_EV4T select CPU_CACHE_V4WT @@ -121,8 +121,8 @@ config CPU_ARM925T # ARM926T config CPU_ARM926T bool "Support ARM926T processor" - depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB - default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX + depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 + default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 select CPU_32v5 select CPU_ABRT_EV5TJ select CPU_CACHE_VIVT diff --git a/arch/arm/mm/copypage-v3.S b/arch/arm/mm/copypage-v3.S index 3c58ebb..2ee394b 100644 --- a/arch/arm/mm/copypage-v3.S +++ b/arch/arm/mm/copypage-v3.S @@ -35,7 +35,7 @@ ENTRY(v3_copy_user_page) stmia r0!, {r3, r4, ip, lr} @ 4 ldmneia r1!, {r3, r4, ip, lr} @ 4 bne 1b @ 1 - LOADREGS(fd, sp!, {r4, pc}) @ 3 + ldmfd sp!, {r4, pc} @ 3 .align 5 /* diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index ee6f152..09b1a41 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -29,38 +29,6 @@ #define TTB_RGN_WBWA (1 << 3) #define TTB_RGN_WT (2 << 3) #define TTB_RGN_WB (3 << 3) - .macro cpsie, flags - .ifc \flags, f - .long 0xf1080040 - .exitm - .endif - .ifc \flags, i - .long 0xf1080080 - .exitm - .endif - .ifc \flags, if - .long 0xf10800c0 - .exitm - .endif - .err - .endm - - .macro cpsid, flags - .ifc \flags, f - .long 0xf10c0040 - .exitm - .endif - .ifc \flags, i - .long 0xf10c0080 - .exitm - .endif - .ifc \flags, if - .long 0xf10c00c0 - .exitm - .endif - .err - .endm - ENTRY(cpu_v6_proc_init) mov pc, lr diff --git a/arch/arm/nwfpe/entry26.S b/arch/arm/nwfpe/entry26.S index 51940a9..3e6fb5d 100644 --- a/arch/arm/nwfpe/entry26.S +++ b/arch/arm/nwfpe/entry26.S @@ -26,7 +26,7 @@ #include It is called from the kernel with code similar to this: mov fp, #0 - teqp pc, #PSR_I_BIT | MODE_SVC + teqp pc, #PSR_I_BIT | SVC_MODE ldr r4, .LC2 ldr pc, [r4] @ Call FP module USR entry point diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c index 2dfe1ac..7d977d2 100644 --- a/arch/arm/nwfpe/fpmodule.c +++ b/arch/arm/nwfpe/fpmodule.c @@ -33,7 +33,8 @@ #include #include #include #include -/* XXX */ + +#include #include "softfloat.h" #include "fpopcode.h" @@ -56,16 +57,28 @@ #define kern_fp_enter fp_enter extern char fpe_type[]; #endif +static int nwfpe_notify(struct notifier_block *self, unsigned long cmd, void *v) +{ + struct thread_info *thread = v; + + if (cmd == THREAD_NOTIFY_FLUSH) + nwfpe_init_fpa(&thread->fpstate); + + return NOTIFY_DONE; +} + +static struct notifier_block nwfpe_notifier_block = { + .notifier_call = nwfpe_notify, +}; + /* kernel function prototypes required */ void fp_setup(void); /* external declarations for saved kernel symbols */ extern void (*kern_fp_enter)(void); -extern void (*fp_init)(union fp_state *); /* Original value of fp_enter from kernel before patched by fpe_init. */ static void (*orig_fp_enter)(void); -static void (*orig_fp_init)(union fp_state *); /* forward declarations */ extern void nwfpe_enter(void); @@ -88,20 +101,20 @@ static int __init fpe_init(void) printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 (" NWFPE_BITS " precision)\n"); + thread_register_notifier(&nwfpe_notifier_block); + /* Save pointer to the old FP handler and then patch ourselves in */ orig_fp_enter = kern_fp_enter; - orig_fp_init = fp_init; kern_fp_enter = nwfpe_enter; - fp_init = nwfpe_init_fpa; return 0; } static void __exit fpe_exit(void) { + thread_unregister_notifier(&nwfpe_notifier_block); /* Restore the values we saved earlier. */ kern_fp_enter = orig_fp_enter; - fp_init = orig_fp_init; } /* diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c index b2a943b..3461a6c 100644 --- a/arch/arm/plat-omap/timer32k.c +++ b/arch/arm/plat-omap/timer32k.c @@ -210,7 +210,8 @@ static irqreturn_t omap_32k_timer_interr now = omap_32k_sync_timer_read(); - while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) { + while ((signed long)(now - omap_32k_last_tick) + >= OMAP_32K_TICKS_PER_HZ) { omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ; timer_tick(regs); } diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 6d7de9c..e1372a2 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # or visit: # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Mon May 8 20:11:05 2006 +# Last update: Mon Jun 26 22:26:08 2006 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -566,8 +566,8 @@ switchgrass MACH_SWITCHGRASS SWITCHGRAS ens_cmu MACH_ENS_CMU ENS_CMU 550 mm6_sdb MACH_MM6_SDB MM6_SDB 551 saturn MACH_SATURN SATURN 552 -i30030evb MACH_ARGONPLUSEVB ARGONPLUSEVB 553 -mxc27530evb MACH_SCMA11EVB SCMA11EVB 554 +i30030evb MACH_I30030EVB I30030EVB 553 +mxc27530evb MACH_MXC27530EVB MXC27530EVB 554 smdk2800 MACH_SMDK2800 SMDK2800 555 mtwilson MACH_MTWILSON MTWILSON 556 ziti MACH_ZITI ZITI 557 @@ -647,7 +647,7 @@ sendt MACH_SENDT SENDT 630 mx2jazz MACH_MX2JAZZ MX2JAZZ 631 multiio MACH_MULTIIO MULTIIO 632 hrdisplay MACH_HRDISPLAY HRDISPLAY 633 -mxc27530ads MACH_SCMA11BB SCMA11BB 634 +mxc27530ads MACH_MXC27530ADS MXC27530ADS 634 trizeps3 MACH_TRIZEPS3 TRIZEPS3 635 zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636 zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637 @@ -721,7 +721,7 @@ gp32 MACH_GP32 GP32 706 gem MACH_GEM GEM 707 i858 MACH_I858 I858 708 hx2750 MACH_HX2750 HX2750 709 -mxc91131evb MACH_ZEUSEVB ZEUSEVB 710 +mxc91131evb MACH_MXC91131EVB MXC91131EVB 710 p700 MACH_P700 P700 711 cpe MACH_CPE CPE 712 spitz MACH_SPITZ SPITZ 713 @@ -802,7 +802,7 @@ cpuat91 MACH_CPUAT91 CPUAT91 787 rea9200 MACH_REA9200 REA9200 788 acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789 ixp425 MACH_IXP425 IXP425 790 -i30030ads MACH_ARGONPLUSODYSSEY ARGONPLUSODYSSEY 791 +i30030ads MACH_I30030ADS I30030ADS 791 perch MACH_PERCH PERCH 792 eis05r1 MACH_EIS05R1 EIS05R1 793 pepperpad MACH_PEPPERPAD PEPPERPAD 794 @@ -930,7 +930,7 @@ netclient MACH_NETCLIENT NETCLIENT 91 xscale_palmtt5 MACH_XSCALE_PALMTT5 XSCALE_PALMTT5 917 xscale_palmtc MACH_OMAP_PALMTC OMAP_PALMTC 918 omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919 -mxc30030evb MACH_ARGONLVEVB ARGONLVEVB 920 +mxc30030evb MACH_MXC30030EVB MXC30030EVB 920 rea_2d MACH_REA_2D REA_2D 921 eti3e524 MACH_TI3E524 TI3E524 922 ateb9200 MACH_ATEB9200 ATEB9200 923 @@ -986,7 +986,7 @@ redfox MACH_REDFOX REDFOX 972 mysh_ep9315_1 MACH_MYSH_EP9315_1 MYSH_EP9315_1 973 tpf106 MACH_TPF106 TPF106 974 at91rm9200kg MACH_AT91RM9200KG AT91RM9200KG 975 -racemt2 MACH_SLEDB SLEDB 976 +rcmt2 MACH_SLEDB SLEDB 976 ontrack MACH_ONTRACK ONTRACK 977 pm1200 MACH_PM1200 PM1200 978 ess24562 MACH_ESS24XXX ESS24XXX 979 @@ -1022,7 +1022,7 @@ smdk2440 MACH_SMDK2440 SMDK2440 1008 smdk2412 MACH_SMDK2412 SMDK2412 1009 webbox MACH_WEBBOX WEBBOX 1010 cwwndp MACH_CWWNDP CWWNDP 1011 -dragon MACH_DRAGON DRAGON 1012 +i839 MACH_DRAGON DRAGON 1012 opendo_cpu_board MACH_OPENDO_CPU_BOARD OPENDO_CPU_BOARD 1013 ccm2200 MACH_CCM2200 CCM2200 1014 etwarm MACH_ETWARM ETWARM 1015 @@ -1040,3 +1040,56 @@ edg79524 MACH_EDG79524 EDG79524 1026 ai2410 MACH_AI2410 AI2410 1027 ixp465 MACH_IXP465 IXP465 1028 balloon3 MACH_BALLOON3 BALLOON3 1029 +heins MACH_HEINS HEINS 1030 +mpluseva MACH_MPLUSEVA MPLUSEVA 1031 +rt042 MACH_RT042 RT042 1032 +cwiem MACH_CWIEM CWIEM 1033 +cm_x270 MACH_CM_X270 CM_X270 1034 +cm_x255 MACH_CM_X255 CM_X255 1035 +esh_at91 MACH_ESH_AT91 ESH_AT91 1036 +sandgate3 MACH_SANDGATE3 SANDGATE3 1037 +primo MACH_PRIMO PRIMO 1038 +gemstone MACH_GEMSTONE GEMSTONE 1039 +pronghorn_metro MACH_PRONGHORNMETRO PRONGHORNMETRO 1040 +sidewinder MACH_SIDEWINDER SIDEWINDER 1041 +picomod1 MACH_PICOMOD1 PICOMOD1 1042 +sg590 MACH_SG590 SG590 1043 +akai9307 MACH_AKAI9307 AKAI9307 1044 +fontaine MACH_FONTAINE FONTAINE 1045 +wombat MACH_WOMBAT WOMBAT 1046 +acq300 MACH_ACQ300 ACQ300 1047 +mod_270 MACH_MOD_270 MOD_270 1048 +vmc_vc0820 MACH_VC0820 VC0820 1049 +ani_aim MACH_ANI_AIM ANI_AIM 1050 +jellyfish MACH_JELLYFISH JELLYFISH 1051 +amanita MACH_AMANITA AMANITA 1052 +vlink MACH_VLINK VLINK 1053 +dexflex MACH_DEXFLEX DEXFLEX 1054 +eigen_ttq MACH_EIGEN_TTQ EIGEN_TTQ 1055 +arcom_titan MACH_ARCOM_TITAN ARCOM_TITAN 1056 +tabla MACH_TABLA TABLA 1057 +mdirac3 MACH_MDIRAC3 MDIRAC3 1058 +mrhfbp2 MACH_MRHFBP2 MRHFBP2 1059 +at91rm9200rb MACH_AT91RM9200RB AT91RM9200RB 1060 +ani_apm MACH_ANI_APM ANI_APM 1061 +ella1 MACH_ELLA1 ELLA1 1062 +inhand_pxa27x MACH_INHAND_PXA27X INHAND_PXA27X 1063 +inhand_pxa25x MACH_INHAND_PXA25X INHAND_PXA25X 1064 +empos_xm MACH_EMPOS_XM EMPOS_XM 1065 +empos MACH_EMPOS EMPOS 1066 +empos_tiny MACH_EMPOS_TINY EMPOS_TINY 1067 +empos_sm MACH_EMPOS_SM EMPOS_SM 1068 +egret MACH_EGRET EGRET 1069 +ostrich MACH_OSTRICH OSTRICH 1070 +n50 MACH_N50 N50 1071 +ecbat91 MACH_ECBAT91 ECBAT91 1072 +stareast MACH_STAREAST STAREAST 1073 +dspg_dw MACH_DSPG_DW DSPG_DW 1074 +onearm MACH_ONEARM ONEARM 1075 +mrg110_6 MACH_MRG110_6 MRG110_6 1076 +wrt300nv2 MACH_WRT300NV2 WRT300NV2 1077 +xm_bulverde MACH_XM_BULVERDE XM_BULVERDE 1078 +msm6100 MACH_MSM6100 MSM6100 1079 +eti_b1 MACH_ETI_B1 ETI_B1 1080 +za9l_series MACH_ZILOG_ZA9L ZILOG_ZA9L 1081 +bit2440 MACH_BIT2440 BIT2440 1082 diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile index afabac3..7e136e7 100644 --- a/arch/arm/vfp/Makefile +++ b/arch/arm/vfp/Makefile @@ -7,6 +7,9 @@ # # EXTRA_CFLAGS := -DDEBUG # EXTRA_AFLAGS := -DDEBUG +AFLAGS :=$(AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp) +LDFLAGS +=--no-warn-mismatch + obj-y += vfp.o -vfp-$(CONFIG_VFP) += entry.o vfpmodule.o vfphw.o vfpsingle.o vfpdouble.o +vfp-$(CONFIG_VFP) += vfpmodule.o entry.o vfphw.o vfpsingle.o vfpdouble.o diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index a3f65b4..eb683cd 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -192,7 +192,7 @@ vfp_get_double: add pc, pc, r0, lsl #3 mov r0, r0 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mrrc p11, 1, r0, r1, c\dr @ fmrrd r0, r1, d\dr + fmrrd r0, r1, d\dr mov pc, lr .endr @@ -206,6 +206,6 @@ vfp_put_double: add pc, pc, r0, lsl #3 mov r0, r0 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mcrr p11, 1, r1, r2, c\dr @ fmdrr r1, r2, d\dr + fmdrr d\dr, r1, r2 mov pc, lr .endr diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 03486be..2476f4c 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -15,6 +15,8 @@ #include #include #include #include + +#include #include #include "vfpinstr.h" @@ -36,38 +38,55 @@ union vfp_state *last_VFP_context; */ unsigned int VFP_arch; -/* - * Per-thread VFP initialisation. - */ -void vfp_flush_thread(union vfp_state *vfp) +static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v) { - memset(vfp, 0, sizeof(union vfp_state)); + struct thread_info *thread = v; + union vfp_state *vfp = &thread->vfpstate; - vfp->hard.fpexc = FPEXC_ENABLE; - vfp->hard.fpscr = FPSCR_ROUND_NEAREST; + switch (cmd) { + case THREAD_NOTIFY_FLUSH: + /* + * Per-thread VFP initialisation. + */ + memset(vfp, 0, sizeof(union vfp_state)); - /* - * Disable VFP to ensure we initialise it first. - */ - fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE); + vfp->hard.fpexc = FPEXC_ENABLE; + vfp->hard.fpscr = FPSCR_ROUND_NEAREST; - /* - * Ensure we don't try to overwrite our newly initialised - * state information on the first fault. - */ - if (last_VFP_context == vfp) - last_VFP_context = NULL; -} + /* + * Disable VFP to ensure we initialise it first. + */ + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE); -/* - * Per-thread VFP cleanup. - */ -void vfp_release_thread(union vfp_state *vfp) -{ - if (last_VFP_context == vfp) - last_VFP_context = NULL; + /* + * FALLTHROUGH: Ensure we don't try to overwrite our newly + * initialised state information on the first fault. + */ + + case THREAD_NOTIFY_RELEASE: + /* + * Per-thread VFP cleanup. + */ + if (last_VFP_context == vfp) + last_VFP_context = NULL; + break; + + case THREAD_NOTIFY_SWITCH: + /* + * Always disable VFP so we can lazily save/restore the + * old state. + */ + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE); + break; + } + + return NOTIFY_DONE; } +static struct notifier_block vfp_notifier_block = { + .notifier_call = vfp_notifier, +}; + /* * Raise a SIGFPE for the current process. * sicode describes the signal being raised. @@ -281,6 +300,8 @@ static int __init vfp_init(void) (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); vfp_vector = vfp_support_entry; + + thread_register_notifier(&vfp_notifier_block); } return 0; } diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c index 24bc149..1e9d062 100644 --- a/arch/cris/arch-v32/drivers/pci/bios.c +++ b/arch/cris/arch-v32/drivers/pci/bios.c @@ -27,8 +27,6 @@ int pci_mmap_page_range(struct pci_dev * /* Leave vm_pgoff as-is, the PCI space address is the physical * address on this platform. */ - vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO); - prot = pgprot_val(vma->vm_page_prot); vma->vm_page_prot = __pgprot(prot); diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index a9b5952..81d94e4 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -1474,7 +1474,7 @@ sys_call_table: .long sys_mknodat .long sys_fchownat .long sys_futimesat - .long sys_newfstatat /* 300 */ + .long sys_fstatat64 /* 300 */ .long sys_unlinkat .long sys_renameat .long sys_linkat diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c index 0f273a7..dee637f 100644 --- a/arch/frv/kernel/frv_ksyms.c +++ b/arch/frv/kernel/frv_ksyms.c @@ -26,16 +26,6 @@ extern long __memset_user(void *dst, con EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); -EXPORT_SYMBOL(strnlen); -EXPORT_SYMBOL(strrchr); -EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(strchr); -EXPORT_SYMBOL(strcat); -EXPORT_SYMBOL(strlen); -EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strncmp); -EXPORT_SYMBOL(strncpy); - EXPORT_SYMBOL(ip_fast_csum); #if 0 @@ -44,8 +34,6 @@ EXPORT_SYMBOL(local_bh_count); #endif EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(__res_bus_clock_speed_HZ); EXPORT_SYMBOL(__page_offset); EXPORT_SYMBOL(__memcpy_user); @@ -62,18 +50,12 @@ #endif EXPORT_SYMBOL(__debug_bug_trap); -/* Networking helper routines. */ -EXPORT_SYMBOL(csum_partial_copy); - /* The following are special because they're not called explicitly (the C compiler generates them). Fortunately, their interface isn't gonna change any time soon now, so it's OK to leave it out of version control. */ EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memcmp); -EXPORT_SYMBOL(memscan); -EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(__outsl_ns); EXPORT_SYMBOL(__insl_ns); diff --git a/arch/frv/kernel/irq-routing.c b/arch/frv/kernel/irq-routing.c index d4776d1..b90b70a 100644 --- a/arch/frv/kernel/irq-routing.c +++ b/arch/frv/kernel/irq-routing.c @@ -112,7 +112,7 @@ struct irq_source frv_cpuuart[2] = { #define __CPUUART(X, A) \ [X] = { \ .muxname = "uart", \ - .muxdata = (volatile void __iomem *) A, \ + .muxdata = (volatile void __iomem *)(unsigned long)A,\ .irqmask = 1 << IRQ_CPU_UART##X, \ .doirq = frv_cpuuart_doirq, \ } @@ -136,7 +136,7 @@ struct irq_source frv_cpudma[8] = { #define __CPUDMA(X, A) \ [X] = { \ .muxname = "dma", \ - .muxdata = (volatile void __iomem *) A, \ + .muxdata = (volatile void __iomem *)(unsigned long)A,\ .irqmask = 1 << IRQ_CPU_DMA##X, \ .doirq = frv_cpudma_doirq, \ } @@ -164,7 +164,7 @@ struct irq_source frv_cputimer[3] = { #define __CPUTIMER(X) \ [X] = { \ .muxname = "timer", \ - .muxdata = 0, \ + .muxdata = NULL, \ .irqmask = 1 << IRQ_CPU_TIMER##X, \ .doirq = frv_cputimer_doirq, \ } @@ -187,7 +187,7 @@ struct irq_source frv_cpuexternal[8] = { #define __CPUEXTERNAL(X) \ [X] = { \ .muxname = "ext", \ - .muxdata = 0, \ + .muxdata = NULL, \ .irqmask = 1 << IRQ_CPU_EXTERNAL##X, \ .doirq = frv_cpuexternal_doirq, \ } diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c index 11fa326..8b112b3 100644 --- a/arch/frv/kernel/irq.c +++ b/arch/frv/kernel/irq.c @@ -625,7 +625,7 @@ static struct proc_dir_entry * irq_dir [ #define HEX_DIGITS 8 -static unsigned int parse_hex_value (const char *buffer, +static unsigned int parse_hex_value (const char __user *buffer, unsigned long count, unsigned long *ret) { unsigned char hexnum [HEX_DIGITS]; @@ -672,7 +672,7 @@ static int prof_cpu_mask_read_proc (char return sprintf (page, "%08lx\n", *mask); } -static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, +static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer, unsigned long count, void *data) { unsigned long *mask = (unsigned long *) data, full_count = count, err; @@ -711,7 +711,7 @@ void init_irq_proc (void) int i; /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", 0); + root_irq_dir = proc_mkdir("irq", NULL); /* create /proc/irq/prof_cpu_mask */ entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c index f0b8fff..43ce28a 100644 --- a/arch/frv/kernel/pm.c +++ b/arch/frv/kernel/pm.c @@ -137,7 +137,7 @@ #define CTL_PM_CMODE 2 #define CTL_PM_P0 4 #define CTL_PM_CM 5 -static int user_atoi(char *ubuf, size_t len) +static int user_atoi(char __user *ubuf, size_t len) { char buf[16]; unsigned long ret; @@ -159,7 +159,7 @@ static int user_atoi(char *ubuf, size_t * Send us to sleep. */ static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) + void __user *buffer, size_t *lenp, loff_t *fpos) { int retval, mode; @@ -215,7 +215,7 @@ #endif static int cmode_procctl(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) + void __user *buffer, size_t *lenp, loff_t *fpos) { int new_cmode; @@ -227,9 +227,9 @@ static int cmode_procctl(ctl_table *ctl, return try_set_cmode(new_cmode)?:*lenp; } -static int cmode_sysctl(ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, - void *newval, size_t newlen, void **context) +static int cmode_sysctl(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) { if (oldval && oldlenp) { size_t oldlen; @@ -240,7 +240,7 @@ static int cmode_sysctl(ctl_table *table if (oldlen != sizeof(int)) return -EINVAL; - if (put_user(clock_cmode_current, (unsigned int *)oldval) || + if (put_user(clock_cmode_current, (unsigned __user *)oldval) || put_user(sizeof(int), oldlenp)) return -EFAULT; } @@ -250,7 +250,7 @@ static int cmode_sysctl(ctl_table *table if (newlen != sizeof(int)) return -EINVAL; - if (get_user(new_cmode, (int *)newval)) + if (get_user(new_cmode, (int __user *)newval)) return -EFAULT; return try_set_cmode(new_cmode)?:1; @@ -318,7 +318,7 @@ #endif } static int p0_procctl(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) + void __user *buffer, size_t *lenp, loff_t *fpos) { int new_p0; @@ -330,9 +330,9 @@ static int p0_procctl(ctl_table *ctl, in return try_set_p0(new_p0)?:*lenp; } -static int p0_sysctl(ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, - void *newval, size_t newlen, void **context) +static int p0_sysctl(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) { if (oldval && oldlenp) { size_t oldlen; @@ -343,7 +343,7 @@ static int p0_sysctl(ctl_table *table, i if (oldlen != sizeof(int)) return -EINVAL; - if (put_user(clock_p0_current, (unsigned int *)oldval) || + if (put_user(clock_p0_current, (unsigned __user *)oldval) || put_user(sizeof(int), oldlenp)) return -EFAULT; } @@ -353,7 +353,7 @@ static int p0_sysctl(ctl_table *table, i if (newlen != sizeof(int)) return -EINVAL; - if (get_user(new_p0, (int *)newval)) + if (get_user(new_p0, (int __user *)newval)) return -EFAULT; return try_set_p0(new_p0)?:1; @@ -362,7 +362,7 @@ static int p0_sysctl(ctl_table *table, i } static int cm_procctl(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) + void __user *buffer, size_t *lenp, loff_t *fpos) { int new_cm; @@ -374,9 +374,9 @@ static int cm_procctl(ctl_table *ctl, in return try_set_cm(new_cm)?:*lenp; } -static int cm_sysctl(ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, - void *newval, size_t newlen, void **context) +static int cm_sysctl(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) { if (oldval && oldlenp) { size_t oldlen; @@ -387,7 +387,7 @@ static int cm_sysctl(ctl_table *table, i if (oldlen != sizeof(int)) return -EINVAL; - if (put_user(clock_cm_current, (unsigned int *)oldval) || + if (put_user(clock_cm_current, (unsigned __user *)oldval) || put_user(sizeof(int), oldlenp)) return -EFAULT; } @@ -397,7 +397,7 @@ static int cm_sysctl(ctl_table *table, i if (newlen != sizeof(int)) return -EINVAL; - if (get_user(new_cm, (int *)newval)) + if (get_user(new_cm, (int __user *)newval)) return -EFAULT; return try_set_cm(new_cm)?:1; diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 0fff8a6..489e6c4 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -246,7 +246,7 @@ int copy_thread(int nr, unsigned long cl /* * sys_execve() executes a new program. */ -asmlinkage int sys_execve(char *name, char **argv, char **envp) +asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp) { int error; char * filename; diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index 5908dea..1f7d65f 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c @@ -814,7 +814,7 @@ #endif * - by now the stack is part of the init task */ printk("Memory %08lx-%08lx\n", memory_start, memory_end); - if (memory_start == memory_end) BUG(); + BUG_ON(memory_start == memory_end); init_mm.start_code = (unsigned long) &_stext; init_mm.end_code = (unsigned long) &_etext; diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 679c1d5..b8a5882 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -98,7 +98,7 @@ int sys_sigaltstack(const stack_t __user struct sigframe { - void (*pretcode)(void); + __sigrestore_t pretcode; int sig; struct sigcontext sc; unsigned long extramask[_NSIG_WORDS-1]; @@ -107,10 +107,10 @@ struct sigframe struct rt_sigframe { - void (*pretcode)(void); + __sigrestore_t pretcode; int sig; - struct siginfo *pinfo; - void *puc; + struct siginfo __user *pinfo; + void __user *puc; struct siginfo info; struct ucontext uc; uint32_t retcode[2]; @@ -233,7 +233,7 @@ static inline void __user *get_sigframe( /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (! on_sig_stack(sp)) + if (! sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; } @@ -284,7 +284,7 @@ static int setup_frame(int sig, struct k * setlos #__NR_sigreturn,gr7 * tira gr0,0 */ - if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) || + if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) || __put_user(0xc0700000, &frame->retcode[1])) goto give_sigsegv; @@ -300,7 +300,7 @@ static int setup_frame(int sig, struct k if (get_personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = - (struct fdpic_func_descriptor *) ka->sa.sa_handler; + (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; __get_user(__frame->pc, &funcptr->text); __get_user(__frame->gr15, &funcptr->GOT); } else { @@ -359,8 +359,8 @@ static int setup_rt_frame(int sig, struc /* Create the ucontext. */ if (__put_user(0, &frame->uc.uc_flags) || - __put_user(0, &frame->uc.uc_link) || - __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || + __put_user(NULL, &frame->uc.uc_link) || + __put_user((void __user *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) || __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size)) goto give_sigsegv; @@ -382,7 +382,7 @@ static int setup_rt_frame(int sig, struc * setlos #__NR_sigreturn,gr7 * tira gr0,0 */ - if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) || + if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) || __put_user(0xc0700000, &frame->retcode[1])) goto give_sigsegv; @@ -398,7 +398,7 @@ static int setup_rt_frame(int sig, struc __frame->gr9 = (unsigned long) &frame->info; if (get_personality & FDPIC_FUNCPTRS) { - struct fdpic_func_descriptor *funcptr = + struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; __get_user(__frame->pc, &funcptr->text); __get_user(__frame->gr15, &funcptr->GOT); diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c index 931aa6d..c4d4348 100644 --- a/arch/frv/kernel/sys_frv.c +++ b/arch/frv/kernel/sys_frv.c @@ -32,7 +32,7 @@ #include * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. */ -asmlinkage long sys_pipe(unsigned long * fildes) +asmlinkage long sys_pipe(unsigned long __user * fildes) { int fd[2]; int error; diff --git a/arch/frv/kernel/sysctl.c b/arch/frv/kernel/sysctl.c index 408b0f3..b908863 100644 --- a/arch/frv/kernel/sysctl.c +++ b/arch/frv/kernel/sysctl.c @@ -49,7 +49,7 @@ static void frv_change_dcache_mode(unsig * handle requests to dynamically switch the write caching mode delivered by /proc */ static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *ppos) + void __user *buffer, size_t *lenp, loff_t *ppos) { unsigned long hsr0; char buff[8]; @@ -123,7 +123,7 @@ static int procctl_frv_cachemode(ctl_tab */ #ifdef CONFIG_MMU static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *ppos) + void __user *buffer, size_t *lenp, loff_t *ppos) { pid_t pid; char buff[16], *p; diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c index 9b751c0..9fb771a 100644 --- a/arch/frv/kernel/uaccess.c +++ b/arch/frv/kernel/uaccess.c @@ -17,7 +17,7 @@ #include /* * copy a null terminated string from userspace */ -long strncpy_from_user(char *dst, const char *src, long count) +long strncpy_from_user(char *dst, const char __user *src, long count) { unsigned long max; char *p, ch; @@ -70,9 +70,9 @@ EXPORT_SYMBOL(strncpy_from_user); * * Return 0 on exception, a value greater than N if too long */ -long strnlen_user(const char *src, long count) +long strnlen_user(const char __user *src, long count) { - const char *p; + const char __user *p; long err = 0; char ch; diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c index c4a1144..45ae39d 100644 --- a/arch/frv/mb93090-mb00/pci-irq.c +++ b/arch/frv/mb93090-mb00/pci-irq.c @@ -32,11 +32,11 @@ #include "pci-frv.h" */ static const uint8_t __initdata pci_bus0_irq_routing[32][4] = { - [0 ] { IRQ_FPGA_MB86943_PCI_INTA }, - [16] { IRQ_FPGA_RTL8029_INTA }, - [17] { IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB }, - [18] { IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA }, - [19] { IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD }, + [0 ] = { IRQ_FPGA_MB86943_PCI_INTA }, + [16] = { IRQ_FPGA_RTL8029_INTA }, + [17] = { IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB }, + [18] = { IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA }, + [19] = { IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD }, }; void __init pcibios_irq_init(void) diff --git a/arch/frv/mm/kmap.c b/arch/frv/mm/kmap.c index c54f18e..40b62c5 100644 --- a/arch/frv/mm/kmap.c +++ b/arch/frv/mm/kmap.c @@ -31,15 +31,15 @@ #undef DEBUG * Map some physical address range into the kernel address space. */ -void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) +void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) { - return (void *)physaddr; + return (void __iomem *)physaddr; } /* * Unmap a ioremap()ed region again */ -void iounmap(void *addr) +void iounmap(void volatile __iomem *addr) { } diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c index f13d5e8..7787f70 100644 --- a/arch/h8300/kernel/signal.c +++ b/arch/h8300/kernel/signal.c @@ -307,7 +307,7 @@ get_sigframe(struct k_sigaction *ka, str /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (!on_sig_stack(usp)) + if (!sas_ss_flags(usp)) usp = current->sas_ss_sp + current->sas_ss_size; } return (void *)((usp - frame_size) & -8UL); diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 8dfa305..47c08bc 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -14,6 +14,10 @@ config X86_32 486, 586, Pentiums, and various instruction-set-compatible chips by AMD, Cyrix, and others. +config GENERIC_TIME + bool + default y + config SEMAPHORE_SLEEPERS bool default y @@ -173,6 +177,12 @@ config ACPI_SRAT bool default y depends on NUMA && (X86_SUMMIT || X86_GENERICARCH) + select ACPI_NUMA + +config HAVE_ARCH_PARSE_SRAT + bool + default y + depends on ACPI_SRAT config X86_SUMMIT_NUMA bool @@ -224,7 +234,6 @@ config NR_CPUS config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" depends on SMP - default off help SMT scheduler support improves the CPU scheduler's decision making when dealing with Intel Pentium 4 chips with HyperThreading at a @@ -319,6 +328,15 @@ config X86_MCE_P4THERMAL Enabling this feature will cause a message to be printed when the P4 enters thermal throttling. +config VM86 + default y + bool "Enable VM86 support" if EMBEDDED + help + This option is required by programs like DOSEMU to run 16-bit legacy + code on X86 processors. It also may be needed by software like + XFree86 to initialize some video cards via BIOS. Disabling this + option saves about 6k. + config TOSHIBA tristate "Toshiba Laptop support" ---help--- @@ -716,7 +734,7 @@ config KEXEC help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot - but it is indepedent of the system firmware. And like a reboot + but it is independent of the system firmware. And like a reboot you can start any kernel with it, not just Linux. The name comes from the similiarity to the exec system call. @@ -1041,13 +1059,27 @@ config SCx200 tristate "NatSemi SCx200 support" depends on !X86_VOYAGER help - This provides basic support for the National Semiconductor SCx200 - processor. Right now this is just a driver for the GPIO pins. + This provides basic support for National Semiconductor's + (now AMD's) Geode processors. The driver probes for the + PCI-IDs of several on-chip devices, so its a good dependency + for other scx200_* drivers. - If you don't know what to do here, say N. + If compiled as a module, the driver is named scx200. + +config SCx200HR_TIMER + tristate "NatSemi SCx200 27MHz High-Resolution Timer Support" + depends on SCx200 && GENERIC_TIME + default y + help + This driver provides a clocksource built upon the on-chip + 27MHz high-resolution timer. Its also a workaround for + NSC Geode SC-1100's buggy TSC, which loses time when the + processor goes idle (as is done by the scheduler). The + other workaround is idle=poll boot option. - This support is also available as a module. If compiled as a - module, it will be called scx200. +config K8_NB + def_bool y + depends on AGP_AMD64 source "drivers/pcmcia/Kconfig" diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu index eb13048..21c9a4e 100644 --- a/arch/i386/Kconfig.cpu +++ b/arch/i386/Kconfig.cpu @@ -41,7 +41,7 @@ config M386 - "GeodeGX1" for Geode GX1 (Cyrix MediaGX). - "Geode GX/LX" For AMD Geode GX and LX processors. - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. - - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above). + - "VIA C3-2" for VIA C3-2 "Nehemiah" (model 9 and above). If you don't know what to do, choose "386". diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile index 33e5547..e979466 100644 --- a/arch/i386/boot/Makefile +++ b/arch/i386/boot/Makefile @@ -109,8 +109,13 @@ fdimage288: $(BOOTIMAGE) $(obj)/mtools.c isoimage: $(BOOTIMAGE) -rm -rf $(obj)/isoimage mkdir $(obj)/isoimage - cp `echo /usr/lib*/syslinux/isolinux.bin | awk '{ print $1; }'` \ - $(obj)/isoimage + for i in lib lib64 share end ; do \ + if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \ + cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \ + break ; \ + fi ; \ + if [ $$i = end ] ; then exit 1 ; fi ; \ + done cp $(BOOTIMAGE) $(obj)/isoimage/linux echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg if [ -f '$(FDINITRD)' ] ; then \ diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index f19f3a7..b2ccd54 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c @@ -24,14 +24,6 @@ #define STATIC static #undef memset #undef memcpy - -/* - * Why do we do this? Don't ask me.. - * - * Incomprehensible are the ways of bootloaders. - */ -static void* memset(void *, int, size_t); -static void* memcpy(void *, __const void *, size_t); #define memzero(s, n) memset ((s), 0, (n)) typedef unsigned char uch; @@ -93,7 +85,7 @@ #define RM_ALT_MEM_K (*(unsigned long #endif #define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0)) -extern char input_data[]; +extern unsigned char input_data[]; extern int input_len; static long bytes_out = 0; @@ -103,6 +95,9 @@ static unsigned long output_ptr = 0; static void *malloc(int size); static void free(void *where); +static void *memset(void *s, int c, unsigned n); +static void *memcpy(void *dest, const void *src, unsigned n); + static void putstr(const char *); extern int end; @@ -205,7 +200,7 @@ static void putstr(const char *s) outb_p(0xff & (pos >> 1), vidport+1); } -static void* memset(void* s, int c, size_t n) +static void* memset(void* s, int c, unsigned n) { int i; char *ss = (char*)s; @@ -214,14 +209,13 @@ static void* memset(void* s, int c, size return s; } -static void* memcpy(void* __dest, __const void* __src, - size_t __n) +static void* memcpy(void* dest, const void* src, unsigned n) { int i; - char *d = (char *)__dest, *s = (char *)__src; + char *d = (char *)dest, *s = (char *)src; - for (i=0;i<__n;i++) d[i] = s[i]; - return __dest; + for (i=0;i RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory"); #endif - output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */ + output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */ free_mem_end_ptr = (long)real_mode; } @@ -324,11 +318,9 @@ static void setup_output_buffer_if_we_ru #ifdef STANDARD_MEMORY_BIOS_CALL if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory"); #else - if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < - (3*1024)) - error("Less than 4MB of memory"); + if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory"); #endif - mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START; + mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START; low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff; low_buffer_size = low_buffer_end - LOW_BUFFER_START; diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S index c9343c3..8c2a6fa 100644 --- a/arch/i386/boot/video.S +++ b/arch/i386/boot/video.S @@ -1929,7 +1929,7 @@ skip10: movb %ah, %al ret store_edid: -#ifdef CONFIG_FB_FIRMWARE_EDID +#ifdef CONFIG_FIRMWARE_EDID pushw %es # just save all registers pushw %ax pushw %bx @@ -1947,6 +1947,22 @@ #ifdef CONFIG_FB_FIRMWARE_EDID rep stosl + pushw %es # save ES + xorw %di, %di # Report Capability + pushw %di + popw %es # ES:DI must be 0:0 + movw $0x4f15, %ax + xorw %bx, %bx + xorw %cx, %cx + int $0x10 + popw %es # restore ES + + cmpb $0x00, %ah # call successful + jne no_edid + + cmpb $0x4f, %al # function supported + jne no_edid + movw $0x4f15, %ax # do VBE/DDC movw $0x01, %bx movw $0x00, %cx @@ -1954,6 +1970,7 @@ #ifdef CONFIG_FB_FIRMWARE_EDID movw $0x140, %di int $0x10 +no_edid: popw %di # restore all registers popw %dx popw %cx diff --git a/arch/i386/crypto/aes-i586-asm.S b/arch/i386/crypto/aes-i586-asm.S index 911b153..f942f0c 100644 --- a/arch/i386/crypto/aes-i586-asm.S +++ b/arch/i386/crypto/aes-i586-asm.S @@ -36,22 +36,19 @@ .file "aes-i586-asm.S" .text -// aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])// -// aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])// - -#define tlen 1024 // length of each of 4 'xor' arrays (256 32-bit words) +#include -// offsets to parameters with one register pushed onto stack - -#define in_blk 8 // input byte array address parameter -#define out_blk 12 // output byte array address parameter -#define ctx 16 // AES context structure +#define tlen 1024 // length of each of 4 'xor' arrays (256 32-bit words) -// offsets in context structure +/* offsets to parameters with one register pushed onto stack */ +#define tfm 8 +#define out_blk 12 +#define in_blk 16 -#define ekey 0 // encryption key schedule base address -#define nrnd 256 // number of rounds -#define dkey 260 // decryption key schedule base address +/* offsets in crypto_tfm structure */ +#define ekey (crypto_tfm_ctx_offset + 0) +#define nrnd (crypto_tfm_ctx_offset + 256) +#define dkey (crypto_tfm_ctx_offset + 260) // register mapping for encrypt and decrypt subroutines @@ -220,6 +217,7 @@ #define inv_rnd2(arg, table) \ do_col (table, r5,r0,r1,r4, r2,r3); /* idx=r5 */ // AES (Rijndael) Encryption Subroutine +/* void aes_enc_blk(struct crypto_tfm *tfm, u8 *out_blk, const u8 *in_blk) */ .global aes_enc_blk @@ -230,7 +228,7 @@ #define inv_rnd2(arg, table) \ aes_enc_blk: push %ebp - mov ctx(%esp),%ebp // pointer to context + mov tfm(%esp),%ebp // CAUTION: the order and the values used in these assigns // rely on the register mappings @@ -295,6 +293,7 @@ #endif ret // AES (Rijndael) Decryption Subroutine +/* void aes_dec_blk(struct crypto_tfm *tfm, u8 *out_blk, const u8 *in_blk) */ .global aes_dec_blk @@ -305,7 +304,7 @@ #endif aes_dec_blk: push %ebp - mov ctx(%esp),%ebp // pointer to context + mov tfm(%esp),%ebp // CAUTION: the order and the values used in these assigns // rely on the register mappings diff --git a/arch/i386/crypto/aes.c b/arch/i386/crypto/aes.c index a50397b..d3806da 100644 --- a/arch/i386/crypto/aes.c +++ b/arch/i386/crypto/aes.c @@ -45,8 +45,8 @@ #include #include #include -asmlinkage void aes_enc_blk(const u8 *src, u8 *dst, void *ctx); -asmlinkage void aes_dec_blk(const u8 *src, u8 *dst, void *ctx); +asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src); +asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src); #define AES_MIN_KEY_SIZE 16 #define AES_MAX_KEY_SIZE 32 @@ -378,12 +378,12 @@ #define kdl8(k,i) \ k[8*(i)+11] = ss[3]; \ } -static int -aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) +static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len, u32 *flags) { int i; u32 ss[8]; - struct aes_ctx *ctx = ctx_arg; + struct aes_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *key = (const __le32 *)in_key; /* encryption schedule */ @@ -464,16 +464,16 @@ aes_set_key(void *ctx_arg, const u8 *in_ return 0; } -static inline void aes_encrypt(void *ctx, u8 *dst, const u8 *src) +static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - aes_enc_blk(src, dst, ctx); + aes_enc_blk(tfm, dst, src); } -static inline void aes_decrypt(void *ctx, u8 *dst, const u8 *src) + +static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - aes_dec_blk(src, dst, ctx); + aes_dec_blk(tfm, dst, src); } - static struct crypto_alg aes_alg = { .cra_name = "aes", .cra_driver_name = "aes-i586", diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 96fb8a0..5e70c2f 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -7,10 +7,9 @@ extra-y := head.o init_task.o vmlinux.ld obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ pci-dma.o i386_ksyms.o i387.o bootflag.o \ - quirks.o i8237.o topology.o alternative.o + quirks.o i8237.o topology.o alternative.o i8253.o tsc.o obj-y += cpu/ -obj-y += timers/ obj-y += acpi/ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca.o @@ -37,6 +36,8 @@ obj-$(CONFIG_EFI) += efi.o efi_stub.o obj-$(CONFIG_DOUBLEFAULT) += doublefault.o obj-$(CONFIG_VM86) += vm86.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +obj-$(CONFIG_HPET_TIMER) += hpet.o +obj-$(CONFIG_K8_NB) += k8.o EXTRA_AFLAGS := -traditional @@ -76,3 +77,6 @@ SYSCFLAGS_vsyscall-syms.o = -r $(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \ $(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE $(call if_changed,syscall) + +k8-y += ../../x86_64/kernel/k8.o + diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 40e5aba..97ca171 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -202,6 +202,8 @@ int __init acpi_parse_mcfg(unsigned long if (mcfg->config[i].base_reserved) { printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n"); + kfree(pci_mmcfg_config); + pci_mmcfg_config_num = 0; return -ENODEV; } } @@ -215,7 +217,7 @@ static int __init acpi_parse_madt(unsign { struct acpi_table_madt *madt = NULL; - if (!phys_addr || !size) + if (!phys_addr || !size || !cpu_has_apic) return -EINVAL; madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size); @@ -621,9 +623,9 @@ #endif static int __init acpi_parse_fadt(unsigned long phys, unsigned long size) { - struct fadt_descriptor_rev2 *fadt = NULL; + struct fadt_descriptor *fadt = NULL; - fadt = (struct fadt_descriptor_rev2 *)__acpi_map_table(phys, size); + fadt = (struct fadt_descriptor *)__acpi_map_table(phys, size); if (!fadt) { printk(KERN_WARNING PREFIX "Unable to map FADT\n"); return 0; @@ -754,7 +756,7 @@ static int __init acpi_parse_madt_ioapic return -ENODEV; } - if (!cpu_has_apic) + if (!cpu_has_apic) return -ENODEV; /* diff --git a/arch/i386/kernel/acpi/processor.c b/arch/i386/kernel/acpi/processor.c index 9f4cc02..b54fded 100644 --- a/arch/i386/kernel/acpi/processor.c +++ b/arch/i386/kernel/acpi/processor.c @@ -47,7 +47,7 @@ static void init_intel_pdc(struct acpi_p buf[2] = ACPI_PDC_C_CAPABILITY_SMP; if (cpu_has(c, X86_FEATURE_EST)) - buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; + buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP; obj->type = ACPI_TYPE_BUFFER; obj->buffer.length = 12; diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c index 1cb2b18..4ee8357 100644 --- a/arch/i386/kernel/acpi/sleep.c +++ b/arch/i386/kernel/acpi/sleep.c @@ -8,30 +8,17 @@ #include #include #include +#include + #include -#include /* address in low memory of the wakeup routine. */ unsigned long acpi_wakeup_address = 0; unsigned long acpi_video_flags; extern char wakeup_start, wakeup_end; -extern void zap_low_mappings(void); - extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long)); -static void init_low_mapping(pgd_t * pgd, int pgd_limit) -{ - int pgd_ofs = 0; - - while ((pgd_ofs < pgd_limit) - && (pgd_ofs + USER_PTRS_PER_PGD < PTRS_PER_PGD)) { - set_pgd(pgd, *(pgd + USER_PTRS_PER_PGD)); - pgd_ofs++, pgd++; - } - flush_tlb_all(); -} - /** * acpi_save_state_mem - save kernel state * @@ -42,7 +29,6 @@ int acpi_save_state_mem(void) { if (!acpi_wakeup_address) return 1; - init_low_mapping(swapper_pg_dir, USER_PTRS_PER_PGD); memcpy((void *)acpi_wakeup_address, &wakeup_start, &wakeup_end - &wakeup_start); acpi_copy_wakeup_routine(acpi_wakeup_address); @@ -55,7 +41,6 @@ int acpi_save_state_mem(void) */ void acpi_restore_state_mem(void) { - zap_low_mappings(); } /** diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S index 7c74fe0..9f408ee 100644 --- a/arch/i386/kernel/acpi/wakeup.S +++ b/arch/i386/kernel/acpi/wakeup.S @@ -56,7 +56,7 @@ wakeup_code: 1: # set up page table - movl $swapper_pg_dir-__PAGE_OFFSET, %eax + movl $swsusp_pg_dir-__PAGE_OFFSET, %eax movl %eax, %cr3 testl $1, real_efer_save_restore - wakeup_code @@ -265,11 +265,6 @@ ENTRY(acpi_copy_wakeup_routine) movl $0x12345678, saved_magic ret -.data -ALIGN -ENTRY(saved_magic) .long 0 -ENTRY(saved_eip) .long 0 - save_registers: leal 4(%esp), %eax movl %eax, saved_context_esp @@ -304,7 +299,11 @@ ret_point: call restore_processor_state ret +.data ALIGN +ENTRY(saved_magic) .long 0 +ENTRY(saved_eip) .long 0 + # saved registers saved_gdt: .long 0,0 saved_idt: .long 0,0 diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c index 5cbd6f9..50eb0e0 100644 --- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c @@ -4,27 +4,41 @@ #include #include #include -#define DEBUG 0 -#if DEBUG -# define DPRINTK(fmt, args...) printk(fmt, args) -#else -# define DPRINTK(fmt, args...) -#endif +static int no_replacement = 0; +static int smp_alt_once = 0; +static int debug_alternative = 0; + +static int __init noreplacement_setup(char *s) +{ + no_replacement = 1; + return 1; +} +static int __init bootonly(char *str) +{ + smp_alt_once = 1; + return 1; +} +static int __init debug_alt(char *str) +{ + debug_alternative = 1; + return 1; +} +__setup("noreplacement", noreplacement_setup); +__setup("smp-alt-boot", bootonly); +__setup("debug-alternative", debug_alt); + +#define DPRINTK(fmt, args...) if (debug_alternative) \ + printk(KERN_DEBUG fmt, args) + +#ifdef GENERIC_NOP1 /* Use inline assembly to define this because the nops are defined as inline assembly strings in the include files and we cannot get them easily into strings. */ asm("\t.data\nintelnops: " GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6 GENERIC_NOP7 GENERIC_NOP8); -asm("\t.data\nk8nops: " - K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6 - K8_NOP7 K8_NOP8); -asm("\t.data\nk7nops: " - K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6 - K7_NOP7 K7_NOP8); - -extern unsigned char intelnops[], k8nops[], k7nops[]; +extern unsigned char intelnops[]; static unsigned char *intel_nops[ASM_NOP_MAX+1] = { NULL, intelnops, @@ -36,6 +50,13 @@ static unsigned char *intel_nops[ASM_NOP intelnops + 1 + 2 + 3 + 4 + 5 + 6, intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7, }; +#endif + +#ifdef K8_NOP1 +asm("\t.data\nk8nops: " + K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6 + K8_NOP7 K8_NOP8); +extern unsigned char k8nops[]; static unsigned char *k8_nops[ASM_NOP_MAX+1] = { NULL, k8nops, @@ -47,6 +68,13 @@ static unsigned char *k8_nops[ASM_NOP_MA k8nops + 1 + 2 + 3 + 4 + 5 + 6, k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, }; +#endif + +#ifdef K7_NOP1 +asm("\t.data\nk7nops: " + K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6 + K7_NOP7 K7_NOP8); +extern unsigned char k7nops[]; static unsigned char *k7_nops[ASM_NOP_MAX+1] = { NULL, k7nops, @@ -58,6 +86,18 @@ static unsigned char *k7_nops[ASM_NOP_MA k7nops + 1 + 2 + 3 + 4 + 5 + 6, k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, }; +#endif + +#ifdef CONFIG_X86_64 + +extern char __vsyscall_0; +static inline unsigned char** find_nop_table(void) +{ + return k8_nops; +} + +#else /* CONFIG_X86_64 */ + static struct nop { int cpuid; unsigned char **noptable; @@ -67,14 +107,6 @@ static struct nop { { -1, NULL } }; - -extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; -extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[]; -extern u8 *__smp_locks[], *__smp_locks_end[]; - -extern u8 __smp_alt_begin[], __smp_alt_end[]; - - static unsigned char** find_nop_table(void) { unsigned char **noptable = intel_nops; @@ -89,6 +121,14 @@ static unsigned char** find_nop_table(vo return noptable; } +#endif /* CONFIG_X86_64 */ + +extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; +extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[]; +extern u8 *__smp_locks[], *__smp_locks_end[]; + +extern u8 __smp_alt_begin[], __smp_alt_end[]; + /* Replace instructions with better alternatives for this CPU type. This runs before SMP is initialized to avoid SMP problems with self modifying code. This implies that assymetric systems where @@ -99,6 +139,7 @@ void apply_alternatives(struct alt_instr { unsigned char **noptable = find_nop_table(); struct alt_instr *a; + u8 *instr; int diff, i, k; DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end); @@ -106,7 +147,16 @@ void apply_alternatives(struct alt_instr BUG_ON(a->replacementlen > a->instrlen); if (!boot_cpu_has(a->cpuid)) continue; - memcpy(a->instr, a->replacement, a->replacementlen); + instr = a->instr; +#ifdef CONFIG_X86_64 + /* vsyscall code is not mapped yet. resolve it manually. */ + if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) { + instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0)); + DPRINTK("%s: vsyscall fixup: %p => %p\n", + __FUNCTION__, a->instr, instr); + } +#endif + memcpy(instr, a->replacement, a->replacementlen); diff = a->instrlen - a->replacementlen; /* Pad the rest with nops */ for (i = a->replacementlen; diff > 0; diff -= k, i += k) { @@ -186,14 +236,6 @@ struct smp_alt_module { static LIST_HEAD(smp_alt_modules); static DEFINE_SPINLOCK(smp_alt); -static int smp_alt_once = 0; -static int __init bootonly(char *str) -{ - smp_alt_once = 1; - return 1; -} -__setup("smp-alt-boot", bootonly); - void alternatives_smp_module_add(struct module *mod, char *name, void *locks, void *locks_end, void *text, void *text_end) @@ -201,6 +243,9 @@ void alternatives_smp_module_add(struct struct smp_alt_module *smp; unsigned long flags; + if (no_replacement) + return; + if (smp_alt_once) { if (boot_cpu_has(X86_FEATURE_UP)) alternatives_smp_unlock(locks, locks_end, @@ -235,7 +280,7 @@ void alternatives_smp_module_del(struct struct smp_alt_module *item; unsigned long flags; - if (smp_alt_once) + if (no_replacement || smp_alt_once) return; spin_lock_irqsave(&smp_alt, flags); @@ -256,7 +301,7 @@ void alternatives_smp_switch(int smp) struct smp_alt_module *mod; unsigned long flags; - if (smp_alt_once) + if (no_replacement || smp_alt_once) return; BUG_ON(!smp && (num_online_cpus() > 1)); @@ -285,6 +330,13 @@ void alternatives_smp_switch(int smp) void __init alternative_instructions(void) { + if (no_replacement) { + printk(KERN_INFO "(SMP-)alternatives turned off\n"); + free_init_pages("SMP alternatives", + (unsigned long)__smp_alt_begin, + (unsigned long)__smp_alt_end); + return; + } apply_alternatives(__alt_instructions, __alt_instructions_end); /* switch to patch-once-at-boottime-only mode and free the diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 3d4b2f3..7ce0949 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -36,6 +36,7 @@ #include #include #include #include +#include #include #include @@ -62,7 +63,7 @@ int apic_verbosity; static void apic_pm_activate(void); -int modern_apic(void) +static int modern_apic(void) { unsigned int lvr, version; /* AMD systems use old APIC versions, so check the CPU */ @@ -113,7 +114,7 @@ #endif } /* Using APIC to generate smp_local_timer_interrupt? */ -int using_apic_timer = 0; +int using_apic_timer __read_mostly = 0; static int enabled_via_apicbase; @@ -156,7 +157,7 @@ void clear_local_APIC(void) maxlvt = get_maxlvt(); /* - * Masking an LVT entry on a P6 can trigger a local APIC error + * Masking an LVT entry can trigger a local APIC error * if the vector is zero. Mask LVTERR first to prevent this. */ if (maxlvt >= 3) { @@ -1117,7 +1118,18 @@ void disable_APIC_timer(void) unsigned long v; v = apic_read(APIC_LVTT); - apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED); + /* + * When an illegal vector value (0-15) is written to an LVT + * entry and delivery mode is Fixed, the APIC may signal an + * illegal vector error, with out regard to whether the mask + * bit is set or whether an interrupt is actually seen on input. + * + * Boot sequence might call this function when the LVTT has + * '0' vector value. So make sure vector field is set to + * valid value. + */ + v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); + apic_write_around(APIC_LVTT, v); } } diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index df0e174..7c5729d 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -374,14 +374,14 @@ static struct { unsigned short segment; } apm_bios_entry; static int clock_slowed; -static int idle_threshold = DEFAULT_IDLE_THRESHOLD; -static int idle_period = DEFAULT_IDLE_PERIOD; +static int idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD; +static int idle_period __read_mostly = DEFAULT_IDLE_PERIOD; static int set_pm_idle; static int suspends_pending; static int standbys_pending; static int ignore_sys_suspend; static int ignore_normal_resume; -static int bounce_interval = DEFAULT_BOUNCE_INTERVAL; +static int bounce_interval __read_mostly = DEFAULT_BOUNCE_INTERVAL; #ifdef CONFIG_APM_RTC_IS_GMT # define clock_cmos_diff 0 @@ -390,8 +390,8 @@ #else static long clock_cmos_diff; static int got_clock_diff; #endif -static int debug; -static int smp; +static int debug __read_mostly; +static int smp __read_mostly; static int apm_disabled = -1; #ifdef CONFIG_SMP static int power_off; @@ -403,8 +403,8 @@ static int realmode_power_off = 1; #else static int realmode_power_off; #endif -static int exit_kapmd; -static int kapmd_running; +static int exit_kapmd __read_mostly; +static int kapmd_running __read_mostly; #ifdef CONFIG_APM_ALLOW_INTS static int allow_ints = 1; #else @@ -416,15 +416,15 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitq static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); static struct apm_user * user_list; static DEFINE_SPINLOCK(user_list_lock); -static struct desc_struct bad_bios_desc = { 0, 0x00409200 }; +static const struct desc_struct bad_bios_desc = { 0, 0x00409200 }; -static char driver_version[] = "1.16ac"; /* no spaces */ +static const char driver_version[] = "1.16ac"; /* no spaces */ /* * APM event names taken from the APM 1.2 specification. These are * the message codes that the BIOS uses to tell us about events */ -static char * apm_event_name[] = { +static const char * const apm_event_name[] = { "system standby", "system suspend", "normal resume", @@ -616,7 +616,7 @@ static u8 apm_bios_call(u32 func, u32 eb * @ecx_in: ECX register value for BIOS call * @eax: EAX register on return from the BIOS call * - * Make a BIOS call that does only returns one value, or just status. + * Make a BIOS call that returns one value only, or just status. * If there is an error, then the error code is returned in AH * (bits 8-15 of eax) and this function returns non-zero. This is * used for simpler BIOS operations. This call may hold interrupts @@ -764,9 +764,9 @@ static int apm_do_idle(void) int idled = 0; int polling; - polling = test_thread_flag(TIF_POLLING_NRFLAG); + polling = !!(current_thread_info()->status & TS_POLLING); if (polling) { - clear_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status &= ~TS_POLLING; smp_mb__after_clear_bit(); } if (!need_resched()) { @@ -774,7 +774,7 @@ static int apm_do_idle(void) ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax); } if (polling) - set_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status |= TS_POLLING; if (!idled) return 0; @@ -822,7 +822,7 @@ static void apm_do_busy(void) #define IDLE_CALC_LIMIT (HZ * 100) #define IDLE_LEAKY_MAX 16 -static void (*original_pm_idle)(void); +static void (*original_pm_idle)(void) __read_mostly; /** * apm_cpu_idle - cpu idling for APM capable Linux @@ -1063,7 +1063,8 @@ #if defined(CONFIG_APM_DISPLAY_BLANK) && static int apm_console_blank(int blank) { - int error, i; + int error = APM_NOT_ENGAGED; /* silence gcc */ + int i; u_short state; static const u_short dev[3] = { 0x100, 0x1FF, 0x101 }; @@ -1104,7 +1105,8 @@ static int queue_empty(struct apm_user * static apm_event_t get_queued_event(struct apm_user *as) { - as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; + if (++as->event_tail >= APM_MAX_EVENTS) + as->event_tail = 0; return as->events[as->event_tail]; } @@ -1118,13 +1120,16 @@ static void queue_event(apm_event_t even for (as = user_list; as != NULL; as = as->next) { if ((as == sender) || (!as->reader)) continue; - as->event_head = (as->event_head + 1) % APM_MAX_EVENTS; + if (++as->event_head >= APM_MAX_EVENTS) + as->event_head = 0; + if (as->event_head == as->event_tail) { static int notified; if (notified++ == 0) printk(KERN_ERR "apm: an event queue overflowed\n"); - as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; + if (++as->event_tail >= APM_MAX_EVENTS) + as->event_tail = 0; } as->events[as->event_head] = event; if ((!as->suser) || (!as->writer)) @@ -1282,7 +1287,7 @@ static void standby(void) static apm_event_t get_event(void) { int error; - apm_event_t event; + apm_event_t event = APM_NO_EVENTS; /* silence gcc */ apm_eventinfo_t info; static int notified; diff --git a/arch/i386/kernel/asm-offsets.c b/arch/i386/kernel/asm-offsets.c index 36d66e2..1c3a809 100644 --- a/arch/i386/kernel/asm-offsets.c +++ b/arch/i386/kernel/asm-offsets.c @@ -4,6 +4,7 @@ * to extract and format the required data. */ +#include #include #include #include @@ -69,4 +70,6 @@ void foo(void) DEFINE(PAGE_SIZE_asm, PAGE_SIZE); DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL)); + + OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx); } diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 786d1a5..fd0457c 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -224,15 +224,17 @@ #define CBAR_KEY (0X000000CB) #ifdef CONFIG_X86_HT /* - * On a AMD dual core setup the lower bits of the APIC id - * distingush the cores. Assumes number of cores is a power - * of two. + * On a AMD multi core setup the lower bits of the APIC id + * distingush the cores. */ if (c->x86_max_cores > 1) { int cpu = smp_processor_id(); - unsigned bits = 0; - while ((1 << bits) < c->x86_max_cores) - bits++; + unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf; + + if (bits == 0) { + while ((1 << bits) < c->x86_max_cores) + bits++; + } cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<>= bits; printk(KERN_INFO "CPU %d(%d) -> Core %d\n", @@ -240,6 +242,8 @@ #ifdef CONFIG_X86_HT } #endif + if (cpuid_eax(0x80000000) >= 0x80000006) + num_cache_leaves = 3; } static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index a06a490..44f2c5f 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -11,6 +11,8 @@ #include #include #include #include +#include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #include diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 3852d0a..5fd6532 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -48,12 +48,13 @@ MODULE_LICENSE("GPL"); struct cpufreq_acpi_io { - struct acpi_processor_performance acpi_data; + struct acpi_processor_performance *acpi_data; struct cpufreq_frequency_table *freq_table; unsigned int resume; }; static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS]; +static struct acpi_processor_performance *acpi_perf_data[NR_CPUS]; static struct cpufreq_driver acpi_cpufreq_driver; @@ -104,64 +105,43 @@ acpi_processor_set_performance ( { u16 port = 0; u8 bit_width = 0; + int i = 0; int ret = 0; u32 value = 0; - int i = 0; - struct cpufreq_freqs cpufreq_freqs; - cpumask_t saved_mask; int retval; + struct acpi_processor_performance *perf; dprintk("acpi_processor_set_performance\n"); - /* - * TBD: Use something other than set_cpus_allowed. - * As set_cpus_allowed is a bit racy, - * with any other set_cpus_allowed for this process. - */ - saved_mask = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - if (smp_processor_id() != cpu) { - return (-EAGAIN); - } - - if (state == data->acpi_data.state) { + retval = 0; + perf = data->acpi_data; + if (state == perf->state) { if (unlikely(data->resume)) { dprintk("Called after resume, resetting to P%d\n", state); data->resume = 0; } else { dprintk("Already at target state (P%d)\n", state); - retval = 0; - goto migrate_end; + return (retval); } } - dprintk("Transitioning from P%d to P%d\n", - data->acpi_data.state, state); - - /* cpufreq frequency struct */ - cpufreq_freqs.cpu = cpu; - cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency; - cpufreq_freqs.new = data->freq_table[state].frequency; - - /* notify cpufreq */ - cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); + dprintk("Transitioning from P%d to P%d\n", perf->state, state); /* * First we write the target state's 'control' value to the * control_register. */ - port = data->acpi_data.control_register.address; - bit_width = data->acpi_data.control_register.bit_width; - value = (u32) data->acpi_data.states[state].control; + port = perf->control_register.address; + bit_width = perf->control_register.bit_width; + value = (u32) perf->states[state].control; dprintk("Writing 0x%08x to port 0x%04x\n", value, port); ret = acpi_processor_write_port(port, bit_width, value); if (ret) { dprintk("Invalid port width 0x%04x\n", bit_width); - retval = ret; - goto migrate_end; + return (ret); } /* @@ -177,49 +157,35 @@ acpi_processor_set_performance ( * before giving up. */ - port = data->acpi_data.status_register.address; - bit_width = data->acpi_data.status_register.bit_width; + port = perf->status_register.address; + bit_width = perf->status_register.bit_width; dprintk("Looking for 0x%08x from port 0x%04x\n", - (u32) data->acpi_data.states[state].status, port); + (u32) perf->states[state].status, port); - for (i=0; i<100; i++) { + for (i = 0; i < 100; i++) { ret = acpi_processor_read_port(port, bit_width, &value); if (ret) { dprintk("Invalid port width 0x%04x\n", bit_width); - retval = ret; - goto migrate_end; + return (ret); } - if (value == (u32) data->acpi_data.states[state].status) + if (value == (u32) perf->states[state].status) break; udelay(10); } } else { - i = 0; - value = (u32) data->acpi_data.states[state].status; + value = (u32) perf->states[state].status; } - /* notify cpufreq */ - cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); - - if (unlikely(value != (u32) data->acpi_data.states[state].status)) { - unsigned int tmp = cpufreq_freqs.new; - cpufreq_freqs.new = cpufreq_freqs.old; - cpufreq_freqs.old = tmp; - cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); - cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); + if (unlikely(value != (u32) perf->states[state].status)) { printk(KERN_WARNING "acpi-cpufreq: Transition failed\n"); retval = -ENODEV; - goto migrate_end; + return (retval); } dprintk("Transition successful after %d microseconds\n", i * 10); - data->acpi_data.state = state; - - retval = 0; -migrate_end: - set_cpus_allowed(current, saved_mask); + perf->state = state; return (retval); } @@ -231,8 +197,17 @@ acpi_cpufreq_target ( unsigned int relation) { struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; + struct acpi_processor_performance *perf; + struct cpufreq_freqs freqs; + cpumask_t online_policy_cpus; + cpumask_t saved_mask; + cpumask_t set_mask; + cpumask_t covered_cpus; + unsigned int cur_state = 0; unsigned int next_state = 0; unsigned int result = 0; + unsigned int j; + unsigned int tmp; dprintk("acpi_cpufreq_setpolicy\n"); @@ -241,11 +216,95 @@ acpi_cpufreq_target ( target_freq, relation, &next_state); - if (result) + if (unlikely(result)) return (result); - result = acpi_processor_set_performance (data, policy->cpu, next_state); + perf = data->acpi_data; + cur_state = perf->state; + freqs.old = data->freq_table[cur_state].frequency; + freqs.new = data->freq_table[next_state].frequency; + +#ifdef CONFIG_HOTPLUG_CPU + /* cpufreq holds the hotplug lock, so we are safe from here on */ + cpus_and(online_policy_cpus, cpu_online_map, policy->cpus); +#else + online_policy_cpus = policy->cpus; +#endif + + for_each_cpu_mask(j, online_policy_cpus) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + + /* + * We need to call driver->target() on all or any CPU in + * policy->cpus, depending on policy->shared_type. + */ + saved_mask = current->cpus_allowed; + cpus_clear(covered_cpus); + for_each_cpu_mask(j, online_policy_cpus) { + /* + * Support for SMP systems. + * Make sure we are running on CPU that wants to change freq + */ + cpus_clear(set_mask); + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + cpus_or(set_mask, set_mask, online_policy_cpus); + else + cpu_set(j, set_mask); + + set_cpus_allowed(current, set_mask); + if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) { + dprintk("couldn't limit to CPUs in this domain\n"); + result = -EAGAIN; + break; + } + + result = acpi_processor_set_performance (data, j, next_state); + if (result) { + result = -EAGAIN; + break; + } + + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + break; + + cpu_set(j, covered_cpus); + } + + for_each_cpu_mask(j, online_policy_cpus) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + if (unlikely(result)) { + /* + * We have failed halfway through the frequency change. + * We have sent callbacks to online_policy_cpus and + * acpi_processor_set_performance() has been called on + * coverd_cpus. Best effort undo.. + */ + + if (!cpus_empty(covered_cpus)) { + for_each_cpu_mask(j, covered_cpus) { + policy->cpu = j; + acpi_processor_set_performance (data, + j, + cur_state); + } + } + + tmp = freqs.new; + freqs.new = freqs.old; + freqs.old = tmp; + for_each_cpu_mask(j, online_policy_cpus) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + } + + set_cpus_allowed(current, saved_mask); return (result); } @@ -271,30 +330,65 @@ acpi_cpufreq_guess_freq ( struct cpufreq_acpi_io *data, unsigned int cpu) { + struct acpi_processor_performance *perf = data->acpi_data; + if (cpu_khz) { /* search the closest match to cpu_khz */ unsigned int i; unsigned long freq; - unsigned long freqn = data->acpi_data.states[0].core_frequency * 1000; + unsigned long freqn = perf->states[0].core_frequency * 1000; - for (i=0; i < (data->acpi_data.state_count - 1); i++) { + for (i = 0; i < (perf->state_count - 1); i++) { freq = freqn; - freqn = data->acpi_data.states[i+1].core_frequency * 1000; + freqn = perf->states[i+1].core_frequency * 1000; if ((2 * cpu_khz) > (freqn + freq)) { - data->acpi_data.state = i; + perf->state = i; return (freq); } } - data->acpi_data.state = data->acpi_data.state_count - 1; + perf->state = perf->state_count - 1; return (freqn); - } else + } else { /* assume CPU is at P0... */ - data->acpi_data.state = 0; - return data->acpi_data.states[0].core_frequency * 1000; - + perf->state = 0; + return perf->states[0].core_frequency * 1000; + } } +/* + * acpi_cpufreq_early_init - initialize ACPI P-States library + * + * Initialize the ACPI P-States library (drivers/acpi/processor_perflib.c) + * in order to determine correct frequency and voltage pairings. We can + * do _PDC and _PSD and find out the processor dependency for the + * actual init that will happen later... + */ +static int acpi_cpufreq_early_init_acpi(void) +{ + struct acpi_processor_performance *data; + unsigned int i, j; + + dprintk("acpi_cpufreq_early_init\n"); + + for_each_possible_cpu(i) { + data = kzalloc(sizeof(struct acpi_processor_performance), + GFP_KERNEL); + if (!data) { + for_each_possible_cpu(j) { + kfree(acpi_perf_data[j]); + acpi_perf_data[j] = NULL; + } + return (-ENOMEM); + } + acpi_perf_data[i] = data; + } + + /* Do initialization in ACPI core */ + acpi_processor_preregister_performance(acpi_perf_data); + return 0; +} + static int acpi_cpufreq_cpu_init ( struct cpufreq_policy *policy) @@ -304,41 +398,51 @@ acpi_cpufreq_cpu_init ( struct cpufreq_acpi_io *data; unsigned int result = 0; struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; + struct acpi_processor_performance *perf; dprintk("acpi_cpufreq_cpu_init\n"); + if (!acpi_perf_data[cpu]) + return (-ENODEV); + data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); if (!data) return (-ENOMEM); + data->acpi_data = acpi_perf_data[cpu]; acpi_io_data[cpu] = data; - result = acpi_processor_register_performance(&data->acpi_data, cpu); + result = acpi_processor_register_performance(data->acpi_data, cpu); if (result) goto err_free; + perf = data->acpi_data; + policy->cpus = perf->shared_cpu_map; + policy->shared_type = perf->shared_type; + if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; } /* capability check */ - if (data->acpi_data.state_count <= 1) { + if (perf->state_count <= 1) { dprintk("No P-States\n"); result = -ENODEV; goto err_unreg; } - if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) || - (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { + + if ((perf->control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) || + (perf->status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { dprintk("Unsupported address space [%d, %d]\n", - (u32) (data->acpi_data.control_register.space_id), - (u32) (data->acpi_data.status_register.space_id)); + (u32) (perf->control_register.space_id), + (u32) (perf->status_register.space_id)); result = -ENODEV; goto err_unreg; } /* alloc freq_table */ - data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (data->acpi_data.state_count + 1), GFP_KERNEL); + data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (perf->state_count + 1), GFP_KERNEL); if (!data->freq_table) { result = -ENOMEM; goto err_unreg; @@ -346,9 +450,9 @@ acpi_cpufreq_cpu_init ( /* detect transition latency */ policy->cpuinfo.transition_latency = 0; - for (i=0; iacpi_data.state_count; i++) { - if ((data->acpi_data.states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency) - policy->cpuinfo.transition_latency = data->acpi_data.states[i].transition_latency * 1000; + for (i=0; istate_count; i++) { + if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency) + policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000; } policy->governor = CPUFREQ_DEFAULT_GOVERNOR; @@ -356,11 +460,11 @@ acpi_cpufreq_cpu_init ( policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu); /* table init */ - for (i=0; i<=data->acpi_data.state_count; i++) + for (i=0; i<=perf->state_count; i++) { data->freq_table[i].index = i; - if (iacpi_data.state_count) - data->freq_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000; + if (istate_count) + data->freq_table[i].frequency = perf->states[i].core_frequency * 1000; else data->freq_table[i].frequency = CPUFREQ_TABLE_END; } @@ -375,12 +479,12 @@ acpi_cpufreq_cpu_init ( printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n", cpu); - for (i = 0; i < data->acpi_data.state_count; i++) + for (i = 0; i < perf->state_count; i++) dprintk(" %cP%d: %d MHz, %d mW, %d uS\n", - (i == data->acpi_data.state?'*':' '), i, - (u32) data->acpi_data.states[i].core_frequency, - (u32) data->acpi_data.states[i].power, - (u32) data->acpi_data.states[i].transition_latency); + (i == perf->state?'*':' '), i, + (u32) perf->states[i].core_frequency, + (u32) perf->states[i].power, + (u32) perf->states[i].transition_latency); cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu); @@ -395,7 +499,7 @@ acpi_cpufreq_cpu_init ( err_freqfree: kfree(data->freq_table); err_unreg: - acpi_processor_unregister_performance(&data->acpi_data, cpu); + acpi_processor_unregister_performance(perf, cpu); err_free: kfree(data); acpi_io_data[cpu] = NULL; @@ -416,7 +520,7 @@ acpi_cpufreq_cpu_exit ( if (data) { cpufreq_frequency_table_put_attr(policy->cpu); acpi_io_data[policy->cpu] = NULL; - acpi_processor_unregister_performance(&data->acpi_data, policy->cpu); + acpi_processor_unregister_performance(data->acpi_data, policy->cpu); kfree(data); } @@ -444,14 +548,15 @@ static struct freq_attr* acpi_cpufreq_at }; static struct cpufreq_driver acpi_cpufreq_driver = { - .verify = acpi_cpufreq_verify, - .target = acpi_cpufreq_target, - .init = acpi_cpufreq_cpu_init, - .exit = acpi_cpufreq_cpu_exit, - .resume = acpi_cpufreq_resume, - .name = "acpi-cpufreq", - .owner = THIS_MODULE, - .attr = acpi_cpufreq_attr, + .verify = acpi_cpufreq_verify, + .target = acpi_cpufreq_target, + .init = acpi_cpufreq_cpu_init, + .exit = acpi_cpufreq_cpu_exit, + .resume = acpi_cpufreq_resume, + .name = "acpi-cpufreq", + .owner = THIS_MODULE, + .attr = acpi_cpufreq_attr, + .flags = CPUFREQ_STICKY, }; @@ -462,7 +567,10 @@ acpi_cpufreq_init (void) dprintk("acpi_cpufreq_init\n"); - result = cpufreq_register_driver(&acpi_cpufreq_driver); + result = acpi_cpufreq_early_init_acpi(); + + if (!result) + result = cpufreq_register_driver(&acpi_cpufreq_driver); return (result); } @@ -471,10 +579,15 @@ acpi_cpufreq_init (void) static void __exit acpi_cpufreq_exit (void) { + unsigned int i; dprintk("acpi_cpufreq_exit\n"); cpufreq_unregister_driver(&acpi_cpufreq_driver); + for_each_possible_cpu(i) { + kfree(acpi_perf_data[i]); + acpi_perf_data[i] = NULL; + } return; } diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c index f275e0d..0d49d73 100644 --- a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c +++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c @@ -1,5 +1,5 @@ /* - * (C) 2004 Sebastian Witt + * (C) 2004-2006 Sebastian Witt * * Licensed under the terms of the GNU GPL License version 2. * Based upon reverse engineered information @@ -90,7 +90,7 @@ static int nforce2_calc_pll(unsigned int /* Try to calculate multiplier and divider up to 4 times */ while (((mul == 0) || (div == 0)) && (tried <= 3)) { - for (xdiv = 1; xdiv <= 0x80; xdiv++) + for (xdiv = 2; xdiv <= 0x80; xdiv++) for (xmul = 1; xmul <= 0xfe; xmul++) if (nforce2_calc_fsb(NFORCE2_PLL(xmul, xdiv)) == fsb + tried) { @@ -117,8 +117,7 @@ static void nforce2_write_pll(int pll) int temp; /* Set the pll addr. to 0x00 */ - temp = 0x00; - pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLADR, temp); + pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLADR, 0); /* Now write the value in all 64 registers */ for (temp = 0; temp <= 0x3f; temp++) @@ -266,7 +265,7 @@ static int nforce2_target(struct cpufreq if (freqs.old == freqs.new) return 0; - dprintk(KERN_INFO "cpufreq: Old CPU frequency %d kHz, new %d kHz\n", + dprintk("Old CPU frequency %d kHz, new %d kHz\n", freqs.old, freqs.new); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); @@ -278,7 +277,7 @@ static int nforce2_target(struct cpufreq printk(KERN_ERR "cpufreq: Changing FSB to %d failed\n", target_fsb); else - dprintk(KERN_INFO "cpufreq: Changed FSB successfully to %d\n", + dprintk("Changed FSB successfully to %d\n", target_fsb); /* Enable IRQs */ diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 8ef3854..146f607 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -77,13 +77,17 @@ static char speedbuffer[8]; static char *print_speed(int speed) { - if (speed > 1000) { - if (speed%1000 == 0) - sprintf (speedbuffer, "%dGHz", speed/1000); - else - sprintf (speedbuffer, "%d.%dGHz", speed/1000, (speed%1000)/100); - } else - sprintf (speedbuffer, "%dMHz", speed); + if (speed < 1000) { + snprintf(speedbuffer, sizeof(speedbuffer),"%dMHz", speed); + return speedbuffer; + } + + if (speed%1000 == 0) + snprintf(speedbuffer, sizeof(speedbuffer), + "%dGHz", speed/1000); + else + snprintf(speedbuffer, sizeof(speedbuffer), + "%d.%dGHz", speed/1000, (speed%1000)/100); return speedbuffer; } @@ -675,7 +679,7 @@ static int __init longhaul_init(void) static void __exit longhaul_exit(void) { - int i=0; + int i; for (i=0; i < numscales; i++) { if (clock_ratio[i] == maxmult) { diff --git a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c index e3868de..b268951 100644 --- a/arch/i386/kernel/cpu/cpufreq/longrun.c +++ b/arch/i386/kernel/cpu/cpufreq/longrun.c @@ -223,7 +223,6 @@ static unsigned int __init longrun_deter /* set to 0 to try_hi perf_pctg */ msr_lo &= 0xFFFFFF80; msr_hi &= 0xFFFFFF80; - msr_lo |= 0; msr_hi |= try_hi; wrmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi); diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 2bf4237..694d479 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -452,23 +452,23 @@ static int powernow_decode_bios (int max pst = (struct pst_s *) p; - for (i = 0 ; i numpst; i++) { + for (j=0; jnumpst; j++) { pst = (struct pst_s *) p; number_scales = pst->numpstates; if ((etuple == pst->cpuid) && check_fsb(pst->fsbspeed) && (maxfid==pst->maxfid) && (startvid==pst->startvid)) { - dprintk ("PST:%d (@%p)\n", i, pst); + dprintk ("PST:%d (@%p)\n", j, pst); dprintk (" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n", pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid); ret = get_ranges ((char *) pst + sizeof (struct pst_s)); return ret; - } else { + unsigned int k; p = (char *) pst + sizeof (struct pst_s); - for (j=0 ; j < number_scales; j++) + for (k=0; k> did; +} + +static u32 find_khz_freq_from_fiddid(u32 fid, u32 did) { - return 1550-vid*25; + return 1000 * find_freq_from_fiddid(fid, did); +} + +static u32 find_fid_from_pstate(u32 pstate) +{ + u32 hi, lo; + rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi); + return lo & HW_PSTATE_FID_MASK; +} + +static u32 find_did_from_pstate(u32 pstate) +{ + u32 hi, lo; + rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi); + return (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT; } /* Return the vco fid for an input fid @@ -98,6 +120,9 @@ static int pending_bit_stuck(void) { u32 lo, hi; + if (cpu_family == CPU_HW_PSTATE) + return 0; + rdmsr(MSR_FIDVID_STATUS, lo, hi); return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0; } @@ -111,6 +136,14 @@ static int query_current_values_with_pen u32 lo, hi; u32 i = 0; + if (cpu_family == CPU_HW_PSTATE) { + rdmsr(MSR_PSTATE_STATUS, lo, hi); + i = lo & HW_PSTATE_MASK; + rdmsr(MSR_PSTATE_DEF_BASE + i, lo, hi); + data->currfid = lo & HW_PSTATE_FID_MASK; + data->currdid = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT; + return 0; + } do { if (i++ > 10000) { dprintk("detected change pending stuck\n"); @@ -175,7 +208,7 @@ static int write_new_fid(struct powernow do { wrmsr(MSR_FIDVID_CTL, lo, data->plllock * PLL_LOCK_CONVERSION); if (i++ > 100) { - printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n"); + printk(KERN_ERR PFX "Hardware error - pending bit very stuck - no further pstate changes possible\n"); return 1; } } while (query_current_values_with_pending_wait(data)); @@ -255,7 +288,15 @@ static int decrease_vid_code_by_step(str return 0; } -/* Change the fid and vid, by the 3 phases. */ +/* Change hardware pstate by single MSR write */ +static int transition_pstate(struct powernow_k8_data *data, u32 pstate) +{ + wrmsr(MSR_PSTATE_CTRL, pstate, 0); + data->currfid = find_fid_from_pstate(pstate); + return 0; +} + +/* Change Opteron/Athlon64 fid and vid, by the 3 phases. */ static int transition_fid_vid(struct powernow_k8_data *data, u32 reqfid, u32 reqvid) { if (core_voltage_pre_transition(data, reqvid)) @@ -474,26 +515,35 @@ static int check_supported_cpu(unsigned goto out; eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); - if ((eax & CPUID_XFAM) != CPUID_XFAM_K8) + if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) && + ((eax & CPUID_XFAM) < CPUID_XFAM_10H)) goto out; - if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || - ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) { - printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax); - goto out; - } + if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) { + if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || + ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) { + printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax); + goto out; + } - eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES); - if (eax < CPUID_FREQ_VOLT_CAPABILITIES) { - printk(KERN_INFO PFX - "No frequency change capabilities detected\n"); - goto out; - } + eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES); + if (eax < CPUID_FREQ_VOLT_CAPABILITIES) { + printk(KERN_INFO PFX + "No frequency change capabilities detected\n"); + goto out; + } - cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx); - if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) { - printk(KERN_INFO PFX "Power state transitions not supported\n"); - goto out; + cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx); + if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) { + printk(KERN_INFO PFX "Power state transitions not supported\n"); + goto out; + } + } else { /* must be a HW Pstate capable processor */ + cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx); + if ((edx & USE_HW_PSTATE) == USE_HW_PSTATE) + cpu_family = CPU_HW_PSTATE; + else + goto out; } rc = 1; @@ -547,12 +597,18 @@ static void print_basics(struct powernow { int j; for (j = 0; j < data->numps; j++) { - if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) - printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x (%d mV)\n", j, + if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) { + if (cpu_family == CPU_HW_PSTATE) { + printk(KERN_INFO PFX " %d : fid 0x%x gid 0x%x (%d MHz)\n", j, (data->powernow_table[j].index & 0xff00) >> 8, + (data->powernow_table[j].index & 0xff0000) >> 16, + data->powernow_table[j].frequency/1000); + } else { + printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", j, data->powernow_table[j].index & 0xff, data->powernow_table[j].frequency/1000, - data->powernow_table[j].index >> 8, - find_millivolts_from_vid(data, data->powernow_table[j].index >> 8)); + data->powernow_table[j].index >> 8); + } + } } if (data->batps) printk(KERN_INFO PFX "Only %d pstates on battery\n", data->batps); @@ -702,7 +758,7 @@ static int find_psb_table(struct powerno #ifdef CONFIG_X86_POWERNOW_K8_ACPI static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) { - if (!data->acpi_data.state_count) + if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE)) return; data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK; @@ -715,9 +771,8 @@ static void powernow_k8_acpi_pst_values( static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) { - int i; - int cntlofreq = 0; struct cpufreq_frequency_table *powernow_table; + int ret_val; if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { dprintk("register performance failed: bad ACPI data\n"); @@ -746,13 +801,92 @@ static int powernow_k8_cpu_init_acpi(str goto err_out; } + if (cpu_family == CPU_HW_PSTATE) + ret_val = fill_powernow_table_pstate(data, powernow_table); + else + ret_val = fill_powernow_table_fidvid(data, powernow_table); + if (ret_val) + goto err_out_mem; + + powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END; + powernow_table[data->acpi_data.state_count].index = 0; + data->powernow_table = powernow_table; + + /* fill in data */ + data->numps = data->acpi_data.state_count; + print_basics(data); + powernow_k8_acpi_pst_values(data, 0); + + /* notify BIOS that we exist */ + acpi_processor_notify_smm(THIS_MODULE); + + return 0; + +err_out_mem: + kfree(powernow_table); + +err_out: + acpi_processor_unregister_performance(&data->acpi_data, data->cpu); + + /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */ + data->acpi_data.state_count = 0; + + return -ENODEV; +} + +static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table) +{ + int i; + + for (i = 0; i < data->acpi_data.state_count; i++) { + u32 index; + u32 hi = 0, lo = 0; + u32 fid; + u32 did; + + index = data->acpi_data.states[i].control & HW_PSTATE_MASK; + if (index > MAX_HW_PSTATE) { + printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index); + printk(KERN_ERR PFX "Please report to BIOS manufacturer\n"); + } + rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi); + if (!(hi & HW_PSTATE_VALID_MASK)) { + dprintk("invalid pstate %d, ignoring\n", index); + powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; + continue; + } + + fid = lo & HW_PSTATE_FID_MASK; + did = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT; + + dprintk(" %d : fid 0x%x, did 0x%x\n", index, fid, did); + + powernow_table[i].index = index | (fid << HW_FID_INDEX_SHIFT) | (did << HW_DID_INDEX_SHIFT); + + powernow_table[i].frequency = find_khz_freq_from_fiddid(fid, did); + + if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) { + printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n", + powernow_table[i].frequency, + (unsigned int) (data->acpi_data.states[i].core_frequency * 1000)); + powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; + continue; + } + } + return 0; +} + +static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table) +{ + int i; + int cntlofreq = 0; for (i = 0; i < data->acpi_data.state_count; i++) { u32 fid; u32 vid; if (data->exttype) { - fid = data->acpi_data.states[i].status & FID_MASK; - vid = (data->acpi_data.states[i].status >> VID_SHIFT) & VID_MASK; + fid = data->acpi_data.states[i].status & EXT_FID_MASK; + vid = (data->acpi_data.states[i].status >> VID_SHIFT) & EXT_VID_MASK; } else { fid = data->acpi_data.states[i].control & FID_MASK; vid = (data->acpi_data.states[i].control >> VID_SHIFT) & VID_MASK; @@ -786,7 +920,7 @@ static int powernow_k8_cpu_init_acpi(str if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) || (powernow_table[i].index != powernow_table[cntlofreq].index)) { printk(KERN_ERR PFX "Too many lo freq table entries\n"); - goto err_out_mem; + return 1; } dprintk("double low frequency table entry, ignoring it.\n"); @@ -804,31 +938,7 @@ static int powernow_k8_cpu_init_acpi(str continue; } } - - powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END; - powernow_table[data->acpi_data.state_count].index = 0; - data->powernow_table = powernow_table; - - /* fill in data */ - data->numps = data->acpi_data.state_count; - print_basics(data); - powernow_k8_acpi_pst_values(data, 0); - - /* notify BIOS that we exist */ - acpi_processor_notify_smm(THIS_MODULE); - return 0; - -err_out_mem: - kfree(powernow_table); - -err_out: - acpi_processor_unregister_performance(&data->acpi_data, data->cpu); - - /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */ - data->acpi_data.state_count = 0; - - return -ENODEV; } static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) @@ -844,20 +954,20 @@ static void powernow_k8_acpi_pst_values( #endif /* CONFIG_X86_POWERNOW_K8_ACPI */ /* Take a frequency, and issue the fid/vid transition command */ -static int transition_frequency(struct powernow_k8_data *data, unsigned int index) +static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned int index) { - u32 fid; - u32 vid; + u32 fid = 0; + u32 vid = 0; int res, i; struct cpufreq_freqs freqs; dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); + /* fid/vid correctness check for k8 */ /* fid are the lower 8 bits of the index we stored into - * the cpufreq frequency table in find_psb_table, vid are - * the upper 8 bits. + * the cpufreq frequency table in find_psb_table, vid + * are the upper 8 bits. */ - fid = data->powernow_table[index].index & 0xFF; vid = (data->powernow_table[index].index & 0xFF00) >> 8; @@ -881,22 +991,58 @@ static int transition_frequency(struct p dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n", smp_processor_id(), fid, vid); - - freqs.cpu = data->cpu; freqs.old = find_khz_freq_from_fid(data->currfid); freqs.new = find_khz_freq_from_fid(fid); - for_each_cpu_mask(i, cpu_core_map[data->cpu]) { + + for_each_cpu_mask(i, *(data->available_cores)) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); } res = transition_fid_vid(data, fid, vid); - freqs.new = find_khz_freq_from_fid(data->currfid); - for_each_cpu_mask(i, cpu_core_map[data->cpu]) { + + for_each_cpu_mask(i, *(data->available_cores)) { freqs.cpu = i; cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - } + } + return res; +} + +/* Take a frequency, and issue the hardware pstate transition command */ +static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned int index) +{ + u32 fid = 0; + u32 did = 0; + u32 pstate = 0; + int res, i; + struct cpufreq_freqs freqs; + + dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); + + /* get fid did for hardware pstate transition */ + pstate = index & HW_PSTATE_MASK; + if (pstate > MAX_HW_PSTATE) + return 0; + fid = (index & HW_FID_INDEX_MASK) >> HW_FID_INDEX_SHIFT; + did = (index & HW_DID_INDEX_MASK) >> HW_DID_INDEX_SHIFT; + freqs.old = find_khz_freq_from_fiddid(data->currfid, data->currdid); + freqs.new = find_khz_freq_from_fiddid(fid, did); + + for_each_cpu_mask(i, *(data->available_cores)) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } + + res = transition_pstate(data, pstate); + data->currfid = find_fid_from_pstate(pstate); + data->currdid = find_did_from_pstate(pstate); + freqs.new = find_khz_freq_from_fiddid(data->currfid, data->currdid); + + for_each_cpu_mask(i, *(data->available_cores)) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } return res; } @@ -933,18 +1079,21 @@ static int powernowk8_target(struct cpuf dprintk("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n", pol->cpu, targfreq, pol->min, pol->max, relation); - if (query_current_values_with_pending_wait(data)) { - ret = -EIO; + if (query_current_values_with_pending_wait(data)) goto err_out; - } - dprintk("targ: curr fid 0x%x, vid 0x%x\n", + if (cpu_family == CPU_HW_PSTATE) + dprintk("targ: curr fid 0x%x, did 0x%x\n", + data->currfid, data->currvid); + else { + dprintk("targ: curr fid 0x%x, vid 0x%x\n", data->currfid, data->currvid); - if ((checkvid != data->currvid) || (checkfid != data->currfid)) { - printk(KERN_INFO PFX - "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n", - checkfid, data->currfid, checkvid, data->currvid); + if ((checkvid != data->currvid) || (checkfid != data->currfid)) { + printk(KERN_INFO PFX + "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n", + checkfid, data->currfid, checkvid, data->currvid); + } } if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) @@ -954,7 +1103,11 @@ static int powernowk8_target(struct cpuf powernow_k8_acpi_pst_values(data, newstate); - if (transition_frequency(data, newstate)) { + if (cpu_family == CPU_HW_PSTATE) + ret = transition_frequency_pstate(data, newstate); + else + ret = transition_frequency_fidvid(data, newstate); + if (ret) { printk(KERN_ERR PFX "transition frequency failed\n"); ret = 1; mutex_unlock(&fidvid_mutex); @@ -962,7 +1115,10 @@ static int powernowk8_target(struct cpuf } mutex_unlock(&fidvid_mutex); - pol->cur = find_khz_freq_from_fid(data->currfid); + if (cpu_family == CPU_HW_PSTATE) + pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid); + else + pol->cur = find_khz_freq_from_fid(data->currfid); ret = 0; err_out: @@ -1007,14 +1163,13 @@ static int __cpuinit powernowk8_cpu_init * Use the PSB BIOS structure. This is only availabe on * an UP version, and is deprecated by AMD. */ - - if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) { + if (num_online_cpus() != 1) { printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n"); kfree(data); return -ENODEV; } if (pol->cpu != 0) { - printk(KERN_ERR PFX "init not cpu 0\n"); + printk(KERN_ERR PFX "No _PSS objects for CPU other than CPU0\n"); kfree(data); return -ENODEV; } @@ -1042,20 +1197,28 @@ static int __cpuinit powernowk8_cpu_init if (query_current_values_with_pending_wait(data)) goto err_out; - fidvid_msr_init(); + if (cpu_family == CPU_OPTERON) + fidvid_msr_init(); /* run on any CPU again */ set_cpus_allowed(current, oldmask); pol->governor = CPUFREQ_DEFAULT_GOVERNOR; - pol->cpus = cpu_core_map[pol->cpu]; + if (cpu_family == CPU_HW_PSTATE) + pol->cpus = cpumask_of_cpu(pol->cpu); + else + pol->cpus = cpu_core_map[pol->cpu]; + data->available_cores = &(pol->cpus); /* Take a crude guess here. * That guess was in microseconds, so multiply with 1000 */ pol->cpuinfo.transition_latency = (((data->rvo + 8) * data->vstable * VST_UNITS_20US) + (3 * (1 << data->irt) * 10)) * 1000; - pol->cur = find_khz_freq_from_fid(data->currfid); + if (cpu_family == CPU_HW_PSTATE) + pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid); + else + pol->cur = find_khz_freq_from_fid(data->currfid); dprintk("policy current frequency %d kHz\n", pol->cur); /* min/max the cpu is capable of */ @@ -1069,8 +1232,12 @@ static int __cpuinit powernowk8_cpu_init cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); - printk("cpu_init done, current fid 0x%x, vid 0x%x\n", - data->currfid, data->currvid); + if (cpu_family == CPU_HW_PSTATE) + dprintk("cpu_init done, current fid 0x%x, did 0x%x\n", + data->currfid, data->currdid); + else + dprintk("cpu_init done, current fid 0x%x, vid 0x%x\n", + data->currfid, data->currvid); powernow_data[pol->cpu] = data; @@ -1156,8 +1323,9 @@ static int __cpuinit powernowk8_init(voi } if (supported_cpus == num_online_cpus()) { - printk(KERN_INFO PFX "Found %d AMD Athlon 64 / Opteron " - "processors (" VERSION ")\n", supported_cpus); + printk(KERN_INFO PFX "Found %d %s " + "processors (" VERSION ")\n", supported_cpus, + boot_cpu_data.x86_model_id); return cpufreq_register_driver(&cpufreq_amd64_driver); } diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index 79a7c5c..0fb2a30 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h @@ -1,5 +1,5 @@ /* - * (c) 2003, 2004, 2005 Advanced Micro Devices, Inc. + * (c) 2003-2006 Advanced Micro Devices, Inc. * Your use of this code is subject to the terms and conditions of the * GNU general public license version 2. See "COPYING" or * http://www.gnu.org/licenses/gpl.html @@ -21,8 +21,8 @@ struct powernow_k8_data { u32 plllock; /* pll lock time, units 1 us */ u32 exttype; /* extended interface = 1 */ - /* keep track of the current fid / vid */ - u32 currvid, currfid; + /* keep track of the current fid / vid or did */ + u32 currvid, currfid, currdid; /* the powernow_table includes all frequency and vid/fid pairings: * fid are the lower 8 bits of the index, vid are the upper 8 bits. @@ -34,6 +34,10 @@ #ifdef CONFIG_X86_POWERNOW_K8_ACPI * used to determine valid frequency/vid/fid states */ struct acpi_processor_performance acpi_data; #endif + /* we need to keep track of associated cores, but let cpufreq + * handle hotplug events - so just point at cpufreq pol->cpus + * structure */ + cpumask_t *available_cores; }; @@ -43,6 +47,7 @@ #define CPUID_XFAM 0x0ff00000 /* exten #define CPUID_XFAM_K8 0 #define CPUID_XMOD 0x000f0000 /* extended model */ #define CPUID_XMOD_REV_G 0x00060000 +#define CPUID_XFAM_10H 0x00100000 /* family 0x10 */ #define CPUID_USE_XFAM_XMOD 0x00000f00 #define CPUID_GET_MAX_CAPABILITIES 0x80000000 #define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 @@ -79,6 +84,32 @@ #define MSR_S_HI_START_VID 0x0000 #define MSR_S_HI_CURRENT_VID 0x0000003f #define MSR_C_HI_STP_GNT_BENIGN 0x00000001 + +/* Hardware Pstate _PSS and MSR definitions */ +#define USE_HW_PSTATE 0x00000080 +#define HW_PSTATE_FID_MASK 0x0000003f +#define HW_PSTATE_DID_MASK 0x000001c0 +#define HW_PSTATE_DID_SHIFT 6 +#define HW_PSTATE_MASK 0x00000007 +#define HW_PSTATE_VALID_MASK 0x80000000 +#define HW_FID_INDEX_SHIFT 8 +#define HW_FID_INDEX_MASK 0x0000ff00 +#define HW_DID_INDEX_SHIFT 16 +#define HW_DID_INDEX_MASK 0x00ff0000 +#define HW_WATTS_MASK 0xff +#define HW_PWR_DVR_MASK 0x300 +#define HW_PWR_DVR_SHIFT 8 +#define HW_PWR_MAX_MULT 3 +#define MAX_HW_PSTATE 8 /* hw pstate supports up to 8 */ +#define MSR_PSTATE_DEF_BASE 0xc0010064 /* base of Pstate MSRs */ +#define MSR_PSTATE_STATUS 0xc0010063 /* Pstate Status MSR */ +#define MSR_PSTATE_CTRL 0xc0010062 /* Pstate control MSR */ + +/* define the two driver architectures */ +#define CPU_OPTERON 0 +#define CPU_HW_PSTATE 1 + + /* * There are restrictions frequencies have to follow: * - only 1 entry in the low fid table ( <=1.4GHz ) @@ -138,7 +169,9 @@ #define PLL_L_MASK 0x7f #define MVS_MASK 3 #define VST_MASK 0x7f #define VID_MASK 0x1f -#define FID_MASK 0x3f +#define FID_MASK 0x1f +#define EXT_VID_MASK 0x3f +#define EXT_FID_MASK 0x3f /* @@ -182,6 +215,9 @@ static int core_frequency_transition(str static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index); +static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table); +static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table); + #ifdef CONFIG_SMP static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[]) { diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index b0ff907..f7e4356 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -2,19 +2,15 @@ * cpufreq driver for Enhanced SpeedStep, as found in Intel's Pentium * M (part of the Centrino chipset). * + * Since the original Pentium M, most new Intel CPUs support Enhanced + * SpeedStep. + * * Despite the "SpeedStep" in the name, this is almost entirely unlike * traditional SpeedStep. * * Modelled on speedstep.c * * Copyright (C) 2003 Jeremy Fitzhardinge - * - * WARNING WARNING WARNING - * - * This driver manipulates the PERF_CTL MSR, which is only somewhat - * documented. While it seems to work on my laptop, it has not been - * tested anywhere else, and it may not work for you, do strange - * things or simply crash. */ #include @@ -36,7 +32,7 @@ #include #include #define PFX "speedstep-centrino: " -#define MAINTAINER "Jeremy Fitzhardinge " +#define MAINTAINER "cpufreq@lists.linux.org.uk" #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg) @@ -250,7 +246,7 @@ static int centrino_cpu_init_table(struc if (model->cpu_id == NULL) { /* No match at all */ - dprintk(KERN_INFO PFX "no support for CPU model \"%s\": " + dprintk("no support for CPU model \"%s\": " "send /proc/cpuinfo to " MAINTAINER "\n", cpu->x86_model_id); return -ENOENT; @@ -258,10 +254,10 @@ static int centrino_cpu_init_table(struc if (model->op_points == NULL) { /* Matched a non-match */ - dprintk(KERN_INFO PFX "no table support for CPU model \"%s\"\n", + dprintk("no table support for CPU model \"%s\"\n", cpu->x86_model_id); #ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI - dprintk(KERN_INFO PFX "try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n"); + dprintk("try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n"); #endif return -ENOENT; } @@ -351,7 +347,36 @@ static unsigned int get_cur_freq(unsigne #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI -static struct acpi_processor_performance p; +static struct acpi_processor_performance *acpi_perf_data[NR_CPUS]; + +/* + * centrino_cpu_early_init_acpi - Do the preregistering with ACPI P-States + * library + * + * Before doing the actual init, we need to do _PSD related setup whenever + * supported by the BIOS. These are handled by this early_init routine. + */ +static int centrino_cpu_early_init_acpi(void) +{ + unsigned int i, j; + struct acpi_processor_performance *data; + + for_each_possible_cpu(i) { + data = kzalloc(sizeof(struct acpi_processor_performance), + GFP_KERNEL); + if (!data) { + for_each_possible_cpu(j) { + kfree(acpi_perf_data[j]); + acpi_perf_data[j] = NULL; + } + return (-ENOMEM); + } + acpi_perf_data[i] = data; + } + + acpi_processor_preregister_performance(acpi_perf_data); + return 0; +} /* * centrino_cpu_init_acpi - register with ACPI P-States library @@ -365,46 +390,51 @@ static int centrino_cpu_init_acpi(struct unsigned long cur_freq; int result = 0, i; unsigned int cpu = policy->cpu; + struct acpi_processor_performance *p; + + p = acpi_perf_data[cpu]; /* register with ACPI core */ - if (acpi_processor_register_performance(&p, cpu)) { - dprintk(KERN_INFO PFX "obtaining ACPI data failed\n"); + if (acpi_processor_register_performance(p, cpu)) { + dprintk(PFX "obtaining ACPI data failed\n"); return -EIO; } + policy->cpus = p->shared_cpu_map; + policy->shared_type = p->shared_type; /* verify the acpi_data */ - if (p.state_count <= 1) { + if (p->state_count <= 1) { dprintk("No P-States\n"); result = -ENODEV; goto err_unreg; } - if ((p.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || - (p.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { + if ((p->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || + (p->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { dprintk("Invalid control/status registers (%x - %x)\n", - p.control_register.space_id, p.status_register.space_id); + p->control_register.space_id, p->status_register.space_id); result = -EIO; goto err_unreg; } - for (i=0; istate_count; i++) { + if (p->states[i].control != p->states[i].status) { dprintk("Different control (%llu) and status values (%llu)\n", - p.states[i].control, p.states[i].status); + p->states[i].control, p->states[i].status); result = -EINVAL; goto err_unreg; } - if (!p.states[i].core_frequency) { + if (!p->states[i].core_frequency) { dprintk("Zero core frequency for state %u\n", i); result = -EINVAL; goto err_unreg; } - if (p.states[i].core_frequency > p.states[0].core_frequency) { + if (p->states[i].core_frequency > p->states[0].core_frequency) { dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i, - p.states[i].core_frequency, p.states[0].core_frequency); - p.states[i].core_frequency = 0; + p->states[i].core_frequency, p->states[0].core_frequency); + p->states[i].core_frequency = 0; continue; } } @@ -416,26 +446,26 @@ static int centrino_cpu_init_acpi(struct } centrino_model[cpu]->model_name=NULL; - centrino_model[cpu]->max_freq = p.states[0].core_frequency * 1000; + centrino_model[cpu]->max_freq = p->states[0].core_frequency * 1000; centrino_model[cpu]->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) * - (p.state_count + 1), GFP_KERNEL); + (p->state_count + 1), GFP_KERNEL); if (!centrino_model[cpu]->op_points) { result = -ENOMEM; goto err_kfree; } - for (i=0; iop_points[i].index = p.states[i].control; - centrino_model[cpu]->op_points[i].frequency = p.states[i].core_frequency * 1000; + for (i=0; istate_count; i++) { + centrino_model[cpu]->op_points[i].index = p->states[i].control; + centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000; dprintk("adding state %i with frequency %u and control value %04x\n", i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index); } - centrino_model[cpu]->op_points[p.state_count].frequency = CPUFREQ_TABLE_END; + centrino_model[cpu]->op_points[p->state_count].frequency = CPUFREQ_TABLE_END; cur_freq = get_cur_freq(cpu); - for (i=0; istate_count; i++) { + if (!p->states[i].core_frequency) { dprintk("skipping state %u\n", i); centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID; continue; @@ -451,7 +481,7 @@ static int centrino_cpu_init_acpi(struct } if (cur_freq == centrino_model[cpu]->op_points[i].frequency) - p.state = i; + p->state = i; } /* notify BIOS that we exist */ @@ -464,12 +494,13 @@ static int centrino_cpu_init_acpi(struct err_kfree: kfree(centrino_model[cpu]); err_unreg: - acpi_processor_unregister_performance(&p, cpu); - dprintk(KERN_INFO PFX "invalid ACPI data\n"); + acpi_processor_unregister_performance(p, cpu); + dprintk(PFX "invalid ACPI data\n"); return (result); } #else static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; } +static inline int centrino_cpu_early_init_acpi(void) { return 0; } #endif static int centrino_cpu_init(struct cpufreq_policy *policy) @@ -499,7 +530,7 @@ static int centrino_cpu_init(struct cpuf centrino_cpu[policy->cpu] = &cpu_ids[i]; if (!centrino_cpu[policy->cpu]) { - dprintk(KERN_INFO PFX "found unsupported CPU with " + dprintk("found unsupported CPU with " "Enhanced SpeedStep: send /proc/cpuinfo to " MAINTAINER "\n"); return -ENODEV; @@ -555,10 +586,15 @@ static int centrino_cpu_exit(struct cpuf #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI if (!centrino_model[cpu]->model_name) { - dprintk("unregistering and freeing ACPI data\n"); - acpi_processor_unregister_performance(&p, cpu); - kfree(centrino_model[cpu]->op_points); - kfree(centrino_model[cpu]); + static struct acpi_processor_performance *p; + + if (acpi_perf_data[cpu]) { + p = acpi_perf_data[cpu]; + dprintk("unregistering and freeing ACPI data\n"); + acpi_processor_unregister_performance(p, cpu); + kfree(centrino_model[cpu]->op_points); + kfree(centrino_model[cpu]); + } } #endif @@ -592,63 +628,128 @@ static int centrino_target (struct cpufr unsigned int relation) { unsigned int newstate = 0; - unsigned int msr, oldmsr, h, cpu = policy->cpu; + unsigned int msr, oldmsr = 0, h = 0, cpu = policy->cpu; struct cpufreq_freqs freqs; + cpumask_t online_policy_cpus; cpumask_t saved_mask; - int retval; + cpumask_t set_mask; + cpumask_t covered_cpus; + int retval = 0; + unsigned int j, k, first_cpu, tmp; - if (centrino_model[cpu] == NULL) + if (unlikely(centrino_model[cpu] == NULL)) return -ENODEV; - /* - * Support for SMP systems. - * Make sure we are running on the CPU that wants to change frequency - */ - saved_mask = current->cpus_allowed; - set_cpus_allowed(current, policy->cpus); - if (!cpu_isset(smp_processor_id(), policy->cpus)) { - dprintk("couldn't limit to CPUs in this domain\n"); - return(-EAGAIN); + if (unlikely(cpufreq_frequency_table_target(policy, + centrino_model[cpu]->op_points, + target_freq, + relation, + &newstate))) { + return -EINVAL; } - if (cpufreq_frequency_table_target(policy, centrino_model[cpu]->op_points, target_freq, - relation, &newstate)) { - retval = -EINVAL; - goto migrate_end; - } +#ifdef CONFIG_HOTPLUG_CPU + /* cpufreq holds the hotplug lock, so we are safe from here on */ + cpus_and(online_policy_cpus, cpu_online_map, policy->cpus); +#else + online_policy_cpus = policy->cpus; +#endif - msr = centrino_model[cpu]->op_points[newstate].index; - rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); + saved_mask = current->cpus_allowed; + first_cpu = 1; + cpus_clear(covered_cpus); + for_each_cpu_mask(j, online_policy_cpus) { + /* + * Support for SMP systems. + * Make sure we are running on CPU that wants to change freq + */ + cpus_clear(set_mask); + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + cpus_or(set_mask, set_mask, online_policy_cpus); + else + cpu_set(j, set_mask); + + set_cpus_allowed(current, set_mask); + if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) { + dprintk("couldn't limit to CPUs in this domain\n"); + retval = -EAGAIN; + if (first_cpu) { + /* We haven't started the transition yet. */ + goto migrate_end; + } + break; + } - if (msr == (oldmsr & 0xffff)) { - retval = 0; - dprintk("no change needed - msr was and needs to be %x\n", oldmsr); - goto migrate_end; - } + msr = centrino_model[cpu]->op_points[newstate].index; + + if (first_cpu) { + rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); + if (msr == (oldmsr & 0xffff)) { + dprintk("no change needed - msr was and needs " + "to be %x\n", oldmsr); + retval = 0; + goto migrate_end; + } + + freqs.old = extract_clock(oldmsr, cpu, 0); + freqs.new = extract_clock(msr, cpu, 0); + + dprintk("target=%dkHz old=%d new=%d msr=%04x\n", + target_freq, freqs.old, freqs.new, msr); + + for_each_cpu_mask(k, online_policy_cpus) { + freqs.cpu = k; + cpufreq_notify_transition(&freqs, + CPUFREQ_PRECHANGE); + } + + first_cpu = 0; + /* all but 16 LSB are reserved, treat them with care */ + oldmsr &= ~0xffff; + msr &= 0xffff; + oldmsr |= msr; + } - freqs.cpu = cpu; - freqs.old = extract_clock(oldmsr, cpu, 0); - freqs.new = extract_clock(msr, cpu, 0); + wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + break; - dprintk("target=%dkHz old=%d new=%d msr=%04x\n", - target_freq, freqs.old, freqs.new, msr); + cpu_set(j, covered_cpus); + } - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + for_each_cpu_mask(k, online_policy_cpus) { + freqs.cpu = k; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } - /* all but 16 LSB are "reserved", so treat them with - care */ - oldmsr &= ~0xffff; - msr &= 0xffff; - oldmsr |= msr; + if (unlikely(retval)) { + /* + * We have failed halfway through the frequency change. + * We have sent callbacks to policy->cpus and + * MSRs have already been written on coverd_cpus. + * Best effort undo.. + */ - wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); + if (!cpus_empty(covered_cpus)) { + for_each_cpu_mask(j, covered_cpus) { + set_cpus_allowed(current, cpumask_of_cpu(j)); + wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); + } + } - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + tmp = freqs.new; + freqs.new = freqs.old; + freqs.old = tmp; + for_each_cpu_mask(j, online_policy_cpus) { + freqs.cpu = j; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + } - retval = 0; migrate_end: set_cpus_allowed(current, saved_mask); - return (retval); + return 0; } static struct freq_attr* centrino_attr[] = { @@ -690,12 +791,25 @@ static int __init centrino_init(void) if (!cpu_has(cpu, X86_FEATURE_EST)) return -ENODEV; + centrino_cpu_early_init_acpi(); + return cpufreq_register_driver(¢rino_driver); } static void __exit centrino_exit(void) { +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI + unsigned int j; +#endif + cpufreq_unregister_driver(¢rino_driver); + +#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI + for_each_possible_cpu(j) { + kfree(acpi_perf_data[j]); + acpi_perf_data[j] = NULL; + } +#endif } MODULE_AUTHOR ("Jeremy Fitzhardinge "); diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c index 00f2e05..f03b7f9 100644 --- a/arch/i386/kernel/cpu/cyrix.c +++ b/arch/i386/kernel/cpu/cyrix.c @@ -184,7 +184,7 @@ static void __init geode_configure(void) #ifdef CONFIG_PCI -static struct pci_device_id cyrix_55x0[] = { +static struct pci_device_id __initdata cyrix_55x0[] = { { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510) }, { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520) }, { }, @@ -272,14 +272,15 @@ #ifdef CONFIG_PCI printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n"); isa_dma_bridge_buggy = 2; -#endif - c->x86_cache_size=16; /* Yep 16K integrated cache thats it */ - + + /* * The 5510/5520 companion chips have a funky PIT. */ if (pci_dev_present(cyrix_55x0)) pit_latch_buggy = 1; +#endif + c->x86_cache_size=16; /* Yep 16K integrated cache thats it */ /* GXm supports extended cpuid levels 'ala' AMD */ if (c->cpuid_level == 2) { @@ -353,7 +354,7 @@ static void __init init_nsc(struct cpuin * This function only handles the GX processor, and kicks every * thing else to the Cyrix init function above - that should * cover any processors that might have been branded differently - * after NSC aquired Cyrix. + * after NSC acquired Cyrix. * * If this breaks your GX1 horribly, please e-mail * info-linux@ldcmail.amd.com to tell us. diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index 5386b29..10afc64 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c @@ -122,6 +122,12 @@ #endif select_idle_routine(c); l2 = init_intel_cacheinfo(c); + if (c->cpuid_level > 9 ) { + unsigned eax = cpuid_eax(10); + /* Check for version and the number of counters */ + if ((eax & 0xff) && (((eax>>8) & 0xff) > 1)) + set_bit(X86_FEATURE_ARCH_PERFMON, c->x86_capability); + } /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */ if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633) diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c index c8547a6..6c37b4f 100644 --- a/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/arch/i386/kernel/cpu/intel_cacheinfo.c @@ -4,6 +4,7 @@ * Changes: * Venkatesh Pallipadi : Adding cache identification through cpuid(4) * Ashok Raj : Work with CPU hotplug infrastructure. + * Andi Kleen : CPUID4 emulation on AMD. */ #include @@ -130,25 +131,111 @@ struct _cpuid4_info { cpumask_t shared_cpu_map; }; -static unsigned short num_cache_leaves; +unsigned short num_cache_leaves; + +/* AMD doesn't have CPUID4. Emulate it here to report the same + information to the user. This makes some assumptions about the machine: + No L3, L2 not shared, no SMT etc. that is currently true on AMD CPUs. + + In theory the TLBs could be reported as fake type (they are in "dummy"). + Maybe later */ +union l1_cache { + struct { + unsigned line_size : 8; + unsigned lines_per_tag : 8; + unsigned assoc : 8; + unsigned size_in_kb : 8; + }; + unsigned val; +}; + +union l2_cache { + struct { + unsigned line_size : 8; + unsigned lines_per_tag : 4; + unsigned assoc : 4; + unsigned size_in_kb : 16; + }; + unsigned val; +}; + +static unsigned short assocs[] = { + [1] = 1, [2] = 2, [4] = 4, [6] = 8, + [8] = 16, + [0xf] = 0xffff // ?? + }; +static unsigned char levels[] = { 1, 1, 2 }; +static unsigned char types[] = { 1, 2, 3 }; + +static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, + union _cpuid4_leaf_ebx *ebx, + union _cpuid4_leaf_ecx *ecx) +{ + unsigned dummy; + unsigned line_size, lines_per_tag, assoc, size_in_kb; + union l1_cache l1i, l1d; + union l2_cache l2; + + eax->full = 0; + ebx->full = 0; + ecx->full = 0; + + cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val); + cpuid(0x80000006, &dummy, &dummy, &l2.val, &dummy); + + if (leaf > 2 || !l1d.val || !l1i.val || !l2.val) + return; + + eax->split.is_self_initializing = 1; + eax->split.type = types[leaf]; + eax->split.level = levels[leaf]; + eax->split.num_threads_sharing = 0; + eax->split.num_cores_on_die = current_cpu_data.x86_max_cores - 1; + + if (leaf <= 1) { + union l1_cache *l1 = leaf == 0 ? &l1d : &l1i; + assoc = l1->assoc; + line_size = l1->line_size; + lines_per_tag = l1->lines_per_tag; + size_in_kb = l1->size_in_kb; + } else { + assoc = l2.assoc; + line_size = l2.line_size; + lines_per_tag = l2.lines_per_tag; + /* cpu_data has errata corrections for K7 applied */ + size_in_kb = current_cpu_data.x86_cache_size; + } + + if (assoc == 0xf) + eax->split.is_fully_associative = 1; + ebx->split.coherency_line_size = line_size - 1; + ebx->split.ways_of_associativity = assocs[assoc] - 1; + ebx->split.physical_line_partition = lines_per_tag - 1; + ecx->split.number_of_sets = (size_in_kb * 1024) / line_size / + (ebx->split.ways_of_associativity + 1) - 1; +} static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) { - unsigned int eax, ebx, ecx, edx; - union _cpuid4_leaf_eax cache_eax; + union _cpuid4_leaf_eax eax; + union _cpuid4_leaf_ebx ebx; + union _cpuid4_leaf_ecx ecx; + unsigned edx; - cpuid_count(4, index, &eax, &ebx, &ecx, &edx); - cache_eax.full = eax; - if (cache_eax.split.type == CACHE_TYPE_NULL) + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) + amd_cpuid4(index, &eax, &ebx, &ecx); + else + cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); + if (eax.split.type == CACHE_TYPE_NULL) return -EIO; /* better error ? */ - this_leaf->eax.full = eax; - this_leaf->ebx.full = ebx; - this_leaf->ecx.full = ecx; - this_leaf->size = (this_leaf->ecx.split.number_of_sets + 1) * - (this_leaf->ebx.split.coherency_line_size + 1) * - (this_leaf->ebx.split.physical_line_partition + 1) * - (this_leaf->ebx.split.ways_of_associativity + 1); + this_leaf->eax = eax; + this_leaf->ebx = ebx; + this_leaf->ecx = ecx; + this_leaf->size = (ecx.split.number_of_sets + 1) * + (ebx.split.coherency_line_size + 1) * + (ebx.split.physical_line_partition + 1) * + (ebx.split.ways_of_associativity + 1); return 0; } diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index f94cdb7..a19fcb2 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -52,7 +52,7 @@ static int show_cpuinfo(struct seq_file /* VIA/Cyrix/Centaur-defined */ NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c index 2b0cfce..48f0f62 100644 --- a/arch/i386/kernel/crash.c +++ b/arch/i386/kernel/crash.c @@ -114,19 +114,15 @@ static int crash_nmi_callback(struct pt_ atomic_dec(&waiting_for_crash_ipi); /* Assume hlt works */ halt(); - for(;;); + for (;;) + cpu_relax(); return 1; } -/* - * By using the NMI code instead of a vector we just sneak thru the - * word generator coming out with just what we want. AND it does - * not matter if clustered_apic_mode is set or not. - */ static void smp_send_nmi_allbutself(void) { - send_IPI_allbutself(APIC_DM_NMI); + send_IPI_allbutself(NMI_VECTOR); } static void nmi_shootdown_cpus(void) @@ -162,7 +158,7 @@ #endif void machine_crash_shutdown(struct pt_regs *regs) { /* This function is only called after the system - * has paniced or is otherwise in a critical state. + * has panicked or is otherwise in a critical state. * The minimum amount of code to allow a kexec'd kernel * to run successfully needs to happen here. * diff --git a/arch/i386/kernel/doublefault.c b/arch/i386/kernel/doublefault.c index 5edb1d3..b4d14c2 100644 --- a/arch/i386/kernel/doublefault.c +++ b/arch/i386/kernel/doublefault.c @@ -44,7 +44,8 @@ static void doublefault_fn(void) } } - for (;;) /* nothing */; + for (;;) + cpu_relax(); } struct tss_struct doublefault_tss __cacheline_aligned = { diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index cfc683f..e6e4506 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -48,6 +48,7 @@ #include #include #include #include +#include #include "irq_vectors.h" #define nr_syscalls ((syscall_table_size)/4) @@ -85,31 +86,67 @@ #endif #define SAVE_ALL \ cld; \ pushl %es; \ + CFI_ADJUST_CFA_OFFSET 4;\ + /*CFI_REL_OFFSET es, 0;*/\ pushl %ds; \ + CFI_ADJUST_CFA_OFFSET 4;\ + /*CFI_REL_OFFSET ds, 0;*/\ pushl %eax; \ + CFI_ADJUST_CFA_OFFSET 4;\ + CFI_REL_OFFSET eax, 0;\ pushl %ebp; \ + CFI_ADJUST_CFA_OFFSET 4;\ + CFI_REL_OFFSET ebp, 0;\ pushl %edi; \ + CFI_ADJUST_CFA_OFFSET 4;\ + CFI_REL_OFFSET edi, 0;\ pushl %esi; \ + CFI_ADJUST_CFA_OFFSET 4;\ + CFI_REL_OFFSET esi, 0;\ pushl %edx; \ + CFI_ADJUST_CFA_OFFSET 4;\ + CFI_REL_OFFSET edx, 0;\ pushl %ecx; \ + CFI_ADJUST_CFA_OFFSET 4;\ + CFI_REL_OFFSET ecx, 0;\ pushl %ebx; \ + CFI_ADJUST_CFA_OFFSET 4;\ + CFI_REL_OFFSET ebx, 0;\ movl $(__USER_DS), %edx; \ movl %edx, %ds; \ movl %edx, %es; #define RESTORE_INT_REGS \ popl %ebx; \ + CFI_ADJUST_CFA_OFFSET -4;\ + CFI_RESTORE ebx;\ popl %ecx; \ + CFI_ADJUST_CFA_OFFSET -4;\ + CFI_RESTORE ecx;\ popl %edx; \ + CFI_ADJUST_CFA_OFFSET -4;\ + CFI_RESTORE edx;\ popl %esi; \ + CFI_ADJUST_CFA_OFFSET -4;\ + CFI_RESTORE esi;\ popl %edi; \ + CFI_ADJUST_CFA_OFFSET -4;\ + CFI_RESTORE edi;\ popl %ebp; \ - popl %eax + CFI_ADJUST_CFA_OFFSET -4;\ + CFI_RESTORE ebp;\ + popl %eax; \ + CFI_ADJUST_CFA_OFFSET -4;\ + CFI_RESTORE eax #define RESTORE_REGS \ RESTORE_INT_REGS; \ 1: popl %ds; \ + CFI_ADJUST_CFA_OFFSET -4;\ + /*CFI_RESTORE ds;*/\ 2: popl %es; \ + CFI_ADJUST_CFA_OFFSET -4;\ + /*CFI_RESTORE es;*/\ .section .fixup,"ax"; \ 3: movl $0,(%esp); \ jmp 1b; \ @@ -122,13 +159,43 @@ #define RESTORE_REGS \ .long 2b,4b; \ .previous +#define RING0_INT_FRAME \ + CFI_STARTPROC simple;\ + CFI_DEF_CFA esp, 3*4;\ + /*CFI_OFFSET cs, -2*4;*/\ + CFI_OFFSET eip, -3*4 + +#define RING0_EC_FRAME \ + CFI_STARTPROC simple;\ + CFI_DEF_CFA esp, 4*4;\ + /*CFI_OFFSET cs, -2*4;*/\ + CFI_OFFSET eip, -3*4 + +#define RING0_PTREGS_FRAME \ + CFI_STARTPROC simple;\ + CFI_DEF_CFA esp, OLDESP-EBX;\ + /*CFI_OFFSET cs, CS-OLDESP;*/\ + CFI_OFFSET eip, EIP-OLDESP;\ + /*CFI_OFFSET es, ES-OLDESP;*/\ + /*CFI_OFFSET ds, DS-OLDESP;*/\ + CFI_OFFSET eax, EAX-OLDESP;\ + CFI_OFFSET ebp, EBP-OLDESP;\ + CFI_OFFSET edi, EDI-OLDESP;\ + CFI_OFFSET esi, ESI-OLDESP;\ + CFI_OFFSET edx, EDX-OLDESP;\ + CFI_OFFSET ecx, ECX-OLDESP;\ + CFI_OFFSET ebx, EBX-OLDESP ENTRY(ret_from_fork) + CFI_STARTPROC pushl %eax + CFI_ADJUST_CFA_OFFSET -4 call schedule_tail GET_THREAD_INFO(%ebp) popl %eax + CFI_ADJUST_CFA_OFFSET -4 jmp syscall_exit + CFI_ENDPROC /* * Return to user mode is not as complex as all this looks, @@ -139,6 +206,7 @@ ENTRY(ret_from_fork) # userspace resumption stub bypassing syscall exit tracing ALIGN + RING0_PTREGS_FRAME ret_from_exception: preempt_stop ret_from_intr: @@ -171,20 +239,33 @@ need_resched: call preempt_schedule_irq jmp need_resched #endif + CFI_ENDPROC /* SYSENTER_RETURN points to after the "sysenter" instruction in the vsyscall page. See vsyscall-sysentry.S, which defines the symbol. */ # sysenter call handler stub ENTRY(sysenter_entry) + CFI_STARTPROC simple + CFI_DEF_CFA esp, 0 + CFI_REGISTER esp, ebp movl TSS_sysenter_esp0(%esp),%esp sysenter_past_esp: sti pushl $(__USER_DS) + CFI_ADJUST_CFA_OFFSET 4 + /*CFI_REL_OFFSET ss, 0*/ pushl %ebp + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET esp, 0 pushfl + CFI_ADJUST_CFA_OFFSET 4 pushl $(__USER_CS) + CFI_ADJUST_CFA_OFFSET 4 + /*CFI_REL_OFFSET cs, 0*/ pushl $SYSENTER_RETURN + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET eip, 0 /* * Load the potential sixth argument from user stack. @@ -199,6 +280,7 @@ sysenter_past_esp: .previous pushl %eax + CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL GET_THREAD_INFO(%ebp) @@ -219,11 +301,14 @@ sysenter_past_esp: xorl %ebp,%ebp sti sysexit + CFI_ENDPROC # system call handler stub ENTRY(system_call) + RING0_INT_FRAME # can't unwind into user space anyway pushl %eax # save orig_eax + CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL GET_THREAD_INFO(%ebp) testl $TF_MASK,EFLAGS(%esp) @@ -256,10 +341,12 @@ restore_all: movb CS(%esp), %al andl $(VM_MASK | (4 << 8) | 3), %eax cmpl $((4 << 8) | 3), %eax + CFI_REMEMBER_STATE je ldt_ss # returning to user-space with LDT SS restore_nocheck: RESTORE_REGS addl $4, %esp + CFI_ADJUST_CFA_OFFSET -4 1: iret .section .fixup,"ax" iret_exc: @@ -273,6 +360,7 @@ iret_exc: .long 1b,iret_exc .previous + CFI_RESTORE_STATE ldt_ss: larl OLDSS(%esp), %eax jnz restore_nocheck @@ -285,11 +373,13 @@ ldt_ss: * CPUs, which we can try to work around to make * dosemu and wine happy. */ subl $8, %esp # reserve space for switch16 pointer + CFI_ADJUST_CFA_OFFSET 8 cli movl %esp, %eax /* Set up the 16bit stack frame with switch32 pointer on top, * and a switch16 pointer on top of the current frame. */ call setup_x86_bogus_stack + CFI_ADJUST_CFA_OFFSET -8 # frame has moved RESTORE_REGS lss 20+4(%esp), %esp # switch to 16bit stack 1: iret @@ -297,9 +387,11 @@ ldt_ss: .align 4 .long 1b,iret_exc .previous + CFI_ENDPROC # perform work that needs to be done immediately before resumption ALIGN + RING0_PTREGS_FRAME # can't unwind into user space anyway work_pending: testb $_TIF_NEED_RESCHED, %cl jz work_notifysig @@ -329,8 +421,10 @@ work_notifysig: # deal with pending s work_notifysig_v86: #ifdef CONFIG_VM86 pushl %ecx # save ti_flags for do_notify_resume + CFI_ADJUST_CFA_OFFSET 4 call save_v86_state # %eax contains pt_regs pointer popl %ecx + CFI_ADJUST_CFA_OFFSET -4 movl %eax, %esp xorl %edx, %edx call do_notify_resume @@ -363,19 +457,21 @@ syscall_exit_work: movl $1, %edx call do_syscall_trace jmp resume_userspace + CFI_ENDPROC - ALIGN + RING0_INT_FRAME # can't unwind into user space anyway syscall_fault: pushl %eax # save orig_eax + CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL GET_THREAD_INFO(%ebp) movl $-EFAULT,EAX(%esp) jmp resume_userspace - ALIGN syscall_badsys: movl $-ENOSYS,EAX(%esp) jmp resume_userspace + CFI_ENDPROC #define FIXUP_ESPFIX_STACK \ movl %esp, %eax; \ @@ -387,16 +483,21 @@ #define FIXUP_ESPFIX_STACK \ movl %eax, %esp; #define UNWIND_ESPFIX_STACK \ pushl %eax; \ + CFI_ADJUST_CFA_OFFSET 4; \ movl %ss, %eax; \ /* see if on 16bit stack */ \ cmpw $__ESPFIX_SS, %ax; \ - jne 28f; \ - movl $__KERNEL_DS, %edx; \ - movl %edx, %ds; \ - movl %edx, %es; \ + je 28f; \ +27: popl %eax; \ + CFI_ADJUST_CFA_OFFSET -4; \ +.section .fixup,"ax"; \ +28: movl $__KERNEL_DS, %eax; \ + movl %eax, %ds; \ + movl %eax, %es; \ /* switch to 32bit stack */ \ - FIXUP_ESPFIX_STACK \ -28: popl %eax; + FIXUP_ESPFIX_STACK; \ + jmp 27b; \ +.previous /* * Build the entry stubs and pointer table with @@ -408,9 +509,14 @@ ENTRY(interrupt) vector=0 ENTRY(irq_entries_start) + RING0_INT_FRAME .rept NR_IRQS ALIGN + .if vector + CFI_ADJUST_CFA_OFFSET -4 + .endif 1: pushl $vector-256 + CFI_ADJUST_CFA_OFFSET 4 jmp common_interrupt .data .long 1b @@ -424,60 +530,99 @@ common_interrupt: movl %esp,%eax call do_IRQ jmp ret_from_intr + CFI_ENDPROC #define BUILD_INTERRUPT(name, nr) \ ENTRY(name) \ + RING0_INT_FRAME; \ pushl $nr-256; \ - SAVE_ALL \ + CFI_ADJUST_CFA_OFFSET 4; \ + SAVE_ALL; \ movl %esp,%eax; \ call smp_/**/name; \ - jmp ret_from_intr; + jmp ret_from_intr; \ + CFI_ENDPROC /* The include is where all of the SMP etc. interrupts come from */ #include "entry_arch.h" ENTRY(divide_error) + RING0_INT_FRAME pushl $0 # no error code + CFI_ADJUST_CFA_OFFSET 4 pushl $do_divide_error + CFI_ADJUST_CFA_OFFSET 4 ALIGN error_code: pushl %ds + CFI_ADJUST_CFA_OFFSET 4 + /*CFI_REL_OFFSET ds, 0*/ pushl %eax + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET eax, 0 xorl %eax, %eax pushl %ebp + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET ebp, 0 pushl %edi + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET edi, 0 pushl %esi + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET esi, 0 pushl %edx + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET edx, 0 decl %eax # eax = -1 pushl %ecx + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET ecx, 0 pushl %ebx + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET ebx, 0 cld pushl %es + CFI_ADJUST_CFA_OFFSET 4 + /*CFI_REL_OFFSET es, 0*/ UNWIND_ESPFIX_STACK popl %ecx + CFI_ADJUST_CFA_OFFSET -4 + /*CFI_REGISTER es, ecx*/ movl ES(%esp), %edi # get the function address movl ORIG_EAX(%esp), %edx # get the error code movl %eax, ORIG_EAX(%esp) movl %ecx, ES(%esp) + /*CFI_REL_OFFSET es, ES*/ movl $(__USER_DS), %ecx movl %ecx, %ds movl %ecx, %es movl %esp,%eax # pt_regs pointer call *%edi jmp ret_from_exception + CFI_ENDPROC ENTRY(coprocessor_error) + RING0_INT_FRAME pushl $0 + CFI_ADJUST_CFA_OFFSET 4 pushl $do_coprocessor_error + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC ENTRY(simd_coprocessor_error) + RING0_INT_FRAME pushl $0 + CFI_ADJUST_CFA_OFFSET 4 pushl $do_simd_coprocessor_error + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC ENTRY(device_not_available) + RING0_INT_FRAME pushl $-1 # mark this as an int + CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL movl %cr0, %eax testl $0x4, %eax # EM (math emulation bit) @@ -487,9 +632,12 @@ ENTRY(device_not_available) jmp ret_from_exception device_not_available_emulate: pushl $0 # temporary storage for ORIG_EIP + CFI_ADJUST_CFA_OFFSET 4 call math_emulate addl $4, %esp + CFI_ADJUST_CFA_OFFSET -4 jmp ret_from_exception + CFI_ENDPROC /* * Debug traps and NMI can happen at the one SYSENTER instruction @@ -514,16 +662,19 @@ label: \ pushl $sysenter_past_esp KPROBE_ENTRY(debug) + RING0_INT_FRAME cmpl $sysenter_entry,(%esp) jne debug_stack_correct FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn) debug_stack_correct: pushl $-1 # mark this as an int + CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL xorl %edx,%edx # error code 0 movl %esp,%eax # pt_regs pointer call do_debug jmp ret_from_exception + CFI_ENDPROC .previous .text /* * NMI is doubly nasty. It can happen _while_ we're handling @@ -534,14 +685,18 @@ debug_stack_correct: * fault happened on the sysenter path. */ ENTRY(nmi) + RING0_INT_FRAME pushl %eax + CFI_ADJUST_CFA_OFFSET 4 movl %ss, %eax cmpw $__ESPFIX_SS, %ax popl %eax + CFI_ADJUST_CFA_OFFSET -4 je nmi_16bit_stack cmpl $sysenter_entry,(%esp) je nmi_stack_fixup pushl %eax + CFI_ADJUST_CFA_OFFSET 4 movl %esp,%eax /* Do not access memory above the end of our stack page, * it might not exist. @@ -549,16 +704,19 @@ ENTRY(nmi) andl $(THREAD_SIZE-1),%eax cmpl $(THREAD_SIZE-20),%eax popl %eax + CFI_ADJUST_CFA_OFFSET -4 jae nmi_stack_correct cmpl $sysenter_entry,12(%esp) je nmi_debug_stack_check nmi_stack_correct: pushl %eax + CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL xorl %edx,%edx # zero error code movl %esp,%eax # pt_regs pointer call do_nmi jmp restore_all + CFI_ENDPROC nmi_stack_fixup: FIX_STACK(12,nmi_stack_correct, 1) @@ -574,94 +732,177 @@ nmi_debug_stack_check: jmp nmi_stack_correct nmi_16bit_stack: + RING0_INT_FRAME /* create the pointer to lss back */ pushl %ss + CFI_ADJUST_CFA_OFFSET 4 pushl %esp + CFI_ADJUST_CFA_OFFSET 4 movzwl %sp, %esp addw $4, (%esp) /* copy the iret frame of 12 bytes */ .rept 3 pushl 16(%esp) + CFI_ADJUST_CFA_OFFSET 4 .endr pushl %eax + CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL FIXUP_ESPFIX_STACK # %eax == %esp + CFI_ADJUST_CFA_OFFSET -20 # the frame has now moved xorl %edx,%edx # zero error code call do_nmi RESTORE_REGS lss 12+4(%esp), %esp # back to 16bit stack 1: iret + CFI_ENDPROC .section __ex_table,"a" .align 4 .long 1b,iret_exc .previous KPROBE_ENTRY(int3) + RING0_INT_FRAME pushl $-1 # mark this as an int + CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL xorl %edx,%edx # zero error code movl %esp,%eax # pt_regs pointer call do_int3 jmp ret_from_exception + CFI_ENDPROC .previous .text ENTRY(overflow) + RING0_INT_FRAME pushl $0 + CFI_ADJUST_CFA_OFFSET 4 pushl $do_overflow + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC ENTRY(bounds) + RING0_INT_FRAME pushl $0 + CFI_ADJUST_CFA_OFFSET 4 pushl $do_bounds + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC ENTRY(invalid_op) + RING0_INT_FRAME pushl $0 + CFI_ADJUST_CFA_OFFSET 4 pushl $do_invalid_op + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC ENTRY(coprocessor_segment_overrun) + RING0_INT_FRAME pushl $0 + CFI_ADJUST_CFA_OFFSET 4 pushl $do_coprocessor_segment_overrun + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC ENTRY(invalid_TSS) + RING0_EC_FRAME pushl $do_invalid_TSS + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC ENTRY(segment_not_present) + RING0_EC_FRAME pushl $do_segment_not_present + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC ENTRY(stack_segment) + RING0_EC_FRAME pushl $do_stack_segment + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC KPROBE_ENTRY(general_protection) + RING0_EC_FRAME pushl $do_general_protection + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC .previous .text ENTRY(alignment_check) + RING0_EC_FRAME pushl $do_alignment_check + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC KPROBE_ENTRY(page_fault) + RING0_EC_FRAME pushl $do_page_fault + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC .previous .text #ifdef CONFIG_X86_MCE ENTRY(machine_check) + RING0_INT_FRAME pushl $0 + CFI_ADJUST_CFA_OFFSET 4 pushl machine_check_vector + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC #endif ENTRY(spurious_interrupt_bug) + RING0_INT_FRAME pushl $0 + CFI_ADJUST_CFA_OFFSET 4 pushl $do_spurious_interrupt_bug + CFI_ADJUST_CFA_OFFSET 4 jmp error_code + CFI_ENDPROC + +#ifdef CONFIG_STACK_UNWIND +ENTRY(arch_unwind_init_running) + CFI_STARTPROC + movl 4(%esp), %edx + movl (%esp), %ecx + leal 4(%esp), %eax + movl %ebx, EBX(%edx) + xorl %ebx, %ebx + movl %ebx, ECX(%edx) + movl %ebx, EDX(%edx) + movl %esi, ESI(%edx) + movl %edi, EDI(%edx) + movl %ebp, EBP(%edx) + movl %ebx, EAX(%edx) + movl $__USER_DS, DS(%edx) + movl $__USER_DS, ES(%edx) + movl %ebx, ORIG_EAX(%edx) + movl %ecx, EIP(%edx) + movl 12(%esp), %ecx + movl $__KERNEL_CS, CS(%edx) + movl %ebx, EFLAGS(%edx) + movl %eax, OLDESP(%edx) + movl 8(%esp), %eax + movl %ecx, 8(%esp) + movl EBX(%edx), %ebx + movl $__KERNEL_DS, OLDSS(%edx) + jmpl *%eax + CFI_ENDPROC +ENDPROC(arch_unwind_init_running) +#endif .section .rodata,"a" #include "syscall_table.S" diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c new file mode 100644 index 0000000..c6737c3 --- /dev/null +++ b/arch/i386/kernel/hpet.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include + +#include +#include + +#define HPET_MASK CLOCKSOURCE_MASK(32) +#define HPET_SHIFT 22 + +/* FSEC = 10^-15 NSEC = 10^-9 */ +#define FSEC_PER_NSEC 1000000 + +static void *hpet_ptr; + +static cycle_t read_hpet(void) +{ + return (cycle_t)readl(hpet_ptr); +} + +static struct clocksource clocksource_hpet = { + .name = "hpet", + .rating = 250, + .read = read_hpet, + .mask = HPET_MASK, + .mult = 0, /* set below */ + .shift = HPET_SHIFT, + .is_continuous = 1, +}; + +static int __init init_hpet_clocksource(void) +{ + unsigned long hpet_period; + void __iomem* hpet_base; + u64 tmp; + + if (!hpet_address) + return -ENODEV; + + /* calculate the hpet address: */ + hpet_base = + (void __iomem*)ioremap_nocache(hpet_address, HPET_MMAP_SIZE); + hpet_ptr = hpet_base + HPET_COUNTER; + + /* calculate the frequency: */ + hpet_period = readl(hpet_base + HPET_PERIOD); + + /* + * hpet period is in femto seconds per cycle + * so we need to convert this to ns/cyc units + * aproximated by mult/2^shift + * + * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift + * fsec/cyc * 1ns/1000000fsec * 2^shift = mult + * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult + * (fsec/cyc << shift)/1000000 = mult + * (hpet_period << shift)/FSEC_PER_NSEC = mult + */ + tmp = (u64)hpet_period << HPET_SHIFT; + do_div(tmp, FSEC_PER_NSEC); + clocksource_hpet.mult = (u32)tmp; + + return clocksource_register(&clocksource_hpet); +} + +module_init(init_hpet_clocksource); diff --git a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c index d755247..c435197 100644 --- a/arch/i386/kernel/i387.c +++ b/arch/i386/kernel/i387.c @@ -25,7 +25,7 @@ #else #define HAVE_HWFP 1 #endif -static unsigned long mxcsr_feature_mask = 0xffffffff; +static unsigned long mxcsr_feature_mask __read_mostly = 0xffffffff; void mxcsr_feature_mask_init(void) { diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c new file mode 100644 index 0000000..477b24d --- /dev/null +++ b/arch/i386/kernel/i8253.c @@ -0,0 +1,118 @@ +/* + * i8253.c 8253/PIT functions + * + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "io_ports.h" + +DEFINE_SPINLOCK(i8253_lock); +EXPORT_SYMBOL(i8253_lock); + +void setup_pit_timer(void) +{ + unsigned long flags; + + spin_lock_irqsave(&i8253_lock, flags); + outb_p(0x34,PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */ + udelay(10); + outb_p(LATCH & 0xff , PIT_CH0); /* LSB */ + udelay(10); + outb(LATCH >> 8 , PIT_CH0); /* MSB */ + spin_unlock_irqrestore(&i8253_lock, flags); +} + +/* + * Since the PIT overflows every tick, its not very useful + * to just read by itself. So use jiffies to emulate a free + * running counter: + */ +static cycle_t pit_read(void) +{ + unsigned long flags; + int count; + u32 jifs; + static int old_count; + static u32 old_jifs; + + spin_lock_irqsave(&i8253_lock, flags); + /* + * Although our caller may have the read side of xtime_lock, + * this is now a seqlock, and we are cheating in this routine + * by having side effects on state that we cannot undo if + * there is a collision on the seqlock and our caller has to + * retry. (Namely, old_jifs and old_count.) So we must treat + * jiffies as volatile despite the lock. We read jiffies + * before latching the timer count to guarantee that although + * the jiffies value might be older than the count (that is, + * the counter may underflow between the last point where + * jiffies was incremented and the point where we latch the + * count), it cannot be newer. + */ + jifs = jiffies; + outb_p(0x00, PIT_MODE); /* latch the count ASAP */ + count = inb_p(PIT_CH0); /* read the latched count */ + count |= inb_p(PIT_CH0) << 8; + + /* VIA686a test code... reset the latch if count > max + 1 */ + if (count > LATCH) { + outb_p(0x34, PIT_MODE); + outb_p(LATCH & 0xff, PIT_CH0); + outb(LATCH >> 8, PIT_CH0); + count = LATCH - 1; + } + + /* + * It's possible for count to appear to go the wrong way for a + * couple of reasons: + * + * 1. The timer counter underflows, but we haven't handled the + * resulting interrupt and incremented jiffies yet. + * 2. Hardware problem with the timer, not giving us continuous time, + * the counter does small "jumps" upwards on some Pentium systems, + * (see c't 95/10 page 335 for Neptun bug.) + * + * Previous attempts to handle these cases intelligently were + * buggy, so we just do the simple thing now. + */ + if (count > old_count && jifs == old_jifs) { + count = old_count; + } + old_count = count; + old_jifs = jifs; + + spin_unlock_irqrestore(&i8253_lock, flags); + + count = (LATCH - 1) - count; + + return (cycle_t)(jifs * LATCH) + count; +} + +static struct clocksource clocksource_pit = { + .name = "pit", + .rating = 110, + .read = pit_read, + .mask = CLOCKSOURCE_MASK(32), + .mult = 0, + .shift = 20, +}; + +static int __init init_pit_clocksource(void) +{ + if (num_possible_cpus() > 4) /* PIT does not scale! */ + return 0; + + clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20); + return clocksource_register(&clocksource_pit); +} +module_init(init_pit_clocksource); diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index 323ef8a..c1a42fe 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -175,7 +175,7 @@ static void mask_and_ack_8259A(unsigned * Lightweight spurious IRQ detection. We do not want * to overdo spurious IRQ handling - it's usually a sign * of hardware problems, so we only do the checks we can - * do without slowing down good hardware unnecesserily. + * do without slowing down good hardware unnecessarily. * * Note that IRQ7 and IRQ15 (the two spurious IRQs * usually resulting from the 8259A-1|2 PICs) occur @@ -271,8 +271,8 @@ static int i8259A_shutdown(struct sys_de * the kernel initialization code can get it * out of. */ - outb(0xff, 0x21); /* mask all of 8259A-1 */ - outb(0xff, 0xA1); /* mask all of 8259A-1 */ + outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ + outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */ return 0; } diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index d70f2ad..72ae414 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -38,6 +38,7 @@ #include #include #include #include +#include #include @@ -50,6 +51,7 @@ atomic_t irq_mis_count; static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; static DEFINE_SPINLOCK(ioapic_lock); +static DEFINE_SPINLOCK(vector_lock); int timer_over_8254 __initdata = 1; @@ -267,7 +269,7 @@ # include /* kstat # include /* kmalloc() */ # include /* time_after() */ -# ifdef CONFIG_BALANCED_IRQ_DEBUG +#ifdef CONFIG_BALANCED_IRQ_DEBUG # define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0) # define Dprintk(x...) do { TDprintk(x); } while (0) # else @@ -275,10 +277,15 @@ # define TDprintk(x...) # define Dprintk(x...) # endif - #define IRQBALANCE_CHECK_ARCH -999 -static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH; -static int physical_balance = 0; +#define MAX_BALANCED_IRQ_INTERVAL (5*HZ) +#define MIN_BALANCED_IRQ_INTERVAL (HZ/2) +#define BALANCED_IRQ_MORE_DELTA (HZ/10) +#define BALANCED_IRQ_LESS_DELTA (HZ) + +static int irqbalance_disabled __read_mostly = IRQBALANCE_CHECK_ARCH; +static int physical_balance __read_mostly; +static long balanced_irq_interval __read_mostly = MAX_BALANCED_IRQ_INTERVAL; static struct irq_cpu_info { unsigned long * last_irq; @@ -297,12 +304,14 @@ #define IRQ_ALLOWED(cpu, allowed_mask) c #define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i])) -#define MAX_BALANCED_IRQ_INTERVAL (5*HZ) -#define MIN_BALANCED_IRQ_INTERVAL (HZ/2) -#define BALANCED_IRQ_MORE_DELTA (HZ/10) -#define BALANCED_IRQ_LESS_DELTA (HZ) +static cpumask_t balance_irq_affinity[NR_IRQS] = { + [0 ... NR_IRQS-1] = CPU_MASK_ALL +}; -static long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL; +void set_balance_irq_affinity(unsigned int irq, cpumask_t mask) +{ + balance_irq_affinity[irq] = mask; +} static unsigned long move(int curr_cpu, cpumask_t allowed_mask, unsigned long now, int direction) @@ -340,7 +349,7 @@ static inline void balance_irq(int cpu, if (irqbalance_disabled) return; - cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]); + cpus_and(allowed_mask, cpu_online_map, balance_irq_affinity[irq]); new_cpu = move(cpu, allowed_mask, now, 1); if (cpu != new_cpu) { set_pending_irq(irq, cpumask_of_cpu(new_cpu)); @@ -529,7 +538,9 @@ tryanotherirq: } } - cpus_and(allowed_mask, cpu_online_map, irq_affinity[selected_irq]); + cpus_and(allowed_mask, + cpu_online_map, + balance_irq_affinity[selected_irq]); target_cpu_mask = cpumask_of_cpu(min_loaded); cpus_and(tmp, target_cpu_mask, allowed_mask); @@ -1152,10 +1163,17 @@ u8 irq_vector[NR_IRQ_VECTORS] __read_mos int assign_irq_vector(int irq) { static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; + unsigned long flags; + int vector; + + BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS); - BUG_ON(irq >= NR_IRQ_VECTORS); - if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) + spin_lock_irqsave(&vector_lock, flags); + + if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) { + spin_unlock_irqrestore(&vector_lock, flags); return IO_APIC_VECTOR(irq); + } next: current_vector += 8; if (current_vector == SYSCALL_VECTOR) @@ -1163,16 +1181,21 @@ next: if (current_vector >= FIRST_SYSTEM_VECTOR) { offset++; - if (!(offset%8)) + if (!(offset%8)) { + spin_unlock_irqrestore(&vector_lock, flags); return -ENOSPC; + } current_vector = FIRST_DEVICE_VECTOR + offset; } - vector_irq[current_vector] = irq; + vector = current_vector; + vector_irq[vector] = irq; if (irq != AUTO_ASSIGN) - IO_APIC_VECTOR(irq) = current_vector; + IO_APIC_VECTOR(irq) = vector; - return current_vector; + spin_unlock_irqrestore(&vector_lock, flags); + + return vector; } static struct hw_interrupt_type ioapic_level_type; @@ -1184,21 +1207,14 @@ #define IOAPIC_LEVEL 1 static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger) { - if (use_pci_vector() && !platform_legacy_irq(irq)) { - if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || - trigger == IOAPIC_LEVEL) - irq_desc[vector].handler = &ioapic_level_type; - else - irq_desc[vector].handler = &ioapic_edge_type; - set_intr_gate(vector, interrupt[vector]); - } else { - if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || - trigger == IOAPIC_LEVEL) - irq_desc[irq].handler = &ioapic_level_type; - else - irq_desc[irq].handler = &ioapic_edge_type; - set_intr_gate(vector, interrupt[irq]); - } + unsigned idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq; + + if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || + trigger == IOAPIC_LEVEL) + irq_desc[idx].handler = &ioapic_level_type; + else + irq_desc[idx].handler = &ioapic_edge_type; + set_intr_gate(vector, interrupt[idx]); } static void __init setup_IO_APIC_irqs(void) diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index f3a9c78..061533e 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -42,8 +42,8 @@ union irq_ctx { u32 stack[THREAD_SIZE/sizeof(u32)]; }; -static union irq_ctx *hardirq_ctx[NR_CPUS]; -static union irq_ctx *softirq_ctx[NR_CPUS]; +static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; +static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; #endif /* @@ -95,6 +95,14 @@ #ifdef CONFIG_4KSTACKS irqctx->tinfo.task = curctx->tinfo.task; irqctx->tinfo.previous_esp = current_stack_pointer; + /* + * Copy the softirq bits in preempt_count so that the + * softirq checks work in the hardirq context. + */ + irqctx->tinfo.preempt_count = + irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK | + curctx->tinfo.preempt_count & SOFTIRQ_MASK; + asm volatile( " xchgl %%ebx,%%esp \n" " call __do_IRQ \n" @@ -219,7 +227,7 @@ int show_interrupts(struct seq_file *p, if (i == 0) { seq_printf(p, " "); for_each_online_cpu(j) - seq_printf(p, "CPU%d ",j); + seq_printf(p, "CPU%-8d",j); seq_putc(p, '\n'); } diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 38806f4..727e419 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -57,34 +57,85 @@ static __always_inline void set_jmp_op(v /* * returns non-zero if opcodes can be boosted. */ -static __always_inline int can_boost(kprobe_opcode_t opcode) +static __always_inline int can_boost(kprobe_opcode_t *opcodes) { - switch (opcode & 0xf0 ) { +#define W(row,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf) \ + (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \ + (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) | \ + (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) | \ + (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf)) \ + << (row % 32)) + /* + * Undefined/reserved opcodes, conditional jump, Opcode Extension + * Groups, and some special opcodes can not be boost. + */ + static const unsigned long twobyte_is_boostable[256 / 32] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + /* ------------------------------- */ + W(0x00, 0,0,1,1,0,0,1,0,1,1,0,0,0,0,0,0)| /* 00 */ + W(0x10, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 10 */ + W(0x20, 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0)| /* 20 */ + W(0x30, 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 30 */ + W(0x40, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 40 */ + W(0x50, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 50 */ + W(0x60, 1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1)| /* 60 */ + W(0x70, 0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1), /* 70 */ + W(0x80, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 80 */ + W(0x90, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), /* 90 */ + W(0xa0, 1,1,0,1,1,1,0,0,1,1,0,1,1,1,0,1)| /* a0 */ + W(0xb0, 1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1), /* b0 */ + W(0xc0, 1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1)| /* c0 */ + W(0xd0, 0,1,1,1,0,1,0,0,1,1,0,1,1,1,0,1), /* d0 */ + W(0xe0, 0,1,1,0,0,1,0,0,1,1,0,1,1,1,0,1)| /* e0 */ + W(0xf0, 0,1,1,1,0,1,0,0,1,1,1,0,1,1,1,0) /* f0 */ + /* ------------------------------- */ + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + }; +#undef W + kprobe_opcode_t opcode; + kprobe_opcode_t *orig_opcodes = opcodes; +retry: + if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1) + return 0; + opcode = *(opcodes++); + + /* 2nd-byte opcode */ + if (opcode == 0x0f) { + if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1) + return 0; + return test_bit(*opcodes, twobyte_is_boostable); + } + + switch (opcode & 0xf0) { + case 0x60: + if (0x63 < opcode && opcode < 0x67) + goto retry; /* prefixes */ + /* can't boost Address-size override and bound */ + return (opcode != 0x62 && opcode != 0x67); case 0x70: return 0; /* can't boost conditional jump */ - case 0x90: - /* can't boost call and pushf */ - return opcode != 0x9a && opcode != 0x9c; case 0xc0: - /* can't boost undefined opcodes and soft-interruptions */ - return (0xc1 < opcode && opcode < 0xc6) || - (0xc7 < opcode && opcode < 0xcc) || opcode == 0xcf; + /* can't boost software-interruptions */ + return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf; case 0xd0: /* can boost AA* and XLAT */ return (opcode == 0xd4 || opcode == 0xd5 || opcode == 0xd7); case 0xe0: - /* can boost in/out and (may be) jmps */ - return (0xe3 < opcode && opcode != 0xe8); + /* can boost in/out and absolute jmps */ + return ((opcode & 0x04) || opcode == 0xea); case 0xf0: + if ((opcode & 0x0c) == 0 && opcode != 0xf1) + goto retry; /* lock/rep(ne) prefix */ /* clear and set flags can be boost */ return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe)); default: - /* currently, can't boost 2 bytes opcodes */ - return opcode != 0x0f; + if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e) + goto retry; /* prefixes */ + /* can't boost CS override and call */ + return (opcode != 0x2e && opcode != 0x9a); } } - /* * returns non-zero if opcode modifies the interrupt flag. */ @@ -109,7 +160,7 @@ int __kprobes arch_prepare_kprobe(struct memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); p->opcode = *p->addr; - if (can_boost(p->opcode)) { + if (can_boost(p->addr)) { p->ainsn.boostable = 0; } else { p->ainsn.boostable = -1; @@ -208,7 +259,9 @@ static int __kprobes kprobe_handler(stru struct kprobe_ctlblk *kcb; #ifdef CONFIG_PREEMPT unsigned pre_preempt_count = preempt_count(); -#endif /* CONFIG_PREEMPT */ +#else + unsigned pre_preempt_count = 1; +#endif addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t)); @@ -285,22 +338,14 @@ #endif /* CONFIG_PREEMPT */ /* handler has already set things up, so skip ss setup */ return 1; - if (p->ainsn.boostable == 1 && -#ifdef CONFIG_PREEMPT - !(pre_preempt_count) && /* - * This enables booster when the direct - * execution path aren't preempted. - */ -#endif /* CONFIG_PREEMPT */ - !p->post_handler && !p->break_handler ) { +ss_probe: + if (pre_preempt_count && p->ainsn.boostable == 1 && !p->post_handler){ /* Boost up -- we can execute copied instructions directly */ reset_current_kprobe(); regs->eip = (unsigned long)p->ainsn.insn; preempt_enable_no_resched(); return 1; } - -ss_probe: prepare_singlestep(p, regs); kcb->kprobe_status = KPROBE_HIT_SS; return 1; @@ -607,7 +652,7 @@ int __kprobes kprobe_exceptions_notify(s struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - if (args->regs && user_mode(args->regs)) + if (args->regs && user_mode_vm(args->regs)) return ret; switch (val) { diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c index f73d737..511abe5 100644 --- a/arch/i386/kernel/machine_kexec.c +++ b/arch/i386/kernel/machine_kexec.c @@ -133,9 +133,9 @@ typedef asmlinkage NORET_TYPE void (*rel unsigned long start_address, unsigned int has_pae) ATTRIB_NORET; -const extern unsigned char relocate_new_kernel[]; +extern const unsigned char relocate_new_kernel[]; extern void relocate_new_kernel_end(void); -const extern unsigned int relocate_new_kernel_size; +extern const unsigned int relocate_new_kernel_size; /* * A architecture hook called to validate the diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index e7c138f..0a86588 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -91,7 +91,10 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) Mi MODULE_AUTHOR("Tigran Aivazian "); MODULE_LICENSE("GPL"); -#define MICROCODE_VERSION "1.14" +static int verbose; +module_param(verbose, int, 0644); + +#define MICROCODE_VERSION "1.14a" #define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ #define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ @@ -122,14 +125,15 @@ static unsigned int user_buffer_size; /* typedef enum mc_error_code { MC_SUCCESS = 0, - MC_NOTFOUND = 1, - MC_MARKED = 2, - MC_ALLOCATED = 3, + MC_IGNORED = 1, + MC_NOTFOUND = 2, + MC_MARKED = 3, + MC_ALLOCATED = 4, } mc_error_code_t; static struct ucode_cpu_info { unsigned int sig; - unsigned int pf; + unsigned int pf, orig_pf; unsigned int rev; unsigned int cksum; mc_error_code_t err; @@ -164,6 +168,7 @@ static void collect_cpu_info (void *unus rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); uci->pf = 1 << ((val[1] >> 18) & 7); } + uci->orig_pf = uci->pf; } wrmsr(MSR_IA32_UCODE_REV, 0, 0); @@ -197,21 +202,34 @@ static inline void mark_microcode_update pr_debug(" Checksum 0x%x\n", cksum); if (mc_header->rev < uci->rev) { - printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision" - " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); - goto out; + if (uci->err == MC_NOTFOUND) { + uci->err = MC_IGNORED; + uci->cksum = mc_header->rev; + } else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev) + uci->cksum = mc_header->rev; } else if (mc_header->rev == uci->rev) { - /* notify the caller of success on this cpu */ - uci->err = MC_SUCCESS; - goto out; + if (uci->err < MC_MARKED) { + /* notify the caller of success on this cpu */ + uci->err = MC_SUCCESS; + } + } else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) { + pr_debug("microcode: CPU%d found a matching microcode update with " + " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); + uci->cksum = cksum; + uci->pf = pf; /* keep the original mc pf for cksum calculation */ + uci->err = MC_MARKED; /* found the match */ + for_each_online_cpu(cpu_num) { + if (ucode_cpu_info + cpu_num != uci + && ucode_cpu_info[cpu_num].mc == uci->mc) { + uci->mc = NULL; + break; + } + } + if (uci->mc != NULL) { + vfree(uci->mc); + uci->mc = NULL; + } } - - pr_debug("microcode: CPU%d found a matching microcode update with " - " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev); - uci->cksum = cksum; - uci->pf = pf; /* keep the original mc pf for cksum calculation */ - uci->err = MC_MARKED; /* found the match */ -out: return; } @@ -253,10 +271,8 @@ static int find_matching_ucodes (void) for_each_online_cpu(cpu_num) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/ - continue; - if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->pf)) + if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf)) mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum); } @@ -295,9 +311,8 @@ static int find_matching_ucodes (void) } for_each_online_cpu(cpu_num) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; - if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/ - continue; - if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->pf)) { + + if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) { mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum); } } @@ -368,6 +383,13 @@ static void do_update_one (void * unused struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; if (uci->mc == NULL) { + if (verbose) { + if (uci->err == MC_SUCCESS) + printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n", + cpu_num, uci->rev); + else + printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num); + } return; } @@ -426,6 +448,9 @@ out_free: ucode_cpu_info[j].mc = NULL; } } + if (ucode_cpu_info[i].err == MC_IGNORED && verbose) + printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision" + " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev); } out: return error; diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index d43b498..a76e931 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -14,21 +14,17 @@ */ #include -#include #include -#include -#include #include -#include -#include #include #include #include #include +#include #include -#include #include +#include #include "mach_traps.h" @@ -100,6 +96,9 @@ #define P4_NMI_IQ_CCCR0 \ (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \ P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE) +#define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL +#define ARCH_PERFMON_NMI_EVENT_UMASK ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK + #ifdef CONFIG_SMP /* The performance counters used by NMI_LOCAL_APIC don't trigger when * the CPU is idle. To make sure the NMI watchdog really ticks on all @@ -212,6 +211,8 @@ static int __init setup_nmi_watchdog(cha __setup("nmi_watchdog=", setup_nmi_watchdog); +static void disable_intel_arch_watchdog(void); + static void disable_lapic_nmi_watchdog(void) { if (nmi_active <= 0) @@ -221,6 +222,10 @@ static void disable_lapic_nmi_watchdog(v wrmsr(MSR_K7_EVNTSEL0, 0, 0); break; case X86_VENDOR_INTEL: + if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { + disable_intel_arch_watchdog(); + break; + } switch (boot_cpu_data.x86) { case 6: if (boot_cpu_data.x86_model > 0xd) @@ -449,6 +454,53 @@ #endif return 1; } +static void disable_intel_arch_watchdog(void) +{ + unsigned ebx; + + /* + * Check whether the Architectural PerfMon supports + * Unhalted Core Cycles Event or not. + * NOTE: Corresponding bit = 0 in ebp indicates event present. + */ + ebx = cpuid_ebx(10); + if (!(ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT)) + wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, 0, 0); +} + +static int setup_intel_arch_watchdog(void) +{ + unsigned int evntsel; + unsigned ebx; + + /* + * Check whether the Architectural PerfMon supports + * Unhalted Core Cycles Event or not. + * NOTE: Corresponding bit = 0 in ebp indicates event present. + */ + ebx = cpuid_ebx(10); + if ((ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT)) + return 0; + + nmi_perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0; + + clear_msr_range(MSR_ARCH_PERFMON_EVENTSEL0, 2); + clear_msr_range(MSR_ARCH_PERFMON_PERFCTR0, 2); + + evntsel = ARCH_PERFMON_EVENTSEL_INT + | ARCH_PERFMON_EVENTSEL_OS + | ARCH_PERFMON_EVENTSEL_USR + | ARCH_PERFMON_NMI_EVENT_SEL + | ARCH_PERFMON_NMI_EVENT_UMASK; + + wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0); + write_watchdog_counter("INTEL_ARCH_PERFCTR0"); + apic_write(APIC_LVTPC, APIC_DM_NMI); + evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE; + wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0); + return 1; +} + void setup_apic_nmi_watchdog (void) { switch (boot_cpu_data.x86_vendor) { @@ -458,6 +510,11 @@ void setup_apic_nmi_watchdog (void) setup_k7_watchdog(); break; case X86_VENDOR_INTEL: + if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { + if (!setup_intel_arch_watchdog()) + return; + break; + } switch (boot_cpu_data.x86) { case 6: if (boot_cpu_data.x86_model > 0xd) @@ -561,7 +618,8 @@ void nmi_watchdog_tick (struct pt_regs * wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0); apic_write(APIC_LVTPC, APIC_DM_NMI); } - else if (nmi_perfctr_msr == MSR_P6_PERFCTR0) { + else if (nmi_perfctr_msr == MSR_P6_PERFCTR0 || + nmi_perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) { /* Only P6 based Pentium M need to re-unmask * the apic vector but it doesn't hurt * other P6 variant */ diff --git a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c index 5f5b075..0caf146 100644 --- a/arch/i386/kernel/numaq.c +++ b/arch/i386/kernel/numaq.c @@ -79,10 +79,12 @@ int __init get_memcfg_numaq(void) return 1; } -static int __init numaq_dsc_disable(void) +static int __init numaq_tsc_disable(void) { - printk(KERN_DEBUG "NUMAQ: disabling TSC\n"); - tsc_disable = 1; + if (num_online_nodes() > 1) { + printk(KERN_DEBUG "NUMAQ: disabling TSC\n"); + tsc_disable = 1; + } return 0; } -core_initcall(numaq_dsc_disable); +arch_initcall(numaq_tsc_disable); diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 6259afe..6946b06 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -102,7 +102,7 @@ void default_idle(void) local_irq_enable(); if (!hlt_counter && boot_cpu_data.hlt_works_ok) { - clear_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status &= ~TS_POLLING; smp_mb__after_clear_bit(); while (!need_resched()) { local_irq_disable(); @@ -111,7 +111,7 @@ void default_idle(void) else local_irq_enable(); } - set_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status |= TS_POLLING; } else { while (!need_resched()) cpu_relax(); @@ -174,7 +174,7 @@ void cpu_idle(void) { int cpu = smp_processor_id(); - set_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status |= TS_POLLING; /* endless idle loop with no priority at all */ while (1) { @@ -312,7 +312,7 @@ void show_regs(struct pt_regs * regs) cr3 = read_cr3(); cr4 = read_cr4_safe(); printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); - show_trace(NULL, ®s->esp); + show_trace(NULL, regs, ®s->esp); } /* diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index dd6b0e3..4a65040 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -60,7 +60,7 @@ #include #include #include #include -#include "setup_arch_pre.h" +#include #include /* Forward Declaration. */ @@ -410,8 +410,8 @@ static void __init limit_regions(unsigne } } -static void __init add_memory_region(unsigned long long start, - unsigned long long size, int type) +void __init add_memory_region(unsigned long long start, + unsigned long long size, int type) { int x; @@ -474,7 +474,7 @@ static struct change_member *change_poin static struct e820entry *overlap_list[E820MAX] __initdata; static struct e820entry new_bios[E820MAX] __initdata; -static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map) +int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map) { struct change_member *change_tmp; unsigned long current_type, last_type; @@ -643,7 +643,7 @@ static int __init sanitize_e820_map(stru * thinkpad 560x, for example, does not cooperate with the memory * detection code.) */ -static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) +int __init copy_e820_map(struct e820entry * biosmap, int nr_map) { /* Only one memory region (or negative)? Ignore it */ if (nr_map < 2) @@ -701,12 +701,6 @@ static inline void copy_edd(void) } #endif -/* - * Do NOT EVER look at the BIOS memory size location. - * It does not work on many machines. - */ -#define LOWMEMSIZE() (0x9f000) - static void __init parse_cmdline_early (char ** cmdline_p) { char c = ' ', *to = command_line, *from = saved_command_line; @@ -1423,8 +1417,6 @@ static void __init register_memory(void) pci_mem_start, gapstart, gapsize); } -static char * __init machine_specific_memory_setup(void); - #ifdef CONFIG_MCA static void set_mca_bus(int x) { @@ -1583,6 +1575,7 @@ #elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; #endif #endif + tsc_init(); } static __init int add_pcspkr(void) @@ -1602,7 +1595,6 @@ static __init int add_pcspkr(void) } device_initcall(add_pcspkr); -#include "setup_arch_post.h" /* * Local Variables: * mode:c diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index d134e96..c10789d 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -114,7 +114,17 @@ DEFINE_PER_CPU(struct tlb_state, cpu_tlb static inline int __prepare_ICR (unsigned int shortcut, int vector) { - return APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL; + unsigned int icr = shortcut | APIC_DEST_LOGICAL; + + switch (vector) { + default: + icr |= APIC_DM_FIXED | vector; + break; + case NMI_VECTOR: + icr |= APIC_DM_NMI; + break; + } + return icr; } static inline int __prepare_ICR2 (unsigned int mask) diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 825b2b4..bce5470 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -52,6 +52,7 @@ #include #include #include #include +#include #include #include @@ -257,7 +258,7 @@ static void __init synchronize_tsc_bp (v * all APs synchronize but they loop on '== num_cpus' */ while (atomic_read(&tsc_count_start) != num_booting_cpus()-1) - mb(); + cpu_relax(); atomic_set(&tsc_count_stop, 0); wmb(); /* @@ -276,7 +277,7 @@ static void __init synchronize_tsc_bp (v * Wait for all APs to leave the synchronization point: */ while (atomic_read(&tsc_count_stop) != num_booting_cpus()-1) - mb(); + cpu_relax(); atomic_set(&tsc_count_start, 0); wmb(); atomic_inc(&tsc_count_stop); @@ -333,19 +334,21 @@ static void __init synchronize_tsc_ap (v * this gets called, so we first wait for the BP to * finish SMP initialization: */ - while (!atomic_read(&tsc_start_flag)) mb(); + while (!atomic_read(&tsc_start_flag)) + cpu_relax(); for (i = 0; i < NR_LOOPS; i++) { atomic_inc(&tsc_count_start); while (atomic_read(&tsc_count_start) != num_booting_cpus()) - mb(); + cpu_relax(); rdtscll(tsc_values[smp_processor_id()]); if (i == NR_LOOPS-1) write_tsc(0, 0); atomic_inc(&tsc_count_stop); - while (atomic_read(&tsc_count_stop) != num_booting_cpus()) mb(); + while (atomic_read(&tsc_count_stop) != num_booting_cpus()) + cpu_relax(); } } #undef NR_LOOPS @@ -1433,7 +1436,7 @@ #endif /* Unleash the CPU! */ cpu_set(cpu, smp_commenced_mask); while (!cpu_isset(cpu, cpu_online_map)) - mb(); + cpu_relax(); return 0; } diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c index 52b3ed5..989c852 100644 --- a/arch/i386/kernel/srat.c +++ b/arch/i386/kernel/srat.c @@ -39,7 +39,6 @@ #define NODE_ARRAY_INDEX(x) ((x) / 8) /* #define NODE_ARRAY_OFFSET(x) ((x) % 8) /* 8 bits/char */ #define BMAP_SET(bmap, bit) ((bmap)[NODE_ARRAY_INDEX(bit)] |= 1 << NODE_ARRAY_OFFSET(bit)) #define BMAP_TEST(bmap, bit) ((bmap)[NODE_ARRAY_INDEX(bit)] & (1 << NODE_ARRAY_OFFSET(bit))) -#define MAX_PXM_DOMAINS 256 /* 1 byte and no promises about values */ /* bitmap length; _PXM is at most 255 */ #define PXM_BITMAP_LEN (MAX_PXM_DOMAINS / 8) static u8 pxm_bitmap[PXM_BITMAP_LEN]; /* bitmap of proximity domains */ @@ -213,19 +212,11 @@ static __init void node_read_chunk(int n node_end_pfn[nid] = memory_chunk->end_pfn; } -static u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */ - -int pxm_to_node(int pxm) -{ - return pxm_to_nid_map[pxm]; -} - /* Parse the ACPI Static Resource Affinity Table */ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp) { u8 *start, *end, *p; int i, j, nid; - u8 nid_to_pxm_map[MAX_NUMNODES];/* logical node ID to _PXM map */ start = (u8 *)(&(sratp->reserved) + 1); /* skip header */ p = start; @@ -235,10 +226,6 @@ static int __init acpi20_parse_srat(stru memset(node_memory_chunk, 0, sizeof(node_memory_chunk)); memset(zholes_size, 0, sizeof(zholes_size)); - /* -1 in these maps means not available */ - memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map)); - memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map)); - num_memory_chunks = 0; while (p < end) { switch (*p) { @@ -278,9 +265,7 @@ static int __init acpi20_parse_srat(stru nodes_clear(node_online_map); for (i = 0; i < MAX_PXM_DOMAINS; i++) { if (BMAP_TEST(pxm_bitmap, i)) { - nid = num_online_nodes(); - pxm_to_nid_map[i] = nid; - nid_to_pxm_map[nid] = i; + int nid = acpi_map_pxm_to_node(i); node_set_online(nid); } } @@ -288,7 +273,7 @@ static int __init acpi20_parse_srat(stru /* set cnode id in memory chunk structure */ for (i = 0; i < num_memory_chunks; i++) - node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm]; + node_memory_chunk[i].nid = pxm_to_node(node_memory_chunk[i].pxm); printk("pxm bitmap: "); for (i = 0; i < sizeof(pxm_bitmap); i++) { diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index af56987..dd63d47 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -316,3 +316,4 @@ ENTRY(sys_call_table) .long sys_sync_file_range .long sys_tee /* 315 */ .long sys_vmsplice + .long sys_move_pages diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 9d30747..5f43d04 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -82,13 +82,6 @@ extern unsigned long wall_jiffies; DEFINE_SPINLOCK(rtc_lock); EXPORT_SYMBOL(rtc_lock); -#include - -DEFINE_SPINLOCK(i8253_lock); -EXPORT_SYMBOL(i8253_lock); - -struct timer_opts *cur_timer __read_mostly = &timer_none; - /* * This is a special lock that is owned by the CPU and holds the index * register we are working with. It is required for NMI access to the @@ -118,99 +111,19 @@ void rtc_cmos_write(unsigned char val, u } EXPORT_SYMBOL(rtc_cmos_write); -/* - * This version of gettimeofday has microsecond resolution - * and better than microsecond precision on fast x86 machines with TSC. - */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long seq; - unsigned long usec, sec; - unsigned long max_ntp_tick; - - do { - unsigned long lost; - - seq = read_seqbegin(&xtime_lock); - - usec = cur_timer->get_offset(); - lost = jiffies - wall_jiffies; - - /* - * If time_adjust is negative then NTP is slowing the clock - * so make sure not to go into next possible interval. - * Better to lose some accuracy than have time go backwards.. - */ - if (unlikely(time_adjust < 0)) { - max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj; - usec = min(usec, max_ntp_tick); - - if (lost) - usec += lost * max_ntp_tick; - } - else if (unlikely(lost)) - usec += lost * (USEC_PER_SEC / HZ); - - sec = xtime.tv_sec; - usec += (xtime.tv_nsec / 1000); - } while (read_seqretry(&xtime_lock, seq)); - - while (usec >= 1000000) { - usec -= 1000000; - sec++; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -EXPORT_SYMBOL(do_gettimeofday); - -int do_settimeofday(struct timespec *tv) -{ - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - write_seqlock_irq(&xtime_lock); - /* - * This is revolting. We need to set "xtime" correctly. However, the - * value in this location is the value at the most recent update of - * wall time. Discover what correction gettimeofday() would have - * made, and then undo it! - */ - nsec -= cur_timer->get_offset() * NSEC_PER_USEC; - nsec -= (jiffies - wall_jiffies) * TICK_NSEC; - - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - ntp_clear(); - write_sequnlock_irq(&xtime_lock); - clock_was_set(); - return 0; -} - -EXPORT_SYMBOL(do_settimeofday); - static int set_rtc_mmss(unsigned long nowtime) { int retval; - - WARN_ON(irqs_disabled()); + unsigned long flags; /* gets recalled with irq locally disabled */ - spin_lock_irq(&rtc_lock); + /* XXX - does irqsave resolve this? -johnstul */ + spin_lock_irqsave(&rtc_lock, flags); if (efi_enabled) retval = efi_set_rtc_mmss(nowtime); else retval = mach_set_rtc_mmss(nowtime); - spin_unlock_irq(&rtc_lock); + spin_unlock_irqrestore(&rtc_lock, flags); return retval; } @@ -218,16 +131,6 @@ static int set_rtc_mmss(unsigned long no int timer_ack; -/* monotonic_clock(): returns # of nanoseconds passed since time_init() - * Note: This function is required to return accurate - * time even in the absence of multiple timer ticks. - */ -unsigned long long monotonic_clock(void) -{ - return cur_timer->monotonic_clock(); -} -EXPORT_SYMBOL(monotonic_clock); - #if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER) unsigned long profile_pc(struct pt_regs *regs) { @@ -242,11 +145,21 @@ EXPORT_SYMBOL(profile_pc); #endif /* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick + * This is the same as the above, except we _also_ save the current + * Time Stamp Counter value at the time of the timer interrupt, so that + * we later on can estimate the time of day more exactly. */ -static inline void do_timer_interrupt(int irq, struct pt_regs *regs) +irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + /* + * Here we are in the timer irq handler. We just have irqs locally + * disabled but we don't know if the timer_bh is running on the other + * CPU. We need to avoid to SMP race with it. NOTE: we don' t need + * the irq version of write_lock because as just said we have irq + * locally disabled. -arca + */ + write_seqlock(&xtime_lock); + #ifdef CONFIG_X86_IO_APIC if (timer_ack) { /* @@ -279,27 +192,6 @@ #endif irq = inb_p( 0x61 ); /* read the current state */ outb_p( irq|0x80, 0x61 ); /* reset the IRQ */ } -} - -/* - * This is the same as the above, except we _also_ save the current - * Time Stamp Counter value at the time of the timer interrupt, so that - * we later on can estimate the time of day more exactly. - */ -irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - /* - * Here we are in the timer irq handler. We just have irqs locally - * disabled but we don't know if the timer_bh is running on the other - * CPU. We need to avoid to SMP race with it. NOTE: we don' t need - * the irq version of write_lock because as just said we have irq - * locally disabled. -arca - */ - write_seqlock(&xtime_lock); - - cur_timer->mark_offset(); - - do_timer_interrupt(irq, regs); write_sequnlock(&xtime_lock); @@ -380,7 +272,6 @@ void notify_arch_cmos_timer(void) static long clock_cmos_diff, sleep_start; -static struct timer_opts *last_timer; static int timer_suspend(struct sys_device *dev, pm_message_t state) { /* @@ -389,10 +280,6 @@ static int timer_suspend(struct sys_devi clock_cmos_diff = -get_cmos_time(); clock_cmos_diff += get_seconds(); sleep_start = get_cmos_time(); - last_timer = cur_timer; - cur_timer = &timer_none; - if (last_timer->suspend) - last_timer->suspend(state); return 0; } @@ -415,10 +302,6 @@ #endif jiffies_64 += sleep_length; wall_jiffies += sleep_length; write_sequnlock_irqrestore(&xtime_lock, flags); - if (last_timer->resume) - last_timer->resume(); - cur_timer = last_timer; - last_timer = NULL; touch_softlockup_watchdog(); return 0; } @@ -460,9 +343,6 @@ static void __init hpet_time_init(void) printk("Using HPET for base-timer\n"); } - cur_timer = select_timer(); - printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); - time_init_hook(); } #endif @@ -484,8 +364,5 @@ #endif set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - cur_timer = select_timer(); - printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name); - time_init_hook(); } diff --git a/arch/i386/kernel/timers/Makefile b/arch/i386/kernel/timers/Makefile deleted file mode 100644 index 8fa12be..0000000 --- a/arch/i386/kernel/timers/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for x86 timers -# - -obj-y := timer.o timer_none.o timer_tsc.o timer_pit.o common.o - -obj-$(CONFIG_X86_CYCLONE_TIMER) += timer_cyclone.o -obj-$(CONFIG_HPET_TIMER) += timer_hpet.o -obj-$(CONFIG_X86_PM_TIMER) += timer_pm.o diff --git a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c deleted file mode 100644 index 8163fe0..0000000 --- a/arch/i386/kernel/timers/common.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Common functions used across the timers go here - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "mach_timer.h" - -/* ------ Calibrate the TSC ------- - * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset(). - * Too much 64-bit arithmetic here to do this cleanly in C, and for - * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2) - * output busy loop as low as possible. We avoid reading the CTC registers - * directly because of the awkward 8-bit access mechanism of the 82C54 - * device. - */ - -#define CALIBRATE_TIME (5 * 1000020/HZ) - -unsigned long calibrate_tsc(void) -{ - mach_prepare_counter(); - - { - unsigned long startlow, starthigh; - unsigned long endlow, endhigh; - unsigned long count; - - rdtsc(startlow,starthigh); - mach_countup(&count); - rdtsc(endlow,endhigh); - - - /* Error: ECTCNEVERSET */ - if (count <= 1) - goto bad_ctc; - - /* 64-bit subtract - gcc just messes up with long longs */ - __asm__("subl %2,%0\n\t" - "sbbl %3,%1" - :"=a" (endlow), "=d" (endhigh) - :"g" (startlow), "g" (starthigh), - "0" (endlow), "1" (endhigh)); - - /* Error: ECPUTOOFAST */ - if (endhigh) - goto bad_ctc; - - /* Error: ECPUTOOSLOW */ - if (endlow <= CALIBRATE_TIME) - goto bad_ctc; - - __asm__("divl %2" - :"=a" (endlow), "=d" (endhigh) - :"r" (endlow), "0" (0), "1" (CALIBRATE_TIME)); - - return endlow; - } - - /* - * The CTC wasn't reliable: we got a hit on the very first read, - * or the CPU was so fast/slow that the quotient wouldn't fit in - * 32 bits.. - */ -bad_ctc: - return 0; -} - -#ifdef CONFIG_HPET_TIMER -/* ------ Calibrate the TSC using HPET ------- - * Return 2^32 * (1 / (TSC clocks per usec)) for getting the CPU freq. - * Second output is parameter 1 (when non NULL) - * Set 2^32 * (1 / (tsc per HPET clk)) for delay_hpet(). - * calibrate_tsc() calibrates the processor TSC by comparing - * it to the HPET timer of known frequency. - * Too much 64-bit arithmetic here to do this cleanly in C - */ -#define CALIBRATE_CNT_HPET (5 * hpet_tick) -#define CALIBRATE_TIME_HPET (5 * KERNEL_TICK_USEC) - -unsigned long __devinit calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr) -{ - unsigned long tsc_startlow, tsc_starthigh; - unsigned long tsc_endlow, tsc_endhigh; - unsigned long hpet_start, hpet_end; - unsigned long result, remain; - - hpet_start = hpet_readl(HPET_COUNTER); - rdtsc(tsc_startlow, tsc_starthigh); - do { - hpet_end = hpet_readl(HPET_COUNTER); - } while ((hpet_end - hpet_start) < CALIBRATE_CNT_HPET); - rdtsc(tsc_endlow, tsc_endhigh); - - /* 64-bit subtract - gcc just messes up with long longs */ - __asm__("subl %2,%0\n\t" - "sbbl %3,%1" - :"=a" (tsc_endlow), "=d" (tsc_endhigh) - :"g" (tsc_startlow), "g" (tsc_starthigh), - "0" (tsc_endlow), "1" (tsc_endhigh)); - - /* Error: ECPUTOOFAST */ - if (tsc_endhigh) - goto bad_calibration; - - /* Error: ECPUTOOSLOW */ - if (tsc_endlow <= CALIBRATE_TIME_HPET) - goto bad_calibration; - - ASM_DIV64_REG(result, remain, tsc_endlow, 0, CALIBRATE_TIME_HPET); - if (remain > (tsc_endlow >> 1)) - result++; /* rounding the result */ - - if (tsc_hpet_quotient_ptr) { - unsigned long tsc_hpet_quotient; - - ASM_DIV64_REG(tsc_hpet_quotient, remain, tsc_endlow, 0, - CALIBRATE_CNT_HPET); - if (remain > (tsc_endlow >> 1)) - tsc_hpet_quotient++; /* rounding the result */ - *tsc_hpet_quotient_ptr = tsc_hpet_quotient; - } - - return result; -bad_calibration: - /* - * the CPU was so fast/slow that the quotient wouldn't fit in - * 32 bits.. - */ - return 0; -} -#endif - - -unsigned long read_timer_tsc(void) -{ - unsigned long retval; - rdtscl(retval); - return retval; -} - - -/* calculate cpu_khz */ -void init_cpu_khz(void) -{ - if (cpu_has_tsc) { - unsigned long tsc_quotient = calibrate_tsc(); - if (tsc_quotient) { - /* report CPU clock rate in Hz. - * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = - * clock/second. Our precision is about 100 ppm. - */ - { unsigned long eax=0, edx=1000; - __asm__("divl %2" - :"=a" (cpu_khz), "=d" (edx) - :"r" (tsc_quotient), - "0" (eax), "1" (edx)); - printk("Detected %u.%03u MHz processor.\n", - cpu_khz / 1000, cpu_khz % 1000); - } - } - } -} - diff --git a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c deleted file mode 100644 index 7e39ed8..0000000 --- a/arch/i386/kernel/timers/timer.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include - -#ifdef CONFIG_HPET_TIMER -/* - * HPET memory read is slower than tsc reads, but is more dependable as it - * always runs at constant frequency and reduces complexity due to - * cpufreq. So, we prefer HPET timer to tsc based one. Also, we cannot use - * timer_pit when HPET is active. So, we default to timer_tsc. - */ -#endif -/* list of timers, ordered by preference, NULL terminated */ -static struct init_timer_opts* __initdata timers[] = { -#ifdef CONFIG_X86_CYCLONE_TIMER - &timer_cyclone_init, -#endif -#ifdef CONFIG_HPET_TIMER - &timer_hpet_init, -#endif -#ifdef CONFIG_X86_PM_TIMER - &timer_pmtmr_init, -#endif - &timer_tsc_init, - &timer_pit_init, - NULL, -}; - -static char clock_override[10] __initdata; - -static int __init clock_setup(char* str) -{ - if (str) - strlcpy(clock_override, str, sizeof(clock_override)); - return 1; -} -__setup("clock=", clock_setup); - - -/* The chosen timesource has been found to be bad. - * Fall back to a known good timesource (the PIT) - */ -void clock_fallback(void) -{ - cur_timer = &timer_pit; -} - -/* iterates through the list of timers, returning the first - * one that initializes successfully. - */ -struct timer_opts* __init select_timer(void) -{ - int i = 0; - - /* find most preferred working timer */ - while (timers[i]) { - if (timers[i]->init) - if (timers[i]->init(clock_override) == 0) - return timers[i]->opts; - ++i; - } - - panic("select_timer: Cannot find a suitable timer\n"); - return NULL; -} - -int read_current_timer(unsigned long *timer_val) -{ - if (cur_timer->read_timer) { - *timer_val = cur_timer->read_timer(); - return 0; - } - return -1; -} diff --git a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c deleted file mode 100644 index 13892a6..0000000 --- a/arch/i386/kernel/timers/timer_cyclone.c +++ /dev/null @@ -1,259 +0,0 @@ -/* Cyclone-timer: - * This code implements timer_ops for the cyclone counter found - * on IBM x440, x360, and other Summit based systems. - * - * Copyright (C) 2002 IBM, John Stultz (johnstul@us.ibm.com) - */ - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "io_ports.h" - -/* Number of usecs that the last interrupt was delayed */ -static int delay_at_last_interrupt; - -#define CYCLONE_CBAR_ADDR 0xFEB00CD0 -#define CYCLONE_PMCC_OFFSET 0x51A0 -#define CYCLONE_MPMC_OFFSET 0x51D0 -#define CYCLONE_MPCS_OFFSET 0x51A8 -#define CYCLONE_TIMER_FREQ 100000000 -#define CYCLONE_TIMER_MASK (((u64)1<<40)-1) /* 40 bit mask */ -int use_cyclone = 0; - -static u32* volatile cyclone_timer; /* Cyclone MPMC0 register */ -static u32 last_cyclone_low; -static u32 last_cyclone_high; -static unsigned long long monotonic_base; -static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; - -/* helper macro to atomically read both cyclone counter registers */ -#define read_cyclone_counter(low,high) \ - do{ \ - high = cyclone_timer[1]; low = cyclone_timer[0]; \ - } while (high != cyclone_timer[1]); - - -static void mark_offset_cyclone(void) -{ - unsigned long lost, delay; - unsigned long delta = last_cyclone_low; - int count; - unsigned long long this_offset, last_offset; - - write_seqlock(&monotonic_lock); - last_offset = ((unsigned long long)last_cyclone_high<<32)|last_cyclone_low; - - spin_lock(&i8253_lock); - read_cyclone_counter(last_cyclone_low,last_cyclone_high); - - /* read values for delay_at_last_interrupt */ - outb_p(0x00, 0x43); /* latch the count ASAP */ - - count = inb_p(0x40); /* read the latched count */ - count |= inb(0x40) << 8; - - /* - * VIA686a test code... reset the latch if count > max + 1 - * from timer_pit.c - cjb - */ - if (count > LATCH) { - outb_p(0x34, PIT_MODE); - outb_p(LATCH & 0xff, PIT_CH0); - outb(LATCH >> 8, PIT_CH0); - count = LATCH - 1; - } - spin_unlock(&i8253_lock); - - /* lost tick compensation */ - delta = last_cyclone_low - delta; - delta /= (CYCLONE_TIMER_FREQ/1000000); - delta += delay_at_last_interrupt; - lost = delta/(1000000/HZ); - delay = delta%(1000000/HZ); - if (lost >= 2) - jiffies_64 += lost-1; - - /* update the monotonic base value */ - this_offset = ((unsigned long long)last_cyclone_high<<32)|last_cyclone_low; - monotonic_base += (this_offset - last_offset) & CYCLONE_TIMER_MASK; - write_sequnlock(&monotonic_lock); - - /* calculate delay_at_last_interrupt */ - count = ((LATCH-1) - count) * TICK_SIZE; - delay_at_last_interrupt = (count + LATCH/2) / LATCH; - - - /* catch corner case where tick rollover occured - * between cyclone and pit reads (as noted when - * usec delta is > 90% # of usecs/tick) - */ - if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ)) - jiffies_64++; -} - -static unsigned long get_offset_cyclone(void) -{ - u32 offset; - - if(!cyclone_timer) - return delay_at_last_interrupt; - - /* Read the cyclone timer */ - offset = cyclone_timer[0]; - - /* .. relative to previous jiffy */ - offset = offset - last_cyclone_low; - - /* convert cyclone ticks to microseconds */ - /* XXX slow, can we speed this up? */ - offset = offset/(CYCLONE_TIMER_FREQ/1000000); - - /* our adjusted time offset in microseconds */ - return delay_at_last_interrupt + offset; -} - -static unsigned long long monotonic_clock_cyclone(void) -{ - u32 now_low, now_high; - unsigned long long last_offset, this_offset, base; - unsigned long long ret; - unsigned seq; - - /* atomically read monotonic base & last_offset */ - do { - seq = read_seqbegin(&monotonic_lock); - last_offset = ((unsigned long long)last_cyclone_high<<32)|last_cyclone_low; - base = monotonic_base; - } while (read_seqretry(&monotonic_lock, seq)); - - - /* Read the cyclone counter */ - read_cyclone_counter(now_low,now_high); - this_offset = ((unsigned long long)now_high<<32)|now_low; - - /* convert to nanoseconds */ - ret = base + ((this_offset - last_offset)&CYCLONE_TIMER_MASK); - return ret * (1000000000 / CYCLONE_TIMER_FREQ); -} - -static int __init init_cyclone(char* override) -{ - u32* reg; - u32 base; /* saved cyclone base address */ - u32 pageaddr; /* page that contains cyclone_timer register */ - u32 offset; /* offset from pageaddr to cyclone_timer register */ - int i; - - /* check clock override */ - if (override[0] && strncmp(override,"cyclone",7)) - return -ENODEV; - - /*make sure we're on a summit box*/ - if(!use_cyclone) return -ENODEV; - - printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n"); - - /* find base address */ - pageaddr = (CYCLONE_CBAR_ADDR)&PAGE_MASK; - offset = (CYCLONE_CBAR_ADDR)&(~PAGE_MASK); - set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr); - reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset); - if(!reg){ - printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n"); - return -ENODEV; - } - base = *reg; - if(!base){ - printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n"); - return -ENODEV; - } - - /* setup PMCC */ - pageaddr = (base + CYCLONE_PMCC_OFFSET)&PAGE_MASK; - offset = (base + CYCLONE_PMCC_OFFSET)&(~PAGE_MASK); - set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr); - reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset); - if(!reg){ - printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n"); - return -ENODEV; - } - reg[0] = 0x00000001; - - /* setup MPCS */ - pageaddr = (base + CYCLONE_MPCS_OFFSET)&PAGE_MASK; - offset = (base + CYCLONE_MPCS_OFFSET)&(~PAGE_MASK); - set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr); - reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset); - if(!reg){ - printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n"); - return -ENODEV; - } - reg[0] = 0x00000001; - - /* map in cyclone_timer */ - pageaddr = (base + CYCLONE_MPMC_OFFSET)&PAGE_MASK; - offset = (base + CYCLONE_MPMC_OFFSET)&(~PAGE_MASK); - set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr); - cyclone_timer = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset); - if(!cyclone_timer){ - printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n"); - return -ENODEV; - } - - /*quick test to make sure its ticking*/ - for(i=0; i<3; i++){ - u32 old = cyclone_timer[0]; - int stall = 100; - while(stall--) barrier(); - if(cyclone_timer[0] == old){ - printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n"); - cyclone_timer = 0; - return -ENODEV; - } - } - - init_cpu_khz(); - - /* Everything looks good! */ - return 0; -} - - -static void delay_cyclone(unsigned long loops) -{ - unsigned long bclock, now; - if(!cyclone_timer) - return; - bclock = cyclone_timer[0]; - do { - rep_nop(); - now = cyclone_timer[0]; - } while ((now-bclock) < loops); -} -/************************************************************/ - -/* cyclone timer_opts struct */ -static struct timer_opts timer_cyclone = { - .name = "cyclone", - .mark_offset = mark_offset_cyclone, - .get_offset = get_offset_cyclone, - .monotonic_clock = monotonic_clock_cyclone, - .delay = delay_cyclone, -}; - -struct init_timer_opts __initdata timer_cyclone_init = { - .init = init_cyclone, - .opts = &timer_cyclone, -}; diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c deleted file mode 100644 index 17a6fe7..0000000 --- a/arch/i386/kernel/timers/timer_hpet.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * This code largely moved from arch/i386/kernel/time.c. - * See comments there for proper credits. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "io_ports.h" -#include "mach_timer.h" -#include - -static unsigned long hpet_usec_quotient __read_mostly; /* convert hpet clks to usec */ -static unsigned long tsc_hpet_quotient __read_mostly; /* convert tsc to hpet clks */ -static unsigned long hpet_last; /* hpet counter value at last tick*/ -static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */ -static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */ -static unsigned long long monotonic_base; -static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; - -/* convert from cycles(64bits) => nanoseconds (64bits) - * basic equation: - * ns = cycles / (freq / ns_per_sec) - * ns = cycles * (ns_per_sec / freq) - * ns = cycles * (10^9 / (cpu_khz * 10^3)) - * ns = cycles * (10^6 / cpu_khz) - * - * Then we use scaling math (suggested by george@mvista.com) to get: - * ns = cycles * (10^6 * SC / cpu_khz) / SC - * ns = cycles * cyc2ns_scale / SC - * - * And since SC is a constant power of two, we can convert the div - * into a shift. - * - * We can use khz divisor instead of mhz to keep a better percision, since - * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits. - * (mathieu.desnoyers@polymtl.ca) - * - * -johnstul@us.ibm.com "math is hard, lets go shopping!" - */ -static unsigned long cyc2ns_scale __read_mostly; -#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ - -static inline void set_cyc2ns_scale(unsigned long cpu_khz) -{ - cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; -} - -static inline unsigned long long cycles_2_ns(unsigned long long cyc) -{ - return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; -} - -static unsigned long long monotonic_clock_hpet(void) -{ - unsigned long long last_offset, this_offset, base; - unsigned seq; - - /* atomically read monotonic base & last_offset */ - do { - seq = read_seqbegin(&monotonic_lock); - last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; - base = monotonic_base; - } while (read_seqretry(&monotonic_lock, seq)); - - /* Read the Time Stamp Counter */ - rdtscll(this_offset); - - /* return the value in ns */ - return base + cycles_2_ns(this_offset - last_offset); -} - -static unsigned long get_offset_hpet(void) -{ - register unsigned long eax, edx; - - eax = hpet_readl(HPET_COUNTER); - eax -= hpet_last; /* hpet delta */ - eax = min(hpet_tick, eax); - /* - * Time offset = (hpet delta) * ( usecs per HPET clock ) - * = (hpet delta) * ( usecs per tick / HPET clocks per tick) - * = (hpet delta) * ( hpet_usec_quotient ) / (2^32) - * - * Where, - * hpet_usec_quotient = (2^32 * usecs per tick)/HPET clocks per tick - * - * Using a mull instead of a divl saves some cycles in critical path. - */ - ASM_MUL64_REG(eax, edx, hpet_usec_quotient, eax); - - /* our adjusted time offset in microseconds */ - return edx; -} - -static void mark_offset_hpet(void) -{ - unsigned long long this_offset, last_offset; - unsigned long offset; - - write_seqlock(&monotonic_lock); - last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; - rdtsc(last_tsc_low, last_tsc_high); - - if (hpet_use_timer) - offset = hpet_readl(HPET_T0_CMP) - hpet_tick; - else - offset = hpet_readl(HPET_COUNTER); - if (unlikely(((offset - hpet_last) >= (2*hpet_tick)) && (hpet_last != 0))) { - int lost_ticks = ((offset - hpet_last) / hpet_tick) - 1; - jiffies_64 += lost_ticks; - } - hpet_last = offset; - - /* update the monotonic base value */ - this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; - monotonic_base += cycles_2_ns(this_offset - last_offset); - write_sequnlock(&monotonic_lock); -} - -static void delay_hpet(unsigned long loops) -{ - unsigned long hpet_start, hpet_end; - unsigned long eax; - - /* loops is the number of cpu cycles. Convert it to hpet clocks */ - ASM_MUL64_REG(eax, loops, tsc_hpet_quotient, loops); - - hpet_start = hpet_readl(HPET_COUNTER); - do { - rep_nop(); - hpet_end = hpet_readl(HPET_COUNTER); - } while ((hpet_end - hpet_start) < (loops)); -} - -static struct timer_opts timer_hpet; - -static int __init init_hpet(char* override) -{ - unsigned long result, remain; - - /* check clock override */ - if (override[0] && strncmp(override,"hpet",4)) - return -ENODEV; - - if (!is_hpet_enabled()) - return -ENODEV; - - printk("Using HPET for gettimeofday\n"); - if (cpu_has_tsc) { - unsigned long tsc_quotient = calibrate_tsc_hpet(&tsc_hpet_quotient); - if (tsc_quotient) { - /* report CPU clock rate in Hz. - * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = - * clock/second. Our precision is about 100 ppm. - */ - { unsigned long eax=0, edx=1000; - ASM_DIV64_REG(cpu_khz, edx, tsc_quotient, - eax, edx); - printk("Detected %u.%03u MHz processor.\n", - cpu_khz / 1000, cpu_khz % 1000); - } - set_cyc2ns_scale(cpu_khz); - } - /* set this only when cpu_has_tsc */ - timer_hpet.read_timer = read_timer_tsc; - } - - /* - * Math to calculate hpet to usec multiplier - * Look for the comments at get_offset_hpet() - */ - ASM_DIV64_REG(result, remain, hpet_tick, 0, KERNEL_TICK_USEC); - if (remain > (hpet_tick >> 1)) - result++; /* rounding the result */ - hpet_usec_quotient = result; - - return 0; -} - -static int hpet_resume(void) -{ - write_seqlock(&monotonic_lock); - /* Assume this is the last mark offset time */ - rdtsc(last_tsc_low, last_tsc_high); - - if (hpet_use_timer) - hpet_last = hpet_readl(HPET_T0_CMP) - hpet_tick; - else - hpet_last = hpet_readl(HPET_COUNTER); - write_sequnlock(&monotonic_lock); - return 0; -} -/************************************************************/ - -/* tsc timer_opts struct */ -static struct timer_opts timer_hpet __read_mostly = { - .name = "hpet", - .mark_offset = mark_offset_hpet, - .get_offset = get_offset_hpet, - .monotonic_clock = monotonic_clock_hpet, - .delay = delay_hpet, - .resume = hpet_resume, -}; - -struct init_timer_opts __initdata timer_hpet_init = { - .init = init_hpet, - .opts = &timer_hpet, -}; diff --git a/arch/i386/kernel/timers/timer_none.c b/arch/i386/kernel/timers/timer_none.c deleted file mode 100644 index 4ea2f41..0000000 --- a/arch/i386/kernel/timers/timer_none.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include - -static void mark_offset_none(void) -{ - /* nothing needed */ -} - -static unsigned long get_offset_none(void) -{ - return 0; -} - -static unsigned long long monotonic_clock_none(void) -{ - return 0; -} - -static void delay_none(unsigned long loops) -{ - int d0; - __asm__ __volatile__( - "\tjmp 1f\n" - ".align 16\n" - "1:\tjmp 2f\n" - ".align 16\n" - "2:\tdecl %0\n\tjns 2b" - :"=&a" (d0) - :"0" (loops)); -} - -/* none timer_opts struct */ -struct timer_opts timer_none = { - .name = "none", - .mark_offset = mark_offset_none, - .get_offset = get_offset_none, - .monotonic_clock = monotonic_clock_none, - .delay = delay_none, -}; diff --git a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c deleted file mode 100644 index b9b6bd5..0000000 --- a/arch/i386/kernel/timers/timer_pit.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This code largely moved from arch/i386/kernel/time.c. - * See comments there for proper credits. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "do_timer.h" -#include "io_ports.h" - -static int count_p; /* counter in get_offset_pit() */ - -static int __init init_pit(char* override) -{ - /* check clock override */ - if (override[0] && strncmp(override,"pit",3)) - printk(KERN_ERR "Warning: clock= override failed. Defaulting " - "to PIT\n"); - init_cpu_khz(); - count_p = LATCH; - return 0; -} - -static void mark_offset_pit(void) -{ - /* nothing needed */ -} - -static unsigned long long monotonic_clock_pit(void) -{ - return 0; -} - -static void delay_pit(unsigned long loops) -{ - int d0; - __asm__ __volatile__( - "\tjmp 1f\n" - ".align 16\n" - "1:\tjmp 2f\n" - ".align 16\n" - "2:\tdecl %0\n\tjns 2b" - :"=&a" (d0) - :"0" (loops)); -} - - -/* This function must be called with xtime_lock held. - * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs - * - * However, the pc-audio speaker driver changes the divisor so that - * it gets interrupted rather more often - it loads 64 into the - * counter rather than 11932! This has an adverse impact on - * do_gettimeoffset() -- it stops working! What is also not - * good is that the interval that our timer function gets called - * is no longer 10.0002 ms, but 9.9767 ms. To get around this - * would require using a different timing source. Maybe someone - * could use the RTC - I know that this can interrupt at frequencies - * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix - * it so that at startup, the timer code in sched.c would select - * using either the RTC or the 8253 timer. The decision would be - * based on whether there was any other device around that needed - * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz, - * and then do some jiggery to have a version of do_timer that - * advanced the clock by 1/1024 s. Every time that reached over 1/100 - * of a second, then do all the old code. If the time was kept correct - * then do_gettimeoffset could just return 0 - there is no low order - * divider that can be accessed. - * - * Ideally, you would be able to use the RTC for the speaker driver, - * but it appears that the speaker driver really needs interrupt more - * often than every 120 us or so. - * - * Anyway, this needs more thought.... pjsg (1993-08-28) - * - * If you are really that interested, you should be reading - * comp.protocols.time.ntp! - */ - -static unsigned long get_offset_pit(void) -{ - int count; - unsigned long flags; - static unsigned long jiffies_p = 0; - - /* - * cache volatile jiffies temporarily; we have xtime_lock. - */ - unsigned long jiffies_t; - - spin_lock_irqsave(&i8253_lock, flags); - /* timer count may underflow right here */ - outb_p(0x00, PIT_MODE); /* latch the count ASAP */ - - count = inb_p(PIT_CH0); /* read the latched count */ - - /* - * We do this guaranteed double memory access instead of a _p - * postfix in the previous port access. Wheee, hackady hack - */ - jiffies_t = jiffies; - - count |= inb_p(PIT_CH0) << 8; - - /* VIA686a test code... reset the latch if count > max + 1 */ - if (count > LATCH) { - outb_p(0x34, PIT_MODE); - outb_p(LATCH & 0xff, PIT_CH0); - outb(LATCH >> 8, PIT_CH0); - count = LATCH - 1; - } - - /* - * avoiding timer inconsistencies (they are rare, but they happen)... - * there are two kinds of problems that must be avoided here: - * 1. the timer counter underflows - * 2. hardware problem with the timer, not giving us continuous time, - * the counter does small "jumps" upwards on some Pentium systems, - * (see c't 95/10 page 335 for Neptun bug.) - */ - - if( jiffies_t == jiffies_p ) { - if( count > count_p ) { - /* the nutcase */ - count = do_timer_overflow(count); - } - } else - jiffies_p = jiffies_t; - - count_p = count; - - spin_unlock_irqrestore(&i8253_lock, flags); - - count = ((LATCH-1) - count) * TICK_SIZE; - count = (count + LATCH/2) / LATCH; - - return count; -} - - -/* tsc timer_opts struct */ -struct timer_opts timer_pit = { - .name = "pit", - .mark_offset = mark_offset_pit, - .get_offset = get_offset_pit, - .monotonic_clock = monotonic_clock_pit, - .delay = delay_pit, -}; - -struct init_timer_opts __initdata timer_pit_init = { - .init = init_pit, - .opts = &timer_pit, -}; - -void setup_pit_timer(void) -{ - unsigned long flags; - - spin_lock_irqsave(&i8253_lock, flags); - outb_p(0x34,PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */ - udelay(10); - outb_p(LATCH & 0xff , PIT_CH0); /* LSB */ - udelay(10); - outb(LATCH >> 8 , PIT_CH0); /* MSB */ - spin_unlock_irqrestore(&i8253_lock, flags); -} diff --git a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c deleted file mode 100644 index 144e94a..0000000 --- a/arch/i386/kernel/timers/timer_pm.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * (C) Dominik Brodowski 2003 - * - * Driver to use the Power Management Timer (PMTMR) available in some - * southbridges as primary timing source for the Linux kernel. - * - * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c, - * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4. - * - * This file is licensed under the GPL v2. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "mach_timer.h" - -/* Number of PMTMR ticks expected during calibration run */ -#define PMTMR_TICKS_PER_SEC 3579545 -#define PMTMR_EXPECTED_RATE \ - ((CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (CLOCK_TICK_RATE>>10)) - - -/* The I/O port the PMTMR resides at. - * The location is detected during setup_arch(), - * in arch/i386/acpi/boot.c */ -u32 pmtmr_ioport = 0; - - -/* value of the Power timer at last timer interrupt */ -static u32 offset_tick; -static u32 offset_delay; - -static unsigned long long monotonic_base; -static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; - -#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */ - -static int pmtmr_need_workaround __read_mostly = 1; - -/*helper function to safely read acpi pm timesource*/ -static inline u32 read_pmtmr(void) -{ - if (pmtmr_need_workaround) { - u32 v1, v2, v3; - - /* It has been reported that because of various broken - * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time - * source is not latched, so you must read it multiple - * times to insure a safe value is read. - */ - do { - v1 = inl(pmtmr_ioport); - v2 = inl(pmtmr_ioport); - v3 = inl(pmtmr_ioport); - } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) - || (v3 > v1 && v3 < v2)); - - /* mask the output to 24 bits */ - return v2 & ACPI_PM_MASK; - } - - return inl(pmtmr_ioport) & ACPI_PM_MASK; -} - - -/* - * Some boards have the PMTMR running way too fast. We check - * the PMTMR rate against PIT channel 2 to catch these cases. - */ -static int verify_pmtmr_rate(void) -{ - u32 value1, value2; - unsigned long count, delta; - - mach_prepare_counter(); - value1 = read_pmtmr(); - mach_countup(&count); - value2 = read_pmtmr(); - delta = (value2 - value1) & ACPI_PM_MASK; - - /* Check that the PMTMR delta is within 5% of what we expect */ - if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 || - delta > (PMTMR_EXPECTED_RATE * 21) / 20) { - printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% of normal - aborting.\n", 100UL * delta / PMTMR_EXPECTED_RATE); - return -1; - } - - return 0; -} - - -static int init_pmtmr(char* override) -{ - u32 value1, value2; - unsigned int i; - - if (override[0] && strncmp(override,"pmtmr",5)) - return -ENODEV; - - if (!pmtmr_ioport) - return -ENODEV; - - /* we use the TSC for delay_pmtmr, so make sure it exists */ - if (!cpu_has_tsc) - return -ENODEV; - - /* "verify" this timing source */ - value1 = read_pmtmr(); - for (i = 0; i < 10000; i++) { - value2 = read_pmtmr(); - if (value2 == value1) - continue; - if (value2 > value1) - goto pm_good; - if ((value2 < value1) && ((value2) < 0xFFF)) - goto pm_good; - printk(KERN_INFO "PM-Timer had inconsistent results: 0x%#x, 0x%#x - aborting.\n", value1, value2); - return -EINVAL; - } - printk(KERN_INFO "PM-Timer had no reasonable result: 0x%#x - aborting.\n", value1); - return -ENODEV; - -pm_good: - if (verify_pmtmr_rate() != 0) - return -ENODEV; - - init_cpu_khz(); - return 0; -} - -static inline u32 cyc2us(u32 cycles) -{ - /* The Power Management Timer ticks at 3.579545 ticks per microsecond. - * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%] - * - * Even with HZ = 100, delta is at maximum 35796 ticks, so it can - * easily be multiplied with 286 (=0x11E) without having to fear - * u32 overflows. - */ - cycles *= 286; - return (cycles >> 10); -} - -/* - * this gets called during each timer interrupt - * - Called while holding the writer xtime_lock - */ -static void mark_offset_pmtmr(void) -{ - u32 lost, delta, last_offset; - static int first_run = 1; - last_offset = offset_tick; - - write_seqlock(&monotonic_lock); - - offset_tick = read_pmtmr(); - - /* calculate tick interval */ - delta = (offset_tick - last_offset) & ACPI_PM_MASK; - - /* convert to usecs */ - delta = cyc2us(delta); - - /* update the monotonic base value */ - monotonic_base += delta * NSEC_PER_USEC; - write_sequnlock(&monotonic_lock); - - /* convert to ticks */ - delta += offset_delay; - lost = delta / (USEC_PER_SEC / HZ); - offset_delay = delta % (USEC_PER_SEC / HZ); - - - /* compensate for lost ticks */ - if (lost >= 2) - jiffies_64 += lost - 1; - - /* don't calculate delay for first run, - or if we've got less then a tick */ - if (first_run || (lost < 1)) { - first_run = 0; - offset_delay = 0; - } -} - -static int pmtmr_resume(void) -{ - write_seqlock(&monotonic_lock); - /* Assume this is the last mark offset time */ - offset_tick = read_pmtmr(); - write_sequnlock(&monotonic_lock); - return 0; -} - -static unsigned long long monotonic_clock_pmtmr(void) -{ - u32 last_offset, this_offset; - unsigned long long base, ret; - unsigned seq; - - - /* atomically read monotonic base & last_offset */ - do { - seq = read_seqbegin(&monotonic_lock); - last_offset = offset_tick; - base = monotonic_base; - } while (read_seqretry(&monotonic_lock, seq)); - - /* Read the pmtmr */ - this_offset = read_pmtmr(); - - /* convert to nanoseconds */ - ret = (this_offset - last_offset) & ACPI_PM_MASK; - ret = base + (cyc2us(ret) * NSEC_PER_USEC); - return ret; -} - -static void delay_pmtmr(unsigned long loops) -{ - unsigned long bclock, now; - - rdtscl(bclock); - do - { - rep_nop(); - rdtscl(now); - } while ((now-bclock) < loops); -} - - -/* - * get the offset (in microseconds) from the last call to mark_offset() - * - Called holding a reader xtime_lock - */ -static unsigned long get_offset_pmtmr(void) -{ - u32 now, offset, delta = 0; - - offset = offset_tick; - now = read_pmtmr(); - delta = (now - offset)&ACPI_PM_MASK; - - return (unsigned long) offset_delay + cyc2us(delta); -} - - -/* acpi timer_opts struct */ -static struct timer_opts timer_pmtmr = { - .name = "pmtmr", - .mark_offset = mark_offset_pmtmr, - .get_offset = get_offset_pmtmr, - .monotonic_clock = monotonic_clock_pmtmr, - .delay = delay_pmtmr, - .read_timer = read_timer_tsc, - .resume = pmtmr_resume, -}; - -struct init_timer_opts __initdata timer_pmtmr_init = { - .init = init_pmtmr, - .opts = &timer_pmtmr, -}; - -#ifdef CONFIG_PCI -/* - * PIIX4 Errata: - * - * The power management timer may return improper results when read. - * Although the timer value settles properly after incrementing, - * while incrementing there is a 3 ns window every 69.8 ns where the - * timer value is indeterminate (a 4.2% chance that the data will be - * incorrect when read). As a result, the ACPI free running count up - * timer specification is violated due to erroneous reads. - */ -static int __init pmtmr_bug_check(void) -{ - static struct pci_device_id gray_list[] __initdata = { - /* these chipsets may have bug. */ - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801DB_0) }, - { }, - }; - struct pci_dev *dev; - int pmtmr_has_bug = 0; - u8 rev; - - if (cur_timer != &timer_pmtmr || !pmtmr_need_workaround) - return 0; - - dev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, NULL); - if (dev) { - pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - /* the bug has been fixed in PIIX4M */ - if (rev < 3) { - printk(KERN_WARNING "* Found PM-Timer Bug on this " - "chipset. Due to workarounds for a bug,\n" - "* this time source is slow. Consider trying " - "other time sources (clock=)\n"); - pmtmr_has_bug = 1; - } - pci_dev_put(dev); - } - - if (pci_dev_present(gray_list)) { - printk(KERN_WARNING "* This chipset may have PM-Timer Bug. Due" - " to workarounds for a bug,\n" - "* this time source is slow. If you are sure your timer" - " does not have\n" - "* this bug, please use \"pmtmr_good\" to disable the " - "workaround\n"); - pmtmr_has_bug = 1; - } - - if (!pmtmr_has_bug) - pmtmr_need_workaround = 0; - - return 0; -} -device_initcall(pmtmr_bug_check); -#endif - -static int __init pmtr_good_setup(char *__str) -{ - pmtmr_need_workaround = 0; - return 1; -} -__setup("pmtmr_good", pmtr_good_setup); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Dominik Brodowski "); -MODULE_DESCRIPTION("Power Management Timer (PMTMR) as primary timing source for x86"); diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c deleted file mode 100644 index f1187dd..0000000 --- a/arch/i386/kernel/timers/timer_tsc.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - * This code largely moved from arch/i386/kernel/time.c. - * See comments there for proper credits. - * - * 2004-06-25 Jesper Juhl - * moved mark_offset_tsc below cpufreq_delayed_get to avoid gcc 3.4 - * failing to inline. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -/* processor.h for distable_tsc flag */ -#include - -#include "io_ports.h" -#include "mach_timer.h" - -#include -#include - -#ifdef CONFIG_HPET_TIMER -static unsigned long hpet_usec_quotient; -static unsigned long hpet_last; -static struct timer_opts timer_tsc; -#endif - -static inline void cpufreq_delayed_get(void); - -int tsc_disable __devinitdata = 0; - -static int use_tsc; -/* Number of usecs that the last interrupt was delayed */ -static int delay_at_last_interrupt; - -static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */ -static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */ -static unsigned long long monotonic_base; -static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; - -/* Avoid compensating for lost ticks before TSCs are synched */ -static int detect_lost_ticks; -static int __init start_lost_tick_compensation(void) -{ - detect_lost_ticks = 1; - return 0; -} -late_initcall(start_lost_tick_compensation); - -/* convert from cycles(64bits) => nanoseconds (64bits) - * basic equation: - * ns = cycles / (freq / ns_per_sec) - * ns = cycles * (ns_per_sec / freq) - * ns = cycles * (10^9 / (cpu_khz * 10^3)) - * ns = cycles * (10^6 / cpu_khz) - * - * Then we use scaling math (suggested by george@mvista.com) to get: - * ns = cycles * (10^6 * SC / cpu_khz) / SC - * ns = cycles * cyc2ns_scale / SC - * - * And since SC is a constant power of two, we can convert the div - * into a shift. - * - * We can use khz divisor instead of mhz to keep a better percision, since - * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits. - * (mathieu.desnoyers@polymtl.ca) - * - * -johnstul@us.ibm.com "math is hard, lets go shopping!" - */ -static unsigned long cyc2ns_scale __read_mostly; -#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ - -static inline void set_cyc2ns_scale(unsigned long cpu_khz) -{ - cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; -} - -static inline unsigned long long cycles_2_ns(unsigned long long cyc) -{ - return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; -} - -static int count2; /* counter for mark_offset_tsc() */ - -/* Cached *multiplier* to convert TSC counts to microseconds. - * (see the equation below). - * Equal to 2^32 * (1 / (clocks per usec) ). - * Initialized in time_init. - */ -static unsigned long fast_gettimeoffset_quotient; - -static unsigned long get_offset_tsc(void) -{ - register unsigned long eax, edx; - - /* Read the Time Stamp Counter */ - - rdtsc(eax,edx); - - /* .. relative to previous jiffy (32 bits is enough) */ - eax -= last_tsc_low; /* tsc_low delta */ - - /* - * Time offset = (tsc_low delta) * fast_gettimeoffset_quotient - * = (tsc_low delta) * (usecs_per_clock) - * = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy) - * - * Using a mull instead of a divl saves up to 31 clock cycles - * in the critical path. - */ - - __asm__("mull %2" - :"=a" (eax), "=d" (edx) - :"rm" (fast_gettimeoffset_quotient), - "0" (eax)); - - /* our adjusted time offset in microseconds */ - return delay_at_last_interrupt + edx; -} - -static unsigned long long monotonic_clock_tsc(void) -{ - unsigned long long last_offset, this_offset, base; - unsigned seq; - - /* atomically read monotonic base & last_offset */ - do { - seq = read_seqbegin(&monotonic_lock); - last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; - base = monotonic_base; - } while (read_seqretry(&monotonic_lock, seq)); - - /* Read the Time Stamp Counter */ - rdtscll(this_offset); - - /* return the value in ns */ - return base + cycles_2_ns(this_offset - last_offset); -} - -/* - * Scheduler clock - returns current time in nanosec units. - */ -unsigned long long sched_clock(void) -{ - unsigned long long this_offset; - - /* - * In the NUMA case we dont use the TSC as they are not - * synchronized across all CPUs. - */ -#ifndef CONFIG_NUMA - if (!use_tsc) -#endif - /* no locking but a rare wrong value is not a big deal */ - return jiffies_64 * (1000000000 / HZ); - - /* Read the Time Stamp Counter */ - rdtscll(this_offset); - - /* return the value in ns */ - return cycles_2_ns(this_offset); -} - -static void delay_tsc(unsigned long loops) -{ - unsigned long bclock, now; - - rdtscl(bclock); - do - { - rep_nop(); - rdtscl(now); - } while ((now-bclock) < loops); -} - -#ifdef CONFIG_HPET_TIMER -static void mark_offset_tsc_hpet(void) -{ - unsigned long long this_offset, last_offset; - unsigned long offset, temp, hpet_current; - - write_seqlock(&monotonic_lock); - last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; - /* - * It is important that these two operations happen almost at - * the same time. We do the RDTSC stuff first, since it's - * faster. To avoid any inconsistencies, we need interrupts - * disabled locally. - */ - /* - * Interrupts are just disabled locally since the timer irq - * has the SA_INTERRUPT flag set. -arca - */ - /* read Pentium cycle counter */ - - hpet_current = hpet_readl(HPET_COUNTER); - rdtsc(last_tsc_low, last_tsc_high); - - /* lost tick compensation */ - offset = hpet_readl(HPET_T0_CMP) - hpet_tick; - if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0)) - && detect_lost_ticks) { - int lost_ticks = (offset - hpet_last) / hpet_tick; - jiffies_64 += lost_ticks; - } - hpet_last = hpet_current; - - /* update the monotonic base value */ - this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; - monotonic_base += cycles_2_ns(this_offset - last_offset); - write_sequnlock(&monotonic_lock); - - /* calculate delay_at_last_interrupt */ - /* - * Time offset = (hpet delta) * ( usecs per HPET clock ) - * = (hpet delta) * ( usecs per tick / HPET clocks per tick) - * = (hpet delta) * ( hpet_usec_quotient ) / (2^32) - * Where, - * hpet_usec_quotient = (2^32 * usecs per tick)/HPET clocks per tick - */ - delay_at_last_interrupt = hpet_current - offset; - ASM_MUL64_REG(temp, delay_at_last_interrupt, - hpet_usec_quotient, delay_at_last_interrupt); -} -#endif - - -#ifdef CONFIG_CPU_FREQ -#include - -static unsigned int cpufreq_delayed_issched = 0; -static unsigned int cpufreq_init = 0; -static struct work_struct cpufreq_delayed_get_work; - -static void handle_cpufreq_delayed_get(void *v) -{ - unsigned int cpu; - for_each_online_cpu(cpu) { - cpufreq_get(cpu); - } - cpufreq_delayed_issched = 0; -} - -/* if we notice lost ticks, schedule a call to cpufreq_get() as it tries - * to verify the CPU frequency the timing core thinks the CPU is running - * at is still correct. - */ -static inline void cpufreq_delayed_get(void) -{ - if (cpufreq_init && !cpufreq_delayed_issched) { - cpufreq_delayed_issched = 1; - printk(KERN_DEBUG "Losing some ticks... checking if CPU frequency changed.\n"); - schedule_work(&cpufreq_delayed_get_work); - } -} - -/* If the CPU frequency is scaled, TSC-based delays will need a different - * loops_per_jiffy value to function properly. - */ - -static unsigned int ref_freq = 0; -static unsigned long loops_per_jiffy_ref = 0; - -#ifndef CONFIG_SMP -static unsigned long fast_gettimeoffset_ref = 0; -static unsigned int cpu_khz_ref = 0; -#endif - -static int -time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - struct cpufreq_freqs *freq = data; - - if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE) - write_seqlock_irq(&xtime_lock); - if (!ref_freq) { - if (!freq->old){ - ref_freq = freq->new; - goto end; - } - ref_freq = freq->old; - loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; -#ifndef CONFIG_SMP - fast_gettimeoffset_ref = fast_gettimeoffset_quotient; - cpu_khz_ref = cpu_khz; -#endif - } - - if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || - (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || - (val == CPUFREQ_RESUMECHANGE)) { - if (!(freq->flags & CPUFREQ_CONST_LOOPS)) - cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new); -#ifndef CONFIG_SMP - if (cpu_khz) - cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new); - if (use_tsc) { - if (!(freq->flags & CPUFREQ_CONST_LOOPS)) { - fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq); - set_cyc2ns_scale(cpu_khz); - } - } -#endif - } - -end: - if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE) - write_sequnlock_irq(&xtime_lock); - - return 0; -} - -static struct notifier_block time_cpufreq_notifier_block = { - .notifier_call = time_cpufreq_notifier -}; - - -static int __init cpufreq_tsc(void) -{ - int ret; - INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); - ret = cpufreq_register_notifier(&time_cpufreq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); - if (!ret) - cpufreq_init = 1; - return ret; -} -core_initcall(cpufreq_tsc); - -#else /* CONFIG_CPU_FREQ */ -static inline void cpufreq_delayed_get(void) { return; } -#endif - -int recalibrate_cpu_khz(void) -{ -#ifndef CONFIG_SMP - unsigned int cpu_khz_old = cpu_khz; - - if (cpu_has_tsc) { - local_irq_disable(); - init_cpu_khz(); - local_irq_enable(); - cpu_data[0].loops_per_jiffy = - cpufreq_scale(cpu_data[0].loops_per_jiffy, - cpu_khz_old, - cpu_khz); - return 0; - } else - return -ENODEV; -#else - return -ENODEV; -#endif -} -EXPORT_SYMBOL(recalibrate_cpu_khz); - -static void mark_offset_tsc(void) -{ - unsigned long lost,delay; - unsigned long delta = last_tsc_low; - int count; - int countmp; - static int count1 = 0; - unsigned long long this_offset, last_offset; - static int lost_count = 0; - - write_seqlock(&monotonic_lock); - last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; - /* - * It is important that these two operations happen almost at - * the same time. We do the RDTSC stuff first, since it's - * faster. To avoid any inconsistencies, we need interrupts - * disabled locally. - */ - - /* - * Interrupts are just disabled locally since the timer irq - * has the SA_INTERRUPT flag set. -arca - */ - - /* read Pentium cycle counter */ - - rdtsc(last_tsc_low, last_tsc_high); - - spin_lock(&i8253_lock); - outb_p(0x00, PIT_MODE); /* latch the count ASAP */ - - count = inb_p(PIT_CH0); /* read the latched count */ - count |= inb(PIT_CH0) << 8; - - /* - * VIA686a test code... reset the latch if count > max + 1 - * from timer_pit.c - cjb - */ - if (count > LATCH) { - outb_p(0x34, PIT_MODE); - outb_p(LATCH & 0xff, PIT_CH0); - outb(LATCH >> 8, PIT_CH0); - count = LATCH - 1; - } - - spin_unlock(&i8253_lock); - - if (pit_latch_buggy) { - /* get center value of last 3 time lutch */ - if ((count2 >= count && count >= count1) - || (count1 >= count && count >= count2)) { - count2 = count1; count1 = count; - } else if ((count1 >= count2 && count2 >= count) - || (count >= count2 && count2 >= count1)) { - countmp = count;count = count2; - count2 = count1;count1 = countmp; - } else { - count2 = count1; count1 = count; count = count1; - } - } - - /* lost tick compensation */ - delta = last_tsc_low - delta; - { - register unsigned long eax, edx; - eax = delta; - __asm__("mull %2" - :"=a" (eax), "=d" (edx) - :"rm" (fast_gettimeoffset_quotient), - "0" (eax)); - delta = edx; - } - delta += delay_at_last_interrupt; - lost = delta/(1000000/HZ); - delay = delta%(1000000/HZ); - if (lost >= 2 && detect_lost_ticks) { - jiffies_64 += lost-1; - - /* sanity check to ensure we're not always losing ticks */ - if (lost_count++ > 100) { - printk(KERN_WARNING "Losing too many ticks!\n"); - printk(KERN_WARNING "TSC cannot be used as a timesource. \n"); - printk(KERN_WARNING "Possible reasons for this are:\n"); - printk(KERN_WARNING " You're running with Speedstep,\n"); - printk(KERN_WARNING " You don't have DMA enabled for your hard disk (see hdparm),\n"); - printk(KERN_WARNING " Incorrect TSC synchronization on an SMP system (see dmesg).\n"); - printk(KERN_WARNING "Falling back to a sane timesource now.\n"); - - clock_fallback(); - } - /* ... but give the TSC a fair chance */ - if (lost_count > 25) - cpufreq_delayed_get(); - } else - lost_count = 0; - /* update the monotonic base value */ - this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; - monotonic_base += cycles_2_ns(this_offset - last_offset); - write_sequnlock(&monotonic_lock); - - /* calculate delay_at_last_interrupt */ - count = ((LATCH-1) - count) * TICK_SIZE; - delay_at_last_interrupt = (count + LATCH/2) / LATCH; - - /* catch corner case where tick rollover occured - * between tsc and pit reads (as noted when - * usec delta is > 90% # of usecs/tick) - */ - if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ)) - jiffies_64++; -} - -static int __init init_tsc(char* override) -{ - - /* check clock override */ - if (override[0] && strncmp(override,"tsc",3)) { -#ifdef CONFIG_HPET_TIMER - if (is_hpet_enabled()) { - printk(KERN_ERR "Warning: clock= override failed. Defaulting to tsc\n"); - } else -#endif - { - return -ENODEV; - } - } - - /* - * If we have APM enabled or the CPU clock speed is variable - * (CPU stops clock on HLT or slows clock to save power) - * then the TSC timestamps may diverge by up to 1 jiffy from - * 'real time' but nothing will break. - * The most frequent case is that the CPU is "woken" from a halt - * state by the timer interrupt itself, so we get 0 error. In the - * rare cases where a driver would "wake" the CPU and request a - * timestamp, the maximum error is < 1 jiffy. But timestamps are - * still perfectly ordered. - * Note that the TSC counter will be reset if APM suspends - * to disk; this won't break the kernel, though, 'cuz we're - * smart. See arch/i386/kernel/apm.c. - */ - /* - * Firstly we have to do a CPU check for chips with - * a potentially buggy TSC. At this point we haven't run - * the ident/bugs checks so we must run this hook as it - * may turn off the TSC flag. - * - * NOTE: this doesn't yet handle SMP 486 machines where only - * some CPU's have a TSC. Thats never worked and nobody has - * moaned if you have the only one in the world - you fix it! - */ - - count2 = LATCH; /* initialize counter for mark_offset_tsc() */ - - if (cpu_has_tsc) { - unsigned long tsc_quotient; -#ifdef CONFIG_HPET_TIMER - if (is_hpet_enabled() && hpet_use_timer) { - unsigned long result, remain; - printk("Using TSC for gettimeofday\n"); - tsc_quotient = calibrate_tsc_hpet(NULL); - timer_tsc.mark_offset = &mark_offset_tsc_hpet; - /* - * Math to calculate hpet to usec multiplier - * Look for the comments at get_offset_tsc_hpet() - */ - ASM_DIV64_REG(result, remain, hpet_tick, - 0, KERNEL_TICK_USEC); - if (remain > (hpet_tick >> 1)) - result++; /* rounding the result */ - - hpet_usec_quotient = result; - } else -#endif - { - tsc_quotient = calibrate_tsc(); - } - - if (tsc_quotient) { - fast_gettimeoffset_quotient = tsc_quotient; - use_tsc = 1; - /* - * We could be more selective here I suspect - * and just enable this for the next intel chips ? - */ - /* report CPU clock rate in Hz. - * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = - * clock/second. Our precision is about 100 ppm. - */ - { unsigned long eax=0, edx=1000; - __asm__("divl %2" - :"=a" (cpu_khz), "=d" (edx) - :"r" (tsc_quotient), - "0" (eax), "1" (edx)); - printk("Detected %u.%03u MHz processor.\n", - cpu_khz / 1000, cpu_khz % 1000); - } - set_cyc2ns_scale(cpu_khz); - return 0; - } - } - return -ENODEV; -} - -static int tsc_resume(void) -{ - write_seqlock(&monotonic_lock); - /* Assume this is the last mark offset time */ - rdtsc(last_tsc_low, last_tsc_high); -#ifdef CONFIG_HPET_TIMER - if (is_hpet_enabled() && hpet_use_timer) - hpet_last = hpet_readl(HPET_COUNTER); -#endif - write_sequnlock(&monotonic_lock); - return 0; -} - -#ifndef CONFIG_X86_TSC -/* disable flag for tsc. Takes effect by clearing the TSC cpu flag - * in cpu/common.c */ -static int __init tsc_setup(char *str) -{ - tsc_disable = 1; - return 1; -} -#else -static int __init tsc_setup(char *str) -{ - printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, " - "cannot disable TSC.\n"); - return 1; -} -#endif -__setup("notsc", tsc_setup); - - - -/************************************************************/ - -/* tsc timer_opts struct */ -static struct timer_opts timer_tsc = { - .name = "tsc", - .mark_offset = mark_offset_tsc, - .get_offset = get_offset_tsc, - .monotonic_clock = monotonic_clock_tsc, - .delay = delay_tsc, - .read_timer = read_timer_tsc, - .resume = tsc_resume, -}; - -struct init_timer_opts __initdata timer_tsc_init = { - .init = init_tsc, - .opts = &timer_tsc, -}; diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 0e49836..7846409 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -28,6 +28,7 @@ #include #include #include #include +#include #ifdef CONFIG_EISA #include @@ -47,7 +48,7 @@ #include #include #include #include - +#include #include #include #include @@ -92,6 +93,7 @@ asmlinkage void spurious_interrupt_bug(v asmlinkage void machine_check(void); static int kstack_depth_to_print = 24; +static int call_trace = 1; ATOMIC_NOTIFIER_HEAD(i386die_chain); int register_die_notifier(struct notifier_block *nb) @@ -149,6 +151,12 @@ #ifdef CONFIG_FRAME_POINTER while (valid_stack_ptr(tinfo, (void *)ebp)) { addr = *(unsigned long *)(ebp + 4); printed = print_addr_and_symbol(addr, log_lvl, printed); + /* + * break out of recursive entries (such as + * end_of_stack_stop_unwind_function): + */ + if (ebp == *(unsigned long *)ebp) + break; ebp = *(unsigned long *)ebp; } #else @@ -164,7 +172,23 @@ #endif return ebp; } -static void show_trace_log_lvl(struct task_struct *task, +static asmlinkage int show_trace_unwind(struct unwind_frame_info *info, void *log_lvl) +{ + int n = 0; + int printed = 0; /* nr of entries already printed on current line */ + + while (unwind(info) == 0 && UNW_PC(info)) { + ++n; + printed = print_addr_and_symbol(UNW_PC(info), log_lvl, printed); + if (arch_unw_user_mode(info)) + break; + } + if (printed) + printk("\n"); + return n; +} + +static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *stack, char *log_lvl) { unsigned long ebp; @@ -172,6 +196,26 @@ static void show_trace_log_lvl(struct ta if (!task) task = current; + if (call_trace >= 0) { + int unw_ret = 0; + struct unwind_frame_info info; + + if (regs) { + if (unwind_init_frame_info(&info, task, regs) == 0) + unw_ret = show_trace_unwind(&info, log_lvl); + } else if (task == current) + unw_ret = unwind_init_running(&info, show_trace_unwind, log_lvl); + else { + if (unwind_init_blocked(&info, task) == 0) + unw_ret = show_trace_unwind(&info, log_lvl); + } + if (unw_ret > 0) { + if (call_trace > 0) + return; + printk("%sLegacy call trace:\n", log_lvl); + } + } + if (task == current) { /* Grab ebp right from our regs */ asm ("movl %%ebp, %0" : "=r" (ebp) : ); @@ -192,13 +236,13 @@ static void show_trace_log_lvl(struct ta } } -void show_trace(struct task_struct *task, unsigned long * stack) +void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long * stack) { - show_trace_log_lvl(task, stack, ""); + show_trace_log_lvl(task, regs, stack, ""); } -static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp, - char *log_lvl) +static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, + unsigned long *esp, char *log_lvl) { unsigned long *stack; int i; @@ -219,13 +263,13 @@ static void show_stack_log_lvl(struct ta printk("%08lx ", *stack++); } printk("\n%sCall Trace:\n", log_lvl); - show_trace_log_lvl(task, esp, log_lvl); + show_trace_log_lvl(task, regs, esp, log_lvl); } void show_stack(struct task_struct *task, unsigned long *esp) { printk(" "); - show_stack_log_lvl(task, esp, ""); + show_stack_log_lvl(task, NULL, esp, ""); } /* @@ -235,7 +279,7 @@ void dump_stack(void) { unsigned long stack; - show_trace(current, &stack); + show_trace(current, NULL, &stack); } EXPORT_SYMBOL(dump_stack); @@ -268,8 +312,9 @@ void show_registers(struct pt_regs *regs regs->esi, regs->edi, regs->ebp, esp); printk(KERN_EMERG "ds: %04x es: %04x ss: %04x\n", regs->xds & 0xffff, regs->xes & 0xffff, ss); - printk(KERN_EMERG "Process %s (pid: %d, threadinfo=%p task=%p)", - current->comm, current->pid, current_thread_info(), current); + printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)", + TASK_COMM_LEN, current->comm, current->pid, + current_thread_info(), current, current->thread_info); /* * When in-kernel, we also print out the stack and code at the * time of the fault.. @@ -278,7 +323,7 @@ void show_registers(struct pt_regs *regs u8 __user *eip; printk("\n" KERN_EMERG "Stack: "); - show_stack_log_lvl(NULL, (unsigned long *)esp, KERN_EMERG); + show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG); printk(KERN_EMERG "Code: "); @@ -1208,3 +1253,15 @@ static int __init kstack_setup(char *s) return 1; } __setup("kstack=", kstack_setup); + +static int __init call_trace_setup(char *s) +{ + if (strcmp(s, "old") == 0) + call_trace = -1; + else if (strcmp(s, "both") == 0) + call_trace = 0; + else if (strcmp(s, "new") == 0) + call_trace = 1; + return 1; +} +__setup("call_trace=", call_trace_setup); diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c new file mode 100644 index 0000000..7e0d8da --- /dev/null +++ b/arch/i386/kernel/tsc.c @@ -0,0 +1,478 @@ +/* + * This code largely moved from arch/i386/kernel/timer/timer_tsc.c + * which was originally moved from arch/i386/kernel/time.c. + * See comments there for proper credits. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mach_timer.h" + +/* + * On some systems the TSC frequency does not + * change with the cpu frequency. So we need + * an extra value to store the TSC freq + */ +unsigned int tsc_khz; + +int tsc_disable __cpuinitdata = 0; + +#ifdef CONFIG_X86_TSC +static int __init tsc_setup(char *str) +{ + printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, " + "cannot disable TSC.\n"); + return 1; +} +#else +/* + * disable flag for tsc. Takes effect by clearing the TSC cpu flag + * in cpu/common.c + */ +static int __init tsc_setup(char *str) +{ + tsc_disable = 1; + + return 1; +} +#endif + +__setup("notsc", tsc_setup); + +/* + * code to mark and check if the TSC is unstable + * due to cpufreq or due to unsynced TSCs + */ +static int tsc_unstable; + +static inline int check_tsc_unstable(void) +{ + return tsc_unstable; +} + +void mark_tsc_unstable(void) +{ + tsc_unstable = 1; +} +EXPORT_SYMBOL_GPL(mark_tsc_unstable); + +/* Accellerators for sched_clock() + * convert from cycles(64bits) => nanoseconds (64bits) + * basic equation: + * ns = cycles / (freq / ns_per_sec) + * ns = cycles * (ns_per_sec / freq) + * ns = cycles * (10^9 / (cpu_khz * 10^3)) + * ns = cycles * (10^6 / cpu_khz) + * + * Then we use scaling math (suggested by george@mvista.com) to get: + * ns = cycles * (10^6 * SC / cpu_khz) / SC + * ns = cycles * cyc2ns_scale / SC + * + * And since SC is a constant power of two, we can convert the div + * into a shift. + * + * We can use khz divisor instead of mhz to keep a better percision, since + * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits. + * (mathieu.desnoyers@polymtl.ca) + * + * -johnstul@us.ibm.com "math is hard, lets go shopping!" + */ +static unsigned long cyc2ns_scale __read_mostly; + +#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ + +static inline void set_cyc2ns_scale(unsigned long cpu_khz) +{ + cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; +} + +static inline unsigned long long cycles_2_ns(unsigned long long cyc) +{ + return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; +} + +/* + * Scheduler clock - returns current time in nanosec units. + */ +unsigned long long sched_clock(void) +{ + unsigned long long this_offset; + + /* + * in the NUMA case we dont use the TSC as they are not + * synchronized across all CPUs. + */ +#ifndef CONFIG_NUMA + if (!cpu_khz || check_tsc_unstable()) +#endif + /* no locking but a rare wrong value is not a big deal */ + return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ); + + /* read the Time Stamp Counter: */ + rdtscll(this_offset); + + /* return the value in ns */ + return cycles_2_ns(this_offset); +} + +static unsigned long calculate_cpu_khz(void) +{ + unsigned long long start, end; + unsigned long count; + u64 delta64; + int i; + unsigned long flags; + + local_irq_save(flags); + + /* run 3 times to ensure the cache is warm */ + for (i = 0; i < 3; i++) { + mach_prepare_counter(); + rdtscll(start); + mach_countup(&count); + rdtscll(end); + } + /* + * Error: ECTCNEVERSET + * The CTC wasn't reliable: we got a hit on the very first read, + * or the CPU was so fast/slow that the quotient wouldn't fit in + * 32 bits.. + */ + if (count <= 1) + goto err; + + delta64 = end - start; + + /* cpu freq too fast: */ + if (delta64 > (1ULL<<32)) + goto err; + + /* cpu freq too slow: */ + if (delta64 <= CALIBRATE_TIME_MSEC) + goto err; + + delta64 += CALIBRATE_TIME_MSEC/2; /* round for do_div */ + do_div(delta64,CALIBRATE_TIME_MSEC); + + local_irq_restore(flags); + return (unsigned long)delta64; +err: + local_irq_restore(flags); + return 0; +} + +int recalibrate_cpu_khz(void) +{ +#ifndef CONFIG_SMP + unsigned long cpu_khz_old = cpu_khz; + + if (cpu_has_tsc) { + cpu_khz = calculate_cpu_khz(); + tsc_khz = cpu_khz; + cpu_data[0].loops_per_jiffy = + cpufreq_scale(cpu_data[0].loops_per_jiffy, + cpu_khz_old, cpu_khz); + return 0; + } else + return -ENODEV; +#else + return -ENODEV; +#endif +} + +EXPORT_SYMBOL(recalibrate_cpu_khz); + +void tsc_init(void) +{ + if (!cpu_has_tsc || tsc_disable) + return; + + cpu_khz = calculate_cpu_khz(); + tsc_khz = cpu_khz; + + if (!cpu_khz) + return; + + printk("Detected %lu.%03lu MHz processor.\n", + (unsigned long)cpu_khz / 1000, + (unsigned long)cpu_khz % 1000); + + set_cyc2ns_scale(cpu_khz); + use_tsc_delay(); +} + +#ifdef CONFIG_CPU_FREQ + +static unsigned int cpufreq_delayed_issched = 0; +static unsigned int cpufreq_init = 0; +static struct work_struct cpufreq_delayed_get_work; + +static void handle_cpufreq_delayed_get(void *v) +{ + unsigned int cpu; + + for_each_online_cpu(cpu) + cpufreq_get(cpu); + + cpufreq_delayed_issched = 0; +} + +/* + * if we notice cpufreq oddness, schedule a call to cpufreq_get() as it tries + * to verify the CPU frequency the timing core thinks the CPU is running + * at is still correct. + */ +static inline void cpufreq_delayed_get(void) +{ + if (cpufreq_init && !cpufreq_delayed_issched) { + cpufreq_delayed_issched = 1; + printk(KERN_DEBUG "Checking if CPU frequency changed.\n"); + schedule_work(&cpufreq_delayed_get_work); + } +} + +/* + * if the CPU frequency is scaled, TSC-based delays will need a different + * loops_per_jiffy value to function properly. + */ +static unsigned int ref_freq = 0; +static unsigned long loops_per_jiffy_ref = 0; +static unsigned long cpu_khz_ref = 0; + +static int +time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = data; + + if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE) + write_seqlock_irq(&xtime_lock); + + if (!ref_freq) { + if (!freq->old){ + ref_freq = freq->new; + goto end; + } + ref_freq = freq->old; + loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; + cpu_khz_ref = cpu_khz; + } + + if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || + (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || + (val == CPUFREQ_RESUMECHANGE)) { + if (!(freq->flags & CPUFREQ_CONST_LOOPS)) + cpu_data[freq->cpu].loops_per_jiffy = + cpufreq_scale(loops_per_jiffy_ref, + ref_freq, freq->new); + + if (cpu_khz) { + + if (num_online_cpus() == 1) + cpu_khz = cpufreq_scale(cpu_khz_ref, + ref_freq, freq->new); + if (!(freq->flags & CPUFREQ_CONST_LOOPS)) { + tsc_khz = cpu_khz; + set_cyc2ns_scale(cpu_khz); + /* + * TSC based sched_clock turns + * to junk w/ cpufreq + */ + mark_tsc_unstable(); + } + } + } +end: + if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE) + write_sequnlock_irq(&xtime_lock); + + return 0; +} + +static struct notifier_block time_cpufreq_notifier_block = { + .notifier_call = time_cpufreq_notifier +}; + +static int __init cpufreq_tsc(void) +{ + int ret; + + INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); + ret = cpufreq_register_notifier(&time_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + if (!ret) + cpufreq_init = 1; + + return ret; +} + +core_initcall(cpufreq_tsc); + +#endif + +/* clock source code */ + +static unsigned long current_tsc_khz = 0; +static int tsc_update_callback(void); + +static cycle_t read_tsc(void) +{ + cycle_t ret; + + rdtscll(ret); + + return ret; +} + +static struct clocksource clocksource_tsc = { + .name = "tsc", + .rating = 300, + .read = read_tsc, + .mask = CLOCKSOURCE_MASK(64), + .mult = 0, /* to be set */ + .shift = 22, + .update_callback = tsc_update_callback, + .is_continuous = 1, +}; + +static int tsc_update_callback(void) +{ + int change = 0; + + /* check to see if we should switch to the safe clocksource: */ + if (clocksource_tsc.rating != 50 && check_tsc_unstable()) { + clocksource_tsc.rating = 50; + clocksource_reselect(); + change = 1; + } + + /* only update if tsc_khz has changed: */ + if (current_tsc_khz != tsc_khz) { + current_tsc_khz = tsc_khz; + clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz, + clocksource_tsc.shift); + change = 1; + } + + return change; +} + +static int __init dmi_mark_tsc_unstable(struct dmi_system_id *d) +{ + printk(KERN_NOTICE "%s detected: marking TSC unstable.\n", + d->ident); + mark_tsc_unstable(); + return 0; +} + +/* List of systems that have known TSC problems */ +static struct dmi_system_id __initdata bad_tsc_dmi_table[] = { + { + .callback = dmi_mark_tsc_unstable, + .ident = "IBM Thinkpad 380XD", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), + DMI_MATCH(DMI_BOARD_NAME, "2635FA0"), + }, + }, + {} +}; + +#define TSC_FREQ_CHECK_INTERVAL (10*MSEC_PER_SEC) /* 10sec in MS */ +static struct timer_list verify_tsc_freq_timer; + +/* XXX - Probably should add locking */ +static void verify_tsc_freq(unsigned long unused) +{ + static u64 last_tsc; + static unsigned long last_jiffies; + + u64 now_tsc, interval_tsc; + unsigned long now_jiffies, interval_jiffies; + + + if (check_tsc_unstable()) + return; + + rdtscll(now_tsc); + now_jiffies = jiffies; + + if (!last_jiffies) { + goto out; + } + + interval_jiffies = now_jiffies - last_jiffies; + interval_tsc = now_tsc - last_tsc; + interval_tsc *= HZ; + do_div(interval_tsc, cpu_khz*1000); + + if (interval_tsc < (interval_jiffies * 3 / 4)) { + printk("TSC appears to be running slowly. " + "Marking it as unstable\n"); + mark_tsc_unstable(); + return; + } + +out: + last_tsc = now_tsc; + last_jiffies = now_jiffies; + /* set us up to go off on the next interval: */ + mod_timer(&verify_tsc_freq_timer, + jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL)); +} + +/* + * Make an educated guess if the TSC is trustworthy and synchronized + * over all CPUs. + */ +static __init int unsynchronized_tsc(void) +{ + /* + * Intel systems are normally all synchronized. + * Exceptions must mark TSC as unstable: + */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) + return 0; + + /* assume multi socket systems are not synchronized: */ + return num_possible_cpus() > 1; +} + +static int __init init_tsc_clocksource(void) +{ + + if (cpu_has_tsc && tsc_khz && !tsc_disable) { + /* check blacklist */ + dmi_check_system(bad_tsc_dmi_table); + + if (unsynchronized_tsc()) /* mark unstable if unsynced */ + mark_tsc_unstable(); + current_tsc_khz = tsc_khz; + clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz, + clocksource_tsc.shift); + /* lower the rating if we already know its unstable: */ + if (check_tsc_unstable()) + clocksource_tsc.rating = 50; + + init_timer(&verify_tsc_freq_timer); + verify_tsc_freq_timer.function = verify_tsc_freq; + verify_tsc_freq_timer.expires = + jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL); + add_timer(&verify_tsc_freq_timer); + + return clocksource_register(&clocksource_tsc); + } + + return 0; +} + +module_init(init_tsc_clocksource); diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index 8831303..2d4f138 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S @@ -37,6 +37,13 @@ SECTIONS RODATA + . = ALIGN(4); + __tracedata_start = .; + .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { + *(.tracedata) + } + __tracedata_end = .; + /* writeable */ .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ *(.data) @@ -64,6 +71,15 @@ SECTIONS .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) } _edata = .; /* End of data section */ +#ifdef CONFIG_STACK_UNWIND + . = ALIGN(4); + .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) { + __start_unwind = .; + *(.eh_frame) + __end_unwind = .; + } +#endif + . = ALIGN(THREAD_SIZE); /* init_task */ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { *(.data.init_task) diff --git a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c index c49a6ac..3c0714c 100644 --- a/arch/i386/lib/delay.c +++ b/arch/i386/lib/delay.c @@ -10,43 +10,92 @@ * we have to worry about. */ +#include #include #include #include -#include + #include #include #include #ifdef CONFIG_SMP -#include +# include #endif -extern struct timer_opts* timer; +/* simple loop based delay: */ +static void delay_loop(unsigned long loops) +{ + int d0; + + __asm__ __volatile__( + "\tjmp 1f\n" + ".align 16\n" + "1:\tjmp 2f\n" + ".align 16\n" + "2:\tdecl %0\n\tjns 2b" + :"=&a" (d0) + :"0" (loops)); +} + +/* TSC based delay: */ +static void delay_tsc(unsigned long loops) +{ + unsigned long bclock, now; + + rdtscl(bclock); + do { + rep_nop(); + rdtscl(now); + } while ((now-bclock) < loops); +} + +/* + * Since we calibrate only once at boot, this + * function should be set once at boot and not changed + */ +static void (*delay_fn)(unsigned long) = delay_loop; + +void use_tsc_delay(void) +{ + delay_fn = delay_tsc; +} + +int read_current_timer(unsigned long *timer_val) +{ + if (delay_fn == delay_tsc) { + rdtscl(*timer_val); + return 0; + } + return -1; +} void __delay(unsigned long loops) { - cur_timer->delay(loops); + delay_fn(loops); } inline void __const_udelay(unsigned long xloops) { int d0; + xloops *= 4; __asm__("mull %0" :"=d" (xloops), "=&a" (d0) - :"1" (xloops),"0" (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4))); - __delay(++xloops); + :"1" (xloops), "0" + (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4))); + + __delay(++xloops); } void __udelay(unsigned long usecs) { - __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */ + __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */ } void __ndelay(unsigned long nsecs) { - __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */ + __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */ } EXPORT_SYMBOL(__delay); diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c index 4cf981d..c5aa65f 100644 --- a/arch/i386/lib/usercopy.c +++ b/arch/i386/lib/usercopy.c @@ -425,15 +425,212 @@ __copy_user_zeroing_intel(void *to, cons : "eax", "edx", "memory"); return size; } + +/* + * Non Temporal Hint version of __copy_user_zeroing_intel. It is cache aware. + * hyoshiok@miraclelinux.com + */ + +static unsigned long __copy_user_zeroing_intel_nocache(void *to, + const void __user *from, unsigned long size) +{ + int d0, d1; + + __asm__ __volatile__( + " .align 2,0x90\n" + "0: movl 32(%4), %%eax\n" + " cmpl $67, %0\n" + " jbe 2f\n" + "1: movl 64(%4), %%eax\n" + " .align 2,0x90\n" + "2: movl 0(%4), %%eax\n" + "21: movl 4(%4), %%edx\n" + " movnti %%eax, 0(%3)\n" + " movnti %%edx, 4(%3)\n" + "3: movl 8(%4), %%eax\n" + "31: movl 12(%4),%%edx\n" + " movnti %%eax, 8(%3)\n" + " movnti %%edx, 12(%3)\n" + "4: movl 16(%4), %%eax\n" + "41: movl 20(%4), %%edx\n" + " movnti %%eax, 16(%3)\n" + " movnti %%edx, 20(%3)\n" + "10: movl 24(%4), %%eax\n" + "51: movl 28(%4), %%edx\n" + " movnti %%eax, 24(%3)\n" + " movnti %%edx, 28(%3)\n" + "11: movl 32(%4), %%eax\n" + "61: movl 36(%4), %%edx\n" + " movnti %%eax, 32(%3)\n" + " movnti %%edx, 36(%3)\n" + "12: movl 40(%4), %%eax\n" + "71: movl 44(%4), %%edx\n" + " movnti %%eax, 40(%3)\n" + " movnti %%edx, 44(%3)\n" + "13: movl 48(%4), %%eax\n" + "81: movl 52(%4), %%edx\n" + " movnti %%eax, 48(%3)\n" + " movnti %%edx, 52(%3)\n" + "14: movl 56(%4), %%eax\n" + "91: movl 60(%4), %%edx\n" + " movnti %%eax, 56(%3)\n" + " movnti %%edx, 60(%3)\n" + " addl $-64, %0\n" + " addl $64, %4\n" + " addl $64, %3\n" + " cmpl $63, %0\n" + " ja 0b\n" + " sfence \n" + "5: movl %0, %%eax\n" + " shrl $2, %0\n" + " andl $3, %%eax\n" + " cld\n" + "6: rep; movsl\n" + " movl %%eax,%0\n" + "7: rep; movsb\n" + "8:\n" + ".section .fixup,\"ax\"\n" + "9: lea 0(%%eax,%0,4),%0\n" + "16: pushl %0\n" + " pushl %%eax\n" + " xorl %%eax,%%eax\n" + " rep; stosb\n" + " popl %%eax\n" + " popl %0\n" + " jmp 8b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 0b,16b\n" + " .long 1b,16b\n" + " .long 2b,16b\n" + " .long 21b,16b\n" + " .long 3b,16b\n" + " .long 31b,16b\n" + " .long 4b,16b\n" + " .long 41b,16b\n" + " .long 10b,16b\n" + " .long 51b,16b\n" + " .long 11b,16b\n" + " .long 61b,16b\n" + " .long 12b,16b\n" + " .long 71b,16b\n" + " .long 13b,16b\n" + " .long 81b,16b\n" + " .long 14b,16b\n" + " .long 91b,16b\n" + " .long 6b,9b\n" + " .long 7b,16b\n" + ".previous" + : "=&c"(size), "=&D" (d0), "=&S" (d1) + : "1"(to), "2"(from), "0"(size) + : "eax", "edx", "memory"); + return size; +} + +static unsigned long __copy_user_intel_nocache(void *to, + const void __user *from, unsigned long size) +{ + int d0, d1; + + __asm__ __volatile__( + " .align 2,0x90\n" + "0: movl 32(%4), %%eax\n" + " cmpl $67, %0\n" + " jbe 2f\n" + "1: movl 64(%4), %%eax\n" + " .align 2,0x90\n" + "2: movl 0(%4), %%eax\n" + "21: movl 4(%4), %%edx\n" + " movnti %%eax, 0(%3)\n" + " movnti %%edx, 4(%3)\n" + "3: movl 8(%4), %%eax\n" + "31: movl 12(%4),%%edx\n" + " movnti %%eax, 8(%3)\n" + " movnti %%edx, 12(%3)\n" + "4: movl 16(%4), %%eax\n" + "41: movl 20(%4), %%edx\n" + " movnti %%eax, 16(%3)\n" + " movnti %%edx, 20(%3)\n" + "10: movl 24(%4), %%eax\n" + "51: movl 28(%4), %%edx\n" + " movnti %%eax, 24(%3)\n" + " movnti %%edx, 28(%3)\n" + "11: movl 32(%4), %%eax\n" + "61: movl 36(%4), %%edx\n" + " movnti %%eax, 32(%3)\n" + " movnti %%edx, 36(%3)\n" + "12: movl 40(%4), %%eax\n" + "71: movl 44(%4), %%edx\n" + " movnti %%eax, 40(%3)\n" + " movnti %%edx, 44(%3)\n" + "13: movl 48(%4), %%eax\n" + "81: movl 52(%4), %%edx\n" + " movnti %%eax, 48(%3)\n" + " movnti %%edx, 52(%3)\n" + "14: movl 56(%4), %%eax\n" + "91: movl 60(%4), %%edx\n" + " movnti %%eax, 56(%3)\n" + " movnti %%edx, 60(%3)\n" + " addl $-64, %0\n" + " addl $64, %4\n" + " addl $64, %3\n" + " cmpl $63, %0\n" + " ja 0b\n" + " sfence \n" + "5: movl %0, %%eax\n" + " shrl $2, %0\n" + " andl $3, %%eax\n" + " cld\n" + "6: rep; movsl\n" + " movl %%eax,%0\n" + "7: rep; movsb\n" + "8:\n" + ".section .fixup,\"ax\"\n" + "9: lea 0(%%eax,%0,4),%0\n" + "16: jmp 8b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 0b,16b\n" + " .long 1b,16b\n" + " .long 2b,16b\n" + " .long 21b,16b\n" + " .long 3b,16b\n" + " .long 31b,16b\n" + " .long 4b,16b\n" + " .long 41b,16b\n" + " .long 10b,16b\n" + " .long 51b,16b\n" + " .long 11b,16b\n" + " .long 61b,16b\n" + " .long 12b,16b\n" + " .long 71b,16b\n" + " .long 13b,16b\n" + " .long 81b,16b\n" + " .long 14b,16b\n" + " .long 91b,16b\n" + " .long 6b,9b\n" + " .long 7b,16b\n" + ".previous" + : "=&c"(size), "=&D" (d0), "=&S" (d1) + : "1"(to), "2"(from), "0"(size) + : "eax", "edx", "memory"); + return size; +} + #else + /* * Leave these declared but undefined. They should not be any references to * them */ -unsigned long -__copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size); -unsigned long -__copy_user_intel(void __user *to, const void *from, unsigned long size); +unsigned long __copy_user_zeroing_intel(void *to, const void __user *from, + unsigned long size); +unsigned long __copy_user_intel(void __user *to, const void *from, + unsigned long size); +unsigned long __copy_user_zeroing_intel_nocache(void *to, + const void __user *from, unsigned long size); #endif /* CONFIG_X86_INTEL_USERCOPY */ /* Generic arbitrary sized copy. */ @@ -515,8 +712,8 @@ do { \ : "memory"); \ } while (0) - -unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n) +unsigned long __copy_to_user_ll(void __user *to, const void *from, + unsigned long n) { BUG_ON((long) n < 0); #ifndef CONFIG_X86_WP_WORKS_OK @@ -576,8 +773,8 @@ #endif } EXPORT_SYMBOL(__copy_to_user_ll); -unsigned long -__copy_from_user_ll(void *to, const void __user *from, unsigned long n) +unsigned long __copy_from_user_ll(void *to, const void __user *from, + unsigned long n) { BUG_ON((long)n < 0); if (movsl_is_ok(to, from, n)) @@ -588,6 +785,49 @@ __copy_from_user_ll(void *to, const void } EXPORT_SYMBOL(__copy_from_user_ll); +unsigned long __copy_from_user_ll_nozero(void *to, const void __user *from, + unsigned long n) +{ + BUG_ON((long)n < 0); + if (movsl_is_ok(to, from, n)) + __copy_user(to, from, n); + else + n = __copy_user_intel((void __user *)to, + (const void *)from, n); + return n; +} +EXPORT_SYMBOL(__copy_from_user_ll_nozero); + +unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from, + unsigned long n) +{ + BUG_ON((long)n < 0); +#ifdef CONFIG_X86_INTEL_USERCOPY + if ( n > 64 && cpu_has_xmm2) + n = __copy_user_zeroing_intel_nocache(to, from, n); + else + __copy_user_zeroing(to, from, n); +#else + __copy_user_zeroing(to, from, n); +#endif + return n; +} + +unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from, + unsigned long n) +{ + BUG_ON((long)n < 0); +#ifdef CONFIG_X86_INTEL_USERCOPY + if ( n > 64 && cpu_has_xmm2) + n = __copy_user_intel_nocache(to, from, n); + else + __copy_user(to, from, n); +#else + __copy_user(to, from, n); +#endif + return n; +} + /** * copy_to_user: - Copy a block of data into user space. * @to: Destination address, in user space. diff --git a/arch/i386/mach-default/setup.c b/arch/i386/mach-default/setup.c index b4a7455..004837c 100644 --- a/arch/i386/mach-default/setup.c +++ b/arch/i386/mach-default/setup.c @@ -8,6 +8,8 @@ #include #include #include #include +#include +#include #ifdef CONFIG_HOTPLUG_CPU #define DEFAULT_SEND_IPI (1) @@ -130,3 +132,44 @@ static int __init print_ipi_mode(void) } late_initcall(print_ipi_mode); + +/** + * machine_specific_memory_setup - Hook for machine specific memory setup. + * + * Description: + * This is included late in kernel/setup.c so that it can make + * use of all of the static functions. + **/ + +char * __init machine_specific_memory_setup(void) +{ + char *who; + + + who = "BIOS-e820"; + + /* + * Try to copy the BIOS-supplied E820-map. + * + * Otherwise fake a memory map; one section from 0k->640k, + * the next section from 1mb->appropriate_mem_k + */ + sanitize_e820_map(E820_MAP, &E820_MAP_NR); + if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) { + unsigned long mem_size; + + /* compare results from other methods and take the greater */ + if (ALT_MEM_K < EXT_MEM_K) { + mem_size = EXT_MEM_K; + who = "BIOS-88"; + } else { + mem_size = ALT_MEM_K; + who = "BIOS-e801"; + } + + e820.nr_map = 0; + add_memory_region(0, LOWMEMSIZE(), E820_RAM); + add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM); + } + return who; +} diff --git a/arch/i386/mach-visws/setup.c b/arch/i386/mach-visws/setup.c index 07fac7e..8a9e1a6 100644 --- a/arch/i386/mach-visws/setup.c +++ b/arch/i386/mach-visws/setup.c @@ -10,6 +10,8 @@ #include #include #include #include +#include +#include #include "cobalt.h" #include "piix4.h" @@ -133,3 +135,50 @@ void __init time_init_hook(void) /* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */ setup_irq(0, &irq0); } + +/* Hook for machine specific memory setup. */ + +#define MB (1024 * 1024) + +static unsigned long sgivwfb_mem_phys; +static unsigned long sgivwfb_mem_size; + +long long mem_size __initdata = 0; + +char * __init machine_specific_memory_setup(void) +{ + long long gfx_mem_size = 8 * MB; + + mem_size = ALT_MEM_K; + + if (!mem_size) { + printk(KERN_WARNING "Bootloader didn't set memory size, upgrade it !\n"); + mem_size = 128 * MB; + } + + /* + * this hardcodes the graphics memory to 8 MB + * it really should be sized dynamically (or at least + * set as a boot param) + */ + if (!sgivwfb_mem_size) { + printk(KERN_WARNING "Defaulting to 8 MB framebuffer size\n"); + sgivwfb_mem_size = 8 * MB; + } + + /* + * Trim to nearest MB + */ + sgivwfb_mem_size &= ~((1 << 20) - 1); + sgivwfb_mem_phys = mem_size - gfx_mem_size; + + add_memory_region(0, LOWMEMSIZE(), E820_RAM); + add_memory_region(HIGH_MEMORY, mem_size - sgivwfb_mem_size - HIGH_MEMORY, E820_RAM); + add_memory_region(sgivwfb_mem_phys, sgivwfb_mem_size, E820_RESERVED); + + return "PROM"; + + /* Remove gcc warnings */ + (void) sanitize_e820_map(NULL, NULL); + (void) copy_e820_map(NULL, 0); +} diff --git a/arch/i386/mach-voyager/setup.c b/arch/i386/mach-voyager/setup.c index 7d8a3ac..0e22505 100644 --- a/arch/i386/mach-voyager/setup.c +++ b/arch/i386/mach-voyager/setup.c @@ -7,6 +7,9 @@ #include #include #include #include +#include +#include +#include void __init pre_intr_init_hook(void) { @@ -45,3 +48,74 @@ void __init time_init_hook(void) { setup_irq(0, &irq0); } + +/* Hook for machine specific memory setup. */ + +char * __init machine_specific_memory_setup(void) +{ + char *who; + + who = "NOT VOYAGER"; + + if(voyager_level == 5) { + __u32 addr, length; + int i; + + who = "Voyager-SUS"; + + e820.nr_map = 0; + for(i=0; voyager_memory_detect(i, &addr, &length); i++) { + add_memory_region(addr, length, E820_RAM); + } + return who; + } else if(voyager_level == 4) { + __u32 tom; + __u16 catbase = inb(VOYAGER_SSPB_RELOCATION_PORT)<<8; + /* select the DINO config space */ + outb(VOYAGER_DINO, VOYAGER_CAT_CONFIG_PORT); + /* Read DINO top of memory register */ + tom = ((inb(catbase + 0x4) & 0xf0) << 16) + + ((inb(catbase + 0x5) & 0x7f) << 24); + + if(inb(catbase) != VOYAGER_DINO) { + printk(KERN_ERR "Voyager: Failed to get DINO for L4, setting tom to EXT_MEM_K\n"); + tom = (EXT_MEM_K)<<10; + } + who = "Voyager-TOM"; + add_memory_region(0, 0x9f000, E820_RAM); + /* map from 1M to top of memory */ + add_memory_region(1*1024*1024, tom - 1*1024*1024, E820_RAM); + /* FIXME: Should check the ASICs to see if I need to + * take out the 8M window. Just do it at the moment + * */ + add_memory_region(8*1024*1024, 8*1024*1024, E820_RESERVED); + return who; + } + + who = "BIOS-e820"; + + /* + * Try to copy the BIOS-supplied E820-map. + * + * Otherwise fake a memory map; one section from 0k->640k, + * the next section from 1mb->appropriate_mem_k + */ + sanitize_e820_map(E820_MAP, &E820_MAP_NR); + if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) { + unsigned long mem_size; + + /* compare results from other methods and take the greater */ + if (ALT_MEM_K < EXT_MEM_K) { + mem_size = EXT_MEM_K; + who = "BIOS-88"; + } else { + mem_size = ALT_MEM_K; + who = "BIOS-e801"; + } + + e820.nr_map = 0; + add_memory_region(0, LOWMEMSIZE(), E820_RAM); + add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM); + } + return who; +} diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 7f0fcf2..6ee7faa 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -30,6 +30,40 @@ #include extern void die(const char *,struct pt_regs *,long); +#ifdef CONFIG_KPROBES +ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); +int register_page_fault_notifier(struct notifier_block *nb) +{ + vmalloc_sync_all(); + return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); +} + +int unregister_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); +} + +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + struct die_args args = { + .regs = regs, + .str = str, + .err = err, + .trapnr = trap, + .signr = sig + }; + return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); +} +#else +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + return NOTIFY_DONE; +} +#endif + + /* * Unlock any spinlocks which will prevent us from getting the * message out @@ -77,12 +111,15 @@ static inline unsigned long get_segment_ unsigned seg = regs->xcs & 0xffff; u32 seg_ar, seg_limit, base, *desc; + /* Unlikely, but must come before segment checks. */ + if (unlikely(regs->eflags & VM_MASK)) { + base = seg << 4; + *eip_limit = base + 0xffff; + return base + (eip & 0xffff); + } + /* The standard kernel/user address space limit. */ *eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg; - - /* Unlikely, but must come before segment checks. */ - if (unlikely((regs->eflags & VM_MASK) != 0)) - return eip + (seg << 4); /* By far the most common cases. */ if (likely(seg == __USER_CS || seg == __KERNEL_CS)) @@ -321,7 +358,7 @@ fastcall void __kprobes do_page_fault(st if (unlikely(address >= TASK_SIZE)) { if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) return; - if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, + if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, SIGSEGV) == NOTIFY_STOP) return; /* @@ -331,7 +368,7 @@ fastcall void __kprobes do_page_fault(st goto bad_area_nosemaphore; } - if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, + if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, SIGSEGV) == NOTIFY_STOP) return; @@ -380,12 +417,12 @@ fastcall void __kprobes do_page_fault(st goto bad_area; if (error_code & 4) { /* - * accessing the stack below %esp is always a bug. - * The "+ 32" is there due to some instructions (like - * pusha) doing post-decrement on the stack and that - * doesn't show up until later.. + * Accessing the stack below %esp is always a bug. + * The large cushion allows instructions like enter + * and pusha to work. ("enter $65535,$31" pushes + * 32 pointers and then decrements %esp by 65535.) */ - if (address + 32 < regs->esp) + if (address + 65536 + 32 * sizeof(unsigned long) < regs->esp) goto bad_area; } if (expand_stack(vma, address)) diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 3df1371..bf19513 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -29,6 +29,7 @@ #include #include #include #include +#include #include #include @@ -384,7 +385,7 @@ #ifdef CONFIG_X86_PAE #endif } -#ifdef CONFIG_SOFTWARE_SUSPEND +#if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_ACPI_SLEEP) /* * Swap suspend & friends need this for resume because things like the intel-agp * driver might have split up a kernel 4MB mapping. diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index 92c3d9f..0887b34 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c @@ -209,19 +209,19 @@ int change_page_attr(struct page *page, } void global_flush_tlb(void) -{ - LIST_HEAD(l); +{ + struct list_head l; struct page *pg, *next; BUG_ON(irqs_disabled()); spin_lock_irq(&cpa_lock); - list_splice_init(&df_list, &l); + list_replace_init(&df_list, &l); spin_unlock_irq(&cpa_lock); flush_map(); list_for_each_entry_safe(pg, next, &l, lru) __free_page(pg); -} +} #ifdef CONFIG_DEBUG_PAGEALLOC void kernel_map_pages(struct page *page, int numpages, int enable) diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c index ec0fd3c..fa8a37b 100644 --- a/arch/i386/oprofile/nmi_int.c +++ b/arch/i386/oprofile/nmi_int.c @@ -281,9 +281,9 @@ static int nmi_create_files(struct super for (i = 0; i < model->num_counters; ++i) { struct dentry * dir; - char buf[2]; + char buf[4]; - snprintf(buf, 2, "%d", i); + snprintf(buf, sizeof(buf), "%d", i); dir = oprofilefs_mkdir(sb, root, buf); oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled); oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event); diff --git a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c index 3ad9a72..693bdea 100644 --- a/arch/i386/oprofile/op_model_athlon.c +++ b/arch/i386/oprofile/op_model_athlon.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "op_x86_model.h" #include "op_counter.h" diff --git a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c index ac8a066..7c61d35 100644 --- a/arch/i386/oprofile/op_model_p4.c +++ b/arch/i386/oprofile/op_model_p4.c @@ -14,6 +14,7 @@ #include #include #include #include +#include #include "op_x86_model.h" #include "op_counter.h" diff --git a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c index d719015..5c3ab4b 100644 --- a/arch/i386/oprofile/op_model_ppro.c +++ b/arch/i386/oprofile/op_model_ppro.c @@ -14,6 +14,7 @@ #include #include #include #include +#include #include "op_x86_model.h" #include "op_counter.h" diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index dbece77..c624b61 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -288,6 +288,7 @@ int pcibios_enable_device(struct pci_dev void pcibios_disable_device (struct pci_dev *dev) { + pcibios_disable_resources(dev); if (pcibios_disable_irq) pcibios_disable_irq(dev); } diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c index ed2c8c8..a151f7a 100644 --- a/arch/i386/pci/i386.c +++ b/arch/i386/pci/i386.c @@ -242,6 +242,15 @@ int pcibios_enable_resources(struct pci_ return 0; } +void pcibios_disable_resources(struct pci_dev *dev) +{ + u16 cmd; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, cmd); +} + /* * If we set up a device for bus mastering, we need to check the latency * timer as certain crappy BIOSes forget to set it properly. @@ -276,8 +285,6 @@ int pci_mmap_page_range(struct pci_dev * /* Leave vm_pgoff as-is, the PCI space address is the physical * address on this platform. */ - vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO); - prot = pgprot_val(vma->vm_page_prot); if (boot_cpu_data.x86 > 3) prot |= _PAGE_PCD | _PAGE_PWT; diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 06dab00..8ce6950 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -198,14 +198,14 @@ static void write_config_nybble(struct p */ static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { - static unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; + static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; return irqmap[read_config_nybble(router, 0x48, pirq-1)]; } static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - static unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 }; + static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 }; unsigned int val = irqmap[irq]; if (val) { @@ -256,13 +256,13 @@ static int pirq_via_set(struct pci_dev * */ static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { - static unsigned int pirqmap[4] = { 3, 2, 5, 1 }; + static const unsigned int pirqmap[4] = { 3, 2, 5, 1 }; return read_config_nybble(router, 0x55, pirqmap[pirq-1]); } static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - static unsigned int pirqmap[4] = { 3, 2, 5, 1 }; + static const unsigned int pirqmap[4] = { 3, 2, 5, 1 }; write_config_nybble(router, 0x55, pirqmap[pirq-1], irq); return 1; } @@ -274,13 +274,13 @@ static int pirq_via586_set(struct pci_de */ static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq) { - static unsigned char pirqmap[4] = { 1, 0, 2, 3 }; + static const unsigned char pirqmap[4] = { 1, 0, 2, 3 }; return read_config_nybble(router,0x43, pirqmap[pirq-1]); } static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - static unsigned char pirqmap[4] = { 1, 0, 2, 3 }; + static const unsigned char pirqmap[4] = { 1, 0, 2, 3 }; write_config_nybble(router, 0x43, pirqmap[pirq-1], irq); return 1; } @@ -505,7 +505,7 @@ #endif static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) { - static struct pci_device_id pirq_440gx[] = { + static struct pci_device_id __initdata pirq_440gx[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) }, { }, @@ -880,6 +880,7 @@ static int pcibios_lookup_irq(struct pci ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) { DBG(" -> got IRQ %d\n", irq); msg = "Found"; + eisa_set_level_irq(irq); } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { DBG(" -> assigning IRQ %d", newirq); if (r->set(pirq_router_dev, dev, pirq, newirq)) { diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 6b1ea0c..e545b09 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c @@ -15,7 +15,9 @@ #include #include #include "pci.h" -#define MMCONFIG_APER_SIZE (256*1024*1024) +/* aperture is up to 256MB but BIOS may reserve less */ +#define MMCONFIG_APER_MIN (2 * 1024*1024) +#define MMCONFIG_APER_MAX (256 * 1024*1024) /* Assume systems with more busses have correct MCFG */ #define MAX_CHECK_BUS 16 @@ -197,9 +199,10 @@ void __init pci_mmcfg_init(void) return; if (!e820_all_mapped(pci_mmcfg_config[0].base_address, - pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, E820_RESERVED)) { - printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", + pci_mmcfg_config[0].base_address); printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); return; } diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c index 1eec086..ed1512a 100644 --- a/arch/i386/pci/pcbios.c +++ b/arch/i386/pci/pcbios.c @@ -371,8 +371,7 @@ void __devinit pcibios_sort(void) list_for_each(ln, &pci_devices) { d = pci_dev_g(ln); if (d->bus->number == bus && d->devfn == devfn) { - list_del(&d->global_list); - list_add_tail(&d->global_list, &sorted_devices); + list_move_tail(&d->global_list, &sorted_devices); if (d == dev) found = 1; break; @@ -390,8 +389,7 @@ void __devinit pcibios_sort(void) if (!found) { printk(KERN_WARNING "PCI: Device %s not found by BIOS\n", pci_name(dev)); - list_del(&dev->global_list); - list_add_tail(&dev->global_list, &sorted_devices); + list_move_tail(&dev->global_list, &sorted_devices); } } list_splice(&sorted_devices, &pci_devices); diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index 12035e2..12bf3d8 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h @@ -35,6 +35,7 @@ extern unsigned int pcibios_max_latency; void pcibios_resource_survey(void); int pcibios_enable_resources(struct pci_dev *, int); +void pcibios_disable_resources(struct pci_dev *); /* pci-pc.c */ diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index 79b2370..e651791 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include static struct saved_context saved_context; diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 0f3076a..1831874 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -77,6 +77,7 @@ choice config IA64_GENERIC bool "generic" select ACPI + select PCI select NUMA select ACPI_NUMA help @@ -273,7 +274,6 @@ config HOTPLUG_CPU config SCHED_SMT bool "SMT scheduler support" depends on SMP - default off help Improves the CPU scheduler's decision making when dealing with Intel IA64 chips with MultiThreading at a cost of slightly increased @@ -449,6 +449,8 @@ config PCI_DOMAINS bool default PCI +source "drivers/pci/pcie/Kconfig" + source "drivers/pci/Kconfig" source "drivers/pci/hotplug/Kconfig" diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 80ea750..21033ed 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -71,6 +71,8 @@ all: compressed unwcheck compressed: vmlinux.gz +vmlinuz: vmlinux.gz + vmlinux.gz: vmlinux $(Q)$(MAKE) $(build)=$(boot) $@ diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index bdccd0b..5825dde 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -1958,7 +1958,7 @@ sba_map_ioc_to_node(struct ioc *ioc, acp if (pxm < 0) return; - node = pxm_to_nid_map[pxm]; + node = pxm_to_node(pxm); if (node >= MAX_NUMNODES || !node_online(node)) return; @@ -1999,7 +1999,7 @@ acpi_sba_ioc_add(struct acpi_device *dev if (!iovp_shift) iovp_shift = min(PAGE_SHIFT, 16); } - ACPI_MEM_FREE(dev_info); + kfree(dev_info); /* * default anything not caught above or specified on cmdline to 4k diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 58c93a3..ca16d95 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -68,8 +68,6 @@ EXPORT_SYMBOL(pm_power_off); unsigned char acpi_kbd_controller_present = 1; unsigned char acpi_legacy_devices; -static unsigned int __initdata acpi_madt_rev; - unsigned int acpi_cpei_override; unsigned int acpi_cpei_phys_cpuid; @@ -243,6 +241,8 @@ acpi_parse_iosapic(acpi_table_entry_head return iosapic_init(iosapic->address, iosapic->global_irq_base); } +static unsigned int __initdata acpi_madt_rev; + static int __init acpi_parse_plat_int_src(acpi_table_entry_header * header, const unsigned long end) @@ -415,9 +415,6 @@ static int __initdata srat_num_cpus; /* static u32 __devinitdata pxm_flag[PXM_FLAG_LEN]; #define pxm_bit_set(bit) (set_bit(bit,(void *)pxm_flag)) #define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag)) -/* maps to convert between proximity domain and logical node ID */ -int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS]; -int __initdata nid_to_pxm_map[MAX_NUMNODES]; static struct acpi_table_slit __initdata *slit_table; static int get_processor_proximity_domain(struct acpi_table_processor_affinity *pa) @@ -533,22 +530,17 @@ void __init acpi_numa_arch_fixup(void) * MCD - This can probably be dropped now. No need for pxm ID to node ID * mapping with sparse node numbering iff MAX_PXM_DOMAINS <= MAX_NUMNODES. */ - /* calculate total number of nodes in system from PXM bitmap */ - memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map)); - memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map)); nodes_clear(node_online_map); for (i = 0; i < MAX_PXM_DOMAINS; i++) { if (pxm_bit_test(i)) { - int nid = num_online_nodes(); - pxm_to_nid_map[i] = nid; - nid_to_pxm_map[nid] = i; + int nid = acpi_map_pxm_to_node(i); node_set_online(nid); } } /* set logical node id in memory chunk structure */ for (i = 0; i < num_node_memblks; i++) - node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid]; + node_memblk[i].nid = pxm_to_node(node_memblk[i].nid); /* assign memory bank numbers for each chunk on each node */ for_each_online_node(i) { @@ -562,7 +554,7 @@ void __init acpi_numa_arch_fixup(void) /* set logical node id in cpu structure */ for (i = 0; i < srat_num_cpus; i++) - node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid]; + node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid); printk(KERN_INFO "Number of logical nodes in system = %d\n", num_online_nodes()); @@ -575,11 +567,11 @@ void __init acpi_numa_arch_fixup(void) for (i = 0; i < slit_table->localities; i++) { if (!pxm_bit_test(i)) continue; - node_from = pxm_to_nid_map[i]; + node_from = pxm_to_node(i); for (j = 0; j < slit_table->localities; j++) { if (!pxm_bit_test(j)) continue; - node_to = pxm_to_nid_map[j]; + node_to = pxm_to_node(j); node_distance(node_from, node_to) = slit_table->entry[i * slit_table->localities + j]; } @@ -626,7 +618,7 @@ EXPORT_SYMBOL(acpi_unregister_gsi); static int __init acpi_parse_fadt(unsigned long phys_addr, unsigned long size) { struct acpi_table_header *fadt_header; - struct fadt_descriptor_rev2 *fadt; + struct fadt_descriptor *fadt; if (!phys_addr || !size) return -EINVAL; @@ -635,7 +627,7 @@ static int __init acpi_parse_fadt(unsign if (fadt_header->revision != 3) return -ENODEV; /* Only deal with ACPI 2.0 FADT */ - fadt = (struct fadt_descriptor_rev2 *)fadt_header; + fadt = (struct fadt_descriptor *)fadt_header; if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER)) acpi_kbd_controller_present = 0; @@ -785,9 +777,9 @@ #ifdef CONFIG_ACPI_NUMA /* * Assuming that the container driver would have set the proximity - * domain and would have initialized pxm_to_nid_map[pxm_id] && pxm_flag + * domain and would have initialized pxm_to_node(pxm_id) && pxm_flag */ - node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_nid_map[pxm_id]; + node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_node(pxm_id); node_cpuid[cpu].phys_id = physid; #endif @@ -966,7 +958,7 @@ acpi_map_iosapic(acpi_handle handle, u32 if (pxm < 0) return AE_OK; - node = pxm_to_nid_map[pxm]; + node = pxm_to_node(pxm); if (node >= MAX_NUMNODES || !node_online(node) || cpus_empty(node_to_cpumask(node))) diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index 7722565..16e7b66 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c @@ -217,16 +217,24 @@ #endif DEFINE(IA64_MCA_CPU_INIT_STACK_OFFSET, offsetof (struct ia64_mca_cpu, init_stack)); BLANK(); - DEFINE(IA64_SAL_OS_STATE_COMMON_OFFSET, - offsetof (struct ia64_sal_os_state, sal_ra)); DEFINE(IA64_SAL_OS_STATE_OS_GP_OFFSET, offsetof (struct ia64_sal_os_state, os_gp)); - DEFINE(IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET, - offsetof (struct ia64_sal_os_state, pal_min_state)); DEFINE(IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET, offsetof (struct ia64_sal_os_state, proc_state_param)); + DEFINE(IA64_SAL_OS_STATE_SAL_RA_OFFSET, + offsetof (struct ia64_sal_os_state, sal_ra)); + DEFINE(IA64_SAL_OS_STATE_SAL_GP_OFFSET, + offsetof (struct ia64_sal_os_state, sal_gp)); + DEFINE(IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET, + offsetof (struct ia64_sal_os_state, pal_min_state)); + DEFINE(IA64_SAL_OS_STATE_OS_STATUS_OFFSET, + offsetof (struct ia64_sal_os_state, os_status)); + DEFINE(IA64_SAL_OS_STATE_CONTEXT_OFFSET, + offsetof (struct ia64_sal_os_state, context)); DEFINE(IA64_SAL_OS_STATE_SIZE, sizeof (struct ia64_sal_os_state)); + BLANK(); + DEFINE(IA64_PMSA_GR_OFFSET, offsetof (struct pal_min_state_area_s, pmsa_gr)); DEFINE(IA64_PMSA_BANK1_GR_OFFSET, diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 12cfedc..c33d0ba 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -8,6 +8,8 @@ * Copyright (C) 1999-2003 Hewlett-Packard Co. * David Mosberger-Tang * Stephane Eranian + * (c) Copyright 2006 Hewlett-Packard Development Company, L.P. + * Bjorn Helgaas * * All EFI Runtime Services are not implemented yet as EFI only * supports physical mode addressing on SoftSDV. This is to be fixed @@ -622,28 +624,20 @@ efi_get_iobase (void) return 0; } -static efi_memory_desc_t * -efi_memory_descriptor (unsigned long phys_addr) +static struct kern_memdesc * +kern_memory_descriptor (unsigned long phys_addr) { - void *efi_map_start, *efi_map_end, *p; - efi_memory_desc_t *md; - u64 efi_desc_size; - - efi_map_start = __va(ia64_boot_param->efi_memmap); - efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; - efi_desc_size = ia64_boot_param->efi_memdesc_size; + struct kern_memdesc *md; - for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { - md = p; - - if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) + for (md = kern_memmap; md->start != ~0UL; md++) { + if (phys_addr - md->start < (md->num_pages << EFI_PAGE_SHIFT)) return md; } return 0; } -static int -efi_memmap_has_mmio (void) +static efi_memory_desc_t * +efi_memory_descriptor (unsigned long phys_addr) { void *efi_map_start, *efi_map_end, *p; efi_memory_desc_t *md; @@ -656,8 +650,8 @@ efi_memmap_has_mmio (void) for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { md = p; - if (md->type == EFI_MEMORY_MAPPED_IO) - return 1; + if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) + return md; } return 0; } @@ -683,71 +677,125 @@ efi_mem_attributes (unsigned long phys_a } EXPORT_SYMBOL(efi_mem_attributes); -/* - * Determines whether the memory at phys_addr supports the desired - * attribute (WB, UC, etc). If this returns 1, the caller can safely - * access size bytes at phys_addr with the specified attribute. - */ -int -efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, u64 attr) +u64 +efi_mem_attribute (unsigned long phys_addr, unsigned long size) { unsigned long end = phys_addr + size; efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); + u64 attr; + + if (!md) + return 0; + + /* + * EFI_MEMORY_RUNTIME is not a memory attribute; it just tells + * the kernel that firmware needs this region mapped. + */ + attr = md->attribute & ~EFI_MEMORY_RUNTIME; + do { + unsigned long md_end = efi_md_end(md); + + if (end <= md_end) + return attr; + + md = efi_memory_descriptor(md_end); + if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr) + return 0; + } while (md); + return 0; +} + +u64 +kern_mem_attribute (unsigned long phys_addr, unsigned long size) +{ + unsigned long end = phys_addr + size; + struct kern_memdesc *md; + u64 attr; /* - * Some firmware doesn't report MMIO regions in the EFI memory - * map. The Intel BigSur (a.k.a. HP i2000) has this problem. - * On those platforms, we have to assume UC is valid everywhere. + * This is a hack for ioremap calls before we set up kern_memmap. + * Maybe we should do efi_memmap_init() earlier instead. */ - if (!md || (md->attribute & attr) != attr) { - if (attr == EFI_MEMORY_UC && !efi_memmap_has_mmio()) - return 1; + if (!kern_memmap) { + attr = efi_mem_attribute(phys_addr, size); + if (attr & EFI_MEMORY_WB) + return EFI_MEMORY_WB; return 0; } + md = kern_memory_descriptor(phys_addr); + if (!md) + return 0; + + attr = md->attribute; do { - unsigned long md_end = efi_md_end(md); + unsigned long md_end = kmd_end(md); if (end <= md_end) - return 1; + return attr; - md = efi_memory_descriptor(md_end); - if (!md || (md->attribute & attr) != attr) + md = kern_memory_descriptor(md_end); + if (!md || md->attribute != attr) return 0; } while (md); return 0; } +EXPORT_SYMBOL(kern_mem_attribute); -/* - * For /dev/mem, we only allow read & write system calls to access - * write-back memory, because read & write don't allow the user to - * control access size. - */ int valid_phys_addr_range (unsigned long phys_addr, unsigned long size) { - return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB); + u64 attr; + + /* + * /dev/mem reads and writes use copy_to_user(), which implicitly + * uses a granule-sized kernel identity mapping. It's really + * only safe to do this for regions in kern_memmap. For more + * details, see Documentation/ia64/aliasing.txt. + */ + attr = kern_mem_attribute(phys_addr, size); + if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC) + return 1; + return 0; } -/* - * We allow mmap of anything in the EFI memory map that supports - * either write-back or uncacheable access. For uncacheable regions, - * the supported access sizes are system-dependent, and the user is - * responsible for using the correct size. - * - * Note that this doesn't currently allow access to hot-added memory, - * because that doesn't appear in the boot-time EFI memory map. - */ int valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long size) { - if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB)) - return 1; + /* + * MMIO regions are often missing from the EFI memory map. + * We must allow mmap of them for programs like X, so we + * currently can't do any useful validation. + */ + return 1; +} - if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC)) - return 1; +pgprot_t +phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size, + pgprot_t vma_prot) +{ + unsigned long phys_addr = pfn << PAGE_SHIFT; + u64 attr; - return 0; + /* + * For /dev/mem mmap, we use user mappings, but if the region is + * in kern_memmap (and hence may be covered by a kernel mapping), + * we must use the same attribute as the kernel mapping. + */ + attr = kern_mem_attribute(phys_addr, size); + if (attr & EFI_MEMORY_WB) + return pgprot_cacheable(vma_prot); + else if (attr & EFI_MEMORY_UC) + return pgprot_noncached(vma_prot); + + /* + * Some chipsets don't support UC access to memory. If + * WB is supported, we prefer that. + */ + if (efi_mem_attribute(phys_addr, size) & EFI_MEMORY_WB) + return pgprot_cacheable(vma_prot); + + return pgprot_noncached(vma_prot); } int __init diff --git a/arch/ia64/kernel/efi_stub.S b/arch/ia64/kernel/efi_stub.S index 5a7fe70..a56e161 100644 --- a/arch/ia64/kernel/efi_stub.S +++ b/arch/ia64/kernel/efi_stub.S @@ -61,7 +61,7 @@ GLOBAL_ENTRY(efi_call_phys) or loc3=loc3,r17 mov b6=r2 ;; - andcm r16=loc3,r16 // get psr with IT, DT, and RT bits cleared + andcm r16=loc3,r16 // get psr with IT, DT, and RT bits cleared br.call.sptk.many rp=ia64_switch_mode_phys .ret0: mov out4=in5 mov out0=in1 diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index bcb80ca..32c999f 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1584,7 +1584,7 @@ sys_call_table: data8 sys_keyctl data8 sys_ioprio_set data8 sys_ioprio_get // 1275 - data8 sys_ni_syscall + data8 sys_move_pages data8 sys_inotify_init data8 sys_inotify_add_watch data8 sys_inotify_rm_watch diff --git a/arch/ia64/kernel/entry.h b/arch/ia64/kernel/entry.h index 78eeb07..ebc3dfb 100644 --- a/arch/ia64/kernel/entry.h +++ b/arch/ia64/kernel/entry.h @@ -23,6 +23,7 @@ #endif #define PT(f) (IA64_PT_REGS_##f##_OFFSET) #define SW(f) (IA64_SWITCH_STACK_##f##_OFFSET) +#define SOS(f) (IA64_SAL_OS_STATE_##f##_OFFSET) #define PT_REGS_SAVES(off) \ .unwabi 3, 'i'; \ diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 6c4d59f..ef9a2b4 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -46,6 +46,10 @@ #endif #define IRQ_DEBUG 0 +/* These can be overridden in platform_irq_init */ +int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR; +int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR; + /* default base addr of IPI table */ void __iomem *ipi_base_addr = ((void __iomem *) (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR)); @@ -60,7 +64,7 @@ __u8 isa_irq_to_vector_map[16] = { }; EXPORT_SYMBOL(isa_irq_to_vector_map); -static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)]; +static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)]; int assign_irq_vector (int irq) @@ -89,6 +93,19 @@ free_irq_vector (int vector) printk(KERN_WARNING "%s: double free!\n", __FUNCTION__); } +int +reserve_irq_vector (int vector) +{ + int pos; + + if (vector < IA64_FIRST_DEVICE_VECTOR || + vector > IA64_LAST_DEVICE_VECTOR) + return -EINVAL; + + pos = vector - IA64_FIRST_DEVICE_VECTOR; + return test_and_set_bit(pos, ia64_vector_mask); +} + #ifdef CONFIG_SMP # define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) #else diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index 6dff024..c1bd1fe 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -159,7 +159,7 @@ (p6) br ia64_os_mca_spin GET_IA64_MCA_DATA(r2) // Using MCA stack, struct ia64_sal_os_state, variable proc_state_param ;; - add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET, r2 + add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+SOS(PROC_STATE_PARAM), r2 ;; ld8 r18=[r3] // Get processor state parameter on existing PALE_CHECK. ;; @@ -479,9 +479,11 @@ ia64_state_save: st8 [temp2]=r11,16 // rv_rc mov r11=cr.iipa ;; - st8 [temp1]=r18,16 // proc_state_param - st8 [temp2]=r19,16 // monarch + st8 [temp1]=r18 // proc_state_param + st8 [temp2]=r19 // monarch mov r6=IA64_KR(CURRENT) + add temp1=SOS(SAL_RA), regs + add temp2=SOS(SAL_GP), regs ;; st8 [temp1]=r12,16 // sal_ra st8 [temp2]=r10,16 // sal_gp @@ -503,12 +505,14 @@ ia64_state_save: st8 [temp2]=r11,16 // cr.iipa mov r12=cr.iim ;; - st8 [temp1]=r12,16 // cr.iim + st8 [temp1]=r12 // cr.iim (p1) mov r12=IA64_MCA_COLD_BOOT (p2) mov r12=IA64_INIT_WARM_BOOT mov r6=cr.iha + add temp1=SOS(OS_STATUS), regs ;; - st8 [temp2]=r6,16 // cr.iha + st8 [temp2]=r6 // cr.iha + add temp2=SOS(CONTEXT), regs st8 [temp1]=r12 // os_status, default is cold boot mov r6=IA64_MCA_SAME_CONTEXT ;; @@ -820,8 +824,8 @@ ia64_state_restore: // Restore the SAL to OS state. The previous code left regs at pt_regs. add regs=MCA_SOS_OFFSET-MCA_PT_REGS_OFFSET, regs ;; - add temp1=IA64_SAL_OS_STATE_COMMON_OFFSET, regs - add temp2=IA64_SAL_OS_STATE_COMMON_OFFSET+8, regs + add temp1=SOS(SAL_RA), regs + add temp2=SOS(SAL_GP), regs ;; ld8 r12=[temp1],16 // sal_ra ld8 r9=[temp2],16 // sal_gp @@ -842,8 +846,10 @@ ia64_state_restore: ;; mov cr.itir=temp3 mov cr.iipa=temp4 - ld8 temp3=[temp1],16 // cr.iim - ld8 temp4=[temp2],16 // cr.iha + ld8 temp3=[temp1] // cr.iim + ld8 temp4=[temp2] // cr.iha + add temp1=SOS(OS_STATUS), regs + add temp2=SOS(CONTEXT), regs ;; mov cr.iim=temp3 mov cr.iha=temp4 @@ -916,7 +922,7 @@ (p6) br.spnt 1f // the dreaded cpu 0 ia64_new_stack: add regs=MCA_PT_REGS_OFFSET, r3 - add temp2=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET, r3 + add temp2=MCA_SOS_OFFSET+SOS(PAL_MIN_STATE), r3 mov b0=r2 // save return address GET_IA64_MCA_DATA(temp1) invala @@ -1020,7 +1026,7 @@ ia64_old_stack: ia64_set_kernel_registers: add temp3=MCA_SP_OFFSET, r3 - add temp4=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_OS_GP_OFFSET, r3 + add temp4=MCA_SOS_OFFSET+SOS(OS_GP), r3 mov b0=r2 // save return address GET_IA64_MCA_DATA(temp1) ;; diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 077f212..6d7bc8f 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -532,7 +532,6 @@ static ctl_table pfm_sysctl_root[] = { static struct ctl_table_header *pfm_sysctl_header; static int pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs); -static int pfm_flush(struct file *filp); #define pfm_get_cpu_var(v) __ia64_per_cpu_var(v) #define pfm_get_cpu_data(a,b) per_cpu(a, b) @@ -595,10 +594,11 @@ pfm_get_unmapped_area(struct file *file, } -static struct super_block * -pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) +static int +pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, + struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC); + return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC, mnt); } static struct file_system_type pfm_fs_type = { @@ -1773,7 +1773,7 @@ #endif /* CONFIG_SMP */ * When caller is self-monitoring, the context is unloaded. */ static int -pfm_flush(struct file *filp) +pfm_flush(struct file *filp, fl_owner_t id) { pfm_context_t *ctx; struct task_struct *task; diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 355d579..b045c27 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -272,9 +272,9 @@ cpu_idle (void) /* endless idle loop with no priority at all */ while (1) { if (can_do_pal_halt) - clear_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status &= ~TS_POLLING; else - set_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status |= TS_POLLING; if (!need_resched()) { void (*idle)(void); diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c index 056f7a6..77fa659 100644 --- a/arch/ia64/kernel/sal.c +++ b/arch/ia64/kernel/sal.c @@ -227,7 +227,7 @@ static int sal_cache_flush_drops_interru static void __init check_sal_cache_flush (void) { - unsigned long flags, itv; + unsigned long flags; int cpu; u64 vector; @@ -238,9 +238,6 @@ check_sal_cache_flush (void) * Schedule a timer interrupt, wait until it's reported, and see if * SAL_CACHE_FLUSH drops it. */ - itv = ia64_get_itv(); - BUG_ON((itv & (1 << 16)) == 0); - ia64_set_itv(IA64_TIMER_VECTOR); ia64_set_itm(ia64_get_itc() + 1000); @@ -260,7 +257,6 @@ check_sal_cache_flush (void) ia64_eoi(); } - ia64_set_itv(itv); local_irq_restore(flags); put_cpu(); } diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index e4dfda1..6dba2d6 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -260,6 +260,7 @@ #endif n++; num_rsvd_regions = n; + BUG_ON(IA64_MAX_RSVD_REGIONS + 1 < n); sort_regions(rsvd_region, num_rsvd_regions); } diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index 4f3a16b..879edb5 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -166,7 +166,7 @@ static void cache_shared_cpu_map_setup( num_shared = (int) csi.num_shared; do { - for_each_cpu(j) + for_each_possible_cpu(j) if (cpu_data(cpu)->socket_id == cpu_data(j)->socket_id && cpu_data(j)->core_id == csi.log1_cid && cpu_data(j)->thread_id == csi.log1_tid) diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c index fcd2bad..5f03b9e 100644 --- a/arch/ia64/kernel/uncached.c +++ b/arch/ia64/kernel/uncached.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2006 Silicon Graphics, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -29,15 +29,8 @@ #include #include #include -#define DEBUG 0 -#if DEBUG -#define dprintk printk -#else -#define dprintk(x...) do { } while (0) -#endif - -void __init efi_memmap_walk_uc (efi_freemem_callback_t callback); +extern void __init efi_memmap_walk_uc(efi_freemem_callback_t, void *); #define MAX_UNCACHED_GRANULES 5 static int allocated_granules; @@ -60,6 +53,7 @@ static void uncached_ipi_visibility(void static void uncached_ipi_mc_drain(void *data) { int status; + status = ia64_pal_mc_drain(); if (status) printk(KERN_WARNING "ia64_pal_mc_drain() failed with %i on " @@ -67,30 +61,35 @@ static void uncached_ipi_mc_drain(void * } -static unsigned long -uncached_get_new_chunk(struct gen_pool *poolp) +/* + * Add a new chunk of uncached memory pages to the specified pool. + * + * @pool: pool to add new chunk of uncached memory to + * @nid: node id of node to allocate memory from, or -1 + * + * This is accomplished by first allocating a granule of cached memory pages + * and then converting them to uncached memory pages. + */ +static int uncached_add_chunk(struct gen_pool *pool, int nid) { struct page *page; - void *tmp; int status, i; - unsigned long addr, node; + unsigned long c_addr, uc_addr; if (allocated_granules >= MAX_UNCACHED_GRANULES) - return 0; + return -1; + + /* attempt to allocate a granule's worth of cached memory pages */ - node = poolp->private; - page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, + page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO, IA64_GRANULE_SHIFT-PAGE_SHIFT); + if (!page) + return -1; - dprintk(KERN_INFO "get_new_chunk page %p, addr %lx\n", - page, (unsigned long)(page-vmem_map) << PAGE_SHIFT); + /* convert the memory pages from cached to uncached */ - /* - * Do magic if no mem on local node! XXX - */ - if (!page) - return 0; - tmp = page_address(page); + c_addr = (unsigned long)page_address(page); + uc_addr = c_addr - PAGE_OFFSET + __IA64_UNCACHED_OFFSET; /* * There's a small race here where it's possible for someone to @@ -100,76 +99,90 @@ uncached_get_new_chunk(struct gen_pool * for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++) SetPageUncached(&page[i]); - flush_tlb_kernel_range(tmp, tmp + IA64_GRANULE_SIZE); + flush_tlb_kernel_range(uc_addr, uc_adddr + IA64_GRANULE_SIZE); status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL); - - dprintk(KERN_INFO "pal_prefetch_visibility() returns %i on cpu %i\n", - status, raw_smp_processor_id()); - if (!status) { status = smp_call_function(uncached_ipi_visibility, NULL, 0, 1); if (status) - printk(KERN_WARNING "smp_call_function failed for " - "uncached_ipi_visibility! (%i)\n", status); + goto failed; } + preempt_disable(); + if (ia64_platform_is("sn2")) - sn_flush_all_caches((unsigned long)tmp, IA64_GRANULE_SIZE); + sn_flush_all_caches(uc_addr, IA64_GRANULE_SIZE); else - flush_icache_range((unsigned long)tmp, - (unsigned long)tmp+IA64_GRANULE_SIZE); + flush_icache_range(uc_addr, uc_addr + IA64_GRANULE_SIZE); + + /* flush the just introduced uncached translation from the TLB */ + local_flush_tlb_all(); + + preempt_enable(); ia64_pal_mc_drain(); status = smp_call_function(uncached_ipi_mc_drain, NULL, 0, 1); if (status) - printk(KERN_WARNING "smp_call_function failed for " - "uncached_ipi_mc_drain! (%i)\n", status); + goto failed; - addr = (unsigned long)tmp - PAGE_OFFSET + __IA64_UNCACHED_OFFSET; + /* + * The chunk of memory pages has been converted to uncached so now we + * can add it to the pool. + */ + status = gen_pool_add(pool, uc_addr, IA64_GRANULE_SIZE, nid); + if (status) + goto failed; allocated_granules++; - return addr; + return 0; + + /* failed to convert or add the chunk so give it back to the kernel */ +failed: + for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++) + ClearPageUncached(&page[i]); + + free_pages(c_addr, IA64_GRANULE_SHIFT-PAGE_SHIFT); + return -1; } /* * uncached_alloc_page * + * @starting_nid: node id of node to start with, or -1 + * * Allocate 1 uncached page. Allocates on the requested node. If no * uncached pages are available on the requested node, roundrobin starting - * with higher nodes. + * with the next higher node. */ -unsigned long -uncached_alloc_page(int nid) +unsigned long uncached_alloc_page(int starting_nid) { - unsigned long maddr; + unsigned long uc_addr; + struct gen_pool *pool; + int nid; - maddr = gen_pool_alloc(uncached_pool[nid], PAGE_SIZE); + if (unlikely(starting_nid >= MAX_NUMNODES)) + return 0; - dprintk(KERN_DEBUG "uncached_alloc_page returns %lx on node %i\n", - maddr, nid); + if (starting_nid < 0) + starting_nid = numa_node_id(); + nid = starting_nid; - /* - * If no memory is availble on our local node, try the - * remaining nodes in the system. - */ - if (!maddr) { - int i; - - for (i = MAX_NUMNODES - 1; i >= 0; i--) { - if (i == nid || !node_online(i)) - continue; - maddr = gen_pool_alloc(uncached_pool[i], PAGE_SIZE); - dprintk(KERN_DEBUG "uncached_alloc_page alternate search " - "returns %lx on node %i\n", maddr, i); - if (maddr) { - break; - } - } - } + do { + if (!node_online(nid)) + continue; + pool = uncached_pool[nid]; + if (pool == NULL) + continue; + do { + uc_addr = gen_pool_alloc(pool, PAGE_SIZE); + if (uc_addr != 0) + return uc_addr; + } while (uncached_add_chunk(pool, nid) == 0); + + } while ((nid = (nid + 1) % MAX_NUMNODES) != starting_nid); - return maddr; + return 0; } EXPORT_SYMBOL(uncached_alloc_page); @@ -177,21 +190,22 @@ EXPORT_SYMBOL(uncached_alloc_page); /* * uncached_free_page * + * @uc_addr: uncached address of page to free + * * Free a single uncached page. */ -void -uncached_free_page(unsigned long maddr) +void uncached_free_page(unsigned long uc_addr) { - int node; - - node = paddr_to_nid(maddr - __IA64_UNCACHED_OFFSET); + int nid = paddr_to_nid(uc_addr - __IA64_UNCACHED_OFFSET); + struct gen_pool *pool = uncached_pool[nid]; - dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node); + if (unlikely(pool == NULL)) + return; - if ((maddr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET) - panic("uncached_free_page invalid address %lx\n", maddr); + if ((uc_addr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET) + panic("uncached_free_page invalid address %lx\n", uc_addr); - gen_pool_free(uncached_pool[node], maddr, PAGE_SIZE); + gen_pool_free(pool, uc_addr, PAGE_SIZE); } EXPORT_SYMBOL(uncached_free_page); @@ -199,43 +213,39 @@ EXPORT_SYMBOL(uncached_free_page); /* * uncached_build_memmap, * + * @uc_start: uncached starting address of a chunk of uncached memory + * @uc_end: uncached ending address of a chunk of uncached memory + * @arg: ignored, (NULL argument passed in on call to efi_memmap_walk_uc()) + * * Called at boot time to build a map of pages that can be used for * memory special operations. */ -static int __init -uncached_build_memmap(unsigned long start, unsigned long end, void *arg) +static int __init uncached_build_memmap(unsigned long uc_start, + unsigned long uc_end, void *arg) { - long length = end - start; - int node; - - dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end); + int nid = paddr_to_nid(uc_start - __IA64_UNCACHED_OFFSET); + struct gen_pool *pool = uncached_pool[nid]; + size_t size = uc_end - uc_start; touch_softlockup_watchdog(); - memset((char *)start, 0, length); - node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET); - - for (; start < end ; start += PAGE_SIZE) { - dprintk(KERN_INFO "sticking %lx into the pool!\n", start); - gen_pool_free(uncached_pool[node], start, PAGE_SIZE); + if (pool != NULL) { + memset((char *)uc_start, 0, size); + (void) gen_pool_add(pool, uc_start, size, nid); } - return 0; } -static int __init uncached_init(void) { - int i; +static int __init uncached_init(void) +{ + int nid; - for (i = 0; i < MAX_NUMNODES; i++) { - if (!node_online(i)) - continue; - uncached_pool[i] = gen_pool_create(0, IA64_GRANULE_SHIFT, - &uncached_get_new_chunk, i); + for_each_online_node(nid) { + uncached_pool[nid] = gen_pool_create(PAGE_SHIFT, nid); } - efi_memmap_walk_uc(uncached_build_memmap); - + efi_memmap_walk_uc(uncached_build_memmap, NULL); return 0; } diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index d98ec49..14ef7cc 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -19,6 +19,40 @@ #include extern void die (char *, struct pt_regs *, long); +#ifdef CONFIG_KPROBES +ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); + +/* Hook to register for page fault notifications */ +int register_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); +} + +int unregister_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); +} + +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + struct die_args args = { + .regs = regs, + .str = str, + .err = err, + .trapnr = trap, + .signr = sig + }; + return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); +} +#else +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + return NOTIFY_DONE; +} +#endif + /* * Return TRUE if ADDRESS points at a page in the kernel's mapped segment * (inside region 5, on ia64) and that page is present. @@ -84,7 +118,7 @@ #endif /* * This is to handle the kprobes on user space access instructions */ - if (notify_die(DIE_PAGE_FAULT, "page fault", regs, code, TRAP_BRKPT, + if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, code, TRAP_BRKPT, SIGSEGV) == NOTIFY_STOP) return; diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index cafa877..11f0800 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -671,9 +671,11 @@ int add_memory(u64 start, u64 size) return ret; } +EXPORT_SYMBOL_GPL(add_memory); int remove_memory(u64 start, u64 size) { return -EINVAL; } +EXPORT_SYMBOL_GPL(remove_memory); #endif diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c index 643ccc6..07bd02b 100644 --- a/arch/ia64/mm/ioremap.c +++ b/arch/ia64/mm/ioremap.c @@ -11,6 +11,7 @@ #include #include #include #include +#include static inline void __iomem * __ioremap (unsigned long offset, unsigned long size) @@ -21,16 +22,29 @@ __ioremap (unsigned long offset, unsigne void __iomem * ioremap (unsigned long offset, unsigned long size) { - if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB)) - return phys_to_virt(offset); + u64 attr; + unsigned long gran_base, gran_size; - if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC)) + /* + * For things in kern_memmap, we must use the same attribute + * as the rest of the kernel. For more details, see + * Documentation/ia64/aliasing.txt. + */ + attr = kern_mem_attribute(offset, size); + if (attr & EFI_MEMORY_WB) + return phys_to_virt(offset); + else if (attr & EFI_MEMORY_UC) return __ioremap(offset, size); /* - * Someday this should check ACPI resources so we - * can do the right thing for hot-plugged regions. + * Some chipsets don't support UC access to memory. If + * WB is supported for the whole granule, we prefer that. */ + gran_base = GRANULEROUNDDOWN(offset); + gran_size = GRANULEROUNDUP(offset + size) - gran_base; + if (efi_mem_attribute(gran_base, gran_size) & EFI_MEMORY_WB) + return phys_to_virt(offset); + return __ioremap(offset, size); } EXPORT_SYMBOL(ioremap); @@ -38,6 +52,9 @@ EXPORT_SYMBOL(ioremap); void __iomem * ioremap_nocache (unsigned long offset, unsigned long size) { + if (kern_mem_attribute(offset, size) & EFI_MEMORY_WB) + return 0; + return __ioremap(offset, size); } EXPORT_SYMBOL(ioremap_nocache); diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index ab829a2..77375a5 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -352,7 +352,7 @@ pci_acpi_scan_root(struct acpi_device *d pxm = acpi_get_pxm(controller->acpi_handle); #ifdef CONFIG_NUMA if (pxm >= 0) - controller->node = pxm_to_nid_map[pxm]; + controller->node = pxm_to_node(pxm); #endif acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, @@ -602,8 +602,6 @@ pci_mmap_page_range (struct pci_dev *dev * Leave vm_pgoff as-is, the PCI space address is the physical * address on this platform. */ - vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO); - if (write_combine && efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start)) vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); @@ -645,18 +643,30 @@ char *ia64_pci_get_legacy_mem(struct pci int pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma) { + unsigned long size = vma->vm_end - vma->vm_start; + pgprot_t prot; char *addr; + /* + * Avoid attribute aliasing. See Documentation/ia64/aliasing.txt + * for more details. + */ + if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, size)) + return -EINVAL; + prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size, + vma->vm_page_prot); + if (pgprot_val(prot) != pgprot_val(pgprot_noncached(vma->vm_page_prot))) + return -EINVAL; + addr = pci_get_legacy_mem(bus); if (IS_ERR(addr)) return PTR_ERR(addr); vma->vm_pgoff += (unsigned long)addr >> PAGE_SHIFT; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO); + vma->vm_page_prot = prot; if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) + size, vma->vm_page_prot)) return -EAGAIN; return 0; diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 5101ac4..dc09a6a 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -58,7 +58,7 @@ static int max_pcibus_number = 255; /* D */ static dma_addr_t -sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size) +sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type) { return 0; } @@ -457,13 +457,6 @@ void sn_pci_fixup_slot(struct pci_dev *d pcidev_info->pdi_sn_irq_info = NULL; kfree(sn_irq_info); } - - /* - * MSI currently not supported on altix. Remove this when - * the MSI abstraction patches are integrated into the kernel - * (sometime after 2.6.16 releases) - */ - dev->no_msi = 1; } /* diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index c265e02..dc8e2b6 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -26,11 +26,11 @@ static void unregister_intr_pda(struct s int sn_force_interrupt_flag = 1; extern int sn_ioif_inited; -static struct list_head **sn_irq_lh; +struct list_head **sn_irq_lh; static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */ -static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, - u64 sn_irq_info, +u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, + struct sn_irq_info *sn_irq_info, int req_irq, nasid_t req_nasid, int req_slice) { @@ -40,12 +40,13 @@ static inline u64 sn_intr_alloc(nasid_t SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT, (u64) SAL_INTR_ALLOC, (u64) local_nasid, - (u64) local_widget, (u64) sn_irq_info, (u64) req_irq, + (u64) local_widget, __pa(sn_irq_info), (u64) req_irq, (u64) req_nasid, (u64) req_slice); + return ret_stuff.status; } -static inline void sn_intr_free(nasid_t local_nasid, int local_widget, +void sn_intr_free(nasid_t local_nasid, int local_widget, struct sn_irq_info *sn_irq_info) { struct ia64_sal_retval ret_stuff; @@ -112,73 +113,91 @@ static void sn_end_irq(unsigned int irq) static void sn_irq_info_free(struct rcu_head *head); -static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) +struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, + nasid_t nasid, int slice) { - struct sn_irq_info *sn_irq_info, *sn_irq_info_safe; - int cpuid, cpuphys; + int vector; + int cpuphys; + int64_t bridge; + int local_widget, status; + nasid_t local_nasid; + struct sn_irq_info *new_irq_info; + struct sn_pcibus_provider *pci_provider; - cpuid = first_cpu(mask); - cpuphys = cpu_physical_id(cpuid); + new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); + if (new_irq_info == NULL) + return NULL; - list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, - sn_irq_lh[irq], list) { - u64 bridge; - int local_widget, status; - nasid_t local_nasid; - struct sn_irq_info *new_irq_info; - struct sn_pcibus_provider *pci_provider; - - new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); - if (new_irq_info == NULL) - break; - memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); - - bridge = (u64) new_irq_info->irq_bridge; - if (!bridge) { - kfree(new_irq_info); - break; /* irq is not a device interrupt */ - } + memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); + + bridge = (u64) new_irq_info->irq_bridge; + if (!bridge) { + kfree(new_irq_info); + return NULL; /* irq is not a device interrupt */ + } - local_nasid = NASID_GET(bridge); + local_nasid = NASID_GET(bridge); - if (local_nasid & 1) - local_widget = TIO_SWIN_WIDGETNUM(bridge); - else - local_widget = SWIN_WIDGETNUM(bridge); + if (local_nasid & 1) + local_widget = TIO_SWIN_WIDGETNUM(bridge); + else + local_widget = SWIN_WIDGETNUM(bridge); - /* Free the old PROM new_irq_info structure */ - sn_intr_free(local_nasid, local_widget, new_irq_info); - /* Update kernels new_irq_info with new target info */ - unregister_intr_pda(new_irq_info); + vector = sn_irq_info->irq_irq; + /* Free the old PROM new_irq_info structure */ + sn_intr_free(local_nasid, local_widget, new_irq_info); + /* Update kernels new_irq_info with new target info */ + unregister_intr_pda(new_irq_info); - /* allocate a new PROM new_irq_info struct */ - status = sn_intr_alloc(local_nasid, local_widget, - __pa(new_irq_info), irq, - cpuid_to_nasid(cpuid), - cpuid_to_slice(cpuid)); + /* allocate a new PROM new_irq_info struct */ + status = sn_intr_alloc(local_nasid, local_widget, + new_irq_info, vector, + nasid, slice); - /* SAL call failed */ - if (status) { - kfree(new_irq_info); - break; - } + /* SAL call failed */ + if (status) { + kfree(new_irq_info); + return NULL; + } - new_irq_info->irq_cpuid = cpuid; - register_intr_pda(new_irq_info); + cpuphys = nasid_slice_to_cpuid(nasid, slice); + new_irq_info->irq_cpuid = cpuphys; + register_intr_pda(new_irq_info); - pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; - if (pci_provider && pci_provider->target_interrupt) - (pci_provider->target_interrupt)(new_irq_info); + pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; - spin_lock(&sn_irq_info_lock); - list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); - spin_unlock(&sn_irq_info_lock); - call_rcu(&sn_irq_info->rcu, sn_irq_info_free); + /* + * If this represents a line interrupt, target it. If it's + * an msi (irq_int_bit < 0), it's already targeted. + */ + if (new_irq_info->irq_int_bit >= 0 && + pci_provider && pci_provider->target_interrupt) + (pci_provider->target_interrupt)(new_irq_info); + + spin_lock(&sn_irq_info_lock); + list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); + spin_unlock(&sn_irq_info_lock); + call_rcu(&sn_irq_info->rcu, sn_irq_info_free); #ifdef CONFIG_SMP - set_irq_affinity_info((irq & 0xff), cpuphys, 0); + set_irq_affinity_info((vector & 0xff), cpuphys, 0); #endif - } + + return new_irq_info; +} + +static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) +{ + struct sn_irq_info *sn_irq_info, *sn_irq_info_safe; + nasid_t nasid; + int slice; + + nasid = cpuid_to_nasid(first_cpu(mask)); + slice = cpuid_to_slice(first_cpu(mask)); + + list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, + sn_irq_lh[irq], list) + (void)sn_retarget_vector(sn_irq_info, nasid, slice); } struct hw_interrupt_type irq_type_sn = { @@ -202,6 +221,9 @@ void sn_irq_init(void) int i; irq_desc_t *base_desc = irq_desc; + ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR; + ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR; + for (i = 0; i < NR_IRQS; i++) { if (base_desc[i].handler == &no_irq_type) { base_desc[i].handler = &irq_type_sn; @@ -285,6 +307,7 @@ void sn_irq_fixup(struct pci_dev *pci_de /* link it into the sn_irq[irq] list */ spin_lock(&sn_irq_info_lock); list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]); + reserve_irq_vector(sn_irq_info->irq_irq); spin_unlock(&sn_irq_info_lock); register_intr_pda(sn_irq_info); @@ -310,8 +333,11 @@ void sn_irq_unfixup(struct pci_dev *pci_ spin_lock(&sn_irq_info_lock); list_del_rcu(&sn_irq_info->list); spin_unlock(&sn_irq_info_lock); + if (list_empty(sn_irq_lh[sn_irq_info->irq_irq])) + free_irq_vector(sn_irq_info->irq_irq); call_rcu(&sn_irq_info->rcu, sn_irq_info_free); pci_dev_put(pci_dev); + } static inline void diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 30988df..93577ab 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -139,7 +139,7 @@ static int __init pxm_to_nasid(int pxm) int i; int nid; - nid = pxm_to_nid_map[pxm]; + nid = pxm_to_node(pxm); for (i = 0; i < num_node_memblks; i++) { if (node_memblk[i].nid == nid) { return NASID_GET(node_memblk[i].start_paddr); @@ -704,7 +704,7 @@ void __init build_cnode_tables(void) * cnode == node for all C & M bricks. */ for_each_online_node(node) { - nasid = pxm_to_nasid(nid_to_pxm_map[node]); + nasid = pxm_to_nasid(node_to_pxm(node)); sn_cnodeid_to_nasid[node] = nasid; physical_node_map[nasid] = node; } diff --git a/arch/ia64/sn/kernel/sn2/cache.c b/arch/ia64/sn/kernel/sn2/cache.c index bc3cfa1..2862cb3 100644 --- a/arch/ia64/sn/kernel/sn2/cache.c +++ b/arch/ia64/sn/kernel/sn2/cache.c @@ -3,11 +3,12 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2003, 2006 Silicon Graphics, Inc. All rights reserved. * */ #include #include +#include /** * sn_flush_all_caches - flush a range of address from all caches (incl. L4) @@ -17,18 +18,24 @@ #include * Flush a range of addresses from all caches including L4. * All addresses fully or partially contained within * @flush_addr to @flush_addr + @bytes are flushed - * from the all caches. + * from all caches. */ void sn_flush_all_caches(long flush_addr, long bytes) { - flush_icache_range(flush_addr, flush_addr+bytes); + unsigned long addr = flush_addr; + + /* SHub1 requires a cached address */ + if (is_shub1() && (addr & RGN_BITS) == RGN_BASE(RGN_UNCACHED)) + addr = (addr - RGN_BASE(RGN_UNCACHED)) + RGN_BASE(RGN_KERNEL); + + flush_icache_range(addr, addr + bytes); /* * The last call may have returned before the caches * were actually flushed, so we call it again to make * sure. */ - flush_icache_range(flush_addr, flush_addr+bytes); + flush_icache_range(addr, addr + bytes); mb(); } EXPORT_SYMBOL(sn_flush_all_caches); diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 739c948..9a8a293 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -51,6 +51,8 @@ static nasid_t sn_hwperf_master_nasid = static int sn_hwperf_init(void); static DECLARE_MUTEX(sn_hwperf_init_mutex); +#define cnode_possible(n) ((n) < num_cnodes) + static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret) { int e; @@ -127,14 +129,14 @@ static int sn_hwperf_geoid_to_cnode(char } } - return node_possible(cnode) ? cnode : -1; + return cnode_possible(cnode) ? cnode : -1; } static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj) { if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) BUG(); - if (!obj->sn_hwp_this_part) + if (SN_HWPERF_FOREIGN(obj)) return -1; return sn_hwperf_geoid_to_cnode(obj->location); } @@ -199,12 +201,12 @@ static void print_pci_topology(struct se static inline int sn_hwperf_has_cpus(cnodeid_t node) { - return node_online(node) && nr_cpus_node(node); + return node < MAX_NUMNODES && node_online(node) && nr_cpus_node(node); } static inline int sn_hwperf_has_mem(cnodeid_t node) { - return node_online(node) && NODE_DATA(node)->node_present_pages; + return node < MAX_NUMNODES && node_online(node) && NODE_DATA(node)->node_present_pages; } static struct sn_hwperf_object_info * @@ -237,7 +239,7 @@ static int sn_hwperf_get_nearest_node_ob int found_mem = 0; int found_cpu = 0; - if (!node_possible(node)) + if (!cnode_possible(node)) return -EINVAL; if (sn_hwperf_has_cpus(node)) { @@ -442,7 +444,7 @@ static int sn_topology_show(struct seq_f seq_printf(s, "%s %d %s %s asic %s", slabname, ordinal, obj->location, obj->sn_hwp_this_part ? "local" : "shared", obj->name); - if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) + if (ordinal < 0 || (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))) seq_putc(s, '\n'); else { cnodeid_t near_mem = -1; @@ -468,22 +470,24 @@ static int sn_topology_show(struct seq_f /* * CPUs on this node, if any */ - cpumask = node_to_cpumask(ordinal); - for_each_online_cpu(i) { - if (cpu_isset(i, cpumask)) { - slice = 'a' + cpuid_to_slice(i); - c = cpu_data(i); - seq_printf(s, "cpu %d %s%c local" - " freq %luMHz, arch ia64", - i, obj->location, slice, - c->proc_freq / 1000000); - for_each_online_cpu(j) { - seq_printf(s, j ? ":%d" : ", dist %d", - node_distance( - cpu_to_node(i), - cpu_to_node(j))); + if (!SN_HWPERF_IS_IONODE(obj)) { + cpumask = node_to_cpumask(ordinal); + for_each_online_cpu(i) { + if (cpu_isset(i, cpumask)) { + slice = 'a' + cpuid_to_slice(i); + c = cpu_data(i); + seq_printf(s, "cpu %d %s%c local" + " freq %luMHz, arch ia64", + i, obj->location, slice, + c->proc_freq / 1000000); + for_each_online_cpu(j) { + seq_printf(s, j ? ":%d" : ", dist %d", + node_distance( + cpu_to_node(i), + cpu_to_node(j))); + } + seq_putc(s, '\n'); } - seq_putc(s, '\n'); } } } @@ -523,7 +527,7 @@ static int sn_topology_show(struct seq_f if (obj->sn_hwp_this_part && p->sn_hwp_this_part) /* both ends local to this partition */ seq_puts(s, " local"); - else if (!obj->sn_hwp_this_part && !p->sn_hwp_this_part) + else if (SN_HWPERF_FOREIGN(p)) /* both ends of the link in foreign partiton */ seq_puts(s, " foreign"); else @@ -776,7 +780,7 @@ sn_hwperf_ioctl(struct inode *in, struct case SN_HWPERF_GET_NODE_NASID: if (a.sz != sizeof(u64) || - (node = a.arg) < 0 || !node_possible(node)) { + (node = a.arg) < 0 || !cnode_possible(node)) { r = -EINVAL; goto error; } diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index b4b84c2..7a291a2 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include @@ -113,7 +113,8 @@ void *sn_dma_alloc_coherent(struct devic * resources. */ - *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size); + *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size, + SN_DMA_ADDR_PHYS); if (!*dma_handle) { printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); free_pages((unsigned long)cpuaddr, get_order(size)); @@ -176,7 +177,7 @@ dma_addr_t sn_dma_map_single(struct devi BUG_ON(dev->bus != &pci_bus_type); phys_addr = __pa(cpu_addr); - dma_addr = provider->dma_map(pdev, phys_addr, size); + dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS); if (!dma_addr) { printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); return 0; @@ -260,7 +261,8 @@ int sn_dma_map_sg(struct device *dev, st for (i = 0; i < nhwentries; i++, sg++) { phys_addr = SG_ENT_PHYS_ADDRESS(sg); sg->dma_address = provider->dma_map(pdev, - phys_addr, sg->length); + phys_addr, sg->length, + SN_DMA_ADDR_PHYS); if (!sg->dma_address) { printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index 9f86bb6..a86c7b9 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c @@ -41,7 +41,7 @@ extern int sn_ioif_inited; static dma_addr_t pcibr_dmamap_ate32(struct pcidev_info *info, - u64 paddr, size_t req_size, u64 flags) + u64 paddr, size_t req_size, u64 flags, int dma_flags) { struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; @@ -81,9 +81,12 @@ pcibr_dmamap_ate32(struct pcidev_info *i if (IS_PCIX(pcibus_info)) ate_flags &= ~(PCI32_ATE_PREF); - xio_addr = - IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : - PHYS_TO_TIODMA(paddr); + if (SN_DMA_ADDRTYPE(dma_flags == SN_DMA_ADDR_PHYS)) + xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : + PHYS_TO_TIODMA(paddr); + else + xio_addr = paddr; + offset = IOPGOFF(xio_addr); ate = ate_flags | (xio_addr - offset); @@ -91,6 +94,13 @@ pcibr_dmamap_ate32(struct pcidev_info *i if (IS_PIC_SOFT(pcibus_info)) { ate |= (pcibus_info->pbi_hub_xid << PIC_ATE_TARGETID_SHFT); } + + /* + * If we're mapping for MSI, set the MSI bit in the ATE + */ + if (dma_flags & SN_DMA_MSI) + ate |= PCI32_ATE_MSI; + ate_write(pcibus_info, ate_index, ate_count, ate); /* @@ -105,20 +115,27 @@ pcibr_dmamap_ate32(struct pcidev_info *i if (pcibus_info->pbi_devreg[internal_device] & PCIBR_DEV_SWAP_DIR) ATE_SWAP_ON(pci_addr); + return pci_addr; } static dma_addr_t pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, - u64 dma_attributes) + u64 dma_attributes, int dma_flags) { struct pcibus_info *pcibus_info = (struct pcibus_info *) ((info->pdi_host_pcidev_info)->pdi_pcibus_info); u64 pci_addr; /* Translate to Crosstalk View of Physical Address */ - pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : - PHYS_TO_TIODMA(paddr)) | dma_attributes; + if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS) + pci_addr = IS_PIC_SOFT(pcibus_info) ? + PHYS_TO_DMA(paddr) : + PHYS_TO_TIODMA(paddr) | dma_attributes; + else + pci_addr = IS_PIC_SOFT(pcibus_info) ? + paddr : + paddr | dma_attributes; /* Handle Bus mode */ if (IS_PCIX(pcibus_info)) @@ -130,7 +147,9 @@ pcibr_dmatrans_direct64(struct pcidev_in ((u64) pcibus_info-> pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT); } else - pci_addr |= TIOCP_PCI64_CMDTYPE_MEM; + pci_addr |= (dma_flags & SN_DMA_MSI) ? + TIOCP_PCI64_CMDTYPE_MSI : + TIOCP_PCI64_CMDTYPE_MEM; /* If PCI mode, func zero uses VCHAN0, every other func uses VCHAN1 */ if (!IS_PCIX(pcibus_info) && PCI_FUNC(info->pdi_linux_pcidev->devfn)) @@ -141,7 +160,7 @@ pcibr_dmatrans_direct64(struct pcidev_in static dma_addr_t pcibr_dmatrans_direct32(struct pcidev_info * info, - u64 paddr, size_t req_size, u64 flags) + u64 paddr, size_t req_size, u64 flags, int dma_flags) { struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> @@ -156,8 +175,14 @@ pcibr_dmatrans_direct32(struct pcidev_in return 0; } - xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : - PHYS_TO_TIODMA(paddr); + if (dma_flags & SN_DMA_MSI) + return 0; + + if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS) + xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : + PHYS_TO_TIODMA(paddr); + else + xio_addr = paddr; xio_base = pcibus_info->pbi_dir_xbase; offset = xio_addr - xio_base; @@ -327,7 +352,7 @@ void sn_dma_flush(u64 addr) */ dma_addr_t -pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size) +pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size, int dma_flags) { dma_addr_t dma_handle; struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev); @@ -344,11 +369,11 @@ pcibr_dma_map(struct pci_dev * hwdev, un */ dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr, - PCI64_ATTR_PREF); + PCI64_ATTR_PREF, dma_flags); } else { /* Handle 32-63 bit cards via direct mapping */ dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr, - size, 0); + size, 0, dma_flags); if (!dma_handle) { /* * It is a 32 bit card and we cannot do direct mapping, @@ -356,7 +381,8 @@ pcibr_dma_map(struct pci_dev * hwdev, un */ dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr, - size, PCI32_ATE_PREF); + size, PCI32_ATE_PREF, + dma_flags); } } @@ -365,18 +391,18 @@ pcibr_dma_map(struct pci_dev * hwdev, un dma_addr_t pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr, - size_t size) + size_t size, int dma_flags) { dma_addr_t dma_handle; struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev); if (hwdev->dev.coherent_dma_mask == ~0UL) { dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr, - PCI64_ATTR_BAR); + PCI64_ATTR_BAR, dma_flags); } else { dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info, phys_addr, size, - PCI32_ATE_BAR); + PCI32_ATE_BAR, dma_flags); } return dma_handle; diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index be01769..20de727 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -515,11 +515,17 @@ tioca_dma_unmap(struct pci_dev *pdev, dm * use the GART mapped mode. */ static u64 -tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count) +tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) { u64 mapaddr; /* + * Not supported for now ... + */ + if (dma_flags & SN_DMA_MSI) + return 0; + + /* * If card is 64 or 48 bit addresable, use a direct mapping. 32 * bit direct is so restrictive w.r.t. where the memory resides that * we don't use it even though CA has some support. diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index 8332956..2d79485 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2003-2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2003-2006 Silicon Graphics, Inc. All Rights Reserved. */ #include @@ -170,7 +170,8 @@ #define ATE_NPAGES(start, len, pagesize) (ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1) #define ATE_VALID(ate) ((ate) & (1UL << 63)) -#define ATE_MAKE(addr, ps) (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63)) +#define ATE_MAKE(addr, ps, msi) \ + (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63) | ((msi)?(1UL << 62):0)) /* * Flavors of ate-based mapping supported by tioce_alloc_map() @@ -196,15 +197,17 @@ #define GB(x) ((u64)(x) << 30) * * 63 - must be 1 to indicate d64 mode to CE hardware * 62 - barrier bit ... controlled with tioce_dma_barrier() - * 61 - 0 since this is not an MSI transaction + * 61 - msi bit ... specified through dma_flags * 60:54 - reserved, MBZ */ static u64 -tioce_dma_d64(unsigned long ct_addr) +tioce_dma_d64(unsigned long ct_addr, int dma_flags) { u64 bus_addr; bus_addr = ct_addr | (1UL << 63); + if (dma_flags & SN_DMA_MSI) + bus_addr |= (1UL << 61); return bus_addr; } @@ -261,7 +264,7 @@ pcidev_to_tioce(struct pci_dev *pdev, st */ static u64 tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, - u64 ct_addr, int len) + u64 ct_addr, int len, int dma_flags) { int i; int j; @@ -270,6 +273,7 @@ tioce_alloc_map(struct tioce_kernel *ce_ int entries; int nates; u64 pagesize; + int msi_capable, msi_wanted; u64 *ate_shadow; u64 *ate_reg; u64 addr; @@ -291,6 +295,7 @@ tioce_alloc_map(struct tioce_kernel *ce_ ate_reg = ce_mmr->ce_ure_ate3240; pagesize = ce_kern->ce_ate3240_pagesize; bus_base = TIOCE_M32_MIN; + msi_capable = 1; break; case TIOCE_ATE_M40: first = 0; @@ -299,6 +304,7 @@ tioce_alloc_map(struct tioce_kernel *ce_ ate_reg = ce_mmr->ce_ure_ate40; pagesize = MB(64); bus_base = TIOCE_M40_MIN; + msi_capable = 0; break; case TIOCE_ATE_M40S: /* @@ -311,11 +317,16 @@ tioce_alloc_map(struct tioce_kernel *ce_ ate_reg = ce_mmr->ce_ure_ate3240; pagesize = GB(16); bus_base = TIOCE_M40S_MIN; + msi_capable = 0; break; default: return 0; } + msi_wanted = dma_flags & SN_DMA_MSI; + if (msi_wanted && !msi_capable) + return 0; + nates = ATE_NPAGES(ct_addr, len, pagesize); if (nates > entries) return 0; @@ -344,7 +355,7 @@ tioce_alloc_map(struct tioce_kernel *ce_ for (j = 0; j < nates; j++) { u64 ate; - ate = ATE_MAKE(addr, pagesize); + ate = ATE_MAKE(addr, pagesize, msi_wanted); ate_shadow[i + j] = ate; tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate); addr += pagesize; @@ -371,7 +382,7 @@ tioce_alloc_map(struct tioce_kernel *ce_ * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info. */ static u64 -tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr) +tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr, int dma_flags) { int dma_ok; int port; @@ -381,6 +392,9 @@ tioce_dma_d32(struct pci_dev *pdev, u64 u64 ct_lower; dma_addr_t bus_addr; + if (dma_flags & SN_DMA_MSI) + return 0; + ct_upper = ct_addr & ~0x3fffffffUL; ct_lower = ct_addr & 0x3fffffffUL; @@ -507,7 +521,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dm */ static u64 tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, - int barrier) + int barrier, int dma_flags) { unsigned long flags; u64 ct_addr; @@ -523,15 +537,18 @@ tioce_do_dma_map(struct pci_dev *pdev, u if (dma_mask < 0x7fffffffUL) return 0; - ct_addr = PHYS_TO_TIODMA(paddr); + if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS) + ct_addr = PHYS_TO_TIODMA(paddr); + else + ct_addr = paddr; /* * If the device can generate 64 bit addresses, create a D64 map. - * Since this should never fail, bypass the rest of the checks. */ if (dma_mask == ~0UL) { - mapaddr = tioce_dma_d64(ct_addr); - goto dma_map_done; + mapaddr = tioce_dma_d64(ct_addr, dma_flags); + if (mapaddr) + goto dma_map_done; } pcidev_to_tioce(pdev, NULL, &ce_kern, &port); @@ -574,18 +591,22 @@ tioce_do_dma_map(struct pci_dev *pdev, u if (byte_count > MB(64)) { mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S, - port, ct_addr, byte_count); + port, ct_addr, byte_count, + dma_flags); if (!mapaddr) mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1, - ct_addr, byte_count); + ct_addr, byte_count, + dma_flags); } else { mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1, - ct_addr, byte_count); + ct_addr, byte_count, + dma_flags); if (!mapaddr) mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S, - port, ct_addr, byte_count); + port, ct_addr, byte_count, + dma_flags); } } @@ -593,7 +614,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u * 32-bit direct is the next mode to try */ if (!mapaddr && dma_mask >= 0xffffffffUL) - mapaddr = tioce_dma_d32(pdev, ct_addr); + mapaddr = tioce_dma_d32(pdev, ct_addr, dma_flags); /* * Last resort, try 32-bit ATE-based map. @@ -601,7 +622,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u if (!mapaddr) mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr, - byte_count); + byte_count, dma_flags); spin_unlock_irqrestore(&ce_kern->ce_lock, flags); @@ -622,9 +643,9 @@ dma_map_done: * in the address. */ static u64 -tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count) +tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) { - return tioce_do_dma_map(pdev, paddr, byte_count, 0); + return tioce_do_dma_map(pdev, paddr, byte_count, 0, dma_flags); } /** @@ -636,9 +657,9 @@ tioce_dma(struct pci_dev *pdev, u64 padd * Simply call tioce_do_dma_map() to create a map with the barrier bit set * in the address. */ static u64 -tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count) +tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) { - return tioce_do_dma_map(pdev, paddr, byte_count, 1); + return tioce_do_dma_map(pdev, paddr, byte_count, 1, dma_flags); } /** @@ -696,7 +717,7 @@ tioce_reserve_m32(struct tioce_kernel *c while (ate_index <= last_ate) { u64 ate; - ate = ATE_MAKE(0xdeadbeef, ps); + ate = ATE_MAKE(0xdeadbeef, ps, 0); ce_kern->ce_ate3240_shadow[ate_index] = ate; tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index], ate); @@ -1002,7 +1023,7 @@ tioce_bus_fixup(struct pcibus_bussoft *p tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_int_status_alias, ~0ULL); tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_error_summary_alias, ~0ULL); - tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, ~0ULL); + tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, 0ULL); if (request_irq(SGI_PCIASIC_ERROR, tioce_error_intr_handler, diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c index b7bd84c..8f2e058 100644 --- a/arch/m68k/amiga/amiga_ksyms.c +++ b/arch/m68k/amiga/amiga_ksyms.c @@ -23,8 +23,6 @@ EXPORT_SYMBOL(amiga_chip_avail); EXPORT_SYMBOL(amiga_chip_size); EXPORT_SYMBOL(amiga_audio_period); EXPORT_SYMBOL(amiga_audio_min_period); -EXPORT_SYMBOL(amiga_do_irq); -EXPORT_SYMBOL(amiga_do_irq_list); #ifdef CONFIG_AMIGA_PCMCIA EXPORT_SYMBOL(pcmcia_reset); diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index b0aa61b..f9403f4 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -35,61 +35,30 @@ * /Jes */ -#include -#include -#include -#include #include +#include #include -#include -#include #include #include #include #include #include -extern int cia_request_irq(struct ciabase *base,int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id); -extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id); -extern void cia_init_IRQ(struct ciabase *base); -extern int cia_get_irq_list(struct ciabase *base, struct seq_file *p); - -/* irq node variables for amiga interrupt sources */ -static irq_node_t *ami_irq_list[AMI_STD_IRQS]; - -static unsigned short amiga_intena_vals[AMI_STD_IRQS] = { - [IRQ_AMIGA_VERTB] = IF_VERTB, - [IRQ_AMIGA_COPPER] = IF_COPER, - [IRQ_AMIGA_AUD0] = IF_AUD0, - [IRQ_AMIGA_AUD1] = IF_AUD1, - [IRQ_AMIGA_AUD2] = IF_AUD2, - [IRQ_AMIGA_AUD3] = IF_AUD3, - [IRQ_AMIGA_BLIT] = IF_BLIT, - [IRQ_AMIGA_DSKSYN] = IF_DSKSYN, - [IRQ_AMIGA_DSKBLK] = IF_DSKBLK, - [IRQ_AMIGA_RBF] = IF_RBF, - [IRQ_AMIGA_TBE] = IF_TBE, - [IRQ_AMIGA_SOFT] = IF_SOFT, - [IRQ_AMIGA_PORTS] = IF_PORTS, - [IRQ_AMIGA_EXTER] = IF_EXTER -}; -static const unsigned char ami_servers[AMI_STD_IRQS] = { - [IRQ_AMIGA_VERTB] = 1, - [IRQ_AMIGA_PORTS] = 1, - [IRQ_AMIGA_EXTER] = 1 +static void amiga_enable_irq(unsigned int irq); +static void amiga_disable_irq(unsigned int irq); +static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp); +static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp); +static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp); +static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp); + +static struct irq_controller amiga_irq_controller = { + .name = "amiga", + .lock = SPIN_LOCK_UNLOCKED, + .enable = amiga_enable_irq, + .disable = amiga_disable_irq, }; -static short ami_ablecount[AMI_IRQS]; - -static irqreturn_t ami_badint(int irq, void *dev_id, struct pt_regs *fp) -{ - num_spurious += 1; - return IRQ_NONE; -} - /* * void amiga_init_IRQ(void) * @@ -103,23 +72,12 @@ static irqreturn_t ami_badint(int irq, v void __init amiga_init_IRQ(void) { - int i; + request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL); + request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL); + request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL); + request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL); - /* initialize handlers */ - for (i = 0; i < AMI_STD_IRQS; i++) { - if (ami_servers[i]) { - ami_irq_list[i] = NULL; - } else { - ami_irq_list[i] = new_irq_node(); - ami_irq_list[i]->handler = ami_badint; - ami_irq_list[i]->flags = 0; - ami_irq_list[i]->dev_id = NULL; - ami_irq_list[i]->devname = NULL; - ami_irq_list[i]->next = NULL; - } - } - for (i = 0; i < AMI_IRQS; i++) - ami_ablecount[i] = 0; + m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS); /* turn off PCMCIA interrupts */ if (AMIGAHW_PRESENT(PCMCIA)) @@ -134,249 +92,21 @@ void __init amiga_init_IRQ(void) cia_init_IRQ(&ciab_base); } -static inline int amiga_insert_irq(irq_node_t **list, irq_node_t *node) -{ - unsigned long flags; - irq_node_t *cur; - - if (!node->dev_id) - printk("%s: Warning: dev_id of %s is zero\n", - __FUNCTION__, node->devname); - - local_irq_save(flags); - - cur = *list; - - if (node->flags & SA_INTERRUPT) { - if (node->flags & SA_SHIRQ) - return -EBUSY; - /* - * There should never be more than one - */ - while (cur && cur->flags & SA_INTERRUPT) { - list = &cur->next; - cur = cur->next; - } - } else { - while (cur) { - list = &cur->next; - cur = cur->next; - } - } - - node->next = cur; - *list = node; - - local_irq_restore(flags); - return 0; -} - -static inline void amiga_delete_irq(irq_node_t **list, void *dev_id) -{ - unsigned long flags; - irq_node_t *node; - - local_irq_save(flags); - - for (node = *list; node; list = &node->next, node = *list) { - if (node->dev_id == dev_id) { - *list = node->next; - /* Mark it as free. */ - node->handler = NULL; - local_irq_restore(flags); - return; - } - } - local_irq_restore(flags); - printk ("%s: tried to remove invalid irq\n", __FUNCTION__); -} - -/* - * amiga_request_irq : add an interrupt service routine for a particular - * machine specific interrupt source. - * If the addition was successful, it returns 0. - */ - -int amiga_request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - irq_node_t *node; - int error = 0; - - if (irq >= AMI_IRQS) { - printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, - irq, devname); - return -ENXIO; - } - - if (irq >= IRQ_AMIGA_AUTO) - return cpu_request_irq(irq - IRQ_AMIGA_AUTO, handler, - flags, devname, dev_id); - - if (irq >= IRQ_AMIGA_CIAB) - return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, - handler, flags, devname, dev_id); - - if (irq >= IRQ_AMIGA_CIAA) - return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, - handler, flags, devname, dev_id); - - /* - * IRQ_AMIGA_PORTS & IRQ_AMIGA_EXTER defaults to shared, - * we could add a check here for the SA_SHIRQ flag but all drivers - * should be aware of sharing anyway. - */ - if (ami_servers[irq]) { - if (!(node = new_irq_node())) - return -ENOMEM; - node->handler = handler; - node->flags = flags; - node->dev_id = dev_id; - node->devname = devname; - node->next = NULL; - error = amiga_insert_irq(&ami_irq_list[irq], node); - } else { - ami_irq_list[irq]->handler = handler; - ami_irq_list[irq]->flags = flags; - ami_irq_list[irq]->dev_id = dev_id; - ami_irq_list[irq]->devname = devname; - } - - /* enable the interrupt */ - if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq]) - amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq]; - - return error; -} - -void amiga_free_irq(unsigned int irq, void *dev_id) -{ - if (irq >= AMI_IRQS) { - printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq); - return; - } - - if (irq >= IRQ_AMIGA_AUTO) - cpu_free_irq(irq - IRQ_AMIGA_AUTO, dev_id); - - if (irq >= IRQ_AMIGA_CIAB) { - cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id); - return; - } - - if (irq >= IRQ_AMIGA_CIAA) { - cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id); - return; - } - - if (ami_servers[irq]) { - amiga_delete_irq(&ami_irq_list[irq], dev_id); - /* if server list empty, disable the interrupt */ - if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS) - amiga_custom.intena = amiga_intena_vals[irq]; - } else { - if (ami_irq_list[irq]->dev_id != dev_id) - printk("%s: removing probably wrong IRQ %d from %s\n", - __FUNCTION__, irq, ami_irq_list[irq]->devname); - ami_irq_list[irq]->handler = ami_badint; - ami_irq_list[irq]->flags = 0; - ami_irq_list[irq]->dev_id = NULL; - ami_irq_list[irq]->devname = NULL; - amiga_custom.intena = amiga_intena_vals[irq]; - } -} - /* * Enable/disable a particular machine specific interrupt source. * Note that this may affect other interrupts in case of a shared interrupt. * This function should only be called for a _very_ short time to change some * internal data, that may not be changed by the interrupt at the same time. - * ami_(enable|disable)_irq calls may also be nested. */ -void amiga_enable_irq(unsigned int irq) -{ - if (irq >= AMI_IRQS) { - printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); - return; - } - - if (--ami_ablecount[irq]) - return; - - /* No action for auto-vector interrupts */ - if (irq >= IRQ_AMIGA_AUTO){ - printk("%s: Trying to enable auto-vector IRQ %i\n", - __FUNCTION__, irq - IRQ_AMIGA_AUTO); - return; - } - - if (irq >= IRQ_AMIGA_CIAB) { - cia_set_irq(&ciab_base, (1 << (irq - IRQ_AMIGA_CIAB))); - cia_able_irq(&ciab_base, CIA_ICR_SETCLR | - (1 << (irq - IRQ_AMIGA_CIAB))); - return; - } - - if (irq >= IRQ_AMIGA_CIAA) { - cia_set_irq(&ciaa_base, (1 << (irq - IRQ_AMIGA_CIAA))); - cia_able_irq(&ciaa_base, CIA_ICR_SETCLR | - (1 << (irq - IRQ_AMIGA_CIAA))); - return; - } - - /* enable the interrupt */ - amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq]; -} - -void amiga_disable_irq(unsigned int irq) -{ - if (irq >= AMI_IRQS) { - printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); - return; - } - - if (ami_ablecount[irq]++) - return; - - /* No action for auto-vector interrupts */ - if (irq >= IRQ_AMIGA_AUTO) { - printk("%s: Trying to disable auto-vector IRQ %i\n", - __FUNCTION__, irq - IRQ_AMIGA_AUTO); - return; - } - - if (irq >= IRQ_AMIGA_CIAB) { - cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB)); - return; - } - - if (irq >= IRQ_AMIGA_CIAA) { - cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA)); - return; - } - - /* disable the interrupt */ - amiga_custom.intena = amiga_intena_vals[irq]; -} - -inline void amiga_do_irq(int irq, struct pt_regs *fp) +static void amiga_enable_irq(unsigned int irq) { - kstat_cpu(0).irqs[SYS_IRQS + irq]++; - ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp); + amiga_custom.intena = IF_SETCLR | (1 << (irq - IRQ_USER)); } -void amiga_do_irq_list(int irq, struct pt_regs *fp) +static void amiga_disable_irq(unsigned int irq) { - irq_node_t *node; - - kstat_cpu(0).irqs[SYS_IRQS + irq]++; - - amiga_custom.intreq = amiga_intena_vals[irq]; - - for (node = ami_irq_list[irq]; node; node = node->next) - node->handler(irq, node->dev_id, fp); + amiga_custom.intena = 1 << (irq - IRQ_USER); } /* @@ -390,19 +120,19 @@ static irqreturn_t ami_int1(int irq, voi /* if serial transmit buffer empty, interrupt */ if (ints & IF_TBE) { amiga_custom.intreq = IF_TBE; - amiga_do_irq(IRQ_AMIGA_TBE, fp); + m68k_handle_int(IRQ_AMIGA_TBE, fp); } /* if floppy disk transfer complete, interrupt */ if (ints & IF_DSKBLK) { amiga_custom.intreq = IF_DSKBLK; - amiga_do_irq(IRQ_AMIGA_DSKBLK, fp); + m68k_handle_int(IRQ_AMIGA_DSKBLK, fp); } /* if software interrupt set, interrupt */ if (ints & IF_SOFT) { amiga_custom.intreq = IF_SOFT; - amiga_do_irq(IRQ_AMIGA_SOFT, fp); + m68k_handle_int(IRQ_AMIGA_SOFT, fp); } return IRQ_HANDLED; } @@ -414,18 +144,20 @@ static irqreturn_t ami_int3(int irq, voi /* if a blitter interrupt */ if (ints & IF_BLIT) { amiga_custom.intreq = IF_BLIT; - amiga_do_irq(IRQ_AMIGA_BLIT, fp); + m68k_handle_int(IRQ_AMIGA_BLIT, fp); } /* if a copper interrupt */ if (ints & IF_COPER) { amiga_custom.intreq = IF_COPER; - amiga_do_irq(IRQ_AMIGA_COPPER, fp); + m68k_handle_int(IRQ_AMIGA_COPPER, fp); } /* if a vertical blank interrupt */ - if (ints & IF_VERTB) - amiga_do_irq_list(IRQ_AMIGA_VERTB, fp); + if (ints & IF_VERTB) { + amiga_custom.intreq = IF_VERTB; + m68k_handle_int(IRQ_AMIGA_VERTB, fp); + } return IRQ_HANDLED; } @@ -436,25 +168,25 @@ static irqreturn_t ami_int4(int irq, voi /* if audio 0 interrupt */ if (ints & IF_AUD0) { amiga_custom.intreq = IF_AUD0; - amiga_do_irq(IRQ_AMIGA_AUD0, fp); + m68k_handle_int(IRQ_AMIGA_AUD0, fp); } /* if audio 1 interrupt */ if (ints & IF_AUD1) { amiga_custom.intreq = IF_AUD1; - amiga_do_irq(IRQ_AMIGA_AUD1, fp); + m68k_handle_int(IRQ_AMIGA_AUD1, fp); } /* if audio 2 interrupt */ if (ints & IF_AUD2) { amiga_custom.intreq = IF_AUD2; - amiga_do_irq(IRQ_AMIGA_AUD2, fp); + m68k_handle_int(IRQ_AMIGA_AUD2, fp); } /* if audio 3 interrupt */ if (ints & IF_AUD3) { amiga_custom.intreq = IF_AUD3; - amiga_do_irq(IRQ_AMIGA_AUD3, fp); + m68k_handle_int(IRQ_AMIGA_AUD3, fp); } return IRQ_HANDLED; } @@ -466,55 +198,13 @@ static irqreturn_t ami_int5(int irq, voi /* if serial receive buffer full interrupt */ if (ints & IF_RBF) { /* acknowledge of IF_RBF must be done by the serial interrupt */ - amiga_do_irq(IRQ_AMIGA_RBF, fp); + m68k_handle_int(IRQ_AMIGA_RBF, fp); } /* if a disk sync interrupt */ if (ints & IF_DSKSYN) { amiga_custom.intreq = IF_DSKSYN; - amiga_do_irq(IRQ_AMIGA_DSKSYN, fp); + m68k_handle_int(IRQ_AMIGA_DSKSYN, fp); } return IRQ_HANDLED; } - -static irqreturn_t ami_int7(int irq, void *dev_id, struct pt_regs *fp) -{ - panic ("level 7 interrupt received\n"); -} - -irqreturn_t (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { - [0] = ami_badint, - [1] = ami_int1, - [2] = ami_badint, - [3] = ami_int3, - [4] = ami_int4, - [5] = ami_int5, - [6] = ami_badint, - [7] = ami_int7 -}; - -int show_amiga_interrupts(struct seq_file *p, void *v) -{ - int i; - irq_node_t *node; - - for (i = 0; i < AMI_STD_IRQS; i++) { - if (!(node = ami_irq_list[i])) - continue; - seq_printf(p, "ami %2d: %10u ", i, - kstat_cpu(0).irqs[SYS_IRQS + i]); - do { - if (node->flags & SA_INTERRUPT) - seq_puts(p, "F "); - else - seq_puts(p, " "); - seq_printf(p, "%s\n", node->devname); - if ((node = node->next)) - seq_puts(p, " "); - } while (node); - } - - cia_get_irq_list(&ciaa_base, p); - cia_get_irq_list(&ciab_base, p); - return 0; -} diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index 9476eb9..0956e45 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c @@ -29,21 +29,18 @@ struct ciabase { unsigned short int_mask; int handler_irq, cia_irq, server_irq; char *name; - irq_handler_t irq_list[CIA_IRQS]; } ciaa_base = { .cia = &ciaa, .int_mask = IF_PORTS, - .handler_irq = IRQ_AMIGA_AUTO_2, + .handler_irq = IRQ_AMIGA_PORTS, .cia_irq = IRQ_AMIGA_CIAA, - .server_irq = IRQ_AMIGA_PORTS, - .name = "CIAA handler" + .name = "CIAA" }, ciab_base = { .cia = &ciab, .int_mask = IF_EXTER, - .handler_irq = IRQ_AMIGA_AUTO_6, + .handler_irq = IRQ_AMIGA_EXTER, .cia_irq = IRQ_AMIGA_CIAB, - .server_irq = IRQ_AMIGA_EXTER, - .name = "CIAB handler" + .name = "CIAB" }; /* @@ -66,13 +63,11 @@ unsigned char cia_set_irq(struct ciabase /* * Enable or disable CIA interrupts, return old interrupt mask, - * interrupts will only be enabled if a handler exists */ unsigned char cia_able_irq(struct ciabase *base, unsigned char mask) { - unsigned char old, tmp; - int i; + unsigned char old; old = base->icr_mask; base->icr_data |= base->cia->icr; @@ -82,99 +77,104 @@ unsigned char cia_able_irq(struct ciabas else base->icr_mask &= ~mask; base->icr_mask &= CIA_ICR_ALL; - for (i = 0, tmp = 1; i < CIA_IRQS; i++, tmp <<= 1) { - if ((tmp & base->icr_mask) && !base->irq_list[i].handler) { - base->icr_mask &= ~tmp; - base->cia->icr = tmp; - } - } if (base->icr_data & base->icr_mask) amiga_custom.intreq = IF_SETCLR | base->int_mask; return old; } -int cia_request_irq(struct ciabase *base, unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - unsigned char mask; - - base->irq_list[irq].handler = handler; - base->irq_list[irq].flags = flags; - base->irq_list[irq].dev_id = dev_id; - base->irq_list[irq].devname = devname; - - /* enable the interrupt */ - mask = 1 << irq; - cia_set_irq(base, mask); - cia_able_irq(base, CIA_ICR_SETCLR | mask); - return 0; -} - -void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id) -{ - if (base->irq_list[irq].dev_id != dev_id) - printk("%s: removing probably wrong IRQ %i from %s\n", - __FUNCTION__, base->cia_irq + irq, - base->irq_list[irq].devname); - - base->irq_list[irq].handler = NULL; - base->irq_list[irq].flags = 0; - - cia_able_irq(base, 1 << irq); -} - static irqreturn_t cia_handler(int irq, void *dev_id, struct pt_regs *fp) { struct ciabase *base = (struct ciabase *)dev_id; - int mach_irq, i; + int mach_irq; unsigned char ints; mach_irq = base->cia_irq; - irq = SYS_IRQS + mach_irq; ints = cia_set_irq(base, CIA_ICR_ALL); amiga_custom.intreq = base->int_mask; - for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) { - if (ints & 1) { - kstat_cpu(0).irqs[irq]++; - base->irq_list[i].handler(mach_irq, base->irq_list[i].dev_id, fp); - } - ints >>= 1; + for (; ints; mach_irq++, ints >>= 1) { + if (ints & 1) + m68k_handle_int(mach_irq, fp); } - amiga_do_irq_list(base->server_irq, fp); return IRQ_HANDLED; } -void __init cia_init_IRQ(struct ciabase *base) +static void cia_enable_irq(unsigned int irq) { - int i; + unsigned char mask; - /* init isr handlers */ - for (i = 0; i < CIA_IRQS; i++) { - base->irq_list[i].handler = NULL; - base->irq_list[i].flags = 0; + if (irq >= IRQ_AMIGA_CIAB) { + mask = 1 << (irq - IRQ_AMIGA_CIAB); + cia_set_irq(&ciab_base, mask); + cia_able_irq(&ciab_base, CIA_ICR_SETCLR | mask); + } else { + mask = 1 << (irq - IRQ_AMIGA_CIAA); + cia_set_irq(&ciaa_base, mask); + cia_able_irq(&ciaa_base, CIA_ICR_SETCLR | mask); } +} - /* clear any pending interrupt and turn off all interrupts */ - cia_set_irq(base, CIA_ICR_ALL); - cia_able_irq(base, CIA_ICR_ALL); +static void cia_disable_irq(unsigned int irq) +{ + if (irq >= IRQ_AMIGA_CIAB) + cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB)); + else + cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA)); +} - /* install CIA handler */ - request_irq(base->handler_irq, cia_handler, 0, base->name, base); +static struct irq_controller cia_irq_controller = { + .name = "cia", + .lock = SPIN_LOCK_UNLOCKED, + .enable = cia_enable_irq, + .disable = cia_disable_irq, +}; + +/* + * Override auto irq 2 & 6 and use them as general chain + * for external interrupts, we link the CIA interrupt sources + * into this chain. + */ - amiga_custom.intena = IF_SETCLR | base->int_mask; +static void auto_enable_irq(unsigned int irq) +{ + switch (irq) { + case IRQ_AUTO_2: + amiga_custom.intena = IF_SETCLR | IF_PORTS; + break; + case IRQ_AUTO_6: + amiga_custom.intena = IF_SETCLR | IF_EXTER; + break; + } } -int cia_get_irq_list(struct ciabase *base, struct seq_file *p) +static void auto_disable_irq(unsigned int irq) { - int i, j; - - j = base->cia_irq; - for (i = 0; i < CIA_IRQS; i++) { - seq_printf(p, "cia %2d: %10d ", j + i, - kstat_cpu(0).irqs[SYS_IRQS + j + i]); - seq_puts(p, " "); - seq_printf(p, "%s\n", base->irq_list[i].devname); + switch (irq) { + case IRQ_AUTO_2: + amiga_custom.intena = IF_PORTS; + break; + case IRQ_AUTO_6: + amiga_custom.intena = IF_EXTER; + break; } - return 0; +} + +static struct irq_controller auto_irq_controller = { + .name = "auto", + .lock = SPIN_LOCK_UNLOCKED, + .enable = auto_enable_irq, + .disable = auto_disable_irq, +}; + +void __init cia_init_IRQ(struct ciabase *base) +{ + m68k_setup_irq_controller(&cia_irq_controller, base->cia_irq, CIA_IRQS); + + /* clear any pending interrupt and turn off all interrupts */ + cia_set_irq(base, CIA_ICR_ALL); + cia_able_irq(base, CIA_ICR_ALL); + + /* override auto int and install CIA handler */ + m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1); + m68k_irq_startup(base->handler_irq); + request_irq(base->handler_irq, cia_handler, SA_SHIRQ, base->name, base); } diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index 12e3706..b5b8a41 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -87,17 +87,8 @@ extern char m68k_debug_device[]; static void amiga_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); /* amiga specific irq functions */ extern void amiga_init_IRQ (void); -extern irqreturn_t (*amiga_default_handler[]) (int, void *, struct pt_regs *); -extern int amiga_request_irq (unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, - void *dev_id); -extern void amiga_free_irq (unsigned int irq, void *dev_id); -extern void amiga_enable_irq (unsigned int); -extern void amiga_disable_irq (unsigned int); static void amiga_get_model(char *model); static int amiga_get_hardware_list(char *buffer); -extern int show_amiga_interrupts (struct seq_file *, void *); /* amiga specific timer functions */ static unsigned long amiga_gettimeoffset (void); static int a3000_hwclk (int, struct rtc_time *); @@ -392,14 +383,8 @@ void __init config_amiga(void) mach_sched_init = amiga_sched_init; mach_init_IRQ = amiga_init_IRQ; - mach_default_handler = &amiga_default_handler; - mach_request_irq = amiga_request_irq; - mach_free_irq = amiga_free_irq; - enable_irq = amiga_enable_irq; - disable_irq = amiga_disable_irq; mach_get_model = amiga_get_model; mach_get_hardware_list = amiga_get_hardware_list; - mach_get_irq_list = show_amiga_interrupts; mach_gettimeoffset = amiga_gettimeoffset; if (AMIGAHW_PRESENT(A3000_CLK)){ mach_hwclk = a3000_hwclk; diff --git a/arch/m68k/apollo/Makefile b/arch/m68k/apollo/Makefile index 39264f3..76a0579 100644 --- a/arch/m68k/apollo/Makefile +++ b/arch/m68k/apollo/Makefile @@ -2,4 +2,4 @@ # # Makefile for Linux arch/m68k/amiga source directory # -obj-y := config.o dn_ints.o dma.o +obj-y := config.o dn_ints.o diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c index d401962..99c7097 100644 --- a/arch/m68k/apollo/config.c +++ b/arch/m68k/apollo/config.c @@ -28,11 +28,6 @@ u_long apollo_model; extern void dn_sched_init(irqreturn_t (*handler)(int,void *,struct pt_regs *)); extern void dn_init_IRQ(void); -extern int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); -extern void dn_free_irq(unsigned int irq, void *dev_id); -extern void dn_enable_irq(unsigned int); -extern void dn_disable_irq(unsigned int); -extern int show_dn_interrupts(struct seq_file *, void *); extern unsigned long dn_gettimeoffset(void); extern int dn_dummy_hwclk(int, struct rtc_time *); extern int dn_dummy_set_clock_mmss(unsigned long); @@ -40,13 +35,11 @@ extern void dn_dummy_reset(void); extern void dn_dummy_waitbut(void); extern struct fb_info *dn_fb_init(long *); extern void dn_dummy_debug_init(void); -extern void dn_dummy_video_setup(char *,int *); extern irqreturn_t dn_process_int(int irq, struct pt_regs *fp); #ifdef CONFIG_HEARTBEAT static void dn_heartbeat(int on); #endif static irqreturn_t dn_timer_int(int irq,void *, struct pt_regs *); -static irqreturn_t (*sched_timer_handler)(int, void *, struct pt_regs *)=NULL; static void dn_get_model(char *model); static const char *apollo_models[] = { [APOLLO_DN3000-APOLLO_DN3000] = "DN3000 (Otter)", @@ -164,17 +157,10 @@ void config_apollo(void) { mach_sched_init=dn_sched_init; /* */ mach_init_IRQ=dn_init_IRQ; - mach_default_handler=NULL; - mach_request_irq = dn_request_irq; - mach_free_irq = dn_free_irq; - enable_irq = dn_enable_irq; - disable_irq = dn_disable_irq; - mach_get_irq_list = show_dn_interrupts; mach_gettimeoffset = dn_gettimeoffset; mach_max_dma_address = 0xffffffff; mach_hwclk = dn_dummy_hwclk; /* */ mach_set_clock_mmss = dn_dummy_set_clock_mmss; /* */ - mach_process_int = dn_process_int; mach_reset = dn_dummy_reset; /* */ #ifdef CONFIG_HEARTBEAT mach_heartbeat = dn_heartbeat; @@ -189,11 +175,13 @@ #endif } -irqreturn_t dn_timer_int(int irq, void *dev_id, struct pt_regs *fp) { +irqreturn_t dn_timer_int(int irq, void *dev_id, struct pt_regs *fp) +{ + irqreturn_t (*timer_handler)(int, void *, struct pt_regs *) = dev_id; volatile unsigned char x; - sched_timer_handler(irq,dev_id,fp); + timer_handler(irq, dev_id, fp); x=*(volatile unsigned char *)(timer+3); x=*(volatile unsigned char *)(timer+5); @@ -217,9 +205,7 @@ #if 0 printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3)); #endif - sched_timer_handler=timer_routine; - request_irq(0,dn_timer_int,0,NULL,NULL); - + request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine); } unsigned long dn_gettimeoffset(void) { diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c index a312593..9fe0780 100644 --- a/arch/m68k/apollo/dn_ints.c +++ b/arch/m68k/apollo/dn_ints.c @@ -1,125 +1,44 @@ -#include -#include -#include -#include -#include +#include -#include #include #include -#include -#include #include -#include -static irq_handler_t dn_irqs[16]; - -irqreturn_t dn_process_int(int irq, struct pt_regs *fp) +void dn_process_int(unsigned int irq, struct pt_regs *fp) { - irqreturn_t res = IRQ_NONE; - - if(dn_irqs[irq-160].handler) { - res = dn_irqs[irq-160].handler(irq,dn_irqs[irq-160].dev_id,fp); - } else { - printk("spurious irq %d occurred\n",irq); - } - - *(volatile unsigned char *)(pica)=0x20; - *(volatile unsigned char *)(picb)=0x20; - - return res; -} - -void dn_init_IRQ(void) { - - int i; - - for(i=0;i<16;i++) { - dn_irqs[i].handler=NULL; - dn_irqs[i].flags=IRQ_FLG_STD; - dn_irqs[i].dev_id=NULL; - dn_irqs[i].devname=NULL; - } - -} - -int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { - - if((irq<0) || (irq>15)) { - printk("Trying to request invalid IRQ\n"); - return -ENXIO; - } - - if(!dn_irqs[irq].handler) { - dn_irqs[irq].handler=handler; - dn_irqs[irq].flags=IRQ_FLG_STD; - dn_irqs[irq].dev_id=dev_id; - dn_irqs[irq].devname=devname; - if(irq<8) - *(volatile unsigned char *)(pica+1)&=~(1<15)) { - printk("Trying to free invalid IRQ\n"); - return ; - } - - if(irq<8) - *(volatile unsigned char *)(pica+1)|=(1< * the sr copy in the frame. */ +#if 0 #define NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES) @@ -133,13 +134,6 @@ static struct irqhandler irq_handler[NUM */ static struct irqparam irq_param[NUM_INT_SOURCES]; -/* - * Bitmap for free interrupt vector numbers - * (new vectors starting from 0x70 can be allocated by - * atari_register_vme_int()) - */ -static int free_vme_vec_bitmap; - /* check for valid int number (complex, sigh...) */ #define IS_VALID_INTNO(n) \ ((n) > 0 && \ @@ -301,6 +295,14 @@ __asm__ (__ALIGN_STR "\n" ); for (;;); } +#endif + +/* + * Bitmap for free interrupt vector numbers + * (new vectors starting from 0x70 can be allocated by + * atari_register_vme_int()) + */ +static int free_vme_vec_bitmap; /* GK: * HBL IRQ handler for Falcon. Nobody needs it :-) @@ -313,13 +315,34 @@ __ALIGN_STR "\n\t" "orw #0x200,%sp@\n\t" /* set saved ipl to 2 */ "rte"); -/* Defined in entry.S; only increments 'num_spurious' */ -asmlinkage void bad_interrupt(void); - -extern void atari_microwire_cmd( int cmd ); +extern void atari_microwire_cmd(int cmd); extern int atari_SCC_reset_done; +static int atari_startup_irq(unsigned int irq) +{ + m68k_irq_startup(irq); + atari_turnon_irq(irq); + atari_enable_irq(irq); + return 0; +} + +static void atari_shutdown_irq(unsigned int irq) +{ + atari_disable_irq(irq); + atari_turnoff_irq(irq); + m68k_irq_shutdown(irq); +} + +static struct irq_controller atari_irq_controller = { + .name = "atari", + .lock = SPIN_LOCK_UNLOCKED, + .startup = atari_startup_irq, + .shutdown = atari_shutdown_irq, + .enable = atari_enable_irq, + .disable = atari_disable_irq, +}; + /* * void atari_init_IRQ (void) * @@ -333,12 +356,8 @@ extern int atari_SCC_reset_done; void __init atari_init_IRQ(void) { - int i; - - /* initialize the vector table */ - for (i = 0; i < NUM_INT_SOURCES; ++i) { - vectors[IRQ_SOURCE_TO_VECTOR(i)] = bad_interrupt; - } + m68k_setup_user_interrupt(VEC_USER, 192, NULL); + m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1); /* Initialize the MFP(s) */ @@ -378,8 +397,7 @@ #endif * enabled in VME mask */ tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */ - } - else { + } else { /* If no SCU and no Hades, the HSYNC interrupt needs to be * disabled this way. (Else _inthandler in kernel/sys_call.S * gets overruns) @@ -404,184 +422,6 @@ #endif } -static irqreturn_t atari_call_irq_list( int irq, void *dev_id, struct pt_regs *fp ) -{ - irq_node_t *node; - - for (node = (irq_node_t *)dev_id; node; node = node->next) - node->handler(irq, node->dev_id, fp); - return IRQ_HANDLED; -} - - -/* - * atari_request_irq : add an interrupt service routine for a particular - * machine specific interrupt source. - * If the addition was successful, it returns 0. - */ - -int atari_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - int vector; - unsigned long oflags = flags; - - /* - * The following is a hack to make some PCI card drivers work, - * which set the SA_SHIRQ flag. - */ - - flags &= ~SA_SHIRQ; - - if (flags == SA_INTERRUPT) { - printk ("%s: SA_INTERRUPT changed to IRQ_TYPE_SLOW for %s\n", - __FUNCTION__, devname); - flags = IRQ_TYPE_SLOW; - } - if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) { - printk ("%s: Bad irq type 0x%lx <0x%lx> requested from %s\n", - __FUNCTION__, flags, oflags, devname); - return -EINVAL; - } - if (!IS_VALID_INTNO(irq)) { - printk ("%s: Unknown irq %d requested from %s\n", - __FUNCTION__, irq, devname); - return -ENXIO; - } - vector = IRQ_SOURCE_TO_VECTOR(irq); - - /* - * Check type/source combination: slow ints are (currently) - * only possible for MFP-interrupts. - */ - if (flags == IRQ_TYPE_SLOW && - (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE)) { - printk ("%s: Slow irq requested for non-MFP source %d from %s\n", - __FUNCTION__, irq, devname); - return -EINVAL; - } - - if (vectors[vector] == bad_interrupt) { - /* int has no handler yet */ - irq_handler[irq].handler = handler; - irq_handler[irq].dev_id = dev_id; - irq_param[irq].flags = flags; - irq_param[irq].devname = devname; - vectors[vector] = - (flags == IRQ_TYPE_SLOW) ? slow_handlers[irq-STMFP_SOURCE_BASE] : - (flags == IRQ_TYPE_FAST) ? atari_fast_irq_handler : - atari_prio_irq_handler; - /* If MFP int, also enable and umask it */ - atari_turnon_irq(irq); - atari_enable_irq(irq); - - return 0; - } - else if (irq_param[irq].flags == flags) { - /* old handler is of same type -> handlers can be chained */ - irq_node_t *node; - unsigned long flags; - - local_irq_save(flags); - - if (irq_handler[irq].handler != atari_call_irq_list) { - /* Only one handler yet, make a node for this first one */ - if (!(node = new_irq_node())) - return -ENOMEM; - node->handler = irq_handler[irq].handler; - node->dev_id = irq_handler[irq].dev_id; - node->devname = irq_param[irq].devname; - node->next = NULL; - - irq_handler[irq].handler = atari_call_irq_list; - irq_handler[irq].dev_id = node; - irq_param[irq].devname = "chained"; - } - - if (!(node = new_irq_node())) - return -ENOMEM; - node->handler = handler; - node->dev_id = dev_id; - node->devname = devname; - /* new handlers are put in front of the queue */ - node->next = irq_handler[irq].dev_id; - irq_handler[irq].dev_id = node; - - local_irq_restore(flags); - return 0; - } else { - printk ("%s: Irq %d allocated by other type int (call from %s)\n", - __FUNCTION__, irq, devname); - return -EBUSY; - } -} - -void atari_free_irq(unsigned int irq, void *dev_id) -{ - unsigned long flags; - int vector; - irq_node_t **list, *node; - - if (!IS_VALID_INTNO(irq)) { - printk("%s: Unknown irq %d\n", __FUNCTION__, irq); - return; - } - - vector = IRQ_SOURCE_TO_VECTOR(irq); - if (vectors[vector] == bad_interrupt) - goto not_found; - - local_irq_save(flags); - - if (irq_handler[irq].handler != atari_call_irq_list) { - /* It's the only handler for the interrupt */ - if (irq_handler[irq].dev_id != dev_id) { - local_irq_restore(flags); - goto not_found; - } - irq_handler[irq].handler = NULL; - irq_handler[irq].dev_id = NULL; - irq_param[irq].devname = NULL; - vectors[vector] = bad_interrupt; - /* If MFP int, also disable it */ - atari_disable_irq(irq); - atari_turnoff_irq(irq); - - local_irq_restore(flags); - return; - } - - /* The interrupt is chained, find the irq on the list */ - for(list = (irq_node_t **)&irq_handler[irq].dev_id; *list; list = &(*list)->next) { - if ((*list)->dev_id == dev_id) break; - } - if (!*list) { - local_irq_restore(flags); - goto not_found; - } - - (*list)->handler = NULL; /* Mark it as free for reallocation */ - *list = (*list)->next; - - /* If there's now only one handler, unchain the interrupt, i.e. plug in - * the handler directly again and omit atari_call_irq_list */ - node = (irq_node_t *)irq_handler[irq].dev_id; - if (node && !node->next) { - irq_handler[irq].handler = node->handler; - irq_handler[irq].dev_id = node->dev_id; - irq_param[irq].devname = node->devname; - node->handler = NULL; /* Mark it as free for reallocation */ - } - - local_irq_restore(flags); - return; - -not_found: - printk("%s: tried to remove invalid irq\n", __FUNCTION__); - return; -} - - /* * atari_register_vme_int() returns the number of a free interrupt vector for * hardware with a programmable int vector (probably a VME board). @@ -591,58 +431,24 @@ unsigned long atari_register_vme_int(voi { int i; - for(i = 0; i < 32; i++) - if((free_vme_vec_bitmap & (1 << i)) == 0) + for (i = 0; i < 32; i++) + if ((free_vme_vec_bitmap & (1 << i)) == 0) break; - if(i == 16) + if (i == 16) return 0; free_vme_vec_bitmap |= 1 << i; - return (VME_SOURCE_BASE + i); + return VME_SOURCE_BASE + i; } void atari_unregister_vme_int(unsigned long irq) { - if(irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) { + if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) { irq -= VME_SOURCE_BASE; free_vme_vec_bitmap &= ~(1 << irq); } } -int show_atari_interrupts(struct seq_file *p, void *v) -{ - int i; - - for (i = 0; i < NUM_INT_SOURCES; ++i) { - if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt) - continue; - if (i < STMFP_SOURCE_BASE) - seq_printf(p, "auto %2d: %10u ", - i, kstat_cpu(0).irqs[i]); - else - seq_printf(p, "vec $%02x: %10u ", - IRQ_SOURCE_TO_VECTOR(i), - kstat_cpu(0).irqs[i]); - - if (irq_handler[i].handler != atari_call_irq_list) { - seq_printf(p, "%s\n", irq_param[i].devname); - } - else { - irq_node_t *n; - for( n = (irq_node_t *)irq_handler[i].dev_id; n; n = n->next ) { - seq_printf(p, "%s\n", n->devname); - if (n->next) - seq_puts(p, " " ); - } - } - } - if (num_spurious) - seq_printf(p, "spurio.: %10u\n", num_spurious); - - return 0; -} - - diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c index 1012b08..727289a 100644 --- a/arch/m68k/atari/config.c +++ b/arch/m68k/atari/config.c @@ -57,12 +57,6 @@ static int atari_get_hardware_list(char /* atari specific irq functions */ extern void atari_init_IRQ (void); -extern int atari_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id); -extern void atari_free_irq (unsigned int irq, void *dev_id); -extern void atari_enable_irq (unsigned int); -extern void atari_disable_irq (unsigned int); -extern int show_atari_interrupts (struct seq_file *, void *); extern void atari_mksound( unsigned int count, unsigned int ticks ); #ifdef CONFIG_HEARTBEAT static void atari_heartbeat( int on ); @@ -232,13 +226,8 @@ void __init config_atari(void) mach_sched_init = atari_sched_init; mach_init_IRQ = atari_init_IRQ; - mach_request_irq = atari_request_irq; - mach_free_irq = atari_free_irq; - enable_irq = atari_enable_irq; - disable_irq = atari_disable_irq; mach_get_model = atari_get_model; mach_get_hardware_list = atari_get_hardware_list; - mach_get_irq_list = show_atari_interrupts; mach_gettimeoffset = atari_gettimeoffset; mach_reset = atari_reset; mach_max_dma_address = 0xffffff; diff --git a/arch/m68k/bvme6000/Makefile b/arch/m68k/bvme6000/Makefile index 2348e6c..d817400 100644 --- a/arch/m68k/bvme6000/Makefile +++ b/arch/m68k/bvme6000/Makefile @@ -2,4 +2,4 @@ # # Makefile for Linux arch/m68k/bvme6000 source directory # -obj-y := config.o bvmeints.o rtc.o +obj-y := config.o rtc.o diff --git a/arch/m68k/bvme6000/bvmeints.c b/arch/m68k/bvme6000/bvmeints.c deleted file mode 100644 index 298a8df..0000000 --- a/arch/m68k/bvme6000/bvmeints.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * arch/m68k/bvme6000/bvmeints.c - * - * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk] - * - * based on amiints.c -- Amiga Linux interrupt handling code - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file README.legal in the main directory of this archive - * for more details. - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp); - -/* - * This should ideally be 4 elements only, for speed. - */ - -static struct { - irqreturn_t (*handler)(int, void *, struct pt_regs *); - unsigned long flags; - void *dev_id; - const char *devname; - unsigned count; -} irq_tab[256]; - -/* - * void bvme6000_init_IRQ (void) - * - * Parameters: None - * - * Returns: Nothing - * - * This function is called during kernel startup to initialize - * the bvme6000 IRQ handling routines. - */ - -void bvme6000_init_IRQ (void) -{ - int i; - - for (i = 0; i < 256; i++) { - irq_tab[i].handler = bvme6000_defhand; - irq_tab[i].flags = IRQ_FLG_STD; - irq_tab[i].dev_id = NULL; - irq_tab[i].devname = NULL; - irq_tab[i].count = 0; - } -} - -int bvme6000_request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - if (irq > 255) { - printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); - return -ENXIO; - } -#if 0 - /* Nothing special about auto-vectored devices for the BVME6000, - * but treat it specially to avoid changes elsewhere. - */ - - if (irq >= VEC_INT1 && irq <= VEC_INT7) - return cpu_request_irq(irq - VEC_SPUR, handler, flags, - devname, dev_id); -#endif - if (!(irq_tab[irq].flags & IRQ_FLG_STD)) { - if (irq_tab[irq].flags & IRQ_FLG_LOCK) { - printk("%s: IRQ %d from %s is not replaceable\n", - __FUNCTION__, irq, irq_tab[irq].devname); - return -EBUSY; - } - if (flags & IRQ_FLG_REPLACE) { - printk("%s: %s can't replace IRQ %d from %s\n", - __FUNCTION__, devname, irq, irq_tab[irq].devname); - return -EBUSY; - } - } - irq_tab[irq].handler = handler; - irq_tab[irq].flags = flags; - irq_tab[irq].dev_id = dev_id; - irq_tab[irq].devname = devname; - return 0; -} - -void bvme6000_free_irq(unsigned int irq, void *dev_id) -{ - if (irq > 255) { - printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); - return; - } -#if 0 - if (irq >= VEC_INT1 && irq <= VEC_INT7) { - cpu_free_irq(irq - VEC_SPUR, dev_id); - return; - } -#endif - if (irq_tab[irq].dev_id != dev_id) - printk("%s: Removing probably wrong IRQ %d from %s\n", - __FUNCTION__, irq, irq_tab[irq].devname); - - irq_tab[irq].handler = bvme6000_defhand; - irq_tab[irq].flags = IRQ_FLG_STD; - irq_tab[irq].dev_id = NULL; - irq_tab[irq].devname = NULL; -} - -irqreturn_t bvme6000_process_int (unsigned long vec, struct pt_regs *fp) -{ - if (vec > 255) { - printk ("bvme6000_process_int: Illegal vector %ld", vec); - return IRQ_NONE; - } else { - irq_tab[vec].count++; - irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp); - return IRQ_HANDLED; - } -} - -int show_bvme6000_interrupts(struct seq_file *p, void *v) -{ - int i; - - for (i = 0; i < 256; i++) { - if (irq_tab[i].count) - seq_printf(p, "Vec 0x%02x: %8d %s\n", - i, irq_tab[i].count, - irq_tab[i].devname ? irq_tab[i].devname : "free"); - } - return 0; -} - - -static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp) -{ - printk ("Unknown interrupt 0x%02x\n", irq); - return IRQ_NONE; -} - -void bvme6000_enable_irq (unsigned int irq) -{ -} - - -void bvme6000_disable_irq (unsigned int irq) -{ -} - diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c index c90cb5f..d1e916a 100644 --- a/arch/m68k/bvme6000/config.c +++ b/arch/m68k/bvme6000/config.c @@ -36,15 +36,8 @@ #include #include #include -extern irqreturn_t bvme6000_process_int (int level, struct pt_regs *regs); -extern void bvme6000_init_IRQ (void); -extern void bvme6000_free_irq (unsigned int, void *); -extern int show_bvme6000_interrupts(struct seq_file *, void *); -extern void bvme6000_enable_irq (unsigned int); -extern void bvme6000_disable_irq (unsigned int); static void bvme6000_get_model(char *model); static int bvme6000_get_hardware_list(char *buffer); -extern int bvme6000_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); extern void bvme6000_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); extern unsigned long bvme6000_gettimeoffset (void); extern int bvme6000_hwclk (int, struct rtc_time *); @@ -100,6 +93,14 @@ static int bvme6000_get_hardware_list(ch return 0; } +/* + * This function is called during kernel startup to initialize + * the bvme6000 IRQ handling routines. + */ +static void bvme6000_init_IRQ(void) +{ + m68k_setup_user_interrupt(VEC_USER, 192, NULL); +} void __init config_bvme6000(void) { @@ -127,12 +128,6 @@ #endif mach_hwclk = bvme6000_hwclk; mach_set_clock_mmss = bvme6000_set_clock_mmss; mach_reset = bvme6000_reset; - mach_free_irq = bvme6000_free_irq; - mach_process_int = bvme6000_process_int; - mach_get_irq_list = show_bvme6000_interrupts; - mach_request_irq = bvme6000_request_irq; - enable_irq = bvme6000_enable_irq; - disable_irq = bvme6000_disable_irq; mach_get_model = bvme6000_get_model; mach_get_hardware_list = bvme6000_get_hardware_list; diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile index 89b6317..288b9c6 100644 --- a/arch/m68k/hp300/Makefile +++ b/arch/m68k/hp300/Makefile @@ -2,4 +2,4 @@ # # Makefile for Linux arch/m68k/hp300 source directory # -obj-y := ksyms.o config.o ints.o time.o reboot.o +obj-y := ksyms.o config.o time.o reboot.o diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c index 6d129ee..2ef271c 100644 --- a/arch/m68k/hp300/config.c +++ b/arch/m68k/hp300/config.c @@ -21,7 +21,6 @@ #include #include #include -#include "ints.h" #include "time.h" unsigned long hp300_model; @@ -64,8 +63,6 @@ static char *hp300_models[] __initdata = static char hp300_model_name[13] = "HP9000/"; extern void hp300_reset(void); -extern irqreturn_t (*hp300_default_handler[])(int, void *, struct pt_regs *); -extern int show_hp300_interrupts(struct seq_file *, void *); #ifdef CONFIG_SERIAL_8250_CONSOLE extern int hp300_setup_serial_console(void) __init; #endif @@ -245,16 +242,16 @@ static unsigned int hp300_get_ss(void) hp300_rtc_read(RTC_REG_SEC2); } +static void __init hp300_init_IRQ(void) +{ +} + void __init config_hp300(void) { mach_sched_init = hp300_sched_init; mach_init_IRQ = hp300_init_IRQ; - mach_request_irq = hp300_request_irq; - mach_free_irq = hp300_free_irq; mach_get_model = hp300_get_model; - mach_get_irq_list = show_hp300_interrupts; mach_gettimeoffset = hp300_gettimeoffset; - mach_default_handler = &hp300_default_handler; mach_hwclk = hp300_hwclk; mach_get_ss = hp300_get_ss; mach_reset = hp300_reset; diff --git a/arch/m68k/hp300/ints.c b/arch/m68k/hp300/ints.c deleted file mode 100644 index 0c5bb40..0000000 --- a/arch/m68k/hp300/ints.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * linux/arch/m68k/hp300/ints.c - * - * Copyright (C) 1998 Philip Blundell - * - * This file contains the HP300-specific interrupt handling. - * We only use the autovector interrupts, and therefore we need to - * maintain lists of devices sharing each ipl. - * [ipl list code added by Peter Maydell 06/1998] - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ints.h" - -/* Each ipl has a linked list of interrupt service routines. - * Service routines are added via hp300_request_irq() and removed - * via hp300_free_irq(). The device driver should set IRQ_FLG_FAST - * if it needs to be serviced early (eg FIFOless UARTs); this will - * cause it to be added at the front of the queue rather than - * the back. - * Currently IRQ_FLG_SLOW and flags=0 are treated identically; if - * we needed three levels of priority we could distinguish them - * but this strikes me as mildly ugly... - */ - -/* we start with no entries in any list */ -static irq_node_t *hp300_irq_list[HP300_NUM_IRQS]; - -static spinlock_t irqlist_lock; - -/* This handler receives all interrupts, dispatching them to the registered handlers */ -static irqreturn_t hp300_int_handler(int irq, void *dev_id, struct pt_regs *fp) -{ - irq_node_t *t; - /* We just give every handler on the chain an opportunity to handle - * the interrupt, in priority order. - */ - for(t = hp300_irq_list[irq]; t; t=t->next) - t->handler(irq, t->dev_id, fp); - /* We could put in some accounting routines, checks for stray interrupts, - * etc, in here. Note that currently we can't tell whether or not - * a handler handles the interrupt, though. - */ - return IRQ_HANDLED; -} - -static irqreturn_t hp300_badint(int irq, void *dev_id, struct pt_regs *fp) -{ - num_spurious += 1; - return IRQ_NONE; -} - -irqreturn_t (*hp300_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { - [0] = hp300_badint, - [1] = hp300_int_handler, - [2] = hp300_int_handler, - [3] = hp300_int_handler, - [4] = hp300_int_handler, - [5] = hp300_int_handler, - [6] = hp300_int_handler, - [7] = hp300_int_handler -}; - -/* dev_id had better be unique to each handler because it's the only way we have - * to distinguish handlers when removing them... - * - * It would be pretty easy to support IRQ_FLG_LOCK (handler is not replacable) - * and IRQ_FLG_REPLACE (handler replaces existing one with this dev_id) - * if we wanted to. IRQ_FLG_FAST is needed for devices where interrupt latency - * matters (eg the dreaded FIFOless UART...) - */ -int hp300_request_irq(unsigned int irq, - irqreturn_t (*handler) (int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - irq_node_t *t, *n = new_irq_node(); - - if (!n) /* oops, no free nodes */ - return -ENOMEM; - - spin_lock_irqsave(&irqlist_lock, flags); - - if (!hp300_irq_list[irq]) { - /* no list yet */ - hp300_irq_list[irq] = n; - n->next = NULL; - } else if (flags & IRQ_FLG_FAST) { - /* insert at head of list */ - n->next = hp300_irq_list[irq]; - hp300_irq_list[irq] = n; - } else { - /* insert at end of list */ - for(t = hp300_irq_list[irq]; t->next; t = t->next) - /* do nothing */; - n->next = NULL; - t->next = n; - } - - /* Fill in n appropriately */ - n->handler = handler; - n->flags = flags; - n->dev_id = dev_id; - n->devname = devname; - spin_unlock_irqrestore(&irqlist_lock, flags); - return 0; -} - -void hp300_free_irq(unsigned int irq, void *dev_id) -{ - irq_node_t *t; - unsigned long flags; - - spin_lock_irqsave(&irqlist_lock, flags); - - t = hp300_irq_list[irq]; - if (!t) /* no handlers at all for that IRQ */ - { - printk(KERN_ERR "hp300_free_irq: attempt to remove nonexistent handler for IRQ %d\n", irq); - spin_unlock_irqrestore(&irqlist_lock, flags); - return; - } - - if (t->dev_id == dev_id) - { /* removing first handler on chain */ - t->flags = IRQ_FLG_STD; /* we probably don't really need these */ - t->dev_id = NULL; - t->devname = NULL; - t->handler = NULL; /* frees this irq_node_t */ - hp300_irq_list[irq] = t->next; - spin_unlock_irqrestore(&irqlist_lock, flags); - return; - } - - /* OK, must be removing from middle of the chain */ - - for (t = hp300_irq_list[irq]; t->next && t->next->dev_id != dev_id; t = t->next) - /* do nothing */; - if (!t->next) - { - printk(KERN_ERR "hp300_free_irq: attempt to remove nonexistent handler for IRQ %d\n", irq); - spin_unlock_irqrestore(&irqlist_lock, flags); - return; - } - /* remove the entry after t: */ - t->next->flags = IRQ_FLG_STD; - t->next->dev_id = NULL; - t->next->devname = NULL; - t->next->handler = NULL; - t->next = t->next->next; - - spin_unlock_irqrestore(&irqlist_lock, flags); -} - -int show_hp300_interrupts(struct seq_file *p, void *v) -{ - return 0; -} - -void __init hp300_init_IRQ(void) -{ - spin_lock_init(&irqlist_lock); -} diff --git a/arch/m68k/hp300/ints.h b/arch/m68k/hp300/ints.h deleted file mode 100644 index 8cfabe2..0000000 --- a/arch/m68k/hp300/ints.h +++ /dev/null @@ -1,9 +0,0 @@ -extern void hp300_init_IRQ(void); -extern void (*hp300_handlers[8])(int, void *, struct pt_regs *); -extern void hp300_free_irq(unsigned int irq, void *dev_id); -extern int hp300_request_irq(unsigned int irq, - irqreturn_t (*handler) (int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id); - -/* number of interrupts, includes 0 (what's that?) */ -#define HP300_NUM_IRQS 8 diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c index 8da5b1b..7df0566 100644 --- a/arch/m68k/hp300/time.c +++ b/arch/m68k/hp300/time.c @@ -18,7 +18,6 @@ #include #include #include #include -#include "ints.h" /* Clock hardware definitions */ @@ -71,7 +70,7 @@ void __init hp300_sched_init(irqreturn_t asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE)); - cpu_request_irq(6, hp300_tick, IRQ_FLG_STD, "timer tick", vector); + request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector); out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */ out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */ diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index 458925c..dae6097 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -9,8 +9,8 @@ else endif extra-y += vmlinux.lds -obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \ - sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o +obj-y := entry.o process.o traps.o ints.o dma.o signal.o ptrace.o \ + sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o obj-$(CONFIG_PCI) += bios32.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c new file mode 100644 index 0000000..fc449f8 --- /dev/null +++ b/arch/m68k/kernel/dma.c @@ -0,0 +1,129 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#undef DEBUG + +#include +#include +#include +#include + +#include +#include + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *handle, int flag) +{ + struct page *page, **map; + pgprot_t pgprot; + void *addr; + int i, order; + + pr_debug("dma_alloc_coherent: %d,%x\n", size, flag); + + size = PAGE_ALIGN(size); + order = get_order(size); + + page = alloc_pages(flag, order); + if (!page) + return NULL; + + *handle = page_to_phys(page); + map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA); + if (!map) { + __free_pages(page, order); + return NULL; + } + split_page(page, order); + + order = 1 << order; + size >>= PAGE_SHIFT; + map[0] = page; + for (i = 1; i < size; i++) + map[i] = page + i; + for (; i < order; i++) + __free_page(page + i); + pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY); + if (CPU_IS_040_OR_060) + pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S; + else + pgprot_val(pgprot) |= _PAGE_NOCACHE030; + addr = vmap(map, size, flag, pgprot); + kfree(map); + + return addr; +} +EXPORT_SYMBOL(dma_alloc_coherent); + +void dma_free_coherent(struct device *dev, size_t size, + void *addr, dma_addr_t handle) +{ + pr_debug("dma_free_coherent: %p, %x\n", addr, handle); + vfree(addr); +} +EXPORT_SYMBOL(dma_free_coherent); + +inline void dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size, + enum dma_data_direction dir) +{ + switch (dir) { + case DMA_TO_DEVICE: + cache_push(handle, size); + break; + case DMA_FROM_DEVICE: + cache_clear(handle, size); + break; + default: + if (printk_ratelimit()) + printk("dma_sync_single_for_device: unsupported dir %u\n", dir); + break; + } +} +EXPORT_SYMBOL(dma_sync_single_for_device); + +void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir) +{ + int i; + + for (i = 0; i < nents; sg++, i++) + dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); +} +EXPORT_SYMBOL(dma_sync_sg_for_device); + +dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, + enum dma_data_direction dir) +{ + dma_addr_t handle = virt_to_bus(addr); + + dma_sync_single_for_device(dev, handle, size, dir); + return handle; +} +EXPORT_SYMBOL(dma_map_single); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction dir) +{ + dma_addr_t handle = page_to_phys(page) + offset; + + dma_sync_single_for_device(dev, handle, size, dir); + return handle; +} +EXPORT_SYMBOL(dma_map_page); + +int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir) +{ + int i; + + for (i = 0; i < nents; sg++, i++) { + sg->dma_address = page_to_phys(sg->page) + sg->offset; + dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); + } + return nents; +} +EXPORT_SYMBOL(dma_map_sg); diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 320fde0..449b62b 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -45,9 +45,11 @@ #include #include .globl system_call, buserr, trap, resume -.globl inthandler, sys_call_table +.globl sys_call_table .globl sys_fork, sys_clone, sys_vfork .globl ret_from_interrupt, bad_interrupt +.globl auto_irqhandler_fixup +.globl user_irqvec_fixup, user_irqhandler_fixup .text ENTRY(buserr) @@ -191,65 +193,29 @@ do_delayed_trace: jbra resume_userspace -#if 0 -#ifdef CONFIG_AMIGA -ami_inthandler: - addql #1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT - SAVE_ALL_INT - GET_CURRENT(%d0) +/* This is the main interrupt handler for autovector interrupts */ - bfextu %sp@(PT_VECTOR){#4,#12},%d0 - movel %d0,%a0 - addql #1,%a0@(kstat+STAT_IRQ-VECOFF(VEC_SPUR)) - movel %a0@(autoirq_list-VECOFF(VEC_SPUR)),%a0 - -| amiga vector int handler get the req mask instead of irq vector - lea CUSTOMBASE,%a1 - movew %a1@(C_INTREQR),%d0 - andw %a1@(C_INTENAR),%d0 - -| prepare stack (push frame pointer, dev_id & req mask) - pea %sp@ - movel %a0@(IRQ_DEVID),%sp@- - movel %d0,%sp@- - pea %pc@(ret_from_interrupt:w) - jbra @(IRQ_HANDLER,%a0)@(0) - -ENTRY(nmi_handler) - rte -#endif -#endif - -/* -** This is the main interrupt handler, responsible for calling process_int() -*/ -inthandler: +ENTRY(auto_inthandler) SAVE_ALL_INT GET_CURRENT(%d0) - addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) | put exception # in d0 - bfextu %sp@(PT_VECTOR){#4,#10},%d0 + bfextu %sp@(PT_VECTOR){#4,#10},%d0 + subw #VEC_SPUR,%d0 movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack -#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD) - btstb #4,0xff000000 | Q40 floppy needs very special treatment ... - jbeq 1f - btstb #3,0xff000004 - jbeq 1f - jbsr floppy_hardint - jbra 3f -1: -#endif - jbsr process_int | process the IRQ -3: addql #8,%sp | pop parameters off stack +auto_irqhandler_fixup = . + 2 + jsr m68k_handle_int | process the IRQ + addql #8,%sp | pop parameters off stack ret_from_interrupt: - subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) - jeq 1f -2: - RESTORE_ALL -1: + subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + jeq ret_from_last_interrupt +2: RESTORE_ALL + + ALIGN +ret_from_last_interrupt: moveq #(~ALLOWINT>>8)&0xff,%d0 andb %sp@(PT_SR),%d0 jne 2b @@ -260,12 +226,42 @@ ret_from_interrupt: pea ret_from_exception jra do_softirq +/* Handler for user defined interrupt vectors */ + +ENTRY(user_inthandler) + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + | put exception # in d0 + bfextu %sp@(PT_VECTOR){#4,#10},%d0 +user_irqvec_fixup = . + 2 + subw #VEC_USER,%d0 + + movel %sp,%sp@- + movel %d0,%sp@- | put vector # on stack +user_irqhandler_fixup = . + 2 + jsr m68k_handle_int | process the IRQ + addql #8,%sp | pop parameters off stack + + subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + jeq ret_from_last_interrupt + RESTORE_ALL /* Handler for uninitialized and spurious interrupts */ -bad_interrupt: - addql #1,num_spurious - rte +ENTRY(bad_inthandler) + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + + movel %sp,%sp@- + jsr handle_badint + addql #4,%sp + + subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + jeq ret_from_last_interrupt + RESTORE_ALL + ENTRY(sys_fork) SAVE_SWITCH_STACK diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 514d323..5a8344b 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -39,47 +39,40 @@ #include #include #include #include +#include #ifdef CONFIG_Q40 #include #endif +extern u32 auto_irqhandler_fixup[]; +extern u32 user_irqhandler_fixup[]; +extern u16 user_irqvec_fixup[]; + /* table for system interrupt handlers */ -static irq_handler_t irq_list[SYS_IRQS]; - -static const char *default_names[SYS_IRQS] = { - [0] = "spurious int", - [1] = "int1 handler", - [2] = "int2 handler", - [3] = "int3 handler", - [4] = "int4 handler", - [5] = "int5 handler", - [6] = "int6 handler", - [7] = "int7 handler" +static struct irq_node *irq_list[NR_IRQS]; +static struct irq_controller *irq_controller[NR_IRQS]; +static int irq_depth[NR_IRQS]; + +static int m68k_first_user_vec; + +static struct irq_controller auto_irq_controller = { + .name = "auto", + .lock = SPIN_LOCK_UNLOCKED, + .startup = m68k_irq_startup, + .shutdown = m68k_irq_shutdown, }; -/* The number of spurious interrupts */ -volatile unsigned int num_spurious; +static struct irq_controller user_irq_controller = { + .name = "user", + .lock = SPIN_LOCK_UNLOCKED, + .startup = m68k_irq_startup, + .shutdown = m68k_irq_shutdown, +}; #define NUM_IRQ_NODES 100 static irq_node_t nodes[NUM_IRQ_NODES]; -static void dummy_enable_irq(unsigned int irq); -static void dummy_disable_irq(unsigned int irq); -static int dummy_request_irq(unsigned int irq, - irqreturn_t (*handler) (int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id); -static void dummy_free_irq(unsigned int irq, void *dev_id); - -void (*enable_irq) (unsigned int) = dummy_enable_irq; -void (*disable_irq) (unsigned int) = dummy_disable_irq; - -int (*mach_request_irq) (unsigned int, irqreturn_t (*)(int, void *, struct pt_regs *), - unsigned long, const char *, void *) = dummy_request_irq; -void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq; - -void init_irq_proc(void); - /* * void init_IRQ(void) * @@ -95,18 +88,76 @@ void __init init_IRQ(void) { int i; - for (i = 0; i < SYS_IRQS; i++) { - if (mach_default_handler) - irq_list[i].handler = (*mach_default_handler)[i]; - irq_list[i].flags = 0; - irq_list[i].dev_id = NULL; - irq_list[i].devname = default_names[i]; + /* assembly irq entry code relies on this... */ + if (HARDIRQ_MASK != 0x00ff0000) { + extern void hardirq_mask_is_broken(void); + hardirq_mask_is_broken(); } - for (i = 0; i < NUM_IRQ_NODES; i++) - nodes[i].handler = NULL; + for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) + irq_controller[i] = &auto_irq_controller; + + mach_init_IRQ(); +} + +/** + * m68k_setup_auto_interrupt + * @handler: called from auto vector interrupts + * + * setup the handler to be called from auto vector interrupts instead of the + * standard m68k_handle_int(), it will be called with irq numbers in the range + * from IRQ_AUTO_1 - IRQ_AUTO_7. + */ +void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)) +{ + if (handler) + *auto_irqhandler_fixup = (u32)handler; + flush_icache(); +} + +/** + * m68k_setup_user_interrupt + * @vec: first user vector interrupt to handle + * @cnt: number of active user vector interrupts + * @handler: called from user vector interrupts + * + * setup user vector interrupts, this includes activating the specified range + * of interrupts, only then these interrupts can be requested (note: this is + * different from auto vector interrupts). An optional handler can be installed + * to be called instead of the default m68k_handle_int(), it will be called + * with irq numbers starting from IRQ_USER. + */ +void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, + void (*handler)(unsigned int, struct pt_regs *)) +{ + int i; + + m68k_first_user_vec = vec; + for (i = 0; i < cnt; i++) + irq_controller[IRQ_USER + i] = &user_irq_controller; + *user_irqvec_fixup = vec - IRQ_USER; + if (handler) + *user_irqhandler_fixup = (u32)handler; + flush_icache(); +} + +/** + * m68k_setup_irq_controller + * @contr: irq controller which controls specified irq + * @irq: first irq to be managed by the controller + * + * Change the controller for the specified range of irq, which will be used to + * manage these irq. auto/user irq already have a default controller, which can + * be changed as well, but the controller probably should use m68k_irq_startup/ + * m68k_irq_shutdown. + */ +void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq, + unsigned int cnt) +{ + int i; - mach_init_IRQ (); + for (i = 0; i < cnt; i++) + irq_controller[irq + i] = contr; } irq_node_t *new_irq_node(void) @@ -114,84 +165,183 @@ irq_node_t *new_irq_node(void) irq_node_t *node; short i; - for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) - if (!node->handler) + for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) { + if (!node->handler) { + memset(node, 0, sizeof(*node)); return node; + } + } printk ("new_irq_node: out of nodes\n"); return NULL; } -/* - * We will keep these functions until I have convinced Linus to move - * the declaration of them from include/linux/sched.h to - * include/asm/irq.h. - */ +int setup_irq(unsigned int irq, struct irq_node *node) +{ + struct irq_controller *contr; + struct irq_node **prev; + unsigned long flags; + + if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + printk("%s: Incorrect IRQ %d from %s\n", + __FUNCTION__, irq, node->devname); + return -ENXIO; + } + + spin_lock_irqsave(&contr->lock, flags); + + prev = irq_list + irq; + if (*prev) { + /* Can't share interrupts unless both agree to */ + if (!((*prev)->flags & node->flags & SA_SHIRQ)) { + spin_unlock_irqrestore(&contr->lock, flags); + return -EBUSY; + } + while (*prev) + prev = &(*prev)->next; + } + + if (!irq_list[irq]) { + if (contr->startup) + contr->startup(irq); + else + contr->enable(irq); + } + node->next = NULL; + *prev = node; + + spin_unlock_irqrestore(&contr->lock, flags); + + return 0; +} + int request_irq(unsigned int irq, irqreturn_t (*handler) (int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { - return mach_request_irq(irq, handler, flags, devname, dev_id); + struct irq_node *node; + int res; + + node = new_irq_node(); + if (!node) + return -ENOMEM; + + node->handler = handler; + node->flags = flags; + node->dev_id = dev_id; + node->devname = devname; + + res = setup_irq(irq, node); + if (res) + node->handler = NULL; + + return res; } EXPORT_SYMBOL(request_irq); void free_irq(unsigned int irq, void *dev_id) { - mach_free_irq(irq, dev_id); + struct irq_controller *contr; + struct irq_node **p, *node; + unsigned long flags; + + if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + return; + } + + spin_lock_irqsave(&contr->lock, flags); + + p = irq_list + irq; + while ((node = *p)) { + if (node->dev_id == dev_id) + break; + p = &node->next; + } + + if (node) { + *p = node->next; + node->handler = NULL; + } else + printk("%s: Removing probably wrong IRQ %d\n", + __FUNCTION__, irq); + + if (!irq_list[irq]) { + if (contr->shutdown) + contr->shutdown(irq); + else + contr->disable(irq); + } + + spin_unlock_irqrestore(&contr->lock, flags); } EXPORT_SYMBOL(free_irq); -int cpu_request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) +void enable_irq(unsigned int irq) { - if (irq < IRQ1 || irq > IRQ7) { - printk("%s: Incorrect IRQ %d from %s\n", - __FUNCTION__, irq, devname); - return -ENXIO; - } + struct irq_controller *contr; + unsigned long flags; -#if 0 - if (!(irq_list[irq].flags & IRQ_FLG_STD)) { - if (irq_list[irq].flags & IRQ_FLG_LOCK) { - printk("%s: IRQ %d from %s is not replaceable\n", - __FUNCTION__, irq, irq_list[irq].devname); - return -EBUSY; - } - if (!(flags & IRQ_FLG_REPLACE)) { - printk("%s: %s can't replace IRQ %d from %s\n", - __FUNCTION__, devname, irq, irq_list[irq].devname); - return -EBUSY; - } + if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + printk("%s: Incorrect IRQ %d\n", + __FUNCTION__, irq); + return; } -#endif - irq_list[irq].handler = handler; - irq_list[irq].flags = flags; - irq_list[irq].dev_id = dev_id; - irq_list[irq].devname = devname; - return 0; + spin_lock_irqsave(&contr->lock, flags); + if (irq_depth[irq]) { + if (!--irq_depth[irq]) { + if (contr->enable) + contr->enable(irq); + } + } else + WARN_ON(1); + spin_unlock_irqrestore(&contr->lock, flags); } -void cpu_free_irq(unsigned int irq, void *dev_id) +EXPORT_SYMBOL(enable_irq); + +void disable_irq(unsigned int irq) { - if (irq < IRQ1 || irq > IRQ7) { - printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + struct irq_controller *contr; + unsigned long flags; + + if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + printk("%s: Incorrect IRQ %d\n", + __FUNCTION__, irq); return; } - if (irq_list[irq].dev_id != dev_id) - printk("%s: Removing probably wrong IRQ %d from %s\n", - __FUNCTION__, irq, irq_list[irq].devname); + spin_lock_irqsave(&contr->lock, flags); + if (!irq_depth[irq]++) { + if (contr->disable) + contr->disable(irq); + } + spin_unlock_irqrestore(&contr->lock, flags); +} - irq_list[irq].handler = (*mach_default_handler)[irq]; - irq_list[irq].flags = 0; - irq_list[irq].dev_id = NULL; - irq_list[irq].devname = default_names[irq]; +EXPORT_SYMBOL(disable_irq); + +int m68k_irq_startup(unsigned int irq) +{ + if (irq <= IRQ_AUTO_7) + vectors[VEC_SPUR + irq] = auto_inthandler; + else + vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler; + return 0; } +void m68k_irq_shutdown(unsigned int irq) +{ + if (irq <= IRQ_AUTO_7) + vectors[VEC_SPUR + irq] = bad_inthandler; + else + vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler; +} + + /* * Do we need these probe functions on the m68k? * @@ -219,58 +369,50 @@ #endif EXPORT_SYMBOL(probe_irq_off); -static void dummy_enable_irq(unsigned int irq) -{ - printk("calling uninitialized enable_irq()\n"); -} - -static void dummy_disable_irq(unsigned int irq) +unsigned int irq_canonicalize(unsigned int irq) { - printk("calling uninitialized disable_irq()\n"); +#ifdef CONFIG_Q40 + if (MACH_IS_Q40 && irq == 11) + irq = 10; +#endif + return irq; } -static int dummy_request_irq(unsigned int irq, - irqreturn_t (*handler) (int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - printk("calling uninitialized request_irq()\n"); - return 0; -} +EXPORT_SYMBOL(irq_canonicalize); -static void dummy_free_irq(unsigned int irq, void *dev_id) +asmlinkage void m68k_handle_int(unsigned int irq, struct pt_regs *regs) { - printk("calling uninitialized disable_irq()\n"); + struct irq_node *node; + + kstat_cpu(0).irqs[irq]++; + node = irq_list[irq]; + do { + node->handler(irq, node->dev_id, regs); + node = node->next; + } while (node); } -asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) +asmlinkage void handle_badint(struct pt_regs *regs) { - if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) { - vec -= VEC_SPUR; - kstat_cpu(0).irqs[vec]++; - irq_list[vec].handler(vec, irq_list[vec].dev_id, fp); - } else { - if (mach_process_int) - mach_process_int(vec, fp); - else - panic("Can't process interrupt vector %ld\n", vec); - return; - } + kstat_cpu(0).irqs[0]++; + printk("unexpected interrupt from %u\n", regs->vector); } int show_interrupts(struct seq_file *p, void *v) { + struct irq_controller *contr; + struct irq_node *node; int i = *(loff_t *) v; /* autovector interrupts */ - if (i < SYS_IRQS) { - if (mach_default_handler) { - seq_printf(p, "auto %2d: %10u ", i, - i ? kstat_cpu(0).irqs[i] : num_spurious); - seq_puts(p, " "); - seq_printf(p, "%s\n", irq_list[i].devname); - } - } else if (i == SYS_IRQS) - mach_get_irq_list(p, v); + if (irq_list[i]) { + contr = irq_controller[i]; + node = irq_list[i]; + seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname); + while ((node = node->next)) + seq_printf(p, ", %s", node->devname); + seq_puts(p, "\n"); + } return 0; } diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 5b7952e..1f5e1b5 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -57,8 +57,6 @@ EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_thread); #ifdef CONFIG_VME EXPORT_SYMBOL(vme_brdtype); diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index 750d5b3..214a95f 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -68,11 +68,8 @@ char m68k_debug_device[6] = ""; void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) __initdata = NULL; /* machine dependent irq functions */ void (*mach_init_IRQ) (void) __initdata = NULL; -irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *); void (*mach_get_model) (char *model); int (*mach_get_hardware_list) (char *buffer); -int (*mach_get_irq_list) (struct seq_file *, void *); -irqreturn_t (*mach_process_int) (int, struct pt_regs *); /* machine dependent timer functions */ unsigned long (*mach_gettimeoffset) (void); int (*mach_hwclk) (int, struct rtc_time*); diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 866917b..f9af893 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -763,7 +763,7 @@ get_sigframe(struct k_sigaction *ka, str /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (!on_sig_stack(usp)) + if (!sas_ss_flags(usp)) usp = current->sas_ss_sp + current->sas_ss_size; } return (void __user *)((usp - frame_size) & -8UL); diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index cdf58fb..e86de7b 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -45,7 +45,6 @@ #include asmlinkage void system_call(void); asmlinkage void buserr(void); asmlinkage void trap(void); -asmlinkage void inthandler(void); asmlinkage void nmihandler(void); #ifdef CONFIG_M68KFPU_EMU asmlinkage void fpu_emu(void); @@ -53,51 +52,7 @@ #endif e_vector vectors[256] = { [VEC_BUSERR] = buserr, - [VEC_ADDRERR] = trap, - [VEC_ILLEGAL] = trap, - [VEC_ZERODIV] = trap, - [VEC_CHK] = trap, - [VEC_TRAP] = trap, - [VEC_PRIV] = trap, - [VEC_TRACE] = trap, - [VEC_LINE10] = trap, - [VEC_LINE11] = trap, - [VEC_RESV12] = trap, - [VEC_COPROC] = trap, - [VEC_FORMAT] = trap, - [VEC_UNINT] = trap, - [VEC_RESV16] = trap, - [VEC_RESV17] = trap, - [VEC_RESV18] = trap, - [VEC_RESV19] = trap, - [VEC_RESV20] = trap, - [VEC_RESV21] = trap, - [VEC_RESV22] = trap, - [VEC_RESV23] = trap, - [VEC_SPUR] = inthandler, - [VEC_INT1] = inthandler, - [VEC_INT2] = inthandler, - [VEC_INT3] = inthandler, - [VEC_INT4] = inthandler, - [VEC_INT5] = inthandler, - [VEC_INT6] = inthandler, - [VEC_INT7] = inthandler, [VEC_SYS] = system_call, - [VEC_TRAP1] = trap, - [VEC_TRAP2] = trap, - [VEC_TRAP3] = trap, - [VEC_TRAP4] = trap, - [VEC_TRAP5] = trap, - [VEC_TRAP6] = trap, - [VEC_TRAP7] = trap, - [VEC_TRAP8] = trap, - [VEC_TRAP9] = trap, - [VEC_TRAP10] = trap, - [VEC_TRAP11] = trap, - [VEC_TRAP12] = trap, - [VEC_TRAP13] = trap, - [VEC_TRAP14] = trap, - [VEC_TRAP15] = trap, }; /* nmi handler for the Amiga */ @@ -114,7 +69,7 @@ void __init base_trap_init(void) if(MACH_IS_SUN3X) { extern e_vector *sun3x_prom_vbr; - __asm__ volatile ("movec %%vbr, %0" : "=r" ((void*)sun3x_prom_vbr)); + __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr)); } /* setup the exception vector table */ @@ -132,12 +87,15 @@ void __init trap_init (void) { int i; - for (i = 48; i < 64; i++) + for (i = VEC_SPUR; i <= VEC_INT7; i++) + vectors[i] = bad_inthandler; + + for (i = 0; i < VEC_USER; i++) if (!vectors[i]) vectors[i] = trap; - for (i = 64; i < 256; i++) - vectors[i] = inthandler; + for (i = VEC_USER; i < 256; i++) + vectors[i] = bad_inthandler; #ifdef CONFIG_M68KFPU_EMU if (FPU_IS_EMU) @@ -927,71 +885,94 @@ #endif void show_registers(struct pt_regs *regs) { struct frame *fp = (struct frame *)regs; + mm_segment_t old_fs = get_fs(); + u16 c, *cp; unsigned long addr; int i; + print_modules(); + printk("PC: [<%08lx>]",regs->pc); + print_symbol(" %s", regs->pc); + printk("\nSR: %04x SP: %p a2: %08lx\n", + regs->sr, regs, regs->a2); + printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", + regs->d0, regs->d1, regs->d2, regs->d3); + printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", + regs->d4, regs->d5, regs->a0, regs->a1); + + printk("Process %s (pid: %d, task=%p)\n", + current->comm, current->pid, current); addr = (unsigned long)&fp->un; - printk("Frame format=%X ", fp->ptregs.format); - switch (fp->ptregs.format) { + printk("Frame format=%X ", regs->format); + switch (regs->format) { case 0x2: - printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); - addr += sizeof(fp->un.fmt2); - break; + printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); + addr += sizeof(fp->un.fmt2); + break; case 0x3: - printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); - addr += sizeof(fp->un.fmt3); - break; + printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); + addr += sizeof(fp->un.fmt3); + break; case 0x4: - printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" - : "eff addr=%08lx pc=%08lx\n"), - fp->un.fmt4.effaddr, fp->un.fmt4.pc); - addr += sizeof(fp->un.fmt4); - break; + printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" + : "eff addr=%08lx pc=%08lx\n"), + fp->un.fmt4.effaddr, fp->un.fmt4.pc); + addr += sizeof(fp->un.fmt4); + break; case 0x7: - printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", - fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); - printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); - printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); - printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); - printk("push data: %08lx %08lx %08lx %08lx\n", - fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, - fp->un.fmt7.pd3); - addr += sizeof(fp->un.fmt7); - break; + printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", + fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); + printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); + printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); + printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); + printk("push data: %08lx %08lx %08lx %08lx\n", + fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, + fp->un.fmt7.pd3); + addr += sizeof(fp->un.fmt7); + break; case 0x9: - printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); - addr += sizeof(fp->un.fmt9); - break; + printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); + addr += sizeof(fp->un.fmt9); + break; case 0xa: - printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", - fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, - fp->un.fmta.daddr, fp->un.fmta.dobuf); - addr += sizeof(fp->un.fmta); - break; + printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", + fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, + fp->un.fmta.daddr, fp->un.fmta.dobuf); + addr += sizeof(fp->un.fmta); + break; case 0xb: - printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", - fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, - fp->un.fmtb.daddr, fp->un.fmtb.dobuf); - printk("baddr=%08lx dibuf=%08lx ver=%x\n", - fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); - addr += sizeof(fp->un.fmtb); - break; + printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", + fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, + fp->un.fmtb.daddr, fp->un.fmtb.dobuf); + printk("baddr=%08lx dibuf=%08lx ver=%x\n", + fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); + addr += sizeof(fp->un.fmtb); + break; default: - printk("\n"); + printk("\n"); } show_stack(NULL, (unsigned long *)addr); - printk("Code: "); - for (i = 0; i < 10; i++) - printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]); + printk("Code:"); + set_fs(KERNEL_DS); + cp = (u16 *)regs->pc; + for (i = -8; i < 16; i++) { + if (get_user(c, cp + i) && i >= 0) { + printk(" Bad PC value."); + break; + } + printk(i ? " %04x" : " <%04x>", c); + } + set_fs(old_fs); printk ("\n"); } void show_stack(struct task_struct *task, unsigned long *stack) { + unsigned long *p; unsigned long *endstack; int i; @@ -1004,12 +985,13 @@ void show_stack(struct task_struct *task endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); printk("Stack from %08lx:", (unsigned long)stack); + p = stack; for (i = 0; i < kstack_depth_to_print; i++) { - if (stack + 1 > endstack) + if (p + 1 > endstack) break; if (i % 8 == 0) printk("\n "); - printk(" %08lx", *stack++); + printk(" %08lx", *p++); } printk("\n"); show_trace(stack); @@ -1188,19 +1170,7 @@ void die_if_kernel (char *str, struct pt console_verbose(); printk("%s: %08x\n",str,nr); - print_modules(); - printk("PC: [<%08lx>]",fp->pc); - print_symbol(" %s\n", fp->pc); - printk("\nSR: %04x SP: %p a2: %08lx\n", - fp->sr, fp, fp->a2); - printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", - fp->d0, fp->d1, fp->d2, fp->d3); - printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", - fp->d4, fp->d5, fp->a0, fp->a1); - - printk("Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, PAGE_SIZE+(unsigned long)current); - show_stack(NULL, (unsigned long *)fp); + show_registers(fp); do_exit(SIGSEGV); } diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile index ebe51a5..6bbf19f 100644 --- a/arch/m68k/lib/Makefile +++ b/arch/m68k/lib/Makefile @@ -4,5 +4,5 @@ # EXTRA_AFLAGS := -traditional -lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ - checksum.o string.o semaphore.o +lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ + checksum.o string.o semaphore.o uaccess.o diff --git a/arch/m68k/lib/uaccess.c b/arch/m68k/lib/uaccess.c new file mode 100644 index 0000000..1bc188c --- /dev/null +++ b/arch/m68k/lib/uaccess.c @@ -0,0 +1,222 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include + +unsigned long __generic_copy_from_user(void *to, const void __user *from, + unsigned long n) +{ + unsigned long tmp, res; + + asm volatile ("\n" + " tst.l %0\n" + " jeq 2f\n" + "1: moves.l (%1)+,%3\n" + " move.l %3,(%2)+\n" + " subq.l #1,%0\n" + " jne 1b\n" + "2: btst #1,%5\n" + " jeq 4f\n" + "3: moves.w (%1)+,%3\n" + " move.w %3,(%2)+\n" + "4: btst #0,%5\n" + " jeq 6f\n" + "5: moves.b (%1)+,%3\n" + " move.b %3,(%2)+\n" + "6:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "10: move.l %0,%3\n" + "7: clr.l (%2)+\n" + " subq.l #1,%3\n" + " jne 7b\n" + " lsl.l #2,%0\n" + " btst #1,%5\n" + " jeq 8f\n" + "30: clr.w (%2)+\n" + " addq.l #2,%0\n" + "8: btst #0,%5\n" + " jeq 6b\n" + "50: clr.b (%2)+\n" + " addq.l #1,%0\n" + " jra 6b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,10b\n" + " .long 3b,30b\n" + " .long 5b,50b\n" + " .previous" + : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp) + : "0" (n / 4), "d" (n & 3)); + + return res; +} +EXPORT_SYMBOL(__generic_copy_from_user); + +unsigned long __generic_copy_to_user(void __user *to, const void *from, + unsigned long n) +{ + unsigned long tmp, res; + + asm volatile ("\n" + " tst.l %0\n" + " jeq 4f\n" + "1: move.l (%1)+,%3\n" + "2: moves.l %3,(%2)+\n" + "3: subq.l #1,%0\n" + " jne 1b\n" + "4: btst #1,%5\n" + " jeq 6f\n" + " move.w (%1)+,%3\n" + "5: moves.w %3,(%2)+\n" + "6: btst #0,%5\n" + " jeq 8f\n" + " move.b (%1)+,%3\n" + "7: moves.b %3,(%2)+\n" + "8:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "20: lsl.l #2,%0\n" + "50: add.l %5,%0\n" + " jra 7b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 2b,20b\n" + " .long 3b,20b\n" + " .long 5b,50b\n" + " .long 6b,50b\n" + " .long 7b,50b\n" + " .long 8b,50b\n" + " .previous" + : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp) + : "0" (n / 4), "d" (n & 3)); + + return res; +} +EXPORT_SYMBOL(__generic_copy_to_user); + +/* + * Copy a null terminated string from userspace. + */ +long strncpy_from_user(char *dst, const char __user *src, long count) +{ + long res; + char c; + + if (count <= 0) + return count; + + asm volatile ("\n" + "1: moves.b (%2)+,%4\n" + " move.b %4,(%1)+\n" + " jeq 2f\n" + " subq.l #1,%3\n" + " jne 1b\n" + "2: sub.l %3,%0\n" + "3:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "10: move.l %5,%0\n" + " jra 3b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,10b\n" + " .previous" + : "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c) + : "i" (-EFAULT), "0" (count)); + + return res; +} +EXPORT_SYMBOL(strncpy_from_user); + +/* + * Return the size of a string (including the ending 0) + * + * Return 0 on exception, a value greater than N if too long + */ +long strnlen_user(const char __user *src, long n) +{ + char c; + long res; + + asm volatile ("\n" + "1: subq.l #1,%1\n" + " jmi 3f\n" + "2: moves.b (%0)+,%2\n" + " tst.b %2\n" + " jne 1b\n" + " jra 4f\n" + "\n" + "3: addq.l #1,%0\n" + "4: sub.l %4,%0\n" + "5:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "20: sub.l %0,%0\n" + " jra 5b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 2b,20b\n" + " .previous\n" + : "=&a" (res), "+d" (n), "=&d" (c) + : "0" (src), "r" (src)); + + return res; +} +EXPORT_SYMBOL(strnlen_user); + +/* + * Zero Userspace + */ + +unsigned long clear_user(void __user *to, unsigned long n) +{ + unsigned long res; + + asm volatile ("\n" + " tst.l %0\n" + " jeq 3f\n" + "1: moves.l %2,(%1)+\n" + "2: subq.l #1,%0\n" + " jne 1b\n" + "3: btst #1,%4\n" + " jeq 5f\n" + "4: moves.w %2,(%1)+\n" + "5: btst #0,%4\n" + " jeq 7f\n" + "6: moves.b %2,(%1)\n" + "7:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "10: lsl.l #2,%0\n" + "40: add.l %4,%0\n" + " jra 7b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,10b\n" + " .long 2b,10b\n" + " .long 4b,40b\n" + " .long 5b,40b\n" + " .long 6b,40b\n" + " .long 7b,40b\n" + " .previous" + : "=d" (res), "+a" (to) + : "r" (0), "0" (n / 4), "d" (n & 3)); + + return res; +} +EXPORT_SYMBOL(clear_user); diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c index b19b7dd..6eaa881 100644 --- a/arch/m68k/mac/baboon.c +++ b/arch/m68k/mac/baboon.c @@ -81,7 +81,7 @@ #endif for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) { if (events & irq_bit/* & baboon_active*/) { baboon_active &= ~irq_bit; - mac_do_irq_list(IRQ_BABOON_0 + i, regs); + m68k_handle_int(IRQ_BABOON_0 + i, regs); baboon_active |= irq_bit; baboon->mb_ifr &= ~irq_bit; } diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index 14f8d3f..5a9990e 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -89,38 +89,11 @@ extern void mac_debugging_long(int, long static void mac_get_model(char *str); -void mac_bang(int irq, void *vector, struct pt_regs *p) -{ - printk(KERN_INFO "Resetting ...\n"); - mac_reset(); -} - static void mac_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *)) { via_init_clock(vector); } -#if 0 -void mac_waitbut (void) -{ - ; -} -#endif - -extern irqreturn_t mac_default_handler(int, void *, struct pt_regs *); - -irqreturn_t (*mac_handlers[8])(int, void *, struct pt_regs *)= -{ - mac_default_handler, - mac_default_handler, - mac_default_handler, - mac_default_handler, - mac_default_handler, - mac_default_handler, - mac_default_handler, - mac_default_handler -}; - /* * Parse a Macintosh-specific record in the bootinfo */ @@ -196,13 +169,7 @@ void __init config_mac(void) mach_sched_init = mac_sched_init; mach_init_IRQ = mac_init_IRQ; - mach_request_irq = mac_request_irq; - mach_free_irq = mac_free_irq; - enable_irq = mac_enable_irq; - disable_irq = mac_disable_irq; mach_get_model = mac_get_model; - mach_default_handler = &mac_handlers; - mach_get_irq_list = show_mac_interrupts; mach_gettimeoffset = mac_gettimeoffset; #warning move to adb/via init #if 0 diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index 9179a37..4c8ece7 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c @@ -317,7 +317,7 @@ void __init iop_register_interrupts(void { if (iop_ism_present) { if (oss_present) { - cpu_request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, + request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, IRQ_FLG_LOCK, "ISM IOP", (void *) IOP_NUM_ISM); oss_irq_enable(IRQ_MAC_ADB); diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c index 1809601..694b14b 100644 --- a/arch/m68k/mac/macints.c +++ b/arch/m68k/mac/macints.c @@ -137,14 +137,6 @@ #include #define DEBUG_SPURIOUS #define SHUTUP_SONIC -/* - * The mac_irq_list array is an array of linked lists of irq_node_t nodes. - * Each node contains one handler to be called whenever the interrupt - * occurs, with fast handlers listed before slow handlers. - */ - -irq_node_t *mac_irq_list[NUM_MAC_SOURCES]; - /* SCC interrupt mask */ static int scc_mask; @@ -209,34 +201,37 @@ extern int baboon_irq_pending(int); * SCC interrupt routines */ -static void scc_irq_enable(int); -static void scc_irq_disable(int); +static void scc_irq_enable(unsigned int); +static void scc_irq_disable(unsigned int); /* * console_loglevel determines NMI handler function */ -extern irqreturn_t mac_bang(int, void *, struct pt_regs *); irqreturn_t mac_nmi_handler(int, void *, struct pt_regs *); irqreturn_t mac_debug_handler(int, void *, struct pt_regs *); /* #define DEBUG_MACINTS */ +static void mac_enable_irq(unsigned int irq); +static void mac_disable_irq(unsigned int irq); + +static struct irq_controller mac_irq_controller = { + .name = "mac", + .lock = SPIN_LOCK_UNLOCKED, + .enable = mac_enable_irq, + .disable = mac_disable_irq, +}; + void mac_init_IRQ(void) { - int i; - #ifdef DEBUG_MACINTS printk("mac_init_IRQ(): Setting things up...\n"); #endif - /* Initialize the IRQ handler lists. Initially each list is empty, */ - - for (i = 0; i < NUM_MAC_SOURCES; i++) { - mac_irq_list[i] = NULL; - } - scc_mask = 0; + m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER, + NUM_MAC_SOURCES - IRQ_USER); /* Make sure the SONIC interrupt is cleared or things get ugly */ #ifdef SHUTUP_SONIC printk("Killing onboard sonic... "); @@ -253,15 +248,16 @@ #endif /* SHUTUP_SONIC */ * at levels 1-7. Most of the work is done elsewhere. */ - if (oss_present) { + if (oss_present) oss_register_interrupts(); - } else { + else via_register_interrupts(); - } - if (psc_present) psc_register_interrupts(); - if (baboon_present) baboon_register_interrupts(); + if (psc_present) + psc_register_interrupts(); + if (baboon_present) + baboon_register_interrupts(); iop_register_interrupts(); - cpu_request_irq(7, mac_nmi_handler, IRQ_FLG_LOCK, "NMI", + request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI", mac_nmi_handler); #ifdef DEBUG_MACINTS printk("mac_init_IRQ(): Done!\n"); @@ -269,104 +265,6 @@ #endif } /* - * Routines to work with irq_node_t's on linked lists lifted from - * the Amiga code written by Roman Zippel. - */ - -static inline void mac_insert_irq(irq_node_t **list, irq_node_t *node) -{ - unsigned long flags; - irq_node_t *cur; - - if (!node->dev_id) - printk("%s: Warning: dev_id of %s is zero\n", - __FUNCTION__, node->devname); - - local_irq_save(flags); - - cur = *list; - - if (node->flags & IRQ_FLG_FAST) { - node->flags &= ~IRQ_FLG_SLOW; - while (cur && cur->flags & IRQ_FLG_FAST) { - list = &cur->next; - cur = cur->next; - } - } else if (node->flags & IRQ_FLG_SLOW) { - while (cur) { - list = &cur->next; - cur = cur->next; - } - } else { - while (cur && !(cur->flags & IRQ_FLG_SLOW)) { - list = &cur->next; - cur = cur->next; - } - } - - node->next = cur; - *list = node; - - local_irq_restore(flags); -} - -static inline void mac_delete_irq(irq_node_t **list, void *dev_id) -{ - unsigned long flags; - irq_node_t *node; - - local_irq_save(flags); - - for (node = *list; node; list = &node->next, node = *list) { - if (node->dev_id == dev_id) { - *list = node->next; - /* Mark it as free. */ - node->handler = NULL; - local_irq_restore(flags); - return; - } - } - local_irq_restore(flags); - printk ("%s: tried to remove invalid irq\n", __FUNCTION__); -} - -/* - * Call all the handlers for a given interrupt. Fast handlers are called - * first followed by slow handlers. - * - * This code taken from the original Amiga code written by Roman Zippel. - */ - -void mac_do_irq_list(int irq, struct pt_regs *fp) -{ - irq_node_t *node, *slow_nodes; - unsigned long flags; - - kstat_cpu(0).irqs[irq]++; - -#ifdef DEBUG_SPURIOUS - if (!mac_irq_list[irq] && (console_loglevel > 7)) { - printk("mac_do_irq_list: spurious interrupt %d!\n", irq); - return; - } -#endif - - /* serve first fast and normal handlers */ - for (node = mac_irq_list[irq]; - node && (!(node->flags & IRQ_FLG_SLOW)); - node = node->next) - node->handler(irq, node->dev_id, fp); - if (!node) return; - local_save_flags(flags); - local_irq_restore((flags & ~0x0700) | (fp->sr & 0x0700)); - /* if slow handlers exists, serve them now */ - slow_nodes = node; - for (; node; node = node->next) { - node->handler(irq, node->dev_id, fp); - } -} - -/* * mac_enable_irq - enable an interrupt source * mac_disable_irq - disable an interrupt source * mac_clear_irq - clears a pending interrupt @@ -375,276 +273,124 @@ #endif * These routines are just dispatchers to the VIA/OSS/PSC routines. */ -void mac_enable_irq (unsigned int irq) +static void mac_enable_irq(unsigned int irq) { - int irq_src = IRQ_SRC(irq); + int irq_src = IRQ_SRC(irq); switch(irq_src) { - case 1: via_irq_enable(irq); - break; - case 2: - case 7: if (oss_present) { - oss_irq_enable(irq); - } else { - via_irq_enable(irq); - } - break; - case 3: - case 4: - case 5: - case 6: if (psc_present) { - psc_irq_enable(irq); - } else if (oss_present) { - oss_irq_enable(irq); - } else if (irq_src == 4) { - scc_irq_enable(irq); - } - break; - case 8: if (baboon_present) { - baboon_irq_enable(irq); - } - break; + case 1: + via_irq_enable(irq); + break; + case 2: + case 7: + if (oss_present) + oss_irq_enable(irq); + else + via_irq_enable(irq); + break; + case 3: + case 4: + case 5: + case 6: + if (psc_present) + psc_irq_enable(irq); + else if (oss_present) + oss_irq_enable(irq); + else if (irq_src == 4) + scc_irq_enable(irq); + break; + case 8: + if (baboon_present) + baboon_irq_enable(irq); + break; } } -void mac_disable_irq (unsigned int irq) +static void mac_disable_irq(unsigned int irq) { - int irq_src = IRQ_SRC(irq); + int irq_src = IRQ_SRC(irq); switch(irq_src) { - case 1: via_irq_disable(irq); - break; - case 2: - case 7: if (oss_present) { - oss_irq_disable(irq); - } else { - via_irq_disable(irq); - } - break; - case 3: - case 4: - case 5: - case 6: if (psc_present) { - psc_irq_disable(irq); - } else if (oss_present) { - oss_irq_disable(irq); - } else if (irq_src == 4) { - scc_irq_disable(irq); - } - break; - case 8: if (baboon_present) { - baboon_irq_disable(irq); - } - break; + case 1: + via_irq_disable(irq); + break; + case 2: + case 7: + if (oss_present) + oss_irq_disable(irq); + else + via_irq_disable(irq); + break; + case 3: + case 4: + case 5: + case 6: + if (psc_present) + psc_irq_disable(irq); + else if (oss_present) + oss_irq_disable(irq); + else if (irq_src == 4) + scc_irq_disable(irq); + break; + case 8: + if (baboon_present) + baboon_irq_disable(irq); + break; } } -void mac_clear_irq( unsigned int irq ) +void mac_clear_irq(unsigned int irq) { switch(IRQ_SRC(irq)) { - case 1: via_irq_clear(irq); - break; - case 2: - case 7: if (oss_present) { - oss_irq_clear(irq); - } else { - via_irq_clear(irq); - } - break; - case 3: - case 4: - case 5: - case 6: if (psc_present) { - psc_irq_clear(irq); - } else if (oss_present) { - oss_irq_clear(irq); - } - break; - case 8: if (baboon_present) { - baboon_irq_clear(irq); - } - break; + case 1: + via_irq_clear(irq); + break; + case 2: + case 7: + if (oss_present) + oss_irq_clear(irq); + else + via_irq_clear(irq); + break; + case 3: + case 4: + case 5: + case 6: + if (psc_present) + psc_irq_clear(irq); + else if (oss_present) + oss_irq_clear(irq); + break; + case 8: + if (baboon_present) + baboon_irq_clear(irq); + break; } } -int mac_irq_pending( unsigned int irq ) +int mac_irq_pending(unsigned int irq) { switch(IRQ_SRC(irq)) { - case 1: return via_irq_pending(irq); - case 2: - case 7: if (oss_present) { - return oss_irq_pending(irq); - } else { - return via_irq_pending(irq); - } - case 3: - case 4: - case 5: - case 6: if (psc_present) { - return psc_irq_pending(irq); - } else if (oss_present) { - return oss_irq_pending(irq); - } - } - return 0; -} - -/* - * Add an interrupt service routine to an interrupt source. - * Returns 0 on success. - * - * FIXME: You can register interrupts on nonexistent source (ie PSC4 on a - * non-PSC machine). We should return -EINVAL in those cases. - */ - -int mac_request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - irq_node_t *node; - -#ifdef DEBUG_MACINTS - printk ("%s: irq %d requested for %s\n", __FUNCTION__, irq, devname); -#endif - - if (irq < VIA1_SOURCE_BASE) { - return cpu_request_irq(irq, handler, flags, devname, dev_id); + case 1: + return via_irq_pending(irq); + case 2: + case 7: + if (oss_present) + return oss_irq_pending(irq); + else + return via_irq_pending(irq); + case 3: + case 4: + case 5: + case 6: + if (psc_present) + return psc_irq_pending(irq); + else if (oss_present) + return oss_irq_pending(irq); } - - if (irq >= NUM_MAC_SOURCES) { - printk ("%s: unknown irq %d requested by %s\n", - __FUNCTION__, irq, devname); - } - - /* Get a node and stick it onto the right list */ - - if (!(node = new_irq_node())) return -ENOMEM; - - node->handler = handler; - node->flags = flags; - node->dev_id = dev_id; - node->devname = devname; - node->next = NULL; - mac_insert_irq(&mac_irq_list[irq], node); - - /* Now enable the IRQ source */ - - mac_enable_irq(irq); - return 0; } -/* - * Removes an interrupt service routine from an interrupt source. - */ - -void mac_free_irq(unsigned int irq, void *dev_id) -{ -#ifdef DEBUG_MACINTS - printk ("%s: irq %d freed by %p\n", __FUNCTION__, irq, dev_id); -#endif - - if (irq < VIA1_SOURCE_BASE) { - cpu_free_irq(irq, dev_id); - return; - } - - if (irq >= NUM_MAC_SOURCES) { - printk ("%s: unknown irq %d freed\n", - __FUNCTION__, irq); - return; - } - - mac_delete_irq(&mac_irq_list[irq], dev_id); - - /* If the list for this interrupt is */ - /* empty then disable the source. */ - - if (!mac_irq_list[irq]) { - mac_disable_irq(irq); - } -} - -/* - * Generate a pretty listing for /proc/interrupts - * - * By the time we're called the autovector interrupt list has already been - * generated, so we just need to do the machspec interrupts. - * - * 990506 (jmt) - rewritten to handle chained machspec interrupt handlers. - * Also removed display of num_spurious it is already - * displayed for us as autovector irq 0. - */ - -int show_mac_interrupts(struct seq_file *p, void *v) -{ - int i; - irq_node_t *node; - char *base; - - /* Don't do Nubus interrupts in this loop; we do them separately */ - /* below so that we can print slot numbers instead of IRQ numbers */ - - for (i = VIA1_SOURCE_BASE ; i < NUM_MAC_SOURCES ; ++i) { - - /* Nonexistant interrupt or nothing registered; skip it. */ - - if ((node = mac_irq_list[i]) == NULL) continue; - if (node->flags & IRQ_FLG_STD) continue; - - base = ""; - switch(IRQ_SRC(i)) { - case 1: base = "via1"; - break; - case 2: if (oss_present) { - base = "oss"; - } else { - base = "via2"; - } - break; - case 3: - case 4: - case 5: - case 6: if (psc_present) { - base = "psc"; - } else if (oss_present) { - base = "oss"; - } else { - if (IRQ_SRC(i) == 4) base = "scc"; - } - break; - case 7: base = "nbus"; - break; - case 8: base = "bbn"; - break; - } - seq_printf(p, "%4s %2d: %10u ", base, i, kstat_cpu(0).irqs[i]); - - do { - if (node->flags & IRQ_FLG_FAST) { - seq_puts(p, "F "); - } else if (node->flags & IRQ_FLG_SLOW) { - seq_puts(p, "S "); - } else { - seq_puts(p, " "); - } - seq_printf(p, "%s\n", node->devname); - if ((node = node->next)) { - seq_puts(p, " "); - } - } while(node); - - } - return 0; -} - -void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs) -{ -#ifdef DEBUG_SPURIOUS - printk("Unexpected IRQ %d on device %p\n", irq, dev_id); -#endif -} - static int num_debug[8]; irqreturn_t mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs) @@ -684,7 +430,7 @@ irqreturn_t mac_nmi_handler(int irq, voi while (nmi_hold == 1) udelay(1000); - if ( console_loglevel >= 8 ) { + if (console_loglevel >= 8) { #if 0 show_state(); printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp); @@ -713,14 +459,16 @@ #endif * done in hardware (only the PSC can do that.) */ -static void scc_irq_enable(int irq) { - int irq_idx = IRQ_IDX(irq); +static void scc_irq_enable(unsigned int irq) +{ + int irq_idx = IRQ_IDX(irq); scc_mask |= (1 << irq_idx); } -static void scc_irq_disable(int irq) { - int irq_idx = IRQ_IDX(irq); +static void scc_irq_disable(unsigned int irq) +{ + int irq_idx = IRQ_IDX(irq); scc_mask &= ~(1 << irq_idx); } @@ -755,6 +503,8 @@ void mac_scc_dispatch(int irq, void *dev /* and since they're autovector interrupts they */ /* pretty much kill the system. */ - if (reg & 0x38) mac_do_irq_list(IRQ_SCCA, regs); - if (reg & 0x07) mac_do_irq_list(IRQ_SCCB, regs); + if (reg & 0x38) + m68k_handle_int(IRQ_SCCA, regs); + if (reg & 0x07) + m68k_handle_int(IRQ_SCCB, regs); } diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c index 3335476..63e0436 100644 --- a/arch/m68k/mac/oss.c +++ b/arch/m68k/mac/oss.c @@ -67,15 +67,15 @@ void __init oss_init(void) void __init oss_register_interrupts(void) { - cpu_request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK, + request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK, "scsi", (void *) oss); - cpu_request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK, + request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK, "scc", mac_scc_dispatch); - cpu_request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK, + request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK, "nubus", (void *) oss); - cpu_request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK, + request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK, "sound", (void *) oss); - cpu_request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK, + request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK, "via1", (void *) via1); } @@ -113,7 +113,7 @@ #endif oss->irq_pending &= ~OSS_IP_SOUND; } else if (events & OSS_IP_SCSI) { oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED; - mac_do_irq_list(IRQ_MAC_SCSI, regs); + m68k_handle_int(IRQ_MAC_SCSI, regs); oss->irq_pending &= ~OSS_IP_SCSI; oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI; } else { @@ -146,7 +146,7 @@ #endif for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) { if (events & irq_bit) { oss->irq_level[i] = OSS_IRQLEV_DISABLED; - mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs); + m68k_handle_int(NUBUS_SOURCE_BASE + i, regs); oss->irq_pending &= ~irq_bit; oss->irq_level[i] = OSS_IRQLEV_NUBUS; } diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c index e72384e..e262180 100644 --- a/arch/m68k/mac/psc.c +++ b/arch/m68k/mac/psc.c @@ -117,10 +117,10 @@ #endif void __init psc_register_interrupts(void) { - cpu_request_irq(3, psc_irq, IRQ_FLG_LOCK, "psc3", (void *) 0x30); - cpu_request_irq(4, psc_irq, IRQ_FLG_LOCK, "psc4", (void *) 0x40); - cpu_request_irq(5, psc_irq, IRQ_FLG_LOCK, "psc5", (void *) 0x50); - cpu_request_irq(6, psc_irq, IRQ_FLG_LOCK, "psc6", (void *) 0x60); + request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30); + request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40); + request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50); + request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60); } /* @@ -149,7 +149,7 @@ #endif for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) { if (events & irq_bit) { psc_write_byte(pIER, irq_bit); - mac_do_irq_list(base_irq + i, regs); + m68k_handle_int(base_irq + i, regs); psc_write_byte(pIFR, irq_bit); psc_write_byte(pIER, irq_bit | 0x80); } diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index cd528bf..c4aa345 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -71,7 +70,6 @@ void via_irq_enable(int irq); void via_irq_disable(int irq); void via_irq_clear(int irq); -extern irqreturn_t mac_bang(int, void *, struct pt_regs *); extern irqreturn_t mac_scc_dispatch(int, void *, struct pt_regs *); extern int oss_present; @@ -212,11 +210,6 @@ #if 1 break; } #else - /* The alernate IRQ mapping seems to just not work. Anyone with a */ - /* supported machine is welcome to take a stab at fixing it. It */ - /* _should_ work on the following Quadras: 610,650,700,800,900,950 */ - /* - 1999-06-12 (jmt) */ - via_alt_mapping = 0; #endif @@ -260,27 +253,21 @@ void __init via_init_clock(irqreturn_t ( void __init via_register_interrupts(void) { if (via_alt_mapping) { - cpu_request_irq(IRQ_AUTO_1, via1_irq, + request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, "software", (void *) via1); - cpu_request_irq(IRQ_AUTO_6, via1_irq, + request_irq(IRQ_AUTO_6, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", (void *) via1); } else { - cpu_request_irq(IRQ_AUTO_1, via1_irq, + request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", (void *) via1); -#if 0 /* interferes with serial on some machines */ - if (!psc_present) { - cpu_request_irq(IRQ_AUTO_6, mac_bang, IRQ_FLG_LOCK, - "Off Switch", mac_bang); - } -#endif } - cpu_request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, + request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, "via2", (void *) via2); if (!psc_present) { - cpu_request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK, + request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK, "scc", mac_scc_dispatch); } request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, @@ -437,7 +424,7 @@ irqreturn_t via1_irq(int irq, void *dev_ for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) if (events & irq_bit) { via1[vIER] = irq_bit; - mac_do_irq_list(VIA1_SOURCE_BASE + i, regs); + m68k_handle_int(VIA1_SOURCE_BASE + i, regs); via1[vIFR] = irq_bit; via1[vIER] = irq_bit | 0x80; } @@ -452,7 +439,7 @@ #if 0 /* freakin' pmu is doing weird stu /* No, it won't be set. that's why we're doing this. */ via_irq_disable(IRQ_MAC_NUBUS); via_irq_clear(IRQ_MAC_NUBUS); - mac_do_irq_list(IRQ_MAC_NUBUS, regs); + m68k_handle_int(IRQ_MAC_NUBUS, regs); via_irq_enable(IRQ_MAC_NUBUS); } #endif @@ -471,8 +458,8 @@ irqreturn_t via2_irq(int irq, void *dev_ for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) if (events & irq_bit) { via2[gIER] = irq_bit; - mac_do_irq_list(VIA2_SOURCE_BASE + i, regs); via2[gIFR] = irq_bit | rbv_clear; + m68k_handle_int(VIA2_SOURCE_BASE + i, regs); via2[gIER] = irq_bit | 0x80; } return IRQ_HANDLED; @@ -494,7 +481,7 @@ irqreturn_t via_nubus_irq(int irq, void for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) { if (events & irq_bit) { via_irq_disable(NUBUS_SOURCE_BASE + i); - mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs); + m68k_handle_int(NUBUS_SOURCE_BASE + i, regs); via_irq_enable(NUBUS_SOURCE_BASE + i); } } @@ -529,6 +516,7 @@ #endif } via2[gIER] = irq_bit | 0x80; } else if (irq_src == 7) { + nubus_active |= irq_bit; if (rbv_present) { /* enable the slot interrupt. SIER works like IER. */ via2[rSIER] = IER_SET_BIT(irq_idx); @@ -550,7 +538,6 @@ #endif } } } - nubus_active |= irq_bit; } } diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c index 85ad19a..43ffab0 100644 --- a/arch/m68k/mm/kmap.c +++ b/arch/m68k/mm/kmap.c @@ -259,13 +259,15 @@ void __iounmap(void *addr, unsigned long if (CPU_IS_020_OR_030) { int pmd_off = (virtaddr/PTRTREESIZE) & 15; + int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK; - if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) { + if (pmd_type == _PAGE_PRESENT) { pmd_dir->pmd[pmd_off] = 0; virtaddr += PTRTREESIZE; size -= PTRTREESIZE; continue; - } + } else if (pmd_type == 0) + continue; } if (pmd_bad(*pmd_dir)) { diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c index d6d582a..a226668 100644 --- a/arch/m68k/mm/memory.c +++ b/arch/m68k/mm/memory.c @@ -94,8 +94,7 @@ pmd_t *get_pointer_table (void) PD_MARKBITS(dp) = mask & ~tmp; if (!PD_MARKBITS(dp)) { /* move to end of list */ - list_del(dp); - list_add_tail(dp, &ptable_list); + list_move_tail(dp, &ptable_list); } return (pmd_t *) (page_address(PD_PAGE(dp)) + off); } @@ -123,8 +122,7 @@ int free_pointer_table (pmd_t *ptable) * move this descriptor to the front of the list, since * it has one or more free tables. */ - list_del(dp); - list_add(dp, &ptable_list); + list_move(dp, &ptable_list); } return 0; } diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c index afb57ee..bdb1110 100644 --- a/arch/m68k/mm/motorola.c +++ b/arch/m68k/mm/motorola.c @@ -203,7 +203,7 @@ void __init paging_init(void) { int chunk; unsigned long mem_avail = 0; - unsigned long zones_size[3] = { 0, }; + unsigned long zones_size[MAX_NR_ZONES] = { 0, }; #ifdef DEBUG { @@ -257,12 +257,12 @@ #endif #ifdef DEBUG printk ("before free_area_init\n"); #endif - zones_size[0] = (mach_max_dma_address < (unsigned long)high_memory ? - (mach_max_dma_address+1) : (unsigned long)high_memory); - zones_size[1] = (unsigned long)high_memory - zones_size[0]; + zones_size[ZONE_DMA] = (mach_max_dma_address < (unsigned long)high_memory ? + (mach_max_dma_address+1) : (unsigned long)high_memory); + zones_size[ZONE_NORMAL] = (unsigned long)high_memory - zones_size[0]; - zones_size[0] = (zones_size[0] - PAGE_OFFSET) >> PAGE_SHIFT; - zones_size[1] >>= PAGE_SHIFT; + zones_size[ZONE_DMA] = (zones_size[ZONE_DMA] - PAGE_OFFSET) >> PAGE_SHIFT; + zones_size[ZONE_NORMAL] >>= PAGE_SHIFT; free_area_init(zones_size); } diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c index a47be19..ac6640a 100644 --- a/arch/m68k/mm/sun3mmu.c +++ b/arch/m68k/mm/sun3mmu.c @@ -46,7 +46,7 @@ void __init paging_init(void) unsigned long address; unsigned long next_pgtable; unsigned long bootmem_end; - unsigned long zones_size[3] = {0, 0, 0}; + unsigned long zones_size[MAX_NR_ZONES] = { 0, }; unsigned long size; @@ -92,8 +92,7 @@ #endif current->mm = NULL; /* memory sizing is a hack stolen from motorola.c.. hope it works for us */ - zones_size[0] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT; - zones_size[1] = 0; + zones_size[ZONE_DMA] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT; free_area_init(zones_size); diff --git a/arch/m68k/mvme147/147ints.c b/arch/m68k/mvme147/147ints.c deleted file mode 100644 index 69a744e..0000000 --- a/arch/m68k/mvme147/147ints.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * arch/m68k/mvme147/147ints.c - * - * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk] - * - * based on amiints.c -- Amiga Linux interrupt handling code - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file README.legal in the main directory of this archive - * for more details. - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -static irqreturn_t mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp); - -/* - * This should ideally be 4 elements only, for speed. - */ - -static struct { - irqreturn_t (*handler)(int, void *, struct pt_regs *); - unsigned long flags; - void *dev_id; - const char *devname; - unsigned count; -} irq_tab[256]; - -/* - * void mvme147_init_IRQ (void) - * - * Parameters: None - * - * Returns: Nothing - * - * This function is called during kernel startup to initialize - * the mvme147 IRQ handling routines. - */ - -void mvme147_init_IRQ (void) -{ - int i; - - for (i = 0; i < 256; i++) { - irq_tab[i].handler = mvme147_defhand; - irq_tab[i].flags = IRQ_FLG_STD; - irq_tab[i].dev_id = NULL; - irq_tab[i].devname = NULL; - irq_tab[i].count = 0; - } -} - -int mvme147_request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - if (irq > 255) { - printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); - return -ENXIO; - } - if (!(irq_tab[irq].flags & IRQ_FLG_STD)) { - if (irq_tab[irq].flags & IRQ_FLG_LOCK) { - printk("%s: IRQ %d from %s is not replaceable\n", - __FUNCTION__, irq, irq_tab[irq].devname); - return -EBUSY; - } - if (flags & IRQ_FLG_REPLACE) { - printk("%s: %s can't replace IRQ %d from %s\n", - __FUNCTION__, devname, irq, irq_tab[irq].devname); - return -EBUSY; - } - } - irq_tab[irq].handler = handler; - irq_tab[irq].flags = flags; - irq_tab[irq].dev_id = dev_id; - irq_tab[irq].devname = devname; - return 0; -} - -void mvme147_free_irq(unsigned int irq, void *dev_id) -{ - if (irq > 255) { - printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); - return; - } - if (irq_tab[irq].dev_id != dev_id) - printk("%s: Removing probably wrong IRQ %d from %s\n", - __FUNCTION__, irq, irq_tab[irq].devname); - - irq_tab[irq].handler = mvme147_defhand; - irq_tab[irq].flags = IRQ_FLG_STD; - irq_tab[irq].dev_id = NULL; - irq_tab[irq].devname = NULL; -} - -irqreturn_t mvme147_process_int (unsigned long vec, struct pt_regs *fp) -{ - if (vec > 255) { - printk ("mvme147_process_int: Illegal vector %ld\n", vec); - return IRQ_NONE; - } else { - irq_tab[vec].count++; - irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp); - return IRQ_HANDLED; - } -} - -int show_mvme147_interrupts (struct seq_file *p, void *v) -{ - int i; - - for (i = 0; i < 256; i++) { - if (irq_tab[i].count) - seq_printf(p, "Vec 0x%02x: %8d %s\n", - i, irq_tab[i].count, - irq_tab[i].devname ? irq_tab[i].devname : "free"); - } - return 0; -} - - -static irqreturn_t mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp) -{ - printk ("Unknown interrupt 0x%02x\n", irq); - return IRQ_NONE; -} - -void mvme147_enable_irq (unsigned int irq) -{ -} - - -void mvme147_disable_irq (unsigned int irq) -{ -} - diff --git a/arch/m68k/mvme147/Makefile b/arch/m68k/mvme147/Makefile index f0153ed..a36d38d 100644 --- a/arch/m68k/mvme147/Makefile +++ b/arch/m68k/mvme147/Makefile @@ -2,4 +2,4 @@ # # Makefile for Linux arch/m68k/mvme147 source directory # -obj-y := config.o 147ints.o +obj-y := config.o diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c index 0fcf972..0cd0e5b 100644 --- a/arch/m68k/mvme147/config.c +++ b/arch/m68k/mvme147/config.c @@ -36,15 +36,8 @@ #include #include -extern irqreturn_t mvme147_process_int (int level, struct pt_regs *regs); -extern void mvme147_init_IRQ (void); -extern void mvme147_free_irq (unsigned int, void *); -extern int show_mvme147_interrupts (struct seq_file *, void *); -extern void mvme147_enable_irq (unsigned int); -extern void mvme147_disable_irq (unsigned int); static void mvme147_get_model(char *model); static int mvme147_get_hardware_list(char *buffer); -extern int mvme147_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); extern void mvme147_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); extern unsigned long mvme147_gettimeoffset (void); extern int mvme147_hwclk (int, struct rtc_time *); @@ -91,6 +84,15 @@ static int mvme147_get_hardware_list(cha return 0; } +/* + * This function is called during kernel startup to initialize + * the mvme147 IRQ handling routines. + */ + +void mvme147_init_IRQ(void) +{ + m68k_setup_user_interrupt(VEC_USER, 192, NULL); +} void __init config_mvme147(void) { @@ -101,12 +103,6 @@ void __init config_mvme147(void) mach_hwclk = mvme147_hwclk; mach_set_clock_mmss = mvme147_set_clock_mmss; mach_reset = mvme147_reset; - mach_free_irq = mvme147_free_irq; - mach_process_int = mvme147_process_int; - mach_get_irq_list = show_mvme147_interrupts; - mach_request_irq = mvme147_request_irq; - enable_irq = mvme147_enable_irq; - disable_irq = mvme147_disable_irq; mach_get_model = mvme147_get_model; mach_get_hardware_list = mvme147_get_hardware_list; diff --git a/arch/m68k/mvme16x/16xints.c b/arch/m68k/mvme16x/16xints.c deleted file mode 100644 index 793ef73..0000000 --- a/arch/m68k/mvme16x/16xints.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * arch/m68k/mvme16x/16xints.c - * - * Copyright (C) 1995 Richard Hirst [richard@sleepie.demon.co.uk] - * - * based on amiints.c -- Amiga Linux interrupt handling code - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file README.legal in the main directory of this archive - * for more details. - * - */ - -#include -#include -#include -#include - -#include -#include -#include - -static irqreturn_t mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp); - -/* - * This should ideally be 4 elements only, for speed. - */ - -static struct { - irqreturn_t (*handler)(int, void *, struct pt_regs *); - unsigned long flags; - void *dev_id; - const char *devname; - unsigned count; -} irq_tab[192]; - -/* - * void mvme16x_init_IRQ (void) - * - * Parameters: None - * - * Returns: Nothing - * - * This function is called during kernel startup to initialize - * the mvme16x IRQ handling routines. Should probably ensure - * that the base vectors for the VMEChip2 and PCCChip2 are valid. - */ - -void mvme16x_init_IRQ (void) -{ - int i; - - for (i = 0; i < 192; i++) { - irq_tab[i].handler = mvme16x_defhand; - irq_tab[i].flags = IRQ_FLG_STD; - irq_tab[i].dev_id = NULL; - irq_tab[i].devname = NULL; - irq_tab[i].count = 0; - } -} - -int mvme16x_request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - if (irq < 64 || irq > 255) { - printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); - return -ENXIO; - } - - if (!(irq_tab[irq-64].flags & IRQ_FLG_STD)) { - if (irq_tab[irq-64].flags & IRQ_FLG_LOCK) { - printk("%s: IRQ %d from %s is not replaceable\n", - __FUNCTION__, irq, irq_tab[irq-64].devname); - return -EBUSY; - } - if (flags & IRQ_FLG_REPLACE) { - printk("%s: %s can't replace IRQ %d from %s\n", - __FUNCTION__, devname, irq, irq_tab[irq-64].devname); - return -EBUSY; - } - } - irq_tab[irq-64].handler = handler; - irq_tab[irq-64].flags = flags; - irq_tab[irq-64].dev_id = dev_id; - irq_tab[irq-64].devname = devname; - return 0; -} - -void mvme16x_free_irq(unsigned int irq, void *dev_id) -{ - if (irq < 64 || irq > 255) { - printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); - return; - } - - if (irq_tab[irq-64].dev_id != dev_id) - printk("%s: Removing probably wrong IRQ %d from %s\n", - __FUNCTION__, irq, irq_tab[irq-64].devname); - - irq_tab[irq-64].handler = mvme16x_defhand; - irq_tab[irq-64].flags = IRQ_FLG_STD; - irq_tab[irq-64].dev_id = NULL; - irq_tab[irq-64].devname = NULL; -} - -irqreturn_t mvme16x_process_int (unsigned long vec, struct pt_regs *fp) -{ - if (vec < 64 || vec > 255) { - printk ("mvme16x_process_int: Illegal vector %ld", vec); - return IRQ_NONE; - } else { - irq_tab[vec-64].count++; - irq_tab[vec-64].handler(vec, irq_tab[vec-64].dev_id, fp); - return IRQ_HANDLED; - } -} - -int show_mvme16x_interrupts (struct seq_file *p, void *v) -{ - int i; - - for (i = 0; i < 192; i++) { - if (irq_tab[i].count) - seq_printf(p, "Vec 0x%02x: %8d %s\n", - i+64, irq_tab[i].count, - irq_tab[i].devname ? irq_tab[i].devname : "free"); - } - return 0; -} - - -static irqreturn_t mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp) -{ - printk ("Unknown interrupt 0x%02x\n", irq); - return IRQ_NONE; -} - - -void mvme16x_enable_irq (unsigned int irq) -{ -} - - -void mvme16x_disable_irq (unsigned int irq) -{ -} - - diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile index 5129f56..950e82f 100644 --- a/arch/m68k/mvme16x/Makefile +++ b/arch/m68k/mvme16x/Makefile @@ -2,4 +2,4 @@ # # Makefile for Linux arch/m68k/mvme16x source directory # -obj-y := config.o 16xints.o rtc.o mvme16x_ksyms.o +obj-y := config.o rtc.o mvme16x_ksyms.o diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c index 26ce81c..ce2727e 100644 --- a/arch/m68k/mvme16x/config.c +++ b/arch/m68k/mvme16x/config.c @@ -40,15 +40,8 @@ extern t_bdid mvme_bdid; static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE; -extern irqreturn_t mvme16x_process_int (int level, struct pt_regs *regs); -extern void mvme16x_init_IRQ (void); -extern void mvme16x_free_irq (unsigned int, void *); -extern int show_mvme16x_interrupts (struct seq_file *, void *); -extern void mvme16x_enable_irq (unsigned int); -extern void mvme16x_disable_irq (unsigned int); static void mvme16x_get_model(char *model); static int mvme16x_get_hardware_list(char *buffer); -extern int mvme16x_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); extern void mvme16x_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); extern unsigned long mvme16x_gettimeoffset (void); extern int mvme16x_hwclk (int, struct rtc_time *); @@ -120,6 +113,16 @@ static int mvme16x_get_hardware_list(cha return (len); } +/* + * This function is called during kernel startup to initialize + * the mvme16x IRQ handling routines. Should probably ensure + * that the base vectors for the VMEChip2 and PCCChip2 are valid. + */ + +static void mvme16x_init_IRQ (void) +{ + m68k_setup_user_interrupt(VEC_USER, 192, NULL); +} #define pcc2chip ((volatile u_char *)0xfff42000) #define PccSCCMICR 0x1d @@ -138,12 +141,6 @@ void __init config_mvme16x(void) mach_hwclk = mvme16x_hwclk; mach_set_clock_mmss = mvme16x_set_clock_mmss; mach_reset = mvme16x_reset; - mach_free_irq = mvme16x_free_irq; - mach_process_int = mvme16x_process_int; - mach_get_irq_list = show_mvme16x_interrupts; - mach_request_irq = mvme16x_request_irq; - enable_irq = mvme16x_enable_irq; - disable_irq = mvme16x_disable_irq; mach_get_model = mvme16x_get_model; mach_get_hardware_list = mvme16x_get_hardware_list; diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c index 5e0f9b0..efa52d3 100644 --- a/arch/m68k/q40/config.c +++ b/arch/m68k/q40/config.c @@ -37,15 +37,9 @@ #include #include extern irqreturn_t q40_process_int (int level, struct pt_regs *regs); -extern irqreturn_t (*q40_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */ extern void q40_init_IRQ (void); -extern void q40_free_irq (unsigned int, void *); -extern int show_q40_interrupts (struct seq_file *, void *); -extern void q40_enable_irq (unsigned int); -extern void q40_disable_irq (unsigned int); static void q40_get_model(char *model); static int q40_get_hardware_list(char *buffer); -extern int q40_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); extern unsigned long q40_gettimeoffset (void); @@ -175,13 +169,6 @@ void __init config_q40(void) mach_set_clock_mmss = q40_set_clock_mmss; mach_reset = q40_reset; - mach_free_irq = q40_free_irq; - mach_process_int = q40_process_int; - mach_get_irq_list = show_q40_interrupts; - mach_request_irq = q40_request_irq; - enable_irq = q40_enable_irq; - disable_irq = q40_disable_irq; - mach_default_handler = &q40_default_handler; mach_get_model = q40_get_model; mach_get_hardware_list = q40_get_hardware_list; diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index f8ecc26..472f41c 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c @@ -14,13 +14,8 @@ #include #include #include -#include -#include -#include #include -#include -#include #include #include #include @@ -39,29 +34,37 @@ #include * */ -extern int ints_inited; +static void q40_irq_handler(unsigned int, struct pt_regs *fp); +static void q40_enable_irq(unsigned int); +static void q40_disable_irq(unsigned int); +unsigned short q40_ablecount[35]; +unsigned short q40_state[35]; -irqreturn_t q40_irq2_handler (int, void *, struct pt_regs *fp); - - -static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp); -static irqreturn_t default_handler(int lev, void *dev_id, struct pt_regs *regs); - - -#define DEVNAME_SIZE 24 +static int q40_irq_startup(unsigned int irq) +{ + /* test for ISA ints not implemented by HW */ + switch (irq) { + case 1: case 2: case 8: case 9: + case 11: case 12: case 13: + printk("%s: ISA IRQ %d not implemented by HW\n", __FUNCTION__, irq); + return -ENXIO; + } + return 0; +} -static struct q40_irq_node { - irqreturn_t (*handler)(int, void *, struct pt_regs *); - unsigned long flags; - void *dev_id; - /* struct q40_irq_node *next;*/ - char devname[DEVNAME_SIZE]; - unsigned count; - unsigned short state; -} irq_tab[Q40_IRQ_MAX+1]; +static void q40_irq_shutdown(unsigned int irq) +{ +} -short unsigned q40_ablecount[Q40_IRQ_MAX+1]; +static struct irq_controller q40_irq_controller = { + .name = "q40", + .lock = SPIN_LOCK_UNLOCKED, + .startup = q40_irq_startup, + .shutdown = q40_irq_shutdown, + .enable = q40_enable_irq, + .disable = q40_disable_irq, +}; /* * void q40_init_IRQ (void) @@ -74,139 +77,29 @@ short unsigned q40_ablecount[Q40_IRQ_MAX * the q40 IRQ handling routines. */ -static int disabled=0; +static int disabled; -void q40_init_IRQ (void) +void q40_init_IRQ(void) { - int i; - - disabled=0; - for (i = 0; i <= Q40_IRQ_MAX; i++) { - irq_tab[i].handler = q40_defhand; - irq_tab[i].flags = 0; - irq_tab[i].dev_id = NULL; - /* irq_tab[i].next = NULL;*/ - irq_tab[i].devname[0] = 0; - irq_tab[i].count = 0; - irq_tab[i].state =0; - q40_ablecount[i]=0; /* all enabled */ - } + m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX); /* setup handler for ISA ints */ - cpu_request_irq(IRQ2, q40_irq2_handler, 0, "q40 ISA and master chip", - NULL); + m68k_setup_auto_interrupt(q40_irq_handler); + + m68k_irq_startup(IRQ_AUTO_2); + m68k_irq_startup(IRQ_AUTO_4); /* now enable some ints.. */ - master_outb(1,EXT_ENABLE_REG); /* ISA IRQ 5-15 */ + master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */ /* make sure keyboard IRQ is disabled */ - master_outb(0,KEY_IRQ_ENABLE_REG); + master_outb(0, KEY_IRQ_ENABLE_REG); } -int q40_request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - /*printk("q40_request_irq %d, %s\n",irq,devname);*/ - - if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) { - printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); - return -ENXIO; - } - - /* test for ISA ints not implemented by HW */ - switch (irq) - { - case 1: case 2: case 8: case 9: - case 12: case 13: - printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname); - return -ENXIO; - case 11: - printk("warning IRQ 10 and 11 not distinguishable\n"); - irq=10; - default: - ; - } - - if (irq Q40_IRQ_MAX || (irq>15 && irq<32)) { - printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id); - return; - } - - /* test for ISA ints not implemented by HW */ - switch (irq) - { - case 1: case 2: case 8: case 9: - case 12: case 13: - printk("%s: ISA IRQ %d from %x invalid\n", __FUNCTION__, irq, (unsigned)dev_id); - return; - case 11: irq=10; - default: - ; - } - - if (irqpc, fp->d0, fp->orig_d0, fp->d1, fp->d2); - printk("\tIIRQ_REG = %x, EIRQ_REG = %x\n",master_inb(IIRQ_REG),master_inb(EIRQ_REG)); - return IRQ_HANDLED; -} /* * this stuff doesn't really belong here.. -*/ + */ int ql_ticks; /* 200Hz ticks since last jiffie */ static int sound_ticks; @@ -215,54 +108,53 @@ #define SVOL 45 void q40_mksound(unsigned int hz, unsigned int ticks) { - /* for now ignore hz, except that hz==0 switches off sound */ - /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */ - if (hz==0) - { - if (sound_ticks) - sound_ticks=1; - - *DAC_LEFT=128; - *DAC_RIGHT=128; - - return; - } - /* sound itself is done in q40_timer_int */ - if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */ - sound_ticks=ticks<<1; + /* for now ignore hz, except that hz==0 switches off sound */ + /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */ + if (hz == 0) { + if (sound_ticks) + sound_ticks = 1; + + *DAC_LEFT = 128; + *DAC_RIGHT = 128; + + return; + } + /* sound itself is done in q40_timer_int */ + if (sound_ticks == 0) + sound_ticks = 1000; /* pretty long beep */ + sound_ticks = ticks << 1; } static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *); static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs) { - ql_ticks = ql_ticks ? 0 : 1; - if (sound_ticks) - { - unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL; - sound_ticks--; - *DAC_LEFT=sval; - *DAC_RIGHT=sval; - } - - if (!ql_ticks) - q40_timer_routine(irq, dev, regs); - return IRQ_HANDLED; + ql_ticks = ql_ticks ? 0 : 1; + if (sound_ticks) { + unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL; + sound_ticks--; + *DAC_LEFT=sval; + *DAC_RIGHT=sval; + } + + if (!ql_ticks) + q40_timer_routine(irq, dev, regs); + return IRQ_HANDLED; } void q40_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *)) { - int timer_irq; + int timer_irq; - q40_timer_routine = timer_routine; - timer_irq=Q40_IRQ_FRAME; + q40_timer_routine = timer_routine; + timer_irq = Q40_IRQ_FRAME; - if (request_irq(timer_irq, q40_timer_int, 0, + if (request_irq(timer_irq, q40_timer_int, 0, "timer", q40_timer_int)) - panic ("Couldn't register timer int"); + panic("Couldn't register timer int"); - master_outb(-1,FRAME_CLEAR_REG); - master_outb( 1,FRAME_RATE_REG); + master_outb(-1, FRAME_CLEAR_REG); + master_outb( 1, FRAME_RATE_REG); } @@ -308,169 +200,132 @@ static int mext_disabled=0; /* ext irq static int aliased_irq=0; /* how many times inside handler ?*/ -/* got level 2 interrupt, dispatch to ISA or keyboard/timer IRQs */ -irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp) +/* got interrupt, dispatch to ISA or keyboard/timer IRQs */ +static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) { - unsigned mir, mer; - int irq,i; + unsigned mir, mer; + int i; //repeat: - mir=master_inb(IIRQ_REG); - if (mir&Q40_IRQ_FRAME_MASK) { - irq_tab[Q40_IRQ_FRAME].count++; - irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp); - master_outb(-1,FRAME_CLEAR_REG); - } - if ((mir&Q40_IRQ_SER_MASK) || (mir&Q40_IRQ_EXT_MASK)) { - mer=master_inb(EIRQ_REG); - for (i=0; eirqs[i].mask; i++) { - if (mer&(eirqs[i].mask)) { - irq=eirqs[i].irq; + mir = master_inb(IIRQ_REG); +#ifdef CONFIG_BLK_DEV_FD + if ((mir & Q40_IRQ_EXT_MASK) && + (master_inb(EIRQ_REG) & Q40_IRQ6_MASK)) { + floppy_hardint(); + return; + } +#endif + switch (irq) { + case 4: + case 6: + m68k_handle_int(Q40_IRQ_SAMPLE, fp); + return; + } + if (mir & Q40_IRQ_FRAME_MASK) { + m68k_handle_int(Q40_IRQ_FRAME, fp); + master_outb(-1, FRAME_CLEAR_REG); + } + if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) { + mer = master_inb(EIRQ_REG); + for (i = 0; eirqs[i].mask; i++) { + if (mer & eirqs[i].mask) { + irq = eirqs[i].irq; /* * There is a little mess wrt which IRQ really caused this irq request. The * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they * are read - which is long after the request came in. In theory IRQs should * not just go away but they occassionally do */ - if (irq>4 && irq<=15 && mext_disabled) { - /*aliased_irq++;*/ - goto iirq; - } - if (irq_tab[irq].handler == q40_defhand ) { - printk("handler for IRQ %d not defined\n",irq); - continue; /* ignore uninited INTs :-( */ - } - if ( irq_tab[irq].state & IRQ_INPROGRESS ) { - /* some handlers do local_irq_enable() for irq latency reasons, */ - /* however reentering an active irq handler is not permitted */ + if (irq > 4 && irq <= 15 && mext_disabled) { + /*aliased_irq++;*/ + goto iirq; + } + if (q40_state[irq] & IRQ_INPROGRESS) { + /* some handlers do local_irq_enable() for irq latency reasons, */ + /* however reentering an active irq handler is not permitted */ #ifdef IP_USE_DISABLE - /* in theory this is the better way to do it because it still */ - /* lets through eg the serial irqs, unfortunately it crashes */ - disable_irq(irq); - disabled=1; + /* in theory this is the better way to do it because it still */ + /* lets through eg the serial irqs, unfortunately it crashes */ + disable_irq(irq); + disabled = 1; #else - /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */ - fp->sr = (((fp->sr) & (~0x700))+0x200); - disabled=1; + /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n", + irq, disabled ? "already" : "not yet"); */ + fp->sr = (((fp->sr) & (~0x700))+0x200); + disabled = 1; #endif - goto iirq; - } - irq_tab[irq].count++; - irq_tab[irq].state |= IRQ_INPROGRESS; - irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp); - irq_tab[irq].state &= ~IRQ_INPROGRESS; - - /* naively enable everything, if that fails than */ - /* this function will be reentered immediately thus */ - /* getting another chance to disable the IRQ */ - - if ( disabled ) { + goto iirq; + } + q40_state[irq] |= IRQ_INPROGRESS; + m68k_handle_int(irq, fp); + q40_state[irq] &= ~IRQ_INPROGRESS; + + /* naively enable everything, if that fails than */ + /* this function will be reentered immediately thus */ + /* getting another chance to disable the IRQ */ + + if (disabled) { #ifdef IP_USE_DISABLE - if (irq>4){ - disabled=0; - enable_irq(irq);} + if (irq > 4) { + disabled = 0; + enable_irq(irq); + } #else - disabled=0; - /*printk("reenabling irq %d\n",irq); */ + disabled = 0; + /*printk("reenabling irq %d\n", irq); */ #endif - } + } // used to do 'goto repeat;' here, this delayed bh processing too long - return IRQ_HANDLED; - } - } - if (mer && ccleirq>0 && !aliased_irq) - printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--; - } - iirq: - mir=master_inb(IIRQ_REG); - /* should test whether keyboard irq is really enabled, doing it in defhand */ - if (mir&Q40_IRQ_KEYB_MASK) { - irq_tab[Q40_IRQ_KEYBOARD].count++; - irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp); - } - return IRQ_HANDLED; -} - -int show_q40_interrupts (struct seq_file *p, void *v) -{ - int i; - - for (i = 0; i <= Q40_IRQ_MAX; i++) { - if (irq_tab[i].count) - seq_printf(p, "%sIRQ %02d: %8d %s%s\n", - (i<=15) ? "ISA-" : " " , - i, irq_tab[i].count, - irq_tab[i].devname[0] ? irq_tab[i].devname : "?", - irq_tab[i].handler == q40_defhand ? - " (now unassigned)" : ""); + return; + } + } + if (mer && ccleirq > 0 && !aliased_irq) { + printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer); + ccleirq--; + } } - return 0; -} - + iirq: + mir = master_inb(IIRQ_REG); + /* should test whether keyboard irq is really enabled, doing it in defhand */ + if (mir & Q40_IRQ_KEYB_MASK) + m68k_handle_int(Q40_IRQ_KEYBOARD, fp); -static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp) -{ - if (irq!=Q40_IRQ_KEYBOARD) - printk ("Unknown q40 interrupt %d\n", irq); - else master_outb(-1,KEYBOARD_UNLOCK_REG); - return IRQ_NONE; + return; } -static irqreturn_t default_handler(int lev, void *dev_id, struct pt_regs *regs) -{ - printk ("Uninitialised interrupt level %d\n", lev); - return IRQ_NONE; -} - -irqreturn_t (*q40_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { - [0] = default_handler, - [1] = default_handler, - [2] = default_handler, - [3] = default_handler, - [4] = default_handler, - [5] = default_handler, - [6] = default_handler, - [7] = default_handler -}; - -void q40_enable_irq (unsigned int irq) +void q40_enable_irq(unsigned int irq) { - if ( irq>=5 && irq<=15 ) - { - mext_disabled--; - if (mext_disabled>0) - printk("q40_enable_irq : nested disable/enable\n"); - if (mext_disabled==0) - master_outb(1,EXT_ENABLE_REG); - } + if (irq >= 5 && irq <= 15) { + mext_disabled--; + if (mext_disabled > 0) + printk("q40_enable_irq : nested disable/enable\n"); + if (mext_disabled == 0) + master_outb(1, EXT_ENABLE_REG); + } } -void q40_disable_irq (unsigned int irq) +void q40_disable_irq(unsigned int irq) { - /* disable ISA iqs : only do something if the driver has been - * verified to be Q40 "compatible" - right now IDE, NE2K - * Any driver should not attempt to sleep across disable_irq !! - */ - - if ( irq>=5 && irq<=15 ) { - master_outb(0,EXT_ENABLE_REG); - mext_disabled++; - if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled); - } + /* disable ISA iqs : only do something if the driver has been + * verified to be Q40 "compatible" - right now IDE, NE2K + * Any driver should not attempt to sleep across disable_irq !! + */ + + if (irq >= 5 && irq <= 15) { + master_outb(0, EXT_ENABLE_REG); + mext_disabled++; + if (mext_disabled > 1) + printk("disable_irq nesting count %d\n",mext_disabled); + } } -unsigned long q40_probe_irq_on (void) +unsigned long q40_probe_irq_on(void) { - printk("irq probing not working - reconfigure the driver to avoid this\n"); - return -1; + printk("irq probing not working - reconfigure the driver to avoid this\n"); + return -1; } -int q40_probe_irq_off (unsigned long irqs) +int q40_probe_irq_off(unsigned long irqs) { - return -1; + return -1; } -/* - * Local variables: - * compile-command: "m68k-linux-gcc -D__KERNEL__ -I/home/rz/lx/linux-2.2.6/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -m68040 -c -o q40ints.o q40ints.c" - * End: - */ diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c index f1ca0df..553c304 100644 --- a/arch/m68k/sun3/config.c +++ b/arch/m68k/sun3/config.c @@ -36,7 +36,6 @@ extern char _text, _end; char sun3_reserved_pmeg[SUN3_PMEGS_NUM]; extern unsigned long sun3_gettimeoffset(void); -extern int show_sun3_interrupts (struct seq_file *, void *); extern void sun3_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); extern void sun3_get_model (char* model); extern void idprom_init (void); @@ -147,13 +146,6 @@ void __init config_sun3(void) mach_sched_init = sun3_sched_init; mach_init_IRQ = sun3_init_IRQ; - mach_default_handler = &sun3_default_handler; - mach_request_irq = sun3_request_irq; - mach_free_irq = sun3_free_irq; - enable_irq = sun3_enable_irq; - disable_irq = sun3_disable_irq; - mach_process_int = sun3_process_int; - mach_get_irq_list = show_sun3_interrupts; mach_reset = sun3_reboot; mach_gettimeoffset = sun3_gettimeoffset; mach_get_model = sun3_get_model; diff --git a/arch/m68k/sun3/sun3dvma.c b/arch/m68k/sun3/sun3dvma.c index f04a1d2..97c7bfd 100644 --- a/arch/m68k/sun3/sun3dvma.c +++ b/arch/m68k/sun3/sun3dvma.c @@ -119,8 +119,7 @@ static inline int refill(void) if(hole->end == prev->start) { hole->size += prev->size; hole->end = prev->end; - list_del(&(prev->list)); - list_add(&(prev->list), &hole_cache); + list_move(&(prev->list), &hole_cache); ret++; } @@ -182,8 +181,7 @@ #ifdef DVMA_DEBUG #endif return hole->end; } else if(hole->size == newlen) { - list_del(&(hole->list)); - list_add(&(hole->list), &hole_cache); + list_move(&(hole->list), &hole_cache); dvma_entry_use(hole->start) = newlen; #ifdef DVMA_DEBUG dvma_allocs++; diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c index e62a033..0912435 100644 --- a/arch/m68k/sun3/sun3ints.c +++ b/arch/m68k/sun3/sun3ints.c @@ -19,7 +19,6 @@ #include #include extern void sun3_leds (unsigned char); -static irqreturn_t sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp); void sun3_disable_interrupts(void) { @@ -40,48 +39,30 @@ int led_pattern[8] = { volatile unsigned char* sun3_intreg; -void sun3_insert_irq(irq_node_t **list, irq_node_t *node) -{ -} - -void sun3_delete_irq(irq_node_t **list, void *dev_id) -{ -} - void sun3_enable_irq(unsigned int irq) { - *sun3_intreg |= (1<= 64) && (irq <= 255)) { - int vec; - - vec = irq - 64; - if(sun3_vechandler[vec] != NULL) { - printk("sun3_request_irq: request for vec %d -- already taken!\n", irq); - return 1; - } - - sun3_vechandler[vec] = handler; - vec_ids[vec] = dev_id; - vec_names[vec] = devname; - vec_ints[vec] = 0; - - return 0; - } - } - - printk("sun3_request_irq: invalid irq %d\n", irq); - return 1; + *sun3_intreg &= ~(1 << irq); + m68k_handle_int(irq, fp); } -void sun3_free_irq(unsigned int irq, void *dev_id) -{ - - if(irq < SYS_IRQS) { - if(sun3_inthandler[irq] == NULL) - panic("sun3_free_int: attempt to free unused irq %d\n", irq); - if(dev_ids[irq] != dev_id) - panic("sun3_free_int: incorrect dev_id for irq %d\n", irq); - - sun3_inthandler[irq] = NULL; - return; - } else if((irq >= 64) && (irq <= 255)) { - int vec; - - vec = irq - 64; - if(sun3_vechandler[vec] == NULL) - panic("sun3_free_int: attempt to free unused vector %d\n", irq); - if(vec_ids[irq] != dev_id) - panic("sun3_free_int: incorrect dev_id for vec %d\n", irq); - - sun3_vechandler[vec] = NULL; - return; - } else { - panic("sun3_free_irq: invalid irq %d\n", irq); - } -} +static struct irq_controller sun3_irq_controller = { + .name = "sun3", + .lock = SPIN_LOCK_UNLOCKED, + .startup = m68k_irq_startup, + .shutdown = m68k_irq_shutdown, + .enable = sun3_enable_irq, + .disable = sun3_disable_irq, +}; -irqreturn_t sun3_process_int(int irq, struct pt_regs *regs) +void sun3_init_IRQ(void) { + *sun3_intreg = 1; - if((irq >= 64) && (irq <= 255)) { - int vec; - - vec = irq - 64; - if(sun3_vechandler[vec] == NULL) - panic ("bad interrupt vector %d received\n",irq); + m68k_setup_auto_interrupt(sun3_inthandle); + m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7); + m68k_setup_user_interrupt(VEC_USER, 192, NULL); - vec_ints[vec]++; - return sun3_vechandler[vec](irq, vec_ids[vec], regs); - } else { - panic("sun3_process_int: unable to handle interrupt vector %d\n", - irq); - } + request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL); + request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL); + request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL); } diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c index 0920f5d..52fb174 100644 --- a/arch/m68k/sun3x/config.c +++ b/arch/m68k/sun3x/config.c @@ -52,17 +52,10 @@ void __init config_sun3x(void) sun3x_prom_init(); - mach_get_irq_list = show_sun3_interrupts; mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */ - mach_default_handler = &sun3_default_handler; mach_sched_init = sun3x_sched_init; mach_init_IRQ = sun3_init_IRQ; - enable_irq = sun3_enable_irq; - disable_irq = sun3_disable_irq; - mach_request_irq = sun3_request_irq; - mach_free_irq = sun3_free_irq; - mach_process_int = sun3_process_int; mach_gettimeoffset = sun3x_gettimeoffset; mach_reset = sun3x_reboot; diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index 3cde682..8b6e723 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -5,7 +5,7 @@ # mainmenu "uClinux/68k (w/o MMU) Kernel Configuration" -config M68KNOMMU +config M68K bool default y @@ -119,6 +119,11 @@ config M5307 help Motorola ColdFire 5307 processor support. +config M532x + bool "MCF532x" + help + Freescale (Motorola) ColdFire 532x processor support. + config M5407 bool "MCF5407" help @@ -133,125 +138,43 @@ config M527x config COLDFIRE bool - depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M5407) + depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407) default y -choice - prompt "CPU CLOCK Frequency" - default AUTO - -config CLOCK_AUTO - bool "AUTO" - ---help--- - Define the CPU clock frequency in use. On many boards you don't - really need to know, so you can select the AUTO option. On some - boards you need to know the real clock frequency to determine other - system timing (for example baud rate dividors, etc). Some processors - have an internal PLL and you can select a frequency to run at. - You need to know a little about the internals of your processor to - set this. If in doubt choose the AUTO option. - -config CLOCK_11MHz - bool "11MHz" - help - Select a 11MHz CPU clock frequency. - -config CLOCK_16MHz - bool "16MHz" - help - Select a 16MHz CPU clock frequency. - -config CLOCK_20MHz - bool "20MHz" - help - Select a 20MHz CPU clock frequency. - -config CLOCK_24MHz - bool "24MHz" - help - Select a 24MHz CPU clock frequency. - -config CLOCK_25MHz - bool "25MHz" - help - Select a 25MHz CPU clock frequency. - -config CLOCK_33MHz - bool "33MHz" - help - Select a 33MHz CPU clock frequency. - -config CLOCK_40MHz - bool "40MHz" - help - Select a 40MHz CPU clock frequency. - -config CLOCK_45MHz - bool "45MHz" - help - Select a 45MHz CPU clock frequency. - -config CLOCK_48MHz - bool "48MHz" - help - Select a 48MHz CPU clock frequency. - -config CLOCK_50MHz - bool "50MHz" - help - Select a 50MHz CPU clock frequency. - -config CLOCK_54MHz - bool "54MHz" - help - Select a 54MHz CPU clock frequency. - -config CLOCK_60MHz - bool "60MHz" - help - Select a 60MHz CPU clock frequency. - -config CLOCK_62_5MHz - bool "62.5MHz" - help - Select a 62.5MHz CPU clock frequency. - -config CLOCK_64MHz - bool "64MHz" - help - Select a 64MHz CPU clock frequency. - -config CLOCK_66MHz - bool "66MHz" - help - Select a 66MHz CPU clock frequency. - -config CLOCK_70MHz - bool "70MHz" - help - Select a 70MHz CPU clock frequency. - -config CLOCK_100MHz - bool "100MHz" - help - Select a 100MHz CPU clock frequency. - -config CLOCK_140MHz - bool "140MHz" - help - Select a 140MHz CPU clock frequency. - -config CLOCK_150MHz - bool "150MHz" - help - Select a 150MHz CPU clock frequency. - -config CLOCK_166MHz - bool "166MHz" +config CLOCK_SET + bool "Enable setting the CPU clock frequency" + default n help - Select a 166MHz CPU clock frequency. - -endchoice + On some CPU's you do not need to know what the core CPU clock + frequency is. On these you can disable clock setting. On some + traditional 68K parts, and on all ColdFire parts you need to set + the appropriate CPU clock frequency. On these devices many of the + onboard peripherals derive their timing from the master CPU clock + frequency. + +config CLOCK_FREQ + int "Set the core clock frequency" + default "66666666" + depends on CLOCK_SET + help + Define the CPU clock frequency in use. This is the core clock + frequency, it may or may not be the same as the external clock + crystal fitted to your board. Some processors have an internal + PLL and can have their frequency programmed at run time, others + use internal dividers. In gernal the kernel won't setup a PLL + if it is fitted (there are some expections). This value will be + specific to the exact CPU that you are using. + +config CLOCK_DIV + int "Set the core/bus clock divide ratio" + default "1" + depends on CLOCK_SET + help + On many SoC style CPUs the master CPU clock is also used to drive + on-chip peripherals. The clock that is distributed to these + peripherals is sometimes a fixed ratio of the master clock + frequency. If so then set this to the divider ration of the + master clock to the peripheral clock. If not sure then select 1. config OLDMASK bool "Old mask 5307 (1H55J) silicon" @@ -377,6 +300,12 @@ config COBRA5272 help Support for the senTec COBRA5272 board. +config AVNET5282 + bool "Avnet 5282 board support" + depends on M528x + help + Support for the Avnet 5282 board. + config M5282EVB bool "Motorola M5282EVB board support" depends on M528x @@ -419,6 +348,18 @@ config SECUREEDGEMP3 help Support for the SnapGear SecureEdge/MP3 platform. +config M5329EVB + bool "Freescale (Motorola) M5329EVB board support" + depends on M532x + help + Support for the Freescale (Motorola) M5329EVB board. + +config COBRA5329 + bool "senTec COBRA5329 board support" + depends on M532x + help + Support for the senTec COBRA5329 board. + config M5407C3 bool "Motorola M5407C3 board support" depends on M5407 @@ -487,7 +428,7 @@ config ARNEWSH config FREESCALE bool default y - depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3) + depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5329EVB || M5407C3) config HW_FEITH bool @@ -508,6 +449,11 @@ config SNEHA bool default y depends on CPU16B + +config AVNET + bool + default y + depends on (AVNET5282) config LARGE_ALLOCS bool "Allow allocating large blocks (> 1MB) of memory" @@ -526,38 +472,46 @@ config 4KSTACKS running more threads on a system and also reduces the pressure on the VM subsystem for higher order allocations. -choice - prompt "RAM size" - default AUTO - -config RAMAUTO - bool "AUTO" - ---help--- - Configure the RAM size on your platform. Many platforms can auto - detect this, on those choose the AUTO option. Otherwise set the - RAM size you intend using. +comment "RAM configuration" -config RAM4MB - bool "4MiB" +config RAMBASE + hex "Address of the base of RAM" + default "0" help - Set RAM size to be 4MiB. + Define the address that RAM starts at. On many platforms this is + 0, the base of the address space. And this is the default. Some + platforms choose to setup their RAM at other addresses within the + processor address space. -config RAM8MB - bool "8MiB" +config RAMSIZE + hex "Size of RAM (in bytes)" + default "0x400000" help - Set RAM size to be 8MiB. + Define the size of the system RAM. If you select 0 then the + kernel will try to probe the RAM size at runtime. This is not + supported on all CPU types. -config RAM16MB - bool "16MiB" +config VECTORBASE + hex "Address of the base of system vectors" + default "0" help - Set RAM size to be 16MiB. + Define the address of the the system vectors. Commonly this is + put at the start of RAM, but it doesn't have to be. On ColdFire + platforms this address is programmed into the VBR register, thus + actually setting the address to use. -config RAM32MB - bool "32MiB" +config KERNELBASE + hex "Address of the base of kernel code" + default "0x400" help - Set RAM size to be 32MiB. - -endchoice + Typically on m68k systems the kernel will not start at the base + of RAM, but usually some small offset from it. Define the start + address of the kernel here. The most common setup will have the + processor vectors at the base of RAM and then the start of the + kernel. On some platforms some RAM is reserved for boot loaders + and the kernel starts after that. The 0x400 default was based on + a system with the RAM based at address 0, and leaving enough room + for the theoretical maximum number of 256 vectors. choice prompt "RAM bus width" @@ -565,7 +519,7 @@ choice config RAMAUTOBIT bool "AUTO" - ---help--- + help Select the physical RAM data bus size. Not needed on most platforms, so you can generally choose AUTO. @@ -599,7 +553,9 @@ config RAMKERNEL config ROMKERNEL bool "ROM" help - The kernel will be resident in FLASH/ROM when running. + The kernel will be resident in FLASH/ROM when running. This is + often referred to as Execute-in-Place (XIP), since the kernel + code executes from the position it is stored in the FLASH/ROM. endchoice diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c index 93120b9..99d038e 100644 --- a/arch/m68knommu/kernel/setup.c +++ b/arch/m68knommu/kernel/setup.c @@ -42,7 +42,6 @@ #ifdef CONFIG_BLK_DEV_INITRD #include #endif -unsigned long rom_length; unsigned long memory_start; unsigned long memory_end; @@ -56,29 +55,29 @@ static void dummy_waitbut(void) { } -void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) = NULL; -void (*mach_tick)( void ) = NULL; +void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)); +void (*mach_tick)( void ); /* machine dependent keyboard functions */ -int (*mach_keyb_init) (void) = NULL; -int (*mach_kbdrate) (struct kbd_repeat *) = NULL; -void (*mach_kbd_leds) (unsigned int) = NULL; +int (*mach_keyb_init) (void); +int (*mach_kbdrate) (struct kbd_repeat *); +void (*mach_kbd_leds) (unsigned int); /* machine dependent irq functions */ -void (*mach_init_IRQ) (void) = NULL; -irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL; -int (*mach_get_irq_list) (struct seq_file *, void *) = NULL; -void (*mach_process_int) (int irq, struct pt_regs *fp) = NULL; +void (*mach_init_IRQ) (void); +irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *); +int (*mach_get_irq_list) (struct seq_file *, void *); +void (*mach_process_int) (int irq, struct pt_regs *fp); void (*mach_trap_init) (void); /* machine dependent timer functions */ -unsigned long (*mach_gettimeoffset) (void) = NULL; -void (*mach_gettod) (int*, int*, int*, int*, int*, int*) = NULL; -int (*mach_hwclk) (int, struct hwclk_time*) = NULL; -int (*mach_set_clock_mmss) (unsigned long) = NULL; -void (*mach_mksound)( unsigned int count, unsigned int ticks ) = NULL; -void (*mach_reset)( void ) = NULL; +unsigned long (*mach_gettimeoffset) (void); +void (*mach_gettod) (int*, int*, int*, int*, int*, int*); +int (*mach_hwclk) (int, struct hwclk_time*); +int (*mach_set_clock_mmss) (unsigned long); +void (*mach_mksound)( unsigned int count, unsigned int ticks ); +void (*mach_reset)( void ); void (*waitbut)(void) = dummy_waitbut; -void (*mach_debug_init)(void) = NULL; -void (*mach_halt)( void ) = NULL; -void (*mach_power_off)( void ) = NULL; +void (*mach_debug_init)(void); +void (*mach_halt)( void ); +void (*mach_power_off)( void ); #ifdef CONFIG_M68000 @@ -129,6 +128,9 @@ #endif #if defined(CONFIG_M5307) #define CPU "COLDFIRE(m5307)" #endif +#if defined(CONFIG_M532x) + #define CPU "COLDFIRE(m532x)" +#endif #if defined(CONFIG_M5407) #define CPU "COLDFIRE(m5407)" #endif @@ -267,34 +269,6 @@ #endif paging_init(); } -int get_cpuinfo(char * buffer) -{ - char *cpu, *mmu, *fpu; - u_long clockfreq; - - cpu = CPU; - mmu = "none"; - fpu = "none"; - -#ifdef CONFIG_COLDFIRE - clockfreq = (loops_per_jiffy*HZ)*3; -#else - clockfreq = (loops_per_jiffy*HZ)*16; -#endif - - return(sprintf(buffer, "CPU:\t\t%s\n" - "MMU:\t\t%s\n" - "FPU:\t\t%s\n" - "Clocking:\t%lu.%1luMHz\n" - "BogoMips:\t%lu.%02lu\n" - "Calibration:\t%lu loops\n", - cpu, mmu, fpu, - clockfreq/1000000,(clockfreq/100000)%10, - (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100, - (loops_per_jiffy*HZ))); - -} - /* * Get CPU information for use by the procfs. */ diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c index e1b3aa3..437f8c6 100644 --- a/arch/m68knommu/kernel/signal.c +++ b/arch/m68knommu/kernel/signal.c @@ -553,7 +553,7 @@ get_sigframe(struct k_sigaction *ka, str /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (!on_sig_stack(usp)) + if (!sas_ss_flags(usp)) usp = current->sas_ss_sp + current->sas_ss_size; } return (void *)((usp - frame_size) & -8UL); @@ -608,7 +608,7 @@ adjust_stack: if (regs->stkadj) { struct pt_regs *tregs = (struct pt_regs *)((ulong)regs + regs->stkadj); -#if DEBUG +#if defined(DEBUG) printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj); #endif /* This must be copied with decreasing addresses to @@ -678,7 +678,7 @@ adjust_stack: if (regs->stkadj) { struct pt_regs *tregs = (struct pt_regs *)((ulong)regs + regs->stkadj); -#if DEBUG +#if defined(DEBUG) printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj); #endif /* This must be copied with decreasing addresses to diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c index 5bc0684..44ff74e 100644 --- a/arch/m68knommu/kernel/traps.c +++ b/arch/m68knommu/kernel/traps.c @@ -93,12 +93,12 @@ asmlinkage void buserr_c(struct frame *f if (user_mode(&fp->ptregs)) current->thread.esp0 = (unsigned long) fp; -#if DEBUG +#if defined(DEBUG) printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format); #endif die_if_kernel("bad frame format",&fp->ptregs,0); -#if DEBUG +#if defined(DEBUG) printk(KERN_DEBUG "Unknown SIGSEGV - 4\n"); #endif force_sig(SIGSEGV, current); diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S index a331cc9..6a2f0c6 100644 --- a/arch/m68knommu/kernel/vmlinux.lds.S +++ b/arch/m68knommu/kernel/vmlinux.lds.S @@ -1,7 +1,7 @@ /* * vmlinux.lds.S -- master linker script for m68knommu arch * - * (C) Copyright 2002-2004, Greg Ungerer + * (C) Copyright 2002-2006, Greg Ungerer * * This ends up looking compilcated, because of the number of * address variations for ram and rom/flash layouts. The real @@ -22,13 +22,7 @@ #define ROMVEC_LENGTH 0x10400 #define ROM_START 0x10c10400 #define ROM_LENGTH 0xfec00 #define ROM_END 0x10d00000 -#define RAMVEC_START 0x00000000 -#define RAMVEC_LENGTH 0x400 -#define RAM_START 0x10000400 -#define RAM_LENGTH 0xffc00 -#define RAM_END 0x10100000 -#define _ramend _ram_end_notused -#define DATA_ADDR RAM_START +#define DATA_ADDR CONFIG_KERNELBASE #endif /* @@ -41,11 +35,6 @@ #define ROMVEC_LENGTH 0x400 #define ROM_START 0x10c10400 #define ROM_LENGTH 0x1efc00 #define ROM_END 0x10e00000 -#define RAMVEC_START 0x00000000 -#define RAMVEC_LENGTH 0x400 -#define RAM_START 0x00020400 -#define RAM_LENGTH 0x7dfc00 -#define RAM_END 0x00800000 #endif #ifdef CONFIG_ROMKERNEL #define ROMVEC_START 0x10c10000 @@ -53,11 +42,6 @@ #define ROMVEC_LENGTH 0x400 #define ROM_START 0x10c10400 #define ROM_LENGTH 0x1efc00 #define ROM_END 0x10e00000 -#define RAMVEC_START 0x00000000 -#define RAMVEC_LENGTH 0x400 -#define RAM_START 0x00020000 -#define RAM_LENGTH 0x600000 -#define RAM_END 0x00800000 #endif #ifdef CONFIG_HIMEMKERNEL #define ROMVEC_START 0x00600000 @@ -65,141 +49,28 @@ #define ROMVEC_LENGTH 0x400 #define ROM_START 0x00600400 #define ROM_LENGTH 0x1efc00 #define ROM_END 0x007f0000 -#define RAMVEC_START 0x00000000 -#define RAMVEC_LENGTH 0x400 -#define RAM_START 0x00020000 -#define RAM_LENGTH 0x5e0000 -#define RAM_END 0x00600000 #endif #endif -#ifdef CONFIG_DRAGEN2 -#define RAM_START 0x10000 -#define RAM_LENGTH 0x7f0000 -#endif - #ifdef CONFIG_UCQUICC #define ROMVEC_START 0x00000000 #define ROMVEC_LENGTH 0x404 #define ROM_START 0x00000404 #define ROM_LENGTH 0x1ff6fc #define ROM_END 0x00200000 -#define RAMVEC_START 0x00200000 -#define RAMVEC_LENGTH 0x404 -#define RAM_START 0x00200404 -#define RAM_LENGTH 0x1ff6fc -#define RAM_END 0x00400000 -#endif - -/* - * The standard Arnewsh 5206 board only has 1MiB of ram. Not normally - * enough to be useful. Assume the user has fitted something larger, - * at least 4MiB in size. No point in not letting the kernel completely - * link, it will be obvious if it is too big when they go to load it. - */ -#if defined(CONFIG_ARN5206) -#define RAM_START 0x10000 -#define RAM_LENGTH 0x3f0000 -#endif - -/* - * The Motorola 5206eLITE board only has 1MiB of static RAM. - */ -#if defined(CONFIG_ELITE) -#define RAM_START 0x30020000 -#define RAM_LENGTH 0xe0000 -#endif - -/* - * All the Motorola eval boards have the same basic arrangement. - * The end of RAM will vary depending on how much ram is fitted, - * but this isn't important here, we assume at least 4MiB. - */ -#if defined(CONFIG_M5206eC3) || defined(CONFIG_M5249C3) || \ - defined(CONFIG_M5272C3) || defined(CONFIG_M5307C3) || \ - defined(CONFIG_ARN5307) || defined(CONFIG_M5407C3) || \ - defined(CONFIG_M5271EVB) || defined(CONFIG_M5275EVB) || \ - defined(CONFIG_M5235EVB) -#define RAM_START 0x20000 -#define RAM_LENGTH 0x3e0000 -#endif - -/* - * The Freescale 5208EVB board has 32MB of RAM. - */ -#if defined(CONFIG_M5208EVB) -#define RAM_START 0x40020000 -#define RAM_LENGTH 0x01fe0000 -#endif - -/* - * The senTec COBRA5272 board has nearly the same memory layout as - * the M5272C3. We assume 16MiB ram. - */ -#if defined(CONFIG_COBRA5272) -#define RAM_START 0x20000 -#define RAM_LENGTH 0xfe0000 -#endif - -#if defined(CONFIG_M5282EVB) -#define RAM_START 0x10000 -#define RAM_LENGTH 0x3f0000 -#endif - -/* - * The senTec COBRA5282 board has the same memory layout as the M5282EVB. - */ -#if defined(CONFIG_COBRA5282) -#define RAM_START 0x10000 -#define RAM_LENGTH 0x3f0000 -#endif - - -/* - * The EMAC SoM-5282EM module. - */ -#if defined(CONFIG_SOM5282EM) -#define RAM_START 0x10000 -#define RAM_LENGTH 0xff0000 -#endif - - -/* - * These flash boot boards use all of ram for operation. Again the - * actual memory size is not important here, assume at least 4MiB. - * They currently have no support for running in flash. - */ -#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ - defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \ - defined(CONFIG_HW_FEITH) -#define RAM_START 0x400 -#define RAM_LENGTH 0x3ffc00 -#endif - -/* - * Sneha Boards mimimun memory - * The end of RAM will vary depending on how much ram is fitted, - * but this isn't important here, we assume at least 4MiB. - */ -#if defined(CONFIG_CPU16B) -#define RAM_START 0x20000 -#define RAM_LENGTH 0x3e0000 -#endif - -#if defined(CONFIG_MOD5272) -#define RAM_START 0x02000000 -#define RAM_LENGTH 0x00800000 -#define RAMVEC_START 0x20000000 -#define RAMVEC_LENGTH 0x00000400 #endif #if defined(CONFIG_RAMKERNEL) +#define RAM_START CONFIG_KERNELBASE +#define RAM_LENGTH (CONFIG_RAMBASE + CONFIG_RAMSIZE - CONFIG_KERNELBASE) #define TEXT ram #define DATA ram #define INIT ram #define BSS ram #endif #if defined(CONFIG_ROMKERNEL) || defined(CONFIG_HIMEMKERNEL) +#define RAM_START CONFIG_RAMBASE +#define RAM_LENGTH CONFIG_RAMSIZE #define TEXT rom #define DATA ram #define INIT ram @@ -215,13 +86,7 @@ OUTPUT_ARCH(m68k) ENTRY(_start) MEMORY { -#ifdef RAMVEC_START - ramvec : ORIGIN = RAMVEC_START, LENGTH = RAMVEC_LENGTH -#endif ram : ORIGIN = RAM_START, LENGTH = RAM_LENGTH -#ifdef RAM_END - eram : ORIGIN = RAM_END, LENGTH = 0 -#endif #ifdef ROM_START romvec : ORIGIN = ROMVEC_START, LENGTH = ROMVEC_LENGTH rom : ORIGIN = ROM_START, LENGTH = ROM_LENGTH @@ -308,12 +173,6 @@ #ifdef ROM_END __rom_end = . ; } > erom #endif -#ifdef RAMVEC_START - . = RAMVEC_START ; - .ramvec : { - __ramvec = .; - } > ramvec -#endif .data DATA_ADDR : { . = ALIGN(4); @@ -373,12 +232,5 @@ #endif _ebss = . ; } > BSS -#ifdef RAM_END - . = RAM_END ; - .eram : { - __ramend = . ; - _ramend = . ; - } > eram -#endif } diff --git a/arch/m68knommu/mm/init.c b/arch/m68knommu/mm/init.c index d79503f..70d1653 100644 --- a/arch/m68knommu/mm/init.c +++ b/arch/m68knommu/mm/init.c @@ -63,8 +63,6 @@ static unsigned long empty_bad_page; unsigned long empty_zero_page; -extern unsigned long rom_length; - void show_mem(void) { unsigned long i; @@ -178,11 +176,9 @@ #endif initk = (&__init_begin - &__init_end) >> 10; tmp = nr_free_pages() << PAGE_SHIFT; - printk(KERN_INFO "Memory available: %luk/%luk RAM, %luk/%luk ROM (%dk kernel code, %dk data)\n", + printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n", tmp >> 10, len >> 10, - (rom_length > 0) ? ((rom_length >> 10) - codek) : 0, - rom_length >> 10, codek, datak ); diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile index 8d1619d..2fd37dc 100644 --- a/arch/m68knommu/platform/5307/Makefile +++ b/arch/m68knommu/platform/5307/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_M5249) += timers.o obj-$(CONFIG_M527x) += pit.o obj-$(CONFIG_M5272) += timers.o obj-$(CONFIG_M5307) += config.o timers.o +obj-$(CONFIG_M532x) += timers.o obj-$(CONFIG_M528x) += pit.o obj-$(CONFIG_M5407) += timers.o diff --git a/arch/m68knommu/platform/5307/entry.S b/arch/m68knommu/platform/5307/entry.S index 89b180d..9ddf547 100644 --- a/arch/m68knommu/platform/5307/entry.S +++ b/arch/m68knommu/platform/5307/entry.S @@ -4,8 +4,8 @@ * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) * Copyright (C) 1998 D. Jeff Dionne , * Kenneth Albanowski , - * Copyright (C) 2000 Lineo Inc. (www.lineo.com) - * Copyright (C) 2004 Macq Electronique SA. (www.macqel.com) + * Copyright (C) 2000 Lineo Inc. (www.lineo.com) + * Copyright (C) 2004-2006 Macq Electronique SA. (www.macqel.com) * * Based on: * @@ -56,32 +56,27 @@ sw_usp: .globl inthandler .globl fasthandler +enosys: + mov.l #sys_ni_syscall,%d3 + bra 1f + ENTRY(system_call) SAVE_ALL move #0x2000,%sr /* enable intrs again */ - movel #-LENOSYS,%d2 - movel %d2,PT_D0(%sp) /* default return value in d0 */ - /* original D0 is in orig_d0 */ - movel %d0,%d2 - - /* save top of frame */ - pea %sp@ - jbsr set_esp0 - addql #4,%sp - - cmpl #NR_syscalls,%d2 - jcc ret_from_exception + cmpl #NR_syscalls,%d0 + jcc enosys lea sys_call_table,%a0 - lsll #2,%d2 /* movel %a0@(%d2:l:4),%d3 */ - movel %a0@(%d2),%d3 - jeq ret_from_exception - lsrl #2,%d2 + lsll #2,%d0 /* movel %a0@(%d0:l:4),%d3 */ + movel %a0@(%d0),%d3 + jeq enosys +1: movel %sp,%d2 /* get thread_info pointer */ andl #-THREAD_SIZE,%d2 /* at start of kernel stack */ movel %d2,%a0 - btst #TIF_SYSCALL_TRACE,%a0@(TI_FLAGS) + movel %sp,%a0@(THREAD_ESP0) /* save top of frame */ + btst #(TIF_SYSCALL_TRACE%8),%a0@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8) bnes 1f movel %d3,%a0 @@ -126,8 +121,8 @@ Luser_return: jne Lwork_to_do /* still work to do */ Lreturn: - move #0x2700,%sr /* disable intrs */ - movel sw_usp,%a0 /* get usp */ + move #0x2700,%sr /* disable intrs */ + movel sw_usp,%a0 /* get usp */ movel %sp@(PT_PC),%a0@- /* copy exception program counter */ movel %sp@(PT_FORMATVEC),%a0@-/* copy exception format/vector/sr */ moveml %sp@,%d1-%d5/%a0-%a2 @@ -170,7 +165,7 @@ ENTRY(inthandler) movel %d0,%sp@(PT_ORIG_D0) addql #1,local_irq_count - movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */ + movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */ andl #0x03fc,%d0 /* mask out vector only */ leal per_cpu__kstat+STAT_IRQ,%a0 @@ -184,7 +179,7 @@ ENTRY(inthandler) movel %sp,%sp@- /* push regs arg onto stack */ movel %a0@(8),%sp@- /* push devid arg */ - movel %d0,%sp@- /* push vector # on stack */ + movel %d0,%sp@- /* push vector # on stack */ movel %a0@,%a0 /* get function to call */ jbsr %a0@ /* call vector handler */ @@ -201,7 +196,7 @@ ENTRY(inthandler) ENTRY(fasthandler) SAVE_LOCAL - movew %sp@(PT_FORMATVEC),%d0 + movew %sp@(PT_FORMATVEC),%d0 andl #0x03fc,%d0 /* mask out vector only */ leal per_cpu__kstat+STAT_IRQ,%a0 @@ -210,7 +205,7 @@ ENTRY(fasthandler) movel %sp,%sp@- /* push regs arg onto stack */ clrl %sp@- /* push devid arg */ lsrl #2,%d0 /* calculate real vector # */ - movel %d0,%sp@- /* push vector # on stack */ + movel %d0,%sp@- /* push vector # on stack */ lsll #4,%d0 /* adjust for array offset */ lea irq_list,%a0 @@ -265,4 +260,3 @@ ENTRY(resume) movew %a1@(TASK_THREAD+THREAD_SR),%d0 /* restore thread status reg */ movew %d0, %sr rts - diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S index c30c462..1d9eb30 100644 --- a/arch/m68knommu/platform/5307/head.S +++ b/arch/m68knommu/platform/5307/head.S @@ -3,7 +3,7 @@ /* * head.S -- common startup code for ColdFire CPUs. * - * (C) Copyright 1999-2004, Greg Ungerer (gerg@snapgear.com). + * (C) Copyright 1999-2006, Greg Ungerer . */ /*****************************************************************************/ @@ -19,47 +19,15 @@ #include /*****************************************************************************/ /* - * Define fixed memory sizes. Configuration of a fixed memory size - * overrides everything else. If the user defined a size we just - * blindly use it (they know what they are doing right :-) - */ -#if defined(CONFIG_RAM32MB) -#define MEM_SIZE 0x02000000 /* memory size 32Mb */ -#elif defined(CONFIG_RAM16MB) -#define MEM_SIZE 0x01000000 /* memory size 16Mb */ -#elif defined(CONFIG_RAM8MB) -#define MEM_SIZE 0x00800000 /* memory size 8Mb */ -#elif defined(CONFIG_RAM4MB) -#define MEM_SIZE 0x00400000 /* memory size 4Mb */ -#elif defined(CONFIG_RAM1MB) -#define MEM_SIZE 0x00100000 /* memory size 1Mb */ -#endif - -/* - * Memory size exceptions for special cases. Some boards may be set - * for auto memory sizing, but we can't do it that way for some reason. - * For example the 5206eLITE board has static RAM, and auto-detecting - * the SDRAM will do you no good at all. Same goes for the MOD5272. - */ -#ifdef CONFIG_RAMAUTO -#if defined(CONFIG_M5206eLITE) -#define MEM_SIZE 0x00100000 /* 1MiB default memory */ -#endif -#if defined(CONFIG_MOD5272) -#define MEM_SIZE 0x00800000 /* 8MiB default memory */ -#endif -#endif /* CONFIG_RAMAUTO */ - - -/* - * If we don't have a fixed memory size now, then lets build in code + * If we don't have a fixed memory size, then lets build in code * to auto detect the DRAM size. Obviously this is the prefered - * method, and should work for most boards (it won't work for those - * that do not have their RAM starting at address 0). + * method, and should work for most boards. It won't work for those + * that do not have their RAM starting at address 0, and it only + * works on SDRAM (not boards fitted with SRAM). */ -#if defined(MEM_SIZE) +#if CONFIG_RAMSIZE != 0 .macro GET_MEM_SIZE - movel #MEM_SIZE,%d0 /* hard coded memory size */ + movel #CONFIG_RAMSIZE,%d0 /* hard coded memory size */ .endm #elif defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \ @@ -98,37 +66,7 @@ #elif defined(CONFIG_M5272) .endm #else -#error "ERROR: I don't know how to determine your boards memory size?" -#endif - - -/* - * Most ColdFire boards have their DRAM starting at address 0. - * Notable exception is the 5206eLITE board, another is the MOD5272. - */ -#if defined(CONFIG_M5206eLITE) -#define MEM_BASE 0x30000000 -#endif -#if defined(CONFIG_MOD5272) -#define MEM_BASE 0x02000000 -#define VBR_BASE 0x20000000 /* vectors in SRAM */ -#endif -#if defined(CONFIG_M5208EVB) -#define MEM_BASE 0x40000000 -#endif - -#ifndef MEM_BASE -#define MEM_BASE 0x00000000 /* memory base at address 0 */ -#endif - -/* - * The default location for the vectors is at the base of RAM. - * Some boards might like to use internal SRAM or something like - * that. If no board specific header defines an alternative then - * use the base of RAM. - */ -#ifndef VBR_BASE -#define VBR_BASE MEM_BASE /* vector address */ +#error "ERROR: I don't know how to probe your boards memory size?" #endif /*****************************************************************************/ @@ -191,11 +129,11 @@ _start: * Create basic memory configuration. Set VBR accordingly, * and size memory. */ - movel #VBR_BASE,%a7 + movel #CONFIG_VECTORBASE,%a7 movec %a7,%VBR /* set vectors addr */ movel %a7,_ramvec - movel #MEM_BASE,%a7 /* mark the base of RAM */ + movel #CONFIG_RAMBASE,%a7 /* mark the base of RAM */ movel %a7,_rambase GET_MEM_SIZE /* macro code determines size */ diff --git a/arch/m68knommu/platform/5307/pit.c b/arch/m68knommu/platform/5307/pit.c index 323f267..ef17474 100644 --- a/arch/m68knommu/platform/5307/pit.c +++ b/arch/m68knommu/platform/5307/pit.c @@ -1,11 +1,11 @@ /***************************************************************************/ /* - * pit.c -- Motorola ColdFire PIT timer. Currently this type of - * hardware timer only exists in the Motorola ColdFire + * pit.c -- Freescale ColdFire PIT timer. Currently this type of + * hardware timer only exists in the Freescale ColdFire * 5270/5271, 5282 and other CPUs. * - * Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 1999-2006, Greg Ungerer (gerg@snapgear.com) * Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com) * */ @@ -18,6 +18,7 @@ #include #include #include #include +#include #include #include #include @@ -25,13 +26,20 @@ #include /***************************************************************************/ +/* + * By default use timer1 as the system clock timer. + */ +#define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a)) + +/***************************************************************************/ + void coldfire_pit_tick(void) { - volatile struct mcfpit *tp; + unsigned short pcsr; /* Reset the ColdFire timer */ - tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1); - tp->pcsr |= MCFPIT_PCSR_PIF; + pcsr = __raw_readw(TA(MCFPIT_PCSR)); + __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR)); } /***************************************************************************/ @@ -40,7 +48,6 @@ void coldfire_pit_init(irqreturn_t (*han { volatile unsigned char *icrp; volatile unsigned long *imrp; - volatile struct mcfpit *tp; request_irq(MCFINT_VECBASE + MCFINT_PIT1, handler, SA_INTERRUPT, "ColdFire Timer", NULL); @@ -53,27 +60,23 @@ void coldfire_pit_init(irqreturn_t (*han *imrp &= ~MCFPIT_IMR_IBIT; /* Set up PIT timer 1 as poll clock */ - tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1); - tp->pcsr = MCFPIT_PCSR_DISABLE; - - tp->pmr = ((MCF_CLK / 2) / 64) / HZ; - tp->pcsr = MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW | - MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64; + __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); + __raw_writew(((MCF_CLK / 2) / 64) / HZ, TA(MCFPIT_PMR)); + __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW | + MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR)); } /***************************************************************************/ unsigned long coldfire_pit_offset(void) { - volatile struct mcfpit *tp; volatile unsigned long *ipr; unsigned long pmr, pcntr, offset; - tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1); ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR); - pmr = *(&tp->pmr); - pcntr = *(&tp->pcntr); + pmr = __raw_readw(TA(MCFPIT_PMR)); + pcntr = __raw_readw(TA(MCFPIT_PCNTR)); /* * If we are still in the first half of the upcount and a diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c index ef49596..83b8b89 100644 --- a/arch/m68knommu/platform/5307/timers.c +++ b/arch/m68knommu/platform/5307/timers.c @@ -14,6 +14,7 @@ #include #include #include #include +#include #include #include #include @@ -24,6 +25,11 @@ #include /***************************************************************************/ /* + * By default use timer1 as the system clock timer. + */ +#define TA(a) (MCF_MBAR + MCFTIMER_BASE1 + (a)) + +/* * Default the timer and vector to use for ColdFire. Some ColdFire * CPU's and some boards may want different. Their sub-architecture * startup code (in config.c) can change these if they want. @@ -32,8 +38,6 @@ unsigned int mcf_timervector = 29; unsigned int mcf_profilevector = 31; unsigned int mcf_timerlevel = 5; -static volatile struct mcftimer *mcf_timerp; - /* * These provide the underlying interrupt vector support. * Unfortunately it is a little different on each ColdFire. @@ -46,20 +50,17 @@ extern int mcf_timerirqpending(int timer void coldfire_tick(void) { /* Reset the ColdFire timer */ - mcf_timerp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; + __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, TA(MCFTIMER_TER)); } /***************************************************************************/ void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)) { - /* Set up an internal TIMER as poll clock */ - mcf_timerp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE1); - mcf_timerp->tmr = MCFTIMER_TMR_DISABLE; - - mcf_timerp->trr = (unsigned short) ((MCF_BUSCLK / 16) / HZ); - mcf_timerp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + __raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR)); + __raw_writew(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR)); + __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR)); request_irq(mcf_timervector, handler, SA_INTERRUPT, "timer", NULL); mcf_settimericr(1, mcf_timerlevel); @@ -75,13 +76,8 @@ unsigned long coldfire_timer_offset(void { unsigned long trr, tcn, offset; - /* - * The change to pointer and de-reference is to force the compiler - * to read the registers with a single 16bit access. Otherwise it - * does some crazy 8bit read combining. - */ - tcn = *(&mcf_timerp->tcn); - trr = *(&mcf_timerp->trr); + tcn = __raw_readw(TA(MCFTIMER_TCN)); + trr = __raw_readw(TA(MCFTIMER_TRR)); offset = (tcn * (1000000 / HZ)) / trr; /* Check if we just wrapped the counters and maybe missed a tick */ @@ -95,21 +91,23 @@ #ifdef CONFIG_HIGHPROFILE /***************************************************************************/ /* + * By default use timer2 as the profiler clock timer. + */ +#define PA(a) (MCF_MBAR + MCFTIMER_BASE2 + (a)) + +/* * Choose a reasonably fast profile timer. Make it an odd value to * try and get good coverage of kernal operations. */ #define PROFILEHZ 1013 -static volatile struct mcftimer *mcf_proftp; - /* * Use the other timer to provide high accuracy profiling info. */ - void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) { /* Reset ColdFire timer2 */ - mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; + __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER)); if (current->pid) profile_tick(CPU_PROFILING, regs); } @@ -121,12 +119,11 @@ void coldfire_profile_init(void) printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ); /* Set up TIMER 2 as high speed profile clock */ - mcf_proftp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE2); - mcf_proftp->tmr = MCFTIMER_TMR_DISABLE; + __raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR)); - mcf_proftp->trr = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ); - mcf_proftp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + __raw_writew(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR)); + __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR)); request_irq(mcf_profilevector, coldfire_profile_tick, (SA_INTERRUPT | IRQ_FLG_FAST), "profile timer", NULL); diff --git a/arch/m68knommu/platform/532x/Makefile b/arch/m68knommu/platform/532x/Makefile new file mode 100644 index 0000000..1230180 --- /dev/null +++ b/arch/m68knommu/platform/532x/Makefile @@ -0,0 +1,20 @@ +# +# Makefile for the m68knommu linux kernel. +# + +# +# If you want to play with the HW breakpoints then you will +# need to add define this, which will give you a stack backtrace +# on the console port whenever a DBG interrupt occurs. You have to +# set up you HW breakpoints to trigger a DBG interrupt: +# +# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT +# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT +# + +ifdef CONFIG_FULLDEBUG +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +endif + +#obj-y := config.o usb-mcf532x.o spi-mcf532x.o +obj-y := config.o diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68knommu/platform/532x/config.c new file mode 100644 index 0000000..ceef9bc --- /dev/null +++ b/arch/m68knommu/platform/532x/config.c @@ -0,0 +1,486 @@ +/***************************************************************************/ + +/* + * linux/arch/m68knommu/platform/532x/config.c + * + * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 2000, Lineo (www.lineo.com) + * Yaroslav Vinogradov yaroslav.vinogradov@freescale.com + * Copyright Freescale Semiconductor, Inc 2006 + * Copyright (c) 2006, emlix, Sebastian Hess + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +/***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/***************************************************************************/ + +void coldfire_tick(void); +void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); +unsigned long coldfire_timer_offset(void); +void coldfire_trap_init(void); +void coldfire_reset(void); + +extern unsigned int mcf_timervector; +extern unsigned int mcf_profilevector; +extern unsigned int mcf_timerlevel; + +/***************************************************************************/ + +/* + * DMA channel base address table. + */ +unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { }; +unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; + +/***************************************************************************/ + +void mcf_settimericr(unsigned int timer, unsigned int level) +{ + volatile unsigned char *icrp; + unsigned int icr; + unsigned char irq; + + if (timer <= 2) { + switch (timer) { + case 2: irq = 33; icr = MCFSIM_ICR_TIMER2; break; + default: irq = 32; icr = MCFSIM_ICR_TIMER1; break; + } + + icrp = (volatile unsigned char *) (MCF_MBAR + icr); + *icrp = level; + mcf_enable_irq0(irq); + } +} + +/***************************************************************************/ + +int mcf_timerirqpending(int timer) +{ + unsigned int imr = 0; + + switch (timer) { + case 1: imr = 0x1; break; + case 2: imr = 0x2; break; + default: break; + } + return (mcf_getiprh() & imr); +} + +/***************************************************************************/ + +void config_BSP(char *commandp, int size) +{ + mcf_setimr(MCFSIM_IMR_MASKALL); + +#if defined(CONFIG_BOOTPARAM) + strncpy(commandp, CONFIG_BOOTPARAM_STRING, size); + commandp[size-1] = 0; +#else + /* Copy command line from FLASH to local buffer... */ + memcpy(commandp, (char *) 0x4000, 4); + if(strncmp(commandp, "kcl ", 4) == 0){ + memcpy(commandp, (char *) 0x4004, size); + commandp[size-1] = 0; + } else { + memset(commandp, 0, size); + } +#endif + + mcf_timervector = 64+32; + mcf_profilevector = 64+33; + mach_sched_init = coldfire_timer_init; + mach_tick = coldfire_tick; + mach_gettimeoffset = coldfire_timer_offset; + mach_trap_init = coldfire_trap_init; + mach_reset = coldfire_reset; + +#ifdef MCF_BDM_DISABLE + /* + * Disable the BDM clocking. This also turns off most of the rest of + * the BDM device. This is good for EMC reasons. This option is not + * incompatible with the memory protection option. + */ + wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK); +#endif +} + +/***************************************************************************/ +/* Board initialization */ + +/********************************************************************/ +/* + * PLL min/max specifications + */ +#define MAX_FVCO 500000 /* KHz */ +#define MAX_FSYS 80000 /* KHz */ +#define MIN_FSYS 58333 /* KHz */ +#define FREF 16000 /* KHz */ + + +#define MAX_MFD 135 /* Multiplier */ +#define MIN_MFD 88 /* Multiplier */ +#define BUSDIV 6 /* Divider */ + +/* + * Low Power Divider specifications + */ +#define MIN_LPD (1 << 0) /* Divider (not encoded) */ +#define MAX_LPD (1 << 15) /* Divider (not encoded) */ +#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */ + +#define SYS_CLK_KHZ 80000 +#define SYSTEM_PERIOD 12.5 +/* + * SDRAM Timing Parameters + */ +#define SDRAM_BL 8 /* # of beats in a burst */ +#define SDRAM_TWR 2 /* in clocks */ +#define SDRAM_CASL 2.5 /* CASL in clocks */ +#define SDRAM_TRCD 2 /* in clocks */ +#define SDRAM_TRP 2 /* in clocks */ +#define SDRAM_TRFC 7 /* in clocks */ +#define SDRAM_TREFI 7800 /* in ns */ + +#define EXT_SRAM_ADDRESS (0xC0000000) +#define FLASH_ADDRESS (0x00000000) +#define SDRAM_ADDRESS (0x40000000) + +#define NAND_FLASH_ADDRESS (0xD0000000) + +int sys_clk_khz = 0; +int sys_clk_mhz = 0; + +void wtm_init(void); +void scm_init(void); +void gpio_init(void); +void fbcs_init(void); +void sdramc_init(void); +int clock_pll (int fsys, int flags); +int clock_limp (int); +int clock_exit_limp (void); +int get_sys_clock (void); + +asmlinkage void __init sysinit(void) +{ + sys_clk_khz = clock_pll(0, 0); + sys_clk_mhz = sys_clk_khz/1000; + + wtm_init(); + scm_init(); + gpio_init(); + fbcs_init(); + sdramc_init(); +} + +void wtm_init(void) +{ + /* Disable watchdog timer */ + MCF_WTM_WCR = 0; +} + +#define MCF_SCM_BCR_GBW (0x00000100) +#define MCF_SCM_BCR_GBR (0x00000200) + +void scm_init(void) +{ + /* All masters are trusted */ + MCF_SCM_MPR = 0x77777777; + + /* Allow supervisor/user, read/write, and trusted/untrusted + access to all slaves */ + MCF_SCM_PACRA = 0; + MCF_SCM_PACRB = 0; + MCF_SCM_PACRC = 0; + MCF_SCM_PACRD = 0; + MCF_SCM_PACRE = 0; + MCF_SCM_PACRF = 0; + + /* Enable bursts */ + MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW); +} + + +void fbcs_init(void) +{ + MCF_GPIO_PAR_CS = 0x0000003E; + + /* Latch chip select */ + MCF_FBCS1_CSAR = 0x10080000; + + MCF_FBCS1_CSCR = 0x002A3780; + MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V); + + /* Initialize latch to drive signals to inactive states */ + *((u16 *)(0x10080000)) = 0xFFFF; + + /* External SRAM */ + MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS; + MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16 + | MCF_FBCS_CSCR_AA + | MCF_FBCS_CSCR_SBM + | MCF_FBCS_CSCR_WS(1)); + MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K + | MCF_FBCS_CSMR_V); + + /* Boot Flash connected to FBCS0 */ + MCF_FBCS0_CSAR = FLASH_ADDRESS; + MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16 + | MCF_FBCS_CSCR_BEM + | MCF_FBCS_CSCR_AA + | MCF_FBCS_CSCR_SBM + | MCF_FBCS_CSCR_WS(7)); + MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M + | MCF_FBCS_CSMR_V); +} + +void sdramc_init(void) +{ + /* + * Check to see if the SDRAM has already been initialized + * by a run control tool + */ + if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) { + /* SDRAM chip select initialization */ + + /* Initialize SDRAM chip select */ + MCF_SDRAMC_SDCS0 = (0 + | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS) + | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE)); + + /* + * Basic configuration and initialization + */ + MCF_SDRAMC_SDCFG1 = (0 + | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 )) + | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1) + | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2)) + | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5)) + | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5)) + | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5)) + | MCF_SDRAMC_SDCFG1_WTLAT(3)); + MCF_SDRAMC_SDCFG2 = (0 + | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1) + | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR) + | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5)) + | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1)); + + + /* + * Precharge and enable write to SDMR + */ + MCF_SDRAMC_SDCR = (0 + | MCF_SDRAMC_SDCR_MODE_EN + | MCF_SDRAMC_SDCR_CKE + | MCF_SDRAMC_SDCR_DDR + | MCF_SDRAMC_SDCR_MUX(1) + | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5)) + | MCF_SDRAMC_SDCR_PS_16 + | MCF_SDRAMC_SDCR_IPALL); + + /* + * Write extended mode register + */ + MCF_SDRAMC_SDMR = (0 + | MCF_SDRAMC_SDMR_BNKAD_LEMR + | MCF_SDRAMC_SDMR_AD(0x0) + | MCF_SDRAMC_SDMR_CMD); + + /* + * Write mode register and reset DLL + */ + MCF_SDRAMC_SDMR = (0 + | MCF_SDRAMC_SDMR_BNKAD_LMR + | MCF_SDRAMC_SDMR_AD(0x163) + | MCF_SDRAMC_SDMR_CMD); + + /* + * Execute a PALL command + */ + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL; + + /* + * Perform two REF cycles + */ + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF; + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF; + + /* + * Write mode register and clear reset DLL + */ + MCF_SDRAMC_SDMR = (0 + | MCF_SDRAMC_SDMR_BNKAD_LMR + | MCF_SDRAMC_SDMR_AD(0x063) + | MCF_SDRAMC_SDMR_CMD); + + /* + * Enable auto refresh and lock SDMR + */ + MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN; + MCF_SDRAMC_SDCR |= (0 + | MCF_SDRAMC_SDCR_REF + | MCF_SDRAMC_SDCR_DQS_OE(0xC)); + } +} + +void gpio_init(void) +{ + /* Enable UART0 pins */ + MCF_GPIO_PAR_UART = ( 0 + | MCF_GPIO_PAR_UART_PAR_URXD0 + | MCF_GPIO_PAR_UART_PAR_UTXD0); + + /* Initialize TIN3 as a GPIO output to enable the write + half of the latch */ + MCF_GPIO_PAR_TIMER = 0x00; + MCF_GPIO_PDDR_TIMER = 0x08; + MCF_GPIO_PCLRR_TIMER = 0x0; + +} + +int clock_pll(int fsys, int flags) +{ + int fref, temp, fout, mfd; + u32 i; + + fref = FREF; + + if (fsys == 0) { + /* Return current PLL output */ + mfd = MCF_PLL_PFDR; + + return (fref * mfd / (BUSDIV * 4)); + } + + /* Check bounds of requested system clock */ + if (fsys > MAX_FSYS) + fsys = MAX_FSYS; + if (fsys < MIN_FSYS) + fsys = MIN_FSYS; + + /* Multiplying by 100 when calculating the temp value, + and then dividing by 100 to calculate the mfd allows + for exact values without needing to include floating + point libraries. */ + temp = 100 * fsys / fref; + mfd = 4 * BUSDIV * temp / 100; + + /* Determine the output frequency for selected values */ + fout = (fref * mfd / (BUSDIV * 4)); + + /* + * Check to see if the SDRAM has already been initialized. + * If it has then the SDRAM needs to be put into self refresh + * mode before reprogramming the PLL. + */ + if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) + /* Put SDRAM into self refresh mode */ + MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE; + + /* + * Initialize the PLL to generate the new system clock frequency. + * The device must be put into LIMP mode to reprogram the PLL. + */ + + /* Enter LIMP mode */ + clock_limp(DEFAULT_LPD); + + /* Reprogram PLL for desired fsys */ + MCF_PLL_PODR = (0 + | MCF_PLL_PODR_CPUDIV(BUSDIV/3) + | MCF_PLL_PODR_BUSDIV(BUSDIV)); + + MCF_PLL_PFDR = mfd; + + /* Exit LIMP mode */ + clock_exit_limp(); + + /* + * Return the SDRAM to normal operation if it is in use. + */ + if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) + /* Exit self refresh mode */ + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE; + + /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */ + MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH; + + /* wait for DQS logic to relock */ + for (i = 0; i < 0x200; i++) + ; + + return fout; +} + +int clock_limp(int div) +{ + u32 temp; + + /* Check bounds of divider */ + if (div < MIN_LPD) + div = MIN_LPD; + if (div > MAX_LPD) + div = MAX_LPD; + + /* Save of the current value of the SSIDIV so we don't + overwrite the value*/ + temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF)); + + /* Apply the divider to the system clock */ + MCF_CCM_CDR = ( 0 + | MCF_CCM_CDR_LPDIV(div) + | MCF_CCM_CDR_SSIDIV(temp)); + + MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP; + + return (FREF/(3*(1 << div))); +} + +int clock_exit_limp(void) +{ + int fout; + + /* Exit LIMP mode */ + MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP); + + /* Wait for PLL to lock */ + while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK)) + ; + + fout = get_sys_clock(); + + return fout; +} + +int get_sys_clock(void) +{ + int divider; + + /* Test to see if device is in LIMP mode */ + if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) { + divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF); + return (FREF/(2 << divider)); + } + else + return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4)); +} diff --git a/arch/m68knommu/platform/68328/head-pilot.S b/arch/m68knommu/platform/68328/head-pilot.S index c46775f..46b3604 100644 --- a/arch/m68knommu/platform/68328/head-pilot.S +++ b/arch/m68knommu/platform/68328/head-pilot.S @@ -21,7 +21,6 @@ #include .global _start .global _rambase -.global __ramvec .global _ramvec .global _ramstart .global _ramend @@ -121,7 +120,7 @@ L0: DBG_PUTC('B') /* Copy command line from beginning of RAM (+16) to end of bss */ - movel #__ramvec, %d7 + movel #CONFIG_VECTORBASE, %d7 addl #16, %d7 moveal %d7, %a0 moveal #_ebss, %a1 diff --git a/arch/m68knommu/platform/68328/head-ram.S b/arch/m68knommu/platform/68328/head-ram.S index 6bdc9bc..e8dc924 100644 --- a/arch/m68knommu/platform/68328/head-ram.S +++ b/arch/m68knommu/platform/68328/head-ram.S @@ -1,10 +1,7 @@ #include .global __main - .global __ram_start - .global __ram_end .global __rom_start - .global __rom_end .global _rambase .global _ramstart @@ -12,6 +9,7 @@ #include .global splash_bits .global _start .global _stext + .global _edata #define DEBUG #define ROM_OFFSET 0x10C00000 @@ -73,7 +71,7 @@ #endif /* DEBUG */ #ifdef CONFIG_RELOCATE /* Copy me to RAM */ moveal #__rom_start, %a0 - moveal #__ram_start, %a1 + moveal #_stext, %a1 moveal #_edata, %a2 /* Copy %a0 to %a1 until %a1 == %a2 */ diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e8ff09f..35e038a 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -119,6 +119,32 @@ config MIPS_MIRAGE select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_LITTLE_ENDIAN +config BASLER_EXCITE + bool "Basler eXcite smart camera support" + select DMA_COHERENT + select HW_HAS_PCI + select IRQ_CPU + select IRQ_CPU_RM7K + select IRQ_CPU_RM9K + select SERIAL_RM9000 + select SYS_HAS_CPU_RM9000 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + help + The eXcite is a smart camera platform manufactured by + Basler Vision Technologies AG + +config BASLER_EXCITE_PROTOTYPE + bool "Support for pre-release units" + depends on BASLER_EXCITE + default n + help + Pre-series (prototype) units are different from later ones in + some ways. Select this option if you have one of these. Please + note that a kernel built with this option selected will not be + able to run on normal units. + config MIPS_COBALT bool "Cobalt Server" select DMA_NONCOHERENT @@ -142,6 +168,9 @@ config MACH_DECSTATION select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_128HZ + select SYS_SUPPORTS_256HZ + select SYS_SUPPORTS_1024HZ help This enables support for DEC's MIPS based workstations. For details see the Linux/MIPS FAQ on and the @@ -239,6 +268,7 @@ config MACH_JAZZ select SYS_HAS_CPU_R4X00 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL + select SYS_SUPPORTS_100HZ help This a family of machines based on the MIPS R4030 chipset which was used by several vendors to build RISC/os and Windows NT workstations. @@ -327,6 +357,27 @@ config MIPS_SEAD This enables support for the MIPS Technologies SEAD evaluation board. +config WR_PPMC + bool "Support for Wind River PPMC board" + select IRQ_CPU + select BOOT_ELF32 + select DMA_NONCOHERENT + select HW_HAS_PCI + select MIPS_GT64120 + select SWAP_IO_SPACE + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_CPU_MIPS32_R2 + select SYS_HAS_CPU_MIPS64_R1 + select SYS_HAS_CPU_NEVADA + select SYS_HAS_CPU_RM7000 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_LITTLE_ENDIAN + help + This enables support for the Wind River MIPS32 4KC PPMC evaluation + board, which is based on GT64120 bridge chip. + config MIPS_SIM bool 'MIPS simulator (MIPSsim)' select DMA_NONCOHERENT @@ -438,53 +489,16 @@ config MIPS_XXS1500 config PNX8550_V2PCI bool "Philips PNX8550 based Viper2-PCI board" + depends on BROKEN select PNX8550 select SYS_SUPPORTS_LITTLE_ENDIAN config PNX8550_JBS bool "Philips PNX8550 based JBS board" + depends on BROKEN select PNX8550 select SYS_SUPPORTS_LITTLE_ENDIAN -config DDB5074 - bool "NEC DDB Vrc-5074 (EXPERIMENTAL)" - depends on EXPERIMENTAL - select DDB5XXX_COMMON - select DMA_NONCOHERENT - select HAVE_STD_PC_SERIAL_PORT - select HW_HAS_PCI - select IRQ_CPU - select I8259 - select ISA - select SYS_HAS_CPU_R5000 - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL - select SYS_SUPPORTS_LITTLE_ENDIAN - help - This enables support for the VR5000-based NEC DDB Vrc-5074 - evaluation board. - -config DDB5476 - bool "NEC DDB Vrc-5476" - select DDB5XXX_COMMON - select DMA_NONCOHERENT - select HAVE_STD_PC_SERIAL_PORT - select HW_HAS_PCI - select IRQ_CPU - select I8259 - select ISA - select SYS_HAS_CPU_R5432 - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL - select SYS_SUPPORTS_LITTLE_ENDIAN - help - This enables support for the R5432-based NEC DDB Vrc-5476 - evaluation board. - - Features : kernel debugging, serial terminal, NFS root fs, on-board - ether port USB, AC97, PCI, PCI VGA card & framebuffer console, - IDE controller, PS2 keyboard, PS2 mouse, etc. - config DDB5477 bool "NEC DDB Vrc-5477" select DDB5XXX_COMMON @@ -546,6 +560,20 @@ config QEMU simulate actual MIPS hardware platforms. More information on Qemu can be found at http://www.linux-mips.org/wiki/Qemu. +config MARKEINS + bool "Support for NEC EMMA2RH Mark-eins" + select DMA_NONCOHERENT + select HW_HAS_PCI + select IRQ_CPU + select SWAP_IO_SPACE + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_HAS_CPU_R5000 + help + This enables support for the R5432-based NEC Mark-eins + boards with R5500 CPU. + config SGI_IP22 bool "SGI IP22 (Indy/Indigo2)" select ARC @@ -555,6 +583,7 @@ config SGI_IP22 select HW_HAS_EISA select IP22_CPU_SCACHE select IRQ_CPU + select NO_ISA if ISA select SWAP_IO_SPACE select SYS_HAS_CPU_R4X00 select SYS_HAS_CPU_R5000 @@ -577,6 +606,7 @@ config SGI_IP27 select SYS_HAS_CPU_R10000 select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_NUMA help This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics workstations. To compile a Linux kernel that runs on these, say Y @@ -707,8 +737,8 @@ config SIBYTE_CRHONE config SNI_RM200_PCI bool "SNI RM200 PCI" - select ARC - select ARC32 + select ARC if CPU_LITTLE_ENDIAN + select ARC32 if CPU_LITTLE_ENDIAN select ARCH_MAY_HAVE_PC_FDC select BOOT_ELF32 select DMA_NONCOHERENT @@ -719,10 +749,13 @@ config SNI_RM200_PCI select I8253 select I8259 select ISA + select SWAP_IO_SPACE if CPU_BIG_ENDIAN select SYS_HAS_CPU_R4X00 + select SYS_HAS_CPU_R5000 + select R5000_CPU_SCACHE select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL - select SYS_SUPPORTS_BIG_ENDIAN if EXPERIMENTAL + select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_HIGHMEM select SYS_SUPPORTS_LITTLE_ENDIAN help @@ -979,6 +1012,11 @@ config SOC_PNX8550 config SWAP_IO_SPACE bool +config EMMA2RH + bool + depends on MARKEINS + default y + # # Unfortunately not all GT64120 systems run the chip at the same clock. # As the user for the clock rate and try to minimize the available options. @@ -1607,6 +1645,28 @@ config ARCH_FLATMEM_ENABLE def_bool y depends on !NUMA +config ARCH_DISCONTIGMEM_ENABLE + bool + default y if SGI_IP27 + help + Say Y to upport efficient handling of discontiguous physical memory, + for architectures which are either NUMA (Non-Uniform Memory Access) + or have huge holes in the physical address space for other reasons. + See for more. + +config NUMA + bool "NUMA Support" + depends on SYS_SUPPORTS_NUMA + help + Say Y to compile the kernel to support NUMA (Non-Uniform Memory + Access). This option improves performance on systems with more + than two nodes; on two node systems it is generally better to + leave it disabled; on single node systems disable this option + disabled. + +config SYS_SUPPORTS_NUMA + bool + config NODES_SHIFT int default "6" @@ -1651,6 +1711,77 @@ config NR_CPUS This is purely to save memory - each supported CPU adds approximately eight kilobytes to the kernel image. +# +# Timer Interrupt Frequency Configuration +# + +choice + prompt "Timer frequency" + default HZ_250 + help + Allows the configuration of the timer frequency. + + config HZ_48 + bool "48 HZ" if SYS_SUPPORTS_48HZ + + config HZ_100 + bool "100 HZ" if SYS_SUPPORTS_100HZ || SYS_SUPPORTS_ARBIT_HZ + + config HZ_128 + bool "128 HZ" if SYS_SUPPORTS_128HZ || SYS_SUPPORTS_ARBIT_HZ + + config HZ_250 + bool "250 HZ" if SYS_SUPPORTS_250HZ || SYS_SUPPORTS_ARBIT_HZ + + config HZ_256 + bool "256 HZ" if SYS_SUPPORTS_256HZ || SYS_SUPPORTS_ARBIT_HZ + + config HZ_1000 + bool "1000 HZ" if SYS_SUPPORTS_1000HZ || SYS_SUPPORTS_ARBIT_HZ + + config HZ_1024 + bool "1024 HZ" if SYS_SUPPORTS_1024HZ || SYS_SUPPORTS_ARBIT_HZ + +endchoice + +config SYS_SUPPORTS_48HZ + bool + +config SYS_SUPPORTS_100HZ + bool + +config SYS_SUPPORTS_128HZ + bool + +config SYS_SUPPORTS_250HZ + bool + +config SYS_SUPPORTS_256HZ + bool + +config SYS_SUPPORTS_1000HZ + bool + +config SYS_SUPPORTS_1024HZ + bool + +config SYS_SUPPORTS_ARBIT_HZ + bool + default y if !SYS_SUPPORTS_48HZ && !SYS_SUPPORTS_100HZ && \ + !SYS_SUPPORTS_128HZ && !SYS_SUPPORTS_250HZ && \ + !SYS_SUPPORTS_256HZ && !SYS_SUPPORTS_1000HZ && \ + !SYS_SUPPORTS_1024HZ + +config HZ + int + default 48 if HZ_48 + default 100 if HZ_100 + default 128 if HZ_128 + default 250 if HZ_250 + default 256 if HZ_256 + default 1000 if HZ_1000 + default 1024 if HZ_1024 + source "kernel/Kconfig.preempt" config RTC_DS1742 @@ -1710,6 +1841,9 @@ # config ISA bool +config NO_ISA + bool + config EISA bool "EISA support" depends on HW_HAS_EISA @@ -1840,6 +1974,32 @@ config PM bool "Power Management support (EXPERIMENTAL)" depends on EXPERIMENTAL && SOC_AU1X00 +config APM + tristate "Advanced Power Management Emulation" + depends on PM + ---help--- + APM is a BIOS specification for saving power using several different + techniques. This is mostly useful for battery powered systems with + APM compliant BIOSes. If you say Y here, the system time will be + reset after a RESUME operation, the /proc/apm device will provide + battery status information, and user-space programs will receive + notification of APM "events" (e.g. battery status change). + + In order to use APM, you will need supporting software. For location + and more information, read and the + Battery Powered Linux mini-HOWTO, available from + . + + This driver does not spin down disk drives (see the hdparm(8) + manpage ("man 8 hdparm") for that), and it doesn't turn off + VESA-compliant "green" monitors. + + Generally, if you don't have a battery in your machine, there isn't + much point in using this driver and you should say N. If you get + random kernel OOPSes or reboots that don't seem to be related to + anything, try disabling/enabling this option (or disabling/enabling + APM in your BIOS). + endmenu source "net/Kconfig" diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 133900a..d593014 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -83,6 +83,8 @@ cflags-y += -msoft-float LDFLAGS_vmlinux += -G 0 -static -n -nostdlib MODFLAGS += -mlong-calls +cflags-y += -ffreestanding + # # We explicitly add the endianness specifier if needed, this allows # to compile kernels with a toolchain for the other endianness. We @@ -285,6 +287,13 @@ cflags-$(CONFIG_MIPS_EV96100) += -Iinclu load-$(CONFIG_MIPS_EV96100) += 0xffffffff80100000 # +# Wind River PPMC Board (4KC + GT64120) +# +core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/ +cflags-$(CONFIG_WR_PPMC) += -Iinclude/asm-mips/mach-wrppmc +load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 + +# # Globespan IVR eval board with QED 5231 CPU # core-$(CONFIG_ITE_BOARD_GEN) += arch/mips/ite-boards/generic/ @@ -379,6 +388,13 @@ cflags-$(CONFIG_MOMENCO_OCELOT_3) += -Ii load-$(CONFIG_MOMENCO_OCELOT_3) += 0xffffffff80100000 # +# Basler eXcite +# +core-$(CONFIG_BASLER_EXCITE) += arch/mips/basler/excite/ +cflags-$(CONFIG_BASLER_EXCITE) += -Iinclude/asm-mips/mach-excite +load-$(CONFIG_BASLER_EXCITE) += 0x80100000 + +# # Momentum Jaguar ATX # core-$(CONFIG_MOMENCO_JAGUAR_ATX) += arch/mips/momentum/jaguar_atx/ @@ -395,18 +411,6 @@ # core-$(CONFIG_DDB5XXX_COMMON) += arch/mips/ddb5xxx/common/ # -# NEC DDB Vrc-5074 -# -core-$(CONFIG_DDB5074) += arch/mips/ddb5xxx/ddb5074/ -load-$(CONFIG_DDB5074) += 0xffffffff80080000 - -# -# NEC DDB Vrc-5476 -# -core-$(CONFIG_DDB5476) += arch/mips/ddb5xxx/ddb5476/ -load-$(CONFIG_DDB5476) += 0xffffffff80080000 - -# # NEC DDB Vrc-5477 # core-$(CONFIG_DDB5477) += arch/mips/ddb5xxx/ddb5477/ @@ -468,6 +472,15 @@ libs-$(CONFIG_PNX8550_JBS) += arch/mips/ #cflags-$(CONFIG_PNX8550_JBS) += -Iinclude/asm-mips/mach-pnx8550 load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000 +# NEC EMMA2RH boards +# +core-$(CONFIG_EMMA2RH) += arch/mips/emma2rh/common/ +cflags-$(CONFIG_EMMA2RH) += -Iinclude/asm-mips/mach-emma2rh + +# NEC EMMA2RH Mark-eins +core-$(CONFIG_MARKEINS) += arch/mips/emma2rh/markeins/ +load-$(CONFIG_MARKEINS) += 0xffffffff88100000 + # # SGI IP22 (Indy/Indigo2) # diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c index 0b2c03c..5a1e368 100644 --- a/arch/mips/au1000/common/au1xxx_irqmap.c +++ b/arch/mips/au1000/common/au1xxx_irqmap.c @@ -55,7 +55,7 @@ #include * Careful if you change match 2 request! * The interrupt handler is called directly from the low level dispatch code. */ -au1xxx_irq_map_t au1xxx_ic0_map[] = { +au1xxx_irq_map_t __initdata au1xxx_ic0_map[] = { #if defined(CONFIG_SOC_AU1000) { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, @@ -220,5 +220,5 @@ #endif }; -int au1xxx_ic0_nr_irqs = sizeof(au1xxx_ic0_map)/sizeof(au1xxx_irq_map_t); +int __initdata au1xxx_ic0_nr_irqs = ARRAY_SIZE(au1xxx_ic0_map); diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c index 4e5a6e1..b1392ab 100644 --- a/arch/mips/au1000/common/pci.c +++ b/arch/mips/au1000/common/pci.c @@ -40,17 +40,17 @@ #include /* TBD */ static struct resource pci_io_resource = { - "pci IO space", - (u32)PCI_IO_START, - (u32)PCI_IO_END, - IORESOURCE_IO + .start = PCI_IO_START, + .end = PCI_IO_END, + .name = "PCI IO space", + .flags = IORESOURCE_IO }; static struct resource pci_mem_resource = { - "pci memory space", - (u32)PCI_MEM_START, - (u32)PCI_MEM_END, - IORESOURCE_MEM + .start = PCI_MEM_START, + .end = PCI_MEM_END, + .name = "PCI memory space", + .flags = IORESOURCE_MEM }; extern struct pci_ops au1x_pci_ops; diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c index 307e98c..97165b6 100644 --- a/arch/mips/au1000/common/setup.c +++ b/arch/mips/au1000/common/setup.c @@ -49,17 +49,13 @@ extern void __init board_setup(void); extern void au1000_restart(char *); extern void au1000_halt(void); extern void au1000_power_off(void); -extern struct resource ioport_resource; -extern struct resource iomem_resource; -extern void (*board_time_init)(void); extern void au1x_time_init(void); -extern void (*board_timer_setup)(struct irqaction *irq); extern void au1x_timer_setup(struct irqaction *irq); extern void au1xxx_time_init(void); extern void au1xxx_timer_setup(struct irqaction *irq); extern void set_cpuspec(void); -void __init plat_setup(void) +void __init plat_mem_setup(void) { struct cpu_spec *sp; char *argptr; diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index f74d66a..842e1b5 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -50,10 +50,6 @@ #include #include #include -extern void do_softirq(void); -extern volatile unsigned long wall_jiffies; -unsigned long missed_heart_beats = 0; - static unsigned long r4k_offset; /* Amount to increment compare reg each time */ static unsigned long r4k_cur; /* What counter should be at next timer irq */ int no_au1xxx_32khz; @@ -388,10 +384,9 @@ static unsigned long do_fast_pm_gettimeo } #endif -void au1xxx_timer_setup(struct irqaction *irq) +void __init au1xxx_timer_setup(struct irqaction *irq) { - unsigned int est_freq; - extern unsigned long (*do_gettimeoffset)(void); + unsigned int est_freq; printk("calculating r4koff... "); r4k_offset = cal_r4koff(); diff --git a/arch/mips/au1000/csb250/irqmap.c b/arch/mips/au1000/csb250/irqmap.c index 5cb1166..57d6040 100644 --- a/arch/mips/au1000/csb250/irqmap.c +++ b/arch/mips/au1000/csb250/irqmap.c @@ -47,7 +47,7 @@ #include #include #include -au1xxx_irq_map_t au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, @@ -57,4 +57,4 @@ au1xxx_irq_map_t au1xxx_irq_map[] = { { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 }, }; -int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c index f63024a..0138c5b 100644 --- a/arch/mips/au1000/db1x00/irqmap.c +++ b/arch/mips/au1000/db1x00/irqmap.c @@ -80,7 +80,7 @@ char irq_tab_alchemy[][5] __initdata = { #endif -au1xxx_irq_map_t au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { #ifndef CONFIG_MIPS_MIRAGE #ifdef CONFIG_MIPS_DB1550 @@ -101,4 +101,4 @@ #endif }; -int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/hydrogen3/irqmap.c b/arch/mips/au1000/hydrogen3/irqmap.c index 6eacaa0..14e1ed3 100644 --- a/arch/mips/au1000/hydrogen3/irqmap.c +++ b/arch/mips/au1000/hydrogen3/irqmap.c @@ -47,10 +47,10 @@ #include #include #include -au1xxx_irq_map_t au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { /* { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, */ { AU1000_GPIO_21, INTC_INT_LOW_LEVEL, 0 }, }; -int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c index f9a0a8b..4693a4e 100644 --- a/arch/mips/au1000/mtx-1/irqmap.c +++ b/arch/mips/au1000/mtx-1/irqmap.c @@ -58,7 +58,7 @@ char irq_tab_alchemy[][5] __initdata = { [7] = { -1, INTD, INTC, INTX, INTX}, /* IDSEL 07 - AdapterD-Slot1 (bottom) */ }; -au1xxx_irq_map_t au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, @@ -66,4 +66,4 @@ au1xxx_irq_map_t au1xxx_irq_map[] = { { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, }; -int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/au1000/pb1000/irqmap.c index a3c460e..156500b 100644 --- a/arch/mips/au1000/pb1000/irqmap.c +++ b/arch/mips/au1000/pb1000/irqmap.c @@ -47,8 +47,8 @@ #include #include #include -au1xxx_irq_map_t au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 }, }; -int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/au1000/pb1100/irqmap.c index 43be715..d986916 100644 --- a/arch/mips/au1000/pb1100/irqmap.c +++ b/arch/mips/au1000/pb1100/irqmap.c @@ -47,11 +47,11 @@ #include #include #include -au1xxx_irq_map_t au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card Fully_Interted# { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card STSCHG# { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card IRQ# { AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, // DC_IRQ# }; -int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c index 59e70e5..bacc0c6 100644 --- a/arch/mips/au1000/pb1200/irqmap.c +++ b/arch/mips/au1000/pb1200/irqmap.c @@ -55,11 +55,11 @@ #define PB1200_INT_BEGIN DB1200_INT_BEGI #define PB1200_INT_END DB1200_INT_END #endif -au1xxx_irq_map_t au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, // This is exteranl interrupt cascade }; -int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); /* * Support for External interrupts on the PbAu1200 Development platform. diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c index 8cb76c2..409d161 100644 --- a/arch/mips/au1000/pb1500/irqmap.c +++ b/arch/mips/au1000/pb1500/irqmap.c @@ -52,7 +52,7 @@ char irq_tab_alchemy[][5] __initdata = { [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */ }; -au1xxx_irq_map_t au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, @@ -60,4 +60,4 @@ au1xxx_irq_map_t au1xxx_irq_map[] = { { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, }; -int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c index 47c7a1c..24a9d18 100644 --- a/arch/mips/au1000/pb1550/irqmap.c +++ b/arch/mips/au1000/pb1550/irqmap.c @@ -52,9 +52,9 @@ char irq_tab_alchemy[][5] __initdata = { [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot 1 (right) */ }; -au1xxx_irq_map_t au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, }; -int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c index 52f2f7d..3844c64 100644 --- a/arch/mips/au1000/xxs1500/irqmap.c +++ b/arch/mips/au1000/xxs1500/irqmap.c @@ -47,7 +47,7 @@ #include #include #include -au1xxx_irq_map_t au1xxx_irq_map[] = { +au1xxx_irq_map_t __initdata au1xxx_irq_map[] = { { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, @@ -63,4 +63,4 @@ au1xxx_irq_map_t au1xxx_irq_map[] = { { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, }; -int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); +int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); diff --git a/arch/mips/basler/excite/Makefile b/arch/mips/basler/excite/Makefile new file mode 100644 index 0000000..519142c --- /dev/null +++ b/arch/mips/basler/excite/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for Basler eXcite +# + +obj-$(CONFIG_BASLER_EXCITE) += excite_irq.o excite_prom.o excite_setup.o \ + excite_device.o excite_procfs.o + +obj-$(CONFIG_KGDB) += excite_dbg_io.o +obj-m += excite_iodev.o diff --git a/arch/mips/basler/excite/excite_dbg_io.c b/arch/mips/basler/excite/excite_dbg_io.c new file mode 100644 index 0000000..83f6bdd --- /dev/null +++ b/arch/mips/basler/excite/excite_dbg_io.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2004 by Basler Vision Technologies AG + * Author: Thomas Koeller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_SERIAL_8250) && CONFIG_SERIAL_8250_NR_UARTS > 1 +#error Debug port used by serial driver +#endif + +#define UART_CLK 25000000 +#define BASE_BAUD (UART_CLK / 16) +#define REGISTER_BASE_0 0x0208UL +#define REGISTER_BASE_1 0x0238UL + +#define REGISTER_BASE_DBG REGISTER_BASE_1 + +#define CPRR 0x0004 +#define UACFG 0x0200 +#define UAINTS 0x0204 +#define UARBR (REGISTER_BASE_DBG + 0x0000) +#define UATHR (REGISTER_BASE_DBG + 0x0004) +#define UADLL (REGISTER_BASE_DBG + 0x0008) +#define UAIER (REGISTER_BASE_DBG + 0x000c) +#define UADLH (REGISTER_BASE_DBG + 0x0010) +#define UAIIR (REGISTER_BASE_DBG + 0x0014) +#define UAFCR (REGISTER_BASE_DBG + 0x0018) +#define UALCR (REGISTER_BASE_DBG + 0x001c) +#define UAMCR (REGISTER_BASE_DBG + 0x0020) +#define UALSR (REGISTER_BASE_DBG + 0x0024) +#define UAMSR (REGISTER_BASE_DBG + 0x0028) +#define UASCR (REGISTER_BASE_DBG + 0x002c) + +#define PARITY_NONE 0 +#define PARITY_ODD 0x08 +#define PARITY_EVEN 0x18 +#define PARITY_MARK 0x28 +#define PARITY_SPACE 0x38 + +#define DATA_5BIT 0x0 +#define DATA_6BIT 0x1 +#define DATA_7BIT 0x2 +#define DATA_8BIT 0x3 + +#define STOP_1BIT 0x0 +#define STOP_2BIT 0x4 + +#define BAUD_DBG 57600 +#define PARITY_DBG PARITY_NONE +#define DATA_DBG DATA_8BIT +#define STOP_DBG STOP_1BIT + +/* Initialize the serial port for KGDB debugging */ +void __init excite_kgdb_init(void) +{ + const u32 divisor = BASE_BAUD / BAUD_DBG; + + /* Take the UART out of reset */ + titan_writel(0x00ff1cff, CPRR); + titan_writel(0x00000000, UACFG); + titan_writel(0x00000002, UACFG); + + titan_writel(0x0, UALCR); + titan_writel(0x0, UAIER); + + /* Disable FIFOs */ + titan_writel(0x00, UAFCR); + + titan_writel(0x80, UALCR); + titan_writel(divisor & 0xff, UADLL); + titan_writel((divisor & 0xff00) >> 8, UADLH); + titan_writel(0x0, UALCR); + + titan_writel(DATA_DBG | PARITY_DBG | STOP_DBG, UALCR); + + /* Enable receiver interrupt */ + titan_readl(UARBR); + titan_writel(0x1, UAIER); +} + +int getDebugChar(void) +{ + while (!(titan_readl(UALSR) & 0x1)); + return titan_readl(UARBR); +} + +int putDebugChar(int data) +{ + while (!(titan_readl(UALSR) & 0x20)); + titan_writel(data, UATHR); + return 1; +} + +/* KGDB interrupt handler */ +asmlinkage void excite_kgdb_inthdl(struct pt_regs *regs) +{ + if (unlikely( + ((titan_readl(UAIIR) & 0x7) == 4) + && ((titan_readl(UARBR) & 0xff) == 0x3))) + set_async_breakpoint(®s->cp0_epc); +} diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c new file mode 100644 index 0000000..34ec767 --- /dev/null +++ b/arch/mips/basler/excite/excite_device.c @@ -0,0 +1,404 @@ +/* + * Copyright (C) 2004 by Basler Vision Technologies AG + * Author: Thomas Koeller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "excite_iodev.h" + +#define RM9K_GE_UNIT 0 +#define XICAP_UNIT 0 +#define NAND_UNIT 0 + +#define DLL_TIMEOUT 3 /* seconds */ + + +#define RINIT(__start__, __end__, __name__, __parent__) { \ + .name = __name__ "_0", \ + .start = (__start__), \ + .end = (__end__), \ + .flags = 0, \ + .parent = (__parent__) \ +} + +#define RINIT_IRQ(__irq__, __name__) { \ + .name = __name__ "_0", \ + .start = (__irq__), \ + .end = (__irq__), \ + .flags = IORESOURCE_IRQ, \ + .parent = NULL \ +} + + + +enum { + slice_xicap, + slice_eth +}; + + + +static struct resource + excite_ctr_resource = { + .name = "GPI counters", + .start = 0, + .end = 5, + .flags = 0, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_gpislice_resource = { + .name = "GPI slices", + .start = 0, + .end = 1, + .flags = 0, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_mdio_channel_resource = { + .name = "MDIO channels", + .start = 0, + .end = 1, + .flags = 0, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_fifomem_resource = { + .name = "FIFO memory", + .start = 0, + .end = 767, + .flags = 0, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_scram_resource = { + .name = "Scratch RAM", + .start = EXCITE_PHYS_SCRAM, + .end = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1, + .flags = IORESOURCE_MEM, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_fpga_resource = { + .name = "System FPGA", + .start = EXCITE_PHYS_FPGA, + .end = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1, + .flags = IORESOURCE_MEM, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_nand_resource = { + .name = "NAND flash control", + .start = EXCITE_PHYS_NAND, + .end = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1, + .flags = IORESOURCE_MEM, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_titan_resource = { + .name = "TITAN registers", + .start = EXCITE_PHYS_TITAN, + .end = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1, + .flags = IORESOURCE_MEM, + .parent = NULL, + .sibling = NULL, + .child = NULL + }; + + + +static void adjust_resources(struct resource *res, unsigned int n) +{ + struct resource *p; + const unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM + | IORESOURCE_IRQ | IORESOURCE_DMA; + + for (p = res; p < res + n; p++) { + const struct resource * const parent = p->parent; + if (parent) { + p->start += parent->start; + p->end += parent->start; + p->flags = parent->flags & mask; + } + } +} + + + +#if defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) +static struct resource xicap_rsrc[] = { + RINIT(0x4840, 0x486f, XICAP_RESOURCE_FIFO_RX, &excite_titan_resource), + RINIT(0x4940, 0x494b, XICAP_RESOURCE_FIFO_TX, &excite_titan_resource), + RINIT(0x5040, 0x5127, XICAP_RESOURCE_XDMA, &excite_titan_resource), + RINIT(0x1000, 0x112f, XICAP_RESOURCE_PKTPROC, &excite_titan_resource), + RINIT(0x1100, 0x110f, XICAP_RESOURCE_PKT_STREAM, &excite_fpga_resource), + RINIT(0x0800, 0x0bff, XICAP_RESOURCE_DMADESC, &excite_scram_resource), + RINIT(slice_xicap, slice_xicap, XICAP_RESOURCE_GPI_SLICE, &excite_gpislice_resource), + RINIT(0x0100, 0x02ff, XICAP_RESOURCE_FIFO_BLK, &excite_fifomem_resource), + RINIT_IRQ(TITAN_IRQ, XICAP_RESOURCE_IRQ) +}; + +static struct platform_device xicap_pdev = { + .name = XICAP_NAME, + .id = XICAP_UNIT, + .num_resources = ARRAY_SIZE(xicap_rsrc), + .resource = xicap_rsrc +}; + +/* + * Create a platform device for the GPI port that receives the + * image data from the embedded camera. + */ +static int __init xicap_devinit(void) +{ + unsigned long tend; + u32 reg; + int retval; + + adjust_resources(xicap_rsrc, ARRAY_SIZE(xicap_rsrc)); + + /* Power up the slice and configure it. */ + reg = titan_readl(CPTC1R); + reg &= ~(0x11100 << slice_xicap); + titan_writel(reg, CPTC1R); + + /* Enable slice & DLL. */ + reg= titan_readl(CPRR); + reg &= ~(0x00030003 << (slice_xicap * 2)); + titan_writel(reg, CPRR); + + /* Wait for DLLs to lock */ + tend = jiffies + DLL_TIMEOUT * HZ; + while (time_before(jiffies, tend)) { + if (!(~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4)))) + break; + yield(); + } + + if (~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))) { + printk(KERN_ERR "%s: DLL not locked after %u seconds\n", + xicap_pdev.name, DLL_TIMEOUT); + retval = -ETIME; + } else { + /* Register platform device */ + retval = platform_device_register(&xicap_pdev); + } + + return retval; +} + +device_initcall(xicap_devinit); +#endif /* defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) */ + + + +#if defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) +static struct resource wdt_rsrc[] = { + RINIT(0, 0, WDT_RESOURCE_COUNTER, &excite_ctr_resource), + RINIT(0x0084, 0x008f, WDT_RESOURCE_REGS, &excite_titan_resource), + RINIT_IRQ(TITAN_IRQ, WDT_RESOURCE_IRQ) +}; + +static struct platform_device wdt_pdev = { + .name = WDT_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(wdt_rsrc), + .resource = wdt_rsrc +}; + +/* + * Create a platform device for the GPI port that receives the + * image data from the embedded camera. + */ +static int __init wdt_devinit(void) +{ + adjust_resources(wdt_rsrc, ARRAY_SIZE(wdt_rsrc)); + return platform_device_register(&wdt_pdev); +} + +device_initcall(wdt_devinit); +#endif /* defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) */ + + + +static struct resource excite_nandflash_rsrc[] = { + RINIT(0x2000, 0x201f, EXCITE_NANDFLASH_RESOURCE_REGS, &excite_nand_resource) +}; + +static struct platform_device excite_nandflash_pdev = { + .name = "excite_nand", + .id = NAND_UNIT, + .num_resources = ARRAY_SIZE(excite_nandflash_rsrc), + .resource = excite_nandflash_rsrc +}; + +/* + * Create a platform device for the access to the nand-flash + * port + */ +static int __init excite_nandflash_devinit(void) +{ + adjust_resources(excite_nandflash_rsrc, ARRAY_SIZE(excite_nandflash_rsrc)); + + /* nothing to be done here */ + + /* Register platform device */ + return platform_device_register(&excite_nandflash_pdev); +} + +device_initcall(excite_nandflash_devinit); + + + +static struct resource iodev_rsrc[] = { + RINIT_IRQ(FPGA1_IRQ, IODEV_RESOURCE_IRQ) +}; + +static struct platform_device io_pdev = { + .name = IODEV_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(iodev_rsrc), + .resource = iodev_rsrc +}; + +/* + * Create a platform device for the external I/O ports. + */ +static int __init io_devinit(void) +{ + adjust_resources(iodev_rsrc, ARRAY_SIZE(iodev_rsrc)); + return platform_device_register(&io_pdev); +} + +device_initcall(io_devinit); + + + + +#if defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) +static struct resource rm9k_ge_rsrc[] = { + RINIT(0x2200, 0x27ff, RM9K_GE_RESOURCE_MAC, &excite_titan_resource), + RINIT(0x1800, 0x1fff, RM9K_GE_RESOURCE_MSTAT, &excite_titan_resource), + RINIT(0x2000, 0x212f, RM9K_GE_RESOURCE_PKTPROC, &excite_titan_resource), + RINIT(0x5140, 0x5227, RM9K_GE_RESOURCE_XDMA, &excite_titan_resource), + RINIT(0x4870, 0x489f, RM9K_GE_RESOURCE_FIFO_RX, &excite_titan_resource), + RINIT(0x494c, 0x4957, RM9K_GE_RESOURCE_FIFO_TX, &excite_titan_resource), + RINIT(0x0000, 0x007f, RM9K_GE_RESOURCE_FIFOMEM_RX, &excite_fifomem_resource), + RINIT(0x0080, 0x00ff, RM9K_GE_RESOURCE_FIFOMEM_TX, &excite_fifomem_resource), + RINIT(0x0180, 0x019f, RM9K_GE_RESOURCE_PHY, &excite_titan_resource), + RINIT(0x0000, 0x03ff, RM9K_GE_RESOURCE_DMADESC_RX, &excite_scram_resource), + RINIT(0x0400, 0x07ff, RM9K_GE_RESOURCE_DMADESC_TX, &excite_scram_resource), + RINIT(slice_eth, slice_eth, RM9K_GE_RESOURCE_GPI_SLICE, &excite_gpislice_resource), + RINIT(0, 0, RM9K_GE_RESOURCE_MDIO_CHANNEL, &excite_mdio_channel_resource), + RINIT_IRQ(TITAN_IRQ, RM9K_GE_RESOURCE_IRQ_MAIN), + RINIT_IRQ(PHY_IRQ, RM9K_GE_RESOURCE_IRQ_PHY) +}; + +static struct platform_device rm9k_ge_pdev = { + .name = RM9K_GE_NAME, + .id = RM9K_GE_UNIT, + .num_resources = ARRAY_SIZE(rm9k_ge_rsrc), + .resource = rm9k_ge_rsrc +}; + + + +/* + * Create a platform device for the Ethernet port. + */ +static int __init rm9k_ge_devinit(void) +{ + u32 reg; + + adjust_resources(rm9k_ge_rsrc, ARRAY_SIZE(rm9k_ge_rsrc)); + + /* Power up the slice and configure it. */ + reg = titan_readl(CPTC1R); + reg &= ~(0x11000 << slice_eth); + reg |= 0x100 << slice_eth; + titan_writel(reg, CPTC1R); + + /* Take the MAC out of reset, reset the DLLs. */ + reg = titan_readl(CPRR); + reg &= ~(0x00030000 << (slice_eth * 2)); + reg |= 0x3 << (slice_eth * 2); + titan_writel(reg, CPRR); + + return platform_device_register(&rm9k_ge_pdev); +} + +device_initcall(rm9k_ge_devinit); +#endif /* defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) */ + + + +static int __init excite_setup_devs(void) +{ + int res; + u32 reg; + + /* Enable xdma and fifo interrupts */ + reg = titan_readl(0x0050); + titan_writel(reg | 0x18000000, 0x0050); + + res = request_resource(&iomem_resource, &excite_titan_resource); + if (res) + return res; + res = request_resource(&iomem_resource, &excite_scram_resource); + if (res) + return res; + res = request_resource(&iomem_resource, &excite_fpga_resource); + if (res) + return res; + res = request_resource(&iomem_resource, &excite_nand_resource); + if (res) + return res; + excite_fpga_resource.flags = excite_fpga_resource.parent->flags & + ( IORESOURCE_IO | IORESOURCE_MEM + | IORESOURCE_IRQ | IORESOURCE_DMA); + excite_nand_resource.flags = excite_nand_resource.parent->flags & + ( IORESOURCE_IO | IORESOURCE_MEM + | IORESOURCE_IRQ | IORESOURCE_DMA); + + return 0; +} + +arch_initcall(excite_setup_devs); + diff --git a/arch/mips/basler/excite/excite_flashtest.c b/arch/mips/basler/excite/excite_flashtest.c new file mode 100644 index 0000000..f0024a8 --- /dev/null +++ b/arch/mips/basler/excite/excite_flashtest.c @@ -0,0 +1,294 @@ +/* +* Copyright (C) 2005 by Basler Vision Technologies AG +* Author: Thies Moeller +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include // for ocd_write +#include // for queue + +#include "excite_nandflash.h" +#include "nandflash.h" + +#define PFX "excite flashtest: " +typedef void __iomem *io_reg_t; + +#define io_readb(__a__) __raw_readb((__a__)) +#define io_writeb(__v__, __a__) __raw_writeb((__v__), (__a__)) + + + +static inline const struct resource *excite_nandflash_get_resource( + struct platform_device *d, unsigned long flags, const char *basename) +{ + const char fmt[] = "%s_%u"; + char buf[80]; + + if (unlikely(snprintf(buf, sizeof buf, fmt, basename, d->id) >= sizeof buf)) + return NULL; + + return platform_get_resource_byname(d, flags, buf); +} + +static inline io_reg_t +excite_nandflash_map_regs(struct platform_device *d, const char *basename) +{ + void *result = NULL; + const struct resource *const r = + excite_nandflash_get_resource(d, IORESOURCE_MEM, basename); + if (r) + result = ioremap_nocache(r->start, r->end + 1 - r->start); + return result; +} + +/* controller and mtd information */ + +struct excite_nandflash_drvdata { + struct mtd_info board_mtd; + struct nand_chip board_chip; + io_reg_t regs; +}; + + +/* command and control functions */ +static void excite_nandflash_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct nand_chip *this = mtd->priv; + io_reg_t regs = container_of(mtd,struct excite_nandflash_drvdata,board_mtd)->regs; + + switch (cmd) { + /* Select the command latch */ + case NAND_CTL_SETCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_CMD; + break; + /* Deselect the command latch */ + case NAND_CTL_CLRCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_DATA; + break; + /* Select the address latch */ + case NAND_CTL_SETALE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_ADDR; + break; + /* Deselect the address latch */ + case NAND_CTL_CLRALE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_DATA; + break; + /* Select the chip -- not used */ + case NAND_CTL_SETNCE: + break; + /* Deselect the chip -- not used */ + case NAND_CTL_CLRNCE: + break; + } + + this->IO_ADDR_R = this->IO_ADDR_W; +} + +/* excite_nandflash_devready() + * + * returns 0 if the nand is busy, 1 if it is ready + */ +static int excite_nandflash_devready(struct mtd_info *mtd) +{ + struct excite_nandflash_drvdata *drvdata = + container_of(mtd, struct excite_nandflash_drvdata, board_mtd); + + return io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS); +} + +/* device management functions */ + +/* excite_nandflash_remove + * + * called by device layer to remove the driver + * the binding to the mtd and all allocated + * resources are released + */ +static int excite_nandflash_remove(struct device *dev) +{ + struct excite_nandflash_drvdata *this = dev_get_drvdata(dev); + + pr_info(PFX "remove"); + + dev_set_drvdata(dev, NULL); + + if (this == NULL) { + pr_debug(PFX "call remove without private data!!"); + return 0; + } + + + /* free the common resources */ + if (this->regs != NULL) { + iounmap(this->regs); + this->regs = NULL; + } + + kfree(this); + + return 0; +} + +static int elapsed; + +void my_workqueue_handler(void *arg) +{ + elapsed = 1; +} + +DECLARE_WORK(sigElapsed, my_workqueue_handler, 0); + + +/* excite_nandflash_probe + * + * called by device layer when it finds a device matching + * one our driver can handled. This code checks to see if + * it can allocate all necessary resources then calls the + * nand layer to look for devices +*/ +static int excite_nandflash_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + struct excite_nandflash_drvdata *drvdata; /* private driver data */ + struct nand_chip *board_chip; /* private flash chip data */ + struct mtd_info *board_mtd; /* mtd info for this board */ + + int err = 0; + int count = 0; + struct timeval tv,endtv; + unsigned int dt; + + pr_info(PFX "probe dev: (%p)\n", dev); + + pr_info(PFX "adjust LB timing\n"); + ocd_writel(0x00000330, LDP2); + + drvdata = kmalloc(sizeof(*drvdata), GFP_KERNEL); + if (unlikely(!drvdata)) { + printk(KERN_ERR PFX "no memory for drvdata\n"); + err = -ENOMEM; + goto mem_error; + } + + /* Initialize structures */ + memset(drvdata, 0, sizeof(*drvdata)); + + /* bind private data into driver */ + dev_set_drvdata(dev, drvdata); + + /* allocate and map the resource */ + drvdata->regs = + excite_nandflash_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS); + + if (unlikely(!drvdata->regs)) { + printk(KERN_ERR PFX "cannot reserve register region\n"); + err = -ENXIO; + goto io_error; + } + + /* initialise our chip */ + board_chip = &drvdata->board_chip; + + board_chip->IO_ADDR_R = drvdata->regs + EXCITE_NANDFLASH_DATA; + board_chip->IO_ADDR_W = drvdata->regs + EXCITE_NANDFLASH_DATA; + + board_chip->hwcontrol = excite_nandflash_hwcontrol; + board_chip->dev_ready = excite_nandflash_devready; + + board_chip->chip_delay = 25; + #if 0 + /* TODO: speedup the initial scan */ + board_chip->options = NAND_USE_FLASH_BBT; + #endif + board_chip->eccmode = NAND_ECC_SOFT; + + /* link chip to mtd */ + board_mtd = &drvdata->board_mtd; + board_mtd->priv = board_chip; + + + pr_info(PFX "FlashTest\n"); + elapsed = 0; +/* schedule_delayed_work(&sigElapsed, 1*HZ); + while (!elapsed) { + io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS); + count++; + } + pr_info(PFX "reads in 1 sec --> %d\n",count); +*/ + do_gettimeofday(&tv); + for (count = 0 ; count < 1000000; count ++) { + io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS); + } + do_gettimeofday(&endtv); + dt = (endtv.tv_sec - tv.tv_sec) * 1000000 + endtv.tv_usec - tv.tv_usec; + pr_info(PFX "%8d us timeval\n",dt); + pr_info(PFX "EndFlashTest\n"); + +/* return with error to unload everything +*/ +io_error: + iounmap(drvdata->regs); + +mem_error: + kfree(drvdata); + + if (err == 0) + err = -EINVAL; + return err; +} + +static struct device_driver excite_nandflash_driver = { + .name = "excite_nand", + .bus = &platform_bus_type, + .probe = excite_nandflash_probe, + .remove = excite_nandflash_remove, +}; + +static int __init excite_nandflash_init(void) +{ + pr_info(PFX "register Driver (Rev: $Revision:$)\n"); + return driver_register(&excite_nandflash_driver); +} + +static void __exit excite_nandflash_exit(void) +{ + driver_unregister(&excite_nandflash_driver); + pr_info(PFX "Driver unregistered"); +} + +module_init(excite_nandflash_init); +module_exit(excite_nandflash_exit); + +MODULE_AUTHOR("Thies Moeller "); +MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/mips/basler/excite/excite_fpga.h b/arch/mips/basler/excite/excite_fpga.h new file mode 100644 index 0000000..38fcda7 --- /dev/null +++ b/arch/mips/basler/excite/excite_fpga.h @@ -0,0 +1,80 @@ +#ifndef EXCITE_FPGA_H_INCLUDED +#define EXCITE_FPGA_H_INCLUDED + + +/** + * Adress alignment of the individual FPGA bytes. + * The address arrangement of the individual bytes of the FPGA is two + * byte aligned at the embedded MK2 platform. + */ +#ifdef EXCITE_CCI_FPGA_MK2 +typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2))); +#else +typedef unsigned char excite_cci_fpga_align_t; +#endif + + +/** + * Size of Dual Ported RAM. + */ +#define EXCITE_DPR_SIZE 263 + + +/** + * Size of Reserved Status Fields in Dual Ported RAM. + */ +#define EXCITE_DPR_STATUS_SIZE 7 + + + +/** + * FPGA. + * Hardware register layout of the FPGA interface. The FPGA must accessed + * byte wise solely. + * @see EXCITE_CCI_DPR_MK2 + */ +typedef struct excite_fpga { + + /** + * Dual Ported RAM. + */ + excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE]; + + /** + * Status. + */ + excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE]; + +#ifdef EXCITE_CCI_FPGA_MK2 + /** + * RM9000 Interrupt. + * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite. + */ + excite_cci_fpga_align_t rm9k_int; +#else + /** + * MK2 Interrupt. + * Write access initiates interrupt at the ARM processor of the MK2. + */ + excite_cci_fpga_align_t mk2_int; + + excite_cci_fpga_align_t gap[0x1000-0x10f]; + + /** + * IRQ Source/Acknowledge. + */ + excite_cci_fpga_align_t rm9k_irq_src; + + /** + * IRQ Mask. + * Set bits enable the related interrupt. + */ + excite_cci_fpga_align_t rm9k_irq_mask; +#endif + + +} excite_fpga; + + + +#endif /* ndef EXCITE_FPGA_H_INCLUDED */ diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c new file mode 100644 index 0000000..91121e5 --- /dev/null +++ b/arch/mips/basler/excite/excite_iodev.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2005 by Basler Vision Technologies AG + * Author: Thomas Koeller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "excite_iodev.h" + + + +static const struct resource *iodev_get_resource(struct platform_device *, const char *, unsigned int); +static int __init iodev_probe(struct device *); +static int __exit iodev_remove(struct device *); +static int iodev_open(struct inode *, struct file *); +static int iodev_release(struct inode *, struct file *); +static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *); +static unsigned int iodev_poll(struct file *, struct poll_table_struct *); +static irqreturn_t iodev_irqhdl(int, void *, struct pt_regs *); + + + +static const char iodev_name[] = "iodev"; +static unsigned int iodev_irq; +static DECLARE_WAIT_QUEUE_HEAD(wq); + + + +static struct file_operations fops = +{ + .owner = THIS_MODULE, + .open = iodev_open, + .release = iodev_release, + .read = iodev_read, + .poll = iodev_poll +}; + +static struct miscdevice miscdev = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = iodev_name, + .fops = &fops +}; + +static struct device_driver iodev_driver = +{ + .name = (char *) iodev_name, + .bus = &platform_bus_type, + .owner = THIS_MODULE, + .probe = iodev_probe, + .remove = __exit_p(iodev_remove) +}; + + + +static const struct resource * +iodev_get_resource(struct platform_device *pdv, const char *name, + unsigned int type) +{ + char buf[80]; + if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf) + return NULL; + return platform_get_resource_byname(pdv, type, buf); +} + + + +/* No hotplugging on the platform bus - use __init */ +static int __init iodev_probe(struct device *dev) +{ + struct platform_device * const pdv = to_platform_device(dev); + const struct resource * const ri = + iodev_get_resource(pdv, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ); + + if (unlikely(!ri)) + return -ENXIO; + + iodev_irq = ri->start; + return misc_register(&miscdev); +} + + + +static int __exit iodev_remove(struct device *dev) +{ + return misc_deregister(&miscdev); +} + + + +static int iodev_open(struct inode *i, struct file *f) +{ + return request_irq(iodev_irq, iodev_irqhdl, SA_INTERRUPT, + iodev_name, &miscdev); +} + + + +static int iodev_release(struct inode *i, struct file *f) +{ + free_irq(iodev_irq, &miscdev); + return 0; +} + + + + +static ssize_t +iodev_read(struct file *f, char __user *d, size_t s, loff_t *o) +{ + ssize_t ret; + DEFINE_WAIT(w); + + prepare_to_wait(&wq, &w, TASK_INTERRUPTIBLE); + if (!signal_pending(current)) + schedule(); + ret = signal_pending(current) ? -ERESTARTSYS : 0; + finish_wait(&wq, &w); + return ret; +} + + +static unsigned int iodev_poll(struct file *f, struct poll_table_struct *p) +{ + poll_wait(f, &wq, p); + return POLLOUT | POLLWRNORM; +} + + + + +static irqreturn_t iodev_irqhdl(int irq, void *ctxt, struct pt_regs *regs) +{ + wake_up(&wq); + return IRQ_HANDLED; +} + + + +static int __init iodev_init_module(void) +{ + return driver_register(&iodev_driver); +} + + + +static void __exit iodev_cleanup_module(void) +{ + driver_unregister(&iodev_driver); +} + +module_init(iodev_init_module); +module_exit(iodev_cleanup_module); + + + +MODULE_AUTHOR("Thomas Koeller "); +MODULE_DESCRIPTION("Basler eXcite i/o interrupt handler"); +MODULE_VERSION("0.0"); +MODULE_LICENSE("GPL"); diff --git a/arch/mips/basler/excite/excite_iodev.h b/arch/mips/basler/excite/excite_iodev.h new file mode 100644 index 0000000..cbfbb5d --- /dev/null +++ b/arch/mips/basler/excite/excite_iodev.h @@ -0,0 +1,10 @@ +#ifndef __EXCITE_IODEV_H__ +#define __EXCITE_IODEV_H__ + +/* Device name */ +#define IODEV_NAME "iodev" + +/* Resource names */ +#define IODEV_RESOURCE_IRQ "excite_iodev_irq" + +#endif /* __EXCITE_IODEV_H__ */ diff --git a/arch/mips/basler/excite/excite_irq.c b/arch/mips/basler/excite/excite_irq.c new file mode 100644 index 0000000..511ad87 --- /dev/null +++ b/arch/mips/basler/excite/excite_irq.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) by Basler Vision Technologies AG + * Author: Thomas Koeller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern asmlinkage void excite_handle_int(void); + +/* + * Initialize the interrupt handler + */ +void __init arch_init_irq(void) +{ + mips_cpu_irq_init(0); + rm7k_cpu_irq_init(8); + rm9k_cpu_irq_init(12); + +#ifdef CONFIG_KGDB + excite_kgdb_init(); +#endif +} + +asmlinkage void plat_irq_dispatch(struct pt_regs *regs) +{ + const u32 + interrupts = read_c0_cause() >> 8, + mask = ((read_c0_status() >> 8) & 0x000000ff) | + (read_c0_intcontrol() & 0x0000ff00), + pending = interrupts & mask; + u32 msgintflags, msgintmask, msgint; + + /* process timer interrupt */ + if (pending & (1 << TIMER_IRQ)) { + do_IRQ(TIMER_IRQ, regs); + return; + } + + /* Process PCI interrupts */ +#if USB_IRQ < 10 + msgintflags = ocd_readl(INTP0Status0 + (USB_MSGINT / 0x20 * 0x10)); + msgintmask = ocd_readl(INTP0Mask0 + (USB_MSGINT / 0x20 * 0x10)); + msgint = msgintflags & msgintmask & (0x1 << (USB_MSGINT % 0x20)); + if ((pending & (1 << USB_IRQ)) && msgint) { +#else + if (pending & (1 << USB_IRQ)) { +#endif + do_IRQ(USB_IRQ, regs); + return; + } + + /* Process TITAN interrupts */ + msgintflags = ocd_readl(INTP0Status0 + (TITAN_MSGINT / 0x20 * 0x10)); + msgintmask = ocd_readl(INTP0Mask0 + (TITAN_MSGINT / 0x20 * 0x10)); + msgint = msgintflags & msgintmask & (0x1 << (TITAN_MSGINT % 0x20)); + if ((pending & (1 << TITAN_IRQ)) && msgint) { + ocd_writel(msgint, INTP0Clear0 + (TITAN_MSGINT / 0x20 * 0x10)); +#if defined(CONFIG_KGDB) + excite_kgdb_inthdl(regs); +#endif + do_IRQ(TITAN_IRQ, regs); + return; + } + + /* Process FPGA line #0 interrupts */ + msgintflags = ocd_readl(INTP0Status0 + (FPGA0_MSGINT / 0x20 * 0x10)); + msgintmask = ocd_readl(INTP0Mask0 + (FPGA0_MSGINT / 0x20 * 0x10)); + msgint = msgintflags & msgintmask & (0x1 << (FPGA0_MSGINT % 0x20)); + if ((pending & (1 << FPGA0_IRQ)) && msgint) { + do_IRQ(FPGA0_IRQ, regs); + return; + } + + /* Process FPGA line #1 interrupts */ + msgintflags = ocd_readl(INTP0Status0 + (FPGA1_MSGINT / 0x20 * 0x10)); + msgintmask = ocd_readl(INTP0Mask0 + (FPGA1_MSGINT / 0x20 * 0x10)); + msgint = msgintflags & msgintmask & (0x1 << (FPGA1_MSGINT % 0x20)); + if ((pending & (1 << FPGA1_IRQ)) && msgint) { + do_IRQ(FPGA1_IRQ, regs); + return; + } + + /* Process PHY interrupts */ + msgintflags = ocd_readl(INTP0Status0 + (PHY_MSGINT / 0x20 * 0x10)); + msgintmask = ocd_readl(INTP0Mask0 + (PHY_MSGINT / 0x20 * 0x10)); + msgint = msgintflags & msgintmask & (0x1 << (PHY_MSGINT % 0x20)); + if ((pending & (1 << PHY_IRQ)) && msgint) { + do_IRQ(PHY_IRQ, regs); + return; + } + + /* Process spurious interrupts */ + spurious_interrupt(regs); +} diff --git a/arch/mips/basler/excite/excite_procfs.c b/arch/mips/basler/excite/excite_procfs.c new file mode 100644 index 0000000..c62be03 --- /dev/null +++ b/arch/mips/basler/excite/excite_procfs.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2004, 2005 by Basler Vision Technologies AG + * Author: Thomas Koeller + * + * Procfs support for Basler eXcite + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +static int excite_get_unit_id(char *buf, char **addr, off_t offs, int size) +{ + const int len = snprintf(buf, PAGE_SIZE, "%06x", unit_id); + const int w = len - offs; + *addr = buf + offs; + return w < size ? w : size; +} + +static int +excite_bootrom_read(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + void __iomem * src; + + if (off >= EXCITE_SIZE_BOOTROM) { + *eof = 1; + return 0; + } + + if ((off + count) > EXCITE_SIZE_BOOTROM) + count = EXCITE_SIZE_BOOTROM - off; + + src = ioremap(EXCITE_PHYS_BOOTROM + off, count); + if (src) { + memcpy_fromio(page, src, count); + iounmap(src); + *start = page; + } else { + count = -ENOMEM; + } + + return count; +} + +void excite_procfs_init(void) +{ + /* Create & populate /proc/excite */ + struct proc_dir_entry * const pdir = proc_mkdir("excite", &proc_root); + if (pdir) { + struct proc_dir_entry * e; + + e = create_proc_info_entry("unit_id", S_IRUGO, pdir, + excite_get_unit_id); + if (e) e->size = 6; + + e = create_proc_read_entry("bootrom", S_IRUGO, pdir, + excite_bootrom_read, NULL); + if (e) e->size = EXCITE_SIZE_BOOTROM; + } +} diff --git a/arch/mips/basler/excite/excite_prom.c b/arch/mips/basler/excite/excite_prom.c new file mode 100644 index 0000000..84724b2 --- /dev/null +++ b/arch/mips/basler/excite/excite_prom.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2004, 2005 by Thomas Koeller (thomas.koeller@baslerweb.com) + * Based on the PMC-Sierra Yosemite board support by Ralf Baechle and + * Manish Lachwani. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* This struct is used by Redboot to pass arguments to the kernel */ +typedef struct +{ + char *name; + char *val; +} t_env_var; + +struct parmblock { + t_env_var memsize; + t_env_var modetty0; + t_env_var ethaddr; + t_env_var env_end; + char *argv[2]; + char text[0]; +}; + +static unsigned int prom_argc; +static const char ** prom_argv; +static const t_env_var * prom_env; + +static void prom_halt(void) __attribute__((noreturn)); +static void prom_exit(void) __attribute__((noreturn)); + + + +const char *get_system_type(void) +{ + return "Basler eXcite"; +} + +/* + * Halt the system + */ +static void prom_halt(void) +{ + printk(KERN_NOTICE "\n** System halted.\n"); + while (1) + asm volatile ( + "\t.set\tmips3\n" + "\twait\n" + "\t.set\tmips0\n" + ); +} + +/* + * Reset the CPU and re-enter Redboot + */ +static void prom_exit(void) +{ + unsigned int i; + volatile unsigned char * const flg = + (volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_DPR); + + /* Clear the watchdog reset flag, set the reboot flag */ + *flg &= ~0x01; + *flg |= 0x80; + + for (i = 0; i < 10; i++) { + *(volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_SYSCTL) = 0x02; + iob(); + mdelay(1000); + } + + printk(KERN_NOTICE "Reset failed\n"); + prom_halt(); +} + +static const char __init *prom_getenv(char *name) +{ + const t_env_var * p; + for (p = prom_env; p->name != NULL; p++) + if(strcmp(name, p->name) == 0) + break; + return p->val; +} + +/* + * Init routine which accepts the variables from Redboot + */ +void __init prom_init(void) +{ + const struct parmblock * const pb = (struct parmblock *) fw_arg2; + + prom_argc = fw_arg0; + prom_argv = (const char **) fw_arg1; + prom_env = &pb->memsize; + + /* Callbacks for halt, restart */ + _machine_restart = (void (*)(char *)) prom_exit; + _machine_halt = prom_halt; + +#ifdef CONFIG_32BIT + /* copy command line */ + strcpy(arcs_cmdline, prom_argv[1]); + memsize = simple_strtol(prom_getenv("memsize"), NULL, 16); + strcpy(modetty, prom_getenv("modetty0")); +#endif /* CONFIG_32BIT */ + +#ifdef CONFIG_64BIT +# error 64 bit support not implemented +#endif /* CONFIG_64BIT */ + + mips_machgroup = MACH_GROUP_TITAN; + mips_machtype = MACH_TITAN_EXCITE; +} + +/* This is called from free_initmem(), so we need to provide it */ +void __init prom_free_prom_memory(void) +{ + /* Nothing to do */ +} diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c new file mode 100644 index 0000000..005b025 --- /dev/null +++ b/arch/mips/basler/excite/excite_setup.c @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2004, 2005 by Basler Vision Technologies AG + * Author: Thomas Koeller + * Based on the PMC-Sierra Yosemite board support by Ralf Baechle and + * Manish Lachwani. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TITAN_UART_CLK 25000000 + +#if 1 +/* normal serial port assignment */ +#define REGBASE_SER0 0x0208 +#define REGBASE_SER1 0x0238 +#define MASK_SER0 0x1 +#define MASK_SER1 0x2 +#else +/* serial ports swapped */ +#define REGBASE_SER0 0x0238 +#define REGBASE_SER1 0x0208 +#define MASK_SER0 0x2 +#define MASK_SER1 0x1 +#endif + +unsigned long memsize; +char modetty[30]; +unsigned int titan_irq = TITAN_IRQ; +static void __iomem * ctl_regs; +u32 unit_id; + +volatile void __iomem * const ocd_base = (void *) (EXCITE_ADDR_OCD); +volatile void __iomem * const titan_base = (void *) (EXCITE_ADDR_TITAN); + +/* Protect access to shared GPI registers */ +spinlock_t titan_lock = SPIN_LOCK_UNLOCKED; +int titan_irqflags; + + +static void excite_timer_init(void) +{ + const u32 modebit5 = ocd_readl(0x00e4); + unsigned int + mult = ((modebit5 >> 11) & 0x1f) + 2, + div = ((modebit5 >> 16) & 0x1f) + 2; + + if (div == 33) div = 1; + mips_hpt_frequency = EXCITE_CPU_EXT_CLOCK * mult / div / 2; +} + +static void excite_timer_setup(struct irqaction *irq) +{ + /* The eXcite platform uses the alternate timer interrupt */ + set_c0_intcontrol(0x80); + setup_irq(TIMER_IRQ, irq); +} + +static int __init excite_init_console(void) +{ +#if defined(CONFIG_SERIAL_8250) + static __initdata char serr[] = + KERN_ERR "Serial port #%u setup failed\n"; + struct uart_port up; + + /* Take the DUART out of reset */ + titan_writel(0x00ff1cff, CPRR); + +#if defined(CONFIG_KGDB) || (CONFIG_SERIAL_8250_NR_UARTS > 1) + /* Enable both ports */ + titan_writel(MASK_SER0 | MASK_SER1, UACFG); +#else + /* Enable port #0 only */ + titan_writel(MASK_SER0, UACFG); +#endif /* defined(CONFIG_KGDB) */ + + /* + * Set up serial port #0. Do not use autodetection; the result is + * not what we want. + */ + memset(&up, 0, sizeof(up)); + up.membase = (char *) titan_addr(REGBASE_SER0); + up.irq = TITAN_IRQ; + up.uartclk = TITAN_UART_CLK; + up.regshift = 0; + up.iotype = UPIO_MEM32; + up.type = PORT_RM9000; + up.flags = UPF_SHARE_IRQ; + up.line = 0; + if (early_serial_setup(&up)) + printk(serr, up.line); + +#if CONFIG_SERIAL_8250_NR_UARTS > 1 + /* And now for port #1. */ + up.membase = (char *) titan_addr(REGBASE_SER1); + up.line = 1; + if (early_serial_setup(&up)) + printk(serr, up.line); +#endif /* CONFIG_SERIAL_8250_NR_UARTS > 1 */ +#else + /* Leave the DUART in reset */ + titan_writel(0x00ff3cff, CPRR); +#endif /* defined(CONFIG_SERIAL_8250) */ + + return 0; +} + +static int __init excite_platform_init(void) +{ + unsigned int i; + unsigned char buf[3]; + u8 reg; + void __iomem * dpr; + + /* BIU buffer allocations */ + ocd_writel(8, CPURSLMT); /* CPU */ + titan_writel(4, CPGRWL); /* GPI / Ethernet */ + + /* Map control registers located in FPGA */ + ctl_regs = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_SYSCTL, 16); + if (!ctl_regs) + panic("eXcite: failed to map platform control registers\n"); + memcpy_fromio(buf, ctl_regs + 2, ARRAY_SIZE(buf)); + unit_id = buf[0] | (buf[1] << 8) | (buf[2] << 16); + + /* Clear the reboot flag */ + dpr = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_DPR, 1); + reg = __raw_readb(dpr); + __raw_writeb(reg & 0x7f, dpr); + iounmap(dpr); + + /* Interrupt controller setup */ + for (i = INTP0Status0; i < INTP0Status0 + 0x80; i += 0x10) { + ocd_writel(0x00000000, i + 0x04); + ocd_writel(0xffffffff, i + 0x0c); + } + ocd_writel(0x2, NMICONFIG); + + ocd_writel(0x1 << (TITAN_MSGINT % 0x20), + INTP0Mask0 + (0x10 * (TITAN_MSGINT / 0x20))); + ocd_writel((0x1 << (FPGA0_MSGINT % 0x20)) + | ocd_readl(INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20))), + INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20))); + ocd_writel((0x1 << (FPGA1_MSGINT % 0x20)) + | ocd_readl(INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20))), + INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20))); + ocd_writel((0x1 << (PHY_MSGINT % 0x20)) + | ocd_readl(INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20))), + INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20))); +#if USB_IRQ < 10 + ocd_writel((0x1 << (USB_MSGINT % 0x20)) + | ocd_readl(INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20))), + INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20))); +#endif + /* Enable the packet FIFO, XDMA and XDMA arbiter */ + titan_writel(0x00ff18ff, CPRR); + + /* + * Set up the PADMUX. Power down all ethernet slices, + * they will be powered up and configured at device startup. + */ + titan_writel(0x00878206, CPTC1R); + titan_writel(0x00001100, CPTC0R); /* latch PADMUX, enable WCIMODE */ + + /* Reset and enable the FIFO block */ + titan_writel(0x00000001, SDRXFCIE); + titan_writel(0x00000001, SDTXFCIE); + titan_writel(0x00000100, SDRXFCIE); + titan_writel(0x00000000, SDTXFCIE); + + /* + * Initialize the common interrupt shared by all components of + * the GPI/Ethernet subsystem. + */ + titan_writel((EXCITE_PHYS_OCD >> 12), CPCFG0); + titan_writel(TITAN_MSGINT, CPCFG1); + + /* + * XDMA configuration. + * In order for the XDMA to be sharable among multiple drivers, + * the setup must be done here in the platform. The reason is that + * this setup can only be done while the XDMA is in reset. If this + * were done in a driver, it would interrupt all other drivers + * using the XDMA. + */ + titan_writel(0x80021dff, GXCFG); /* XDMA reset */ + titan_writel(0x00000000, CPXCISRA); + titan_writel(0x00000000, CPXCISRB); /* clear pending interrupts */ +#if defined (CONFIG_HIGHMEM) +# error change for HIGHMEM support! +#else + titan_writel(0x00000000, GXDMADRPFX); /* buffer address prefix */ +#endif + titan_writel(0, GXDMA_DESCADR); + + for (i = 0x5040; i <= 0x5300; i += 0x0040) + titan_writel(0x80080000, i); /* reset channel */ + + titan_writel((0x1 << 29) /* no sparse tx descr. */ + | (0x1 << 28) /* no sparse rx descr. */ + | (0x1 << 23) | (0x1 << 24) /* descriptor coherency */ + | (0x1 << 21) | (0x1 << 22) /* data coherency */ + | (0x1 << 17) + | 0x1dff, + GXCFG); + +#if defined(CONFIG_SMP) +# error No SMP support +#else + /* All interrupts go to core #0 only. */ + titan_writel(0x1f007fff, CPDST0A); + titan_writel(0x00000000, CPDST0B); + titan_writel(0x0000ff3f, CPDST1A); + titan_writel(0x00000000, CPDST1B); + titan_writel(0x00ffffff, CPXDSTA); + titan_writel(0x00000000, CPXDSTB); +#endif + + /* Enable DUART interrupts, disable everything else. */ + titan_writel(0x04000000, CPGIG0ER); + titan_writel(0x000000c0, CPGIG1ER); + + excite_procfs_init(); + return 0; +} + +void __init plat_setup(void) +{ + volatile u32 * const boot_ocd_base = (u32 *) 0xbf7fc000; + + /* Announce RAM to system */ + add_memory_region(0x00000000, memsize, BOOT_MEM_RAM); + + /* Set up timer initialization hooks */ + board_time_init = excite_timer_init; + board_timer_setup = excite_timer_setup; + + /* Set up the peripheral address map */ + *(boot_ocd_base + (LKB9 / sizeof (u32))) = 0; + *(boot_ocd_base + (LKB10 / sizeof (u32))) = 0; + *(boot_ocd_base + (LKB11 / sizeof (u32))) = 0; + *(boot_ocd_base + (LKB12 / sizeof (u32))) = 0; + wmb(); + *(boot_ocd_base + (LKB0 / sizeof (u32))) = EXCITE_PHYS_OCD >> 4; + wmb(); + + ocd_writel((EXCITE_PHYS_TITAN >> 4) | 0x1UL, LKB5); + ocd_writel(((EXCITE_SIZE_TITAN >> 4) & 0x7fffff00) - 0x100, LKM5); + ocd_writel((EXCITE_PHYS_SCRAM >> 4) | 0x1UL, LKB13); + ocd_writel(((EXCITE_SIZE_SCRAM >> 4) & 0xffffff00) - 0x100, LKM13); + + /* Local bus slot #0 */ + ocd_writel(0x00040510, LDP0); + ocd_writel((EXCITE_PHYS_BOOTROM >> 4) | 0x1UL, LKB9); + ocd_writel(((EXCITE_SIZE_BOOTROM >> 4) & 0x03ffff00) - 0x100, LKM9); + + /* Local bus slot #2 */ + ocd_writel(0x00000330, LDP2); + ocd_writel((EXCITE_PHYS_FPGA >> 4) | 0x1, LKB11); + ocd_writel(((EXCITE_SIZE_FPGA >> 4) - 0x100) & 0x03ffff00, LKM11); + + /* Local bus slot #3 */ + ocd_writel(0x00123413, LDP3); + ocd_writel((EXCITE_PHYS_NAND >> 4) | 0x1, LKB12); + ocd_writel(((EXCITE_SIZE_NAND >> 4) - 0x100) & 0x03ffff00, LKM12); +} + + + +console_initcall(excite_init_console); +arch_initcall(excite_platform_init); + +EXPORT_SYMBOL(titan_lock); +EXPORT_SYMBOL(titan_irqflags); +EXPORT_SYMBOL(titan_irq); +EXPORT_SYMBOL(ocd_base); +EXPORT_SYMBOL(titan_base); diff --git a/arch/mips/cobalt/console.c b/arch/mips/cobalt/console.c index 45c2d27..300797d 100644 --- a/arch/mips/cobalt/console.c +++ b/arch/mips/cobalt/console.c @@ -41,3 +41,8 @@ void __init cobalt_early_console(void) printk("Cobalt: early console registered\n"); } + +void __init disable_early_printk(void) +{ + unregister_console(&cons_info); +} diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c index 4f9ea12..ca719d6 100644 --- a/arch/mips/cobalt/setup.c +++ b/arch/mips/cobalt/setup.c @@ -68,19 +68,46 @@ static void __init cobalt_timer_setup(st extern struct pci_ops gt64111_pci_ops; static struct resource cobalt_mem_resource = { - "PCI memory", GT64111_MEM_BASE, GT64111_MEM_END, IORESOURCE_MEM + .start = GT64111_MEM_BASE, + .end = GT64111_MEM_END, + .name = "PCI memory", + .flags = IORESOURCE_MEM }; static struct resource cobalt_io_resource = { - "PCI I/O", 0x1000, 0xffff, IORESOURCE_IO + .start = 0x1000, + .end = 0xffff, + .name = "PCI I/O", + .flags = IORESOURCE_IO }; static struct resource cobalt_io_resources[] = { - { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, - { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, - { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY }, - { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, - { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, + { + .start = 0x00, + .end = 0x1f, + .name = "dma1", + .flags = IORESOURCE_BUSY + }, { + .start = 0x40, + .end = 0x5f, + .name = "timer", + .flags = IORESOURCE_BUSY + }, { + .start = 0x60, + .end = 0x6f, + .name = "keyboard", + .flags = IORESOURCE_BUSY + }, { + .start = 0x80, + .end = 0x8f, + .name = "dma page reg", + .flags = IORESOURCE_BUSY + }, { + .start = 0xc0, + .end = 0xdf, + .name = "dma2", + .flags = IORESOURCE_BUSY + }, }; #define COBALT_IO_RESOURCES (sizeof(cobalt_io_resources)/sizeof(struct resource)) @@ -93,7 +120,7 @@ static struct pci_controller cobalt_pci_ .io_offset = 0 - GT64111_IO_BASE }; -void __init plat_setup(void) +void __init plat_mem_setup(void) { static struct uart_port uart; unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0); diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig index 4b080bc..0cc1b3c 100644 --- a/arch/mips/configs/atlas_defconfig +++ b/arch/mips/configs/atlas_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -143,6 +141,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +CONFIG_HZ_100=y +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=100 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index d85cda5..dabf90a 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -145,6 +143,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_SMP=y CONFIG_NR_CPUS=4 CONFIG_PREEMPT_NONE=y diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig index ca0af16..aeb7be8 100644 --- a/arch/mips/configs/capcella_defconfig +++ b/arch/mips/configs/capcella_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set CONFIG_MACH_VR41XX=y # CONFIG_PMC_YOSEMITE is not set @@ -132,6 +130,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig index 7d269e6..d680d3e 100644 --- a/arch/mips/configs/cobalt_defconfig +++ b/arch/mips/configs/cobalt_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -129,6 +127,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig index 579b665..6a7aa40 100644 --- a/arch/mips/configs/db1000_defconfig +++ b/arch/mips/configs/db1000_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -130,6 +128,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig index e5eb538..5c2da56 100644 --- a/arch/mips/configs/db1100_defconfig +++ b/arch/mips/configs/db1100_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -130,6 +128,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig index a43fb23..85ef90c 100644 --- a/arch/mips/configs/db1200_defconfig +++ b/arch/mips/configs/db1200_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -130,6 +128,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig index ad632d8..6f757d8 100644 --- a/arch/mips/configs/db1500_defconfig +++ b/arch/mips/configs/db1500_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -132,6 +130,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig index 8130e23..da4c7e8 100644 --- a/arch/mips/configs/db1550_defconfig +++ b/arch/mips/configs/db1550_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -131,6 +129,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig deleted file mode 100644 index 8d88ac1..0000000 --- a/arch/mips/configs/ddb5476_defconfig +++ /dev/null @@ -1,917 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-rc2 -# Mon Apr 24 14:51:00 2006 -# -CONFIG_MIPS=y - -# -# Machine selection -# -# CONFIG_MIPS_MTX1 is not set -# CONFIG_MIPS_BOSPORUS is not set -# CONFIG_MIPS_PB1000 is not set -# CONFIG_MIPS_PB1100 is not set -# CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_PB1550 is not set -# CONFIG_MIPS_PB1200 is not set -# CONFIG_MIPS_DB1000 is not set -# CONFIG_MIPS_DB1100 is not set -# CONFIG_MIPS_DB1500 is not set -# CONFIG_MIPS_DB1550 is not set -# CONFIG_MIPS_DB1200 is not set -# CONFIG_MIPS_MIRAGE is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_MACH_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MACH_JAZZ is not set -# CONFIG_LASAT is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MIPS_SIM is not set -# CONFIG_MOMENCO_JAGUAR_ATX is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_3 is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MIPS_XXS1500 is not set -# CONFIG_PNX8550_V2PCI is not set -# CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -CONFIG_DDB5476=y -# CONFIG_DDB5477 is not set -# CONFIG_MACH_VR41XX is not set -# CONFIG_PMC_YOSEMITE is not set -# CONFIG_QEMU is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP27 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SIBYTE_BIGSUR is not set -# CONFIG_SIBYTE_SWARM is not set -# CONFIG_SIBYTE_SENTOSA is not set -# CONFIG_SIBYTE_RHONE is not set -# CONFIG_SIBYTE_CARMEL is not set -# CONFIG_SIBYTE_PTSWARM is not set -# CONFIG_SIBYTE_LITTLESUR is not set -# CONFIG_SIBYTE_CRHINE is not set -# CONFIG_SIBYTE_CRHONE is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_TOSHIBA_RBTX4938 is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DMA_NEED_PCI_MAP_STATE=y -CONFIG_I8259=y -# CONFIG_CPU_BIG_ENDIAN is not set -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_DDB5XXX_COMMON=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_HAVE_STD_PC_SERIAL_PORT=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32_R1 is not set -# CONFIG_CPU_MIPS32_R2 is not set -# CONFIG_CPU_MIPS64_R1 is not set -# CONFIG_CPU_MIPS64_R2 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -CONFIG_CPU_R5432=y -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_RM9000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_SYS_HAS_CPU_R5432=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y - -# -# Kernel type -# -CONFIG_32BIT=y -# CONFIG_64BIT is not set -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PAGE_SIZE_16KB is not set -# CONFIG_PAGE_SIZE_64KB is not set -# CONFIG_MIPS_MT is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_ARCH_FLATMEM_ENABLE=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set -# CONFIG_PREEMPT is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set -CONFIG_RELAY=y -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_EMBEDDED=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SHMEM=y -CONFIG_SLAB=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Block layer -# -# CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_DEFAULT_AS=y -# CONFIG_DEFAULT_DEADLINE is not set -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="anticipatory" - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_HW_HAS_PCI=y -CONFIG_PCI=y -CONFIG_ISA=y -CONFIG_MMU=y - -# -# PCCARD (PCMCIA/CardBus) support -# -# CONFIG_PCCARD is not set - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Networking -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_NETDEBUG is not set -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_UNIX=y -CONFIG_XFRM=y -CONFIG_XFRM_USER=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -# CONFIG_NETFILTER is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -CONFIG_IEEE80211=y -# CONFIG_IEEE80211_DEBUG is not set -CONFIG_IEEE80211_CRYPT_WEP=y -CONFIG_IEEE80211_CRYPT_CCMP=y -CONFIG_IEEE80211_SOFTMAC=y -# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set -CONFIG_WIRELESS_EXT=y - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y - -# -# Connector - unified userspace <-> kernelspace linker -# -CONFIG_CONNECTOR=y -CONFIG_PROC_EVENTS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Block devices -# -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_SX8 is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -CONFIG_CDROM_PKTCDVD=y -CONFIG_CDROM_PKTCDVD_BUFFERS=8 -# CONFIG_CDROM_PKTCDVD_WCACHE is not set -CONFIG_ATA_OVER_ETH=y - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_IDE_GENERIC=y -# CONFIG_BLK_DEV_IDEPCI is not set -# CONFIG_IDE_ARM is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI device support -# -CONFIG_RAID_ATTRS=y -# CONFIG_SCSI is not set - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set - -# -# PHY device support -# -CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -CONFIG_MARVELL_PHY=y -CONFIG_DAVICOM_PHY=y -CONFIG_QSEMI_PHY=y -CONFIG_LXT_PHY=y -CONFIG_CICADA_PHY=y - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_CASSINI is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_DM9000 is not set -# CONFIG_NET_VENDOR_RACAL is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SIS190 is not set -# CONFIG_SKGE is not set -# CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set -# CONFIG_BNX2 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_CHELSIO_T1 is not set -# CONFIG_IXGB is not set -# CONFIG_S2IO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_PCIPS2 is not set -# CONFIG_SERIO_LIBPS2 is not set -CONFIG_SERIO_RAW=y -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# -# CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# SPI support -# -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# -# CONFIG_W1 is not set - -# -# Hardware Monitoring support -# -# CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set - -# -# Misc devices -# - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -CONFIG_FB=y -# CONFIG_FB_CFB_FILLRECT is not set -# CONFIG_FB_CFB_COPYAREA is not set -# CONFIG_FB_CFB_IMAGEBLIT is not set -# CONFIG_FB_MACMODES is not set -CONFIG_FB_FIRMWARE_EDID=y -# CONFIG_FB_MODE_HELPERS is not set -# CONFIG_FB_TILEBLITTING is not set -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_NVIDIA is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_SMIVGX is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB_ARCH_HAS_EHCI=y -# CONFIG_USB is not set - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# LED devices -# -# CONFIG_NEW_LEDS is not set - -# -# LED drivers -# - -# -# LED Triggers -# - -# -# InfiniBand support -# -# CONFIG_INFINIBAND is not set - -# -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) -# - -# -# Real Time Clock -# -# CONFIG_RTC_CLASS is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set -# CONFIG_EXT3_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_XFS_FS is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_INOTIFY=y -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -CONFIG_FUSE_FS=y - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -CONFIG_SYSFS=y -# CONFIG_TMPFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y -# CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# -# CONFIG_NLS is not set - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_DEBUG_KERNEL is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_DEBUG_FS is not set -# CONFIG_UNWIND_INFO is not set -CONFIG_CROSSCOMPILE=y -CONFIG_CMDLINE="ip=any" - -# -# Security options -# -CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_WP512=y -CONFIG_CRYPTO_TGR192=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_CAST5=y -CONFIG_CRYPTO_CAST6=y -CONFIG_CRYPTO_TEA=y -CONFIG_CRYPTO_ARC4=y -CONFIG_CRYPTO_KHAZAD=y -CONFIG_CRYPTO_ANUBIS=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=y -CONFIG_CRYPTO_CRC32C=y -# CONFIG_CRYPTO_TEST is not set - -# -# Hardware crypto devices -# - -# -# Library routines -# -# CONFIG_CRC_CCITT is not set -CONFIG_CRC16=y -CONFIG_CRC32=y -CONFIG_LIBCRC32C=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig index 8c911b6..c1c6bfe 100644 --- a/arch/mips/configs/ddb5477_defconfig +++ b/arch/mips/configs/ddb5477_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set CONFIG_DDB5477=y # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -129,6 +127,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig index d838496..d5d0d3f 100644 --- a/arch/mips/configs/decstation_defconfig +++ b/arch/mips/configs/decstation_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -128,6 +126,17 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_128=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_128HZ=y +CONFIG_SYS_SUPPORTS_256HZ=y +CONFIG_SYS_SUPPORTS_1024HZ=y +CONFIG_HZ=128 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig index 0760f43..439677b 100644 --- a/arch/mips/configs/e55_defconfig +++ b/arch/mips/configs/e55_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set CONFIG_MACH_VR41XX=y # CONFIG_PMC_YOSEMITE is not set @@ -130,6 +128,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig new file mode 100644 index 0000000..01f29f4 --- /dev/null +++ b/arch/mips/configs/emma2rh_defconfig @@ -0,0 +1,1207 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17 +# Sun Jun 18 13:46:53 2006 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MIPS_MTX1 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set +# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set +# CONFIG_MIPS_DB1200 is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_WR_PPMC is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_3 is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_PNX8550_V2PCI is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_DDB5477 is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_QEMU is not set +CONFIG_MARKEINS=y +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_PTSWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_TOSHIBA_RBTX4938 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_CPU_BIG_ENDIAN=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_EMMA2RH=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# CONFIG_CPU_MIPS32_R1 is not set +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_SYS_HAS_CPU_R5000=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMTC is not set +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_VPE_LOADER is not set +# CONFIG_64BIT_PHYS_ADDR is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_BKL=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set +CONFIG_OBSOLETE_INTERMODULE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +CONFIG_MMU=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_FWMARK is not set +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_IPV6_TUNNEL is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +# CONFIG_IP6_NF_QUEUE is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x1e000000 +CONFIG_MTD_PHYSMAP_LEN=0x02000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_DM9000 is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +CONFIG_NATSEMI=y +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_LAN_SAA9730 is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPP_MPPE is not set +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_RTC=m +CONFIG_GEN_RTC=m +CONFIG_GEN_RTC_X=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +CONFIG_I2C_DEBUG_CORE=y +# CONFIG_I2C_DEBUG_ALGO is not set +CONFIG_I2C_DEBUG_BUS=y +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_EXPORT=y +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_SECURITY is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=m +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_FS is not set +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="console=ttyS0,115200 mem=192m ip=bootp root=/dev/nfs rw" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig index 7067f60..5248a1d 100644 --- a/arch/mips/configs/ev64120_defconfig +++ b/arch/mips/configs/ev64120_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -131,6 +129,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig index 00b56ed..4858491 100644 --- a/arch/mips/configs/ev96100_defconfig +++ b/arch/mips/configs/ev96100_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -135,6 +133,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig new file mode 100644 index 0000000..f2ce64c --- /dev/null +++ b/arch/mips/configs/excite_defconfig @@ -0,0 +1,1220 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.16-rc4 +# Thu Feb 23 13:15:27 2006 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MIPS_MTX1 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set +# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set +# CONFIG_MIPS_DB1200 is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_3 is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_PNX8550_V2PCI is not set +# CONFIG_PNX8550_JBS is not set +CONFIG_BASLER_EXCITE=y +# CONFIG_BASLER_EXCITE_PROTOTYPE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_QEMU is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_PTSWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_TOSHIBA_RBTX4938 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_DMA_COHERENT=y +CONFIG_SERIAL_RM9000=y +CONFIG_CPU_BIG_ENDIAN=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_IRQ_CPU_RM7K=y +CONFIG_IRQ_CPU_RM9K=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# CONFIG_CPU_MIPS32_R1 is not set +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +CONFIG_CPU_RM9000=y +# CONFIG_CPU_SB1 is not set +CONFIG_SYS_HAS_CPU_RM9000=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_MIPS_MT is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 +# CONFIG_SMP is not set +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_BKL=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_LBD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +# CONFIG_PCI_LEGACY_PROC is not set +CONFIG_MMU=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_VERIFY_WRITE=y +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_BASLER_EXCITE=y +# CONFIG_MTD_NAND_BASLER_EXCITE_RDNBY is not set +# CONFIG_MTD_NAND_BASLER_EXCITE_PERF is not set +# CONFIG_MTD_NAND_NANDSIM is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +# CONFIG_TITAN_GE is not set +CONFIG_RM9K_GE=m + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_WDT_RM9K_GPI=m + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON_OLD is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_SMIVGX is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FB_DD=y + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=m +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +# CONFIG_LOGO is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +CONFIG_USB_ARTTFT=m +# CONFIG_USB_ARTTOUCH is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# SN Devices +# + +# +# EDAC - error detection and reporting (RAS) +# + +# +# eXcite frame capture support +# +CONFIG_EXCITE_FCAP=m +CONFIG_EXCITE_FCAP_GPI=m + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=m +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig index 607e298..879ba1a 100644 --- a/arch/mips/configs/ip22_defconfig +++ b/arch/mips/configs/ip22_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -136,6 +134,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index f724b4b..bb14268 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -63,7 +61,7 @@ # CONFIG_SNI_RM200_PCI is not set # CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_TOSHIBA_RBTX4927 is not set # CONFIG_TOSHIBA_RBTX4938 is not set -# CONFIG_SGI_SN0_N_MODE is not set +# CONFIG_SGI_SN_N_MODE is not set CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_NUMA=y # CONFIG_MAPPED_KERNEL is not set @@ -135,6 +133,15 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_NEED_MULTIPLE_NODES=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_MIGRATION=y CONFIG_SMP=y CONFIG_NR_CPUS=64 diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index 8f11d35..31b3c92 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -136,6 +134,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig index 757adf2..809bae9 100644 --- a/arch/mips/configs/it8172_defconfig +++ b/arch/mips/configs/it8172_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -130,6 +128,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig index 021761a..55108fd 100644 --- a/arch/mips/configs/ivr_defconfig +++ b/arch/mips/configs/ivr_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -127,6 +125,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig index 08f6c30..ef28434 100644 --- a/arch/mips/configs/jaguar-atx_defconfig +++ b/arch/mips/configs/jaguar-atx_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -136,6 +134,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 # CONFIG_SMP is not set CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig index 38b1e02..5ef5a08 100644 --- a/arch/mips/configs/jmr3927_defconfig +++ b/arch/mips/configs/jmr3927_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -125,6 +123,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig index 4d25990..eabcff2 100644 --- a/arch/mips/configs/lasat200_defconfig +++ b/arch/mips/configs/lasat200_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -134,6 +132,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig index 977f52b..b73cff0 100644 --- a/arch/mips/configs/malta_defconfig +++ b/arch/mips/configs/malta_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -154,6 +152,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +CONFIG_HZ_100=y +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=100 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig index 00560e0..8dd27b5 100644 --- a/arch/mips/configs/mipssim_defconfig +++ b/arch/mips/configs/mipssim_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -138,6 +136,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig index 286a018..5d6ff3c 100644 --- a/arch/mips/configs/mpc30x_defconfig +++ b/arch/mips/configs/mpc30x_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set CONFIG_MACH_VR41XX=y # CONFIG_PMC_YOSEMITE is not set @@ -132,6 +130,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig index 1ce4310..fe5e3dd 100644 --- a/arch/mips/configs/ocelot_3_defconfig +++ b/arch/mips/configs/ocelot_3_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -136,6 +134,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 # CONFIG_SMP is not set CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig index 8a6aa50..f4a33ce 100644 --- a/arch/mips/configs/ocelot_c_defconfig +++ b/arch/mips/configs/ocelot_c_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -133,6 +131,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig index f9ee35e..21dea95 100644 --- a/arch/mips/configs/ocelot_defconfig +++ b/arch/mips/configs/ocelot_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -137,6 +135,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig index b48bdee..c63b1ca 100644 --- a/arch/mips/configs/ocelot_g_defconfig +++ b/arch/mips/configs/ocelot_g_defconfig @@ -41,8 +41,6 @@ CONFIG_MOMENCO_OCELOT_G=y # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -136,6 +134,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig index 01aac40..6f5c726 100644 --- a/arch/mips/configs/pb1100_defconfig +++ b/arch/mips/configs/pb1100_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -132,6 +130,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig index 398c3c2..5676f37 100644 --- a/arch/mips/configs/pb1500_defconfig +++ b/arch/mips/configs/pb1500_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -131,6 +129,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig index ea282a5..a1c479f 100644 --- a/arch/mips/configs/pb1550_defconfig +++ b/arch/mips/configs/pb1550_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -131,6 +129,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig index 4c57e56..b2d991b 100644 --- a/arch/mips/configs/pnx8550-jbs_defconfig +++ b/arch/mips/configs/pnx8550-jbs_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set CONFIG_PNX8550_JBS=y -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -130,6 +128,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig index 3c8f351..fe092ac 100644 --- a/arch/mips/configs/pnx8550-v2pci_defconfig +++ b/arch/mips/configs/pnx8550-v2pci_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set CONFIG_PNX8550_V2PCI=y # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -130,6 +128,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig index 4bcc01d..db87013 100644 --- a/arch/mips/configs/qemu_defconfig +++ b/arch/mips/configs/qemu_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -128,6 +126,15 @@ CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_SMP is not set +# CONFIG_HZ_48 is not set +CONFIG_HZ_100=y +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=100 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig index 3d44193..b16731f 100644 --- a/arch/mips/configs/rbhma4500_defconfig +++ b/arch/mips/configs/rbhma4500_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -138,6 +136,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig index edfb967..8b0dd86 100644 --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -138,6 +136,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig index e388a3d..ff34ed6 100644 --- a/arch/mips/configs/sb1250-swarm_defconfig +++ b/arch/mips/configs/sb1250-swarm_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -149,6 +147,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_SMP=y CONFIG_NR_CPUS=2 CONFIG_PREEMPT_NONE=y diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig index 6b8a6a4..77edeae 100644 --- a/arch/mips/configs/sead_defconfig +++ b/arch/mips/configs/sead_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -134,6 +132,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig index dba0bdc..6aa229d 100644 --- a/arch/mips/configs/tb0226_defconfig +++ b/arch/mips/configs/tb0226_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set CONFIG_MACH_VR41XX=y # CONFIG_PMC_YOSEMITE is not set @@ -134,6 +132,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig index 5a924c1..a187b1f 100644 --- a/arch/mips/configs/tb0229_defconfig +++ b/arch/mips/configs/tb0229_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set CONFIG_MACH_VR41XX=y # CONFIG_PMC_YOSEMITE is not set @@ -134,6 +132,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig index 9f215ea..258457f 100644 --- a/arch/mips/configs/tb0287_defconfig +++ b/arch/mips/configs/tb0287_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set CONFIG_MACH_VR41XX=y # CONFIG_PMC_YOSEMITE is not set @@ -135,6 +133,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig index ac7765e..68af54f 100644 --- a/arch/mips/configs/workpad_defconfig +++ b/arch/mips/configs/workpad_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set CONFIG_MACH_VR41XX=y # CONFIG_PMC_YOSEMITE is not set @@ -130,6 +128,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig new file mode 100644 index 0000000..40572a3 --- /dev/null +++ b/arch/mips/configs/wrppmc_defconfig @@ -0,0 +1,808 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.16.11 +# Fri May 5 17:11:22 2006 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MIPS_MTX1 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set +# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set +# CONFIG_MIPS_DB1200 is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +CONFIG_WR_PPMC=y +# CONFIG_MIPS_SIM is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_3 is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_PNX8550_V2PCI is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_DDB5477 is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_QEMU is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_PTSWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_TOSHIBA_RBTX4938 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_CPU_BIG_ENDIAN=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_MIPS_GT64120=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_CPU_MIPS64_R1=y +CONFIG_SYS_HAS_CPU_NEVADA=y +CONFIG_SYS_HAS_CPU_RM7000=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_MIPS_MT is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +# CONFIG_EPOLL is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_LBD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_MMU=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_FAKE is not set +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_TRAD_SIGNALS=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +CONFIG_ARPD=y +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_DM9000 is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_LAN_SAA9730 is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=1 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="console=ttyS0,115200n8" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC32=y +CONFIG_LIBCRC32C=y diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig index b52d709..7ece2c0 100644 --- a/arch/mips/configs/yosemite_defconfig +++ b/arch/mips/configs/yosemite_defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set CONFIG_PMC_YOSEMITE=y @@ -130,6 +128,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 CONFIG_SMP=y CONFIG_NR_CPUS=2 CONFIG_PREEMPT_NONE=y diff --git a/arch/mips/ddb5xxx/common/prom.c b/arch/mips/ddb5xxx/common/prom.c index b8d1f74..00c62c1 100644 --- a/arch/mips/ddb5xxx/common/prom.c +++ b/arch/mips/ddb5xxx/common/prom.c @@ -56,13 +56,7 @@ void __init prom_init(void) mips_machgroup = MACH_GROUP_NEC_DDB; -#if defined(CONFIG_DDB5074) - mips_machtype = MACH_NEC_DDB5074; - add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM); -#elif defined(CONFIG_DDB5476) - mips_machtype = MACH_NEC_DDB5476; - add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM); -#elif defined(CONFIG_DDB5477) +#if defined(CONFIG_DDB5477) ddb5477_runtime_detection(); add_memory_region(0, board_ram_size, BOOT_MEM_RAM); #endif diff --git a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile deleted file mode 100644 index 304c021..0000000 --- a/arch/mips/ddb5xxx/ddb5074/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines -# under Linux. -# - -obj-y += setup.o irq.o nile4_pic.o - -EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c deleted file mode 100644 index 60c087b..0000000 --- a/arch/mips/ddb5xxx/ddb5074/irq.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * arch/mips/ddb5074/irq.c -- NEC DDB Vrc-5074 interrupt routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - - -static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL }; - -#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */ -#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */ -#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */ - -#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */ -#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */ -#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */ - -#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */ -#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */ - -#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */ -#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */ - -#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */ -#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */ - - -static void m1543_irq_setup(void) -{ - /* - * The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all - * the possible IO sources in the M1543 are in use by us. We will - * use the following mapping: - * - * IRQ1 - keyboard (default set by M1543) - * IRQ3 - reserved for UART B (default set by M1543) (note that - * the schematics for the DDB Vrc-5074 board seem to - * indicate that IRQ3 is connected to the DS1386 - * watchdog timer interrupt output so we might have - * a conflict) - * IRQ4 - reserved for UART A (default set by M1543) - * IRQ5 - parallel (default set by M1543) - * IRQ8 - DS1386 time of day (RTC) interrupt - * IRQ12 - mouse - */ - - /* - * Assing mouse interrupt to IRQ12 - */ - - /* Enter configuration mode */ - outb(0x51, M1543_PNP_CONFIG); - outb(0x23, M1543_PNP_CONFIG); - - /* Select logical device 7 (Keyboard) */ - outb(0x07, M1543_PNP_INDEX); - outb(0x07, M1543_PNP_DATA); - - /* Select IRQ12 */ - outb(0x72, M1543_PNP_INDEX); - outb(0x0c, M1543_PNP_DATA); - - outb(0x30, M1543_PNP_INDEX); - printk("device 7, 0x30: %02x\n",inb(M1543_PNP_DATA)); - - outb(0x70, M1543_PNP_INDEX); - printk("device 7, 0x70: %02x\n",inb(M1543_PNP_DATA)); - - /* Leave configration mode */ - outb(0xbb, M1543_PNP_CONFIG); - - -} - -static void ddb_local0_irqdispatch(struct pt_regs *regs) -{ - u32 mask; - int nile4_irq; - - mask = nile4_get_irq_stat(0); - - /* Handle the timer interrupt first */ -#if 0 - if (mask & (1 << NILE4_INT_GPT)) { - do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs); - mask &= ~(1 << NILE4_INT_GPT); - } -#endif - for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1) - if (mask & 1) { - if (nile4_irq == NILE4_INT_INTE) { - int i8259_irq; - - nile4_clear_irq(NILE4_INT_INTE); - i8259_irq = nile4_i8259_iack(); - do_IRQ(i8259_irq, regs); - } else - do_IRQ(nile4_to_irq(nile4_irq), regs); - - } -} - -static void ddb_local1_irqdispatch(void) -{ - printk("ddb_local1_irqdispatch called\n"); -} - -static void ddb_buserror_irq(void) -{ - printk("ddb_buserror_irq called\n"); -} - -static void ddb_8254timer_irq(void) -{ - printk("ddb_8254timer_irq called\n"); -} - -asmlinkage void plat_irq_dispatch(struct pt_regs *regs) -{ - unsigned int pending = read_c0_cause() & read_c0_status(); - - if (pending & CAUSEF_IP2) - ddb_local0_irqdispatch(regs); - else if (pending & CAUSEF_IP3) - ddb_local1_irqdispatch(); - else if (pending & CAUSEF_IP6) - ddb_buserror_irq(); - else if (pending & (CAUSEF_IP4 | CAUSEF_IP5)) - ddb_8254timer_irq(); -} - -void __init arch_init_irq(void) -{ - /* setup cascade interrupts */ - setup_irq(NILE4_IRQ_BASE + NILE4_INT_INTE, &irq_cascade); - setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade); - - nile4_irq_setup(NILE4_IRQ_BASE); - m1543_irq_setup(); - init_i8259_irqs(); - - - printk("CPU_IRQ_BASE: %d\n",CPU_IRQ_BASE); - - mips_cpu_irq_init(CPU_IRQ_BASE); - - printk("enabling 8259 cascade\n"); - - ddb5074_led_hex(0); - - /* Enable the interrupt cascade */ - nile4_enable_irq(NILE4_IRQ_BASE+IRQ_I8259_CASCADE); -} diff --git a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c deleted file mode 100644 index 8743ffc..0000000 --- a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * arch/mips/ddb5476/nile4.c -- - * low-level PIC code for NEC Vrc-5476 (Nile 4) - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - * - * Copyright 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - * - */ -#include -#include -#include -#include -#include - -#include - -#include - -static int irq_base; - -/* - * Interrupt Programming - */ -void nile4_map_irq(int nile4_irq, int cpu_irq) -{ - u32 offset, t; - - offset = DDB_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - t = ddb_in32(offset); - t &= ~(7 << (nile4_irq * 4)); - t |= cpu_irq << (nile4_irq * 4); - ddb_out32(offset, t); -} - -void nile4_map_irq_all(int cpu_irq) -{ - u32 all, t; - - all = cpu_irq; - all |= all << 4; - all |= all << 8; - all |= all << 16; - t = ddb_in32(DDB_INTCTRL); - t &= 0x88888888; - t |= all; - ddb_out32(DDB_INTCTRL, t); - t = ddb_in32(DDB_INTCTRL + 4); - t &= 0x88888888; - t |= all; - ddb_out32(DDB_INTCTRL + 4, t); -} - -void nile4_enable_irq(unsigned int nile4_irq) -{ - u32 offset, t; - - nile4_irq-=irq_base; - - ddb5074_led_hex(8); - - offset = DDB_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - ddb5074_led_hex(9); - t = ddb_in32(offset); - ddb5074_led_hex(0xa); - t |= 8 << (nile4_irq * 4); - ddb_out32(offset, t); - ddb5074_led_hex(0xb); -} - -void nile4_disable_irq(unsigned int nile4_irq) -{ - u32 offset, t; - - nile4_irq-=irq_base; - - offset = DDB_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - t = ddb_in32(offset); - t &= ~(8 << (nile4_irq * 4)); - ddb_out32(offset, t); -} - -void nile4_disable_irq_all(void) -{ - ddb_out32(DDB_INTCTRL, 0); - ddb_out32(DDB_INTCTRL + 4, 0); -} - -u16 nile4_get_irq_stat(int cpu_irq) -{ - return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2); -} - -void nile4_enable_irq_output(int cpu_irq) -{ - u32 t; - - t = ddb_in32(DDB_INTSTAT1 + 4); - t |= 1 << (16 + cpu_irq); - ddb_out32(DDB_INTSTAT1, t); -} - -void nile4_disable_irq_output(int cpu_irq) -{ - u32 t; - - t = ddb_in32(DDB_INTSTAT1 + 4); - t &= ~(1 << (16 + cpu_irq)); - ddb_out32(DDB_INTSTAT1, t); -} - -void nile4_set_pci_irq_polarity(int pci_irq, int high) -{ - u32 t; - - t = ddb_in32(DDB_INTPPES); - if (high) - t &= ~(1 << (pci_irq * 2)); - else - t |= 1 << (pci_irq * 2); - ddb_out32(DDB_INTPPES, t); -} - -void nile4_set_pci_irq_level_or_edge(int pci_irq, int level) -{ - u32 t; - - t = ddb_in32(DDB_INTPPES); - if (level) - t |= 2 << (pci_irq * 2); - else - t &= ~(2 << (pci_irq * 2)); - ddb_out32(DDB_INTPPES, t); -} - -void nile4_clear_irq(int nile4_irq) -{ - nile4_irq-=irq_base; - ddb_out32(DDB_INTCLR, 1 << nile4_irq); -} - -void nile4_clear_irq_mask(u32 mask) -{ - ddb_out32(DDB_INTCLR, mask); -} - -u8 nile4_i8259_iack(void) -{ - u8 irq; - u32 reg; - - /* Set window 0 for interrupt acknowledge */ - reg = ddb_in32(DDB_PCIINIT0); - - ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32); - irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE); - /* restore window 0 for PCI I/O space */ - // ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32); - ddb_out32(DDB_PCIINIT0, reg); - - /* i8269.c set the base vector to be 0x0 */ - return irq ; -} - -static unsigned int nile4_irq_startup(unsigned int irq) { - - nile4_enable_irq(irq); - return 0; - -} - -static void nile4_ack_irq(unsigned int irq) { - - ddb5074_led_hex(4); - - nile4_clear_irq(irq); - ddb5074_led_hex(2); - nile4_disable_irq(irq); - - ddb5074_led_hex(0); -} - -static void nile4_irq_end(unsigned int irq) { - - ddb5074_led_hex(3); - if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - ddb5074_led_hex(5); - nile4_enable_irq(irq); - ddb5074_led_hex(7); - } - - ddb5074_led_hex(1); -} - -#define nile4_irq_shutdown nile4_disable_irq - -static hw_irq_controller nile4_irq_controller = { - .typename = "nile4", - .startup = nile4_irq_startup, - .shutdown = nile4_irq_shutdown, - .enable = nile4_enable_irq, - .disable = nile4_disable_irq, - .ack = nile4_ack_irq, - .end = nile4_irq_end, -}; - -void nile4_irq_setup(u32 base) { - - int i; - - irq_base=base; - - /* Map all interrupts to CPU int #0 */ - nile4_map_irq_all(0); - - /* PCI INTA#-E# must be level triggered */ - nile4_set_pci_irq_level_or_edge(0, 1); - nile4_set_pci_irq_level_or_edge(1, 1); - nile4_set_pci_irq_level_or_edge(2, 1); - nile4_set_pci_irq_level_or_edge(3, 1); - nile4_set_pci_irq_level_or_edge(4, 1); - - /* PCI INTA#-D# must be active low, INTE# must be active high */ - nile4_set_pci_irq_polarity(0, 0); - nile4_set_pci_irq_polarity(1, 0); - nile4_set_pci_irq_polarity(2, 0); - nile4_set_pci_irq_polarity(3, 0); - nile4_set_pci_irq_polarity(4, 1); - - - for (i = 0; i < 16; i++) { - nile4_clear_irq(i); - nile4_disable_irq(i); - } - - /* Enable CPU int #0 */ - nile4_enable_irq_output(0); - - for (i= base; i< base + NUM_NILE4_INTERRUPTS; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].handler = &nile4_irq_controller; - } -} - -#if defined(CONFIG_RUNTIME_DEBUG) -void nile4_dump_irq_status(void) -{ - printk(KERN_DEBUG " - CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4), - (void *) ddb_in32(DDB_CPUSTAT)); - printk(KERN_DEBUG " - INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4), - (void *) ddb_in32(DDB_INTCTRL)); - printk(KERN_DEBUG - "INTSTAT0 = %p:%p\n", - (void *) ddb_in32(DDB_INTSTAT0 + 4), - (void *) ddb_in32(DDB_INTSTAT0)); - printk(KERN_DEBUG - "INTSTAT1 = %p:%p\n", - (void *) ddb_in32(DDB_INTSTAT1 + 4), - (void *) ddb_in32(DDB_INTSTAT1)); - printk(KERN_DEBUG - "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4), - (void *) ddb_in32(DDB_INTCLR)); - printk(KERN_DEBUG - "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4), - (void *) ddb_in32(DDB_INTPPES)); -} - -#endif diff --git a/arch/mips/ddb5xxx/ddb5074/setup.c b/arch/mips/ddb5xxx/ddb5074/setup.c deleted file mode 100644 index 91456b0..0000000 --- a/arch/mips/ddb5xxx/ddb5074/setup.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * arch/mips/ddb5074/setup.c -- NEC DDB Vrc-5074 setup routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000; - -static void ddb_machine_restart(char *command) -{ - u32 t; - - /* PCI cold reset */ - t = nile4_in32(NILE4_PCICTRL + 4); - t |= 0x40000000; - nile4_out32(NILE4_PCICTRL + 4, t); - /* CPU cold reset */ - t = nile4_in32(NILE4_CPUSTAT); - t |= 1; - nile4_out32(NILE4_CPUSTAT, t); - /* Call the PROM */ - back_to_prom(); -} - -static void ddb_machine_halt(void) -{ - printk("DDB Vrc-5074 halted.\n"); - do { - } while (1); -} - -static void ddb_machine_power_off(void) -{ - printk("DDB Vrc-5074 halted. Please turn off the power.\n"); - do { - } while (1); -} - -extern void rtc_ds1386_init(unsigned long base); - -extern void (*board_timer_setup) (struct irqaction * irq); - -static void __init ddb_timer_init(struct irqaction *irq) -{ - /* set the clock to 1 Hz */ - nile4_out32(NILE4_T2CTRL, 1000000); - /* enable the General-Purpose Timer */ - nile4_out32(NILE4_T2CTRL + 4, 0x00000001); - /* reset timer */ - nile4_out32(NILE4_T2CNTR, 0); - /* enable interrupt */ - setup_irq(nile4_to_irq(NILE4_INT_GPT), irq); - nile4_enable_irq(nile4_to_irq(NILE4_INT_GPT)); - change_c0_status(ST0_IM, - IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4); - -} - -static void __init ddb_time_init(void) -{ - /* we have ds1396 RTC chip */ - rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE)); -} - - - -void __init plat_setup(void) -{ - set_io_port_base(NILE4_PCI_IO_BASE); - isa_slot_offset = NILE4_PCI_MEM_BASE; - board_timer_setup = ddb_timer_init; - board_time_init = ddb_time_init; - - - _machine_restart = ddb_machine_restart; - _machine_halt = ddb_machine_halt; - pm_power_off = ddb_machine_power_off; - - ddb_out32(DDB_BAR0, 0); - - ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, 0x10); - ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE , 0x10); - - /* Reboot on panic */ - panic_timeout = 180; -} - -#define USE_NILE4_SERIAL 0 - -#if USE_NILE4_SERIAL -#define ns16550_in(reg) nile4_in8((reg)*8) -#define ns16550_out(reg, val) nile4_out8((reg)*8, (val)) -#else -#define NS16550_BASE (NILE4_PCI_IO_BASE+0x03f8) -static inline u8 ns16550_in(u32 reg) -{ - return *(volatile u8 *) (NS16550_BASE + reg); -} - -static inline void ns16550_out(u32 reg, u8 val) -{ - *(volatile u8 *) (NS16550_BASE + reg) = val; -} -#endif - -#define NS16550_RBR 0 -#define NS16550_THR 0 -#define NS16550_DLL 0 -#define NS16550_IER 1 -#define NS16550_DLM 1 -#define NS16550_FCR 2 -#define NS16550_IIR 2 -#define NS16550_LCR 3 -#define NS16550_MCR 4 -#define NS16550_LSR 5 -#define NS16550_MSR 6 -#define NS16550_SCR 7 - -#define NS16550_LSR_DR 0x01 /* Data ready */ -#define NS16550_LSR_OE 0x02 /* Overrun */ -#define NS16550_LSR_PE 0x04 /* Parity error */ -#define NS16550_LSR_FE 0x08 /* Framing error */ -#define NS16550_LSR_BI 0x10 /* Break */ -#define NS16550_LSR_THRE 0x20 /* Xmit holding register empty */ -#define NS16550_LSR_TEMT 0x40 /* Xmitter empty */ -#define NS16550_LSR_ERR 0x80 /* Error */ - - -void _serinit(void) -{ -#if USE_NILE4_SERIAL - ns16550_out(NS16550_LCR, 0x80); - ns16550_out(NS16550_DLM, 0x00); - ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */ - ns16550_out(NS16550_LCR, 0x00); - ns16550_out(NS16550_LCR, 0x03); - ns16550_out(NS16550_FCR, 0x47); -#else - /* done by PMON */ -#endif -} - -void _putc(char c) -{ - while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE)); - ns16550_out(NS16550_THR, c); - if (c == '\n') { - while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE)); - ns16550_out(NS16550_THR, '\r'); - } -} - -void _puts(const char *s) -{ - char c; - while ((c = *s++)) - _putc(c); -} - -char _getc(void) -{ - while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR)); - return ns16550_in(NS16550_RBR); -} - -int _testc(void) -{ - return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0; -} - - -/* - * Hexadecimal 7-segment LED - */ -void ddb5074_led_hex(int hex) -{ - outb(hex, 0x80); -} - - -/* - * LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543 - */ -struct pci_dev *pci_pmu = NULL; - -void ddb5074_led_d2(int on) -{ - u8 t; - - if (pci_pmu) { - pci_read_config_byte(pci_pmu, 0x7e, &t); - if (on) - t &= 0x7f; - else - t |= 0x80; - pci_write_config_byte(pci_pmu, 0x7e, t); - } -} - -void ddb5074_led_d3(int on) -{ - u8 t; - - if (pci_pmu) { - pci_read_config_byte(pci_pmu, 0x7e, &t); - if (on) - t &= 0xbf; - else - t |= 0x40; - pci_write_config_byte(pci_pmu, 0x7e, t); - } -} diff --git a/arch/mips/ddb5xxx/ddb5476/Makefile b/arch/mips/ddb5xxx/ddb5476/Makefile deleted file mode 100644 index ab0312c..0000000 --- a/arch/mips/ddb5xxx/ddb5476/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for the NEC DDB Vrc-5476 specific kernel interface routines -# under Linux. -# - -obj-y += setup.o irq.o nile4_pic.o vrc5476_irq.o -obj-$(CONFIG_KGDB) += dbg_io.o - -EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/ddb5xxx/ddb5476/dbg_io.c b/arch/mips/ddb5xxx/ddb5476/dbg_io.c deleted file mode 100644 index f2296a9..0000000 --- a/arch/mips/ddb5xxx/ddb5476/dbg_io.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * kgdb io functions for DDB5476. We use the second serial port. - * - * Copyright (C) 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -/* ======================= CONFIG ======================== */ - -/* [jsun] we use the second serial port for kdb */ -#define BASE 0xa60002f8 -#define MAX_BAUD 115200 - -/* distance in bytes between two serial registers */ -#define REG_OFFSET 1 - -/* - * 0 - kgdb does serial init - * 1 - kgdb skip serial init - */ -static int remoteDebugInitialized = 0; - -/* - * the default baud rate *if* kgdb does serial init - */ -#define BAUD_DEFAULT UART16550_BAUD_38400 - -/* ======================= END OF CONFIG ======================== */ - -typedef unsigned char uint8; -typedef unsigned int uint32; - -#define UART16550_BAUD_2400 2400 -#define UART16550_BAUD_4800 4800 -#define UART16550_BAUD_9600 9600 -#define UART16550_BAUD_19200 19200 -#define UART16550_BAUD_38400 38400 -#define UART16550_BAUD_57600 57600 -#define UART16550_BAUD_115200 115200 - -#define UART16550_PARITY_NONE 0 -#define UART16550_PARITY_ODD 0x08 -#define UART16550_PARITY_EVEN 0x18 -#define UART16550_PARITY_MARK 0x28 -#define UART16550_PARITY_SPACE 0x38 - -#define UART16550_DATA_5BIT 0x0 -#define UART16550_DATA_6BIT 0x1 -#define UART16550_DATA_7BIT 0x2 -#define UART16550_DATA_8BIT 0x3 - -#define UART16550_STOP_1BIT 0x0 -#define UART16550_STOP_2BIT 0x4 - -/* register offset */ -#define OFS_RCV_BUFFER 0 -#define OFS_TRANS_HOLD 0 -#define OFS_SEND_BUFFER 0 -#define OFS_INTR_ENABLE (1*REG_OFFSET) -#define OFS_INTR_ID (2*REG_OFFSET) -#define OFS_DATA_FORMAT (3*REG_OFFSET) -#define OFS_LINE_CONTROL (3*REG_OFFSET) -#define OFS_MODEM_CONTROL (4*REG_OFFSET) -#define OFS_RS232_OUTPUT (4*REG_OFFSET) -#define OFS_LINE_STATUS (5*REG_OFFSET) -#define OFS_MODEM_STATUS (6*REG_OFFSET) -#define OFS_RS232_INPUT (6*REG_OFFSET) -#define OFS_SCRATCH_PAD (7*REG_OFFSET) - -#define OFS_DIVISOR_LSB (0*REG_OFFSET) -#define OFS_DIVISOR_MSB (1*REG_OFFSET) - - -/* memory-mapped read/write of the port */ -#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) -#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) - -void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) -{ - /* disable interrupts */ - UART16550_WRITE(OFS_INTR_ENABLE, 0); - - /* set up baud rate */ - { - uint32 divisor; - - /* set DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x80); - - /* set divisor */ - divisor = MAX_BAUD / baud; - UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); - UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); - - /* clear DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x0); - } - - /* set data format */ - UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); -} - - -uint8 getDebugChar(void) -{ - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(BAUD_DEFAULT, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, UART16550_STOP_1BIT); - } - - while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); - return UART16550_READ(OFS_RCV_BUFFER); -} - - -int putDebugChar(uint8 byte) -{ - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(BAUD_DEFAULT, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, UART16550_STOP_1BIT); - } - - while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); - UART16550_WRITE(OFS_SEND_BUFFER, byte); - return 1; -} diff --git a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c deleted file mode 100644 index 7583a1f..0000000 --- a/arch/mips/ddb5xxx/ddb5476/irq.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - * - * Re-write the whole thing to use new irq.c file. - * Copyright (C) 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - */ -#include -#include -#include -#include - -#include -#include -#include - -#include - -#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */ -#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */ -#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */ - -#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */ -#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */ -#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */ - -#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */ -#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */ - -#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */ -#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */ - -#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */ -#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */ - -static void m1543_irq_setup(void) -{ - /* - * The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all - * the possible IO sources in the M1543 are in use by us. We will - * use the following mapping: - * - * IRQ1 - keyboard (default set by M1543) - * IRQ3 - reserved for UART B (default set by M1543) (note that - * the schematics for the DDB Vrc-5476 board seem to - * indicate that IRQ3 is connected to the DS1386 - * watchdog timer interrupt output so we might have - * a conflict) - * IRQ4 - reserved for UART A (default set by M1543) - * IRQ5 - parallel (default set by M1543) - * IRQ8 - DS1386 time of day (RTC) interrupt - * IRQ9 - USB (hardwired in ddb_setup) - * IRQ10 - PMU (hardwired in ddb_setup) - * IRQ12 - mouse - * IRQ14,15 - IDE controller (need to be confirmed, jsun) - */ - - /* - * Assing mouse interrupt to IRQ12 - */ - - /* Enter configuration mode */ - outb(0x51, M1543_PNP_CONFIG); - outb(0x23, M1543_PNP_CONFIG); - - /* Select logical device 7 (Keyboard) */ - outb(0x07, M1543_PNP_INDEX); - outb(0x07, M1543_PNP_DATA); - - /* Select IRQ12 */ - outb(0x72, M1543_PNP_INDEX); - outb(0x0c, M1543_PNP_DATA); - - /* Leave configration mode */ - outb(0xbb, M1543_PNP_CONFIG); -} - -static void nile4_irq_setup(void) -{ - int i; - - /* Map all interrupts to CPU int #0 (IP2) */ - nile4_map_irq_all(0); - - /* PCI INTA#-E# must be level triggered */ - nile4_set_pci_irq_level_or_edge(0, 1); - nile4_set_pci_irq_level_or_edge(1, 1); - nile4_set_pci_irq_level_or_edge(2, 1); - nile4_set_pci_irq_level_or_edge(3, 1); - - /* PCI INTA#, B#, D# must be active low, INTC# must be active high */ - nile4_set_pci_irq_polarity(0, 0); - nile4_set_pci_irq_polarity(1, 0); - nile4_set_pci_irq_polarity(2, 1); - nile4_set_pci_irq_polarity(3, 0); - - for (i = 0; i < 16; i++) - nile4_clear_irq(i); - - /* Enable CPU int #0 */ - nile4_enable_irq_output(0); - - /* memory resource acquire in ddb_setup */ -} - -static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL }; -static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL }; - -extern int setup_irq(unsigned int irq, struct irqaction *irqaction); -extern void mips_cpu_irq_init(u32 irq_base); -extern void vrc5476_irq_init(u32 irq_base); - -extern void vrc5476_irq_dispatch(struct pt_regs *regs); - -asmlinkage void plat_irq_dispatch(struct pt_regs *regs) -{ - unsigned int pending = read_c0_cause() & read_c0_status(); - - if (pending & STATUSF_IP7) - do_IRQ(CPU_IRQ_BASE + 7, regs); - else if (pending & STATUSF_IP2) - vrc5476_irq_dispatch(regs); - else if (pending & STATUSF_IP3) - do_IRQ(CPU_IRQ_BASE + 3, regs); - else if (pending & STATUSF_IP4) - do_IRQ(CPU_IRQ_BASE + 4, regs); - else if (pending & STATUSF_IP5) - do_IRQ(CPU_IRQ_BASE + 5, regs); - else if (pending & STATUSF_IP6) - do_IRQ(CPU_IRQ_BASE + 6, regs); - else if (pending & STATUSF_IP0) - do_IRQ(CPU_IRQ_BASE, regs); - else if (pending & STATUSF_IP1) - do_IRQ(CPU_IRQ_BASE + 1, regs); - - vrc5476_irq_dispatch(regs); -} - -void __init arch_init_irq(void) -{ - /* hardware initialization */ - nile4_irq_setup(); - m1543_irq_setup(); - - /* controller setup */ - init_i8259_irqs(); - vrc5476_irq_init(VRC5476_IRQ_BASE); - mips_cpu_irq_init(CPU_IRQ_BASE); - - /* setup cascade interrupts */ - setup_irq(VRC5476_IRQ_BASE + VRC5476_I8259_CASCADE, &irq_cascade); - setup_irq(CPU_IRQ_BASE + CPU_VRC5476_CASCADE, &irq_cascade); - - /* setup error interrupts for debugging */ - setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CPCE, &irq_error); - setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CNTD, &irq_error); - setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_MCE, &irq_error); - setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error); - setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error); - setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error); -} diff --git a/arch/mips/ddb5xxx/ddb5476/nile4_pic.c b/arch/mips/ddb5xxx/ddb5476/nile4_pic.c deleted file mode 100644 index e930cee..0000000 --- a/arch/mips/ddb5xxx/ddb5476/nile4_pic.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * arch/mips/ddb5476/nile4.c -- - * low-level PIC code for NEC Vrc-5476 (Nile 4) - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - * - * Copyright 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - * - */ -#include -#include -#include - -#include - -#include - - -/* - * Interrupt Programming - */ -void nile4_map_irq(int nile4_irq, int cpu_irq) -{ - u32 offset, t; - - offset = DDB_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - t = ddb_in32(offset); - t &= ~(7 << (nile4_irq * 4)); - t |= cpu_irq << (nile4_irq * 4); - ddb_out32(offset, t); -} - -void nile4_map_irq_all(int cpu_irq) -{ - u32 all, t; - - all = cpu_irq; - all |= all << 4; - all |= all << 8; - all |= all << 16; - t = ddb_in32(DDB_INTCTRL); - t &= 0x88888888; - t |= all; - ddb_out32(DDB_INTCTRL, t); - t = ddb_in32(DDB_INTCTRL + 4); - t &= 0x88888888; - t |= all; - ddb_out32(DDB_INTCTRL + 4, t); -} - -void nile4_enable_irq(int nile4_irq) -{ - u32 offset, t; - - offset = DDB_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - t = ddb_in32(offset); - t |= 8 << (nile4_irq * 4); - ddb_out32(offset, t); -} - -void nile4_disable_irq(int nile4_irq) -{ - u32 offset, t; - - offset = DDB_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - t = ddb_in32(offset); - t &= ~(8 << (nile4_irq * 4)); - ddb_out32(offset, t); -} - -void nile4_disable_irq_all(void) -{ - ddb_out32(DDB_INTCTRL, 0); - ddb_out32(DDB_INTCTRL + 4, 0); -} - -u16 nile4_get_irq_stat(int cpu_irq) -{ - return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2); -} - -void nile4_enable_irq_output(int cpu_irq) -{ - u32 t; - - t = ddb_in32(DDB_INTSTAT1 + 4); - t |= 1 << (16 + cpu_irq); - ddb_out32(DDB_INTSTAT1, t); -} - -void nile4_disable_irq_output(int cpu_irq) -{ - u32 t; - - t = ddb_in32(DDB_INTSTAT1 + 4); - t &= ~(1 << (16 + cpu_irq)); - ddb_out32(DDB_INTSTAT1, t); -} - -void nile4_set_pci_irq_polarity(int pci_irq, int high) -{ - u32 t; - - t = ddb_in32(DDB_INTPPES); - if (high) - t &= ~(1 << (pci_irq * 2)); - else - t |= 1 << (pci_irq * 2); - ddb_out32(DDB_INTPPES, t); -} - -void nile4_set_pci_irq_level_or_edge(int pci_irq, int level) -{ - u32 t; - - t = ddb_in32(DDB_INTPPES); - if (level) - t |= 2 << (pci_irq * 2); - else - t &= ~(2 << (pci_irq * 2)); - ddb_out32(DDB_INTPPES, t); -} - -void nile4_clear_irq(int nile4_irq) -{ - ddb_out32(DDB_INTCLR, 1 << nile4_irq); -} - -void nile4_clear_irq_mask(u32 mask) -{ - ddb_out32(DDB_INTCLR, mask); -} - -u8 nile4_i8259_iack(void) -{ - u8 irq; - u32 reg; - - /* Set window 0 for interrupt acknowledge */ - reg = ddb_in32(DDB_PCIINIT0); - - ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32); - irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE); - /* restore window 0 for PCI I/O space */ - // ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32); - ddb_out32(DDB_PCIINIT0, reg); - - /* i8269.c set the base vector to be 0x0 */ - return irq + I8259_IRQ_BASE; -} - -#if defined(CONFIG_RUNTIME_DEBUG) -void nile4_dump_irq_status(void) -{ - printk(KERN_DEBUG " - CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4), - (void *) ddb_in32(DDB_CPUSTAT)); - printk(KERN_DEBUG " - INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4), - (void *) ddb_in32(DDB_INTCTRL)); - printk(KERN_DEBUG - "INTSTAT0 = %p:%p\n", - (void *) ddb_in32(DDB_INTSTAT0 + 4), - (void *) ddb_in32(DDB_INTSTAT0)); - printk(KERN_DEBUG - "INTSTAT1 = %p:%p\n", - (void *) ddb_in32(DDB_INTSTAT1 + 4), - (void *) ddb_in32(DDB_INTSTAT1)); - printk(KERN_DEBUG - "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4), - (void *) ddb_in32(DDB_INTCLR)); - printk(KERN_DEBUG - "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4), - (void *) ddb_in32(DDB_INTPPES)); -} -#endif diff --git a/arch/mips/ddb5xxx/ddb5476/setup.c b/arch/mips/ddb5xxx/ddb5476/setup.c deleted file mode 100644 index c902ade..0000000 --- a/arch/mips/ddb5xxx/ddb5476/setup.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * arch/mips/ddb5476/setup.c -- NEC DDB Vrc-5476 setup routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -// #define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */ - -#ifdef USE_CPU_COUNTER_TIMER - -#define CPU_COUNTER_FREQUENCY 83000000 -#else -/* otherwise we use general purpose timer */ -#define TIMER_FREQUENCY 83000000 -#define TIMER_BASE DDB_T2CTRL -#define TIMER_IRQ (VRC5476_IRQ_BASE + VRC5476_IRQ_GPT) -#endif - -static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000; - -static void ddb_machine_restart(char *command) -{ - u32 t; - - /* PCI cold reset */ - t = ddb_in32(DDB_PCICTRL + 4); - t |= 0x40000000; - ddb_out32(DDB_PCICTRL + 4, t); - /* CPU cold reset */ - t = ddb_in32(DDB_CPUSTAT); - t |= 1; - ddb_out32(DDB_CPUSTAT, t); - /* Call the PROM */ - back_to_prom(); -} - -static void ddb_machine_halt(void) -{ - printk(KERN_NOTICE "DDB Vrc-5476 halted.\n"); - while (1); -} - -static void ddb_machine_power_off(void) -{ - printk(KERN_NOTICE "DDB Vrc-5476 halted. Please turn off the power.\n"); - while (1); -} - -extern void rtc_ds1386_init(unsigned long base); - -static void __init ddb_time_init(void) -{ -#if defined(USE_CPU_COUNTER_TIMER) - mips_hpt_frequency = CPU_COUNTER_FREQUENCY; -#endif - - /* we have ds1396 RTC chip */ - rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE)); -} - - -extern int setup_irq(unsigned int irq, struct irqaction *irqaction); -static void __init ddb_timer_setup(struct irqaction *irq) -{ -#if defined(USE_CPU_COUNTER_TIMER) - - unsigned int count; - - /* we are using the cpu counter for timer interrupts */ - setup_irq(CPU_IRQ_BASE + 7, irq); - - /* to generate the first timer interrupt */ - count = read_c0_count(); - write_c0_compare(count + 1000); - -#else - - ddb_out32(TIMER_BASE, TIMER_FREQUENCY/HZ); - ddb_out32(TIMER_BASE+4, 0x1); /* enable timer */ - setup_irq(TIMER_IRQ, irq); -#endif -} - -static struct { - struct resource dma1; - struct resource timer; - struct resource rtc; - struct resource dma_page_reg; - struct resource dma2; -} ddb5476_ioport = { - { - "dma1", 0x00, 0x1f, IORESOURCE_BUSY}, { - "timer", 0x40, 0x5f, IORESOURCE_BUSY}, { - "rtc", 0x70, 0x7f, IORESOURCE_BUSY}, { - "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, { - "dma2", 0xc0, 0xdf, IORESOURCE_BUSY} -}; - -static struct { - struct resource nile4; -} ddb5476_iomem = { - { "Nile 4", DDB_BASE, DDB_BASE + DDB_SIZE - 1, IORESOURCE_BUSY} -}; - - -static void ddb5476_board_init(void); - -void __init plat_setup(void) -{ - set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE)); - - board_time_init = ddb_time_init; - board_timer_setup = ddb_timer_setup; - - _machine_restart = ddb_machine_restart; - _machine_halt = ddb_machine_halt; - pm_power_off = ddb_machine_power_off; - - /* request io port/mem resources */ - if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) || - request_resource(&ioport_resource, &ddb5476_ioport.timer) || - request_resource(&ioport_resource, &ddb5476_ioport.rtc) || - request_resource(&ioport_resource, - &ddb5476_ioport.dma_page_reg) - || request_resource(&ioport_resource, &ddb5476_ioport.dma2) - || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) { - printk - ("ddb_setup - requesting oo port resources failed.\n"); - for (;;); - } - - /* Reboot on panic */ - panic_timeout = 180; - - /* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */ - /* *(long*)0xbfa00218 = 0x8; */ - - /* board initialization stuff */ - ddb5476_board_init(); -} - -/* - * We don't trust bios. We essentially does hardware re-initialization - * as complete as possible, as far as we know we can safely do. - */ -static void ddb5476_board_init(void) -{ - /* ----------- setup PDARs ------------ */ - /* check SDRAM0, whether we are on MEM bus does not matter */ - db_assert((ddb_in32(DDB_SDRAM0) & 0xffffffef) == - ddb_calc_pdar(DDB_SDRAM_BASE, DDB_SDRAM_SIZE, 32, 0, 1)); - - /* SDRAM1 should be turned off. What is this for anyway ? */ - db_assert( (ddb_in32(DDB_SDRAM1) & 0xf) == 0); - - /* flash 1&2, DDB status, DDB control */ - ddb_set_pdar(DDB_DCS2, DDB_DCS2_BASE, DDB_DCS2_SIZE, 16, 0, 0); - ddb_set_pdar(DDB_DCS3, DDB_DCS3_BASE, DDB_DCS3_SIZE, 16, 0, 0); - ddb_set_pdar(DDB_DCS4, DDB_DCS4_BASE, DDB_DCS4_SIZE, 8, 0, 0); - ddb_set_pdar(DDB_DCS5, DDB_DCS5_BASE, DDB_DCS5_SIZE, 8, 0, 0); - - /* shut off other pdar so they don't accidentally get into the way */ - ddb_set_pdar(DDB_DCS6, 0xffffffff, 0, 32, 0, 0); - ddb_set_pdar(DDB_DCS7, 0xffffffff, 0, 32, 0, 0); - ddb_set_pdar(DDB_DCS8, 0xffffffff, 0, 32, 0, 0); - - /* verify VRC5477 base addr */ - /* don't care about some details */ - db_assert((ddb_in32(DDB_INTCS) & 0xffffff0f) == - ddb_calc_pdar(DDB_INTCS_BASE, DDB_INTCS_SIZE, 8, 0, 0)); - - /* verify BOOT ROM addr */ - /* don't care about some details */ - db_assert((ddb_in32(DDB_BOOTCS) & 0xffffff0f) == - ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0)); - - /* setup PCI windows - window1 for MEM/config, window0 for IO */ - ddb_set_pdar(DDB_PCIW0, DDB_PCI_IO_BASE, DDB_PCI_IO_SIZE, 32, 0, 1); - ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32); - - ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1); - ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32); - - /* ----------- setup PDARs ------------ */ - /* this is problematic - it will reset Aladin which cause we loose - * serial port, and we don't know how to set up Aladin chip again. - */ - // ddb_pci_reset_bus(); - - ddb_out32(DDB_BAR0, 0x00000008); - - ddb_out32(DDB_BARC, 0xffffffff); - ddb_out32(DDB_BARB, 0xffffffff); - ddb_out32(DDB_BAR1, 0xffffffff); - ddb_out32(DDB_BAR2, 0xffffffff); - ddb_out32(DDB_BAR3, 0xffffffff); - ddb_out32(DDB_BAR4, 0xffffffff); - ddb_out32(DDB_BAR5, 0xffffffff); - ddb_out32(DDB_BAR6, 0xffffffff); - ddb_out32(DDB_BAR7, 0xffffffff); - ddb_out32(DDB_BAR8, 0xffffffff); - - /* ----------- switch PCI1 to PCI CONFIG space ------------ */ - ddb_set_pdar(DDB_PCIW1, DDB_PCI_CONFIG_BASE, DDB_PCI_CONFIG_SIZE, 32, 0, 1); - ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_CFG, 0x0, DDB_PCI_ACCESS_32); - - /* ----- M1543 PCI setup ------ */ - - /* we know M1543 PCI-ISA controller is at addr:18 */ - /* xxxx1010 makes USB at addr:13 and PMU at addr:14 */ - *(volatile unsigned char *) 0xa8040072 &= 0xf0; - *(volatile unsigned char *) 0xa8040072 |= 0xa; - - /* setup USB interrupt to IRQ 9, (bit 0:3 - 0001) - * no IOCHRDY signal, (bit 7 - 1) - * M1543C & M7101 VID and Subsys Device ID are read-only (bit 6 - 1) - * Make USB Master INTAJ level to edge conversion (bit 4 - 1) - */ - *(unsigned char *) 0xa8040074 = 0xd1; - - /* setup PMU(SCI to IRQ 10 (bit 0:3 - 0011) - * SCI routing to IRQ 13 disabled (bit 7 - 1) - * SCI interrupt level to edge conversion bypassed (bit 4 - 0) - */ - *(unsigned char *) 0xa8040076 = 0x83; - - /* setup IDE controller - * enable IDE controller (bit 6 - 1) - * IDE IDSEL to be addr:24 (bit 4:5 - 11) - * no IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0) - * no IDE ATA Primary Bus Signal Pad Control (bit 2 - 0) - * primary IRQ is 14, secondary is 15 (bit 1:0 - 01 - */ - // *(unsigned char*)0xa8040058 = 0x71; - // *(unsigned char*)0xa8040058 = 0x79; - // *(unsigned char*)0xa8040058 = 0x74; // use SIRQ, primary tri-state - *(unsigned char *) 0xa8040058 = 0x75; // primary tri-state - -#if 0 - /* this is not necessary if M5229 does not use SIRQ */ - *(unsigned char *) 0xa8040044 = 0x0d; // primary to IRQ 14 - *(unsigned char *) 0xa8040075 = 0x0d; // secondary to IRQ 14 -#endif - - /* enable IDE in the M5229 config register 0x50 (bit 0 - 1) */ - /* M5229 IDSEL is addr:24; see above setting */ - *(unsigned char *) 0xa9000050 |= 0x1; - - /* enable bus master (bit 2) and IO decoding (bit 0) */ - *(unsigned char *) 0xa9000004 |= 0x5; - - /* enable native, copied from arch/ppc/k2boot/head.S */ - /* TODO - need volatile, need to be portable */ - *(unsigned char *) 0xa9000009 = 0xff; - - /* ----- end of M1543 PCI setup ------ */ - - /* ----- reset on-board ether chip ------ */ - *((volatile u32 *) 0xa8020004) |= 1; /* decode I/O */ - *((volatile u32 *) 0xa8020010) = 0; /* set BAR address */ - - /* send reset command */ - *((volatile u32 *) 0xa6000000) = 1; /* do a soft reset */ - - /* disable ether chip */ - *((volatile u32 *) 0xa8020004) = 0; /* disable any decoding */ - - /* put it into sleep */ - *((volatile u32 *) 0xa8020040) = 0x80000000; - - /* ----- end of reset on-board ether chip ------ */ - - /* ----------- switch PCI1 back to PCI MEM space ------------ */ - ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1); - ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32); -} diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c deleted file mode 100644 index a3c5e7b..0000000 --- a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * The irq controller for vrc5476. - * - * Copyright (C) 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ -#include -#include -#include -#include -#include - -#include - -#include - -static int irq_base; - -static void vrc5476_irq_enable(uint irq) -{ - nile4_enable_irq(irq - irq_base); -} - -static void vrc5476_irq_disable(uint irq) -{ - nile4_disable_irq(irq - irq_base); -} - -static unsigned int vrc5476_irq_startup(uint irq) -{ - nile4_enable_irq(irq - irq_base); - return 0; -} - -#define vrc5476_irq_shutdown vrc5476_irq_disable - -static void vrc5476_irq_ack(uint irq) -{ - nile4_clear_irq(irq - irq_base); - nile4_disable_irq(irq - irq_base); -} - -static void vrc5476_irq_end(uint irq) -{ - if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - vrc5476_irq_enable(irq); -} - -static hw_irq_controller vrc5476_irq_controller = { - .typename = "vrc5476", - .startup = vrc5476_irq_startup, - .shutdown = vrc5476_irq_shutdown, - .enable = vrc5476_irq_enable, - .disable = vrc5476_irq_disable, - .ack = vrc5476_irq_ack, - .end = vrc5476_irq_end -}; - -void __init -vrc5476_irq_init(u32 base) -{ - u32 i; - - irq_base = base; - for (i= base; i< base + NUM_VRC5476_IRQ; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].handler = &vrc5476_irq_controller; - } -} - - -void -vrc5476_irq_dispatch(struct pt_regs *regs) -{ - u32 mask; - int nile4_irq; - - mask = nile4_get_irq_stat(0); - - /* quick check for possible time interrupt */ - if (mask & (1 << VRC5476_IRQ_GPT)) { - do_IRQ(VRC5476_IRQ_BASE + VRC5476_IRQ_GPT, regs); - return; - } - - /* check for i8259 interrupts */ - if (mask & (1 << VRC5476_I8259_CASCADE)) { - int i8259_irq = nile4_i8259_iack(); - do_IRQ(I8259_IRQ_BASE + i8259_irq, regs); - return; - } - - /* regular nile4 interrupts (we should not really have any */ - for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1) { - if (mask & 1) { - do_IRQ(VRC5476_IRQ_BASE + nile4_irq, regs); - return; - } - } - spurious_interrupt(regs); -} diff --git a/arch/mips/ddb5xxx/ddb5477/setup.c b/arch/mips/ddb5xxx/ddb5477/setup.c index 2f56603..93167ec 100644 --- a/arch/mips/ddb5xxx/ddb5477/setup.c +++ b/arch/mips/ddb5xxx/ddb5477/setup.c @@ -171,7 +171,7 @@ static void ddb5477_board_init(void); extern struct pci_controller ddb5477_ext_controller; extern struct pci_controller ddb5477_io_controller; -void __init plat_setup(void) +void __init plat_mem_setup(void) { /* initialize board - we don't trust the loader */ ddb5477_board_init(); diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c index ad5d436..9c707b9 100644 --- a/arch/mips/dec/setup.c +++ b/arch/mips/dec/setup.c @@ -147,7 +147,7 @@ static void __init dec_be_init(void) extern void dec_time_init(void); extern void dec_timer_setup(struct irqaction *); -void __init plat_setup(void) +void __init plat_mem_setup(void) { board_be_init = dec_be_init; board_time_init = dec_time_init; diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index 74cb055..76e4d09 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c @@ -181,7 +181,7 @@ void __init dec_time_init(void) } /* Set up the rate of periodic DS1287 interrupts. */ - CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A); + CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A); } EXPORT_SYMBOL(do_settimeofday); diff --git a/arch/mips/defconfig b/arch/mips/defconfig index 607e298..879ba1a 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -41,8 +41,6 @@ # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MIPS_XXS1500 is not set # CONFIG_PNX8550_V2PCI is not set # CONFIG_PNX8550_JBS is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_MACH_VR41XX is not set # CONFIG_PMC_YOSEMITE is not set @@ -136,6 +134,15 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set diff --git a/arch/mips/emma2rh/common/Makefile b/arch/mips/emma2rh/common/Makefile new file mode 100644 index 0000000..859121b --- /dev/null +++ b/arch/mips/emma2rh/common/Makefile @@ -0,0 +1,13 @@ +# +# arch/mips/emma2rh/common/Makefile +# Makefile for the common code of NEC EMMA2RH based board. +# +# Copyright (C) NEC Electronics Corporation 2005-2006 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# + +obj-$(CONFIG_MARKEINS) += irq.o irq_emma2rh.o prom.o diff --git a/arch/mips/emma2rh/common/irq.c b/arch/mips/emma2rh/common/irq.c new file mode 100644 index 0000000..b075281 --- /dev/null +++ b/arch/mips/emma2rh/common/irq.c @@ -0,0 +1,108 @@ +/* + * arch/mips/emma2rh/common/irq.c + * This file is common irq dispatcher. + * + * Copyright (C) NEC Electronics Corporation 2005-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* + * the first level int-handler will jump here if it is a emma2rh irq + */ +asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs) +{ + u32 intStatus; + u32 bitmask; + u32 i; + + intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_0) + & emma2rh_in32(EMMA2RH_BHIF_INT_EN_0); + +#ifdef EMMA2RH_SW_CASCADE + if (intStatus & + (1 << ((EMMA2RH_SW_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) { + u32 swIntStatus; + swIntStatus = emma2rh_in32(EMMA2RH_BHIF_SW_INT) + & emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); + for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) { + if (swIntStatus & bitmask) { + do_IRQ(EMMA2RH_SW_IRQ_BASE + i, regs); + return; + } + } + } +#endif + + for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) { + if (intStatus & bitmask) { + do_IRQ(EMMA2RH_IRQ_BASE + i, regs); + return; + } + } + + intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_1) + & emma2rh_in32(EMMA2RH_BHIF_INT_EN_1); + +#ifdef EMMA2RH_GPIO_CASCADE + if (intStatus & + (1 << ((EMMA2RH_GPIO_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) { + u32 gpioIntStatus; + gpioIntStatus = emma2rh_in32(EMMA2RH_GPIO_INT_ST) + & emma2rh_in32(EMMA2RH_GPIO_INT_MASK); + for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) { + if (gpioIntStatus & bitmask) { + do_IRQ(EMMA2RH_GPIO_IRQ_BASE + i, regs); + return; + } + } + } +#endif + + for (i = 32, bitmask = 1; i < 64; i++, bitmask <<= 1) { + if (intStatus & bitmask) { + do_IRQ(EMMA2RH_IRQ_BASE + i, regs); + return; + } + } + + intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_2) + & emma2rh_in32(EMMA2RH_BHIF_INT_EN_2); + + for (i = 64, bitmask = 1; i < 96; i++, bitmask <<= 1) { + if (intStatus & bitmask) { + do_IRQ(EMMA2RH_IRQ_BASE + i, regs); + return; + } + } +} diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c new file mode 100644 index 0000000..b886aa9 --- /dev/null +++ b/arch/mips/emma2rh/common/irq_emma2rh.c @@ -0,0 +1,134 @@ +/* + * arch/mips/emma2rh/common/irq_emma2rh.c + * This file defines the irq handler for EMMA2RH. + * + * Copyright (C) NEC Electronics Corporation 2005-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/irq_5477.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * EMMA2RH defines 64 IRQs. + * + * This file exports one function: + * emma2rh_irq_init(u32 irq_base); + */ + +#include +#include +#include + +#include + +#include + +/* number of total irqs supported by EMMA2RH */ +#define NUM_EMMA2RH_IRQ 96 + +static int emma2rh_irq_base = -1; + +void ll_emma2rh_irq_enable(int); +void ll_emma2rh_irq_disable(int); + +static void emma2rh_irq_enable(unsigned int irq) +{ + ll_emma2rh_irq_enable(irq - emma2rh_irq_base); +} + +static void emma2rh_irq_disable(unsigned int irq) +{ + ll_emma2rh_irq_disable(irq - emma2rh_irq_base); +} + +static unsigned int emma2rh_irq_startup(unsigned int irq) +{ + emma2rh_irq_enable(irq); + return 0; +} + +#define emma2rh_irq_shutdown emma2rh_irq_disable + +static void emma2rh_irq_ack(unsigned int irq) +{ + /* disable interrupt - some handler will re-enable the irq + * and if the interrupt is leveled, we will have infinite loop + */ + ll_emma2rh_irq_disable(irq - emma2rh_irq_base); +} + +static void emma2rh_irq_end(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + ll_emma2rh_irq_enable(irq - emma2rh_irq_base); +} + +hw_irq_controller emma2rh_irq_controller = { + .typename = "emma2rh_irq", + .startup = emma2rh_irq_startup, + .shutdown = emma2rh_irq_shutdown, + .enable = emma2rh_irq_enable, + .disable = emma2rh_irq_disable, + .ack = emma2rh_irq_ack, + .end = emma2rh_irq_end, + .set_affinity = NULL /* no affinity stuff for UP */ +}; + +void emma2rh_irq_init(u32 irq_base) +{ + u32 i; + + for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &emma2rh_irq_controller; + } + + emma2rh_irq_base = irq_base; +} + +void ll_emma2rh_irq_enable(int emma2rh_irq) +{ + u32 reg_value; + u32 reg_bitmask; + u32 reg_index; + + reg_index = EMMA2RH_BHIF_INT_EN_0 + + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) + * (emma2rh_irq / 32); + reg_value = emma2rh_in32(reg_index); + reg_bitmask = 0x1 << (emma2rh_irq % 32); + db_assert((reg_value & reg_bitmask) == 0); + emma2rh_out32(reg_index, reg_value | reg_bitmask); +} + +void ll_emma2rh_irq_disable(int emma2rh_irq) +{ + u32 reg_value; + u32 reg_bitmask; + u32 reg_index; + + reg_index = EMMA2RH_BHIF_INT_EN_0 + + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) + * (emma2rh_irq / 32); + reg_value = emma2rh_in32(reg_index); + reg_bitmask = 0x1 << (emma2rh_irq % 32); + db_assert((reg_value & reg_bitmask) != 0); + emma2rh_out32(reg_index, reg_value & ~reg_bitmask); +} diff --git a/arch/mips/emma2rh/common/prom.c b/arch/mips/emma2rh/common/prom.c new file mode 100644 index 0000000..8bba0b0 --- /dev/null +++ b/arch/mips/emma2rh/common/prom.c @@ -0,0 +1,77 @@ +/* + * arch/mips/emma2rh/common/prom.c + * This file is prom file. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/common/prom.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +const char *get_system_type(void) +{ + switch (mips_machtype) { + case MACH_NEC_MARKEINS: + return "NEC EMMA2RH Mark-eins"; + default: + return "Unknown NEC board"; + } +} + +/* [jsun@junsun.net] PMON passes arguments in C main() style */ +void __init prom_init(void) +{ + int argc = fw_arg0; + char **arg = (char **)fw_arg1; + int i; + + /* if user passes kernel args, ignore the default one */ + if (argc > 1) + arcs_cmdline[0] = '\0'; + + /* arg[0] is "g", the rest is boot parameters */ + for (i = 1; i < argc; i++) { + if (strlen(arcs_cmdline) + strlen(arg[i] + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, arg[i]); + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_NEC_EMMA2RH; + +#if defined(CONFIG_MARKEINS) + mips_machtype = MACH_NEC_MARKEINS; + add_memory_region(0, EMMA2RH_RAM_SIZE, BOOT_MEM_RAM); +#endif + +} + +void __init prom_free_prom_memory(void) +{ +} diff --git a/arch/mips/emma2rh/markeins/Makefile b/arch/mips/emma2rh/markeins/Makefile new file mode 100644 index 0000000..14fc268 --- /dev/null +++ b/arch/mips/emma2rh/markeins/Makefile @@ -0,0 +1,13 @@ +# +# arch/mips/emma2rh/markeins/Makefile +# Makefile for the common code of NEC EMMA2RH based board. +# +# Copyright (C) NEC Electronics Corporation 2005-2006 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# + +obj-$(CONFIG_MARKEINS) += irq.o irq_markeins.o setup.o led.o platform.o diff --git a/arch/mips/emma2rh/markeins/irq.c b/arch/mips/emma2rh/markeins/irq.c new file mode 100644 index 0000000..76dc3fa --- /dev/null +++ b/arch/mips/emma2rh/markeins/irq.c @@ -0,0 +1,134 @@ +/* + * arch/mips/emma2rh/markeins/irq.c + * This file defines the irq handler for EMMA2RH. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * IRQ mapping + * + * 0-7: 8 CPU interrupts + * 0 - software interrupt 0 + * 1 - software interrupt 1 + * 2 - most Vrc5477 interrupts are routed to this pin + * 3 - (optional) some other interrupts routed to this pin for debugg + * 4 - not used + * 5 - not used + * 6 - not used + * 7 - cpu timer (used by default) + * + */ + +extern void emma2rh_sw_irq_init(u32 base); +extern void emma2rh_gpio_irq_init(u32 base); +extern void emma2rh_irq_init(u32 base); +extern asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs); + +static struct irqaction irq_cascade = { + .handler = no_action, + .flags = 0, + .mask = CPU_MASK_NONE, + .name = "cascade", + .dev_id = NULL, + .next = NULL, +}; + +void __init arch_init_irq(void) +{ + u32 reg; + + db_run(printk("markeins_irq_setup invoked.\n")); + + /* by default, interrupts are disabled. */ + emma2rh_out32(EMMA2RH_BHIF_INT_EN_0, 0); + emma2rh_out32(EMMA2RH_BHIF_INT_EN_1, 0); + emma2rh_out32(EMMA2RH_BHIF_INT_EN_2, 0); + emma2rh_out32(EMMA2RH_BHIF_INT1_EN_0, 0); + emma2rh_out32(EMMA2RH_BHIF_INT1_EN_1, 0); + emma2rh_out32(EMMA2RH_BHIF_INT1_EN_2, 0); + emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, 0); + + clear_c0_status(0xff00); + set_c0_status(0x0400); + +#define GPIO_PCI (0xf<<15) + /* setup GPIO interrupt for PCI interface */ + /* direction input */ + reg = emma2rh_in32(EMMA2RH_GPIO_DIR); + emma2rh_out32(EMMA2RH_GPIO_DIR, reg & ~GPIO_PCI); + /* disable interrupt */ + reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); + emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg & ~GPIO_PCI); + /* level triggerd */ + reg = emma2rh_in32(EMMA2RH_GPIO_INT_MODE); + emma2rh_out32(EMMA2RH_GPIO_INT_MODE, reg | GPIO_PCI); + reg = emma2rh_in32(EMMA2RH_GPIO_INT_CND_A); + emma2rh_out32(EMMA2RH_GPIO_INT_CND_A, reg & (~GPIO_PCI)); + /* interrupt clear */ + emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~GPIO_PCI); + + /* init all controllers */ + emma2rh_irq_init(EMMA2RH_IRQ_BASE); + emma2rh_sw_irq_init(EMMA2RH_SW_IRQ_BASE); + emma2rh_gpio_irq_init(EMMA2RH_GPIO_IRQ_BASE); + mips_cpu_irq_init(CPU_IRQ_BASE); + + /* setup cascade interrupts */ + setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade); + setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade); + setup_irq(CPU_IRQ_BASE + CPU_EMMA2RH_CASCADE, &irq_cascade); +} + +asmlinkage void plat_irq_dispatch(struct pt_regs *regs) +{ + unsigned int pending = read_c0_status() & read_c0_cause(); + + if (pending & STATUSF_IP7) + do_IRQ(CPU_IRQ_BASE + 7, regs); + else if (pending & STATUSF_IP2) + emma2rh_irq_dispatch(regs); + else if (pending & STATUSF_IP1) + do_IRQ(CPU_IRQ_BASE + 1, regs); + else if (pending & STATUSF_IP0) + do_IRQ(CPU_IRQ_BASE + 0, regs); + else + spurious_interrupt(regs); +} + + diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c new file mode 100644 index 0000000..1783fda --- /dev/null +++ b/arch/mips/emma2rh/markeins/irq_markeins.c @@ -0,0 +1,197 @@ +/* + * arch/mips/emma2rh/markeins/irq_markeins.c + * This file defines the irq handler for Mark-eins. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/irq_5477.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include + +#include +#include + +static int emma2rh_sw_irq_base = -1; +static int emma2rh_gpio_irq_base = -1; + +void ll_emma2rh_sw_irq_enable(int reg); +void ll_emma2rh_sw_irq_disable(int reg); +void ll_emma2rh_gpio_irq_enable(int reg); +void ll_emma2rh_gpio_irq_disable(int reg); + +static void emma2rh_sw_irq_enable(unsigned int irq) +{ + ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base); +} + +static void emma2rh_sw_irq_disable(unsigned int irq) +{ + ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base); +} + +static unsigned int emma2rh_sw_irq_startup(unsigned int irq) +{ + emma2rh_sw_irq_enable(irq); + return 0; +} + +#define emma2rh_sw_irq_shutdown emma2rh_sw_irq_disable + +static void emma2rh_sw_irq_ack(unsigned int irq) +{ + ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base); +} + +static void emma2rh_sw_irq_end(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base); +} + +hw_irq_controller emma2rh_sw_irq_controller = { + .typename = "emma2rh_sw_irq", + .startup = emma2rh_sw_irq_startup, + .shutdown = emma2rh_sw_irq_shutdown, + .enable = emma2rh_sw_irq_enable, + .disable = emma2rh_sw_irq_disable, + .ack = emma2rh_sw_irq_ack, + .end = emma2rh_sw_irq_end, + .set_affinity = NULL, +}; + +void emma2rh_sw_irq_init(u32 irq_base) +{ + u32 i; + + for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_SW; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 2; + irq_desc[i].handler = &emma2rh_sw_irq_controller; + } + + emma2rh_sw_irq_base = irq_base; +} + +void ll_emma2rh_sw_irq_enable(int irq) +{ + u32 reg; + + db_assert(irq >= 0); + db_assert(irq < NUM_EMMA2RH_IRQ_SW); + + reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); + reg |= 1 << irq; + emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg); +} + +void ll_emma2rh_sw_irq_disable(int irq) +{ + u32 reg; + + db_assert(irq >= 0); + db_assert(irq < 32); + + reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); + reg &= ~(1 << irq); + emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg); +} + +static void emma2rh_gpio_irq_enable(unsigned int irq) +{ + ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base); +} + +static void emma2rh_gpio_irq_disable(unsigned int irq) +{ + ll_emma2rh_gpio_irq_disable(irq - emma2rh_gpio_irq_base); +} + +static unsigned int emma2rh_gpio_irq_startup(unsigned int irq) +{ + emma2rh_gpio_irq_enable(irq); + return 0; +} + +#define emma2rh_gpio_irq_shutdown emma2rh_gpio_irq_disable + +static void emma2rh_gpio_irq_ack(unsigned int irq) +{ + irq -= emma2rh_gpio_irq_base; + emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq)); + ll_emma2rh_gpio_irq_disable(irq); +} + +static void emma2rh_gpio_irq_end(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base); +} + +hw_irq_controller emma2rh_gpio_irq_controller = { + .typename = "emma2rh_gpio_irq", + .startup = emma2rh_gpio_irq_startup, + .shutdown = emma2rh_gpio_irq_shutdown, + .enable = emma2rh_gpio_irq_enable, + .disable = emma2rh_gpio_irq_disable, + .ack = emma2rh_gpio_irq_ack, + .end = emma2rh_gpio_irq_end, + .set_affinity = NULL, +}; + +void emma2rh_gpio_irq_init(u32 irq_base) +{ + u32 i; + + for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_GPIO; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 2; + irq_desc[i].handler = &emma2rh_gpio_irq_controller; + } + + emma2rh_gpio_irq_base = irq_base; +} + +void ll_emma2rh_gpio_irq_enable(int irq) +{ + u32 reg; + + db_assert(irq >= 0); + db_assert(irq < NUM_EMMA2RH_IRQ_GPIO); + + reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); + reg |= 1 << irq; + emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg); +} + +void ll_emma2rh_gpio_irq_disable(int irq) +{ + u32 reg; + + db_assert(irq >= 0); + db_assert(irq < NUM_EMMA2RH_IRQ_GPIO); + + reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); + reg &= ~(1 << irq); + emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg); +} diff --git a/arch/mips/emma2rh/markeins/led.c b/arch/mips/emma2rh/markeins/led.c new file mode 100644 index 0000000..b65254c --- /dev/null +++ b/arch/mips/emma2rh/markeins/led.c @@ -0,0 +1,60 @@ +/* + * arch/mips/emma2rh/markeins/led.c + * This file defines the led display for Mark-eins. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include + +const unsigned long clear = 0x20202020; + +#define LED_BASE 0xb1400038 + +void markeins_led_clear(void) +{ + emma2rh_out32(LED_BASE, clear); + emma2rh_out32(LED_BASE + 4, clear); +} + +void markeins_led(const char *str) +{ + int i; + int len = strlen(str); + + markeins_led_clear(); + if (len > 8) + len = 8; + + if (emma2rh_in32(0xb0000800) & (0x1 << 18)) + for (i = 0; i < len; i++) + emma2rh_out8(LED_BASE + i, str[i]); + else + for (i = 0; i < len; i++) + emma2rh_out8(LED_BASE + (i & 4) + (3 - (i & 3)), + str[i]); +} + +void markeins_led_hex(u32 val) +{ + char str[10]; + + sprintf(str, "%08x", val); + markeins_led(str); +} diff --git a/arch/mips/emma2rh/markeins/platform.c b/arch/mips/emma2rh/markeins/platform.c new file mode 100644 index 0000000..6c1eeae --- /dev/null +++ b/arch/mips/emma2rh/markeins/platform.c @@ -0,0 +1,170 @@ +/* + * arch/mips/emma2rh/markeins/platofrm.c + * This file sets up platform devices for EMMA2RH Mark-eins. + * + * Copyright(C) MontaVista Software Inc, 2006 + * + * Author: dmitry pervushin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#define I2C_EMMA2RH "emma2rh-iic" /* must be in sync with IIC driver */ + +static struct resource i2c_emma_resources_0[] = { + { NULL, EMMA2RH_IRQ_PIIC0, EMMA2RH_IRQ_PIIC0, IORESOURCE_IRQ }, + { NULL, KSEG1ADDR(EMMA2RH_PIIC0_BASE), KSEG1ADDR(EMMA2RH_PIIC0_BASE + 0x1000), 0 }, +}; + +struct resource i2c_emma_resources_1[] = { + { NULL, EMMA2RH_IRQ_PIIC1, EMMA2RH_IRQ_PIIC1, IORESOURCE_IRQ }, + { NULL, KSEG1ADDR(EMMA2RH_PIIC1_BASE), KSEG1ADDR(EMMA2RH_PIIC1_BASE + 0x1000), 0 }, +}; + +struct resource i2c_emma_resources_2[] = { + { NULL, EMMA2RH_IRQ_PIIC2, EMMA2RH_IRQ_PIIC2, IORESOURCE_IRQ }, + { NULL, KSEG1ADDR(EMMA2RH_PIIC2_BASE), KSEG1ADDR(EMMA2RH_PIIC2_BASE + 0x1000), 0 }, +}; + +struct platform_device i2c_emma_devices[] = { + [0] = { + .name = I2C_EMMA2RH, + .id = 0, + .resource = i2c_emma_resources_0, + .num_resources = ARRAY_SIZE(i2c_emma_resources_0), + }, + [1] = { + .name = I2C_EMMA2RH, + .id = 1, + .resource = i2c_emma_resources_1, + .num_resources = ARRAY_SIZE(i2c_emma_resources_1), + }, + [2] = { + .name = I2C_EMMA2RH, + .id = 2, + .resource = i2c_emma_resources_2, + .num_resources = ARRAY_SIZE(i2c_emma_resources_2), + }, +}; + +#define EMMA2RH_SERIAL_CLOCK 18544000 +#define EMMA2RH_SERIAL_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST + +static struct plat_serial8250_port platform_serial_ports[] = { + [0] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR0, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, + [1] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR1, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, + [2] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR2, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, + [3] = { + .flags = 0, + }, +}; + +static struct platform_device serial_emma = { + .name = "serial8250", + .dev = { + .platform_data = &platform_serial_ports, + }, +}; + +static struct platform_device *devices[] = { + &i2c_emma_devices[0], + &i2c_emma_devices[1], + &i2c_emma_devices[2], + &serial_emma, +}; + +static struct mtd_partition markeins_parts[] = { + [0] = { + .name = "RootFS", + .offset = 0x00000000, + .size = 0x00c00000, + }, + [1] = { + .name = "boot code area", + .offset = MTDPART_OFS_APPEND, + .size = 0x00100000, + }, + [2] = { + .name = "kernel image", + .offset = MTDPART_OFS_APPEND, + .size = 0x00300000, + }, + [3] = { + .name = "RootFS2", + .offset = MTDPART_OFS_APPEND, + .size = 0x00c00000, + }, + [4] = { + .name = "boot code area2", + .offset = MTDPART_OFS_APPEND, + .size = 0x00100000, + }, + [5] = { + .name = "kernel image2", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static int __init platform_devices_setup(void) +{ + physmap_set_partitions(markeins_parts, ARRAY_SIZE(markeins_parts)); + return platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +arch_initcall(platform_devices_setup); + diff --git a/arch/mips/emma2rh/markeins/setup.c b/arch/mips/emma2rh/markeins/setup.c new file mode 100644 index 0000000..7d98fdb --- /dev/null +++ b/arch/mips/emma2rh/markeins/setup.c @@ -0,0 +1,182 @@ +/* + * arch/mips/emma2rh/markeins/setup.c + * This file is setup for EMMA2RH Mark-eins. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/setup.c. + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for HZ */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */ + +extern void markeins_led(const char *); + +static int bus_frequency = 0; + +static void markeins_machine_restart(char *command) +{ + static void (*back_to_prom) (void) = (void (*)(void))0xbfc00000; + + printk("cannot EMMA2RH Mark-eins restart.\n"); + markeins_led("restart."); + back_to_prom(); +} + +static void markeins_machine_halt(void) +{ + printk("EMMA2RH Mark-eins halted.\n"); + markeins_led("halted."); + while (1) ; +} + +static void markeins_machine_power_off(void) +{ + printk("EMMA2RH Mark-eins halted. Please turn off the power.\n"); + markeins_led("poweroff."); + while (1) ; +} + +static unsigned long clock[4] = { 166500000, 187312500, 199800000, 210600000 }; + +static unsigned int __init detect_bus_frequency(unsigned long rtc_base) +{ + u32 reg; + + /* detect from boot strap */ + reg = emma2rh_in32(EMMA2RH_BHIF_STRAP_0); + reg = (reg >> 4) & 0x3; + return clock[reg]; +} + +static void __init emma2rh_time_init(void) +{ + u32 reg; + if (bus_frequency == 0) + bus_frequency = detect_bus_frequency(0); + + reg = emma2rh_in32(EMMA2RH_BHIF_STRAP_0); + if ((reg & 0x3) == 0) + reg = (reg >> 6) & 0x3; + else { + reg = emma2rh_in32(EMMA2RH_BHIF_MAIN_CTRL); + reg = (reg >> 4) & 0x3; + } + mips_hpt_frequency = (bus_frequency * (4 + reg)) / 4 / 2; +} + +static void __init emma2rh_timer_setup(struct irqaction *irq) +{ + /* we are using the cpu counter for timer interrupts */ + setup_irq(CPU_IRQ_BASE + 7, irq); +} + +static void markeins_board_init(void); +extern void markeins_irq_setup(void); + +static void inline __init markeins_sio_setup(void) +{ +#ifdef CONFIG_KGDB_8250 + struct uart_port emma_port; + + memset(&emma_port, 0, sizeof(emma_port)); + + emma_port.flags = + UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + emma_port.iotype = UPIO_MEM; + emma_port.regshift = 4; /* I/O addresses are every 8 bytes */ + emma_port.uartclk = 18544000; /* Clock rate of the chip */ + + emma_port.line = 0; + emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3); + emma_port.membase = (u8*)emma_port.mapbase; + early_serial_setup(&emma_port); + + emma_port.line = 1; + emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3); + emma_port.membase = (u8*)emma_port.mapbase; + early_serial_setup(&emma_port); + + emma_port.irq = EMMA2RH_IRQ_PFUR1; + kgdb8250_add_port(1, &emma_port); +#endif +} + +void __init plat_mem_setup(void) +{ + /* initialize board - we don't trust the loader */ + markeins_board_init(); + + set_io_port_base(KSEG1ADDR(EMMA2RH_PCI_IO_BASE)); + + board_time_init = emma2rh_time_init; + board_timer_setup = emma2rh_timer_setup; + + _machine_restart = markeins_machine_restart; + _machine_halt = markeins_machine_halt; + pm_power_off = markeins_machine_power_off; + + /* setup resource limits */ + ioport_resource.start = EMMA2RH_PCI_IO_BASE; + ioport_resource.end = EMMA2RH_PCI_IO_BASE + EMMA2RH_PCI_IO_SIZE - 1; + iomem_resource.start = EMMA2RH_IO_BASE; + iomem_resource.end = EMMA2RH_ROM_BASE - 1; + + /* Reboot on panic */ + panic_timeout = 180; + + markeins_sio_setup(); +} + +static void __init markeins_board_init(void) +{ + u32 val; + + val = emma2rh_in32(EMMA2RH_PBRD_INT_EN); /* open serial interrupts. */ + emma2rh_out32(EMMA2RH_PBRD_INT_EN, val | 0xaa); + val = emma2rh_in32(EMMA2RH_PBRD_CLKSEL); /* set serial clocks. */ + emma2rh_out32(EMMA2RH_PBRD_CLKSEL, val | 0x5); /* 18MHz */ + emma2rh_out32(EMMA2RH_PCI_CONTROL, 0); + + markeins_led("MVL E2RH"); +} diff --git a/arch/mips/galileo-boards/ev96100/setup.c b/arch/mips/galileo-boards/ev96100/setup.c index 78dbb18..a04aea6 100644 --- a/arch/mips/galileo-boards/ev96100/setup.c +++ b/arch/mips/galileo-boards/ev96100/setup.c @@ -55,7 +55,7 @@ extern void mips_reboot_setup(void); unsigned char mac_0_1[12]; -void __init plat_setup(void) +void __init plat_mem_setup(void) { unsigned int config = read_c0_config(); unsigned int status = read_c0_status(); diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c index 6d859d1..4236da3 100644 --- a/arch/mips/gt64120/ev64120/setup.c +++ b/arch/mips/gt64120/ev64120/setup.c @@ -71,7 +71,7 @@ unsigned long __init prom_free_prom_memo */ extern void gt64120_time_init(void); -void __init plat_setup(void) +void __init plat_mem_setup(void) { _machine_restart = galileo_machine_restart; _machine_halt = galileo_machine_halt; diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c index 20b65d3..1193a22 100644 --- a/arch/mips/gt64120/momenco_ocelot/setup.c +++ b/arch/mips/gt64120/momenco_ocelot/setup.c @@ -152,7 +152,7 @@ void PMON_v2_setup() gt64120_base = 0xe0000000; } -void __init plat_setup(void) +void __init plat_mem_setup(void) { void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache); unsigned int tmpword; diff --git a/arch/mips/gt64120/wrppmc/Makefile b/arch/mips/gt64120/wrppmc/Makefile new file mode 100644 index 0000000..72606b9 --- /dev/null +++ b/arch/mips/gt64120/wrppmc/Makefile @@ -0,0 +1,14 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright 2006 Wind River System, Inc. +# Author: Rongkai.Zhan +# +# Makefile for the Wind River MIPS 4KC PPMC Eval Board +# + +obj-y += int-handler.o irq.o reset.o setup.o time.o pci.o + +EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/gt64120/wrppmc/int-handler.S b/arch/mips/gt64120/wrppmc/int-handler.S new file mode 100644 index 0000000..edee7b3 --- /dev/null +++ b/arch/mips/gt64120/wrppmc/int-handler.S @@ -0,0 +1,59 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle + * Copyright (C) Wind River System Inc. Rongkai.Zhan + */ +#include +#include +#include +#include +#include +#include + + .align 5 + .set noat +NESTED(handle_IRQ, PT_SIZE, sp) + SAVE_ALL + CLI # Important: mark KERNEL mode ! + .set at + + mfc0 t0, CP0_CAUSE # get pending interrupts + mfc0 t1, CP0_STATUS # get enabled interrupts + and t0, t0, t1 # get allowed interrupts + andi t0, t0, 0xFF00 + beqz t0, 1f + move a1, sp # Prepare 'struct pt_regs *regs' pointer + + andi t1, t0, CAUSEF_IP7 # CPU Compare/Count internal timer + bnez t1, handle_cputimer_irq + andi t1, t0, CAUSEF_IP6 # UART 16550 port + bnez t1, handle_uart_irq + andi t1, t0, CAUSEF_IP3 # PCI INT_A + bnez t1, handle_pci_intA_irq + + /* wrong alarm or masked ... */ +1: j spurious_interrupt + nop +END(handle_IRQ) + + .align 5 +handle_cputimer_irq: + li a0, WRPPMC_MIPS_TIMER_IRQ + jal do_IRQ + j ret_from_irq + + .align 5 +handle_uart_irq: + li a0, WRPPMC_UART16550_IRQ + jal do_IRQ + j ret_from_irq + + .align 5 +handle_pci_intA_irq: + li a0, WRPPMC_PCI_INTA_IRQ + jal do_IRQ + j ret_from_irq + diff --git a/arch/mips/gt64120/wrppmc/irq.c b/arch/mips/gt64120/wrppmc/irq.c new file mode 100644 index 0000000..8605687 --- /dev/null +++ b/arch/mips/gt64120/wrppmc/irq.c @@ -0,0 +1,63 @@ +/* + * irq.c: GT64120 Interrupt Controller + * + * Copyright (C) 2006, Wind River System Inc. + * Author: Rongkai.Zhan, + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern asmlinkage void handle_IRQ(void); + +/** + * Initialize GT64120 Interrupt Controller + */ +void gt64120_init_pic(void) +{ + /* clear CPU Interrupt Cause Registers */ + GT_WRITE(GT_INTRCAUSE_OFS, (0x1F << 21)); + GT_WRITE(GT_HINTRCAUSE_OFS, 0x00); + + /* Disable all interrupts from GT64120 bridge chip */ + GT_WRITE(GT_INTRMASK_OFS, 0x00); + GT_WRITE(GT_HINTRMASK_OFS, 0x00); + GT_WRITE(GT_PCI0_ICMASK_OFS, 0x00); + GT_WRITE(GT_PCI0_HICMASK_OFS, 0x00); +} + +void __init arch_init_irq(void) +{ + /* enable all CPU interrupt bits. */ + set_c0_status(ST0_IM); /* IE bit is still 0 */ + + /* Install MIPS Interrupt Trap Vector */ + set_except_vector(0, handle_IRQ); + + /* IRQ 0 - 7 are for MIPS common irq_cpu controller */ + mips_cpu_irq_init(0); + + gt64120_init_pic(); +} diff --git a/arch/mips/gt64120/wrppmc/pci.c b/arch/mips/gt64120/wrppmc/pci.c new file mode 100644 index 0000000..2fbe934 --- /dev/null +++ b/arch/mips/gt64120/wrppmc/pci.c @@ -0,0 +1,53 @@ +/* + * pci.c: GT64120 PCI support. + * + * Copyright (C) 2006, Wind River System Inc. Rongkai.Zhan + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +extern struct pci_ops gt64120_pci_ops; + +static struct resource pci0_io_resource = { + .name = "pci_0 io", + .start = GT_PCI_IO_BASE, + .end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1, + .flags = IORESOURCE_IO, +}; + +static struct resource pci0_mem_resource = { + .name = "pci_0 memory", + .start = GT_PCI_MEM_BASE, + .end = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct pci_controller hose_0 = { + .pci_ops = >64120_pci_ops, + .io_resource = &pci0_io_resource, + .mem_resource = &pci0_mem_resource, +}; + +static int __init gt64120_pci_init(void) +{ + u32 tmp; + + tmp = GT_READ(GT_PCI0_CMD_OFS); /* Huh??? -- Ralf */ + tmp = GT_READ(GT_PCI0_BARE_OFS); + + /* reset the whole PCI I/O space range */ + ioport_resource.start = GT_PCI_IO_BASE; + ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; + + register_pci_controller(&hose_0); + return 0; +} + +arch_initcall(gt64120_pci_init); diff --git a/arch/mips/gt64120/wrppmc/reset.c b/arch/mips/gt64120/wrppmc/reset.c new file mode 100644 index 0000000..b97039c --- /dev/null +++ b/arch/mips/gt64120/wrppmc/reset.c @@ -0,0 +1,50 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997 Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include + +void wrppmc_machine_restart(char *command) +{ + /* + * Ouch, we're still alive ... This time we take the silver bullet ... + * ... and find that we leave the hardware in a state in which the + * kernel in the flush locks up somewhen during of after the PCI + * detection stuff. + */ + local_irq_disable(); + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void wrppmc_machine_halt(void) +{ + local_irq_disable(); + + printk(KERN_NOTICE "You can safely turn off the power\n"); + while (1) { + __asm__( + ".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0" + ); + } +} + +void wrppmc_machine_power_off(void) +{ + wrppmc_machine_halt(); +} diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c new file mode 100644 index 0000000..20c591e --- /dev/null +++ b/arch/mips/gt64120/wrppmc/setup.c @@ -0,0 +1,173 @@ +/* + * setup.c: Setup pointers to hardware dependent routines. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2006, Wind River System Inc. Rongkai.zhan + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +unsigned long gt64120_base = KSEG1ADDR(0x14000000); + +#ifdef WRPPMC_EARLY_DEBUG + +static volatile unsigned char * wrppmc_led = \ + (volatile unsigned char *)KSEG1ADDR(WRPPMC_LED_BASE); + +/* + * PPMC LED control register: + * -) bit[0] controls DS1 LED (1 - OFF, 0 - ON) + * -) bit[1] controls DS2 LED (1 - OFF, 0 - ON) + * -) bit[2] controls DS4 LED (1 - OFF, 0 - ON) + */ +void wrppmc_led_on(int mask) +{ + unsigned char value = *wrppmc_led; + + value &= (0xF8 | mask); + *wrppmc_led = value; +} + +/* If mask = 0, turn off all LEDs */ +void wrppmc_led_off(int mask) +{ + unsigned char value = *wrppmc_led; + + value |= (0x7 & mask); + *wrppmc_led = value; +} + +/* + * We assume that bootloader has initialized UART16550 correctly + */ +void __init wrppmc_early_putc(char ch) +{ + static volatile unsigned char *wrppmc_uart = \ + (volatile unsigned char *)KSEG1ADDR(WRPPMC_UART16550_BASE); + unsigned char value; + + /* Wait until Transmit-Holding-Register is empty */ + while (1) { + value = *(wrppmc_uart + 5); + if (value & 0x20) + break; + } + + *wrppmc_uart = ch; +} + +void __init wrppmc_early_printk(const char *fmt, ...) +{ + static char pbuf[256] = {'\0', }; + char *ch = pbuf; + va_list args; + unsigned int i; + + memset(pbuf, 0, 256); + va_start(args, fmt); + i = vsprintf(pbuf, fmt, args); + va_end(args); + + /* Print the string */ + while (*ch != '\0') { + wrppmc_early_putc(*ch); + /* if print '\n', also print '\r' */ + if (*ch++ == '\n') + wrppmc_early_putc('\r'); + } +} +#endif /* WRPPMC_EARLY_DEBUG */ + +unsigned long __init prom_free_prom_memory(void) +{ + return 0; +} + +#ifdef CONFIG_SERIAL_8250 +static void wrppmc_setup_serial(void) +{ + struct uart_port up; + + memset(&up, 0x00, sizeof(struct uart_port)); + + /* + * A note about mapbase/membase + * -) mapbase is the physical address of the IO port. + * -) membase is an 'ioremapped' cookie. + */ + up.line = 0; + up.type = PORT_16550; + up.iotype = UPIO_MEM; + up.mapbase = WRPPMC_UART16550_BASE; + up.membase = ioremap(up.mapbase, 8); + up.irq = WRPPMC_UART16550_IRQ; + up.uartclk = WRPPMC_UART16550_CLOCK; + up.flags = UPF_SKIP_TEST/* | UPF_BOOT_AUTOCONF */; + up.regshift = 0; + + early_serial_setup(&up); +} +#endif + +void __init plat_setup(void) +{ + extern void wrppmc_time_init(void); + extern void wrppmc_timer_setup(struct irqaction *); + extern void wrppmc_machine_restart(char *command); + extern void wrppmc_machine_halt(void); + extern void wrppmc_machine_power_off(void); + + _machine_restart = wrppmc_machine_restart; + _machine_halt = wrppmc_machine_halt; + pm_power_off = wrppmc_machine_power_off; + + /* Use MIPS Count/Compare Timer */ + board_time_init = wrppmc_time_init; + board_timer_setup = wrppmc_timer_setup; + + /* This makes the operations of 'in/out[bwl]' to the + * physical address ( < KSEG0) can work via KSEG1 + */ + set_io_port_base(KSEG1); + +#ifdef CONFIG_SERIAL_8250 + wrppmc_setup_serial(); +#endif +} + +const char *get_system_type(void) +{ + return "Wind River PPMC (GT64120)"; +} + +/* + * Initializes basic routines and structures pointers, memory size (as + * given by the bios and saves the command line. + */ +void __init prom_init(void) +{ + mips_machgroup = MACH_GROUP_GALILEO; + mips_machtype = MACH_EV64120A; + + add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM); + add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA); + + wrppmc_early_printk("prom_init: GT64120 SDRAM Bank 0: 0x%x - 0x%08lx\n", + WRPPMC_SDRAM_SCS0_BASE, (WRPPMC_SDRAM_SCS0_BASE + WRPPMC_SDRAM_SCS0_SIZE)); +} diff --git a/arch/mips/gt64120/wrppmc/time.c b/arch/mips/gt64120/wrppmc/time.c new file mode 100644 index 0000000..175d22a --- /dev/null +++ b/arch/mips/gt64120/wrppmc/time.c @@ -0,0 +1,57 @@ +/* + * time.c: MIPS CPU Count/Compare timer hookup + * + * Author: Mark.Zhan, + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2006, Wind River System Inc. + */ +#include +#include +#include +#include +#include /* for HZ */ +#include +#include +#include + +#include +#include +#include +#include +#include + +#define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */ + +void __init wrppmc_timer_setup(struct irqaction *irq) +{ + /* Install ISR for timer interrupt */ + setup_irq(WRPPMC_MIPS_TIMER_IRQ, irq); + + /* to generate the first timer interrupt */ + write_c0_compare(mips_hpt_frequency/HZ); + write_c0_count(0); +} + +/* + * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect + * + * NOTE: We disable all GT64120 timers, and use MIPS processor internal + * timer as the source of kernel clock tick. + */ +void __init wrppmc_time_init(void) +{ + /* Disable GT64120 timers */ + GT_WRITE(GT_TC_CONTROL_OFS, 0x00); + GT_WRITE(GT_TC0_OFS, 0x00); + GT_WRITE(GT_TC1_OFS, 0x00); + GT_WRITE(GT_TC2_OFS, 0x00); + GT_WRITE(GT_TC3_OFS, 0x00); + + /* Use MIPS compare/count internal timer */ + mips_hpt_frequency = WRPPMC_CPU_CLK_FREQ; +} diff --git a/arch/mips/ite-boards/generic/it8172_setup.c b/arch/mips/ite-boards/generic/it8172_setup.c index fc73c8d..da6ae09 100644 --- a/arch/mips/ite-boards/generic/it8172_setup.c +++ b/arch/mips/ite-boards/generic/it8172_setup.c @@ -72,11 +72,29 @@ struct { struct resource flash; struct resource boot; } it8172_resources = { - { "RAM", 0, 0, IORESOURCE_MEM }, /* to be initted */ - { "PCI Mem", 0x10000000, 0x13FFFFFF, IORESOURCE_MEM }, - { "PCI I/O", 0x14000000, 0x17FFFFFF }, - { "Flash", 0x08000000, 0x0CFFFFFF }, - { "Boot ROM", 0x1FC00000, 0x1FFFFFFF } + { + .start = 0, /* to be initted */ + .end = 0, + .name = "RAM", + .flags = IORESOURCE_MEM + }, { + .start = 0x10000000, + .end = 0x13FFFFFF, + .name = "PCI Mem", + .flags = IORESOURCE_MEM + }, { + .start = 0x14000000, + .end = 0x17FFFFFF + .name = "PCI I/O", + }, { + .start = 0x08000000, + .end = 0x0CFFFFFF + .name = "Flash", + }, { + .start = 0x1FC00000, + .end = 0x1FFFFFFF + .name = "Boot ROM", + } }; #else struct { @@ -89,14 +107,44 @@ struct { struct resource flash; struct resource boot; } it8172_resources = { - { "RAM", 0, 0, IORESOURCE_MEM }, /* to be initted */ - { "PCI Mem0", 0x0C000000, 0x0FFFFFFF, IORESOURCE_MEM }, - { "PCI Mem1", 0x10000000, 0x13FFFFFF, IORESOURCE_MEM }, - { "PCI I/O", 0x14000000, 0x17FFFFFF }, - { "PCI Mem2", 0x1A000000, 0x1BFFFFFF, IORESOURCE_MEM }, - { "PCI Mem3", 0x1C000000, 0x1FBFFFFF, IORESOURCE_MEM }, - { "Flash", 0x08000000, 0x0CFFFFFF }, - { "Boot ROM", 0x1FC00000, 0x1FFFFFFF } + { + .start = 0, /* to be initted */ + .end = 0, + .name = "RAM", + .flags = IORESOURCE_MEM + }, { + .start = 0x0C000000, + .end = 0x0FFFFFFF, + .name = "PCI Mem0", + .flags = IORESOURCE_MEM + }, { + .start = 0x10000000, + .end = 0x13FFFFFF, + .name = "PCI Mem1", + .flags = IORESOURCE_MEM + }, { + .start = 0x14000000, + .end = 0x17FFFFFF + .name = "PCI I/O", + }, { + .start = 0x1A000000, + .end = 0x1BFFFFFF, + .name = "PCI Mem2", + .flags = IORESOURCE_MEM + }, { + .start = 0x1C000000, + .end = 0x1FBFFFFF, + .name = "PCI Mem3", + .flags = IORESOURCE_MEM + }, { + .start = 0x08000000, + .end = 0x0CFFFFFF + .name = "Flash", + }, { + .start = 0x1FC00000, + .end = 0x1FFFFFFF + .name = "Boot ROM", + } }; #endif @@ -106,7 +154,7 @@ void __init it8172_init_ram_resource(uns it8172_resources.ram.end = memsize; } -void __init plat_setup(void) +void __init plat_mem_setup(void) { unsigned short dsr; char *argptr; diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c index 4036dc4..c8d0df7 100644 --- a/arch/mips/jazz/setup.c +++ b/arch/mips/jazz/setup.c @@ -52,7 +52,7 @@ static struct resource jazz_io_resources { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, }; -void __init plat_setup(void) +void __init plat_mem_setup(void) { int i; diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c index 9359cc4..308e6cd 100644 --- a/arch/mips/jmr3927/rbhma3100/setup.c +++ b/arch/mips/jmr3927/rbhma3100/setup.c @@ -82,17 +82,54 @@ struct { struct resource sio0; struct resource sio1; } jmr3927_resources = { - { "RAM0", 0, 0x01FFFFFF, IORESOURCE_MEM }, - { "RAM1", 0x02000000, 0x03FFFFFF, IORESOURCE_MEM }, - { "PCIMEM", 0x08000000, 0x07FFFFFF, IORESOURCE_MEM }, - { "IOB", 0x10000000, 0x13FFFFFF }, - { "IOC", 0x14000000, 0x14FFFFFF }, - { "PCIIO", 0x15000000, 0x15FFFFFF }, - { "JMY1394", 0x1D000000, 0x1D3FFFFF }, - { "ROM1", 0x1E000000, 0x1E3FFFFF }, - { "ROM0", 0x1FC00000, 0x1FFFFFFF }, - { "SIO0", 0xFFFEF300, 0xFFFEF3FF }, - { "SIO1", 0xFFFEF400, 0xFFFEF4FF }, + { + .start = 0, + .end = 0x01FFFFFF, + .name = "RAM0", + .flags = IORESOURCE_MEM + }, { + .start = 0x02000000, + .end = 0x03FFFFFF, + .name = "RAM1", + .flags = IORESOURCE_MEM + }, { + .start = 0x08000000, + .end = 0x07FFFFFF, + .name = "PCIMEM", + .flags = IORESOURCE_MEM + }, { + .start = 0x10000000, + .end = 0x13FFFFFF, + .name = "IOB" + }, { + .start = 0x14000000, + .end = 0x14FFFFFF, + .name = "IOC" + }, { + .start = 0x15000000, + .end = 0x15FFFFFF, + .name = "PCIIO" + }, { + .start = 0x1D000000, + .end = 0x1D3FFFFF, + .name = "JMY1394" + }, { + .start = 0x1E000000, + .end = 0x1E3FFFFF, + .name = "ROM1" + }, { + .start = 0x1FC00000, + .end = 0x1FFFFFFF, + .name = "ROM0" + }, { + .start = 0xFFFEF300, + .end = 0xFFFEF3FF, + .name = "SIO0" + }, { + .start = 0xFFFEF400, + .end = 0xFFFEF4FF, + .name = "SIO1" + }, }; /* don't enable - see errata */ @@ -201,7 +238,7 @@ static void jmr3927_board_init(void); extern struct resource pci_io_resource; extern struct resource pci_mem_resource; -void __init plat_setup(void) +void __init plat_mem_setup(void) { char *argptr; diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 34e8a25..881c467 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -13,6 +13,8 @@ binfmt_irix-objs := irixelf.o irixinv.o obj-$(CONFIG_MODULES) += mips_ksyms.o module.o +obj-$(CONFIG_APM) += apm.o + obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o diff --git a/arch/mips/kernel/apm.c b/arch/mips/kernel/apm.c new file mode 100644 index 0000000..15f46b4 --- /dev/null +++ b/arch/mips/kernel/apm.c @@ -0,0 +1,605 @@ +/* + * bios-less APM driver for MIPS Linux + * Jamey Hicks + * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com) + * + * APM 1.2 Reference: + * Intel Corporation, Microsoft Corporation. Advanced Power Management + * (APM) BIOS Interface Specification, Revision 1.2, February 1996. + * + * [This document is available from Microsoft at: + * http://www.microsoft.com/hwdev/busbios/amp_12.htm] + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* apm_power_info */ +#include + +/* + * The apm_bios device is one of the misc char devices. + * This is its minor number. + */ +#define APM_MINOR_DEV 134 + +/* + * See Documentation/Config.help for the configuration options. + * + * Various options can be changed at boot time as follows: + * (We allow underscores for compatibility with the modules code) + * apm=on/off enable/disable APM + */ + +/* + * Maximum number of events stored + */ +#define APM_MAX_EVENTS 16 + +struct apm_queue { + unsigned int event_head; + unsigned int event_tail; + apm_event_t events[APM_MAX_EVENTS]; +}; + +/* + * The per-file APM data + */ +struct apm_user { + struct list_head list; + + unsigned int suser: 1; + unsigned int writer: 1; + unsigned int reader: 1; + + int suspend_result; + unsigned int suspend_state; +#define SUSPEND_NONE 0 /* no suspend pending */ +#define SUSPEND_PENDING 1 /* suspend pending read */ +#define SUSPEND_READ 2 /* suspend read, pending ack */ +#define SUSPEND_ACKED 3 /* suspend acked */ +#define SUSPEND_DONE 4 /* suspend completed */ + + struct apm_queue queue; +}; + +/* + * Local variables + */ +static int suspends_pending; +static int apm_disabled; +static int mips_apm_active; + +static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); +static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); + +/* + * This is a list of everyone who has opened /dev/apm_bios + */ +static DECLARE_RWSEM(user_list_lock); +static LIST_HEAD(apm_user_list); + +/* + * kapmd info. kapmd provides us a process context to handle + * "APM" events within - specifically necessary if we're going + * to be suspending the system. + */ +static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait); +static DECLARE_COMPLETION(kapmd_exit); +static DEFINE_SPINLOCK(kapmd_queue_lock); +static struct apm_queue kapmd_queue; + + +static const char driver_version[] = "1.13"; /* no spaces */ + + + +/* + * Compatibility cruft until the IPAQ people move over to the new + * interface. + */ +static void __apm_get_power_status(struct apm_power_info *info) +{ +} + +/* + * This allows machines to provide their own "apm get power status" function. + */ +void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status; +EXPORT_SYMBOL(apm_get_power_status); + + +/* + * APM event queue management. + */ +static inline int queue_empty(struct apm_queue *q) +{ + return q->event_head == q->event_tail; +} + +static inline apm_event_t queue_get_event(struct apm_queue *q) +{ + q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; + return q->events[q->event_tail]; +} + +static void queue_add_event(struct apm_queue *q, apm_event_t event) +{ + q->event_head = (q->event_head + 1) % APM_MAX_EVENTS; + if (q->event_head == q->event_tail) { + static int notified; + + if (notified++ == 0) + printk(KERN_ERR "apm: an event queue overflowed\n"); + q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; + } + q->events[q->event_head] = event; +} + +static void queue_event_one_user(struct apm_user *as, apm_event_t event) +{ + if (as->suser && as->writer) { + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + /* + * If this user already has a suspend pending, + * don't queue another one. + */ + if (as->suspend_state != SUSPEND_NONE) + return; + + as->suspend_state = SUSPEND_PENDING; + suspends_pending++; + break; + } + } + queue_add_event(&as->queue, event); +} + +static void queue_event(apm_event_t event, struct apm_user *sender) +{ + struct apm_user *as; + + down_read(&user_list_lock); + list_for_each_entry(as, &apm_user_list, list) { + if (as != sender && as->reader) + queue_event_one_user(as, event); + } + up_read(&user_list_lock); + wake_up_interruptible(&apm_waitqueue); +} + +static void apm_suspend(void) +{ + struct apm_user *as; + int err = pm_suspend(PM_SUSPEND_MEM); + + /* + * Anyone on the APM queues will think we're still suspended. + * Send a message so everyone knows we're now awake again. + */ + queue_event(APM_NORMAL_RESUME, NULL); + + /* + * Finally, wake up anyone who is sleeping on the suspend. + */ + down_read(&user_list_lock); + list_for_each_entry(as, &apm_user_list, list) { + as->suspend_result = err; + as->suspend_state = SUSPEND_DONE; + } + up_read(&user_list_lock); + + wake_up(&apm_suspend_waitqueue); +} + +static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) +{ + struct apm_user *as = fp->private_data; + apm_event_t event; + int i = count, ret = 0; + + if (count < sizeof(apm_event_t)) + return -EINVAL; + + if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK) + return -EAGAIN; + + wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue)); + + while ((i >= sizeof(event)) && !queue_empty(&as->queue)) { + event = queue_get_event(&as->queue); + + ret = -EFAULT; + if (copy_to_user(buf, &event, sizeof(event))) + break; + + if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND) + as->suspend_state = SUSPEND_READ; + + buf += sizeof(event); + i -= sizeof(event); + } + + if (i < count) + ret = count - i; + + return ret; +} + +static unsigned int apm_poll(struct file *fp, poll_table * wait) +{ + struct apm_user *as = fp->private_data; + + poll_wait(fp, &apm_waitqueue, wait); + return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM; +} + +/* + * apm_ioctl - handle APM ioctl + * + * APM_IOC_SUSPEND + * This IOCTL is overloaded, and performs two functions. It is used to: + * - initiate a suspend + * - acknowledge a suspend read from /dev/apm_bios. + * Only when everyone who has opened /dev/apm_bios with write permission + * has acknowledge does the actual suspend happen. + */ +static int +apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) +{ + struct apm_user *as = filp->private_data; + unsigned long flags; + int err = -EINVAL; + + if (!as->suser || !as->writer) + return -EPERM; + + switch (cmd) { + case APM_IOC_SUSPEND: + as->suspend_result = -EINTR; + + if (as->suspend_state == SUSPEND_READ) { + /* + * If we read a suspend command from /dev/apm_bios, + * then the corresponding APM_IOC_SUSPEND ioctl is + * interpreted as an acknowledge. + */ + as->suspend_state = SUSPEND_ACKED; + suspends_pending--; + } else { + /* + * Otherwise it is a request to suspend the system. + * Queue an event for all readers, and expect an + * acknowledge from all writers who haven't already + * acknowledged. + */ + queue_event(APM_USER_SUSPEND, as); + } + + /* + * If there are no further acknowledges required, suspend + * the system. + */ + if (suspends_pending == 0) + apm_suspend(); + + /* + * Wait for the suspend/resume to complete. If there are + * pending acknowledges, we wait here for them. + * + * Note that we need to ensure that the PM subsystem does + * not kick us out of the wait when it suspends the threads. + */ + flags = current->flags; + current->flags |= PF_NOFREEZE; + + /* + * Note: do not allow a thread which is acking the suspend + * to escape until the resume is complete. + */ + if (as->suspend_state == SUSPEND_ACKED) + wait_event(apm_suspend_waitqueue, + as->suspend_state == SUSPEND_DONE); + else + wait_event_interruptible(apm_suspend_waitqueue, + as->suspend_state == SUSPEND_DONE); + + current->flags = flags; + err = as->suspend_result; + as->suspend_state = SUSPEND_NONE; + break; + } + + return err; +} + +static int apm_release(struct inode * inode, struct file * filp) +{ + struct apm_user *as = filp->private_data; + filp->private_data = NULL; + + down_write(&user_list_lock); + list_del(&as->list); + up_write(&user_list_lock); + + /* + * We are now unhooked from the chain. As far as new + * events are concerned, we no longer exist. However, we + * need to balance suspends_pending, which means the + * possibility of sleeping. + */ + if (as->suspend_state != SUSPEND_NONE) { + suspends_pending -= 1; + if (suspends_pending == 0) + apm_suspend(); + } + + kfree(as); + return 0; +} + +static int apm_open(struct inode * inode, struct file * filp) +{ + struct apm_user *as; + + as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL); + if (as) { + /* + * XXX - this is a tiny bit broken, when we consider BSD + * process accounting. If the device is opened by root, we + * instantly flag that we used superuser privs. Who knows, + * we might close the device immediately without doing a + * privileged operation -- cevans + */ + as->suser = capable(CAP_SYS_ADMIN); + as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE; + as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ; + + down_write(&user_list_lock); + list_add(&as->list, &apm_user_list); + up_write(&user_list_lock); + + filp->private_data = as; + } + + return as ? 0 : -ENOMEM; +} + +static struct file_operations apm_bios_fops = { + .owner = THIS_MODULE, + .read = apm_read, + .poll = apm_poll, + .ioctl = apm_ioctl, + .open = apm_open, + .release = apm_release, +}; + +static struct miscdevice apm_device = { + .minor = APM_MINOR_DEV, + .name = "apm_bios", + .fops = &apm_bios_fops +}; + + +#ifdef CONFIG_PROC_FS +/* + * Arguments, with symbols from linux/apm_bios.h. + * + * 0) Linux driver version (this will change if format changes) + * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2. + * 2) APM flags from APM Installation Check (0x00): + * bit 0: APM_16_BIT_SUPPORT + * bit 1: APM_32_BIT_SUPPORT + * bit 2: APM_IDLE_SLOWS_CLOCK + * bit 3: APM_BIOS_DISABLED + * bit 4: APM_BIOS_DISENGAGED + * 3) AC line status + * 0x00: Off-line + * 0x01: On-line + * 0x02: On backup power (BIOS >= 1.1 only) + * 0xff: Unknown + * 4) Battery status + * 0x00: High + * 0x01: Low + * 0x02: Critical + * 0x03: Charging + * 0x04: Selected battery not present (BIOS >= 1.2 only) + * 0xff: Unknown + * 5) Battery flag + * bit 0: High + * bit 1: Low + * bit 2: Critical + * bit 3: Charging + * bit 7: No system battery + * 0xff: Unknown + * 6) Remaining battery life (percentage of charge): + * 0-100: valid + * -1: Unknown + * 7) Remaining battery life (time units): + * Number of remaining minutes or seconds + * -1: Unknown + * 8) min = minutes; sec = seconds + */ +static int apm_get_info(char *buf, char **start, off_t fpos, int length) +{ + struct apm_power_info info; + char *units; + int ret; + + info.ac_line_status = 0xff; + info.battery_status = 0xff; + info.battery_flag = 0xff; + info.battery_life = -1; + info.time = -1; + info.units = -1; + + if (apm_get_power_status) + apm_get_power_status(&info); + + switch (info.units) { + default: units = "?"; break; + case 0: units = "min"; break; + case 1: units = "sec"; break; + } + + ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", + driver_version, APM_32_BIT_SUPPORT, + info.ac_line_status, info.battery_status, + info.battery_flag, info.battery_life, + info.time, units); + + return ret; +} +#endif + +static int kapmd(void *arg) +{ + daemonize("kapmd"); + current->flags |= PF_NOFREEZE; + + do { + apm_event_t event; + + wait_event_interruptible(kapmd_wait, + !queue_empty(&kapmd_queue) || !mips_apm_active); + + if (!mips_apm_active) + break; + + spin_lock_irq(&kapmd_queue_lock); + event = 0; + if (!queue_empty(&kapmd_queue)) + event = queue_get_event(&kapmd_queue); + spin_unlock_irq(&kapmd_queue_lock); + + switch (event) { + case 0: + break; + + case APM_LOW_BATTERY: + case APM_POWER_STATUS_CHANGE: + queue_event(event, NULL); + break; + + case APM_USER_SUSPEND: + case APM_SYS_SUSPEND: + queue_event(event, NULL); + if (suspends_pending == 0) + apm_suspend(); + break; + + case APM_CRITICAL_SUSPEND: + apm_suspend(); + break; + } + } while (1); + + complete_and_exit(&kapmd_exit, 0); +} + +static int __init apm_init(void) +{ + int ret; + + if (apm_disabled) { + printk(KERN_NOTICE "apm: disabled on user request.\n"); + return -ENODEV; + } + + mips_apm_active = 1; + + ret = kernel_thread(kapmd, NULL, CLONE_KERNEL); + if (ret < 0) { + mips_apm_active = 0; + return ret; + } + +#ifdef CONFIG_PROC_FS + create_proc_info_entry("apm", 0, NULL, apm_get_info); +#endif + + ret = misc_register(&apm_device); + if (ret != 0) { + remove_proc_entry("apm", NULL); + + mips_apm_active = 0; + wake_up(&kapmd_wait); + wait_for_completion(&kapmd_exit); + } + + return ret; +} + +static void __exit apm_exit(void) +{ + misc_deregister(&apm_device); + remove_proc_entry("apm", NULL); + + mips_apm_active = 0; + wake_up(&kapmd_wait); + wait_for_completion(&kapmd_exit); +} + +module_init(apm_init); +module_exit(apm_exit); + +MODULE_AUTHOR("Stephen Rothwell"); +MODULE_DESCRIPTION("Advanced Power Management"); +MODULE_LICENSE("GPL"); + +#ifndef MODULE +static int __init apm_setup(char *str) +{ + while ((str != NULL) && (*str != '\0')) { + if (strncmp(str, "off", 3) == 0) + apm_disabled = 1; + if (strncmp(str, "on", 2) == 0) + apm_disabled = 0; + str = strchr(str, ','); + if (str != NULL) + str += strspn(str, ", \t"); + } + return 1; +} + +__setup("apm=", apm_setup); +#endif + +/** + * apm_queue_event - queue an APM event for kapmd + * @event: APM event + * + * Queue an APM event for kapmd to process and ultimately take the + * appropriate action. Only a subset of events are handled: + * %APM_LOW_BATTERY + * %APM_POWER_STATUS_CHANGE + * %APM_USER_SUSPEND + * %APM_SYS_SUSPEND + * %APM_CRITICAL_SUSPEND + */ +void apm_queue_event(apm_event_t event) +{ + unsigned long flags; + + spin_lock_irqsave(&kapmd_queue_lock, flags); + queue_add_event(&kapmd_queue, event); + spin_unlock_irqrestore(&kapmd_queue_lock, flags); + + wake_up_interruptible(&kapmd_wait); +} +EXPORT_SYMBOL(apm_queue_event); diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 0facfaf..f1bb6a2 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -141,72 +141,72 @@ void output_thread_defines(void) void output_thread_fpu_defines(void) { offset("#define THREAD_FPR0 ", - struct task_struct, thread.fpu.hard.fpr[0]); + struct task_struct, thread.fpu.fpr[0]); offset("#define THREAD_FPR1 ", - struct task_struct, thread.fpu.hard.fpr[1]); + struct task_struct, thread.fpu.fpr[1]); offset("#define THREAD_FPR2 ", - struct task_struct, thread.fpu.hard.fpr[2]); + struct task_struct, thread.fpu.fpr[2]); offset("#define THREAD_FPR3 ", - struct task_struct, thread.fpu.hard.fpr[3]); + struct task_struct, thread.fpu.fpr[3]); offset("#define THREAD_FPR4 ", - struct task_struct, thread.fpu.hard.fpr[4]); + struct task_struct, thread.fpu.fpr[4]); offset("#define THREAD_FPR5 ", - struct task_struct, thread.fpu.hard.fpr[5]); + struct task_struct, thread.fpu.fpr[5]); offset("#define THREAD_FPR6 ", - struct task_struct, thread.fpu.hard.fpr[6]); + struct task_struct, thread.fpu.fpr[6]); offset("#define THREAD_FPR7 ", - struct task_struct, thread.fpu.hard.fpr[7]); + struct task_struct, thread.fpu.fpr[7]); offset("#define THREAD_FPR8 ", - struct task_struct, thread.fpu.hard.fpr[8]); + struct task_struct, thread.fpu.fpr[8]); offset("#define THREAD_FPR9 ", - struct task_struct, thread.fpu.hard.fpr[9]); + struct task_struct, thread.fpu.fpr[9]); offset("#define THREAD_FPR10 ", - struct task_struct, thread.fpu.hard.fpr[10]); + struct task_struct, thread.fpu.fpr[10]); offset("#define THREAD_FPR11 ", - struct task_struct, thread.fpu.hard.fpr[11]); + struct task_struct, thread.fpu.fpr[11]); offset("#define THREAD_FPR12 ", - struct task_struct, thread.fpu.hard.fpr[12]); + struct task_struct, thread.fpu.fpr[12]); offset("#define THREAD_FPR13 ", - struct task_struct, thread.fpu.hard.fpr[13]); + struct task_struct, thread.fpu.fpr[13]); offset("#define THREAD_FPR14 ", - struct task_struct, thread.fpu.hard.fpr[14]); + struct task_struct, thread.fpu.fpr[14]); offset("#define THREAD_FPR15 ", - struct task_struct, thread.fpu.hard.fpr[15]); + struct task_struct, thread.fpu.fpr[15]); offset("#define THREAD_FPR16 ", - struct task_struct, thread.fpu.hard.fpr[16]); + struct task_struct, thread.fpu.fpr[16]); offset("#define THREAD_FPR17 ", - struct task_struct, thread.fpu.hard.fpr[17]); + struct task_struct, thread.fpu.fpr[17]); offset("#define THREAD_FPR18 ", - struct task_struct, thread.fpu.hard.fpr[18]); + struct task_struct, thread.fpu.fpr[18]); offset("#define THREAD_FPR19 ", - struct task_struct, thread.fpu.hard.fpr[19]); + struct task_struct, thread.fpu.fpr[19]); offset("#define THREAD_FPR20 ", - struct task_struct, thread.fpu.hard.fpr[20]); + struct task_struct, thread.fpu.fpr[20]); offset("#define THREAD_FPR21 ", - struct task_struct, thread.fpu.hard.fpr[21]); + struct task_struct, thread.fpu.fpr[21]); offset("#define THREAD_FPR22 ", - struct task_struct, thread.fpu.hard.fpr[22]); + struct task_struct, thread.fpu.fpr[22]); offset("#define THREAD_FPR23 ", - struct task_struct, thread.fpu.hard.fpr[23]); + struct task_struct, thread.fpu.fpr[23]); offset("#define THREAD_FPR24 ", - struct task_struct, thread.fpu.hard.fpr[24]); + struct task_struct, thread.fpu.fpr[24]); offset("#define THREAD_FPR25 ", - struct task_struct, thread.fpu.hard.fpr[25]); + struct task_struct, thread.fpu.fpr[25]); offset("#define THREAD_FPR26 ", - struct task_struct, thread.fpu.hard.fpr[26]); + struct task_struct, thread.fpu.fpr[26]); offset("#define THREAD_FPR27 ", - struct task_struct, thread.fpu.hard.fpr[27]); + struct task_struct, thread.fpu.fpr[27]); offset("#define THREAD_FPR28 ", - struct task_struct, thread.fpu.hard.fpr[28]); + struct task_struct, thread.fpu.fpr[28]); offset("#define THREAD_FPR29 ", - struct task_struct, thread.fpu.hard.fpr[29]); + struct task_struct, thread.fpu.fpr[29]); offset("#define THREAD_FPR30 ", - struct task_struct, thread.fpu.hard.fpr[30]); + struct task_struct, thread.fpu.fpr[30]); offset("#define THREAD_FPR31 ", - struct task_struct, thread.fpu.hard.fpr[31]); + struct task_struct, thread.fpu.fpr[31]); offset("#define THREAD_FCR31 ", - struct task_struct, thread.fpu.hard.fcr31); + struct task_struct, thread.fpu.fcr31); linefeed; } diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index b6232d9..76fd3f2 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -178,7 +178,7 @@ int __compute_return_epc(struct pt_regs if (is_fpu_owner()) asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); else - fcr31 = current->thread.fpu.hard.fcr31; + fcr31 = current->thread.fpu.fcr31; preempt_enable(); bit = (insn.i_format.rt >> 2); diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index 2125ba5..0cb8ed5 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c @@ -302,11 +302,11 @@ static struct irqaction irq2 = { }; static struct resource pic1_io_resource = { - "pic1", 0x20, 0x3f, IORESOURCE_BUSY + .name = "pic1", .start = 0x20, .end = 0x3f, .flags = IORESOURCE_BUSY }; static struct resource pic2_io_resource = { - "pic2", 0xa0, 0xbf, IORESOURCE_BUSY + .name = "pic2", .start = 0xa0, .end = 0xbf, .flags = IORESOURCE_BUSY }; /* diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 8150f07..676e868 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -13,6 +13,7 @@ #include #include #include #include +#include #include #include @@ -260,7 +261,7 @@ #endif for(i = 0; i < 32; i++) error |= __get_user(fregs[i], &context->fpregs[i]); - error |= __get_user(current->thread.fpu.hard.fcr31, &context->fpcsr); + error |= __get_user(current->thread.fpu.fcr31, &context->fpcsr); } /* XXX do sigstack crapola here... XXX */ @@ -540,8 +541,6 @@ #define IRIX_P_PID 0 #define IRIX_P_PGID 2 #define IRIX_P_ALL 7 -extern int getrusage(struct task_struct *, int, struct rusage __user *); - #define W_EXITED 1 #define W_TRAPPED 2 #define W_STOPPED 4 diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 9b4733c..1d44025 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -120,11 +120,11 @@ int ptrace_getfpregs (struct task_struct __put_user ((__u64) -1, i + (__u64 __user *) data); } + __put_user (child->thread.fpu.fcr31, data + 64); + if (cpu_has_fpu) { unsigned int flags, tmp; - __put_user (child->thread.fpu.hard.fcr31, data + 64); - preempt_disable(); if (cpu_has_mipsmt) { unsigned int vpflags = dvpe(); @@ -142,7 +142,6 @@ int ptrace_getfpregs (struct task_struct preempt_enable(); __put_user (tmp, data + 65); } else { - __put_user (child->thread.fpu.soft.fcr31, data + 64); __put_user ((__u32) 0, data + 65); } @@ -162,10 +161,7 @@ int ptrace_setfpregs (struct task_struct for (i = 0; i < 32; i++) __get_user (fregs[i], i + (__u64 __user *) data); - if (cpu_has_fpu) - __get_user (child->thread.fpu.hard.fcr31, data + 64); - else - __get_user (child->thread.fpu.soft.fcr31, data + 64); + __get_user (child->thread.fpu.fcr31, data + 64); /* FIR may not be written. */ @@ -241,10 +237,7 @@ #endif tmp = regs->lo; break; case FPC_CSR: - if (cpu_has_fpu) - tmp = child->thread.fpu.hard.fcr31; - else - tmp = child->thread.fpu.soft.fcr31; + tmp = child->thread.fpu.fcr31; break; case FPC_EIR: { /* implementation / version register */ unsigned int flags; @@ -336,9 +329,9 @@ #endif /* CONFIG_MIPS_MT_SMTC */ if (!tsk_used_math(child)) { /* FP not yet used */ - memset(&child->thread.fpu.hard, ~0, - sizeof(child->thread.fpu.hard)); - child->thread.fpu.hard.fcr31 = 0; + memset(&child->thread.fpu, ~0, + sizeof(child->thread.fpu)); + child->thread.fpu.fcr31 = 0; } #ifdef CONFIG_32BIT /* @@ -369,10 +362,7 @@ #endif regs->lo = data; break; case FPC_CSR: - if (cpu_has_fpu) - child->thread.fpu.hard.fcr31 = data; - else - child->thread.fpu.soft.fcr31 = data; + child->thread.fpu.fcr31 = data; break; case DSP_BASE ... DSP_BASE + 5: { dspreg_t *dregs; diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 8704dc0..f40ecd8 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -166,10 +166,7 @@ #endif tmp = regs->lo; break; case FPC_CSR: - if (cpu_has_fpu) - tmp = child->thread.fpu.hard.fcr31; - else - tmp = child->thread.fpu.soft.fcr31; + tmp = child->thread.fpu.fcr31; break; case FPC_EIR: { /* implementation / version register */ unsigned int flags; @@ -288,9 +285,9 @@ #endif /* CONFIG_MIPS_MT_SMTC */ if (!tsk_used_math(child)) { /* FP not yet used */ - memset(&child->thread.fpu.hard, ~0, - sizeof(child->thread.fpu.hard)); - child->thread.fpu.hard.fcr31 = 0; + memset(&child->thread.fpu, ~0, + sizeof(child->thread.fpu)); + child->thread.fpu.fcr31 = 0; } /* * The odd registers are actually the high order bits @@ -318,10 +315,7 @@ #endif /* CONFIG_MIPS_MT_SMTC */ regs->lo = data; break; case FPC_CSR: - if (cpu_has_fpu) - child->thread.fpu.hard.fcr31 = data; - else - child->thread.fpu.soft.fcr31 = data; + child->thread.fpu.fcr31 = data; break; case DSP_BASE ... DSP_BASE + 5: { dspreg_t *dregs; diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 0b1b54a..db94e55 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -75,8 +75,8 @@ #endif and t0, t0, t1 LONG_S t0, ST_OFF(t3) - fpu_save_double a0 t1 t0 t2 # c0_status passed in t1 - # clobbers t0 and t2 + fpu_save_double a0 t0 t1 # c0_status passed in t0 + # clobbers t1 1: /* @@ -129,9 +129,9 @@ #endif /* CONFIG_MIPS_MT_SMTC */ */ LEAF(_save_fp) #ifdef CONFIG_64BIT - mfc0 t1, CP0_STATUS + mfc0 t0, CP0_STATUS #endif - fpu_save_double a0 t1 t0 t2 # clobbers t1 + fpu_save_double a0 t0 t1 # clobbers t1 jr ra END(_save_fp) @@ -139,7 +139,10 @@ #endif * Restore a thread's fp context. */ LEAF(_restore_fp) - fpu_restore_double a0, t1 # clobbers t1 +#ifdef CONFIG_64BIT + mfc0 t0, CP0_STATUS +#endif + fpu_restore_double a0 t0 t1 # clobbers t1 jr ra END(_restore_fp) diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index a0ac0e5..2d2fdf7 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -497,7 +497,7 @@ #endif sys sys_sched_get_priority_min 1 sys sys_sched_rr_get_interval 2 /* 4165 */ sys sys_nanosleep, 2 - sys sys_mremap, 4 + sys sys_mremap, 5 sys sys_accept 3 sys sys_bind 3 sys sys_connect 3 /* 4170 */ diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 397a70e..bfcec8d 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -442,6 +442,48 @@ #ifdef CONFIG_BLK_DEV_INITRD #endif /* CONFIG_BLK_DEV_INITRD */ } +/* + * arch_mem_init - initialize memory managment subsystem + * + * o plat_mem_setup() detects the memory configuration and will record detected + * memory areas using add_memory_region. + * o parse_cmdline_early() parses the command line for mem= options which, + * iff detected, will override the results of the automatic detection. + * + * At this stage the memory configuration of the system is known to the + * kernel but generic memory managment system is still entirely uninitialized. + * + * o bootmem_init() + * o sparse_init() + * o paging_init() + * + * At this stage the bootmem allocator is ready to use. + * + * NOTE: historically plat_mem_setup did the entire platform initialization. + * This was rather impractical because it meant plat_mem_setup had to + * get away without any kind of memory allocator. To keep old code from + * breaking plat_setup was just renamed to plat_setup and a second platform + * initialization hook for anything else was introduced. + */ + +extern void plat_mem_setup(void); + +static void __init arch_mem_init(char **cmdline_p) +{ + /* call board setup routine */ + plat_mem_setup(); + + strlcpy(command_line, arcs_cmdline, sizeof(command_line)); + strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); + + *cmdline_p = command_line; + + parse_cmdline_early(); + bootmem_init(); + sparse_init(); + paging_init(); +} + static inline void resource_init(void) { int i; @@ -495,8 +537,6 @@ static inline void resource_init(void) #undef MAXMEM #undef MAXMEM_PFN -extern void plat_setup(void); - void __init setup_arch(char **cmdline_p) { cpu_probe(); @@ -511,18 +551,8 @@ #elif defined(CONFIG_DUMMY_CONSOLE) #endif #endif - /* call board setup routine */ - plat_setup(); + arch_mem_init(cmdline_p); - strlcpy(command_line, arcs_cmdline, sizeof(command_line)); - strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); - - *cmdline_p = command_line; - - parse_cmdline_early(); - bootmem_init(); - sparse_init(); - paging_init(); resource_init(); #ifdef CONFIG_SMP plat_smp_setup(); diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 5407b78..1137dd6 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -31,6 +31,7 @@ #include #include #include #include +#include #include #include @@ -235,7 +236,6 @@ asmlinkage int irix_prctl(unsigned optio #undef DEBUG_PROCGRPS extern unsigned long irix_mapelf(int fd, struct elf_phdr __user *user_phdrp, int cnt); -extern int getrusage(struct task_struct *p, int who, struct rusage __user *ru); extern char *prom_getenv(char *name); extern long prom_setenv(char *name, char *value); @@ -694,7 +694,7 @@ asmlinkage int irix_statfs(const char __ if (error) goto out; - error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(nd.dentry, &kbuf); if (error) goto dput_and_out; @@ -732,7 +732,7 @@ asmlinkage int irix_fstatfs(unsigned int goto out; } - error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(file->f_dentry, &kbuf); if (error) goto out_f; @@ -1360,7 +1360,7 @@ asmlinkage int irix_statvfs(char __user error = user_path_walk(fname, &nd); if (error) goto out; - error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(nd.dentry, &kbuf); if (error) goto dput_and_out; @@ -1406,7 +1406,7 @@ asmlinkage int irix_fstatvfs(int fd, str error = -EBADF; goto out; } - error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(file->f_dentry, &kbuf); if (error) goto out_f; @@ -1611,7 +1611,7 @@ asmlinkage int irix_statvfs64(char __use error = user_path_walk(fname, &nd); if (error) goto out; - error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(nd.dentry, &kbuf); if (error) goto dput_and_out; @@ -1658,7 +1658,7 @@ asmlinkage int irix_fstatvfs64(int fd, s error = -EBADF; goto out; } - error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf); + error = vfs_statfs(file->f_dentry, &kbuf); if (error) goto out_f; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index a7564b0..ad16ece 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -65,7 +65,7 @@ extern asmlinkage void handle_mcheck(voi extern asmlinkage void handle_reserved(void); extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, - struct mips_fpu_soft_struct *ctx); + struct mips_fpu_struct *ctx); void (*board_be_init)(void); int (*board_be_handler)(struct pt_regs *regs, int is_fixup); @@ -600,8 +600,7 @@ #endif preempt_enable(); /* Run the emulator */ - sig = fpu_emulator_cop1Handler (regs, - ¤t->thread.fpu.soft); + sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu); preempt_disable(); @@ -610,7 +609,7 @@ #endif * We can't allow the emulated instruction to leave any of * the cause bit set in $fcr31. */ - current->thread.fpu.soft.fcr31 &= ~FPU_CSR_ALL_X; + current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; /* Restore the hardware register state */ restore_fp(current); @@ -755,7 +754,7 @@ asmlinkage void do_cpu(struct pt_regs *r if (!cpu_has_fpu) { int sig = fpu_emulator_cop1Handler(regs, - ¤t->thread.fpu.soft); + ¤t->thread.fpu); if (sig) force_sig(sig, current); #ifdef CONFIG_MIPS_MT_FPAFF diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c index bb70a82..3f64277 100644 --- a/arch/mips/lasat/setup.c +++ b/arch/mips/lasat/setup.c @@ -155,7 +155,7 @@ #endif } #endif -void __init plat_setup(void) +void __init plat_mem_setup(void) { int i; lasat_misc = &lasat_misc_info[mips_machtype]; diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index cf12caf..b225543 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -7,4 +7,7 @@ lib-y += csum_partial_copy.o memcpy.o pr obj-y += iomap.o +# libgcc-style stuff needed in the kernel +lib-y += ashldi3.o ashrdi3.o lshrdi3.o + EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c new file mode 100644 index 0000000..beb80f3 --- /dev/null +++ b/arch/mips/lib/ashldi3.c @@ -0,0 +1,29 @@ +#include + +#include "libgcc.h" + +long long __ashldi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.low = 0; + w.s.high = (unsigned int) uu.s.low << -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.low >> bm; + + w.s.low = (unsigned int) uu.s.low << b; + w.s.high = ((unsigned int) uu.s.high << b) | carries; + } + + return w.ll; +} + +EXPORT_SYMBOL(__ashldi3); diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c new file mode 100644 index 0000000..c884a91 --- /dev/null +++ b/arch/mips/lib/ashrdi3.c @@ -0,0 +1,31 @@ +#include + +#include "libgcc.h" + +long long __ashrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = + uu.s.high >> 31; + w.s.low = uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +} + +EXPORT_SYMBOL(__ashrdi3); diff --git a/arch/mips/lib/libgcc.h b/arch/mips/lib/libgcc.h new file mode 100644 index 0000000..3f19d1c --- /dev/null +++ b/arch/mips/lib/libgcc.h @@ -0,0 +1,26 @@ +#ifndef __ASM_LIBGCC_H +#define __ASM_LIBGCC_H + +#include + +typedef int word_type __attribute__ ((mode (__word__))); + +#ifdef __BIG_ENDIAN +struct DWstruct { + int high, low; +}; +#elif defined(__LITTLE_ENDIAN) +struct DWstruct { + int low, high; +}; +#else +#error I feel sick. +#endif + +typedef union +{ + struct DWstruct s; + long long ll; +} DWunion; + +#endif /* __ASM_LIBGCC_H */ diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c new file mode 100644 index 0000000..dcf8d68 --- /dev/null +++ b/arch/mips/lib/lshrdi3.c @@ -0,0 +1,29 @@ +#include + +#include "libgcc.h" + +long long __lshrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.high = 0; + w.s.low = (unsigned int) uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = (unsigned int) uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +} + +EXPORT_SYMBOL(__lshrdi3); diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index aa5818a..3f0d5d2 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -60,15 +60,15 @@ #define __mips 4 /* Function which emulates a floating point instruction. */ -static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *, +static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *, mips_instruction); #if __mips >= 4 && __mips != 32 static int fpux_emu(struct pt_regs *, - struct mips_fpu_soft_struct *, mips_instruction); + struct mips_fpu_struct *, mips_instruction); #endif -/* Further private data for which no space exists in mips_fpu_soft_struct */ +/* Further private data for which no space exists in mips_fpu_struct */ struct mips_fpu_emulator_stats fpuemustats; @@ -203,7 +203,7 @@ #define DPTOREG(dp,x) DITOREG((dp).bits, * Two instructions if the instruction is in a branch delay slot. */ -static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx) +static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) { mips_instruction ir; void * emulpc, *contpc; @@ -595,7 +595,7 @@ DEF3OP(msub, dp, ieee754dp_mul, ieee754d DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg); DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); -static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, +static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, mips_instruction ir) { unsigned rcsr = 0; /* resulting csr */ @@ -759,7 +759,7 @@ #endif /* * Emulate a single COP1 arithmetic instruction. */ -static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, +static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, mips_instruction ir) { int rfmt; /* resulting format */ @@ -1233,8 +1233,7 @@ #endif return 0; } -int fpu_emulator_cop1Handler(struct pt_regs *xcp, - struct mips_fpu_soft_struct *ctx) +int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx) { unsigned long oldepc, prevepc; mips_instruction insn; diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 171f177..dd91733 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -329,7 +329,7 @@ #ifdef __LITTLE_ENDIAN unsigned pad0:7; #endif }; -#define ieee754_csr (*(struct _ieee754_csr *)(¤t->thread.fpu.soft.fcr31)) +#define ieee754_csr (*(struct _ieee754_csr *)(¤t->thread.fpu.fcr31)) static inline unsigned ieee754_getrm(void) { diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c index d187ab7..56ca0c6 100644 --- a/arch/mips/math-emu/kernel_linkage.c +++ b/arch/mips/math-emu/kernel_linkage.c @@ -39,9 +39,9 @@ void fpu_emulator_init_fpu(void) printk("Algorithmics/MIPS FPU Emulator v1.5\n"); } - current->thread.fpu.soft.fcr31 = 0; + current->thread.fpu.fcr31 = 0; for (i = 0; i < 32; i++) { - current->thread.fpu.soft.fpr[i] = SIGNALLING_NAN; + current->thread.fpu.fpr[i] = SIGNALLING_NAN; } } @@ -59,10 +59,9 @@ int fpu_emulator_save_context(struct sig for (i = 0; i < 32; i++) { err |= - __put_user(current->thread.fpu.soft.fpr[i], - &sc->sc_fpregs[i]); + __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); } - err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr); + err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); return err; } @@ -74,10 +73,9 @@ int fpu_emulator_restore_context(struct for (i = 0; i < 32; i++) { err |= - __get_user(current->thread.fpu.soft.fpr[i], - &sc->sc_fpregs[i]); + __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); } - err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr); + err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); return err; } @@ -94,10 +92,9 @@ int fpu_emulator_save_context32(struct s for (i = 0; i < 32; i+=2) { err |= - __put_user(current->thread.fpu.soft.fpr[i], - &sc->sc_fpregs[i]); + __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); } - err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr); + err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); return err; } @@ -109,10 +106,9 @@ int fpu_emulator_restore_context32(struc for (i = 0; i < 32; i+=2) { err |= - __get_user(current->thread.fpu.soft.fpr[i], - &sc->sc_fpregs[i]); + __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]); } - err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr); + err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr); return err; } diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c index c20d401..8cc9eff 100644 --- a/arch/mips/mips-boards/atlas/atlas_setup.c +++ b/arch/mips/mips-boards/atlas/atlas_setup.c @@ -50,7 +50,7 @@ const char *get_system_type(void) return "MIPS Atlas"; } -void __init plat_setup(void) +void __init plat_mem_setup(void) { mips_pcibios_init(); diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c index bc4d093..fd49256 100644 --- a/arch/mips/mips-boards/generic/memory.c +++ b/arch/mips/mips-boards/generic/memory.c @@ -76,6 +76,15 @@ #endif memsize = simple_strtol(memsize_str, NULL, 0); } } + +#ifdef CONFIG_CPU_BIG_ENDIAN + /* + * SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last + * word of physical memory + */ + memsize -= PAGE_SIZE; +#endif + memset(mdesc, 0, sizeof(mdesc)); mdesc[0].type = yamon_dontuse; diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c index b8488aa..0766e43 100644 --- a/arch/mips/mips-boards/malta/malta_setup.c +++ b/arch/mips/mips-boards/malta/malta_setup.c @@ -53,11 +53,11 @@ extern void kgdb_config(void); #endif struct resource standard_io_resources[] = { - { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, - { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, - { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY }, - { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, - { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, + { .name = "dma1", .start = 0x00, .end = 0x1f, .flags = IORESOURCE_BUSY }, + { .name = "timer", .start = 0x40, .end = 0x5f, .flags = IORESOURCE_BUSY }, + { .name = "keyboard", .start = 0x60, .end = 0x6f, .flags = IORESOURCE_BUSY }, + { .name = "dma page reg", .start = 0x80, .end = 0x8f, .flags = IORESOURCE_BUSY }, + { .name = "dma2", .start = 0xc0, .end = 0xdf, .flags = IORESOURCE_BUSY }, }; #ifdef CONFIG_MTD @@ -111,7 +111,7 @@ void __init fd_activate(void) } #endif -void __init plat_setup(void) +void __init plat_mem_setup(void) { unsigned int i; diff --git a/arch/mips/mips-boards/malta/malta_smp.c b/arch/mips/mips-boards/malta/malta_smp.c index 6c6c8ee..cf96717 100644 --- a/arch/mips/mips-boards/malta/malta_smp.c +++ b/arch/mips/mips-boards/malta/malta_smp.c @@ -34,25 +34,6 @@ #endif /* CONFIG_MIPS_MT_SMTC */ } /* - * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map - */ - -void __init prom_build_cpu_map(void) -{ - int nextslot; - - /* - * As of November, 2004, MIPSsim only simulates one core - * at a time. However, that core may be a MIPS MT core - * with multiple virtual processors and thread contexts. - */ - - if (read_c0_config3() & (1<<2)) { - nextslot = mipsmt_build_cpu_map(1); - } -} - -/* * Platform "CPU" startup hook */ diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c index 4266ce4..6430f11 100644 --- a/arch/mips/mips-boards/sead/sead_setup.c +++ b/arch/mips/mips-boards/sead/sead_setup.c @@ -45,7 +45,7 @@ const char *get_system_type(void) return "MIPS SEAD"; } -void __init plat_setup(void) +void __init plat_mem_setup(void) { ioport_resource.end = 0x7fffffff; diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c index a2fd629..15a5dac 100644 --- a/arch/mips/mips-boards/sim/sim_setup.c +++ b/arch/mips/mips-boards/sim/sim_setup.c @@ -50,7 +50,7 @@ const char *get_system_type(void) return "MIPSsim"; } -void __init plat_setup(void) +void __init plat_mem_setup(void) { set_io_port_base(0xbfd00000); diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c index b7084e7..0040709 100644 --- a/arch/mips/mips-boards/sim/sim_smp.c +++ b/arch/mips/mips-boards/sim/sim_smp.c @@ -51,27 +51,6 @@ #endif /* CONFIG_MIPS_MT_SMTC */ } /* - * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map - */ - -void __init prom_build_cpu_map(void) -{ -#ifdef CONFIG_MIPS_MT_SMTC - int nextslot; - - /* - * As of November, 2004, MIPSsim only simulates one core - * at a time. However, that core may be a MIPS MT core - * with multiple virtual processors and thread contexts. - */ - - if (read_c0_config3() & (1<<2)) { - nextslot = mipsmt_build_cpu_map(1); - } -#endif /* CONFIG_MIPS_MT_SMTC */ -} - -/* * Platform "CPU" startup hook */ diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 9dca099..965cb4c 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -413,7 +413,6 @@ out: return ret; } -extern void __init sanitize_tlb_entries(void); static void __init probe_tlb(unsigned long config) { struct cpuinfo_mips *c = ¤t_cpu_data; diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c index 1379c76..df14855 100644 --- a/arch/mips/momentum/jaguar_atx/setup.c +++ b/arch/mips/momentum/jaguar_atx/setup.c @@ -359,7 +359,7 @@ static __init int __init ja_pci_init(voi arch_initcall(ja_pci_init); -void __init plat_setup(void) +void __init plat_mem_setup(void) { unsigned int tmpword; diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c index c691952..8c53490 100644 --- a/arch/mips/momentum/ocelot_3/setup.c +++ b/arch/mips/momentum/ocelot_3/setup.c @@ -313,7 +313,7 @@ static __init int __init ja_pci_init(voi arch_initcall(ja_pci_init); -void __init plat_setup(void) +void __init plat_mem_setup(void) { unsigned int tmpword; diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index a3e6f55..257e1d1 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c @@ -231,7 +231,7 @@ #endif rtc_mips_set_time = m48t37y_set_time; } -void __init plat_setup(void) +void __init plat_mem_setup(void) { unsigned int tmpword; diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c index e5eceed..8bd9b84 100644 --- a/arch/mips/momentum/ocelot_g/gt-irq.c +++ b/arch/mips/momentum/ocelot_g/gt-irq.c @@ -59,7 +59,7 @@ void hook_irq_handler(int int_cause, int * bit_num - Indicates which bit number in the cause register * * Outputs : - * 1 if succesful, 0 if failure + * 1 if successful, 0 if failure */ int enable_galileo_irq(int int_cause, int bit_num) { @@ -83,7 +83,7 @@ int enable_galileo_irq(int int_cause, in * bit_num - Indicates which bit number in the cause register * * Outputs : - * 1 if succesful, 0 if failure + * 1 if successful, 0 if failure */ int disable_galileo_irq(int int_cause, int bit_num) { diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c index fed4e8e..72143ab 100644 --- a/arch/mips/momentum/ocelot_g/setup.c +++ b/arch/mips/momentum/ocelot_g/setup.c @@ -162,7 +162,7 @@ static void __init setup_l3cache(unsigne printk("Done\n"); } -void __init plat_setup(void) +void __init plat_mem_setup(void) { void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache); unsigned int tmpword; diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c index c31e4cf..65eb554 100644 --- a/arch/mips/oprofile/common.c +++ b/arch/mips/oprofile/common.c @@ -38,7 +38,7 @@ static int op_mips_create_files(struct s for (i = 0; i < model->num_counters; ++i) { struct dentry *dir; - char buf[3]; + char buf[4]; snprintf(buf, sizeof buf, "%d", i); dir = oprofilefs_mkdir(sb, root, buf); diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 16205b5..465778c 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -18,12 +18,12 @@ obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o obj-$(CONFIG_MIPS_TX3927) += ops-tx3927.o obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o obj-$(CONFIG_NEC_CMBVR4133) += fixup-vr4133.o +obj-$(CONFIG_MARKEINS) += ops-emma2rh.o pci-emma2rh.o fixup-emma2rh.o # # These are still pretty much in the old state, watch, go blind. # -obj-$(CONFIG_DDB5074) += fixup-ddb5074.o pci-ddb5074.o ops-ddb5074.o -obj-$(CONFIG_DDB5476) += ops-ddb5476.o pci-ddb5476.o +obj-$(CONFIG_BASLER_EXCITE) = ops-titan.o pci-excite.o fixup-excite.o obj-$(CONFIG_DDB5477) += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o obj-$(CONFIG_LASAT) += pci-lasat.o obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o @@ -43,7 +43,7 @@ obj-$(CONFIG_MOMENCO_OCELOT_C) += fixup- obj-$(CONFIG_MOMENCO_OCELOT_G) += fixup-ocelot-g.o pci-ocelot-g.o obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o ops-titan-ht.o \ pci-yosemite.o -obj-$(CONFIG_SGI_IP27) += pci-ip27.o +obj-$(CONFIG_SGI_IP27) += ops-bridge.o pci-ip27.o obj-$(CONFIG_SGI_IP32) += fixup-ip32.o ops-mace.o pci-ip32.o obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o @@ -57,3 +57,4 @@ obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup- obj-$(CONFIG_TOSHIBA_RBTX4938) += fixup-tx4938.o ops-tx4938.o obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o +obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o diff --git a/arch/mips/pci/fixup-ddb5074.c b/arch/mips/pci/fixup-ddb5074.c deleted file mode 100644 index 5a4a7c2..0000000 --- a/arch/mips/pci/fixup-ddb5074.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * It's nice to have the LEDs on the GPIO pins available for debugging - */ -static void ddb5074_fixup(struct pci_dev *dev) -{ - extern struct pci_dev *pci_pmu; - u8 t8; - - pci_pmu = dev; /* for LEDs D2 and D3 */ - /* Program the lines for LEDs D2 and D3 to output */ - pci_read_config_byte(dev, 0x7d, &t8); - t8 |= 0xc0; - pci_write_config_byte(dev, 0x7d, t8); - /* Turn LEDs D2 and D3 off */ - pci_read_config_byte(dev, 0x7e, &t8); - t8 |= 0xc0; - pci_write_config_byte(dev, 0x7e, t8); -} - -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, - ddb5074_fixup); diff --git a/arch/mips/pci/fixup-emma2rh.c b/arch/mips/pci/fixup-emma2rh.c new file mode 100644 index 0000000..3a34cd0 --- /dev/null +++ b/arch/mips/pci/fixup-emma2rh.c @@ -0,0 +1,102 @@ +/* + * arch/mips/pci/fixup-emma2rh.c + * This file defines the PCI configration. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define EMMA2RH_PCI_HOST_SLOT 0x09 +#define EMMA2RH_USB_SLOT 0x03 +#define PCI_DEVICE_ID_NEC_EMMA2RH 0x014b /* EMMA2RH PCI Host */ + +/* + * we fix up irqs based on the slot number. + * The first entry is at AD:11. + * Fortunately this works because, although we have two pci buses, + * they all have different slot numbers (except for rockhopper slot 20 + * which is handled below). + * + */ + +#define MAX_SLOT_NUM 10 +static unsigned char irq_map[][5] __initdata = { + [3] = {0, MARKEINS_PCI_IRQ_INTB, MARKEINS_PCI_IRQ_INTC, + MARKEINS_PCI_IRQ_INTD, 0,}, + [4] = {0, MARKEINS_PCI_IRQ_INTA, 0, 0, 0,}, + [5] = {0, 0, 0, 0, 0,}, + [6] = {0, MARKEINS_PCI_IRQ_INTC, MARKEINS_PCI_IRQ_INTD, + MARKEINS_PCI_IRQ_INTA, MARKEINS_PCI_IRQ_INTB,}, +}; + +static void __devinit nec_usb_controller_fixup(struct pci_dev *dev) +{ + if (PCI_SLOT(dev->devfn) == EMMA2RH_USB_SLOT) + /* on board USB controller configuration */ + pci_write_config_dword(dev, 0xe4, 1 << 5); +} + +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, + nec_usb_controller_fixup); + +/* + * Prevent the PCI layer from seeing the resources allocated to this device + * if it is the host bridge by marking it as such. These resources are of + * no consequence to the PCI layer (they are handled elsewhere). + */ +static void __devinit emma2rh_pci_host_fixup(struct pci_dev *dev) +{ + int i; + + if (PCI_SLOT(dev->devfn) == EMMA2RH_PCI_HOST_SLOT) { + dev->class &= 0xff; + dev->class |= PCI_CLASS_BRIDGE_HOST << 8; + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + dev->resource[i].start = 0; + dev->resource[i].end = 0; + dev->resource[i].flags = 0; + } + } +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH, + emma2rh_pci_host_fixup); + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return irq_map[slot][pin]; +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-excite.c b/arch/mips/pci/fixup-excite.c new file mode 100644 index 0000000..1da696d --- /dev/null +++ b/arch/mips/pci/fixup-excite.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2004 by Basler Vision Technologies AG + * Author: Thomas Koeller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + if (pin == 0) + return -1; + + return USB_IRQ; /* USB controller is the only PCI device */ +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-wrppmc.c b/arch/mips/pci/fixup-wrppmc.c new file mode 100644 index 0000000..3357c13 --- /dev/null +++ b/arch/mips/pci/fixup-wrppmc.c @@ -0,0 +1,37 @@ +/* + * fixup-wrppmc.c: PPMC board specific PCI fixup + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006, Wind River Inc. Rongkai.zhan (rongkai.zhan@windriver.com) + */ +#include +#include +#include + +/* PCI interrupt pins */ +#define PCI_INTA 1 +#define PCI_INTB 2 +#define PCI_INTC 3 +#define PCI_INTD 4 + +#define PCI_SLOT_MAXNR 32 /* Each PCI bus has 32 physical slots */ + +static char pci_irq_tab[PCI_SLOT_MAXNR][5] __initdata = { + /* 0 INTA INTB INTC INTD */ + [0] = {0, 0, 0, 0, 0}, /* Slot 0: GT64120 PCI bridge */ + [6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0}, +}; + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return pci_irq_tab[slot][pin]; +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/ops-bridge.c b/arch/mips/pci/ops-bridge.c new file mode 100644 index 0000000..1fa0992 --- /dev/null +++ b/arch/mips/pci/ops-bridge.c @@ -0,0 +1,306 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999, 2000, 04, 06 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#include +#include +#include +#include +#include +#include + +/* + * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is + * not really documented, so right now I can't write code which uses it. + * Therefore we use type 0 accesses for now even though they won't work + * correcly for PCI-to-PCI bridges. + * + * The function is complicated by the ultimate brokeness of the IOC3 chip + * which is used in SGI systems. The IOC3 can only handle 32-bit PCI + * accesses and does only decode parts of it's address space. + */ + +static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + volatile void *addr; + u32 cf, shift, mask; + int res; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; + + if (size == 1) + res = get_dbe(*value, (u8 *) addr); + else if (size == 2) + res = get_dbe(*value, (u16 *) addr); + else + res = get_dbe(*value, (u32 *) addr); + + return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { + *value = 0; + return PCIBIOS_SUCCESSFUL; + } + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + *value = (cf >> shift) & mask; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int busno = bus->number; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + volatile void *addr; + u32 cf, shift, mask; + int res; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; + + if (size == 1) + res = get_dbe(*value, (u8 *) addr); + else if (size == 2) + res = get_dbe(*value, (u16 *) addr); + else + res = get_dbe(*value, (u32 *) addr); + + return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { + *value = 0; + return PCIBIOS_SUCCESSFUL; + } + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + *value = (cf >> shift) & mask; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * value) +{ + if (bus->number > 0) + return pci_conf1_read_config(bus, devfn, where, size, value); + + return pci_conf0_read_config(bus, devfn, where, size, value); +} + +static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + volatile void *addr; + u32 cf, shift, mask, smask; + int res; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; + + if (size == 1) { + res = put_dbe(value, (u8 *) addr); + } else if (size == 2) { + res = put_dbe(value, (u16 *) addr); + } else { + res = put_dbe(value, (u32 *) addr); + } + + if (res) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to touch the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) + return PCIBIOS_SUCCESSFUL; + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + smask = mask << shift; + + cf = (cf & ~smask) | ((value & mask) << shift); + if (put_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + int busno = bus->number; + volatile void *addr; + u32 cf, shift, mask, smask; + int res; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; + + if (size == 1) { + res = put_dbe(value, (u8 *) addr); + } else if (size == 2) { + res = put_dbe(value, (u16 *) addr); + } else { + res = put_dbe(value, (u32 *) addr); + } + + if (res) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to touch the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) + return PCIBIOS_SUCCESSFUL; + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + smask = mask << shift; + + cf = (cf & ~smask) | ((value & mask) << shift); + if (put_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + if (bus->number > 0) + return pci_conf1_write_config(bus, devfn, where, size, value); + + return pci_conf0_write_config(bus, devfn, where, size, value); +} + +struct pci_ops bridge_pci_ops = { + .read = pci_read_config, + .write = pci_write_config, +}; diff --git a/arch/mips/pci/ops-ddb5074.c b/arch/mips/pci/ops-ddb5074.c deleted file mode 100644 index 89f97be..0000000 --- a/arch/mips/pci/ops-ddb5074.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * arch/mips/ddb5xxx/ddb5476/pci_ops.c - * Define the pci_ops for DB5477. - * - * Much of the code is derived from the original DDB5074 port by - * Geert Uytterhoeven - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ -#include -#include -#include - -#include -#include - -#include - -/* - * config_swap structure records what set of pdar/pmr are used - * to access pci config space. It also provides a place hold the - * original values for future restoring. - */ -struct pci_config_swap { - u32 pdar; - u32 pmr; - u32 config_base; - u32 config_size; - u32 pdar_backup; - u32 pmr_backup; -}; - -/* - * On DDB5476, we have one set of swap registers - */ -struct pci_config_swap ext_pci_swap = { - DDB_PCIW0, - DDB_PCIINIT0, - DDB_PCI_CONFIG_BASE, - DDB_PCI_CONFIG_SIZE -}; - -static int pci_config_workaround = 1; - -/* - * access config space - */ -static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */ - u32 slot_num) -{ - u32 pci_addr = 0; - u32 pciinit_offset = 0; - u32 virt_addr = swap->config_base; - u32 option; - - if (pci_config_workaround) { - if (slot_num == 5) - slot_num = 14; - } else { - if (slot_num == 5) - return DDB_BASE + DDB_PCI_BASE; - } - - /* minimum pdar (window) size is 2MB */ - db_assert(swap->config_size >= (2 << 20)); - - db_assert(slot_num < (1 << 5)); - db_assert(bus < (1 << 8)); - - /* backup registers */ - swap->pdar_backup = ddb_in32(swap->pdar); - swap->pmr_backup = ddb_in32(swap->pmr); - - /* set the pdar (pci window) register */ - ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */ - 0, /* not on local memory bus */ - 0); /* not visible from PCI bus (N/A) */ - - /* - * calcuate the absolute pci config addr; - * according to the spec, we start scanning from adr:11 (0x800) - */ - if (bus == 0) { - /* type 0 config */ - pci_addr = 0x00040000 << slot_num; - } else { - /* type 1 config */ - pci_addr = 0x00040000 << slot_num; - panic - ("ddb_access_config_base: we don't support type 1 config Yet"); - } - - /* - * if pci_addr is less than pci config window size, we set - * pciinit_offset to 0 and adjust the virt_address. - * Otherwise we will try to adjust pciinit_offset. - */ - if (pci_addr < swap->config_size) { - virt_addr = KSEG1ADDR(swap->config_base + pci_addr); - pciinit_offset = 0; - } else { - db_assert((pci_addr & (swap->config_size - 1)) == 0); - virt_addr = KSEG1ADDR(swap->config_base); - pciinit_offset = pci_addr; - } - - /* set the pmr register */ - option = DDB_PCI_ACCESS_32; - if (bus != 0) - option |= DDB_PCI_CFGTYPE1; - ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); - - return virt_addr; -} - -static inline void ddb_close_config_base(struct pci_config_swap *swap) -{ - ddb_out32(swap->pdar, swap->pdar_backup); - ddb_out32(swap->pmr, swap->pmr_backup); -} - -static int read_config_dword(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u32 * val) -{ - u32 bus, slot_num, func_num; - u32 base; - - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - slot_num = PCI_SLOT(dev->devfn); - func_num = PCI_FUNC(dev->devfn); - base = ddb_access_config_base(swap, bus, slot_num); - *val = *(volatile u32 *) (base + (func_num << 8) + where); - ddb_close_config_base(swap); - return PCIBIOS_SUCCESSFUL; -} - -static int read_config_word(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u16 * val) -{ - int status; - u32 result; - - db_assert((where & 1) == 0); - - status = read_config_dword(swap, dev, where & ~3, &result); - if (where & 2) - result >>= 16; - *val = result & 0xffff; - return status; -} - -static int read_config_byte(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u8 * val) -{ - int status; - u32 result; - - status = read_config_dword(swap, dev, where & ~3, &result); - if (where & 1) - result >>= 8; - if (where & 2) - result >>= 16; - *val = result & 0xff; - return status; -} - -static int write_config_dword(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u32 val) -{ - u32 bus, slot_num, func_num; - u32 base; - - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - slot_num = PCI_SLOT(dev->devfn); - func_num = PCI_FUNC(dev->devfn); - base = ddb_access_config_base(swap, bus, slot_num); - *(volatile u32 *) (base + (func_num << 8) + where) = val; - ddb_close_config_base(swap); - return PCIBIOS_SUCCESSFUL; -} - -static int write_config_word(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u16 val) -{ - int status, shift = 0; - u32 result; - - db_assert((where & 1) == 0); - - status = read_config_dword(swap, dev, where & ~3, &result); - if (status != PCIBIOS_SUCCESSFUL) - return status; - - if (where & 2) - shift += 16; - result &= ~(0xffff << shift); - result |= val << shift; - return write_config_dword(swap, dev, where & ~3, result); -} - -static int write_config_byte(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u8 val) -{ - int status, shift = 0; - u32 result; - - status = read_config_dword(swap, dev, where & ~3, &result); - if (status != PCIBIOS_SUCCESSFUL) - return status; - - if (where & 2) - shift += 16; - if (where & 1) - shift += 8; - result &= ~(0xff << shift); - result |= val << shift; - return write_config_dword(swap, dev, where & ~3, result); -} - -#define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \ -static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \ -{ \ - return rw##_config_##unitname(pciswap, \ - dev, \ - where, \ - val); \ -} - -MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap) - MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap) - MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap) - - MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap) - MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap) - MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap) - -struct pci_ops ddb5476_ext_pci_ops = { - extpci_read_config_byte, - extpci_read_config_word, - extpci_read_config_dword, - extpci_write_config_byte, - extpci_write_config_word, - extpci_write_config_dword -}; diff --git a/arch/mips/pci/ops-ddb5476.c b/arch/mips/pci/ops-ddb5476.c deleted file mode 100644 index 12da58e..0000000 --- a/arch/mips/pci/ops-ddb5476.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * arch/mips/ddb5xxx/ddb5476/pci_ops.c - * Define the pci_ops for DB5477. - * - * Much of the code is derived from the original DDB5074 port by - * Geert Uytterhoeven - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ -#include -#include -#include - -#include -#include - -#include - -/* - * config_swap structure records what set of pdar/pmr are used - * to access pci config space. It also provides a place hold the - * original values for future restoring. - */ -struct pci_config_swap { - u32 pdar; - u32 pmr; - u32 config_base; - u32 config_size; - u32 pdar_backup; - u32 pmr_backup; -}; - -/* - * On DDB5476, we have one set of swap registers - */ -struct pci_config_swap ext_pci_swap = { - DDB_PCIW0, - DDB_PCIINIT0, - DDB_PCI_CONFIG_BASE, - DDB_PCI_CONFIG_SIZE -}; - -static int pci_config_workaround = 1; - -/* - * access config space - */ -static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */ - u32 slot_num) -{ - u32 pci_addr = 0; - u32 pciinit_offset = 0; - u32 virt_addr = swap->config_base; - u32 option; - - if (pci_config_workaround) { - /* [jsun] work around Vrc5476 controller itself, returnning - * slot 0 essentially makes vrc5476 invisible - */ - if (slot_num == 12) - slot_num = 0; - -#if 0 - /* BUG : skip P2P bridge for now */ - if (slot_num == 5) - slot_num = 0; -#endif - - } else { - /* now we have to be hornest, returning the true - * PCI config headers for vrc5476 - */ - if (slot_num == 12) { - swap->pdar_backup = ddb_in32(swap->pdar); - swap->pmr_backup = ddb_in32(swap->pmr); - return DDB_BASE + DDB_PCI_BASE; - } - } - - /* minimum pdar (window) size is 2MB */ - db_assert(swap->config_size >= (2 << 20)); - - db_assert(slot_num < (1 << 5)); - db_assert(bus < (1 << 8)); - - /* backup registers */ - swap->pdar_backup = ddb_in32(swap->pdar); - swap->pmr_backup = ddb_in32(swap->pmr); - - /* set the pdar (pci window) register */ - ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */ - 0, /* not on local memory bus */ - 0); /* not visible from PCI bus (N/A) */ - - /* - * calcuate the absolute pci config addr; - * according to the spec, we start scanning from adr:11 (0x800) - */ - if (bus == 0) { - /* type 0 config */ - pci_addr = 0x800 << slot_num; - } else { - /* type 1 config */ - pci_addr = (bus << 16) | (slot_num << 11); - /* panic("ddb_access_config_base: we don't support type 1 config Yet"); */ - } - - /* - * if pci_addr is less than pci config window size, we set - * pciinit_offset to 0 and adjust the virt_address. - * Otherwise we will try to adjust pciinit_offset. - */ - if (pci_addr < swap->config_size) { - virt_addr = KSEG1ADDR(swap->config_base + pci_addr); - pciinit_offset = 0; - } else { - db_assert((pci_addr & (swap->config_size - 1)) == 0); - virt_addr = KSEG1ADDR(swap->config_base); - pciinit_offset = pci_addr; - } - - /* set the pmr register */ - option = DDB_PCI_ACCESS_32; - if (bus != 0) - option |= DDB_PCI_CFGTYPE1; - ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); - - return virt_addr; -} - -static inline void ddb_close_config_base(struct pci_config_swap *swap) -{ - ddb_out32(swap->pdar, swap->pdar_backup); - ddb_out32(swap->pmr, swap->pmr_backup); -} - -static int read_config_dword(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u32 * val) -{ - u32 bus, slot_num, func_num; - u32 base; - - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - slot_num = PCI_SLOT(dev->devfn); - func_num = PCI_FUNC(dev->devfn); - base = ddb_access_config_base(swap, bus, slot_num); - *val = *(volatile u32 *) (base + (func_num << 8) + where); - ddb_close_config_base(swap); - return PCIBIOS_SUCCESSFUL; -} - -static int read_config_word(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u16 * val) -{ - int status; - u32 result; - - db_assert((where & 1) == 0); - - status = read_config_dword(swap, dev, where & ~3, &result); - if (where & 2) - result >>= 16; - *val = result & 0xffff; - return status; -} - -static int read_config_byte(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u8 * val) -{ - int status; - u32 result; - - status = read_config_dword(swap, dev, where & ~3, &result); - if (where & 1) - result >>= 8; - if (where & 2) - result >>= 16; - *val = result & 0xff; - return status; -} - -static int write_config_dword(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u32 val) -{ - u32 bus, slot_num, func_num; - u32 base; - - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - slot_num = PCI_SLOT(dev->devfn); - func_num = PCI_FUNC(dev->devfn); - base = ddb_access_config_base(swap, bus, slot_num); - *(volatile u32 *) (base + (func_num << 8) + where) = val; - ddb_close_config_base(swap); - return PCIBIOS_SUCCESSFUL; -} - -static int write_config_word(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u16 val) -{ - int status, shift = 0; - u32 result; - - db_assert((where & 1) == 0); - - status = read_config_dword(swap, dev, where & ~3, &result); - if (status != PCIBIOS_SUCCESSFUL) - return status; - - if (where & 2) - shift += 16; - result &= ~(0xffff << shift); - result |= val << shift; - return write_config_dword(swap, dev, where & ~3, result); -} - -static int write_config_byte(struct pci_config_swap *swap, - struct pci_dev *dev, u32 where, u8 val) -{ - int status, shift = 0; - u32 result; - - status = read_config_dword(swap, dev, where & ~3, &result); - if (status != PCIBIOS_SUCCESSFUL) - return status; - - if (where & 2) - shift += 16; - if (where & 1) - shift += 8; - result &= ~(0xff << shift); - result |= val << shift; - return write_config_dword(swap, dev, where & ~3, result); -} - -#define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \ -static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \ -{ \ - return rw##_config_##unitname(pciswap, \ - dev, \ - where, \ - val); \ -} - -MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap) - MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap) - MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap) - - MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap) - MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap) - MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap) - -struct pci_ops ddb5476_ext_pci_ops = { - extpci_read_config_byte, - extpci_read_config_word, - extpci_read_config_dword, - extpci_write_config_byte, - extpci_write_config_word, - extpci_write_config_dword -}; diff --git a/arch/mips/pci/ops-emma2rh.c b/arch/mips/pci/ops-emma2rh.c new file mode 100644 index 0000000..e21b11b --- /dev/null +++ b/arch/mips/pci/ops-emma2rh.c @@ -0,0 +1,186 @@ +/* + * arch/mips/pci/ops-emma2rh.c + * This file defines the PCI operation for EMMA2RH. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/pci/ops-vr41xx.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include + +#define RTABORT (0x1<<9) +#define RMABORT (0x1<<10) +#define EMMA2RH_PCI_SLOT_NUM 9 /* 0000:09.0 is final PCI device */ + +/* + * access config space + */ + +static int check_args(struct pci_bus *bus, u32 devfn, u32 * bus_num) +{ + /* check if the bus is top-level */ + if (bus->parent != NULL) { + *bus_num = bus->number; + db_assert(bus_num != 0); + } else + *bus_num = 0; + + if (*bus_num == 0) { + /* Type 0 */ + if (PCI_SLOT(devfn) >= 10) + return PCIBIOS_DEVICE_NOT_FOUND; + } else { + /* Type 1 */ + if ((*bus_num >= 64) || (PCI_SLOT(devfn) >= 16)) + return PCIBIOS_DEVICE_NOT_FOUND; + } + return 0; +} + +static inline int set_pci_configuration_address(unsigned char bus_num, + unsigned int devfn, int where) +{ + u32 config_win0; + + emma2rh_out32(EMMA2RH_PCI_INT, ~RMABORT); + if (bus_num == 0) + /* + * Type 0 configuration + */ + config_win0 = (1 << (22 + PCI_SLOT(devfn))) | (5 << 9); + else + /* + * Type 1 configuration + */ + config_win0 = (bus_num << 26) | (PCI_SLOT(devfn) << 22) | + (1 << 15) | (5 << 9); + + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, config_win0); + + return 0; +} + +static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, + int size, uint32_t * val) +{ + u32 bus_num; + u32 base = KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE); + u32 backup_win0; + u32 data; + + *val = 0xffffffffU; + + if (check_args(bus, devfn, &bus_num) == PCIBIOS_DEVICE_NOT_FOUND) + return PCIBIOS_DEVICE_NOT_FOUND; + + backup_win0 = emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR); + + if (set_pci_configuration_address(bus_num, devfn, where) < 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + data = + *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) + + (where & 0xfffffffc)); + + switch (size) { + case 1: + *val = (data >> ((where & 3) << 3)) & 0xffU; + break; + case 2: + *val = (data >> ((where & 2) << 3)) & 0xffffU; + break; + case 4: + *val = data; + break; + default: + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0); + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0); + + if (emma2rh_in32(EMMA2RH_PCI_INT) & RMABORT) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 val) +{ + u32 bus_num; + u32 base = KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE); + u32 backup_win0; + u32 data; + int shift; + + if (check_args(bus, devfn, &bus_num) == PCIBIOS_DEVICE_NOT_FOUND) + return PCIBIOS_DEVICE_NOT_FOUND; + + backup_win0 = emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR); + + if (set_pci_configuration_address(bus_num, devfn, where) < 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* read modify write */ + data = + *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) + + (where & 0xfffffffc)); + + switch (size) { + case 1: + shift = (where & 3) << 3; + data &= ~(0xffU << shift); + data |= ((val & 0xffU) << shift); + break; + case 2: + shift = (where & 2) << 3; + data &= ~(0xffffU << shift); + data |= ((val & 0xffffU) << shift); + break; + case 4: + data = val; + break; + default: + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0); + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) + + (where & 0xfffffffc)) = data; + + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0); + if (emma2rh_in32(EMMA2RH_PCI_INT) & RMABORT) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops emma2rh_pci_ops = { + .read = pci_config_read, + .write = pci_config_write, +}; diff --git a/arch/mips/pci/ops-it8172.c b/arch/mips/pci/ops-it8172.c index b7a8b9a..ba83285 100644 --- a/arch/mips/pci/ops-it8172.c +++ b/arch/mips/pci/ops-it8172.c @@ -50,30 +50,28 @@ #endif static struct resource pci_mem_resource_1; static struct resource pci_io_resource = { - "io pci IO space", - 0x14018000, - 0x17FFFFFF, - IORESOURCE_IO + .start = 0x14018000, + .end = 0x17FFFFFF, + .name = "io pci IO space", + .flags = IORESOURCE_IO }; static struct resource pci_mem_resource_0 = { - "ext pci memory space 0/1", - 0x10101000, - 0x13FFFFFF, - IORESOURCE_MEM, - &pci_mem_resource_0, - NULL, - &pci_mem_resource_1 + .start = 0x10101000, + .end = 0x13FFFFFF, + .name = "ext pci memory space 0/1", + .flags = IORESOURCE_MEM, + .parent = &pci_mem_resource_0, + .sibling = NULL, + .child = &pci_mem_resource_1 }; static struct resource pci_mem_resource_1 = { - "ext pci memory space 2/3", - 0x1A000000, - 0x1FBFFFFF, - IORESOURCE_MEM, - &pci_mem_resource_0, - NULL, - NULL + .start = 0x1A000000, + .end = 0x1FBFFFFF, + .name = "ext pci memory space 2/3", + .flags = IORESOURCE_MEM, + .parent = &pci_mem_resource_0 }; extern struct pci_ops it8172_pci_ops; diff --git a/arch/mips/pci/ops-sni.c b/arch/mips/pci/ops-sni.c index 62bdd19..2b0ccd6 100644 --- a/arch/mips/pci/ops-sni.c +++ b/arch/mips/pci/ops-sni.c @@ -47,13 +47,13 @@ static int pcimt_read(struct pci_bus *bu switch (size) { case 1: - *val = *(volatile u8 *) (PCIMT_CONFIG_DATA + (reg & 3)); + *val = inb(PCIMT_CONFIG_DATA + (reg & 3)); break; case 2: - *val = *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2)); + *val = inw(PCIMT_CONFIG_DATA + (reg & 2)); break; case 4: - *val = *(volatile u32 *) PCIMT_CONFIG_DATA; + *val = inl(PCIMT_CONFIG_DATA); break; } @@ -70,13 +70,13 @@ static int pcimt_write(struct pci_bus *b switch (size) { case 1: - *(volatile u8 *) (PCIMT_CONFIG_DATA + (reg & 3)) = val; + outb (val, PCIMT_CONFIG_DATA + (reg & 3)); break; case 2: - *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2)) = val; + outw (val, PCIMT_CONFIG_DATA + (reg & 2)); break; case 4: - *(volatile u32 *) PCIMT_CONFIG_DATA = val; + outl (val, PCIMT_CONFIG_DATA); break; } diff --git a/arch/mips/pci/ops-titan.c b/arch/mips/pci/ops-titan.c index 233ec6f..ebf8fc4 100644 --- a/arch/mips/pci/ops-titan.c +++ b/arch/mips/pci/ops-titan.c @@ -26,8 +26,19 @@ #include #include #include -#include +#include +#include +#include +/* + * PCI specific defines + */ +#define TITAN_PCI_0_CONFIG_ADDRESS 0x780 +#define TITAN_PCI_0_CONFIG_DATA 0x784 + +/* + * Titan PCI Config Read Byte + */ static int titan_read_config(struct pci_bus *bus, unsigned int devfn, int reg, int size, u32 * val) { @@ -43,8 +54,8 @@ static int titan_read_config(struct pci_ /* start the configuration cycle */ - TITAN_WRITE(TITAN_PCI_0_CONFIG_ADDRESS, address); - tmp = TITAN_READ(TITAN_PCI_0_CONFIG_DATA) >> ((reg & 3) << 3); + ocd_writel(address, TITAN_PCI_0_CONFIG_ADDRESS); + tmp = ocd_readl(TITAN_PCI_0_CONFIG_DATA) >> ((reg & 3) << 3); switch (size) { case 1: @@ -71,20 +82,20 @@ static int titan_write_config(struct pci (reg & 0xfc) | 0x80000000; /* start the configuration cycle */ - TITAN_WRITE(TITAN_PCI_0_CONFIG_ADDRESS, address); + ocd_writel(address, TITAN_PCI_0_CONFIG_ADDRESS); /* write the data */ switch (size) { case 1: - TITAN_WRITE_8(TITAN_PCI_0_CONFIG_DATA + (~reg & 0x3), val); + ocd_writeb(val, TITAN_PCI_0_CONFIG_DATA + (~reg & 0x3)); break; case 2: - TITAN_WRITE_16(TITAN_PCI_0_CONFIG_DATA + (~reg & 0x2), val); + ocd_writew(val, TITAN_PCI_0_CONFIG_DATA + (~reg & 0x2)); break; case 4: - TITAN_WRITE(TITAN_PCI_0_CONFIG_DATA, val); + ocd_writel(val, TITAN_PCI_0_CONFIG_DATA); break; } diff --git a/arch/mips/pci/pci-ddb5074.c b/arch/mips/pci/pci-ddb5074.c deleted file mode 100644 index 73f9cee..0000000 --- a/arch/mips/pci/pci-ddb5074.c +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include -#include -#include - -#include - -#include - -static struct resource extpci_io_resource = { - "pci IO space", - 0x1000, /* leave some room for ISA bus */ - DDB_PCI_IO_SIZE - 1, - IORESOURCE_IO -}; - -static struct resource extpci_mem_resource = { - "pci memory space", - DDB_PCI_MEM_BASE + 0x00100000, /* leave 1 MB for RTC */ - DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1, - IORESOURCE_MEM -}; - -extern struct pci_ops ddb5476_ext_pci_ops; - -struct pci_controller ddb5476_controller = { - .pci_ops = &ddb5476_ext_pci_ops, - .io_resource = &extpci_io_resource, - .mem_resource = &extpci_mem_resource, -}; - -#define PCI_EXT_INTA 8 -#define PCI_EXT_INTB 9 -#define PCI_EXT_INTC 10 -#define PCI_EXT_INTD 11 -#define PCI_EXT_INTE 12 - -#define MAX_SLOT_NUM 14 - -static unsigned char irq_map[MAX_SLOT_NUM] = { - [ 0] = nile4_to_irq(PCI_EXT_INTE), - [ 1] = nile4_to_irq(PCI_EXT_INTA), - [ 2] = nile4_to_irq(PCI_EXT_INTA), - [ 3] = nile4_to_irq(PCI_EXT_INTB), - [ 4] = nile4_to_irq(PCI_EXT_INTC), - [ 5] = nile4_to_irq(NILE4_INT_UART), - [10] = nile4_to_irq(PCI_EXT_INTE), - [13] = nile4_to_irq(PCI_EXT_INTE), -}; - -int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - return irq_map[slot]; -} - -/* Do platform specific device initialization at pci_enable_device() time */ -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - return 0; -} - -void __init ddb_pci_reset_bus(void) -{ - u32 temp; - - /* - * I am not sure about the "official" procedure, the following - * steps work as far as I know: - * We first set PCI cold reset bit (bit 31) in PCICTRL-H. - * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H. - * The same is true for both PCI channels. - */ - temp = ddb_in32(DDB_PCICTRL + 4); - temp |= 0x80000000; - ddb_out32(DDB_PCICTRL + 4, temp); - temp &= ~0xc0000000; - ddb_out32(DDB_PCICTRL + 4, temp); - -} diff --git a/arch/mips/pci/pci-ddb5476.c b/arch/mips/pci/pci-ddb5476.c deleted file mode 100644 index 90dd495..0000000 --- a/arch/mips/pci/pci-ddb5476.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include -#include -#include - -#include - -#include - -static struct resource extpci_io_resource = { - "pci IO space", - 0x1000, /* leave some room for ISA bus */ - DDB_PCI_IO_SIZE - 1, - IORESOURCE_IO -}; - -static struct resource extpci_mem_resource = { - "pci memory space", - DDB_PCI_MEM_BASE + 0x00100000, /* leave 1 MB for RTC */ - DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1, - IORESOURCE_MEM -}; - -extern struct pci_ops ddb5476_ext_pci_ops; - -struct pci_controller ddb5476_controller = { - .pci_ops = &ddb5476_ext_pci_ops, - .io_resource = &extpci_io_resource, - .mem_resource = &extpci_mem_resource -}; - - -/* - * we fix up irqs based on the slot number. - * The first entry is at AD:11. - * - * This does not work for devices on sub-buses yet. - */ - -/* - * temporary - */ - -#define PCI_EXT_INTA 8 -#define PCI_EXT_INTB 9 -#define PCI_EXT_INTC 10 -#define PCI_EXT_INTD 11 -#define PCI_EXT_INTE 12 - -/* - * based on ddb5477 manual page 11 - */ -#define MAX_SLOT_NUM 21 -static unsigned char irq_map[MAX_SLOT_NUM] = { - [ 2] = 9, /* AD:13 USB */ - [ 3] = 10, /* AD:14 PMU */ - [ 5] = 0, /* AD:16 P2P bridge */ - [ 6] = nile4_to_irq(PCI_EXT_INTB), /* AD:17 */ - [ 7] = nile4_to_irq(PCI_EXT_INTC), /* AD:18 */ - [ 8] = nile4_to_irq(PCI_EXT_INTD), /* AD:19 */ - [ 9] = nile4_to_irq(PCI_EXT_INTA), /* AD:20 */ - [13] = 14, /* AD:24 HD controller, M5229 */ -}; - -int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - return irq_map[slot]; -} - -/* Do platform specific device initialization at pci_enable_device() time */ -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - return 0; -} - -void __init ddb_pci_reset_bus(void) -{ - u32 temp; - - /* - * I am not sure about the "official" procedure, the following - * steps work as far as I know: - * We first set PCI cold reset bit (bit 31) in PCICTRL-H. - * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H. - * The same is true for both PCI channels. - */ - temp = ddb_in32(DDB_PCICTRL + 4); - temp |= 0x80000000; - ddb_out32(DDB_PCICTRL + 4, temp); - temp &= ~0xc0000000; - ddb_out32(DDB_PCICTRL + 4, temp); - -} diff --git a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c index 826d653..d071bc3 100644 --- a/arch/mips/pci/pci-ddb5477.c +++ b/arch/mips/pci/pci-ddb5477.c @@ -22,31 +22,31 @@ #include #include static struct resource extpci_io_resource = { - "ext pci IO space", - DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + 0x4000, - DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE - 1, - IORESOURCE_IO + .start = DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + 0x4000, + .end = DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE - 1, + .name = "ext pci IO space", + .flags = IORESOURCE_IO }; static struct resource extpci_mem_resource = { - "ext pci memory space", - DDB_PCI0_MEM_BASE + 0x100000, - DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE - 1, - IORESOURCE_MEM + .start = DDB_PCI0_MEM_BASE + 0x100000, + .end = DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE - 1, + .name = "ext pci memory space", + .flags = IORESOURCE_MEM }; static struct resource iopci_io_resource = { - "io pci IO space", - DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE, - DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE - 1, - IORESOURCE_IO + .start = DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE, + .end = DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE - 1, + .name = "io pci IO space", + .flags = IORESOURCE_IO }; static struct resource iopci_mem_resource = { - "ext pci memory space", - DDB_PCI1_MEM_BASE, - DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE - 1, - IORESOURCE_MEM + .start = DDB_PCI1_MEM_BASE, + .end = DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE - 1, + .name = "ext pci memory space", + .flags = IORESOURCE_MEM }; extern struct pci_ops ddb5477_ext_pci_ops; diff --git a/arch/mips/pci/pci-emma2rh.c b/arch/mips/pci/pci-emma2rh.c new file mode 100644 index 0000000..0f8b230 --- /dev/null +++ b/arch/mips/pci/pci-emma2rh.c @@ -0,0 +1,90 @@ +/* + * arch/mips/pci/pci-emma2rh.c + * This file defines the PCI configration. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include + +static struct resource pci_io_resource = { + .name = "pci IO space", + .start = EMMA2RH_PCI_IO_BASE, + .end = EMMA2RH_PCI_IO_BASE + EMMA2RH_PCI_IO_SIZE - 1, + .flags = IORESOURCE_IO, +}; + +static struct resource pci_mem_resource = { + .name = "pci memory space", + .start = EMMA2RH_PCI_MEM_BASE, + .end = EMMA2RH_PCI_MEM_BASE + EMMA2RH_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +extern struct pci_ops emma2rh_pci_ops; + +static struct pci_controller emma2rh_pci_controller = { + .pci_ops = &emma2rh_pci_ops, + .mem_resource = &pci_mem_resource, + .io_resource = &pci_io_resource, + .mem_offset = -0x04000000, + .io_offset = 0, +}; + +static void __init emma2rh_pci_init(void) +{ + /* setup PCI interface */ + emma2rh_out32(EMMA2RH_PCI_ARBIT_CTR, 0x70f); + + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, 0x80000a18); + emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_COMMAND, + PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_CAP_LIST | + PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_BASE_ADDRESS_0, 0x10000000); + emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_BASE_ADDRESS_1, 0x00000000); + + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, 0x12000000 | 0x218); + emma2rh_out32(EMMA2RH_PCI_IWIN1_CTR, 0x18000000 | 0x600); + emma2rh_out32(EMMA2RH_PCI_INIT_ESWP, 0x00000200); + + emma2rh_out32(EMMA2RH_PCI_TWIN_CTR, 0x00009200); + emma2rh_out32(EMMA2RH_PCI_TWIN_BADR, 0x00000000); + emma2rh_out32(EMMA2RH_PCI_TWIN0_DADR, 0x00000000); + emma2rh_out32(EMMA2RH_PCI_TWIN1_DADR, 0x00000000); +} + +static int __init emma2rh_pci_setup(void) +{ + emma2rh_pci_init(); + register_pci_controller(&emma2rh_pci_controller); + return 0; +} + +arch_initcall(emma2rh_pci_setup); diff --git a/arch/mips/pci/pci-excite.c b/arch/mips/pci/pci-excite.c new file mode 100644 index 0000000..3c86c77 --- /dev/null +++ b/arch/mips/pci/pci-excite.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2004 by Basler Vision Technologies AG + * Author: Thomas Koeller + * Based on the PMC-Sierra Yosemite board support by Ralf Baechle. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include + + +extern struct pci_ops titan_pci_ops; + + +static struct resource + mem_resource = { + .name = "PCI memory", + .start = EXCITE_PHYS_PCI_MEM, + .end = EXCITE_PHYS_PCI_MEM + EXCITE_SIZE_PCI_MEM - 1, + .flags = IORESOURCE_MEM + }, + io_resource = { + .name = "PCI I/O", + .start = EXCITE_PHYS_PCI_IO, + .end = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1, + .flags = IORESOURCE_IO + }; + + +static struct pci_controller bx_controller = { + .pci_ops = &titan_pci_ops, + .mem_resource = &mem_resource, + .mem_offset = 0x00000000UL, + .io_resource = &io_resource, + .io_offset = 0x00000000UL +}; + + +static char + iopage_failed[] __initdata = "Cannot allocate PCI I/O page", + modebits_no_pci[] __initdata = "PCI is not configured in mode bits"; + +#define RM9000x2_OCD_HTSC 0x0604 +#define RM9000x2_OCD_HTBHL 0x060c +#define RM9000x2_OCD_PCIHRST 0x078c + +#define RM9K_OCD_MODEBIT1 0x00d4 /* (MODEBIT1) Mode Bit 1 */ +#define RM9K_OCD_CPHDCR 0x00f4 /* CPU-PCI/HT Data Control. */ + +#define PCISC_FB2B 0x00000200 +#define PCISC_MWICG 0x00000010 +#define PCISC_EMC 0x00000004 +#define PCISC_ERMA 0x00000002 + + + +static int __init basler_excite_pci_setup(void) +{ + const unsigned int fullbars = memsize / (256 << 20); + unsigned int i; + + /* Check modebits to see if PCI is really enabled. */ + if (!((ocd_readl(RM9K_OCD_MODEBIT1) >> (47-32)) & 0x1)) + panic(modebits_no_pci); + + if (NULL == request_mem_region(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO, + "Memory-mapped PCI I/O page")) + panic(iopage_failed); + + /* Enable PCI 0 as master for config cycles */ + ocd_writel(PCISC_EMC | PCISC_ERMA, RM9000x2_OCD_HTSC); + + + /* Set up latency timer */ + ocd_writel(0x8008, RM9000x2_OCD_HTBHL); + + /* Setup host IO and Memory space */ + ocd_writel((EXCITE_PHYS_PCI_IO >> 4) | 1, LKB7); + ocd_writel(((EXCITE_SIZE_PCI_IO >> 4) & 0x7fffff00) - 0x100, LKM7); + ocd_writel((EXCITE_PHYS_PCI_MEM >> 4) | 1, LKB8); + ocd_writel(((EXCITE_SIZE_PCI_MEM >> 4) & 0x7fffff00) - 0x100, LKM8); + + /* Set up PCI BARs to map all installed memory */ + for (i = 0; i < 6; i++) { + const unsigned int bar = 0x610 + i * 4; + + if (i < fullbars) { + ocd_writel(0x10000000 * i, bar); + ocd_writel(0x01000000 * i, bar + 0x140); + ocd_writel(0x0ffff029, bar + 0x100); + continue; + } + + if (i == fullbars) { + int o; + u32 mask; + + const unsigned long rem = memsize - i * 0x10000000; + if (!rem) { + ocd_writel(0x00000000, bar + 0x100); + continue; + } + + o = ffs(rem) - 1; + if (rem & ~(0x1 << o)) + o++; + mask = ((0x1 << o) & 0x0ffff000) - 0x1000; + ocd_writel(0x10000000 * i, bar); + ocd_writel(0x01000000 * i, bar + 0x140); + ocd_writel(0x00000029 | mask, bar + 0x100); + continue; + } + + ocd_writel(0x00000000, bar + 0x100); + } + + /* Finally, enable the PCI interupt */ +#if USB_IRQ > 7 + set_c0_intcontrol(1 << USB_IRQ); +#else + set_c0_status(1 << (USB_IRQ + 8)); +#endif + + ioport_resource.start = EXCITE_PHYS_PCI_IO; + ioport_resource.end = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1; + set_io_port_base((unsigned long) ioremap_nocache(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO)); + register_pci_controller(&bx_controller); + return 0; +} + + +arch_initcall(basler_excite_pci_setup); diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 6002d2a..80eb9af 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -40,297 +40,7 @@ static struct bridge_controller bridges[ struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; -/* - * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is - * not really documented, so right now I can't write code which uses it. - * Therefore we use type 0 accesses for now even though they won't work - * correcly for PCI-to-PCI bridges. - * - * The function is complicated by the ultimate brokeness of the IOC3 chip - * which is used in SGI systems. The IOC3 can only handle 32-bit PCI - * accesses and does only decode parts of it's address space. - */ - -static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * value) -{ - struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); - bridge_t *bridge = bc->base; - int slot = PCI_SLOT(devfn); - int fn = PCI_FUNC(devfn); - volatile void *addr; - u32 cf, shift, mask; - int res; - - addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; - if (get_dbe(cf, (u32 *) addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - /* - * IOC3 is fucked fucked beyond believe ... Don't even give the - * generic PCI code a chance to look at it for real ... - */ - if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) - goto oh_my_gawd; - - addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; - - if (size == 1) - res = get_dbe(*value, (u8 *) addr); - else if (size == 2) - res = get_dbe(*value, (u16 *) addr); - else - res = get_dbe(*value, (u32 *) addr); - - return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; - -oh_my_gawd: - - /* - * IOC3 is fucked fucked beyond believe ... Don't even give the - * generic PCI code a chance to look at the wrong register. - */ - if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { - *value = 0; - return PCIBIOS_SUCCESSFUL; - } - - /* - * IOC3 is fucked fucked beyond believe ... Don't try to access - * anything but 32-bit words ... - */ - addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; - - if (get_dbe(cf, (u32 *) addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - shift = ((where & 3) << 3); - mask = (0xffffffffU >> ((4 - size) << 3)); - *value = (cf >> shift) & mask; - - return PCIBIOS_SUCCESSFUL; -} - -static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * value) -{ - struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); - bridge_t *bridge = bc->base; - int busno = bus->number; - int slot = PCI_SLOT(devfn); - int fn = PCI_FUNC(devfn); - volatile void *addr; - u32 cf, shift, mask; - int res; - - bridge->b_pci_cfg = (busno << 16) | (slot << 11); - addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; - if (get_dbe(cf, (u32 *) addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - /* - * IOC3 is fucked fucked beyond believe ... Don't even give the - * generic PCI code a chance to look at it for real ... - */ - if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) - goto oh_my_gawd; - - bridge->b_pci_cfg = (busno << 16) | (slot << 11); - addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; - - if (size == 1) - res = get_dbe(*value, (u8 *) addr); - else if (size == 2) - res = get_dbe(*value, (u16 *) addr); - else - res = get_dbe(*value, (u32 *) addr); - - return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; - -oh_my_gawd: - - /* - * IOC3 is fucked fucked beyond believe ... Don't even give the - * generic PCI code a chance to look at the wrong register. - */ - if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { - *value = 0; - return PCIBIOS_SUCCESSFUL; - } - - /* - * IOC3 is fucked fucked beyond believe ... Don't try to access - * anything but 32-bit words ... - */ - bridge->b_pci_cfg = (busno << 16) | (slot << 11); - addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; - - if (get_dbe(cf, (u32 *) addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - shift = ((where & 3) << 3); - mask = (0xffffffffU >> ((4 - size) << 3)); - *value = (cf >> shift) & mask; - - return PCIBIOS_SUCCESSFUL; -} - -static int pci_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * value) -{ - if (bus->number > 0) - return pci_conf1_read_config(bus, devfn, where, size, value); - - return pci_conf0_read_config(bus, devfn, where, size, value); -} - -static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 value) -{ - struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); - bridge_t *bridge = bc->base; - int slot = PCI_SLOT(devfn); - int fn = PCI_FUNC(devfn); - volatile void *addr; - u32 cf, shift, mask, smask; - int res; - - addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; - if (get_dbe(cf, (u32 *) addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - /* - * IOC3 is fucked fucked beyond believe ... Don't even give the - * generic PCI code a chance to look at it for real ... - */ - if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) - goto oh_my_gawd; - - addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; - - if (size == 1) { - res = put_dbe(value, (u8 *) addr); - } else if (size == 2) { - res = put_dbe(value, (u16 *) addr); - } else { - res = put_dbe(value, (u32 *) addr); - } - - if (res) - return PCIBIOS_DEVICE_NOT_FOUND; - - return PCIBIOS_SUCCESSFUL; - -oh_my_gawd: - - /* - * IOC3 is fucked fucked beyond believe ... Don't even give the - * generic PCI code a chance to touch the wrong register. - */ - if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) - return PCIBIOS_SUCCESSFUL; - - /* - * IOC3 is fucked fucked beyond believe ... Don't try to access - * anything but 32-bit words ... - */ - addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; - - if (get_dbe(cf, (u32 *) addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - shift = ((where & 3) << 3); - mask = (0xffffffffU >> ((4 - size) << 3)); - smask = mask << shift; - - cf = (cf & ~smask) | ((value & mask) << shift); - if (put_dbe(cf, (u32 *) addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - return PCIBIOS_SUCCESSFUL; -} - -static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 value) -{ - struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); - bridge_t *bridge = bc->base; - int slot = PCI_SLOT(devfn); - int fn = PCI_FUNC(devfn); - int busno = bus->number; - volatile void *addr; - u32 cf, shift, mask, smask; - int res; - - bridge->b_pci_cfg = (busno << 16) | (slot << 11); - addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; - if (get_dbe(cf, (u32 *) addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - /* - * IOC3 is fucked fucked beyond believe ... Don't even give the - * generic PCI code a chance to look at it for real ... - */ - if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) - goto oh_my_gawd; - - addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; - - if (size == 1) { - res = put_dbe(value, (u8 *) addr); - } else if (size == 2) { - res = put_dbe(value, (u16 *) addr); - } else { - res = put_dbe(value, (u32 *) addr); - } - - if (res) - return PCIBIOS_DEVICE_NOT_FOUND; - - return PCIBIOS_SUCCESSFUL; - -oh_my_gawd: - - /* - * IOC3 is fucked fucked beyond believe ... Don't even give the - * generic PCI code a chance to touch the wrong register. - */ - if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) - return PCIBIOS_SUCCESSFUL; - - /* - * IOC3 is fucked fucked beyond believe ... Don't try to access - * anything but 32-bit words ... - */ - addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; - - if (get_dbe(cf, (u32 *) addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - shift = ((where & 3) << 3); - mask = (0xffffffffU >> ((4 - size) << 3)); - smask = mask << shift; - - cf = (cf & ~smask) | ((value & mask) << shift); - if (put_dbe(cf, (u32 *) addr)) - return PCIBIOS_DEVICE_NOT_FOUND; - - return PCIBIOS_SUCCESSFUL; -} - -static int pci_write_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 value) -{ - if (bus->number > 0) - return pci_conf1_write_config(bus, devfn, where, size, value); - - return pci_conf0_write_config(bus, devfn, where, size, value); -} - -static struct pci_ops bridge_pci_ops = { - .read = pci_read_config, - .write = pci_write_config, -}; +extern struct pci_ops bridge_pci_ops; int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) { @@ -370,8 +80,7 @@ int __init bridge_probe(nasid_t nasid, i bc->widget_id = widget_id; bc->nasid = nasid; - bc->baddr = (u64)masterwid << 60; - bc->baddr |= (1UL << 56); /* Barrier set */ + bc->baddr = (u64)masterwid << 60 | PCI64_ATTR_BAR; /* * point to this bridge diff --git a/arch/mips/pci/pci-jmr3927.c b/arch/mips/pci/pci-jmr3927.c index f02ef6e..cb84f4e 100644 --- a/arch/mips/pci/pci-jmr3927.c +++ b/arch/mips/pci/pci-jmr3927.c @@ -35,17 +35,17 @@ #include #include struct resource pci_io_resource = { - "IO MEM", - 0x1000, /* reserve regacy I/O space */ - 0x1000 + JMR3927_PCIIO_SIZE - 1, - IORESOURCE_IO + .name = "IO MEM", + .start = 0x1000, /* reserve regacy I/O space */ + .end = 0x1000 + JMR3927_PCIIO_SIZE - 1, + .flags = IORESOURCE_IO }; struct resource pci_mem_resource = { - "PCI MEM", - JMR3927_PCIMEM, - JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1, - IORESOURCE_MEM + .name = "PCI MEM", + .start = JMR3927_PCIMEM, + .end = JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1, + .flags = IORESOURCE_MEM }; extern struct pci_ops jmr3927_pci_ops; diff --git a/arch/mips/pci/pci-ocelot.c b/arch/mips/pci/pci-ocelot.c index 3da8a4e..2b9495d 100644 --- a/arch/mips/pci/pci-ocelot.c +++ b/arch/mips/pci/pci-ocelot.c @@ -71,13 +71,13 @@ static inline void pci0WriteConfigReg(un } static struct resource ocelot_mem_resource = { - iomem_resource.start = GT_PCI_MEM_BASE; - iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1; + start = GT_PCI_MEM_BASE; + end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1; }; static struct resource ocelot_io_resource = { - ioport_resource.start = GT_PCI_IO_BASE; - ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; + start = GT_PCI_IO_BASE; + end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; }; static struct pci_controller ocelot_pci_controller = { diff --git a/arch/mips/pci/pci-yosemite.c b/arch/mips/pci/pci-yosemite.c index dac9ed4..0357946 100644 --- a/arch/mips/pci/pci-yosemite.c +++ b/arch/mips/pci/pci-yosemite.c @@ -14,7 +14,10 @@ #include extern struct pci_ops titan_pci_ops; static struct resource py_mem_resource = { - "Titan PCI MEM", 0xe0000000UL, 0xe3ffffffUL, IORESOURCE_MEM + .start = 0xe0000000UL, + .end = 0xe3ffffffUL, + .name = "Titan PCI MEM", + .flags = IORESOURCE_MEM }; /* @@ -26,7 +29,10 @@ #define TITAN_IO_SIZE 0x0000ffffUL #define TITAN_IO_BASE 0xe8000000UL static struct resource py_io_resource = { - "Titan IO MEM", 0x00001000UL, TITAN_IO_SIZE - 1, IORESOURCE_IO, + .start = 0x00001000UL, + .end = TITAN_IO_SIZE - 1, + .name = "Titan IO MEM", + .flags = IORESOURCE_IO, }; static struct pci_controller py_controller = { diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 21402ff..4dfce15 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -76,11 +76,6 @@ pcibios_align_resource(void *data, struc res->start = start; } -struct pci_controller * __init alloc_pci_controller(void) -{ - return alloc_bootmem(sizeof(struct pci_controller)); -} - void __init register_pci_controller(struct pci_controller *hose) { *hose_tail = hose; diff --git a/arch/mips/philips/pnx8550/common/pci.c b/arch/mips/philips/pnx8550/common/pci.c index baa6905..eee4f3d 100644 --- a/arch/mips/philips/pnx8550/common/pci.c +++ b/arch/mips/philips/pnx8550/common/pci.c @@ -27,17 +27,17 @@ #include #include static struct resource pci_io_resource = { - "pci IO space", - (u32)(PNX8550_PCIIO + 0x1000), /* reserve regacy I/O space */ - (u32)(PNX8550_PCIIO + PNX8550_PCIIO_SIZE), - IORESOURCE_IO + .start = PNX8550_PCIIO + 0x1000, /* reserve regacy I/O space */ + .end = PNX8550_PCIIO + PNX8550_PCIIO_SIZE, + .name = "pci IO space", + .flags = IORESOURCE_IO }; static struct resource pci_mem_resource = { - "pci memory space", - (u32)(PNX8550_PCIMEM), - (u32)(PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1), - IORESOURCE_MEM + .start = PNX8550_PCIMEM, + .end = PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1, + .name = "pci memory space", + .flags = IORESOURCE_MEM }; extern struct pci_ops pnx8550_pci_ops; diff --git a/arch/mips/philips/pnx8550/common/setup.c b/arch/mips/philips/pnx8550/common/setup.c index 0d8a776..0e791f4 100644 --- a/arch/mips/philips/pnx8550/common/setup.c +++ b/arch/mips/philips/pnx8550/common/setup.c @@ -58,10 +58,27 @@ extern void prom_printf(char *fmt, ...); extern char *prom_getcmdline(void); struct resource standard_io_resources[] = { - {"dma1", 0x00, 0x1f, IORESOURCE_BUSY}, - {"timer", 0x40, 0x5f, IORESOURCE_BUSY}, - {"dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, - {"dma2", 0xc0, 0xdf, IORESOURCE_BUSY}, + { + .start = .0x00, + .end = 0x1f, + .name = "dma1", + .flags = IORESOURCE_BUSY + }, { + .start = 0x40, + .end = 0x5f, + .name = "timer", + .flags = IORESOURCE_BUSY + }, { + .start = 0x80, + .end = 0x8f, + .name = "dma page reg", + .flags = IORESOURCE_BUSY + }, { + .start = 0xc0, + .end = 0xdf, + .name = "dma2", + .flags = IORESOURCE_BUSY + }, }; #define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource)) @@ -82,7 +99,7 @@ unsigned long get_system_mem_size(void) int pnx8550_console_port = -1; -void __init plat_setup(void) +void __init plat_mem_setup(void) { int i; char* argptr; diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c index 3f724d6..aa0d6ff 100644 --- a/arch/mips/pmc-sierra/yosemite/setup.c +++ b/arch/mips/pmc-sierra/yosemite/setup.c @@ -218,7 +218,7 @@ static void __init py_late_time_init(voi py_rtc_setup(); } -void __init plat_setup(void) +void __init plat_mem_setup(void) { board_time_init = yosemite_time_init; late_time_init = py_late_time_init; diff --git a/arch/mips/qemu/Makefile b/arch/mips/qemu/Makefile index 730f459..078cd30 100644 --- a/arch/mips/qemu/Makefile +++ b/arch/mips/qemu/Makefile @@ -2,6 +2,6 @@ # # Makefile for Qemu specific kernel interface routines under Linux. # -obj-y = q-firmware.o q-irq.o q-mem.o q-setup.o +obj-y = q-firmware.o q-irq.o q-mem.o q-setup.o q-reset.o obj-$(CONFIG_SMP) += q-smp.o diff --git a/arch/mips/qemu/q-reset.c b/arch/mips/qemu/q-reset.c new file mode 100644 index 0000000..c04ebcf --- /dev/null +++ b/arch/mips/qemu/q-reset.c @@ -0,0 +1,34 @@ +#include + +#include +#include +#include +#include + +static void qemu_machine_restart(char *command) +{ + volatile unsigned int *reg = (unsigned int *)QEMU_RESTART_REG; + + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + *reg = 42; + while (1) + cpu_wait(); +} + +static void qemu_machine_halt(void) +{ + volatile unsigned int *reg = (unsigned int *)QEMU_HALT_REG; + + *reg = 42; + while (1) + cpu_wait(); +} + +void qemu_reboot_setup(void) +{ + _machine_restart = qemu_machine_restart; + _machine_halt = qemu_machine_halt; +} diff --git a/arch/mips/qemu/q-setup.c b/arch/mips/qemu/q-setup.c index 022eb1a..e100d60 100644 --- a/arch/mips/qemu/q-setup.c +++ b/arch/mips/qemu/q-setup.c @@ -2,6 +2,8 @@ #include #include #include +extern void qemu_reboot_setup(void); + #define QEMU_PORT_BASE 0xb4000000 const char *get_system_type(void) @@ -18,8 +20,10 @@ static void __init qemu_timer_setup(stru setup_irq(0, irq); } -void __init plat_setup(void) +void __init plat_mem_setup(void) { set_io_port_base(QEMU_PORT_BASE); board_timer_setup = qemu_timer_setup; + + qemu_reboot_setup(); } diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c index a9c58e0..8134220 100644 --- a/arch/mips/sgi-ip22/ip22-reset.c +++ b/arch/mips/sgi-ip22/ip22-reset.c @@ -34,7 +34,7 @@ #include #define POWERDOWN_TIMEOUT 120 /* - * Blink frequency during reboot grace period and when paniced. + * Blink frequency during reboot grace period and when panicked. */ #define POWERDOWN_FREQ (HZ / 4) #define PANIC_FREQ (HZ / 8) diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c index 7018e18..d713890 100644 --- a/arch/mips/sgi-ip22/ip22-setup.c +++ b/arch/mips/sgi-ip22/ip22-setup.c @@ -53,7 +53,7 @@ EXPORT_SYMBOL(ip22_do_break); extern void ip22_be_init(void) __init; extern void ip22_time_init(void) __init; -void __init plat_setup(void) +void __init plat_mem_setup(void) { char *ctype; char *cserial; diff --git a/arch/mips/sgi-ip27/Kconfig b/arch/mips/sgi-ip27/Kconfig index 7b0bc44..f14ef38 100644 --- a/arch/mips/sgi-ip27/Kconfig +++ b/arch/mips/sgi-ip27/Kconfig @@ -4,31 +4,29 @@ # depends on SGI_IP27 # This options adds support for userspace processes upto 16TB size. # Normally the limit is just .5TB. -config SGI_SN0_N_MODE - bool "IP27 N-Mode" +choice + prompt "Node addressing mode" depends on SGI_IP27 - help - The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be - configured in either N-Modes which allows for more nodes or M-Mode - which allows for more memory. Your system is most probably - running in M-Mode, so you should say N here. + default SGI_SN_M_MODE -config ARCH_DISCONTIGMEM_ENABLE - bool - default y if SGI_IP27 +config SGI_SN_M_MODE + bool "IP27 M-Mode" help - Say Y to upport efficient handling of discontiguous physical memory, - for architectures which are either NUMA (Non-Uniform Memory Access) - or have huge holes in the physical address space for other reasons. - See for more. + The nodes of Origin, Onyx, Fuel and Tezro systems can be configured + in either N-Modes which allows for more nodes or M-Mode which allows + for more memory. Your hardware is almost certainly running in + M-Mode, so choose M-mode here. -config NUMA - bool "NUMA Support" - depends on SGI_IP27 +config SGI_SN_N_MODE + bool "IP27 N-Mode" + depends on EXPERIMENTAL help - Say Y to compile the kernel to support NUMA (Non-Uniform Memory - Access). This option is for configuring high-end multiprocessor - server machines. If in doubt, say N. + The nodes of Origin, Onyx, Fuel and Tezro systems can be configured + in either N-Modes which allows for more nodes or M-Mode which allows + for more memory. Your hardware is almost certainly running in + M-Mode, so choose M-mode here. + +endchoice config MAPPED_KERNEL bool "Mapped kernel support" diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 8651a0e..a6b490e 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -196,7 +196,7 @@ extern void ip27_setup_console(void); extern void ip27_time_init(void); extern void ip27_reboot_setup(void); -void __init plat_setup(void) +void __init plat_mem_setup(void) { hubreg_t p, e, n_mode; nasid_t nid; @@ -228,7 +228,7 @@ void __init plat_setup(void) */ n_mode = LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_MORENODES_MASK; printk("Machine is in %c mode.\n", n_mode ? 'N' : 'M'); -#ifdef CONFIG_SGI_SN0_N_MODE +#ifdef CONFIG_SGI_SN_N_MODE if (!n_mode) panic("Kernel compiled for M mode."); #else diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 2e643d2..0b61a39 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -360,7 +360,7 @@ static struct hw_interrupt_type bridge_i static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; -static int allocate_irqno(void) +int allocate_irqno(void) { int irq; diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 36b662e..1fb860c 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -89,11 +89,13 @@ static int set_rtc_mmss(unsigned long no } #endif +static unsigned int rt_timer_irq; + void ip27_rt_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); int cpuA = cputoslice(cpu) == 0; - int irq = 9; /* XXX Assign number */ + unsigned int irq = rt_timer_irq; irq_enter(); write_seqlock(&xtime_lock); @@ -179,13 +181,68 @@ static __init unsigned long get_m48t35_t return mktime(year, month, date, hour, min, sec); } +static void startup_rt_irq(unsigned int irq) +{ +} + +static void shutdown_rt_irq(unsigned int irq) +{ +} + +static void enable_rt_irq(unsigned int irq) +{ +} + +static void disable_rt_irq(unsigned int irq) +{ +} + +static void mask_and_ack_rt(unsigned int irq) +{ +} + +static void end_rt_irq(unsigned int irq) +{ +} + +static struct hw_interrupt_type rt_irq_type = { + .typename = "SN HUB RT timer", + .startup = startup_rt_irq, + .shutdown = shutdown_rt_irq, + .enable = enable_rt_irq, + .disable = disable_rt_irq, + .ack = mask_and_ack_rt, + .end = end_rt_irq, +}; + +static struct irqaction rt_irqaction = { + .handler = ip27_rt_timer_interrupt, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "timer" +}; + +extern int allocate_irqno(void); + static void ip27_timer_setup(struct irqaction *irq) { + int irqno = allocate_irqno(); + + if (irqno < 0) + panic("Can't allocate interrupt number for timer interrupt"); + + irq_desc[irqno].status = IRQ_DISABLED; + irq_desc[irqno].action = NULL; + irq_desc[irqno].depth = 1; + irq_desc[irqno].handler = &rt_irq_type; + /* over-write the handler, we use our own way */ irq->handler = no_action; /* setup irqaction */ -// setup_irq(IP27_TIMER_IRQ, irq); /* XXX Can't do this yet. */ + irq_desc[irqno].status |= IRQ_PER_CPU; + + rt_timer_irq = irqno; } void __init ip27_time_init(void) diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index ab9d9ce..79ddb46 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c @@ -28,13 +28,13 @@ #include #define POWERDOWN_TIMEOUT 120 /* - * Blink frequency during reboot grace period and when paniced. + * Blink frequency during reboot grace period and when panicked. */ #define POWERDOWN_FREQ (HZ / 4) #define PANIC_FREQ (HZ / 8) static struct timer_list power_timer, blink_timer, debounce_timer; -static int has_paniced, shuting_down; +static int has_panicked, shuting_down; static void ip32_machine_restart(char *command) __attribute__((noreturn)); static void ip32_machine_halt(void) __attribute__((noreturn)); @@ -109,7 +109,7 @@ static void debounce(unsigned long data) } CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A); - if (has_paniced) + if (has_panicked) ip32_machine_restart(NULL); enable_irq(MACEISA_RTC_IRQ); @@ -117,7 +117,7 @@ static void debounce(unsigned long data) static inline void ip32_power_button(void) { - if (has_paniced) + if (has_panicked) return; if (shuting_down || kill_proc(1, SIGINT, 1)) { @@ -161,9 +161,9 @@ static int panic_event(struct notifier_b { unsigned long led; - if (has_paniced) + if (has_panicked) return NOTIFY_DONE; - has_paniced = 1; + has_panicked = 1; /* turn off the green LED */ led = mace->perif.ctrl.misc | MACEISA_LED_GREEN; diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c index a2dd8ae..acbdad0 100644 --- a/arch/mips/sgi-ip32/ip32-setup.c +++ b/arch/mips/sgi-ip32/ip32-setup.c @@ -87,7 +87,7 @@ void __init ip32_timer_setup(struct irqa setup_irq(IP32_R4K_TIMER_IRQ, irq); } -void __init plat_setup(void) +void __init plat_mem_setup(void) { board_be_init = ip32_be_init; diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c index e545752..efaf83e 100644 --- a/arch/mips/sibyte/bcm1480/time.c +++ b/arch/mips/sibyte/bcm1480/time.c @@ -110,17 +110,18 @@ void bcm1480_timer_interrupt(struct pt_r __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); - /* - * CPU 0 handles the global timer interrupt job - */ if (cpu == 0) { + /* + * CPU 0 handles the global timer interrupt job + */ ll_timer_interrupt(irq, regs); } - - /* - * every CPU should do profiling and process accouting - */ - ll_local_timer_interrupt(irq, regs); + else { + /* + * other CPUs should just do profiling and process accounting + */ + ll_local_timer_interrupt(irq, regs); + } } /* diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c index 0f6e54d..f853c32 100644 --- a/arch/mips/sibyte/sb1250/irq.c +++ b/arch/mips/sibyte/sb1250/irq.c @@ -435,13 +435,17 @@ static inline int dclz(unsigned long lon return lz; } +extern void sb1250_timer_interrupt(struct pt_regs *regs); +extern void sb1250_mailbox_interrupt(struct pt_regs *regs); +extern void sb1250_kgdb_interrupt(struct pt_regs *regs); + asmlinkage void plat_irq_dispatch(struct pt_regs *regs) { unsigned int pending; #ifdef CONFIG_SIBYTE_SB1250_PROF /* Set compare to count to silence count/compare timer interrupts */ - write_c0_count(read_c0_count()); + write_c0_compare(read_c0_count()); #endif /* @@ -482,7 +486,7 @@ #endif * Default...we've hit an IP[2] interrupt, which means we've * got to check the 1250 interrupt registers to figure out what * to do. Need to detect which CPU we're on, now that - ~ smp_affinity is supported. + * smp_affinity is supported. */ mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(), R_IMR_INTERRUPT_STATUS_BASE))); diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c index 4b5f74f..f9e6949 100644 --- a/arch/mips/sibyte/swarm/setup.c +++ b/arch/mips/sibyte/swarm/setup.c @@ -72,8 +72,10 @@ const char *get_system_type(void) void __init swarm_time_init(void) { +#if defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) /* Setup HPT */ sb1250_hpt_setup(); +#endif } void __init swarm_timer_setup(struct irqaction *irq) @@ -103,7 +105,7 @@ int swarm_be_handler(struct pt_regs *reg return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL); } -void __init plat_setup(void) +void __init plat_mem_setup(void) { #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) bcm1480_setup(); diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile index 9c7eaa5..a5eb0ad 100644 --- a/arch/mips/sni/Makefile +++ b/arch/mips/sni/Makefile @@ -3,5 +3,6 @@ # Makefile for the SNI specific part of # obj-y += irq.o pcimt_scache.o reset.o setup.o +obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c index 01ba6c5..a050bb6 100644 --- a/arch/mips/sni/setup.c +++ b/arch/mips/sni/setup.c @@ -21,8 +21,11 @@ #include #include #include +#ifdef CONFIG_ARC #include #include +#endif + #include #include #include @@ -72,8 +75,7 @@ static inline void sni_pcimt_detect(void static void __init sni_display_setup(void) { -#ifdef CONFIG_VT -#if defined(CONFIG_VGA_CONSOLE) +#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_ARC) struct screen_info *si = &screen_info; DISPLAY_STATUS *di; @@ -88,24 +90,54 @@ #if defined(CONFIG_VGA_CONSOLE) si->orig_video_points = 16; } #endif -#endif } static struct resource sni_io_resource = { - "PCIMT IO MEM", 0x00001000UL, 0x03bfffffUL, IORESOURCE_IO, + .start = 0x00001000UL, + .end = 0x03bfffffUL, + .name = "PCIMT IO MEM", + .flags = IORESOURCE_IO, }; static struct resource pcimt_io_resources[] = { - { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, - { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, - { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY }, - { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, - { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, - { "PCI config data", 0xcfc, 0xcff, IORESOURCE_BUSY } + { + .start = 0x00, + .end = 0x1f, + .name = "dma1", + .flags = IORESOURCE_BUSY + }, { + .start = 0x40, + .end = 0x5f, + .name = "timer", + .flags = IORESOURCE_BUSY + }, { + .start = 0x60, + .end = 0x6f, + .name = "keyboard", + .flags = IORESOURCE_BUSY + }, { + .start = 0x80, + .end = 0x8f, + .name = "dma page reg", + .flags = IORESOURCE_BUSY + }, { + .start = 0xc0, + .end = 0xdf, + .name = "dma2", + .flags = IORESOURCE_BUSY + }, { + .start = 0xcfc, + .end = 0xcff, + .name = "PCI config data", + .flags = IORESOURCE_BUSY + } }; static struct resource sni_mem_resource = { - "PCIMT PCI MEM", 0x10000000UL, 0xffffffffUL, IORESOURCE_MEM + .start = 0x10000000UL, + .end = 0xffffffffUL, + .name = "PCIMT PCI MEM", + .flags = IORESOURCE_MEM }; /* @@ -122,19 +154,72 @@ static struct resource sni_mem_resource * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory */ static struct resource pcimt_mem_resources[] = { - { "Video RAM area", 0x100a0000, 0x100bffff, IORESOURCE_BUSY }, - { "ISA Reserved", 0x100c0000, 0x100fffff, IORESOURCE_BUSY }, - { "PCI IO", 0x14000000, 0x17bfffff, IORESOURCE_BUSY }, - { "Cache Replacement Area", 0x17c00000, 0x17ffffff, IORESOURCE_BUSY}, - { "PCI INT Acknowledge", 0x1a000000, 0x1a000003, IORESOURCE_BUSY }, - { "Boot PROM", 0x1fc00000, 0x1fc7ffff, IORESOURCE_BUSY}, - { "Diag PROM", 0x1fc80000, 0x1fcfffff, IORESOURCE_BUSY}, - { "X-Bus", 0x1fd00000, 0x1fdfffff, IORESOURCE_BUSY}, - { "BIOS map", 0x1fe00000, 0x1fefffff, IORESOURCE_BUSY}, - { "NVRAM / EEPROM", 0x1ff00000, 0x1ff7ffff, IORESOURCE_BUSY}, - { "ASIC PCI", 0x1fff0000, 0x1fffefff, IORESOURCE_BUSY}, - { "MP Agent", 0x1ffff000, 0x1fffffff, IORESOURCE_BUSY}, - { "Main Memory", 0x20000000, 0x9fffffff, IORESOURCE_BUSY} + { + .start = 0x100a0000, + .end = 0x100bffff, + .name = "Video RAM area", + .flags = IORESOURCE_BUSY + }, { + .start = 0x100c0000, + .end = 0x100fffff, + .name = "ISA Reserved", + .flags = IORESOURCE_BUSY + }, { + .start = 0x14000000, + .end = 0x17bfffff, + .name = "PCI IO", + .flags = IORESOURCE_BUSY + }, { + .start = 0x17c00000, + .end = 0x17ffffff, + .name = "Cache Replacement Area", + .flags = IORESOURCE_BUSY + }, { + .start = 0x1a000000, + .end = 0x1a000003, + .name = "PCI INT Acknowledge", + .flags = IORESOURCE_BUSY + }, { + .start = 0x1fc00000, + .end = 0x1fc7ffff, + .name = "Boot PROM", + .flags = IORESOURCE_BUSY + }, { + .start = 0x1fc80000, + .end = 0x1fcfffff, + .name = "Diag PROM", + .flags = IORESOURCE_BUSY + }, { + .start = 0x1fd00000, + .end = 0x1fdfffff, + .name = "X-Bus", + .flags = IORESOURCE_BUSY + }, { + .start = 0x1fe00000, + .end = 0x1fefffff, + .name = "BIOS map", + .flags = IORESOURCE_BUSY + }, { + .start = 0x1ff00000, + .end = 0x1ff7ffff, + .name = "NVRAM / EEPROM", + .flags = IORESOURCE_BUSY + }, { + .start = 0x1fff0000, + .end = 0x1fffefff, + .name = "ASIC PCI", + .flags = IORESOURCE_BUSY + }, { + .start = 0x1ffff000, + .end = 0x1fffffff, + .name = "MP Agent", + .flags = IORESOURCE_BUSY + }, { + .start = 0x20000000, + .end = 0x9fffffff, + .name = "Main Memory", + .flags = IORESOURCE_BUSY + } }; static void __init sni_resource_init(void) @@ -168,7 +253,7 @@ static inline void sni_pcimt_time_init(v rtc_mips_set_time = mc146818_set_rtc_mmss; } -void __init plat_setup(void) +void __init plat_mem_setup(void) { sni_pcimt_detect(); sni_pcimt_sc_init(); diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c new file mode 100644 index 0000000..d1d0f1f --- /dev/null +++ b/arch/mips/sni/sniprom.c @@ -0,0 +1,158 @@ +/* + * Big Endian PROM code for SNI RM machines + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2005-2006 Florian Lohoff (flo@rfc822.org) + * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + */ + +#include +#include +#include + +#include +#include +#include +#include + +/* special SNI prom calls */ +/* + * This does not exist in all proms - SINIX compares + * the prom env variable "version" against "2.0008" + * or greater. If lesser it tries to probe interesting + * registers + */ +#define PROM_GET_MEMCONF 58 + +#define PROM_VEC (u64 *)CKSEG1ADDR(0x1fc00000) +#define PROM_ENTRY(x) (PROM_VEC + (x)) + + +#undef DEBUG +#ifdef DEBUG +#define DBG_PRINTF(x...) prom_printf(x) +#else +#define DBG_PRINTF(x...) +#endif + +static int *(*__prom_putchar)(int) = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR); +static char *(*__prom_getenv)(char *) = (char *(*)(char *))PROM_ENTRY(PROM_GETENV); +static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF); + +char *prom_getenv (char *s) +{ + return __prom_getenv(s); +} + +void prom_printf(char *fmt, ...) +{ + va_list args; + char ppbuf[1024]; + char *bptr; + + va_start(args, fmt); + vsprintf(ppbuf, fmt, args); + + bptr = ppbuf; + + while (*bptr != 0) { + if (*bptr == '\n') + __prom_putchar('\r'); + + __prom_putchar(*bptr++); + } + va_end(args); +} + +unsigned long prom_free_prom_memory(void) +{ + return 0; +} + +/* + * /proc/cpuinfo system type + * + */ +static const char *systype = "Unknown"; +const char *get_system_type(void) +{ + return systype; +} + +#define SNI_IDPROM_BASE 0xbff00000 +#define SNI_IDPROM_MEMSIZE (SNI_IDPROM_BASE+0x28) /* Memsize in 16MB quantities */ +#define SNI_IDPROM_BRDTYPE (SNI_IDPROM_BASE+0x29) /* Board Type */ +#define SNI_IDPROM_CPUTYPE (SNI_IDPROM_BASE+0x30) /* CPU Type */ + +#define SNI_IDPROM_SIZE 0x1000 + +#ifdef DEBUG +static void sni_idprom_dump(void) +{ + int i; + + prom_printf("SNI IDProm dump (first 128byte):\n"); + for(i=0;i<128;i++) { + if (i%16 == 0) + prom_printf("%04x ", i); + + prom_printf("%02x ", *(unsigned char *) (SNI_IDPROM_BASE+i)); + + if (i%16 == 15) + prom_printf("\n"); + } +} +#endif + +static void sni_mem_init(void ) +{ + int i, memsize; + struct membank { + u32 size; + u32 base; + u32 size2; + u32 pad1; + u32 pad2; + } memconf[8]; + + /* MemSIZE from prom in 16MByte chunks */ + memsize=*((unsigned char *) SNI_IDPROM_MEMSIZE) * 16; + + DBG_PRINTF("IDProm memsize: %lu MByte\n", memsize); + + /* get memory bank layout from prom */ + __prom_get_memconf(&memconf); + + DBG_PRINTF("prom_get_mem_conf memory configuration:\n"); + for(i=0;i<8 && memconf[i].size;i++) { + prom_printf("Bank%d: %08x @ %08x\n", i, + memconf[i].size, memconf[i].base); + add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM); + } +} + +void __init prom_init(void) +{ + int argc = fw_arg0; + char **argv = (void *)fw_arg1; + unsigned int sni_brd_type = *(unsigned char *) SNI_IDPROM_BRDTYPE; + int i; + + DBG_PRINTF("Found SNI brdtype %02x\n", sni_brd_type); + +#ifdef DEBUG + sni_idprom_dump(); +#endif + sni_mem_init(); + + /* copy prom cmdline parameters to kernel cmdline */ + for (i = 1; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } +} + diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c index 77c3b66..81a5acf 100644 --- a/arch/mips/tx4927/common/tx4927_setup.c +++ b/arch/mips/tx4927/common/tx4927_setup.c @@ -64,7 +64,7 @@ static void tx4927_write_buffer_flush(vo } -void __init plat_setup(void) +void __init plat_mem_setup(void) { board_time_init = tx4927_time_init; board_timer_setup = tx4927_timer_setup; diff --git a/arch/mips/tx4938/common/setup.c b/arch/mips/tx4938/common/setup.c index fc99295..ef59a5c 100644 --- a/arch/mips/tx4938/common/setup.c +++ b/arch/mips/tx4938/common/setup.c @@ -61,7 +61,7 @@ tx4938_write_buffer_flush(void) } void __init -plat_setup(void) +plat_mem_setup(void) { board_time_init = tx4938_time_init; board_timer_setup = tx4938_timer_setup; diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c index 9166cd4..96e833c 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c @@ -664,7 +664,10 @@ static struct resource rbtx4938_fpga_res static char pcode_str[8]; static struct resource tx4938_reg_resource = { - pcode_str, TX4938_REG_BASE, TX4938_REG_BASE+TX4938_REG_SIZE, IORESOURCE_MEM + .start = TX4938_REG_BASE, + .end = TX4938_REG_BASE + TX4938_REG_SIZE, + .name = pcode_str, + .flags = IORESOURCE_MEM }; void __init tx4938_board_setup(void) diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig index 055a2cd..6046ef2 100644 --- a/arch/mips/vr41xx/Kconfig +++ b/arch/mips/vr41xx/Kconfig @@ -4,7 +4,6 @@ config CASIO_E55 select DMA_NONCOHERENT select IRQ_CPU select ISA - select SYS_HAS_CPU_VR41XX select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN @@ -14,18 +13,15 @@ config IBM_WORKPAD select DMA_NONCOHERENT select IRQ_CPU select ISA - select SYS_HAS_CPU_VR41XX select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN config NEC_CMBVR4133 bool "Support for NEC CMB-VR4133" depends on MACH_VR41XX - select CPU_VR41XX select DMA_NONCOHERENT select IRQ_CPU select HW_HAS_PCI - select SYS_HAS_CPU_VR41XX select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN @@ -41,7 +37,6 @@ config TANBAC_TB022X select DMA_NONCOHERENT select HW_HAS_PCI select IRQ_CPU - select SYS_HAS_CPU_VR41XX select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN help @@ -74,7 +69,6 @@ config VICTOR_MPC30X select DMA_NONCOHERENT select HW_HAS_PCI select IRQ_CPU - select SYS_HAS_CPU_VR41XX select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN @@ -84,7 +78,6 @@ config ZAO_CAPCELLA select DMA_NONCOHERENT select HW_HAS_PCI select IRQ_CPU - select SYS_HAS_CPU_VR41XX select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c index 707bd09..915bfa5 100644 --- a/arch/mips/vr41xx/common/init.c +++ b/arch/mips/vr41xx/common/init.c @@ -58,7 +58,7 @@ static void __init timer_init(void) board_timer_setup = setup_timer_irq; } -void __init plat_setup(void) +void __init plat_mem_setup(void) { vr41xx_calculate_clock_frequency(); diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c index 05273cc..cb69727 100644 --- a/arch/parisc/hpux/sys_hpux.c +++ b/arch/parisc/hpux/sys_hpux.c @@ -145,7 +145,7 @@ static int hpux_ustat(dev_t dev, struct s = user_get_super(dev); if (s == NULL) goto out; - err = vfs_statfs(s, &sbuf); + err = vfs_statfs(s->s_root, &sbuf); drop_super(s); if (err) goto out; @@ -186,12 +186,12 @@ struct hpux_statfs { int16_t f_pad; }; -static int vfs_statfs_hpux(struct super_block *sb, struct hpux_statfs *buf) +static int vfs_statfs_hpux(struct dentry *dentry, struct hpux_statfs *buf) { struct kstatfs st; int retval; - retval = vfs_statfs(sb, &st); + retval = vfs_statfs(dentry, &st); if (retval) return retval; @@ -219,7 +219,7 @@ asmlinkage long hpux_statfs(const char _ error = user_path_walk(path, &nd); if (!error) { struct hpux_statfs tmp; - error = vfs_statfs_hpux(nd.dentry->d_inode->i_sb, &tmp); + error = vfs_statfs_hpux(nd.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; path_release(&nd); @@ -237,7 +237,7 @@ asmlinkage long hpux_fstatfs(unsigned in file = fget(fd); if (!file) goto out; - error = vfs_statfs_hpux(file->f_dentry->d_inode->i_sb, &tmp); + error = vfs_statfs_hpux(file->f_dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; fput(file); diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 05767e8..cc38edf 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -248,7 +248,7 @@ get_sigframe(struct k_sigaction *ka, uns DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n", (unsigned long)ka, sp, frame_size); - if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) sp = current->sas_ss_sp; /* Stacks grow up! */ DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp); diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6729c98..e922a88 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -45,6 +45,10 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_FIND_NEXT_BIT + bool + default y + config PPC bool default y @@ -137,6 +141,15 @@ config PPC_85xx select FSL_SOC select 85xx +config PPC_86xx + bool "Freescale 86xx" + select 6xx + select FSL_SOC + select PPC_FPU + select ALTIVEC + help + The Freescale E600 SoCs have 74xx cores. + config 40x bool "AMCC 40x" @@ -336,7 +349,7 @@ endchoice config PPC_PSERIES depends on PPC_MULTIPLATFORM && PPC64 - bool " IBM pSeries & new (POWER5-based) iSeries" + bool "IBM pSeries & new (POWER5-based) iSeries" select PPC_I8259 select PPC_RTAS select RTAS_ERROR_LOGGING @@ -344,7 +357,7 @@ config PPC_PSERIES default y config PPC_CHRP - bool " Common Hardware Reference Platform (CHRP) based machines" + bool "Common Hardware Reference Platform (CHRP) based machines" depends on PPC_MULTIPLATFORM && PPC32 select PPC_I8259 select PPC_INDIRECT_PCI @@ -354,7 +367,7 @@ config PPC_CHRP default y config PPC_PMAC - bool " Apple PowerMac based machines" + bool "Apple PowerMac based machines" depends on PPC_MULTIPLATFORM select PPC_INDIRECT_PCI if PPC32 select PPC_MPC106 if PPC32 @@ -370,7 +383,7 @@ config PPC_PMAC64 default y config PPC_PREP - bool " PowerPC Reference Platform (PReP) based machines" + bool "PowerPC Reference Platform (PReP) based machines" depends on PPC_MULTIPLATFORM && PPC32 && BROKEN select PPC_I8259 select PPC_INDIRECT_PCI @@ -379,7 +392,7 @@ config PPC_PREP config PPC_MAPLE depends on PPC_MULTIPLATFORM && PPC64 - bool " Maple 970FX Evaluation Board" + bool "Maple 970FX Evaluation Board" select U3_DART select MPIC_BROKEN_U3 select GENERIC_TBSYNC @@ -391,8 +404,18 @@ config PPC_MAPLE For more informations, refer to config PPC_CELL - bool " Cell Broadband Processor Architecture" + bool + default n + +config PPC_CELL_NATIVE + bool + select PPC_CELL + default n + +config PPC_IBM_CELL_BLADE + bool " IBM Cell Blade" depends on PPC_MULTIPLATFORM && PPC64 + select PPC_CELL_NATIVE select PPC_RTAS select MMIO_NVRAM select PPC_UDBG_16550 @@ -439,11 +462,6 @@ config MPIC_BROKEN_U3 depends on PPC_MAPLE default y -config CELL_IIC - depends on PPC_CELL - bool - default y - config IBMVIO depends on PPC_PSERIES || PPC_ISERIES bool @@ -545,6 +563,7 @@ source arch/powerpc/platforms/embedded6x source arch/powerpc/platforms/4xx/Kconfig source arch/powerpc/platforms/83xx/Kconfig source arch/powerpc/platforms/85xx/Kconfig +source arch/powerpc/platforms/86xx/Kconfig source arch/powerpc/platforms/8xx/Kconfig source arch/powerpc/platforms/cell/Kconfig @@ -699,7 +718,6 @@ config PPC_64K_PAGES config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" depends on PPC64 && SMP - default off help SMT scheduler support improves the CPU scheduler's decision making when dealing with POWER5 cpus at a cost of slightly increased @@ -776,6 +794,7 @@ config GENERIC_ISA_DMA config PPC_I8259 bool + default y if MPC8641_HPCN default n config PPC_INDIRECT_PCI @@ -798,8 +817,8 @@ config MCA bool config PCI - bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) - default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx + bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) + default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx && !PPC_86xx default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS default PCI_QSPAN if !4xx && !CPM2 && 8xx help @@ -827,12 +846,12 @@ config PCI_8260 default y config 8260_PCI9 - bool " Enable workaround for MPC826x erratum PCI 9" + bool "Enable workaround for MPC826x erratum PCI 9" depends on PCI_8260 && !ADS8272 default y choice - prompt " IDMA channel for PCI 9 workaround" + prompt "IDMA channel for PCI 9 workaround" depends on 8260_PCI9 config 8260_PCI9_IDMA1 @@ -849,6 +868,8 @@ config 8260_PCI9_IDMA4 endchoice +source "drivers/pci/pcie/Kconfig" + source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 8d48e9e..c69006a 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -110,13 +110,16 @@ config SERIAL_TEXT_DEBUG depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \ PPC_GEN550 || PPC_MPC52xx +config PPC_EARLY_DEBUG + bool "Early debugging (dangerous)" + choice - prompt "Early debugging (dangerous)" - bool - optional + prompt "Early debugging console" + depends on PPC_EARLY_DEBUG help - Enable early debugging. Careful, if you enable debugging for the - wrong type of machine your kernel _will not boot_. + Use the selected console for early debugging. Careful, if you + enable debugging for the wrong type of machine your kernel + _will not boot_. config PPC_EARLY_DEBUG_LPAR bool "LPAR HV Console" diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index ed5b26a..01667d1 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -108,7 +108,6 @@ ifeq ($(CONFIG_6xx),y) CFLAGS += -mcpu=powerpc endif -cpu-as-$(CONFIG_PPC64BRIDGE) += -Wa,-mppc64bridge cpu-as-$(CONFIG_4xx) += -Wa,-m405 cpu-as-$(CONFIG_6xx) += -Wa,-maltivec cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 840ae59..d961bfe 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -29,8 +29,8 @@ OBJCOPYFLAGS := contents,alloc,load,r OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 OBJCOPY_MIB_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment -zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c -zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h +zlib := inffast.c inflate.c inftrees.c +zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h zliblinuxheader := zlib.h zconf.h zutil.h $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 816446f..b66634c 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c @@ -33,6 +33,14 @@ extern char _vmlinux_end[]; extern char _initrd_start[]; extern char _initrd_end[]; +/* A buffer that may be edited by tools operating on a zImage binary so as to + * edit the command line passed to vmlinux (by setting /chosen/bootargs). + * The buffer is put in it's own section so that tools may locate it easier. + */ +static char builtin_cmdline[512] + __attribute__((section("__builtin_cmdline"))); + + struct addr_range { unsigned long addr; unsigned long size; @@ -204,6 +212,23 @@ static int is_elf32(void *hdr) return 1; } +void export_cmdline(void* chosen_handle) +{ + int len; + char cmdline[2] = { 0, 0 }; + + if (builtin_cmdline[0] == 0) + return; + + len = getprop(chosen_handle, "bootargs", cmdline, sizeof(cmdline)); + if (len > 0 && cmdline[0] != 0) + return; + + setprop(chosen_handle, "bootargs", builtin_cmdline, + strlen(builtin_cmdline) + 1); +} + + void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) { int len; @@ -289,6 +314,8 @@ void start(unsigned long a1, unsigned lo memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size); } + export_cmdline(chosen_handle); + /* Skip over the ELF header */ #ifdef DEBUG printf("... skipping 0x%lx bytes of ELF header\n\r", diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h index 3e2ddd4..a57b184 100644 --- a/arch/powerpc/boot/prom.h +++ b/arch/powerpc/boot/prom.h @@ -31,4 +31,11 @@ static inline int getprop(void *phandle, return call_prom("getprop", 4, 1, phandle, name, buf, buflen); } + +static inline int setprop(void *phandle, const char *name, + void *buf, int buflen) +{ + return call_prom("setprop", 4, 1, phandle, name, buf, buflen); +} + #endif /* _PPC_BOOT_PROM_H_ */ diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index dbe421d..b8b8d46 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16 -# Thu Mar 23 20:48:09 2006 +# Linux kernel version: 2.6.17 +# Mon Jun 19 17:23:03 2006 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -11,6 +11,7 @@ CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y @@ -55,7 +56,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -# CONFIG_CPUSETS is not set +CONFIG_CPUSETS=y # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -116,13 +117,15 @@ # CONFIG_PPC_PSERIES is not set # CONFIG_PPC_PMAC is not set # CONFIG_PPC_MAPLE is not set CONFIG_PPC_CELL=y +CONFIG_PPC_CELL_NATIVE=y +CONFIG_PPC_IBM_CELL_BLADE=y +CONFIG_PPC_SYSTEMSIM=y # CONFIG_U3_DART is not set CONFIG_PPC_RTAS=y # CONFIG_RTAS_ERROR_LOGGING is not set CONFIG_RTAS_PROC=y CONFIG_RTAS_FLASH=y CONFIG_MMIO_NVRAM=y -CONFIG_CELL_IIC=y # CONFIG_PPC_MPC106 is not set # CONFIG_PPC_970_NAP is not set # CONFIG_CPU_FREQ is not set @@ -132,7 +135,9 @@ # # Cell Broadband Engine options # CONFIG_SPU_FS=m +CONFIG_SPU_BASE=y CONFIG_SPUFS_MMAP=y +CONFIG_CBE_RAS=y # # Kernel options @@ -152,20 +157,24 @@ # CONFIG_IOMMU_VMERGE is not set CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_IRQ_ALL_CPUS=y -# CONFIG_NUMA is not set +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=4 CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_FLATMEM_MANUAL is not set # CONFIG_DISCONTIGMEM_MANUAL is not set CONFIG_SPARSEMEM_MANUAL=y CONFIG_SPARSEMEM=y +CONFIG_NEED_MULTIPLE_NODES=y CONFIG_HAVE_MEMORY_PRESENT=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPARSEMEM_EXTREME=y -# CONFIG_MEMORY_HOTPLUG is not set +CONFIG_MEMORY_HOTPLUG=y CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y +CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_ARCH_MEMORY_PROBE=y # CONFIG_PPC_64K_PAGES is not set CONFIG_SCHED_SMT=y CONFIG_PROC_DEVICETREE=y @@ -182,6 +191,7 @@ # CONFIG_PPC_I8259 is not set # CONFIG_PPC_INDIRECT_PCI is not set CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +CONFIG_PCIEPORTBUS=y # CONFIG_PCI_DEBUG is not set # @@ -476,7 +486,7 @@ # Network device support # CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set -# CONFIG_BONDING is not set +CONFIG_BONDING=y # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set @@ -624,6 +634,7 @@ # CONFIG_SYNCLINK_GT is not set # CONFIG_N_HDLC is not set # CONFIG_SPECIALIX is not set # CONFIG_SX is not set +# CONFIG_RIO is not set # CONFIG_STALDRV is not set # @@ -766,6 +777,7 @@ # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -1054,11 +1066,7 @@ CONFIG_DEBUGGER=y # CONFIG_XMON is not set CONFIG_IRQSTACKS=y # CONFIG_BOOTX_TEXT is not set -# CONFIG_PPC_EARLY_DEBUG_LPAR is not set -# CONFIG_PPC_EARLY_DEBUG_G5 is not set -# CONFIG_PPC_EARLY_DEBUG_RTAS is not set -# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set -# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set +# CONFIG_PPC_EARLY_DEBUG is not set # # Security options diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig new file mode 100644 index 0000000..9bb022a --- /dev/null +++ b/arch/powerpc/configs/mpc85xx_cds_defconfig @@ -0,0 +1,846 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.16 +# Sun Apr 2 11:23:42 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +CONFIG_PPC_85xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_85xx=y +CONFIG_E500=y +CONFIG_BOOKE=y +CONFIG_FSL_BOOKE=y +# CONFIG_PHYS_64BIT is not set +CONFIG_SPE=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_MPIC=y +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +# CONFIG_MPC8540_ADS is not set +CONFIG_MPC85xx_CDS=y +CONFIG_MPC8540=y +CONFIG_PPC_INDIRECT_PCI_BE=y + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_MATH_EMULATION=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_PPC_I8259=y +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_IDEDISK is not set +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +# CONFIG_IDEDMA_PCI_AUTO is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +CONFIG_GFAR_NAPI=y + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUGGER is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig new file mode 100644 index 0000000..d7a30f9 --- /dev/null +++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig @@ -0,0 +1,921 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc3 +# Fri Jun 16 10:47:09 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +CONFIG_GENERIC_TBSYNC=y +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set +CONFIG_PPC_86xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +CONFIG_SMP=y +CONFIG_NR_CPUS=2 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +# CONFIG_SLAB is not set +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_SLOB=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +CONFIG_MPIC=y +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_PPC_INDIRECT_PCI_BE=y + +# +# Platform Support +# +CONFIG_MPC8641_HPCN=y +CONFIG_MPC8641=y + +# +# Kernel options +# +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_IRQ_ALL_CPUS is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +CONFIG_PPC_I8259=y +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +CONFIG_VITESSE_PHY=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +# CONFIG_GFAR_NAPI is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUGGER is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig index 57a0279..addc793 100644 --- a/arch/powerpc/configs/pmac32_defconfig +++ b/arch/powerpc/configs/pmac32_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-rc6 -# Wed Mar 15 16:21:32 2006 +# Linux kernel version: 2.6.17-rc5 +# Mon May 29 14:47:49 2006 # # CONFIG_PPC64 is not set CONFIG_PPC32=y @@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y @@ -27,11 +28,11 @@ CONFIG_CLASSIC32=y # CONFIG_PPC_52xx is not set # CONFIG_PPC_82xx is not set # CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set # CONFIG_40x is not set # CONFIG_44x is not set # CONFIG_8xx is not set # CONFIG_E200 is not set -# CONFIG_E500 is not set CONFIG_6xx=y CONFIG_PPC_FPU=y CONFIG_ALTIVEC=y @@ -59,6 +60,7 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_EMBEDDED is not set @@ -73,10 +75,6 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 @@ -88,7 +86,6 @@ # CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y @@ -97,6 +94,8 @@ # # Block layer # CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_LSF=y # # IO Schedulers @@ -124,6 +123,7 @@ CONFIG_MPIC=y # CONFIG_PPC_RTAS is not set # CONFIG_MMIO_NVRAM is not set CONFIG_PPC_MPC106=y +# CONFIG_PPC_970_NAP is not set CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_TABLE=y # CONFIG_CPU_FREQ_DEBUG is not set @@ -182,7 +182,6 @@ # CONFIG_PPC_I8259 is not set CONFIG_PPC_INDIRECT_PCI=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_PCI_LEGACY_PROC=y # CONFIG_PCI_DEBUG is not set # @@ -239,7 +238,9 @@ # CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y -# CONFIG_NET_KEY is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=y CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -250,9 +251,10 @@ # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set +CONFIG_INET_AH=y +CONFIG_INET_ESP=y # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y @@ -264,6 +266,8 @@ # IP: Virtual Server Configuration # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -278,12 +282,15 @@ CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m CONFIG_NETFILTER_XT_TARGET_NOTRACK=m CONFIG_NETFILTER_XT_MATCH_COMMENT=m CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m CONFIG_NETFILTER_XT_MATCH_HELPER=m CONFIG_NETFILTER_XT_MATCH_LENGTH=m CONFIG_NETFILTER_XT_MATCH_LIMIT=m CONFIG_NETFILTER_XT_MATCH_MAC=m CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m CONFIG_NETFILTER_XT_MATCH_REALM=m CONFIG_NETFILTER_XT_MATCH_SCTP=m @@ -305,15 +312,15 @@ CONFIG_IP_NF_NETBIOS_NS=m CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_AMANDA=m CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m # CONFIG_IP_NF_QUEUE is not set CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MULTIPORT=m CONFIG_IP_NF_MATCH_TOS=m CONFIG_IP_NF_MATCH_RECENT=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_TTL=m CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_ADDRTYPE=m @@ -335,6 +342,7 @@ CONFIG_IP_NF_NAT_FTP=m CONFIG_IP_NF_NAT_TFTP=m CONFIG_IP_NF_NAT_AMANDA=m CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_TOS=m CONFIG_IP_NF_TARGET_ECN=m @@ -350,10 +358,12 @@ # DCCP Configuration (EXPERIMENTAL) # CONFIG_IP_DCCP=m CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y # # DCCP CCIDs Configuration (EXPERIMENTAL) # +CONFIG_IP_DCCP_CCID2=m CONFIG_IP_DCCP_CCID3=m CONFIG_IP_DCCP_TFRC_LIB=m @@ -361,7 +371,6 @@ # # DCCP Kernel Hacking # # CONFIG_IP_DCCP_DEBUG is not set -# CONFIG_IP_DCCP_UNLOAD_HACK is not set # # SCTP Configuration (EXPERIMENTAL) @@ -477,6 +486,8 @@ # CONFIG_IEEE80211_DEBUG is not set CONFIG_IEEE80211_CRYPT_WEP=m CONFIG_IEEE80211_CRYPT_CCMP=m CONFIG_IEEE80211_CRYPT_TKIP=m +# CONFIG_IEEE80211_SOFTMAC is not set +CONFIG_WIRELESS_EXT=y # # Device Drivers @@ -662,9 +673,8 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set @@ -694,16 +704,17 @@ CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m -# CONFIG_MD_RAID10 is not set +CONFIG_MD_RAID10=m CONFIG_MD_RAID5=m +CONFIG_MD_RAID5_RESHAPE=y CONFIG_MD_RAID6=m CONFIG_MD_MULTIPATH=m CONFIG_MD_FAULTY=m CONFIG_BLK_DEV_DM=m CONFIG_DM_CRYPT=m -# CONFIG_DM_SNAPSHOT is not set -# CONFIG_DM_MIRROR is not set -# CONFIG_DM_ZERO is not set +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m # CONFIG_DM_MULTIPATH is not set # @@ -740,7 +751,7 @@ # CONFIG_IEEE1394_VIDEO1394=m CONFIG_IEEE1394_SBP2=m # CONFIG_IEEE1394_SBP2_PHYS_DMA is not set -CONFIG_IEEE1394_ETH1394=m +# CONFIG_IEEE1394_ETH1394 is not set CONFIG_IEEE1394_DV1394=m CONFIG_IEEE1394_RAWIO=m @@ -769,10 +780,10 @@ # # Network device support # CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set +CONFIG_DUMMY=m # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set +CONFIG_TUN=m # # ARCnet devices @@ -857,6 +868,7 @@ # # Wireless LAN (non-hamradio) # CONFIG_NET_RADIO=y +# CONFIG_NET_WIRELESS_RTNETLINK is not set # # Obsolete Wireless cards support (pre-802.11) @@ -992,6 +1004,7 @@ # # Serial drivers # CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_PCI=m # CONFIG_SERIAL_8250_CS is not set CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 @@ -1027,6 +1040,7 @@ # # Ftape, the floppy tape device driver # CONFIG_AGP=m +# CONFIG_AGP_VIA is not set CONFIG_AGP_UNINORTH=m CONFIG_DRM=m # CONFIG_DRM_TDFX is not set @@ -1081,7 +1095,6 @@ # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set @@ -1100,10 +1113,8 @@ # CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_M41T00 is not set # CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -1131,18 +1142,16 @@ # Misc devices # # -# Multimedia Capabilities Port drivers -# - -# # Multimedia devices # # CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support @@ -1152,6 +1161,7 @@ CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y CONFIG_FB_MACMODES=y +CONFIG_FB_FIRMWARE_EDID=y CONFIG_FB_MODE_HELPERS=y CONFIG_FB_TILEBLITTING=y # CONFIG_FB_CIRRUS is not set @@ -1175,7 +1185,6 @@ CONFIG_FB_MATROX_MYSTIQUE=y # CONFIG_FB_MATROX_G is not set # CONFIG_FB_MATROX_I2C is not set # CONFIG_FB_MATROX_MULTIHEAD is not set -# CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y CONFIG_FB_RADEON_I2C=y # CONFIG_FB_RADEON_DEBUG is not set @@ -1234,9 +1243,11 @@ CONFIG_SND_SEQ_DUMMY=m CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=m CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -1253,6 +1264,7 @@ # # PCI devices # # CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set # CONFIG_SND_ALS4000 is not set # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ATIIXP is not set @@ -1285,6 +1297,7 @@ # CONFIG_SND_MAESTRO3 is not set # CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set # CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set @@ -1310,6 +1323,8 @@ # CONFIG_SND_USB_USX2Y is not set # # PCMCIA devices # +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set # # Open Sound System @@ -1321,6 +1336,7 @@ # USB support # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -1336,7 +1352,9 @@ # CONFIG_USB_OTG is not set # # USB Host Controller Drivers # -# CONFIG_USB_EHCI_HCD is not set +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1347,7 +1365,6 @@ # CONFIG_USB_SL811_HCD is not set # # USB Device Class drivers # -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set CONFIG_USB_ACM=m CONFIG_USB_PRINTER=m @@ -1358,7 +1375,17 @@ # # # may also be needed; see USB_STORAGE Help for more information # -# CONFIG_USB_STORAGE is not set +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set # CONFIG_USB_LIBUSUAL is not set # @@ -1374,9 +1401,7 @@ # CONFIG_USB_WACOM is not set # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -1391,15 +1416,6 @@ # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set # -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set - -# -# Video4Linux support is needed for USB Multimedia device support -# - -# # USB Network Adapters # # CONFIG_USB_CATC is not set @@ -1429,6 +1445,7 @@ CONFIG_USB_SERIAL=m # CONFIG_USB_SERIAL_GENERIC is not set # CONFIG_USB_SERIAL_AIRPRIME is not set # CONFIG_USB_SERIAL_ANYDATA is not set +# CONFIG_USB_SERIAL_ARK3116 is not set # CONFIG_USB_SERIAL_BELKIN is not set # CONFIG_USB_SERIAL_WHITEHEAT is not set # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set @@ -1436,6 +1453,7 @@ # CONFIG_USB_SERIAL_CP2101 is not set # CONFIG_USB_SERIAL_CYPRESS_M8 is not set # CONFIG_USB_SERIAL_EMPEG is not set # CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_FUNSOFT is not set CONFIG_USB_SERIAL_VISOR=m CONFIG_USB_SERIAL_IPAQ=m # CONFIG_USB_SERIAL_IR is not set @@ -1460,6 +1478,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y # CONFIG_USB_SERIAL_KLSI is not set # CONFIG_USB_SERIAL_KOBIL_SCT is not set # CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_NAVMAN is not set # CONFIG_USB_SERIAL_PL2303 is not set # CONFIG_USB_SERIAL_HP4X is not set # CONFIG_USB_SERIAL_SAFE is not set @@ -1484,6 +1503,7 @@ # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set @@ -1502,6 +1522,19 @@ # # CONFIG_MMC is not set # +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# # InfiniBand support # # CONFIG_INFINIBAND is not set @@ -1511,6 +1544,11 @@ # EDAC - error detection and reporting ( # # +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# # File systems # CONFIG_EXT2_FS=y @@ -1518,14 +1556,14 @@ # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set +CONFIG_EXT3_FS_POSIX_ACL=y # CONFIG_EXT3_FS_SECURITY is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set +CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set @@ -1534,7 +1572,7 @@ CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set +CONFIG_AUTOFS4_FS=m CONFIG_FUSE_FS=m # @@ -1566,7 +1604,6 @@ CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -CONFIG_RELAYFS_FS=m # CONFIG_CONFIGFS_FS is not set # @@ -1590,17 +1627,24 @@ # # Network File Systems # CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y # CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y CONFIG_LOCKD=y -CONFIG_EXPORTFS=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set @@ -1681,7 +1725,7 @@ # CONFIG_CRC_CCITT=y CONFIG_CRC16=y CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set +CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y CONFIG_TEXTSEARCH=y @@ -1735,29 +1779,29 @@ # # Cryptographic options # CONFIG_CRYPTO=y -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_WP512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_DEFLATE is not set +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m CONFIG_CRYPTO_MICHAEL_MIC=m -# CONFIG_CRYPTO_CRC32C is not set +CONFIG_CRYPTO_CRC32C=m # CONFIG_CRYPTO_TEST is not set # diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 58e68ce..31708ad 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-rc1 -# Wed Apr 19 11:48:00 2006 +# Linux kernel version: 2.6.17-rc4 +# Sun May 28 07:26:56 2006 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -11,6 +11,7 @@ CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y @@ -126,8 +127,9 @@ CONFIG_RTAS_PROC=y CONFIG_RTAS_FLASH=m # CONFIG_MMIO_NVRAM is not set CONFIG_IBMVIO=y -# CONFIG_IBMEBUS is not set +CONFIG_IBMEBUS=y # CONFIG_PPC_MPC106 is not set +# CONFIG_PPC_970_NAP is not set # CONFIG_CPU_FREQ is not set # CONFIG_WANT_EARLY_SERIAL is not set @@ -143,7 +145,7 @@ # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set # CONFIG_PREEMPT_BKL is not set CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set +CONFIG_BINFMT_MISC=m CONFIG_FORCE_MAX_ZONEORDER=13 CONFIG_IOMMU_VMERGE=y CONFIG_HOTPLUG_CPU=y @@ -155,6 +157,7 @@ CONFIG_EEH=y CONFIG_SCANLOG=m CONFIG_LPARCFG=y CONFIG_NUMA=y +CONFIG_NODES_SHIFT=4 CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_DEFAULT=y @@ -467,7 +470,7 @@ # CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_ISCSI_ATTRS=m -# CONFIG_SCSI_SAS_ATTRS is not set +CONFIG_SCSI_SAS_ATTRS=m # # SCSI low-level drivers @@ -499,13 +502,18 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y CONFIG_SCSI_IPR=y CONFIG_SCSI_IPR_TRACE=y CONFIG_SCSI_IPR_DUMP=y -# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLA_FC is not set +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y +CONFIG_SCSI_QLA21XX=m +CONFIG_SCSI_QLA22XX=m +CONFIG_SCSI_QLA2300=m +CONFIG_SCSI_QLA2322=m +CONFIG_SCSI_QLA24XX=m CONFIG_SCSI_LPFC=m # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -521,7 +529,7 @@ CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y CONFIG_MD_RAID10=m CONFIG_MD_RAID5=y -# CONFIG_MD_RAID5_RESHAPE is not set +CONFIG_MD_RAID5_RESHAPE=y CONFIG_MD_RAID6=m CONFIG_MD_MULTIPATH=m CONFIG_MD_FAULTY=m @@ -764,7 +772,7 @@ # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_ICOM=m -# CONFIG_SERIAL_JSM is not set +CONFIG_SERIAL_JSM=m CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -773,7 +781,7 @@ # CONFIG_PPDEV is not set # CONFIG_TIPAR is not set CONFIG_HVC_DRIVER=y CONFIG_HVC_CONSOLE=y -# CONFIG_HVC_RTAS is not set +CONFIG_HVC_RTAS=y CONFIG_HVCS=m # @@ -1031,9 +1039,7 @@ # CONFIG_USB_WACOM is not set # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -1105,16 +1111,25 @@ # # CONFIG_NEW_LEDS is not set # +# LED drivers +# + +# +# LED Triggers +# + +# # InfiniBand support # CONFIG_INFINIBAND=m -# CONFIG_INFINIBAND_USER_MAD is not set -# CONFIG_INFINIBAND_USER_ACCESS is not set +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m CONFIG_INFINIBAND_MTHCA=m -# CONFIG_INFINIBAND_MTHCA_DEBUG is not set +CONFIG_INFINIBAND_MTHCA_DEBUG=y CONFIG_INFINIBAND_IPOIB=m -# CONFIG_INFINIBAND_IPOIB_DEBUG is not set -# CONFIG_INFINIBAND_SRP is not set +CONFIG_INFINIBAND_IPOIB_DEBUG=y +# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set +CONFIG_INFINIBAND_SRP=m # # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) @@ -1159,15 +1174,15 @@ # CONFIG_XFS_QUOTA is not set CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y # CONFIG_XFS_RT is not set -# CONFIG_OCFS2_FS is not set +CONFIG_OCFS2_FS=m # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y -CONFIG_AUTOFS_FS=m -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m # # CD-ROM/DVD Filesystems @@ -1199,7 +1214,7 @@ CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y -# CONFIG_CONFIGFS_FS is not set +CONFIG_CONFIGFS_FS=m # # Miscellaneous filesystems @@ -1317,7 +1332,7 @@ # Instrumentation Support # CONFIG_PROFILING=y CONFIG_OPROFILE=y -# CONFIG_KPROBES is not set +CONFIG_KPROBES=y # # Kernel hacking @@ -1329,7 +1344,7 @@ CONFIG_LOG_BUF_SHIFT=17 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set @@ -1339,17 +1354,13 @@ # CONFIG_DEBUG_VM is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_STACKOVERFLOW=y -CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_STACK_USAGE is not set CONFIG_DEBUGGER=y CONFIG_XMON=y CONFIG_XMON_DEFAULT=y CONFIG_IRQSTACKS=y # CONFIG_BOOTX_TEXT is not set -# CONFIG_PPC_EARLY_DEBUG_LPAR is not set -# CONFIG_PPC_EARLY_DEBUG_G5 is not set -# CONFIG_PPC_EARLY_DEBUG_RTAS is not set -# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set -# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set +# CONFIG_PPC_EARLY_DEBUG is not set # # Security options diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index faaec9c..4734b5d 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c @@ -35,17 +35,19 @@ #define IS_DSFORM(inst) (((inst) >> 26) #define INVALID { 0, 0 } -#define LD 1 /* load */ -#define ST 2 /* store */ -#define SE 4 /* sign-extend value */ -#define F 8 /* to/from fp regs */ -#define U 0x10 /* update index register */ -#define M 0x20 /* multiple load/store */ -#define SW 0x40 /* byte swap int or ... */ -#define S 0x40 /* ... single-precision fp */ -#define SX 0x40 /* byte count in XER */ +/* Bits in the flags field */ +#define LD 0 /* load */ +#define ST 1 /* store */ +#define SE 2 /* sign-extend value */ +#define F 4 /* to/from fp regs */ +#define U 8 /* update index register */ +#define M 0x10 /* multiple load/store */ +#define SW 0x20 /* byte swap */ +#define S 0x40 /* single-precision fp or... */ +#define SX 0x40 /* ... byte count in XER */ #define HARD 0x80 /* string, stwcx. */ +/* DSISR bits reported for a DCBZ instruction: */ #define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */ #define SWAP(a, b) (t = (a), (a) = (b), (b) = t) @@ -256,12 +258,16 @@ #else #define REG_BYTE(rp, i) *((u8 *)(rp) + (i)) #endif +#define SWIZ_PTR(p) ((unsigned char __user *)((p) ^ swiz)) + static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, unsigned int reg, unsigned int nb, - unsigned int flags, unsigned int instr) + unsigned int flags, unsigned int instr, + unsigned long swiz) { unsigned long *rptr; - unsigned int nb0, i; + unsigned int nb0, i, bswiz; + unsigned long p; /* * We do not try to emulate 8 bytes multiple as they aren't really @@ -280,9 +286,12 @@ static int emulate_multiple(struct pt_re if (nb == 0) return 1; } else { - if (__get_user(instr, - (unsigned int __user *)regs->nip)) + unsigned long pc = regs->nip ^ (swiz & 4); + + if (__get_user(instr, (unsigned int __user *)pc)) return -EFAULT; + if (swiz == 0 && (flags & SW)) + instr = cpu_to_le32(instr); nb = (instr >> 11) & 0x1f; if (nb == 0) nb = 32; @@ -300,7 +309,10 @@ static int emulate_multiple(struct pt_re return -EFAULT; /* bad address */ rptr = ®s->gpr[reg]; - if (flags & LD) { + p = (unsigned long) addr; + bswiz = (flags & SW)? 3: 0; + + if (!(flags & ST)) { /* * This zeroes the top 4 bytes of the affected registers * in 64-bit mode, and also zeroes out any remaining @@ -311,26 +323,28 @@ static int emulate_multiple(struct pt_re memset(®s->gpr[0], 0, ((nb0 + 3) / 4) * sizeof(unsigned long)); - for (i = 0; i < nb; ++i) - if (__get_user(REG_BYTE(rptr, i), addr + i)) + for (i = 0; i < nb; ++i, ++p) + if (__get_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p))) return -EFAULT; if (nb0 > 0) { rptr = ®s->gpr[0]; addr += nb; - for (i = 0; i < nb0; ++i) - if (__get_user(REG_BYTE(rptr, i), addr + i)) + for (i = 0; i < nb0; ++i, ++p) + if (__get_user(REG_BYTE(rptr, i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; } } else { - for (i = 0; i < nb; ++i) - if (__put_user(REG_BYTE(rptr, i), addr + i)) + for (i = 0; i < nb; ++i, ++p) + if (__put_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p))) return -EFAULT; if (nb0 > 0) { rptr = ®s->gpr[0]; addr += nb; - for (i = 0; i < nb0; ++i) - if (__put_user(REG_BYTE(rptr, i), addr + i)) + for (i = 0; i < nb0; ++i, ++p) + if (__put_user(REG_BYTE(rptr, i ^ bswiz), + SWIZ_PTR(p))) return -EFAULT; } } @@ -352,7 +366,7 @@ int fix_alignment(struct pt_regs *regs) unsigned int reg, areg; unsigned int dsisr; unsigned char __user *addr; - unsigned char __user *p; + unsigned long p, swiz; int ret, t; union { u64 ll; @@ -380,11 +394,15 @@ int fix_alignment(struct pt_regs *regs) * let's make one up from the instruction */ if (cpu_has_feature(CPU_FTR_NODSISRALIGN)) { - unsigned int real_instr; - if (unlikely(__get_user(real_instr, - (unsigned int __user *)regs->nip))) + unsigned long pc = regs->nip; + + if (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE)) + pc ^= 4; + if (unlikely(__get_user(instr, (unsigned int __user *)pc))) return -EFAULT; - dsisr = make_dsisr(real_instr); + if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE)) + instr = cpu_to_le32(instr); + dsisr = make_dsisr(instr); } /* extract the operation and registers from the dsisr */ @@ -397,6 +415,24 @@ int fix_alignment(struct pt_regs *regs) nb = aligninfo[instr].len; flags = aligninfo[instr].flags; + /* Byteswap little endian loads and stores */ + swiz = 0; + if (regs->msr & MSR_LE) { + flags ^= SW; + /* + * So-called "PowerPC little endian" mode works by + * swizzling addresses rather than by actually doing + * any byte-swapping. To emulate this, we XOR each + * byte address with 7. We also byte-swap, because + * the processor's address swizzling depends on the + * operand size (it xors the address with 7 for bytes, + * 6 for halfwords, 4 for words, 0 for doublewords) but + * we will xor with 7 and load/store each byte separately. + */ + if (cpu_has_feature(CPU_FTR_PPC_LE)) + swiz = 7; + } + /* DAR has the operand effective address */ addr = (unsigned char __user *)regs->dar; @@ -412,7 +448,8 @@ int fix_alignment(struct pt_regs *regs) * function */ if (flags & M) - return emulate_multiple(regs, addr, reg, nb, flags, instr); + return emulate_multiple(regs, addr, reg, nb, + flags, instr, swiz); /* Verify the address of the operand */ if (unlikely(user_mode(regs) && @@ -431,51 +468,71 @@ int fix_alignment(struct pt_regs *regs) /* If we are loading, get the data from user space, else * get it from register values */ - if (flags & LD) { + if (!(flags & ST)) { data.ll = 0; ret = 0; - p = addr; + p = (unsigned long) addr; switch (nb) { case 8: - ret |= __get_user(data.v[0], p++); - ret |= __get_user(data.v[1], p++); - ret |= __get_user(data.v[2], p++); - ret |= __get_user(data.v[3], p++); + ret |= __get_user(data.v[0], SWIZ_PTR(p++)); + ret |= __get_user(data.v[1], SWIZ_PTR(p++)); + ret |= __get_user(data.v[2], SWIZ_PTR(p++)); + ret |= __get_user(data.v[3], SWIZ_PTR(p++)); case 4: - ret |= __get_user(data.v[4], p++); - ret |= __get_user(data.v[5], p++); + ret |= __get_user(data.v[4], SWIZ_PTR(p++)); + ret |= __get_user(data.v[5], SWIZ_PTR(p++)); case 2: - ret |= __get_user(data.v[6], p++); - ret |= __get_user(data.v[7], p++); + ret |= __get_user(data.v[6], SWIZ_PTR(p++)); + ret |= __get_user(data.v[7], SWIZ_PTR(p++)); if (unlikely(ret)) return -EFAULT; } - } else if (flags & F) + } else if (flags & F) { data.dd = current->thread.fpr[reg]; - else + if (flags & S) { + /* Single-precision FP store requires conversion... */ +#ifdef CONFIG_PPC_FPU + preempt_disable(); + enable_kernel_fp(); + cvt_df(&data.dd, (float *)&data.v[4], ¤t->thread); + preempt_enable(); +#else + return 0; +#endif + } + } else data.ll = regs->gpr[reg]; - /* Perform other misc operations like sign extension, byteswap, + if (flags & SW) { + switch (nb) { + case 8: + SWAP(data.v[0], data.v[7]); + SWAP(data.v[1], data.v[6]); + SWAP(data.v[2], data.v[5]); + SWAP(data.v[3], data.v[4]); + break; + case 4: + SWAP(data.v[4], data.v[7]); + SWAP(data.v[5], data.v[6]); + break; + case 2: + SWAP(data.v[6], data.v[7]); + break; + } + } + + /* Perform other misc operations like sign extension * or floating point single precision conversion */ - switch (flags & ~U) { + switch (flags & ~(U|SW)) { case LD+SE: /* sign extend */ if ( nb == 2 ) data.ll = data.x16.low16; else /* nb must be 4 */ data.ll = data.x32.low32; break; - case LD+S: /* byte-swap */ - case ST+S: - if (nb == 2) { - SWAP(data.v[6], data.v[7]); - } else { - SWAP(data.v[4], data.v[7]); - SWAP(data.v[5], data.v[6]); - } - break; - /* Single-precision FP load and store require conversions... */ + /* Single-precision FP load requires conversion... */ case LD+F+S: #ifdef CONFIG_PPC_FPU preempt_disable(); @@ -486,34 +543,24 @@ #else return 0; #endif break; - case ST+F+S: -#ifdef CONFIG_PPC_FPU - preempt_disable(); - enable_kernel_fp(); - cvt_df(&data.dd, (float *)&data.v[4], ¤t->thread); - preempt_enable(); -#else - return 0; -#endif - break; } /* Store result to memory or update registers */ if (flags & ST) { ret = 0; - p = addr; + p = (unsigned long) addr; switch (nb) { case 8: - ret |= __put_user(data.v[0], p++); - ret |= __put_user(data.v[1], p++); - ret |= __put_user(data.v[2], p++); - ret |= __put_user(data.v[3], p++); + ret |= __put_user(data.v[0], SWIZ_PTR(p++)); + ret |= __put_user(data.v[1], SWIZ_PTR(p++)); + ret |= __put_user(data.v[2], SWIZ_PTR(p++)); + ret |= __put_user(data.v[3], SWIZ_PTR(p++)); case 4: - ret |= __put_user(data.v[4], p++); - ret |= __put_user(data.v[5], p++); + ret |= __put_user(data.v[4], SWIZ_PTR(p++)); + ret |= __put_user(data.v[5], SWIZ_PTR(p++)); case 2: - ret |= __put_user(data.v[6], p++); - ret |= __put_user(data.v[7], p++); + ret |= __put_user(data.v[6], SWIZ_PTR(p++)); + ret |= __put_user(data.v[7], SWIZ_PTR(p++)); } if (unlikely(ret)) return -EFAULT; diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 8f85c5e..ff29405 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -122,9 +122,8 @@ #ifdef CONFIG_PPC64 DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); -#ifdef CONFIG_PPC_64K_PAGES - DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir)); -#endif + DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp)); + DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp)); #ifdef CONFIG_HUGETLB_PAGE DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S index 55ed771..365381f 100644 --- a/arch/powerpc/kernel/cpu_setup_6xx.S +++ b/arch/powerpc/kernel/cpu_setup_6xx.S @@ -210,9 +210,11 @@ setup_745x_specifics: * the firmware. If any, we disable NAP capability as * it's known to be bogus on rev 2.1 and earlier */ +BEGIN_FTR_SECTION mfspr r11,SPRN_L3CR andis. r11,r11,L3CR_L3E@h beq 1f +END_FTR_SECTION_IFSET(CPU_FTR_L3CR) lwz r6,CPU_SPEC_FEATURES(r5) andi. r0,r6,CPU_FTR_L3_DISABLE_NAP beq 1f diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S index b61d86e..2714183 100644 --- a/arch/powerpc/kernel/cpu_setup_power4.S +++ b/arch/powerpc/kernel/cpu_setup_power4.S @@ -73,23 +73,6 @@ _GLOBAL(__970_cpu_preinit) isync blr -_GLOBAL(__setup_cpu_power4) - blr - -_GLOBAL(__setup_cpu_be) - /* Set large page sizes LP=0: 16MB, LP=1: 64KB */ - addi r3, 0, 0 - ori r3, r3, HID6_LB - sldi r3, r3, 32 - nor r3, r3, r3 - mfspr r4, SPRN_HID6 - and r4, r4, r3 - addi r3, 0, 0x02000 - sldi r3, r3, 32 - or r4, r4, r3 - mtspr SPRN_HID6, r4 - blr - _GLOBAL(__setup_cpu_ppc970) mfspr r0,SPRN_HID0 li r11,5 /* clear DOZE and SLEEP */ diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 3f7182d..1c11488 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -30,11 +30,7 @@ EXPORT_SYMBOL(cur_cpu_spec); * part of the cputable though. That has to be fixed for both ppc32 * and ppc64 */ -#ifdef CONFIG_PPC64 -extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec); -extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec); -extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec); -#else +#ifdef CONFIG_PPC32 extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); @@ -58,7 +54,8 @@ #define COMMON_USER_POWER5 (COMMON_USER_ #define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\ PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) #define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\ - PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) + PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \ + PPC_FEATURE_TRUE_LE) #define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ PPC_FEATURE_BOOKE) @@ -78,11 +75,10 @@ #ifdef CONFIG_PPC64 .pvr_value = 0x00400000, .cpu_name = "POWER3 (630)", .cpu_features = CPU_FTRS_POWER3, - .cpu_user_features = COMMON_USER_PPC64, + .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", .oprofile_type = PPC_OPROFILE_RS64, .platform = "power3", @@ -92,11 +88,10 @@ #ifdef CONFIG_PPC64 .pvr_value = 0x00410000, .cpu_name = "POWER3 (630+)", .cpu_features = CPU_FTRS_POWER3, - .cpu_user_features = COMMON_USER_PPC64, + .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/power3", .oprofile_type = PPC_OPROFILE_RS64, .platform = "power3", @@ -110,7 +105,6 @@ #ifdef CONFIG_PPC64 .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", @@ -124,7 +118,6 @@ #ifdef CONFIG_PPC64 .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", @@ -138,7 +131,6 @@ #ifdef CONFIG_PPC64 .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", @@ -152,7 +144,6 @@ #ifdef CONFIG_PPC64 .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power3, .oprofile_cpu_type = "ppc64/rs64", .oprofile_type = PPC_OPROFILE_RS64, .platform = "rs64", @@ -166,7 +157,6 @@ #ifdef CONFIG_PPC64 .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power4", @@ -180,7 +170,6 @@ #ifdef CONFIG_PPC64 .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, - .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power4", .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power4", @@ -200,17 +189,11 @@ #ifdef CONFIG_PPC64 .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, -#endif /* CONFIG_PPC64 */ -#if defined(CONFIG_PPC64) || defined(CONFIG_POWER4) { /* PPC970FX */ .pvr_mask = 0xffff0000, .pvr_value = 0x003c0000, .cpu_name = "PPC970FX", -#ifdef CONFIG_PPC32 - .cpu_features = CPU_FTRS_970_32, -#else .cpu_features = CPU_FTRS_PPC970, -#endif .cpu_user_features = COMMON_USER_POWER4 | PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, @@ -221,8 +204,6 @@ #endif .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, -#endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ -#ifdef CONFIG_PPC64 { /* PPC970MP */ .pvr_mask = 0xffff0000, .pvr_value = 0x00440000, @@ -232,6 +213,7 @@ #ifdef CONFIG_PPC64 PPC_FEATURE_HAS_ALTIVEC_COMP, .icache_bsize = 128, .dcache_bsize = 128, + .num_pmcs = 8, .cpu_setup = __setup_cpu_ppc970, .oprofile_cpu_type = "ppc64/970", .oprofile_type = PPC_OPROFILE_POWER4, @@ -246,9 +228,13 @@ #ifdef CONFIG_PPC64 .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6, - .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5", .oprofile_type = PPC_OPROFILE_POWER4, + /* SIHV / SIPR bits are implemented on POWER4+ (GQ) + * and above but only works on POWER5 and above + */ + .oprofile_mmcra_sihv = MMCRA_SIHV, + .oprofile_mmcra_sipr = MMCRA_SIPR, .platform = "power5", }, { /* Power5 GS */ @@ -260,9 +246,10 @@ #ifdef CONFIG_PPC64 .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6, - .cpu_setup = __setup_cpu_power4, .oprofile_cpu_type = "ppc64/power5+", .oprofile_type = PPC_OPROFILE_POWER4, + .oprofile_mmcra_sihv = MMCRA_SIHV, + .oprofile_mmcra_sipr = MMCRA_SIPR, .platform = "power5+", }, { /* Power6 */ @@ -273,10 +260,13 @@ #ifdef CONFIG_PPC64 .cpu_user_features = COMMON_USER_POWER6, .icache_bsize = 128, .dcache_bsize = 128, - .num_pmcs = 6, - .cpu_setup = __setup_cpu_power4, + .num_pmcs = 8, .oprofile_cpu_type = "ppc64/power6", .oprofile_type = PPC_OPROFILE_POWER4, + .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, + .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, + .oprofile_mmcra_clear = POWER6_MMCRA_THRM | + POWER6_MMCRA_OTHER, .platform = "power6", }, { /* Cell Broadband Engine */ @@ -289,7 +279,6 @@ #ifdef CONFIG_PPC64 PPC_FEATURE_SMT, .icache_bsize = 128, .dcache_bsize = 128, - .cpu_setup = __setup_cpu_be, .platform = "ppc-cell-be", }, { /* default match */ @@ -301,7 +290,6 @@ #ifdef CONFIG_PPC64 .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6, - .cpu_setup = __setup_cpu_power4, .platform = "power4", } #endif /* CONFIG_PPC64 */ @@ -323,7 +311,7 @@ #if CLASSIC_PPC .pvr_value = 0x00030000, .cpu_name = "603", .cpu_features = CPU_FTRS_603, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .cpu_setup = __setup_cpu_603, @@ -334,7 +322,7 @@ #if CLASSIC_PPC .pvr_value = 0x00060000, .cpu_name = "603e", .cpu_features = CPU_FTRS_603, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .cpu_setup = __setup_cpu_603, @@ -345,7 +333,7 @@ #if CLASSIC_PPC .pvr_value = 0x00070000, .cpu_name = "603ev", .cpu_features = CPU_FTRS_603, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .cpu_setup = __setup_cpu_603, @@ -356,7 +344,7 @@ #if CLASSIC_PPC .pvr_value = 0x00040000, .cpu_name = "604", .cpu_features = CPU_FTRS_604, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 2, @@ -368,7 +356,7 @@ #if CLASSIC_PPC .pvr_value = 0x00090000, .cpu_name = "604e", .cpu_features = CPU_FTRS_604, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -380,7 +368,7 @@ #if CLASSIC_PPC .pvr_value = 0x00090000, .cpu_name = "604r", .cpu_features = CPU_FTRS_604, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -392,7 +380,7 @@ #if CLASSIC_PPC .pvr_value = 0x000a0000, .cpu_name = "604ev", .cpu_features = CPU_FTRS_604, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -404,7 +392,7 @@ #if CLASSIC_PPC .pvr_value = 0x00084202, .cpu_name = "740/750", .cpu_features = CPU_FTRS_740_NOTAU, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -416,7 +404,7 @@ #if CLASSIC_PPC .pvr_value = 0x00080100, .cpu_name = "750CX", .cpu_features = CPU_FTRS_750, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -428,7 +416,7 @@ #if CLASSIC_PPC .pvr_value = 0x00082200, .cpu_name = "750CX", .cpu_features = CPU_FTRS_750, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -440,7 +428,7 @@ #if CLASSIC_PPC .pvr_value = 0x00082210, .cpu_name = "750CXe", .cpu_features = CPU_FTRS_750, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -452,7 +440,7 @@ #if CLASSIC_PPC .pvr_value = 0x00083214, .cpu_name = "750CXe", .cpu_features = CPU_FTRS_750, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -464,7 +452,7 @@ #if CLASSIC_PPC .pvr_value = 0x00083000, .cpu_name = "745/755", .cpu_features = CPU_FTRS_750, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -476,7 +464,7 @@ #if CLASSIC_PPC .pvr_value = 0x70000100, .cpu_name = "750FX", .cpu_features = CPU_FTRS_750FX1, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -488,7 +476,7 @@ #if CLASSIC_PPC .pvr_value = 0x70000200, .cpu_name = "750FX", .cpu_features = CPU_FTRS_750FX2, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -500,7 +488,7 @@ #if CLASSIC_PPC .pvr_value = 0x70000000, .cpu_name = "750FX", .cpu_features = CPU_FTRS_750FX, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -512,7 +500,7 @@ #if CLASSIC_PPC .pvr_value = 0x70020000, .cpu_name = "750GX", .cpu_features = CPU_FTRS_750GX, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -524,7 +512,7 @@ #if CLASSIC_PPC .pvr_value = 0x00080000, .cpu_name = "740/750", .cpu_features = CPU_FTRS_740, - .cpu_user_features = COMMON_USER, + .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -536,7 +524,8 @@ #if CLASSIC_PPC .pvr_value = 0x000c1101, .cpu_name = "7400 (1.1)", .cpu_features = CPU_FTRS_7400_NOTAU, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -548,7 +537,8 @@ #if CLASSIC_PPC .pvr_value = 0x000c0000, .cpu_name = "7400", .cpu_features = CPU_FTRS_7400, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -560,7 +550,8 @@ #if CLASSIC_PPC .pvr_value = 0x800c0000, .cpu_name = "7410", .cpu_features = CPU_FTRS_7400, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, @@ -572,7 +563,8 @@ #if CLASSIC_PPC .pvr_value = 0x80000200, .cpu_name = "7450", .cpu_features = CPU_FTRS_7450_20, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -586,7 +578,8 @@ #if CLASSIC_PPC .pvr_value = 0x80000201, .cpu_name = "7450", .cpu_features = CPU_FTRS_7450_21, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -600,7 +593,8 @@ #if CLASSIC_PPC .pvr_value = 0x80000000, .cpu_name = "7450", .cpu_features = CPU_FTRS_7450_23, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -614,7 +608,8 @@ #if CLASSIC_PPC .pvr_value = 0x80010100, .cpu_name = "7455", .cpu_features = CPU_FTRS_7455_1, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -628,7 +623,8 @@ #if CLASSIC_PPC .pvr_value = 0x80010200, .cpu_name = "7455", .cpu_features = CPU_FTRS_7455_20, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -642,7 +638,8 @@ #if CLASSIC_PPC .pvr_value = 0x80010000, .cpu_name = "7455", .cpu_features = CPU_FTRS_7455, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -656,7 +653,8 @@ #if CLASSIC_PPC .pvr_value = 0x80020100, .cpu_name = "7447/7457", .cpu_features = CPU_FTRS_7447_10, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -670,7 +668,8 @@ #if CLASSIC_PPC .pvr_value = 0x80020101, .cpu_name = "7447/7457", .cpu_features = CPU_FTRS_7447_10, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -684,7 +683,7 @@ #if CLASSIC_PPC .pvr_value = 0x80020000, .cpu_name = "7447/7457", .cpu_features = CPU_FTRS_7447, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -698,7 +697,8 @@ #if CLASSIC_PPC .pvr_value = 0x80030000, .cpu_name = "7447A", .cpu_features = CPU_FTRS_7447A, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -712,7 +712,8 @@ #if CLASSIC_PPC .pvr_value = 0x80040000, .cpu_name = "7448", .cpu_features = CPU_FTRS_7447A, - .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features = COMMON_USER | + PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 6, @@ -721,6 +722,18 @@ #if CLASSIC_PPC .oprofile_type = PPC_OPROFILE_G4, .platform = "ppc7450", }, + { /* 8641 */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x80040010, + .cpu_name = "8641", + .cpu_features = CPU_FTRS_7447A, + .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, + { /* 82xx (8240, 8245, 8260 are all 603e cores) */ .pvr_mask = 0x7fff0000, .pvr_value = 0x00810000, diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 778f22f..e253a45 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -22,6 +22,7 @@ #include #include #include #include +#include #include #include @@ -174,9 +175,11 @@ #endif void default_machine_crash_shutdown(struct pt_regs *regs) { + unsigned int irq; + /* * This function is only called after the system - * has paniced or is otherwise in a critical state. + * has panicked or is otherwise in a critical state. * The minimum amount of code to allow a kexec'd kernel * to run successfully needs to happen here. * @@ -186,6 +189,16 @@ void default_machine_crash_shutdown(stru */ local_irq_disable(); + for_each_irq(irq) { + struct irq_desc *desc = irq_descp(irq); + + if (desc->status & IRQ_INPROGRESS) + desc->handler->end(irq); + + if (!(desc->status & IRQ_DISABLED)) + desc->handler->disable(irq); + } + if (ppc_md.kexec_cpu_down) ppc_md.kexec_cpu_down(1, 0); diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 764d073..371973b 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -25,6 +25,11 @@ #else #define DBG(fmt...) #endif +void reserve_kdump_trampoline(void) +{ + lmb_reserve(0, KDUMP_RESERVE_LIMIT); +} + static void __init create_trampoline(unsigned long addr) { /* The maximum range of a single instruction branch, is the current @@ -39,11 +44,11 @@ static void __init create_trampoline(uns create_branch(addr + 4, addr + PHYSICAL_START, 0); } -void __init kdump_setup(void) +void __init setup_kdump_trampoline(void) { unsigned long i; - DBG(" -> kdump_setup()\n"); + DBG(" -> setup_kdump_trampoline()\n"); for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) { create_trampoline(i); @@ -52,7 +57,7 @@ void __init kdump_setup(void) create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START); create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START); - DBG(" <- kdump_setup()\n"); + DBG(" <- setup_kdump_trampoline()\n"); } #ifdef CONFIG_PROC_VMCORE diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 19ad5c6..221062c 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -57,6 +57,7 @@ system_call_common: beq- 1f ld r1,PACAKSAVE(r13) 1: std r10,0(r1) + crclr so std r11,_NIP(r1) std r12,_MSR(r1) std r0,GPR0(r1) @@ -75,7 +76,6 @@ system_call_common: std r11,GPR11(r1) std r11,GPR12(r1) std r9,GPR13(r1) - crclr so mfcr r9 mflr r10 li r11,0xc01 diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index 340730f..01f7120 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S @@ -72,7 +72,7 @@ #else std r12,_MSR(r1) #endif lfd fr0,THREAD_FPSCR(r5) - mtfsf 0xff,fr0 + MTFSF_L(fr0) REST_32FPRS(0, r5) #ifndef CONFIG_SMP subi r4,r5,THREAD @@ -127,7 +127,7 @@ #endif /* CONFIG_SMP */ _GLOBAL(cvt_fd) lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */ - mtfsf 0xff,0 + MTFSF_L(0) lfs 0,0(r3) stfd 0,0(r4) mffs 0 @@ -136,7 +136,7 @@ _GLOBAL(cvt_fd) _GLOBAL(cvt_df) lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */ - mtfsf 0xff,0 + MTFSF_L(0) lfd 0,0(r3) stfs 0,0(r4) mffs 0 diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index a0579e8..b25b259 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S @@ -973,6 +973,13 @@ __secondary_start_gemini: b __secondary_start #endif /* CONFIG_GEMINI */ + .globl __secondary_start_mpc86xx +__secondary_start_mpc86xx: + mfspr r3, SPRN_PIR + stw r3, __secondary_hold_acknowledge@l(0) + mr r24, r3 /* cpu # */ + b __secondary_start + .globl __secondary_start_pmac_0 __secondary_start_pmac_0: /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */ @@ -1088,7 +1095,12 @@ load_up_mmu: LOAD_BAT(1,r3,r4,r5) LOAD_BAT(2,r3,r4,r5) LOAD_BAT(3,r3,r4,r5) - +BEGIN_FTR_SECTION + LOAD_BAT(4,r3,r4,r5) + LOAD_BAT(5,r3,r4,r5) + LOAD_BAT(6,r3,r4,r5) + LOAD_BAT(7,r3,r4,r5) +END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) blr /* diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index b7d1404..831acbd 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -316,6 +316,21 @@ label##_pSeries: \ mtspr SPRN_SPRG1,r13; /* save r13 */ \ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) +#define HSTD_EXCEPTION_PSERIES(n, label) \ + . = n; \ + .globl label##_pSeries; \ +label##_pSeries: \ + HMT_MEDIUM; \ + mtspr SPRN_SPRG1,r20; /* save r20 */ \ + mfspr r20,SPRN_HSRR0; /* copy HSRR0 to SRR0 */ \ + mtspr SPRN_SRR0,r20; \ + mfspr r20,SPRN_HSRR1; /* copy HSRR0 to SRR0 */ \ + mtspr SPRN_SRR1,r20; \ + mfspr r20,SPRN_SPRG1; /* restore r20 */ \ + mtspr SPRN_SPRG1,r13; /* save r13 */ \ + EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) + + #define STD_EXCEPTION_ISERIES(n, label, area) \ .globl label##_iSeries; \ label##_iSeries: \ @@ -544,8 +559,17 @@ system_call_pSeries: STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable) +#ifdef CONFIG_CBE_RAS + HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error) +#endif /* CONFIG_CBE_RAS */ STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) +#ifdef CONFIG_CBE_RAS + HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance) +#endif /* CONFIG_CBE_RAS */ STD_EXCEPTION_PSERIES(0x1700, altivec_assist) +#ifdef CONFIG_CBE_RAS + HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal) +#endif /* CONFIG_CBE_RAS */ . = 0x3000 @@ -827,6 +851,11 @@ #ifdef CONFIG_ALTIVEC #else STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception) #endif +#ifdef CONFIG_CBE_RAS + STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception) + STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception) + STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception) +#endif /* CONFIG_CBE_RAS */ /* * Here we have detected that the kernel stack pointer is bad. diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index fd8214c..a13a93d 100644 --- a/arch/powerpc/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c @@ -106,8 +106,6 @@ EXPORT_SYMBOL(iowrite32_rep); void __iomem *ioport_map(unsigned long port, unsigned int len) { - if (!_IO_IS_VALID(port)) - return NULL; return (void __iomem *) (port+pci_io_base); } diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 4eba60a..7cb77c2 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -418,10 +418,11 @@ void iommu_unmap_sg(struct iommu_table * * Build a iommu_table structure. This contains a bit map which * is used to manage allocation of the tce space. */ -struct iommu_table *iommu_init_table(struct iommu_table *tbl) +struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) { unsigned long sz; static int welcomed = 0; + struct page *page; /* Set aside 1/4 of the table for large allocations. */ tbl->it_halfpoint = tbl->it_size * 3 / 4; @@ -429,10 +430,10 @@ struct iommu_table *iommu_init_table(str /* number of bytes needed for the bitmap */ sz = (tbl->it_size + 7) >> 3; - tbl->it_map = (unsigned long *)__get_free_pages(GFP_ATOMIC, get_order(sz)); - if (!tbl->it_map) + page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz)); + if (!page) panic("iommu_init_table: Can't allocate %ld bytes\n", sz); - + tbl->it_map = page_address(page); memset(tbl->it_map, 0, sz); tbl->it_hint = 0; @@ -536,11 +537,12 @@ void iommu_unmap_single(struct iommu_tab * to the dma address (mapping) of the first page. */ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, - dma_addr_t *dma_handle, unsigned long mask, gfp_t flag) + dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node) { void *ret = NULL; dma_addr_t mapping; unsigned int npages, order; + struct page *page; size = PAGE_ALIGN(size); npages = size >> PAGE_SHIFT; @@ -560,9 +562,10 @@ void *iommu_alloc_coherent(struct iommu_ return NULL; /* Alloc enough pages (and possibly more) */ - ret = (void *)__get_free_pages(flag, order); - if (!ret) + page = alloc_pages_node(node, flag, order); + if (!page) return NULL; + ret = page_address(page); memset(ret, 0, size); /* Set up tces to cover the allocated range */ @@ -570,9 +573,9 @@ void *iommu_alloc_coherent(struct iommu_ mask >> PAGE_SHIFT, order); if (mapping == DMA_ERROR_CODE) { free_pages((unsigned long)ret, order); - ret = NULL; - } else - *dma_handle = mapping; + return NULL; + } + *dma_handle = mapping; return ret; } diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 57d560c..40d4c14 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -47,6 +47,7 @@ #include #include #include #include +#include #include #include @@ -379,8 +380,8 @@ unsigned int real_irq_to_virt_slowpath(u #endif /* CONFIG_PPC64 */ #ifdef CONFIG_IRQSTACKS -struct thread_info *softirq_ctx[NR_CPUS]; -struct thread_info *hardirq_ctx[NR_CPUS]; +struct thread_info *softirq_ctx[NR_CPUS] __read_mostly; +struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly; void irq_ctx_init(void) { @@ -436,6 +437,30 @@ void do_softirq(void) } EXPORT_SYMBOL(do_softirq); +#ifdef CONFIG_PCI_MSI +int pci_enable_msi(struct pci_dev * pdev) +{ + if (ppc_md.enable_msi) + return ppc_md.enable_msi(pdev); + else + return -1; +} + +void pci_disable_msi(struct pci_dev * pdev) +{ + if (ppc_md.disable_msi) + ppc_md.disable_msi(pdev); +} + +void pci_scan_msi_device(struct pci_dev *dev) {} +int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;} +void pci_disable_msix(struct pci_dev *dev) {} +void msi_remove_pci_irq_vectors(struct pci_dev *dev) {} +void disable_msi_mode(struct pci_dev *dev, int pos, int type) {} +void pci_no_msi(void) {} + +#endif + #ifdef CONFIG_PPC64 static int __init setup_noirqdistrib(char *str) { diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 2cbde86..c02deaa 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -521,10 +521,10 @@ static ssize_t lparcfg_write(struct file current_weight = (resource >> 5 * 8) & 0xFF; - pr_debug("%s: current_entitled = %lu, current_weight = %lu\n", + pr_debug("%s: current_entitled = %lu, current_weight = %u\n", __FUNCTION__, current_entitled, current_weight); - pr_debug("%s: new_entitled = %lu, new_weight = %lu\n", + pr_debug("%s: new_entitled = %lu, new_weight = %u\n", __FUNCTION__, *new_entitled_ptr, *new_weight_ptr); retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr, diff --git a/arch/powerpc/kernel/machine_kexec_32.c b/arch/powerpc/kernel/machine_kexec_32.c index 4436061..cbaa341 100644 --- a/arch/powerpc/kernel/machine_kexec_32.c +++ b/arch/powerpc/kernel/machine_kexec_32.c @@ -30,8 +30,8 @@ typedef NORET_TYPE void (*relocate_new_k */ void default_machine_kexec(struct kimage *image) { - const extern unsigned char relocate_new_kernel[]; - const extern unsigned int relocate_new_kernel_size; + extern const unsigned char relocate_new_kernel[]; + extern const unsigned int relocate_new_kernel_size; unsigned long page_list; unsigned long reboot_code_buffer, reboot_code_buffer_phys; relocate_new_kernel_t rnk; diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index ee166c5..a8fa04e 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -21,6 +21,7 @@ #include #include #include #include +#include #include #include /* _end */ #include @@ -335,7 +336,105 @@ static void __init export_htab_values(vo of_node_put(node); } +static struct property crashk_base_prop = { + .name = "linux,crashkernel-base", + .length = sizeof(unsigned long), + .value = (unsigned char *)&crashk_res.start, +}; + +static unsigned long crashk_size; + +static struct property crashk_size_prop = { + .name = "linux,crashkernel-size", + .length = sizeof(unsigned long), + .value = (unsigned char *)&crashk_size, +}; + +static void __init export_crashk_values(void) +{ + struct device_node *node; + struct property *prop; + + node = of_find_node_by_path("/chosen"); + if (!node) + return; + + /* There might be existing crash kernel properties, but we can't + * be sure what's in them, so remove them. */ + prop = of_find_property(node, "linux,crashkernel-base", NULL); + if (prop) + prom_remove_property(node, prop); + + prop = of_find_property(node, "linux,crashkernel-size", NULL); + if (prop) + prom_remove_property(node, prop); + + if (crashk_res.start != 0) { + prom_add_property(node, &crashk_base_prop); + crashk_size = crashk_res.end - crashk_res.start + 1; + prom_add_property(node, &crashk_size_prop); + } + + of_node_put(node); +} + void __init kexec_setup(void) { export_htab_values(); + export_crashk_values(); +} + +static int __init early_parse_crashk(char *p) +{ + unsigned long size; + + if (!p) + return 1; + + size = memparse(p, &p); + + if (*p == '@') + crashk_res.start = memparse(p + 1, &p); + else + crashk_res.start = KDUMP_KERNELBASE; + + crashk_res.end = crashk_res.start + size - 1; + + return 0; +} +early_param("crashkernel", early_parse_crashk); + +void __init reserve_crashkernel(void) +{ + unsigned long size; + + if (crashk_res.start == 0) + return; + + /* We might have got these values via the command line or the + * device tree, either way sanitise them now. */ + + size = crashk_res.end - crashk_res.start + 1; + + if (crashk_res.start != KDUMP_KERNELBASE) + printk("Crash kernel location must be 0x%x\n", + KDUMP_KERNELBASE); + + crashk_res.start = KDUMP_KERNELBASE; + size = PAGE_ALIGN(size); + crashk_res.end = crashk_res.start + size - 1; + + /* Crash kernel trumps memory limit */ + if (memory_limit && memory_limit <= crashk_res.end) { + memory_limit = crashk_res.end + 1; + printk("Adjusted memory limit for crashkernel, now 0x%lx\n", + memory_limit); + } + + lmb_reserve(crashk_res.start, size); +} + +int overlaps_crashkernel(unsigned long start, unsigned long size) +{ + return (start + size) > crashk_res.start && start <= crashk_res.end; } diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index be98202..01d3916 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -216,7 +216,7 @@ _GLOBAL(call_setup_cpu) lwz r4,0(r4) add r4,r4,r3 lwz r5,CPU_SPEC_SETUP(r4) - cmpi 0,r5,0 + cmpwi 0,r5,0 add r5,r5,r3 beqlr mtctr r5 diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 2778cce..e8883d4 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -482,7 +482,9 @@ _GLOBAL(identify_cpu) sub r0,r3,r5 std r0,0(r4) ld r4,CPU_SPEC_SETUP(r3) + cmpdi 0,r4,0 add r4,r4,r5 + beqlr ld r4,0(r4) add r4,r4,r5 mtctr r4 @@ -768,9 +770,6 @@ #endif /* CONFIG_SMP */ #endif /* CONFIG_ALTIVEC */ -_GLOBAL(__setup_cpu_power3) - blr - _GLOBAL(execve) li r0,__NR_execve sc diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index ada50aa..6960f09 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -204,7 +204,7 @@ static void nvram_print_partitions(char printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); list_for_each(p, &nvram_part->partition) { tmp_part = list_entry(p, struct nvram_partition, partition); - printk(KERN_WARNING "%d \t%02x\t%02x\t%d\t%s\n", + printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%s\n", tmp_part->index, tmp_part->header.signature, tmp_part->header.checksum, tmp_part->header.length, tmp_part->header.name); diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index b129d2e..b5431cc 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -1113,9 +1113,10 @@ check_for_io_childs(struct pci_bus *bus, int i; int rc = 0; -#define push_end(res, size) do { unsigned long __sz = (size) ; \ - res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \ - } while (0) +#define push_end(res, mask) do { \ + BUG_ON((mask+1) & mask); \ + res->end = (res->end + mask) | mask; \ +} while (0) list_for_each_entry(dev, &bus->devices, bus_list) { u16 class = dev->class >> 8; @@ -1653,7 +1654,6 @@ int pci_mmap_page_range(struct pci_dev * return -EINVAL; vma->vm_pgoff = offset >> PAGE_SHIFT; - vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO; vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, vma->vm_page_prot, mmap_state, write_combine); diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 4c4449b..247937d 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -42,14 +42,6 @@ #endif unsigned long pci_probe_only = 1; int pci_assign_all_buses = 0; -/* - * legal IO pages under MAX_ISA_PORT. This is to ensure we don't touch - * devices we don't have access to. - */ -unsigned long io_page_mask; - -EXPORT_SYMBOL(io_page_mask); - #ifdef CONFIG_PPC_MULTIPLATFORM static void fixup_resource(struct resource *res, struct pci_dev *dev); static void do_bus_setup(struct pci_bus *bus); @@ -235,8 +227,10 @@ struct pci_controller * pcibios_alloc_co pci_setup_pci_controller(phb); phb->arch_data = dev; phb->is_dynamic = mem_init_done; - if (dev) + if (dev) { + PHB_SET_NODE(phb, of_node_to_nid(dev)); add_linux_pci_domain(dev, phb); + } return phb; } @@ -396,7 +390,7 @@ struct pci_dev *of_create_pci_dev(struct dev->current_state = 4; /* unknown power state */ - if (!strcmp(type, "pci")) { + if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { /* a PCI-PCI bridge */ dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; dev->rom_base_reg = PCI_ROM_ADDRESS1; @@ -605,7 +599,7 @@ #ifdef CONFIG_PPC_ISERIES iSeries_pcibios_init(); #endif - printk("PCI: Probing PCI hardware\n"); + printk(KERN_DEBUG "PCI: Probing PCI hardware\n"); /* Scan all of the recorded PCI controllers. */ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { @@ -630,14 +624,14 @@ #endif /* !CONFIG_PPC_ISERIES */ /* Cache the location of the ISA bridge (if we have one) */ ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); if (ppc64_isabridge_dev != NULL) - printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); + printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); #ifdef CONFIG_PPC_MULTIPLATFORM /* map in PCI I/O space */ phbs_remap_io(); #endif - printk("PCI: Probing PCI hardware done\n"); + printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); return 0; } @@ -804,7 +798,7 @@ static pgprot_t __pci_mmap_set_pgprot(st else prot |= _PAGE_GUARDED; - printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, + printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, prot); return __pgprot(prot); @@ -883,7 +877,6 @@ int pci_mmap_page_range(struct pci_dev * return -EINVAL; vma->vm_pgoff = offset >> PAGE_SHIFT; - vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO; vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, vma->vm_page_prot, mmap_state, write_combine); @@ -894,8 +887,8 @@ int pci_mmap_page_range(struct pci_dev * return ret; } -#ifdef CONFIG_PPC_MULTIPLATFORM -static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t pci_show_devspec(struct device *dev, + struct device_attribute *attr, char *buf) { struct pci_dev *pdev; struct device_node *np; @@ -907,13 +900,10 @@ static ssize_t pci_show_devspec(struct d return sprintf(buf, "%s", np->full_name); } static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); -#endif /* CONFIG_PPC_MULTIPLATFORM */ void pcibios_add_platform_entries(struct pci_dev *pdev) { -#ifdef CONFIG_PPC_MULTIPLATFORM device_create_file(&pdev->dev, &dev_attr_devspec); -#endif /* CONFIG_PPC_MULTIPLATFORM */ } #ifdef CONFIG_PPC_MULTIPLATFORM @@ -1104,8 +1094,6 @@ void __init pci_setup_phb_io(struct pci_ pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys, hose->io_base_virt); of_node_put(isa_dn); - /* Allow all IO */ - io_page_mask = -1; } } @@ -1212,7 +1200,7 @@ int remap_bus_range(struct pci_bus *bus) return 1; if (start_phys == 0) return 1; - printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); + printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); if (__ioremap_explicit(start_phys, start_virt, size, _PAGE_NO_CACHE | _PAGE_GUARDED)) return 1; @@ -1232,27 +1220,13 @@ static void phbs_remap_io(void) static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) { struct pci_controller *hose = pci_bus_to_host(dev->bus); - unsigned long start, end, mask, offset; + unsigned long offset; if (res->flags & IORESOURCE_IO) { offset = (unsigned long)hose->io_base_virt - pci_io_base; - start = res->start += offset; - end = res->end += offset; - - /* Need to allow IO access to pages that are in the - ISA range */ - if (start < MAX_ISA_PORT) { - if (end > MAX_ISA_PORT) - end = MAX_ISA_PORT; - - start >>= PAGE_SHIFT; - end >>= PAGE_SHIFT; - - /* get the range of pages for the map */ - mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1); - io_page_mask |= mask; - } + res->start += offset; + res->end += offset; } else if (res->flags & IORESOURCE_MEM) { res->start += hose->pci_mem_offset; res->end += hose->pci_mem_offset; @@ -1442,3 +1416,12 @@ long sys_pciconfig_iobase(long which, un return -EOPNOTSUPP; } + +#ifdef CONFIG_NUMA +int pcibus_to_node(struct pci_bus *bus) +{ + struct pci_controller *phb = pci_bus_to_host(bus); + return phb->node; +} +EXPORT_SYMBOL(pcibus_to_node); +#endif diff --git a/arch/powerpc/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c index e1a32f8..72ce082 100644 --- a/arch/powerpc/kernel/pci_direct_iommu.c +++ b/arch/powerpc/kernel/pci_direct_iommu.c @@ -82,13 +82,17 @@ static int pci_direct_dma_supported(stru return mask < 0x100000000ull; } +static struct dma_mapping_ops pci_direct_ops = { + .alloc_coherent = pci_direct_alloc_coherent, + .free_coherent = pci_direct_free_coherent, + .map_single = pci_direct_map_single, + .unmap_single = pci_direct_unmap_single, + .map_sg = pci_direct_map_sg, + .unmap_sg = pci_direct_unmap_sg, + .dma_supported = pci_direct_dma_supported, +}; + void __init pci_direct_iommu_init(void) { - pci_dma_ops.alloc_coherent = pci_direct_alloc_coherent; - pci_dma_ops.free_coherent = pci_direct_free_coherent; - pci_dma_ops.map_single = pci_direct_map_single; - pci_dma_ops.unmap_single = pci_direct_unmap_single; - pci_dma_ops.map_sg = pci_direct_map_sg; - pci_dma_ops.unmap_sg = pci_direct_unmap_sg; - pci_dma_ops.dma_supported = pci_direct_dma_supported; + pci_dma_ops = pci_direct_ops; } diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 12c4c9e..1c18953 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -31,6 +31,7 @@ #include #include #include #include +#include /* * Traverse_func that inits the PCI fields of the device node. @@ -59,6 +60,11 @@ static void * __devinit update_dn_pci_in pdn->busno = (regs[0] >> 16) & 0xff; pdn->devfn = (regs[0] >> 8) & 0xff; } + if (firmware_has_feature(FW_FEATURE_ISERIES)) { + u32 *busp = (u32 *)get_property(dn, "linux,subbus", NULL); + if (busp) + pdn->bussubno = *busp; + } pdn->pci_ext_config_space = (type && *type == 1); return NULL; diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index c1d95e1..0688b25 100644 --- a/arch/powerpc/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c @@ -44,16 +44,16 @@ #include */ #define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata)) -static inline struct iommu_table *devnode_table(struct device *dev) +static inline struct iommu_table *device_to_table(struct device *hwdev) { struct pci_dev *pdev; - if (!dev) { + if (!hwdev) { pdev = ppc64_isabridge_dev; if (!pdev) return NULL; } else - pdev = to_pci_dev(dev); + pdev = to_pci_dev(hwdev); return PCI_DN(PCI_GET_DN(pdev))->iommu_table; } @@ -85,14 +85,15 @@ static inline unsigned long device_to_ma static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { - return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle, - device_to_mask(hwdev), flag); + return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle, + device_to_mask(hwdev), flag, + pcibus_to_node(to_pci_dev(hwdev)->bus)); } static void pci_iommu_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { - iommu_free_coherent(devnode_table(hwdev), size, vaddr, dma_handle); + iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle); } /* Creates TCEs for a user provided buffer. The user buffer must be @@ -104,7 +105,7 @@ static void pci_iommu_free_coherent(stru static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, size_t size, enum dma_data_direction direction) { - return iommu_map_single(devnode_table(hwdev), vaddr, size, + return iommu_map_single(device_to_table(hwdev), vaddr, size, device_to_mask(hwdev), direction); } @@ -112,27 +113,27 @@ static dma_addr_t pci_iommu_map_single(s static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { - iommu_unmap_single(devnode_table(hwdev), dma_handle, size, direction); + iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction); } static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { - return iommu_map_sg(pdev, devnode_table(pdev), sglist, + return iommu_map_sg(pdev, device_to_table(pdev), sglist, nelems, device_to_mask(pdev), direction); } static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist, int nelems, enum dma_data_direction direction) { - iommu_unmap_sg(devnode_table(pdev), sglist, nelems, direction); + iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction); } /* We support DMA to/from any memory page via the iommu */ static int pci_iommu_dma_supported(struct device *dev, u64 mask) { - struct iommu_table *tbl = devnode_table(dev); + struct iommu_table *tbl = device_to_table(dev); if (!tbl || tbl->it_offset > mask) { printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n"); @@ -147,13 +148,17 @@ static int pci_iommu_dma_supported(struc return 1; } +struct dma_mapping_ops pci_iommu_ops = { + .alloc_coherent = pci_iommu_alloc_coherent, + .free_coherent = pci_iommu_free_coherent, + .map_single = pci_iommu_map_single, + .unmap_single = pci_iommu_unmap_single, + .map_sg = pci_iommu_map_sg, + .unmap_sg = pci_iommu_unmap_sg, + .dma_supported = pci_iommu_dma_supported, +}; + void pci_iommu_init(void) { - pci_dma_ops.alloc_coherent = pci_iommu_alloc_coherent; - pci_dma_ops.free_coherent = pci_iommu_free_coherent; - pci_dma_ops.map_single = pci_iommu_map_single; - pci_dma_ops.unmap_single = pci_iommu_unmap_single; - pci_dma_ops.map_sg = pci_iommu_map_sg; - pci_dma_ops.unmap_sg = pci_iommu_unmap_sg; - pci_dma_ops.dma_supported = pci_iommu_dma_supported; + pci_dma_ops = pci_iommu_ops; } diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index 3c2cf66..2ab8f2b 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c @@ -52,7 +52,7 @@ static int __init proc_ppc64_create(void if (!root) return 1; - if (!machine_is(pseries) && !machine_is(cell)) + if (!of_find_node_by_path("/rtas")) return 0; if (!proc_mkdir("rtas", root)) @@ -115,8 +115,6 @@ static int page_map_mmap( struct file *f { struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); - vma->vm_flags |= VM_SHM | VM_LOCKED; - if ((vma->vm_end - vma->vm_start) > dp->size) return -EINVAL; diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 2dd47d2..e473245 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -708,6 +708,61 @@ #endif return put_user(val, (unsigned int __user *) adr); } +int set_endian(struct task_struct *tsk, unsigned int val) +{ + struct pt_regs *regs = tsk->thread.regs; + + if ((val == PR_ENDIAN_LITTLE && !cpu_has_feature(CPU_FTR_REAL_LE)) || + (val == PR_ENDIAN_PPC_LITTLE && !cpu_has_feature(CPU_FTR_PPC_LE))) + return -EINVAL; + + if (regs == NULL) + return -EINVAL; + + if (val == PR_ENDIAN_BIG) + regs->msr &= ~MSR_LE; + else if (val == PR_ENDIAN_LITTLE || val == PR_ENDIAN_PPC_LITTLE) + regs->msr |= MSR_LE; + else + return -EINVAL; + + return 0; +} + +int get_endian(struct task_struct *tsk, unsigned long adr) +{ + struct pt_regs *regs = tsk->thread.regs; + unsigned int val; + + if (!cpu_has_feature(CPU_FTR_PPC_LE) && + !cpu_has_feature(CPU_FTR_REAL_LE)) + return -EINVAL; + + if (regs == NULL) + return -EINVAL; + + if (regs->msr & MSR_LE) { + if (cpu_has_feature(CPU_FTR_REAL_LE)) + val = PR_ENDIAN_LITTLE; + else + val = PR_ENDIAN_PPC_LITTLE; + } else + val = PR_ENDIAN_BIG; + + return put_user(val, (unsigned int __user *)adr); +} + +int set_unalign_ctl(struct task_struct *tsk, unsigned int val) +{ + tsk->thread.align_ctl = val; + return 0; +} + +int get_unalign_ctl(struct task_struct *tsk, unsigned long adr) +{ + return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr); +} + #define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) int sys_clone(unsigned long clone_flags, unsigned long usp, diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 9a07f97..483455c 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -50,6 +50,7 @@ #include #include #include #include +#include #ifdef DEBUG #define DBG(fmt...) printk(KERN_ERR fmt) @@ -836,6 +837,42 @@ #endif return mem; } +static int __init early_parse_mem(char *p) +{ + if (!p) + return 1; + + memory_limit = PAGE_ALIGN(memparse(p, &p)); + DBG("memory limit = 0x%lx\n", memory_limit); + + return 0; +} +early_param("mem", early_parse_mem); + +/* + * The device tree may be allocated below our memory limit, or inside the + * crash kernel region for kdump. If so, move it out now. + */ +static void move_device_tree(void) +{ + unsigned long start, size; + void *p; + + DBG("-> move_device_tree\n"); + + start = __pa(initial_boot_params); + size = initial_boot_params->totalsize; + + if ((memory_limit && (start + size) > memory_limit) || + overlaps_crashkernel(start, size)) { + p = __va(lmb_alloc_base(size, PAGE_SIZE, lmb.rmo_size)); + memcpy(p, initial_boot_params, size); + initial_boot_params = (struct boot_param_header *)p; + DBG("Moved device tree to 0x%p\n", p); + } + + DBG("<- move_device_tree\n"); +} /** * unflattens the device-tree passed by the firmware, creating the @@ -911,7 +948,10 @@ static struct ibm_pa_feature { {CPU_FTR_CTRL, 0, 0, 3, 0}, {CPU_FTR_NOEXECUTE, 0, 0, 6, 0}, {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1}, +#if 0 + /* put this back once we know how to test if firmware does 64k IO */ {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, +#endif }; static void __init check_cpu_pa_features(unsigned long node) @@ -1070,6 +1110,7 @@ #ifdef CONFIG_PPC64 iommu_force_on = 1; #endif + /* mem=x on the command line is the preferred mechanism */ lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); if (lprop) memory_limit = *lprop; @@ -1123,17 +1164,6 @@ #endif /* CONFIG_CMDLINE */ DBG("Command line is: %s\n", cmd_line); - if (strstr(cmd_line, "mem=")) { - char *p, *q; - - for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { - q = p + 4; - if (p > cmd_line && p[-1] != ' ') - continue; - memory_limit = memparse(q, &q); - } - } - /* break now */ return 1; } @@ -1237,9 +1267,17 @@ static void __init early_reserve_mem(voi { u64 base, size; u64 *reserve_map; + unsigned long self_base; + unsigned long self_size; reserve_map = (u64 *)(((unsigned long)initial_boot_params) + initial_boot_params->off_mem_rsvmap); + + /* before we do anything, lets reserve the dt blob */ + self_base = __pa((unsigned long)initial_boot_params); + self_size = initial_boot_params->totalsize; + lmb_reserve(self_base, self_size); + #ifdef CONFIG_PPC32 /* * Handle the case where we might be booting from an old kexec @@ -1254,6 +1292,9 @@ #ifdef CONFIG_PPC32 size_32 = *(reserve_map_32++); if (size_32 == 0) break; + /* skip if the reservation is for the blob */ + if (base_32 == self_base && size_32 == self_size) + continue; DBG("reserving: %x -> %x\n", base_32, size_32); lmb_reserve(base_32, size_32); } @@ -1265,6 +1306,9 @@ #endif size = *(reserve_map++); if (size == 0) break; + /* skip if the reservation is for the blob */ + if (base == self_base && size == self_size) + continue; DBG("reserving: %llx -> %llx\n", base, size); lmb_reserve(base, size); } @@ -1292,18 +1336,26 @@ void __init early_init_devtree(void *par lmb_init(); of_scan_flat_dt(early_init_dt_scan_root, NULL); of_scan_flat_dt(early_init_dt_scan_memory, NULL); - lmb_enforce_memory_limit(memory_limit); - lmb_analyze(); - DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); + /* Save command line for /proc/cmdline and then parse parameters */ + strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); + parse_early_param(); /* Reserve LMB regions used by kernel, initrd, dt, etc... */ lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); -#ifdef CONFIG_CRASH_DUMP - lmb_reserve(0, KDUMP_RESERVE_LIMIT); -#endif + reserve_kdump_trampoline(); + reserve_crashkernel(); early_reserve_mem(); + lmb_enforce_memory_limit(memory_limit); + lmb_analyze(); + + DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); + + /* We may need to relocate the flat tree, do it now. + * FIXME .. and the initrd too? */ + move_device_tree(); + DBG("Scanning CPUs ...\n"); /* Retreive CPU related informations from the flat tree @@ -2053,29 +2105,46 @@ #endif /* CONFIG_PROC_DEVICETREE */ return 0; } -#ifdef CONFIG_KEXEC -/* We may have allocated the flat device tree inside the crash kernel region - * in prom_init. If so we need to move it out into regular memory. */ -void kdump_move_device_tree(void) -{ - unsigned long start, end; - struct boot_param_header *new; - - start = __pa((unsigned long)initial_boot_params); - end = start + initial_boot_params->totalsize; - - if (end < crashk_res.start || start > crashk_res.end) - return; - new = (struct boot_param_header*) - __va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE)); - - memcpy(new, initial_boot_params, initial_boot_params->totalsize); +/* Find the device node for a given logical cpu number, also returns the cpu + * local thread number (index in ibm,interrupt-server#s) if relevant and + * asked for (non NULL) + */ +struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) +{ + int hardid; + struct device_node *np; - initial_boot_params = new; + hardid = get_hard_smp_processor_id(cpu); - DBG("Flat device tree blob moved to %p\n", initial_boot_params); + for_each_node_by_type(np, "cpu") { + u32 *intserv; + unsigned int plen, t; - /* XXX should we unreserve the old DT? */ + /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist + * fallback to "reg" property and assume no threads + */ + intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s", + &plen); + if (intserv == NULL) { + u32 *reg = (u32 *)get_property(np, "reg", NULL); + if (reg == NULL) + continue; + if (*reg == hardid) { + if (thread) + *thread = 0; + return np; + } + } else { + plen /= sizeof(u32); + for (t = 0; t < plen; t++) { + if (hardid == intserv[t]) { + if (thread) + *thread = t; + return np; + } + } + } + } + return NULL; } -#endif /* CONFIG_KEXEC */ diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index f70bd09..8c28eb0 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -194,19 +194,12 @@ static int __initdata of_platform; static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; -static unsigned long __initdata prom_memory_limit; - static unsigned long __initdata alloc_top; static unsigned long __initdata alloc_top_high; static unsigned long __initdata alloc_bottom; static unsigned long __initdata rmo_top; static unsigned long __initdata ram_top; -#ifdef CONFIG_KEXEC -static unsigned long __initdata prom_crashk_base; -static unsigned long __initdata prom_crashk_size; -#endif - static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE]; static int __initdata mem_reserve_cnt; @@ -574,7 +567,7 @@ static void __init early_cmdline_parse(v if ((long)_prom->chosen > 0) l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1); #ifdef CONFIG_CMDLINE - if (l == 0) /* dbl check */ + if (l <= 0 || p[0] == '\0') /* dbl check */ strlcpy(RELOC(prom_cmd_line), RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line)); #endif /* CONFIG_CMDLINE */ @@ -593,45 +586,6 @@ #ifdef CONFIG_PPC64 RELOC(iommu_force_on) = 1; } #endif - - opt = strstr(RELOC(prom_cmd_line), RELOC("mem=")); - if (opt) { - opt += 4; - RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt); -#ifdef CONFIG_PPC64 - /* Align to 16 MB == size of ppc64 large page */ - RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000); -#endif - } - -#ifdef CONFIG_KEXEC - /* - * crashkernel=size@addr specifies the location to reserve for - * crash kernel. - */ - opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel=")); - if (opt) { - opt += 12; - RELOC(prom_crashk_size) = - prom_memparse(opt, (const char **)&opt); - - if (ALIGN(RELOC(prom_crashk_size), 0x1000000) != - RELOC(prom_crashk_size)) { - prom_printf("Warning: crashkernel size is not " - "aligned to 16MB\n"); - } - - /* - * At present, the crash kernel always run at 32MB. - * Just ignore whatever user passed. - */ - RELOC(prom_crashk_base) = 0x2000000; - if (*opt == '@') { - prom_printf("Warning: PPC64 kdump kernel always runs " - "at 32 MB\n"); - } - } -#endif } #ifdef CONFIG_PPC_PSERIES @@ -1116,29 +1070,6 @@ #endif /* DEBUG_PROM */ } /* - * If prom_memory_limit is set we reduce the upper limits *except* for - * alloc_top_high. This must be the real top of RAM so we can put - * TCE's up there. - */ - - RELOC(alloc_top_high) = RELOC(ram_top); - - if (RELOC(prom_memory_limit)) { - if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) { - prom_printf("Ignoring mem=%x <= alloc_bottom.\n", - RELOC(prom_memory_limit)); - RELOC(prom_memory_limit) = 0; - } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) { - prom_printf("Ignoring mem=%x >= ram_top.\n", - RELOC(prom_memory_limit)); - RELOC(prom_memory_limit) = 0; - } else { - RELOC(ram_top) = RELOC(prom_memory_limit); - RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit)); - } - } - - /* * Setup our top alloc point, that is top of RMO or top of * segment 0 when running non-LPAR. * Some RS64 machines have buggy firmware where claims up at @@ -1150,20 +1081,14 @@ #endif /* DEBUG_PROM */ RELOC(rmo_top) = RELOC(ram_top); RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top)); RELOC(alloc_top) = RELOC(rmo_top); + RELOC(alloc_top_high) = RELOC(ram_top); prom_printf("memory layout at init:\n"); - prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit)); prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom)); prom_printf(" alloc_top : %x\n", RELOC(alloc_top)); prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); prom_printf(" rmo_top : %x\n", RELOC(rmo_top)); prom_printf(" ram_top : %x\n", RELOC(ram_top)); -#ifdef CONFIG_KEXEC - if (RELOC(prom_crashk_base)) { - prom_printf(" crashk_base : %x\n", RELOC(prom_crashk_base)); - prom_printf(" crashk_size : %x\n", RELOC(prom_crashk_size)); - } -#endif } @@ -1349,16 +1274,10 @@ static void __init prom_initialize_tce_t reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom); - if (RELOC(prom_memory_limit)) { - /* - * We align the start to a 16MB boundary so we can map - * the TCE area using large pages if possible. - * The end should be the top of RAM so no need to align it. - */ - RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom, - 0x1000000); - RELOC(prom_tce_alloc_end) = local_alloc_top; - } + /* These are only really needed if there is a memory limit in + * effect, but we don't know so export them always. */ + RELOC(prom_tce_alloc_start) = local_alloc_bottom; + RELOC(prom_tce_alloc_end) = local_alloc_top; /* Flag the first invalid entry */ prom_debug("ending prom_initialize_tce_table\n"); @@ -2041,11 +1960,7 @@ static void __init flatten_device_tree(v /* Version 16 is not backward compatible */ hdr->last_comp_version = 0x10; - /* Reserve the whole thing and copy the reserve map in, we - * also bump mem_reserve_cnt to cause further reservations to - * fail since it's too late. - */ - reserve_mem(RELOC(dt_header_start), hdr->totalsize); + /* Copy the reserve map in */ memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map)); #ifdef DEBUG_PROM @@ -2058,6 +1973,9 @@ #ifdef DEBUG_PROM RELOC(mem_reserve_map)[i].size); } #endif + /* Bump mem_reserve_cnt to cause further reservations to fail + * since it's too late. + */ RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE; prom_printf("Device tree strings 0x%x -> 0x%x\n", @@ -2280,10 +2198,6 @@ #endif */ prom_init_mem(); -#ifdef CONFIG_KEXEC - if (RELOC(prom_crashk_base)) - reserve_mem(RELOC(prom_crashk_base), RELOC(prom_crashk_size)); -#endif /* * Determine which cpu is actually running right _now_ */ @@ -2317,10 +2231,6 @@ #endif /* * Fill in some infos for use by the kernel later on */ - if (RELOC(prom_memory_limit)) - prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit", - &RELOC(prom_memory_limit), - sizeof(prom_memory_limit)); #ifdef CONFIG_PPC64 if (RELOC(ppc64_iommu_off)) prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", @@ -2340,16 +2250,6 @@ #ifdef CONFIG_PPC64 } #endif -#ifdef CONFIG_KEXEC - if (RELOC(prom_crashk_base)) { - prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-base", - PTRRELOC(&prom_crashk_base), - sizeof(RELOC(prom_crashk_base))); - prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-size", - PTRRELOC(&prom_crashk_size), - sizeof(RELOC(prom_crashk_size))); - } -#endif /* * Fixup any known bugs in the device-tree */ diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 3934c22..45df420 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -548,3 +548,28 @@ int of_pci_address_to_resource(struct de return __of_address_to_resource(dev, addrp, size, flags, r); } EXPORT_SYMBOL_GPL(of_pci_address_to_resource); + +void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop, + unsigned long *busno, unsigned long *phys, unsigned long *size) +{ + u32 *dma_window, cells; + unsigned char *prop; + + dma_window = (u32 *)dma_window_prop; + + /* busno is always one cell */ + *busno = *(dma_window++); + + prop = get_property(dn, "ibm,#dma-address-cells", NULL); + if (!prop) + prop = get_property(dn, "#address-cells", NULL); + + cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn); + *phys = of_read_addr(dma_window, cells); + + dma_window += cells; + + prop = get_property(dn, "ibm,#dma-size-cells", NULL); + cells = prop ? *(u32 *)prop : prom_n_size_cells(dn); + *size = of_read_addr(dma_window, cells); +} diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 4a677d1..5563e2e 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -404,7 +404,6 @@ #endif ret = ptrace_detach(child, data); break; -#ifdef CONFIG_PPC64 case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ int i; unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; @@ -468,7 +467,6 @@ #ifdef CONFIG_PPC64 } break; } -#endif /* CONFIG_PPC64 */ #ifdef CONFIG_ALTIVEC case PTRACE_GETVRREGS: diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c index 34d073f..77578c0 100644 --- a/arch/powerpc/kernel/rtas-rtc.c +++ b/arch/powerpc/kernel/rtas-rtc.c @@ -14,19 +14,20 @@ #define RTAS_CLOCK_BUSY (-2) unsigned long __init rtas_get_boot_time(void) { int ret[8]; - int error, wait_time; + int error; + unsigned int wait_time; u64 max_wait_tb; max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; do { error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); - if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { - wait_time = rtas_extended_busy_delay_time(error); + + wait_time = rtas_busy_delay_time(error); + if (wait_time) { /* This is boot time so we spin. */ udelay(wait_time*1000); - error = RTAS_CLOCK_BUSY; } - } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); + } while (wait_time && (get_tb() < max_wait_tb)); if (error != 0 && printk_ratelimit()) { printk(KERN_WARNING "error: reading the clock failed (%d)\n", @@ -44,24 +45,25 @@ unsigned long __init rtas_get_boot_time( void rtas_get_rtc_time(struct rtc_time *rtc_tm) { int ret[8]; - int error, wait_time; + int error; + unsigned int wait_time; u64 max_wait_tb; max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; do { error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); - if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { + + wait_time = rtas_busy_delay_time(error); + if (wait_time) { if (in_interrupt() && printk_ratelimit()) { memset(rtc_tm, 0, sizeof(struct rtc_time)); printk(KERN_WARNING "error: reading clock" " would delay interrupt\n"); return; /* delay not allowed */ } - wait_time = rtas_extended_busy_delay_time(error); msleep(wait_time); - error = RTAS_CLOCK_BUSY; } - } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); + } while (wait_time && (get_tb() < max_wait_tb)); if (error != 0 && printk_ratelimit()) { printk(KERN_WARNING "error: reading the clock failed (%d)\n", @@ -88,14 +90,14 @@ int rtas_set_rtc_time(struct rtc_time *t tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, 0); - if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { + + wait_time = rtas_busy_delay_time(error); + if (wait_time) { if (in_interrupt()) return 1; /* probably decrementer */ - wait_time = rtas_extended_busy_delay_time(error); msleep(wait_time); - error = RTAS_CLOCK_BUSY; } - } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); + } while (wait_time && (get_tb() < max_wait_tb)); if (error != 0 && printk_ratelimit()) printk(KERN_WARNING "error: setting the clock failed (%d)\n", diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 0112318..17dc791 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -370,24 +370,36 @@ int rtas_call(int token, int nargs, int return ret; } -/* Given an RTAS status code of 990n compute the hinted delay of 10^n - * (last digit) milliseconds. For now we bound at n=5 (100 sec). +/* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status + * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds. */ -unsigned int rtas_extended_busy_delay_time(int status) +unsigned int rtas_busy_delay_time(int status) { - int order = status - 9900; - unsigned long ms; + int order; + unsigned int ms = 0; + + if (status == RTAS_BUSY) { + ms = 1; + } else if (status >= 9900 && status <= 9905) { + order = status - 9900; + for (ms = 1; order > 0; order--) + ms *= 10; + } - if (order < 0) - order = 0; /* RTC depends on this for -2 clock busy */ - else if (order > 5) - order = 5; /* bound */ + return ms; +} - /* Use microseconds for reasonable accuracy */ - for (ms = 1; order > 0; order--) - ms *= 10; +/* For an RTAS busy status code, perform the hinted delay. */ +unsigned int rtas_busy_delay(int status) +{ + unsigned int ms; - return ms; + might_sleep(); + ms = rtas_busy_delay_time(status); + if (ms) + msleep(ms); + + return ms; } int rtas_error_rc(int rtas_rc) @@ -438,22 +450,14 @@ int rtas_get_power_level(int powerdomain int rtas_set_power_level(int powerdomain, int level, int *setlevel) { int token = rtas_token("set-power-level"); - unsigned int wait_time; int rc; if (token == RTAS_UNKNOWN_SERVICE) return -ENOENT; - while (1) { + do { rc = rtas_call(token, 2, 2, setlevel, powerdomain, level); - if (rc == RTAS_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } else - break; - } + } while (rtas_busy_delay(rc)); if (rc < 0) return rtas_error_rc(rc); @@ -463,22 +467,14 @@ int rtas_set_power_level(int powerdomain int rtas_get_sensor(int sensor, int index, int *state) { int token = rtas_token("get-sensor-state"); - unsigned int wait_time; int rc; if (token == RTAS_UNKNOWN_SERVICE) return -ENOENT; - while (1) { + do { rc = rtas_call(token, 2, 2, state, sensor, index); - if (rc == RTAS_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } else - break; - } + } while (rtas_busy_delay(rc)); if (rc < 0) return rtas_error_rc(rc); @@ -488,23 +484,14 @@ int rtas_get_sensor(int sensor, int inde int rtas_set_indicator(int indicator, int index, int new_value) { int token = rtas_token("set-indicator"); - unsigned int wait_time; int rc; if (token == RTAS_UNKNOWN_SERVICE) return -ENOENT; - while (1) { + do { rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value); - if (rc == RTAS_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } - else - break; - } + } while (rtas_busy_delay(rc)); if (rc < 0) return rtas_error_rc(rc); @@ -555,13 +542,11 @@ void rtas_os_term(char *str) do { status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL, __pa(rtas_os_term_buf)); + } while (rtas_busy_delay(status)); - if (status == RTAS_BUSY) - udelay(1); - else if (status != 0) - printk(KERN_EMERG "ibm,os-term call failed %d\n", + if (status != 0) + printk(KERN_EMERG "ibm,os-term call failed %d\n", status); - } while (status == RTAS_BUSY); } static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; @@ -608,9 +593,31 @@ out: static int rtas_ibm_suspend_me(struct rtas_args *args) { int i; + long state; + long rc; + unsigned long dummy; struct rtas_suspend_me_data data; + /* Make sure the state is valid */ + rc = plpar_hcall(H_VASI_STATE, + ((u64)args->args[0] << 32) | args->args[1], + 0, 0, 0, + &state, &dummy, &dummy); + + if (rc) { + printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc); + return rc; + } else if (state == H_VASI_ENABLED) { + args->args[args->nargs] = RTAS_NOT_SUSPENDABLE; + return 0; + } else if (state != H_VASI_SUSPENDING) { + printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n", + state); + args->args[args->nargs] = -1; + return 0; + } + data.waiting = 1; data.args = args; @@ -789,7 +796,8 @@ EXPORT_SYMBOL(rtas_token); EXPORT_SYMBOL(rtas_call); EXPORT_SYMBOL(rtas_data_buf); EXPORT_SYMBOL(rtas_data_buf_lock); -EXPORT_SYMBOL(rtas_extended_busy_delay_time); +EXPORT_SYMBOL(rtas_busy_delay_time); +EXPORT_SYMBOL(rtas_busy_delay); EXPORT_SYMBOL(rtas_get_sensor); EXPORT_SYMBOL(rtas_get_power_level); EXPORT_SYMBOL(rtas_set_power_level); diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index aaf384c..1442b63 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -365,20 +365,12 @@ static int rtas_excl_release(struct inod static void manage_flash(struct rtas_manage_flash_t *args_buf) { - unsigned int wait_time; s32 rc; - while (1) { + do { rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, 1, NULL, args_buf->op); - if (rc == RTAS_RC_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } else - break; - } + } while (rtas_busy_delay(rc)); args_buf->status = rc; } @@ -451,27 +443,18 @@ static ssize_t manage_flash_write(struct static void validate_flash(struct rtas_validate_flash_t *args_buf) { int token = rtas_token("ibm,validate-flash-image"); - unsigned int wait_time; int update_results; s32 rc; rc = 0; - while(1) { + do { spin_lock(&rtas_data_buf_lock); memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE); rc = rtas_call(token, 2, 2, &update_results, (u32) __pa(rtas_data_buf), args_buf->buf_size); memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE); spin_unlock(&rtas_data_buf_lock); - - if (rc == RTAS_RC_BUSY) - udelay(1); - else if (rtas_is_extended_busy(rc)) { - wait_time = rtas_extended_busy_delay_time(rc); - udelay(wait_time * 1000); - } else - break; - } + } while (rtas_busy_delay(rc)); args_buf->status = rc; args_buf->update_results = update_results; diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 57b539a..6eb7e49 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -313,7 +313,9 @@ unsigned long __init find_and_init_phbs( for (node = of_get_next_child(root, NULL); node != NULL; node = of_get_next_child(root, node)) { - if (node->type == NULL || strcmp(node->type, "pci") != 0) + + if (node->type == NULL || (strcmp(node->type, "pci") != 0 && + strcmp(node->type, "pciex") != 0)) continue; phb = pcibios_alloc_controller(node); diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 684ab1d..bd32812 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -443,6 +443,7 @@ #endif /* CONFIG_PPC64 */ } #endif /* CONFIG_SMP */ +int __initdata do_early_xmon; #ifdef CONFIG_XMON static int __init early_xmon(char *p) { @@ -456,7 +457,7 @@ static int __init early_xmon(char *p) return 0; } xmon_init(1); - debugger(NULL); + do_early_xmon = 1; return 0; } @@ -524,3 +525,20 @@ int check_legacy_ioport(unsigned long ba return ppc_md.check_legacy_ioport(base_port); } EXPORT_SYMBOL(check_legacy_ioport); + +static int ppc_panic_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + ppc_md.panic(ptr); /* May not return */ + return NOTIFY_DONE; +} + +static struct notifier_block ppc_panic_block = { + .notifier_call = ppc_panic_event, + .priority = INT_MIN /* may not return; must be done last */ +}; + +void __init setup_panic(void) +{ + atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block); +} diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h index 2ebba75..4c67ad7 100644 --- a/arch/powerpc/kernel/setup.h +++ b/arch/powerpc/kernel/setup.h @@ -2,5 +2,8 @@ #ifndef _POWERPC_KERNEL_SETUP_H #define _POWERPC_KERNEL_SETUP_H void check_for_initrd(void); +void do_init_bootmem(void); +void setup_panic(void); +extern int do_early_xmon; #endif /* _POWERPC_KERNEL_SETUP_H */ diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 69ac257..e5a4481 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -131,12 +131,6 @@ #endif /* Do some early initialization based on the flat device tree */ early_init_devtree(__va(dt_ptr)); - /* Check default command line */ -#ifdef CONFIG_CMDLINE - if (cmd_line[0] == 0) - strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); -#endif /* CONFIG_CMDLINE */ - probe_machine(); #ifdef CONFIG_6xx @@ -235,7 +229,7 @@ arch_initcall(ppc_init); /* Warning, IO base is not yet inited */ void __init setup_arch(char **cmdline_p) { - extern void do_init_bootmem(void); + *cmdline_p = cmd_line; /* so udelay does something sensible, assume <= 1000 bogomips */ loops_per_jiffy = 500000000 / HZ; @@ -285,16 +279,16 @@ #endif /* reboot on panic */ panic_timeout = 180; + if (ppc_md.panic) + setup_panic(); + init_mm.start_code = PAGE_OFFSET; init_mm.end_code = (unsigned long) _etext; init_mm.end_data = (unsigned long) _edata; init_mm.brk = klimit; - /* Save unparsed command line copy for /proc/cmdline */ - strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); - *cmdline_p = cmd_line; - - parse_early_param(); + if (do_early_xmon) + debugger(NULL); /* set up the bootmem stuff with available memory */ do_init_bootmem(); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 4467c49..78f3a5f 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -100,12 +100,6 @@ unsigned long SYSRQ_KEY; #endif /* CONFIG_MAGIC_SYSRQ */ -static int ppc64_panic_event(struct notifier_block *, unsigned long, void *); -static struct notifier_block ppc64_panic_block = { - .notifier_call = ppc64_panic_event, - .priority = INT_MIN /* may not return; must be done last */ -}; - #ifdef CONFIG_SMP static int smt_enabled_cmdline; @@ -199,9 +193,7 @@ void __init early_setup(unsigned long dt /* Probe the machine type */ probe_machine(); -#ifdef CONFIG_CRASH_DUMP - kdump_setup(); -#endif + setup_kdump_trampoline(); DBG("Found, Initializing memory management...\n"); @@ -353,9 +345,6 @@ void __init setup_system(void) { DBG(" -> setup_system()\n"); -#ifdef CONFIG_KEXEC - kdump_move_device_tree(); -#endif /* * Unflatten the device-tree passed by prom_init or kexec */ @@ -420,10 +409,8 @@ #endif */ register_early_udbg_console(); - /* Save unparsed command line copy for /proc/cmdline */ - strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); - - parse_early_param(); + if (do_early_xmon) + debugger(NULL); check_smt_enabled(); smp_setup_cpu_maps(); @@ -456,13 +443,6 @@ #endif DBG(" <- setup_system()\n"); } -static int ppc64_panic_event(struct notifier_block *this, - unsigned long event, void *ptr) -{ - ppc_md.panic((char *)ptr); /* May not return */ - return NOTIFY_DONE; -} - #ifdef CONFIG_IRQSTACKS static void __init irqstack_early_init(void) { @@ -517,8 +497,6 @@ static void __init emergency_stack_init( */ void __init setup_arch(char **cmdline_p) { - extern void do_init_bootmem(void); - ppc64_boot_msg(0x12, "Setup Arch"); *cmdline_p = cmd_line; @@ -535,8 +513,7 @@ void __init setup_arch(char **cmdline_p) panic_timeout = 180; if (ppc_md.panic) - atomic_notifier_chain_register(&panic_notifier_list, - &ppc64_panic_block); + setup_panic(); init_mm.start_code = PAGE_OFFSET; init_mm.end_code = (unsigned long) _etext; diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 8fdeca2..d73b25e 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -419,9 +419,7 @@ static long restore_user_regs(struct pt_ { long err; unsigned int save_r2 = 0; -#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE) unsigned long msr; -#endif /* * restore general registers but not including MSR or SOFTE. Also @@ -430,11 +428,16 @@ #endif if (!sig) save_r2 = (unsigned int)regs->gpr[2]; err = restore_general_regs(regs, sr); + err |= __get_user(msr, &sr->mc_gregs[PT_MSR]); if (!sig) regs->gpr[2] = (unsigned long) save_r2; if (err) return 1; + /* if doing signal return, restore the previous little-endian mode */ + if (sig) + regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); + /* * Do this before updating the thread state in * current->thread.fpr/vr/evr. That way, if we get preempted @@ -455,7 +458,7 @@ #ifdef CONFIG_ALTIVEC /* force the process to reload the altivec registers from current->thread when it next does altivec instructions */ regs->msr &= ~MSR_VEC; - if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) { + if (msr & MSR_VEC) { /* restore altivec registers from the stack */ if (__copy_from_user(current->thread.vr, &sr->mc_vregs, sizeof(sr->mc_vregs))) @@ -472,7 +475,7 @@ #ifdef CONFIG_SPE /* force the process to reload the spe registers from current->thread when it next does spe instructions */ regs->msr &= ~MSR_SPE; - if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) { + if (msr & MSR_SPE) { /* restore spe registers from the stack */ if (__copy_from_user(current->thread.evr, &sr->mc_vregs, ELF_NEVRREG * sizeof(u32))) @@ -757,10 +760,10 @@ static int handle_rt_signal(unsigned lon /* Save user registers on the stack */ frame = &rt_sf->uc.uc_mcontext; - if (vdso32_rt_sigtramp && current->thread.vdso_base) { + if (vdso32_rt_sigtramp && current->mm->context.vdso_base) { if (save_user_regs(regs, frame, 0)) goto badframe; - regs->link = current->thread.vdso_base + vdso32_rt_sigtramp; + regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp; } else { if (save_user_regs(regs, frame, __NR_rt_sigreturn)) goto badframe; @@ -777,6 +780,8 @@ static int handle_rt_signal(unsigned lon regs->gpr[5] = (unsigned long) &rt_sf->uc; regs->gpr[6] = (unsigned long) rt_sf; regs->nip = (unsigned long) ka->sa.sa_handler; + /* enter the signal handler in big-endian mode */ + regs->msr &= ~MSR_LE; regs->trap = 0; return 1; @@ -1038,10 +1043,10 @@ #endif || __put_user(sig, &sc->signal)) goto badframe; - if (vdso32_sigtramp && current->thread.vdso_base) { + if (vdso32_sigtramp && current->mm->context.vdso_base) { if (save_user_regs(regs, &frame->mctx, 0)) goto badframe; - regs->link = current->thread.vdso_base + vdso32_sigtramp; + regs->link = current->mm->context.vdso_base + vdso32_sigtramp; } else { if (save_user_regs(regs, &frame->mctx, __NR_sigreturn)) goto badframe; @@ -1056,6 +1061,8 @@ #endif regs->gpr[3] = sig; regs->gpr[4] = (unsigned long) sc; regs->nip = (unsigned long) ka->sa.sa_handler; + /* enter the signal handler in big-endian mode */ + regs->msr &= ~MSR_LE; regs->trap = 0; return 1; diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index c2db642..6e75d7a 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -141,9 +141,7 @@ #endif unsigned long err = 0; unsigned long save_r13 = 0; elf_greg_t *gregs = (elf_greg_t *)regs; -#ifdef CONFIG_ALTIVEC unsigned long msr; -#endif int i; /* If this is not a signal return, we preserve the TLS in r13 */ @@ -154,7 +152,12 @@ #endif err |= __copy_from_user(regs, &sc->gp_regs, PT_MSR*sizeof(unsigned long)); - /* skip MSR and SOFTE */ + /* get MSR separately, transfer the LE bit if doing signal return */ + err |= __get_user(msr, &sc->gp_regs[PT_MSR]); + if (sig) + regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); + + /* skip SOFTE */ for (i = PT_MSR+1; i <= PT_RESULT; i++) { if (i == PT_SOFTE) continue; @@ -179,7 +182,6 @@ #endif #ifdef CONFIG_ALTIVEC err |= __get_user(v_regs, &sc->v_regs); - err |= __get_user(msr, &sc->gp_regs[PT_MSR]); if (err) return err; if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128))) @@ -396,8 +398,8 @@ static int setup_rt_frame(int signr, str current->thread.fpscr.val = 0; /* Set up to return from userspace. */ - if (vdso64_rt_sigtramp && current->thread.vdso_base) { - regs->link = current->thread.vdso_base + vdso64_rt_sigtramp; + if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { + regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) @@ -412,6 +414,8 @@ static int setup_rt_frame(int signr, str /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); + /* enter the signal handler in big-endian mode */ + regs->msr &= ~MSR_LE; regs->gpr[1] = newsp; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); regs->gpr[3] = signr; diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 530f7db..c5d179d 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -492,7 +492,7 @@ int __devinit __cpu_up(unsigned int cpu) * -- Cort */ if (system_state < SYSTEM_RUNNING) - for (c = 5000; c && !cpu_callin_map[cpu]; c--) + for (c = 50000; c && !cpu_callin_map[cpu]; c--) udelay(100); #ifdef CONFIG_HOTPLUG_CPU else diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 26ed1f5..ee75ccf 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -32,6 +32,10 @@ #define OLDSYS(func) .long sys_##func #define SYS32ONLY(func) .long sys_##func #define SYSX(f, f3264, f32) .long f32 #endif +#define SYSCALL_SPU(func) SYSCALL(func) +#define COMPAT_SYS_SPU(func) COMPAT_SYS(func) +#define PPC_SYS_SPU(func) PPC_SYS(func) +#define SYSX_SPU(f, f3264, f32) SYSX(f, f3264, f32) #ifdef CONFIG_PPC64 #define sys_sigpending sys_ni_syscall @@ -39,309 +43,4 @@ #define sys_old_getrlimit sys_ni_syscall #endif _GLOBAL(sys_call_table) -SYSCALL(restart_syscall) -SYSCALL(exit) -PPC_SYS(fork) -SYSCALL(read) -SYSCALL(write) -COMPAT_SYS(open) -SYSCALL(close) -COMPAT_SYS(waitpid) -COMPAT_SYS(creat) -SYSCALL(link) -SYSCALL(unlink) -COMPAT_SYS(execve) -SYSCALL(chdir) -COMPAT_SYS(time) -SYSCALL(mknod) -SYSCALL(chmod) -SYSCALL(lchown) -SYSCALL(ni_syscall) -OLDSYS(stat) -SYSX(sys_lseek,ppc32_lseek,sys_lseek) -SYSCALL(getpid) -COMPAT_SYS(mount) -SYSX(sys_ni_syscall,sys_oldumount,sys_oldumount) -SYSCALL(setuid) -SYSCALL(getuid) -COMPAT_SYS(stime) -COMPAT_SYS(ptrace) -SYSCALL(alarm) -OLDSYS(fstat) -COMPAT_SYS(pause) -COMPAT_SYS(utime) -SYSCALL(ni_syscall) -SYSCALL(ni_syscall) -COMPAT_SYS(access) -COMPAT_SYS(nice) -SYSCALL(ni_syscall) -SYSCALL(sync) -COMPAT_SYS(kill) -SYSCALL(rename) -COMPAT_SYS(mkdir) -SYSCALL(rmdir) -SYSCALL(dup) -SYSCALL(pipe) -COMPAT_SYS(times) -SYSCALL(ni_syscall) -SYSCALL(brk) -SYSCALL(setgid) -SYSCALL(getgid) -SYSCALL(signal) -SYSCALL(geteuid) -SYSCALL(getegid) -SYSCALL(acct) -SYSCALL(umount) -SYSCALL(ni_syscall) -COMPAT_SYS(ioctl) -COMPAT_SYS(fcntl) -SYSCALL(ni_syscall) -COMPAT_SYS(setpgid) -SYSCALL(ni_syscall) -SYSX(sys_ni_syscall,sys_olduname, sys_olduname) -COMPAT_SYS(umask) -SYSCALL(chroot) -SYSCALL(ustat) -SYSCALL(dup2) -SYSCALL(getppid) -SYSCALL(getpgrp) -SYSCALL(setsid) -SYS32ONLY(sigaction) -SYSCALL(sgetmask) -COMPAT_SYS(ssetmask) -SYSCALL(setreuid) -SYSCALL(setregid) -SYS32ONLY(sigsuspend) -COMPAT_SYS(sigpending) -COMPAT_SYS(sethostname) -COMPAT_SYS(setrlimit) -COMPAT_SYS(old_getrlimit) -COMPAT_SYS(getrusage) -COMPAT_SYS(gettimeofday) -COMPAT_SYS(settimeofday) -COMPAT_SYS(getgroups) -COMPAT_SYS(setgroups) -SYSX(sys_ni_syscall,sys_ni_syscall,ppc_select) -SYSCALL(symlink) -OLDSYS(lstat) -COMPAT_SYS(readlink) -SYSCALL(uselib) -SYSCALL(swapon) -SYSCALL(reboot) -SYSX(sys_ni_syscall,old32_readdir,old_readdir) -SYSCALL(mmap) -SYSCALL(munmap) -SYSCALL(truncate) -SYSCALL(ftruncate) -SYSCALL(fchmod) -SYSCALL(fchown) -COMPAT_SYS(getpriority) -COMPAT_SYS(setpriority) -SYSCALL(ni_syscall) -COMPAT_SYS(statfs) -COMPAT_SYS(fstatfs) -SYSCALL(ni_syscall) -COMPAT_SYS(socketcall) -COMPAT_SYS(syslog) -COMPAT_SYS(setitimer) -COMPAT_SYS(getitimer) -COMPAT_SYS(newstat) -COMPAT_SYS(newlstat) -COMPAT_SYS(newfstat) -SYSX(sys_ni_syscall,sys_uname,sys_uname) -SYSCALL(ni_syscall) -SYSCALL(vhangup) -SYSCALL(ni_syscall) -SYSCALL(ni_syscall) -COMPAT_SYS(wait4) -SYSCALL(swapoff) -COMPAT_SYS(sysinfo) -COMPAT_SYS(ipc) -SYSCALL(fsync) -SYS32ONLY(sigreturn) -PPC_SYS(clone) -COMPAT_SYS(setdomainname) -PPC_SYS(newuname) -SYSCALL(ni_syscall) -COMPAT_SYS(adjtimex) -SYSCALL(mprotect) -SYSX(sys_ni_syscall,compat_sys_sigprocmask,sys_sigprocmask) -SYSCALL(ni_syscall) -SYSCALL(init_module) -SYSCALL(delete_module) -SYSCALL(ni_syscall) -SYSCALL(quotactl) -COMPAT_SYS(getpgid) -SYSCALL(fchdir) -SYSCALL(bdflush) -COMPAT_SYS(sysfs) -SYSX(ppc64_personality,ppc64_personality,sys_personality) -SYSCALL(ni_syscall) -SYSCALL(setfsuid) -SYSCALL(setfsgid) -SYSCALL(llseek) -COMPAT_SYS(getdents) -SYSX(sys_select,ppc32_select,ppc_select) -SYSCALL(flock) -SYSCALL(msync) -COMPAT_SYS(readv) -COMPAT_SYS(writev) -COMPAT_SYS(getsid) -SYSCALL(fdatasync) -COMPAT_SYS(sysctl) -SYSCALL(mlock) -SYSCALL(munlock) -SYSCALL(mlockall) -SYSCALL(munlockall) -COMPAT_SYS(sched_setparam) -COMPAT_SYS(sched_getparam) -COMPAT_SYS(sched_setscheduler) -COMPAT_SYS(sched_getscheduler) -SYSCALL(sched_yield) -COMPAT_SYS(sched_get_priority_max) -COMPAT_SYS(sched_get_priority_min) -COMPAT_SYS(sched_rr_get_interval) -COMPAT_SYS(nanosleep) -SYSCALL(mremap) -SYSCALL(setresuid) -SYSCALL(getresuid) -SYSCALL(ni_syscall) -SYSCALL(poll) -COMPAT_SYS(nfsservctl) -SYSCALL(setresgid) -SYSCALL(getresgid) -COMPAT_SYS(prctl) -COMPAT_SYS(rt_sigreturn) -COMPAT_SYS(rt_sigaction) -COMPAT_SYS(rt_sigprocmask) -COMPAT_SYS(rt_sigpending) -COMPAT_SYS(rt_sigtimedwait) -COMPAT_SYS(rt_sigqueueinfo) -COMPAT_SYS(rt_sigsuspend) -COMPAT_SYS(pread64) -COMPAT_SYS(pwrite64) -SYSCALL(chown) -SYSCALL(getcwd) -SYSCALL(capget) -SYSCALL(capset) -COMPAT_SYS(sigaltstack) -SYSX(sys_sendfile64,compat_sys_sendfile,sys_sendfile) -SYSCALL(ni_syscall) -SYSCALL(ni_syscall) -PPC_SYS(vfork) -COMPAT_SYS(getrlimit) -COMPAT_SYS(readahead) -SYS32ONLY(mmap2) -SYS32ONLY(truncate64) -SYS32ONLY(ftruncate64) -SYSX(sys_ni_syscall,sys_stat64,sys_stat64) -SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64) -SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64) -SYSCALL(pciconfig_read) -SYSCALL(pciconfig_write) -SYSCALL(pciconfig_iobase) -SYSCALL(ni_syscall) -SYSCALL(getdents64) -SYSCALL(pivot_root) -SYSX(sys_ni_syscall,compat_sys_fcntl64,sys_fcntl64) -SYSCALL(madvise) -SYSCALL(mincore) -SYSCALL(gettid) -SYSCALL(tkill) -SYSCALL(setxattr) -SYSCALL(lsetxattr) -SYSCALL(fsetxattr) -SYSCALL(getxattr) -SYSCALL(lgetxattr) -SYSCALL(fgetxattr) -SYSCALL(listxattr) -SYSCALL(llistxattr) -SYSCALL(flistxattr) -SYSCALL(removexattr) -SYSCALL(lremovexattr) -SYSCALL(fremovexattr) -COMPAT_SYS(futex) -COMPAT_SYS(sched_setaffinity) -COMPAT_SYS(sched_getaffinity) -SYSCALL(ni_syscall) -SYSCALL(ni_syscall) -SYS32ONLY(sendfile64) -COMPAT_SYS(io_setup) -SYSCALL(io_destroy) -COMPAT_SYS(io_getevents) -COMPAT_SYS(io_submit) -SYSCALL(io_cancel) -SYSCALL(set_tid_address) -SYSX(sys_fadvise64,ppc32_fadvise64,sys_fadvise64) -SYSCALL(exit_group) -SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie) -SYSCALL(epoll_create) -SYSCALL(epoll_ctl) -SYSCALL(epoll_wait) -SYSCALL(remap_file_pages) -SYSX(sys_timer_create,compat_sys_timer_create,sys_timer_create) -COMPAT_SYS(timer_settime) -COMPAT_SYS(timer_gettime) -SYSCALL(timer_getoverrun) -SYSCALL(timer_delete) -COMPAT_SYS(clock_settime) -COMPAT_SYS(clock_gettime) -COMPAT_SYS(clock_getres) -COMPAT_SYS(clock_nanosleep) -SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext) -COMPAT_SYS(tgkill) -COMPAT_SYS(utimes) -COMPAT_SYS(statfs64) -COMPAT_SYS(fstatfs64) -SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64) -PPC_SYS(rtas) -OLDSYS(debug_setcontext) -SYSCALL(ni_syscall) -SYSCALL(ni_syscall) -COMPAT_SYS(mbind) -COMPAT_SYS(get_mempolicy) -COMPAT_SYS(set_mempolicy) -COMPAT_SYS(mq_open) -SYSCALL(mq_unlink) -COMPAT_SYS(mq_timedsend) -COMPAT_SYS(mq_timedreceive) -COMPAT_SYS(mq_notify) -COMPAT_SYS(mq_getsetattr) -COMPAT_SYS(kexec_load) -COMPAT_SYS(add_key) -COMPAT_SYS(request_key) -COMPAT_SYS(keyctl) -COMPAT_SYS(waitid) -COMPAT_SYS(ioprio_set) -COMPAT_SYS(ioprio_get) -SYSCALL(inotify_init) -SYSCALL(inotify_add_watch) -SYSCALL(inotify_rm_watch) -SYSCALL(spu_run) -SYSCALL(spu_create) -COMPAT_SYS(pselect6) -COMPAT_SYS(ppoll) -SYSCALL(unshare) -SYSCALL(splice) -SYSCALL(tee) -SYSCALL(vmsplice) -COMPAT_SYS(openat) -SYSCALL(mkdirat) -SYSCALL(mknodat) -SYSCALL(fchownat) -COMPAT_SYS(futimesat) -SYSX(sys_newfstatat, sys_fstatat64, sys_fstatat64) -SYSCALL(unlinkat) -SYSCALL(renameat) -SYSCALL(linkat) -SYSCALL(symlinkat) -SYSCALL(readlinkat) -SYSCALL(fchmodat) -SYSCALL(faccessat) -COMPAT_SYS(get_robust_list) -COMPAT_SYS(set_robust_list) - -/* - * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c - * as well when appropriate. - */ +#include diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 24e3ad7..7dd5dab 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -76,7 +76,6 @@ #include /* keep track of when we need to update the rtc */ time_t last_rtc_update; -extern int piranha_simulator; #ifdef CONFIG_PPC_ISERIES unsigned long iSeries_recal_titan = 0; unsigned long iSeries_recal_tb = 0; @@ -103,7 +102,7 @@ EXPORT_SYMBOL(tb_ticks_per_sec); /* for u64 tb_to_xs; unsigned tb_to_us; -#define TICKLEN_SCALE (SHIFT_SCALE - 10) +#define TICKLEN_SCALE TICK_LENGTH_SHIFT u64 last_tick_len; /* units are ns / 2^TICKLEN_SCALE */ u64 ticklen_to_xs; /* 0.64 fraction */ @@ -858,42 +857,50 @@ #endif EXPORT_SYMBOL(do_settimeofday); -void __init generic_calibrate_decr(void) +static int __init get_freq(char *name, int cells, unsigned long *val) { struct device_node *cpu; unsigned int *fp; - int node_found; + int found = 0; - /* - * The cpu node should have a timebase-frequency property - * to tell us the rate at which the decrementer counts. - */ + /* The cpu node should have timebase and clock frequency properties */ cpu = of_find_node_by_type(NULL, "cpu"); - ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */ - node_found = 0; if (cpu) { - fp = (unsigned int *)get_property(cpu, "timebase-frequency", - NULL); + fp = (unsigned int *)get_property(cpu, name, NULL); if (fp) { - node_found = 1; - ppc_tb_freq = *fp; + found = 1; + *val = 0; + while (cells--) + *val = (*val << 32) | *fp++; } + + of_node_put(cpu); } - if (!node_found) + + return found; +} + +void __init generic_calibrate_decr(void) +{ + ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */ + + if (!get_freq("ibm,extended-timebase-frequency", 2, &ppc_tb_freq) && + !get_freq("timebase-frequency", 1, &ppc_tb_freq)) { + printk(KERN_ERR "WARNING: Estimating decrementer frequency " "(not found)\n"); + } - ppc_proc_freq = DEFAULT_PROC_FREQ; - node_found = 0; - if (cpu) { - fp = (unsigned int *)get_property(cpu, "clock-frequency", - NULL); - if (fp) { - node_found = 1; - ppc_proc_freq = *fp; - } + ppc_proc_freq = DEFAULT_PROC_FREQ; /* hardcoded default */ + + if (!get_freq("ibm,extended-clock-frequency", 2, &ppc_proc_freq) && + !get_freq("clock-frequency", 1, &ppc_proc_freq)) { + + printk(KERN_ERR "WARNING: Estimating processor frequency " + "(not found)\n"); } + #ifdef CONFIG_BOOKE /* Set the time base to zero */ mtspr(SPRN_TBWL, 0); @@ -905,11 +912,6 @@ #ifdef CONFIG_BOOKE /* Enable decrementer interrupt */ mtspr(SPRN_TCR, TCR_DIE); #endif - if (!node_found) - printk(KERN_ERR "WARNING: Estimating processor frequency " - "(not found)\n"); - - of_node_put(cpu); } unsigned long get_boot_time(void) @@ -945,9 +947,9 @@ void __init time_init(void) } else { /* Normal PowerPC with timebase register */ ppc_md.calibrate_decr(); - printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n", + printk(KERN_DEBUG "time_init: decrementer frequency = %lu.%.6lu MHz\n", ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); - printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n", + printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n", ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); tb_last_stamp = tb_last_jiffy = get_tb(); } @@ -1010,10 +1012,7 @@ void __init time_init(void) tb_to_ns_scale = scale; tb_to_ns_shift = shift; -#ifdef CONFIG_PPC_ISERIES - if (!piranha_simulator) -#endif - tm = get_boot_time(); + tm = get_boot_time(); write_seqlock_irqsave(&xtime_lock, flags); diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 064a525..52f5659 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -32,6 +32,7 @@ #include #include #include #include +#include #include #include @@ -105,10 +106,18 @@ int die(const char *str, struct pt_regs spin_lock_irq(&die_lock); bust_spinlocks(1); #ifdef CONFIG_PMAC_BACKLIGHT - if (machine_is(powermac)) { - set_backlight_enable(1); - set_backlight_level(BACKLIGHT_MAX); + mutex_lock(&pmac_backlight_mutex); + if (machine_is(powermac) && pmac_backlight) { + struct backlight_properties *props; + + down(&pmac_backlight->sem); + props = pmac_backlight->props; + props->brightness = props->max_brightness; + props->power = FB_BLANK_UNBLANK; + props->update_status(pmac_backlight); + up(&pmac_backlight->sem); } + mutex_unlock(&pmac_backlight_mutex); #endif printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); #ifdef CONFIG_PREEMPT @@ -658,7 +667,7 @@ static int emulate_instruction(struct pt u32 instword; u32 rd; - if (!user_mode(regs)) + if (!user_mode(regs) || (regs->msr & MSR_LE)) return -EINVAL; CHECK_FULL_REGS(regs); @@ -805,9 +814,11 @@ #endif /* CONFIG_MATH_EMULATION */ void alignment_exception(struct pt_regs *regs) { - int fixed; + int fixed = 0; - fixed = fix_alignment(regs); + /* we don't implement logging of alignment exceptions */ + if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) + fixed = fix_alignment(regs); if (fixed == 1) { regs->nip += 4; /* skip over emulated instruction */ diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 3774e80..67d9fd9 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c @@ -14,6 +14,7 @@ #include #include #include #include +#include #include #include @@ -141,12 +142,14 @@ static int early_console_initialized; void __init disable_early_printk(void) { -#if 1 if (!early_console_initialized) return; + if (strstr(saved_command_line, "udbg-immortal")) { + printk(KERN_INFO "early console immortal !\n"); + return; + } unregister_console(&udbg_console); early_console_initialized = 0; -#endif } /* called by setup_system */ diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 573afb6..bc3e15b 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -223,6 +223,7 @@ int arch_setup_additional_pages(struct l struct vm_area_struct *vma; unsigned long vdso_pages; unsigned long vdso_base; + int rc; #ifdef CONFIG_PPC64 if (test_thread_flag(TIF_32BIT)) { @@ -237,20 +238,13 @@ #else vdso_base = VDSO32_MBASE; #endif - current->thread.vdso_base = 0; + current->mm->context.vdso_base = 0; /* vDSO has a problem and was disabled, just don't "enable" it for the * process */ if (vdso_pages == 0) return 0; - - vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); - if (vma == NULL) - return -ENOMEM; - - memset(vma, 0, sizeof(*vma)); - /* Add a page to the vdso size for the data page */ vdso_pages ++; @@ -259,17 +253,23 @@ #endif * at vdso_base which is the "natural" base for it, but we might fail * and end up putting it elsewhere. */ + down_write(&mm->mmap_sem); vdso_base = get_unmapped_area(NULL, vdso_base, vdso_pages << PAGE_SHIFT, 0, 0); - if (vdso_base & ~PAGE_MASK) { - kmem_cache_free(vm_area_cachep, vma); - return (int)vdso_base; + if (IS_ERR_VALUE(vdso_base)) { + rc = vdso_base; + goto fail_mmapsem; } - current->thread.vdso_base = vdso_base; + /* Allocate a VMA structure and fill it up */ + vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL); + if (vma == NULL) { + rc = -ENOMEM; + goto fail_mmapsem; + } vma->vm_mm = mm; - vma->vm_start = current->thread.vdso_base; + vma->vm_start = vdso_base; vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT); /* @@ -282,23 +282,38 @@ #endif * It's fine to use that for setting breakpoints in the vDSO code * pages though */ - vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; + vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC; vma->vm_flags |= mm->def_flags; vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; vma->vm_ops = &vdso_vmops; - down_write(&mm->mmap_sem); - if (insert_vm_struct(mm, vma)) { - up_write(&mm->mmap_sem); - kmem_cache_free(vm_area_cachep, vma); - return -ENOMEM; - } + /* Insert new VMA */ + rc = insert_vm_struct(mm, vma); + if (rc) + goto fail_vma; + + /* Put vDSO base into mm struct and account for memory usage */ + current->mm->context.vdso_base = vdso_base; mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; up_write(&mm->mmap_sem); - return 0; + + fail_vma: + kmem_cache_free(vm_area_cachep, vma); + fail_mmapsem: + up_write(&mm->mmap_sem); + return rc; +} + +const char *arch_vma_name(struct vm_area_struct *vma) +{ + if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base) + return "[vdso]"; + return NULL; } + + static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname, unsigned long *size) { diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index 66b3d03..9416b4a 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S @@ -53,12 +53,12 @@ #endif stfd fr31,8(r1) LDCONST(fr1, fpzero) mffs fr31 - mtfsf 0xff,fr1 + MTFSF_L(fr1) blr fpdisable: mtlr r12 - mtfsf 0xff,fr31 + MTFSF_L(fr31) lfd fr31,8(r1) lfd fr1,16(r1) lfd fr0,24(r1) diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 971020c..cdf5867 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -13,27 +13,116 @@ * 2 of the License, or (at your option) any later version. */ +#include +#include #include #include #include #include #include +#include + #include #include #include #include - -static const struct vio_device_id *vio_match_device( - const struct vio_device_id *, const struct vio_dev *); - -struct vio_dev vio_bus_device = { /* fake "parent" device */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct subsystem devices_subsys; /* needed for vio_find_name() */ + +static struct vio_dev vio_bus_device = { /* fake "parent" device */ .name = vio_bus_device.dev.bus_id, .type = "", .dev.bus_id = "vio", .dev.bus = &vio_bus_type, }; -static struct vio_bus_ops vio_bus_ops; +#ifdef CONFIG_PPC_ISERIES +struct device *iSeries_vio_dev = &vio_bus_device.dev; +EXPORT_SYMBOL(iSeries_vio_dev); + +static struct iommu_table veth_iommu_table; +static struct iommu_table vio_iommu_table; + +static void __init iommu_vio_init(void) +{ + iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); + veth_iommu_table.it_size /= 2; + vio_iommu_table = veth_iommu_table; + vio_iommu_table.it_offset += veth_iommu_table.it_size; + + if (!iommu_init_table(&veth_iommu_table, -1)) + printk("Virtual Bus VETH TCE table failed.\n"); + if (!iommu_init_table(&vio_iommu_table, -1)) + printk("Virtual Bus VIO TCE table failed.\n"); +} +#endif + +static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) +{ +#ifdef CONFIG_PPC_ISERIES + if (firmware_has_feature(FW_FEATURE_ISERIES)) { + if (strcmp(dev->type, "network") == 0) + return &veth_iommu_table; + return &vio_iommu_table; + } else +#endif + { + unsigned char *dma_window; + struct iommu_table *tbl; + unsigned long offset, size; + + dma_window = get_property(dev->dev.platform_data, + "ibm,my-dma-window", NULL); + if (!dma_window) + return NULL; + + tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); + + of_parse_dma_window(dev->dev.platform_data, dma_window, + &tbl->it_index, &offset, &size); + + /* TCE table size - measured in tce entries */ + tbl->it_size = size >> PAGE_SHIFT; + /* offset for VIO should always be 0 */ + tbl->it_offset = offset >> PAGE_SHIFT; + tbl->it_busno = 0; + tbl->it_type = TCE_VB; + + return iommu_init_table(tbl, -1); + } +} + +/** + * vio_match_device: - Tell if a VIO device has a matching + * VIO device id structure. + * @ids: array of VIO device id structures to search in + * @dev: the VIO device structure to match against + * + * Used by a driver to check whether a VIO device present in the + * system is in its list of supported devices. Returns the matching + * vio_device_id structure or NULL if there is no match. + */ +static const struct vio_device_id *vio_match_device( + const struct vio_device_id *ids, const struct vio_dev *dev) +{ + while (ids->type[0] != '\0') { + if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && + device_is_compatible(dev->dev.platform_data, ids->compat)) + return ids; + ids++; + } + return NULL; +} /* * Convert from struct device to struct vio_dev and pass to driver. @@ -106,35 +195,110 @@ void vio_unregister_driver(struct vio_dr } EXPORT_SYMBOL(vio_unregister_driver); +/* vio_dev refcount hit 0 */ +static void __devinit vio_dev_release(struct device *dev) +{ + if (dev->platform_data) { + /* XXX free TCE table */ + of_node_put(dev->platform_data); + } + kfree(to_vio_dev(dev)); +} + /** - * vio_match_device: - Tell if a VIO device has a matching - * VIO device id structure. - * @ids: array of VIO device id structures to search in - * @dev: the VIO device structure to match against + * vio_register_device_node: - Register a new vio device. + * @of_node: The OF node for this device. * - * Used by a driver to check whether a VIO device present in the - * system is in its list of supported devices. Returns the matching - * vio_device_id structure or NULL if there is no match. + * Creates and initializes a vio_dev structure from the data in + * of_node (dev.platform_data) and adds it to the list of virtual devices. + * Returns a pointer to the created vio_dev or NULL if node has + * NULL device_type or compatible fields. */ -static const struct vio_device_id *vio_match_device( - const struct vio_device_id *ids, const struct vio_dev *dev) +struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) { - while (ids->type[0] != '\0') { - if (vio_bus_ops.match(ids, dev)) - return ids; - ids++; + struct vio_dev *viodev; + unsigned int *unit_address; + unsigned int *irq_p; + + /* we need the 'device_type' property, in order to match with drivers */ + if (of_node->type == NULL) { + printk(KERN_WARNING "%s: node %s missing 'device_type'\n", + __FUNCTION__, + of_node->name ? of_node->name : ""); + return NULL; } - return NULL; + + unit_address = (unsigned int *)get_property(of_node, "reg", NULL); + if (unit_address == NULL) { + printk(KERN_WARNING "%s: node %s missing 'reg'\n", + __FUNCTION__, + of_node->name ? of_node->name : ""); + return NULL; + } + + /* allocate a vio_dev for this node */ + viodev = kzalloc(sizeof(struct vio_dev), GFP_KERNEL); + if (viodev == NULL) + return NULL; + + viodev->dev.platform_data = of_node_get(of_node); + + viodev->irq = NO_IRQ; + irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL); + if (irq_p) { + int virq = virt_irq_create_mapping(*irq_p); + if (virq == NO_IRQ) { + printk(KERN_ERR "Unable to allocate interrupt " + "number for %s\n", of_node->full_name); + } else + viodev->irq = irq_offset_up(virq); + } + + snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); + viodev->name = of_node->name; + viodev->type = of_node->type; + viodev->unit_address = *unit_address; + if (firmware_has_feature(FW_FEATURE_ISERIES)) { + unit_address = (unsigned int *)get_property(of_node, + "linux,unit_address", NULL); + if (unit_address != NULL) + viodev->unit_address = *unit_address; + } + viodev->iommu_table = vio_build_iommu_table(viodev); + + /* init generic 'struct device' fields: */ + viodev->dev.parent = &vio_bus_device.dev; + viodev->dev.bus = &vio_bus_type; + viodev->dev.release = vio_dev_release; + + /* register with generic device framework */ + if (device_register(&viodev->dev)) { + printk(KERN_ERR "%s: failed to register device %s\n", + __FUNCTION__, viodev->dev.bus_id); + /* XXX free TCE table */ + kfree(viodev); + return NULL; + } + + return viodev; } +EXPORT_SYMBOL(vio_register_device_node); /** * vio_bus_init: - Initialize the virtual IO bus */ -int __init vio_bus_init(struct vio_bus_ops *ops) +static int __init vio_bus_init(void) { int err; + struct device_node *node_vroot; - vio_bus_ops = *ops; +#ifdef CONFIG_PPC_ISERIES + if (firmware_has_feature(FW_FEATURE_ISERIES)) { + iommu_vio_init(); + vio_bus_device.iommu_table = &vio_iommu_table; + iSeries_vio_dev = &vio_bus_device.dev; + } +#endif err = bus_register(&vio_bus_type); if (err) { @@ -153,47 +317,48 @@ int __init vio_bus_init(struct vio_bus_o return err; } - return 0; -} + node_vroot = find_devices("vdevice"); + if (node_vroot) { + struct device_node *of_node; + + /* + * Create struct vio_devices for each virtual device in + * the device tree. Drivers will associate with them later. + */ + for (of_node = node_vroot->child; of_node != NULL; + of_node = of_node->sibling) { + printk(KERN_DEBUG "%s: processing %p\n", + __FUNCTION__, of_node); + vio_register_device_node(of_node); + } + } -/* vio_dev refcount hit 0 */ -static void __devinit vio_dev_release(struct device *dev) -{ - if (vio_bus_ops.release_device) - vio_bus_ops.release_device(dev); - kfree(to_vio_dev(dev)); + return 0; } +__initcall(vio_bus_init); -static ssize_t viodev_show_name(struct device *dev, +static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", to_vio_dev(dev)->name); } -DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL); -struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev) +static ssize_t devspec_show(struct device *dev, + struct device_attribute *attr, char *buf) { - /* init generic 'struct device' fields: */ - viodev->dev.parent = &vio_bus_device.dev; - viodev->dev.bus = &vio_bus_type; - viodev->dev.release = vio_dev_release; - - /* register with generic device framework */ - if (device_register(&viodev->dev)) { - printk(KERN_ERR "%s: failed to register device %s\n", - __FUNCTION__, viodev->dev.bus_id); - return NULL; - } - device_create_file(&viodev->dev, &dev_attr_name); + struct device_node *of_node = dev->platform_data; - return viodev; + return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none"); } +static struct device_attribute vio_dev_attrs[] = { + __ATTR_RO(name), + __ATTR_RO(devspec), + __ATTR_NULL +}; + void __devinit vio_unregister_device(struct vio_dev *viodev) { - if (vio_bus_ops.unregister_device) - vio_bus_ops.unregister_device(viodev); - device_remove_file(&viodev->dev, &dev_attr_name); device_unregister(&viodev->dev); } EXPORT_SYMBOL(vio_unregister_device); @@ -229,7 +394,7 @@ static void *vio_alloc_coherent(struct d dma_addr_t *dma_handle, gfp_t flag) { return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, - dma_handle, ~0ul, flag); + dma_handle, ~0ul, flag, -1); } static void vio_free_coherent(struct device *dev, size_t size, @@ -267,22 +432,23 @@ static int vio_hotplug(struct device *de char *buffer, int buffer_size) { const struct vio_dev *vio_dev = to_vio_dev(dev); + struct device_node *dn = dev->platform_data; char *cp; int length; if (!num_envp) return -ENOMEM; - if (!vio_dev->dev.platform_data) + if (!dn) return -ENODEV; - cp = (char *)get_property(vio_dev->dev.platform_data, "compatible", &length); + cp = (char *)get_property(dn, "compatible", &length); if (!cp) return -ENODEV; envp[0] = buffer; length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s", vio_dev->type, cp); - if (buffer_size - length <= 0) + if ((buffer_size - length) <= 0) return -ENOMEM; envp[1] = NULL; return 0; @@ -290,9 +456,81 @@ static int vio_hotplug(struct device *de struct bus_type vio_bus_type = { .name = "vio", + .dev_attrs = vio_dev_attrs, .uevent = vio_hotplug, .match = vio_bus_match, .probe = vio_bus_probe, .remove = vio_bus_remove, .shutdown = vio_bus_shutdown, }; + +/** + * vio_get_attribute: - get attribute for virtual device + * @vdev: The vio device to get property. + * @which: The property/attribute to be extracted. + * @length: Pointer to length of returned data size (unused if NULL). + * + * Calls prom.c's get_property() to return the value of the + * attribute specified by @which +*/ +const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) +{ + return get_property(vdev->dev.platform_data, which, length); +} +EXPORT_SYMBOL(vio_get_attribute); + +#ifdef CONFIG_PPC_PSERIES +/* vio_find_name() - internal because only vio.c knows how we formatted the + * kobject name + * XXX once vio_bus_type.devices is actually used as a kset in + * drivers/base/bus.c, this function should be removed in favor of + * "device_find(kobj_name, &vio_bus_type)" + */ +static struct vio_dev *vio_find_name(const char *kobj_name) +{ + struct kobject *found; + + found = kset_find_obj(&devices_subsys.kset, kobj_name); + if (!found) + return NULL; + + return to_vio_dev(container_of(found, struct device, kobj)); +} + +/** + * vio_find_node - find an already-registered vio_dev + * @vnode: device_node of the virtual device we're looking for + */ +struct vio_dev *vio_find_node(struct device_node *vnode) +{ + uint32_t *unit_address; + char kobj_name[BUS_ID_SIZE]; + + /* construct the kobject name from the device node */ + unit_address = (uint32_t *)get_property(vnode, "reg", NULL); + if (!unit_address) + return NULL; + snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); + + return vio_find_name(kobj_name); +} +EXPORT_SYMBOL(vio_find_node); + +int vio_enable_interrupts(struct vio_dev *dev) +{ + int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE); + if (rc != H_SUCCESS) + printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc); + return rc; +} +EXPORT_SYMBOL(vio_enable_interrupts); + +int vio_disable_interrupts(struct vio_dev *dev) +{ + int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE); + if (rc != H_SUCCESS) + printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc); + return rc; +} +EXPORT_SYMBOL(vio_disable_interrupts); +#endif /* CONFIG_PPC_PSERIES */ diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index fe79c25..8b25953 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -93,6 +93,11 @@ #endif /* CONFIG_PPC32 */ __ptov_table_begin = .; *(.ptov_fixup); __ptov_table_end = .; +#ifdef CONFIG_PPC_ISERIES + __dt_strings_start = .; + *(.dt_strings); + __dt_strings_end = .; +#endif } . = ALIGN(16); diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 34f5c2e..ff70964 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -2,12 +2,15 @@ # # Makefile for ppc-specific library files.. # +ifeq ($(CONFIG_PPC64),y) +EXTRA_CFLAGS += -mno-minimal-toc +endif + ifeq ($(CONFIG_PPC_MERGE),y) obj-y := string.o strcase.o obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o endif -obj-y += bitops.o obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \ memcpy_64.o usercopy_64.o mem_64.o string.o \ strcase.o diff --git a/arch/powerpc/lib/bitops.c b/arch/powerpc/lib/bitops.c deleted file mode 100644 index f68ad71..0000000 --- a/arch/powerpc/lib/bitops.c +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include -#include -#include - -/** - * find_next_bit - find the next set bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search - */ -unsigned long find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + BITOP_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG-1); - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset %= BITS_PER_LONG; - if (offset) { - tmp = *(p++); - tmp &= (~0UL << offset); - if (size < BITS_PER_LONG) - goto found_first; - if (tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - while (size & ~(BITS_PER_LONG-1)) { - if ((tmp = *(p++))) - goto found_middle; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp &= (~0UL >> (BITS_PER_LONG - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); -} -EXPORT_SYMBOL(find_next_bit); - -/* - * This implementation of find_{first,next}_zero_bit was stolen from - * Linus' asm-alpha/bitops.h. - */ -unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + BITOP_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG-1); - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset %= BITS_PER_LONG; - if (offset) { - tmp = *(p++); - tmp |= ~0UL >> (BITS_PER_LONG - offset); - if (size < BITS_PER_LONG) - goto found_first; - if (~tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - while (size & ~(BITS_PER_LONG-1)) { - if (~(tmp = *(p++))) - goto found_middle; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} -EXPORT_SYMBOL(find_next_zero_bit); - -static inline unsigned int ext2_ilog2(unsigned int x) -{ - int lz; - - asm("cntlzw %0,%1": "=r"(lz):"r"(x)); - return 31 - lz; -} - -static inline unsigned int ext2_ffz(unsigned int x) -{ - u32 rc; - if ((x = ~x) == 0) - return 32; - rc = ext2_ilog2(x & -x); - return rc; -} - -unsigned long find_next_zero_le_bit(const unsigned long *addr, - unsigned long size, unsigned long offset) -{ - const unsigned int *p = ((const unsigned int *)addr) + (offset >> 5); - unsigned int result = offset & ~31; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31; - if (offset) { - tmp = cpu_to_le32p(p++); - tmp |= ~0U >> (32 - offset); /* bug or feature ? */ - if (size < 32) - goto found_first; - if (tmp != ~0) - goto found_middle; - size -= 32; - result += 32; - } - while (size >= 32) { - if ((tmp = cpu_to_le32p(p++)) != ~0) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = cpu_to_le32p(p); -found_first: - tmp |= ~0 << size; - if (tmp == ~0) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ext2_ffz(tmp); -} -EXPORT_SYMBOL(find_next_zero_le_bit); diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index fdbba42..a0a9e1e 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -40,6 +40,40 @@ #include #include #include +#ifdef CONFIG_KPROBES +ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); + +/* Hook to register for page fault notifications */ +int register_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); +} + +int unregister_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); +} + +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + struct die_args args = { + .regs = regs, + .str = str, + .err = err, + .trapnr = trap, + .signr = sig + }; + return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); +} +#else +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + return NOTIFY_DONE; +} +#endif + /* * Check whether the instruction at regs->nip is a store using * an update addressing form which will update r1. @@ -142,7 +176,7 @@ #else is_write = error_code & ESR_DST; #endif /* CONFIG_4xx || CONFIG_BOOKE */ - if (notify_die(DIE_PAGE_FAULT, "page_fault", regs, error_code, + if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, error_code, 11, SIGSEGV) == NOTIFY_STOP) return 0; diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S index ea469ee..94255be 100644 --- a/arch/powerpc/mm/hash_low_32.S +++ b/arch/powerpc/mm/hash_low_32.S @@ -74,12 +74,6 @@ #endif */ .text _GLOBAL(hash_page) -#ifdef CONFIG_PPC64BRIDGE - mfmsr r0 - clrldi r0,r0,1 /* make sure it's in 32-bit mode */ - MTMSRD(r0) - isync -#endif tophys(r7,0) /* gets -KERNELBASE into r7 */ #ifdef CONFIG_SMP addis r8,r7,mmu_hash_lock@h @@ -285,7 +279,6 @@ Hash_base = 0xc0180000 Hash_bits = 12 /* e.g. 256kB hash table */ Hash_msk = (((1 << Hash_bits) - 1) * 64) -#ifndef CONFIG_PPC64BRIDGE /* defines for the PTE format for 32-bit PPCs */ #define PTE_SIZE 8 #define PTEG_SIZE 64 @@ -299,21 +292,6 @@ #define TST_V(r) rlwinm. r,r,0,0,0 #define SET_V(r) oris r,r,PTE_V@h #define CLR_V(r,t) rlwinm r,r,0,1,31 -#else -/* defines for the PTE format for 64-bit PPCs */ -#define PTE_SIZE 16 -#define PTEG_SIZE 128 -#define LG_PTEG_SIZE 7 -#define LDPTEu ldu -#define STPTE std -#define CMPPTE cmpd -#define PTE_H 2 -#define PTE_V 1 -#define TST_V(r) andi. r,r,PTE_V -#define SET_V(r) ori r,r,PTE_V -#define CLR_V(r,t) li t,PTE_V; andc r,r,t -#endif /* CONFIG_PPC64BRIDGE */ - #define HASH_LEFT 31-(LG_PTEG_SIZE+Hash_bits-1) #define HASH_RIGHT 31-LG_PTEG_SIZE @@ -331,14 +309,8 @@ BEGIN_FTR_SECTION END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT) /* Construct the high word of the PPC-style PTE (r5) */ -#ifndef CONFIG_PPC64BRIDGE rlwinm r5,r3,7,1,24 /* put VSID in 0x7fffff80 bits */ rlwimi r5,r4,10,26,31 /* put in API (abbrev page index) */ -#else /* CONFIG_PPC64BRIDGE */ - clrlwi r3,r3,8 /* reduce vsid to 24 bits */ - sldi r5,r3,12 /* shift vsid into position */ - rlwimi r5,r4,16,20,24 /* put in API (abbrev page index) */ -#endif /* CONFIG_PPC64BRIDGE */ SET_V(r5) /* set V (valid) bit */ /* Get the address of the primary PTE group in the hash table (r3) */ @@ -516,14 +488,8 @@ _GLOBAL(flush_hash_pages) add r3,r3,r0 /* note code below trims to 24 bits */ /* Construct the high word of the PPC-style PTE (r11) */ -#ifndef CONFIG_PPC64BRIDGE rlwinm r11,r3,7,1,24 /* put VSID in 0x7fffff80 bits */ rlwimi r11,r4,10,26,31 /* put in API (abbrev page index) */ -#else /* CONFIG_PPC64BRIDGE */ - clrlwi r3,r3,8 /* reduce vsid to 24 bits */ - sldi r11,r3,12 /* shift vsid into position */ - rlwimi r11,r4,16,20,24 /* put in API (abbrev page index) */ -#endif /* CONFIG_PPC64BRIDGE */ SET_V(r11) /* set V (valid) bit */ #ifdef CONFIG_SMP diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index e0d02c4..52e9142 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -136,6 +136,7 @@ _GLOBAL(__hash_page_4K) and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ andc r0,r30,r0 /* r0 = pte & ~r0 */ rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ + ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */ /* We eventually do the icache sync here (maybe inline that * code rather than call a C function...) @@ -368,6 +369,7 @@ _GLOBAL(__hash_page_4K) rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ or r30,r30,r31 ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE + oris r30,r30,_PAGE_COMBO@h /* Write the linux PTE atomically (setting busy) */ stdcx. r30,0,r6 bne- 1b @@ -400,6 +402,7 @@ _GLOBAL(__hash_page_4K) and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ andc r0,r30,r0 /* r0 = pte & ~r0 */ rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ + ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */ /* We eventually do the icache sync here (maybe inline that * code rather than call a C function...) @@ -426,6 +429,14 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FT andi. r0,r31,_PAGE_HASHPTE li r26,0 /* Default hidx */ beq htab_insert_pte + + /* + * Check if the pte was already inserted into the hash table + * as a 64k HW page, and invalidate the 64k HPTE if so. + */ + andis. r0,r31,_PAGE_COMBO@h + beq htab_inval_old_hpte + ld r6,STK_PARM(r6)(r1) ori r26,r6,0x8000 /* Load the hidx mask */ ld r26,0(r26) @@ -496,6 +507,19 @@ _GLOBAL(htab_call_hpte_remove) /* Try all again */ b htab_insert_pte + /* + * Call out to C code to invalidate an 64k HW HPTE that is + * useless now that the segment has been switched to 4k pages. + */ +htab_inval_old_hpte: + mr r3,r29 /* virtual addr */ + mr r4,r31 /* PTE.pte */ + li r5,0 /* PTE.hidx */ + li r6,MMU_PAGE_64K /* psize */ + ld r7,STK_PARM(r8)(r1) /* local */ + bl .flush_hash_page + b htab_insert_pte + htab_bail_ok: li r3,0 b htab_bail @@ -636,6 +660,12 @@ _GLOBAL(__hash_page_64K) * is changing this PTE anyway and might hash it. */ bne- ht64_bail_ok +BEGIN_FTR_SECTION + /* Check if PTE has the cache-inhibit bit set */ + andi. r0,r31,_PAGE_NO_CACHE + /* If so, bail out and refault as a 4k page */ + bne- ht64_bail_ok +END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE) /* Prepare new PTE value (turn access RW into DIRTY, then * add BUSY,HASHPTE and ACCESSED) */ @@ -671,6 +701,7 @@ _GLOBAL(__hash_page_64K) and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ andc r0,r30,r0 /* r0 = pte & ~r0 */ rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ + ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */ /* We eventually do the icache sync here (maybe inline that * code rather than call a C function...) diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 994856e..a0f3cbd 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -238,7 +238,7 @@ static long native_hpte_updatepp(unsigne DBG_LOW(" -> hit\n"); /* Update the HPTE */ hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | - (newpp & (HPTE_R_PP | HPTE_R_N)); + (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); native_unlock_hpte(hptep); } diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index c006d90..d03fd2b 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -92,10 +92,15 @@ unsigned long htab_size_bytes; unsigned long htab_hash_mask; int mmu_linear_psize = MMU_PAGE_4K; int mmu_virtual_psize = MMU_PAGE_4K; +int mmu_vmalloc_psize = MMU_PAGE_4K; +int mmu_io_psize = MMU_PAGE_4K; #ifdef CONFIG_HUGETLB_PAGE int mmu_huge_psize = MMU_PAGE_16M; unsigned int HPAGE_SHIFT; #endif +#ifdef CONFIG_PPC_64K_PAGES +int mmu_ci_restrictions; +#endif /* There are definitions of page sizes arrays to be used when none * is provided by the firmware. @@ -308,20 +313,31 @@ static void __init htab_init_page_sizes( else if (mmu_psize_defs[MMU_PAGE_1M].shift) mmu_linear_psize = MMU_PAGE_1M; +#ifdef CONFIG_PPC_64K_PAGES /* * Pick a size for the ordinary pages. Default is 4K, we support - * 64K if cache inhibited large pages are supported by the - * processor + * 64K for user mappings and vmalloc if supported by the processor. + * We only use 64k for ioremap if the processor + * (and firmware) support cache-inhibited large pages. + * If not, we use 4k and set mmu_ci_restrictions so that + * hash_page knows to switch processes that use cache-inhibited + * mappings to 4k pages. */ -#ifdef CONFIG_PPC_64K_PAGES - if (mmu_psize_defs[MMU_PAGE_64K].shift && - cpu_has_feature(CPU_FTR_CI_LARGE_PAGE)) + if (mmu_psize_defs[MMU_PAGE_64K].shift) { mmu_virtual_psize = MMU_PAGE_64K; + mmu_vmalloc_psize = MMU_PAGE_64K; + if (cpu_has_feature(CPU_FTR_CI_LARGE_PAGE)) + mmu_io_psize = MMU_PAGE_64K; + else + mmu_ci_restrictions = 1; + } #endif - printk(KERN_INFO "Page orders: linear mapping = %d, others = %d\n", + printk(KERN_DEBUG "Page orders: linear mapping = %d, " + "virtual = %d, io = %d\n", mmu_psize_defs[mmu_linear_psize].shift, - mmu_psize_defs[mmu_virtual_psize].shift); + mmu_psize_defs[mmu_virtual_psize].shift, + mmu_psize_defs[mmu_io_psize].shift); #ifdef CONFIG_HUGETLB_PAGE /* Init large page size. Currently, we pick 16M or 1M depending @@ -556,6 +572,7 @@ int hash_page(unsigned long ea, unsigned pte_t *ptep; cpumask_t tmp; int rc, user_region = 0, local = 0; + int psize; DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n", ea, access, trap); @@ -575,10 +592,15 @@ int hash_page(unsigned long ea, unsigned return 1; } vsid = get_vsid(mm->context.id, ea); + psize = mm->context.user_psize; break; case VMALLOC_REGION_ID: mm = &init_mm; vsid = get_kernel_vsid(ea); + if (ea < VMALLOC_END) + psize = mmu_vmalloc_psize; + else + psize = mmu_io_psize; break; default: /* Not a valid range @@ -629,7 +651,40 @@ #endif #ifndef CONFIG_PPC_64K_PAGES rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); #else - if (mmu_virtual_psize == MMU_PAGE_64K) + if (mmu_ci_restrictions) { + /* If this PTE is non-cacheable, switch to 4k */ + if (psize == MMU_PAGE_64K && + (pte_val(*ptep) & _PAGE_NO_CACHE)) { + if (user_region) { + psize = MMU_PAGE_4K; + mm->context.user_psize = MMU_PAGE_4K; + mm->context.sllp = SLB_VSID_USER | + mmu_psize_defs[MMU_PAGE_4K].sllp; + } else if (ea < VMALLOC_END) { + /* + * some driver did a non-cacheable mapping + * in vmalloc space, so switch vmalloc + * to 4k pages + */ + printk(KERN_ALERT "Reducing vmalloc segment " + "to 4kB pages because of " + "non-cacheable mapping\n"); + psize = mmu_vmalloc_psize = MMU_PAGE_4K; + } + } + if (user_region) { + if (psize != get_paca()->context.user_psize) { + get_paca()->context = mm->context; + slb_flush_and_rebolt(); + } + } else if (get_paca()->vmalloc_sllp != + mmu_psize_defs[mmu_vmalloc_psize].sllp) { + get_paca()->vmalloc_sllp = + mmu_psize_defs[mmu_vmalloc_psize].sllp; + slb_flush_and_rebolt(); + } + } + if (psize == MMU_PAGE_64K) rc = __hash_page_64K(ea, access, vsid, ptep, trap, local); else rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); @@ -681,7 +736,18 @@ void hash_preload(struct mm_struct *mm, #ifndef CONFIG_PPC_64K_PAGES __hash_page_4K(ea, access, vsid, ptep, trap, local); #else - if (mmu_virtual_psize == MMU_PAGE_64K) + if (mmu_ci_restrictions) { + /* If this PTE is non-cacheable, switch to 4k */ + if (mm->context.user_psize == MMU_PAGE_64K && + (pte_val(*ptep) & _PAGE_NO_CACHE)) { + mm->context.user_psize = MMU_PAGE_4K; + mm->context.sllp = SLB_VSID_USER | + mmu_psize_defs[MMU_PAGE_4K].sllp; + get_paca()->context = mm->context; + slb_flush_and_rebolt(); + } + } + if (mm->context.user_psize == MMU_PAGE_64K) __hash_page_64K(ea, access, vsid, ptep, trap, local); else __hash_page_4K(ea, access, vsid, ptep, trap, local); diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index 417d585..8b6f522 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c @@ -89,20 +89,25 @@ static long __init lmb_regions_adjacent( return lmb_addrs_adjacent(base1, size1, base2, size2); } -/* Assumption: base addr of region 1 < base addr of region 2 */ -static void __init lmb_coalesce_regions(struct lmb_region *rgn, - unsigned long r1, unsigned long r2) +static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r) { unsigned long i; - rgn->region[r1].size += rgn->region[r2].size; - for (i=r2; i < rgn->cnt-1; i++) { - rgn->region[i].base = rgn->region[i+1].base; - rgn->region[i].size = rgn->region[i+1].size; + for (i = r; i < rgn->cnt - 1; i++) { + rgn->region[i].base = rgn->region[i + 1].base; + rgn->region[i].size = rgn->region[i + 1].size; } rgn->cnt--; } +/* Assumption: base addr of region 1 < base addr of region 2 */ +static void __init lmb_coalesce_regions(struct lmb_region *rgn, + unsigned long r1, unsigned long r2) +{ + rgn->region[r1].size += rgn->region[r2].size; + lmb_remove_region(rgn, r2); +} + /* This routine called with relocation disabled. */ void __init lmb_init(void) { @@ -294,17 +299,16 @@ unsigned long __init lmb_end_of_DRAM(voi return (lmb.memory.region[idx].base + lmb.memory.region[idx].size); } -/* - * Truncate the lmb list to memory_limit if it's set - * You must call lmb_analyze() after this. - */ +/* You must call lmb_analyze() after this. */ void __init lmb_enforce_memory_limit(unsigned long memory_limit) { unsigned long i, limit; + struct lmb_property *p; if (! memory_limit) return; + /* Truncate the lmb regions to satisfy the memory limit. */ limit = memory_limit; for (i = 0; i < lmb.memory.cnt; i++) { if (limit > lmb.memory.region[i].size) { @@ -316,4 +320,21 @@ void __init lmb_enforce_memory_limit(uns lmb.memory.cnt = i + 1; break; } + + lmb.rmo_size = lmb.memory.region[0].size; + + /* And truncate any reserves above the limit also. */ + for (i = 0; i < lmb.reserved.cnt; i++) { + p = &lmb.reserved.region[i]; + + if (p->base > memory_limit) + p->size = 0; + else if ((p->base + p->size) > memory_limit) + p->size = memory_limit - p->base; + + if (p->size == 0) { + lmb_remove_region(&lmb.reserved, i); + i--; + } + } } diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 741dd88..69f3b9a 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -299,9 +299,9 @@ #ifdef CONFIG_HIGHMEM kmap_prot = PAGE_KERNEL; #endif /* CONFIG_HIGHMEM */ - printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", + printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", top_of_ram, total_ram); - printk(KERN_INFO "Memory hole size: %ldMB\n", + printk(KERN_DEBUG "Memory hole size: %ldMB\n", (top_of_ram - total_ram) >> 20); /* * All pages are DMA-able so we put them all in the DMA zone. @@ -380,7 +380,7 @@ #ifdef CONFIG_HIGHMEM totalhigh_pages++; } totalram_pages += totalhigh_pages; - printk(KERN_INFO "High memory: %luk\n", + printk(KERN_DEBUG "High memory: %luk\n", totalhigh_pages << (PAGE_SHIFT-10)); } #endif /* CONFIG_HIGHMEM */ diff --git a/arch/powerpc/mm/mmu_context_32.c b/arch/powerpc/mm/mmu_context_32.c index a8816e0..e326e42 100644 --- a/arch/powerpc/mm/mmu_context_32.c +++ b/arch/powerpc/mm/mmu_context_32.c @@ -30,7 +30,7 @@ #include #include #include -mm_context_t next_mmu_context; +unsigned long next_mmu_context; unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1]; #ifdef FEW_CONTEXTS atomic_t nr_free_contexts; diff --git a/arch/powerpc/mm/mmu_context_64.c b/arch/powerpc/mm/mmu_context_64.c index 714a84d..65d18dc 100644 --- a/arch/powerpc/mm/mmu_context_64.c +++ b/arch/powerpc/mm/mmu_context_64.c @@ -49,6 +49,9 @@ again: } mm->context.id = index; + mm->context.user_psize = mmu_virtual_psize; + mm->context.sllp = SLB_VSID_USER | + mmu_psize_defs[mmu_virtual_psize].sllp; return 0; } diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 092355f..aa98cb3 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -487,9 +487,9 @@ static void __init setup_nonnuma(void) unsigned long total_ram = lmb_phys_mem_size(); unsigned int i; - printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", + printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", top_of_ram, total_ram); - printk(KERN_INFO "Memory hole size: %ldMB\n", + printk(KERN_DEBUG "Memory hole size: %ldMB\n", (top_of_ram - total_ram) >> 20); for (i = 0; i < lmb.memory.cnt; ++i) @@ -507,7 +507,7 @@ void __init dump_numa_cpu_topology(void) return; for_each_online_node(node) { - printk(KERN_INFO "Node %d CPUs:", node); + printk(KERN_DEBUG "Node %d CPUs:", node); count = 0; /* @@ -543,7 +543,7 @@ static void __init dump_numa_memory_topo for_each_online_node(node) { unsigned long i; - printk(KERN_INFO "Node %d Memory:", node); + printk(KERN_DEBUG "Node %d Memory:", node); count = 0; diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index ed7fcfe..2ed43a4 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -42,18 +42,14 @@ unsigned long _SDR1; union ubat { /* BAT register values to be loaded */ BAT bat; -#ifdef CONFIG_PPC64BRIDGE - u64 word[2]; -#else u32 word[2]; -#endif -} BATS[4][2]; /* 4 pairs of IBAT, DBAT */ +} BATS[8][2]; /* 8 pairs of IBAT, DBAT */ struct batrange { /* stores address ranges mapped by BATs */ unsigned long start; unsigned long limit; unsigned long phys; -} bat_addrs[4]; +} bat_addrs[8]; /* * Return PA for this VA if it is mapped by a BAT, or 0 @@ -190,7 +186,7 @@ void hash_preload(struct mm_struct *mm, return; pmd = pmd_offset(pgd_offset(mm, ea), ea); if (!pmd_none(*pmd)) - add_hash_page(mm->context, ea, pmd_val(*pmd)); + add_hash_page(mm->context.id, ea, pmd_val(*pmd)); } /* @@ -220,15 +216,9 @@ void __init MMU_init_hw(void) if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105); -#ifdef CONFIG_PPC64BRIDGE -#define LG_HPTEG_SIZE 7 /* 128 bytes per HPTEG */ -#define SDR1_LOW_BITS (lg_n_hpteg - 11) -#define MIN_N_HPTEG 2048 /* min 256kB hash table */ -#else #define LG_HPTEG_SIZE 6 /* 64 bytes per HPTEG */ #define SDR1_LOW_BITS ((n_hpteg - 1) >> 10) #define MIN_N_HPTEG 1024 /* min 64kB hash table */ -#endif /* * Allow 1 HPTE (1/8 HPTEG) for each page of memory. diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index ffc8ed4..6a8bf6c 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -60,19 +60,19 @@ static inline void create_slbe(unsigned : "memory" ); } -static void slb_flush_and_rebolt(void) +void slb_flush_and_rebolt(void) { /* If you change this make sure you change SLB_NUM_BOLTED * appropriately too. */ - unsigned long linear_llp, virtual_llp, lflags, vflags; + unsigned long linear_llp, vmalloc_llp, lflags, vflags; unsigned long ksp_esid_data; WARN_ON(!irqs_disabled()); linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; - virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp; + vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp; lflags = SLB_VSID_KERNEL | linear_llp; - vflags = SLB_VSID_KERNEL | virtual_llp; + vflags = SLB_VSID_KERNEL | vmalloc_llp; ksp_esid_data = mk_esid_data(get_paca()->kstack, 2); if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET) @@ -122,9 +122,6 @@ void switch_slb(struct task_struct *tsk, get_paca()->slb_cache_ptr = 0; get_paca()->context = mm->context; -#ifdef CONFIG_PPC_64K_PAGES - get_paca()->pgdir = mm->pgd; -#endif /* CONFIG_PPC_64K_PAGES */ /* * preload some userspace segments into the SLB. @@ -167,11 +164,10 @@ static inline void patch_slb_encoding(un void slb_initialize(void) { - unsigned long linear_llp, virtual_llp; + unsigned long linear_llp, vmalloc_llp, io_llp; static int slb_encoding_inited; extern unsigned int *slb_miss_kernel_load_linear; - extern unsigned int *slb_miss_kernel_load_virtual; - extern unsigned int *slb_miss_user_load_normal; + extern unsigned int *slb_miss_kernel_load_io; #ifdef CONFIG_HUGETLB_PAGE extern unsigned int *slb_miss_user_load_huge; unsigned long huge_llp; @@ -181,18 +177,19 @@ #endif /* Prepare our SLB miss handler based on our page size */ linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; - virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp; + io_llp = mmu_psize_defs[mmu_io_psize].sllp; + vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp; + get_paca()->vmalloc_sllp = SLB_VSID_KERNEL | vmalloc_llp; + if (!slb_encoding_inited) { slb_encoding_inited = 1; patch_slb_encoding(slb_miss_kernel_load_linear, SLB_VSID_KERNEL | linear_llp); - patch_slb_encoding(slb_miss_kernel_load_virtual, - SLB_VSID_KERNEL | virtual_llp); - patch_slb_encoding(slb_miss_user_load_normal, - SLB_VSID_USER | virtual_llp); + patch_slb_encoding(slb_miss_kernel_load_io, + SLB_VSID_KERNEL | io_llp); DBG("SLB: linear LLP = %04x\n", linear_llp); - DBG("SLB: virtual LLP = %04x\n", virtual_llp); + DBG("SLB: io LLP = %04x\n", io_llp); #ifdef CONFIG_HUGETLB_PAGE patch_slb_encoding(slb_miss_user_load_huge, SLB_VSID_USER | huge_llp); @@ -207,7 +204,7 @@ #ifndef CONFIG_PPC_ISERIES unsigned long lflags, vflags; lflags = SLB_VSID_KERNEL | linear_llp; - vflags = SLB_VSID_KERNEL | virtual_llp; + vflags = SLB_VSID_KERNEL | vmalloc_llp; /* Invalidate the entire SLB (even slot 0) & all the ERATS */ asm volatile("isync":::"memory"); @@ -215,7 +212,6 @@ #ifndef CONFIG_PPC_ISERIES asm volatile("isync; slbia; isync":::"memory"); create_slbe(PAGE_OFFSET, lflags, 0); - /* VMALLOC space has 4K pages always for now */ create_slbe(VMALLOC_START, vflags, 1); /* We don't bolt the stack for the time being - we're in boot, diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index abfaabf..8548dcf 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -59,10 +59,19 @@ _GLOBAL(slb_miss_kernel_load_linear) li r11,0 b slb_finish_load -1: /* vmalloc/ioremap mapping encoding bits, the "li" instruction below +1: /* vmalloc/ioremap mapping encoding bits, the "li" instructions below * will be patched by the kernel at boot */ -_GLOBAL(slb_miss_kernel_load_virtual) +BEGIN_FTR_SECTION + /* check whether this is in vmalloc or ioremap space */ + clrldi r11,r10,48 + cmpldi r11,(VMALLOC_SIZE >> 28) - 1 + bgt 5f + lhz r11,PACAVMALLOCSLLP(r13) + b slb_finish_load +5: +END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE) +_GLOBAL(slb_miss_kernel_load_io) li r11,0 b slb_finish_load @@ -96,9 +105,7 @@ _GLOBAL(slb_miss_user_load_huge) 1: #endif /* CONFIG_HUGETLB_PAGE */ -_GLOBAL(slb_miss_user_load_normal) - li r11,0 - + lhz r11,PACACONTEXTSLLP(r13) 2: ld r9,PACACONTEXTID(r13) rldimi r10,r9,USER_ESID_BITS,0 diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 4a9291d..691320c 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c @@ -200,10 +200,6 @@ void switch_stab(struct task_struct *tsk __get_cpu_var(stab_cache_ptr) = 0; -#ifdef CONFIG_PPC_64K_PAGES - get_paca()->pgdir = mm->pgd; -#endif /* CONFIG_PPC_64K_PAGES */ - /* Now preload some entries for the new task */ if (test_tsk_thread_flag(tsk, TIF_32BIT)) unmapped_base = TASK_UNMAPPED_BASE_USER32; diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c index ad580f3..02eb23e 100644 --- a/arch/powerpc/mm/tlb_32.c +++ b/arch/powerpc/mm/tlb_32.c @@ -42,7 +42,7 @@ void flush_hash_entry(struct mm_struct * if (Hash != 0) { ptephys = __pa(ptep) & PAGE_MASK; - flush_hash_pages(mm->context, addr, ptephys, 1); + flush_hash_pages(mm->context.id, addr, ptephys, 1); } } @@ -102,7 +102,7 @@ static void flush_range(struct mm_struct pmd_t *pmd; unsigned long pmd_end; int count; - unsigned int ctx = mm->context; + unsigned int ctx = mm->context.id; if (Hash == 0) { _tlbia(); @@ -172,7 +172,7 @@ void flush_tlb_page(struct vm_area_struc mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr); if (!pmd_none(*pmd)) - flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1); + flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1); FINISH_FLUSH; } diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index f734b11..e7449b0 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c @@ -131,7 +131,7 @@ void hpte_update(struct mm_struct *mm, u { struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); unsigned long vsid; - unsigned int psize = mmu_virtual_psize; + unsigned int psize; int i; i = batch->index; @@ -148,7 +148,8 @@ #ifdef CONFIG_HUGETLB_PAGE #else BUG(); #endif - } + } else + psize = pte_pagesize_index(pte); /* * This can happen when we are in the middle of a TLB batch and diff --git a/arch/powerpc/oprofile/Kconfig b/arch/powerpc/oprofile/Kconfig index d03c0e5..eb2dece 100644 --- a/arch/powerpc/oprofile/Kconfig +++ b/arch/powerpc/oprofile/Kconfig @@ -1,5 +1,4 @@ config PROFILING - depends on !PPC_ISERIES bool "Profiling support (EXPERIMENTAL)" help Say Y here to enable the extended profiling support mechanisms used diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index f5f9859..3145d61 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile @@ -1,3 +1,7 @@ +ifeq ($(CONFIG_PPC64),y) +EXTRA_CFLAGS += -mno-minimal-toc +endif + obj-$(CONFIG_OPROFILE) += oprofile.o DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index 5b1de7e..fd0bbbe 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -22,6 +22,7 @@ #include #include #include #include +#include static struct op_powerpc_model *model; @@ -93,7 +94,7 @@ #endif for (i = 0; i < model->num_counters; ++i) { struct dentry *dir; - char buf[3]; + char buf[4]; snprintf(buf, sizeof buf, "%d", i); dir = oprofilefs_mkdir(sb, root, buf); @@ -130,6 +131,9 @@ int __init oprofile_arch_init(struct opr if (!cur_cpu_spec->oprofile_cpu_type) return -ENODEV; + if (firmware_has_feature(FW_FEATURE_ISERIES)) + return -ENODEV; + switch (cur_cpu_spec->oprofile_type) { #ifdef CONFIG_PPC64 case PPC_OPROFILE_RS64: @@ -162,7 +166,7 @@ #endif ops->stop = op_powerpc_stop; ops->backtrace = op_powerpc_backtrace; - printk(KERN_INFO "oprofile: using %s performance monitoring.\n", + printk(KERN_DEBUG "oprofile: using %s performance monitoring.\n", ops->cpu_type); return 0; diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 4c2beab..506f6b7 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c @@ -24,10 +24,6 @@ #define dbg(args...) static unsigned long reset_value[OP_MAX_COUNTER]; static int oprofile_running; -static int mmcra_has_sihv; -/* Unfortunately these bits vary between CPUs */ -static unsigned long mmcra_sihv = MMCRA_SIHV; -static unsigned long mmcra_sipr = MMCRA_SIPR; /* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */ static u32 mmcr0_val; @@ -41,16 +37,6 @@ static void power4_reg_setup(struct op_c int i; /* - * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above. - * However we disable it on all POWER4 until we verify it works - * (I was seeing some strange behaviour last time I tried). - * - * It has been verified to work on POWER5 so we enable it there. - */ - if (cpu_has_feature(CPU_FTR_MMCRA_SIHV)) - mmcra_has_sihv = 1; - - /* * The performance counter event settings are given in the mmcr0, * mmcr1 and mmcra values passed from the user in the * op_system_config structure (sys variable). @@ -202,18 +188,19 @@ static unsigned long get_pc(struct pt_re unsigned long mmcra; /* Cant do much about it */ - if (!mmcra_has_sihv) + if (!cur_cpu_spec->oprofile_mmcra_sihv) return pc; mmcra = mfspr(SPRN_MMCRA); /* Were we in the hypervisor? */ - if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv)) + if (firmware_has_feature(FW_FEATURE_LPAR) && + (mmcra & cur_cpu_spec->oprofile_mmcra_sihv)) /* function descriptor madness */ return *((unsigned long *)hypervisor_bucket); /* We were in userspace, nothing to do */ - if (mmcra & mmcra_sipr) + if (mmcra & cur_cpu_spec->oprofile_mmcra_sipr) return pc; #ifdef CONFIG_PPC_RTAS @@ -235,15 +222,14 @@ #endif return pc; } -static int get_kernel(unsigned long pc) +static int get_kernel(unsigned long pc, unsigned long mmcra) { int is_kernel; - if (!mmcra_has_sihv) { + if (!cur_cpu_spec->oprofile_mmcra_sihv) { is_kernel = is_kernel_addr(pc); } else { - unsigned long mmcra = mfspr(SPRN_MMCRA); - is_kernel = ((mmcra & mmcra_sipr) == 0); + is_kernel = ((mmcra & cur_cpu_spec->oprofile_mmcra_sipr) == 0); } return is_kernel; @@ -257,9 +243,12 @@ static void power4_handle_interrupt(stru int val; int i; unsigned int mmcr0; + unsigned long mmcra; + + mmcra = mfspr(SPRN_MMCRA); pc = get_pc(regs); - is_kernel = get_kernel(pc); + is_kernel = get_kernel(pc, mmcra); /* set the PMM bit (see comment below) */ mtmsrd(mfmsr() | MSR_PMM); @@ -287,6 +276,10 @@ static void power4_handle_interrupt(stru */ mmcr0 &= ~MMCR0_PMAO; + /* Clear the appropriate bits in the MMCRA */ + mmcra &= ~cur_cpu_spec->oprofile_mmcra_clear; + mtspr(SPRN_MMCRA, mmcra); + /* * now clear the freeze bit, counting will not start until we * rfid from this exception, because only at that point will diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 06e3712..454fc53 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -11,13 +11,20 @@ config MPC8540_ADS help This option enables support for the MPC 8540 ADS board +config MPC85xx_CDS + bool "Freescale MPC85xx CDS" + select DEFAULT_UIMAGE + select PPC_I8259 if PCI + help + This option enables support for the MPC85xx CDS board + endchoice config MPC8540 bool select PPC_UDBG_16550 select PPC_INDIRECT_PCI - default y if MPC8540_ADS + default y if MPC8540_ADS || MPC85xx_CDS config PPC_INDIRECT_PCI_BE bool diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index ffc4139..7615aa5 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -3,3 +3,4 @@ # Makefile for the PowerPC 85xx linux ke # obj-$(CONFIG_PPC_85xx) += misc.o pci.o obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o +obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c new file mode 100644 index 0000000..18e6e11 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -0,0 +1,359 @@ +/* + * MPC85xx setup and early boot code plus other random bits. + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * Copyright 2005 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "mpc85xx.h" + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +static int cds_pci_slot = 2; +static volatile u8 *cadmus; + +/* + * Internal interrupts are all Level Sensitive, and Positive Polarity + * + * Note: Likely, this table and the following function should be + * obtained and derived from the OF Device Tree. + */ +static u_char mpc85xx_cds_openpic_initsenses[] __initdata = { + MPC85XX_INTERNAL_IRQ_SENSES, +#if defined(CONFIG_PCI) + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Ext 0: PCI slot 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 1: PCI slot 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 2: PCI slot 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 3: PCI slot 3 */ +#else + 0x0, /* External 0: */ + 0x0, /* External 1: */ + 0x0, /* External 2: */ + 0x0, /* External 3: */ +#endif + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */ + 0x0, /* External 6: */ + 0x0, /* External 7: */ + 0x0, /* External 8: */ + 0x0, /* External 9: */ + 0x0, /* External 10: */ +#ifdef CONFIG_PCI + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 11: PCI2 slot 0 */ +#else + 0x0, /* External 11: */ +#endif +}; + + +#ifdef CONFIG_PCI +/* + * interrupt routing + */ +int +mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); + + if (!hose->index) + { + /* Handle PCI1 interrupts */ + char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + + /* Note IRQ assignment for slots is based on which slot the elysium is + * in -- in this setup elysium is in slot #2 (this PIRQA as first + * interrupt on slot */ + { + { 0, 1, 2, 3 }, /* 16 - PMC */ + { 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */ + { 0, 1, 2, 3 }, /* 18 - Slot 1 */ + { 1, 2, 3, 0 }, /* 19 - Slot 2 */ + { 2, 3, 0, 1 }, /* 20 - Slot 3 */ + { 3, 0, 1, 2 }, /* 21 - Slot 4 */ + }; + + const long min_idsel = 16, max_idsel = 21, irqs_per_slot = 4; + int i, j; + + for (i = 0; i < 6; i++) + for (j = 0; j < 4; j++) + pci_irq_table[i][j] = + ((pci_irq_table[i][j] + 5 - + cds_pci_slot) & 0x3) + PIRQ0A; + + return PCI_IRQ_TABLE_LOOKUP; + } else { + /* Handle PCI2 interrupts (if we have one) */ + char pci_irq_table[][4] = + { + /* + * We only have one slot and one interrupt + * going to PIRQA - PIRQD */ + { PIRQ1A, PIRQ1A, PIRQ1A, PIRQ1A }, /* 21 - slot 0 */ + }; + + const long min_idsel = 21, max_idsel = 21, irqs_per_slot = 4; + + return PCI_IRQ_TABLE_LOOKUP; + } +} + +#define ARCADIA_HOST_BRIDGE_IDSEL 17 +#define ARCADIA_2ND_BRIDGE_IDSEL 3 + +extern int mpc85xx_pci2_busno; + +int +mpc85xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (mpc85xx_pci2_busno) + if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + /* We explicitly do not go past the Tundra 320 Bridge */ + if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) + return PCIBIOS_DEVICE_NOT_FOUND; + if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) + return PCIBIOS_DEVICE_NOT_FOUND; + else + return PCIBIOS_SUCCESSFUL; +} + +void __init +mpc85xx_cds_pcibios_fixup(void) +{ + struct pci_dev *dev; + u_char c; + + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_1, NULL))) { + /* + * U-Boot does not set the enable bits + * for the IDE device. Force them on here. + */ + pci_read_config_byte(dev, 0x40, &c); + c |= 0x03; /* IDE: Chip Enable Bits */ + pci_write_config_byte(dev, 0x40, c); + + /* + * Since only primary interface works, force the + * IDE function to standard primary IDE interrupt + * w/ 8259 offset + */ + dev->irq = 14; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + pci_dev_put(dev); + } + + /* + * Force legacy USB interrupt routing + */ + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, NULL))) { + dev->irq = 10; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); + pci_dev_put(dev); + } + + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, dev))) { + dev->irq = 11; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + pci_dev_put(dev); + } +} +#endif /* CONFIG_PCI */ + +void __init mpc85xx_cds_pic_init(void) +{ + struct mpic *mpic1; + phys_addr_t OpenPIC_PAddr; + + /* Determine the Physical Address of the OpenPIC regs */ + OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET; + + mpic1 = mpic_alloc(OpenPIC_PAddr, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250, + mpc85xx_cds_openpic_initsenses, + sizeof(mpc85xx_cds_openpic_initsenses), " OpenPIC "); + BUG_ON(mpic1 == NULL); + mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200); + mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280); + mpic_assign_isu(mpic1, 2, OpenPIC_PAddr + 0x10300); + mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10380); + mpic_assign_isu(mpic1, 4, OpenPIC_PAddr + 0x10400); + mpic_assign_isu(mpic1, 5, OpenPIC_PAddr + 0x10480); + mpic_assign_isu(mpic1, 6, OpenPIC_PAddr + 0x10500); + mpic_assign_isu(mpic1, 7, OpenPIC_PAddr + 0x10580); + + /* dummy mappings to get to 48 */ + mpic_assign_isu(mpic1, 8, OpenPIC_PAddr + 0x10600); + mpic_assign_isu(mpic1, 9, OpenPIC_PAddr + 0x10680); + mpic_assign_isu(mpic1, 10, OpenPIC_PAddr + 0x10700); + mpic_assign_isu(mpic1, 11, OpenPIC_PAddr + 0x10780); + + /* External ints */ + mpic_assign_isu(mpic1, 12, OpenPIC_PAddr + 0x10000); + mpic_assign_isu(mpic1, 13, OpenPIC_PAddr + 0x10080); + mpic_assign_isu(mpic1, 14, OpenPIC_PAddr + 0x10100); + + mpic_init(mpic1); + +#ifdef CONFIG_PCI + mpic_setup_cascade(PIRQ0A, i8259_irq_cascade, NULL); + + i8259_init(0,0); +#endif +} + + +/* + * Setup the architecture + */ +static void __init +mpc85xx_cds_setup_arch(void) +{ + struct device_node *cpu; +#ifdef CONFIG_PCI + struct device_node *np; +#endif + + if (ppc_md.progress) + ppc_md.progress("mpc85xx_cds_setup_arch()", 0); + + cpu = of_find_node_by_type(NULL, "cpu"); + if (cpu != 0) { + unsigned int *fp; + + fp = (int *)get_property(cpu, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 500000000 / HZ; + of_node_put(cpu); + } + + cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE); + cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1; + + if (ppc_md.progress) { + char buf[40]; + snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n", + cadmus[CM_VER], cds_pci_slot); + ppc_md.progress(buf, 0); + } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup; + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc85xx_map_irq; + ppc_md.pci_exclude_device = mpc85xx_exclude_device; +#endif + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif +} + + +void +mpc85xx_cds_show_cpuinfo(struct seq_file *m) +{ + uint pvid, svid, phid1; + uint memsize = total_memory; + + pvid = mfspr(SPRN_PVR); + svid = mfspr(SPRN_SVR); + + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); + seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n", cadmus[CM_VER]); + seq_printf(m, "PVR\t\t: 0x%x\n", pvid); + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + + /* Display cpu Pll setting */ + phid1 = mfspr(SPRN_HID1); + seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); +} + + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mpc85xx_cds_probe(void) +{ + /* We always match for now, eventually we should look at + * the flat dev tree to ensure this is the board we are + * supposed to run on + */ + return 1; +} + +define_machine(mpc85xx_cds) { + .name = "MPC85xx CDS", + .probe = mpc85xx_cds_probe, + .setup_arch = mpc85xx_cds_setup_arch, + .init_IRQ = mpc85xx_cds_pic_init, + .show_cpuinfo = mpc85xx_cds_show_cpuinfo, + .get_irq = mpic_get_irq, + .restart = mpc85xx_restart, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.h b/arch/powerpc/platforms/85xx/mpc85xx_cds.h new file mode 100644 index 0000000..671f54f --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.h @@ -0,0 +1,43 @@ +/* + * arch/ppc/platforms/85xx/mpc85xx_cds_common.h + * + * MPC85xx CDS board definitions + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MACH_MPC85XX_CDS_H__ +#define __MACH_MPC85XX_CDS_H__ + +/* CADMUS info */ +#define CADMUS_BASE (0xf8004000) +#define CADMUS_SIZE (256) +#define CM_VER (0) +#define CM_CSR (1) +#define CM_RST (2) + +/* CDS NVRAM/RTC */ +#define CDS_RTC_ADDR (0xf8000000) +#define CDS_RTC_SIZE (8 * 1024) + +/* PCI interrupt controller */ +#define PIRQ0A MPC85xx_IRQ_EXT0 +#define PIRQ0B MPC85xx_IRQ_EXT1 +#define PIRQ0C MPC85xx_IRQ_EXT2 +#define PIRQ0D MPC85xx_IRQ_EXT3 +#define PIRQ1A MPC85xx_IRQ_EXT11 + +#define NR_8259_INTS 16 +#define CPM_IRQ_OFFSET NR_8259_INTS + +#define MPC85xx_OPENPIC_IRQ_OFFSET 80 + +#endif /* __MACH_MPC85XX_CDS_H__ */ diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig new file mode 100644 index 0000000..3a87863 --- /dev/null +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -0,0 +1,36 @@ +menu "Platform Support" + depends on PPC_86xx + +choice + prompt "Machine Type" + default MPC8641_HPCN + +config MPC8641_HPCN + bool "Freescale MPC8641 HPCN" + help + This option enables support for the MPC8641 HPCN board. + +endchoice + + +config MPC8641 + bool + select PPC_INDIRECT_PCI + select PPC_UDBG_16550 + default y if MPC8641_HPCN + +config MPIC + bool + default y + +config PPC_INDIRECT_PCI_BE + bool + depends on PPC_86xx + default y + +config PPC_STD_MMU + bool + depends on PPC_86xx + default y + +endmenu diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile new file mode 100644 index 0000000..7be796c --- /dev/null +++ b/arch/powerpc/platforms/86xx/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the PowerPC 86xx linux kernel. +# + + +ifeq ($(CONFIG_PPC_86xx),y) +obj-$(CONFIG_SMP) += mpc86xx_smp.o +endif +obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o +obj-$(CONFIG_PCI) += pci.o mpc86xx_pcie.o diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h new file mode 100644 index 0000000..5042253 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h @@ -0,0 +1,54 @@ +/* + * MPC8641 HPCN board definitions + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Author: Xianghua Xiao + */ + +#ifndef __MPC8641_HPCN_H__ +#define __MPC8641_HPCN_H__ + +#include +#include + +/* PCI interrupt controller */ +#define PIRQA 3 +#define PIRQB 4 +#define PIRQC 5 +#define PIRQD 6 +#define PIRQ7 7 +#define PIRQE 9 +#define PIRQF 10 +#define PIRQG 11 +#define PIRQH 12 + +/* PCI-Express memory map */ +#define MPC86XX_PCIE_LOWER_IO 0x00000000 +#define MPC86XX_PCIE_UPPER_IO 0x00ffffff + +#define MPC86XX_PCIE_LOWER_MEM 0x80000000 +#define MPC86XX_PCIE_UPPER_MEM 0x9fffffff + +#define MPC86XX_PCIE_IO_BASE 0xe2000000 +#define MPC86XX_PCIE_MEM_OFFSET 0x00000000 + +#define MPC86XX_PCIE_IO_SIZE 0x01000000 + +#define PCIE1_CFG_ADDR_OFFSET (0x8000) +#define PCIE1_CFG_DATA_OFFSET (0x8004) + +#define PCIE2_CFG_ADDR_OFFSET (0x9000) +#define PCIE2_CFG_DATA_OFFSET (0x9004) + +#define MPC86xx_PCIE_OFFSET PCIE1_CFG_ADDR_OFFSET +#define MPC86xx_PCIE_SIZE (0x1000) + +#define MPC86XX_RSTCR_OFFSET (0xe00b0) /* Reset Control Register */ + +#endif /* __MPC8641_HPCN_H__ */ diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h new file mode 100644 index 0000000..e3c9e4f --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx.h @@ -0,0 +1,28 @@ +/* + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __MPC86XX_H__ +#define __MPC86XX_H__ + +/* + * Declaration for the various functions exported by the + * mpc86xx_* files. Mostly for use by mpc86xx_setup(). + */ + +extern int __init add_bridge(struct device_node *dev); + +extern void __init setup_indirect_pcie(struct pci_controller *hose, + u32 cfg_addr, u32 cfg_data); +extern void __init setup_indirect_pcie_nomap(struct pci_controller *hose, + void __iomem *cfg_addr, + void __iomem *cfg_data); + +extern void __init mpc86xx_smp_init(void); + +#endif /* __MPC86XX_H__ */ diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file mode 100644 index 0000000..483c21d --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -0,0 +1,326 @@ +/* + * MPC86xx HPCN board specific routines + * + * Recode: ZHANG WEI + * Initial author: Xianghua Xiao + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "mpc86xx.h" + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +unsigned long pci_dram_offset = 0; +#endif + + +/* + * Internal interrupts are all Level Sensitive, and Positive Polarity + */ + +static u_char mpc86xx_hpcn_openpic_initsenses[] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: MCM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCIE1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: PCIE2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: DUART2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 1 Transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 1 Receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: TSEC 3 transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: TSEC 3 receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: TSEC 3 error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 1 Receive/Transmit Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 2 Transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 2 Receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: TSEC 4 transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: TSEC 4 receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: TSEC 4 error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 2 Receive/Transmit Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 32: SRIO error/write-port unit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 33: SRIO outbound doorbell */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 34: SRIO inbound doorbell */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 35: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 36: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 37: SRIO outbound message unit 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 38: SRIO inbound message unit 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 39: SRIO outbound message unit 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 40: SRIO inbound message unit 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 41: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 42: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 43: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 44: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 45: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 46: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 47: Unused */ + 0x0, /* External 0: */ + 0x0, /* External 1: */ + 0x0, /* External 2: */ + 0x0, /* External 3: */ + 0x0, /* External 4: */ + 0x0, /* External 5: */ + 0x0, /* External 6: */ + 0x0, /* External 7: */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 8: Pixis FPGA */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* External 9: ULI 8259 INTR Cascade */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 10: Quad ETH PHY */ + 0x0, /* External 11: */ + 0x0, + 0x0, + 0x0, + 0x0, +}; + + +void __init +mpc86xx_hpcn_init_irq(void) +{ + struct mpic *mpic1; + phys_addr_t openpic_paddr; + + /* Determine the Physical Address of the OpenPIC regs */ + openpic_paddr = get_immrbase() + MPC86xx_OPENPIC_OFFSET; + + /* Alloc mpic structure and per isu has 16 INT entries. */ + mpic1 = mpic_alloc(openpic_paddr, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 16, MPC86xx_OPENPIC_IRQ_OFFSET, 0, 250, + mpc86xx_hpcn_openpic_initsenses, + sizeof(mpc86xx_hpcn_openpic_initsenses), + " MPIC "); + BUG_ON(mpic1 == NULL); + + /* 48 Internal Interrupts */ + mpic_assign_isu(mpic1, 0, openpic_paddr + 0x10200); + mpic_assign_isu(mpic1, 1, openpic_paddr + 0x10400); + mpic_assign_isu(mpic1, 2, openpic_paddr + 0x10600); + + /* 16 External interrupts */ + mpic_assign_isu(mpic1, 3, openpic_paddr + 0x10000); + + mpic_init(mpic1); + +#ifdef CONFIG_PCI + mpic_setup_cascade(MPC86xx_IRQ_EXT9, i8259_irq_cascade, NULL); + i8259_init(0, I8259_OFFSET); +#endif +} + + + +#ifdef CONFIG_PCI +/* + * interrupt routing + */ + +int +mpc86xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = { + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 17 -- PCI Slot 1 */ + {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 18 -- PCI Slot 2 */ + {0, 0, 0, 0}, /* IDSEL 19 */ + {0, 0, 0, 0}, /* IDSEL 20 */ + {0, 0, 0, 0}, /* IDSEL 21 */ + {0, 0, 0, 0}, /* IDSEL 22 */ + {0, 0, 0, 0}, /* IDSEL 23 */ + {0, 0, 0, 0}, /* IDSEL 24 */ + {0, 0, 0, 0}, /* IDSEL 25 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, /* IDSEL 26 -- PCI Bridge*/ + {PIRQC, 0, 0, 0}, /* IDSEL 27 -- LAN */ + {PIRQE, PIRQF, PIRQH, PIRQ7}, /* IDSEL 28 -- USB 1.1 */ + {PIRQE, PIRQF, PIRQG, 0}, /* IDSEL 29 -- Audio & Modem */ + {PIRQH, 0, 0, 0}, /* IDSEL 30 -- LPC & PMU*/ + {PIRQD, 0, 0, 0}, /* IDSEL 31 -- ATA */ + }; + + const long min_idsel = 17, max_idsel = 31, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP + I8259_OFFSET; +} + + +int +mpc86xx_exclude_device(u_char bus, u_char devfn) +{ +#if !defined(CONFIG_PCI) + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; +#endif + + return PCIBIOS_SUCCESSFUL; +} +#endif /* CONFIG_PCI */ + + +static void __init +mpc86xx_hpcn_setup_arch(void) +{ + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0); + + np = of_find_node_by_type(NULL, "cpu"); + if (np != 0) { + unsigned int *fp; + + fp = (int *)get_property(np, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(np); + } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc86xx_map_irq; + ppc_md.pci_exclude_device = mpc86xx_exclude_device; +#endif + + printk("MPC86xx HPCN board from Freescale Semiconductor\n"); + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + +#ifdef CONFIG_SMP + mpc86xx_smp_init(); +#endif +} + + +void +mpc86xx_hpcn_show_cpuinfo(struct seq_file *m) +{ + struct device_node *root; + uint memsize = total_memory; + const char *model = ""; + uint svid = mfspr(SPRN_SVR); + + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); + + root = of_find_node_by_path("/"); + if (root) + model = get_property(root, "model", NULL); + seq_printf(m, "Machine\t\t: %s\n", model); + of_node_put(root); + + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); +} + + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mpc86xx_hpcn_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (of_flat_dt_is_compatible(root, "mpc86xx")) + return 1; /* Looks good */ + + return 0; +} + + +void +mpc86xx_restart(char *cmd) +{ + void __iomem *rstcr; + + rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100); + + local_irq_disable(); + + /* Assert reset request to Reset Control Register */ + out_be32(rstcr, 0x2); + + /* not reached */ +} + + +long __init +mpc86xx_time_init(void) +{ + unsigned int temp; + + /* Set the time base to zero */ + mtspr(SPRN_TBWL, 0); + mtspr(SPRN_TBWU, 0); + + temp = mfspr(SPRN_HID0); + temp |= HID0_TBEN; + mtspr(SPRN_HID0, temp); + asm volatile("isync"); + + return 0; +} + + +define_machine(mpc86xx_hpcn) { + .name = "MPC86xx HPCN", + .probe = mpc86xx_hpcn_probe, + .setup_arch = mpc86xx_hpcn_setup_arch, + .init_IRQ = mpc86xx_hpcn_init_irq, + .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, + .get_irq = mpic_get_irq, + .restart = mpc86xx_restart, + .time_init = mpc86xx_time_init, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c new file mode 100644 index 0000000..a2f4f73 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c @@ -0,0 +1,173 @@ +/* + * Support for indirect PCI bridges. + * + * Copyright (C) 1998 Gabriel Paubert. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * "Temporary" MPC8548 Errata file - + * The standard indirect_pci code should work with future silicon versions. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mpc86xx.h" + +#define PCI_CFG_OUT out_be32 + +/* ERRATA PCI-Ex 14 PCIE Controller timeout */ +#define PCIE_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff) + + +static int +indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 *val) +{ + struct pci_controller *hose = bus->sysdata; + volatile void __iomem *cfg_data; + u32 temp; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* Possible artifact of CDCpp50937 needs further investigation */ + if (devfn != 0x0 && bus->number == 0xff) + return PCIBIOS_DEVICE_NOT_FOUND; + + PCIE_FIX; + if (bus->number == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } else { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000001 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + PCIE_FIX; + temp = in_le32(cfg_data); + switch (len) { + case 1: + *val = (temp >> (((offset & 3))*8)) & 0xff; + break; + case 2: + *val = (temp >> (((offset & 3))*8)) & 0xffff; + break; + default: + *val = temp; + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int +indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 val) +{ + struct pci_controller *hose = bus->sysdata; + volatile void __iomem *cfg_data; + u32 temp; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* Possible artifact of CDCpp50937 needs further investigation */ + if (devfn != 0x0 && bus->number == 0xff) + return PCIBIOS_DEVICE_NOT_FOUND; + + PCIE_FIX; + if (bus->number == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } else { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000001 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + switch (len) { + case 1: + PCIE_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xff << ((offset & 3) * 8))) | + (val << ((offset & 3) * 8)); + PCIE_FIX; + out_le32(cfg_data, temp); + break; + case 2: + PCIE_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xffff << ((offset & 3) * 8))); + temp |= (val << ((offset & 3) * 8)) ; + PCIE_FIX; + out_le32(cfg_data, temp); + break; + default: + PCIE_FIX; + out_le32(cfg_data, val); + break; + } + PCIE_FIX; + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops indirect_pcie_ops = { + indirect_read_config_pcie, + indirect_write_config_pcie +}; + +void __init +setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr, + void __iomem * cfg_data) +{ + hose->cfg_addr = cfg_addr; + hose->cfg_data = cfg_data; + hose->ops = &indirect_pcie_ops; +} + +void __init +setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) +{ + unsigned long base = cfg_addr & PAGE_MASK; + void __iomem *mbase, *addr, *data; + + mbase = ioremap(base, PAGE_SIZE); + addr = mbase + (cfg_addr & ~PAGE_MASK); + if ((cfg_data & PAGE_MASK) != base) + mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); + data = mbase + (cfg_data & ~PAGE_MASK); + setup_indirect_pcie_nomap(hose, addr, data); +} diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c new file mode 100644 index 0000000..944ec4b --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c @@ -0,0 +1,117 @@ +/* + * Author: Xianghua Xiao + * Zhang Wei + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "mpc86xx.h" + +extern void __secondary_start_mpc86xx(void); +extern unsigned long __secondary_hold_acknowledge; + + +static void __init +smp_86xx_release_core(int nr) +{ + void *mcm_vaddr; + unsigned long vaddr, pcr; + + if (nr < 0 || nr >= NR_CPUS) + return; + + /* + * Startup Core #nr. + */ + mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET, + MPC86xx_MCM_SIZE); + vaddr = (unsigned long)mcm_vaddr + MCM_PORT_CONFIG_OFFSET; + pcr = in_be32((volatile unsigned *)vaddr); + pcr |= 1 << (nr + 24); + out_be32((volatile unsigned *)vaddr, pcr); +} + + +static void __init +smp_86xx_kick_cpu(int nr) +{ + unsigned int save_vector; + unsigned long target, flags; + int n = 0; + volatile unsigned int *vector + = (volatile unsigned int *)(KERNELBASE + 0x100); + + if (nr < 0 || nr >= NR_CPUS) + return; + + pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr); + + local_irq_save(flags); + local_irq_disable(); + + /* Save reset vector */ + save_vector = *vector; + + /* Setup fake reset vector to call __secondary_start_mpc86xx. */ + target = (unsigned long) __secondary_start_mpc86xx; + create_branch((unsigned long)vector, target, BRANCH_SET_LINK); + + /* Kick that CPU */ + smp_86xx_release_core(nr); + + /* Wait a bit for the CPU to take the exception. */ + while ((__secondary_hold_acknowledge != nr) && (n++, n < 1000)) + mdelay(1); + + /* Restore the exception vector */ + *vector = save_vector; + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + local_irq_restore(flags); + + pr_debug("wait CPU #%d for %d msecs.\n", nr, n); +} + + +static void __init +smp_86xx_setup_cpu(int cpu_nr) +{ + mpic_setup_this_cpu(); +} + + +struct smp_ops_t smp_86xx_ops = { + .message_pass = smp_mpic_message_pass, + .probe = smp_mpic_probe, + .kick_cpu = smp_86xx_kick_cpu, + .setup_cpu = smp_86xx_setup_cpu, + .take_timebase = smp_generic_take_timebase, + .give_timebase = smp_generic_give_timebase, +}; + + +void __init +mpc86xx_smp_init(void) +{ + smp_ops = &smp_86xx_ops; +} diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c new file mode 100644 index 0000000..5180df7 --- /dev/null +++ b/arch/powerpc/platforms/86xx/pci.c @@ -0,0 +1,325 @@ +/* + * MPC86XX pci setup code + * + * Recode: ZHANG WEI + * Initial author: Xianghua Xiao + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "mpc86xx.h" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) +#else +#define DBG(fmt, args...) +#endif + +struct pcie_outbound_window_regs { + uint pexotar; /* 0x.0 - PCI Express outbound translation address register */ + uint pexotear; /* 0x.4 - PCI Express outbound translation extended address register */ + uint pexowbar; /* 0x.8 - PCI Express outbound window base address register */ + char res1[4]; + uint pexowar; /* 0x.10 - PCI Express outbound window attributes register */ + char res2[12]; +}; + +struct pcie_inbound_window_regs { + uint pexitar; /* 0x.0 - PCI Express inbound translation address register */ + char res1[4]; + uint pexiwbar; /* 0x.8 - PCI Express inbound window base address register */ + uint pexiwbear; /* 0x.c - PCI Express inbound window base extended address register */ + uint pexiwar; /* 0x.10 - PCI Express inbound window attributes register */ + char res2[12]; +}; + +static void __init setup_pcie_atmu(struct pci_controller *hose, struct resource *rsrc) +{ + volatile struct ccsr_pex *pcie; + volatile struct pcie_outbound_window_regs *pcieow; + volatile struct pcie_inbound_window_regs *pcieiw; + int i = 0; + + DBG("PCIE memory map start 0x%x, size 0x%x\n", rsrc->start, + rsrc->end - rsrc->start + 1); + pcie = ioremap(rsrc->start, rsrc->end - rsrc->start + 1); + + /* Disable all windows (except pexowar0 since its ignored) */ + pcie->pexowar1 = 0; + pcie->pexowar2 = 0; + pcie->pexowar3 = 0; + pcie->pexowar4 = 0; + pcie->pexiwar1 = 0; + pcie->pexiwar2 = 0; + pcie->pexiwar3 = 0; + + pcieow = (struct pcie_outbound_window_regs *)&pcie->pexotar1; + pcieiw = (struct pcie_inbound_window_regs *)&pcie->pexitar1; + + /* Setup outbound MEM window */ + for(i = 0; i < 3; i++) + if (hose->mem_resources[i].flags & IORESOURCE_MEM){ + DBG("PCIE MEM resource start 0x%08x, size 0x%08x.\n", + hose->mem_resources[i].start, + hose->mem_resources[i].end + - hose->mem_resources[i].start + 1); + pcieow->pexotar = (hose->mem_resources[i].start) >> 12 + & 0x000fffff; + pcieow->pexotear = 0; + pcieow->pexowbar = (hose->mem_resources[i].start) >> 12 + & 0x000fffff; + /* Enable, Mem R/W */ + pcieow->pexowar = 0x80044000 | + (__ilog2(hose->mem_resources[i].end + - hose->mem_resources[i].start + 1) + - 1); + pcieow++; + } + + /* Setup outbound IO window */ + if (hose->io_resource.flags & IORESOURCE_IO){ + DBG("PCIE IO resource start 0x%08x, size 0x%08x, phy base 0x%08x.\n", + hose->io_resource.start, + hose->io_resource.end - hose->io_resource.start + 1, + hose->io_base_phys); + pcieow->pexotar = (hose->io_resource.start) >> 12 & 0x000fffff; + pcieow->pexotear = 0; + pcieow->pexowbar = (hose->io_base_phys) >> 12 & 0x000fffff; + /* Enable, IO R/W */ + pcieow->pexowar = 0x80088000 | (__ilog2(hose->io_resource.end + - hose->io_resource.start + 1) - 1); + } + + /* Setup 2G inbound Memory Window @ 0 */ + pcieiw->pexitar = 0x00000000; + pcieiw->pexiwbar = 0x00000000; + /* Enable, Prefetch, Local Mem, Snoop R/W, 2G */ + pcieiw->pexiwar = 0xa0f5501e; +} + +static void __init +mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) +{ + volatile struct ccsr_pex *pcie; + u16 cmd; + unsigned int temps; + + DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", + pcie_offset, pcie_size); + + pcie = ioremap(pcie_offset, pcie_size); + + early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY + | PCI_COMMAND_IO; + early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); + + early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); + + /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */ + early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps); + temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16); + early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps); +} + +int __init add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + struct resource rsrc; + int *bus_range; + int has_address = 0; + int primary = 0; + + DBG("Adding PCIE host bridge %s\n", dev->full_name); + + /* Fetch host bridge registers address */ + has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); + + /* Get bus range if any */ + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) + printk(KERN_WARNING "Can't get bus-range for %s, assume" + " bus 0\n", dev->full_name); + + hose = pcibios_alloc_controller(); + if (!hose) + return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; + + /* last_busno = 0xfe cause by MPC8641 PCIE bug */ + hose->first_busno = bus_range ? bus_range[0] : 0x0; + hose->last_busno = bus_range ? bus_range[1] : 0xfe; + + setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4); + + /* Setup the PCIE host controller. */ + mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); + + if ((rsrc.start & 0xfffff) == 0x8000) + primary = 1; + + printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. " + "Firmware bus number: %d->%d\n", + rsrc.start, hose->first_busno, hose->last_busno); + + DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", + hose, hose->cfg_addr, hose->cfg_data); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pci_process_bridge_OF_ranges(hose, dev, primary); + + /* Setup PEX window registers */ + setup_pcie_atmu(hose, &rsrc); + + return 0; +} + +static void __devinit quirk_ali1575(struct pci_dev *dev) +{ + unsigned short temp; + + /* + * ALI1575 interrupts route table setup: + * + * IRQ pin IRQ# + * PIRQA ---- 3 + * PIRQB ---- 4 + * PIRQC ---- 5 + * PIRQD ---- 6 + * PIRQE ---- 9 + * PIRQF ---- 10 + * PIRQG ---- 11 + * PIRQH ---- 12 + * + * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD + * PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA + */ + pci_write_config_dword(dev, 0x48, 0xb9317542); + + /* USB 1.1 OHCI controller 1, interrupt: PIRQE */ + pci_write_config_byte(dev, 0x86, 0x0c); + + /* USB 1.1 OHCI controller 2, interrupt: PIRQF */ + pci_write_config_byte(dev, 0x87, 0x0d); + + /* USB 1.1 OHCI controller 3, interrupt: PIRQH */ + pci_write_config_byte(dev, 0x88, 0x0f); + + /* USB 2.0 controller, interrupt: PIRQ7 */ + pci_write_config_byte(dev, 0x74, 0x06); + + /* Audio controller, interrupt: PIRQE */ + pci_write_config_byte(dev, 0x8a, 0x0c); + + /* Modem controller, interrupt: PIRQF */ + pci_write_config_byte(dev, 0x8b, 0x0d); + + /* HD audio controller, interrupt: PIRQG */ + pci_write_config_byte(dev, 0x8c, 0x0e); + + /* Serial ATA interrupt: PIRQD */ + pci_write_config_byte(dev, 0x8d, 0x0b); + + /* SMB interrupt: PIRQH */ + pci_write_config_byte(dev, 0x8e, 0x0f); + + /* PMU ACPI SCI interrupt: PIRQH */ + pci_write_config_byte(dev, 0x8f, 0x0f); + + /* Primary PATA IDE IRQ: 14 + * Secondary PATA IDE IRQ: 15 + */ + pci_write_config_byte(dev, 0x44, 0x3d); + pci_write_config_byte(dev, 0x75, 0x0f); + + /* Set IRQ14 and IRQ15 to legacy IRQs */ + pci_read_config_word(dev, 0x46, &temp); + temp |= 0xc000; + pci_write_config_word(dev, 0x46, temp); + + /* Set i8259 interrupt trigger + * IRQ 3: Level + * IRQ 4: Level + * IRQ 5: Level + * IRQ 6: Level + * IRQ 7: Level + * IRQ 9: Level + * IRQ 10: Level + * IRQ 11: Level + * IRQ 12: Level + * IRQ 14: Edge + * IRQ 15: Edge + */ + outb(0xfa, 0x4d0); + outb(0x1e, 0x4d1); +} + +static void __devinit quirk_uli5288(struct pci_dev *dev) +{ + unsigned char c; + + pci_read_config_byte(dev,0x83,&c); + c |= 0x80; + pci_write_config_byte(dev, 0x83, c); + + pci_write_config_byte(dev, 0x09, 0x01); + pci_write_config_byte(dev, 0x0a, 0x06); + + pci_read_config_byte(dev,0x83,&c); + c &= 0x7f; + pci_write_config_byte(dev, 0x83, c); + + pci_read_config_byte(dev,0x84,&c); + c |= 0x01; + pci_write_config_byte(dev, 0x84, c); +} + +static void __devinit quirk_uli5229(struct pci_dev *dev) +{ + unsigned short temp; + pci_write_config_word(dev, 0x04, 0x0405); + pci_read_config_word(dev, 0x4a, &temp); + temp |= 0x1000; + pci_write_config_word(dev, 0x4a, temp); +} + +static void __devinit early_uli5249(struct pci_dev *dev) +{ + unsigned char temp; + pci_write_config_word(dev, 0x04, 0x0007); + pci_read_config_byte(dev, 0x7c, &temp); + pci_write_config_byte(dev, 0x7c, 0x80); + pci_write_config_byte(dev, 0x09, 0x01); + pci_write_config_byte(dev, 0x7c, temp); + dev->class |= 0x1; +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_ali1575); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249); diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index c4f6b0d..2928636 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_PPC_CHRP) += chrp/ obj-$(CONFIG_4xx) += 4xx/ obj-$(CONFIG_PPC_83xx) += 83xx/ obj-$(CONFIG_PPC_85xx) += 85xx/ +obj-$(CONFIG_PPC_86xx) += 86xx/ obj-$(CONFIG_PPC_PSERIES) += pseries/ obj-$(CONFIG_PPC_ISERIES) += iseries/ obj-$(CONFIG_PPC_MAPLE) += maple/ diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 6a02d51..352bbba 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -5,15 +5,24 @@ config SPU_FS tristate "SPU file system" default m depends on PPC_CELL + select SPU_BASE help The SPU file system is used to access Synergistic Processing Units on machines implementing the Broadband Processor Architecture. +config SPU_BASE + bool + default n + config SPUFS_MMAP bool depends on SPU_FS && SPARSEMEM select MEMORY_HOTPLUG default y +config CBE_RAS + bool "RAS features for bare metal Cell BE" + default y + endmenu diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index e570bad..c89cdd6 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -1,16 +1,15 @@ -obj-y += interrupt.o iommu.o setup.o spider-pic.o -obj-y += pervasive.o +obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ + cbe_regs.o spider-pic.o pervasive.o +obj-$(CONFIG_CBE_RAS) += ras.o -obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_SPU_FS) += spu-base.o spufs/ - -spu-base-y += spu_base.o spu_priv1.o +ifeq ($(CONFIG_SMP),y) +obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o +endif # needed only when building loadable spufs.ko -spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o -obj-y += $(spufs-modular-m) - -# always needed in kernel -spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o -obj-y += $(spufs-builtin-y) $(spufs-builtin-m) +spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o +spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o +obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ + $(spufs-modular-m) \ + $(spu-priv1-y) spufs/ diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c new file mode 100644 index 0000000..ce696c1 --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -0,0 +1,128 @@ +/* + * cbe_regs.c + * + * Accessor routines for the various MMIO register blocks of the CBE + * + * (c) 2006 Benjamin Herrenschmidt , IBM Corp. + */ + + +#include +#include +#include + +#include +#include +#include +#include + +#include "cbe_regs.h" + +#define MAX_CBE 2 + +/* + * Current implementation uses "cpu" nodes. We build our own mapping + * array of cpu numbers to cpu nodes locally for now to allow interrupt + * time code to have a fast path rather than call of_get_cpu_node(). If + * we implement cpu hotplug, we'll have to install an appropriate norifier + * in order to release references to the cpu going away + */ +static struct cbe_regs_map +{ + struct device_node *cpu_node; + struct cbe_pmd_regs __iomem *pmd_regs; + struct cbe_iic_regs __iomem *iic_regs; +} cbe_regs_maps[MAX_CBE]; +static int cbe_regs_map_count; + +static struct cbe_thread_map +{ + struct device_node *cpu_node; + struct cbe_regs_map *regs; +} cbe_thread_map[NR_CPUS]; + +static struct cbe_regs_map *cbe_find_map(struct device_node *np) +{ + int i; + + for (i = 0; i < cbe_regs_map_count; i++) + if (cbe_regs_maps[i].cpu_node == np) + return &cbe_regs_maps[i]; + return NULL; +} + +struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) +{ + struct cbe_regs_map *map = cbe_find_map(np); + if (map == NULL) + return NULL; + return map->pmd_regs; +} + +struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) +{ + struct cbe_regs_map *map = cbe_thread_map[cpu].regs; + if (map == NULL) + return NULL; + return map->pmd_regs; +} + + +struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) +{ + struct cbe_regs_map *map = cbe_find_map(np); + if (map == NULL) + return NULL; + return map->iic_regs; +} +struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu) +{ + struct cbe_regs_map *map = cbe_thread_map[cpu].regs; + if (map == NULL) + return NULL; + return map->iic_regs; +} + +void __init cbe_regs_init(void) +{ + int i; + struct device_node *cpu; + + /* Build local fast map of CPUs */ + for_each_possible_cpu(i) + cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL); + + /* Find maps for each device tree CPU */ + for_each_node_by_type(cpu, "cpu") { + struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++]; + + /* That hack must die die die ! */ + struct address_prop { + unsigned long address; + unsigned int len; + } __attribute__((packed)) *prop; + + + if (cbe_regs_map_count > MAX_CBE) { + printk(KERN_ERR "cbe_regs: More BE chips than supported" + "!\n"); + cbe_regs_map_count--; + return; + } + map->cpu_node = cpu; + for_each_possible_cpu(i) + if (cbe_thread_map[i].cpu_node == cpu) + cbe_thread_map[i].regs = map; + + prop = (struct address_prop *)get_property(cpu, "pervasive", + NULL); + if (prop != NULL) + map->pmd_regs = ioremap(prop->address, prop->len); + + prop = (struct address_prop *)get_property(cpu, "iic", + NULL); + if (prop != NULL) + map->iic_regs = ioremap(prop->address, prop->len); + } +} + diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h new file mode 100644 index 0000000..e76e4a6 --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -0,0 +1,129 @@ +/* + * cbe_regs.h + * + * This file is intended to hold the various register definitions for CBE + * on-chip system devices (memory controller, IO controller, etc...) + * + * (c) 2006 Benjamin Herrenschmidt , IBM Corp. + */ + +#ifndef CBE_REGS_H +#define CBE_REGS_H + +/* + * + * Some HID register definitions + * + */ + +/* CBE specific HID0 bits */ +#define HID0_CBE_THERM_WAKEUP 0x0000020000000000ul +#define HID0_CBE_SYSERR_WAKEUP 0x0000008000000000ul +#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul +#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul + + +/* + * + * Pervasive unit register definitions + * + */ + +struct cbe_pmd_regs { + u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */ + + /* Thermal Sensor Registers */ + u64 ts_ctsr1; /* 0x0800 */ + u64 ts_ctsr2; /* 0x0808 */ + u64 ts_mtsr1; /* 0x0810 */ + u64 ts_mtsr2; /* 0x0818 */ + u64 ts_itr1; /* 0x0820 */ + u64 ts_itr2; /* 0x0828 */ + u64 ts_gitr; /* 0x0830 */ + u64 ts_isr; /* 0x0838 */ + u64 ts_imr; /* 0x0840 */ + u64 tm_cr1; /* 0x0848 */ + u64 tm_cr2; /* 0x0850 */ + u64 tm_simr; /* 0x0858 */ + u64 tm_tpr; /* 0x0860 */ + u64 tm_str1; /* 0x0868 */ + u64 tm_str2; /* 0x0870 */ + u64 tm_tsr; /* 0x0878 */ + + /* Power Management */ + u64 pm_control; /* 0x0880 */ +#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 + u64 pm_status; /* 0x0888 */ + + /* Time Base Register */ + u64 tbr; /* 0x0890 */ + + u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ + + /* Fault Isolation Registers */ + u64 checkstop_fir; /* 0x0c00 */ + u64 recoverable_fir; + u64 spec_att_mchk_fir; + u64 fir_mode_reg; + u64 fir_enable_mask; + + u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */ +}; + +extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); +extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); + +/* + * + * IIC unit register definitions + * + */ + +struct cbe_iic_pending_bits { + u32 data; + u8 flags; + u8 class; + u8 source; + u8 prio; +}; + +#define CBE_IIC_IRQ_VALID 0x80 +#define CBE_IIC_IRQ_IPI 0x40 + +struct cbe_iic_thread_regs { + struct cbe_iic_pending_bits pending; + struct cbe_iic_pending_bits pending_destr; + u64 generate; + u64 prio; +}; + +struct cbe_iic_regs { + u8 pad_0x0000_0x0400[0x0400 - 0x0000]; /* 0x0000 */ + + /* IIC interrupt registers */ + struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ + u64 iic_ir; /* 0x0440 */ + u64 iic_is; /* 0x0448 */ + + u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */ + + /* IOC FIR */ + u64 ioc_fir_reset; /* 0x0500 */ + u64 ioc_fir_set; + u64 ioc_checkstop_enable; + u64 ioc_fir_error_mask; + u64 ioc_syserr_enable; + u64 ioc_fir; + + u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */ +}; + +extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np); +extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu); + + +/* Init this module early */ +extern void cbe_regs_init(void); + + +#endif /* CBE_REGS_H */ diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 978be1c..1bbf822 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -33,29 +33,10 @@ #include #include #include "interrupt.h" - -struct iic_pending_bits { - u32 data; - u8 flags; - u8 class; - u8 source; - u8 prio; -}; - -enum iic_pending_flags { - IIC_VALID = 0x80, - IIC_IPI = 0x40, -}; - -struct iic_regs { - struct iic_pending_bits pending; - struct iic_pending_bits pending_destr; - u64 generate; - u64 prio; -}; +#include "cbe_regs.h" struct iic { - struct iic_regs __iomem *regs; + struct cbe_iic_thread_regs __iomem *regs; u8 target_id; }; @@ -115,7 +96,7 @@ static struct hw_interrupt_type iic_pic .end = iic_end, }; -static int iic_external_get_irq(struct iic_pending_bits pending) +static int iic_external_get_irq(struct cbe_iic_pending_bits pending) { int irq; unsigned char node, unit; @@ -136,8 +117,7 @@ static int iic_external_get_irq(struct i * One of these units can be connected * to an external interrupt controller. */ - if (pending.prio > 0x3f || - pending.class != 2) + if (pending.class != 2) break; irq = IIC_EXT_OFFSET + spider_get_irq(node) @@ -168,15 +148,15 @@ int iic_get_irq(struct pt_regs *regs) { struct iic *iic; int irq; - struct iic_pending_bits pending; + struct cbe_iic_pending_bits pending; iic = &__get_cpu_var(iic); *(unsigned long *) &pending = in_be64((unsigned long __iomem *) &iic->regs->pending_destr); irq = -1; - if (pending.flags & IIC_VALID) { - if (pending.flags & IIC_IPI) { + if (pending.flags & CBE_IIC_IRQ_VALID) { + if (pending.flags & CBE_IIC_IRQ_IPI) { irq = IIC_IPI_OFFSET + (pending.prio >> 4); /* if (irq > 0x80) @@ -200,7 +180,7 @@ static int setup_iic_hardcoded(void) unsigned long regs; struct iic *iic; - for_each_cpu(cpu) { + for_each_possible_cpu(cpu) { iic = &per_cpu(iic, cpu); nodeid = cpu/2; @@ -226,7 +206,7 @@ static int setup_iic_hardcoded(void) regs += 0x20; printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs); - iic->regs = ioremap(regs, sizeof(struct iic_regs)); + iic->regs = ioremap(regs, sizeof(struct cbe_iic_thread_regs)); iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe); } @@ -267,12 +247,12 @@ static int setup_iic(void) } iic = &per_cpu(iic, np[0]); - iic->regs = ioremap(regs[0], sizeof(struct iic_regs)); + iic->regs = ioremap(regs[0], sizeof(struct cbe_iic_thread_regs)); iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe); printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs); iic = &per_cpu(iic, np[1]); - iic->regs = ioremap(regs[2], sizeof(struct iic_regs)); + iic->regs = ioremap(regs[2], sizeof(struct cbe_iic_thread_regs)); iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe); printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs); diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index a49ceb7..a35004e 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -473,6 +473,16 @@ static int cell_dma_supported(struct dev return mask < 0x100000000ull; } +static struct dma_mapping_ops cell_iommu_ops = { + .alloc_coherent = cell_alloc_coherent, + .free_coherent = cell_free_coherent, + .map_single = cell_map_single, + .unmap_single = cell_unmap_single, + .map_sg = cell_map_sg, + .unmap_sg = cell_unmap_sg, + .dma_supported = cell_dma_supported, +}; + void cell_init_iommu(void) { int setup_bus = 0; @@ -498,11 +508,5 @@ void cell_init_iommu(void) } } - pci_dma_ops.alloc_coherent = cell_alloc_coherent; - pci_dma_ops.free_coherent = cell_free_coherent; - pci_dma_ops.map_single = cell_map_single; - pci_dma_ops.unmap_single = cell_unmap_single; - pci_dma_ops.map_sg = cell_map_sg; - pci_dma_ops.unmap_sg = cell_unmap_sg; - pci_dma_ops.dma_supported = cell_dma_supported; + pci_dma_ops = cell_iommu_ops; } diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 7eed8c6..695ac4e 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -37,36 +37,28 @@ #include #include #include "pervasive.h" +#include "cbe_regs.h" static DEFINE_SPINLOCK(cbe_pervasive_lock); -struct cbe_pervasive { - struct pmd_regs __iomem *regs; - unsigned int thread; -}; - -/* can't use per_cpu from setup_arch */ -static struct cbe_pervasive cbe_pervasive[NR_CPUS]; static void __init cbe_enable_pause_zero(void) { unsigned long thread_switch_control; unsigned long temp_register; - struct cbe_pervasive *p; - int thread; + struct cbe_pmd_regs __iomem *pregs; spin_lock_irq(&cbe_pervasive_lock); - p = &cbe_pervasive[smp_processor_id()]; - - if (!cbe_pervasive->regs) + pregs = cbe_get_cpu_pmd_regs(smp_processor_id()); + if (pregs == NULL) goto out; pr_debug("Power Management: CPU %d\n", smp_processor_id()); /* Enable Pause(0) control bit */ - temp_register = in_be64(&p->regs->pm_control); + temp_register = in_be64(&pregs->pm_control); - out_be64(&p->regs->pm_control, - temp_register|PMD_PAUSE_ZERO_CONTROL); + out_be64(&pregs->pm_control, + temp_register | CBE_PMD_PAUSE_ZERO_CONTROL); /* Enable DEC and EE interrupt request */ thread_switch_control = mfspr(SPRN_TSC_CELL); @@ -75,25 +67,16 @@ static void __init cbe_enable_pause_zero switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) { case CTRL_CT0: thread_switch_control |= TSC_CELL_DEC_ENABLE_0; - thread = 0; break; case CTRL_CT1: thread_switch_control |= TSC_CELL_DEC_ENABLE_1; - thread = 1; break; default: printk(KERN_WARNING "%s: unknown configuration\n", __FUNCTION__); - thread = -1; break; } - if (p->thread != thread) - printk(KERN_WARNING "%s: device tree inconsistant, " - "cpu %i: %d/%d\n", __FUNCTION__, - smp_processor_id(), - p->thread, thread); - mtspr(SPRN_TSC_CELL, thread_switch_control); out: @@ -104,6 +87,11 @@ static void cbe_idle(void) { unsigned long ctrl; + /* Why do we do that on every idle ? Couldn't that be done once for + * all or do we lose the state some way ? Also, the pm_control + * register setting, that can't be set once at boot ? We really want + * to move that away in order to implement a simple powersave + */ cbe_enable_pause_zero(); while (1) { @@ -152,8 +140,15 @@ static int cbe_system_reset_exception(st timer_interrupt(regs); break; case SRR1_WAKEMT: - /* no action required */ break; +#ifdef CONFIG_CBE_RAS + case SRR1_WAKESYSERR: + cbe_system_error_exception(regs); + break; + case SRR1_WAKETHERM: + cbe_thermal_exception(regs); + break; +#endif /* CONFIG_CBE_RAS */ default: /* do system reset */ return 0; @@ -162,68 +157,11 @@ static int cbe_system_reset_exception(st return 1; } -static int __init cbe_find_pmd_mmio(int cpu, struct cbe_pervasive *p) -{ - struct device_node *node; - unsigned int *int_servers; - char *addr; - unsigned long real_address; - unsigned int size; - - struct pmd_regs __iomem *pmd_mmio_area; - int hardid, thread; - int proplen; - - pmd_mmio_area = NULL; - hardid = get_hard_smp_processor_id(cpu); - for (node = NULL; (node = of_find_node_by_type(node, "cpu"));) { - int_servers = (void *) get_property(node, - "ibm,ppc-interrupt-server#s", &proplen); - if (!int_servers) { - printk(KERN_WARNING "%s misses " - "ibm,ppc-interrupt-server#s property", - node->full_name); - continue; - } - for (thread = 0; thread < proplen / sizeof (int); thread++) { - if (hardid == int_servers[thread]) { - addr = get_property(node, "pervasive", NULL); - goto found; - } - } - } - - printk(KERN_WARNING "%s: CPU %d not found\n", __FUNCTION__, cpu); - return -EINVAL; - -found: - real_address = *(unsigned long*) addr; - addr += sizeof (unsigned long); - size = *(unsigned int*) addr; - - pr_debug("pervasive area for CPU %d at %lx, size %x\n", - cpu, real_address, size); - p->regs = ioremap(real_address, size); - p->thread = thread; - return 0; -} - -void __init cell_pervasive_init(void) +void __init cbe_pervasive_init(void) { - struct cbe_pervasive *p; - int cpu; - int ret; - if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) return; - for_each_possible_cpu(cpu) { - p = &cbe_pervasive[cpu]; - ret = cbe_find_pmd_mmio(cpu, p); - if (ret) - return; - } - ppc_md.idle_loop = cbe_idle; ppc_md.system_reset_exception = cbe_system_reset_exception; } diff --git a/arch/powerpc/platforms/cell/pervasive.h b/arch/powerpc/platforms/cell/pervasive.h index da1fb85..7b50947 100644 --- a/arch/powerpc/platforms/cell/pervasive.h +++ b/arch/powerpc/platforms/cell/pervasive.h @@ -25,38 +25,9 @@ #ifndef PERVASIVE_H #define PERVASIVE_H -struct pmd_regs { - u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */ - - /* Thermal Sensor Registers */ - u64 ts_ctsr1; /* 0x0800 */ - u64 ts_ctsr2; /* 0x0808 */ - u64 ts_mtsr1; /* 0x0810 */ - u64 ts_mtsr2; /* 0x0818 */ - u64 ts_itr1; /* 0x0820 */ - u64 ts_itr2; /* 0x0828 */ - u64 ts_gitr; /* 0x0830 */ - u64 ts_isr; /* 0x0838 */ - u64 ts_imr; /* 0x0840 */ - u64 tm_cr1; /* 0x0848 */ - u64 tm_cr2; /* 0x0850 */ - u64 tm_simr; /* 0x0858 */ - u64 tm_tpr; /* 0x0860 */ - u64 tm_str1; /* 0x0868 */ - u64 tm_str2; /* 0x0870 */ - u64 tm_tsr; /* 0x0878 */ - - /* Power Management */ - u64 pm_control; /* 0x0880 */ -#define PMD_PAUSE_ZERO_CONTROL 0x10000 - u64 pm_status; /* 0x0888 */ - - /* Time Base Register */ - u64 tbr; /* 0x0890 */ - - u8 pad_0x0898_0x1000 [0x1000 - 0x0898]; /* 0x0898 */ -}; - -void __init cell_pervasive_init(void); +extern void cbe_pervasive_init(void); +extern void cbe_system_error_exception(struct pt_regs *regs); +extern void cbe_maintenance_exception(struct pt_regs *regs); +extern void cbe_thermal_exception(struct pt_regs *regs); #endif diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c new file mode 100644 index 0000000..033ad6e --- /dev/null +++ b/arch/powerpc/platforms/cell/ras.c @@ -0,0 +1,112 @@ +#define DEBUG + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ras.h" +#include "cbe_regs.h" + + +static void dump_fir(int cpu) +{ + struct cbe_pmd_regs __iomem *pregs = cbe_get_cpu_pmd_regs(cpu); + struct cbe_iic_regs __iomem *iregs = cbe_get_cpu_iic_regs(cpu); + + if (pregs == NULL) + return; + + /* Todo: do some nicer parsing of bits and based on them go down + * to other sub-units FIRs and not only IIC + */ + printk(KERN_ERR "Global Checkstop FIR : 0x%016lx\n", + in_be64(&pregs->checkstop_fir)); + printk(KERN_ERR "Global Recoverable FIR : 0x%016lx\n", + in_be64(&pregs->checkstop_fir)); + printk(KERN_ERR "Global MachineCheck FIR : 0x%016lx\n", + in_be64(&pregs->spec_att_mchk_fir)); + + if (iregs == NULL) + return; + printk(KERN_ERR "IOC FIR : 0x%016lx\n", + in_be64(&iregs->ioc_fir)); + +} + +void cbe_system_error_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + printk(KERN_ERR "System Error Interrupt on CPU %d !\n", cpu); + dump_fir(cpu); + dump_stack(); +} + +void cbe_maintenance_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + /* + * Nothing implemented for the maintenance interrupt at this point + */ + + printk(KERN_ERR "Unhandled Maintenance interrupt on CPU %d !\n", cpu); + dump_stack(); +} + +void cbe_thermal_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + /* + * Nothing implemented for the thermal interrupt at this point + */ + + printk(KERN_ERR "Unhandled Thermal interrupt on CPU %d !\n", cpu); + dump_stack(); +} + +static int cbe_machine_check_handler(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + printk(KERN_ERR "Machine Check Interrupt on CPU %d !\n", cpu); + dump_fir(cpu); + + /* No recovery from this code now, lets continue */ + return 0; +} + +void __init cbe_ras_init(void) +{ + unsigned long hid0; + + /* + * Enable System Error & thermal interrupts and wakeup conditions + */ + + hid0 = mfspr(SPRN_HID0); + hid0 |= HID0_CBE_THERM_INT_EN | HID0_CBE_THERM_WAKEUP | + HID0_CBE_SYSERR_INT_EN | HID0_CBE_SYSERR_WAKEUP; + mtspr(SPRN_HID0, hid0); + mb(); + + /* + * Install machine check handler. Leave setting of precise mode to + * what the firmware did for now + */ + ppc_md.machine_check_exception = cbe_machine_check_handler; + mb(); + + /* + * For now, we assume that IOC_FIR is already set to forward some + * error conditions to the System Error handler. If that is not true + * then it will have to be fixed up here. + */ +} diff --git a/arch/powerpc/platforms/cell/ras.h b/arch/powerpc/platforms/cell/ras.h new file mode 100644 index 0000000..eb7ee54 --- /dev/null +++ b/arch/powerpc/platforms/cell/ras.h @@ -0,0 +1,9 @@ +#ifndef RAS_H +#define RAS_H + +extern void cbe_system_error_exception(struct pt_regs *regs); +extern void cbe_maintenance_exception(struct pt_regs *regs); +extern void cbe_thermal_exception(struct pt_regs *regs); +extern void cbe_ras_init(void); + +#endif /* RAS_H */ diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index fd3e560..3d1831d 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -49,10 +49,13 @@ #include #include #include #include +#include #include "interrupt.h" #include "iommu.h" +#include "cbe_regs.h" #include "pervasive.h" +#include "ras.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -81,6 +84,15 @@ static void __init cell_setup_arch(void) { ppc_md.init_IRQ = iic_init_IRQ; ppc_md.get_irq = iic_get_irq; +#ifdef CONFIG_SPU_BASE + spu_priv1_ops = &spu_priv1_mmio_ops; +#endif + + cbe_regs_init(); + +#ifdef CONFIG_CBE_RAS + cbe_ras_init(); +#endif #ifdef CONFIG_SMP smp_init_cell(); @@ -98,7 +110,7 @@ #endif init_pci_config_tokens(); find_and_init_phbs(); spider_init_IRQ(); - cell_pervasive_init(); + cbe_pervasive_init(); #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index ad141fe..db82f50 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -34,10 +34,15 @@ #include #include #include #include +#include #include #include "interrupt.h" +const struct spu_priv1_ops *spu_priv1_ops; + +EXPORT_SYMBOL_GPL(spu_priv1_ops); + static int __spu_trap_invalid_dma(struct spu *spu) { pr_debug("%s\n", __FUNCTION__); @@ -71,7 +76,7 @@ static int __spu_trap_data_seg(struct sp { struct spu_priv2 __iomem *priv2 = spu->priv2; struct mm_struct *mm = spu->mm; - u64 esid, vsid; + u64 esid, vsid, llp; pr_debug("%s\n", __FUNCTION__); @@ -91,9 +96,14 @@ static int __spu_trap_data_seg(struct sp } esid = (ea & ESID_MASK) | SLB_ESID_V; - vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | SLB_VSID_USER; +#ifdef CONFIG_HUGETLB_PAGE if (in_hugepage_area(mm->context, ea)) - vsid |= SLB_VSID_L; + llp = mmu_psize_defs[mmu_huge_psize].sllp; + else +#endif + llp = mmu_psize_defs[mmu_virtual_psize].sllp; + vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | + SLB_VSID_USER | llp; out_be64(&priv2->slb_index_W, spu->slb_replace); out_be64(&priv2->slb_vsid_RW, vsid); @@ -130,57 +140,7 @@ static int __spu_trap_data_map(struct sp spu->dar = ea; spu->dsisr = dsisr; mb(); - if (spu->stop_callback) - spu->stop_callback(spu); - return 0; -} - -static int __spu_trap_mailbox(struct spu *spu) -{ - if (spu->ibox_callback) - spu->ibox_callback(spu); - - /* atomically disable SPU mailbox interrupts */ - spin_lock(&spu->register_lock); - spu_int_mask_and(spu, 2, ~0x1); - spin_unlock(&spu->register_lock); - return 0; -} - -static int __spu_trap_stop(struct spu *spu) -{ - pr_debug("%s\n", __FUNCTION__); - spu->stop_code = in_be32(&spu->problem->spu_status_R); - if (spu->stop_callback) - spu->stop_callback(spu); - return 0; -} - -static int __spu_trap_halt(struct spu *spu) -{ - pr_debug("%s\n", __FUNCTION__); - spu->stop_code = in_be32(&spu->problem->spu_status_R); - if (spu->stop_callback) - spu->stop_callback(spu); - return 0; -} - -static int __spu_trap_tag_group(struct spu *spu) -{ - pr_debug("%s\n", __FUNCTION__); - spu->mfc_callback(spu); - return 0; -} - -static int __spu_trap_spubox(struct spu *spu) -{ - if (spu->wbox_callback) - spu->wbox_callback(spu); - - /* atomically disable SPU mailbox interrupts */ - spin_lock(&spu->register_lock); - spu_int_mask_and(spu, 2, ~0x10); - spin_unlock(&spu->register_lock); + spu->stop_callback(spu); return 0; } @@ -191,8 +151,7 @@ spu_irq_class_0(int irq, void *data, str spu = data; spu->class_0_pending = 1; - if (spu->stop_callback) - spu->stop_callback(spu); + spu->stop_callback(spu); return IRQ_HANDLED; } @@ -270,29 +229,38 @@ spu_irq_class_2(int irq, void *data, str unsigned long mask; spu = data; + spin_lock(&spu->register_lock); stat = spu_int_stat_get(spu, 2); mask = spu_int_mask_get(spu, 2); + /* ignore interrupts we're not waiting for */ + stat &= mask; + /* + * mailbox interrupts (0x1 and 0x10) are level triggered. + * mask them now before acknowledging. + */ + if (stat & 0x11) + spu_int_mask_and(spu, 2, ~(stat & 0x11)); + /* acknowledge all interrupts before the callbacks */ + spu_int_stat_clear(spu, 2, stat); + spin_unlock(&spu->register_lock); pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask); - stat &= mask; - if (stat & 1) /* PPC core mailbox */ - __spu_trap_mailbox(spu); + spu->ibox_callback(spu); if (stat & 2) /* SPU stop-and-signal */ - __spu_trap_stop(spu); + spu->stop_callback(spu); if (stat & 4) /* SPU halted */ - __spu_trap_halt(spu); + spu->stop_callback(spu); if (stat & 8) /* DMA tag group complete */ - __spu_trap_tag_group(spu); + spu->mfc_callback(spu); if (stat & 0x10) /* SPU mailbox threshold */ - __spu_trap_spubox(spu); + spu->wbox_callback(spu); - spu_int_stat_clear(spu, 2, stat); return stat ? IRQ_HANDLED : IRQ_NONE; } @@ -512,14 +480,6 @@ int spu_irq_class_1_bottom(struct spu *s return ret; } -void spu_irq_setaffinity(struct spu *spu, int cpu) -{ - u64 target = iic_get_target_id(cpu); - u64 route = target << 48 | target << 32 | target << 16; - spu_int_route_set(spu, route); -} -EXPORT_SYMBOL_GPL(spu_irq_setaffinity); - static int __init find_spu_node_id(struct device_node *spe) { unsigned int *id; @@ -649,6 +609,46 @@ out: return ret; } +struct sysdev_class spu_sysdev_class = { + set_kset_name("spu") +}; + +static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf) +{ + struct spu *spu = container_of(sysdev, struct spu, sysdev); + return sprintf(buf, "%d\n", spu->isrc); + +} +static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL); + +extern int attach_sysdev_to_node(struct sys_device *dev, int nid); + +static int spu_create_sysdev(struct spu *spu) +{ + int ret; + + spu->sysdev.id = spu->number; + spu->sysdev.cls = &spu_sysdev_class; + ret = sysdev_register(&spu->sysdev); + if (ret) { + printk(KERN_ERR "Can't register SPU %d with sysfs\n", + spu->number); + return ret; + } + + sysdev_create_file(&spu->sysdev, &attr_isrc); + sysfs_add_device_to_node(&spu->sysdev, spu->nid); + + return 0; +} + +static void spu_destroy_sysdev(struct spu *spu) +{ + sysdev_remove_file(&spu->sysdev, &attr_isrc); + sysfs_remove_device_from_node(&spu->sysdev, spu->nid); + sysdev_unregister(&spu->sysdev); +} + static int __init create_spu(struct device_node *spe) { struct spu *spu; @@ -656,7 +656,7 @@ static int __init create_spu(struct devi static int number; ret = -ENOMEM; - spu = kmalloc(sizeof (*spu), GFP_KERNEL); + spu = kzalloc(sizeof (*spu), GFP_KERNEL); if (!spu) goto out; @@ -668,33 +668,20 @@ static int __init create_spu(struct devi spu->nid = of_node_to_nid(spe); if (spu->nid == -1) spu->nid = 0; - - spu->stop_code = 0; - spu->slb_replace = 0; - spu->mm = NULL; - spu->ctx = NULL; - spu->rq = NULL; - spu->pid = 0; - spu->class_0_pending = 0; - spu->flags = 0UL; - spu->dar = 0UL; - spu->dsisr = 0UL; spin_lock_init(&spu->register_lock); - spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1)); spu_mfc_sr1_set(spu, 0x33); - - spu->ibox_callback = NULL; - spu->wbox_callback = NULL; - spu->stop_callback = NULL; - spu->mfc_callback = NULL; - mutex_lock(&spu_mutex); + spu->number = number++; ret = spu_request_irqs(spu); if (ret) goto out_unmap; + ret = spu_create_sysdev(spu); + if (ret) + goto out_free_irqs; + list_add(&spu->list, &spu_list); mutex_unlock(&spu_mutex); @@ -703,6 +690,9 @@ static int __init create_spu(struct devi spu->problem, spu->priv1, spu->priv2, spu->number); goto out; +out_free_irqs: + spu_free_irqs(spu); + out_unmap: mutex_unlock(&spu_mutex); spu_unmap(spu); @@ -716,6 +706,7 @@ static void destroy_spu(struct spu *spu) { list_del_init(&spu->list); + spu_destroy_sysdev(spu); spu_free_irqs(spu); spu_unmap(spu); kfree(spu); @@ -728,6 +719,7 @@ static void cleanup_spu_base(void) list_for_each_entry_safe(spu, tmp, &spu_list, list) destroy_spu(spu); mutex_unlock(&spu_mutex); + sysdev_class_unregister(&spu_sysdev_class); } module_exit(cleanup_spu_base); @@ -736,6 +728,11 @@ static int __init init_spu_base(void) struct device_node *node; int ret; + /* create sysdev class for spus */ + ret = sysdev_class_register(&spu_sysdev_class); + if (ret) + return ret; + ret = -ENODEV; for (node = of_find_node_by_type(NULL, "spe"); node; node = of_find_node_by_type(node, "spe")) { diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c index b47fcc5..47ec3be 100644 --- a/arch/powerpc/platforms/cell/spu_callbacks.c +++ b/arch/powerpc/platforms/cell/spu_callbacks.c @@ -34,307 +34,19 @@ #include */ void *spu_syscall_table[] = { - [__NR_restart_syscall] sys_ni_syscall, /* sys_restart_syscall */ - [__NR_exit] sys_ni_syscall, /* sys_exit */ - [__NR_fork] sys_ni_syscall, /* ppc_fork */ - [__NR_read] sys_read, - [__NR_write] sys_write, - [__NR_open] sys_open, - [__NR_close] sys_close, - [__NR_waitpid] sys_waitpid, - [__NR_creat] sys_creat, - [__NR_link] sys_link, - [__NR_unlink] sys_unlink, - [__NR_execve] sys_ni_syscall, /* sys_execve */ - [__NR_chdir] sys_chdir, - [__NR_time] sys_time, - [__NR_mknod] sys_mknod, - [__NR_chmod] sys_chmod, - [__NR_lchown] sys_lchown, - [__NR_break] sys_ni_syscall, - [__NR_oldstat] sys_ni_syscall, - [__NR_lseek] sys_lseek, - [__NR_getpid] sys_getpid, - [__NR_mount] sys_ni_syscall, /* sys_mount */ - [__NR_umount] sys_ni_syscall, - [__NR_setuid] sys_setuid, - [__NR_getuid] sys_getuid, - [__NR_stime] sys_stime, - [__NR_ptrace] sys_ni_syscall, /* sys_ptrace */ - [__NR_alarm] sys_alarm, - [__NR_oldfstat] sys_ni_syscall, - [__NR_pause] sys_ni_syscall, /* sys_pause */ - [__NR_utime] sys_ni_syscall, /* sys_utime */ - [__NR_stty] sys_ni_syscall, - [__NR_gtty] sys_ni_syscall, - [__NR_access] sys_access, - [__NR_nice] sys_nice, - [__NR_ftime] sys_ni_syscall, - [__NR_sync] sys_sync, - [__NR_kill] sys_kill, - [__NR_rename] sys_rename, - [__NR_mkdir] sys_mkdir, - [__NR_rmdir] sys_rmdir, - [__NR_dup] sys_dup, - [__NR_pipe] sys_pipe, - [__NR_times] sys_times, - [__NR_prof] sys_ni_syscall, - [__NR_brk] sys_brk, - [__NR_setgid] sys_setgid, - [__NR_getgid] sys_getgid, - [__NR_signal] sys_ni_syscall, /* sys_signal */ - [__NR_geteuid] sys_geteuid, - [__NR_getegid] sys_getegid, - [__NR_acct] sys_ni_syscall, /* sys_acct */ - [__NR_umount2] sys_ni_syscall, /* sys_umount */ - [__NR_lock] sys_ni_syscall, - [__NR_ioctl] sys_ioctl, - [__NR_fcntl] sys_fcntl, - [__NR_mpx] sys_ni_syscall, - [__NR_setpgid] sys_setpgid, - [__NR_ulimit] sys_ni_syscall, - [__NR_oldolduname] sys_ni_syscall, - [__NR_umask] sys_umask, - [__NR_chroot] sys_chroot, - [__NR_ustat] sys_ni_syscall, /* sys_ustat */ - [__NR_dup2] sys_dup2, - [__NR_getppid] sys_getppid, - [__NR_getpgrp] sys_getpgrp, - [__NR_setsid] sys_setsid, - [__NR_sigaction] sys_ni_syscall, - [__NR_sgetmask] sys_sgetmask, - [__NR_ssetmask] sys_ssetmask, - [__NR_setreuid] sys_setreuid, - [__NR_setregid] sys_setregid, - [__NR_sigsuspend] sys_ni_syscall, - [__NR_sigpending] sys_ni_syscall, - [__NR_sethostname] sys_sethostname, - [__NR_setrlimit] sys_setrlimit, - [__NR_getrlimit] sys_ni_syscall, - [__NR_getrusage] sys_getrusage, - [__NR_gettimeofday] sys_gettimeofday, - [__NR_settimeofday] sys_settimeofday, - [__NR_getgroups] sys_getgroups, - [__NR_setgroups] sys_setgroups, - [__NR_select] sys_ni_syscall, - [__NR_symlink] sys_symlink, - [__NR_oldlstat] sys_ni_syscall, - [__NR_readlink] sys_readlink, - [__NR_uselib] sys_ni_syscall, /* sys_uselib */ - [__NR_swapon] sys_ni_syscall, /* sys_swapon */ - [__NR_reboot] sys_ni_syscall, /* sys_reboot */ - [__NR_readdir] sys_ni_syscall, - [__NR_mmap] sys_mmap, - [__NR_munmap] sys_munmap, - [__NR_truncate] sys_truncate, - [__NR_ftruncate] sys_ftruncate, - [__NR_fchmod] sys_fchmod, - [__NR_fchown] sys_fchown, - [__NR_getpriority] sys_getpriority, - [__NR_setpriority] sys_setpriority, - [__NR_profil] sys_ni_syscall, - [__NR_statfs] sys_ni_syscall, /* sys_statfs */ - [__NR_fstatfs] sys_ni_syscall, /* sys_fstatfs */ - [__NR_ioperm] sys_ni_syscall, - [__NR_socketcall] sys_socketcall, - [__NR_syslog] sys_syslog, - [__NR_setitimer] sys_setitimer, - [__NR_getitimer] sys_getitimer, - [__NR_stat] sys_newstat, - [__NR_lstat] sys_newlstat, - [__NR_fstat] sys_newfstat, - [__NR_olduname] sys_ni_syscall, - [__NR_iopl] sys_ni_syscall, - [__NR_vhangup] sys_vhangup, - [__NR_idle] sys_ni_syscall, - [__NR_vm86] sys_ni_syscall, - [__NR_wait4] sys_wait4, - [__NR_swapoff] sys_ni_syscall, /* sys_swapoff */ - [__NR_sysinfo] sys_sysinfo, - [__NR_ipc] sys_ni_syscall, /* sys_ipc */ - [__NR_fsync] sys_fsync, - [__NR_sigreturn] sys_ni_syscall, - [__NR_clone] sys_ni_syscall, /* ppc_clone */ - [__NR_setdomainname] sys_setdomainname, - [__NR_uname] ppc_newuname, - [__NR_modify_ldt] sys_ni_syscall, - [__NR_adjtimex] sys_adjtimex, - [__NR_mprotect] sys_mprotect, - [__NR_sigprocmask] sys_ni_syscall, - [__NR_create_module] sys_ni_syscall, - [__NR_init_module] sys_ni_syscall, /* sys_init_module */ - [__NR_delete_module] sys_ni_syscall, /* sys_delete_module */ - [__NR_get_kernel_syms] sys_ni_syscall, - [__NR_quotactl] sys_ni_syscall, /* sys_quotactl */ - [__NR_getpgid] sys_getpgid, - [__NR_fchdir] sys_fchdir, - [__NR_bdflush] sys_bdflush, - [__NR_sysfs] sys_ni_syscall, /* sys_sysfs */ - [__NR_personality] ppc64_personality, - [__NR_afs_syscall] sys_ni_syscall, - [__NR_setfsuid] sys_setfsuid, - [__NR_setfsgid] sys_setfsgid, - [__NR__llseek] sys_llseek, - [__NR_getdents] sys_getdents, - [__NR__newselect] sys_select, - [__NR_flock] sys_flock, - [__NR_msync] sys_msync, - [__NR_readv] sys_readv, - [__NR_writev] sys_writev, - [__NR_getsid] sys_getsid, - [__NR_fdatasync] sys_fdatasync, - [__NR__sysctl] sys_ni_syscall, /* sys_sysctl */ - [__NR_mlock] sys_mlock, - [__NR_munlock] sys_munlock, - [__NR_mlockall] sys_mlockall, - [__NR_munlockall] sys_munlockall, - [__NR_sched_setparam] sys_sched_setparam, - [__NR_sched_getparam] sys_sched_getparam, - [__NR_sched_setscheduler] sys_sched_setscheduler, - [__NR_sched_getscheduler] sys_sched_getscheduler, - [__NR_sched_yield] sys_sched_yield, - [__NR_sched_get_priority_max] sys_sched_get_priority_max, - [__NR_sched_get_priority_min] sys_sched_get_priority_min, - [__NR_sched_rr_get_interval] sys_sched_rr_get_interval, - [__NR_nanosleep] sys_nanosleep, - [__NR_mremap] sys_mremap, - [__NR_setresuid] sys_setresuid, - [__NR_getresuid] sys_getresuid, - [__NR_query_module] sys_ni_syscall, - [__NR_poll] sys_poll, - [__NR_nfsservctl] sys_ni_syscall, /* sys_nfsservctl */ - [__NR_setresgid] sys_setresgid, - [__NR_getresgid] sys_getresgid, - [__NR_prctl] sys_prctl, - [__NR_rt_sigreturn] sys_ni_syscall, /* ppc64_rt_sigreturn */ - [__NR_rt_sigaction] sys_ni_syscall, /* sys_rt_sigaction */ - [__NR_rt_sigprocmask] sys_ni_syscall, /* sys_rt_sigprocmask */ - [__NR_rt_sigpending] sys_ni_syscall, /* sys_rt_sigpending */ - [__NR_rt_sigtimedwait] sys_ni_syscall, /* sys_rt_sigtimedwait */ - [__NR_rt_sigqueueinfo] sys_ni_syscall, /* sys_rt_sigqueueinfo */ - [__NR_rt_sigsuspend] sys_ni_syscall, /* sys_rt_sigsuspend */ - [__NR_pread64] sys_pread64, - [__NR_pwrite64] sys_pwrite64, - [__NR_chown] sys_chown, - [__NR_getcwd] sys_getcwd, - [__NR_capget] sys_capget, - [__NR_capset] sys_capset, - [__NR_sigaltstack] sys_ni_syscall, /* sys_sigaltstack */ - [__NR_sendfile] sys_sendfile64, - [__NR_getpmsg] sys_ni_syscall, - [__NR_putpmsg] sys_ni_syscall, - [__NR_vfork] sys_ni_syscall, /* ppc_vfork */ - [__NR_ugetrlimit] sys_getrlimit, - [__NR_readahead] sys_readahead, - [192] sys_ni_syscall, - [193] sys_ni_syscall, - [194] sys_ni_syscall, - [195] sys_ni_syscall, - [196] sys_ni_syscall, - [197] sys_ni_syscall, - [__NR_pciconfig_read] sys_ni_syscall, /* sys_pciconfig_read */ - [__NR_pciconfig_write] sys_ni_syscall, /* sys_pciconfig_write */ - [__NR_pciconfig_iobase] sys_ni_syscall, /* sys_pciconfig_iobase */ - [__NR_multiplexer] sys_ni_syscall, - [__NR_getdents64] sys_getdents64, - [__NR_pivot_root] sys_pivot_root, - [204] sys_ni_syscall, - [__NR_madvise] sys_madvise, - [__NR_mincore] sys_mincore, - [__NR_gettid] sys_gettid, - [__NR_tkill] sys_tkill, - [__NR_setxattr] sys_setxattr, - [__NR_lsetxattr] sys_lsetxattr, - [__NR_fsetxattr] sys_fsetxattr, - [__NR_getxattr] sys_getxattr, - [__NR_lgetxattr] sys_lgetxattr, - [__NR_fgetxattr] sys_fgetxattr, - [__NR_listxattr] sys_listxattr, - [__NR_llistxattr] sys_llistxattr, - [__NR_flistxattr] sys_flistxattr, - [__NR_removexattr] sys_removexattr, - [__NR_lremovexattr] sys_lremovexattr, - [__NR_fremovexattr] sys_fremovexattr, - [__NR_futex] sys_futex, - [__NR_sched_setaffinity] sys_sched_setaffinity, - [__NR_sched_getaffinity] sys_sched_getaffinity, - [224] sys_ni_syscall, - [__NR_tuxcall] sys_ni_syscall, - [226] sys_ni_syscall, - [__NR_io_setup] sys_io_setup, - [__NR_io_destroy] sys_io_destroy, - [__NR_io_getevents] sys_io_getevents, - [__NR_io_submit] sys_io_submit, - [__NR_io_cancel] sys_io_cancel, - [__NR_set_tid_address] sys_ni_syscall, /* sys_set_tid_address */ - [__NR_fadvise64] sys_fadvise64, - [__NR_exit_group] sys_ni_syscall, /* sys_exit_group */ - [__NR_lookup_dcookie] sys_ni_syscall, /* sys_lookup_dcookie */ - [__NR_epoll_create] sys_epoll_create, - [__NR_epoll_ctl] sys_epoll_ctl, - [__NR_epoll_wait] sys_epoll_wait, - [__NR_remap_file_pages] sys_remap_file_pages, - [__NR_timer_create] sys_timer_create, - [__NR_timer_settime] sys_timer_settime, - [__NR_timer_gettime] sys_timer_gettime, - [__NR_timer_getoverrun] sys_timer_getoverrun, - [__NR_timer_delete] sys_timer_delete, - [__NR_clock_settime] sys_clock_settime, - [__NR_clock_gettime] sys_clock_gettime, - [__NR_clock_getres] sys_clock_getres, - [__NR_clock_nanosleep] sys_clock_nanosleep, - [__NR_swapcontext] sys_ni_syscall, /* ppc64_swapcontext */ - [__NR_tgkill] sys_tgkill, - [__NR_utimes] sys_utimes, - [__NR_statfs64] sys_statfs64, - [__NR_fstatfs64] sys_fstatfs64, - [254] sys_ni_syscall, - [__NR_rtas] ppc_rtas, - [256] sys_ni_syscall, - [257] sys_ni_syscall, - [258] sys_ni_syscall, - [__NR_mbind] sys_ni_syscall, /* sys_mbind */ - [__NR_get_mempolicy] sys_ni_syscall, /* sys_get_mempolicy */ - [__NR_set_mempolicy] sys_ni_syscall, /* sys_set_mempolicy */ - [__NR_mq_open] sys_ni_syscall, /* sys_mq_open */ - [__NR_mq_unlink] sys_ni_syscall, /* sys_mq_unlink */ - [__NR_mq_timedsend] sys_ni_syscall, /* sys_mq_timedsend */ - [__NR_mq_timedreceive] sys_ni_syscall, /* sys_mq_timedreceive */ - [__NR_mq_notify] sys_ni_syscall, /* sys_mq_notify */ - [__NR_mq_getsetattr] sys_ni_syscall, /* sys_mq_getsetattr */ - [__NR_kexec_load] sys_ni_syscall, /* sys_kexec_load */ - [__NR_add_key] sys_ni_syscall, /* sys_add_key */ - [__NR_request_key] sys_ni_syscall, /* sys_request_key */ - [__NR_keyctl] sys_ni_syscall, /* sys_keyctl */ - [__NR_waitid] sys_ni_syscall, /* sys_waitid */ - [__NR_ioprio_set] sys_ni_syscall, /* sys_ioprio_set */ - [__NR_ioprio_get] sys_ni_syscall, /* sys_ioprio_get */ - [__NR_inotify_init] sys_ni_syscall, /* sys_inotify_init */ - [__NR_inotify_add_watch] sys_ni_syscall, /* sys_inotify_add_watch */ - [__NR_inotify_rm_watch] sys_ni_syscall, /* sys_inotify_rm_watch */ - [__NR_spu_run] sys_ni_syscall, /* sys_spu_run */ - [__NR_spu_create] sys_ni_syscall, /* sys_spu_create */ - [__NR_pselect6] sys_ni_syscall, /* sys_pselect */ - [__NR_ppoll] sys_ni_syscall, /* sys_ppoll */ - [__NR_unshare] sys_unshare, - [__NR_splice] sys_splice, - [__NR_tee] sys_tee, - [__NR_vmsplice] sys_vmsplice, - [__NR_openat] sys_openat, - [__NR_mkdirat] sys_mkdirat, - [__NR_mknodat] sys_mknodat, - [__NR_fchownat] sys_fchownat, - [__NR_futimesat] sys_futimesat, - [__NR_newfstatat] sys_newfstatat, - [__NR_unlinkat] sys_unlinkat, - [__NR_renameat] sys_renameat, - [__NR_linkat] sys_linkat, - [__NR_symlinkat] sys_symlinkat, - [__NR_readlinkat] sys_readlinkat, - [__NR_fchmodat] sys_fchmodat, - [__NR_faccessat] sys_faccessat, - [__NR_get_robust_list] sys_get_robust_list, - [__NR_set_robust_list] sys_set_robust_list, +#define SYSCALL(func) sys_ni_syscall, +#define COMPAT_SYS(func) sys_ni_syscall, +#define PPC_SYS(func) sys_ni_syscall, +#define OLDSYS(func) sys_ni_syscall, +#define SYS32ONLY(func) sys_ni_syscall, +#define SYSX(f, f3264, f32) sys_ni_syscall, + +#define SYSCALL_SPU(func) sys_##func, +#define COMPAT_SYS_SPU(func) sys_##func, +#define PPC_SYS_SPU(func) ppc_##func, +#define SYSX_SPU(f, f3264, f32) f, + +#include }; long spu_sys_callback(struct spu_syscall_block *s) diff --git a/arch/powerpc/platforms/cell/spu_priv1.c b/arch/powerpc/platforms/cell/spu_priv1.c deleted file mode 100644 index b265642..0000000 --- a/arch/powerpc/platforms/cell/spu_priv1.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * access to SPU privileged registers - */ -#include - -#include -#include - -void spu_int_mask_and(struct spu *spu, int class, u64 mask) -{ - u64 old_mask; - - old_mask = in_be64(&spu->priv1->int_mask_RW[class]); - out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); -} -EXPORT_SYMBOL_GPL(spu_int_mask_and); - -void spu_int_mask_or(struct spu *spu, int class, u64 mask) -{ - u64 old_mask; - - old_mask = in_be64(&spu->priv1->int_mask_RW[class]); - out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); -} -EXPORT_SYMBOL_GPL(spu_int_mask_or); - -void spu_int_mask_set(struct spu *spu, int class, u64 mask) -{ - out_be64(&spu->priv1->int_mask_RW[class], mask); -} -EXPORT_SYMBOL_GPL(spu_int_mask_set); - -u64 spu_int_mask_get(struct spu *spu, int class) -{ - return in_be64(&spu->priv1->int_mask_RW[class]); -} -EXPORT_SYMBOL_GPL(spu_int_mask_get); - -void spu_int_stat_clear(struct spu *spu, int class, u64 stat) -{ - out_be64(&spu->priv1->int_stat_RW[class], stat); -} -EXPORT_SYMBOL_GPL(spu_int_stat_clear); - -u64 spu_int_stat_get(struct spu *spu, int class) -{ - return in_be64(&spu->priv1->int_stat_RW[class]); -} -EXPORT_SYMBOL_GPL(spu_int_stat_get); - -void spu_int_route_set(struct spu *spu, u64 route) -{ - out_be64(&spu->priv1->int_route_RW, route); -} -EXPORT_SYMBOL_GPL(spu_int_route_set); - -u64 spu_mfc_dar_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_dar_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_dar_get); - -u64 spu_mfc_dsisr_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_dsisr_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get); - -void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr) -{ - out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); -} -EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set); - -void spu_mfc_sdr_set(struct spu *spu, u64 sdr) -{ - out_be64(&spu->priv1->mfc_sdr_RW, sdr); -} -EXPORT_SYMBOL_GPL(spu_mfc_sdr_set); - -void spu_mfc_sr1_set(struct spu *spu, u64 sr1) -{ - out_be64(&spu->priv1->mfc_sr1_RW, sr1); -} -EXPORT_SYMBOL_GPL(spu_mfc_sr1_set); - -u64 spu_mfc_sr1_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_sr1_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_sr1_get); - -void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id) -{ - out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); -} -EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set); - -u64 spu_mfc_tclass_id_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_tclass_id_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get); - -void spu_tlb_invalidate(struct spu *spu) -{ - out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); -} -EXPORT_SYMBOL_GPL(spu_tlb_invalidate); - -void spu_resource_allocation_groupID_set(struct spu *spu, u64 id) -{ - out_be64(&spu->priv1->resource_allocation_groupID_RW, id); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set); - -u64 spu_resource_allocation_groupID_get(struct spu *spu) -{ - return in_be64(&spu->priv1->resource_allocation_groupID_RW); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get); - -void spu_resource_allocation_enable_set(struct spu *spu, u64 enable) -{ - out_be64(&spu->priv1->resource_allocation_enable_RW, enable); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set); - -u64 spu_resource_allocation_enable_get(struct spu *spu) -{ - return in_be64(&spu->priv1->resource_allocation_enable_RW); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get); diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c new file mode 100644 index 0000000..71b69f0 --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -0,0 +1,159 @@ +/* + * spu hypervisor abstraction for direct hardware access. + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * Copyright 2006 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include +#include +#include + +#include "interrupt.h" + +static void int_mask_and(struct spu *spu, int class, u64 mask) +{ + u64 old_mask; + + old_mask = in_be64(&spu->priv1->int_mask_RW[class]); + out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); +} + +static void int_mask_or(struct spu *spu, int class, u64 mask) +{ + u64 old_mask; + + old_mask = in_be64(&spu->priv1->int_mask_RW[class]); + out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); +} + +static void int_mask_set(struct spu *spu, int class, u64 mask) +{ + out_be64(&spu->priv1->int_mask_RW[class], mask); +} + +static u64 int_mask_get(struct spu *spu, int class) +{ + return in_be64(&spu->priv1->int_mask_RW[class]); +} + +static void int_stat_clear(struct spu *spu, int class, u64 stat) +{ + out_be64(&spu->priv1->int_stat_RW[class], stat); +} + +static u64 int_stat_get(struct spu *spu, int class) +{ + return in_be64(&spu->priv1->int_stat_RW[class]); +} + +static void cpu_affinity_set(struct spu *spu, int cpu) +{ + u64 target = iic_get_target_id(cpu); + u64 route = target << 48 | target << 32 | target << 16; + out_be64(&spu->priv1->int_route_RW, route); +} + +static u64 mfc_dar_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_dar_RW); +} + +static u64 mfc_dsisr_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_dsisr_RW); +} + +static void mfc_dsisr_set(struct spu *spu, u64 dsisr) +{ + out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); +} + +static void mfc_sdr_set(struct spu *spu, u64 sdr) +{ + out_be64(&spu->priv1->mfc_sdr_RW, sdr); +} + +static void mfc_sr1_set(struct spu *spu, u64 sr1) +{ + out_be64(&spu->priv1->mfc_sr1_RW, sr1); +} + +static u64 mfc_sr1_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_sr1_RW); +} + +static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) +{ + out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); +} + +static u64 mfc_tclass_id_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_tclass_id_RW); +} + +static void tlb_invalidate(struct spu *spu) +{ + out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); +} + +static void resource_allocation_groupID_set(struct spu *spu, u64 id) +{ + out_be64(&spu->priv1->resource_allocation_groupID_RW, id); +} + +static u64 resource_allocation_groupID_get(struct spu *spu) +{ + return in_be64(&spu->priv1->resource_allocation_groupID_RW); +} + +static void resource_allocation_enable_set(struct spu *spu, u64 enable) +{ + out_be64(&spu->priv1->resource_allocation_enable_RW, enable); +} + +static u64 resource_allocation_enable_get(struct spu *spu) +{ + return in_be64(&spu->priv1->resource_allocation_enable_RW); +} + +const struct spu_priv1_ops spu_priv1_mmio_ops = +{ + .int_mask_and = int_mask_and, + .int_mask_or = int_mask_or, + .int_mask_set = int_mask_set, + .int_mask_get = int_mask_get, + .int_stat_clear = int_stat_clear, + .int_stat_get = int_stat_get, + .cpu_affinity_set = cpu_affinity_set, + .mfc_dar_get = mfc_dar_get, + .mfc_dsisr_get = mfc_dsisr_get, + .mfc_dsisr_set = mfc_dsisr_set, + .mfc_sdr_set = mfc_sdr_set, + .mfc_sr1_set = mfc_sr1_set, + .mfc_sr1_get = mfc_sr1_get, + .mfc_tclass_id_set = mfc_tclass_id_set, + .mfc_tclass_id_get = mfc_tclass_id_get, + .tlb_invalidate = tlb_invalidate, + .resource_allocation_groupID_set = resource_allocation_groupID_set, + .resource_allocation_groupID_get = resource_allocation_groupID_get, + .resource_allocation_enable_set = resource_allocation_enable_set, + .resource_allocation_enable_get = resource_allocation_enable_get, +}; diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index a7cddf4..bb5dc63 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile @@ -1,5 +1,7 @@ +obj-y += switch.o + obj-$(CONFIG_SPU_FS) += spufs.o -spufs-y += inode.o file.o context.o switch.o syscalls.o +spufs-y += inode.o file.o context.o syscalls.o spufs-y += sched.o backing_ops.o hw_ops.o run.o # Rules to build switch.o with the help of SPU tool chain @@ -8,11 +10,14 @@ SPU_CC := $(SPU_CROSS)gcc SPU_AS := $(SPU_CROSS)gcc SPU_LD := $(SPU_CROSS)ld SPU_OBJCOPY := $(SPU_CROSS)objcopy -SPU_CFLAGS := -O2 -Wall -I$(srctree)/include -I$(objtree)/include2 -SPU_AFLAGS := -c -D__ASSEMBLY__ -I$(srctree)/include -I$(objtree)/include2 +SPU_CFLAGS := -O2 -Wall -I$(srctree)/include \ + -I$(objtree)/include2 -D__KERNEL__ +SPU_AFLAGS := -c -D__ASSEMBLY__ -I$(srctree)/include \ + -I$(objtree)/include2 -D__KERNEL__ SPU_LDFLAGS := -N -Ttext=0x0 $(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h +clean-files := spu_save_dump.h spu_restore_dump.h # Compile SPU files cmd_spu_cc = $(SPU_CC) $(SPU_CFLAGS) -c -o $@ $< @@ -45,7 +50,8 @@ cmd_hexdump = ( \ echo " * Hex-dump auto generated from $*.c." ; \ echo " * Do not edit!" ; \ echo " */" ; \ - echo "static unsigned int $*_code[] __page_aligned = {" ; \ + echo "static unsigned int $*_code[] " \ + "__attribute__((__aligned__(128))) = {" ; \ hexdump -v -e '"0x" 4/1 "%02x" "," "\n"' $< ; \ echo "};" ; \ ) > $@ diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 8bb33ab..36439c5 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c @@ -30,7 +30,7 @@ #include "spufs.h" struct spu_context *alloc_spu_context(void) { struct spu_context *ctx; - ctx = kmalloc(sizeof *ctx, GFP_KERNEL); + ctx = kzalloc(sizeof *ctx, GFP_KERNEL); if (!ctx) goto out; /* Binding to physical processor deferred @@ -48,17 +48,7 @@ struct spu_context *alloc_spu_context(vo init_waitqueue_head(&ctx->wbox_wq); init_waitqueue_head(&ctx->stop_wq); init_waitqueue_head(&ctx->mfc_wq); - ctx->ibox_fasync = NULL; - ctx->wbox_fasync = NULL; - ctx->mfc_fasync = NULL; - ctx->mfc = NULL; - ctx->tagwait = 0; ctx->state = SPU_STATE_SAVED; - ctx->local_store = NULL; - ctx->cntl = NULL; - ctx->signal1 = NULL; - ctx->signal2 = NULL; - ctx->spu = NULL; ctx->ops = &spu_backing_ops; ctx->owner = get_task_mm(current); goto out; diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 366185e..7854a38 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -825,6 +825,55 @@ DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_ty spufs_signal2_type_set, "%llu"); #ifdef CONFIG_SPUFS_MMAP +static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) +{ + return spufs_ps_nopage(vma, address, type, 0x0000); +} + +static struct vm_operations_struct spufs_mss_mmap_vmops = { + .nopage = spufs_mss_mmap_nopage, +}; + +/* + * mmap support for problem state MFC DMA area [0x0000 - 0x0fff]. + * Mapping this area requires that the application have CAP_SYS_RAWIO, + * as these registers require special care when read/writing. + */ +static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma) +{ + if (!(vma->vm_flags & VM_SHARED)) + return -EINVAL; + + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + + vma->vm_flags |= VM_RESERVED; + vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) + | _PAGE_NO_CACHE); + + vma->vm_ops = &spufs_mss_mmap_vmops; + return 0; +} +#endif + +static int spufs_mss_open(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + + file->private_data = i->i_ctx; + return nonseekable_open(inode, file); +} + +static struct file_operations spufs_mss_fops = { + .open = spufs_mss_open, +#ifdef CONFIG_SPUFS_MMAP + .mmap = spufs_mss_mmap, +#endif +}; + + +#ifdef CONFIG_SPUFS_MMAP static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma, unsigned long address, int *type) { @@ -1101,7 +1150,7 @@ static unsigned int spufs_mfc_poll(struc return mask; } -static int spufs_mfc_flush(struct file *file) +static int spufs_mfc_flush(struct file *file, fl_owner_t id) { struct spu_context *ctx = file->private_data; int ret; @@ -1127,7 +1176,7 @@ #endif static int spufs_mfc_fsync(struct file *file, struct dentry *dentry, int datasync) { - return spufs_mfc_flush(file); + return spufs_mfc_flush(file, NULL); } static int spufs_mfc_fasync(int fd, struct file *file, int on) @@ -1279,6 +1328,22 @@ static u64 spufs_srr0_get(void *data) DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set, "%llx\n") +static u64 spufs_id_get(void *data) +{ + struct spu_context *ctx = data; + u64 num; + + spu_acquire(ctx); + if (ctx->state == SPU_STATE_RUNNABLE) + num = ctx->spu->number; + else + num = (unsigned int)-1; + spu_release(ctx); + + return num; +} +DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, 0, "0x%llx\n") + struct tree_descr spufs_dir_contents[] = { { "mem", &spufs_mem_fops, 0666, }, { "regs", &spufs_regs_fops, 0666, }, @@ -1292,6 +1357,7 @@ struct tree_descr spufs_dir_contents[] = { "signal2", &spufs_signal2_fops, 0666, }, { "signal1_type", &spufs_signal1_type, 0666, }, { "signal2_type", &spufs_signal2_type, 0666, }, + { "mss", &spufs_mss_fops, 0666, }, { "mfc", &spufs_mfc_fops, 0666, }, { "cntl", &spufs_cntl_fops, 0666, }, { "npc", &spufs_npc_ops, 0666, }, @@ -1301,5 +1367,6 @@ struct tree_descr spufs_dir_contents[] = { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, }, { "event_mask", &spufs_event_mask_ops, 0666, }, { "srr0", &spufs_srr0_ops, 0666, }, + { "phys-id", &spufs_id_ops, 0666, }, {}, }; diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index a13a8b5..ede2cac 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include "spufs.h" diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index d955419..7b45728 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -157,20 +157,12 @@ static void spufs_prune_dir(struct dentr mutex_unlock(&dir->d_inode->i_mutex); } +/* Caller must hold root->i_mutex */ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) { - struct spu_context *ctx; - /* remove all entries */ - mutex_lock(&root->i_mutex); spufs_prune_dir(dir_dentry); - mutex_unlock(&root->i_mutex); - - /* We have to give up the mm_struct */ - ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx; - spu_forget(ctx); - /* XXX Do we need to hold i_mutex here ? */ return simple_rmdir(root, dir_dentry); } @@ -199,16 +191,23 @@ out: static int spufs_dir_close(struct inode *inode, struct file *file) { + struct spu_context *ctx; struct inode *dir; struct dentry *dentry; int ret; dentry = file->f_dentry; dir = dentry->d_parent->d_inode; + ctx = SPUFS_I(dentry->d_inode)->i_ctx; + mutex_lock(&dir->i_mutex); ret = spufs_rmdir(dir, dentry); + mutex_unlock(&dir->i_mutex); WARN_ON(ret); + /* We have to give up the mm_struct */ + spu_forget(ctx); + return dcache_dir_close(inode, file); } @@ -305,6 +304,10 @@ long spufs_create_thread(struct nameidat nd->dentry != nd->dentry->d_sb->s_root) goto out; + /* all flags are reserved */ + if (flags) + goto out; + dentry = lookup_create(nd, 1); ret = PTR_ERR(dentry); if (IS_ERR(dentry)) @@ -324,8 +327,13 @@ long spufs_create_thread(struct nameidat * in error path of *_open(). */ ret = spufs_context_open(dget(dentry), mntget(nd->mnt)); - if (ret < 0) - spufs_rmdir(nd->dentry->d_inode, dentry); + if (ret < 0) { + WARN_ON(spufs_rmdir(nd->dentry->d_inode, dentry)); + mutex_unlock(&nd->dentry->d_inode->i_mutex); + spu_forget(SPUFS_I(dentry->d_inode)->i_ctx); + dput(dentry); + goto out; + } out_dput: dput(dentry); @@ -428,11 +436,11 @@ spufs_fill_super(struct super_block *sb, return spufs_create_root(sb, data); } -static struct super_block * +static int spufs_get_sb(struct file_system_type *fstype, int flags, - const char *name, void *data) + const char *name, void *data, struct vfsmount *mnt) { - return get_sb_single(fstype, flags, data, spufs_fill_super); + return get_sb_single(fstype, flags, data, spufs_fill_super, mnt); } static struct file_system_type spufs_type = { diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index bf652cd..3dcc5d8 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -43,6 +43,7 @@ #include #include #include #include +#include #include "spufs.h" #define SPU_MIN_TIMESLICE (100 * HZ / 1000) @@ -363,7 +364,7 @@ int spu_activate(struct spu_context *ctx * We're likely to wait for interrupts on the same * CPU that we are now on, so send them here. */ - spu_irq_setaffinity(spu, raw_smp_processor_id()); + spu_cpu_affinity_set(spu, raw_smp_processor_id()); put_active_spu(spu); return 0; } diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped index 1b2355f..15183d2 100644 --- a/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped +++ b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped @@ -3,229 +3,901 @@ * Hex-dump auto generated from spu_restore.c. * Do not edit! */ -static unsigned int spu_restore_code[] __page_aligned = { -0x40800000, 0x409ff801, 0x24000080, 0x24fd8081, -0x1cd80081, 0x33001180, 0x42030003, 0x33800284, -0x1c010204, 0x40200000, 0x40200000, 0x40200000, -0x34000190, 0x34004191, 0x34008192, 0x3400c193, -0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffa85, -0x3080a000, 0x3080a201, 0x3080a402, 0x3080a603, -0x3080a804, 0x3080aa05, 0x3080ac06, 0x3080ae07, -0x3080b008, 0x3080b209, 0x3080b40a, 0x3080b60b, -0x3080b80c, 0x3080ba0d, 0x3080bc0e, 0x3080be0f, -0x00003ffc, 0x00000000, 0x00000000, 0x00000000, -0x01a00182, 0x3ec00083, 0xb0a14103, 0x01a00204, -0x3ec10082, 0x4202800e, 0x04000703, 0xb0a14202, -0x21a00803, 0x3fbf028d, 0x3f20068d, 0x3fbe0682, -0x3fe30102, 0x21a00882, 0x3f82028f, 0x3fe3078f, -0x3fbf0784, 0x3f200204, 0x3fbe0204, 0x3fe30204, -0x04000203, 0x21a00903, 0x40848002, 0x21a00982, -0x40800003, 0x21a00a03, 0x40802002, 0x21a00a82, -0x21a00083, 0x40800082, 0x21a00b02, 0x10002818, -0x40a80002, 0x32800007, 0x4207000c, 0x18008208, -0x40a0000b, 0x4080020a, 0x40800709, 0x00200000, -0x42070002, 0x3ac30384, 0x1cffc489, 0x00200000, -0x18008383, 0x38830382, 0x4cffc486, 0x3ac28185, -0xb0408584, 0x28830382, 0x1c020387, 0x38828182, -0xb0408405, 0x1802c408, 0x28828182, 0x217ff886, -0x04000583, 0x21a00803, 0x3fbe0682, 0x3fe30102, -0x04000106, 0x21a00886, 0x04000603, 0x21a00903, -0x40803c02, 0x21a00982, 0x40800003, 0x04000184, -0x21a00a04, 0x40802202, 0x21a00a82, 0x42028005, -0x34208702, 0x21002282, 0x21a00804, 0x21a00886, -0x3fbf0782, 0x3f200102, 0x3fbe0102, 0x3fe30102, -0x21a00902, 0x40804003, 0x21a00983, 0x21a00a04, -0x40805a02, 0x21a00a82, 0x40800083, 0x21a00b83, -0x01a00c02, 0x01a00d83, 0x3420c282, 0x21a00e02, -0x34210283, 0x21a00f03, 0x34200284, 0x77400200, -0x3421c282, 0x21a00702, 0x34218283, 0x21a00083, -0x34214282, 0x21a00b02, 0x4200480c, 0x00200000, -0x1c010286, 0x34220284, 0x34220302, 0x0f608203, -0x5c024204, 0x3b81810b, 0x42013c02, 0x00200000, -0x18008185, 0x38808183, 0x3b814182, 0x21004e84, -0x4020007f, 0x35000100, 0x000004e0, 0x000002a0, -0x000002e8, 0x00000428, 0x00000360, 0x000002e8, -0x000004a0, 0x00000468, 0x000003c8, 0x00000360, -0x409ffe02, 0x30801203, 0x40800204, 0x3ec40085, -0x10009c09, 0x3ac10606, 0xb060c105, 0x4020007f, -0x4020007f, 0x20801203, 0x38810602, 0xb0408586, -0x28810602, 0x32004180, 0x34204702, 0x21a00382, -0x4020007f, 0x327fdc80, 0x409ffe02, 0x30801203, -0x40800204, 0x3ec40087, 0x40800405, 0x00200000, -0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a, -0xb060c107, 0x20801203, 0x41004003, 0x38810602, -0x4020007f, 0xb0408188, 0x4020007f, 0x28810602, -0x41201002, 0x38814603, 0x10009c09, 0xb060c109, -0x4020007f, 0x28814603, 0x41193f83, 0x38818602, -0x60ffc003, 0xb040818a, 0x28818602, 0x32003080, -0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087, -0x41201008, 0x10009c14, 0x40800405, 0x3ac10609, -0x40800606, 0x3ac1460a, 0xb060c107, 0x3ac1860b, -0x20801203, 0x38810602, 0xb0408409, 0x28810602, -0x38814603, 0xb060c40a, 0x4020007f, 0x28814603, -0x41193f83, 0x38818602, 0x60ffc003, 0xb040818b, -0x28818602, 0x32002380, 0x409ffe02, 0x30801204, -0x40800205, 0x3ec40083, 0x40800406, 0x3ac14607, -0x3ac18608, 0xb0810103, 0x41004002, 0x20801204, -0x4020007f, 0x38814603, 0x10009c0b, 0xb060c107, -0x4020007f, 0x4020007f, 0x28814603, 0x38818602, -0x4020007f, 0x4020007f, 0xb0408588, 0x28818602, -0x4020007f, 0x32001780, 0x409ffe02, 0x1000640e, -0x40800204, 0x30801203, 0x40800405, 0x3ec40087, -0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a, -0xb060c107, 0x20801203, 0x413d8003, 0x38810602, -0x4020007f, 0x327fd780, 0x409ffe02, 0x10007f0c, -0x40800205, 0x30801204, 0x40800406, 0x3ec40083, -0x3ac14607, 0x3ac18608, 0xb0810103, 0x413d8002, -0x20801204, 0x38814603, 0x4020007f, 0x327feb80, -0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087, -0x40800405, 0x1000650a, 0x40800606, 0x3ac10608, -0x3ac14609, 0x3ac1860a, 0xb060c107, 0x20801203, -0x38810602, 0xb0408588, 0x4020007f, 0x327fc980, -0x00400000, 0x40800003, 0x4020007f, 0x35000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, +static unsigned int spu_restore_code[] __attribute__((__aligned__(128))) = { +0x40800000, +0x409ff801, +0x24000080, +0x24fd8081, +0x1cd80081, +0x33001180, +0x42030003, +0x33800284, +0x1c010204, +0x40200000, +0x40200000, +0x40200000, +0x34000190, +0x34004191, +0x34008192, +0x3400c193, +0x141fc205, +0x23fffd84, +0x1c100183, +0x217ffa85, +0x3080a000, +0x3080a201, +0x3080a402, +0x3080a603, +0x3080a804, +0x3080aa05, +0x3080ac06, +0x3080ae07, +0x3080b008, +0x3080b209, +0x3080b40a, +0x3080b60b, +0x3080b80c, +0x3080ba0d, +0x3080bc0e, +0x3080be0f, +0x00003ffc, +0x00000000, +0x00000000, +0x00000000, +0x01a00182, +0x3ec00083, +0xb0a14103, +0x01a00204, +0x3ec10082, +0x4202800e, +0x04000703, +0xb0a14202, +0x21a00803, +0x3fbf028d, +0x3f20068d, +0x3fbe0682, +0x3fe30102, +0x21a00882, +0x3f82028f, +0x3fe3078f, +0x3fbf0784, +0x3f200204, +0x3fbe0204, +0x3fe30204, +0x04000203, +0x21a00903, +0x40848002, +0x21a00982, +0x40800003, +0x21a00a03, +0x40802002, +0x21a00a82, +0x21a00083, +0x40800082, +0x21a00b02, +0x10002818, +0x42a00002, +0x32800007, +0x4207000c, +0x18008208, +0x40a0000b, +0x4080020a, +0x40800709, +0x00200000, +0x42070002, +0x3ac30384, +0x1cffc489, +0x00200000, +0x18008383, +0x38830382, +0x4cffc486, +0x3ac28185, +0xb0408584, +0x28830382, +0x1c020387, +0x38828182, +0xb0408405, +0x1802c408, +0x28828182, +0x217ff886, +0x04000583, +0x21a00803, +0x3fbe0682, +0x3fe30102, +0x04000106, +0x21a00886, +0x04000603, +0x21a00903, +0x40803c02, +0x21a00982, +0x40800003, +0x04000184, +0x21a00a04, +0x40802202, +0x21a00a82, +0x42028005, +0x34208702, +0x21002282, +0x21a00804, +0x21a00886, +0x3fbf0782, +0x3f200102, +0x3fbe0102, +0x3fe30102, +0x21a00902, +0x40804003, +0x21a00983, +0x21a00a04, +0x40805a02, +0x21a00a82, +0x40800083, +0x21a00b83, +0x01a00c02, +0x01a00d83, +0x3420c282, +0x21a00e02, +0x34210283, +0x21a00f03, +0x34200284, +0x77400200, +0x3421c282, +0x21a00702, +0x34218283, +0x21a00083, +0x34214282, +0x21a00b02, +0x4200480c, +0x00200000, +0x1c010286, +0x34220284, +0x34220302, +0x0f608203, +0x5c024204, +0x3b81810b, +0x42013c02, +0x00200000, +0x18008185, +0x38808183, +0x3b814182, +0x21004e84, +0x4020007f, +0x35000100, +0x000004e0, +0x000002a0, +0x000002e8, +0x00000428, +0x00000360, +0x000002e8, +0x000004a0, +0x00000468, +0x000003c8, +0x00000360, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40085, +0x10009c09, +0x3ac10606, +0xb060c105, +0x4020007f, +0x4020007f, +0x20801203, +0x38810602, +0xb0408586, +0x28810602, +0x32004180, +0x34204702, +0x21a00382, +0x4020007f, +0x327fdc80, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40087, +0x40800405, +0x00200000, +0x40800606, +0x3ac10608, +0x3ac14609, +0x3ac1860a, +0xb060c107, +0x20801203, +0x41004003, +0x38810602, +0x4020007f, +0xb0408188, +0x4020007f, +0x28810602, +0x41201002, +0x38814603, +0x10009c09, +0xb060c109, +0x4020007f, +0x28814603, +0x41193f83, +0x38818602, +0x60ffc003, +0xb040818a, +0x28818602, +0x32003080, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40087, +0x41201008, +0x10009c14, +0x40800405, +0x3ac10609, +0x40800606, +0x3ac1460a, +0xb060c107, +0x3ac1860b, +0x20801203, +0x38810602, +0xb0408409, +0x28810602, +0x38814603, +0xb060c40a, +0x4020007f, +0x28814603, +0x41193f83, +0x38818602, +0x60ffc003, +0xb040818b, +0x28818602, +0x32002380, +0x409ffe02, +0x30801204, +0x40800205, +0x3ec40083, +0x40800406, +0x3ac14607, +0x3ac18608, +0xb0810103, +0x41004002, +0x20801204, +0x4020007f, +0x38814603, +0x10009c0b, +0xb060c107, +0x4020007f, +0x4020007f, +0x28814603, +0x38818602, +0x4020007f, +0x4020007f, +0xb0408588, +0x28818602, +0x4020007f, +0x32001780, +0x409ffe02, +0x1000640e, +0x40800204, +0x30801203, +0x40800405, +0x3ec40087, +0x40800606, +0x3ac10608, +0x3ac14609, +0x3ac1860a, +0xb060c107, +0x20801203, +0x413d8003, +0x38810602, +0x4020007f, +0x327fd780, +0x409ffe02, +0x10007f0c, +0x40800205, +0x30801204, +0x40800406, +0x3ec40083, +0x3ac14607, +0x3ac18608, +0xb0810103, +0x413d8002, +0x20801204, +0x38814603, +0x4020007f, +0x327feb80, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40087, +0x40800405, +0x1000650a, +0x40800606, +0x3ac10608, +0x3ac14609, +0x3ac1860a, +0xb060c107, +0x20801203, +0x38810602, +0xb0408588, +0x4020007f, +0x327fc980, +0x00400000, +0x40800003, +0x4020007f, +0x35000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, }; diff --git a/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped index 39e5400..b9f81ac 100644 --- a/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped +++ b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped @@ -3,189 +3,741 @@ * Hex-dump auto generated from spu_save.c. * Do not edit! */ -static unsigned int spu_save_code[] __page_aligned = { -0x20805000, 0x20805201, 0x20805402, 0x20805603, -0x20805804, 0x20805a05, 0x20805c06, 0x20805e07, -0x20806008, 0x20806209, 0x2080640a, 0x2080660b, -0x2080680c, 0x20806a0d, 0x20806c0e, 0x20806e0f, -0x4201c003, 0x33800184, 0x1c010204, 0x40200000, -0x24000190, 0x24004191, 0x24008192, 0x2400c193, -0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffb85, -0x40800000, 0x409ff801, 0x24000080, 0x24fd8081, -0x1cd80081, 0x33000180, 0x00000000, 0x00000000, -0x01a00182, 0x3ec00083, 0xb1c38103, 0x01a00204, -0x3ec10082, 0x4201400d, 0xb1c38202, 0x01a00583, -0x34218682, 0x3ed80684, 0xb0408184, 0x24218682, -0x01a00603, 0x00200000, 0x34214682, 0x3ed40684, -0xb0408184, 0x40800003, 0x24214682, 0x21a00083, -0x40800082, 0x21a00b02, 0x4020007f, 0x1000251e, -0x40a80002, 0x32800008, 0x4205c00c, 0x00200000, -0x40a0000b, 0x3f82070f, 0x4080020a, 0x40800709, -0x3fe3078f, 0x3fbf0783, 0x3f200183, 0x3fbe0183, -0x3fe30187, 0x18008387, 0x4205c002, 0x3ac30404, -0x1cffc489, 0x00200000, 0x18008403, 0x38830402, -0x4cffc486, 0x3ac28185, 0xb0408584, 0x28830402, -0x1c020408, 0x38828182, 0xb0408385, 0x1802c387, -0x28828182, 0x217ff886, 0x04000582, 0x32800007, -0x21a00802, 0x3fbf0705, 0x3f200285, 0x3fbe0285, -0x3fe30285, 0x21a00885, 0x04000603, 0x21a00903, -0x40803c02, 0x21a00982, 0x04000386, 0x21a00a06, -0x40801202, 0x21a00a82, 0x73000003, 0x24200683, -0x01a00404, 0x00200000, 0x34204682, 0x3ec40683, -0xb0408203, 0x24204682, 0x01a00783, 0x00200000, -0x3421c682, 0x3edc0684, 0xb0408184, 0x2421c682, -0x21a00806, 0x21a00885, 0x3fbf0784, 0x3f200204, -0x3fbe0204, 0x3fe30204, 0x21a00904, 0x40804002, -0x21a00982, 0x21a00a06, 0x40805a02, 0x21a00a82, -0x04000683, 0x21a00803, 0x21a00885, 0x21a00904, -0x40848002, 0x21a00982, 0x21a00a06, 0x40801002, -0x21a00a82, 0x21a00a06, 0x40806602, 0x00200000, -0x35800009, 0x21a00a82, 0x40800083, 0x21a00b83, -0x01a00c02, 0x01a00d83, 0x00003ffb, 0x40800003, -0x4020007f, 0x35000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, +static unsigned int spu_save_code[] __attribute__((__aligned__(128))) = { +0x20805000, +0x20805201, +0x20805402, +0x20805603, +0x20805804, +0x20805a05, +0x20805c06, +0x20805e07, +0x20806008, +0x20806209, +0x2080640a, +0x2080660b, +0x2080680c, +0x20806a0d, +0x20806c0e, +0x20806e0f, +0x4201c003, +0x33800184, +0x1c010204, +0x40200000, +0x24000190, +0x24004191, +0x24008192, +0x2400c193, +0x141fc205, +0x23fffd84, +0x1c100183, +0x217ffb85, +0x40800000, +0x409ff801, +0x24000080, +0x24fd8081, +0x1cd80081, +0x33000180, +0x00000000, +0x00000000, +0x01a00182, +0x3ec00083, +0xb1c38103, +0x01a00204, +0x3ec10082, +0x4201400d, +0xb1c38202, +0x01a00583, +0x34218682, +0x3ed80684, +0xb0408184, +0x24218682, +0x01a00603, +0x00200000, +0x34214682, +0x3ed40684, +0xb0408184, +0x40800003, +0x24214682, +0x21a00083, +0x40800082, +0x21a00b02, +0x4020007f, +0x1000251e, +0x42a00002, +0x32800008, +0x4205c00c, +0x00200000, +0x40a0000b, +0x3f82070f, +0x4080020a, +0x40800709, +0x3fe3078f, +0x3fbf0783, +0x3f200183, +0x3fbe0183, +0x3fe30187, +0x18008387, +0x4205c002, +0x3ac30404, +0x1cffc489, +0x00200000, +0x18008403, +0x38830402, +0x4cffc486, +0x3ac28185, +0xb0408584, +0x28830402, +0x1c020408, +0x38828182, +0xb0408385, +0x1802c387, +0x28828182, +0x217ff886, +0x04000582, +0x32800007, +0x21a00802, +0x3fbf0705, +0x3f200285, +0x3fbe0285, +0x3fe30285, +0x21a00885, +0x04000603, +0x21a00903, +0x40803c02, +0x21a00982, +0x04000386, +0x21a00a06, +0x40801202, +0x21a00a82, +0x73000003, +0x24200683, +0x01a00404, +0x00200000, +0x34204682, +0x3ec40683, +0xb0408203, +0x24204682, +0x01a00783, +0x00200000, +0x3421c682, +0x3edc0684, +0xb0408184, +0x2421c682, +0x21a00806, +0x21a00885, +0x3fbf0784, +0x3f200204, +0x3fbe0204, +0x3fe30204, +0x21a00904, +0x40804002, +0x21a00982, +0x21a00a06, +0x40805a02, +0x21a00a82, +0x04000683, +0x21a00803, +0x21a00885, +0x21a00904, +0x40848002, +0x21a00982, +0x21a00a06, +0x40801002, +0x21a00a82, +0x21a00a06, +0x40806602, +0x00200000, +0x35800009, +0x21a00a82, +0x40800083, +0x21a00b83, +0x01a00c02, +0x01a00d83, +0x00003ffb, +0x40800003, +0x4020007f, +0x35000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, }; diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 1726bfe..3068b42 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -622,12 +623,17 @@ static inline void save_ppuint_mb(struct static inline void save_ch_part1(struct spu_state *csa, struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; - u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL }; + u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL }; int i; /* Save, Step 42: - * Save the following CH: [0,1,3,4,24,25,27] */ + + /* Save CH 1, without channel count */ + out_be64(&priv2->spu_chnlcntptr_RW, 1); + csa->spu_chnldata_RW[1] = in_be64(&priv2->spu_chnldata_RW); + + /* Save the following CH: [0,3,4,24,25,27] */ for (i = 0; i < 7; i++) { idx = ch_indices[i]; out_be64(&priv2->spu_chnlcntptr_RW, idx); @@ -718,13 +724,15 @@ static inline void invalidate_slbs(struc static inline void get_kernel_slb(u64 ea, u64 slb[2]) { - slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL; - slb[1] = (ea & ESID_MASK) | SLB_ESID_V; + u64 llp; - /* Large pages are used for kernel text/data, but not vmalloc. */ - if (cpu_has_feature(CPU_FTR_16M_PAGE) - && REGION_ID(ea) == KERNEL_REGION_ID) - slb[0] |= SLB_VSID_L; + if (REGION_ID(ea) == KERNEL_REGION_ID) + llp = mmu_psize_defs[mmu_linear_psize].sllp; + else + llp = mmu_psize_defs[mmu_virtual_psize].sllp; + slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | + SLB_VSID_KERNEL | llp; + slb[1] = (ea & ESID_MASK) | SLB_ESID_V; } static inline void load_mfc_slb(struct spu *spu, u64 slb[2], int slbe) @@ -1103,13 +1111,18 @@ static inline void clear_spu_status(stru static inline void reset_ch_part1(struct spu_state *csa, struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; - u64 ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL }; + u64 ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL }; u64 idx; int i; /* Restore, Step 20: - * Reset the following CH: [0,1,3,4,24,25,27] */ + + /* Reset CH 1 */ + out_be64(&priv2->spu_chnlcntptr_RW, 1); + out_be64(&priv2->spu_chnldata_RW, 0UL); + + /* Reset the following CH: [0,3,4,24,25,27] */ for (i = 0; i < 7; i++) { idx = ch_indices[i]; out_be64(&priv2->spu_chnlcntptr_RW, idx); @@ -1570,12 +1583,17 @@ static inline void restore_decr_wrapped( static inline void restore_ch_part1(struct spu_state *csa, struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; - u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL }; + u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL }; int i; /* Restore, Step 59: - * Restore the following CH: [0,1,3,4,24,25,27] */ + + /* Restore CH 1 without count */ + out_be64(&priv2->spu_chnlcntptr_RW, 1); + out_be64(&priv2->spu_chnldata_RW, csa->spu_chnldata_RW[1]); + + /* Restore the following CH: [0,3,4,24,25,27] */ for (i = 0; i < 7; i++) { idx = ch_indices[i]; out_be64(&priv2->spu_chnlcntptr_RW, idx); @@ -2074,6 +2092,7 @@ int spu_save(struct spu_state *prev, str } return rc; } +EXPORT_SYMBOL_GPL(spu_save); /** * spu_restore - SPU context restore, with harvest and locking. @@ -2081,7 +2100,7 @@ int spu_save(struct spu_state *prev, str * @spu: pointer to SPU iomem structure. * * Perform harvest + restore, as we may not be coming - * from a previous succesful save operation, and the + * from a previous successful save operation, and the * hardware state is unknown. */ int spu_restore(struct spu_state *new, struct spu *spu) @@ -2090,7 +2109,6 @@ int spu_restore(struct spu_state *new, s acquire_spu_lock(spu); harvest(NULL, spu); - spu->stop_code = 0; spu->dar = 0; spu->dsisr = 0; spu->slb_replace = 0; @@ -2103,6 +2121,7 @@ int spu_restore(struct spu_state *new, s } return rc; } +EXPORT_SYMBOL_GPL(spu_restore); /** * spu_harvest - SPU harvest (reset) operation @@ -2125,6 +2144,7 @@ static void init_prob(struct spu_state * csa->spu_chnlcnt_RW[28] = 1; csa->spu_chnlcnt_RW[30] = 1; csa->prob.spu_runcntl_RW = SPU_RUNCNTL_STOP; + csa->prob.mb_stat_R = 0x000400; } static void init_priv1(struct spu_state *csa) @@ -2193,6 +2213,7 @@ void spu_init_csa(struct spu_state *csa) init_priv1(csa); init_priv2(csa); } +EXPORT_SYMBOL_GPL(spu_init_csa); void spu_fini_csa(struct spu_state *csa) { @@ -2203,3 +2224,4 @@ void spu_fini_csa(struct spu_state *csa) vfree(csa->lscsa); } +EXPORT_SYMBOL_GPL(spu_fini_csa); diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index ce8c0b9..dee4eb4 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,9 +1,11 @@ EXTRA_CFLAGS += -mno-minimal-toc -obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ +obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \ hvcall.o proc.o htab.o iommu.o misc.o irq.o obj-$(CONFIG_PCI) += pci.o vpdinfo.o -obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_VIOPATH) += viopath.o obj-$(CONFIG_MODULES) += ksyms.o + +$(obj)/dt_mod.o: $(obj)/dt.o + @$(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings $(obj)/dt.o $(obj)/dt_mod.o diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h index 59d4e0a..dbdf698 100644 --- a/arch/powerpc/platforms/iseries/call_pci.h +++ b/arch/powerpc/platforms/iseries/call_pci.h @@ -145,6 +145,25 @@ static inline u64 HvCallPci_configLoad16 return retVal.rc; } +static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber, + u8 deviceId, u32 offset, u32 *value) +{ + struct HvCallPci_DsaAddr dsa; + struct HvCallPci_LoadReturn retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumber; + dsa.subBusNumber = subBusNumber; + dsa.deviceId = deviceId; + + HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0); + + *value = retVal.value; + + return retVal.rc; +} + static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber, u8 deviceId, u32 offset, u8 value) { diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c new file mode 100644 index 0000000..d3444aa --- /dev/null +++ b/arch/powerpc/platforms/iseries/dt.c @@ -0,0 +1,615 @@ +/* + * Copyright (c) 2005-2006 Michael Ellerman, IBM Corporation + * + * Description: + * This file contains all the routines to build a flattened device + * tree for a legacy iSeries machine. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* ETH_ALEN */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "processor_vpd.h" +#include "call_hpt.h" +#include "call_pci.h" +#include "pci.h" + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +/* + * These are created by the linker script at the start and end + * of the section containing all the strings from this file. + */ +extern char __dt_strings_start[]; +extern char __dt_strings_end[]; + +struct iseries_flat_dt { + struct boot_param_header header; + u64 reserve_map[2]; +}; + +static void * __initdata dt_data; + +/* + * Putting these strings here keeps them out of the section + * that we rename to .dt_strings using objcopy and capture + * for the strings blob of the flattened device tree. + */ +static char __initdata device_type_cpu[] = "cpu"; +static char __initdata device_type_memory[] = "memory"; +static char __initdata device_type_serial[] = "serial"; +static char __initdata device_type_network[] = "network"; +static char __initdata device_type_block[] = "block"; +static char __initdata device_type_byte[] = "byte"; +static char __initdata device_type_pci[] = "pci"; +static char __initdata device_type_vdevice[] = "vdevice"; +static char __initdata device_type_vscsi[] = "vscsi"; + +static struct iseries_flat_dt * __init dt_init(void) +{ + struct iseries_flat_dt *dt; + unsigned long str_len; + + str_len = __dt_strings_end - __dt_strings_start; + dt = (struct iseries_flat_dt *)ALIGN(klimit, 8); + dt->header.off_mem_rsvmap = + offsetof(struct iseries_flat_dt, reserve_map); + dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8); + dt->header.off_dt_struct = dt->header.off_dt_strings + + ALIGN(str_len, 8); + dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct); + dt->header.dt_strings_size = str_len; + + /* There is no notion of hardware cpu id on iSeries */ + dt->header.boot_cpuid_phys = smp_processor_id(); + + memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start, + str_len); + + dt->header.magic = OF_DT_HEADER; + dt->header.version = 0x10; + dt->header.last_comp_version = 0x10; + + dt->reserve_map[0] = 0; + dt->reserve_map[1] = 0; + + return dt; +} + +static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) +{ + *((u32 *)dt_data) = value; + dt_data += sizeof(u32); +} + +#ifdef notyet +static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) +{ + *((u64 *)dt_data) = value; + dt_data += sizeof(u64); +} +#endif + +static void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data, + int len) +{ + memcpy(dt_data, data, len); + dt_data += ALIGN(len, 4); +} + +static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name) +{ + dt_push_u32(dt, OF_DT_BEGIN_NODE); + dt_push_bytes(dt, name, strlen(name) + 1); +} + +#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) + +static void __init dt_prop(struct iseries_flat_dt *dt, const char *name, + const void *data, int len) +{ + unsigned long offset; + + dt_push_u32(dt, OF_DT_PROP); + + /* Length of the data */ + dt_push_u32(dt, len); + + offset = name - __dt_strings_start; + + /* The offset of the properties name in the string blob. */ + dt_push_u32(dt, (u32)offset); + + /* The actual data. */ + dt_push_bytes(dt, data, len); +} + +static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name, + const char *data) +{ + dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ +} + +static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name, + u32 data) +{ + dt_prop(dt, name, &data, sizeof(u32)); +} + +#ifdef notyet +static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name, + u64 data) +{ + dt_prop(dt, name, &data, sizeof(u64)); +} +#endif + +static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, + const char *name, u64 *data, int n) +{ + dt_prop(dt, name, data, sizeof(u64) * n); +} + +static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, + const char *name, u32 *data, int n) +{ + dt_prop(dt, name, data, sizeof(u32) * n); +} + +#ifdef notyet +static void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name) +{ + dt_prop(dt, name, NULL, 0); +} +#endif + +static void __init dt_cpus(struct iseries_flat_dt *dt) +{ + unsigned char buf[32]; + unsigned char *p; + unsigned int i, index; + struct IoHriProcessorVpd *d; + u32 pft_size[2]; + + /* yuck */ + snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name); + p = strchr(buf, ' '); + if (!p) p = buf + strlen(buf); + + dt_start_node(dt, "cpus"); + dt_prop_u32(dt, "#address-cells", 1); + dt_prop_u32(dt, "#size-cells", 0); + + pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */ + pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); + + for (i = 0; i < NR_CPUS; i++) { + if (lppaca[i].dyn_proc_status >= 2) + continue; + + snprintf(p, 32 - (p - buf), "@%d", i); + dt_start_node(dt, buf); + + dt_prop_str(dt, "device_type", device_type_cpu); + + index = lppaca[i].dyn_hv_phys_proc_index; + d = &xIoHriProcessorVpd[index]; + + dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); + dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize); + + dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024); + dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize); + + /* magic conversions to Hz copied from old code */ + dt_prop_u32(dt, "clock-frequency", + ((1UL << 34) * 1000000) / d->xProcFreq); + dt_prop_u32(dt, "timebase-frequency", + ((1UL << 32) * 1000000) / d->xTimeBaseFreq); + + dt_prop_u32(dt, "reg", i); + + dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2); + + dt_end_node(dt); + } + + dt_end_node(dt); +} + +static void __init dt_model(struct iseries_flat_dt *dt) +{ + char buf[16] = "IBM,"; + + /* "IBM," + mfgId[2:3] + systemSerial[1:5] */ + strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2); + strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5); + buf[11] = '\0'; + dt_prop_str(dt, "system-id", buf); + + /* "IBM," + machineType[0:4] */ + strne2a(buf + 4, xItExtVpdPanel.machineType, 4); + buf[8] = '\0'; + dt_prop_str(dt, "model", buf); + + dt_prop_str(dt, "compatible", "IBM,iSeries"); +} + +static void __init dt_do_vdevice(struct iseries_flat_dt *dt, + const char *name, u32 reg, int unit, + const char *type, const char *compat, int end) +{ + char buf[32]; + + snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0)); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", type); + if (compat) + dt_prop_str(dt, "compatible", compat); + dt_prop_u32(dt, "reg", reg + ((unit >= 0) ? unit : 0)); + if (unit >= 0) + dt_prop_u32(dt, "linux,unit_address", unit); + if (end) + dt_end_node(dt); +} + +static void __init dt_vdevices(struct iseries_flat_dt *dt) +{ + u32 reg = 0; + HvLpIndexMap vlan_map; + int i; + + dt_start_node(dt, "vdevice"); + dt_prop_str(dt, "device_type", device_type_vdevice); + dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice"); + dt_prop_u32(dt, "#address-cells", 1); + dt_prop_u32(dt, "#size-cells", 0); + + dt_do_vdevice(dt, "vty", reg, -1, device_type_serial, NULL, 1); + reg++; + + dt_do_vdevice(dt, "v-scsi", reg, -1, device_type_vscsi, + "IBM,v-scsi", 1); + reg++; + + vlan_map = HvLpConfig_getVirtualLanIndexMap(); + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { + unsigned char mac_addr[ETH_ALEN]; + + if ((vlan_map & (0x8000 >> i)) == 0) + continue; + dt_do_vdevice(dt, "l-lan", reg, i, device_type_network, + "IBM,iSeries-l-lan", 0); + mac_addr[0] = 0x02; + mac_addr[1] = 0x01; + mac_addr[2] = 0xff; + mac_addr[3] = i; + mac_addr[4] = 0xff; + mac_addr[5] = HvLpConfig_getLpIndex_outline(); + dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop_u32(dt, "max-frame-size", 9000); + dt_prop_u32(dt, "address-bits", 48); + + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALLANS; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) + dt_do_vdevice(dt, "viodasd", reg, i, device_type_block, + "IBM,iSeries-viodasd", 1); + reg += HVMAXARCHITECTEDVIRTUALDISKS; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) + dt_do_vdevice(dt, "viocd", reg, i, device_type_block, + "IBM,iSeries-viocd", 1); + reg += HVMAXARCHITECTEDVIRTUALCDROMS; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) + dt_do_vdevice(dt, "viotape", reg, i, device_type_byte, + "IBM,iSeries-viotape", 1); + + dt_end_node(dt); +} + +struct pci_class_name { + u16 code; + const char *name; + const char *type; +}; + +static struct pci_class_name __initdata pci_class_name[] = { + { PCI_CLASS_NETWORK_ETHERNET, "ethernet", device_type_network }, +}; + +static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code) +{ + struct pci_class_name *cp; + + for (cp = pci_class_name; + cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++) + if (cp->code == class_code) + return cp; + return NULL; +} + +/* + * This assumes that the node slot is always on the primary bus! + */ +static void __init scan_bridge_slot(struct iseries_flat_dt *dt, + HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info) +{ + HvSubBusNumber sub_bus = bridge_info->subBusNumber; + u16 vendor_id; + u16 device_id; + u32 class_id; + int err; + char buf[32]; + u32 reg[5]; + int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); + int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); + HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); + u8 devfn; + struct pci_class_name *cp; + + /* + * Connect all functions of any device found. + */ + for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { + for (function = 0; function < 8; function++) { + HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, + function); + err = HvCallXm_connectBusUnit(bus, sub_bus, + agent_id, 0); + if (err) { + if (err != 0x302) + DBG("connectBusUnit(%x, %x, %x) %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_VENDOR_ID, &vendor_id); + if (err) { + DBG("ReadVendor(%x, %x, %x) %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_DEVICE_ID, &device_id); + if (err) { + DBG("ReadDevice(%x, %x, %x) %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad32(bus, sub_bus, agent_id, + PCI_CLASS_REVISION , &class_id); + if (err) { + DBG("ReadClass(%x, %x, %x) %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), + function); + cp = dt_find_pci_class_name(class_id >> 16); + if (cp && cp->name) + strncpy(buf, cp->name, sizeof(buf) - 1); + else + snprintf(buf, sizeof(buf), "pci%x,%x", + vendor_id, device_id); + buf[sizeof(buf) - 1] = '\0'; + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "@%x", PCI_SLOT(devfn)); + buf[sizeof(buf) - 1] = '\0'; + if (function != 0) + snprintf(buf + strlen(buf), + sizeof(buf) - strlen(buf), + ",%x", function); + dt_start_node(dt, buf); + reg[0] = (bus << 16) | (devfn << 8); + reg[1] = 0; + reg[2] = 0; + reg[3] = 0; + reg[4] = 0; + dt_prop_u32_list(dt, "reg", reg, 5); + if (cp && (cp->type || cp->name)) + dt_prop_str(dt, "device_type", + cp->type ? cp->type : cp->name); + dt_prop_u32(dt, "vendor-id", vendor_id); + dt_prop_u32(dt, "device-id", device_id); + dt_prop_u32(dt, "class-code", class_id >> 8); + dt_prop_u32(dt, "revision-id", class_id & 0xff); + dt_prop_u32(dt, "linux,subbus", sub_bus); + dt_prop_u32(dt, "linux,agent-id", agent_id); + dt_prop_u32(dt, "linux,logical-slot-number", + bridge_info->logicalSlotNumber); + dt_end_node(dt); + + } + } +} + +static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, + HvSubBusNumber sub_bus, int id_sel) +{ + struct HvCallPci_BridgeInfo bridge_info; + HvAgentId agent_id; + int function; + int ret; + + /* Note: hvSubBus and irq is always be 0 at this level! */ + for (function = 0; function < 8; ++function) { + agent_id = ISERIES_PCI_AGENTID(id_sel, function); + ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0); + if (ret != 0) { + if (ret != 0xb) + DBG("connectBusUnit(%x, %x, %x) %x\n", + bus, sub_bus, agent_id, ret); + continue; + } + DBG("found device at bus %d idsel %d func %d (AgentId %x)\n", + bus, id_sel, function, agent_id); + ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id, + iseries_hv_addr(&bridge_info), + sizeof(struct HvCallPci_BridgeInfo)); + if (ret != 0) + continue; + DBG("bridge info: type %x subbus %x " + "maxAgents %x maxsubbus %x logslot %x\n", + bridge_info.busUnitInfo.deviceType, + bridge_info.subBusNumber, + bridge_info.maxAgents, + bridge_info.maxSubBusNumber, + bridge_info.logicalSlotNumber); + if (bridge_info.busUnitInfo.deviceType == + HvCallPci_BridgeDevice) + scan_bridge_slot(dt, bus, &bridge_info); + else + DBG("PCI: Invalid Bridge Configuration(0x%02X)", + bridge_info.busUnitInfo.deviceType); + } +} + +static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) +{ + struct HvCallPci_DeviceInfo dev_info; + const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ + int err; + int id_sel; + const int max_agents = 8; + + /* + * Probe for EADs Bridges + */ + for (id_sel = 1; id_sel < max_agents; ++id_sel) { + err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel, + iseries_hv_addr(&dev_info), + sizeof(struct HvCallPci_DeviceInfo)); + if (err) { + if (err != 0x302) + DBG("getDeviceInfo(%x, %x, %x) %x\n", + bus, sub_bus, id_sel, err); + continue; + } + if (dev_info.deviceType != HvCallPci_NodeDevice) { + DBG("PCI: Invalid System Configuration" + "(0x%02X) for bus 0x%02x id 0x%02x.\n", + dev_info.deviceType, bus, id_sel); + continue; + } + scan_bridge(dt, bus, sub_bus, id_sel); + } +} + +static void __init dt_pci_devices(struct iseries_flat_dt *dt) +{ + HvBusNumber bus; + char buf[32]; + u32 buses[2]; + int phb_num = 0; + + /* Check all possible buses. */ + for (bus = 0; bus < 256; bus++) { + int err = HvCallXm_testBus(bus); + + if (err) { + /* + * Check for Unexpected Return code, a clue that + * something has gone wrong. + */ + if (err != 0x0301) + DBG("Unexpected Return on Probe(0x%02X) " + "0x%04X\n", bus, err); + continue; + } + DBG("bus %d appears to exist\n", bus); + snprintf(buf, 32, "pci@%d", phb_num); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", device_type_pci); + dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB"); + dt_prop_u32(dt, "#address-cells", 3); + dt_prop_u32(dt, "#size-cells", 2); + buses[0] = buses[1] = bus; + dt_prop_u32_list(dt, "bus-range", buses, 2); + scan_phb(dt, bus); + dt_end_node(dt); + phb_num++; + } +} + +static void dt_finish(struct iseries_flat_dt *dt) +{ + dt_push_u32(dt, OF_DT_END); + dt->header.totalsize = (unsigned long)dt_data - (unsigned long)dt; + klimit = ALIGN((unsigned long)dt_data, 8); +} + +void * __init build_flat_dt(unsigned long phys_mem_size) +{ + struct iseries_flat_dt *iseries_dt; + u64 tmp[2]; + + iseries_dt = dt_init(); + + dt_start_node(iseries_dt, ""); + + dt_prop_u32(iseries_dt, "#address-cells", 2); + dt_prop_u32(iseries_dt, "#size-cells", 2); + dt_model(iseries_dt); + + /* /memory */ + dt_start_node(iseries_dt, "memory@0"); + dt_prop_str(iseries_dt, "device_type", device_type_memory); + tmp[0] = 0; + tmp[1] = phys_mem_size; + dt_prop_u64_list(iseries_dt, "reg", tmp, 2); + dt_end_node(iseries_dt); + + /* /chosen */ + dt_start_node(iseries_dt, "chosen"); + dt_prop_str(iseries_dt, "bootargs", cmd_line); + dt_end_node(iseries_dt); + + dt_cpus(iseries_dt); + + dt_vdevices(iseries_dt); + dt_pci_devices(iseries_dt); + + dt_end_node(iseries_dt); + + dt_finish(iseries_dt); + + return iseries_dt; +} diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index bea0b70..e3bd201 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -4,6 +4,7 @@ * Rewrite, cleanup: * * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2006 Olof Johansson * * Dynamic DMA mapping support, iSeries-specific parts. * @@ -31,42 +32,37 @@ #include #include #include #include +#include #include #include - -#include "iommu.h" - -extern struct list_head iSeries_Global_Device_List; - +#include static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, unsigned long uaddr, enum dma_data_direction direction) { u64 rc; - union tce_entry tce; + u64 tce, rpn; index <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; while (npages--) { - tce.te_word = 0; - tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> TCE_SHIFT; + rpn = virt_to_abs(uaddr) >> TCE_SHIFT; + tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; if (tbl->it_type == TCE_VB) { /* Virtual Bus */ - tce.te_bits.tb_valid = 1; - tce.te_bits.tb_allio = 1; + tce |= TCE_VALID|TCE_ALLIO; if (direction != DMA_TO_DEVICE) - tce.te_bits.tb_rdwr = 1; + tce |= TCE_VB_WRITE; } else { /* PCI Bus */ - tce.te_bits.tb_rdwr = 1; /* Read allowed */ + tce |= TCE_PCI_READ; /* Read allowed */ if (direction != DMA_TO_DEVICE) - tce.te_bits.tb_pciwr = 1; + tce |= TCE_PCI_WRITE; } - rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, - tce.te_word); + rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce); if (rc) panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc); @@ -124,7 +120,7 @@ void iommu_table_getparms_iSeries(unsign /* itc_size is in pages worth of table, it_size is in # of entries */ tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) / - sizeof(union tce_entry)) >> TCE_PAGE_FACTOR; + TCE_ENTRY_SIZE) >> TCE_PAGE_FACTOR; tbl->it_busno = parms->itc_busno; tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR; tbl->it_index = parms->itc_index; @@ -142,10 +138,15 @@ #ifdef CONFIG_PCI */ static struct iommu_table *iommu_table_find(struct iommu_table * tbl) { - struct pci_dn *pdn; + struct device_node *node; - list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { - struct iommu_table *it = pdn->iommu_table; + for (node = NULL; (node = of_find_all_nodes(node)); ) { + struct pci_dn *pdn = PCI_DN(node); + struct iommu_table *it; + + if (pdn == NULL) + continue; + it = pdn->iommu_table; if ((it != NULL) && (it->it_type == TCE_PCI) && (it->it_offset == tbl->it_offset) && @@ -161,15 +162,18 @@ void iommu_devnode_init_iSeries(struct d { struct iommu_table *tbl; struct pci_dn *pdn = PCI_DN(dn); + u32 *lsn = (u32 *)get_property(dn, "linux,logical-slot-number", NULL); + + BUG_ON(lsn == NULL); tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - iommu_table_getparms_iSeries(pdn->busno, pdn->LogicalSlot, 0, tbl); + iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl); /* Look for existing tce table */ pdn->iommu_table = iommu_table_find(tbl); if (pdn->iommu_table == NULL) - pdn->iommu_table = iommu_init_table(tbl); + pdn->iommu_table = iommu_init_table(tbl, -1); else kfree(tbl); } diff --git a/arch/powerpc/platforms/iseries/iommu.h b/arch/powerpc/platforms/iseries/iommu.h deleted file mode 100644 index cb5658f..0000000 --- a/arch/powerpc/platforms/iseries/iommu.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _PLATFORMS_ISERIES_IOMMU_H -#define _PLATFORMS_ISERIES_IOMMU_H - -/* - * Copyright (C) 2005 Stephen Rothwell, IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - */ - -struct device_node; -struct iommu_table; - -/* Creates table for an individual device node */ -extern void iommu_devnode_init_iSeries(struct device_node *dn); - -/* Get table parameters from HV */ -extern void iommu_table_getparms_iSeries(unsigned long busno, - unsigned char slotno, unsigned char virtbus, - struct iommu_table *tbl); - -#endif /* _PLATFORMS_ISERIES_IOMMU_H */ diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index be3fbfc..62bbbcf 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -42,6 +42,7 @@ #include #include #include "irq.h" +#include "pci.h" #include "call_pci.h" #if defined(CONFIG_SMP) @@ -312,12 +313,12 @@ static hw_irq_controller iSeries_IRQ_han * Note that sub_bus is always 0 (at the moment at least). */ int __init iSeries_allocate_IRQ(HvBusNumber bus, - HvSubBusNumber sub_bus, HvAgentId dev_id) + HvSubBusNumber sub_bus, u32 bsubbus) { int virtirq; unsigned int realirq; - u8 idsel = (dev_id >> 4); - u8 function = dev_id & 7; + u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus); + u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus); realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) + function; diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h index b9c801b..188aa80 100644 --- a/arch/powerpc/platforms/iseries/irq.h +++ b/arch/powerpc/platforms/iseries/irq.h @@ -2,7 +2,7 @@ #ifndef _ISERIES_IRQ_H #define _ISERIES_IRQ_H extern void iSeries_init_IRQ(void); -extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId); +extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32); extern void iSeries_activate_IRQs(void); extern int iSeries_get_irq(struct pt_regs *); diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index d771b8e..1a2c2a5 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -45,7 +45,6 @@ #include #include "setup.h" -extern int piranha_simulator; static int mf_initialized; /* @@ -658,7 +657,7 @@ static void mf_clear_src(void) void __init mf_display_progress(u16 value) { - if (piranha_simulator || !mf_initialized) + if (!mf_initialized) return; if (0xFFFF == value) @@ -1295,9 +1294,6 @@ #endif /* CONFIG_PROC_FS */ */ void iSeries_get_rtc_time(struct rtc_time *rtc_tm) { - if (piranha_simulator) - return; - mf_get_rtc(rtc_tm); rtc_tm->tm_mon--; } @@ -1316,9 +1312,6 @@ unsigned long iSeries_get_boot_time(void { struct rtc_time tm; - if (piranha_simulator) - return 0; - mf_get_boot_rtc(&tm); return mktime(tm.tm_year + 1900, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index a19833b..35bcc98 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -37,36 +37,18 @@ #include #include #include +#include #include #include "irq.h" #include "pci.h" #include "call_pci.h" -#include "iommu.h" - -extern unsigned long io_page_mask; /* * Forward declares of prototypes. */ static struct device_node *find_Device_Node(int bus, int devfn); -static void scan_PHB_slots(struct pci_controller *Phb); -static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel); -static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info); - -LIST_HEAD(iSeries_Global_Device_List); - -static int DeviceCount; - -/* Counters and control flags. */ -static long Pci_Io_Read_Count; -static long Pci_Io_Write_Count; -#if 0 -static long Pci_Cfg_Read_Count; -static long Pci_Cfg_Write_Count; -#endif -static long Pci_Error_Count; static int Pci_Retry_Max = 3; /* Only retry 3 times */ static int Pci_Error_Flag = 1; /* Set Retry Error on. */ @@ -81,41 +63,19 @@ #define IOMM_TABLE_MAX_ENTRIES 1024 #define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL #define BASE_IO_MEMORY 0xE000000000000000UL -static unsigned long max_io_memory = 0xE000000000000000UL; +static unsigned long max_io_memory = BASE_IO_MEMORY; static long current_iomm_table_entry; /* * Lookup Tables. */ -static struct device_node **iomm_table; -static u8 *iobar_table; +static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES]; +static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES]; -/* - * Static and Global variables - */ -static char *pci_io_text = "iSeries PCI I/O"; +static const char pci_io_text[] = "iSeries PCI I/O"; static DEFINE_SPINLOCK(iomm_table_lock); /* - * iomm_table_initialize - * - * Allocates and initalizes the Address Translation Table and Bar - * Tables to get them ready for use. Must be called before any - * I/O space is handed out to the device BARs. - */ -static void iomm_table_initialize(void) -{ - spin_lock(&iomm_table_lock); - iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES, - GFP_KERNEL); - iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES, - GFP_KERNEL); - spin_unlock(&iomm_table_lock); - if ((iomm_table == NULL) || (iobar_table == NULL)) - panic("PCI: I/O tables allocation failed.\n"); -} - -/* * iomm_table_allocate_entry * * Adds pci_dev entry in address translation table @@ -142,9 +102,8 @@ static void iomm_table_allocate_entry(st */ spin_lock(&iomm_table_lock); bar_res->name = pci_io_text; - bar_res->start = + bar_res->start = BASE_IO_MEMORY + IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry; - bar_res->start += BASE_IO_MEMORY; bar_res->end = bar_res->start + bar_size - 1; /* * Allocate the number of table entries needed for BAR. @@ -156,7 +115,7 @@ static void iomm_table_allocate_entry(st ++current_iomm_table_entry; } max_io_memory = BASE_IO_MEMORY + - (IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry); + IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry; spin_unlock(&iomm_table_lock); } @@ -173,13 +132,10 @@ static void iomm_table_allocate_entry(st */ static void allocate_device_bars(struct pci_dev *dev) { - struct resource *bar_res; int bar_num; - for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) { - bar_res = &dev->resource[bar_num]; + for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) iomm_table_allocate_entry(dev, bar_num); - } } /* @@ -199,34 +155,7 @@ static void pci_Log_Error(char *Error_Te } /* - * build_device_node(u16 Bus, int SubBus, u8 DevFn) - */ -static struct device_node *build_device_node(HvBusNumber Bus, - HvSubBusNumber SubBus, int AgentId, int Function) -{ - struct device_node *node; - struct pci_dn *pdn; - - node = kmalloc(sizeof(struct device_node), GFP_KERNEL); - if (node == NULL) - return NULL; - memset(node, 0, sizeof(struct device_node)); - pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); - if (pdn == NULL) { - kfree(node); - return NULL; - } - node->data = pdn; - pdn->node = node; - list_add_tail(&pdn->Device_List, &iSeries_Global_Device_List); - pdn->busno = Bus; - pdn->bussubno = SubBus; - pdn->devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); - return node; -} - -/* - * unsigned long __init find_and_init_phbs(void) + * iSeries_pcibios_init * * Description: * This function checks for all possible system PCI host bridges that connect @@ -234,50 +163,42 @@ static struct device_node *build_device_ * ownership status. A pci_controller is built for any bus which is partially * owned or fully owned by this guest partition. */ -unsigned long __init find_and_init_phbs(void) +void iSeries_pcibios_init(void) { struct pci_controller *phb; - HvBusNumber bus; - - /* Check all possible buses. */ - for (bus = 0; bus < 256; bus++) { - int ret = HvCallXm_testBus(bus); - if (ret == 0) { - printk("bus %d appears to exist\n", bus); + struct device_node *root = of_find_node_by_path("/"); + struct device_node *node = NULL; - phb = pcibios_alloc_controller(NULL); - if (phb == NULL) - return -ENOMEM; - - phb->pci_mem_offset = phb->local_number = bus; - phb->first_busno = bus; - phb->last_busno = bus; - phb->ops = &iSeries_pci_ops; - - /* Find and connect the devices. */ - scan_PHB_slots(phb); - } - /* - * Check for Unexpected Return code, a clue that something - * has gone wrong. - */ - else if (ret != 0x0301) - printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X", - bus, ret); + if (root == NULL) { + printk(KERN_CRIT "iSeries_pcibios_init: can't find root " + "of device tree\n"); + return; + } + while ((node = of_get_next_child(root, node)) != NULL) { + HvBusNumber bus; + u32 *busp; + + if ((node->type == NULL) || (strcmp(node->type, "pci") != 0)) + continue; + + busp = (u32 *)get_property(node, "bus-range", NULL); + if (busp == NULL) + continue; + bus = *busp; + printk("bus %d appears to exist\n", bus); + phb = pcibios_alloc_controller(node); + if (phb == NULL) + continue; + + phb->pci_mem_offset = phb->local_number = bus; + phb->first_busno = bus; + phb->last_busno = bus; + phb->ops = &iSeries_pci_ops; } - return 0; -} -/* - * iSeries_pcibios_init - * - * Chance to initialize and structures or variable before PCI Bus walk. - */ -void iSeries_pcibios_init(void) -{ - iomm_table_initialize(); - find_and_init_phbs(); - io_page_mask = -1; + of_node_put(root); + + pci_devs_phb_init(); } /* @@ -299,6 +220,34 @@ void __init iSeries_pci_final_fixup(void pdev->bus->number, pdev->devfn, node); if (node != NULL) { + struct pci_dn *pdn = PCI_DN(node); + u32 *agent; + + agent = (u32 *)get_property(node, "linux,agent-id", + NULL); + if ((pdn != NULL) && (agent != NULL)) { + u8 irq = iSeries_allocate_IRQ(pdn->busno, 0, + pdn->bussubno); + int err; + + err = HvCallXm_connectBusUnit(pdn->busno, pdn->bussubno, + *agent, irq); + if (err) + pci_Log_Error("Connect Bus Unit", + pdn->busno, pdn->bussubno, *agent, err); + else { + err = HvCallPci_configStore8(pdn->busno, pdn->bussubno, + *agent, + PCI_INTERRUPT_LINE, + irq); + if (err) + pci_Log_Error("PciCfgStore Irq Failed!", + pdn->busno, pdn->bussubno, *agent, err); + } + if (!err) + pdev->irq = irq; + } + ++DeviceCount; pdev->sysdata = (void *)node; PCI_DN(node)->pcidev = pdev; @@ -308,7 +257,6 @@ void __init iSeries_pci_final_fixup(void } else printk("PCI: Device Tree not found for 0x%016lX\n", (unsigned long)pdev); - pdev->irq = PCI_DN(node)->Irq; } iSeries_activate_IRQs(); mf_display_src(0xC9000200); @@ -323,148 +271,6 @@ void pcibios_fixup_resources(struct pci_ } /* - * Loop through each node function to find usable EADs bridges. - */ -static void scan_PHB_slots(struct pci_controller *Phb) -{ - struct HvCallPci_DeviceInfo *DevInfo; - HvBusNumber bus = Phb->local_number; /* System Bus */ - const HvSubBusNumber SubBus = 0; /* EADs is always 0. */ - int HvRc = 0; - int IdSel; - const int MaxAgents = 8; - - DevInfo = (struct HvCallPci_DeviceInfo*) - kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); - if (DevInfo == NULL) - return; - - /* - * Probe for EADs Bridges - */ - for (IdSel = 1; IdSel < MaxAgents; ++IdSel) { - HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel, - iseries_hv_addr(DevInfo), - sizeof(struct HvCallPci_DeviceInfo)); - if (HvRc == 0) { - if (DevInfo->deviceType == HvCallPci_NodeDevice) - scan_EADS_bridge(bus, SubBus, IdSel); - else - printk("PCI: Invalid System Configuration(0x%02X)" - " for bus 0x%02x id 0x%02x.\n", - DevInfo->deviceType, bus, IdSel); - } - else - pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc); - } - kfree(DevInfo); -} - -static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus, - int IdSel) -{ - struct HvCallPci_BridgeInfo *BridgeInfo; - HvAgentId AgentId; - int Function; - int HvRc; - - BridgeInfo = (struct HvCallPci_BridgeInfo *) - kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL); - if (BridgeInfo == NULL) - return; - - /* Note: hvSubBus and irq is always be 0 at this level! */ - for (Function = 0; Function < 8; ++Function) { - AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0); - if (HvRc == 0) { - printk("found device at bus %d idsel %d func %d (AgentId %x)\n", - bus, IdSel, Function, AgentId); - /* Connect EADs: 0x18.00.12 = 0x00 */ - HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId, - iseries_hv_addr(BridgeInfo), - sizeof(struct HvCallPci_BridgeInfo)); - if (HvRc == 0) { - printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n", - BridgeInfo->busUnitInfo.deviceType, - BridgeInfo->subBusNumber, - BridgeInfo->maxAgents, - BridgeInfo->maxSubBusNumber, - BridgeInfo->logicalSlotNumber); - if (BridgeInfo->busUnitInfo.deviceType == - HvCallPci_BridgeDevice) { - /* Scan_Bridge_Slot...: 0x18.00.12 */ - scan_bridge_slot(bus, BridgeInfo); - } else - printk("PCI: Invalid Bridge Configuration(0x%02X)", - BridgeInfo->busUnitInfo.deviceType); - } - } else if (HvRc != 0x000B) - pci_Log_Error("EADs Connect", - bus, SubBus, AgentId, HvRc); - } - kfree(BridgeInfo); -} - -/* - * This assumes that the node slot is always on the primary bus! - */ -static int scan_bridge_slot(HvBusNumber Bus, - struct HvCallPci_BridgeInfo *BridgeInfo) -{ - struct device_node *node; - HvSubBusNumber SubBus = BridgeInfo->subBusNumber; - u16 VendorId = 0; - int HvRc = 0; - u8 Irq = 0; - int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus); - int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus); - HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function); - - /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ - Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel); - - /* - * Connect all functions of any device found. - */ - for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) { - for (Function = 0; Function < 8; ++Function) { - HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvRc = HvCallXm_connectBusUnit(Bus, SubBus, - AgentId, Irq); - if (HvRc != 0) { - pci_Log_Error("Connect Bus Unit", - Bus, SubBus, AgentId, HvRc); - continue; - } - - HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, - PCI_VENDOR_ID, &VendorId); - if (HvRc != 0) { - pci_Log_Error("Read Vendor", - Bus, SubBus, AgentId, HvRc); - continue; - } - printk("read vendor ID: %x\n", VendorId); - - /* FoundDevice: 0x18.28.10 = 0x12AE */ - HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, - PCI_INTERRUPT_LINE, Irq); - if (HvRc != 0) - pci_Log_Error("PciCfgStore Irq Failed!", - Bus, SubBus, AgentId, HvRc); - - ++DeviceCount; - node = build_device_node(Bus, SubBus, EADsIdSel, Function); - PCI_DN(node)->Irq = Irq; - PCI_DN(node)->LogicalSlot = BridgeInfo->logicalSlotNumber; - - } /* for (Function = 0; Function < 8; ++Function) */ - } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */ - return HvRc; -} - -/* * I/0 Memory copy MUST use mmio commands on iSeries * To do; For performance, include the hv call directly */ @@ -509,11 +315,13 @@ EXPORT_SYMBOL(iSeries_memcpy_fromio); */ static struct device_node *find_Device_Node(int bus, int devfn) { - struct pci_dn *pdn; + struct device_node *node; + + for (node = NULL; (node = of_find_all_nodes(node)); ) { + struct pci_dn *pdn = PCI_DN(node); - list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { - if ((bus == pdn->busno) && (devfn == pdn->devfn)) - return pdn->node; + if (pdn && (bus == pdn->busno) && (devfn == pdn->devfn)) + return node; } return NULL; } @@ -625,7 +433,6 @@ static int CheckReturnCode(char *TextHdr if (ret != 0) { struct pci_dn *pdn = PCI_DN(DevNode); - ++Pci_Error_Count; (*retry)++; printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", TextHdr, pdn->busno, pdn->devfn, @@ -707,7 +514,6 @@ u8 iSeries_Read_Byte(const volatile void return 0xff; } do { - ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); @@ -737,7 +543,6 @@ u16 iSeries_Read_Word(const volatile voi return 0xffff; } do { - ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa, BarOffset, 0); } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); @@ -768,7 +573,6 @@ u32 iSeries_Read_Long(const volatile voi return 0xffffffff; } do { - ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa, BarOffset, 0); } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); @@ -806,7 +610,6 @@ void iSeries_Write_Byte(u8 data, volatil return; } do { - ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0); } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0); } @@ -834,7 +637,6 @@ void iSeries_Write_Word(u16 data, volati return; } do { - ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); } @@ -862,7 +664,6 @@ void iSeries_Write_Long(u32 data, volati return; } do { - ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); } diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index a6fd9be..617c724 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -50,7 +50,6 @@ #include #include #include #include -#include #include #include #include @@ -81,9 +80,6 @@ #else static void iSeries_pci_final_fixup(void) { } #endif -/* Global Variables */ -int piranha_simulator; - extern int rd_size; /* Defined in drivers/block/rd.c */ extern unsigned long embedded_sysmap_start; extern unsigned long embedded_sysmap_end; @@ -91,8 +87,6 @@ extern unsigned long embedded_sysmap_end extern unsigned long iSeries_recal_tb; extern unsigned long iSeries_recal_titan; -static unsigned long cmd_mem_limit; - struct MemoryBlock { unsigned long absStart; unsigned long absEnd; @@ -340,8 +334,6 @@ #endif /* CONFIG_BLK_DEV_INITRD */ #ifdef CONFIG_SMP smp_init_iSeries(); #endif - if (itLpNaca.xPirEnvironMode == 0) - piranha_simulator = 1; /* Associate Lp Event Queue 0 with processor 0 */ HvCallEvent_setLpEventQueueInterruptProc(0, 0); @@ -536,10 +528,10 @@ static void __init iSeries_setup_arch(vo { if (get_lppaca()->shared_proc) { ppc_md.idle_loop = iseries_shared_idle; - printk(KERN_INFO "Using shared processor idle loop\n"); + printk(KERN_DEBUG "Using shared processor idle loop\n"); } else { ppc_md.idle_loop = iseries_dedicated_idle; - printk(KERN_INFO "Using dedicated idle loop\n"); + printk(KERN_DEBUG "Using dedicated idle loop\n"); } /* Setup the Lp Event Queue */ @@ -714,243 +706,6 @@ define_machine(iseries) { /* XXX Implement enable_pmcs for iSeries */ }; -struct blob { - unsigned char data[PAGE_SIZE]; - unsigned long next; -}; - -struct iseries_flat_dt { - struct boot_param_header header; - u64 reserve_map[2]; - struct blob dt; - struct blob strings; -}; - -struct iseries_flat_dt iseries_dt; - -void dt_init(struct iseries_flat_dt *dt) -{ - dt->header.off_mem_rsvmap = - offsetof(struct iseries_flat_dt, reserve_map); - dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt); - dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings); - dt->header.totalsize = sizeof(struct iseries_flat_dt); - dt->header.dt_strings_size = sizeof(struct blob); - - /* There is no notion of hardware cpu id on iSeries */ - dt->header.boot_cpuid_phys = smp_processor_id(); - - dt->dt.next = (unsigned long)&dt->dt.data; - dt->strings.next = (unsigned long)&dt->strings.data; - - dt->header.magic = OF_DT_HEADER; - dt->header.version = 0x10; - dt->header.last_comp_version = 0x10; - - dt->reserve_map[0] = 0; - dt->reserve_map[1] = 0; -} - -void dt_check_blob(struct blob *b) -{ - if (b->next >= (unsigned long)&b->next) { - DBG("Ran out of space in flat device tree blob!\n"); - BUG(); - } -} - -void dt_push_u32(struct iseries_flat_dt *dt, u32 value) -{ - *((u32*)dt->dt.next) = value; - dt->dt.next += sizeof(u32); - - dt_check_blob(&dt->dt); -} - -void dt_push_u64(struct iseries_flat_dt *dt, u64 value) -{ - *((u64*)dt->dt.next) = value; - dt->dt.next += sizeof(u64); - - dt_check_blob(&dt->dt); -} - -unsigned long dt_push_bytes(struct blob *blob, char *data, int len) -{ - unsigned long start = blob->next - (unsigned long)blob->data; - - memcpy((char *)blob->next, data, len); - blob->next = _ALIGN(blob->next + len, 4); - - dt_check_blob(blob); - - return start; -} - -void dt_start_node(struct iseries_flat_dt *dt, char *name) -{ - dt_push_u32(dt, OF_DT_BEGIN_NODE); - dt_push_bytes(&dt->dt, name, strlen(name) + 1); -} - -#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) - -void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) -{ - unsigned long offset; - - dt_push_u32(dt, OF_DT_PROP); - - /* Length of the data */ - dt_push_u32(dt, len); - - /* Put the property name in the string blob. */ - offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1); - - /* The offset of the properties name in the string blob. */ - dt_push_u32(dt, (u32)offset); - - /* The actual data. */ - dt_push_bytes(&dt->dt, data, len); -} - -void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data) -{ - dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ -} - -void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) -{ - dt_prop(dt, name, (char *)&data, sizeof(u32)); -} - -void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) -{ - dt_prop(dt, name, (char *)&data, sizeof(u64)); -} - -void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) -{ - dt_prop(dt, name, (char *)data, sizeof(u64) * n); -} - -void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) -{ - dt_prop(dt, name, (char *)data, sizeof(u32) * n); -} - -void dt_prop_empty(struct iseries_flat_dt *dt, char *name) -{ - dt_prop(dt, name, NULL, 0); -} - -void dt_cpus(struct iseries_flat_dt *dt) -{ - unsigned char buf[32]; - unsigned char *p; - unsigned int i, index; - struct IoHriProcessorVpd *d; - u32 pft_size[2]; - - /* yuck */ - snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name); - p = strchr(buf, ' '); - if (!p) p = buf + strlen(buf); - - dt_start_node(dt, "cpus"); - dt_prop_u32(dt, "#address-cells", 1); - dt_prop_u32(dt, "#size-cells", 0); - - pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */ - pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); - - for (i = 0; i < NR_CPUS; i++) { - if (lppaca[i].dyn_proc_status >= 2) - continue; - - snprintf(p, 32 - (p - buf), "@%d", i); - dt_start_node(dt, buf); - - dt_prop_str(dt, "device_type", "cpu"); - - index = lppaca[i].dyn_hv_phys_proc_index; - d = &xIoHriProcessorVpd[index]; - - dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); - dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize); - - dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024); - dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize); - - /* magic conversions to Hz copied from old code */ - dt_prop_u32(dt, "clock-frequency", - ((1UL << 34) * 1000000) / d->xProcFreq); - dt_prop_u32(dt, "timebase-frequency", - ((1UL << 32) * 1000000) / d->xTimeBaseFreq); - - dt_prop_u32(dt, "reg", i); - - dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2); - - dt_end_node(dt); - } - - dt_end_node(dt); -} - -void dt_model(struct iseries_flat_dt *dt) -{ - char buf[16] = "IBM,"; - - /* "IBM," + mfgId[2:3] + systemSerial[1:5] */ - strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2); - strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5); - buf[11] = '\0'; - dt_prop_str(dt, "system-id", buf); - - /* "IBM," + machineType[0:4] */ - strne2a(buf + 4, xItExtVpdPanel.machineType, 4); - buf[8] = '\0'; - dt_prop_str(dt, "model", buf); - - dt_prop_str(dt, "compatible", "IBM,iSeries"); -} - -void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) -{ - u64 tmp[2]; - - dt_init(dt); - - dt_start_node(dt, ""); - - dt_prop_u32(dt, "#address-cells", 2); - dt_prop_u32(dt, "#size-cells", 2); - dt_model(dt); - - /* /memory */ - dt_start_node(dt, "memory@0"); - dt_prop_str(dt, "name", "memory"); - dt_prop_str(dt, "device_type", "memory"); - tmp[0] = 0; - tmp[1] = phys_mem_size; - dt_prop_u64_list(dt, "reg", tmp, 2); - dt_end_node(dt); - - /* /chosen */ - dt_start_node(dt, "chosen"); - dt_prop_str(dt, "bootargs", cmd_line); - if (cmd_mem_limit) - dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit); - dt_end_node(dt); - - dt_cpus(dt); - - dt_end_node(dt); - - dt_push_u32(dt, OF_DT_END); -} - void * __init iSeries_early_setup(void) { unsigned long phys_mem_size; @@ -965,28 +720,8 @@ void * __init iSeries_early_setup(void) iSeries_get_cmdline(); - /* Save unparsed command line copy for /proc/cmdline */ - strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); - - /* Parse early parameters, in particular mem=x */ - parse_early_param(); - - build_flat_dt(&iseries_dt, phys_mem_size); - - return (void *) __pa(&iseries_dt); -} - -/* - * On iSeries we just parse the mem=X option from the command line. - * On pSeries it's a bit more complicated, see prom_init_mem() - */ -static int __init early_parsemem(char *p) -{ - if (p) - cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE); - return 0; + return (void *) __pa(build_flat_dt(phys_mem_size)); } -early_param("mem", early_parsemem); static void hvputc(char c) { diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h index 5213044..0a47ac5 100644 --- a/arch/powerpc/platforms/iseries/setup.h +++ b/arch/powerpc/platforms/iseries/setup.h @@ -21,4 +21,6 @@ extern unsigned long iSeries_get_boot_ti extern int iSeries_set_rtc_time(struct rtc_time *tm); extern void iSeries_get_rtc_time(struct rtc_time *tm); +extern void *build_flat_dt(unsigned long phys_mem_size); + #endif /* __ISERIES_SETUP_H__ */ diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c deleted file mode 100644 index ad36ab0..0000000 --- a/arch/powerpc/platforms/iseries/vio.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * IBM PowerPC iSeries Virtual I/O Infrastructure Support. - * - * Copyright (c) 2005 Stephen Rothwell, IBM Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iommu.h" - -struct device *iSeries_vio_dev = &vio_bus_device.dev; -EXPORT_SYMBOL(iSeries_vio_dev); - -static struct iommu_table veth_iommu_table; -static struct iommu_table vio_iommu_table; - -static void __init iommu_vio_init(void) -{ - iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); - veth_iommu_table.it_size /= 2; - vio_iommu_table = veth_iommu_table; - vio_iommu_table.it_offset += veth_iommu_table.it_size; - - if (!iommu_init_table(&veth_iommu_table)) - printk("Virtual Bus VETH TCE table failed.\n"); - if (!iommu_init_table(&vio_iommu_table)) - printk("Virtual Bus VIO TCE table failed.\n"); -} - -/** - * vio_register_device_iseries: - Register a new iSeries vio device. - * @voidev: The device to register. - */ -static struct vio_dev *__init vio_register_device_iseries(char *type, - uint32_t unit_num) -{ - struct vio_dev *viodev; - - /* allocate a vio_dev for this device */ - viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); - if (!viodev) - return NULL; - memset(viodev, 0, sizeof(struct vio_dev)); - - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num); - - viodev->name = viodev->dev.bus_id; - viodev->type = type; - viodev->unit_address = unit_num; - viodev->iommu_table = &vio_iommu_table; - if (vio_register_device(viodev) == NULL) { - kfree(viodev); - return NULL; - } - return viodev; -} - -void __init probe_bus_iseries(void) -{ - HvLpIndexMap vlan_map; - struct vio_dev *viodev; - int i; - - /* there is only one of each of these */ - vio_register_device_iseries("viocons", 0); - vio_register_device_iseries("vscsi", 0); - - vlan_map = HvLpConfig_getVirtualLanIndexMap(); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { - if ((vlan_map & (0x8000 >> i)) == 0) - continue; - viodev = vio_register_device_iseries("vlan", i); - /* veth is special and has it own iommu_table */ - viodev->iommu_table = &veth_iommu_table; - } - for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) - vio_register_device_iseries("viodasd", i); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) - vio_register_device_iseries("viocd", i); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) - vio_register_device_iseries("viotape", i); -} - -/** - * vio_match_device_iseries: - Tell if a iSeries VIO device matches a - * vio_device_id - */ -static int vio_match_device_iseries(const struct vio_device_id *id, - const struct vio_dev *dev) -{ - return strncmp(dev->type, id->type, strlen(id->type)) == 0; -} - -static struct vio_bus_ops vio_bus_ops_iseries = { - .match = vio_match_device_iseries, -}; - -/** - * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus - */ -static int __init vio_bus_init_iseries(void) -{ - int err; - - err = vio_bus_init(&vio_bus_ops_iseries); - if (err == 0) { - iommu_vio_init(); - vio_bus_device.iommu_table = &vio_iommu_table; - iSeries_vio_dev = &vio_bus_device.dev; - probe_bus_iseries(); - } - return err; -} - -__initcall(vio_bus_init_iseries); diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 85d6c93..9a4efc0 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -437,9 +437,6 @@ void __init maple_pci_init(void) /* Tell pci.c to not change any resource allocations. */ pci_probe_only = 1; - - /* Allow all IO */ - io_page_mask = -1; } int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel) diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 24c0aef..a0505ea 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -189,7 +189,7 @@ #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif - printk(KERN_INFO "Using native/NAP idle loop\n"); + printk(KERN_DEBUG "Using native/NAP idle loop\n"); } /* diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c index 8be2f7d..498b042 100644 --- a/arch/powerpc/platforms/powermac/backlight.c +++ b/arch/powerpc/platforms/powermac/backlight.c @@ -3,200 +3,148 @@ * Contains support for the backlight. * * Copyright (C) 2000 Benjamin Herrenschmidt + * Copyright (C) 2006 Michael Hanselmann * */ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include -#include -#include #include -#include -#include +#define OLD_BACKLIGHT_MAX 15 -static struct backlight_controller *backlighter; -static void* backlighter_data; -static int backlight_autosave; -static int backlight_level = BACKLIGHT_MAX; -static int backlight_enabled = 1; -static int backlight_req_level = -1; -static int backlight_req_enable = -1; +/* Protect the pmac_backlight variable */ +DEFINE_MUTEX(pmac_backlight_mutex); -static void backlight_callback(void *); -static DECLARE_WORK(backlight_work, backlight_callback, NULL); +/* Main backlight storage + * + * Backlight drivers in this variable are required to have the "props" + * attribute set and to have an update_status function. + * + * We can only store one backlight here, but since Apple laptops have only one + * internal display, it doesn't matter. Other backlight drivers can be used + * independently. + * + * Lock ordering: + * pmac_backlight_mutex (global, main backlight) + * pmac_backlight->sem (backlight class) + */ +struct backlight_device *pmac_backlight; -void register_backlight_controller(struct backlight_controller *ctrler, - void *data, char *type) +int pmac_has_backlight_type(const char *type) { - struct device_node* bk_node; - char *prop; - int valid = 0; - - /* There's already a matching controller, bail out */ - if (backlighter != NULL) - return; - - bk_node = find_devices("backlight"); - -#ifdef CONFIG_ADB_PMU - /* Special case for the old PowerBook since I can't test on it */ - backlight_autosave = machine_is_compatible("AAPL,3400/2400") - || machine_is_compatible("AAPL,3500"); - if ((backlight_autosave - || machine_is_compatible("AAPL,PowerBook1998") - || machine_is_compatible("PowerBook1,1")) - && !strcmp(type, "pmu")) - valid = 1; -#endif + struct device_node* bk_node = find_devices("backlight"); + if (bk_node) { - prop = get_property(bk_node, "backlight-control", NULL); - if (prop && !strncmp(prop, type, strlen(type))) - valid = 1; - } - if (!valid) - return; - backlighter = ctrler; - backlighter_data = data; - - if (bk_node && !backlight_autosave) - prop = get_property(bk_node, "bklt", NULL); - else - prop = NULL; - if (prop) { - backlight_level = ((*prop)+1) >> 1; - if (backlight_level > BACKLIGHT_MAX) - backlight_level = BACKLIGHT_MAX; + char *prop = get_property(bk_node, "backlight-control", NULL); + if (prop && strncmp(prop, type, strlen(type)) == 0) + return 1; } -#ifdef CONFIG_ADB_PMU - if (backlight_autosave) { - struct adb_request req; - pmu_request(&req, NULL, 2, 0xd9, 0); - while (!req.complete) - pmu_poll(); - backlight_level = req.reply[0] >> 4; - } -#endif - acquire_console_sem(); - if (!backlighter->set_enable(1, backlight_level, data)) - backlight_enabled = 1; - release_console_sem(); - - printk(KERN_INFO "Registered \"%s\" backlight controller," - "level: %d/15\n", type, backlight_level); + return 0; } -EXPORT_SYMBOL(register_backlight_controller); -void unregister_backlight_controller(struct backlight_controller - *ctrler, void *data) +int pmac_backlight_curve_lookup(struct fb_info *info, int value) { - /* We keep the current backlight level (for now) */ - if (ctrler == backlighter && data == backlighter_data) - backlighter = NULL; + int level = (FB_BACKLIGHT_LEVELS - 1); + + if (info && info->bl_dev) { + int i, max = 0; + + /* Look for biggest value */ + for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) + max = max((int)info->bl_curve[i], max); + + /* Look for nearest value */ + for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) { + int diff = abs(info->bl_curve[i] - value); + if (diff < max) { + max = diff; + level = i; + } + } + + } + + return level; } -EXPORT_SYMBOL(unregister_backlight_controller); -static int __set_backlight_enable(int enable) +static void pmac_backlight_key(int direction) { - int rc; - - if (!backlighter) - return -ENODEV; - acquire_console_sem(); - rc = backlighter->set_enable(enable, backlight_level, - backlighter_data); - if (!rc) - backlight_enabled = enable; - release_console_sem(); - return rc; + mutex_lock(&pmac_backlight_mutex); + if (pmac_backlight) { + struct backlight_properties *props; + int brightness; + + down(&pmac_backlight->sem); + props = pmac_backlight->props; + + brightness = props->brightness + + ((direction?-1:1) * (props->max_brightness / 15)); + + if (brightness < 0) + brightness = 0; + else if (brightness > props->max_brightness) + brightness = props->max_brightness; + + props->brightness = brightness; + props->update_status(pmac_backlight); + + up(&pmac_backlight->sem); + } + mutex_unlock(&pmac_backlight_mutex); } -int set_backlight_enable(int enable) + +void pmac_backlight_key_up() { - if (!backlighter) - return -ENODEV; - backlight_req_enable = enable; - schedule_work(&backlight_work); - return 0; + pmac_backlight_key(0); } -EXPORT_SYMBOL(set_backlight_enable); - -int get_backlight_enable(void) +void pmac_backlight_key_down() { - if (!backlighter) - return -ENODEV; - return backlight_enabled; + pmac_backlight_key(1); } -EXPORT_SYMBOL(get_backlight_enable); -static int __set_backlight_level(int level) +int pmac_backlight_set_legacy_brightness(int brightness) { - int rc = 0; - - if (!backlighter) - return -ENODEV; - if (level < BACKLIGHT_MIN) - level = BACKLIGHT_OFF; - if (level > BACKLIGHT_MAX) - level = BACKLIGHT_MAX; - acquire_console_sem(); - if (backlight_enabled) - rc = backlighter->set_level(level, backlighter_data); - if (!rc) - backlight_level = level; - release_console_sem(); - if (!rc && !backlight_autosave) { - level <<=1; - if (level & 0x10) - level |= 0x01; - // -- todo: save to property "bklt" + int error = -ENXIO; + + mutex_lock(&pmac_backlight_mutex); + if (pmac_backlight) { + struct backlight_properties *props; + + down(&pmac_backlight->sem); + props = pmac_backlight->props; + props->brightness = brightness * + props->max_brightness / OLD_BACKLIGHT_MAX; + props->update_status(pmac_backlight); + up(&pmac_backlight->sem); + + error = 0; } - return rc; + mutex_unlock(&pmac_backlight_mutex); + + return error; } -int set_backlight_level(int level) + +int pmac_backlight_get_legacy_brightness() { - if (!backlighter) - return -ENODEV; - backlight_req_level = level; - schedule_work(&backlight_work); - return 0; -} + int result = -ENXIO; -EXPORT_SYMBOL(set_backlight_level); + mutex_lock(&pmac_backlight_mutex); + if (pmac_backlight) { + struct backlight_properties *props; -int get_backlight_level(void) -{ - if (!backlighter) - return -ENODEV; - return backlight_level; -} -EXPORT_SYMBOL(get_backlight_level); + down(&pmac_backlight->sem); + props = pmac_backlight->props; + result = props->brightness * + OLD_BACKLIGHT_MAX / props->max_brightness; + up(&pmac_backlight->sem); + } + mutex_unlock(&pmac_backlight_mutex); -static void backlight_callback(void *dummy) -{ - int level, enable; - - do { - level = backlight_req_level; - enable = backlight_req_enable; - mb(); - - if (level >= 0) - __set_backlight_level(level); - if (enable >= 0) - __set_backlight_enable(enable); - } while(cmpxchg(&backlight_req_level, level, -1) != level || - cmpxchg(&backlight_req_enable, enable, -1) != enable); + return result; } diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index cfd6527..af2a8f9 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -314,7 +314,7 @@ #endif /* CONFIG_ALTIVEC */ _set_L3CR(save_l3cr); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context.id, current->active_mm->pgd); #ifdef DEBUG_FREQ printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index a5063cd..85e00cb 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -2510,7 +2510,7 @@ #ifndef CONFIG_POWER4 if (get_property(np, "flush-on-lock", NULL)) break; powersave_nap = 1; - printk(KERN_INFO "Processor NAP mode on idle enabled.\n"); + printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n"); break; } diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index ea179af..8003585 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -1068,9 +1068,6 @@ #ifdef CONFIG_PPC64 /* Tell pci.c to not use the common resource allocation mechanism */ pci_probe_only = 1; - /* Allow all IO */ - io_page_mask = -1; - #else /* CONFIG_PPC64 */ init_p2pbridge(); fixup_nec_usb2(); diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index f08173b..047f954 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c @@ -871,10 +871,17 @@ int pmf_register_irq_client(struct devic spin_unlock_irqrestore(&pmf_lock, flags); if (func == NULL) return -ENODEV; + + /* guard against manipulations of list */ mutex_lock(&pmf_irq_mutex); if (list_empty(&func->irq_clients)) func->dev->handlers->irq_enable(func); + + /* guard against pmf_do_irq while changing list */ + spin_lock_irqsave(&pmf_lock, flags); list_add(&client->link, &func->irq_clients); + spin_unlock_irqrestore(&pmf_lock, flags); + client->func = func; mutex_unlock(&pmf_irq_mutex); @@ -885,12 +892,19 @@ EXPORT_SYMBOL_GPL(pmf_register_irq_clien void pmf_unregister_irq_client(struct pmf_irq_client *client) { struct pmf_function *func = client->func; + unsigned long flags; BUG_ON(func == NULL); + /* guard against manipulations of list */ mutex_lock(&pmf_irq_mutex); client->func = NULL; + + /* guard against pmf_do_irq while changing list */ + spin_lock_irqsave(&pmf_lock, flags); list_del(&client->link); + spin_unlock_irqrestore(&pmf_lock, flags); + if (list_empty(&func->irq_clients)) func->dev->handlers->irq_disable(func); mutex_unlock(&pmf_irq_mutex); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index b9200fb..9cc7db7 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -458,7 +458,7 @@ static int pmac_pm_finish(suspend_state_ printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context.id, current->active_mm->pgd); return 0; } diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 9308986..e5e0ff4 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -1,8 +1,11 @@ +ifeq ($(CONFIG_PPC64),y) +EXTRA_CFLAGS += -mno-minimal-toc +endif + obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ firmware.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_SCANLOG) += scanlog.o obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c index d4a402c..c37a849 100644 --- a/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/arch/powerpc/platforms/pseries/eeh_cache.c @@ -287,7 +287,7 @@ void pci_addr_cache_remove_device(struct * find the pci device that corresponds to a given address. * This routine scans all pci busses to build the cache. * Must be run late in boot process, after the pci controllers - * have been scaned for devices (after all device resources are known). + * have been scanned for devices (after all device resources are known). */ void __init pci_addr_cache_build(void) { @@ -304,6 +304,8 @@ void __init pci_addr_cache_build(void) pci_addr_cache_insert_device(dev); dn = pci_device_to_OF_node(dev); + if (!dn) + continue; pci_dev_get (dev); /* matching put is in eeh_remove_device() */ PCI_DN(dn)->pcidev = dev; } diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 1fba695..0ec9a54 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -23,9 +23,8 @@ * */ #include -#include #include -#include +#include #include #include #include @@ -202,7 +201,11 @@ static void eeh_report_failure(struct pc static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) { - int rc; + int cnt, rc; + + /* pcibios will clear the counter; save the value */ + cnt = pe_dn->eeh_freeze_count; + if (bus) pcibios_remove_pci_devices(bus); @@ -241,6 +244,7 @@ static int eeh_reset_device (struct pci_ ssleep (5); pcibios_add_pci_devices(bus); } + pe_dn->eeh_freeze_count = cnt; return 0; } @@ -250,23 +254,29 @@ static int eeh_reset_device (struct pci_ */ #define MAX_WAIT_FOR_RECOVERY 15 -void handle_eeh_events (struct eeh_event *event) +struct pci_dn * handle_eeh_events (struct eeh_event *event) { struct device_node *frozen_dn; struct pci_dn *frozen_pdn; struct pci_bus *frozen_bus; int rc = 0; enum pci_ers_result result = PCI_ERS_RESULT_NONE; - const char *pci_str, *drv_str; + const char *location, *pci_str, *drv_str; frozen_dn = find_device_pe(event->dn); frozen_bus = pcibios_find_pci_bus(frozen_dn); if (!frozen_dn) { - printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n", - pci_name(event->dev)); - return; + + location = (char *) get_property(event->dn, "ibm,loc-code", NULL); + location = location ? location : "unknown"; + printk(KERN_ERR "EEH: Error: Cannot find partition endpoint " + "for location=%s pci addr=%s\n", + location, pci_name(event->dev)); + return NULL; } + location = (char *) get_property(frozen_dn, "ibm,loc-code", NULL); + location = location ? location : "unknown"; /* There are two different styles for coming up with the PE. * In the old style, it was the highest EEH-capable device @@ -278,9 +288,10 @@ void handle_eeh_events (struct eeh_event frozen_bus = pcibios_find_pci_bus (frozen_dn->parent); if (!frozen_bus) { - printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n", - frozen_dn->full_name); - return; + printk(KERN_ERR "EEH: Cannot find PCI bus " + "for location=%s dn=%s\n", + location, frozen_dn->full_name); + return NULL; } #if 0 @@ -314,8 +325,9 @@ #endif eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); printk(KERN_WARNING - "EEH: This PCI device has failed %d times since last reboot: %s - %s\n", - frozen_pdn->eeh_freeze_count, drv_str, pci_str); + "EEH: This PCI device has failed %d times since last reboot: " + "location=%s driver=%s pci addr=%s\n", + frozen_pdn->eeh_freeze_count, location, drv_str, pci_str); /* Walk the various device drivers attached to this slot through * a reset sequence, giving each an opportunity to do what it needs @@ -355,7 +367,7 @@ #endif /* Tell all device drivers that they can resume operations */ pci_walk_bus(frozen_bus, eeh_report_resume, NULL); - return; + return frozen_pdn; excess_failures: /* @@ -364,17 +376,18 @@ excess_failures: * due to actual, failed cards. */ printk(KERN_ERR - "EEH: PCI device %s - %s has failed %d times \n" - "and has been permanently disabled. Please try reseating\n" - "this device or replacing it.\n", - drv_str, pci_str, frozen_pdn->eeh_freeze_count); + "EEH: PCI device at location=%s driver=%s pci addr=%s \n" + "has failed %d times and has been permanently disabled. \n" + "Please try reseating this device or replacing it.\n", + location, drv_str, pci_str, frozen_pdn->eeh_freeze_count); goto perm_error; hard_fail: printk(KERN_ERR - "EEH: Unable to recover from failure of PCI device %s - %s\n" + "EEH: Unable to recover from failure of PCI device " + "at location=%s driver=%s pci addr=%s \n" "Please try reseating this device or replacing it.\n", - drv_str, pci_str); + location, drv_str, pci_str); perm_error: eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */); @@ -384,6 +397,8 @@ perm_error: /* Shut down the device drivers for good. */ pcibios_remove_pci_devices(frozen_bus); + + return NULL; } /* ---------- end of file ---------- */ diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 40020c6..8f2d129 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -18,6 +18,7 @@ * Copyright (c) 2005 Linas Vepstas */ +#include #include #include #include @@ -56,38 +57,43 @@ static int eeh_event_handler(void * dumm { unsigned long flags; struct eeh_event *event; + struct pci_dn *pdn; daemonize ("eehd"); + set_current_state(TASK_INTERRUPTIBLE); - while (1) { - set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&eeh_eventlist_lock, flags); + event = NULL; - spin_lock_irqsave(&eeh_eventlist_lock, flags); - event = NULL; + /* Unqueue the event, get ready to process. */ + if (!list_empty(&eeh_eventlist)) { + event = list_entry(eeh_eventlist.next, struct eeh_event, list); + list_del(&event->list); + } + spin_unlock_irqrestore(&eeh_eventlist_lock, flags); - /* Unqueue the event, get ready to process. */ - if (!list_empty(&eeh_eventlist)) { - event = list_entry(eeh_eventlist.next, struct eeh_event, list); - list_del(&event->list); - } - spin_unlock_irqrestore(&eeh_eventlist_lock, flags); + if (event == NULL) + return 0; - if (event == NULL) - break; + /* Serialize processing of EEH events */ + mutex_lock(&eeh_event_mutex); + eeh_mark_slot(event->dn, EEH_MODE_RECOVERING); - /* Serialize processing of EEH events */ - mutex_lock(&eeh_event_mutex); - eeh_mark_slot(event->dn, EEH_MODE_RECOVERING); + printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", + pci_name(event->dev)); - printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", - pci_name(event->dev)); + pdn = handle_eeh_events(event); - handle_eeh_events(event); + eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); + pci_dev_put(event->dev); + kfree(event); + mutex_unlock(&eeh_event_mutex); - eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); - pci_dev_put(event->dev); - kfree(event); - mutex_unlock(&eeh_event_mutex); + /* If there are no new errors after an hour, clear the counter. */ + if (pdn && pdn->eeh_freeze_count>0) { + msleep_interruptible (3600*1000); + if (pdn->eeh_freeze_count>0) + pdn->eeh_freeze_count--; } return 0; diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 2643078..d03a8b0 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -1,23 +1,24 @@ /* * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * - * Rewrite, cleanup: + * Rewrite, cleanup: * * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2006 Olof Johansson * * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR. * - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -49,52 +50,46 @@ #include "plpar_wrappers.h" #define DBG(fmt...) -static void tce_build_pSeries(struct iommu_table *tbl, long index, - long npages, unsigned long uaddr, +static void tce_build_pSeries(struct iommu_table *tbl, long index, + long npages, unsigned long uaddr, enum dma_data_direction direction) { - union tce_entry t; - union tce_entry *tp; + u64 proto_tce; + u64 *tcep; + u64 rpn; index <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - t.te_word = 0; - t.te_rdwr = 1; // Read allowed + proto_tce = TCE_PCI_READ; // Read allowed if (direction != DMA_TO_DEVICE) - t.te_pciwr = 1; + proto_tce |= TCE_PCI_WRITE; - tp = ((union tce_entry *)tbl->it_base) + index; + tcep = ((u64 *)tbl->it_base) + index; while (npages--) { /* can't move this out since we might cross LMB boundary */ - t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; - - tp->te_word = t.te_word; + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; + *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; uaddr += TCE_PAGE_SIZE; - tp++; + tcep++; } } static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) { - union tce_entry t; - union tce_entry *tp; + u64 *tcep; npages <<= TCE_PAGE_FACTOR; index <<= TCE_PAGE_FACTOR; - t.te_word = 0; - tp = ((union tce_entry *)tbl->it_base) + index; - - while (npages--) { - tp->te_word = t.te_word; - - tp++; - } + tcep = ((u64 *)tbl->it_base) + index; + + while (npages--) + *(tcep++) = 0; } @@ -103,43 +98,44 @@ static void tce_build_pSeriesLP(struct i enum dma_data_direction direction) { u64 rc; - union tce_entry tce; + u64 proto_tce, tce; + u64 rpn; tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; - tce.te_rdwr = 1; + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; + proto_tce = TCE_PCI_READ; if (direction != DMA_TO_DEVICE) - tce.te_pciwr = 1; + proto_tce |= TCE_PCI_WRITE; while (npages--) { - rc = plpar_tce_put((u64)tbl->it_index, - (u64)tcenum << 12, - tce.te_word ); - + tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; + rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce); + if (rc && printk_ratelimit()) { printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\ttcenum = 0x%lx\n", (u64)tcenum); - printk("\ttce val = 0x%lx\n", tce.te_word ); + printk("\ttce val = 0x%lx\n", tce ); show_stack(current, (unsigned long *)__get_SP()); } - + tcenum++; - tce.te_rpn++; + rpn++; } } -static DEFINE_PER_CPU(void *, tce_page) = NULL; +static DEFINE_PER_CPU(u64 *, tce_page) = NULL; static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages, unsigned long uaddr, enum dma_data_direction direction) { u64 rc; - union tce_entry tce, *tcep; + u64 proto_tce; + u64 *tcep; + u64 rpn; long l, limit; if (TCE_PAGE_FACTOR == 0 && npages == 1) @@ -152,7 +148,7 @@ static void tce_buildmulti_pSeriesLP(str * from iommu_alloc{,_sg}() */ if (!tcep) { - tcep = (void *)__get_free_page(GFP_ATOMIC); + tcep = (u64 *)__get_free_page(GFP_ATOMIC); /* If allocation fails, fall back to the loop implementation */ if (!tcep) return tce_build_pSeriesLP(tbl, tcenum, npages, @@ -163,11 +159,10 @@ static void tce_buildmulti_pSeriesLP(str tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; - tce.te_rdwr = 1; + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; + proto_tce = TCE_PCI_READ; if (direction != DMA_TO_DEVICE) - tce.te_pciwr = 1; + proto_tce |= TCE_PCI_WRITE; /* We can map max one pageful of TCEs at a time */ do { @@ -175,11 +170,11 @@ static void tce_buildmulti_pSeriesLP(str * Set up the page with TCE data, looping through and setting * the values. */ - limit = min_t(long, npages, 4096/sizeof(union tce_entry)); + limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE); for (l = 0; l < limit; l++) { - tcep[l] = tce; - tce.te_rpn++; + tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; + rpn++; } rc = plpar_tce_put_indirect((u64)tbl->it_index, @@ -195,7 +190,7 @@ static void tce_buildmulti_pSeriesLP(str printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\tnpages = 0x%lx\n", (u64)npages); - printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word); + printk("\ttce[0] val = 0x%lx\n", tcep[0]); show_stack(current, (unsigned long *)__get_SP()); } } @@ -203,23 +198,17 @@ static void tce_buildmulti_pSeriesLP(str static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) { u64 rc; - union tce_entry tce; tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - while (npages--) { - rc = plpar_tce_put((u64)tbl->it_index, - (u64)tcenum << 12, - tce.te_word); + rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0); if (rc && printk_ratelimit()) { printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\ttcenum = 0x%lx\n", (u64)tcenum); - printk("\ttce val = 0x%lx\n", tce.te_word ); show_stack(current, (unsigned long *)__get_SP()); } @@ -231,31 +220,24 @@ static void tce_free_pSeriesLP(struct io static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) { u64 rc; - union tce_entry tce; tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - - rc = plpar_tce_stuff((u64)tbl->it_index, - (u64)tcenum << 12, - tce.te_word, - npages); + rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages); if (rc && printk_ratelimit()) { printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n"); printk("\trc = %ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\tnpages = 0x%lx\n", (u64)npages); - printk("\ttce val = 0x%lx\n", tce.te_word ); show_stack(current, (unsigned long *)__get_SP()); } } static void iommu_table_setparms(struct pci_controller *phb, struct device_node *dn, - struct iommu_table *tbl) + struct iommu_table *tbl) { struct device_node *node; unsigned long *basep; @@ -275,16 +257,16 @@ static void iommu_table_setparms(struct memset((void *)tbl->it_base, 0, *sizep); tbl->it_busno = phb->bus->number; - + /* Units of tce entries */ tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; - + /* Test if we are going over 2GB of DMA space */ if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) { udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); - panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); + panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); } - + phb->dma_window_base_cur += phb->dma_window_size; /* Set the tce table size - measured in entries */ @@ -299,30 +281,22 @@ static void iommu_table_setparms(struct * iommu_table_setparms_lpar * * Function: On pSeries LPAR systems, return TCE table info, given a pci bus. - * - * ToDo: properly interpret the ibm,dma-window property. The definition is: - * logical-bus-number (1 word) - * phys-address (#address-cells words) - * size (#cell-size words) - * - * Currently we hard code these sizes (more or less). */ static void iommu_table_setparms_lpar(struct pci_controller *phb, struct device_node *dn, struct iommu_table *tbl, - unsigned int *dma_window) + unsigned char *dma_window) { + unsigned long offset, size; + tbl->it_busno = PCI_DN(dn)->bussubno; + of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size); - /* TODO: Parse field size properties properly. */ - tbl->it_size = (((unsigned long)dma_window[4] << 32) | - (unsigned long)dma_window[5]) >> PAGE_SHIFT; - tbl->it_offset = (((unsigned long)dma_window[2] << 32) | - (unsigned long)dma_window[3]) >> PAGE_SHIFT; tbl->it_base = 0; - tbl->it_index = dma_window[0]; tbl->it_blocksize = 16; tbl->it_type = TCE_PCI; + tbl->it_offset = offset >> PAGE_SHIFT; + tbl->it_size = size >> PAGE_SHIFT; } static void iommu_bus_setup_pSeries(struct pci_bus *bus) @@ -357,13 +331,9 @@ static void iommu_bus_setup_pSeries(stru if (isa_dn_orig) of_node_put(isa_dn_orig); - /* Count number of direct PCI children of the PHB. - * All PCI device nodes have class-code property, so it's - * an easy way to find them. - */ + /* Count number of direct PCI children of the PHB. */ for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) - if (get_property(tmp, "class-code", NULL)) - children++; + children++; DBG("Children: %d\n", children); @@ -394,10 +364,11 @@ static void iommu_bus_setup_pSeries(stru pci->phb->dma_window_size = 0x8000000ul; pci->phb->dma_window_base_cur = 0x8000000ul; - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + pci->phb->node); iommu_table_setparms(pci->phb, dn, tbl); - pci->iommu_table = iommu_init_table(tbl); + pci->iommu_table = iommu_init_table(tbl, pci->phb->node); /* Divide the rest (1.75GB) among the children */ pci->phb->dma_window_size = 0x80000000ul; @@ -414,7 +385,7 @@ static void iommu_bus_setup_pSeriesLP(st struct iommu_table *tbl; struct device_node *dn, *pdn; struct pci_dn *ppci; - unsigned int *dma_window = NULL; + unsigned char *dma_window = NULL; DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); @@ -422,7 +393,7 @@ static void iommu_bus_setup_pSeriesLP(st /* Find nearest ibm,dma-window, walking up the device tree */ for (pdn = dn; pdn != NULL; pdn = pdn->parent) { - dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL); + dma_window = get_property(pdn, "ibm,dma-window", NULL); if (dma_window != NULL) break; } @@ -440,12 +411,12 @@ static void iommu_bus_setup_pSeriesLP(st ppci->bussubno = bus->number; - tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), - GFP_KERNEL); - + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + ppci->phb->node); + iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); - ppci->iommu_table = iommu_init_table(tbl); + ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); } if (pdn != dn) @@ -468,9 +439,11 @@ static void iommu_dev_setup_pSeries(stru */ if (!dev->bus->self) { DBG(" --> first child, no bridge. Allocating iommu table.\n"); - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + PCI_DN(dn)->phb->node); iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); - PCI_DN(mydn)->iommu_table = iommu_init_table(tbl); + PCI_DN(dn)->iommu_table = iommu_init_table(tbl, + PCI_DN(dn)->phb->node); return; } @@ -516,7 +489,7 @@ static void iommu_dev_setup_pSeriesLP(st { struct device_node *pdn, *dn; struct iommu_table *tbl; - int *dma_window = NULL; + unsigned char *dma_window = NULL; struct pci_dn *pci; DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev)); @@ -531,8 +504,7 @@ static void iommu_dev_setup_pSeriesLP(st for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; pdn = pdn->parent) { - dma_window = (unsigned int *) - get_property(pdn, "ibm,dma-window", NULL); + dma_window = get_property(pdn, "ibm,dma-window", NULL); if (dma_window) break; } @@ -553,12 +525,12 @@ static void iommu_dev_setup_pSeriesLP(st /* iommu_table_setparms_lpar needs bussubno. */ pci->bussubno = pci->phb->bus->number; - tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), - GFP_KERNEL); + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + pci->phb->node); iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); - pci->iommu_table = iommu_init_table(tbl); + pci->iommu_table = iommu_init_table(tbl, pci->phb->node); } if (pdn != dn) diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index e0000ce..2e4e040 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -348,7 +348,7 @@ static int enable_surveillance(int timeo return 0; if (error == -EINVAL) { - printk(KERN_INFO "rtasd: surveillance not supported\n"); + printk(KERN_DEBUG "rtasd: surveillance not supported\n"); return 0; } @@ -440,7 +440,7 @@ static int rtasd(void *unused) goto error; } - printk(KERN_INFO "RTAS daemon started\n"); + printk(KERN_DEBUG "RTAS daemon started\n"); DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate)); @@ -487,7 +487,7 @@ static int __init rtas_init(void) /* No RTAS */ if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { - printk(KERN_INFO "rtasd: no event-scan on system\n"); + printk(KERN_DEBUG "rtasd: no event-scan on system\n"); return -ENODEV; } diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 5064349..77a5bb1 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c @@ -107,9 +107,9 @@ static ssize_t scanlog_read(struct file /* Break to sleep default time */ break; default: - if (status > 9900 && status <= 9905) { - wait_time = rtas_extended_busy_delay_time(status); - } else { + /* Assume extended busy */ + wait_time = rtas_busy_delay_time(status); + if (!wait_time) { printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status); return -EIO; } diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 3ba8783..1e28518 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -235,14 +235,14 @@ #endif if (firmware_has_feature(FW_FEATURE_SPLPAR)) { vpa_init(boot_cpuid); if (get_lppaca()->shared_proc) { - printk(KERN_INFO "Using shared processor idle loop\n"); + printk(KERN_DEBUG "Using shared processor idle loop\n"); ppc_md.power_save = pseries_shared_idle_sleep; } else { - printk(KERN_INFO "Using dedicated idle loop\n"); + printk(KERN_DEBUG "Using dedicated idle loop\n"); ppc_md.power_save = pseries_dedicated_idle_sleep; } } else { - printk(KERN_INFO "Using default idle loop\n"); + printk(KERN_DEBUG "Using default idle loop\n"); } if (firmware_has_feature(FW_FEATURE_LPAR)) diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c deleted file mode 100644 index 8e53e04..0000000 --- a/arch/powerpc/platforms/pseries/vio.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * IBM PowerPC pSeries Virtual I/O Infrastructure Support. - * - * Copyright (c) 2003-2005 IBM Corp. - * Dave Engebretsen engebret@us.ibm.com - * Santiago Leon santil@us.ibm.com - * Hollis Blanchard - * Stephen Rothwell - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern struct subsystem devices_subsys; /* needed for vio_find_name() */ - -static void probe_bus_pseries(void) -{ - struct device_node *node_vroot, *of_node; - - node_vroot = find_devices("vdevice"); - if ((node_vroot == NULL) || (node_vroot->child == NULL)) - /* this machine doesn't do virtual IO, and that's ok */ - return; - - /* - * Create struct vio_devices for each virtual device in the device tree. - * Drivers will associate with them later. - */ - for (of_node = node_vroot->child; of_node != NULL; - of_node = of_node->sibling) { - printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node); - vio_register_device_node(of_node); - } -} - -/** - * vio_match_device_pseries: - Tell if a pSeries VIO device matches a - * vio_device_id - */ -static int vio_match_device_pseries(const struct vio_device_id *id, - const struct vio_dev *dev) -{ - return (strncmp(dev->type, id->type, strlen(id->type)) == 0) && - device_is_compatible(dev->dev.platform_data, id->compat); -} - -static void vio_release_device_pseries(struct device *dev) -{ - /* XXX free TCE table */ - of_node_put(dev->platform_data); -} - -static ssize_t viodev_show_devspec(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct device_node *of_node = dev->platform_data; - - return sprintf(buf, "%s\n", of_node->full_name); -} -DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL); - -static void vio_unregister_device_pseries(struct vio_dev *viodev) -{ - device_remove_file(&viodev->dev, &dev_attr_devspec); -} - -static struct vio_bus_ops vio_bus_ops_pseries = { - .match = vio_match_device_pseries, - .unregister_device = vio_unregister_device_pseries, - .release_device = vio_release_device_pseries, -}; - -/** - * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus - */ -static int __init vio_bus_init_pseries(void) -{ - int err; - - err = vio_bus_init(&vio_bus_ops_pseries); - if (err == 0) - probe_bus_pseries(); - return err; -} - -__initcall(vio_bus_init_pseries); - -/** - * vio_build_iommu_table: - gets the dma information from OF and - * builds the TCE tree. - * @dev: the virtual device. - * - * Returns a pointer to the built tce tree, or NULL if it can't - * find property. -*/ -static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) -{ - unsigned int *dma_window; - struct iommu_table *newTceTable; - unsigned long offset; - int dma_window_property_size; - - dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size); - if(!dma_window) { - return NULL; - } - - newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - - /* There should be some code to extract the phys-encoded offset - using prom_n_addr_cells(). However, according to a comment - on earlier versions, it's always zero, so we don't bother */ - offset = dma_window[1] >> PAGE_SHIFT; - - /* TCE table size - measured in tce entries */ - newTceTable->it_size = dma_window[4] >> PAGE_SHIFT; - /* offset for VIO should always be 0 */ - newTceTable->it_offset = offset; - newTceTable->it_busno = 0; - newTceTable->it_index = (unsigned long)dma_window[0]; - newTceTable->it_type = TCE_VB; - - return iommu_init_table(newTceTable); -} - -/** - * vio_register_device_node: - Register a new vio device. - * @of_node: The OF node for this device. - * - * Creates and initializes a vio_dev structure from the data in - * of_node (dev.platform_data) and adds it to the list of virtual devices. - * Returns a pointer to the created vio_dev or NULL if node has - * NULL device_type or compatible fields. - */ -struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) -{ - struct vio_dev *viodev; - unsigned int *unit_address; - unsigned int *irq_p; - - /* we need the 'device_type' property, in order to match with drivers */ - if ((NULL == of_node->type)) { - printk(KERN_WARNING - "%s: node %s missing 'device_type'\n", __FUNCTION__, - of_node->name ? of_node->name : ""); - return NULL; - } - - unit_address = (unsigned int *)get_property(of_node, "reg", NULL); - if (!unit_address) { - printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__, - of_node->name ? of_node->name : ""); - return NULL; - } - - /* allocate a vio_dev for this node */ - viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); - if (!viodev) { - return NULL; - } - memset(viodev, 0, sizeof(struct vio_dev)); - - viodev->dev.platform_data = of_node_get(of_node); - - viodev->irq = NO_IRQ; - irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL); - if (irq_p) { - int virq = virt_irq_create_mapping(*irq_p); - if (virq == NO_IRQ) { - printk(KERN_ERR "Unable to allocate interrupt " - "number for %s\n", of_node->full_name); - } else - viodev->irq = irq_offset_up(virq); - } - - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); - viodev->name = of_node->name; - viodev->type = of_node->type; - viodev->unit_address = *unit_address; - viodev->iommu_table = vio_build_iommu_table(viodev); - - /* register with generic device framework */ - if (vio_register_device(viodev) == NULL) { - /* XXX free TCE table */ - kfree(viodev); - return NULL; - } - device_create_file(&viodev->dev, &dev_attr_devspec); - - return viodev; -} -EXPORT_SYMBOL(vio_register_device_node); - -/** - * vio_get_attribute: - get attribute for virtual device - * @vdev: The vio device to get property. - * @which: The property/attribute to be extracted. - * @length: Pointer to length of returned data size (unused if NULL). - * - * Calls prom.c's get_property() to return the value of the - * attribute specified by the preprocessor constant @which -*/ -const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length) -{ - return get_property(vdev->dev.platform_data, (char*)which, length); -} -EXPORT_SYMBOL(vio_get_attribute); - -/* vio_find_name() - internal because only vio.c knows how we formatted the - * kobject name - * XXX once vio_bus_type.devices is actually used as a kset in - * drivers/base/bus.c, this function should be removed in favor of - * "device_find(kobj_name, &vio_bus_type)" - */ -static struct vio_dev *vio_find_name(const char *kobj_name) -{ - struct kobject *found; - - found = kset_find_obj(&devices_subsys.kset, kobj_name); - if (!found) - return NULL; - - return to_vio_dev(container_of(found, struct device, kobj)); -} - -/** - * vio_find_node - find an already-registered vio_dev - * @vnode: device_node of the virtual device we're looking for - */ -struct vio_dev *vio_find_node(struct device_node *vnode) -{ - uint32_t *unit_address; - char kobj_name[BUS_ID_SIZE]; - - /* construct the kobject name from the device node */ - unit_address = (uint32_t *)get_property(vnode, "reg", NULL); - if (!unit_address) - return NULL; - snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); - - return vio_find_name(kobj_name); -} -EXPORT_SYMBOL(vio_find_node); - -int vio_enable_interrupts(struct vio_dev *dev) -{ - int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE); - if (rc != H_SUCCESS) - printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc); - return rc; -} -EXPORT_SYMBOL(vio_enable_interrupts); - -int vio_disable_interrupts(struct vio_dev *dev) -{ - int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE); - if (rc != H_SUCCESS) - printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc); - return rc; -} -EXPORT_SYMBOL(vio_disable_interrupts); diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 2d60ea3..b14f9b5 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -522,7 +522,7 @@ nextnode: np = of_find_node_by_type(NULL, "interrupt-controller"); if (!np) { - printk(KERN_WARNING "xics: no ISA interrupt controller\n"); + printk(KERN_DEBUG "xics: no ISA interrupt controller\n"); xics_irq_8259_cascade_real = -1; xics_irq_8259_cascade = -1; } else { @@ -641,23 +641,26 @@ void xics_teardown_cpu(int secondary) ops->cppr_info(cpu, 0x00); iosync(); + /* Clear IPI */ + ops->qirr_info(cpu, 0xff); + + /* + * we need to EOI the IPI if we got here from kexec down IPI + * + * probably need to check all the other interrupts too + * should we be flagging idle loop instead? + * or creating some task to be scheduled? + */ + ops->xirr_info_set(cpu, XICS_IPI); + /* * Some machines need to have at least one cpu in the GIQ, * so leave the master cpu in the group. */ - if (secondary) { - /* - * we need to EOI the IPI if we got here from kexec down IPI - * - * probably need to check all the other interrupts too - * should we be flagging idle loop instead? - * or creating some task to be scheduled? - */ - ops->xirr_info_set(cpu, XICS_IPI); + if (secondary) rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, (1UL << interrupt_server_size) - 1 - default_distrib_server, 0); - } } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 4c2b356..cef95b0 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -1,3 +1,7 @@ +ifeq ($(CONFIG_PPC64),y) +EXTRA_CFLAGS += -mno-minimal-toc +endif + obj-$(CONFIG_MPIC) += mpic.o obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o obj-$(CONFIG_PPC_I8259) += i8259.o diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 38087bd..6232091 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -246,7 +246,7 @@ static void iommu_table_dart_setup(void) iommu_table_dart.it_base = (unsigned long)dart_vbase; iommu_table_dart.it_index = 0; iommu_table_dart.it_blocksize = 1; - iommu_init_table(&iommu_table_dart); + iommu_init_table(&iommu_table_dart, -1); /* Reserve the last page of the DART to avoid possible prefetch * past the DART mapped area diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index ceb5846..71a3275 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -372,7 +372,7 @@ static int __init fsl_usb_of_init(void) { struct device_node *np; unsigned int i; - struct platform_device *usb_dev; + struct platform_device *usb_dev_mph = NULL, *usb_dev_dr = NULL; int ret; for (np = NULL, i = 0; @@ -393,15 +393,15 @@ static int __init fsl_usb_of_init(void) r[1].end = np->intrs[0].line; r[1].flags = IORESOURCE_IRQ; - usb_dev = - platform_device_register_simple("fsl-usb2-mph", i, r, 2); - if (IS_ERR(usb_dev)) { - ret = PTR_ERR(usb_dev); + usb_dev_mph = + platform_device_register_simple("fsl-ehci", i, r, 2); + if (IS_ERR(usb_dev_mph)) { + ret = PTR_ERR(usb_dev_mph); goto err; } - usb_dev->dev.coherent_dma_mask = 0xffffffffUL; - usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask; + usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL; + usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask; usb_data.operating_mode = FSL_USB2_MPH_HOST; @@ -417,31 +417,14 @@ static int __init fsl_usb_of_init(void) usb_data.phy_mode = determine_usb_phy(prop); ret = - platform_device_add_data(usb_dev, &usb_data, + platform_device_add_data(usb_dev_mph, &usb_data, sizeof(struct fsl_usb2_platform_data)); if (ret) - goto unreg; + goto unreg_mph; } - return 0; - -unreg: - platform_device_unregister(usb_dev); -err: - return ret; -} - -arch_initcall(fsl_usb_of_init); - -static int __init fsl_usb_dr_of_init(void) -{ - struct device_node *np; - unsigned int i; - struct platform_device *usb_dev; - int ret; - - for (np = NULL, i = 0; + for (np = NULL; (np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL; i++) { struct resource r[2]; @@ -453,21 +436,21 @@ static int __init fsl_usb_dr_of_init(voi ret = of_address_to_resource(np, 0, &r[0]); if (ret) - goto err; + goto unreg_mph; r[1].start = np->intrs[0].line; r[1].end = np->intrs[0].line; r[1].flags = IORESOURCE_IRQ; - usb_dev = - platform_device_register_simple("fsl-usb2-dr", i, r, 2); - if (IS_ERR(usb_dev)) { - ret = PTR_ERR(usb_dev); + usb_dev_dr = + platform_device_register_simple("fsl-ehci", i, r, 2); + if (IS_ERR(usb_dev_dr)) { + ret = PTR_ERR(usb_dev_dr); goto err; } - usb_dev->dev.coherent_dma_mask = 0xffffffffUL; - usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask; + usb_dev_dr->dev.coherent_dma_mask = 0xffffffffUL; + usb_dev_dr->dev.dma_mask = &usb_dev_dr->dev.coherent_dma_mask; usb_data.operating_mode = FSL_USB2_DR_HOST; @@ -475,19 +458,22 @@ static int __init fsl_usb_dr_of_init(voi usb_data.phy_mode = determine_usb_phy(prop); ret = - platform_device_add_data(usb_dev, &usb_data, + platform_device_add_data(usb_dev_dr, &usb_data, sizeof(struct fsl_usb2_platform_data)); if (ret) - goto unreg; + goto unreg_dr; } - return 0; -unreg: - platform_device_unregister(usb_dev); +unreg_dr: + if (usb_dev_dr) + platform_device_unregister(usb_dev_dr); +unreg_mph: + if (usb_dev_mph) + platform_device_unregister(usb_dev_mph); err: return ret; } -arch_initcall(fsl_usb_dr_of_init); +arch_initcall(fsl_usb_of_init); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 7dcdfcb..bffe50d 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -829,7 +829,27 @@ #endif mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0); } +void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) +{ + u32 v; + + v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1); + v &= ~MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK; + v |= MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO(clock_ratio); + mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v); +} +void __init mpic_set_serial_int(struct mpic *mpic, int enable) +{ + u32 v; + + v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1); + if (enable) + v |= MPIC_GREG_GLOBAL_CONF_1_SIE; + else + v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE; + mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v); +} void mpic_irq_set_priority(unsigned int irq, unsigned int pri) { diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 4735b41..0741df8 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -26,9 +26,6 @@ #include #include #include #include -#ifdef CONFIG_PMAC_BACKLIGHT -#include -#endif #include #include #include diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index e9a8f5d..b55de4f 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -40,6 +40,10 @@ config GENERIC_NVRAM bool default y +config GENERIC_FIND_NEXT_BIT + bool + default y + config SCHED_NO_NO_OMIT_FRAME_POINTER bool default y diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile index 80c84d5..2f995f7 100644 --- a/arch/ppc/boot/lib/Makefile +++ b/arch/ppc/boot/lib/Makefile @@ -5,7 +5,7 @@ # CFLAGS_kbd.o := -Idrivers/char CFLAGS_vreset.o := -Iarch/ppc/boot/include -zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c +zlib := inffast.c inflate.c inftrees.c lib-y += $(zlib:.c=.o) div64.o lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o diff --git a/arch/ppc/kernel/machine_kexec.c b/arch/ppc/kernel/machine_kexec.c index 84d65a8..a469ba4 100644 --- a/arch/ppc/kernel/machine_kexec.c +++ b/arch/ppc/kernel/machine_kexec.c @@ -25,8 +25,8 @@ typedef NORET_TYPE void (*relocate_new_k unsigned long reboot_code_buffer, unsigned long start_address) ATTRIB_NORET; -const extern unsigned char relocate_new_kernel[]; -const extern unsigned int relocate_new_kernel_size; +extern const unsigned char relocate_new_kernel[]; +extern const unsigned int relocate_new_kernel_size; void machine_shutdown(void) { diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 809673a..d20accf 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -1032,7 +1032,6 @@ int pci_mmap_page_range(struct pci_dev * return -EINVAL; vma->vm_pgoff = offset >> PAGE_SHIFT; - vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO; vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, vma->vm_page_prot, mmap_state, write_combine); diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 386e000..c9bd184 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -583,7 +583,7 @@ #ifdef CONFIG_PPC_STD_MMU mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm; pmd = pmd_offset(pgd_offset(mm, address), address); if (!pmd_none(*pmd)) - add_hash_page(mm->context, address, pmd_val(*pmd)); + add_hash_page(mm->context.id, address, pmd_val(*pmd)); } #endif } diff --git a/arch/ppc/mm/mmu_context.c b/arch/ppc/mm/mmu_context.c index b4a4b3f..8784f37 100644 --- a/arch/ppc/mm/mmu_context.c +++ b/arch/ppc/mm/mmu_context.c @@ -30,7 +30,7 @@ #include #include #include -mm_context_t next_mmu_context; +unsigned long next_mmu_context; unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1]; #ifdef FEW_CONTEXTS atomic_t nr_free_contexts; diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c index 6c3dc3c..606b023 100644 --- a/arch/ppc/mm/tlb.c +++ b/arch/ppc/mm/tlb.c @@ -42,7 +42,7 @@ void flush_hash_entry(struct mm_struct * if (Hash != 0) { ptephys = __pa(ptep) & PAGE_MASK; - flush_hash_pages(mm->context, addr, ptephys, 1); + flush_hash_pages(mm->context.id, addr, ptephys, 1); } } @@ -102,7 +102,7 @@ static void flush_range(struct mm_struct pmd_t *pmd; unsigned long pmd_end; int count; - unsigned int ctx = mm->context; + unsigned int ctx = mm->context.id; if (Hash == 0) { _tlbia(); @@ -166,7 +166,7 @@ void flush_tlb_page(struct vm_area_struc mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm; pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr); if (!pmd_none(*pmd)) - flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1); + flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1); FINISH_FLUSH; } diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig index 174ddbc..293bd48 100644 --- a/arch/ppc/platforms/4xx/Kconfig +++ b/arch/ppc/platforms/4xx/Kconfig @@ -183,7 +183,7 @@ config IBM_EMAC4 config BIOS_FIXUP bool - depends on BUBINGA || EP405 || SYCAMORE || WALNUT + depends on BUBINGA || EP405 || SYCAMORE || WALNUT || CPCI405 default y # OAK doesn't exist but wanted to keep this around for any future 403GCX boards diff --git a/arch/ppc/platforms/4xx/cpci405.c b/arch/ppc/platforms/4xx/cpci405.c index 6571e39..970b698 100644 --- a/arch/ppc/platforms/4xx/cpci405.c +++ b/arch/ppc/platforms/4xx/cpci405.c @@ -1,10 +1,12 @@ /* * Board setup routines for the esd CPCI-405 cPCI Board. * - * Author: Stefan Roese - * stefan.roese@esd-electronics.com + * Copyright 2001-2006 esd electronic system design - hannover germany * - * Copyright 2001 esd electronic system design - hannover germany + * Authors: Matthias Fuchs + * matthias.fuchs@esd-electronics.com + * Stefan Roese + * stefan.roese@esd-electronics.com * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -20,9 +22,17 @@ #include #include #include #include +#include +#include #include +#include +#include +#ifdef CONFIG_GEN_RTC void *cpci405_nvram; +#endif + +extern bd_t __res; /* * Some IRQs unique to CPCI-405. @@ -36,18 +46,69 @@ ppc405_map_irq(struct pci_dev *dev, unsi * A B C D */ { - {28, 28, 28, 28}, /* IDSEL 15 - cPCI slot 8 */ - {29, 29, 29, 29}, /* IDSEL 16 - cPCI slot 7 */ - {30, 30, 30, 30}, /* IDSEL 17 - cPCI slot 6 */ - {27, 27, 27, 27}, /* IDSEL 18 - cPCI slot 5 */ - {28, 28, 28, 28}, /* IDSEL 19 - cPCI slot 4 */ - {29, 29, 29, 29}, /* IDSEL 20 - cPCI slot 3 */ - {30, 30, 30, 30}, /* IDSEL 21 - cPCI slot 2 */ + {28, 29, 30, 27}, /* IDSEL 15 - cPCI slot 8 */ + {29, 30, 27, 28}, /* IDSEL 16 - cPCI slot 7 */ + {30, 27, 28, 29}, /* IDSEL 17 - cPCI slot 6 */ + {27, 28, 29, 30}, /* IDSEL 18 - cPCI slot 5 */ + {28, 29, 30, 27}, /* IDSEL 19 - cPCI slot 4 */ + {29, 30, 27, 28}, /* IDSEL 20 - cPCI slot 3 */ + {30, 27, 28, 29}, /* IDSEL 21 - cPCI slot 2 */ }; const long min_idsel = 15, max_idsel = 21, irqs_per_slot = 4; return PCI_IRQ_TABLE_LOOKUP; }; +/* The serial clock for the chip is an internal clock determined by + * different clock speeds/dividers. + * Calculate the proper input baud rate and setup the serial driver. + */ +static void __init +cpci405_early_serial_map(void) +{ + u32 uart_div; + int uart_clock; + struct uart_port port; + + /* Calculate the serial clock input frequency + * + * The uart clock is the cpu frequency (provided in the board info + * structure) divided by the external UART Divisor. + */ + uart_div = ((mfdcr(DCRN_CHCR_BASE) & CHR0_UDIV) >> 1) + 1; + uart_clock = __res.bi_procfreq / uart_div; + + /* Setup serial port access */ + memset(&port, 0, sizeof(port)); +#if defined(CONFIG_UART0_TTYS0) + port.membase = (void*)UART0_IO_BASE; + port.irq = UART0_INT; +#else + port.membase = (void*)UART1_IO_BASE; + port.irq = UART1_INT; +#endif + port.uartclk = uart_clock; + port.regshift = 0; + port.iotype = UPIO_MEM; + port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + port.line = 0; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 0 failed\n"); + } +#if defined(CONFIG_UART0_TTYS0) + port.membase = (void*)UART1_IO_BASE; + port.irq = UART1_INT; +#else + port.membase = (void*)UART0_IO_BASE; + port.irq = UART0_INT; +#endif + port.line = 1; + + if (early_serial_setup(&port) != 0) { + printk("Early serial init of port 1 failed\n"); + } +} + void __init cpci405_setup_arch(void) { @@ -55,14 +116,68 @@ cpci405_setup_arch(void) ibm_ocp_set_emac(0, 0); - TODC_INIT(TODC_TYPE_MK48T35, cpci405_nvram, cpci405_nvram, cpci405_nvram, 8); + cpci405_early_serial_map(); + +#ifdef CONFIG_GEN_RTC + TODC_INIT(TODC_TYPE_MK48T35, + cpci405_nvram, cpci405_nvram, cpci405_nvram, 8); +#endif +} + +void __init +bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) +{ + unsigned int bar_response, bar; + + /* Disable region first */ + out_le32((void *) &(pcip->pmm[0].ma), 0x00000000); + /* PLB starting addr, PCI: 0x80000000 */ + out_le32((void *) &(pcip->pmm[0].la), 0x80000000); + /* PCI start addr, 0x80000000 */ + out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE); + /* 512MB range of PLB to PCI */ + out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000); + /* Enable no pre-fetch, enable region */ + out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff - + (PPC405_PCI_UPPER_MEM - + PPC405_PCI_MEM_BASE)) | 0x01)); + + /* Disable region one */ + out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); + out_le32((void *) &(pcip->pmm[1].la), 0x00000000); + out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000); + out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000); + out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); + out_le32((void *) &(pcip->ptm1ms), 0x00000001); + + /* Disable region two */ + out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); + out_le32((void *) &(pcip->pmm[2].la), 0x00000000); + out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000); + out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000); + out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); + out_le32((void *) &(pcip->ptm2ms), 0x00000000); + out_le32((void *) &(pcip->ptm2la), 0x00000000); + + /* Zero config bars */ + for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) { + early_write_config_dword(hose, hose->first_busno, + PCI_FUNC(hose->first_busno), bar, + 0x00000000); + early_read_config_dword(hose, hose->first_busno, + PCI_FUNC(hose->first_busno), bar, + &bar_response); + } } void __init cpci405_map_io(void) { ppc4xx_map_io(); + +#ifdef CONFIG_GEN_RTC cpci405_nvram = ioremap(CPCI405_NVRAM_PADDR, CPCI405_NVRAM_SIZE); +#endif } void __init @@ -74,9 +189,11 @@ platform_init(unsigned long r3, unsigned ppc_md.setup_arch = cpci405_setup_arch; ppc_md.setup_io_mappings = cpci405_map_io; +#ifdef CONFIG_GEN_RTC ppc_md.time_init = todc_time_init; ppc_md.set_rtc_time = todc_set_rtc_time; ppc_md.get_rtc_time = todc_get_rtc_time; ppc_md.nvram_read_val = todc_direct_read_val; ppc_md.nvram_write_val = todc_direct_write_val; +#endif } diff --git a/arch/ppc/platforms/4xx/cpci405.h b/arch/ppc/platforms/4xx/cpci405.h index e27f7cb..f5a5c0c 100644 --- a/arch/ppc/platforms/4xx/cpci405.h +++ b/arch/ppc/platforms/4xx/cpci405.h @@ -1,37 +1,29 @@ /* * CPCI-405 board specific definitions * - * Copyright (c) 2001 Stefan Roese (stefan.roese@esd-electronics.com) + * Copyright 2001-2006 esd electronic system design - hannover germany + * + * Authors: Matthias Fuchs + * matthias.fuchs@esd-electronics.com + * Stefan Roese + * stefan.roese@esd-electronics.com */ #ifdef __KERNEL__ -#ifndef __ASM_CPCI405_H__ -#define __ASM_CPCI405_H__ +#ifndef __CPCI405_H__ +#define __CPCI405_H__ #include - -/* We have a 405GP core */ #include - #include -#ifndef __ASSEMBLY__ -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - /* Map for the NVRAM space */ #define CPCI405_NVRAM_PADDR ((uint)0xf0200000) #define CPCI405_NVRAM_SIZE ((uint)32*1024) -#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK -#define BASE_BAUD 201600 -#else -#define BASE_BAUD 691200 -#endif +#define BASE_BAUD 0 -#define PPC4xx_MACHINE_NAME "esd CPCI-405" +#define PPC4xx_MACHINE_NAME "esd CPCI-405" -#endif /* !__ASSEMBLY__ */ -#endif /* __ASM_CPCI405_H__ */ +#endif /* __CPCI405_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index c9e0aee..4368dc3 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -379,13 +379,12 @@ mpc85xx_cds_pcibios_fixup(void) PCI_DEVICE_ID_VIA_82C586_2, NULL))) { dev->irq = 10; pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); - pci_dev_put(dev); - } - if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, dev))) { - dev->irq = 11; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + dev->irq = 11; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + } pci_dev_put(dev); } } diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index 1af2c00..5c4932c 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c @@ -186,7 +186,7 @@ struct platform_device ppc_sys_platform_ }, }, [MPC83xx_USB2_DR] = { - .name = "fsl-usb2-dr", + .name = "fsl-ehci", .id = 1, .num_resources = 2, .resource = (struct resource[]) { @@ -203,8 +203,8 @@ struct platform_device ppc_sys_platform_ }, }, [MPC83xx_USB2_MPH] = { - .name = "fsl-usb2-mph", - .id = 1, + .name = "fsl-ehci", + .id = 2, .num_resources = 2, .resource = (struct resource[]) { { diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 01c5c08..821a141 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -446,6 +446,14 @@ config NO_IDLE_HZ_INIT The HZ timer is switched off in idle by default. That means the HZ timer is already disabled at boot time. +config S390_HYPFS_FS + bool "s390 hypervisor file system support" + select SYS_HYPERVISOR + default y + help + This is a virtual file system intended to provide accounting + information in an s390 hypervisor environment. + config KEXEC bool "kexec system call (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 7bb16fb..b3791fb 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -76,7 +76,7 @@ LDFLAGS_vmlinux := -e start head-y := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \ - arch/$(ARCH)/appldata/ + arch/$(ARCH)/appldata/ arch/$(ARCH)/hypfs/ libs-y += arch/$(ARCH)/lib/ drivers-y += drivers/s390/ drivers-$(CONFIG_MATHEMU) += arch/$(ARCH)/math-emu/ diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index c5ca2dc..5713c7e 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -37,10 +37,10 @@ struct s390_aes_ctx { int key_len; }; -static int aes_set_key(void *ctx, const u8 *in_key, unsigned int key_len, - u32 *flags) +static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len, u32 *flags) { - struct s390_aes_ctx *sctx = ctx; + struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); switch (key_len) { case 16: @@ -70,9 +70,9 @@ fail: return -EINVAL; } -static void aes_encrypt(void *ctx, u8 *out, const u8 *in) +static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - const struct s390_aes_ctx *sctx = ctx; + const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); switch (sctx->key_len) { case 16: @@ -90,9 +90,9 @@ static void aes_encrypt(void *ctx, u8 *o } } -static void aes_decrypt(void *ctx, u8 *out, const u8 *in) +static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - const struct s390_aes_ctx *sctx = ctx; + const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); switch (sctx->key_len) { case 16: diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c index e3c37aa..b3f7496 100644 --- a/arch/s390/crypto/des_s390.c +++ b/arch/s390/crypto/des_s390.c @@ -44,10 +44,10 @@ struct crypt_s390_des3_192_ctx { u8 key[DES3_192_KEY_SIZE]; }; -static int des_setkey(void *ctx, const u8 *key, unsigned int keylen, - u32 *flags) +static int des_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen, u32 *flags) { - struct crypt_s390_des_ctx *dctx = ctx; + struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm); int ret; /* test if key is valid (not a weak key) */ @@ -57,16 +57,16 @@ static int des_setkey(void *ctx, const u return ret; } -static void des_encrypt(void *ctx, u8 *out, const u8 *in) +static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - struct crypt_s390_des_ctx *dctx = ctx; + struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm); crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, out, in, DES_BLOCK_SIZE); } -static void des_decrypt(void *ctx, u8 *out, const u8 *in) +static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - struct crypt_s390_des_ctx *dctx = ctx; + struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm); crypt_s390_km(KM_DEA_DECRYPT, dctx->key, out, in, DES_BLOCK_SIZE); } @@ -166,11 +166,11 @@ static struct crypto_alg des_alg = { * Implementers MUST reject keys that exhibit this property. * */ -static int des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, - u32 *flags) +static int des3_128_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen, u32 *flags) { int i, ret; - struct crypt_s390_des3_128_ctx *dctx = ctx; + struct crypt_s390_des3_128_ctx *dctx = crypto_tfm_ctx(tfm); const u8* temp_key = key; if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) { @@ -186,17 +186,17 @@ static int des3_128_setkey(void *ctx, co return 0; } -static void des3_128_encrypt(void *ctx, u8 *dst, const u8 *src) +static void des3_128_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct crypt_s390_des3_128_ctx *dctx = ctx; + struct crypt_s390_des3_128_ctx *dctx = crypto_tfm_ctx(tfm); crypt_s390_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src, DES3_128_BLOCK_SIZE); } -static void des3_128_decrypt(void *ctx, u8 *dst, const u8 *src) +static void des3_128_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct crypt_s390_des3_128_ctx *dctx = ctx; + struct crypt_s390_des3_128_ctx *dctx = crypto_tfm_ctx(tfm); crypt_s390_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src, DES3_128_BLOCK_SIZE); @@ -302,11 +302,11 @@ static struct crypto_alg des3_128_alg = * property. * */ -static int des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, - u32 *flags) +static int des3_192_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen, u32 *flags) { int i, ret; - struct crypt_s390_des3_192_ctx *dctx = ctx; + struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm); const u8* temp_key = key; if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && @@ -325,17 +325,17 @@ static int des3_192_setkey(void *ctx, co return 0; } -static void des3_192_encrypt(void *ctx, u8 *dst, const u8 *src) +static void des3_192_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct crypt_s390_des3_192_ctx *dctx = ctx; + struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm); crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src, DES3_192_BLOCK_SIZE); } -static void des3_192_decrypt(void *ctx, u8 *dst, const u8 *src) +static void des3_192_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct crypt_s390_des3_192_ctx *dctx = ctx; + struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm); crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src, DES3_192_BLOCK_SIZE); diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c index 98c896b..9d34a35 100644 --- a/arch/s390/crypto/sha1_s390.c +++ b/arch/s390/crypto/sha1_s390.c @@ -40,28 +40,29 @@ struct crypt_s390_sha1_ctx { u8 buffer[2 * SHA1_BLOCK_SIZE]; }; -static void -sha1_init(void *ctx) +static void sha1_init(struct crypto_tfm *tfm) { - static const struct crypt_s390_sha1_ctx initstate = { - .state = { - 0x67452301, - 0xEFCDAB89, - 0x98BADCFE, - 0x10325476, - 0xC3D2E1F0 - }, + struct crypt_s390_sha1_ctx *ctx = crypto_tfm_ctx(tfm); + static const u32 initstate[5] = { + 0x67452301, + 0xEFCDAB89, + 0x98BADCFE, + 0x10325476, + 0xC3D2E1F0 }; - memcpy(ctx, &initstate, sizeof(initstate)); + + ctx->count = 0; + memcpy(ctx->state, &initstate, sizeof(initstate)); + ctx->buf_len = 0; } -static void -sha1_update(void *ctx, const u8 *data, unsigned int len) +static void sha1_update(struct crypto_tfm *tfm, const u8 *data, + unsigned int len) { struct crypt_s390_sha1_ctx *sctx; long imd_len; - sctx = ctx; + sctx = crypto_tfm_ctx(tfm); sctx->count += len * 8; //message bit length //anything in buffer yet? -> must be completed @@ -110,10 +111,9 @@ pad_message(struct crypt_s390_sha1_ctx* } /* Add padding and return the message digest. */ -static void -sha1_final(void* ctx, u8 *out) +static void sha1_final(struct crypto_tfm *tfm, u8 *out) { - struct crypt_s390_sha1_ctx *sctx = ctx; + struct crypt_s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm); //must perform manual padding pad_message(sctx); diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c index 1ec5e92..f573df3 100644 --- a/arch/s390/crypto/sha256_s390.c +++ b/arch/s390/crypto/sha256_s390.c @@ -31,9 +31,9 @@ struct s390_sha256_ctx { u8 buf[2 * SHA256_BLOCK_SIZE]; }; -static void sha256_init(void *ctx) +static void sha256_init(struct crypto_tfm *tfm) { - struct s390_sha256_ctx *sctx = ctx; + struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm); sctx->state[0] = 0x6a09e667; sctx->state[1] = 0xbb67ae85; @@ -44,12 +44,12 @@ static void sha256_init(void *ctx) sctx->state[6] = 0x1f83d9ab; sctx->state[7] = 0x5be0cd19; sctx->count = 0; - memset(sctx->buf, 0, sizeof(sctx->buf)); } -static void sha256_update(void *ctx, const u8 *data, unsigned int len) +static void sha256_update(struct crypto_tfm *tfm, const u8 *data, + unsigned int len) { - struct s390_sha256_ctx *sctx = ctx; + struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm); unsigned int index; int ret; @@ -108,9 +108,9 @@ static void pad_message(struct s390_sha2 } /* Add padding and return the message digest */ -static void sha256_final(void* ctx, u8 *out) +static void sha256_final(struct crypto_tfm *tfm, u8 *out) { - struct s390_sha256_ctx *sctx = ctx; + struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm); /* must perform manual padding */ pad_message(sctx); diff --git a/arch/s390/hypfs/Makefile b/arch/s390/hypfs/Makefile new file mode 100644 index 0000000..f4b00cd --- /dev/null +++ b/arch/s390/hypfs/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the linux hypfs filesystem routines. +# + +obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o + +s390_hypfs-objs := inode.o hypfs_diag.o diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h new file mode 100644 index 0000000..ea5567b --- /dev/null +++ b/arch/s390/hypfs/hypfs.h @@ -0,0 +1,30 @@ +/* + * fs/hypfs/hypfs.h + * Hypervisor filesystem for Linux on s390. + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Michael Holzheu + */ + +#ifndef _HYPFS_H_ +#define _HYPFS_H_ + +#include +#include + +#define REG_FILE_MODE 0440 +#define UPDATE_FILE_MODE 0220 +#define DIR_MODE 0550 + +extern struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent, + const char *name); + +extern struct dentry *hypfs_create_u64(struct super_block *sb, + struct dentry *dir, const char *name, + __u64 value); + +extern struct dentry *hypfs_create_str(struct super_block *sb, + struct dentry *dir, const char *name, + char *string); + +#endif /* _HYPFS_H_ */ diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c new file mode 100644 index 0000000..efa74af --- /dev/null +++ b/arch/s390/hypfs/hypfs_diag.c @@ -0,0 +1,696 @@ +/* + * fs/hypfs/hypfs_diag.c + * Hypervisor filesystem for Linux on s390. Diag 204 and 224 + * implementation. + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Michael Holzheu + */ + +#include +#include +#include +#include +#include +#include "hypfs.h" + +#define LPAR_NAME_LEN 8 /* lpar name len in diag 204 data */ +#define CPU_NAME_LEN 16 /* type name len of cpus in diag224 name table */ +#define TMP_SIZE 64 /* size of temporary buffers */ + +/* diag 204 subcodes */ +enum diag204_sc { + SUBC_STIB4 = 4, + SUBC_RSI = 5, + SUBC_STIB6 = 6, + SUBC_STIB7 = 7 +}; + +/* The two available diag 204 data formats */ +enum diag204_format { + INFO_SIMPLE = 0, + INFO_EXT = 0x00010000 +}; + +/* bit is set in flags, when physical cpu info is included in diag 204 data */ +#define LPAR_PHYS_FLG 0x80 + +static char *diag224_cpu_names; /* diag 224 name table */ +static enum diag204_sc diag204_store_sc; /* used subcode for store */ +static enum diag204_format diag204_info_type; /* used diag 204 data format */ + +static void *diag204_buf; /* 4K aligned buffer for diag204 data */ +static void *diag204_buf_vmalloc; /* vmalloc pointer for diag204 data */ +static int diag204_buf_pages; /* number of pages for diag204 data */ + +/* + * DIAG 204 data structures and member access functions. + * + * Since we have two different diag 204 data formats for old and new s390 + * machines, we do not access the structs directly, but use getter functions for + * each struct member instead. This should make the code more readable. + */ + +/* Time information block */ + +struct info_blk_hdr { + __u8 npar; + __u8 flags; + __u16 tslice; + __u16 phys_cpus; + __u16 this_part; + __u64 curtod; +} __attribute__ ((packed)); + +struct x_info_blk_hdr { + __u8 npar; + __u8 flags; + __u16 tslice; + __u16 phys_cpus; + __u16 this_part; + __u64 curtod1; + __u64 curtod2; + char reserved[40]; +} __attribute__ ((packed)); + +static inline int info_blk_hdr__size(enum diag204_format type) +{ + if (type == INFO_SIMPLE) + return sizeof(struct info_blk_hdr); + else /* INFO_EXT */ + return sizeof(struct x_info_blk_hdr); +} + +static inline __u8 info_blk_hdr__npar(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct info_blk_hdr *)hdr)->npar; + else /* INFO_EXT */ + return ((struct x_info_blk_hdr *)hdr)->npar; +} + +static inline __u8 info_blk_hdr__flags(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct info_blk_hdr *)hdr)->flags; + else /* INFO_EXT */ + return ((struct x_info_blk_hdr *)hdr)->flags; +} + +static inline __u16 info_blk_hdr__pcpus(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct info_blk_hdr *)hdr)->phys_cpus; + else /* INFO_EXT */ + return ((struct x_info_blk_hdr *)hdr)->phys_cpus; +} + +/* Partition header */ + +struct part_hdr { + __u8 pn; + __u8 cpus; + char reserved[6]; + char part_name[LPAR_NAME_LEN]; +} __attribute__ ((packed)); + +struct x_part_hdr { + __u8 pn; + __u8 cpus; + __u8 rcpus; + __u8 pflag; + __u32 mlu; + char part_name[LPAR_NAME_LEN]; + char lpc_name[8]; + char os_name[8]; + __u64 online_cs; + __u64 online_es; + __u8 upid; + char reserved1[3]; + __u32 group_mlu; + char group_name[8]; + char reserved2[32]; +} __attribute__ ((packed)); + +static inline int part_hdr__size(enum diag204_format type) +{ + if (type == INFO_SIMPLE) + return sizeof(struct part_hdr); + else /* INFO_EXT */ + return sizeof(struct x_part_hdr); +} + +static inline __u8 part_hdr__rcpus(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct part_hdr *)hdr)->cpus; + else /* INFO_EXT */ + return ((struct x_part_hdr *)hdr)->rcpus; +} + +static inline void part_hdr__part_name(enum diag204_format type, void *hdr, + char *name) +{ + if (type == INFO_SIMPLE) + memcpy(name, ((struct part_hdr *)hdr)->part_name, + LPAR_NAME_LEN); + else /* INFO_EXT */ + memcpy(name, ((struct x_part_hdr *)hdr)->part_name, + LPAR_NAME_LEN); + EBCASC(name, LPAR_NAME_LEN); + name[LPAR_NAME_LEN] = 0; + strstrip(name); +} + +struct cpu_info { + __u16 cpu_addr; + char reserved1[2]; + __u8 ctidx; + __u8 cflag; + __u16 weight; + __u64 acc_time; + __u64 lp_time; +} __attribute__ ((packed)); + +struct x_cpu_info { + __u16 cpu_addr; + char reserved1[2]; + __u8 ctidx; + __u8 cflag; + __u16 weight; + __u64 acc_time; + __u64 lp_time; + __u16 min_weight; + __u16 cur_weight; + __u16 max_weight; + char reseved2[2]; + __u64 online_time; + __u64 wait_time; + __u32 pma_weight; + __u32 polar_weight; + char reserved3[40]; +} __attribute__ ((packed)); + +/* CPU info block */ + +static inline int cpu_info__size(enum diag204_format type) +{ + if (type == INFO_SIMPLE) + return sizeof(struct cpu_info); + else /* INFO_EXT */ + return sizeof(struct x_cpu_info); +} + +static inline __u8 cpu_info__ctidx(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct cpu_info *)hdr)->ctidx; + else /* INFO_EXT */ + return ((struct x_cpu_info *)hdr)->ctidx; +} + +static inline __u16 cpu_info__cpu_addr(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct cpu_info *)hdr)->cpu_addr; + else /* INFO_EXT */ + return ((struct x_cpu_info *)hdr)->cpu_addr; +} + +static inline __u64 cpu_info__acc_time(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct cpu_info *)hdr)->acc_time; + else /* INFO_EXT */ + return ((struct x_cpu_info *)hdr)->acc_time; +} + +static inline __u64 cpu_info__lp_time(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct cpu_info *)hdr)->lp_time; + else /* INFO_EXT */ + return ((struct x_cpu_info *)hdr)->lp_time; +} + +static inline __u64 cpu_info__online_time(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return 0; /* online_time not available in simple info */ + else /* INFO_EXT */ + return ((struct x_cpu_info *)hdr)->online_time; +} + +/* Physical header */ + +struct phys_hdr { + char reserved1[1]; + __u8 cpus; + char reserved2[6]; + char mgm_name[8]; +} __attribute__ ((packed)); + +struct x_phys_hdr { + char reserved1[1]; + __u8 cpus; + char reserved2[6]; + char mgm_name[8]; + char reserved3[80]; +} __attribute__ ((packed)); + +static inline int phys_hdr__size(enum diag204_format type) +{ + if (type == INFO_SIMPLE) + return sizeof(struct phys_hdr); + else /* INFO_EXT */ + return sizeof(struct x_phys_hdr); +} + +static inline __u8 phys_hdr__cpus(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct phys_hdr *)hdr)->cpus; + else /* INFO_EXT */ + return ((struct x_phys_hdr *)hdr)->cpus; +} + +/* Physical CPU info block */ + +struct phys_cpu { + __u16 cpu_addr; + char reserved1[2]; + __u8 ctidx; + char reserved2[3]; + __u64 mgm_time; + char reserved3[8]; +} __attribute__ ((packed)); + +struct x_phys_cpu { + __u16 cpu_addr; + char reserved1[2]; + __u8 ctidx; + char reserved2[3]; + __u64 mgm_time; + char reserved3[80]; +} __attribute__ ((packed)); + +static inline int phys_cpu__size(enum diag204_format type) +{ + if (type == INFO_SIMPLE) + return sizeof(struct phys_cpu); + else /* INFO_EXT */ + return sizeof(struct x_phys_cpu); +} + +static inline __u16 phys_cpu__cpu_addr(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct phys_cpu *)hdr)->cpu_addr; + else /* INFO_EXT */ + return ((struct x_phys_cpu *)hdr)->cpu_addr; +} + +static inline __u64 phys_cpu__mgm_time(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct phys_cpu *)hdr)->mgm_time; + else /* INFO_EXT */ + return ((struct x_phys_cpu *)hdr)->mgm_time; +} + +static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct phys_cpu *)hdr)->ctidx; + else /* INFO_EXT */ + return ((struct x_phys_cpu *)hdr)->ctidx; +} + +/* Diagnose 204 functions */ + +static int diag204(unsigned long subcode, unsigned long size, void *addr) +{ + register unsigned long _subcode asm("0") = subcode; + register unsigned long _size asm("1") = size; + + asm volatile (" diag %2,%0,0x204\n" + "0: \n" ".section __ex_table,\"a\"\n" +#ifndef __s390x__ + " .align 4\n" + " .long 0b,0b\n" +#else + " .align 8\n" + " .quad 0b,0b\n" +#endif + ".previous":"+d" (_subcode), "+d"(_size) + :"d"(addr) + :"memory"); + if (_subcode) + return -1; + else + return _size; +} + +/* + * For the old diag subcode 4 with simple data format we have to use real + * memory. If we use subcode 6 or 7 with extended data format, we can (and + * should) use vmalloc, since we need a lot of memory in that case. Currently + * up to 93 pages! + */ + +static void diag204_free_buffer(void) +{ + if (!diag204_buf) + return; + if (diag204_buf_vmalloc) { + vfree(diag204_buf_vmalloc); + diag204_buf_vmalloc = NULL; + } else { + free_pages((unsigned long) diag204_buf, 0); + } + diag204_buf_pages = 0; + diag204_buf = NULL; +} + +static void *diag204_alloc_vbuf(int pages) +{ + /* The buffer has to be page aligned! */ + diag204_buf_vmalloc = vmalloc(PAGE_SIZE * (pages + 1)); + if (!diag204_buf_vmalloc) + return ERR_PTR(-ENOMEM); + diag204_buf = (void*)((unsigned long)diag204_buf_vmalloc + & ~0xfffUL) + 0x1000; + diag204_buf_pages = pages; + return diag204_buf; +} + +static void *diag204_alloc_rbuf(void) +{ + diag204_buf = (void*)__get_free_pages(GFP_KERNEL,0); + if (diag204_buf) + return ERR_PTR(-ENOMEM); + diag204_buf_pages = 1; + return diag204_buf; +} + +static void *diag204_get_buffer(enum diag204_format fmt, int *pages) +{ + if (diag204_buf) { + *pages = diag204_buf_pages; + return diag204_buf; + } + if (fmt == INFO_SIMPLE) { + *pages = 1; + return diag204_alloc_rbuf(); + } else {/* INFO_EXT */ + *pages = diag204(SUBC_RSI | INFO_EXT, 0, 0); + if (*pages <= 0) + return ERR_PTR(-ENOSYS); + else + return diag204_alloc_vbuf(*pages); + } +} + +/* + * diag204_probe() has to find out, which type of diagnose 204 implementation + * we have on our machine. Currently there are three possible scanarios: + * - subcode 4 + simple data format (only one page) + * - subcode 4-6 + extended data format + * - subcode 4-7 + extended data format + * + * Subcode 5 is used to retrieve the size of the data, provided by subcodes + * 6 and 7. Subcode 7 basically has the same function as subcode 6. In addition + * to subcode 6 it provides also information about secondary cpus. + * In order to get as much information as possible, we first try + * subcode 7, then 6 and if both fail, we use subcode 4. + */ + +static int diag204_probe(void) +{ + void *buf; + int pages, rc; + + buf = diag204_get_buffer(INFO_EXT, &pages); + if (!IS_ERR(buf)) { + if (diag204(SUBC_STIB7 | INFO_EXT, pages, buf) >= 0) { + diag204_store_sc = SUBC_STIB7; + diag204_info_type = INFO_EXT; + goto out; + } + if (diag204(SUBC_STIB6 | INFO_EXT, pages, buf) >= 0) { + diag204_store_sc = SUBC_STIB7; + diag204_info_type = INFO_EXT; + goto out; + } + diag204_free_buffer(); + } + + /* subcodes 6 and 7 failed, now try subcode 4 */ + + buf = diag204_get_buffer(INFO_SIMPLE, &pages); + if (IS_ERR(buf)) { + rc = PTR_ERR(buf); + goto fail_alloc; + } + if (diag204(SUBC_STIB4 | INFO_SIMPLE, pages, buf) >= 0) { + diag204_store_sc = SUBC_STIB4; + diag204_info_type = INFO_SIMPLE; + goto out; + } else { + rc = -ENOSYS; + goto fail_store; + } +out: + rc = 0; +fail_store: + diag204_free_buffer(); +fail_alloc: + return rc; +} + +static void *diag204_store(void) +{ + void *buf; + int pages; + + buf = diag204_get_buffer(diag204_info_type, &pages); + if (IS_ERR(buf)) + goto out; + if (diag204(diag204_store_sc | diag204_info_type, pages, buf) < 0) + return ERR_PTR(-ENOSYS); +out: + return buf; +} + +/* Diagnose 224 functions */ + +static void diag224(void *ptr) +{ + asm volatile(" diag %0,%1,0x224\n" + : :"d" (0), "d"(ptr) : "memory"); +} + +static int diag224_get_name_table(void) +{ + /* memory must be below 2GB */ + diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA); + if (!diag224_cpu_names) + return -ENOMEM; + diag224(diag224_cpu_names); + EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16); + return 0; +} + +static void diag224_delete_name_table(void) +{ + kfree(diag224_cpu_names); +} + +static int diag224_idx2name(int index, char *name) +{ + memcpy(name, diag224_cpu_names + ((index + 1) * CPU_NAME_LEN), + CPU_NAME_LEN); + name[CPU_NAME_LEN] = 0; + strstrip(name); + return 0; +} + +__init int hypfs_diag_init(void) +{ + int rc; + + if (diag204_probe()) { + printk(KERN_ERR "hypfs: diag 204 not working."); + return -ENODATA; + } + rc = diag224_get_name_table(); + if (rc) { + diag224_delete_name_table(); + printk(KERN_ERR "hypfs: could not get name table.\n"); + } + return rc; +} + +__exit void hypfs_diag_exit(void) +{ + diag224_delete_name_table(); + diag204_free_buffer(); +} + +/* + * Functions to create the directory structure + * ******************************************* + */ + +static int hypfs_create_cpu_files(struct super_block *sb, + struct dentry *cpus_dir, void *cpu_info) +{ + struct dentry *cpu_dir; + char buffer[TMP_SIZE]; + void *rc; + + snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_info_type, + cpu_info)); + cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer); + rc = hypfs_create_u64(sb, cpu_dir, "mgmtime", + cpu_info__acc_time(diag204_info_type, cpu_info) - + cpu_info__lp_time(diag204_info_type, cpu_info)); + if (IS_ERR(rc)) + return PTR_ERR(rc); + rc = hypfs_create_u64(sb, cpu_dir, "cputime", + cpu_info__lp_time(diag204_info_type, cpu_info)); + if (IS_ERR(rc)) + return PTR_ERR(rc); + if (diag204_info_type == INFO_EXT) { + rc = hypfs_create_u64(sb, cpu_dir, "onlinetime", + cpu_info__online_time(diag204_info_type, + cpu_info)); + if (IS_ERR(rc)) + return PTR_ERR(rc); + } + diag224_idx2name(cpu_info__ctidx(diag204_info_type, cpu_info), buffer); + rc = hypfs_create_str(sb, cpu_dir, "type", buffer); + if (IS_ERR(rc)) + return PTR_ERR(rc); + return 0; +} + +static void *hypfs_create_lpar_files(struct super_block *sb, + struct dentry *systems_dir, void *part_hdr) +{ + struct dentry *cpus_dir; + struct dentry *lpar_dir; + char lpar_name[LPAR_NAME_LEN + 1]; + void *cpu_info; + int i; + + part_hdr__part_name(diag204_info_type, part_hdr, lpar_name); + lpar_name[LPAR_NAME_LEN] = 0; + lpar_dir = hypfs_mkdir(sb, systems_dir, lpar_name); + if (IS_ERR(lpar_dir)) + return lpar_dir; + cpus_dir = hypfs_mkdir(sb, lpar_dir, "cpus"); + if (IS_ERR(cpus_dir)) + return cpus_dir; + cpu_info = part_hdr + part_hdr__size(diag204_info_type); + for (i = 0; i < part_hdr__rcpus(diag204_info_type, part_hdr); i++) { + int rc; + rc = hypfs_create_cpu_files(sb, cpus_dir, cpu_info); + if (rc) + return ERR_PTR(rc); + cpu_info += cpu_info__size(diag204_info_type); + } + return cpu_info; +} + +static int hypfs_create_phys_cpu_files(struct super_block *sb, + struct dentry *cpus_dir, void *cpu_info) +{ + struct dentry *cpu_dir; + char buffer[TMP_SIZE]; + void *rc; + + snprintf(buffer, TMP_SIZE, "%i", phys_cpu__cpu_addr(diag204_info_type, + cpu_info)); + cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer); + if (IS_ERR(cpu_dir)) + return PTR_ERR(cpu_dir); + rc = hypfs_create_u64(sb, cpu_dir, "mgmtime", + phys_cpu__mgm_time(diag204_info_type, cpu_info)); + if (IS_ERR(rc)) + return PTR_ERR(rc); + diag224_idx2name(phys_cpu__ctidx(diag204_info_type, cpu_info), buffer); + rc = hypfs_create_str(sb, cpu_dir, "type", buffer); + if (IS_ERR(rc)) + return PTR_ERR(rc); + return 0; +} + +static void *hypfs_create_phys_files(struct super_block *sb, + struct dentry *parent_dir, void *phys_hdr) +{ + int i; + void *cpu_info; + struct dentry *cpus_dir; + + cpus_dir = hypfs_mkdir(sb, parent_dir, "cpus"); + if (IS_ERR(cpus_dir)) + return cpus_dir; + cpu_info = phys_hdr + phys_hdr__size(diag204_info_type); + for (i = 0; i < phys_hdr__cpus(diag204_info_type, phys_hdr); i++) { + int rc; + rc = hypfs_create_phys_cpu_files(sb, cpus_dir, cpu_info); + if (rc) + return ERR_PTR(rc); + cpu_info += phys_cpu__size(diag204_info_type); + } + return cpu_info; +} + +int hypfs_diag_create_files(struct super_block *sb, struct dentry *root) +{ + struct dentry *systems_dir, *hyp_dir; + void *time_hdr, *part_hdr; + int i, rc; + void *buffer, *ptr; + + buffer = diag204_store(); + if (IS_ERR(buffer)) + return PTR_ERR(buffer); + + systems_dir = hypfs_mkdir(sb, root, "systems"); + if (IS_ERR(systems_dir)) { + rc = PTR_ERR(systems_dir); + goto err_out; + } + time_hdr = (struct x_info_blk_hdr *)buffer; + part_hdr = time_hdr + info_blk_hdr__size(diag204_info_type); + for (i = 0; i < info_blk_hdr__npar(diag204_info_type, time_hdr); i++) { + part_hdr = hypfs_create_lpar_files(sb, systems_dir, part_hdr); + if (IS_ERR(part_hdr)) { + rc = PTR_ERR(part_hdr); + goto err_out; + } + } + if (info_blk_hdr__flags(diag204_info_type, time_hdr) & LPAR_PHYS_FLG) { + ptr = hypfs_create_phys_files(sb, root, part_hdr); + if (IS_ERR(ptr)) { + rc = PTR_ERR(ptr); + goto err_out; + } + } + hyp_dir = hypfs_mkdir(sb, root, "hyp"); + if (IS_ERR(hyp_dir)) { + rc = PTR_ERR(hyp_dir); + goto err_out; + } + ptr = hypfs_create_str(sb, hyp_dir, "type", "LPAR Hypervisor"); + if (IS_ERR(ptr)) { + rc = PTR_ERR(ptr); + goto err_out; + } + rc = 0; + +err_out: + return rc; +} diff --git a/arch/s390/hypfs/hypfs_diag.h b/arch/s390/hypfs/hypfs_diag.h new file mode 100644 index 0000000..793dea6 --- /dev/null +++ b/arch/s390/hypfs/hypfs_diag.h @@ -0,0 +1,16 @@ +/* + * fs/hypfs/hypfs_diag.h + * Hypervisor filesystem for Linux on s390. + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Michael Holzheu + */ + +#ifndef _HYPFS_DIAG_H_ +#define _HYPFS_DIAG_H_ + +extern int hypfs_diag_init(void); +extern void hypfs_diag_exit(void); +extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root); + +#endif /* _HYPFS_DIAG_H_ */ diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c new file mode 100644 index 0000000..18c0919 --- /dev/null +++ b/arch/s390/hypfs/inode.c @@ -0,0 +1,491 @@ +/* + * fs/hypfs/inode.c + * Hypervisor filesystem for Linux on s390. + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Michael Holzheu + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hypfs.h" +#include "hypfs_diag.h" + +#define HYPFS_MAGIC 0x687970 /* ASCII 'hyp' */ +#define TMP_SIZE 64 /* size of temporary buffers */ + +static struct dentry *hypfs_create_update_file(struct super_block *sb, + struct dentry *dir); + +struct hypfs_sb_info { + uid_t uid; /* uid used for files and dirs */ + gid_t gid; /* gid used for files and dirs */ + struct dentry *update_file; /* file to trigger update */ + time_t last_update; /* last update time in secs since 1970 */ + struct mutex lock; /* lock to protect update process */ +}; + +static struct file_operations hypfs_file_ops; +static struct file_system_type hypfs_type; +static struct super_operations hypfs_s_ops; + +/* start of list of all dentries, which have to be deleted on update */ +static struct dentry *hypfs_last_dentry; + +static void hypfs_update_update(struct super_block *sb) +{ + struct hypfs_sb_info *sb_info = sb->s_fs_info; + struct inode *inode = sb_info->update_file->d_inode; + + sb_info->last_update = get_seconds(); + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; +} + +/* directory tree removal functions */ + +static void hypfs_add_dentry(struct dentry *dentry) +{ + dentry->d_fsdata = hypfs_last_dentry; + hypfs_last_dentry = dentry; +} + +static void hypfs_remove(struct dentry *dentry) +{ + struct dentry *parent; + + parent = dentry->d_parent; + if (S_ISDIR(dentry->d_inode->i_mode)) + simple_rmdir(parent->d_inode, dentry); + else + simple_unlink(parent->d_inode, dentry); + d_delete(dentry); + dput(dentry); +} + +static void hypfs_delete_tree(struct dentry *root) +{ + while (hypfs_last_dentry) { + struct dentry *next_dentry; + next_dentry = hypfs_last_dentry->d_fsdata; + hypfs_remove(hypfs_last_dentry); + hypfs_last_dentry = next_dentry; + } +} + +static struct inode *hypfs_make_inode(struct super_block *sb, int mode) +{ + struct inode *ret = new_inode(sb); + + if (ret) { + struct hypfs_sb_info *hypfs_info = sb->s_fs_info; + ret->i_mode = mode; + ret->i_uid = hypfs_info->uid; + ret->i_gid = hypfs_info->gid; + ret->i_blksize = PAGE_CACHE_SIZE; + ret->i_blocks = 0; + ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; + if (mode & S_IFDIR) + ret->i_nlink = 2; + else + ret->i_nlink = 1; + } + return ret; +} + +static void hypfs_drop_inode(struct inode *inode) +{ + kfree(inode->u.generic_ip); + generic_delete_inode(inode); +} + +static int hypfs_open(struct inode *inode, struct file *filp) +{ + char *data = filp->f_dentry->d_inode->u.generic_ip; + struct hypfs_sb_info *fs_info; + + if (filp->f_mode & FMODE_WRITE) { + if (!(inode->i_mode & S_IWUGO)) + return -EACCES; + } + if (filp->f_mode & FMODE_READ) { + if (!(inode->i_mode & S_IRUGO)) + return -EACCES; + } + + fs_info = inode->i_sb->s_fs_info; + if(data) { + mutex_lock(&fs_info->lock); + filp->private_data = kstrdup(data, GFP_KERNEL); + if (!filp->private_data) { + mutex_unlock(&fs_info->lock); + return -ENOMEM; + } + mutex_unlock(&fs_info->lock); + } + return 0; +} + +static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf, + size_t count, loff_t offset) +{ + char *data; + size_t len; + struct file *filp = iocb->ki_filp; + + data = filp->private_data; + len = strlen(data); + if (offset > len) { + count = 0; + goto out; + } + if (count > len - offset) + count = len - offset; + if (copy_to_user(buf, data + offset, count)) { + count = -EFAULT; + goto out; + } + iocb->ki_pos += count; + file_accessed(filp); +out: + return count; +} +static ssize_t hypfs_aio_write(struct kiocb *iocb, const char __user *buf, + size_t count, loff_t pos) +{ + int rc; + struct super_block *sb; + struct hypfs_sb_info *fs_info; + + sb = iocb->ki_filp->f_dentry->d_inode->i_sb; + fs_info = sb->s_fs_info; + /* + * Currently we only allow one update per second for two reasons: + * 1. diag 204 is VERY expensive + * 2. If several processes do updates in parallel and then read the + * hypfs data, the likelihood of collisions is reduced, if we restrict + * the minimum update interval. A collision occurs, if during the + * data gathering of one process another process triggers an update + * If the first process wants to ensure consistent data, it has + * to restart data collection in this case. + */ + mutex_lock(&fs_info->lock); + if (fs_info->last_update == get_seconds()) { + rc = -EBUSY; + goto out; + } + hypfs_delete_tree(sb->s_root); + rc = hypfs_diag_create_files(sb, sb->s_root); + if (rc) { + printk(KERN_ERR "hypfs: Update failed\n"); + hypfs_delete_tree(sb->s_root); + goto out; + } + hypfs_update_update(sb); + rc = count; +out: + mutex_unlock(&fs_info->lock); + return rc; +} + +static int hypfs_release(struct inode *inode, struct file *filp) +{ + kfree(filp->private_data); + return 0; +} + +enum { opt_uid, opt_gid, opt_err }; + +static match_table_t hypfs_tokens = { + {opt_uid, "uid=%u"}, + {opt_gid, "gid=%u"}, + {opt_err, NULL} +}; + +static int hypfs_parse_options(char *options, struct super_block *sb) +{ + char *str; + substring_t args[MAX_OPT_ARGS]; + + if (!options) + return 0; + while ((str = strsep(&options, ",")) != NULL) { + int token, option; + struct hypfs_sb_info *hypfs_info = sb->s_fs_info; + + if (!*str) + continue; + token = match_token(str, hypfs_tokens, args); + switch (token) { + case opt_uid: + if (match_int(&args[0], &option)) + return -EINVAL; + hypfs_info->uid = option; + break; + case opt_gid: + if (match_int(&args[0], &option)) + return -EINVAL; + hypfs_info->gid = option; + break; + case opt_err: + default: + printk(KERN_ERR "hypfs: Unrecognized mount option " + "\"%s\" or missing value\n", str); + return -EINVAL; + } + } + return 0; +} + +static int hypfs_fill_super(struct super_block *sb, void *data, int silent) +{ + struct inode *root_inode; + struct dentry *root_dentry; + int rc = 0; + struct hypfs_sb_info *sbi; + + sbi = kzalloc(sizeof(struct hypfs_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; + mutex_init(&sbi->lock); + sbi->uid = current->uid; + sbi->gid = current->gid; + sb->s_fs_info = sbi; + sb->s_blocksize = PAGE_CACHE_SIZE; + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; + sb->s_magic = HYPFS_MAGIC; + sb->s_op = &hypfs_s_ops; + if (hypfs_parse_options(data, sb)) { + rc = -EINVAL; + goto err_alloc; + } + root_inode = hypfs_make_inode(sb, S_IFDIR | 0755); + if (!root_inode) { + rc = -ENOMEM; + goto err_alloc; + } + root_inode->i_op = &simple_dir_inode_operations; + root_inode->i_fop = &simple_dir_operations; + root_dentry = d_alloc_root(root_inode); + if (!root_dentry) { + iput(root_inode); + rc = -ENOMEM; + goto err_alloc; + } + rc = hypfs_diag_create_files(sb, root_dentry); + if (rc) + goto err_tree; + sbi->update_file = hypfs_create_update_file(sb, root_dentry); + if (IS_ERR(sbi->update_file)) { + rc = PTR_ERR(sbi->update_file); + goto err_tree; + } + hypfs_update_update(sb); + sb->s_root = root_dentry; + return 0; + +err_tree: + hypfs_delete_tree(root_dentry); + d_genocide(root_dentry); + dput(root_dentry); +err_alloc: + kfree(sbi); + return rc; +} + +static int hypfs_get_super(struct file_system_type *fst, int flags, + const char *devname, void *data, struct vfsmount *mnt) +{ + return get_sb_single(fst, flags, data, hypfs_fill_super, mnt); +} + +static void hypfs_kill_super(struct super_block *sb) +{ + struct hypfs_sb_info *sb_info = sb->s_fs_info; + + hypfs_delete_tree(sb->s_root); + hypfs_remove(sb_info->update_file); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + kill_litter_super(sb); +} + +static struct dentry *hypfs_create_file(struct super_block *sb, + struct dentry *parent, const char *name, + char *data, mode_t mode) +{ + struct dentry *dentry; + struct inode *inode; + struct qstr qname; + + qname.name = name; + qname.len = strlen(name); + qname.hash = full_name_hash(name, qname.len); + dentry = lookup_one_len(name, parent, strlen(name)); + if (IS_ERR(dentry)) + return ERR_PTR(-ENOMEM); + inode = hypfs_make_inode(sb, mode); + if (!inode) { + dput(dentry); + return ERR_PTR(-ENOMEM); + } + if (mode & S_IFREG) { + inode->i_fop = &hypfs_file_ops; + if (data) + inode->i_size = strlen(data); + else + inode->i_size = 0; + } else if (mode & S_IFDIR) { + inode->i_op = &simple_dir_inode_operations; + inode->i_fop = &simple_dir_operations; + parent->d_inode->i_nlink++; + } else + BUG(); + inode->u.generic_ip = data; + d_instantiate(dentry, inode); + dget(dentry); + return dentry; +} + +struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent, + const char *name) +{ + struct dentry *dentry; + + dentry = hypfs_create_file(sb, parent, name, NULL, S_IFDIR | DIR_MODE); + if (IS_ERR(dentry)) + return dentry; + hypfs_add_dentry(dentry); + parent->d_inode->i_nlink++; + return dentry; +} + +static struct dentry *hypfs_create_update_file(struct super_block *sb, + struct dentry *dir) +{ + struct dentry *dentry; + + dentry = hypfs_create_file(sb, dir, "update", NULL, + S_IFREG | UPDATE_FILE_MODE); + /* + * We do not put the update file on the 'delete' list with + * hypfs_add_dentry(), since it should not be removed when the tree + * is updated. + */ + return dentry; +} + +struct dentry *hypfs_create_u64(struct super_block *sb, struct dentry *dir, + const char *name, __u64 value) +{ + char *buffer; + char tmp[TMP_SIZE]; + struct dentry *dentry; + + snprintf(tmp, TMP_SIZE, "%lld\n", (unsigned long long int)value); + buffer = kstrdup(tmp, GFP_KERNEL); + if (!buffer) + return ERR_PTR(-ENOMEM); + dentry = + hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE); + if (IS_ERR(dentry)) { + kfree(buffer); + return ERR_PTR(-ENOMEM); + } + hypfs_add_dentry(dentry); + return dentry; +} + +struct dentry *hypfs_create_str(struct super_block *sb, struct dentry *dir, + const char *name, char *string) +{ + char *buffer; + struct dentry *dentry; + + buffer = kmalloc(strlen(string) + 2, GFP_KERNEL); + if (!buffer) + return ERR_PTR(-ENOMEM); + sprintf(buffer, "%s\n", string); + dentry = + hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE); + if (IS_ERR(dentry)) { + kfree(buffer); + return ERR_PTR(-ENOMEM); + } + hypfs_add_dentry(dentry); + return dentry; +} + +static struct file_operations hypfs_file_ops = { + .open = hypfs_open, + .release = hypfs_release, + .read = do_sync_read, + .write = do_sync_write, + .aio_read = hypfs_aio_read, + .aio_write = hypfs_aio_write, +}; + +static struct file_system_type hypfs_type = { + .owner = THIS_MODULE, + .name = "s390_hypfs", + .get_sb = hypfs_get_super, + .kill_sb = hypfs_kill_super +}; + +static struct super_operations hypfs_s_ops = { + .statfs = simple_statfs, + .drop_inode = hypfs_drop_inode, +}; + +static decl_subsys(s390, NULL, NULL); + +static int __init hypfs_init(void) +{ + int rc; + + if (MACHINE_IS_VM) + return -ENODATA; + if (hypfs_diag_init()) { + rc = -ENODATA; + goto fail_diag; + } + kset_set_kset_s(&s390_subsys, hypervisor_subsys); + rc = subsystem_register(&s390_subsys); + if (rc) + goto fail_sysfs; + rc = register_filesystem(&hypfs_type); + if (rc) + goto fail_filesystem; + return 0; + +fail_filesystem: + subsystem_unregister(&s390_subsys); +fail_sysfs: + hypfs_diag_exit(); +fail_diag: + printk(KERN_ERR "hypfs: Initialization failed with rc = %i.\n", rc); + return rc; +} + +static void __exit hypfs_exit(void) +{ + hypfs_diag_exit(); + unregister_filesystem(&hypfs_type); + subsystem_unregister(&s390_subsys); +} + +module_init(hypfs_init) +module_exit(hypfs_exit) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Michael Holzheu "); +MODULE_DESCRIPTION("s390 Hypervisor Filesystem"); diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index bad81b5..fbde6a9 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -27,8 +27,8 @@ static void kexec_halt_all_cpus(void *); typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long); -const extern unsigned char relocate_kernel[]; -const extern unsigned long long relocate_kernel_len; +extern const unsigned char relocate_kernel[]; +extern const unsigned long long relocate_kernel_len; int machine_kexec_prepare(struct kimage *image) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 0a04e4a..b282034 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -47,6 +47,7 @@ #include #include #include #include +#include /* * Machine setup.. @@ -66,11 +67,6 @@ unsigned long __initdata zholes_size[MAX static unsigned long __initdata memory_end; /* - * Setup options - */ -extern int _text,_etext, _edata, _end; - -/* * This is set up by the setup-routine at boot-time * for S390 need to find out, what we have to setup * using address 0x10400 ... @@ -80,15 +76,11 @@ #include static struct resource code_resource = { .name = "Kernel code", - .start = (unsigned long) &_text, - .end = (unsigned long) &_etext - 1, .flags = IORESOURCE_BUSY | IORESOURCE_MEM, }; static struct resource data_resource = { .name = "Kernel data", - .start = (unsigned long) &_etext, - .end = (unsigned long) &_edata - 1, .flags = IORESOURCE_BUSY | IORESOURCE_MEM, }; @@ -422,6 +414,11 @@ setup_resources(void) struct resource *res; int i; + code_resource.start = (unsigned long) &_text; + code_resource.end = (unsigned long) &_etext - 1; + data_resource.start = (unsigned long) &_etext; + data_resource.end = (unsigned long) &_edata - 1; + for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { res = alloc_bootmem_low(sizeof(struct resource)); res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index dfe6f08..1f0439d 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -356,7 +356,7 @@ static void internal_add_vtimer(struct v set_vtimer(event->expires); spin_unlock_irqrestore(&vt_list->lock, flags); - /* release CPU aquired in prepare_vtimer or mod_virt_timer() */ + /* release CPU acquired in prepare_vtimer or mod_virt_timer() */ put_cpu(); } diff --git a/arch/sh/Makefile b/arch/sh/Makefile index c72e17a..e467a45 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -147,7 +147,7 @@ # Update machine arch and proc symlinks # them changed. We use .arch and .mach to indicate when they were # updated last, otherwise make uses the target directory mtime. -include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/MARKER +include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/auto.conf @echo ' SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)' $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi $(Q)ln -fsn $(incdir-prefix)$(cpuincdir-y) include/asm-sh/cpu @@ -157,7 +157,7 @@ # Most boards have their own mach direct # don't, just reference the parent directory so the semantics are # kept roughly the same. -include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/MARKER +include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/auto.conf @echo -n ' SYMLINK include/asm-sh/mach -> ' $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi $(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \ diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index 4354652..6bcd8d9 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -25,8 +25,8 @@ typedef NORET_TYPE void (*relocate_new_k unsigned long start_address, unsigned long vbr_reg) ATTRIB_NORET; -const extern unsigned char relocate_new_kernel[]; -const extern unsigned int relocate_new_kernel_size; +extern const unsigned char relocate_new_kernel[]; +extern const unsigned int relocate_new_kernel_size; extern void *gdb_vbr_vector; /* diff --git a/arch/sh/oprofile/op_model_sh7750.c b/arch/sh/oprofile/op_model_sh7750.c index 5ec9ddc..c265185 100644 --- a/arch/sh/oprofile/op_model_sh7750.c +++ b/arch/sh/oprofile/op_model_sh7750.c @@ -198,7 +198,7 @@ static int sh7750_perf_counter_create_fi for (i = 0; i < NR_CNTRS; i++) { struct dentry *dir; - char buf[3]; + char buf[4]; snprintf(buf, sizeof(buf), "%d", i); dir = oprofilefs_mkdir(sb, root, buf); diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c index 3ea8929..9e2ffc4 100644 --- a/arch/sh64/kernel/signal.c +++ b/arch/sh64/kernel/signal.c @@ -407,7 +407,7 @@ #undef COPY static inline void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) { - if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; return (void __user *)((sp - frame_size) & -8ul); diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 1b83e21..6616ee0 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -12,7 +12,7 @@ obj-y := entry.o wof.o wuf.o etrap.o sys_sparc.o sunos_asm.o systbls.o \ time.o windows.o cpu.o devices.o sclow.o \ tadpole.o tick14.o ptrace.o sys_solaris.o \ - unaligned.o muldiv.o semaphore.o + unaligned.o muldiv.o semaphore.o prom.o of_device.o obj-$(CONFIG_PCI) += pcic.o obj-$(CONFIG_SUN4) += sun4setup.o diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index 5c3529c..a7a4892 100644 --- a/arch/sparc/kernel/ebus.c +++ b/arch/sparc/kernel/ebus.c @@ -20,6 +20,7 @@ #include #include #include #include +#include #include struct linux_ebus *ebus_chain = NULL; @@ -83,79 +84,81 @@ int __init ebus_blacklist_irq(char *name return 0; } -void __init fill_ebus_child(int node, struct linux_prom_registers *preg, - struct linux_ebus_child *dev) +void __init fill_ebus_child(struct device_node *dp, + struct linux_ebus_child *dev) { - int regs[PROMREG_MAX]; - int irqs[PROMREG_MAX]; - char lbuf[128]; + int *regs; + int *irqs; int i, len; - dev->prom_node = node; - prom_getstring(node, "name", lbuf, sizeof(lbuf)); - strcpy(dev->prom_name, lbuf); - - len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); - if (len == -1) len = 0; + dev->prom_node = dp; + regs = of_get_property(dp, "reg", &len); + if (!regs) + len = 0; dev->num_addrs = len / sizeof(regs[0]); for (i = 0; i < dev->num_addrs; i++) { if (regs[i] >= dev->parent->num_addrs) { prom_printf("UGH: property for %s was %d, need < %d\n", - dev->prom_name, len, dev->parent->num_addrs); + dev->prom_node->name, len, + dev->parent->num_addrs); panic(__FUNCTION__); } - dev->resource[i].start = dev->parent->resource[regs[i]].start; /* XXX resource */ + + /* XXX resource */ + dev->resource[i].start = + dev->parent->resource[regs[i]].start; } for (i = 0; i < PROMINTR_MAX; i++) dev->irqs[i] = PCI_IRQ_NONE; - if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) { + if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) { dev->num_irqs = 1; - } else if ((len = prom_getproperty(node, "interrupts", - (char *)&irqs, sizeof(irqs))) == -1 || len == 0) { - dev->num_irqs = 0; - dev->irqs[0] = 0; - if (dev->parent->num_irqs != 0) { - dev->num_irqs = 1; - dev->irqs[0] = dev->parent->irqs[0]; -/* P3 */ /* printk("EBUS: dev %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */ - } } else { - dev->num_irqs = len / sizeof(irqs[0]); - if (irqs[0] == 0 || irqs[0] >= 8) { - /* - * XXX Zero is a valid pin number... - * This works as long as Ebus is not wired to INTA#. - */ - printk("EBUS: %s got bad irq %d from PROM\n", - dev->prom_name, irqs[0]); + irqs = of_get_property(dp, "interrupts", &len); + if (!irqs) { dev->num_irqs = 0; dev->irqs[0] = 0; + if (dev->parent->num_irqs != 0) { + dev->num_irqs = 1; + dev->irqs[0] = dev->parent->irqs[0]; + } } else { - dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name); + dev->num_irqs = len / sizeof(irqs[0]); + if (irqs[0] == 0 || irqs[0] >= 8) { + /* + * XXX Zero is a valid pin number... + * This works as long as Ebus is not wired + * to INTA#. + */ + printk("EBUS: %s got bad irq %d from PROM\n", + dev->prom_node->name, irqs[0]); + dev->num_irqs = 0; + dev->irqs[0] = 0; + } else { + dev->irqs[0] = + pcic_pin_to_irq(irqs[0], + dev->prom_node->name); + } } } } -void __init fill_ebus_device(int node, struct linux_ebus_device *dev) +void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) { - struct linux_prom_registers regs[PROMREG_MAX]; + struct linux_prom_registers *regs; struct linux_ebus_child *child; - int irqs[PROMINTR_MAX]; - char lbuf[128]; + int *irqs; int i, n, len; unsigned long baseaddr; - dev->prom_node = node; - prom_getstring(node, "name", lbuf, sizeof(lbuf)); - strcpy(dev->prom_name, lbuf); + dev->prom_node = dp; - len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); + regs = of_get_property(dp, "reg", &len); if (len % sizeof(struct linux_prom_registers)) { prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", - dev->prom_name, len, + dev->prom_node->name, len, (int)sizeof(struct linux_prom_registers)); panic(__FUNCTION__); } @@ -197,7 +200,7 @@ void __init fill_ebus_device(int node, s if ((baseaddr = (unsigned long) ioremap(baseaddr, regs[i].reg_size)) == 0) { panic("ebus: unable to remap dev %s", - dev->prom_name); + dev->prom_node->name); } } dev->resource[i].start = baseaddr; /* XXX Unaligned */ @@ -206,29 +209,43 @@ void __init fill_ebus_device(int node, s for (i = 0; i < PROMINTR_MAX; i++) dev->irqs[i] = PCI_IRQ_NONE; - if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) { + if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) { dev->num_irqs = 1; - } else if ((len = prom_getproperty(node, "interrupts", - (char *)&irqs, sizeof(irqs))) == -1 || len == 0) { - dev->num_irqs = 0; - if ((dev->irqs[0] = dev->bus->self->irq) != 0) { - dev->num_irqs = 1; -/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */ - } } else { - dev->num_irqs = 1; /* dev->num_irqs = len / sizeof(irqs[0]); */ - if (irqs[0] == 0 || irqs[0] >= 8) { - /* See above for the parent. XXX */ - printk("EBUS: %s got bad irq %d from PROM\n", - dev->prom_name, irqs[0]); + irqs = of_get_property(dp, "interrupts", &len); + if (!irqs) { dev->num_irqs = 0; - dev->irqs[0] = 0; + if ((dev->irqs[0] = dev->bus->self->irq) != 0) { + dev->num_irqs = 1; +/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */ + } } else { - dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name); + dev->num_irqs = 1; /* dev->num_irqs = len / sizeof(irqs[0]); */ + if (irqs[0] == 0 || irqs[0] >= 8) { + /* See above for the parent. XXX */ + printk("EBUS: %s got bad irq %d from PROM\n", + dev->prom_node->name, irqs[0]); + dev->num_irqs = 0; + dev->irqs[0] = 0; + } else { + dev->irqs[0] = + pcic_pin_to_irq(irqs[0], + dev->prom_node->name); + } } } - if ((node = prom_getchild(node))) { + dev->ofdev.node = dp; + dev->ofdev.dev.parent = &dev->bus->ofdev.dev; + dev->ofdev.dev.bus = &ebus_bus_type; + strcpy(dev->ofdev.dev.bus_id, dp->path_component_name); + + /* Register with core */ + if (of_device_register(&dev->ofdev) != 0) + printk(KERN_DEBUG "ebus: device registration error for %s!\n", + dev->ofdev.dev.bus_id); + + if ((dp = dp->child) != NULL) { dev->children = (struct linux_ebus_child *) ebus_alloc(sizeof(struct linux_ebus_child)); @@ -236,9 +253,9 @@ void __init fill_ebus_device(int node, s child->next = NULL; child->parent = dev; child->bus = dev->bus; - fill_ebus_child(node, ®s[0], child); + fill_ebus_child(dp, child); - while ((node = prom_getsibling(node)) != 0) { + while ((dp = dp->sibling) != NULL) { child->next = (struct linux_ebus_child *) ebus_alloc(sizeof(struct linux_ebus_child)); @@ -246,51 +263,49 @@ void __init fill_ebus_device(int node, s child->next = NULL; child->parent = dev; child->bus = dev->bus; - fill_ebus_child(node, ®s[0], child); + fill_ebus_child(dp, child); } } } void __init ebus_init(void) { - struct linux_prom_pci_registers regs[PROMREG_MAX]; + struct linux_prom_pci_registers *regs; struct linux_pbm_info *pbm; struct linux_ebus_device *dev; struct linux_ebus *ebus; struct ebus_system_entry *sp; struct pci_dev *pdev; struct pcidev_cookie *cookie; - char lbuf[128]; + struct device_node *dp; unsigned long addr, *base; unsigned short pci_command; - int nd, len, ebusnd; - int reg, nreg; + int len, reg, nreg; int num_ebus = 0; - prom_getstring(prom_root_node, "name", lbuf, sizeof(lbuf)); + dp = of_find_node_by_path("/"); for (sp = ebus_blacklist; sp->esname != NULL; sp++) { - if (strcmp(lbuf, sp->esname) == 0) { + if (strcmp(dp->name, sp->esname) == 0) { ebus_blackp = sp->ipt; break; } } pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL); - if (!pdev) { + if (!pdev) return; - } + cookie = pdev->sysdata; - ebusnd = cookie->prom_node; + dp = cookie->prom_node; ebus_chain = ebus = (struct linux_ebus *) ebus_alloc(sizeof(struct linux_ebus)); ebus->next = NULL; - while (ebusnd) { + while (dp) { + struct device_node *nd; - prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf)); - ebus->prom_node = ebusnd; - strcpy(ebus->prom_name, lbuf); + ebus->prom_node = dp; ebus->self = pdev; ebus->parent = pbm = cookie->pbm; @@ -299,9 +314,8 @@ void __init ebus_init(void) pci_command |= PCI_COMMAND_MASTER; pci_write_config_word(pdev, PCI_COMMAND, pci_command); - len = prom_getproperty(ebusnd, "reg", (void *)regs, - sizeof(regs)); - if (len == 0 || len == -1) { + regs = of_get_property(dp, "reg", &len); + if (!regs) { prom_printf("%s: can't find reg property\n", __FUNCTION__); prom_halt(); @@ -317,7 +331,18 @@ void __init ebus_init(void) *base++ = addr; } - nd = prom_getchild(ebusnd); + ebus->ofdev.node = dp; + ebus->ofdev.dev.parent = &pdev->dev; + ebus->ofdev.dev.bus = &ebus_bus_type; + strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name); + + /* Register with core */ + if (of_device_register(&ebus->ofdev) != 0) + printk(KERN_DEBUG "ebus: device registration error for %s!\n", + ebus->ofdev.dev.bus_id); + + + nd = dp->child; if (!nd) goto next_ebus; @@ -330,7 +355,7 @@ void __init ebus_init(void) dev->bus = ebus; fill_ebus_device(nd, dev); - while ((nd = prom_getsibling(nd)) != 0) { + while ((nd = nd->sibling) != NULL) { dev->next = (struct linux_ebus_device *) ebus_alloc(sizeof(struct linux_ebus_device)); @@ -348,7 +373,7 @@ void __init ebus_init(void) break; cookie = pdev->sysdata; - ebusnd = cookie->prom_node; + dp = cookie->prom_node; ebus->next = (struct linux_ebus *) ebus_alloc(sizeof(struct linux_ebus)); diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index f9ff297..ae4c667 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -39,6 +39,8 @@ #include #include #include #include +#include +#include #include #include #include @@ -224,10 +226,54 @@ static void _sparc_free_io(struct resour #ifdef CONFIG_SBUS -void sbus_set_sbus64(struct sbus_dev *sdev, int x) { +void sbus_set_sbus64(struct sbus_dev *sdev, int x) +{ printk("sbus_set_sbus64: unsupported\n"); } +extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); +void __init sbus_fill_device_irq(struct sbus_dev *sdev) +{ + struct linux_prom_irqs irqs[PROMINTR_MAX]; + int len; + + len = prom_getproperty(sdev->prom_node, "intr", + (char *)irqs, sizeof(irqs)); + if (len != -1) { + sdev->num_irqs = len / 8; + if (sdev->num_irqs == 0) { + sdev->irqs[0] = 0; + } else if (sparc_cpu_model == sun4d) { + for (len = 0; len < sdev->num_irqs; len++) + sdev->irqs[len] = + sun4d_build_irq(sdev, irqs[len].pri); + } else { + for (len = 0; len < sdev->num_irqs; len++) + sdev->irqs[len] = irqs[len].pri; + } + } else { + int interrupts[PROMINTR_MAX]; + + /* No "intr" node found-- check for "interrupts" node. + * This node contains SBus interrupt levels, not IPLs + * as in "intr", and no vector values. We convert + * SBus interrupt levels to PILs (platform specific). + */ + len = prom_getproperty(sdev->prom_node, "interrupts", + (char *)interrupts, sizeof(interrupts)); + if (len == -1) { + sdev->irqs[0] = 0; + sdev->num_irqs = 0; + } else { + sdev->num_irqs = len / sizeof(int); + for (len = 0; len < sdev->num_irqs; len++) { + sdev->irqs[len] = + sbint_to_irq(sdev, interrupts[len]); + } + } + } +} + /* * Allocate a chunk of memory suitable for DMA. * Typically devices use them for control blocks. @@ -414,6 +460,89 @@ void sbus_dma_sync_sg_for_device(struct { printk("sbus_dma_sync_sg_for_device: not implemented yet\n"); } + +/* Support code for sbus_init(). */ +/* + * XXX This functions appears to be a distorted version of + * prom_sbus_ranges_init(), with all sun4d stuff cut away. + * Ask DaveM what is going on here, how is sun4d supposed to work... XXX + */ +/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */ +void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) +{ + int parent_node = pn->node; + + if (sparc_cpu_model == sun4d) { + struct linux_prom_ranges iounit_ranges[PROMREG_MAX]; + int num_iounit_ranges, len; + + len = prom_getproperty(parent_node, "ranges", + (char *) iounit_ranges, + sizeof (iounit_ranges)); + if (len != -1) { + num_iounit_ranges = + (len / sizeof(struct linux_prom_ranges)); + prom_adjust_ranges(sbus->sbus_ranges, + sbus->num_sbus_ranges, + iounit_ranges, num_iounit_ranges); + } + } +} + +void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) +{ + struct device_node *parent = dp->parent; + + if (sparc_cpu_model != sun4d && + parent != NULL && + !strcmp(parent->name, "iommu")) { + extern void iommu_init(int iommu_node, struct sbus_bus *sbus); + + iommu_init(parent->node, sbus); + } + + if (sparc_cpu_model == sun4d) { + extern void iounit_init(int sbi_node, int iounit_node, + struct sbus_bus *sbus); + + iounit_init(dp->node, parent->node, sbus); + } +} + +void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) +{ + if (sparc_cpu_model == sun4d) { + struct device_node *parent = dp->parent; + + sbus->devid = of_getintprop_default(parent, "device-id", 0); + sbus->board = of_getintprop_default(parent, "board#", 0); + } +} + +int __init sbus_arch_preinit(void) +{ + extern void register_proc_sparc_ioport(void); + + register_proc_sparc_ioport(); + +#ifdef CONFIG_SUN4 + { + extern void sun4_dvma_init(void); + sun4_dvma_init(); + } + return 1; +#else + return 0; +#endif +} + +void __init sbus_arch_postinit(void) +{ + if (sparc_cpu_model == sun4d) { + extern void sun4d_init_sbi_irq(void); + sun4d_init_sbi_irq(); + } +} #endif /* CONFIG_SBUS */ #ifdef CONFIG_PCI diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c new file mode 100644 index 0000000..80a8094 --- /dev/null +++ b/arch/sparc/kernel/of_device.c @@ -0,0 +1,270 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/** + * of_match_device - Tell if an of_device structure has a matching + * of_match structure + * @ids: array of of device match structures to search in + * @dev: the of device structure to match against + * + * Used by a driver to check whether an of_device present in the + * system is in its list of supported devices. + */ +const struct of_device_id *of_match_device(const struct of_device_id *matches, + const struct of_device *dev) +{ + if (!dev->node) + return NULL; + while (matches->name[0] || matches->type[0] || matches->compatible[0]) { + int match = 1; + if (matches->name[0]) + match &= dev->node->name + && !strcmp(matches->name, dev->node->name); + if (matches->type[0]) + match &= dev->node->type + && !strcmp(matches->type, dev->node->type); + if (matches->compatible[0]) + match &= of_device_is_compatible(dev->node, + matches->compatible); + if (match) + return matches; + matches++; + } + return NULL; +} + +static int of_platform_bus_match(struct device *dev, struct device_driver *drv) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * of_drv = to_of_platform_driver(drv); + const struct of_device_id * matches = of_drv->match_table; + + if (!matches) + return 0; + + return of_match_device(matches, of_dev) != NULL; +} + +struct of_device *of_dev_get(struct of_device *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + tmp = get_device(&dev->dev); + if (tmp) + return to_of_device(tmp); + else + return NULL; +} + +void of_dev_put(struct of_device *dev) +{ + if (dev) + put_device(&dev->dev); +} + + +static int of_device_probe(struct device *dev) +{ + int error = -ENODEV; + struct of_platform_driver *drv; + struct of_device *of_dev; + const struct of_device_id *match; + + drv = to_of_platform_driver(dev->driver); + of_dev = to_of_device(dev); + + if (!drv->probe) + return error; + + of_dev_get(of_dev); + + match = of_match_device(drv->match_table, of_dev); + if (match) + error = drv->probe(of_dev, match); + if (error) + of_dev_put(of_dev); + + return error; +} + +static int of_device_remove(struct device *dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + + if (dev->driver && drv->remove) + drv->remove(of_dev); + return 0; +} + +static int of_device_suspend(struct device *dev, pm_message_t state) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->suspend) + error = drv->suspend(of_dev, state); + return error; +} + +static int of_device_resume(struct device * dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->resume) + error = drv->resume(of_dev); + return error; +} + +#ifdef CONFIG_PCI +struct bus_type ebus_bus_type = { + .name = "ebus", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(ebus_bus_type); +#endif + +#ifdef CONFIG_SBUS +struct bus_type sbus_bus_type = { + .name = "sbus", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(sbus_bus_type); +#endif + +static int __init of_bus_driver_init(void) +{ + int err = 0; + +#ifdef CONFIG_PCI + if (!err) + err = bus_register(&ebus_bus_type); +#endif +#ifdef CONFIG_SBUS + if (!err) + err = bus_register(&sbus_bus_type); +#endif + return 0; +} + +postcore_initcall(of_bus_driver_init); + +int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) +{ + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = bus; + + /* register with core */ + return driver_register(&drv->driver); +} + +void of_unregister_driver(struct of_platform_driver *drv) +{ + driver_unregister(&drv->driver); +} + + +static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + return sprintf(buf, "%s", ofdev->node->full_name); +} + +static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); + +/** + * of_release_dev - free an of device structure when all users of it are finished. + * @dev: device that's been disconnected + * + * Will be called only by the device core when all users of this of device are + * done. + */ +void of_release_dev(struct device *dev) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + + kfree(ofdev); +} + +int of_device_register(struct of_device *ofdev) +{ + int rc; + + BUG_ON(ofdev->node == NULL); + + rc = device_register(&ofdev->dev); + if (rc) + return rc; + + device_create_file(&ofdev->dev, &dev_attr_devspec); + + return 0; +} + +void of_device_unregister(struct of_device *ofdev) +{ + device_remove_file(&ofdev->dev, &dev_attr_devspec); + device_unregister(&ofdev->dev); +} + +struct of_device* of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent, + struct bus_type *bus) +{ + struct of_device *dev; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof(*dev)); + + dev->dev.parent = parent; + dev->dev.bus = bus; + dev->dev.release = of_release_dev; + + strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); + + if (of_device_register(dev) != 0) { + kfree(dev); + return NULL; + } + + return dev; +} + +EXPORT_SYMBOL(of_match_device); +EXPORT_SYMBOL(of_register_driver); +EXPORT_SYMBOL(of_unregister_driver); +EXPORT_SYMBOL(of_device_register); +EXPORT_SYMBOL(of_device_unregister); +EXPORT_SYMBOL(of_dev_get); +EXPORT_SYMBOL(of_dev_put); +EXPORT_SYMBOL(of_platform_device_create); +EXPORT_SYMBOL(of_release_dev); diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 42002b7..bcfdddd 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -665,7 +666,7 @@ void __init pcibios_fixup_bus(struct pci /* cookies */ pcp = pci_devcookie_alloc(); pcp->pbm = &pcic->pbm; - pcp->prom_node = node; + pcp->prom_node = of_find_node_by_phandle(node); dev->sysdata = pcp; /* fixing I/O to look like memory */ @@ -896,13 +897,6 @@ static inline unsigned long get_irqmask( return 1 << irq_nr; } -static inline char *pcic_irq_itoa(unsigned int irq) -{ - static char buff[16]; - sprintf(buff, "%d", irq); - return buff; -} - static void pcic_disable_irq(unsigned int irq_nr) { unsigned long mask, flags; @@ -955,7 +949,6 @@ void __init sun4m_pci_init_IRQ(void) BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_profile_irq, pcic_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(__irq_itoa, pcic_irq_itoa, BTFIXUPCALL_NORM); } int pcibios_assign_resource(struct pci_dev *pdev, int resource) diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c new file mode 100644 index 0000000..946ce6d --- /dev/null +++ b/arch/sparc/kernel/prom.c @@ -0,0 +1,544 @@ +/* + * Procedures for creating, accessing and interpreting the device tree. + * + * Paul Mackerras August 1996. + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. + * {engebret|bergner}@us.ibm.com + * + * Adapted for sparc32 by David S. Miller davem@davemloft.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +static struct device_node *allnodes; + +/* use when traversing tree through the allnext, child, sibling, + * or parent members of struct device_node. + */ +static DEFINE_RWLOCK(devtree_lock); + +int of_device_is_compatible(struct device_node *device, const char *compat) +{ + const char* cp; + int cplen, l; + + cp = (char *) of_get_property(device, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + if (strncmp(cp, compat, strlen(compat)) == 0) + return 1; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} +EXPORT_SYMBOL(of_device_is_compatible); + +struct device_node *of_get_parent(const struct device_node *node) +{ + struct device_node *np; + + if (!node) + return NULL; + + np = node->parent; + + return np; +} +EXPORT_SYMBOL(of_get_parent); + +struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev) +{ + struct device_node *next; + + next = prev ? prev->sibling : node->child; + for (; next != 0; next = next->sibling) { + break; + } + + return next; +} +EXPORT_SYMBOL(of_get_next_child); + +struct device_node *of_find_node_by_path(const char *path) +{ + struct device_node *np = allnodes; + + for (; np != 0; np = np->allnext) { + if (np->full_name != 0 && strcmp(np->full_name, path) == 0) + break; + } + + return np; +} +EXPORT_SYMBOL(of_find_node_by_path); + +struct device_node *of_find_node_by_phandle(phandle handle) +{ + struct device_node *np; + + for (np = allnodes; np != 0; np = np->allnext) + if (np->node == handle) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_phandle); + +struct device_node *of_find_node_by_name(struct device_node *from, + const char *name) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != NULL; np = np->allnext) + if (np->name != NULL && strcmp(np->name, name) == 0) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_name); + +struct device_node *of_find_node_by_type(struct device_node *from, + const char *type) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != 0; np = np->allnext) + if (np->type != 0 && strcmp(np->type, type) == 0) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_type); + +struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compatible) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != 0; np = np->allnext) { + if (type != NULL + && !(np->type != 0 && strcmp(np->type, type) == 0)) + continue; + if (of_device_is_compatible(np, compatible)) + break; + } + + return np; +} +EXPORT_SYMBOL(of_find_compatible_node); + +struct property *of_find_property(struct device_node *np, const char *name, + int *lenp) +{ + struct property *pp; + + for (pp = np->properties; pp != 0; pp = pp->next) { + if (strcmp(pp->name, name) == 0) { + if (lenp != 0) + *lenp = pp->length; + break; + } + } + return pp; +} +EXPORT_SYMBOL(of_find_property); + +/* + * Find a property with a given name for a given node + * and return the value. + */ +void *of_get_property(struct device_node *np, const char *name, int *lenp) +{ + struct property *pp = of_find_property(np,name,lenp); + return pp ? pp->value : NULL; +} +EXPORT_SYMBOL(of_get_property); + +int of_getintprop_default(struct device_node *np, const char *name, int def) +{ + struct property *prop; + int len; + + prop = of_find_property(np, name, &len); + if (!prop || len != 4) + return def; + + return *(int *) prop->value; +} +EXPORT_SYMBOL(of_getintprop_default); + +int of_set_property(struct device_node *dp, const char *name, void *val, int len) +{ + struct property **prevp; + void *new_val; + int err; + + new_val = kmalloc(len, GFP_KERNEL); + if (!new_val) + return -ENOMEM; + + memcpy(new_val, val, len); + + err = -ENODEV; + + write_lock(&devtree_lock); + prevp = &dp->properties; + while (*prevp) { + struct property *prop = *prevp; + + if (!strcmp(prop->name, name)) { + void *old_val = prop->value; + int ret; + + ret = prom_setprop(dp->node, name, val, len); + err = -EINVAL; + if (ret >= 0) { + prop->value = new_val; + prop->length = len; + + if (OF_IS_DYNAMIC(prop)) + kfree(old_val); + + OF_MARK_DYNAMIC(prop); + + err = 0; + } + break; + } + prevp = &(*prevp)->next; + } + write_unlock(&devtree_lock); + + /* XXX Upate procfs if necessary... */ + + return err; +} +EXPORT_SYMBOL(of_set_property); + +static unsigned int prom_early_allocated; + +static void * __init prom_early_alloc(unsigned long size) +{ + void *ret; + + ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); + if (ret != NULL) + memset(ret, 0, size); + + prom_early_allocated += size; + + return ret; +} + +static int is_root_node(const struct device_node *dp) +{ + if (!dp) + return 0; + + return (dp->parent == NULL); +} + +/* The following routines deal with the black magic of fully naming a + * node. + * + * Certain well known named nodes are just the simple name string. + * + * Actual devices have an address specifier appended to the base name + * string, like this "foo@addr". The "addr" can be in any number of + * formats, and the platform plus the type of the node determine the + * format and how it is constructed. + * + * For children of the ROOT node, the naming convention is fixed and + * determined by whether this is a sun4u or sun4v system. + * + * For children of other nodes, it is bus type specific. So + * we walk up the tree until we discover a "device_type" property + * we recognize and we go from there. + */ +static void __init sparc32_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_registers *regs; + struct property *rprop; + + rprop = of_find_property(dp, "reg", NULL); + if (!rprop) + return; + + regs = rprop->value; + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + regs->which_io, regs->phys_addr); +} + +/* "name@slot,offset" */ +static void __init sbus_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + regs->which_io, + regs->phys_addr); +} + +/* "name@devnum[,func]" */ +static void __init pci_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_pci_registers *regs; + struct property *prop; + unsigned int devfn; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + devfn = (regs->phys_hi >> 8) & 0xff; + if (devfn & 0x07) { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + devfn >> 3, + devfn & 0x07); + } else { + sprintf(tmp_buf, "%s@%x", + dp->name, + devfn >> 3); + } +} + +/* "name@addrhi,addrlo" */ +static void __init ebus_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + regs->which_io, regs->phys_addr); +} + +static void __init __build_path_component(struct device_node *dp, char *tmp_buf) +{ + struct device_node *parent = dp->parent; + + if (parent != NULL) { + if (!strcmp(parent->type, "pci") || + !strcmp(parent->type, "pciex")) + return pci_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "sbus")) + return sbus_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "ebus")) + return ebus_path_component(dp, tmp_buf); + + /* "isa" is handled with platform naming */ + } + + /* Use platform naming convention. */ + return sparc32_path_component(dp, tmp_buf); +} + +static char * __init build_path_component(struct device_node *dp) +{ + char tmp_buf[64], *n; + + tmp_buf[0] = '\0'; + __build_path_component(dp, tmp_buf); + if (tmp_buf[0] == '\0') + strcpy(tmp_buf, dp->name); + + n = prom_early_alloc(strlen(tmp_buf) + 1); + strcpy(n, tmp_buf); + + return n; +} + +static char * __init build_full_name(struct device_node *dp) +{ + int len, ourlen, plen; + char *n; + + plen = strlen(dp->parent->full_name); + ourlen = strlen(dp->path_component_name); + len = ourlen + plen + 2; + + n = prom_early_alloc(len); + strcpy(n, dp->parent->full_name); + if (!is_root_node(dp->parent)) { + strcpy(n + plen, "/"); + plen++; + } + strcpy(n + plen, dp->path_component_name); + + return n; +} + +static unsigned int unique_id; + +static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len) +{ + static struct property *tmp = NULL; + struct property *p; + int len; + + if (tmp) { + p = tmp; + memset(p, 0, sizeof(*p) + 32); + tmp = NULL; + } else { + p = prom_early_alloc(sizeof(struct property) + 32); + p->unique_id = unique_id++; + } + + p->name = (char *) (p + 1); + if (special_name) { + p->length = special_len; + p->value = prom_early_alloc(special_len); + memcpy(p->value, special_val, special_len); + } else { + if (prev == NULL) { + prom_firstprop(node, p->name); + } else { + prom_nextprop(node, prev, p->name); + } + if (strlen(p->name) == 0) { + tmp = p; + return NULL; + } + p->length = prom_getproplen(node, p->name); + if (p->length <= 0) { + p->length = 0; + } else { + p->value = prom_early_alloc(p->length + 1); + prom_getproperty(node, p->name, p->value, p->length); + ((unsigned char *)p->value)[p->length] = '\0'; + } + } + return p; +} + +static struct property * __init build_prop_list(phandle node) +{ + struct property *head, *tail; + + head = tail = build_one_prop(node, NULL, + ".node", &node, sizeof(node)); + + tail->next = build_one_prop(node, NULL, NULL, NULL, 0); + tail = tail->next; + while(tail) { + tail->next = build_one_prop(node, tail->name, + NULL, NULL, 0); + tail = tail->next; + } + + return head; +} + +static char * __init get_one_property(phandle node, char *name) +{ + char *buf = ""; + int len; + + len = prom_getproplen(node, name); + if (len > 0) { + buf = prom_early_alloc(len); + len = prom_getproperty(node, name, buf, len); + } + + return buf; +} + +static struct device_node * __init create_node(phandle node) +{ + struct device_node *dp; + + if (!node) + return NULL; + + dp = prom_early_alloc(sizeof(*dp)); + dp->unique_id = unique_id++; + + kref_init(&dp->kref); + + dp->name = get_one_property(node, "name"); + dp->type = get_one_property(node, "device_type"); + dp->node = node; + + /* Build interrupts later... */ + + dp->properties = build_prop_list(node); + + return dp; +} + +static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) +{ + struct device_node *dp; + + dp = create_node(node); + if (dp) { + *(*nextp) = dp; + *nextp = &dp->allnext; + + dp->parent = parent; + dp->path_component_name = build_path_component(dp); + dp->full_name = build_full_name(dp); + + dp->child = build_tree(dp, prom_getchild(node), nextp); + + dp->sibling = build_tree(parent, prom_getsibling(node), nextp); + } + + return dp; +} + +void __init prom_build_devicetree(void) +{ + struct device_node **nextp; + + allnodes = create_node(prom_root_node); + allnodes->path_component_name = ""; + allnodes->full_name = "/"; + + nextp = &allnodes->allnext; + allnodes->child = build_tree(allnodes, + prom_getchild(allnodes->node), + &nextp); + printk("PROM: Built device tree with %u bytes of memory.\n", + prom_early_allocated); +} diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 3509e43..a893a9c 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -31,6 +31,7 @@ #include #include #include #include +#include #include #include @@ -331,7 +332,7 @@ #endif if (!root_flags) root_mountflags &= ~MS_RDONLY; ROOT_DEV = old_decode_dev(root_dev); -#ifdef CONFIG_BLK_DEV_INITRD +#ifdef CONFIG_BLK_DEV_RAM rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK; rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0); rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); @@ -348,6 +349,8 @@ #endif init_mm.context = (unsigned long) NO_CONTEXT; init_task.thread.kregs = &fake_swapper_regs; + smp_setup_cpu_possible_map(); + paging_init(); } @@ -389,6 +392,8 @@ console_initcall(set_preferred_console); extern char *sparc_cpu_type; extern char *sparc_fpu_type; +static int ncpus_probed; + static int show_cpuinfo(struct seq_file *m, void *__unused) { seq_printf(m, @@ -411,7 +416,7 @@ #endif romvec->pv_printrev >> 16, romvec->pv_printrev & 0xffff, &cputypval, - num_possible_cpus(), + ncpus_probed, num_online_cpus() #ifndef CONFIG_SMP , cpu_data(0).udelay_val/(500000/HZ), @@ -471,3 +476,30 @@ void sun_do_break(void) int serial_console = -1; int stop_a_enabled = 1; + +static int __init topology_init(void) +{ + int i, ncpus, err; + + /* Count the number of physically present processors in + * the machine, even on uniprocessor, so that /proc/cpuinfo + * output is consistent with 2.4.x + */ + ncpus = 0; + while (!cpu_find_by_instance(ncpus, NULL, NULL)) + ncpus++; + ncpus_probed = ncpus; + + err = 0; + for_each_online_cpu(i) { + struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + err = -ENOMEM; + else + register_cpu(p, i, NULL); + } + + return err; +} + +subsys_initcall(topology_init); diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index 40b42c8..6135d4f 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -58,7 +58,7 @@ cpumask_t smp_commenced_mask = CPU_MASK_ /* Used to make bitops atomic */ unsigned char bitops_spinlock = 0; -void __init smp_store_cpu_info(int id) +void __cpuinit smp_store_cpu_info(int id) { int cpu_node; @@ -267,22 +267,18 @@ int setup_profiling_timer(unsigned int m void __init smp_prepare_cpus(unsigned int max_cpus) { extern void smp4m_boot_cpus(void); - int i, cpuid, ncpus, extra; + int i, cpuid, extra; BUG_ON(sparc_cpu_model != sun4m); printk("Entering SMP Mode...\n"); - ncpus = 1; extra = 0; for (i = 0; !cpu_find_by_instance(i, NULL, &cpuid); i++) { - if (cpuid == boot_cpu_id) - continue; - if (cpuid < NR_CPUS && ncpus++ < max_cpus) - cpu_set(cpuid, phys_cpu_present_map); - else + if (cpuid >= NR_CPUS) extra++; } - if (max_cpus >= NR_CPUS && extra) + /* i = number of cpus */ + if (extra && max_cpus > i - extra) printk("Warning: NR_CPUS is too low to start all cpus\n"); smp_store_cpu_info(boot_cpu_id); @@ -290,7 +286,25 @@ void __init smp_prepare_cpus(unsigned in smp4m_boot_cpus(); } -void __devinit smp_prepare_boot_cpu(void) +/* Set this up early so that things like the scheduler can init + * properly. We use the same cpu mask for both the present and + * possible cpu map. + */ +void __init smp_setup_cpu_possible_map(void) +{ + int instance, mid; + + instance = 0; + while (!cpu_find_by_instance(instance, NULL, &mid)) { + if (mid < NR_CPUS) { + cpu_set(mid, phys_cpu_present_map); + cpu_set(mid, cpu_present_map); + } + instance++; + } +} + +void __init smp_prepare_boot_cpu(void) { int cpuid = hard_smp_processor_id(); @@ -306,7 +320,7 @@ void __devinit smp_prepare_boot_cpu(void cpu_set(cpuid, phys_cpu_present_map); } -int __devinit __cpu_up(unsigned int cpu) +int __cpuinit __cpu_up(unsigned int cpu) { extern int smp4m_boot_one_cpu(int); int ret; diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 4b376fa..fd7deab 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -163,7 +163,6 @@ EXPORT_SYMBOL(BTFIXUP_CALL(__hard_smp_pr #endif EXPORT_SYMBOL(BTFIXUP_CALL(enable_irq)); EXPORT_SYMBOL(BTFIXUP_CALL(disable_irq)); -EXPORT_SYMBOL(BTFIXUP_CALL(__irq_itoa)); EXPORT_SYMBOL(BTFIXUP_CALL(mmu_unlockarea)); EXPORT_SYMBOL(BTFIXUP_CALL(mmu_lockarea)); EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_sgl)); diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 3d6a990..0f2d8d9 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -198,8 +198,6 @@ #ifdef CONFIG_SMP static void sun4c_nop(void) {} #endif -extern char *sun4m_irq_itoa(unsigned int irq); - void __init sun4c_init_IRQ(void) { struct linux_prom_registers int_regs[2]; @@ -238,7 +236,6 @@ void __init sun4c_init_IRQ(void) BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_profile_irq, sun4c_clear_profile_irq, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM); sparc_init_timers = sun4c_init_timers; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index ca656d9..9c30e35 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -560,17 +560,6 @@ #endif } } -static char *sun4d_irq_itoa(unsigned int irq) -{ - static char buff[16]; - - if (irq < (1 << 5)) - sprintf(buff, "%d", irq); - else - sprintf(buff, "%d,%x", sbus_to_pil[(irq >> 2) & 7], irq); - return buff; -} - void __init sun4d_init_IRQ(void) { local_irq_disable(); @@ -581,7 +570,6 @@ void __init sun4d_init_IRQ(void) BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_profile_irq, sun4d_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(__irq_itoa, sun4d_irq_itoa, BTFIXUPCALL_NORM); sparc_init_timers = sun4d_init_timers; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 39d712c..a296c13 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -229,13 +229,6 @@ static void sun4m_load_profile_irq(int c sun4m_timers->cpu_timers[cpu].l14_timer_limit = limit; } -char *sun4m_irq_itoa(unsigned int irq) -{ - static char buff[16]; - sprintf(buff, "%d", irq); - return buff; -} - static void __init sun4m_init_timers(irqreturn_t (*counter_fn)(int, void *, struct pt_regs *)) { int reg_count, irq, cpu; @@ -388,7 +381,6 @@ void __init sun4m_init_IRQ(void) BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM); sparc_init_timers = sun4m_init_timers; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 70b375a..3b32096 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -66,7 +66,7 @@ static inline unsigned long swap(volatil static void smp_setup_percpu_timer(void); extern void cpu_probe(void); -void __init smp4m_callin(void) +void __cpuinit smp4m_callin(void) { int cpuid = hard_smp_processor_id(); @@ -112,13 +112,8 @@ void __init smp4m_callin(void) local_irq_enable(); cpu_set(cpuid, cpu_online_map); - /* last one in gets all the interrupts (for testing) */ - set_irq_udt(boot_cpu_id); } -extern void init_IRQ(void); -extern void cpu_panic(void); - /* * Cycle through the processors asking the PROM to start each one. */ @@ -134,7 +129,7 @@ void __init smp4m_boot_cpus(void) local_flush_cache_all(); } -int smp4m_boot_one_cpu(int i) +int __cpuinit smp4m_boot_one_cpu(int i) { extern unsigned long sun4m_cpu_startup; unsigned long *entry = &sun4m_cpu_startup; diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index fa50069..5db7e1d 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile @@ -9,3 +9,5 @@ lib-y := mul.o rem.o sdiv.o udiv.o umul. strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \ copy_user.o locks.o atomic.o atomic32.o bitops.o \ lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o + +obj-y += iomap.o diff --git a/arch/sparc/lib/iomap.c b/arch/sparc/lib/iomap.c new file mode 100644 index 0000000..54501c1 --- /dev/null +++ b/arch/sparc/lib/iomap.c @@ -0,0 +1,48 @@ +/* + * Implement the sparc iomap interfaces + */ +#include +#include +#include + +/* Create a virtual mapping cookie for an IO port range */ +void __iomem *ioport_map(unsigned long port, unsigned int nr) +{ + return (void __iomem *) (unsigned long) port; +} + +void ioport_unmap(void __iomem *addr) +{ + /* Nothing to do */ +} +EXPORT_SYMBOL(ioport_map); +EXPORT_SYMBOL(ioport_unmap); + +/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) +{ + unsigned long start = pci_resource_start(dev, bar); + unsigned long len = pci_resource_len(dev, bar); + unsigned long flags = pci_resource_flags(dev, bar); + + if (!len || !start) + return NULL; + if (maxlen && len > maxlen) + len = maxlen; + if (flags & IORESOURCE_IO) + return ioport_map(start, len); + if (flags & IORESOURCE_MEM) { + if (flags & IORESOURCE_CACHEABLE) + return ioremap(start, len); + return ioremap_nocache(start, len); + } + /* What? */ + return NULL; +} + +void pci_iounmap(struct pci_dev *dev, void __iomem * addr) +{ + /* nothing to do */ +} +EXPORT_SYMBOL(pci_iomap); +EXPORT_SYMBOL(pci_iounmap); diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c index 8986697..cfa7d34 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init.c @@ -31,6 +31,7 @@ #include #include #include /* bug in asm-generic/tlb.h: check_pgt_cache */ #include +#include DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -349,6 +350,7 @@ void __init paging_init(void) protection_map[14] = PAGE_SHARED; protection_map[15] = PAGE_SHARED; btfixup(); + prom_build_devicetree(); device_scan(); } diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 77840c8..7215849 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -144,8 +144,9 @@ static void iommu_flush_iotlb(iopte_t *i unsigned long start; unsigned long end; - start = (unsigned long)iopte & PAGE_MASK; + start = (unsigned long)iopte; end = PAGE_ALIGN(start + niopte*sizeof(iopte_t)); + start &= PAGE_MASK; if (viking_mxcc_present) { while(start < end) { viking_mxcc_flush_page(start); diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 43a66f5..a7a111d 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -87,6 +87,10 @@ config SYSVIPC_COMPAT depends on COMPAT && SYSVIPC default y +config GENERIC_HARDIRQS + bool + default y + menu "General machine setup" config SMP diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index f09a70b..b2f4114 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-rc3 -# Fri May 12 12:43:49 2006 +# Linux kernel version: 2.6.17 +# Fri Jun 23 23:17:09 2006 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -87,6 +87,7 @@ # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" CONFIG_SYSVIPC_COMPAT=y +CONFIG_GENERIC_HARDIRQS=y # # General machine setup @@ -183,6 +184,8 @@ CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y CONFIG_INET_XFRM_TUNNEL=y CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y CONFIG_TCP_CONG_ADVANCED=y @@ -198,6 +201,9 @@ CONFIG_TCP_CONG_HSTCP=m CONFIG_TCP_CONG_HYBLA=m CONFIG_TCP_CONG_VEGAS=m CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_COMPOUND=m CONFIG_IPV6=m CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y @@ -207,7 +213,10 @@ CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m CONFIG_INET6_XFRM_TUNNEL=m CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m CONFIG_IPV6_TUNNEL=m +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # @@ -260,6 +269,7 @@ # # Network testing # CONFIG_NET_PKTGEN=m +CONFIG_NET_TCPPROBE=m # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -276,6 +286,7 @@ CONFIG_STANDALONE=y # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker @@ -424,6 +435,7 @@ # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -562,6 +574,7 @@ # # CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices @@ -722,6 +735,7 @@ # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set @@ -765,6 +779,7 @@ # Hardware Monitoring support # CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -793,10 +808,12 @@ # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set @@ -811,6 +828,7 @@ # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -1006,6 +1024,7 @@ # CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1085,10 +1104,12 @@ # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set @@ -1135,6 +1156,19 @@ # # CONFIG_RTC_CLASS is not set # +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# # Misc Linux/SPARC drivers # CONFIG_SUN_OPENPROMIO=m @@ -1173,6 +1207,7 @@ # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 6f68164..86c9fe3 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -12,7 +12,7 @@ obj-y := process.o setup.o cpu.o idprom irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o pci.o starfire.o semaphore.o \ power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \ - visemul.o + visemul.o prom.o of_device.o obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \ pci_psycho.o pci_sabre.o pci_schizo.o \ diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index 8852c20..c2c69c1 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -16,8 +17,8 @@ #include #include #include -/* This cannot be static, as it is referenced in irq.c */ void __iomem *auxio_register = NULL; +EXPORT_SYMBOL(auxio_register); enum auxio_type { AUXIO_TYPE_NODEV, @@ -110,43 +111,82 @@ void auxio_set_lte(int on) } } -void __init auxio_probe(void) +static void __devinit auxio_report_dev(struct device_node *dp) { - struct sbus_bus *sbus; - struct sbus_dev *sdev = NULL; - - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if(!strcmp(sdev->prom_name, "auxio")) - goto found_sdev; - } - } - -found_sdev: - if (sdev) { - auxio_devtype = AUXIO_TYPE_SBUS; - auxio_register = sbus_ioremap(&sdev->resource[0], 0, - sdev->reg_addrs[0].reg_size, - "auxiliaryIO"); - } + printk(KERN_INFO "AUXIO: Found device at %s\n", + dp->full_name); +} + +static struct of_device_id auxio_match[] = { + { + .name = "auxio", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, auxio_match); + +#ifdef CONFIG_SBUS +static int __devinit auxio_sbus_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct sbus_dev *sdev = to_sbus_device(&dev->dev); + + auxio_devtype = AUXIO_TYPE_SBUS; + auxio_register = sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, + "auxiliaryIO"); + if (!auxio_register) + return -ENODEV; + + auxio_report_dev(dev->node); + return 0; +} + +static struct of_platform_driver auxio_sbus_driver = { + .name = "auxio", + .match_table = auxio_match, + .probe = auxio_sbus_probe, +}; +#endif + #ifdef CONFIG_PCI - else { - struct linux_ebus *ebus; - struct linux_ebus_device *edev = NULL; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "auxio")) - goto ebus_done; - } - } - ebus_done: - if (edev) { - auxio_devtype = AUXIO_TYPE_EBUS; - auxio_register = - ioremap(edev->resource[0].start, sizeof(u32)); - } - } +static int __devinit auxio_ebus_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct linux_ebus_device *edev = to_ebus_device(&dev->dev); + + auxio_devtype = AUXIO_TYPE_EBUS; + auxio_register = ioremap(edev->resource[0].start, sizeof(u32)); + if (!auxio_register) + return -ENODEV; + + auxio_report_dev(dev->node); + auxio_set_led(AUXIO_LED_ON); + + return 0; +} + +static struct of_platform_driver auxio_ebus_driver = { + .name = "auxio", + .match_table = auxio_match, + .probe = auxio_ebus_probe, +}; #endif + +static int __init auxio_probe(void) +{ +#ifdef CONFIG_SBUS + of_register_driver(&auxio_sbus_driver, &sbus_bus_type); +#endif +#ifdef CONFIG_PCI + of_register_driver(&auxio_ebus_driver, &ebus_bus_type); +#endif + + return 0; } + +/* Must be after subsys_initcall() so that busses are probed. Must + * be before device_initcall() because things like the floppy driver + * need to use the AUXIO register. + */ +fs_initcall(auxio_probe); diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c index 3d184a7..b66336d 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc64/kernel/central.c @@ -29,28 +29,34 @@ static void central_probe_failure(int li prom_halt(); } -static void central_ranges_init(int cnode, struct linux_central *central) +static void central_ranges_init(struct linux_central *central) { - int success; + struct device_node *dp = central->prom_node; + void *pval; + int len; central->num_central_ranges = 0; - success = prom_getproperty(central->prom_node, "ranges", - (char *) central->central_ranges, - sizeof (central->central_ranges)); - if (success != -1) - central->num_central_ranges = (success/sizeof(struct linux_prom_ranges)); + pval = of_get_property(dp, "ranges", &len); + if (pval) { + memcpy(central->central_ranges, pval, len); + central->num_central_ranges = + (len / sizeof(struct linux_prom_ranges)); + } } -static void fhc_ranges_init(int fnode, struct linux_fhc *fhc) +static void fhc_ranges_init(struct linux_fhc *fhc) { - int success; + struct device_node *dp = fhc->prom_node; + void *pval; + int len; fhc->num_fhc_ranges = 0; - success = prom_getproperty(fhc->prom_node, "ranges", - (char *) fhc->fhc_ranges, - sizeof (fhc->fhc_ranges)); - if (success != -1) - fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges)); + pval = of_get_property(dp, "ranges", &len); + if (pval) { + memcpy(fhc->fhc_ranges, pval, len); + fhc->num_fhc_ranges = + (len / sizeof(struct linux_prom_ranges)); + } } /* Range application routines are exported to various drivers, @@ -112,15 +118,10 @@ static unsigned long prom_reg_to_paddr(s static void probe_other_fhcs(void) { - struct linux_prom64_registers fpregs[6]; - char namebuf[128]; - int node; + struct device_node *dp; + struct linux_prom64_registers *fpregs; - node = prom_getchild(prom_root_node); - node = prom_searchsiblings(node, "fhc"); - if (node == 0) - central_probe_failure(__LINE__); - while (node) { + for_each_node_by_name(dp, "fhc") { struct linux_fhc *fhc; int board; u32 tmp; @@ -137,14 +138,12 @@ static void probe_other_fhcs(void) /* Toplevel FHCs have no parent. */ fhc->parent = NULL; - fhc->prom_node = node; - prom_getstring(node, "name", namebuf, sizeof(namebuf)); - strcpy(fhc->prom_name, namebuf); - fhc_ranges_init(node, fhc); + fhc->prom_node = dp; + fhc_ranges_init(fhc); /* Non-central FHC's have 64-bit OBP format registers. */ - if (prom_getproperty(node, "reg", - (char *)&fpregs[0], sizeof(fpregs)) == -1) + fpregs = of_get_property(dp, "reg", NULL); + if (!fpregs) central_probe_failure(__LINE__); /* Only central FHC needs special ranges applied. */ @@ -155,7 +154,7 @@ static void probe_other_fhcs(void) fhc->fhc_regs.uregs = fpregs[4].phys_addr; fhc->fhc_regs.tregs = fpregs[5].phys_addr; - board = prom_getintdefault(node, "board#", -1); + board = of_getintprop_default(dp, "board#", -1); fhc->board = board; tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL); @@ -179,33 +178,33 @@ static void probe_other_fhcs(void) tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); tmp |= FHC_CONTROL_IXIST; upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - - /* Look for the next FHC. */ - node = prom_getsibling(node); - if (node == 0) - break; - node = prom_searchsiblings(node, "fhc"); - if (node == 0) - break; } } static void probe_clock_board(struct linux_central *central, struct linux_fhc *fhc, - int cnode, int fnode) + struct device_node *fp) { - struct linux_prom_registers cregs[3]; - int clknode, nslots, tmp, nregs; + struct device_node *dp; + struct linux_prom_registers cregs[3], *pr; + int nslots, tmp, nregs; - clknode = prom_searchsiblings(prom_getchild(fnode), "clock-board"); - if (clknode == 0 || clknode == -1) + dp = fp->child; + while (dp) { + if (!strcmp(dp->name, "clock-board")) + break; + dp = dp->sibling; + } + if (!dp) central_probe_failure(__LINE__); - nregs = prom_getproperty(clknode, "reg", (char *)&cregs[0], sizeof(cregs)); - if (nregs == -1) + pr = of_get_property(dp, "reg", &nregs); + if (!pr) central_probe_failure(__LINE__); + memcpy(cregs, pr, nregs); nregs /= sizeof(struct linux_prom_registers); + apply_fhc_ranges(fhc, &cregs[0], nregs); apply_central_ranges(central, &cregs[0], nregs); central->cfreg = prom_reg_to_paddr(&cregs[0]); @@ -296,13 +295,13 @@ static void init_all_fhc_hw(void) void central_probe(void) { - struct linux_prom_registers fpregs[6]; + struct linux_prom_registers fpregs[6], *pr; struct linux_fhc *fhc; - char namebuf[128]; - int cnode, fnode, err; + struct device_node *dp, *fp; + int err; - cnode = prom_finddevice("/central"); - if (cnode == 0 || cnode == -1) { + dp = of_find_node_by_name(NULL, "central"); + if (!dp) { if (this_is_starfire) starfire_cpu_setup(); return; @@ -321,31 +320,31 @@ void central_probe(void) /* First init central. */ central_bus->child = fhc; - central_bus->prom_node = cnode; - - prom_getstring(cnode, "name", namebuf, sizeof(namebuf)); - strcpy(central_bus->prom_name, namebuf); - - central_ranges_init(cnode, central_bus); + central_bus->prom_node = dp; + central_ranges_init(central_bus); /* And then central's FHC. */ fhc->next = fhc_list; fhc_list = fhc; fhc->parent = central_bus; - fnode = prom_searchsiblings(prom_getchild(cnode), "fhc"); - if (fnode == 0 || fnode == -1) + fp = dp->child; + while (fp) { + if (!strcmp(fp->name, "fhc")) + break; + fp = fp->sibling; + } + if (!fp) central_probe_failure(__LINE__); - fhc->prom_node = fnode; - prom_getstring(fnode, "name", namebuf, sizeof(namebuf)); - strcpy(fhc->prom_name, namebuf); - - fhc_ranges_init(fnode, fhc); + fhc->prom_node = fp; + fhc_ranges_init(fhc); /* Now, map in FHC register set. */ - if (prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)) == -1) + pr = of_get_property(fp, "reg", NULL); + if (!pr) central_probe_failure(__LINE__); + memcpy(fpregs, pr, sizeof(fpregs)); apply_central_ranges(central_bus, &fpregs[0], 6); @@ -366,7 +365,7 @@ void central_probe(void) fhc->jtag_master = 0; /* Attach the clock board registers for CENTRAL. */ - probe_clock_board(central_bus, fhc, cnode, fnode); + probe_clock_board(central_bus, fhc, fp); err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n", diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 97cf912..259f37e 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -17,6 +17,7 @@ #include #include #include #include +#include #include #define CHMCTRL_NDGRPS 2 @@ -67,7 +68,6 @@ struct bank_info { struct mctrl_info { struct list_head list; int portid; - int index; struct obp_mem_layout layout_prop; int layout_size; @@ -339,12 +339,13 @@ static void fetch_decode_regs(struct mct read_mcreg(mp, CHMCTRL_DECODE4)); } -static int init_one_mctrl(int node, int index) +static int init_one_mctrl(struct device_node *dp) { struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL); - int portid = prom_getintdefault(node, "portid", -1); - struct linux_prom64_registers p_reg_prop; - int t; + int portid = of_getintprop_default(dp, "portid", -1); + struct linux_prom64_registers *regs; + void *pval; + int len; if (!mp) return -1; @@ -353,24 +354,21 @@ static int init_one_mctrl(int node, int goto fail; mp->portid = portid; - mp->layout_size = prom_getproplen(node, "memory-layout"); - if (mp->layout_size < 0) + pval = of_get_property(dp, "memory-layout", &len); + mp->layout_size = len; + if (!pval) mp->layout_size = 0; - if (mp->layout_size > sizeof(mp->layout_prop)) - goto fail; - - if (mp->layout_size > 0) - prom_getproperty(node, "memory-layout", - (char *) &mp->layout_prop, - mp->layout_size); + else { + if (mp->layout_size > sizeof(mp->layout_prop)) + goto fail; + memcpy(&mp->layout_prop, pval, len); + } - t = prom_getproperty(node, "reg", - (char *) &p_reg_prop, - sizeof(p_reg_prop)); - if (t < 0 || p_reg_prop.reg_size != 0x48) + regs = of_get_property(dp, "reg", NULL); + if (!regs || regs->reg_size != 0x48) goto fail; - mp->regs = ioremap(p_reg_prop.phys_addr, p_reg_prop.reg_size); + mp->regs = ioremap(regs->phys_addr, regs->reg_size); if (mp->regs == NULL) goto fail; @@ -384,13 +382,11 @@ static int init_one_mctrl(int node, int fetch_decode_regs(mp); - mp->index = index; - list_add(&mp->list, &mctrl_list); /* Report the device. */ - printk(KERN_INFO "chmc%d: US3 memory controller at %p [%s]\n", - mp->index, + printk(KERN_INFO "%s: US3 memory controller at %p [%s]\n", + dp->full_name, mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE")); return 0; @@ -404,34 +400,19 @@ fail: return -1; } -static int __init probe_for_string(char *name, int index) -{ - int node = prom_getchild(prom_root_node); - - while ((node = prom_searchsiblings(node, name)) != 0) { - int ret = init_one_mctrl(node, index); - - if (!ret) - index++; - - node = prom_getsibling(node); - if (!node) - break; - } - - return index; -} - static int __init chmc_init(void) { - int index; + struct device_node *dp; /* This driver is only for cheetah platforms. */ if (tlb_type != cheetah && tlb_type != cheetah_plus) return -ENODEV; - index = probe_for_string("memory-controller", 0); - index = probe_for_string("mc-us3", index); + for_each_node_by_name(dp, "memory-controller") + init_one_mctrl(dp); + + for_each_node_by_name(dp, "mc-us3") + init_one_mctrl(dp); return 0; } diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c index 007e892..389301c 100644 --- a/arch/sparc64/kernel/devices.c +++ b/arch/sparc64/kernel/devices.c @@ -33,7 +33,7 @@ extern void cpu_probe(void); extern void central_probe(void); u32 sun4v_vdev_devhandle; -int sun4v_vdev_root; +struct device_node *sun4v_vdev_root; struct vdev_intmap { unsigned int phys; @@ -50,102 +50,68 @@ struct vdev_intmask { static struct vdev_intmap *vdev_intmap; static int vdev_num_intmap; -static struct vdev_intmask vdev_intmask; +static struct vdev_intmask *vdev_intmask; static void __init sun4v_virtual_device_probe(void) { - struct linux_prom64_registers regs; - struct vdev_intmap *ip; - int node, sz, err; + struct linux_prom64_registers *regs; + struct property *prop; + struct device_node *dp; + int sz; if (tlb_type != hypervisor) return; - node = prom_getchild(prom_root_node); - node = prom_searchsiblings(node, "virtual-devices"); - if (!node) { + dp = of_find_node_by_name(NULL, "virtual-devices"); + if (!dp) { prom_printf("SUN4V: Fatal error, no virtual-devices node.\n"); prom_halt(); } - sun4v_vdev_root = node; + sun4v_vdev_root = dp; - prom_getproperty(node, "reg", (char *)®s, sizeof(regs)); - sun4v_vdev_devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; + prop = of_find_property(dp, "reg", NULL); + regs = prop->value; + sun4v_vdev_devhandle = (regs[0].phys_addr >> 32UL) & 0x0fffffff; - sz = prom_getproplen(node, "interrupt-map"); - if (sz <= 0) { - prom_printf("SUN4V: Error, no vdev interrupt-map.\n"); - prom_halt(); - } - - if ((sz % sizeof(*ip)) != 0) { - prom_printf("SUN4V: Bogus interrupt-map property size %d\n", - sz); - prom_halt(); - } - - vdev_intmap = ip = alloc_bootmem_low_pages(sz); - if (!vdev_intmap) { - prom_printf("SUN4V: Error, cannot allocate vdev_intmap.\n"); - prom_halt(); - } - - err = prom_getproperty(node, "interrupt-map", (char *) ip, sz); - if (err == -1) { - prom_printf("SUN4V: Fatal error, no vdev interrupt-map.\n"); - prom_halt(); - } - if (err != sz) { - prom_printf("SUN4V: Inconsistent interrupt-map size, " - "proplen(%d) vs getprop(%d).\n", sz,err); - prom_halt(); - } - - vdev_num_intmap = err / sizeof(*ip); + prop = of_find_property(dp, "interrupt-map", &sz); + vdev_intmap = prop->value; + vdev_num_intmap = sz / sizeof(struct vdev_intmap); - err = prom_getproperty(node, "interrupt-map-mask", - (char *) &vdev_intmask, - sizeof(vdev_intmask)); - if (err <= 0) { - prom_printf("SUN4V: Fatal error, no vdev " - "interrupt-map-mask.\n"); - prom_halt(); - } - if (err % sizeof(vdev_intmask)) { - prom_printf("SUN4V: Bogus interrupt-map-mask " - "property size %d\n", err); - prom_halt(); - } + prop = of_find_property(dp, "interrupt-map-mask", NULL); + vdev_intmask = prop->value; - printk("SUN4V: virtual-devices devhandle[%x]\n", - sun4v_vdev_devhandle); + printk("%s: Virtual Device Bus devhandle[%x]\n", + dp->full_name, sun4v_vdev_devhandle); } -unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node) +unsigned int sun4v_vdev_device_interrupt(struct device_node *dev_node) { + struct property *prop; unsigned int irq, reg; - int err, i; + int i; - err = prom_getproperty(dev_node, "interrupts", - (char *) &irq, sizeof(irq)); - if (err <= 0) { + prop = of_find_property(dev_node, "interrupts", NULL); + if (!prop) { printk("VDEV: Cannot get \"interrupts\" " - "property for OBP node %x\n", dev_node); + "property for OBP node %s\n", + dev_node->full_name); return 0; } + irq = *(unsigned int *) prop->value; - err = prom_getproperty(dev_node, "reg", - (char *) ®, sizeof(reg)); - if (err <= 0) { + prop = of_find_property(dev_node, "reg", NULL); + if (!prop) { printk("VDEV: Cannot get \"reg\" " - "property for OBP node %x\n", dev_node); + "property for OBP node %s\n", + dev_node->full_name); return 0; } + reg = *(unsigned int *) prop->value; for (i = 0; i < vdev_num_intmap; i++) { - if (vdev_intmap[i].phys == (reg & vdev_intmask.phys) && - vdev_intmap[i].irq == (irq & vdev_intmask.interrupt)) { + if (vdev_intmap[i].phys == (reg & vdev_intmask->phys) && + vdev_intmap[i].irq == (irq & vdev_intmask->interrupt)) { irq = vdev_intmap[i].cinterrupt; break; } @@ -153,11 +119,11 @@ unsigned int sun4v_vdev_device_interrupt if (i == vdev_num_intmap) { printk("VDEV: No matching interrupt map entry " - "for OBP node %x\n", dev_node); + "for OBP node %s\n", dev_node->full_name); return 0; } - return sun4v_build_irq(sun4v_vdev_devhandle, irq, 5, 0); + return sun4v_build_irq(sun4v_vdev_devhandle, irq); } static const char *cpu_mid_prop(void) @@ -167,38 +133,44 @@ static const char *cpu_mid_prop(void) return "portid"; } -static int get_cpu_mid(int prom_node) +static int get_cpu_mid(struct device_node *dp) { + struct property *prop; + if (tlb_type == hypervisor) { - struct linux_prom64_registers reg; + struct linux_prom64_registers *reg; + int len; - if (prom_getproplen(prom_node, "cpuid") == 4) - return prom_getintdefault(prom_node, "cpuid", 0); + prop = of_find_property(dp, "cpuid", &len); + if (prop && len == 4) + return *(int *) prop->value; - prom_getproperty(prom_node, "reg", (char *) ®, sizeof(reg)); - return (reg.phys_addr >> 32) & 0x0fffffffUL; + prop = of_find_property(dp, "reg", NULL); + reg = prop->value; + return (reg[0].phys_addr >> 32) & 0x0fffffffUL; } else { const char *prop_name = cpu_mid_prop(); - return prom_getintdefault(prom_node, prop_name, 0); + prop = of_find_property(dp, prop_name, NULL); + if (prop) + return *(int *) prop->value; + return 0; } } -static int check_cpu_node(int nd, int *cur_inst, - int (*compare)(int, int, void *), void *compare_arg, - int *prom_node, int *mid) +static int check_cpu_node(struct device_node *dp, int *cur_inst, + int (*compare)(struct device_node *, int, void *), + void *compare_arg, + struct device_node **dev_node, int *mid) { - char node_str[128]; - - prom_getstring(nd, "device_type", node_str, sizeof(node_str)); - if (strcmp(node_str, "cpu")) + if (strcmp(dp->type, "cpu")) return -ENODEV; - if (!compare(nd, *cur_inst, compare_arg)) { - if (prom_node) - *prom_node = nd; + if (!compare(dp, *cur_inst, compare_arg)) { + if (dev_node) + *dev_node = dp; if (mid) - *mid = get_cpu_mid(nd); + *mid = get_cpu_mid(dp); return 0; } @@ -207,25 +179,18 @@ static int check_cpu_node(int nd, int *c return -ENODEV; } -static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, - int *prom_node, int *mid) +static int __cpu_find_by(int (*compare)(struct device_node *, int, void *), + void *compare_arg, + struct device_node **dev_node, int *mid) { - int nd, cur_inst, err; + struct device_node *dp; + int cur_inst; - nd = prom_root_node; cur_inst = 0; - - err = check_cpu_node(nd, &cur_inst, - compare, compare_arg, - prom_node, mid); - if (err == 0) - return 0; - - nd = prom_getchild(nd); - while ((nd = prom_getsibling(nd)) != 0) { - err = check_cpu_node(nd, &cur_inst, - compare, compare_arg, - prom_node, mid); + for_each_node_by_type(dp, "cpu") { + int err = check_cpu_node(dp, &cur_inst, + compare, compare_arg, + dev_node, mid); if (err == 0) return 0; } @@ -233,7 +198,7 @@ static int __cpu_find_by(int (*compare)( return -ENODEV; } -static int cpu_instance_compare(int nd, int instance, void *_arg) +static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg) { int desired_instance = (int) (long) _arg; @@ -242,27 +207,27 @@ static int cpu_instance_compare(int nd, return -ENODEV; } -int cpu_find_by_instance(int instance, int *prom_node, int *mid) +int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid) { return __cpu_find_by(cpu_instance_compare, (void *)(long)instance, - prom_node, mid); + dev_node, mid); } -static int cpu_mid_compare(int nd, int instance, void *_arg) +static int cpu_mid_compare(struct device_node *dp, int instance, void *_arg) { int desired_mid = (int) (long) _arg; int this_mid; - this_mid = get_cpu_mid(nd); + this_mid = get_cpu_mid(dp); if (this_mid == desired_mid) return 0; return -ENODEV; } -int cpu_find_by_mid(int mid, int *prom_node) +int cpu_find_by_mid(int mid, struct device_node **dev_node) { return __cpu_find_by(cpu_mid_compare, (void *)(long)mid, - prom_node, NULL); + dev_node, NULL); } void __init device_scan(void) @@ -274,50 +239,47 @@ void __init device_scan(void) #ifndef CONFIG_SMP { - int err, cpu_node, def; + struct device_node *dp; + int err, def; - err = cpu_find_by_instance(0, &cpu_node, NULL); + err = cpu_find_by_instance(0, &dp, NULL); if (err) { prom_printf("No cpu nodes, cannot continue\n"); prom_halt(); } - cpu_data(0).clock_tick = prom_getintdefault(cpu_node, - "clock-frequency", - 0); + cpu_data(0).clock_tick = + of_getintprop_default(dp, "clock-frequency", 0); def = ((tlb_type == hypervisor) ? (8 * 1024) : (16 * 1024)); - cpu_data(0).dcache_size = prom_getintdefault(cpu_node, - "dcache-size", - def); + cpu_data(0).dcache_size = of_getintprop_default(dp, + "dcache-size", + def); def = 32; cpu_data(0).dcache_line_size = - prom_getintdefault(cpu_node, "dcache-line-size", - def); + of_getintprop_default(dp, "dcache-line-size", def); def = 16 * 1024; - cpu_data(0).icache_size = prom_getintdefault(cpu_node, - "icache-size", - def); + cpu_data(0).icache_size = of_getintprop_default(dp, + "icache-size", + def); def = 32; cpu_data(0).icache_line_size = - prom_getintdefault(cpu_node, "icache-line-size", - def); + of_getintprop_default(dp, "icache-line-size", def); def = ((tlb_type == hypervisor) ? (3 * 1024 * 1024) : (4 * 1024 * 1024)); - cpu_data(0).ecache_size = prom_getintdefault(cpu_node, - "ecache-size", - def); + cpu_data(0).ecache_size = of_getintprop_default(dp, + "ecache-size", + def); def = 64; cpu_data(0).ecache_line_size = - prom_getintdefault(cpu_node, "ecache-line-size", - def); + of_getintprop_default(dp, "ecache-line-size", def); printk("CPU[0]: Caches " "D[sz(%d):line_sz(%d)] " "I[sz(%d):line_sz(%d)] " diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index c69504a..98e0a8c 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -269,10 +269,6 @@ EXPORT_SYMBOL(ebus_dma_enable); struct linux_ebus *ebus_chain = NULL; -#ifdef CONFIG_SUN_AUXIO -extern void auxio_probe(void); -#endif - static inline void *ebus_alloc(size_t size) { void *mem; @@ -283,77 +279,55 @@ static inline void *ebus_alloc(size_t si return mem; } -static void __init ebus_ranges_init(struct linux_ebus *ebus) -{ - int success; - - ebus->num_ebus_ranges = 0; - success = prom_getproperty(ebus->prom_node, "ranges", - (char *)ebus->ebus_ranges, - sizeof(ebus->ebus_ranges)); - if (success != -1) - ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges)); -} - -static void __init ebus_intmap_init(struct linux_ebus *ebus) -{ - int success; - - ebus->num_ebus_intmap = 0; - success = prom_getproperty(ebus->prom_node, "interrupt-map", - (char *)ebus->ebus_intmap, - sizeof(ebus->ebus_intmap)); - if (success == -1) - return; - - ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap)); - - success = prom_getproperty(ebus->prom_node, "interrupt-map-mask", - (char *)&ebus->ebus_intmask, - sizeof(ebus->ebus_intmask)); - if (success == -1) { - prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__); - prom_halt(); - } -} - int __init ebus_intmap_match(struct linux_ebus *ebus, struct linux_prom_registers *reg, int *interrupt) { + struct linux_prom_ebus_intmap *imap; + struct linux_prom_ebus_intmask *imask; unsigned int hi, lo, irq; - int i; + int i, len, n_imap; + + imap = of_get_property(ebus->prom_node, "interrupt-map", &len); + if (!imap) + return 0; + n_imap = len / sizeof(imap[0]); - if (!ebus->num_ebus_intmap) + imask = of_get_property(ebus->prom_node, "interrupt-map-mask", NULL); + if (!imask) return 0; - hi = reg->which_io & ebus->ebus_intmask.phys_hi; - lo = reg->phys_addr & ebus->ebus_intmask.phys_lo; - irq = *interrupt & ebus->ebus_intmask.interrupt; - for (i = 0; i < ebus->num_ebus_intmap; i++) { - if ((ebus->ebus_intmap[i].phys_hi == hi) && - (ebus->ebus_intmap[i].phys_lo == lo) && - (ebus->ebus_intmap[i].interrupt == irq)) { - *interrupt = ebus->ebus_intmap[i].cinterrupt; + hi = reg->which_io & imask->phys_hi; + lo = reg->phys_addr & imask->phys_lo; + irq = *interrupt & imask->interrupt; + for (i = 0; i < n_imap; i++) { + if ((imap[i].phys_hi == hi) && + (imap[i].phys_lo == lo) && + (imap[i].interrupt == irq)) { + *interrupt = imap[i].cinterrupt; return 0; } } return -1; } -void __init fill_ebus_child(int node, struct linux_prom_registers *preg, - struct linux_ebus_child *dev, int non_standard_regs) +void __init fill_ebus_child(struct device_node *dp, + struct linux_prom_registers *preg, + struct linux_ebus_child *dev, + int non_standard_regs) { - int regs[PROMREG_MAX]; - int irqs[PROMREG_MAX]; + int *regs; + int *irqs; int i, len; - dev->prom_node = node; - prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); - printk(" (%s)", dev->prom_name); + dev->prom_node = dp; + printk(" (%s)", dp->name); - len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); - dev->num_addrs = len / sizeof(regs[0]); + regs = of_get_property(dp, "reg", &len); + if (!regs) + dev->num_addrs = 0; + else + dev->num_addrs = len / sizeof(regs[0]); if (non_standard_regs) { /* This is to handle reg properties which are not @@ -370,21 +344,21 @@ void __init fill_ebus_child(int node, st int rnum = regs[i]; if (rnum >= dev->parent->num_addrs) { prom_printf("UGH: property for %s was %d, need < %d\n", - dev->prom_name, len, dev->parent->num_addrs); - panic(__FUNCTION__); + dp->name, len, dev->parent->num_addrs); + prom_halt(); } dev->resource[i].start = dev->parent->resource[i].start; dev->resource[i].end = dev->parent->resource[i].end; dev->resource[i].flags = IORESOURCE_MEM; - dev->resource[i].name = dev->prom_name; + dev->resource[i].name = dp->name; } } for (i = 0; i < PROMINTR_MAX; i++) dev->irqs[i] = PCI_IRQ_NONE; - len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); - if ((len == -1) || (len == 0)) { + irqs = of_get_property(dp, "interrupts", &len); + if (!irqs) { dev->num_irqs = 0; /* * Oh, well, some PROMs don't export interrupts @@ -392,8 +366,8 @@ void __init fill_ebus_child(int node, st * * Be smart about PS/2 keyboard and mouse. */ - if (!strcmp(dev->parent->prom_name, "8042")) { - if (!strcmp(dev->prom_name, "kb_ps2")) { + if (!strcmp(dev->parent->prom_node->name, "8042")) { + if (!strcmp(dev->prom_node->name, "kb_ps2")) { dev->num_irqs = 1; dev->irqs[0] = dev->parent->irqs[0]; } else { @@ -423,32 +397,32 @@ void __init fill_ebus_child(int node, st static int __init child_regs_nonstandard(struct linux_ebus_device *dev) { - if (!strcmp(dev->prom_name, "i2c") || - !strcmp(dev->prom_name, "SUNW,lombus")) + if (!strcmp(dev->prom_node->name, "i2c") || + !strcmp(dev->prom_node->name, "SUNW,lombus")) return 1; return 0; } -void __init fill_ebus_device(int node, struct linux_ebus_device *dev) +void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) { - struct linux_prom_registers regs[PROMREG_MAX]; + struct linux_prom_registers *regs; struct linux_ebus_child *child; - int irqs[PROMINTR_MAX]; + int *irqs; int i, n, len; - dev->prom_node = node; - prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); - printk(" [%s", dev->prom_name); + dev->prom_node = dp; + + printk(" [%s", dp->name); - len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); - if (len == -1) { + regs = of_get_property(dp, "reg", &len); + if (!regs) { dev->num_addrs = 0; goto probe_interrupts; } if (len % sizeof(struct linux_prom_registers)) { prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", - dev->prom_name, len, + dev->prom_node->name, len, (int)sizeof(struct linux_prom_registers)); prom_halt(); } @@ -466,7 +440,7 @@ void __init fill_ebus_device(int node, s dev->resource[i].end = (dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL); dev->resource[i].flags = IORESOURCE_MEM; - dev->resource[i].name = dev->prom_name; + dev->resource[i].name = dev->prom_node->name; request_resource(&dev->bus->self->resource[n], &dev->resource[i]); } @@ -475,8 +449,8 @@ probe_interrupts: for (i = 0; i < PROMINTR_MAX; i++) dev->irqs[i] = PCI_IRQ_NONE; - len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); - if ((len == -1) || (len == 0)) { + irqs = of_get_property(dp, "interrupts", &len); + if (!irqs) { dev->num_irqs = 0; } else { dev->num_irqs = len / sizeof(irqs[0]); @@ -497,7 +471,18 @@ probe_interrupts: } } - if ((node = prom_getchild(node))) { + dev->ofdev.node = dp; + dev->ofdev.dev.parent = &dev->bus->ofdev.dev; + dev->ofdev.dev.bus = &ebus_bus_type; + strcpy(dev->ofdev.dev.bus_id, dp->path_component_name); + + /* Register with core */ + if (of_device_register(&dev->ofdev) != 0) + printk(KERN_DEBUG "ebus: device registration error for %s!\n", + dev->ofdev.dev.bus_id); + + dp = dp->child; + if (dp) { printk(" ->"); dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); @@ -505,18 +490,18 @@ probe_interrupts: child->next = NULL; child->parent = dev; child->bus = dev->bus; - fill_ebus_child(node, ®s[0], - child, child_regs_nonstandard(dev)); + fill_ebus_child(dp, regs, child, + child_regs_nonstandard(dev)); - while ((node = prom_getsibling(node)) != 0) { + while ((dp = dp->sibling) != NULL) { child->next = ebus_alloc(sizeof(struct linux_ebus_child)); child = child->next; child->next = NULL; child->parent = dev; child->bus = dev->bus; - fill_ebus_child(node, ®s[0], - child, child_regs_nonstandard(dev)); + fill_ebus_child(dp, regs, child, + child_regs_nonstandard(dev)); } } printk("]"); @@ -543,7 +528,8 @@ void __init ebus_init(void) struct linux_ebus *ebus; struct pci_dev *pdev; struct pcidev_cookie *cookie; - int nd, ebusnd, is_rio; + struct device_node *dp; + int is_rio; int num_ebus = 0; pdev = find_next_ebus(NULL, &is_rio); @@ -553,20 +539,22 @@ void __init ebus_init(void) } cookie = pdev->sysdata; - ebusnd = cookie->prom_node; + dp = cookie->prom_node; ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); ebus->next = NULL; ebus->is_rio = is_rio; - while (ebusnd) { + while (dp) { + struct device_node *child; + /* SUNW,pci-qfe uses four empty ebuses on it. I think we should not consider them here, as they have half of the properties this code expects and once we do PCI hot-plug, we'd have to tweak with the ebus_chain in the runtime after initialization. -jj */ - if (!prom_getchild (ebusnd)) { + if (!dp->child) { pdev = find_next_ebus(pdev, &is_rio); if (!pdev) { if (ebus == ebus_chain) { @@ -578,22 +566,29 @@ void __init ebus_init(void) } ebus->is_rio = is_rio; cookie = pdev->sysdata; - ebusnd = cookie->prom_node; + dp = cookie->prom_node; continue; } printk("ebus%d:", num_ebus); - prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name)); ebus->index = num_ebus; - ebus->prom_node = ebusnd; + ebus->prom_node = dp; ebus->self = pdev; ebus->parent = pbm = cookie->pbm; - ebus_ranges_init(ebus); - ebus_intmap_init(ebus); + ebus->ofdev.node = dp; + ebus->ofdev.dev.parent = &pdev->dev; + ebus->ofdev.dev.bus = &ebus_bus_type; + strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name); - nd = prom_getchild(ebusnd); - if (!nd) + /* Register with core */ + if (of_device_register(&ebus->ofdev) != 0) + printk(KERN_DEBUG "ebus: device registration error for %s!\n", + ebus->ofdev.dev.bus_id); + + + child = dp->child; + if (!child) goto next_ebus; ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device)); @@ -602,16 +597,16 @@ void __init ebus_init(void) dev->next = NULL; dev->children = NULL; dev->bus = ebus; - fill_ebus_device(nd, dev); + fill_ebus_device(child, dev); - while ((nd = prom_getsibling(nd)) != 0) { + while ((child = child->sibling) != NULL) { dev->next = ebus_alloc(sizeof(struct linux_ebus_device)); dev = dev->next; dev->next = NULL; dev->children = NULL; dev->bus = ebus; - fill_ebus_device(nd, dev); + fill_ebus_device(child, dev); } next_ebus: @@ -622,7 +617,7 @@ void __init ebus_init(void) break; cookie = pdev->sysdata; - ebusnd = cookie->prom_node; + dp = cookie->prom_node; ebus->next = ebus_alloc(sizeof(struct linux_ebus)); ebus = ebus->next; @@ -631,8 +626,4 @@ void __init ebus_init(void) ++num_ebus; } pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */ - -#ifdef CONFIG_SUN_AUXIO - auxio_probe(); -#endif } diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 6d0b3ed..be85ce2 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -22,6 +22,7 @@ #include #include #include #include +#include #define curptr g6 @@ -431,20 +432,16 @@ do_ivec: membar #Sync sethi %hi(ivector_table), %g2 - sllx %g3, 5, %g3 + sllx %g3, 3, %g3 or %g2, %lo(ivector_table), %g2 add %g2, %g3, %g3 - ldub [%g3 + 0x04], %g4 /* pil */ - mov 1, %g2 - sllx %g2, %g4, %g2 - sllx %g4, 2, %g4 TRAP_LOAD_IRQ_WORK(%g6, %g1) - lduw [%g6 + %g4], %g5 /* g5 = irq_work(cpu, pil) */ + lduw [%g6], %g5 /* g5 = irq_work(cpu) */ stw %g5, [%g3 + 0x00] /* bucket->irq_chain = g5 */ - stw %g3, [%g6 + %g4] /* irq_work(cpu, pil) = bucket */ - wr %g2, 0x0, %set_softint + stw %g3, [%g6] /* irq_work(cpu) = bucket */ + wr %g0, 1 << PIL_DEVICE_IRQ, %set_softint retry do_ivec_xcall: mov 0x50, %g1 diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 11e645c..cc89b06 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -22,6 +22,7 @@ #include #include #include #include +#include #include #include @@ -33,6 +34,7 @@ #include #include #include #include +#include #include #include #include @@ -42,10 +44,6 @@ #include #include #include -#ifdef CONFIG_SMP -static void distribute_irqs(void); -#endif - /* UPA nodes send interrupt packet to UltraSparc with first data reg * value low 5 (7 on Starfire) bits holding the IRQ identifier being * delivered. We must translate this into a non-vector IRQ so we can @@ -57,10 +55,29 @@ #endif * The IVEC handler does not need to act atomically, the PIL dispatch * code uses CAS to get an atomic snapshot of the list and clear it * at the same time. + * + * If you make changes to ino_bucket, please update hand coded assembler + * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S */ +struct ino_bucket { + /* Next handler in per-CPU IRQ worklist. We know that + * bucket pointers have the high 32-bits clear, so to + * save space we only store the bits we need. + */ +/*0x00*/unsigned int irq_chain; + /* Virtual interrupt number assigned to this INO. */ +/*0x04*/unsigned int virt_irq; +}; + +#define NUM_IVECS (IMAP_INR + 1) struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BYTES))); +#define __irq_ino(irq) \ + (((struct ino_bucket *)(unsigned long)(irq)) - &ivector_table[0]) +#define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq)) +#define __irq(bucket) ((unsigned int)(unsigned long)(bucket)) + /* This has to be in the main kernel image, it cannot be * turned into per-cpu data. The reason is that the main * kernel image is locked into the TLB and this structure @@ -68,71 +85,82 @@ struct ino_bucket ivector_table[NUM_IVEC * access to this structure takes a TLB miss it could cause * the 5-level sparc v9 trap stack to overflow. */ -struct irq_work_struct { - unsigned int irq_worklists[16]; -}; -struct irq_work_struct __irq_work[NR_CPUS]; -#define irq_work(__cpu, __pil) &(__irq_work[(__cpu)].irq_worklists[(__pil)]) +#define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) -static struct irqaction *irq_action[NR_IRQS+1]; +static unsigned int virt_to_real_irq_table[NR_IRQS]; +static unsigned char virt_irq_cur = 1; -/* This only synchronizes entities which modify IRQ handler - * state and some selected user-level spots that want to - * read things in the table. IRQ handler processing orders - * its' accesses such that no locking is needed. - */ -static DEFINE_SPINLOCK(irq_action_lock); +static unsigned char virt_irq_alloc(unsigned int real_irq) +{ + unsigned char ent; + + BUILD_BUG_ON(NR_IRQS >= 256); + + ent = virt_irq_cur; + if (ent >= NR_IRQS) { + printk(KERN_ERR "IRQ: Out of virtual IRQs.\n"); + return 0; + } + + virt_irq_cur = ent + 1; + virt_to_real_irq_table[ent] = real_irq; -static void register_irq_proc (unsigned int irq); + return ent; +} + +#if 0 /* Currently unused. */ +static unsigned char real_to_virt_irq(unsigned int real_irq) +{ + struct ino_bucket *bucket = __bucket(real_irq); + + return bucket->virt_irq; +} +#endif + +static unsigned int virt_to_real_irq(unsigned char virt_irq) +{ + return virt_to_real_irq_table[virt_irq]; +} /* - * Upper 2b of irqaction->flags holds the ino. - * irqaction->mask holds the smp affinity information. + * /proc/interrupts printing: */ -#define put_ino_in_irqaction(action, irq) \ - action->flags &= 0xffffffffffffUL; \ - if (__bucket(irq) == &pil0_dummy_bucket) \ - action->flags |= 0xdeadUL << 48; \ - else \ - action->flags |= __irq_ino(irq) << 48; -#define get_ino_in_irqaction(action) (action->flags >> 48) - -#define put_smpaff_in_irqaction(action, smpaff) (action)->mask = (smpaff) -#define get_smpaff_in_irqaction(action) ((action)->mask) int show_interrupts(struct seq_file *p, void *v) { + int i = *(loff_t *) v, j; + struct irqaction * action; unsigned long flags; - int i = *(loff_t *) v; - struct irqaction *action; -#ifdef CONFIG_SMP - int j; -#endif - spin_lock_irqsave(&irq_action_lock, flags); - if (i <= NR_IRQS) { - if (!(action = *(i + irq_action))) - goto out_unlock; - seq_printf(p, "%3d: ", i); + if (i == 0) { + seq_printf(p, " "); + for_each_online_cpu(j) + seq_printf(p, "CPU%d ",j); + seq_putc(p, '\n'); + } + + if (i < NR_IRQS) { + spin_lock_irqsave(&irq_desc[i].lock, flags); + action = irq_desc[i].action; + if (!action) + goto skip; + seq_printf(p, "%3d: ",i); #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); #else - for_each_online_cpu(j) { - seq_printf(p, "%10u ", - kstat_cpu(j).irqs[i]); - } + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); #endif - seq_printf(p, " %s:%lx", action->name, - get_ino_in_irqaction(action)); - for (action = action->next; action; action = action->next) { - seq_printf(p, ", %s:%lx", action->name, - get_ino_in_irqaction(action)); - } + seq_printf(p, " %9s", irq_desc[i].handler->typename); + seq_printf(p, " %s", action->name); + + for (action=action->next; action; action = action->next) + seq_printf(p, ", %s", action->name); + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } -out_unlock: - spin_unlock_irqrestore(&irq_action_lock, flags); - return 0; } @@ -173,694 +201,367 @@ static unsigned int sun4u_compute_tid(un return tid; } -/* Now these are always passed a true fully specified sun4u INO. */ -void enable_irq(unsigned int irq) -{ - struct ino_bucket *bucket = __bucket(irq); - unsigned long imap, cpuid; - - imap = bucket->imap; - if (imap == 0UL) - return; - - preempt_disable(); +struct irq_handler_data { + unsigned long iclr; + unsigned long imap; - /* This gets the physical processor ID, even on uniprocessor, - * so we can always program the interrupt target correctly. - */ - cpuid = real_hard_smp_processor_id(); - - if (tlb_type == hypervisor) { - unsigned int ino = __irq_ino(irq); - int err; - - err = sun4v_intr_settarget(ino, cpuid); - if (err != HV_EOK) - printk("sun4v_intr_settarget(%x,%lu): err(%d)\n", - ino, cpuid, err); - err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED); - if (err != HV_EOK) - printk("sun4v_intr_setenabled(%x): err(%d)\n", - ino, err); - } else { - unsigned int tid = sun4u_compute_tid(imap, cpuid); - - /* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product - * of this SYSIO's preconfigured IGN in the SYSIO Control - * Register, the hardware just mirrors that value here. - * However for Graphics and UPA Slave devices the full - * IMAP_INR field can be set by the programmer here. - * - * Things like FFB can now be handled via the new IRQ - * mechanism. - */ - upa_writel(tid | IMAP_VALID, imap); - } - - preempt_enable(); -} + void (*pre_handler)(unsigned int, void *, void *); + void *pre_handler_arg1; + void *pre_handler_arg2; +}; -/* This now gets passed true ino's as well. */ -void disable_irq(unsigned int irq) +static inline struct ino_bucket *virt_irq_to_bucket(unsigned int virt_irq) { - struct ino_bucket *bucket = __bucket(irq); - unsigned long imap; - - imap = bucket->imap; - if (imap != 0UL) { - if (tlb_type == hypervisor) { - unsigned int ino = __irq_ino(irq); - int err; - - err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); - if (err != HV_EOK) - printk("sun4v_intr_setenabled(%x): " - "err(%d)\n", ino, err); - } else { - u32 tmp; - - /* NOTE: We do not want to futz with the IRQ clear registers - * and move the state to IDLE, the SCSI code does call - * disable_irq() to assure atomicity in the queue cmd - * SCSI adapter driver code. Thus we'd lose interrupts. - */ - tmp = upa_readl(imap); - tmp &= ~IMAP_VALID; - upa_writel(tmp, imap); - } - } -} + unsigned int real_irq = virt_to_real_irq(virt_irq); + struct ino_bucket *bucket = NULL; -/* The timer is the one "weird" interrupt which is generated by - * the CPU %tick register and not by some normal vectored interrupt - * source. To handle this special case, we use this dummy INO bucket. - */ -static struct irq_desc pil0_dummy_desc; -static struct ino_bucket pil0_dummy_bucket = { - .irq_info = &pil0_dummy_desc, -}; + if (likely(real_irq)) + bucket = __bucket(real_irq); -static void build_irq_error(const char *msg, unsigned int ino, int pil, int inofixup, - unsigned long iclr, unsigned long imap, - struct ino_bucket *bucket) -{ - prom_printf("IRQ: INO %04x (%d:%016lx:%016lx) --> " - "(%d:%d:%016lx:%016lx), halting...\n", - ino, bucket->pil, bucket->iclr, bucket->imap, - pil, inofixup, iclr, imap); - prom_halt(); + return bucket; } -unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap) +#ifdef CONFIG_SMP +static int irq_choose_cpu(unsigned int virt_irq) { - struct ino_bucket *bucket; - int ino; + cpumask_t mask = irq_affinity[virt_irq]; + int cpuid; - if (pil == 0) { - if (iclr != 0UL || imap != 0UL) { - prom_printf("Invalid dummy bucket for PIL0 (%lx:%lx)\n", - iclr, imap); - prom_halt(); - } - return __irq(&pil0_dummy_bucket); - } + if (cpus_equal(mask, CPU_MASK_ALL)) { + static int irq_rover; + static DEFINE_SPINLOCK(irq_rover_lock); + unsigned long flags; - BUG_ON(tlb_type == hypervisor); + /* Round-robin distribution... */ + do_round_robin: + spin_lock_irqsave(&irq_rover_lock, flags); - /* RULE: Both must be specified in all other cases. */ - if (iclr == 0UL || imap == 0UL) { - prom_printf("Invalid build_irq %d %d %016lx %016lx\n", - pil, inofixup, iclr, imap); - prom_halt(); - } - - ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; - if (ino > NUM_IVECS) { - prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)\n", - ino, pil, inofixup, iclr, imap); - prom_halt(); - } + while (!cpu_online(irq_rover)) { + if (++irq_rover >= NR_CPUS) + irq_rover = 0; + } + cpuid = irq_rover; + do { + if (++irq_rover >= NR_CPUS) + irq_rover = 0; + } while (!cpu_online(irq_rover)); - bucket = &ivector_table[ino]; - if (bucket->flags & IBF_ACTIVE) - build_irq_error("IRQ: Trying to build active INO bucket.\n", - ino, pil, inofixup, iclr, imap, bucket); + spin_unlock_irqrestore(&irq_rover_lock, flags); + } else { + cpumask_t tmp; - if (bucket->irq_info) { - if (bucket->imap != imap || bucket->iclr != iclr) - build_irq_error("IRQ: Trying to reinit INO bucket.\n", - ino, pil, inofixup, iclr, imap, bucket); + cpus_and(tmp, cpu_online_map, mask); - goto out; - } + if (cpus_empty(tmp)) + goto do_round_robin; - bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC); - if (!bucket->irq_info) { - prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n"); - prom_halt(); + cpuid = first_cpu(tmp); } - /* Ok, looks good, set it up. Don't touch the irq_chain or - * the pending flag. - */ - bucket->imap = imap; - bucket->iclr = iclr; - bucket->pil = pil; - bucket->flags = 0; - -out: - return __irq(bucket); + return cpuid; } - -unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags) +#else +static int irq_choose_cpu(unsigned int virt_irq) { - struct ino_bucket *bucket; - unsigned long sysino; + return real_hard_smp_processor_id(); +} +#endif - sysino = sun4v_devino_to_sysino(devhandle, devino); +static void sun4u_irq_enable(unsigned int virt_irq) +{ + irq_desc_t *desc = irq_desc + virt_irq; + struct irq_handler_data *data = desc->handler_data; - bucket = &ivector_table[sysino]; + if (likely(data)) { + unsigned long cpuid, imap; + unsigned int tid; - /* Catch accidental accesses to these things. IMAP/ICLR handling - * is done by hypervisor calls on sun4v platforms, not by direct - * register accesses. - * - * But we need to make them look unique for the disable_irq() logic - * in free_irq(). - */ - bucket->imap = ~0UL - sysino; - bucket->iclr = ~0UL - sysino; + cpuid = irq_choose_cpu(virt_irq); + imap = data->imap; - bucket->pil = pil; - bucket->flags = flags; + tid = sun4u_compute_tid(imap, cpuid); - bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC); - if (!bucket->irq_info) { - prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n"); - prom_halt(); + upa_writel(tid | IMAP_VALID, imap); } - - return __irq(bucket); } -static void atomic_bucket_insert(struct ino_bucket *bucket) +static void sun4u_irq_disable(unsigned int virt_irq) { - unsigned long pstate; - unsigned int *ent; + irq_desc_t *desc = irq_desc + virt_irq; + struct irq_handler_data *data = desc->handler_data; - __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); - __asm__ __volatile__("wrpr %0, %1, %%pstate" - : : "r" (pstate), "i" (PSTATE_IE)); - ent = irq_work(smp_processor_id(), bucket->pil); - bucket->irq_chain = *ent; - *ent = __irq(bucket); - __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); -} + if (likely(data)) { + unsigned long imap = data->imap; + u32 tmp = upa_readl(imap); -static int check_irq_sharing(int pil, unsigned long irqflags) -{ - struct irqaction *action, *tmp; - - action = *(irq_action + pil); - if (action) { - if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { - for (tmp = action; tmp->next; tmp = tmp->next) - ; - } else { - return -EBUSY; - } + tmp &= ~IMAP_VALID; + upa_writel(tmp, imap); } - return 0; } -static void append_irq_action(int pil, struct irqaction *action) +static void sun4u_irq_end(unsigned int virt_irq) { - struct irqaction **pp = irq_action + pil; + irq_desc_t *desc = irq_desc + virt_irq; + struct irq_handler_data *data = desc->handler_data; - while (*pp) - pp = &((*pp)->next); - *pp = action; + if (likely(data)) + upa_writel(ICLR_IDLE, data->iclr); } -static struct irqaction *get_action_slot(struct ino_bucket *bucket) +static void sun4v_irq_enable(unsigned int virt_irq) { - struct irq_desc *desc = bucket->irq_info; - int max_irq, i; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; - max_irq = 1; - if (bucket->flags & IBF_PCI) - max_irq = MAX_IRQ_DESC_ACTION; - for (i = 0; i < max_irq; i++) { - struct irqaction *p = &desc->action[i]; - u32 mask = (1 << i); + if (likely(bucket)) { + unsigned long cpuid; + int err; - if (desc->action_active_mask & mask) - continue; + cpuid = irq_choose_cpu(virt_irq); - desc->action_active_mask |= mask; - return p; + err = sun4v_intr_settarget(ino, cpuid); + if (err != HV_EOK) + printk("sun4v_intr_settarget(%x,%lu): err(%d)\n", + ino, cpuid, err); + err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED); + if (err != HV_EOK) + printk("sun4v_intr_setenabled(%x): err(%d)\n", + ino, err); } - return NULL; } -int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char *name, void *dev_id) +static void sun4v_irq_disable(unsigned int virt_irq) { - struct irqaction *action; - struct ino_bucket *bucket = __bucket(irq); - unsigned long flags; - int pending = 0; - - if (unlikely(!handler)) - return -EINVAL; - - if (unlikely(!bucket->irq_info)) - return -ENODEV; - - if ((bucket != &pil0_dummy_bucket) && (irqflags & SA_SAMPLE_RANDOM)) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. In SA_STATIC_ALLOC case, - * random driver's kmalloc will fail, but it is safe. - * If already initialized, random driver will not reinit. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(irq); - } - - spin_lock_irqsave(&irq_action_lock, flags); + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; - if (check_irq_sharing(bucket->pil, irqflags)) { - spin_unlock_irqrestore(&irq_action_lock, flags); - return -EBUSY; - } - - action = get_action_slot(bucket); - if (!action) { - spin_unlock_irqrestore(&irq_action_lock, flags); - return -ENOMEM; - } - - bucket->flags |= IBF_ACTIVE; - pending = 0; - if (bucket != &pil0_dummy_bucket) { - pending = bucket->pending; - if (pending) - bucket->pending = 0; - } - - action->handler = handler; - action->flags = irqflags; - action->name = name; - action->next = NULL; - action->dev_id = dev_id; - put_ino_in_irqaction(action, irq); - put_smpaff_in_irqaction(action, CPU_MASK_NONE); - - append_irq_action(bucket->pil, action); - - enable_irq(irq); + if (likely(bucket)) { + int err; - /* We ate the IVEC already, this makes sure it does not get lost. */ - if (pending) { - atomic_bucket_insert(bucket); - set_softint(1 << bucket->pil); + err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); + if (err != HV_EOK) + printk("sun4v_intr_setenabled(%x): " + "err(%d)\n", ino, err); } - - spin_unlock_irqrestore(&irq_action_lock, flags); - - if (bucket != &pil0_dummy_bucket) - register_irq_proc(__irq_ino(irq)); - -#ifdef CONFIG_SMP - distribute_irqs(); -#endif - return 0; } -EXPORT_SYMBOL(request_irq); - -static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id) +static void sun4v_irq_end(unsigned int virt_irq) { - struct ino_bucket *bucket = __bucket(irq); - struct irqaction *action, **pp; - - pp = irq_action + bucket->pil; - action = *pp; - if (unlikely(!action)) - return NULL; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; - if (unlikely(!action->handler)) { - printk("Freeing free IRQ %d\n", bucket->pil); - return NULL; - } + if (likely(bucket)) { + int err; - while (action && action->dev_id != dev_id) { - pp = &action->next; - action = *pp; + err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); + if (err != HV_EOK) + printk("sun4v_intr_setstate(%x): " + "err(%d)\n", ino, err); } - - if (likely(action)) - *pp = action->next; - - return action; } -void free_irq(unsigned int irq, void *dev_id) +static void run_pre_handler(unsigned int virt_irq) { - struct irqaction *action; - struct ino_bucket *bucket; - unsigned long flags; - - spin_lock_irqsave(&irq_action_lock, flags); - - action = unlink_irq_action(irq, dev_id); - - spin_unlock_irqrestore(&irq_action_lock, flags); - - if (unlikely(!action)) - return; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + irq_desc_t *desc = irq_desc + virt_irq; + struct irq_handler_data *data = desc->handler_data; - synchronize_irq(irq); + if (likely(data->pre_handler)) { + data->pre_handler(__irq_ino(__irq(bucket)), + data->pre_handler_arg1, + data->pre_handler_arg2); + } +} - spin_lock_irqsave(&irq_action_lock, flags); +static struct hw_interrupt_type sun4u_irq = { + .typename = "sun4u", + .enable = sun4u_irq_enable, + .disable = sun4u_irq_disable, + .end = sun4u_irq_end, +}; - bucket = __bucket(irq); - if (bucket != &pil0_dummy_bucket) { - struct irq_desc *desc = bucket->irq_info; - int ent, i; +static struct hw_interrupt_type sun4u_irq_ack = { + .typename = "sun4u+ack", + .enable = sun4u_irq_enable, + .disable = sun4u_irq_disable, + .ack = run_pre_handler, + .end = sun4u_irq_end, +}; - for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) { - struct irqaction *p = &desc->action[i]; +static struct hw_interrupt_type sun4v_irq = { + .typename = "sun4v", + .enable = sun4v_irq_enable, + .disable = sun4v_irq_disable, + .end = sun4v_irq_end, +}; - if (p == action) { - desc->action_active_mask &= ~(1 << i); - break; - } - } +static struct hw_interrupt_type sun4v_irq_ack = { + .typename = "sun4v+ack", + .enable = sun4v_irq_enable, + .disable = sun4v_irq_disable, + .ack = run_pre_handler, + .end = sun4v_irq_end, +}; - if (!desc->action_active_mask) { - unsigned long imap = bucket->imap; - - /* This unique interrupt source is now inactive. */ - bucket->flags &= ~IBF_ACTIVE; - - /* See if any other buckets share this bucket's IMAP - * and are still active. - */ - for (ent = 0; ent < NUM_IVECS; ent++) { - struct ino_bucket *bp = &ivector_table[ent]; - if (bp != bucket && - bp->imap == imap && - (bp->flags & IBF_ACTIVE) != 0) - break; - } +void irq_install_pre_handler(int virt_irq, + void (*func)(unsigned int, void *, void *), + void *arg1, void *arg2) +{ + irq_desc_t *desc = irq_desc + virt_irq; + struct irq_handler_data *data = desc->handler_data; - /* Only disable when no other sub-irq levels of - * the same IMAP are active. - */ - if (ent == NUM_IVECS) - disable_irq(irq); - } - } + data->pre_handler = func; + data->pre_handler_arg1 = arg1; + data->pre_handler_arg2 = arg2; - spin_unlock_irqrestore(&irq_action_lock, flags); + desc->handler = (desc->handler == &sun4u_irq ? + &sun4u_irq_ack : &sun4v_irq_ack); } -EXPORT_SYMBOL(free_irq); - -#ifdef CONFIG_SMP -void synchronize_irq(unsigned int irq) +unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) { - struct ino_bucket *bucket = __bucket(irq); - -#if 0 - /* The following is how I wish I could implement this. - * Unfortunately the ICLR registers are read-only, you can - * only write ICLR_foo values to them. To get the current - * IRQ status you would need to get at the IRQ diag registers - * in the PCI/SBUS controller and the layout of those vary - * from one controller to the next, sigh... -DaveM - */ - unsigned long iclr = bucket->iclr; - - while (1) { - u32 tmp = upa_readl(iclr); - - if (tmp == ICLR_TRANSMIT || - tmp == ICLR_PENDING) { - cpu_relax(); - continue; - } - break; - } -#else - /* So we have to do this with a INPROGRESS bit just like x86. */ - while (bucket->flags & IBF_INPROGRESS) - cpu_relax(); -#endif -} -#endif /* CONFIG_SMP */ - -static void process_bucket(int irq, struct ino_bucket *bp, struct pt_regs *regs) -{ - struct irq_desc *desc = bp->irq_info; - unsigned char flags = bp->flags; - u32 action_mask, i; - int random; + struct ino_bucket *bucket; + struct irq_handler_data *data; + irq_desc_t *desc; + int ino; - bp->flags |= IBF_INPROGRESS; + BUG_ON(tlb_type == hypervisor); - if (unlikely(!(flags & IBF_ACTIVE))) { - bp->pending = 1; - goto out; + ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; + bucket = &ivector_table[ino]; + if (!bucket->virt_irq) { + bucket->virt_irq = virt_irq_alloc(__irq(bucket)); + irq_desc[bucket->virt_irq].handler = &sun4u_irq; } - if (desc->pre_handler) - desc->pre_handler(bp, - desc->pre_handler_arg1, - desc->pre_handler_arg2); - - action_mask = desc->action_active_mask; - random = 0; - for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) { - struct irqaction *p = &desc->action[i]; - u32 mask = (1 << i); - - if (!(action_mask & mask)) - continue; - - action_mask &= ~mask; - - if (p->handler(__irq(bp), p->dev_id, regs) == IRQ_HANDLED) - random |= p->flags; + desc = irq_desc + bucket->virt_irq; + if (unlikely(desc->handler_data)) + goto out; - if (!action_mask) - break; + data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); + if (unlikely(!data)) { + prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); + prom_halt(); } - if (bp->pil != 0) { - if (tlb_type == hypervisor) { - unsigned int ino = __irq_ino(bp); - int err; - - err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); - if (err != HV_EOK) - printk("sun4v_intr_setstate(%x): " - "err(%d)\n", ino, err); - } else { - upa_writel(ICLR_IDLE, bp->iclr); - } + desc->handler_data = data; + + data->imap = imap; + data->iclr = iclr; - /* Test and add entropy */ - if (random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - } out: - bp->flags &= ~IBF_INPROGRESS; + return bucket->virt_irq; } -void handler_irq(int irq, struct pt_regs *regs) +unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) { - struct ino_bucket *bp; - int cpu = smp_processor_id(); + struct ino_bucket *bucket; + struct irq_handler_data *data; + unsigned long sysino; + irq_desc_t *desc; -#ifndef CONFIG_SMP - /* - * Check for TICK_INT on level 14 softint. - */ - { - unsigned long clr_mask = 1 << irq; - unsigned long tick_mask = tick_ops->softint_mask; + BUG_ON(tlb_type != hypervisor); - if ((irq == 14) && (get_softint() & tick_mask)) { - irq = 0; - clr_mask = tick_mask; - } - clear_softint(clr_mask); + sysino = sun4v_devino_to_sysino(devhandle, devino); + bucket = &ivector_table[sysino]; + if (!bucket->virt_irq) { + bucket->virt_irq = virt_irq_alloc(__irq(bucket)); + irq_desc[bucket->virt_irq].handler = &sun4v_irq; } -#else - clear_softint(1 << irq); -#endif - irq_enter(); - kstat_this_cpu.irqs[irq]++; - - /* Sliiiick... */ -#ifndef CONFIG_SMP - bp = ((irq != 0) ? - __bucket(xchg32(irq_work(cpu, irq), 0)) : - &pil0_dummy_bucket); -#else - bp = __bucket(xchg32(irq_work(cpu, irq), 0)); -#endif - while (bp) { - struct ino_bucket *nbp = __bucket(bp->irq_chain); + desc = irq_desc + bucket->virt_irq; + if (unlikely(desc->handler_data)) + goto out; - bp->irq_chain = 0; - process_bucket(irq, bp, regs); - bp = nbp; + data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); + if (unlikely(!data)) { + prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); + prom_halt(); } - irq_exit(); -} + desc->handler_data = data; -#ifdef CONFIG_BLK_DEV_FD -extern irqreturn_t floppy_interrupt(int, void *, struct pt_regs *); + /* Catch accidental accesses to these things. IMAP/ICLR handling + * is done by hypervisor calls on sun4v platforms, not by direct + * register accesses. + */ + data->imap = ~0UL; + data->iclr = ~0UL; -/* XXX No easy way to include asm/floppy.h XXX */ -extern unsigned char *pdma_vaddr; -extern unsigned long pdma_size; -extern volatile int doing_pdma; -extern unsigned long fdc_status; +out: + return bucket->virt_irq; +} -irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs) +void hw_resend_irq(struct hw_interrupt_type *handler, unsigned int virt_irq) { - if (likely(doing_pdma)) { - void __iomem *stat = (void __iomem *) fdc_status; - unsigned char *vaddr = pdma_vaddr; - unsigned long size = pdma_size; - u8 val; - - while (size) { - val = readb(stat); - if (unlikely(!(val & 0x80))) { - pdma_vaddr = vaddr; - pdma_size = size; - return IRQ_HANDLED; - } - if (unlikely(!(val & 0x20))) { - pdma_vaddr = vaddr; - pdma_size = size; - doing_pdma = 0; - goto main_interrupt; - } - if (val & 0x40) { - /* read */ - *vaddr++ = readb(stat + 1); - } else { - unsigned char data = *vaddr++; - - /* write */ - writeb(data, stat + 1); - } - size--; - } - - pdma_vaddr = vaddr; - pdma_size = size; - - /* Send Terminal Count pulse to floppy controller. */ - val = readb(auxio_register); - val |= AUXIO_AUX1_FTCNT; - writeb(val, auxio_register); - val &= ~AUXIO_AUX1_FTCNT; - writeb(val, auxio_register); - - doing_pdma = 0; - } + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned long pstate; + unsigned int *ent; -main_interrupt: - return floppy_interrupt(irq, dev_cookie, regs); + __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); + __asm__ __volatile__("wrpr %0, %1, %%pstate" + : : "r" (pstate), "i" (PSTATE_IE)); + ent = irq_work(smp_processor_id()); + bucket->irq_chain = *ent; + *ent = __irq(bucket); + set_softint(1 << PIL_DEVICE_IRQ); + __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); } -EXPORT_SYMBOL(sparc_floppy_irq); -#endif -/* We really don't need these at all on the Sparc. We only have - * stubs here because they are exported to modules. - */ -unsigned long probe_irq_on(void) +void ack_bad_irq(unsigned int virt_irq) { - return 0; -} + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = 0xdeadbeef; -EXPORT_SYMBOL(probe_irq_on); + if (bucket) + ino = bucket - &ivector_table[0]; -int probe_irq_off(unsigned long mask) -{ - return 0; + printk(KERN_CRIT "Unexpected IRQ from ino[%x] virt_irq[%u]\n", + ino, virt_irq); } -EXPORT_SYMBOL(probe_irq_off); +#ifndef CONFIG_SMP +extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *); -#ifdef CONFIG_SMP -static int retarget_one_irq(struct irqaction *p, int goal_cpu) +void timer_irq(int irq, struct pt_regs *regs) { - struct ino_bucket *bucket = get_ino_in_irqaction(p) + ivector_table; + unsigned long clr_mask = 1 << irq; + unsigned long tick_mask = tick_ops->softint_mask; - while (!cpu_online(goal_cpu)) { - if (++goal_cpu >= NR_CPUS) - goal_cpu = 0; + if (get_softint() & tick_mask) { + irq = 0; + clr_mask = tick_mask; } + clear_softint(clr_mask); - if (tlb_type == hypervisor) { - unsigned int ino = __irq_ino(bucket); - - sun4v_intr_settarget(ino, goal_cpu); - sun4v_intr_setenabled(ino, HV_INTR_ENABLED); - } else { - unsigned long imap = bucket->imap; - unsigned int tid = sun4u_compute_tid(imap, goal_cpu); - - upa_writel(tid | IMAP_VALID, imap); - } + irq_enter(); - do { - if (++goal_cpu >= NR_CPUS) - goal_cpu = 0; - } while (!cpu_online(goal_cpu)); + kstat_this_cpu.irqs[0]++; + timer_interrupt(irq, NULL, regs); - return goal_cpu; + irq_exit(); } +#endif -/* Called from request_irq. */ -static void distribute_irqs(void) +void handler_irq(int irq, struct pt_regs *regs) { - unsigned long flags; - int cpu, level; + struct ino_bucket *bucket; - spin_lock_irqsave(&irq_action_lock, flags); - cpu = 0; + clear_softint(1 << irq); - /* - * Skip the timer at [0], and very rare error/power intrs at [15]. - * Also level [12], it causes problems on Ex000 systems. - */ - for (level = 1; level < NR_IRQS; level++) { - struct irqaction *p = irq_action[level]; + irq_enter(); - if (level == 12) - continue; + /* Sliiiick... */ + bucket = __bucket(xchg32(irq_work(smp_processor_id()), 0)); + while (bucket) { + struct ino_bucket *next = __bucket(bucket->irq_chain); - while(p) { - cpu = retarget_one_irq(p, cpu); - p = p->next; - } + bucket->irq_chain = 0; + __do_IRQ(bucket->virt_irq, regs); + + bucket = next; } - spin_unlock_irqrestore(&irq_action_lock, flags); + + irq_exit(); } -#endif struct sun5_timer { u64 count0; @@ -874,23 +575,29 @@ static u64 prom_limit0, prom_limit1; static void map_prom_timers(void) { - unsigned int addr[3]; - int tnode, err; + struct device_node *dp; + unsigned int *addr; /* PROM timer node hangs out in the top level of device siblings... */ - tnode = prom_finddevice("/counter-timer"); + dp = of_find_node_by_path("/"); + dp = dp->child; + while (dp) { + if (!strcmp(dp->name, "counter-timer")) + break; + dp = dp->sibling; + } /* Assume if node is not present, PROM uses different tick mechanism * which we should not care about. */ - if (tnode == 0 || tnode == -1) { + if (!dp) { prom_timers = (struct sun5_timer *) 0; return; } /* If PROM is really using this, it must be mapped by him. */ - err = prom_getproperty(tnode, "address", (char *)addr, sizeof(addr)); - if (err == -1) { + addr = of_get_property(dp, "address", NULL); + if (!addr) { prom_printf("PROM does not have timer mapped, trying to continue.\n"); prom_timers = (struct sun5_timer *) 0; return; @@ -929,7 +636,7 @@ void init_irqwork_curcpu(void) { int cpu = hard_smp_processor_id(); - memset(__irq_work + cpu, 0, sizeof(struct irq_work_struct)); + trap_block[cpu].irq_worklist = 0; } static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type) @@ -1037,6 +744,10 @@ void __cpuinit sun4v_init_mondo_queues(i } } +static struct irqaction timer_irq_action = { + .name = "timer", +}; + /* Only invoked on boot processor. */ void __init init_IRQ(void) { @@ -1064,109 +775,6 @@ void __init init_IRQ(void) : /* No outputs */ : "i" (PSTATE_IE) : "g1"); -} - -static struct proc_dir_entry * root_irq_dir; -static struct proc_dir_entry * irq_dir [NUM_IVECS]; - -#ifdef CONFIG_SMP - -static int irq_affinity_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct ino_bucket *bp = ivector_table + (long)data; - struct irq_desc *desc = bp->irq_info; - struct irqaction *ap = desc->action; - cpumask_t mask; - int len; - - mask = get_smpaff_in_irqaction(ap); - if (cpus_empty(mask)) - mask = cpu_online_map; - - len = cpumask_scnprintf(page, count, mask); - if (count - len < 2) - return -EINVAL; - len += sprintf(page + len, "\n"); - return len; -} - -static inline void set_intr_affinity(int irq, cpumask_t hw_aff) -{ - struct ino_bucket *bp = ivector_table + irq; - struct irq_desc *desc = bp->irq_info; - struct irqaction *ap = desc->action; - - /* Users specify affinity in terms of hw cpu ids. - * As soon as we do this, handler_irq() might see and take action. - */ - put_smpaff_in_irqaction(ap, hw_aff); - - /* Migration is simply done by the next cpu to service this - * interrupt. - */ -} - -static int irq_affinity_write_proc (struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - int irq = (long) data, full_count = count, err; - cpumask_t new_value; - - err = cpumask_parse(buffer, count, new_value); - - /* - * Do not allow disabling IRQs completely - it's a too easy - * way to make the system unusable accidentally :-) At least - * one online CPU still has to be targeted. - */ - cpus_and(new_value, new_value, cpu_online_map); - if (cpus_empty(new_value)) - return -EINVAL; - - set_intr_affinity(irq, new_value); - return full_count; + irq_desc[0].action = &timer_irq_action; } - -#endif - -#define MAX_NAMELEN 10 - -static void register_irq_proc (unsigned int irq) -{ - char name [MAX_NAMELEN]; - - if (!root_irq_dir || irq_dir[irq]) - return; - - memset(name, 0, MAX_NAMELEN); - sprintf(name, "%x", irq); - - /* create /proc/irq/1234 */ - irq_dir[irq] = proc_mkdir(name, root_irq_dir); - -#ifdef CONFIG_SMP - /* XXX SMP affinity not supported on starfire yet. */ - if (this_is_starfire == 0) { - struct proc_dir_entry *entry; - - /* create /proc/irq/1234/smp_affinity */ - entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); - - if (entry) { - entry->nlink = 1; - entry->data = (void *)(long)irq; - entry->read_proc = irq_affinity_read_proc; - entry->write_proc = irq_affinity_write_proc; - } - } -#endif -} - -void init_irq_proc (void) -{ - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", NULL); -} - diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 30862ab..6f16dee 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c @@ -15,23 +15,19 @@ static void __init fatal_err(const char static void __init report_dev(struct sparc_isa_device *isa_dev, int child) { if (child) - printk(" (%s)", isa_dev->prom_name); + printk(" (%s)", isa_dev->prom_node->name); else - printk(" [%s", isa_dev->prom_name); + printk(" [%s", isa_dev->prom_node->name); } -static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev, - struct linux_prom_registers *pregs, - int pregs_size) +static struct linux_prom_registers * __init +isa_dev_get_resource(struct sparc_isa_device *isa_dev) { + struct linux_prom_registers *pregs; unsigned long base, len; int prop_len; - prop_len = prom_getproperty(isa_dev->prom_node, "reg", - (char *) pregs, pregs_size); - - if (prop_len <= 0) - return; + pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len); /* Only the first one is interesting. */ len = pregs[0].reg_size; @@ -42,10 +38,12 @@ static void __init isa_dev_get_resource( isa_dev->resource.start = base; isa_dev->resource.end = (base + len - 1UL); isa_dev->resource.flags = IORESOURCE_IO; - isa_dev->resource.name = isa_dev->prom_name; + isa_dev->resource.name = isa_dev->prom_node->name; request_resource(&isa_dev->bus->parent->io_space, &isa_dev->resource); + + return pregs; } /* I can't believe they didn't put a real INO in the isa device @@ -74,19 +72,30 @@ static struct { static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev, struct sparc_isa_bridge *isa_br, int *interrupt, - struct linux_prom_registers *pregs) + struct linux_prom_registers *reg) { + struct linux_prom_ebus_intmap *imap; + struct linux_prom_ebus_intmap *imask; unsigned int hi, lo, irq; - int i; - - hi = pregs->which_io & isa_br->isa_intmask.phys_hi; - lo = pregs->phys_addr & isa_br->isa_intmask.phys_lo; - irq = *interrupt & isa_br->isa_intmask.interrupt; - for (i = 0; i < isa_br->num_isa_intmap; i++) { - if ((isa_br->isa_intmap[i].phys_hi == hi) && - (isa_br->isa_intmap[i].phys_lo == lo) && - (isa_br->isa_intmap[i].interrupt == irq)) { - *interrupt = isa_br->isa_intmap[i].cinterrupt; + int i, len, n_imap; + + imap = of_get_property(isa_br->prom_node, "interrupt-map", &len); + if (!imap) + return 0; + n_imap = len / sizeof(imap[0]); + + imask = of_get_property(isa_br->prom_node, "interrupt-map-mask", NULL); + if (!imask) + return 0; + + hi = reg->which_io & imask->phys_hi; + lo = reg->phys_addr & imask->phys_lo; + irq = *interrupt & imask->interrupt; + for (i = 0; i < n_imap; i++) { + if ((imap[i].phys_hi == hi) && + (imap[i].phys_lo == lo) && + (imap[i].interrupt == irq)) { + *interrupt = imap[i].cinterrupt; return 0; } } @@ -98,8 +107,8 @@ static void __init isa_dev_get_irq(struc { int irq_prop; - irq_prop = prom_getintdefault(isa_dev->prom_node, - "interrupts", -1); + irq_prop = of_getintprop_default(isa_dev->prom_node, + "interrupts", -1); if (irq_prop <= 0) { goto no_irq; } else { @@ -107,7 +116,8 @@ static void __init isa_dev_get_irq(struc struct pci_pbm_info *pbm; int i; - if (isa_dev->bus->num_isa_intmap) { + if (of_find_property(isa_dev->bus->prom_node, + "interrupt-map", NULL)) { if (!isa_dev_get_irq_using_imap(isa_dev, isa_dev->bus, &irq_prop, @@ -141,16 +151,15 @@ no_irq: static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) { - int node = prom_getchild(parent_isa_dev->prom_node); + struct device_node *dp = parent_isa_dev->prom_node->child; - if (node == 0) + if (!dp) return; printk(" ->"); - while (node != 0) { - struct linux_prom_registers regs[PROMREG_MAX]; + while (dp) { + struct linux_prom_registers *regs; struct sparc_isa_device *isa_dev; - int prop_len; isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); if (!isa_dev) { @@ -165,49 +174,46 @@ static void __init isa_fill_children(str parent_isa_dev->child = isa_dev; isa_dev->bus = parent_isa_dev->bus; - isa_dev->prom_node = node; - prop_len = prom_getproperty(node, "name", - (char *) isa_dev->prom_name, - sizeof(isa_dev->prom_name)); - if (prop_len <= 0) { - fatal_err("cannot get child isa_dev OBP node name"); - prom_halt(); - } + isa_dev->prom_node = dp; - prop_len = prom_getproperty(node, "compatible", - (char *) isa_dev->compatible, - sizeof(isa_dev->compatible)); - - /* Not having this is OK. */ - if (prop_len <= 0) - isa_dev->compatible[0] = '\0'; - - isa_dev_get_resource(isa_dev, regs, sizeof(regs)); + regs = isa_dev_get_resource(isa_dev); isa_dev_get_irq(isa_dev, regs); report_dev(isa_dev, 1); - node = prom_getsibling(node); + dp = dp->sibling; } } static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) { - int node = prom_getchild(isa_br->prom_node); + struct device_node *dp = isa_br->prom_node->child; - while (node != 0) { - struct linux_prom_registers regs[PROMREG_MAX]; + while (dp) { + struct linux_prom_registers *regs; struct sparc_isa_device *isa_dev; - int prop_len; isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL); if (!isa_dev) { - fatal_err("cannot allocate isa_dev"); - prom_halt(); + printk(KERN_DEBUG "ISA: cannot allocate isa_dev"); + return; } memset(isa_dev, 0, sizeof(*isa_dev)); + isa_dev->ofdev.node = dp; + isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; + isa_dev->ofdev.dev.bus = &isa_bus_type; + strcpy(isa_dev->ofdev.dev.bus_id, dp->path_component_name); + + /* Register with core */ + if (of_device_register(&isa_dev->ofdev) != 0) { + printk(KERN_DEBUG "isa: device registration error for %s!\n", + isa_dev->ofdev.dev.bus_id); + kfree(isa_dev); + goto next_sibling; + } + /* Link it in. */ isa_dev->next = NULL; if (isa_br->devices == NULL) { @@ -222,24 +228,9 @@ static void __init isa_fill_devices(stru } isa_dev->bus = isa_br; - isa_dev->prom_node = node; - prop_len = prom_getproperty(node, "name", - (char *) isa_dev->prom_name, - sizeof(isa_dev->prom_name)); - if (prop_len <= 0) { - fatal_err("cannot get isa_dev OBP node name"); - prom_halt(); - } - - prop_len = prom_getproperty(node, "compatible", - (char *) isa_dev->compatible, - sizeof(isa_dev->compatible)); + isa_dev->prom_node = dp; - /* Not having this is OK. */ - if (prop_len <= 0) - isa_dev->compatible[0] = '\0'; - - isa_dev_get_resource(isa_dev, regs, sizeof(regs)); + regs = isa_dev_get_resource(isa_dev); isa_dev_get_irq(isa_dev, regs); report_dev(isa_dev, 0); @@ -248,7 +239,8 @@ static void __init isa_fill_devices(stru printk("]"); - node = prom_getsibling(node); + next_sibling: + dp = dp->sibling; } } @@ -266,7 +258,7 @@ void __init isa_init(void) struct pcidev_cookie *pdev_cookie; struct pci_pbm_info *pbm; struct sparc_isa_bridge *isa_br; - int prop_len; + struct device_node *dp; pdev_cookie = pdev->sysdata; if (!pdev_cookie) { @@ -275,15 +267,29 @@ void __init isa_init(void) continue; } pbm = pdev_cookie->pbm; + dp = pdev_cookie->prom_node; isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL); if (!isa_br) { - fatal_err("cannot allocate sparc_isa_bridge"); - prom_halt(); + printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge"); + return; } memset(isa_br, 0, sizeof(*isa_br)); + isa_br->ofdev.node = dp; + isa_br->ofdev.dev.parent = &pdev->dev; + isa_br->ofdev.dev.bus = &isa_bus_type; + strcpy(isa_br->ofdev.dev.bus_id, dp->path_component_name); + + /* Register with core */ + if (of_device_register(&isa_br->ofdev) != 0) { + printk(KERN_DEBUG "isa: device registration error for %s!\n", + isa_br->ofdev.dev.bus_id); + kfree(isa_br); + return; + } + /* Link it in. */ isa_br->next = isa_chain; isa_chain = isa_br; @@ -292,33 +298,6 @@ void __init isa_init(void) isa_br->self = pdev; isa_br->index = index++; isa_br->prom_node = pdev_cookie->prom_node; - strncpy(isa_br->prom_name, pdev_cookie->prom_name, - sizeof(isa_br->prom_name)); - - prop_len = prom_getproperty(isa_br->prom_node, - "ranges", - (char *) isa_br->isa_ranges, - sizeof(isa_br->isa_ranges)); - if (prop_len <= 0) - isa_br->num_isa_ranges = 0; - else - isa_br->num_isa_ranges = - (prop_len / sizeof(struct linux_prom_isa_ranges)); - - prop_len = prom_getproperty(isa_br->prom_node, - "interrupt-map", - (char *) isa_br->isa_intmap, - sizeof(isa_br->isa_intmap)); - if (prop_len <= 0) - isa_br->num_isa_intmap = 0; - else - isa_br->num_isa_intmap = - (prop_len / sizeof(struct linux_prom_isa_intmap)); - - prop_len = prom_getproperty(isa_br->prom_node, - "interrupt-map-mask", - (char *) &(isa_br->isa_intmask), - sizeof(isa_br->isa_intmask)); printk("isa%d:", isa_br->index); diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c new file mode 100644 index 0000000..768475b --- /dev/null +++ b/arch/sparc64/kernel/of_device.c @@ -0,0 +1,282 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/** + * of_match_device - Tell if an of_device structure has a matching + * of_match structure + * @ids: array of of device match structures to search in + * @dev: the of device structure to match against + * + * Used by a driver to check whether an of_device present in the + * system is in its list of supported devices. + */ +const struct of_device_id *of_match_device(const struct of_device_id *matches, + const struct of_device *dev) +{ + if (!dev->node) + return NULL; + while (matches->name[0] || matches->type[0] || matches->compatible[0]) { + int match = 1; + if (matches->name[0]) + match &= dev->node->name + && !strcmp(matches->name, dev->node->name); + if (matches->type[0]) + match &= dev->node->type + && !strcmp(matches->type, dev->node->type); + if (matches->compatible[0]) + match &= of_device_is_compatible(dev->node, + matches->compatible); + if (match) + return matches; + matches++; + } + return NULL; +} + +static int of_platform_bus_match(struct device *dev, struct device_driver *drv) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * of_drv = to_of_platform_driver(drv); + const struct of_device_id * matches = of_drv->match_table; + + if (!matches) + return 0; + + return of_match_device(matches, of_dev) != NULL; +} + +struct of_device *of_dev_get(struct of_device *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + tmp = get_device(&dev->dev); + if (tmp) + return to_of_device(tmp); + else + return NULL; +} + +void of_dev_put(struct of_device *dev) +{ + if (dev) + put_device(&dev->dev); +} + + +static int of_device_probe(struct device *dev) +{ + int error = -ENODEV; + struct of_platform_driver *drv; + struct of_device *of_dev; + const struct of_device_id *match; + + drv = to_of_platform_driver(dev->driver); + of_dev = to_of_device(dev); + + if (!drv->probe) + return error; + + of_dev_get(of_dev); + + match = of_match_device(drv->match_table, of_dev); + if (match) + error = drv->probe(of_dev, match); + if (error) + of_dev_put(of_dev); + + return error; +} + +static int of_device_remove(struct device *dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + + if (dev->driver && drv->remove) + drv->remove(of_dev); + return 0; +} + +static int of_device_suspend(struct device *dev, pm_message_t state) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->suspend) + error = drv->suspend(of_dev, state); + return error; +} + +static int of_device_resume(struct device * dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->resume) + error = drv->resume(of_dev); + return error; +} + +#ifdef CONFIG_PCI +struct bus_type isa_bus_type = { + .name = "isa", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(isa_bus_type); + +struct bus_type ebus_bus_type = { + .name = "ebus", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(ebus_bus_type); +#endif + +#ifdef CONFIG_SBUS +struct bus_type sbus_bus_type = { + .name = "sbus", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(sbus_bus_type); +#endif + +static int __init of_bus_driver_init(void) +{ + int err = 0; + +#ifdef CONFIG_PCI + if (!err) + err = bus_register(&isa_bus_type); + if (!err) + err = bus_register(&ebus_bus_type); +#endif +#ifdef CONFIG_SBUS + if (!err) + err = bus_register(&sbus_bus_type); +#endif + return 0; +} + +postcore_initcall(of_bus_driver_init); + +int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) +{ + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = bus; + + /* register with core */ + return driver_register(&drv->driver); +} + +void of_unregister_driver(struct of_platform_driver *drv) +{ + driver_unregister(&drv->driver); +} + + +static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + return sprintf(buf, "%s", ofdev->node->full_name); +} + +static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); + +/** + * of_release_dev - free an of device structure when all users of it are finished. + * @dev: device that's been disconnected + * + * Will be called only by the device core when all users of this of device are + * done. + */ +void of_release_dev(struct device *dev) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + + kfree(ofdev); +} + +int of_device_register(struct of_device *ofdev) +{ + int rc; + + BUG_ON(ofdev->node == NULL); + + rc = device_register(&ofdev->dev); + if (rc) + return rc; + + device_create_file(&ofdev->dev, &dev_attr_devspec); + + return 0; +} + +void of_device_unregister(struct of_device *ofdev) +{ + device_remove_file(&ofdev->dev, &dev_attr_devspec); + device_unregister(&ofdev->dev); +} + +struct of_device* of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent, + struct bus_type *bus) +{ + struct of_device *dev; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof(*dev)); + + dev->dev.parent = parent; + dev->dev.bus = bus; + dev->dev.release = of_release_dev; + + strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); + + if (of_device_register(dev) != 0) { + kfree(dev); + return NULL; + } + + return dev; +} + +EXPORT_SYMBOL(of_match_device); +EXPORT_SYMBOL(of_register_driver); +EXPORT_SYMBOL(of_unregister_driver); +EXPORT_SYMBOL(of_device_register); +EXPORT_SYMBOL(of_device_unregister); +EXPORT_SYMBOL(of_dev_get); +EXPORT_SYMBOL(of_dev_put); +EXPORT_SYMBOL(of_platform_device_create); +EXPORT_SYMBOL(of_release_dev); diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index f97ddeb..6c9e3e9 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -22,6 +22,7 @@ #include #include #include #include +#include unsigned long pci_memspace_mask = 0xffffffffUL; @@ -47,12 +48,6 @@ struct pci_controller_info *pci_controll /* Each PCI controller found gets a unique index. */ int pci_num_controllers = 0; -/* At boot time the user can give the kernel a command - * line option which controls if and how PCI devices - * are reordered at PCI bus probing time. - */ -int pci_device_reorder = 0; - volatile int pci_poke_in_progress; volatile int pci_poke_cpu = -1; volatile int pci_poke_faulted; @@ -183,16 +178,16 @@ void pci_config_write32(u32 *addr, u32 v } /* Probe for all PCI controllers in the system. */ -extern void sabre_init(int, char *); -extern void psycho_init(int, char *); -extern void schizo_init(int, char *); -extern void schizo_plus_init(int, char *); -extern void tomatillo_init(int, char *); -extern void sun4v_pci_init(int, char *); +extern void sabre_init(struct device_node *, const char *); +extern void psycho_init(struct device_node *, const char *); +extern void schizo_init(struct device_node *, const char *); +extern void schizo_plus_init(struct device_node *, const char *); +extern void tomatillo_init(struct device_node *, const char *); +extern void sun4v_pci_init(struct device_node *, const char *); static struct { char *model_name; - void (*init)(int, char *); + void (*init)(struct device_node *, const char *); } pci_controller_table[] __initdata = { { "SUNW,sabre", sabre_init }, { "pci108e,a000", sabre_init }, @@ -210,7 +205,7 @@ static struct { #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \ sizeof(pci_controller_table[0])) -static int __init pci_controller_init(char *model_name, int namelen, int node) +static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp) { int i; @@ -218,18 +213,15 @@ static int __init pci_controller_init(ch if (!strncmp(model_name, pci_controller_table[i].model_name, namelen)) { - pci_controller_table[i].init(node, model_name); + pci_controller_table[i].init(dp, model_name); return 1; } } - printk("PCI: Warning unknown controller, model name [%s]\n", - model_name); - printk("PCI: Ignoring controller...\n"); return 0; } -static int __init pci_is_controller(char *model_name, int namelen, int node) +static int __init pci_is_controller(const char *model_name, int namelen, struct device_node *dp) { int i; @@ -243,36 +235,35 @@ static int __init pci_is_controller(char return 0; } -static int __init pci_controller_scan(int (*handler)(char *, int, int)) +static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *)) { - char namebuf[64]; - int node; + struct device_node *dp; int count = 0; - node = prom_getchild(prom_root_node); - while ((node = prom_searchsiblings(node, "pci")) != 0) { + for_each_node_by_name(dp, "pci") { + struct property *prop; int len; - if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 || - (len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) { + prop = of_find_property(dp, "model", &len); + if (!prop) + prop = of_find_property(dp, "compatible", &len); + + if (prop) { + const char *model = prop->value; int item_len = 0; /* Our value may be a multi-valued string in the * case of some compatible properties. For sanity, - * only try the first one. */ - - while (namebuf[item_len] && len) { + * only try the first one. + */ + while (model[item_len] && len) { len--; item_len++; } - if (handler(namebuf, item_len, node)) + if (handler(model, item_len, dp)) count++; } - - node = prom_getsibling(node); - if (!node) - break; } return count; @@ -316,27 +307,6 @@ static void __init pci_scan_each_control p->scan_bus(p); } -/* Reorder the pci_dev chain, so that onboard devices come first - * and then come the pluggable cards. - */ -static void __init pci_reorder_devs(void) -{ - struct list_head *pci_onboard = &pci_devices; - struct list_head *walk = pci_onboard->next; - - while (walk != pci_onboard) { - struct pci_dev *pdev = pci_dev_g(walk); - struct list_head *walk_next = walk->next; - - if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) { - list_del(walk); - list_add(walk, pci_onboard); - } - - walk = walk_next; - } -} - extern void clock_probe(void); extern void power_init(void); @@ -348,9 +318,6 @@ static int __init pcibios_init(void) pci_scan_each_controller_bus(); - if (pci_device_reorder) - pci_reorder_devs(); - isa_init(); ebus_init(); clock_probe(); @@ -439,14 +406,12 @@ void pcibios_bus_to_resource(struct pci_ } EXPORT_SYMBOL(pcibios_bus_to_resource); +extern int pci_irq_verbose; + char * __init pcibios_setup(char *str) { - if (!strcmp(str, "onboardfirst")) { - pci_device_reorder = 1; - return NULL; - } - if (!strcmp(str, "noreorder")) { - pci_device_reorder = 0; + if (!strcmp(str, "irq_verbose")) { + pci_irq_verbose = 1; return NULL; } return str; diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 33dedb1..b06a295 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -9,6 +9,12 @@ #include #include #include +#include + +#include "pci_impl.h" + +/* Pass "pci=irq_verbose" on the kernel command line to enable this. */ +int pci_irq_verbose; /* Fix self device of BUS and hook it into BUS->self. * The pci_scan_bus does not do this for the host bridge. @@ -28,16 +34,14 @@ void __init pci_fixup_host_bridge_self(s prom_halt(); } -/* Find the OBP PROM device tree node for a PCI device. - * Return zero if not found. - */ -static int __init find_device_prom_node(struct pci_pbm_info *pbm, - struct pci_dev *pdev, - int bus_prom_node, - struct linux_prom_pci_registers *pregs, - int *nregs) +/* Find the OBP PROM device tree node for a PCI device. */ +static struct device_node * __init +find_device_prom_node(struct pci_pbm_info *pbm, struct pci_dev *pdev, + struct device_node *bus_node, + struct linux_prom_pci_registers **pregs, + int *nregs) { - int node; + struct device_node *dp; *nregs = 0; @@ -54,24 +58,30 @@ static int __init find_device_prom_node( pdev->device == PCI_DEVICE_ID_SUN_TOMATILLO || pdev->device == PCI_DEVICE_ID_SUN_SABRE || pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD)) - return bus_prom_node; - - node = prom_getchild(bus_prom_node); - while (node != 0) { - int err = prom_getproperty(node, "reg", - (char *)pregs, - sizeof(*pregs) * PROMREG_MAX); - if (err == 0 || err == -1) + return bus_node; + + dp = bus_node->child; + while (dp) { + struct linux_prom_pci_registers *regs; + struct property *prop; + int len; + + prop = of_find_property(dp, "reg", &len); + if (!prop) goto do_next_sibling; - if (((pregs[0].phys_hi >> 8) & 0xff) == pdev->devfn) { - *nregs = err / sizeof(*pregs); - return node; + + regs = prop->value; + if (((regs[0].phys_hi >> 8) & 0xff) == pdev->devfn) { + *pregs = regs; + *nregs = len / sizeof(struct linux_prom_pci_registers); + return dp; } do_next_sibling: - node = prom_getsibling(node); + dp = dp->sibling; } - return 0; + + return NULL; } /* Older versions of OBP on PCI systems encode 64-bit MEM @@ -128,15 +138,17 @@ static void __init fixup_obp_assignments */ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm, struct pci_dev *pdev, - int bus_prom_node) + struct device_node *bus_node) { - struct linux_prom_pci_registers pregs[PROMREG_MAX]; + struct linux_prom_pci_registers *pregs = NULL; struct pcidev_cookie *pcp; - int device_prom_node, nregs, err; + struct device_node *dp; + struct property *prop; + int nregs, len; - device_prom_node = find_device_prom_node(pbm, pdev, bus_prom_node, - pregs, &nregs); - if (device_prom_node == 0) { + dp = find_device_prom_node(pbm, pdev, bus_node, + &pregs, &nregs); + if (!dp) { /* If it is not in the OBP device tree then * there must be a damn good reason for it. * @@ -150,45 +162,43 @@ static void __init pdev_cookie_fillin(st return; } - pcp = kmalloc(sizeof(*pcp), GFP_ATOMIC); + pcp = kzalloc(sizeof(*pcp), GFP_ATOMIC); if (pcp == NULL) { prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n"); prom_halt(); } pcp->pbm = pbm; - pcp->prom_node = device_prom_node; - memcpy(pcp->prom_regs, pregs, sizeof(pcp->prom_regs)); + pcp->prom_node = dp; + memcpy(pcp->prom_regs, pregs, + nregs * sizeof(struct linux_prom_pci_registers)); pcp->num_prom_regs = nregs; - err = prom_getproperty(device_prom_node, "name", - pcp->prom_name, sizeof(pcp->prom_name)); - if (err > 0) - pcp->prom_name[err] = 0; - else - pcp->prom_name[0] = 0; - - err = prom_getproperty(device_prom_node, - "assigned-addresses", - (char *)pcp->prom_assignments, - sizeof(pcp->prom_assignments)); - if (err == 0 || err == -1) + + /* We can't have the pcidev_cookie assignments be just + * direct pointers into the property value, since they + * are potentially modified by the probing process. + */ + prop = of_find_property(dp, "assigned-addresses", &len); + if (!prop) { pcp->num_prom_assignments = 0; - else + } else { + memcpy(pcp->prom_assignments, prop->value, len); pcp->num_prom_assignments = - (err / sizeof(pcp->prom_assignments[0])); + (len / sizeof(pcp->prom_assignments[0])); + } - if (strcmp(pcp->prom_name, "ebus") == 0) { - struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX]; + if (strcmp(dp->name, "ebus") == 0) { + struct linux_prom_ebus_ranges *erng; int iter; /* EBUS is special... */ - err = prom_getproperty(device_prom_node, "ranges", - (char *)&erng[0], sizeof(erng)); - if (err == 0 || err == -1) { + prop = of_find_property(dp, "ranges", &len); + if (!prop) { prom_printf("EBUS: Fatal error, no range property\n"); prom_halt(); } - err = (err / sizeof(erng[0])); - for(iter = 0; iter < err; iter++) { + erng = prop->value; + len = (len / sizeof(erng[0])); + for (iter = 0; iter < len; iter++) { struct linux_prom_ebus_ranges *ep = &erng[iter]; struct linux_prom_pci_registers *ap; @@ -200,7 +210,7 @@ static void __init pdev_cookie_fillin(st ap->size_hi = 0; ap->size_lo = ep->size; } - pcp->num_prom_assignments = err; + pcp->num_prom_assignments = len; } fixup_obp_assignments(pdev, pcp); @@ -210,7 +220,7 @@ static void __init pdev_cookie_fillin(st void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus, struct pci_pbm_info *pbm, - int prom_node) + struct device_node *dp) { struct pci_dev *pdev, *pdev_next; struct pci_bus *this_pbus, *pbus_next; @@ -218,7 +228,7 @@ void __init pci_fill_in_pbm_cookies(stru /* This must be _safe because the cookie fillin routine can delete devices from the tree. */ list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list) - pdev_cookie_fillin(pbm, pdev, prom_node); + pdev_cookie_fillin(pbm, pdev, dp); list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) { struct pcidev_cookie *pcp = this_pbus->self->sysdata; @@ -241,7 +251,6 @@ static void __init bad_assignment(struct if (res) prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n", res->start, res->end, res->flags); - prom_printf("Please email this information to davem@redhat.com\n"); if (do_prom_halt) prom_halt(); } @@ -273,8 +282,7 @@ __init get_root_resource(struct linux_pr return &pbm->mem_space; default: - printk("PCI: What is resource space %x? " - "Tell davem@redhat.com about it!\n", space); + printk("PCI: What is resource space %x?\n", space); return NULL; }; } @@ -556,9 +564,10 @@ static inline unsigned int pci_slot_swiv ret = ((interrupt - 1 + (PCI_SLOT(pdev->devfn) & 3)) & 3) + 1; - printk("%s: %s IRQ Swivel %s [%x:%x] -> [%x]\n", - pbm->name, pci_name(toplevel_pdev), pci_name(pdev), - interrupt, PCI_SLOT(pdev->devfn), ret); + if (pci_irq_verbose) + printk("%s: %s IRQ Swivel %s [%x:%x] -> [%x]\n", + pbm->name, pci_name(toplevel_pdev), pci_name(pdev), + interrupt, PCI_SLOT(pdev->devfn), ret); return ret; } @@ -568,58 +577,60 @@ static inline unsigned int pci_apply_int struct pci_dev *pbus, struct pci_dev *pdev, unsigned int interrupt, - unsigned int *cnode) + struct device_node **cnode) { - struct linux_prom_pci_intmap imap[PROM_PCIIMAP_MAX]; - struct linux_prom_pci_intmask imask; + struct linux_prom_pci_intmap *imap; + struct linux_prom_pci_intmask *imask; struct pcidev_cookie *pbus_pcp = pbus->sysdata; struct pcidev_cookie *pdev_pcp = pdev->sysdata; struct linux_prom_pci_registers *pregs = pdev_pcp->prom_regs; + struct property *prop; int plen, num_imap, i; unsigned int hi, mid, lo, irq, orig_interrupt; *cnode = pbus_pcp->prom_node; - plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map", - (char *) &imap[0], sizeof(imap)); - if (plen <= 0 || + prop = of_find_property(pbus_pcp->prom_node, "interrupt-map", &plen); + if (!prop || (plen % sizeof(struct linux_prom_pci_intmap)) != 0) { printk("%s: Device %s interrupt-map has bad len %d\n", pbm->name, pci_name(pbus), plen); goto no_intmap; } + imap = prop->value; num_imap = plen / sizeof(struct linux_prom_pci_intmap); - plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map-mask", - (char *) &imask, sizeof(imask)); - if (plen <= 0 || + prop = of_find_property(pbus_pcp->prom_node, "interrupt-map-mask", &plen); + if (!prop || (plen % sizeof(struct linux_prom_pci_intmask)) != 0) { printk("%s: Device %s interrupt-map-mask has bad len %d\n", pbm->name, pci_name(pbus), plen); goto no_intmap; } + imask = prop->value; orig_interrupt = interrupt; - hi = pregs->phys_hi & imask.phys_hi; - mid = pregs->phys_mid & imask.phys_mid; - lo = pregs->phys_lo & imask.phys_lo; - irq = interrupt & imask.interrupt; + hi = pregs->phys_hi & imask->phys_hi; + mid = pregs->phys_mid & imask->phys_mid; + lo = pregs->phys_lo & imask->phys_lo; + irq = interrupt & imask->interrupt; for (i = 0; i < num_imap; i++) { if (imap[i].phys_hi == hi && imap[i].phys_mid == mid && imap[i].phys_lo == lo && imap[i].interrupt == irq) { - *cnode = imap[i].cnode; + *cnode = of_find_node_by_phandle(imap[i].cnode); interrupt = imap[i].cinterrupt; } } - printk("%s: %s MAP BUS %s DEV %s [%x] -> [%x]\n", - pbm->name, pci_name(toplevel_pdev), - pci_name(pbus), pci_name(pdev), - orig_interrupt, interrupt); + if (pci_irq_verbose) + printk("%s: %s MAP BUS %s DEV %s [%x] -> [%x]\n", + pbm->name, pci_name(toplevel_pdev), + pci_name(pbus), pci_name(pdev), + orig_interrupt, interrupt); no_intmap: return interrupt; @@ -633,21 +644,22 @@ no_intmap: * all interrupt translations are complete, else we should use that node's * "reg" property to apply the PBM's "interrupt-{map,mask}" to the interrupt. */ -static unsigned int __init pci_intmap_match_to_root(struct pci_pbm_info *pbm, - struct pci_dev *pdev, - unsigned int *interrupt) +static struct device_node * __init +pci_intmap_match_to_root(struct pci_pbm_info *pbm, + struct pci_dev *pdev, + unsigned int *interrupt) { struct pci_dev *toplevel_pdev = pdev; struct pcidev_cookie *toplevel_pcp = toplevel_pdev->sysdata; - unsigned int cnode = toplevel_pcp->prom_node; + struct device_node *cnode = toplevel_pcp->prom_node; while (pdev->bus->number != pbm->pci_first_busno) { struct pci_dev *pbus = pdev->bus->self; struct pcidev_cookie *pcp = pbus->sysdata; - int plen; + struct property *prop; - plen = prom_getproplen(pcp->prom_node, "interrupt-map"); - if (plen <= 0) { + prop = of_find_property(pcp->prom_node, "interrupt-map", NULL); + if (!prop) { *interrupt = pci_slot_swivel(pbm, toplevel_pdev, pdev, *interrupt); cnode = pcp->prom_node; @@ -675,26 +687,29 @@ static int __init pci_intmap_match(struc { struct pcidev_cookie *dev_pcp = pdev->sysdata; struct pci_pbm_info *pbm = dev_pcp->pbm; - struct linux_prom_pci_registers reg[PROMREG_MAX]; + struct linux_prom_pci_registers *reg; + struct device_node *cnode; + struct property *prop; unsigned int hi, mid, lo, irq; - int i, cnode, plen; + int i, plen; cnode = pci_intmap_match_to_root(pbm, pdev, interrupt); if (cnode == pbm->prom_node) goto success; - plen = prom_getproperty(cnode, "reg", (char *) reg, sizeof(reg)); - if (plen <= 0 || + prop = of_find_property(cnode, "reg", &plen); + if (!prop || (plen % sizeof(struct linux_prom_pci_registers)) != 0) { - printk("%s: OBP node %x reg property has bad len %d\n", - pbm->name, cnode, plen); + printk("%s: OBP node %s reg property has bad len %d\n", + pbm->name, cnode->full_name, plen); goto fail; } + reg = prop->value; - hi = reg[0].phys_hi & pbm->pbm_intmask.phys_hi; - mid = reg[0].phys_mid & pbm->pbm_intmask.phys_mid; - lo = reg[0].phys_lo & pbm->pbm_intmask.phys_lo; - irq = *interrupt & pbm->pbm_intmask.interrupt; + hi = reg[0].phys_hi & pbm->pbm_intmask->phys_hi; + mid = reg[0].phys_mid & pbm->pbm_intmask->phys_mid; + lo = reg[0].phys_lo & pbm->pbm_intmask->phys_lo; + irq = *interrupt & pbm->pbm_intmask->interrupt; for (i = 0; i < pbm->num_pbm_intmap; i++) { struct linux_prom_pci_intmap *intmap; @@ -714,9 +729,11 @@ fail: return 0; success: - printk("PCI-IRQ: Routing bus[%2x] slot[%2x] to INO[%02x]\n", - pdev->bus->number, PCI_SLOT(pdev->devfn), - *interrupt); + if (pci_irq_verbose) + printk("%s: Routing bus[%2x] slot[%2x] to INO[%02x]\n", + pbm->name, + pdev->bus->number, PCI_SLOT(pdev->devfn), + *interrupt); return 1; } @@ -727,8 +744,8 @@ static void __init pdev_fixup_irq(struct struct pci_controller_info *p = pbm->parent; unsigned int portid = pbm->portid; unsigned int prom_irq; - int prom_node = pcp->prom_node; - int err; + struct device_node *dp = pcp->prom_node; + struct property *prop; /* If this is an empty EBUS device, sometimes OBP fails to * give it a valid fully specified interrupts property. @@ -739,17 +756,17 @@ static void __init pdev_fixup_irq(struct */ if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_EBUS && - !prom_getchild(prom_node)) { + !dp->child) { pdev->irq = 0; return; } - err = prom_getproperty(prom_node, "interrupts", - (char *)&prom_irq, sizeof(prom_irq)); - if (err == 0 || err == -1) { + prop = of_find_property(dp, "interrupts", NULL); + if (!prop) { pdev->irq = 0; return; } + prom_irq = *(unsigned int *) prop->value; if (tlb_type != hypervisor) { /* Fully specified already? */ diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 6c32059..971e2be 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -10,6 +10,7 @@ #define PCI_IMPL_H #include #include #include +#include extern struct pci_controller_info *pci_controller_root; @@ -19,7 +20,7 @@ extern int pci_num_controllers; extern void pci_fixup_host_bridge_self(struct pci_bus *pbus); extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus, struct pci_pbm_info *pbm, - int prom_node); + struct device_node *prom_node); extern void pci_record_assignments(struct pci_pbm_info *pbm, struct pci_bus *pbus); extern void pci_assign_unassigned(struct pci_pbm_info *pbm, diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index d17878b..5b2261e 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -17,6 +17,7 @@ #include #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" @@ -276,82 +277,13 @@ #define psycho_iclr_offset(ino) ((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ (PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3))) -/* PCI PSYCHO INO number to Sparc PIL level. */ -static unsigned char psycho_pil_table[] = { -/*0x00*/0, 0, 0, 0, /* PCI A slot 0 Int A, B, C, D */ -/*0x04*/0, 0, 0, 0, /* PCI A slot 1 Int A, B, C, D */ -/*0x08*/0, 0, 0, 0, /* PCI A slot 2 Int A, B, C, D */ -/*0x0c*/0, 0, 0, 0, /* PCI A slot 3 Int A, B, C, D */ -/*0x10*/0, 0, 0, 0, /* PCI B slot 0 Int A, B, C, D */ -/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */ -/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */ -/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */ -/*0x20*/5, /* SCSI */ -/*0x21*/5, /* Ethernet */ -/*0x22*/8, /* Parallel Port */ -/*0x23*/13, /* Audio Record */ -/*0x24*/14, /* Audio Playback */ -/*0x25*/15, /* PowerFail */ -/*0x26*/5, /* second SCSI */ -/*0x27*/11, /* Floppy */ -/*0x28*/5, /* Spare Hardware */ -/*0x29*/9, /* Keyboard */ -/*0x2a*/5, /* Mouse */ -/*0x2b*/12, /* Serial */ -/*0x2c*/10, /* Timer 0 */ -/*0x2d*/11, /* Timer 1 */ -/*0x2e*/15, /* Uncorrectable ECC */ -/*0x2f*/15, /* Correctable ECC */ -/*0x30*/15, /* PCI Bus A Error */ -/*0x31*/15, /* PCI Bus B Error */ -/*0x32*/15, /* Power Management */ -}; - -static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino) -{ - int ret; - - ret = psycho_pil_table[ino]; - if (ret == 0 && pdev == NULL) { - ret = 5; - } else if (ret == 0) { - switch ((pdev->class >> 16) & 0xff) { - case PCI_BASE_CLASS_STORAGE: - ret = 5; - break; - - case PCI_BASE_CLASS_NETWORK: - ret = 6; - break; - - case PCI_BASE_CLASS_DISPLAY: - ret = 9; - break; - - case PCI_BASE_CLASS_MULTIMEDIA: - case PCI_BASE_CLASS_MEMORY: - case PCI_BASE_CLASS_BRIDGE: - case PCI_BASE_CLASS_SERIAL: - ret = 10; - break; - - default: - ret = 5; - break; - }; - } - - return ret; -} - static unsigned int psycho_irq_build(struct pci_pbm_info *pbm, struct pci_dev *pdev, unsigned int ino) { - struct ino_bucket *bucket; unsigned long imap, iclr; unsigned long imap_off, iclr_off; - int pil, inofixup = 0; + int inofixup = 0; ino &= PCI_IRQ_INO; if (ino < PSYCHO_ONBOARD_IRQ_BASE) { @@ -367,11 +299,6 @@ static unsigned int psycho_irq_build(str } /* Now build the IRQ bucket. */ - pil = psycho_ino_to_pil(pdev, ino); - - if (PIL_RESERVED(pil)) - BUG(); - imap = pbm->controller_regs + imap_off; imap += 4; @@ -382,10 +309,7 @@ static unsigned int psycho_irq_build(str if ((ino & 0x20) == 0) inofixup = ino & 0x03; - bucket = __bucket(build_irq(pil, inofixup, iclr, imap)); - bucket->flags |= IBF_PCI; - - return __irq(bucket); + return build_irq(inofixup, iclr, imap); } /* PSYCHO error handling support. */ @@ -1368,11 +1292,12 @@ #define PSYCHO_MEMSPACE_B 0x180000000UL #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL static void psycho_pbm_init(struct pci_controller_info *p, - int prom_node, int is_pbm_a) + struct device_node *dp, int is_pbm_a) { - unsigned int busrange[2]; + unsigned int *busrange; + struct property *prop; struct pci_pbm_info *pbm; - int err; + int len; if (is_pbm_a) { pbm = &p->pbm_A; @@ -1387,10 +1312,14 @@ static void psycho_pbm_init(struct pci_c } pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; - pbm->chip_version = - prom_getintdefault(prom_node, "version#", 0); - pbm->chip_revision = - prom_getintdefault(prom_node, "module-revision#", 0); + pbm->chip_version = 0; + prop = of_find_property(dp, "version#", NULL); + if (prop) + pbm->chip_version = *(int *) prop->value; + pbm->chip_revision = 0; + prop = of_find_property(dp, "module-revision#", NULL); + if (prop) + pbm->chip_revision = *(int *) prop->value; pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE; pbm->io_space.flags = IORESOURCE_IO; @@ -1399,45 +1328,36 @@ static void psycho_pbm_init(struct pci_c pbm_register_toplevel_resources(p, pbm); pbm->parent = p; - pbm->prom_node = prom_node; - prom_getstring(prom_node, "name", - pbm->prom_name, - sizeof(pbm->prom_name)); - - err = prom_getproperty(prom_node, "ranges", - (char *)pbm->pbm_ranges, - sizeof(pbm->pbm_ranges)); - if (err != -1) + pbm->prom_node = dp; + pbm->name = dp->full_name; + + printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", + pbm->name, + pbm->chip_version, pbm->chip_revision); + + prop = of_find_property(dp, "ranges", &len); + if (prop) { + pbm->pbm_ranges = prop->value; pbm->num_pbm_ranges = - (err / sizeof(struct linux_prom_pci_ranges)); - else + (len / sizeof(struct linux_prom_pci_ranges)); + } else { pbm->num_pbm_ranges = 0; + } - err = prom_getproperty(prom_node, "interrupt-map", - (char *)pbm->pbm_intmap, - sizeof(pbm->pbm_intmap)); - if (err != -1) { - pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); - err = prom_getproperty(prom_node, "interrupt-map-mask", - (char *)&pbm->pbm_intmask, - sizeof(pbm->pbm_intmask)); - if (err == -1) { - prom_printf("PSYCHO-PBM: Fatal error, no " - "interrupt-map-mask.\n"); - prom_halt(); - } + prop = of_find_property(dp, "interrupt-map", &len); + if (prop) { + pbm->pbm_intmap = prop->value; + pbm->num_pbm_intmap = + (len / sizeof(struct linux_prom_pci_intmap)); + + prop = of_find_property(dp, "interrupt-map-mask", NULL); + pbm->pbm_intmask = prop->value; } else { pbm->num_pbm_intmap = 0; - memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); } - err = prom_getproperty(prom_node, "bus-range", - (char *)&busrange[0], - sizeof(busrange)); - if (err == 0 || err == -1) { - prom_printf("PSYCHO-PBM: Fatal error, no bus-range.\n"); - prom_halt(); - } + prop = of_find_property(dp, "bus-range", NULL); + busrange = prop->value; pbm->pci_first_busno = busrange[0]; pbm->pci_last_busno = busrange[1]; @@ -1446,20 +1366,24 @@ static void psycho_pbm_init(struct pci_c #define PSYCHO_CONFIGSPACE 0x001000000UL -void psycho_init(int node, char *model_name) +void psycho_init(struct device_node *dp, char *model_name) { - struct linux_prom64_registers pr_regs[3]; + struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; struct pci_iommu *iommu; + struct property *prop; u32 upa_portid; - int is_pbm_a, err; + int is_pbm_a; - upa_portid = prom_getintdefault(node, "upa-portid", 0xff); + upa_portid = 0xff; + prop = of_find_property(dp, "upa-portid", NULL); + if (prop) + upa_portid = *(u32 *) prop->value; for(p = pci_controller_root; p; p = p->next) { if (p->pbm_A.portid == upa_portid) { - is_pbm_a = (p->pbm_A.prom_node == 0); - psycho_pbm_init(p, node, is_pbm_a); + is_pbm_a = (p->pbm_A.prom_node == NULL); + psycho_pbm_init(p, dp, is_pbm_a); return; } } @@ -1489,23 +1413,14 @@ void psycho_init(int node, char *model_n p->resource_adjust = psycho_resource_adjust; p->pci_ops = &psycho_ops; - err = prom_getproperty(node, "reg", - (char *)&pr_regs[0], - sizeof(pr_regs)); - if (err == 0 || err == -1) { - prom_printf("PSYCHO: Fatal error, no reg property.\n"); - prom_halt(); - } + prop = of_find_property(dp, "reg", NULL); + pr_regs = prop->value; p->pbm_A.controller_regs = pr_regs[2].phys_addr; p->pbm_B.controller_regs = pr_regs[2].phys_addr; - printk("PCI: Found PSYCHO, control regs at %016lx\n", - p->pbm_A.controller_regs); p->pbm_A.config_space = p->pbm_B.config_space = (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); - printk("PSYCHO: Shared PCI config space at %016lx\n", - p->pbm_A.config_space); /* * Psycho's PCI MEM space is mapped to a 2GB aligned area, so @@ -1518,5 +1433,5 @@ void psycho_init(int node, char *model_n psycho_iommu_init(p); is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); - psycho_pbm_init(p, node, is_pbm_a); + psycho_pbm_init(p, dp, is_pbm_a); } diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index f67bb7f..26f194c 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -19,6 +19,7 @@ #include #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" @@ -523,78 +524,6 @@ #define sabre_iclr_offset(ino) ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3))) -/* PCI SABRE INO number to Sparc PIL level. */ -static unsigned char sabre_pil_table[] = { -/*0x00*/0, 0, 0, 0, /* PCI A slot 0 Int A, B, C, D */ -/*0x04*/0, 0, 0, 0, /* PCI A slot 1 Int A, B, C, D */ -/*0x08*/0, 0, 0, 0, /* PCI A slot 2 Int A, B, C, D */ -/*0x0c*/0, 0, 0, 0, /* PCI A slot 3 Int A, B, C, D */ -/*0x10*/0, 0, 0, 0, /* PCI B slot 0 Int A, B, C, D */ -/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */ -/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */ -/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */ -/*0x20*/5, /* SCSI */ -/*0x21*/5, /* Ethernet */ -/*0x22*/8, /* Parallel Port */ -/*0x23*/13, /* Audio Record */ -/*0x24*/14, /* Audio Playback */ -/*0x25*/15, /* PowerFail */ -/*0x26*/5, /* second SCSI */ -/*0x27*/11, /* Floppy */ -/*0x28*/5, /* Spare Hardware */ -/*0x29*/9, /* Keyboard */ -/*0x2a*/5, /* Mouse */ -/*0x2b*/12, /* Serial */ -/*0x2c*/10, /* Timer 0 */ -/*0x2d*/11, /* Timer 1 */ -/*0x2e*/15, /* Uncorrectable ECC */ -/*0x2f*/15, /* Correctable ECC */ -/*0x30*/15, /* PCI Bus A Error */ -/*0x31*/15, /* PCI Bus B Error */ -/*0x32*/15, /* Power Management */ -}; - -static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino) -{ - int ret; - - if (pdev && - pdev->vendor == PCI_VENDOR_ID_SUN && - pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) - return 9; - - ret = sabre_pil_table[ino]; - if (ret == 0 && pdev == NULL) { - ret = 5; - } else if (ret == 0) { - switch ((pdev->class >> 16) & 0xff) { - case PCI_BASE_CLASS_STORAGE: - ret = 5; - break; - - case PCI_BASE_CLASS_NETWORK: - ret = 6; - break; - - case PCI_BASE_CLASS_DISPLAY: - ret = 9; - break; - - case PCI_BASE_CLASS_MULTIMEDIA: - case PCI_BASE_CLASS_MEMORY: - case PCI_BASE_CLASS_BRIDGE: - case PCI_BASE_CLASS_SERIAL: - ret = 10; - break; - - default: - ret = 5; - break; - }; - } - return ret; -} - /* When a device lives behind a bridge deeper in the PCI bus topology * than APB, a special sequence must run to make sure all pending DMA * transfers at the time of IRQ delivery are visible in the coherency @@ -602,7 +531,7 @@ static int sabre_ino_to_pil(struct pci_d * side of the non-APB bridge, then perform a read of Sabre's DMA * write-sync register. */ -static void sabre_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) +static void sabre_wsync_handler(unsigned int ino, void *_arg1, void *_arg2) { struct pci_dev *pdev = _arg1; unsigned long sync_reg = (unsigned long) _arg2; @@ -616,10 +545,10 @@ static unsigned int sabre_irq_build(stru struct pci_dev *pdev, unsigned int ino) { - struct ino_bucket *bucket; unsigned long imap, iclr; unsigned long imap_off, iclr_off; - int pil, inofixup = 0; + int inofixup = 0; + int virt_irq; ino &= PCI_IRQ_INO; if (ino < SABRE_ONBOARD_IRQ_BASE) { @@ -635,11 +564,6 @@ static unsigned int sabre_irq_build(stru } /* Now build the IRQ bucket. */ - pil = sabre_ino_to_pil(pdev, ino); - - if (PIL_RESERVED(pil)) - BUG(); - imap = pbm->controller_regs + imap_off; imap += 4; @@ -650,23 +574,23 @@ static unsigned int sabre_irq_build(stru if ((ino & 0x20) == 0) inofixup = ino & 0x03; - bucket = __bucket(build_irq(pil, inofixup, iclr, imap)); - bucket->flags |= IBF_PCI; + virt_irq = build_irq(inofixup, iclr, imap); if (pdev) { struct pcidev_cookie *pcp = pdev->sysdata; if (pdev->bus->number != pcp->pbm->pci_first_busno) { struct pci_controller_info *p = pcp->pbm->parent; - struct irq_desc *d = bucket->irq_info; - d->pre_handler = sabre_wsync_handler; - d->pre_handler_arg1 = pdev; - d->pre_handler_arg2 = (void *) - p->pbm_A.controller_regs + SABRE_WRSYNC; + irq_install_pre_handler(virt_irq, + sabre_wsync_handler, + pdev, + (void *) + p->pbm_A.controller_regs + + SABRE_WRSYNC); } } - return __irq(bucket); + return virt_irq; } /* SABRE error handling support. */ @@ -1383,34 +1307,36 @@ static void pbm_register_toplevel_resour &pbm->mem_space); } -static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin) +static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin) { struct pci_pbm_info *pbm; - char namebuf[128]; - u32 busrange[2]; - int node, simbas_found; + struct device_node *node; + struct property *prop; + u32 *busrange; + int len, simbas_found; simbas_found = 0; - node = prom_getchild(sabre_node); - while ((node = prom_searchsiblings(node, "pci")) != 0) { - int err; - - err = prom_getproperty(node, "model", namebuf, sizeof(namebuf)); - if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err)) + node = dp->child; + while (node != NULL) { + if (strcmp(node->name, "pci")) goto next_pci; - err = prom_getproperty(node, "bus-range", - (char *)&busrange[0], sizeof(busrange)); - if (err == 0 || err == -1) { - prom_printf("APB: Error, cannot get PCI bus-range.\n"); - prom_halt(); - } + prop = of_find_property(node, "model", NULL); + if (!prop || strncmp(prop->value, "SUNW,simba", prop->length)) + goto next_pci; simbas_found++; + + prop = of_find_property(node, "bus-range", NULL); + busrange = prop->value; if (busrange[0] == 1) pbm = &p->pbm_B; else pbm = &p->pbm_A; + + pbm->name = node->full_name; + printk("%s: SABRE PCI Bus Module\n", pbm->name); + pbm->chip_type = PBM_CHIP_TYPE_SABRE; pbm->parent = p; pbm->prom_node = node; @@ -1418,83 +1344,68 @@ static void sabre_pbm_init(struct pci_co pbm->pci_first_busno = busrange[0]; pbm->pci_last_busno = busrange[1]; - prom_getstring(node, "name", pbm->prom_name, sizeof(pbm->prom_name)); - err = prom_getproperty(node, "ranges", - (char *)pbm->pbm_ranges, - sizeof(pbm->pbm_ranges)); - if (err != -1) + prop = of_find_property(node, "ranges", &len); + if (prop) { + pbm->pbm_ranges = prop->value; pbm->num_pbm_ranges = - (err / sizeof(struct linux_prom_pci_ranges)); - else + (len / sizeof(struct linux_prom_pci_ranges)); + } else { pbm->num_pbm_ranges = 0; + } - err = prom_getproperty(node, "interrupt-map", - (char *)pbm->pbm_intmap, - sizeof(pbm->pbm_intmap)); - if (err != -1) { - pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); - err = prom_getproperty(node, "interrupt-map-mask", - (char *)&pbm->pbm_intmask, - sizeof(pbm->pbm_intmask)); - if (err == -1) { - prom_printf("APB: Fatal error, no interrupt-map-mask.\n"); - prom_halt(); - } + prop = of_find_property(node, "interrupt-map", &len); + if (prop) { + pbm->pbm_intmap = prop->value; + pbm->num_pbm_intmap = + (len / sizeof(struct linux_prom_pci_intmap)); + + prop = of_find_property(node, "interrupt-map-mask", + NULL); + pbm->pbm_intmask = prop->value; } else { pbm->num_pbm_intmap = 0; - memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); } pbm_register_toplevel_resources(p, pbm); next_pci: - node = prom_getsibling(node); - if (!node) - break; + node = node->sibling; } if (simbas_found == 0) { - int err; - /* No APBs underneath, probably this is a hummingbird * system. */ pbm = &p->pbm_A; pbm->parent = p; - pbm->prom_node = sabre_node; + pbm->prom_node = dp; pbm->pci_first_busno = p->pci_first_busno; pbm->pci_last_busno = p->pci_last_busno; - prom_getstring(sabre_node, "name", pbm->prom_name, sizeof(pbm->prom_name)); - err = prom_getproperty(sabre_node, "ranges", - (char *) pbm->pbm_ranges, - sizeof(pbm->pbm_ranges)); - if (err != -1) + prop = of_find_property(dp, "ranges", &len); + if (prop) { + pbm->pbm_ranges = prop->value; pbm->num_pbm_ranges = - (err / sizeof(struct linux_prom_pci_ranges)); - else + (len / sizeof(struct linux_prom_pci_ranges)); + } else { pbm->num_pbm_ranges = 0; + } - err = prom_getproperty(sabre_node, "interrupt-map", - (char *) pbm->pbm_intmap, - sizeof(pbm->pbm_intmap)); - - if (err != -1) { - pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); - err = prom_getproperty(sabre_node, "interrupt-map-mask", - (char *)&pbm->pbm_intmask, - sizeof(pbm->pbm_intmask)); - if (err == -1) { - prom_printf("Hummingbird: Fatal error, no interrupt-map-mask.\n"); - prom_halt(); - } + prop = of_find_property(dp, "interrupt-map", &len); + if (prop) { + pbm->pbm_intmap = prop->value; + pbm->num_pbm_intmap = + (len / sizeof(struct linux_prom_pci_intmap)); + + prop = of_find_property(dp, "interrupt-map-mask", + NULL); + pbm->pbm_intmask = prop->value; } else { pbm->num_pbm_intmap = 0; - memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); } + pbm->name = dp->full_name; + printk("%s: SABRE PCI Bus Module\n", pbm->name); - sprintf(pbm->name, "SABRE%d PBM%c", p->index, - (pbm == &p->pbm_A ? 'A' : 'B')); pbm->io_space.name = pbm->mem_space.name = pbm->name; /* Hack up top-level resources. */ @@ -1520,14 +1431,15 @@ static void sabre_pbm_init(struct pci_co } } -void sabre_init(int pnode, char *model_name) +void sabre_init(struct device_node *dp, char *model_name) { - struct linux_prom64_registers pr_regs[2]; + struct linux_prom64_registers *pr_regs; struct pci_controller_info *p; struct pci_iommu *iommu; - int tsbsize, err; - u32 busrange[2]; - u32 vdma[2]; + struct property *prop; + int tsbsize; + u32 *busrange; + u32 *vdma; u32 upa_portid, dma_mask; u64 clear_irq; @@ -1535,22 +1447,21 @@ void sabre_init(int pnode, char *model_n if (!strcmp(model_name, "pci108e,a001")) hummingbird_p = 1; else if (!strcmp(model_name, "SUNW,sabre")) { - char compat[64]; + prop = of_find_property(dp, "compatible", NULL); + if (prop) { + const char *compat = prop->value; - if (prom_getproperty(pnode, "compatible", - compat, sizeof(compat)) > 0 && - !strcmp(compat, "pci108e,a001")) { - hummingbird_p = 1; - } else { - int cpu_node; + if (!strcmp(compat, "pci108e,a001")) + hummingbird_p = 1; + } + if (!hummingbird_p) { + struct device_node *dp; /* Of course, Sun has to encode things a thousand * different ways, inconsistently. */ - cpu_find_by_instance(0, &cpu_node, NULL); - if (prom_getproperty(cpu_node, "name", - compat, sizeof(compat)) > 0 && - !strcmp(compat, "SUNW,UltraSPARC-IIe")) + cpu_find_by_instance(0, &dp, NULL); + if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe")) hummingbird_p = 1; } } @@ -1568,7 +1479,10 @@ void sabre_init(int pnode, char *model_n } p->pbm_A.iommu = p->pbm_B.iommu = iommu; - upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff); + upa_portid = 0xff; + prop = of_find_property(dp, "upa-portid", NULL); + if (prop) + upa_portid = *(u32 *) prop->value; p->next = pci_controller_root; pci_controller_root = p; @@ -1586,13 +1500,9 @@ void sabre_init(int pnode, char *model_n /* * Map in SABRE register set and report the presence of this SABRE. */ - err = prom_getproperty(pnode, "reg", - (char *)&pr_regs[0], sizeof(pr_regs)); - if(err == 0 || err == -1) { - prom_printf("SABRE: Error, cannot get U2P registers " - "from PROM.\n"); - prom_halt(); - } + + prop = of_find_property(dp, "reg", NULL); + pr_regs = prop->value; /* * First REG in property is base of entire SABRE register space. @@ -1600,9 +1510,6 @@ void sabre_init(int pnode, char *model_n p->pbm_A.controller_regs = pr_regs[0].phys_addr; p->pbm_B.controller_regs = pr_regs[0].phys_addr; - printk("PCI: Found SABRE, main regs at %016lx\n", - p->pbm_A.controller_regs); - /* Clear interrupts */ /* PCI first */ @@ -1621,16 +1528,9 @@ void sabre_init(int pnode, char *model_n /* Now map in PCI config space for entire SABRE. */ p->pbm_A.config_space = p->pbm_B.config_space = (p->pbm_A.controller_regs + SABRE_CONFIGSPACE); - printk("SABRE: Shared PCI config space at %016lx\n", - p->pbm_A.config_space); - - err = prom_getproperty(pnode, "virtual-dma", - (char *)&vdma[0], sizeof(vdma)); - if(err == 0 || err == -1) { - prom_printf("SABRE: Error, cannot get virtual-dma property " - "from PROM.\n"); - prom_halt(); - } + + prop = of_find_property(dp, "virtual-dma", NULL); + vdma = prop->value; dma_mask = vdma[0]; switch(vdma[1]) { @@ -1654,21 +1554,13 @@ void sabre_init(int pnode, char *model_n sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); - printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]); - - err = prom_getproperty(pnode, "bus-range", - (char *)&busrange[0], sizeof(busrange)); - if(err == 0 || err == -1) { - prom_printf("SABRE: Error, cannot get PCI bus-range " - " from PROM.\n"); - prom_halt(); - } - + prop = of_find_property(dp, "bus-range", NULL); + busrange = prop->value; p->pci_first_busno = busrange[0]; p->pci_last_busno = busrange[1]; /* * Look for APB underneath. */ - sabre_pbm_init(p, pnode, vdma[0]); + sabre_pbm_init(p, dp, vdma[0]); } diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 7fe4de0..f16449c 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -16,6 +16,7 @@ #include #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" @@ -232,105 +233,10 @@ static unsigned long schizo_iclr_offset( return SCHIZO_ICLR_BASE + (ino * 8UL); } -/* PCI SCHIZO INO number to Sparc PIL level. This table only matters for - * INOs which will not have an associated PCI device struct, ie. onboard - * EBUS devices and PCI controller internal error interrupts. - */ -static unsigned char schizo_pil_table[] = { -/*0x00*/0, 0, 0, 0, /* PCI slot 0 Int A, B, C, D */ -/*0x04*/0, 0, 0, 0, /* PCI slot 1 Int A, B, C, D */ -/*0x08*/0, 0, 0, 0, /* PCI slot 2 Int A, B, C, D */ -/*0x0c*/0, 0, 0, 0, /* PCI slot 3 Int A, B, C, D */ -/*0x10*/0, 0, 0, 0, /* PCI slot 4 Int A, B, C, D */ -/*0x14*/0, 0, 0, 0, /* PCI slot 5 Int A, B, C, D */ -/*0x18*/5, /* SCSI */ -/*0x19*/5, /* second SCSI */ -/*0x1a*/0, /* UNKNOWN */ -/*0x1b*/0, /* UNKNOWN */ -/*0x1c*/8, /* Parallel */ -/*0x1d*/5, /* Ethernet */ -/*0x1e*/8, /* Firewire-1394 */ -/*0x1f*/9, /* USB */ -/*0x20*/13, /* Audio Record */ -/*0x21*/14, /* Audio Playback */ -/*0x22*/12, /* Serial */ -/*0x23*/5, /* EBUS I2C */ -/*0x24*/10, /* RTC Clock */ -/*0x25*/11, /* Floppy */ -/*0x26*/0, /* UNKNOWN */ -/*0x27*/0, /* UNKNOWN */ -/*0x28*/0, /* UNKNOWN */ -/*0x29*/0, /* UNKNOWN */ -/*0x2a*/10, /* UPA 1 */ -/*0x2b*/10, /* UPA 2 */ -/*0x2c*/0, /* UNKNOWN */ -/*0x2d*/0, /* UNKNOWN */ -/*0x2e*/0, /* UNKNOWN */ -/*0x2f*/0, /* UNKNOWN */ -/*0x30*/15, /* Uncorrectable ECC */ -/*0x31*/15, /* Correctable ECC */ -/*0x32*/15, /* PCI Bus A Error */ -/*0x33*/15, /* PCI Bus B Error */ -/*0x34*/15, /* Safari Bus Error */ -/*0x35*/0, /* Reserved */ -/*0x36*/0, /* Reserved */ -/*0x37*/0, /* Reserved */ -/*0x38*/0, /* Reserved for NewLink */ -/*0x39*/0, /* Reserved for NewLink */ -/*0x3a*/0, /* Reserved for NewLink */ -/*0x3b*/0, /* Reserved for NewLink */ -/*0x3c*/0, /* Reserved for NewLink */ -/*0x3d*/0, /* Reserved for NewLink */ -/*0x3e*/0, /* Reserved for NewLink */ -/*0x3f*/0, /* Reserved for NewLink */ -}; - -static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino) -{ - int ret; - - if (pdev && - pdev->vendor == PCI_VENDOR_ID_SUN && - pdev->device == PCI_DEVICE_ID_SUN_RIO_USB) - return 9; - - ret = schizo_pil_table[ino]; - if (ret == 0 && pdev == NULL) { - ret = 5; - } else if (ret == 0) { - switch ((pdev->class >> 16) & 0xff) { - case PCI_BASE_CLASS_STORAGE: - ret = 5; - break; - - case PCI_BASE_CLASS_NETWORK: - ret = 6; - break; - - case PCI_BASE_CLASS_DISPLAY: - ret = 9; - break; - - case PCI_BASE_CLASS_MULTIMEDIA: - case PCI_BASE_CLASS_MEMORY: - case PCI_BASE_CLASS_BRIDGE: - case PCI_BASE_CLASS_SERIAL: - ret = 10; - break; - - default: - ret = 5; - break; - }; - } - - return ret; -} - -static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) +static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2) { unsigned long sync_reg = (unsigned long) _arg2; - u64 mask = 1UL << (__irq_ino(__irq(bucket)) & IMAP_INO); + u64 mask = 1UL << (ino & IMAP_INO); u64 val; int limit; @@ -365,30 +271,33 @@ static void tomatillo_wsync_handler(stru } } +static unsigned long schizo_ino_to_iclr(struct pci_pbm_info *pbm, + unsigned int ino) +{ + ino &= PCI_IRQ_INO; + return pbm->pbm_regs + schizo_iclr_offset(ino) + 4; +} + +static unsigned long schizo_ino_to_imap(struct pci_pbm_info *pbm, + unsigned int ino) +{ + ino &= PCI_IRQ_INO; + return pbm->pbm_regs + schizo_imap_offset(ino) + 4; +} + static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, struct pci_dev *pdev, unsigned int ino) { - struct ino_bucket *bucket; unsigned long imap, iclr; - unsigned long imap_off, iclr_off; - int pil, ign_fixup; + int ign_fixup; + int virt_irq; ino &= PCI_IRQ_INO; - imap_off = schizo_imap_offset(ino); /* Now build the IRQ bucket. */ - pil = schizo_ino_to_pil(pdev, ino); - - if (PIL_RESERVED(pil)) - BUG(); - - imap = pbm->pbm_regs + imap_off; - imap += 4; - - iclr_off = schizo_iclr_offset(ino); - iclr = pbm->pbm_regs + iclr_off; - iclr += 4; + imap = schizo_ino_to_imap(pbm, ino); + iclr = schizo_ino_to_iclr(pbm, ino); /* On Schizo, no inofixup occurs. This is because each * INO has it's own IMAP register. On Psycho and Sabre @@ -405,19 +314,17 @@ static unsigned int schizo_irq_build(str ign_fixup = (1 << 6); } - bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap)); - bucket->flags |= IBF_PCI; + virt_irq = build_irq(ign_fixup, iclr, imap); if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { - struct irq_desc *p = bucket->irq_info; - - p->pre_handler = tomatillo_wsync_handler; - p->pre_handler_arg1 = ((pbm->chip_version <= 4) ? - (void *) 1 : (void *) 0); - p->pre_handler_arg2 = (void *) pbm->sync_reg; + irq_install_pre_handler(virt_irq, + tomatillo_wsync_handler, + ((pbm->chip_version <= 4) ? + (void *) 1 : (void *) 0), + (void *) pbm->sync_reg); } - return __irq(bucket); + return virt_irq; } /* SCHIZO error handling support. */ @@ -458,7 +365,6 @@ struct pci_pbm_info *pbm_for_ino(struct static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq) { struct pci_pbm_info *pbm; - struct ino_bucket *bucket; unsigned long iclr; /* Do not clear the interrupt for the other PCI bus. @@ -476,11 +382,11 @@ static void schizo_clear_other_err_intr( else pbm = &p->pbm_A; - irq = schizo_irq_build(pbm, NULL, - (pbm->portid << 6) | (irq & IMAP_INO)); - bucket = __bucket(irq); - iclr = bucket->iclr; + schizo_irq_build(pbm, NULL, + (pbm->portid << 6) | (irq & IMAP_INO)); + iclr = schizo_ino_to_iclr(pbm, + (pbm->portid << 6) | (irq & IMAP_INO)); upa_writel(ICLR_IDLE, iclr); } @@ -1225,7 +1131,6 @@ static void tomatillo_register_error_han { struct pci_pbm_info *pbm; unsigned int irq; - struct ino_bucket *bucket; u64 tmp, err_mask, err_no_mask; /* Build IRQs and register handlers. */ @@ -1237,8 +1142,7 @@ static void tomatillo_register_error_han pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); @@ -1250,8 +1154,7 @@ static void tomatillo_register_error_han pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); @@ -1264,8 +1167,8 @@ static void tomatillo_register_error_han pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | + SCHIZO_PCIERR_A_INO))); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); @@ -1278,8 +1181,8 @@ static void tomatillo_register_error_han pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | + SCHIZO_PCIERR_B_INO))); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); @@ -1291,8 +1194,8 @@ static void tomatillo_register_error_han pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) | + SCHIZO_SERR_INO))); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); @@ -1363,7 +1266,6 @@ static void schizo_register_error_handle { struct pci_pbm_info *pbm; unsigned int irq; - struct ino_bucket *bucket; u64 tmp, err_mask, err_no_mask; /* Build IRQs and register handlers. */ @@ -1375,8 +1277,7 @@ static void schizo_register_error_handle pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_CE_INO); @@ -1387,8 +1288,7 @@ static void schizo_register_error_handle pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); @@ -1399,8 +1299,7 @@ static void schizo_register_error_handle pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); @@ -1411,8 +1310,7 @@ static void schizo_register_error_handle pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4)); pbm = pbm_for_ino(p, SCHIZO_SERR_INO); @@ -1423,8 +1321,7 @@ static void schizo_register_error_handle pbm->name); prom_halt(); } - bucket = __bucket(irq); - tmp = upa_readl(bucket->imap); + tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_SERR_INO)); upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4)); /* Enable UE and CE interrupts for controller. */ @@ -1560,10 +1457,12 @@ static void __schizo_scan_bus(struct pci pbm_config_busmastering(&p->pbm_B); p->pbm_B.is_66mhz_capable = - prom_getbool(p->pbm_B.prom_node, "66mhz-capable"); + (of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL) + != NULL); pbm_config_busmastering(&p->pbm_A); p->pbm_A.is_66mhz_capable = - prom_getbool(p->pbm_A.prom_node, "66mhz-capable"); + (of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL) + != NULL); pbm_scan_bus(p, &p->pbm_B); pbm_scan_bus(p, &p->pbm_A); @@ -1765,13 +1664,18 @@ static void schizo_pbm_iommu_init(struct { struct pci_iommu *iommu = pbm->iommu; unsigned long i, tagbase, database; + struct property *prop; u32 vdma[2], dma_mask; u64 control; - int err, tsbsize; + int tsbsize; + + prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); + if (prop) { + u32 *val = prop->value; - err = prom_getproperty(pbm->prom_node, "virtual-dma", - (char *)&vdma[0], sizeof(vdma)); - if (err == 0 || err == -1) { + vdma[0] = val[0]; + vdma[1] = val[1]; + } else { /* No property, use default values. */ vdma[0] = 0xc0000000; vdma[1] = 0x40000000; @@ -1882,6 +1786,7 @@ #define TOMATILLO_PCI_IOC_DDIAG (0x2290 static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) { + struct property *prop; u64 tmp; schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); @@ -1895,7 +1800,8 @@ static void schizo_pbm_hw_init(struct pc pbm->chip_version >= 0x2) tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; - if (!prom_getbool(pbm->prom_node, "no-bus-parking")) + prop = of_find_property(pbm->prom_node, "no-bus-parking", NULL); + if (!prop) tmp |= SCHIZO_PCICTRL_PARK; else tmp &= ~SCHIZO_PCICTRL_PARK; @@ -1935,16 +1841,17 @@ static void schizo_pbm_hw_init(struct pc } static void schizo_pbm_init(struct pci_controller_info *p, - int prom_node, u32 portid, + struct device_node *dp, u32 portid, int chip_type) { - struct linux_prom64_registers pr_regs[4]; - unsigned int busrange[2]; + struct linux_prom64_registers *regs; + struct property *prop; + unsigned int *busrange; struct pci_pbm_info *pbm; const char *chipset_name; - u32 ino_bitmap[2]; + u32 *ino_bitmap; int is_pbm_a; - int err; + int len; switch (chip_type) { case PBM_CHIP_TYPE_TOMATILLO: @@ -1972,16 +1879,10 @@ static void schizo_pbm_init(struct pci_c * 3) PBM PCI config space * 4) Ichip regs */ - err = prom_getproperty(prom_node, "reg", - (char *)&pr_regs[0], - sizeof(pr_regs)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no reg property.\n", - chipset_name); - prom_halt(); - } + prop = of_find_property(dp, "reg", NULL); + regs = prop->value; - is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000); + is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); if (is_pbm_a) pbm = &p->pbm_A; @@ -1990,92 +1891,62 @@ static void schizo_pbm_init(struct pci_c pbm->portid = portid; pbm->parent = p; - pbm->prom_node = prom_node; + pbm->prom_node = dp; pbm->pci_first_slot = 1; pbm->chip_type = chip_type; - pbm->chip_version = - prom_getintdefault(prom_node, "version#", 0); - pbm->chip_revision = - prom_getintdefault(prom_node, "module-revision#", 0); - - pbm->pbm_regs = pr_regs[0].phys_addr; - pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL; + pbm->chip_version = 0; + prop = of_find_property(dp, "version#", NULL); + if (prop) + pbm->chip_version = *(int *) prop->value; + pbm->chip_revision = 0; + prop = of_find_property(dp, "module-revision#", NULL); + if (prop) + pbm->chip_revision = *(int *) prop->value; + + pbm->pbm_regs = regs[0].phys_addr; + pbm->controller_regs = regs[1].phys_addr - 0x10000UL; if (chip_type == PBM_CHIP_TYPE_TOMATILLO) - pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL; + pbm->sync_reg = regs[3].phys_addr + 0x1a18UL; - sprintf(pbm->name, - (chip_type == PBM_CHIP_TYPE_TOMATILLO ? - "TOMATILLO%d PBM%c" : - "SCHIZO%d PBM%c"), - p->index, - (pbm == &p->pbm_A ? 'A' : 'B')); + pbm->name = dp->full_name; - printk("%s: ver[%x:%x], portid %x, " - "cregs[%lx] pregs[%lx]\n", + printk("%s: %s PCI Bus Module ver[%x:%x]\n", pbm->name, - pbm->chip_version, pbm->chip_revision, - pbm->portid, - pbm->controller_regs, - pbm->pbm_regs); + (chip_type == PBM_CHIP_TYPE_TOMATILLO ? + "TOMATILLO" : "SCHIZO"), + pbm->chip_version, pbm->chip_revision); schizo_pbm_hw_init(pbm); - prom_getstring(prom_node, "name", - pbm->prom_name, - sizeof(pbm->prom_name)); - - err = prom_getproperty(prom_node, "ranges", - (char *) pbm->pbm_ranges, - sizeof(pbm->pbm_ranges)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no ranges property.\n", - pbm->name); - prom_halt(); - } - + prop = of_find_property(dp, "ranges", &len); + pbm->pbm_ranges = prop->value; pbm->num_pbm_ranges = - (err / sizeof(struct linux_prom_pci_ranges)); + (len / sizeof(struct linux_prom_pci_ranges)); schizo_determine_mem_io_space(pbm); pbm_register_toplevel_resources(p, pbm); - err = prom_getproperty(prom_node, "interrupt-map", - (char *)pbm->pbm_intmap, - sizeof(pbm->pbm_intmap)); - if (err != -1) { - pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); - err = prom_getproperty(prom_node, "interrupt-map-mask", - (char *)&pbm->pbm_intmask, - sizeof(pbm->pbm_intmask)); - if (err == -1) { - prom_printf("%s: Fatal error, no " - "interrupt-map-mask.\n", pbm->name); - prom_halt(); - } + prop = of_find_property(dp, "interrupt-map", &len); + if (prop) { + pbm->pbm_intmap = prop->value; + pbm->num_pbm_intmap = + (len / sizeof(struct linux_prom_pci_intmap)); + + prop = of_find_property(dp, "interrupt-map-mask", NULL); + pbm->pbm_intmask = prop->value; } else { pbm->num_pbm_intmap = 0; - memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask)); } - err = prom_getproperty(prom_node, "ino-bitmap", - (char *) &ino_bitmap[0], - sizeof(ino_bitmap)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no ino-bitmap.\n", pbm->name); - prom_halt(); - } + prop = of_find_property(dp, "ino-bitmap", NULL); + ino_bitmap = prop->value; pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) | ((u64)ino_bitmap[0] << 0UL)); - err = prom_getproperty(prom_node, "bus-range", - (char *)&busrange[0], - sizeof(busrange)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no bus-range.\n", pbm->name); - prom_halt(); - } + prop = of_find_property(dp, "bus-range", NULL); + busrange = prop->value; pbm->pci_first_busno = busrange[0]; pbm->pci_last_busno = busrange[1]; @@ -2093,16 +1964,20 @@ static inline int portid_compare(u32 x, return (x == y); } -static void __schizo_init(int node, char *model_name, int chip_type) +static void __schizo_init(struct device_node *dp, char *model_name, int chip_type) { struct pci_controller_info *p; struct pci_iommu *iommu; + struct property *prop; int is_pbm_a; u32 portid; - portid = prom_getintdefault(node, "portid", 0xff); + portid = 0xff; + prop = of_find_property(dp, "portid", NULL); + if (prop) + portid = *(u32 *) prop->value; - for(p = pci_controller_root; p; p = p->next) { + for (p = pci_controller_root; p; p = p->next) { struct pci_pbm_info *pbm; if (p->pbm_A.prom_node && p->pbm_B.prom_node) @@ -2113,8 +1988,8 @@ static void __schizo_init(int node, char &p->pbm_B); if (portid_compare(pbm->portid, portid, chip_type)) { - is_pbm_a = (p->pbm_A.prom_node == 0); - schizo_pbm_init(p, node, portid, chip_type); + is_pbm_a = (p->pbm_A.prom_node == NULL); + schizo_pbm_init(p, dp, portid, chip_type); return; } } @@ -2155,20 +2030,20 @@ static void __schizo_init(int node, char /* Like PSYCHO we have a 2GB aligned area for memory space. */ pci_memspace_mask = 0x7fffffffUL; - schizo_pbm_init(p, node, portid, chip_type); + schizo_pbm_init(p, dp, portid, chip_type); } -void schizo_init(int node, char *model_name) +void schizo_init(struct device_node *dp, char *model_name) { - __schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO); + __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO); } -void schizo_plus_init(int node, char *model_name) +void schizo_plus_init(struct device_node *dp, char *model_name) { - __schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); + __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); } -void tomatillo_init(int node, char *model_name) +void tomatillo_init(struct device_node *dp, char *model_name) { - __schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO); + __schizo_init(dp, model_name, PBM_CHIP_TYPE_TOMATILLO); } diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 0c08952..b69e227 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -18,6 +18,7 @@ #include #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" @@ -646,35 +647,37 @@ static int pdev_htab_add(u32 devhandle, /* Recursively descend into the OBP device tree, rooted at toplevel_node, * looking for a PCI device matching bus and devfn. */ -static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn) +static int obp_find(struct device_node *toplevel_node, unsigned int bus, unsigned int devfn) { - toplevel_node = prom_getchild(toplevel_node); + toplevel_node = toplevel_node->child; - while (toplevel_node != 0) { - int ret = obp_find(pregs, toplevel_node, bus, devfn); + while (toplevel_node != NULL) { + struct linux_prom_pci_registers *regs; + struct property *prop; + int ret; + ret = obp_find(toplevel_node, bus, devfn); if (ret != 0) return ret; - ret = prom_getproperty(toplevel_node, "reg", (char *) pregs, - sizeof(*pregs) * PROMREG_MAX); - if (ret == 0 || ret == -1) + prop = of_find_property(toplevel_node, "reg", NULL); + if (!prop) goto next_sibling; - if (((pregs[0].phys_hi >> 16) & 0xff) == bus && - ((pregs[0].phys_hi >> 8) & 0xff) == devfn) + regs = prop->value; + if (((regs->phys_hi >> 16) & 0xff) == bus && + ((regs->phys_hi >> 8) & 0xff) == devfn) break; next_sibling: - toplevel_node = prom_getsibling(toplevel_node); + toplevel_node = toplevel_node->sibling; } - return toplevel_node; + return toplevel_node != NULL; } static int pdev_htab_populate(struct pci_pbm_info *pbm) { - struct linux_prom_pci_registers pr[PROMREG_MAX]; u32 devhandle = pbm->devhandle; unsigned int bus; @@ -685,7 +688,7 @@ static int pdev_htab_populate(struct pci unsigned int device = PCI_SLOT(devfn); unsigned int func = PCI_FUNC(devfn); - if (obp_find(pr, pbm->prom_node, bus, devfn)) { + if (obp_find(pbm->prom_node, bus, devfn)) { int err = pdev_htab_add(devhandle, bus, device, func); if (err) @@ -811,8 +814,7 @@ #if 0 pci_fixup_host_bridge_self(pbm->pci_bus); pbm->pci_bus->self->sysdata = cookie; #endif - pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, - pbm->prom_node); + pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); pci_record_assignments(pbm, pbm->pci_bus); pci_assign_unassigned(pbm, pbm->pci_bus); pci_fixup_irq(pbm, pbm->pci_bus); @@ -822,15 +824,18 @@ #endif static void pci_sun4v_scan_bus(struct pci_controller_info *p) { - if (p->pbm_A.prom_node) { - p->pbm_A.is_66mhz_capable = - prom_getbool(p->pbm_A.prom_node, "66mhz-capable"); + struct property *prop; + struct device_node *dp; + + if ((dp = p->pbm_A.prom_node) != NULL) { + prop = of_find_property(dp, "66mhz-capable", NULL); + p->pbm_A.is_66mhz_capable = (prop != NULL); pbm_scan_bus(p, &p->pbm_A); } - if (p->pbm_B.prom_node) { - p->pbm_B.is_66mhz_capable = - prom_getbool(p->pbm_B.prom_node, "66mhz-capable"); + if ((dp = p->pbm_B.prom_node) != NULL) { + prop = of_find_property(dp, "66mhz-capable", NULL); + p->pbm_B.is_66mhz_capable = (prop != NULL); pbm_scan_bus(p, &p->pbm_B); } @@ -843,38 +848,8 @@ static unsigned int pci_sun4v_irq_build( unsigned int devino) { u32 devhandle = pbm->devhandle; - int pil; - - pil = 5; - if (pdev) { - switch ((pdev->class >> 16) & 0xff) { - case PCI_BASE_CLASS_STORAGE: - pil = 5; - break; - - case PCI_BASE_CLASS_NETWORK: - pil = 6; - break; - - case PCI_BASE_CLASS_DISPLAY: - pil = 9; - break; - - case PCI_BASE_CLASS_MULTIMEDIA: - case PCI_BASE_CLASS_MEMORY: - case PCI_BASE_CLASS_BRIDGE: - case PCI_BASE_CLASS_SERIAL: - pil = 10; - break; - - default: - pil = 5; - break; - }; - } - BUG_ON(PIL_RESERVED(pil)); - return sun4v_build_irq(devhandle, devino, pil, IBF_PCI); + return sun4v_build_irq(devhandle, devino); } static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource) @@ -1012,8 +987,13 @@ static unsigned long probe_existing_entr HV_PCI_TSBID(0, i), &io_attrs, &ra); if (ret == HV_EOK) { - cnt++; - __set_bit(i, arena->map); + if (page_in_phys_avail(ra)) { + pci_sun4v_iommu_demap(devhandle, + HV_PCI_TSBID(0, i), 1); + } else { + cnt++; + __set_bit(i, arena->map); + } } } @@ -1023,13 +1003,18 @@ static unsigned long probe_existing_entr static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) { struct pci_iommu *iommu = pbm->iommu; + struct property *prop; unsigned long num_tsb_entries, sz; u32 vdma[2], dma_mask, dma_offset; - int err, tsbsize; + int tsbsize; + + prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); + if (prop) { + u32 *val = prop->value; - err = prom_getproperty(pbm->prom_node, "virtual-dma", - (char *)&vdma[0], sizeof(vdma)); - if (err == 0 || err == -1) { + vdma[0] = val[0]; + vdma[1] = val[1]; + } else { /* No property, use default values. */ vdma[0] = 0x80000000; vdma[1] = 0x80000000; @@ -1081,34 +1066,30 @@ static void pci_sun4v_iommu_init(struct iommu->arena.limit = num_tsb_entries; sz = probe_existing_entries(pbm, iommu); - - printk("%s: TSB entries [%lu], existing mapings [%lu]\n", - pbm->name, num_tsb_entries, sz); + if (sz) + printk("%s: Imported %lu TSB entries from OBP\n", + pbm->name, sz); } static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) { - unsigned int busrange[2]; - int prom_node = pbm->prom_node; - int err; - - err = prom_getproperty(prom_node, "bus-range", - (char *)&busrange[0], - sizeof(busrange)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no bus-range.\n", pbm->name); - prom_halt(); - } + struct property *prop; + unsigned int *busrange; + + prop = of_find_property(pbm->prom_node, "bus-range", NULL); + + busrange = prop->value; pbm->pci_first_busno = busrange[0]; pbm->pci_last_busno = busrange[1]; } -static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 devhandle) +static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle) { struct pci_pbm_info *pbm; - int err, i; + struct property *prop; + int len, i; if (devhandle & 0x40) pbm = &p->pbm_B; @@ -1116,32 +1097,19 @@ static void pci_sun4v_pbm_init(struct pc pbm = &p->pbm_A; pbm->parent = p; - pbm->prom_node = prom_node; + pbm->prom_node = dp; pbm->pci_first_slot = 1; pbm->devhandle = devhandle; - sprintf(pbm->name, "SUN4V-PCI%d PBM%c", - p->index, (pbm == &p->pbm_A ? 'A' : 'B')); + pbm->name = dp->full_name; - printk("%s: devhandle[%x] prom_node[%x:%x]\n", - pbm->name, pbm->devhandle, - pbm->prom_node, prom_getchild(pbm->prom_node)); - - prom_getstring(prom_node, "name", - pbm->prom_name, sizeof(pbm->prom_name)); - - err = prom_getproperty(prom_node, "ranges", - (char *) pbm->pbm_ranges, - sizeof(pbm->pbm_ranges)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no ranges property.\n", - pbm->name); - prom_halt(); - } + printk("%s: SUN4V PCI Bus Module\n", pbm->name); + prop = of_find_property(dp, "ranges", &len); + pbm->pbm_ranges = prop->value; pbm->num_pbm_ranges = - (err / sizeof(struct linux_prom_pci_ranges)); + (len / sizeof(struct linux_prom_pci_ranges)); /* Mask out the top 8 bits of the ranges, leaving the real * physical address. @@ -1152,24 +1120,13 @@ static void pci_sun4v_pbm_init(struct pc pci_sun4v_determine_mem_io_space(pbm); pbm_register_toplevel_resources(p, pbm); - err = prom_getproperty(prom_node, "interrupt-map", - (char *)pbm->pbm_intmap, - sizeof(pbm->pbm_intmap)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no interrupt-map property.\n", - pbm->name); - prom_halt(); - } + prop = of_find_property(dp, "interrupt-map", &len); + pbm->pbm_intmap = prop->value; + pbm->num_pbm_intmap = + (len / sizeof(struct linux_prom_pci_intmap)); - pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap)); - err = prom_getproperty(prom_node, "interrupt-map-mask", - (char *)&pbm->pbm_intmask, - sizeof(pbm->pbm_intmask)); - if (err == 0 || err == -1) { - prom_printf("%s: Fatal error, no interrupt-map-mask.\n", - pbm->name); - prom_halt(); - } + prop = of_find_property(dp, "interrupt-map-mask", NULL); + pbm->pbm_intmask = prop->value; pci_sun4v_get_bus_range(pbm); pci_sun4v_iommu_init(pbm); @@ -1177,16 +1134,19 @@ static void pci_sun4v_pbm_init(struct pc pdev_htab_populate(pbm); } -void sun4v_pci_init(int node, char *model_name) +void sun4v_pci_init(struct device_node *dp, char *model_name) { struct pci_controller_info *p; struct pci_iommu *iommu; - struct linux_prom64_registers regs; + struct property *prop; + struct linux_prom64_registers *regs; u32 devhandle; int i; - prom_getproperty(node, "reg", (char *)®s, sizeof(regs)); - devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; + prop = of_find_property(dp, "reg", NULL); + regs = prop->value; + + devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; for (p = pci_controller_root; p; p = p->next) { struct pci_pbm_info *pbm; @@ -1199,7 +1159,7 @@ void sun4v_pci_init(int node, char *mode &p->pbm_B); if (pbm->devhandle == (devhandle ^ 0x40)) { - pci_sun4v_pbm_init(p, node, devhandle); + pci_sun4v_pbm_init(p, dp, devhandle); return; } } @@ -1250,7 +1210,7 @@ void sun4v_pci_init(int node, char *mode */ pci_memspace_mask = 0x7fffffffUL; - pci_sun4v_pbm_init(p, node, devhandle); + pci_sun4v_pbm_init(p, dp, devhandle); return; fatal_memory_error: diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 30bcaf5..9496c77 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -105,76 +105,25 @@ again: return 0; } -static int __init has_button_interrupt(unsigned int irq, int prom_node) +static int __init has_button_interrupt(unsigned int irq, struct device_node *dp) { if (irq == PCI_IRQ_NONE) return 0; - if (!prom_node_has_property(prom_node, "button")) + if (!of_find_property(dp, "button", NULL)) return 0; return 1; } -static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p) +static void __devinit power_probe_common(struct of_device *dev, struct resource *res, unsigned int irq) { - struct linux_ebus *ebus; - struct linux_ebus_device *edev; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "power")) { - *resp = &edev->resource[0]; - *irq_p = edev->irqs[0]; - *prom_node_p = edev->prom_node; - return 0; - } - } - } - return -ENODEV; -} - -static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p) -{ - struct sparc_isa_bridge *isa_bus; - struct sparc_isa_device *isa_dev; - - for_each_isa(isa_bus) { - for_each_isadev(isa_dev, isa_bus) { - if (!strcmp(isa_dev->prom_name, "power")) { - *resp = &isa_dev->resource; - *irq_p = isa_dev->irq; - *prom_node_p = isa_dev->prom_node; - return 0; - } - } - } - return -ENODEV; -} - -void __init power_init(void) -{ - struct resource *res = NULL; - unsigned int irq; - int prom_node; - static int invoked; - - if (invoked) - return; - invoked = 1; - - if (!power_probe_ebus(&res, &irq, &prom_node)) - goto found; - - if (!power_probe_isa(&res, &irq, &prom_node)) - goto found; - - return; - -found: power_reg = ioremap(res->start, 0x4); + printk("power: Control reg at %p ... ", power_reg); + poweroff_method = machine_halt; /* able to use the standard halt */ - if (has_button_interrupt(irq, prom_node)) { + + if (has_button_interrupt(irq, dev->node)) { if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { printk("Failed to start power daemon.\n"); return; @@ -188,4 +137,52 @@ found: printk("not using powerd.\n"); } } + +static struct of_device_id power_match[] = { + { + .name = "power", + }, + {}, +}; + +static int __devinit ebus_power_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct linux_ebus_device *edev = to_ebus_device(&dev->dev); + struct resource *res = &edev->resource[0]; + unsigned int irq = edev->irqs[0]; + + power_probe_common(dev, res,irq); + + return 0; +} + +static struct of_platform_driver ebus_power_driver = { + .name = "power", + .match_table = power_match, + .probe = ebus_power_probe, +}; + +static int __devinit isa_power_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct sparc_isa_device *idev = to_isa_device(&dev->dev); + struct resource *res = &idev->resource; + unsigned int irq = idev->irq; + + power_probe_common(dev, res,irq); + + return 0; +} + +static struct of_platform_driver isa_power_driver = { + .name = "power", + .match_table = power_match, + .probe = isa_power_probe, +}; + +void __init power_init(void) +{ + of_register_driver(&ebus_power_driver, &ebus_bus_type); + of_register_driver(&isa_power_driver, &isa_bus_type); + return; +} #endif /* CONFIG_PCI */ diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c new file mode 100644 index 0000000..8e87e7e --- /dev/null +++ b/arch/sparc64/kernel/prom.c @@ -0,0 +1,721 @@ +/* + * Procedures for creating, accessing and interpreting the device tree. + * + * Paul Mackerras August 1996. + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. + * {engebret|bergner}@us.ibm.com + * + * Adapted for sparc64 by David S. Miller davem@davemloft.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +static struct device_node *allnodes; + +/* use when traversing tree through the allnext, child, sibling, + * or parent members of struct device_node. + */ +static DEFINE_RWLOCK(devtree_lock); + +int of_device_is_compatible(struct device_node *device, const char *compat) +{ + const char* cp; + int cplen, l; + + cp = (char *) of_get_property(device, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + if (strncmp(cp, compat, strlen(compat)) == 0) + return 1; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} +EXPORT_SYMBOL(of_device_is_compatible); + +struct device_node *of_get_parent(const struct device_node *node) +{ + struct device_node *np; + + if (!node) + return NULL; + + np = node->parent; + + return np; +} +EXPORT_SYMBOL(of_get_parent); + +struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev) +{ + struct device_node *next; + + next = prev ? prev->sibling : node->child; + for (; next != 0; next = next->sibling) { + break; + } + + return next; +} +EXPORT_SYMBOL(of_get_next_child); + +struct device_node *of_find_node_by_path(const char *path) +{ + struct device_node *np = allnodes; + + for (; np != 0; np = np->allnext) { + if (np->full_name != 0 && strcmp(np->full_name, path) == 0) + break; + } + + return np; +} +EXPORT_SYMBOL(of_find_node_by_path); + +struct device_node *of_find_node_by_phandle(phandle handle) +{ + struct device_node *np; + + for (np = allnodes; np != 0; np = np->allnext) + if (np->node == handle) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_phandle); + +struct device_node *of_find_node_by_name(struct device_node *from, + const char *name) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != NULL; np = np->allnext) + if (np->name != NULL && strcmp(np->name, name) == 0) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_name); + +struct device_node *of_find_node_by_type(struct device_node *from, + const char *type) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != 0; np = np->allnext) + if (np->type != 0 && strcmp(np->type, type) == 0) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_type); + +struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compatible) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != 0; np = np->allnext) { + if (type != NULL + && !(np->type != 0 && strcmp(np->type, type) == 0)) + continue; + if (of_device_is_compatible(np, compatible)) + break; + } + + return np; +} +EXPORT_SYMBOL(of_find_compatible_node); + +struct property *of_find_property(struct device_node *np, const char *name, + int *lenp) +{ + struct property *pp; + + for (pp = np->properties; pp != 0; pp = pp->next) { + if (strcmp(pp->name, name) == 0) { + if (lenp != 0) + *lenp = pp->length; + break; + } + } + return pp; +} +EXPORT_SYMBOL(of_find_property); + +/* + * Find a property with a given name for a given node + * and return the value. + */ +void *of_get_property(struct device_node *np, const char *name, int *lenp) +{ + struct property *pp = of_find_property(np,name,lenp); + return pp ? pp->value : NULL; +} +EXPORT_SYMBOL(of_get_property); + +int of_getintprop_default(struct device_node *np, const char *name, int def) +{ + struct property *prop; + int len; + + prop = of_find_property(np, name, &len); + if (!prop || len != 4) + return def; + + return *(int *) prop->value; +} +EXPORT_SYMBOL(of_getintprop_default); + +int of_set_property(struct device_node *dp, const char *name, void *val, int len) +{ + struct property **prevp; + void *new_val; + int err; + + new_val = kmalloc(len, GFP_KERNEL); + if (!new_val) + return -ENOMEM; + + memcpy(new_val, val, len); + + err = -ENODEV; + + write_lock(&devtree_lock); + prevp = &dp->properties; + while (*prevp) { + struct property *prop = *prevp; + + if (!strcmp(prop->name, name)) { + void *old_val = prop->value; + int ret; + + ret = prom_setprop(dp->node, name, val, len); + err = -EINVAL; + if (ret >= 0) { + prop->value = new_val; + prop->length = len; + + if (OF_IS_DYNAMIC(prop)) + kfree(old_val); + + OF_MARK_DYNAMIC(prop); + + err = 0; + } + break; + } + prevp = &(*prevp)->next; + } + write_unlock(&devtree_lock); + + /* XXX Upate procfs if necessary... */ + + return err; +} +EXPORT_SYMBOL(of_set_property); + +static unsigned int prom_early_allocated; + +static void * __init prom_early_alloc(unsigned long size) +{ + void *ret; + + ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); + if (ret != NULL) + memset(ret, 0, size); + + prom_early_allocated += size; + + return ret; +} + +static int is_root_node(const struct device_node *dp) +{ + if (!dp) + return 0; + + return (dp->parent == NULL); +} + +/* The following routines deal with the black magic of fully naming a + * node. + * + * Certain well known named nodes are just the simple name string. + * + * Actual devices have an address specifier appended to the base name + * string, like this "foo@addr". The "addr" can be in any number of + * formats, and the platform plus the type of the node determine the + * format and how it is constructed. + * + * For children of the ROOT node, the naming convention is fixed and + * determined by whether this is a sun4u or sun4v system. + * + * For children of other nodes, it is bus type specific. So + * we walk up the tree until we discover a "device_type" property + * we recognize and we go from there. + * + * As an example, the boot device on my workstation has a full path: + * + * /pci@1e,600000/ide@d/disk@0,0:c + */ +static void __init sun4v_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *rprop; + u32 high_bits, low_bits, type; + + rprop = of_find_property(dp, "reg", NULL); + if (!rprop) + return; + + regs = rprop->value; + if (!is_root_node(dp->parent)) { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + (unsigned int) (regs->phys_addr >> 32UL), + (unsigned int) (regs->phys_addr & 0xffffffffUL)); + return; + } + + type = regs->phys_addr >> 60UL; + high_bits = (regs->phys_addr >> 32UL) & 0x0fffffffUL; + low_bits = (regs->phys_addr & 0xffffffffUL); + + if (type == 0 || type == 8) { + const char *prefix = (type == 0) ? "m" : "i"; + + if (low_bits) + sprintf(tmp_buf, "%s@%s%x,%x", + dp->name, prefix, + high_bits, low_bits); + else + sprintf(tmp_buf, "%s@%s%x", + dp->name, + prefix, + high_bits); + } else if (type == 12) { + sprintf(tmp_buf, "%s@%x", + dp->name, high_bits); + } +} + +static void __init sun4u_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + if (!is_root_node(dp->parent)) { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + (unsigned int) (regs->phys_addr >> 32UL), + (unsigned int) (regs->phys_addr & 0xffffffffUL)); + return; + } + + prop = of_find_property(dp, "upa-portid", NULL); + if (!prop) + prop = of_find_property(dp, "portid", NULL); + if (prop) { + unsigned long mask = 0xffffffffUL; + + if (tlb_type >= cheetah) + mask = 0x7fffff; + + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + *(u32 *)prop->value, + (unsigned int) (regs->phys_addr & mask)); + } +} + +/* "name@slot,offset" */ +static void __init sbus_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + regs->which_io, + regs->phys_addr); +} + +/* "name@devnum[,func]" */ +static void __init pci_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_pci_registers *regs; + struct property *prop; + unsigned int devfn; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + devfn = (regs->phys_hi >> 8) & 0xff; + if (devfn & 0x07) { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + devfn >> 3, + devfn & 0x07); + } else { + sprintf(tmp_buf, "%s@%x", + dp->name, + devfn >> 3); + } +} + +/* "name@UPA_PORTID,offset" */ +static void __init upa_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + prop = of_find_property(dp, "upa-portid", NULL); + if (!prop) + return; + + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + *(u32 *) prop->value, + (unsigned int) (regs->phys_addr & 0xffffffffUL)); +} + +/* "name@reg" */ +static void __init vdev_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + sprintf(tmp_buf, "%s@%x", dp->name, *regs); +} + +/* "name@addrhi,addrlo" */ +static void __init ebus_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + (unsigned int) (regs->phys_addr >> 32UL), + (unsigned int) (regs->phys_addr & 0xffffffffUL)); +} + +/* "name@bus,addr" */ +static void __init i2c_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + /* This actually isn't right... should look at the #address-cells + * property of the i2c bus node etc. etc. + */ + sprintf(tmp_buf, "%s@%x,%x", + dp->name, regs[0], regs[1]); +} + +/* "name@reg0[,reg1]" */ +static void __init usb_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + if (prop->length == sizeof(u32) || regs[1] == 1) { + sprintf(tmp_buf, "%s@%x", + dp->name, regs[0]); + } else { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, regs[0], regs[1]); + } +} + +/* "name@reg0reg1[,reg2reg3]" */ +static void __init ieee1394_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + if (regs[2] || regs[3]) { + sprintf(tmp_buf, "%s@%08x%08x,%04x%08x", + dp->name, regs[0], regs[1], regs[2], regs[3]); + } else { + sprintf(tmp_buf, "%s@%08x%08x", + dp->name, regs[0], regs[1]); + } +} + +static void __init __build_path_component(struct device_node *dp, char *tmp_buf) +{ + struct device_node *parent = dp->parent; + + if (parent != NULL) { + if (!strcmp(parent->type, "pci") || + !strcmp(parent->type, "pciex")) + return pci_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "sbus")) + return sbus_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "upa")) + return upa_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "ebus")) + return ebus_path_component(dp, tmp_buf); + if (!strcmp(parent->name, "usb") || + !strcmp(parent->name, "hub")) + return usb_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "i2c")) + return i2c_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "firewire")) + return ieee1394_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "virtual-devices")) + return vdev_path_component(dp, tmp_buf); + + /* "isa" is handled with platform naming */ + } + + /* Use platform naming convention. */ + if (tlb_type == hypervisor) + return sun4v_path_component(dp, tmp_buf); + else + return sun4u_path_component(dp, tmp_buf); +} + +static char * __init build_path_component(struct device_node *dp) +{ + char tmp_buf[64], *n; + + tmp_buf[0] = '\0'; + __build_path_component(dp, tmp_buf); + if (tmp_buf[0] == '\0') + strcpy(tmp_buf, dp->name); + + n = prom_early_alloc(strlen(tmp_buf) + 1); + strcpy(n, tmp_buf); + + return n; +} + +static char * __init build_full_name(struct device_node *dp) +{ + int len, ourlen, plen; + char *n; + + plen = strlen(dp->parent->full_name); + ourlen = strlen(dp->path_component_name); + len = ourlen + plen + 2; + + n = prom_early_alloc(len); + strcpy(n, dp->parent->full_name); + if (!is_root_node(dp->parent)) { + strcpy(n + plen, "/"); + plen++; + } + strcpy(n + plen, dp->path_component_name); + + return n; +} + +static unsigned int unique_id; + +static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len) +{ + static struct property *tmp = NULL; + struct property *p; + + if (tmp) { + p = tmp; + memset(p, 0, sizeof(*p) + 32); + tmp = NULL; + } else { + p = prom_early_alloc(sizeof(struct property) + 32); + p->unique_id = unique_id++; + } + + p->name = (char *) (p + 1); + if (special_name) { + strcpy(p->name, special_name); + p->length = special_len; + p->value = prom_early_alloc(special_len); + memcpy(p->value, special_val, special_len); + } else { + if (prev == NULL) { + prom_firstprop(node, p->name); + } else { + prom_nextprop(node, prev, p->name); + } + if (strlen(p->name) == 0) { + tmp = p; + return NULL; + } + p->length = prom_getproplen(node, p->name); + if (p->length <= 0) { + p->length = 0; + } else { + p->value = prom_early_alloc(p->length + 1); + prom_getproperty(node, p->name, p->value, p->length); + ((unsigned char *)p->value)[p->length] = '\0'; + } + } + return p; +} + +static struct property * __init build_prop_list(phandle node) +{ + struct property *head, *tail; + + head = tail = build_one_prop(node, NULL, + ".node", &node, sizeof(node)); + + tail->next = build_one_prop(node, NULL, NULL, NULL, 0); + tail = tail->next; + while(tail) { + tail->next = build_one_prop(node, tail->name, + NULL, NULL, 0); + tail = tail->next; + } + + return head; +} + +static char * __init get_one_property(phandle node, const char *name) +{ + char *buf = ""; + int len; + + len = prom_getproplen(node, name); + if (len > 0) { + buf = prom_early_alloc(len); + prom_getproperty(node, name, buf, len); + } + + return buf; +} + +static struct device_node * __init create_node(phandle node) +{ + struct device_node *dp; + + if (!node) + return NULL; + + dp = prom_early_alloc(sizeof(*dp)); + dp->unique_id = unique_id++; + + kref_init(&dp->kref); + + dp->name = get_one_property(node, "name"); + dp->type = get_one_property(node, "device_type"); + dp->node = node; + + /* Build interrupts later... */ + + dp->properties = build_prop_list(node); + + return dp; +} + +static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) +{ + struct device_node *dp; + + dp = create_node(node); + if (dp) { + *(*nextp) = dp; + *nextp = &dp->allnext; + + dp->parent = parent; + dp->path_component_name = build_path_component(dp); + dp->full_name = build_full_name(dp); + + dp->child = build_tree(dp, prom_getchild(node), nextp); + + dp->sibling = build_tree(parent, prom_getsibling(node), nextp); + } + + return dp; +} + +void __init prom_build_devicetree(void) +{ + struct device_node **nextp; + + allnodes = create_node(prom_root_node); + allnodes->path_component_name = ""; + allnodes->full_name = "/"; + + nextp = &allnodes->allnext; + allnodes->child = build_tree(allnodes, + prom_getchild(allnodes->node), + &nextp); + printk("PROM: Built device tree with %u bytes of memory.\n", + prom_early_allocated); +} diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 1d6ffde..ac05e0f 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -19,6 +19,7 @@ #include #include #include #include +#include #include #include "iommu_common.h" @@ -691,36 +692,6 @@ void sbus_set_sbus64(struct sbus_dev *sd upa_writeq(val, cfg_reg); } -/* SBUS SYSIO INO number to Sparc PIL level. */ -static unsigned char sysio_ino_to_pil[] = { - 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 0 */ - 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 1 */ - 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 2 */ - 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 3 */ - 5, /* Onboard SCSI */ - 5, /* Onboard Ethernet */ -/*XXX*/ 8, /* Onboard BPP */ - 0, /* Bogon */ - 13, /* Audio */ -/*XXX*/15, /* PowerFail */ - 0, /* Bogon */ - 0, /* Bogon */ - 12, /* Zilog Serial Channels (incl. Keyboard/Mouse lines) */ - 11, /* Floppy */ - 0, /* Spare Hardware (bogon for now) */ - 0, /* Keyboard (bogon for now) */ - 0, /* Mouse (bogon for now) */ - 0, /* Serial (bogon for now) */ - 0, 0, /* Bogon, Bogon */ - 10, /* Timer 0 */ - 11, /* Timer 1 */ - 0, 0, /* Bogon, Bogon */ - 15, /* Uncorrectable SBUS Error */ - 15, /* Correctable SBUS Error */ - 15, /* SBUS Error */ -/*XXX*/ 0, /* Power Management (bogon for now) */ -}; - /* INO number to IMAP register offset for SYSIO external IRQ's. * This should conform to both Sunfire/Wildfire server and Fusion * desktop designs. @@ -812,21 +783,12 @@ unsigned int sbus_build_irq(void *buscoo struct sbus_iommu *iommu = sbus->iommu; unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; unsigned long imap, iclr; - int pil, sbus_level = 0; - - pil = sysio_ino_to_pil[ino]; - if (!pil) { - printk("sbus_irq_build: Bad SYSIO INO[%x]\n", ino); - panic("Bad SYSIO IRQ translations..."); - } - - if (PIL_RESERVED(pil)) - BUG(); + int sbus_level = 0; imap = sysio_irq_offsets[ino]; if (imap == ((unsigned long)-1)) { - prom_printf("get_irq_translations: Bad SYSIO INO[%x] cpu[%d]\n", - ino, pil); + prom_printf("get_irq_translations: Bad SYSIO INO[%x]\n", + ino); prom_halt(); } imap += reg_base; @@ -860,7 +822,7 @@ unsigned int sbus_build_irq(void *buscoo iclr += ((unsigned long)sbus_level - 1UL) * 8UL; } - return build_irq(pil, sbus_level, iclr, imap); + return build_irq(sbus_level, iclr, imap); } /* Error interrupt handling. */ @@ -1137,24 +1099,25 @@ static void __init sysio_register_error_ } /* Boot time initialization. */ -void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus) +static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) { - struct linux_prom64_registers rprop; + struct linux_prom64_registers *pr; + struct device_node *dp; struct sbus_iommu *iommu; unsigned long regs, tsb_base; u64 control; - int err, i; + int i; - sbus->portid = prom_getintdefault(sbus->prom_node, - "upa-portid", -1); + dp = of_find_node_by_phandle(__node); - err = prom_getproperty(prom_node, "reg", - (char *)&rprop, sizeof(rprop)); - if (err < 0) { + sbus->portid = of_getintprop_default(dp, "upa-portid", -1); + + pr = of_get_property(dp, "reg", NULL); + if (!pr) { prom_printf("sbus_iommu_init: Cannot map SYSIO control registers.\n"); prom_halt(); } - regs = rprop.phys_addr; + regs = pr->phys_addr; iommu = kmalloc(sizeof(*iommu) + SMP_CACHE_BYTES, GFP_ATOMIC); if (iommu == NULL) { @@ -1264,3 +1227,50 @@ void __init sbus_iommu_init(int prom_nod sysio_register_error_handlers(sbus); } + +void sbus_fill_device_irq(struct sbus_dev *sdev) +{ + struct device_node *dp = of_find_node_by_phandle(sdev->prom_node); + struct linux_prom_irqs *irqs; + + irqs = of_get_property(dp, "interrupts", NULL); + if (!irqs) { + sdev->irqs[0] = 0; + sdev->num_irqs = 0; + } else { + unsigned int pri = irqs[0].pri; + + sdev->num_irqs = 1; + if (pri < 0x20) + pri += sdev->slot * 8; + + sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); + } +} + +void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) +{ +} + +void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) +{ + sbus_iommu_init(dp->node, sbus); +} + +void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) +{ +} + +int __init sbus_arch_preinit(void) +{ + return 0; +} + +void __init sbus_arch_postinit(void) +{ + extern void firetruck_init(void); + extern void clock_probe(void); + + firetruck_init(); + clock_probe(); +} diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 9cf1c88..a6a7d81 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -376,12 +376,12 @@ #endif } #endif - smp_setup_cpu_possible_map(); - /* Get boot processor trap_block[] setup. */ init_cur_cpu_trap(current_thread_info()); paging_init(); + + smp_setup_cpu_possible_map(); } static int __init set_preferred_console(void) diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index f03d52d..f62bf3a 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -39,6 +39,7 @@ #include #include #include #include +#include extern void calibrate_delay(void); @@ -76,41 +77,42 @@ void smp_bogo(struct seq_file *m) void __init smp_store_cpu_info(int id) { - int cpu_node, def; + struct device_node *dp; + int def; /* multiplier and counter set by smp_setup_percpu_timer() */ cpu_data(id).udelay_val = loops_per_jiffy; - cpu_find_by_mid(id, &cpu_node); - cpu_data(id).clock_tick = prom_getintdefault(cpu_node, - "clock-frequency", 0); + cpu_find_by_mid(id, &dp); + cpu_data(id).clock_tick = + of_getintprop_default(dp, "clock-frequency", 0); def = ((tlb_type == hypervisor) ? (8 * 1024) : (16 * 1024)); - cpu_data(id).dcache_size = prom_getintdefault(cpu_node, "dcache-size", - def); + cpu_data(id).dcache_size = + of_getintprop_default(dp, "dcache-size", def); def = 32; cpu_data(id).dcache_line_size = - prom_getintdefault(cpu_node, "dcache-line-size", def); + of_getintprop_default(dp, "dcache-line-size", def); def = 16 * 1024; - cpu_data(id).icache_size = prom_getintdefault(cpu_node, "icache-size", - def); + cpu_data(id).icache_size = + of_getintprop_default(dp, "icache-size", def); def = 32; cpu_data(id).icache_line_size = - prom_getintdefault(cpu_node, "icache-line-size", def); + of_getintprop_default(dp, "icache-line-size", def); def = ((tlb_type == hypervisor) ? (3 * 1024 * 1024) : (4 * 1024 * 1024)); - cpu_data(id).ecache_size = prom_getintdefault(cpu_node, "ecache-size", - def); + cpu_data(id).ecache_size = + of_getintprop_default(dp, "ecache-size", def); def = 64; cpu_data(id).ecache_line_size = - prom_getintdefault(cpu_node, "ecache-line-size", def); + of_getintprop_default(dp, "ecache-line-size", def); printk("CPU[%d]: Caches " "D[sz(%d):line_sz(%d)] " @@ -342,10 +344,10 @@ static int __devinit smp_boot_one_cpu(un prom_startcpu_cpuid(cpu, entry, cookie); } else { - int cpu_node; + struct device_node *dp; - cpu_find_by_mid(cpu, &cpu_node); - prom_startcpu(cpu_node, entry, cookie); + cpu_find_by_mid(cpu, &dp); + prom_startcpu(dp->node, entry, cookie); } for (timeout = 0; timeout < 5000000; timeout++) { @@ -1289,7 +1291,8 @@ int setup_profiling_timer(unsigned int m static void __init smp_tune_scheduling(void) { - int instance, node; + struct device_node *dp; + int instance; unsigned int def, smallest = ~0U; def = ((tlb_type == hypervisor) ? @@ -1297,10 +1300,10 @@ static void __init smp_tune_scheduling(v (4 * 1024 * 1024)); instance = 0; - while (!cpu_find_by_instance(instance, &node, NULL)) { + while (!cpu_find_by_instance(instance, &dp, NULL)) { unsigned int val; - val = prom_getintdefault(node, "ecache-size", def); + val = of_getintprop_default(dp, "ecache-size", def); if (val < smallest) smallest = val; diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 38e569f..4ac35dd 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -125,9 +125,6 @@ EXPORT_SYMBOL(__write_lock); EXPORT_SYMBOL(__write_unlock); EXPORT_SYMBOL(__write_trylock); -/* Hard IRQ locking */ -EXPORT_SYMBOL(synchronize_irq); - #if defined(CONFIG_MCOUNT) extern void _mcount(void); EXPORT_SYMBOL(_mcount); @@ -175,10 +172,6 @@ EXPORT_SYMBOL(set_bit); EXPORT_SYMBOL(clear_bit); EXPORT_SYMBOL(change_bit); -EXPORT_SYMBOL(ivector_table); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); - EXPORT_SYMBOL(__flushw_user); EXPORT_SYMBOL(tlb_type); diff --git a/arch/sparc64/kernel/sun4v_ivec.S b/arch/sparc64/kernel/sun4v_ivec.S index b49a68b..49703c3 100644 --- a/arch/sparc64/kernel/sun4v_ivec.S +++ b/arch/sparc64/kernel/sun4v_ivec.S @@ -5,6 +5,7 @@ #include #include +#include .text .align 32 @@ -102,23 +103,17 @@ sun4v_dev_mondo: /* Get &ivector_table[IVEC] into %g4. */ sethi %hi(ivector_table), %g4 - sllx %g3, 5, %g3 + sllx %g3, 3, %g3 or %g4, %lo(ivector_table), %g4 add %g4, %g3, %g4 - /* Load IRQ %pil into %g5. */ - ldub [%g4 + 0x04], %g5 - /* Insert ivector_table[] entry into __irq_work[] queue. */ - sllx %g5, 2, %g3 - lduw [%g1 + %g3], %g2 /* g2 = irq_work(cpu, pil) */ + lduw [%g1], %g2 /* g2 = irq_work(cpu) */ stw %g2, [%g4 + 0x00] /* bucket->irq_chain = g2 */ - stw %g4, [%g1 + %g3] /* irq_work(cpu, pil) = bucket */ + stw %g4, [%g1] /* irq_work(cpu) = bucket */ /* Signal the interrupt by setting (1 << pil) in %softint. */ - mov 1, %g2 - sllx %g2, %g5, %g2 - wr %g2, 0x0, %set_softint + wr %g0, 1 << PIL_DEVICE_IRQ, %set_softint sun4v_dev_mondo_queue_empty: retry diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index e55b5c6..348b820 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -48,6 +48,7 @@ #include #include #include #include +#include DEFINE_SPINLOCK(mostek_lock); DEFINE_SPINLOCK(rtc_lock); @@ -457,7 +458,7 @@ static inline void timer_check_rtc(void) } } -static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { unsigned long ticks, compare, pstate; @@ -755,24 +756,200 @@ retry: return -EOPNOTSUPP; } -void __init clock_probe(void) +static int __init clock_model_matches(char *model) { - struct linux_prom_registers clk_reg[2]; - char model[128]; - int node, busnd = -1, err; - unsigned long flags; - struct linux_central *cbus; + if (strcmp(model, "mk48t02") && + strcmp(model, "mk48t08") && + strcmp(model, "mk48t59") && + strcmp(model, "m5819") && + strcmp(model, "m5819p") && + strcmp(model, "m5823") && + strcmp(model, "ds1287")) + return 0; + + return 1; +} + +static void __init __clock_assign_common(void __iomem *addr, char *model) +{ + if (model[5] == '0' && model[6] == '2') { + mstk48t02_regs = addr; + } else if(model[5] == '0' && model[6] == '8') { + mstk48t08_regs = addr; + mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; + } else { + mstk48t59_regs = addr; + mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; + } +} + +static void __init clock_assign_clk_reg(struct linux_prom_registers *clk_reg, + char *model) +{ + unsigned long addr; + + addr = ((unsigned long) clk_reg[0].phys_addr | + (((unsigned long) clk_reg[0].which_io) << 32UL)); + + __clock_assign_common((void __iomem *) addr, model); +} + +static int __init clock_probe_central(void) +{ + struct linux_prom_registers clk_reg[2], *pr; + struct device_node *dp; + char *model; + + if (!central_bus) + return 0; + + /* Get Central FHC's prom node. */ + dp = central_bus->child->prom_node; + + /* Then get the first child device below it. */ + dp = dp->child; + + while (dp) { + model = of_get_property(dp, "model", NULL); + if (!model || !clock_model_matches(model)) + goto next_sibling; + + pr = of_get_property(dp, "reg", NULL); + memcpy(clk_reg, pr, sizeof(clk_reg)); + + apply_fhc_ranges(central_bus->child, clk_reg, 1); + apply_central_ranges(central_bus, clk_reg, 1); + + clock_assign_clk_reg(clk_reg, model); + return 1; + + next_sibling: + dp = dp->sibling; + } + + return 0; +} + #ifdef CONFIG_PCI - struct linux_ebus *ebus = NULL; - struct sparc_isa_bridge *isa_br = NULL; +static void __init clock_isa_ebus_assign_regs(struct resource *res, char *model) +{ + if (!strcmp(model, "ds1287") || + !strcmp(model, "m5819") || + !strcmp(model, "m5819p") || + !strcmp(model, "m5823")) { + ds1287_regs = res->start; + } else { + mstk48t59_regs = (void __iomem *) res->start; + mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; + } +} + +static int __init clock_probe_one_ebus_dev(struct linux_ebus_device *edev) +{ + struct device_node *dp = edev->prom_node; + char *model; + + model = of_get_property(dp, "model", NULL); + if (!clock_model_matches(model)) + return 0; + + clock_isa_ebus_assign_regs(&edev->resource[0], model); + + return 1; +} + +static int __init clock_probe_ebus(void) +{ + struct linux_ebus *ebus; + + for_each_ebus(ebus) { + struct linux_ebus_device *edev; + + for_each_ebusdev(edev, ebus) { + if (clock_probe_one_ebus_dev(edev)) + return 1; + } + } + + return 0; +} + +static int __init clock_probe_one_isa_dev(struct sparc_isa_device *idev) +{ + struct device_node *dp = idev->prom_node; + char *model; + + model = of_get_property(dp, "model", NULL); + if (!clock_model_matches(model)) + return 0; + + clock_isa_ebus_assign_regs(&idev->resource, model); + + return 1; +} + +static int __init clock_probe_isa(void) +{ + struct sparc_isa_bridge *isa_br; + + for_each_isa(isa_br) { + struct sparc_isa_device *isa_dev; + + for_each_isadev(isa_dev, isa_br) { + if (clock_probe_one_isa_dev(isa_dev)) + return 1; + } + } + + return 0; +} +#endif /* CONFIG_PCI */ + +#ifdef CONFIG_SBUS +static int __init clock_probe_one_sbus_dev(struct sbus_bus *sbus, struct sbus_dev *sdev) +{ + struct resource *res; + char model[64]; + void __iomem *addr; + + prom_getstring(sdev->prom_node, "model", model, sizeof(model)); + if (!clock_model_matches(model)) + return 0; + + res = &sdev->resource[0]; + addr = sbus_ioremap(res, 0, 0x800UL, "eeprom"); + + __clock_assign_common(addr, model); + + return 1; +} + +static int __init clock_probe_sbus(void) +{ + struct sbus_bus *sbus; + + for_each_sbus(sbus) { + struct sbus_dev *sdev; + + for_each_sbusdev(sdev, sbus) { + if (clock_probe_one_sbus_dev(sbus, sdev)) + return 1; + } + } + + return 0; +} #endif + +void __init clock_probe(void) +{ static int invoked; + unsigned long flags; if (invoked) return; invoked = 1; - if (this_is_starfire) { xtime.tv_sec = starfire_get_time(); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); @@ -788,183 +965,27 @@ #endif return; } - local_irq_save(flags); - - cbus = central_bus; - if (cbus != NULL) - busnd = central_bus->child->prom_node; - /* Check FHC Central then EBUSs then ISA bridges then SBUSs. * That way we handle the presence of multiple properly. * * As a special case, machines with Central must provide the * timer chip there. */ + if (!clock_probe_central() && #ifdef CONFIG_PCI - if (ebus_chain != NULL) { - ebus = ebus_chain; - if (busnd == -1) - busnd = ebus->prom_node; - } - if (isa_chain != NULL) { - isa_br = isa_chain; - if (busnd == -1) - busnd = isa_br->prom_node; - } -#endif - if (sbus_root != NULL && busnd == -1) - busnd = sbus_root->prom_node; - - if (busnd == -1) { - prom_printf("clock_probe: problem, cannot find bus to search.\n"); - prom_halt(); - } - - node = prom_getchild(busnd); - - while (1) { - if (!node) - model[0] = 0; - else - prom_getstring(node, "model", model, sizeof(model)); - if (strcmp(model, "mk48t02") && - strcmp(model, "mk48t08") && - strcmp(model, "mk48t59") && - strcmp(model, "m5819") && - strcmp(model, "m5819p") && - strcmp(model, "m5823") && - strcmp(model, "ds1287")) { - if (cbus != NULL) { - prom_printf("clock_probe: Central bus lacks timer chip.\n"); - prom_halt(); - } - - if (node != 0) - node = prom_getsibling(node); -#ifdef CONFIG_PCI - while ((node == 0) && ebus != NULL) { - ebus = ebus->next; - if (ebus != NULL) { - busnd = ebus->prom_node; - node = prom_getchild(busnd); - } - } - while ((node == 0) && isa_br != NULL) { - isa_br = isa_br->next; - if (isa_br != NULL) { - busnd = isa_br->prom_node; - node = prom_getchild(busnd); - } - } + !clock_probe_ebus() && + !clock_probe_isa() && #endif - if (node == 0) { - prom_printf("clock_probe: Cannot find timer chip\n"); - prom_halt(); - } - continue; - } - - err = prom_getproperty(node, "reg", (char *)clk_reg, - sizeof(clk_reg)); - if(err == -1) { - prom_printf("clock_probe: Cannot get Mostek reg property\n"); - prom_halt(); - } - - if (cbus != NULL) { - apply_fhc_ranges(central_bus->child, clk_reg, 1); - apply_central_ranges(central_bus, clk_reg, 1); - } -#ifdef CONFIG_PCI - else if (ebus != NULL) { - struct linux_ebus_device *edev; - - for_each_ebusdev(edev, ebus) - if (edev->prom_node == node) - break; - if (edev == NULL) { - if (isa_chain != NULL) - goto try_isa_clock; - prom_printf("%s: Mostek not probed by EBUS\n", - __FUNCTION__); - prom_halt(); - } - - if (!strcmp(model, "ds1287") || - !strcmp(model, "m5819") || - !strcmp(model, "m5819p") || - !strcmp(model, "m5823")) { - ds1287_regs = edev->resource[0].start; - } else { - mstk48t59_regs = (void __iomem *) - edev->resource[0].start; - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } - break; - } - else if (isa_br != NULL) { - struct sparc_isa_device *isadev; - -try_isa_clock: - for_each_isadev(isadev, isa_br) - if (isadev->prom_node == node) - break; - if (isadev == NULL) { - prom_printf("%s: Mostek not probed by ISA\n"); - prom_halt(); - } - if (!strcmp(model, "ds1287") || - !strcmp(model, "m5819") || - !strcmp(model, "m5819p") || - !strcmp(model, "m5823")) { - ds1287_regs = isadev->resource.start; - } else { - mstk48t59_regs = (void __iomem *) - isadev->resource.start; - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } - break; - } +#ifdef CONFIG_SBUS + !clock_probe_sbus() #endif - else { - if (sbus_root->num_sbus_ranges) { - int nranges = sbus_root->num_sbus_ranges; - int rngc; - - for (rngc = 0; rngc < nranges; rngc++) - if (clk_reg[0].which_io == - sbus_root->sbus_ranges[rngc].ot_child_space) - break; - if (rngc == nranges) { - prom_printf("clock_probe: Cannot find ranges for " - "clock regs.\n"); - prom_halt(); - } - clk_reg[0].which_io = - sbus_root->sbus_ranges[rngc].ot_parent_space; - clk_reg[0].phys_addr += - sbus_root->sbus_ranges[rngc].ot_parent_base; - } - } - - if(model[5] == '0' && model[6] == '2') { - mstk48t02_regs = (void __iomem *) - (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); - } else if(model[5] == '0' && model[6] == '8') { - mstk48t08_regs = (void __iomem *) - (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); - mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; - } else { - mstk48t59_regs = (void __iomem *) - (((u64)clk_reg[0].phys_addr) | - (((u64)clk_reg[0].which_io)<<32UL)); - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } - break; + ) { + printk(KERN_WARNING "No clock chip found.\n"); + return; } + local_irq_save(flags); + if (mstk48t02_regs != NULL) { /* Report a low battery voltage condition. */ if (has_low_battery()) @@ -983,12 +1004,14 @@ #endif /* This is gets the master TICK_INT timer going. */ static unsigned long sparc64_init_timers(void) { + struct device_node *dp; + struct property *prop; unsigned long clock; - int node; #ifdef CONFIG_SMP extern void smp_tick_init(void); #endif + dp = of_find_node_by_path("/"); if (tlb_type == spitfire) { unsigned long ver, manuf, impl; @@ -999,18 +1022,17 @@ #endif if (manuf == 0x17 && impl == 0x13) { /* Hummingbird, aka Ultra-IIe */ tick_ops = &hbtick_operations; - node = prom_root_node; - clock = prom_getint(node, "stick-frequency"); + prop = of_find_property(dp, "stick-frequency", NULL); } else { tick_ops = &tick_operations; - cpu_find_by_instance(0, &node, NULL); - clock = prom_getint(node, "clock-frequency"); + cpu_find_by_instance(0, &dp, NULL); + prop = of_find_property(dp, "clock-frequency", NULL); } } else { tick_ops = &stick_operations; - node = prom_root_node; - clock = prom_getint(node, "stick-frequency"); + prop = of_find_property(dp, "stick-frequency", NULL); } + clock = *(unsigned int *) prop->value; timer_tick_offset = clock / HZ; #ifdef CONFIG_SMP @@ -1020,19 +1042,9 @@ #endif return clock; } -static void sparc64_start_timers(irqreturn_t (*cfunc)(int, void *, struct pt_regs *)) +static void sparc64_start_timers(void) { unsigned long pstate; - int err; - - /* Register IRQ handler. */ - err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, 0, - "timer", NULL); - - if (err) { - prom_printf("Serious problem, cannot register TICK_INT\n"); - prom_halt(); - } /* Guarantee that the following sequences execute * uninterrupted. @@ -1116,7 +1128,7 @@ void __init time_init(void) /* Now that the interpolator is registered, it is * safe to start the timer ticking. */ - sparc64_start_timers(timer_interrupt); + sparc64_start_timers(); timer_ticks_per_nsec_quotient = (((NSEC_PER_SEC << SPARC64_NSEC_PER_CYC_SHIFT) + diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 563db52..1ff34b0 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -42,6 +42,7 @@ #include #ifdef CONFIG_KMOD #include #endif +#include ATOMIC_NOTIFIER_HEAD(sparc64die_chain); @@ -807,7 +808,8 @@ extern unsigned int cheetah_deferred_tra void __init cheetah_ecache_flush_init(void) { unsigned long largest_size, smallest_linesize, order, ver; - int node, i, instance; + struct device_node *dp; + int i, instance, sz; /* Scan all cpu device tree nodes, note two values: * 1) largest E-cache size @@ -817,14 +819,14 @@ void __init cheetah_ecache_flush_init(vo smallest_linesize = ~0UL; instance = 0; - while (!cpu_find_by_instance(instance, &node, NULL)) { + while (!cpu_find_by_instance(instance, &dp, NULL)) { unsigned long val; - val = prom_getintdefault(node, "ecache-size", - (2 * 1024 * 1024)); + val = of_getintprop_default(dp, "ecache-size", + (2 * 1024 * 1024)); if (val > largest_size) largest_size = val; - val = prom_getintdefault(node, "ecache-line-size", 64); + val = of_getintprop_default(dp, "ecache-line-size", 64); if (val < smallest_linesize) smallest_linesize = val; instance++; @@ -849,16 +851,16 @@ void __init cheetah_ecache_flush_init(vo } /* Now allocate error trap reporting scoreboard. */ - node = NR_CPUS * (2 * sizeof(struct cheetah_err_info)); + sz = NR_CPUS * (2 * sizeof(struct cheetah_err_info)); for (order = 0; order < MAX_ORDER; order++) { - if ((PAGE_SIZE << order) >= node) + if ((PAGE_SIZE << order) >= sz) break; } cheetah_error_log = (struct cheetah_err_info *) __get_free_pages(GFP_KERNEL, order); if (!cheetah_error_log) { prom_printf("cheetah_ecache_flush_init: Failed to allocate " - "error logging scoreboard (%d bytes).\n", node); + "error logging scoreboard (%d bytes).\n", sz); prom_halt(); } memset(cheetah_error_log, 0, PAGE_SIZE << order); @@ -2544,7 +2546,9 @@ void __init trap_init(void) (TRAP_PER_CPU_TSB_HUGE != offsetof(struct trap_per_cpu, tsb_huge)) || (TRAP_PER_CPU_TSB_HUGE_TEMP != - offsetof(struct trap_per_cpu, tsb_huge_temp))) + offsetof(struct trap_per_cpu, tsb_huge_temp)) || + (TRAP_PER_CPU_IRQ_WORKLIST != + offsetof(struct trap_per_cpu, irq_worklist))) trap_per_cpu_offsets_are_bolixed_dave(); if ((TSB_CONFIG_TSB != diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S index 5d90151..ee45ca2 100644 --- a/arch/sparc64/kernel/ttable.S +++ b/arch/sparc64/kernel/ttable.S @@ -58,13 +58,11 @@ tl0_irq2: BTRAP(0x42) tl0_irq3: BTRAP(0x43) tl0_irq4: BTRAP(0x44) #endif -tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6) -tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8) -tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10) -tl0_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12) -tl0_irq13: TRAP_IRQ(handler_irq, 13) +tl0_irq5: TRAP_IRQ(handler_irq, 5) +tl0_irq6: BTRAP(0x46) BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) +tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) #ifndef CONFIG_SMP -tl0_irq14: TRAP_IRQ(handler_irq, 14) +tl0_irq14: TRAP_IRQ(timer_irq, 14) #else tl0_irq14: TICK_SMP_IRQ #endif diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index 001e851..bb2d685 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -279,12 +279,21 @@ static void kernel_mna_trap_fault(void) asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) { + static unsigned long count, last_time; enum direction dir = decode_direction(insn); int size = decode_access_size(insn); current_thread_info()->kern_una_regs = regs; current_thread_info()->kern_una_insn = insn; + if (jiffies - last_time > 5 * HZ) + count = 0; + if (count < 5) { + last_time = jiffies; + count++; + printk("Kernel unaligned access at TPC[%lx]\n", regs->tpc); + } + if (!ok_for_kernel(insn) || dir == both) { printk("Unsupported unaligned load/store trap for kernel " "at <%016lx>.\n", regs->tpc); diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 6e002aa..1605967 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -31,6 +31,40 @@ #include #include #include +#ifdef CONFIG_KPROBES +ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); + +/* Hook to register for page fault notifications */ +int register_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); +} + +int unregister_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); +} + +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + struct die_args args = { + .regs = regs, + .str = str, + .err = err, + .trapnr = trap, + .signr = sig + }; + return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); +} +#else +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + return NOTIFY_DONE; +} +#endif + /* * To debug kernel to catch accesses to certain virtual/physical addresses. * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints. @@ -263,7 +297,7 @@ asmlinkage void __kprobes do_sparc64_fau fault_code = get_thread_fault_code(); - if (notify_die(DIE_PAGE_FAULT, "page_fault", regs, + if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, fault_code, 0, SIGSEGV) == NOTIFY_STOP) return; diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 1539a83..5c2bcf3 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -42,6 +42,7 @@ #include #include #include #include +#include extern void device_scan(void); @@ -101,8 +102,6 @@ static void __init read_obp_memory(const prom_halt(); } - *num_ents = ents; - /* Sanitize what we got from the firmware, by page aligning * everything. */ @@ -124,6 +123,25 @@ static void __init read_obp_memory(const regs[i].phys_addr = base; regs[i].reg_size = size; } + + for (i = 0; i < ents; i++) { + if (regs[i].reg_size == 0UL) { + int j; + + for (j = i; j < ents - 1; j++) { + regs[j].phys_addr = + regs[j+1].phys_addr; + regs[j].reg_size = + regs[j+1].reg_size; + } + + ents--; + i--; + } + } + + *num_ents = ents; + sort(regs, ents, sizeof(struct linux_prom64_registers), cmp_p64, NULL); } @@ -1339,6 +1357,8 @@ void __init paging_init(void) kernel_physical_mapping_init(); + prom_build_devicetree(); + { unsigned long zones_size[MAX_NR_ZONES]; unsigned long zholes_size[MAX_NR_ZONES]; @@ -1376,7 +1396,7 @@ static void __init taint_real_pages(void while (old_start < old_end) { int n; - for (n = 0; pavail_rescan_ents; n++) { + for (n = 0; n < pavail_rescan_ents; n++) { unsigned long new_start, new_end; new_start = pavail_rescan[n].phys_addr; @@ -1398,6 +1418,32 @@ static void __init taint_real_pages(void } } +int __init page_in_phys_avail(unsigned long paddr) +{ + int i; + + paddr &= PAGE_MASK; + + for (i = 0; i < pavail_rescan_ents; i++) { + unsigned long start, end; + + start = pavail_rescan[i].phys_addr; + end = start + pavail_rescan[i].reg_size; + + if (paddr >= start && paddr < end) + return 1; + } + if (paddr >= kern_base && paddr < (kern_base + kern_size)) + return 1; +#ifdef CONFIG_BLK_DEV_INITRD + if (paddr >= __pa(initrd_start) && + paddr < __pa(PAGE_ALIGN(initrd_end))) + return 1; +#endif + + return 0; +} + void __init mem_init(void) { unsigned long codepages, datapages, initpages; @@ -1522,6 +1568,7 @@ pgprot_t PAGE_EXEC __read_mostly; unsigned long pg_iobits __read_mostly; unsigned long _PAGE_IE __read_mostly; +EXPORT_SYMBOL(_PAGE_IE); unsigned long _PAGE_E __read_mostly; EXPORT_SYMBOL(_PAGE_E); diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index 4885ca6..0f0eb6a 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -356,7 +356,7 @@ static int report_statvfs(struct vfsmoun int error; struct sol_statvfs __user *ss = A(buf); - error = vfs_statfs(mnt->mnt_sb, &s); + error = vfs_statfs(mnt->mnt_root, &s); if (!error) { const char *p = mnt->mnt_sb->s_type->name; int i = 0; @@ -392,7 +392,7 @@ static int report_statvfs64(struct vfsmo int error; struct sol_statvfs64 __user *ss = A(buf); - error = vfs_statfs(mnt->mnt_sb, &s); + error = vfs_statfs(mnt->mnt_root, &s); if (!error) { const char *p = mnt->mnt_sb->s_type->name; int i = 0; diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index 5284996..719c909 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c @@ -23,6 +23,7 @@ #include #include #include #include +#include #include "conv.h" @@ -194,14 +195,17 @@ static char *machine(void) } } -static char *platform(char *buffer) +static char *platform(char *buffer, int sz) { + struct device_node *dp = of_find_node_by_path("/"); int len; *buffer = 0; - len = prom_getproperty(prom_root_node, "name", buffer, 256); - if(len > 0) - buffer[len] = 0; + len = strlen(dp->name); + if (len > sz) + len = sz; + memcpy(buffer, dp->name, len); + buffer[len] = 0; if (*buffer) { char *p; @@ -213,16 +217,22 @@ static char *platform(char *buffer) return "sun4u"; } -static char *serial(char *buffer) +static char *serial(char *buffer, int sz) { - int node = prom_getchild(prom_root_node); + struct device_node *dp = of_find_node_by_path("/options"); int len; - node = prom_searchsiblings(node, "options"); *buffer = 0; - len = prom_getproperty(node, "system-board-serial#", buffer, 256); - if(len > 0) - buffer[len] = 0; + if (dp) { + char *val = of_get_property(dp, "system-board-serial#", &len); + + if (val && len > 0) { + if (len > sz) + len = sz; + memcpy(buffer, val, len); + buffer[len] = 0; + } + } if (!*buffer) return "4512348717234"; else @@ -305,8 +315,8 @@ asmlinkage int solaris_sysinfo(int cmd, case SI_MACHINE: r = machine(); break; case SI_ARCHITECTURE: r = "sparc"; break; case SI_HW_PROVIDER: r = "Sun_Microsystems"; break; - case SI_HW_SERIAL: r = serial(buffer); break; - case SI_PLATFORM: r = platform(buffer); break; + case SI_HW_SERIAL: r = serial(buffer, sizeof(buffer)); break; + case SI_PLATFORM: r = platform(buffer, sizeof(buffer)); break; case SI_SRPC_DOMAIN: r = ""; break; case SI_VERSION: r = "Generic"; break; default: return -EINVAL; diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug index 5681a8b..bab51d6 100644 --- a/arch/um/Kconfig.debug +++ b/arch/um/Kconfig.debug @@ -49,7 +49,6 @@ config GCOV config SYSCALL_DEBUG bool "Enable system call debugging" - default N depends on DEBUG_INFO help This adds some system debugging to UML, including keeping a ring buffer diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 6d7173f..7914931 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -300,8 +300,6 @@ void mconsole_reboot(struct mc_request * machine_restart(NULL); } -extern void ctrl_alt_del(void); - void mconsole_cad(struct mc_request *req) { mconsole_reply(req, "", 0, 0); diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 0897852..290cec6 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1222,7 +1222,7 @@ int open_ubd_file(char *file, struct ope } } - /* Succesful return case! */ + /* Successful return case! */ if(backing_file_out == NULL) return(fd); diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h index e06f83e..5e86aa0 100644 --- a/arch/um/include/sysdep-x86_64/syscalls.h +++ b/arch/um/include/sysdep-x86_64/syscalls.h @@ -12,8 +12,6 @@ #include typedef long syscall_handler_t(void); -extern syscall_handler_t *ia32_sys_call_table[]; - extern syscall_handler_t *sys_call_table[]; #define EXECUTE_SYSCALL(syscall, regs) \ diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index fc0f0b0..166cb09 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -69,7 +69,7 @@ static void insert_phys_mapping(struct p panic("Physical remapping for %p already present", desc->virt); - rb_link_node(&desc->rb, (*n)->rb_parent, n); + rb_link_node(&desc->rb, rb_parent(*n), n); rb_insert_color(&desc->rb, &phys_mappings); } diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 86f51d0..87cdbc5 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -87,7 +87,7 @@ #endif void time_init_kern(void) { - unsigned long long nsecs; + long long nsecs; nsecs = os_nsecs(); set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, diff --git a/arch/um/sys-ppc/misc.S b/arch/um/sys-ppc/misc.S index 11b7bd7..f0c971d 100644 --- a/arch/um/sys-ppc/misc.S +++ b/arch/um/sys-ppc/misc.S @@ -23,14 +23,10 @@ #if defined(CONFIG_4xx) || defined(CONFI #define CACHE_LINE_SIZE 16 #define LG_CACHE_LINE_SIZE 4 #define MAX_COPY_PREFETCH 1 -#elif !defined(CONFIG_PPC64BRIDGE) +#else #define CACHE_LINE_SIZE 32 #define LG_CACHE_LINE_SIZE 5 #define MAX_COPY_PREFETCH 4 -#else -#define CACHE_LINE_SIZE 128 -#define LG_CACHE_LINE_SIZE 7 -#define MAX_COPY_PREFETCH 1 #endif /* CONFIG_4xx || CONFIG_8xx */ .text diff --git a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c index 633e4e1..17c2d43 100644 --- a/arch/v850/kernel/signal.c +++ b/arch/v850/kernel/signal.c @@ -274,7 +274,7 @@ get_sigframe(struct k_sigaction *ka, str /* Default to using normal stack */ unsigned long sp = regs->gpr[GPR_SP]; - if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; return (void *)((sp - frame_size) & -8UL); diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 408d44a..ccc4a7f 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -299,6 +299,7 @@ config X86_64_ACPI_NUMA bool "ACPI NUMA detection" depends on NUMA select ACPI + select PCI select ACPI_NUMA default y help @@ -385,27 +386,47 @@ config HPET_EMULATE_RTC bool "Provide RTC interrupt" depends on HPET_TIMER && RTC=y -config GART_IOMMU - bool "K8 GART IOMMU support" +# Mark as embedded because too many people got it wrong. +# The code disables itself when not needed. +config IOMMU + bool "IOMMU support" if EMBEDDED default y select SWIOTLB + select AGP depends on PCI help - Support for hardware IOMMU in AMD's Opteron/Athlon64 Processors - and for the bounce buffering software IOMMU. - Needed to run systems with more than 3GB of memory properly with - 32-bit PCI devices that do not support DAC (Double Address Cycle). - The IOMMU can be turned off at runtime with the iommu=off parameter. - Normally the kernel will take the right choice by itself. - This option includes a driver for the AMD Opteron/Athlon64 IOMMU - northbridge and a software emulation used on other systems without - hardware IOMMU. If unsure, say Y. - -# need this always enabled with GART_IOMMU for the VIA workaround + Support for full DMA access of devices with 32bit memory access only + on systems with more than 3GB. This is usually needed for USB, + sound, many IDE/SATA chipsets and some other devices. + Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART + based IOMMU and a software bounce buffer based IOMMU used on Intel + systems and as fallback. + The code is only active when needed (enough memory and limited + device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified + too. + +config CALGARY_IOMMU + bool "IBM Calgary IOMMU support" + default y + select SWIOTLB + depends on PCI && EXPERIMENTAL + help + Support for hardware IOMMUs in IBM's xSeries x366 and x460 + systems. Needed to run systems with more than 3GB of memory + properly with 32-bit PCI devices that do not support DAC + (Double Address Cycle). Calgary also supports bus level + isolation, where all DMAs pass through the IOMMU. This + prevents them from going anywhere except their intended + destination. This catches hard-to-find kernel bugs and + mis-behaving drivers and devices that do not use the DMA-API + properly to set up their DMA buffers. The IOMMU can be + turned off at boot time with the iommu=off parameter. + Normally the kernel will make the right choice by itself. + If unsure, say Y. + +# need this always selected by IOMMU for the VIA workaround config SWIOTLB bool - default y - depends on GART_IOMMU config X86_MCE bool "Machine check support" if EMBEDDED @@ -501,6 +522,10 @@ config REORDER optimal TLB usage. If you have pretty much any version of binutils, this can increase your kernel build time by roughly one minute. +config K8_NB + def_bool y + depends on AGP_AMD64 || IOMMU || (PCI && NUMA) + endmenu # diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug index ea31b4c..1d92ab5 100644 --- a/arch/x86_64/Kconfig.debug +++ b/arch/x86_64/Kconfig.debug @@ -13,7 +13,7 @@ config DEBUG_RODATA If in doubt, say "N". config IOMMU_DEBUG - depends on GART_IOMMU && DEBUG_KERNEL + depends on IOMMU && DEBUG_KERNEL bool "Enable IOMMU debugging" help Force the IOMMU to on even when you have less than 4GB of @@ -35,6 +35,22 @@ config IOMMU_LEAK Add a simple leak tracer to the IOMMU code. This is useful when you are debugging a buggy device driver that leaks IOMMU mappings. +config DEBUG_STACKOVERFLOW + bool "Check for stack overflows" + depends on DEBUG_KERNEL + help + This option will cause messages to be printed if free stack space + drops below a certain limit. + +config DEBUG_STACK_USAGE + bool "Stack utilization instrumentation" + depends on DEBUG_KERNEL + help + Enables the display of the minimum amount of free stack which each + task has ever had available in the sysrq-T and sysrq-P debug output. + + This option will slow down process creation somewhat. + #config X86_REMOTE_DEBUG # bool "kgdb debugging stub" diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile index e573e2a..431bb4b 100644 --- a/arch/x86_64/Makefile +++ b/arch/x86_64/Makefile @@ -27,6 +27,7 @@ LDFLAGS_vmlinux := CHECKFLAGS += -D__x86_64__ -m64 cflags-y := +cflags-kernel-y := cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic) @@ -35,7 +36,7 @@ cflags-y += -m64 cflags-y += -mno-red-zone cflags-y += -mcmodel=kernel cflags-y += -pipe -cflags-$(CONFIG_REORDER) += -ffunction-sections +cflags-kernel-$(CONFIG_REORDER) += -ffunction-sections # this makes reading assembly source easier, but produces worse code # actually it makes the kernel smaller too. cflags-y += -fno-reorder-blocks @@ -55,6 +56,7 @@ # prevent gcc from generating any FP cod cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) CFLAGS += $(cflags-y) +CFLAGS_KERNEL += $(cflags-kernel-y) AFLAGS += -m64 head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile index 43ee6c5..deb063e 100644 --- a/arch/x86_64/boot/Makefile +++ b/arch/x86_64/boot/Makefile @@ -107,8 +107,13 @@ fdimage288: $(BOOTIMAGE) $(obj)/mtools.c isoimage: $(BOOTIMAGE) -rm -rf $(obj)/isoimage mkdir $(obj)/isoimage - cp `echo /usr/lib*/syslinux/isolinux.bin | awk '{ print $1; }'` \ - $(obj)/isoimage + for i in lib lib64 share end ; do \ + if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \ + cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \ + break ; \ + fi ; \ + if [ $$i = end ] ; then exit 1 ; fi ; \ + done cp $(BOOTIMAGE) $(obj)/isoimage/linux echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg if [ -f '$(FDINITRD)' ] ; then \ diff --git a/arch/x86_64/boot/compressed/misc.c b/arch/x86_64/boot/compressed/misc.c index cf4b88c..3755b2e 100644 --- a/arch/x86_64/boot/compressed/misc.c +++ b/arch/x86_64/boot/compressed/misc.c @@ -77,11 +77,11 @@ static void gzip_release(void **); */ static unsigned char *real_mode; /* Pointer to real-mode data */ -#define EXT_MEM_K (*(unsigned short *)(real_mode + 0x2)) +#define RM_EXT_MEM_K (*(unsigned short *)(real_mode + 0x2)) #ifndef STANDARD_MEMORY_BIOS_CALL -#define ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0)) +#define RM_ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0)) #endif -#define SCREEN_INFO (*(struct screen_info *)(real_mode+0)) +#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0)) extern unsigned char input_data[]; extern int input_len; @@ -92,9 +92,9 @@ static unsigned long output_ptr = 0; static void *malloc(int size); static void free(void *where); - -void* memset(void* s, int c, unsigned n); -void* memcpy(void* dest, const void* src, unsigned n); + +static void *memset(void *s, int c, unsigned n); +static void *memcpy(void *dest, const void *src, unsigned n); static void putstr(const char *); @@ -162,8 +162,8 @@ static void putstr(const char *s) int x,y,pos; char c; - x = SCREEN_INFO.orig_x; - y = SCREEN_INFO.orig_y; + x = RM_SCREEN_INFO.orig_x; + y = RM_SCREEN_INFO.orig_y; while ( ( c = *s++ ) != '\0' ) { if ( c == '\n' ) { @@ -184,8 +184,8 @@ static void putstr(const char *s) } } - SCREEN_INFO.orig_x = x; - SCREEN_INFO.orig_y = y; + RM_SCREEN_INFO.orig_x = x; + RM_SCREEN_INFO.orig_y = y; pos = (x + cols * y) * 2; /* Update cursor position */ outb_p(14, vidport); @@ -194,7 +194,7 @@ static void putstr(const char *s) outb_p(0xff & (pos >> 1), vidport+1); } -void* memset(void* s, int c, unsigned n) +static void* memset(void* s, int c, unsigned n) { int i; char *ss = (char*)s; @@ -203,7 +203,7 @@ void* memset(void* s, int c, unsigned n) return s; } -void* memcpy(void* dest, const void* src, unsigned n) +static void* memcpy(void* dest, const void* src, unsigned n) { int i; char *d = (char *)dest, *s = (char *)src; @@ -278,15 +278,15 @@ static void error(char *x) putstr(x); putstr("\n\n -- System halted"); - while(1); + while(1); /* Halt */ } -void setup_normal_output_buffer(void) +static void setup_normal_output_buffer(void) { #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < 1024) error("Less than 2MB of memory"); + if (RM_EXT_MEM_K < 1024) error("Less than 2MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory"); + if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory"); #endif output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */ free_mem_end_ptr = (long)real_mode; @@ -297,13 +297,13 @@ struct moveparams { uch *high_buffer_start; int hcount; }; -void setup_output_buffer_if_we_run_high(struct moveparams *mv) +static void setup_output_buffer_if_we_run_high(struct moveparams *mv) { high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE); #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory"); + if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory"); + if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory"); #endif mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START; low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX @@ -319,7 +319,7 @@ #endif mv->high_buffer_start = high_buffer_start; } -void close_output_buffer_if_we_run_high(struct moveparams *mv) +static void close_output_buffer_if_we_run_high(struct moveparams *mv) { if (bytes_out > low_buffer_size) { mv->lcount = low_buffer_size; @@ -335,7 +335,7 @@ int decompress_kernel(struct moveparams { real_mode = rmode; - if (SCREEN_INFO.orig_video_mode == 7) { + if (RM_SCREEN_INFO.orig_video_mode == 7) { vidmem = (char *) 0xb0000; vidport = 0x3b4; } else { @@ -343,8 +343,8 @@ int decompress_kernel(struct moveparams vidport = 0x3d4; } - lines = SCREEN_INFO.orig_video_lines; - cols = SCREEN_INFO.orig_video_cols; + lines = RM_SCREEN_INFO.orig_video_lines; + cols = RM_SCREEN_INFO.orig_video_cols; if (free_mem_ptr < 0x100000) setup_normal_output_buffer(); else setup_output_buffer_if_we_run_high(mv); diff --git a/arch/x86_64/boot/tools/build.c b/arch/x86_64/boot/tools/build.c index c44f5e2..eae8669 100644 --- a/arch/x86_64/boot/tools/build.c +++ b/arch/x86_64/boot/tools/build.c @@ -149,10 +149,8 @@ int main(int argc, char ** argv) sz = sb.st_size; fprintf (stderr, "System is %d kB\n", sz/1024); sys_size = (sz + 15) / 16; - /* 0x40000*16 = 4.0 MB, reasonable estimate for the current maximum */ - if (sys_size > (is_big_kernel ? 0x40000 : DEF_SYSSIZE)) - die("System is too big. Try using %smodules.", - is_big_kernel ? "" : "bzImage or "); + if (!is_big_kernel && sys_size > DEF_SYSSIZE) + die("System is too big. Try using bzImage or modules."); while (sz > 0) { int l, n; diff --git a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S index 32327bb..2aa565c 100644 --- a/arch/x86_64/boot/video.S +++ b/arch/x86_64/boot/video.S @@ -1929,6 +1929,7 @@ skip10: movb %ah, %al ret store_edid: +#ifdef CONFIG_FIRMWARE_EDID pushw %es # just save all registers pushw %ax pushw %bx @@ -1946,6 +1947,22 @@ store_edid: rep stosl + pushw %es # save ES + xorw %di, %di # Report Capability + pushw %di + popw %es # ES:DI must be 0:0 + movw $0x4f15, %ax + xorw %bx, %bx + xorw %cx, %cx + int $0x10 + popw %es # restore ES + + cmpb $0x00, %ah # call successful + jne no_edid + + cmpb $0x4f, %al # function supported + jne no_edid + movw $0x4f15, %ax # do VBE/DDC movw $0x01, %bx movw $0x00, %cx @@ -1953,12 +1970,14 @@ store_edid: movw $0x140, %di int $0x10 +no_edid: popw %di # restore all registers popw %dx popw %cx popw %bx popw %ax popw %es +#endif ret # VIDEO_SELECT-only variables diff --git a/arch/x86_64/crypto/aes-x86_64-asm.S b/arch/x86_64/crypto/aes-x86_64-asm.S index 483cbb2..26b40de 100644 --- a/arch/x86_64/crypto/aes-x86_64-asm.S +++ b/arch/x86_64/crypto/aes-x86_64-asm.S @@ -15,6 +15,10 @@ .text +#include + +#define BASE crypto_tfm_ctx_offset + #define R1 %rax #define R1E %eax #define R1X %ax @@ -46,19 +50,19 @@ #define R9 %r9 #define R10 %r10 #define R11 %r11 -#define prologue(FUNC,BASE,B128,B192,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11) \ +#define prologue(FUNC,KEY,B128,B192,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11) \ .global FUNC; \ .type FUNC,@function; \ .align 8; \ FUNC: movq r1,r2; \ movq r3,r4; \ - leaq BASE+52(r8),r9; \ + leaq BASE+KEY+52(r8),r9; \ movq r10,r11; \ movl (r7),r5 ## E; \ movl 4(r7),r1 ## E; \ movl 8(r7),r6 ## E; \ movl 12(r7),r7 ## E; \ - movl (r8),r10 ## E; \ + movl BASE(r8),r10 ## E; \ xorl -48(r9),r5 ## E; \ xorl -44(r9),r1 ## E; \ xorl -40(r9),r6 ## E; \ @@ -128,8 +132,8 @@ #define move_regs(r1,r2,r3,r4) \ movl r3 ## E,r1 ## E; \ movl r4 ## E,r2 ## E; -#define entry(FUNC,BASE,B128,B192) \ - prologue(FUNC,BASE,B128,B192,R2,R8,R7,R9,R1,R3,R4,R6,R10,R5,R11) +#define entry(FUNC,KEY,B128,B192) \ + prologue(FUNC,KEY,B128,B192,R2,R8,R7,R9,R1,R3,R4,R6,R10,R5,R11) #define return epilogue(R8,R2,R9,R7,R5,R6,R3,R4,R11) @@ -147,9 +151,9 @@ #define decrypt_round(TAB,OFFSET) \ #define decrypt_final(TAB,OFFSET) \ round(TAB,OFFSET,R2,R1,R4,R3,R6,R5,R7,R10,R5,R6,R3,R4) -/* void aes_encrypt(void *ctx, u8 *out, const u8 *in) */ +/* void aes_enc_blk(stuct crypto_tfm *tfm, u8 *out, const u8 *in) */ - entry(aes_encrypt,0,enc128,enc192) + entry(aes_enc_blk,0,enc128,enc192) encrypt_round(aes_ft_tab,-96) encrypt_round(aes_ft_tab,-80) enc192: encrypt_round(aes_ft_tab,-64) @@ -166,9 +170,9 @@ enc128: encrypt_round(aes_ft_tab,-32) encrypt_final(aes_fl_tab,112) return -/* void aes_decrypt(void *ctx, u8 *out, const u8 *in) */ +/* void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in) */ - entry(aes_decrypt,240,dec128,dec192) + entry(aes_dec_blk,240,dec128,dec192) decrypt_round(aes_it_tab,-96) decrypt_round(aes_it_tab,-80) dec192: decrypt_round(aes_it_tab,-64) diff --git a/arch/x86_64/crypto/aes.c b/arch/x86_64/crypto/aes.c index 6f77e77..68866fa 100644 --- a/arch/x86_64/crypto/aes.c +++ b/arch/x86_64/crypto/aes.c @@ -227,10 +227,10 @@ #define loop8(i) \ t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \ } -static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, - u32 *flags) +static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len, u32 *flags) { - struct aes_ctx *ctx = ctx_arg; + struct aes_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *key = (const __le32 *)in_key; u32 i, j, t, u, v, w; @@ -283,8 +283,18 @@ static int aes_set_key(void *ctx_arg, co return 0; } -extern void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in); -extern void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in); +asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in); +asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in); + +static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ + aes_enc_blk(tfm, dst, src); +} + +static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ + aes_dec_blk(tfm, dst, src); +} static struct crypto_alg aes_alg = { .cra_name = "aes", diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 69db0c0..e69d403 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-rc1-git11 -# Sun Apr 16 07:22:36 2006 +# Linux kernel version: 2.6.17-git6 +# Sat Jun 24 00:52:28 2006 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -42,7 +42,6 @@ # CONFIG_CPUSETS is not set # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_UID16=y -CONFIG_VM86=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y @@ -57,7 +56,6 @@ CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y CONFIG_SLAB=y -CONFIG_DOUBLEFAULT=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -144,7 +142,8 @@ CONFIG_NR_CPUS=32 CONFIG_HOTPLUG_CPU=y CONFIG_HPET_TIMER=y CONFIG_HPET_EMULATE_RTC=y -CONFIG_GART_IOMMU=y +CONFIG_IOMMU=y +# CONFIG_CALGARY_IOMMU is not set CONFIG_SWIOTLB=y CONFIG_X86_MCE=y CONFIG_X86_MCE_INTEL=y @@ -158,6 +157,7 @@ CONFIG_HZ_250=y # CONFIG_HZ_1000 is not set CONFIG_HZ=250 # CONFIG_REORDER is not set +CONFIG_K8_NB=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_ISA_DMA_API=y @@ -293,6 +293,8 @@ # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -305,7 +307,10 @@ # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set # CONFIG_IPV6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # @@ -344,6 +349,7 @@ # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NET_TCPPROBE is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -360,6 +366,7 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker @@ -526,6 +533,7 @@ CONFIG_SCSI_ATA_PIIX=y # CONFIG_SCSI_SATA_MV is not set CONFIG_SCSI_SATA_NV=y # CONFIG_SCSI_PDC_ADMA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_SATA_QSTOR is not set # CONFIG_SCSI_SATA_PROMISE is not set # CONFIG_SCSI_SATA_SX4 is not set @@ -591,10 +599,7 @@ # CONFIG_IEEE1394_EXPORT_FULL_API is not # # Device Drivers # - -# -# Texas Instruments PCILynx requires I2C -# +# CONFIG_IEEE1394_PCILYNX is not set CONFIG_IEEE1394_OHCI1394=y # @@ -645,7 +650,16 @@ # CONFIG_TYPHOON is not set # # Tulip family network device support # -# CONFIG_NET_TULIP is not set +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +CONFIG_TULIP=y +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +# CONFIG_TULIP_NAPI is not set +# CONFIG_DE4X5 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +# CONFIG_ULI526X is not set # CONFIG_HP100 is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set @@ -697,6 +711,7 @@ # CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set CONFIG_S2IO=m # CONFIG_S2IO_NAPI is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices @@ -887,7 +902,56 @@ # CONFIG_TELCLOCK is not set # # I2C support # -# CONFIG_I2C is not set +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_ISA=m +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set # # SPI support @@ -898,14 +962,51 @@ # CONFIG_SPI_MASTER is not set # # Dallas's 1-wire bus # -# CONFIG_W1 is not set # # Hardware Monitoring support # CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +CONFIG_SENSORS_SMSC47B397=m +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set # CONFIG_SENSORS_HDAPS is not set # CONFIG_HWMON_DEBUG_CHIP is not set @@ -918,6 +1019,7 @@ # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -953,28 +1055,17 @@ # # Open Sound System # CONFIG_SOUND_PRIME=y -CONFIG_OBSOLETE_OSS_DRIVER=y # CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set # CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set CONFIG_SOUND_ICH=y -# CONFIG_SOUND_SONICVIBES is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set # CONFIG_SOUND_VIA82CXXX is not set # CONFIG_SOUND_OSS is not set -# CONFIG_SOUND_ALI5455 is not set -# CONFIG_SOUND_FORTE is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_AD1980 is not set +# CONFIG_SOUND_TVMIXER is not set # # USB support @@ -1000,6 +1091,7 @@ # CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1089,10 +1181,12 @@ # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set @@ -1141,6 +1235,19 @@ # # CONFIG_RTC_CLASS is not set # +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# # Firmware Drivers # # CONFIG_EDD is not set @@ -1175,6 +1282,7 @@ # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y @@ -1331,7 +1439,8 @@ # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_FRAME_POINTER is not set -# CONFIG_UNWIND_INFO is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y # CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_RODATA is not set diff --git a/arch/x86_64/ia32/fpu32.c b/arch/x86_64/ia32/fpu32.c index 1c23095..2c8209a 100644 --- a/arch/x86_64/ia32/fpu32.c +++ b/arch/x86_64/ia32/fpu32.c @@ -2,7 +2,6 @@ * Copyright 2002 Andi Kleen, SuSE Labs. * FXSAVE<->i387 conversion support. Based on code by Gareth Hughes. * This is used for ptrace, signals and coredumps in 32bit emulation. - * $Id: fpu32.c,v 1.1 2002/03/21 14:16:32 ak Exp $ */ #include diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c index e0a9243..25e5ca2 100644 --- a/arch/x86_64/ia32/ia32_signal.c +++ b/arch/x86_64/ia32/ia32_signal.c @@ -6,8 +6,6 @@ * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes * 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen - * - * $Id: ia32_signal.c,v 1.22 2002/07/29 10:34:03 ak Exp $ */ #include diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 5a92fed..c536fa9 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -155,6 +155,7 @@ sysenter_tracesys: .previous jmp sysenter_do_call CFI_ENDPROC +ENDPROC(ia32_sysenter_target) /* * 32bit SYSCALL instruction entry. @@ -178,7 +179,7 @@ sysenter_tracesys: */ ENTRY(ia32_cstar_target) CFI_STARTPROC32 simple - CFI_DEF_CFA rsp,0 + CFI_DEF_CFA rsp,PDA_STACKOFFSET CFI_REGISTER rip,rcx /*CFI_REGISTER rflags,r11*/ swapgs @@ -249,6 +250,7 @@ cstar_tracesys: .quad 1b,ia32_badarg .previous jmp cstar_do_call +END(ia32_cstar_target) ia32_badarg: movq $-EFAULT,%rax @@ -314,16 +316,13 @@ ia32_tracesys: LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST jmp ia32_do_syscall +END(ia32_syscall) ia32_badsys: movq $0,ORIG_RAX-ARGOFFSET(%rsp) movq $-ENOSYS,RAX-ARGOFFSET(%rsp) jmp int_ret_from_sys_call -ni_syscall: - movq %rax,%rdi - jmp sys32_ni_syscall - quiet_ni_syscall: movq $-ENOSYS,%rax ret @@ -370,10 +369,10 @@ ENTRY(ia32_ptregs_common) RESTORE_REST jmp ia32_sysret /* misbalances the return cache */ CFI_ENDPROC +END(ia32_ptregs_common) .section .rodata,"a" .align 8 - .globl ia32_sys_call_table ia32_sys_call_table: .quad sys_restart_syscall .quad sys_exit @@ -696,4 +695,5 @@ #endif .quad sys_sync_file_range .quad sys_tee .quad compat_sys_vmsplice + .quad compat_sys_move_pages ia32_syscall_end: diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index 23a4515..a590b7a 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c @@ -7,8 +7,6 @@ * * This allows to access 64bit processes too; but there is no way to see the extended * register contents. - * - * $Id: ptrace32.c,v 1.16 2003/03/14 16:06:35 ak Exp $ */ #include @@ -27,6 +25,7 @@ #include #include #include #include +#include /* * Determines which flags the user has access to [1 = access, 0 = no access]. @@ -199,6 +198,24 @@ static int getreg32(struct task_struct * #undef R32 +static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data) +{ + int ret; + compat_siginfo_t *si32 = (compat_siginfo_t *)compat_ptr(data); + siginfo_t *si = compat_alloc_user_space(sizeof(siginfo_t)); + if (request == PTRACE_SETSIGINFO) { + ret = copy_siginfo_from_user32(si, si32); + if (ret) + return ret; + } + ret = sys_ptrace(request, pid, addr, (unsigned long)si); + if (ret) + return ret; + if (request == PTRACE_GETSIGINFO) + ret = copy_siginfo_to_user32(si32, si); + return ret; +} + asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) { struct task_struct *child; @@ -208,9 +225,19 @@ asmlinkage long sys32_ptrace(long reques __u32 val; switch (request) { - default: + case PTRACE_TRACEME: + case PTRACE_ATTACH: + case PTRACE_KILL: + case PTRACE_CONT: + case PTRACE_SINGLESTEP: + case PTRACE_DETACH: + case PTRACE_SYSCALL: + case PTRACE_SETOPTIONS: return sys_ptrace(request, pid, addr, data); + default: + return -EINVAL; + case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: case PTRACE_POKEDATA: @@ -225,10 +252,11 @@ asmlinkage long sys32_ptrace(long reques case PTRACE_GETFPXREGS: case PTRACE_GETEVENTMSG: break; - } - if (request == PTRACE_TRACEME) - return ptrace_traceme(); + case PTRACE_SETSIGINFO: + case PTRACE_GETSIGINFO: + return ptrace32_siginfo(request, pid, addr, data); + } child = ptrace_get_task_struct(pid); if (IS_ERR(child)) @@ -349,8 +377,7 @@ asmlinkage long sys32_ptrace(long reques break; default: - ret = -EINVAL; - break; + BUG(); } out: diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c index f182b20..dc88154 100644 --- a/arch/x86_64/ia32/sys_ia32.c +++ b/arch/x86_64/ia32/sys_ia32.c @@ -508,19 +508,6 @@ sys32_waitpid(compat_pid_t pid, unsigned return compat_sys_wait4(pid, stat_addr, options, NULL); } -int sys32_ni_syscall(int call) -{ - struct task_struct *me = current; - static char lastcomm[sizeof(me->comm)]; - - if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) { - printk(KERN_INFO "IA32 syscall %d from %s not implemented\n", - call, me->comm); - strncpy(lastcomm, me->comm, sizeof(lastcomm)); - } - return -ENOSYS; -} - /* 32-bit timeval and related flotsam. */ asmlinkage long @@ -916,7 +903,7 @@ long sys32_vm86_warning(void) struct task_struct *me = current; static char lastcomm[sizeof(me->comm)]; if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) { - printk(KERN_INFO "%s: vm86 mode not supported on 64 bit kernel\n", + compat_printk(KERN_INFO "%s: vm86 mode not supported on 64 bit kernel\n", me->comm); strncpy(lastcomm, me->comm, sizeof(lastcomm)); } @@ -929,13 +916,3 @@ long sys32_lookup_dcookie(u32 addr_low, return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len); } -static int __init ia32_init (void) -{ - printk("IA32 emulation $Id: sys_ia32.c,v 1.32 2002/03/24 13:02:28 ak Exp $\n"); - return 0; -} - -__initcall(ia32_init); - -extern unsigned long ia32_sys_call_table[]; -EXPORT_SYMBOL(ia32_sys_call_table); diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index 059c883..aeb9c56 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -8,7 +8,7 @@ obj-y := process.o signal.o entry.o trap ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \ x8664_ksyms.o i387.o syscall.o vsyscall.o \ setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \ - pci-dma.o pci-nommu.o + pci-dma.o pci-nommu.o alternative.o obj-$(CONFIG_X86_MCE) += mce.o obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o @@ -28,11 +28,13 @@ obj-$(CONFIG_PM) += suspend.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o +obj-$(CONFIG_IOMMU) += pci-gart.o aperture.o +obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary.o tce.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o obj-$(CONFIG_X86_VSMP) += vsmp.o +obj-$(CONFIG_K8_NB) += k8.o obj-$(CONFIG_MODULES) += module.o @@ -49,3 +51,5 @@ intel_cacheinfo-y += ../../i386/kernel/ quirks-y += ../../i386/kernel/quirks.o i8237-y += ../../i386/kernel/i8237.o msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o +alternative-y += ../../i386/kernel/alternative.o + diff --git a/arch/x86_64/kernel/acpi/Makefile b/arch/x86_64/kernel/acpi/Makefile index 4fe9707..080b996 100644 --- a/arch/x86_64/kernel/acpi/Makefile +++ b/arch/x86_64/kernel/acpi/Makefile @@ -4,5 +4,6 @@ obj-$(CONFIG_ACPI_SLEEP) += sleep.o wake ifneq ($(CONFIG_ACPI_PROCESSOR),) obj-y += processor.o +processor-y := ../../../i386/kernel/acpi/processor.o ../../../i386/kernel/acpi/cstate.o endif diff --git a/arch/x86_64/kernel/acpi/processor.c b/arch/x86_64/kernel/acpi/processor.c deleted file mode 100644 index 3bdc2ba..0000000 --- a/arch/x86_64/kernel/acpi/processor.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * arch/x86_64/kernel/acpi/processor.c - * - * Copyright (C) 2005 Intel Corporation - * Venkatesh Pallipadi - * - Added _PDC for platforms with Intel CPUs - */ - -#include -#include -#include -#include - -#include -#include - -static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) -{ - struct acpi_object_list *obj_list; - union acpi_object *obj; - u32 *buf; - - /* allocate and initialize pdc. It will be used later. */ - obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); - if (!obj_list) { - printk(KERN_ERR "Memory allocation error\n"); - return; - } - - obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); - if (!obj) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj_list); - return; - } - - buf = kmalloc(12, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj); - kfree(obj_list); - return; - } - - buf[0] = ACPI_PDC_REVISION_ID; - buf[1] = 1; - buf[2] = ACPI_PDC_EST_CAPABILITY_SMP; - - obj->type = ACPI_TYPE_BUFFER; - obj->buffer.length = 12; - obj->buffer.pointer = (u8 *) buf; - obj_list->count = 1; - obj_list->pointer = obj; - pr->pdc = obj_list; - - return; -} - -/* Initialize _PDC data based on the CPU vendor */ -void arch_acpi_processor_init_pdc(struct acpi_processor *pr) -{ - unsigned int cpu = pr->id; - struct cpuinfo_x86 *c = cpu_data + cpu; - - pr->pdc = NULL; - if (c->x86_vendor == X86_VENDOR_INTEL && cpu_has(c, X86_FEATURE_EST)) - init_intel_pdc(pr, c); - - return; -} - -EXPORT_SYMBOL(arch_acpi_processor_init_pdc); diff --git a/arch/x86_64/kernel/acpi/sleep.c b/arch/x86_64/kernel/acpi/sleep.c index 867a0eb..091bc79 100644 --- a/arch/x86_64/kernel/acpi/sleep.c +++ b/arch/x86_64/kernel/acpi/sleep.c @@ -35,6 +35,8 @@ #include #include #include #include +#include + #include #include #include @@ -66,7 +68,8 @@ static void init_low_mapping(void) pgd_t *slot0 = pgd_offset(current->mm, 0UL); low_ptr = *slot0; set_pgd(slot0, *pgd_offset(current->mm, PAGE_OFFSET)); - flush_tlb_all(); + WARN_ON(num_online_cpus() != 1); + local_flush_tlb(); } /** @@ -92,7 +95,7 @@ int acpi_save_state_mem(void) void acpi_restore_state_mem(void) { set_pgd(pgd_offset(current->mm, 0UL), low_ptr); - flush_tlb_all(); + local_flush_tlb(); } /** diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c index 70b9d21..a195ef0 100644 --- a/arch/x86_64/kernel/aperture.c +++ b/arch/x86_64/kernel/aperture.c @@ -8,7 +8,6 @@ * because only the bootmem allocator can allocate 32+MB. * * Copyright 2002 Andi Kleen, SuSE Labs. - * $Id: aperture.c,v 1.7 2003/08/01 03:36:18 ak Exp $ */ #include #include @@ -24,6 +23,7 @@ #include #include #include #include +#include int iommu_aperture; int iommu_aperture_disabled __initdata = 0; @@ -37,8 +37,6 @@ int fix_aperture __initdata = 1; /* This code runs before the PCI subsystem is initialized, so just access the northbridge directly. */ -#define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16)) - static u32 __init allocate_aperture(void) { pg_data_t *nd0 = NODE_DATA(0); @@ -68,20 +66,20 @@ static u32 __init allocate_aperture(void return (u32)__pa(p); } -static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size) +static int __init aperture_valid(u64 aper_base, u32 aper_size) { if (!aper_base) return 0; if (aper_size < 64*1024*1024) { - printk("Aperture from %s too small (%d MB)\n", name, aper_size>>20); + printk("Aperture too small (%d MB)\n", aper_size>>20); return 0; } if (aper_base + aper_size >= 0xffffffff) { - printk("Aperture from %s beyond 4GB. Ignoring.\n",name); + printk("Aperture beyond 4GB. Ignoring.\n"); return 0; } if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) { - printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name); + printk("Aperture pointing to e820 RAM. Ignoring.\n"); return 0; } return 1; @@ -140,7 +138,7 @@ static __u32 __init read_agp(int num, in printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", aper, 32 << *order, apsizereg); - if (!aperture_valid("AGP bridge", aper, (32*1024*1024) << *order)) + if (!aperture_valid(aper, (32*1024*1024) << *order)) return 0; return (u32)aper; } @@ -208,10 +206,10 @@ void __init iommu_hole_init(void) fix = 0; for (num = 24; num < 32; num++) { - char name[30]; - if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) - continue; + if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) + continue; + iommu_detected = 1; iommu_aperture = 1; aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; @@ -222,9 +220,7 @@ void __init iommu_hole_init(void) printk("CPU %d: aperture @ %Lx size %u MB\n", num-24, aper_base, aper_size>>20); - sprintf(name, "northbridge cpu %d", num-24); - - if (!aperture_valid(name, aper_base, aper_size)) { + if (!aperture_valid(aper_base, aper_size)) { fix = 1; break; } @@ -273,7 +269,7 @@ void __init iommu_hole_init(void) /* Fix up the north bridges */ for (num = 24; num < 32; num++) { - if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) + if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) continue; /* Don't enable translation yet. That is done later. diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 100a30c..b2ead91 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c @@ -51,7 +51,7 @@ int disable_apic_timer __initdata; static cpumask_t timer_interrupt_broadcast_ipi_mask; /* Using APIC to generate smp_local_timer_interrupt? */ -int using_apic_timer = 0; +int using_apic_timer __read_mostly = 0; static void apic_pm_activate(void); @@ -100,7 +100,7 @@ void clear_local_APIC(void) maxlvt = get_maxlvt(); /* - * Masking an LVT entry on a P6 can trigger a local APIC error + * Masking an LVT entry can trigger a local APIC error * if the vector is zero. Mask LVTERR first to prevent this. */ if (maxlvt >= 3) { @@ -851,7 +851,18 @@ void disable_APIC_timer(void) unsigned long v; v = apic_read(APIC_LVTT); - apic_write(APIC_LVTT, v | APIC_LVT_MASKED); + /* + * When an illegal vector value (0-15) is written to an LVT + * entry and delivery mode is Fixed, the APIC may signal an + * illegal vector error, with out regard to whether the mask + * bit is set or whether an interrupt is actually seen on input. + * + * Boot sequence might call this function when the LVTT has + * '0' vector value. So make sure vector field is set to + * valid value. + */ + v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); + apic_write(APIC_LVTT, v); } } @@ -909,15 +920,13 @@ int setup_profiling_timer(unsigned int m return -EINVAL; } -#ifdef CONFIG_X86_MCE_AMD -void setup_threshold_lvt(unsigned long lvt_off) +void setup_APIC_extened_lvt(unsigned char lvt_off, unsigned char vector, + unsigned char msg_type, unsigned char mask) { - unsigned int v = 0; - unsigned long reg = (lvt_off << 4) + 0x500; - v |= THRESHOLD_APIC_VECTOR; + unsigned long reg = (lvt_off << 4) + K8_APIC_EXT_LVT_BASE; + unsigned int v = (mask << 16) | (msg_type << 8) | vector; apic_write(reg, v); } -#endif /* CONFIG_X86_MCE_AMD */ #undef APIC_DIVISOR @@ -983,7 +992,7 @@ void smp_apic_timer_interrupt(struct pt_ } /* - * oem_force_hpet_timer -- force HPET mode for some boxes. + * apic_is_clustered_box() -- Check if we can expect good TSC * * Thus far, the major user of this is IBM's Summit2 series: * @@ -991,7 +1000,7 @@ void smp_apic_timer_interrupt(struct pt_ * multi-chassis. Use available data to take a good guess. * If in doubt, go HPET. */ -__cpuinit int oem_force_hpet_timer(void) +__cpuinit int apic_is_clustered_box(void) { int i, clusters, zeros; unsigned id; @@ -1022,8 +1031,7 @@ __cpuinit int oem_force_hpet_timer(void) } /* - * If clusters > 2, then should be multi-chassis. Return 1 for HPET. - * Else return 0 to use TSC. + * If clusters > 2, then should be multi-chassis. * May have to revisit this when multi-core + hyperthreaded CPUs come * out, but AFAIK this will work even for them. */ diff --git a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c index 38834bb..96687e2 100644 --- a/arch/x86_64/kernel/asm-offsets.c +++ b/arch/x86_64/kernel/asm-offsets.c @@ -4,6 +4,7 @@ * and format the required data. */ +#include #include #include #include @@ -68,5 +69,7 @@ #endif DEFINE(pbe_next, offsetof(struct pbe, next)); BLANK(); DEFINE(TSS_ist, offsetof(struct tss_struct, ist)); + BLANK(); + DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); return 0; } diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c index 4e6c3b7..d8d5750 100644 --- a/arch/x86_64/kernel/crash.c +++ b/arch/x86_64/kernel/crash.c @@ -111,14 +111,14 @@ static int crash_nmi_callback(struct pt_ atomic_dec(&waiting_for_crash_ipi); /* Assume hlt works */ for(;;) - asm("hlt"); + halt(); return 1; } static void smp_send_nmi_allbutself(void) { - send_IPI_allbutself(APIC_DM_NMI); + send_IPI_allbutself(NMI_VECTOR); } /* @@ -161,7 +161,7 @@ void machine_crash_shutdown(struct pt_re { /* * This function is only called after the system - * has paniced or is otherwise in a critical state. + * has panicked or is otherwise in a critical state. * The minimum amount of code to allow a kexec'd kernel * to run successfully needs to happen here. * diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index 1ef6028..9e94d83 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c @@ -1,7 +1,6 @@ /* * Handle the memory map. * The functions here do the job until bootmem takes over. - * $Id: e820.c,v 1.4 2002/09/19 19:25:32 ak Exp $ * * Getting sanitize_e820_map() in sync with i386 version by applying change: * - Provisions for empty E820 memory regions (reported by certain BIOSes). @@ -621,6 +620,7 @@ void __init parse_memmapopt(char *p, cha } unsigned long pci_mem_start = 0xaeedbabe; +EXPORT_SYMBOL(pci_mem_start); /* * Search for the biggest gap in the low 32 bits of the e820 diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 586b34c..7290e72 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -154,6 +154,7 @@ rff_trace: GET_THREAD_INFO(%rcx) jmp rff_action CFI_ENDPROC +END(ret_from_fork) /* * System call entry. Upto 6 arguments in registers are supported. @@ -188,7 +189,7 @@ rff_trace: ENTRY(system_call) CFI_STARTPROC simple - CFI_DEF_CFA rsp,0 + CFI_DEF_CFA rsp,PDA_STACKOFFSET CFI_REGISTER rip,rcx /*CFI_REGISTER rflags,r11*/ swapgs @@ -285,6 +286,7 @@ tracesys: /* Use IRET because user could have changed frame */ jmp int_ret_from_sys_call CFI_ENDPROC +END(system_call) /* * Syscall return path ending with IRET. @@ -364,6 +366,7 @@ int_restore_rest: cli jmp int_with_check CFI_ENDPROC +END(int_ret_from_sys_call) /* * Certain special system calls that need to save a complete full stack frame. @@ -375,6 +378,7 @@ int_restore_rest: leaq \func(%rip),%rax leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */ jmp ptregscall_common +END(\label) .endm CFI_STARTPROC @@ -404,6 +408,7 @@ ENTRY(ptregscall_common) CFI_REL_OFFSET rip, 0 ret CFI_ENDPROC +END(ptregscall_common) ENTRY(stub_execve) CFI_STARTPROC @@ -418,6 +423,7 @@ ENTRY(stub_execve) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC +END(stub_execve) /* * sigreturn is special because it needs to restore all registers on return. @@ -435,6 +441,7 @@ ENTRY(stub_rt_sigreturn) RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC +END(stub_rt_sigreturn) /* * initial frame state for interrupts and exceptions @@ -466,29 +473,18 @@ #define XCPT_FRAME _frame ORIG_RAX /* 0(%rsp): interrupt number */ .macro interrupt func cld -#ifdef CONFIG_DEBUG_INFO - SAVE_ALL - movq %rsp,%rdi - /* - * Setup a stack frame pointer. This allows gdb to trace - * back to the original stack. - */ - movq %rsp,%rbp - CFI_DEF_CFA_REGISTER rbp -#else SAVE_ARGS leaq -ARGOFFSET(%rsp),%rdi # arg1 for handler -#endif + pushq %rbp + CFI_ADJUST_CFA_OFFSET 8 + CFI_REL_OFFSET rbp, 0 + movq %rsp,%rbp + CFI_DEF_CFA_REGISTER rbp testl $3,CS(%rdi) je 1f swapgs 1: incl %gs:pda_irqcount # RED-PEN should check preempt count - movq %gs:pda_irqstackptr,%rax - cmoveq %rax,%rsp /*todo This needs CFI annotation! */ - pushq %rdi # save old stack -#ifndef CONFIG_DEBUG_INFO - CFI_ADJUST_CFA_OFFSET 8 -#endif + cmoveq %gs:pda_irqstackptr,%rsp call \func .endm @@ -497,17 +493,11 @@ ENTRY(common_interrupt) interrupt do_IRQ /* 0(%rsp): oldrsp-ARGOFFSET */ ret_from_intr: - popq %rdi -#ifndef CONFIG_DEBUG_INFO - CFI_ADJUST_CFA_OFFSET -8 -#endif cli decl %gs:pda_irqcount -#ifdef CONFIG_DEBUG_INFO - movq RBP(%rdi),%rbp + leaveq CFI_DEF_CFA_REGISTER rsp -#endif - leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */ + CFI_ADJUST_CFA_OFFSET -8 exit_intr: GET_THREAD_INFO(%rcx) testl $3,CS-ARGOFFSET(%rsp) @@ -589,7 +579,9 @@ retint_kernel: call preempt_schedule_irq jmp exit_intr #endif + CFI_ENDPROC +END(common_interrupt) /* * APIC interrupts. @@ -605,17 +597,21 @@ #endif ENTRY(thermal_interrupt) apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt +END(thermal_interrupt) ENTRY(threshold_interrupt) apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt +END(threshold_interrupt) #ifdef CONFIG_SMP ENTRY(reschedule_interrupt) apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt +END(reschedule_interrupt) .macro INVALIDATE_ENTRY num ENTRY(invalidate_interrupt\num) apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt +END(invalidate_interrupt\num) .endm INVALIDATE_ENTRY 0 @@ -629,17 +625,21 @@ ENTRY(invalidate_interrupt\num) ENTRY(call_function_interrupt) apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt +END(call_function_interrupt) #endif #ifdef CONFIG_X86_LOCAL_APIC ENTRY(apic_timer_interrupt) apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt +END(apic_timer_interrupt) ENTRY(error_interrupt) apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt +END(error_interrupt) ENTRY(spurious_interrupt) apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt +END(spurious_interrupt) #endif /* @@ -777,6 +777,7 @@ error_kernelspace: cmpq $gs_change,RIP(%rsp) je error_swapgs jmp error_sti +END(error_entry) /* Reload gs selector with exception handling */ /* edi: new selector */ @@ -794,6 +795,7 @@ gs_change: CFI_ADJUST_CFA_OFFSET -8 ret CFI_ENDPROC +ENDPROC(load_gs_index) .section __ex_table,"a" .align 8 @@ -847,7 +849,7 @@ ENTRY(kernel_thread) UNFAKE_STACK_FRAME ret CFI_ENDPROC - +ENDPROC(kernel_thread) child_rip: /* @@ -860,6 +862,7 @@ child_rip: # exit xorl %edi, %edi call do_exit +ENDPROC(child_rip) /* * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. @@ -889,19 +892,24 @@ ENTRY(execve) UNFAKE_STACK_FRAME ret CFI_ENDPROC +ENDPROC(execve) KPROBE_ENTRY(page_fault) errorentry do_page_fault +END(page_fault) .previous .text ENTRY(coprocessor_error) zeroentry do_coprocessor_error +END(coprocessor_error) ENTRY(simd_coprocessor_error) zeroentry do_simd_coprocessor_error +END(simd_coprocessor_error) ENTRY(device_not_available) zeroentry math_state_restore +END(device_not_available) /* runs on exception stack */ KPROBE_ENTRY(debug) @@ -911,6 +919,7 @@ KPROBE_ENTRY(debug) paranoidentry do_debug, DEBUG_STACK jmp paranoid_exit CFI_ENDPROC +END(debug) .previous .text /* runs on exception stack */ @@ -961,6 +970,7 @@ paranoid_schedule: cli jmp paranoid_userspace CFI_ENDPROC +END(nmi) .previous .text KPROBE_ENTRY(int3) @@ -970,22 +980,28 @@ KPROBE_ENTRY(int3) paranoidentry do_int3, DEBUG_STACK jmp paranoid_exit CFI_ENDPROC +END(int3) .previous .text ENTRY(overflow) zeroentry do_overflow +END(overflow) ENTRY(bounds) zeroentry do_bounds +END(bounds) ENTRY(invalid_op) zeroentry do_invalid_op +END(invalid_op) ENTRY(coprocessor_segment_overrun) zeroentry do_coprocessor_segment_overrun +END(coprocessor_segment_overrun) ENTRY(reserved) zeroentry do_reserved +END(reserved) /* runs on exception stack */ ENTRY(double_fault) @@ -993,12 +1009,15 @@ ENTRY(double_fault) paranoidentry do_double_fault jmp paranoid_exit CFI_ENDPROC +END(double_fault) ENTRY(invalid_TSS) errorentry do_invalid_TSS +END(invalid_TSS) ENTRY(segment_not_present) errorentry do_segment_not_present +END(segment_not_present) /* runs on exception stack */ ENTRY(stack_segment) @@ -1006,19 +1025,24 @@ ENTRY(stack_segment) paranoidentry do_stack_segment jmp paranoid_exit CFI_ENDPROC +END(stack_segment) KPROBE_ENTRY(general_protection) errorentry do_general_protection +END(general_protection) .previous .text ENTRY(alignment_check) errorentry do_alignment_check +END(alignment_check) ENTRY(divide_error) zeroentry do_divide_error +END(divide_error) ENTRY(spurious_interrupt_bug) zeroentry do_spurious_interrupt_bug +END(spurious_interrupt_bug) #ifdef CONFIG_X86_MCE /* runs on exception stack */ @@ -1029,6 +1053,7 @@ ENTRY(machine_check) paranoidentry do_machine_check jmp paranoid_exit CFI_ENDPROC +END(machine_check) #endif ENTRY(call_softirq) @@ -1046,3 +1071,37 @@ ENTRY(call_softirq) decl %gs:pda_irqcount ret CFI_ENDPROC +ENDPROC(call_softirq) + +#ifdef CONFIG_STACK_UNWIND +ENTRY(arch_unwind_init_running) + CFI_STARTPROC + movq %r15, R15(%rdi) + movq %r14, R14(%rdi) + xchgq %rsi, %rdx + movq %r13, R13(%rdi) + movq %r12, R12(%rdi) + xorl %eax, %eax + movq %rbp, RBP(%rdi) + movq %rbx, RBX(%rdi) + movq (%rsp), %rcx + movq %rax, R11(%rdi) + movq %rax, R10(%rdi) + movq %rax, R9(%rdi) + movq %rax, R8(%rdi) + movq %rax, RAX(%rdi) + movq %rax, RCX(%rdi) + movq %rax, RDX(%rdi) + movq %rax, RSI(%rdi) + movq %rax, RDI(%rdi) + movq %rax, ORIG_RAX(%rdi) + movq %rcx, RIP(%rdi) + leaq 8(%rsp), %rcx + movq $__KERNEL_CS, CS(%rdi) + movq %rax, EFLAGS(%rdi) + movq %rcx, RSP(%rdi) + movq $__KERNEL_DS, SS(%rdi) + jmpq *%rdx + CFI_ENDPROC +ENDPROC(arch_unwind_init_running) +#endif diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c index 1a2ab82..21c7066 100644 --- a/arch/x86_64/kernel/genapic_flat.c +++ b/arch/x86_64/kernel/genapic_flat.c @@ -78,22 +78,29 @@ static void flat_send_IPI_mask(cpumask_t static void flat_send_IPI_allbutself(int vector) { -#ifndef CONFIG_HOTPLUG_CPU - if (((num_online_cpus()) - 1) >= 1) - __send_IPI_shortcut(APIC_DEST_ALLBUT, vector,APIC_DEST_LOGICAL); +#ifdef CONFIG_HOTPLUG_CPU + int hotplug = 1; #else - cpumask_t allbutme = cpu_online_map; + int hotplug = 0; +#endif + if (hotplug || vector == NMI_VECTOR) { + cpumask_t allbutme = cpu_online_map; - cpu_clear(smp_processor_id(), allbutme); + cpu_clear(smp_processor_id(), allbutme); - if (!cpus_empty(allbutme)) - flat_send_IPI_mask(allbutme, vector); -#endif + if (!cpus_empty(allbutme)) + flat_send_IPI_mask(allbutme, vector); + } else if (num_online_cpus() > 1) { + __send_IPI_shortcut(APIC_DEST_ALLBUT, vector,APIC_DEST_LOGICAL); + } } static void flat_send_IPI_all(int vector) { - __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL); + if (vector == NMI_VECTOR) + flat_send_IPI_mask(cpu_online_map, vector); + else + __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL); } static int flat_apic_id_registered(void) @@ -108,10 +115,7 @@ static unsigned int flat_cpu_mask_to_api static unsigned int phys_pkg_id(int index_msb) { - u32 ebx; - - ebx = cpuid_ebx(1); - return ((ebx >> 24) & 0xFF) >> index_msb; + return hard_smp_processor_id() >> index_msb; } struct genapic apic_flat = { diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c index cea20a6..e6a71c9 100644 --- a/arch/x86_64/kernel/head64.c +++ b/arch/x86_64/kernel/head64.c @@ -2,8 +2,6 @@ * linux/arch/x86_64/kernel/head64.c -- prepare to run common code * * Copyright (C) 2000 Andrea Arcangeli SuSE - * - * $Id: head64.c,v 1.22 2001/07/06 14:28:20 ak Exp $ */ #include diff --git a/arch/x86_64/kernel/i387.c b/arch/x86_64/kernel/i387.c index a5d7e16..44ddb1e 100644 --- a/arch/x86_64/kernel/i387.c +++ b/arch/x86_64/kernel/i387.c @@ -24,7 +24,7 @@ #include #include #include -unsigned int mxcsr_feature_mask = 0xffffffff; +unsigned int mxcsr_feature_mask __read_mostly = 0xffffffff; void mxcsr_feature_mask_init(void) { diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c index 5ecd34a..86b2c1e 100644 --- a/arch/x86_64/kernel/i8259.c +++ b/arch/x86_64/kernel/i8259.c @@ -44,11 +44,11 @@ #define BUILD_16_IRQS(x) \ BI(x,8) BI(x,9) BI(x,a) BI(x,b) \ BI(x,c) BI(x,d) BI(x,e) BI(x,f) -#define BUILD_14_IRQS(x) \ +#define BUILD_15_IRQS(x) \ BI(x,0) BI(x,1) BI(x,2) BI(x,3) \ BI(x,4) BI(x,5) BI(x,6) BI(x,7) \ BI(x,8) BI(x,9) BI(x,a) BI(x,b) \ - BI(x,c) BI(x,d) + BI(x,c) BI(x,d) BI(x,e) /* * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts: @@ -73,13 +73,13 @@ BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BU BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd) #ifdef CONFIG_PCI_MSI - BUILD_14_IRQS(0xe) + BUILD_15_IRQS(0xe) #endif #endif #undef BUILD_16_IRQS -#undef BUILD_14_IRQS +#undef BUILD_15_IRQS #undef BI @@ -92,11 +92,11 @@ #define IRQLIST_16(x) \ IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \ IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f) -#define IRQLIST_14(x) \ +#define IRQLIST_15(x) \ IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \ IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \ IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \ - IRQ(x,c), IRQ(x,d) + IRQ(x,c), IRQ(x,d), IRQ(x,e) void (*interrupt[NR_IRQS])(void) = { IRQLIST_16(0x0), @@ -108,7 +108,7 @@ #ifdef CONFIG_X86_IO_APIC IRQLIST_16(0xc), IRQLIST_16(0xd) #ifdef CONFIG_PCI_MSI - , IRQLIST_14(0xe) + , IRQLIST_15(0xe) #endif #endif @@ -278,7 +278,7 @@ static void mask_and_ack_8259A(unsigned * Lightweight spurious IRQ detection. We do not want * to overdo spurious IRQ handling - it's usually a sign * of hardware problems, so we only do the checks we can - * do without slowing down good hardware unnecesserily. + * do without slowing down good hardware unnecessarily. * * Note that IRQ7 and IRQ15 (the two spurious IRQs * usually resulting from the 8259A-1|2 PICs) occur diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 9cc7031..c768d8a 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -41,6 +41,7 @@ #include #include #include #include +#include #define __apicdebuginit __init @@ -56,6 +57,7 @@ int timer_over_8254 __initdata = 0; static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; static DEFINE_SPINLOCK(ioapic_lock); +static DEFINE_SPINLOCK(vector_lock); /* * # of IRQ routing registers @@ -317,7 +319,7 @@ void __init check_ioapic(void) vendor &= 0xffff; switch (vendor) { case PCI_VENDOR_ID_VIA: -#ifdef CONFIG_GART_IOMMU +#ifdef CONFIG_IOMMU if ((end_pfn > MAX_DMA32_PFN || force_iommu) && !iommu_aperture_allowed) { @@ -834,10 +836,17 @@ u8 irq_vector[NR_IRQ_VECTORS] __read_mos int assign_irq_vector(int irq) { static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; + unsigned long flags; + int vector; BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS); - if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) + + spin_lock_irqsave(&vector_lock, flags); + + if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) { + spin_unlock_irqrestore(&vector_lock, flags); return IO_APIC_VECTOR(irq); + } next: current_vector += 8; if (current_vector == IA32_SYSCALL_VECTOR) @@ -849,11 +858,14 @@ next: current_vector = FIRST_DEVICE_VECTOR + offset; } - vector_irq[current_vector] = irq; + vector = current_vector; + vector_irq[vector] = irq; if (irq != AUTO_ASSIGN) - IO_APIC_VECTOR(irq) = current_vector; + IO_APIC_VECTOR(irq) = vector; + + spin_unlock_irqrestore(&vector_lock, flags); - return current_vector; + return vector; } extern void (*interrupt[NR_IRQS])(void); @@ -866,21 +878,14 @@ #define IOAPIC_LEVEL 1 static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger) { - if (use_pci_vector() && !platform_legacy_irq(irq)) { - if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || - trigger == IOAPIC_LEVEL) - irq_desc[vector].handler = &ioapic_level_type; - else - irq_desc[vector].handler = &ioapic_edge_type; - set_intr_gate(vector, interrupt[vector]); - } else { - if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || - trigger == IOAPIC_LEVEL) - irq_desc[irq].handler = &ioapic_level_type; - else - irq_desc[irq].handler = &ioapic_edge_type; - set_intr_gate(vector, interrupt[irq]); - } + unsigned idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq; + + if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || + trigger == IOAPIC_LEVEL) + irq_desc[idx].handler = &ioapic_level_type; + else + irq_desc[idx].handler = &ioapic_edge_type; + set_intr_gate(vector, interrupt[idx]); } static void __init setup_IO_APIC_irqs(void) diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c index d8bd0b3..59518d4 100644 --- a/arch/x86_64/kernel/irq.c +++ b/arch/x86_64/kernel/irq.c @@ -26,6 +26,30 @@ atomic_t irq_mis_count; #endif #endif +#ifdef CONFIG_DEBUG_STACKOVERFLOW +/* + * Probabilistic stack overflow check: + * + * Only check the stack in process context, because everything else + * runs on the big interrupt stacks. Checking reliably is too expensive, + * so we just check from interrupts. + */ +static inline void stack_overflow_check(struct pt_regs *regs) +{ + u64 curbase = (u64) current->thread_info; + static unsigned long warned = -60*HZ; + + if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE && + regs->rsp < curbase + sizeof(struct thread_info) + 128 && + time_after(jiffies, warned + 60*HZ)) { + printk("do_IRQ: %s near stack overflow (cur:%Lx,rsp:%lx)\n", + current->comm, curbase, regs->rsp); + show_stack(NULL,NULL); + warned = jiffies; + } +} +#endif + /* * Generic, controller-independent functions: */ @@ -39,7 +63,7 @@ int show_interrupts(struct seq_file *p, if (i == 0) { seq_printf(p, " "); for_each_online_cpu(j) - seq_printf(p, "CPU%d ",j); + seq_printf(p, "CPU%-8d",j); seq_putc(p, '\n'); } @@ -96,7 +120,9 @@ asmlinkage unsigned int do_IRQ(struct pt exit_idle(); irq_enter(); - +#ifdef CONFIG_DEBUG_STACKOVERFLOW + stack_overflow_check(regs); +#endif __do_IRQ(irq, regs); irq_exit(); diff --git a/arch/x86_64/kernel/k8.c b/arch/x86_64/kernel/k8.c new file mode 100644 index 0000000..6416682 --- /dev/null +++ b/arch/x86_64/kernel/k8.c @@ -0,0 +1,118 @@ +/* + * Shared support code for AMD K8 northbridges and derivates. + * Copyright 2006 Andi Kleen, SUSE Labs. Subject to GPLv2. + */ +#include +#include +#include +#include +#include +#include +#include + +int num_k8_northbridges; +EXPORT_SYMBOL(num_k8_northbridges); + +static u32 *flush_words; + +struct pci_device_id k8_nb_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, + {} +}; +EXPORT_SYMBOL(k8_nb_ids); + +struct pci_dev **k8_northbridges; +EXPORT_SYMBOL(k8_northbridges); + +static struct pci_dev *next_k8_northbridge(struct pci_dev *dev) +{ + do { + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); + if (!dev) + break; + } while (!pci_match_id(&k8_nb_ids[0], dev)); + return dev; +} + +int cache_k8_northbridges(void) +{ + int i; + struct pci_dev *dev; + if (num_k8_northbridges) + return 0; + + num_k8_northbridges = 0; + dev = NULL; + while ((dev = next_k8_northbridge(dev)) != NULL) + num_k8_northbridges++; + + k8_northbridges = kmalloc((num_k8_northbridges + 1) * sizeof(void *), + GFP_KERNEL); + if (!k8_northbridges) + return -ENOMEM; + + flush_words = kmalloc(num_k8_northbridges * sizeof(u32), GFP_KERNEL); + if (!flush_words) { + kfree(k8_northbridges); + return -ENOMEM; + } + + dev = NULL; + i = 0; + while ((dev = next_k8_northbridge(dev)) != NULL) { + k8_northbridges[i++] = dev; + pci_read_config_dword(dev, 0x9c, &flush_words[i]); + } + k8_northbridges[i] = NULL; + return 0; +} +EXPORT_SYMBOL_GPL(cache_k8_northbridges); + +/* Ignores subdevice/subvendor but as far as I can figure out + they're useless anyways */ +int __init early_is_k8_nb(u32 device) +{ + struct pci_device_id *id; + u32 vendor = device & 0xffff; + device >>= 16; + for (id = k8_nb_ids; id->vendor; id++) + if (vendor == id->vendor && device == id->device) + return 1; + return 0; +} + +void k8_flush_garts(void) +{ + int flushed, i; + unsigned long flags; + static DEFINE_SPINLOCK(gart_lock); + + /* Avoid races between AGP and IOMMU. In theory it's not needed + but I'm not sure if the hardware won't lose flush requests + when another is pending. This whole thing is so expensive anyways + that it doesn't matter to serialize more. -AK */ + spin_lock_irqsave(&gart_lock, flags); + flushed = 0; + for (i = 0; i < num_k8_northbridges; i++) { + pci_write_config_dword(k8_northbridges[i], 0x9c, + flush_words[i]|1); + flushed++; + } + for (i = 0; i < num_k8_northbridges; i++) { + u32 w; + /* Make sure the hardware actually executed the flush*/ + for (;;) { + pci_read_config_dword(k8_northbridges[i], + 0x9c, &w); + if (!(w & 1)) + break; + cpu_relax(); + } + } + spin_unlock_irqrestore(&gart_lock, flags); + if (!flushed) + printk("nothing to flush?\n"); +} +EXPORT_SYMBOL_GPL(k8_flush_garts); + diff --git a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c index 25ac8a3..83fb24a 100644 --- a/arch/x86_64/kernel/machine_kexec.c +++ b/arch/x86_64/kernel/machine_kexec.c @@ -149,8 +149,8 @@ typedef NORET_TYPE void (*relocate_new_k unsigned long start_address, unsigned long pgtable) ATTRIB_NORET; -const extern unsigned char relocate_new_kernel[]; -const extern unsigned long relocate_new_kernel_size; +extern const unsigned char relocate_new_kernel[]; +extern const unsigned long relocate_new_kernel_size; int machine_kexec_prepare(struct kimage *image) { diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index c69fc43..acd5816 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -562,7 +562,7 @@ static struct sysdev_class mce_sysclass set_kset_name("machinecheck"), }; -static DEFINE_PER_CPU(struct sys_device, device_mce); +DEFINE_PER_CPU(struct sys_device, device_mce); /* Why are there no generic functions for this? */ #define ACCESSOR(name, var, start) \ diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c index d13b241..335200a 100644 --- a/arch/x86_64/kernel/mce_amd.c +++ b/arch/x86_64/kernel/mce_amd.c @@ -1,5 +1,5 @@ /* - * (c) 2005 Advanced Micro Devices, Inc. + * (c) 2005, 2006 Advanced Micro Devices, Inc. * Your use of this code is subject to the terms and conditions of the * GNU general public license version 2. See "COPYING" or * http://www.gnu.org/licenses/gpl.html @@ -8,9 +8,10 @@ * * Support : jacob.shin@amd.com * - * MC4_MISC0 DRAM ECC Error Threshold available under AMD K8 Rev F. - * MC4_MISC0 exists per physical processor. + * April 2006 + * - added support for AMD Family 0x10 processors * + * All MC4_MISCi registers are shared between multi-cores */ #include @@ -29,32 +30,45 @@ #include #include #include -#define PFX "mce_threshold: " -#define VERSION "version 1.00.9" -#define NR_BANKS 5 -#define THRESHOLD_MAX 0xFFF -#define INT_TYPE_APIC 0x00020000 -#define MASK_VALID_HI 0x80000000 -#define MASK_LVTOFF_HI 0x00F00000 -#define MASK_COUNT_EN_HI 0x00080000 -#define MASK_INT_TYPE_HI 0x00060000 -#define MASK_OVERFLOW_HI 0x00010000 +#define PFX "mce_threshold: " +#define VERSION "version 1.1.1" +#define NR_BANKS 6 +#define NR_BLOCKS 9 +#define THRESHOLD_MAX 0xFFF +#define INT_TYPE_APIC 0x00020000 +#define MASK_VALID_HI 0x80000000 +#define MASK_LVTOFF_HI 0x00F00000 +#define MASK_COUNT_EN_HI 0x00080000 +#define MASK_INT_TYPE_HI 0x00060000 +#define MASK_OVERFLOW_HI 0x00010000 #define MASK_ERR_COUNT_HI 0x00000FFF -#define MASK_OVERFLOW 0x0001000000000000L +#define MASK_BLKPTR_LO 0xFF000000 +#define MCG_XBLK_ADDR 0xC0000400 -struct threshold_bank { +struct threshold_block { + unsigned int block; + unsigned int bank; unsigned int cpu; - u8 bank; - u8 interrupt_enable; + u32 address; + u16 interrupt_enable; u16 threshold_limit; struct kobject kobj; + struct list_head miscj; }; -static struct threshold_bank threshold_defaults = { +/* defaults used early on boot */ +static struct threshold_block threshold_defaults = { .interrupt_enable = 0, .threshold_limit = THRESHOLD_MAX, }; +struct threshold_bank { + struct kobject kobj; + struct threshold_block *blocks; + cpumask_t cpus; +}; +static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]); + #ifdef CONFIG_SMP static unsigned char shared_bank[NR_BANKS] = { 0, 0, 0, 0, 1 @@ -68,12 +82,12 @@ static DEFINE_PER_CPU(unsigned char, ban */ /* must be called with correct cpu affinity */ -static void threshold_restart_bank(struct threshold_bank *b, +static void threshold_restart_bank(struct threshold_block *b, int reset, u16 old_limit) { u32 mci_misc_hi, mci_misc_lo; - rdmsr(MSR_IA32_MC0_MISC + b->bank * 4, mci_misc_lo, mci_misc_hi); + rdmsr(b->address, mci_misc_lo, mci_misc_hi); if (b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX)) reset = 1; /* limit cannot be lower than err count */ @@ -94,35 +108,57 @@ static void threshold_restart_bank(struc (mci_misc_hi &= ~MASK_INT_TYPE_HI); mci_misc_hi |= MASK_COUNT_EN_HI; - wrmsr(MSR_IA32_MC0_MISC + b->bank * 4, mci_misc_lo, mci_misc_hi); + wrmsr(b->address, mci_misc_lo, mci_misc_hi); } +/* cpu init entry point, called from mce.c with preempt off */ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c) { - int bank; - u32 mci_misc_lo, mci_misc_hi; + unsigned int bank, block; unsigned int cpu = smp_processor_id(); + u32 low = 0, high = 0, address = 0; for (bank = 0; bank < NR_BANKS; ++bank) { - rdmsr(MSR_IA32_MC0_MISC + bank * 4, mci_misc_lo, mci_misc_hi); + for (block = 0; block < NR_BLOCKS; ++block) { + if (block == 0) + address = MSR_IA32_MC0_MISC + bank * 4; + else if (block == 1) + address = MCG_XBLK_ADDR + + ((low & MASK_BLKPTR_LO) >> 21); + else + ++address; + + if (rdmsr_safe(address, &low, &high)) + continue; - /* !valid, !counter present, bios locked */ - if (!(mci_misc_hi & MASK_VALID_HI) || - !(mci_misc_hi & MASK_VALID_HI >> 1) || - (mci_misc_hi & MASK_VALID_HI >> 2)) - continue; + if (!(high & MASK_VALID_HI)) { + if (block) + continue; + else + break; + } - per_cpu(bank_map, cpu) |= (1 << bank); + if (!(high & MASK_VALID_HI >> 1) || + (high & MASK_VALID_HI >> 2)) + continue; + if (!block) + per_cpu(bank_map, cpu) |= (1 << bank); #ifdef CONFIG_SMP - if (shared_bank[bank] && cpu_core_id[cpu]) - continue; + if (shared_bank[bank] && c->cpu_core_id) + break; #endif + high &= ~MASK_LVTOFF_HI; + high |= K8_APIC_EXT_LVT_ENTRY_THRESHOLD << 20; + wrmsr(address, low, high); - setup_threshold_lvt((mci_misc_hi & MASK_LVTOFF_HI) >> 20); - threshold_defaults.cpu = cpu; - threshold_defaults.bank = bank; - threshold_restart_bank(&threshold_defaults, 0, 0); + setup_APIC_extened_lvt(K8_APIC_EXT_LVT_ENTRY_THRESHOLD, + THRESHOLD_APIC_VECTOR, + K8_APIC_EXT_INT_MSG_FIX, 0); + + threshold_defaults.address = address; + threshold_restart_bank(&threshold_defaults, 0, 0); + } } } @@ -137,8 +173,9 @@ #endif */ asmlinkage void mce_threshold_interrupt(void) { - int bank; + unsigned int bank, block; struct mce m; + u32 low = 0, high = 0, address = 0; ack_APIC_irq(); exit_idle(); @@ -150,15 +187,42 @@ asmlinkage void mce_threshold_interrupt( /* assume first bank caused it */ for (bank = 0; bank < NR_BANKS; ++bank) { - m.bank = MCE_THRESHOLD_BASE + bank; - rdmsrl(MSR_IA32_MC0_MISC + bank * 4, m.misc); + for (block = 0; block < NR_BLOCKS; ++block) { + if (block == 0) + address = MSR_IA32_MC0_MISC + bank * 4; + else if (block == 1) + address = MCG_XBLK_ADDR + + ((low & MASK_BLKPTR_LO) >> 21); + else + ++address; + + if (rdmsr_safe(address, &low, &high)) + continue; - if (m.misc & MASK_OVERFLOW) { - mce_log(&m); - goto out; + if (!(high & MASK_VALID_HI)) { + if (block) + continue; + else + break; + } + + if (!(high & MASK_VALID_HI >> 1) || + (high & MASK_VALID_HI >> 2)) + continue; + + if (high & MASK_OVERFLOW_HI) { + rdmsrl(address, m.misc); + rdmsrl(MSR_IA32_MC0_STATUS + bank * 4, + m.status); + m.bank = K8_MCE_THRESHOLD_BASE + + bank * NR_BLOCKS + + block; + mce_log(&m); + goto out; + } } } - out: +out: irq_exit(); } @@ -166,20 +230,12 @@ asmlinkage void mce_threshold_interrupt( * Sysfs Interface */ -static struct sysdev_class threshold_sysclass = { - set_kset_name("threshold"), -}; - -static DEFINE_PER_CPU(struct sys_device, device_threshold); - struct threshold_attr { - struct attribute attr; - ssize_t(*show) (struct threshold_bank *, char *); - ssize_t(*store) (struct threshold_bank *, const char *, size_t count); + struct attribute attr; + ssize_t(*show) (struct threshold_block *, char *); + ssize_t(*store) (struct threshold_block *, const char *, size_t count); }; -static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]); - static cpumask_t affinity_set(unsigned int cpu) { cpumask_t oldmask = current->cpus_allowed; @@ -194,15 +250,15 @@ static void affinity_restore(cpumask_t o set_cpus_allowed(current, oldmask); } -#define SHOW_FIELDS(name) \ - static ssize_t show_ ## name(struct threshold_bank * b, char *buf) \ - { \ - return sprintf(buf, "%lx\n", (unsigned long) b->name); \ - } +#define SHOW_FIELDS(name) \ +static ssize_t show_ ## name(struct threshold_block * b, char *buf) \ +{ \ + return sprintf(buf, "%lx\n", (unsigned long) b->name); \ +} SHOW_FIELDS(interrupt_enable) SHOW_FIELDS(threshold_limit) -static ssize_t store_interrupt_enable(struct threshold_bank *b, +static ssize_t store_interrupt_enable(struct threshold_block *b, const char *buf, size_t count) { char *end; @@ -219,7 +275,7 @@ static ssize_t store_interrupt_enable(st return end - buf; } -static ssize_t store_threshold_limit(struct threshold_bank *b, +static ssize_t store_threshold_limit(struct threshold_block *b, const char *buf, size_t count) { char *end; @@ -242,18 +298,18 @@ static ssize_t store_threshold_limit(str return end - buf; } -static ssize_t show_error_count(struct threshold_bank *b, char *buf) +static ssize_t show_error_count(struct threshold_block *b, char *buf) { u32 high, low; cpumask_t oldmask; oldmask = affinity_set(b->cpu); - rdmsr(MSR_IA32_MC0_MISC + b->bank * 4, low, high); /* ignore low 32 */ + rdmsr(b->address, low, high); affinity_restore(oldmask); return sprintf(buf, "%x\n", (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit)); } -static ssize_t store_error_count(struct threshold_bank *b, +static ssize_t store_error_count(struct threshold_block *b, const char *buf, size_t count) { cpumask_t oldmask; @@ -269,13 +325,13 @@ #define THRESHOLD_ATTR(_name,_mode,_show .store = _store, \ }; -#define ATTR_FIELDS(name) \ - static struct threshold_attr name = \ +#define RW_ATTR(name) \ +static struct threshold_attr name = \ THRESHOLD_ATTR(name, 0644, show_## name, store_## name) -ATTR_FIELDS(interrupt_enable); -ATTR_FIELDS(threshold_limit); -ATTR_FIELDS(error_count); +RW_ATTR(interrupt_enable); +RW_ATTR(threshold_limit); +RW_ATTR(error_count); static struct attribute *default_attrs[] = { &interrupt_enable.attr, @@ -284,12 +340,12 @@ static struct attribute *default_attrs[] NULL }; -#define to_bank(k) container_of(k,struct threshold_bank,kobj) -#define to_attr(a) container_of(a,struct threshold_attr,attr) +#define to_block(k) container_of(k, struct threshold_block, kobj) +#define to_attr(a) container_of(a, struct threshold_attr, attr) static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) { - struct threshold_bank *b = to_bank(kobj); + struct threshold_block *b = to_block(kobj); struct threshold_attr *a = to_attr(attr); ssize_t ret; ret = a->show ? a->show(b, buf) : -EIO; @@ -299,7 +355,7 @@ static ssize_t show(struct kobject *kobj static ssize_t store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) { - struct threshold_bank *b = to_bank(kobj); + struct threshold_block *b = to_block(kobj); struct threshold_attr *a = to_attr(attr); ssize_t ret; ret = a->store ? a->store(b, buf, count) : -EIO; @@ -316,69 +372,174 @@ static struct kobj_type threshold_ktype .default_attrs = default_attrs, }; +static __cpuinit int allocate_threshold_blocks(unsigned int cpu, + unsigned int bank, + unsigned int block, + u32 address) +{ + int err; + u32 low, high; + struct threshold_block *b = NULL; + + if ((bank >= NR_BANKS) || (block >= NR_BLOCKS)) + return 0; + + if (rdmsr_safe(address, &low, &high)) + goto recurse; + + if (!(high & MASK_VALID_HI)) { + if (block) + goto recurse; + else + return 0; + } + + if (!(high & MASK_VALID_HI >> 1) || + (high & MASK_VALID_HI >> 2)) + goto recurse; + + b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL); + if (!b) + return -ENOMEM; + memset(b, 0, sizeof(struct threshold_block)); + + b->block = block; + b->bank = bank; + b->cpu = cpu; + b->address = address; + b->interrupt_enable = 0; + b->threshold_limit = THRESHOLD_MAX; + + INIT_LIST_HEAD(&b->miscj); + + if (per_cpu(threshold_banks, cpu)[bank]->blocks) + list_add(&b->miscj, + &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj); + else + per_cpu(threshold_banks, cpu)[bank]->blocks = b; + + kobject_set_name(&b->kobj, "misc%i", block); + b->kobj.parent = &per_cpu(threshold_banks, cpu)[bank]->kobj; + b->kobj.ktype = &threshold_ktype; + err = kobject_register(&b->kobj); + if (err) + goto out_free; +recurse: + if (!block) { + address = (low & MASK_BLKPTR_LO) >> 21; + if (!address) + return 0; + address += MCG_XBLK_ADDR; + } else + ++address; + + err = allocate_threshold_blocks(cpu, bank, ++block, address); + if (err) + goto out_free; + + return err; + +out_free: + if (b) { + kobject_unregister(&b->kobj); + kfree(b); + } + return err; +} + /* symlinks sibling shared banks to first core. first core owns dir/files. */ -static __cpuinit int threshold_create_bank(unsigned int cpu, int bank) +static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) { - int err = 0; + int i, err = 0; struct threshold_bank *b = NULL; + cpumask_t oldmask = CPU_MASK_NONE; + char name[32]; + + sprintf(name, "threshold_bank%i", bank); #ifdef CONFIG_SMP - if (cpu_core_id[cpu] && shared_bank[bank]) { /* symlink */ - char name[16]; - unsigned lcpu = first_cpu(cpu_core_map[cpu]); - if (cpu_core_id[lcpu]) - goto out; /* first core not up yet */ + if (cpu_data[cpu].cpu_core_id && shared_bank[bank]) { /* symlink */ + i = first_cpu(cpu_core_map[cpu]); + + /* first core not up yet */ + if (cpu_data[i].cpu_core_id) + goto out; + + /* already linked */ + if (per_cpu(threshold_banks, cpu)[bank]) + goto out; + + b = per_cpu(threshold_banks, i)[bank]; - b = per_cpu(threshold_banks, lcpu)[bank]; if (!b) goto out; - sprintf(name, "bank%i", bank); - err = sysfs_create_link(&per_cpu(device_threshold, cpu).kobj, + + err = sysfs_create_link(&per_cpu(device_mce, cpu).kobj, &b->kobj, name); if (err) goto out; + + b->cpus = cpu_core_map[cpu]; per_cpu(threshold_banks, cpu)[bank] = b; goto out; } #endif - b = kmalloc(sizeof(struct threshold_bank), GFP_KERNEL); + b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL); if (!b) { err = -ENOMEM; goto out; } memset(b, 0, sizeof(struct threshold_bank)); - b->cpu = cpu; - b->bank = bank; - b->interrupt_enable = 0; - b->threshold_limit = THRESHOLD_MAX; - kobject_set_name(&b->kobj, "bank%i", bank); - b->kobj.parent = &per_cpu(device_threshold, cpu).kobj; - b->kobj.ktype = &threshold_ktype; - + kobject_set_name(&b->kobj, "threshold_bank%i", bank); + b->kobj.parent = &per_cpu(device_mce, cpu).kobj; +#ifndef CONFIG_SMP + b->cpus = CPU_MASK_ALL; +#else + b->cpus = cpu_core_map[cpu]; +#endif err = kobject_register(&b->kobj); - if (err) { - kfree(b); - goto out; - } + if (err) + goto out_free; + per_cpu(threshold_banks, cpu)[bank] = b; - out: + + oldmask = affinity_set(cpu); + err = allocate_threshold_blocks(cpu, bank, 0, + MSR_IA32_MC0_MISC + bank * 4); + affinity_restore(oldmask); + + if (err) + goto out_free; + + for_each_cpu_mask(i, b->cpus) { + if (i == cpu) + continue; + + err = sysfs_create_link(&per_cpu(device_mce, i).kobj, + &b->kobj, name); + if (err) + goto out; + + per_cpu(threshold_banks, i)[bank] = b; + } + + goto out; + +out_free: + per_cpu(threshold_banks, cpu)[bank] = NULL; + kfree(b); +out: return err; } /* create dir/files for all valid threshold banks */ static __cpuinit int threshold_create_device(unsigned int cpu) { - int bank; + unsigned int bank; int err = 0; - per_cpu(device_threshold, cpu).id = cpu; - per_cpu(device_threshold, cpu).cls = &threshold_sysclass; - err = sysdev_register(&per_cpu(device_threshold, cpu)); - if (err) - goto out; - for (bank = 0; bank < NR_BANKS; ++bank) { if (!(per_cpu(bank_map, cpu) & 1 << bank)) continue; @@ -386,7 +547,7 @@ static __cpuinit int threshold_create_de if (err) goto out; } - out: +out: return err; } @@ -397,92 +558,85 @@ #ifdef CONFIG_HOTPLUG_CPU * of shared sysfs dir/files, and rest of the cores will be symlinked to it. */ -/* cpu hotplug call removes all symlinks before first core dies */ +static __cpuinit void deallocate_threshold_block(unsigned int cpu, + unsigned int bank) +{ + struct threshold_block *pos = NULL; + struct threshold_block *tmp = NULL; + struct threshold_bank *head = per_cpu(threshold_banks, cpu)[bank]; + + if (!head) + return; + + list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) { + kobject_unregister(&pos->kobj); + list_del(&pos->miscj); + kfree(pos); + } + + kfree(per_cpu(threshold_banks, cpu)[bank]->blocks); + per_cpu(threshold_banks, cpu)[bank]->blocks = NULL; +} + static __cpuinit void threshold_remove_bank(unsigned int cpu, int bank) { + int i = 0; struct threshold_bank *b; - char name[16]; + char name[32]; b = per_cpu(threshold_banks, cpu)[bank]; + if (!b) return; - if (shared_bank[bank] && atomic_read(&b->kobj.kref.refcount) > 2) { - sprintf(name, "bank%i", bank); - sysfs_remove_link(&per_cpu(device_threshold, cpu).kobj, name); - per_cpu(threshold_banks, cpu)[bank] = NULL; - } else { - kobject_unregister(&b->kobj); - kfree(per_cpu(threshold_banks, cpu)[bank]); + + if (!b->blocks) + goto free_out; + + sprintf(name, "threshold_bank%i", bank); + + /* sibling symlink */ + if (shared_bank[bank] && b->blocks->cpu != cpu) { + sysfs_remove_link(&per_cpu(device_mce, cpu).kobj, name); + per_cpu(threshold_banks, i)[bank] = NULL; + return; + } + + /* remove all sibling symlinks before unregistering */ + for_each_cpu_mask(i, b->cpus) { + if (i == cpu) + continue; + + sysfs_remove_link(&per_cpu(device_mce, i).kobj, name); + per_cpu(threshold_banks, i)[bank] = NULL; } + + deallocate_threshold_block(cpu, bank); + +free_out: + kobject_unregister(&b->kobj); + kfree(b); + per_cpu(threshold_banks, cpu)[bank] = NULL; } static __cpuinit void threshold_remove_device(unsigned int cpu) { - int bank; + unsigned int bank; for (bank = 0; bank < NR_BANKS; ++bank) { if (!(per_cpu(bank_map, cpu) & 1 << bank)) continue; threshold_remove_bank(cpu, bank); } - sysdev_unregister(&per_cpu(device_threshold, cpu)); } -/* link all existing siblings when first core comes up */ -static __cpuinit int threshold_create_symlinks(unsigned int cpu) -{ - int bank, err = 0; - unsigned int lcpu = 0; - - if (cpu_core_id[cpu]) - return 0; - for_each_cpu_mask(lcpu, cpu_core_map[cpu]) { - if (lcpu == cpu) - continue; - for (bank = 0; bank < NR_BANKS; ++bank) { - if (!(per_cpu(bank_map, cpu) & 1 << bank)) - continue; - if (!shared_bank[bank]) - continue; - err = threshold_create_bank(lcpu, bank); - } - } - return err; -} - -/* remove all symlinks before first core dies. */ -static __cpuinit void threshold_remove_symlinks(unsigned int cpu) -{ - int bank; - unsigned int lcpu = 0; - if (cpu_core_id[cpu]) - return; - for_each_cpu_mask(lcpu, cpu_core_map[cpu]) { - if (lcpu == cpu) - continue; - for (bank = 0; bank < NR_BANKS; ++bank) { - if (!(per_cpu(bank_map, cpu) & 1 << bank)) - continue; - if (!shared_bank[bank]) - continue; - threshold_remove_bank(lcpu, bank); - } - } -} #else /* !CONFIG_HOTPLUG_CPU */ -static __cpuinit void threshold_create_symlinks(unsigned int cpu) -{ -} -static __cpuinit void threshold_remove_symlinks(unsigned int cpu) -{ -} static void threshold_remove_device(unsigned int cpu) { } #endif /* get notified when a cpu comes on/off */ -static int threshold_cpu_callback(struct notifier_block *nfb, +static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { /* cpu was unsigned int to begin with */ @@ -494,13 +648,6 @@ static int threshold_cpu_callback(struct switch (action) { case CPU_ONLINE: threshold_create_device(cpu); - threshold_create_symlinks(cpu); - break; - case CPU_DOWN_PREPARE: - threshold_remove_symlinks(cpu); - break; - case CPU_DOWN_FAILED: - threshold_create_symlinks(cpu); break; case CPU_DEAD: threshold_remove_device(cpu); @@ -512,29 +659,22 @@ static int threshold_cpu_callback(struct return NOTIFY_OK; } -static struct notifier_block threshold_cpu_notifier = { +static struct notifier_block threshold_cpu_notifier __cpuinitdata = { .notifier_call = threshold_cpu_callback, }; static __init int threshold_init_device(void) { - int err; - int lcpu = 0; - - err = sysdev_class_register(&threshold_sysclass); - if (err) - goto out; + unsigned lcpu = 0; /* to hit CPUs online before the notifier is up */ for_each_online_cpu(lcpu) { - err = threshold_create_device(lcpu); + int err = threshold_create_device(lcpu); if (err) - goto out; + return err; } register_cpu_notifier(&threshold_cpu_notifier); - - out: - return err; + return 0; } device_initcall(threshold_init_device); diff --git a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c index bac195c..9d0958f 100644 --- a/arch/x86_64/kernel/module.c +++ b/arch/x86_64/kernel/module.c @@ -145,26 +145,38 @@ int apply_relocate(Elf_Shdr *sechdrs, return -ENOSYS; } -extern void apply_alternatives(void *start, void *end); - int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *me) + const Elf_Shdr *sechdrs, + struct module *me) { - const Elf_Shdr *s; + const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL; char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - /* look for .altinstructions to patch */ - for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { - void *seg; - if (strcmp(".altinstructions", secstrings + s->sh_name)) - continue; - seg = (void *)s->sh_addr; - apply_alternatives(seg, seg + s->sh_size); - } + for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { + if (!strcmp(".text", secstrings + s->sh_name)) + text = s; + if (!strcmp(".altinstructions", secstrings + s->sh_name)) + alt = s; + if (!strcmp(".smp_locks", secstrings + s->sh_name)) + locks= s; + } + + if (alt) { + /* patch .altinstructions */ + void *aseg = (void *)alt->sh_addr; + apply_alternatives(aseg, aseg + alt->sh_size); + } + if (locks && text) { + void *lseg = (void *)locks->sh_addr; + void *tseg = (void *)text->sh_addr; + alternatives_smp_module_add(me, me->name, + lseg, lseg + locks->sh_size, + tseg, tseg + text->sh_size); + } return 0; } void module_arch_cleanup(struct module *mod) { + alternatives_smp_module_del(mod); } diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 4e6357f..399489c 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -15,11 +15,7 @@ #include #include #include -#include -#include #include -#include -#include #include #include #include @@ -27,14 +23,11 @@ #include #include #include -#include -#include #include -#include #include #include -#include #include +#include /* * lapic_nmi_owner tracks the ownership of the lapic NMI hardware: @@ -74,6 +67,9 @@ #define K7_EVNTSEL_USR (1 << 16) #define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76 #define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING +#define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL +#define ARCH_PERFMON_NMI_EVENT_UMASK ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK + #define MSR_P4_MISC_ENABLE 0x1A0 #define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7) #define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL (1<<12) @@ -105,7 +101,10 @@ static __cpuinit inline int nmi_known_cp case X86_VENDOR_AMD: return boot_cpu_data.x86 == 15; case X86_VENDOR_INTEL: - return boot_cpu_data.x86 == 15; + if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) + return 1; + else + return (boot_cpu_data.x86 == 15); } return 0; } @@ -211,6 +210,8 @@ int __init setup_nmi_watchdog(char *str) __setup("nmi_watchdog=", setup_nmi_watchdog); +static void disable_intel_arch_watchdog(void); + static void disable_lapic_nmi_watchdog(void) { if (nmi_active <= 0) @@ -223,6 +224,8 @@ static void disable_lapic_nmi_watchdog(v if (boot_cpu_data.x86 == 15) { wrmsr(MSR_P4_IQ_CCCR0, 0, 0); wrmsr(MSR_P4_CRU_ESCR0, 0, 0); + } else if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { + disable_intel_arch_watchdog(); } break; } @@ -375,6 +378,53 @@ static void setup_k7_watchdog(void) wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); } +static void disable_intel_arch_watchdog(void) +{ + unsigned ebx; + + /* + * Check whether the Architectural PerfMon supports + * Unhalted Core Cycles Event or not. + * NOTE: Corresponding bit = 0 in ebp indicates event present. + */ + ebx = cpuid_ebx(10); + if (!(ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT)) + wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, 0, 0); +} + +static int setup_intel_arch_watchdog(void) +{ + unsigned int evntsel; + unsigned ebx; + + /* + * Check whether the Architectural PerfMon supports + * Unhalted Core Cycles Event or not. + * NOTE: Corresponding bit = 0 in ebp indicates event present. + */ + ebx = cpuid_ebx(10); + if ((ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT)) + return 0; + + nmi_perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0; + + clear_msr_range(MSR_ARCH_PERFMON_EVENTSEL0, 2); + clear_msr_range(MSR_ARCH_PERFMON_PERFCTR0, 2); + + evntsel = ARCH_PERFMON_EVENTSEL_INT + | ARCH_PERFMON_EVENTSEL_OS + | ARCH_PERFMON_EVENTSEL_USR + | ARCH_PERFMON_NMI_EVENT_SEL + | ARCH_PERFMON_NMI_EVENT_UMASK; + + wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0); + wrmsrl(MSR_ARCH_PERFMON_PERFCTR0, -((u64)cpu_khz * 1000 / nmi_hz)); + apic_write(APIC_LVTPC, APIC_DM_NMI); + evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE; + wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0); + return 1; +} + static int setup_p4_watchdog(void) { @@ -428,10 +478,16 @@ void setup_apic_nmi_watchdog(void) setup_k7_watchdog(); break; case X86_VENDOR_INTEL: - if (boot_cpu_data.x86 != 15) - return; - if (!setup_p4_watchdog()) + if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { + if (!setup_intel_arch_watchdog()) + return; + } else if (boot_cpu_data.x86 == 15) { + if (!setup_p4_watchdog()) + return; + } else { return; + } + break; default: @@ -516,7 +572,14 @@ #endif */ wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0); apic_write(APIC_LVTPC, APIC_DM_NMI); - } + } else if (nmi_perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) { + /* + * For Intel based architectural perfmon + * - LVTPC is masked on interrupt and must be + * unmasked by the LVTPC handler. + */ + apic_write(APIC_LVTPC, APIC_DM_NMI); + } wrmsrl(nmi_perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz)); } } diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c new file mode 100644 index 0000000..d91cb84 --- /dev/null +++ b/arch/x86_64/kernel/pci-calgary.c @@ -0,0 +1,1018 @@ +/* + * Derived from arch/powerpc/kernel/iommu.c + * + * Copyright (C) 2006 Jon Mason , IBM Corporation + * Copyright (C) 2006 Muli Ben-Yehuda , IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCI_DEVICE_ID_IBM_CALGARY 0x02a1 +#define PCI_VENDOR_DEVICE_ID_CALGARY \ + (PCI_VENDOR_ID_IBM | PCI_DEVICE_ID_IBM_CALGARY << 16) + +/* we need these for register space address calculation */ +#define START_ADDRESS 0xfe000000 +#define CHASSIS_BASE 0 +#define ONE_BASED_CHASSIS_NUM 1 + +/* register offsets inside the host bridge space */ +#define PHB_CSR_OFFSET 0x0110 +#define PHB_PLSSR_OFFSET 0x0120 +#define PHB_CONFIG_RW_OFFSET 0x0160 +#define PHB_IOBASE_BAR_LOW 0x0170 +#define PHB_IOBASE_BAR_HIGH 0x0180 +#define PHB_MEM_1_LOW 0x0190 +#define PHB_MEM_1_HIGH 0x01A0 +#define PHB_IO_ADDR_SIZE 0x01B0 +#define PHB_MEM_1_SIZE 0x01C0 +#define PHB_MEM_ST_OFFSET 0x01D0 +#define PHB_AER_OFFSET 0x0200 +#define PHB_CONFIG_0_HIGH 0x0220 +#define PHB_CONFIG_0_LOW 0x0230 +#define PHB_CONFIG_0_END 0x0240 +#define PHB_MEM_2_LOW 0x02B0 +#define PHB_MEM_2_HIGH 0x02C0 +#define PHB_MEM_2_SIZE_HIGH 0x02D0 +#define PHB_MEM_2_SIZE_LOW 0x02E0 +#define PHB_DOSHOLE_OFFSET 0x08E0 + +/* PHB_CONFIG_RW */ +#define PHB_TCE_ENABLE 0x20000000 +#define PHB_SLOT_DISABLE 0x1C000000 +#define PHB_DAC_DISABLE 0x01000000 +#define PHB_MEM2_ENABLE 0x00400000 +#define PHB_MCSR_ENABLE 0x00100000 +/* TAR (Table Address Register) */ +#define TAR_SW_BITS 0x0000ffffffff800fUL +#define TAR_VALID 0x0000000000000008UL +/* CSR (Channel/DMA Status Register) */ +#define CSR_AGENT_MASK 0xffe0ffff + +#define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */ +#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * 2) /* max dev->bus->number */ +#define PHBS_PER_CALGARY 4 + +/* register offsets in Calgary's internal register space */ +static const unsigned long tar_offsets[] = { + 0x0580 /* TAR0 */, + 0x0588 /* TAR1 */, + 0x0590 /* TAR2 */, + 0x0598 /* TAR3 */ +}; + +static const unsigned long split_queue_offsets[] = { + 0x4870 /* SPLIT QUEUE 0 */, + 0x5870 /* SPLIT QUEUE 1 */, + 0x6870 /* SPLIT QUEUE 2 */, + 0x7870 /* SPLIT QUEUE 3 */ +}; + +static const unsigned long phb_offsets[] = { + 0x8000 /* PHB0 */, + 0x9000 /* PHB1 */, + 0xA000 /* PHB2 */, + 0xB000 /* PHB3 */ +}; + +void* tce_table_kva[MAX_NUM_OF_PHBS * MAX_NUMNODES]; +unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED; +static int translate_empty_slots __read_mostly = 0; +static int calgary_detected __read_mostly = 0; + +/* + * the bitmap of PHBs the user requested that we disable + * translation on. + */ +static DECLARE_BITMAP(translation_disabled, MAX_NUMNODES * MAX_PHB_BUS_NUM); + +static void tce_cache_blast(struct iommu_table *tbl); + +/* enable this to stress test the chip's TCE cache */ +#ifdef CONFIG_IOMMU_DEBUG +static inline void tce_cache_blast_stress(struct iommu_table *tbl) +{ + tce_cache_blast(tbl); +} +#else +static inline void tce_cache_blast_stress(struct iommu_table *tbl) +{ +} +#endif /* BLAST_TCE_CACHE_ON_UNMAP */ + +static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen) +{ + unsigned int npages; + + npages = PAGE_ALIGN(dma + dmalen) - (dma & PAGE_MASK); + npages >>= PAGE_SHIFT; + + return npages; +} + +static inline int translate_phb(struct pci_dev* dev) +{ + int disabled = test_bit(dev->bus->number, translation_disabled); + return !disabled; +} + +static void iommu_range_reserve(struct iommu_table *tbl, + unsigned long start_addr, unsigned int npages) +{ + unsigned long index; + unsigned long end; + + index = start_addr >> PAGE_SHIFT; + + /* bail out if we're asked to reserve a region we don't cover */ + if (index >= tbl->it_size) + return; + + end = index + npages; + if (end > tbl->it_size) /* don't go off the table */ + end = tbl->it_size; + + while (index < end) { + if (test_bit(index, tbl->it_map)) + printk(KERN_ERR "Calgary: entry already allocated at " + "0x%lx tbl %p dma 0x%lx npages %u\n", + index, tbl, start_addr, npages); + ++index; + } + set_bit_string(tbl->it_map, start_addr >> PAGE_SHIFT, npages); +} + +static unsigned long iommu_range_alloc(struct iommu_table *tbl, + unsigned int npages) +{ + unsigned long offset; + + BUG_ON(npages == 0); + + offset = find_next_zero_string(tbl->it_map, tbl->it_hint, + tbl->it_size, npages); + if (offset == ~0UL) { + tce_cache_blast(tbl); + offset = find_next_zero_string(tbl->it_map, 0, + tbl->it_size, npages); + if (offset == ~0UL) { + printk(KERN_WARNING "Calgary: IOMMU full.\n"); + if (panic_on_overflow) + panic("Calgary: fix the allocator.\n"); + else + return bad_dma_address; + } + } + + set_bit_string(tbl->it_map, offset, npages); + tbl->it_hint = offset + npages; + BUG_ON(tbl->it_hint > tbl->it_size); + + return offset; +} + +static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *vaddr, + unsigned int npages, int direction) +{ + unsigned long entry, flags; + dma_addr_t ret = bad_dma_address; + + spin_lock_irqsave(&tbl->it_lock, flags); + + entry = iommu_range_alloc(tbl, npages); + + if (unlikely(entry == bad_dma_address)) + goto error; + + /* set the return dma address */ + ret = (entry << PAGE_SHIFT) | ((unsigned long)vaddr & ~PAGE_MASK); + + /* put the TCEs in the HW table */ + tce_build(tbl, entry, npages, (unsigned long)vaddr & PAGE_MASK, + direction); + + spin_unlock_irqrestore(&tbl->it_lock, flags); + + return ret; + +error: + spin_unlock_irqrestore(&tbl->it_lock, flags); + printk(KERN_WARNING "Calgary: failed to allocate %u pages in " + "iommu %p\n", npages, tbl); + return bad_dma_address; +} + +static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, + unsigned int npages) +{ + unsigned long entry; + unsigned long i; + + entry = dma_addr >> PAGE_SHIFT; + + BUG_ON(entry + npages > tbl->it_size); + + tce_free(tbl, entry, npages); + + for (i = 0; i < npages; ++i) { + if (!test_bit(entry + i, tbl->it_map)) + printk(KERN_ERR "Calgary: bit is off at 0x%lx " + "tbl %p dma 0x%Lx entry 0x%lx npages %u\n", + entry + i, tbl, dma_addr, entry, npages); + } + + __clear_bit_string(tbl->it_map, entry, npages); + + tce_cache_blast_stress(tbl); +} + +static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, + unsigned int npages) +{ + unsigned long flags; + + spin_lock_irqsave(&tbl->it_lock, flags); + + __iommu_free(tbl, dma_addr, npages); + + spin_unlock_irqrestore(&tbl->it_lock, flags); +} + +static void __calgary_unmap_sg(struct iommu_table *tbl, + struct scatterlist *sglist, int nelems, int direction) +{ + while (nelems--) { + unsigned int npages; + dma_addr_t dma = sglist->dma_address; + unsigned int dmalen = sglist->dma_length; + + if (dmalen == 0) + break; + + npages = num_dma_pages(dma, dmalen); + __iommu_free(tbl, dma, npages); + sglist++; + } +} + +void calgary_unmap_sg(struct device *dev, struct scatterlist *sglist, + int nelems, int direction) +{ + unsigned long flags; + struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata; + + if (!translate_phb(to_pci_dev(dev))) + return; + + spin_lock_irqsave(&tbl->it_lock, flags); + + __calgary_unmap_sg(tbl, sglist, nelems, direction); + + spin_unlock_irqrestore(&tbl->it_lock, flags); +} + +static int calgary_nontranslate_map_sg(struct device* dev, + struct scatterlist *sg, int nelems, int direction) +{ + int i; + + for (i = 0; i < nelems; i++ ) { + struct scatterlist *s = &sg[i]; + BUG_ON(!s->page); + s->dma_address = virt_to_bus(page_address(s->page) +s->offset); + s->dma_length = s->length; + } + return nelems; +} + +int calgary_map_sg(struct device *dev, struct scatterlist *sg, + int nelems, int direction) +{ + struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata; + unsigned long flags; + unsigned long vaddr; + unsigned int npages; + unsigned long entry; + int i; + + if (!translate_phb(to_pci_dev(dev))) + return calgary_nontranslate_map_sg(dev, sg, nelems, direction); + + spin_lock_irqsave(&tbl->it_lock, flags); + + for (i = 0; i < nelems; i++ ) { + struct scatterlist *s = &sg[i]; + BUG_ON(!s->page); + + vaddr = (unsigned long)page_address(s->page) + s->offset; + npages = num_dma_pages(vaddr, s->length); + + entry = iommu_range_alloc(tbl, npages); + if (entry == bad_dma_address) { + /* makes sure unmap knows to stop */ + s->dma_length = 0; + goto error; + } + + s->dma_address = (entry << PAGE_SHIFT) | s->offset; + + /* insert into HW table */ + tce_build(tbl, entry, npages, vaddr & PAGE_MASK, + direction); + + s->dma_length = s->length; + } + + spin_unlock_irqrestore(&tbl->it_lock, flags); + + return nelems; +error: + __calgary_unmap_sg(tbl, sg, nelems, direction); + for (i = 0; i < nelems; i++) { + sg[i].dma_address = bad_dma_address; + sg[i].dma_length = 0; + } + spin_unlock_irqrestore(&tbl->it_lock, flags); + return 0; +} + +dma_addr_t calgary_map_single(struct device *dev, void *vaddr, + size_t size, int direction) +{ + dma_addr_t dma_handle = bad_dma_address; + unsigned long uaddr; + unsigned int npages; + struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata; + + uaddr = (unsigned long)vaddr; + npages = num_dma_pages(uaddr, size); + + if (translate_phb(to_pci_dev(dev))) + dma_handle = iommu_alloc(tbl, vaddr, npages, direction); + else + dma_handle = virt_to_bus(vaddr); + + return dma_handle; +} + +void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle, + size_t size, int direction) +{ + struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata; + unsigned int npages; + + if (!translate_phb(to_pci_dev(dev))) + return; + + npages = num_dma_pages(dma_handle, size); + iommu_free(tbl, dma_handle, npages); +} + +void* calgary_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag) +{ + void *ret = NULL; + dma_addr_t mapping; + unsigned int npages, order; + struct iommu_table *tbl; + + tbl = to_pci_dev(dev)->bus->self->sysdata; + + size = PAGE_ALIGN(size); /* size rounded up to full pages */ + npages = size >> PAGE_SHIFT; + order = get_order(size); + + /* alloc enough pages (and possibly more) */ + ret = (void *)__get_free_pages(flag, order); + if (!ret) + goto error; + memset(ret, 0, size); + + if (translate_phb(to_pci_dev(dev))) { + /* set up tces to cover the allocated range */ + mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL); + if (mapping == bad_dma_address) + goto free; + + *dma_handle = mapping; + } else /* non translated slot */ + *dma_handle = virt_to_bus(ret); + + return ret; + +free: + free_pages((unsigned long)ret, get_order(size)); + ret = NULL; +error: + return ret; +} + +static struct dma_mapping_ops calgary_dma_ops = { + .alloc_coherent = calgary_alloc_coherent, + .map_single = calgary_map_single, + .unmap_single = calgary_unmap_single, + .map_sg = calgary_map_sg, + .unmap_sg = calgary_unmap_sg, +}; + +static inline int busno_to_phbid(unsigned char num) +{ + return bus_to_phb(num) % PHBS_PER_CALGARY; +} + +static inline unsigned long split_queue_offset(unsigned char num) +{ + size_t idx = busno_to_phbid(num); + + return split_queue_offsets[idx]; +} + +static inline unsigned long tar_offset(unsigned char num) +{ + size_t idx = busno_to_phbid(num); + + return tar_offsets[idx]; +} + +static inline unsigned long phb_offset(unsigned char num) +{ + size_t idx = busno_to_phbid(num); + + return phb_offsets[idx]; +} + +static inline void __iomem* calgary_reg(void __iomem *bar, unsigned long offset) +{ + unsigned long target = ((unsigned long)bar) | offset; + return (void __iomem*)target; +} + +static void tce_cache_blast(struct iommu_table *tbl) +{ + u64 val; + u32 aer; + int i = 0; + void __iomem *bbar = tbl->bbar; + void __iomem *target; + + /* disable arbitration on the bus */ + target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_AER_OFFSET); + aer = readl(target); + writel(0, target); + + /* read plssr to ensure it got there */ + target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_PLSSR_OFFSET); + val = readl(target); + + /* poll split queues until all DMA activity is done */ + target = calgary_reg(bbar, split_queue_offset(tbl->it_busno)); + do { + val = readq(target); + i++; + } while ((val & 0xff) != 0xff && i < 100); + if (i == 100) + printk(KERN_WARNING "Calgary: PCI bus not quiesced, " + "continuing anyway\n"); + + /* invalidate TCE cache */ + target = calgary_reg(bbar, tar_offset(tbl->it_busno)); + writeq(tbl->tar_val, target); + + /* enable arbitration */ + target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_AER_OFFSET); + writel(aer, target); + (void)readl(target); /* flush */ +} + +static void __init calgary_reserve_mem_region(struct pci_dev *dev, u64 start, + u64 limit) +{ + unsigned int numpages; + + limit = limit | 0xfffff; + limit++; + + numpages = ((limit - start) >> PAGE_SHIFT); + iommu_range_reserve(dev->sysdata, start, numpages); +} + +static void __init calgary_reserve_peripheral_mem_1(struct pci_dev *dev) +{ + void __iomem *target; + u64 low, high, sizelow; + u64 start, limit; + struct iommu_table *tbl = dev->sysdata; + unsigned char busnum = dev->bus->number; + void __iomem *bbar = tbl->bbar; + + /* peripheral MEM_1 region */ + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_LOW); + low = be32_to_cpu(readl(target)); + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_HIGH); + high = be32_to_cpu(readl(target)); + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_SIZE); + sizelow = be32_to_cpu(readl(target)); + + start = (high << 32) | low; + limit = sizelow; + + calgary_reserve_mem_region(dev, start, limit); +} + +static void __init calgary_reserve_peripheral_mem_2(struct pci_dev *dev) +{ + void __iomem *target; + u32 val32; + u64 low, high, sizelow, sizehigh; + u64 start, limit; + struct iommu_table *tbl = dev->sysdata; + unsigned char busnum = dev->bus->number; + void __iomem *bbar = tbl->bbar; + + /* is it enabled? */ + target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET); + val32 = be32_to_cpu(readl(target)); + if (!(val32 & PHB_MEM2_ENABLE)) + return; + + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_LOW); + low = be32_to_cpu(readl(target)); + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_HIGH); + high = be32_to_cpu(readl(target)); + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_SIZE_LOW); + sizelow = be32_to_cpu(readl(target)); + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_SIZE_HIGH); + sizehigh = be32_to_cpu(readl(target)); + + start = (high << 32) | low; + limit = (sizehigh << 32) | sizelow; + + calgary_reserve_mem_region(dev, start, limit); +} + +/* + * some regions of the IO address space do not get translated, so we + * must not give devices IO addresses in those regions. The regions + * are the 640KB-1MB region and the two PCI peripheral memory holes. + * Reserve all of them in the IOMMU bitmap to avoid giving them out + * later. + */ +static void __init calgary_reserve_regions(struct pci_dev *dev) +{ + unsigned int npages; + void __iomem *bbar; + unsigned char busnum; + u64 start; + struct iommu_table *tbl = dev->sysdata; + + bbar = tbl->bbar; + busnum = dev->bus->number; + + /* reserve bad_dma_address in case it's a legal address */ + iommu_range_reserve(tbl, bad_dma_address, 1); + + /* avoid the BIOS/VGA first 640KB-1MB region */ + start = (640 * 1024); + npages = ((1024 - 640) * 1024) >> PAGE_SHIFT; + iommu_range_reserve(tbl, start, npages); + + /* reserve the two PCI peripheral memory regions in IO space */ + calgary_reserve_peripheral_mem_1(dev); + calgary_reserve_peripheral_mem_2(dev); +} + +static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar) +{ + u64 val64; + u64 table_phys; + void __iomem *target; + int ret; + struct iommu_table *tbl; + + /* build TCE tables for each PHB */ + ret = build_tce_table(dev, bbar); + if (ret) + return ret; + + calgary_reserve_regions(dev); + + /* set TARs for each PHB */ + target = calgary_reg(bbar, tar_offset(dev->bus->number)); + val64 = be64_to_cpu(readq(target)); + + /* zero out all TAR bits under sw control */ + val64 &= ~TAR_SW_BITS; + + tbl = dev->sysdata; + table_phys = (u64)__pa(tbl->it_base); + val64 |= table_phys; + + BUG_ON(specified_table_size > TCE_TABLE_SIZE_8M); + val64 |= (u64) specified_table_size; + + tbl->tar_val = cpu_to_be64(val64); + writeq(tbl->tar_val, target); + readq(target); /* flush */ + + return 0; +} + +static void __init calgary_free_tar(struct pci_dev *dev) +{ + u64 val64; + struct iommu_table *tbl = dev->sysdata; + void __iomem *target; + + target = calgary_reg(tbl->bbar, tar_offset(dev->bus->number)); + val64 = be64_to_cpu(readq(target)); + val64 &= ~TAR_SW_BITS; + writeq(cpu_to_be64(val64), target); + readq(target); /* flush */ + + kfree(tbl); + dev->sysdata = NULL; +} + +static void calgary_watchdog(unsigned long data) +{ + struct pci_dev *dev = (struct pci_dev *)data; + struct iommu_table *tbl = dev->sysdata; + void __iomem *bbar = tbl->bbar; + u32 val32; + void __iomem *target; + + target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_CSR_OFFSET); + val32 = be32_to_cpu(readl(target)); + + /* If no error, the agent ID in the CSR is not valid */ + if (val32 & CSR_AGENT_MASK) { + printk(KERN_EMERG "calgary_watchdog: DMA error on bus %d, " + "CSR = %#x\n", dev->bus->number, val32); + writel(0, target); + + /* Disable bus that caused the error */ + target = calgary_reg(bbar, phb_offset(tbl->it_busno) | + PHB_CONFIG_RW_OFFSET); + val32 = be32_to_cpu(readl(target)); + val32 |= PHB_SLOT_DISABLE; + writel(cpu_to_be32(val32), target); + readl(target); /* flush */ + } else { + /* Reset the timer */ + mod_timer(&tbl->watchdog_timer, jiffies + 2 * HZ); + } +} + +static void __init calgary_enable_translation(struct pci_dev *dev) +{ + u32 val32; + unsigned char busnum; + void __iomem *target; + void __iomem *bbar; + struct iommu_table *tbl; + + busnum = dev->bus->number; + tbl = dev->sysdata; + bbar = tbl->bbar; + + /* enable TCE in PHB Config Register */ + target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET); + val32 = be32_to_cpu(readl(target)); + val32 |= PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE; + + printk(KERN_INFO "Calgary: enabling translation on PHB %d\n", busnum); + printk(KERN_INFO "Calgary: errant DMAs will now be prevented on this " + "bus.\n"); + + writel(cpu_to_be32(val32), target); + readl(target); /* flush */ + + init_timer(&tbl->watchdog_timer); + tbl->watchdog_timer.function = &calgary_watchdog; + tbl->watchdog_timer.data = (unsigned long)dev; + mod_timer(&tbl->watchdog_timer, jiffies); +} + +static void __init calgary_disable_translation(struct pci_dev *dev) +{ + u32 val32; + unsigned char busnum; + void __iomem *target; + void __iomem *bbar; + struct iommu_table *tbl; + + busnum = dev->bus->number; + tbl = dev->sysdata; + bbar = tbl->bbar; + + /* disable TCE in PHB Config Register */ + target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET); + val32 = be32_to_cpu(readl(target)); + val32 &= ~(PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE); + + printk(KERN_INFO "Calgary: disabling translation on PHB %d!\n", busnum); + writel(cpu_to_be32(val32), target); + readl(target); /* flush */ + + del_timer_sync(&tbl->watchdog_timer); +} + +static inline unsigned int __init locate_register_space(struct pci_dev *dev) +{ + int rionodeid; + u32 address; + + rionodeid = (dev->bus->number % 15 > 4) ? 3 : 2; + /* + * register space address calculation as follows: + * FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase) + * ChassisBase is always zero for x366/x260/x460 + * RioNodeId is 2 for first Calgary, 3 for second Calgary + */ + address = START_ADDRESS - + (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 15)) + + (0x100000) * (rionodeid - CHASSIS_BASE); + return address; +} + +static int __init calgary_init_one_nontraslated(struct pci_dev *dev) +{ + dev->sysdata = NULL; + dev->bus->self = dev; + + return 0; +} + +static int __init calgary_init_one(struct pci_dev *dev) +{ + u32 address; + void __iomem *bbar; + int ret; + + address = locate_register_space(dev); + /* map entire 1MB of Calgary config space */ + bbar = ioremap_nocache(address, 1024 * 1024); + if (!bbar) { + ret = -ENODATA; + goto done; + } + + ret = calgary_setup_tar(dev, bbar); + if (ret) + goto iounmap; + + dev->bus->self = dev; + calgary_enable_translation(dev); + + return 0; + +iounmap: + iounmap(bbar); +done: + return ret; +} + +static int __init calgary_init(void) +{ + int i, ret = -ENODEV; + struct pci_dev *dev = NULL; + + for (i = 0; i <= num_online_nodes() * MAX_NUM_OF_PHBS; i++) { + dev = pci_get_device(PCI_VENDOR_ID_IBM, + PCI_DEVICE_ID_IBM_CALGARY, + dev); + if (!dev) + break; + if (!translate_phb(dev)) { + calgary_init_one_nontraslated(dev); + continue; + } + if (!tce_table_kva[i] && !translate_empty_slots) { + pci_dev_put(dev); + continue; + } + ret = calgary_init_one(dev); + if (ret) + goto error; + } + + return ret; + +error: + for (i--; i >= 0; i--) { + dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM, + PCI_DEVICE_ID_IBM_CALGARY, + dev); + if (!translate_phb(dev)) { + pci_dev_put(dev); + continue; + } + if (!tce_table_kva[i] && !translate_empty_slots) + continue; + calgary_disable_translation(dev); + calgary_free_tar(dev); + pci_dev_put(dev); + } + + return ret; +} + +static inline int __init determine_tce_table_size(u64 ram) +{ + int ret; + + if (specified_table_size != TCE_TABLE_SIZE_UNSPECIFIED) + return specified_table_size; + + /* + * Table sizes are from 0 to 7 (TCE_TABLE_SIZE_64K to + * TCE_TABLE_SIZE_8M). Table size 0 has 8K entries and each + * larger table size has twice as many entries, so shift the + * max ram address by 13 to divide by 8K and then look at the + * order of the result to choose between 0-7. + */ + ret = get_order(ram >> 13); + if (ret > TCE_TABLE_SIZE_8M) + ret = TCE_TABLE_SIZE_8M; + + return ret; +} + +void __init detect_calgary(void) +{ + u32 val; + int bus, table_idx; + void *tbl; + int detected = 0; + + /* + * if the user specified iommu=off or iommu=soft or we found + * another HW IOMMU already, bail out. + */ + if (swiotlb || no_iommu || iommu_detected) + return; + + specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE); + + for (bus = 0, table_idx = 0; + bus <= num_online_nodes() * MAX_PHB_BUS_NUM; + bus++) { + BUG_ON(bus > MAX_NUMNODES * MAX_PHB_BUS_NUM); + if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY) + continue; + if (test_bit(bus, translation_disabled)) { + printk(KERN_INFO "Calgary: translation is disabled for " + "PHB 0x%x\n", bus); + /* skip this phb, don't allocate a tbl for it */ + tce_table_kva[table_idx] = NULL; + table_idx++; + continue; + } + /* + * scan the first slot of the PCI bus to see if there + * are any devices present + */ + val = read_pci_config(bus, 1, 0, 0); + if (val != 0xffffffff || translate_empty_slots) { + tbl = alloc_tce_table(); + if (!tbl) + goto cleanup; + detected = 1; + } else + tbl = NULL; + + tce_table_kva[table_idx] = tbl; + table_idx++; + } + + if (detected) { + iommu_detected = 1; + calgary_detected = 1; + printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected. " + "TCE table spec is %d.\n", specified_table_size); + } + return; + +cleanup: + for (--table_idx; table_idx >= 0; --table_idx) + if (tce_table_kva[table_idx]) + free_tce_table(tce_table_kva[table_idx]); +} + +int __init calgary_iommu_init(void) +{ + int ret; + + if (no_iommu || swiotlb) + return -ENODEV; + + if (!calgary_detected) + return -ENODEV; + + /* ok, we're trying to use Calgary - let's roll */ + printk(KERN_INFO "PCI-DMA: Using Calgary IOMMU\n"); + + ret = calgary_init(); + if (ret) { + printk(KERN_ERR "PCI-DMA: Calgary init failed %d, " + "falling back to no_iommu\n", ret); + if (end_pfn > MAX_DMA32_PFN) + printk(KERN_ERR "WARNING more than 4GB of memory, " + "32bit PCI may malfunction.\n"); + return ret; + } + + force_iommu = 1; + dma_ops = &calgary_dma_ops; + + return 0; +} + +static int __init calgary_parse_options(char *p) +{ + unsigned int bridge; + size_t len; + char* endp; + + while (*p) { + if (!strncmp(p, "64k", 3)) + specified_table_size = TCE_TABLE_SIZE_64K; + else if (!strncmp(p, "128k", 4)) + specified_table_size = TCE_TABLE_SIZE_128K; + else if (!strncmp(p, "256k", 4)) + specified_table_size = TCE_TABLE_SIZE_256K; + else if (!strncmp(p, "512k", 4)) + specified_table_size = TCE_TABLE_SIZE_512K; + else if (!strncmp(p, "1M", 2)) + specified_table_size = TCE_TABLE_SIZE_1M; + else if (!strncmp(p, "2M", 2)) + specified_table_size = TCE_TABLE_SIZE_2M; + else if (!strncmp(p, "4M", 2)) + specified_table_size = TCE_TABLE_SIZE_4M; + else if (!strncmp(p, "8M", 2)) + specified_table_size = TCE_TABLE_SIZE_8M; + + len = strlen("translate_empty_slots"); + if (!strncmp(p, "translate_empty_slots", len)) + translate_empty_slots = 1; + + len = strlen("disable"); + if (!strncmp(p, "disable", len)) { + p += len; + if (*p == '=') + ++p; + if (*p == '\0') + break; + bridge = simple_strtol(p, &endp, 0); + if (p == endp) + break; + + if (bridge <= (num_online_nodes() * MAX_PHB_BUS_NUM)) { + printk(KERN_INFO "Calgary: disabling " + "translation for PHB 0x%x\n", bridge); + set_bit(bridge, translation_disabled); + } + } + + p = strpbrk(p, ","); + if (!p) + break; + + p++; /* skip ',' */ + } + return 1; +} +__setup("calgary=", calgary_parse_options); diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c index a9275c9..9c44f4f 100644 --- a/arch/x86_64/kernel/pci-dma.c +++ b/arch/x86_64/kernel/pci-dma.c @@ -9,6 +9,7 @@ #include #include #include #include +#include int iommu_merge __read_mostly = 0; EXPORT_SYMBOL(iommu_merge); @@ -33,12 +34,15 @@ int panic_on_overflow __read_mostly = 0; int force_iommu __read_mostly= 0; #endif +/* Set this to 1 if there is a HW IOMMU in the system */ +int iommu_detected __read_mostly = 0; + /* Dummy device used for NULL arguments (normally ISA). Better would be probably a smaller DMA mask, but this is bug-to-bug compatible to i386. */ struct device fallback_dev = { .bus_id = "fallback device", - .coherent_dma_mask = 0xffffffff, + .coherent_dma_mask = DMA_32BIT_MASK, .dma_mask = &fallback_dev.coherent_dma_mask, }; @@ -77,7 +81,7 @@ dma_alloc_coherent(struct device *dev, s dev = &fallback_dev; dma_mask = dev->coherent_dma_mask; if (dma_mask == 0) - dma_mask = 0xffffffff; + dma_mask = DMA_32BIT_MASK; /* Don't invoke OOM killer */ gfp |= __GFP_NORETRY; @@ -90,7 +94,7 @@ dma_alloc_coherent(struct device *dev, s larger than 16MB and in this case we have a chance of finding fitting memory in the next higher zone first. If not retry with true GFP_DMA. -AK */ - if (dma_mask <= 0xffffffff) + if (dma_mask <= DMA_32BIT_MASK) gfp |= GFP_DMA32; again: @@ -111,7 +115,7 @@ dma_alloc_coherent(struct device *dev, s /* Don't use the 16MB ZONE_DMA unless absolutely needed. It's better to use remapping first. */ - if (dma_mask < 0xffffffff && !(gfp & GFP_DMA)) { + if (dma_mask < DMA_32BIT_MASK && !(gfp & GFP_DMA)) { gfp = (gfp & ~GFP_DMA32) | GFP_DMA; goto again; } @@ -174,7 +178,7 @@ int dma_supported(struct device *dev, u6 /* Copied from i386. Doesn't make much sense, because it will only work for pci_alloc_coherent. The caller just has to use GFP_DMA in this case. */ - if (mask < 0x00ffffff) + if (mask < DMA_24BIT_MASK) return 0; /* Tell the device to use SAC when IOMMU force is on. This @@ -189,7 +193,7 @@ int dma_supported(struct device *dev, u6 SAC for these. Assume all masks <= 40 bits are of this type. Normally this doesn't make any difference, but gives more gentle handling of IOMMU overflow. */ - if (iommu_sac_force && (mask >= 0xffffffffffULL)) { + if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) { printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask); return 0; } @@ -266,7 +270,7 @@ #ifdef CONFIG_SWIOTLB swiotlb = 1; #endif -#ifdef CONFIG_GART_IOMMU +#ifdef CONFIG_IOMMU gart_parse_options(p); #endif @@ -276,3 +280,40 @@ #endif } return 1; } +__setup("iommu=", iommu_setup); + +void __init pci_iommu_alloc(void) +{ + /* + * The order of these functions is important for + * fall-back/fail-over reasons + */ +#ifdef CONFIG_IOMMU + iommu_hole_init(); +#endif + +#ifdef CONFIG_CALGARY_IOMMU + detect_calgary(); +#endif + +#ifdef CONFIG_SWIOTLB + pci_swiotlb_init(); +#endif +} + +static int __init pci_iommu_init(void) +{ +#ifdef CONFIG_CALGARY_IOMMU + calgary_iommu_init(); +#endif + +#ifdef CONFIG_IOMMU + gart_iommu_init(); +#endif + + no_iommu_init(); + return 0; +} + +/* Must execute after PCI subsystem */ +fs_initcall(pci_iommu_init); diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 82a7c9b..4ca674d 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -32,6 +32,7 @@ #include #include #include #include +#include unsigned long iommu_bus_base; /* GART remapping area (physical) */ static unsigned long iommu_size; /* size of remapping area bytes */ @@ -46,8 +47,6 @@ u32 *iommu_gatt_base; /* Remapping tab also seen with Qlogic at least). */ int iommu_fullflush = 1; -#define MAX_NB 8 - /* Allocation bitmap for the remapping area */ static DEFINE_SPINLOCK(iommu_bitmap_lock); static unsigned long *iommu_gart_bitmap; /* guarded by iommu_bitmap_lock */ @@ -63,13 +62,6 @@ #define GPTE_DECODE(x) (((x) & 0xfffff00 #define to_pages(addr,size) \ (round_up(((addr) & ~PAGE_MASK) + (size), PAGE_SIZE) >> PAGE_SHIFT) -#define for_all_nb(dev) \ - dev = NULL; \ - while ((dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, dev))!=NULL) - -static struct pci_dev *northbridges[MAX_NB]; -static u32 northbridge_flush_word[MAX_NB]; - #define EMERGENCY_PAGES 32 /* = 128KB */ #ifdef CONFIG_AGP @@ -93,7 +85,7 @@ static unsigned long alloc_iommu(int siz offset = find_next_zero_string(iommu_gart_bitmap,next_bit,iommu_pages,size); if (offset == -1) { need_flush = 1; - offset = find_next_zero_string(iommu_gart_bitmap,0,next_bit,size); + offset = find_next_zero_string(iommu_gart_bitmap,0,iommu_pages,size); } if (offset != -1) { set_bit_string(iommu_gart_bitmap, offset, size); @@ -120,44 +112,17 @@ static void free_iommu(unsigned long off /* * Use global flush state to avoid races with multiple flushers. */ -static void flush_gart(struct device *dev) +static void flush_gart(void) { unsigned long flags; - int flushed = 0; - int i, max; - spin_lock_irqsave(&iommu_bitmap_lock, flags); - if (need_flush) { - max = 0; - for (i = 0; i < MAX_NB; i++) { - if (!northbridges[i]) - continue; - pci_write_config_dword(northbridges[i], 0x9c, - northbridge_flush_word[i] | 1); - flushed++; - max = i; - } - for (i = 0; i <= max; i++) { - u32 w; - if (!northbridges[i]) - continue; - /* Make sure the hardware actually executed the flush. */ - for (;;) { - pci_read_config_dword(northbridges[i], 0x9c, &w); - if (!(w & 1)) - break; - cpu_relax(); - } - } - if (!flushed) - printk("nothing to flush?\n"); + if (need_flush) { + k8_flush_garts(); need_flush = 0; } spin_unlock_irqrestore(&iommu_bitmap_lock, flags); } - - #ifdef CONFIG_IOMMU_LEAK #define SET_LEAK(x) if (iommu_leak_tab) \ @@ -266,7 +231,7 @@ static dma_addr_t gart_map_simple(struct size_t size, int dir) { dma_addr_t map = dma_map_area(dev, virt_to_bus(buf), size, dir); - flush_gart(dev); + flush_gart(); return map; } @@ -289,6 +254,28 @@ dma_addr_t gart_map_single(struct device } /* + * Free a DMA mapping. + */ +void gart_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, int direction) +{ + unsigned long iommu_page; + int npages; + int i; + + if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || + dma_addr >= iommu_bus_base + iommu_size) + return; + iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT; + npages = to_pages(dma_addr, size); + for (i = 0; i < npages; i++) { + iommu_gatt_base[iommu_page + i] = gart_unmapped_entry; + CLEAR_LEAK(iommu_page + i); + } + free_iommu(iommu_page, npages); +} + +/* * Wrapper for pci_unmap_single working with scatterlists. */ void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) @@ -299,7 +286,7 @@ void gart_unmap_sg(struct device *dev, s struct scatterlist *s = &sg[i]; if (!s->dma_length || !s->length) break; - dma_unmap_single(dev, s->dma_address, s->dma_length, dir); + gart_unmap_single(dev, s->dma_address, s->dma_length, dir); } } @@ -329,7 +316,7 @@ #endif s->dma_address = addr; s->dma_length = s->length; } - flush_gart(dev); + flush_gart(); return nents; } @@ -436,13 +423,13 @@ int gart_map_sg(struct device *dev, stru if (dma_map_cont(sg, start, i, sg+out, pages, need) < 0) goto error; out++; - flush_gart(dev); + flush_gart(); if (out < nents) sg[out].dma_length = 0; return out; error: - flush_gart(NULL); + flush_gart(); gart_unmap_sg(dev, sg, nents, dir); /* When it was forced or merged try again in a dumb way */ if (force_iommu || iommu_merge) { @@ -458,28 +445,6 @@ error: return 0; } -/* - * Free a DMA mapping. - */ -void gart_unmap_single(struct device *dev, dma_addr_t dma_addr, - size_t size, int direction) -{ - unsigned long iommu_page; - int npages; - int i; - - if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || - dma_addr >= iommu_bus_base + iommu_size) - return; - iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT; - npages = to_pages(dma_addr, size); - for (i = 0; i < npages; i++) { - iommu_gatt_base[iommu_page + i] = gart_unmapped_entry; - CLEAR_LEAK(iommu_page + i); - } - free_iommu(iommu_page, npages); -} - static int no_agp; static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) @@ -532,10 +497,13 @@ static __init int init_k8_gatt(struct ag void *gatt; unsigned aper_base, new_aper_base; unsigned aper_size, gatt_size, new_aper_size; - + int i; + printk(KERN_INFO "PCI-DMA: Disabling AGP.\n"); aper_size = aper_base = info->aper_size = 0; - for_all_nb(dev) { + dev = NULL; + for (i = 0; i < num_k8_northbridges; i++) { + dev = k8_northbridges[i]; new_aper_base = read_aperture(dev, &new_aper_size); if (!new_aper_base) goto nommu; @@ -558,11 +526,12 @@ static __init int init_k8_gatt(struct ag panic("Cannot allocate GATT table"); memset(gatt, 0, gatt_size); agp_gatt_table = gatt; - - for_all_nb(dev) { + + for (i = 0; i < num_k8_northbridges; i++) { u32 ctl; u32 gatt_reg; + dev = k8_northbridges[i]; gatt_reg = __pa(gatt) >> 12; gatt_reg <<= 4; pci_write_config_dword(dev, 0x98, gatt_reg); @@ -573,7 +542,7 @@ static __init int init_k8_gatt(struct ag pci_write_config_dword(dev, 0x90, ctl); } - flush_gart(NULL); + flush_gart(); printk("PCI-DMA: aperture base @ %x size %u KB\n",aper_base, aper_size>>10); return 0; @@ -602,15 +571,19 @@ static struct dma_mapping_ops gart_dma_o .unmap_sg = gart_unmap_sg, }; -static int __init pci_iommu_init(void) +void __init gart_iommu_init(void) { struct agp_kern_info info; unsigned long aper_size; unsigned long iommu_start; - struct pci_dev *dev; unsigned long scratch; long i; + if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0) { + printk(KERN_INFO "PCI-GART: No AMD northbridge found.\n"); + return; + } + #ifndef CONFIG_AGP_AMD64 no_agp = 1; #else @@ -622,7 +595,11 @@ #else #endif if (swiotlb) - return -1; + return; + + /* Did we detect a different HW IOMMU? */ + if (iommu_detected && !iommu_aperture) + return; if (no_iommu || (!force_iommu && end_pfn <= MAX_DMA32_PFN) || @@ -634,15 +611,7 @@ #endif "but IOMMU not available.\n" KERN_ERR "WARNING 32bit PCI may malfunction.\n"); } - return -1; - } - - i = 0; - for_all_nb(dev) - i++; - if (i > MAX_NB) { - printk(KERN_ERR "PCI-GART: Too many northbridges (%ld). Disabled\n", i); - return -1; + return; } printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n"); @@ -707,26 +676,10 @@ #endif for (i = EMERGENCY_PAGES; i < iommu_pages; i++) iommu_gatt_base[i] = gart_unmapped_entry; - for_all_nb(dev) { - u32 flag; - int cpu = PCI_SLOT(dev->devfn) - 24; - if (cpu >= MAX_NB) - continue; - northbridges[cpu] = dev; - pci_read_config_dword(dev, 0x9c, &flag); /* cache flush word */ - northbridge_flush_word[cpu] = flag; - } - - flush_gart(NULL); - + flush_gart(); dma_ops = &gart_dma_ops; - - return 0; } -/* Must execute after PCI subsystem */ -fs_initcall(pci_iommu_init); - void gart_parse_options(char *p) { int arg; diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c index 1f6ecc6..c4c3cc3 100644 --- a/arch/x86_64/kernel/pci-nommu.c +++ b/arch/x86_64/kernel/pci-nommu.c @@ -4,6 +4,8 @@ #include #include #include #include +#include + #include #include #include @@ -12,10 +14,11 @@ static int check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size) { if (hwdev && bus + size > *hwdev->dma_mask) { - if (*hwdev->dma_mask >= 0xffffffffULL) + if (*hwdev->dma_mask >= DMA_32BIT_MASK) printk(KERN_ERR - "nommu_%s: overflow %Lx+%lu of device mask %Lx\n", - name, (long long)bus, size, (long long)*hwdev->dma_mask); + "nommu_%s: overflow %Lx+%zu of device mask %Lx\n", + name, (long long)bus, size, + (long long)*hwdev->dma_mask); return 0; } return 1; diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c index 990ed67..ebdb77f 100644 --- a/arch/x86_64/kernel/pci-swiotlb.c +++ b/arch/x86_64/kernel/pci-swiotlb.c @@ -31,7 +31,7 @@ struct dma_mapping_ops swiotlb_dma_ops = void pci_swiotlb_init(void) { /* don't initialize swiotlb if iommu=off (no_iommu=1) */ - if (!iommu_aperture && !no_iommu && + if (!iommu_detected && !no_iommu && (end_pfn > MAX_DMA32_PFN || force_iommu)) swiotlb = 1; if (swiotlb) { diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c index bf421ed..7554458 100644 --- a/arch/x86_64/kernel/pmtimer.c +++ b/arch/x86_64/kernel/pmtimer.c @@ -27,7 +27,7 @@ #include /* The I/O port the PMTMR resides at. * The location is detected during setup_arch(), * in arch/i386/kernel/acpi/boot.c */ -u32 pmtmr_ioport; +u32 pmtmr_ioport __read_mostly; /* value of the Power timer at last timer interrupt */ static u32 offset_delay; diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index fb903e6..ca56e19 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -10,7 +10,6 @@ * Andi Kleen. * * CPU hotplug support - ashok.raj@intel.com - * $Id: process.c,v 1.38 2002/01/15 10:08:03 ak Exp $ */ /* @@ -64,6 +63,7 @@ EXPORT_SYMBOL(boot_option_idle_override) * Powermanagement idle function, if any.. */ void (*pm_idle)(void); +EXPORT_SYMBOL(pm_idle); static DEFINE_PER_CPU(unsigned int, cpu_idle_state); static ATOMIC_NOTIFIER_HEAD(idle_notifier); @@ -111,7 +111,7 @@ static void default_idle(void) { local_irq_enable(); - clear_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status &= ~TS_POLLING; smp_mb__after_clear_bit(); while (!need_resched()) { local_irq_disable(); @@ -120,7 +120,7 @@ static void default_idle(void) else local_irq_enable(); } - set_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status |= TS_POLLING; } /* @@ -203,8 +203,7 @@ #endif /* CONFIG_HOTPLUG_CPU */ */ void cpu_idle (void) { - set_thread_flag(TIF_POLLING_NRFLAG); - + current_thread_info()->status |= TS_POLLING; /* endless idle loop with no priority at all */ while (1) { while (!need_resched()) { @@ -335,7 +334,7 @@ void show_regs(struct pt_regs *regs) { printk("CPU %d:", smp_processor_id()); __show_regs(regs); - show_trace(®s->rsp); + show_trace(NULL, regs, (void *)(regs + 1)); } /* @@ -365,8 +364,11 @@ void flush_thread(void) struct task_struct *tsk = current; struct thread_info *t = current_thread_info(); - if (t->flags & _TIF_ABI_PENDING) + if (t->flags & _TIF_ABI_PENDING) { t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32); + if (t->flags & _TIF_IA32) + current_thread_info()->status |= TS_COMPAT; + } tsk->thread.debugreg0 = 0; tsk->thread.debugreg1 = 0; diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c index 57117b8..2d67698 100644 --- a/arch/x86_64/kernel/reboot.c +++ b/arch/x86_64/kernel/reboot.c @@ -20,6 +20,7 @@ #include * Power off function, if any */ void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); static long no_idt[3]; static enum { diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 655b919..1129918 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -5,8 +5,6 @@ * * Nov 2001 Dave Jones * Forked from i386 setup code. - * - * $Id$ */ /* @@ -65,9 +63,7 @@ #include #include #include #include -#include #include -#include #include /* @@ -75,6 +71,7 @@ #include */ struct cpuinfo_x86 boot_cpu_data __read_mostly; +EXPORT_SYMBOL(boot_cpu_data); unsigned long mmu_cr4_features; @@ -103,12 +100,14 @@ char dmi_alloc_data[DMI_MAX_DATA]; * Setup options */ struct screen_info screen_info; +EXPORT_SYMBOL(screen_info); struct sys_desc_table_struct { unsigned short length; unsigned char table[0]; }; struct edid_info edid_info; +EXPORT_SYMBOL_GPL(edid_info); struct e820map e820; extern int root_mountflags; @@ -473,80 +472,6 @@ contig_initmem_init(unsigned long start_ } #endif -/* Use inline assembly to define this because the nops are defined - as inline assembly strings in the include files and we cannot - get them easily into strings. */ -asm("\t.data\nk8nops: " - K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6 - K8_NOP7 K8_NOP8); - -extern unsigned char k8nops[]; -static unsigned char *k8_nops[ASM_NOP_MAX+1] = { - NULL, - k8nops, - k8nops + 1, - k8nops + 1 + 2, - k8nops + 1 + 2 + 3, - k8nops + 1 + 2 + 3 + 4, - k8nops + 1 + 2 + 3 + 4 + 5, - k8nops + 1 + 2 + 3 + 4 + 5 + 6, - k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7, -}; - -extern char __vsyscall_0; - -/* Replace instructions with better alternatives for this CPU type. - - This runs before SMP is initialized to avoid SMP problems with - self modifying code. This implies that assymetric systems where - APs have less capabilities than the boot processor are not handled. - In this case boot with "noreplacement". */ -void apply_alternatives(void *start, void *end) -{ - struct alt_instr *a; - int diff, i, k; - for (a = start; (void *)a < end; a++) { - u8 *instr; - - if (!boot_cpu_has(a->cpuid)) - continue; - - BUG_ON(a->replacementlen > a->instrlen); - instr = a->instr; - /* vsyscall code is not mapped yet. resolve it manually. */ - if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) - instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0)); - __inline_memcpy(instr, a->replacement, a->replacementlen); - diff = a->instrlen - a->replacementlen; - - /* Pad the rest with nops */ - for (i = a->replacementlen; diff > 0; diff -= k, i += k) { - k = diff; - if (k > ASM_NOP_MAX) - k = ASM_NOP_MAX; - __inline_memcpy(instr + i, k8_nops[k], k); - } - } -} - -static int no_replacement __initdata = 0; - -void __init alternative_instructions(void) -{ - extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; - if (no_replacement) - return; - apply_alternatives(__alt_instructions, __alt_instructions_end); -} - -static int __init noreplacement_setup(char *s) -{ - no_replacement = 1; - return 1; -} - -__setup("noreplacement", noreplacement_setup); - #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) struct edd edd; #ifdef CONFIG_EDD_MODULE @@ -728,7 +653,7 @@ #ifdef CONFIG_BLK_DEV_INITRD #endif #ifdef CONFIG_KEXEC if (crashk_res.start != crashk_res.end) { - reserve_bootmem(crashk_res.start, + reserve_bootmem_generic(crashk_res.start, crashk_res.end - crashk_res.start + 1); } #endif @@ -779,10 +704,6 @@ #endif e820_setup_gap(); -#ifdef CONFIG_GART_IOMMU - iommu_hole_init(); -#endif - #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) conswitchp = &vga_con; @@ -867,24 +788,32 @@ #endif static void __init amd_detect_cmp(struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP - int cpu = smp_processor_id(); unsigned bits; #ifdef CONFIG_NUMA + int cpu = smp_processor_id(); int node = 0; unsigned apicid = hard_smp_processor_id(); #endif + unsigned ecx = cpuid_ecx(0x80000008); + + c->x86_max_cores = (ecx & 0xff) + 1; - bits = 0; - while ((1 << bits) < c->x86_max_cores) - bits++; + /* CPU telling us the core id bits shift? */ + bits = (ecx >> 12) & 0xF; + + /* Otherwise recompute */ + if (bits == 0) { + while ((1 << bits) < c->x86_max_cores) + bits++; + } /* Low order bits define the core id (index of core in socket) */ - cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1); + c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1); /* Convert the APIC ID into the socket ID */ - phys_proc_id[cpu] = phys_pkg_id(bits); + c->phys_proc_id = phys_pkg_id(bits); #ifdef CONFIG_NUMA - node = phys_proc_id[cpu]; + node = c->phys_proc_id; if (apicid_to_node[apicid] != NUMA_NO_NODE) node = apicid_to_node[apicid]; if (!node_online(node)) { @@ -897,7 +826,7 @@ #ifdef CONFIG_NUMA but in the same order as the HT nodeids. If that doesn't result in a usable node fall back to the path for the previous case. */ - int ht_nodeid = apicid - (phys_proc_id[0] << bits); + int ht_nodeid = apicid - (cpu_data[0].phys_proc_id << bits); if (ht_nodeid >= 0 && apicid_to_node[ht_nodeid] != NUMA_NO_NODE) node = apicid_to_node[ht_nodeid]; @@ -907,15 +836,13 @@ #ifdef CONFIG_NUMA } numa_set_node(cpu, node); - printk(KERN_INFO "CPU %d/%x(%d) -> Node %d -> Core %d\n", - cpu, apicid, c->x86_max_cores, node, cpu_core_id[cpu]); + printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node); #endif #endif } -static int __init init_amd(struct cpuinfo_x86 *c) +static void __init init_amd(struct cpuinfo_x86 *c) { - int r; unsigned level; #ifdef CONFIG_SMP @@ -948,8 +875,8 @@ #endif if (c->x86 >= 6) set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability); - r = get_model_name(c); - if (!r) { + level = get_model_name(c); + if (!level) { switch (c->x86) { case 15: /* Should distinguish Models here, but this is only @@ -964,13 +891,12 @@ #endif if (c->x86_power & (1<<8)) set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); - if (c->extended_cpuid_level >= 0x80000008) { - c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; - + /* Multi core CPU? */ + if (c->extended_cpuid_level >= 0x80000008) amd_detect_cmp(c); - } - return r; + /* Fix cpuid4 emulation for more */ + num_cache_leaves = 3; } static void __cpuinit detect_ht(struct cpuinfo_x86 *c) @@ -978,13 +904,14 @@ static void __cpuinit detect_ht(struct c #ifdef CONFIG_SMP u32 eax, ebx, ecx, edx; int index_msb, core_bits; - int cpu = smp_processor_id(); cpuid(1, &eax, &ebx, &ecx, &edx); - if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) + if (!cpu_has(c, X86_FEATURE_HT)) return; + if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) + goto out; smp_num_siblings = (ebx & 0xff0000) >> 16; @@ -999,10 +926,7 @@ #ifdef CONFIG_SMP } index_msb = get_count_order(smp_num_siblings); - phys_proc_id[cpu] = phys_pkg_id(index_msb); - - printk(KERN_INFO "CPU: Physical Processor ID: %d\n", - phys_proc_id[cpu]); + c->phys_proc_id = phys_pkg_id(index_msb); smp_num_siblings = smp_num_siblings / c->x86_max_cores; @@ -1010,13 +934,15 @@ #ifdef CONFIG_SMP core_bits = get_count_order(c->x86_max_cores); - cpu_core_id[cpu] = phys_pkg_id(index_msb) & + c->cpu_core_id = phys_pkg_id(index_msb) & ((1 << core_bits) - 1); - - if (c->x86_max_cores > 1) - printk(KERN_INFO "CPU: Processor Core ID: %d\n", - cpu_core_id[cpu]); } +out: + if ((c->x86_max_cores * smp_num_siblings) > 1) { + printk(KERN_INFO "CPU: Physical Processor ID: %d\n", c->phys_proc_id); + printk(KERN_INFO "CPU: Processor Core ID: %d\n", c->cpu_core_id); + } + #endif } @@ -1025,15 +951,12 @@ #endif */ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) { - unsigned int eax; + unsigned int eax, t; if (c->cpuid_level < 4) return 1; - __asm__("cpuid" - : "=a" (eax) - : "0" (4), "c" (0) - : "bx", "dx"); + cpuid_count(4, 0, &eax, &t, &t, &t); if (eax & 0x1f) return ((eax >> 26) + 1); @@ -1046,16 +969,17 @@ static void srat_detect_node(void) #ifdef CONFIG_NUMA unsigned node; int cpu = smp_processor_id(); + int apicid = hard_smp_processor_id(); /* Don't do the funky fallback heuristics the AMD version employs for now. */ - node = apicid_to_node[hard_smp_processor_id()]; + node = apicid_to_node[apicid]; if (node == NUMA_NO_NODE) node = first_node(node_online_map); numa_set_node(cpu, node); if (acpi_numa > 0) - printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node); + printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node); #endif } @@ -1065,6 +989,13 @@ static void __cpuinit init_intel(struct unsigned n; init_intel_cacheinfo(c); + if (c->cpuid_level > 9 ) { + unsigned eax = cpuid_eax(10); + /* Check for version and the number of counters */ + if ((eax & 0xff) && (((eax>>8) & 0xff) > 1)) + set_bit(X86_FEATURE_ARCH_PERFMON, &c->x86_capability); + } + n = c->extended_cpuid_level; if (n >= 0x80000008) { unsigned eax = cpuid_eax(0x80000008); @@ -1156,7 +1087,7 @@ void __cpuinit early_identify_cpu(struct } #ifdef CONFIG_SMP - phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff; + c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff; #endif } @@ -1283,7 +1214,7 @@ static int show_cpuinfo(struct seq_file NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL, - NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow", + NULL, "fxsr_opt", NULL, "rdtscp", NULL, "lm", "3dnowext", "3dnow", /* Transmeta-defined */ "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, @@ -1294,7 +1225,7 @@ static int show_cpuinfo(struct seq_file /* Other (Linux-defined) */ "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL, "constant_tsc", NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "up", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -1364,9 +1295,9 @@ #endif #ifdef CONFIG_SMP if (smp_num_siblings * c->x86_max_cores > 1) { int cpu = c - cpu_data; - seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]); + seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu])); - seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]); + seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); } #endif @@ -1440,7 +1371,7 @@ struct seq_operations cpuinfo_op = { .show = show_cpuinfo, }; -#ifdef CONFIG_INPUT_PCSPKR +#if defined(CONFIG_INPUT_PCSPKR) || defined(CONFIG_INPUT_PCSPKR_MODULE) #include static __init int add_pcspkr(void) { diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 8a691fa..f5934cb 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -3,7 +3,6 @@ * Copyright (C) 1995 Linus Torvalds * Copyright 2001, 2002, 2003 SuSE Labs / Andi Kleen. * See setup.c for older changelog. - * $Id: setup64.c,v 1.12 2002/03/21 10:09:17 ak Exp $ */ #include #include @@ -31,6 +30,7 @@ char x86_boot_params[BOOT_PARAM_SIZE] __ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; struct x8664_pda *_cpu_pda[NR_CPUS] __read_mostly; +EXPORT_SYMBOL(_cpu_pda); struct x8664_pda boot_cpu_pda[NR_CPUS] __cacheline_aligned; struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; @@ -38,6 +38,7 @@ struct desc_ptr idt_descr = { 256 * 16 - char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned"))); unsigned long __supported_pte_mask __read_mostly = ~0UL; +EXPORT_SYMBOL(__supported_pte_mask); static int do_not_nx __cpuinitdata = 0; /* noexec=on|off diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index e5f5ce7..2816117 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c @@ -7,8 +7,6 @@ * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes * 2000-2002 x86-64 support by Andi Kleen - * - * $Id: signal.c,v 1.18 2001/10/17 22:30:37 ak Exp $ */ #include @@ -239,7 +237,6 @@ get_stack(struct k_sigaction *ka, struct rsp = regs->rsp - 128; /* This is the X/Open sanctioned signal stack switching. */ - /* RED-PEN: redzone on that stack? */ if (ka->sa.sa_flags & SA_ONSTACK) { if (sas_ss_flags(rsp) == 0) rsp = current->sas_ss_sp + current->sas_ss_size; diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index 4a6628b..acee4bc 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c @@ -224,6 +224,7 @@ void flush_tlb_current_task(void) flush_tlb_others(cpu_mask, mm, FLUSH_ALL); preempt_enable(); } +EXPORT_SYMBOL(flush_tlb_current_task); void flush_tlb_mm (struct mm_struct * mm) { @@ -244,6 +245,7 @@ void flush_tlb_mm (struct mm_struct * mm preempt_enable(); } +EXPORT_SYMBOL(flush_tlb_mm); void flush_tlb_page(struct vm_area_struct * vma, unsigned long va) { @@ -266,6 +268,7 @@ void flush_tlb_page(struct vm_area_struc preempt_enable(); } +EXPORT_SYMBOL(flush_tlb_page); static void do_flush_tlb_all(void* info) { @@ -443,6 +446,7 @@ int smp_call_function (void (*func) (voi spin_unlock(&call_lock); return 0; } +EXPORT_SYMBOL(smp_call_function); void smp_stop_cpu(void) { @@ -460,7 +464,7 @@ static void smp_really_stop_cpu(void *du { smp_stop_cpu(); for (;;) - asm("hlt"); + halt(); } void smp_send_stop(void) @@ -470,7 +474,7 @@ void smp_send_stop(void) return; /* Don't deadlock on the call lock in panic */ if (!spin_trylock(&call_lock)) { - /* ignore locking because we have paniced anyways */ + /* ignore locking because we have panicked anyways */ nolock = 1; } __smp_call_function(smp_really_stop_cpu, NULL, 0, 0); @@ -520,13 +524,13 @@ asmlinkage void smp_call_function_interr int safe_smp_processor_id(void) { - int apicid, i; + unsigned apicid, i; if (disable_apic) return 0; apicid = hard_smp_processor_id(); - if (x86_cpu_to_apicid[apicid] == apicid) + if (apicid < NR_CPUS && x86_cpu_to_apicid[apicid] == apicid) return apicid; for (i = 0; i < NR_CPUS; ++i) { diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 71a7222..4e97551 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -63,13 +63,11 @@ #include /* Number of siblings per CPU package */ int smp_num_siblings = 1; -/* Package ID of each logical CPU */ -u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; -/* core ID of each logical CPU */ -u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; +EXPORT_SYMBOL(smp_num_siblings); /* Last level cache ID of each logical CPU */ u8 cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID}; +EXPORT_SYMBOL(cpu_llc_id); /* Bitmask of currently online CPUs */ cpumask_t cpu_online_map __read_mostly; @@ -82,18 +80,21 @@ EXPORT_SYMBOL(cpu_online_map); */ cpumask_t cpu_callin_map; cpumask_t cpu_callout_map; +EXPORT_SYMBOL(cpu_callout_map); cpumask_t cpu_possible_map; EXPORT_SYMBOL(cpu_possible_map); /* Per CPU bogomips and other parameters */ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; +EXPORT_SYMBOL(cpu_data); /* Set when the idlers are all forked */ int smp_threads_ready; /* representing HT siblings of each logical CPU */ cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; +EXPORT_SYMBOL(cpu_sibling_map); /* representing HT and core siblings of each logical CPU */ cpumask_t cpu_core_map[NR_CPUS] __read_mostly; @@ -472,8 +473,8 @@ static inline void set_cpu_sibling_map(i if (smp_num_siblings > 1) { for_each_cpu_mask(i, cpu_sibling_setup_map) { - if (phys_proc_id[cpu] == phys_proc_id[i] && - cpu_core_id[cpu] == cpu_core_id[i]) { + if (c[cpu].phys_proc_id == c[i].phys_proc_id && + c[cpu].cpu_core_id == c[i].cpu_core_id) { cpu_set(i, cpu_sibling_map[cpu]); cpu_set(cpu, cpu_sibling_map[i]); cpu_set(i, cpu_core_map[cpu]); @@ -500,7 +501,7 @@ static inline void set_cpu_sibling_map(i cpu_set(i, c[cpu].llc_shared_map); cpu_set(cpu, c[i].llc_shared_map); } - if (phys_proc_id[cpu] == phys_proc_id[i]) { + if (c[cpu].phys_proc_id == c[i].phys_proc_id) { cpu_set(i, cpu_core_map[cpu]); cpu_set(cpu, cpu_core_map[i]); /* @@ -797,6 +798,8 @@ static int __cpuinit do_boot_cpu(int cpu } + alternatives_smp_switch(1); + c_idle.idle = get_idle_for_cpu(cpu); if (c_idle.idle) { @@ -1199,8 +1202,8 @@ static void remove_siblinginfo(int cpu) cpu_clear(cpu, cpu_sibling_map[sibling]); cpus_clear(cpu_sibling_map[cpu]); cpus_clear(cpu_core_map[cpu]); - phys_proc_id[cpu] = BAD_APICID; - cpu_core_id[cpu] = BAD_APICID; + c[cpu].phys_proc_id = 0; + c[cpu].cpu_core_id = 0; cpu_clear(cpu, cpu_sibling_setup_map); } @@ -1259,6 +1262,8 @@ void __cpu_die(unsigned int cpu) /* They ack this in play_dead by setting CPU_DEAD */ if (per_cpu(cpu_state, cpu) == CPU_DEAD) { printk ("CPU %d is now offline\n", cpu); + if (1 == num_online_cpus()) + alternatives_smp_switch(0); return; } msleep(100); diff --git a/arch/x86_64/kernel/tce.c b/arch/x86_64/kernel/tce.c new file mode 100644 index 0000000..8d4c67f --- /dev/null +++ b/arch/x86_64/kernel/tce.c @@ -0,0 +1,202 @@ +/* + * Derived from arch/powerpc/platforms/pseries/iommu.c + * + * Copyright (C) 2006 Jon Mason , IBM Corporation + * Copyright (C) 2006 Muli Ben-Yehuda , IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* flush a tce at 'tceaddr' to main memory */ +static inline void flush_tce(void* tceaddr) +{ + /* a single tce can't cross a cache line */ + if (cpu_has_clflush) + asm volatile("clflush (%0)" :: "r" (tceaddr)); + else + asm volatile("wbinvd":::"memory"); +} + +void tce_build(struct iommu_table *tbl, unsigned long index, + unsigned int npages, unsigned long uaddr, int direction) +{ + u64* tp; + u64 t; + u64 rpn; + + t = (1 << TCE_READ_SHIFT); + if (direction != DMA_TO_DEVICE) + t |= (1 << TCE_WRITE_SHIFT); + + tp = ((u64*)tbl->it_base) + index; + + while (npages--) { + rpn = (virt_to_bus((void*)uaddr)) >> PAGE_SHIFT; + t &= ~TCE_RPN_MASK; + t |= (rpn << TCE_RPN_SHIFT); + + *tp = cpu_to_be64(t); + flush_tce(tp); + + uaddr += PAGE_SIZE; + tp++; + } +} + +void tce_free(struct iommu_table *tbl, long index, unsigned int npages) +{ + u64* tp; + + tp = ((u64*)tbl->it_base) + index; + + while (npages--) { + *tp = cpu_to_be64(0); + flush_tce(tp); + tp++; + } +} + +static inline unsigned int table_size_to_number_of_entries(unsigned char size) +{ + /* + * size is the order of the table, 0-7 + * smallest table is 8K entries, so shift result by 13 to + * multiply by 8K + */ + return (1 << size) << 13; +} + +static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl) +{ + unsigned int bitmapsz; + unsigned int tce_table_index; + unsigned long bmppages; + int ret; + + tbl->it_busno = dev->bus->number; + + /* set the tce table size - measured in entries */ + tbl->it_size = table_size_to_number_of_entries(specified_table_size); + + tce_table_index = bus_to_phb(tbl->it_busno); + tbl->it_base = (unsigned long)tce_table_kva[tce_table_index]; + if (!tbl->it_base) { + printk(KERN_ERR "Calgary: iommu_table_setparms: " + "no table allocated?!\n"); + ret = -ENOMEM; + goto done; + } + + /* + * number of bytes needed for the bitmap size in number of + * entries; we need one bit per entry + */ + bitmapsz = tbl->it_size / BITS_PER_BYTE; + bmppages = __get_free_pages(GFP_KERNEL, get_order(bitmapsz)); + if (!bmppages) { + printk(KERN_ERR "Calgary: cannot allocate bitmap\n"); + ret = -ENOMEM; + goto done; + } + + tbl->it_map = (unsigned long*)bmppages; + + memset(tbl->it_map, 0, bitmapsz); + + tbl->it_hint = 0; + + spin_lock_init(&tbl->it_lock); + + return 0; + +done: + return ret; +} + +int build_tce_table(struct pci_dev *dev, void __iomem *bbar) +{ + struct iommu_table *tbl; + int ret; + + if (dev->sysdata) { + printk(KERN_ERR "Calgary: dev %p has sysdata %p\n", + dev, dev->sysdata); + BUG(); + } + + tbl = kzalloc(sizeof(struct iommu_table), GFP_KERNEL); + if (!tbl) { + printk(KERN_ERR "Calgary: error allocating iommu_table\n"); + ret = -ENOMEM; + goto done; + } + + ret = tce_table_setparms(dev, tbl); + if (ret) + goto free_tbl; + + tce_free(tbl, 0, tbl->it_size); + + tbl->bbar = bbar; + + /* + * NUMA is already using the bus's sysdata pointer, so we use + * the bus's pci_dev's sysdata instead. + */ + dev->sysdata = tbl; + + return 0; + +free_tbl: + kfree(tbl); +done: + return ret; +} + +void* alloc_tce_table(void) +{ + unsigned int size; + + size = table_size_to_number_of_entries(specified_table_size); + size *= TCE_ENTRY_SIZE; + + return __alloc_bootmem_low(size, size, 0); +} + +void free_tce_table(void *tbl) +{ + unsigned int size; + + if (!tbl) + return; + + size = table_size_to_number_of_entries(specified_table_size); + size *= TCE_ENTRY_SIZE; + + free_bootmem(__pa(tbl), size); +} diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 7392570..ebbee6f 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -8,7 +8,7 @@ * Copyright (c) 1995 Markus Kuhn * Copyright (c) 1996 Ingo Molnar * Copyright (c) 1998 Andrea Arcangeli - * Copyright (c) 2002 Vojtech Pavlik + * Copyright (c) 2002,2006 Vojtech Pavlik * Copyright (c) 2003 Andi Kleen * RTC support code taken from arch/i386/kernel/timers/time_hpet.c */ @@ -51,14 +51,21 @@ extern int using_apic_timer; static char *time_init_gtod(void); DEFINE_SPINLOCK(rtc_lock); +EXPORT_SYMBOL(rtc_lock); DEFINE_SPINLOCK(i8253_lock); int nohpet __initdata = 0; static int notsc __initdata = 0; -#undef HPET_HACK_ENABLE_DANGEROUS +#define USEC_PER_TICK (USEC_PER_SEC / HZ) +#define NSEC_PER_TICK (NSEC_PER_SEC / HZ) +#define FSEC_PER_TICK (FSEC_PER_SEC / HZ) + +#define NS_SCALE 10 /* 2^10, carefully chosen */ +#define US_SCALE 32 /* 2^32, arbitralrily chosen */ unsigned int cpu_khz; /* TSC clocks / usec, not used here */ +EXPORT_SYMBOL(cpu_khz); static unsigned long hpet_period; /* fsecs / HPET clock */ unsigned long hpet_tick; /* HPET clocks / interrupt */ int hpet_use_timer; /* Use counter of hpet for time keeping, otherwise PIT */ @@ -90,7 +97,7 @@ static inline unsigned int do_gettimeoff t = get_cycles_sync(); if (t < vxtime.last_tsc) t = vxtime.last_tsc; /* hack */ - x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> 32; + x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> US_SCALE; return x; } @@ -98,7 +105,7 @@ static inline unsigned int do_gettimeoff { /* cap counter read to one tick to avoid inconsistencies */ unsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last; - return (min(counter,hpet_tick) * vxtime.quot) >> 32; + return (min(counter,hpet_tick) * vxtime.quot) >> US_SCALE; } unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc; @@ -118,7 +125,7 @@ void do_gettimeofday(struct timeval *tv) seq = read_seqbegin(&xtime_lock); sec = xtime.tv_sec; - usec = xtime.tv_nsec / 1000; + usec = xtime.tv_nsec / NSEC_PER_USEC; /* i386 does some correction here to keep the clock monotonous even when ntpd is fixing drift. @@ -129,14 +136,14 @@ void do_gettimeofday(struct timeval *tv) in arch/x86_64/kernel/vsyscall.c and export all needed variables in vmlinux.lds. -AK */ - t = (jiffies - wall_jiffies) * (1000000L / HZ) + + t = (jiffies - wall_jiffies) * USEC_PER_TICK + do_gettimeoffset(); usec += t; } while (read_seqretry(&xtime_lock, seq)); - tv->tv_sec = sec + usec / 1000000; - tv->tv_usec = usec % 1000000; + tv->tv_sec = sec + usec / USEC_PER_SEC; + tv->tv_usec = usec % USEC_PER_SEC; } EXPORT_SYMBOL(do_gettimeofday); @@ -157,8 +164,8 @@ int do_settimeofday(struct timespec *tv) write_seqlock_irq(&xtime_lock); - nsec -= do_gettimeoffset() * 1000 + - (jiffies - wall_jiffies) * (NSEC_PER_SEC/HZ); + nsec -= do_gettimeoffset() * NSEC_PER_USEC + + (jiffies - wall_jiffies) * NSEC_PER_TICK; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); @@ -288,7 +295,7 @@ unsigned long long monotonic_clock(void) this_offset = hpet_readl(HPET_COUNTER); } while (read_seqretry(&xtime_lock, seq)); offset = (this_offset - last_offset); - offset *= (NSEC_PER_SEC/HZ) / hpet_tick; + offset *= NSEC_PER_TICK / hpet_tick; } else { do { seq = read_seqbegin(&xtime_lock); @@ -297,7 +304,8 @@ unsigned long long monotonic_clock(void) base = monotonic_base; } while (read_seqretry(&xtime_lock, seq)); this_offset = get_cycles_sync(); - offset = (this_offset - last_offset)*1000 / cpu_khz; + /* FIXME: 1000 or 1000000? */ + offset = (this_offset - last_offset)*1000 / cpu_khz; } return base + offset; } @@ -382,7 +390,7 @@ void main_timer_handler(struct pt_regs * } monotonic_base += - (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick; + (offset - vxtime.last) * NSEC_PER_TICK / hpet_tick; vxtime.last = offset; #ifdef CONFIG_X86_PM_TIMER @@ -391,24 +399,25 @@ #ifdef CONFIG_X86_PM_TIMER #endif } else { offset = (((tsc - vxtime.last_tsc) * - vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ); + vxtime.tsc_quot) >> US_SCALE) - USEC_PER_TICK; if (offset < 0) offset = 0; - if (offset > (USEC_PER_SEC / HZ)) { - lost = offset / (USEC_PER_SEC / HZ); - offset %= (USEC_PER_SEC / HZ); + if (offset > USEC_PER_TICK) { + lost = offset / USEC_PER_TICK; + offset %= USEC_PER_TICK; } - monotonic_base += (tsc - vxtime.last_tsc)*1000000/cpu_khz ; + /* FIXME: 1000 or 1000000? */ + monotonic_base += (tsc - vxtime.last_tsc) * 1000000 / cpu_khz; vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot; if ((((tsc - vxtime.last_tsc) * - vxtime.tsc_quot) >> 32) < offset) + vxtime.tsc_quot) >> US_SCALE) < offset) vxtime.last_tsc = tsc - - (((long) offset << 32) / vxtime.tsc_quot) - 1; + (((long) offset << US_SCALE) / vxtime.tsc_quot) - 1; } if (lost > 0) { @@ -468,16 +477,15 @@ #endif } static unsigned int cyc2ns_scale __read_mostly; -#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ static inline void set_cyc2ns_scale(unsigned long cpu_khz) { - cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; + cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / cpu_khz; } static inline unsigned long long cycles_2_ns(unsigned long long cyc) { - return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; + return (cyc * cyc2ns_scale) >> NS_SCALE; } unsigned long long sched_clock(void) @@ -490,7 +498,7 @@ #if 0 Disadvantage is a small drift between CPUs in some configurations, but that should be tolerable. */ if (__vxtime.mode == VXTIME_HPET) - return (hpet_readl(HPET_COUNTER) * vxtime.quot) >> 32; + return (hpet_readl(HPET_COUNTER) * vxtime.quot) >> US_SCALE; #endif /* Could do CPU core sync here. Opteron can execute rdtsc speculatively, @@ -633,7 +641,7 @@ #endif cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new); if (!(freq->flags & CPUFREQ_CONST_LOOPS)) - vxtime.tsc_quot = (1000L << 32) / cpu_khz; + vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz; } set_cyc2ns_scale(cpu_khz_ref); @@ -789,8 +797,8 @@ static int hpet_timer_stop_set_go(unsign if (hpet_use_timer) { hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL | HPET_TN_32BIT, HPET_T0_CFG); - hpet_writel(hpet_tick, HPET_T0_CMP); - hpet_writel(hpet_tick, HPET_T0_CMP); /* AK: why twice? */ + hpet_writel(hpet_tick, HPET_T0_CMP); /* next interrupt */ + hpet_writel(hpet_tick, HPET_T0_CMP); /* period */ cfg |= HPET_CFG_LEGACY; } /* @@ -825,8 +833,7 @@ static int hpet_init(void) if (hpet_period < 100000 || hpet_period > 100000000) return -1; - hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) / - hpet_period; + hpet_tick = (FSEC_PER_TICK + hpet_period / 2) / hpet_period; hpet_use_timer = (id & HPET_ID_LEGSUP); @@ -890,18 +897,6 @@ void __init time_init(void) char *timename; char *gtod; -#ifdef HPET_HACK_ENABLE_DANGEROUS - if (!vxtime.hpet_address) { - printk(KERN_WARNING "time.c: WARNING: Enabling HPET base " - "manually!\n"); - outl(0x800038a0, 0xcf8); - outl(0xff000001, 0xcfc); - outl(0x800038a0, 0xcf8); - vxtime.hpet_address = inl(0xcfc) & 0xfffffffe; - printk(KERN_WARNING "time.c: WARNING: Enabled HPET " - "at %#lx.\n", vxtime.hpet_address); - } -#endif if (nohpet) vxtime.hpet_address = 0; @@ -912,7 +907,7 @@ #endif -xtime.tv_sec, -xtime.tv_nsec); if (!hpet_init()) - vxtime_hz = (1000000000000000L + hpet_period / 2) / hpet_period; + vxtime_hz = (FSEC_PER_SEC + hpet_period / 2) / hpet_period; else vxtime.hpet_address = 0; @@ -941,8 +936,8 @@ #endif vxtime_hz / 1000000, vxtime_hz % 1000000, timename, gtod); printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); - vxtime.quot = (1000000L << 32) / vxtime_hz; - vxtime.tsc_quot = (1000L << 32) / cpu_khz; + vxtime.quot = (USEC_PER_SEC << US_SCALE) / vxtime_hz; + vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz; vxtime.last_tsc = get_cycles_sync(); setup_irq(0, &irq0); @@ -956,10 +951,10 @@ #endif __cpuinit int unsynchronized_tsc(void) { #ifdef CONFIG_SMP - if (oem_force_hpet_timer()) + if (apic_is_clustered_box()) return 1; /* Intel systems are normally all synchronized. Exceptions - are handled in the OEM check above. */ + are handled in the check above. */ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) return 0; #endif diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index cea335e..3d11a2f 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -6,8 +6,6 @@ * * Pentium III FXSR, SSE support * Gareth Hughes , May 2000 - * - * $Id: traps.c,v 1.36 2002/03/24 11:09:10 ak Exp $ */ /* @@ -31,6 +29,7 @@ #include #include #include #include +#include #include #include @@ -41,7 +40,7 @@ #include #include #include #include - +#include #include #include #include @@ -71,6 +70,7 @@ asmlinkage void machine_check(void); asmlinkage void spurious_interrupt_bug(void); ATOMIC_NOTIFIER_HEAD(die_chain); +EXPORT_SYMBOL(die_chain); int register_die_notifier(struct notifier_block *nb) { @@ -107,7 +107,8 @@ static inline void preempt_conditional_c preempt_enable_no_resched(); } -static int kstack_depth_to_print = 10; +static int kstack_depth_to_print = 12; +static int call_trace = 1; #ifdef CONFIG_KALLSYMS #include @@ -191,6 +192,25 @@ #endif return NULL; } +static int show_trace_unwind(struct unwind_frame_info *info, void *context) +{ + int i = 11, n = 0; + + while (unwind(info) == 0 && UNW_PC(info)) { + ++n; + if (i > 50) { + printk("\n "); + i = 7; + } else + i += printk(" "); + i += printk_address(UNW_PC(info)); + if (arch_unw_user_mode(info)) + break; + } + printk("\n"); + return n; +} + /* * x86-64 can have upto three kernel stacks: * process stack @@ -198,15 +218,39 @@ #endif * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack */ -void show_trace(unsigned long *stack) +void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack) { const unsigned cpu = safe_smp_processor_id(); unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; - int i; + int i = 11; unsigned used = 0; printk("\nCall Trace:"); + if (!tsk) + tsk = current; + + if (call_trace >= 0) { + int unw_ret = 0; + struct unwind_frame_info info; + + if (regs) { + if (unwind_init_frame_info(&info, tsk, regs) == 0) + unw_ret = show_trace_unwind(&info, NULL); + } else if (tsk == current) + unw_ret = unwind_init_running(&info, show_trace_unwind, NULL); + else { + if (unwind_init_blocked(&info, tsk) == 0) + unw_ret = show_trace_unwind(&info, NULL); + } + if (unw_ret > 0) { + if (call_trace > 0) + return; + printk("Legacy call trace:"); + i = 18; + } + } + #define HANDLE_STACK(cond) \ do while (cond) { \ unsigned long addr = *stack++; \ @@ -229,7 +273,7 @@ #define HANDLE_STACK(cond) \ } \ } while (0) - for(i = 11; ; ) { + for(; ; ) { const char *id; unsigned long *estack_end; estack_end = in_exception_stack(cpu, (unsigned long)stack, @@ -264,7 +308,7 @@ #undef HANDLE_STACK printk("\n"); } -void show_stack(struct task_struct *tsk, unsigned long * rsp) +static void _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long * rsp) { unsigned long *stack; int i; @@ -298,7 +342,12 @@ void show_stack(struct task_struct *tsk, printk("%016lx ", *stack++); touch_nmi_watchdog(); } - show_trace((unsigned long *)rsp); + show_trace(tsk, regs, rsp); +} + +void show_stack(struct task_struct *tsk, unsigned long * rsp) +{ + _show_stack(tsk, NULL, rsp); } /* @@ -307,7 +356,7 @@ void show_stack(struct task_struct *tsk, void dump_stack(void) { unsigned long dummy; - show_trace(&dummy); + show_trace(NULL, NULL, &dummy); } EXPORT_SYMBOL(dump_stack); @@ -334,7 +383,7 @@ void show_registers(struct pt_regs *regs if (in_kernel) { printk("Stack: "); - show_stack(NULL, (unsigned long*)rsp); + _show_stack(NULL, regs, (unsigned long*)rsp); printk("\nCode: "); if (regs->rip < PAGE_OFFSET) @@ -383,6 +432,7 @@ void out_of_line_bug(void) { BUG(); } +EXPORT_SYMBOL(out_of_line_bug); #endif static DEFINE_SPINLOCK(die_lock); @@ -1012,3 +1062,14 @@ static int __init kstack_setup(char *s) } __setup("kstack=", kstack_setup); +static int __init call_trace_setup(char *s) +{ + if (strcmp(s, "old") == 0) + call_trace = -1; + else if (strcmp(s, "both") == 0) + call_trace = 0; + else if (strcmp(s, "new") == 0) + call_trace = 1; + return 1; +} +__setup("call_trace=", call_trace_setup); diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index b81f473..1c6a5f3 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S @@ -45,6 +45,15 @@ SECTIONS RODATA +#ifdef CONFIG_STACK_UNWIND + . = ALIGN(8); + .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) { + __start_unwind = .; + *(.eh_frame) + __end_unwind = .; + } +#endif + /* Data */ .data : AT(ADDR(.data) - LOAD_OFFSET) { *(.data) @@ -131,6 +140,26 @@ #undef VVIRT *(.data.page_aligned) } + /* might get freed after init */ + . = ALIGN(4096); + __smp_alt_begin = .; + __smp_alt_instructions = .; + .smp_altinstructions : AT(ADDR(.smp_altinstructions) - LOAD_OFFSET) { + *(.smp_altinstructions) + } + __smp_alt_instructions_end = .; + . = ALIGN(8); + __smp_locks = .; + .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { + *(.smp_locks) + } + __smp_locks_end = .; + .smp_altinstr_replacement : AT(ADDR(.smp_altinstr_replacement) - LOAD_OFFSET) { + *(.smp_altinstr_replacement) + } + . = ALIGN(4096); + __smp_alt_end = .; + . = ALIGN(4096); /* Init code and data */ __init_begin = .; .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c index 9468fb2..f603037 100644 --- a/arch/x86_64/kernel/vsyscall.c +++ b/arch/x86_64/kernel/vsyscall.c @@ -107,7 +107,7 @@ static __always_inline long time_syscall int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz) { - if (unlikely(!__sysctl_vsyscall)) + if (!__sysctl_vsyscall) return gettimeofday(tv,tz); if (tv) do_vgettimeofday(tv); @@ -120,7 +120,7 @@ int __vsyscall(0) vgettimeofday(struct t * unlikely */ time_t __vsyscall(1) vtime(time_t *t) { - if (unlikely(!__sysctl_vsyscall)) + if (!__sysctl_vsyscall) return time_syscall(t); else if (t) *t = __xtime.tv_sec; diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index 1def21c..370952c 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c @@ -1,66 +1,21 @@ +/* Exports for assembly files. + All C exports should go in the respective C files. */ + #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include #include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include - -extern spinlock_t rtc_lock; -#ifdef CONFIG_SMP -extern void __write_lock_failed(rwlock_t *rw); -extern void __read_lock_failed(rwlock_t *rw); -#endif - -/* platform dependent support */ -EXPORT_SYMBOL(boot_cpu_data); -//EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(__ioremap); -EXPORT_SYMBOL(ioremap_nocache); -EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(pm_idle); -EXPORT_SYMBOL(pm_power_off); EXPORT_SYMBOL(__down_failed); EXPORT_SYMBOL(__down_failed_interruptible); EXPORT_SYMBOL(__down_failed_trylock); EXPORT_SYMBOL(__up_wakeup); -/* Networking helper routines. */ -EXPORT_SYMBOL(csum_partial_copy_nocheck); -EXPORT_SYMBOL(ip_compute_csum); -/* Delay loops */ -EXPORT_SYMBOL(__udelay); -EXPORT_SYMBOL(__ndelay); -EXPORT_SYMBOL(__delay); -EXPORT_SYMBOL(__const_udelay); EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); @@ -71,42 +26,20 @@ EXPORT_SYMBOL(__put_user_2); EXPORT_SYMBOL(__put_user_4); EXPORT_SYMBOL(__put_user_8); -EXPORT_SYMBOL(strncpy_from_user); -EXPORT_SYMBOL(__strncpy_from_user); -EXPORT_SYMBOL(clear_user); -EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(copy_user_generic); EXPORT_SYMBOL(copy_from_user); EXPORT_SYMBOL(copy_to_user); -EXPORT_SYMBOL(copy_in_user); -EXPORT_SYMBOL(strnlen_user); - -#ifdef CONFIG_PCI -EXPORT_SYMBOL(pci_mem_start); -#endif EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(clear_page); -EXPORT_SYMBOL(_cpu_pda); #ifdef CONFIG_SMP -EXPORT_SYMBOL(cpu_data); +extern void FASTCALL( __write_lock_failed(rwlock_t *rw)); +extern void FASTCALL( __read_lock_failed(rwlock_t *rw)); EXPORT_SYMBOL(__write_lock_failed); EXPORT_SYMBOL(__read_lock_failed); - -EXPORT_SYMBOL(smp_call_function); -EXPORT_SYMBOL(cpu_callout_map); -#endif - -#ifdef CONFIG_VT -EXPORT_SYMBOL(screen_info); #endif -EXPORT_SYMBOL(rtc_lock); - -EXPORT_SYMBOL_GPL(set_nmi_callback); -EXPORT_SYMBOL_GPL(unset_nmi_callback); - /* Export string functions. We normally rely on gcc builtin for most of these, but gcc sometimes decides not to inline them. */ #undef memcpy @@ -114,51 +47,14 @@ #undef memset #undef memmove extern void * memset(void *,int,__kernel_size_t); -extern size_t strlen(const char *); -extern void * memmove(void * dest,const void *src,size_t count); extern void * memcpy(void *,const void *,__kernel_size_t); extern void * __memcpy(void *,const void *,__kernel_size_t); EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(__memcpy); -#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM -/* prototypes are wrong, these are assembly with custom calling functions */ -extern void rwsem_down_read_failed_thunk(void); -extern void rwsem_wake_thunk(void); -extern void rwsem_downgrade_thunk(void); -extern void rwsem_down_write_failed_thunk(void); -EXPORT_SYMBOL(rwsem_down_read_failed_thunk); -EXPORT_SYMBOL(rwsem_wake_thunk); -EXPORT_SYMBOL(rwsem_downgrade_thunk); -EXPORT_SYMBOL(rwsem_down_write_failed_thunk); -#endif - EXPORT_SYMBOL(empty_zero_page); - -EXPORT_SYMBOL(die_chain); - -#ifdef CONFIG_SMP -EXPORT_SYMBOL(cpu_sibling_map); -EXPORT_SYMBOL(smp_num_siblings); -#endif - -#ifdef CONFIG_BUG -EXPORT_SYMBOL(out_of_line_bug); -#endif - EXPORT_SYMBOL(init_level4_pgt); - -extern unsigned long __supported_pte_mask; -EXPORT_SYMBOL(__supported_pte_mask); - -#ifdef CONFIG_SMP -EXPORT_SYMBOL(flush_tlb_page); -#endif - -EXPORT_SYMBOL(cpu_khz); - EXPORT_SYMBOL(load_gs_index); diff --git a/arch/x86_64/lib/csum-partial.c b/arch/x86_64/lib/csum-partial.c index 5384e22..c493735 100644 --- a/arch/x86_64/lib/csum-partial.c +++ b/arch/x86_64/lib/csum-partial.c @@ -147,4 +147,5 @@ unsigned short ip_compute_csum(unsigned { return csum_fold(csum_partial(buff,len,0)); } +EXPORT_SYMBOL(ip_compute_csum); diff --git a/arch/x86_64/lib/csum-wrappers.c b/arch/x86_64/lib/csum-wrappers.c index 94323f2..b1320ec 100644 --- a/arch/x86_64/lib/csum-wrappers.c +++ b/arch/x86_64/lib/csum-wrappers.c @@ -109,6 +109,7 @@ csum_partial_copy_nocheck(const unsigned { return csum_partial_copy_generic(src,dst,len,sum,NULL,NULL); } +EXPORT_SYMBOL(csum_partial_copy_nocheck); unsigned short csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len, unsigned short proto, unsigned int sum) diff --git a/arch/x86_64/lib/delay.c b/arch/x86_64/lib/delay.c index 03c460c..b6cd3cc 100644 --- a/arch/x86_64/lib/delay.c +++ b/arch/x86_64/lib/delay.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -36,18 +37,22 @@ void __delay(unsigned long loops) } while((now-bclock) < loops); } +EXPORT_SYMBOL(__delay); inline void __const_udelay(unsigned long xloops) { __delay((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32); } +EXPORT_SYMBOL(__const_udelay); void __udelay(unsigned long usecs) { __const_udelay(usecs * 0x000010c6); /* 2**32 / 1000000 */ } +EXPORT_SYMBOL(__udelay); void __ndelay(unsigned long nsecs) { __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */ } +EXPORT_SYMBOL(__ndelay); diff --git a/arch/x86_64/lib/memmove.c b/arch/x86_64/lib/memmove.c index e93d525..751ebae 100644 --- a/arch/x86_64/lib/memmove.c +++ b/arch/x86_64/lib/memmove.c @@ -3,12 +3,13 @@ */ #define _STRING_C #include +#include #undef memmove void *memmove(void * dest,const void *src,size_t count) { if (dest < src) { - __inline_memcpy(dest,src,count); + return memcpy(dest,src,count); } else { char *p = (char *) dest + count; char *s = (char *) src + count; @@ -17,3 +18,4 @@ void *memmove(void * dest,const void *sr } return dest; } +EXPORT_SYMBOL(memmove); diff --git a/arch/x86_64/lib/usercopy.c b/arch/x86_64/lib/usercopy.c index 9bc2c29..893d43f 100644 --- a/arch/x86_64/lib/usercopy.c +++ b/arch/x86_64/lib/usercopy.c @@ -5,6 +5,7 @@ * Copyright 1997 Linus Torvalds * Copyright 2002 Andi Kleen */ +#include #include /* @@ -47,15 +48,17 @@ __strncpy_from_user(char *dst, const cha __do_strncpy_from_user(dst, src, count, res); return res; } +EXPORT_SYMBOL(__strncpy_from_user); long strncpy_from_user(char *dst, const char __user *src, long count) { long res = -EFAULT; if (access_ok(VERIFY_READ, src, 1)) - __do_strncpy_from_user(dst, src, count, res); + return __strncpy_from_user(dst, src, count); return res; } +EXPORT_SYMBOL(strncpy_from_user); /* * Zero Userspace @@ -94,7 +97,7 @@ unsigned long __clear_user(void __user * [zero] "r" (0UL), [eight] "r" (8UL)); return size; } - +EXPORT_SYMBOL(__clear_user); unsigned long clear_user(void __user *to, unsigned long n) { @@ -102,6 +105,7 @@ unsigned long clear_user(void __user *to return __clear_user(to, n); return n; } +EXPORT_SYMBOL(clear_user); /* * Return the size of a string (including the ending 0) @@ -125,6 +129,7 @@ long __strnlen_user(const char __user *s s++; } } +EXPORT_SYMBOL(__strnlen_user); long strnlen_user(const char __user *s, long n) { @@ -132,6 +137,7 @@ long strnlen_user(const char __user *s, return 0; return __strnlen_user(s, n); } +EXPORT_SYMBOL(strnlen_user); long strlen_user(const char __user *s) { @@ -147,6 +153,7 @@ long strlen_user(const char __user *s) s++; } } +EXPORT_SYMBOL(strlen_user); unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len) { @@ -155,3 +162,5 @@ unsigned long copy_in_user(void __user * } return len; } +EXPORT_SYMBOL(copy_in_user); + diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 5525059..08dc696 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c @@ -41,6 +41,41 @@ #define PF_USER (1<<2) #define PF_RSVD (1<<3) #define PF_INSTR (1<<4) +#ifdef CONFIG_KPROBES +ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); + +/* Hook to register for page fault notifications */ +int register_page_fault_notifier(struct notifier_block *nb) +{ + vmalloc_sync_all(); + return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); +} + +int unregister_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); +} + +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + struct die_args args = { + .regs = regs, + .str = str, + .err = err, + .trapnr = trap, + .signr = sig + }; + return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); +} +#else +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + return NOTIFY_DONE; +} +#endif + void bust_spinlocks(int yes) { int loglevel_save = console_loglevel; @@ -160,7 +195,7 @@ void dump_pagetable(unsigned long addres printk("PGD %lx ", pgd_val(*pgd)); if (!pgd_present(*pgd)) goto ret; - pud = __pud_offset_k((pud_t *)pgd_page(*pgd), address); + pud = pud_offset(pgd, address); if (bad_address(pud)) goto bad; printk("PUD %lx ", pud_val(*pud)); if (!pud_present(*pud)) goto ret; @@ -348,7 +383,7 @@ asmlinkage void __kprobes do_page_fault( if (vmalloc_fault(address) >= 0) return; } - if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, + if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, SIGSEGV) == NOTIFY_STOP) return; /* @@ -358,7 +393,7 @@ asmlinkage void __kprobes do_page_fault( goto bad_area_nosemaphore; } - if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, + if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, SIGSEGV) == NOTIFY_STOP) return; @@ -410,8 +445,10 @@ asmlinkage void __kprobes do_page_fault( if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; if (error_code & 4) { - // XXX: align red zone size with ABI - if (address + 128 < regs->rsp) + /* Allow userspace just enough access below the stack pointer + * to let the 'enter' instruction work. + */ + if (address + 65536 + 32 * sizeof(unsigned long) < regs->rsp) goto bad_area; } if (expand_stack(vma, address)) diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index 4ba34e9..02add1d 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -41,8 +41,6 @@ #include #include #include #include -#include -#include #ifndef Dprintk #define Dprintk(x...) @@ -90,8 +88,6 @@ void show_mem(void) printk(KERN_INFO "%lu pages swap cached\n",cached); } -/* References to section boundaries */ - int after_bootmem; static __init void *spp_getpage(void) @@ -261,9 +257,10 @@ phys_pmd_init(pmd_t *pmd, unsigned long for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) { unsigned long entry; - if (address > end) { - for (; i < PTRS_PER_PMD; i++, pmd++) - set_pmd(pmd, __pmd(0)); + if (address >= end) { + if (!after_bootmem) + for (; i < PTRS_PER_PMD; i++, pmd++) + set_pmd(pmd, __pmd(0)); break; } entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address; @@ -341,7 +338,8 @@ static void __init find_early_table_spac table_end = table_start; early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n", - end, table_start << PAGE_SHIFT, table_end << PAGE_SHIFT); + end, table_start << PAGE_SHIFT, + (table_start << PAGE_SHIFT) + tables); } /* Setup the direct mapping of the physical memory at PAGE_OFFSET. @@ -372,7 +370,7 @@ void __meminit init_memory_mapping(unsig pud_t *pud; if (after_bootmem) - pud = pud_offset_k(pgd, start & PGDIR_MASK); + pud = pud_offset(pgd, start & PGDIR_MASK); else pud = alloc_low_page(&map, &pud_phys); @@ -587,10 +585,7 @@ void __init mem_init(void) { long codesize, reservedpages, datasize, initsize; -#ifdef CONFIG_SWIOTLB - pci_swiotlb_init(); -#endif - no_iommu_init(); + pci_iommu_alloc(); /* How many end-of-memory variables you have, grandma! */ max_low_pfn = end_pfn; @@ -644,20 +639,29 @@ #ifdef CONFIG_SMP #endif } -void free_initmem(void) +void free_init_pages(char *what, unsigned long begin, unsigned long end) { unsigned long addr; - addr = (unsigned long)(&__init_begin); - for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { + if (begin >= end) + return; + + printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10); + for (addr = begin; addr < end; addr += PAGE_SIZE) { ClearPageReserved(virt_to_page(addr)); init_page_count(virt_to_page(addr)); memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE); free_page(addr); totalram_pages++; } +} + +void free_initmem(void) +{ memset(__initdata_begin, 0xba, __initdata_end - __initdata_begin); - printk ("Freeing unused kernel memory: %luk freed\n", (__init_end - __init_begin) >> 10); + free_init_pages("unused kernel memory", + (unsigned long)(&__init_begin), + (unsigned long)(&__init_end)); } #ifdef CONFIG_DEBUG_RODATA @@ -686,15 +690,7 @@ #endif #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { - if (start >= end) - return; - printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(virt_to_page(start)); - init_page_count(virt_to_page(start)); - free_page(start); - totalram_pages++; - } + free_init_pages("initrd memory", start, end); } #endif diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c index ae20706..45d7d82 100644 --- a/arch/x86_64/mm/ioremap.c +++ b/arch/x86_64/mm/ioremap.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -219,6 +220,7 @@ #endif } return (__force void __iomem *) (offset + (char *)addr); } +EXPORT_SYMBOL(__ioremap); /** * ioremap_nocache - map bus memory into CPU space @@ -246,6 +248,7 @@ void __iomem *ioremap_nocache (unsigned { return __ioremap(phys_addr, size, _PAGE_PCD); } +EXPORT_SYMBOL(ioremap_nocache); /** * iounmap - Free a IO remapping @@ -291,3 +294,5 @@ void iounmap(volatile void __iomem *addr BUG_ON(p != o || o == NULL); kfree(p); } +EXPORT_SYMBOL(iounmap); + diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 474df22..502fce6 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c @@ -30,7 +30,6 @@ #endif static struct acpi_table_slit *acpi_slit; static nodemask_t nodes_parsed __initdata; -static nodemask_t nodes_found __initdata; static struct bootnode nodes[MAX_NUMNODES] __initdata; static struct bootnode nodes_add[MAX_NUMNODES] __initdata; static int found_add_area __initdata; @@ -38,33 +37,14 @@ int hotadd_percent __initdata = 0; #ifndef RESERVE_HOTADD #define hotadd_percent 0 /* Ignore all settings */ #endif -static u8 pxm2node[256] = { [0 ... 255] = 0xff }; /* Too small nodes confuse the VM badly. Usually they result from BIOS bugs. */ #define NODE_MIN_SIZE (4*1024*1024) -static int node_to_pxm(int n); - -int pxm_to_node(int pxm) -{ - if ((unsigned)pxm >= 256) - return -1; - /* Extend 0xff to (int)-1 */ - return (signed char)pxm2node[pxm]; -} - static __init int setup_node(int pxm) { - unsigned node = pxm2node[pxm]; - if (node == 0xff) { - if (nodes_weight(nodes_found) >= MAX_NUMNODES) - return -1; - node = first_unset_node(nodes_found); - node_set(node, nodes_found); - pxm2node[pxm] = node; - } - return pxm2node[pxm]; + return acpi_map_pxm_to_node(pxm); } static __init int conflicting_nodes(unsigned long start, unsigned long end) @@ -440,17 +420,6 @@ int __init acpi_scan_nodes(unsigned long return 0; } -static int node_to_pxm(int n) -{ - int i; - if (pxm2node[n] == n) - return n; - for (i = 0; i < 256; i++) - if (pxm2node[i] == n) - return i; - return 0; -} - void __init srat_reserve_add_area(int nodeid) { if (found_add_area && nodes_add[nodeid].end) { diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c index 3acf60d..b50a7c7 100644 --- a/arch/x86_64/pci/k8-bus.c +++ b/arch/x86_64/pci/k8-bus.c @@ -2,6 +2,7 @@ #include #include #include #include +#include /* * This discovers the pcibus <-> node mapping on AMD K8. @@ -18,7 +19,6 @@ #define LDT_BUS_NUMBER_REGISTER_2 0xD4 #define NR_LDT_BUS_NUMBER_REGISTERS 3 #define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF) #define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF) -#define PCI_DEVICE_ID_K8HTCONFIG 0x1100 /** * fill_mp_bus_to_cpumask() @@ -28,8 +28,7 @@ #define PCI_DEVICE_ID_K8HTCONFIG 0x1100 __init static int fill_mp_bus_to_cpumask(void) { - struct pci_dev *nb_dev = NULL; - int i, j; + int i, j, k; u32 ldtbus, nid; static int lbnr[3] = { LDT_BUS_NUMBER_REGISTER_0, @@ -37,8 +36,9 @@ fill_mp_bus_to_cpumask(void) LDT_BUS_NUMBER_REGISTER_2 }; - while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) { + cache_k8_northbridges(); + for (k = 0; k < num_k8_northbridges; k++) { + struct pci_dev *nb_dev = k8_northbridges[k]; pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid); for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) { diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index a2060e4..3c55c76 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c @@ -13,7 +13,10 @@ #include #include "pci.h" -#define MMCONFIG_APER_SIZE (256*1024*1024) +/* aperture is up to 256MB but BIOS may reserve less */ +#define MMCONFIG_APER_MIN (2 * 1024*1024) +#define MMCONFIG_APER_MAX (256 * 1024*1024) + /* Verify the first 16 busses. We assume that systems with more busses get MCFG right. */ #define MAX_CHECK_BUS 16 @@ -175,9 +178,10 @@ void __init pci_mmcfg_init(void) return; if (!e820_all_mapped(pci_mmcfg_config[0].base_address, - pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, E820_RESERVED)) { - printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", + pci_mmcfg_config[0].base_address); printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); return; } @@ -190,7 +194,8 @@ void __init pci_mmcfg_init(void) } for (i = 0; i < pci_mmcfg_config_num; ++i) { pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; - pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE); + pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, + MMCONFIG_APER_MAX); if (!pci_mmcfg_virt[i].virt) { printk("PCI: Cannot map mmconfig aperture for segment %d\n", pci_mmcfg_config[i].pci_segment_group_number); diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index dbeb350..848f173 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -34,10 +34,6 @@ config GENERIC_HARDIRQS bool default y -config RWSEM_GENERIC_SPINLOCK - bool - default y - source "init/Kconfig" menu "Processor type and features" diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile index 98fac84..3a3a4c6 100644 --- a/arch/xtensa/Makefile +++ b/arch/xtensa/Makefile @@ -71,7 +71,7 @@ archprepare: $(archinc)/.platform # Update machine cpu and platform symlinks if something which affects # them changed. -$(archinc)/.platform: $(wildcard include/config/arch/*.h) include/config/MARKER +$(archinc)/.platform: $(wildcard include/config/arch/*.h) include/config/auto.conf @echo ' SYMLINK $(archinc)/xtensa/config -> $(archinc)/xtensa/config-$(CPU)' $(Q)mkdir -p $(archinc) $(Q)mkdir -p $(archinc)/xtensa diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile index 9e73bb8..d3d2aa2 100644 --- a/arch/xtensa/boot/lib/Makefile +++ b/arch/xtensa/boot/lib/Makefile @@ -2,7 +2,7 @@ # # Makefile for some libs needed by zImage. # -zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c +zlib := inffast.c inflate.c inftrees.c lib-y += $(zlib:.c=.o) zmem.o diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 5c018c5..89e409e 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1102,7 +1102,7 @@ ENTRY(fast_syscall_sysxtensa) s32i a7, a2, PT_AREG7 movi a7, 4 # sizeof(unsigned int) - verify_area a3, a7, a0, a2, .Leac + access_ok a0, a3, a7, a2, .Leac _beqi a6, SYSXTENSA_ATOMIC_SET, .Lset _beqi a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index de19501..c6f471b 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -350,17 +350,6 @@ __pci_mmap_make_offset(struct pci_dev *d } /* - * Set vm_flags of VMA, as appropriate for this architecture, for a pci device - * mapping. - */ -static __inline__ void -__pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state) -{ - vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO; -} - -/* * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci * device mapping. */ @@ -399,7 +388,6 @@ int pci_mmap_page_range(struct pci_dev * if (ret < 0) return ret; - __pci_mmap_set_flags(dev, vma, mmap_state); __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine); ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index e252b61..c494f08 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -104,7 +104,7 @@ sys_sigaction(int sig, const struct old_ if (act) { old_sigset_t mask; - if (verify_area(VERIFY_READ, act, sizeof(*act)) || + if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) return -EFAULT; @@ -116,7 +116,7 @@ sys_sigaction(int sig, const struct old_ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) return -EFAULT; @@ -236,7 +236,7 @@ #undef COPY err |= __copy_from_user (regs->areg, sc->sc_areg, XCHAL_NUM_AREGS*4); err |= __get_user(buf, &sc->sc_cpstate); if (buf) { - if (verify_area(VERIFY_READ, buf, sizeof(*buf))) + if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) goto badframe; err |= restore_cpextra(buf); } @@ -357,7 +357,7 @@ asmlinkage int sys_sigreturn(struct pt_r if (regs->depc > 64) panic ("Double exception sys_sigreturn\n"); - if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__get_user(set.sig[0], &frame->sc.oldmask) @@ -394,7 +394,7 @@ asmlinkage int sys_rt_sigreturn(struct p return 0; } - if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) @@ -433,7 +433,7 @@ badframe: static inline void * get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) { - if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; return (void *)((sp - frame_size) & -16ul); diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index f3b7753..48d090e 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched @@ -40,7 +40,7 @@ config IOSCHED_CFQ choice prompt "Default I/O scheduler" - default DEFAULT_AS + default DEFAULT_CFQ help Select the I/O scheduler which will be used by default for all block devices. diff --git a/block/as-iosched.c b/block/as-iosched.c index a7caf35..3af31ed 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -96,7 +96,7 @@ struct as_data { struct as_rq *next_arq[2]; /* next in sort order */ sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */ - struct list_head *hash; /* request hash */ + struct hlist_head *hash; /* request hash */ unsigned long exit_prob; /* probability a task will exit while being waited on */ @@ -165,8 +165,7 @@ struct as_rq { /* * request hash, key is the ending offset (for back merge lookup) */ - struct list_head hash; - unsigned int on_hash; + struct hlist_node hash; /* * expire fifo @@ -282,17 +281,15 @@ #define AS_HASH_BLOCK(sec) ((sec) >> 3) #define AS_HASH_FN(sec) (hash_long(AS_HASH_BLOCK((sec)), as_hash_shift)) #define AS_HASH_ENTRIES (1 << as_hash_shift) #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) -#define list_entry_hash(ptr) list_entry((ptr), struct as_rq, hash) static inline void __as_del_arq_hash(struct as_rq *arq) { - arq->on_hash = 0; - list_del_init(&arq->hash); + hlist_del_init(&arq->hash); } static inline void as_del_arq_hash(struct as_rq *arq) { - if (arq->on_hash) + if (!hlist_unhashed(&arq->hash)) __as_del_arq_hash(arq); } @@ -300,10 +297,9 @@ static void as_add_arq_hash(struct as_da { struct request *rq = arq->request; - BUG_ON(arq->on_hash); + BUG_ON(!hlist_unhashed(&arq->hash)); - arq->on_hash = 1; - list_add(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]); + hlist_add_head(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]); } /* @@ -312,31 +308,29 @@ static void as_add_arq_hash(struct as_da static inline void as_hot_arq_hash(struct as_data *ad, struct as_rq *arq) { struct request *rq = arq->request; - struct list_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))]; + struct hlist_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))]; - if (!arq->on_hash) { + if (hlist_unhashed(&arq->hash)) { WARN_ON(1); return; } - if (arq->hash.prev != head) { - list_del(&arq->hash); - list_add(&arq->hash, head); + if (&arq->hash != head->first) { + hlist_del(&arq->hash); + hlist_add_head(&arq->hash, head); } } static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset) { - struct list_head *hash_list = &ad->hash[AS_HASH_FN(offset)]; - struct list_head *entry, *next = hash_list->next; + struct hlist_head *hash_list = &ad->hash[AS_HASH_FN(offset)]; + struct hlist_node *entry, *next; + struct as_rq *arq; - while ((entry = next) != hash_list) { - struct as_rq *arq = list_entry_hash(entry); + hlist_for_each_entry_safe(arq, entry, next, hash_list, hash) { struct request *__rq = arq->request; - next = entry->next; - - BUG_ON(!arq->on_hash); + BUG_ON(hlist_unhashed(&arq->hash)); if (!rq_mergeable(__rq)) { as_del_arq_hash(arq); @@ -353,10 +347,6 @@ static struct request *as_find_arq_hash( /* * rb tree support functions */ -#define RB_NONE (2) -#define RB_EMPTY(root) ((root)->rb_node == NULL) -#define ON_RB(node) ((node)->rb_color != RB_NONE) -#define RB_CLEAR(node) ((node)->rb_color = RB_NONE) #define rb_entry_arq(node) rb_entry((node), struct as_rq, rb_node) #define ARQ_RB_ROOT(ad, arq) (&(ad)->sort_list[(arq)->is_sync]) #define rq_rb_key(rq) (rq)->sector @@ -425,13 +415,13 @@ static void as_add_arq_rb(struct as_data static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq) { - if (!ON_RB(&arq->rb_node)) { + if (!RB_EMPTY_NODE(&arq->rb_node)) { WARN_ON(1); return; } rb_erase(&arq->rb_node, ARQ_RB_ROOT(ad, arq)); - RB_CLEAR(&arq->rb_node); + RB_CLEAR_NODE(&arq->rb_node); } static struct request * @@ -552,7 +542,7 @@ static struct as_rq *as_find_next_arq(st struct rb_node *rbprev = rb_prev(&last->rb_node); struct as_rq *arq_next, *arq_prev; - BUG_ON(!ON_RB(&last->rb_node)); + BUG_ON(!RB_EMPTY_NODE(&last->rb_node)); if (rbprev) arq_prev = rb_entry_arq(rbprev); @@ -902,7 +892,7 @@ static int as_can_break_anticipation(str } /* - * as_can_anticipate indicates weather we should either run arq + * as_can_anticipate indicates whether we should either run arq * or keep anticipating a better request. */ static int as_can_anticipate(struct as_data *ad, struct as_rq *arq) @@ -1129,7 +1119,7 @@ static void as_move_to_dispatch(struct a struct request *rq = arq->request; const int data_dir = arq->is_sync; - BUG_ON(!ON_RB(&arq->rb_node)); + BUG_ON(!RB_EMPTY_NODE(&arq->rb_node)); as_antic_stop(ad); ad->antic_status = ANTIC_OFF; @@ -1254,7 +1244,7 @@ static int as_dispatch_request(request_q */ if (reads) { - BUG_ON(RB_EMPTY(&ad->sort_list[REQ_SYNC])); + BUG_ON(RB_EMPTY_ROOT(&ad->sort_list[REQ_SYNC])); if (writes && ad->batch_data_dir == REQ_SYNC) /* @@ -1278,7 +1268,7 @@ static int as_dispatch_request(request_q if (writes) { dispatch_writes: - BUG_ON(RB_EMPTY(&ad->sort_list[REQ_ASYNC])); + BUG_ON(RB_EMPTY_ROOT(&ad->sort_list[REQ_ASYNC])); if (ad->batch_data_dir == REQ_SYNC) { ad->changed_batch = 1; @@ -1346,7 +1336,7 @@ static void as_add_request(request_queue arq->state = AS_RQ_NEW; if (rq_data_dir(arq->request) == READ - || current->flags&PF_SYNCWRITE) + || (arq->request->flags & REQ_RW_SYNC)) arq->is_sync = 1; else arq->is_sync = 0; @@ -1598,12 +1588,11 @@ static int as_set_request(request_queue_ if (arq) { memset(arq, 0, sizeof(*arq)); - RB_CLEAR(&arq->rb_node); + RB_CLEAR_NODE(&arq->rb_node); arq->request = rq; arq->state = AS_RQ_PRESCHED; arq->io_context = NULL; - INIT_LIST_HEAD(&arq->hash); - arq->on_hash = 0; + INIT_HLIST_NODE(&arq->hash); INIT_LIST_HEAD(&arq->fifo); rq->elevator_private = arq; return 0; @@ -1663,7 +1652,7 @@ static void *as_init_queue(request_queue ad->q = q; /* Identify what queue the data belongs to */ - ad->hash = kmalloc_node(sizeof(struct list_head)*AS_HASH_ENTRIES, + ad->hash = kmalloc_node(sizeof(struct hlist_head)*AS_HASH_ENTRIES, GFP_KERNEL, q->node); if (!ad->hash) { kfree(ad); @@ -1685,7 +1674,7 @@ static void *as_init_queue(request_queue INIT_WORK(&ad->antic_work, as_work_handler, q); for (i = 0; i < AS_HASH_ENTRIES; i++) - INIT_LIST_HEAD(&ad->hash[i]); + INIT_HLIST_HEAD(&ad->hash[i]); INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]); INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 052b174..e25223e 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -26,7 +26,7 @@ static const int cfq_back_penalty = 2; static const int cfq_slice_sync = HZ / 10; static int cfq_slice_async = HZ / 25; static const int cfq_slice_async_rq = 2; -static int cfq_slice_idle = HZ / 70; +static int cfq_slice_idle = HZ / 125; #define CFQ_IDLE_GRACE (HZ / 10) #define CFQ_SLICE_SCALE (5) @@ -60,16 +60,6 @@ #define RQ_DATA(rq) (rq)->elevator_priv /* * rb-tree defines */ -#define RB_NONE (2) -#define RB_EMPTY(node) ((node)->rb_node == NULL) -#define RB_CLEAR_COLOR(node) (node)->rb_color = RB_NONE -#define RB_CLEAR(node) do { \ - (node)->rb_parent = NULL; \ - RB_CLEAR_COLOR((node)); \ - (node)->rb_right = NULL; \ - (node)->rb_left = NULL; \ -} while (0) -#define RB_CLEAR_ROOT(root) ((root)->rb_node = NULL) #define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node) #define rq_rb_key(rq) (rq)->sector @@ -128,8 +118,6 @@ struct cfq_data { */ struct hlist_head *crq_hash; - unsigned int max_queued; - mempool_t *crq_pool; int rq_in_driver; @@ -284,8 +272,6 @@ static struct cfq_queue *cfq_find_cfq_ha static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *); static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk, gfp_t gfp_mask); -#define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE) - /* * lots of deadline iosched dupes, can be abstracted later... */ @@ -341,7 +327,7 @@ static int cfq_queue_empty(request_queue static inline pid_t cfq_queue_pid(struct task_struct *task, int rw) { - if (rw == READ || process_sync(task)) + if (rw == READ || rw == WRITE_SYNC) return task->pid; return CFQ_KEY_ASYNC; @@ -567,9 +553,8 @@ static inline void cfq_del_crq_rb(struct cfq_update_next_crq(crq); rb_erase(&crq->rb_node, &cfqq->sort_list); - RB_CLEAR_COLOR(&crq->rb_node); - if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list)) + if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list)) cfq_del_cfqq_rr(cfqd, cfqq); } @@ -916,13 +901,15 @@ static struct cfq_queue *cfq_set_active_ return cfqq; } +#define CIC_SEEKY(cic) ((cic)->seek_mean > (128 * 1024)) + static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) { struct cfq_io_context *cic; unsigned long sl; - WARN_ON(!RB_EMPTY(&cfqq->sort_list)); + WARN_ON(!RB_EMPTY_ROOT(&cfqq->sort_list)); WARN_ON(cfqq != cfqd->active_queue); /* @@ -949,7 +936,7 @@ static int cfq_arm_slice_timer(struct cf * fair distribution of slice time for a process doing back-to-back * seeks. so allow a little bit of time for him to submit a new rq */ - if (sample_valid(cic->seek_samples) && cic->seek_mean > 131072) + if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic)) sl = 2; mod_timer(&cfqd->idle_slice_timer, jiffies + sl); @@ -960,11 +947,15 @@ static void cfq_dispatch_insert(request_ { struct cfq_data *cfqd = q->elevator->elevator_data; struct cfq_queue *cfqq = crq->cfq_queue; + struct request *rq; cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq); cfq_remove_request(crq->request); cfqq->on_dispatch[cfq_crq_is_sync(crq)]++; elv_dispatch_sort(q, crq->request); + + rq = list_entry(q->queue_head.prev, struct request, queuelist); + cfqd->last_sector = rq->sector + rq->nr_sectors; } /* @@ -1046,10 +1037,12 @@ static struct cfq_queue *cfq_select_queu * if queue has requests, dispatch one. if not, check if * enough slice is left to wait for one */ - if (!RB_EMPTY(&cfqq->sort_list)) + if (!RB_EMPTY_ROOT(&cfqq->sort_list)) goto keep_queue; - else if (cfq_cfqq_class_sync(cfqq) && - time_before(now, cfqq->slice_end)) { + else if (cfq_cfqq_dispatched(cfqq)) { + cfqq = NULL; + goto keep_queue; + } else if (cfq_cfqq_class_sync(cfqq)) { if (cfq_arm_slice_timer(cfqd, cfqq)) return NULL; } @@ -1068,7 +1061,7 @@ __cfq_dispatch_requests(struct cfq_data { int dispatched = 0; - BUG_ON(RB_EMPTY(&cfqq->sort_list)); + BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list)); do { struct cfq_rq *crq; @@ -1092,14 +1085,13 @@ __cfq_dispatch_requests(struct cfq_data cfqd->active_cic = crq->io_context; } - if (RB_EMPTY(&cfqq->sort_list)) + if (RB_EMPTY_ROOT(&cfqq->sort_list)) break; } while (dispatched < max_dispatch); /* - * if slice end isn't set yet, set it. if at least one request was - * sync, use the sync time slice value + * if slice end isn't set yet, set it. */ if (!cfqq->slice_end) cfq_set_prio_slice(cfqd, cfqq); @@ -1110,7 +1102,8 @@ __cfq_dispatch_requests(struct cfq_data */ if ((!cfq_cfqq_sync(cfqq) && cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) || - cfq_class_idle(cfqq)) + cfq_class_idle(cfqq) || + !cfq_cfqq_idle_window(cfqq)) cfq_slice_expired(cfqd, 0); return dispatched; @@ -1119,10 +1112,11 @@ __cfq_dispatch_requests(struct cfq_data static int cfq_forced_dispatch_cfqqs(struct list_head *list) { - int dispatched = 0; struct cfq_queue *cfqq, *next; struct cfq_rq *crq; + int dispatched; + dispatched = 0; list_for_each_entry_safe(cfqq, next, list, cfq_list) { while ((crq = cfqq->next_crq)) { cfq_dispatch_insert(cfqq->cfqd->queue, crq); @@ -1130,6 +1124,7 @@ cfq_forced_dispatch_cfqqs(struct list_he } BUG_ON(!list_empty(&cfqq->fifo)); } + return dispatched; } @@ -1156,7 +1151,8 @@ static int cfq_dispatch_requests(request_queue_t *q, int force) { struct cfq_data *cfqd = q->elevator->elevator_data; - struct cfq_queue *cfqq; + struct cfq_queue *cfqq, *prev_cfqq; + int dispatched; if (!cfqd->busy_queues) return 0; @@ -1164,10 +1160,17 @@ cfq_dispatch_requests(request_queue_t *q if (unlikely(force)) return cfq_forced_dispatch(cfqd); - cfqq = cfq_select_queue(cfqd); - if (cfqq) { + dispatched = 0; + prev_cfqq = NULL; + while ((cfqq = cfq_select_queue(cfqd)) != NULL) { int max_dispatch; + /* + * Don't repeat dispatch from the previous queue. + */ + if (prev_cfqq == cfqq) + break; + cfq_clear_cfqq_must_dispatch(cfqq); cfq_clear_cfqq_wait_request(cfqq); del_timer(&cfqd->idle_slice_timer); @@ -1176,10 +1179,19 @@ cfq_dispatch_requests(request_queue_t *q if (cfq_class_idle(cfqq)) max_dispatch = 1; - return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); + dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); + + /* + * If the dispatch cfqq has idling enabled and is still + * the active queue, break out. + */ + if (cfq_cfqq_idle_window(cfqq) && cfqd->active_queue) + break; + + prev_cfqq = cfqq; } - return 0; + return dispatched; } /* @@ -1324,7 +1336,6 @@ cfq_alloc_io_context(struct cfq_data *cf if (cic) { memset(cic, 0, sizeof(*cic)); - RB_CLEAR_COLOR(&cic->rb_node); cic->last_end_request = jiffies; INIT_LIST_HEAD(&cic->queue_list); cic->dtor = cfq_free_io_context; @@ -1386,25 +1397,28 @@ static inline void changed_ioprio(struct { struct cfq_data *cfqd = cic->key; struct cfq_queue *cfqq; - if (cfqd) { - spin_lock(cfqd->queue->queue_lock); - cfqq = cic->cfqq[ASYNC]; - if (cfqq) { - struct cfq_queue *new_cfqq; - new_cfqq = cfq_get_queue(cfqd, CFQ_KEY_ASYNC, - cic->ioc->task, GFP_ATOMIC); - if (new_cfqq) { - cic->cfqq[ASYNC] = new_cfqq; - cfq_put_queue(cfqq); - } - } - cfqq = cic->cfqq[SYNC]; - if (cfqq) { - cfq_mark_cfqq_prio_changed(cfqq); - cfq_init_prio_data(cfqq); + + if (unlikely(!cfqd)) + return; + + spin_lock(cfqd->queue->queue_lock); + + cfqq = cic->cfqq[ASYNC]; + if (cfqq) { + struct cfq_queue *new_cfqq; + new_cfqq = cfq_get_queue(cfqd, CFQ_KEY_ASYNC, cic->ioc->task, + GFP_ATOMIC); + if (new_cfqq) { + cic->cfqq[ASYNC] = new_cfqq; + cfq_put_queue(cfqq); } - spin_unlock(cfqd->queue->queue_lock); } + + cfqq = cic->cfqq[SYNC]; + if (cfqq) + cfq_mark_cfqq_prio_changed(cfqq); + + spin_unlock(cfqd->queue->queue_lock); } /* @@ -1461,7 +1475,6 @@ retry: INIT_HLIST_NODE(&cfqq->cfq_hash); INIT_LIST_HEAD(&cfqq->cfq_list); - RB_CLEAR_ROOT(&cfqq->sort_list); INIT_LIST_HEAD(&cfqq->fifo); cfqq->key = key; @@ -1473,8 +1486,7 @@ retry: * set ->slice_left to allow preemption for a new process */ cfqq->slice_left = 2 * cfqd->cfq_slice_idle; - if (!cfqd->hw_tag) - cfq_mark_cfqq_idle_window(cfqq); + cfq_mark_cfqq_idle_window(cfqq); cfq_mark_cfqq_prio_changed(cfqq); cfq_init_prio_data(cfqq); } @@ -1665,7 +1677,8 @@ cfq_update_idle_window(struct cfq_data * { int enable_idle = cfq_cfqq_idle_window(cfqq); - if (!cic->ioc->task || !cfqd->cfq_slice_idle || cfqd->hw_tag) + if (!cic->ioc->task || !cfqd->cfq_slice_idle || + (cfqd->hw_tag && CIC_SEEKY(cic))) enable_idle = 0; else if (sample_valid(cic->ttime_samples)) { if (cic->ttime_mean > cfqd->cfq_slice_idle) @@ -1695,7 +1708,7 @@ cfq_should_preempt(struct cfq_data *cfqd return 0; if (!cfqq) - return 1; + return 0; if (cfq_class_idle(cfqq)) return 1; @@ -1727,7 +1740,7 @@ static void cfq_preempt_queue(struct cfq cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2; cfqq->slice_end = cfqq->slice_left + jiffies; - __cfq_slice_expired(cfqd, cfqq, 1); + cfq_slice_expired(cfqd, 1); __cfq_set_active_queue(cfqd, cfqq); } @@ -1752,11 +1765,7 @@ static void cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, struct cfq_rq *crq) { - struct cfq_io_context *cic; - - cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq); - - cic = crq->io_context; + struct cfq_io_context *cic = crq->io_context; /* * we never wait for an async request and we don't allow preemption @@ -1846,11 +1855,23 @@ static void cfq_completed_request(reques cfqq->service_last = now; cfq_resort_rr_list(cfqq, 0); } - cfq_schedule_dispatch(cfqd); } - if (cfq_crq_is_sync(crq)) + if (sync) crq->io_context->last_end_request = now; + + /* + * If this is the active queue, check if it needs to be expired, + * or if we want to idle in case it has no pending requests. + */ + if (cfqd->active_queue == cfqq) { + if (time_after(now, cfqq->slice_end)) + cfq_slice_expired(cfqd, 0); + else if (sync && RB_EMPTY_ROOT(&cfqq->sort_list)) { + if (!cfq_arm_slice_timer(cfqd, cfqq)) + cfq_schedule_dispatch(cfqd); + } + } } static struct request * @@ -1917,7 +1938,6 @@ static inline int __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, struct task_struct *task, int rw) { -#if 1 if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) && !cfq_cfqq_must_alloc_slice(cfqq)) { cfq_mark_cfqq_must_alloc_slice(cfqq); @@ -1925,39 +1945,6 @@ #if 1 } return ELV_MQUEUE_MAY; -#else - if (!cfqq || task->flags & PF_MEMALLOC) - return ELV_MQUEUE_MAY; - if (!cfqq->allocated[rw] || cfq_cfqq_must_alloc(cfqq)) { - if (cfq_cfqq_wait_request(cfqq)) - return ELV_MQUEUE_MUST; - - /* - * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we - * can quickly flood the queue with writes from a single task - */ - if (rw == READ || !cfq_cfqq_must_alloc_slice(cfqq)) { - cfq_mark_cfqq_must_alloc_slice(cfqq); - return ELV_MQUEUE_MUST; - } - - return ELV_MQUEUE_MAY; - } - if (cfq_class_idle(cfqq)) - return ELV_MQUEUE_NO; - if (cfqq->allocated[rw] >= cfqd->max_queued) { - struct io_context *ioc = get_io_context(GFP_ATOMIC); - int ret = ELV_MQUEUE_NO; - - if (ioc && ioc->nr_batch_requests) - ret = ELV_MQUEUE_MAY; - - put_io_context(ioc); - return ret; - } - - return ELV_MQUEUE_MAY; -#endif } static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio) @@ -1986,16 +1973,13 @@ static int cfq_may_queue(request_queue_t static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq) { struct cfq_data *cfqd = q->elevator->elevator_data; - struct request_list *rl = &q->rq; - if (cfqq->allocated[READ] <= cfqd->max_queued || cfqd->rq_starved) { + if (unlikely(cfqd->rq_starved)) { + struct request_list *rl = &q->rq; + smp_mb(); if (waitqueue_active(&rl->wait[READ])) wake_up(&rl->wait[READ]); - } - - if (cfqq->allocated[WRITE] <= cfqd->max_queued || cfqd->rq_starved) { - smp_mb(); if (waitqueue_active(&rl->wait[WRITE])) wake_up(&rl->wait[WRITE]); } @@ -2069,7 +2053,7 @@ cfq_set_request(request_queue_t *q, stru crq = mempool_alloc(cfqd->crq_pool, gfp_mask); if (crq) { - RB_CLEAR(&crq->rb_node); + RB_CLEAR_NODE(&crq->rb_node); crq->rb_key = 0; crq->request = rq; INIT_HLIST_NODE(&crq->hash); @@ -2155,16 +2139,13 @@ static void cfq_idle_slice_timer(unsigne * only expire and reinvoke request handler, if there are * other queues with pending requests */ - if (!cfqd->busy_queues) { - cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end); - add_timer(&cfqd->idle_slice_timer); + if (!cfqd->busy_queues) goto out_cont; - } /* * not expired and it has a request pending, let it dispatch */ - if (!RB_EMPTY(&cfqq->sort_list)) { + if (!RB_EMPTY_ROOT(&cfqq->sort_list)) { cfq_mark_cfqq_must_dispatch(cfqq); goto out_kick; } @@ -2285,9 +2266,6 @@ static void *cfq_init_queue(request_queu cfqd->queue = q; - cfqd->max_queued = q->nr_requests / 4; - q->nr_batching = cfq_queued; - init_timer(&cfqd->idle_slice_timer); cfqd->idle_slice_timer.function = cfq_idle_slice_timer; cfqd->idle_slice_timer.data = (unsigned long) cfqd; diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index 3bd0415..4469dd8 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -30,8 +30,7 @@ #define DL_HASH_BLOCK(sec) ((sec) >> 3) #define DL_HASH_FN(sec) (hash_long(DL_HASH_BLOCK((sec)), deadline_hash_shift)) #define DL_HASH_ENTRIES (1 << deadline_hash_shift) #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) -#define list_entry_hash(ptr) list_entry((ptr), struct deadline_rq, hash) -#define ON_HASH(drq) (drq)->on_hash +#define ON_HASH(drq) (!hlist_unhashed(&(drq)->hash)) struct deadline_data { /* @@ -48,7 +47,7 @@ struct deadline_data { * next in sort order. read, write or both are NULL */ struct deadline_rq *next_drq[2]; - struct list_head *hash; /* request hash */ + struct hlist_head *hash; /* request hash */ unsigned int batching; /* number of sequential requests made */ sector_t last_sector; /* head position */ unsigned int starved; /* times reads have starved writes */ @@ -79,8 +78,7 @@ struct deadline_rq { /* * request hash, key is the ending offset (for back merge lookup) */ - struct list_head hash; - char on_hash; + struct hlist_node hash; /* * expire fifo @@ -100,8 +98,7 @@ #define RQ_DATA(rq) ((struct deadline_rq */ static inline void __deadline_del_drq_hash(struct deadline_rq *drq) { - drq->on_hash = 0; - list_del_init(&drq->hash); + hlist_del_init(&drq->hash); } static inline void deadline_del_drq_hash(struct deadline_rq *drq) @@ -117,8 +114,7 @@ deadline_add_drq_hash(struct deadline_da BUG_ON(ON_HASH(drq)); - drq->on_hash = 1; - list_add(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]); + hlist_add_head(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]); } /* @@ -128,26 +124,24 @@ static inline void deadline_hot_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) { struct request *rq = drq->request; - struct list_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))]; + struct hlist_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))]; - if (ON_HASH(drq) && drq->hash.prev != head) { - list_del(&drq->hash); - list_add(&drq->hash, head); + if (ON_HASH(drq) && &drq->hash != head->first) { + hlist_del(&drq->hash); + hlist_add_head(&drq->hash, head); } } static struct request * deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) { - struct list_head *hash_list = &dd->hash[DL_HASH_FN(offset)]; - struct list_head *entry, *next = hash_list->next; + struct hlist_head *hash_list = &dd->hash[DL_HASH_FN(offset)]; + struct hlist_node *entry, *next; + struct deadline_rq *drq; - while ((entry = next) != hash_list) { - struct deadline_rq *drq = list_entry_hash(entry); + hlist_for_each_entry_safe(drq, entry, next, hash_list, hash) { struct request *__rq = drq->request; - next = entry->next; - BUG_ON(!ON_HASH(drq)); if (!rq_mergeable(__rq)) { @@ -165,10 +159,6 @@ deadline_find_drq_hash(struct deadline_d /* * rb tree support functions */ -#define RB_NONE (2) -#define RB_EMPTY(root) ((root)->rb_node == NULL) -#define ON_RB(node) ((node)->rb_color != RB_NONE) -#define RB_CLEAR(node) ((node)->rb_color = RB_NONE) #define rb_entry_drq(node) rb_entry((node), struct deadline_rq, rb_node) #define DRQ_RB_ROOT(dd, drq) (&(dd)->sort_list[rq_data_dir((drq)->request)]) #define rq_rb_key(rq) (rq)->sector @@ -227,9 +217,9 @@ deadline_del_drq_rb(struct deadline_data dd->next_drq[data_dir] = rb_entry_drq(rbnext); } - BUG_ON(!ON_RB(&drq->rb_node)); + BUG_ON(!RB_EMPTY_NODE(&drq->rb_node)); rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq)); - RB_CLEAR(&drq->rb_node); + RB_CLEAR_NODE(&drq->rb_node); } static struct request * @@ -503,7 +493,7 @@ static int deadline_dispatch_requests(re */ if (reads) { - BUG_ON(RB_EMPTY(&dd->sort_list[READ])); + BUG_ON(RB_EMPTY_ROOT(&dd->sort_list[READ])); if (writes && (dd->starved++ >= dd->writes_starved)) goto dispatch_writes; @@ -519,7 +509,7 @@ static int deadline_dispatch_requests(re if (writes) { dispatch_writes: - BUG_ON(RB_EMPTY(&dd->sort_list[WRITE])); + BUG_ON(RB_EMPTY_ROOT(&dd->sort_list[WRITE])); dd->starved = 0; @@ -626,7 +616,7 @@ static void *deadline_init_queue(request return NULL; memset(dd, 0, sizeof(*dd)); - dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES, + dd->hash = kmalloc_node(sizeof(struct hlist_head)*DL_HASH_ENTRIES, GFP_KERNEL, q->node); if (!dd->hash) { kfree(dd); @@ -642,7 +632,7 @@ static void *deadline_init_queue(request } for (i = 0; i < DL_HASH_ENTRIES; i++) - INIT_LIST_HEAD(&dd->hash[i]); + INIT_HLIST_HEAD(&dd->hash[i]); INIT_LIST_HEAD(&dd->fifo_list[READ]); INIT_LIST_HEAD(&dd->fifo_list[WRITE]); @@ -675,11 +665,10 @@ deadline_set_request(request_queue_t *q, drq = mempool_alloc(dd->drq_pool, gfp_mask); if (drq) { memset(drq, 0, sizeof(*drq)); - RB_CLEAR(&drq->rb_node); + RB_CLEAR_NODE(&drq->rb_node); drq->request = rq; - INIT_LIST_HEAD(&drq->hash); - drq->on_hash = 0; + INIT_HLIST_NODE(&drq->hash); INIT_LIST_HEAD(&drq->fifo); diff --git a/block/elevator.c b/block/elevator.c index a0afdd3..d00b283 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -850,12 +850,9 @@ fail_register: * one again (along with re-adding the sysfs dir) */ elevator_exit(e); - e = NULL; q->elevator = old_elevator; elv_register_queue(q); clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); - if (e) - kobject_put(&e->kobj); return 0; } diff --git a/block/genhd.c b/block/genhd.c index 5a8d3bf..8d73395 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -17,8 +17,7 @@ #include #include #include -static struct subsystem block_subsys; - +struct subsystem block_subsys; static DEFINE_MUTEX(block_subsys_lock); /* @@ -511,9 +510,7 @@ static struct kset_uevent_ops block_ueve .uevent = block_uevent, }; -/* declare block_subsys. */ -static decl_subsys(block, &ktype_block, &block_uevent_ops); - +decl_subsys(block, &ktype_block, &block_uevent_ops); /* * aggregate disk stat collector. Uses the same stats that the sysfs diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 7eb36c5..c04422a 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -638,7 +638,7 @@ #if BITS_PER_LONG == 64 /* Assume anything <= 4GB can be handled by IOMMU. Actually some IOMMUs can handle everything, but I don't know of a way to test this here. */ - if (bounce_pfn < (0xffffffff>>PAGE_SHIFT)) + if (bounce_pfn < (min_t(u64,0xffffffff,BLK_BOUNCE_HIGH) >> PAGE_SHIFT)) dma = 1; q->bounce_pfn = max_low_pfn; #else @@ -1663,6 +1663,8 @@ static void blk_unplug_timeout(unsigned **/ void blk_start_queue(request_queue_t *q) { + WARN_ON(!irqs_disabled()); + clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); /* @@ -1878,7 +1880,8 @@ EXPORT_SYMBOL(blk_alloc_queue_node); * get dealt with eventually. * * The queue spin lock must be held while manipulating the requests on the - * request queue. + * request queue; this lock will be taken also from interrupt context, so irq + * disabling is needed for it. * * Function returns a pointer to the initialized request queue, or NULL if * it didn't succeed. @@ -2742,7 +2745,7 @@ static int attempt_merge(request_queue_t return 0; /* - * not contigious + * not contiguous */ if (req->sector + req->nr_sectors != next->sector) return 0; @@ -2824,6 +2827,9 @@ static void init_request_from_bio(struct if (unlikely(bio_barrier(bio))) req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE); + if (bio_sync(bio)) + req->flags |= REQ_RW_SYNC; + req->errors = 0; req->hard_sector = req->sector = bio->bi_sector; req->hard_nr_sectors = req->nr_sectors = bio_sectors(bio); @@ -3359,12 +3365,11 @@ EXPORT_SYMBOL(end_that_request_chunk); */ static void blk_done_softirq(struct softirq_action *h) { - struct list_head *cpu_list; - LIST_HEAD(local_list); + struct list_head *cpu_list, local_list; local_irq_disable(); cpu_list = &__get_cpu_var(blk_cpu_done); - list_splice_init(cpu_list, &local_list); + list_replace_init(cpu_list, &local_list); local_irq_enable(); while (!list_empty(&local_list)) { @@ -3410,7 +3415,7 @@ #endif /* CONFIG_HOTPLUG_CPU */ * * Description: * Ends all I/O on a request. It does not handle partial completions, - * unless the driver actually implements this in its completionc callback + * unless the driver actually implements this in its completion callback * through requeueing. Theh actual completion happens out-of-order, * through a softirq handler. The user must have registered a completion * callback through blk_queue_softirq_done(). diff --git a/crypto/Kconfig b/crypto/Kconfig index c442f2e..ba133d5 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -337,7 +337,7 @@ config CRYPTO_CRC32C config CRYPTO_TEST tristate "Testing module" - depends on CRYPTO + depends on CRYPTO && m help Quick & dirty crypto test module. diff --git a/crypto/aes.c b/crypto/aes.c index a501729..a038711 100644 --- a/crypto/aes.c +++ b/crypto/aes.c @@ -248,10 +248,10 @@ #define loop8(i) t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \ } -static int -aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) +static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len, u32 *flags) { - struct aes_ctx *ctx = ctx_arg; + struct aes_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *key = (const __le32 *)in_key; u32 i, t, u, v, w; @@ -318,9 +318,9 @@ #define f_lround(bo, bi, k) \ f_rl(bo, bi, 2, k); \ f_rl(bo, bi, 3, k) -static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in) +static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - const struct aes_ctx *ctx = ctx_arg; + const struct aes_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *src = (const __le32 *)in; __le32 *dst = (__le32 *)out; u32 b0[4], b1[4]; @@ -373,9 +373,9 @@ #define i_lround(bo, bi, k) \ i_rl(bo, bi, 2, k); \ i_rl(bo, bi, 3, k) -static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in) +static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - const struct aes_ctx *ctx = ctx_arg; + const struct aes_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *src = (const __le32 *)in; __le32 *dst = (__le32 *)out; u32 b0[4], b1[4]; diff --git a/crypto/anubis.c b/crypto/anubis.c index 2c796bd..7e2e1a2 100644 --- a/crypto/anubis.c +++ b/crypto/anubis.c @@ -460,16 +460,15 @@ static const u32 rc[] = { 0xf726ffedU, 0xe89d6f8eU, 0x19a0f089U, }; -static int anubis_setkey(void *ctx_arg, const u8 *in_key, +static int anubis_setkey(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len, u32 *flags) { + struct anubis_ctx *ctx = crypto_tfm_ctx(tfm); const __be32 *key = (const __be32 *)in_key; int N, R, i, r; u32 kappa[ANUBIS_MAX_N]; u32 inter[ANUBIS_MAX_N]; - struct anubis_ctx *ctx = ctx_arg; - switch (key_len) { case 16: case 20: case 24: case 28: @@ -660,15 +659,15 @@ static void anubis_crypt(u32 roundKey[AN dst[i] = cpu_to_be32(inter[i]); } -static void anubis_encrypt(void *ctx_arg, u8 *dst, const u8 *src) +static void anubis_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct anubis_ctx *ctx = ctx_arg; + struct anubis_ctx *ctx = crypto_tfm_ctx(tfm); anubis_crypt(ctx->E, dst, src, ctx->R); } -static void anubis_decrypt(void *ctx_arg, u8 *dst, const u8 *src) +static void anubis_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct anubis_ctx *ctx = ctx_arg; + struct anubis_ctx *ctx = crypto_tfm_ctx(tfm); anubis_crypt(ctx->D, dst, src, ctx->R); } diff --git a/crypto/api.c b/crypto/api.c index 80bba63..c11ec1f 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -188,13 +188,16 @@ struct crypto_tfm *crypto_alloc_tfm(cons if (crypto_init_flags(tfm, flags)) goto out_free_tfm; - if (crypto_init_ops(tfm)) { - crypto_exit_ops(tfm); + if (crypto_init_ops(tfm)) goto out_free_tfm; - } + + if (alg->cra_init && alg->cra_init(tfm)) + goto cra_init_failed; goto out; +cra_init_failed: + crypto_exit_ops(tfm); out_free_tfm: kfree(tfm); tfm = NULL; @@ -215,6 +218,8 @@ void crypto_free_tfm(struct crypto_tfm * alg = tfm->__crt_alg; size = sizeof(*tfm) + alg->cra_ctxsize; + if (alg->cra_exit) + alg->cra_exit(tfm); crypto_exit_ops(tfm); crypto_alg_put(alg); memset(tfm, 0, size); @@ -224,7 +229,7 @@ void crypto_free_tfm(struct crypto_tfm * static inline int crypto_set_driver_name(struct crypto_alg *alg) { static const char suffix[] = "-generic"; - char *driver_name = (char *)alg->cra_driver_name; + char *driver_name = alg->cra_driver_name; int len; if (*driver_name) @@ -262,13 +267,13 @@ int crypto_register_alg(struct crypto_al down_write(&crypto_alg_sem); list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (!strcmp(q->cra_driver_name, alg->cra_driver_name)) { + if (q == alg) { ret = -EEXIST; goto out; } } - list_add_tail(&alg->cra_list, &crypto_alg_list); + list_add(&alg->cra_list, &crypto_alg_list); out: up_write(&crypto_alg_sem); return ret; diff --git a/crypto/arc4.c b/crypto/arc4.c index 9efbcaa..5edc6a6 100644 --- a/crypto/arc4.c +++ b/crypto/arc4.c @@ -24,9 +24,10 @@ struct arc4_ctx { u8 x, y; }; -static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) +static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len, u32 *flags) { - struct arc4_ctx *ctx = ctx_arg; + struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); int i, j = 0, k = 0; ctx->x = 1; @@ -48,9 +49,9 @@ static int arc4_set_key(void *ctx_arg, c return 0; } -static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in) +static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - struct arc4_ctx *ctx = ctx_arg; + struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); u8 *const S = ctx->S; u8 x = ctx->x; diff --git a/crypto/blowfish.c b/crypto/blowfish.c index 7f710b2..490265f 100644 --- a/crypto/blowfish.c +++ b/crypto/blowfish.c @@ -349,7 +349,7 @@ static void encrypt_block(struct bf_ctx dst[1] = yl; } -static void bf_encrypt(void *ctx, u8 *dst, const u8 *src) +static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { const __be32 *in_blk = (const __be32 *)src; __be32 *const out_blk = (__be32 *)dst; @@ -357,17 +357,18 @@ static void bf_encrypt(void *ctx, u8 *ds in32[0] = be32_to_cpu(in_blk[0]); in32[1] = be32_to_cpu(in_blk[1]); - encrypt_block(ctx, out32, in32); + encrypt_block(crypto_tfm_ctx(tfm), out32, in32); out_blk[0] = cpu_to_be32(out32[0]); out_blk[1] = cpu_to_be32(out32[1]); } -static void bf_decrypt(void *ctx, u8 *dst, const u8 *src) +static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { + struct bf_ctx *ctx = crypto_tfm_ctx(tfm); const __be32 *in_blk = (const __be32 *)src; __be32 *const out_blk = (__be32 *)dst; - const u32 *P = ((struct bf_ctx *)ctx)->p; - const u32 *S = ((struct bf_ctx *)ctx)->s; + const u32 *P = ctx->p; + const u32 *S = ctx->s; u32 yl = be32_to_cpu(in_blk[0]); u32 yr = be32_to_cpu(in_blk[1]); @@ -398,12 +399,14 @@ static void bf_decrypt(void *ctx, u8 *ds /* * Calculates the blowfish S and P boxes for encryption and decryption. */ -static int bf_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +static int bf_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen, u32 *flags) { + struct bf_ctx *ctx = crypto_tfm_ctx(tfm); + u32 *P = ctx->p; + u32 *S = ctx->s; short i, j, count; u32 data[2], temp; - u32 *P = ((struct bf_ctx *)ctx)->p; - u32 *S = ((struct bf_ctx *)ctx)->s; /* Copy the initialization s-boxes */ for (i = 0, count = 0; i < 256; i++) diff --git a/crypto/cast5.c b/crypto/cast5.c index 8834c85..08eef58 100644 --- a/crypto/cast5.c +++ b/crypto/cast5.c @@ -577,9 +577,9 @@ #define F3(D,m,r) ( (I = ((m) - (D))), (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) ) -static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf) +static void cast5_encrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf) { - struct cast5_ctx *c = (struct cast5_ctx *) ctx; + struct cast5_ctx *c = crypto_tfm_ctx(tfm); const __be32 *src = (const __be32 *)inbuf; __be32 *dst = (__be32 *)outbuf; u32 l, r, t; @@ -642,9 +642,9 @@ static void cast5_encrypt(void *ctx, u8 dst[1] = cpu_to_be32(l); } -static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf) +static void cast5_decrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf) { - struct cast5_ctx *c = (struct cast5_ctx *) ctx; + struct cast5_ctx *c = crypto_tfm_ctx(tfm); const __be32 *src = (const __be32 *)inbuf; __be32 *dst = (__be32 *)outbuf; u32 l, r, t; @@ -769,15 +769,15 @@ #undef zi } -static int -cast5_setkey(void *ctx, const u8 * key, unsigned key_len, u32 * flags) +static int cast5_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned key_len, u32 *flags) { + struct cast5_ctx *c = crypto_tfm_ctx(tfm); int i; u32 x[4]; u32 z[4]; u32 k[16]; __be32 p_key[4]; - struct cast5_ctx *c = (struct cast5_ctx *) ctx; if (key_len < 5 || key_len > 16) { *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; diff --git a/crypto/cast6.c b/crypto/cast6.c index 9e28740..08e33bf 100644 --- a/crypto/cast6.c +++ b/crypto/cast6.c @@ -381,13 +381,13 @@ static inline void W(u32 *key, unsigned key[7] ^= F2(key[0], Tr[i % 4][7], Tm[i][7]); } -static int -cast6_setkey(void *ctx, const u8 * in_key, unsigned key_len, u32 * flags) +static int cast6_setkey(struct crypto_tfm *tfm, const u8 *in_key, + unsigned key_len, u32 *flags) { int i; u32 key[8]; __be32 p_key[8]; /* padded key */ - struct cast6_ctx *c = (struct cast6_ctx *) ctx; + struct cast6_ctx *c = crypto_tfm_ctx(tfm); if (key_len < 16 || key_len > 32 || key_len % 4 != 0) { *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; @@ -444,8 +444,9 @@ static inline void QBAR (u32 * block, u8 block[2] ^= F1(block[3], Kr[0], Km[0]); } -static void cast6_encrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { - struct cast6_ctx * c = (struct cast6_ctx *)ctx; +static void cast6_encrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf) +{ + struct cast6_ctx *c = crypto_tfm_ctx(tfm); const __be32 *src = (const __be32 *)inbuf; __be32 *dst = (__be32 *)outbuf; u32 block[4]; @@ -476,8 +477,8 @@ static void cast6_encrypt (void * ctx, u dst[3] = cpu_to_be32(block[3]); } -static void cast6_decrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { - struct cast6_ctx * c = (struct cast6_ctx *)ctx; +static void cast6_decrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf) { + struct cast6_ctx * c = crypto_tfm_ctx(tfm); const __be32 *src = (const __be32 *)inbuf; __be32 *dst = (__be32 *)outbuf; u32 block[4]; diff --git a/crypto/cipher.c b/crypto/cipher.c index 65bcea0..b899eb9 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -187,7 +187,7 @@ static unsigned int cbc_process_encrypt( void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block; int bsize = crypto_tfm_alg_blocksize(tfm); - void (*fn)(void *, u8 *, const u8 *) = desc->crfn; + void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn; u8 *iv = desc->info; unsigned int done = 0; @@ -195,7 +195,7 @@ static unsigned int cbc_process_encrypt( do { xor(iv, src); - fn(crypto_tfm_ctx(tfm), dst, iv); + fn(tfm, dst, iv); memcpy(iv, dst, bsize); src += bsize; @@ -218,7 +218,7 @@ static unsigned int cbc_process_decrypt( u8 *buf = (u8 *)ALIGN((unsigned long)stack, alignmask + 1); u8 **dst_p = src == dst ? &buf : &dst; - void (*fn)(void *, u8 *, const u8 *) = desc->crfn; + void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn; u8 *iv = desc->info; unsigned int done = 0; @@ -227,7 +227,7 @@ static unsigned int cbc_process_decrypt( do { u8 *tmp_dst = *dst_p; - fn(crypto_tfm_ctx(tfm), tmp_dst, src); + fn(tfm, tmp_dst, src); xor(tmp_dst, iv); memcpy(iv, src, bsize); if (tmp_dst != dst) @@ -245,13 +245,13 @@ static unsigned int ecb_process(const st { struct crypto_tfm *tfm = desc->tfm; int bsize = crypto_tfm_alg_blocksize(tfm); - void (*fn)(void *, u8 *, const u8 *) = desc->crfn; + void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn; unsigned int done = 0; nbytes -= bsize; do { - fn(crypto_tfm_ctx(tfm), dst, src); + fn(tfm, dst, src); src += bsize; dst += bsize; @@ -268,7 +268,7 @@ static int setkey(struct crypto_tfm *tfm tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } else - return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen, + return cia->cia_setkey(tfm, key, keylen, &tfm->crt_flags); } diff --git a/crypto/compress.c b/crypto/compress.c index eb36d93..eca182a 100644 --- a/crypto/compress.c +++ b/crypto/compress.c @@ -22,8 +22,7 @@ static int crypto_compress(struct crypto const u8 *src, unsigned int slen, u8 *dst, unsigned int *dlen) { - return tfm->__crt_alg->cra_compress.coa_compress(crypto_tfm_ctx(tfm), - src, slen, dst, + return tfm->__crt_alg->cra_compress.coa_compress(tfm, src, slen, dst, dlen); } @@ -31,8 +30,7 @@ static int crypto_decompress(struct cryp const u8 *src, unsigned int slen, u8 *dst, unsigned int *dlen) { - return tfm->__crt_alg->cra_compress.coa_decompress(crypto_tfm_ctx(tfm), - src, slen, dst, + return tfm->__crt_alg->cra_compress.coa_decompress(tfm, src, slen, dst, dlen); } @@ -43,21 +41,14 @@ int crypto_init_compress_flags(struct cr int crypto_init_compress_ops(struct crypto_tfm *tfm) { - int ret = 0; struct compress_tfm *ops = &tfm->crt_compress; - - ret = tfm->__crt_alg->cra_compress.coa_init(crypto_tfm_ctx(tfm)); - if (ret) - goto out; ops->cot_compress = crypto_compress; ops->cot_decompress = crypto_decompress; -out: - return ret; + return 0; } void crypto_exit_compress_ops(struct crypto_tfm *tfm) { - tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm)); } diff --git a/crypto/crc32c.c b/crypto/crc32c.c index 9533624..f266012 100644 --- a/crypto/crc32c.c +++ b/crypto/crc32c.c @@ -31,9 +31,9 @@ struct chksum_ctx { * crc using table. */ -static void chksum_init(void *ctx) +static void chksum_init(struct crypto_tfm *tfm) { - struct chksum_ctx *mctx = ctx; + struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); mctx->crc = ~(u32)0; /* common usage */ } @@ -43,10 +43,10 @@ static void chksum_init(void *ctx) * If your algorithm starts with ~0, then XOR with ~0 before you set * the seed. */ -static int chksum_setkey(void *ctx, const u8 *key, unsigned int keylen, - u32 *flags) +static int chksum_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen, u32 *flags) { - struct chksum_ctx *mctx = ctx; + struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); if (keylen != sizeof(mctx->crc)) { if (flags) @@ -57,9 +57,10 @@ static int chksum_setkey(void *ctx, cons return 0; } -static void chksum_update(void *ctx, const u8 *data, unsigned int length) +static void chksum_update(struct crypto_tfm *tfm, const u8 *data, + unsigned int length) { - struct chksum_ctx *mctx = ctx; + struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); u32 mcrc; mcrc = crc32c(mctx->crc, data, (size_t)length); @@ -67,9 +68,9 @@ static void chksum_update(void *ctx, con mctx->crc = mcrc; } -static void chksum_final(void *ctx, u8 *out) +static void chksum_final(struct crypto_tfm *tfm, u8 *out) { - struct chksum_ctx *mctx = ctx; + struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); u32 mcrc = (mctx->crc ^ ~(u32)0); *(u32 *)out = __le32_to_cpu(mcrc); diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c index 3fcf6e8..a0d956b 100644 --- a/crypto/crypto_null.c +++ b/crypto/crypto_null.c @@ -27,8 +27,8 @@ #define NULL_KEY_SIZE 0 #define NULL_BLOCK_SIZE 1 #define NULL_DIGEST_SIZE 0 -static int null_compress(void *ctx, const u8 *src, unsigned int slen, - u8 *dst, unsigned int *dlen) +static int null_compress(struct crypto_tfm *tfm, const u8 *src, + unsigned int slen, u8 *dst, unsigned int *dlen) { if (slen > *dlen) return -EINVAL; @@ -37,20 +37,21 @@ static int null_compress(void *ctx, cons return 0; } -static void null_init(void *ctx) +static void null_init(struct crypto_tfm *tfm) { } -static void null_update(void *ctx, const u8 *data, unsigned int len) +static void null_update(struct crypto_tfm *tfm, const u8 *data, + unsigned int len) { } -static void null_final(void *ctx, u8 *out) +static void null_final(struct crypto_tfm *tfm, u8 *out) { } -static int null_setkey(void *ctx, const u8 *key, - unsigned int keylen, u32 *flags) +static int null_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen, u32 *flags) { return 0; } -static void null_crypt(void *ctx, u8 *dst, const u8 *src) +static void null_crypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { memcpy(dst, src, NULL_BLOCK_SIZE); } diff --git a/crypto/deflate.c b/crypto/deflate.c index f209368..6588bbf 100644 --- a/crypto/deflate.c +++ b/crypto/deflate.c @@ -102,8 +102,9 @@ static void deflate_decomp_exit(struct d kfree(ctx->decomp_stream.workspace); } -static int deflate_init(void *ctx) +static int deflate_init(struct crypto_tfm *tfm) { + struct deflate_ctx *ctx = crypto_tfm_ctx(tfm); int ret; ret = deflate_comp_init(ctx); @@ -116,17 +117,19 @@ out: return ret; } -static void deflate_exit(void *ctx) +static void deflate_exit(struct crypto_tfm *tfm) { + struct deflate_ctx *ctx = crypto_tfm_ctx(tfm); + deflate_comp_exit(ctx); deflate_decomp_exit(ctx); } -static int deflate_compress(void *ctx, const u8 *src, unsigned int slen, - u8 *dst, unsigned int *dlen) +static int deflate_compress(struct crypto_tfm *tfm, const u8 *src, + unsigned int slen, u8 *dst, unsigned int *dlen) { int ret = 0; - struct deflate_ctx *dctx = ctx; + struct deflate_ctx *dctx = crypto_tfm_ctx(tfm); struct z_stream_s *stream = &dctx->comp_stream; ret = zlib_deflateReset(stream); @@ -151,12 +154,12 @@ out: return ret; } -static int deflate_decompress(void *ctx, const u8 *src, unsigned int slen, - u8 *dst, unsigned int *dlen) +static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src, + unsigned int slen, u8 *dst, unsigned int *dlen) { int ret = 0; - struct deflate_ctx *dctx = ctx; + struct deflate_ctx *dctx = crypto_tfm_ctx(tfm); struct z_stream_s *stream = &dctx->decomp_stream; ret = zlib_inflateReset(stream); @@ -198,9 +201,9 @@ static struct crypto_alg alg = { .cra_ctxsize = sizeof(struct deflate_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_init = deflate_init, + .cra_exit = deflate_exit, .cra_u = { .compress = { - .coa_init = deflate_init, - .coa_exit = deflate_exit, .coa_compress = deflate_compress, .coa_decompress = deflate_decompress } } }; diff --git a/crypto/des.c b/crypto/des.c index 2d74cab..a9d3c23 100644 --- a/crypto/des.c +++ b/crypto/des.c @@ -783,9 +783,10 @@ static void dkey(u32 *pe, const u8 *k) } } -static int des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +static int des_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen, u32 *flags) { - struct des_ctx *dctx = ctx; + struct des_ctx *dctx = crypto_tfm_ctx(tfm); u32 tmp[DES_EXPKEY_WORDS]; int ret; @@ -803,9 +804,10 @@ static int des_setkey(void *ctx, const u return 0; } -static void des_encrypt(void *ctx, u8 *dst, const u8 *src) +static void des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - const u32 *K = ((struct des_ctx *)ctx)->expkey; + struct des_ctx *ctx = crypto_tfm_ctx(tfm); + const u32 *K = ctx->expkey; const __le32 *s = (const __le32 *)src; __le32 *d = (__le32 *)dst; u32 L, R, A, B; @@ -825,9 +827,10 @@ static void des_encrypt(void *ctx, u8 *d d[1] = cpu_to_le32(L); } -static void des_decrypt(void *ctx, u8 *dst, const u8 *src) +static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - const u32 *K = ((struct des_ctx *)ctx)->expkey + DES_EXPKEY_WORDS - 2; + struct des_ctx *ctx = crypto_tfm_ctx(tfm); + const u32 *K = ctx->expkey + DES_EXPKEY_WORDS - 2; const __le32 *s = (const __le32 *)src; __le32 *d = (__le32 *)dst; u32 L, R, A, B; @@ -860,11 +863,11 @@ static void des_decrypt(void *ctx, u8 *d * property. * */ -static int des3_ede_setkey(void *ctx, const u8 *key, +static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen, u32 *flags) { const u32 *K = (const u32 *)key; - struct des3_ede_ctx *dctx = ctx; + struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); u32 *expkey = dctx->expkey; if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) || @@ -881,9 +884,9 @@ static int des3_ede_setkey(void *ctx, co return 0; } -static void des3_ede_encrypt(void *ctx, u8 *dst, const u8 *src) +static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct des3_ede_ctx *dctx = ctx; + struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); const u32 *K = dctx->expkey; const __le32 *s = (const __le32 *)src; __le32 *d = (__le32 *)dst; @@ -912,9 +915,9 @@ static void des3_ede_encrypt(void *ctx, d[1] = cpu_to_le32(L); } -static void des3_ede_decrypt(void *ctx, u8 *dst, const u8 *src) +static void des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct des3_ede_ctx *dctx = ctx; + struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); const u32 *K = dctx->expkey + DES3_EDE_EXPKEY_WORDS - 2; const __le32 *s = (const __le32 *)src; __le32 *d = (__le32 *)dst; diff --git a/crypto/digest.c b/crypto/digest.c index d9b6ac9..603006a 100644 --- a/crypto/digest.c +++ b/crypto/digest.c @@ -20,13 +20,14 @@ #include "internal.h" static void init(struct crypto_tfm *tfm) { - tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm)); + tfm->__crt_alg->cra_digest.dia_init(tfm); } static void update(struct crypto_tfm *tfm, struct scatterlist *sg, unsigned int nsg) { unsigned int i; + unsigned int alignmask = crypto_tfm_alg_alignmask(tfm); for (i = 0; i < nsg; i++) { @@ -38,12 +39,22 @@ static void update(struct crypto_tfm *tf unsigned int bytes_from_page = min(l, ((unsigned int) (PAGE_SIZE)) - offset); - char *p = crypto_kmap(pg, 0) + offset; + char *src = crypto_kmap(pg, 0); + char *p = src + offset; - tfm->__crt_alg->cra_digest.dia_update - (crypto_tfm_ctx(tfm), p, - bytes_from_page); - crypto_kunmap(p, 0); + if (unlikely(offset & alignmask)) { + unsigned int bytes = + alignmask + 1 - (offset & alignmask); + bytes = min(bytes, bytes_from_page); + tfm->__crt_alg->cra_digest.dia_update(tfm, p, + bytes); + p += bytes; + bytes_from_page -= bytes; + l -= bytes; + } + tfm->__crt_alg->cra_digest.dia_update(tfm, p, + bytes_from_page); + crypto_kunmap(src, 0); crypto_yield(tfm); offset = 0; pg++; @@ -54,7 +65,15 @@ static void update(struct crypto_tfm *tf static void final(struct crypto_tfm *tfm, u8 *out) { - tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out); + unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); + if (unlikely((unsigned long)out & alignmask)) { + unsigned int size = crypto_tfm_alg_digestsize(tfm); + u8 buffer[size + alignmask]; + u8 *dst = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); + tfm->__crt_alg->cra_digest.dia_final(tfm, dst); + memcpy(out, dst, size); + } else + tfm->__crt_alg->cra_digest.dia_final(tfm, out); } static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) @@ -62,25 +81,15 @@ static int setkey(struct crypto_tfm *tfm u32 flags; if (tfm->__crt_alg->cra_digest.dia_setkey == NULL) return -ENOSYS; - return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm), - key, keylen, &flags); + return tfm->__crt_alg->cra_digest.dia_setkey(tfm, key, keylen, &flags); } static void digest(struct crypto_tfm *tfm, struct scatterlist *sg, unsigned int nsg, u8 *out) { - unsigned int i; - - tfm->crt_digest.dit_init(tfm); - - for (i = 0; i < nsg; i++) { - char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; - tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), - p, sg[i].length); - crypto_kunmap(p, 0); - crypto_yield(tfm); - } - crypto_digest_final(tfm, out); + init(tfm); + update(tfm, sg, nsg); + final(tfm, out); } int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) diff --git a/crypto/khazad.c b/crypto/khazad.c index 807f2bf..d4c9d36 100644 --- a/crypto/khazad.c +++ b/crypto/khazad.c @@ -754,11 +754,11 @@ static const u64 c[KHAZAD_ROUNDS + 1] = 0xccc41d14c363da5dULL, 0x5fdc7dcd7f5a6c5cULL, 0xf726ffede89d6f8eULL }; -static int khazad_setkey(void *ctx_arg, const u8 *in_key, - unsigned int key_len, u32 *flags) +static int khazad_setkey(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len, u32 *flags) { - struct khazad_ctx *ctx = ctx_arg; - const __be64 *key = (const __be64 *)in_key; + struct khazad_ctx *ctx = crypto_tfm_ctx(tfm); + const __be32 *key = (const __be32 *)in_key; int r; const u64 *S = T7; u64 K2, K1; @@ -769,8 +769,9 @@ static int khazad_setkey(void *ctx_arg, return -EINVAL; } - K2 = be64_to_cpu(key[0]); - K1 = be64_to_cpu(key[1]); + /* key is supposed to be 32-bit aligned */ + K2 = ((u64)be32_to_cpu(key[0]) << 32) | be32_to_cpu(key[1]); + K1 = ((u64)be32_to_cpu(key[2]) << 32) | be32_to_cpu(key[3]); /* setup the encrypt key */ for (r = 0; r <= KHAZAD_ROUNDS; r++) { @@ -840,15 +841,15 @@ static void khazad_crypt(const u64 round *dst = cpu_to_be64(state); } -static void khazad_encrypt(void *ctx_arg, u8 *dst, const u8 *src) +static void khazad_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct khazad_ctx *ctx = ctx_arg; + struct khazad_ctx *ctx = crypto_tfm_ctx(tfm); khazad_crypt(ctx->E, dst, src); } -static void khazad_decrypt(void *ctx_arg, u8 *dst, const u8 *src) +static void khazad_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { - struct khazad_ctx *ctx = ctx_arg; + struct khazad_ctx *ctx = crypto_tfm_ctx(tfm); khazad_crypt(ctx->D, dst, src); } diff --git a/crypto/md4.c b/crypto/md4.c index a2d6df5..c1bc71b 100644 --- a/crypto/md4.c +++ b/crypto/md4.c @@ -152,9 +152,9 @@ static inline void md4_transform_helper( md4_transform(ctx->hash, ctx->block); } -static void md4_init(void *ctx) +static void md4_init(struct crypto_tfm *tfm) { - struct md4_ctx *mctx = ctx; + struct md4_ctx *mctx = crypto_tfm_ctx(tfm); mctx->hash[0] = 0x67452301; mctx->hash[1] = 0xefcdab89; @@ -163,9 +163,9 @@ static void md4_init(void *ctx) mctx->byte_count = 0; } -static void md4_update(void *ctx, const u8 *data, unsigned int len) +static void md4_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len) { - struct md4_ctx *mctx = ctx; + struct md4_ctx *mctx = crypto_tfm_ctx(tfm); const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); mctx->byte_count += len; @@ -193,9 +193,9 @@ static void md4_update(void *ctx, const memcpy(mctx->block, data, len); } -static void md4_final(void *ctx, u8 *out) +static void md4_final(struct crypto_tfm *tfm, u8 *out) { - struct md4_ctx *mctx = ctx; + struct md4_ctx *mctx = crypto_tfm_ctx(tfm); const unsigned int offset = mctx->byte_count & 0x3f; char *p = (char *)mctx->block + offset; int padding = 56 - (offset + 1); diff --git a/crypto/md5.c b/crypto/md5.c index 7f041ae..93d18e8 100644 --- a/crypto/md5.c +++ b/crypto/md5.c @@ -147,9 +147,9 @@ static inline void md5_transform_helper( md5_transform(ctx->hash, ctx->block); } -static void md5_init(void *ctx) +static void md5_init(struct crypto_tfm *tfm) { - struct md5_ctx *mctx = ctx; + struct md5_ctx *mctx = crypto_tfm_ctx(tfm); mctx->hash[0] = 0x67452301; mctx->hash[1] = 0xefcdab89; @@ -158,9 +158,9 @@ static void md5_init(void *ctx) mctx->byte_count = 0; } -static void md5_update(void *ctx, const u8 *data, unsigned int len) +static void md5_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len) { - struct md5_ctx *mctx = ctx; + struct md5_ctx *mctx = crypto_tfm_ctx(tfm); const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); mctx->byte_count += len; @@ -188,9 +188,9 @@ static void md5_update(void *ctx, const memcpy(mctx->block, data, len); } -static void md5_final(void *ctx, u8 *out) +static void md5_final(struct crypto_tfm *tfm, u8 *out) { - struct md5_ctx *mctx = ctx; + struct md5_ctx *mctx = crypto_tfm_ctx(tfm); const unsigned int offset = mctx->byte_count & 0x3f; char *p = (char *)mctx->block + offset; int padding = 56 - (offset + 1); diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c index 4f6ab23..d061da2 100644 --- a/crypto/michael_mic.c +++ b/crypto/michael_mic.c @@ -45,16 +45,17 @@ do { \ } while (0) -static void michael_init(void *ctx) +static void michael_init(struct crypto_tfm *tfm) { - struct michael_mic_ctx *mctx = ctx; + struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm); mctx->pending_len = 0; } -static void michael_update(void *ctx, const u8 *data, unsigned int len) +static void michael_update(struct crypto_tfm *tfm, const u8 *data, + unsigned int len) { - struct michael_mic_ctx *mctx = ctx; + struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm); const __le32 *src; if (mctx->pending_len) { @@ -90,9 +91,9 @@ static void michael_update(void *ctx, co } -static void michael_final(void *ctx, u8 *out) +static void michael_final(struct crypto_tfm *tfm, u8 *out) { - struct michael_mic_ctx *mctx = ctx; + struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm); u8 *data = mctx->pending; __le32 *dst = (__le32 *)out; @@ -121,10 +122,10 @@ static void michael_final(void *ctx, u8 } -static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen, - u32 *flags) +static int michael_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen, u32 *flags) { - struct michael_mic_ctx *mctx = ctx; + struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm); const __le32 *data = (const __le32 *)key; if (keylen != 8) { @@ -145,6 +146,7 @@ static struct crypto_alg michael_mic_alg .cra_blocksize = 8, .cra_ctxsize = sizeof(struct michael_mic_ctx), .cra_module = THIS_MODULE, + .cra_alignmask = 3, .cra_list = LIST_HEAD_INIT(michael_mic_alg.cra_list), .cra_u = { .digest = { .dia_digestsize = 8, diff --git a/crypto/serpent.c b/crypto/serpent.c index e366406..de60cdd 100644 --- a/crypto/serpent.c +++ b/crypto/serpent.c @@ -215,9 +215,11 @@ struct serpent_ctx { }; -static int serpent_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +static int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen, u32 *flags) { - u32 *k = ((struct serpent_ctx *)ctx)->expkey; + struct serpent_ctx *ctx = crypto_tfm_ctx(tfm); + u32 *k = ctx->expkey; u8 *k8 = (u8 *)k; u32 r0,r1,r2,r3,r4; int i; @@ -365,10 +367,11 @@ static int serpent_setkey(void *ctx, con return 0; } -static void serpent_encrypt(void *ctx, u8 *dst, const u8 *src) +static void serpent_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { + struct serpent_ctx *ctx = crypto_tfm_ctx(tfm); const u32 - *k = ((struct serpent_ctx *)ctx)->expkey, + *k = ctx->expkey, *s = (const u32 *)src; u32 *d = (u32 *)dst, r0, r1, r2, r3, r4; @@ -423,8 +426,9 @@ static void serpent_encrypt(void *ctx, u d[3] = cpu_to_le32(r3); } -static void serpent_decrypt(void *ctx, u8 *dst, const u8 *src) +static void serpent_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { + struct serpent_ctx *ctx = crypto_tfm_ctx(tfm); const u32 *k = ((struct serpent_ctx *)ctx)->expkey, *s = (const u32 *)src; @@ -492,7 +496,8 @@ static struct crypto_alg serpent_alg = { .cia_decrypt = serpent_decrypt } } }; -static int tnepres_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) +static int tnepres_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen, u32 *flags) { u8 rev_key[SERPENT_MAX_KEY_SIZE]; int i; @@ -506,10 +511,10 @@ static int tnepres_setkey(void *ctx, con for (i = 0; i < keylen; ++i) rev_key[keylen - i - 1] = key[i]; - return serpent_setkey(ctx, rev_key, keylen, flags); + return serpent_setkey(tfm, rev_key, keylen, flags); } -static void tnepres_encrypt(void *ctx, u8 *dst, const u8 *src) +static void tnepres_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { const u32 * const s = (const u32 * const)src; u32 * const d = (u32 * const)dst; @@ -521,7 +526,7 @@ static void tnepres_encrypt(void *ctx, u rs[2] = swab32(s[1]); rs[3] = swab32(s[0]); - serpent_encrypt(ctx, (u8 *)rd, (u8 *)rs); + serpent_encrypt(tfm, (u8 *)rd, (u8 *)rs); d[0] = swab32(rd[3]); d[1] = swab32(rd[2]); @@ -529,7 +534,7 @@ static void tnepres_encrypt(void *ctx, u d[3] = swab32(rd[0]); } -static void tnepres_decrypt(void *ctx, u8 *dst, const u8 *src) +static void tnepres_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { const u32 * const s = (const u32 * const)src; u32 * const d = (u32 * const)dst; @@ -541,7 +546,7 @@ static void tnepres_decrypt(void *ctx, u rs[2] = swab32(s[1]); rs[3] = swab32(s[0]); - serpent_decrypt(ctx, (u8 *)rd, (u8 *)rs); + serpent_decrypt(tfm, (u8 *)rd, (u8 *)rs); d[0] = swab32(rd[3]); d[1] = swab32(rd[2]); diff --git a/crypto/sha1.c b/crypto/sha1.c index 21571ed..6c77b68 100644 --- a/crypto/sha1.c +++ b/crypto/sha1.c @@ -34,9 +34,9 @@ struct sha1_ctx { u8 buffer[64]; }; -static void sha1_init(void *ctx) +static void sha1_init(struct crypto_tfm *tfm) { - struct sha1_ctx *sctx = ctx; + struct sha1_ctx *sctx = crypto_tfm_ctx(tfm); static const struct sha1_ctx initstate = { 0, { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }, @@ -46,9 +46,10 @@ static void sha1_init(void *ctx) *sctx = initstate; } -static void sha1_update(void *ctx, const u8 *data, unsigned int len) +static void sha1_update(struct crypto_tfm *tfm, const u8 *data, + unsigned int len) { - struct sha1_ctx *sctx = ctx; + struct sha1_ctx *sctx = crypto_tfm_ctx(tfm); unsigned int partial, done; const u8 *src; @@ -80,9 +81,9 @@ static void sha1_update(void *ctx, const /* Add padding and return the message digest. */ -static void sha1_final(void* ctx, u8 *out) +static void sha1_final(struct crypto_tfm *tfm, u8 *out) { - struct sha1_ctx *sctx = ctx; + struct sha1_ctx *sctx = crypto_tfm_ctx(tfm); __be32 *dst = (__be32 *)out; u32 i, index, padlen; __be64 bits; @@ -93,10 +94,10 @@ static void sha1_final(void* ctx, u8 *ou /* Pad out to 56 mod 64 */ index = sctx->count & 0x3f; padlen = (index < 56) ? (56 - index) : ((64+56) - index); - sha1_update(sctx, padding, padlen); + sha1_update(tfm, padding, padlen); /* Append length */ - sha1_update(sctx, (const u8 *)&bits, sizeof(bits)); + sha1_update(tfm, (const u8 *)&bits, sizeof(bits)); /* Store state in digest */ for (i = 0; i < 5; i++) @@ -112,6 +113,7 @@ static struct crypto_alg alg = { .cra_blocksize = SHA1_HMAC_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sha1_ctx), .cra_module = THIS_MODULE, + .cra_alignmask = 3, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { .digest = { .dia_digestsize = SHA1_DIGEST_SIZE, diff --git a/crypto/sha256.c b/crypto/sha256.c index 9d5ef67..bc71d85 100644 --- a/crypto/sha256.c +++ b/crypto/sha256.c @@ -230,9 +230,9 @@ static void sha256_transform(u32 *state, memset(W, 0, 64 * sizeof(u32)); } -static void sha256_init(void *ctx) +static void sha256_init(struct crypto_tfm *tfm) { - struct sha256_ctx *sctx = ctx; + struct sha256_ctx *sctx = crypto_tfm_ctx(tfm); sctx->state[0] = H0; sctx->state[1] = H1; sctx->state[2] = H2; @@ -242,12 +242,12 @@ static void sha256_init(void *ctx) sctx->state[6] = H6; sctx->state[7] = H7; sctx->count[0] = sctx->count[1] = 0; - memset(sctx->buf, 0, sizeof(sctx->buf)); } -static void sha256_update(void *ctx, const u8 *data, unsigned int len) +static void sha256_update(struct crypto_tfm *tfm, const u8 *data, + unsigned int len) { - struct sha256_ctx *sctx = ctx; + struct sha256_ctx *sctx = crypto_tfm_ctx(tfm); unsigned int i, index, part_len; /* Compute number of bytes mod 128 */ @@ -277,9 +277,9 @@ static void sha256_update(void *ctx, con memcpy(&sctx->buf[index], &data[i], len-i); } -static void sha256_final(void* ctx, u8 *out) +static void sha256_final(struct crypto_tfm *tfm, u8 *out) { - struct sha256_ctx *sctx = ctx; + struct sha256_ctx *sctx = crypto_tfm_ctx(tfm); __be32 *dst = (__be32 *)out; __be32 bits[2]; unsigned int index, pad_len; @@ -293,10 +293,10 @@ static void sha256_final(void* ctx, u8 * /* Pad out to 56 mod 64. */ index = (sctx->count[0] >> 3) & 0x3f; pad_len = (index < 56) ? (56 - index) : ((64+56) - index); - sha256_update(sctx, padding, pad_len); + sha256_update(tfm, padding, pad_len); /* Append length (before padding) */ - sha256_update(sctx, (const u8 *)bits, sizeof(bits)); + sha256_update(tfm, (const u8 *)bits, sizeof(bits)); /* Store state in digest */ for (i = 0; i < 8; i++) @@ -313,6 +313,7 @@ static struct crypto_alg alg = { .cra_blocksize = SHA256_HMAC_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sha256_ctx), .cra_module = THIS_MODULE, + .cra_alignmask = 3, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { .digest = { .dia_digestsize = SHA256_DIGEST_SIZE, diff --git a/crypto/sha512.c b/crypto/sha512.c index 3e6e939..2dfe7f1 100644 --- a/crypto/sha512.c +++ b/crypto/sha512.c @@ -161,9 +161,9 @@ sha512_transform(u64 *state, u64 *W, con } static void -sha512_init(void *ctx) +sha512_init(struct crypto_tfm *tfm) { - struct sha512_ctx *sctx = ctx; + struct sha512_ctx *sctx = crypto_tfm_ctx(tfm); sctx->state[0] = H0; sctx->state[1] = H1; sctx->state[2] = H2; @@ -173,13 +173,12 @@ sha512_init(void *ctx) sctx->state[6] = H6; sctx->state[7] = H7; sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; - memset(sctx->buf, 0, sizeof(sctx->buf)); } static void -sha384_init(void *ctx) +sha384_init(struct crypto_tfm *tfm) { - struct sha512_ctx *sctx = ctx; + struct sha512_ctx *sctx = crypto_tfm_ctx(tfm); sctx->state[0] = HP0; sctx->state[1] = HP1; sctx->state[2] = HP2; @@ -189,13 +188,12 @@ sha384_init(void *ctx) sctx->state[6] = HP6; sctx->state[7] = HP7; sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0; - memset(sctx->buf, 0, sizeof(sctx->buf)); } static void -sha512_update(void *ctx, const u8 *data, unsigned int len) +sha512_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len) { - struct sha512_ctx *sctx = ctx; + struct sha512_ctx *sctx = crypto_tfm_ctx(tfm); unsigned int i, index, part_len; @@ -233,9 +231,9 @@ sha512_update(void *ctx, const u8 *data, } static void -sha512_final(void *ctx, u8 *hash) +sha512_final(struct crypto_tfm *tfm, u8 *hash) { - struct sha512_ctx *sctx = ctx; + struct sha512_ctx *sctx = crypto_tfm_ctx(tfm); static u8 padding[128] = { 0x80, }; __be64 *dst = (__be64 *)hash; __be32 bits[4]; @@ -251,10 +249,10 @@ sha512_final(void *ctx, u8 *hash) /* Pad out to 112 mod 128. */ index = (sctx->count[0] >> 3) & 0x7f; pad_len = (index < 112) ? (112 - index) : ((128+112) - index); - sha512_update(sctx, padding, pad_len); + sha512_update(tfm, padding, pad_len); /* Append length (before padding) */ - sha512_update(sctx, (const u8 *)bits, sizeof(bits)); + sha512_update(tfm, (const u8 *)bits, sizeof(bits)); /* Store state in digest */ for (i = 0; i < 8; i++) @@ -264,12 +262,11 @@ sha512_final(void *ctx, u8 *hash) memset(sctx, 0, sizeof(struct sha512_ctx)); } -static void sha384_final(void *ctx, u8 *hash) +static void sha384_final(struct crypto_tfm *tfm, u8 *hash) { - struct sha512_ctx *sctx = ctx; u8 D[64]; - sha512_final(sctx, D); + sha512_final(tfm, D); memcpy(hash, D, 48); memset(D, 0, 64); @@ -281,6 +278,7 @@ static struct crypto_alg sha512 = { .cra_blocksize = SHA512_HMAC_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sha512_ctx), .cra_module = THIS_MODULE, + .cra_alignmask = 3, .cra_list = LIST_HEAD_INIT(sha512.cra_list), .cra_u = { .digest = { .dia_digestsize = SHA512_DIGEST_SIZE, @@ -295,6 +293,7 @@ static struct crypto_alg sha384 = { .cra_flags = CRYPTO_ALG_TYPE_DIGEST, .cra_blocksize = SHA384_HMAC_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sha512_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(sha384.cra_list), .cra_u = { .digest = { diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 49e344f..e52f56c 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -570,6 +570,122 @@ out: crypto_free_tfm(tfm); } +static void test_digest_jiffies(struct crypto_tfm *tfm, char *p, int blen, + int plen, char *out, int sec) +{ + struct scatterlist sg[1]; + unsigned long start, end; + int bcount, pcount; + + for (start = jiffies, end = start + sec * HZ, bcount = 0; + time_before(jiffies, end); bcount++) { + crypto_digest_init(tfm); + for (pcount = 0; pcount < blen; pcount += plen) { + sg_set_buf(sg, p + pcount, plen); + crypto_digest_update(tfm, sg, 1); + } + /* we assume there is enough space in 'out' for the result */ + crypto_digest_final(tfm, out); + } + + printk("%6u opers/sec, %9lu bytes/sec\n", + bcount / sec, ((long)bcount * blen) / sec); + + return; +} + +static void test_digest_cycles(struct crypto_tfm *tfm, char *p, int blen, + int plen, char *out) +{ + struct scatterlist sg[1]; + unsigned long cycles = 0; + int i, pcount; + + local_bh_disable(); + local_irq_disable(); + + /* Warm-up run. */ + for (i = 0; i < 4; i++) { + crypto_digest_init(tfm); + for (pcount = 0; pcount < blen; pcount += plen) { + sg_set_buf(sg, p + pcount, plen); + crypto_digest_update(tfm, sg, 1); + } + crypto_digest_final(tfm, out); + } + + /* The real thing. */ + for (i = 0; i < 8; i++) { + cycles_t start, end; + + crypto_digest_init(tfm); + + start = get_cycles(); + + for (pcount = 0; pcount < blen; pcount += plen) { + sg_set_buf(sg, p + pcount, plen); + crypto_digest_update(tfm, sg, 1); + } + crypto_digest_final(tfm, out); + + end = get_cycles(); + + cycles += end - start; + } + + local_irq_enable(); + local_bh_enable(); + + printk("%6lu cycles/operation, %4lu cycles/byte\n", + cycles / 8, cycles / (8 * blen)); + + return; +} + +static void test_digest_speed(char *algo, unsigned int sec, + struct digest_speed *speed) +{ + struct crypto_tfm *tfm; + char output[1024]; + int i; + + printk("\ntesting speed of %s\n", algo); + + tfm = crypto_alloc_tfm(algo, 0); + + if (tfm == NULL) { + printk("failed to load transform for %s\n", algo); + return; + } + + if (crypto_tfm_alg_digestsize(tfm) > sizeof(output)) { + printk("digestsize(%u) > outputbuffer(%zu)\n", + crypto_tfm_alg_digestsize(tfm), sizeof(output)); + goto out; + } + + for (i = 0; speed[i].blen != 0; i++) { + if (speed[i].blen > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", + speed[i].blen, TVMEMSIZE); + goto out; + } + + printk("test%3u (%5u byte blocks,%5u bytes per update,%4u updates): ", + i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen); + + memset(tvmem, 0xff, speed[i].blen); + + if (sec) + test_digest_jiffies(tfm, tvmem, speed[i].blen, speed[i].plen, output, sec); + else + test_digest_cycles(tfm, tvmem, speed[i].blen, speed[i].plen, output); + } + +out: + crypto_free_tfm(tfm); +} + static void test_deflate(void) { unsigned int i; @@ -1086,6 +1202,60 @@ #endif des_speed_template); break; + case 300: + /* fall through */ + + case 301: + test_digest_speed("md4", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 302: + test_digest_speed("md5", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 303: + test_digest_speed("sha1", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 304: + test_digest_speed("sha256", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 305: + test_digest_speed("sha384", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 306: + test_digest_speed("sha512", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 307: + test_digest_speed("wp256", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 308: + test_digest_speed("wp384", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 309: + test_digest_speed("wp512", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 310: + test_digest_speed("tgr128", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 311: + test_digest_speed("tgr160", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 312: + test_digest_speed("tgr192", sec, generic_digest_speed_template); + if (mode > 300 && mode < 400) break; + + case 399: + break; + case 1000: test_available(); break; @@ -1113,7 +1283,14 @@ static int __init init(void) kfree(xbuf); kfree(tvmem); - return 0; + + /* We intentionaly return -EAGAIN to prevent keeping + * the module. It does all its work from init() + * and doesn't offer any runtime functionality + * => we don't need it in the memory, do we? + * -- mludvig + */ + return -EAGAIN; } /* diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h index 1f683ba..1fac560 100644 --- a/crypto/tcrypt.h +++ b/crypto/tcrypt.h @@ -65,6 +65,11 @@ struct cipher_speed { unsigned int blen; }; +struct digest_speed { + unsigned int blen; /* buffer length */ + unsigned int plen; /* per-update length */ +}; + /* * MD4 test vectors from RFC1320 */ @@ -2975,4 +2980,35 @@ static struct cipher_speed des_speed_tem { .klen = 0, .blen = 0, } }; +/* + * Digest speed tests + */ +static struct digest_speed generic_digest_speed_template[] = { + { .blen = 16, .plen = 16, }, + { .blen = 64, .plen = 16, }, + { .blen = 64, .plen = 64, }, + { .blen = 256, .plen = 16, }, + { .blen = 256, .plen = 64, }, + { .blen = 256, .plen = 256, }, + { .blen = 1024, .plen = 16, }, + { .blen = 1024, .plen = 256, }, + { .blen = 1024, .plen = 1024, }, + { .blen = 2048, .plen = 16, }, + { .blen = 2048, .plen = 256, }, + { .blen = 2048, .plen = 1024, }, + { .blen = 2048, .plen = 2048, }, + { .blen = 4096, .plen = 16, }, + { .blen = 4096, .plen = 256, }, + { .blen = 4096, .plen = 1024, }, + { .blen = 4096, .plen = 4096, }, + { .blen = 8192, .plen = 16, }, + { .blen = 8192, .plen = 256, }, + { .blen = 8192, .plen = 1024, }, + { .blen = 8192, .plen = 4096, }, + { .blen = 8192, .plen = 8192, }, + + /* End marker */ + { .blen = 0, .plen = 0, } +}; + #endif /* _CRYPTO_TCRYPT_H */ diff --git a/crypto/tea.c b/crypto/tea.c index a6a02b3..5367adc 100644 --- a/crypto/tea.c +++ b/crypto/tea.c @@ -45,10 +45,10 @@ struct xtea_ctx { u32 KEY[4]; }; -static int tea_setkey(void *ctx_arg, const u8 *in_key, - unsigned int key_len, u32 *flags) -{ - struct tea_ctx *ctx = ctx_arg; +static int tea_setkey(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len, u32 *flags) +{ + struct tea_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *key = (const __le32 *)in_key; if (key_len != 16) @@ -66,12 +66,11 @@ static int tea_setkey(void *ctx_arg, con } -static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) -{ +static void tea_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ u32 y, z, n, sum = 0; u32 k0, k1, k2, k3; - - struct tea_ctx *ctx = ctx_arg; + struct tea_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *in = (const __le32 *)src; __le32 *out = (__le32 *)dst; @@ -95,11 +94,11 @@ static void tea_encrypt(void *ctx_arg, u out[1] = cpu_to_le32(z); } -static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) -{ +static void tea_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ u32 y, z, n, sum; u32 k0, k1, k2, k3; - struct tea_ctx *ctx = ctx_arg; + struct tea_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *in = (const __le32 *)src; __le32 *out = (__le32 *)dst; @@ -125,10 +124,10 @@ static void tea_decrypt(void *ctx_arg, u out[1] = cpu_to_le32(z); } -static int xtea_setkey(void *ctx_arg, const u8 *in_key, - unsigned int key_len, u32 *flags) -{ - struct xtea_ctx *ctx = ctx_arg; +static int xtea_setkey(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len, u32 *flags) +{ + struct xtea_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *key = (const __le32 *)in_key; if (key_len != 16) @@ -146,12 +145,11 @@ static int xtea_setkey(void *ctx_arg, co } -static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) -{ +static void xtea_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ u32 y, z, sum = 0; u32 limit = XTEA_DELTA * XTEA_ROUNDS; - - struct xtea_ctx *ctx = ctx_arg; + struct xtea_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *in = (const __le32 *)src; __le32 *out = (__le32 *)dst; @@ -168,10 +166,10 @@ static void xtea_encrypt(void *ctx_arg, out[1] = cpu_to_le32(z); } -static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) -{ +static void xtea_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ u32 y, z, sum; - struct tea_ctx *ctx = ctx_arg; + struct tea_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *in = (const __le32 *)src; __le32 *out = (__le32 *)dst; @@ -191,12 +189,11 @@ static void xtea_decrypt(void *ctx_arg, } -static void xeta_encrypt(void *ctx_arg, u8 *dst, const u8 *src) -{ +static void xeta_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ u32 y, z, sum = 0; u32 limit = XTEA_DELTA * XTEA_ROUNDS; - - struct xtea_ctx *ctx = ctx_arg; + struct xtea_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *in = (const __le32 *)src; __le32 *out = (__le32 *)dst; @@ -213,10 +210,10 @@ static void xeta_encrypt(void *ctx_arg, out[1] = cpu_to_le32(z); } -static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src) -{ +static void xeta_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ u32 y, z, sum; - struct tea_ctx *ctx = ctx_arg; + struct tea_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *in = (const __le32 *)src; __le32 *out = (__le32 *)dst; diff --git a/crypto/tgr192.c b/crypto/tgr192.c index 2d8e44f..a0fadf3 100644 --- a/crypto/tgr192.c +++ b/crypto/tgr192.c @@ -496,11 +496,10 @@ static void tgr192_transform(struct tgr1 tctx->c = c; } -static void tgr192_init(void *ctx) +static void tgr192_init(struct crypto_tfm *tfm) { - struct tgr192_ctx *tctx = ctx; + struct tgr192_ctx *tctx = crypto_tfm_ctx(tfm); - memset (tctx->hash, 0, 64); tctx->a = 0x0123456789abcdefULL; tctx->b = 0xfedcba9876543210ULL; tctx->c = 0xf096a5b4c3b2e187ULL; @@ -511,9 +510,10 @@ static void tgr192_init(void *ctx) /* Update the message digest with the contents * of INBUF with length INLEN. */ -static void tgr192_update(void *ctx, const u8 * inbuf, unsigned int len) +static void tgr192_update(struct crypto_tfm *tfm, const u8 *inbuf, + unsigned int len) { - struct tgr192_ctx *tctx = ctx; + struct tgr192_ctx *tctx = crypto_tfm_ctx(tfm); if (tctx->count == 64) { /* flush the buffer */ tgr192_transform(tctx, tctx->hash); @@ -527,7 +527,7 @@ static void tgr192_update(void *ctx, con for (; len && tctx->count < 64; len--) { tctx->hash[tctx->count++] = *inbuf++; } - tgr192_update(tctx, NULL, 0); + tgr192_update(tfm, NULL, 0); if (!len) { return; } @@ -549,15 +549,15 @@ static void tgr192_update(void *ctx, con /* The routine terminates the computation */ -static void tgr192_final(void *ctx, u8 * out) +static void tgr192_final(struct crypto_tfm *tfm, u8 * out) { - struct tgr192_ctx *tctx = ctx; + struct tgr192_ctx *tctx = crypto_tfm_ctx(tfm); __be64 *dst = (__be64 *)out; __be64 *be64p; __le32 *le32p; u32 t, msb, lsb; - tgr192_update(tctx, NULL, 0); /* flush */ ; + tgr192_update(tfm, NULL, 0); /* flush */ ; msb = 0; t = tctx->nblocks; @@ -585,7 +585,7 @@ static void tgr192_final(void *ctx, u8 * while (tctx->count < 64) { tctx->hash[tctx->count++] = 0; } - tgr192_update(tctx, NULL, 0); /* flush */ ; + tgr192_update(tfm, NULL, 0); /* flush */ ; memset(tctx->hash, 0, 56); /* fill next block with zeroes */ } /* append the 64 bit count */ @@ -601,22 +601,20 @@ static void tgr192_final(void *ctx, u8 * dst[2] = be64p[2] = cpu_to_be64(tctx->c); } -static void tgr160_final(void *ctx, u8 * out) +static void tgr160_final(struct crypto_tfm *tfm, u8 * out) { - struct tgr192_ctx *wctx = ctx; u8 D[64]; - tgr192_final(wctx, D); + tgr192_final(tfm, D); memcpy(out, D, TGR160_DIGEST_SIZE); memset(D, 0, TGR192_DIGEST_SIZE); } -static void tgr128_final(void *ctx, u8 * out) +static void tgr128_final(struct crypto_tfm *tfm, u8 * out) { - struct tgr192_ctx *wctx = ctx; u8 D[64]; - tgr192_final(wctx, D); + tgr192_final(tfm, D); memcpy(out, D, TGR128_DIGEST_SIZE); memset(D, 0, TGR192_DIGEST_SIZE); } @@ -627,6 +625,7 @@ static struct crypto_alg tgr192 = { .cra_blocksize = TGR192_BLOCK_SIZE, .cra_ctxsize = sizeof(struct tgr192_ctx), .cra_module = THIS_MODULE, + .cra_alignmask = 7, .cra_list = LIST_HEAD_INIT(tgr192.cra_list), .cra_u = {.digest = { .dia_digestsize = TGR192_DIGEST_SIZE, @@ -641,6 +640,7 @@ static struct crypto_alg tgr160 = { .cra_blocksize = TGR192_BLOCK_SIZE, .cra_ctxsize = sizeof(struct tgr192_ctx), .cra_module = THIS_MODULE, + .cra_alignmask = 7, .cra_list = LIST_HEAD_INIT(tgr160.cra_list), .cra_u = {.digest = { .dia_digestsize = TGR160_DIGEST_SIZE, @@ -655,6 +655,7 @@ static struct crypto_alg tgr128 = { .cra_blocksize = TGR192_BLOCK_SIZE, .cra_ctxsize = sizeof(struct tgr192_ctx), .cra_module = THIS_MODULE, + .cra_alignmask = 7, .cra_list = LIST_HEAD_INIT(tgr128.cra_list), .cra_u = {.digest = { .dia_digestsize = TGR128_DIGEST_SIZE, diff --git a/crypto/twofish.c b/crypto/twofish.c index ddfd5a3..ec24882 100644 --- a/crypto/twofish.c +++ b/crypto/twofish.c @@ -643,11 +643,11 @@ struct twofish_ctx { }; /* Perform the key setup. */ -static int twofish_setkey(void *cx, const u8 *key, - unsigned int key_len, u32 *flags) +static int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int key_len, u32 *flags) { - struct twofish_ctx *ctx = cx; + struct twofish_ctx *ctx = crypto_tfm_ctx(tfm); int i, j, k; @@ -802,9 +802,9 @@ static int twofish_setkey(void *cx, cons } /* Encrypt one block. in and out may be the same. */ -static void twofish_encrypt(void *cx, u8 *out, const u8 *in) +static void twofish_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - struct twofish_ctx *ctx = cx; + struct twofish_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *src = (const __le32 *)in; __le32 *dst = (__le32 *)out; @@ -839,9 +839,9 @@ static void twofish_encrypt(void *cx, u8 } /* Decrypt one block. in and out may be the same. */ -static void twofish_decrypt(void *cx, u8 *out, const u8 *in) +static void twofish_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - struct twofish_ctx *ctx = cx; + struct twofish_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *src = (const __le32 *)in; __le32 *dst = (__le32 *)out; diff --git a/crypto/wp512.c b/crypto/wp512.c index b226a12..727d05a 100644 --- a/crypto/wp512.c +++ b/crypto/wp512.c @@ -981,9 +981,9 @@ static void wp512_process_buffer(struct } -static void wp512_init (void *ctx) { +static void wp512_init(struct crypto_tfm *tfm) { + struct wp512_ctx *wctx = crypto_tfm_ctx(tfm); int i; - struct wp512_ctx *wctx = ctx; memset(wctx->bitLength, 0, 32); wctx->bufferBits = wctx->bufferPos = 0; @@ -993,10 +993,10 @@ static void wp512_init (void *ctx) { } } -static void wp512_update(void *ctx, const u8 *source, unsigned int len) +static void wp512_update(struct crypto_tfm *tfm, const u8 *source, + unsigned int len) { - - struct wp512_ctx *wctx = ctx; + struct wp512_ctx *wctx = crypto_tfm_ctx(tfm); int sourcePos = 0; unsigned int bits_len = len * 8; // convert to number of bits int sourceGap = (8 - ((int)bits_len & 7)) & 7; @@ -1054,9 +1054,9 @@ static void wp512_update(void *ctx, cons } -static void wp512_final(void *ctx, u8 *out) +static void wp512_final(struct crypto_tfm *tfm, u8 *out) { - struct wp512_ctx *wctx = ctx; + struct wp512_ctx *wctx = crypto_tfm_ctx(tfm); int i; u8 *buffer = wctx->buffer; u8 *bitLength = wctx->bitLength; @@ -1087,22 +1087,20 @@ static void wp512_final(void *ctx, u8 *o wctx->bufferPos = bufferPos; } -static void wp384_final(void *ctx, u8 *out) +static void wp384_final(struct crypto_tfm *tfm, u8 *out) { - struct wp512_ctx *wctx = ctx; u8 D[64]; - wp512_final (wctx, D); + wp512_final(tfm, D); memcpy (out, D, WP384_DIGEST_SIZE); memset (D, 0, WP512_DIGEST_SIZE); } -static void wp256_final(void *ctx, u8 *out) +static void wp256_final(struct crypto_tfm *tfm, u8 *out) { - struct wp512_ctx *wctx = ctx; u8 D[64]; - wp512_final (wctx, D); + wp512_final(tfm, D); memcpy (out, D, WP256_DIGEST_SIZE); memset (D, 0, WP512_DIGEST_SIZE); } diff --git a/drivers/Kconfig b/drivers/Kconfig index aeb5ab2..8b11ceb 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -72,4 +72,6 @@ source "drivers/edac/Kconfig" source "drivers/rtc/Kconfig" +source "drivers/dma/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 447d8e6..fc2d744 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -74,3 +74,5 @@ obj-$(CONFIG_SGI_SN) += sn/ obj-y += firmware/ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ +obj-$(CONFIG_GENERIC_TIME) += clocksource/ +obj-$(CONFIG_DMA_ENGINE) += dma/ diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index c24652d..94b8d82 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -10,9 +10,8 @@ menu "ACPI (Advanced Configuration and P config ACPI bool "ACPI Support" depends on IA64 || X86 + depends on PCI select PM - select PCI - default y ---help--- Advanced Configuration and Power Interface (ACPI) support for @@ -162,7 +161,7 @@ config ACPI_THERMAL config ACPI_NUMA bool "NUMA support" depends on NUMA - depends on (IA64 || X86_64) + depends on (X86 || IA64) default y if IA64_GENERIC || IA64_SGI_SN2 config ACPI_ASUS diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index d882bf8..e0a95ba 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -74,7 +74,7 @@ struct acpi_memory_device { unsigned short caching; /* memory cache attribute */ unsigned short write_protect; /* memory read/write attribute */ u64 start_addr; /* Memory Range start physical addr */ - u64 end_addr; /* Memory Range end physical addr */ + u64 length; /* Memory Range length */ }; static int @@ -97,12 +97,11 @@ acpi_memory_get_device_resources(struct if (ACPI_SUCCESS(status)) { if (address64.resource_type == ACPI_MEMORY_RANGE) { /* Populate the structure */ - mem_device->caching = - address64.info.mem.caching; + mem_device->caching = address64.info.mem.caching; mem_device->write_protect = address64.info.mem.write_protect; mem_device->start_addr = address64.minimum; - mem_device->end_addr = address64.maximum; + mem_device->length = address64.address_length; } } @@ -199,8 +198,7 @@ static int acpi_memory_enable_device(str * Tell the VM there is more memory here... * Note: Assume that this function returns zero on success */ - result = add_memory(mem_device->start_addr, - (mem_device->end_addr - mem_device->start_addr) + 1); + result = add_memory(mem_device->start_addr, mem_device->length); if (result) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "\nadd_memory failed\n")); mem_device->state = MEMORY_INVALID_STATE; @@ -249,7 +247,7 @@ static int acpi_memory_disable_device(st { int result; u64 start = mem_device->start_addr; - u64 len = mem_device->end_addr - start + 1; + u64 len = mem_device->length; ACPI_FUNCTION_TRACE("acpi_memory_disable_device"); diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index f4c8775..839f423 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -817,7 +817,7 @@ typedef int (proc_writefunc) (struct fil unsigned long count, void *data); static int -__init asus_proc_add(char *name, proc_writefunc * writefunc, +asus_proc_add(char *name, proc_writefunc * writefunc, proc_readfunc * readfunc, mode_t mode, struct acpi_device *device) { @@ -836,7 +836,7 @@ __init asus_proc_add(char *name, proc_wr return 0; } -static int __init asus_hotk_add_fs(struct acpi_device *device) +static int asus_hotk_add_fs(struct acpi_device *device) { struct proc_dir_entry *proc; mode_t mode; @@ -954,7 +954,7 @@ static void asus_hotk_notify(acpi_handle * This function is used to initialize the hotk with right values. In this * method, we can make all the detection we want, and modify the hotk struct */ -static int __init asus_hotk_get_info(void) +static int asus_hotk_get_info(void) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -970,7 +970,7 @@ static int __init asus_hotk_get_info(voi * HID), this bit will be moved. A global variable asus_info contains * the DSDT header. */ - status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt); + status = acpi_get_table(ACPI_TABLE_ID_DSDT, 1, &dsdt); if (ACPI_FAILURE(status)) printk(KERN_WARNING " Couldn't get the DSDT table header\n"); else @@ -1101,7 +1101,7 @@ static int __init asus_hotk_get_info(voi return AE_OK; } -static int __init asus_hotk_check(void) +static int asus_hotk_check(void) { int result = 0; @@ -1119,7 +1119,9 @@ static int __init asus_hotk_check(void) return result; } -static int __init asus_hotk_add(struct acpi_device *device) +static int asus_hotk_found; + +static int asus_hotk_add(struct acpi_device *device) { acpi_status status = AE_OK; int result; @@ -1180,6 +1182,8 @@ static int __init asus_hotk_add(struct a } } + asus_hotk_found = 1; + end: if (result) { kfree(hotk); @@ -1226,12 +1230,24 @@ static int __init asus_acpi_init(void) asus_proc_dir->owner = THIS_MODULE; result = acpi_bus_register_driver(&asus_hotk_driver); - if (result < 1) { - acpi_bus_unregister_driver(&asus_hotk_driver); + if (result < 0) { remove_proc_entry(PROC_ASUS, acpi_root_dir); return -ENODEV; } + /* + * This is a bit of a kludge. We only want this module loaded + * for ASUS systems, but there's currently no way to probe the + * ACPI namespace for ASUS HIDs. So we just return failure if + * we didn't find one, which will cause the module to be + * unloaded. + */ + if (!asus_hotk_found) { + acpi_bus_unregister_driver(&asus_hotk_driver); + remove_proc_entry(PROC_ASUS, acpi_root_dir); + return result; + } + return 0; } diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 606f873..dd3983c 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -43,7 +43,7 @@ #ifdef CONFIG_X86 extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger); #endif -FADT_DESCRIPTOR acpi_fadt; +struct fadt_descriptor acpi_fadt; EXPORT_SYMBOL(acpi_fadt); struct acpi_device *acpi_root; @@ -205,12 +205,14 @@ int acpi_bus_set_power(acpi_handle handl * Get device's current power state if it's unknown * This means device power state isn't initialized or previous setting failed */ - if (device->power.state == ACPI_STATE_UNKNOWN) - acpi_bus_get_power(device->handle, &device->power.state); - if (state == device->power.state) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", - state)); - return_VALUE(0); + if (!device->flags.force_power_state) { + if (device->power.state == ACPI_STATE_UNKNOWN) + acpi_bus_get_power(device->handle, &device->power.state); + if (state == device->power.state) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", + state)); + return_VALUE(0); + } } if (!device->power.states[state].flags.valid) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n", @@ -596,6 +598,8 @@ void __init acpi_early_init(void) if (acpi_disabled) return_VOID; + printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); + /* enable workarounds, unless strict ACPI spec. compliance */ if (!acpi_strict) acpi_gbl_enable_interpreter_slack = TRUE; @@ -617,7 +621,7 @@ void __init acpi_early_init(void) /* * Get a separate copy of the FADT for use by other drivers. */ - status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer); + status = acpi_get_table(ACPI_TABLE_ID_FADT, 1, &buffer); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to get the FADT\n"); goto error0; @@ -743,8 +747,6 @@ static int __init acpi_init(void) ACPI_FUNCTION_TRACE("acpi_init"); - printk(KERN_INFO PREFIX "Subsystem revision %08x\n", ACPI_CA_VERSION); - if (acpi_disabled) { printk(KERN_INFO PREFIX "Interpreter disabled.\n"); return_VALUE(-ENODEV); diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index 76bc046..a6d77ef 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -87,7 +87,7 @@ acpi_ds_create_buffer_field(union acpi_p union acpi_operand_object *second_desc = NULL; u32 flags; - ACPI_FUNCTION_TRACE("ds_create_buffer_field"); + ACPI_FUNCTION_TRACE(ds_create_buffer_field); /* Get the name_string argument */ @@ -210,7 +210,7 @@ acpi_ds_get_field_names(struct acpi_crea acpi_status status; acpi_integer position; - ACPI_FUNCTION_TRACE_PTR("ds_get_field_names", info); + ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); /* First field starts at bit zero */ @@ -342,7 +342,7 @@ acpi_ds_create_field(union acpi_parse_ob union acpi_parse_object *arg; struct acpi_create_field_info info; - ACPI_FUNCTION_TRACE_PTR("ds_create_field", op); + ACPI_FUNCTION_TRACE_PTR(ds_create_field, op); /* First arg is the name of the parent op_region (must already exist) */ @@ -399,7 +399,7 @@ acpi_ds_init_field_objects(union acpi_pa struct acpi_namespace_node *node; u8 type = 0; - ACPI_FUNCTION_TRACE_PTR("ds_init_field_objects", op); + ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); switch (walk_state->opcode) { case AML_FIELD_OP: @@ -425,6 +425,7 @@ acpi_ds_init_field_objects(union acpi_pa * Walk the list of entries in the field_list */ while (arg) { + /* Ignore OFFSET and ACCESSAS terms here */ if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { @@ -481,7 +482,7 @@ acpi_ds_create_bank_field(union acpi_par union acpi_parse_object *arg; struct acpi_create_field_info info; - ACPI_FUNCTION_TRACE_PTR("ds_create_bank_field", op); + ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op); /* First arg is the name of the parent op_region (must already exist) */ @@ -554,7 +555,7 @@ acpi_ds_create_index_field(union acpi_pa union acpi_parse_object *arg; struct acpi_create_field_info info; - ACPI_FUNCTION_TRACE_PTR("ds_create_index_field", op); + ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op); /* First arg is the name of the Index register (must already exist) */ diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c index e65a07a..bbdf990 100644 --- a/drivers/acpi/dispatcher/dsinit.c +++ b/drivers/acpi/dispatcher/dsinit.c @@ -184,7 +184,7 @@ #endif * * RETURN: Status * - * DESCRIPTION: Walk the namespace starting at "start_node" and perform any + * DESCRIPTION: Walk the namespace starting at "StartNode" and perform any * necessary initialization on the objects found therein * ******************************************************************************/ @@ -196,7 +196,7 @@ acpi_ds_initialize_objects(struct acpi_t acpi_status status; struct acpi_init_walk_info info; - ACPI_FUNCTION_TRACE("ds_initialize_objects"); + ACPI_FUNCTION_TRACE(ds_initialize_objects); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "**** Starting initialization of namespace objects ****\n")); @@ -213,7 +213,7 @@ acpi_ds_initialize_objects(struct acpi_t status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, acpi_ds_init_one_object, &info, NULL); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace")); + ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index c475546..bc9aca4 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -81,6 +81,7 @@ acpi_ds_method_error(acpi_status status, /* Invoke the global exception handler */ if (acpi_gbl_exception_handler) { + /* Exit the interpreter, allow handler to execute methods */ acpi_ex_exit_interpreter(); @@ -100,6 +101,7 @@ acpi_ds_method_error(acpi_status status, } #ifdef ACPI_DISASSEMBLER if (ACPI_FAILURE(status)) { + /* Display method locals/args if disassembler is present */ acpi_dm_dump_method_info(status, walk_state, walk_state->op); @@ -132,7 +134,7 @@ acpi_ds_begin_method_execution(struct ac { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ds_begin_method_execution", method_node); + ACPI_FUNCTION_TRACE_PTR(ds_begin_method_execution, method_node); if (!method_node) { return_ACPI_STATUS(AE_NULL_ENTRY); @@ -168,11 +170,14 @@ acpi_ds_begin_method_execution(struct ac /* * Get a unit from the method semaphore. This releases the - * interpreter if we block + * interpreter if we block (then reacquires it) */ status = acpi_ex_system_wait_semaphore(obj_desc->method.semaphore, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } } /* @@ -183,7 +188,7 @@ acpi_ds_begin_method_execution(struct ac if (!obj_desc->method.owner_id) { status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto cleanup; } } @@ -193,6 +198,14 @@ acpi_ds_begin_method_execution(struct ac */ obj_desc->method.thread_count++; return_ACPI_STATUS(status); + + cleanup: + /* On error, must signal the method semaphore if present */ + + if (obj_desc->method.semaphore) { + (void)acpi_os_signal_semaphore(obj_desc->method.semaphore, 1); + } + return_ACPI_STATUS(status); } /******************************************************************************* @@ -218,10 +231,10 @@ acpi_ds_call_control_method(struct acpi_ struct acpi_namespace_node *method_node; struct acpi_walk_state *next_walk_state = NULL; union acpi_operand_object *obj_desc; - struct acpi_parameter_info info; + struct acpi_evaluate_info *info; u32 i; - ACPI_FUNCTION_TRACE_PTR("ds_call_control_method", this_walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n", @@ -240,25 +253,31 @@ acpi_ds_call_control_method(struct acpi_ return_ACPI_STATUS(AE_NULL_OBJECT); } - /* Init for new method, wait on concurrency semaphore */ + /* Init for new method, possibly wait on concurrency semaphore */ status = acpi_ds_begin_method_execution(method_node, obj_desc, this_walk_state->method_node); if (ACPI_FAILURE(status)) { - goto cleanup; + return_ACPI_STATUS(status); } + /* + * 1) Parse the method. All "normal" methods are parsed for each execution. + * Internal methods (_OSI, etc.) do not require parsing. + */ if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { - /* 1) Parse: Create a new walk state for the preempting walk */ + + /* Create a new walk state for the parse */ next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, op, obj_desc, NULL); if (!next_walk_state) { - return_ACPI_STATUS(AE_NO_MEMORY); + status = AE_NO_MEMORY; + goto cleanup; } - /* Create and init a Root Node */ + /* Create and init a parse tree root */ op = acpi_ps_create_scope_op(); if (!op) { @@ -271,17 +290,20 @@ acpi_ds_call_control_method(struct acpi_ obj_desc->method.aml_length, NULL, 1); if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(next_walk_state); + acpi_ps_delete_parse_tree(op); goto cleanup; } - /* Begin AML parse */ + /* Begin AML parse (deletes next_walk_state) */ status = acpi_ps_parse_aml(next_walk_state); acpi_ps_delete_parse_tree(op); + if (ACPI_FAILURE(status)) { + goto cleanup; + } } - /* 2) Execute: Create a new state for the preempting walk */ + /* 2) Begin method execution. Create a new walk state */ next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, obj_desc, thread); @@ -289,6 +311,7 @@ acpi_ds_call_control_method(struct acpi_ status = AE_NO_MEMORY; goto cleanup; } + /* * The resolved arguments were put on the previous walk state's operand * stack. Operands on the previous walk state stack always @@ -296,12 +319,24 @@ acpi_ds_call_control_method(struct acpi_ */ this_walk_state->operands[this_walk_state->num_operands] = NULL; - info.parameters = &this_walk_state->operands[0]; - info.parameter_type = ACPI_PARAM_ARGS; + /* + * Allocate and initialize the evaluation information block + * TBD: this is somewhat inefficient, should change interface to + * ds_init_aml_walk. For now, keeps this struct off the CPU stack + */ + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->parameters = &this_walk_state->operands[0]; + info->parameter_type = ACPI_PARAM_ARGS; status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node, obj_desc->method.aml_start, - obj_desc->method.aml_length, &info, 3); + obj_desc->method.aml_length, info, 3); + + ACPI_FREE(info); if (ACPI_FAILURE(status)) { goto cleanup; } @@ -323,6 +358,8 @@ acpi_ds_call_control_method(struct acpi_ "Starting nested execution, newstate=%p\n", next_walk_state)); + /* Invoke an internal method if necessary */ + if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { status = obj_desc->method.implementation(next_walk_state); } @@ -330,16 +367,14 @@ acpi_ds_call_control_method(struct acpi_ return_ACPI_STATUS(status); cleanup: - /* Decrement the thread count on the method parse tree */ - if (next_walk_state && (next_walk_state->method_desc)) { - next_walk_state->method_desc->method.thread_count--; - } + /* On error, we must terminate the method properly */ - /* On error, we must delete the new walk state */ + acpi_ds_terminate_control_method(obj_desc, next_walk_state); + if (next_walk_state) { + acpi_ds_delete_walk_state(next_walk_state); + } - acpi_ds_terminate_control_method(next_walk_state); - acpi_ds_delete_walk_state(next_walk_state); return_ACPI_STATUS(status); } @@ -362,25 +397,33 @@ acpi_ds_restart_control_method(struct ac union acpi_operand_object *return_desc) { acpi_status status; + int same_as_implicit_return; - ACPI_FUNCTION_TRACE_PTR("ds_restart_control_method", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "****Restart [%4.4s] Op %p return_value_from_callee %p\n", + "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n", (char *)&walk_state->method_node->name, walk_state->method_call_op, return_desc)); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - " return_from_this_method_used?=%X res_stack %p Walk %p\n", + " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n", walk_state->return_used, walk_state->results, walk_state)); /* Did the called method return a value? */ if (return_desc) { + + /* Is the implicit return object the same as the return desc? */ + + same_as_implicit_return = + (walk_state->implicit_return_obj == return_desc); + /* Are we actually going to use the return value? */ if (walk_state->return_used) { + /* Save the return value from the previous method */ status = acpi_ds_result_push(return_desc, walk_state); @@ -397,18 +440,23 @@ acpi_ds_restart_control_method(struct ac } /* - * The following code is the - * optional support for a so-called "implicit return". Some AML code - * assumes that the last value of the method is "implicitly" returned - * to the caller. Just save the last result as the return value. + * The following code is the optional support for the so-called + * "implicit return". Some AML code assumes that the last value of the + * method is "implicitly" returned to the caller, in the absence of an + * explicit return value. + * + * Just save the last result of the method as the return value. + * * NOTE: this is optional because the ASL language does not actually * support this behavior. */ else if (!acpi_ds_do_implicit_return - (return_desc, walk_state, FALSE)) { + (return_desc, walk_state, FALSE) + || same_as_implicit_return) { /* * Delete the return value if it will not be used by the - * calling method + * calling method or remove one reference if the explicit return + * is the same as the implicit return value. */ acpi_ut_remove_reference(return_desc); } @@ -421,7 +469,8 @@ acpi_ds_restart_control_method(struct ac * * FUNCTION: acpi_ds_terminate_control_method * - * PARAMETERS: walk_state - State of the method + * PARAMETERS: method_desc - Method object + * walk_state - State associated with the method * * RETURN: None * @@ -431,95 +480,100 @@ acpi_ds_restart_control_method(struct ac * ******************************************************************************/ -void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state) +void +acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, + struct acpi_walk_state *walk_state) { - union acpi_operand_object *obj_desc; struct acpi_namespace_node *method_node; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_terminate_control_method", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state); - if (!walk_state) { - return_VOID; - } + /* method_desc is required, walk_state is optional */ - /* The current method object was saved in the walk state */ - - obj_desc = walk_state->method_desc; - if (!obj_desc) { + if (!method_desc) { return_VOID; } - /* Delete all arguments and locals */ + if (walk_state) { - acpi_ds_method_data_delete_all(walk_state); + /* Delete all arguments and locals */ + + acpi_ds_method_data_delete_all(walk_state); + } /* * Lock the parser while we terminate this method. * If this is the last thread executing the method, * we have additional cleanup to perform */ - status = acpi_ut_acquire_mutex(ACPI_MTX_PARSER); + status = acpi_ut_acquire_mutex(ACPI_MTX_CONTROL_METHOD); if (ACPI_FAILURE(status)) { return_VOID; } /* Signal completion of the execution of this method if necessary */ - if (walk_state->method_desc->method.semaphore) { + if (method_desc->method.semaphore) { status = - acpi_os_signal_semaphore(walk_state->method_desc->method. - semaphore, 1); + acpi_os_signal_semaphore(method_desc->method.semaphore, 1); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not signal method semaphore")); - /* Ignore error and continue cleanup */ + /* Ignore error and continue */ + + ACPI_EXCEPTION((AE_INFO, status, + "Could not signal method semaphore")); } } - /* - * There are no more threads executing this method. Perform - * additional cleanup. - * - * The method Node is stored in the walk state - */ - method_node = walk_state->method_node; + if (walk_state) { + /* + * Delete any objects created by this method during execution. + * The method Node is stored in the walk state + */ + method_node = walk_state->method_node; - /* Lock namespace for possible update */ + /* Lock namespace for possible update */ - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto exit; - } + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; + } - /* - * Delete any namespace entries created immediately underneath - * the method - */ - if (method_node->child) { - acpi_ns_delete_namespace_subtree(method_node); + /* + * Delete any namespace entries created immediately underneath + * the method + */ + if (method_node && method_node->child) { + acpi_ns_delete_namespace_subtree(method_node); + } + + /* + * Delete any namespace entries created anywhere else within + * the namespace by the execution of this method + */ + acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id); + status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); } - /* - * Delete any namespace entries created anywhere else within - * the namespace by the execution of this method - */ - acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method. - owner_id); - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + /* Decrement the thread count on the method */ + + if (method_desc->method.thread_count) { + method_desc->method.thread_count--; + } else { + ACPI_ERROR((AE_INFO, "Invalid zero thread count in method")); + } /* Are there any other threads currently executing this method? */ - if (walk_state->method_desc->method.thread_count) { + if (method_desc->method.thread_count) { /* * Additional threads. Do not release the owner_id in this case, * we immediately reuse it for the next thread executing this method */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "*** Completed execution of one thread, %d threads remaining\n", - walk_state->method_desc->method. - thread_count)); + method_desc->method.thread_count)); } else { /* This is the only executing thread for this method */ @@ -533,22 +587,20 @@ void acpi_ds_terminate_control_method(st * This code is here because we must wait until the last thread exits * before creating the synchronization semaphore. */ - if ((walk_state->method_desc->method.concurrency == 1) && - (!walk_state->method_desc->method.semaphore)) { + if ((method_desc->method.concurrency == 1) && + (!method_desc->method.semaphore)) { status = acpi_os_create_semaphore(1, 1, - &walk_state-> - method_desc->method. + &method_desc->method. semaphore); } /* No more threads, we can free the owner_id */ - acpi_ut_release_owner_id(&walk_state->method_desc->method. - owner_id); + acpi_ut_release_owner_id(&method_desc->method.owner_id); } exit: - (void)acpi_ut_release_mutex(ACPI_MTX_PARSER); + (void)acpi_ut_release_mutex(ACPI_MTX_CONTROL_METHOD); return_VOID; } @@ -581,7 +633,7 @@ acpi_status acpi_ds_parse_method(struct union acpi_parse_object *op; struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node); + ACPI_FUNCTION_TRACE_PTR(ds_parse_method, node); /* Parameter Validation */ @@ -590,7 +642,7 @@ acpi_status acpi_ds_parse_method(struct } ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "**** Parsing [%4.4s] **** named_obj=%p\n", + "**** Parsing [%4.4s] **** NamedObj=%p\n", acpi_ut_get_node_name(node), node)); /* Extract the method object from the method Node */ @@ -669,7 +721,7 @@ acpi_status acpi_ds_parse_method(struct } ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", + "**** [%4.4s] Parsed **** NamedObj=%p Op=%p\n", acpi_ut_get_node_name(node), node, op)); /* diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index c025674..459160f 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -81,7 +81,7 @@ #endif * special data types. * * NOTES: walk_state fields are initialized to zero by the - * ACPI_MEM_CALLOCATE(). + * ACPI_ALLOCATE_ZEROED(). * * A pseudo-Namespace Node is assigned to each argument and local * so that ref_of() can return a pointer to the Node. @@ -92,7 +92,7 @@ void acpi_ds_method_data_init(struct acp { u32 i; - ACPI_FUNCTION_TRACE("ds_method_data_init"); + ACPI_FUNCTION_TRACE(ds_method_data_init); /* Init the method arguments */ @@ -100,10 +100,10 @@ void acpi_ds_method_data_init(struct acp ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name, NAMEOF_ARG_NTE); walk_state->arguments[i].name.integer |= (i << 24); - walk_state->arguments[i].descriptor = ACPI_DESC_TYPE_NAMED; + walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED; walk_state->arguments[i].type = ACPI_TYPE_ANY; - walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST | - ANOBJ_METHOD_ARG; + walk_state->arguments[i].flags = + ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG; } /* Init the method locals */ @@ -113,11 +113,11 @@ void acpi_ds_method_data_init(struct acp NAMEOF_LOCAL_NTE); walk_state->local_variables[i].name.integer |= (i << 24); - walk_state->local_variables[i].descriptor = + walk_state->local_variables[i].descriptor_type = ACPI_DESC_TYPE_NAMED; walk_state->local_variables[i].type = ACPI_TYPE_ANY; - walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST | - ANOBJ_METHOD_LOCAL; + walk_state->local_variables[i].flags = + ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL; } return_VOID; @@ -140,7 +140,7 @@ void acpi_ds_method_data_delete_all(stru { u32 index; - ACPI_FUNCTION_TRACE("ds_method_data_delete_all"); + ACPI_FUNCTION_TRACE(ds_method_data_delete_all); /* Detach the locals */ @@ -199,7 +199,7 @@ acpi_ds_method_data_init_args(union acpi acpi_status status; u32 index = 0; - ACPI_FUNCTION_TRACE_PTR("ds_method_data_init_args", params); + ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params); if (!params) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -251,7 +251,7 @@ acpi_ds_method_data_get_node(u16 opcode, struct acpi_walk_state *walk_state, struct acpi_namespace_node **node) { - ACPI_FUNCTION_TRACE("ds_method_data_get_node"); + ACPI_FUNCTION_TRACE(ds_method_data_get_node); /* * Method Locals and Arguments are supported @@ -318,10 +318,10 @@ acpi_ds_method_data_set_value(u16 opcode acpi_status status; struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE("ds_method_data_set_value"); + ACPI_FUNCTION_TRACE(ds_method_data_set_value); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "new_obj %p Opcode %X, Refs=%d [%s]\n", object, + "NewObj %p Opcode %X, Refs=%d [%s]\n", object, opcode, object->common.reference_count, acpi_ut_get_type_name(object->common.type))); @@ -336,7 +336,7 @@ acpi_ds_method_data_set_value(u16 opcode * Increment ref count so object can't be deleted while installed. * NOTE: We do not copy the object in order to preserve the call by * reference semantics of ACPI Control Method invocation. - * (See ACPI specification 2.0_c) + * (See ACPI Specification 2.0_c) */ acpi_ut_add_reference(object); @@ -351,7 +351,7 @@ acpi_ds_method_data_set_value(u16 opcode * FUNCTION: acpi_ds_method_data_get_value * * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP - * Index - which local_var or argument to get + * Index - Which local_var or argument to get * walk_state - Current walk state object * dest_desc - Where Arg or Local value is returned * @@ -372,7 +372,7 @@ acpi_ds_method_data_get_value(u16 opcode struct acpi_namespace_node *node; union acpi_operand_object *object; - ACPI_FUNCTION_TRACE("ds_method_data_get_value"); + ACPI_FUNCTION_TRACE(ds_method_data_get_value); /* Validate the object descriptor */ @@ -459,7 +459,7 @@ acpi_ds_method_data_get_value(u16 opcode * FUNCTION: acpi_ds_method_data_delete_value * * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP - * Index - which local_var or argument to delete + * Index - Which local_var or argument to delete * walk_state - Current walk state object * * RETURN: None @@ -477,7 +477,7 @@ acpi_ds_method_data_delete_value(u16 opc struct acpi_namespace_node *node; union acpi_operand_object *object; - ACPI_FUNCTION_TRACE("ds_method_data_delete_value"); + ACPI_FUNCTION_TRACE(ds_method_data_delete_value); /* Get the namespace node for the arg/local */ @@ -538,7 +538,7 @@ acpi_ds_store_object_to_local(u16 opcode union acpi_operand_object *current_obj_desc; union acpi_operand_object *new_obj_desc; - ACPI_FUNCTION_TRACE("ds_store_object_to_local"); + ACPI_FUNCTION_TRACE(ds_store_object_to_local); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n", opcode, index, obj_desc)); @@ -614,7 +614,7 @@ acpi_ds_store_object_to_local(u16 opcode && (current_obj_desc->reference.opcode == AML_REF_OF_OP)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Arg (%p) is an obj_ref(Node), storing in node %p\n", + "Arg (%p) is an ObjRef(Node), storing in node %p\n", new_obj_desc, current_obj_desc)); @@ -688,7 +688,7 @@ acpi_ds_method_data_get_type(u16 opcode, struct acpi_namespace_node *node; union acpi_operand_object *object; - ACPI_FUNCTION_TRACE("ds_method_data_get_type"); + ACPI_FUNCTION_TRACE(ds_method_data_get_type); /* Get the namespace node for the arg/local */ @@ -701,6 +701,7 @@ acpi_ds_method_data_get_type(u16 opcode, object = acpi_ns_get_attached_object(node); if (!object) { + /* Uninitialized local/arg, return TYPE_ANY */ return_VALUE(ACPI_TYPE_ANY); diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 8b21f0f..72190ab 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -81,7 +81,7 @@ acpi_ds_build_internal_object(struct acp union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("ds_build_internal_object"); + ACPI_FUNCTION_TRACE(ds_build_internal_object); *obj_desc_ptr = NULL; if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { @@ -103,6 +103,7 @@ acpi_ds_build_internal_object(struct acp common. node))); if (ACPI_FAILURE(status)) { + /* Check if we are resolving a named reference within a package */ if ((status == AE_NOT_FOUND) @@ -186,7 +187,7 @@ acpi_ds_build_internal_buffer_obj(struct union acpi_parse_object *byte_list; u32 byte_list_length = 0; - ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj"); + ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj); /* * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". @@ -195,6 +196,7 @@ acpi_ds_build_internal_buffer_obj(struct */ obj_desc = *obj_desc_ptr; if (!obj_desc) { + /* Create a new buffer object */ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); @@ -243,7 +245,7 @@ acpi_ds_build_internal_buffer_obj(struct "Buffer defined with zero length in AML, creating\n")); } else { obj_desc->buffer.pointer = - ACPI_MEM_CALLOCATE(obj_desc->buffer.length); + ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length); if (!obj_desc->buffer.pointer) { acpi_ut_delete_object_desc(obj_desc); return_ACPI_STATUS(AE_NO_MEMORY); @@ -291,7 +293,7 @@ acpi_ds_build_internal_package_obj(struc acpi_status status = AE_OK; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ds_build_internal_package_obj"); + ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); /* Find the parent of a possibly nested package */ @@ -339,9 +341,10 @@ acpi_ds_build_internal_package_obj(struc * individual objects). Add an extra pointer slot so * that the list is always null terminated. */ - obj_desc->package.elements = ACPI_MEM_CALLOCATE(((acpi_size) obj_desc-> - package.count + - 1) * sizeof(void *)); + obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) + obj_desc->package. + count + + 1) * sizeof(void *)); if (!obj_desc->package.elements) { acpi_ut_delete_object_desc(obj_desc); @@ -355,6 +358,7 @@ acpi_ds_build_internal_package_obj(struc arg = arg->common.next; for (i = 0; arg; i++) { if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { + /* Object (package or buffer) is already built */ obj_desc->package.elements[i] = @@ -396,7 +400,7 @@ acpi_ds_create_node(struct acpi_walk_sta acpi_status status; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE_PTR("ds_create_node", op); + ACPI_FUNCTION_TRACE_PTR(ds_create_node, op); /* * Because of the execution pass through the non-control-method @@ -408,6 +412,7 @@ acpi_ds_create_node(struct acpi_walk_sta } if (!op->common.value.arg) { + /* No arguments, there is nothing to do */ return_ACPI_STATUS(AE_OK); @@ -464,11 +469,12 @@ acpi_ds_init_object_from_op(struct acpi_ union acpi_operand_object *obj_desc; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ds_init_object_from_op"); + ACPI_FUNCTION_TRACE(ds_init_object_from_op); obj_desc = *ret_obj_desc; op_info = acpi_ps_get_opcode_info(opcode); if (op_info->class == AML_CLASS_UNKNOWN) { + /* Unknown opcode */ return_ACPI_STATUS(AE_TYPE); @@ -626,6 +632,7 @@ #endif default: /* Other literals, etc.. */ if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { + /* Node was saved in Op */ obj_desc->reference.node = op->common.node; diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index 6229c10..5b974a8 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c @@ -91,7 +91,7 @@ acpi_ds_execute_arguments(struct acpi_na union acpi_parse_object *op; struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE("ds_execute_arguments"); + ACPI_FUNCTION_TRACE(ds_execute_arguments); /* * Allocate a new parser op to be the root of the parsed tree @@ -193,7 +193,7 @@ acpi_ds_get_buffer_field_arguments(union struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_field_arguments", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return_ACPI_STATUS(AE_OK); @@ -206,7 +206,7 @@ acpi_ds_get_buffer_field_arguments(union ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_BUFFER_FIELD, node, NULL)); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] buffer_field Arg Init\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", acpi_ut_get_node_name(node))); /* Execute the AML code for the term_arg arguments */ @@ -235,7 +235,7 @@ acpi_status acpi_ds_get_buffer_arguments struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_arguments", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return_ACPI_STATUS(AE_OK); @@ -279,7 +279,7 @@ acpi_status acpi_ds_get_package_argument struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_get_package_arguments", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return_ACPI_STATUS(AE_OK); @@ -324,7 +324,7 @@ acpi_status acpi_ds_get_region_arguments acpi_status status; union acpi_operand_object *extra_desc; - ACPI_FUNCTION_TRACE_PTR("ds_get_region_arguments", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { return_ACPI_STATUS(AE_OK); @@ -342,8 +342,7 @@ acpi_status acpi_ds_get_region_arguments ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_REGION, node, NULL)); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[%4.4s] op_region Arg Init at AML %p\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", acpi_ut_get_node_name(node), extra_desc->extra.aml_start)); @@ -352,6 +351,28 @@ acpi_status acpi_ds_get_region_arguments status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), extra_desc->extra.aml_length, extra_desc->extra.aml_start); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Validate the region address/length via the host OS */ + + status = acpi_os_validate_address(obj_desc->region.space_id, + obj_desc->region.address, + (acpi_size) obj_desc->region.length); + if (ACPI_FAILURE(status)) { + /* + * Invalid address/length. We will emit an error message and mark + * the region as invalid, so that it will cause an additional error if + * it is ever used. Then return AE_OK. + */ + ACPI_EXCEPTION((AE_INFO, status, + "During address validation of OpRegion [%4.4s]", + node->name.ascii)); + obj_desc->common.flags |= AOPOBJ_INVALID; + status = AE_OK; + } + return_ACPI_STATUS(status); } @@ -411,7 +432,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode u8 field_flags; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_init_buffer_field", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc); /* Host object must be a Buffer */ @@ -457,7 +478,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode if (bit_count == 0) { ACPI_ERROR((AE_INFO, - "Attempt to create_field of length zero")); + "Attempt to CreateField of length zero")); status = AE_AML_OPERAND_VALUE; goto cleanup; } @@ -595,7 +616,7 @@ acpi_ds_eval_buffer_field_operands(struc struct acpi_namespace_node *node; union acpi_parse_object *next_op; - ACPI_FUNCTION_TRACE_PTR("ds_eval_buffer_field_operands", op); + ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op); /* * This is where we evaluate the address and length fields of the @@ -627,7 +648,7 @@ acpi_ds_eval_buffer_field_operands(struc ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, acpi_ps_get_opcode_name(op->common.aml_opcode), walk_state->num_operands, - "after acpi_ex_resolve_operands"); + "after AcpiExResolveOperands"); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)", @@ -640,6 +661,7 @@ acpi_ds_eval_buffer_field_operands(struc /* Initialize the Buffer Field */ if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { + /* NOTE: Slightly different operands for this opcode */ status = @@ -685,7 +707,7 @@ acpi_ds_eval_region_operands(struct acpi struct acpi_namespace_node *node; union acpi_parse_object *next_op; - ACPI_FUNCTION_TRACE_PTR("ds_eval_region_operands", op); + ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op); /* * This is where we evaluate the address and length fields of the @@ -718,7 +740,7 @@ acpi_ds_eval_region_operands(struct acpi ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, acpi_ps_get_opcode_name(op->common.aml_opcode), - 1, "after acpi_ex_resolve_operands"); + 1, "after AcpiExResolveOperands"); obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { @@ -744,7 +766,7 @@ acpi_ds_eval_region_operands(struct acpi operand_desc->integer.value; acpi_ut_remove_reference(operand_desc); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "rgn_obj %p Addr %8.8X%8.8X Len %X\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", obj_desc, ACPI_FORMAT_UINT64(obj_desc->region.address), obj_desc->region.length)); @@ -780,7 +802,7 @@ acpi_ds_eval_data_object_operands(struct union acpi_operand_object *arg_desc; u32 length; - ACPI_FUNCTION_TRACE("ds_eval_data_object_operands"); + ACPI_FUNCTION_TRACE(ds_eval_data_object_operands); /* The first operand (for all of these data objects) is the length */ @@ -874,7 +896,7 @@ acpi_ds_exec_begin_control_op(struct acp acpi_status status = AE_OK; union acpi_generic_state *control_state; - ACPI_FUNCTION_NAME("ds_exec_begin_control_op"); + ACPI_FUNCTION_NAME(ds_exec_begin_control_op); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, op->common.aml_opcode, walk_state)); @@ -952,7 +974,7 @@ acpi_ds_exec_end_control_op(struct acpi_ acpi_status status = AE_OK; union acpi_generic_state *control_state; - ACPI_FUNCTION_NAME("ds_exec_end_control_op"); + ACPI_FUNCTION_NAME(ds_exec_end_control_op); switch (op->common.aml_opcode) { case AML_IF_OP: @@ -984,6 +1006,7 @@ acpi_ds_exec_end_control_op(struct acpi_ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); if (walk_state->control_state->common.value) { + /* Predicate was true, go back and evaluate it again! */ status = AE_CTRL_PENDING; @@ -1014,6 +1037,7 @@ acpi_ds_exec_end_control_op(struct acpi_ * has been bubbled up the tree */ if (op->common.value.arg) { + /* Since we have a real Return(), delete any implicit return */ acpi_ds_clear_implicit_return(walk_state); @@ -1047,6 +1071,7 @@ acpi_ds_exec_end_control_op(struct acpi_ walk_state->return_desc = walk_state->operands[0]; } else if ((walk_state->results) && (walk_state->results->results.num_results > 0)) { + /* Since we have a real Return(), delete any implicit return */ acpi_ds_clear_implicit_return(walk_state); @@ -1095,7 +1120,7 @@ acpi_ds_exec_end_control_op(struct acpi_ } ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Completed RETURN_OP State=%p, ret_val=%p\n", + "Completed RETURN_OP State=%p, RetVal=%p\n", walk_state, walk_state->return_desc)); /* End the control method execution right now */ diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 53356a5..05230ba 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -68,7 +68,7 @@ ACPI_MODULE_NAME("dsutils") ******************************************************************************/ void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state) { - ACPI_FUNCTION_NAME("ds_clear_implicit_return"); + ACPI_FUNCTION_NAME(ds_clear_implicit_return); /* * Slack must be enabled for this feature @@ -115,7 +115,7 @@ u8 acpi_ds_do_implicit_return(union acpi_operand_object *return_desc, struct acpi_walk_state *walk_state, u8 add_reference) { - ACPI_FUNCTION_NAME("ds_do_implicit_return"); + ACPI_FUNCTION_NAME(ds_do_implicit_return); /* * Slack must be enabled for this feature, and we must @@ -171,7 +171,7 @@ acpi_ds_is_result_used(union acpi_parse_ { const struct acpi_opcode_info *parent_info; - ACPI_FUNCTION_TRACE_PTR("ds_is_result_used", op); + ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op); /* Must have both an Op and a Result Object */ @@ -202,6 +202,7 @@ acpi_ds_is_result_used(union acpi_parse_ */ if ((!op->common.parent) || (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) { + /* No parent, the return value cannot possibly be used */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, @@ -340,7 +341,7 @@ acpi_ds_delete_result_if_not_used(union union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ds_delete_result_if_not_used", result_obj); + ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj); if (!op) { ACPI_ERROR((AE_INFO, "Null Op")); @@ -352,6 +353,7 @@ acpi_ds_delete_result_if_not_used(union } if (!acpi_ds_is_result_used(op, walk_state)) { + /* Must pop the result stack (obj_desc should be equal to result_obj) */ status = acpi_ds_result_pop(&obj_desc, walk_state); @@ -382,7 +384,7 @@ acpi_status acpi_ds_resolve_operands(str u32 i; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ds_resolve_operands", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state); /* * Attempt to resolve each of the valid operands @@ -417,7 +419,7 @@ void acpi_ds_clear_operands(struct acpi_ { u32 i; - ACPI_FUNCTION_TRACE_PTR("ds_clear_operands", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state); /* Remove a reference on each operand on the stack */ @@ -465,7 +467,7 @@ acpi_ds_create_operand(struct acpi_walk_ acpi_interpreter_mode interpreter_mode; const struct acpi_opcode_info *op_info; - ACPI_FUNCTION_TRACE_PTR("ds_create_operand", arg); + ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg); /* A valid name must be looked up in the namespace */ @@ -498,7 +500,9 @@ acpi_ds_create_operand(struct acpi_walk_ */ if ((walk_state->deferred_node) && (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) - && (arg_index != 0)) { + && (arg_index == + (u32) ((walk_state->opcode == + AML_CREATE_FIELD_OP) ? 3 : 2))) { obj_desc = ACPI_CAST_PTR(union acpi_operand_object, walk_state->deferred_node); @@ -521,6 +525,7 @@ acpi_ds_create_operand(struct acpi_walk_ && (parent_op->common.aml_opcode != AML_REGION_OP) && (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) { + /* Enter name into namespace if not found */ interpreter_mode = ACPI_IMODE_LOAD_PASS2; @@ -572,7 +577,7 @@ acpi_ds_create_operand(struct acpi_walk_ /* Free the namestring created above */ - ACPI_MEM_FREE(name_string); + ACPI_FREE(name_string); /* Check status from the lookup */ @@ -696,7 +701,7 @@ acpi_ds_create_operands(struct acpi_walk union acpi_parse_object *arg; u32 arg_count = 0; - ACPI_FUNCTION_TRACE_PTR("ds_create_operands", first_arg); + ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); /* For all arguments in the list... */ diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index f1af655..3acbd91 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -49,7 +49,6 @@ #include #include #include #include -#include #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dswexec") @@ -93,7 +92,7 @@ acpi_ds_get_predicate_value(struct acpi_ union acpi_operand_object *obj_desc; union acpi_operand_object *local_obj_desc = NULL; - ACPI_FUNCTION_TRACE_PTR("ds_get_predicate_value", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state); walk_state->control_state->common.state = 0; @@ -123,7 +122,7 @@ acpi_ds_get_predicate_value(struct acpi_ if (!obj_desc) { ACPI_ERROR((AE_INFO, - "No predicate obj_desc=%p State=%p", + "No predicate ObjDesc=%p State=%p", obj_desc, walk_state)); return_ACPI_STATUS(AE_AML_NO_OPERAND); @@ -140,7 +139,7 @@ acpi_ds_get_predicate_value(struct acpi_ if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, - "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X", + "Bad predicate (not an integer) ObjDesc=%p State=%p Type=%X", obj_desc, walk_state, ACPI_GET_OBJECT_TYPE(obj_desc))); @@ -214,7 +213,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_s acpi_status status = AE_OK; u32 opcode_class; - ACPI_FUNCTION_TRACE_PTR("ds_exec_begin_op", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state); op = walk_state->op; if (!op) { @@ -296,7 +295,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_s case AML_CLASS_NAMED_OBJECT: - if (walk_state->walk_type == ACPI_WALK_METHOD) { + if (walk_state->walk_type & ACPI_WALK_METHOD) { /* * Found a named object declaration during method execution; * we must enter this object into the namespace. The created @@ -354,7 +353,7 @@ acpi_status acpi_ds_exec_end_op(struct a union acpi_parse_object *next_op; union acpi_parse_object *first_arg; - ACPI_FUNCTION_TRACE_PTR("ds_exec_end_op", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state); op = walk_state->op; op_type = walk_state->op_info->type; @@ -409,6 +408,7 @@ acpi_status acpi_ds_exec_end_op(struct a * being the object_type and size_of operators. */ if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) { + /* Resolve all operands */ status = acpi_ex_resolve_operands(walk_state->opcode, @@ -423,7 +423,7 @@ acpi_status acpi_ds_exec_end_op(struct a acpi_ps_get_opcode_name (walk_state->opcode), walk_state->num_operands, - "after ex_resolve_operands"); + "after ExResolveOperands"); } } @@ -437,7 +437,7 @@ acpi_status acpi_ds_exec_end_op(struct a acpi_gbl_op_type_dispatch[op_type] (walk_state); } else { /* - * Treat constructs of the form "Store(local_x,local_x)" as noops when the + * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the * Local is uninitialized. */ if ((status == AE_AML_UNINITIALIZED_LOCAL) && @@ -548,6 +548,7 @@ acpi_status acpi_ds_exec_end_op(struct a */ status = acpi_ds_resolve_operands(walk_state); if (ACPI_FAILURE(status)) { + /* On error, clear all resolved operands */ acpi_ds_clear_operands(walk_state); @@ -569,7 +570,7 @@ acpi_status acpi_ds_exec_end_op(struct a case AML_TYPE_CREATE_FIELD: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Executing create_field Buffer/Index Op=%p\n", + "Executing CreateField Buffer/Index Op=%p\n", op)); status = acpi_ds_load2_end_op(walk_state); @@ -584,7 +585,7 @@ acpi_status acpi_ds_exec_end_op(struct a case AML_TYPE_CREATE_OBJECT: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Executing create_object (Buffer/Package) Op=%p\n", + "Executing CreateObject (Buffer/Package) Op=%p\n", op)); switch (op->common.parent->common.aml_opcode) { @@ -657,7 +658,7 @@ acpi_status acpi_ds_exec_end_op(struct a if (op->common.aml_opcode == AML_REGION_OP) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Executing op_region Address/Length Op=%p\n", + "Executing OpRegion Address/Length Op=%p\n", op)); status = @@ -722,6 +723,7 @@ acpi_status acpi_ds_exec_end_op(struct a cleanup: if (walk_state->result_obj) { + /* Break to debugger to display result */ ACPI_DEBUGGER_EXEC(acpi_db_display_result_object diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index d3d24da..3507439 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -127,7 +127,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_ char *path; u32 flags; - ACPI_FUNCTION_TRACE("ds_load1_begin_op"); + ACPI_FUNCTION_TRACE(ds_load1_begin_op); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, @@ -178,12 +178,12 @@ #ifdef ACPI_ASL_COMPILER * Target of Scope() not found. Generate an External for it, and * insert the name into the namespace. */ - acpi_dm_add_to_external_list(path); + acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0); status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, walk_state, - &(node)); + &node); } #endif if (ACPI_FAILURE(status)) { @@ -261,6 +261,7 @@ #endif */ if (walk_state->deferred_node) { + /* This name is already in the namespace, get the node */ node = walk_state->deferred_node; @@ -300,10 +301,41 @@ #endif status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, flags, walk_state, - &(node)); + &node); if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(path, status); - return_ACPI_STATUS(status); + if (status == AE_ALREADY_EXISTS) { + + /* The name already exists in this scope */ + + if (node->flags & ANOBJ_IS_EXTERNAL) { + /* + * Allow one create on an object or segment that was + * previously declared External + */ + node->flags &= ~ANOBJ_IS_EXTERNAL; + node->type = (u8) object_type; + + /* Just retyped a node, probably will need to open a scope */ + + if (acpi_ns_opens_scope(object_type)) { + status = + acpi_ds_scope_stack_push + (node, object_type, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS + (status); + } + } + status = AE_OK; + } + } + + if (ACPI_FAILURE(status)) { + + ACPI_ERROR_NAMESPACE(path, status); + return_ACPI_STATUS(status); + } } break; } @@ -311,6 +343,7 @@ #endif /* Common exit */ if (!op) { + /* Create a new op */ op = acpi_ps_alloc_op(walk_state->opcode); @@ -359,7 +392,7 @@ acpi_status acpi_ds_load1_end_op(struct acpi_object_type object_type; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ds_load1_end_op"); + ACPI_FUNCTION_TRACE(ds_load1_end_op); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, @@ -413,6 +446,7 @@ #ifndef ACPI_NO_METHOD_EXECUTION #endif if (op->common.aml_opcode == AML_NAME_OP) { + /* For Name opcode, get the object type from the argument */ if (op->common.value.arg) { @@ -445,7 +479,7 @@ #endif * arguments.) */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "LOADING-Method: State=%p Op=%p named_obj=%p\n", + "LOADING-Method: State=%p Op=%p NamedObj=%p\n", walk_state, op, op->named.node)); if (!acpi_ns_get_attached_object(op->named.node)) { @@ -511,7 +545,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_ acpi_object_type object_type; char *buffer_ptr; - ACPI_FUNCTION_TRACE("ds_load2_begin_op"); + ACPI_FUNCTION_TRACE(ds_load2_begin_op); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, @@ -521,6 +555,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_ if ((walk_state->control_state) && (walk_state->control_state->common.state == ACPI_CONTROL_CONDITIONAL_EXECUTING)) { + /* We are executing a while loop outside of a method */ status = acpi_ds_exec_begin_op(walk_state, out_op); @@ -554,10 +589,12 @@ #endif /* Get the name we are going to enter or lookup in the namespace */ if (walk_state->opcode == AML_INT_NAMEPATH_OP) { + /* For Namepath op, get the path string */ buffer_ptr = op->common.value.string; if (!buffer_ptr) { + /* No name, just exit */ return_ACPI_STATUS(AE_OK); @@ -680,6 +717,7 @@ #endif /* All other opcodes */ if (op && op->common.node) { + /* This op/node was previously entered into the namespace */ node = op->common.node; @@ -705,6 +743,7 @@ #endif * Note: Name may already exist if we are executing a deferred opcode. */ if (walk_state->deferred_node) { + /* This name is already in the namespace, get the node */ node = walk_state->deferred_node; @@ -727,6 +766,7 @@ #endif } if (!op) { + /* Create a new op */ op = acpi_ps_alloc_op(walk_state->opcode); @@ -776,7 +816,7 @@ #ifndef ACPI_NO_METHOD_EXECUTION u32 i; #endif - ACPI_FUNCTION_TRACE("ds_load2_end_op"); + ACPI_FUNCTION_TRACE(ds_load2_end_op); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", @@ -870,7 +910,7 @@ #endif */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "Create-Load [%s] State=%p Op=%p named_obj=%p\n", + "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", acpi_ps_get_opcode_name(op->common.aml_opcode), walk_state, op, node)); @@ -1045,7 +1085,7 @@ #ifndef ACPI_NO_METHOD_EXECUTION * arguments.) */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "LOADING-Method: State=%p Op=%p named_obj=%p\n", + "LOADING-Method: State=%p Op=%p NamedObj=%p\n", walk_state, op, op->named.node)); if (!acpi_ns_get_attached_object(op->named.node)) { @@ -1090,7 +1130,7 @@ #endif /* ACPI_NO_METHOD_EXECUTION */ case AML_CLASS_METHOD_CALL: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "RESOLVING-method_call: State=%p Op=%p named_obj=%p\n", + "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", walk_state, op, node)); /* @@ -1104,7 +1144,6 @@ #endif /* ACPI_NO_METHOD_EXECUTION */ ACPI_NS_DONT_OPEN_SCOPE, walk_state, &(new_node)); if (ACPI_SUCCESS(status)) { - /* * Make sure that what we found is indeed a method * We didn't search for a method on purpose, to see if the name diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c index ada21ef..c922897 100644 --- a/drivers/acpi/dispatcher/dswscope.c +++ b/drivers/acpi/dispatcher/dswscope.c @@ -63,9 +63,10 @@ void acpi_ds_scope_stack_clear(struct ac { union acpi_generic_state *scope_info; - ACPI_FUNCTION_NAME("ds_scope_stack_clear"); + ACPI_FUNCTION_NAME(ds_scope_stack_clear); while (walk_state->scope_info) { + /* Pop a scope off the stack */ scope_info = walk_state->scope_info; @@ -102,9 +103,10 @@ acpi_ds_scope_stack_push(struct acpi_nam union acpi_generic_state *scope_info; union acpi_generic_state *old_scope_info; - ACPI_FUNCTION_TRACE("ds_scope_stack_push"); + ACPI_FUNCTION_TRACE(ds_scope_stack_push); if (!node) { + /* Invalid scope */ ACPI_ERROR((AE_INFO, "Null scope parameter")); @@ -126,7 +128,7 @@ acpi_ds_scope_stack_push(struct acpi_nam /* Init new scope object */ - scope_info->common.data_type = ACPI_DESC_TYPE_STATE_WSCOPE; + scope_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_WSCOPE; scope_info->scope.node = node; scope_info->common.value = (u16) type; @@ -176,7 +178,7 @@ acpi_status acpi_ds_scope_stack_pop(stru union acpi_generic_state *scope_info; union acpi_generic_state *new_scope_info; - ACPI_FUNCTION_TRACE("ds_scope_stack_pop"); + ACPI_FUNCTION_TRACE(ds_scope_stack_pop); /* * Pop scope info object off the stack. diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index fa78cb7..7817e55 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -66,7 +66,6 @@ void *acpi_ds_obj_stack_get_value(u32 in #endif #ifdef ACPI_FUTURE_USAGE - /******************************************************************************* * * FUNCTION: acpi_ds_result_remove @@ -88,7 +87,7 @@ acpi_ds_result_remove(union acpi_operand { union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_remove"); + ACPI_FUNCTION_NAME(ds_result_remove); state = walk_state->results; if (!state) { @@ -128,7 +127,6 @@ acpi_ds_result_remove(union acpi_operand return (AE_OK); } - #endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -152,7 +150,7 @@ acpi_ds_result_pop(union acpi_operand_ob acpi_native_uint index; union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_pop"); + ACPI_FUNCTION_NAME(ds_result_pop); state = walk_state->results; if (!state) { @@ -170,6 +168,7 @@ acpi_ds_result_pop(union acpi_operand_ob state->results.num_results--; for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) { + /* Check for a valid result object */ if (state->results.obj_desc[index - 1]) { @@ -213,7 +212,7 @@ acpi_ds_result_pop_from_bottom(union acp acpi_native_uint index; union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_pop_from_bottom"); + ACPI_FUNCTION_NAME(ds_result_pop_from_bottom); state = walk_state->results; if (!state) { @@ -278,7 +277,7 @@ acpi_ds_result_push(union acpi_operand_o { union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_push"); + ACPI_FUNCTION_NAME(ds_result_push); state = walk_state->results; if (!state) { @@ -331,14 +330,14 @@ acpi_status acpi_ds_result_stack_push(st { union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_stack_push"); + ACPI_FUNCTION_NAME(ds_result_stack_push); state = acpi_ut_create_generic_state(); if (!state) { return (AE_NO_MEMORY); } - state->common.data_type = ACPI_DESC_TYPE_STATE_RESULT; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT; acpi_ut_push_generic_state(&walk_state->results, state); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n", @@ -363,7 +362,7 @@ acpi_status acpi_ds_result_stack_pop(str { union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_stack_pop"); + ACPI_FUNCTION_NAME(ds_result_stack_pop); /* Check for stack underflow */ @@ -376,7 +375,7 @@ acpi_status acpi_ds_result_stack_pop(str state = acpi_ut_pop_generic_state(&walk_state->results); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Result=%p remaining_results=%X State=%p\n", + "Result=%p RemainingResults=%X State=%p\n", state, state->results.num_results, walk_state)); acpi_ut_delete_generic_state(state); @@ -400,7 +399,7 @@ acpi_status acpi_ds_result_stack_pop(str acpi_status acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) { - ACPI_FUNCTION_NAME("ds_obj_stack_push"); + ACPI_FUNCTION_NAME(ds_obj_stack_push); /* Check for stack overflow */ @@ -445,9 +444,10 @@ acpi_ds_obj_stack_pop(u32 pop_count, str { u32 i; - ACPI_FUNCTION_NAME("ds_obj_stack_pop"); + ACPI_FUNCTION_NAME(ds_obj_stack_pop); for (i = 0; i < pop_count; i++) { + /* Check for stack underflow */ if (walk_state->num_operands == 0) { @@ -491,9 +491,10 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop u32 i; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_NAME("ds_obj_stack_pop_and_delete"); + ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); for (i = 0; i < pop_count; i++) { + /* Check for stack underflow */ if (walk_state->num_operands == 0) { @@ -538,13 +539,13 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state *thread) { - ACPI_FUNCTION_NAME("ds_get_current_walk_state"); + ACPI_FUNCTION_NAME(ds_get_current_walk_state); if (!thread) { return (NULL); } - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current walk_state %p\n", + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current WalkState %p\n", thread->walk_state_list)); return (thread->walk_state_list); @@ -567,7 +568,7 @@ void acpi_ds_push_walk_state(struct acpi_walk_state *walk_state, struct acpi_thread_state *thread) { - ACPI_FUNCTION_TRACE("ds_push_walk_state"); + ACPI_FUNCTION_TRACE(ds_push_walk_state); walk_state->next = thread->walk_state_list; thread->walk_state_list = walk_state; @@ -593,11 +594,12 @@ struct acpi_walk_state *acpi_ds_pop_walk { struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE("ds_pop_walk_state"); + ACPI_FUNCTION_TRACE(ds_pop_walk_state); walk_state = thread->walk_state_list; if (walk_state) { + /* Next walk state becomes the current walk state */ thread->walk_state_list = walk_state->next; @@ -618,7 +620,7 @@ struct acpi_walk_state *acpi_ds_pop_walk * * PARAMETERS: owner_id - ID for object creation * Origin - Starting point for this walk - * mth_desc - Method object + * method_desc - Method object * Thread - Current thread state * * RETURN: Pointer to the new walk state. @@ -632,24 +634,24 @@ struct acpi_walk_state *acpi_ds_create_w union acpi_parse_object *origin, union acpi_operand_object - *mth_desc, + *method_desc, struct acpi_thread_state *thread) { struct acpi_walk_state *walk_state; acpi_status status; - ACPI_FUNCTION_TRACE("ds_create_walk_state"); + ACPI_FUNCTION_TRACE(ds_create_walk_state); - walk_state = ACPI_MEM_CALLOCATE(sizeof(struct acpi_walk_state)); + walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state)); if (!walk_state) { return_PTR(NULL); } - walk_state->data_type = ACPI_DESC_TYPE_WALK; + walk_state->descriptor_type = ACPI_DESC_TYPE_WALK; + walk_state->method_desc = method_desc; walk_state->owner_id = owner_id; walk_state->origin = origin; - walk_state->method_desc = mth_desc; walk_state->thread = thread; walk_state->parser_state.start_op = origin; @@ -664,7 +666,7 @@ #endif status = acpi_ds_result_stack_push(walk_state); if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(walk_state); + ACPI_FREE(walk_state); return_PTR(NULL); } @@ -701,13 +703,13 @@ acpi_ds_init_aml_walk(struct acpi_walk_s struct acpi_namespace_node *method_node, u8 * aml_start, u32 aml_length, - struct acpi_parameter_info *info, u8 pass_number) + struct acpi_evaluate_info *info, u8 pass_number) { acpi_status status; struct acpi_parse_state *parser_state = &walk_state->parser_state; union acpi_parse_object *extra_op; - ACPI_FUNCTION_TRACE("ds_init_aml_walk"); + ACPI_FUNCTION_TRACE(ds_init_aml_walk); walk_state->parser_state.aml = walk_state->parser_state.aml_start = aml_start; @@ -778,6 +780,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_s } if (parser_state->start_node) { + /* Push start scope on scope stack and make it current */ status = @@ -810,21 +813,24 @@ void acpi_ds_delete_walk_state(struct ac { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR("ds_delete_walk_state", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state); if (!walk_state) { return; } - if (walk_state->data_type != ACPI_DESC_TYPE_WALK) { + if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) { ACPI_ERROR((AE_INFO, "%p is not a valid walk state", walk_state)); return; } + /* There should not be any open scopes */ + if (walk_state->parser_state.scope) { ACPI_ERROR((AE_INFO, "%p walk still has a scope list", walk_state)); + acpi_ps_cleanup_scope(&walk_state->parser_state); } /* Always must free any linked control states */ @@ -854,7 +860,7 @@ void acpi_ds_delete_walk_state(struct ac acpi_ut_delete_generic_state(state); } - ACPI_MEM_FREE(walk_state); + ACPI_FREE(walk_state); return_VOID; } @@ -879,7 +885,7 @@ acpi_ds_result_insert(void *object, { union acpi_generic_state *state; - ACPI_FUNCTION_NAME("ds_result_insert"); + ACPI_FUNCTION_NAME(ds_result_insert); state = walk_state->results; if (!state) { @@ -937,7 +943,7 @@ acpi_status acpi_ds_obj_stack_delete_all { u32 i; - ACPI_FUNCTION_TRACE_PTR("ds_obj_stack_delete_all", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_delete_all, walk_state); /* The stack size is configurable, but fixed */ @@ -969,7 +975,7 @@ acpi_status acpi_ds_obj_stack_pop_object(union acpi_operand_object **object, struct acpi_walk_state *walk_state) { - ACPI_FUNCTION_NAME("ds_obj_stack_pop_object"); + ACPI_FUNCTION_NAME(ds_obj_stack_pop_object); /* Check for stack underflow */ @@ -1025,7 +1031,7 @@ acpi_ds_obj_stack_pop_object(union acpi_ void *acpi_ds_obj_stack_get_value(u32 index, struct acpi_walk_state *walk_state) { - ACPI_FUNCTION_TRACE_PTR("ds_obj_stack_get_value", walk_state); + ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_get_value, walk_state); /* Can't do it if the stack is empty */ diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index eee0864..18b3ea9 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -116,7 +116,7 @@ union acpi_ec { struct acpi_generic_address command_addr; struct acpi_generic_address data_addr; unsigned long global_lock; - spinlock_t lock; + struct semaphore sem; } poll; }; @@ -323,7 +323,6 @@ static int acpi_ec_poll_read(union acpi_ { acpi_status status = AE_OK; int result = 0; - unsigned long flags = 0; u32 glk = 0; ACPI_FUNCTION_TRACE("acpi_ec_read"); @@ -339,8 +338,11 @@ static int acpi_ec_poll_read(union acpi_ return_VALUE(-ENODEV); } - spin_lock_irqsave(&ec->poll.lock, flags); - + if (down_interruptible(&ec->poll.sem)) { + result = -ERESTARTSYS; + goto end_nosem; + } + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); @@ -358,8 +360,8 @@ static int acpi_ec_poll_read(union acpi_ *data, address)); end: - spin_unlock_irqrestore(&ec->poll.lock, flags); - + up(&ec->poll.sem); +end_nosem: if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -370,7 +372,6 @@ static int acpi_ec_poll_write(union acpi { int result = 0; acpi_status status = AE_OK; - unsigned long flags = 0; u32 glk = 0; ACPI_FUNCTION_TRACE("acpi_ec_write"); @@ -384,8 +385,11 @@ static int acpi_ec_poll_write(union acpi return_VALUE(-ENODEV); } - spin_lock_irqsave(&ec->poll.lock, flags); - + if (down_interruptible(&ec->poll.sem)) { + result = -ERESTARTSYS; + goto end_nosem; + } + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); @@ -406,8 +410,8 @@ static int acpi_ec_poll_write(union acpi data, address)); end: - spin_unlock_irqrestore(&ec->poll.lock, flags); - + up(&ec->poll.sem); +end_nosem: if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -568,7 +572,6 @@ static int acpi_ec_poll_query(union acpi { int result = 0; acpi_status status = AE_OK; - unsigned long flags = 0; u32 glk = 0; ACPI_FUNCTION_TRACE("acpi_ec_query"); @@ -589,8 +592,11 @@ static int acpi_ec_poll_query(union acpi * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source). */ - spin_lock_irqsave(&ec->poll.lock, flags); - + if (down_interruptible(&ec->poll.sem)) { + result = -ERESTARTSYS; + goto end_nosem; + } + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); @@ -602,8 +608,8 @@ static int acpi_ec_poll_query(union acpi result = -ENODATA; end: - spin_unlock_irqrestore(&ec->poll.lock, flags); - + up(&ec->poll.sem); +end_nosem: if (ec->common.global_lock) acpi_release_global_lock(glk); @@ -680,7 +686,6 @@ static void acpi_ec_gpe_poll_query(void { union acpi_ec *ec = (union acpi_ec *)ec_cxt; u32 value = 0; - unsigned long flags = 0; static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' @@ -691,9 +696,11 @@ static void acpi_ec_gpe_poll_query(void if (!ec_cxt) goto end; - spin_lock_irqsave(&ec->poll.lock, flags); + if (down_interruptible (&ec->poll.sem)) { + return_VOID; + } acpi_hw_low_level_read(8, &value, &ec->common.command_addr); - spin_unlock_irqrestore(&ec->poll.lock, flags); + up(&ec->poll.sem); /* TBD: Implement asynch events! * NOTE: All we care about are EC-SCI's. Other EC events are @@ -763,8 +770,7 @@ static u32 acpi_ec_gpe_poll_handler(void acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); - status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, - acpi_ec_gpe_query, ec); + status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec); if (status == AE_OK) return ACPI_INTERRUPT_HANDLED; @@ -799,7 +805,7 @@ static u32 acpi_ec_gpe_intr_handler(void if (value & ACPI_EC_FLAG_SCI) { atomic_add(1, &ec->intr.pending_gpe); - status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; @@ -991,7 +997,6 @@ static int acpi_ec_poll_add(struct acpi_ int result = 0; acpi_status status = AE_OK; union acpi_ec *ec = NULL; - unsigned long uid; ACPI_FUNCTION_TRACE("acpi_ec_add"); @@ -1005,7 +1010,7 @@ static int acpi_ec_poll_add(struct acpi_ ec->common.handle = device->handle; ec->common.uid = -1; - spin_lock_init(&ec->poll.lock); + init_MUTEX(&ec->poll.sem); strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_EC_CLASS); acpi_driver_data(device) = ec; @@ -1014,10 +1019,9 @@ static int acpi_ec_poll_add(struct acpi_ acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); - /* If our UID matches the UID for the ECDT-enumerated EC, - we now have the *real* EC info, so kill the makeshift one. */ - acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); - if (ec_ecdt && ec_ecdt->common.uid == uid) { + /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: + http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ + if (ec_ecdt) { acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); @@ -1062,7 +1066,6 @@ static int acpi_ec_intr_add(struct acpi_ int result = 0; acpi_status status = AE_OK; union acpi_ec *ec = NULL; - unsigned long uid; ACPI_FUNCTION_TRACE("acpi_ec_add"); @@ -1088,10 +1091,9 @@ static int acpi_ec_intr_add(struct acpi_ acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, &ec->common.global_lock); - /* If our UID matches the UID for the ECDT-enumerated EC, - we now have the *real* EC info, so kill the makeshift one. */ - acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid); - if (ec_ecdt && ec_ecdt->common.uid == uid) { + /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: + http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ + if (ec_ecdt) { acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); @@ -1300,7 +1302,7 @@ acpi_fake_ecdt_poll_callback(acpi_handle &ec_ecdt->common.gpe_bit); if (ACPI_FAILURE(status)) return status; - spin_lock_init(&ec_ecdt->poll.lock); + init_MUTEX(&ec_ecdt->poll.sem); ec_ecdt->common.global_lock = TRUE; ec_ecdt->common.handle = handle; @@ -1416,7 +1418,7 @@ static int __init acpi_ec_poll_get_real_ ec_ecdt->common.status_addr = ecdt_ptr->ec_control; ec_ecdt->common.data_addr = ecdt_ptr->ec_data; ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; - spin_lock_init(&ec_ecdt->poll.lock); + init_MUTEX(&ec_ecdt->poll.sem); /* use the GL just to be safe */ ec_ecdt->common.global_lock = TRUE; ec_ecdt->common.uid = ecdt_ptr->uid; diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c index c9ac05c..919037d 100644 --- a/drivers/acpi/events/evevent.c +++ b/drivers/acpi/events/evevent.c @@ -68,7 +68,7 @@ acpi_status acpi_ev_initialize_events(vo { acpi_status status; - ACPI_FUNCTION_TRACE("ev_initialize_events"); + ACPI_FUNCTION_TRACE(ev_initialize_events); /* Make sure we have ACPI tables */ @@ -118,7 +118,7 @@ acpi_status acpi_ev_install_fadt_gpes(vo { acpi_status status; - ACPI_FUNCTION_TRACE("ev_install_fadt_gpes"); + ACPI_FUNCTION_TRACE(ev_install_fadt_gpes); /* Namespace must be locked */ @@ -157,7 +157,7 @@ acpi_status acpi_ev_install_xrupt_handle { acpi_status status; - ACPI_FUNCTION_TRACE("ev_install_xrupt_handlers"); + ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers); /* Install the SCI handler */ @@ -241,7 +241,7 @@ u32 acpi_ev_fixed_event_detect(void) u32 fixed_enable; acpi_native_uint i; - ACPI_FUNCTION_NAME("ev_fixed_event_detect"); + ACPI_FUNCTION_NAME(ev_fixed_event_detect); /* * Read the fixed feature status and enable registers, as all the cases @@ -260,12 +260,14 @@ u32 acpi_ev_fixed_event_detect(void) * Check for all possible Fixed Events and dispatch those that are active */ for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + /* Both the status and enable bits must be on for this event */ if ((fixed_status & acpi_gbl_fixed_event_info[i]. status_bit_mask) && (fixed_enable & acpi_gbl_fixed_event_info[i]. enable_bit_mask)) { + /* Found an active (signalled) event */ int_status |= acpi_ev_fixed_event_dispatch((u32) i); diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index f64f977..f01d339 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -69,7 +69,7 @@ acpi_ev_set_gpe_type(struct acpi_gpe_eve { acpi_status status; - ACPI_FUNCTION_TRACE("ev_set_gpe_type"); + ACPI_FUNCTION_TRACE(ev_set_gpe_type); /* Validate type and update register enable masks */ @@ -115,7 +115,7 @@ acpi_ev_update_gpe_enable_masks(struct a struct acpi_gpe_register_info *gpe_register_info; u8 register_bit; - ACPI_FUNCTION_TRACE("ev_update_gpe_enable_masks"); + ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks); gpe_register_info = gpe_event_info->register_info; if (!gpe_register_info) { @@ -178,7 +178,7 @@ acpi_ev_enable_gpe(struct acpi_gpe_event { acpi_status status; - ACPI_FUNCTION_TRACE("ev_enable_gpe"); + ACPI_FUNCTION_TRACE(ev_enable_gpe); /* Make sure HW enable masks are updated */ @@ -207,6 +207,7 @@ acpi_ev_enable_gpe(struct acpi_gpe_event ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); if (write_to_hardware) { + /* Clear the GPE (of stale events), then enable it */ status = acpi_hw_clear_gpe(gpe_event_info); @@ -243,7 +244,7 @@ acpi_status acpi_ev_disable_gpe(struct a { acpi_status status; - ACPI_FUNCTION_TRACE("ev_disable_gpe"); + ACPI_FUNCTION_TRACE(ev_disable_gpe); if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) { return_ACPI_STATUS(AE_OK); @@ -313,6 +314,7 @@ struct acpi_gpe_event_info *acpi_ev_get_ /* A NULL gpe_block means use the FADT-defined GPE block(s) */ if (!gpe_device) { + /* Examine GPE Block 0 and 1 (These blocks are permanent) */ for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) { @@ -380,10 +382,11 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x u32 status_reg; u32 enable_reg; acpi_cpu_flags flags; + acpi_cpu_flags hw_flags; acpi_native_uint i; acpi_native_uint j; - ACPI_FUNCTION_NAME("ev_gpe_detect"); + ACPI_FUNCTION_NAME(ev_gpe_detect); /* Check for the case where there are no GPEs */ @@ -391,9 +394,12 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x return (int_status); } - /* Examine all GPE blocks attached to this interrupt level */ + /* We need to hold the GPE lock now, hardware lock in the loop */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Examine all GPE blocks attached to this interrupt level */ + gpe_block = gpe_xrupt_list->gpe_block_list_head; while (gpe_block) { /* @@ -402,10 +408,13 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x * Find all currently active GP events. */ for (i = 0; i < gpe_block->register_count; i++) { + /* Get the next status/enable pair */ gpe_register_info = &gpe_block->register_info[i]; + hw_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); + /* Read the Status Register */ status = @@ -414,6 +423,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x &gpe_register_info-> status_address); if (ACPI_FAILURE(status)) { + acpi_os_release_lock(acpi_gbl_hardware_lock, + hw_flags); goto unlock_and_exit; } @@ -424,6 +435,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x &enable_reg, &gpe_register_info-> enable_address); + acpi_os_release_lock(acpi_gbl_hardware_lock, hw_flags); + if (ACPI_FAILURE(status)) { goto unlock_and_exit; } @@ -437,6 +450,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x enabled_status_byte = (u8) (status_reg & enable_reg); if (!enabled_status_byte) { + /* No active GPEs in this register, move on */ continue; @@ -445,6 +459,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x /* Now look at the individual GPEs in this byte register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { + /* Examine one GPE bit */ if (enabled_status_byte & @@ -483,9 +498,9 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x * * RETURN: None * - * DESCRIPTION: Perform the actual execution of a GPE control method. This - * function is called from an invocation of acpi_os_queue_for_execution - * (and therefore does NOT execute at interrupt level) so that + * DESCRIPTION: Perform the actual execution of a GPE control method. This + * function is called from an invocation of acpi_os_execute and + * therefore does NOT execute at interrupt level - so that * the control method itself is not executed in the context of * an interrupt handler. * @@ -494,12 +509,11 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) { struct acpi_gpe_event_info *gpe_event_info = (void *)context; - u32 gpe_number = 0; acpi_status status; struct acpi_gpe_event_info local_gpe_event_info; - struct acpi_parameter_info info; + struct acpi_evaluate_info *info; - ACPI_FUNCTION_TRACE("ev_asynch_execute_gpe_method"); + ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { @@ -535,22 +549,35 @@ static void ACPI_SYSTEM_XFACE acpi_ev_as */ if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) { - /* - * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx - * control method that corresponds to this GPE - */ - info.node = local_gpe_event_info.dispatch.method_node; - info.parameters = - ACPI_CAST_PTR(union acpi_operand_object *, gpe_event_info); - info.parameter_type = ACPI_PARAM_GPE; - status = acpi_ns_evaluate_by_handle(&info); + /* Allocate the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + status = AE_NO_MEMORY; + } else { + /* + * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx + * control method that corresponds to this GPE + */ + info->prefix_node = + local_gpe_event_info.dispatch.method_node; + info->parameters = + ACPI_CAST_PTR(union acpi_operand_object *, + gpe_event_info); + info->parameter_type = ACPI_PARAM_GPE; + info->flags = ACPI_IGNORE_RETURN_VALUE; + + status = acpi_ns_evaluate(info); + ACPI_FREE(info); + } + if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "While evaluating method [%4.4s] for GPE[%2X]", + "While evaluating GPE method [%4.4s]", acpi_ut_get_node_name (local_gpe_event_info.dispatch. - method_node), gpe_number)); + method_node))); } } @@ -593,7 +620,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_eve { acpi_status status; - ACPI_FUNCTION_TRACE("ev_gpe_dispatch"); + ACPI_FUNCTION_TRACE(ev_gpe_dispatch); /* * If edge-triggered, clear the GPE status bit now. Note that @@ -669,9 +696,9 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_eve * Execute the method associated with the GPE * NOTE: Level-triggered GPEs are cleared after the method completes. */ - status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE, - acpi_ev_asynch_execute_gpe_method, - gpe_event_info); + status = acpi_os_execute(OSL_GPE_HANDLER, + acpi_ev_asynch_execute_gpe_method, + gpe_event_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to queue handler for GPE[%2X] - event disabled", @@ -716,7 +743,7 @@ #ifdef ACPI_GPE_NOTIFY_CHECK * * DESCRIPTION: Determine if a a GPE is "wake-only". * - * Called from Notify() code in interpreter when a "device_wake" + * Called from Notify() code in interpreter when a "DeviceWake" * Notify comes in. * ******************************************************************************/ @@ -726,7 +753,7 @@ acpi_ev_check_for_wake_only_gpe(struct a { acpi_status status; - ACPI_FUNCTION_TRACE("ev_check_for_wake_only_gpe"); + ACPI_FUNCTION_TRACE(ev_check_for_wake_only_gpe); if ((gpe_event_info) && /* Only >0 for _Lxx/_Exx */ ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) { /* System state at GPE time */ diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index 0fd00b5..95ddeb4 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c @@ -131,14 +131,14 @@ u8 acpi_ev_valid_gpe_event(struct acpi_g * ******************************************************************************/ -acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback) +acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback) { struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_xrupt_info *gpe_xrupt_info; acpi_status status = AE_OK; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("ev_walk_gpe_list"); + ACPI_FUNCTION_TRACE(ev_walk_gpe_list); flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); @@ -146,10 +146,12 @@ acpi_status acpi_ev_walk_gpe_list(ACPI_G gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; while (gpe_xrupt_info) { + /* Walk all Gpe Blocks attached to this interrupt level */ gpe_block = gpe_xrupt_info->gpe_block_list_head; while (gpe_block) { + /* One callback per GPE block */ status = gpe_walk_callback(gpe_xrupt_info, gpe_block); @@ -190,11 +192,12 @@ acpi_ev_delete_gpe_handlers(struct acpi_ acpi_native_uint i; acpi_native_uint j; - ACPI_FUNCTION_TRACE("ev_delete_gpe_handlers"); + ACPI_FUNCTION_TRACE(ev_delete_gpe_handlers); /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { + /* Now look at the individual GPEs in this byte register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { @@ -204,7 +207,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_ if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { - ACPI_MEM_FREE(gpe_event_info->dispatch.handler); + ACPI_FREE(gpe_event_info->dispatch.handler); gpe_event_info->dispatch.handler = NULL; gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; @@ -248,7 +251,7 @@ acpi_ev_save_method_info(acpi_handle obj u8 type; acpi_status status; - ACPI_FUNCTION_TRACE("ev_save_method_info"); + ACPI_FUNCTION_TRACE(ev_save_method_info); /* * _Lxx and _Exx GPE method support @@ -279,9 +282,9 @@ acpi_ev_save_method_info(acpi_handle obj default: /* Unknown method type, just ignore it! */ - ACPI_ERROR((AE_INFO, - "Unknown GPE method type: %s (name not of form _Lxx or _Exx)", - name)); + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, + "Ignoring unknown GPE method type: %s (name not of form _Lxx or _Exx)", + name)); return_ACPI_STATUS(AE_OK); } @@ -289,11 +292,12 @@ acpi_ev_save_method_info(acpi_handle obj gpe_number = ACPI_STRTOUL(&name[2], NULL, 16); if (gpe_number == ACPI_UINT32_MAX) { + /* Conversion failed; invalid method, just ignore it */ - ACPI_ERROR((AE_INFO, - "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)", - name)); + ACPI_DEBUG_PRINT((ACPI_DB_LOAD, + "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)", + name)); return_ACPI_STATUS(AE_OK); } @@ -364,13 +368,14 @@ acpi_ev_match_prw_and_gpe(acpi_handle ob u32 gpe_number; acpi_status status; - ACPI_FUNCTION_TRACE("ev_match_prw_and_gpe"); + ACPI_FUNCTION_TRACE(ev_match_prw_and_gpe); /* Check for a _PRW method under this device */ status = acpi_ut_evaluate_object(obj_handle, METHOD_NAME__PRW, ACPI_BTYPE_PACKAGE, &pkg_desc); if (ACPI_FAILURE(status)) { + /* Ignore all errors from _PRW, we don't want to abort the subsystem */ return_ACPI_STATUS(AE_OK); @@ -394,6 +399,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle ob obj_desc = pkg_desc->package.elements[0]; if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + /* Use FADT-defined GPE device (from definition of _PRW) */ target_gpe_device = acpi_gbl_fadt_gpe_device; @@ -402,6 +408,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle ob gpe_number = (u32) obj_desc->integer.value; } else if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + /* Package contains a GPE reference and GPE number within a GPE block */ if ((obj_desc->package.count < 2) || @@ -482,7 +489,7 @@ static struct acpi_gpe_xrupt_info *acpi_ acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("ev_get_gpe_xrupt_block"); + ACPI_FUNCTION_TRACE(ev_get_gpe_xrupt_block); /* No need for lock since we are not changing any list elements here */ @@ -497,7 +504,7 @@ static struct acpi_gpe_xrupt_info *acpi_ /* Not found, must allocate a new xrupt descriptor */ - gpe_xrupt = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_xrupt_info)); + gpe_xrupt = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_xrupt_info)); if (!gpe_xrupt) { return_PTR(NULL); } @@ -556,7 +563,7 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("ev_delete_gpe_xrupt"); + ACPI_FUNCTION_TRACE(ev_delete_gpe_xrupt); /* We never want to remove the SCI interrupt handler */ @@ -588,7 +595,7 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe /* Free the block */ - ACPI_MEM_FREE(gpe_xrupt); + ACPI_FREE(gpe_xrupt); return_ACPI_STATUS(AE_OK); } @@ -614,7 +621,7 @@ acpi_ev_install_gpe_block(struct acpi_gp acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("ev_install_gpe_block"); + ACPI_FUNCTION_TRACE(ev_install_gpe_block); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { @@ -667,7 +674,7 @@ acpi_status acpi_ev_delete_gpe_block(str acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("ev_install_gpe_block"); + ACPI_FUNCTION_TRACE(ev_install_gpe_block); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { @@ -679,6 +686,7 @@ acpi_status acpi_ev_delete_gpe_block(str status = acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block); if (!gpe_block->previous && !gpe_block->next) { + /* This is the last gpe_block on this interrupt */ status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block); @@ -704,9 +712,9 @@ acpi_status acpi_ev_delete_gpe_block(str /* Free the gpe_block */ - ACPI_MEM_FREE(gpe_block->register_info); - ACPI_MEM_FREE(gpe_block->event_info); - ACPI_MEM_FREE(gpe_block); + ACPI_FREE(gpe_block->register_info); + ACPI_FREE(gpe_block->event_info); + ACPI_FREE(gpe_block); unlock_and_exit: status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); @@ -736,17 +744,17 @@ acpi_ev_create_gpe_info_blocks(struct ac acpi_native_uint j; acpi_status status; - ACPI_FUNCTION_TRACE("ev_create_gpe_info_blocks"); + ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks); /* Allocate the GPE register information block */ - gpe_register_info = ACPI_MEM_CALLOCATE((acpi_size) gpe_block-> - register_count * - sizeof(struct - acpi_gpe_register_info)); + gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block-> + register_count * + sizeof(struct + acpi_gpe_register_info)); if (!gpe_register_info) { ACPI_ERROR((AE_INFO, - "Could not allocate the gpe_register_info table")); + "Could not allocate the GpeRegisterInfo table")); return_ACPI_STATUS(AE_NO_MEMORY); } @@ -754,13 +762,14 @@ acpi_ev_create_gpe_info_blocks(struct ac * Allocate the GPE event_info block. There are eight distinct GPEs * per register. Initialization to zeros is sufficient. */ - gpe_event_info = ACPI_MEM_CALLOCATE(((acpi_size) gpe_block-> - register_count * - ACPI_GPE_REGISTER_WIDTH) * - sizeof(struct acpi_gpe_event_info)); + gpe_event_info = ACPI_ALLOCATE_ZEROED(((acpi_size) gpe_block-> + register_count * + ACPI_GPE_REGISTER_WIDTH) * + sizeof(struct + acpi_gpe_event_info)); if (!gpe_event_info) { ACPI_ERROR((AE_INFO, - "Could not allocate the gpe_event_info table")); + "Could not allocate the GpeEventInfo table")); status = AE_NO_MEMORY; goto error_exit; } @@ -780,6 +789,7 @@ acpi_ev_create_gpe_info_blocks(struct ac this_event = gpe_event_info; for (i = 0; i < gpe_block->register_count; i++) { + /* Init the register_info for this GPE register (8 GPEs) */ this_register->base_gpe_number = @@ -839,10 +849,10 @@ acpi_ev_create_gpe_info_blocks(struct ac error_exit: if (gpe_register_info) { - ACPI_MEM_FREE(gpe_register_info); + ACPI_FREE(gpe_register_info); } if (gpe_event_info) { - ACPI_MEM_FREE(gpe_event_info); + ACPI_FREE(gpe_event_info); } return_ACPI_STATUS(status); @@ -878,7 +888,7 @@ acpi_ev_create_gpe_block(struct acpi_nam acpi_status status; struct acpi_gpe_block_info *gpe_block; - ACPI_FUNCTION_TRACE("ev_create_gpe_block"); + ACPI_FUNCTION_TRACE(ev_create_gpe_block); if (!register_count) { return_ACPI_STATUS(AE_OK); @@ -886,7 +896,7 @@ acpi_ev_create_gpe_block(struct acpi_nam /* Allocate a new GPE block */ - gpe_block = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_block_info)); + gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info)); if (!gpe_block) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -906,7 +916,7 @@ acpi_ev_create_gpe_block(struct acpi_nam */ status = acpi_ev_create_gpe_info_blocks(gpe_block); if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(gpe_block); + ACPI_FREE(gpe_block); return_ACPI_STATUS(status); } @@ -914,7 +924,7 @@ acpi_ev_create_gpe_block(struct acpi_nam status = acpi_ev_install_gpe_block(gpe_block, interrupt_number); if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(gpe_block); + ACPI_FREE(gpe_block); return_ACPI_STATUS(status); } @@ -971,7 +981,7 @@ acpi_ev_initialize_gpe_block(struct acpi acpi_native_uint i; acpi_native_uint j; - ACPI_FUNCTION_TRACE("ev_initialize_gpe_block"); + ACPI_FUNCTION_TRACE(ev_initialize_gpe_block); /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */ @@ -1013,6 +1023,7 @@ acpi_ev_initialize_gpe_block(struct acpi for (i = 0; i < gpe_block->register_count; i++) { for (j = 0; j < 8; j++) { + /* Get the info block for this particular GPE */ gpe_event_info = @@ -1040,7 +1051,7 @@ acpi_ev_initialize_gpe_block(struct acpi status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Could not enable GPEs in gpe_block %p", + ACPI_ERROR((AE_INFO, "Could not enable GPEs in GpeBlock %p", gpe_block)); } @@ -1066,7 +1077,7 @@ acpi_status acpi_ev_gpe_initialize(void) u32 gpe_number_max = 0; acpi_status status; - ACPI_FUNCTION_TRACE("ev_gpe_initialize"); + ACPI_FUNCTION_TRACE(ev_gpe_initialize); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -1099,6 +1110,7 @@ acpi_status acpi_ev_gpe_initialize(void) * particular block is not supported. */ if (acpi_gbl_FADT->gpe0_blk_len && acpi_gbl_FADT->xgpe0_blk.address) { + /* GPE block 0 exists (has both length and address > 0) */ register_count0 = (u16) (acpi_gbl_FADT->gpe0_blk_len / 2); @@ -1121,6 +1133,7 @@ acpi_status acpi_ev_gpe_initialize(void) } if (acpi_gbl_FADT->gpe1_blk_len && acpi_gbl_FADT->xgpe1_blk.address) { + /* GPE block 1 exists (has both length and address > 0) */ register_count1 = (u16) (acpi_gbl_FADT->gpe1_blk_len / 2); @@ -1168,6 +1181,7 @@ acpi_status acpi_ev_gpe_initialize(void) /* Exit if there are no GPE registers */ if ((register_count0 + register_count1) == 0) { + /* GPEs are not required by ACPI, this is OK */ ACPI_DEBUG_PRINT((ACPI_DB_INIT, diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 0909ba6..6eef4ef 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c @@ -49,12 +49,13 @@ #include #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME("evmisc") +/* Names for Notify() values, used for debug output */ #ifdef ACPI_DEBUG_OUTPUT static const char *acpi_notify_value_names[] = { "Bus Check", "Device Check", "Device Wake", - "Eject request", + "Eject Request", "Device Check Light", "Frequency Mismatch", "Bus Mode Mismatch", @@ -124,7 +125,7 @@ acpi_ev_queue_notify_request(struct acpi union acpi_generic_state *notify_info; acpi_status status = AE_OK; - ACPI_FUNCTION_NAME("ev_queue_notify_request"); + ACPI_FUNCTION_NAME(ev_queue_notify_request); /* * For value 3 (Ejection Request), some device method may need to be run. @@ -150,6 +151,7 @@ acpi_ev_queue_notify_request(struct acpi obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { + /* We have the notify object, Get the right handler */ switch (node->type) { @@ -184,14 +186,15 @@ acpi_ev_queue_notify_request(struct acpi return (AE_NO_MEMORY); } - notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY; + notify_info->common.descriptor_type = + ACPI_DESC_TYPE_STATE_NOTIFY; notify_info->notify.node = node; notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; - status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH, - acpi_ev_notify_dispatch, - notify_info); + status = + acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, + notify_info); if (ACPI_FAILURE(status)) { acpi_ut_delete_generic_state(notify_info); } @@ -240,6 +243,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_no * to the device. */ if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) { + /* Global system notification handler */ if (acpi_gbl_system_notify.handler) { @@ -297,6 +301,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_gl /* Signal threads that are waiting for the lock */ if (acpi_gbl_global_lock_thread_count) { + /* Send sufficient units to the semaphore */ status = @@ -335,15 +340,16 @@ static u32 acpi_ev_global_lock_handler(v */ ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired); if (acquired) { + /* Got the lock, now wake all threads waiting for it */ acpi_gbl_global_lock_acquired = TRUE; /* Run the Global Lock thread which will signal all waiting threads */ - status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH, - acpi_ev_global_lock_thread, - context); + status = + acpi_os_execute(OSL_GLOBAL_LOCK_HANDLER, + acpi_ev_global_lock_thread, context); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not queue Global Lock thread")); @@ -371,7 +377,7 @@ acpi_status acpi_ev_init_global_lock_han { acpi_status status; - ACPI_FUNCTION_TRACE("ev_init_global_lock_handler"); + ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); acpi_gbl_global_lock_present = TRUE; status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL, @@ -413,7 +419,7 @@ acpi_status acpi_ev_acquire_global_lock( acpi_status status = AE_OK; u8 acquired = FALSE; - ACPI_FUNCTION_TRACE("ev_acquire_global_lock"); + ACPI_FUNCTION_TRACE(ev_acquire_global_lock); #ifndef ACPI_APPLICATION /* Make sure that we actually have a global lock */ @@ -439,6 +445,7 @@ #endif ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired); if (acquired) { + /* We got the lock */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -458,8 +465,9 @@ #endif * Acquire the global lock semaphore first. * Since this wait will block, we must release the interpreter */ - status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, - timeout); + status = + acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, + timeout); return_ACPI_STATUS(status); } @@ -480,7 +488,7 @@ acpi_status acpi_ev_release_global_lock( u8 pending = FALSE; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ev_release_global_lock"); + ACPI_FUNCTION_TRACE(ev_release_global_lock); if (!acpi_gbl_global_lock_thread_count) { ACPI_WARNING((AE_INFO, @@ -492,6 +500,7 @@ acpi_status acpi_ev_release_global_lock( acpi_gbl_global_lock_thread_count--; if (acpi_gbl_global_lock_thread_count) { + /* There are still some threads holding the lock, cannot release */ return_ACPI_STATUS(AE_OK); @@ -533,7 +542,7 @@ void acpi_ev_terminate(void) acpi_native_uint i; acpi_status status; - ACPI_FUNCTION_TRACE("ev_terminate"); + ACPI_FUNCTION_TRACE(ev_terminate); if (acpi_gbl_events_initialized) { /* @@ -573,7 +582,7 @@ void acpi_ev_terminate(void) if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) { status = acpi_disable(); if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, "acpi_disable failed")); + ACPI_WARNING((AE_INFO, "AcpiDisable failed")); } } return_VOID; diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index 6da58e7..094a17e 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -83,7 +83,7 @@ acpi_status acpi_ev_install_region_handl acpi_status status; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ev_install_region_handlers"); + ACPI_FUNCTION_TRACE(ev_install_region_handlers); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -153,7 +153,7 @@ acpi_status acpi_ev_initialize_op_region acpi_status status; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ev_initialize_op_regions"); + ACPI_FUNCTION_TRACE(ev_initialize_op_regions); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -164,6 +164,7 @@ acpi_status acpi_ev_initialize_op_region * Run the _REG methods for op_regions in each default address space */ for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { + /* TBD: Make sure handler is the DEFAULT handler, otherwise * _REG will have already been run. */ @@ -192,12 +193,12 @@ acpi_status acpi_ev_initialize_op_region acpi_status acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) { - struct acpi_parameter_info info; - union acpi_operand_object *params[3]; + struct acpi_evaluate_info *info; + union acpi_operand_object *args[3]; union acpi_operand_object *region_obj2; acpi_status status; - ACPI_FUNCTION_TRACE("ev_execute_reg_method"); + ACPI_FUNCTION_TRACE(ev_execute_reg_method); region_obj2 = acpi_ns_get_secondary_object(region_obj); if (!region_obj2) { @@ -208,48 +209,60 @@ acpi_ev_execute_reg_method(union acpi_op return_ACPI_STATUS(AE_OK); } + /* Allocate and initialize the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->prefix_node = region_obj2->extra.method_REG; + info->pathname = NULL; + info->parameters = args; + info->parameter_type = ACPI_PARAM_ARGS; + info->flags = ACPI_IGNORE_RETURN_VALUE; + /* * The _REG method has two arguments: * - * Arg0, Integer: Operation region space ID - * Same value as region_obj->Region.space_id - * Arg1, Integer: connection status - * 1 for connecting the handler, - * 0 for disconnecting the handler - * Passed as a parameter + * Arg0 - Integer: + * Operation region space ID Same value as region_obj->Region.space_id + * + * Arg1 - Integer: + * connection status 1 for connecting the handler, 0 for disconnecting + * the handler (Passed as a parameter) */ - params[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!params[0]) { - return_ACPI_STATUS(AE_NO_MEMORY); + args[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!args[0]) { + status = AE_NO_MEMORY; + goto cleanup1; } - params[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); - if (!params[1]) { + args[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); + if (!args[1]) { status = AE_NO_MEMORY; - goto cleanup; + goto cleanup2; } /* Setup the parameter objects */ - params[0]->integer.value = region_obj->region.space_id; - params[1]->integer.value = function; - params[2] = NULL; - - info.node = region_obj2->extra.method_REG; - info.parameters = params; - info.parameter_type = ACPI_PARAM_ARGS; + args[0]->integer.value = region_obj->region.space_id; + args[1]->integer.value = function; + args[2] = NULL; /* Execute the method, no return value */ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_METHOD, info.node, NULL)); - status = acpi_ns_evaluate_by_handle(&info); + (ACPI_TYPE_METHOD, info->prefix_node, NULL)); - acpi_ut_remove_reference(params[1]); + status = acpi_ns_evaluate(info); + acpi_ut_remove_reference(args[1]); - cleanup: - acpi_ut_remove_reference(params[0]); + cleanup2: + acpi_ut_remove_reference(args[0]); + cleanup1: + ACPI_FREE(info); return_ACPI_STATUS(status); } @@ -261,7 +274,8 @@ acpi_ev_execute_reg_method(union acpi_op * Function - Read or Write operation * Address - Where in the space to read or write * bit_width - Field width in bits (8, 16, 32, or 64) - * Value - Pointer to in or out value + * Value - Pointer to in or out value, must be + * full 64-bit acpi_integer * * RETURN: Status * @@ -274,7 +288,7 @@ acpi_status acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, u32 function, acpi_physical_address address, - u32 bit_width, void *value) + u32 bit_width, acpi_integer * value) { acpi_status status; acpi_status status2; @@ -284,7 +298,7 @@ acpi_ev_address_space_dispatch(union acp union acpi_operand_object *region_obj2; void *region_context = NULL; - ACPI_FUNCTION_TRACE("ev_address_space_dispatch"); + ACPI_FUNCTION_TRACE(ev_address_space_dispatch); region_obj2 = acpi_ns_get_secondary_object(region_obj); if (!region_obj2) { @@ -315,6 +329,7 @@ acpi_ev_address_space_dispatch(union acp */ region_setup = handler_desc->address_space.setup; if (!region_setup) { + /* No initialization routine, exit with error */ ACPI_ERROR((AE_INFO, @@ -361,9 +376,10 @@ acpi_ev_address_space_dispatch(union acp region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; if (region_obj2->extra.region_context) { + /* The handler for this region was already installed */ - ACPI_MEM_FREE(region_context); + ACPI_FREE(region_context); } else { /* * Save the returned context for use in all accesses to @@ -386,9 +402,8 @@ acpi_ev_address_space_dispatch(union acp acpi_ut_get_region_name(region_obj->region. space_id))); - if (! - (handler_desc->address_space. - hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * For handlers other than the default (supplied) handlers, we must * exit the interpreter because the handler *might* block -- we don't @@ -409,9 +424,8 @@ acpi_ev_address_space_dispatch(union acp space_id))); } - if (! - (handler_desc->address_space. - hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * We just returned from a non-default handler, we must re-enter the * interpreter @@ -451,7 +465,7 @@ acpi_ev_detach_region(union acpi_operand union acpi_operand_object *region_obj2; acpi_status status; - ACPI_FUNCTION_TRACE("ev_detach_region"); + ACPI_FUNCTION_TRACE(ev_detach_region); region_obj2 = acpi_ns_get_secondary_object(region_obj); if (!region_obj2) { @@ -463,6 +477,7 @@ acpi_ev_detach_region(union acpi_operand handler_obj = region_obj->region.handler; if (!handler_obj) { + /* This region has no handler, all done */ return_VOID; @@ -474,6 +489,7 @@ acpi_ev_detach_region(union acpi_operand last_obj_ptr = &handler_obj->address_space.region_list; while (obj_desc) { + /* Is this the correct Region? */ if (obj_desc == region_obj) { @@ -583,7 +599,7 @@ acpi_ev_attach_region(union acpi_operand u8 acpi_ns_is_locked) { - ACPI_FUNCTION_TRACE("ev_attach_region"); + ACPI_FUNCTION_TRACE(ev_attach_region); ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Adding Region [%4.4s] %p to address handler %p [%s]\n", @@ -636,7 +652,7 @@ acpi_ev_install_handler(acpi_handle obj_ struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_NAME("ev_install_handler"); + ACPI_FUNCTION_NAME(ev_install_handler); handler_obj = (union acpi_operand_object *)context; @@ -666,6 +682,7 @@ acpi_ev_install_handler(acpi_handle obj_ obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { + /* No object, just exit */ return (AE_OK); @@ -674,10 +691,12 @@ acpi_ev_install_handler(acpi_handle obj_ /* Devices are handled different than regions */ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) { + /* Check if this Device already has a handler for this address space */ next_handler_obj = obj_desc->device.handler; while (next_handler_obj) { + /* Found a handler, is it for the same address space? */ if (next_handler_obj->address_space.space_id == @@ -764,9 +783,9 @@ acpi_ev_install_space_handler(struct acp union acpi_operand_object *handler_obj; acpi_status status; acpi_object_type type; - u16 flags = 0; + u8 flags = 0; - ACPI_FUNCTION_TRACE("ev_install_space_handler"); + ACPI_FUNCTION_TRACE(ev_install_space_handler); /* * This registration is valid for only the types below @@ -839,6 +858,7 @@ acpi_ev_install_space_handler(struct acp /* Walk the handler list for this device */ while (handler_obj) { + /* Same space_id indicates a handler already installed */ if (handler_obj->address_space.space_id == space_id) { @@ -921,7 +941,7 @@ acpi_ev_install_space_handler(struct acp /* Init handler obj */ handler_obj->address_space.space_id = (u8) space_id; - handler_obj->address_space.hflags = flags; + handler_obj->address_space.handler_flags = flags; handler_obj->address_space.region_list = NULL; handler_obj->address_space.node = node; handler_obj->address_space.handler = handler; @@ -979,7 +999,7 @@ acpi_ev_execute_reg_methods(struct acpi_ { acpi_status status; - ACPI_FUNCTION_TRACE("ev_execute_reg_methods"); + ACPI_FUNCTION_TRACE(ev_execute_reg_methods); /* * Run all _REG methods for all Operation Regions for this @@ -1001,7 +1021,7 @@ acpi_ev_execute_reg_methods(struct acpi_ * * PARAMETERS: walk_namespace callback * - * DESCRIPTION: Run _REg method for region objects of the requested space_iD + * DESCRIPTION: Run _REG method for region objects of the requested space_iD * ******************************************************************************/ @@ -1035,6 +1055,7 @@ acpi_ev_reg_run(acpi_handle obj_handle, obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { + /* No object, just exit */ return (AE_OK); diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index baed8c1..5b3c7a8 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c @@ -71,11 +71,22 @@ acpi_ev_system_memory_region_setup(acpi_ (union acpi_operand_object *)handle; struct acpi_mem_space_context *local_region_context; - ACPI_FUNCTION_TRACE("ev_system_memory_region_setup"); + ACPI_FUNCTION_TRACE(ev_system_memory_region_setup); if (function == ACPI_REGION_DEACTIVATE) { if (*region_context) { - ACPI_MEM_FREE(*region_context); + local_region_context = + (struct acpi_mem_space_context *)*region_context; + + /* Delete a cached mapping if present */ + + if (local_region_context->mapped_length) { + acpi_os_unmap_memory(local_region_context-> + mapped_logical_address, + local_region_context-> + mapped_length); + } + ACPI_FREE(local_region_context); *region_context = NULL; } return_ACPI_STATUS(AE_OK); @@ -84,7 +95,7 @@ acpi_ev_system_memory_region_setup(acpi_ /* Create a new context */ local_region_context = - ACPI_MEM_CALLOCATE(sizeof(struct acpi_mem_space_context)); + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); if (!(local_region_context)) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -118,7 +129,7 @@ acpi_ev_io_space_region_setup(acpi_handl u32 function, void *handler_context, void **region_context) { - ACPI_FUNCTION_TRACE("ev_io_space_region_setup"); + ACPI_FUNCTION_TRACE(ev_io_space_region_setup); if (function == ACPI_REGION_DEACTIVATE) { *region_context = NULL; @@ -161,7 +172,7 @@ acpi_ev_pci_config_region_setup(acpi_han (union acpi_operand_object *)handle; struct acpi_device_id object_hID; - ACPI_FUNCTION_TRACE("ev_pci_config_region_setup"); + ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); handler_obj = region_obj->region.handler; if (!handler_obj) { @@ -178,7 +189,7 @@ acpi_ev_pci_config_region_setup(acpi_han *region_context = NULL; if (function == ACPI_REGION_DEACTIVATE) { if (pci_id) { - ACPI_MEM_FREE(pci_id); + ACPI_FREE(pci_id); } return_ACPI_STATUS(status); } @@ -199,6 +210,7 @@ acpi_ev_pci_config_region_setup(acpi_han * handlers with that device. */ if (handler_obj->address_space.node == acpi_gbl_root_node) { + /* Start search from the parent object */ pci_root_node = parent_node; @@ -220,6 +232,7 @@ acpi_ev_pci_config_region_setup(acpi_han PCI_EXPRESS_ROOT_HID_STRING, sizeof(PCI_EXPRESS_ROOT_HID_STRING))))) { + /* Install a handler for this PCI root bridge */ status = @@ -235,7 +248,7 @@ acpi_ev_pci_config_region_setup(acpi_han } else { ACPI_EXCEPTION((AE_INFO, status, - "Could not install pci_config handler for Root Bridge %4.4s", + "Could not install PciConfig handler for Root Bridge %4.4s", acpi_ut_get_node_name (pci_root_node))); } @@ -262,7 +275,7 @@ acpi_ev_pci_config_region_setup(acpi_han /* Region is still not initialized. Create a new context */ - pci_id = ACPI_MEM_CALLOCATE(sizeof(struct acpi_pci_id)); + pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id)); if (!pci_id) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -337,7 +350,7 @@ acpi_ev_pci_bar_region_setup(acpi_handle u32 function, void *handler_context, void **region_context) { - ACPI_FUNCTION_TRACE("ev_pci_bar_region_setup"); + ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup); return_ACPI_STATUS(AE_OK); } @@ -364,7 +377,7 @@ acpi_ev_cmos_region_setup(acpi_handle ha u32 function, void *handler_context, void **region_context) { - ACPI_FUNCTION_TRACE("ev_cmos_region_setup"); + ACPI_FUNCTION_TRACE(ev_cmos_region_setup); return_ACPI_STATUS(AE_OK); } @@ -389,7 +402,7 @@ acpi_ev_default_region_setup(acpi_handle u32 function, void *handler_context, void **region_context) { - ACPI_FUNCTION_TRACE("ev_default_region_setup"); + ACPI_FUNCTION_TRACE(ev_default_region_setup); if (function == ACPI_REGION_DEACTIVATE) { *region_context = NULL; @@ -435,7 +448,7 @@ acpi_ev_initialize_region(union acpi_ope acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG; union acpi_operand_object *region_obj2; - ACPI_FUNCTION_TRACE_U32("ev_initialize_region", acpi_ns_locked); + ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked); if (!region_obj) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -462,8 +475,9 @@ acpi_ev_initialize_region(union acpi_ope /* Find any "_REG" method associated with this region definition */ - status = acpi_ns_search_node(*reg_name_ptr, node, - ACPI_TYPE_METHOD, &method_node); + status = + acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD, + &method_node); if (ACPI_SUCCESS(status)) { /* * The _REG method is optional and there can be only one per region @@ -478,11 +492,13 @@ acpi_ev_initialize_region(union acpi_ope * ie: acpi_gbl_root_node->parent_entry being set to NULL */ while (node) { + /* Check to see if a handler exists */ handler_obj = NULL; obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { + /* Can only be a handler if the object exists */ switch (node->type) { @@ -507,10 +523,12 @@ acpi_ev_initialize_region(union acpi_ope } while (handler_obj) { + /* Is this handler of the correct type? */ if (handler_obj->address_space.space_id == space_id) { + /* Found correct handler */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, @@ -571,7 +589,7 @@ acpi_ev_initialize_region(union acpi_ope /* If we get here, there is no handler for this region */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "No handler for region_type %s(%X) (region_obj %p)\n", + "No handler for RegionType %s(%X) (RegionObj %p)\n", acpi_ut_get_region_name(space_id), space_id, region_obj)); diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c index 9a62216..8106215 100644 --- a/drivers/acpi/events/evsci.c +++ b/drivers/acpi/events/evsci.c @@ -69,7 +69,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci struct acpi_gpe_xrupt_info *gpe_xrupt_list = context; u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; - ACPI_FUNCTION_TRACE("ev_sci_xrupt_handler"); + ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler); /* * We are guaranteed by the ACPI CA initialization/shutdown code that @@ -108,7 +108,7 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_ struct acpi_gpe_xrupt_info *gpe_xrupt_list = context; u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; - ACPI_FUNCTION_TRACE("ev_gpe_xrupt_handler"); + ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler); /* * We are guaranteed by the ACPI CA initialization/shutdown code that @@ -140,7 +140,7 @@ u32 acpi_ev_install_sci_handler(void) { u32 status = AE_OK; - ACPI_FUNCTION_TRACE("ev_install_sci_handler"); + ACPI_FUNCTION_TRACE(ev_install_sci_handler); status = acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT->sci_int, acpi_ev_sci_xrupt_handler, @@ -171,7 +171,7 @@ acpi_status acpi_ev_remove_sci_handler(v { acpi_status status; - ACPI_FUNCTION_TRACE("ev_remove_sci_handler"); + ACPI_FUNCTION_TRACE(ev_remove_sci_handler); /* Just let the OS remove the handler and disable the level */ diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index b38b39d..76c34a6 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -68,7 +66,7 @@ acpi_status acpi_install_exception_handl { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_install_exception_handler"); + ACPI_FUNCTION_TRACE(acpi_install_exception_handler); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { @@ -90,6 +88,8 @@ acpi_status acpi_install_exception_handl (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } + +ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) #endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -107,14 +107,13 @@ #endif /* ACPI_FUTURE_USAGE */ * event. * ******************************************************************************/ - acpi_status acpi_install_fixed_event_handler(u32 event, acpi_event_handler handler, void *context) { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_install_fixed_event_handler"); + ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler); /* Parameter validation */ @@ -161,7 +160,7 @@ acpi_install_fixed_event_handler(u32 eve return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_install_fixed_event_handler); +ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler) /******************************************************************************* * @@ -175,13 +174,12 @@ EXPORT_SYMBOL(acpi_install_fixed_event_h * DESCRIPTION: Disables the event and unregisters the event handler. * ******************************************************************************/ - acpi_status acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_remove_fixed_event_handler"); + ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler); /* Parameter validation */ @@ -216,7 +214,7 @@ acpi_remove_fixed_event_handler(u32 even return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_remove_fixed_event_handler); +ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler) /******************************************************************************* * @@ -235,7 +233,6 @@ EXPORT_SYMBOL(acpi_remove_fixed_event_ha * DESCRIPTION: Install a handler for notifies on an ACPI device * ******************************************************************************/ - acpi_status acpi_install_notify_handler(acpi_handle device, u32 handler_type, @@ -246,7 +243,7 @@ acpi_install_notify_handler(acpi_handle struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_install_notify_handler"); + ACPI_FUNCTION_TRACE(acpi_install_notify_handler); /* Parameter validation */ @@ -275,6 +272,7 @@ acpi_install_notify_handler(acpi_handle * only one global handler can be regsitered (per notify type). */ if (device == ACPI_ROOT_OBJECT) { + /* Make sure the handler is not already installed */ if (((handler_type & ACPI_SYSTEM_NOTIFY) && @@ -317,6 +315,7 @@ acpi_install_notify_handler(acpi_handle obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { + /* Object exists - make sure there's no handler */ if (((handler_type & ACPI_SYSTEM_NOTIFY) && @@ -370,6 +369,7 @@ acpi_install_notify_handler(acpi_handle } if (handler_type == ACPI_ALL_NOTIFY) { + /* Extra ref if installed in both */ acpi_ut_add_reference(notify_obj); @@ -381,7 +381,7 @@ acpi_install_notify_handler(acpi_handle return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_install_notify_handler); +ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) /******************************************************************************* * @@ -399,7 +399,6 @@ EXPORT_SYMBOL(acpi_install_notify_handle * DESCRIPTION: Remove a handler for notifies on an ACPI device * ******************************************************************************/ - acpi_status acpi_remove_notify_handler(acpi_handle device, u32 handler_type, acpi_notify_handler handler) @@ -409,7 +408,7 @@ acpi_remove_notify_handler(acpi_handle d struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_remove_notify_handler"); + ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); /* Parameter validation */ @@ -535,7 +534,7 @@ acpi_remove_notify_handler(acpi_handle d return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_remove_notify_handler); +ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) /******************************************************************************* * @@ -554,7 +553,6 @@ EXPORT_SYMBOL(acpi_remove_notify_handler * DESCRIPTION: Install a handler for a General Purpose Event. * ******************************************************************************/ - acpi_status acpi_install_gpe_handler(acpi_handle gpe_device, u32 gpe_number, @@ -565,7 +563,7 @@ acpi_install_gpe_handler(acpi_handle gpe acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("acpi_install_gpe_handler"); + ACPI_FUNCTION_TRACE(acpi_install_gpe_handler); /* Parameter validation */ @@ -596,7 +594,7 @@ acpi_install_gpe_handler(acpi_handle gpe /* Allocate and init handler object */ - handler = ACPI_MEM_CALLOCATE(sizeof(struct acpi_handler_info)); + handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info)); if (!handler) { status = AE_NO_MEMORY; goto unlock_and_exit; @@ -630,7 +628,7 @@ acpi_install_gpe_handler(acpi_handle gpe return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_install_gpe_handler); +ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) /******************************************************************************* * @@ -646,7 +644,6 @@ EXPORT_SYMBOL(acpi_install_gpe_handler); * DESCRIPTION: Remove a handler for a General Purpose acpi_event. * ******************************************************************************/ - acpi_status acpi_remove_gpe_handler(acpi_handle gpe_device, u32 gpe_number, acpi_event_handler address) @@ -656,7 +653,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_ acpi_status status; acpi_cpu_flags flags; - ACPI_FUNCTION_TRACE("acpi_remove_gpe_handler"); + ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler); /* Parameter validation */ @@ -724,14 +721,14 @@ acpi_remove_gpe_handler(acpi_handle gpe_ /* Now we can free the handler object */ - ACPI_MEM_FREE(handler); + ACPI_FREE(handler); unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_remove_gpe_handler); +ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) /******************************************************************************* * @@ -746,7 +743,6 @@ EXPORT_SYMBOL(acpi_remove_gpe_handler); * DESCRIPTION: Acquire the ACPI Global Lock * ******************************************************************************/ - acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) { acpi_status status; @@ -771,7 +767,7 @@ acpi_status acpi_acquire_global_lock(u16 return (status); } -EXPORT_SYMBOL(acpi_acquire_global_lock); +ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock) /******************************************************************************* * @@ -784,7 +780,6 @@ EXPORT_SYMBOL(acpi_acquire_global_lock); * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. * ******************************************************************************/ - acpi_status acpi_release_global_lock(u32 handle) { acpi_status status; @@ -797,4 +792,4 @@ acpi_status acpi_release_global_lock(u32 return (status); } -EXPORT_SYMBOL(acpi_release_global_lock); +ACPI_EXPORT_SYMBOL(acpi_release_global_lock) diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index ec9ce84..7ebc2ef 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -65,7 +63,7 @@ acpi_status acpi_enable(void) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_enable"); + ACPI_FUNCTION_TRACE(acpi_enable); /* Make sure we have the FADT */ @@ -94,6 +92,8 @@ acpi_status acpi_enable(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_enable) + /******************************************************************************* * * FUNCTION: acpi_disable @@ -105,12 +105,11 @@ acpi_status acpi_enable(void) * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode. * ******************************************************************************/ - acpi_status acpi_disable(void) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_disable"); + ACPI_FUNCTION_TRACE(acpi_disable); if (!acpi_gbl_FADT) { ACPI_WARNING((AE_INFO, "No FADT information present!")); @@ -137,6 +136,8 @@ acpi_status acpi_disable(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_disable) + /******************************************************************************* * * FUNCTION: acpi_enable_event @@ -149,13 +150,12 @@ acpi_status acpi_disable(void) * DESCRIPTION: Enable an ACPI event (fixed) * ******************************************************************************/ - acpi_status acpi_enable_event(u32 event, u32 flags) { acpi_status status = AE_OK; u32 value; - ACPI_FUNCTION_TRACE("acpi_enable_event"); + ACPI_FUNCTION_TRACE(acpi_enable_event); /* Decode the Fixed Event */ @@ -193,7 +193,7 @@ acpi_status acpi_enable_event(u32 event, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_enable_event); +ACPI_EXPORT_SYMBOL(acpi_enable_event) /******************************************************************************* * @@ -208,13 +208,12 @@ EXPORT_SYMBOL(acpi_enable_event); * DESCRIPTION: Set the type of an individual GPE * ******************************************************************************/ - acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type) { acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE("acpi_set_gpe_type"); + ACPI_FUNCTION_TRACE(acpi_set_gpe_type); /* Ensure that we have a valid GPE number */ @@ -236,7 +235,7 @@ acpi_status acpi_set_gpe_type(acpi_handl return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_set_gpe_type); +ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) /******************************************************************************* * @@ -252,13 +251,12 @@ EXPORT_SYMBOL(acpi_set_gpe_type); * DESCRIPTION: Enable an ACPI event (general purpose) * ******************************************************************************/ - acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) { acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE("acpi_enable_gpe"); + ACPI_FUNCTION_TRACE(acpi_enable_gpe); /* Use semaphore lock if not executing at interrupt level */ @@ -288,7 +286,7 @@ acpi_status acpi_enable_gpe(acpi_handle return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_enable_gpe); +ACPI_EXPORT_SYMBOL(acpi_enable_gpe) /******************************************************************************* * @@ -304,13 +302,12 @@ EXPORT_SYMBOL(acpi_enable_gpe); * DESCRIPTION: Disable an ACPI event (general purpose) * ******************************************************************************/ - acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) { acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE("acpi_disable_gpe"); + ACPI_FUNCTION_TRACE(acpi_disable_gpe); /* Use semaphore lock if not executing at interrupt level */ @@ -338,6 +335,8 @@ acpi_status acpi_disable_gpe(acpi_handle return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_disable_gpe) + /******************************************************************************* * * FUNCTION: acpi_disable_event @@ -350,13 +349,12 @@ acpi_status acpi_disable_gpe(acpi_handle * DESCRIPTION: Disable an ACPI event (fixed) * ******************************************************************************/ - acpi_status acpi_disable_event(u32 event, u32 flags) { acpi_status status = AE_OK; u32 value; - ACPI_FUNCTION_TRACE("acpi_disable_event"); + ACPI_FUNCTION_TRACE(acpi_disable_event); /* Decode the Fixed Event */ @@ -392,7 +390,7 @@ acpi_status acpi_disable_event(u32 event return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_disable_event); +ACPI_EXPORT_SYMBOL(acpi_disable_event) /******************************************************************************* * @@ -405,12 +403,11 @@ EXPORT_SYMBOL(acpi_disable_event); * DESCRIPTION: Clear an ACPI event (fixed) * ******************************************************************************/ - acpi_status acpi_clear_event(u32 event) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_clear_event"); + ACPI_FUNCTION_TRACE(acpi_clear_event); /* Decode the Fixed Event */ @@ -429,7 +426,7 @@ acpi_status acpi_clear_event(u32 event) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_clear_event); +ACPI_EXPORT_SYMBOL(acpi_clear_event) /******************************************************************************* * @@ -444,13 +441,12 @@ EXPORT_SYMBOL(acpi_clear_event); * DESCRIPTION: Clear an ACPI event (general purpose) * ******************************************************************************/ - acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) { acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE("acpi_clear_gpe"); + ACPI_FUNCTION_TRACE(acpi_clear_gpe); /* Use semaphore lock if not executing at interrupt level */ @@ -478,6 +474,8 @@ acpi_status acpi_clear_gpe(acpi_handle g return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_clear_gpe) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -492,12 +490,11 @@ #ifdef ACPI_FUTURE_USAGE * DESCRIPTION: Obtains and returns the current status of the event * ******************************************************************************/ - acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_get_event_status"); + ACPI_FUNCTION_TRACE(acpi_get_event_status); if (!event_status) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -518,6 +515,8 @@ acpi_status acpi_get_event_status(u32 ev return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_get_event_status) + /******************************************************************************* * * FUNCTION: acpi_get_gpe_status @@ -533,7 +532,6 @@ acpi_status acpi_get_event_status(u32 ev * DESCRIPTION: Get status of an event (general purpose) * ******************************************************************************/ - acpi_status acpi_get_gpe_status(acpi_handle gpe_device, u32 gpe_number, u32 flags, acpi_event_status * event_status) @@ -541,7 +539,7 @@ acpi_get_gpe_status(acpi_handle gpe_devi acpi_status status = AE_OK; struct acpi_gpe_event_info *gpe_event_info; - ACPI_FUNCTION_TRACE("acpi_get_gpe_status"); + ACPI_FUNCTION_TRACE(acpi_get_gpe_status); /* Use semaphore lock if not executing at interrupt level */ @@ -570,6 +568,8 @@ acpi_get_gpe_status(acpi_handle gpe_devi } return_ACPI_STATUS(status); } + +ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) #endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -586,7 +586,6 @@ #endif /* ACPI_FUTURE_USAGE */ * DESCRIPTION: Create and Install a block of GPE registers * ******************************************************************************/ - acpi_status acpi_install_gpe_block(acpi_handle gpe_device, struct acpi_generic_address *gpe_block_address, @@ -597,7 +596,7 @@ acpi_install_gpe_block(acpi_handle gpe_d struct acpi_namespace_node *node; struct acpi_gpe_block_info *gpe_block; - ACPI_FUNCTION_TRACE("acpi_install_gpe_block"); + ACPI_FUNCTION_TRACE(acpi_install_gpe_block); if ((!gpe_device) || (!gpe_block_address) || (!register_count)) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -636,6 +635,7 @@ acpi_install_gpe_block(acpi_handle gpe_d obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { + /* No object, create a new one */ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); @@ -665,7 +665,7 @@ acpi_install_gpe_block(acpi_handle gpe_d return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_install_gpe_block); +ACPI_EXPORT_SYMBOL(acpi_install_gpe_block) /******************************************************************************* * @@ -678,14 +678,13 @@ EXPORT_SYMBOL(acpi_install_gpe_block); * DESCRIPTION: Remove a previously installed block of GPE registers * ******************************************************************************/ - acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) { union acpi_operand_object *obj_desc; acpi_status status; struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE("acpi_remove_gpe_block"); + ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); if (!gpe_device) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -721,4 +720,4 @@ acpi_status acpi_remove_gpe_block(acpi_h return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_remove_gpe_block); +ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block) diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c index abf5cac..e8b86a0 100644 --- a/drivers/acpi/events/evxfregn.c +++ b/drivers/acpi/events/evxfregn.c @@ -42,8 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -75,7 +73,7 @@ acpi_install_address_space_handler(acpi_ struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_install_address_space_handler"); + ACPI_FUNCTION_TRACE(acpi_install_address_space_handler); /* Parameter validation */ @@ -114,7 +112,7 @@ acpi_install_address_space_handler(acpi_ return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_install_address_space_handler); +ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler) /******************************************************************************* * @@ -129,7 +127,6 @@ EXPORT_SYMBOL(acpi_install_address_space * DESCRIPTION: Remove a previously installed handler. * ******************************************************************************/ - acpi_status acpi_remove_address_space_handler(acpi_handle device, acpi_adr_space_type space_id, @@ -142,7 +139,7 @@ acpi_remove_address_space_handler(acpi_h struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_remove_address_space_handler"); + ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler); /* Parameter validation */ @@ -176,9 +173,11 @@ acpi_remove_address_space_handler(acpi_h handler_obj = obj_desc->device.handler; last_obj_ptr = &obj_desc->device.handler; while (handler_obj) { + /* We have a handler, see if user requested this one */ if (handler_obj->address_space.space_id == space_id) { + /* Matched space_id, first dereference this in the Regions */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, @@ -229,7 +228,7 @@ acpi_remove_address_space_handler(acpi_h /* The handler does not exist */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Unable to remove address handler %p for %s(%X), dev_node %p, obj %p\n", + "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n", handler, acpi_ut_get_region_name(space_id), space_id, node, obj_desc)); @@ -240,4 +239,4 @@ acpi_remove_address_space_handler(acpi_h return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_remove_address_space_handler); +ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler) diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index a29782f..8233524 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -82,7 +82,7 @@ acpi_ex_add_table(struct acpi_table_head struct acpi_table_desc table_info; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE("ex_add_table"); + ACPI_FUNCTION_TRACE(ex_add_table); /* Create an object to be the table handle */ @@ -100,7 +100,7 @@ acpi_ex_add_table(struct acpi_table_head ACPI_MEMSET(&table_info, 0, sizeof(struct acpi_table_desc)); - table_info.type = ACPI_TABLE_SSDT; + table_info.type = ACPI_TABLE_ID_SSDT; table_info.pointer = table; table_info.length = (acpi_size) table->length; table_info.allocation = ACPI_MEM_ALLOCATED; @@ -110,6 +110,7 @@ acpi_ex_add_table(struct acpi_table_head if (ACPI_FAILURE(status)) { if (status == AE_ALREADY_EXISTS) { + /* Table already exists, just return the handle */ return_ACPI_STATUS(AE_OK); @@ -121,6 +122,7 @@ acpi_ex_add_table(struct acpi_table_head status = acpi_ns_load_table(table_info.installed_desc, parent_node); if (ACPI_FAILURE(status)) { + /* Uninstall table on error */ (void)acpi_tb_uninstall_table(table_info.installed_desc); @@ -160,7 +162,7 @@ acpi_ex_load_table_op(struct acpi_walk_s struct acpi_namespace_node *parameter_node = NULL; union acpi_operand_object *ddb_handle; - ACPI_FUNCTION_TRACE("ex_load_table_op"); + ACPI_FUNCTION_TRACE(ex_load_table_op); #if 0 /* @@ -169,6 +171,7 @@ #if 0 */ status = acpi_tb_match_signature(operand[0]->string.pointer, NULL); if (status == AE_OK) { + /* Signature matched -- don't allow override */ return_ACPI_STATUS(AE_ALREADY_EXISTS); @@ -211,9 +214,8 @@ #endif * location within the namespace where the table will be loaded. */ status = - acpi_ns_get_node_by_path(operand[3]->string.pointer, - start_node, ACPI_NS_SEARCH_PARENT, - &parent_node); + acpi_ns_get_node(start_node, operand[3]->string.pointer, + ACPI_NS_SEARCH_PARENT, &parent_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -234,9 +236,8 @@ #endif /* Find the node referenced by the parameter_path_string */ status = - acpi_ns_get_node_by_path(operand[4]->string.pointer, - start_node, ACPI_NS_SEARCH_PARENT, - ¶meter_node); + acpi_ns_get_node(start_node, operand[4]->string.pointer, + ACPI_NS_SEARCH_PARENT, ¶meter_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -252,6 +253,7 @@ #endif /* Parameter Data (optional) */ if (parameter_node) { + /* Store the parameter data into the optional parameter object */ status = acpi_ex_store(operand[5], @@ -294,9 +296,10 @@ acpi_ex_load_op(union acpi_operand_objec struct acpi_table_header *table_ptr = NULL; acpi_physical_address address; struct acpi_table_header table_header; + acpi_integer temp; u32 i; - ACPI_FUNCTION_TRACE("ex_load_op"); + ACPI_FUNCTION_TRACE(ex_load_op); /* Object can be either an op_region or a Field */ @@ -322,7 +325,7 @@ acpi_ex_load_op(union acpi_operand_objec address = obj_desc->region.address; - /* Get the table length from the table header */ + /* Get part of the table header to get the table length */ table_header.length = 0; for (i = 0; i < 8; i++) { @@ -330,11 +333,14 @@ acpi_ex_load_op(union acpi_operand_objec acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, (acpi_physical_address) (i + address), 8, - ((u8 *) & - table_header) + i); + &temp); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + + /* Get the one valid byte of the returned 64-bit value */ + + ACPI_CAST_PTR(u8, &table_header)[i] = (u8) temp; } /* Sanity check the table length */ @@ -345,7 +351,7 @@ acpi_ex_load_op(union acpi_operand_objec /* Allocate a buffer for the entire table */ - table_ptr = ACPI_MEM_ALLOCATE(table_header.length); + table_ptr = ACPI_ALLOCATE(table_header.length); if (!table_ptr) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -357,11 +363,14 @@ acpi_ex_load_op(union acpi_operand_objec acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, (acpi_physical_address) (i + address), 8, - ((u8 *) table_ptr + - i)); + &temp); if (ACPI_FAILURE(status)) { goto cleanup; } + + /* Get the one valid byte of the returned 64-bit value */ + + ACPI_CAST_PTR(u8, table_ptr)[i] = (u8) temp; } break; @@ -407,12 +416,8 @@ acpi_ex_load_op(union acpi_operand_objec /* The table must be either an SSDT or a PSDT */ - if ((!ACPI_STRNCMP(table_ptr->signature, - acpi_gbl_table_data[ACPI_TABLE_PSDT].signature, - acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) && - (!ACPI_STRNCMP(table_ptr->signature, - acpi_gbl_table_data[ACPI_TABLE_SSDT].signature, - acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) { + if ((!ACPI_COMPARE_NAME(table_ptr->signature, PSDT_SIG)) && + (!ACPI_COMPARE_NAME(table_ptr->signature, SSDT_SIG))) { ACPI_ERROR((AE_INFO, "Table has invalid signature [%4.4s], must be SSDT or PSDT", table_ptr->signature)); @@ -424,6 +429,7 @@ acpi_ex_load_op(union acpi_operand_objec status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle); if (ACPI_FAILURE(status)) { + /* On error, table_ptr was deallocated above */ return_ACPI_STATUS(status); @@ -442,7 +448,7 @@ acpi_ex_load_op(union acpi_operand_objec cleanup: if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(table_ptr); + ACPI_FREE(table_ptr); } return_ACPI_STATUS(status); } @@ -465,7 +471,7 @@ acpi_status acpi_ex_unload_table(union a union acpi_operand_object *table_desc = ddb_handle; struct acpi_table_desc *table_info; - ACPI_FUNCTION_TRACE("ex_unload_table"); + ACPI_FUNCTION_TRACE(ex_unload_table); /* * Validate the handle diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index e6d52e1..b732e39 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c @@ -79,7 +79,7 @@ acpi_ex_convert_to_integer(union acpi_op u32 count; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ex_convert_to_integer", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc); switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_INTEGER: @@ -199,7 +199,7 @@ acpi_ex_convert_to_buffer(union acpi_ope union acpi_operand_object *return_desc; u8 *new_buf; - ACPI_FUNCTION_TRACE_PTR("ex_convert_to_buffer", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc); switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_BUFFER: @@ -319,6 +319,7 @@ acpi_ex_convert_to_ascii(acpi_integer in remainder = 0; for (i = decimal_length; i > 0; i--) { + /* Divide by nth factor of 10 */ digit = integer; @@ -346,6 +347,7 @@ acpi_ex_convert_to_ascii(acpi_integer in hex_length = (acpi_native_uint) ACPI_MUL_2(data_width); for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) { + /* Get one hex digit, most significant digits first */ string[k] = @@ -400,7 +402,7 @@ acpi_ex_convert_to_string(union acpi_ope u16 base = 16; u8 separator = ','; - ACPI_FUNCTION_TRACE_PTR("ex_convert_to_string", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc); switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_STRING: @@ -567,7 +569,7 @@ acpi_ex_convert_to_target_type(acpi_obje { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_convert_to_target_type"); + ACPI_FUNCTION_TRACE(ex_convert_to_target_type); /* Default behavior */ @@ -657,7 +659,7 @@ acpi_ex_convert_to_target_type(acpi_obje default: ACPI_ERROR((AE_INFO, - "Unknown Target type ID 0x%X aml_opcode %X dest_type %s", + "Unknown Target type ID 0x%X AmlOpcode %X DestType %s", GET_CURRENT_ARG_TYPE(walk_state->op_info-> runtime_args), walk_state->opcode, diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 6805754..106dc72 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -69,7 +69,7 @@ acpi_status acpi_ex_create_alias(struct struct acpi_namespace_node *alias_node; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_create_alias"); + ACPI_FUNCTION_TRACE(ex_create_alias); /* Get the source/alias operands (both namespace nodes) */ @@ -164,7 +164,7 @@ acpi_status acpi_ex_create_event(struct acpi_status status; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE("ex_create_event"); + ACPI_FUNCTION_TRACE(ex_create_event); obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT); if (!obj_desc) { @@ -216,7 +216,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_status status = AE_OK; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE_PTR("ex_create_mutex", ACPI_WALK_OPERANDS); + ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS); /* Create the new mutex object */ @@ -243,8 +243,9 @@ acpi_status acpi_ex_create_mutex(struct obj_desc->mutex.node = (struct acpi_namespace_node *)walk_state->operands[0]; - status = acpi_ns_attach_object(obj_desc->mutex.node, - obj_desc, ACPI_TYPE_MUTEX); + status = + acpi_ns_attach_object(obj_desc->mutex.node, obj_desc, + ACPI_TYPE_MUTEX); cleanup: /* @@ -280,7 +281,7 @@ acpi_ex_create_region(u8 * aml_start, struct acpi_namespace_node *node; union acpi_operand_object *region_obj2; - ACPI_FUNCTION_TRACE("ex_create_region"); + ACPI_FUNCTION_TRACE(ex_create_region); /* Get the Namespace Node */ @@ -300,7 +301,7 @@ acpi_ex_create_region(u8 * aml_start, */ if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) && (region_space < ACPI_USER_REGION_BEGIN)) { - ACPI_ERROR((AE_INFO, "Invalid address_space type %X", + ACPI_ERROR((AE_INFO, "Invalid AddressSpace type %X", region_space)); return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); } @@ -364,7 +365,7 @@ acpi_status acpi_ex_create_table_region( struct acpi_table_header *table; union acpi_operand_object *region_obj2; - ACPI_FUNCTION_TRACE("ex_create_table_region"); + ACPI_FUNCTION_TRACE(ex_create_table_region); /* Get the Node from the object stack */ @@ -452,7 +453,7 @@ acpi_status acpi_ex_create_processor(str union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ex_create_processor", walk_state); + ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state); /* Create the processor object */ @@ -464,9 +465,9 @@ acpi_status acpi_ex_create_processor(str /* Initialize the processor object from the operands */ obj_desc->processor.proc_id = (u8) operand[1]->integer.value; + obj_desc->processor.length = (u8) operand[3]->integer.value; obj_desc->processor.address = (acpi_io_address) operand[2]->integer.value; - obj_desc->processor.length = (u8) operand[3]->integer.value; /* Install the processor object in the parent Node */ @@ -499,7 +500,7 @@ acpi_status acpi_ex_create_power_resourc acpi_status status; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE_PTR("ex_create_power_resource", walk_state); + ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state); /* Create the power resource object */ @@ -549,7 +550,7 @@ acpi_ex_create_method(u8 * aml_start, acpi_status status; u8 method_flags; - ACPI_FUNCTION_TRACE_PTR("ex_create_method", walk_state); + ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state); /* Create a new method object */ diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index a7cca8d..7b9718e 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -61,6 +61,10 @@ static void acpi_ex_out_pointer(char *ti static void acpi_ex_out_address(char *title, acpi_physical_address value); +static void +acpi_ex_dump_object(union acpi_operand_object *obj_desc, + struct acpi_exdump_info *info); + static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc); static void @@ -119,7 +123,7 @@ static struct acpi_exdump_info acpi_ex_d static struct acpi_exdump_info acpi_ex_dump_method[8] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL}, - {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "param_count"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "ParamCount"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.concurrency), "Concurrency"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.semaphore), "Semaphore"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"}, @@ -263,12 +267,10 @@ static struct acpi_exdump_info acpi_ex_d {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(common_field.node), "Parent Node"} }; -static struct acpi_exdump_info acpi_ex_dump_node[6] = { +static struct acpi_exdump_info acpi_ex_dump_node[5] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"}, {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"}, - {ACPI_EXD_UINT16, ACPI_EXD_NSOFFSET(reference_count), - "Reference Count"}, {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(child), "Child List"}, {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(peer), "Next Peer"} }; @@ -330,7 +332,7 @@ acpi_ex_dump_object(union acpi_operand_o if (!info) { acpi_os_printf - ("ex_dump_object: Display not implemented for object type %s\n", + ("ExDumpObject: Display not implemented for object type %s\n", acpi_ut_get_object_type_name(obj_desc)); return; } @@ -454,7 +456,7 @@ void acpi_ex_dump_operand(union acpi_ope u32 length; u32 index; - ACPI_FUNCTION_NAME("ex_dump_operand") + ACPI_FUNCTION_NAME(ex_dump_operand) if (! ((ACPI_LV_EXEC & acpi_dbg_level) @@ -463,6 +465,7 @@ void acpi_ex_dump_operand(union acpi_ope } if (!obj_desc) { + /* This could be a null element of a package */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n")); @@ -522,7 +525,7 @@ void acpi_ex_dump_operand(union acpi_ope case AML_REF_OF_OP: - acpi_os_printf("Reference: (ref_of) %p\n", + acpi_os_printf("Reference: (RefOf) %p\n", obj_desc->reference.object); break; @@ -532,6 +535,7 @@ void acpi_ex_dump_operand(union acpi_ope obj_desc->reference.offset); if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + /* Value is an Integer */ acpi_os_printf(" value is [%8.8X%8.8x]", @@ -610,7 +614,7 @@ void acpi_ex_dump_operand(union acpi_ope case ACPI_TYPE_PACKAGE: - acpi_os_printf("Package [Len %X] element_array %p\n", + acpi_os_printf("Package [Len %X] ElementArray %p\n", obj_desc->package.count, obj_desc->package.elements); @@ -662,13 +666,13 @@ void acpi_ex_dump_operand(union acpi_ope case ACPI_TYPE_LOCAL_BANK_FIELD: - acpi_os_printf("bank_field\n"); + acpi_os_printf("BankField\n"); break; case ACPI_TYPE_LOCAL_REGION_FIELD: acpi_os_printf - ("region_field: Bits=%X acc_width=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n", + ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n", obj_desc->field.bit_length, obj_desc->field.access_byte_width, obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK, @@ -681,12 +685,12 @@ void acpi_ex_dump_operand(union acpi_ope case ACPI_TYPE_LOCAL_INDEX_FIELD: - acpi_os_printf("index_field\n"); + acpi_os_printf("IndexField\n"); break; case ACPI_TYPE_BUFFER_FIELD: - acpi_os_printf("buffer_field: %X bits at byte %X bit %X of\n", + acpi_os_printf("BufferField: %X bits at byte %X bit %X of\n", obj_desc->buffer_field.bit_length, obj_desc->buffer_field.base_byte_offset, obj_desc->buffer_field.start_field_bit_offset); @@ -777,7 +781,7 @@ acpi_ex_dump_operands(union acpi_operand { acpi_native_uint i; - ACPI_FUNCTION_NAME("ex_dump_operands"); + ACPI_FUNCTION_NAME(ex_dump_operands); if (!ident) { ident = "?"; @@ -901,7 +905,7 @@ static void acpi_ex_dump_reference_obj(u acpi_os_printf("Could not convert name to pathname\n"); } else { acpi_os_printf("%s\n", (char *)ret_buf.pointer); - ACPI_MEM_FREE(ret_buf.pointer); + ACPI_FREE(ret_buf.pointer); } } else if (obj_desc->reference.object) { acpi_os_printf("\nReferenced Object: %p\n", @@ -1017,7 +1021,7 @@ acpi_ex_dump_package_obj(union acpi_oper void acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) { - ACPI_FUNCTION_TRACE("ex_dump_object_descriptor"); + ACPI_FUNCTION_TRACE(ex_dump_object_descriptor); if (!obj_desc) { return_VOID; @@ -1046,7 +1050,7 @@ acpi_ex_dump_object_descriptor(union acp if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) { acpi_os_printf - ("ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n", + ("ExDumpObjectDescriptor: %p is not an ACPI operand object: [%s]\n", obj_desc, acpi_ut_get_descriptor_name(obj_desc)); return_VOID; } diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index e259201..9ea9c3a 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c @@ -73,7 +73,7 @@ acpi_ex_read_data_from_field(struct acpi void *buffer; u8 locked; - ACPI_FUNCTION_TRACE_PTR("ex_read_data_from_field", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); /* Parameter validation */ @@ -142,6 +142,7 @@ acpi_ex_read_data_from_field(struct acpi length = (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length); if (length > acpi_gbl_integer_byte_width) { + /* Field is too large for an Integer, create a Buffer instead */ buffer_desc = acpi_ut_create_buffer_object(length); @@ -163,11 +164,11 @@ acpi_ex_read_data_from_field(struct acpi } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "field_read [TO]: Obj %p, Type %X, Buf %p, byte_len %X\n", + "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", obj_desc, ACPI_GET_OBJECT_TYPE(obj_desc), buffer, (u32) length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "field_read [FROM]: bit_len %X, bit_off %X, byte_off %X\n", + "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", obj_desc->common_field.bit_length, obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.base_byte_offset)); @@ -219,7 +220,7 @@ acpi_ex_write_data_to_field(union acpi_o u8 locked; union acpi_operand_object *buffer_desc; - ACPI_FUNCTION_TRACE_PTR("ex_write_data_to_field", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); /* Parameter validation */ @@ -329,9 +330,10 @@ acpi_ex_write_data_to_field(union acpi_o ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); if (length < required_length) { + /* We need to create a new buffer */ - new_buffer = ACPI_MEM_CALLOCATE(required_length); + new_buffer = ACPI_ALLOCATE_ZEROED(required_length); if (!new_buffer) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -347,14 +349,14 @@ acpi_ex_write_data_to_field(union acpi_o } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %X\n", + "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", source_desc, acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE (source_desc)), ACPI_GET_OBJECT_TYPE(source_desc), buffer, length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "field_write [TO]: Obj %p (%s:%X), bit_len %X, bit_off %X, byte_off %X\n", + "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", obj_desc, acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)), ACPI_GET_OBJECT_TYPE(obj_desc), @@ -375,7 +377,7 @@ acpi_ex_write_data_to_field(union acpi_o /* Free temporary buffer if we used one */ if (new_buffer) { - ACPI_MEM_FREE(new_buffer); + ACPI_FREE(new_buffer); } return_ACPI_STATUS(status); diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index bd1af35..051053f 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -87,7 +87,7 @@ acpi_ex_setup_region(union acpi_operand_ acpi_status status = AE_OK; union acpi_operand_object *rgn_desc; - ACPI_FUNCTION_TRACE_U32("ex_setup_region", field_datum_byte_offset); + ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset); rgn_desc = obj_desc->common_field.region_obj; @@ -112,7 +112,18 @@ acpi_ex_setup_region(union acpi_operand_ } } + /* Exit if Address/Length have been disallowed by the host OS */ + + if (rgn_desc->common.flags & AOPOBJ_INVALID) { + return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); + } + + /* + * Exit now for SMBus address space, it has a non-linear address space + * and the request cannot be directly validated + */ if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { + /* SMBus has a non-linear address space */ return_ACPI_STATUS(AE_OK); @@ -134,10 +145,10 @@ #endif * length of one field datum (access width) must fit within the region. * (Region length is specified in bytes) */ - if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset + - field_datum_byte_offset + - obj_desc->common_field. - access_byte_width)) { + if (rgn_desc->region.length < + (obj_desc->common_field.base_byte_offset + + field_datum_byte_offset + + obj_desc->common_field.access_byte_width)) { if (acpi_gbl_enable_interpreter_slack) { /* * Slack mode only: We will go ahead and allow access to this @@ -217,7 +228,7 @@ acpi_ex_access_region(union acpi_operand union acpi_operand_object *rgn_desc; acpi_physical_address address; - ACPI_FUNCTION_TRACE("ex_access_region"); + ACPI_FUNCTION_TRACE(ex_access_region); /* * Ensure that the region operands are fully evaluated and verify @@ -246,7 +257,7 @@ acpi_ex_access_region(union acpi_operand } ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, - " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n", + " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n", acpi_ut_get_region_name(rgn_desc->region. space_id), rgn_desc->region.space_id, @@ -352,7 +363,7 @@ acpi_ex_field_datum_io(union acpi_operan acpi_status status; acpi_integer local_value; - ACPI_FUNCTION_TRACE_U32("ex_field_datum_io", field_datum_byte_offset); + ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset); if (read_write == ACPI_READ) { if (!value) { @@ -487,10 +498,11 @@ acpi_ex_field_datum_io(union acpi_operan } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "I/O to Data Register: value_ptr %p\n", + "I/O to Data Register: ValuePtr %p\n", value)); if (read_write == ACPI_READ) { + /* Read the datum from the data_register */ status = @@ -559,7 +571,7 @@ acpi_ex_write_with_update_rule(union acp acpi_integer merged_value; acpi_integer current_value; - ACPI_FUNCTION_TRACE_U32("ex_write_with_update_rule", mask); + ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask); /* Start with the new bits */ @@ -568,6 +580,7 @@ acpi_ex_write_with_update_rule(union acp /* If the mask is all ones, we don't need to worry about the update rule */ if (mask != ACPI_INTEGER_MAX) { + /* Decode the update rule */ switch (obj_desc->common_field. @@ -614,7 +627,7 @@ acpi_ex_write_with_update_rule(union acp default: ACPI_ERROR((AE_INFO, - "Unknown update_rule value: %X", + "Unknown UpdateRule value: %X", (obj_desc->common_field. field_flags & AML_FIELD_UPDATE_RULE_MASK))); @@ -623,7 +636,7 @@ acpi_ex_write_with_update_rule(union acp } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n", + "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n", ACPI_FORMAT_UINT64(mask), field_datum_byte_offset, obj_desc->common_field.access_byte_width, @@ -666,7 +679,7 @@ acpi_ex_extract_from_field(union acpi_op u32 field_datum_count; u32 i; - ACPI_FUNCTION_TRACE("ex_extract_from_field"); + ACPI_FUNCTION_TRACE(ex_extract_from_field); /* Validate target buffer and clear it */ @@ -704,6 +717,7 @@ acpi_ex_extract_from_field(union acpi_op /* Read the rest of the field */ for (i = 1; i < field_datum_count; i++) { + /* Get next input datum from the field */ field_offset += obj_desc->common_field.access_byte_width; @@ -771,6 +785,7 @@ acpi_ex_insert_into_field(union acpi_ope { acpi_status status; acpi_integer mask; + acpi_integer width_mask; acpi_integer merged_datum; acpi_integer raw_datum = 0; u32 field_offset = 0; @@ -780,7 +795,7 @@ acpi_ex_insert_into_field(union acpi_ope u32 field_datum_count; u32 i; - ACPI_FUNCTION_TRACE("ex_insert_into_field"); + ACPI_FUNCTION_TRACE(ex_insert_into_field); /* Validate input buffer */ @@ -795,15 +810,20 @@ acpi_ex_insert_into_field(union acpi_ope /* Compute the number of datums (access width data items) */ + width_mask = + ACPI_MASK_BITS_ABOVE(obj_desc->common_field.access_bit_width); mask = - ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset); - datum_count = - ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, - obj_desc->common_field.access_bit_width); - field_datum_count = - ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + - obj_desc->common_field.start_field_bit_offset, - obj_desc->common_field.access_bit_width); + width_mask & ACPI_MASK_BITS_BELOW(obj_desc->common_field. + start_field_bit_offset); + + datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, + obj_desc->common_field.access_bit_width); + + field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + + obj_desc->common_field. + start_field_bit_offset, + obj_desc->common_field. + access_bit_width); /* Get initial Datum from the input buffer */ @@ -817,6 +837,7 @@ acpi_ex_insert_into_field(union acpi_ope /* Write the entire field */ for (i = 1; i < field_datum_count; i++) { + /* Write merged datum to the target field */ merged_datum &= mask; @@ -833,7 +854,7 @@ acpi_ex_insert_into_field(union acpi_ope merged_datum = raw_datum >> (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset); - mask = ACPI_INTEGER_MAX; + mask = width_mask; if (i == datum_count) { break; diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index 48c18d2..bd98aab 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c @@ -72,7 +72,7 @@ acpi_ex_get_object_reference(union acpi_ union acpi_operand_object *reference_obj; union acpi_operand_object *referenced_obj; - ACPI_FUNCTION_TRACE_PTR("ex_get_object_reference", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc); *return_desc = NULL; @@ -168,7 +168,7 @@ acpi_ex_concat_template(union acpi_opera acpi_size length1; acpi_size new_length; - ACPI_FUNCTION_TRACE("ex_concat_template"); + ACPI_FUNCTION_TRACE(ex_concat_template); /* * Find the end_tag descriptor in each resource template. @@ -250,7 +250,7 @@ acpi_ex_do_concatenate(union acpi_operan char *new_buf; acpi_status status; - ACPI_FUNCTION_TRACE("ex_do_concatenate"); + ACPI_FUNCTION_TRACE(ex_do_concatenate); /* * Convert the second operand if necessary. The first operand @@ -445,10 +445,24 @@ acpi_ex_do_math_op(u16 opcode, acpi_inte case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */ + /* + * We need to check if the shiftcount is larger than the integer bit + * width since the behavior of this is not well-defined in the C language. + */ + if (integer1 >= acpi_gbl_integer_bit_width) { + return (0); + } return (integer0 << integer1); case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */ + /* + * We need to check if the shiftcount is larger than the integer bit + * width since the behavior of this is not well-defined in the C language. + */ + if (integer1 >= acpi_gbl_integer_bit_width) { + return (0); + } return (integer0 >> integer1); case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ @@ -489,7 +503,7 @@ acpi_ex_do_logical_numeric_op(u16 opcode acpi_status status = AE_OK; u8 local_result = FALSE; - ACPI_FUNCTION_TRACE("ex_do_logical_numeric_op"); + ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op); switch (opcode) { case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ @@ -557,7 +571,7 @@ acpi_ex_do_logical_op(u16 opcode, u8 local_result = FALSE; int compare; - ACPI_FUNCTION_TRACE("ex_do_logical_op"); + ACPI_FUNCTION_TRACE(ex_do_logical_op); /* * Convert the second operand if necessary. The first operand @@ -649,6 +663,7 @@ acpi_ex_do_logical_op(u16 opcode, /* Length and all bytes must be equal */ if ((length0 == length1) && (compare == 0)) { + /* Length and all bytes match ==> TRUE */ local_result = TRUE; diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index f843b22..93098d6 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -61,7 +61,7 @@ acpi_ex_link_mutex(union acpi_operand_ob * * RETURN: None * - * DESCRIPTION: Remove a mutex from the "acquired_mutex" list + * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list * ******************************************************************************/ @@ -95,7 +95,7 @@ void acpi_ex_unlink_mutex(union acpi_ope * * RETURN: None * - * DESCRIPTION: Add a mutex to the "acquired_mutex" list for this walk + * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk * ******************************************************************************/ @@ -144,7 +144,7 @@ acpi_ex_acquire_mutex(union acpi_operand { acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ex_acquire_mutex", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex, obj_desc); if (!obj_desc) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -165,7 +165,7 @@ acpi_ex_acquire_mutex(union acpi_operand */ if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { ACPI_ERROR((AE_INFO, - "Cannot acquire Mutex [%4.4s], incorrect sync_level", + "Cannot acquire Mutex [%4.4s], incorrect SyncLevel", acpi_ut_get_node_name(obj_desc->mutex.node))); return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } @@ -173,6 +173,7 @@ acpi_ex_acquire_mutex(union acpi_operand /* Support for multiple acquires by the owning thread */ if (obj_desc->mutex.owner_thread) { + /* Special case for Global Lock, allow all threads */ if ((obj_desc->mutex.owner_thread->thread_id == @@ -192,6 +193,7 @@ acpi_ex_acquire_mutex(union acpi_operand status = acpi_ex_system_acquire_mutex(time_desc, obj_desc); if (ACPI_FAILURE(status)) { + /* Includes failure from a timeout on time_desc */ return_ACPI_STATUS(status); @@ -232,7 +234,7 @@ acpi_ex_release_mutex(union acpi_operand { acpi_status status; - ACPI_FUNCTION_TRACE("ex_release_mutex"); + ACPI_FUNCTION_TRACE(ex_release_mutex); if (!obj_desc) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -277,7 +279,7 @@ acpi_ex_release_mutex(union acpi_operand */ if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], incorrect sync_level", + "Cannot release Mutex [%4.4s], incorrect SyncLevel", acpi_ut_get_node_name(obj_desc->mutex.node))); return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } @@ -286,6 +288,7 @@ acpi_ex_release_mutex(union acpi_operand obj_desc->mutex.acquisition_depth--; if (obj_desc->mutex.acquisition_depth != 0) { + /* Just decrement the depth and return */ return_ACPI_STATUS(AE_OK); diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c index 054fe5e..d3d7036 100644 --- a/drivers/acpi/executer/exnames.c +++ b/drivers/acpi/executer/exnames.c @@ -77,7 +77,7 @@ static char *acpi_ex_allocate_name_strin char *name_string; u32 size_needed; - ACPI_FUNCTION_TRACE("ex_allocate_name_string"); + ACPI_FUNCTION_TRACE(ex_allocate_name_string); /* * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix. @@ -85,6 +85,7 @@ static char *acpi_ex_allocate_name_strin * This may actually be somewhat longer than needed. */ if (prefix_count == ACPI_UINT32_MAX) { + /* Special case for root */ size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; @@ -97,7 +98,7 @@ static char *acpi_ex_allocate_name_strin * Allocate a buffer for the name. * This buffer must be deleted by the caller! */ - name_string = ACPI_MEM_ALLOCATE(size_needed); + name_string = ACPI_ALLOCATE(size_needed); if (!name_string) { ACPI_ERROR((AE_INFO, "Could not allocate size %d", size_needed)); @@ -119,11 +120,13 @@ static char *acpi_ex_allocate_name_strin /* Set up Dual or Multi prefixes if needed */ if (num_name_segs > 2) { + /* Set up multi prefixes */ *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; *temp_ptr++ = (char)num_name_segs; } else if (2 == num_name_segs) { + /* Set up dual prefixes */ *temp_ptr++ = AML_DUAL_NAME_PREFIX; @@ -159,7 +162,7 @@ static acpi_status acpi_ex_name_segment( u32 index; char char_buf[5]; - ACPI_FUNCTION_TRACE("ex_name_segment"); + ACPI_FUNCTION_TRACE(ex_name_segment); /* * If first character is a digit, then we know that we aren't looking at a @@ -176,7 +179,7 @@ static acpi_status acpi_ex_name_segment( for (index = 0; (index < ACPI_NAME_SIZE) - && (acpi_ut_valid_acpi_character(*aml_address)); index++) { + && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) { char_buf[index] = *aml_address++; ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index])); } @@ -184,6 +187,7 @@ static acpi_status acpi_ex_name_segment( /* Valid name segment */ if (index == 4) { + /* Found 4 valid characters */ char_buf[4] = '\0'; @@ -249,11 +253,12 @@ acpi_ex_get_name_string(acpi_object_type u32 prefix_count = 0; u8 has_prefix = FALSE; - ACPI_FUNCTION_TRACE_PTR("ex_get_name_string", aml_address); + ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address); if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type || ACPI_TYPE_LOCAL_BANK_FIELD == data_type || ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) { + /* Disallow prefixes for types associated with field_unit names */ name_string = acpi_ex_allocate_name_string(0, 1); @@ -272,7 +277,7 @@ acpi_ex_get_name_string(acpi_object_type case AML_ROOT_PREFIX: ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "root_prefix(\\) at %p\n", + "RootPrefix(\\) at %p\n", aml_address)); /* @@ -290,7 +295,7 @@ acpi_ex_get_name_string(acpi_object_type do { ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "parent_prefix (^) at %p\n", + "ParentPrefix (^) at %p\n", aml_address)); aml_address++; @@ -314,7 +319,7 @@ acpi_ex_get_name_string(acpi_object_type case AML_DUAL_NAME_PREFIX: ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "dual_name_prefix at %p\n", + "DualNamePrefix at %p\n", aml_address)); aml_address++; @@ -341,7 +346,7 @@ acpi_ex_get_name_string(acpi_object_type case AML_MULTI_NAME_PREFIX_OP: ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "multi_name_prefix at %p\n", + "MultiNamePrefix at %p\n", aml_address)); /* Fetch count of segments remaining in name path */ @@ -377,7 +382,7 @@ acpi_ex_get_name_string(acpi_object_type if (prefix_count == ACPI_UINT32_MAX) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "name_seg is \"\\\" followed by NULL\n")); + "NameSeg is \"\\\" followed by NULL\n")); } /* Consume the NULL byte */ @@ -410,6 +415,7 @@ acpi_ex_get_name_string(acpi_object_type } if (AE_CTRL_PENDING == status && has_prefix) { + /* Ran out of segments after processing a prefix */ ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string)); @@ -418,7 +424,7 @@ acpi_ex_get_name_string(acpi_object_type if (ACPI_FAILURE(status)) { if (name_string) { - ACPI_MEM_FREE(name_string); + ACPI_FREE(name_string); } return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 23d0823..6374d8b 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -89,7 +89,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(stru acpi_status status = AE_OK; union acpi_operand_object *return_desc = NULL; - ACPI_FUNCTION_TRACE_STR("ex_opcode_0A_0T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_0A_0T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the AML opcode */ @@ -150,7 +150,7 @@ acpi_status acpi_ex_opcode_1A_0T_0R(stru union acpi_operand_object **operand = &walk_state->operands[0]; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_0R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_0R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the AML opcode */ @@ -216,7 +216,7 @@ acpi_status acpi_ex_opcode_1A_1T_0R(stru acpi_status status = AE_OK; union acpi_operand_object **operand = &walk_state->operands[0]; - ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_0R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_0R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the AML opcode */ @@ -264,7 +264,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(stru acpi_integer power_of_ten; acpi_integer digit; - ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the AML opcode */ @@ -322,8 +322,9 @@ acpi_status acpi_ex_opcode_1A_1T_1R(stru /* Since the bit position is one-based, subtract from 33 (65) */ - return_desc->integer.value = temp32 == 0 ? 0 : - (ACPI_INTEGER_BIT_SIZE + 1) - temp32; + return_desc->integer.value = + temp32 == + 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32; break; case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */ @@ -342,6 +343,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(stru for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) { + /* Get the least significant 4-bit BCD digit */ temp32 = ((u32) digit) & 0xF; @@ -487,6 +489,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(stru status = acpi_ex_convert_to_string(operand[0], &return_desc, ACPI_EXPLICIT_CONVERT_DECIMAL); if (return_desc == operand[0]) { + /* No conversion performed, add ref to handle return value */ acpi_ut_add_reference(return_desc); } @@ -497,6 +500,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(stru status = acpi_ex_convert_to_string(operand[0], &return_desc, ACPI_EXPLICIT_CONVERT_HEX); if (return_desc == operand[0]) { + /* No conversion performed, add ref to handle return value */ acpi_ut_add_reference(return_desc); } @@ -506,6 +510,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(stru status = acpi_ex_convert_to_buffer(operand[0], &return_desc); if (return_desc == operand[0]) { + /* No conversion performed, add ref to handle return value */ acpi_ut_add_reference(return_desc); } @@ -516,6 +521,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(stru status = acpi_ex_convert_to_integer(operand[0], &return_desc, ACPI_ANY_BASE); if (return_desc == operand[0]) { + /* No conversion performed, add ref to handle return value */ acpi_ut_add_reference(return_desc); } @@ -541,6 +547,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(stru } if (ACPI_SUCCESS(status)) { + /* Store the return value computed above into the target object */ status = acpi_ex_store(return_desc, operand[1], walk_state); @@ -548,16 +555,18 @@ acpi_status acpi_ex_opcode_1A_1T_1R(stru cleanup: - if (!walk_state->result_obj) { - walk_state->result_obj = return_desc; - } - /* Delete return object on error */ if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(return_desc); } + /* Save return object on success */ + + else if (!walk_state->result_obj) { + walk_state->result_obj = return_desc; + } + return_ACPI_STATUS(status); } @@ -582,7 +591,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(stru u32 type; acpi_integer value; - ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the AML opcode */ @@ -625,6 +634,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(stru temp_desc = operand[0]; if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) == ACPI_DESC_TYPE_OPERAND) { + /* Internal reference object - prevent deletion */ acpi_ut_add_reference(temp_desc); @@ -689,6 +699,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(stru if (ACPI_FAILURE(status)) { goto cleanup; } + /* Allocate a descriptor to hold the type. */ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); @@ -777,8 +788,25 @@ acpi_status acpi_ex_opcode_1A_0T_1R(stru /* Check for a method local or argument, or standalone String */ - if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) != + if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) == ACPI_DESC_TYPE_NAMED) { + temp_desc = + acpi_ns_get_attached_object((struct + acpi_namespace_node *) + operand[0]); + if (temp_desc + && + ((ACPI_GET_OBJECT_TYPE(temp_desc) == + ACPI_TYPE_STRING) + || (ACPI_GET_OBJECT_TYPE(temp_desc) == + ACPI_TYPE_LOCAL_REFERENCE))) { + operand[0] = temp_desc; + acpi_ut_add_reference(temp_desc); + } else { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + } else { switch (ACPI_GET_OBJECT_TYPE(operand[0])) { case ACPI_TYPE_LOCAL_REFERENCE: /* @@ -827,26 +855,35 @@ acpi_status acpi_ex_opcode_1A_0T_1R(stru break; case ACPI_TYPE_STRING: + break; + default: + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + } + + if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) != + ACPI_DESC_TYPE_NAMED) { + if (ACPI_GET_OBJECT_TYPE(operand[0]) == + ACPI_TYPE_STRING) { /* * This is a deref_of (String). The string is a reference * to a named ACPI object. * * 1) Find the owning Node - * 2) Dereference the node to an actual object. Could be a + * 2) Dereference the node to an actual object. Could be a * Field, so we need to resolve the node to a value. */ status = - acpi_ns_get_node_by_path(operand[0]->string. - pointer, - walk_state-> - scope_info->scope. - node, - ACPI_NS_SEARCH_PARENT, - ACPI_CAST_INDIRECT_PTR - (struct - acpi_namespace_node, - &return_desc)); + acpi_ns_get_node(walk_state->scope_info-> + scope.node, + operand[0]->string.pointer, + ACPI_NS_SEARCH_PARENT, + ACPI_CAST_INDIRECT_PTR + (struct + acpi_namespace_node, + &return_desc)); if (ACPI_FAILURE(status)) { goto cleanup; } @@ -857,11 +894,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(stru (struct acpi_namespace_node, &return_desc), walk_state); goto cleanup; - - default: - - status = AE_AML_OPERAND_TYPE; - goto cleanup; } } @@ -937,13 +969,12 @@ acpi_status acpi_ex_opcode_1A_0T_1R(stru acpi_ut_add_reference (return_desc); } - break; default: ACPI_ERROR((AE_INFO, - "Unknown Index target_type %X in obj %p", + "Unknown Index TargetType %X in obj %p", operand[0]->reference. target_type, operand[0])); status = AE_AML_OPERAND_TYPE; @@ -957,7 +988,6 @@ acpi_status acpi_ex_opcode_1A_0T_1R(stru if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) == ACPI_DESC_TYPE_NAMED) { - return_desc = acpi_ns_get_attached_object((struct acpi_namespace_node @@ -972,7 +1002,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(stru default: ACPI_ERROR((AE_INFO, - "Unknown opcode in ref(%p) - %X", + "Unknown opcode in reference(%p) - %X", operand[0], operand[0]->reference.opcode)); @@ -998,6 +1028,11 @@ acpi_status acpi_ex_opcode_1A_0T_1R(stru acpi_ut_remove_reference(return_desc); } - walk_state->result_obj = return_desc; + /* Save return object on success */ + + else { + walk_state->result_obj = return_desc; + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index e263a5d..7d2cbc1 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c @@ -92,7 +92,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(stru u32 value; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_0R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the opcode */ @@ -121,7 +121,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(stru #ifdef ACPI_GPE_NOTIFY_CHECK /* * GPE method wake/notify check. Here, we want to ensure that we - * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx + * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx * GPE method during system runtime. If we do, the GPE is marked * as "wake-only" and disabled. * @@ -138,6 +138,7 @@ #ifdef ACPI_GPE_NOTIFY_CHECK acpi_ev_check_for_wake_only_gpe(walk_state-> gpe_event_info); if (ACPI_FAILURE(status)) { + /* AE_WAKE_ONLY_GPE only error, means ignore this notify */ return_ACPI_STATUS(AE_OK) @@ -185,7 +186,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(stru union acpi_operand_object *return_desc2 = NULL; acpi_status status; - ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_2T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Execute the opcode */ @@ -252,6 +253,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(stru acpi_ut_remove_reference(return_desc2); if (ACPI_FAILURE(status)) { + /* Delete the return object */ acpi_ut_remove_reference(return_desc1); @@ -281,12 +283,13 @@ acpi_status acpi_ex_opcode_2A_1T_1R(stru acpi_status status = AE_OK; acpi_size length; - ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_1T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Execute the opcode */ if (walk_state->op_info->flags & AML_MATH) { + /* All simple math opcodes (add, etc.) */ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); @@ -383,54 +386,70 @@ acpi_status acpi_ex_opcode_2A_1T_1R(stru goto cleanup; } + /* Initialize the Index reference object */ + index = operand[1]->integer.value; + return_desc->reference.offset = (u32) index; + return_desc->reference.opcode = AML_INDEX_OP; - /* At this point, the Source operand is a Package, Buffer, or String */ + /* + * At this point, the Source operand is a String, Buffer, or Package. + * Verify that the index is within range. + */ + switch (ACPI_GET_OBJECT_TYPE(operand[0])) { + case ACPI_TYPE_STRING: - if (ACPI_GET_OBJECT_TYPE(operand[0]) == ACPI_TYPE_PACKAGE) { - /* Object to be indexed is a Package */ + if (index >= operand[0]->string.length) { + status = AE_AML_STRING_LIMIT; + } + + return_desc->reference.target_type = + ACPI_TYPE_BUFFER_FIELD; + break; + + case ACPI_TYPE_BUFFER: + + if (index >= operand[0]->buffer.length) { + status = AE_AML_BUFFER_LIMIT; + } + + return_desc->reference.target_type = + ACPI_TYPE_BUFFER_FIELD; + break; + + case ACPI_TYPE_PACKAGE: if (index >= operand[0]->package.count) { - ACPI_ERROR((AE_INFO, - "Index value (%X%8.8X) beyond package end (%X)", - ACPI_FORMAT_UINT64(index), - operand[0]->package.count)); status = AE_AML_PACKAGE_LIMIT; - goto cleanup; } return_desc->reference.target_type = ACPI_TYPE_PACKAGE; - return_desc->reference.object = operand[0]; return_desc->reference.where = &operand[0]->package.elements[index]; - } else { - /* Object to be indexed is a Buffer/String */ + break; - if (index >= operand[0]->buffer.length) { - ACPI_ERROR((AE_INFO, - "Index value (%X%8.8X) beyond end of buffer (%X)", - ACPI_FORMAT_UINT64(index), - operand[0]->buffer.length)); - status = AE_AML_BUFFER_LIMIT; - goto cleanup; - } + default: - return_desc->reference.target_type = - ACPI_TYPE_BUFFER_FIELD; - return_desc->reference.object = operand[0]; + status = AE_AML_INTERNAL; + goto cleanup; + } + + /* Failure means that the Index was beyond the end of the object */ + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Index (%X%8.8X) is beyond end of object", + ACPI_FORMAT_UINT64(index))); + goto cleanup; } /* - * Add a reference to the target package/buffer/string for the life - * of the index. + * Save the target object and add a reference to it for the life + * of the index */ + return_desc->reference.object = operand[0]; acpi_ut_add_reference(operand[0]); - /* Complete the Index reference object */ - - return_desc->reference.opcode = AML_INDEX_OP; - return_desc->reference.offset = (u32) index; - /* Store the reference to the Target */ status = acpi_ex_store(return_desc, operand[2], walk_state); @@ -495,7 +514,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(stru acpi_status status = AE_OK; u8 logical_result = FALSE; - ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); /* Create the internal return object */ @@ -509,6 +528,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(stru /* Execute the Opcode */ if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) { + /* logical_op (Operand0, Operand1) */ status = acpi_ex_do_logical_numeric_op(walk_state->opcode, @@ -518,6 +538,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(stru value, &logical_result); goto store_logical_result; } else if (walk_state->op_info->flags & AML_LOGICAL) { + /* logical_op (Operand0, Operand1) */ status = acpi_ex_do_logical_op(walk_state->opcode, operand[0], diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index 6a3a883..e2d945d 100644 --- a/drivers/acpi/executer/exoparg3.c +++ b/drivers/acpi/executer/exoparg3.c @@ -88,20 +88,19 @@ acpi_status acpi_ex_opcode_3A_0T_0R(stru struct acpi_signal_fatal_info *fatal; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_0T_0R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R, acpi_ps_get_opcode_name(walk_state->opcode)); switch (walk_state->opcode) { case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", + "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", (u32) operand[0]->integer.value, (u32) operand[1]->integer.value, (u32) operand[2]->integer.value)); - fatal = - ACPI_MEM_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); + fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); if (fatal) { fatal->type = (u32) operand[0]->integer.value; fatal->code = (u32) operand[1]->integer.value; @@ -114,7 +113,7 @@ acpi_status acpi_ex_opcode_3A_0T_0R(stru /* Might return while OS is shutting down, just continue */ - ACPI_MEM_FREE(fatal); + ACPI_FREE(fatal); break; default: @@ -151,7 +150,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(stru acpi_integer index; acpi_size length; - ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_1T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); switch (walk_state->opcode) { @@ -196,7 +195,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(stru /* Always allocate a new buffer for the String */ - buffer = ACPI_MEM_CALLOCATE((acpi_size) length + 1); + buffer = ACPI_ALLOCATE_ZEROED((acpi_size) length + 1); if (!buffer) { status = AE_NO_MEMORY; goto cleanup; @@ -208,9 +207,10 @@ acpi_status acpi_ex_opcode_3A_1T_1R(stru /* If the requested length is zero, don't allocate a buffer */ if (length > 0) { + /* Allocate a new buffer for the Buffer */ - buffer = ACPI_MEM_CALLOCATE(length); + buffer = ACPI_ALLOCATE_ZEROED(length); if (!buffer) { status = AE_NO_MEMORY; goto cleanup; @@ -225,6 +225,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(stru } if (buffer) { + /* We have a buffer, copy the portion requested */ ACPI_MEMCPY(buffer, operand[0]->string.pointer + index, diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c index e043d92..f0c0ba6 100644 --- a/drivers/acpi/executer/exoparg6.c +++ b/drivers/acpi/executer/exoparg6.c @@ -220,7 +220,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(stru acpi_integer index; union acpi_operand_object *this_element; - ACPI_FUNCTION_TRACE_STR("ex_opcode_6A_0T_1R", + ACPI_FUNCTION_TRACE_STR(ex_opcode_6A_0T_1R, acpi_ps_get_opcode_name(walk_state->opcode)); switch (walk_state->opcode) { @@ -276,6 +276,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(stru * match was found. */ for (; index < operand[0]->package.count; index++) { + /* Get the current package element */ this_element = operand[0]->package.elements[index]; diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c index 7719ae5..44d064f 100644 --- a/drivers/acpi/executer/exprep.c +++ b/drivers/acpi/executer/exprep.c @@ -97,7 +97,7 @@ acpi_ex_generate_access(u32 field_bit_of u32 minimum_accesses = 0xFFFFFFFF; u32 accesses; - ACPI_FUNCTION_TRACE("ex_generate_access"); + ACPI_FUNCTION_TRACE(ex_generate_access); /* Round Field start offset and length to "minimal" byte boundaries */ @@ -146,7 +146,7 @@ acpi_ex_generate_access(u32 field_bit_of accesses = field_end_offset - field_start_offset; ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "access_width %d end is within region\n", + "AccessWidth %d end is within region\n", access_byte_width)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, @@ -173,7 +173,7 @@ acpi_ex_generate_access(u32 field_bit_of } } else { ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "access_width %d end is NOT within region\n", + "AccessWidth %d end is NOT within region\n", access_byte_width)); if (access_byte_width == 1) { ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, @@ -228,7 +228,7 @@ acpi_ex_decode_field_access(union acpi_o u32 byte_alignment; u32 bit_length; - ACPI_FUNCTION_TRACE("ex_decode_field_access"); + ACPI_FUNCTION_TRACE(ex_decode_field_access); access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK); @@ -322,7 +322,7 @@ acpi_ex_prep_common_field_object(union a u32 byte_alignment; u32 nearest_byte_address; - ACPI_FUNCTION_TRACE("ex_prep_common_field_object"); + ACPI_FUNCTION_TRACE(ex_prep_common_field_object); /* * Note: the structure being initialized is the @@ -415,13 +415,13 @@ acpi_status acpi_ex_prep_field_value(str u32 type; acpi_status status; - ACPI_FUNCTION_TRACE("ex_prep_field_value"); + ACPI_FUNCTION_TRACE(ex_prep_field_value); /* Parameter validation */ if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) { if (!info->region_node) { - ACPI_ERROR((AE_INFO, "Null region_node")); + ACPI_ERROR((AE_INFO, "Null RegionNode")); return_ACPI_STATUS(AE_AML_NO_OPERAND); } @@ -467,7 +467,7 @@ acpi_status acpi_ex_prep_field_value(str acpi_ut_add_reference(obj_desc->field.region_obj); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "region_field: bit_off %X, Off %X, Gran %X, Region %p\n", + "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset, obj_desc->field.access_byte_width, @@ -488,7 +488,7 @@ acpi_status acpi_ex_prep_field_value(str acpi_ut_add_reference(obj_desc->bank_field.bank_obj); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n", + "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n", obj_desc->bank_field.start_field_bit_offset, obj_desc->bank_field.base_byte_offset, obj_desc->field.access_byte_width, @@ -519,16 +519,29 @@ acpi_status acpi_ex_prep_field_value(str acpi_ut_add_reference(obj_desc->index_field.index_obj); /* + * April 2006: Changed to match MS behavior + * * The value written to the Index register is the byte offset of the - * target field - * Note: may change code to: ACPI_DIV_8 (Info->field_bit_position) + * target field in units of the granularity of the index_field + * + * Previously, the value was calculated as an index in terms of the + * width of the Data register, as below: + * + * obj_desc->index_field.Value = (u32) + * (Info->field_bit_position / ACPI_MUL_8 ( + * obj_desc->Field.access_byte_width)); + * + * February 2006: Tried value as a byte offset: + * obj_desc->index_field.Value = (u32) + * ACPI_DIV_8 (Info->field_bit_position); */ - obj_desc->index_field.value = (u32) - (info->field_bit_position / - ACPI_MUL_8(obj_desc->field.access_byte_width)); + obj_desc->index_field.value = + (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position), + obj_desc->index_field. + access_byte_width); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", + "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", obj_desc->index_field.start_field_bit_offset, obj_desc->index_field.base_byte_offset, obj_desc->index_field.value, @@ -550,7 +563,7 @@ acpi_status acpi_ex_prep_field_value(str acpi_ns_get_type(info->field_node)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, - "Set named_obj %p [%4.4s], obj_desc %p\n", + "Set NamedObj %p [%4.4s], ObjDesc %p\n", info->field_node, acpi_ut_get_node_name(info->field_node), obj_desc)); diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index 6a4cfdf..3cc97ba 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -81,7 +81,7 @@ #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED u32 remainder; #endif - ACPI_FUNCTION_TRACE("ex_system_memory_space_handler"); + ACPI_FUNCTION_TRACE(ex_system_memory_space_handler); /* Validate and translate the bit width */ @@ -103,7 +103,7 @@ #endif break; default: - ACPI_ERROR((AE_INFO, "Invalid system_memory width %d", + ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %d", bit_width)); return_ACPI_STATUS(AE_AML_OPERAND_VALUE); } @@ -135,6 +135,7 @@ #endif * Delete the existing mapping and create a new one. */ if (mem_info->mapped_length) { + /* Valid mapping, delete it */ acpi_os_unmap_memory(mem_info->mapped_logical_address, @@ -181,8 +182,8 @@ #endif (acpi_integer) mem_info->mapped_physical_address); ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "system_memory %d (%d width) Address=%8.8X%8.8X\n", - function, bit_width, ACPI_FORMAT_UINT64(address))); + "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", + bit_width, function, ACPI_FORMAT_UINT64(address))); /* * Perform the memory read or write @@ -283,11 +284,11 @@ acpi_ex_system_io_space_handler(u32 func acpi_status status = AE_OK; u32 value32; - ACPI_FUNCTION_TRACE("ex_system_io_space_handler"); + ACPI_FUNCTION_TRACE(ex_system_io_space_handler); ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "system_iO %d (%d width) Address=%8.8X%8.8X\n", - function, bit_width, ACPI_FORMAT_UINT64(address))); + "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", + bit_width, function, ACPI_FORMAT_UINT64(address))); /* Decode the function parameter */ @@ -342,7 +343,7 @@ acpi_ex_pci_config_space_handler(u32 fun struct acpi_pci_id *pci_id; u16 pci_register; - ACPI_FUNCTION_TRACE("ex_pci_config_space_handler"); + ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); /* * The arguments to acpi_os(Read|Write)pci_configuration are: @@ -360,7 +361,7 @@ acpi_ex_pci_config_space_handler(u32 fun pci_register = (u16) (u32) address; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", + "Pci-Config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", function, bit_width, pci_id->segment, pci_id->bus, pci_id->device, pci_id->function, pci_register)); @@ -414,7 +415,7 @@ acpi_ex_cmos_space_handler(u32 function, { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_cmos_space_handler"); + ACPI_FUNCTION_TRACE(ex_cmos_space_handler); return_ACPI_STATUS(status); } @@ -446,7 +447,7 @@ acpi_ex_pci_bar_space_handler(u32 functi { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_pci_bar_space_handler"); + ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler); return_ACPI_STATUS(status); } @@ -476,23 +477,16 @@ acpi_ex_data_table_space_handler(u32 fun acpi_integer * value, void *handler_context, void *region_context) { - acpi_status status = AE_OK; - u32 byte_width = ACPI_DIV_8(bit_width); - u32 i; - char *logical_addr_ptr; - - ACPI_FUNCTION_TRACE("ex_data_table_space_handler"); - - logical_addr_ptr = ACPI_PHYSADDR_TO_PTR(address); + ACPI_FUNCTION_TRACE(ex_data_table_space_handler); /* Perform the memory read or write */ switch (function) { case ACPI_READ: - for (i = 0; i < byte_width; i++) { - ((char *)value)[i] = logical_addr_ptr[i]; - } + ACPI_MEMCPY(ACPI_CAST_PTR(char, value), + ACPI_PHYSADDR_TO_PTR(address), + ACPI_DIV_8(bit_width)); break; case ACPI_WRITE: @@ -501,5 +495,5 @@ acpi_ex_data_table_space_handler(u32 fun return_ACPI_STATUS(AE_SUPPORT); } - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index 01b26c8..3089b05 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c @@ -87,7 +87,7 @@ acpi_ex_resolve_node_to_value(struct acp struct acpi_namespace_node *node; acpi_object_type entry_type; - ACPI_FUNCTION_TRACE("ex_resolve_node_to_value"); + ACPI_FUNCTION_TRACE(ex_resolve_node_to_value); /* * The stack pointer points to a struct acpi_namespace_node (Node). Get the @@ -97,12 +97,13 @@ acpi_ex_resolve_node_to_value(struct acp source_desc = acpi_ns_get_attached_object(node); entry_type = acpi_ns_get_type((acpi_handle) node); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n", node, source_desc, acpi_ut_get_type_name(entry_type))); if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) || (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { + /* There is always exactly one level of indirection */ node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object); @@ -113,10 +114,11 @@ acpi_ex_resolve_node_to_value(struct acp /* * Several object types require no further processing: - * 1) Devices rarely have an attached object, return the Node + * 1) Device/Thermal objects don't have a "real" subobject, return the Node * 2) Method locals and arguments have a pseudo-Node */ - if (entry_type == ACPI_TYPE_DEVICE || + if ((entry_type == ACPI_TYPE_DEVICE) || + (entry_type == ACPI_TYPE_THERMAL) || (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { return_ACPI_STATUS(AE_OK); } @@ -141,6 +143,7 @@ acpi_ex_resolve_node_to_value(struct acp status = acpi_ds_get_package_arguments(source_desc); if (ACPI_SUCCESS(status)) { + /* Return an additional reference to the object */ obj_desc = source_desc; @@ -158,6 +161,7 @@ acpi_ex_resolve_node_to_value(struct acp status = acpi_ds_get_buffer_arguments(source_desc); if (ACPI_SUCCESS(status)) { + /* Return an additional reference to the object */ obj_desc = source_desc; @@ -199,7 +203,7 @@ acpi_ex_resolve_node_to_value(struct acp case ACPI_TYPE_LOCAL_INDEX_FIELD: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "field_read Node=%p source_desc=%p Type=%X\n", + "FieldRead Node=%p SourceDesc=%p Type=%X\n", node, source_desc, entry_type)); status = @@ -213,7 +217,6 @@ acpi_ex_resolve_node_to_value(struct acp case ACPI_TYPE_METHOD: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: - case ACPI_TYPE_THERMAL: case ACPI_TYPE_EVENT: case ACPI_TYPE_REGION: @@ -240,6 +243,8 @@ acpi_ex_resolve_node_to_value(struct acp /* This is a ddb_handle */ /* Return an additional reference to the object */ + case AML_REF_OF_OP: + obj_desc = source_desc; acpi_ut_add_reference(obj_desc); break; diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 1deed49..6499de8 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c @@ -78,7 +78,7 @@ acpi_ex_resolve_to_value(union acpi_oper { acpi_status status; - ACPI_FUNCTION_TRACE_PTR("ex_resolve_to_value", stack_ptr); + ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr); if (!stack_ptr || !*stack_ptr) { ACPI_ERROR((AE_INFO, "Internal - null pointer")); @@ -144,7 +144,7 @@ acpi_ex_resolve_object_to_value(union ac union acpi_operand_object *obj_desc; u16 opcode; - ACPI_FUNCTION_TRACE("ex_resolve_object_to_value"); + ACPI_FUNCTION_TRACE(ex_resolve_object_to_value); stack_desc = *stack_ptr; @@ -190,7 +190,7 @@ acpi_ex_resolve_object_to_value(union ac } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Arg/Local %X] value_obj is %p\n", + "[Arg/Local %X] ValueObj is %p\n", stack_desc->reference.offset, obj_desc)); @@ -239,7 +239,7 @@ acpi_ex_resolve_object_to_value(union ac /* Invalid reference object */ ACPI_ERROR((AE_INFO, - "Unknown target_type %X in Index/Reference obj %p", + "Unknown TargetType %X in Index/Reference obj %p", stack_desc->reference.target_type, stack_desc)); status = AE_AML_INTERNAL; @@ -257,10 +257,24 @@ acpi_ex_resolve_object_to_value(union ac case AML_INT_NAMEPATH_OP: /* Reference to a named object */ - /* Get the object pointed to by the namespace node */ + /* Dereference the name */ + + if ((stack_desc->reference.node->type == + ACPI_TYPE_DEVICE) + || (stack_desc->reference.node->type == + ACPI_TYPE_THERMAL)) { + + /* These node types do not have 'real' subobjects */ + + *stack_ptr = (void *)stack_desc->reference.node; + } else { + /* Get the object pointed to by the namespace node */ + + *stack_ptr = + (stack_desc->reference.node)->object; + acpi_ut_add_reference(*stack_ptr); + } - *stack_ptr = (stack_desc->reference.node)->object; - acpi_ut_add_reference(*stack_ptr); acpi_ut_remove_reference(stack_desc); break; @@ -293,7 +307,7 @@ acpi_ex_resolve_object_to_value(union ac case ACPI_TYPE_LOCAL_INDEX_FIELD: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "field_read source_desc=%p Type=%X\n", + "FieldRead SourceDesc=%p Type=%X\n", stack_desc, ACPI_GET_OBJECT_TYPE(stack_desc))); @@ -337,7 +351,7 @@ acpi_ex_resolve_multiple(struct acpi_wal acpi_object_type type; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_ex_resolve_multiple"); + ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple); /* Operand can be either a namespace node or an operand descriptor */ @@ -382,10 +396,16 @@ acpi_ex_resolve_multiple(struct acpi_wal while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { switch (obj_desc->reference.opcode) { case AML_REF_OF_OP: + case AML_INT_NAMEPATH_OP: /* Dereference the reference pointer */ - node = obj_desc->reference.object; + if (obj_desc->reference.opcode == AML_REF_OF_OP) { + node = obj_desc->reference.object; + } else { /* AML_INT_NAMEPATH_OP */ + + node = obj_desc->reference.node; + } /* All "References" point to a NS node */ @@ -401,6 +421,7 @@ acpi_ex_resolve_multiple(struct acpi_wal obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { + /* No object, use the NS node type */ type = acpi_ns_get_type(node); @@ -432,6 +453,7 @@ acpi_ex_resolve_multiple(struct acpi_wal */ obj_desc = *(obj_desc->reference.where); if (!obj_desc) { + /* NULL package elements are allowed */ type = 0; /* Uninitialized */ @@ -439,39 +461,6 @@ acpi_ex_resolve_multiple(struct acpi_wal } break; - case AML_INT_NAMEPATH_OP: - - /* Dereference the reference pointer */ - - node = obj_desc->reference.node; - - /* All "References" point to a NS node */ - - if (ACPI_GET_DESCRIPTOR_TYPE(node) != - ACPI_DESC_TYPE_NAMED) { - ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]", - node, - acpi_ut_get_descriptor_name(node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - /* Get the attached object */ - - obj_desc = acpi_ns_get_attached_object(node); - if (!obj_desc) { - /* No object, use the NS node type */ - - type = acpi_ns_get_type(node); - goto exit; - } - - /* Check for circular references */ - - if (obj_desc == operand) { - return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE); - } - break; - case AML_LOCAL_OP: case AML_ARG_OP: @@ -513,7 +502,7 @@ acpi_ex_resolve_multiple(struct acpi_wal case AML_DEBUG_OP: - /* The Debug Object is of type "debug_object" */ + /* The Debug Object is of type "DebugObject" */ type = ACPI_TYPE_DEBUG_OBJECT; goto exit; diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index a1c000f..4c93d09 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c @@ -77,6 +77,7 @@ acpi_ex_check_object_type(acpi_object_ty ACPI_FUNCTION_ENTRY(); if (type_needed == ACPI_TYPE_ANY) { + /* All types OK, so we don't perform any typechecks */ return (AE_OK); @@ -143,7 +144,7 @@ acpi_ex_resolve_operands(u16 opcode, acpi_object_type type_needed; u16 target_op = 0; - ACPI_FUNCTION_TRACE_U32("ex_resolve_operands", opcode); + ACPI_FUNCTION_TRACE_U32(ex_resolve_operands, opcode); op_info = acpi_ps_get_opcode_info(opcode); if (op_info->class == AML_CLASS_UNKNOWN) { @@ -158,7 +159,7 @@ acpi_ex_resolve_operands(u16 opcode, } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Opcode %X [%s] required_operand_types=%8.8X\n", + "Opcode %X [%s] RequiredOperandTypes=%8.8X\n", opcode, op_info->name, arg_types)); /* @@ -224,6 +225,7 @@ acpi_ex_resolve_operands(u16 opcode, } if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) { + /* Decode the Reference */ op_info = acpi_ps_get_opcode_info(opcode); @@ -247,7 +249,7 @@ acpi_ex_resolve_operands(u16 opcode, ACPI_DEBUG_ONLY_MEMBERS(ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, - "Operand is a Reference, ref_opcode [%s]\n", + "Operand is a Reference, RefOpcode [%s]\n", (acpi_ps_get_opcode_info (obj_desc-> reference. @@ -332,6 +334,7 @@ acpi_ex_resolve_operands(u16 opcode, } if (obj_desc->reference.opcode == AML_NAME_OP) { + /* Convert a named reference to the actual named object */ temp_node = obj_desc->reference.object; @@ -623,7 +626,7 @@ acpi_ex_resolve_operands(u16 opcode, default: ACPI_ERROR((AE_INFO, - "Needed [Region/region_field], found [%s] %p", + "Needed [Region/RegionField], found [%s] %p", acpi_ut_get_object_type_name (obj_desc), obj_desc)); @@ -662,6 +665,7 @@ acpi_ex_resolve_operands(u16 opcode, } if (target_op == AML_DEBUG_OP) { + /* Allow store of any object to the Debug object */ break; diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 3f020c0..0456405 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c @@ -82,7 +82,7 @@ acpi_ex_do_debug_object(union acpi_opera { u32 i; - ACPI_FUNCTION_TRACE_PTR("ex_do_debug_object", source_desc); + ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", level, " ")); @@ -245,7 +245,7 @@ acpi_ex_store(union acpi_operand_object acpi_status status = AE_OK; union acpi_operand_object *ref_desc = dest_desc; - ACPI_FUNCTION_TRACE_PTR("ex_store", dest_desc); + ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc); /* Validate parameters */ @@ -297,7 +297,7 @@ acpi_ex_store(union acpi_operand_object ACPI_DUMP_STACK_ENTRY(source_desc); ACPI_DUMP_STACK_ENTRY(dest_desc); - ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ex_store", + ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ExStore", 2, "Target is not a Reference or Constant object"); @@ -396,7 +396,7 @@ acpi_ex_store_object_to_index(union acpi u8 value = 0; u32 i; - ACPI_FUNCTION_TRACE("ex_store_object_to_index"); + ACPI_FUNCTION_TRACE(ex_store_object_to_index); /* * Destination must be a reference pointer, and @@ -423,6 +423,7 @@ acpi_ex_store_object_to_index(union acpi } if (obj_desc) { + /* Decrement reference count by the ref count of the parent package */ for (i = 0; i < ((union acpi_operand_object *) @@ -502,8 +503,7 @@ acpi_ex_store_object_to_index(union acpi break; default: - ACPI_ERROR((AE_INFO, - "Target is not a Package or buffer_field")); + ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField")); status = AE_AML_OPERAND_TYPE; break; } @@ -548,7 +548,7 @@ acpi_ex_store_object_to_node(union acpi_ union acpi_operand_object *new_desc; acpi_object_type target_type; - ACPI_FUNCTION_TRACE_PTR("ex_store_object_to_node", source_desc); + ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc); /* Get current type of the node, and object attached to Node */ @@ -572,6 +572,7 @@ acpi_ex_store_object_to_node(union acpi_ /* If no implicit conversion, drop into the default case below */ if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) { + /* Force execution of default (no implicit conversion) */ target_type = ACPI_TYPE_ANY; diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c index 42967ba..591aaf0 100644 --- a/drivers/acpi/executer/exstoren.c +++ b/drivers/acpi/executer/exstoren.c @@ -72,7 +72,7 @@ acpi_ex_resolve_object(union acpi_operan union acpi_operand_object *source_desc = *source_desc_ptr; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_resolve_object"); + ACPI_FUNCTION_TRACE(ex_resolve_object); /* Ensure we have a Target that can be stored to */ @@ -97,6 +97,7 @@ acpi_ex_resolve_object(union acpi_operan */ if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_LOCAL_REFERENCE) { + /* Resolve a reference object first */ status = @@ -121,6 +122,7 @@ acpi_ex_resolve_object(union acpi_operan !((ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_LOCAL_REFERENCE) && (source_desc->reference.opcode == AML_LOAD_OP))) { + /* Conversion successful but still not a valid type */ ACPI_ERROR((AE_INFO, @@ -199,7 +201,7 @@ acpi_ex_store_object_to_object(union acp union acpi_operand_object *actual_src_desc; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ex_store_object_to_object", source_desc); + ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_object, source_desc); actual_src_desc = source_desc; if (!dest_desc) { @@ -289,6 +291,7 @@ acpi_ex_store_object_to_object(union acp } if (actual_src_desc != source_desc) { + /* Delete the intermediate (temporary) source object */ acpi_ut_remove_reference(actual_src_desc); diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c index 6ab7070..99ebe5a 100644 --- a/drivers/acpi/executer/exstorob.c +++ b/drivers/acpi/executer/exstorob.c @@ -67,7 +67,7 @@ acpi_ex_store_buffer_to_buffer(union acp u32 length; u8 *buffer; - ACPI_FUNCTION_TRACE_PTR("ex_store_buffer_to_buffer", source_desc); + ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc); /* We know that source_desc is a buffer by now */ @@ -80,7 +80,7 @@ acpi_ex_store_buffer_to_buffer(union acp */ if ((target_desc->buffer.length == 0) || (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) { - target_desc->buffer.pointer = ACPI_MEM_ALLOCATE(length); + target_desc->buffer.pointer = ACPI_ALLOCATE(length); if (!target_desc->buffer.pointer) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -91,6 +91,7 @@ acpi_ex_store_buffer_to_buffer(union acp /* Copy source buffer to target buffer */ if (length <= target_desc->buffer.length) { + /* Clear existing buffer and copy in the new one */ ACPI_MEMSET(target_desc->buffer.pointer, 0, @@ -102,7 +103,7 @@ #ifdef ACPI_OBSOLETE_BEHAVIOR * NOTE: ACPI versions up to 3.0 specified that the buffer must be * truncated if the string is smaller than the buffer. However, "other" * implementations of ACPI never did this and thus became the defacto - * standard. ACPi 3.0_a changes this behavior such that the buffer + * standard. ACPI 3.0_a changes this behavior such that the buffer * is no longer truncated. */ @@ -113,6 +114,7 @@ #ifdef ACPI_OBSOLETE_BEHAVIOR * copy must not truncate the original buffer. */ if (original_src_type == ACPI_TYPE_STRING) { + /* Set the new length of the target */ target_desc->buffer.length = length; @@ -156,7 +158,7 @@ acpi_ex_store_string_to_string(union acp u32 length; u8 *buffer; - ACPI_FUNCTION_TRACE_PTR("ex_store_string_to_string", source_desc); + ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc); /* We know that source_desc is a string by now */ @@ -183,13 +185,14 @@ acpi_ex_store_string_to_string(union acp */ if (target_desc->string.pointer && (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) { + /* Only free if not a pointer into the DSDT */ - ACPI_MEM_FREE(target_desc->string.pointer); + ACPI_FREE(target_desc->string.pointer); } - target_desc->string.pointer = ACPI_MEM_CALLOCATE((acpi_size) - length + 1); + target_desc->string.pointer = ACPI_ALLOCATE_ZEROED((acpi_size) + length + 1); if (!target_desc->string.pointer) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index ea9144f..52beee3 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c @@ -68,7 +68,7 @@ acpi_status acpi_ex_system_wait_semaphor acpi_status status; acpi_status status2; - ACPI_FUNCTION_TRACE("ex_system_wait_semaphore"); + ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); status = acpi_os_wait_semaphore(semaphore, 1, 0); if (ACPI_SUCCESS(status)) { @@ -76,6 +76,7 @@ acpi_status acpi_ex_system_wait_semaphor } if (status == AE_TIME) { + /* We must wait, so unlock the interpreter */ acpi_ex_exit_interpreter(); @@ -90,6 +91,7 @@ acpi_status acpi_ex_system_wait_semaphor status2 = acpi_ex_enter_interpreter(); if (ACPI_FAILURE(status2)) { + /* Report fatal error, could not acquire interpreter */ return_ACPI_STATUS(status2); @@ -191,7 +193,7 @@ acpi_ex_system_acquire_mutex(union acpi_ { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ex_system_acquire_mutex", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ex_system_acquire_mutex, obj_desc); if (!obj_desc) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -229,7 +231,7 @@ acpi_status acpi_ex_system_release_mutex { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_system_release_mutex"); + ACPI_FUNCTION_TRACE(ex_system_release_mutex); if (!obj_desc) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -263,7 +265,7 @@ acpi_status acpi_ex_system_signal_event( { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_system_signal_event"); + ACPI_FUNCTION_TRACE(ex_system_signal_event); if (obj_desc) { status = acpi_os_signal_semaphore(obj_desc->event.semaphore, 1); @@ -293,7 +295,7 @@ acpi_ex_system_wait_event(union acpi_ope { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ex_system_wait_event"); + ACPI_FUNCTION_TRACE(ex_system_wait_event); if (obj_desc) { status = diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index f73a61a..982c8b6 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -87,9 +87,9 @@ acpi_status acpi_ex_enter_interpreter(vo { acpi_status status; - ACPI_FUNCTION_TRACE("ex_enter_interpreter"); + ACPI_FUNCTION_TRACE(ex_enter_interpreter); - status = acpi_ut_acquire_mutex(ACPI_MTX_EXECUTE); + status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex")); } @@ -123,9 +123,9 @@ void acpi_ex_exit_interpreter(void) { acpi_status status; - ACPI_FUNCTION_TRACE("ex_exit_interpreter"); + ACPI_FUNCTION_TRACE(ex_exit_interpreter); - status = acpi_ut_release_mutex(ACPI_MTX_EXECUTE); + status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Could not release interpreter mutex")); } @@ -189,11 +189,12 @@ u8 acpi_ex_acquire_global_lock(u32 field u8 locked = FALSE; acpi_status status; - ACPI_FUNCTION_TRACE("ex_acquire_global_lock"); + ACPI_FUNCTION_TRACE(ex_acquire_global_lock); /* Only attempt lock if the always_lock bit is set */ if (field_flags & AML_FIELD_LOCK_RULE_MASK) { + /* We should attempt to get the lock, wait forever */ status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER); @@ -225,15 +226,17 @@ void acpi_ex_release_global_lock(u8 lock { acpi_status status; - ACPI_FUNCTION_TRACE("ex_release_global_lock"); + ACPI_FUNCTION_TRACE(ex_release_global_lock); /* Only attempt unlock if the caller locked it */ if (locked_by_me) { + /* OK, now release the lock */ status = acpi_ev_release_global_lock(); if (ACPI_FAILURE(status)) { + /* Report the error, but there isn't much else we can do */ ACPI_EXCEPTION((AE_INFO, status, @@ -263,7 +266,7 @@ static u32 acpi_ex_digits_needed(acpi_in u32 num_digits; acpi_integer current_value; - ACPI_FUNCTION_TRACE("ex_digits_needed"); + ACPI_FUNCTION_TRACE(ex_digits_needed); /* acpi_integer is unsigned, so we don't worry about a '-' prefix */ diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index e8165c4..1cd2578 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -48,6 +48,8 @@ MODULE_LICENSE("GPL"); static int acpi_fan_add(struct acpi_device *device); static int acpi_fan_remove(struct acpi_device *device, int type); +static int acpi_fan_suspend(struct acpi_device *device, int state); +static int acpi_fan_resume(struct acpi_device *device, int state); static struct acpi_driver acpi_fan_driver = { .name = ACPI_FAN_DRIVER_NAME, @@ -56,6 +58,8 @@ static struct acpi_driver acpi_fan_drive .ops = { .add = acpi_fan_add, .remove = acpi_fan_remove, + .suspend = acpi_fan_suspend, + .resume = acpi_fan_resume, }, }; @@ -206,6 +210,10 @@ static int acpi_fan_add(struct acpi_devi goto end; } + device->flags.force_power_state = 1; + acpi_bus_set_power(device->handle, state); + device->flags.force_power_state = 0; + result = acpi_fan_add_fs(device); if (result) goto end; @@ -239,6 +247,38 @@ static int acpi_fan_remove(struct acpi_d return_VALUE(0); } +static int acpi_fan_suspend(struct acpi_device *device, int state) +{ + if (!device) + return -EINVAL; + + acpi_bus_set_power(device->handle, ACPI_STATE_D0); + + return AE_OK; +} + +static int acpi_fan_resume(struct acpi_device *device, int state) +{ + int result = 0; + int power_state = 0; + + if (!device) + return -EINVAL; + + result = acpi_bus_get_power(device->handle, &power_state); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Error reading fan power state\n")); + return result; + } + + device->flags.force_power_state = 1; + acpi_bus_set_power(device->handle, power_state); + device->flags.force_power_state = 0; + + return result; +} + static int __init acpi_fan_init(void) { int result = 0; diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c index ea2f132..de50fab 100644 --- a/drivers/acpi/hardware/hwacpi.c +++ b/drivers/acpi/hardware/hwacpi.c @@ -63,7 +63,7 @@ acpi_status acpi_hw_initialize(void) { acpi_status status; - ACPI_FUNCTION_TRACE("hw_initialize"); + ACPI_FUNCTION_TRACE(hw_initialize); /* We must have the ACPI tables by the time we get here */ @@ -100,7 +100,7 @@ acpi_status acpi_hw_set_mode(u32 mode) acpi_status status; u32 retry; - ACPI_FUNCTION_TRACE("hw_set_mode"); + ACPI_FUNCTION_TRACE(hw_set_mode); /* * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, @@ -198,7 +198,7 @@ u32 acpi_hw_get_mode(void) acpi_status status; u32 value; - ACPI_FUNCTION_TRACE("hw_get_mode"); + ACPI_FUNCTION_TRACE(hw_get_mode); /* * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c index d84942d..608a3a6 100644 --- a/drivers/acpi/hardware/hwgpe.c +++ b/drivers/acpi/hardware/hwgpe.c @@ -214,6 +214,7 @@ acpi_hw_disable_gpe_block(struct acpi_gp /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { + /* Disable all GPEs in this register */ status = acpi_hw_low_level_write(8, 0x00, @@ -250,6 +251,7 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_ /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { + /* Clear status on all GPEs in this register */ status = acpi_hw_low_level_write(8, 0xFF, @@ -368,7 +370,7 @@ acpi_status acpi_hw_disable_all_gpes(voi { acpi_status status; - ACPI_FUNCTION_TRACE("hw_disable_all_gpes"); + ACPI_FUNCTION_TRACE(hw_disable_all_gpes); status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block); status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block); @@ -391,7 +393,7 @@ acpi_status acpi_hw_enable_all_runtime_g { acpi_status status; - ACPI_FUNCTION_TRACE("hw_enable_all_runtime_gpes"); + ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes); status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block); return_ACPI_STATUS(status); @@ -413,7 +415,7 @@ acpi_status acpi_hw_enable_all_wakeup_gp { acpi_status status; - ACPI_FUNCTION_TRACE("hw_enable_all_wakeup_gpes"); + ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes); status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block); return_ACPI_STATUS(status); diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index e1fe754..ae142de 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c @@ -43,8 +43,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -63,23 +61,21 @@ ACPI_MODULE_NAME("hwregs") * DESCRIPTION: Clears all fixed and general purpose status bits * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * + * NOTE: TBD: Flags parameter is obsolete, to be removed + * ******************************************************************************/ acpi_status acpi_hw_clear_acpi_status(u32 flags) { acpi_status status; + acpi_cpu_flags lock_flags = 0; - ACPI_FUNCTION_TRACE("hw_clear_acpi_status"); + ACPI_FUNCTION_TRACE(hw_clear_acpi_status); ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n", ACPI_BITMASK_ALL_FIXED_STATUS, (u16) acpi_gbl_FADT->xpm1a_evt_blk.address)); - if (flags & ACPI_MTX_LOCK) { - status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } + lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, @@ -104,9 +100,7 @@ acpi_status acpi_hw_clear_acpi_status(u3 status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block); unlock_and_exit: - if (flags & ACPI_MTX_LOCK) { - (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE); - } + acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); return_ACPI_STATUS(status); } @@ -129,10 +123,9 @@ acpi_status acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b) { acpi_status status = AE_OK; - struct acpi_parameter_info info; - char *sleep_state_name; + struct acpi_evaluate_info *info; - ACPI_FUNCTION_TRACE("acpi_get_sleep_type_data"); + ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data); /* Validate parameters */ @@ -140,34 +133,39 @@ acpi_get_sleep_type_data(u8 sleep_state, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Evaluate the namespace object containing the values for this state */ + /* Allocate the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } - info.parameters = NULL; - info.return_object = NULL; - sleep_state_name = + info->pathname = ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]); - status = acpi_ns_evaluate_by_name(sleep_state_name, &info); + /* Evaluate the namespace object containing the values for this state */ + + status = acpi_ns_evaluate(info); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "%s while evaluating sleep_state [%s]\n", + "%s while evaluating SleepState [%s]\n", acpi_format_exception(status), - sleep_state_name)); + info->pathname)); - return_ACPI_STATUS(status); + goto cleanup; } /* Must have a return object */ - if (!info.return_object) { + if (!info->return_object) { ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]", - sleep_state_name)); + info->pathname)); status = AE_NOT_EXIST; } /* It must be of type Package */ - else if (ACPI_GET_OBJECT_TYPE(info.return_object) != ACPI_TYPE_PACKAGE) { + else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) { ACPI_ERROR((AE_INFO, "Sleep State return object is not a Package")); status = AE_AML_OPERAND_TYPE; @@ -180,7 +178,7 @@ acpi_get_sleep_type_data(u8 sleep_state, * by BIOS vendors seems to be to have 2 or more elements, at least * one per sleep type (A/B). */ - else if (info.return_object->package.count < 2) { + else if (info->return_object->package.count < 2) { ACPI_ERROR((AE_INFO, "Sleep State return package does not have at least two elements")); status = AE_AML_NO_OPERAND; @@ -188,39 +186,42 @@ acpi_get_sleep_type_data(u8 sleep_state, /* The first two elements must both be of type Integer */ - else if ((ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[0]) + else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0]) != ACPI_TYPE_INTEGER) || - (ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[1]) + (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1]) != ACPI_TYPE_INTEGER)) { ACPI_ERROR((AE_INFO, "Sleep State return package elements are not both Integers (%s, %s)", - acpi_ut_get_object_type_name(info.return_object-> + acpi_ut_get_object_type_name(info->return_object-> package.elements[0]), - acpi_ut_get_object_type_name(info.return_object-> + acpi_ut_get_object_type_name(info->return_object-> package.elements[1]))); status = AE_AML_OPERAND_TYPE; } else { /* Valid _Sx_ package size, type, and value */ *sleep_type_a = (u8) - (info.return_object->package.elements[0])->integer.value; + (info->return_object->package.elements[0])->integer.value; *sleep_type_b = (u8) - (info.return_object->package.elements[1])->integer.value; + (info->return_object->package.elements[1])->integer.value; } if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "While evaluating sleep_state [%s], bad Sleep object %p type %s", - sleep_state_name, info.return_object, - acpi_ut_get_object_type_name(info. + "While evaluating SleepState [%s], bad Sleep object %p type %s", + info->pathname, info->return_object, + acpi_ut_get_object_type_name(info-> return_object))); } - acpi_ut_remove_reference(info.return_object); + acpi_ut_remove_reference(info->return_object); + + cleanup: + ACPI_FREE(info); return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_sleep_type_data); +ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data) /******************************************************************************* * @@ -233,13 +234,12 @@ EXPORT_SYMBOL(acpi_get_sleep_type_data); * DESCRIPTION: Map register_id into a register bitmask. * ******************************************************************************/ - struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) { ACPI_FUNCTION_ENTRY(); if (register_id > ACPI_BITREG_MAX) { - ACPI_ERROR((AE_INFO, "Invalid bit_register ID: %X", + ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X", register_id)); return (NULL); } @@ -260,6 +260,8 @@ struct acpi_bit_register_info *acpi_hw_g * * DESCRIPTION: ACPI bit_register read function. * + * NOTE: TBD: Flags parameter is obsolete, to be removed + * ******************************************************************************/ acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags) @@ -268,7 +270,7 @@ acpi_status acpi_get_register(u32 regist struct acpi_bit_register_info *bit_reg_info; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_get_register"); + ACPI_FUNCTION_TRACE(acpi_get_register); /* Get the info structure corresponding to the requested ACPI Register */ @@ -277,24 +279,14 @@ acpi_status acpi_get_register(u32 regist return_ACPI_STATUS(AE_BAD_PARAMETER); } - if (flags & ACPI_MTX_LOCK) { - status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - /* Read from the register */ - status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, + status = acpi_hw_register_read(ACPI_MTX_LOCK, bit_reg_info->parent_register, ®ister_value); - if (flags & ACPI_MTX_LOCK) { - (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE); - } - if (ACPI_SUCCESS(status)) { + /* Normalize the value that was read */ register_value = @@ -311,7 +303,7 @@ acpi_status acpi_get_register(u32 regist return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_register); +ACPI_EXPORT_SYMBOL(acpi_get_register) /******************************************************************************* * @@ -326,31 +318,28 @@ EXPORT_SYMBOL(acpi_get_register); * * DESCRIPTION: ACPI Bit Register write function. * + * NOTE: TBD: Flags parameter is obsolete, to be removed + * ******************************************************************************/ - acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags) { u32 register_value = 0; struct acpi_bit_register_info *bit_reg_info; acpi_status status; + acpi_cpu_flags lock_flags; - ACPI_FUNCTION_TRACE_U32("acpi_set_register", register_id); + ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id); /* Get the info structure corresponding to the requested ACPI Register */ bit_reg_info = acpi_hw_get_bit_register_info(register_id); if (!bit_reg_info) { - ACPI_ERROR((AE_INFO, "Bad ACPI HW register_id: %X", + ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X", register_id)); return_ACPI_STATUS(AE_BAD_PARAMETER); } - if (flags & ACPI_MTX_LOCK) { - status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } + lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); /* Always do a register read first so we can insert the new bits */ @@ -458,9 +447,7 @@ acpi_status acpi_set_register(u32 regist unlock_and_exit: - if (flags & ACPI_MTX_LOCK) { - (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE); - } + acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); /* Normalize the value that was read */ @@ -474,7 +461,7 @@ acpi_status acpi_set_register(u32 regist return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_set_register); +ACPI_EXPORT_SYMBOL(acpi_set_register) /****************************************************************************** * @@ -490,21 +477,18 @@ EXPORT_SYMBOL(acpi_set_register); * given offset. * ******************************************************************************/ - acpi_status acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) { u32 value1 = 0; u32 value2 = 0; acpi_status status; + acpi_cpu_flags lock_flags = 0; - ACPI_FUNCTION_TRACE("hw_register_read"); + ACPI_FUNCTION_TRACE(hw_register_read); if (ACPI_MTX_LOCK == use_lock) { - status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); } switch (register_id) { @@ -582,7 +566,7 @@ acpi_hw_register_read(u8 use_lock, u32 r unlock_and_exit: if (ACPI_MTX_LOCK == use_lock) { - (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE); + acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); } if (ACPI_SUCCESS(status)) { @@ -610,14 +594,12 @@ acpi_hw_register_read(u8 use_lock, u32 r acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value) { acpi_status status; + acpi_cpu_flags lock_flags = 0; - ACPI_FUNCTION_TRACE("hw_register_write"); + ACPI_FUNCTION_TRACE(hw_register_write); if (ACPI_MTX_LOCK == use_lock) { - status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); } switch (register_id) { @@ -707,7 +689,7 @@ acpi_status acpi_hw_register_write(u8 us unlock_and_exit: if (ACPI_MTX_LOCK == use_lock) { - (void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE); + acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); } return_ACPI_STATUS(status); @@ -733,7 +715,7 @@ acpi_hw_low_level_read(u32 width, u32 * u64 address; acpi_status status; - ACPI_FUNCTION_NAME("hw_low_level_read"); + ACPI_FUNCTION_NAME(hw_low_level_read); /* * Must have a valid pointer to a GAS structure, and @@ -805,7 +787,7 @@ acpi_hw_low_level_write(u32 width, u32 v u64 address; acpi_status status; - ACPI_FUNCTION_NAME("hw_low_level_write"); + ACPI_FUNCTION_NAME(hw_low_level_write); /* * Must have a valid pointer to a GAS structure, and diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 8926927..8bb43ca 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -42,7 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include #include #define _COMPONENT ACPI_HARDWARE @@ -64,7 +63,7 @@ acpi_status acpi_set_firmware_waking_vector(acpi_physical_address physical_address) { - ACPI_FUNCTION_TRACE("acpi_set_firmware_waking_vector"); + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); /* Set the vector */ @@ -79,6 +78,8 @@ acpi_set_firmware_waking_vector(acpi_phy return_ACPI_STATUS(AE_OK); } +ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) + /******************************************************************************* * * FUNCTION: acpi_get_firmware_waking_vector @@ -92,13 +93,12 @@ acpi_set_firmware_waking_vector(acpi_phy * DESCRIPTION: Access function for the firmware_waking_vector field in FACS * ******************************************************************************/ - #ifdef ACPI_FUTURE_USAGE acpi_status acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) { - ACPI_FUNCTION_TRACE("acpi_get_firmware_waking_vector"); + ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector); if (!physical_address) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -118,6 +118,8 @@ acpi_get_firmware_waking_vector(acpi_phy return_ACPI_STATUS(AE_OK); } + +ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector) #endif /******************************************************************************* @@ -134,14 +136,13 @@ #endif * various OS-specific tasks between the two steps. * ******************************************************************************/ - acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) { acpi_status status; struct acpi_object_list arg_list; union acpi_object arg; - ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_prep"); + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); /* * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. @@ -206,6 +207,8 @@ acpi_status acpi_enter_sleep_state_prep( return_ACPI_STATUS(AE_OK); } +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) + /******************************************************************************* * * FUNCTION: acpi_enter_sleep_state @@ -218,7 +221,6 @@ acpi_status acpi_enter_sleep_state_prep( * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ - acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) { u32 PM1Acontrol; @@ -228,7 +230,7 @@ acpi_status asmlinkage acpi_enter_sleep_ u32 in_value; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_enter_sleep_state"); + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { @@ -378,7 +380,7 @@ acpi_status asmlinkage acpi_enter_sleep_ return_ACPI_STATUS(AE_OK); } -EXPORT_SYMBOL(acpi_enter_sleep_state); +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) /******************************************************************************* * @@ -392,13 +394,12 @@ EXPORT_SYMBOL(acpi_enter_sleep_state); * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ - acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) { u32 in_value; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_s4bios"); + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); @@ -443,7 +444,7 @@ acpi_status asmlinkage acpi_enter_sleep_ return_ACPI_STATUS(AE_OK); } -EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios); +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) /******************************************************************************* * @@ -457,7 +458,6 @@ EXPORT_SYMBOL(acpi_enter_sleep_state_s4b * Called with interrupts ENABLED. * ******************************************************************************/ - acpi_status acpi_leave_sleep_state(u8 sleep_state) { struct acpi_object_list arg_list; @@ -468,7 +468,7 @@ acpi_status acpi_leave_sleep_state(u8 sl u32 PM1Acontrol; u32 PM1Bcontrol; - ACPI_FUNCTION_TRACE("acpi_leave_sleep_state"); + ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); /* * Set SLP_TYPE and SLP_EN to state S0. @@ -490,6 +490,7 @@ acpi_status acpi_leave_sleep_state(u8 sl ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); if (ACPI_SUCCESS(status)) { + /* Clear SLP_EN and SLP_TYP fields */ PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | @@ -583,3 +584,5 @@ acpi_status acpi_leave_sleep_state(u8 sl return_ACPI_STATUS(status); } + +ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state) diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c index fc10b7c..c4ec47c 100644 --- a/drivers/acpi/hardware/hwtimer.c +++ b/drivers/acpi/hardware/hwtimer.c @@ -42,7 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include #include #define _COMPONENT ACPI_HARDWARE @@ -61,13 +60,13 @@ ACPI_MODULE_NAME("hwtimer") ******************************************************************************/ acpi_status acpi_get_timer_resolution(u32 * resolution) { - ACPI_FUNCTION_TRACE("acpi_get_timer_resolution"); + ACPI_FUNCTION_TRACE(acpi_get_timer_resolution); if (!resolution) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - if (0 == acpi_gbl_FADT->tmr_val_ext) { + if (acpi_gbl_FADT->tmr_val_ext == 0) { *resolution = 24; } else { *resolution = 32; @@ -76,6 +75,8 @@ acpi_status acpi_get_timer_resolution(u3 return_ACPI_STATUS(AE_OK); } +ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution) + /****************************************************************************** * * FUNCTION: acpi_get_timer @@ -87,12 +88,11 @@ acpi_status acpi_get_timer_resolution(u3 * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks). * ******************************************************************************/ - acpi_status acpi_get_timer(u32 * ticks) { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_get_timer"); + ACPI_FUNCTION_TRACE(acpi_get_timer); if (!ticks) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -103,7 +103,7 @@ acpi_status acpi_get_timer(u32 * ticks) return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_timer); +ACPI_EXPORT_SYMBOL(acpi_get_timer) /****************************************************************************** * @@ -133,7 +133,6 @@ EXPORT_SYMBOL(acpi_get_timer); * 2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes * ******************************************************************************/ - acpi_status acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) { @@ -141,7 +140,7 @@ acpi_get_timer_duration(u32 start_ticks, u32 delta_ticks; acpi_integer quotient; - ACPI_FUNCTION_TRACE("acpi_get_timer_duration"); + ACPI_FUNCTION_TRACE(acpi_get_timer_duration); if (!time_elapsed) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -154,7 +153,8 @@ acpi_get_timer_duration(u32 start_ticks, if (start_ticks < end_ticks) { delta_ticks = end_ticks - start_ticks; } else if (start_ticks > end_ticks) { - if (0 == acpi_gbl_FADT->tmr_val_ext) { + if (acpi_gbl_FADT->tmr_val_ext == 0) { + /* 24-bit Timer */ delta_ticks = @@ -183,4 +183,4 @@ acpi_get_timer_duration(u32 start_ticks, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_timer_duration); +ACPI_EXPORT_SYMBOL(acpi_get_timer_duration) diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c index 2e2e405..c25b2b9 100644 --- a/drivers/acpi/hotkey.c +++ b/drivers/acpi/hotkey.c @@ -723,6 +723,8 @@ get_parms(char *config_record, goto do_fail; count = tmp1 - tmp; *action_handle = (char *)kmalloc(count + 1, GFP_KERNEL); + if (!*action_handle) + goto do_fail; strncpy(*action_handle, tmp, count); *(*action_handle + count) = 0; diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 262b1f4..15fc124 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -567,6 +567,69 @@ static int bluetooth_write(char *buf) return 0; } +static int wan_supported; + +static int wan_init(void) +{ + wan_supported = hkey_handle && + acpi_evalf(hkey_handle, NULL, "GWAN", "qv"); + + return 0; +} + +static int wan_status(void) +{ + int status; + + if (!wan_supported || + !acpi_evalf(hkey_handle, &status, "GWAN", "d")) + status = 0; + + return status; +} + +static int wan_read(char *p) +{ + int len = 0; + int status = wan_status(); + + if (!wan_supported) + len += sprintf(p + len, "status:\t\tnot supported\n"); + else if (!(status & 1)) + len += sprintf(p + len, "status:\t\tnot installed\n"); + else { + len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1)); + len += sprintf(p + len, "commands:\tenable, disable\n"); + } + + return len; +} + +static int wan_write(char *buf) +{ + int status = wan_status(); + char *cmd; + int do_cmd = 0; + + if (!wan_supported) + return -ENODEV; + + while ((cmd = next_cmd(&buf))) { + if (strlencmp(cmd, "enable") == 0) { + status |= 2; + } else if (strlencmp(cmd, "disable") == 0) { + status &= ~2; + } else + return -EINVAL; + do_cmd = 1; + } + + if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) + return -EIO; + + return 0; +} + static int video_supported; static int video_orig_autosw; @@ -1563,6 +1626,13 @@ static struct ibm_struct ibms[] = { .write = bluetooth_write, }, { + .name = "wan", + .init = wan_init, + .read = wan_read, + .write = wan_write, + .experimental = 1, + }, + { .name = "video", .init = video_init, .read = video_read, diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c index 4682441..d51d68f 100644 --- a/drivers/acpi/motherboard.c +++ b/drivers/acpi/motherboard.c @@ -37,7 +37,7 @@ #define ACPI_MB_HID1 "PNP0C01" #define ACPI_MB_HID2 "PNP0C02" /** * Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved - * Doesn't care about the failure of 'request_region', since other may reserve + * Doesn't care about the failure of 'request_region', since other may reserve * the io ports as well */ #define IS_RESERVED_ADDR(base, len) \ @@ -46,7 +46,7 @@ #define IS_RESERVED_ADDR(base, len) \ /* * Clearing the flag (IORESOURCE_BUSY) allows drivers to use * the io ports if they really know they can use it, while - * still preventing hotplug PCI devices from using it. + * still preventing hotplug PCI devices from using it. */ static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data) { @@ -123,49 +123,54 @@ static struct acpi_driver acpi_motherboa }, }; +static void __init acpi_request_region (struct acpi_generic_address *addr, + unsigned int length, char *desc) +{ + if (!addr->address || !length) + return; + + if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) + request_region(addr->address, length, desc); + else if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + request_mem_region(addr->address, length, desc); +} + static void __init acpi_reserve_resources(void) { - if (acpi_gbl_FADT->xpm1a_evt_blk.address && acpi_gbl_FADT->pm1_evt_len) - request_region(acpi_gbl_FADT->xpm1a_evt_blk.address, - acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK"); + acpi_request_region(&acpi_gbl_FADT->xpm1a_evt_blk, + acpi_gbl_FADT->pm1_evt_len, "ACPI PM1a_EVT_BLK"); - if (acpi_gbl_FADT->xpm1b_evt_blk.address && acpi_gbl_FADT->pm1_evt_len) - request_region(acpi_gbl_FADT->xpm1b_evt_blk.address, - acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK"); + acpi_request_region(&acpi_gbl_FADT->xpm1b_evt_blk, + acpi_gbl_FADT->pm1_evt_len, "ACPI PM1b_EVT_BLK"); - if (acpi_gbl_FADT->xpm1a_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len) - request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address, - acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK"); + acpi_request_region(&acpi_gbl_FADT->xpm1a_cnt_blk, + acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1a_CNT_BLK"); - if (acpi_gbl_FADT->xpm1b_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len) - request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address, - acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK"); + acpi_request_region(&acpi_gbl_FADT->xpm1b_cnt_blk, + acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1b_CNT_BLK"); - if (acpi_gbl_FADT->xpm_tmr_blk.address && acpi_gbl_FADT->pm_tm_len == 4) - request_region(acpi_gbl_FADT->xpm_tmr_blk.address, 4, "PM_TMR"); + if (acpi_gbl_FADT->pm_tm_len == 4) + acpi_request_region(&acpi_gbl_FADT->xpm_tmr_blk, 4, "ACPI PM_TMR"); - if (acpi_gbl_FADT->xpm2_cnt_blk.address && acpi_gbl_FADT->pm2_cnt_len) - request_region(acpi_gbl_FADT->xpm2_cnt_blk.address, - acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK"); + acpi_request_region(&acpi_gbl_FADT->xpm2_cnt_blk, + acpi_gbl_FADT->pm2_cnt_len, "ACPI PM2_CNT_BLK"); /* Length of GPE blocks must be a non-negative multiple of 2 */ - if (acpi_gbl_FADT->xgpe0_blk.address && acpi_gbl_FADT->gpe0_blk_len && - !(acpi_gbl_FADT->gpe0_blk_len & 0x1)) - request_region(acpi_gbl_FADT->xgpe0_blk.address, - acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK"); + if (!(acpi_gbl_FADT->gpe0_blk_len & 0x1)) + acpi_request_region(&acpi_gbl_FADT->xgpe0_blk, + acpi_gbl_FADT->gpe0_blk_len, "ACPI GPE0_BLK"); - if (acpi_gbl_FADT->xgpe1_blk.address && acpi_gbl_FADT->gpe1_blk_len && - !(acpi_gbl_FADT->gpe1_blk_len & 0x1)) - request_region(acpi_gbl_FADT->xgpe1_blk.address, - acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK"); + if (!(acpi_gbl_FADT->gpe1_blk_len & 0x1)) + acpi_request_region(&acpi_gbl_FADT->xgpe1_blk, + acpi_gbl_FADT->gpe1_blk_len, "ACPI GPE1_BLK"); } static int __init acpi_motherboard_init(void) { acpi_bus_register_driver(&acpi_motherboard_driver1); acpi_bus_register_driver(&acpi_motherboard_driver2); - /* + /* * Guarantee motherboard IO reservation first * This module must run after scan.c */ diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index 1149bc1..48fadad 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c @@ -70,7 +70,7 @@ acpi_status acpi_ns_root_initialize(void union acpi_operand_object *obj_desc; acpi_string val = NULL; - ACPI_FUNCTION_TRACE("ns_root_initialize"); + ACPI_FUNCTION_TRACE(ns_root_initialize); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -98,6 +98,7 @@ acpi_status acpi_ns_root_initialize(void "Entering predefined entries into namespace\n")); for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { + /* _OSI is optional for now, will be permanent later */ if (!ACPI_STRCMP(init_val->name, "_OSI") @@ -156,7 +157,7 @@ acpi_status acpi_ns_root_initialize(void #if defined (ACPI_ASL_COMPILER) - /* save the parameter count for the i_aSL compiler */ + /* Save the parameter count for the i_aSL compiler */ new_node->value = obj_desc->method.param_count; #else @@ -258,10 +259,8 @@ #endif /* Save a handle to "_GPE", it is always present */ if (ACPI_SUCCESS(status)) { - status = - acpi_ns_get_node_by_path("\\_GPE", NULL, - ACPI_NS_NO_UPSEARCH, - &acpi_gbl_fadt_gpe_device); + status = acpi_ns_get_node(NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, + &acpi_gbl_fadt_gpe_device); } return_ACPI_STATUS(status); @@ -310,17 +309,17 @@ acpi_ns_lookup(union acpi_generic_state acpi_object_type type_to_check_for; acpi_object_type this_search_type; u32 search_parent_flag = ACPI_NS_SEARCH_PARENT; - u32 local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | - ACPI_NS_SEARCH_PARENT); + u32 local_flags; - ACPI_FUNCTION_TRACE("ns_lookup"); + ACPI_FUNCTION_TRACE(ns_lookup); if (!return_node) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - acpi_gbl_ns_lookup_count++; + local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); *return_node = ACPI_ENTRY_NOT_FOUND; + acpi_gbl_ns_lookup_count++; if (!acpi_gbl_root_node) { return_ACPI_STATUS(AE_NO_NAMESPACE); @@ -346,14 +345,17 @@ acpi_ns_lookup(union acpi_generic_state return_ACPI_STATUS(AE_AML_INTERNAL); } - /* - * This node might not be a actual "scope" node (such as a - * Device/Method, etc.) It could be a Package or other object node. - * Backup up the tree to find the containing scope node. - */ - while (!acpi_ns_opens_scope(prefix_node->type) && - prefix_node->type != ACPI_TYPE_ANY) { - prefix_node = acpi_ns_get_parent_node(prefix_node); + if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) { + /* + * This node might not be a actual "scope" node (such as a + * Device/Method, etc.) It could be a Package or other object node. + * Backup up the tree to find the containing scope node. + */ + while (!acpi_ns_opens_scope(prefix_node->type) && + prefix_node->type != ACPI_TYPE_ANY) { + prefix_node = + acpi_ns_get_parent_node(prefix_node); + } } } @@ -365,6 +367,7 @@ acpi_ns_lookup(union acpi_generic_state * Begin examination of the actual pathname */ if (!pathname) { + /* A Null name_path is allowed and refers to the root */ num_segments = 0; @@ -389,6 +392,7 @@ acpi_ns_lookup(union acpi_generic_state * to the current scope). */ if (*path == (u8) AML_ROOT_PREFIX) { + /* Pathname is fully qualified, start from the root */ this_node = acpi_gbl_root_node; @@ -416,6 +420,7 @@ acpi_ns_lookup(union acpi_generic_state this_node = prefix_node; num_carats = 0; while (*path == (u8) AML_PARENT_PREFIX) { + /* Name is fully qualified, no search rules apply */ search_parent_flag = ACPI_NS_NO_UPSEARCH; @@ -430,6 +435,7 @@ acpi_ns_lookup(union acpi_generic_state num_carats++; this_node = acpi_ns_get_parent_node(this_node); if (!this_node) { + /* Current scope has no parent scope */ ACPI_ERROR((AE_INFO, @@ -569,6 +575,7 @@ acpi_ns_lookup(union acpi_generic_state &this_node); if (ACPI_FAILURE(status)) { if (status == AE_NOT_FOUND) { + /* Name not found in ACPI namespace */ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, @@ -602,10 +609,11 @@ acpi_ns_lookup(union acpi_generic_state (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) && (this_node->type != ACPI_TYPE_ANY) && (this_node->type != type_to_check_for)) { + /* Complain about a type mismatch */ ACPI_WARNING((AE_INFO, - "ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)", + "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", ACPI_CAST_PTR(char, &simple_name), acpi_ut_get_type_name(this_node->type), acpi_ut_get_type_name diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index 9b871f3..dc3f073 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c @@ -47,9 +47,6 @@ #include #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsalloc") -/* Local prototypes */ -static void acpi_ns_remove_reference(struct acpi_namespace_node *node); - /******************************************************************************* * * FUNCTION: acpi_ns_create_node @@ -61,14 +58,13 @@ static void acpi_ns_remove_reference(str * DESCRIPTION: Create a namespace node * ******************************************************************************/ - struct acpi_namespace_node *acpi_ns_create_node(u32 name) { struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE("ns_create_node"); + ACPI_FUNCTION_TRACE(ns_create_node); - node = ACPI_MEM_CALLOCATE(sizeof(struct acpi_namespace_node)); + node = acpi_os_acquire_object(acpi_gbl_namespace_cache); if (!node) { return_PTR(NULL); } @@ -76,9 +72,7 @@ struct acpi_namespace_node *acpi_ns_crea ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++); node->name.integer = name; - node->reference_count = 1; ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED); - return_PTR(node); } @@ -100,7 +94,7 @@ void acpi_ns_delete_node(struct acpi_nam struct acpi_namespace_node *prev_node; struct acpi_namespace_node *next_node; - ACPI_FUNCTION_TRACE_PTR("ns_delete_node", node); + ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node); parent_node = acpi_ns_get_parent_node(node); @@ -115,6 +109,7 @@ void acpi_ns_delete_node(struct acpi_nam } if (prev_node) { + /* Node is not first child, unlink it */ prev_node->peer = next_node->peer; @@ -125,6 +120,7 @@ void acpi_ns_delete_node(struct acpi_nam /* Node is first child (has no previous peer) */ if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + /* No peers at all */ parent_node->child = NULL; @@ -137,10 +133,10 @@ void acpi_ns_delete_node(struct acpi_nam ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); /* - * Detach an object if there is one then delete the node + * Detach an object if there is one, then delete the node */ acpi_ns_detach_object(node); - ACPI_MEM_FREE(node); + (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); return_VOID; } @@ -171,7 +167,7 @@ void acpi_ns_install_node(struct acpi_wa acpi_owner_id owner_id = 0; struct acpi_namespace_node *child_node; - ACPI_FUNCTION_TRACE("ns_install_node"); + ACPI_FUNCTION_TRACE(ns_install_node); /* * Get the owner ID from the Walk state @@ -216,14 +212,6 @@ void acpi_ns_install_node(struct acpi_wa acpi_ut_get_type_name(parent_node->type), parent_node)); - /* - * Increment the reference count(s) of all parents up to - * the root! - */ - while ((node = acpi_ns_get_parent_node(node)) != NULL) { - node->reference_count++; - } - return_VOID; } @@ -244,10 +232,9 @@ void acpi_ns_delete_children(struct acpi { struct acpi_namespace_node *child_node; struct acpi_namespace_node *next_node; - struct acpi_namespace_node *node; u8 flags; - ACPI_FUNCTION_TRACE_PTR("ns_delete_children", parent_node); + ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node); if (!parent_node) { return_VOID; @@ -264,6 +251,7 @@ void acpi_ns_delete_children(struct acpi * Deallocate all children at this level */ do { + /* Get the things we need */ next_node = child_node->peer; @@ -289,26 +277,10 @@ void acpi_ns_delete_children(struct acpi */ acpi_ns_detach_object(child_node); - /* - * Decrement the reference count(s) of all parents up to - * the root! (counts were incremented when the node was created) - */ - node = child_node; - while ((node = acpi_ns_get_parent_node(node)) != NULL) { - node->reference_count--; - } - - /* There should be only one reference remaining on this node */ - - if (child_node->reference_count != 1) { - ACPI_WARNING((AE_INFO, - "Existing references (%d) on node being deleted (%p)", - child_node->reference_count, child_node)); - } - /* Now we can delete the node */ - ACPI_MEM_FREE(child_node); + (void)acpi_os_release_object(acpi_gbl_namespace_cache, + child_node); /* And move on to the next child in the list */ @@ -341,7 +313,7 @@ void acpi_ns_delete_namespace_subtree(st struct acpi_namespace_node *child_node = NULL; u32 level = 1; - ACPI_FUNCTION_TRACE("ns_delete_namespace_subtree"); + ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree); if (!parent_node) { return_VOID; @@ -352,11 +324,14 @@ void acpi_ns_delete_namespace_subtree(st * to where we started. */ while (level > 0) { + /* Get the next node in this scope (NULL if none) */ - child_node = acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, - child_node); + child_node = + acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, + child_node); if (child_node) { + /* Found a child node - detach any attached object */ acpi_ns_detach_object(child_node); @@ -401,55 +376,6 @@ void acpi_ns_delete_namespace_subtree(st /******************************************************************************* * - * FUNCTION: acpi_ns_remove_reference - * - * PARAMETERS: Node - Named node whose reference count is to be - * decremented - * - * RETURN: None. - * - * DESCRIPTION: Remove a Node reference. Decrements the reference count - * of all parent Nodes up to the root. Any node along - * the way that reaches zero references is freed. - * - ******************************************************************************/ - -static void acpi_ns_remove_reference(struct acpi_namespace_node *node) -{ - struct acpi_namespace_node *parent_node; - struct acpi_namespace_node *this_node; - - ACPI_FUNCTION_ENTRY(); - - /* - * Decrement the reference count(s) of this node and all - * nodes up to the root, Delete anything with zero remaining references. - */ - this_node = node; - while (this_node) { - /* Prepare to move up to parent */ - - parent_node = acpi_ns_get_parent_node(this_node); - - /* Decrement the reference count on this node */ - - this_node->reference_count--; - - /* Delete the node if no more references */ - - if (!this_node->reference_count) { - /* Delete all children and delete the node */ - - acpi_ns_delete_children(this_node); - acpi_ns_delete_node(this_node); - } - - this_node = parent_node; - } -} - -/******************************************************************************* - * * FUNCTION: acpi_ns_delete_namespace_by_owner * * PARAMETERS: owner_id - All nodes with this owner will be deleted @@ -469,15 +395,15 @@ void acpi_ns_delete_namespace_by_owner(a u32 level; struct acpi_namespace_node *parent_node; - ACPI_FUNCTION_TRACE_U32("ns_delete_namespace_by_owner", owner_id); + ACPI_FUNCTION_TRACE_U32(ns_delete_namespace_by_owner, owner_id); if (owner_id == 0) { return_VOID; } + deletion_node = NULL; parent_node = acpi_gbl_root_node; child_node = NULL; - deletion_node = NULL; level = 1; /* @@ -494,12 +420,14 @@ void acpi_ns_delete_namespace_by_owner(a child_node); if (deletion_node) { - acpi_ns_remove_reference(deletion_node); + acpi_ns_delete_children(deletion_node); + acpi_ns_delete_node(deletion_node); deletion_node = NULL; } if (child_node) { if (child_node->owner_id == owner_id) { + /* Found a matching child node - detach any attached object */ acpi_ns_detach_object(child_node); diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index a280731..d72df66 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -75,7 +75,7 @@ void acpi_ns_print_pathname(u32 num_segm { acpi_native_uint i; - ACPI_FUNCTION_NAME("ns_print_pathname"); + ACPI_FUNCTION_NAME(ns_print_pathname); if (!(acpi_dbg_level & ACPI_LV_NAMES) || !(acpi_dbg_layer & ACPI_NAMESPACE)) { @@ -123,7 +123,7 @@ void acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component) { - ACPI_FUNCTION_TRACE("ns_dump_pathname"); + ACPI_FUNCTION_TRACE(ns_dump_pathname); /* Do this only if the requested debug level and component are enabled */ @@ -167,7 +167,7 @@ acpi_ns_dump_one_object(acpi_handle obj_ u32 dbg_level; u32 i; - ACPI_FUNCTION_NAME("ns_dump_one_object"); + ACPI_FUNCTION_NAME(ns_dump_one_object); /* Is output enabled? */ @@ -191,6 +191,7 @@ acpi_ns_dump_one_object(acpi_handle obj_ } if (!(info->display_type & ACPI_DISPLAY_SHORT)) { + /* Indent the object according to the level */ acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " "); @@ -203,6 +204,9 @@ acpi_ns_dump_one_object(acpi_handle obj_ } if (!acpi_ut_valid_acpi_name(this_node->name.integer)) { + this_node->name.integer = + acpi_ut_repair_name(this_node->name.integer); + ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X", this_node->name.integer)); } @@ -226,6 +230,7 @@ acpi_ns_dump_one_object(acpi_handle obj_ case ACPI_DISPLAY_SUMMARY: if (!obj_desc) { + /* No attached object, we are done */ acpi_os_printf("\n"); @@ -419,6 +424,7 @@ acpi_ns_dump_one_object(acpi_handle obj_ acpi_os_printf("O:%p", obj_desc); if (!obj_desc) { + /* No attached object, we are done */ acpi_os_printf("\n"); @@ -669,7 +675,7 @@ void acpi_ns_dump_tables(acpi_handle sea { acpi_handle search_handle = search_base; - ACPI_FUNCTION_TRACE("ns_dump_tables"); + ACPI_FUNCTION_TRACE(ns_dump_tables); if (!acpi_gbl_root_node) { /* @@ -682,6 +688,7 @@ void acpi_ns_dump_tables(acpi_handle sea } if (ACPI_NS_ALL == search_base) { + /* Entire namespace */ search_handle = acpi_gbl_root_node; diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c index aff899a..c6bf5d3 100644 --- a/drivers/acpi/namespace/nsdumpdv.c +++ b/drivers/acpi/namespace/nsdumpdv.c @@ -74,7 +74,7 @@ acpi_ns_dump_one_device(acpi_handle obj_ acpi_status status; u32 i; - ACPI_FUNCTION_NAME("ns_dump_one_device"); + ACPI_FUNCTION_NAME(ns_dump_one_device); status = acpi_ns_dump_one_object(obj_handle, level, context, return_value); @@ -92,7 +92,7 @@ acpi_ns_dump_one_device(acpi_handle obj_ info->hardware_id.value, ACPI_FORMAT_UINT64(info->address), info->current_status)); - ACPI_MEM_FREE(info); + ACPI_FREE(info); } return (status); @@ -115,7 +115,7 @@ void acpi_ns_dump_root_devices(void) acpi_handle sys_bus_handle; acpi_status status; - ACPI_FUNCTION_NAME("ns_dump_root_devices"); + ACPI_FUNCTION_NAME(ns_dump_root_devices); /* Only dump the table if tracing is enabled */ diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index 19d7b94..4b0a4a8 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c @@ -1,7 +1,6 @@ /******************************************************************************* * - * Module Name: nseval - Object evaluation interfaces -- includes control - * method lookup and execution. + * Module Name: nseval - Object evaluation, includes control method execution * ******************************************************************************/ @@ -50,196 +49,14 @@ #include #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nseval") -/* Local prototypes */ -static acpi_status -acpi_ns_execute_control_method(struct acpi_parameter_info *info); - -static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info); - -/******************************************************************************* - * - * FUNCTION: acpi_ns_evaluate_relative - * - * PARAMETERS: Pathname - Name of method to execute, If NULL, the - * handle is the object to execute - * Info - Method info block, contains: - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * Params - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * - * RETURN: Status - * - * DESCRIPTION: Evaluate the object or find and execute the requested method - * - * MUTEX: Locks Namespace - * - ******************************************************************************/ - -acpi_status -acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info) -{ - acpi_status status; - struct acpi_namespace_node *node = NULL; - union acpi_generic_state *scope_info; - char *internal_path = NULL; - - ACPI_FUNCTION_TRACE("ns_evaluate_relative"); - - /* - * Must have a valid object handle - */ - if (!info || !info->node) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - /* Build an internal name string for the method */ - - status = acpi_ns_internalize_name(pathname, &internal_path); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - scope_info = acpi_ut_create_generic_state(); - if (!scope_info) { - goto cleanup1; - } - - /* Get the prefix handle and Node */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - info->node = acpi_ns_map_handle_to_node(info->node); - if (!info->node) { - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - status = AE_BAD_PARAMETER; - goto cleanup; - } - - /* Lookup the name in the namespace */ - - scope_info->scope.node = info->node; - status = acpi_ns_lookup(scope_info, internal_path, ACPI_TYPE_ANY, - ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, - &node); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Object [%s] not found [%s]\n", - pathname, acpi_format_exception(status))); - goto cleanup; - } - - /* - * Now that we have a handle to the object, we can attempt to evaluate it. - */ - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", - pathname, node, acpi_ns_get_attached_object(node))); - - info->node = node; - status = acpi_ns_evaluate_by_handle(info); - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "*** Completed eval of object %s ***\n", pathname)); - - cleanup: - acpi_ut_delete_generic_state(scope_info); - - cleanup1: - ACPI_MEM_FREE(internal_path); - return_ACPI_STATUS(status); -} - /******************************************************************************* * - * FUNCTION: acpi_ns_evaluate_by_name + * FUNCTION: acpi_ns_evaluate * - * PARAMETERS: Pathname - Fully qualified pathname to the object - * Info - Method info block, contains: - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * Params - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * - * RETURN: Status - * - * DESCRIPTION: Evaluate the object or rind and execute the requested method - * passing the given parameters - * - * MUTEX: Locks Namespace - * - ******************************************************************************/ - -acpi_status -acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info) -{ - acpi_status status; - char *internal_path = NULL; - - ACPI_FUNCTION_TRACE("ns_evaluate_by_name"); - - /* Build an internal name string for the method */ - - status = acpi_ns_internalize_name(pathname, &internal_path); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Lookup the name in the namespace */ - - status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY, - ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, - &info->node); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Object at [%s] was not found, status=%.4X\n", - pathname, status)); - goto cleanup; - } - - /* - * Now that we have a handle to the object, we can attempt to evaluate it. - */ - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", - pathname, info->node, - acpi_ns_get_attached_object(info->node))); - - status = acpi_ns_evaluate_by_handle(info); - - ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "*** Completed eval of object %s ***\n", pathname)); - - cleanup: - - /* Cleanup */ - - if (internal_path) { - ACPI_MEM_FREE(internal_path); - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_evaluate_by_handle - * - * PARAMETERS: Info - Method info block, contains: - * Node - Method/Object Node to execute + * PARAMETERS: Info - Evaluation info block, contains: + * prefix_node - Prefix or Method/Object Node to execute + * Pathname - Name of method to execute, If NULL, the + * Node is the object to execute * Parameters - List of parameters to pass to the method, * terminated by NULL. Params itself may be * NULL if no parameters are being passed. @@ -248,29 +65,21 @@ acpi_ns_evaluate_by_name(char *pathname, * parameter_type - Type of Parameter list * return_object - Where to put method's return value (if * any). If NULL, no value is returned. + * Flags - ACPI_IGNORE_RETURN_VALUE to delete return * * RETURN: Status * - * DESCRIPTION: Evaluate object or execute the requested method passing the - * given parameters + * DESCRIPTION: Execute a control method or return the current value of an + * ACPI namespace object. * - * MUTEX: Locks Namespace + * MUTEX: Locks interpreter * ******************************************************************************/ - -acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info) +acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) { acpi_status status; - ACPI_FUNCTION_TRACE("ns_evaluate_by_handle"); - - /* Check if namespace has been initialized */ - - if (!acpi_gbl_root_node) { - return_ACPI_STATUS(AE_NO_NAMESPACE); - } - - /* Parameter Validation */ + ACPI_FUNCTION_TRACE(ns_evaluate); if (!info) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -280,202 +89,120 @@ acpi_status acpi_ns_evaluate_by_handle(s info->return_object = NULL; - /* Get the prefix handle and Node */ - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + /* + * Get the actual namespace node for the target object. Handles these cases: + * + * 1) Null node, Pathname (absolute path) + * 2) Node, Pathname (path relative to Node) + * 3) Node, Null Pathname + */ + status = acpi_ns_get_node(info->prefix_node, info->pathname, + ACPI_NS_NO_UPSEARCH, &info->resolved_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - info->node = acpi_ns_map_handle_to_node(info->node); - if (!info->node) { - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - /* * For a method alias, we must grab the actual method node so that proper * scoping context will be established before execution. */ - if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { - info->node = + if (acpi_ns_get_type(info->resolved_node) == + ACPI_TYPE_LOCAL_METHOD_ALIAS) { + info->resolved_node = ACPI_CAST_PTR(struct acpi_namespace_node, - info->node->object); + info->resolved_node->object); } + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname, + info->resolved_node, + acpi_ns_get_attached_object(info->resolved_node))); + /* * Two major cases here: - * 1) The object is an actual control method -- execute it. - * 2) The object is not a method -- just return it's current value * - * In both cases, the namespace is unlocked by the acpi_ns* procedure + * 1) The object is a control method -- execute it + * 2) The object is not a method -- just return it's current value */ - if (acpi_ns_get_type(info->node) == ACPI_TYPE_METHOD) { - /* - * Case 1) We have an actual control method to execute - */ - status = acpi_ns_execute_control_method(info); - } else { + if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) { /* - * Case 2) Object is NOT a method, just return its current value + * 1) Object is a control method - execute it */ - status = acpi_ns_get_object_value(info); - } - - /* - * Check if there is a return value on the stack that must be dealt with - */ - if (status == AE_CTRL_RETURN_VALUE) { - /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ - - status = AE_OK; - } - - /* - * Namespace was unlocked by the handling acpi_ns* function, so we - * just return - */ - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_execute_control_method - * - * PARAMETERS: Info - Method info block, contains: - * Node - Method Node to execute - * obj_desc - Method object - * Parameters - List of parameters to pass to the method, - * terminated by NULL. Params itself may be - * NULL if no parameters are being passed. - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * parameter_type - Type of Parameter list - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. - * - * RETURN: Status - * - * DESCRIPTION: Execute the requested method passing the given parameters - * - * MUTEX: Assumes namespace is locked - * - ******************************************************************************/ - -static acpi_status -acpi_ns_execute_control_method(struct acpi_parameter_info *info) -{ - acpi_status status; - - ACPI_FUNCTION_TRACE("ns_execute_control_method"); - - /* Verify that there is a method associated with this object */ - - info->obj_desc = acpi_ns_get_attached_object(info->node); - if (!info->obj_desc) { - ACPI_ERROR((AE_INFO, "No attached method object")); - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return_ACPI_STATUS(AE_NULL_OBJECT); - } - - ACPI_DUMP_PATHNAME(info->node, "Execute Method:", - ACPI_LV_INFO, _COMPONENT); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Method at AML address %p Length %X\n", - info->obj_desc->method.aml_start + 1, - info->obj_desc->method.aml_length - 1)); - - /* - * Unlock the namespace before execution. This allows namespace access - * via the external Acpi* interfaces while a method is being executed. - * However, any namespace deletion must acquire both the namespace and - * interpreter locks to ensure that no thread is using the portion of the - * namespace that is being deleted. - */ - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + /* Verify that there is a method object associated with this node */ - /* - * Execute the method via the interpreter. The interpreter is locked - * here before calling into the AML parser - */ - status = acpi_ex_enter_interpreter(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + info->obj_desc = + acpi_ns_get_attached_object(info->resolved_node); + if (!info->obj_desc) { + ACPI_ERROR((AE_INFO, + "Control method has no attached sub-object")); + return_ACPI_STATUS(AE_NULL_OBJECT); + } - status = acpi_ps_execute_method(info); - acpi_ex_exit_interpreter(); + ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:", + ACPI_LV_INFO, _COMPONENT); - return_ACPI_STATUS(status); -} + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Method at AML address %p Length %X\n", + info->obj_desc->method.aml_start + 1, + info->obj_desc->method.aml_length - 1)); -/******************************************************************************* - * - * FUNCTION: acpi_ns_get_object_value - * - * PARAMETERS: Info - Method info block, contains: - * Node - Object's NS node - * return_object - Where to put object value (if - * any). If NULL, no value is returned. - * - * RETURN: Status - * - * DESCRIPTION: Return the current value of the object - * - * MUTEX: Assumes namespace is locked, leaves namespace unlocked - * - ******************************************************************************/ + /* + * Any namespace deletion must acquire both the namespace and + * interpreter locks to ensure that no thread is using the portion of + * the namespace that is being deleted. + * + * Execute the method via the interpreter. The interpreter is locked + * here before calling into the AML parser + */ + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } -static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info) -{ - acpi_status status = AE_OK; - struct acpi_namespace_node *resolved_node = info->node; + status = acpi_ps_execute_method(info); + acpi_ex_exit_interpreter(); + } else { + /* + * 2) Object is not a method, return its current value + */ - ACPI_FUNCTION_TRACE("ns_get_object_value"); + /* + * Objects require additional resolution steps (e.g., the Node may be + * a field that must be read, etc.) -- we can't just grab the object + * out of the node. + * + * Use resolve_node_to_value() to get the associated value. + * + * NOTE: we can get away with passing in NULL for a walk state because + * resolved_node is guaranteed to not be a reference to either a method + * local or a method argument (because this interface is never called + * from a running method.) + * + * Even though we do not directly invoke the interpreter for object + * resolution, we must lock it because we could access an opregion. + * The opregion access code assumes that the interpreter is locked. + */ + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } - /* - * Objects require additional resolution steps (e.g., the Node may be a - * field that must be read, etc.) -- we can't just grab the object out of - * the node. - */ + /* Function has a strange interface */ - /* - * Use resolve_node_to_value() to get the associated value. This call always - * deletes obj_desc (allocated above). - * - * NOTE: we can get away with passing in NULL for a walk state because - * obj_desc is guaranteed to not be a reference to either a method local or - * a method argument (because this interface can only be called from the - * acpi_evaluate external interface, never called from a running method.) - * - * Even though we do not directly invoke the interpreter for this, we must - * enter it because we could access an opregion. The opregion access code - * assumes that the interpreter is locked. - * - * We must release the namespace lock before entering the intepreter. - */ - status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + status = + acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); + acpi_ex_exit_interpreter(); - status = acpi_ex_enter_interpreter(); - if (ACPI_SUCCESS(status)) { - status = acpi_ex_resolve_node_to_value(&resolved_node, NULL); /* * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed * in resolved_node. */ - acpi_ex_exit_interpreter(); - if (ACPI_SUCCESS(status)) { status = AE_CTRL_RETURN_VALUE; - info->return_object = ACPI_CAST_PTR - (union acpi_operand_object, resolved_node); + info->return_object = + ACPI_CAST_PTR(union acpi_operand_object, + info->resolved_node); + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Returning object %p [%s]\n", info->return_object, @@ -484,7 +211,30 @@ static acpi_status acpi_ns_get_object_va } } - /* Namespace is unlocked */ + /* + * Check if there is a return value that must be dealt with + */ + if (status == AE_CTRL_RETURN_VALUE) { + + /* If caller does not want the return value, delete it */ + if (info->flags & ACPI_IGNORE_RETURN_VALUE) { + acpi_ut_remove_reference(info->return_object); + info->return_object = NULL; + } + + /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ + + status = AE_OK; + } + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "*** Completed evaluation of object %s ***\n", + info->pathname)); + + /* + * Namespace was unlocked by the handling acpi_ns* function, so we + * just return + */ return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 9f929e4..aec8488 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c @@ -58,6 +58,10 @@ static acpi_status acpi_ns_init_one_device(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value); +static acpi_status +acpi_ns_find_ini_methods(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value); + /******************************************************************************* * * FUNCTION: acpi_ns_initialize_objects @@ -76,7 +80,7 @@ acpi_status acpi_ns_initialize_objects(v acpi_status status; struct acpi_init_walk_info info; - ACPI_FUNCTION_TRACE("ns_initialize_objects"); + ACPI_FUNCTION_TRACE(ns_initialize_objects); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "**** Starting initialization of namespace objects ****\n")); @@ -93,7 +97,7 @@ acpi_status acpi_ns_initialize_objects(v ACPI_UINT32_MAX, acpi_ns_init_one_object, &info, NULL); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace")); + ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, @@ -133,7 +137,7 @@ acpi_status acpi_ns_initialize_devices(v acpi_status status; struct acpi_device_walk_info info; - ACPI_FUNCTION_TRACE("ns_initialize_devices"); + ACPI_FUNCTION_TRACE(ns_initialize_devices); /* Init counters */ @@ -142,30 +146,46 @@ acpi_status acpi_ns_initialize_devices(v info.num_INI = 0; ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "Executing all Device _STA and_INI methods:")); + "Initializing Device/Processor/Thermal objects by executing _INI methods:")); + + /* Tree analysis: find all subtrees that contain _INI methods */ - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, + acpi_ns_find_ini_methods, &info, NULL); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto error_exit; } - /* Walk namespace for all objects */ + /* Allocate the evaluation information block */ + + info.evaluate_info = + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info.evaluate_info) { + status = AE_NO_MEMORY; + goto error_exit; + } + + /* Walk namespace to execute all _INIs on present devices */ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, TRUE, + ACPI_UINT32_MAX, FALSE, acpi_ns_init_one_device, &info, NULL); - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - + ACPI_FREE(info.evaluate_info); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace")); + goto error_exit; } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\n%hd Devices found - executed %hd _STA, %hd _INI methods\n", - info.device_count, info.num_STA, info.num_INI)); + "\nExecuted %hd _INI methods requiring %hd _STA executions (examined %hd objects)\n", + info.num_INI, info.num_STA, info.device_count)); return_ACPI_STATUS(status); + + error_exit: + ACPI_EXCEPTION((AE_INFO, status, "During device initialization")); + return_ACPI_STATUS(status); } /******************************************************************************* @@ -200,7 +220,7 @@ acpi_ns_init_one_object(acpi_handle obj_ (struct acpi_namespace_node *)obj_handle; union acpi_operand_object *obj_desc; - ACPI_FUNCTION_NAME("ns_init_one_object"); + ACPI_FUNCTION_NAME(ns_init_one_object); info->object_count++; @@ -311,6 +331,72 @@ acpi_ns_init_one_object(acpi_handle obj_ /******************************************************************************* * + * FUNCTION: acpi_ns_find_ini_methods + * + * PARAMETERS: acpi_walk_callback + * + * RETURN: acpi_status + * + * DESCRIPTION: Called during namespace walk. Finds objects named _INI under + * device/processor/thermal objects, and marks the entire subtree + * with a SUBTREE_HAS_INI flag. This flag is used during the + * subsequent device initialization walk to avoid entire subtrees + * that do not contain an _INI. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_find_ini_methods(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value) +{ + struct acpi_device_walk_info *info = + ACPI_CAST_PTR(struct acpi_device_walk_info, context); + struct acpi_namespace_node *node; + struct acpi_namespace_node *parent_node; + + /* Keep count of device/processor/thermal objects */ + + node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); + if ((node->type == ACPI_TYPE_DEVICE) || + (node->type == ACPI_TYPE_PROCESSOR) || + (node->type == ACPI_TYPE_THERMAL)) { + info->device_count++; + return (AE_OK); + } + + /* We are only looking for methods named _INI */ + + if (!ACPI_COMPARE_NAME(node->name.ascii, METHOD_NAME__INI)) { + return (AE_OK); + } + + /* + * The only _INI methods that we care about are those that are + * present under Device, Processor, and Thermal objects. + */ + parent_node = acpi_ns_get_parent_node(node); + switch (parent_node->type) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* Mark parent and bubble up the INI present flag to the root */ + + while (parent_node) { + parent_node->flags |= ANOBJ_SUBTREE_HAS_INI; + parent_node = acpi_ns_get_parent_node(parent_node); + } + break; + + default: + break; + } + + return (AE_OK); +} + +/******************************************************************************* + * * FUNCTION: acpi_ns_init_one_device * * PARAMETERS: acpi_walk_callback @@ -327,119 +413,165 @@ static acpi_status acpi_ns_init_one_device(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { - struct acpi_device_walk_info *info = - (struct acpi_device_walk_info *)context; - struct acpi_parameter_info pinfo; + struct acpi_device_walk_info *walk_info = + ACPI_CAST_PTR(struct acpi_device_walk_info, context); + struct acpi_evaluate_info *info = walk_info->evaluate_info; u32 flags; acpi_status status; - struct acpi_namespace_node *ini_node; struct acpi_namespace_node *device_node; - ACPI_FUNCTION_TRACE("ns_init_one_device"); + ACPI_FUNCTION_TRACE(ns_init_one_device); - device_node = acpi_ns_map_handle_to_node(obj_handle); - if (!device_node) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } + /* We are interested in Devices, Processors and thermal_zones only */ - /* - * We will run _STA/_INI on Devices, Processors and thermal_zones only - */ + device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); if ((device_node->type != ACPI_TYPE_DEVICE) && (device_node->type != ACPI_TYPE_PROCESSOR) && (device_node->type != ACPI_TYPE_THERMAL)) { return_ACPI_STATUS(AE_OK); } - if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && - (!(acpi_dbg_level & ACPI_LV_INFO))) { - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); - } - - info->device_count++; - /* - * Check if the _INI method exists for this device - - * if _INI does not exist, there is no need to run _STA - * No _INI means device requires no initialization + * Because of an earlier namespace analysis, all subtrees that contain an + * _INI method are tagged. + * + * If this device subtree does not contain any _INI methods, we + * can exit now and stop traversing this entire subtree. */ - status = acpi_ns_search_node(*ACPI_CAST_PTR(u32, METHOD_NAME__INI), - device_node, ACPI_TYPE_METHOD, &ini_node); - if (ACPI_FAILURE(status)) { - /* No _INI method found - move on to next device */ - - return_ACPI_STATUS(AE_OK); + if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) { + return_ACPI_STATUS(AE_CTRL_DEPTH); } /* - * Run _STA to determine if we can run _INI on the device - - * the device must be present before _INI can be run. - * However, _STA is not required - assume device present if no _STA + * Run _STA to determine if this device is present and functioning. We + * must know this information for two important reasons (from ACPI spec): + * + * 1) We can only run _INI if the device is present. + * 2) We must abort the device tree walk on this subtree if the device is + * not present and is not functional (we will not examine the children) + * + * The _STA method is not required to be present under the device, we + * assume the device is present if _STA does not exist. */ - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD, - device_node, - METHOD_NAME__STA)); - - pinfo.node = device_node; - pinfo.parameters = NULL; - pinfo.parameter_type = ACPI_PARAM_ARGS; + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA)); - status = acpi_ut_execute_STA(pinfo.node, &flags); + status = acpi_ut_execute_STA(device_node, &flags); if (ACPI_FAILURE(status)) { + /* Ignore error and move on to next device */ return_ACPI_STATUS(AE_OK); } + /* + * Flags == -1 means that _STA was not found. In this case, we assume that + * the device is both present and functional. + * + * From the ACPI spec, description of _STA: + * + * "If a device object (including the processor object) does not have an + * _STA object, then OSPM assumes that all of the above bits are set (in + * other words, the device is present, ..., and functioning)" + */ if (flags != ACPI_UINT32_MAX) { - info->num_STA++; + walk_info->num_STA++; } + /* + * Examine the PRESENT and FUNCTIONING status bits + * + * Note: ACPI spec does not seem to specify behavior for the present but + * not functioning case, so we assume functioning if present. + */ if (!(flags & ACPI_STA_DEVICE_PRESENT)) { - /* Don't look at children of a not present device */ - return_ACPI_STATUS(AE_CTRL_DEPTH); + /* Device is not present, we must examine the Functioning bit */ + + if (flags & ACPI_STA_DEVICE_FUNCTIONING) { + /* + * Device is not present but is "functioning". In this case, + * we will not run _INI, but we continue to examine the children + * of this device. + * + * From the ACPI spec, description of _STA: (Note - no mention + * of whether to run _INI or not on the device in question) + * + * "_STA may return bit 0 clear (not present) with bit 3 set + * (device is functional). This case is used to indicate a valid + * device for which no device driver should be loaded (for example, + * a bridge device.) Children of this device may be present and + * valid. OSPM should continue enumeration below a device whose + * _STA returns this bit combination" + */ + return_ACPI_STATUS(AE_OK); + } else { + /* + * Device is not present and is not functioning. We must abort the + * walk of this subtree immediately -- don't look at the children + * of such a device. + * + * From the ACPI spec, description of _INI: + * + * "If the _STA method indicates that the device is not present, + * OSPM will not run the _INI and will not examine the children + * of the device for _INI methods" + */ + return_ACPI_STATUS(AE_CTRL_DEPTH); + } } /* - * The device is present and _INI exists. Run the _INI method. - * (We already have the _INI node from above) + * The device is present or is assumed present if no _STA exists. + * Run the _INI if it exists (not required to exist) + * + * Note: We know there is an _INI within this subtree, but it may not be + * under this particular device, it may be lower in the branch. */ - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD, - pinfo.node, - METHOD_NAME__INI)); + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname + (ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI)); + + info->prefix_node = device_node; + info->pathname = METHOD_NAME__INI; + info->parameters = NULL; + info->parameter_type = ACPI_PARAM_ARGS; + info->flags = ACPI_IGNORE_RETURN_VALUE; + + status = acpi_ns_evaluate(info); + if (ACPI_SUCCESS(status)) { + walk_info->num_INI++; + + if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) && + (!(acpi_dbg_level & ACPI_LV_INFO))) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); + } + } +#ifdef ACPI_DEBUG_OUTPUT + else if (status != AE_NOT_FOUND) { - pinfo.node = ini_node; - status = acpi_ns_evaluate_by_handle(&pinfo); - if (ACPI_FAILURE(status)) { /* Ignore error and move on to next device */ -#ifdef ACPI_DEBUG_OUTPUT - char *scope_name = acpi_ns_get_external_pathname(ini_node); - - ACPI_WARNING((AE_INFO, "%s._INI failed: %s", - scope_name, acpi_format_exception(status))); + char *scope_name = + acpi_ns_get_external_pathname(info->resolved_node); - ACPI_MEM_FREE(scope_name); + ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution", + scope_name)); + ACPI_FREE(scope_name); + } #endif - } else { - /* Delete any return object (especially if implicit_return is enabled) */ - if (pinfo.return_object) { - acpi_ut_remove_reference(pinfo.return_object); - } + /* Ignore errors from above */ - /* Count of successful INIs */ - - info->num_INI++; - } + status = AE_OK; + /* + * The _INI method has been run if present; call the Global Initialization + * Handler for this device. + */ if (acpi_gbl_init_handler) { - /* External initialization handler is present, call it */ - status = - acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI); + acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI); } - return_ACPI_STATUS(AE_OK); + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index 4e0b052..fe75d88 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c @@ -77,13 +77,14 @@ acpi_ns_load_table(struct acpi_table_des { acpi_status status; - ACPI_FUNCTION_TRACE("ns_load_table"); + ACPI_FUNCTION_TRACE(ns_load_table); /* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */ if (! (acpi_gbl_table_data[table_desc->type]. flags & ACPI_TABLE_EXECUTABLE)) { + /* Just ignore this table */ return_ACPI_STATUS(AE_OK); @@ -168,7 +169,7 @@ static acpi_status acpi_ns_load_table_by acpi_status status; struct acpi_table_desc *table_desc; - ACPI_FUNCTION_TRACE("ns_load_table_by_type"); + ACPI_FUNCTION_TRACE(ns_load_table_by_type); status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); if (ACPI_FAILURE(status)) { @@ -180,11 +181,11 @@ static acpi_status acpi_ns_load_table_by * DSDT (one), SSDT/PSDT (multiple) */ switch (table_type) { - case ACPI_TABLE_DSDT: + case ACPI_TABLE_ID_DSDT: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace load: DSDT\n")); - table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next; + table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_DSDT].next; /* If table already loaded into namespace, just return */ @@ -200,8 +201,8 @@ static acpi_status acpi_ns_load_table_by } break; - case ACPI_TABLE_SSDT: - case ACPI_TABLE_PSDT: + case ACPI_TABLE_ID_SSDT: + case ACPI_TABLE_ID_PSDT: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace load: %d SSDT or PSDTs\n", @@ -258,7 +259,7 @@ acpi_status acpi_ns_load_namespace(void) { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_load_name_space"); + ACPI_FUNCTION_TRACE(acpi_load_name_space); /* There must be at least a DSDT installed */ @@ -271,15 +272,15 @@ acpi_status acpi_ns_load_namespace(void) * Load the namespace. The DSDT is required, * but the SSDT and PSDT tables are optional. */ - status = acpi_ns_load_table_by_type(ACPI_TABLE_DSDT); + status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Ignore exceptions from these */ - (void)acpi_ns_load_table_by_type(ACPI_TABLE_SSDT); - (void)acpi_ns_load_table_by_type(ACPI_TABLE_PSDT); + (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT); + (void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT); ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "ACPI Namespace successfully loaded at root %p\n", @@ -314,7 +315,7 @@ static acpi_status acpi_ns_delete_subtre acpi_handle dummy; u32 level; - ACPI_FUNCTION_TRACE("ns_delete_subtree"); + ACPI_FUNCTION_TRACE(ns_delete_subtree); parent_handle = start_handle; child_handle = NULL; @@ -325,6 +326,7 @@ static acpi_status acpi_ns_delete_subtre * to where we started. */ while (level > 0) { + /* Attempt to get the next object in this scope */ status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, @@ -335,6 +337,7 @@ static acpi_status acpi_ns_delete_subtre /* Did we get a new object? */ if (ACPI_SUCCESS(status)) { + /* Check if this object has any children */ if (ACPI_SUCCESS @@ -392,7 +395,7 @@ acpi_status acpi_ns_unload_namespace(acp { acpi_status status; - ACPI_FUNCTION_TRACE("ns_unload_name_space"); + ACPI_FUNCTION_TRACE(ns_unload_name_space); /* Parameter validation */ diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index 639f653..97b8332 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c @@ -48,11 +48,6 @@ #include #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsnames") -/* Local prototypes */ -static void -acpi_ns_build_external_path(struct acpi_namespace_node *node, - acpi_size size, char *name_buffer); - /******************************************************************************* * * FUNCTION: acpi_ns_build_external_path @@ -67,8 +62,7 @@ acpi_ns_build_external_path(struct acpi_ * DESCRIPTION: Generate a full pathaname * ******************************************************************************/ - -static void +void acpi_ns_build_external_path(struct acpi_namespace_node *node, acpi_size size, char *name_buffer) { @@ -138,7 +132,7 @@ char *acpi_ns_get_external_pathname(stru char *name_buffer; acpi_size size; - ACPI_FUNCTION_TRACE_PTR("ns_get_external_pathname", node); + ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node); /* Calculate required buffer size based on depth below root */ @@ -146,7 +140,7 @@ char *acpi_ns_get_external_pathname(stru /* Allocate a buffer to be returned to caller */ - name_buffer = ACPI_MEM_CALLOCATE(size); + name_buffer = ACPI_ALLOCATE_ZEROED(size); if (!name_buffer) { ACPI_ERROR((AE_INFO, "Allocation failure")); return_PTR(NULL); @@ -219,7 +213,7 @@ acpi_ns_handle_to_pathname(acpi_handle t struct acpi_namespace_node *node; acpi_size required_size; - ACPI_FUNCTION_TRACE_PTR("ns_handle_to_pathname", target_handle); + ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle); node = acpi_ns_map_handle_to_node(target_handle); if (!node) { diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c index 10ae629..aabe879 100644 --- a/drivers/acpi/namespace/nsobject.c +++ b/drivers/acpi/namespace/nsobject.c @@ -76,19 +76,21 @@ acpi_ns_attach_object(struct acpi_namesp union acpi_operand_object *last_obj_desc; acpi_object_type object_type = ACPI_TYPE_ANY; - ACPI_FUNCTION_TRACE("ns_attach_object"); + ACPI_FUNCTION_TRACE(ns_attach_object); /* * Parameter validation */ if (!node) { + /* Invalid handle */ - ACPI_ERROR((AE_INFO, "Null named_obj handle")); + ACPI_ERROR((AE_INFO, "Null NamedObj handle")); return_ACPI_STATUS(AE_BAD_PARAMETER); } if (!object && (ACPI_TYPE_ANY != type)) { + /* Null object */ ACPI_ERROR((AE_INFO, @@ -97,6 +99,7 @@ acpi_ns_attach_object(struct acpi_namesp } if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { + /* Not a name handle */ ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]", @@ -108,7 +111,7 @@ acpi_ns_attach_object(struct acpi_namesp if (node->object == object) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Obj %p already installed in name_obj %p\n", + "Obj %p already installed in NameObj %p\n", object, node)); return_ACPI_STATUS(AE_OK); @@ -201,7 +204,7 @@ void acpi_ns_detach_object(struct acpi_n { union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE("ns_detach_object"); + ACPI_FUNCTION_TRACE(ns_detach_object); obj_desc = node->object; @@ -252,7 +255,7 @@ union acpi_operand_object *acpi_ns_get_a acpi_namespace_node *node) { - ACPI_FUNCTION_TRACE_PTR("ns_get_attached_object", node); + ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node); if (!node) { ACPI_WARNING((AE_INFO, "Null Node ptr")); @@ -287,7 +290,7 @@ union acpi_operand_object *acpi_ns_get_s acpi_operand_object *obj_desc) { - ACPI_FUNCTION_TRACE_PTR("ns_get_secondary_object", obj_desc); + ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc); if ((!obj_desc) || (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) || diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c index 232be43..155505a 100644 --- a/drivers/acpi/namespace/nsparse.c +++ b/drivers/acpi/namespace/nsparse.c @@ -62,13 +62,13 @@ ACPI_MODULE_NAME("nsparse") * ******************************************************************************/ acpi_status -acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc * table_desc) +acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc) { union acpi_parse_object *parse_root; acpi_status status; struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE("ns_one_complete_parse"); + ACPI_FUNCTION_TRACE(ns_one_complete_parse); /* Create and init a Root Node */ @@ -124,7 +124,7 @@ acpi_ns_parse_table(struct acpi_table_de { acpi_status status; - ACPI_FUNCTION_TRACE("ns_parse_table"); + ACPI_FUNCTION_TRACE(ns_parse_table); /* * AML Parse, pass 1 diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index d64b789..500e2bb 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c @@ -56,16 +56,16 @@ acpi_ns_search_parent_tree(u32 target_na /******************************************************************************* * - * FUNCTION: acpi_ns_search_node + * FUNCTION: acpi_ns_search_one_scope * * PARAMETERS: target_name - Ascii ACPI name to search for - * Node - Starting node where search will begin + * parent_node - Starting node where search will begin * Type - Object type to match * return_node - Where the matched Named obj is returned * * RETURN: Status * - * DESCRIPTION: Search a single level of the namespace. Performs a + * DESCRIPTION: Search a single level of the namespace. Performs a * simple search of the specified level, and does not add * entries or search parents. * @@ -75,35 +75,40 @@ acpi_ns_search_parent_tree(u32 target_na * * All namespace searching is linear in this implementation, but * could be easily modified to support any improved search - * algorithm. However, the linear search was chosen for simplicity + * algorithm. However, the linear search was chosen for simplicity * and because the trees are small and the other interpreter * execution overhead is relatively high. * + * Note: CPU execution analysis has shown that the AML interpreter spends + * a very small percentage of its time searching the namespace. Therefore, + * the linear search seems to be sufficient, as there would seem to be + * little value in improving the search. + * ******************************************************************************/ acpi_status -acpi_ns_search_node(u32 target_name, - struct acpi_namespace_node *node, - acpi_object_type type, - struct acpi_namespace_node **return_node) +acpi_ns_search_one_scope(u32 target_name, + struct acpi_namespace_node *parent_node, + acpi_object_type type, + struct acpi_namespace_node **return_node) { - struct acpi_namespace_node *next_node; + struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE("ns_search_node"); + ACPI_FUNCTION_TRACE(ns_search_one_scope); #ifdef ACPI_DEBUG_OUTPUT if (ACPI_LV_NAMES & acpi_dbg_level) { char *scope_name; - scope_name = acpi_ns_get_external_pathname(node); + scope_name = acpi_ns_get_external_pathname(parent_node); if (scope_name) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Searching %s (%p) For [%4.4s] (%s)\n", - scope_name, node, ACPI_CAST_PTR(char, - &target_name), + scope_name, parent_node, + ACPI_CAST_PTR(char, &target_name), acpi_ut_get_type_name(type))); - ACPI_MEM_FREE(scope_name); + ACPI_FREE(scope_name); } } #endif @@ -112,32 +117,33 @@ #endif * Search for name at this namespace level, which is to say that we * must search for the name among the children of this object */ - next_node = node->child; - while (next_node) { + node = parent_node->child; + while (node) { + /* Check for match against the name */ - if (next_node->name.integer == target_name) { + if (node->name.integer == target_name) { + /* Resolve a control method alias if any */ - if (acpi_ns_get_type(next_node) == + if (acpi_ns_get_type(node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { - next_node = + node = ACPI_CAST_PTR(struct acpi_namespace_node, - next_node->object); + node->object); } - /* - * Found matching entry. - */ + /* Found matching entry */ + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n", ACPI_CAST_PTR(char, &target_name), - acpi_ut_get_type_name(next_node-> - type), - next_node, - acpi_ut_get_node_name(node), node)); + acpi_ut_get_type_name(node->type), + node, + acpi_ut_get_node_name(parent_node), + parent_node)); - *return_node = next_node; + *return_node = node; return_ACPI_STATUS(AE_OK); } @@ -145,7 +151,8 @@ #endif * The last entry in the list points back to the parent, * so a flag is used to indicate the end-of-list */ - if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + if (node->flags & ANOBJ_END_OF_PEER_LIST) { + /* Searched entire list, we are done */ break; @@ -153,7 +160,7 @@ #endif /* Didn't match name, move on to the next peer object */ - next_node = next_node->peer; + node = node->peer; } /* Searched entire namespace level, not found */ @@ -162,7 +169,8 @@ #endif "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n", ACPI_CAST_PTR(char, &target_name), acpi_ut_get_type_name(type), - acpi_ut_get_node_name(node), node, node->child)); + acpi_ut_get_node_name(parent_node), parent_node, + parent_node->child)); return_ACPI_STATUS(AE_NOT_FOUND); } @@ -179,14 +187,14 @@ #endif * RETURN: Status * * DESCRIPTION: Called when a name has not been found in the current namespace - * level. Before adding it or giving up, ACPI scope rules require + * level. Before adding it or giving up, ACPI scope rules require * searching enclosing scopes in cases identified by acpi_ns_local(). * * "A name is located by finding the matching name in the current * name space, and then in the parent name space. If the parent * name space does not contain the name, the search continues * recursively until either the name is found or the name space - * does not have a parent (the root of the name space). This + * does not have a parent (the root of the name space). This * indicates that the name is not found" (From ACPI Specification, * section 5.3) * @@ -201,7 +209,7 @@ acpi_ns_search_parent_tree(u32 target_na acpi_status status; struct acpi_namespace_node *parent_node; - ACPI_FUNCTION_TRACE("ns_search_parent_tree"); + ACPI_FUNCTION_TRACE(ns_search_parent_tree); parent_node = acpi_ns_get_parent_node(node); @@ -235,20 +243,19 @@ acpi_ns_search_parent_tree(u32 target_na */ while (parent_node) { /* - * Search parent scope. Use TYPE_ANY because we don't care about the + * Search parent scope. Use TYPE_ANY because we don't care about the * object type at this point, we only care about the existence of - * the actual name we are searching for. Typechecking comes later. + * the actual name we are searching for. Typechecking comes later. */ - status = acpi_ns_search_node(target_name, parent_node, + status = + acpi_ns_search_one_scope(target_name, parent_node, ACPI_TYPE_ANY, return_node); if (ACPI_SUCCESS(status)) { return_ACPI_STATUS(status); } - /* - * Not found here, go up another level - * (until we reach the root) - */ + /* Not found here, go up another level (until we reach the root) */ + parent_node = acpi_ns_get_parent_node(parent_node); } @@ -273,7 +280,7 @@ acpi_ns_search_parent_tree(u32 target_na * RETURN: Status * * DESCRIPTION: Search for a name segment in a single namespace level, - * optionally adding it if it is not found. If the passed + * optionally adding it if it is not found. If the passed * Type is not Any and the type previously stored in the * entry was Any (i.e. unknown), update the stored type. * @@ -293,29 +300,46 @@ acpi_ns_search_and_enter(u32 target_name acpi_status status; struct acpi_namespace_node *new_node; - ACPI_FUNCTION_TRACE("ns_search_and_enter"); + ACPI_FUNCTION_TRACE(ns_search_and_enter); /* Parameter validation */ if (!node || !target_name || !return_node) { ACPI_ERROR((AE_INFO, - "Null param: Node %p Name %X return_node %p", + "Null parameter: Node %p Name %X ReturnNode %p", node, target_name, return_node)); return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Name must consist of printable characters */ - + /* + * Name must consist of valid ACPI characters. We will repair the name if + * necessary because we don't want to abort because of this, but we want + * all namespace names to be printable. A warning message is appropriate. + * + * This issue came up because there are in fact machines that exhibit + * this problem, and we want to be able to enable ACPI support for them, + * even though there are a few bad names. + */ if (!acpi_ut_valid_acpi_name(target_name)) { - ACPI_ERROR((AE_INFO, "Bad character in ACPI Name: %X", - target_name)); - return_ACPI_STATUS(AE_BAD_CHARACTER); + target_name = acpi_ut_repair_name(target_name); + + /* Report warning only if in strict mode or debug mode */ + + if (!acpi_gbl_enable_interpreter_slack) { + ACPI_WARNING((AE_INFO, + "Found bad character(s) in name, repaired: [%4.4s]\n", + ACPI_CAST_PTR(char, &target_name))); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "Found bad character(s) in name, repaired: [%4.4s]\n", + ACPI_CAST_PTR(char, &target_name))); + } } /* Try to find the name in the namespace level specified by the caller */ *return_node = ACPI_ENTRY_NOT_FOUND; - status = acpi_ns_search_node(target_name, node, type, return_node); + status = acpi_ns_search_one_scope(target_name, node, type, return_node); if (status != AE_NOT_FOUND) { /* * If we found it AND the request specifies that a find is an error, @@ -325,18 +349,16 @@ acpi_ns_search_and_enter(u32 target_name status = AE_ALREADY_EXISTS; } - /* - * Either found it or there was an error - * -- finished either way - */ + /* Either found it or there was an error: finished either way */ + return_ACPI_STATUS(status); } /* - * The name was not found. If we are NOT performing the first pass + * The name was not found. If we are NOT performing the first pass * (name entry) of loading the namespace, search the parent tree (all the * way to the root if necessary.) We don't want to perform the parent - * search when the namespace is actually being loaded. We want to perform + * search when the namespace is actually being loaded. We want to perform * the search when namespace references are being resolved (load pass 2) * and during the execution phase. */ @@ -354,9 +376,8 @@ acpi_ns_search_and_enter(u32 target_name } } - /* - * In execute mode, just search, never add names. Exit now. - */ + /* In execute mode, just search, never add names. Exit now */ + if (interpreter_mode == ACPI_IMODE_EXECUTE) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%4.4s Not found in %p [Not adding]\n", @@ -371,11 +392,18 @@ acpi_ns_search_and_enter(u32 target_name if (!new_node) { return_ACPI_STATUS(AE_NO_MEMORY); } +#ifdef ACPI_ASL_COMPILER + /* + * Node is an object defined by an External() statement + */ + if (flags & ACPI_NS_EXTERNAL) { + new_node->flags |= ANOBJ_IS_EXTERNAL; + } +#endif /* Install the new object into the parent's list of children */ acpi_ns_install_node(walk_state, node, new_node, type); *return_node = new_node; - return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index 3e7cad5..aa4e799 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c @@ -78,15 +78,17 @@ acpi_ns_report_error(char *module_name, char *internal_name, acpi_status lookup_status) { acpi_status status; + u32 bad_name; char *name = NULL; - acpi_ut_report_error(module_name, line_number); + acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); if (lookup_status == AE_BAD_CHARACTER) { + /* There is a non-ascii character in the name */ - acpi_os_printf("[0x%4.4X] (NON-ASCII)", - *(ACPI_CAST_PTR(u32, internal_name))); + ACPI_MOVE_32_TO_32(&bad_name, internal_name); + acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); } else { /* Convert path to external format */ @@ -102,7 +104,7 @@ acpi_ns_report_error(char *module_name, } if (name) { - ACPI_MEM_FREE(name); + ACPI_FREE(name); } } @@ -137,11 +139,12 @@ acpi_ns_report_method_error(char *module acpi_status status; struct acpi_namespace_node *node = prefix_node; - acpi_ut_report_error(module_name, line_number); + acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); if (path) { - status = acpi_ns_get_node_by_path(path, prefix_node, - ACPI_NS_NO_UPSEARCH, &node); + status = + acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH, + &node); if (ACPI_FAILURE(status)) { acpi_os_printf("[Could not get node by pathname]"); } @@ -185,7 +188,7 @@ acpi_ns_print_node_pathname(struct acpi_ } acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node); - ACPI_MEM_FREE(buffer.pointer); + ACPI_FREE(buffer.pointer); } } @@ -239,7 +242,7 @@ static u8 acpi_ns_valid_path_separator(c acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node) { - ACPI_FUNCTION_TRACE("ns_get_type"); + ACPI_FUNCTION_TRACE(ns_get_type); if (!node) { ACPI_WARNING((AE_INFO, "Null Node parameter")); @@ -264,9 +267,10 @@ acpi_object_type acpi_ns_get_type(struct u32 acpi_ns_local(acpi_object_type type) { - ACPI_FUNCTION_TRACE("ns_local"); + ACPI_FUNCTION_TRACE(ns_local); if (!acpi_ut_valid_object_type(type)) { + /* Type code out of range */ ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); @@ -363,7 +367,7 @@ acpi_status acpi_ns_build_internal_name( char *result = NULL; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ns_build_internal_name"); + ACPI_FUNCTION_TRACE(ns_build_internal_name); /* Setup the correct prefixes, counts, and pointers */ @@ -411,6 +415,7 @@ acpi_status acpi_ns_build_internal_name( for (i = 0; i < ACPI_NAME_SIZE; i++) { if (acpi_ns_valid_path_separator(*external_name) || (*external_name == 0)) { + /* Pad the segment with underscore(s) if segment is short */ result[i] = '_'; @@ -473,7 +478,7 @@ acpi_status acpi_ns_internalize_name(cha struct acpi_namestring_info info; acpi_status status; - ACPI_FUNCTION_TRACE("ns_internalize_name"); + ACPI_FUNCTION_TRACE(ns_internalize_name); if ((!external_name) || (*external_name == 0) || (!converted_name)) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -486,7 +491,7 @@ acpi_status acpi_ns_internalize_name(cha /* We need a segment to store the internal name */ - internal_name = ACPI_MEM_CALLOCATE(info.length); + internal_name = ACPI_ALLOCATE_ZEROED(info.length); if (!internal_name) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -496,7 +501,7 @@ acpi_status acpi_ns_internalize_name(cha info.internal_name = internal_name; status = acpi_ns_build_internal_name(&info); if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(internal_name); + ACPI_FREE(internal_name); return_ACPI_STATUS(status); } @@ -533,7 +538,7 @@ acpi_ns_externalize_name(u32 internal_na acpi_native_uint i = 0; acpi_native_uint j = 0; - ACPI_FUNCTION_TRACE("ns_externalize_name"); + ACPI_FUNCTION_TRACE(ns_externalize_name); if (!internal_name_length || !internal_name || !converted_name) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -628,7 +633,7 @@ acpi_ns_externalize_name(u32 internal_na /* * Build converted_name */ - *converted_name = ACPI_MEM_CALLOCATE(required_length); + *converted_name = ACPI_ALLOCATE_ZEROED(required_length); if (!(*converted_name)) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -681,13 +686,9 @@ struct acpi_namespace_node *acpi_ns_map_ ACPI_FUNCTION_ENTRY(); /* - * Simple implementation. + * Simple implementation */ - if (!handle) { - return (NULL); - } - - if (handle == ACPI_ROOT_OBJECT) { + if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { return (acpi_gbl_root_node); } @@ -697,7 +698,7 @@ struct acpi_namespace_node *acpi_ns_map_ return (NULL); } - return ((struct acpi_namespace_node *)handle); + return (ACPI_CAST_PTR(struct acpi_namespace_node, handle)); } /******************************************************************************* @@ -752,7 +753,7 @@ void acpi_ns_terminate(void) { union acpi_operand_object *obj_desc; - ACPI_FUNCTION_TRACE("ns_terminate"); + ACPI_FUNCTION_TRACE(ns_terminate); /* * 1) Free the entire namespace -- all nodes and objects @@ -792,9 +793,10 @@ void acpi_ns_terminate(void) u32 acpi_ns_opens_scope(acpi_object_type type) { - ACPI_FUNCTION_TRACE_STR("ns_opens_scope", acpi_ut_get_type_name(type)); + ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); if (!acpi_ut_valid_object_type(type)) { + /* type code out of range */ ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type)); @@ -806,12 +808,12 @@ u32 acpi_ns_opens_scope(acpi_object_type /******************************************************************************* * - * FUNCTION: acpi_ns_get_node_by_path + * FUNCTION: acpi_ns_get_node * * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The * \ (backslash) and ^ (carat) prefixes, and the * . (period) to separate segments are supported. - * start_node - Root of subtree to be searched, or NS_ALL for the + * prefix_node - Root of subtree to be searched, or NS_ALL for the * root of the name space. If Name is fully * qualified (first s8 is '\'), the passed value * of Scope will not be accessed. @@ -827,23 +829,29 @@ u32 acpi_ns_opens_scope(acpi_object_type ******************************************************************************/ acpi_status -acpi_ns_get_node_by_path(char *pathname, - struct acpi_namespace_node *start_node, - u32 flags, struct acpi_namespace_node **return_node) +acpi_ns_get_node(struct acpi_namespace_node *prefix_node, + char *pathname, + u32 flags, struct acpi_namespace_node **return_node) { union acpi_generic_state scope_info; acpi_status status; - char *internal_path = NULL; - - ACPI_FUNCTION_TRACE_PTR("ns_get_node_by_path", pathname); + char *internal_path; - if (pathname) { - /* Convert path to internal representation */ + ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname); - status = acpi_ns_internalize_name(pathname, &internal_path); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + if (!pathname) { + *return_node = prefix_node; + if (!prefix_node) { + *return_node = acpi_gbl_root_node; } + return_ACPI_STATUS(AE_OK); + } + + /* Convert path to internal representation */ + + status = acpi_ns_internalize_name(pathname, &internal_path); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } /* Must lock namespace during lookup */ @@ -855,26 +863,23 @@ acpi_ns_get_node_by_path(char *pathname, /* Setup lookup scope (search starting point) */ - scope_info.scope.node = start_node; + scope_info.scope.node = prefix_node; /* Lookup the name in the namespace */ - status = acpi_ns_lookup(&scope_info, internal_path, - ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, - (flags | ACPI_NS_DONT_OPEN_SCOPE), - NULL, return_node); + status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, + (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, + return_node); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n", - internal_path, - acpi_format_exception(status))); + pathname, acpi_format_exception(status))); } (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); cleanup: - if (internal_path) { - ACPI_MEM_FREE(internal_path); - } + ACPI_FREE(internal_path); return_ACPI_STATUS(status); } @@ -960,9 +965,10 @@ acpi_name acpi_ns_find_parent_name(struc { struct acpi_namespace_node *parent_node; - ACPI_FUNCTION_TRACE("ns_find_parent_name"); + ACPI_FUNCTION_TRACE(ns_find_parent_name); if (child_node) { + /* Valid entry. Get the parent Node */ parent_node = acpi_ns_get_parent_node(child_node); diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c index fcab1e7..c8f6bef 100644 --- a/drivers/acpi/namespace/nswalk.c +++ b/drivers/acpi/namespace/nswalk.c @@ -76,6 +76,7 @@ struct acpi_namespace_node *acpi_ns_get_ ACPI_FUNCTION_ENTRY(); if (!child_node) { + /* It's really the parent's _scope_ that we want */ if (parent_node->child) { @@ -92,6 +93,7 @@ struct acpi_namespace_node *acpi_ns_get_ /* If any type is OK, we are done */ if (type == ACPI_TYPE_ANY) { + /* next_node is NULL if we are at the end-of-list */ return (next_node); @@ -100,6 +102,7 @@ struct acpi_namespace_node *acpi_ns_get_ /* Must search for the node -- but within this scope only */ while (next_node) { + /* If type matches, we are done */ if (next_node->type == type) { @@ -161,7 +164,7 @@ acpi_ns_walk_namespace(acpi_object_type acpi_object_type child_type; u32 level; - ACPI_FUNCTION_TRACE("ns_walk_namespace"); + ACPI_FUNCTION_TRACE(ns_walk_namespace); /* Special case for the namespace Root Node */ @@ -182,6 +185,7 @@ acpi_ns_walk_namespace(acpi_object_type * bubbled up to (and passed) the original parent handle (start_entry) */ while (level > 0) { + /* Get the next node in this scope. Null if not found */ status = AE_OK; diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index a95f636..6d9bd45 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c @@ -42,8 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -51,6 +49,7 @@ #include #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsxfeval") +#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * * FUNCTION: acpi_evaluate_object_typed @@ -71,18 +70,17 @@ ACPI_MODULE_NAME("nsxfeval") * be valid (non-null) * ******************************************************************************/ -#ifdef ACPI_FUTURE_USAGE acpi_status acpi_evaluate_object_typed(acpi_handle handle, acpi_string pathname, - struct acpi_object_list *external_params, - struct acpi_buffer *return_buffer, + struct acpi_object_list * external_params, + struct acpi_buffer * return_buffer, acpi_object_type return_type) { acpi_status status; u8 must_free = FALSE; - ACPI_FUNCTION_TRACE("acpi_evaluate_object_typed"); + ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed); /* Return buffer must be valid */ @@ -110,6 +108,7 @@ acpi_evaluate_object_typed(acpi_handle h } if (return_buffer->length == 0) { + /* Error because caller specifically asked for a return value */ ACPI_ERROR((AE_INFO, "No return value")); @@ -131,6 +130,7 @@ acpi_evaluate_object_typed(acpi_handle h acpi_ut_get_type_name(return_type))); if (must_free) { + /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ acpi_os_free(return_buffer->pointer); @@ -140,6 +140,8 @@ acpi_evaluate_object_typed(acpi_handle h return_buffer->length = 0; return_ACPI_STATUS(AE_TYPE); } + +ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed) #endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -161,7 +163,6 @@ #endif /* ACPI_FUTURE_USAGE */ * be valid (non-null) * ******************************************************************************/ - acpi_status acpi_evaluate_object(acpi_handle handle, acpi_string pathname, @@ -170,51 +171,61 @@ acpi_evaluate_object(acpi_handle handle, { acpi_status status; acpi_status status2; - struct acpi_parameter_info info; + struct acpi_evaluate_info *info; acpi_size buffer_space_needed; u32 i; - ACPI_FUNCTION_TRACE("acpi_evaluate_object"); + ACPI_FUNCTION_TRACE(acpi_evaluate_object); - info.node = handle; - info.parameters = NULL; - info.return_object = NULL; - info.parameter_type = ACPI_PARAM_ARGS; + /* Allocate and initialize the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->pathname = pathname; + info->parameter_type = ACPI_PARAM_ARGS; + + /* Convert and validate the device handle */ + + info->prefix_node = acpi_ns_map_handle_to_node(handle); + if (!info->prefix_node) { + status = AE_BAD_PARAMETER; + goto cleanup; + } /* - * If there are parameters to be passed to the object - * (which must be a control method), the external objects - * must be converted to internal objects + * If there are parameters to be passed to a control method, the external + * objects must all be converted to internal objects */ if (external_params && external_params->count) { /* * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ - info.parameters = ACPI_MEM_CALLOCATE(((acpi_size) - external_params->count + - 1) * sizeof(void *)); - if (!info.parameters) { - return_ACPI_STATUS(AE_NO_MEMORY); + info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) + external_params-> + count + + 1) * sizeof(void *)); + if (!info->parameters) { + status = AE_NO_MEMORY; + goto cleanup; } - /* - * Convert each external object in the list to an - * internal object - */ + /* Convert each external object in the list to an internal object */ + for (i = 0; i < external_params->count; i++) { status = acpi_ut_copy_eobject_to_iobject(&external_params-> pointer[i], - &info. + &info-> parameters[i]); if (ACPI_FAILURE(status)) { - acpi_ut_delete_internal_object_list(info. - parameters); - return_ACPI_STATUS(status); + goto cleanup; } } - info.parameters[external_params->count] = NULL; + info->parameters[external_params->count] = NULL; } /* @@ -224,43 +235,31 @@ acpi_evaluate_object(acpi_handle handle, * 3) Valid handle */ if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { - /* - * The path is fully qualified, just evaluate by name - */ - status = acpi_ns_evaluate_by_name(pathname, &info); + + /* The path is fully qualified, just evaluate by name */ + + info->prefix_node = NULL; + status = acpi_ns_evaluate(info); } else if (!handle) { /* - * A handle is optional iff a fully qualified pathname - * is specified. Since we've already handled fully - * qualified names above, this is an error + * A handle is optional iff a fully qualified pathname is specified. + * Since we've already handled fully qualified names above, this is + * an error */ if (!pathname) { - ACPI_ERROR((AE_INFO, - "Both Handle and Pathname are NULL")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Both Handle and Pathname are NULL")); } else { - ACPI_ERROR((AE_INFO, - "Handle is NULL and Pathname is relative")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Null Handle with relative pathname [%s]", + pathname)); } status = AE_BAD_PARAMETER; } else { - /* - * We get here if we have a handle -- and if we have a - * pathname it is relative. The handle will be validated - * in the lower procedures - */ - if (!pathname) { - /* - * The null pathname case means the handle is for - * the actual object to be evaluated - */ - status = acpi_ns_evaluate_by_handle(&info); - } else { - /* - * Both a Handle and a relative Pathname - */ - status = acpi_ns_evaluate_relative(pathname, &info); - } + /* We have a namespace a node and a possible relative path */ + + status = acpi_ns_evaluate(info); } /* @@ -268,10 +267,10 @@ acpi_evaluate_object(acpi_handle handle, * copy the return value to an external object. */ if (return_buffer) { - if (!info.return_object) { + if (!info->return_object) { return_buffer->length = 0; } else { - if (ACPI_GET_DESCRIPTOR_TYPE(info.return_object) == + if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) == ACPI_DESC_TYPE_NAMED) { /* * If we received a NS Node as a return object, this means that @@ -282,19 +281,19 @@ acpi_evaluate_object(acpi_handle handle, * support for various types at a later date if necessary. */ status = AE_TYPE; - info.return_object = NULL; /* No need to delete a NS Node */ + info->return_object = NULL; /* No need to delete a NS Node */ return_buffer->length = 0; } if (ACPI_SUCCESS(status)) { - /* - * Find out how large a buffer is needed - * to contain the returned object - */ + + /* Get the size of the returned object */ + status = - acpi_ut_get_object_size(info.return_object, + acpi_ut_get_object_size(info->return_object, &buffer_space_needed); if (ACPI_SUCCESS(status)) { + /* Validate/Allocate/Clear caller buffer */ status = @@ -303,7 +302,8 @@ acpi_evaluate_object(acpi_handle handle, buffer_space_needed); if (ACPI_FAILURE(status)) { /* - * Caller's buffer is too small or a new one can't be allocated + * Caller's buffer is too small or a new one can't + * be allocated */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Needed buffer size %X, %s\n", @@ -312,12 +312,11 @@ acpi_evaluate_object(acpi_handle handle, acpi_format_exception (status))); } else { - /* - * We have enough space for the object, build it - */ + /* We have enough space for the object, build it */ + status = acpi_ut_copy_iobject_to_eobject - (info.return_object, + (info->return_object, return_buffer); } } @@ -325,35 +324,37 @@ acpi_evaluate_object(acpi_handle handle, } } - if (info.return_object) { + if (info->return_object) { /* - * Delete the internal return object. NOTE: Interpreter - * must be locked to avoid race condition. + * Delete the internal return object. NOTE: Interpreter must be + * locked to avoid race condition. */ status2 = acpi_ex_enter_interpreter(); if (ACPI_SUCCESS(status2)) { - /* - * Delete the internal return object. (Or at least - * decrement the reference count by one) - */ - acpi_ut_remove_reference(info.return_object); + + /* Remove one reference on the return object (should delete it) */ + + acpi_ut_remove_reference(info->return_object); acpi_ex_exit_interpreter(); } } - /* - * Free the input parameter list (if we created one), - */ - if (info.parameters) { + cleanup: + + /* Free the input parameter list (if we created one) */ + + if (info->parameters) { + /* Free the allocated parameter block */ - acpi_ut_delete_internal_object_list(info.parameters); + acpi_ut_delete_internal_object_list(info->parameters); } + ACPI_FREE(info); return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_evaluate_object); +ACPI_EXPORT_SYMBOL(acpi_evaluate_object) /******************************************************************************* * @@ -384,7 +385,6 @@ EXPORT_SYMBOL(acpi_evaluate_object); * function, etc. * ******************************************************************************/ - acpi_status acpi_walk_namespace(acpi_object_type type, acpi_handle start_object, @@ -394,7 +394,7 @@ acpi_walk_namespace(acpi_object_type typ { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_walk_namespace"); + ACPI_FUNCTION_TRACE(acpi_walk_namespace); /* Parameter validation */ @@ -421,7 +421,7 @@ acpi_walk_namespace(acpi_object_type typ return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_walk_namespace); +ACPI_EXPORT_SYMBOL(acpi_walk_namespace) /******************************************************************************* * @@ -436,7 +436,6 @@ EXPORT_SYMBOL(acpi_walk_namespace); * on that. * ******************************************************************************/ - static acpi_status acpi_ns_get_device_callback(acpi_handle obj_handle, u32 nesting_level, @@ -473,6 +472,7 @@ acpi_ns_get_device_callback(acpi_handle } if (!(flags & ACPI_STA_DEVICE_PRESENT)) { + /* Don't examine children of the device if not present */ return (AE_CTRL_DEPTH); @@ -489,6 +489,7 @@ acpi_ns_get_device_callback(acpi_handle } if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) { + /* Get the list of Compatible IDs */ status = acpi_ut_execute_CID(node, &cid); @@ -505,11 +506,11 @@ acpi_ns_get_device_callback(acpi_handle sizeof(struct acpi_compatible_id)) != 0) { - ACPI_MEM_FREE(cid); + ACPI_FREE(cid); return (AE_OK); } } - ACPI_MEM_FREE(cid); + ACPI_FREE(cid); } } @@ -551,7 +552,7 @@ acpi_get_devices(char *HID, acpi_status status; struct acpi_get_devices_info info; - ACPI_FUNCTION_TRACE("acpi_get_devices"); + ACPI_FUNCTION_TRACE(acpi_get_devices); /* Parameter validation */ @@ -563,9 +564,9 @@ acpi_get_devices(char *HID, * We're going to call their callback from OUR callback, so we need * to know what it is, and their context parameter. */ + info.hid = HID; info.context = context; info.user_function = user_function; - info.hid = HID; /* * Lock the namespace around the walk. @@ -578,9 +579,8 @@ acpi_get_devices(char *HID, return_ACPI_STATUS(status); } - status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, - ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - ACPI_NS_WALK_UNLOCK, + status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ns_get_device_callback, &info, return_value); @@ -588,7 +588,7 @@ acpi_get_devices(char *HID, return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_devices); +ACPI_EXPORT_SYMBOL(acpi_get_devices) /******************************************************************************* * @@ -603,7 +603,6 @@ EXPORT_SYMBOL(acpi_get_devices); * DESCRIPTION: Attach arbitrary data and handler to a namespace node. * ******************************************************************************/ - acpi_status acpi_attach_data(acpi_handle obj_handle, acpi_object_handler handler, void *data) @@ -637,6 +636,8 @@ acpi_attach_data(acpi_handle obj_handle, return (status); } +ACPI_EXPORT_SYMBOL(acpi_attach_data) + /******************************************************************************* * * FUNCTION: acpi_detach_data @@ -649,7 +650,6 @@ acpi_attach_data(acpi_handle obj_handle, * DESCRIPTION: Remove data that was previously attached to a node. * ******************************************************************************/ - acpi_status acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) { @@ -682,6 +682,8 @@ acpi_detach_data(acpi_handle obj_handle, return (status); } +ACPI_EXPORT_SYMBOL(acpi_detach_data) + /******************************************************************************* * * FUNCTION: acpi_get_data @@ -695,7 +697,6 @@ acpi_detach_data(acpi_handle obj_handle, * DESCRIPTION: Retrieve data that was previously attached to a namespace node. * ******************************************************************************/ - acpi_status acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) { @@ -727,3 +728,5 @@ acpi_get_data(acpi_handle obj_handle, ac (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (status); } + +ACPI_EXPORT_SYMBOL(acpi_get_data) diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index 8cd8675..978213a 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c @@ -42,8 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include @@ -114,9 +112,8 @@ acpi_get_handle(acpi_handle parent, /* * Find the Node and convert to a handle */ - status = - acpi_ns_get_node_by_path(pathname, prefix_node, ACPI_NS_NO_UPSEARCH, - &node); + status = acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, + &node); *ret_handle = NULL; if (ACPI_SUCCESS(status)) { @@ -126,7 +123,7 @@ acpi_get_handle(acpi_handle parent, return (status); } -EXPORT_SYMBOL(acpi_get_handle); +ACPI_EXPORT_SYMBOL(acpi_get_handle) /****************************************************************************** * @@ -143,7 +140,6 @@ EXPORT_SYMBOL(acpi_get_handle); * complementary functions. * ******************************************************************************/ - acpi_status acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) { @@ -162,6 +158,7 @@ acpi_get_name(acpi_handle handle, u32 na } if (name_type == ACPI_FULL_PATHNAME) { + /* Get the full pathname (From the namespace root) */ status = acpi_ns_handle_to_pathname(handle, buffer); @@ -203,7 +200,7 @@ acpi_get_name(acpi_handle handle, u32 na return (status); } -EXPORT_SYMBOL(acpi_get_name); +ACPI_EXPORT_SYMBOL(acpi_get_name) /****************************************************************************** * @@ -219,7 +216,6 @@ EXPORT_SYMBOL(acpi_get_name); * control methods (Such as in the case of a device.) * ******************************************************************************/ - acpi_status acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) { @@ -241,7 +237,7 @@ acpi_get_object_info(acpi_handle handle, return (status); } - info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_device_info)); + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info)); if (!info) { return (AE_NO_MEMORY); } @@ -345,11 +341,11 @@ acpi_get_object_info(acpi_handle handle, } cleanup: - ACPI_MEM_FREE(info); + ACPI_FREE(info); if (cid_list) { - ACPI_MEM_FREE(cid_list); + ACPI_FREE(cid_list); } return (status); } -EXPORT_SYMBOL(acpi_get_object_info); +ACPI_EXPORT_SYMBOL(acpi_get_object_info) diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c index a033259..a163e1d 100644 --- a/drivers/acpi/namespace/nsxfobj.c +++ b/drivers/acpi/namespace/nsxfobj.c @@ -42,8 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include @@ -101,7 +99,7 @@ acpi_status acpi_get_type(acpi_handle ha return (status); } -EXPORT_SYMBOL(acpi_get_type); +ACPI_EXPORT_SYMBOL(acpi_get_type) /******************************************************************************* * @@ -116,7 +114,6 @@ EXPORT_SYMBOL(acpi_get_type); * Handle. * ******************************************************************************/ - acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle) { struct acpi_namespace_node *node; @@ -162,7 +159,7 @@ acpi_status acpi_get_parent(acpi_handle return (status); } -EXPORT_SYMBOL(acpi_get_parent); +ACPI_EXPORT_SYMBOL(acpi_get_parent) /******************************************************************************* * @@ -181,7 +178,6 @@ EXPORT_SYMBOL(acpi_get_parent); * Scope is returned. * ******************************************************************************/ - acpi_status acpi_get_next_object(acpi_object_type type, acpi_handle parent, @@ -206,6 +202,7 @@ acpi_get_next_object(acpi_object_type ty /* If null handle, use the parent */ if (!child) { + /* Start search at the beginning of the specified scope */ parent_node = acpi_ns_map_handle_to_node(parent); @@ -242,4 +239,4 @@ acpi_get_next_object(acpi_object_type ty return (status); } -EXPORT_SYMBOL(acpi_get_next_object); +ACPI_EXPORT_SYMBOL(acpi_get_next_object) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 64b98e8..e2c1a16 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -36,12 +36,60 @@ #define ACPI_NUMA 0x80000000 #define _COMPONENT ACPI_NUMA ACPI_MODULE_NAME("numa") +static nodemask_t nodes_found_map = NODE_MASK_NONE; +#define PXM_INVAL -1 +#define NID_INVAL -1 + +/* maps to convert between proximity domain and logical node ID */ +int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS] + = { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL }; +int __cpuinitdata node_to_pxm_map[MAX_NUMNODES] + = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; + extern int __init acpi_table_parse_madt_family(enum acpi_table_id id, unsigned long madt_size, int entry_id, acpi_madt_entry_handler handler, unsigned int max_entries); +int __cpuinit pxm_to_node(int pxm) +{ + if (pxm < 0) + return NID_INVAL; + return pxm_to_node_map[pxm]; +} + +int __cpuinit node_to_pxm(int node) +{ + if (node < 0) + return PXM_INVAL; + return node_to_pxm_map[node]; +} + +int __cpuinit acpi_map_pxm_to_node(int pxm) +{ + int node = pxm_to_node_map[pxm]; + + if (node < 0){ + if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) + return NID_INVAL; + node = first_unset_node(nodes_found_map); + pxm_to_node_map[pxm] = node; + node_to_pxm_map[node] = pxm; + node_set(node, nodes_found_map); + } + + return node; +} + +void __cpuinit acpi_unmap_pxm_to_node(int node) +{ + int pxm = node_to_pxm_map[node]; + pxm_to_node_map[pxm] = NID_INVAL; + node_to_pxm_map[node] = PXM_INVAL; + node_clear(node, nodes_found_map); +} + void __init acpi_table_print_srat_entry(acpi_table_entry_header * header) { diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 13b5fd5..1bb558a 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -37,6 +37,7 @@ #include #include #include #include +#include #include #include #include @@ -600,23 +601,41 @@ static void acpi_os_execute_deferred(voi return_VOID; } -acpi_status -acpi_os_queue_for_execution(u32 priority, +static int acpi_os_execute_thread(void *context) +{ + struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context; + if (dpc) { + dpc->function(dpc->context); + kfree(dpc); + } + do_exit(0); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_execute + * + * PARAMETERS: Type - Type of the callback + * Function - Function to be executed + * Context - Function parameters + * + * RETURN: Status + * + * DESCRIPTION: Depending on type, either queues function for deferred execution or + * immediately executes function on a separate thread. + * + ******************************************************************************/ + +acpi_status acpi_os_execute(acpi_execute_type type, acpi_osd_exec_callback function, void *context) { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; struct work_struct *task; - - ACPI_FUNCTION_TRACE("os_queue_for_execution"); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Scheduling function [%p(%p)] for deferred execution.\n", - function, context)); + struct task_struct *p; if (!function) - return_ACPI_STATUS(AE_BAD_PARAMETER); - + return AE_BAD_PARAMETER; /* * Allocate/initialize DPC structure. Note that this memory will be * freed by the callee. The kernel handles the tq_struct list in a @@ -627,30 +646,37 @@ acpi_os_queue_for_execution(u32 priority * We can save time and code by allocating the DPC and tq_structs * from the same memory. */ - - dpc = - kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct), - GFP_ATOMIC); + if (type == OSL_NOTIFY_HANDLER) { + dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_KERNEL); + } else { + dpc = kmalloc(sizeof(struct acpi_os_dpc) + + sizeof(struct work_struct), GFP_ATOMIC); + } if (!dpc) - return_ACPI_STATUS(AE_NO_MEMORY); - + return AE_NO_MEMORY; dpc->function = function; dpc->context = context; - task = (void *)(dpc + 1); - INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); - - if (!queue_work(kacpid_wq, task)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Call to queue_work() failed.\n")); - kfree(dpc); - status = AE_ERROR; + if (type == OSL_NOTIFY_HANDLER) { + p = kthread_create(acpi_os_execute_thread, dpc, "kacpid_notify"); + if (!IS_ERR(p)) { + wake_up_process(p); + } else { + status = AE_NO_MEMORY; + kfree(dpc); + } + } else { + task = (void *)(dpc + 1); + INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); + if (!queue_work(kacpid_wq, task)) { + status = AE_ERROR; + kfree(dpc); + } } - - return_ACPI_STATUS(status); + return status; } -EXPORT_SYMBOL(acpi_os_queue_for_execution); +EXPORT_SYMBOL(acpi_os_execute); void acpi_os_wait_events_complete(void *context) { @@ -769,9 +795,6 @@ acpi_status acpi_os_wait_semaphore(acpi_ ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); - if (in_atomic()) - timeout = 0; - switch (timeout) { /* * No Wait: @@ -896,14 +919,6 @@ u8 acpi_os_writable(void *ptr, acpi_size } #endif -u32 acpi_os_get_thread_id(void) -{ - if (!in_atomic()) - return current->pid; - - return 0; -} - acpi_status acpi_os_signal(u32 function, void *info) { switch (function) { @@ -1050,12 +1065,12 @@ #ifndef ACPI_USE_LOCAL_CACHE * * FUNCTION: acpi_os_create_cache * - * PARAMETERS: CacheName - Ascii name for the cache - * ObjectSize - Size of each cached object - * MaxDepth - Maximum depth of the cache (in objects) - * ReturnCache - Where the new cache object is returned + * PARAMETERS: name - Ascii name for the cache + * size - Size of each cached object + * depth - Maximum depth of the cache (in objects) + * cache - Where the new cache object is returned * - * RETURN: Status + * RETURN: status * * DESCRIPTION: Create a cache object * @@ -1065,7 +1080,10 @@ acpi_status acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache) { *cache = kmem_cache_create(name, size, 0, 0, NULL, NULL); - return AE_OK; + if (cache == NULL) + return AE_ERROR; + else + return AE_OK; } /******************************************************************************* @@ -1134,16 +1152,63 @@ acpi_status acpi_os_release_object(acpi_ * * RETURN: Status * - * DESCRIPTION: Get an object from the specified cache. If cache is empty, - * the object is allocated. + * DESCRIPTION: Return a zero-filled object. * ******************************************************************************/ void *acpi_os_acquire_object(acpi_cache_t * cache) { - void *object = kmem_cache_alloc(cache, GFP_KERNEL); + void *object = kmem_cache_zalloc(cache, GFP_KERNEL); WARN_ON(!object); return object; } +/****************************************************************************** + * + * FUNCTION: acpi_os_validate_interface + * + * PARAMETERS: interface - Requested interface to be validated + * + * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise + * + * DESCRIPTION: Match an interface string to the interfaces supported by the + * host. Strings originate from an AML call to the _OSI method. + * + *****************************************************************************/ + +acpi_status +acpi_os_validate_interface (char *interface) +{ + + return AE_SUPPORT; +} + + +/****************************************************************************** + * + * FUNCTION: acpi_os_validate_address + * + * PARAMETERS: space_id - ACPI space ID + * address - Physical address + * length - Address length + * + * RETURN: AE_OK if address/length is valid for the space_id. Otherwise, + * should return AE_AML_ILLEGAL_ADDRESS. + * + * DESCRIPTION: Validate a system address via the host OS. Used to validate + * the addresses accessed by AML operation regions. + * + *****************************************************************************/ + +acpi_status +acpi_os_validate_address ( + u8 space_id, + acpi_physical_address address, + acpi_size length) +{ + + return AE_OK; +} + + #endif diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index de573be..bf88e07 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -79,7 +79,7 @@ acpi_ps_get_next_package_length(struct a acpi_native_uint byte_count; u8 byte_zero_mask = 0x3F; /* Default [0:5] */ - ACPI_FUNCTION_TRACE("ps_get_next_package_length"); + ACPI_FUNCTION_TRACE(ps_get_next_package_length); /* * Byte 0 bits [6:7] contain the number of additional bytes @@ -128,7 +128,7 @@ u8 *acpi_ps_get_next_package_end(struct u8 *start = parser_state->aml; u32 package_length; - ACPI_FUNCTION_TRACE("ps_get_next_package_end"); + ACPI_FUNCTION_TRACE(ps_get_next_package_end); /* Function below updates parser_state->Aml */ @@ -157,7 +157,7 @@ char *acpi_ps_get_next_namestring(struct u8 *start = parser_state->aml; u8 *end = parser_state->aml; - ACPI_FUNCTION_TRACE("ps_get_next_namestring"); + ACPI_FUNCTION_TRACE(ps_get_next_namestring); /* Point past any namestring prefix characters (backslash or carat) */ @@ -237,7 +237,7 @@ acpi_ps_get_next_namepath(struct acpi_wa struct acpi_namespace_node *node; union acpi_generic_state scope_info; - ACPI_FUNCTION_TRACE("ps_get_next_namepath"); + ACPI_FUNCTION_TRACE(ps_get_next_namepath); path = acpi_ps_get_next_namestring(parser_state); acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP); @@ -275,6 +275,7 @@ acpi_ps_get_next_namepath(struct acpi_wa */ if (ACPI_SUCCESS(status) && possible_method_call && (node->type == ACPI_TYPE_METHOD)) { + /* This name is actually a control method invocation */ method_desc = acpi_ns_get_attached_object(node); @@ -319,6 +320,7 @@ acpi_ps_get_next_namepath(struct acpi_wa * some not_found cases are allowed */ if (status == AE_NOT_FOUND) { + /* 1) not_found is ok during load pass 1/2 (allow forward references) */ if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) != @@ -354,6 +356,7 @@ acpi_ps_get_next_namepath(struct acpi_wa if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) { + /* Report a control method execution error */ status = acpi_ds_method_error(status, walk_state); @@ -388,7 +391,7 @@ acpi_ps_get_next_simple_arg(struct acpi_ u16 opcode; u8 *aml = parser_state->aml; - ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type); + ACPI_FUNCTION_TRACE_U32(ps_get_next_simple_arg, arg_type); switch (arg_type) { case ARGP_BYTEDATA: @@ -453,7 +456,7 @@ acpi_ps_get_next_simple_arg(struct acpi_ default: - ACPI_ERROR((AE_INFO, "Invalid arg_type %X", arg_type)); + ACPI_ERROR((AE_INFO, "Invalid ArgType %X", arg_type)); return_VOID; } @@ -484,7 +487,7 @@ static union acpi_parse_object *acpi_ps_ u16 opcode; u32 name; - ACPI_FUNCTION_TRACE("ps_get_next_field"); + ACPI_FUNCTION_TRACE(ps_get_next_field); /* Determine field type */ @@ -590,7 +593,7 @@ acpi_ps_get_next_arg(struct acpi_walk_st u32 subop; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ps_get_next_arg", parser_state); + ACPI_FUNCTION_TRACE_PTR(ps_get_next_arg, parser_state); switch (arg_type) { case ARGP_BYTEDATA: @@ -620,6 +623,7 @@ acpi_ps_get_next_arg(struct acpi_walk_st case ARGP_FIELDLIST: if (parser_state->aml < parser_state->pkg_end) { + /* Non-empty list */ while (parser_state->aml < parser_state->pkg_end) { @@ -645,6 +649,7 @@ acpi_ps_get_next_arg(struct acpi_walk_st case ARGP_BYTELIST: if (parser_state->aml < parser_state->pkg_end) { + /* Non-empty list */ arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP); @@ -673,6 +678,7 @@ acpi_ps_get_next_arg(struct acpi_walk_st if (subop == 0 || acpi_ps_is_leading_char(subop) || acpi_ps_is_prefix_char(subop)) { + /* null_name or name_string */ arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); @@ -703,6 +709,7 @@ acpi_ps_get_next_arg(struct acpi_walk_st case ARGP_OBJLIST: if (parser_state->aml < parser_state->pkg_end) { + /* Non-empty list of variable arguments, nothing returned */ walk_state->arg_count = ACPI_VAR_ARGS; @@ -711,7 +718,7 @@ acpi_ps_get_next_arg(struct acpi_walk_st default: - ACPI_ERROR((AE_INFO, "Invalid arg_type: %X", arg_type)); + ACPI_ERROR((AE_INFO, "Invalid ArgType: %X", arg_type)); status = AE_AML_OPERAND_TYPE; break; } diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 00b072e..e1541db 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c @@ -83,7 +83,7 @@ acpi_status acpi_ps_parse_loop(struct ac struct acpi_parse_state *parser_state; u8 *aml_op_start = NULL; - ACPI_FUNCTION_TRACE_PTR("ps_parse_loop", walk_state); + ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state); if (walk_state->descending_callback == NULL) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -95,6 +95,7 @@ acpi_status acpi_ps_parse_loop(struct ac #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { + /* We are restarting a preempted control method */ if (acpi_ps_has_completed_scope(parser_state)) { @@ -128,7 +129,7 @@ #if (!defined (ACPI_NO_METHOD_EXECUTION) } ACPI_EXCEPTION((AE_INFO, status, - "get_predicate Failed")); + "GetPredicate Failed")); return_ACPI_STATUS(status); } @@ -143,6 +144,7 @@ #if (!defined (ACPI_NO_METHOD_EXECUTION) ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); } else if (walk_state->prev_op) { + /* We were in the middle of an op */ op = walk_state->prev_op; @@ -156,6 +158,7 @@ #endif while ((parser_state->aml < parser_state->aml_end) || (op)) { aml_op_start = parser_state->aml; if (!op) { + /* Get the next opcode from the AML stream */ walk_state->aml_offset = @@ -213,6 +216,7 @@ #endif /* Create Op structure and append to parent's argument list */ if (walk_state->op_info->flags & AML_NAMED) { + /* Allocate a new pre_op if necessary */ if (!pre_op) { @@ -371,7 +375,7 @@ #endif if (walk_state->op_info) { ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n", + "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", (u32) op->common.aml_opcode, walk_state->op_info->name, op, parser_state->aml, @@ -388,6 +392,7 @@ #endif /* Are there any arguments that must be processed? */ if (walk_state->arg_types) { + /* Get arguments */ switch (op->common.aml_opcode) { @@ -742,7 +747,19 @@ #endif if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } + + status2 = + acpi_ds_result_stack_pop + (walk_state); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } + + acpi_ut_delete_generic_state + (acpi_ut_pop_generic_state + (&walk_state->control_state)); } + acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); @@ -762,6 +779,7 @@ #endif return_ACPI_STATUS(status2); } } + acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); @@ -853,6 +871,7 @@ #endif } else if (ACPI_FAILURE(status)) { + /* First error is most important */ (void) diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 11d6351..4bd25e3 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -725,12 +725,13 @@ static const u8 acpi_gbl_long_op_index[N const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) { - ACPI_FUNCTION_NAME("ps_get_opcode_info"); + ACPI_FUNCTION_NAME(ps_get_opcode_info); /* * Detect normal 8-bit opcode or extended 16-bit opcode */ if (!(opcode & 0xFF00)) { + /* Simple (8-bit) opcode: 0-255, can't index beyond table */ return (&acpi_gbl_aml_op_info @@ -739,6 +740,7 @@ const struct acpi_opcode_info *acpi_ps_g if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) && (((u8) opcode) <= MAX_EXTENDED_OPCODE)) { + /* Valid extended (16-bit) opcode */ return (&acpi_gbl_aml_op_info @@ -779,7 +781,7 @@ #if defined(ACPI_DISASSEMBLER) || define return (op->name); #else - return ("AE_NOT_CONFIGURED"); + return ("OpcodeName unavailable"); #endif } diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index a9f3229..7ee2f2e 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -106,6 +106,7 @@ u16 acpi_ps_peek_opcode(struct acpi_pars opcode = (u16) ACPI_GET8(aml); if (opcode == AML_EXTENDED_OP_PREFIX) { + /* Extended opcode, get the second opcode byte */ aml++; @@ -137,7 +138,7 @@ acpi_ps_complete_this_op(struct acpi_wal const struct acpi_opcode_info *parent_info; union acpi_parse_object *replacement_op = NULL; - ACPI_FUNCTION_TRACE_PTR("ps_complete_this_op", op); + ACPI_FUNCTION_TRACE_PTR(ps_complete_this_op, op); /* Check for null Op, can happen if AML code is corrupt */ @@ -158,6 +159,7 @@ acpi_ps_complete_this_op(struct acpi_wal if (op->common.parent) { prev = op->common.parent->common.value.arg; if (!prev) { + /* Nothing more to do */ goto cleanup; @@ -245,6 +247,7 @@ acpi_ps_complete_this_op(struct acpi_wal /* We must unlink this op from the parent tree */ if (prev == op) { + /* This op is the first in the list */ if (replacement_op) { @@ -265,6 +268,7 @@ acpi_ps_complete_this_op(struct acpi_wal else while (prev) { + /* Traverse all siblings in the parent's argument list */ next = prev->common.next; @@ -329,7 +333,7 @@ acpi_ps_next_parse_state(struct acpi_wal struct acpi_parse_state *parser_state = &walk_state->parser_state; acpi_status status = AE_CTRL_PENDING; - ACPI_FUNCTION_TRACE_PTR("ps_next_parse_state", op); + ACPI_FUNCTION_TRACE_PTR(ps_next_parse_state, op); switch (callback_status) { case AE_CTRL_TERMINATE: @@ -449,10 +453,10 @@ acpi_status acpi_ps_parse_aml(struct acp struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list; struct acpi_walk_state *previous_walk_state; - ACPI_FUNCTION_TRACE("ps_parse_aml"); + ACPI_FUNCTION_TRACE(ps_parse_aml); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Entered with walk_state=%p Aml=%p size=%X\n", + "Entered with WalkState=%p Aml=%p size=%X\n", walk_state, walk_state->parser_state.aml, walk_state->parser_state.aml_size)); @@ -460,6 +464,7 @@ acpi_status acpi_ps_parse_aml(struct acp thread = acpi_ut_create_thread_state(); if (!thread) { + acpi_ds_delete_walk_state(walk_state); return_ACPI_STATUS(AE_NO_MEMORY); } @@ -510,6 +515,7 @@ acpi_status acpi_ps_parse_aml(struct acp } else if (status == AE_CTRL_TERMINATE) { status = AE_OK; } else if ((status != AE_OK) && (walk_state->method_desc)) { + /* Either the method parse or actual execution failed */ ACPI_ERROR_METHOD("Method parse/execution failed", @@ -550,20 +556,9 @@ acpi_status acpi_ps_parse_aml(struct acp */ if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) { - if (walk_state->method_desc) { - /* Decrement the thread count on the method parse tree */ - - if (walk_state->method_desc->method. - thread_count) { - walk_state->method_desc->method. - thread_count--; - } else { - ACPI_ERROR((AE_INFO, - "Invalid zero thread count in method")); - } - } - - acpi_ds_terminate_control_method(walk_state); + acpi_ds_terminate_control_method(walk_state-> + method_desc, + walk_state); } /* Delete this walk state and all linked control states */ @@ -572,7 +567,7 @@ acpi_status acpi_ps_parse_aml(struct acp previous_walk_state = walk_state; ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "return_value=%p, implicit_value=%p State=%p\n", + "ReturnValue=%p, ImplicitValue=%p State=%p\n", walk_state->return_desc, walk_state->implicit_return_obj, walk_state)); @@ -633,12 +628,14 @@ acpi_status acpi_ps_parse_aml(struct acp } } else { if (previous_walk_state->return_desc) { + /* Caller doesn't want it, must delete it */ acpi_ut_remove_reference(previous_walk_state-> return_desc); } if (previous_walk_state->implicit_return_obj) { + /* Caller doesn't want it, must delete it */ acpi_ut_remove_reference(previous_walk_state-> diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c index bc6047c..a3e0314 100644 --- a/drivers/acpi/parser/psscope.c +++ b/drivers/acpi/parser/psscope.c @@ -106,14 +106,14 @@ acpi_ps_init_scope(struct acpi_parse_sta { union acpi_generic_state *scope; - ACPI_FUNCTION_TRACE_PTR("ps_init_scope", root_op); + ACPI_FUNCTION_TRACE_PTR(ps_init_scope, root_op); scope = acpi_ut_create_generic_state(); if (!scope) { return_ACPI_STATUS(AE_NO_MEMORY); } - scope->common.data_type = ACPI_DESC_TYPE_STATE_RPSCOPE; + scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_RPSCOPE; scope->parse_scope.op = root_op; scope->parse_scope.arg_count = ACPI_VAR_ARGS; scope->parse_scope.arg_end = parser_state->aml_end; @@ -147,14 +147,14 @@ acpi_ps_push_scope(struct acpi_parse_sta { union acpi_generic_state *scope; - ACPI_FUNCTION_TRACE_PTR("ps_push_scope", op); + ACPI_FUNCTION_TRACE_PTR(ps_push_scope, op); scope = acpi_ut_create_generic_state(); if (!scope) { return_ACPI_STATUS(AE_NO_MEMORY); } - scope->common.data_type = ACPI_DESC_TYPE_STATE_PSCOPE; + scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_PSCOPE; scope->parse_scope.op = op; scope->parse_scope.arg_list = remaining_args; scope->parse_scope.arg_count = arg_count; @@ -165,6 +165,7 @@ acpi_ps_push_scope(struct acpi_parse_sta acpi_ut_push_generic_state(&parser_state->scope, scope); if (arg_count == ACPI_VAR_ARGS) { + /* Multiple arguments */ scope->parse_scope.arg_end = parser_state->pkg_end; @@ -199,14 +200,14 @@ acpi_ps_pop_scope(struct acpi_parse_stat { union acpi_generic_state *scope = parser_state->scope; - ACPI_FUNCTION_TRACE("ps_pop_scope"); + ACPI_FUNCTION_TRACE(ps_pop_scope); /* Only pop the scope if there is in fact a next scope */ if (scope->common.next) { scope = acpi_ut_pop_generic_state(&parser_state->scope); - /* return to parsing previous op */ + /* Return to parsing previous op */ *op = scope->parse_scope.op; *arg_list = scope->parse_scope.arg_list; @@ -217,7 +218,7 @@ acpi_ps_pop_scope(struct acpi_parse_stat acpi_ut_delete_generic_state(scope); } else { - /* empty parse stack, prepare to fetch next opcode */ + /* Empty parse stack, prepare to fetch next opcode */ *op = NULL; *arg_list = 0; @@ -246,7 +247,7 @@ void acpi_ps_cleanup_scope(struct acpi_p { union acpi_generic_state *scope; - ACPI_FUNCTION_TRACE_PTR("ps_cleanup_scope", parser_state); + ACPI_FUNCTION_TRACE_PTR(ps_cleanup_scope, parser_state); if (!parser_state) { return_VOID; diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c index dd6f167..0015717 100644 --- a/drivers/acpi/parser/pstree.c +++ b/drivers/acpi/parser/pstree.c @@ -77,6 +77,7 @@ union acpi_parse_object *acpi_ps_get_arg op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); if (op_info->class == AML_CLASS_UNKNOWN) { + /* Invalid opcode or ASCII character */ return (NULL); @@ -85,6 +86,7 @@ union acpi_parse_object *acpi_ps_get_arg /* Check if this opcode requires argument sub-objects */ if (!(op_info->flags & AML_HAS_ARGS)) { + /* Has no linked argument objects */ return (NULL); @@ -130,6 +132,7 @@ acpi_ps_append_arg(union acpi_parse_obje op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); if (op_info->class == AML_CLASS_UNKNOWN) { + /* Invalid opcode */ ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X", @@ -140,6 +143,7 @@ acpi_ps_append_arg(union acpi_parse_obje /* Check if this opcode requires argument sub-objects */ if (!(op_info->flags & AML_HAS_ARGS)) { + /* Has no linked argument objects */ return; @@ -148,6 +152,7 @@ acpi_ps_append_arg(union acpi_parse_obje /* Append the argument to the linked argument list */ if (op->common.value.arg) { + /* Append to existing argument list */ prev_arg = op->common.value.arg; @@ -222,12 +227,14 @@ union acpi_parse_object *acpi_ps_get_dep } if (arg == origin) { + /* Reached parent of origin, end search */ return (NULL); } if (parent->common.next) { + /* Found sibling of parent */ return (parent->common.next); @@ -299,5 +306,4 @@ union acpi_parse_object *acpi_ps_get_chi return (child); } #endif - #endif /* ACPI_FUTURE_USAGE */ diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c index 3e07cb9..182474a 100644 --- a/drivers/acpi/parser/psutils.c +++ b/drivers/acpi/parser/psutils.c @@ -89,7 +89,7 @@ void acpi_ps_init_op(union acpi_parse_ob { ACPI_FUNCTION_ENTRY(); - op->common.data_type = ACPI_DESC_TYPE_PARSER; + op->common.descriptor_type = ACPI_DESC_TYPE_PARSER; op->common.aml_opcode = opcode; ACPI_DISASM_ONLY_MEMBERS(ACPI_STRNCPY(op->common.aml_op_name, @@ -135,6 +135,7 @@ union acpi_parse_object *acpi_ps_alloc_o /* Allocate the minimum required size object */ if (flags == ACPI_PARSEOP_GENERIC) { + /* The generic op (default) is by far the most common (16 to 1) */ op = acpi_os_acquire_object(acpi_gbl_ps_node_cache); @@ -171,7 +172,7 @@ union acpi_parse_object *acpi_ps_alloc_o void acpi_ps_free_op(union acpi_parse_object *op) { - ACPI_FUNCTION_NAME("ps_free_op"); + ACPI_FUNCTION_NAME(ps_free_op); if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n", diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c index 06f05bf..a84a547 100644 --- a/drivers/acpi/parser/pswalk.c +++ b/drivers/acpi/parser/pswalk.c @@ -64,18 +64,21 @@ void acpi_ps_delete_parse_tree(union acp union acpi_parse_object *next = NULL; union acpi_parse_object *parent = NULL; - ACPI_FUNCTION_TRACE_PTR("ps_delete_parse_tree", subtree_root); + ACPI_FUNCTION_TRACE_PTR(ps_delete_parse_tree, subtree_root); /* Visit all nodes in the subtree */ while (op) { + /* Check if we are not ascending */ if (op != parent) { + /* Look for an argument or child of the current op */ next = acpi_ps_get_arg(op, 0); if (next) { + /* Still going downward in tree (Op is not completed yet) */ op = next; diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index 2dd48cb..5d996c1 100644 --- a/drivers/acpi/parser/psxface.c +++ b/drivers/acpi/parser/psxface.c @@ -50,14 +50,14 @@ #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psxface") /* Local Prototypes */ -static void acpi_ps_start_trace(struct acpi_parameter_info *info); +static void acpi_ps_start_trace(struct acpi_evaluate_info *info); -static void acpi_ps_stop_trace(struct acpi_parameter_info *info); +static void acpi_ps_stop_trace(struct acpi_evaluate_info *info); -static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info); +static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info); static void -acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action); +acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action); /******************************************************************************* * @@ -113,7 +113,7 @@ acpi_debug_trace(char *name, u32 debug_l * ******************************************************************************/ -static void acpi_ps_start_trace(struct acpi_parameter_info *info) +static void acpi_ps_start_trace(struct acpi_evaluate_info *info) { acpi_status status; @@ -125,7 +125,7 @@ static void acpi_ps_start_trace(struct a } if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->node->name.integer)) { + (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { goto exit; } @@ -158,7 +158,7 @@ static void acpi_ps_start_trace(struct a * ******************************************************************************/ -static void acpi_ps_stop_trace(struct acpi_parameter_info *info) +static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) { acpi_status status; @@ -170,7 +170,7 @@ static void acpi_ps_stop_trace(struct ac } if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->node->name.integer)) { + (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) { goto exit; } @@ -212,22 +212,23 @@ static void acpi_ps_stop_trace(struct ac * ******************************************************************************/ -acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info) +acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) { acpi_status status; - ACPI_FUNCTION_TRACE("ps_execute_method"); + ACPI_FUNCTION_TRACE(ps_execute_method); /* Validate the Info and method Node */ - if (!info || !info->node) { + if (!info || !info->resolved_node) { return_ACPI_STATUS(AE_NULL_ENTRY); } /* Init for new method, wait on concurrency semaphore */ status = - acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL); + acpi_ds_begin_method_execution(info->resolved_node, info->obj_desc, + NULL); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -248,7 +249,7 @@ acpi_status acpi_ps_execute_method(struc */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Begin Method Parse **** Entry=%p obj=%p\n", - info->node, info->obj_desc)); + info->resolved_node, info->obj_desc)); info->pass_number = 1; status = acpi_ps_execute_pass(info); @@ -261,7 +262,7 @@ acpi_status acpi_ps_execute_method(struc */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Begin Method Execution **** Entry=%p obj=%p\n", - info->node, info->obj_desc)); + info->resolved_node, info->obj_desc)); info->pass_number = 3; status = acpi_ps_execute_pass(info); @@ -286,8 +287,7 @@ acpi_status acpi_ps_execute_method(struc * a control exception code */ if (info->return_object) { - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Method returned obj_desc=%p\n", + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n", info->return_object)); ACPI_DUMP_STACK_ENTRY(info->return_object); @@ -301,7 +301,7 @@ acpi_status acpi_ps_execute_method(struc * * FUNCTION: acpi_ps_update_parameter_list * - * PARAMETERS: Info - See struct acpi_parameter_info + * PARAMETERS: Info - See struct acpi_evaluate_info * (Used: parameter_type and Parameters) * Action - Add or Remove reference * @@ -312,14 +312,16 @@ acpi_status acpi_ps_execute_method(struc ******************************************************************************/ static void -acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action) +acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action) { acpi_native_uint i; if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) { + /* Update reference count for each parameter */ for (i = 0; info->parameters[i]; i++) { + /* Ignore errors, just do them all */ (void)acpi_ut_update_object_reference(info-> @@ -333,7 +335,7 @@ acpi_ps_update_parameter_list(struct acp * * FUNCTION: acpi_ps_execute_pass * - * PARAMETERS: Info - See struct acpi_parameter_info + * PARAMETERS: Info - See struct acpi_evaluate_info * (Used: pass_number, Node, and obj_desc) * * RETURN: Status @@ -342,13 +344,13 @@ acpi_ps_update_parameter_list(struct acp * ******************************************************************************/ -static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info) +static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info) { acpi_status status; union acpi_parse_object *op; struct acpi_walk_state *walk_state; - ACPI_FUNCTION_TRACE("ps_execute_pass"); + ACPI_FUNCTION_TRACE(ps_execute_pass); /* Create and init a Root Node */ @@ -367,7 +369,7 @@ static acpi_status acpi_ps_execute_pass( goto cleanup; } - status = acpi_ds_init_aml_walk(walk_state, op, info->node, + status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node, info->obj_desc->method.aml_start, info->obj_desc->method.aml_length, info->pass_number == 1 ? NULL : info, diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 07bc6df..228bdb6 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -38,6 +38,7 @@ #include #include #include #include +#include #include #include @@ -91,7 +92,7 @@ static struct { int count; struct list_head entries; } acpi_link; -DECLARE_MUTEX(acpi_link_lock); +DEFINE_MUTEX(acpi_link_lock); /* -------------------------------------------------------------------------- PCI Link Device Management @@ -641,19 +642,19 @@ acpi_pci_link_allocate_irq(acpi_handle h return_VALUE(-1); } - down(&acpi_link_lock); + mutex_lock(&acpi_link_lock); if (acpi_pci_link_allocate(link)) { - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); return_VALUE(-1); } if (!link->irq.active) { - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); return_VALUE(-1); } link->refcnt++; - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); if (triggering) *triggering = link->irq.triggering; @@ -691,9 +692,9 @@ int acpi_pci_link_free_irq(acpi_handle h return_VALUE(-1); } - down(&acpi_link_lock); + mutex_lock(&acpi_link_lock); if (!link->irq.initialized) { - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n")); return_VALUE(-1); } @@ -716,7 +717,7 @@ #endif if (link->refcnt == 0) { acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); } - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); return_VALUE(link->irq.active); } @@ -747,7 +748,7 @@ static int acpi_pci_link_add(struct acpi strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); acpi_driver_data(device) = link; - down(&acpi_link_lock); + mutex_lock(&acpi_link_lock); result = acpi_pci_link_get_possible(link); if (result) goto end; @@ -782,7 +783,7 @@ static int acpi_pci_link_add(struct acpi end: /* disable all links -- to be activated on use */ acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); if (result) kfree(link); @@ -812,6 +813,9 @@ static int irqrouter_resume(struct sys_d ACPI_FUNCTION_TRACE("irqrouter_resume"); + /* Make sure SCI is enabled again (Apple firmware bug?) */ + acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1, ACPI_MTX_DO_NOT_LOCK); + acpi_in_resume = 1; list_for_each(node, &acpi_link.entries) { link = list_entry(node, struct acpi_pci_link, node); @@ -837,9 +841,9 @@ static int acpi_pci_link_remove(struct a link = (struct acpi_pci_link *)acpi_driver_data(device); - down(&acpi_link_lock); + mutex_lock(&acpi_link_lock); list_del(&link->node); - up(&acpi_link_lock); + mutex_unlock(&acpi_link_lock); kfree(link); diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 713b763..decaebb 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -110,7 +110,7 @@ static struct file_operations acpi_proce }; struct acpi_processor *processors[NR_CPUS]; -struct acpi_processor_errata errata; +struct acpi_processor_errata errata __read_mostly; /* -------------------------------------------------------------------------- Errata Handling @@ -388,7 +388,7 @@ static int acpi_processor_remove_fs(stru /* Use the acpiid in MADT to map cpus in case of SMP */ #ifndef CONFIG_SMP -#define convert_acpiid_to_cpu(acpi_id) (0xff) +#define convert_acpiid_to_cpu(acpi_id) (-1) #else #ifdef CONFIG_IA64 @@ -401,7 +401,7 @@ #define arch_cpu_to_apicid x86_cpu_to_a #define ARCH_BAD_APICID (0xff) #endif -static u8 convert_acpiid_to_cpu(u8 acpi_id) +static int convert_acpiid_to_cpu(u8 acpi_id) { u16 apic_id; int i; @@ -427,7 +427,7 @@ static int acpi_processor_get_info(struc acpi_status status = 0; union acpi_object object = { 0 }; struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; - u8 cpu_index; + int cpu_index; static int cpu0_initialized; ACPI_FUNCTION_TRACE("acpi_processor_get_info"); @@ -473,7 +473,7 @@ static int acpi_processor_get_info(struc cpu_index = convert_acpiid_to_cpu(pr->acpi_id); /* Handle UP system running SMP kernel, with no LAPIC in MADT */ - if (!cpu0_initialized && (cpu_index == 0xff) && + if (!cpu0_initialized && (cpu_index == -1) && (num_online_cpus() == 1)) { cpu_index = 0; } @@ -487,7 +487,7 @@ static int acpi_processor_get_info(struc * less than the max # of CPUs. They should be ignored _iff * they are physically not present. */ - if (cpu_index >= NR_CPUS) { + if (cpu_index == -1) { if (ACPI_FAILURE (acpi_processor_hotadd_init(pr->handle, &pr->id))) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, @@ -558,8 +558,8 @@ static int acpi_processor_start(struct a */ if (processor_device_array[pr->id] != NULL && processor_device_array[pr->id] != (void *)device) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "BIOS reporting wrong ACPI id" - "for the processor\n")); + printk(KERN_WARNING "BIOS reported wrong ACPI id" + "for the processor\n"); return_VALUE(-ENODEV); } processor_device_array[pr->id] = (void *)device; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 80fa434..8a74bf3 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -54,10 +54,10 @@ #define ACPI_PROCESSOR_FILE_POWER "power #define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000) #define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */ #define C3_OVERHEAD 4 /* 1us (3.579 ticks per us) */ -static void (*pm_idle_save) (void); +static void (*pm_idle_save) (void) __read_mostly; module_param(max_cstate, uint, 0644); -static unsigned int nocst = 0; +static unsigned int nocst __read_mostly; module_param(nocst, uint, 0000); /* @@ -67,7 +67,7 @@ module_param(nocst, uint, 0000); * 100 HZ: 0x0000000F: 4 jiffies = 40ms * reduce history for more aggressive entry into C3 */ -static unsigned int bm_history = +static unsigned int bm_history __read_mostly = (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1)); module_param(bm_history, uint, 0644); /* -------------------------------------------------------------------------- @@ -206,11 +206,11 @@ acpi_processor_power_activate(struct acp static void acpi_safe_halt(void) { - clear_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status &= ~TS_POLLING; smp_mb__after_clear_bit(); if (!need_resched()) safe_halt(); - set_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status |= TS_POLLING; } static atomic_t c3_cpu_count; @@ -330,10 +330,10 @@ #endif * Invoke the current Cx state to put the processor to sleep. */ if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) { - clear_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status &= ~TS_POLLING; smp_mb__after_clear_bit(); if (need_resched()) { - set_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status |= TS_POLLING; local_irq_enable(); return; } @@ -369,9 +369,14 @@ #endif t2 = inl(acpi_fadt.xpm_tmr_blk.address); /* Get end time (ticks) */ t2 = inl(acpi_fadt.xpm_tmr_blk.address); + +#ifdef CONFIG_GENERIC_TIME + /* TSC halts in C2, so notify users */ + mark_tsc_unstable(); +#endif /* Re-enable interrupts */ local_irq_enable(); - set_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status |= TS_POLLING; /* Compute time (ticks) that we were actually asleep */ sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD; @@ -409,9 +414,13 @@ #endif ACPI_MTX_DO_NOT_LOCK); } +#ifdef CONFIG_GENERIC_TIME + /* TSC halts in C3, so notify users */ + mark_tsc_unstable(); +#endif /* Re-enable interrupts */ local_irq_enable(); - set_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status |= TS_POLLING; /* Compute time (ticks) that we were actually asleep */ sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD; @@ -1081,7 +1090,7 @@ int acpi_processor_power_init(struct acp struct acpi_device *device) { acpi_status status = 0; - static int first_run = 0; + static int first_run; struct proc_dir_entry *entry = NULL; unsigned int i; diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index f36db22..41aaaba 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -34,6 +34,7 @@ #include #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF #include #include +#include #include #endif @@ -48,7 +49,7 @@ #define ACPI_PROCESSOR_FILE_PERFORMANCE #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("acpi_processor") -static DECLARE_MUTEX(performance_sem); +static DEFINE_MUTEX(performance_mutex); /* * _PPC support is implemented as a CPUfreq policy notifier: @@ -72,7 +73,7 @@ static int acpi_processor_ppc_notifier(s struct acpi_processor *pr; unsigned int ppc = 0; - down(&performance_sem); + mutex_lock(&performance_mutex); if (event != CPUFREQ_INCOMPATIBLE) goto out; @@ -93,7 +94,7 @@ static int acpi_processor_ppc_notifier(s core_frequency * 1000); out: - up(&performance_sem); + mutex_unlock(&performance_mutex); return 0; } @@ -553,6 +554,230 @@ static void acpi_cpufreq_remove_file(str } #endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */ +static int acpi_processor_get_psd(struct acpi_processor *pr) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"}; + struct acpi_buffer state = {0, NULL}; + union acpi_object *psd = NULL; + struct acpi_psd_package *pdomain; + + status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer); + if (ACPI_FAILURE(status)) { + return -ENODEV; + } + + psd = (union acpi_object *) buffer.pointer; + if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + result = -EFAULT; + goto end; + } + + if (psd->package.count != 1) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + result = -EFAULT; + goto end; + } + + pdomain = &(pr->performance->domain_info); + + state.length = sizeof(struct acpi_psd_package); + state.pointer = pdomain; + + status = acpi_extract_package(&(psd->package.elements[0]), + &format, &state); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + result = -EFAULT; + goto end; + } + + if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n")); + result = -EFAULT; + goto end; + } + + if (pdomain->revision != ACPI_PSD_REV0_REVISION) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n")); + result = -EFAULT; + goto end; + } + +end: + acpi_os_free(buffer.pointer); + return result; +} + +int acpi_processor_preregister_performance( + struct acpi_processor_performance **performance) +{ + int count, count_target; + int retval = 0; + unsigned int i, j; + cpumask_t covered_cpus; + struct acpi_processor *pr; + struct acpi_psd_package *pdomain; + struct acpi_processor *match_pr; + struct acpi_psd_package *match_pdomain; + + mutex_lock(&performance_mutex); + + retval = 0; + + /* Call _PSD for all CPUs */ + for_each_possible_cpu(i) { + pr = processors[i]; + if (!pr) { + /* Look only at processors in ACPI namespace */ + continue; + } + + if (pr->performance) { + retval = -EBUSY; + continue; + } + + if (!performance || !performance[i]) { + retval = -EINVAL; + continue; + } + + pr->performance = performance[i]; + cpu_set(i, pr->performance->shared_cpu_map); + if (acpi_processor_get_psd(pr)) { + retval = -EINVAL; + continue; + } + } + if (retval) + goto err_ret; + + /* + * Now that we have _PSD data from all CPUs, lets setup P-state + * domain info. + */ + for_each_possible_cpu(i) { + pr = processors[i]; + if (!pr) + continue; + + /* Basic validity check for domain info */ + pdomain = &(pr->performance->domain_info); + if ((pdomain->revision != ACPI_PSD_REV0_REVISION) || + (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES)) { + retval = -EINVAL; + goto err_ret; + } + if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL && + pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY && + pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) { + retval = -EINVAL; + goto err_ret; + } + } + + cpus_clear(covered_cpus); + for_each_possible_cpu(i) { + pr = processors[i]; + if (!pr) + continue; + + if (cpu_isset(i, covered_cpus)) + continue; + + pdomain = &(pr->performance->domain_info); + cpu_set(i, pr->performance->shared_cpu_map); + cpu_set(i, covered_cpus); + if (pdomain->num_processors <= 1) + continue; + + /* Validate the Domain info */ + count_target = pdomain->num_processors; + count = 1; + if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL || + pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL) { + pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL; + } else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY) { + pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY; + } + + for_each_possible_cpu(j) { + if (i == j) + continue; + + match_pr = processors[j]; + if (!match_pr) + continue; + + match_pdomain = &(match_pr->performance->domain_info); + if (match_pdomain->domain != pdomain->domain) + continue; + + /* Here i and j are in the same domain */ + + if (match_pdomain->num_processors != count_target) { + retval = -EINVAL; + goto err_ret; + } + + if (pdomain->coord_type != match_pdomain->coord_type) { + retval = -EINVAL; + goto err_ret; + } + + cpu_set(j, covered_cpus); + cpu_set(j, pr->performance->shared_cpu_map); + count++; + } + + for_each_possible_cpu(j) { + if (i == j) + continue; + + match_pr = processors[j]; + if (!match_pr) + continue; + + match_pdomain = &(match_pr->performance->domain_info); + if (match_pdomain->domain != pdomain->domain) + continue; + + match_pr->performance->shared_type = + pr->performance->shared_type; + match_pr->performance->shared_cpu_map = + pr->performance->shared_cpu_map; + } + } + +err_ret: + if (retval) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error while parsing _PSD domain information. Assuming no coordination\n")); + } + + for_each_possible_cpu(i) { + pr = processors[i]; + if (!pr || !pr->performance) + continue; + + /* Assume no coordination on any error parsing domain info */ + if (retval) { + cpus_clear(pr->performance->shared_cpu_map); + cpu_set(i, pr->performance->shared_cpu_map); + pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL; + } + pr->performance = NULL; /* Will be set for real in register */ + } + + mutex_unlock(&performance_mutex); + return retval; +} +EXPORT_SYMBOL(acpi_processor_preregister_performance); + + int acpi_processor_register_performance(struct acpi_processor_performance *performance, unsigned int cpu) @@ -564,16 +789,16 @@ acpi_processor_register_performance(stru if (!(acpi_processor_ppc_status & PPC_REGISTERED)) return_VALUE(-EINVAL); - down(&performance_sem); + mutex_lock(&performance_mutex); pr = processors[cpu]; if (!pr) { - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VALUE(-ENODEV); } if (pr->performance) { - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VALUE(-EBUSY); } @@ -583,13 +808,13 @@ acpi_processor_register_performance(stru if (acpi_processor_get_performance_info(pr)) { pr->performance = NULL; - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VALUE(-EIO); } acpi_cpufreq_add_file(pr); - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VALUE(0); } @@ -603,11 +828,11 @@ acpi_processor_unregister_performance(st ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance"); - down(&performance_sem); + mutex_lock(&performance_mutex); pr = processors[cpu]; if (!pr) { - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VOID; } @@ -617,7 +842,7 @@ acpi_processor_unregister_performance(st acpi_cpufreq_remove_file(pr); - up(&performance_sem); + mutex_unlock(&performance_mutex); return_VOID; } diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index 4038dbf..cf87b02 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -78,6 +78,7 @@ static u8 acpi_rs_count_set_bits(u16 bit ACPI_FUNCTION_ENTRY(); for (bits_set = 0; bit_field; bits_set++) { + /* Zero the least significant bit that is set */ bit_field &= (bit_field - 1); @@ -154,15 +155,18 @@ acpi_rs_stream_option_length(u32 resourc * length, minus one byte for the resource_source_index itself. */ if (resource_length > minimum_aml_resource_length) { + /* Compute the length of the optional string */ string_length = resource_length - minimum_aml_resource_length - 1; } - /* Round up length to 32 bits for internal structure alignment */ - - return (ACPI_ROUND_UP_to_32_bITS(string_length)); + /* + * Round the length up to a multiple of the native word in order to + * guarantee that the entire resource descriptor is native word aligned + */ + return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length)); } /******************************************************************************* @@ -186,11 +190,12 @@ acpi_rs_get_aml_length(struct acpi_resou acpi_size aml_size_needed = 0; acpi_rs_length total_size; - ACPI_FUNCTION_TRACE("rs_get_aml_length"); + ACPI_FUNCTION_TRACE(rs_get_aml_length); /* Traverse entire list of internal resource descriptors */ while (resource) { + /* Validate the descriptor type */ if (resource->type > ACPI_RESOURCE_TYPE_MAX) { @@ -214,6 +219,7 @@ acpi_rs_get_aml_length(struct acpi_resou * is a Large Resource data type. */ if (resource->data.vendor.byte_length > 7) { + /* Base size of a Large resource descriptor */ total_size = @@ -332,20 +338,22 @@ acpi_rs_get_list_length(u8 * aml_buffer, acpi_status status; u8 *end_aml; u8 *buffer; - u32 buffer_size = 0; + u32 buffer_size; u16 temp16; u16 resource_length; u32 extra_struct_bytes; u8 resource_index; u8 minimum_aml_resource_length; - ACPI_FUNCTION_TRACE("rs_get_list_length"); + ACPI_FUNCTION_TRACE(rs_get_list_length); + *size_needed = 0; end_aml = aml_buffer + aml_buffer_length; /* Walk the list of AML resource descriptors */ while (aml_buffer < end_aml) { + /* Validate the Resource Type and Resource Length */ status = acpi_ut_validate_resource(aml_buffer, &resource_index); @@ -386,35 +394,28 @@ acpi_rs_get_list_length(u8 * aml_buffer, break; case ACPI_RESOURCE_NAME_VENDOR_SMALL: + case ACPI_RESOURCE_NAME_VENDOR_LARGE: /* * Vendor Resource: - * Ensure a 32-bit boundary for the structure + * Get the number of vendor data bytes */ - extra_struct_bytes = - ACPI_ROUND_UP_to_32_bITS(resource_length); + extra_struct_bytes = resource_length; break; case ACPI_RESOURCE_NAME_END_TAG: /* - * End Tag: This is the normal exit, add size of end_tag + * End Tag: + * This is the normal exit, add size of end_tag */ - *size_needed = buffer_size + ACPI_RS_SIZE_MIN; + *size_needed += ACPI_RS_SIZE_MIN; return_ACPI_STATUS(AE_OK); - case ACPI_RESOURCE_NAME_VENDOR_LARGE: - /* - * Vendor Resource: - * Add vendor data and ensure a 32-bit boundary for the structure - */ - extra_struct_bytes = - ACPI_ROUND_UP_to_32_bITS(resource_length); - break; - case ACPI_RESOURCE_NAME_ADDRESS32: case ACPI_RESOURCE_NAME_ADDRESS16: + case ACPI_RESOURCE_NAME_ADDRESS64: /* - * 32-Bit or 16-bit Address Resource: - * Add the size of any optional data (resource_source) + * Address Resource: + * Add the size of the optional resource_source */ extra_struct_bytes = acpi_rs_stream_option_length(resource_length, @@ -423,50 +424,46 @@ acpi_rs_get_list_length(u8 * aml_buffer, case ACPI_RESOURCE_NAME_EXTENDED_IRQ: /* - * Extended IRQ: - * Point past the interrupt_vector_flags to get the - * interrupt_table_length. + * Extended IRQ Resource: + * Using the interrupt_table_length, add 4 bytes for each additional + * interrupt. Note: at least one interrupt is required and is + * included in the minimum descriptor size (reason for the -1) */ - buffer++; + extra_struct_bytes = (buffer[1] - 1) * sizeof(u32); - extra_struct_bytes = - /* - * Add 4 bytes for each additional interrupt. Note: at - * least one interrupt is required and is included in - * the minimum descriptor size - */ - ((*buffer - 1) * sizeof(u32)) + - /* Add the size of any optional data (resource_source) */ + /* Add the size of the optional resource_source */ + + extra_struct_bytes += acpi_rs_stream_option_length(resource_length - extra_struct_bytes, minimum_aml_resource_length); break; - case ACPI_RESOURCE_NAME_ADDRESS64: - /* - * 64-Bit Address Resource: - * Add the size of any optional data (resource_source) - * Ensure a 64-bit boundary for the structure - */ - extra_struct_bytes = - ACPI_ROUND_UP_to_64_bITS - (acpi_rs_stream_option_length - (resource_length, minimum_aml_resource_length)); - break; - default: break; } - /* Update the required buffer size for the internal descriptor structs */ + /* + * Update the required buffer size for the internal descriptor structs + * + * Important: Round the size up for the appropriate alignment. This + * is a requirement on IA64. + */ + buffer_size = acpi_gbl_resource_struct_sizes[resource_index] + + extra_struct_bytes; + buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size); - temp16 = (u16) (acpi_gbl_resource_struct_sizes[resource_index] + - extra_struct_bytes); - buffer_size += (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(temp16); + *size_needed += buffer_size; + + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, + "Type %.2X, AmlLength %.2X InternalLength %.2X\n", + acpi_ut_get_resource_type(aml_buffer), + acpi_ut_get_descriptor_length(aml_buffer), + buffer_size)); /* - * Point to the next resource within the stream - * using the size of the header plus the length contained in the header + * Point to the next resource within the AML stream using the length + * contained in the resource descriptor header */ aml_buffer += acpi_ut_get_descriptor_length(aml_buffer); } @@ -506,7 +503,7 @@ acpi_rs_get_pci_routing_table_length(uni u8 name_found; u32 table_index; - ACPI_FUNCTION_TRACE("rs_get_pci_routing_table_length"); + ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length); number_of_elements = package_object->package.count; @@ -523,6 +520,7 @@ acpi_rs_get_pci_routing_table_length(uni top_object_list = package_object->package.elements; for (index = 0; index < number_of_elements; index++) { + /* Dereference the sub-package */ package_element = *top_object_list; @@ -581,7 +579,7 @@ acpi_rs_get_pci_routing_table_length(uni /* Round up the size since each element must be aligned */ - temp_size_needed = ACPI_ROUND_UP_to_64_bITS(temp_size_needed); + temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed); /* Point to the next union acpi_operand_object */ @@ -589,7 +587,7 @@ acpi_rs_get_pci_routing_table_length(uni } /* - * Adding an extra element to the end of the list, essentially a + * Add an extra element to the end of the list, essentially a * NULL terminator */ *buffer_size_needed = diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 8c128de..008058a 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c @@ -75,10 +75,11 @@ acpi_rs_create_resource_list(union acpi_ u8 *aml_start; acpi_size list_size_needed = 0; u32 aml_buffer_length; + void *resource; - ACPI_FUNCTION_TRACE("rs_create_resource_list"); + ACPI_FUNCTION_TRACE(rs_create_resource_list); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_buffer = %p\n", aml_buffer)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlBuffer = %p\n", aml_buffer)); /* Params already validated, so we don't re-validate here */ @@ -92,7 +93,7 @@ acpi_rs_create_resource_list(union acpi_ status = acpi_rs_get_list_length(aml_start, aml_buffer_length, &list_size_needed); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X ListSizeNeeded=%X\n", status, (u32) list_size_needed)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -107,13 +108,15 @@ acpi_rs_create_resource_list(union acpi_ /* Do the conversion */ - status = acpi_rs_convert_aml_to_resources(aml_start, aml_buffer_length, - output_buffer->pointer); + resource = output_buffer->pointer; + status = acpi_ut_walk_aml_resources(aml_start, aml_buffer_length, + acpi_rs_convert_aml_to_resources, + &resource); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", output_buffer->pointer, (u32) output_buffer->length)); return_ACPI_STATUS(AE_OK); } @@ -155,7 +158,7 @@ acpi_rs_create_pci_routing_table(union a acpi_status status; struct acpi_buffer path_buffer; - ACPI_FUNCTION_TRACE("rs_create_pci_routing_table"); + ACPI_FUNCTION_TRACE(rs_create_pci_routing_table); /* Params already validated, so we don't re-validate here */ @@ -167,7 +170,7 @@ acpi_rs_create_pci_routing_table(union a return_ACPI_STATUS(status); } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "buffer_size_needed = %X\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "BufferSizeNeeded = %X\n", (u32) buffer_size_needed)); /* Validate/Allocate/Clear caller buffer */ @@ -332,7 +335,7 @@ acpi_rs_create_pci_routing_table(union a /* Now align the current length */ user_prt->length = - (u32) ACPI_ROUND_UP_to_64_bITS(user_prt->length); + (u32) ACPI_ROUND_UP_TO_64BIT(user_prt->length); /* 4) Fourth subobject: Dereference the PRT.source_index */ @@ -341,7 +344,7 @@ acpi_rs_create_pci_routing_table(union a user_prt->source_index = (u32) obj_desc->integer.value; } else { ACPI_ERROR((AE_INFO, - "(PRT[%X].source_index) Need Integer, found %s", + "(PRT[%X].SourceIndex) Need Integer, found %s", index, acpi_ut_get_object_type_name(obj_desc))); return_ACPI_STATUS(AE_BAD_DATA); @@ -352,7 +355,7 @@ acpi_rs_create_pci_routing_table(union a top_object_list++; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", output_buffer->pointer, (u32) output_buffer->length)); return_ACPI_STATUS(AE_OK); } @@ -382,9 +385,9 @@ acpi_rs_create_aml_resources(struct acpi acpi_status status; acpi_size aml_size_needed = 0; - ACPI_FUNCTION_TRACE("rs_create_aml_resources"); + ACPI_FUNCTION_TRACE(rs_create_aml_resources); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "linked_list_buffer = %p\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "LinkedListBuffer = %p\n", linked_list_buffer)); /* @@ -395,7 +398,7 @@ acpi_rs_create_aml_resources(struct acpi */ status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_size_needed=%X, %s\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n", (u32) aml_size_needed, acpi_format_exception(status))); if (ACPI_FAILURE(status)) { @@ -419,7 +422,7 @@ acpi_rs_create_aml_resources(struct acpi return_ACPI_STATUS(status); } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n", output_buffer->pointer, (u32) output_buffer->length)); return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c index e7de061..9c99a72 100644 --- a/drivers/acpi/resources/rsdump.c +++ b/drivers/acpi/resources/rsdump.c @@ -91,11 +91,11 @@ #define ACPI_RSD_TABLE_SIZE(name) (siz struct acpi_rsdump_info acpi_rs_dump_irq[6] = { {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", - acpi_gbl_HEdecode}, + acpi_gbl_he_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", - acpi_gbl_LLdecode}, + acpi_gbl_ll_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing", - acpi_gbl_SHRdecode}, + acpi_gbl_shr_decode}, {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count), "Interrupt Count", NULL}, {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]), @@ -105,11 +105,11 @@ struct acpi_rsdump_info acpi_rs_dump_irq struct acpi_rsdump_info acpi_rs_dump_dma[6] = { {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed", - acpi_gbl_TYPdecode}, + acpi_gbl_typ_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering", - acpi_gbl_BMdecode}, + acpi_gbl_bm_decode}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type", - acpi_gbl_SIZdecode}, + acpi_gbl_siz_decode}, {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count", NULL}, {ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List", @@ -158,7 +158,7 @@ struct acpi_rsdump_info acpi_rs_dump_ven }; struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = { - {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "end_tag", + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag", NULL} }; @@ -166,7 +166,7 @@ struct acpi_rsdump_info acpi_rs_dump_mem {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24), "24-Bit Memory Range", NULL}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect), - "Write Protect", acpi_gbl_RWdecode}, + "Write Protect", acpi_gbl_rw_decode}, {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum", NULL}, {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum", @@ -181,7 +181,7 @@ struct acpi_rsdump_info acpi_rs_dump_mem {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32), "32-Bit Memory Range", NULL}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect), - "Write Protect", acpi_gbl_RWdecode}, + "Write Protect", acpi_gbl_rw_decode}, {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum", NULL}, {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum", @@ -196,7 +196,7 @@ struct acpi_rsdump_info acpi_rs_dump_fix {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32), "32-Bit Fixed Memory Range", NULL}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect), - "Write Protect", acpi_gbl_RWdecode}, + "Write Protect", acpi_gbl_rw_decode}, {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address", NULL}, {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length), @@ -278,11 +278,11 @@ struct acpi_rsdump_info acpi_rs_dump_ext {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer), "Type", acpi_gbl_consume_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering), - "Triggering", acpi_gbl_HEdecode}, + "Triggering", acpi_gbl_he_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity", - acpi_gbl_LLdecode}, + acpi_gbl_ll_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing", - acpi_gbl_SHRdecode}, + acpi_gbl_shr_decode}, {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL, NULL}, {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count), @@ -314,7 +314,7 @@ static struct acpi_rsdump_info acpi_rs_d {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer), "Consumer/Producer", acpi_gbl_consume_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode", - acpi_gbl_DECdecode}, + acpi_gbl_dec_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed), "Min Relocatability", acpi_gbl_min_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed), @@ -325,24 +325,24 @@ static struct acpi_rsdump_info acpi_rs_d {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags), "Resource Type", (void *)"Memory Range"}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect), - "Write Protect", acpi_gbl_RWdecode}, + "Write Protect", acpi_gbl_rw_decode}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching), - "Caching", acpi_gbl_MEMdecode}, + "Caching", acpi_gbl_mem_decode}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type), - "Range Type", acpi_gbl_MTPdecode}, + "Range Type", acpi_gbl_mtp_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation), - "Translation", acpi_gbl_TTPdecode} + "Translation", acpi_gbl_ttp_decode} }; static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = { {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags), "Resource Type", (void *)"I/O Range"}, {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type), - "Range Type", acpi_gbl_RNGdecode}, + "Range Type", acpi_gbl_rng_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation), - "Translation", acpi_gbl_TTPdecode}, + "Translation", acpi_gbl_ttp_decode}, {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type), - "Translation Type", acpi_gbl_TRSdecode} + "Translation Type", acpi_gbl_trs_decode} }; /* diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c index d9ae64b..9e7ae2f 100644 --- a/drivers/acpi/resources/rsinfo.c +++ b/drivers/acpi/resources/rsinfo.c @@ -141,6 +141,7 @@ struct acpi_rsdump_info *acpi_gbl_dump_r acpi_rs_dump_generic_reg, /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */ }; #endif + #endif /* ACPI_FUTURE_USAGE */ /* * Base sizes for external AML resource descriptors, indexed by internal type. diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c index 1434e78..29423ce 100644 --- a/drivers/acpi/resources/rslist.c +++ b/drivers/acpi/resources/rslist.c @@ -51,76 +51,62 @@ ACPI_MODULE_NAME("rslist") * * FUNCTION: acpi_rs_convert_aml_to_resources * - * PARAMETERS: Aml - Pointer to the resource byte stream - * aml_length - Length of Aml - * output_buffer - Pointer to the buffer that will - * contain the output structures + * PARAMETERS: acpi_walk_aml_callback + * resource_ptr - Pointer to the buffer that will + * contain the output structures * * RETURN: Status * - * DESCRIPTION: Takes the resource byte stream and parses it, creating a - * linked list of resources in the caller's output buffer + * DESCRIPTION: Convert an AML resource to an internal representation of the + * resource that is aligned and easier to access. * ******************************************************************************/ acpi_status -acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer) +acpi_rs_convert_aml_to_resources(u8 * aml, + u32 length, + u32 offset, u8 resource_index, void **context) { - struct acpi_resource *resource = (void *)output_buffer; + struct acpi_resource **resource_ptr = + ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context); + struct acpi_resource *resource; acpi_status status; - u8 resource_index; - u8 *end_aml; - - ACPI_FUNCTION_TRACE("rs_convert_aml_to_resources"); - - end_aml = aml + aml_length; - - /* Loop until end-of-buffer or an end_tag is found */ - - while (aml < end_aml) { - /* Validate the Resource Type and Resource Length */ - - status = acpi_ut_validate_resource(aml, &resource_index); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - /* Convert the AML byte stream resource to a local resource struct */ - - status = - acpi_rs_convert_aml_to_resource(resource, - ACPI_CAST_PTR(union - aml_resource, - aml), - acpi_gbl_get_resource_dispatch - [resource_index]); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not convert AML resource (Type %X)", - *aml)); - return_ACPI_STATUS(status); - } + ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources); - /* Normal exit on completion of an end_tag resource descriptor */ - - if (acpi_ut_get_resource_type(aml) == - ACPI_RESOURCE_NAME_END_TAG) { - return_ACPI_STATUS(AE_OK); - } - - /* Point to the next input AML resource */ - - aml += acpi_ut_get_descriptor_length(aml); - - /* Point to the next structure in the output buffer */ + /* + * Check that the input buffer and all subsequent pointers into it + * are aligned on a native word boundary. Most important on IA64 + */ + resource = *resource_ptr; + if (ACPI_IS_MISALIGNED(resource)) { + ACPI_WARNING((AE_INFO, + "Misaligned resource pointer %p", resource)); + } - resource = - ACPI_ADD_PTR(struct acpi_resource, resource, - resource->length); + /* Convert the AML byte stream resource to a local resource struct */ + + status = + acpi_rs_convert_aml_to_resource(resource, + ACPI_CAST_PTR(union aml_resource, + aml), + acpi_gbl_get_resource_dispatch + [resource_index]); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not convert AML resource (Type %X)", + *aml)); + return_ACPI_STATUS(status); } - /* Did not find an end_tag resource descriptor */ + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, + "Type %.2X, AmlLength %.2X InternalLength %.2X\n", + acpi_ut_get_resource_type(aml), length, + resource->length)); - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + /* Point to the next structure in the output buffer */ + + *resource_ptr = ACPI_ADD_PTR(void, resource, resource->length); + return_ACPI_STATUS(AE_OK); } /******************************************************************************* @@ -150,11 +136,12 @@ acpi_rs_convert_resources_to_aml(struct u8 *end_aml = output_buffer + aml_size_needed; acpi_status status; - ACPI_FUNCTION_TRACE("rs_convert_resources_to_aml"); + ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml); /* Walk the resource descriptor list, convert each descriptor */ while (aml < end_aml) { + /* Validate the (internal) Resource Type */ if (resource->type > ACPI_RESOURCE_TYPE_MAX) { @@ -191,6 +178,7 @@ acpi_rs_convert_resources_to_aml(struct /* Check for end-of-list, normal exit */ if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { + /* An End Tag indicates the end of the input Resource Template */ return_ACPI_STATUS(AE_OK); diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c index ed866cf..faf6e10 100644 --- a/drivers/acpi/resources/rsmisc.c +++ b/drivers/acpi/resources/rsmisc.c @@ -81,9 +81,10 @@ acpi_rs_convert_aml_to_resource(struct a u16 item_count = 0; u16 temp16 = 0; - ACPI_FUNCTION_TRACE("rs_get_resource"); + ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource); if (((acpi_native_uint) resource) & 0x3) { + /* Each internal resource struct is expected to be 32-bit aligned */ ACPI_WARNING((AE_INFO, @@ -295,9 +296,11 @@ acpi_rs_convert_aml_to_resource(struct a exit: if (!flags_mode) { - /* Round the resource struct length up to the next 32-bit boundary */ - resource->length = ACPI_ROUND_UP_to_32_bITS(resource->length); + /* Round the resource struct length up to the next boundary (32 or 64) */ + + resource->length = + (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length); } return_ACPI_STATUS(AE_OK); } @@ -329,7 +332,7 @@ acpi_rs_convert_resource_to_aml(struct a u16 temp16 = 0; u16 item_count = 0; - ACPI_FUNCTION_TRACE("rs_convert_resource_to_aml"); + ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml); /* * First table entry must be ACPI_RSC_INITxxx and must contain the @@ -535,6 +538,7 @@ if (((aml->irq.flags & 0x09) == 0x00) || resource->data.extended_irq.interrupt_count = temp8; if (temp8 < 1) { + /* Must have at least one IRQ */ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index 25b5aed..a9cbee8 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -205,6 +205,7 @@ acpi_rs_set_resource_length(acpi_rsdesc_ /* Length is stored differently for large and small descriptors */ if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) { + /* Large descriptor -- bytes 1-2 contain the 16-bit length */ ACPI_MOVE_16_TO_16(&aml->large_header.resource_length, @@ -298,7 +299,8 @@ static u16 acpi_rs_strcpy(char *destinat * string_ptr - (optional) where to store the actual * resource_source string * - * RETURN: Length of the string plus NULL terminator, rounded up to 32 bit + * RETURN: Length of the string plus NULL terminator, rounded up to native + * word boundary * * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor * to an internal resource descriptor @@ -328,6 +330,7 @@ acpi_rs_get_resource_source(acpi_rs_leng * we add 1 to the minimum length. */ if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) { + /* Get the resource_source_index */ resource_source->index = aml_resource_source[0]; @@ -344,23 +347,26 @@ acpi_rs_get_resource_source(acpi_rs_leng } /* - * In order for the struct_size to fall on a 32-bit boundary, calculate - * the length of the string (+1 for the NULL terminator) and expand the - * struct_size to the next 32-bit boundary. + * In order for the Resource length to be a multiple of the native + * word, calculate the length of the string (+1 for NULL terminator) + * and expand to the next word multiple. * * Zero the entire area of the buffer. */ total_length = - ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN - ((char *)&aml_resource_source[1]) + - 1); + (u32) + ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + + 1; + total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); + ACPI_MEMSET(resource_source->string_ptr, 0, total_length); /* Copy the resource_source string to the destination */ resource_source->string_length = acpi_rs_strcpy(resource_source->string_ptr, - (char *)&aml_resource_source[1]); + ACPI_CAST_PTR(char, + &aml_resource_source[1])); return ((acpi_rs_length) total_length); } @@ -405,6 +411,7 @@ acpi_rs_set_resource_source(union aml_re /* Non-zero string length indicates presence of a resource_source */ if (resource_source->string_length) { + /* Point to the end of the AML descriptor */ aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); @@ -415,7 +422,7 @@ acpi_rs_set_resource_source(union aml_re /* Copy the resource_source string */ - ACPI_STRCPY((char *)&aml_resource_source[1], + ACPI_STRCPY(ACPI_CAST_PTR(char, &aml_resource_source[1]), resource_source->string_ptr); /* @@ -435,9 +442,9 @@ acpi_rs_set_resource_source(union aml_re * * FUNCTION: acpi_rs_get_prt_method_data * - * PARAMETERS: Handle - a handle to the containing object - * ret_buffer - a pointer to a buffer structure for the - * results + * PARAMETERS: Node - Device node + * ret_buffer - Pointer to a buffer structure for the + * results * * RETURN: Status * @@ -450,18 +457,19 @@ acpi_rs_set_resource_source(union aml_re ******************************************************************************/ acpi_status -acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer) +acpi_rs_get_prt_method_data(struct acpi_namespace_node * node, + struct acpi_buffer * ret_buffer) { union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("rs_get_prt_method_data"); + ACPI_FUNCTION_TRACE(rs_get_prt_method_data); /* Parameters guaranteed valid by caller */ /* Execute the method, no parameters */ - status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRT, + status = acpi_ut_evaluate_object(node, METHOD_NAME__PRT, ACPI_BTYPE_PACKAGE, &obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -483,9 +491,9 @@ acpi_rs_get_prt_method_data(acpi_handle * * FUNCTION: acpi_rs_get_crs_method_data * - * PARAMETERS: Handle - a handle to the containing object - * ret_buffer - a pointer to a buffer structure for the - * results + * PARAMETERS: Node - Device node + * ret_buffer - Pointer to a buffer structure for the + * results * * RETURN: Status * @@ -498,18 +506,19 @@ acpi_rs_get_prt_method_data(acpi_handle ******************************************************************************/ acpi_status -acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) +acpi_rs_get_crs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *ret_buffer) { union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("rs_get_crs_method_data"); + ACPI_FUNCTION_TRACE(rs_get_crs_method_data); /* Parameters guaranteed valid by caller */ /* Execute the method, no parameters */ - status = acpi_ut_evaluate_object(handle, METHOD_NAME__CRS, + status = acpi_ut_evaluate_object(node, METHOD_NAME__CRS, ACPI_BTYPE_BUFFER, &obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -522,7 +531,7 @@ acpi_rs_get_crs_method_data(acpi_handle */ status = acpi_rs_create_resource_list(obj_desc, ret_buffer); - /* on exit, we must delete the object returned by evaluate_object */ + /* On exit, we must delete the object returned by evaluate_object */ acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); @@ -532,9 +541,9 @@ acpi_rs_get_crs_method_data(acpi_handle * * FUNCTION: acpi_rs_get_prs_method_data * - * PARAMETERS: Handle - a handle to the containing object - * ret_buffer - a pointer to a buffer structure for the - * results + * PARAMETERS: Node - Device node + * ret_buffer - Pointer to a buffer structure for the + * results * * RETURN: Status * @@ -548,18 +557,19 @@ acpi_rs_get_crs_method_data(acpi_handle #ifdef ACPI_FUTURE_USAGE acpi_status -acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) +acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *ret_buffer) { union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("rs_get_prs_method_data"); + ACPI_FUNCTION_TRACE(rs_get_prs_method_data); /* Parameters guaranteed valid by caller */ /* Execute the method, no parameters */ - status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRS, + status = acpi_ut_evaluate_object(node, METHOD_NAME__PRS, ACPI_BTYPE_BUFFER, &obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -572,7 +582,7 @@ acpi_rs_get_prs_method_data(acpi_handle */ status = acpi_rs_create_resource_list(obj_desc, ret_buffer); - /* on exit, we must delete the object returned by evaluate_object */ + /* On exit, we must delete the object returned by evaluate_object */ acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); @@ -583,10 +593,10 @@ #endif /* ACPI_FUTURE_USAGE */ * * FUNCTION: acpi_rs_get_method_data * - * PARAMETERS: Handle - a handle to the containing object + * PARAMETERS: Handle - Handle to the containing object * Path - Path to method, relative to Handle - * ret_buffer - a pointer to a buffer structure for the - * results + * ret_buffer - Pointer to a buffer structure for the + * results * * RETURN: Status * @@ -605,7 +615,7 @@ acpi_rs_get_method_data(acpi_handle hand union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("rs_get_method_data"); + ACPI_FUNCTION_TRACE(rs_get_method_data); /* Parameters guaranteed valid by caller */ @@ -634,9 +644,9 @@ acpi_rs_get_method_data(acpi_handle hand * * FUNCTION: acpi_rs_set_srs_method_data * - * PARAMETERS: Handle - a handle to the containing object - * in_buffer - a pointer to a buffer structure of the - * parameter + * PARAMETERS: Node - Device node + * in_buffer - Pointer to a buffer structure of the + * parameter * * RETURN: Status * @@ -646,23 +656,37 @@ acpi_rs_get_method_data(acpi_handle hand * If the function fails an appropriate status will be returned * and the contents of the callers buffer is undefined. * + * Note: Parameters guaranteed valid by caller + * ******************************************************************************/ acpi_status -acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer) +acpi_rs_set_srs_method_data(struct acpi_namespace_node *node, + struct acpi_buffer *in_buffer) { - struct acpi_parameter_info info; - union acpi_operand_object *params[2]; + struct acpi_evaluate_info *info; + union acpi_operand_object *args[2]; acpi_status status; struct acpi_buffer buffer; - ACPI_FUNCTION_TRACE("rs_set_srs_method_data"); + ACPI_FUNCTION_TRACE(rs_set_srs_method_data); - /* Parameters guaranteed valid by caller */ + /* Allocate and initialize the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->prefix_node = node; + info->pathname = METHOD_NAME__SRS; + info->parameters = args; + info->parameter_type = ACPI_PARAM_ARGS; + info->flags = ACPI_IGNORE_RETURN_VALUE; /* * The in_buffer parameter will point to a linked list of - * resource parameters. It needs to be formatted into a + * resource parameters. It needs to be formatted into a * byte stream to be sent in as an input parameter to _SRS * * Convert the linked list into a byte stream @@ -670,41 +694,36 @@ acpi_rs_set_srs_method_data(acpi_handle buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto cleanup; } - /* Init the param object */ + /* Create and initialize the method parameter object */ - params[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); - if (!params[0]) { - acpi_os_free(buffer.pointer); - return_ACPI_STATUS(AE_NO_MEMORY); + args[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); + if (!args[0]) { + /* + * Must free the buffer allocated above (otherwise it is freed + * later) + */ + ACPI_FREE(buffer.pointer); + status = AE_NO_MEMORY; + goto cleanup; } - /* Set up the parameter object */ - - params[0]->buffer.length = (u32) buffer.length; - params[0]->buffer.pointer = buffer.pointer; - params[0]->common.flags = AOPOBJ_DATA_VALID; - params[1] = NULL; - - info.node = handle; - info.parameters = params; - info.parameter_type = ACPI_PARAM_ARGS; + args[0]->buffer.length = (u32) buffer.length; + args[0]->buffer.pointer = buffer.pointer; + args[0]->common.flags = AOPOBJ_DATA_VALID; + args[1] = NULL; - /* Execute the method, no return value */ + /* Execute the method, no return value is expected */ - status = acpi_ns_evaluate_relative(METHOD_NAME__SRS, &info); - if (ACPI_SUCCESS(status)) { - /* Delete any return object (especially if implicit_return is enabled) */ + status = acpi_ns_evaluate(info); - if (info.return_object) { - acpi_ut_remove_reference(info.return_object); - } - } + /* Clean up and return the status from acpi_ns_evaluate */ - /* Clean up and return the status from acpi_ns_evaluate_relative */ + acpi_ut_remove_reference(args[0]); - acpi_ut_remove_reference(params[0]); + cleanup: + ACPI_FREE(info); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index 88b6707..1999e2a 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c @@ -41,10 +41,9 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include +#include #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rsxface") @@ -68,312 +67,262 @@ #define ACPI_COPY_ADDRESS(out, in) static acpi_status acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context); +static acpi_status +acpi_rs_validate_parameters(acpi_handle device_handle, + struct acpi_buffer *buffer, + struct acpi_namespace_node **return_node); + /******************************************************************************* * - * FUNCTION: acpi_get_irq_routing_table + * FUNCTION: acpi_rs_validate_parameters * - * PARAMETERS: device_handle - a handle to the Bus device we are querying - * ret_buffer - a pointer to a buffer to receive the - * current resources for the device + * PARAMETERS: device_handle - Handle to a device + * Buffer - Pointer to a data buffer + * return_node - Pointer to where the device node is returned * * RETURN: Status * - * DESCRIPTION: This function is called to get the IRQ routing table for a - * specific bus. The caller must first acquire a handle for the - * desired bus. The routine table is placed in the buffer pointed - * to by the ret_buffer variable parameter. - * - * If the function fails an appropriate status will be returned - * and the value of ret_buffer is undefined. - * - * This function attempts to execute the _PRT method contained in - * the object indicated by the passed device_handle. + * DESCRIPTION: Common parameter validation for resource interfaces * ******************************************************************************/ -acpi_status -acpi_get_irq_routing_table(acpi_handle device_handle, - struct acpi_buffer *ret_buffer) +static acpi_status +acpi_rs_validate_parameters(acpi_handle device_handle, + struct acpi_buffer *buffer, + struct acpi_namespace_node **return_node) { acpi_status status; + struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE("acpi_get_irq_routing_table "); + ACPI_FUNCTION_TRACE(rs_validate_parameters); /* - * Must have a valid handle and buffer, So we have to have a handle - * and a return buffer structure, and if there is a non-zero buffer length - * we also need a valid pointer in the buffer. If it's a zero buffer length, - * we'll be returning the needed buffer size, so keep going. + * Must have a valid handle to an ACPI device */ if (!device_handle) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_ut_validate_buffer(ret_buffer); + node = acpi_ns_map_handle_to_node(device_handle); + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (node->type != ACPI_TYPE_DEVICE) { + return_ACPI_STATUS(AE_TYPE); + } + + /* + * Validate the user buffer object + * + * if there is a non-zero buffer length we also need a valid pointer in + * the buffer. If it's a zero buffer length, we'll be returning the + * needed buffer size (later), so keep going. + */ + status = acpi_ut_validate_buffer(buffer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_rs_get_prt_method_data(device_handle, ret_buffer); - return_ACPI_STATUS(status); + *return_node = node; + return_ACPI_STATUS(AE_OK); } /******************************************************************************* * - * FUNCTION: acpi_get_current_resources + * FUNCTION: acpi_get_irq_routing_table * - * PARAMETERS: device_handle - a handle to the device object for the - * device we are querying - * ret_buffer - a pointer to a buffer to receive the + * PARAMETERS: device_handle - Handle to the Bus device we are querying + * ret_buffer - Pointer to a buffer to receive the * current resources for the device * * RETURN: Status * - * DESCRIPTION: This function is called to get the current resources for a - * specific device. The caller must first acquire a handle for - * the desired device. The resource data is placed in the buffer - * pointed to by the ret_buffer variable parameter. + * DESCRIPTION: This function is called to get the IRQ routing table for a + * specific bus. The caller must first acquire a handle for the + * desired bus. The routine table is placed in the buffer pointed + * to by the ret_buffer variable parameter. * * If the function fails an appropriate status will be returned * and the value of ret_buffer is undefined. * - * This function attempts to execute the _CRS method contained in + * This function attempts to execute the _PRT method contained in * the object indicated by the passed device_handle. * ******************************************************************************/ acpi_status -acpi_get_current_resources(acpi_handle device_handle, +acpi_get_irq_routing_table(acpi_handle device_handle, struct acpi_buffer *ret_buffer) { acpi_status status; + struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE("acpi_get_current_resources"); + ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table); - /* - * Must have a valid handle and buffer, So we have to have a handle - * and a return buffer structure, and if there is a non-zero buffer length - * we also need a valid pointer in the buffer. If it's a zero buffer length, - * we'll be returning the needed buffer size, so keep going. - */ - if (!device_handle) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } + /* Validate parameters then dispatch to internal routine */ - status = acpi_ut_validate_buffer(ret_buffer); + status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_rs_get_crs_method_data(device_handle, ret_buffer); + status = acpi_rs_get_prt_method_data(node, ret_buffer); return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_current_resources); +ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table) /******************************************************************************* * - * FUNCTION: acpi_get_possible_resources + * FUNCTION: acpi_get_current_resources * - * PARAMETERS: device_handle - a handle to the device object for the + * PARAMETERS: device_handle - Handle to the device object for the * device we are querying - * ret_buffer - a pointer to a buffer to receive the - * resources for the device + * ret_buffer - Pointer to a buffer to receive the + * current resources for the device * * RETURN: Status * - * DESCRIPTION: This function is called to get a list of the possible resources - * for a specific device. The caller must first acquire a handle - * for the desired device. The resource data is placed in the - * buffer pointed to by the ret_buffer variable. + * DESCRIPTION: This function is called to get the current resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is placed in the buffer + * pointed to by the ret_buffer variable parameter. * * If the function fails an appropriate status will be returned * and the value of ret_buffer is undefined. * + * This function attempts to execute the _CRS method contained in + * the object indicated by the passed device_handle. + * ******************************************************************************/ - -#ifdef ACPI_FUTURE_USAGE acpi_status -acpi_get_possible_resources(acpi_handle device_handle, - struct acpi_buffer *ret_buffer) +acpi_get_current_resources(acpi_handle device_handle, + struct acpi_buffer *ret_buffer) { acpi_status status; + struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE("acpi_get_possible_resources"); + ACPI_FUNCTION_TRACE(acpi_get_current_resources); - /* - * Must have a valid handle and buffer, So we have to have a handle - * and a return buffer structure, and if there is a non-zero buffer length - * we also need a valid pointer in the buffer. If it's a zero buffer length, - * we'll be returning the needed buffer size, so keep going. - */ - if (!device_handle) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } + /* Validate parameters then dispatch to internal routine */ - status = acpi_ut_validate_buffer(ret_buffer); + status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_rs_get_prs_method_data(device_handle, ret_buffer); + status = acpi_rs_get_crs_method_data(node, ret_buffer); return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_possible_resources); -#endif /* ACPI_FUTURE_USAGE */ +ACPI_EXPORT_SYMBOL(acpi_get_current_resources) +#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * - * FUNCTION: acpi_walk_resources + * FUNCTION: acpi_get_possible_resources * * PARAMETERS: device_handle - Handle to the device object for the * device we are querying - * Name - Method name of the resources we want - * (METHOD_NAME__CRS or METHOD_NAME__PRS) - * user_function - Called for each resource - * Context - Passed to user_function + * ret_buffer - Pointer to a buffer to receive the + * resources for the device * * RETURN: Status * - * DESCRIPTION: Retrieves the current or possible resource list for the - * specified device. The user_function is called once for - * each resource in the list. + * DESCRIPTION: This function is called to get a list of the possible resources + * for a specific device. The caller must first acquire a handle + * for the desired device. The resource data is placed in the + * buffer pointed to by the ret_buffer variable. + * + * If the function fails an appropriate status will be returned + * and the value of ret_buffer is undefined. * ******************************************************************************/ - acpi_status -acpi_walk_resources(acpi_handle device_handle, - char *name, - ACPI_WALK_RESOURCE_CALLBACK user_function, void *context) +acpi_get_possible_resources(acpi_handle device_handle, + struct acpi_buffer *ret_buffer) { acpi_status status; - struct acpi_buffer buffer; - struct acpi_resource *resource; - struct acpi_resource *resource_end; - - ACPI_FUNCTION_TRACE("acpi_walk_resources"); - - /* Parameter validation */ + struct acpi_namespace_node *node; - if (!device_handle || !user_function || !name || - (ACPI_STRNCMP(name, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) && - ACPI_STRNCMP(name, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } + ACPI_FUNCTION_TRACE(acpi_get_possible_resources); - /* Get the _CRS or _PRS resource list */ + /* Validate parameters then dispatch to internal routine */ - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_rs_get_method_data(device_handle, name, &buffer); + status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - /* Buffer now contains the resource list */ - - resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); - resource_end = - ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); - - /* Walk the resource list until the end_tag is found (or buffer end) */ - - while (resource < resource_end) { - /* Sanity check the resource */ - - if (resource->type > ACPI_RESOURCE_TYPE_MAX) { - status = AE_AML_INVALID_RESOURCE_TYPE; - break; - } - - /* Invoke the user function, abort on any error returned */ - - status = user_function(resource, context); - if (ACPI_FAILURE(status)) { - if (status == AE_CTRL_TERMINATE) { - /* This is an OK termination by the user function */ - - status = AE_OK; - } - break; - } - - /* end_tag indicates end-of-list */ - - if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { - break; - } - - /* Get the next resource descriptor */ - - resource = - ACPI_ADD_PTR(struct acpi_resource, resource, - resource->length); - } - - ACPI_MEM_FREE(buffer.pointer); + status = acpi_rs_get_prs_method_data(node, ret_buffer); return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_walk_resources); +ACPI_EXPORT_SYMBOL(acpi_get_possible_resources) +#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* * * FUNCTION: acpi_set_current_resources * - * PARAMETERS: device_handle - a handle to the device object for the - * device we are changing the resources of - * in_buffer - a pointer to a buffer containing the + * PARAMETERS: device_handle - Handle to the device object for the + * device we are setting resources + * in_buffer - Pointer to a buffer containing the * resources to be set for the device * * RETURN: Status * * DESCRIPTION: This function is called to set the current resources for a - * specific device. The caller must first acquire a handle for - * the desired device. The resource data is passed to the routine + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is passed to the routine * the buffer pointed to by the in_buffer variable. * ******************************************************************************/ - acpi_status acpi_set_current_resources(acpi_handle device_handle, struct acpi_buffer *in_buffer) { acpi_status status; + struct acpi_namespace_node *node; - ACPI_FUNCTION_TRACE("acpi_set_current_resources"); + ACPI_FUNCTION_TRACE(acpi_set_current_resources); - /* Must have a valid handle and buffer */ + /* Validate the buffer, don't allow zero length */ - if ((!device_handle) || - (!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) { + if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_rs_set_srs_method_data(device_handle, in_buffer); + /* Validate parameters then dispatch to internal routine */ + + status = acpi_rs_validate_parameters(device_handle, in_buffer, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_rs_set_srs_method_data(node, in_buffer); return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_set_current_resources); +ACPI_EXPORT_SYMBOL(acpi_set_current_resources) /****************************************************************************** * * FUNCTION: acpi_resource_to_address64 * - * PARAMETERS: Resource - Pointer to a resource - * Out - Pointer to the users's return - * buffer (a struct - * struct acpi_resource_address64) + * PARAMETERS: Resource - Pointer to a resource + * Out - Pointer to the users's return buffer + * (a struct acpi_resource_address64) * * RETURN: Status * * DESCRIPTION: If the resource is an address16, address32, or address64, - * copy it to the address64 return buffer. This saves the + * copy it to the address64 return buffer. This saves the * caller from having to duplicate code for different-sized * addresses. * ******************************************************************************/ - acpi_status acpi_resource_to_address64(struct acpi_resource *resource, struct acpi_resource_address64 *out) @@ -415,18 +364,18 @@ acpi_resource_to_address64(struct acpi_r return (AE_OK); } -EXPORT_SYMBOL(acpi_resource_to_address64); +ACPI_EXPORT_SYMBOL(acpi_resource_to_address64) /******************************************************************************* * * FUNCTION: acpi_get_vendor_resource * - * PARAMETERS: device_handle - Handle for the parent device object - * Name - Method name for the parent resource - * (METHOD_NAME__CRS or METHOD_NAME__PRS) - * Uuid - Pointer to the UUID to be matched. - * includes both subtype and 16-byte UUID - * ret_buffer - Where the vendor resource is returned + * PARAMETERS: device_handle - Handle for the parent device object + * Name - Method name for the parent resource + * (METHOD_NAME__CRS or METHOD_NAME__PRS) + * Uuid - Pointer to the UUID to be matched. + * includes both subtype and 16-byte UUID + * ret_buffer - Where the vendor resource is returned * * RETURN: Status * @@ -435,7 +384,6 @@ EXPORT_SYMBOL(acpi_resource_to_address64 * UUID subtype. Returns a struct acpi_resource of type Vendor. * ******************************************************************************/ - acpi_status acpi_get_vendor_resource(acpi_handle device_handle, char *name, @@ -467,18 +415,19 @@ acpi_get_vendor_resource(acpi_handle dev return (info.status); } +ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource) + /******************************************************************************* * * FUNCTION: acpi_rs_match_vendor_resource * - * PARAMETERS: ACPI_WALK_RESOURCE_CALLBACK + * PARAMETERS: acpi_walk_resource_callback * * RETURN: Status * * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID * ******************************************************************************/ - static acpi_status acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) { @@ -526,3 +475,101 @@ acpi_rs_match_vendor_resource(struct acp info->status = AE_OK; return (AE_CTRL_TERMINATE); } + +ACPI_EXPORT_SYMBOL(acpi_rs_match_vendor_resource) + +/******************************************************************************* + * + * FUNCTION: acpi_walk_resources + * + * PARAMETERS: device_handle - Handle to the device object for the + * device we are querying + * Name - Method name of the resources we want + * (METHOD_NAME__CRS or METHOD_NAME__PRS) + * user_function - Called for each resource + * Context - Passed to user_function + * + * RETURN: Status + * + * DESCRIPTION: Retrieves the current or possible resource list for the + * specified device. The user_function is called once for + * each resource in the list. + * + ******************************************************************************/ + +acpi_status +acpi_walk_resources(acpi_handle device_handle, + char *name, + acpi_walk_resource_callback user_function, void *context) +{ + acpi_status status; + struct acpi_buffer buffer; + struct acpi_resource *resource; + struct acpi_resource *resource_end; + + ACPI_FUNCTION_TRACE(acpi_walk_resources); + + /* Parameter validation */ + + if (!device_handle || !user_function || !name || + (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && + !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the _CRS or _PRS resource list */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_rs_get_method_data(device_handle, name, &buffer); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Buffer now contains the resource list */ + + resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); + resource_end = + ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); + + /* Walk the resource list until the end_tag is found (or buffer end) */ + + while (resource < resource_end) { + + /* Sanity check the resource */ + + if (resource->type > ACPI_RESOURCE_TYPE_MAX) { + status = AE_AML_INVALID_RESOURCE_TYPE; + break; + } + + /* Invoke the user function, abort on any error returned */ + + status = user_function(resource, context); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_TERMINATE) { + + /* This is an OK termination by the user function */ + + status = AE_OK; + } + break; + } + + /* end_tag indicates end-of-list */ + + if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { + break; + } + + /* Get the next resource descriptor */ + + resource = + ACPI_ADD_PTR(struct acpi_resource, resource, + resource->length); + } + + ACPI_FREE(buffer.pointer); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_walk_resources) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a0ab828..f8316a0 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -142,7 +142,7 @@ static void acpi_device_register(struct create_sysfs_device_files(device); } -static int acpi_device_unregister(struct acpi_device *device, int type) +static void acpi_device_unregister(struct acpi_device *device, int type) { spin_lock(&acpi_device_lock); if (device->parent) { @@ -158,7 +158,6 @@ static int acpi_device_unregister(struct acpi_detach_data(device->handle, acpi_bus_data_handler); remove_sysfs_device_files(device); kobject_unregister(&device->kobj); - return 0; } void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) @@ -234,12 +233,9 @@ static int acpi_bus_get_power_flags(stru int acpi_match_ids(struct acpi_device *device, char *ids) { - int error = 0; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - if (device->flags.hardware_id) if (strstr(ids, device->pnp.hardware_id)) - goto Done; + return 0; if (device->flags.compatible_ids) { struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; @@ -248,15 +244,10 @@ int acpi_match_ids(struct acpi_device *d /* compare multiple _CID entries against driver ids */ for (i = 0; i < cid_list->count; i++) { if (strstr(ids, cid_list->id[i].value)) - goto Done; + return 0; } } - error = -ENOENT; - - Done: - if (buffer.pointer) - acpi_os_free(buffer.pointer); - return error; + return -ENOENT; } static acpi_status @@ -441,10 +432,7 @@ #endif islockable = device->flags.lockable; handle = device->handle; - if (type == ACPI_TYPE_PROCESSOR) - result = acpi_bus_trim(device, 0); - else - result = acpi_bus_trim(device, 1); + result = acpi_bus_trim(device, 1); if (!result) result = acpi_eject_operation(handle, islockable); @@ -471,7 +459,6 @@ static int acpi_bus_get_perf_flags(struc -------------------------------------------------------------------------- */ static LIST_HEAD(acpi_bus_drivers); -static DECLARE_MUTEX(acpi_bus_drivers_lock); /** * acpi_bus_match - match device IDs to driver's supported IDs @@ -548,10 +535,9 @@ static int acpi_start_single_object(stru return_VALUE(result); } -static int acpi_driver_attach(struct acpi_driver *drv) +static void acpi_driver_attach(struct acpi_driver *drv) { struct list_head *node, *next; - int count = 0; ACPI_FUNCTION_TRACE("acpi_driver_attach"); @@ -568,7 +554,6 @@ static int acpi_driver_attach(struct acp if (!acpi_bus_driver_init(dev, drv)) { acpi_start_single_object(dev); atomic_inc(&drv->references); - count++; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", drv->name, dev->pnp.bus_id)); @@ -577,10 +562,9 @@ static int acpi_driver_attach(struct acp spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock); - return_VALUE(count); } -static int acpi_driver_detach(struct acpi_driver *drv) +static void acpi_driver_detach(struct acpi_driver *drv) { struct list_head *node, *next; @@ -602,7 +586,6 @@ static int acpi_driver_detach(struct acp } } spin_unlock(&acpi_device_lock); - return_VALUE(0); } /** @@ -610,28 +593,22 @@ static int acpi_driver_detach(struct acp * @driver: driver being registered * * Registers a driver with the ACPI bus. Searches the namespace for all - * devices that match the driver's criteria and binds. Returns the - * number of devices that were claimed by the driver, or a negative - * error status for failure. + * devices that match the driver's criteria and binds. Returns zero for + * success or a negative error status for failure. */ int acpi_bus_register_driver(struct acpi_driver *driver) { - int count; - ACPI_FUNCTION_TRACE("acpi_bus_register_driver"); if (acpi_disabled) return_VALUE(-ENODEV); - if (!driver) - return_VALUE(-EINVAL); - spin_lock(&acpi_device_lock); list_add_tail(&driver->node, &acpi_bus_drivers); spin_unlock(&acpi_device_lock); - count = acpi_driver_attach(driver); + acpi_driver_attach(driver); - return_VALUE(count); + return_VALUE(0); } EXPORT_SYMBOL(acpi_bus_register_driver); @@ -643,23 +620,16 @@ EXPORT_SYMBOL(acpi_bus_register_driver); * Unregisters a driver with the ACPI bus. Searches the namespace for all * devices that match the driver's criteria and unbinds. */ -int acpi_bus_unregister_driver(struct acpi_driver *driver) +void acpi_bus_unregister_driver(struct acpi_driver *driver) { - int error = 0; + acpi_driver_detach(driver); - ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver"); - - if (driver) { - acpi_driver_detach(driver); - - if (!atomic_read(&driver->references)) { - spin_lock(&acpi_device_lock); - list_del_init(&driver->node); - spin_unlock(&acpi_device_lock); - } - } else - error = -EINVAL; - return_VALUE(error); + if (!atomic_read(&driver->references)) { + spin_lock(&acpi_device_lock); + list_del_init(&driver->node); + spin_unlock(&acpi_device_lock); + } + return; } EXPORT_SYMBOL(acpi_bus_unregister_driver); @@ -1371,6 +1341,100 @@ static int acpi_bus_scan_fixed(struct ac return_VALUE(result); } + +static inline struct acpi_device * to_acpi_dev(struct device * dev) +{ + return container_of(dev, struct acpi_device, dev); +} + + +static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state) +{ + struct acpi_device * dev, * next; + int result; + + spin_lock(&acpi_device_lock); + list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { + if (dev->driver && dev->driver->ops.suspend) { + spin_unlock(&acpi_device_lock); + result = dev->driver->ops.suspend(dev, 0); + if (result) { + printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n", + acpi_device_name(dev), + acpi_device_bid(dev), result); + } + spin_lock(&acpi_device_lock); + } + } + spin_unlock(&acpi_device_lock); + return 0; +} + + +static int acpi_device_suspend(struct device * dev, pm_message_t state) +{ + struct acpi_device * acpi_dev = to_acpi_dev(dev); + + /* + * For now, we should only register 1 generic device - + * the ACPI root device - and from there, we walk the + * tree of ACPI devices to suspend each one using the + * ACPI driver methods. + */ + if (acpi_dev->handle == ACPI_ROOT_OBJECT) + root_suspend(acpi_dev, state); + return 0; +} + + + +static int root_resume(struct acpi_device * acpi_dev) +{ + struct acpi_device * dev, * next; + int result; + + spin_lock(&acpi_device_lock); + list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { + if (dev->driver && dev->driver->ops.resume) { + spin_unlock(&acpi_device_lock); + result = dev->driver->ops.resume(dev, 0); + if (result) { + printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", + acpi_device_name(dev), + acpi_device_bid(dev), result); + } + spin_lock(&acpi_device_lock); + } + } + spin_unlock(&acpi_device_lock); + return 0; +} + + +static int acpi_device_resume(struct device * dev) +{ + struct acpi_device * acpi_dev = to_acpi_dev(dev); + + /* + * For now, we should only register 1 generic device - + * the ACPI root device - and from there, we walk the + * tree of ACPI devices to resume each one using the + * ACPI driver methods. + */ + if (acpi_dev->handle == ACPI_ROOT_OBJECT) + root_resume(acpi_dev); + return 0; +} + + +struct bus_type acpi_bus_type = { + .name = "acpi", + .suspend = acpi_device_suspend, + .resume = acpi_device_resume, +}; + + + static int __init acpi_scan_init(void) { int result; @@ -1383,6 +1447,12 @@ static int __init acpi_scan_init(void) kset_register(&acpi_namespace_kset); + result = bus_register(&acpi_bus_type); + if (result) { + /* We don't want to quit even if we failed to add suspend/resume */ + printk(KERN_ERR PREFIX "Could not register bus type\n"); + } + /* * Create the root device in the bus's device tree */ @@ -1392,6 +1462,16 @@ static int __init acpi_scan_init(void) goto Done; result = acpi_start_single_object(acpi_root); + if (result) + goto Done; + + acpi_root->dev.bus = &acpi_bus_type; + snprintf(acpi_root->dev.bus_id, BUS_ID_SIZE, "%s", acpi_bus_type.name); + result = device_register(&acpi_root->dev); + if (result) { + /* We don't want to quit even if we failed to add suspend/resume */ + printk(KERN_ERR PREFIX "Could not register device\n"); + } /* * Enumerate devices in the ACPI namespace. diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 930427f..62ce87d 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -105,6 +105,14 @@ static int acpi_pm_enter(suspend_state_t default: return -EINVAL; } + + /* ACPI 3.0 specs (P62) says that it's the responsabilty + * of the OSPM to clear the status bit [ implying that the + * POWER_BUTTON event should not reach userspace ] + */ + if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) + acpi_clear_event(ACPI_EVENT_POWER_BUTTON); + local_irq_restore(flags); printk(KERN_DEBUG "Back to C!\n"); diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 85df0ce..af1dbab 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c @@ -155,7 +155,6 @@ static int __init acpi_wakeup_device_ini if (acpi_disabled) return 0; - printk("ACPI wakeup devices: \n"); spin_lock(&acpi_device_lock); list_for_each_safe(node, next, &acpi_wakeup_device_list) { @@ -174,10 +173,8 @@ static int __init acpi_wakeup_device_ini dev->wakeup.state.enabled = 1; spin_lock(&acpi_device_lock); } - printk("%4s ", dev->pnp.bus_id); } spin_unlock(&acpi_device_lock); - printk("\n"); return 0; } diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index e4308c7..a934ac4 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -39,7 +39,7 @@ #define ACPI_SYSTEM_FILE_INFO "info" #define ACPI_SYSTEM_FILE_EVENT "event" #define ACPI_SYSTEM_FILE_DSDT "dsdt" #define ACPI_SYSTEM_FILE_FADT "fadt" -extern FADT_DESCRIPTOR acpi_fadt; +extern struct fadt_descriptor acpi_fadt; /* -------------------------------------------------------------------------- FS Interface (/proc) @@ -82,7 +82,7 @@ acpi_system_read_dsdt(struct file *file, ACPI_FUNCTION_TRACE("acpi_system_read_dsdt"); - status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt); + status = acpi_get_table(ACPI_TABLE_ID_DSDT, 1, &dsdt); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); @@ -110,7 +110,7 @@ acpi_system_read_fadt(struct file *file, ACPI_FUNCTION_TRACE("acpi_system_read_fadt"); - status = acpi_get_table(ACPI_TABLE_FADT, 1, &fadt); + status = acpi_get_table(ACPI_TABLE_ID_FADT, 1, &fadt); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 7f37c7c..ed5e881 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -282,8 +282,8 @@ acpi_get_table_header_early(enum acpi_ta /* Map the DSDT header via the pointer in the FADT */ if (id == ACPI_DSDT) { - struct fadt_descriptor_rev2 *fadt = - (struct fadt_descriptor_rev2 *)*header; + struct fadt_descriptor *fadt = + (struct fadt_descriptor *)*header; if (fadt->revision == 3 && fadt->Xdsdt) { *header = (void *)__acpi_map_table(fadt->Xdsdt, diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c index 03b37d2..d697fcb 100644 --- a/drivers/acpi/tables/tbconvrt.c +++ b/drivers/acpi/tables/tbconvrt.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include @@ -56,15 +54,15 @@ acpi_tb_init_generic_address(struct acpi acpi_physical_address address); static void -acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt, +acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt, struct fadt_descriptor_rev1 *original_fadt); static void -acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt, - struct fadt_descriptor_rev2 *original_fadt); +acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt, + struct fadt_descriptor *original_fadt); u8 acpi_fadt_is_v1; -EXPORT_SYMBOL(acpi_fadt_is_v1); +ACPI_EXPORT_SYMBOL(acpi_fadt_is_v1) /******************************************************************************* * @@ -122,7 +120,7 @@ acpi_status acpi_tb_convert_to_xsdt(stru { acpi_size table_size; u32 i; - XSDT_DESCRIPTOR *new_table; + struct xsdt_descriptor *new_table; ACPI_FUNCTION_ENTRY(); @@ -133,7 +131,7 @@ acpi_status acpi_tb_convert_to_xsdt(stru /* Allocate an XSDT */ - new_table = ACPI_MEM_CALLOCATE(table_size); + new_table = ACPI_ALLOCATE_ZEROED(table_size); if (!new_table) { return (AE_NO_MEMORY); } @@ -147,17 +145,18 @@ acpi_status acpi_tb_convert_to_xsdt(stru /* Copy the table pointers */ for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { + /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { ACPI_STORE_ADDRESS(new_table->table_offset_entry[i], (ACPI_CAST_PTR - (struct rsdt_descriptor_rev1, + (struct rsdt_descriptor, table_info->pointer))-> table_offset_entry[i]); } else { new_table->table_offset_entry[i] = - (ACPI_CAST_PTR(XSDT_DESCRIPTOR, + (ACPI_CAST_PTR(struct xsdt_descriptor, table_info->pointer))-> table_offset_entry[i]; } @@ -219,7 +218,7 @@ acpi_tb_init_generic_address(struct acpi ******************************************************************************/ static void -acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt, +acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt, struct fadt_descriptor_rev1 *original_fadt) { @@ -365,14 +364,13 @@ acpi_tb_convert_fadt1(struct fadt_descri ******************************************************************************/ static void -acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt, - struct fadt_descriptor_rev2 *original_fadt) +acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt, + struct fadt_descriptor *original_fadt) { /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */ - ACPI_MEMCPY(local_fadt, original_fadt, - sizeof(struct fadt_descriptor_rev2)); + ACPI_MEMCPY(local_fadt, original_fadt, sizeof(struct fadt_descriptor)); /* * "X" fields are optional extensions to the original V1.0 fields, so @@ -491,10 +489,10 @@ acpi_tb_convert_fadt2(struct fadt_descri acpi_status acpi_tb_convert_table_fadt(void) { - struct fadt_descriptor_rev2 *local_fadt; + struct fadt_descriptor *local_fadt; struct acpi_table_desc *table_desc; - ACPI_FUNCTION_TRACE("tb_convert_table_fadt"); + ACPI_FUNCTION_TRACE(tb_convert_table_fadt); /* * acpi_gbl_FADT is valid. Validate the FADT length. The table must be @@ -508,13 +506,14 @@ acpi_status acpi_tb_convert_table_fadt(v /* Allocate buffer for the ACPI 2.0(+) FADT */ - local_fadt = ACPI_MEM_CALLOCATE(sizeof(struct fadt_descriptor_rev2)); + local_fadt = ACPI_ALLOCATE_ZEROED(sizeof(struct fadt_descriptor)); if (!local_fadt) { return_ACPI_STATUS(AE_NO_MEMORY); } if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) { - if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev2)) { + if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor)) { + /* Length is too short to be a V2.0 table */ ACPI_WARNING((AE_INFO, @@ -538,11 +537,11 @@ acpi_status acpi_tb_convert_table_fadt(v /* Global FADT pointer will point to the new common V2.0 FADT */ acpi_gbl_FADT = local_fadt; - acpi_gbl_FADT->length = sizeof(FADT_DESCRIPTOR); + acpi_gbl_FADT->length = sizeof(struct fadt_descriptor); /* Free the original table */ - table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next; + table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_FADT].next; acpi_tb_delete_single_table(table_desc); /* Install the new table */ @@ -550,7 +549,7 @@ acpi_status acpi_tb_convert_table_fadt(v table_desc->pointer = ACPI_CAST_PTR(struct acpi_table_header, acpi_gbl_FADT); table_desc->allocation = ACPI_MEM_ALLOCATED; - table_desc->length = sizeof(struct fadt_descriptor_rev2); + table_desc->length = sizeof(struct fadt_descriptor); /* Dump the entire FADT */ @@ -580,7 +579,7 @@ acpi_status acpi_tb_convert_table_fadt(v acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info) { - ACPI_FUNCTION_TRACE("tb_build_common_facs"); + ACPI_FUNCTION_TRACE(tb_build_common_facs); /* Absolute minimum length is 24, but the ACPI spec says 64 */ @@ -603,6 +602,7 @@ acpi_status acpi_tb_build_common_facs(st if ((acpi_gbl_RSDP->revision < 2) || (acpi_gbl_FACS->length < 32) || (!(acpi_gbl_FACS->xfirmware_waking_vector))) { + /* ACPI 1.0 FACS or short table or optional X_ field is zero */ acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR(u64, diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c index 09b4ee6..99eacce 100644 --- a/drivers/acpi/tables/tbget.c +++ b/drivers/acpi/tables/tbget.c @@ -78,7 +78,7 @@ acpi_tb_get_table(struct acpi_pointer *a acpi_status status; struct acpi_table_header header; - ACPI_FUNCTION_TRACE("tb_get_table"); + ACPI_FUNCTION_TRACE(tb_get_table); /* Get the header in order to get signature and table size */ @@ -124,7 +124,7 @@ acpi_tb_get_table_header(struct acpi_poi acpi_status status = AE_OK; struct acpi_table_header *header = NULL; - ACPI_FUNCTION_TRACE("tb_get_table_header"); + ACPI_FUNCTION_TRACE(tb_get_table_header); /* * Flags contains the current processor mode (Virtual or Physical @@ -148,6 +148,10 @@ acpi_tb_get_table_header(struct acpi_poi sizeof(struct acpi_table_header), (void *)&header); if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, + "Could not map memory at %8.8X%8.8X for table header", + ACPI_FORMAT_UINT64(address->pointer. + physical))); return_ACPI_STATUS(status); } @@ -198,7 +202,7 @@ acpi_tb_get_table_body(struct acpi_point { acpi_status status; - ACPI_FUNCTION_TRACE("tb_get_table_body"); + ACPI_FUNCTION_TRACE(tb_get_table_body); if (!table_info || !address) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -208,6 +212,7 @@ acpi_tb_get_table_body(struct acpi_point status = acpi_tb_table_override(header, table_info); if (ACPI_SUCCESS(status)) { + /* Table was overridden by the host OS */ return_ACPI_STATUS(status); @@ -241,7 +246,7 @@ acpi_tb_table_override(struct acpi_table acpi_status status; struct acpi_pointer address; - ACPI_FUNCTION_TRACE("tb_table_override"); + ACPI_FUNCTION_TRACE(tb_table_override); /* * The OSL will examine the header and decide whether to override this @@ -250,6 +255,7 @@ acpi_tb_table_override(struct acpi_table */ status = acpi_os_table_override(header, &new_table); if (ACPI_FAILURE(status)) { + /* Some severe error from the OSL, but we basically ignore it */ ACPI_EXCEPTION((AE_INFO, status, @@ -258,6 +264,7 @@ acpi_tb_table_override(struct acpi_table } if (!new_table) { + /* No table override */ return_ACPI_STATUS(AE_NO_ACPI_TABLES); @@ -311,7 +318,7 @@ acpi_tb_get_this_table(struct acpi_point u8 allocation; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("tb_get_this_table"); + ACPI_FUNCTION_TRACE(tb_get_this_table); /* * Flags contains the current processor mode (Virtual or Physical @@ -323,7 +330,7 @@ acpi_tb_get_this_table(struct acpi_point /* Pointer matches processor mode, copy the table to a new buffer */ - full_table = ACPI_MEM_ALLOCATE(header->length); + full_table = ACPI_ALLOCATE(header->length); if (!full_table) { ACPI_ERROR((AE_INFO, "Could not allocate table memory for [%4.4s] length %X", @@ -376,11 +383,12 @@ acpi_tb_get_this_table(struct acpi_point * Validate checksum for _most_ tables, * even the ones whose signature we don't recognize */ - if (table_info->type != ACPI_TABLE_FACS) { + if (table_info->type != ACPI_TABLE_ID_FACS) { status = acpi_tb_verify_table_checksum(full_table); #if (!ACPI_CHECKSUM_ABORT) if (ACPI_FAILURE(status)) { + /* Ignore the error if configuration says so */ status = AE_OK; @@ -409,7 +417,7 @@ #endif * * PARAMETERS: table_type - one of the defined table types * Instance - Which table of this type - * table_ptr_loc - pointer to location to place the pointer for + * return_table - pointer to location to place the pointer for * return * * RETURN: Status @@ -420,57 +428,34 @@ #endif acpi_status acpi_tb_get_table_ptr(acpi_table_type table_type, - u32 instance, struct acpi_table_header **table_ptr_loc) + u32 instance, struct acpi_table_header **return_table) { struct acpi_table_desc *table_desc; u32 i; - ACPI_FUNCTION_TRACE("tb_get_table_ptr"); - - if (!acpi_gbl_DSDT) { - return_ACPI_STATUS(AE_NO_ACPI_TABLES); - } + ACPI_FUNCTION_TRACE(tb_get_table_ptr); - if (table_type > ACPI_TABLE_MAX) { + if (table_type > ACPI_TABLE_ID_MAX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* - * For all table types (Single/Multiple), the first - * instance is always in the list head. - */ - if (instance == 1) { - /* Get the first */ - - *table_ptr_loc = NULL; - if (acpi_gbl_table_lists[table_type].next) { - *table_ptr_loc = - acpi_gbl_table_lists[table_type].next->pointer; - } - return_ACPI_STATUS(AE_OK); - } - - /* Check for instance out of range */ + /* Check for instance out of range of the current table count */ if (instance > acpi_gbl_table_lists[table_type].count) { return_ACPI_STATUS(AE_NOT_EXIST); } - /* Walk the list to get the desired table - * Since the if (Instance == 1) check above checked for the - * first table, setting table_desc equal to the .Next member - * is actually pointing to the second table. Therefore, we - * need to walk from the 2nd table until we reach the Instance - * that the user is looking for and return its table pointer. + /* + * Walk the list to get the desired table + * Note: Instance is one-based */ table_desc = acpi_gbl_table_lists[table_type].next; - for (i = 2; i < instance; i++) { + for (i = 1; i < instance; i++) { table_desc = table_desc->next; } /* We are now pointing to the requested table's descriptor */ - *table_ptr_loc = table_desc->pointer; - + *return_table = table_desc->pointer; return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c index 134e5dc..ad98211 100644 --- a/drivers/acpi/tables/tbgetall.c +++ b/drivers/acpi/tables/tbgetall.c @@ -77,7 +77,7 @@ acpi_tb_get_primary_table(struct acpi_po acpi_status status; struct acpi_table_header header; - ACPI_FUNCTION_TRACE("tb_get_primary_table"); + ACPI_FUNCTION_TRACE(tb_get_primary_table); /* Ignore a NULL address in the RSDT */ @@ -140,7 +140,7 @@ acpi_tb_get_secondary_table(struct acpi_ acpi_status status; struct acpi_table_header header; - ACPI_FUNCTION_TRACE_STR("tb_get_secondary_table", signature); + ACPI_FUNCTION_TRACE_STR(tb_get_secondary_table, signature); /* Get the header in order to match the signature */ @@ -151,7 +151,7 @@ acpi_tb_get_secondary_table(struct acpi_ /* Signature must match request */ - if (ACPI_STRNCMP(header.signature, signature, ACPI_NAME_SIZE)) { + if (!ACPI_COMPARE_NAME(header.signature, signature)) { ACPI_ERROR((AE_INFO, "Incorrect table signature - wanted [%s] found [%4.4s]", signature, header.signature)); @@ -207,7 +207,7 @@ acpi_status acpi_tb_get_required_tables( struct acpi_table_desc table_info; struct acpi_pointer address; - ACPI_FUNCTION_TRACE("tb_get_required_tables"); + ACPI_FUNCTION_TRACE(tb_get_required_tables); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%d ACPI tables in RSDT\n", acpi_gbl_rsdt_table_count)); @@ -223,6 +223,7 @@ acpi_status acpi_tb_get_required_tables( * any SSDTs. */ for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { + /* Get the table address from the common internal XSDT */ address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i]; @@ -305,6 +306,6 @@ acpi_status acpi_tb_get_required_tables( /* Always delete the RSDP mapping, we are done with it */ - acpi_tb_delete_tables_by_type(ACPI_TABLE_RSDP); + acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_RSDP); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 7ffd0fd..7ca2df7 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -73,17 +73,18 @@ acpi_tb_match_signature(char *signature, { acpi_native_uint i; - ACPI_FUNCTION_TRACE("tb_match_signature"); + ACPI_FUNCTION_TRACE(tb_match_signature); /* Search for a signature match among the known table types */ - for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { + for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { if (!(acpi_gbl_table_data[i].flags & search_type)) { continue; } if (!ACPI_STRNCMP(signature, acpi_gbl_table_data[i].signature, acpi_gbl_table_data[i].sig_length)) { + /* Found a signature match, return index if requested */ if (table_info) { @@ -122,7 +123,7 @@ acpi_status acpi_tb_install_table(struct { acpi_status status; - ACPI_FUNCTION_TRACE("tb_install_table"); + ACPI_FUNCTION_TRACE(tb_install_table); /* Lock tables while installing */ @@ -187,7 +188,7 @@ acpi_tb_recognize_table(struct acpi_tabl struct acpi_table_header *table_header; acpi_status status; - ACPI_FUNCTION_TRACE("tb_recognize_table"); + ACPI_FUNCTION_TRACE(tb_recognize_table); /* Ensure that we have a valid table pointer */ @@ -218,7 +219,6 @@ acpi_tb_recognize_table(struct acpi_tabl /* Return the table type and length via the info struct */ table_info->length = (acpi_size) table_header->length; - return_ACPI_STATUS(status); } @@ -243,11 +243,11 @@ acpi_tb_init_table_descriptor(acpi_table struct acpi_table_desc *table_desc; acpi_status status; - ACPI_FUNCTION_TRACE_U32("tb_init_table_descriptor", table_type); + ACPI_FUNCTION_TRACE_U32(tb_init_table_descriptor, table_type); /* Allocate a descriptor for this table */ - table_desc = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc)); + table_desc = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); if (!table_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -274,7 +274,7 @@ acpi_tb_init_table_descriptor(acpi_table * at this location, so return an error. */ if (list_head->next) { - ACPI_MEM_FREE(table_desc); + ACPI_FREE(table_desc); return_ACPI_STATUS(AE_ALREADY_EXISTS); } @@ -312,15 +312,14 @@ acpi_tb_init_table_descriptor(acpi_table /* Finish initialization of the table descriptor */ + table_desc->loaded_into_namespace = FALSE; table_desc->type = (u8) table_type; table_desc->pointer = table_info->pointer; table_desc->length = table_info->length; table_desc->allocation = table_info->allocation; table_desc->aml_start = (u8 *) (table_desc->pointer + 1), - table_desc->aml_length = (u32) (table_desc->length - - (u32) sizeof(struct - acpi_table_header)); - table_desc->loaded_into_namespace = FALSE; + table_desc->aml_length = (u32) + (table_desc->length - (u32) sizeof(struct acpi_table_header)); /* * Set the appropriate global pointer (if there is one) to point to the @@ -335,7 +334,6 @@ acpi_tb_init_table_descriptor(acpi_table table_info->owner_id = table_desc->owner_id; table_info->installed_desc = table_desc; - return_ACPI_STATUS(AE_OK); } @@ -359,7 +357,7 @@ void acpi_tb_delete_all_tables(void) * Free memory allocated for ACPI tables * Memory can either be mapped or allocated */ - for (type = 0; type < NUM_ACPI_TABLE_TYPES; type++) { + for (type = 0; type < (ACPI_TABLE_ID_MAX + 1); type++) { acpi_tb_delete_tables_by_type(type); } } @@ -383,9 +381,9 @@ void acpi_tb_delete_tables_by_type(acpi_ u32 count; u32 i; - ACPI_FUNCTION_TRACE_U32("tb_delete_tables_by_type", type); + ACPI_FUNCTION_TRACE_U32(tb_delete_tables_by_type, type); - if (type > ACPI_TABLE_MAX) { + if (type > ACPI_TABLE_ID_MAX) { return_VOID; } @@ -396,28 +394,28 @@ void acpi_tb_delete_tables_by_type(acpi_ /* Clear the appropriate "typed" global table pointer */ switch (type) { - case ACPI_TABLE_RSDP: + case ACPI_TABLE_ID_RSDP: acpi_gbl_RSDP = NULL; break; - case ACPI_TABLE_DSDT: + case ACPI_TABLE_ID_DSDT: acpi_gbl_DSDT = NULL; break; - case ACPI_TABLE_FADT: + case ACPI_TABLE_ID_FADT: acpi_gbl_FADT = NULL; break; - case ACPI_TABLE_FACS: + case ACPI_TABLE_ID_FACS: acpi_gbl_FACS = NULL; break; - case ACPI_TABLE_XSDT: + case ACPI_TABLE_ID_XSDT: acpi_gbl_XSDT = NULL; break; - case ACPI_TABLE_SSDT: - case ACPI_TABLE_PSDT: + case ACPI_TABLE_ID_SSDT: + case ACPI_TABLE_ID_PSDT: default: break; } @@ -471,7 +469,7 @@ void acpi_tb_delete_single_table(struct case ACPI_MEM_ALLOCATED: - ACPI_MEM_FREE(table_desc->pointer); + ACPI_FREE(table_desc->pointer); break; case ACPI_MEM_MAPPED: @@ -503,7 +501,7 @@ struct acpi_table_desc *acpi_tb_uninstal { struct acpi_table_desc *next_desc; - ACPI_FUNCTION_TRACE_PTR("tb_uninstall_table", table_desc); + ACPI_FUNCTION_TRACE_PTR(tb_uninstall_table, table_desc); if (!table_desc) { return_PTR(NULL); @@ -530,7 +528,7 @@ struct acpi_table_desc *acpi_tb_uninstal /* Free the table descriptor */ next_desc = table_desc->next; - ACPI_MEM_FREE(table_desc); + ACPI_FREE(table_desc); /* Return pointer to the next descriptor */ diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c index 4d30822..abcb08c 100644 --- a/drivers/acpi/tables/tbrsdt.c +++ b/drivers/acpi/tables/tbrsdt.c @@ -64,7 +64,7 @@ acpi_status acpi_tb_verify_rsdp(struct a acpi_status status; struct rsdp_descriptor *rsdp; - ACPI_FUNCTION_TRACE("tb_verify_rsdp"); + ACPI_FUNCTION_TRACE(tb_verify_rsdp); switch (address->pointer_type) { case ACPI_LOGICAL_POINTER: @@ -78,7 +78,7 @@ acpi_status acpi_tb_verify_rsdp(struct a */ status = acpi_os_map_memory(address->pointer.physical, sizeof(struct rsdp_descriptor), - (void *)&rsdp); + ACPI_CAST_PTR(void, &rsdp)); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -95,15 +95,20 @@ acpi_status acpi_tb_verify_rsdp(struct a goto cleanup; } - /* The RSDP supplied is OK */ + /* RSDP is ok. Init the table info */ table_info.pointer = ACPI_CAST_PTR(struct acpi_table_header, rsdp); table_info.length = sizeof(struct rsdp_descriptor); - table_info.allocation = ACPI_MEM_MAPPED; + + if (address->pointer_type == ACPI_PHYSICAL_POINTER) { + table_info.allocation = ACPI_MEM_MAPPED; + } else { + table_info.allocation = ACPI_MEM_NOT_ALLOCATED; + } /* Save the table pointers and allocation info */ - status = acpi_tb_init_table_descriptor(ACPI_TABLE_RSDP, &table_info); + status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_RSDP, &table_info); if (ACPI_FAILURE(status)) { goto cleanup; } @@ -174,22 +179,20 @@ void acpi_tb_get_rsdt_address(struct acp acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr) { - int no_match; + char *signature; ACPI_FUNCTION_ENTRY(); - /* - * Search for appropriate signature, RSDT or XSDT - */ + /* Search for appropriate signature, RSDT or XSDT */ + if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { - no_match = ACPI_STRNCMP((char *)table_ptr, RSDT_SIG, - sizeof(RSDT_SIG) - 1); + signature = RSDT_SIG; } else { - no_match = ACPI_STRNCMP((char *)table_ptr, XSDT_SIG, - sizeof(XSDT_SIG) - 1); + signature = XSDT_SIG; } - if (no_match) { + if (!ACPI_COMPARE_NAME(table_ptr->signature, signature)) { + /* Invalid RSDT or XSDT signature */ ACPI_ERROR((AE_INFO, @@ -198,10 +201,8 @@ acpi_status acpi_tb_validate_rsdt(struct ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20); ACPI_ERROR((AE_INFO, - "RSDT/XSDT signature at %X (%p) is invalid", - acpi_gbl_RSDP->rsdt_physical_address, - (void *)(acpi_native_uint) acpi_gbl_RSDP-> - rsdt_physical_address)); + "RSDT/XSDT signature at %X is invalid", + acpi_gbl_RSDP->rsdt_physical_address)); if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { ACPI_ERROR((AE_INFO, "Looking for RSDT")); @@ -234,13 +235,13 @@ acpi_status acpi_tb_get_table_rsdt(void) acpi_status status; struct acpi_pointer address; - ACPI_FUNCTION_TRACE("tb_get_table_rsdt"); + ACPI_FUNCTION_TRACE(tb_get_table_rsdt); /* Get the RSDT/XSDT via the RSDP */ acpi_tb_get_rsdt_address(&address); - table_info.type = ACPI_TABLE_XSDT; + table_info.type = ACPI_TABLE_ID_XSDT; status = acpi_tb_get_table(&address, &table_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, @@ -274,12 +275,13 @@ acpi_status acpi_tb_get_table_rsdt(void) /* Save the table pointers and allocation info */ - status = acpi_tb_init_table_descriptor(ACPI_TABLE_XSDT, &table_info); + status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_XSDT, &table_info); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - acpi_gbl_XSDT = ACPI_CAST_PTR(XSDT_DESCRIPTOR, table_info.pointer); + acpi_gbl_XSDT = + ACPI_CAST_PTR(struct xsdt_descriptor, table_info.pointer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT)); return_ACPI_STATUS(status); diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index bc57159..209a401 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -71,7 +71,7 @@ acpi_status acpi_tb_is_table_installed(s { struct acpi_table_desc *table_desc; - ACPI_FUNCTION_TRACE("tb_is_table_installed"); + ACPI_FUNCTION_TRACE(tb_is_table_installed); /* Get the list descriptor and first table descriptor */ @@ -96,10 +96,11 @@ acpi_status acpi_tb_is_table_installed(s (!ACPI_MEMCMP (table_desc->pointer, new_table_desc->pointer, new_table_desc->pointer->length))) { + /* Match: this table is already installed */ ACPI_DEBUG_PRINT((ACPI_DB_TABLES, - "Table [%4.4s] already installed: Rev %X oem_table_id [%8.8s]\n", + "Table [%4.4s] already installed: Rev %X OemTableId [%8.8s]\n", new_table_desc->pointer->signature, new_table_desc->pointer->revision, new_table_desc->pointer-> @@ -159,12 +160,8 @@ acpi_tb_validate_table_header(struct acp ACPI_MOVE_32_TO_32(&signature, table_header->signature); if (!acpi_ut_valid_acpi_name(signature)) { - ACPI_ERROR((AE_INFO, - "Table signature at %p [%p] has invalid characters", - table_header, &signature)); - - ACPI_WARNING((AE_INFO, "Invalid table signature found: [%4.4s]", - ACPI_CAST_PTR(char, &signature))); + ACPI_ERROR((AE_INFO, "Invalid table signature 0x%8.8X", + signature)); ACPI_DUMP_BUFFER(table_header, sizeof(struct acpi_table_header)); @@ -175,12 +172,9 @@ acpi_tb_validate_table_header(struct acp if (table_header->length < sizeof(struct acpi_table_header)) { ACPI_ERROR((AE_INFO, - "Invalid length in table header %p name %4.4s", - table_header, (char *)&signature)); - - ACPI_WARNING((AE_INFO, - "Invalid table header length (0x%X) found", - (u32) table_header->length)); + "Invalid length 0x%X in table with signature %4.4s", + (u32) table_header->length, + ACPI_CAST_PTR(char, &signature))); ACPI_DUMP_BUFFER(table_header, sizeof(struct acpi_table_header)); @@ -192,72 +186,119 @@ acpi_tb_validate_table_header(struct acp /******************************************************************************* * - * FUNCTION: acpi_tb_verify_table_checksum + * FUNCTION: acpi_tb_sum_table * - * PARAMETERS: *table_header - ACPI table to verify + * PARAMETERS: Buffer - Buffer to sum + * Length - Size of the buffer * - * RETURN: 8 bit checksum of table + * RETURN: 8 bit sum of buffer * - * DESCRIPTION: Does an 8 bit checksum of table and returns status. A correct - * table should have a checksum of 0. + * DESCRIPTION: Computes an 8 bit sum of the buffer(length) and returns it. * ******************************************************************************/ -acpi_status -acpi_tb_verify_table_checksum(struct acpi_table_header * table_header) +u8 acpi_tb_sum_table(void *buffer, u32 length) +{ + acpi_native_uint i; + u8 sum = 0; + + if (!buffer || !length) { + return (0); + } + + for (i = 0; i < length; i++) { + sum = (u8) (sum + ((u8 *) buffer)[i]); + } + return (sum); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_generate_checksum + * + * PARAMETERS: Table - Pointer to a valid ACPI table (with a + * standard ACPI header) + * + * RETURN: 8 bit checksum of buffer + * + * DESCRIPTION: Computes an 8 bit checksum of the table. + * + ******************************************************************************/ + +u8 acpi_tb_generate_checksum(struct acpi_table_header * table) { u8 checksum; - acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("tb_verify_table_checksum"); + /* Sum the entire table as-is */ - /* Compute the checksum on the table */ + checksum = acpi_tb_sum_table(table, table->length); - checksum = - acpi_tb_generate_checksum(table_header, table_header->length); + /* Subtract off the existing checksum value in the table */ - /* Return the appropriate exception */ + checksum = (u8) (checksum - table->checksum); - if (checksum) { - ACPI_WARNING((AE_INFO, - "Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)", - table_header->signature, - (u32) table_header->checksum, (u32) checksum)); + /* Compute the final checksum */ - status = AE_BAD_CHECKSUM; - } - return_ACPI_STATUS(status); + checksum = (u8) (0 - checksum); + return (checksum); } /******************************************************************************* * - * FUNCTION: acpi_tb_generate_checksum + * FUNCTION: acpi_tb_set_checksum * - * PARAMETERS: Buffer - Buffer to checksum - * Length - Size of the buffer + * PARAMETERS: Table - Pointer to a valid ACPI table (with a + * standard ACPI header) * - * RETURN: 8 bit checksum of buffer + * RETURN: None. Sets the table checksum field * - * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it. + * DESCRIPTION: Computes an 8 bit checksum of the table and inserts the + * checksum into the table header. * ******************************************************************************/ -u8 acpi_tb_generate_checksum(void *buffer, u32 length) +void acpi_tb_set_checksum(struct acpi_table_header *table) { - u8 *end_buffer; - u8 *rover; - u8 sum = 0; - if (buffer && length) { - /* Buffer and Length are valid */ + table->checksum = acpi_tb_generate_checksum(table); +} - end_buffer = ACPI_ADD_PTR(u8, buffer, length); +/******************************************************************************* + * + * FUNCTION: acpi_tb_verify_table_checksum + * + * PARAMETERS: *table_header - ACPI table to verify + * + * RETURN: 8 bit checksum of table + * + * DESCRIPTION: Generates an 8 bit checksum of table and returns and compares + * it to the existing checksum value. + * + ******************************************************************************/ - for (rover = buffer; rover < end_buffer; rover++) { - sum = (u8) (sum + *rover); - } +acpi_status +acpi_tb_verify_table_checksum(struct acpi_table_header *table_header) +{ + u8 checksum; + + ACPI_FUNCTION_TRACE(tb_verify_table_checksum); + + /* Compute the checksum on the table */ + + checksum = acpi_tb_generate_checksum(table_header); + + /* Checksum ok? */ + + if (checksum == table_header->checksum) { + return_ACPI_STATUS(AE_OK); } - return (sum); + + ACPI_WARNING((AE_INFO, + "Incorrect checksum in table [%4.4s] - is %2.2X, should be %2.2X", + table_header->signature, table_header->checksum, + checksum)); + + return_ACPI_STATUS(AE_BAD_CHECKSUM); } #ifdef ACPI_OBSOLETE_FUNCTIONS @@ -276,12 +317,12 @@ #ifdef ACPI_OBSOLETE_FUNCTIONS acpi_status acpi_tb_handle_to_object(u16 table_id, - struct acpi_table_desc ** return_table_desc) + struct acpi_table_desc **return_table_desc) { u32 i; struct acpi_table_desc *table_desc; - ACPI_FUNCTION_NAME("tb_handle_to_object"); + ACPI_FUNCTION_NAME(tb_handle_to_object); for (i = 0; i < ACPI_TABLE_MAX; i++) { table_desc = acpi_gbl_table_lists[i].next; @@ -295,7 +336,7 @@ acpi_tb_handle_to_object(u16 table_id, } } - ACPI_ERROR((AE_INFO, "table_id=%X does not exist", table_id)); + ACPI_ERROR((AE_INFO, "TableId=%X does not exist", table_id)); return (AE_BAD_PARAMETER); } #endif diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 9fe53c9..4e91f29 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -42,8 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -68,7 +66,7 @@ acpi_status acpi_load_tables(void) struct acpi_pointer rsdp_address; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_load_tables"); + ACPI_FUNCTION_TRACE(acpi_load_tables); /* Get the RSDP */ @@ -123,6 +121,8 @@ acpi_status acpi_load_tables(void) return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_load_tables) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -139,14 +139,13 @@ #ifdef ACPI_FUTURE_USAGE * is determined that the table is invalid, the call will fail. * ******************************************************************************/ - acpi_status acpi_load_table(struct acpi_table_header *table_ptr) { acpi_status status; struct acpi_table_desc table_info; struct acpi_pointer address; - ACPI_FUNCTION_TRACE("acpi_load_table"); + ACPI_FUNCTION_TRACE(acpi_load_table); if (!table_ptr) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -174,6 +173,7 @@ acpi_status acpi_load_table(struct acpi_ status = acpi_tb_install_table(&table_info); if (ACPI_FAILURE(status)) { if (status == AE_ALREADY_EXISTS) { + /* Table already exists, no error */ status = AE_OK; @@ -188,12 +188,12 @@ acpi_status acpi_load_table(struct acpi_ /* Convert the table to common format if necessary */ switch (table_info.type) { - case ACPI_TABLE_FADT: + case ACPI_TABLE_ID_FADT: status = acpi_tb_convert_table_fadt(); break; - case ACPI_TABLE_FACS: + case ACPI_TABLE_ID_FACS: status = acpi_tb_build_common_facs(&table_info); break; @@ -208,6 +208,7 @@ acpi_status acpi_load_table(struct acpi_ } if (ACPI_FAILURE(status)) { + /* Uninstall table and free the buffer */ (void)acpi_tb_uninstall_table(table_info.installed_desc); @@ -216,6 +217,8 @@ acpi_status acpi_load_table(struct acpi_ return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_load_table) + /******************************************************************************* * * FUNCTION: acpi_unload_table @@ -227,16 +230,15 @@ acpi_status acpi_load_table(struct acpi_ * DESCRIPTION: This routine is used to force the unload of a table * ******************************************************************************/ - acpi_status acpi_unload_table(acpi_table_type table_type) { struct acpi_table_desc *table_desc; - ACPI_FUNCTION_TRACE("acpi_unload_table"); + ACPI_FUNCTION_TRACE(acpi_unload_table); /* Parameter validation */ - if (table_type > ACPI_TABLE_MAX) { + if (table_type > ACPI_TABLE_ID_MAX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -261,6 +263,8 @@ acpi_status acpi_unload_table(acpi_table return_ACPI_STATUS(AE_OK); } +ACPI_EXPORT_SYMBOL(acpi_unload_table) + /******************************************************************************* * * FUNCTION: acpi_get_table_header @@ -281,7 +285,6 @@ acpi_status acpi_unload_table(acpi_table * have a standard header and is fixed length. * ******************************************************************************/ - acpi_status acpi_get_table_header(acpi_table_type table_type, u32 instance, struct acpi_table_header *out_table_header) @@ -289,16 +292,16 @@ acpi_get_table_header(acpi_table_type ta struct acpi_table_header *tbl_ptr; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_get_table_header"); + ACPI_FUNCTION_TRACE(acpi_get_table_header); if ((instance == 0) || - (table_type == ACPI_TABLE_RSDP) || (!out_table_header)) { + (table_type == ACPI_TABLE_ID_RSDP) || (!out_table_header)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Check the table type and instance */ - if ((table_type > ACPI_TABLE_MAX) || + if ((table_type > ACPI_TABLE_ID_MAX) || (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && instance > 1)) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -325,6 +328,7 @@ acpi_get_table_header(acpi_table_type ta return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_get_table_header) #endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* @@ -349,7 +353,6 @@ #endif /* ACPI_FUTURE_USAGE */ * a complete table including the header. * ******************************************************************************/ - acpi_status acpi_get_table(acpi_table_type table_type, u32 instance, struct acpi_buffer *ret_buffer) @@ -358,7 +361,7 @@ acpi_get_table(acpi_table_type table_typ acpi_status status; acpi_size table_length; - ACPI_FUNCTION_TRACE("acpi_get_table"); + ACPI_FUNCTION_TRACE(acpi_get_table); /* Parameter validation */ @@ -373,7 +376,7 @@ acpi_get_table(acpi_table_type table_typ /* Check the table type and instance */ - if ((table_type > ACPI_TABLE_MAX) || + if ((table_type > ACPI_TABLE_ID_MAX) || (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && instance > 1)) { return_ACPI_STATUS(AE_BAD_PARAMETER); @@ -396,7 +399,8 @@ acpi_get_table(acpi_table_type table_typ /* Get the table length */ - if (table_type == ACPI_TABLE_RSDP) { + if (table_type == ACPI_TABLE_ID_RSDP) { + /* RSD PTR is the only "table" without a header */ table_length = sizeof(struct rsdp_descriptor); @@ -417,4 +421,4 @@ acpi_get_table(acpi_table_type table_typ return_ACPI_STATUS(AE_OK); } -EXPORT_SYMBOL(acpi_get_table); +ACPI_EXPORT_SYMBOL(acpi_get_table) diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index a62db6a..da2648b 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include @@ -75,6 +73,7 @@ acpi_status acpi_tb_validate_rsdp(struct * The signature and checksum must both be correct */ if (ACPI_STRNCMP((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) { + /* Nope, BAD Signature */ return (AE_BAD_SIGNATURE); @@ -82,15 +81,14 @@ acpi_status acpi_tb_validate_rsdp(struct /* Check the standard checksum */ - if (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { + if (acpi_tb_sum_table(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { return (AE_BAD_CHECKSUM); } /* Check extended checksum if table version >= 2 */ if ((rsdp->revision >= 2) && - (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != - 0)) { + (acpi_tb_sum_table(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { return (AE_BAD_CHECKSUM); } @@ -121,7 +119,7 @@ acpi_tb_find_table(char *signature, acpi_status status; struct acpi_table_header *table; - ACPI_FUNCTION_TRACE("tb_find_table"); + ACPI_FUNCTION_TRACE(tb_find_table); /* Validate string lengths */ @@ -131,7 +129,7 @@ acpi_tb_find_table(char *signature, return_ACPI_STATUS(AE_AML_STRING_LIMIT); } - if (!ACPI_STRNCMP(signature, DSDT_SIG, ACPI_NAME_SIZE)) { + if (ACPI_COMPARE_NAME(signature, DSDT_SIG)) { /* * The DSDT pointer is contained in the FADT, not the RSDT. * This code should suffice, because the only code that would perform @@ -156,10 +154,12 @@ acpi_tb_find_table(char *signature, /* Check oem_id and oem_table_id */ - if ((oem_id[0] && ACPI_STRNCMP(oem_id, table->oem_id, - sizeof(table->oem_id))) || - (oem_table_id[0] && ACPI_STRNCMP(oem_table_id, table->oem_table_id, - sizeof(table->oem_table_id)))) { + if ((oem_id[0] && + ACPI_STRNCMP(oem_id, table->oem_id, + sizeof(table->oem_id))) || + (oem_table_id[0] && + ACPI_STRNCMP(oem_table_id, table->oem_table_id, + sizeof(table->oem_table_id)))) { return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND); } @@ -203,7 +203,7 @@ acpi_get_firmware_table(acpi_string sign u32 i; u32 j; - ACPI_FUNCTION_TRACE("acpi_get_firmware_table"); + ACPI_FUNCTION_TRACE(acpi_get_firmware_table); /* * Ensure that at least the table manager is initialized. We don't @@ -217,6 +217,7 @@ acpi_get_firmware_table(acpi_string sign /* Ensure that we have a RSDP */ if (!acpi_gbl_RSDP) { + /* Get the RSDP */ status = acpi_os_get_root_pointer(flags, &address); @@ -261,7 +262,7 @@ acpi_get_firmware_table(acpi_string sign /* Get and validate the RSDT */ - rsdt_info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc)); + rsdt_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); if (!rsdt_info) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -278,13 +279,13 @@ acpi_get_firmware_table(acpi_string sign /* Allocate a scratch table header and table descriptor */ - header = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_header)); + header = ACPI_ALLOCATE(sizeof(struct acpi_table_header)); if (!header) { status = AE_NO_MEMORY; goto cleanup; } - table_info = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_desc)); + table_info = ACPI_ALLOCATE(sizeof(struct acpi_table_desc)); if (!table_info) { status = AE_NO_MEMORY; goto cleanup; @@ -308,12 +309,12 @@ acpi_get_firmware_table(acpi_string sign if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { address.pointer.value = (ACPI_CAST_PTR - (RSDT_DESCRIPTOR, + (struct rsdt_descriptor, rsdt_info->pointer))->table_offset_entry[i]; } else { address.pointer.value = (ACPI_CAST_PTR - (XSDT_DESCRIPTOR, + (struct xsdt_descriptor, rsdt_info->pointer))->table_offset_entry[i]; } @@ -326,11 +327,13 @@ acpi_get_firmware_table(acpi_string sign /* Compare table signatures and table instance */ - if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) { + if (ACPI_COMPARE_NAME(header->signature, signature)) { + /* An instance of the table was found */ j++; if (j >= instance) { + /* Found the correct instance, get the entire table */ status = @@ -355,23 +358,21 @@ acpi_get_firmware_table(acpi_string sign acpi_os_unmap_memory(rsdt_info->pointer, (acpi_size) rsdt_info->pointer->length); } - ACPI_MEM_FREE(rsdt_info); + ACPI_FREE(rsdt_info); if (header) { - ACPI_MEM_FREE(header); + ACPI_FREE(header); } if (table_info) { - ACPI_MEM_FREE(table_info); + ACPI_FREE(table_info); } return_ACPI_STATUS(status); } -EXPORT_SYMBOL(acpi_get_firmware_table); +ACPI_EXPORT_SYMBOL(acpi_get_firmware_table) /* TBD: Move to a new file */ - #if ACPI_MACHINE_WIDTH != 16 - /******************************************************************************* * * FUNCTION: acpi_find_root_pointer @@ -384,13 +385,12 @@ #if ACPI_MACHINE_WIDTH != 16 * DESCRIPTION: Find the RSDP * ******************************************************************************/ - acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address) { struct acpi_table_desc table_info; acpi_status status; - ACPI_FUNCTION_TRACE("acpi_find_root_pointer"); + ACPI_FUNCTION_TRACE(acpi_find_root_pointer); /* Get the RSDP */ @@ -407,6 +407,8 @@ acpi_status acpi_find_root_pointer(u32 f return_ACPI_STATUS(AE_OK); } +ACPI_EXPORT_SYMBOL(acpi_find_root_pointer) + /******************************************************************************* * * FUNCTION: acpi_tb_scan_memory_for_rsdp @@ -419,14 +421,13 @@ acpi_status acpi_find_root_pointer(u32 f * DESCRIPTION: Search a block of memory for the RSDP signature * ******************************************************************************/ - static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) { acpi_status status; u8 *mem_rover; u8 *end_address; - ACPI_FUNCTION_TRACE("tb_scan_memory_for_rsdp"); + ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp); end_address = start_address + length; @@ -434,12 +435,14 @@ static u8 *acpi_tb_scan_memory_for_rsdp( for (mem_rover = start_address; mem_rover < end_address; mem_rover += ACPI_RSDP_SCAN_STEP) { + /* The RSDP signature and checksum must both be correct */ status = acpi_tb_validate_rsdp(ACPI_CAST_PTR (struct rsdp_descriptor, mem_rover)); if (ACPI_SUCCESS(status)) { + /* Sig and checksum valid, we have found a real RSDP */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -469,10 +472,10 @@ static u8 *acpi_tb_scan_memory_for_rsdp( * * RETURN: Status, RSDP physical address * - * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor + * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor * pointer structure. If it is found, set *RSDP to point to it. * - * NOTE1: The RSDp must be either in the first 1_k of the Extended + * NOTE1: The RSDP must be either in the first 1_k of the Extended * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) * Only a 32-bit physical address is necessary. * @@ -489,12 +492,13 @@ acpi_tb_find_rsdp(struct acpi_table_desc u32 physical_address; acpi_status status; - ACPI_FUNCTION_TRACE("tb_find_rsdp"); + ACPI_FUNCTION_TRACE(tb_find_rsdp); /* * Scan supports either logical addressing or physical addressing */ if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { + /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ status = acpi_os_map_memory((acpi_physical_address) @@ -521,7 +525,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc if (physical_address > 0x400) { /* - * 1b) Search EBDA paragraphs (EBDa is required to be a + * 1b) Search EBDA paragraphs (EBDA is required to be a * minimum of 1_k length) */ status = acpi_os_map_memory((acpi_physical_address) @@ -542,10 +546,11 @@ acpi_tb_find_rsdp(struct acpi_table_desc acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); if (mem_rover) { + /* Return the physical address */ physical_address += - ACPI_PTR_DIFF(mem_rover, table_ptr); + (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); table_info->physical_address = (acpi_physical_address) physical_address; @@ -576,11 +581,12 @@ acpi_tb_find_rsdp(struct acpi_table_desc acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); if (mem_rover) { + /* Return the physical address */ - physical_address = - ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF(mem_rover, - table_ptr); + physical_address = (u32) + (ACPI_HI_RSDP_WINDOW_BASE + + ACPI_PTR_DIFF(mem_rover, table_ptr)); table_info->physical_address = (acpi_physical_address) physical_address; @@ -601,7 +607,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc if (physical_address > 0x400) { /* - * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of + * 1b) Search EBDA paragraphs (EBDA is required to be a minimum of * 1_k length) */ mem_rover = @@ -609,6 +615,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc (physical_address), ACPI_EBDA_WINDOW_SIZE); if (mem_rover) { + /* Return the physical address */ table_info->physical_address = @@ -624,6 +631,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc (ACPI_HI_RSDP_WINDOW_BASE), ACPI_HI_RSDP_WINDOW_SIZE); if (mem_rover) { + /* Found it, return the physical address */ table_info->physical_address = diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 19f3ea4..e7fe3a1 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -82,6 +82,7 @@ MODULE_PARM_DESC(tzp, "Thermal zone poll static int acpi_thermal_add(struct acpi_device *device); static int acpi_thermal_remove(struct acpi_device *device, int type); +static int acpi_thermal_resume(struct acpi_device *device, int state); static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); @@ -103,6 +104,7 @@ static struct acpi_driver acpi_thermal_d .ops = { .add = acpi_thermal_add, .remove = acpi_thermal_remove, + .resume = acpi_thermal_resume, }, }; @@ -684,8 +686,7 @@ static void acpi_thermal_run(unsigned lo { struct acpi_thermal *tz = (struct acpi_thermal *)data; if (!tz->zombie) - acpi_os_queue_for_execution(OSD_PRIORITY_GPE, - acpi_thermal_check, (void *)data); + acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data); } static void acpi_thermal_check(void *data) @@ -942,8 +943,10 @@ acpi_thermal_write_trip_points(struct fi memset(limit_string, 0, ACPI_THERMAL_MAX_LIMIT_STR_LEN); active = kmalloc(ACPI_THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL); - if (!active) + if (!active) { + kfree(limit_string); return_VALUE(-ENOMEM); + } if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n")); @@ -1342,7 +1345,7 @@ static int acpi_thermal_add(struct acpi_ result = acpi_thermal_add_fs(device); if (result) - return_VALUE(result); + goto end; init_timer(&tz->timer); @@ -1416,6 +1419,20 @@ static int acpi_thermal_remove(struct ac return_VALUE(0); } +static int acpi_thermal_resume(struct acpi_device *device, int state) +{ + struct acpi_thermal *tz = NULL; + + if (!device || !acpi_driver_data(device)) + return_VALUE(-EINVAL); + + tz = (struct acpi_thermal *)acpi_driver_data(device); + + acpi_thermal_check(tz); + + return AE_OK; +} + static int __init acpi_thermal_init(void) { int result = 0; diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 03b0044..7940fc1 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c @@ -46,24 +46,6 @@ #include #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utalloc") -/* Local prototypes */ -#ifdef ACPI_DBG_TRACK_ALLOCATIONS -static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation); - -static acpi_status -acpi_ut_track_allocation(struct acpi_debug_mem_block *address, - acpi_size size, - u8 alloc_type, u32 component, char *module, u32 line); - -static acpi_status -acpi_ut_remove_allocation(struct acpi_debug_mem_block *address, - u32 component, char *module, u32 line); - -static acpi_status -acpi_ut_create_list(char *list_name, - u16 object_size, struct acpi_memory_list **return_cache); -#endif - /******************************************************************************* * * FUNCTION: acpi_ut_create_caches @@ -75,33 +57,23 @@ #endif * DESCRIPTION: Create all local caches * ******************************************************************************/ - acpi_status acpi_ut_create_caches(void) { acpi_status status; -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - - /* Memory allocation lists */ - - status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list); - if (ACPI_FAILURE(status)) { - return (status); - } + /* Object Caches, for frequently used objects */ status = - acpi_ut_create_list("Acpi-Namespace", - sizeof(struct acpi_namespace_node), - &acpi_gbl_ns_node_list); + acpi_os_create_cache("Acpi-Namespace", + sizeof(struct acpi_namespace_node), + ACPI_MAX_NAMESPACE_CACHE_DEPTH, + &acpi_gbl_namespace_cache); if (ACPI_FAILURE(status)) { return (status); } -#endif - - /* Object Caches, for frequently used objects */ status = - acpi_os_create_cache("acpi_state", sizeof(union acpi_generic_state), + acpi_os_create_cache("Acpi-State", sizeof(union acpi_generic_state), ACPI_MAX_STATE_CACHE_DEPTH, &acpi_gbl_state_cache); if (ACPI_FAILURE(status)) { @@ -109,7 +81,7 @@ #endif } status = - acpi_os_create_cache("acpi_parse", + acpi_os_create_cache("Acpi-Parse", sizeof(struct acpi_parse_obj_common), ACPI_MAX_PARSE_CACHE_DEPTH, &acpi_gbl_ps_node_cache); @@ -118,7 +90,7 @@ #endif } status = - acpi_os_create_cache("acpi_parse_ext", + acpi_os_create_cache("Acpi-ParseExt", sizeof(struct acpi_parse_obj_named), ACPI_MAX_EXTPARSE_CACHE_DEPTH, &acpi_gbl_ps_node_ext_cache); @@ -127,7 +99,7 @@ #endif } status = - acpi_os_create_cache("acpi_operand", + acpi_os_create_cache("Acpi-Operand", sizeof(union acpi_operand_object), ACPI_MAX_OBJECT_CACHE_DEPTH, &acpi_gbl_operand_cache); @@ -135,6 +107,24 @@ #endif return (status); } +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + /* Memory allocation lists */ + + status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = + acpi_ut_create_list("Acpi-Namespace", + sizeof(struct acpi_namespace_node), + &acpi_gbl_ns_node_list); + if (ACPI_FAILURE(status)) { + return (status); + } +#endif + return (AE_OK); } @@ -153,6 +143,9 @@ #endif acpi_status acpi_ut_delete_caches(void) { + (void)acpi_os_delete_cache(acpi_gbl_namespace_cache); + acpi_gbl_namespace_cache = NULL; + (void)acpi_os_delete_cache(acpi_gbl_state_cache); acpi_gbl_state_cache = NULL; @@ -165,6 +158,21 @@ acpi_status acpi_ut_delete_caches(void) (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache); acpi_gbl_ps_node_ext_cache = NULL; +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + /* Debug only - display leftover memory allocation, if any */ + + acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL); + + /* Free memory lists */ + + acpi_os_free(acpi_gbl_global_list); + acpi_gbl_global_list = NULL; + + acpi_os_free(acpi_gbl_ns_node_list); + acpi_gbl_ns_node_list = NULL; +#endif + return (AE_OK); } @@ -252,7 +260,7 @@ acpi_ut_initialize_buffer(struct acpi_bu /* Allocate a new buffer with local interface to allow tracking */ - buffer->pointer = ACPI_MEM_CALLOCATE(required_length); + buffer->pointer = ACPI_ALLOCATE_ZEROED(required_length); if (!buffer->pointer) { return (AE_NO_MEMORY); } @@ -288,7 +296,7 @@ acpi_ut_initialize_buffer(struct acpi_bu * * RETURN: Address of the allocated memory on success, NULL on failure. * - * DESCRIPTION: The subsystem's equivalent of malloc. + * DESCRIPTION: Subsystem equivalent of malloc. * ******************************************************************************/ @@ -296,23 +304,23 @@ void *acpi_ut_allocate(acpi_size size, u { void *allocation; - ACPI_FUNCTION_TRACE_U32("ut_allocate", size); + ACPI_FUNCTION_TRACE_U32(ut_allocate, size); /* Check for an inadvertent size of zero bytes */ if (!size) { - ACPI_ERROR((module, line, - "ut_allocate: Attempt to allocate zero bytes, allocating 1 byte")); + ACPI_WARNING((module, line, + "Attempt to allocate zero bytes, allocating 1 byte")); size = 1; } allocation = acpi_os_allocate(size); if (!allocation) { + /* Report allocation error */ - ACPI_ERROR((module, line, - "ut_allocate: Could not allocate size %X", - (u32) size)); + ACPI_WARNING((module, line, + "Could not allocate size %X", (u32) size)); return_PTR(NULL); } @@ -322,7 +330,7 @@ void *acpi_ut_allocate(acpi_size size, u /******************************************************************************* * - * FUNCTION: acpi_ut_callocate + * FUNCTION: acpi_ut_allocate_zeroed * * PARAMETERS: Size - Size of the allocation * Component - Component type of caller @@ -331,542 +339,24 @@ void *acpi_ut_allocate(acpi_size size, u * * RETURN: Address of the allocated memory on success, NULL on failure. * - * DESCRIPTION: Subsystem equivalent of calloc. + * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. * ******************************************************************************/ -void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line) +void *acpi_ut_allocate_zeroed(acpi_size size, + u32 component, char *module, u32 line) { void *allocation; - ACPI_FUNCTION_TRACE_U32("ut_callocate", size); - - /* Check for an inadvertent size of zero bytes */ - - if (!size) { - ACPI_ERROR((module, line, - "Attempt to allocate zero bytes, allocating 1 byte")); - size = 1; - } - - allocation = acpi_os_allocate(size); - if (!allocation) { - /* Report allocation error */ - - ACPI_ERROR((module, line, - "Could not allocate size %X", (u32) size)); - return_PTR(NULL); - } - - /* Clear the memory block */ - - ACPI_MEMSET(allocation, 0, size); - return_PTR(allocation); -} - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS -/* - * These procedures are used for tracking memory leaks in the subsystem, and - * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set. - * - * Each memory allocation is tracked via a doubly linked list. Each - * element contains the caller's component, module name, function name, and - * line number. acpi_ut_allocate and acpi_ut_callocate call - * acpi_ut_track_allocation to add an element to the list; deletion - * occurs in the body of acpi_ut_free. - */ - -/******************************************************************************* - * - * FUNCTION: acpi_ut_create_list - * - * PARAMETERS: cache_name - Ascii name for the cache - * object_size - Size of each cached object - * return_cache - Where the new cache object is returned - * - * RETURN: Status - * - * DESCRIPTION: Create a local memory list for tracking purposed - * - ******************************************************************************/ - -static acpi_status -acpi_ut_create_list(char *list_name, - u16 object_size, struct acpi_memory_list **return_cache) -{ - struct acpi_memory_list *cache; - - cache = acpi_os_allocate(sizeof(struct acpi_memory_list)); - if (!cache) { - return (AE_NO_MEMORY); - } - - ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list)); - - cache->list_name = list_name; - cache->object_size = object_size; - - *return_cache = cache; - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_allocate_and_track - * - * PARAMETERS: Size - Size of the allocation - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: The subsystem's equivalent of malloc. - * - ******************************************************************************/ - -void *acpi_ut_allocate_and_track(acpi_size size, - u32 component, char *module, u32 line) -{ - struct acpi_debug_mem_block *allocation; - acpi_status status; - - allocation = - acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header), - component, module, line); - if (!allocation) { - return (NULL); - } - - status = acpi_ut_track_allocation(allocation, size, - ACPI_MEM_MALLOC, component, module, - line); - if (ACPI_FAILURE(status)) { - acpi_os_free(allocation); - return (NULL); - } - - acpi_gbl_global_list->total_allocated++; - acpi_gbl_global_list->current_total_size += (u32) size; - - return ((void *)&allocation->user_space); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_callocate_and_track - * - * PARAMETERS: Size - Size of the allocation - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: Address of the allocated memory on success, NULL on failure. - * - * DESCRIPTION: Subsystem equivalent of calloc. - * - ******************************************************************************/ - -void *acpi_ut_callocate_and_track(acpi_size size, - u32 component, char *module, u32 line) -{ - struct acpi_debug_mem_block *allocation; - acpi_status status; - - allocation = - acpi_ut_callocate(size + sizeof(struct acpi_debug_mem_header), - component, module, line); - if (!allocation) { - /* Report allocation error */ - - ACPI_ERROR((module, line, - "Could not allocate size %X", (u32) size)); - return (NULL); - } - - status = acpi_ut_track_allocation(allocation, size, - ACPI_MEM_CALLOC, component, module, - line); - if (ACPI_FAILURE(status)) { - acpi_os_free(allocation); - return (NULL); - } - - acpi_gbl_global_list->total_allocated++; - acpi_gbl_global_list->current_total_size += (u32) size; - - return ((void *)&allocation->user_space); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_free_and_track - * - * PARAMETERS: Allocation - Address of the memory to deallocate - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: None - * - * DESCRIPTION: Frees the memory at Allocation - * - ******************************************************************************/ - -void -acpi_ut_free_and_track(void *allocation, u32 component, char *module, u32 line) -{ - struct acpi_debug_mem_block *debug_block; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR("ut_free", allocation); - - if (NULL == allocation) { - ACPI_ERROR((module, line, "Attempt to delete a NULL address")); - - return_VOID; - } - - debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block, - (((char *)allocation) - - sizeof(struct acpi_debug_mem_header))); - - acpi_gbl_global_list->total_freed++; - acpi_gbl_global_list->current_total_size -= debug_block->size; - - status = acpi_ut_remove_allocation(debug_block, - component, module, line); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Could not free memory")); - } - - acpi_os_free(debug_block); - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation)); - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_find_allocation - * - * PARAMETERS: Allocation - Address of allocated memory - * - * RETURN: A list element if found; NULL otherwise. - * - * DESCRIPTION: Searches for an element in the global allocation tracking list. - * - ******************************************************************************/ - -static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation) -{ - struct acpi_debug_mem_block *element; - ACPI_FUNCTION_ENTRY(); - element = acpi_gbl_global_list->list_head; - - /* Search for the address. */ - - while (element) { - if (element == allocation) { - return (element); - } - - element = element->next; - } - - return (NULL); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_track_allocation - * - * PARAMETERS: Allocation - Address of allocated memory - * Size - Size of the allocation - * alloc_type - MEM_MALLOC or MEM_CALLOC - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: None. - * - * DESCRIPTION: Inserts an element into the global allocation tracking list. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation, - acpi_size size, - u8 alloc_type, u32 component, char *module, u32 line) -{ - struct acpi_memory_list *mem_list; - struct acpi_debug_mem_block *element; - acpi_status status = AE_OK; - - ACPI_FUNCTION_TRACE_PTR("ut_track_allocation", allocation); - - mem_list = acpi_gbl_global_list; - status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Search list for this address to make sure it is not already on the list. - * This will catch several kinds of problems. - */ - element = acpi_ut_find_allocation(allocation); - if (element) { - ACPI_ERROR((AE_INFO, - "ut_track_allocation: Allocation already present in list! (%p)", - allocation)); - - ACPI_ERROR((AE_INFO, "Element %p Address %p", - element, allocation)); - - goto unlock_and_exit; - } - - /* Fill in the instance data. */ - - allocation->size = (u32) size; - allocation->alloc_type = alloc_type; - allocation->component = component; - allocation->line = line; - - ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME); - allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0; - - /* Insert at list head */ - - if (mem_list->list_head) { - ((struct acpi_debug_mem_block *)(mem_list->list_head))-> - previous = allocation; - } - - allocation->next = mem_list->list_head; - allocation->previous = NULL; - - mem_list->list_head = allocation; - - unlock_and_exit: - status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_remove_allocation - * - * PARAMETERS: Allocation - Address of allocated memory - * Component - Component type of caller - * Module - Source file name of caller - * Line - Line number of caller - * - * RETURN: - * - * DESCRIPTION: Deletes an element from the global allocation tracking list. - * - ******************************************************************************/ - -static acpi_status -acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation, - u32 component, char *module, u32 line) -{ - struct acpi_memory_list *mem_list; - acpi_status status; - - ACPI_FUNCTION_TRACE("ut_remove_allocation"); - - mem_list = acpi_gbl_global_list; - if (NULL == mem_list->list_head) { - /* No allocations! */ - - ACPI_ERROR((module, line, - "Empty allocation list, nothing to free!")); - - return_ACPI_STATUS(AE_OK); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Unlink */ - - if (allocation->previous) { - (allocation->previous)->next = allocation->next; - } else { - mem_list->list_head = allocation->next; - } - - if (allocation->next) { - (allocation->next)->previous = allocation->previous; - } - - /* Mark the segment as deleted */ - - ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size); - - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n", - allocation->size)); + allocation = acpi_ut_allocate(size, component, module, line); + if (allocation) { - status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_dump_allocation_info - * - * PARAMETERS: - * - * RETURN: None - * - * DESCRIPTION: Print some info about the outstanding allocations. - * - ******************************************************************************/ + /* Clear the memory block */ -#ifdef ACPI_FUTURE_USAGE -void acpi_ut_dump_allocation_info(void) -{ -/* - struct acpi_memory_list *mem_list; -*/ - - ACPI_FUNCTION_TRACE("ut_dump_allocation_info"); - -/* - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Current allocations", - mem_list->current_count, - ROUND_UP_TO_1K (mem_list->current_size))); - - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations", - mem_list->max_concurrent_count, - ROUND_UP_TO_1K (mem_list->max_concurrent_size))); - - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects", - running_object_count, - ROUND_UP_TO_1K (running_object_size))); - - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Total (all) allocations", - running_alloc_count, - ROUND_UP_TO_1K (running_alloc_size))); - - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Current Nodes", - acpi_gbl_current_node_count, - ROUND_UP_TO_1K (acpi_gbl_current_node_size))); - - ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, - ("%30s: %4d (%3d Kb)\n", "Max Nodes", - acpi_gbl_max_concurrent_node_count, - ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count * - sizeof (struct acpi_namespace_node))))); -*/ - return_VOID; -} -#endif /* ACPI_FUTURE_USAGE */ - -/******************************************************************************* - * - * FUNCTION: acpi_ut_dump_allocations - * - * PARAMETERS: Component - Component(s) to dump info for. - * Module - Module to dump info for. NULL means all. - * - * RETURN: None - * - * DESCRIPTION: Print a list of all outstanding allocations. - * - ******************************************************************************/ - -void acpi_ut_dump_allocations(u32 component, char *module) -{ - struct acpi_debug_mem_block *element; - union acpi_descriptor *descriptor; - u32 num_outstanding = 0; - - ACPI_FUNCTION_TRACE("ut_dump_allocations"); - - /* - * Walk the allocation list. - */ - if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) { - return; + ACPI_MEMSET(allocation, 0, size); } - element = acpi_gbl_global_list->list_head; - while (element) { - if ((element->component & component) && - ((module == NULL) - || (0 == ACPI_STRCMP(module, element->module)))) { - /* Ignore allocated objects that are in a cache */ - - descriptor = - ACPI_CAST_PTR(union acpi_descriptor, - &element->user_space); - if (descriptor->descriptor_id != ACPI_DESC_TYPE_CACHED) { - acpi_os_printf("%p Len %04X %9.9s-%d [%s] ", - descriptor, element->size, - element->module, element->line, - acpi_ut_get_descriptor_name - (descriptor)); - - /* Most of the elements will be Operand objects. */ - - switch (ACPI_GET_DESCRIPTOR_TYPE(descriptor)) { - case ACPI_DESC_TYPE_OPERAND: - acpi_os_printf("%12.12s R%hd", - acpi_ut_get_type_name - (descriptor->object. - common.type), - descriptor->object. - common.reference_count); - break; - - case ACPI_DESC_TYPE_PARSER: - acpi_os_printf("aml_opcode %04hX", - descriptor->op.asl. - aml_opcode); - break; - - case ACPI_DESC_TYPE_NAMED: - acpi_os_printf("%4.4s", - acpi_ut_get_node_name - (&descriptor->node)); - break; - - default: - break; - } - - acpi_os_printf("\n"); - num_outstanding++; - } - } - element = element->next; - } - - (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY); - - /* Print summary */ - - if (!num_outstanding) { - ACPI_INFO((AE_INFO, "No outstanding allocations")); - } else { - ACPI_ERROR((AE_INFO, - "%d(%X) Outstanding allocations", - num_outstanding, num_outstanding)); - } - - return_VOID; + return (allocation); } - -#endif /* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */ diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c index 2177cb1..56270a3 100644 --- a/drivers/acpi/utilities/utcache.c +++ b/drivers/acpi/utilities/utcache.c @@ -118,13 +118,14 @@ acpi_status acpi_os_purge_cache(struct a /* Walk the list of objects in this cache */ while (cache->list_head) { + /* Delete and unlink one cached state object */ next = *(ACPI_CAST_INDIRECT_PTR(char, &(((char *)cache-> list_head)[cache-> link_offset]))); - ACPI_MEM_FREE(cache->list_head); + ACPI_FREE(cache->list_head); cache->list_head = next; cache->current_depth--; @@ -193,7 +194,7 @@ acpi_os_release_object(struct acpi_memor /* If cache is full, just free this object */ if (cache->current_depth >= cache->max_depth) { - ACPI_MEM_FREE(object); + ACPI_FREE(object); ACPI_MEM_TRACKING(cache->total_freed++); } @@ -243,7 +244,7 @@ void *acpi_os_acquire_object(struct acpi acpi_status status; void *object; - ACPI_FUNCTION_NAME("os_acquire_object"); + ACPI_FUNCTION_NAME(os_acquire_object); if (!cache) { return (NULL); @@ -259,6 +260,7 @@ void *acpi_os_acquire_object(struct acpi /* Check the cache first */ if (cache->list_head) { + /* There is an object available, use it */ object = cache->list_head; @@ -270,9 +272,9 @@ void *acpi_os_acquire_object(struct acpi cache->current_depth--; ACPI_MEM_TRACKING(cache->hits++); - ACPI_MEM_TRACKING(ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Object %p from %s cache\n", - object, cache->list_name))); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Object %p from %s cache\n", object, + cache->list_name)); status = acpi_ut_release_mutex(ACPI_MTX_CACHES); if (ACPI_FAILURE(status)) { @@ -287,14 +289,14 @@ void *acpi_os_acquire_object(struct acpi ACPI_MEM_TRACKING(cache->total_allocated++); - /* Avoid deadlock with ACPI_MEM_CALLOCATE */ + /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ status = acpi_ut_release_mutex(ACPI_MTX_CACHES); if (ACPI_FAILURE(status)) { return (NULL); } - object = ACPI_MEM_CALLOCATE(cache->object_size); + object = ACPI_ALLOCATE_ZEROED(cache->object_size); if (!object) { return (NULL); } diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index df2d320..5e1a80d 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c @@ -109,7 +109,7 @@ acpi_ut_copy_isimple_to_esimple(union ac { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ut_copy_isimple_to_esimple"); + ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple); *buffer_space_used = 0; @@ -325,7 +325,7 @@ acpi_ut_copy_ipackage_to_epackage(union acpi_status status; struct acpi_pkg_info info; - ACPI_FUNCTION_TRACE("ut_copy_ipackage_to_epackage"); + ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage); /* * First package at head of the buffer @@ -383,7 +383,7 @@ acpi_ut_copy_iobject_to_eobject(union ac { acpi_status status; - ACPI_FUNCTION_TRACE("ut_copy_iobject_to_eobject"); + ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject); if (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE) { /* @@ -442,7 +442,7 @@ acpi_ut_copy_esimple_to_isimple(union ac { union acpi_operand_object *internal_object; - ACPI_FUNCTION_TRACE("ut_copy_esimple_to_isimple"); + ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple); /* * Simple types supported are: String, Buffer, Integer @@ -472,8 +472,8 @@ acpi_ut_copy_esimple_to_isimple(union ac case ACPI_TYPE_STRING: internal_object->string.pointer = - ACPI_MEM_CALLOCATE((acpi_size) external_object->string. - length + 1); + ACPI_ALLOCATE_ZEROED((acpi_size) external_object->string. + length + 1); if (!internal_object->string.pointer) { goto error_exit; } @@ -488,7 +488,7 @@ acpi_ut_copy_esimple_to_isimple(union ac case ACPI_TYPE_BUFFER: internal_object->buffer.pointer = - ACPI_MEM_CALLOCATE(external_object->buffer.length); + ACPI_ALLOCATE_ZEROED(external_object->buffer.length); if (!internal_object->buffer.pointer) { goto error_exit; } @@ -552,7 +552,7 @@ acpi_ut_copy_epackage_to_ipackage(union union acpi_operand_object *this_internal_obj; union acpi_object *this_external_obj; - ACPI_FUNCTION_TRACE("ut_copy_epackage_to_ipackage"); + ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage); /* * First package at head of the buffer @@ -600,7 +600,7 @@ acpi_ut_copy_eobject_to_iobject(union ac { acpi_status status; - ACPI_FUNCTION_TRACE("ut_copy_eobject_to_iobject"); + ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject); if (external_object->type == ACPI_TYPE_PACKAGE) { /* @@ -676,7 +676,7 @@ acpi_ut_copy_simple_object(union acpi_op if ((source_desc->buffer.pointer) && (source_desc->buffer.length)) { dest_desc->buffer.pointer = - ACPI_MEM_ALLOCATE(source_desc->buffer.length); + ACPI_ALLOCATE(source_desc->buffer.length); if (!dest_desc->buffer.pointer) { return (AE_NO_MEMORY); } @@ -697,8 +697,8 @@ acpi_ut_copy_simple_object(union acpi_op */ if (source_desc->string.pointer) { dest_desc->string.pointer = - ACPI_MEM_ALLOCATE((acpi_size) source_desc->string. - length + 1); + ACPI_ALLOCATE((acpi_size) source_desc->string. + length + 1); if (!dest_desc->string.pointer) { return (AE_NO_MEMORY); } @@ -805,9 +805,7 @@ acpi_ut_copy_ielement_to_ielement(u8 obj /* * Create the object array */ - target_object->package.elements = - ACPI_MEM_CALLOCATE(((acpi_size) source_object->package. - count + 1) * sizeof(void *)); + target_object->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.count + 1) * sizeof(void *)); if (!target_object->package.elements) { status = AE_NO_MEMORY; goto error_exit; @@ -856,7 +854,7 @@ acpi_ut_copy_ipackage_to_ipackage(union { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ut_copy_ipackage_to_ipackage"); + ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage); dest_obj->common.type = ACPI_GET_OBJECT_TYPE(source_obj); dest_obj->common.flags = source_obj->common.flags; @@ -865,10 +863,10 @@ acpi_ut_copy_ipackage_to_ipackage(union /* * Create the object array and walk the source package tree */ - dest_obj->package.elements = ACPI_MEM_CALLOCATE(((acpi_size) - source_obj->package. - count + - 1) * sizeof(void *)); + dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) + source_obj->package. + count + + 1) * sizeof(void *)); if (!dest_obj->package.elements) { ACPI_ERROR((AE_INFO, "Package allocation failure")); return_ACPI_STATUS(AE_NO_MEMORY); @@ -882,6 +880,7 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_ut_copy_ielement_to_ielement, walk_state); if (ACPI_FAILURE(status)) { + /* On failure, delete the destination package object */ acpi_ut_remove_reference(dest_obj); @@ -911,7 +910,7 @@ acpi_ut_copy_iobject_to_iobject(union ac { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("ut_copy_iobject_to_iobject"); + ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject); /* Create the top level object */ diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index 35f3d58..5ec1cfc 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #define _COMPONENT ACPI_UTILITIES @@ -123,12 +121,14 @@ static const char *acpi_ut_trim_function /* All Function names are longer than 4 chars, check is safe */ if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_MIXED) { + /* This is the case where the original source has not been modified */ return (function_name + 4); } if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_LOWER) { + /* This is the case where the source has been 'linuxized' */ return (function_name + 5); @@ -162,7 +162,7 @@ acpi_ut_debug_print(u32 requested_debug_ const char *function_name, char *module_name, u32 component_id, char *format, ...) { - u32 thread_id; + acpi_thread_id thread_id; va_list args; /* @@ -177,7 +177,6 @@ acpi_ut_debug_print(u32 requested_debug_ * Thread tracking and context switch notification */ thread_id = acpi_os_get_thread_id(); - if (thread_id != acpi_gbl_prev_thread_id) { if (ACPI_LV_THREADS & acpi_dbg_level) { acpi_os_printf @@ -206,7 +205,7 @@ acpi_ut_debug_print(u32 requested_debug_ acpi_os_vprintf(format, args); } -EXPORT_SYMBOL(acpi_ut_debug_print); +ACPI_EXPORT_SYMBOL(acpi_ut_debug_print) /******************************************************************************* * @@ -226,7 +225,6 @@ EXPORT_SYMBOL(acpi_ut_debug_print); * debug_print so that the same macros can be used. * ******************************************************************************/ - void ACPI_INTERNAL_VAR_XFACE acpi_ut_debug_print_raw(u32 requested_debug_level, u32 line_number, @@ -244,7 +242,7 @@ acpi_ut_debug_print_raw(u32 requested_de acpi_os_vprintf(format, args); } -EXPORT_SYMBOL(acpi_ut_debug_print_raw); +ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw) /******************************************************************************* * @@ -261,7 +259,6 @@ EXPORT_SYMBOL(acpi_ut_debug_print_raw); * set in debug_level * ******************************************************************************/ - void acpi_ut_trace(u32 line_number, const char *function_name, char *module_name, u32 component_id) @@ -275,7 +272,7 @@ acpi_ut_trace(u32 line_number, component_id, "%s\n", acpi_gbl_fn_entry_str); } -EXPORT_SYMBOL(acpi_ut_trace); +ACPI_EXPORT_SYMBOL(acpi_ut_trace) /******************************************************************************* * @@ -293,7 +290,6 @@ EXPORT_SYMBOL(acpi_ut_trace); * set in debug_level * ******************************************************************************/ - void acpi_ut_trace_ptr(u32 line_number, const char *function_name, @@ -400,7 +396,7 @@ acpi_ut_exit(u32 line_number, acpi_gbl_nesting_level--; } -EXPORT_SYMBOL(acpi_ut_exit); +ACPI_EXPORT_SYMBOL(acpi_ut_exit) /******************************************************************************* * @@ -418,7 +414,6 @@ EXPORT_SYMBOL(acpi_ut_exit); * set in debug_level. Prints exit status also. * ******************************************************************************/ - void acpi_ut_status_exit(u32 line_number, const char *function_name, @@ -442,7 +437,7 @@ acpi_ut_status_exit(u32 line_number, acpi_gbl_nesting_level--; } -EXPORT_SYMBOL(acpi_ut_status_exit); +ACPI_EXPORT_SYMBOL(acpi_ut_status_exit) /******************************************************************************* * @@ -460,7 +455,6 @@ EXPORT_SYMBOL(acpi_ut_status_exit); * set in debug_level. Prints exit value also. * ******************************************************************************/ - void acpi_ut_value_exit(u32 line_number, const char *function_name, @@ -475,7 +469,7 @@ acpi_ut_value_exit(u32 line_number, acpi_gbl_nesting_level--; } -EXPORT_SYMBOL(acpi_ut_value_exit); +ACPI_EXPORT_SYMBOL(acpi_ut_value_exit) /******************************************************************************* * @@ -493,7 +487,6 @@ EXPORT_SYMBOL(acpi_ut_value_exit); * set in debug_level. Prints exit value also. * ******************************************************************************/ - void acpi_ut_ptr_exit(u32 line_number, const char *function_name, @@ -524,20 +517,13 @@ #endif * ******************************************************************************/ -void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) +void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) { acpi_native_uint i = 0; acpi_native_uint j; u32 temp32; u8 buf_char; - /* Only dump the buffer if tracing is enabled */ - - if (!((ACPI_LV_TABLES & acpi_dbg_level) && - (component_id & acpi_dbg_layer))) { - return; - } - if ((count < 4) || (count & 0x01)) { display = DB_BYTE_DISPLAY; } @@ -545,6 +531,7 @@ void acpi_ut_dump_buffer(u8 * buffer, u3 /* Nasty little dump buffer routine! */ while (i < count) { + /* Print current offset */ acpi_os_printf("%6.4X: ", (u32) i); @@ -553,6 +540,7 @@ void acpi_ut_dump_buffer(u8 * buffer, u3 for (j = 0; j < 16;) { if (i + j >= count) { + /* Dump fill spaces */ acpi_os_printf("%*s", ((display * 2) + 1), " "); @@ -561,6 +549,7 @@ void acpi_ut_dump_buffer(u8 * buffer, u3 } switch (display) { + case DB_BYTE_DISPLAY: default: /* Default is BYTE display */ acpi_os_printf("%02X ", buffer[i + j]); @@ -618,3 +607,31 @@ void acpi_ut_dump_buffer(u8 * buffer, u3 return; } + +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_buffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Display - BYTE, WORD, DWORD, or QWORD display + * component_iD - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id) +{ + + /* Only dump the buffer if tracing is enabled */ + + if (!((ACPI_LV_TABLES & acpi_dbg_level) && + (component_id & acpi_dbg_layer))) { + return; + } + + acpi_ut_dump_buffer2(buffer, count, display); +} diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index 1db9695..67b9f32 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c @@ -76,7 +76,7 @@ static void acpi_ut_delete_internal_obj( union acpi_operand_object *second_desc; union acpi_operand_object *next_desc; - ACPI_FUNCTION_TRACE_PTR("ut_delete_internal_obj", object); + ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object); if (!object) { return_VOID; @@ -96,6 +96,7 @@ static void acpi_ut_delete_internal_obj( /* Free the actual string buffer */ if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { + /* But only if it is NOT a pointer into an ACPI table */ obj_pointer = object->string.pointer; @@ -111,6 +112,7 @@ static void acpi_ut_delete_internal_obj( /* Free the actual buffer */ if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { + /* But only if it is NOT a pointer into an ACPI table */ obj_pointer = object->buffer.pointer; @@ -198,11 +200,22 @@ static void acpi_ut_delete_internal_obj( */ handler_desc = object->region.handler; if (handler_desc) { - if (handler_desc->address_space. - hflags & + if (handler_desc->address_space.handler_flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { - obj_pointer = - second_desc->extra.region_context; + + /* Deactivate region and free region context */ + + if (handler_desc->address_space.setup) { + (void)handler_desc-> + address_space.setup(object, + ACPI_REGION_DEACTIVATE, + handler_desc-> + address_space. + context, + &second_desc-> + extra. + region_context); + } } acpi_ut_remove_reference(handler_desc); @@ -234,7 +247,7 @@ static void acpi_ut_delete_internal_obj( if (obj_pointer) { ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n", obj_pointer)); - ACPI_MEM_FREE(obj_pointer); + ACPI_FREE(obj_pointer); } /* Now the object can be safely deleted */ @@ -263,7 +276,7 @@ void acpi_ut_delete_internal_object_list { union acpi_operand_object **internal_obj; - ACPI_FUNCTION_TRACE("ut_delete_internal_object_list"); + ACPI_FUNCTION_TRACE(ut_delete_internal_object_list); /* Walk the null-terminated internal list */ @@ -273,7 +286,7 @@ void acpi_ut_delete_internal_object_list /* Free the combined parameter pointer list and object array */ - ACPI_MEM_FREE(obj_list); + ACPI_FREE(obj_list); return_VOID; } @@ -296,7 +309,7 @@ acpi_ut_update_ref_count(union acpi_oper u16 count; u16 new_count; - ACPI_FUNCTION_NAME("ut_update_ref_count"); + ACPI_FUNCTION_NAME(ut_update_ref_count); if (!object) { return; @@ -306,11 +319,9 @@ acpi_ut_update_ref_count(union acpi_oper new_count = count; /* - * Perform the reference count action - * (increment, decrement, or force delete) + * Perform the reference count action (increment, decrement, force delete) */ switch (action) { - case REF_INCREMENT: new_count++; @@ -347,7 +358,6 @@ acpi_ut_update_ref_count(union acpi_oper if (new_count == 0) { acpi_ut_delete_internal_obj(object); } - break; case REF_FORCE_DELETE: @@ -372,13 +382,10 @@ acpi_ut_update_ref_count(union acpi_oper * (A deleted object will have a huge reference count) */ if (count > ACPI_MAX_REFERENCE_COUNT) { - ACPI_WARNING((AE_INFO, - "Large Reference Count (%X) in object %p", - count, object)); + "Large Reference Count (%X) in object %p", count, + object)); } - - return; } /******************************************************************************* @@ -404,7 +411,7 @@ acpi_ut_update_ref_count(union acpi_oper ******************************************************************************/ acpi_status -acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action) +acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) { acpi_status status = AE_OK; union acpi_generic_state *state_list = NULL; @@ -412,9 +419,10 @@ acpi_ut_update_object_reference(union ac union acpi_generic_state *state; acpi_native_uint i; - ACPI_FUNCTION_TRACE_PTR("ut_update_object_reference", object); + ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object); while (object) { + /* Make sure that this isn't a namespace handle */ if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) { @@ -507,11 +515,11 @@ acpi_ut_update_object_reference(union ac case ACPI_TYPE_REGION: default: - break; /* No subobjects */ + break; /* No subobjects for all other types */ } /* - * Now we can update the count in the main object. This can only + * Now we can update the count in the main object. This can only * happen after we update the sub-objects in case this causes the * main object to be deleted. */ @@ -556,7 +564,7 @@ acpi_ut_update_object_reference(union ac void acpi_ut_add_reference(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR("ut_add_reference", object); + ACPI_FUNCTION_TRACE_PTR(ut_add_reference, object); /* Ensure that we have a valid object */ @@ -589,11 +597,11 @@ void acpi_ut_add_reference(union acpi_op void acpi_ut_remove_reference(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR("ut_remove_reference", object); + ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object); /* - * Allow a NULL pointer to be passed in, just ignore it. This saves - * each caller from having to check. Also, ignore NS nodes. + * Allow a NULL pointer to be passed in, just ignore it. This saves + * each caller from having to check. Also, ignore NS nodes. * */ if (!object || @@ -613,7 +621,7 @@ void acpi_ut_remove_reference(union acpi /* * Decrement the reference count, and only actually delete the object - * if the reference count becomes 0. (Must also decrement the ref count + * if the reference count becomes 0. (Must also decrement the ref count * of all subobjects!) */ (void)acpi_ut_update_object_reference(object, REF_DECREMENT); diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index 106cc97..d6d7121 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c @@ -56,6 +56,34 @@ static acpi_status acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, struct acpi_compatible_id *one_cid); +/* + * Strings supported by the _OSI predefined (internal) method. + */ +static const char *acpi_interfaces_supported[] = { + /* Operating System Vendor Strings */ + + "Linux", + "Windows 2000", + "Windows 2001", + "Windows 2001 SP0", + "Windows 2001 SP1", + "Windows 2001 SP2", + "Windows 2001 SP3", + "Windows 2001 SP4", + "Windows 2001.1", + "Windows 2001.1 SP1", /* Added 03/2006 */ + "Windows 2006", /* Added 03/2006 */ + + /* Feature Group Strings */ + + "Extended Address Space Descriptor" + /* + * All "optional" feature group strings (features that are implemented + * by the host) should be implemented in the host version of + * acpi_os_validate_interface and should not be added here. + */ +}; + /******************************************************************************* * * FUNCTION: acpi_ut_osi_implementation @@ -64,18 +92,18 @@ acpi_ut_translate_one_cid(union acpi_ope * * RETURN: Status * - * DESCRIPTION: Implementation of _OSI predefined control method - * Supported = _OSI (String) + * DESCRIPTION: Implementation of the _OSI predefined control method * ******************************************************************************/ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) { + acpi_status status; union acpi_operand_object *string_desc; union acpi_operand_object *return_desc; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ut_osi_implementation"); + ACPI_FUNCTION_TRACE(ut_osi_implementation); /* Validate the string input argument */ @@ -84,28 +112,47 @@ acpi_status acpi_ut_osi_implementation(s return_ACPI_STATUS(AE_TYPE); } - /* Create a return object (Default value = 0) */ + /* Create a return object */ return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); if (!return_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } - /* Compare input string to table of supported strings */ + /* Default return value is SUPPORTED */ + + return_desc->integer.value = ACPI_UINT32_MAX; + walk_state->return_desc = return_desc; + + /* Compare input string to static table of supported interfaces */ - for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) { - if (!ACPI_STRCMP(string_desc->string.pointer, - ACPI_CAST_PTR(char, - acpi_gbl_valid_osi_strings[i]))) - { - /* This string is supported */ + for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { + if (!ACPI_STRCMP + (string_desc->string.pointer, + acpi_interfaces_supported[i])) { - return_desc->integer.value = 0xFFFFFFFF; - break; + /* The interface is supported */ + + return_ACPI_STATUS(AE_CTRL_TERMINATE); } } - walk_state->return_desc = return_desc; + /* + * Did not match the string in the static table, call the host OSL to + * check for a match with one of the optional strings (such as + * "Module Device", "3.0 Thermal Model", etc.) + */ + status = acpi_os_validate_interface(string_desc->string.pointer); + if (ACPI_SUCCESS(status)) { + + /* The interface is supported */ + + return_ACPI_STATUS(AE_CTRL_TERMINATE); + } + + /* The interface is not supported */ + + return_desc->integer.value = 0; return_ACPI_STATUS(AE_CTRL_TERMINATE); } @@ -134,19 +181,26 @@ acpi_ut_evaluate_object(struct acpi_name u32 expected_return_btypes, union acpi_operand_object **return_desc) { - struct acpi_parameter_info info; + struct acpi_evaluate_info *info; acpi_status status; u32 return_btype; - ACPI_FUNCTION_TRACE("ut_evaluate_object"); + ACPI_FUNCTION_TRACE(ut_evaluate_object); - info.node = prefix_node; - info.parameters = NULL; - info.parameter_type = ACPI_PARAM_ARGS; + /* Allocate the evaluation information block */ + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + info->prefix_node = prefix_node; + info->pathname = path; + info->parameter_type = ACPI_PARAM_ARGS; /* Evaluate the object/method */ - status = acpi_ns_evaluate_relative(path, &info); + status = acpi_ns_evaluate(info); if (ACPI_FAILURE(status)) { if (status == AE_NOT_FOUND) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -158,25 +212,25 @@ acpi_ut_evaluate_object(struct acpi_name prefix_node, path, status); } - return_ACPI_STATUS(status); + goto cleanup; } /* Did we get a return object? */ - if (!info.return_object) { + if (!info->return_object) { if (expected_return_btypes) { ACPI_ERROR_METHOD("No object was returned from", prefix_node, path, AE_NOT_EXIST); - return_ACPI_STATUS(AE_NOT_EXIST); + status = AE_NOT_EXIST; } - return_ACPI_STATUS(AE_OK); + goto cleanup; } /* Map the return object type to the bitmapped type */ - switch (ACPI_GET_OBJECT_TYPE(info.return_object)) { + switch (ACPI_GET_OBJECT_TYPE(info->return_object)) { case ACPI_TYPE_INTEGER: return_btype = ACPI_BTYPE_INTEGER; break; @@ -204,8 +258,8 @@ acpi_ut_evaluate_object(struct acpi_name * happen frequently if the "implicit return" feature is enabled. * Just delete the return object and return AE_OK. */ - acpi_ut_remove_reference(info.return_object); - return_ACPI_STATUS(AE_OK); + acpi_ut_remove_reference(info->return_object); + goto cleanup; } /* Is the return object one of the expected types? */ @@ -217,19 +271,23 @@ acpi_ut_evaluate_object(struct acpi_name ACPI_ERROR((AE_INFO, "Type returned from %s was incorrect: %s, expected Btypes: %X", path, - acpi_ut_get_object_type_name(info.return_object), + acpi_ut_get_object_type_name(info->return_object), expected_return_btypes)); /* On error exit, we must delete the return object */ - acpi_ut_remove_reference(info.return_object); - return_ACPI_STATUS(AE_TYPE); + acpi_ut_remove_reference(info->return_object); + status = AE_TYPE; + goto cleanup; } /* Object type is OK, return it */ - *return_desc = info.return_object; - return_ACPI_STATUS(AE_OK); + *return_desc = info->return_object; + + cleanup: + ACPI_FREE(info); + return_ACPI_STATUS(status); } /******************************************************************************* @@ -257,7 +315,7 @@ acpi_ut_evaluate_numeric_object(char *ob union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("ut_evaluate_numeric_object"); + ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object); status = acpi_ut_evaluate_object(device_node, object_name, ACPI_BTYPE_INTEGER, &obj_desc); @@ -333,7 +391,7 @@ acpi_ut_execute_HID(struct acpi_namespac union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("ut_execute_HID"); + ACPI_FUNCTION_TRACE(ut_execute_HID); status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID, ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, @@ -343,6 +401,7 @@ acpi_ut_execute_HID(struct acpi_namespac } if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + /* Convert the Numeric HID to string */ acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value, @@ -436,7 +495,7 @@ acpi_ut_execute_CID(struct acpi_namespac struct acpi_compatible_id_list *cid_list; acpi_native_uint i; - ACPI_FUNCTION_TRACE("ut_execute_CID"); + ACPI_FUNCTION_TRACE(ut_execute_CID); /* Evaluate the _CID method for this device */ @@ -459,7 +518,7 @@ acpi_ut_execute_CID(struct acpi_namespac size = (((count - 1) * sizeof(struct acpi_compatible_id)) + sizeof(struct acpi_compatible_id_list)); - cid_list = ACPI_MEM_CALLOCATE((acpi_size) size); + cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); if (!cid_list) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -479,6 +538,7 @@ acpi_ut_execute_CID(struct acpi_namespac /* The _CID object can be either a single CID or a package (list) of CIDs */ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + /* Translate each package element */ for (i = 0; i < count; i++) { @@ -499,7 +559,7 @@ acpi_ut_execute_CID(struct acpi_namespac /* Cleanup on error */ if (ACPI_FAILURE(status)) { - ACPI_MEM_FREE(cid_list); + ACPI_FREE(cid_list); } else { *return_cid_list = cid_list; } @@ -533,7 +593,7 @@ acpi_ut_execute_UID(struct acpi_namespac union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("ut_execute_UID"); + ACPI_FUNCTION_TRACE(ut_execute_UID); status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID, ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, @@ -543,6 +603,7 @@ acpi_ut_execute_UID(struct acpi_namespac } if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + /* Convert the Numeric UID to string */ acpi_ex_unsigned_integer_to_string(obj_desc->integer.value, @@ -582,7 +643,7 @@ acpi_ut_execute_STA(struct acpi_namespac union acpi_operand_object *obj_desc; acpi_status status; - ACPI_FUNCTION_TRACE("ut_execute_STA"); + ACPI_FUNCTION_TRACE(ut_execute_STA); status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA, ACPI_BTYPE_INTEGER, &obj_desc); @@ -632,7 +693,7 @@ acpi_ut_execute_sxds(struct acpi_namespa acpi_status status; u32 i; - ACPI_FUNCTION_TRACE("ut_execute_Sxds"); + ACPI_FUNCTION_TRACE(ut_execute_sxds); for (i = 0; i < 4; i++) { highest[i] = 0xFF; diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index ffd1338..e5999c6 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -43,7 +43,6 @@ #define DEFINE_ACPI_GLOBALS -#include #include #include @@ -119,6 +118,7 @@ const char *acpi_format_exception(acpi_s } if (!exception) { + /* Exception code was not recognized */ ACPI_ERROR((AE_INFO, @@ -143,12 +143,10 @@ const char *acpi_format_exception(acpi_s /* Debug switch - level and trace mask */ u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT; -EXPORT_SYMBOL(acpi_dbg_level); /* Debug switch - layer (component) mask */ u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS; -EXPORT_SYMBOL(acpi_dbg_layer); u32 acpi_gbl_nesting_level = 0; /* Debugger globals */ @@ -183,28 +181,6 @@ const char *acpi_gbl_highest_dstate_name "_S4D" }; -/* - * Strings supported by the _OSI predefined (internal) method. - * When adding strings, be sure to update ACPI_NUM_OSI_STRINGS. - */ -const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = { - /* Operating System Vendor Strings */ - - "Linux", - "Windows 2000", - "Windows 2001", - "Windows 2001.1", - "Windows 2001 SP0", - "Windows 2001 SP1", - "Windows 2001 SP2", - "Windows 2001 SP3", - "Windows 2001 SP4", - - /* Feature Group Strings */ - - "Extended Address Space Descriptor" -}; - /******************************************************************************* * * Namespace globals @@ -317,9 +293,9 @@ char acpi_ut_hex_to_ascii_char(acpi_inte * ******************************************************************************/ -struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES]; +struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1]; -struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] = { +struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1] = { /*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */ /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof(RSDP_SIG) - 1, @@ -467,7 +443,6 @@ struct acpi_fixed_event_info acpi_gbl_fi /* Region type decoding */ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { -/*! [Begin] no source code translation (keep these ASL Keywords as-is) */ "SystemMemory", "SystemIO", "PCI_Config", @@ -476,16 +451,15 @@ const char *acpi_gbl_region_types[ACPI_N "CMOS", "PCIBARTarget", "DataTable" -/*! [End] no source code translation !*/ }; char *acpi_ut_get_region_name(u8 space_id) { if (space_id >= ACPI_USER_REGION_BEGIN) { - return ("user_defined_region"); + return ("UserDefinedRegion"); } else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) { - return ("invalid_space_id"); + return ("InvalidSpaceId"); } return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); @@ -506,20 +480,18 @@ char *acpi_ut_get_region_name(u8 space_i /* Event type decoding */ static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { -/*! [Begin] no source code translation (keep these strings as-is) */ "PM_Timer", "GlobalLock", "PowerButton", "SleepButton", "RealTimeClock", -/*! [End] no source code translation !*/ }; char *acpi_ut_get_event_name(u32 event_id) { if (event_id > ACPI_EVENT_MAX) { - return ("invalid_event_iD"); + return ("InvalidEventID"); } return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id])); @@ -550,7 +522,6 @@ static const char acpi_gbl_bad_type[] = /* Printable names of the ACPI object types */ static const char *acpi_gbl_ns_type_names[] = { -/*! [Begin] no source code translation (keep these strings as-is) */ /* 00 */ "Untyped", /* 01 */ "Integer", /* 02 */ "String", @@ -582,7 +553,6 @@ static const char *acpi_gbl_ns_type_name /* 28 */ "Extra", /* 29 */ "Data", /* 30 */ "Invalid" -/*! [End] no source code translation !*/ }; char *acpi_ut_get_type_name(acpi_object_type type) @@ -635,14 +605,14 @@ char *acpi_ut_get_node_name(void *object /* Descriptor must be a namespace node */ - if (node->descriptor != ACPI_DESC_TYPE_NAMED) { + if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { return ("####"); } /* Name must be a valid ACPI name */ if (!acpi_ut_valid_acpi_name(node->name.integer)) { - return ("????"); + node->name.integer = acpi_ut_repair_name(node->name.integer); } /* Return the name */ @@ -665,7 +635,6 @@ char *acpi_ut_get_node_name(void *object /* Printable names of object descriptor types */ static const char *acpi_gbl_desc_type_names[] = { -/*! [Begin] no source code translation (keep these ASL Keywords as-is) */ /* 00 */ "Invalid", /* 01 */ "Cached", /* 02 */ "State-Generic", @@ -682,7 +651,6 @@ static const char *acpi_gbl_desc_type_na /* 13 */ "Parser", /* 14 */ "Operand", /* 15 */ "Node" -/*! [End] no source code translation !*/ }; char *acpi_ut_get_descriptor_name(void *object) @@ -723,7 +691,7 @@ #if defined(ACPI_DEBUG_OUTPUT) || define char *acpi_ut_get_mutex_name(u32 mutex_id) { - if (mutex_id > MAX_MUTEX) { + if (mutex_id > ACPI_MAX_MUTEX) { return ("Invalid Mutex ID"); } @@ -747,6 +715,7 @@ u8 acpi_ut_valid_object_type(acpi_object { if (type > ACPI_TYPE_LOCAL_MAX) { + /* Note: Assumes all TYPEs are contiguous (external/local) */ return (FALSE); @@ -773,7 +742,7 @@ void acpi_ut_init_globals(void) acpi_status status; u32 i; - ACPI_FUNCTION_TRACE("ut_init_globals"); + ACPI_FUNCTION_TRACE(ut_init_globals); /* Create all memory caches */ @@ -784,14 +753,14 @@ void acpi_ut_init_globals(void) /* ACPI table structure */ - for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { + for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { acpi_gbl_table_lists[i].next = NULL; acpi_gbl_table_lists[i].count = 0; } /* Mutex locked flags */ - for (i = 0; i < NUM_MUTEX; i++) { + for (i = 0; i < ACPI_NUM_MUTEX; i++) { acpi_gbl_mutex_info[i].mutex = NULL; acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED; acpi_gbl_mutex_info[i].use_count = 0; @@ -856,7 +825,7 @@ void acpi_ut_init_globals(void) acpi_gbl_root_node = NULL; acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; - acpi_gbl_root_node_struct.descriptor = ACPI_DESC_TYPE_NAMED; + acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE; acpi_gbl_root_node_struct.child = NULL; acpi_gbl_root_node_struct.peer = NULL; @@ -869,3 +838,6 @@ #endif return_VOID; } + +ACPI_EXPORT_SYMBOL(acpi_dbg_level) +ACPI_EXPORT_SYMBOL(acpi_dbg_layer) diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index ba771b4..ff76055 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c @@ -50,7 +50,7 @@ ACPI_MODULE_NAME("utinit") /* Local prototypes */ static void -acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset); +acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset); static void acpi_ut_terminate(void); @@ -69,12 +69,12 @@ static void acpi_ut_terminate(void); ******************************************************************************/ static void -acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset) +acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset) { ACPI_WARNING((AE_INFO, "Invalid FADT value %s=%X at offset %X FADT=%p", - register_name, value, (u32) offset, acpi_gbl_FADT)); + register_name, value, offset, acpi_gbl_FADT)); } /****************************************************************************** @@ -176,7 +176,7 @@ static void acpi_ut_terminate(void) struct acpi_gpe_xrupt_info *gpe_xrupt_info; struct acpi_gpe_xrupt_info *next_gpe_xrupt_info; - ACPI_FUNCTION_TRACE("ut_terminate"); + ACPI_FUNCTION_TRACE(ut_terminate); /* Free global tables, etc. */ /* Free global GPE blocks and related info structures */ @@ -186,14 +186,14 @@ static void acpi_ut_terminate(void) gpe_block = gpe_xrupt_info->gpe_block_list_head; while (gpe_block) { next_gpe_block = gpe_block->next; - ACPI_MEM_FREE(gpe_block->event_info); - ACPI_MEM_FREE(gpe_block->register_info); - ACPI_MEM_FREE(gpe_block); + ACPI_FREE(gpe_block->event_info); + ACPI_FREE(gpe_block->register_info); + ACPI_FREE(gpe_block); gpe_block = next_gpe_block; } next_gpe_xrupt_info = gpe_xrupt_info->next; - ACPI_MEM_FREE(gpe_xrupt_info); + ACPI_FREE(gpe_xrupt_info); gpe_xrupt_info = next_gpe_xrupt_info; } @@ -216,7 +216,7 @@ static void acpi_ut_terminate(void) void acpi_ut_subsystem_shutdown(void) { - ACPI_FUNCTION_TRACE("ut_subsystem_shutdown"); + ACPI_FUNCTION_TRACE(ut_subsystem_shutdown); /* Just exit if subsystem is already shutdown */ @@ -228,6 +228,7 @@ void acpi_ut_subsystem_shutdown(void) /* Subsystem appears active, go ahead and shut it down */ acpi_gbl_shutdown = TRUE; + acpi_gbl_startup_flags = 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); /* Close the acpi_event Handling */ @@ -245,12 +246,5 @@ void acpi_ut_subsystem_shutdown(void) /* Purge the local caches */ (void)acpi_ut_delete_caches(); - - /* Debug only - display leftover memory allocation, if any */ - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL); -#endif - return_VOID; } diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c index 4a33604..19d74be 100644 --- a/drivers/acpi/utilities/utmath.c +++ b/drivers/acpi/utilities/utmath.c @@ -77,7 +77,7 @@ acpi_ut_short_divide(acpi_integer divide union uint64_overlay quotient; u32 remainder32; - ACPI_FUNCTION_TRACE("ut_short_divide"); + ACPI_FUNCTION_TRACE(ut_short_divide); /* Always check for a zero divisor */ @@ -139,7 +139,7 @@ acpi_ut_divide(acpi_integer in_dividend, union uint64_overlay partial2; union uint64_overlay partial3; - ACPI_FUNCTION_TRACE("ut_divide"); + ACPI_FUNCTION_TRACE(ut_divide); /* Always check for a zero divisor */ @@ -261,7 +261,7 @@ acpi_ut_short_divide(acpi_integer in_div acpi_integer * out_quotient, u32 * out_remainder) { - ACPI_FUNCTION_TRACE("ut_short_divide"); + ACPI_FUNCTION_TRACE(ut_short_divide); /* Always check for a zero divisor */ @@ -287,7 +287,7 @@ acpi_ut_divide(acpi_integer in_dividend, acpi_integer in_divisor, acpi_integer * out_quotient, acpi_integer * out_remainder) { - ACPI_FUNCTION_TRACE("ut_divide"); + ACPI_FUNCTION_TRACE(ut_divide); /* Always check for a zero divisor */ diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 7364f5f..5c75d35 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -49,6 +49,33 @@ ACPI_MODULE_NAME("utmisc") /******************************************************************************* * + * FUNCTION: acpi_ut_is_aml_table + * + * PARAMETERS: Table - An ACPI table + * + * RETURN: TRUE if table contains executable AML; FALSE otherwise + * + * DESCRIPTION: Check ACPI Signature for a table that contains AML code. + * Currently, these are DSDT,SSDT,PSDT. All other table types are + * data tables that do not contain AML code. + * + ******************************************************************************/ +u8 acpi_ut_is_aml_table(struct acpi_table_header *table) +{ + + /* Ignore tables that contain AML */ + + if (ACPI_COMPARE_NAME(table->signature, DSDT_SIG) || + ACPI_COMPARE_NAME(table->signature, PSDT_SIG) || + ACPI_COMPARE_NAME(table->signature, SSDT_SIG)) { + return (TRUE); + } + + return (FALSE); +} + +/******************************************************************************* + * * FUNCTION: acpi_ut_allocate_owner_id * * PARAMETERS: owner_id - Where the new owner ID is returned @@ -60,6 +87,7 @@ ACPI_MODULE_NAME("utmisc") * when the method exits or the table is unloaded. * ******************************************************************************/ + acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) { acpi_native_uint i; @@ -67,7 +95,7 @@ acpi_status acpi_ut_allocate_owner_id(ac acpi_native_uint k; acpi_status status; - ACPI_FUNCTION_TRACE("ut_allocate_owner_id"); + ACPI_FUNCTION_TRACE(ut_allocate_owner_id); /* Guard against multiple allocations of ID to the same location */ @@ -97,6 +125,7 @@ acpi_status acpi_ut_allocate_owner_id(ac for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) { if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) { + /* There are no free IDs in this mask */ break; @@ -123,7 +152,7 @@ acpi_status acpi_ut_allocate_owner_id(ac (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j)); ACPI_DEBUG_PRINT((ACPI_DB_VALUES, - "Allocated owner_id: %2.2X\n", + "Allocated OwnerId: %2.2X\n", (unsigned int)*owner_id)); goto exit; } @@ -144,7 +173,7 @@ acpi_status acpi_ut_allocate_owner_id(ac */ status = AE_OWNER_ID_LIMIT; ACPI_ERROR((AE_INFO, - "Could not allocate new owner_id (255 max), AE_OWNER_ID_LIMIT")); + "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); exit: (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); @@ -172,7 +201,7 @@ void acpi_ut_release_owner_id(acpi_owner acpi_native_uint index; u32 bit; - ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id); + ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id); /* Always clear the input owner_id (zero is an invalid ID) */ @@ -181,7 +210,7 @@ void acpi_ut_release_owner_id(acpi_owner /* Zero is not a valid owner_iD */ if (owner_id == 0) { - ACPI_ERROR((AE_INFO, "Invalid owner_id: %2.2X", owner_id)); + ACPI_ERROR((AE_INFO, "Invalid OwnerId: %2.2X", owner_id)); return_VOID; } @@ -207,7 +236,7 @@ void acpi_ut_release_owner_id(acpi_owner acpi_gbl_owner_id_mask[index] ^= bit; } else { ACPI_ERROR((AE_INFO, - "Release of non-allocated owner_id: %2.2X", + "Release of non-allocated OwnerId: %2.2X", owner_id + 1)); } @@ -273,6 +302,7 @@ void acpi_ut_print_string(char *string, acpi_os_printf("\""); for (i = 0; string[i] && (i < max_length); i++) { + /* Escape sequences */ switch (string[i]) { @@ -461,12 +491,47 @@ acpi_ut_display_init_pathname(u8 type, } acpi_os_printf("\n"); - ACPI_MEM_FREE(buffer.pointer); + ACPI_FREE(buffer.pointer); } #endif /******************************************************************************* * + * FUNCTION: acpi_ut_valid_acpi_char + * + * PARAMETERS: Char - The character to be examined + * + * RETURN: TRUE if the character is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI character. Must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + * We allow a '!' as the last character because of the ASF! table + * + ******************************************************************************/ + +u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position) +{ + + if (!((character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9') || (character == '_'))) { + + /* Allow a '!' in the last position */ + + if (character == '!' && position == 3) { + return (TRUE); + } + + return (FALSE); + } + + return (TRUE); +} + +/******************************************************************************* + * * FUNCTION: acpi_ut_valid_acpi_name * * PARAMETERS: Name - The name to be examined @@ -482,19 +547,13 @@ #endif u8 acpi_ut_valid_acpi_name(u32 name) { - char *name_ptr = (char *)&name; - char character; acpi_native_uint i; ACPI_FUNCTION_ENTRY(); for (i = 0; i < ACPI_NAME_SIZE; i++) { - character = *name_ptr; - name_ptr++; - - if (!((character == '_') || - (character >= 'A' && character <= 'Z') || - (character >= '0' && character <= '9'))) { + if (!acpi_ut_valid_acpi_char + ((ACPI_CAST_PTR(char, &name))[i], i)) { return (FALSE); } } @@ -504,24 +563,37 @@ u8 acpi_ut_valid_acpi_name(u32 name) /******************************************************************************* * - * FUNCTION: acpi_ut_valid_acpi_character + * FUNCTION: acpi_ut_repair_name * - * PARAMETERS: Character - The character to be examined + * PARAMETERS: Name - The ACPI name to be repaired * - * RETURN: 1 if Character may appear in a name, else 0 + * RETURN: Repaired version of the name * - * DESCRIPTION: Check for a printable character + * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and + * return the new name. * ******************************************************************************/ -u8 acpi_ut_valid_acpi_character(char character) +acpi_name acpi_ut_repair_name(acpi_name name) { + char *name_ptr = ACPI_CAST_PTR(char, &name); + char new_name[ACPI_NAME_SIZE]; + acpi_native_uint i; - ACPI_FUNCTION_ENTRY(); + for (i = 0; i < ACPI_NAME_SIZE; i++) { + new_name[i] = name_ptr[i]; - return ((u8) ((character == '_') || - (character >= 'A' && character <= 'Z') || - (character >= '0' && character <= '9'))); + /* + * Replace a bad character with something printable, yet technically + * still invalid. This prevents any collisions with existing "good" + * names in the namespace. + */ + if (!acpi_ut_valid_acpi_char(name_ptr[i], i)) { + new_name[i] = '*'; + } + } + + return (*ACPI_CAST_PTR(u32, new_name)); } /******************************************************************************* @@ -529,7 +601,8 @@ u8 acpi_ut_valid_acpi_character(char cha * FUNCTION: acpi_ut_strtoul64 * * PARAMETERS: String - Null terminated string - * Base - Radix of the string: 10, 16, or ACPI_ANY_BASE + * Base - Radix of the string: 16 or ACPI_ANY_BASE; + * ACPI_ANY_BASE means 'in behalf of to_integer' * ret_integer - Where the converted integer is returned * * RETURN: Status and Converted value @@ -545,16 +618,17 @@ acpi_ut_strtoul64(char *string, u32 base u32 this_digit = 0; acpi_integer return_value = 0; acpi_integer quotient; + acpi_integer dividend; + u32 to_integer_op = (base == ACPI_ANY_BASE); + u32 mode32 = (acpi_gbl_integer_byte_width == 4); + u8 valid_digits = 0; + u8 sign_of0x = 0; + u8 term = 0; - ACPI_FUNCTION_TRACE("ut_stroul64"); - - if ((!string) || !(*string)) { - goto error_exit; - } + ACPI_FUNCTION_TRACE(ut_stroul64); switch (base) { case ACPI_ANY_BASE: - case 10: case 16: break; @@ -563,76 +637,110 @@ acpi_ut_strtoul64(char *string, u32 base return_ACPI_STATUS(AE_BAD_PARAMETER); } + if (!string) { + goto error_exit; + } + /* Skip over any white space in the buffer */ - while (ACPI_IS_SPACE(*string) || *string == '\t') { + while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { string++; } - /* - * If the input parameter Base is zero, then we need to - * determine if it is decimal or hexadecimal: - */ - if (base == 0) { + if (to_integer_op) { + /* + * Base equal to ACPI_ANY_BASE means 'to_integer operation case'. + * We need to determine if it is decimal or hexadecimal. + */ if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { + sign_of0x = 1; base = 16; + + /* Skip over the leading '0x' */ string += 2; } else { base = 10; } } - /* - * For hexadecimal base, skip over the leading - * 0 or 0x, if they are present. - */ - if ((base == 16) && - (*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { - string += 2; + /* Any string left? Check that '0x' is not followed by white space. */ + + if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { + if (to_integer_op) { + goto error_exit; + } else { + goto all_done; + } } - /* Any string left? */ + dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; - if (!(*string)) { - goto error_exit; - } + /* At least one character in the string here */ /* Main loop: convert the string to a 64-bit integer */ while (*string) { if (ACPI_IS_DIGIT(*string)) { + /* Convert ASCII 0-9 to Decimal value */ this_digit = ((u8) * string) - '0'; - } else { - if (base == 10) { - /* Digit is out of range */ + } else if (base == 10) { - goto error_exit; - } + /* Digit is out of range; possible in to_integer case only */ + term = 1; + } else { this_digit = (u8) ACPI_TOUPPER(*string); if (ACPI_IS_XDIGIT((char)this_digit)) { + /* Convert ASCII Hex char to value */ this_digit = this_digit - 'A' + 10; } else { - /* - * We allow non-hex chars, just stop now, same as end-of-string. - * See ACPI spec, string-to-integer conversion. - */ + term = 1; + } + } + + if (term) { + if (to_integer_op) { + goto error_exit; + } else { break; } + } else if ((valid_digits == 0) && (this_digit == 0) + && !sign_of0x) { + + /* Skip zeros */ + string++; + continue; + } + + valid_digits++; + + if (sign_of0x + && ((valid_digits > 16) + || ((valid_digits > 8) && mode32))) { + /* + * This is to_integer operation case. + * No any restrictions for string-to-integer conversion, + * see ACPI spec. + */ + goto error_exit; } /* Divide the digit into the correct position */ (void) - acpi_ut_short_divide((ACPI_INTEGER_MAX - - (acpi_integer) this_digit), base, - "ient, NULL); + acpi_ut_short_divide((dividend - (acpi_integer) this_digit), + base, "ient, NULL); + if (return_value > quotient) { - goto error_exit; + if (to_integer_op) { + goto error_exit; + } else { + break; + } } return_value *= base; @@ -642,6 +750,8 @@ acpi_ut_strtoul64(char *string, u32 base /* All done, normal exit */ + all_done: + *ret_integer = return_value; return_ACPI_STATUS(AE_OK); @@ -719,7 +829,7 @@ acpi_ut_walk_package_tree(union acpi_ope u32 this_index; union acpi_operand_object *this_source_obj; - ACPI_FUNCTION_TRACE("ut_walk_package_tree"); + ACPI_FUNCTION_TRACE(ut_walk_package_tree); state = acpi_ut_create_pkg_state(source_object, target_object, 0); if (!state) { @@ -727,6 +837,7 @@ acpi_ut_walk_package_tree(union acpi_ope } while (state) { + /* Get one element of the package */ this_index = state->pkg.index; @@ -814,31 +925,6 @@ acpi_ut_walk_package_tree(union acpi_ope /******************************************************************************* * - * FUNCTION: acpi_ut_generate_checksum - * - * PARAMETERS: Buffer - Buffer to be scanned - * Length - number of bytes to examine - * - * RETURN: The generated checksum - * - * DESCRIPTION: Generate a checksum on a raw buffer - * - ******************************************************************************/ - -u8 acpi_ut_generate_checksum(u8 * buffer, u32 length) -{ - u32 i; - signed char sum = 0; - - for (i = 0; i < length; i++) { - sum = (signed char)(sum + buffer[i]); - } - - return ((u8) (0 - sum)); -} - -/******************************************************************************* - * * FUNCTION: acpi_ut_error, acpi_ut_warning, acpi_ut_info * * PARAMETERS: module_name - Caller's module name (for error output) @@ -900,36 +986,3 @@ acpi_ut_info(char *module_name, u32 line acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); } - -/******************************************************************************* - * - * FUNCTION: acpi_ut_report_error, Warning, Info - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * - * RETURN: None - * - * DESCRIPTION: Print error message - * - * Note: Legacy only, should be removed when no longer used by drivers. - * - ******************************************************************************/ - -void acpi_ut_report_error(char *module_name, u32 line_number) -{ - - acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number); -} - -void acpi_ut_report_warning(char *module_name, u32 line_number) -{ - - acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number); -} - -void acpi_ut_report_info(char *module_name, u32 line_number) -{ - - acpi_os_printf("ACPI (%s-%04d): ", module_name, line_number); -} diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c index 45a7244..25eb343 100644 --- a/drivers/acpi/utilities/utmutex.c +++ b/drivers/acpi/utilities/utmutex.c @@ -68,19 +68,26 @@ acpi_status acpi_ut_mutex_initialize(voi u32 i; acpi_status status; - ACPI_FUNCTION_TRACE("ut_mutex_initialize"); + ACPI_FUNCTION_TRACE(ut_mutex_initialize); /* * Create each of the predefined mutex objects */ - for (i = 0; i < NUM_MUTEX; i++) { + for (i = 0; i < ACPI_NUM_MUTEX; i++) { status = acpi_ut_create_mutex(i); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } + /* Create the spinlocks for use at interrupt level */ + status = acpi_os_create_lock(&acpi_gbl_gpe_lock); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_os_create_lock(&acpi_gbl_hardware_lock); return_ACPI_STATUS(status); } @@ -100,16 +107,19 @@ void acpi_ut_mutex_terminate(void) { u32 i; - ACPI_FUNCTION_TRACE("ut_mutex_terminate"); + ACPI_FUNCTION_TRACE(ut_mutex_terminate); /* * Delete each predefined mutex object */ - for (i = 0; i < NUM_MUTEX; i++) { + for (i = 0; i < ACPI_NUM_MUTEX; i++) { (void)acpi_ut_delete_mutex(i); } + /* Delete the spinlocks */ + acpi_os_delete_lock(acpi_gbl_gpe_lock); + acpi_os_delete_lock(acpi_gbl_hardware_lock); return_VOID; } @@ -129,9 +139,9 @@ static acpi_status acpi_ut_create_mutex( { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_U32("ut_create_mutex", mutex_id); + ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id); - if (mutex_id > MAX_MUTEX) { + if (mutex_id > ACPI_MAX_MUTEX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -163,9 +173,9 @@ static acpi_status acpi_ut_delete_mutex( { acpi_status status; - ACPI_FUNCTION_TRACE_U32("ut_delete_mutex", mutex_id); + ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id); - if (mutex_id > MAX_MUTEX) { + if (mutex_id > ACPI_MAX_MUTEX) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -192,11 +202,11 @@ static acpi_status acpi_ut_delete_mutex( acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) { acpi_status status; - u32 this_thread_id; + acpi_thread_id this_thread_id; - ACPI_FUNCTION_NAME("ut_acquire_mutex"); + ACPI_FUNCTION_NAME(ut_acquire_mutex); - if (mutex_id > MAX_MUTEX) { + if (mutex_id > ACPI_MAX_MUTEX) { return (AE_BAD_PARAMETER); } @@ -213,7 +223,7 @@ #ifdef ACPI_MUTEX_DEBUG * the mutex ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ - for (i = mutex_id; i < MAX_MUTEX; i++) { + for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) { if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { if (i == mutex_id) { ACPI_ERROR((AE_INFO, @@ -275,16 +285,16 @@ #endif acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) { acpi_status status; - u32 this_thread_id; + acpi_thread_id this_thread_id; - ACPI_FUNCTION_NAME("ut_release_mutex"); + ACPI_FUNCTION_NAME(ut_release_mutex); this_thread_id = acpi_os_get_thread_id(); ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %X releasing Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name(mutex_id))); - if (mutex_id > MAX_MUTEX) { + if (mutex_id > ACPI_MAX_MUTEX) { return (AE_BAD_PARAMETER); } @@ -309,7 +319,7 @@ #ifdef ACPI_MUTEX_DEBUG * ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ - for (i = mutex_id; i < MAX_MUTEX; i++) { + for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) { if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) { if (i == mutex_id) { continue; diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index 7ee2d1d..ba7d8ac 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c @@ -92,7 +92,7 @@ union acpi_operand_object *acpi_ut_creat union acpi_operand_object *object; union acpi_operand_object *second_object; - ACPI_FUNCTION_TRACE_STR("ut_create_internal_object_dbg", + ACPI_FUNCTION_TRACE_STR(ut_create_internal_object_dbg, acpi_ut_get_type_name(type)); /* Allocate the raw object descriptor */ @@ -161,7 +161,7 @@ union acpi_operand_object *acpi_ut_creat union acpi_operand_object *buffer_desc; u8 *buffer = NULL; - ACPI_FUNCTION_TRACE_U32("ut_create_buffer_object", buffer_size); + ACPI_FUNCTION_TRACE_U32(ut_create_buffer_object, buffer_size); /* Create a new Buffer object */ @@ -173,9 +173,10 @@ union acpi_operand_object *acpi_ut_creat /* Create an actual buffer only if size > 0 */ if (buffer_size > 0) { + /* Allocate the actual buffer */ - buffer = ACPI_MEM_CALLOCATE(buffer_size); + buffer = ACPI_ALLOCATE_ZEROED(buffer_size); if (!buffer) { ACPI_ERROR((AE_INFO, "Could not allocate size %X", (u32) buffer_size)); @@ -214,7 +215,7 @@ union acpi_operand_object *acpi_ut_creat union acpi_operand_object *string_desc; char *string; - ACPI_FUNCTION_TRACE_U32("ut_create_string_object", string_size); + ACPI_FUNCTION_TRACE_U32(ut_create_string_object, string_size); /* Create a new String object */ @@ -227,7 +228,7 @@ union acpi_operand_object *acpi_ut_creat * Allocate the actual string buffer -- (Size + 1) for NULL terminator. * NOTE: Zero-length strings are NULL terminated */ - string = ACPI_MEM_CALLOCATE(string_size + 1); + string = ACPI_ALLOCATE_ZEROED(string_size + 1); if (!string) { ACPI_ERROR((AE_INFO, "Could not allocate size %X", (u32) string_size)); @@ -260,7 +261,7 @@ union acpi_operand_object *acpi_ut_creat u8 acpi_ut_valid_internal_object(void *object) { - ACPI_FUNCTION_NAME("ut_valid_internal_object"); + ACPI_FUNCTION_NAME(ut_valid_internal_object); /* Check for a null pointer */ @@ -308,7 +309,7 @@ void *acpi_ut_allocate_object_desc_dbg(c { union acpi_operand_object *object; - ACPI_FUNCTION_TRACE("ut_allocate_object_desc_dbg"); + ACPI_FUNCTION_TRACE(ut_allocate_object_desc_dbg); object = acpi_os_acquire_object(acpi_gbl_operand_cache); if (!object) { @@ -319,6 +320,7 @@ void *acpi_ut_allocate_object_desc_dbg(c } /* Mark the descriptor type */ + memset(object, 0, sizeof(union acpi_operand_object)); ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND); @@ -342,7 +344,7 @@ void *acpi_ut_allocate_object_desc_dbg(c void acpi_ut_delete_object_desc(union acpi_operand_object *object) { - ACPI_FUNCTION_TRACE_PTR("ut_delete_object_desc", object); + ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object); /* Object must be an union acpi_operand_object */ @@ -381,7 +383,7 @@ acpi_ut_get_simple_object_size(union acp acpi_size length; acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE_PTR("ut_get_simple_object_size", internal_object); + ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object); /* * Handle a null object (Could be a uninitialized package @@ -397,6 +399,7 @@ acpi_ut_get_simple_object_size(union acp length = sizeof(union acpi_object); if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) { + /* Object is a named object (reference), just return the length */ *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); @@ -559,7 +562,7 @@ acpi_ut_get_package_object_size(union ac acpi_status status; struct acpi_pkg_info info; - ACPI_FUNCTION_TRACE_PTR("ut_get_package_object_size", internal_object); + ACPI_FUNCTION_TRACE_PTR(ut_get_package_object_size, internal_object); info.length = 0; info.object_space = 0; diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c index 1646131..5a2de92 100644 --- a/drivers/acpi/utilities/utresrc.c +++ b/drivers/acpi/utilities/utresrc.c @@ -45,113 +45,113 @@ #include #include #define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utmisc") +ACPI_MODULE_NAME("utresrc") #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) /* * Strings used to decode resource descriptors. * Used by both the disasssembler and the debugger resource dump routines */ -const char *acpi_gbl_BMdecode[2] = { - "not_bus_master", - "bus_master" +const char *acpi_gbl_bm_decode[] = { + "NotBusMaster", + "BusMaster" }; -const char *acpi_gbl_config_decode[4] = { +const char *acpi_gbl_config_decode[] = { "0 - Good Configuration", "1 - Acceptable Configuration", "2 - Suboptimal Configuration", "3 - ***Invalid Configuration***", }; -const char *acpi_gbl_consume_decode[2] = { - "resource_producer", - "resource_consumer" +const char *acpi_gbl_consume_decode[] = { + "ResourceProducer", + "ResourceConsumer" }; -const char *acpi_gbl_DECdecode[2] = { - "pos_decode", - "sub_decode" +const char *acpi_gbl_dec_decode[] = { + "PosDecode", + "SubDecode" }; -const char *acpi_gbl_HEdecode[2] = { +const char *acpi_gbl_he_decode[] = { "Level", "Edge" }; -const char *acpi_gbl_io_decode[2] = { +const char *acpi_gbl_io_decode[] = { "Decode10", "Decode16" }; -const char *acpi_gbl_LLdecode[2] = { - "active_high", - "active_low" +const char *acpi_gbl_ll_decode[] = { + "ActiveHigh", + "ActiveLow" }; -const char *acpi_gbl_max_decode[2] = { - "max_not_fixed", - "max_fixed" +const char *acpi_gbl_max_decode[] = { + "MaxNotFixed", + "MaxFixed" }; -const char *acpi_gbl_MEMdecode[4] = { - "non_cacheable", +const char *acpi_gbl_mem_decode[] = { + "NonCacheable", "Cacheable", - "write_combining", + "WriteCombining", "Prefetchable" }; -const char *acpi_gbl_min_decode[2] = { - "min_not_fixed", - "min_fixed" +const char *acpi_gbl_min_decode[] = { + "MinNotFixed", + "MinFixed" }; -const char *acpi_gbl_MTPdecode[4] = { - "address_range_memory", - "address_range_reserved", - "address_range_aCPI", - "address_range_nVS" +const char *acpi_gbl_mtp_decode[] = { + "AddressRangeMemory", + "AddressRangeReserved", + "AddressRangeACPI", + "AddressRangeNVS" }; -const char *acpi_gbl_RNGdecode[4] = { - "invalid_ranges", - "non_iSAonly_ranges", - "ISAonly_ranges", - "entire_range" +const char *acpi_gbl_rng_decode[] = { + "InvalidRanges", + "NonISAOnlyRanges", + "ISAOnlyRanges", + "EntireRange" }; -const char *acpi_gbl_RWdecode[2] = { - "read_only", - "read_write" +const char *acpi_gbl_rw_decode[] = { + "ReadOnly", + "ReadWrite" }; -const char *acpi_gbl_SHRdecode[2] = { +const char *acpi_gbl_shr_decode[] = { "Exclusive", "Shared" }; -const char *acpi_gbl_SIZdecode[4] = { +const char *acpi_gbl_siz_decode[] = { "Transfer8", "Transfer8_16", "Transfer16", - "invalid_size" + "InvalidSize" }; -const char *acpi_gbl_TRSdecode[2] = { - "dense_translation", - "sparse_translation" +const char *acpi_gbl_trs_decode[] = { + "DenseTranslation", + "SparseTranslation" }; -const char *acpi_gbl_TTPdecode[2] = { - "type_static", - "type_translation" +const char *acpi_gbl_ttp_decode[] = { + "TypeStatic", + "TypeTranslation" }; -const char *acpi_gbl_TYPdecode[4] = { +const char *acpi_gbl_typ_decode[] = { "Compatibility", - "type_a", - "type_b", - "type_f" + "TypeA", + "TypeB", + "TypeF" }; #endif @@ -240,6 +240,104 @@ static const u8 acpi_gbl_resource_types[ /******************************************************************************* * + * FUNCTION: acpi_ut_walk_aml_resources + * + * PARAMETERS: Aml - Pointer to the raw AML resource template + * aml_length - Length of the entire template + * user_function - Called once for each descriptor found. If + * NULL, a pointer to the end_tag is returned + * Context - Passed to user_function + * + * RETURN: Status + * + * DESCRIPTION: Walk a raw AML resource list(buffer). User function called + * once for each resource found. + * + ******************************************************************************/ + +acpi_status +acpi_ut_walk_aml_resources(u8 * aml, + acpi_size aml_length, + acpi_walk_aml_callback user_function, void **context) +{ + acpi_status status; + u8 *end_aml; + u8 resource_index; + u32 length; + u32 offset = 0; + + ACPI_FUNCTION_TRACE(ut_walk_aml_resources); + + /* The absolute minimum resource template is one end_tag descriptor */ + + if (aml_length < sizeof(struct aml_resource_end_tag)) { + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + } + + /* Point to the end of the resource template buffer */ + + end_aml = aml + aml_length; + + /* Walk the byte list, abort on any invalid descriptor type or length */ + + while (aml < end_aml) { + + /* Validate the Resource Type and Resource Length */ + + status = acpi_ut_validate_resource(aml, &resource_index); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the length of this descriptor */ + + length = acpi_ut_get_descriptor_length(aml); + + /* Invoke the user function */ + + if (user_function) { + status = + user_function(aml, length, offset, resource_index, + context); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + /* An end_tag descriptor terminates this resource template */ + + if (acpi_ut_get_resource_type(aml) == + ACPI_RESOURCE_NAME_END_TAG) { + /* + * There must be at least one more byte in the buffer for + * the 2nd byte of the end_tag + */ + if ((aml + 1) >= end_aml) { + return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + } + + /* Return the pointer to the end_tag if requested */ + + if (!user_function) { + *context = aml; + } + + /* Normal exit */ + + return_ACPI_STATUS(AE_OK); + } + + aml += length; + offset += length; + } + + /* Did not find an end_tag descriptor */ + + return (AE_AML_NO_RESOURCE_END_TAG); +} + +/******************************************************************************* + * * FUNCTION: acpi_ut_validate_resource * * PARAMETERS: Aml - Pointer to the raw AML resource descriptor @@ -273,6 +371,7 @@ acpi_status acpi_ut_validate_resource(vo * Examine the large/small bit in the resource header */ if (resource_type & ACPI_RESOURCE_NAME_LARGE) { + /* Verify the large resource type (name) against the max */ if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) { @@ -376,6 +475,7 @@ u8 acpi_ut_get_resource_type(void *aml) * Examine the large/small bit in the resource header */ if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { + /* Large Resource Type -- bits 6:0 contain the name */ return (ACPI_GET8(aml)); @@ -411,6 +511,7 @@ u16 acpi_ut_get_resource_length(void *am * Examine the large/small bit in the resource header */ if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { + /* Large Resource type -- bytes 1-2 contain the 16-bit length */ ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1)); @@ -495,60 +596,21 @@ acpi_ut_get_resource_end_tag(union acpi_ u8 ** end_tag) { acpi_status status; - u8 *aml; - u8 *end_aml; - - ACPI_FUNCTION_TRACE("ut_get_resource_end_tag"); - /* Get start and end pointers */ - - aml = obj_desc->buffer.pointer; - end_aml = aml + obj_desc->buffer.length; + ACPI_FUNCTION_TRACE(ut_get_resource_end_tag); /* Allow a buffer length of zero */ if (!obj_desc->buffer.length) { - *end_tag = aml; + *end_tag = obj_desc->buffer.pointer; return_ACPI_STATUS(AE_OK); } - /* Walk the resource template, one descriptor per iteration */ - - while (aml < end_aml) { - /* Validate the Resource Type and Resource Length */ - - status = acpi_ut_validate_resource(aml, NULL); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* end_tag resource indicates the end of the resource template */ - - if (acpi_ut_get_resource_type(aml) == - ACPI_RESOURCE_NAME_END_TAG) { - /* - * There must be at least one more byte in the buffer for - * the 2nd byte of the end_tag - */ - if ((aml + 1) >= end_aml) { - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); - } - - /* Return the pointer to the end_tag */ - - *end_tag = aml; - return_ACPI_STATUS(AE_OK); - } - - /* - * Point to the next resource descriptor in the AML buffer. The - * descriptor length is guaranteed to be non-zero by resource - * validation above. - */ - aml += acpi_ut_get_descriptor_length(aml); - } + /* Validate the template and get a pointer to the end_tag */ - /* Did not find an end_tag resource descriptor */ + status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer, + obj_desc->buffer.length, NULL, + (void **)end_tag); - return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c index 4b134a7..0f5c5bb 100644 --- a/drivers/acpi/utilities/utstate.c +++ b/drivers/acpi/utilities/utstate.c @@ -96,7 +96,7 @@ void acpi_ut_push_generic_state(union acpi_generic_state **list_head, union acpi_generic_state *state) { - ACPI_FUNCTION_TRACE("ut_push_generic_state"); + ACPI_FUNCTION_TRACE(ut_push_generic_state); /* Push the state object onto the front of the list (stack) */ @@ -123,12 +123,13 @@ union acpi_generic_state *acpi_ut_pop_ge { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE("ut_pop_generic_state"); + ACPI_FUNCTION_TRACE(ut_pop_generic_state); /* Remove the state object at the head of the list (stack) */ state = *list_head; if (state) { + /* Update the list head */ *list_head = state->common.next; @@ -158,9 +159,10 @@ union acpi_generic_state *acpi_ut_create state = acpi_os_acquire_object(acpi_gbl_state_cache); if (state) { + /* Initialize */ memset(state, 0, sizeof(union acpi_generic_state)); - state->common.data_type = ACPI_DESC_TYPE_STATE; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE; } return (state); @@ -183,7 +185,7 @@ struct acpi_thread_state *acpi_ut_create { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE("ut_create_thread_state"); + ACPI_FUNCTION_TRACE(ut_create_thread_state); /* Create the generic state object */ @@ -194,7 +196,7 @@ struct acpi_thread_state *acpi_ut_create /* Init fields specific to the update struct */ - state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_THREAD; state->thread.thread_id = acpi_os_get_thread_id(); return_PTR((struct acpi_thread_state *)state); @@ -220,7 +222,7 @@ union acpi_generic_state *acpi_ut_create { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR("ut_create_update_state", object); + ACPI_FUNCTION_TRACE_PTR(ut_create_update_state, object); /* Create the generic state object */ @@ -231,7 +233,7 @@ union acpi_generic_state *acpi_ut_create /* Init fields specific to the update struct */ - state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_UPDATE; state->update.object = object; state->update.value = action; @@ -257,7 +259,7 @@ union acpi_generic_state *acpi_ut_create { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE_PTR("ut_create_pkg_state", internal_object); + ACPI_FUNCTION_TRACE_PTR(ut_create_pkg_state, internal_object); /* Create the generic state object */ @@ -268,7 +270,7 @@ union acpi_generic_state *acpi_ut_create /* Init fields specific to the update struct */ - state->common.data_type = ACPI_DESC_TYPE_STATE_PACKAGE; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_PACKAGE; state->pkg.source_object = (union acpi_operand_object *)internal_object; state->pkg.dest_object = external_object; state->pkg.index = index; @@ -294,7 +296,7 @@ union acpi_generic_state *acpi_ut_create { union acpi_generic_state *state; - ACPI_FUNCTION_TRACE("ut_create_control_state"); + ACPI_FUNCTION_TRACE(ut_create_control_state); /* Create the generic state object */ @@ -305,7 +307,7 @@ union acpi_generic_state *acpi_ut_create /* Init fields specific to the control struct */ - state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL; + state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL; state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING; return_PTR(state); @@ -319,15 +321,19 @@ union acpi_generic_state *acpi_ut_create * * RETURN: None * - * DESCRIPTION: Put a state object back into the global state cache. The object - * is not actually freed at this time. + * DESCRIPTION: Release a state object to the state cache. NULL state objects + * are ignored. * ******************************************************************************/ void acpi_ut_delete_generic_state(union acpi_generic_state *state) { - ACPI_FUNCTION_TRACE("ut_delete_generic_state"); + ACPI_FUNCTION_TRACE(ut_delete_generic_state); + + /* Ignore null state */ - (void)acpi_os_release_object(acpi_gbl_state_cache, state); + if (state) { + (void)acpi_os_release_object(acpi_gbl_state_cache, state); + } return_VOID; } diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index 308a960..3538f69 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -41,8 +41,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#include - #include #include #include @@ -67,7 +65,7 @@ acpi_status acpi_initialize_subsystem(vo { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_initialize_subsystem"); + ACPI_FUNCTION_TRACE(acpi_initialize_subsystem); ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace()); @@ -109,6 +107,8 @@ acpi_status acpi_initialize_subsystem(vo return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem) + /******************************************************************************* * * FUNCTION: acpi_enable_subsystem @@ -121,12 +121,11 @@ acpi_status acpi_initialize_subsystem(vo * Puts system into ACPI mode if it isn't already. * ******************************************************************************/ - acpi_status acpi_enable_subsystem(u32 flags) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_enable_subsystem"); + ACPI_FUNCTION_TRACE(acpi_enable_subsystem); /* * We must initialize the hardware before we can enable ACPI. @@ -152,7 +151,7 @@ acpi_status acpi_enable_subsystem(u32 fl status = acpi_enable(); if (ACPI_FAILURE(status)) { - ACPI_WARNING((AE_INFO, "acpi_enable failed")); + ACPI_WARNING((AE_INFO, "AcpiEnable failed")); return_ACPI_STATUS(status); } } @@ -229,6 +228,8 @@ acpi_status acpi_enable_subsystem(u32 fl return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_enable_subsystem) + /******************************************************************************* * * FUNCTION: acpi_initialize_objects @@ -241,12 +242,11 @@ acpi_status acpi_enable_subsystem(u32 fl * objects and executing AML code for Regions, buffers, etc. * ******************************************************************************/ - acpi_status acpi_initialize_objects(u32 flags) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE("acpi_initialize_objects"); + ACPI_FUNCTION_TRACE(acpi_initialize_objects); /* * Run all _REG methods @@ -257,7 +257,7 @@ acpi_status acpi_initialize_objects(u32 */ if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "[Init] Executing _REG op_region methods\n")); + "[Init] Executing _REG OpRegion methods\n")); status = acpi_ev_initialize_op_regions(); if (ACPI_FAILURE(status)) { @@ -305,6 +305,8 @@ acpi_status acpi_initialize_objects(u32 return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_initialize_objects) + /******************************************************************************* * * FUNCTION: acpi_terminate @@ -316,12 +318,11 @@ acpi_status acpi_initialize_objects(u32 * DESCRIPTION: Shutdown the ACPI subsystem. Release all resources. * ******************************************************************************/ - acpi_status acpi_terminate(void) { acpi_status status; - ACPI_FUNCTION_TRACE("acpi_terminate"); + ACPI_FUNCTION_TRACE(acpi_terminate); /* Terminate the AML Debugger if present */ @@ -348,6 +349,8 @@ #endif return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_terminate) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -362,7 +365,6 @@ #ifdef ACPI_FUTURE_USAGE * initialized successfully. * ******************************************************************************/ - acpi_status acpi_subsystem_status(void) { @@ -373,6 +375,8 @@ acpi_status acpi_subsystem_status(void) } } +ACPI_EXPORT_SYMBOL(acpi_subsystem_status) + /******************************************************************************* * * FUNCTION: acpi_get_system_info @@ -390,14 +394,13 @@ acpi_status acpi_subsystem_status(void) * and the value of out_buffer is undefined. * ******************************************************************************/ - acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) { struct acpi_system_info *info_ptr; acpi_status status; u32 i; - ACPI_FUNCTION_TRACE("acpi_get_system_info"); + ACPI_FUNCTION_TRACE(acpi_get_system_info); /* Parameter validation */ @@ -448,15 +451,15 @@ acpi_status acpi_get_system_info(struct /* Current status of the ACPI tables, per table type */ - info_ptr->num_table_types = NUM_ACPI_TABLE_TYPES; - for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { + info_ptr->num_table_types = ACPI_TABLE_ID_MAX + 1; + for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { info_ptr->table_info[i].count = acpi_gbl_table_lists[i].count; } return_ACPI_STATUS(AE_OK); } -EXPORT_SYMBOL(acpi_get_system_info); +ACPI_EXPORT_SYMBOL(acpi_get_system_info) /***************************************************************************** * @@ -472,7 +475,6 @@ EXPORT_SYMBOL(acpi_get_system_info); * TBD: When a second function is added, must save the Function also. * ****************************************************************************/ - acpi_status acpi_install_initialization_handler(acpi_init_handler handler, u32 function) { @@ -489,6 +491,7 @@ acpi_install_initialization_handler(acpi return AE_OK; } +ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) #endif /* ACPI_FUTURE_USAGE */ /***************************************************************************** @@ -502,10 +505,9 @@ #endif /* ACPI_FUTURE_USAGE */ * DESCRIPTION: Empty all caches (delete the cached objects) * ****************************************************************************/ - acpi_status acpi_purge_cached_objects(void) { - ACPI_FUNCTION_TRACE("acpi_purge_cached_objects"); + ACPI_FUNCTION_TRACE(acpi_purge_cached_objects); (void)acpi_os_purge_cache(acpi_gbl_state_cache); (void)acpi_os_purge_cache(acpi_gbl_operand_cache); @@ -513,3 +515,5 @@ acpi_status acpi_purge_cached_objects(vo (void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache); return_ACPI_STATUS(AE_OK); } + +ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 6458c47..6b51685 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -273,11 +273,13 @@ acpi_evaluate_integer(acpi_handle handle status = acpi_evaluate_object(handle, pathname, arguments, &buffer); if (ACPI_FAILURE(status)) { acpi_util_eval_error(handle, pathname, status); + kfree(element); return_ACPI_STATUS(status); } if (element->type != ACPI_TYPE_INTEGER) { acpi_util_eval_error(handle, pathname, AE_BAD_DATA); + kfree(element); return_ACPI_STATUS(AE_BAD_DATA); } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bd48875..e7e9a69 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -323,7 +323,7 @@ acpi_video_device_lcd_query_levels(struc if (!ACPI_SUCCESS(status)) return_VALUE(status); obj = (union acpi_object *)buffer.pointer; - if (!obj && (obj->type != ACPI_TYPE_PACKAGE)) { + if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _BCL data\n")); status = -EFAULT; goto err; @@ -1294,7 +1294,7 @@ acpi_video_bus_get_one_device(struct acp struct acpi_video_bus *video) { unsigned long device_id; - int status, result; + int status; struct acpi_video_device *data; ACPI_FUNCTION_TRACE("acpi_video_bus_get_one_device"); @@ -1346,8 +1346,11 @@ acpi_video_bus_get_one_device(struct acp if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n")); - result = -ENODEV; - goto end; + if(data->brightness) + kfree(data->brightness->levels); + kfree(data->brightness); + kfree(data); + return -ENODEV; } down(&video->sem); @@ -1359,7 +1362,6 @@ acpi_video_bus_get_one_device(struct acp return_VALUE(0); } - end: return_VALUE(-ENOENT); } @@ -1643,8 +1645,9 @@ static int acpi_video_bus_put_devices(st printk(KERN_WARNING PREFIX "hhuuhhuu bug in acpi video driver.\n"); + if (data->brightness) + kfree(data->brightness->levels); kfree(data->brightness); - kfree(data); } @@ -1785,6 +1788,10 @@ static int acpi_video_bus_add(struct acp if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n")); + acpi_video_bus_stop_devices(video); + acpi_video_bus_put_devices(video); + kfree(video->attached_array); + acpi_video_bus_remove_fs(device); result = -ENODEV; goto end; } @@ -1796,10 +1803,8 @@ static int acpi_video_bus_add(struct acp video->flags.post ? "yes" : "no"); end: - if (result) { - acpi_video_bus_remove_fs(device); + if (result) kfree(video); - } return_VALUE(result); } diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 7f7ec28..f2eeaf9 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -951,7 +951,7 @@ static int fs_open(struct atm_vcc *atm_v it most likely that the chip will notice it. It also prevents us from having to wait for completion. On the other hand, we may need to wait for completion anyway, to see if it completed - succesfully. */ + successfully. */ switch (atm_vcc->qos.aal) { case ATM_AAL2: diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 05983a3..92923bf 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -167,13 +167,9 @@ fore200e_atm2fore_aal(int aal) static char* fore200e_irq_itoa(int irq) { -#if defined(__sparc_v9__) - return __irq_itoa(irq); -#else static char str[8]; sprintf(str, "%d", irq); return str; -#endif } diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index f0eff3d..80502dc 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -38,3 +38,7 @@ config DEBUG_DRIVER If you are unsure about this, say N here. endmenu + +config SYS_HYPERVISOR + bool + default n diff --git a/drivers/base/Makefile b/drivers/base/Makefile index e99471d..b539e5e 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -5,10 +5,12 @@ obj-y := core.o sys.o bus.o dd.o \ cpu.o firmware.o init.o map.o dmapool.o \ attribute_container.o transport_class.o obj-y += power/ +obj-$(CONFIG_ISA) += isa.o obj-$(CONFIG_FW_LOADER) += firmware_class.o obj-$(CONFIG_NUMA) += node.o obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o obj-$(CONFIG_SMP) += topology.o +obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o ifeq ($(CONFIG_DEBUG_DRIVER),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index 2a7d7ae..2222073 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c @@ -236,7 +236,6 @@ attribute_container_remove_device(struct } up(&attribute_container_mutex); } -EXPORT_SYMBOL_GPL(attribute_container_remove_device); /** * attribute_container_device_trigger - execute a trigger for each matching classdev @@ -276,7 +275,6 @@ attribute_container_device_trigger(struc } up(&attribute_container_mutex); } -EXPORT_SYMBOL_GPL(attribute_container_device_trigger); /** * attribute_container_trigger - trigger a function for each matching container @@ -304,7 +302,6 @@ attribute_container_trigger(struct devic } up(&attribute_container_mutex); } -EXPORT_SYMBOL_GPL(attribute_container_trigger); /** * attribute_container_add_attrs - add attributes @@ -333,7 +330,6 @@ attribute_container_add_attrs(struct cla return 0; } -EXPORT_SYMBOL_GPL(attribute_container_add_attrs); /** * attribute_container_add_class_device - same function as class_device_add @@ -352,7 +348,6 @@ attribute_container_add_class_device(str return error; return attribute_container_add_attrs(classdev); } -EXPORT_SYMBOL_GPL(attribute_container_add_class_device); /** * attribute_container_add_class_device_adapter - simple adapter for triggers @@ -367,7 +362,6 @@ attribute_container_add_class_device_ada { return attribute_container_add_class_device(classdev); } -EXPORT_SYMBOL_GPL(attribute_container_add_class_device_adapter); /** * attribute_container_remove_attrs - remove any attribute files @@ -389,7 +383,6 @@ attribute_container_remove_attrs(struct for (i = 0; attrs[i]; i++) class_device_remove_file(classdev, attrs[i]); } -EXPORT_SYMBOL_GPL(attribute_container_remove_attrs); /** * attribute_container_class_device_del - equivalent of class_device_del @@ -405,7 +398,6 @@ attribute_container_class_device_del(str attribute_container_remove_attrs(classdev); class_device_del(classdev); } -EXPORT_SYMBOL_GPL(attribute_container_class_device_del); /** * attribute_container_find_class_device - find the corresponding class_device diff --git a/drivers/base/base.h b/drivers/base/base.h index 5735b38..c3b8dc9 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -5,13 +5,21 @@ extern int devices_init(void); extern int buses_init(void); extern int classes_init(void); extern int firmware_init(void); +#ifdef CONFIG_SYS_HYPERVISOR +extern int hypervisor_init(void); +#else +static inline int hypervisor_init(void) { return 0; } +#endif extern int platform_bus_init(void); extern int system_bus_init(void); extern int cpu_dev_init(void); extern int attribute_container_init(void); extern int bus_add_device(struct device * dev); +extern void bus_attach_device(struct device * dev); extern void bus_remove_device(struct device * dev); +extern struct bus_type *get_bus(struct bus_type * bus); +extern void put_bus(struct bus_type * bus); extern int bus_add_driver(struct device_driver *); extern void bus_remove_driver(struct device_driver *); @@ -34,4 +42,5 @@ struct class_device_attribute *to_class_ return container_of(_attr, struct class_device_attribute, attr); } +extern char *make_class_name(const char *name, struct kobject *kobj); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 76656ac..050d86d 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -362,8 +362,7 @@ static void device_remove_attrs(struct b * @dev: device being added * * - Add the device to its bus's list of devices. - * - Try to attach to driver. - * - Create link to device's physical location. + * - Create link to device's bus. */ int bus_add_device(struct device * dev) { @@ -372,11 +371,10 @@ int bus_add_device(struct device * dev) if (bus) { pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); - device_attach(dev); - klist_add_tail(&dev->knode_bus, &bus->klist_devices); error = device_add_attrs(bus, dev); if (!error) { sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); + sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "subsystem"); sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); } } @@ -384,6 +382,22 @@ int bus_add_device(struct device * dev) } /** + * bus_attach_device - add device to bus + * @dev: device tried to attach to a driver + * + * - Try to attach to driver. + */ +void bus_attach_device(struct device * dev) +{ + struct bus_type * bus = dev->bus; + + if (bus) { + device_attach(dev); + klist_add_tail(&dev->knode_bus, &bus->klist_devices); + } +} + +/** * bus_remove_device - remove device from bus * @dev: device to be removed * @@ -395,6 +409,7 @@ int bus_add_device(struct device * dev) void bus_remove_device(struct device * dev) { if (dev->bus) { + sysfs_remove_link(&dev->kobj, "subsystem"); sysfs_remove_link(&dev->kobj, "bus"); sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); device_remove_attrs(dev->bus, dev); @@ -732,14 +747,9 @@ EXPORT_SYMBOL_GPL(bus_for_each_dev); EXPORT_SYMBOL_GPL(bus_find_device); EXPORT_SYMBOL_GPL(bus_for_each_drv); -EXPORT_SYMBOL_GPL(bus_add_device); -EXPORT_SYMBOL_GPL(bus_remove_device); EXPORT_SYMBOL_GPL(bus_register); EXPORT_SYMBOL_GPL(bus_unregister); EXPORT_SYMBOL_GPL(bus_rescan_devices); -EXPORT_SYMBOL_GPL(get_bus); -EXPORT_SYMBOL_GPL(put_bus); -EXPORT_SYMBOL_GPL(find_bus); EXPORT_SYMBOL_GPL(bus_create_file); EXPORT_SYMBOL_GPL(bus_remove_file); diff --git a/drivers/base/class.c b/drivers/base/class.c index b1ea4df..9aa1274 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -91,14 +91,14 @@ void class_remove_file(struct class * cl sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr); } -struct class * class_get(struct class * cls) +static struct class *class_get(struct class *cls) { if (cls) return container_of(subsys_get(&cls->subsys), struct class, subsys); return NULL; } -void class_put(struct class * cls) +static void class_put(struct class * cls) { if (cls) subsys_put(&cls->subsys); @@ -142,6 +142,7 @@ int class_register(struct class * cls) pr_debug("device class '%s': registering\n", cls->name); INIT_LIST_HEAD(&cls->children); + INIT_LIST_HEAD(&cls->devices); INIT_LIST_HEAD(&cls->interfaces); init_MUTEX(&cls->sem); error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name); @@ -504,22 +505,21 @@ void class_device_initialize(struct clas INIT_LIST_HEAD(&class_dev->node); } -static char *make_class_name(struct class_device *class_dev) +char *make_class_name(const char *name, struct kobject *kobj) { - char *name; + char *class_name; int size; - size = strlen(class_dev->class->name) + - strlen(kobject_name(&class_dev->kobj)) + 2; + size = strlen(name) + strlen(kobject_name(kobj)) + 2; - name = kmalloc(size, GFP_KERNEL); - if (!name) + class_name = kmalloc(size, GFP_KERNEL); + if (!class_name) return ERR_PTR(-ENOMEM); - strcpy(name, class_dev->class->name); - strcat(name, ":"); - strcat(name, kobject_name(&class_dev->kobj)); - return name; + strcpy(class_name, name); + strcat(class_name, ":"); + strcat(class_name, kobject_name(kobj)); + return class_name; } int class_device_add(struct class_device *class_dev) @@ -535,18 +535,22 @@ int class_device_add(struct class_device return -EINVAL; if (!strlen(class_dev->class_id)) - goto register_done; + goto out1; parent_class = class_get(class_dev->class); if (!parent_class) - goto register_done; + goto out1; + parent_class_dev = class_device_get(class_dev->parent); pr_debug("CLASS: registering class device: ID = '%s'\n", class_dev->class_id); /* first, register with generic layer. */ - kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id); + error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id); + if (error) + goto out2; + if (parent_class_dev) class_dev->kobj.parent = &parent_class_dev->kobj; else @@ -554,41 +558,58 @@ int class_device_add(struct class_device error = kobject_add(&class_dev->kobj); if (error) - goto register_done; + goto out2; /* add the needed attributes to this device */ + sysfs_create_link(&class_dev->kobj, &parent_class->subsys.kset.kobj, "subsystem"); class_dev->uevent_attr.attr.name = "uevent"; class_dev->uevent_attr.attr.mode = S_IWUSR; class_dev->uevent_attr.attr.owner = parent_class->owner; class_dev->uevent_attr.store = store_uevent; - class_device_create_file(class_dev, &class_dev->uevent_attr); + error = class_device_create_file(class_dev, &class_dev->uevent_attr); + if (error) + goto out3; if (MAJOR(class_dev->devt)) { struct class_device_attribute *attr; attr = kzalloc(sizeof(*attr), GFP_KERNEL); if (!attr) { error = -ENOMEM; - kobject_del(&class_dev->kobj); - goto register_done; + goto out4; } attr->attr.name = "dev"; attr->attr.mode = S_IRUGO; attr->attr.owner = parent_class->owner; attr->show = show_dev; - class_device_create_file(class_dev, attr); + error = class_device_create_file(class_dev, attr); + if (error) { + kfree(attr); + goto out4; + } + class_dev->devt_attr = attr; } - class_device_add_attrs(class_dev); + error = class_device_add_attrs(class_dev); + if (error) + goto out5; + if (class_dev->dev) { - class_name = make_class_name(class_dev); - sysfs_create_link(&class_dev->kobj, - &class_dev->dev->kobj, "device"); - sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, - class_name); + class_name = make_class_name(class_dev->class->name, + &class_dev->kobj); + error = sysfs_create_link(&class_dev->kobj, + &class_dev->dev->kobj, "device"); + if (error) + goto out6; + error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, + class_name); + if (error) + goto out7; } - class_device_add_groups(class_dev); + error = class_device_add_groups(class_dev); + if (error) + goto out8; kobject_uevent(&class_dev->kobj, KOBJ_ADD); @@ -601,11 +622,28 @@ int class_device_add(struct class_device } up(&parent_class->sem); - register_done: - if (error) { - class_put(parent_class); + goto out1; + + out8: + if (class_dev->dev) + sysfs_remove_link(&class_dev->kobj, class_name); + out7: + if (class_dev->dev) + sysfs_remove_link(&class_dev->kobj, "device"); + out6: + class_device_remove_attrs(class_dev); + out5: + if (class_dev->devt_attr) + class_device_remove_file(class_dev, class_dev->devt_attr); + out4: + class_device_remove_file(class_dev, &class_dev->uevent_attr); + out3: + kobject_del(&class_dev->kobj); + out2: + if(parent_class_dev) class_device_put(parent_class_dev); - } + class_put(parent_class); + out1: class_device_put(class_dev); kfree(class_name); return error; @@ -695,10 +733,12 @@ void class_device_del(struct class_devic } if (class_dev->dev) { - class_name = make_class_name(class_dev); + class_name = make_class_name(class_dev->class->name, + &class_dev->kobj); sysfs_remove_link(&class_dev->kobj, "device"); sysfs_remove_link(&class_dev->dev->kobj, class_name); } + sysfs_remove_link(&class_dev->kobj, "subsystem"); class_device_remove_file(class_dev, &class_dev->uevent_attr); if (class_dev->devt_attr) class_device_remove_file(class_dev, class_dev->devt_attr); @@ -760,14 +800,16 @@ int class_device_rename(struct class_dev new_name); if (class_dev->dev) - old_class_name = make_class_name(class_dev); + old_class_name = make_class_name(class_dev->class->name, + &class_dev->kobj); strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); error = kobject_rename(&class_dev->kobj, new_name); if (class_dev->dev) { - new_class_name = make_class_name(class_dev); + new_class_name = make_class_name(class_dev->class->name, + &class_dev->kobj); sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, new_class_name); sysfs_remove_link(&class_dev->dev->kobj, old_class_name); @@ -858,8 +900,6 @@ EXPORT_SYMBOL_GPL(class_create_file); EXPORT_SYMBOL_GPL(class_remove_file); EXPORT_SYMBOL_GPL(class_register); EXPORT_SYMBOL_GPL(class_unregister); -EXPORT_SYMBOL_GPL(class_get); -EXPORT_SYMBOL_GPL(class_put); EXPORT_SYMBOL_GPL(class_create); EXPORT_SYMBOL_GPL(class_destroy); diff --git a/drivers/base/core.c b/drivers/base/core.c index 6b355bd..27c2176 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -15,6 +15,7 @@ #include #include #include #include +#include #include @@ -28,6 +29,22 @@ int (*platform_notify_remove)(struct dev * sysfs bindings for devices. */ +/** + * dev_driver_string - Return a device's driver name, if at all possible + * @dev: struct device to get the name of + * + * Will return the device's driver's name if it is bound to a device. If + * the device is not bound to a device, it will return the name of the bus + * it is attached to. If it is not attached to a bus either, an empty + * string will be returned. + */ +const char *dev_driver_string(struct device *dev) +{ + return dev->driver ? dev->driver->name : + (dev->bus ? dev->bus->name : ""); +} +EXPORT_SYMBOL_GPL(dev_driver_string); + #define to_dev(obj) container_of(obj, struct device, kobj) #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) @@ -98,6 +115,8 @@ static int dev_uevent_filter(struct kset struct device *dev = to_dev(kobj); if (dev->bus) return 1; + if (dev->class) + return 1; } return 0; } @@ -106,7 +125,11 @@ static const char *dev_uevent_name(struc { struct device *dev = to_dev(kobj); - return dev->bus->name; + if (dev->bus) + return dev->bus->name; + if (dev->class) + return dev->class->name; + return NULL; } static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, @@ -117,6 +140,16 @@ static int dev_uevent(struct kset *kset, int length = 0; int retval = 0; + /* add the major/minor if present */ + if (MAJOR(dev->devt)) { + add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "MAJOR=%u", MAJOR(dev->devt)); + add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "MINOR=%u", MINOR(dev->devt)); + } + /* add bus name of physical device */ if (dev->bus) add_uevent_var(envp, num_envp, &i, @@ -161,6 +194,12 @@ static ssize_t store_uevent(struct devic return count; } +static ssize_t show_dev(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return print_dev_t(buf, dev->devt); +} + /* * devices_subsys - structure to be registered with kobject core. */ @@ -231,6 +270,7 @@ void device_initialize(struct device *de klist_init(&dev->klist_children, klist_children_get, klist_children_put); INIT_LIST_HEAD(&dev->dma_pools); + INIT_LIST_HEAD(&dev->node); init_MUTEX(&dev->sem); device_init_wakeup(dev, 0); } @@ -249,6 +289,7 @@ void device_initialize(struct device *de int device_add(struct device *dev) { struct device *parent = NULL; + char *class_name = NULL; int error = -EINVAL; dev = get_device(dev); @@ -274,23 +315,69 @@ int device_add(struct device *dev) dev->uevent_attr.store = store_uevent; device_create_file(dev, &dev->uevent_attr); - kobject_uevent(&dev->kobj, KOBJ_ADD); + if (MAJOR(dev->devt)) { + struct device_attribute *attr; + attr = kzalloc(sizeof(*attr), GFP_KERNEL); + if (!attr) { + error = -ENOMEM; + goto PMError; + } + attr->attr.name = "dev"; + attr->attr.mode = S_IRUGO; + if (dev->driver) + attr->attr.owner = dev->driver->owner; + attr->show = show_dev; + error = device_create_file(dev, attr); + if (error) { + kfree(attr); + goto attrError; + } + + dev->devt_attr = attr; + } + + if (dev->class) { + sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj, + "subsystem"); + sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, + dev->bus_id); + + sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); + class_name = make_class_name(dev->class->name, &dev->kobj); + sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); + } + if ((error = device_pm_add(dev))) goto PMError; if ((error = bus_add_device(dev))) goto BusError; + kobject_uevent(&dev->kobj, KOBJ_ADD); + bus_attach_device(dev); if (parent) klist_add_tail(&dev->knode_parent, &parent->klist_children); + if (dev->class) { + /* tie the class to the device */ + down(&dev->class->sem); + list_add_tail(&dev->node, &dev->class->devices); + up(&dev->class->sem); + } + /* notify platform of device entry */ if (platform_notify) platform_notify(dev); Done: + kfree(class_name); put_device(dev); return error; BusError: device_pm_remove(dev); PMError: + if (dev->devt_attr) { + device_remove_file(dev, dev->devt_attr); + kfree(dev->devt_attr); + } + attrError: kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); Error: @@ -362,9 +449,23 @@ void put_device(struct device * dev) void device_del(struct device * dev) { struct device * parent = dev->parent; + char *class_name = NULL; if (parent) klist_del(&dev->knode_parent); + if (dev->devt_attr) + device_remove_file(dev, dev->devt_attr); + if (dev->class) { + sysfs_remove_link(&dev->kobj, "subsystem"); + sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); + class_name = make_class_name(dev->class->name, &dev->kobj); + sysfs_remove_link(&dev->kobj, "device"); + sysfs_remove_link(&dev->parent->kobj, class_name); + kfree(class_name); + down(&dev->class->sem); + list_del_init(&dev->node); + up(&dev->class->sem); + } device_remove_file(dev, &dev->uevent_attr); /* Notify the platform of the removal, in case they @@ -449,3 +550,98 @@ EXPORT_SYMBOL_GPL(put_device); EXPORT_SYMBOL_GPL(device_create_file); EXPORT_SYMBOL_GPL(device_remove_file); + + +static void device_create_release(struct device *dev) +{ + pr_debug("%s called for %s\n", __FUNCTION__, dev->bus_id); + kfree(dev); +} + +/** + * device_create - creates a device and registers it with sysfs + * @cs: pointer to the struct class that this device should be registered to. + * @parent: pointer to the parent struct device of this new device, if any. + * @dev: the dev_t for the char device to be added. + * @fmt: string for the class device's name + * + * This function can be used by char device classes. A struct + * device will be created in sysfs, registered to the specified + * class. + * A "dev" file will be created, showing the dev_t for the device, if + * the dev_t is not 0,0. + * If a pointer to a parent struct device is passed in, the newly + * created struct device will be a child of that device in sysfs. The + * pointer to the struct device will be returned from the call. Any + * further sysfs files that might be required can be created using this + * pointer. + * + * Note: the struct class passed to this function must have previously + * been created with a call to class_create(). + */ +struct device *device_create(struct class *class, struct device *parent, + dev_t devt, char *fmt, ...) +{ + va_list args; + struct device *dev = NULL; + int retval = -ENODEV; + + if (class == NULL || IS_ERR(class)) + goto error; + if (parent == NULL) { + printk(KERN_WARNING "%s does not work yet for NULL parents\n", __FUNCTION__); + goto error; + } + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + retval = -ENOMEM; + goto error; + } + + dev->devt = devt; + dev->class = class; + dev->parent = parent; + dev->release = device_create_release; + + va_start(args, fmt); + vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args); + va_end(args); + retval = device_register(dev); + if (retval) + goto error; + + return dev; + +error: + kfree(dev); + return ERR_PTR(retval); +} +EXPORT_SYMBOL_GPL(device_create); + +/** + * device_destroy - removes a device that was created with device_create() + * @class: the pointer to the struct class that this device was registered * with. + * @dev: the dev_t of the device that was previously registered. + * + * This call unregisters and cleans up a class device that was created with a + * call to class_device_create() + */ +void device_destroy(struct class *class, dev_t devt) +{ + struct device *dev = NULL; + struct device *dev_tmp; + + down(&class->sem); + list_for_each_entry(dev_tmp, &class->devices, node) { + if (dev_tmp->devt == devt) { + dev = dev_tmp; + break; + } + } + up(&class->sem); + + if (dev) + device_unregister(dev); +} +EXPORT_SYMBOL_GPL(device_destroy); diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 0c99ae6..5d6c011 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -15,7 +15,7 @@ #include #include #include #include -#include +#include #include #include "base.h" @@ -36,7 +36,7 @@ static int loading_timeout = 10; /* In s /* fw_lock could be moved to 'struct firmware_priv' but since it is just * guarding for corner cases a global lock should be OK */ -static DECLARE_MUTEX(fw_lock); +static DEFINE_MUTEX(fw_lock); struct firmware_priv { char fw_id[FIRMWARE_NAME_MAX]; @@ -142,9 +142,9 @@ firmware_loading_store(struct class_devi switch (loading) { case 1: - down(&fw_lock); + mutex_lock(&fw_lock); if (!fw_priv->fw) { - up(&fw_lock); + mutex_unlock(&fw_lock); break; } vfree(fw_priv->fw->data); @@ -152,7 +152,7 @@ firmware_loading_store(struct class_devi fw_priv->fw->size = 0; fw_priv->alloc_size = 0; set_bit(FW_STATUS_LOADING, &fw_priv->status); - up(&fw_lock); + mutex_unlock(&fw_lock); break; case 0: if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) { @@ -185,7 +185,7 @@ firmware_data_read(struct kobject *kobj, struct firmware *fw; ssize_t ret_count = count; - down(&fw_lock); + mutex_lock(&fw_lock); fw = fw_priv->fw; if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { ret_count = -ENODEV; @@ -200,7 +200,7 @@ firmware_data_read(struct kobject *kobj, memcpy(buffer, fw->data + offset, ret_count); out: - up(&fw_lock); + mutex_unlock(&fw_lock); return ret_count; } @@ -253,7 +253,7 @@ firmware_data_write(struct kobject *kobj if (!capable(CAP_SYS_RAWIO)) return -EPERM; - down(&fw_lock); + mutex_lock(&fw_lock); fw = fw_priv->fw; if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { retval = -ENODEV; @@ -268,7 +268,7 @@ firmware_data_write(struct kobject *kobj fw->size = max_t(size_t, offset + count, fw->size); retval = count; out: - up(&fw_lock); + mutex_unlock(&fw_lock); return retval; } @@ -436,14 +436,14 @@ _request_firmware(const struct firmware } else wait_for_completion(&fw_priv->completion); - down(&fw_lock); + mutex_lock(&fw_lock); if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { retval = -ENOENT; release_firmware(fw_priv->fw); *firmware_p = NULL; } fw_priv->fw = NULL; - up(&fw_lock); + mutex_unlock(&fw_lock); class_device_unregister(class_dev); goto out; diff --git a/drivers/base/hypervisor.c b/drivers/base/hypervisor.c new file mode 100644 index 0000000..0c85e9d --- /dev/null +++ b/drivers/base/hypervisor.c @@ -0,0 +1,19 @@ +/* + * hypervisor.c - /sys/hypervisor subsystem. + * + * This file is released under the GPLv2 + * + */ + +#include +#include + +#include "base.h" + +decl_subsys(hypervisor, NULL, NULL); +EXPORT_SYMBOL_GPL(hypervisor_subsys); + +int __init hypervisor_init(void) +{ + return subsystem_register(&hypervisor_subsys); +} diff --git a/drivers/base/init.c b/drivers/base/init.c index c648914..3713815 100644 --- a/drivers/base/init.c +++ b/drivers/base/init.c @@ -27,6 +27,7 @@ void __init driver_init(void) buses_init(); classes_init(); firmware_init(); + hypervisor_init(); /* These are also core pieces, but must come after the * core core pieces. diff --git a/drivers/base/isa.c b/drivers/base/isa.c new file mode 100644 index 0000000..d222239 --- /dev/null +++ b/drivers/base/isa.c @@ -0,0 +1,180 @@ +/* + * ISA bus. + */ + +#include +#include +#include +#include +#include +#include + +static struct device isa_bus = { + .bus_id = "isa" +}; + +struct isa_dev { + struct device dev; + struct device *next; + unsigned int id; +}; + +#define to_isa_dev(x) container_of((x), struct isa_dev, dev) + +static int isa_bus_match(struct device *dev, struct device_driver *driver) +{ + struct isa_driver *isa_driver = to_isa_driver(driver); + + if (dev->platform_data == isa_driver) { + if (!isa_driver->match || + isa_driver->match(dev, to_isa_dev(dev)->id)) + return 1; + dev->platform_data = NULL; + } + return 0; +} + +static int isa_bus_probe(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->probe) + return isa_driver->probe(dev, to_isa_dev(dev)->id); + + return 0; +} + +static int isa_bus_remove(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->remove) + return isa_driver->remove(dev, to_isa_dev(dev)->id); + + return 0; +} + +static void isa_bus_shutdown(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->shutdown) + isa_driver->shutdown(dev, to_isa_dev(dev)->id); +} + +static int isa_bus_suspend(struct device *dev, pm_message_t state) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->suspend) + return isa_driver->suspend(dev, to_isa_dev(dev)->id, state); + + return 0; +} + +static int isa_bus_resume(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->resume) + return isa_driver->resume(dev, to_isa_dev(dev)->id); + + return 0; +} + +static struct bus_type isa_bus_type = { + .name = "isa", + .match = isa_bus_match, + .probe = isa_bus_probe, + .remove = isa_bus_remove, + .shutdown = isa_bus_shutdown, + .suspend = isa_bus_suspend, + .resume = isa_bus_resume +}; + +static void isa_dev_release(struct device *dev) +{ + kfree(to_isa_dev(dev)); +} + +void isa_unregister_driver(struct isa_driver *isa_driver) +{ + struct device *dev = isa_driver->devices; + + while (dev) { + struct device *tmp = to_isa_dev(dev)->next; + device_unregister(dev); + dev = tmp; + } + driver_unregister(&isa_driver->driver); +} +EXPORT_SYMBOL_GPL(isa_unregister_driver); + +int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev) +{ + int error; + unsigned int id; + + isa_driver->driver.bus = &isa_bus_type; + isa_driver->devices = NULL; + + error = driver_register(&isa_driver->driver); + if (error) + return error; + + for (id = 0; id < ndev; id++) { + struct isa_dev *isa_dev; + + isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL); + if (!isa_dev) { + error = -ENOMEM; + break; + } + + isa_dev->dev.parent = &isa_bus; + isa_dev->dev.bus = &isa_bus_type; + + snprintf(isa_dev->dev.bus_id, BUS_ID_SIZE, "%s.%u", + isa_driver->driver.name, id); + + isa_dev->dev.platform_data = isa_driver; + isa_dev->dev.release = isa_dev_release; + isa_dev->id = id; + + error = device_register(&isa_dev->dev); + if (error) { + put_device(&isa_dev->dev); + break; + } + + if (isa_dev->dev.platform_data) { + isa_dev->next = isa_driver->devices; + isa_driver->devices = &isa_dev->dev; + } else + device_unregister(&isa_dev->dev); + } + + if (!error && !isa_driver->devices) + error = -ENODEV; + + if (error) + isa_unregister_driver(isa_driver); + + return error; +} +EXPORT_SYMBOL_GPL(isa_register_driver); + +static int __init isa_bus_init(void) +{ + int error; + + error = bus_register(&isa_bus_type); + if (!error) { + error = device_register(&isa_bus); + if (error) + bus_unregister(&isa_bus_type); + } + return error; +} + +device_initcall(isa_bus_init); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 83f5c59..2b8755d 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -275,7 +275,7 @@ int platform_device_add(struct platform_ pr_debug("Registering platform device '%s'. Parent at %s\n", pdev->dev.bus_id, pdev->dev.parent->bus_id); - ret = device_register(&pdev->dev); + ret = device_add(&pdev->dev); if (ret == 0) return ret; @@ -452,6 +452,37 @@ void platform_driver_unregister(struct p EXPORT_SYMBOL_GPL(platform_driver_unregister); +/* modalias support enables more hands-off userspace setup: + * (a) environment variable lets new-style hotplug events work once system is + * fully running: "modprobe $MODALIAS" + * (b) sysfs attribute lets new-style coldplug recover from hotplug events + * mishandled before system is fully running: "modprobe $(cat modalias)" + */ +static ssize_t +modalias_show(struct device *dev, struct device_attribute *a, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + int len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->name); + + return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; +} + +static struct device_attribute platform_dev_attrs[] = { + __ATTR_RO(modalias), + __ATTR_NULL, +}; + +static int platform_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + struct platform_device *pdev = to_platform_device(dev); + + envp[0] = buffer; + snprintf(buffer, buffer_size, "MODALIAS=%s", pdev->name); + return 0; +} + + /** * platform_match - bind platform device to platform driver. * @dev: device. @@ -496,7 +527,9 @@ static int platform_resume(struct device struct bus_type platform_bus_type = { .name = "platform", + .dev_attrs = platform_dev_attrs, .match = platform_match, + .uevent = platform_uevent, .suspend = platform_suspend, .resume = platform_resume, }; diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index c0219ad..91f2309 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile @@ -1,6 +1,10 @@ obj-y := shutdown.o obj-$(CONFIG_PM) += main.o suspend.o resume.o runtime.o sysfs.o +obj-$(CONFIG_PM_TRACE) += trace.o ifeq ($(CONFIG_DEBUG_DRIVER),y) EXTRA_CFLAGS += -DDEBUG endif +ifeq ($(CONFIG_PM_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index 317edbf..826093e 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c @@ -9,6 +9,7 @@ */ #include +#include #include "../base.h" #include "power.h" @@ -23,6 +24,8 @@ int resume_device(struct device * dev) { int error = 0; + TRACE_DEVICE(dev); + TRACE_RESUME(0); down(&dev->sem); if (dev->power.pm_parent && dev->power.pm_parent->power.power_state.event) { @@ -36,6 +39,7 @@ int resume_device(struct device * dev) error = dev->bus->resume(dev); } up(&dev->sem); + TRACE_RESUME(error); return error; } @@ -49,8 +53,7 @@ void dpm_resume(void) struct device * dev = to_device(entry); get_device(dev); - list_del_init(entry); - list_add_tail(entry, &dpm_active); + list_move_tail(entry, &dpm_active); up(&dpm_list_sem); if (!dev->power.prev_state.event) @@ -97,8 +100,7 @@ void dpm_power_up(void) struct device * dev = to_device(entry); get_device(dev); - list_del_init(entry); - list_add_tail(entry, &dpm_active); + list_move_tail(entry, &dpm_active); resume_device(dev); put_device(dev); } diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 2a769cc..69509e0 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -29,6 +29,15 @@ #include "power.h" * lists. This way, the ancestors will be accessed before their descendents. */ +static inline char *suspend_verb(u32 event) +{ + switch (event) { + case PM_EVENT_SUSPEND: return "suspend"; + case PM_EVENT_FREEZE: return "freeze"; + default: return "(unknown suspend event)"; + } +} + /** * suspend_device - Save state of one device. @@ -57,7 +66,13 @@ int suspend_device(struct device * dev, dev->power.prev_state = dev->power.power_state; if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) { - dev_dbg(dev, "suspending\n"); + dev_dbg(dev, "%s%s\n", + suspend_verb(state.event), + ((state.event == PM_EVENT_SUSPEND) + && device_may_wakeup(dev)) + ? ", may wakeup" + : "" + ); error = dev->bus->suspend(dev, state); suspend_report_result(dev->bus->suspend, error); } @@ -101,12 +116,10 @@ int device_suspend(pm_message_t state) /* Check if the device got removed */ if (!list_empty(&dev->power.entry)) { /* Move it to the dpm_off or dpm_off_irq list */ - if (!error) { - list_del(&dev->power.entry); - list_add(&dev->power.entry, &dpm_off); - } else if (error == -EAGAIN) { - list_del(&dev->power.entry); - list_add(&dev->power.entry, &dpm_off_irq); + if (!error) + list_move(&dev->power.entry, &dpm_off); + else if (error == -EAGAIN) { + list_move(&dev->power.entry, &dpm_off_irq); error = 0; } } @@ -124,8 +137,7 @@ int device_suspend(pm_message_t state) */ while (!list_empty(&dpm_off_irq)) { struct list_head * entry = dpm_off_irq.next; - list_del(entry); - list_add(entry, &dpm_off); + list_move(entry, &dpm_off); } dpm_resume(); } diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c new file mode 100644 index 0000000..a9ab30f --- /dev/null +++ b/drivers/base/power/trace.c @@ -0,0 +1,228 @@ +/* + * drivers/base/power/trace.c + * + * Copyright (C) 2006 Linus Torvalds + * + * Trace facility for suspend/resume problems, when none of the + * devices may be working. + */ + +#include +#include + +#include + +#include "power.h" + +/* + * Horrid, horrid, horrid. + * + * It turns out that the _only_ piece of hardware that actually + * keeps its value across a hard boot (and, more importantly, the + * POST init sequence) is literally the realtime clock. + * + * Never mind that an RTC chip has 114 bytes (and often a whole + * other bank of an additional 128 bytes) of nice SRAM that is + * _designed_ to keep data - the POST will clear it. So we literally + * can just use the few bytes of actual time data, which means that + * we're really limited. + * + * It means, for example, that we can't use the seconds at all + * (since the time between the hang and the boot might be more + * than a minute), and we'd better not depend on the low bits of + * the minutes either. + * + * There are the wday fields etc, but I wouldn't guarantee those + * are dependable either. And if the date isn't valid, either the + * hw or POST will do strange things. + * + * So we're left with: + * - year: 0-99 + * - month: 0-11 + * - day-of-month: 1-28 + * - hour: 0-23 + * - min: (0-30)*2 + * + * Giving us a total range of 0-16128000 (0xf61800), ie less + * than 24 bits of actual data we can save across reboots. + * + * And if your box can't boot in less than three minutes, + * you're screwed. + * + * Now, almost 24 bits of data is pitifully small, so we need + * to be pretty dense if we want to use it for anything nice. + * What we do is that instead of saving off nice readable info, + * we save off _hashes_ of information that we can hopefully + * regenerate after the reboot. + * + * In particular, this means that we might be unlucky, and hit + * a case where we have a hash collision, and we end up not + * being able to tell for certain exactly which case happened. + * But that's hopefully unlikely. + * + * What we do is to take the bits we can fit, and split them + * into three parts (16*997*1009 = 16095568), and use the values + * for: + * - 0-15: user-settable + * - 0-996: file + line number + * - 0-1008: device + */ +#define USERHASH (16) +#define FILEHASH (997) +#define DEVHASH (1009) + +#define DEVSEED (7919) + +static unsigned int dev_hash_value; + +static int set_magic_time(unsigned int user, unsigned int file, unsigned int device) +{ + unsigned int n = user + USERHASH*(file + FILEHASH*device); + + // June 7th, 2006 + static struct rtc_time time = { + .tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 7, + .tm_mon = 5, // June - counting from zero + .tm_year = 106, + .tm_wday = 3, + .tm_yday = 160, + .tm_isdst = 1 + }; + + time.tm_year = (n % 100); + n /= 100; + time.tm_mon = (n % 12); + n /= 12; + time.tm_mday = (n % 28) + 1; + n /= 28; + time.tm_hour = (n % 24); + n /= 24; + time.tm_min = (n % 20) * 3; + n /= 20; + set_rtc_time(&time); + return n ? -1 : 0; +} + +static unsigned int read_magic_time(void) +{ + struct rtc_time time; + unsigned int val; + + get_rtc_time(&time); + printk("Time: %2d:%02d:%02d Date: %02d/%02d/%02d\n", + time.tm_hour, time.tm_min, time.tm_sec, + time.tm_mon, time.tm_mday, time.tm_year); + val = time.tm_year; /* 100 years */ + if (val > 100) + val -= 100; + val += time.tm_mon * 100; /* 12 months */ + val += (time.tm_mday-1) * 100 * 12; /* 28 month-days */ + val += time.tm_hour * 100 * 12 * 28; /* 24 hours */ + val += (time.tm_min / 3) * 100 * 12 * 28 * 24; /* 20 3-minute intervals */ + return val; +} + +/* + * This is just the sdbm hash function with a user-supplied + * seed and final size parameter. + */ +static unsigned int hash_string(unsigned int seed, const char *data, unsigned int mod) +{ + unsigned char c; + while ((c = *data++) != 0) { + seed = (seed << 16) + (seed << 6) - seed + c; + } + return seed % mod; +} + +void set_trace_device(struct device *dev) +{ + dev_hash_value = hash_string(DEVSEED, dev->bus_id, DEVHASH); +} + +/* + * We could just take the "tracedata" index into the .tracedata + * section instead. Generating a hash of the data gives us a + * chance to work across kernel versions, and perhaps more + * importantly it also gives us valid/invalid check (ie we will + * likely not give totally bogus reports - if the hash matches, + * it's not any guarantee, but it's a high _likelihood_ that + * the match is valid). + */ +void generate_resume_trace(void *tracedata, unsigned int user) +{ + unsigned short lineno = *(unsigned short *)tracedata; + const char *file = *(const char **)(tracedata + 2); + unsigned int user_hash_value, file_hash_value; + + user_hash_value = user % USERHASH; + file_hash_value = hash_string(lineno, file, FILEHASH); + set_magic_time(user_hash_value, file_hash_value, dev_hash_value); +} + +extern char __tracedata_start, __tracedata_end; +static int show_file_hash(unsigned int value) +{ + int match; + char *tracedata; + + match = 0; + for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ; tracedata += 6) { + unsigned short lineno = *(unsigned short *)tracedata; + const char *file = *(const char **)(tracedata + 2); + unsigned int hash = hash_string(lineno, file, FILEHASH); + if (hash != value) + continue; + printk(" hash matches %s:%u\n", file, lineno); + match++; + } + return match; +} + +static int show_dev_hash(unsigned int value) +{ + int match = 0; + struct list_head * entry = dpm_active.prev; + + while (entry != &dpm_active) { + struct device * dev = to_device(entry); + unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH); + if (hash == value) { + printk(" hash matches device %s\n", dev->bus_id); + match++; + } + entry = entry->prev; + } + return match; +} + +static unsigned int hash_value_early_read; + +static int early_resume_init(void) +{ + hash_value_early_read = read_magic_time(); + return 0; +} + +static int late_resume_init(void) +{ + unsigned int val = hash_value_early_read; + unsigned int user, file, dev; + + user = val % USERHASH; + val = val / USERHASH; + file = val % FILEHASH; + val = val / FILEHASH; + dev = val /* % DEVHASH */; + + printk(" Magic number: %d:%d:%d\n", user, file, dev); + show_file_hash(file); + show_dev_hash(dev); + return 0; +} + +core_initcall(early_resume_init); +late_initcall(late_resume_init); diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 6fc23ab..6858178 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -80,10 +80,59 @@ void sysdev_remove_file(struct sys_devic EXPORT_SYMBOL_GPL(sysdev_create_file); EXPORT_SYMBOL_GPL(sysdev_remove_file); +#define to_sysdev_class(k) container_of(k, struct sysdev_class, kset.kobj) +#define to_sysdev_class_attr(a) container_of(a, \ + struct sysdev_class_attribute, attr) + +static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr, + char *buffer) +{ + struct sysdev_class * class = to_sysdev_class(kobj); + struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); + + if (class_attr->show) + return class_attr->show(class, buffer); + return -EIO; +} + +static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) +{ + struct sysdev_class * class = to_sysdev_class(kobj); + struct sysdev_class_attribute * class_attr = to_sysdev_class_attr(attr); + + if (class_attr->store) + return class_attr->store(class, buffer, count); + return -EIO; +} + +static struct sysfs_ops sysfs_class_ops = { + .show = sysdev_class_show, + .store = sysdev_class_store, +}; + +static struct kobj_type ktype_sysdev_class = { + .sysfs_ops = &sysfs_class_ops, +}; + +int sysdev_class_create_file(struct sysdev_class *c, + struct sysdev_class_attribute *a) +{ + return sysfs_create_file(&c->kset.kobj, &a->attr); +} +EXPORT_SYMBOL_GPL(sysdev_class_create_file); + +void sysdev_class_remove_file(struct sysdev_class *c, + struct sysdev_class_attribute *a) +{ + sysfs_remove_file(&c->kset.kobj, &a->attr); +} +EXPORT_SYMBOL_GPL(sysdev_class_remove_file); + /* * declare system_subsys */ -static decl_subsys(system, &ktype_sysdev, NULL); +static decl_subsys(system, &ktype_sysdev_class, NULL); int sysdev_class_register(struct sysdev_class * cls) { diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 45bcda5..dd8a150 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -17,8 +17,8 @@ */ -#define DAC960_DriverVersion "2.5.47" -#define DAC960_DriverDate "14 November 2002" +#define DAC960_DriverVersion "2.5.48" +#define DAC960_DriverDate "14 May 2006" #include @@ -4780,15 +4780,16 @@ #endif (NewPhysicalDeviceInfo->LogicalUnit != PhysicalDeviceInfo->LogicalUnit)) { - PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *) + PhysicalDeviceInfo = kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); InquiryUnitSerialNumber = - (DAC960_SCSI_Inquiry_UnitSerialNumber_T *) kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC); - if (InquiryUnitSerialNumber == NULL && - PhysicalDeviceInfo != NULL) + if (InquiryUnitSerialNumber == NULL || + PhysicalDeviceInfo == NULL) { + kfree(InquiryUnitSerialNumber); + InquiryUnitSerialNumber = NULL; kfree(PhysicalDeviceInfo); PhysicalDeviceInfo = NULL; } diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index ae0949b..93d9474 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -402,6 +402,7 @@ config BLK_DEV_RAM_SIZE config BLK_DEV_INITRD bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support" + depends on BROKEN || !FRV help The initial RAM filesystem is a ramfs which is loaded by the boot loader (loadlin or lilo) and that is mounted as root diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 2a8af68..2641597 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -64,6 +64,7 @@ #include #include #include #include +#include #include #include diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index fdff774..c1434ed 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -116,8 +116,7 @@ aoenet_rcv(struct sk_buff *skb, struct n skb = skb_share_check(skb, GFP_ATOMIC); if (skb == NULL) return 0; - if (skb_is_nonlinear(skb)) - if (skb_linearize(skb, GFP_ATOMIC) < 0) + if (skb_linearize(skb)) goto exit; if (!is_aoe_netif(ifp)) goto exit; diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 1319d8f..39b0f53 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -34,7 +34,7 @@ #include #include #include #include -#include +#include #include #include #include @@ -64,143 +64,129 @@ #include /* define the PCI info for the cards we can control */ static const struct pci_device_id cciss_pci_device_id[] = { - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISS, - 0x0E11, 0x4070, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, - 0x0E11, 0x4080, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, - 0x0E11, 0x4082, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, - 0x0E11, 0x4083, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x409A, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x409B, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x409C, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x409D, 0, 0, 0}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, - 0x0E11, 0x4091, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA, - 0x103C, 0x3225, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, - 0x103c, 0x3223, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, - 0x103c, 0x3234, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, - 0x103c, 0x3235, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, - 0x103c, 0x3211, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, - 0x103c, 0x3212, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, - 0x103c, 0x3213, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, - 0x103c, 0x3214, 0, 0, 0}, - { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, - 0x103c, 0x3215, 0, 0, 0}, + {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISS, 0x0E11, 0x4070}, + {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, 0x0E11, 0x4080}, + {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, 0x0E11, 0x4082}, + {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, 0x0E11, 0x4083}, + {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x4091}, + {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409A}, + {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409B}, + {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409C}, + {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409D}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA, 0x103C, 0x3225}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3223}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3234}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3235}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3211}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3212}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3213}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3214}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215}, {0,} }; -MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); -#define NR_PRODUCTS ARRAY_SIZE(products) +MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); /* board_id = Subsystem Device ID & Vendor ID * product = Marketing Name for the board - * access = Address of the struct of function pointers + * access = Address of the struct of function pointers */ static struct board_type products[] = { - { 0x40700E11, "Smart Array 5300", &SA5_access }, - { 0x40800E11, "Smart Array 5i", &SA5B_access}, - { 0x40820E11, "Smart Array 532", &SA5B_access}, - { 0x40830E11, "Smart Array 5312", &SA5B_access}, - { 0x409A0E11, "Smart Array 641", &SA5_access}, - { 0x409B0E11, "Smart Array 642", &SA5_access}, - { 0x409C0E11, "Smart Array 6400", &SA5_access}, - { 0x409D0E11, "Smart Array 6400 EM", &SA5_access}, - { 0x40910E11, "Smart Array 6i", &SA5_access}, - { 0x3225103C, "Smart Array P600", &SA5_access}, - { 0x3223103C, "Smart Array P800", &SA5_access}, - { 0x3234103C, "Smart Array P400", &SA5_access}, - { 0x3235103C, "Smart Array P400i", &SA5_access}, - { 0x3211103C, "Smart Array E200i", &SA5_access}, - { 0x3212103C, "Smart Array E200", &SA5_access}, - { 0x3213103C, "Smart Array E200i", &SA5_access}, - { 0x3214103C, "Smart Array E200i", &SA5_access}, - { 0x3215103C, "Smart Array E200i", &SA5_access}, + {0x40700E11, "Smart Array 5300", &SA5_access}, + {0x40800E11, "Smart Array 5i", &SA5B_access}, + {0x40820E11, "Smart Array 532", &SA5B_access}, + {0x40830E11, "Smart Array 5312", &SA5B_access}, + {0x409A0E11, "Smart Array 641", &SA5_access}, + {0x409B0E11, "Smart Array 642", &SA5_access}, + {0x409C0E11, "Smart Array 6400", &SA5_access}, + {0x409D0E11, "Smart Array 6400 EM", &SA5_access}, + {0x40910E11, "Smart Array 6i", &SA5_access}, + {0x3225103C, "Smart Array P600", &SA5_access}, + {0x3223103C, "Smart Array P800", &SA5_access}, + {0x3234103C, "Smart Array P400", &SA5_access}, + {0x3235103C, "Smart Array P400i", &SA5_access}, + {0x3211103C, "Smart Array E200i", &SA5_access}, + {0x3212103C, "Smart Array E200", &SA5_access}, + {0x3213103C, "Smart Array E200i", &SA5_access}, + {0x3214103C, "Smart Array E200i", &SA5_access}, + {0x3215103C, "Smart Array E200i", &SA5_access}, }; -/* How long to wait (in millesconds) for board to go into simple mode */ -#define MAX_CONFIG_WAIT 30000 +/* How long to wait (in milliseconds) for board to go into simple mode */ +#define MAX_CONFIG_WAIT 30000 #define MAX_IOCTL_CONFIG_WAIT 1000 /*define how many times we will try a command because of bus resets */ #define MAX_CMD_RETRIES 3 #define READ_AHEAD 1024 -#define NR_CMDS 384 /* #commands that can be outstanding */ +#define NR_CMDS 384 /* #commands that can be outstanding */ #define MAX_CTLR 32 /* Originally cciss driver only supports 8 major numbers */ #define MAX_CTLR_ORIG 8 - static ctlr_info_t *hba[MAX_CTLR]; static void do_cciss_request(request_queue_t *q); static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs); static int cciss_open(struct inode *inode, struct file *filep); static int cciss_release(struct inode *inode, struct file *filep); -static int cciss_ioctl(struct inode *inode, struct file *filep, - unsigned int cmd, unsigned long arg); +static int cciss_ioctl(struct inode *inode, struct file *filep, + unsigned int cmd, unsigned long arg); static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); static int revalidate_allvol(ctlr_info_t *host); static int cciss_revalidate(struct gendisk *disk); static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk); -static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, int clear_all); +static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, + int clear_all); static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, - int withirq, unsigned int *total_size, unsigned int *block_size); -static void cciss_geometry_inquiry(int ctlr, int logvol, - int withirq, unsigned int total_size, - unsigned int block_size, InquiryData_struct *inq_buff, - drive_info_struct *drv); + int withirq, unsigned int *total_size, + unsigned int *block_size); +static void cciss_geometry_inquiry(int ctlr, int logvol, int withirq, + unsigned int total_size, + unsigned int block_size, + InquiryData_struct *inq_buff, + drive_info_struct *drv); static void cciss_getgeometry(int cntl_num); -static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, __u32); -static void start_io( ctlr_info_t *h); -static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size, - unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, - unsigned char *scsi3addr, int cmd_type); -static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size, - unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, - int cmd_type); +static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, + __u32); +static void start_io(ctlr_info_t *h); +static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, + unsigned int use_unit_num, unsigned int log_unit, + __u8 page_code, unsigned char *scsi3addr, int cmd_type); +static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size, + unsigned int use_unit_num, unsigned int log_unit, + __u8 page_code, int cmd_type); static void fail_all_cmds(unsigned long ctlr); #ifdef CONFIG_PROC_FS -static int cciss_proc_get_info(char *buffer, char **start, off_t offset, - int length, int *eof, void *data); +static int cciss_proc_get_info(char *buffer, char **start, off_t offset, + int length, int *eof, void *data); static void cciss_procinit(int i); #else -static void cciss_procinit(int i) {} -#endif /* CONFIG_PROC_FS */ +static void cciss_procinit(int i) +{ +} +#endif /* CONFIG_PROC_FS */ #ifdef CONFIG_COMPAT static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg); #endif -static struct block_device_operations cciss_fops = { - .owner = THIS_MODULE, - .open = cciss_open, - .release = cciss_release, - .ioctl = cciss_ioctl, - .getgeo = cciss_getgeo, +static struct block_device_operations cciss_fops = { + .owner = THIS_MODULE, + .open = cciss_open, + .release = cciss_release, + .ioctl = cciss_ioctl, + .getgeo = cciss_getgeo, #ifdef CONFIG_COMPAT - .compat_ioctl = cciss_compat_ioctl, + .compat_ioctl = cciss_compat_ioctl, #endif - .revalidate_disk= cciss_revalidate, + .revalidate_disk = cciss_revalidate, }; /* @@ -208,28 +194,29 @@ #endif */ static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c) { - if (*Qptr == NULL) { - *Qptr = c; - c->next = c->prev = c; - } else { - c->prev = (*Qptr)->prev; - c->next = (*Qptr); - (*Qptr)->prev->next = c; - (*Qptr)->prev = c; - } + if (*Qptr == NULL) { + *Qptr = c; + c->next = c->prev = c; + } else { + c->prev = (*Qptr)->prev; + c->next = (*Qptr); + (*Qptr)->prev->next = c; + (*Qptr)->prev = c; + } } -static inline CommandList_struct *removeQ(CommandList_struct **Qptr, - CommandList_struct *c) +static inline CommandList_struct *removeQ(CommandList_struct **Qptr, + CommandList_struct *c) { - if (c && c->next != c) { - if (*Qptr == c) *Qptr = c->next; - c->prev->next = c->next; - c->next->prev = c->prev; - } else { - *Qptr = NULL; - } - return c; + if (c && c->next != c) { + if (*Qptr == c) + *Qptr = c->next; + c->prev->next = c->next; + c->next->prev = c->prev; + } else { + *Qptr = NULL; + } + return c; } #include "cciss_scsi.c" /* For SCSI tape support */ @@ -242,23 +229,24 @@ #ifdef CONFIG_PROC_FS #define ENG_GIG 1000000000 #define ENG_GIG_FACTOR (ENG_GIG/512) #define RAID_UNKNOWN 6 -static const char *raid_label[] = {"0","4","1(1+0)","5","5+1","ADG", - "UNKNOWN"}; +static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", + "UNKNOWN" +}; static struct proc_dir_entry *proc_cciss; -static int cciss_proc_get_info(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) +static int cciss_proc_get_info(char *buffer, char **start, off_t offset, + int length, int *eof, void *data) { - off_t pos = 0; - off_t len = 0; - int size, i, ctlr; - ctlr_info_t *h = (ctlr_info_t*)data; - drive_info_struct *drv; + off_t pos = 0; + off_t len = 0; + int size, i, ctlr; + ctlr_info_t *h = (ctlr_info_t *) data; + drive_info_struct *drv; unsigned long flags; - sector_t vol_sz, vol_sz_frac; + sector_t vol_sz, vol_sz_frac; - ctlr = h->ctlr; + ctlr = h->ctlr; /* prevent displaying bogus info during configuration * or deconfiguration of a logical volume @@ -266,35 +254,35 @@ static int cciss_proc_get_info(char *buf spin_lock_irqsave(CCISS_LOCK(ctlr), flags); if (h->busy_configuring) { spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - return -EBUSY; + return -EBUSY; } h->busy_configuring = 1; spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - size = sprintf(buffer, "%s: HP %s Controller\n" - "Board ID: 0x%08lx\n" - "Firmware Version: %c%c%c%c\n" - "IRQ: %d\n" - "Logical drives: %d\n" - "Current Q depth: %d\n" - "Current # commands on controller: %d\n" - "Max Q depth since init: %d\n" - "Max # commands on controller since init: %d\n" - "Max SG entries since init: %d\n\n", - h->devname, - h->product_name, - (unsigned long)h->board_id, - h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], h->firm_ver[3], - (unsigned int)h->intr[SIMPLE_MODE_INT], - h->num_luns, - h->Qdepth, h->commands_outstanding, - h->maxQsinceinit, h->max_outstanding, h->maxSG); - - pos += size; len += size; + size = sprintf(buffer, "%s: HP %s Controller\n" + "Board ID: 0x%08lx\n" + "Firmware Version: %c%c%c%c\n" + "IRQ: %d\n" + "Logical drives: %d\n" + "Current Q depth: %d\n" + "Current # commands on controller: %d\n" + "Max Q depth since init: %d\n" + "Max # commands on controller since init: %d\n" + "Max SG entries since init: %d\n\n", + h->devname, + h->product_name, + (unsigned long)h->board_id, + h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], + h->firm_ver[3], (unsigned int)h->intr[SIMPLE_MODE_INT], + h->num_luns, h->Qdepth, h->commands_outstanding, + h->maxQsinceinit, h->max_outstanding, h->maxSG); + + pos += size; + len += size; cciss_proc_tape_report(ctlr, buffer, &pos, &len); - for(i=0; i<=h->highest_lun; i++) { + for (i = 0; i <= h->highest_lun; i++) { - drv = &h->drv[i]; + drv = &h->drv[i]; if (drv->heads == 0) continue; @@ -305,25 +293,26 @@ static int cciss_proc_get_info(char *buf if (drv->raid_level > 5) drv->raid_level = RAID_UNKNOWN; - size = sprintf(buffer+len, "cciss/c%dd%d:" - "\t%4u.%02uGB\tRAID %s\n", - ctlr, i, (int)vol_sz, (int)vol_sz_frac, - raid_label[drv->raid_level]); - pos += size; len += size; - } - - *eof = 1; - *start = buffer+offset; - len -= offset; - if (len>length) - len = length; + size = sprintf(buffer + len, "cciss/c%dd%d:" + "\t%4u.%02uGB\tRAID %s\n", + ctlr, i, (int)vol_sz, (int)vol_sz_frac, + raid_label[drv->raid_level]); + pos += size; + len += size; + } + + *eof = 1; + *start = buffer + offset; + len -= offset; + if (len > length) + len = length; h->busy_configuring = 0; - return len; + return len; } -static int -cciss_proc_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int +cciss_proc_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) { unsigned char cmd[80]; int len; @@ -332,20 +321,23 @@ #ifdef CONFIG_CISS_SCSI_TAPE int rc; #endif - if (count > sizeof(cmd)-1) return -EINVAL; - if (copy_from_user(cmd, buffer, count)) return -EFAULT; + if (count > sizeof(cmd) - 1) + return -EINVAL; + if (copy_from_user(cmd, buffer, count)) + return -EFAULT; cmd[count] = '\0'; len = strlen(cmd); // above 3 lines ensure safety - if (len && cmd[len-1] == '\n') + if (len && cmd[len - 1] == '\n') cmd[--len] = '\0'; # ifdef CONFIG_CISS_SCSI_TAPE - if (strcmp("engage scsi", cmd)==0) { - rc = cciss_engage_scsi(h->ctlr); - if (rc != 0) return -rc; - return count; - } - /* might be nice to have "disengage" too, but it's not - safely possible. (only 1 module use count, lock issues.) */ + if (strcmp("engage scsi", cmd) == 0) { + rc = cciss_engage_scsi(h->ctlr); + if (rc != 0) + return -rc; + return count; + } + /* might be nice to have "disengage" too, but it's not + safely possible. (only 1 module use count, lock issues.) */ # endif return -EINVAL; } @@ -358,116 +350,113 @@ static void __devinit cciss_procinit(int { struct proc_dir_entry *pde; - if (proc_cciss == NULL) { - proc_cciss = proc_mkdir("cciss", proc_root_driver); - if (!proc_cciss) + if (proc_cciss == NULL) { + proc_cciss = proc_mkdir("cciss", proc_root_driver); + if (!proc_cciss) return; - } + } - pde = create_proc_read_entry(hba[i]->devname, - S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, - proc_cciss, cciss_proc_get_info, hba[i]); + pde = create_proc_read_entry(hba[i]->devname, + S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, + proc_cciss, cciss_proc_get_info, hba[i]); pde->write_proc = cciss_proc_write; } -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_PROC_FS */ -/* - * For operations that cannot sleep, a command block is allocated at init, +/* + * For operations that cannot sleep, a command block is allocated at init, * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track - * which ones are free or in use. For operations that can wait for kmalloc - * to possible sleep, this routine can be called with get_from_pool set to 0. - * cmd_free() MUST be called with a got_from_pool set to 0 if cmd_alloc was. - */ -static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool) + * which ones are free or in use. For operations that can wait for kmalloc + * to possible sleep, this routine can be called with get_from_pool set to 0. + * cmd_free() MUST be called with a got_from_pool set to 0 if cmd_alloc was. + */ +static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool) { CommandList_struct *c; - int i; + int i; u64bit temp64; dma_addr_t cmd_dma_handle, err_dma_handle; - if (!get_from_pool) - { - c = (CommandList_struct *) pci_alloc_consistent( - h->pdev, sizeof(CommandList_struct), &cmd_dma_handle); - if(c==NULL) - return NULL; + if (!get_from_pool) { + c = (CommandList_struct *) pci_alloc_consistent(h->pdev, + sizeof(CommandList_struct), &cmd_dma_handle); + if (c == NULL) + return NULL; memset(c, 0, sizeof(CommandList_struct)); c->cmdindex = -1; - c->err_info = (ErrorInfo_struct *)pci_alloc_consistent( - h->pdev, sizeof(ErrorInfo_struct), - &err_dma_handle); - - if (c->err_info == NULL) - { - pci_free_consistent(h->pdev, + c->err_info = (ErrorInfo_struct *) + pci_alloc_consistent(h->pdev, sizeof(ErrorInfo_struct), + &err_dma_handle); + + if (c->err_info == NULL) { + pci_free_consistent(h->pdev, sizeof(CommandList_struct), c, cmd_dma_handle); return NULL; } memset(c->err_info, 0, sizeof(ErrorInfo_struct)); - } else /* get it out of the controllers pool */ - { - do { - i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS); - if (i == NR_CMDS) - return NULL; - } while(test_and_set_bit(i & (BITS_PER_LONG - 1), h->cmd_pool_bits+(i/BITS_PER_LONG)) != 0); + } else { /* get it out of the controllers pool */ + + do { + i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS); + if (i == NR_CMDS) + return NULL; + } while (test_and_set_bit + (i & (BITS_PER_LONG - 1), + h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0); #ifdef CCISS_DEBUG printk(KERN_DEBUG "cciss: using command buffer %d\n", i); #endif - c = h->cmd_pool + i; + c = h->cmd_pool + i; memset(c, 0, sizeof(CommandList_struct)); - cmd_dma_handle = h->cmd_pool_dhandle - + i*sizeof(CommandList_struct); + cmd_dma_handle = h->cmd_pool_dhandle + + i * sizeof(CommandList_struct); c->err_info = h->errinfo_pool + i; memset(c->err_info, 0, sizeof(ErrorInfo_struct)); - err_dma_handle = h->errinfo_pool_dhandle - + i*sizeof(ErrorInfo_struct); - h->nr_allocs++; + err_dma_handle = h->errinfo_pool_dhandle + + i * sizeof(ErrorInfo_struct); + h->nr_allocs++; c->cmdindex = i; - } + } c->busaddr = (__u32) cmd_dma_handle; - temp64.val = (__u64) err_dma_handle; + temp64.val = (__u64) err_dma_handle; c->ErrDesc.Addr.lower = temp64.val32.lower; c->ErrDesc.Addr.upper = temp64.val32.upper; c->ErrDesc.Len = sizeof(ErrorInfo_struct); - - c->ctlr = h->ctlr; - return c; - + c->ctlr = h->ctlr; + return c; } -/* - * Frees a command block that was previously allocated with cmd_alloc(). +/* + * Frees a command block that was previously allocated with cmd_alloc(). */ static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool) { int i; u64bit temp64; - if( !got_from_pool) - { + if (!got_from_pool) { temp64.val32.lower = c->ErrDesc.Addr.lower; temp64.val32.upper = c->ErrDesc.Addr.upper; - pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct), - c->err_info, (dma_addr_t) temp64.val); - pci_free_consistent(h->pdev, sizeof(CommandList_struct), - c, (dma_addr_t) c->busaddr); - } else - { + pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct), + c->err_info, (dma_addr_t) temp64.val); + pci_free_consistent(h->pdev, sizeof(CommandList_struct), + c, (dma_addr_t) c->busaddr); + } else { i = c - h->cmd_pool; - clear_bit(i&(BITS_PER_LONG-1), h->cmd_pool_bits+(i/BITS_PER_LONG)); - h->nr_frees++; - } + clear_bit(i & (BITS_PER_LONG - 1), + h->cmd_pool_bits + (i / BITS_PER_LONG)); + h->nr_frees++; + } } static inline ctlr_info_t *get_host(struct gendisk *disk) { - return disk->queue->queuedata; + return disk->queue->queuedata; } static inline drive_info_struct *get_drv(struct gendisk *disk) @@ -485,7 +474,7 @@ static int cciss_open(struct inode *inod #ifdef CCISS_DEBUG printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name); -#endif /* CCISS_DEBUG */ +#endif /* CCISS_DEBUG */ if (host->busy_initializing || drv->busy_configuring) return -EBUSY; @@ -498,10 +487,10 @@ #endif /* CCISS_DEBUG */ * for "raw controller". */ if (drv->nr_blocks == 0) { - if (iminor(inode) != 0) { /* not node 0? */ + if (iminor(inode) != 0) { /* not node 0? */ /* if not node 0 make sure it is a partition = 0 */ if (iminor(inode) & 0x0f) { - return -ENXIO; + return -ENXIO; /* if it is, make sure we have a LUN ID */ } else if (drv->LunID == 0) { return -ENXIO; @@ -514,6 +503,7 @@ #endif /* CCISS_DEBUG */ host->usage_count++; return 0; } + /* * Close. Sync first. */ @@ -523,8 +513,9 @@ static int cciss_release(struct inode *i drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk); #ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss_release %s\n", inode->i_bdev->bd_disk->disk_name); -#endif /* CCISS_DEBUG */ + printk(KERN_DEBUG "cciss_release %s\n", + inode->i_bdev->bd_disk->disk_name); +#endif /* CCISS_DEBUG */ drv->usage_count--; host->usage_count--; @@ -542,8 +533,10 @@ static int do_ioctl(struct file *f, unsi return ret; } -static int cciss_ioctl32_passthru(struct file *f, unsigned cmd, unsigned long arg); -static int cciss_ioctl32_big_passthru(struct file *f, unsigned cmd, unsigned long arg); +static int cciss_ioctl32_passthru(struct file *f, unsigned cmd, + unsigned long arg); +static int cciss_ioctl32_big_passthru(struct file *f, unsigned cmd, + unsigned long arg); static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg) { @@ -575,19 +568,26 @@ static long cciss_compat_ioctl(struct fi } } -static int cciss_ioctl32_passthru(struct file *f, unsigned cmd, unsigned long arg) +static int cciss_ioctl32_passthru(struct file *f, unsigned cmd, + unsigned long arg) { IOCTL32_Command_struct __user *arg32 = - (IOCTL32_Command_struct __user *) arg; + (IOCTL32_Command_struct __user *) arg; IOCTL_Command_struct arg64; IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64)); int err; u32 cp; err = 0; - err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info)); - err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request)); - err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info)); + err |= + copy_from_user(&arg64.LUN_info, &arg32->LUN_info, + sizeof(arg64.LUN_info)); + err |= + copy_from_user(&arg64.Request, &arg32->Request, + sizeof(arg64.Request)); + err |= + copy_from_user(&arg64.error_info, &arg32->error_info, + sizeof(arg64.error_info)); err |= get_user(arg64.buf_size, &arg32->buf_size); err |= get_user(cp, &arg32->buf); arg64.buf = compat_ptr(cp); @@ -596,28 +596,38 @@ static int cciss_ioctl32_passthru(struct if (err) return -EFAULT; - err = do_ioctl(f, CCISS_PASSTHRU, (unsigned long) p); + err = do_ioctl(f, CCISS_PASSTHRU, (unsigned long)p); if (err) return err; - err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info)); + err |= + copy_in_user(&arg32->error_info, &p->error_info, + sizeof(arg32->error_info)); if (err) return -EFAULT; return err; } -static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned long arg) +static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, + unsigned long arg) { BIG_IOCTL32_Command_struct __user *arg32 = - (BIG_IOCTL32_Command_struct __user *) arg; + (BIG_IOCTL32_Command_struct __user *) arg; BIG_IOCTL_Command_struct arg64; - BIG_IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64)); + BIG_IOCTL_Command_struct __user *p = + compat_alloc_user_space(sizeof(arg64)); int err; u32 cp; err = 0; - err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info)); - err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request)); - err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info)); + err |= + copy_from_user(&arg64.LUN_info, &arg32->LUN_info, + sizeof(arg64.LUN_info)); + err |= + copy_from_user(&arg64.Request, &arg32->Request, + sizeof(arg64.Request)); + err |= + copy_from_user(&arg64.error_info, &arg32->error_info, + sizeof(arg64.error_info)); err |= get_user(arg64.buf_size, &arg32->buf_size); err |= get_user(arg64.malloc_size, &arg32->malloc_size); err |= get_user(cp, &arg32->buf); @@ -625,12 +635,14 @@ static int cciss_ioctl32_big_passthru(st err |= copy_to_user(p, &arg64, sizeof(arg64)); if (err) - return -EFAULT; + return -EFAULT; - err = do_ioctl(file, CCISS_BIG_PASSTHRU, (unsigned long) p); + err = do_ioctl(file, CCISS_BIG_PASSTHRU, (unsigned long)p); if (err) return err; - err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info)); + err |= + copy_in_user(&arg32->error_info, &p->error_info, + sizeof(arg32->error_info)); if (err) return -EFAULT; return err; @@ -651,10 +663,10 @@ static int cciss_getgeo(struct block_dev } /* - * ioctl + * ioctl */ -static int cciss_ioctl(struct inode *inode, struct file *filep, - unsigned int cmd, unsigned long arg) +static int cciss_ioctl(struct inode *inode, struct file *filep, + unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; struct gendisk *disk = bdev->bd_disk; @@ -665,171 +677,193 @@ static int cciss_ioctl(struct inode *ino #ifdef CCISS_DEBUG printk(KERN_DEBUG "cciss_ioctl: Called with cmd=%x %lx\n", cmd, arg); -#endif /* CCISS_DEBUG */ - - switch(cmd) { +#endif /* CCISS_DEBUG */ + + switch (cmd) { case CCISS_GETPCIINFO: - { - cciss_pci_info_struct pciinfo; - - if (!arg) return -EINVAL; - pciinfo.domain = pci_domain_nr(host->pdev->bus); - pciinfo.bus = host->pdev->bus->number; - pciinfo.dev_fn = host->pdev->devfn; - pciinfo.board_id = host->board_id; - if (copy_to_user(argp, &pciinfo, sizeof( cciss_pci_info_struct ))) - return -EFAULT; - return(0); - } + { + cciss_pci_info_struct pciinfo; + + if (!arg) + return -EINVAL; + pciinfo.domain = pci_domain_nr(host->pdev->bus); + pciinfo.bus = host->pdev->bus->number; + pciinfo.dev_fn = host->pdev->devfn; + pciinfo.board_id = host->board_id; + if (copy_to_user + (argp, &pciinfo, sizeof(cciss_pci_info_struct))) + return -EFAULT; + return 0; + } case CCISS_GETINTINFO: - { - cciss_coalint_struct intinfo; - if (!arg) return -EINVAL; - intinfo.delay = readl(&host->cfgtable->HostWrite.CoalIntDelay); - intinfo.count = readl(&host->cfgtable->HostWrite.CoalIntCount); - if (copy_to_user(argp, &intinfo, sizeof( cciss_coalint_struct ))) - return -EFAULT; - return(0); - } + { + cciss_coalint_struct intinfo; + if (!arg) + return -EINVAL; + intinfo.delay = + readl(&host->cfgtable->HostWrite.CoalIntDelay); + intinfo.count = + readl(&host->cfgtable->HostWrite.CoalIntCount); + if (copy_to_user + (argp, &intinfo, sizeof(cciss_coalint_struct))) + return -EFAULT; + return 0; + } case CCISS_SETINTINFO: - { - cciss_coalint_struct intinfo; - unsigned long flags; - int i; - - if (!arg) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&intinfo, argp, sizeof( cciss_coalint_struct))) - return -EFAULT; - if ( (intinfo.delay == 0 ) && (intinfo.count == 0)) - { -// printk("cciss_ioctl: delay and count cannot be 0\n"); - return( -EINVAL); + cciss_coalint_struct intinfo; + unsigned long flags; + int i; + + if (!arg) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (copy_from_user + (&intinfo, argp, sizeof(cciss_coalint_struct))) + return -EFAULT; + if ((intinfo.delay == 0) && (intinfo.count == 0)) + { +// printk("cciss_ioctl: delay and count cannot be 0\n"); + return -EINVAL; + } + spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + /* Update the field, and then ring the doorbell */ + writel(intinfo.delay, + &(host->cfgtable->HostWrite.CoalIntDelay)); + writel(intinfo.count, + &(host->cfgtable->HostWrite.CoalIntCount)); + writel(CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL); + + for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) { + if (!(readl(host->vaddr + SA5_DOORBELL) + & CFGTBL_ChangeReq)) + break; + /* delay and try again */ + udelay(1000); + } + spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + if (i >= MAX_IOCTL_CONFIG_WAIT) + return -EAGAIN; + return 0; } - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - /* Update the field, and then ring the doorbell */ - writel( intinfo.delay, - &(host->cfgtable->HostWrite.CoalIntDelay)); - writel( intinfo.count, - &(host->cfgtable->HostWrite.CoalIntCount)); - writel( CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL); - - for(i=0;ivaddr + SA5_DOORBELL) - & CFGTBL_ChangeReq)) - break; - /* delay and try again */ - udelay(1000); - } - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - if (i >= MAX_IOCTL_CONFIG_WAIT) - return -EAGAIN; - return(0); - } case CCISS_GETNODENAME: - { - NodeName_type NodeName; - int i; - - if (!arg) return -EINVAL; - for(i=0;i<16;i++) - NodeName[i] = readb(&host->cfgtable->ServerName[i]); - if (copy_to_user(argp, NodeName, sizeof( NodeName_type))) - return -EFAULT; - return(0); - } + { + NodeName_type NodeName; + int i; + + if (!arg) + return -EINVAL; + for (i = 0; i < 16; i++) + NodeName[i] = + readb(&host->cfgtable->ServerName[i]); + if (copy_to_user(argp, NodeName, sizeof(NodeName_type))) + return -EFAULT; + return 0; + } case CCISS_SETNODENAME: - { - NodeName_type NodeName; - unsigned long flags; - int i; - - if (!arg) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) return -EPERM; - - if (copy_from_user(NodeName, argp, sizeof( NodeName_type))) - return -EFAULT; - - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - - /* Update the field, and then ring the doorbell */ - for(i=0;i<16;i++) - writeb( NodeName[i], &host->cfgtable->ServerName[i]); - - writel( CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL); - - for(i=0;ivaddr + SA5_DOORBELL) - & CFGTBL_ChangeReq)) - break; - /* delay and try again */ - udelay(1000); - } - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - if (i >= MAX_IOCTL_CONFIG_WAIT) - return -EAGAIN; - return(0); - } + { + NodeName_type NodeName; + unsigned long flags; + int i; + + if (!arg) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (copy_from_user + (NodeName, argp, sizeof(NodeName_type))) + return -EFAULT; + + spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + + /* Update the field, and then ring the doorbell */ + for (i = 0; i < 16; i++) + writeb(NodeName[i], + &host->cfgtable->ServerName[i]); + + writel(CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL); + + for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) { + if (!(readl(host->vaddr + SA5_DOORBELL) + & CFGTBL_ChangeReq)) + break; + /* delay and try again */ + udelay(1000); + } + spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + if (i >= MAX_IOCTL_CONFIG_WAIT) + return -EAGAIN; + return 0; + } case CCISS_GETHEARTBEAT: - { - Heartbeat_type heartbeat; - - if (!arg) return -EINVAL; - heartbeat = readl(&host->cfgtable->HeartBeat); - if (copy_to_user(argp, &heartbeat, sizeof( Heartbeat_type))) - return -EFAULT; - return(0); - } + { + Heartbeat_type heartbeat; + + if (!arg) + return -EINVAL; + heartbeat = readl(&host->cfgtable->HeartBeat); + if (copy_to_user + (argp, &heartbeat, sizeof(Heartbeat_type))) + return -EFAULT; + return 0; + } case CCISS_GETBUSTYPES: - { - BusTypes_type BusTypes; - - if (!arg) return -EINVAL; - BusTypes = readl(&host->cfgtable->BusTypes); - if (copy_to_user(argp, &BusTypes, sizeof( BusTypes_type) )) - return -EFAULT; - return(0); - } + { + BusTypes_type BusTypes; + + if (!arg) + return -EINVAL; + BusTypes = readl(&host->cfgtable->BusTypes); + if (copy_to_user + (argp, &BusTypes, sizeof(BusTypes_type))) + return -EFAULT; + return 0; + } case CCISS_GETFIRMVER: - { - FirmwareVer_type firmware; + { + FirmwareVer_type firmware; - if (!arg) return -EINVAL; - memcpy(firmware, host->firm_ver, 4); + if (!arg) + return -EINVAL; + memcpy(firmware, host->firm_ver, 4); - if (copy_to_user(argp, firmware, sizeof( FirmwareVer_type))) - return -EFAULT; - return(0); - } - case CCISS_GETDRIVVER: - { - DriverVer_type DriverVer = DRIVER_VERSION; + if (copy_to_user + (argp, firmware, sizeof(FirmwareVer_type))) + return -EFAULT; + return 0; + } + case CCISS_GETDRIVVER: + { + DriverVer_type DriverVer = DRIVER_VERSION; - if (!arg) return -EINVAL; + if (!arg) + return -EINVAL; - if (copy_to_user(argp, &DriverVer, sizeof( DriverVer_type) )) - return -EFAULT; - return(0); - } + if (copy_to_user + (argp, &DriverVer, sizeof(DriverVer_type))) + return -EFAULT; + return 0; + } case CCISS_REVALIDVOLS: if (bdev != bdev->bd_contains || drv != host->drv) return -ENXIO; - return revalidate_allvol(host); - - case CCISS_GETLUNINFO: { - LogvolInfo_struct luninfo; - - luninfo.LunID = drv->LunID; - luninfo.num_opens = drv->usage_count; - luninfo.num_parts = 0; - if (copy_to_user(argp, &luninfo, - sizeof(LogvolInfo_struct))) - return -EFAULT; - return(0); - } + return revalidate_allvol(host); + + case CCISS_GETLUNINFO:{ + LogvolInfo_struct luninfo; + + luninfo.LunID = drv->LunID; + luninfo.num_opens = drv->usage_count; + luninfo.num_parts = 0; + if (copy_to_user(argp, &luninfo, + sizeof(LogvolInfo_struct))) + return -EFAULT; + return 0; + } case CCISS_DEREGDISK: return rebuild_lun_table(host, disk); @@ -837,278 +871,284 @@ #endif /* CCISS_DEBUG */ return rebuild_lun_table(host, NULL); case CCISS_PASSTHRU: - { - IOCTL_Command_struct iocommand; - CommandList_struct *c; - char *buff = NULL; - u64bit temp64; - unsigned long flags; - DECLARE_COMPLETION(wait); - - if (!arg) return -EINVAL; - - if (!capable(CAP_SYS_RAWIO)) return -EPERM; - - if (copy_from_user(&iocommand, argp, sizeof( IOCTL_Command_struct) )) - return -EFAULT; - if((iocommand.buf_size < 1) && - (iocommand.Request.Type.Direction != XFER_NONE)) - { - return -EINVAL; - } -#if 0 /* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */ - /* Check kmalloc limits */ - if(iocommand.buf_size > 128000) - return -EINVAL; -#endif - if(iocommand.buf_size > 0) - { - buff = kmalloc(iocommand.buf_size, GFP_KERNEL); - if( buff == NULL) - return -EFAULT; - } - if (iocommand.Request.Type.Direction == XFER_WRITE) - { - /* Copy the data into the buffer we created */ - if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) - { - kfree(buff); - return -EFAULT; - } - } else { - memset(buff, 0, iocommand.buf_size); - } - if ((c = cmd_alloc(host , 0)) == NULL) - { - kfree(buff); - return -ENOMEM; - } - // Fill in the command type - c->cmd_type = CMD_IOCTL_PEND; - // Fill in Command Header - c->Header.ReplyQueue = 0; // unused in simple mode - if( iocommand.buf_size > 0) // buffer to fill { - c->Header.SGList = 1; - c->Header.SGTotal= 1; - } else // no buffers to fill - { - c->Header.SGList = 0; - c->Header.SGTotal= 0; - } - c->Header.LUN = iocommand.LUN_info; - c->Header.Tag.lower = c->busaddr; // use the kernel address the cmd block for tag - - // Fill in Request block - c->Request = iocommand.Request; - - // Fill in the scatter gather information - if (iocommand.buf_size > 0 ) - { - temp64.val = pci_map_single( host->pdev, buff, - iocommand.buf_size, - PCI_DMA_BIDIRECTIONAL); - c->SG[0].Addr.lower = temp64.val32.lower; - c->SG[0].Addr.upper = temp64.val32.upper; - c->SG[0].Len = iocommand.buf_size; - c->SG[0].Ext = 0; // we are not chaining - } - c->waiting = &wait; + IOCTL_Command_struct iocommand; + CommandList_struct *c; + char *buff = NULL; + u64bit temp64; + unsigned long flags; + DECLARE_COMPLETION(wait); - /* Put the request on the tail of the request queue */ - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - addQ(&host->reqQ, c); - host->Qdepth++; - start_io(host); - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + if (!arg) + return -EINVAL; - wait_for_completion(&wait); + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; - /* unlock the buffers from DMA */ - temp64.val32.lower = c->SG[0].Addr.lower; - temp64.val32.upper = c->SG[0].Addr.upper; - pci_unmap_single( host->pdev, (dma_addr_t) temp64.val, - iocommand.buf_size, PCI_DMA_BIDIRECTIONAL); + if (copy_from_user + (&iocommand, argp, sizeof(IOCTL_Command_struct))) + return -EFAULT; + if ((iocommand.buf_size < 1) && + (iocommand.Request.Type.Direction != XFER_NONE)) { + return -EINVAL; + } +#if 0 /* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */ + /* Check kmalloc limits */ + if (iocommand.buf_size > 128000) + return -EINVAL; +#endif + if (iocommand.buf_size > 0) { + buff = kmalloc(iocommand.buf_size, GFP_KERNEL); + if (buff == NULL) + return -EFAULT; + } + if (iocommand.Request.Type.Direction == XFER_WRITE) { + /* Copy the data into the buffer we created */ + if (copy_from_user + (buff, iocommand.buf, iocommand.buf_size)) { + kfree(buff); + return -EFAULT; + } + } else { + memset(buff, 0, iocommand.buf_size); + } + if ((c = cmd_alloc(host, 0)) == NULL) { + kfree(buff); + return -ENOMEM; + } + // Fill in the command type + c->cmd_type = CMD_IOCTL_PEND; + // Fill in Command Header + c->Header.ReplyQueue = 0; // unused in simple mode + if (iocommand.buf_size > 0) // buffer to fill + { + c->Header.SGList = 1; + c->Header.SGTotal = 1; + } else // no buffers to fill + { + c->Header.SGList = 0; + c->Header.SGTotal = 0; + } + c->Header.LUN = iocommand.LUN_info; + c->Header.Tag.lower = c->busaddr; // use the kernel address the cmd block for tag - /* Copy the error information out */ - iocommand.error_info = *(c->err_info); - if ( copy_to_user(argp, &iocommand, sizeof( IOCTL_Command_struct) ) ) - { - kfree(buff); - cmd_free(host, c, 0); - return( -EFAULT); - } + // Fill in Request block + c->Request = iocommand.Request; - if (iocommand.Request.Type.Direction == XFER_READ) - { - /* Copy the data out of the buffer we created */ - if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) - { - kfree(buff); + // Fill in the scatter gather information + if (iocommand.buf_size > 0) { + temp64.val = pci_map_single(host->pdev, buff, + iocommand.buf_size, + PCI_DMA_BIDIRECTIONAL); + c->SG[0].Addr.lower = temp64.val32.lower; + c->SG[0].Addr.upper = temp64.val32.upper; + c->SG[0].Len = iocommand.buf_size; + c->SG[0].Ext = 0; // we are not chaining + } + c->waiting = &wait; + + /* Put the request on the tail of the request queue */ + spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + addQ(&host->reqQ, c); + host->Qdepth++; + start_io(host); + spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + + wait_for_completion(&wait); + + /* unlock the buffers from DMA */ + temp64.val32.lower = c->SG[0].Addr.lower; + temp64.val32.upper = c->SG[0].Addr.upper; + pci_unmap_single(host->pdev, (dma_addr_t) temp64.val, + iocommand.buf_size, + PCI_DMA_BIDIRECTIONAL); + + /* Copy the error information out */ + iocommand.error_info = *(c->err_info); + if (copy_to_user + (argp, &iocommand, sizeof(IOCTL_Command_struct))) { + kfree(buff); cmd_free(host, c, 0); return -EFAULT; } - } - kfree(buff); - cmd_free(host, c, 0); - return(0); - } - case CCISS_BIG_PASSTHRU: { - BIG_IOCTL_Command_struct *ioc; - CommandList_struct *c; - unsigned char **buff = NULL; - int *buff_size = NULL; - u64bit temp64; - unsigned long flags; - BYTE sg_used = 0; - int status = 0; - int i; - DECLARE_COMPLETION(wait); - __u32 left; - __u32 sz; - BYTE __user *data_ptr; - - if (!arg) - return -EINVAL; - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - ioc = (BIG_IOCTL_Command_struct *) - kmalloc(sizeof(*ioc), GFP_KERNEL); - if (!ioc) { - status = -ENOMEM; - goto cleanup1; - } - if (copy_from_user(ioc, argp, sizeof(*ioc))) { - status = -EFAULT; - goto cleanup1; + + if (iocommand.Request.Type.Direction == XFER_READ) { + /* Copy the data out of the buffer we created */ + if (copy_to_user + (iocommand.buf, buff, iocommand.buf_size)) { + kfree(buff); + cmd_free(host, c, 0); + return -EFAULT; + } + } + kfree(buff); + cmd_free(host, c, 0); + return 0; } - if ((ioc->buf_size < 1) && - (ioc->Request.Type.Direction != XFER_NONE)) { + case CCISS_BIG_PASSTHRU:{ + BIG_IOCTL_Command_struct *ioc; + CommandList_struct *c; + unsigned char **buff = NULL; + int *buff_size = NULL; + u64bit temp64; + unsigned long flags; + BYTE sg_used = 0; + int status = 0; + int i; + DECLARE_COMPLETION(wait); + __u32 left; + __u32 sz; + BYTE __user *data_ptr; + + if (!arg) + return -EINVAL; + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + ioc = (BIG_IOCTL_Command_struct *) + kmalloc(sizeof(*ioc), GFP_KERNEL); + if (!ioc) { + status = -ENOMEM; + goto cleanup1; + } + if (copy_from_user(ioc, argp, sizeof(*ioc))) { + status = -EFAULT; + goto cleanup1; + } + if ((ioc->buf_size < 1) && + (ioc->Request.Type.Direction != XFER_NONE)) { status = -EINVAL; goto cleanup1; - } - /* Check kmalloc limits using all SGs */ - if (ioc->malloc_size > MAX_KMALLOC_SIZE) { - status = -EINVAL; - goto cleanup1; - } - if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) { - status = -EINVAL; - goto cleanup1; - } - buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL); - if (!buff) { - status = -ENOMEM; - goto cleanup1; - } - buff_size = (int *) kmalloc(MAXSGENTRIES * sizeof(int), - GFP_KERNEL); - if (!buff_size) { - status = -ENOMEM; - goto cleanup1; - } - left = ioc->buf_size; - data_ptr = ioc->buf; - while (left) { - sz = (left > ioc->malloc_size) ? ioc->malloc_size : left; - buff_size[sg_used] = sz; - buff[sg_used] = kmalloc(sz, GFP_KERNEL); - if (buff[sg_used] == NULL) { + } + /* Check kmalloc limits using all SGs */ + if (ioc->malloc_size > MAX_KMALLOC_SIZE) { + status = -EINVAL; + goto cleanup1; + } + if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) { + status = -EINVAL; + goto cleanup1; + } + buff = + kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL); + if (!buff) { status = -ENOMEM; goto cleanup1; } - if (ioc->Request.Type.Direction == XFER_WRITE) { - if (copy_from_user(buff[sg_used], data_ptr, sz)) { + buff_size = (int *)kmalloc(MAXSGENTRIES * sizeof(int), + GFP_KERNEL); + if (!buff_size) { + status = -ENOMEM; + goto cleanup1; + } + left = ioc->buf_size; + data_ptr = ioc->buf; + while (left) { + sz = (left > + ioc->malloc_size) ? ioc-> + malloc_size : left; + buff_size[sg_used] = sz; + buff[sg_used] = kmalloc(sz, GFP_KERNEL); + if (buff[sg_used] == NULL) { status = -ENOMEM; goto cleanup1; } + if (ioc->Request.Type.Direction == XFER_WRITE) { + if (copy_from_user + (buff[sg_used], data_ptr, sz)) { + status = -ENOMEM; + goto cleanup1; + } + } else { + memset(buff[sg_used], 0, sz); + } + left -= sz; + data_ptr += sz; + sg_used++; + } + if ((c = cmd_alloc(host, 0)) == NULL) { + status = -ENOMEM; + goto cleanup1; + } + c->cmd_type = CMD_IOCTL_PEND; + c->Header.ReplyQueue = 0; + + if (ioc->buf_size > 0) { + c->Header.SGList = sg_used; + c->Header.SGTotal = sg_used; } else { - memset(buff[sg_used], 0, sz); + c->Header.SGList = 0; + c->Header.SGTotal = 0; } - left -= sz; - data_ptr += sz; - sg_used++; - } - if ((c = cmd_alloc(host , 0)) == NULL) { - status = -ENOMEM; - goto cleanup1; - } - c->cmd_type = CMD_IOCTL_PEND; - c->Header.ReplyQueue = 0; - - if( ioc->buf_size > 0) { - c->Header.SGList = sg_used; - c->Header.SGTotal= sg_used; - } else { - c->Header.SGList = 0; - c->Header.SGTotal= 0; - } - c->Header.LUN = ioc->LUN_info; - c->Header.Tag.lower = c->busaddr; - - c->Request = ioc->Request; - if (ioc->buf_size > 0 ) { - int i; - for(i=0; ipdev, buff[i], - buff_size[i], + c->Header.LUN = ioc->LUN_info; + c->Header.Tag.lower = c->busaddr; + + c->Request = ioc->Request; + if (ioc->buf_size > 0) { + int i; + for (i = 0; i < sg_used; i++) { + temp64.val = + pci_map_single(host->pdev, buff[i], + buff_size[i], + PCI_DMA_BIDIRECTIONAL); + c->SG[i].Addr.lower = + temp64.val32.lower; + c->SG[i].Addr.upper = + temp64.val32.upper; + c->SG[i].Len = buff_size[i]; + c->SG[i].Ext = 0; /* we are not chaining */ + } + } + c->waiting = &wait; + /* Put the request on the tail of the request queue */ + spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + addQ(&host->reqQ, c); + host->Qdepth++; + start_io(host); + spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + wait_for_completion(&wait); + /* unlock the buffers from DMA */ + for (i = 0; i < sg_used; i++) { + temp64.val32.lower = c->SG[i].Addr.lower; + temp64.val32.upper = c->SG[i].Addr.upper; + pci_unmap_single(host->pdev, + (dma_addr_t) temp64.val, buff_size[i], PCI_DMA_BIDIRECTIONAL); - c->SG[i].Addr.lower = temp64.val32.lower; - c->SG[i].Addr.upper = temp64.val32.upper; - c->SG[i].Len = buff_size[i]; - c->SG[i].Ext = 0; /* we are not chaining */ } - } - c->waiting = &wait; - /* Put the request on the tail of the request queue */ - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - addQ(&host->reqQ, c); - host->Qdepth++; - start_io(host); - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - wait_for_completion(&wait); - /* unlock the buffers from DMA */ - for(i=0; iSG[i].Addr.lower; - temp64.val32.upper = c->SG[i].Addr.upper; - pci_unmap_single( host->pdev, (dma_addr_t) temp64.val, - buff_size[i], PCI_DMA_BIDIRECTIONAL); - } - /* Copy the error information out */ - ioc->error_info = *(c->err_info); - if (copy_to_user(argp, ioc, sizeof(*ioc))) { - cmd_free(host, c, 0); - status = -EFAULT; - goto cleanup1; - } - if (ioc->Request.Type.Direction == XFER_READ) { - /* Copy the data out of the buffer we created */ - BYTE __user *ptr = ioc->buf; - for(i=0; i< sg_used; i++) { - if (copy_to_user(ptr, buff[i], buff_size[i])) { - cmd_free(host, c, 0); - status = -EFAULT; - goto cleanup1; + /* Copy the error information out */ + ioc->error_info = *(c->err_info); + if (copy_to_user(argp, ioc, sizeof(*ioc))) { + cmd_free(host, c, 0); + status = -EFAULT; + goto cleanup1; + } + if (ioc->Request.Type.Direction == XFER_READ) { + /* Copy the data out of the buffer we created */ + BYTE __user *ptr = ioc->buf; + for (i = 0; i < sg_used; i++) { + if (copy_to_user + (ptr, buff[i], buff_size[i])) { + cmd_free(host, c, 0); + status = -EFAULT; + goto cleanup1; + } + ptr += buff_size[i]; } - ptr += buff_size[i]; } + cmd_free(host, c, 0); + status = 0; + cleanup1: + if (buff) { + for (i = 0; i < sg_used; i++) + kfree(buff[i]); + kfree(buff); + } + kfree(buff_size); + kfree(ioc); + return status; } - cmd_free(host, c, 0); - status = 0; -cleanup1: - if (buff) { - for(i=0; ictlr, i; unsigned long flags; - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - if (host->usage_count > 1) { - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - printk(KERN_WARNING "cciss: Device busy for volume" - " revalidation (usage=%d)\n", host->usage_count); - return -EBUSY; - } - host->usage_count++; + spin_lock_irqsave(CCISS_LOCK(ctlr), flags); + if (host->usage_count > 1) { + spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + printk(KERN_WARNING "cciss: Device busy for volume" + " revalidation (usage=%d)\n", host->usage_count); + return -EBUSY; + } + host->usage_count++; spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - for(i=0; i< NWD; i++) { + for (i = 0; i < NWD; i++) { struct gendisk *disk = host->gendisk[i]; if (disk) { request_queue_t *q = disk->queue; @@ -1149,22 +1189,22 @@ static int revalidate_allvol(ctlr_info_t } } - /* - * Set the partition and block size structures for all volumes - * on this controller to zero. We will reread all of this data - */ - memset(host->drv, 0, sizeof(drive_info_struct) - * CISS_MAX_LUN); - /* - * Tell the array controller not to give us any interrupts while - * we check the new geometry. Then turn interrupts back on when - * we're done. - */ - host->access.set_intr_mask(host, CCISS_INTR_OFF); - cciss_getgeometry(ctlr); - host->access.set_intr_mask(host, CCISS_INTR_ON); - - /* Loop through each real device */ + /* + * Set the partition and block size structures for all volumes + * on this controller to zero. We will reread all of this data + */ + memset(host->drv, 0, sizeof(drive_info_struct) + * CISS_MAX_LUN); + /* + * Tell the array controller not to give us any interrupts while + * we check the new geometry. Then turn interrupts back on when + * we're done. + */ + host->access.set_intr_mask(host, CCISS_INTR_OFF); + cciss_getgeometry(ctlr); + host->access.set_intr_mask(host, CCISS_INTR_ON); + + /* Loop through each real device */ for (i = 0; i < NWD; i++) { struct gendisk *disk = host->gendisk[i]; drive_info_struct *drv = &(host->drv[i]); @@ -1176,8 +1216,8 @@ static int revalidate_allvol(ctlr_info_t set_capacity(disk, drv->nr_blocks); add_disk(disk); } - host->usage_count--; - return 0; + host->usage_count--; + return 0; } static inline void complete_buffers(struct bio *bio, int status) @@ -1191,7 +1231,6 @@ static inline void complete_buffers(stru bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO); bio = xbh; } - } static void cciss_softirq_done(struct request *rq) @@ -1209,7 +1248,7 @@ static void cciss_softirq_done(struct re /* command did not need to be retried */ /* unmap the DMA mapping for all the scatter gather elements */ - for(i=0; iHeader.SGList; i++) { + for (i = 0; i < cmd->Header.SGList; i++) { temp64.val32.lower = cmd->SG[i].Addr.lower; temp64.val32.upper = cmd->SG[i].Addr.upper; pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir); @@ -1219,11 +1258,12 @@ static void cciss_softirq_done(struct re #ifdef CCISS_DEBUG printk("Done with %p\n", rq); -#endif /* CCISS_DEBUG */ +#endif /* CCISS_DEBUG */ + add_disk_randomness(rq->rq_disk); spin_lock_irqsave(&h->lock, flags); end_that_request_last(rq, rq->errors); - cmd_free(h, cmd,1); + cmd_free(h, cmd, 1); spin_unlock_irqrestore(&h->lock, flags); } @@ -1234,9 +1274,9 @@ #endif /* CCISS_DEBUG */ * will always be left registered with the kernel since it is also the * controller node. Any changes to disk 0 will show up on the next * reboot. -*/ + */ static void cciss_update_drive_info(int ctlr, int drv_index) - { +{ ctlr_info_t *h = hba[ctlr]; struct gendisk *disk; ReadCapdata_struct *size_buff = NULL; @@ -1246,13 +1286,13 @@ static void cciss_update_drive_info(int unsigned long flags = 0; int ret = 0; - /* if the disk already exists then deregister it before proceeding*/ - if (h->drv[drv_index].raid_level != -1){ + /* if the disk already exists then deregister it before proceeding */ + if (h->drv[drv_index].raid_level != -1) { spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); h->drv[drv_index].busy_configuring = 1; spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); ret = deregister_disk(h->gendisk[drv_index], - &h->drv[drv_index], 0); + &h->drv[drv_index], 0); h->drv[drv_index].busy_configuring = 0; } @@ -1260,27 +1300,25 @@ static void cciss_update_drive_info(int if (ret) return; - - /* Get information about the disk and modify the driver sturcture */ - size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); - if (size_buff == NULL) + /* Get information about the disk and modify the driver structure */ + size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); + if (size_buff == NULL) goto mem_msg; - inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); + inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); if (inq_buff == NULL) goto mem_msg; cciss_read_capacity(ctlr, drv_index, size_buff, 1, - &total_size, &block_size); + &total_size, &block_size); cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size, - inq_buff, &h->drv[drv_index]); + inq_buff, &h->drv[drv_index]); ++h->num_luns; disk = h->gendisk[drv_index]; set_capacity(disk, h->drv[drv_index].nr_blocks); - /* if it's the controller it's already added */ - if (drv_index){ + if (drv_index) { disk->queue = blk_init_queue(do_cciss_request, &h->lock); /* Set up queue information */ @@ -1300,17 +1338,17 @@ static void cciss_update_drive_info(int disk->queue->queuedata = hba[ctlr]; blk_queue_hardsect_size(disk->queue, - hba[ctlr]->drv[drv_index].block_size); + hba[ctlr]->drv[drv_index].block_size); h->drv[drv_index].queue = disk->queue; add_disk(disk); } -freeret: + freeret: kfree(size_buff); kfree(inq_buff); return; -mem_msg: + mem_msg: printk(KERN_ERR "cciss: out of memory\n"); goto freeret; } @@ -1320,13 +1358,13 @@ mem_msg: * where new drives will be added. If the index to be returned is greater * than the highest_lun index for the controller then highest_lun is set * to this new index. If there are no available indexes then -1 is returned. -*/ + */ static int cciss_find_free_drive_index(int ctlr) { int i; - for (i=0; i < CISS_MAX_LUN; i++){ - if (hba[ctlr]->drv[i].raid_level == -1){ + for (i = 0; i < CISS_MAX_LUN; i++) { + if (hba[ctlr]->drv[i].raid_level == -1) { if (i > hba[ctlr]->highest_lun) hba[ctlr]->highest_lun = i; return i; @@ -1336,7 +1374,7 @@ static int cciss_find_free_drive_index(i } /* This function will add and remove logical drives from the Logical - * drive array of the controller and maintain persistancy of ordering + * drive array of the controller and maintain persistency of ordering * so that mount points are preserved until the next reboot. This allows * for the removal of logical drives in the middle of the drive array * without a re-ordering of those drives. @@ -1344,7 +1382,7 @@ static int cciss_find_free_drive_index(i * h = The controller to perform the operations on * del_disk = The disk to remove if specified. If the value given * is NULL then no disk is removed. -*/ + */ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) { int ctlr = h->ctlr; @@ -1361,12 +1399,12 @@ static int rebuild_lun_table(ctlr_info_t /* Set busy_configuring flag for this operation */ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); - if (h->num_luns >= CISS_MAX_LUN){ + if (h->num_luns >= CISS_MAX_LUN) { spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); return -EINVAL; } - if (h->busy_configuring){ + if (h->busy_configuring) { spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); return -EBUSY; } @@ -1376,7 +1414,7 @@ static int rebuild_lun_table(ctlr_info_t * and update the logical drive table. If it is not NULL then * we will check if the disk is in use or not. */ - if (del_disk != NULL){ + if (del_disk != NULL) { drv = get_drv(del_disk); drv->busy_configuring = 1; spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); @@ -1394,61 +1432,67 @@ static int rebuild_lun_table(ctlr_info_t goto mem_msg; return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, - sizeof(ReportLunData_struct), 0, 0, 0, - TYPE_CMD); - - if (return_code == IO_OK){ - listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24; - listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16; - listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8; - listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]); - } else{ /* reading number of logical volumes failed */ + sizeof(ReportLunData_struct), 0, + 0, 0, TYPE_CMD); + + if (return_code == IO_OK) { + listlength |= + (0xff & (unsigned int)(ld_buff->LUNListLength[0])) + << 24; + listlength |= + (0xff & (unsigned int)(ld_buff->LUNListLength[1])) + << 16; + listlength |= + (0xff & (unsigned int)(ld_buff->LUNListLength[2])) + << 8; + listlength |= + 0xff & (unsigned int)(ld_buff->LUNListLength[3]); + } else { /* reading number of logical volumes failed */ printk(KERN_WARNING "cciss: report logical volume" - " command failed\n"); + " command failed\n"); listlength = 0; goto freeret; } num_luns = listlength / 8; /* 8 bytes per entry */ - if (num_luns > CISS_MAX_LUN){ + if (num_luns > CISS_MAX_LUN) { num_luns = CISS_MAX_LUN; printk(KERN_WARNING "cciss: more luns configured" - " on controller than can be handled by" - " this driver.\n"); + " on controller than can be handled by" + " this driver.\n"); } /* Compare controller drive array to drivers drive array. - * Check for updates in the drive information and any new drives - * on the controller. - */ - for (i=0; i < num_luns; i++){ + * Check for updates in the drive information and any new drives + * on the controller. + */ + for (i = 0; i < num_luns; i++) { int j; drv_found = 0; - lunid = (0xff & - (unsigned int)(ld_buff->LUN[i][3])) << 24; - lunid |= (0xff & - (unsigned int)(ld_buff->LUN[i][2])) << 16; - lunid |= (0xff & - (unsigned int)(ld_buff->LUN[i][1])) << 8; - lunid |= 0xff & - (unsigned int)(ld_buff->LUN[i][0]); + lunid = (0xff & + (unsigned int)(ld_buff->LUN[i][3])) << 24; + lunid |= (0xff & + (unsigned int)(ld_buff->LUN[i][2])) << 16; + lunid |= (0xff & + (unsigned int)(ld_buff->LUN[i][1])) << 8; + lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); /* Find if the LUN is already in the drive array * of the controller. If so then update its info * if not is use. If it does not exist then find * the first free index and add it. - */ - for (j=0; j <= h->highest_lun; j++){ - if (h->drv[j].LunID == lunid){ + */ + for (j = 0; j <= h->highest_lun; j++) { + if (h->drv[j].LunID == lunid) { drv_index = j; drv_found = 1; } } /* check if the drive was found already in the array */ - if (!drv_found){ + if (!drv_found) { drv_index = cciss_find_free_drive_index(ctlr); if (drv_index == -1) goto freeret; @@ -1456,18 +1500,18 @@ static int rebuild_lun_table(ctlr_info_t } h->drv[drv_index].LunID = lunid; cciss_update_drive_info(ctlr, drv_index); - } /* end for */ - } /* end else */ + } /* end for */ + } /* end else */ -freeret: + freeret: kfree(ld_buff); h->busy_configuring = 0; /* We return -1 here to tell the ACU that we have registered/updated * all of the drives that we can and to keep it from calling us * additional times. - */ + */ return -1; -mem_msg: + mem_msg: printk(KERN_ERR "cciss: out of memory\n"); goto freeret; } @@ -1483,7 +1527,7 @@ mem_msg: * clear_all = This flag determines whether or not the disk information * is going to be completely cleared out and the highest_lun * reset. Sometimes we want to clear out information about - * the disk in preperation for re-adding it. In this case + * the disk in preparation for re-adding it. In this case * the highest_lun should be left unchanged and the LunID * should not be cleared. */ @@ -1496,19 +1540,17 @@ static int deregister_disk(struct gendis return -EPERM; /* make sure logical volume is NOT is use */ - if(clear_all || (h->gendisk[0] == disk)) { - if (drv->usage_count > 1) - return -EBUSY; - } - else - if( drv->usage_count > 0 ) - return -EBUSY; + if (clear_all || (h->gendisk[0] == disk)) { + if (drv->usage_count > 1) + return -EBUSY; + } else if (drv->usage_count > 0) + return -EBUSY; /* invalidate the devices and deregister the disk. If it is disk * zero do not deregister it but just zero out it's values. This * allows us to delete disk zero but keep the controller registered. - */ - if (h->gendisk[0] != disk){ + */ + if (h->gendisk[0] != disk) { if (disk) { request_queue_t *q = disk->queue; if (disk->flags & GENHD_FL_UP) @@ -1530,91 +1572,90 @@ static int deregister_disk(struct gendis drv->raid_level = -1; /* This can be used as a flag variable to * indicate that this element of the drive * array is free. - */ - - if (clear_all){ - /* check to see if it was the last disk */ - if (drv == h->drv + h->highest_lun) { - /* if so, find the new hightest lun */ - int i, newhighest =-1; - for(i=0; ihighest_lun; i++) { - /* if the disk has size > 0, it is available */ + */ + + if (clear_all) { + /* check to see if it was the last disk */ + if (drv == h->drv + h->highest_lun) { + /* if so, find the new hightest lun */ + int i, newhighest = -1; + for (i = 0; i < h->highest_lun; i++) { + /* if the disk has size > 0, it is available */ if (h->drv[i].heads) - newhighest = i; + newhighest = i; + } + h->highest_lun = newhighest; } - h->highest_lun = newhighest; - } - drv->LunID = 0; + drv->LunID = 0; } - return(0); + return 0; } -static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, - size_t size, - unsigned int use_unit_num, /* 0: address the controller, - 1: address logical volume log_unit, - 2: periph device address is scsi3addr */ - unsigned int log_unit, __u8 page_code, unsigned char *scsi3addr, - int cmd_type) +static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num, /* 0: address the controller, + 1: address logical volume log_unit, + 2: periph device address is scsi3addr */ + unsigned int log_unit, __u8 page_code, + unsigned char *scsi3addr, int cmd_type) { - ctlr_info_t *h= hba[ctlr]; + ctlr_info_t *h = hba[ctlr]; u64bit buff_dma_handle; int status = IO_OK; c->cmd_type = CMD_IOCTL_PEND; c->Header.ReplyQueue = 0; - if( buff != NULL) { + if (buff != NULL) { c->Header.SGList = 1; - c->Header.SGTotal= 1; + c->Header.SGTotal = 1; } else { c->Header.SGList = 0; - c->Header.SGTotal= 0; + c->Header.SGTotal = 0; } c->Header.Tag.lower = c->busaddr; c->Request.Type.Type = cmd_type; if (cmd_type == TYPE_CMD) { - switch(cmd) { - case CISS_INQUIRY: + switch (cmd) { + case CISS_INQUIRY: /* If the logical unit number is 0 then, this is going - to controller so It's a physical command - mode = 0 target = 0. So we have nothing to write. - otherwise, if use_unit_num == 1, - mode = 1(volume set addressing) target = LUNID - otherwise, if use_unit_num == 2, - mode = 0(periph dev addr) target = scsi3addr */ + to controller so It's a physical command + mode = 0 target = 0. So we have nothing to write. + otherwise, if use_unit_num == 1, + mode = 1(volume set addressing) target = LUNID + otherwise, if use_unit_num == 2, + mode = 0(periph dev addr) target = scsi3addr */ if (use_unit_num == 1) { - c->Header.LUN.LogDev.VolId= - h->drv[log_unit].LunID; - c->Header.LUN.LogDev.Mode = 1; + c->Header.LUN.LogDev.VolId = + h->drv[log_unit].LunID; + c->Header.LUN.LogDev.Mode = 1; } else if (use_unit_num == 2) { - memcpy(c->Header.LUN.LunAddrBytes,scsi3addr,8); + memcpy(c->Header.LUN.LunAddrBytes, scsi3addr, + 8); c->Header.LUN.LogDev.Mode = 0; } /* are we trying to read a vital product page */ - if(page_code != 0) { + if (page_code != 0) { c->Request.CDB[1] = 0x01; c->Request.CDB[2] = page_code; } c->Request.CDBLen = 6; - c->Request.Type.Attribute = ATTR_SIMPLE; + c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = XFER_READ; c->Request.Timeout = 0; - c->Request.CDB[0] = CISS_INQUIRY; - c->Request.CDB[4] = size & 0xFF; - break; + c->Request.CDB[0] = CISS_INQUIRY; + c->Request.CDB[4] = size & 0xFF; + break; case CISS_REPORT_LOG: case CISS_REPORT_PHYS: - /* Talking to controller so It's a physical command + /* Talking to controller so It's a physical command mode = 00 target = 0. Nothing to write. - */ + */ c->Request.CDBLen = 12; c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = XFER_READ; c->Request.Timeout = 0; c->Request.CDB[0] = cmd; - c->Request.CDB[6] = (size >> 24) & 0xFF; //MSB + c->Request.CDB[6] = (size >> 24) & 0xFF; //MSB c->Request.CDB[7] = (size >> 16) & 0xFF; c->Request.CDB[8] = (size >> 8) & 0xFF; c->Request.CDB[9] = size & 0xFF; @@ -1628,7 +1669,7 @@ static int fill_cmd(CommandList_struct * c->Request.Type.Direction = XFER_READ; c->Request.Timeout = 0; c->Request.CDB[0] = cmd; - break; + break; case CCISS_CACHE_FLUSH: c->Request.CDBLen = 12; c->Request.Type.Attribute = ATTR_SIMPLE; @@ -1636,32 +1677,32 @@ static int fill_cmd(CommandList_struct * c->Request.Timeout = 0; c->Request.CDB[0] = BMIC_WRITE; c->Request.CDB[6] = BMIC_CACHE_FLUSH; - break; + break; default: printk(KERN_WARNING - "cciss%d: Unknown Command 0x%c\n", ctlr, cmd); - return(IO_ERROR); + "cciss%d: Unknown Command 0x%c\n", ctlr, cmd); + return IO_ERROR; } } else if (cmd_type == TYPE_MSG) { switch (cmd) { - case 0: /* ABORT message */ + case 0: /* ABORT message */ c->Request.CDBLen = 12; c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = XFER_WRITE; c->Request.Timeout = 0; - c->Request.CDB[0] = cmd; /* abort */ - c->Request.CDB[1] = 0; /* abort a command */ + c->Request.CDB[0] = cmd; /* abort */ + c->Request.CDB[1] = 0; /* abort a command */ /* buff contains the tag of the command to abort */ memcpy(&c->Request.CDB[4], buff, 8); break; - case 1: /* RESET message */ + case 1: /* RESET message */ c->Request.CDBLen = 12; c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Direction = XFER_WRITE; c->Request.Timeout = 0; memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); - c->Request.CDB[0] = cmd; /* reset */ - c->Request.CDB[1] = 0x04; /* reset a LUN */ + c->Request.CDB[0] = cmd; /* reset */ + c->Request.CDB[1] = 0x04; /* reset a LUN */ case 3: /* No-Op message */ c->Request.CDBLen = 1; c->Request.Type.Attribute = ATTR_SIMPLE; @@ -1671,168 +1712,164 @@ static int fill_cmd(CommandList_struct * break; default: printk(KERN_WARNING - "cciss%d: unknown message type %d\n", - ctlr, cmd); + "cciss%d: unknown message type %d\n", ctlr, cmd); return IO_ERROR; } } else { printk(KERN_WARNING - "cciss%d: unknown command type %d\n", ctlr, cmd_type); + "cciss%d: unknown command type %d\n", ctlr, cmd_type); return IO_ERROR; } /* Fill in the scatter gather information */ if (size > 0) { buff_dma_handle.val = (__u64) pci_map_single(h->pdev, - buff, size, PCI_DMA_BIDIRECTIONAL); + buff, size, + PCI_DMA_BIDIRECTIONAL); c->SG[0].Addr.lower = buff_dma_handle.val32.lower; c->SG[0].Addr.upper = buff_dma_handle.val32.upper; c->SG[0].Len = size; - c->SG[0].Ext = 0; /* we are not chaining */ + c->SG[0].Ext = 0; /* we are not chaining */ } return status; } -static int sendcmd_withirq(__u8 cmd, - int ctlr, - void *buff, - size_t size, - unsigned int use_unit_num, - unsigned int log_unit, - __u8 page_code, - int cmd_type) + +static int sendcmd_withirq(__u8 cmd, + int ctlr, + void *buff, + size_t size, + unsigned int use_unit_num, + unsigned int log_unit, __u8 page_code, int cmd_type) { ctlr_info_t *h = hba[ctlr]; CommandList_struct *c; - u64bit buff_dma_handle; + u64bit buff_dma_handle; unsigned long flags; int return_status; DECLARE_COMPLETION(wait); - - if ((c = cmd_alloc(h , 0)) == NULL) + + if ((c = cmd_alloc(h, 0)) == NULL) return -ENOMEM; return_status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num, - log_unit, page_code, NULL, cmd_type); + log_unit, page_code, NULL, cmd_type); if (return_status != IO_OK) { cmd_free(h, c, 0); return return_status; } -resend_cmd2: + resend_cmd2: c->waiting = &wait; - + /* Put the request on the tail of the queue and send it */ spin_lock_irqsave(CCISS_LOCK(ctlr), flags); addQ(&h->reqQ, c); h->Qdepth++; start_io(h); spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - + wait_for_completion(&wait); - if(c->err_info->CommandStatus != 0) - { /* an error has occurred */ - switch(c->err_info->CommandStatus) - { - case CMD_TARGET_STATUS: - printk(KERN_WARNING "cciss: cmd %p has " - " completed with errors\n", c); - if( c->err_info->ScsiStatus) - { - printk(KERN_WARNING "cciss: cmd %p " - "has SCSI Status = %x\n", - c, - c->err_info->ScsiStatus); - } + if (c->err_info->CommandStatus != 0) { /* an error has occurred */ + switch (c->err_info->CommandStatus) { + case CMD_TARGET_STATUS: + printk(KERN_WARNING "cciss: cmd %p has " + " completed with errors\n", c); + if (c->err_info->ScsiStatus) { + printk(KERN_WARNING "cciss: cmd %p " + "has SCSI Status = %x\n", + c, c->err_info->ScsiStatus); + } break; - case CMD_DATA_UNDERRUN: - case CMD_DATA_OVERRUN: + case CMD_DATA_UNDERRUN: + case CMD_DATA_OVERRUN: /* expected for inquire and report lun commands */ break; - case CMD_INVALID: - printk(KERN_WARNING "cciss: Cmd %p is " - "reported invalid\n", c); - return_status = IO_ERROR; + case CMD_INVALID: + printk(KERN_WARNING "cciss: Cmd %p is " + "reported invalid\n", c); + return_status = IO_ERROR; break; - case CMD_PROTOCOL_ERR: - printk(KERN_WARNING "cciss: cmd %p has " - "protocol error \n", c); - return_status = IO_ERROR; - break; -case CMD_HARDWARE_ERR: - printk(KERN_WARNING "cciss: cmd %p had " - " hardware error\n", c); - return_status = IO_ERROR; - break; - case CMD_CONNECTION_LOST: - printk(KERN_WARNING "cciss: cmd %p had " - "connection lost\n", c); - return_status = IO_ERROR; + case CMD_PROTOCOL_ERR: + printk(KERN_WARNING "cciss: cmd %p has " + "protocol error \n", c); + return_status = IO_ERROR; break; - case CMD_ABORTED: - printk(KERN_WARNING "cciss: cmd %p was " - "aborted\n", c); - return_status = IO_ERROR; + case CMD_HARDWARE_ERR: + printk(KERN_WARNING "cciss: cmd %p had " + " hardware error\n", c); + return_status = IO_ERROR; break; - case CMD_ABORT_FAILED: - printk(KERN_WARNING "cciss: cmd %p reports " - "abort failed\n", c); - return_status = IO_ERROR; + case CMD_CONNECTION_LOST: + printk(KERN_WARNING "cciss: cmd %p had " + "connection lost\n", c); + return_status = IO_ERROR; break; - case CMD_UNSOLICITED_ABORT: - printk(KERN_WARNING - "cciss%d: unsolicited abort %p\n", - ctlr, c); - if (c->retry_count < MAX_CMD_RETRIES) { - printk(KERN_WARNING - "cciss%d: retrying %p\n", - ctlr, c); - c->retry_count++; - /* erase the old error information */ - memset(c->err_info, 0, - sizeof(ErrorInfo_struct)); - return_status = IO_OK; - INIT_COMPLETION(wait); - goto resend_cmd2; - } - return_status = IO_ERROR; + case CMD_ABORTED: + printk(KERN_WARNING "cciss: cmd %p was " + "aborted\n", c); + return_status = IO_ERROR; + break; + case CMD_ABORT_FAILED: + printk(KERN_WARNING "cciss: cmd %p reports " + "abort failed\n", c); + return_status = IO_ERROR; break; - default: - printk(KERN_WARNING "cciss: cmd %p returned " - "unknown status %x\n", c, - c->err_info->CommandStatus); - return_status = IO_ERROR; + case CMD_UNSOLICITED_ABORT: + printk(KERN_WARNING + "cciss%d: unsolicited abort %p\n", ctlr, c); + if (c->retry_count < MAX_CMD_RETRIES) { + printk(KERN_WARNING + "cciss%d: retrying %p\n", ctlr, c); + c->retry_count++; + /* erase the old error information */ + memset(c->err_info, 0, + sizeof(ErrorInfo_struct)); + return_status = IO_OK; + INIT_COMPLETION(wait); + goto resend_cmd2; + } + return_status = IO_ERROR; + break; + default: + printk(KERN_WARNING "cciss: cmd %p returned " + "unknown status %x\n", c, + c->err_info->CommandStatus); + return_status = IO_ERROR; } - } + } /* unlock the buffers from DMA */ buff_dma_handle.val32.lower = c->SG[0].Addr.lower; buff_dma_handle.val32.upper = c->SG[0].Addr.upper; - pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val, - c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); + pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val, + c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); cmd_free(h, c, 0); - return(return_status); - + return return_status; } + static void cciss_geometry_inquiry(int ctlr, int logvol, - int withirq, unsigned int total_size, - unsigned int block_size, InquiryData_struct *inq_buff, - drive_info_struct *drv) + int withirq, unsigned int total_size, + unsigned int block_size, + InquiryData_struct *inq_buff, + drive_info_struct *drv) { int return_code; memset(inq_buff, 0, sizeof(InquiryData_struct)); if (withirq) return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, - inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1, TYPE_CMD); + inq_buff, sizeof(*inq_buff), 1, + logvol, 0xC1, TYPE_CMD); else return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff, - sizeof(*inq_buff), 1, logvol ,0xC1, NULL, TYPE_CMD); + sizeof(*inq_buff), 1, logvol, 0xC1, NULL, + TYPE_CMD); if (return_code == IO_OK) { - if(inq_buff->data_byte[8] == 0xFF) { + if (inq_buff->data_byte[8] == 0xFF) { printk(KERN_WARNING - "cciss: reading geometry failed, volume " - "does not support reading geometry\n"); + "cciss: reading geometry failed, volume " + "does not support reading geometry\n"); drv->block_size = block_size; drv->nr_blocks = total_size; drv->heads = 255; - drv->sectors = 32; // Sectors per track + drv->sectors = 32; // Sectors per track drv->cylinders = total_size / 255 / 32; } else { unsigned int t; @@ -1846,37 +1883,42 @@ static void cciss_geometry_inquiry(int c drv->raid_level = inq_buff->data_byte[8]; t = drv->heads * drv->sectors; if (t > 1) { - drv->cylinders = total_size/t; + drv->cylinders = total_size / t; } } - } else { /* Get geometry failed */ + } else { /* Get geometry failed */ printk(KERN_WARNING "cciss: reading geometry failed\n"); } printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", - drv->heads, drv->sectors, drv->cylinders); + drv->heads, drv->sectors, drv->cylinders); } + static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, - int withirq, unsigned int *total_size, unsigned int *block_size) + int withirq, unsigned int *total_size, + unsigned int *block_size) { int return_code; memset(buf, 0, sizeof(*buf)); if (withirq) return_code = sendcmd_withirq(CCISS_READ_CAPACITY, - ctlr, buf, sizeof(*buf), 1, logvol, 0, TYPE_CMD); + ctlr, buf, sizeof(*buf), 1, + logvol, 0, TYPE_CMD); else return_code = sendcmd(CCISS_READ_CAPACITY, - ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL, TYPE_CMD); + ctlr, buf, sizeof(*buf), 1, logvol, 0, + NULL, TYPE_CMD); if (return_code == IO_OK) { - *total_size = be32_to_cpu(*((__be32 *) &buf->total_size[0]))+1; - *block_size = be32_to_cpu(*((__be32 *) &buf->block_size[0])); - } else { /* read capacity command failed */ + *total_size = + be32_to_cpu(*((__be32 *) & buf->total_size[0])) + 1; + *block_size = be32_to_cpu(*((__be32 *) & buf->block_size[0])); + } else { /* read capacity command failed */ printk(KERN_WARNING "cciss: read capacity failed\n"); *total_size = 0; *block_size = BLOCK_SIZE; } printk(KERN_INFO " blocks= %u block_size= %d\n", - *total_size, *block_size); + *total_size, *block_size); return; } @@ -1885,38 +1927,38 @@ static int cciss_revalidate(struct gendi ctlr_info_t *h = get_host(disk); drive_info_struct *drv = get_drv(disk); int logvol; - int FOUND=0; + int FOUND = 0; unsigned int block_size; unsigned int total_size; ReadCapdata_struct *size_buff = NULL; InquiryData_struct *inq_buff = NULL; - for(logvol=0; logvol < CISS_MAX_LUN; logvol++) - { - if(h->drv[logvol].LunID == drv->LunID) { - FOUND=1; + for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { + if (h->drv[logvol].LunID == drv->LunID) { + FOUND = 1; break; } } - if (!FOUND) return 1; + if (!FOUND) + return 1; - size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); - if (size_buff == NULL) - { - printk(KERN_WARNING "cciss: out of memory\n"); - return 1; - } - inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); - if (inq_buff == NULL) - { - printk(KERN_WARNING "cciss: out of memory\n"); + size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); + if (size_buff == NULL) { + printk(KERN_WARNING "cciss: out of memory\n"); + return 1; + } + inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); + if (inq_buff == NULL) { + printk(KERN_WARNING "cciss: out of memory\n"); kfree(size_buff); - return 1; - } + return 1; + } - cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size, &block_size); - cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, inq_buff, drv); + cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size, + &block_size); + cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, + inq_buff, drv); blk_queue_hardsect_size(drv->queue, drv->block_size); set_capacity(disk, drv->nr_blocks); @@ -1943,7 +1985,7 @@ static unsigned long pollcomplete(int ct if (done == FIFO_EMPTY) schedule_timeout_uninterruptible(1); else - return (done); + return done; } /* Invalid address to tell caller we ran out of time */ return 1; @@ -1952,28 +1994,28 @@ static unsigned long pollcomplete(int ct static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete) { /* We get in here if sendcmd() is polling for completions - and gets some command back that it wasn't expecting -- - something other than that which it just sent down. - Ordinarily, that shouldn't happen, but it can happen when + and gets some command back that it wasn't expecting -- + something other than that which it just sent down. + Ordinarily, that shouldn't happen, but it can happen when the scsi tape stuff gets into error handling mode, and - starts using sendcmd() to try to abort commands and + starts using sendcmd() to try to abort commands and reset tape drives. In that case, sendcmd may pick up completions of commands that were sent to logical drives - through the block i/o system, or cciss ioctls completing, etc. + through the block i/o system, or cciss ioctls completing, etc. In that case, we need to save those completions for later processing by the interrupt handler. - */ + */ #ifdef CONFIG_CISS_SCSI_TAPE - struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects; + struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects; /* If it's not the scsi tape stuff doing error handling, (abort */ /* or reset) then we don't expect anything weird. */ if (cmd != CCISS_RESET_MSG && cmd != CCISS_ABORT_MSG) { #endif - printk( KERN_WARNING "cciss cciss%d: SendCmd " - "Invalid command list address returned! (%lx)\n", - ctlr, complete); + printk(KERN_WARNING "cciss cciss%d: SendCmd " + "Invalid command list address returned! (%lx)\n", + ctlr, complete); /* not much we can do. */ #ifdef CONFIG_CISS_SCSI_TAPE return 1; @@ -1984,7 +2026,7 @@ #ifdef CONFIG_CISS_SCSI_TAPE if (srl->ncompletions >= (NR_CMDS + 2)) { /* Uh oh. No room to save it for later... */ printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, " - "reject list overflow, command lost!\n", ctlr); + "reject list overflow, command lost!\n", ctlr); return 1; } /* Save it for later */ @@ -1995,340 +2037,327 @@ #endif } /* - * Send a command to the controller, and wait for it to complete. - * Only used at init time. + * Send a command to the controller, and wait for it to complete. + * Only used at init time. */ -static int sendcmd( - __u8 cmd, - int ctlr, - void *buff, - size_t size, - unsigned int use_unit_num, /* 0: address the controller, - 1: address logical volume log_unit, - 2: periph device address is scsi3addr */ - unsigned int log_unit, - __u8 page_code, - unsigned char *scsi3addr, - int cmd_type) +static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num, /* 0: address the controller, + 1: address logical volume log_unit, + 2: periph device address is scsi3addr */ + unsigned int log_unit, + __u8 page_code, unsigned char *scsi3addr, int cmd_type) { CommandList_struct *c; int i; unsigned long complete; - ctlr_info_t *info_p= hba[ctlr]; + ctlr_info_t *info_p = hba[ctlr]; u64bit buff_dma_handle; int status, done = 0; if ((c = cmd_alloc(info_p, 1)) == NULL) { printk(KERN_WARNING "cciss: unable to get memory"); - return(IO_ERROR); + return IO_ERROR; } status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num, - log_unit, page_code, scsi3addr, cmd_type); + log_unit, page_code, scsi3addr, cmd_type); if (status != IO_OK) { cmd_free(info_p, c, 1); return status; } -resend_cmd1: + resend_cmd1: /* - * Disable interrupt - */ + * Disable interrupt + */ #ifdef CCISS_DEBUG printk(KERN_DEBUG "cciss: turning intr off\n"); -#endif /* CCISS_DEBUG */ - info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF); - +#endif /* CCISS_DEBUG */ + info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF); + /* Make sure there is room in the command FIFO */ - /* Actually it should be completely empty at this time */ + /* Actually it should be completely empty at this time */ /* unless we are in here doing error handling for the scsi */ /* tape side of the driver. */ - for (i = 200000; i > 0; i--) - { + for (i = 200000; i > 0; i--) { /* if fifo isn't full go */ - if (!(info_p->access.fifo_full(info_p))) - { - - break; - } - udelay(10); - printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full," - " waiting!\n", ctlr); - } - /* - * Send the cmd - */ - info_p->access.submit_command(info_p, c); + if (!(info_p->access.fifo_full(info_p))) { + + break; + } + udelay(10); + printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full," + " waiting!\n", ctlr); + } + /* + * Send the cmd + */ + info_p->access.submit_command(info_p, c); done = 0; do { complete = pollcomplete(ctlr); #ifdef CCISS_DEBUG printk(KERN_DEBUG "cciss: command completed\n"); -#endif /* CCISS_DEBUG */ +#endif /* CCISS_DEBUG */ if (complete == 1) { - printk( KERN_WARNING - "cciss cciss%d: SendCmd Timeout out, " - "No command list address returned!\n", - ctlr); + printk(KERN_WARNING + "cciss cciss%d: SendCmd Timeout out, " + "No command list address returned!\n", ctlr); status = IO_ERROR; done = 1; break; } /* This will need to change for direct lookup completions */ - if ( (complete & CISS_ERROR_BIT) - && (complete & ~CISS_ERROR_BIT) == c->busaddr) - { - /* if data overrun or underun on Report command - ignore it - */ + if ((complete & CISS_ERROR_BIT) + && (complete & ~CISS_ERROR_BIT) == c->busaddr) { + /* if data overrun or underun on Report command + ignore it + */ if (((c->Request.CDB[0] == CISS_REPORT_LOG) || (c->Request.CDB[0] == CISS_REPORT_PHYS) || (c->Request.CDB[0] == CISS_INQUIRY)) && - ((c->err_info->CommandStatus == - CMD_DATA_OVERRUN) || - (c->err_info->CommandStatus == - CMD_DATA_UNDERRUN) - )) - { + ((c->err_info->CommandStatus == + CMD_DATA_OVERRUN) || + (c->err_info->CommandStatus == CMD_DATA_UNDERRUN) + )) { complete = c->busaddr; } else { if (c->err_info->CommandStatus == - CMD_UNSOLICITED_ABORT) { + CMD_UNSOLICITED_ABORT) { printk(KERN_WARNING "cciss%d: " - "unsolicited abort %p\n", - ctlr, c); + "unsolicited abort %p\n", + ctlr, c); if (c->retry_count < MAX_CMD_RETRIES) { printk(KERN_WARNING - "cciss%d: retrying %p\n", - ctlr, c); + "cciss%d: retrying %p\n", + ctlr, c); c->retry_count++; /* erase the old error */ /* information */ memset(c->err_info, 0, - sizeof(ErrorInfo_struct)); + sizeof + (ErrorInfo_struct)); goto resend_cmd1; } else { printk(KERN_WARNING - "cciss%d: retried %p too " - "many times\n", ctlr, c); + "cciss%d: retried %p too " + "many times\n", ctlr, c); status = IO_ERROR; goto cleanup1; } - } else if (c->err_info->CommandStatus == CMD_UNABORTABLE) { - printk(KERN_WARNING "cciss%d: command could not be aborted.\n", ctlr); + } else if (c->err_info->CommandStatus == + CMD_UNABORTABLE) { + printk(KERN_WARNING + "cciss%d: command could not be aborted.\n", + ctlr); status = IO_ERROR; goto cleanup1; } printk(KERN_WARNING "ciss ciss%d: sendcmd" - " Error %x \n", ctlr, - c->err_info->CommandStatus); + " Error %x \n", ctlr, + c->err_info->CommandStatus); printk(KERN_WARNING "ciss ciss%d: sendcmd" - " offensive info\n" - " size %x\n num %x value %x\n", ctlr, - c->err_info->MoreErrInfo.Invalid_Cmd.offense_size, - c->err_info->MoreErrInfo.Invalid_Cmd.offense_num, - c->err_info->MoreErrInfo.Invalid_Cmd.offense_value); + " offensive info\n" + " size %x\n num %x value %x\n", + ctlr, + c->err_info->MoreErrInfo.Invalid_Cmd. + offense_size, + c->err_info->MoreErrInfo.Invalid_Cmd. + offense_num, + c->err_info->MoreErrInfo.Invalid_Cmd. + offense_value); status = IO_ERROR; goto cleanup1; } } /* This will need changing for direct lookup completions */ - if (complete != c->busaddr) { + if (complete != c->busaddr) { if (add_sendcmd_reject(cmd, ctlr, complete) != 0) { - BUG(); /* we are pretty much hosed if we get here. */ + BUG(); /* we are pretty much hosed if we get here. */ } continue; - } else + } else done = 1; - } while (!done); - -cleanup1: + } while (!done); + + cleanup1: /* unlock the data buffer from DMA */ buff_dma_handle.val32.lower = c->SG[0].Addr.lower; buff_dma_handle.val32.upper = c->SG[0].Addr.upper; pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, - c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); + c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); #ifdef CONFIG_CISS_SCSI_TAPE /* if we saved some commands for later, process them now. */ if (info_p->scsi_rejects.ncompletions > 0) do_cciss_intr(0, info_p, NULL); #endif cmd_free(info_p, c, 1); - return (status); -} + return status; +} + /* * Map (physical) PCI mem into (virtual) kernel space */ static void __iomem *remap_pci_mem(ulong base, ulong size) { - ulong page_base = ((ulong) base) & PAGE_MASK; - ulong page_offs = ((ulong) base) - page_base; - void __iomem *page_remapped = ioremap(page_base, page_offs+size); + ulong page_base = ((ulong) base) & PAGE_MASK; + ulong page_offs = ((ulong) base) - page_base; + void __iomem *page_remapped = ioremap(page_base, page_offs + size); - return page_remapped ? (page_remapped + page_offs) : NULL; + return page_remapped ? (page_remapped + page_offs) : NULL; } -/* - * Takes jobs of the Q and sends them to the hardware, then puts it on - * the Q to wait for completion. - */ -static void start_io( ctlr_info_t *h) +/* + * Takes jobs of the Q and sends them to the hardware, then puts it on + * the Q to wait for completion. + */ +static void start_io(ctlr_info_t *h) { CommandList_struct *c; - - while(( c = h->reqQ) != NULL ) - { + + while ((c = h->reqQ) != NULL) { /* can't do anything if fifo is full */ if ((h->access.fifo_full(h))) { printk(KERN_WARNING "cciss: fifo full\n"); break; } - /* Get the first entry from the Request Q */ + /* Get the first entry from the Request Q */ removeQ(&(h->reqQ), c); h->Qdepth--; - - /* Tell the controller execute command */ + + /* Tell the controller execute command */ h->access.submit_command(h, c); - - /* Put job onto the completed Q */ - addQ (&(h->cmpQ), c); + + /* Put job onto the completed Q */ + addQ(&(h->cmpQ), c); } } + /* Assumes that CCISS_LOCK(h->ctlr) is held. */ /* Zeros out the error record and then resends the command back */ /* to the controller */ -static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c) +static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c) { /* erase the old error information */ memset(c->err_info, 0, sizeof(ErrorInfo_struct)); /* add it to software queue and then send it to the controller */ - addQ(&(h->reqQ),c); + addQ(&(h->reqQ), c); h->Qdepth++; - if(h->Qdepth > h->maxQsinceinit) + if (h->Qdepth > h->maxQsinceinit) h->maxQsinceinit = h->Qdepth; start_io(h); } -/* checks the status of the job and calls complete buffers to mark all +/* checks the status of the job and calls complete buffers to mark all * buffers for the completed job. Note that this function does not need * to hold the hba/queue lock. - */ -static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, - int timeout) + */ +static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, + int timeout) { int status = 1; int retry_cmd = 0; - + if (timeout) - status = 0; + status = 0; - if(cmd->err_info->CommandStatus != 0) - { /* an error has occurred */ - switch(cmd->err_info->CommandStatus) - { + if (cmd->err_info->CommandStatus != 0) { /* an error has occurred */ + switch (cmd->err_info->CommandStatus) { unsigned char sense_key; - case CMD_TARGET_STATUS: - status = 0; - - if( cmd->err_info->ScsiStatus == 0x02) - { - printk(KERN_WARNING "cciss: cmd %p " - "has CHECK CONDITION " - " byte 2 = 0x%x\n", cmd, - cmd->err_info->SenseInfo[2] - ); - /* check the sense key */ - sense_key = 0xf & - cmd->err_info->SenseInfo[2]; - /* no status or recovered error */ - if((sense_key == 0x0) || - (sense_key == 0x1)) - { - status = 1; - } - } else - { - printk(KERN_WARNING "cciss: cmd %p " - "has SCSI Status 0x%x\n", - cmd, cmd->err_info->ScsiStatus); + case CMD_TARGET_STATUS: + status = 0; + + if (cmd->err_info->ScsiStatus == 0x02) { + printk(KERN_WARNING "cciss: cmd %p " + "has CHECK CONDITION " + " byte 2 = 0x%x\n", cmd, + cmd->err_info->SenseInfo[2] + ); + /* check the sense key */ + sense_key = 0xf & cmd->err_info->SenseInfo[2]; + /* no status or recovered error */ + if ((sense_key == 0x0) || (sense_key == 0x1)) { + status = 1; } + } else { + printk(KERN_WARNING "cciss: cmd %p " + "has SCSI Status 0x%x\n", + cmd, cmd->err_info->ScsiStatus); + } break; - case CMD_DATA_UNDERRUN: - printk(KERN_WARNING "cciss: cmd %p has" - " completed with data underrun " - "reported\n", cmd); + case CMD_DATA_UNDERRUN: + printk(KERN_WARNING "cciss: cmd %p has" + " completed with data underrun " + "reported\n", cmd); break; - case CMD_DATA_OVERRUN: - printk(KERN_WARNING "cciss: cmd %p has" - " completed with data overrun " - "reported\n", cmd); + case CMD_DATA_OVERRUN: + printk(KERN_WARNING "cciss: cmd %p has" + " completed with data overrun " + "reported\n", cmd); break; - case CMD_INVALID: - printk(KERN_WARNING "cciss: cmd %p is " - "reported invalid\n", cmd); - status = 0; + case CMD_INVALID: + printk(KERN_WARNING "cciss: cmd %p is " + "reported invalid\n", cmd); + status = 0; break; - case CMD_PROTOCOL_ERR: - printk(KERN_WARNING "cciss: cmd %p has " - "protocol error \n", cmd); - status = 0; - break; - case CMD_HARDWARE_ERR: - printk(KERN_WARNING "cciss: cmd %p had " - " hardware error\n", cmd); - status = 0; - break; - case CMD_CONNECTION_LOST: - printk(KERN_WARNING "cciss: cmd %p had " - "connection lost\n", cmd); - status=0; + case CMD_PROTOCOL_ERR: + printk(KERN_WARNING "cciss: cmd %p has " + "protocol error \n", cmd); + status = 0; break; - case CMD_ABORTED: - printk(KERN_WARNING "cciss: cmd %p was " - "aborted\n", cmd); - status=0; + case CMD_HARDWARE_ERR: + printk(KERN_WARNING "cciss: cmd %p had " + " hardware error\n", cmd); + status = 0; break; - case CMD_ABORT_FAILED: - printk(KERN_WARNING "cciss: cmd %p reports " - "abort failed\n", cmd); - status=0; + case CMD_CONNECTION_LOST: + printk(KERN_WARNING "cciss: cmd %p had " + "connection lost\n", cmd); + status = 0; break; - case CMD_UNSOLICITED_ABORT: - printk(KERN_WARNING "cciss%d: unsolicited " - "abort %p\n", h->ctlr, cmd); - if (cmd->retry_count < MAX_CMD_RETRIES) { - retry_cmd=1; - printk(KERN_WARNING - "cciss%d: retrying %p\n", - h->ctlr, cmd); - cmd->retry_count++; - } else - printk(KERN_WARNING - "cciss%d: %p retried too " - "many times\n", h->ctlr, cmd); - status=0; + case CMD_ABORTED: + printk(KERN_WARNING "cciss: cmd %p was " + "aborted\n", cmd); + status = 0; + break; + case CMD_ABORT_FAILED: + printk(KERN_WARNING "cciss: cmd %p reports " + "abort failed\n", cmd); + status = 0; + break; + case CMD_UNSOLICITED_ABORT: + printk(KERN_WARNING "cciss%d: unsolicited " + "abort %p\n", h->ctlr, cmd); + if (cmd->retry_count < MAX_CMD_RETRIES) { + retry_cmd = 1; + printk(KERN_WARNING + "cciss%d: retrying %p\n", h->ctlr, cmd); + cmd->retry_count++; + } else + printk(KERN_WARNING + "cciss%d: %p retried too " + "many times\n", h->ctlr, cmd); + status = 0; break; - case CMD_TIMEOUT: - printk(KERN_WARNING "cciss: cmd %p timedout\n", - cmd); - status=0; + case CMD_TIMEOUT: + printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd); + status = 0; break; - default: - printk(KERN_WARNING "cciss: cmd %p returned " - "unknown status %x\n", cmd, - cmd->err_info->CommandStatus); - status=0; + default: + printk(KERN_WARNING "cciss: cmd %p returned " + "unknown status %x\n", cmd, + cmd->err_info->CommandStatus); + status = 0; } } /* We need to return this command */ - if(retry_cmd) { - resend_cciss_cmd(h,cmd); + if (retry_cmd) { + resend_cciss_cmd(h, cmd); return; - } + } cmd->rq->completion_data = cmd; cmd->rq->errors = status; @@ -2336,12 +2365,12 @@ static inline void complete_command( ctl blk_complete_request(cmd->rq); } -/* - * Get a request and submit it to the controller. +/* + * Get a request and submit it to the controller. */ static void do_cciss_request(request_queue_t *q) { - ctlr_info_t *h= q->queuedata; + ctlr_info_t *h = q->queuedata; CommandList_struct *c; int start_blk, seg; struct request *creq; @@ -2352,18 +2381,18 @@ static void do_cciss_request(request_que /* We call start_io here in case there is a command waiting on the * queue that has not been sent. - */ + */ if (blk_queue_plugged(q)) goto startio; -queue: + queue: creq = elv_next_request(q); if (!creq) goto startio; BUG_ON(creq->nr_phys_segments > MAXSGENTRIES); - if (( c = cmd_alloc(h, 1)) == NULL) + if ((c = cmd_alloc(h, 1)) == NULL) goto full; blkdev_dequeue_request(creq); @@ -2372,81 +2401,82 @@ queue: c->cmd_type = CMD_RWREQ; c->rq = creq; - - /* fill in the request */ + + /* fill in the request */ drv = creq->rq_disk->private_data; - c->Header.ReplyQueue = 0; // unused in simple mode + c->Header.ReplyQueue = 0; // unused in simple mode /* got command from pool, so use the command block index instead */ /* for direct lookups. */ /* The first 2 bits are reserved for controller error reporting. */ c->Header.Tag.lower = (c->cmdindex << 3); - c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */ - c->Header.LUN.LogDev.VolId= drv->LunID; + c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */ + c->Header.LUN.LogDev.VolId = drv->LunID; c->Header.LUN.LogDev.Mode = 1; - c->Request.CDBLen = 10; // 12 byte commands not in FW yet; - c->Request.Type.Type = TYPE_CMD; // It is a command. - c->Request.Type.Attribute = ATTR_SIMPLE; - c->Request.Type.Direction = - (rq_data_dir(creq) == READ) ? XFER_READ: XFER_WRITE; - c->Request.Timeout = 0; // Don't time out - c->Request.CDB[0] = (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE; + c->Request.CDBLen = 10; // 12 byte commands not in FW yet; + c->Request.Type.Type = TYPE_CMD; // It is a command. + c->Request.Type.Attribute = ATTR_SIMPLE; + c->Request.Type.Direction = + (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE; + c->Request.Timeout = 0; // Don't time out + c->Request.CDB[0] = + (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE; start_blk = creq->sector; #ifdef CCISS_DEBUG - printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n",(int) creq->sector, - (int) creq->nr_sectors); -#endif /* CCISS_DEBUG */ + printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector, + (int)creq->nr_sectors); +#endif /* CCISS_DEBUG */ seg = blk_rq_map_sg(q, creq, tmp_sg); - /* get the DMA records for the setup */ + /* get the DMA records for the setup */ if (c->Request.Type.Direction == XFER_READ) dir = PCI_DMA_FROMDEVICE; else dir = PCI_DMA_TODEVICE; - for (i=0; iSG[i].Len = tmp_sg[i].length; temp64.val = (__u64) pci_map_page(h->pdev, tmp_sg[i].page, - tmp_sg[i].offset, tmp_sg[i].length, - dir); + tmp_sg[i].offset, + tmp_sg[i].length, dir); c->SG[i].Addr.lower = temp64.val32.lower; - c->SG[i].Addr.upper = temp64.val32.upper; - c->SG[i].Ext = 0; // we are not chaining + c->SG[i].Addr.upper = temp64.val32.upper; + c->SG[i].Ext = 0; // we are not chaining } - /* track how many SG entries we are using */ - if( seg > h->maxSG) - h->maxSG = seg; + /* track how many SG entries we are using */ + if (seg > h->maxSG) + h->maxSG = seg; #ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n", creq->nr_sectors, seg); -#endif /* CCISS_DEBUG */ + printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n", + creq->nr_sectors, seg); +#endif /* CCISS_DEBUG */ c->Header.SGList = c->Header.SGTotal = seg; - c->Request.CDB[1]= 0; - c->Request.CDB[2]= (start_blk >> 24) & 0xff; //MSB - c->Request.CDB[3]= (start_blk >> 16) & 0xff; - c->Request.CDB[4]= (start_blk >> 8) & 0xff; - c->Request.CDB[5]= start_blk & 0xff; - c->Request.CDB[6]= 0; // (sect >> 24) & 0xff; MSB - c->Request.CDB[7]= (creq->nr_sectors >> 8) & 0xff; - c->Request.CDB[8]= creq->nr_sectors & 0xff; + c->Request.CDB[1] = 0; + c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB + c->Request.CDB[3] = (start_blk >> 16) & 0xff; + c->Request.CDB[4] = (start_blk >> 8) & 0xff; + c->Request.CDB[5] = start_blk & 0xff; + c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB + c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff; + c->Request.CDB[8] = creq->nr_sectors & 0xff; c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; spin_lock_irq(q->queue_lock); - addQ(&(h->reqQ),c); + addQ(&(h->reqQ), c); h->Qdepth++; - if(h->Qdepth > h->maxQsinceinit) - h->maxQsinceinit = h->Qdepth; + if (h->Qdepth > h->maxQsinceinit) + h->maxQsinceinit = h->Qdepth; goto queue; -full: + full: blk_stop_queue(q); -startio: + startio: /* We will already have the driver lock here so not need * to lock it. - */ + */ start_io(h); } @@ -2473,7 +2503,7 @@ #endif static inline int interrupt_pending(ctlr_info_t *h) { #ifdef CONFIG_CISS_SCSI_TAPE - return ( h->access.intr_pending(h) + return (h->access.intr_pending(h) || (h->scsi_rejects.ncompletions > 0)); #else return h->access.intr_pending(h); @@ -2483,11 +2513,11 @@ #endif static inline long interrupt_not_for_us(ctlr_info_t *h) { #ifdef CONFIG_CISS_SCSI_TAPE - return (((h->access.intr_pending(h) == 0) || - (h->interrupts_enabled == 0)) - && (h->scsi_rejects.ncompletions == 0)); + return (((h->access.intr_pending(h) == 0) || + (h->interrupts_enabled == 0)) + && (h->scsi_rejects.ncompletions == 0)); #else - return (((h->access.intr_pending(h) == 0) || + return (((h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0))); #endif } @@ -2509,12 +2539,14 @@ static irqreturn_t do_cciss_intr(int irq */ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); while (interrupt_pending(h)) { - while((a = get_next_completion(h)) != FIFO_EMPTY) { + while ((a = get_next_completion(h)) != FIFO_EMPTY) { a1 = a; if ((a & 0x04)) { a2 = (a >> 3); if (a2 >= NR_CMDS) { - printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr); + printk(KERN_WARNING + "cciss: controller cciss%d failed, stopping.\n", + h->ctlr); fail_all_cmds(h->ctlr); return IRQ_HANDLED; } @@ -2523,22 +2555,24 @@ static irqreturn_t do_cciss_intr(int irq a = c->busaddr; } else { - a &= ~3; + a &= ~3; if ((c = h->cmpQ) == NULL) { - printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1); - continue; - } - while(c->busaddr != a) { - c = c->next; - if (c == h->cmpQ) - break; - } + printk(KERN_WARNING + "cciss: Completion of %08x ignored\n", + a1); + continue; + } + while (c->busaddr != a) { + c = c->next; + if (c == h->cmpQ) + break; + } } /* * If we've found the command, take it off the * completion Q and free it */ - if (c->busaddr == a) { + if (c->busaddr == a) { removeQ(&h->cmpQ, c); if (c->cmd_type == CMD_RWREQ) { complete_command(h, c, 0); @@ -2554,130 +2588,118 @@ # endif } } - /* check to see if we have maxed out the number of commands that can - * be placed on the queue. If so then exit. We do this check here - * in case the interrupt we serviced was from an ioctl and did not - * free any new commands. + /* check to see if we have maxed out the number of commands that can + * be placed on the queue. If so then exit. We do this check here + * in case the interrupt we serviced was from an ioctl and did not + * free any new commands. + */ + if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) + goto cleanup; + + /* We have room on the queue for more commands. Now we need to queue + * them up. We will also keep track of the next queue to run so + * that every queue gets a chance to be started first. */ - if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) - goto cleanup; - - /* We have room on the queue for more commands. Now we need to queue - * them up. We will also keep track of the next queue to run so - * that every queue gets a chance to be started first. - */ - for (j=0; j < h->highest_lun + 1; j++){ + for (j = 0; j < h->highest_lun + 1; j++) { int curr_queue = (start_queue + j) % (h->highest_lun + 1); - /* make sure the disk has been added and the drive is real - * because this can be called from the middle of init_one. - */ - if(!(h->drv[curr_queue].queue) || - !(h->drv[curr_queue].heads)) - continue; - blk_start_queue(h->gendisk[curr_queue]->queue); - - /* check to see if we have maxed out the number of commands - * that can be placed on the queue. - */ - if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) - { - if (curr_queue == start_queue){ - h->next_to_run = (start_queue + 1) % (h->highest_lun + 1); - goto cleanup; - } else { - h->next_to_run = curr_queue; - goto cleanup; - } - } else { + /* make sure the disk has been added and the drive is real + * because this can be called from the middle of init_one. + */ + if (!(h->drv[curr_queue].queue) || !(h->drv[curr_queue].heads)) + continue; + blk_start_queue(h->gendisk[curr_queue]->queue); + + /* check to see if we have maxed out the number of commands + * that can be placed on the queue. + */ + if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) { + if (curr_queue == start_queue) { + h->next_to_run = + (start_queue + 1) % (h->highest_lun + 1); + goto cleanup; + } else { + h->next_to_run = curr_queue; + goto cleanup; + } + } else { curr_queue = (curr_queue + 1) % (h->highest_lun + 1); - } - } + } + } -cleanup: + cleanup: spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); return IRQ_HANDLED; } -/* - * We cannot read the structure directly, for portablity we must use + +/* + * We cannot read the structure directly, for portability we must use * the io functions. - * This is for debug only. + * This is for debug only. */ #ifdef CCISS_DEBUG -static void print_cfg_table( CfgTable_struct *tb) +static void print_cfg_table(CfgTable_struct *tb) { int i; char temp_name[17]; printk("Controller Configuration information\n"); printk("------------------------------------\n"); - for(i=0;i<4;i++) + for (i = 0; i < 4; i++) temp_name[i] = readb(&(tb->Signature[i])); - temp_name[4]='\0'; - printk(" Signature = %s\n", temp_name); + temp_name[4] = '\0'; + printk(" Signature = %s\n", temp_name); printk(" Spec Number = %d\n", readl(&(tb->SpecValence))); - printk(" Transport methods supported = 0x%x\n", - readl(&(tb-> TransportSupport))); - printk(" Transport methods active = 0x%x\n", - readl(&(tb->TransportActive))); - printk(" Requested transport Method = 0x%x\n", - readl(&(tb->HostWrite.TransportRequest))); - printk(" Coalese Interrupt Delay = 0x%x\n", - readl(&(tb->HostWrite.CoalIntDelay))); - printk(" Coalese Interrupt Count = 0x%x\n", - readl(&(tb->HostWrite.CoalIntCount))); - printk(" Max outstanding commands = 0x%d\n", - readl(&(tb->CmdsOutMax))); - printk(" Bus Types = 0x%x\n", readl(&(tb-> BusTypes))); - for(i=0;i<16;i++) + printk(" Transport methods supported = 0x%x\n", + readl(&(tb->TransportSupport))); + printk(" Transport methods active = 0x%x\n", + readl(&(tb->TransportActive))); + printk(" Requested transport Method = 0x%x\n", + readl(&(tb->HostWrite.TransportRequest))); + printk(" Coalesce Interrupt Delay = 0x%x\n", + readl(&(tb->HostWrite.CoalIntDelay))); + printk(" Coalesce Interrupt Count = 0x%x\n", + readl(&(tb->HostWrite.CoalIntCount))); + printk(" Max outstanding commands = 0x%d\n", + readl(&(tb->CmdsOutMax))); + printk(" Bus Types = 0x%x\n", readl(&(tb->BusTypes))); + for (i = 0; i < 16; i++) temp_name[i] = readb(&(tb->ServerName[i])); temp_name[16] = '\0'; printk(" Server Name = %s\n", temp_name); - printk(" Heartbeat Counter = 0x%x\n\n\n", - readl(&(tb->HeartBeat))); -} -#endif /* CCISS_DEBUG */ - -static void release_io_mem(ctlr_info_t *c) -{ - /* if IO mem was not protected do nothing */ - if( c->io_mem_addr == 0) - return; - release_region(c->io_mem_addr, c->io_mem_length); - c->io_mem_addr = 0; - c->io_mem_length = 0; + printk(" Heartbeat Counter = 0x%x\n\n\n", readl(&(tb->HeartBeat))); } +#endif /* CCISS_DEBUG */ -static int find_PCI_BAR_index(struct pci_dev *pdev, - unsigned long pci_bar_addr) +static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr) { int i, offset, mem_type, bar_type; - if (pci_bar_addr == PCI_BASE_ADDRESS_0) /* looking for BAR zero? */ + if (pci_bar_addr == PCI_BASE_ADDRESS_0) /* looking for BAR zero? */ return 0; offset = 0; - for (i=0; iintr[0] = cciss_msix_entries[0].vector; - c->intr[1] = cciss_msix_entries[1].vector; - c->intr[2] = cciss_msix_entries[2].vector; - c->intr[3] = cciss_msix_entries[3].vector; - c->msix_vector = 1; - return; - } - if (err > 0) { - printk(KERN_WARNING "cciss: only %d MSI-X vectors " - "available\n", err); - } else { - printk(KERN_WARNING "cciss: MSI-X init failed %d\n", - err); - } - } - if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) { - if (!pci_enable_msi(pdev)) { - c->intr[SIMPLE_MODE_INT] = pdev->irq; - c->msi_vector = 1; - return; - } else { - printk(KERN_WARNING "cciss: MSI init failed\n"); - c->intr[SIMPLE_MODE_INT] = pdev->irq; - return; - } - } -default_int_mode: -#endif /* CONFIG_PCI_MSI */ + if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) { + err = pci_enable_msix(pdev, cciss_msix_entries, 4); + if (!err) { + c->intr[0] = cciss_msix_entries[0].vector; + c->intr[1] = cciss_msix_entries[1].vector; + c->intr[2] = cciss_msix_entries[2].vector; + c->intr[3] = cciss_msix_entries[3].vector; + c->msix_vector = 1; + return; + } + if (err > 0) { + printk(KERN_WARNING "cciss: only %d MSI-X vectors " + "available\n", err); + } else { + printk(KERN_WARNING "cciss: MSI-X init failed %d\n", + err); + } + } + if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) { + if (!pci_enable_msi(pdev)) { + c->intr[SIMPLE_MODE_INT] = pdev->irq; + c->msi_vector = 1; + return; + } else { + printk(KERN_WARNING "cciss: MSI init failed\n"); + c->intr[SIMPLE_MODE_INT] = pdev->irq; + return; + } + } + default_int_mode: +#endif /* CONFIG_PCI_MSI */ /* if we get here we're going to use the default interrupt mode */ - c->intr[SIMPLE_MODE_INT] = pdev->irq; + c->intr[SIMPLE_MODE_INT] = pdev->irq; return; } @@ -2743,58 +2766,40 @@ static int cciss_pci_init(ctlr_info_t *c __u64 cfg_offset; __u32 cfg_base_addr; __u64 cfg_base_addr_index; - int i; + int i, err; /* check to see if controller has been disabled */ /* BEFORE trying to enable it */ - (void) pci_read_config_word(pdev, PCI_COMMAND,&command); - if(!(command & 0x02)) - { - printk(KERN_WARNING "cciss: controller appears to be disabled\n"); - return(-1); + (void)pci_read_config_word(pdev, PCI_COMMAND, &command); + if (!(command & 0x02)) { + printk(KERN_WARNING + "cciss: controller appears to be disabled\n"); + return -ENODEV; } - if (pci_enable_device(pdev)) - { + err = pci_enable_device(pdev); + if (err) { printk(KERN_ERR "cciss: Unable to Enable PCI device\n"); - return( -1); + return err; + } + + err = pci_request_regions(pdev, "cciss"); + if (err) { + printk(KERN_ERR "cciss: Cannot obtain PCI resources, " + "aborting\n"); + goto err_out_disable_pdev; } subsystem_vendor_id = pdev->subsystem_vendor; subsystem_device_id = pdev->subsystem_device; board_id = (((__u32) (subsystem_device_id << 16) & 0xffff0000) | - subsystem_vendor_id); - - /* search for our IO range so we can protect it */ - for(i=0; iio_mem_addr = pci_resource_start(pdev, i); - c->io_mem_length = pci_resource_end(pdev, i) - - pci_resource_start(pdev, i) +1; -#ifdef CCISS_DEBUG - printk("IO value found base_addr[%d] %lx %lx\n", i, - c->io_mem_addr, c->io_mem_length); -#endif /* CCISS_DEBUG */ - /* register the IO range */ - if(!request_region( c->io_mem_addr, - c->io_mem_length, "cciss")) - { - printk(KERN_WARNING "cciss I/O memory range already in use addr=%lx length=%ld\n", - c->io_mem_addr, c->io_mem_length); - c->io_mem_addr= 0; - c->io_mem_length = 0; - } - break; - } - } + subsystem_vendor_id); #ifdef CCISS_DEBUG printk("command = %x\n", command); printk("irq = %x\n", pdev->irq); printk("board_id = %x\n", board_id); -#endif /* CCISS_DEBUG */ +#endif /* CCISS_DEBUG */ /* If the kernel supports MSI/MSI-X we will try to enable that functionality, * else we use the IO-APIC interrupt assigned to us by system ROM. @@ -2803,27 +2808,28 @@ #endif /* CCISS_DEBUG */ /* * Memory base addr is first addr , the second points to the config - * table + * table */ - c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */ + c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */ #ifdef CCISS_DEBUG printk("address 0 = %x\n", c->paddr); -#endif /* CCISS_DEBUG */ +#endif /* CCISS_DEBUG */ c->vaddr = remap_pci_mem(c->paddr, 200); /* Wait for the board to become ready. (PCI hotplug needs this.) * We poll for up to 120 secs, once per 100ms. */ - for (i=0; i < 1200; i++) { + for (i = 0; i < 1200; i++) { scratchpad = readl(c->vaddr + SA5_SCRATCHPAD_OFFSET); if (scratchpad == CCISS_FIRMWARE_READY) break; set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); /* wait 100ms */ + schedule_timeout(HZ / 10); /* wait 100ms */ } if (scratchpad != CCISS_FIRMWARE_READY) { printk(KERN_WARNING "cciss: Board not ready. Timed out.\n"); - return -1; + err = -ENODEV; + goto err_out_free_res; } /* get the address index number */ @@ -2831,103 +2837,108 @@ #endif /* CCISS_DEBUG */ cfg_base_addr &= (__u32) 0x0000ffff; #ifdef CCISS_DEBUG printk("cfg base address = %x\n", cfg_base_addr); -#endif /* CCISS_DEBUG */ - cfg_base_addr_index = - find_PCI_BAR_index(pdev, cfg_base_addr); +#endif /* CCISS_DEBUG */ + cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr); #ifdef CCISS_DEBUG printk("cfg base address index = %x\n", cfg_base_addr_index); -#endif /* CCISS_DEBUG */ +#endif /* CCISS_DEBUG */ if (cfg_base_addr_index == -1) { printk(KERN_WARNING "cciss: Cannot find cfg_base_addr_index\n"); - release_io_mem(c); - return -1; + err = -ENODEV; + goto err_out_free_res; } cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET); #ifdef CCISS_DEBUG printk("cfg offset = %x\n", cfg_offset); -#endif /* CCISS_DEBUG */ - c->cfgtable = remap_pci_mem(pci_resource_start(pdev, - cfg_base_addr_index) + cfg_offset, - sizeof(CfgTable_struct)); +#endif /* CCISS_DEBUG */ + c->cfgtable = remap_pci_mem(pci_resource_start(pdev, + cfg_base_addr_index) + + cfg_offset, sizeof(CfgTable_struct)); c->board_id = board_id; #ifdef CCISS_DEBUG print_cfg_table(c->cfgtable); -#endif /* CCISS_DEBUG */ +#endif /* CCISS_DEBUG */ - for(i=0; iproduct_name = products[i].product_name; c->access = *(products[i].access); break; } } - if (i == NR_PRODUCTS) { + if (i == ARRAY_SIZE(products)) { printk(KERN_WARNING "cciss: Sorry, I don't know how" - " to access the Smart Array controller %08lx\n", - (unsigned long)board_id); - return -1; - } - if ( (readb(&c->cfgtable->Signature[0]) != 'C') || - (readb(&c->cfgtable->Signature[1]) != 'I') || - (readb(&c->cfgtable->Signature[2]) != 'S') || - (readb(&c->cfgtable->Signature[3]) != 'S') ) - { + " to access the Smart Array controller %08lx\n", + (unsigned long)board_id); + err = -ENODEV; + goto err_out_free_res; + } + if ((readb(&c->cfgtable->Signature[0]) != 'C') || + (readb(&c->cfgtable->Signature[1]) != 'I') || + (readb(&c->cfgtable->Signature[2]) != 'S') || + (readb(&c->cfgtable->Signature[3]) != 'S')) { printk("Does not appear to be a valid CISS config table\n"); - return -1; + err = -ENODEV; + goto err_out_free_res; } - #ifdef CONFIG_X86 -{ - /* Need to enable prefetch in the SCSI core for 6400 in x86 */ - __u32 prefetch; - prefetch = readl(&(c->cfgtable->SCSI_Prefetch)); - prefetch |= 0x100; - writel(prefetch, &(c->cfgtable->SCSI_Prefetch)); -} + { + /* Need to enable prefetch in the SCSI core for 6400 in x86 */ + __u32 prefetch; + prefetch = readl(&(c->cfgtable->SCSI_Prefetch)); + prefetch |= 0x100; + writel(prefetch, &(c->cfgtable->SCSI_Prefetch)); + } #endif #ifdef CCISS_DEBUG printk("Trying to put board into Simple mode\n"); -#endif /* CCISS_DEBUG */ +#endif /* CCISS_DEBUG */ c->max_commands = readl(&(c->cfgtable->CmdsOutMax)); - /* Update the field, and then ring the doorbell */ - writel( CFGTBL_Trans_Simple, - &(c->cfgtable->HostWrite.TransportRequest)); - writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL); + /* Update the field, and then ring the doorbell */ + writel(CFGTBL_Trans_Simple, &(c->cfgtable->HostWrite.TransportRequest)); + writel(CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL); /* under certain very rare conditions, this can take awhile. * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right * as we enter this code.) */ - for(i=0;ivaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) break; /* delay and try again */ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(10); - } + } #ifdef CCISS_DEBUG - printk(KERN_DEBUG "I counter got to %d %x\n", i, readl(c->vaddr + SA5_DOORBELL)); -#endif /* CCISS_DEBUG */ + printk(KERN_DEBUG "I counter got to %d %x\n", i, + readl(c->vaddr + SA5_DOORBELL)); +#endif /* CCISS_DEBUG */ #ifdef CCISS_DEBUG - print_cfg_table(c->cfgtable); -#endif /* CCISS_DEBUG */ + print_cfg_table(c->cfgtable); +#endif /* CCISS_DEBUG */ - if (!(readl(&(c->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) - { + if (!(readl(&(c->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { printk(KERN_WARNING "cciss: unable to get board into" - " simple mode\n"); - return -1; + " simple mode\n"); + err = -ENODEV; + goto err_out_free_res; } return 0; + err_out_free_res: + pci_release_regions(pdev); + + err_out_disable_pdev: + pci_disable_device(pdev); + return err; } -/* - * Gets information about the local volumes attached to the controller. - */ +/* + * Gets information about the local volumes attached to the controller. + */ static void cciss_getgeometry(int cntl_num) { ReportLunData_struct *ld_buff; @@ -2938,102 +2949,102 @@ static void cciss_getgeometry(int cntl_n int listlength = 0; __u32 lunid = 0; int block_size; - int total_size; + int total_size; ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); - if (ld_buff == NULL) - { + if (ld_buff == NULL) { + printk(KERN_ERR "cciss: out of memory\n"); + return; + } + size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); + if (size_buff == NULL) { printk(KERN_ERR "cciss: out of memory\n"); + kfree(ld_buff); return; } - size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); - if (size_buff == NULL) - { - printk(KERN_ERR "cciss: out of memory\n"); + inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); + if (inq_buff == NULL) { + printk(KERN_ERR "cciss: out of memory\n"); kfree(ld_buff); - return; - } - inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); - if (inq_buff == NULL) - { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); kfree(size_buff); - return; - } - /* Get the firmware version */ - return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, - sizeof(InquiryData_struct), 0, 0 ,0, NULL, TYPE_CMD); - if (return_code == IO_OK) - { + return; + } + /* Get the firmware version */ + return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, + sizeof(InquiryData_struct), 0, 0, 0, NULL, + TYPE_CMD); + if (return_code == IO_OK) { hba[cntl_num]->firm_ver[0] = inq_buff->data_byte[32]; hba[cntl_num]->firm_ver[1] = inq_buff->data_byte[33]; hba[cntl_num]->firm_ver[2] = inq_buff->data_byte[34]; hba[cntl_num]->firm_ver[3] = inq_buff->data_byte[35]; - } else /* send command failed */ - { + } else { /* send command failed */ + printk(KERN_WARNING "cciss: unable to determine firmware" - " version of controller\n"); + " version of controller\n"); } - /* Get the number of logical volumes */ - return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff, - sizeof(ReportLunData_struct), 0, 0, 0, NULL, TYPE_CMD); + /* Get the number of logical volumes */ + return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff, + sizeof(ReportLunData_struct), 0, 0, 0, NULL, + TYPE_CMD); - if( return_code == IO_OK) - { + if (return_code == IO_OK) { #ifdef CCISS_DEBUG printk("LUN Data\n--------------------------\n"); -#endif /* CCISS_DEBUG */ - - listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24; - listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16; - listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8; +#endif /* CCISS_DEBUG */ + + listlength |= + (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24; + listlength |= + (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16; + listlength |= + (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8; listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]); - } else /* reading number of logical volumes failed */ - { + } else { /* reading number of logical volumes failed */ + printk(KERN_WARNING "cciss: report logical volume" - " command failed\n"); + " command failed\n"); listlength = 0; } - hba[cntl_num]->num_luns = listlength / 8; // 8 bytes pre entry - if (hba[cntl_num]->num_luns > CISS_MAX_LUN) - { - printk(KERN_ERR "ciss: only %d number of logical volumes supported\n", - CISS_MAX_LUN); + hba[cntl_num]->num_luns = listlength / 8; // 8 bytes pre entry + if (hba[cntl_num]->num_luns > CISS_MAX_LUN) { + printk(KERN_ERR + "ciss: only %d number of logical volumes supported\n", + CISS_MAX_LUN); hba[cntl_num]->num_luns = CISS_MAX_LUN; } #ifdef CCISS_DEBUG - printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0], - ld_buff->LUNListLength[1], ld_buff->LUNListLength[2], - ld_buff->LUNListLength[3], hba[cntl_num]->num_luns); -#endif /* CCISS_DEBUG */ - - hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1; -// for(i=0; i< hba[cntl_num]->num_luns; i++) - for(i=0; i < CISS_MAX_LUN; i++) - { - if (i < hba[cntl_num]->num_luns){ - lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) - << 24; - lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) - << 16; - lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) - << 8; - lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); - - hba[cntl_num]->drv[i].LunID = lunid; - + printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", + ld_buff->LUNListLength[0], ld_buff->LUNListLength[1], + ld_buff->LUNListLength[2], ld_buff->LUNListLength[3], + hba[cntl_num]->num_luns); +#endif /* CCISS_DEBUG */ + + hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1; +// for(i=0; i< hba[cntl_num]->num_luns; i++) + for (i = 0; i < CISS_MAX_LUN; i++) { + if (i < hba[cntl_num]->num_luns) { + lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) + << 24; + lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) + << 16; + lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) + << 8; + lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); + + hba[cntl_num]->drv[i].LunID = lunid; #ifdef CCISS_DEBUG - printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i, - ld_buff->LUN[i][0], ld_buff->LUN[i][1], - ld_buff->LUN[i][2], ld_buff->LUN[i][3], - hba[cntl_num]->drv[i].LunID); -#endif /* CCISS_DEBUG */ - cciss_read_capacity(cntl_num, i, size_buff, 0, - &total_size, &block_size); + printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i, + ld_buff->LUN[i][0], ld_buff->LUN[i][1], + ld_buff->LUN[i][2], ld_buff->LUN[i][3], + hba[cntl_num]->drv[i].LunID); +#endif /* CCISS_DEBUG */ + cciss_read_capacity(cntl_num, i, size_buff, 0, + &total_size, &block_size); cciss_geometry_inquiry(cntl_num, i, 0, total_size, - block_size, inq_buff, &hba[cntl_num]->drv[i]); + block_size, inq_buff, + &hba[cntl_num]->drv[i]); } else { /* initialize raid_level to indicate a free space */ hba[cntl_num]->drv[i].raid_level = -1; @@ -3042,7 +3053,7 @@ #endif /* CCISS_DEBUG */ kfree(ld_buff); kfree(size_buff); kfree(inq_buff); -} +} /* Function to find the first free pointer into our hba[] array */ /* Returns -1 if no free entries are left. */ @@ -3056,7 +3067,7 @@ static int alloc_cciss_hba(void) goto out; } - for(i=0; i< MAX_CTLR; i++) { + for (i = 0; i < MAX_CTLR; i++) { if (!hba[i]) { ctlr_info_t *p; p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL); @@ -3069,11 +3080,11 @@ static int alloc_cciss_hba(void) } } printk(KERN_WARNING "cciss: This driver supports a maximum" - " of %d controllers.\n", MAX_CTLR); + " of %d controllers.\n", MAX_CTLR); goto out; -Enomem: + Enomem: printk(KERN_ERR "cciss: out of memory.\n"); -out: + out: while (n--) put_disk(disk[n]); return -1; @@ -3096,20 +3107,17 @@ static void free_hba(int i) * returns the number of block devices registered. */ static int __devinit cciss_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { request_queue_t *q; int i; int j; int rc; + int dac; - printk(KERN_DEBUG "cciss: Device 0x%x has been found at" - " bus %d dev %d func %d\n", - pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn)); i = alloc_cciss_hba(); - if(i < 0) - return (-1); + if (i < 0) + return -1; hba[i]->busy_initializing = 1; @@ -3122,11 +3130,11 @@ static int __devinit cciss_init_one(stru /* configure PCI DMA stuff */ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) - printk("cciss: using DAC cycles\n"); + dac = 1; else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) - printk("cciss: not using DAC cycles\n"); + dac = 0; else { - printk("cciss: no suitable DMA available\n"); + printk(KERN_ERR "cciss: no suitable DMA available\n"); goto clean1; } @@ -3138,60 +3146,69 @@ static int __devinit cciss_init_one(stru if (i < MAX_CTLR_ORIG) hba[i]->major = COMPAQ_CISS_MAJOR + i; rc = register_blkdev(hba[i]->major, hba[i]->devname); - if(rc == -EBUSY || rc == -EINVAL) { + if (rc == -EBUSY || rc == -EINVAL) { printk(KERN_ERR - "cciss: Unable to get major number %d for %s " - "on hba %d\n", hba[i]->major, hba[i]->devname, i); + "cciss: Unable to get major number %d for %s " + "on hba %d\n", hba[i]->major, hba[i]->devname, i); goto clean1; - } - else { + } else { if (i >= MAX_CTLR_ORIG) hba[i]->major = rc; } /* make sure the board interrupts are off */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); - if( request_irq(hba[i]->intr[SIMPLE_MODE_INT], do_cciss_intr, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, - hba[i]->devname, hba[i])) { + if (request_irq(hba[i]->intr[SIMPLE_MODE_INT], do_cciss_intr, + SA_INTERRUPT | SA_SHIRQ, hba[i]->devname, hba[i])) { printk(KERN_ERR "cciss: Unable to get irq %d for %s\n", - hba[i]->intr[SIMPLE_MODE_INT], hba[i]->devname); + hba[i]->intr[SIMPLE_MODE_INT], hba[i]->devname); goto clean2; } - hba[i]->cmd_pool_bits = kmalloc(((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long), GFP_KERNEL); - hba[i]->cmd_pool = (CommandList_struct *)pci_alloc_consistent( - hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), - &(hba[i]->cmd_pool_dhandle)); - hba[i]->errinfo_pool = (ErrorInfo_struct *)pci_alloc_consistent( - hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), - &(hba[i]->errinfo_pool_dhandle)); - if((hba[i]->cmd_pool_bits == NULL) - || (hba[i]->cmd_pool == NULL) - || (hba[i]->errinfo_pool == NULL)) { - printk( KERN_ERR "cciss: out of memory"); + + printk(KERN_INFO "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n", + hba[i]->devname, pdev->device, pci_name(pdev), + hba[i]->intr[SIMPLE_MODE_INT], dac ? "" : " not"); + + hba[i]->cmd_pool_bits = + kmalloc(((NR_CMDS + BITS_PER_LONG - + 1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL); + hba[i]->cmd_pool = (CommandList_struct *) + pci_alloc_consistent(hba[i]->pdev, + NR_CMDS * sizeof(CommandList_struct), + &(hba[i]->cmd_pool_dhandle)); + hba[i]->errinfo_pool = (ErrorInfo_struct *) + pci_alloc_consistent(hba[i]->pdev, + NR_CMDS * sizeof(ErrorInfo_struct), + &(hba[i]->errinfo_pool_dhandle)); + if ((hba[i]->cmd_pool_bits == NULL) + || (hba[i]->cmd_pool == NULL) + || (hba[i]->errinfo_pool == NULL)) { + printk(KERN_ERR "cciss: out of memory"); goto clean4; } #ifdef CONFIG_CISS_SCSI_TAPE - hba[i]->scsi_rejects.complete = - kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) * - (NR_CMDS + 5), GFP_KERNEL); + hba[i]->scsi_rejects.complete = + kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) * + (NR_CMDS + 5), GFP_KERNEL); if (hba[i]->scsi_rejects.complete == NULL) { - printk( KERN_ERR "cciss: out of memory"); + printk(KERN_ERR "cciss: out of memory"); goto clean4; } #endif spin_lock_init(&hba[i]->lock); - /* Initialize the pdev driver private data. - have it point to hba[i]. */ + /* Initialize the pdev driver private data. + have it point to hba[i]. */ pci_set_drvdata(pdev, hba[i]); - /* command and error info recs zeroed out before - they are used */ - memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long)); + /* command and error info recs zeroed out before + they are used */ + memset(hba[i]->cmd_pool_bits, 0, + ((NR_CMDS + BITS_PER_LONG - + 1) / BITS_PER_LONG) * sizeof(unsigned long)); -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n",i); -#endif /* CCISS_DEBUG */ +#ifdef CCISS_DEBUG + printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n", i); +#endif /* CCISS_DEBUG */ cciss_getgeometry(i); @@ -3203,15 +3220,15 @@ #endif /* CCISS_DEBUG */ cciss_procinit(i); hba[i]->busy_initializing = 0; - for(j=0; j < NWD; j++) { /* mfm */ + for (j = 0; j < NWD; j++) { /* mfm */ drive_info_struct *drv = &(hba[i]->drv[j]); struct gendisk *disk = hba[i]->gendisk[j]; q = blk_init_queue(do_cciss_request, &hba[i]->lock); if (!q) { printk(KERN_ERR - "cciss: unable to allocate queue for disk %d\n", - j); + "cciss: unable to allocate queue for disk %d\n", + j); break; } drv->queue = q; @@ -3237,94 +3254,90 @@ #endif /* CCISS_DEBUG */ disk->fops = &cciss_fops; disk->queue = q; disk->private_data = drv; + disk->driverfs_dev = &pdev->dev; /* we must register the controller even if no disks exist */ /* this is for the online array utilities */ - if(!drv->heads && j) + if (!drv->heads && j) continue; blk_queue_hardsect_size(q, drv->block_size); set_capacity(disk, drv->nr_blocks); add_disk(disk); } - return(1); + return 1; -clean4: + clean4: #ifdef CONFIG_CISS_SCSI_TAPE kfree(hba[i]->scsi_rejects.complete); #endif kfree(hba[i]->cmd_pool_bits); - if(hba[i]->cmd_pool) + if (hba[i]->cmd_pool) pci_free_consistent(hba[i]->pdev, - NR_CMDS * sizeof(CommandList_struct), - hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); - if(hba[i]->errinfo_pool) + NR_CMDS * sizeof(CommandList_struct), + hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); + if (hba[i]->errinfo_pool) pci_free_consistent(hba[i]->pdev, - NR_CMDS * sizeof( ErrorInfo_struct), - hba[i]->errinfo_pool, - hba[i]->errinfo_pool_dhandle); + NR_CMDS * sizeof(ErrorInfo_struct), + hba[i]->errinfo_pool, + hba[i]->errinfo_pool_dhandle); free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]); -clean2: + clean2: unregister_blkdev(hba[i]->major, hba[i]->devname); -clean1: - release_io_mem(hba[i]); + clean1: hba[i]->busy_initializing = 0; free_hba(i); - return(-1); + return -1; } -static void __devexit cciss_remove_one (struct pci_dev *pdev) +static void __devexit cciss_remove_one(struct pci_dev *pdev) { ctlr_info_t *tmp_ptr; int i, j; char flush_buf[4]; - int return_code; + int return_code; - if (pci_get_drvdata(pdev) == NULL) - { - printk( KERN_ERR "cciss: Unable to remove device \n"); + if (pci_get_drvdata(pdev) == NULL) { + printk(KERN_ERR "cciss: Unable to remove device \n"); return; } tmp_ptr = pci_get_drvdata(pdev); i = tmp_ptr->ctlr; - if (hba[i] == NULL) - { + if (hba[i] == NULL) { printk(KERN_ERR "cciss: device appears to " - "already be removed \n"); + "already be removed \n"); return; } /* Turn board interrupts off and send the flush cache command */ /* sendcmd will turn off interrupt, and send the flush... - * To write all data in the battery backed cache to disks */ + * To write all data in the battery backed cache to disks */ memset(flush_buf, 0, 4); return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL, - TYPE_CMD); - if(return_code != IO_OK) - { - printk(KERN_WARNING "Error Flushing cache on controller %d\n", - i); + TYPE_CMD); + if (return_code != IO_OK) { + printk(KERN_WARNING "Error Flushing cache on controller %d\n", + i); } free_irq(hba[i]->intr[2], hba[i]); #ifdef CONFIG_PCI_MSI - if (hba[i]->msix_vector) - pci_disable_msix(hba[i]->pdev); - else if (hba[i]->msi_vector) - pci_disable_msi(hba[i]->pdev); -#endif /* CONFIG_PCI_MSI */ + if (hba[i]->msix_vector) + pci_disable_msix(hba[i]->pdev); + else if (hba[i]->msi_vector) + pci_disable_msi(hba[i]->pdev); +#endif /* CONFIG_PCI_MSI */ - pci_set_drvdata(pdev, NULL); iounmap(hba[i]->vaddr); - cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ + cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ unregister_blkdev(hba[i]->major, hba[i]->devname); - remove_proc_entry(hba[i]->devname, proc_cciss); - + remove_proc_entry(hba[i]->devname, proc_cciss); + /* remove it from the disk list */ for (j = 0; j < NWD; j++) { struct gendisk *disk = hba[i]->gendisk[j]; if (disk) { request_queue_t *q = disk->queue; - if (disk->flags & GENHD_FL_UP) + if (disk->flags & GENHD_FL_UP) del_gendisk(disk); if (q) blk_cleanup_queue(q); @@ -3333,26 +3346,28 @@ #endif /* CONFIG_PCI_MSI */ pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); - pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), - hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); + pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(ErrorInfo_struct), + hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); kfree(hba[i]->cmd_pool_bits); #ifdef CONFIG_CISS_SCSI_TAPE kfree(hba[i]->scsi_rejects.complete); #endif - release_io_mem(hba[i]); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); free_hba(i); -} +} static struct pci_driver cciss_pci_driver = { - .name = "cciss", - .probe = cciss_init_one, - .remove = __devexit_p(cciss_remove_one), - .id_table = cciss_pci_device_id, /* id_table */ + .name = "cciss", + .probe = cciss_init_one, + .remove = __devexit_p(cciss_remove_one), + .id_table = cciss_pci_device_id, /* id_table */ }; /* * This is it. Register the PCI driver information for the cards we control - * the OS will call our registered routines when it finds one of our cards. + * the OS will call our registered routines when it finds one of our cards. */ static int __init cciss_init(void) { @@ -3368,12 +3383,10 @@ static void __exit cciss_cleanup(void) pci_unregister_driver(&cciss_pci_driver); /* double check that all controller entrys have been removed */ - for (i=0; i< MAX_CTLR; i++) - { - if (hba[i] != NULL) - { + for (i = 0; i < MAX_CTLR; i++) { + if (hba[i] != NULL) { printk(KERN_WARNING "cciss: had to remove" - " controller %d\n", i); + " controller %d\n", i); cciss_remove_one(hba[i]->pdev); } } @@ -3388,21 +3401,21 @@ static void fail_all_cmds(unsigned long unsigned long flags; printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr); - h->alive = 0; /* the controller apparently died... */ + h->alive = 0; /* the controller apparently died... */ spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - pci_disable_device(h->pdev); /* Make sure it is really dead. */ + pci_disable_device(h->pdev); /* Make sure it is really dead. */ /* move everything off the request queue onto the completed queue */ - while( (c = h->reqQ) != NULL ) { + while ((c = h->reqQ) != NULL) { removeQ(&(h->reqQ), c); h->Qdepth--; - addQ (&(h->cmpQ), c); + addQ(&(h->cmpQ), c); } /* Now, fail everything on the completed queue with a HW error */ - while( (c = h->cmpQ) != NULL ) { + while ((c = h->cmpQ) != NULL) { removeQ(&h->cmpQ, c); c->err_info->CommandStatus = CMD_HARDWARE_ERR; if (c->cmd_type == CMD_RWREQ) { @@ -3410,8 +3423,8 @@ static void fail_all_cmds(unsigned long } else if (c->cmd_type == CMD_IOCTL_PEND) complete(c->waiting); #ifdef CONFIG_CISS_SCSI_TAPE - else if (c->cmd_type == CMD_SCSI) - complete_scsi_command(c, 0, 0); + else if (c->cmd_type == CMD_SCSI) + complete_scsi_command(c, 0, 0); #endif } spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index b24fc05..868e0d8 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -60,8 +60,6 @@ struct ctlr_info __u32 board_id; void __iomem *vaddr; unsigned long paddr; - unsigned long io_mem_addr; - unsigned long io_mem_length; CfgTable_struct __iomem *cfgtable; int interrupts_enabled; int major; diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 597c007..afdff32 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -578,7 +578,7 @@ complete_scsi_command( CommandList_struc if (cmd->use_sg) { pci_unmap_sg(ctlr->pdev, - cmd->buffer, cmd->use_sg, + cmd->request_buffer, cmd->use_sg, cmd->sc_data_direction); } else if (cmd->request_bufflen) { @@ -1210,7 +1210,7 @@ cciss_scatter_gather(struct pci_dev *pde struct scsi_cmnd *cmd) { unsigned int use_sg, nsegs=0, len; - struct scatterlist *scatter = (struct scatterlist *) cmd->buffer; + struct scatterlist *scatter = (struct scatterlist *) cmd->request_buffer; __u64 addr64; /* is it just one virtual address? */ @@ -1232,7 +1232,7 @@ cciss_scatter_gather(struct pci_dev *pde } /* else, must be a list of virtual addresses.... */ else if (cmd->use_sg <= MAXSGENTRIES) { /* not too many addrs? */ - use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, + use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, cmd->sc_data_direction); for (nsegs=0; nsegs < use_sg; nsegs++) { diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index b6ea2f0..5eb6fb7 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -392,7 +392,7 @@ static void __devexit cpqarray_remove_on } /* pdev is NULL for eisa */ -static int cpqarray_register_ctlr( int i, struct pci_dev *pdev) +static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev) { request_queue_t *q; int j; @@ -410,8 +410,7 @@ static int cpqarray_register_ctlr( int i } hba[i]->access.set_intr_mask(hba[i], 0); if (request_irq(hba[i]->intr, do_ida_intr, - SA_INTERRUPT|SA_SHIRQ|SA_SAMPLE_RANDOM, - hba[i]->devname, hba[i])) + SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) { printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n", hba[i]->intr, hba[i]->devname); @@ -745,7 +744,7 @@ #endif /* * Find an EISA controller's signature. Set up an hba if we find it. */ -static int cpqarray_eisa_detect(void) +static int __init cpqarray_eisa_detect(void) { int i=0, j; __u32 board_id; @@ -1036,6 +1035,8 @@ static inline void complete_command(cmdl complete_buffers(cmd->rq->bio, ok); + add_disk_randomness(cmd->rq->rq_disk); + DBGPX(printk("Done with %p\n", cmd->rq);); end_that_request_last(cmd->rq, ok ? 1 : -EIO); } diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 9c3b94e..3c74ea7 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -818,7 +818,7 @@ static int loop_set_fd(struct loop_devic lo->lo_device = bdev; lo->lo_flags = lo_flags; lo->lo_backing_file = file; - lo->transfer = NULL; + lo->transfer = transfer_none; lo->ioctl = NULL; lo->lo_sizelimit = 0; lo->old_gfp_mask = mapping_gfp_mask(mapping); diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 8bca490..7f554f2 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -7,39 +7,9 @@ * Copyright 1997-2000 Pavel Machek * Parts copyright 2001 Steven Whitehouse * - * (part of code stolen from loop.c) + * This file is released under GPLv2 or later. * - * 97-3-25 compiled 0-th version, not yet tested it - * (it did not work, BTW) (later that day) HEY! it works! - * (bit later) hmm, not that much... 2:00am next day: - * yes, it works, but it gives something like 50kB/sec - * 97-4-01 complete rewrite to make it possible for many requests at - * once to be processed - * 97-4-11 Making protocol independent of endianity etc. - * 97-9-13 Cosmetic changes - * 98-5-13 Attempt to make 64-bit-clean on 64-bit machines - * 99-1-11 Attempt to make 64-bit-clean on 32-bit machines - * 01-2-27 Fix to store proper blockcount for kernel (calculated using - * BLOCK_SIZE_BITS, not device blocksize) - * 01-3-11 Make nbd work with new Linux block layer code. It now supports - * plugging like all the other block devices. Also added in MSG_MORE to - * reduce number of partial TCP segments sent. - * 01-12-6 Fix deadlock condition by making queue locks independent of - * the transmit lock. - * 02-10-11 Allow hung xmit to be aborted via SIGKILL & various fixes. - * - * 03-06-22 Make nbd work with new linux 2.5 block layer design. This fixes - * memory corruption from module removal and possible memory corruption - * from sending/receiving disk data. - * 03-06-23 Cosmetic changes. - * 03-06-23 Enhance diagnostics support. - * 03-06-24 Remove unneeded blksize_bits field from nbd_device struct. - * - * 03-06-24 Cleanup PARANOIA usage & code. - * 04-02-19 Remove PARANOIA, plus various cleanups (Paul Clements) - * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall - * why not: would need access_ok and friends, would share yet another - * structure with userland + * (part of code stolen from loop.c) */ #include diff --git a/drivers/block/ub.c b/drivers/block/ub.c index c688c25..60e9a94 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -10,17 +10,13 @@ * TODO (sorted by decreasing priority) * -- set readonly flag for CDs, set removable flag for CF readers * -- do inquiry and verify we got a disk and not a tape (for LUN mismatch) - * -- special case some senses, e.g. 3a/0 -> no media present, reduce retries * -- verify the 13 conditions and do bulk resets - * -- kill last_pipe and simply do two-state clearing on both pipes * -- highmem * -- move top_sense and work_bcs into separate allocations (if they survive) * for cache purists and esoteric architectures. * -- Allocate structure for LUN 0 before the first ub_sync_tur, avoid NULL. ? * -- prune comments, they are too volumnous - * -- Exterminate P3 printks * -- Resove XXX's - * -- Redo "benh's retries", perhaps have spin-up code to handle them. V:D=? * -- CLEAR, CLR2STS, CLRRS seem to be ripe for refactoring. */ #include @@ -180,7 +176,6 @@ #define UB_DIR_READ 1 #define UB_DIR_ILLEGAL2 2 #define UB_DIR_WRITE 3 -/* P3 */ #define UB_DIR_CHAR(c) (((c)==UB_DIR_WRITE)? 'w': \ (((c)==UB_DIR_READ)? 'r': 'n')) @@ -669,8 +664,9 @@ static int ub_request_fn_1(struct ub_lun */ n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]); if (n_elem < 0) { + /* Impossible, because blk_rq_map_sg should not hit ENOMEM. */ printk(KERN_INFO "%s: failed request map (%d)\n", - lun->name, n_elem); /* P3 */ + lun->name, n_elem); goto drop; } if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ @@ -824,7 +820,9 @@ static int ub_rw_cmd_retry(struct ub_dev if (urq->current_try >= 3) return -EIO; urq->current_try++; - /* P3 */ printk("%s: dir %c len/act %d/%d " + + /* Remove this if anyone complains of flooding. */ + printk(KERN_DEBUG "%s: dir %c len/act %d/%d " "[sense %x %02x %02x] retry %d\n", sc->name, UB_DIR_CHAR(cmd->dir), cmd->len, cmd->act_len, cmd->key, cmd->asc, cmd->ascq, urq->current_try); @@ -1241,8 +1239,6 @@ static void ub_scsi_urb_compl(struct ub_ * to check. But it's not all right if the device * counts disagree with our counts. */ - /* P3 */ printk("%s: resid %d len %d act %d\n", - sc->name, len, cmd->len, cmd->act_len); goto Bad_End; } @@ -1253,7 +1249,6 @@ static void ub_scsi_urb_compl(struct ub_ ub_state_sense(sc, cmd); return; case US_BULK_STAT_PHASE: - /* P3 */ printk("%s: status PHASE\n", sc->name); goto Bad_End; default: printk(KERN_INFO "%s: unknown CSW status 0x%x\n", @@ -1568,16 +1563,14 @@ static void ub_reset_task(void *arg) } if (atomic_read(&sc->poison)) { - printk(KERN_NOTICE "%s: Not resetting disconnected device\n", - sc->name); /* P3 This floods. Remove soon. XXX */ + ; } else if ((sc->reset & 1) == 0) { ub_sync_reset(sc); msleep(700); /* usb-storage sleeps 6s (!) */ ub_probe_clear_stall(sc, sc->recv_bulk_pipe); ub_probe_clear_stall(sc, sc->send_bulk_pipe); } else if (sc->dev->actconfig->desc.bNumInterfaces != 1) { - printk(KERN_NOTICE "%s: Not resetting multi-interface device\n", - sc->name); /* P3 This floods. Remove soon. XXX */ + ; } else { if ((lkr = usb_lock_device_for_reset(sc->dev, sc->intf)) < 0) { printk(KERN_NOTICE @@ -1651,15 +1644,11 @@ static void ub_revalidate(struct ub_dev static int ub_bd_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct ub_lun *lun; - struct ub_dev *sc; + struct ub_lun *lun = disk->private_data; + struct ub_dev *sc = lun->udev; unsigned long flags; int rc; - if ((lun = disk->private_data) == NULL) - return -ENXIO; - sc = lun->udev; - spin_lock_irqsave(&ub_lock, flags); if (atomic_read(&sc->poison)) { spin_unlock_irqrestore(&ub_lock, flags); @@ -1823,10 +1812,8 @@ static int ub_sync_tur(struct ub_dev *sc rc = ub_submit_scsi(sc, cmd); spin_unlock_irqrestore(sc->lock, flags); - if (rc != 0) { - printk("ub: testing ready: submit error (%d)\n", rc); /* P3 */ + if (rc != 0) goto err_submit; - } wait_for_completion(&compl); @@ -1884,20 +1871,16 @@ static int ub_sync_read_cap(struct ub_de rc = ub_submit_scsi(sc, cmd); spin_unlock_irqrestore(sc->lock, flags); - if (rc != 0) { - printk("ub: reading capacity: submit error (%d)\n", rc); /* P3 */ + if (rc != 0) goto err_submit; - } wait_for_completion(&compl); if (cmd->error != 0) { - printk("ub: reading capacity: error %d\n", cmd->error); /* P3 */ rc = -EIO; goto err_read; } if (cmd->act_len != 8) { - printk("ub: reading capacity: size %d\n", cmd->act_len); /* P3 */ rc = -EIO; goto err_read; } @@ -1911,7 +1894,6 @@ static int ub_sync_read_cap(struct ub_de case 2048: shift = 2; break; case 4096: shift = 3; break; default: - printk("ub: Bad sector size %u\n", bsize); /* P3 */ rc = -EDOM; goto err_inv_bsize; } @@ -2023,17 +2005,8 @@ static int ub_sync_getmaxlun(struct ub_d sc->work_urb.error_count = 0; sc->work_urb.status = 0; - if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { - if (rc == -EPIPE) { - printk("%s: Stall submitting GetMaxLUN, using 1 LUN\n", - sc->name); /* P3 */ - } else { - printk(KERN_NOTICE - "%s: Unable to submit GetMaxLUN (%d)\n", - sc->name, rc); - } + if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) goto err_submit; - } init_timer(&timer); timer.function = ub_probe_timeout; @@ -2046,21 +2019,10 @@ static int ub_sync_getmaxlun(struct ub_d del_timer_sync(&timer); usb_kill_urb(&sc->work_urb); - if ((rc = sc->work_urb.status) < 0) { - if (rc == -EPIPE) { - printk("%s: Stall at GetMaxLUN, using 1 LUN\n", - sc->name); /* P3 */ - } else { - printk(KERN_NOTICE - "%s: Error at GetMaxLUN (%d)\n", - sc->name, rc); - } + if ((rc = sc->work_urb.status) < 0) goto err_io; - } if (sc->work_urb.actual_length != 1) { - printk("%s: GetMaxLUN returned %d bytes\n", sc->name, - sc->work_urb.actual_length); /* P3 */ nluns = 0; } else { if ((nluns = *p) == 55) { @@ -2071,8 +2033,6 @@ static int ub_sync_getmaxlun(struct ub_d if (nluns > UB_MAX_LUNS) nluns = UB_MAX_LUNS; } - printk("%s: GetMaxLUN returned %d, using %d LUNs\n", sc->name, - *p, nluns); /* P3 */ } kfree(p); @@ -2270,7 +2230,7 @@ #endif * has to succeed, so we clear checks with an additional one here. * In any case it's not our business how revaliadation is implemented. */ - for (i = 0; i < 3; i++) { /* Retries for benh's key */ + for (i = 0; i < 3; i++) { /* Retries for the schwag key from KS'04 */ if ((rc = ub_sync_tur(sc, NULL)) <= 0) break; if (rc != 0x6) break; msleep(10); @@ -2318,7 +2278,6 @@ static int ub_probe_lun(struct ub_dev *s goto err_id; lun->udev = sc; - list_add(&lun->link, &sc->luns); snprintf(lun->name, 16, DRV_NAME "%c(%d.%d.%d)", lun->id + 'a', sc->dev->bus->busnum, sc->dev->devnum, lun->num); @@ -2331,7 +2290,6 @@ static int ub_probe_lun(struct ub_dev *s if ((disk = alloc_disk(UB_PARTS_PER_LUN)) == NULL) goto err_diskalloc; - lun->disk = disk; sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a'); sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a'); disk->major = UB_MAJOR; @@ -2353,7 +2311,9 @@ static int ub_probe_lun(struct ub_dev *s blk_queue_max_sectors(q, UB_MAX_SECTORS); blk_queue_hardsect_size(q, lun->capacity.bsize); + lun->disk = disk; q->queuedata = lun; + list_add(&lun->link, &sc->luns); set_capacity(disk, lun->capacity.nsec); if (lun->removable) @@ -2366,7 +2326,6 @@ static int ub_probe_lun(struct ub_dev *s err_blkqinit: put_disk(disk); err_diskalloc: - list_del(&lun->link); ub_id_put(lun->id); err_id: kfree(lun); @@ -2379,7 +2338,6 @@ static void ub_disconnect(struct usb_int struct ub_dev *sc = usb_get_intfdata(intf); struct list_head *p; struct ub_lun *lun; - struct gendisk *disk; unsigned long flags; /* @@ -2435,9 +2393,7 @@ static void ub_disconnect(struct usb_int */ list_for_each (p, &sc->luns) { lun = list_entry(p, struct ub_lun, link); - disk = lun->disk; - if (disk->flags & GENHD_FL_UP) - del_gendisk(disk); + del_gendisk(lun->disk); /* * I wish I could do: * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags); diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index f63e07b..b0df4f5 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -747,7 +747,7 @@ static int viodasd_remove(struct vio_dev * support. */ static struct vio_device_id viodasd_device_table[] __devinitdata = { - { "viodasd", "" }, + { "block", "IBM,iSeries-viodasd" }, { "", "" } }; MODULE_DEVICE_TABLE(vio, viodasd_device_table); diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index a71a240..ed8dca8 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -423,6 +423,9 @@ static int dtl1_hci_send_frame(struct sk nsh.len = skb->len; s = bt_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC); + if (!s) + return -ENOMEM; + skb_reserve(s, NSHL); memcpy(skb_put(s, skb->len), skb->data, skb->len); if (skb->len & 0x0001) diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c index a0b580c..0f6e7aa 100644 --- a/drivers/cdrom/mcdx.c +++ b/drivers/cdrom/mcdx.c @@ -1006,7 +1006,7 @@ #endif /* MODULE STUFF ***********************************************************/ -int __mcdx_init(void) +static int __init __mcdx_init(void) { int i; int drives = 0; diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index c0f817b..af6b3bf 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -731,7 +731,7 @@ static int viocd_remove(struct vio_dev * * support. */ static struct vio_device_id viocd_device_table[] __devinitdata = { - { "viocd", "" }, + { "block", "IBM,iSeries-viocd" }, { "", "" } }; MODULE_DEVICE_TABLE(vio, viocd_device_table); diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 78d928f..3610c57 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -62,6 +62,23 @@ config HW_CONSOLE depends on VT && !S390 && !UML default y +config VT_HW_CONSOLE_BINDING + bool "Support for binding and unbinding console drivers" + depends on HW_CONSOLE + default n + ---help--- + The virtual terminal is the device that interacts with the physical + terminal through console drivers. On these systems, at least one + console driver is loaded. In other configurations, additional console + drivers may be enabled, such as the framebuffer console. If more than + 1 console driver is enabled, setting this to 'y' will allow you to + select the console driver that will serve as the backend for the + virtual terminals. + + See for more + information. For framebuffer console users, please refer to + . + config SERIAL_NONSTANDARD bool "Non-standard serial port support" ---help--- @@ -670,20 +687,7 @@ config NWFLASH If you're not sure, say N. -config HW_RANDOM - tristate "Intel/AMD/VIA HW Random Number Generator support" - depends on (X86 || IA64) && PCI - ---help--- - This driver provides kernel-side support for the Random Number - Generator hardware found on Intel i8xx-based motherboards, - AMD 76x-based motherboards, and Via Nehemiah CPUs. - - Provides a character driver, used to read() entropy data. - - To compile this driver as a module, choose M here: the - module will be called hw_random. - - If unsure, say N. +source "drivers/char/hw_random/Kconfig" config NVRAM tristate "/dev/nvram support" @@ -865,6 +869,7 @@ config SONYPI config TANBAC_TB0219 tristate "TANBAC TB0219 base board support" depends TANBAC_TB022X + select GPIO_VR41XX menu "Ftape, the floppy tape device driver" diff --git a/drivers/char/Makefile b/drivers/char/Makefile index fb919bf..5241055 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -75,7 +75,7 @@ endif obj-$(CONFIG_TOSHIBA) += toshiba.o obj-$(CONFIG_I8K) += i8k.o obj-$(CONFIG_DS1620) += ds1620.o -obj-$(CONFIG_HW_RANDOM) += hw_random.o +obj-$(CONFIG_HW_RANDOM) += hw_random/ obj-$(CONFIG_FTAPE) += ftape/ obj-$(CONFIG_COBALT_LCD) += lcd.o obj-$(CONFIG_PPDEV) += ppdev.o diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 7c88c06..9826a39 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -1,7 +1,6 @@ config AGP - tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU + tristate "/dev/agpgart (AGP Support)" depends on ALPHA || IA64 || PPC || X86 - default y if GART_IOMMU ---help--- AGP (Accelerated Graphics Port) is a bus system mainly used to connect graphics cards to the rest of the system. @@ -56,9 +55,9 @@ config AGP_AMD X on AMD Irongate, 761, and 762 chipsets. config AGP_AMD64 - tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU + tristate "AMD Opteron/Athlon64 on-CPU GART support" if !IOMMU depends on AGP && X86 - default y if GART_IOMMU + default y if IOMMU help This option gives you AGP support for the GLX component of X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c index 2b5838e..b4e00a3 100644 --- a/drivers/char/agp/alpha-agp.c +++ b/drivers/char/agp/alpha-agp.c @@ -46,12 +46,6 @@ struct vm_operations_struct alpha_core_a }; -static int alpha_core_agp_nop(void) -{ - /* just return success */ - return 0; -} - static int alpha_core_agp_fetch_size(void) { return alpha_core_agp_sizes[0].size; @@ -120,6 +114,11 @@ static int alpha_core_agp_remove_memory( return status; } +static int alpha_core_agp_create_free_gatt_table(struct agp_bridge_data *a) +{ + return 0; +} + struct agp_bridge_driver alpha_core_agp_driver = { .owner = THIS_MODULE, .aperture_sizes = alpha_core_agp_sizes, @@ -135,8 +134,8 @@ struct agp_bridge_driver alpha_core_agp_ .tlb_flush = alpha_core_agp_tlbflush, .mask_memory = agp_generic_mask_memory, .cache_flush = global_cache_flush, - .create_gatt_table = alpha_core_agp_nop, - .free_gatt_table = alpha_core_agp_nop, + .create_gatt_table = alpha_core_agp_create_free_gatt_table, + .free_gatt_table = alpha_core_agp_create_free_gatt_table, .insert_memory = alpha_core_agp_insert_memory, .remove_memory = alpha_core_agp_remove_memory, .alloc_by_type = agp_generic_alloc_by_type, diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 1f77665..51d0d56 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -118,7 +118,7 @@ static int amd_create_gatt_pages(int nr_ return retval; } -/* Since we don't need contigious memory we just try +/* Since we don't need contiguous memory we just try * to get the gatt table once */ diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index ac3c33a..f690ee8 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -15,11 +15,9 @@ #include #include #include #include /* PAGE_SIZE */ +#include #include "agp.h" -/* Will need to be increased if AMD64 ever goes >8-way. */ -#define MAX_HAMMER_GARTS 8 - /* PTE bits. */ #define GPTE_VALID 1 #define GPTE_COHERENT 2 @@ -53,28 +51,12 @@ #define ULI_X86_64_BASE_ADDR 0x10 #define ULI_X86_64_HTT_FEA_REG 0x50 #define ULI_X86_64_ENU_SCR_REG 0x54 -static int nr_garts; -static struct pci_dev * hammers[MAX_HAMMER_GARTS]; - static struct resource *aperture_resource; static int __initdata agp_try_unsupported = 1; -#define for_each_nb() for(gart_iterator=0;gart_iteratorgatt_table_real); - int gart_iterator; + int i; /* Configure AGP regs in each x86-64 host bridge. */ - for_each_nb() { + for (i = 0; i < num_k8_northbridges; i++) { agp_bridge->gart_bus_addr = - amd64_configure(hammers[gart_iterator],gatt_bus); + amd64_configure(k8_northbridges[i], gatt_bus); } + k8_flush_garts(); return 0; } @@ -236,12 +216,13 @@ static int amd_8151_configure(void) static void amd64_cleanup(void) { u32 tmp; - int gart_iterator; - for_each_nb() { + int i; + for (i = 0; i < num_k8_northbridges; i++) { + struct pci_dev *dev = k8_northbridges[i]; /* disable gart translation */ - pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp); + pci_read_config_dword (dev, AMD64_GARTAPERTURECTL, &tmp); tmp &= ~AMD64_GARTEN; - pci_write_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, tmp); + pci_write_config_dword (dev, AMD64_GARTAPERTURECTL, tmp); } } @@ -311,7 +292,7 @@ static int __devinit aperture_valid(u64 /* * W*s centric BIOS sometimes only set up the aperture in the AGP * bridge, not the northbridge. On AMD64 this is handled early - * in aperture.c, but when GART_IOMMU is not enabled or we run + * in aperture.c, but when IOMMU is not enabled or we run * on a 32bit kernel this needs to be redone. * Unfortunately it is impossible to fix the aperture here because it's too late * to allocate that much memory. But at least error out cleanly instead of @@ -361,17 +342,15 @@ static __devinit int fix_northbridge(str static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) { - struct pci_dev *loop_dev = NULL; - int i = 0; - - /* cache pci_devs of northbridges. */ - while ((loop_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) - != NULL) { - if (i == MAX_HAMMER_GARTS) { - printk(KERN_ERR PFX "Too many northbridges for AGP\n"); - return -1; - } - if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) { + int i; + + if (cache_k8_northbridges() < 0) + return -ENODEV; + + i = 0; + for (i = 0; i < num_k8_northbridges; i++) { + struct pci_dev *dev = k8_northbridges[i]; + if (fix_northbridge(dev, pdev, cap_ptr) < 0) { printk(KERN_ERR PFX "No usable aperture found.\n"); #ifdef __x86_64__ /* should port this to i386 */ @@ -379,10 +358,8 @@ #ifdef __x86_64__ #endif return -1; } - hammers[i++] = loop_dev; } - nr_garts = i; - return i == 0 ? -1 : 0; + return 0; } /* Handle AMD 8151 quirks */ @@ -450,7 +427,7 @@ static int __devinit uli_agp_init(struct } /* shadow x86-64 registers into ULi registers */ - pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &httfea); + pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea); /* if x86-64 aperture base is beyond 4G, exit here */ if ((httfea & 0x7fff) >> (32 - 25)) @@ -513,7 +490,7 @@ static int __devinit nforce3_agp_init(st pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); /* shadow x86-64 registers into NVIDIA registers */ - pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &apbase); + pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase); /* if x86-64 aperture base is beyond 4G, exit here */ if ( (apbase & 0x7fff) >> (32 - 25) ) { @@ -754,10 +731,6 @@ #endif int __init agp_amd64_init(void) { int err = 0; - static struct pci_device_id amd64nb[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, - { }, - }; if (agp_off) return -EINVAL; @@ -774,7 +747,7 @@ #endif } /* First check that we have at least one AMD64 NB */ - if (!pci_dev_present(amd64nb)) + if (!pci_dev_present(k8_nb_ids)) return -ENODEV; /* Look for any AGP bridge */ @@ -802,7 +775,7 @@ static void __exit agp_amd64_cleanup(voi /* On AMD64 the PCI driver needs to initialize this driver early for the IOMMU, so it has to be called via a backdoor. */ -#ifndef CONFIG_GART_IOMMU +#ifndef CONFIG_IOMMU module_init(agp_amd64_init); module_exit(agp_amd64_cleanup); #endif diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 06fd10b..1605643 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -261,7 +261,7 @@ static int agp_ati_suspend(struct pci_de #endif /* - *Since we don't need contigious memory we just try + *Since we don't need contiguous memory we just try * to get the gatt table once */ diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index 86a966b..b788b0a 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c @@ -177,7 +177,7 @@ static int efficeon_free_gatt_table(stru /* - * Since we don't need contigious memory we just try + * Since we don't need contiguous memory we just try * to get the gatt table once */ diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 4e1891e..a92ab53 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -809,12 +809,10 @@ int agp_generic_create_gatt_table(struct case U32_APER_SIZE: bridge->current_size = A_IDX32(bridge); break; - /* This case will never really happen. */ + /* These cases will never really happen. */ case FIXED_APER_SIZE: case LVL2_APER_SIZE: default: - bridge->current_size = - bridge->current_size; break; } temp = bridge->current_size; diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 8c4c6ef..907fb66 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -497,7 +497,7 @@ zx1_gart_probe (acpi_handle obj, u32 dep info = buffer.pointer; info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0'; match = (strcmp(info->hardware_id.value, "HWP0001") == 0); - ACPI_MEM_FREE(info); + kfree(info); if (match) { status = hp_acpi_csr_space(handle, &sba_hpa, &length); if (ACPI_SUCCESS(status)) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index bddcae5..61ac380 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -736,7 +736,7 @@ static int intel_i915_remove_entries(str static int intel_i915_fetch_size(void) { struct aper_size_info_fixed *values; - u32 temp, offset = 0; + u32 temp, offset; #define I915_256MB_ADDRESS_MASK (1<<27) diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 9846def..1de1b12 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -329,7 +329,7 @@ static int agp_uninorth_suspend(struct p /* turn off AGP on the bridge */ agp = pci_find_capability(pdev, PCI_CAP_ID_AGP); pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd); - bridge->dev_private_data = (void *)cmd; + bridge->dev_private_data = (void *)(long)cmd; if (cmd & PCI_AGP_COMMAND_AGP) { printk("uninorth-agp: disabling AGP on bridge %s\n", pci_name(pdev)); @@ -351,7 +351,7 @@ static int agp_uninorth_resume(struct pc if (bridge == NULL) return -ENODEV; - command = (u32)bridge->dev_private_data; + command = (long)bridge->dev_private_data; bridge->dev_private_data = NULL; if (!(command & PCI_AGP_COMMAND_AGP)) return 0; diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index a370e7a..9275d5e 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c @@ -166,11 +166,7 @@ static int ac_register_board(unsigned lo return boardno + 1; } -#ifdef MODULE - -#define applicom_init init_module - -void cleanup_module(void) +static void __exit applicom_exit(void) { unsigned int i; @@ -188,9 +184,7 @@ void cleanup_module(void) } } -#endif /* MODULE */ - -int __init applicom_init(void) +static int __init applicom_init(void) { int i, numisa = 0; struct pci_dev *dev = NULL; @@ -355,10 +349,9 @@ out: return ret; } +module_init(applicom_init); +module_exit(applicom_exit); -#ifndef MODULE -__initcall(applicom_init); -#endif static ssize_t ac_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { @@ -851,28 +844,3 @@ static int ac_ioctl(struct inode *inode, return 0; } -#ifndef MODULE -static int __init applicom_setup(char *str) -{ - int ints[4]; - - (void) get_options(str, 4, ints); - - if (ints[0] > 2) { - printk(KERN_WARNING "Too many arguments to 'applicom=', expected mem,irq only.\n"); - } - - if (ints[0] < 2) { - printk(KERN_INFO"applicom numargs: %d\n", ints[0]); - return 0; - } - - mem = ints[1]; - irq = ints[2]; - return 1; -} - -__setup("applicom=", applicom_setup); - -#endif /* MODULE */ - diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index cc7acf8..122e7a7 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -2833,9 +2833,8 @@ #endif return 0; } - if (!tty || !info->xmit_buf || !tmp_buf){ - return 0; - } + if (!info->xmit_buf || !tmp_buf) + return 0; CY_LOCK(info, flags); while (1) { @@ -2884,7 +2883,7 @@ #endif if (serial_paranoia_check(info, tty->name, "cy_put_char")) return; - if (!tty || !info->xmit_buf) + if (!info->xmit_buf) return; CY_LOCK(info, flags); diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 9f4b8ce..a94233b 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c @@ -758,7 +758,9 @@ drm_ioctl_desc_t i915_ioctls[] = { [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH}, [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY } + [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, + [DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH }, }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h index 4cb3da5..5aa3e0e 100644 --- a/drivers/char/drm/i915_drm.h +++ b/drivers/char/drm/i915_drm.h @@ -124,6 +124,8 @@ #define DRM_I915_FREE 0x09 #define DRM_I915_INIT_HEAP 0x0a #define DRM_I915_CMDBUFFER 0x0b #define DRM_I915_DESTROY_HEAP 0x0c +#define DRM_I915_SET_VBLANK_PIPE 0x0d +#define DRM_I915_GET_VBLANK_PIPE 0x0e #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -138,6 +140,8 @@ #define DRM_IOCTL_I915_FREE #define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) #define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) +#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) +#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -224,4 +228,13 @@ typedef struct drm_i915_mem_destroy_heap int region; } drm_i915_mem_destroy_heap_t; +/* Allow X server to configure which pipes to monitor for vblank signals + */ +#define DRM_I915_VBLANK_PIPE_A 1 +#define DRM_I915_VBLANK_PIPE_B 2 + +typedef struct drm_i915_vblank_pipe { + int pipe; +} drm_i915_vblank_pipe_t; + #endif /* _I915_DRM_H_ */ diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 7a65666..2d56503 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h @@ -45,9 +45,10 @@ #define DRIVER_DATE "20060119" * 1.2: Add Power Management * 1.3: Add vblank support * 1.4: Fix cmdbuffer path, add heap destroy + * 1.5: Add vblank pipe configuration */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 4 +#define DRIVER_MINOR 5 #define DRIVER_PATCHLEVEL 0 typedef struct _drm_i915_ring_buffer { @@ -96,6 +97,7 @@ typedef struct drm_i915_private { int allow_batchbuffer; struct mem_block *agp_heap; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; + int vblank_pipe; } drm_i915_private_t; extern drm_ioctl_desc_t i915_ioctls[]; @@ -119,6 +121,8 @@ extern irqreturn_t i915_driver_irq_handl extern void i915_driver_irq_preinstall(drm_device_t * dev); extern void i915_driver_irq_postinstall(drm_device_t * dev); extern void i915_driver_irq_uninstall(drm_device_t * dev); +extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS); +extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS); /* i915_mem.c */ extern int i915_mem_alloc(DRM_IOCTL_ARGS); diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index a752afd..cd96cfa 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c @@ -44,7 +44,8 @@ irqreturn_t i915_driver_irq_handler(DRM_ u16 temp; temp = I915_READ16(I915REG_INT_IDENTITY_R); - temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG); + + temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG); DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); @@ -58,7 +59,7 @@ irqreturn_t i915_driver_irq_handler(DRM_ if (temp & USER_INT_FLAG) DRM_WAKEUP(&dev_priv->irq_queue); - if (temp & VSYNC_PIPEA_FLAG) { + if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); @@ -182,6 +183,68 @@ int i915_irq_wait(DRM_IOCTL_ARGS) return i915_wait_irq(dev, irqwait.irq_seq); } +static int i915_enable_interrupt (drm_device_t *dev) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + u16 flag; + + flag = 0; + if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) + flag |= VSYNC_PIPEA_FLAG; + if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) + flag |= VSYNC_PIPEB_FLAG; + if (dev_priv->vblank_pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { + DRM_ERROR("%s called with invalid pipe 0x%x\n", + __FUNCTION__, dev_priv->vblank_pipe); + return DRM_ERR(EINVAL); + } + I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag); + return 0; +} + +/* Set the vblank monitor pipe + */ +int i915_vblank_pipe_set(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_vblank_pipe_t pipe; + + if (!dev_priv) { + DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data, + sizeof(pipe)); + + dev_priv->vblank_pipe = pipe.pipe; + return i915_enable_interrupt (dev); +} + +int i915_vblank_pipe_get(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_vblank_pipe_t pipe; + u16 flag; + + if (!dev_priv) { + DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + return DRM_ERR(EINVAL); + } + + flag = I915_READ(I915REG_INT_ENABLE_R); + pipe.pipe = 0; + if (flag & VSYNC_PIPEA_FLAG) + pipe.pipe |= DRM_I915_VBLANK_PIPE_A; + if (flag & VSYNC_PIPEB_FLAG) + pipe.pipe |= DRM_I915_VBLANK_PIPE_B; + DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe, + sizeof(pipe)); + return 0; +} + /* drm_dma.h hooks */ void i915_driver_irq_preinstall(drm_device_t * dev) @@ -197,7 +260,7 @@ void i915_driver_irq_postinstall(drm_dev { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG); + i915_enable_interrupt(dev); DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); } diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 7f949c9..5ad43ba 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -39,7 +39,7 @@ #define RADEON_FIFO_DEBUG 0 static int radeon_do_cleanup_cp(drm_device_t * dev); /* CP microcode (from ATI) */ -static u32 R200_cp_microcode[][2] = { +static const u32 R200_cp_microcode[][2] = { {0x21007000, 0000000000}, {0x20007000, 0000000000}, {0x000000ab, 0x00000004}, @@ -298,7 +298,7 @@ static u32 R200_cp_microcode[][2] = { {0000000000, 0000000000}, }; -static u32 radeon_cp_microcode[][2] = { +static const u32 radeon_cp_microcode[][2] = { {0x21007000, 0000000000}, {0x20007000, 0000000000}, {0x000000b4, 0x00000004}, @@ -557,7 +557,7 @@ static u32 radeon_cp_microcode[][2] = { {0000000000, 0000000000}, }; -static u32 R300_cp_microcode[][2] = { +static const u32 R300_cp_microcode[][2] = { {0x4200e000, 0000000000}, {0x4000e000, 0000000000}, {0x000000af, 0x00000008}, diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index c8e279e..8d6350d 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h @@ -161,7 +161,8 @@ #define R200_EMIT_PP_TXCTLALL_2 #define R200_EMIT_PP_TXCTLALL_3 91 #define R200_EMIT_PP_TXCTLALL_4 92 #define R200_EMIT_PP_TXCTLALL_5 93 -#define RADEON_MAX_STATE_PACKETS 94 +#define R200_EMIT_VAP_PVS_CNTL 94 +#define RADEON_MAX_STATE_PACKETS 95 /* Commands understood by cmd_buffer ioctl. More can be added but * obviously these can't be removed or changed: @@ -176,6 +177,7 @@ #define RADEON_CMD_SCALARS2 7 /* r20 #define RADEON_CMD_WAIT 8 /* emit hw wait commands -- note: * doesn't make the cpu wait, just * the graphics hardware */ +#define RADEON_CMD_VECLINEAR 9 /* another r200 stopgap */ typedef union { int i; @@ -192,6 +194,9 @@ typedef union { unsigned char cmd_type, offset, stride, count; } vectors; struct { + unsigned char cmd_type, addr_lo, addr_hi, count; + } veclinear; + struct { unsigned char cmd_type, buf_idx, pad0, pad1; } dma; struct { diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 78345ce..e5a256f 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -38,7 +38,7 @@ #define DRIVER_AUTHOR "Gareth Hughes, K #define DRIVER_NAME "radeon" #define DRIVER_DESC "ATI Radeon" -#define DRIVER_DATE "20060225" +#define DRIVER_DATE "20060524" /* Interface history: * @@ -93,9 +93,11 @@ #define DRIVER_DATE "20060225" * 1.22- Add support for texture cache flushes (R300_TX_CNTL) * 1.23- Add new radeon memory map work from benh * 1.24- Add general-purpose packet for manipulating scratch registers (r300) + * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, + * new packet type) */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 24 +#define DRIVER_MINOR 25 #define DRIVER_PATCHLEVEL 0 /* @@ -884,6 +886,8 @@ #define RADEON_PP_CUBIC_OFFSET_T0_0 #define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00 #define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14 +#define RADEON_SE_TCL_STATE_FLUSH 0x2284 + #define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001 #define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000 #define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT 0x00000012 @@ -905,6 +909,8 @@ #define R200_PP_TRI_PERF 0x2cf8 #define R200_PP_AFS_0 0x2f80 #define R200_PP_AFS_1 0x2f00 /* same as txcblend_0 */ +#define R200_VAP_PVS_CNTL_1 0x22D0 + /* Constants */ #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index c5b8f77..5bb2234 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -249,6 +249,7 @@ static __inline__ int radeon_check_and_f case R200_EMIT_PP_TXCTLALL_3: case R200_EMIT_PP_TXCTLALL_4: case R200_EMIT_PP_TXCTLALL_5: + case R200_EMIT_VAP_PVS_CNTL: /* These packets don't contain memory offsets */ break; @@ -626,6 +627,7 @@ static struct { {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"}, {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"}, {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"}, + {R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"}, }; /* ================================================================ @@ -2595,7 +2597,8 @@ static __inline__ int radeon_emit_vector int stride = header.vectors.stride; RING_LOCALS; - BEGIN_RING(3 + sz); + BEGIN_RING(5 + sz); + OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); @@ -2607,6 +2610,32 @@ static __inline__ int radeon_emit_vector return 0; } +static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv, + drm_radeon_cmd_header_t header, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + int sz = header.veclinear.count * 4; + int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8); + RING_LOCALS; + + if (!sz) + return 0; + if (sz * 4 > cmdbuf->bufsz) + return DRM_ERR(EINVAL); + + BEGIN_RING(5 + sz); + OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); + OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); + OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); + OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); + OUT_RING_TABLE(cmdbuf->buf, sz); + ADVANCE_RING(); + + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + static int radeon_emit_packet3(drm_device_t * dev, drm_file_t * filp_priv, drm_radeon_kcmd_buffer_t *cmdbuf) @@ -2865,6 +2894,14 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_AR goto err; } break; + case RADEON_CMD_VECLINEAR: + DRM_DEBUG("RADEON_CMD_VECLINEAR\n"); + if (radeon_emit_veclinear(dev_priv, header, &cmdbuf)) { + DRM_ERROR("radeon_emit_veclinear failed\n"); + goto err; + } + break; + default: DRM_ERROR("bad cmd_type %d at %p\n", header.header.cmd_type, diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 09dc4b0..922174d 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -1212,7 +1212,7 @@ static void rs_put_char(struct tty_struc if (serial_paranoia_check(info, tty->name, "rs_put_char")) return; - if (!tty || !info->xmit_buf) + if (!info->xmit_buf) return; spin_lock_irqsave(&info->lock, flags); @@ -1256,7 +1256,7 @@ static int rs_write(struct tty_struct * if (serial_paranoia_check(info, tty->name, "rs_write")) return 0; - if (!tty || !info->xmit_buf) + if (!info->xmit_buf) return 0; while (1) { diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c index ac62641..d69f2ad 100644 --- a/drivers/char/hangcheck-timer.c +++ b/drivers/char/hangcheck-timer.c @@ -117,12 +117,12 @@ __setup("hcheck_reboot", hangcheck_parse __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks); #endif /* not MODULE */ -#if defined(CONFIG_X86) || defined(CONFIG_S390) +#if defined(CONFIG_X86_64) || defined(CONFIG_S390) # define HAVE_MONOTONIC # define TIMER_FREQ 1000000000ULL #elif defined(CONFIG_IA64) # define TIMER_FREQ ((unsigned long long)local_cpu_data->itc_freq) -#elif defined(CONFIG_PPC64) +#else # define TIMER_FREQ (HZ*loops_per_jiffy) #endif diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index ef140eb..07473cd 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -925,11 +925,8 @@ static acpi_status hpet_resources(struct status = acpi_resource_to_address64(res, &addr); if (ACPI_SUCCESS(status)) { - unsigned long size; - - size = addr.maximum - addr.minimum + 1; hdp->hd_phys_address = addr.minimum; - hdp->hd_address = ioremap(addr.minimum, size); + hdp->hd_address = ioremap(addr.minimum, addr.address_length); if (hpet_is_known(hdp)) { printk(KERN_DEBUG "%s: 0x%lx is busy\n", diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 2b6a56b..a5c6a9d 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -553,7 +553,6 @@ static int hvc_chars_in_buffer(struct tt #define HVC_POLL_READ 0x00000001 #define HVC_POLL_WRITE 0x00000002 -#define HVC_POLL_QUICK 0x00000004 static int hvc_poll(struct hvc_struct *hp) { @@ -568,6 +567,7 @@ static int hvc_poll(struct hvc_struct *h /* Push pending writes */ if (hp->n_outbuf > 0) hvc_push(hp); + /* Reschedule us if still some write pending */ if (hp->n_outbuf > 0) poll_mask |= HVC_POLL_WRITE; @@ -680,7 +680,7 @@ int khvcd(void *unused) poll_mask |= HVC_POLL_READ; if (hvc_kicked) continue; - if (poll_mask & HVC_POLL_QUICK) { + if (poll_mask & HVC_POLL_WRITE) { yield(); continue; } diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c index 83364ea..57106e0 100644 --- a/drivers/char/hvc_rtas.c +++ b/drivers/char/hvc_rtas.c @@ -41,37 +41,28 @@ #include "hvc_console.h" #define hvc_rtas_cookie 0x67781e15 struct hvc_struct *hvc_rtas_dev; -#define RTASCONS_PUT_ATTEMPTS 16 - static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE; static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE; -static int rtascons_put_delay = 100; -module_param_named(put_delay, rtascons_put_delay, int, 0644); -static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, int count) +static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, + int count) { - int done; + int i; - /* if there is more than one character to be displayed, wait a bit */ - for (done = 0; done < count; done++) { - int result; - result = rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[done]); - if (result) + for (i = 0; i < count; i++) { + if (rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[i])) break; } - /* the calling routine expects to receive the number of bytes sent */ - return done; + + return i; } static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count) { - int i; + int i, c; for (i = 0; i < count; i++) { - int c, err; - - err = rtas_call(rtascons_get_char_token, 0, 2, &c); - if (err) + if (rtas_call(rtascons_get_char_token, 0, 2, &c)) break; buf[i] = c; @@ -106,7 +97,9 @@ static int hvc_rtas_init(void) hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops); if (IS_ERR(hp)) return PTR_ERR(hp); + hvc_rtas_dev = hp; + return 0; } module_init(hvc_rtas_init); @@ -114,8 +107,8 @@ module_init(hvc_rtas_init); /* This will tear down the tty portion of the driver */ static void __exit hvc_rtas_exit(void) { - /* Really the fun isn't over until the worker thread breaks down and the - * tty cleans up */ + /* Really the fun isn't over until the worker thread breaks down and + * the tty cleans up */ if (hvc_rtas_dev) hvc_remove(hvc_rtas_dev); } @@ -127,12 +120,14 @@ static int hvc_rtas_console_init(void) rtascons_put_char_token = rtas_token("put-term-char"); if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) return -EIO; + rtascons_get_char_token = rtas_token("get-term-char"); if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) return -EIO; - hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops ); + hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops); add_preferred_console("hvc", 0, NULL); + return 0; } console_initcall(hvc_rtas_console_init); diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index a952218..a0370ed 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -1179,7 +1179,7 @@ static int __init hvsi_init(void) if (tty_register_driver(hvsi_driver)) panic("Couldn't register hvsi console driver\n"); - printk(KERN_INFO "HVSI: registered %i devices\n", hvsi_count); + printk(KERN_DEBUG "HVSI: registered %i devices\n", hvsi_count); return 0; } diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c deleted file mode 100644 index 29dc87e..0000000 --- a/drivers/char/hw_random.c +++ /dev/null @@ -1,698 +0,0 @@ -/* - Added support for the AMD Geode LX RNG - (c) Copyright 2004-2005 Advanced Micro Devices, Inc. - - derived from - - Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) - (c) Copyright 2003 Red Hat Inc - - derived from - - Hardware driver for the AMD 768 Random Number Generator (RNG) - (c) Copyright 2001 Red Hat Inc - - derived from - - Hardware driver for Intel i810 Random Number Generator (RNG) - Copyright 2000,2001 Jeff Garzik - Copyright 2000,2001 Philipp Rumpf - - Please read Documentation/hw_random.txt for details on use. - - ---------------------------------------------------------- - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __i386__ -#include -#include -#endif - -#include -#include - - -/* - * core module and version information - */ -#define RNG_VERSION "1.0.0" -#define RNG_MODULE_NAME "hw_random" -#define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION -#define PFX RNG_MODULE_NAME ": " - - -/* - * debugging macros - */ - -/* pr_debug() collapses to a no-op if DEBUG is not defined */ -#define DPRINTK(fmt, args...) pr_debug(PFX "%s: " fmt, __FUNCTION__ , ## args) - - -#undef RNG_NDEBUG /* define to enable lightweight runtime checks */ -#ifdef RNG_NDEBUG -#define assert(expr) \ - if(!(expr)) { \ - printk(KERN_DEBUG PFX "Assertion failed! %s,%s,%s," \ - "line=%d\n", #expr, __FILE__, __FUNCTION__, __LINE__); \ - } -#else -#define assert(expr) -#endif - -#define RNG_MISCDEV_MINOR 183 /* official */ - -static int rng_dev_open (struct inode *inode, struct file *filp); -static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, - loff_t * offp); - -static int __init intel_init (struct pci_dev *dev); -static void intel_cleanup(void); -static unsigned int intel_data_present (void); -static u32 intel_data_read (void); - -static int __init amd_init (struct pci_dev *dev); -static void amd_cleanup(void); -static unsigned int amd_data_present (void); -static u32 amd_data_read (void); - -#ifdef __i386__ -static int __init via_init(struct pci_dev *dev); -static void via_cleanup(void); -static unsigned int via_data_present (void); -static u32 via_data_read (void); -#endif - -static int __init geode_init(struct pci_dev *dev); -static void geode_cleanup(void); -static unsigned int geode_data_present (void); -static u32 geode_data_read (void); - -struct rng_operations { - int (*init) (struct pci_dev *dev); - void (*cleanup) (void); - unsigned int (*data_present) (void); - u32 (*data_read) (void); - unsigned int n_bytes; /* number of bytes per ->data_read */ -}; -static struct rng_operations *rng_ops; - -static struct file_operations rng_chrdev_ops = { - .owner = THIS_MODULE, - .open = rng_dev_open, - .read = rng_dev_read, -}; - - -static struct miscdevice rng_miscdev = { - RNG_MISCDEV_MINOR, - RNG_MODULE_NAME, - &rng_chrdev_ops, -}; - -enum { - rng_hw_none, - rng_hw_intel, - rng_hw_amd, -#ifdef __i386__ - rng_hw_via, -#endif - rng_hw_geode, -}; - -static struct rng_operations rng_vendor_ops[] = { - /* rng_hw_none */ - { }, - - /* rng_hw_intel */ - { intel_init, intel_cleanup, intel_data_present, - intel_data_read, 1 }, - - /* rng_hw_amd */ - { amd_init, amd_cleanup, amd_data_present, amd_data_read, 4 }, - -#ifdef __i386__ - /* rng_hw_via */ - { via_init, via_cleanup, via_data_present, via_data_read, 1 }, -#endif - - /* rng_hw_geode */ - { geode_init, geode_cleanup, geode_data_present, geode_data_read, 4 } -}; - -/* - * Data for PCI driver interface - * - * This data only exists for exporting the supported - * PCI ids via MODULE_DEVICE_TABLE. We do not actually - * register a pci_driver, because someone else might one day - * want to register another driver on the same PCI id. - */ -static struct pci_device_id rng_pci_tbl[] = { - { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd }, - { 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd }, - - { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, - { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, - { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, - { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, - { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, - { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, - - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_geode }, - - { 0, }, /* terminate list */ -}; -MODULE_DEVICE_TABLE (pci, rng_pci_tbl); - - -/*********************************************************************** - * - * Intel RNG operations - * - */ - -/* - * RNG registers (offsets from rng_mem) - */ -#define INTEL_RNG_HW_STATUS 0 -#define INTEL_RNG_PRESENT 0x40 -#define INTEL_RNG_ENABLED 0x01 -#define INTEL_RNG_STATUS 1 -#define INTEL_RNG_DATA_PRESENT 0x01 -#define INTEL_RNG_DATA 2 - -/* - * Magic address at which Intel PCI bridges locate the RNG - */ -#define INTEL_RNG_ADDR 0xFFBC015F -#define INTEL_RNG_ADDR_LEN 3 - -/* token to our ioremap'd RNG register area */ -static void __iomem *rng_mem; - -static inline u8 intel_hwstatus (void) -{ - assert (rng_mem != NULL); - return readb (rng_mem + INTEL_RNG_HW_STATUS); -} - -static inline u8 intel_hwstatus_set (u8 hw_status) -{ - assert (rng_mem != NULL); - writeb (hw_status, rng_mem + INTEL_RNG_HW_STATUS); - return intel_hwstatus (); -} - -static unsigned int intel_data_present(void) -{ - assert (rng_mem != NULL); - - return (readb (rng_mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT) ? - 1 : 0; -} - -static u32 intel_data_read(void) -{ - assert (rng_mem != NULL); - - return readb (rng_mem + INTEL_RNG_DATA); -} - -static int __init intel_init (struct pci_dev *dev) -{ - int rc; - u8 hw_status; - - DPRINTK ("ENTER\n"); - - rng_mem = ioremap (INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); - if (rng_mem == NULL) { - printk (KERN_ERR PFX "cannot ioremap RNG Memory\n"); - rc = -EBUSY; - goto err_out; - } - - /* Check for Intel 82802 */ - hw_status = intel_hwstatus (); - if ((hw_status & INTEL_RNG_PRESENT) == 0) { - printk (KERN_ERR PFX "RNG not detected\n"); - rc = -ENODEV; - goto err_out_free_map; - } - - /* turn RNG h/w on, if it's off */ - if ((hw_status & INTEL_RNG_ENABLED) == 0) - hw_status = intel_hwstatus_set (hw_status | INTEL_RNG_ENABLED); - if ((hw_status & INTEL_RNG_ENABLED) == 0) { - printk (KERN_ERR PFX "cannot enable RNG, aborting\n"); - rc = -EIO; - goto err_out_free_map; - } - - DPRINTK ("EXIT, returning 0\n"); - return 0; - -err_out_free_map: - iounmap (rng_mem); - rng_mem = NULL; -err_out: - DPRINTK ("EXIT, returning %d\n", rc); - return rc; -} - -static void intel_cleanup(void) -{ - u8 hw_status; - - hw_status = intel_hwstatus (); - if (hw_status & INTEL_RNG_ENABLED) - intel_hwstatus_set (hw_status & ~INTEL_RNG_ENABLED); - else - printk(KERN_WARNING PFX "unusual: RNG already disabled\n"); - iounmap(rng_mem); - rng_mem = NULL; -} - -/*********************************************************************** - * - * AMD RNG operations - * - */ - -static u32 pmbase; /* PMxx I/O base */ -static struct pci_dev *amd_dev; - -static unsigned int amd_data_present (void) -{ - return inl(pmbase + 0xF4) & 1; -} - - -static u32 amd_data_read (void) -{ - return inl(pmbase + 0xF0); -} - -static int __init amd_init (struct pci_dev *dev) -{ - int rc; - u8 rnen; - - DPRINTK ("ENTER\n"); - - pci_read_config_dword(dev, 0x58, &pmbase); - - pmbase &= 0x0000FF00; - - if (pmbase == 0) - { - printk (KERN_ERR PFX "power management base not set\n"); - rc = -EIO; - goto err_out; - } - - pci_read_config_byte(dev, 0x40, &rnen); - rnen |= (1 << 7); /* RNG on */ - pci_write_config_byte(dev, 0x40, rnen); - - pci_read_config_byte(dev, 0x41, &rnen); - rnen |= (1 << 7); /* PMIO enable */ - pci_write_config_byte(dev, 0x41, rnen); - - pr_info( PFX "AMD768 system management I/O registers at 0x%X.\n", - pmbase); - - amd_dev = dev; - - DPRINTK ("EXIT, returning 0\n"); - return 0; - -err_out: - DPRINTK ("EXIT, returning %d\n", rc); - return rc; -} - -static void amd_cleanup(void) -{ - u8 rnen; - - pci_read_config_byte(amd_dev, 0x40, &rnen); - rnen &= ~(1 << 7); /* RNG off */ - pci_write_config_byte(amd_dev, 0x40, rnen); - - /* FIXME: twiddle pmio, also? */ -} - -#ifdef __i386__ -/*********************************************************************** - * - * VIA RNG operations - * - */ - -enum { - VIA_STRFILT_CNT_SHIFT = 16, - VIA_STRFILT_FAIL = (1 << 15), - VIA_STRFILT_ENABLE = (1 << 14), - VIA_RAWBITS_ENABLE = (1 << 13), - VIA_RNG_ENABLE = (1 << 6), - VIA_XSTORE_CNT_MASK = 0x0F, - - VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */ - VIA_RNG_CHUNK_4 = 0x01, /* 32 rand bits, 32 stored bits */ - VIA_RNG_CHUNK_4_MASK = 0xFFFFFFFF, - VIA_RNG_CHUNK_2 = 0x02, /* 16 rand bits, 32 stored bits */ - VIA_RNG_CHUNK_2_MASK = 0xFFFF, - VIA_RNG_CHUNK_1 = 0x03, /* 8 rand bits, 32 stored bits */ - VIA_RNG_CHUNK_1_MASK = 0xFF, -}; - -static u32 via_rng_datum; - -/* - * Investigate using the 'rep' prefix to obtain 32 bits of random data - * in one insn. The upside is potentially better performance. The - * downside is that the instruction becomes no longer atomic. Due to - * this, just like familiar issues with /dev/random itself, the worst - * case of a 'rep xstore' could potentially pause a cpu for an - * unreasonably long time. In practice, this condition would likely - * only occur when the hardware is failing. (or so we hope :)) - * - * Another possible performance boost may come from simply buffering - * until we have 4 bytes, thus returning a u32 at a time, - * instead of the current u8-at-a-time. - */ - -static inline u32 xstore(u32 *addr, u32 edx_in) -{ - u32 eax_out; - - asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */" - :"=m"(*addr), "=a"(eax_out) - :"D"(addr), "d"(edx_in)); - - return eax_out; -} - -static unsigned int via_data_present(void) -{ - u32 bytes_out; - - /* We choose the recommended 1-byte-per-instruction RNG rate, - * for greater randomness at the expense of speed. Larger - * values 2, 4, or 8 bytes-per-instruction yield greater - * speed at lesser randomness. - * - * If you change this to another VIA_CHUNK_n, you must also - * change the ->n_bytes values in rng_vendor_ops[] tables. - * VIA_CHUNK_8 requires further code changes. - * - * A copy of MSR_VIA_RNG is placed in eax_out when xstore - * completes. - */ - via_rng_datum = 0; /* paranoia, not really necessary */ - bytes_out = xstore(&via_rng_datum, VIA_RNG_CHUNK_1) & VIA_XSTORE_CNT_MASK; - if (bytes_out == 0) - return 0; - - return 1; -} - -static u32 via_data_read(void) -{ - return via_rng_datum; -} - -static int __init via_init(struct pci_dev *dev) -{ - u32 lo, hi, old_lo; - - /* Control the RNG via MSR. Tread lightly and pay very close - * close attention to values written, as the reserved fields - * are documented to be "undefined and unpredictable"; but it - * does not say to write them as zero, so I make a guess that - * we restore the values we find in the register. - */ - rdmsr(MSR_VIA_RNG, lo, hi); - - old_lo = lo; - lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT); - lo &= ~VIA_XSTORE_CNT_MASK; - lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE); - lo |= VIA_RNG_ENABLE; - - if (lo != old_lo) - wrmsr(MSR_VIA_RNG, lo, hi); - - /* perhaps-unnecessary sanity check; remove after testing if - unneeded */ - rdmsr(MSR_VIA_RNG, lo, hi); - if ((lo & VIA_RNG_ENABLE) == 0) { - printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n"); - return -ENODEV; - } - - return 0; -} - -static void via_cleanup(void) -{ - /* do nothing */ -} -#endif - -/*********************************************************************** - * - * AMD Geode RNG operations - * - */ - -static void __iomem *geode_rng_base = NULL; - -#define GEODE_RNG_DATA_REG 0x50 -#define GEODE_RNG_STATUS_REG 0x54 - -static u32 geode_data_read(void) -{ - u32 val; - - assert(geode_rng_base != NULL); - val = readl(geode_rng_base + GEODE_RNG_DATA_REG); - return val; -} - -static unsigned int geode_data_present(void) -{ - u32 val; - - assert(geode_rng_base != NULL); - val = readl(geode_rng_base + GEODE_RNG_STATUS_REG); - return val; -} - -static void geode_cleanup(void) -{ - iounmap(geode_rng_base); - geode_rng_base = NULL; -} - -static int geode_init(struct pci_dev *dev) -{ - unsigned long rng_base = pci_resource_start(dev, 0); - - if (rng_base == 0) - return 1; - - geode_rng_base = ioremap(rng_base, 0x58); - - if (geode_rng_base == NULL) { - printk(KERN_ERR PFX "Cannot ioremap RNG memory\n"); - return -EBUSY; - } - - return 0; -} - -/*********************************************************************** - * - * /dev/hwrandom character device handling (major 10, minor 183) - * - */ - -static int rng_dev_open (struct inode *inode, struct file *filp) -{ - /* enforce read-only access to this chrdev */ - if ((filp->f_mode & FMODE_READ) == 0) - return -EINVAL; - if (filp->f_mode & FMODE_WRITE) - return -EINVAL; - - return 0; -} - - -static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, - loff_t * offp) -{ - static DEFINE_SPINLOCK(rng_lock); - unsigned int have_data; - u32 data = 0; - ssize_t ret = 0; - - while (size) { - spin_lock(&rng_lock); - - have_data = 0; - if (rng_ops->data_present()) { - data = rng_ops->data_read(); - have_data = rng_ops->n_bytes; - } - - spin_unlock (&rng_lock); - - while (have_data && size) { - if (put_user((u8)data, buf++)) { - ret = ret ? : -EFAULT; - break; - } - size--; - ret++; - have_data--; - data>>=8; - } - - if (filp->f_flags & O_NONBLOCK) - return ret ? : -EAGAIN; - - if(need_resched()) - schedule_timeout_interruptible(1); - else - udelay(200); /* FIXME: We could poll for 250uS ?? */ - - if (signal_pending (current)) - return ret ? : -ERESTARTSYS; - } - return ret; -} - - - -/* - * rng_init_one - look for and attempt to init a single RNG - */ -static int __init rng_init_one (struct pci_dev *dev) -{ - int rc; - - DPRINTK ("ENTER\n"); - - assert(rng_ops != NULL); - - rc = rng_ops->init(dev); - if (rc) - goto err_out; - - rc = misc_register (&rng_miscdev); - if (rc) { - printk (KERN_ERR PFX "misc device register failed\n"); - goto err_out_cleanup_hw; - } - - DPRINTK ("EXIT, returning 0\n"); - return 0; - -err_out_cleanup_hw: - rng_ops->cleanup(); -err_out: - DPRINTK ("EXIT, returning %d\n", rc); - return rc; -} - - - -MODULE_AUTHOR("The Linux Kernel team"); -MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver"); -MODULE_LICENSE("GPL"); - - -/* - * rng_init - initialize RNG module - */ -static int __init rng_init (void) -{ - int rc; - struct pci_dev *pdev = NULL; - const struct pci_device_id *ent; - - DPRINTK ("ENTER\n"); - - /* Probe for Intel, AMD, Geode RNGs */ - for_each_pci_dev(pdev) { - ent = pci_match_id(rng_pci_tbl, pdev); - if (ent) { - rng_ops = &rng_vendor_ops[ent->driver_data]; - goto match; - } - } - -#ifdef __i386__ - /* Probe for VIA RNG */ - if (cpu_has_xstore) { - rng_ops = &rng_vendor_ops[rng_hw_via]; - pdev = NULL; - goto match; - } -#endif - - DPRINTK ("EXIT, returning -ENODEV\n"); - return -ENODEV; - -match: - rc = rng_init_one (pdev); - if (rc) - return rc; - - pr_info( RNG_DRIVER_NAME " loaded\n"); - - DPRINTK ("EXIT, returning 0\n"); - return 0; -} - - -/* - * rng_init - shutdown RNG module - */ -static void __exit rng_cleanup (void) -{ - DPRINTK ("ENTER\n"); - - misc_deregister (&rng_miscdev); - - if (rng_ops->cleanup) - rng_ops->cleanup(); - - DPRINTK ("EXIT\n"); -} - - -module_init (rng_init); -module_exit (rng_cleanup); diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig new file mode 100644 index 0000000..9f7635f --- /dev/null +++ b/drivers/char/hw_random/Kconfig @@ -0,0 +1,90 @@ +# +# Hardware Random Number Generator (RNG) configuration +# + +config HW_RANDOM + bool "Hardware Random Number Generator Core support" + default y + ---help--- + Hardware Random Number Generator Core infrastructure. + + If unsure, say Y. + +config HW_RANDOM_INTEL + tristate "Intel HW Random Number Generator support" + depends on HW_RANDOM && (X86 || IA64) && PCI + default y + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on Intel i8xx-based motherboards. + + To compile this driver as a module, choose M here: the + module will be called intel-rng. + + If unsure, say Y. + +config HW_RANDOM_AMD + tristate "AMD HW Random Number Generator support" + depends on HW_RANDOM && X86 && PCI + default y + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on AMD 76x-based motherboards. + + To compile this driver as a module, choose M here: the + module will be called amd-rng. + + If unsure, say Y. + +config HW_RANDOM_GEODE + tristate "AMD Geode HW Random Number Generator support" + depends on HW_RANDOM && X86 && PCI + default y + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on the AMD Geode LX. + + To compile this driver as a module, choose M here: the + module will be called geode-rng. + + If unsure, say Y. + +config HW_RANDOM_VIA + tristate "VIA HW Random Number Generator support" + depends on HW_RANDOM && X86_32 + default y + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on VIA based motherboards. + + To compile this driver as a module, choose M here: the + module will be called via-rng. + + If unsure, say Y. + +config HW_RANDOM_IXP4XX + tristate "Intel IXP4xx NPU HW Random Number Generator support" + depends on HW_RANDOM && ARCH_IXP4XX + default y + ---help--- + This driver provides kernel-side support for the Random + Number Generator hardware found on the Intel IXP4xx NPU. + + To compile this driver as a module, choose M here: the + module will be called ixp4xx-rng. + + If unsure, say Y. + +config HW_RANDOM_OMAP + tristate "OMAP Random Number Generator support" + depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP24XX) + default y + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on OMAP16xx and OMAP24xx multimedia + processors. + + To compile this driver as a module, choose M here: the + module will be called omap-rng. + + If unsure, say Y. diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile new file mode 100644 index 0000000..e263ae9 --- /dev/null +++ b/drivers/char/hw_random/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for HW Random Number Generator (RNG) device drivers. +# + +obj-$(CONFIG_HW_RANDOM) += core.o +obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o +obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o +obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o +obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o +obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o +obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c new file mode 100644 index 0000000..71e4e0f --- /dev/null +++ b/drivers/char/hw_random/amd-rng.c @@ -0,0 +1,152 @@ +/* + * RNG driver for AMD RNGs + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * with the majority of the code coming from: + * + * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + * (c) Copyright 2003 Red Hat Inc + * + * derived from + * + * Hardware driver for the AMD 768 Random Number Generator (RNG) + * (c) Copyright 2001 Red Hat Inc + * + * derived from + * + * Hardware driver for Intel i810 Random Number Generator (RNG) + * Copyright 2000,2001 Jeff Garzik + * Copyright 2000,2001 Philipp Rumpf + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include + + +#define PFX KBUILD_MODNAME ": " + + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static const struct pci_device_id pci_tbl[] = { + { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, pci_tbl); + +static struct pci_dev *amd_pdev; + + +static int amd_rng_data_present(struct hwrng *rng) +{ + u32 pmbase = (u32)rng->priv; + + return !!(inl(pmbase + 0xF4) & 1); +} + +static int amd_rng_data_read(struct hwrng *rng, u32 *data) +{ + u32 pmbase = (u32)rng->priv; + + *data = inl(pmbase + 0xF0); + + return 4; +} + +static int amd_rng_init(struct hwrng *rng) +{ + u8 rnen; + + pci_read_config_byte(amd_pdev, 0x40, &rnen); + rnen |= (1 << 7); /* RNG on */ + pci_write_config_byte(amd_pdev, 0x40, rnen); + + pci_read_config_byte(amd_pdev, 0x41, &rnen); + rnen |= (1 << 7); /* PMIO enable */ + pci_write_config_byte(amd_pdev, 0x41, rnen); + + return 0; +} + +static void amd_rng_cleanup(struct hwrng *rng) +{ + u8 rnen; + + pci_read_config_byte(amd_pdev, 0x40, &rnen); + rnen &= ~(1 << 7); /* RNG off */ + pci_write_config_byte(amd_pdev, 0x40, rnen); +} + + +static struct hwrng amd_rng = { + .name = "amd", + .init = amd_rng_init, + .cleanup = amd_rng_cleanup, + .data_present = amd_rng_data_present, + .data_read = amd_rng_data_read, +}; + + +static int __init mod_init(void) +{ + int err = -ENODEV; + struct pci_dev *pdev = NULL; + const struct pci_device_id *ent; + u32 pmbase; + + for_each_pci_dev(pdev) { + ent = pci_match_id(pci_tbl, pdev); + if (ent) + goto found; + } + /* Device not found. */ + goto out; + +found: + err = pci_read_config_dword(pdev, 0x58, &pmbase); + if (err) + goto out; + err = -EIO; + pmbase &= 0x0000FF00; + if (pmbase == 0) + goto out; + amd_rng.priv = (unsigned long)pmbase; + amd_pdev = pdev; + + printk(KERN_INFO "AMD768 RNG detected\n"); + err = hwrng_register(&amd_rng); + if (err) { + printk(KERN_ERR PFX "RNG registering failed (%d)\n", + err); + goto out; + } +out: + return err; +} + +static void __exit mod_exit(void) +{ + hwrng_unregister(&amd_rng); +} + +subsys_initcall(mod_init); +module_exit(mod_exit); + +MODULE_AUTHOR("The Linux Kernel team"); +MODULE_DESCRIPTION("H/W RNG driver for AMD chipsets"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c new file mode 100644 index 0000000..88b0266 --- /dev/null +++ b/drivers/char/hw_random/core.c @@ -0,0 +1,354 @@ +/* + Added support for the AMD Geode LX RNG + (c) Copyright 2004-2005 Advanced Micro Devices, Inc. + + derived from + + Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + (c) Copyright 2003 Red Hat Inc + + derived from + + Hardware driver for the AMD 768 Random Number Generator (RNG) + (c) Copyright 2001 Red Hat Inc + + derived from + + Hardware driver for Intel i810 Random Number Generator (RNG) + Copyright 2000,2001 Jeff Garzik + Copyright 2000,2001 Philipp Rumpf + + Added generic RNG API + Copyright 2006 Michael Buesch + Copyright 2005 (c) MontaVista Software, Inc. + + Please read Documentation/hw_random.txt for details on use. + + ---------------------------------------------------------- + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define RNG_MODULE_NAME "hw_random" +#define PFX RNG_MODULE_NAME ": " +#define RNG_MISCDEV_MINOR 183 /* official */ + + +static struct hwrng *current_rng; +static LIST_HEAD(rng_list); +static DEFINE_MUTEX(rng_mutex); + + +static inline int hwrng_init(struct hwrng *rng) +{ + if (!rng->init) + return 0; + return rng->init(rng); +} + +static inline void hwrng_cleanup(struct hwrng *rng) +{ + if (rng && rng->cleanup) + rng->cleanup(rng); +} + +static inline int hwrng_data_present(struct hwrng *rng) +{ + if (!rng->data_present) + return 1; + return rng->data_present(rng); +} + +static inline int hwrng_data_read(struct hwrng *rng, u32 *data) +{ + return rng->data_read(rng, data); +} + + +static int rng_dev_open(struct inode *inode, struct file *filp) +{ + /* enforce read-only access to this chrdev */ + if ((filp->f_mode & FMODE_READ) == 0) + return -EINVAL; + if (filp->f_mode & FMODE_WRITE) + return -EINVAL; + return 0; +} + +static ssize_t rng_dev_read(struct file *filp, char __user *buf, + size_t size, loff_t *offp) +{ + u32 data; + ssize_t ret = 0; + int i, err = 0; + int data_present; + int bytes_read; + + while (size) { + err = -ERESTARTSYS; + if (mutex_lock_interruptible(&rng_mutex)) + goto out; + if (!current_rng) { + mutex_unlock(&rng_mutex); + err = -ENODEV; + goto out; + } + if (filp->f_flags & O_NONBLOCK) { + data_present = hwrng_data_present(current_rng); + } else { + /* Some RNG require some time between data_reads to gather + * new entropy. Poll it. + */ + for (i = 0; i < 20; i++) { + data_present = hwrng_data_present(current_rng); + if (data_present) + break; + udelay(10); + } + } + bytes_read = 0; + if (data_present) + bytes_read = hwrng_data_read(current_rng, &data); + mutex_unlock(&rng_mutex); + + err = -EAGAIN; + if (!bytes_read && (filp->f_flags & O_NONBLOCK)) + goto out; + + err = -EFAULT; + while (bytes_read && size) { + if (put_user((u8)data, buf++)) + goto out; + size--; + ret++; + bytes_read--; + data >>= 8; + } + + if (need_resched()) + schedule_timeout_interruptible(1); + err = -ERESTARTSYS; + if (signal_pending(current)) + goto out; + } +out: + return ret ? : err; +} + + +static struct file_operations rng_chrdev_ops = { + .owner = THIS_MODULE, + .open = rng_dev_open, + .read = rng_dev_read, +}; + +static struct miscdevice rng_miscdev = { + .minor = RNG_MISCDEV_MINOR, + .name = RNG_MODULE_NAME, + .fops = &rng_chrdev_ops, +}; + + +static ssize_t hwrng_attr_current_store(struct class_device *class, + const char *buf, size_t len) +{ + int err; + struct hwrng *rng; + + err = mutex_lock_interruptible(&rng_mutex); + if (err) + return -ERESTARTSYS; + err = -ENODEV; + list_for_each_entry(rng, &rng_list, list) { + if (strcmp(rng->name, buf) == 0) { + if (rng == current_rng) { + err = 0; + break; + } + err = hwrng_init(rng); + if (err) + break; + hwrng_cleanup(current_rng); + current_rng = rng; + err = 0; + break; + } + } + mutex_unlock(&rng_mutex); + + return err ? : len; +} + +static ssize_t hwrng_attr_current_show(struct class_device *class, + char *buf) +{ + int err; + ssize_t ret; + const char *name = "none"; + + err = mutex_lock_interruptible(&rng_mutex); + if (err) + return -ERESTARTSYS; + if (current_rng) + name = current_rng->name; + ret = snprintf(buf, PAGE_SIZE, "%s\n", name); + mutex_unlock(&rng_mutex); + + return ret; +} + +static ssize_t hwrng_attr_available_show(struct class_device *class, + char *buf) +{ + int err; + ssize_t ret = 0; + struct hwrng *rng; + + err = mutex_lock_interruptible(&rng_mutex); + if (err) + return -ERESTARTSYS; + buf[0] = '\0'; + list_for_each_entry(rng, &rng_list, list) { + strncat(buf, rng->name, PAGE_SIZE - ret - 1); + ret += strlen(rng->name); + strncat(buf, " ", PAGE_SIZE - ret - 1); + ret++; + } + strncat(buf, "\n", PAGE_SIZE - ret - 1); + ret++; + mutex_unlock(&rng_mutex); + + return ret; +} + +static CLASS_DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR, + hwrng_attr_current_show, + hwrng_attr_current_store); +static CLASS_DEVICE_ATTR(rng_available, S_IRUGO, + hwrng_attr_available_show, + NULL); + + +static void unregister_miscdev(void) +{ + class_device_remove_file(rng_miscdev.class, + &class_device_attr_rng_available); + class_device_remove_file(rng_miscdev.class, + &class_device_attr_rng_current); + misc_deregister(&rng_miscdev); +} + +static int register_miscdev(void) +{ + int err; + + err = misc_register(&rng_miscdev); + if (err) + goto out; + err = class_device_create_file(rng_miscdev.class, + &class_device_attr_rng_current); + if (err) + goto err_misc_dereg; + err = class_device_create_file(rng_miscdev.class, + &class_device_attr_rng_available); + if (err) + goto err_remove_current; +out: + return err; + +err_remove_current: + class_device_remove_file(rng_miscdev.class, + &class_device_attr_rng_current); +err_misc_dereg: + misc_deregister(&rng_miscdev); + goto out; +} + +int hwrng_register(struct hwrng *rng) +{ + int must_register_misc; + int err = -EINVAL; + struct hwrng *old_rng, *tmp; + + if (rng->name == NULL || + rng->data_read == NULL) + goto out; + + mutex_lock(&rng_mutex); + + /* Must not register two RNGs with the same name. */ + err = -EEXIST; + list_for_each_entry(tmp, &rng_list, list) { + if (strcmp(tmp->name, rng->name) == 0) + goto out_unlock; + } + + must_register_misc = (current_rng == NULL); + old_rng = current_rng; + if (!old_rng) { + err = hwrng_init(rng); + if (err) + goto out_unlock; + current_rng = rng; + } + err = 0; + if (must_register_misc) { + err = register_miscdev(); + if (err) { + if (!old_rng) { + hwrng_cleanup(rng); + current_rng = NULL; + } + goto out_unlock; + } + } + INIT_LIST_HEAD(&rng->list); + list_add_tail(&rng->list, &rng_list); +out_unlock: + mutex_unlock(&rng_mutex); +out: + return err; +} +EXPORT_SYMBOL_GPL(hwrng_register); + +void hwrng_unregister(struct hwrng *rng) +{ + int err; + + mutex_lock(&rng_mutex); + + list_del(&rng->list); + if (current_rng == rng) { + hwrng_cleanup(rng); + if (list_empty(&rng_list)) { + current_rng = NULL; + } else { + current_rng = list_entry(rng_list.prev, struct hwrng, list); + err = hwrng_init(current_rng); + if (err) + current_rng = NULL; + } + } + if (list_empty(&rng_list)) + unregister_miscdev(); + + mutex_unlock(&rng_mutex); +} +EXPORT_SYMBOL_GPL(hwrng_unregister); + + +MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c new file mode 100644 index 0000000..be61f22 --- /dev/null +++ b/drivers/char/hw_random/geode-rng.c @@ -0,0 +1,128 @@ +/* + * RNG driver for AMD Geode RNGs + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * with the majority of the code coming from: + * + * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + * (c) Copyright 2003 Red Hat Inc + * + * derived from + * + * Hardware driver for the AMD 768 Random Number Generator (RNG) + * (c) Copyright 2001 Red Hat Inc + * + * derived from + * + * Hardware driver for Intel i810 Random Number Generator (RNG) + * Copyright 2000,2001 Jeff Garzik + * Copyright 2000,2001 Philipp Rumpf + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include + + +#define PFX KBUILD_MODNAME ": " + +#define GEODE_RNG_DATA_REG 0x50 +#define GEODE_RNG_STATUS_REG 0x54 + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static const struct pci_device_id pci_tbl[] = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, pci_tbl); + + +static int geode_rng_data_read(struct hwrng *rng, u32 *data) +{ + void __iomem *mem = (void __iomem *)rng->priv; + + *data = readl(mem + GEODE_RNG_DATA_REG); + + return 4; +} + +static int geode_rng_data_present(struct hwrng *rng) +{ + void __iomem *mem = (void __iomem *)rng->priv; + + return !!(readl(mem + GEODE_RNG_STATUS_REG)); +} + + +static struct hwrng geode_rng = { + .name = "geode", + .data_present = geode_rng_data_present, + .data_read = geode_rng_data_read, +}; + + +static int __init mod_init(void) +{ + int err = -ENODEV; + struct pci_dev *pdev = NULL; + const struct pci_device_id *ent; + void __iomem *mem; + unsigned long rng_base; + + for_each_pci_dev(pdev) { + ent = pci_match_id(pci_tbl, pdev); + if (ent) + goto found; + } + /* Device not found. */ + goto out; + +found: + rng_base = pci_resource_start(pdev, 0); + if (rng_base == 0) + goto out; + err = -ENOMEM; + mem = ioremap(rng_base, 0x58); + if (!mem) + goto out; + geode_rng.priv = (unsigned long)mem; + + printk(KERN_INFO "AMD Geode RNG detected\n"); + err = hwrng_register(&geode_rng); + if (err) { + printk(KERN_ERR PFX "RNG registering failed (%d)\n", + err); + goto out; + } +out: + return err; +} + +static void __exit mod_exit(void) +{ + void __iomem *mem = (void __iomem *)geode_rng.priv; + + hwrng_unregister(&geode_rng); + iounmap(mem); +} + +subsys_initcall(mod_init); +module_exit(mod_exit); + +MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c new file mode 100644 index 0000000..6594bd5 --- /dev/null +++ b/drivers/char/hw_random/intel-rng.c @@ -0,0 +1,189 @@ +/* + * RNG driver for Intel RNGs + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * with the majority of the code coming from: + * + * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + * (c) Copyright 2003 Red Hat Inc + * + * derived from + * + * Hardware driver for the AMD 768 Random Number Generator (RNG) + * (c) Copyright 2001 Red Hat Inc + * + * derived from + * + * Hardware driver for Intel i810 Random Number Generator (RNG) + * Copyright 2000,2001 Jeff Garzik + * Copyright 2000,2001 Philipp Rumpf + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include + + +#define PFX KBUILD_MODNAME ": " + +/* + * RNG registers + */ +#define INTEL_RNG_HW_STATUS 0 +#define INTEL_RNG_PRESENT 0x40 +#define INTEL_RNG_ENABLED 0x01 +#define INTEL_RNG_STATUS 1 +#define INTEL_RNG_DATA_PRESENT 0x01 +#define INTEL_RNG_DATA 2 + +/* + * Magic address at which Intel PCI bridges locate the RNG + */ +#define INTEL_RNG_ADDR 0xFFBC015F +#define INTEL_RNG_ADDR_LEN 3 + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static const struct pci_device_id pci_tbl[] = { + { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, pci_tbl); + + +static inline u8 hwstatus_get(void __iomem *mem) +{ + return readb(mem + INTEL_RNG_HW_STATUS); +} + +static inline u8 hwstatus_set(void __iomem *mem, + u8 hw_status) +{ + writeb(hw_status, mem + INTEL_RNG_HW_STATUS); + return hwstatus_get(mem); +} + +static int intel_rng_data_present(struct hwrng *rng) +{ + void __iomem *mem = (void __iomem *)rng->priv; + + return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT); +} + +static int intel_rng_data_read(struct hwrng *rng, u32 *data) +{ + void __iomem *mem = (void __iomem *)rng->priv; + + *data = readb(mem + INTEL_RNG_DATA); + + return 1; +} + +static int intel_rng_init(struct hwrng *rng) +{ + void __iomem *mem = (void __iomem *)rng->priv; + u8 hw_status; + int err = -EIO; + + hw_status = hwstatus_get(mem); + /* turn RNG h/w on, if it's off */ + if ((hw_status & INTEL_RNG_ENABLED) == 0) + hw_status = hwstatus_set(mem, hw_status | INTEL_RNG_ENABLED); + if ((hw_status & INTEL_RNG_ENABLED) == 0) { + printk(KERN_ERR PFX "cannot enable RNG, aborting\n"); + goto out; + } + err = 0; +out: + return err; +} + +static void intel_rng_cleanup(struct hwrng *rng) +{ + void __iomem *mem = (void __iomem *)rng->priv; + u8 hw_status; + + hw_status = hwstatus_get(mem); + if (hw_status & INTEL_RNG_ENABLED) + hwstatus_set(mem, hw_status & ~INTEL_RNG_ENABLED); + else + printk(KERN_WARNING PFX "unusual: RNG already disabled\n"); +} + + +static struct hwrng intel_rng = { + .name = "intel", + .init = intel_rng_init, + .cleanup = intel_rng_cleanup, + .data_present = intel_rng_data_present, + .data_read = intel_rng_data_read, +}; + + +static int __init mod_init(void) +{ + int err = -ENODEV; + void __iomem *mem; + u8 hw_status; + + if (!pci_dev_present(pci_tbl)) + goto out; /* Device not found. */ + + err = -ENOMEM; + mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); + if (!mem) + goto out; + intel_rng.priv = (unsigned long)mem; + + /* Check for Intel 82802 */ + err = -ENODEV; + hw_status = hwstatus_get(mem); + if ((hw_status & INTEL_RNG_PRESENT) == 0) + goto err_unmap; + + printk(KERN_INFO "Intel 82802 RNG detected\n"); + err = hwrng_register(&intel_rng); + if (err) { + printk(KERN_ERR PFX "RNG registering failed (%d)\n", + err); + goto out; + } +out: + return err; + +err_unmap: + iounmap(mem); + goto out; +} + +static void __exit mod_exit(void) +{ + void __iomem *mem = (void __iomem *)intel_rng.priv; + + hwrng_unregister(&intel_rng); + iounmap(mem); +} + +subsys_initcall(mod_init); +module_exit(mod_exit); + +MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c new file mode 100644 index 0000000..ef71022 --- /dev/null +++ b/drivers/char/hw_random/ixp4xx-rng.c @@ -0,0 +1,73 @@ +/* + * drivers/char/rng/ixp4xx-rng.c + * + * RNG driver for Intel IXP4xx family of NPUs + * + * Author: Deepak Saxena + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * Fixes by Michael Buesch + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +static int ixp4xx_rng_data_read(struct hwrng *rng, u32 *buffer) +{ + void __iomem * rng_base = (void __iomem *)rng->priv; + + *buffer = __raw_readl(rng_base); + + return 4; +} + +static struct hwrng ixp4xx_rng_ops = { + .name = "ixp4xx", + .data_read = ixp4xx_rng_data_read, +}; + +static int __init ixp4xx_rng_init(void) +{ + void __iomem * rng_base; + int err; + + rng_base = ioremap(0x70002100, 4); + if (!rng_base) + return -ENOMEM; + ixp4xx_rng_ops.priv = (unsigned long)rng_base; + err = hwrng_register(&ixp4xx_rng_ops); + if (err) + iounmap(rng_base); + + return err; +} + +static void __exit ixp4xx_rng_exit(void) +{ + void __iomem * rng_base = (void __iomem *)ixp4xx_rng_ops.priv; + + hwrng_unregister(&ixp4xx_rng_ops); + iounmap(rng_base); +} + +subsys_initcall(ixp4xx_rng_init); +module_exit(ixp4xx_rng_exit); + +MODULE_AUTHOR("Deepak Saxena "); +MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c new file mode 100644 index 0000000..819516b --- /dev/null +++ b/drivers/char/hw_random/omap-rng.c @@ -0,0 +1,208 @@ +/* + * driver/char/hw_random/omap-rng.c + * + * RNG driver for TI OMAP CPU family + * + * Author: Deepak Saxena + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * Mostly based on original driver: + * + * Copyright (C) 2005 Nokia Corporation + * Author: Juha Yrj�� + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * TODO: + * + * - Make status updated be interrupt driven so we don't poll + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define RNG_OUT_REG 0x00 /* Output register */ +#define RNG_STAT_REG 0x04 /* Status register + [0] = STAT_BUSY */ +#define RNG_ALARM_REG 0x24 /* Alarm register + [7:0] = ALARM_COUNTER */ +#define RNG_CONFIG_REG 0x28 /* Configuration register + [11:6] = RESET_COUNT + [5:3] = RING2_DELAY + [2:0] = RING1_DELAY */ +#define RNG_REV_REG 0x3c /* Revision register + [7:0] = REV_NB */ +#define RNG_MASK_REG 0x40 /* Mask and reset register + [2] = IT_EN + [1] = SOFTRESET + [0] = AUTOIDLE */ +#define RNG_SYSSTATUS 0x44 /* System status + [0] = RESETDONE */ + +static void __iomem *rng_base; +static struct clk *rng_ick; +static struct device *rng_dev; + +static u32 omap_rng_read_reg(int reg) +{ + return __raw_readl(rng_base + reg); +} + +static void omap_rng_write_reg(int reg, u32 val) +{ + __raw_writel(val, rng_base + reg); +} + +/* REVISIT: Does the status bit really work on 16xx? */ +static int omap_rng_data_present(struct hwrng *rng) +{ + return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1; +} + +static int omap_rng_data_read(struct hwrng *rng, u32 *data) +{ + *data = omap_rng_read_reg(RNG_OUT_REG); + + return 4; +} + +static struct hwrng omap_rng_ops = { + .name = "omap", + .data_present = omap_rng_data_present, + .data_read = omap_rng_data_read, +}; + +static int __init omap_rng_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct resource *res, *mem; + int ret; + + /* + * A bit ugly, and it will never actually happen but there can + * be only one RNG and this catches any bork + */ + BUG_ON(rng_dev); + + if (cpu_is_omap24xx()) { + rng_ick = clk_get(NULL, "rng_ick"); + if (IS_ERR(rng_ick)) { + dev_err(dev, "Could not get rng_ick\n"); + ret = PTR_ERR(rng_ick); + return ret; + } + else { + clk_use(rng_ick); + } + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!res) + return -ENOENT; + + mem = request_mem_region(res->start, res->end - res->start + 1, + pdev->name); + if (mem == NULL) + return -EBUSY; + + dev_set_drvdata(dev, mem); + rng_base = (u32 __iomem *)io_p2v(res->start); + + ret = hwrng_register(&omap_rng_ops); + if (ret) { + release_resource(mem); + rng_base = NULL; + return ret; + } + + dev_info(dev, "OMAP Random Number Generator ver. %02x\n", + omap_rng_read_reg(RNG_REV_REG)); + omap_rng_write_reg(RNG_MASK_REG, 0x1); + + rng_dev = dev; + + return 0; +} + +static int __exit omap_rng_remove(struct device *dev) +{ + struct resource *mem = dev_get_drvdata(dev); + + hwrng_unregister(&omap_rng_ops); + + omap_rng_write_reg(RNG_MASK_REG, 0x0); + + if (cpu_is_omap24xx()) { + clk_unuse(rng_ick); + clk_put(rng_ick); + } + + release_resource(mem); + rng_base = NULL; + + return 0; +} + +#ifdef CONFIG_PM + +static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level) +{ + omap_rng_write_reg(RNG_MASK_REG, 0x0); + + return 0; +} + +static int omap_rng_resume(struct device *dev, pm_message_t message, u32 level) +{ + omap_rng_write_reg(RNG_MASK_REG, 0x1); + + return 1; +} + +#else + +#define omap_rng_suspend NULL +#define omap_rng_resume NULL + +#endif + + +static struct device_driver omap_rng_driver = { + .name = "omap_rng", + .bus = &platform_bus_type, + .probe = omap_rng_probe, + .remove = __exit_p(omap_rng_remove), + .suspend = omap_rng_suspend, + .resume = omap_rng_resume +}; + +static int __init omap_rng_init(void) +{ + if (!cpu_is_omap16xx() && !cpu_is_omap24xx()) + return -ENODEV; + + return driver_register(&omap_rng_driver); +} + +static void __exit omap_rng_exit(void) +{ + driver_unregister(&omap_rng_driver); +} + +module_init(omap_rng_init); +module_exit(omap_rng_exit); + +MODULE_AUTHOR("Deepak Saxena (and others)"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c new file mode 100644 index 0000000..0e786b6 --- /dev/null +++ b/drivers/char/hw_random/via-rng.c @@ -0,0 +1,183 @@ +/* + * RNG driver for VIA RNGs + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * with the majority of the code coming from: + * + * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + * (c) Copyright 2003 Red Hat Inc + * + * derived from + * + * Hardware driver for the AMD 768 Random Number Generator (RNG) + * (c) Copyright 2001 Red Hat Inc + * + * derived from + * + * Hardware driver for Intel i810 Random Number Generator (RNG) + * Copyright 2000,2001 Jeff Garzik + * Copyright 2000,2001 Philipp Rumpf + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + + +#define PFX KBUILD_MODNAME ": " + + +enum { + VIA_STRFILT_CNT_SHIFT = 16, + VIA_STRFILT_FAIL = (1 << 15), + VIA_STRFILT_ENABLE = (1 << 14), + VIA_RAWBITS_ENABLE = (1 << 13), + VIA_RNG_ENABLE = (1 << 6), + VIA_XSTORE_CNT_MASK = 0x0F, + + VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */ + VIA_RNG_CHUNK_4 = 0x01, /* 32 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_4_MASK = 0xFFFFFFFF, + VIA_RNG_CHUNK_2 = 0x02, /* 16 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_2_MASK = 0xFFFF, + VIA_RNG_CHUNK_1 = 0x03, /* 8 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_1_MASK = 0xFF, +}; + +/* + * Investigate using the 'rep' prefix to obtain 32 bits of random data + * in one insn. The upside is potentially better performance. The + * downside is that the instruction becomes no longer atomic. Due to + * this, just like familiar issues with /dev/random itself, the worst + * case of a 'rep xstore' could potentially pause a cpu for an + * unreasonably long time. In practice, this condition would likely + * only occur when the hardware is failing. (or so we hope :)) + * + * Another possible performance boost may come from simply buffering + * until we have 4 bytes, thus returning a u32 at a time, + * instead of the current u8-at-a-time. + */ + +static inline u32 xstore(u32 *addr, u32 edx_in) +{ + u32 eax_out; + + asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */" + :"=m"(*addr), "=a"(eax_out) + :"D"(addr), "d"(edx_in)); + + return eax_out; +} + +static int via_rng_data_present(struct hwrng *rng) +{ + u32 bytes_out; + u32 *via_rng_datum = (u32 *)(&rng->priv); + + /* We choose the recommended 1-byte-per-instruction RNG rate, + * for greater randomness at the expense of speed. Larger + * values 2, 4, or 8 bytes-per-instruction yield greater + * speed at lesser randomness. + * + * If you change this to another VIA_CHUNK_n, you must also + * change the ->n_bytes values in rng_vendor_ops[] tables. + * VIA_CHUNK_8 requires further code changes. + * + * A copy of MSR_VIA_RNG is placed in eax_out when xstore + * completes. + */ + + *via_rng_datum = 0; /* paranoia, not really necessary */ + bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1); + bytes_out &= VIA_XSTORE_CNT_MASK; + if (bytes_out == 0) + return 0; + return 1; +} + +static int via_rng_data_read(struct hwrng *rng, u32 *data) +{ + u32 via_rng_datum = (u32)rng->priv; + + *data = via_rng_datum; + + return 1; +} + +static int via_rng_init(struct hwrng *rng) +{ + u32 lo, hi, old_lo; + + /* Control the RNG via MSR. Tread lightly and pay very close + * close attention to values written, as the reserved fields + * are documented to be "undefined and unpredictable"; but it + * does not say to write them as zero, so I make a guess that + * we restore the values we find in the register. + */ + rdmsr(MSR_VIA_RNG, lo, hi); + + old_lo = lo; + lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT); + lo &= ~VIA_XSTORE_CNT_MASK; + lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE); + lo |= VIA_RNG_ENABLE; + + if (lo != old_lo) + wrmsr(MSR_VIA_RNG, lo, hi); + + /* perhaps-unnecessary sanity check; remove after testing if + unneeded */ + rdmsr(MSR_VIA_RNG, lo, hi); + if ((lo & VIA_RNG_ENABLE) == 0) { + printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n"); + return -ENODEV; + } + + return 0; +} + + +static struct hwrng via_rng = { + .name = "via", + .init = via_rng_init, + .data_present = via_rng_data_present, + .data_read = via_rng_data_read, +}; + + +static int __init mod_init(void) +{ + int err; + + if (!cpu_has_xstore) + return -ENODEV; + printk(KERN_INFO "VIA RNG detected\n"); + err = hwrng_register(&via_rng); + if (err) { + printk(KERN_ERR PFX "RNG registering failed (%d)\n", + err); + goto out; + } +out: + return err; +} + +static void __exit mod_exit(void) +{ + hwrng_unregister(&via_rng); +} + +subsys_initcall(mod_init); +module_exit(mod_exit); + +MODULE_DESCRIPTION("H/W RNG driver for VIA chipsets"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 03db1cb..9ab33c3 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -305,7 +305,7 @@ static struct class *ip2_class; // Some functions to keep track of what irq's we have -static int __init +static int is_valid_irq(int irq) { int *i = Valid_Irqs; @@ -316,14 +316,14 @@ is_valid_irq(int irq) return (*i); } -static void __init +static void mark_requested_irq( char irq ) { rirqs[iindx++] = irq; } #ifdef MODULE -static int __init +static int clear_requested_irq( char irq ) { int i; @@ -337,7 +337,7 @@ clear_requested_irq( char irq ) } #endif -static int __init +static int have_requested_irq( char irq ) { // array init to zeros so 0 irq will not be requested as a side effect @@ -818,7 +818,7 @@ EXPORT_SYMBOL(ip2_loadmain); /* the board, the channel structures are initialized, and the board details */ /* are reported on the console. */ /******************************************************************************/ -static void __init +static void ip2_init_board( int boardnum ) { int i; @@ -961,7 +961,7 @@ err_initialize: /* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */ /* it returns the base address of the controller. */ /******************************************************************************/ -static unsigned short __init +static unsigned short find_eisa_board( int start_slot ) { int i, j; diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 9f2f8fd..b03ddab 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -936,11 +936,8 @@ int ipmi_set_gets_events(ipmi_user_t use if (val) { /* Deliver any queued events. */ - list_for_each_entry_safe(msg, msg2, &intf->waiting_events, - link) { - list_del(&msg->link); - list_add_tail(&msg->link, &msgs); - } + list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) + list_move_tail(&msg->link, &msgs); intf->waiting_events_count = 0; } @@ -3677,7 +3674,7 @@ #endif /* CONFIG_IPMI_PANIC_STRING */ } #endif /* CONFIG_IPMI_PANIC_EVENT */ -static int has_paniced = 0; +static int has_panicked = 0; static int panic_event(struct notifier_block *this, unsigned long event, @@ -3686,9 +3683,9 @@ static int panic_event(struct notifier_b int i; ipmi_smi_t intf; - if (has_paniced) + if (has_panicked) return NOTIFY_DONE; - has_paniced = 1; + has_panicked = 1; /* For every registered interface, set it to run to completion. */ for (i = 0; i < MAX_IPMI_INTERFACES; i++) { diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 2d11ddd..8f88671 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -212,24 +212,16 @@ static int set_param_str(const char *val { action_fn fn = (action_fn) kp->arg; int rv = 0; - const char *end; - char valcp[16]; - int len; - - /* Truncate leading and trailing spaces. */ - while (isspace(*val)) - val++; - end = val + strlen(val) - 1; - while ((end >= val) && isspace(*end)) - end--; - len = end - val + 1; - if (len > sizeof(valcp) - 1) - return -EINVAL; - memcpy(valcp, val, len); - valcp[len] = '\0'; + char *dup, *s; + + dup = kstrdup(val, GFP_KERNEL); + if (!dup) + return -ENOMEM; + + s = strstrip(dup); down_read(®ister_sem); - rv = fn(valcp, NULL); + rv = fn(s, NULL); if (rv) goto out_unlock; @@ -239,6 +231,7 @@ static int set_param_str(const char *val out_unlock: up_read(®ister_sem); + kfree(dup); return rv; } diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index e9ebaba..efaaa19 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1145,7 +1145,7 @@ static int isicom_write(struct tty_struc if (isicom_paranoia_check(port, tty->name, "isicom_write")) return 0; - if (!tty || !port->xmit_buf) + if (!port->xmit_buf) return 0; spin_lock_irqsave(&card->card_lock, flags); @@ -1180,7 +1180,7 @@ static void isicom_put_char(struct tty_s if (isicom_paranoia_check(port, tty->name, "isicom_put_char")) return; - if (!tty || !port->xmit_buf) + if (!port->xmit_buf) return; spin_lock_irqsave(&card->card_lock, flags); diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 5755b7e..4bb3d22 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -39,6 +39,7 @@ #include #include #include #include +#include static void kbd_disconnect(struct input_handle *handle); extern void ctrl_alt_del(void); @@ -150,6 +151,7 @@ unsigned char kbd_sysrq_xlate[KEY_MAX + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ "\r\000/"; /* 0x60 - 0x6f */ static int sysrq_down; +static int sysrq_alt_use; #endif static int sysrq_alt; @@ -672,7 +674,7 @@ static void k_dead2(struct vc_data *vc, */ static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) { - static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' }; + static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' }; value = ret_diacr[value]; k_deadunicode(vc, value, up_flag, regs); } @@ -709,8 +711,8 @@ static void k_cur(struct vc_data *vc, un static void k_pad(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) { - static const char *pad_chars = "0123456789+-*/\015,.?()#"; - static const char *app_map = "pqrstuvwxylSRQMnnmPQS"; + static const char pad_chars[] = "0123456789+-*/\015,.?()#"; + static const char app_map[] = "pqrstuvwxylSRQMnnmPQS"; if (up_flag) return; /* no action, if this is a key release */ @@ -1035,7 +1037,7 @@ #if defined(CONFIG_X86) || defined(CONFI #define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\ ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001)) -static unsigned short x86_keycodes[256] = +static const unsigned short x86_keycodes[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, @@ -1073,11 +1075,13 @@ static int emulate_raw(struct vc_data *v put_queue(vc, 0x1d | up_flag); put_queue(vc, 0x45 | up_flag); return 0; - case KEY_HANGUEL: - if (!up_flag) put_queue(vc, 0xf1); + case KEY_HANGEUL: + if (!up_flag) + put_queue(vc, 0xf2); return 0; case KEY_HANJA: - if (!up_flag) put_queue(vc, 0xf2); + if (!up_flag) + put_queue(vc, 0xf1); return 0; } @@ -1142,7 +1146,7 @@ static void kbd_keycode(unsigned int key kbd = kbd_table + fg_console; if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT) - sysrq_alt = down; + sysrq_alt = down ? keycode : 0; #ifdef CONFIG_SPARC if (keycode == KEY_STOP) sparc_l1_a_state = down; @@ -1162,9 +1166,14 @@ #endif /* CONFIG_MAC_EMUMOUSEBTN */ #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) { - sysrq_down = down; + if (!sysrq_down) { + sysrq_down = down; + sysrq_alt_use = sysrq_alt; + } return; } + if (sysrq_down && !down && keycode == sysrq_alt_use) + sysrq_down = 0; if (sysrq_down && down && !rep) { handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty); return; diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 1b05fa6..d65b310 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -329,7 +329,6 @@ static int mmtimer_mmap(struct file *fil if (PAGE_SIZE > (1 << 16)) return -ENOSYS; - vma->vm_flags |= (VM_IO | VM_SHM | VM_LOCKED ); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); mmtimer_addr = __pa(RTC_COUNTER_ADDR); diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 0fb2fb9..645d9d7 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -9,7 +9,7 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -71,8 +71,8 @@ #define MXSER_VERSION "1.8" #define MXSERMAJOR 174 #define MXSERCUMAJOR 175 -#define MXSER_EVENT_TXLOW 1 -#define MXSER_EVENT_HANGUP 2 +#define MXSER_EVENT_TXLOW 1 +#define MXSER_EVENT_HANGUP 2 #define MXSER_BOARDS 4 /* Max. boards */ #define MXSER_PORTS 32 /* Max. ports */ @@ -92,7 +92,8 @@ #define WAKEUP_CHARS 256 #define UART_MCR_AFE 0x20 #define UART_LSR_SPECIAL 0x1E -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|IXON|IXOFF)) +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\ + IXON|IXOFF)) #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) @@ -152,27 +153,27 @@ static char *mxser_brdname[] = { }; static int mxser_numports[] = { - 8, // C168-ISA - 4, // C104-ISA - 4, // CI104J - 8, // C168-PCI - 4, // C104-PCI - 2, // C102-ISA - 2, // CI132 - 4, // CI134 - 2, // CP132 - 4, // CP114 - 4, // CT114 - 2, // CP102 - 4, // CP104U - 8, // CP168U - 2, // CP132U - 4, // CP134U - 4, // CP104JU - 8, // RC7000 - 8, // CP118U - 2, // CP102UL - 2, // CP102U + 8, /* C168-ISA */ + 4, /* C104-ISA */ + 4, /* CI104J */ + 8, /* C168-PCI */ + 4, /* C104-PCI */ + 2, /* C102-ISA */ + 2, /* CI132 */ + 4, /* CI134 */ + 2, /* CP132 */ + 4, /* CP114 */ + 4, /* CT114 */ + 2, /* CP102 */ + 4, /* CP104U */ + 8, /* CP168U */ + 2, /* CP132U */ + 4, /* CP134U */ + 4, /* CP104JU */ + 8, /* RC7000 */ + 8, /* CP118U */ + 2, /* CP102UL */ + 2, /* CP102U */ }; #define UART_TYPE_NUM 2 @@ -182,7 +183,7 @@ static const unsigned int Gmoxa_uart_id[ MOXA_MUST_MU860_HWID }; -// This is only for PCI +/* This is only for PCI */ #define UART_INFO_NUM 3 struct mxpciuart_info { int type; @@ -231,7 +232,7 @@ #endif typedef struct _moxa_pci_info { unsigned short busNum; unsigned short devNum; - struct pci_dev *pdev; // add by Victor Yu. 06-23-2003 + struct pci_dev *pdev; /* add by Victor Yu. 06-23-2003 */ } moxa_pci_info; static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; @@ -280,6 +281,7 @@ struct mxser_mon_ext { int fifo[32]; int iftype[32]; }; + struct mxser_hwconf { int board_type; int ports; @@ -290,9 +292,9 @@ struct mxser_hwconf { int ioaddr[MXSER_PORTS_PER_BOARD]; int baud_base[MXSER_PORTS_PER_BOARD]; moxa_pci_info pciInfo; - int IsMoxaMustChipFlag; // add by Victor Yu. 08-30-2002 - int MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD]; // add by Victor Yu. 09-04-2002 - int opmode_ioaddr[MXSER_PORTS_PER_BOARD]; // add by Victor Yu. 01-05-2004 + int IsMoxaMustChipFlag; /* add by Victor Yu. 08-30-2002 */ + int MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD]; /* add by Victor Yu. 09-04-2002 */ + int opmode_ioaddr[MXSER_PORTS_PER_BOARD]; /* add by Victor Yu. 01-05-2004 */ }; struct mxser_struct { @@ -334,9 +336,9 @@ struct mxser_struct { wait_queue_head_t delta_msr_wait; struct async_icount icount; /* kernel counters for the 4 input interrupts */ int timeout; - int IsMoxaMustChipFlag; // add by Victor Yu. 08-30-2002 - int MaxCanSetBaudRate; // add by Victor Yu. 09-04-2002 - int opmode_ioaddr; // add by Victor Yu. 01-05-2004 + int IsMoxaMustChipFlag; /* add by Victor Yu. 08-30-2002 */ + int MaxCanSetBaudRate; /* add by Victor Yu. 09-04-2002 */ + int opmode_ioaddr; /* add by Victor Yu. 01-05-2004 */ unsigned char stop_rx; unsigned char ldisc_stop_rx; long realbaud; @@ -345,7 +347,6 @@ struct mxser_struct { spinlock_t slock; }; - struct mxser_mstatus { tcflag_t cflag; int cts; @@ -358,7 +359,7 @@ static struct mxser_mstatus GMStatus[MXS static int mxserBoardCAP[MXSER_BOARDS] = { 0, 0, 0, 0 - /* 0x180, 0x280, 0x200, 0x320 */ + /* 0x180, 0x280, 0x200, 0x320 */ }; static struct tty_driver *mxvar_sdriver; @@ -386,7 +387,7 @@ static struct mxser_hwconf mxsercfg[MXSE static void mxser_getcfg(int board, struct mxser_hwconf *hwconf); static int mxser_init(void); -//static void mxser_poll(unsigned long); +/* static void mxser_poll(unsigned long); */ static int mxser_get_ISA_conf(int, struct mxser_hwconf *); static int mxser_get_PCI_conf(int, int, int, struct mxser_hwconf *); static void mxser_do_softint(void *); @@ -440,18 +441,18 @@ static int CheckIsMoxaMust(int io) SET_MOXA_MUST_XON1_VALUE(io, 0x11); if ((hwid = inb(io + UART_MCR)) != 0) { outb(oldmcr, io + UART_MCR); - return (MOXA_OTHER_UART); + return MOXA_OTHER_UART; } GET_MOXA_MUST_HARDWARE_ID(io, &hwid); for (i = 0; i < UART_TYPE_NUM; i++) { if (hwid == Gmoxa_uart_id[i]) - return (int) hwid; + return (int)hwid; } return MOXA_OTHER_UART; } -// above is modified by Victor Yu. 08-15-2002 +/* above is modified by Victor Yu. 08-15-2002 */ static struct tty_operations mxser_ops = { .open = mxser_open, @@ -504,7 +505,6 @@ static void __exit mxser_module_exit(voi else printk(KERN_ERR "Couldn't unregister MOXA Smartio/Industio family serial driver\n"); - for (i = 0; i < MXSER_BOARDS; i++) { struct pci_dev *pdev; @@ -513,7 +513,7 @@ static void __exit mxser_module_exit(voi else { pdev = mxsercfg[i].pciInfo.pdev; free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]); - if (pdev != NULL) { //PCI + if (pdev != NULL) { /* PCI */ release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3)); } else { @@ -524,7 +524,6 @@ static void __exit mxser_module_exit(voi } if (verbose) printk(KERN_DEBUG "Done.\n"); - } static void process_txrx_fifo(struct mxser_struct *info) @@ -558,8 +557,10 @@ static int mxser_initbrd(int board, stru n = board * MXSER_PORTS_PER_BOARD; info = &mxvar_table[n]; /*if (verbose) */ { - printk(KERN_DEBUG " ttyM%d - ttyM%d ", n, n + hwconf->ports - 1); - printk(" max. baud rate = %d bps.\n", hwconf->MaxCanSetBaudRate[0]); + printk(KERN_DEBUG " ttyM%d - ttyM%d ", + n, n + hwconf->ports - 1); + printk(" max. baud rate = %d bps.\n", + hwconf->MaxCanSetBaudRate[0]); } for (i = 0; i < hwconf->ports; i++, n++, info++) { @@ -568,12 +569,12 @@ static int mxser_initbrd(int board, stru info->irq = hwconf->irq; info->vector = hwconf->vector; info->vectormask = hwconf->vector_mask; - info->opmode_ioaddr = hwconf->opmode_ioaddr[i]; // add by Victor Yu. 01-05-2004 + info->opmode_ioaddr = hwconf->opmode_ioaddr[i]; /* add by Victor Yu. 01-05-2004 */ info->stop_rx = 0; info->ldisc_stop_rx = 0; info->IsMoxaMustChipFlag = hwconf->IsMoxaMustChipFlag; - //Enhance mode enabled here + /* Enhance mode enabled here */ if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) { ENABLE_MOXA_MUST_ENCHANCE_MODE(info->base); } @@ -606,22 +607,25 @@ static int mxser_initbrd(int board, stru /* before set INT ISR, disable all int */ for (i = 0; i < hwconf->ports; i++) { - outb(inb(hwconf->ioaddr[i] + UART_IER) & 0xf0, hwconf->ioaddr[i] + UART_IER); + outb(inb(hwconf->ioaddr[i] + UART_IER) & 0xf0, + hwconf->ioaddr[i] + UART_IER); } n = board * MXSER_PORTS_PER_BOARD; info = &mxvar_table[n]; - retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info), "mxser", info); + retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info), + "mxser", info); if (retval) { - printk(KERN_ERR "Board %d: %s", board, mxser_brdname[hwconf->board_type - 1]); - printk(" Request irq fail,IRQ (%d) may be conflit with another device.\n", info->irq); + printk(KERN_ERR "Board %d: %s", + board, mxser_brdname[hwconf->board_type - 1]); + printk(" Request irq failed, IRQ (%d) may conflict with" + " another device.\n", info->irq); return retval; } return 0; } - static void mxser_getcfg(int board, struct mxser_hwconf *hwconf) { mxsercfg[board] = *hwconf; @@ -631,26 +635,27 @@ #ifdef CONFIG_PCI static int mxser_get_PCI_conf(int busnum, int devnum, int board_type, struct mxser_hwconf *hwconf) { int i, j; -// unsigned int val; + /* unsigned int val; */ unsigned int ioaddress; struct pci_dev *pdev = hwconf->pciInfo.pdev; - //io address + /* io address */ hwconf->board_type = board_type; hwconf->ports = mxser_numports[board_type - 1]; ioaddress = pci_resource_start(pdev, 2); - request_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2), "mxser(IO)"); + request_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2), + "mxser(IO)"); - for (i = 0; i < hwconf->ports; i++) { + for (i = 0; i < hwconf->ports; i++) hwconf->ioaddr[i] = ioaddress + 8 * i; - } - //vector + /* vector */ ioaddress = pci_resource_start(pdev, 3); - request_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3), "mxser(vector)"); + request_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3), + "mxser(vector)"); hwconf->vector = ioaddress; - //irq + /* irq */ hwconf->irq = hwconf->pciInfo.pdev->irq; hwconf->IsMoxaMustChipFlag = CheckIsMoxaMust(hwconf->ioaddr[0]); @@ -663,7 +668,7 @@ static int mxser_get_PCI_conf(int busnum if (Gpci_uart_info[j].type == hwconf->IsMoxaMustChipFlag) { hwconf->MaxCanSetBaudRate[i] = Gpci_uart_info[j].max_baud; - //exception....CP-102 + /* exception....CP-102 */ if (board_type == MXSER_BOARD_CP102) hwconf->MaxCanSetBaudRate[i] = 921600; break; @@ -678,15 +683,15 @@ static int mxser_get_PCI_conf(int busnum else hwconf->opmode_ioaddr[i] = ioaddress + 0x0c; } - outb(0, ioaddress + 4); // default set to RS232 mode - outb(0, ioaddress + 0x0c); //default set to RS232 mode + outb(0, ioaddress + 4); /* default set to RS232 mode */ + outb(0, ioaddress + 0x0c); /* default set to RS232 mode */ } for (i = 0; i < hwconf->ports; i++) { hwconf->vector_mask |= (1 << i); hwconf->baud_base[i] = 921600; } - return (0); + return 0; } #endif @@ -707,7 +712,8 @@ static int mxser_init(void) mxsercfg[i].board_type = -1; } - printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", MXSER_VERSION); + printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", + MXSER_VERSION); /* Initialize the tty_driver structure */ memset(mxvar_sdriver, 0, sizeof(struct tty_driver)); @@ -719,7 +725,7 @@ static int mxser_init(void) mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL; mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; mxvar_sdriver->init_termios = tty_std_termios; - mxvar_sdriver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(mxvar_sdriver, &mxser_ops); mxvar_sdriver->ttys = mxvar_tty; @@ -739,23 +745,29 @@ static int mxser_init(void) /* Start finding ISA boards here */ for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { int cap; + if (!(cap = mxserBoardCAP[b])) continue; retval = mxser_get_ISA_conf(cap, &hwconf); if (retval != 0) - printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", mxser_brdname[hwconf.board_type - 1], ioaddr[b]); + printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", + mxser_brdname[hwconf.board_type - 1], ioaddr[b]); if (retval <= 0) { if (retval == MXSER_ERR_IRQ) - printk(KERN_ERR "Invalid interrupt number,board not configured\n"); + printk(KERN_ERR "Invalid interrupt number, " + "board not configured\n"); else if (retval == MXSER_ERR_IRQ_CONFLIT) - printk(KERN_ERR "Invalid interrupt number,board not configured\n"); + printk(KERN_ERR "Invalid interrupt number, " + "board not configured\n"); else if (retval == MXSER_ERR_VECTOR) - printk(KERN_ERR "Invalid interrupt vector,board not configured\n"); + printk(KERN_ERR "Invalid interrupt vector, " + "board not configured\n"); else if (retval == MXSER_ERR_IOADDR) - printk(KERN_ERR "Invalid I/O address,board not configured\n"); + printk(KERN_ERR "Invalid I/O address, " + "board not configured\n"); continue; } @@ -765,35 +777,43 @@ static int mxser_init(void) hwconf.pciInfo.pdev = NULL; mxser_getcfg(m, &hwconf); - //init mxsercfg first, or mxsercfg data is not correct on ISR. - //mxser_initbrd will hook ISR. + /* + * init mxsercfg first, + * or mxsercfg data is not correct on ISR. + */ + /* mxser_initbrd will hook ISR. */ if (mxser_initbrd(m, &hwconf) < 0) continue; - m++; } /* Start finding ISA boards from module arg */ for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { int cap; + if (!(cap = ioaddr[b])) continue; retval = mxser_get_ISA_conf(cap, &hwconf); if (retval != 0) - printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", mxser_brdname[hwconf.board_type - 1], ioaddr[b]); + printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", + mxser_brdname[hwconf.board_type - 1], ioaddr[b]); if (retval <= 0) { if (retval == MXSER_ERR_IRQ) - printk(KERN_ERR "Invalid interrupt number,board not configured\n"); + printk(KERN_ERR "Invalid interrupt number, " + "board not configured\n"); else if (retval == MXSER_ERR_IRQ_CONFLIT) - printk(KERN_ERR "Invalid interrupt number,board not configured\n"); + printk(KERN_ERR "Invalid interrupt number, " + "board not configured\n"); else if (retval == MXSER_ERR_VECTOR) - printk(KERN_ERR "Invalid interrupt vector,board not configured\n"); + printk(KERN_ERR "Invalid interrupt vector, " + "board not configured\n"); else if (retval == MXSER_ERR_IOADDR) - printk(KERN_ERR "Invalid I/O address,board not configured\n"); + printk(KERN_ERR "Invalid I/O address, " + "board not configured\n"); continue; } @@ -803,8 +823,11 @@ static int mxser_init(void) hwconf.pciInfo.pdev = NULL; mxser_getcfg(m, &hwconf); - //init mxsercfg first, or mxsercfg data is not correct on ISR. - //mxser_initbrd will hook ISR. + /* + * init mxsercfg first, + * or mxsercfg data is not correct on ISR. + */ + /* mxser_initbrd will hook ISR. */ if (mxser_initbrd(m, &hwconf) < 0) continue; @@ -817,7 +840,8 @@ #ifdef CONFIG_PCI index = 0; b = 0; while (b < n) { - pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev); + pdev = pci_find_device(mxser_pcibrds[b].vendor, + mxser_pcibrds[b].device, pdev); if (pdev == NULL) { b++; continue; @@ -825,30 +849,48 @@ #ifdef CONFIG_PCI hwconf.pciInfo.busNum = busnum = pdev->bus->number; hwconf.pciInfo.devNum = devnum = PCI_SLOT(pdev->devfn) << 3; hwconf.pciInfo.pdev = pdev; - printk(KERN_INFO "Found MOXA %s board(BusNo=%d,DevNo=%d)\n", mxser_brdname[(int) (mxser_pcibrds[b].driver_data) - 1], busnum, devnum >> 3); + printk(KERN_INFO "Found MOXA %s board(BusNo=%d,DevNo=%d)\n", + mxser_brdname[(int) (mxser_pcibrds[b].driver_data) - 1], + busnum, devnum >> 3); index++; - if (m >= MXSER_BOARDS) { - printk(KERN_ERR "Too many Smartio/Industio family boards find (maximum %d),board not configured\n", MXSER_BOARDS); - } else { + if (m >= MXSER_BOARDS) + printk(KERN_ERR + "Too many Smartio/Industio family boards find " + "(maximum %d), board not configured\n", + MXSER_BOARDS); + else { if (pci_enable_device(pdev)) { - printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n"); + printk(KERN_ERR "Moxa SmartI/O PCI enable " + "fail !\n"); continue; } - retval = mxser_get_PCI_conf(busnum, devnum, (int) mxser_pcibrds[b].driver_data, &hwconf); + retval = mxser_get_PCI_conf(busnum, devnum, + (int)mxser_pcibrds[b].driver_data, + &hwconf); if (retval < 0) { if (retval == MXSER_ERR_IRQ) - printk(KERN_ERR "Invalid interrupt number,board not configured\n"); + printk(KERN_ERR + "Invalid interrupt number, " + "board not configured\n"); else if (retval == MXSER_ERR_IRQ_CONFLIT) - printk(KERN_ERR "Invalid interrupt number,board not configured\n"); + printk(KERN_ERR + "Invalid interrupt number, " + "board not configured\n"); else if (retval == MXSER_ERR_VECTOR) - printk(KERN_ERR "Invalid interrupt vector,board not configured\n"); + printk(KERN_ERR + "Invalid interrupt vector, " + "board not configured\n"); else if (retval == MXSER_ERR_IOADDR) - printk(KERN_ERR "Invalid I/O address,board not configured\n"); + printk(KERN_ERR + "Invalid I/O address, " + "board not configured\n"); continue; } mxser_getcfg(m, &hwconf); - //init mxsercfg first, or mxsercfg data is not correct on ISR. - //mxser_initbrd will hook ISR. + /* init mxsercfg first, + * or mxsercfg data is not correct on ISR. + */ + /* mxser_initbrd will hook ISR. */ if (mxser_initbrd(m, &hwconf) < 0) continue; m++; @@ -858,7 +900,8 @@ #endif retval = tty_register_driver(mxvar_sdriver); if (retval) { - printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family driver !\n"); + printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family" + " driver !\n"); put_tty_driver(mxvar_sdriver); for (i = 0; i < MXSER_BOARDS; i++) { @@ -866,7 +909,7 @@ #endif continue; else { free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]); - //todo: release io, vector + /* todo: release io, vector */ } } return retval; @@ -877,7 +920,7 @@ #endif static void mxser_do_softint(void *private_) { - struct mxser_struct *info = (struct mxser_struct *) private_; + struct mxser_struct *info = private_; struct tty_struct *tty; tty = info->tty; @@ -926,7 +969,7 @@ static int mxser_open(struct tty_struct return -ENODEV; info = mxvar_table + line; if (!info->base) - return (-ENODEV); + return -ENODEV; tty->driver_data = info; info->tty = tty; @@ -935,11 +978,11 @@ static int mxser_open(struct tty_struct */ retval = mxser_startup(info); if (retval) - return (retval); + return retval; retval = mxser_block_til_ready(tty, filp, info); if (retval) - return (retval); + return retval; info->count++; @@ -955,11 +998,12 @@ static int mxser_open(struct tty_struct info->pgrp = process_group(current); clear_bit(TTY_DONT_FLIP, &tty->flags); - //status = mxser_get_msr(info->base, 0, info->port); - //mxser_check_modem_status(info, status); + /* + status = mxser_get_msr(info->base, 0, info->port); + mxser_check_modem_status(info, status); + */ -/* unmark here for very high baud rate (ex. 921600 bps) used -*/ +/* unmark here for very high baud rate (ex. 921600 bps) used */ tty->low_latency = 1; return 0; } @@ -972,7 +1016,7 @@ static int mxser_open(struct tty_struct */ static void mxser_close(struct tty_struct *tty, struct file *filp) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; unsigned long timeout; unsigned long flags; @@ -997,11 +1041,13 @@ static void mxser_close(struct tty_struc * one, we've got real problems, since it means the * serial port won't be shutdown. */ - printk(KERN_ERR "mxser_close: bad serial port count; tty->count is 1, " "info->count is %d\n", info->count); + printk(KERN_ERR "mxser_close: bad serial port count; " + "tty->count is 1, info->count is %d\n", info->count); info->count = 1; } if (--info->count < 0) { - printk(KERN_ERR "mxser_close: bad serial port count for ttys%d: %d\n", info->port, info->count); + printk(KERN_ERR "mxser_close: bad serial port count for " + "ttys%d: %d\n", info->port, info->count); info->count = 0; } if (info->count) { @@ -1056,7 +1102,7 @@ static void mxser_close(struct tty_struc ld = tty_ldisc_ref(tty); if (ld) { - if(ld->flush_buffer) + if (ld->flush_buffer) ld->flush_buffer(tty); tty_ldisc_deref(ld); } @@ -1078,31 +1124,34 @@ static void mxser_close(struct tty_struc static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) { int c, total = 0; - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; unsigned long flags; - if (!tty || !info->xmit_buf) - return (0); + if (!info->xmit_buf) + return 0; while (1) { - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); if (c <= 0) break; memcpy(info->xmit_buf + info->xmit_head, buf, c); spin_lock_irqsave(&info->slock, flags); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1); + info->xmit_head = (info->xmit_head + c) & + (SERIAL_XMIT_SIZE - 1); info->xmit_cnt += c; spin_unlock_irqrestore(&info->slock, flags); buf += c; count -= c; total += c; - } if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) { - if (!tty->hw_stopped || (info->type == PORT_16550A) || (info->IsMoxaMustChipFlag)) { + if (!tty->hw_stopped || + (info->type == PORT_16550A) || + (info->IsMoxaMustChipFlag)) { spin_lock_irqsave(&info->slock, flags); info->IER |= UART_IER_THRI; outb(info->IER, info->base + UART_IER); @@ -1114,10 +1163,10 @@ static int mxser_write(struct tty_struct static void mxser_put_char(struct tty_struct *tty, unsigned char ch) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; unsigned long flags; - if (!tty || !info->xmit_buf) + if (!info->xmit_buf) return; if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) @@ -1129,7 +1178,9 @@ static void mxser_put_char(struct tty_st info->xmit_cnt++; spin_unlock_irqrestore(&info->slock, flags); if (!tty->stopped && !(info->IER & UART_IER_THRI)) { - if (!tty->hw_stopped || (info->type == PORT_16550A) || info->IsMoxaMustChipFlag) { + if (!tty->hw_stopped || + (info->type == PORT_16550A) || + info->IsMoxaMustChipFlag) { spin_lock_irqsave(&info->slock, flags); info->IER |= UART_IER_THRI; outb(info->IER, info->base + UART_IER); @@ -1141,10 +1192,16 @@ static void mxser_put_char(struct tty_st static void mxser_flush_chars(struct tty_struct *tty) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; unsigned long flags; - if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf || (tty->hw_stopped && (info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag))) + if (info->xmit_cnt <= 0 || + tty->stopped || + !info->xmit_buf || + (tty->hw_stopped && + (info->type != PORT_16550A) && + (!info->IsMoxaMustChipFlag) + )) return; spin_lock_irqsave(&info->slock, flags); @@ -1157,24 +1214,24 @@ static void mxser_flush_chars(struct tty static int mxser_write_room(struct tty_struct *tty) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; int ret; ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; if (ret < 0) ret = 0; - return (ret); + return ret; } static int mxser_chars_in_buffer(struct tty_struct *tty) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; return info->xmit_cnt; } static void mxser_flush_buffer(struct tty_struct *tty) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; char fcr; unsigned long flags; @@ -1184,7 +1241,8 @@ static void mxser_flush_buffer(struct tt /* below added by shinhay */ fcr = inb(info->base + UART_FCR); - outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR); + outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), + info->base + UART_FCR); outb(fcr, info->base + UART_FCR); spin_unlock_irqrestore(&info->slock, flags); @@ -1197,7 +1255,7 @@ static void mxser_flush_buffer(struct tt static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; int retval; struct async_icount cprev, cnow; /* kernel counter temps */ struct serial_icounter_struct __user *p_cuser; @@ -1206,9 +1264,9 @@ static int mxser_ioctl(struct tty_struct void __user *argp = (void __user *)arg; if (tty->index == MXSER_PORTS) - return (mxser_ioctl_special(cmd, argp)); + return mxser_ioctl_special(cmd, argp); - // following add by Victor Yu. 01-05-2004 + /* following add by Victor Yu. 01-05-2004 */ if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) { int opmode, p; static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f }; @@ -1219,7 +1277,10 @@ static int mxser_ioctl(struct tty_struct if (cmd == MOXA_SET_OP_MODE) { if (get_user(opmode, (int __user *) argp)) return -EFAULT; - if (opmode != RS232_MODE && opmode != RS485_2WIRE_MODE && opmode != RS422_MODE && opmode != RS485_4WIRE_MODE) + if (opmode != RS232_MODE && + opmode != RS485_2WIRE_MODE && + opmode != RS422_MODE && + opmode != RS485_4WIRE_MODE) return -EFAULT; mask = ModeMask[p]; shiftbit = p * 2; @@ -1236,36 +1297,36 @@ static int mxser_ioctl(struct tty_struct } return 0; } - // above add by Victor Yu. 01-05-2004 + /* above add by Victor Yu. 01-05-2004 */ if ((cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { if (tty->flags & (1 << TTY_IO_ERROR)) - return (-EIO); + return -EIO; } switch (cmd) { case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) - return (retval); + return retval; tty_wait_until_sent(tty, 0); if (!arg) mxser_send_break(info, HZ / 4); /* 1/4 second */ - return (0); + return 0; case TCSBRKP: /* support for POSIX tcsendbreak() */ retval = tty_check_change(tty); if (retval) - return (retval); + return retval; tty_wait_until_sent(tty, 0); mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4); - return (0); + return 0; case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp); + return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); case TIOCSSOFTCAR: if (get_user(templ, (unsigned long __user *) argp)) return -EFAULT; arg = templ; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); - return (0); + return 0; case TIOCGSERIAL: return mxser_get_serial_info(info, argp); case TIOCSSERIAL: @@ -1278,7 +1339,7 @@ static int mxser_ioctl(struct tty_struct * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) * Caller should use TIOCGICOUNT to see which one it was */ - case TIOCMIWAIT:{ + case TIOCMIWAIT: { DECLARE_WAITQUEUE(wait, current); int ret; spin_lock_irqsave(&info->slock, flags); @@ -1292,7 +1353,14 @@ static int mxser_ioctl(struct tty_struct spin_unlock_irqrestore(&info->slock, flags); set_current_state(TASK_INTERRUPTIBLE); - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { + if (((arg & TIOCM_RNG) && + (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && + (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && + (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && + (cnow.cts != cprev.cts))) { ret = 0; break; } @@ -1338,21 +1406,18 @@ static int mxser_ioctl(struct tty_struct put_user(cnow.dsr, &p_cuser->dsr); put_user(cnow.rng, &p_cuser->rng); put_user(cnow.dcd, &p_cuser->dcd); - -/* */ return 0; case MOXA_HighSpeedOn: - return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *) argp); - - case MOXA_SDS_RSTICOUNTER:{ + return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); + case MOXA_SDS_RSTICOUNTER: { info->mon_data.rxcnt = 0; info->mon_data.txcnt = 0; return 0; } -// (above) added by James. +/* (above) added by James. */ case MOXA_ASPP_SETBAUD:{ long baud; - if (get_user(baud, (long __user *) argp)) + if (get_user(baud, (long __user *)argp)) return -EFAULT; mxser_set_baud(info, baud); return 0; @@ -1377,9 +1442,10 @@ static int mxser_ioctl(struct tty_struct return 0; } - case MOXA_ASPP_MON:{ + case MOXA_ASPP_MON: { int mcr, status; -// info->mon_data.ser_param = tty->termios->c_cflag; + + /* info->mon_data.ser_param = tty->termios->c_cflag; */ status = mxser_get_msr(info->base, 1, info->port, info); mxser_check_modem_status(info, status); @@ -1400,25 +1466,25 @@ static int mxser_ioctl(struct tty_struct else info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; - - if (copy_to_user(argp, &info->mon_data, sizeof(struct mxser_mon))) + if (copy_to_user(argp, &info->mon_data, + sizeof(struct mxser_mon))) return -EFAULT; return 0; - } - case MOXA_ASPP_LSTATUS:{ - if (copy_to_user(argp, &info->err_shadow, sizeof(unsigned char))) + case MOXA_ASPP_LSTATUS: { + if (copy_to_user(argp, &info->err_shadow, + sizeof(unsigned char))) return -EFAULT; info->err_shadow = 0; return 0; - } - case MOXA_SET_BAUD_METHOD:{ + case MOXA_SET_BAUD_METHOD: { int method; - if (get_user(method, (int __user *) argp)) + + if (get_user(method, (int __user *)argp)) return -EFAULT; mxser_set_baud_method[info->port] = method; if (copy_to_user(argp, &method, sizeof(int))) @@ -1442,7 +1508,8 @@ static int mxser_ioctl_special(unsigned switch (cmd) { case MOXA_GET_CONF: - if (copy_to_user(argp, mxsercfg, sizeof(struct mxser_hwconf) * 4)) + if (copy_to_user(argp, mxsercfg, + sizeof(struct mxser_hwconf) * 4)) return -EFAULT; return 0; case MOXA_GET_MAJOR: @@ -1461,11 +1528,11 @@ static int mxser_ioctl_special(unsigned if (mxvar_table[i].base) result |= (1 << i); } - return put_user(result, (unsigned long __user *) argp); + return put_user(result, (unsigned long __user *)argp); case MOXA_GETDATACOUNT: if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) return -EFAULT; - return (0); + return 0; case MOXA_GETMSTATUS: for (i = 0; i < MXSER_PORTS; i++) { GMStatus[i].ri = 0; @@ -1498,22 +1565,26 @@ static int mxser_ioctl_special(unsigned else GMStatus[i].cts = 0; } - if (copy_to_user(argp, GMStatus, sizeof(struct mxser_mstatus) * MXSER_PORTS)) + if (copy_to_user(argp, GMStatus, + sizeof(struct mxser_mstatus) * MXSER_PORTS)) return -EFAULT; return 0; - case MOXA_ASPP_MON_EXT:{ + case MOXA_ASPP_MON_EXT: { int status; int opmode, p; int shiftbit; unsigned cflag, iflag; for (i = 0; i < MXSER_PORTS; i++) { - if (!mxvar_table[i].base) continue; - status = mxser_get_msr(mxvar_table[i].base, 0, i, &(mxvar_table[i])); -// mxser_check_modem_status(&mxvar_table[i], status); + status = mxser_get_msr(mxvar_table[i].base, 0, + i, &(mxvar_table[i])); + /* + mxser_check_modem_status(&mxvar_table[i], + status); + */ if (status & UART_MSR_TERI) mxvar_table[i].icount.rng++; if (status & UART_MSR_DDSR) @@ -1578,75 +1649,76 @@ static int mxser_ioctl_special(unsigned return 0; } - static void mxser_stoprx(struct tty_struct *tty) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; - //unsigned long flags; - + struct mxser_struct *info = tty->driver_data; + /* unsigned long flags; */ info->ldisc_stop_rx = 1; if (I_IXOFF(tty)) { - - //MX_LOCK(&info->slock); - // following add by Victor Yu. 09-02-2002 + /* MX_LOCK(&info->slock); */ + /* following add by Victor Yu. 09-02-2002 */ if (info->IsMoxaMustChipFlag) { info->IER &= ~MOXA_MUST_RECV_ISR; outb(info->IER, info->base + UART_IER); } else { - // above add by Victor Yu. 09-02-2002 - + /* above add by Victor Yu. 09-02-2002 */ info->x_char = STOP_CHAR(tty); - // outb(info->IER, 0); // mask by Victor Yu. 09-02-2002 + /* mask by Victor Yu. 09-02-2002 */ + /* outb(info->IER, 0); */ outb(0, info->base + UART_IER); info->IER |= UART_IER_THRI; - outb(info->IER, info->base + UART_IER); /* force Tx interrupt */ - } // add by Victor Yu. 09-02-2002 - //MX_UNLOCK(&info->slock); + /* force Tx interrupt */ + outb(info->IER, info->base + UART_IER); + } /* add by Victor Yu. 09-02-2002 */ + /* MX_UNLOCK(&info->slock); */ } if (info->tty->termios->c_cflag & CRTSCTS) { - //MX_LOCK(&info->slock); + /* MX_LOCK(&info->slock); */ info->MCR &= ~UART_MCR_RTS; outb(info->MCR, info->base + UART_MCR); - //MX_UNLOCK(&info->slock); + /* MX_UNLOCK(&info->slock); */ } } static void mxser_startrx(struct tty_struct *tty) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; - //unsigned long flags; + struct mxser_struct *info = tty->driver_data; + /* unsigned long flags; */ info->ldisc_stop_rx = 0; if (I_IXOFF(tty)) { if (info->x_char) info->x_char = 0; else { - //MX_LOCK(&info->slock); + /* MX_LOCK(&info->slock); */ - // following add by Victor Yu. 09-02-2002 + /* following add by Victor Yu. 09-02-2002 */ if (info->IsMoxaMustChipFlag) { info->IER |= MOXA_MUST_RECV_ISR; outb(info->IER, info->base + UART_IER); } else { - // above add by Victor Yu. 09-02-2002 + /* above add by Victor Yu. 09-02-2002 */ info->x_char = START_CHAR(tty); - // outb(info->IER, 0); // mask by Victor Yu. 09-02-2002 - outb(0, info->base + UART_IER); // add by Victor Yu. 09-02-2002 - info->IER |= UART_IER_THRI; /* force Tx interrupt */ + /* mask by Victor Yu. 09-02-2002 */ + /* outb(info->IER, 0); */ + /* add by Victor Yu. 09-02-2002 */ + outb(0, info->base + UART_IER); + /* force Tx interrupt */ + info->IER |= UART_IER_THRI; outb(info->IER, info->base + UART_IER); - } // add by Victor Yu. 09-02-2002 - //MX_UNLOCK(&info->slock); + } /* add by Victor Yu. 09-02-2002 */ + /* MX_UNLOCK(&info->slock); */ } } if (info->tty->termios->c_cflag & CRTSCTS) { - //MX_LOCK(&info->slock); + /* MX_LOCK(&info->slock); */ info->MCR |= UART_MCR_RTS; outb(info->MCR, info->base + UART_MCR); - //MX_UNLOCK(&info->slock); + /* MX_UNLOCK(&info->slock); */ } } @@ -1656,48 +1728,53 @@ static void mxser_startrx(struct tty_str */ static void mxser_throttle(struct tty_struct *tty) { - //struct mxser_struct *info = (struct mxser_struct *)tty->driver_data; - //unsigned long flags; - //MX_LOCK(&info->slock); + /* struct mxser_struct *info = tty->driver_data; */ + /* unsigned long flags; */ + + /* MX_LOCK(&info->slock); */ mxser_stoprx(tty); - //MX_UNLOCK(&info->slock); + /* MX_UNLOCK(&info->slock); */ } static void mxser_unthrottle(struct tty_struct *tty) { - //struct mxser_struct *info = (struct mxser_struct *)tty->driver_data; - //unsigned long flags; - //MX_LOCK(&info->slock); + /* struct mxser_struct *info = tty->driver_data; */ + /* unsigned long flags; */ + + /* MX_LOCK(&info->slock); */ mxser_startrx(tty); - //MX_UNLOCK(&info->slock); + /* MX_UNLOCK(&info->slock); */ } static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termios) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; unsigned long flags; - if ((tty->termios->c_cflag != old_termios->c_cflag) || (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { + if ((tty->termios->c_cflag != old_termios->c_cflag) || + (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { mxser_change_speed(info, old_termios); - if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; mxser_start(tty); } } /* Handle sw stopped */ - if ((old_termios->c_iflag & IXON) && !(tty->termios->c_iflag & IXON)) { + if ((old_termios->c_iflag & IXON) && + !(tty->termios->c_iflag & IXON)) { tty->stopped = 0; - // following add by Victor Yu. 09-02-2002 + /* following add by Victor Yu. 09-02-2002 */ if (info->IsMoxaMustChipFlag) { spin_lock_irqsave(&info->slock, flags); DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base); spin_unlock_irqrestore(&info->slock, flags); } - // above add by Victor Yu. 09-02-2002 + /* above add by Victor Yu. 09-02-2002 */ mxser_start(tty); } @@ -1711,7 +1788,7 @@ static void mxser_set_termios(struct tty */ static void mxser_stop(struct tty_struct *tty) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; unsigned long flags; spin_lock_irqsave(&info->slock, flags); @@ -1724,7 +1801,7 @@ static void mxser_stop(struct tty_struct static void mxser_start(struct tty_struct *tty) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; unsigned long flags; spin_lock_irqsave(&info->slock, flags); @@ -1740,7 +1817,7 @@ static void mxser_start(struct tty_struc */ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; unsigned long orig_jiffies, char_time; int lsr; @@ -1777,7 +1854,8 @@ static void mxser_wait_until_sent(struct if (!timeout || timeout > 2 * info->timeout) timeout = 2 * info->timeout; #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", timeout, char_time); + printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", + timeout, char_time); printk("jiff=%lu...", jiffies); #endif while (!((lsr = inb(info->base + UART_LSR)) & UART_LSR_TEMT)) { @@ -1803,7 +1881,7 @@ #endif */ void mxser_hangup(struct tty_struct *tty) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; mxser_flush_buffer(tty); mxser_shutdown(info); @@ -1815,24 +1893,26 @@ void mxser_hangup(struct tty_struct *tty } -// added by James 03-12-2004. +/* added by James 03-12-2004. */ /* * mxser_rs_break() --- routine which turns the break handling on or off */ static void mxser_rs_break(struct tty_struct *tty, int break_state) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; unsigned long flags; spin_lock_irqsave(&info->slock, flags); if (break_state == -1) - outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR); + outb(inb(info->base + UART_LCR) | UART_LCR_SBC, + info->base + UART_LCR); else - outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR); + outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, + info->base + UART_LCR); spin_unlock_irqrestore(&info->slock, flags); } -// (above) added by James. +/* (above) added by James. */ /* @@ -1848,7 +1928,7 @@ static irqreturn_t mxser_interrupt(int i int handled = IRQ_NONE; port = NULL; - //spin_lock(&gm_lock); + /* spin_lock(&gm_lock); */ for (i = 0; i < MXSER_BOARDS; i++) { if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) { @@ -1857,29 +1937,25 @@ static irqreturn_t mxser_interrupt(int i } } - if (i == MXSER_BOARDS) { + if (i == MXSER_BOARDS) goto irq_stop; - } - if (port == 0) { + if (port == 0) goto irq_stop; - } max = mxser_numports[mxsercfg[i].board_type - 1]; while (1) { irqbits = inb(port->vector) & port->vectormask; - if (irqbits == port->vectormask) { + if (irqbits == port->vectormask) break; - } handled = IRQ_HANDLED; for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { - if (irqbits == port->vectormask) { + if (irqbits == port->vectormask) break; - } if (bits & irqbits) continue; info = port + i; - // following add by Victor Yu. 09-13-2002 + /* following add by Victor Yu. 09-13-2002 */ iir = inb(info->base + UART_IIR); if (iir & UART_IIR_NO_INT) continue; @@ -1890,9 +1966,9 @@ static irqreturn_t mxser_interrupt(int i inb(info->base + UART_MSR); continue; } - // above add by Victor Yu. 09-13-2002 + /* above add by Victor Yu. 09-13-2002 */ /* - if ( info->tty->flip.count < TTY_FLIPBUF_SIZE/4 ){ + if (info->tty->flip.count < TTY_FLIPBUF_SIZE / 4) { info->IER |= MOXA_MUST_RECV_ISR; outb(info->IER, info->base + UART_IER); } @@ -1908,18 +1984,15 @@ static irqreturn_t mxser_interrupt(int i status = inb(info->base + UART_LSR) & info->read_status_mask; */ - // following add by Victor Yu. 09-02-2002 + /* following add by Victor Yu. 09-02-2002 */ status = inb(info->base + UART_LSR); - if (status & UART_LSR_PE) { + if (status & UART_LSR_PE) info->err_shadow |= NPPI_NOTIFY_PARITY; - } - if (status & UART_LSR_FE) { + if (status & UART_LSR_FE) info->err_shadow |= NPPI_NOTIFY_FRAMING; - } - if (status & UART_LSR_OE) { + if (status & UART_LSR_OE) info->err_shadow |= NPPI_NOTIFY_HW_OVERRUN; - } if (status & UART_LSR_BI) info->err_shadow |= NPPI_NOTIFY_BREAK; @@ -1930,11 +2003,14 @@ static irqreturn_t mxser_interrupt(int i continue; } */ - if (iir == MOXA_MUST_IIR_GDA || iir == MOXA_MUST_IIR_RDA || iir == MOXA_MUST_IIR_RTO || iir == MOXA_MUST_IIR_LSR) + if (iir == MOXA_MUST_IIR_GDA || + iir == MOXA_MUST_IIR_RDA || + iir == MOXA_MUST_IIR_RTO || + iir == MOXA_MUST_IIR_LSR) mxser_receive_chars(info, &status); } else { - // above add by Victor Yu. 09-02-2002 + /* above add by Victor Yu. 09-02-2002 */ status &= info->read_status_mask; if (status & UART_LSR_DR) @@ -1944,13 +2020,13 @@ static irqreturn_t mxser_interrupt(int i if (msr & UART_MSR_ANY_DELTA) { mxser_check_modem_status(info, msr); } - // following add by Victor Yu. 09-13-2002 + /* following add by Victor Yu. 09-13-2002 */ if (info->IsMoxaMustChipFlag) { if ((iir == 0x02) && (status & UART_LSR_THRE)) { mxser_transmit_chars(info); } } else { - // above add by Victor Yu. 09-13-2002 + /* above add by Victor Yu. 09-13-2002 */ if (status & UART_LSR_THRE) { /* 8-2-99 by William @@ -1966,7 +2042,7 @@ static irqreturn_t mxser_interrupt(int i } irq_stop: - //spin_unlock(&gm_lock); + /* spin_unlock(&gm_lock); */ return handled; } @@ -1984,56 +2060,58 @@ static void mxser_receive_chars(struct m recv_room = tty->receive_room; if ((recv_room == 0) && (!info->ldisc_stop_rx)) { - //mxser_throttle(tty); + /* mxser_throttle(tty); */ mxser_stoprx(tty); - //return; + /* return; */ } - // following add by Victor Yu. 09-02-2002 + /* following add by Victor Yu. 09-02-2002 */ if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) { if (*status & UART_LSR_SPECIAL) { goto intr_old; } - // following add by Victor Yu. 02-11-2004 - if (info->IsMoxaMustChipFlag == MOXA_MUST_MU860_HWID && (*status & MOXA_MUST_LSR_RERR)) + /* following add by Victor Yu. 02-11-2004 */ + if (info->IsMoxaMustChipFlag == MOXA_MUST_MU860_HWID && + (*status & MOXA_MUST_LSR_RERR)) goto intr_old; - // above add by Victor Yu. 02-14-2004 + /* above add by Victor Yu. 02-14-2004 */ if (*status & MOXA_MUST_LSR_RERR) goto intr_old; gdl = inb(info->base + MOXA_MUST_GDL_REGISTER); - if (info->IsMoxaMustChipFlag == MOXA_MUST_MU150_HWID) // add by Victor Yu. 02-11-2004 + /* add by Victor Yu. 02-11-2004 */ + if (info->IsMoxaMustChipFlag == MOXA_MUST_MU150_HWID) gdl &= MOXA_MUST_GDL_MASK; if (gdl >= recv_room) { if (!info->ldisc_stop_rx) { - //mxser_throttle(tty); + /* mxser_throttle(tty); */ mxser_stoprx(tty); } - //return; + /* return; */ } while (gdl--) { ch = inb(info->base + UART_RX); tty_insert_flip_char(tty, ch, 0); cnt++; /* - if((cnt>=HI_WATER) && (info->stop_rx==0)){ + if ((cnt >= HI_WATER) && (info->stop_rx == 0)) { mxser_stoprx(tty); - info->stop_rx=1; + info->stop_rx = 1; break; } */ } goto end_intr; } -intr_old: - // above add by Victor Yu. 09-02-2002 + intr_old: + /* above add by Victor Yu. 09-02-2002 */ do { if (max-- < 0) break; /* - if((cnt>=HI_WATER) && (info->stop_rx==0)){ + if ((cnt >= HI_WATER) && (info->stop_rx == 0)) { mxser_stoprx(tty); info->stop_rx=1; break; @@ -2041,11 +2119,11 @@ intr_old: */ ch = inb(info->base + UART_RX); - // following add by Victor Yu. 09-02-2002 + /* following add by Victor Yu. 09-02-2002 */ if (info->IsMoxaMustChipFlag && (*status & UART_LSR_OE) /*&& !(*status&UART_LSR_DR) */ ) outb(0x23, info->base + UART_FCR); *status &= info->read_status_mask; - // above add by Victor Yu. 09-02-2002 + /* above add by Victor Yu. 09-02-2002 */ if (*status & info->ignore_status_mask) { if (++ignored > 100) break; @@ -2080,7 +2158,7 @@ intr_old: cnt++; if (cnt >= recv_room) { if (!info->ldisc_stop_rx) { - //mxser_throttle(tty); + /* mxser_throttle(tty); */ mxser_stoprx(tty); } break; @@ -2088,21 +2166,20 @@ intr_old: } - // following add by Victor Yu. 09-02-2002 + /* following add by Victor Yu. 09-02-2002 */ if (info->IsMoxaMustChipFlag) break; - // above add by Victor Yu. 09-02-2002 + /* above add by Victor Yu. 09-02-2002 */ /* mask by Victor Yu. 09-02-2002 *status = inb(info->base + UART_LSR) & info->read_status_mask; */ - // following add by Victor Yu. 09-02-2002 + /* following add by Victor Yu. 09-02-2002 */ *status = inb(info->base + UART_LSR); - // above add by Victor Yu. 09-02-2002 + /* above add by Victor Yu. 09-02-2002 */ } while (*status & UART_LSR_DR); -end_intr: // add by Victor Yu. 09-02-2002 - +end_intr: /* add by Victor Yu. 09-02-2002 */ mxvar_log.rxcnt[info->port] += cnt; info->mon_data.rxcnt += cnt; info->mon_data.up_rxcnt += cnt; @@ -2137,7 +2214,10 @@ static void mxser_transmit_chars(struct return; } - if ((info->xmit_cnt <= 0) || info->tty->stopped || (info->tty->hw_stopped && (info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag))) { + if ((info->xmit_cnt <= 0) || info->tty->stopped || + (info->tty->hw_stopped && + (info->type != PORT_16550A) && + (!info->IsMoxaMustChipFlag))) { info->IER &= ~UART_IER_THRI; outb(info->IER, info->base + UART_IER); spin_unlock_irqrestore(&info->slock, flags); @@ -2147,17 +2227,18 @@ static void mxser_transmit_chars(struct cnt = info->xmit_cnt; count = info->xmit_fifo_size; do { - outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX); + outb(info->xmit_buf[info->xmit_tail++], + info->base + UART_TX); info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1); if (--info->xmit_cnt <= 0) break; } while (--count > 0); mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt); -// added by James 03-12-2004. +/* added by James 03-12-2004. */ info->mon_data.txcnt += (cnt - info->xmit_cnt); info->mon_data.up_txcnt += (cnt - info->xmit_cnt); -// (above) added by James. +/* (above) added by James. */ /* added by casper 1/11/2000 */ info->icount.tx += (cnt - info->xmit_cnt); @@ -2188,7 +2269,6 @@ static void mxser_check_modem_status(str info->mon_data.modem_status = status; wake_up_interruptible(&info->delta_msr_wait); - if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { if (status & UART_MSR_DCD) wake_up_interruptible(&info->open_wait); @@ -2200,7 +2280,8 @@ static void mxser_check_modem_status(str if (status & UART_MSR_CTS) { info->tty->hw_stopped = 0; - if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) { + if ((info->type != PORT_16550A) && + (!info->IsMoxaMustChipFlag)) { info->IER |= UART_IER_THRI; outb(info->IER, info->base + UART_IER); } @@ -2209,7 +2290,8 @@ static void mxser_check_modem_status(str } else { if (!(status & UART_MSR_CTS)) { info->tty->hw_stopped = 1; - if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) { + if ((info->type != PORT_16550A) && + (!info->IsMoxaMustChipFlag)) { info->IER &= ~UART_IER_THRI; outb(info->IER, info->base + UART_IER); } @@ -2231,7 +2313,7 @@ static int mxser_block_til_ready(struct */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { info->flags |= ASYNC_NORMAL_ACTIVE; - return (0); + return 0; } if (tty->termios->c_cflag & CLOCAL) @@ -2254,7 +2336,8 @@ static int mxser_block_til_ready(struct info->blocked_open++; while (1) { spin_lock_irqsave(&info->slock, flags); - outb(inb(info->base + UART_MCR) | UART_MCR_DTR | UART_MCR_RTS, info->base + UART_MCR); + outb(inb(info->base + UART_MCR) | + UART_MCR_DTR | UART_MCR_RTS, info->base + UART_MCR); spin_unlock_irqrestore(&info->slock, flags); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) { @@ -2264,7 +2347,9 @@ static int mxser_block_til_ready(struct retval = -ERESTARTSYS; break; } - if (!(info->flags & ASYNC_CLOSING) && (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD))) + if (!(info->flags & ASYNC_CLOSING) && + (do_clocal || + (inb(info->base + UART_MSR) & UART_MSR_DCD))) break; if (signal_pending(current)) { retval = -ERESTARTSYS; @@ -2278,27 +2363,26 @@ static int mxser_block_til_ready(struct info->count++; info->blocked_open--; if (retval) - return (retval); + return retval; info->flags |= ASYNC_NORMAL_ACTIVE; - return (0); + return 0; } static int mxser_startup(struct mxser_struct *info) { - unsigned long page; unsigned long flags; page = __get_free_page(GFP_KERNEL); if (!page) - return (-ENOMEM); + return -ENOMEM; spin_lock_irqsave(&info->slock, flags); if (info->flags & ASYNC_INITIALIZED) { free_page(page); spin_unlock_irqrestore(&info->slock, flags); - return (0); + return 0; } if (!info->base || !info->type) { @@ -2306,7 +2390,7 @@ static int mxser_startup(struct mxser_st set_bit(TTY_IO_ERROR, &info->tty->flags); free_page(page); spin_unlock_irqrestore(&info->slock, flags); - return (0); + return 0; } if (info->xmit_buf) free_page(page); @@ -2318,9 +2402,12 @@ static int mxser_startup(struct mxser_st * (they will be reenabled in mxser_change_speed()) */ if (info->IsMoxaMustChipFlag) - outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR); + outb((UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT | + MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR); else - outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR); + outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), + info->base + UART_FCR); /* * At this point there's no way the LSR could still be 0xFF; @@ -2332,9 +2419,9 @@ static int mxser_startup(struct mxser_st if (capable(CAP_SYS_ADMIN)) { if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); - return (0); + return 0; } else - return (-ENODEV); + return -ENODEV; } /* @@ -2356,12 +2443,12 @@ static int mxser_startup(struct mxser_st * Finally, enable interrupts */ info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; -// info->IER = UART_IER_RLSI | UART_IER_RDI; + /* info->IER = UART_IER_RLSI | UART_IER_RDI; */ - // following add by Victor Yu. 08-30-2002 + /* following add by Victor Yu. 08-30-2002 */ if (info->IsMoxaMustChipFlag) info->IER |= MOXA_MUST_IER_EGDAI; - // above add by Victor Yu. 08-30-2002 + /* above add by Victor Yu. 08-30-2002 */ outb(info->IER, info->base + UART_IER); /* enable interrupts */ /* @@ -2383,7 +2470,7 @@ static int mxser_startup(struct mxser_st mxser_change_speed(info, NULL); info->flags |= ASYNC_INITIALIZED; - return (0); + return 0; } /* @@ -2421,12 +2508,15 @@ static void mxser_shutdown(struct mxser_ outb(info->MCR, info->base + UART_MCR); /* clear Rx/Tx FIFO's */ - // following add by Victor Yu. 08-30-2002 + /* following add by Victor Yu. 08-30-2002 */ if (info->IsMoxaMustChipFlag) - outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR); + outb((UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT | + MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR); else - // above add by Victor Yu. 08-30-2002 - outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR); + /* above add by Victor Yu. 08-30-2002 */ + outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), + info->base + UART_FCR); /* read data port to reset things */ (void) inb(info->base + UART_RX); @@ -2436,11 +2526,10 @@ static void mxser_shutdown(struct mxser_ info->flags &= ~ASYNC_INITIALIZED; - // following add by Victor Yu. 09-23-2002 - if (info->IsMoxaMustChipFlag) { + /* following add by Victor Yu. 09-23-2002 */ + if (info->IsMoxaMustChipFlag) SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->base); - } - // above add by Victor Yu. 09-23-2002 + /* above add by Victor Yu. 09-23-2002 */ spin_unlock_irqrestore(&info->slock, flags); } @@ -2457,14 +2546,12 @@ static int mxser_change_speed(struct mxs long baud; unsigned long flags; - if (!info->tty || !info->tty->termios) return ret; cflag = info->tty->termios->c_cflag; if (!(info->base)) return ret; - #ifndef B921600 #define B921600 (B460800 +1) #endif @@ -2559,9 +2646,8 @@ #endif cval |= 0x04; if (cflag & PARENB) cval |= UART_LCR_PARITY; - if (!(cflag & PARODD)) { + if (!(cflag & PARODD)) cval |= UART_LCR_EPAR; - } if (cflag & CMSPAR) cval |= UART_LCR_SPAR; @@ -2574,13 +2660,12 @@ #endif fcr = 0; } else { fcr = UART_FCR_ENABLE_FIFO; - // following add by Victor Yu. 08-30-2002 + /* following add by Victor Yu. 08-30-2002 */ if (info->IsMoxaMustChipFlag) { fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; SET_MOXA_MUST_FIFO_VALUE(info); } else { - // above add by Victor Yu. 08-30-2002 - + /* above add by Victor Yu. 08-30-2002 */ switch (info->rx_trigger) { case 1: fcr |= UART_FCR_TRIGGER_1; @@ -2606,22 +2691,24 @@ #endif info->IER |= UART_IER_MSI; if ((info->type == PORT_16550A) || (info->IsMoxaMustChipFlag)) { info->MCR |= UART_MCR_AFE; - //status = mxser_get_msr(info->base, 0, info->port); -/* save_flags(flags); + /* status = mxser_get_msr(info->base, 0, info->port); */ +/* + save_flags(flags); cli(); status = inb(baseaddr + UART_MSR); - restore_flags(flags);*/ - //mxser_check_modem_status(info, status); + restore_flags(flags); +*/ + /* mxser_check_modem_status(info, status); */ } else { - //status = mxser_get_msr(info->base, 0, info->port); - - //MX_LOCK(&info->slock); + /* status = mxser_get_msr(info->base, 0, info->port); */ + /* MX_LOCK(&info->slock); */ status = inb(info->base + UART_MSR); - //MX_UNLOCK(&info->slock); + /* MX_UNLOCK(&info->slock); */ if (info->tty->hw_stopped) { if (status & UART_MSR_CTS) { info->tty->hw_stopped = 0; - if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) { + if ((info->type != PORT_16550A) && + (!info->IsMoxaMustChipFlag)) { info->IER |= UART_IER_THRI; outb(info->IER, info->base + UART_IER); } @@ -2630,7 +2717,8 @@ #endif } else { if (!(status & UART_MSR_CTS)) { info->tty->hw_stopped = 1; - if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) { + if ((info->type != PORT_16550A) && + (!info->IsMoxaMustChipFlag)) { info->IER &= ~UART_IER_THRI; outb(info->IER, info->base + UART_IER); } @@ -2668,11 +2756,17 @@ #endif * overruns too. (For real raw support). */ if (I_IGNPAR(info->tty)) { - info->ignore_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE; - info->read_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE; + info->ignore_status_mask |= + UART_LSR_OE | + UART_LSR_PE | + UART_LSR_FE; + info->read_status_mask |= + UART_LSR_OE | + UART_LSR_PE | + UART_LSR_FE; } } - // following add by Victor Yu. 09-02-2002 + /* following add by Victor Yu. 09-02-2002 */ if (info->IsMoxaMustChipFlag) { spin_lock_irqsave(&info->slock, flags); SET_MOXA_MUST_XON1_VALUE(info->base, START_CHAR(info->tty)); @@ -2698,7 +2792,7 @@ #endif */ spin_unlock_irqrestore(&info->slock, flags); } - // above add by Victor Yu. 09-02-2002 + /* above add by Victor Yu. 09-02-2002 */ outb(fcr, info->base + UART_FCR); /* set fcr */ @@ -2729,10 +2823,8 @@ static int mxser_set_baud(struct mxser_s quot = (2 * info->baud_base / 269); } else if (newspd) { quot = info->baud_base / newspd; - if (quot == 0) quot = 1; - } else { quot = 0; } @@ -2765,8 +2857,6 @@ static int mxser_set_baud(struct mxser_s return ret; } - - /* * ------------------------------------------------------------ * friends of mxser_ioctl() @@ -2777,7 +2867,7 @@ static int mxser_get_serial_info(struct struct serial_struct tmp; if (!retinfo) - return (-EFAULT); + return -EFAULT; memset(&tmp, 0, sizeof(tmp)); tmp.type = info->type; tmp.line = info->port; @@ -2791,7 +2881,7 @@ static int mxser_get_serial_info(struct tmp.hub6 = 0; if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; - return (0); + return 0; } static int mxser_set_serial_info(struct mxser_struct *info, struct serial_struct __user *new_info) @@ -2801,29 +2891,37 @@ static int mxser_set_serial_info(struct int retval = 0; if (!new_info || !info->base) - return (-EFAULT); + return -EFAULT; if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) return -EFAULT; - if ((new_serial.irq != info->irq) || (new_serial.port != info->base) || (new_serial.custom_divisor != info->custom_divisor) || (new_serial.baud_base != info->baud_base)) - return (-EPERM); + if ((new_serial.irq != info->irq) || + (new_serial.port != info->base) || + (new_serial.custom_divisor != info->custom_divisor) || + (new_serial.baud_base != info->baud_base)) + return -EPERM; flags = info->flags & ASYNC_SPD_MASK; if (!capable(CAP_SYS_ADMIN)) { - if ((new_serial.baud_base != info->baud_base) || (new_serial.close_delay != info->close_delay) || ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK))) - return (-EPERM); - info->flags = ((info->flags & ~ASYNC_USR_MASK) | (new_serial.flags & ASYNC_USR_MASK)); + if ((new_serial.baud_base != info->baud_base) || + (new_serial.close_delay != info->close_delay) || + ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK))) + return -EPERM; + info->flags = ((info->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); } else { /* * OK, past this point, all the error checking has been done. * At this point, we start making changes..... */ - info->flags = ((info->flags & ~ASYNC_FLAGS) | (new_serial.flags & ASYNC_FLAGS)); + info->flags = ((info->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS)); info->close_delay = new_serial.close_delay * HZ / 100; info->closing_wait = new_serial.closing_wait * HZ / 100; - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - info->tty->low_latency = 0; //(info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->tty->low_latency = + (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->tty->low_latency = 0; /* (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; */ } /* added by casper, 3/17/2000, for mouse */ @@ -2831,7 +2929,6 @@ static int mxser_set_serial_info(struct process_txrx_fifo(info); - /* */ if (info->flags & ASYNC_INITIALIZED) { if (flags != (info->flags & ASYNC_SPD_MASK)) { mxser_change_speed(info, NULL); @@ -2839,7 +2936,7 @@ static int mxser_set_serial_info(struct } else { retval = mxser_startup(info); } - return (retval); + return retval; } /* @@ -2876,25 +2973,27 @@ static void mxser_send_break(struct mxse return; set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&info->slock, flags); - outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR); + outb(inb(info->base + UART_LCR) | UART_LCR_SBC, + info->base + UART_LCR); spin_unlock_irqrestore(&info->slock, flags); schedule_timeout(duration); spin_lock_irqsave(&info->slock, flags); - outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR); + outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, + info->base + UART_LCR); spin_unlock_irqrestore(&info->slock, flags); } static int mxser_tiocmget(struct tty_struct *tty, struct file *file) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; unsigned char control, status; unsigned long flags; if (tty->index == MXSER_PORTS) - return (-ENOIOCTLCMD); + return -ENOIOCTLCMD; if (tty->flags & (1 << TTY_IO_ERROR)) - return (-EIO); + return -EIO; control = info->MCR; @@ -2904,12 +3003,16 @@ static int mxser_tiocmget(struct tty_str mxser_check_modem_status(info, status); spin_unlock_irqrestore(&info->slock, flags); return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | - ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); + ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | + ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | + ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | + ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | + ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); } static int mxser_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; + struct mxser_struct *info = tty->driver_data; unsigned long flags; @@ -2968,38 +3071,36 @@ static int mxser_get_ISA_conf(int cap, s hwconf->board_type = MXSER_BOARD_CI104J; hwconf->ports = 4; } else - return (0); + return 0; irq = 0; if (hwconf->ports == 2) { irq = regs[9] & 0xF000; irq = irq | (irq >> 4); if (irq != (regs[9] & 0xFF00)) - return (MXSER_ERR_IRQ_CONFLIT); + return MXSER_ERR_IRQ_CONFLIT; } else if (hwconf->ports == 4) { irq = regs[9] & 0xF000; irq = irq | (irq >> 4); irq = irq | (irq >> 8); if (irq != regs[9]) - return (MXSER_ERR_IRQ_CONFLIT); + return MXSER_ERR_IRQ_CONFLIT; } else if (hwconf->ports == 8) { irq = regs[9] & 0xF000; irq = irq | (irq >> 4); irq = irq | (irq >> 8); if ((irq != regs[9]) || (irq != regs[10])) - return (MXSER_ERR_IRQ_CONFLIT); + return MXSER_ERR_IRQ_CONFLIT; } - if (!irq) { - return (MXSER_ERR_IRQ); - } - hwconf->irq = ((int) (irq & 0xF000) >> 12); + if (!irq) + return MXSER_ERR_IRQ; + hwconf->irq = ((int)(irq & 0xF000) >> 12); for (i = 0; i < 8; i++) hwconf->ioaddr[i] = (int) regs[i + 1] & 0xFFF8; - if ((regs[12] & 0x80) == 0) { - return (MXSER_ERR_VECTOR); - } - hwconf->vector = (int) regs[11]; /* interrupt vector */ + if ((regs[12] & 0x80) == 0) + return MXSER_ERR_VECTOR; + hwconf->vector = (int)regs[11]; /* interrupt vector */ if (id == 1) hwconf->vector_mask = 0x00FF; else @@ -3007,10 +3108,10 @@ static int mxser_get_ISA_conf(int cap, s for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) { if (regs[12] & bits) { hwconf->baud_base[i] = 921600; - hwconf->MaxCanSetBaudRate[i] = 921600; // add by Victor Yu. 09-04-2002 + hwconf->MaxCanSetBaudRate[i] = 921600; /* add by Victor Yu. 09-04-2002 */ } else { hwconf->baud_base[i] = 115200; - hwconf->MaxCanSetBaudRate[i] = 115200; // add by Victor Yu. 09-04-2002 + hwconf->MaxCanSetBaudRate[i] = 115200; /* add by Victor Yu. 09-04-2002 */ } } scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB); @@ -3030,7 +3131,7 @@ static int mxser_get_ISA_conf(int cap, s hwconf->ports = 4; request_region(hwconf->ioaddr[0], 8 * hwconf->ports, "mxser(IO)"); request_region(hwconf->vector, 1, "mxser(vector)"); - return (hwconf->ports); + return hwconf->ports; } #define CHIP_SK 0x01 /* Serial Data Clock in Eprom */ @@ -3053,7 +3154,7 @@ static int mxser_read_register(int port, id = mxser_program_mode(port); if (id < 0) - return (id); + return id; for (i = 0; i < 14; i++) { k = (i & 0x3F) | 0x180; for (j = 0x100; j > 0; j >>= 1) { @@ -3066,7 +3167,7 @@ static int mxser_read_register(int port, outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */ } } - (void) inb(port); + (void)inb(port); value = 0; for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) { outb(CHIP_CS, port); @@ -3078,28 +3179,33 @@ static int mxser_read_register(int port, outb(0, port); } mxser_normal_mode(port); - return (id); + return id; } static int mxser_program_mode(int port) { int id, i, j, n; - //unsigned long flags; + /* unsigned long flags; */ spin_lock(&gm_lock); outb(0, port); outb(0, port); outb(0, port); - (void) inb(port); - (void) inb(port); + (void)inb(port); + (void)inb(port); outb(0, port); - (void) inb(port); - //restore_flags(flags); + (void)inb(port); + /* restore_flags(flags); */ spin_unlock(&gm_lock); id = inb(port + 1) & 0x1F; - if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != C102_ASIC_ID) && (id != CI132_ASIC_ID) && (id != CI134_ASIC_ID) && (id != CI104J_ASIC_ID)) - return (-1); + if ((id != C168_ASIC_ID) && + (id != C104_ASIC_ID) && + (id != C102_ASIC_ID) && + (id != CI132_ASIC_ID) && + (id != CI134_ASIC_ID) && + (id != CI104J_ASIC_ID)) + return -1; for (i = 0, j = 0; i < 4; i++) { n = inb(port + 2); if (n == 'M') { @@ -3112,7 +3218,7 @@ static int mxser_program_mode(int port) } if (j != 2) id = -2; - return (id); + return id; } static void mxser_normal_mode(int port) @@ -3130,7 +3236,7 @@ static void mxser_normal_mode(int port) if ((n & 0x61) == 0x60) break; if ((n & 1) == 1) - (void) inb(port); + (void)inb(port); } outb(0x00, port + 4); } diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index c48de09..203dc2b 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -951,7 +951,8 @@ static void add_msg(struct r3964_client_ { queue_the_message: - pMsg = kmalloc(sizeof(struct r3964_message), GFP_KERNEL); + pMsg = kmalloc(sizeof(struct r3964_message), + error_code?GFP_ATOMIC:GFP_KERNEL); TRACE_M("add_msg - kmalloc %p",pMsg); if(pMsg==NULL) { return; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 0721345..17bc8ab 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -844,7 +844,7 @@ static int bh_action(MGSLPC_INFO *info) return rc; } -void bh_handler(void* Context) +static void bh_handler(void* Context) { MGSLPC_INFO *info = (MGSLPC_INFO*)Context; int action; @@ -888,7 +888,7 @@ void bh_handler(void* Context) __FILE__,__LINE__,info->device_name); } -void bh_transmit(MGSLPC_INFO *info) +static void bh_transmit(MGSLPC_INFO *info) { struct tty_struct *tty = info->tty; if (debug_level >= DEBUG_LEVEL_BH) @@ -900,7 +900,7 @@ void bh_transmit(MGSLPC_INFO *info) } } -void bh_status(MGSLPC_INFO *info) +static void bh_status(MGSLPC_INFO *info) { info->ri_chkcount = 0; info->dsr_chkcount = 0; @@ -1582,7 +1582,7 @@ static void mgslpc_put_char(struct tty_s if (mgslpc_paranoia_check(info, tty->name, "mgslpc_put_char")) return; - if (!tty || !info->tx_buf) + if (!info->tx_buf) return; spin_lock_irqsave(&info->lock,flags); @@ -1649,7 +1649,7 @@ static int mgslpc_write(struct tty_struc __FILE__,__LINE__,info->device_name,count); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_write") || - !tty || !info->tx_buf) + !info->tx_buf) goto cleanup; if (info->params.mode == MGSL_MODE_HDLC) { @@ -2305,7 +2305,7 @@ static int mgslpc_ioctl(struct tty_struc return ioctl_common(info, cmd, arg); } -int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) +static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) { int error; struct mgsl_icount cnow; /* kernel counter temps */ @@ -2877,7 +2877,7 @@ done: return ((count < begin+len-off) ? count : begin+len-off); } -int rx_alloc_buffers(MGSLPC_INFO *info) +static int rx_alloc_buffers(MGSLPC_INFO *info) { /* each buffer has header and data */ info->rx_buf_size = sizeof(RXBUF) + info->max_frame_size; @@ -2900,13 +2900,13 @@ int rx_alloc_buffers(MGSLPC_INFO *info) return 0; } -void rx_free_buffers(MGSLPC_INFO *info) +static void rx_free_buffers(MGSLPC_INFO *info) { kfree(info->rx_buf); info->rx_buf = NULL; } -int claim_resources(MGSLPC_INFO *info) +static int claim_resources(MGSLPC_INFO *info) { if (rx_alloc_buffers(info) < 0 ) { printk( "Cant allocate rx buffer %s\n", info->device_name); @@ -2916,7 +2916,7 @@ int claim_resources(MGSLPC_INFO *info) return 0; } -void release_resources(MGSLPC_INFO *info) +static void release_resources(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_INFO) printk("release_resources(%s)\n", info->device_name); @@ -2928,7 +2928,7 @@ void release_resources(MGSLPC_INFO *info * * Arguments: info pointer to device instance data */ -void mgslpc_add_device(MGSLPC_INFO *info) +static void mgslpc_add_device(MGSLPC_INFO *info) { info->next_device = NULL; info->line = mgslpc_device_count; @@ -2964,7 +2964,7 @@ #ifdef CONFIG_HDLC #endif } -void mgslpc_remove_device(MGSLPC_INFO *remove_info) +static void mgslpc_remove_device(MGSLPC_INFO *remove_info) { MGSLPC_INFO *info = mgslpc_device_list; MGSLPC_INFO *last = NULL; @@ -3257,7 +3257,7 @@ static void loopback_enable(MGSLPC_INFO write_reg(info, CHA + MODE, val); } -void hdlc_mode(MGSLPC_INFO *info) +static void hdlc_mode(MGSLPC_INFO *info) { unsigned char val; unsigned char clkmode, clksubmode; @@ -3497,7 +3497,7 @@ void hdlc_mode(MGSLPC_INFO *info) rx_stop(info); } -void rx_stop(MGSLPC_INFO *info) +static void rx_stop(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):rx_stop(%s)\n", @@ -3510,7 +3510,7 @@ void rx_stop(MGSLPC_INFO *info) info->rx_overflow = 0; } -void rx_start(MGSLPC_INFO *info) +static void rx_start(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):rx_start(%s)\n", @@ -3526,7 +3526,7 @@ void rx_start(MGSLPC_INFO *info) info->rx_enabled = 1; } -void tx_start(MGSLPC_INFO *info) +static void tx_start(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):tx_start(%s)\n", @@ -3564,7 +3564,7 @@ void tx_start(MGSLPC_INFO *info) info->tx_enabled = 1; } -void tx_stop(MGSLPC_INFO *info) +static void tx_stop(MGSLPC_INFO *info) { if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):tx_stop(%s)\n", @@ -3578,7 +3578,7 @@ void tx_stop(MGSLPC_INFO *info) /* Reset the adapter to a known state and prepare it for further use. */ -void reset_device(MGSLPC_INFO *info) +static void reset_device(MGSLPC_INFO *info) { /* power up both channels (set BIT7) */ write_reg(info, CHA + CCR0, 0x80); @@ -3628,7 +3628,7 @@ void reset_device(MGSLPC_INFO *info) write_reg(info, IPC, 0x05); } -void async_mode(MGSLPC_INFO *info) +static void async_mode(MGSLPC_INFO *info) { unsigned char val; @@ -3799,7 +3799,7 @@ void async_mode(MGSLPC_INFO *info) /* Set the HDLC idle mode for the transmitter. */ -void tx_set_idle(MGSLPC_INFO *info) +static void tx_set_idle(MGSLPC_INFO *info) { /* Note: ESCC2 only supports flags and one idle modes */ if (info->idle_mode == HDLC_TXIDLE_FLAGS) @@ -3810,7 +3810,7 @@ void tx_set_idle(MGSLPC_INFO *info) /* get state of the V24 status (input) signals. */ -void get_signals(MGSLPC_INFO *info) +static void get_signals(MGSLPC_INFO *info) { unsigned char status = 0; @@ -3832,7 +3832,7 @@ void get_signals(MGSLPC_INFO *info) /* Set the state of DTR and RTS based on contents of * serial_signals member of device extension. */ -void set_signals(MGSLPC_INFO *info) +static void set_signals(MGSLPC_INFO *info) { unsigned char val; @@ -3856,7 +3856,7 @@ void set_signals(MGSLPC_INFO *info) set_reg_bits(info, CHA + PVR, PVR_DTR); } -void rx_reset_buffers(MGSLPC_INFO *info) +static void rx_reset_buffers(MGSLPC_INFO *info) { RXBUF *buf; int i; @@ -3875,7 +3875,7 @@ void rx_reset_buffers(MGSLPC_INFO *info) * * Returns 1 if frame returned, otherwise 0 */ -int rx_get_frame(MGSLPC_INFO *info) +static int rx_get_frame(MGSLPC_INFO *info) { unsigned short status; RXBUF *buf; @@ -3961,7 +3961,7 @@ #endif return 1; } -BOOLEAN register_test(MGSLPC_INFO *info) +static BOOLEAN register_test(MGSLPC_INFO *info) { static unsigned char patterns[] = { 0x00, 0xff, 0xaa, 0x55, 0x69, 0x96, 0x0f }; @@ -3987,7 +3987,7 @@ BOOLEAN register_test(MGSLPC_INFO *info) return rc; } -BOOLEAN irq_test(MGSLPC_INFO *info) +static BOOLEAN irq_test(MGSLPC_INFO *info) { unsigned long end_time; unsigned long flags; @@ -4022,7 +4022,7 @@ BOOLEAN irq_test(MGSLPC_INFO *info) return info->irq_occurred ? TRUE : FALSE; } -int adapter_test(MGSLPC_INFO *info) +static int adapter_test(MGSLPC_INFO *info) { if (!register_test(info)) { info->init_error = DiagStatus_AddressFailure; @@ -4044,7 +4044,7 @@ int adapter_test(MGSLPC_INFO *info) return 0; } -void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit) +static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit) { int i; int linecount; @@ -4079,7 +4079,7 @@ void trace_block(MGSLPC_INFO *info,const /* HDLC frame time out * update stats and do tx completion processing */ -void tx_timeout(unsigned long context) +static void tx_timeout(unsigned long context) { MGSLPC_INFO *info = (MGSLPC_INFO*)context; unsigned long flags; diff --git a/drivers/char/rio/daemon.h b/drivers/char/rio/daemon.h index 5818a8a..6e63f8b 100644 --- a/drivers/char/rio/daemon.h +++ b/drivers/char/rio/daemon.h @@ -51,7 +51,7 @@ struct Error { }; struct DownLoad { - char *DataP; + char __user *DataP; unsigned int Count; unsigned int ProductCode; }; @@ -83,18 +83,18 @@ struct PortSetup { struct LpbReq { unsigned int Host; unsigned int Link; - struct LPB *LpbP; + struct LPB __user *LpbP; }; struct RupReq { unsigned int HostNum; unsigned int RupNum; - struct RUP *RupP; + struct RUP __user *RupP; }; struct PortReq { unsigned int SysPort; - struct Port *PortP; + struct Port __user *PortP; }; struct StreamInfo { @@ -105,12 +105,12 @@ struct StreamInfo { struct HostReq { unsigned int HostNum; - struct Host *HostP; + struct Host __user *HostP; }; struct HostDpRam { unsigned int HostNum; - struct DpRam *DpRamP; + struct DpRam __user *DpRamP; }; struct DebugCtrl { diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h index e64fe99..6b03918 100644 --- a/drivers/char/rio/func.h +++ b/drivers/char/rio/func.h @@ -46,7 +46,7 @@ int RIOBootCodeRTA(struct rio_info *, st int RIOBootCodeHOST(struct rio_info *, struct DownLoad *); int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *); void msec_timeout(struct Host *); -int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT *); +int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *); int RIOBootOk(struct rio_info *, struct Host *, unsigned long); int RIORtaBound(struct rio_info *, unsigned int); void rio_fill_host_slot(int, int, unsigned int, struct Host *); @@ -55,8 +55,8 @@ void rio_fill_host_slot(int, int, unsign int RIOFoadRta(struct Host *, struct Map *); int RIOZombieRta(struct Host *, struct Map *); int RIOCommandRta(struct rio_info *, unsigned long, int (*func) (struct Host *, struct Map *)); -int RIOIdentifyRta(struct rio_info *, void *); -int RIOKillNeighbour(struct rio_info *, void *); +int RIOIdentifyRta(struct rio_info *, void __user *); +int RIOKillNeighbour(struct rio_info *, void __user *); int RIOSuspendBootRta(struct Host *, int, int); int RIOFoadWakeup(struct rio_info *); struct CmdBlk *RIOGetCmdBlk(void); @@ -68,7 +68,8 @@ int RIORFlushEnable(unsigned long, struc int RIOUnUse(unsigned long, struct CmdBlk *); /* rioctrl.c */ -int riocontrol(struct rio_info *, dev_t, int, caddr_t, int); +int riocontrol(struct rio_info *, dev_t, int, unsigned long, int); + int RIOPreemptiveCmd(struct rio_info *, struct Port *, unsigned char); /* rioinit.c */ @@ -77,13 +78,13 @@ void RIOInitHosts(struct rio_info *, str void RIOISAinit(struct rio_info *, int); int RIODoAT(struct rio_info *, int, int); caddr_t RIOCheckForATCard(int); -int RIOAssignAT(struct rio_info *, int, caddr_t, int); -int RIOBoardTest(unsigned long, caddr_t, unsigned char, int); +int RIOAssignAT(struct rio_info *, int, void __iomem *, int); +int RIOBoardTest(unsigned long, void __iomem *, unsigned char, int); void RIOAllocDataStructs(struct rio_info *); void RIOSetupDataStructs(struct rio_info *); int RIODefaultName(struct rio_info *, struct Host *, unsigned int); struct rioVersion *RIOVersid(void); -void RIOHostReset(unsigned int, struct DpRam *, unsigned int); +void RIOHostReset(unsigned int, struct DpRam __iomem *, unsigned int); /* riointr.c */ void RIOTxEnable(char *); @@ -95,14 +96,14 @@ int RIOParam(struct Port *, int, int, in int RIODelay(struct Port *PortP, int); int RIODelay_ni(struct Port *PortP, int); void ms_timeout(struct Port *); -int can_add_transmit(struct PKT **, struct Port *); +int can_add_transmit(struct PKT __iomem **, struct Port *); void add_transmit(struct Port *); -void put_free_end(struct Host *, struct PKT *); -int can_remove_receive(struct PKT **, struct Port *); +void put_free_end(struct Host *, struct PKT __iomem *); +int can_remove_receive(struct PKT __iomem **, struct Port *); void remove_receive(struct Port *); /* rioroute.c */ -int RIORouteRup(struct rio_info *, unsigned int, struct Host *, struct PKT *); +int RIORouteRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *); void RIOFixPhbs(struct rio_info *, struct Host *, unsigned int); unsigned int GetUnitType(unsigned int); int RIOSetChange(struct rio_info *); @@ -139,7 +140,7 @@ int rio_isr_thread(char *); struct rio_info *rio_info_store(int cmd, struct rio_info *p); #endif -extern void rio_copy_to_card(void *to, void *from, int len); +extern void rio_copy_to_card(void *from, void __iomem *to, int len); extern int rio_minor(struct tty_struct *tty); extern int rio_ismodem(struct tty_struct *tty); diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h index 179cdbe..ee2ddea 100644 --- a/drivers/char/rio/host.h +++ b/drivers/char/rio/host.h @@ -48,8 +48,8 @@ struct Host { unsigned char Ivec; /* POLLED or ivec number */ unsigned char Mode; /* Control stuff */ unsigned char Slot; /* Slot */ - caddr_t Caddr; /* KV address of DPRAM */ - struct DpRam *CardP; /* KV address of DPRAM, with overlay */ + void __iomem *Caddr; /* KV address of DPRAM */ + struct DpRam __iomem *CardP; /* KV address of DPRAM, with overlay */ unsigned long PaddrP; /* Phys. address of DPRAM */ char Name[MAX_NAME_LEN]; /* The name of the host */ unsigned int UniqueNum; /* host unique number */ @@ -57,7 +57,7 @@ struct Host { unsigned int WorkToBeDone; /* set to true each interrupt */ unsigned int InIntr; /* Being serviced? */ unsigned int IntSrvDone; /* host's interrupt has been serviced */ - void (*Copy) (void *, void *, int); /* copy func */ + void (*Copy) (void *, void __iomem *, int); /* copy func */ struct timer_list timer; /* ** I M P O R T A N T ! @@ -83,11 +83,11 @@ #define RC_BOOT_NONE 0x20 /* D struct Top Topology[LINKS_PER_UNIT]; /* one per link */ struct Map Mapping[MAX_RUP]; /* Mappings for host */ - struct PHB *PhbP; /* Pointer to the PHB array */ - unsigned short *PhbNumP; /* Ptr to Number of PHB's */ - struct LPB *LinkStrP; /* Link Structure Array */ - struct RUP *RupP; /* Sixteen real rups here */ - struct PARM_MAP *ParmMapP; /* points to the parmmap */ + struct PHB __iomem *PhbP; /* Pointer to the PHB array */ + unsigned short __iomem *PhbNumP; /* Ptr to Number of PHB's */ + struct LPB __iomem *LinkStrP; /* Link Structure Array */ + struct RUP __iomem *RupP; /* Sixteen real rups here */ + struct PARM_MAP __iomem *ParmMapP; /* points to the parmmap */ unsigned int ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */ unsigned int NumExtraBooted; /* how many of the above */ /* diff --git a/drivers/char/rio/port.h b/drivers/char/rio/port.h index 9b5fa3e..49cf6d1 100644 --- a/drivers/char/rio/port.h +++ b/drivers/char/rio/port.h @@ -40,7 +40,7 @@ struct Port { struct gs_port gs; int PortNum; /* RIO port no., 0-511 */ struct Host *HostP; - caddr_t Caddr; + void __iomem *Caddr; unsigned short HostPort; /* Port number on host card */ unsigned char RupNum; /* Number of RUP for port */ unsigned char ID2; /* Second ID of RTA for port */ @@ -92,13 +92,13 @@ #define RIO_CTSFLOW 0x0200 /* RIO's own #define RIO_RTSFLOW 0x0400 /* RIO's own RTSFLOW flag */ - struct PHB *PhbP; /* pointer to PHB for port */ - u16 *TxAdd; /* Add packets here */ - u16 *TxStart; /* Start of add array */ - u16 *TxEnd; /* End of add array */ - u16 *RxRemove; /* Remove packets here */ - u16 *RxStart; /* Start of remove array */ - u16 *RxEnd; /* End of remove array */ + struct PHB __iomem *PhbP; /* pointer to PHB for port */ + u16 __iomem *TxAdd; /* Add packets here */ + u16 __iomem *TxStart; /* Start of add array */ + u16 __iomem *TxEnd; /* End of add array */ + u16 __iomem *RxRemove; /* Remove packets here */ + u16 __iomem *RxStart; /* Start of remove array */ + u16 __iomem *RxEnd; /* End of remove array */ unsigned int RtaUniqueNum; /* Unique number of RTA */ unsigned short PortState; /* status of port */ unsigned short ModemState; /* status of modem lines */ diff --git a/drivers/char/rio/rio.h b/drivers/char/rio/rio.h index b4c9187..1bf3622 100644 --- a/drivers/char/rio/rio.h +++ b/drivers/char/rio/rio.h @@ -129,8 +129,8 @@ #define COOK_RAW 2 ** RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and ** returns the offset into the DP RAM area. */ -#define RIO_PTR(C,O) (((unsigned char *)(C))+(0xFFFF&(O))) -#define RIO_OFF(C,O) ((long)(O)-(long)(C)) +#define RIO_PTR(C,O) (((unsigned char __iomem *)(C))+(0xFFFF&(O))) +#define RIO_OFF(C,O) ((unsigned char __iomem *)(O)-(unsigned char __iomem *)(C)) /* ** How to convert from various different device number formats: diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 78dd856..aa43436 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -333,9 +333,9 @@ int RIODelay_ni(struct Port *PortP, int return !RIO_FAIL; } -void rio_copy_to_card(void *to, void *from, int len) +void rio_copy_to_card(void *from, void __iomem *to, int len) { - rio_memcpy_toio(NULL, to, from, len); + rio_copy_toio(to, from, len); } int rio_minor(struct tty_struct *tty) @@ -573,7 +573,7 @@ static int rio_fw_ioctl(struct inode *in func_enter(); /* The "dev" argument isn't used. */ - rc = riocontrol(p, 0, cmd, (void *) arg, capable(CAP_SYS_ADMIN)); + rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN)); func_exit(); return rc; @@ -583,6 +583,7 @@ extern int RIOShortCommand(struct rio_in static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg) { + void __user *argp = (void __user *)arg; int rc; struct Port *PortP; int ival; @@ -594,14 +595,14 @@ static int rio_ioctl(struct tty_struct * rc = 0; switch (cmd) { case TIOCSSOFTCAR: - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { + if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) { tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); } break; case TIOCGSERIAL: rc = -EFAULT; - if (access_ok(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct))) - rc = gs_getserial(&PortP->gs, (struct serial_struct *) arg); + if (access_ok(VERIFY_WRITE, argp, sizeof(struct serial_struct))) + rc = gs_getserial(&PortP->gs, argp); break; case TCSBRK: if (PortP->State & RIO_DELETED) { @@ -631,8 +632,8 @@ static int rio_ioctl(struct tty_struct * break; case TIOCSSERIAL: rc = -EFAULT; - if (access_ok(VERIFY_READ, (void *) arg, sizeof(struct serial_struct))) - rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg); + if (access_ok(VERIFY_READ, argp, sizeof(struct serial_struct))) + rc = gs_setserial(&PortP->gs, argp); break; default: rc = -ENOIOCTLCMD; @@ -919,7 +920,7 @@ #ifdef CONFIG_PCI static void fix_rio_pci(struct pci_dev *pdev) { unsigned long hwbase; - unsigned char *rebase; + unsigned char __iomem *rebase; unsigned int t; #define CNTRL_REG_OFFSET 0x50 @@ -999,7 +1000,7 @@ #ifdef CONFIG_PCI if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); - hp->CardP = (struct DpRam *) hp->Caddr; + hp->CardP = (struct DpRam __iomem *) hp->Caddr; hp->Type = RIO_PCI; hp->Copy = rio_copy_to_card; hp->Mode = RIO_PCI_BOOT_FROM_RAM; @@ -1021,7 +1022,7 @@ #ifdef CONFIG_PCI p->RIONumHosts++; found++; } else { - iounmap((char *) (p->RIOHosts[p->RIONumHosts].Caddr)); + iounmap(p->RIOHosts[p->RIONumHosts].Caddr); } } @@ -1047,7 +1048,7 @@ #ifdef CONFIG_RIO_OLDPCI hp->Ivec = 0; hp->Ivec |= 0x8000; /* Mark as non-sharable */ hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); - hp->CardP = (struct DpRam *) hp->Caddr; + hp->CardP = (struct DpRam __iomem *) hp->Caddr; hp->Type = RIO_PCI; hp->Copy = rio_copy_to_card; hp->Mode = RIO_PCI_BOOT_FROM_RAM; @@ -1070,7 +1071,7 @@ #ifdef CONFIG_RIO_OLDPCI p->RIONumHosts++; found++; } else { - iounmap((char *) (p->RIOHosts[p->RIONumHosts].Caddr)); + iounmap(p->RIOHosts[p->RIONumHosts].Caddr); } #else printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n"); @@ -1085,7 +1086,7 @@ #endif /* PCI */ /* There was something about the IRQs of these cards. 'Forget what.--REW */ hp->Ivec = 0; hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); - hp->CardP = (struct DpRam *) hp->Caddr; + hp->CardP = (struct DpRam __iomem *) hp->Caddr; hp->Type = RIO_AT; hp->Copy = rio_copy_to_card; /* AT card PCI???? - PVDL * -- YES! this is now a normal copy. Only the @@ -1111,7 +1112,7 @@ #endif /* PCI */ } if (!okboard) - iounmap((char *) (hp->Caddr)); + iounmap(hp->Caddr); } } diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h index 4ce77fb..55b9c97 100644 --- a/drivers/char/rio/rio_linux.h +++ b/drivers/char/rio/rio_linux.h @@ -131,9 +131,9 @@ #endif #ifdef CONFIG_RIO_OLDPCI -static inline void *rio_memcpy_toio(void *dummy, void *dest, void *source, int n) +static inline void __iomem *rio_memcpy_toio(void __iomem *dummy, void __iomem *dest, void *source, int n) { - char *dst = dest; + char __iomem *dst = dest; char *src = source; while (n--) { @@ -144,11 +144,22 @@ static inline void *rio_memcpy_toio(void return dest; } +static inline void __iomem *rio_copy_toio(void __iomem *dest, void *source, int n) +{ + char __iomem *dst = dest; + char *src = source; + + while (n--) + writeb(*src++, dst++); -static inline void *rio_memcpy_fromio(void *dest, void *source, int n) + return dest; +} + + +static inline void *rio_memcpy_fromio(void *dest, void __iomem *source, int n) { char *dst = dest; - char *src = source; + char __iomem *src = source; while (n--) *dst++ = readb(src++); @@ -158,6 +169,7 @@ static inline void *rio_memcpy_fromio(vo #else #define rio_memcpy_toio(dummy,dest,source,n) memcpy_toio(dest, source, n) +#define rio_copy_toio memcpy_toio #define rio_memcpy_fromio memcpy_fromio #endif diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c index 290143a..eca2b95 100644 --- a/drivers/char/rio/rioboot.c +++ b/drivers/char/rio/rioboot.c @@ -71,7 +71,7 @@ #include "link.h" #include "cmdblk.h" #include "route.h" -static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd *PktCmdP); +static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP); static const unsigned char RIOAtVec2Ctrl[] = { /* 0 */ INTERRUPT_DISABLE, @@ -204,13 +204,13 @@ void rio_start_card_running(struct Host int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp) { struct Host *HostP; - u8 *Cad; - PARM_MAP *ParmMapP; + u8 __iomem *Cad; + PARM_MAP __iomem *ParmMapP; int RupN; int PortN; unsigned int host; - u8 *StartP; - u8 *DestP; + u8 __iomem *StartP; + u8 __iomem *DestP; int wait_count; u16 OldParmMap; u16 offset; /* It is very important that this is a u16 */ @@ -262,7 +262,7 @@ int RIOBootCodeHOST(struct rio_info *p, ** Ensure that the host really is stopped. ** Disable it's external bus & twang its reset line. */ - RIOHostReset(HostP->Type, (struct DpRam *) HostP->CardP, HostP->Slot); + RIOHostReset(HostP->Type, HostP->CardP, HostP->Slot); /* ** Copy the data directly from user space to the SRAM. @@ -280,7 +280,7 @@ int RIOBootCodeHOST(struct rio_info *p, func_exit(); return -ENOMEM; } - if (copy_from_user(rbp->DataP, DownCode, rbp->Count)) { + if (copy_from_user(DownCode, rbp->DataP, rbp->Count)) { kfree(DownCode); p->RIOError.Error = COPYIN_FAILED; func_exit(); @@ -366,7 +366,7 @@ int RIOBootCodeHOST(struct rio_info *p, ** a short branch to 0x7FF8, where a long branch is coded. */ - DestP = (u8 *) &Cad[0x7FF8]; /* <<<---- READ THE ABOVE COMMENTS */ + DestP = &Cad[0x7FF8]; /* <<<---- READ THE ABOVE COMMENTS */ #define NFIX(N) (0x60 | (N)) /* .O = (~(.O + N))<<4 */ #define PFIX(N) (0x20 | (N)) /* .O = (.O + N)<<4 */ @@ -438,7 +438,7 @@ #define JUMP(N) (0x00 | (N)) /* .PC = rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n"); HostP->Flags &= ~RUN_STATE; HostP->Flags |= RC_STUFFED; - RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot ); + RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot ); continue; } @@ -453,9 +453,9 @@ #define JUMP(N) (0x00 | (N)) /* .PC = /* ** Grab a 32 bit pointer to the parmmap structure */ - ParmMapP = (PARM_MAP *) RIO_PTR(Cad, readw(&HostP->__ParmMapR)); + ParmMapP = (PARM_MAP __iomem *) RIO_PTR(Cad, readw(&HostP->__ParmMapR)); rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP); - ParmMapP = (PARM_MAP *) ((unsigned long) Cad + readw(&HostP->__ParmMapR)); + ParmMapP = (PARM_MAP __iomem *)(Cad + readw(&HostP->__ParmMapR)); rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP); /* @@ -468,7 +468,7 @@ #define JUMP(N) (0x00 | (N)) /* .PC = rio_dprintk(RIO_DEBUG_BOOT, "Links = 0x%x\n", readw(&ParmMapP->links)); HostP->Flags &= ~RUN_STATE; HostP->Flags |= RC_STUFFED; - RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot ); + RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot ); continue; } @@ -491,7 +491,7 @@ #define JUMP(N) (0x00 | (N)) /* .PC = rio_dprintk(RIO_DEBUG_BOOT, "Timedout waiting for init_done\n"); HostP->Flags &= ~RUN_STATE; HostP->Flags |= RC_STUFFED; - RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot ); + RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot ); continue; } @@ -512,10 +512,10 @@ #define JUMP(N) (0x00 | (N)) /* .PC = ** 32 bit pointers for the driver in ioremap space. */ HostP->ParmMapP = ParmMapP; - HostP->PhbP = (struct PHB *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr)); - HostP->RupP = (struct RUP *) RIO_PTR(Cad, readw(&ParmMapP->rups)); - HostP->PhbNumP = (unsigned short *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr)); - HostP->LinkStrP = (struct LPB *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr)); + HostP->PhbP = (struct PHB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr)); + HostP->RupP = (struct RUP __iomem *) RIO_PTR(Cad, readw(&ParmMapP->rups)); + HostP->PhbNumP = (unsigned short __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr)); + HostP->LinkStrP = (struct LPB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr)); /* ** point the UnixRups at the real Rups @@ -540,7 +540,7 @@ #define JUMP(N) (0x00 | (N)) /* .PC = for (PortN = p->RIOFirstPortsMapped; PortN < p->RIOLastPortsMapped + PORTS_PER_RTA; PortN++) { if (p->RIOPortp[PortN]->HostP == HostP) { struct Port *PortP = p->RIOPortp[PortN]; - struct PHB *PhbP; + struct PHB __iomem *PhbP; /* int oldspl; */ if (!PortP->Mapped) @@ -551,12 +551,12 @@ #define JUMP(N) (0x00 | (N)) /* .PC = PortP->PhbP = PhbP; - PortP->TxAdd = (u16 *) RIO_PTR(Cad, readw(&PhbP->tx_add)); - PortP->TxStart = (u16 *) RIO_PTR(Cad, readw(&PhbP->tx_start)); - PortP->TxEnd = (u16 *) RIO_PTR(Cad, readw(&PhbP->tx_end)); - PortP->RxRemove = (u16 *) RIO_PTR(Cad, readw(&PhbP->rx_remove)); - PortP->RxStart = (u16 *) RIO_PTR(Cad, readw(&PhbP->rx_start)); - PortP->RxEnd = (u16 *) RIO_PTR(Cad, readw(&PhbP->rx_end)); + PortP->TxAdd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_add)); + PortP->TxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_start)); + PortP->TxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_end)); + PortP->RxRemove = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_remove)); + PortP->RxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_start)); + PortP->RxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_end)); rio_spin_unlock_irqrestore(&PortP->portSem, flags); /* @@ -601,9 +601,9 @@ #define JUMP(N) (0x00 | (N)) /* .PC = * return 1. If we havent, then return 0. */ -int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT *PacketP) +int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem *PacketP) { - struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data; + struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data; struct PktCmd_M *PktReplyP; struct CmdBlk *CmdBlkP; unsigned int sequence; @@ -722,7 +722,7 @@ int RIOBootRup(struct rio_info *p, unsig * RtaUniq is the booted RTA. */ -static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd *PktCmdP) +static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP) { struct Map *MapP = NULL; struct Map *MapP2 = NULL; diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index e6d2b14..4df6ab2 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c @@ -180,7 +180,7 @@ int RIOCommandRta(struct rio_info *p, un } -int RIOIdentifyRta(struct rio_info *p, void * arg) +int RIOIdentifyRta(struct rio_info *p, void __user * arg) { unsigned int Host; @@ -245,7 +245,7 @@ int RIOIdentifyRta(struct rio_info *p, v } -int RIOKillNeighbour(struct rio_info *p, void * arg) +int RIOKillNeighbour(struct rio_info *p, void __user * arg) { uint Host; uint ID; @@ -370,9 +370,9 @@ int RIOFoadWakeup(struct rio_info *p) /* ** Incoming command on the COMMAND_RUP to be processed. */ -static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struct PKT * PacketP) +static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struct PKT __iomem *PacketP) { - struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data; + struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *)PacketP->data; struct Port *PortP; struct UnixRup *UnixRupP; unsigned short SysPort; @@ -407,12 +407,12 @@ static int RIOCommandRup(struct rio_info } else rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name); - rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", PacketP->dest_unit, PacketP->dest_port); - rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source 0x%x:0x%x\n", PacketP->src_unit, PacketP->src_port); - rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", PacketP->len, PacketP->len); - rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", PacketP->control, PacketP->control); - rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", PacketP->csum, PacketP->csum); - rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command); + rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", readb(&PacketP->dest_unit), readb(&PacketP->dest_port)); + rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source 0x%x:0x%x\n", readb(&PacketP->src_unit), readb(&PacketP->src_port)); + rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", readb(&PacketP->len), readb(&PacketP->len)); + rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", readb(&PacketP->control), readb(&PacketP->control)); + rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", readw(&PacketP->csum), readw(&PacketP->csum)); + rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", readb(&PktCmdP->PhbNum), readb(&PktCmdP->Command)); return 1; } PortP = p->RIOPortp[SysPort]; @@ -601,7 +601,7 @@ int RIOQueueCmdBlk(struct Host *HostP, u /* ** Whammy! blat that pack! */ - HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(struct PKT)); + HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT)); /* ** place command packet on the pending position. @@ -655,7 +655,7 @@ void RIOPollHostCommands(struct rio_info { struct CmdBlk *CmdBlkP; struct UnixRup *UnixRupP; - struct PKT *PacketP; + struct PKT __iomem *PacketP; unsigned short Rup; unsigned long flags; @@ -676,7 +676,7 @@ void RIOPollHostCommands(struct rio_info if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) { int FreeMe; - PacketP = (struct PKT *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt)); + PacketP = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt)); switch (readb(&PacketP->dest_port)) { case BOOT_RUP: @@ -694,9 +694,9 @@ void RIOPollHostCommands(struct rio_info */ rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); FreeMe = RIOCommandRup(p, Rup, HostP, PacketP); - if (PacketP->data[5] == MEMDUMP) { - rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", *(unsigned short *) & (PacketP->data[6])); - HostP->Copy((caddr_t) & (PacketP->data[8]), (caddr_t) p->RIOMemDump, 32); + if (readb(&PacketP->data[5]) == MEMDUMP) { + rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6]))); + rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32); } rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); break; @@ -782,7 +782,7 @@ void RIOPollHostCommands(struct rio_info /* ** Whammy! blat that pack! */ - HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(struct PKT)); + HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT)); /* ** remove the command from the rup command queue... @@ -824,7 +824,7 @@ int RIOWFlushMark(unsigned long iPortP, int RIORFlushEnable(unsigned long iPortP, struct CmdBlk *CmdBlkP) { struct Port *PortP = (struct Port *) iPortP; - struct PKT *PacketP; + struct PKT __iomem *PacketP; unsigned long flags; rio_spin_lock_irqsave(&PortP->portSem, flags); diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c index 75b2557..052e812 100644 --- a/drivers/char/rio/rioctrl.c +++ b/drivers/char/rio/rioctrl.c @@ -80,7 +80,7 @@ #include "rioioctl.h" static struct LpbReq LpbReq; static struct RupReq RupReq; static struct PortReq PortReq; -static struct HostReq HostReq; +static struct HostReq HostReq; /* oh really? global? and no locking? */ static struct HostDpRam HostDpRam; static struct DebugCtrl DebugCtrl; static struct Map MapEnt; @@ -126,12 +126,19 @@ static int #define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff)) -int riocontrol(p, dev, cmd, arg, su) -struct rio_info *p; -dev_t dev; -int cmd; -caddr_t arg; -int su; +static int copy_from_io(void __user *to, void __iomem *from, size_t size) +{ + void *buf = kmalloc(size, GFP_KERNEL); + int res = -ENOMEM; + if (buf) { + rio_memcpy_fromio(buf, from, size); + res = copy_to_user(to, buf, size); + kfree(buf); + } + return res; +} + +int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su) { uint Host; /* leave me unsigned! */ uint port; /* and me! */ @@ -139,9 +146,10 @@ int su; ushort loop; int Entry; struct Port *PortP; - struct PKT *PacketP; + struct PKT __iomem *PacketP; int retval = 0; unsigned long flags; + void __user *argp = (void __user *)arg; func_enter(); @@ -149,7 +157,7 @@ int su; Host = 0; PortP = NULL; - rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, arg); + rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, argp); switch (cmd) { /* @@ -160,11 +168,11 @@ int su; ** otherwise just the specified host card will be changed. */ case RIO_SET_TIMER: - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", (unsigned long)arg); + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", arg); { int host, value; - host = ((unsigned long) arg >> 16) & 0x0000FFFF; - value = (unsigned long) arg & 0x0000ffff; + host = (arg >> 16) & 0x0000FFFF; + value = arg & 0x0000ffff; if (host == -1) { for (host = 0; host < p->RIONumHosts; host++) { if (p->RIOHosts[host].Flags == RC_RUNNING) { @@ -183,26 +191,26 @@ int su; case RIO_FOAD_RTA: rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n"); - return RIOCommandRta(p, (unsigned long)arg, RIOFoadRta); + return RIOCommandRta(p, arg, RIOFoadRta); case RIO_ZOMBIE_RTA: rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n"); - return RIOCommandRta(p, (unsigned long)arg, RIOZombieRta); + return RIOCommandRta(p, arg, RIOZombieRta); case RIO_IDENTIFY_RTA: rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n"); - return RIOIdentifyRta(p, arg); + return RIOIdentifyRta(p, argp); case RIO_KILL_NEIGHBOUR: rio_dprintk(RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n"); - return RIOKillNeighbour(p, arg); + return RIOKillNeighbour(p, argp); case SPECIAL_RUP_CMD: { struct CmdBlk *CmdBlkP; rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n"); - if (copy_from_user(&SpecialRupCmd, arg, sizeof(SpecialRupCmd))) { + if (copy_from_user(&SpecialRupCmd, argp, sizeof(SpecialRupCmd))) { rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -239,7 +247,7 @@ int su; if ((retval = RIOApel(p)) != 0) return retval; - if (copy_to_user(arg, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) { + if (copy_to_user(argp, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -284,7 +292,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copy_from_user(&p->RIOConnectTable[0], arg, TOTAL_MAP_ENTRIES * sizeof(struct Map))) { + if (copy_from_user(&p->RIOConnectTable[0], argp, TOTAL_MAP_ENTRIES * sizeof(struct Map))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -330,7 +338,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copy_to_user(arg, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) { + if (copy_to_user(argp, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -349,7 +357,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copy_from_user(&p->RIOBindTab[0], arg, (sizeof(ulong) * MAX_RTA_BINDINGS))) { + if (copy_from_user(&p->RIOBindTab[0], argp, (sizeof(ulong) * MAX_RTA_BINDINGS))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -373,12 +381,12 @@ int su; for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) { if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L)) EmptySlot = Entry; - else if (p->RIOBindTab[Entry] == (long)arg) { + else if (p->RIOBindTab[Entry] == arg) { /* ** Already exists - delete */ p->RIOBindTab[Entry] = 0L; - rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", (unsigned long)arg); + rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", arg); return 0; } } @@ -386,10 +394,10 @@ int su; ** Dosen't exist - add */ if (EmptySlot != -1) { - p->RIOBindTab[EmptySlot] = (unsigned long)arg; - rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", (unsigned long) arg); + p->RIOBindTab[EmptySlot] = arg; + rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", arg); } else { - rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", (unsigned long) arg); + rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", arg); return -ENOMEM; } return 0; @@ -397,7 +405,7 @@ int su; case RIO_RESUME: rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n"); - port = (unsigned long) arg; + port = arg; if ((port < 0) || (port > 511)) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port); p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; @@ -433,7 +441,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copy_from_user(&MapEnt, arg, sizeof(MapEnt))) { + if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) { rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -447,7 +455,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copy_from_user(&MapEnt, arg, sizeof(MapEnt))) { + if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) { rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -461,7 +469,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copy_from_user(&MapEnt, arg, sizeof(MapEnt))) { + if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) { rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -469,14 +477,14 @@ int su; return RIODeleteRta(p, &MapEnt); case RIO_QUICK_CHECK: - if (copy_to_user(arg, &p->RIORtaDisCons, sizeof(unsigned int))) { + if (copy_to_user(argp, &p->RIORtaDisCons, sizeof(unsigned int))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } return 0; case RIO_LAST_ERROR: - if (copy_to_user(arg, &p->RIOError, sizeof(struct Error))) + if (copy_to_user(argp, &p->RIOError, sizeof(struct Error))) return -EFAULT; return 0; @@ -485,7 +493,7 @@ int su; return -EINVAL; case RIO_GET_MODTYPE: - if (copy_from_user(&port, arg, sizeof(unsigned int))) { + if (copy_from_user(&port, argp, sizeof(unsigned int))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -505,7 +513,7 @@ int su; ** Return module type of port */ port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes; - if (copy_to_user(arg, &port, sizeof(unsigned int))) { + if (copy_to_user(argp, &port, sizeof(unsigned int))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } @@ -521,7 +529,7 @@ int su; case RIO_SETUP_PORTS: rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n"); - if (copy_from_user(&PortSetup, arg, sizeof(PortSetup))) { + if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) { p->RIOError.Error = COPYIN_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "EFAULT"); return -EFAULT; @@ -551,7 +559,7 @@ int su; case RIO_GET_PORT_SETUP: rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n"); - if (copy_from_user(&PortSetup, arg, sizeof(PortSetup))) { + if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -572,7 +580,7 @@ int su; PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0'; PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0'; - if (copy_to_user(arg, &PortSetup, sizeof(PortSetup))) { + if (copy_to_user(argp, &PortSetup, sizeof(PortSetup))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } @@ -580,7 +588,7 @@ int su; case RIO_GET_PORT_PARAMS: rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n"); - if (copy_from_user(&PortParams, arg, sizeof(struct PortParams))) { + if (copy_from_user(&PortParams, argp, sizeof(struct PortParams))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -593,7 +601,7 @@ int su; PortParams.State = PortP->State; rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port); - if (copy_to_user(arg, &PortParams, sizeof(struct PortParams))) { + if (copy_to_user(argp, &PortParams, sizeof(struct PortParams))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } @@ -601,7 +609,7 @@ int su; case RIO_GET_PORT_TTY: rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n"); - if (copy_from_user(&PortTty, arg, sizeof(struct PortTty))) { + if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -612,14 +620,14 @@ int su; rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port); PortP = (p->RIOPortp[PortTty.port]); - if (copy_to_user(arg, &PortTty, sizeof(struct PortTty))) { + if (copy_to_user(argp, &PortTty, sizeof(struct PortTty))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } return retval; case RIO_SET_PORT_TTY: - if (copy_from_user(&PortTty, arg, sizeof(struct PortTty))) { + if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -634,7 +642,7 @@ int su; case RIO_SET_PORT_PARAMS: rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n"); - if (copy_from_user(&PortParams, arg, sizeof(PortParams))) { + if (copy_from_user(&PortParams, argp, sizeof(PortParams))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -650,7 +658,7 @@ int su; case RIO_GET_PORT_STATS: rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n"); - if (copy_from_user(&portStats, arg, sizeof(struct portStats))) { + if (copy_from_user(&portStats, argp, sizeof(struct portStats))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -665,14 +673,14 @@ int su; portStats.opens = PortP->opens; portStats.closes = PortP->closes; portStats.ioctls = PortP->ioctls; - if (copy_to_user(arg, &portStats, sizeof(struct portStats))) { + if (copy_to_user(argp, &portStats, sizeof(struct portStats))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } return retval; case RIO_RESET_PORT_STATS: - port = (unsigned long) arg; + port = arg; rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n"); if (port >= RIO_PORTS) { p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; @@ -690,7 +698,7 @@ int su; case RIO_GATHER_PORT_STATS: rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n"); - if (copy_from_user(&portStats, arg, sizeof(struct portStats))) { + if (copy_from_user(&portStats, argp, sizeof(struct portStats))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -706,7 +714,7 @@ int su; case RIO_READ_CONFIG: rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n"); - if (copy_to_user(arg, &p->RIOConf, sizeof(struct Conf))) { + if (copy_to_user(argp, &p->RIOConf, sizeof(struct Conf))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } @@ -718,7 +726,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copy_from_user(&p->RIOConf, arg, sizeof(struct Conf))) { + if (copy_from_user(&p->RIOConf, argp, sizeof(struct Conf))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -746,7 +754,7 @@ int su; case RIO_SETDEBUG: case RIO_GETDEBUG: rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n"); - if (copy_from_user(&DebugCtrl, arg, sizeof(DebugCtrl))) { + if (copy_from_user(&DebugCtrl, argp, sizeof(DebugCtrl))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -763,7 +771,7 @@ int su; rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait); DebugCtrl.Debug = p->rio_debug; DebugCtrl.Wait = p->RIODebugWait; - if (copy_to_user(arg, &DebugCtrl, sizeof(DebugCtrl))) { + if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -785,7 +793,7 @@ int su; } else { rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug); DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug; - if (copy_to_user(arg, &DebugCtrl, sizeof(DebugCtrl))) { + if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -800,7 +808,7 @@ int su; ** textual null terminated string. */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n"); - if (copy_to_user(arg, RIOVersid(), sizeof(struct rioVersion))) { + if (copy_to_user(argp, RIOVersid(), sizeof(struct rioVersion))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -813,7 +821,7 @@ int su; ** at init time. */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n"); - if (copy_to_user(arg, &p->RIONumHosts, sizeof(p->RIONumHosts))) { + if (copy_to_user(argp, &p->RIONumHosts, sizeof(p->RIONumHosts))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -824,7 +832,7 @@ int su; /* ** Kill host. This may not be in the final version... */ - rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", (unsigned long) arg); + rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", arg); if (!su) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n"); p->RIOError.Error = NOT_SUPER_USER; @@ -858,7 +866,7 @@ int su; p->RIOError.Error = NOT_SUPER_USER; return -EPERM; } - if (copy_from_user(&DownLoad, arg, sizeof(DownLoad))) { + if (copy_from_user(&DownLoad, argp, sizeof(DownLoad))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -888,7 +896,7 @@ int su; { unsigned int host; - if (copy_from_user(&host, arg, sizeof(host))) { + if (copy_from_user(&host, argp, sizeof(host))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -897,7 +905,7 @@ int su; ** Fetch the parmmap */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n"); - if (copy_to_user(arg, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) { + if (copy_from_io(argp, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) { p->RIOError.Error = COPYOUT_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n"); return -EFAULT; @@ -907,7 +915,7 @@ int su; case RIO_HOST_REQ: rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n"); - if (copy_from_user(&HostReq, arg, sizeof(HostReq))) { + if (copy_from_user(&HostReq, argp, sizeof(HostReq))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -928,7 +936,7 @@ int su; case RIO_HOST_DPRAM: rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n"); - if (copy_from_user(&HostDpRam, arg, sizeof(HostDpRam))) { + if (copy_from_user(&HostDpRam, argp, sizeof(HostDpRam))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -945,13 +953,13 @@ int su; /* It's hardware like this that really gets on my tits. */ static unsigned char copy[sizeof(struct DpRam)]; for (off = 0; off < sizeof(struct DpRam); off++) - copy[off] = readb(&p->RIOHosts[HostDpRam.HostNum].Caddr[off]); + copy[off] = readb(p->RIOHosts[HostDpRam.HostNum].Caddr + off); if (copy_to_user(HostDpRam.DpRamP, copy, sizeof(struct DpRam))) { p->RIOError.Error = COPYOUT_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); return -EFAULT; } - } else if (copy_to_user(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) { + } else if (copy_from_io(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) { p->RIOError.Error = COPYOUT_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); return -EFAULT; @@ -960,13 +968,13 @@ int su; case RIO_SET_BUSY: rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n"); - if ((unsigned long) arg > 511) { - rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", (unsigned long) arg); + if (arg > 511) { + rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", arg); p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; return -EINVAL; } rio_spin_lock_irqsave(&PortP->portSem, flags); - p->RIOPortp[(unsigned long) arg]->State |= RIO_BUSY; + p->RIOPortp[arg]->State |= RIO_BUSY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return retval; @@ -976,7 +984,7 @@ int su; ** (probably for debug reasons) */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n"); - if (copy_from_user(&PortReq, arg, sizeof(PortReq))) { + if (copy_from_user(&PortReq, argp, sizeof(PortReq))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1001,7 +1009,7 @@ int su; ** (probably for debug reasons) */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n"); - if (copy_from_user(&RupReq, arg, sizeof(RupReq))) { + if (copy_from_user(&RupReq, argp, sizeof(RupReq))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1025,7 +1033,7 @@ int su; } rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum); - if (copy_to_user(HostP->UnixRups[RupReq.RupNum].RupP, RupReq.RupP, sizeof(struct RUP))) { + if (copy_from_io(RupReq.RupP, HostP->UnixRups[RupReq.RupNum].RupP, sizeof(struct RUP))) { p->RIOError.Error = COPYOUT_FAILED; rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n"); return -EFAULT; @@ -1038,7 +1046,7 @@ int su; ** (probably for debug reasons) */ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n"); - if (copy_from_user(&LpbReq, arg, sizeof(LpbReq))) { + if (copy_from_user(&LpbReq, argp, sizeof(LpbReq))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1062,7 +1070,7 @@ int su; } rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host); - if (copy_to_user(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) { + if (copy_from_io(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -1136,7 +1144,7 @@ int su; case RIO_MAP_B110_TO_110: case RIO_MAP_B110_TO_115200: rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n"); - port = (unsigned long) arg; + port = arg; if (port < 0 || port > 511) { rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port); p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; @@ -1166,7 +1174,7 @@ int su; case RIO_SEND_PACKET: rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n"); - if (copy_from_user(&SendPack, arg, sizeof(SendPack))) { + if (copy_from_user(&SendPack, argp, sizeof(SendPack))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n"); p->RIOError.Error = COPYIN_FAILED; return -EFAULT; @@ -1210,7 +1218,7 @@ int su; return su ? 0 : -EPERM; case RIO_WHAT_MESG: - if (copy_to_user(arg, &p->RIONoMessage, sizeof(p->RIONoMessage))) { + if (copy_to_user(argp, &p->RIONoMessage, sizeof(p->RIONoMessage))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -1218,7 +1226,7 @@ int su; return 0; case RIO_MEM_DUMP: - if (copy_from_user(&SubCmd, arg, sizeof(struct SubCmdStruct))) { + if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -1248,7 +1256,7 @@ int su; PortP->State |= RIO_BUSY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (copy_to_user(arg, p->RIOMemDump, MEMDUMP_SIZE)) { + if (copy_to_user(argp, p->RIOMemDump, MEMDUMP_SIZE)) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -1256,30 +1264,30 @@ int su; return 0; case RIO_TICK: - if ((unsigned long) arg >= p->RIONumHosts) + if (arg >= p->RIONumHosts) return -EINVAL; - rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", (unsigned long) arg); - writeb(0xFF, &p->RIOHosts[(unsigned long) arg].SetInt); + rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", arg); + writeb(0xFF, &p->RIOHosts[arg].SetInt); return 0; case RIO_TOCK: - if ((unsigned long) arg >= p->RIONumHosts) + if (arg >= p->RIONumHosts) return -EINVAL; - rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", (unsigned long) arg); - writeb(0xFF, &p->RIOHosts[(unsigned long) arg].ResetInt); + rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", arg); + writeb(0xFF, &p->RIOHosts[arg].ResetInt); return 0; case RIO_READ_CHECK: /* Check reads for pkts with data[0] the same */ p->RIOReadCheck = !p->RIOReadCheck; - if (copy_to_user(arg, &p->RIOReadCheck, sizeof(unsigned int))) { + if (copy_to_user(argp, &p->RIOReadCheck, sizeof(unsigned int))) { p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; } return 0; case RIO_READ_REGISTER: - if (copy_from_user(&SubCmd, arg, sizeof(struct SubCmdStruct))) { + if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) { p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } @@ -1314,7 +1322,7 @@ int su; PortP->State |= RIO_BUSY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); - if (copy_to_user(arg, &p->CdRegister, sizeof(unsigned int))) { + if (copy_to_user(argp, &p->CdRegister, sizeof(unsigned int))) { rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n"); p->RIOError.Error = COPYOUT_FAILED; return -EFAULT; @@ -1327,10 +1335,10 @@ int su; */ case RIO_MAKE_DEV: { - unsigned int port = (unsigned long) arg & RIO_MODEM_MASK; + unsigned int port = arg & RIO_MODEM_MASK; unsigned int ret; - switch ((unsigned long) arg & RIO_DEV_MASK) { + switch (arg & RIO_DEV_MASK) { case RIO_DEV_DIRECT: ret = drv_makedev(MAJOR(dev), port); rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, ret); @@ -1358,7 +1366,7 @@ int su; int mino; unsigned long ret; - dv = (dev_t) ((unsigned long) arg); + dv = (dev_t) (arg); mino = RIO_UNMODEM(dv); if (RIO_ISMODEM(dv)) { diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c index 24d2992..12e34bc 100644 --- a/drivers/char/rio/rioinit.c +++ b/drivers/char/rio/rioinit.c @@ -79,7 +79,7 @@ #include "rio_linux.h" int RIOPCIinit(struct rio_info *p, int Mode); -static int RIOScrub(int, u8 *, int); +static int RIOScrub(int, u8 __iomem *, int); /** @@ -92,10 +92,10 @@ static int RIOScrub(int, u8 *, int); ** bits > 0 indicates 16 bit operation. */ -int RIOAssignAT(struct rio_info *p, int Base, caddr_t virtAddr, int mode) +int RIOAssignAT(struct rio_info *p, int Base, void __iomem *virtAddr, int mode) { int bits; - struct DpRam *cardp = (struct DpRam *)virtAddr; + struct DpRam __iomem *cardp = (struct DpRam __iomem *)virtAddr; if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE)) bits = BYTE_OPERATION; @@ -107,7 +107,7 @@ int RIOAssignAT(struct rio_info *p, int ** transient stuff. */ p->RIOHosts[p->RIONumHosts].Caddr = virtAddr; - p->RIOHosts[p->RIONumHosts].CardP = (struct DpRam *)virtAddr; + p->RIOHosts[p->RIONumHosts].CardP = virtAddr; /* ** Revision 01 AT host cards don't support WORD operations, @@ -151,10 +151,10 @@ #define TEST_END sizeof(val) ** RAM test a board. ** Nothing too complicated, just enough to check it out. */ -int RIOBoardTest(unsigned long paddr, caddr_t caddr, unsigned char type, int slot) +int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, int slot) { - struct DpRam *DpRam = (struct DpRam *)caddr; - char *ram[4]; + struct DpRam __iomem *DpRam = caddr; + void __iomem *ram[4]; int size[4]; int op, bank; int nbanks; @@ -179,12 +179,12 @@ int RIOBoardTest(unsigned long paddr, ca size[2] = DP_SRAM3_SIZE; size[3] = DP_SCRATCH_SIZE; - ram[0] = (char *)&DpRam->DpSram1[0]; - ram[1] = (char *)&DpRam->DpSram2[0]; - ram[2] = (char *)&DpRam->DpSram3[0]; + ram[0] = DpRam->DpSram1; + ram[1] = DpRam->DpSram2; + ram[2] = DpRam->DpSram3; nbanks = (type == RIO_PCI) ? 3 : 4; if (nbanks == 4) - ram[3] = (char *)&DpRam->DpScratch[0]; + ram[3] = DpRam->DpScratch; if (nbanks == 3) { @@ -202,7 +202,7 @@ int RIOBoardTest(unsigned long paddr, ca */ for (op=0; opHostP->Caddr, (caddr_t) PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c); + rio_memcpy_toio(PortP->HostP->Caddr, PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c); /* udelay (1); */ writeb(c, &(PacketP->len)); @@ -219,7 +219,7 @@ void RIOServiceHost(struct rio_info *p, for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) { struct Port *PortP = p->RIOPortp[port]; struct tty_struct *ttyP; - struct PKT *PacketP; + struct PKT __iomem *PacketP; /* ** not mapped in - most of the RIOPortp[] information @@ -298,7 +298,7 @@ void RIOServiceHost(struct rio_info *p, for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) { struct Port *PortP = p->RIOPortp[port]; struct tty_struct *ttyP; - struct PKT *PacketP; + struct PKT __iomem *PacketP; /* ** not mapped in - most of the RIOPortp[] information @@ -427,13 +427,13 @@ void RIOServiceHost(struct rio_info *p, while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) { int p; - struct PktCmd *PktCmdP; + struct PktCmd __iomem *PktCmdP; rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n"); /* ** make it look just like a WFLUSH command */ - PktCmdP = (struct PktCmd *) &PacketP->data[0]; + PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0]; writeb(WFLUSH, &PktCmdP->Command); @@ -525,9 +525,9 @@ static void RIOReceive(struct rio_info * { struct tty_struct *TtyP; unsigned short transCount; - struct PKT *PacketP; + struct PKT __iomem *PacketP; register unsigned int DataCnt; - unsigned char *ptr; + unsigned char __iomem *ptr; unsigned char *buf; int copied = 0; @@ -546,7 +546,7 @@ static void RIOReceive(struct rio_info * ** run out of space it will be set to the offset of the ** next byte to copy from the packet data area. The packet ** length field is decremented by the number of bytes that - ** we succesfully removed from the packet. When this reaches + ** we successfully removed from the packet. When this reaches ** zero, we reset the offset pointer to be zero, and free ** the packet from the front of the queue. */ @@ -585,19 +585,19 @@ static void RIOReceive(struct rio_info * /* ** check that it is not a command! */ - if (PacketP->len & PKT_CMD_BIT) { + if (readb(&PacketP->len) & PKT_CMD_BIT) { rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n"); /* rio_dprint(RIO_DEBUG_INTR, (" sysport = %d\n", p->RIOPortp->PortNum)); */ - rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", PacketP->dest_unit); - rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", PacketP->dest_port); - rio_dprintk(RIO_DEBUG_INTR, " src_unit = %d\n", PacketP->src_unit); - rio_dprintk(RIO_DEBUG_INTR, " src_port = %d\n", PacketP->src_port); - rio_dprintk(RIO_DEBUG_INTR, " len = %d\n", PacketP->len); - rio_dprintk(RIO_DEBUG_INTR, " control = %d\n", PacketP->control); - rio_dprintk(RIO_DEBUG_INTR, " csum = %d\n", PacketP->csum); + rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", readb(&PacketP->dest_unit)); + rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", readb(&PacketP->dest_port)); + rio_dprintk(RIO_DEBUG_INTR, " src_unit = %d\n", readb(&PacketP->src_unit)); + rio_dprintk(RIO_DEBUG_INTR, " src_port = %d\n", readb(&PacketP->src_port)); + rio_dprintk(RIO_DEBUG_INTR, " len = %d\n", readb(&PacketP->len)); + rio_dprintk(RIO_DEBUG_INTR, " control = %d\n", readb(&PacketP->control)); + rio_dprintk(RIO_DEBUG_INTR, " csum = %d\n", readw(&PacketP->csum)); rio_dprintk(RIO_DEBUG_INTR, " data bytes: "); for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++) - rio_dprintk(RIO_DEBUG_INTR, "%d\n", PacketP->data[DataCnt]); + rio_dprintk(RIO_DEBUG_INTR, "%d\n", readb(&PacketP->data[DataCnt])); remove_receive(PortP); put_free_end(PortP->HostP, PacketP); continue; /* with next packet */ @@ -618,24 +618,24 @@ static void RIOReceive(struct rio_info * ** and available space. */ - transCount = tty_buffer_request_room(TtyP, PacketP->len & PKT_LEN_MASK); + transCount = tty_buffer_request_room(TtyP, readb(&PacketP->len) & PKT_LEN_MASK); rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount); /* ** To use the following 'kkprintfs' for debugging - change the '#undef' ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the ** driver). */ - ptr = (unsigned char *) PacketP->data + PortP->RxDataStart; + ptr = (unsigned char __iomem *) PacketP->data + PortP->RxDataStart; tty_prepare_flip_string(TtyP, &buf, transCount); rio_memcpy_fromio(buf, ptr, transCount); PortP->RxDataStart += transCount; - PacketP->len -= transCount; + writeb(readb(&PacketP->len)-transCount, &PacketP->len); copied += transCount; - if (PacketP->len == 0) { + if (readb(&PacketP->len) == 0) { /* ** If we have emptied the packet, then we can ** free it, and reset the start pointer for diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c index d2e8092..1066d97 100644 --- a/drivers/char/rio/rioparam.c +++ b/drivers/char/rio/rioparam.c @@ -154,8 +154,8 @@ int RIOParam(struct Port *PortP, int cmd { struct tty_struct *TtyP; int retval; - struct phb_param *phb_param_ptr; - struct PKT *PacketP; + struct phb_param __iomem *phb_param_ptr; + struct PKT __iomem *PacketP; int res; u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0; u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0; @@ -235,7 +235,7 @@ int RIOParam(struct Port *PortP, int cmd rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res); rio_dprintk(RIO_DEBUG_PARAM, "Packet is %p\n", PacketP); - phb_param_ptr = (struct phb_param *) PacketP->data; + phb_param_ptr = (struct phb_param __iomem *) PacketP->data; switch (TtyP->termios->c_cflag & CSIZE) { @@ -580,11 +580,11 @@ #endif ** We can add another packet to a transmit queue if the packet pointer pointed ** to by the TxAdd pointer has PKT_IN_USE clear in its address. */ -int can_add_transmit(struct PKT **PktP, struct Port *PortP) +int can_add_transmit(struct PKT __iomem **PktP, struct Port *PortP) { - struct PKT *tp; + struct PKT __iomem *tp; - *PktP = tp = (struct PKT *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd)); + *PktP = tp = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd)); return !((unsigned long) tp & PKT_IN_USE); } @@ -608,9 +608,9 @@ void add_transmit(struct Port *PortP) * Put a packet onto the end of the * free list ****************************************/ -void put_free_end(struct Host *HostP, struct PKT *PktP) +void put_free_end(struct Host *HostP, struct PKT __iomem *PktP) { - struct rio_free_list *tmp_pointer; + struct rio_free_list __iomem *tmp_pointer; unsigned short old_end, new_end; unsigned long flags; @@ -625,15 +625,15 @@ void put_free_end(struct Host *HostP, st if ((old_end = readw(&HostP->ParmMapP->free_list_end)) != TPNULL) { new_end = RIO_OFF(HostP->Caddr, PktP); - tmp_pointer = (struct rio_free_list *) RIO_PTR(HostP->Caddr, old_end); + tmp_pointer = (struct rio_free_list __iomem *) RIO_PTR(HostP->Caddr, old_end); writew(new_end, &tmp_pointer->next); - writew(old_end, &((struct rio_free_list *) PktP)->prev); - writew(TPNULL, &((struct rio_free_list *) PktP)->next); + writew(old_end, &((struct rio_free_list __iomem *) PktP)->prev); + writew(TPNULL, &((struct rio_free_list __iomem *) PktP)->next); writew(new_end, &HostP->ParmMapP->free_list_end); } else { /* First packet on the free list this should never happen! */ rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n"); writew(RIO_OFF(HostP->Caddr, PktP), &HostP->ParmMapP->free_list_end); - tmp_pointer = (struct rio_free_list *) PktP; + tmp_pointer = (struct rio_free_list __iomem *) PktP; writew(TPNULL, &tmp_pointer->prev); writew(TPNULL, &tmp_pointer->next); } @@ -647,10 +647,10 @@ void put_free_end(struct Host *HostP, st ** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear, ** then can_remove_receive() returns 0. */ -int can_remove_receive(struct PKT **PktP, struct Port *PortP) +int can_remove_receive(struct PKT __iomem **PktP, struct Port *PortP) { if (readw(PortP->RxRemove) & PKT_IN_USE) { - *PktP = (struct PKT *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE); + *PktP = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE); return 1; } return 0; diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c index 3570853..a99f3d9 100644 --- a/drivers/char/rio/rioroute.c +++ b/drivers/char/rio/rioroute.c @@ -86,9 +86,9 @@ static void RIOConCon(struct rio_info *, ** Incoming on the ROUTE_RUP ** I wrote this while I was tired. Forgive me. */ -int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT * PacketP) +int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem * PacketP) { - struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data; + struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data; struct PktCmd_M *PktReplyP; struct CmdBlk *CmdBlkP; struct Port *PortP; @@ -307,7 +307,7 @@ int RIORouteRup(struct rio_info *p, unsi if (!RIOBootOk(p, HostP, RtaUniq)) { rio_dprintk(RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", RtaUniq); PktReplyP->Command = ROUTE_FOAD; - HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7); + memcpy(PktReplyP->CommandText, "RT_FOAD", 7); RIOQueueCmdBlk(HostP, Rup, CmdBlkP); return 1; } @@ -341,7 +341,7 @@ int RIORouteRup(struct rio_info *p, unsi HostP->Mapping[ThisUnit].Flags |= MSG_DONE; } PktReplyP->Command = ROUTE_FOAD; - HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7); + memcpy(PktReplyP->CommandText, "RT_FOAD", 7); RIOQueueCmdBlk(HostP, Rup, CmdBlkP); return 1; } @@ -367,7 +367,7 @@ int RIORouteRup(struct rio_info *p, unsi PktReplyP->IDNum2 = ROUTE_NO_ID; rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum); } - HostP->Copy("RT_ALLOCAT", PktReplyP->CommandText, 10); + memcpy(PktReplyP->CommandText, "RT_ALLOCAT", 10); RIOQueueCmdBlk(HostP, Rup, CmdBlkP); @@ -469,7 +469,7 @@ int RIORouteRup(struct rio_info *p, unsi } PktReplyP->Command = ROUTE_FOAD; - HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7); + memcpy(PktReplyP->CommandText, "RT_FOAD", 7); } else { /* ** we did boot it (as an extra), and there may now be a table @@ -489,7 +489,7 @@ int RIORouteRup(struct rio_info *p, unsi } } PktReplyP->Command = ROUTE_USED; - HostP->Copy("RT_USED", PktReplyP->CommandText, 7); + memcpy(PktReplyP->CommandText, "RT_USED", 7); } RIOQueueCmdBlk(HostP, Rup, CmdBlkP); return 1; @@ -517,8 +517,8 @@ void RIOFixPhbs(struct rio_info *p, stru for (port = 0; port < PORTS_PER_RTA; port++, PortN++) { unsigned short dest_port = port + 8; - u16 *TxPktP; - struct PKT *Pkt; + u16 __iomem *TxPktP; + struct PKT __iomem *Pkt; PortP = p->RIOPortp[PortN]; @@ -555,12 +555,12 @@ void RIOFixPhbs(struct rio_info *p, stru ** card. This needs to be translated into a 32 bit pointer ** so it can be accessed from the driver. */ - Pkt = (struct PKT *) RIO_PTR(HostP->Caddr, readw(TxPktP)); + Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(TxPktP)); /* ** If the packet is used, reset it. */ - Pkt = (struct PKT *) ((unsigned long) Pkt & ~PKT_IN_USE); + Pkt = (struct PKT __iomem *) ((unsigned long) Pkt & ~PKT_IN_USE); writeb(dest_unit, &Pkt->dest_unit); writeb(dest_port, &Pkt->dest_port); } diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c index d3abe0d..7e98835 100644 --- a/drivers/char/rio/riotable.c +++ b/drivers/char/rio/riotable.c @@ -534,8 +534,8 @@ int RIODeleteRta(struct rio_info *p, str if (PortP->SecondBlock) { u16 dest_unit = HostMapP->ID; u16 dest_port = port - SysPort; - u16 *TxPktP; - struct PKT *Pkt; + u16 __iomem *TxPktP; + struct PKT __iomem *Pkt; for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) { /* @@ -545,12 +545,12 @@ int RIODeleteRta(struct rio_info *p, str ** a 32 bit pointer so it can be ** accessed from the driver. */ - Pkt = (struct PKT *) RIO_PTR(HostP->Caddr, readw(&*TxPktP)); - rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", *TxPktP, Pkt->dest_unit, Pkt->dest_port, dest_unit, dest_port); + Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&*TxPktP)); + rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", readw(TxPktP), readb(&Pkt->dest_unit), readb(&Pkt->dest_port), dest_unit, dest_port); writew(dest_unit, &Pkt->dest_unit); writew(dest_port, &Pkt->dest_port); } - rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, PortP->PhbP->destination & 0xff, (PortP->PhbP->destination >> 8) & 0xff, dest_unit, dest_port); + rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, readb(&PortP->PhbP->destination) & 0xff, (readb(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port); writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination); } rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags); @@ -781,13 +781,13 @@ int RIOReMapPorts(struct rio_info *p, st ** unless the host has been booted */ if ((HostP->Flags & RUN_STATE) == RC_RUNNING) { - struct PHB *PhbP = PortP->PhbP = &HostP->PhbP[HostPort]; - PortP->TxAdd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add)); - PortP->TxStart = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start)); - PortP->TxEnd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end)); - PortP->RxRemove = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove)); - PortP->RxStart = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start)); - PortP->RxEnd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end)); + struct PHB __iomem *PhbP = PortP->PhbP = &HostP->PhbP[HostPort]; + PortP->TxAdd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add)); + PortP->TxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start)); + PortP->TxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end)); + PortP->RxRemove = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove)); + PortP->RxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start)); + PortP->RxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end)); } else PortP->PhbP = NULL; diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c index 2042676..a4f0b1e 100644 --- a/drivers/char/rio/riotty.c +++ b/drivers/char/rio/riotty.c @@ -576,7 +576,7 @@ static void RIOClearUp(struct Port *Port */ int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg) { - struct PKT *PacketP; + struct PKT __iomem *PacketP; int retries = 20; /* at 10 per second -> 2 seconds */ unsigned long flags; diff --git a/drivers/char/rio/unixrup.h b/drivers/char/rio/unixrup.h index 4306e01..46bd532 100644 --- a/drivers/char/rio/unixrup.h +++ b/drivers/char/rio/unixrup.h @@ -44,7 +44,7 @@ #endif struct UnixRup { struct CmdBlk *CmdsWaitingP; /* Commands waiting to be done */ struct CmdBlk *CmdPendingP; /* The command currently being sent */ - struct RUP *RupP; /* the Rup to send it to */ + struct RUP __iomem *RupP; /* the Rup to send it to */ unsigned int Id; /* Id number */ unsigned int BaseSysPort; /* SysPort of first tty on this RTA */ unsigned int ModTypes; /* Modules on this RTA */ diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 7edc6a4..0708c51 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -324,35 +324,15 @@ static void rp_do_receive(struct r_port CHANNEL_t * cp, unsigned int ChanStatus) { unsigned int CharNStat; - int ToRecv, wRecv, space = 0, count; - unsigned char *cbuf, *chead; - char *fbuf, *fhead; - struct tty_ldisc *ld; - - ld = tty_ldisc_ref(tty); + int ToRecv, wRecv, space; + unsigned char *cbuf; ToRecv = sGetRxCnt(cp); - space = tty->receive_room; - if (space > 2 * TTY_FLIPBUF_SIZE) - space = 2 * TTY_FLIPBUF_SIZE; - count = 0; #ifdef ROCKET_DEBUG_INTR - printk(KERN_INFO "rp_do_receive(%d, %d)...", ToRecv, space); + printk(KERN_INFO "rp_do_receive(%d)...", ToRecv); #endif - - /* - * determine how many we can actually read in. If we can't - * read any in then we have a software overrun condition. - */ - if (ToRecv > space) - ToRecv = space; - - ToRecv = tty_prepare_flip_string_flags(tty, &chead, &fhead, ToRecv); - if (ToRecv <= 0) - goto done; - - cbuf = chead; - fbuf = fhead; + if (ToRecv == 0) + return; /* * if status indicates there are errored characters in the @@ -380,6 +360,8 @@ #ifdef ROCKET_DEBUG_RECEIVE info->read_status_mask); #endif while (ToRecv) { + char flag; + CharNStat = sInW(sGetTxRxDataIO(cp)); #ifdef ROCKET_DEBUG_RECEIVE printk(KERN_INFO "%x...", CharNStat); @@ -392,17 +374,16 @@ #endif } CharNStat &= info->read_status_mask; if (CharNStat & STMBREAKH) - *fbuf++ = TTY_BREAK; + flag = TTY_BREAK; else if (CharNStat & STMPARITYH) - *fbuf++ = TTY_PARITY; + flag = TTY_PARITY; else if (CharNStat & STMFRAMEH) - *fbuf++ = TTY_FRAME; + flag = TTY_FRAME; else if (CharNStat & STMRCVROVRH) - *fbuf++ = TTY_OVERRUN; + flag = TTY_OVERRUN; else - *fbuf++ = TTY_NORMAL; - *cbuf++ = CharNStat & 0xff; - count++; + flag = TTY_NORMAL; + tty_insert_flip_char(tty, CharNStat & 0xff, flag); ToRecv--; } @@ -422,20 +403,23 @@ #endif * characters at time by doing repeated word IO * transfer. */ + space = tty_prepare_flip_string(tty, &cbuf, ToRecv); + if (space < ToRecv) { +#ifdef ROCKET_DEBUG_RECEIVE + printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space); +#endif + if (space <= 0) + return; + ToRecv = space; + } wRecv = ToRecv >> 1; if (wRecv) sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv); if (ToRecv & 1) cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp)); - memset(fbuf, TTY_NORMAL, ToRecv); - cbuf += ToRecv; - fbuf += ToRecv; - count += ToRecv; } /* Push the data up to the tty layer */ - ld->receive_buf(tty, chead, fhead, count); -done: - tty_ldisc_deref(ld); + tty_flip_buffer_push(tty); } /* diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 7cac6d0..0897b0c 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -928,7 +928,7 @@ #endif #ifdef __sparc__ for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if(strcmp(edev->prom_name, "rtc") == 0) { + if(strcmp(edev->prom_node->name, "rtc") == 0) { rtc_port = edev->resource[0].start; rtc_irq = edev->irqs[0]; goto found; @@ -938,7 +938,7 @@ #ifdef __sparc__ #ifdef __sparc_v9__ for_each_isa(isa_br) { for_each_isadev(isa_dev, isa_br) { - if (strcmp(isa_dev->prom_name, "rtc") == 0) { + if (strcmp(isa_dev->prom_node->name, "rtc") == 0) { rtc_port = isa_dev->resource.start; rtc_irq = isa_dev->irq; goto found; @@ -960,10 +960,6 @@ found: * PCI Slot 2 INTA# (and some INTx# in Slot 1). */ if (request_irq(rtc_irq, rtc_interrupt, SA_SHIRQ, "rtc", (void *)&rtc_port)) { - /* - * Standard way for sparc to print irq's is to use - * __irq_itoa(). I think for EBus it's ok to use %d. - */ printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq); return -EIO; } diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index a90f5d9..43dfd86 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -512,7 +512,7 @@ #endif /* CONFIG_ACPI */ #ifdef CONFIG_ACPI static struct acpi_device *sonypi_acpi_device; -static int acpi_enabled; +static int acpi_driver_registered; #endif static int sonypi_ec_write(u8 addr, u8 value) @@ -869,7 +869,7 @@ found: sonypi_report_input_event(event); #ifdef CONFIG_ACPI - if (acpi_enabled) + if (sonypi_acpi_device) acpi_bus_generate_event(sonypi_acpi_device, 1, event); #endif @@ -1551,8 +1551,8 @@ static int __init sonypi_init(void) goto err_free_device; #ifdef CONFIG_ACPI - if (acpi_bus_register_driver(&sonypi_acpi_driver) > 0) - acpi_enabled = 1; + if (acpi_bus_register_driver(&sonypi_acpi_driver) >= 0) + acpi_driver_registered = 1; #endif return 0; @@ -1567,7 +1567,7 @@ #endif static void __exit sonypi_exit(void) { #ifdef CONFIG_ACPI - if (acpi_enabled) + if (acpi_driver_registered) acpi_bus_unregister_driver(&sonypi_acpi_driver); #endif platform_device_unregister(sonypi_platform_device); diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 5343e9f..1b53302 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -1683,7 +1683,7 @@ static int sx_write(struct tty_struct * bp = port_Board(port); - if (!tty || !port->xmit_buf || !tmp_buf) { + if (!port->xmit_buf || !tmp_buf) { func_exit(); return 0; } @@ -1733,7 +1733,7 @@ static void sx_put_char(struct tty_struc return; } dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); - if (!tty || !port->xmit_buf) { + if (!port->xmit_buf) { func_exit(); return; } diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index b4d1f4e..4e35d41 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -101,6 +101,7 @@ #define MAX_DEVICES 12 static struct pci_device_id pci_table[] = { {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT2_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {0,}, /* terminate list */ @@ -870,7 +871,7 @@ static int write(struct tty_struct *tty, goto cleanup; DBGINFO(("%s write count=%d\n", info->device_name, count)); - if (!tty || !info->tx_buf) + if (!info->tx_buf) goto cleanup; if (count > info->max_frame_size) { @@ -924,7 +925,7 @@ static void put_char(struct tty_struct * if (sanity_check(info, tty->name, "put_char")) return; DBGINFO(("%s put_char(%d)\n", info->device_name, ch)); - if (!tty || !info->tx_buf) + if (!info->tx_buf) return; spin_lock_irqsave(&info->lock,flags); if (!info->tx_active && (info->tx_count < info->max_frame_size)) @@ -2515,7 +2516,8 @@ static int set_txidle(struct slgt_info * DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode)); spin_lock_irqsave(&info->lock,flags); info->idle_mode = idle_mode; - tx_set_idle(info); + if (info->params.mode != MGSL_MODE_ASYNC) + tx_set_idle(info); spin_unlock_irqrestore(&info->lock,flags); return 0; } @@ -3076,7 +3078,7 @@ static int block_til_ready(struct tty_st static int alloc_tmp_rbuf(struct slgt_info *info) { - info->tmp_rbuf = kmalloc(info->max_frame_size, GFP_KERNEL); + info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL); if (info->tmp_rbuf == NULL) return -ENOMEM; return 0; @@ -3276,6 +3278,9 @@ static void add_device(struct slgt_info case SYNCLINK_GT_DEVICE_ID: devstr = "GT"; break; + case SYNCLINK_GT2_DEVICE_ID: + devstr = "GT2"; + break; case SYNCLINK_GT4_DEVICE_ID: devstr = "GT4"; break; @@ -3353,7 +3358,9 @@ static void device_init(int adapter_num, int i; int port_count = 1; - if (pdev->device == SYNCLINK_GT4_DEVICE_ID) + if (pdev->device == SYNCLINK_GT2_DEVICE_ID) + port_count = 2; + else if (pdev->device == SYNCLINK_GT4_DEVICE_ID) port_count = 4; /* allocate device instances for all ports */ @@ -3940,8 +3947,6 @@ static void async_mode(struct slgt_info msc_set_vcr(info); - tx_set_idle(info); - /* SCR (serial control) * * 15 1=tx req on FIFO half empty @@ -4012,7 +4017,7 @@ static void hdlc_mode(struct slgt_info * case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; } - switch (info->params.crc_type) + switch (info->params.crc_type & HDLC_CRC_MASK) { case HDLC_CRC_16_CCITT: val |= BIT9; break; case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; @@ -4073,7 +4078,7 @@ static void hdlc_mode(struct slgt_info * case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; } - switch (info->params.crc_type) + switch (info->params.crc_type & HDLC_CRC_MASK) { case HDLC_CRC_16_CCITT: val |= BIT9; break; case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; @@ -4175,17 +4180,38 @@ static void hdlc_mode(struct slgt_info * */ static void tx_set_idle(struct slgt_info *info) { - unsigned char val = 0xff; + unsigned char val; + unsigned short tcr; - switch(info->idle_mode) - { - case HDLC_TXIDLE_FLAGS: val = 0x7e; break; - case HDLC_TXIDLE_ALT_ZEROS_ONES: val = 0xaa; break; - case HDLC_TXIDLE_ZEROS: val = 0x00; break; - case HDLC_TXIDLE_ONES: val = 0xff; break; - case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break; - case HDLC_TXIDLE_SPACE: val = 0x00; break; - case HDLC_TXIDLE_MARK: val = 0xff; break; + /* if preamble enabled (tcr[6] == 1) then tx idle size = 8 bits + * else tcr[5:4] = tx idle size: 00 = 8 bits, 01 = 16 bits + */ + tcr = rd_reg16(info, TCR); + if (info->idle_mode & HDLC_TXIDLE_CUSTOM_16) { + /* disable preamble, set idle size to 16 bits */ + tcr = (tcr & ~(BIT6 + BIT5)) | BIT4; + /* MSB of 16 bit idle specified in tx preamble register (TPR) */ + wr_reg8(info, TPR, (unsigned char)((info->idle_mode >> 8) & 0xff)); + } else if (!(tcr & BIT6)) { + /* preamble is disabled, set idle size to 8 bits */ + tcr &= ~(BIT5 + BIT4); + } + wr_reg16(info, TCR, tcr); + + if (info->idle_mode & (HDLC_TXIDLE_CUSTOM_8 | HDLC_TXIDLE_CUSTOM_16)) { + /* LSB of custom tx idle specified in tx idle register */ + val = (unsigned char)(info->idle_mode & 0xff); + } else { + /* standard 8 bit idle patterns */ + switch(info->idle_mode) + { + case HDLC_TXIDLE_FLAGS: val = 0x7e; break; + case HDLC_TXIDLE_ALT_ZEROS_ONES: + case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break; + case HDLC_TXIDLE_ZEROS: + case HDLC_TXIDLE_SPACE: val = 0x00; break; + default: val = 0xff; + } } wr_reg8(info, TIR, val); @@ -4313,6 +4339,12 @@ static int rx_get_frame(struct slgt_info unsigned long flags; struct tty_struct *tty = info->tty; unsigned char addr_field = 0xff; + unsigned int crc_size = 0; + + switch (info->params.crc_type & HDLC_CRC_MASK) { + case HDLC_CRC_16_CCITT: crc_size = 2; break; + case HDLC_CRC_32_CCITT: crc_size = 4; break; + } check_again: @@ -4357,7 +4389,7 @@ check_again: status = desc_status(info->rbufs[end]); /* ignore CRC bit if not using CRC (bit is undefined) */ - if (info->params.crc_type == HDLC_CRC_NONE) + if ((info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_NONE) status &= ~BIT1; if (framesize == 0 || @@ -4366,34 +4398,34 @@ check_again: goto check_again; } - if (framesize < 2 || status & (BIT1+BIT0)) { - if (framesize < 2 || (status & BIT0)) - info->icount.rxshort++; - else - info->icount.rxcrc++; + if (framesize < (2 + crc_size) || status & BIT0) { + info->icount.rxshort++; framesize = 0; + } else if (status & BIT1) { + info->icount.rxcrc++; + if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) + framesize = 0; + } #ifdef CONFIG_HDLC - { - struct net_device_stats *stats = hdlc_stats(info->netdev); - stats->rx_errors++; - stats->rx_frame_errors++; - } -#endif - } else { - /* adjust frame size for CRC, if any */ - if (info->params.crc_type == HDLC_CRC_16_CCITT) - framesize -= 2; - else if (info->params.crc_type == HDLC_CRC_32_CCITT) - framesize -= 4; + if (framesize == 0) { + struct net_device_stats *stats = hdlc_stats(info->netdev); + stats->rx_errors++; + stats->rx_frame_errors++; } +#endif DBGBH(("%s rx frame status=%04X size=%d\n", info->device_name, status, framesize)); DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); if (framesize) { - if (framesize > info->max_frame_size) + if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { + framesize -= crc_size; + crc_size = 0; + } + + if (framesize > info->max_frame_size + crc_size) info->icount.rxlong++; else { /* copy dma buffer(s) to contiguous temp buffer */ @@ -4413,6 +4445,11 @@ #endif i = 0; } + if (info->params.crc_type & HDLC_CRC_RETURN_EX) { + *p = (status & BIT1) ? RX_CRC_ERROR : RX_OK; + framesize++; + } + #ifdef CONFIG_HDLC if (info->netcount) hdlcdev_rx(info,info->tmp_rbuf, framesize); @@ -4671,13 +4708,13 @@ #define TESTFRAMESIZE 20 static int adapter_test(struct slgt_info *info) { DBGINFO(("testing %s\n", info->device_name)); - if ((info->init_error = register_test(info)) < 0) { + if (register_test(info) < 0) { printk("register test failure %s addr=%08X\n", info->device_name, info->phys_reg_addr); - } else if ((info->init_error = irq_test(info)) < 0) { + } else if (irq_test(info) < 0) { printk("IRQ test failure %s IRQ=%d\n", info->device_name, info->irq_level); - } else if ((info->init_error = loopback_test(info)) < 0) { + } else if (loopback_test(info) < 0) { printk("loopback test failure %s\n", info->device_name); } return info->init_error; diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 8587401..21bf15a 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -988,7 +988,7 @@ static int write(struct tty_struct *tty, if (sanity_check(info, tty->name, "write")) goto cleanup; - if (!tty || !info->tx_buf) + if (!info->tx_buf) goto cleanup; if (info->params.mode == MGSL_MODE_HDLC) { @@ -1067,7 +1067,7 @@ static void put_char(struct tty_struct * if (sanity_check(info, tty->name, "put_char")) return; - if (!tty || !info->tx_buf) + if (!info->tx_buf) return; spin_lock_irqsave(&info->lock,flags); diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index f58ad7f..ef68d15 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c @@ -343,7 +343,7 @@ static ssize_t store_received_ref_clk3b( val = (unsigned char)tmp; spin_lock_irqsave(&event_lock, flags); - SET_PORT_BITS(TLCLK_REG1, 0xef, val << 1); + SET_PORT_BITS(TLCLK_REG1, 0xdf, val << 1); spin_unlock_irqrestore(&event_lock, flags); return strnlen(buf, count); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index a88b94a..8b2a599 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2961,12 +2961,14 @@ static struct class *tty_class; * This field is optional, if there is no known struct device for this * tty device it can be set to NULL safely. * + * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error). + * * This call is required to be made to register an individual tty device if * the tty driver's flags have the TTY_DRIVER_NO_DEVFS bit set. If that * bit is not set, this function should not be called. */ -void tty_register_device(struct tty_driver *driver, unsigned index, - struct device *device) +struct class_device *tty_register_device(struct tty_driver *driver, + unsigned index, struct device *device) { char name[64]; dev_t dev = MKDEV(driver->major, driver->minor_start) + index; @@ -2974,7 +2976,7 @@ void tty_register_device(struct tty_driv if (index >= driver->num) { printk(KERN_ERR "Attempt to register invalid tty line number " " (%d).\n", index); - return; + return ERR_PTR(-EINVAL); } devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, @@ -2984,7 +2986,8 @@ void tty_register_device(struct tty_driv pty_line_name(driver, index, name); else tty_line_name(driver, index, name); - class_device_create(tty_class, NULL, dev, device, "%s", name); + + return class_device_create(tty_class, NULL, dev, device, "%s", name); } /** diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 60aabdb..11c7e9d 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -989,7 +989,7 @@ static int viotape_remove(struct vio_dev * support. */ static struct vio_device_id viotape_device_table[] __devinitdata = { - { "viotape", "" }, + { "byte", "IBM,iSeries-viotape" }, { "", "" } }; MODULE_DEVICE_TABLE(vio, viotape_device_table); diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 6c94879..714d95f 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -98,7 +98,22 @@ #include #include #include +#define MAX_NR_CON_DRIVER 16 +#define CON_DRIVER_FLAG_MODULE 1 +#define CON_DRIVER_FLAG_INIT 2 + +struct con_driver { + const struct consw *con; + const char *desc; + struct class_device *class_dev; + int node; + int first; + int last; + int flag; +}; + +static struct con_driver registered_con_driver[MAX_NR_CON_DRIVER]; const struct consw *conswitchp; /* A bitmap for codes <32. A bit of 1 indicates that the code @@ -2557,7 +2572,7 @@ static int __init con_init(void) { const char *display_desc = NULL; struct vc_data *vc; - unsigned int currcons = 0; + unsigned int currcons = 0, i; acquire_console_sem(); @@ -2569,6 +2584,22 @@ static int __init con_init(void) return 0; } + for (i = 0; i < MAX_NR_CON_DRIVER; i++) { + struct con_driver *con_driver = ®istered_con_driver[i]; + + if (con_driver->con == NULL) { + con_driver->con = conswitchp; + con_driver->desc = display_desc; + con_driver->flag = CON_DRIVER_FLAG_INIT; + con_driver->first = 0; + con_driver->last = MAX_NR_CONSOLES - 1; + break; + } + } + + for (i = 0; i < MAX_NR_CONSOLES; i++) + con_driver_map[i] = conswitchp; + init_timer(&console_timer); console_timer.function = blank_screen_t; if (blankinterval) { @@ -2656,38 +2687,53 @@ #endif } #ifndef VT_SINGLE_DRIVER +#include -/* - * If we support more console drivers, this function is used - * when a driver wants to take over some existing consoles - * and become default driver for newly opened ones. - */ +static struct class *vtconsole_class; -int take_over_console(const struct consw *csw, int first, int last, int deflt) +static int bind_con_driver(const struct consw *csw, int first, int last, + int deflt) { - int i, j = -1; - const char *desc; - struct module *owner; + struct module *owner = csw->owner; + const char *desc = NULL; + struct con_driver *con_driver; + int i, j = -1, k = -1, retval = -ENODEV; - owner = csw->owner; if (!try_module_get(owner)) return -ENODEV; acquire_console_sem(); - desc = csw->con_startup(); - if (!desc) { - release_console_sem(); - module_put(owner); - return -ENODEV; + /* check if driver is registered */ + for (i = 0; i < MAX_NR_CON_DRIVER; i++) { + con_driver = ®istered_con_driver[i]; + + if (con_driver->con == csw) { + desc = con_driver->desc; + retval = 0; + break; + } + } + + if (retval) + goto err; + + if (!(con_driver->flag & CON_DRIVER_FLAG_INIT)) { + csw->con_startup(); + con_driver->flag |= CON_DRIVER_FLAG_INIT; } + if (deflt) { if (conswitchp) module_put(conswitchp->owner); + __module_get(owner); conswitchp = csw; } + first = max(first, con_driver->first); + last = min(last, con_driver->last); + for (i = first; i <= last; i++) { int old_was_color; struct vc_data *vc = vc_cons[i].d; @@ -2701,15 +2747,17 @@ int take_over_console(const struct consw continue; j = i; - if (CON_IS_VISIBLE(vc)) + + if (CON_IS_VISIBLE(vc)) { + k = i; save_screen(vc); + } + old_was_color = vc->vc_can_do_color; vc->vc_sw->con_deinit(vc); vc->vc_origin = (unsigned long)vc->vc_screenbuf; - vc->vc_visible_origin = vc->vc_origin; - vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size; - vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x; visual_init(vc, i, 0); + set_origin(vc); update_attr(vc); /* If the console changed between mono <-> color, then @@ -2718,36 +2766,506 @@ int take_over_console(const struct consw */ if (old_was_color != vc->vc_can_do_color) clear_buffer_attributes(vc); - - if (CON_IS_VISIBLE(vc)) - update_screen(vc); } + printk("Console: switching "); if (!deflt) printk("consoles %d-%d ", first+1, last+1); - if (j >= 0) + if (j >= 0) { + struct vc_data *vc = vc_cons[j].d; + printk("to %s %s %dx%d\n", - vc_cons[j].d->vc_can_do_color ? "colour" : "mono", - desc, vc_cons[j].d->vc_cols, vc_cons[j].d->vc_rows); - else + vc->vc_can_do_color ? "colour" : "mono", + desc, vc->vc_cols, vc->vc_rows); + + if (k >= 0) { + vc = vc_cons[k].d; + update_screen(vc); + } + } else printk("to %s\n", desc); + retval = 0; +err: release_console_sem(); + module_put(owner); + return retval; +}; + +#ifdef CONFIG_VT_HW_CONSOLE_BINDING +static int con_is_graphics(const struct consw *csw, int first, int last) +{ + int i, retval = 0; + + for (i = first; i <= last; i++) { + struct vc_data *vc = vc_cons[i].d; + + if (vc && vc->vc_mode == KD_GRAPHICS) { + retval = 1; + break; + } + } + + return retval; +} + +static int unbind_con_driver(const struct consw *csw, int first, int last, + int deflt) +{ + struct module *owner = csw->owner; + const struct consw *defcsw = NULL; + struct con_driver *con_driver = NULL, *con_back = NULL; + int i, retval = -ENODEV; + + if (!try_module_get(owner)) + return -ENODEV; + + acquire_console_sem(); + + /* check if driver is registered and if it is unbindable */ + for (i = 0; i < MAX_NR_CON_DRIVER; i++) { + con_driver = ®istered_con_driver[i]; + + if (con_driver->con == csw && + con_driver->flag & CON_DRIVER_FLAG_MODULE) { + retval = 0; + break; + } + } + + if (retval) { + release_console_sem(); + goto err; + } + + retval = -ENODEV; + + /* check if backup driver exists */ + for (i = 0; i < MAX_NR_CON_DRIVER; i++) { + con_back = ®istered_con_driver[i]; + + if (con_back->con && + !(con_back->flag & CON_DRIVER_FLAG_MODULE)) { + defcsw = con_back->con; + retval = 0; + break; + } + } + + if (retval) { + release_console_sem(); + goto err; + } + + if (!con_is_bound(csw)) { + release_console_sem(); + goto err; + } + + first = max(first, con_driver->first); + last = min(last, con_driver->last); + + for (i = first; i <= last; i++) { + if (con_driver_map[i] == csw) { + module_put(csw->owner); + con_driver_map[i] = NULL; + } + } + + if (!con_is_bound(defcsw)) { + const struct consw *defconsw = conswitchp; + + defcsw->con_startup(); + con_back->flag |= CON_DRIVER_FLAG_INIT; + /* + * vgacon may change the default driver to point + * to dummycon, we restore it here... + */ + conswitchp = defconsw; + } + + if (!con_is_bound(csw)) + con_driver->flag &= ~CON_DRIVER_FLAG_INIT; + release_console_sem(); + /* ignore return value, binding should not fail */ + bind_con_driver(defcsw, first, last, deflt); +err: module_put(owner); + return retval; + +} + +static int vt_bind(struct con_driver *con) +{ + const struct consw *defcsw = NULL, *csw = NULL; + int i, more = 1, first = -1, last = -1, deflt = 0; + + if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) || + con_is_graphics(con->con, con->first, con->last)) + goto err; + + csw = con->con; + + for (i = 0; i < MAX_NR_CON_DRIVER; i++) { + struct con_driver *con = ®istered_con_driver[i]; + + if (con->con && !(con->flag & CON_DRIVER_FLAG_MODULE)) { + defcsw = con->con; + break; + } + } + + if (!defcsw) + goto err; + + while (more) { + more = 0; + + for (i = con->first; i <= con->last; i++) { + if (con_driver_map[i] == defcsw) { + if (first == -1) + first = i; + last = i; + more = 1; + } else if (first != -1) + break; + } + + if (first == 0 && last == MAX_NR_CONSOLES -1) + deflt = 1; + + if (first != -1) + bind_con_driver(csw, first, last, deflt); + + first = -1; + last = -1; + deflt = 0; + } + +err: return 0; } -void give_up_console(const struct consw *csw) +static int vt_unbind(struct con_driver *con) +{ + const struct consw *csw = NULL; + int i, more = 1, first = -1, last = -1, deflt = 0; + + if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) || + con_is_graphics(con->con, con->first, con->last)) + goto err; + + csw = con->con; + + while (more) { + more = 0; + + for (i = con->first; i <= con->last; i++) { + if (con_driver_map[i] == csw) { + if (first == -1) + first = i; + last = i; + more = 1; + } else if (first != -1) + break; + } + + if (first == 0 && last == MAX_NR_CONSOLES -1) + deflt = 1; + + if (first != -1) + unbind_con_driver(csw, first, last, deflt); + + first = -1; + last = -1; + deflt = 0; + } + +err: + return 0; +} +#else +static inline int vt_bind(struct con_driver *con) +{ + return 0; +} +static inline int vt_unbind(struct con_driver *con) +{ + return 0; +} +#endif /* CONFIG_VT_HW_CONSOLE_BINDING */ + +static ssize_t store_bind(struct class_device *class_device, + const char *buf, size_t count) +{ + struct con_driver *con = class_get_devdata(class_device); + int bind = simple_strtoul(buf, NULL, 0); + + if (bind) + vt_bind(con); + else + vt_unbind(con); + + return count; +} + +static ssize_t show_bind(struct class_device *class_device, char *buf) +{ + struct con_driver *con = class_get_devdata(class_device); + int bind = con_is_bound(con->con); + + return snprintf(buf, PAGE_SIZE, "%i\n", bind); +} + +static ssize_t show_name(struct class_device *class_device, char *buf) +{ + struct con_driver *con = class_get_devdata(class_device); + + return snprintf(buf, PAGE_SIZE, "%s %s\n", + (con->flag & CON_DRIVER_FLAG_MODULE) ? "(M)" : "(S)", + con->desc); + +} + +static struct class_device_attribute class_device_attrs[] = { + __ATTR(bind, S_IRUGO|S_IWUSR, show_bind, store_bind), + __ATTR(name, S_IRUGO, show_name, NULL), +}; + +static int vtconsole_init_class_device(struct con_driver *con) +{ + int i; + + class_set_devdata(con->class_dev, con); + for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) + class_device_create_file(con->class_dev, + &class_device_attrs[i]); + + return 0; +} + +static void vtconsole_deinit_class_device(struct con_driver *con) { int i; - for(i = 0; i < MAX_NR_CONSOLES; i++) + for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) + class_device_remove_file(con->class_dev, + &class_device_attrs[i]); +} + +/** + * con_is_bound - checks if driver is bound to the console + * @csw: console driver + * + * RETURNS: zero if unbound, nonzero if bound + * + * Drivers can call this and if zero, they should release + * all resources allocated on con_startup() + */ +int con_is_bound(const struct consw *csw) +{ + int i, bound = 0; + + for (i = 0; i < MAX_NR_CONSOLES; i++) { if (con_driver_map[i] == csw) { - module_put(csw->owner); - con_driver_map[i] = NULL; + bound = 1; + break; + } + } + + return bound; +} +EXPORT_SYMBOL(con_is_bound); + +/** + * register_con_driver - register console driver to console layer + * @csw: console driver + * @first: the first console to take over, minimum value is 0 + * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1 + * + * DESCRIPTION: This function registers a console driver which can later + * bind to a range of consoles specified by @first and @last. It will + * also initialize the console driver by calling con_startup(). + */ +int register_con_driver(const struct consw *csw, int first, int last) +{ + struct module *owner = csw->owner; + struct con_driver *con_driver; + const char *desc; + int i, retval = 0; + + if (!try_module_get(owner)) + return -ENODEV; + + acquire_console_sem(); + + for (i = 0; i < MAX_NR_CON_DRIVER; i++) { + con_driver = ®istered_con_driver[i]; + + /* already registered */ + if (con_driver->con == csw) + retval = -EINVAL; + } + + if (retval) + goto err; + + desc = csw->con_startup(); + + if (!desc) + goto err; + + retval = -EINVAL; + + for (i = 0; i < MAX_NR_CON_DRIVER; i++) { + con_driver = ®istered_con_driver[i]; + + if (con_driver->con == NULL) { + con_driver->con = csw; + con_driver->desc = desc; + con_driver->node = i; + con_driver->flag = CON_DRIVER_FLAG_MODULE | + CON_DRIVER_FLAG_INIT; + con_driver->first = first; + con_driver->last = last; + retval = 0; + break; + } + } + + if (retval) + goto err; + + con_driver->class_dev = class_device_create(vtconsole_class, NULL, + MKDEV(0, con_driver->node), + NULL, "vtcon%i", + con_driver->node); + + if (IS_ERR(con_driver->class_dev)) { + printk(KERN_WARNING "Unable to create class_device for %s; " + "errno = %ld\n", con_driver->desc, + PTR_ERR(con_driver->class_dev)); + con_driver->class_dev = NULL; + } else { + vtconsole_init_class_device(con_driver); + } +err: + release_console_sem(); + module_put(owner); + return retval; +} +EXPORT_SYMBOL(register_con_driver); + +/** + * unregister_con_driver - unregister console driver from console layer + * @csw: console driver + * + * DESCRIPTION: All drivers that registers to the console layer must + * call this function upon exit, or if the console driver is in a state + * where it won't be able to handle console services, such as the + * framebuffer console without loaded framebuffer drivers. + * + * The driver must unbind first prior to unregistration. + */ +int unregister_con_driver(const struct consw *csw) +{ + int i, retval = -ENODEV; + + acquire_console_sem(); + + /* cannot unregister a bound driver */ + if (con_is_bound(csw)) + goto err; + + for (i = 0; i < MAX_NR_CON_DRIVER; i++) { + struct con_driver *con_driver = ®istered_con_driver[i]; + + if (con_driver->con == csw && + con_driver->flag & CON_DRIVER_FLAG_MODULE) { + vtconsole_deinit_class_device(con_driver); + class_device_destroy(vtconsole_class, + MKDEV(0, con_driver->node)); + con_driver->con = NULL; + con_driver->desc = NULL; + con_driver->class_dev = NULL; + con_driver->node = 0; + con_driver->flag = 0; + con_driver->first = 0; + con_driver->last = 0; + retval = 0; + break; + } + } +err: + release_console_sem(); + return retval; +} +EXPORT_SYMBOL(unregister_con_driver); + +/* + * If we support more console drivers, this function is used + * when a driver wants to take over some existing consoles + * and become default driver for newly opened ones. + * + * take_over_console is basically a register followed by unbind + */ +int take_over_console(const struct consw *csw, int first, int last, int deflt) +{ + int err; + + err = register_con_driver(csw, first, last); + + if (!err) + bind_con_driver(csw, first, last, deflt); + + return err; +} + +/* + * give_up_console is a wrapper to unregister_con_driver. It will only + * work if driver is fully unbound. + */ +void give_up_console(const struct consw *csw) +{ + unregister_con_driver(csw); +} + +static int __init vtconsole_class_init(void) +{ + int i; + + vtconsole_class = class_create(THIS_MODULE, "vtconsole"); + if (IS_ERR(vtconsole_class)) { + printk(KERN_WARNING "Unable to create vt console class; " + "errno = %ld\n", PTR_ERR(vtconsole_class)); + vtconsole_class = NULL; + } + + /* Add system drivers to sysfs */ + for (i = 0; i < MAX_NR_CON_DRIVER; i++) { + struct con_driver *con = ®istered_con_driver[i]; + + if (con->con && !con->class_dev) { + con->class_dev = + class_device_create(vtconsole_class, NULL, + MKDEV(0, con->node), NULL, + "vtcon%i", con->node); + + if (IS_ERR(con->class_dev)) { + printk(KERN_WARNING "Unable to create " + "class_device for %s; errno = %ld\n", + con->desc, PTR_ERR(con->class_dev)); + con->class_dev = NULL; + } else { + vtconsole_init_class_device(con); + } } + } + + return 0; } +postcore_initcall(vtconsole_class_init); #endif diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile new file mode 100644 index 0000000..a522254 --- /dev/null +++ b/drivers/clocksource/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o +obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o +obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c new file mode 100644 index 0000000..7ad3be8 --- /dev/null +++ b/drivers/clocksource/acpi_pm.c @@ -0,0 +1,177 @@ +/* + * linux/drivers/clocksource/acpi_pm.c + * + * This file contains the ACPI PM based clocksource. + * + * This code was largely moved from the i386 timer_pm.c file + * which was (C) Dominik Brodowski 2003 + * and contained the following comments: + * + * Driver to use the Power Management Timer (PMTMR) available in some + * southbridges as primary timing source for the Linux kernel. + * + * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c, + * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4. + * + * This file is licensed under the GPL v2. + */ + +#include +#include +#include +#include +#include + +/* Number of PMTMR ticks expected during calibration run */ +#define PMTMR_TICKS_PER_SEC 3579545 + +/* + * The I/O port the PMTMR resides at. + * The location is detected during setup_arch(), + * in arch/i386/acpi/boot.c + */ +u32 pmtmr_ioport __read_mostly; + +#define ACPI_PM_MASK CLOCKSOURCE_MASK(24) /* limit it to 24 bits */ + +static inline u32 read_pmtmr(void) +{ + /* mask the output to 24 bits */ + return inl(pmtmr_ioport) & ACPI_PM_MASK; +} + +static cycle_t acpi_pm_read_verified(void) +{ + u32 v1 = 0, v2 = 0, v3 = 0; + + /* + * It has been reported that because of various broken + * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM clock + * source is not latched, you must read it multiple + * times to ensure a safe value is read: + */ + do { + v1 = read_pmtmr(); + v2 = read_pmtmr(); + v3 = read_pmtmr(); + } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) + || (v3 > v1 && v3 < v2)); + + return (cycle_t)v2; +} + +static cycle_t acpi_pm_read(void) +{ + return (cycle_t)read_pmtmr(); +} + +static struct clocksource clocksource_acpi_pm = { + .name = "acpi_pm", + .rating = 200, + .read = acpi_pm_read, + .mask = (cycle_t)ACPI_PM_MASK, + .mult = 0, /*to be caluclated*/ + .shift = 22, + .is_continuous = 1, +}; + + +#ifdef CONFIG_PCI +static int acpi_pm_good; +static int __init acpi_pm_good_setup(char *__str) +{ + acpi_pm_good = 1; + return 1; +} +__setup("acpi_pm_good", acpi_pm_good_setup); + +static inline void acpi_pm_need_workaround(void) +{ + clocksource_acpi_pm.read = acpi_pm_read_verified; + clocksource_acpi_pm.rating = 110; +} + +/* + * PIIX4 Errata: + * + * The power management timer may return improper results when read. + * Although the timer value settles properly after incrementing, + * while incrementing there is a 3 ns window every 69.8 ns where the + * timer value is indeterminate (a 4.2% chance that the data will be + * incorrect when read). As a result, the ACPI free running count up + * timer specification is violated due to erroneous reads. + */ +static void __devinit acpi_pm_check_blacklist(struct pci_dev *dev) +{ + u8 rev; + + if (acpi_pm_good) + return; + + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + /* the bug has been fixed in PIIX4M */ + if (rev < 3) { + printk(KERN_WARNING "* Found PM-Timer Bug on the chipset." + " Due to workarounds for a bug,\n" + "* this clock source is slow. Consider trying" + " other clock sources\n"); + + acpi_pm_need_workaround(); + } +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, + acpi_pm_check_blacklist); + +static void __devinit acpi_pm_check_graylist(struct pci_dev *dev) +{ + if (acpi_pm_good) + return; + + printk(KERN_WARNING "* The chipset may have PM-Timer Bug. Due to" + " workarounds for a bug,\n" + "* this clock source is slow. If you are sure your timer" + " does not have\n" + "* this bug, please use \"acpi_pm_good\" to disable the" + " workaround\n"); + + acpi_pm_need_workaround(); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, + acpi_pm_check_graylist); +#endif + + +static int __init init_acpi_pm_clocksource(void) +{ + u32 value1, value2; + unsigned int i; + + if (!pmtmr_ioport) + return -ENODEV; + + clocksource_acpi_pm.mult = clocksource_hz2mult(PMTMR_TICKS_PER_SEC, + clocksource_acpi_pm.shift); + + /* "verify" this timing source: */ + value1 = read_pmtmr(); + for (i = 0; i < 10000; i++) { + value2 = read_pmtmr(); + if (value2 == value1) + continue; + if (value2 > value1) + goto pm_good; + if ((value2 < value1) && ((value2) < 0xFFF)) + goto pm_good; + printk(KERN_INFO "PM-Timer had inconsistent results:" + " 0x%#x, 0x%#x - aborting.\n", value1, value2); + return -EINVAL; + } + printk(KERN_INFO "PM-Timer had no reasonable result:" + " 0x%#x - aborting.\n", value1); + return -ENODEV; + +pm_good: + return clocksource_register(&clocksource_acpi_pm); +} + +module_init(init_acpi_pm_clocksource); diff --git a/drivers/clocksource/cyclone.c b/drivers/clocksource/cyclone.c new file mode 100644 index 0000000..bf4d3d5 --- /dev/null +++ b/drivers/clocksource/cyclone.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "mach_timer.h" + +#define CYCLONE_CBAR_ADDR 0xFEB00CD0 /* base address ptr */ +#define CYCLONE_PMCC_OFFSET 0x51A0 /* offset to control register */ +#define CYCLONE_MPCS_OFFSET 0x51A8 /* offset to select register */ +#define CYCLONE_MPMC_OFFSET 0x51D0 /* offset to count register */ +#define CYCLONE_TIMER_FREQ 99780000 /* 100Mhz, but not really */ +#define CYCLONE_TIMER_MASK CLOCKSOURCE_MASK(32) /* 32 bit mask */ + +int use_cyclone = 0; +static void __iomem *cyclone_ptr; + +static cycle_t read_cyclone(void) +{ + return (cycle_t)readl(cyclone_ptr); +} + +static struct clocksource clocksource_cyclone = { + .name = "cyclone", + .rating = 250, + .read = read_cyclone, + .mask = CYCLONE_TIMER_MASK, + .mult = 10, + .shift = 0, + .is_continuous = 1, +}; + +static int __init init_cyclone_clocksource(void) +{ + unsigned long base; /* saved value from CBAR */ + unsigned long offset; + u32 __iomem* volatile cyclone_timer; /* Cyclone MPMC0 register */ + u32 __iomem* reg; + int i; + + /* make sure we're on a summit box: */ + if (!use_cyclone) + return -ENODEV; + + printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n"); + + /* find base address: */ + offset = CYCLONE_CBAR_ADDR; + reg = ioremap_nocache(offset, sizeof(reg)); + if (!reg) { + printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n"); + return -ENODEV; + } + /* even on 64bit systems, this is only 32bits: */ + base = readl(reg); + if (!base) { + printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n"); + return -ENODEV; + } + iounmap(reg); + + /* setup PMCC: */ + offset = base + CYCLONE_PMCC_OFFSET; + reg = ioremap_nocache(offset, sizeof(reg)); + if (!reg) { + printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n"); + return -ENODEV; + } + writel(0x00000001,reg); + iounmap(reg); + + /* setup MPCS: */ + offset = base + CYCLONE_MPCS_OFFSET; + reg = ioremap_nocache(offset, sizeof(reg)); + if (!reg) { + printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n"); + return -ENODEV; + } + writel(0x00000001,reg); + iounmap(reg); + + /* map in cyclone_timer: */ + offset = base + CYCLONE_MPMC_OFFSET; + cyclone_timer = ioremap_nocache(offset, sizeof(u64)); + if (!cyclone_timer) { + printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n"); + return -ENODEV; + } + + /* quick test to make sure its ticking: */ + for (i = 0; i < 3; i++){ + u32 old = readl(cyclone_timer); + int stall = 100; + + while (stall--) + barrier(); + + if (readl(cyclone_timer) == old) { + printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n"); + iounmap(cyclone_timer); + cyclone_timer = NULL; + return -ENODEV; + } + } + cyclone_ptr = cyclone_timer; + + /* sort out mult/shift values: */ + clocksource_cyclone.shift = 22; + clocksource_cyclone.mult = clocksource_hz2mult(CYCLONE_TIMER_FREQ, + clocksource_cyclone.shift); + + return clocksource_register(&clocksource_cyclone); +} + +module_init(init_cyclone_clocksource); diff --git a/drivers/clocksource/scx200_hrt.c b/drivers/clocksource/scx200_hrt.c new file mode 100644 index 0000000..d418b82 --- /dev/null +++ b/drivers/clocksource/scx200_hrt.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2006 Jim Cromie + * + * This is a clocksource driver for the Geode SCx200's 1 or 27 MHz + * high-resolution timer. The Geode SC-1100 (at least) has a buggy + * time stamp counter (TSC), which loses time unless 'idle=poll' is + * given as a boot-arg. In its absence, the Generic Timekeeping code + * will detect and de-rate the bad TSC, allowing this timer to take + * over timekeeping duties. + * + * Based on work by John Stultz, and Ted Phelps (in a 2.6.12-rc6 patch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include + +#define NAME "scx200_hrt" + +static int mhz27; +module_param(mhz27, int, 0); /* load time only */ +MODULE_PARM_DESC(mhz27, "count at 27.0 MHz (default is 1.0 MHz)"); + +static int ppm; +module_param(ppm, int, 0); /* load time only */ +MODULE_PARM_DESC(ppm, "+-adjust to actual XO freq (ppm)"); + +/* HiRes Timer configuration register address */ +#define SCx200_TMCNFG_OFFSET (SCx200_TIMER_OFFSET + 5) + +/* and config settings */ +#define HR_TMEN (1 << 0) /* timer interrupt enable */ +#define HR_TMCLKSEL (1 << 1) /* 1|0 counts at 27|1 MHz */ +#define HR_TM27MPD (1 << 2) /* 1 turns off input clock (power-down) */ + +/* The base timer frequency, * 27 if selected */ +#define HRT_FREQ 1000000 + +static cycle_t read_hrt(void) +{ + /* Read the timer value */ + return (cycle_t) inl(scx200_cb_base + SCx200_TIMER_OFFSET); +} + +#define HRT_SHIFT_1 22 +#define HRT_SHIFT_27 26 + +static struct clocksource cs_hrt = { + .name = "scx200_hrt", + .rating = 250, + .read = read_hrt, + .mask = CLOCKSOURCE_MASK(32), + .is_continuous = 1, + /* mult, shift are set based on mhz27 flag */ +}; + +static int __init init_hrt_clocksource(void) +{ + /* Make sure scx200 has initializedd the configuration block */ + if (!scx200_cb_present()) + return -ENODEV; + + /* Reserve the timer's ISA io-region for ourselves */ + if (!request_region(scx200_cb_base + SCx200_TIMER_OFFSET, + SCx200_TIMER_SIZE, + "NatSemi SCx200 High-Resolution Timer")) { + printk(KERN_WARNING NAME ": unable to lock timer region\n"); + return -ENODEV; + } + + /* write timer config */ + outb(HR_TMEN | (mhz27) ? HR_TMCLKSEL : 0, + scx200_cb_base + SCx200_TMCNFG_OFFSET); + + if (mhz27) { + cs_hrt.shift = HRT_SHIFT_27; + cs_hrt.mult = clocksource_hz2mult((HRT_FREQ + ppm) * 27, + cs_hrt.shift); + } else { + cs_hrt.shift = HRT_SHIFT_1; + cs_hrt.mult = clocksource_hz2mult(HRT_FREQ + ppm, + cs_hrt.shift); + } + printk(KERN_INFO "enabling scx200 high-res timer (%s MHz +%d ppm)\n", + mhz27 ? "27":"1", ppm); + + return clocksource_register(&cs_hrt); +} + +module_init(init_hrt_clocksource); + +MODULE_AUTHOR("Jim Cromie "); +MODULE_DESCRIPTION("clocksource on SCx200 HiRes Timer"); +MODULE_LICENSE("GPL"); diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index 4b4d7db..498aa37 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c @@ -26,6 +26,7 @@ #include #include #include #include +#include #include #include diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c index 9f2f00d..05f8ce2 100644 --- a/drivers/connector/cn_queue.c +++ b/drivers/connector/cn_queue.c @@ -127,7 +127,7 @@ void cn_queue_del_callback(struct cn_que if (found) { cn_queue_free_callback(cbq); - atomic_dec_and_test(&dev->refcnt); + atomic_dec(&dev->refcnt); } } diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index 3589707..b49bacf 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -121,6 +121,7 @@ nlmsg_failure: kfree_skb(skb); return -EINVAL; } +EXPORT_SYMBOL_GPL(cn_netlink_send); /* * Callback helper - queues work and setup destructor for given data. @@ -308,6 +309,9 @@ int cn_add_callback(struct cb_id *id, ch int err; struct cn_dev *dev = &cdev; + if (!cn_already_initialized) + return -EAGAIN; + err = cn_queue_add_callback(dev->cbdev, name, id, callback); if (err) return err; @@ -316,6 +320,7 @@ int cn_add_callback(struct cb_id *id, ch return 0; } +EXPORT_SYMBOL_GPL(cn_add_callback); /* * Callback remove routing - removes callback @@ -332,6 +337,7 @@ void cn_del_callback(struct cb_id *id) cn_queue_del_callback(dev->cbdev, id); cn_notify(id, 1); } +EXPORT_SYMBOL_GPL(cn_del_callback); /* * Checks two connector's control messages to be the same. @@ -435,7 +441,7 @@ static void cn_callback(void *data) mutex_unlock(¬ify_lock); } -static int __init cn_init(void) +static int __devinit cn_init(void) { struct cn_dev *dev = &cdev; int err; @@ -456,21 +462,22 @@ static int __init cn_init(void) sock_release(dev->nls->sk_socket); return -EINVAL; } + + cn_already_initialized = 1; err = cn_add_callback(&dev->id, "connector", &cn_callback); if (err) { + cn_already_initialized = 0; cn_queue_free_dev(dev->cbdev); if (dev->nls->sk_socket) sock_release(dev->nls->sk_socket); return -EINVAL; } - cn_already_initialized = 1; - return 0; } -static void __exit cn_fini(void) +static void __devexit cn_fini(void) { struct cn_dev *dev = &cdev; @@ -482,9 +489,5 @@ static void __exit cn_fini(void) sock_release(dev->nls->sk_socket); } -module_init(cn_init); +subsys_initcall(cn_init); module_exit(cn_fini); - -EXPORT_SYMBOL_GPL(cn_add_callback); -EXPORT_SYMBOL_GPL(cn_del_callback); -EXPORT_SYMBOL_GPL(cn_netlink_send); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 29b2fa5..44d1eca 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -257,7 +257,7 @@ void cpufreq_notify_transition(struct cp if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { if ((policy) && (policy->cpu == freqs->cpu) && (policy->cur) && (policy->cur != freqs->old)) { - dprintk(KERN_WARNING "Warning: CPU frequency is" + dprintk("Warning: CPU frequency is" " %u, cpufreq assumed %u kHz.\n", freqs->old, policy->cur); freqs->old = policy->cur; @@ -874,7 +874,7 @@ static void cpufreq_out_of_sync(unsigned { struct cpufreq_freqs freqs; - dprintk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing " + dprintk("Warning: CPU frequency out of sync: cpufreq and timing " "core thinks of %u, is %u kHz.\n", old_freq, new_freq); freqs.cpu = cpu; @@ -1006,7 +1006,7 @@ static int cpufreq_suspend(struct sys_de struct cpufreq_freqs freqs; if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN)) - dprintk(KERN_DEBUG "Warning: CPU frequency is %u, " + dprintk("Warning: CPU frequency is %u, " "cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur); @@ -1087,7 +1087,7 @@ static int cpufreq_resume(struct sys_dev struct cpufreq_freqs freqs; if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN)) - dprintk(KERN_WARNING "Warning: CPU frequency" + dprintk("Warning: CPU frequency" "is %u, cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur); diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index e07a354..b3ebc8f 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -22,6 +22,7 @@ #include #include #include #include +#include #include #include #include @@ -72,6 +73,14 @@ static DEFINE_PER_CPU(struct cpu_dbs_inf static unsigned int dbs_enable; /* number of CPUs using this policy */ +/* + * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug + * lock and dbs_mutex. cpu_hotplug lock should always be held before + * dbs_mutex. If any function that can potentially take cpu_hotplug lock + * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then + * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock + * is recursive for the same process. -Venki + */ static DEFINE_MUTEX (dbs_mutex); static DECLARE_WORK (dbs_work, do_dbs_timer, NULL); @@ -414,12 +423,14 @@ static void dbs_check_cpu(int cpu) static void do_dbs_timer(void *data) { int i; + lock_cpu_hotplug(); mutex_lock(&dbs_mutex); for_each_online_cpu(i) dbs_check_cpu(i); schedule_delayed_work(&dbs_work, usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); mutex_unlock(&dbs_mutex); + unlock_cpu_hotplug(); } static inline void dbs_timer_init(void) @@ -514,6 +525,7 @@ static int cpufreq_governor_dbs(struct c break; case CPUFREQ_GOV_LIMITS: + lock_cpu_hotplug(); mutex_lock(&dbs_mutex); if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target( @@ -524,6 +536,7 @@ static int cpufreq_governor_dbs(struct c this_dbs_info->cur_policy, policy->min, CPUFREQ_RELATION_L); mutex_unlock(&dbs_mutex); + unlock_cpu_hotplug(); break; } return 0; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 3e6ffca..693e540 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -21,6 +21,7 @@ #include #include #include #include +#include #include #include #include @@ -71,6 +72,14 @@ static DEFINE_PER_CPU(struct cpu_dbs_inf static unsigned int dbs_enable; /* number of CPUs using this policy */ +/* + * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug + * lock and dbs_mutex. cpu_hotplug lock should always be held before + * dbs_mutex. If any function that can potentially take cpu_hotplug lock + * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then + * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock + * is recursive for the same process. -Venki + */ static DEFINE_MUTEX (dbs_mutex); static DECLARE_WORK (dbs_work, do_dbs_timer, NULL); @@ -363,12 +372,14 @@ static void dbs_check_cpu(int cpu) static void do_dbs_timer(void *data) { int i; + lock_cpu_hotplug(); mutex_lock(&dbs_mutex); for_each_online_cpu(i) dbs_check_cpu(i); queue_delayed_work(dbs_workq, &dbs_work, usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); mutex_unlock(&dbs_mutex); + unlock_cpu_hotplug(); } static inline void dbs_timer_init(void) @@ -469,6 +480,7 @@ static int cpufreq_governor_dbs(struct c break; case CPUFREQ_GOV_LIMITS: + lock_cpu_hotplug(); mutex_lock(&dbs_mutex); if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target( @@ -479,6 +491,7 @@ static int cpufreq_governor_dbs(struct c this_dbs_info->cur_policy, policy->min, CPUFREQ_RELATION_L); mutex_unlock(&dbs_mutex); + unlock_cpu_hotplug(); break; } return 0; diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 9694b6e..c576c0b 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -74,7 +74,7 @@ static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf) { struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu]; - if(!stat) + if (!stat) return 0; return sprintf(buf, "%d\n", cpufreq_stats_table[stat->cpu]->total_trans); @@ -86,7 +86,7 @@ show_time_in_state(struct cpufreq_policy ssize_t len = 0; int i; struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu]; - if(!stat) + if (!stat) return 0; cpufreq_stats_update(stat->cpu); for (i = 0; i < stat->state_num; i++) { @@ -104,7 +104,7 @@ show_trans_table(struct cpufreq_policy * int i, j; struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu]; - if(!stat) + if (!stat) return 0; cpufreq_stats_update(stat->cpu); len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n"); diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index a4818ce..551f4cc 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -20,7 +20,7 @@ int cpufreq_frequency_table_cpuinfo(stru { unsigned int min_freq = ~0; unsigned int max_freq = 0; - unsigned int i = 0; + unsigned int i; for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { unsigned int freq = table[i].frequency; @@ -51,7 +51,7 @@ int cpufreq_frequency_table_verify(struc struct cpufreq_frequency_table *table) { unsigned int next_larger = ~0; - unsigned int i = 0; + unsigned int i; unsigned int count = 0; dprintk("request for verification of policy (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu); @@ -91,20 +91,24 @@ int cpufreq_frequency_table_target(struc unsigned int relation, unsigned int *index) { - struct cpufreq_frequency_table optimal = { .index = ~0, }; - struct cpufreq_frequency_table suboptimal = { .index = ~0, }; + struct cpufreq_frequency_table optimal = { + .index = ~0, + .frequency = 0, + }; + struct cpufreq_frequency_table suboptimal = { + .index = ~0, + .frequency = 0, + }; unsigned int i; dprintk("request for target %u kHz (relation: %u) for cpu %u\n", target_freq, relation, policy->cpu); switch (relation) { case CPUFREQ_RELATION_H: - optimal.frequency = 0; suboptimal.frequency = ~0; break; case CPUFREQ_RELATION_L: optimal.frequency = ~0; - suboptimal.frequency = 0; break; } diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 5158a9d..17ee684 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -60,15 +60,14 @@ #define AES_EXTENDED_KEY_SIZE 64 /* in u #define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t)) struct aes_ctx { - uint32_t e_data[AES_EXTENDED_KEY_SIZE]; - uint32_t d_data[AES_EXTENDED_KEY_SIZE]; struct { struct cword encrypt; struct cword decrypt; } cword; - uint32_t *E; - uint32_t *D; + u32 *D; int key_length; + u32 E[AES_EXTENDED_KEY_SIZE]; + u32 d_data[AES_EXTENDED_KEY_SIZE]; }; /* ====== Key management routines ====== */ @@ -282,19 +281,20 @@ aes_hw_extkey_available(uint8_t key_len) return 0; } -static inline struct aes_ctx *aes_ctx(void *ctx) +static inline struct aes_ctx *aes_ctx(struct crypto_tfm *tfm) { + unsigned long addr = (unsigned long)crypto_tfm_ctx(tfm); unsigned long align = PADLOCK_ALIGNMENT; if (align <= crypto_tfm_ctx_alignment()) align = 1; - return (struct aes_ctx *)ALIGN((unsigned long)ctx, align); + return (struct aes_ctx *)ALIGN(addr, align); } -static int -aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t *flags) +static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len, u32 *flags) { - struct aes_ctx *ctx = aes_ctx(ctx_arg); + struct aes_ctx *ctx = aes_ctx(tfm); const __le32 *key = (const __le32 *)in_key; uint32_t i, t, u, v, w; uint32_t P[AES_EXTENDED_KEY_SIZE]; @@ -312,8 +312,7 @@ aes_set_key(void *ctx_arg, const uint8_t * itself we must supply the plain key for both encryption * and decryption. */ - ctx->E = ctx->e_data; - ctx->D = ctx->e_data; + ctx->D = ctx->E; E_KEY[0] = le32_to_cpu(key[0]); E_KEY[1] = le32_to_cpu(key[1]); @@ -414,24 +413,22 @@ static inline u8 *padlock_xcrypt_cbc(con return iv; } -static void -aes_encrypt(void *ctx_arg, uint8_t *out, const uint8_t *in) +static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - struct aes_ctx *ctx = aes_ctx(ctx_arg); + struct aes_ctx *ctx = aes_ctx(tfm); padlock_xcrypt_ecb(in, out, ctx->E, &ctx->cword.encrypt, 1); } -static void -aes_decrypt(void *ctx_arg, uint8_t *out, const uint8_t *in) +static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - struct aes_ctx *ctx = aes_ctx(ctx_arg); + struct aes_ctx *ctx = aes_ctx(tfm); padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, 1); } static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { - struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm)); + struct aes_ctx *ctx = aes_ctx(desc->tfm); padlock_xcrypt_ecb(in, out, ctx->E, &ctx->cword.encrypt, nbytes / AES_BLOCK_SIZE); return nbytes & ~(AES_BLOCK_SIZE - 1); @@ -440,7 +437,7 @@ static unsigned int aes_encrypt_ecb(cons static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { - struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm)); + struct aes_ctx *ctx = aes_ctx(desc->tfm); padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, nbytes / AES_BLOCK_SIZE); return nbytes & ~(AES_BLOCK_SIZE - 1); @@ -449,7 +446,7 @@ static unsigned int aes_decrypt_ecb(cons static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { - struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm)); + struct aes_ctx *ctx = aes_ctx(desc->tfm); u8 *iv; iv = padlock_xcrypt_cbc(in, out, ctx->E, desc->info, @@ -462,7 +459,7 @@ static unsigned int aes_encrypt_cbc(cons static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, const u8 *in, unsigned int nbytes) { - struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm)); + struct aes_ctx *ctx = aes_ctx(desc->tfm); padlock_xcrypt_cbc(in, out, ctx->D, desc->info, &ctx->cword.decrypt, nbytes / AES_BLOCK_SIZE); return nbytes & ~(AES_BLOCK_SIZE - 1); diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig new file mode 100644 index 0000000..30d021d --- /dev/null +++ b/drivers/dma/Kconfig @@ -0,0 +1,34 @@ +# +# DMA engine configuration +# + +menu "DMA Engine support" + +config DMA_ENGINE + bool "Support for DMA engines" + ---help--- + DMA engines offload copy operations from the CPU to dedicated + hardware, allowing the copies to happen asynchronously. + +comment "DMA Clients" + +config NET_DMA + bool "Network: TCP receive copy offload" + depends on DMA_ENGINE && NET + default y + ---help--- + This enables the use of DMA engines in the network stack to + offload receive copy-to-user operations, freeing CPU cycles. + Since this is the main user of the DMA engine, it should be enabled; + say Y here. + +comment "DMA Devices" + +config INTEL_IOATDMA + tristate "Intel I/OAT DMA support" + depends on DMA_ENGINE && PCI + default m + ---help--- + Enable support for the Intel(R) I/OAT DMA engine. + +endmenu diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile new file mode 100644 index 0000000..bdcfdbd --- /dev/null +++ b/drivers/dma/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_DMA_ENGINE) += dmaengine.o +obj-$(CONFIG_NET_DMA) += iovlock.o +obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c new file mode 100644 index 0000000..5829143 --- /dev/null +++ b/drivers/dma/dmaengine.c @@ -0,0 +1,408 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. 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. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +/* + * This code implements the DMA subsystem. It provides a HW-neutral interface + * for other kernel code to use asynchronous memory copy capabilities, + * if present, and allows different HW DMA drivers to register as providing + * this capability. + * + * Due to the fact we are accelerating what is already a relatively fast + * operation, the code goes to great lengths to avoid additional overhead, + * such as locking. + * + * LOCKING: + * + * The subsystem keeps two global lists, dma_device_list and dma_client_list. + * Both of these are protected by a mutex, dma_list_mutex. + * + * Each device has a channels list, which runs unlocked but is never modified + * once the device is registered, it's just setup by the driver. + * + * Each client has a channels list, it's only modified under the client->lock + * and in an RCU callback, so it's safe to read under rcu_read_lock(). + * + * Each device has a kref, which is initialized to 1 when the device is + * registered. A kref_put is done for each class_device registered. When the + * class_device is released, the coresponding kref_put is done in the release + * method. Every time one of the device's channels is allocated to a client, + * a kref_get occurs. When the channel is freed, the coresponding kref_put + * happens. The device's release function does a completion, so + * unregister_device does a remove event, class_device_unregister, a kref_put + * for the first reference, then waits on the completion for all other + * references to finish. + * + * Each channel has an open-coded implementation of Rusty Russell's "bigref," + * with a kref and a per_cpu local_t. A single reference is set when on an + * ADDED event, and removed with a REMOVE event. Net DMA client takes an + * extra reference per outstanding transaction. The relase function does a + * kref_put on the device. -ChrisL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_MUTEX(dma_list_mutex); +static LIST_HEAD(dma_device_list); +static LIST_HEAD(dma_client_list); + +/* --- sysfs implementation --- */ + +static ssize_t show_memcpy_count(struct class_device *cd, char *buf) +{ + struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev); + unsigned long count = 0; + int i; + + for_each_possible_cpu(i) + count += per_cpu_ptr(chan->local, i)->memcpy_count; + + return sprintf(buf, "%lu\n", count); +} + +static ssize_t show_bytes_transferred(struct class_device *cd, char *buf) +{ + struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev); + unsigned long count = 0; + int i; + + for_each_possible_cpu(i) + count += per_cpu_ptr(chan->local, i)->bytes_transferred; + + return sprintf(buf, "%lu\n", count); +} + +static ssize_t show_in_use(struct class_device *cd, char *buf) +{ + struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev); + + return sprintf(buf, "%d\n", (chan->client ? 1 : 0)); +} + +static struct class_device_attribute dma_class_attrs[] = { + __ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL), + __ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL), + __ATTR(in_use, S_IRUGO, show_in_use, NULL), + __ATTR_NULL +}; + +static void dma_async_device_cleanup(struct kref *kref); + +static void dma_class_dev_release(struct class_device *cd) +{ + struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev); + kref_put(&chan->device->refcount, dma_async_device_cleanup); +} + +static struct class dma_devclass = { + .name = "dma", + .class_dev_attrs = dma_class_attrs, + .release = dma_class_dev_release, +}; + +/* --- client and device registration --- */ + +/** + * dma_client_chan_alloc - try to allocate a channel to a client + * @client: &dma_client + * + * Called with dma_list_mutex held. + */ +static struct dma_chan *dma_client_chan_alloc(struct dma_client *client) +{ + struct dma_device *device; + struct dma_chan *chan; + unsigned long flags; + int desc; /* allocated descriptor count */ + + /* Find a channel, any DMA engine will do */ + list_for_each_entry(device, &dma_device_list, global_node) { + list_for_each_entry(chan, &device->channels, device_node) { + if (chan->client) + continue; + + desc = chan->device->device_alloc_chan_resources(chan); + if (desc >= 0) { + kref_get(&device->refcount); + kref_init(&chan->refcount); + chan->slow_ref = 0; + INIT_RCU_HEAD(&chan->rcu); + chan->client = client; + spin_lock_irqsave(&client->lock, flags); + list_add_tail_rcu(&chan->client_node, + &client->channels); + spin_unlock_irqrestore(&client->lock, flags); + return chan; + } + } + } + + return NULL; +} + +/** + * dma_client_chan_free - release a DMA channel + * @chan: &dma_chan + */ +void dma_chan_cleanup(struct kref *kref) +{ + struct dma_chan *chan = container_of(kref, struct dma_chan, refcount); + chan->device->device_free_chan_resources(chan); + chan->client = NULL; + kref_put(&chan->device->refcount, dma_async_device_cleanup); +} + +static void dma_chan_free_rcu(struct rcu_head *rcu) +{ + struct dma_chan *chan = container_of(rcu, struct dma_chan, rcu); + int bias = 0x7FFFFFFF; + int i; + for_each_possible_cpu(i) + bias -= local_read(&per_cpu_ptr(chan->local, i)->refcount); + atomic_sub(bias, &chan->refcount.refcount); + kref_put(&chan->refcount, dma_chan_cleanup); +} + +static void dma_client_chan_free(struct dma_chan *chan) +{ + atomic_add(0x7FFFFFFF, &chan->refcount.refcount); + chan->slow_ref = 1; + call_rcu(&chan->rcu, dma_chan_free_rcu); +} + +/** + * dma_chans_rebalance - reallocate channels to clients + * + * When the number of DMA channel in the system changes, + * channels need to be rebalanced among clients + */ +static void dma_chans_rebalance(void) +{ + struct dma_client *client; + struct dma_chan *chan; + unsigned long flags; + + mutex_lock(&dma_list_mutex); + + list_for_each_entry(client, &dma_client_list, global_node) { + while (client->chans_desired > client->chan_count) { + chan = dma_client_chan_alloc(client); + if (!chan) + break; + client->chan_count++; + client->event_callback(client, + chan, + DMA_RESOURCE_ADDED); + } + while (client->chans_desired < client->chan_count) { + spin_lock_irqsave(&client->lock, flags); + chan = list_entry(client->channels.next, + struct dma_chan, + client_node); + list_del_rcu(&chan->client_node); + spin_unlock_irqrestore(&client->lock, flags); + client->chan_count--; + client->event_callback(client, + chan, + DMA_RESOURCE_REMOVED); + dma_client_chan_free(chan); + } + } + + mutex_unlock(&dma_list_mutex); +} + +/** + * dma_async_client_register - allocate and register a &dma_client + * @event_callback: callback for notification of channel addition/removal + */ +struct dma_client *dma_async_client_register(dma_event_callback event_callback) +{ + struct dma_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return NULL; + + INIT_LIST_HEAD(&client->channels); + spin_lock_init(&client->lock); + client->chans_desired = 0; + client->chan_count = 0; + client->event_callback = event_callback; + + mutex_lock(&dma_list_mutex); + list_add_tail(&client->global_node, &dma_client_list); + mutex_unlock(&dma_list_mutex); + + return client; +} + +/** + * dma_async_client_unregister - unregister a client and free the &dma_client + * @client: + * + * Force frees any allocated DMA channels, frees the &dma_client memory + */ +void dma_async_client_unregister(struct dma_client *client) +{ + struct dma_chan *chan; + + if (!client) + return; + + rcu_read_lock(); + list_for_each_entry_rcu(chan, &client->channels, client_node) + dma_client_chan_free(chan); + rcu_read_unlock(); + + mutex_lock(&dma_list_mutex); + list_del(&client->global_node); + mutex_unlock(&dma_list_mutex); + + kfree(client); + dma_chans_rebalance(); +} + +/** + * dma_async_client_chan_request - request DMA channels + * @client: &dma_client + * @number: count of DMA channels requested + * + * Clients call dma_async_client_chan_request() to specify how many + * DMA channels they need, 0 to free all currently allocated. + * The resulting allocations/frees are indicated to the client via the + * event callback. + */ +void dma_async_client_chan_request(struct dma_client *client, + unsigned int number) +{ + client->chans_desired = number; + dma_chans_rebalance(); +} + +/** + * dma_async_device_register - + * @device: &dma_device + */ +int dma_async_device_register(struct dma_device *device) +{ + static int id; + int chancnt = 0; + struct dma_chan* chan; + + if (!device) + return -ENODEV; + + init_completion(&device->done); + kref_init(&device->refcount); + device->dev_id = id++; + + /* represent channels in sysfs. Probably want devs too */ + list_for_each_entry(chan, &device->channels, device_node) { + chan->local = alloc_percpu(typeof(*chan->local)); + if (chan->local == NULL) + continue; + + chan->chan_id = chancnt++; + chan->class_dev.class = &dma_devclass; + chan->class_dev.dev = NULL; + snprintf(chan->class_dev.class_id, BUS_ID_SIZE, "dma%dchan%d", + device->dev_id, chan->chan_id); + + kref_get(&device->refcount); + class_device_register(&chan->class_dev); + } + + mutex_lock(&dma_list_mutex); + list_add_tail(&device->global_node, &dma_device_list); + mutex_unlock(&dma_list_mutex); + + dma_chans_rebalance(); + + return 0; +} + +/** + * dma_async_device_unregister - + * @device: &dma_device + */ +static void dma_async_device_cleanup(struct kref *kref) +{ + struct dma_device *device; + + device = container_of(kref, struct dma_device, refcount); + complete(&device->done); +} + +void dma_async_device_unregister(struct dma_device* device) +{ + struct dma_chan *chan; + unsigned long flags; + + mutex_lock(&dma_list_mutex); + list_del(&device->global_node); + mutex_unlock(&dma_list_mutex); + + list_for_each_entry(chan, &device->channels, device_node) { + if (chan->client) { + spin_lock_irqsave(&chan->client->lock, flags); + list_del(&chan->client_node); + chan->client->chan_count--; + spin_unlock_irqrestore(&chan->client->lock, flags); + chan->client->event_callback(chan->client, + chan, + DMA_RESOURCE_REMOVED); + dma_client_chan_free(chan); + } + class_device_unregister(&chan->class_dev); + } + dma_chans_rebalance(); + + kref_put(&device->refcount, dma_async_device_cleanup); + wait_for_completion(&device->done); +} + +static int __init dma_bus_init(void) +{ + mutex_init(&dma_list_mutex); + return class_register(&dma_devclass); +} + +subsys_initcall(dma_bus_init); + +EXPORT_SYMBOL(dma_async_client_register); +EXPORT_SYMBOL(dma_async_client_unregister); +EXPORT_SYMBOL(dma_async_client_chan_request); +EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf); +EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg); +EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg); +EXPORT_SYMBOL(dma_async_memcpy_complete); +EXPORT_SYMBOL(dma_async_memcpy_issue_pending); +EXPORT_SYMBOL(dma_async_device_register); +EXPORT_SYMBOL(dma_async_device_unregister); +EXPORT_SYMBOL(dma_chan_cleanup); diff --git a/drivers/dma/ioatdma.c b/drivers/dma/ioatdma.c new file mode 100644 index 0000000..2801d14 --- /dev/null +++ b/drivers/dma/ioatdma.c @@ -0,0 +1,839 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. 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. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +/* + * This driver supports an Intel I/OAT DMA engine, which does asynchronous + * copy operations. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "ioatdma.h" +#include "ioatdma_io.h" +#include "ioatdma_registers.h" +#include "ioatdma_hw.h" + +#define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common) +#define to_ioat_device(dev) container_of(dev, struct ioat_device, common) +#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node) + +/* internal functions */ +static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent); +static void __devexit ioat_remove(struct pci_dev *pdev); + +static int enumerate_dma_channels(struct ioat_device *device) +{ + u8 xfercap_scale; + u32 xfercap; + int i; + struct ioat_dma_chan *ioat_chan; + + device->common.chancnt = ioatdma_read8(device, IOAT_CHANCNT_OFFSET); + xfercap_scale = ioatdma_read8(device, IOAT_XFERCAP_OFFSET); + xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale)); + + for (i = 0; i < device->common.chancnt; i++) { + ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL); + if (!ioat_chan) { + device->common.chancnt = i; + break; + } + + ioat_chan->device = device; + ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1)); + ioat_chan->xfercap = xfercap; + spin_lock_init(&ioat_chan->cleanup_lock); + spin_lock_init(&ioat_chan->desc_lock); + INIT_LIST_HEAD(&ioat_chan->free_desc); + INIT_LIST_HEAD(&ioat_chan->used_desc); + /* This should be made common somewhere in dmaengine.c */ + ioat_chan->common.device = &device->common; + ioat_chan->common.client = NULL; + list_add_tail(&ioat_chan->common.device_node, + &device->common.channels); + } + return device->common.chancnt; +} + +static struct ioat_desc_sw *ioat_dma_alloc_descriptor( + struct ioat_dma_chan *ioat_chan, + int flags) +{ + struct ioat_dma_descriptor *desc; + struct ioat_desc_sw *desc_sw; + struct ioat_device *ioat_device; + dma_addr_t phys; + + ioat_device = to_ioat_device(ioat_chan->common.device); + desc = pci_pool_alloc(ioat_device->dma_pool, flags, &phys); + if (unlikely(!desc)) + return NULL; + + desc_sw = kzalloc(sizeof(*desc_sw), flags); + if (unlikely(!desc_sw)) { + pci_pool_free(ioat_device->dma_pool, desc, phys); + return NULL; + } + + memset(desc, 0, sizeof(*desc)); + desc_sw->hw = desc; + desc_sw->phys = phys; + + return desc_sw; +} + +#define INITIAL_IOAT_DESC_COUNT 128 + +static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan); + +/* returns the actual number of allocated descriptors */ +static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + struct ioat_desc_sw *desc = NULL; + u16 chanctrl; + u32 chanerr; + int i; + LIST_HEAD(tmp_list); + + /* + * In-use bit automatically set by reading chanctrl + * If 0, we got it, if 1, someone else did + */ + chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET); + if (chanctrl & IOAT_CHANCTRL_CHANNEL_IN_USE) + return -EBUSY; + + /* Setup register to interrupt and write completion status on error */ + chanctrl = IOAT_CHANCTRL_CHANNEL_IN_USE | + IOAT_CHANCTRL_ERR_INT_EN | + IOAT_CHANCTRL_ANY_ERR_ABORT_EN | + IOAT_CHANCTRL_ERR_COMPLETION_EN; + ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl); + + chanerr = ioatdma_chan_read32(ioat_chan, IOAT_CHANERR_OFFSET); + if (chanerr) { + printk("IOAT: CHANERR = %x, clearing\n", chanerr); + ioatdma_chan_write32(ioat_chan, IOAT_CHANERR_OFFSET, chanerr); + } + + /* Allocate descriptors */ + for (i = 0; i < INITIAL_IOAT_DESC_COUNT; i++) { + desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL); + if (!desc) { + printk(KERN_ERR "IOAT: Only %d initial descriptors\n", i); + break; + } + list_add_tail(&desc->node, &tmp_list); + } + spin_lock_bh(&ioat_chan->desc_lock); + list_splice(&tmp_list, &ioat_chan->free_desc); + spin_unlock_bh(&ioat_chan->desc_lock); + + /* allocate a completion writeback area */ + /* doing 2 32bit writes to mmio since 1 64b write doesn't work */ + ioat_chan->completion_virt = + pci_pool_alloc(ioat_chan->device->completion_pool, + GFP_KERNEL, + &ioat_chan->completion_addr); + memset(ioat_chan->completion_virt, 0, + sizeof(*ioat_chan->completion_virt)); + ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_LOW, + ((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF); + ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_HIGH, + ((u64) ioat_chan->completion_addr) >> 32); + + ioat_start_null_desc(ioat_chan); + return i; +} + +static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan); + +static void ioat_dma_free_chan_resources(struct dma_chan *chan) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + struct ioat_device *ioat_device = to_ioat_device(chan->device); + struct ioat_desc_sw *desc, *_desc; + u16 chanctrl; + int in_use_descs = 0; + + ioat_dma_memcpy_cleanup(ioat_chan); + + ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET); + + spin_lock_bh(&ioat_chan->desc_lock); + list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) { + in_use_descs++; + list_del(&desc->node); + pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys); + kfree(desc); + } + list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) { + list_del(&desc->node); + pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys); + kfree(desc); + } + spin_unlock_bh(&ioat_chan->desc_lock); + + pci_pool_free(ioat_device->completion_pool, + ioat_chan->completion_virt, + ioat_chan->completion_addr); + + /* one is ok since we left it on there on purpose */ + if (in_use_descs > 1) + printk(KERN_ERR "IOAT: Freeing %d in use descriptors!\n", + in_use_descs - 1); + + ioat_chan->last_completion = ioat_chan->completion_addr = 0; + + /* Tell hw the chan is free */ + chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET); + chanctrl &= ~IOAT_CHANCTRL_CHANNEL_IN_USE; + ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl); +} + +/** + * do_ioat_dma_memcpy - actual function that initiates a IOAT DMA transaction + * @chan: IOAT DMA channel handle + * @dest: DMA destination address + * @src: DMA source address + * @len: transaction length in bytes + */ + +static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan, + dma_addr_t dest, + dma_addr_t src, + size_t len) +{ + struct ioat_desc_sw *first; + struct ioat_desc_sw *prev; + struct ioat_desc_sw *new; + dma_cookie_t cookie; + LIST_HEAD(new_chain); + u32 copy; + size_t orig_len; + dma_addr_t orig_src, orig_dst; + unsigned int desc_count = 0; + unsigned int append = 0; + + if (!ioat_chan || !dest || !src) + return -EFAULT; + + if (!len) + return ioat_chan->common.cookie; + + orig_len = len; + orig_src = src; + orig_dst = dest; + + first = NULL; + prev = NULL; + + spin_lock_bh(&ioat_chan->desc_lock); + + while (len) { + if (!list_empty(&ioat_chan->free_desc)) { + new = to_ioat_desc(ioat_chan->free_desc.next); + list_del(&new->node); + } else { + /* try to get another desc */ + new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC); + /* will this ever happen? */ + /* TODO add upper limit on these */ + BUG_ON(!new); + } + + copy = min((u32) len, ioat_chan->xfercap); + + new->hw->size = copy; + new->hw->ctl = 0; + new->hw->src_addr = src; + new->hw->dst_addr = dest; + new->cookie = 0; + + /* chain together the physical address list for the HW */ + if (!first) + first = new; + else + prev->hw->next = (u64) new->phys; + + prev = new; + + len -= copy; + dest += copy; + src += copy; + + list_add_tail(&new->node, &new_chain); + desc_count++; + } + new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; + new->hw->next = 0; + + /* cookie incr and addition to used_list must be atomic */ + + cookie = ioat_chan->common.cookie; + cookie++; + if (cookie < 0) + cookie = 1; + ioat_chan->common.cookie = new->cookie = cookie; + + pci_unmap_addr_set(new, src, orig_src); + pci_unmap_addr_set(new, dst, orig_dst); + pci_unmap_len_set(new, src_len, orig_len); + pci_unmap_len_set(new, dst_len, orig_len); + + /* write address into NextDescriptor field of last desc in chain */ + to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->phys; + list_splice_init(&new_chain, ioat_chan->used_desc.prev); + + ioat_chan->pending += desc_count; + if (ioat_chan->pending >= 20) { + append = 1; + ioat_chan->pending = 0; + } + + spin_unlock_bh(&ioat_chan->desc_lock); + + if (append) + ioatdma_chan_write8(ioat_chan, + IOAT_CHANCMD_OFFSET, + IOAT_CHANCMD_APPEND); + return cookie; +} + +/** + * ioat_dma_memcpy_buf_to_buf - wrapper that takes src & dest bufs + * @chan: IOAT DMA channel handle + * @dest: DMA destination address + * @src: DMA source address + * @len: transaction length in bytes + */ + +static dma_cookie_t ioat_dma_memcpy_buf_to_buf(struct dma_chan *chan, + void *dest, + void *src, + size_t len) +{ + dma_addr_t dest_addr; + dma_addr_t src_addr; + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + + dest_addr = pci_map_single(ioat_chan->device->pdev, + dest, len, PCI_DMA_FROMDEVICE); + src_addr = pci_map_single(ioat_chan->device->pdev, + src, len, PCI_DMA_TODEVICE); + + return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len); +} + +/** + * ioat_dma_memcpy_buf_to_pg - wrapper, copying from a buf to a page + * @chan: IOAT DMA channel handle + * @page: pointer to the page to copy to + * @offset: offset into that page + * @src: DMA source address + * @len: transaction length in bytes + */ + +static dma_cookie_t ioat_dma_memcpy_buf_to_pg(struct dma_chan *chan, + struct page *page, + unsigned int offset, + void *src, + size_t len) +{ + dma_addr_t dest_addr; + dma_addr_t src_addr; + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + + dest_addr = pci_map_page(ioat_chan->device->pdev, + page, offset, len, PCI_DMA_FROMDEVICE); + src_addr = pci_map_single(ioat_chan->device->pdev, + src, len, PCI_DMA_TODEVICE); + + return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len); +} + +/** + * ioat_dma_memcpy_pg_to_pg - wrapper, copying between two pages + * @chan: IOAT DMA channel handle + * @dest_pg: pointer to the page to copy to + * @dest_off: offset into that page + * @src_pg: pointer to the page to copy from + * @src_off: offset into that page + * @len: transaction length in bytes. This is guaranteed to not make a copy + * across a page boundary. + */ + +static dma_cookie_t ioat_dma_memcpy_pg_to_pg(struct dma_chan *chan, + struct page *dest_pg, + unsigned int dest_off, + struct page *src_pg, + unsigned int src_off, + size_t len) +{ + dma_addr_t dest_addr; + dma_addr_t src_addr; + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + + dest_addr = pci_map_page(ioat_chan->device->pdev, + dest_pg, dest_off, len, PCI_DMA_FROMDEVICE); + src_addr = pci_map_page(ioat_chan->device->pdev, + src_pg, src_off, len, PCI_DMA_TODEVICE); + + return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len); +} + +/** + * ioat_dma_memcpy_issue_pending - push potentially unrecognoized appended descriptors to hw + * @chan: DMA channel handle + */ + +static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + + if (ioat_chan->pending != 0) { + ioat_chan->pending = 0; + ioatdma_chan_write8(ioat_chan, + IOAT_CHANCMD_OFFSET, + IOAT_CHANCMD_APPEND); + } +} + +static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan) +{ + unsigned long phys_complete; + struct ioat_desc_sw *desc, *_desc; + dma_cookie_t cookie = 0; + + prefetch(chan->completion_virt); + + if (!spin_trylock(&chan->cleanup_lock)) + return; + + /* The completion writeback can happen at any time, + so reads by the driver need to be atomic operations + The descriptor physical addresses are limited to 32-bits + when the CPU can only do a 32-bit mov */ + +#if (BITS_PER_LONG == 64) + phys_complete = + chan->completion_virt->full & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR; +#else + phys_complete = chan->completion_virt->low & IOAT_LOW_COMPLETION_MASK; +#endif + + if ((chan->completion_virt->full & IOAT_CHANSTS_DMA_TRANSFER_STATUS) == + IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) { + printk("IOAT: Channel halted, chanerr = %x\n", + ioatdma_chan_read32(chan, IOAT_CHANERR_OFFSET)); + + /* TODO do something to salvage the situation */ + } + + if (phys_complete == chan->last_completion) { + spin_unlock(&chan->cleanup_lock); + return; + } + + spin_lock_bh(&chan->desc_lock); + list_for_each_entry_safe(desc, _desc, &chan->used_desc, node) { + + /* + * Incoming DMA requests may use multiple descriptors, due to + * exceeding xfercap, perhaps. If so, only the last one will + * have a cookie, and require unmapping. + */ + if (desc->cookie) { + cookie = desc->cookie; + + /* yes we are unmapping both _page and _single alloc'd + regions with unmap_page. Is this *really* that bad? + */ + pci_unmap_page(chan->device->pdev, + pci_unmap_addr(desc, dst), + pci_unmap_len(desc, dst_len), + PCI_DMA_FROMDEVICE); + pci_unmap_page(chan->device->pdev, + pci_unmap_addr(desc, src), + pci_unmap_len(desc, src_len), + PCI_DMA_TODEVICE); + } + + if (desc->phys != phys_complete) { + /* a completed entry, but not the last, so cleanup */ + list_del(&desc->node); + list_add_tail(&desc->node, &chan->free_desc); + } else { + /* last used desc. Do not remove, so we can append from + it, but don't look at it next time, either */ + desc->cookie = 0; + + /* TODO check status bits? */ + break; + } + } + + spin_unlock_bh(&chan->desc_lock); + + chan->last_completion = phys_complete; + if (cookie != 0) + chan->completed_cookie = cookie; + + spin_unlock(&chan->cleanup_lock); +} + +/** + * ioat_dma_is_complete - poll the status of a IOAT DMA transaction + * @chan: IOAT DMA channel handle + * @cookie: DMA transaction identifier + */ + +static enum dma_status ioat_dma_is_complete(struct dma_chan *chan, + dma_cookie_t cookie, + dma_cookie_t *done, + dma_cookie_t *used) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + dma_cookie_t last_used; + dma_cookie_t last_complete; + enum dma_status ret; + + last_used = chan->cookie; + last_complete = ioat_chan->completed_cookie; + + if (done) + *done= last_complete; + if (used) + *used = last_used; + + ret = dma_async_is_complete(cookie, last_complete, last_used); + if (ret == DMA_SUCCESS) + return ret; + + ioat_dma_memcpy_cleanup(ioat_chan); + + last_used = chan->cookie; + last_complete = ioat_chan->completed_cookie; + + if (done) + *done= last_complete; + if (used) + *used = last_used; + + return dma_async_is_complete(cookie, last_complete, last_used); +} + +/* PCI API */ + +static struct pci_device_id ioat_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) }, + { 0, } +}; + +static struct pci_driver ioat_pci_drv = { + .name = "ioatdma", + .id_table = ioat_pci_tbl, + .probe = ioat_probe, + .remove = __devexit_p(ioat_remove), +}; + +static irqreturn_t ioat_do_interrupt(int irq, void *data, struct pt_regs *regs) +{ + struct ioat_device *instance = data; + unsigned long attnstatus; + u8 intrctrl; + + intrctrl = ioatdma_read8(instance, IOAT_INTRCTRL_OFFSET); + + if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN)) + return IRQ_NONE; + + if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) { + ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl); + return IRQ_NONE; + } + + attnstatus = ioatdma_read32(instance, IOAT_ATTNSTATUS_OFFSET); + + printk(KERN_ERR "ioatdma error: interrupt! status %lx\n", attnstatus); + + ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl); + return IRQ_HANDLED; +} + +static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan) +{ + struct ioat_desc_sw *desc; + + spin_lock_bh(&ioat_chan->desc_lock); + + if (!list_empty(&ioat_chan->free_desc)) { + desc = to_ioat_desc(ioat_chan->free_desc.next); + list_del(&desc->node); + } else { + /* try to get another desc */ + spin_unlock_bh(&ioat_chan->desc_lock); + desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL); + spin_lock_bh(&ioat_chan->desc_lock); + /* will this ever happen? */ + BUG_ON(!desc); + } + + desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL; + desc->hw->next = 0; + + list_add_tail(&desc->node, &ioat_chan->used_desc); + spin_unlock_bh(&ioat_chan->desc_lock); + +#if (BITS_PER_LONG == 64) + ioatdma_chan_write64(ioat_chan, IOAT_CHAINADDR_OFFSET, desc->phys); +#else + ioatdma_chan_write32(ioat_chan, + IOAT_CHAINADDR_OFFSET_LOW, + (u32) desc->phys); + ioatdma_chan_write32(ioat_chan, IOAT_CHAINADDR_OFFSET_HIGH, 0); +#endif + ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_START); +} + +/* + * Perform a IOAT transaction to verify the HW works. + */ +#define IOAT_TEST_SIZE 2000 + +static int ioat_self_test(struct ioat_device *device) +{ + int i; + u8 *src; + u8 *dest; + struct dma_chan *dma_chan; + dma_cookie_t cookie; + int err = 0; + + src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL); + if (!src) + return -ENOMEM; + dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL); + if (!dest) { + kfree(src); + return -ENOMEM; + } + + /* Fill in src buffer */ + for (i = 0; i < IOAT_TEST_SIZE; i++) + src[i] = (u8)i; + + /* Start copy, using first DMA channel */ + dma_chan = container_of(device->common.channels.next, + struct dma_chan, + device_node); + if (ioat_dma_alloc_chan_resources(dma_chan) < 1) { + err = -ENODEV; + goto out; + } + + cookie = ioat_dma_memcpy_buf_to_buf(dma_chan, dest, src, IOAT_TEST_SIZE); + ioat_dma_memcpy_issue_pending(dma_chan); + msleep(1); + + if (ioat_dma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) { + printk(KERN_ERR "ioatdma: Self-test copy timed out, disabling\n"); + err = -ENODEV; + goto free_resources; + } + if (memcmp(src, dest, IOAT_TEST_SIZE)) { + printk(KERN_ERR "ioatdma: Self-test copy failed compare, disabling\n"); + err = -ENODEV; + goto free_resources; + } + +free_resources: + ioat_dma_free_chan_resources(dma_chan); +out: + kfree(src); + kfree(dest); + return err; +} + +static int __devinit ioat_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int err; + unsigned long mmio_start, mmio_len; + void *reg_base; + struct ioat_device *device; + + err = pci_enable_device(pdev); + if (err) + goto err_enable_device; + + err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + if (err) + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (err) + goto err_set_dma_mask; + + err = pci_request_regions(pdev, ioat_pci_drv.name); + if (err) + goto err_request_regions; + + mmio_start = pci_resource_start(pdev, 0); + mmio_len = pci_resource_len(pdev, 0); + + reg_base = ioremap(mmio_start, mmio_len); + if (!reg_base) { + err = -ENOMEM; + goto err_ioremap; + } + + device = kzalloc(sizeof(*device), GFP_KERNEL); + if (!device) { + err = -ENOMEM; + goto err_kzalloc; + } + + /* DMA coherent memory pool for DMA descriptor allocations */ + device->dma_pool = pci_pool_create("dma_desc_pool", pdev, + sizeof(struct ioat_dma_descriptor), 64, 0); + if (!device->dma_pool) { + err = -ENOMEM; + goto err_dma_pool; + } + + device->completion_pool = pci_pool_create("completion_pool", pdev, sizeof(u64), SMP_CACHE_BYTES, SMP_CACHE_BYTES); + if (!device->completion_pool) { + err = -ENOMEM; + goto err_completion_pool; + } + + device->pdev = pdev; + pci_set_drvdata(pdev, device); +#ifdef CONFIG_PCI_MSI + if (pci_enable_msi(pdev) == 0) { + device->msi = 1; + } else { + device->msi = 0; + } +#endif + err = request_irq(pdev->irq, &ioat_do_interrupt, SA_SHIRQ, "ioat", + device); + if (err) + goto err_irq; + + device->reg_base = reg_base; + + ioatdma_write8(device, IOAT_INTRCTRL_OFFSET, IOAT_INTRCTRL_MASTER_INT_EN); + pci_set_master(pdev); + + INIT_LIST_HEAD(&device->common.channels); + enumerate_dma_channels(device); + + device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources; + device->common.device_free_chan_resources = ioat_dma_free_chan_resources; + device->common.device_memcpy_buf_to_buf = ioat_dma_memcpy_buf_to_buf; + device->common.device_memcpy_buf_to_pg = ioat_dma_memcpy_buf_to_pg; + device->common.device_memcpy_pg_to_pg = ioat_dma_memcpy_pg_to_pg; + device->common.device_memcpy_complete = ioat_dma_is_complete; + device->common.device_memcpy_issue_pending = ioat_dma_memcpy_issue_pending; + printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n", + device->common.chancnt); + + err = ioat_self_test(device); + if (err) + goto err_self_test; + + dma_async_device_register(&device->common); + + return 0; + +err_self_test: +err_irq: + pci_pool_destroy(device->completion_pool); +err_completion_pool: + pci_pool_destroy(device->dma_pool); +err_dma_pool: + kfree(device); +err_kzalloc: + iounmap(reg_base); +err_ioremap: + pci_release_regions(pdev); +err_request_regions: +err_set_dma_mask: + pci_disable_device(pdev); +err_enable_device: + return err; +} + +static void __devexit ioat_remove(struct pci_dev *pdev) +{ + struct ioat_device *device; + struct dma_chan *chan, *_chan; + struct ioat_dma_chan *ioat_chan; + + device = pci_get_drvdata(pdev); + dma_async_device_unregister(&device->common); + + free_irq(device->pdev->irq, device); +#ifdef CONFIG_PCI_MSI + if (device->msi) + pci_disable_msi(device->pdev); +#endif + pci_pool_destroy(device->dma_pool); + pci_pool_destroy(device->completion_pool); + iounmap(device->reg_base); + pci_release_regions(pdev); + pci_disable_device(pdev); + list_for_each_entry_safe(chan, _chan, &device->common.channels, device_node) { + ioat_chan = to_ioat_chan(chan); + list_del(&chan->device_node); + kfree(ioat_chan); + } + kfree(device); +} + +/* MODULE API */ +MODULE_VERSION("1.7"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Intel Corporation"); + +static int __init ioat_init_module(void) +{ + /* it's currently unsafe to unload this module */ + /* if forced, worst case is that rmmod hangs */ + __unsafe(THIS_MODULE); + + pci_module_init(&ioat_pci_drv); +} + +module_init(ioat_init_module); + +static void __exit ioat_exit_module(void) +{ + pci_unregister_driver(&ioat_pci_drv); +} + +module_exit(ioat_exit_module); diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h new file mode 100644 index 0000000..a5d3b36 --- /dev/null +++ b/drivers/dma/ioatdma.h @@ -0,0 +1,125 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. 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. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +#ifndef IOATDMA_H +#define IOATDMA_H + +#include +#include "ioatdma_hw.h" +#include +#include +#include +#include + +#define IOAT_LOW_COMPLETION_MASK 0xffffffc0 + +extern struct list_head dma_device_list; +extern struct list_head dma_client_list; + +/** + * struct ioat_device - internal representation of a IOAT device + * @pdev: PCI-Express device + * @reg_base: MMIO register space base address + * @dma_pool: for allocating DMA descriptors + * @common: embedded struct dma_device + * @msi: Message Signaled Interrupt number + */ + +struct ioat_device { + struct pci_dev *pdev; + void *reg_base; + struct pci_pool *dma_pool; + struct pci_pool *completion_pool; + + struct dma_device common; + u8 msi; +}; + +/** + * struct ioat_dma_chan - internal representation of a DMA channel + * @device: + * @reg_base: + * @sw_in_use: + * @completion: + * @completion_low: + * @completion_high: + * @completed_cookie: last cookie seen completed on cleanup + * @cookie: value of last cookie given to client + * @last_completion: + * @xfercap: + * @desc_lock: + * @free_desc: + * @used_desc: + * @resource: + * @device_node: + */ + +struct ioat_dma_chan { + + void *reg_base; + + dma_cookie_t completed_cookie; + unsigned long last_completion; + + u32 xfercap; /* XFERCAP register value expanded out */ + + spinlock_t cleanup_lock; + spinlock_t desc_lock; + struct list_head free_desc; + struct list_head used_desc; + + int pending; + + struct ioat_device *device; + struct dma_chan common; + + dma_addr_t completion_addr; + union { + u64 full; /* HW completion writeback */ + struct { + u32 low; + u32 high; + }; + } *completion_virt; +}; + +/* wrapper around hardware descriptor format + additional software fields */ + +/** + * struct ioat_desc_sw - wrapper around hardware descriptor + * @hw: hardware DMA descriptor + * @node: + * @cookie: + * @phys: + */ + +struct ioat_desc_sw { + struct ioat_dma_descriptor *hw; + struct list_head node; + dma_cookie_t cookie; + dma_addr_t phys; + DECLARE_PCI_UNMAP_ADDR(src) + DECLARE_PCI_UNMAP_LEN(src_len) + DECLARE_PCI_UNMAP_ADDR(dst) + DECLARE_PCI_UNMAP_LEN(dst_len) +}; + +#endif /* IOATDMA_H */ + diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h new file mode 100644 index 0000000..4d7a128 --- /dev/null +++ b/drivers/dma/ioatdma_hw.h @@ -0,0 +1,52 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. 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. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +#ifndef _IOAT_HW_H_ +#define _IOAT_HW_H_ + +/* PCI Configuration Space Values */ +#define IOAT_PCI_VID 0x8086 +#define IOAT_PCI_DID 0x1A38 +#define IOAT_PCI_RID 0x00 +#define IOAT_PCI_SVID 0x8086 +#define IOAT_PCI_SID 0x8086 +#define IOAT_VER 0x12 /* Version 1.2 */ + +struct ioat_dma_descriptor { + uint32_t size; + uint32_t ctl; + uint64_t src_addr; + uint64_t dst_addr; + uint64_t next; + uint64_t rsv1; + uint64_t rsv2; + uint64_t user1; + uint64_t user2; +}; + +#define IOAT_DMA_DESCRIPTOR_CTL_INT_GN 0x00000001 +#define IOAT_DMA_DESCRIPTOR_CTL_SRC_SN 0x00000002 +#define IOAT_DMA_DESCRIPTOR_CTL_DST_SN 0x00000004 +#define IOAT_DMA_DESCRIPTOR_CTL_CP_STS 0x00000008 +#define IOAT_DMA_DESCRIPTOR_CTL_FRAME 0x00000010 +#define IOAT_DMA_DESCRIPTOR_NUL 0x00000020 +#define IOAT_DMA_DESCRIPTOR_OPCODE 0xFF000000 + +#endif diff --git a/drivers/dma/ioatdma_io.h b/drivers/dma/ioatdma_io.h new file mode 100644 index 0000000..c0b4bf6 --- /dev/null +++ b/drivers/dma/ioatdma_io.h @@ -0,0 +1,118 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. 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. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +#ifndef IOATDMA_IO_H +#define IOATDMA_IO_H + +#include + +/* + * device and per-channel MMIO register read and write functions + * this is a lot of anoying inline functions, but it's typesafe + */ + +static inline u8 ioatdma_read8(struct ioat_device *device, + unsigned int offset) +{ + return readb(device->reg_base + offset); +} + +static inline u16 ioatdma_read16(struct ioat_device *device, + unsigned int offset) +{ + return readw(device->reg_base + offset); +} + +static inline u32 ioatdma_read32(struct ioat_device *device, + unsigned int offset) +{ + return readl(device->reg_base + offset); +} + +static inline void ioatdma_write8(struct ioat_device *device, + unsigned int offset, u8 value) +{ + writeb(value, device->reg_base + offset); +} + +static inline void ioatdma_write16(struct ioat_device *device, + unsigned int offset, u16 value) +{ + writew(value, device->reg_base + offset); +} + +static inline void ioatdma_write32(struct ioat_device *device, + unsigned int offset, u32 value) +{ + writel(value, device->reg_base + offset); +} + +static inline u8 ioatdma_chan_read8(struct ioat_dma_chan *chan, + unsigned int offset) +{ + return readb(chan->reg_base + offset); +} + +static inline u16 ioatdma_chan_read16(struct ioat_dma_chan *chan, + unsigned int offset) +{ + return readw(chan->reg_base + offset); +} + +static inline u32 ioatdma_chan_read32(struct ioat_dma_chan *chan, + unsigned int offset) +{ + return readl(chan->reg_base + offset); +} + +static inline void ioatdma_chan_write8(struct ioat_dma_chan *chan, + unsigned int offset, u8 value) +{ + writeb(value, chan->reg_base + offset); +} + +static inline void ioatdma_chan_write16(struct ioat_dma_chan *chan, + unsigned int offset, u16 value) +{ + writew(value, chan->reg_base + offset); +} + +static inline void ioatdma_chan_write32(struct ioat_dma_chan *chan, + unsigned int offset, u32 value) +{ + writel(value, chan->reg_base + offset); +} + +#if (BITS_PER_LONG == 64) +static inline u64 ioatdma_chan_read64(struct ioat_dma_chan *chan, + unsigned int offset) +{ + return readq(chan->reg_base + offset); +} + +static inline void ioatdma_chan_write64(struct ioat_dma_chan *chan, + unsigned int offset, u64 value) +{ + writeq(value, chan->reg_base + offset); +} +#endif + +#endif /* IOATDMA_IO_H */ + diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h new file mode 100644 index 0000000..41a21ab --- /dev/null +++ b/drivers/dma/ioatdma_registers.h @@ -0,0 +1,126 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. 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. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +#ifndef _IOAT_REGISTERS_H_ +#define _IOAT_REGISTERS_H_ + + +/* MMIO Device Registers */ +#define IOAT_CHANCNT_OFFSET 0x00 /* 8-bit */ + +#define IOAT_XFERCAP_OFFSET 0x01 /* 8-bit */ +#define IOAT_XFERCAP_4KB 12 +#define IOAT_XFERCAP_8KB 13 +#define IOAT_XFERCAP_16KB 14 +#define IOAT_XFERCAP_32KB 15 +#define IOAT_XFERCAP_32GB 0 + +#define IOAT_GENCTRL_OFFSET 0x02 /* 8-bit */ +#define IOAT_GENCTRL_DEBUG_EN 0x01 + +#define IOAT_INTRCTRL_OFFSET 0x03 /* 8-bit */ +#define IOAT_INTRCTRL_MASTER_INT_EN 0x01 /* Master Interrupt Enable */ +#define IOAT_INTRCTRL_INT_STATUS 0x02 /* ATTNSTATUS -or- Channel Int */ +#define IOAT_INTRCTRL_INT 0x04 /* INT_STATUS -and- MASTER_INT_EN */ + +#define IOAT_ATTNSTATUS_OFFSET 0x04 /* Each bit is a channel */ + +#define IOAT_VER_OFFSET 0x08 /* 8-bit */ +#define IOAT_VER_MAJOR_MASK 0xF0 +#define IOAT_VER_MINOR_MASK 0x0F +#define GET_IOAT_VER_MAJOR(x) ((x) & IOAT_VER_MAJOR_MASK) +#define GET_IOAT_VER_MINOR(x) ((x) & IOAT_VER_MINOR_MASK) + +#define IOAT_PERPORTOFFSET_OFFSET 0x0A /* 16-bit */ + +#define IOAT_INTRDELAY_OFFSET 0x0C /* 16-bit */ +#define IOAT_INTRDELAY_INT_DELAY_MASK 0x3FFF /* Interrupt Delay Time */ +#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalesing Supported */ + +#define IOAT_DEVICE_STATUS_OFFSET 0x0E /* 16-bit */ +#define IOAT_DEVICE_STATUS_DEGRADED_MODE 0x0001 + + +#define IOAT_CHANNEL_MMIO_SIZE 0x80 /* Each Channel MMIO space is this size */ + +/* DMA Channel Registers */ +#define IOAT_CHANCTRL_OFFSET 0x00 /* 16-bit Channel Control Register */ +#define IOAT_CHANCTRL_CHANNEL_PRIORITY_MASK 0xF000 +#define IOAT_CHANCTRL_CHANNEL_IN_USE 0x0100 +#define IOAT_CHANCTRL_DESCRIPTOR_ADDR_SNOOP_CONTROL 0x0020 +#define IOAT_CHANCTRL_ERR_INT_EN 0x0010 +#define IOAT_CHANCTRL_ANY_ERR_ABORT_EN 0x0008 +#define IOAT_CHANCTRL_ERR_COMPLETION_EN 0x0004 +#define IOAT_CHANCTRL_INT_DISABLE 0x0001 + +#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatability */ +#define IOAT_DMA_COMP_V1 0x0001 /* Compatability with DMA version 1 */ + +#define IOAT_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */ +#define IOAT_CHANSTS_OFFSET_LOW 0x04 +#define IOAT_CHANSTS_OFFSET_HIGH 0x08 +#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR 0xFFFFFFFFFFFFFFC0 +#define IOAT_CHANSTS_SOFT_ERR 0x0000000000000010 +#define IOAT_CHANSTS_DMA_TRANSFER_STATUS 0x0000000000000007 +#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE 0x0 +#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE 0x1 +#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_SUSPENDED 0x2 +#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED 0x3 + +#define IOAT_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */ +#define IOAT_CHAINADDR_OFFSET_LOW 0x0C +#define IOAT_CHAINADDR_OFFSET_HIGH 0x10 + +#define IOAT_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */ +#define IOAT_CHANCMD_RESET 0x20 +#define IOAT_CHANCMD_RESUME 0x10 +#define IOAT_CHANCMD_ABORT 0x08 +#define IOAT_CHANCMD_SUSPEND 0x04 +#define IOAT_CHANCMD_APPEND 0x02 +#define IOAT_CHANCMD_START 0x01 + +#define IOAT_CHANCMP_OFFSET 0x18 /* 64-bit Channel Completion Address Register */ +#define IOAT_CHANCMP_OFFSET_LOW 0x18 +#define IOAT_CHANCMP_OFFSET_HIGH 0x1C + +#define IOAT_CDAR_OFFSET 0x20 /* 64-bit Current Descriptor Address Register */ +#define IOAT_CDAR_OFFSET_LOW 0x20 +#define IOAT_CDAR_OFFSET_HIGH 0x24 + +#define IOAT_CHANERR_OFFSET 0x28 /* 32-bit Channel Error Register */ +#define IOAT_CHANERR_DMA_TRANSFER_SRC_ADDR_ERR 0x0001 +#define IOAT_CHANERR_DMA_TRANSFER_DEST_ADDR_ERR 0x0002 +#define IOAT_CHANERR_NEXT_DESCRIPTOR_ADDR_ERR 0x0004 +#define IOAT_CHANERR_NEXT_DESCRIPTOR_ALIGNMENT_ERR 0x0008 +#define IOAT_CHANERR_CHAIN_ADDR_VALUE_ERR 0x0010 +#define IOAT_CHANERR_CHANCMD_ERR 0x0020 +#define IOAT_CHANERR_CHIPSET_UNCORRECTABLE_DATA_INTEGRITY_ERR 0x0040 +#define IOAT_CHANERR_DMA_UNCORRECTABLE_DATA_INTEGRITY_ERR 0x0080 +#define IOAT_CHANERR_READ_DATA_ERR 0x0100 +#define IOAT_CHANERR_WRITE_DATA_ERR 0x0200 +#define IOAT_CHANERR_DESCRIPTOR_CONTROL_ERR 0x0400 +#define IOAT_CHANERR_DESCRIPTOR_LENGTH_ERR 0x0800 +#define IOAT_CHANERR_COMPLETION_ADDR_ERR 0x1000 +#define IOAT_CHANERR_INT_CONFIGURATION_ERR 0x2000 +#define IOAT_CHANERR_SOFT_ERR 0x4000 + +#define IOAT_CHANERR_MASK_OFFSET 0x2C /* 32-bit Channel Error Register */ + +#endif /* _IOAT_REGISTERS_H_ */ diff --git a/drivers/dma/iovlock.c b/drivers/dma/iovlock.c new file mode 100644 index 0000000..5ed327e --- /dev/null +++ b/drivers/dma/iovlock.c @@ -0,0 +1,301 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * Portions based on net/core/datagram.c and copyrighted by their authors. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +/* + * This code allows the net stack to make use of a DMA engine for + * skb to iovec copies. + */ + +#include +#include +#include /* for memcpy_toiovec */ +#include +#include + +int num_pages_spanned(struct iovec *iov) +{ + return + ((PAGE_ALIGN((unsigned long)iov->iov_base + iov->iov_len) - + ((unsigned long)iov->iov_base & PAGE_MASK)) >> PAGE_SHIFT); +} + +/* + * Pin down all the iovec pages needed for len bytes. + * Return a struct dma_pinned_list to keep track of pages pinned down. + * + * We are allocating a single chunk of memory, and then carving it up into + * 3 sections, the latter 2 whose size depends on the number of iovecs and the + * total number of pages, respectively. + */ +struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) +{ + struct dma_pinned_list *local_list; + struct page **pages; + int i; + int ret; + int nr_iovecs = 0; + int iovec_len_used = 0; + int iovec_pages_used = 0; + long err; + + /* don't pin down non-user-based iovecs */ + if (segment_eq(get_fs(), KERNEL_DS)) + return NULL; + + /* determine how many iovecs/pages there are, up front */ + do { + iovec_len_used += iov[nr_iovecs].iov_len; + iovec_pages_used += num_pages_spanned(&iov[nr_iovecs]); + nr_iovecs++; + } while (iovec_len_used < len); + + /* single kmalloc for pinned list, page_list[], and the page arrays */ + local_list = kmalloc(sizeof(*local_list) + + (nr_iovecs * sizeof (struct dma_page_list)) + + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL); + if (!local_list) { + err = -ENOMEM; + goto out; + } + + /* list of pages starts right after the page list array */ + pages = (struct page **) &local_list->page_list[nr_iovecs]; + + for (i = 0; i < nr_iovecs; i++) { + struct dma_page_list *page_list = &local_list->page_list[i]; + + len -= iov[i].iov_len; + + if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) { + err = -EFAULT; + goto unpin; + } + + page_list->nr_pages = num_pages_spanned(&iov[i]); + page_list->base_address = iov[i].iov_base; + + page_list->pages = pages; + pages += page_list->nr_pages; + + /* pin pages down */ + down_read(¤t->mm->mmap_sem); + ret = get_user_pages( + current, + current->mm, + (unsigned long) iov[i].iov_base, + page_list->nr_pages, + 1, /* write */ + 0, /* force */ + page_list->pages, + NULL); + up_read(¤t->mm->mmap_sem); + + if (ret != page_list->nr_pages) { + err = -ENOMEM; + goto unpin; + } + + local_list->nr_iovecs = i + 1; + } + + return local_list; + +unpin: + dma_unpin_iovec_pages(local_list); +out: + return ERR_PTR(err); +} + +void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list) +{ + int i, j; + + if (!pinned_list) + return; + + for (i = 0; i < pinned_list->nr_iovecs; i++) { + struct dma_page_list *page_list = &pinned_list->page_list[i]; + for (j = 0; j < page_list->nr_pages; j++) { + set_page_dirty_lock(page_list->pages[j]); + page_cache_release(page_list->pages[j]); + } + } + + kfree(pinned_list); +} + +static dma_cookie_t dma_memcpy_to_kernel_iovec(struct dma_chan *chan, struct + iovec *iov, unsigned char *kdata, size_t len) +{ + dma_cookie_t dma_cookie = 0; + + while (len > 0) { + if (iov->iov_len) { + int copy = min_t(unsigned int, iov->iov_len, len); + dma_cookie = dma_async_memcpy_buf_to_buf( + chan, + iov->iov_base, + kdata, + copy); + kdata += copy; + len -= copy; + iov->iov_len -= copy; + iov->iov_base += copy; + } + iov++; + } + + return dma_cookie; +} + +/* + * We have already pinned down the pages we will be using in the iovecs. + * Each entry in iov array has corresponding entry in pinned_list->page_list. + * Using array indexing to keep iov[] and page_list[] in sync. + * Initial elements in iov array's iov->iov_len will be 0 if already copied into + * by another call. + * iov array length remaining guaranteed to be bigger than len. + */ +dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov, + struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len) +{ + int iov_byte_offset; + int copy; + dma_cookie_t dma_cookie = 0; + int iovec_idx; + int page_idx; + + if (!chan) + return memcpy_toiovec(iov, kdata, len); + + /* -> kernel copies (e.g. smbfs) */ + if (!pinned_list) + return dma_memcpy_to_kernel_iovec(chan, iov, kdata, len); + + iovec_idx = 0; + while (iovec_idx < pinned_list->nr_iovecs) { + struct dma_page_list *page_list; + + /* skip already used-up iovecs */ + while (!iov[iovec_idx].iov_len) + iovec_idx++; + + page_list = &pinned_list->page_list[iovec_idx]; + + iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK); + page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK) + - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT; + + /* break up copies to not cross page boundary */ + while (iov[iovec_idx].iov_len) { + copy = min_t(int, PAGE_SIZE - iov_byte_offset, len); + copy = min_t(int, copy, iov[iovec_idx].iov_len); + + dma_cookie = dma_async_memcpy_buf_to_pg(chan, + page_list->pages[page_idx], + iov_byte_offset, + kdata, + copy); + + len -= copy; + iov[iovec_idx].iov_len -= copy; + iov[iovec_idx].iov_base += copy; + + if (!len) + return dma_cookie; + + kdata += copy; + iov_byte_offset = 0; + page_idx++; + } + iovec_idx++; + } + + /* really bad if we ever run out of iovecs */ + BUG(); + return -EFAULT; +} + +dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov, + struct dma_pinned_list *pinned_list, struct page *page, + unsigned int offset, size_t len) +{ + int iov_byte_offset; + int copy; + dma_cookie_t dma_cookie = 0; + int iovec_idx; + int page_idx; + int err; + + /* this needs as-yet-unimplemented buf-to-buff, so punt. */ + /* TODO: use dma for this */ + if (!chan || !pinned_list) { + u8 *vaddr = kmap(page); + err = memcpy_toiovec(iov, vaddr + offset, len); + kunmap(page); + return err; + } + + iovec_idx = 0; + while (iovec_idx < pinned_list->nr_iovecs) { + struct dma_page_list *page_list; + + /* skip already used-up iovecs */ + while (!iov[iovec_idx].iov_len) + iovec_idx++; + + page_list = &pinned_list->page_list[iovec_idx]; + + iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK); + page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK) + - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT; + + /* break up copies to not cross page boundary */ + while (iov[iovec_idx].iov_len) { + copy = min_t(int, PAGE_SIZE - iov_byte_offset, len); + copy = min_t(int, copy, iov[iovec_idx].iov_len); + + dma_cookie = dma_async_memcpy_pg_to_pg(chan, + page_list->pages[page_idx], + iov_byte_offset, + page, + offset, + copy); + + len -= copy; + iov[iovec_idx].iov_len -= copy; + iov[iovec_idx].iov_base += copy; + + if (!len) + return dma_cookie; + + offset += copy; + iov_byte_offset = 0; + page_idx++; + } + iovec_idx++; + } + + /* really bad if we ever run out of iovecs */ + BUG(); + return -EFAULT; +} diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c index ec1f947..cf8768b 100644 --- a/drivers/fc4/soc.c +++ b/drivers/fc4/soc.c @@ -643,7 +643,7 @@ static inline void soc_init(struct sbus_ return; } - SOD(("SOC uses IRQ%s\n", __irq_itoa(irq))) + SOD(("SOC uses IRQ %d\n", irq)) s->port[0].fc.irq = irq; s->port[1].fc.irq = irq; diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c index 922e961..f52d1e5 100644 --- a/drivers/fc4/socal.c +++ b/drivers/fc4/socal.c @@ -767,7 +767,7 @@ static inline void socal_init(struct sbu return; } - SOD(("SOCAL uses IRQ %s\n", __irq_itoa(irq))) + SOD(("SOCAL uses IRQ %d\n", irq)) s->port[0].fc.irq = irq; s->port[1].fc.irq = irq; diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 1e371a5..731c3d5 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -6,8 +6,7 @@ # menu "Firmware Drivers" config EDD - tristate "BIOS Enhanced Disk Drive calls determine boot disk (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "BIOS Enhanced Disk Drive calls determine boot disk" depends on !IA64 help Say Y or M here if you want to enable BIOS Enhanced Disk Drive diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 948bd7e..b9e3886 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -255,10 +255,15 @@ void __init dmi_scan_machine(void) /** * dmi_check_system - check system DMI data * @list: array of dmi_system_id structures to match against + * All non-null elements of the list must match + * their slot's (field index's) data (i.e., each + * list string must be a substring of the specified + * DMI slot's string data) to be considered a + * successful match. * * Walk the blacklist table running matching functions until someone * returns non zero or we hit the end. Callback function is called for - * each successfull match. Returns the number of matches. + * each successful match. Returns the number of matches. */ int dmi_check_system(struct dmi_system_id *list) { @@ -287,7 +292,7 @@ EXPORT_SYMBOL(dmi_check_system); /** * dmi_get_system_info - return DMI data value - * @field: data index (see enum dmi_filed) + * @field: data index (see enum dmi_field) * * Returns one DMI data value, can be used to perform * complex DMI data checks. @@ -301,13 +306,13 @@ EXPORT_SYMBOL(dmi_get_system_info); /** * dmi_find_device - find onboard device by type/name * @type: device type or %DMI_DEV_TYPE_ANY to match all device types - * @desc: device name string or %NULL to match all + * @name: device name string or %NULL to match all * @from: previous device found in search, or %NULL for new search. * * Iterates through the list of known onboard devices. If a device is * found with a matching @vendor and @device, a pointer to its device * structure is returned. Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL to the @from argument. + * A new search is initiated by passing %NULL as the @from argument. * If @from is not %NULL, searches continue from next device. */ struct dmi_device * dmi_find_device(int type, const char *name, diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 99cdc61..0e31a0c 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1,5 +1,5 @@ # -# I2C Sensor chip drivers configuration +# Hardware monitoring chip drivers configuration # menu "Hardware Monitoring support" @@ -16,6 +16,10 @@ config HWMON should say Y here and also to the specific driver(s) for your sensors chip(s) below. + To find out which specific driver(s) you need, use the + sensors-detect script from the lm_sensors package. Read + for details. + This support can also be built as a module. If so, the module will be called hwmon. @@ -23,6 +27,18 @@ config HWMON_VID tristate default n +config SENSORS_ABITUGURU + tristate "Abit uGuru" + depends on HWMON && EXPERIMENTAL + help + If you say yes here you get support for the Abit uGuru chips + sensor part. The voltage and frequency control parts of the Abit + uGuru are not supported. The Abit uGuru chip can be found on Abit + uGuru featuring motherboards (most modern Abit motherboards). + + This driver can also be built as a module. If so, the module + will be called abituguru. + config SENSORS_ADM1021 tristate "Analog Devices ADM1021 and compatibles" depends on HWMON && I2C @@ -188,6 +204,16 @@ config SENSORS_LM63 This driver can also be built as a module. If so, the module will be called lm63. +config SENSORS_LM70 + tristate "National Semiconductor LM70" + depends on HWMON && SPI_MASTER && EXPERIMENTAL + help + If you say yes here you get support for the National Semiconductor + LM70 digital temperature sensor chip. + + This driver can also be built as a module. If so, the module + will be called lm70. + config SENSORS_LM75 tristate "National Semiconductor LM75 and compatibles" depends on HWMON && I2C @@ -236,11 +262,11 @@ config SENSORS_LM80 will be called lm80. config SENSORS_LM83 - tristate "National Semiconductor LM83" + tristate "National Semiconductor LM83 and compatibles" depends on HWMON && I2C help If you say yes here you get support for National Semiconductor - LM83 sensor chips. + LM82 and LM83 sensor chips. This driver can also be built as a module. If so, the module will be called lm83. @@ -333,11 +359,32 @@ config SENSORS_SMSC47M1 help If you say yes here you get support for the integrated fan monitoring and control capabilities of the SMSC LPC47B27x, - LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192 chips. + LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x, LPC47M192 and + LPC47M997 chips. + + The temperature and voltage sensor features of the LPC47M192 + and LPC47M997 are supported by another driver, select also + "SMSC LPC47M192 and compatibles" below for those. This driver can also be built as a module. If so, the module will be called smsc47m1. +config SENSORS_SMSC47M192 + tristate "SMSC LPC47M192 and compatibles" + depends on HWMON && I2C && EXPERIMENTAL + select HWMON_VID + help + If you say yes here you get support for the temperature and + voltage sensors of the SMSC LPC47M192 and LPC47M997 chips. + + The fan monitoring and control capabilities of these chips + are supported by another driver, select + "SMSC LPC47M10x and compatibles" above. You need both drivers + if you want fan control and voltage/temperature sensor support. + + This driver can also be built as a module. If so, the module + will be called smsc47m192. + config SENSORS_SMSC47B397 tristate "SMSC LPC47B397-NC" depends on HWMON && I2C && EXPERIMENTAL @@ -385,6 +432,16 @@ config SENSORS_W83781D This driver can also be built as a module. If so, the module will be called w83781d. +config SENSORS_W83791D + tristate "Winbond W83791D" + depends on HWMON && I2C && EXPERIMENTAL + select HWMON_VID + help + If you say yes here you get support for the Winbond W83791D chip. + + This driver can also be built as a module. If so, the module + will be called w83791d. + config SENSORS_W83792D tristate "Winbond W83792D" depends on HWMON && I2C && EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index fbdb8d9..3141584 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -10,7 +10,9 @@ obj-$(CONFIG_SENSORS_ASB100) += asb100.o obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o obj-$(CONFIG_SENSORS_W83792D) += w83792d.o obj-$(CONFIG_SENSORS_W83781D) += w83781d.o +obj-$(CONFIG_SENSORS_W83791D) += w83791d.o +obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o @@ -26,6 +28,7 @@ obj-$(CONFIG_SENSORS_GL520SM) += gl520sm obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_LM63) += lm63.o +obj-$(CONFIG_SENSORS_LM70) += lm70.o obj-$(CONFIG_SENSORS_LM75) += lm75.o obj-$(CONFIG_SENSORS_LM77) += lm77.o obj-$(CONFIG_SENSORS_LM78) += lm78.o @@ -40,6 +43,7 @@ obj-$(CONFIG_SENSORS_PC87360) += pc87360 obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o +obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_VT8231) += vt8231.o obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c new file mode 100644 index 0000000..59122cc --- /dev/null +++ b/drivers/hwmon/abituguru.c @@ -0,0 +1,1415 @@ +/* + abituguru.c Copyright (c) 2005-2006 Hans de Goede + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + This driver supports the sensor part of the custom Abit uGuru chip found + on Abit uGuru motherboards. Note: because of lack of specs the CPU / RAM / + etc voltage & frequency control is not supported! +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Banks */ +#define ABIT_UGURU_ALARM_BANK 0x20 /* 1x 3 bytes */ +#define ABIT_UGURU_SENSOR_BANK1 0x21 /* 16x volt and temp */ +#define ABIT_UGURU_FAN_PWM 0x24 /* 3x 5 bytes */ +#define ABIT_UGURU_SENSOR_BANK2 0x26 /* fans */ +/* max nr of sensors in bank1, a bank1 sensor can be in, temp or nc */ +#define ABIT_UGURU_MAX_BANK1_SENSORS 16 +/* Warning if you increase one of the 2 MAX defines below to 10 or higher you + should adjust the belonging _NAMES_LENGTH macro for the 2 digit number! */ +/* max nr of sensors in bank2, currently mb's with max 6 fans are known */ +#define ABIT_UGURU_MAX_BANK2_SENSORS 6 +/* max nr of pwm outputs, currently mb's with max 5 pwm outputs are known */ +#define ABIT_UGURU_MAX_PWMS 5 +/* uGuru sensor bank 1 flags */ /* Alarm if: */ +#define ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE 0x01 /* temp over warn */ +#define ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE 0x02 /* volt over max */ +#define ABIT_UGURU_VOLT_LOW_ALARM_ENABLE 0x04 /* volt under min */ +#define ABIT_UGURU_TEMP_HIGH_ALARM_FLAG 0x10 /* temp is over warn */ +#define ABIT_UGURU_VOLT_HIGH_ALARM_FLAG 0x20 /* volt is over max */ +#define ABIT_UGURU_VOLT_LOW_ALARM_FLAG 0x40 /* volt is under min */ +/* uGuru sensor bank 2 flags */ /* Alarm if: */ +#define ABIT_UGURU_FAN_LOW_ALARM_ENABLE 0x01 /* fan under min */ +/* uGuru sensor bank common flags */ +#define ABIT_UGURU_BEEP_ENABLE 0x08 /* beep if alarm */ +#define ABIT_UGURU_SHUTDOWN_ENABLE 0x80 /* shutdown if alarm */ +/* uGuru fan PWM (speed control) flags */ +#define ABIT_UGURU_FAN_PWM_ENABLE 0x80 /* enable speed control */ +/* Values used for conversion */ +#define ABIT_UGURU_FAN_MAX 15300 /* RPM */ +/* Bank1 sensor types */ +#define ABIT_UGURU_IN_SENSOR 0 +#define ABIT_UGURU_TEMP_SENSOR 1 +#define ABIT_UGURU_NC 2 +/* Timeouts / Retries, if these turn out to need a lot of fiddling we could + convert them to params. */ +/* 250 was determined by trial and error, 200 works most of the time, but not + always. I assume this is cpu-speed independent, since the ISA-bus and not + the CPU should be the bottleneck. Note that 250 sometimes is still not + enough (only reported on AN7 mb) this is handled by a higher layer. */ +#define ABIT_UGURU_WAIT_TIMEOUT 250 +/* Normally all expected status in abituguru_ready, are reported after the + first read, but sometimes not and we need to poll, 5 polls was not enough + 50 sofar is. */ +#define ABIT_UGURU_READY_TIMEOUT 50 +/* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */ +#define ABIT_UGURU_MAX_RETRIES 3 +#define ABIT_UGURU_RETRY_DELAY (HZ/5) +/* Maximum 2 timeouts in abituguru_update_device, iow 3 in a row is an error */ +#define ABIT_UGURU_MAX_TIMEOUTS 2 +/* utility macros */ +#define ABIT_UGURU_NAME "abituguru" +#define ABIT_UGURU_DEBUG(level, format, arg...) \ + if (level <= verbose) \ + printk(KERN_DEBUG ABIT_UGURU_NAME ": " format , ## arg) +/* Macros to help calculate the sysfs_names array length */ +/* sum of strlen of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0, + in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0 */ +#define ABITUGURU_IN_NAMES_LENGTH (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14) +/* sum of strlen of: temp??_input\0, temp??_max\0, temp??_crit\0, + temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0 */ +#define ABITUGURU_TEMP_NAMES_LENGTH (13 + 11 + 12 + 13 + 20 + 12 + 16) +/* sum of strlen of: fan?_input\0, fan?_min\0, fan?_alarm\0, + fan?_alarm_enable\0, fan?_beep\0, fan?_shutdown\0 */ +#define ABITUGURU_FAN_NAMES_LENGTH (11 + 9 + 11 + 18 + 10 + 14) +/* sum of strlen of: pwm?_enable\0, pwm?_auto_channels_temp\0, + pwm?_auto_point{1,2}_pwm\0, pwm?_auto_point{1,2}_temp\0 */ +#define ABITUGURU_PWM_NAMES_LENGTH (12 + 24 + 2 * 21 + 2 * 22) +/* IN_NAMES_LENGTH > TEMP_NAMES_LENGTH so assume all bank1 sensors are in */ +#define ABITUGURU_SYSFS_NAMES_LENGTH ( \ + ABIT_UGURU_MAX_BANK1_SENSORS * ABITUGURU_IN_NAMES_LENGTH + \ + ABIT_UGURU_MAX_BANK2_SENSORS * ABITUGURU_FAN_NAMES_LENGTH + \ + ABIT_UGURU_MAX_PWMS * ABITUGURU_PWM_NAMES_LENGTH) + +/* All the macros below are named identical to the oguru and oguru2 programs + reverse engineered by Olle Sandberg, hence the names might not be 100% + logical. I could come up with better names, but I prefer keeping the names + identical so that this driver can be compared with his work more easily. */ +/* Two i/o-ports are used by uGuru */ +#define ABIT_UGURU_BASE 0x00E0 +/* Used to tell uGuru what to read and to read the actual data */ +#define ABIT_UGURU_CMD 0x00 +/* Mostly used to check if uGuru is busy */ +#define ABIT_UGURU_DATA 0x04 +#define ABIT_UGURU_REGION_LENGTH 5 +/* uGuru status' */ +#define ABIT_UGURU_STATUS_WRITE 0x00 /* Ready to be written */ +#define ABIT_UGURU_STATUS_READ 0x01 /* Ready to be read */ +#define ABIT_UGURU_STATUS_INPUT 0x08 /* More input */ +#define ABIT_UGURU_STATUS_READY 0x09 /* Ready to be written */ + +/* Constants */ +/* in (Volt) sensors go up to 3494 mV, temp to 255000 millidegrees Celsius */ +static const int abituguru_bank1_max_value[2] = { 3494, 255000 }; +/* Min / Max allowed values for sensor2 (fan) alarm threshold, these values + correspond to 300-3000 RPM */ +static const u8 abituguru_bank2_min_threshold = 5; +static const u8 abituguru_bank2_max_threshold = 50; +/* Register 0 is a bitfield, 1 and 2 are pwm settings (255 = 100%), 3 and 4 + are temperature trip points. */ +static const int abituguru_pwm_settings_multiplier[5] = { 0, 1, 1, 1000, 1000 }; +/* Min / Max allowed values for pwm_settings. Note: pwm1 (CPU fan) is a + special case the minium allowed pwm% setting for this is 30% (77) on + some MB's this special case is handled in the code! */ +static const u8 abituguru_pwm_min[5] = { 0, 170, 170, 25, 25 }; +static const u8 abituguru_pwm_max[5] = { 0, 255, 255, 75, 75 }; + + +/* Insmod parameters */ +static int force; +module_param(force, bool, 0); +MODULE_PARM_DESC(force, "Set to one to force detection."); +static int fan_sensors; +module_param(fan_sensors, int, 0); +MODULE_PARM_DESC(fan_sensors, "Number of fan sensors on the uGuru " + "(0 = autodetect)"); +static int pwms; +module_param(pwms, int, 0); +MODULE_PARM_DESC(pwms, "Number of PWMs on the uGuru " + "(0 = autodetect)"); + +/* Default verbose is 2, since this driver is still in the testing phase */ +static int verbose = 2; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "How verbose should the driver be? (0-3):\n" + " 0 normal output\n" + " 1 + verbose error reporting\n" + " 2 + sensors type probing info\n" + " 3 + retryable error reporting"); + + +/* For the Abit uGuru, we need to keep some data in memory. + The structure is dynamically allocated, at the same time when a new + abituguru device is allocated. */ +struct abituguru_data { + struct class_device *class_dev; /* hwmon registered device */ + struct mutex update_lock; /* protect access to data and uGuru */ + unsigned long last_updated; /* In jiffies */ + unsigned short addr; /* uguru base address */ + char uguru_ready; /* is the uguru in ready state? */ + unsigned char update_timeouts; /* number of update timeouts since last + successful update */ + + /* The sysfs attr and their names are generated automatically, for bank1 + we cannot use a predefined array because we don't know beforehand + of a sensor is a volt or a temp sensor, for bank2 and the pwms its + easier todo things the same way. For in sensors we have 9 (temp 7) + sysfs entries per sensor, for bank2 and pwms 6. */ + struct sensor_device_attribute_2 sysfs_attr[ + ABIT_UGURU_MAX_BANK1_SENSORS * 9 + + ABIT_UGURU_MAX_BANK2_SENSORS * 6 + ABIT_UGURU_MAX_PWMS * 6]; + /* Buffer to store the dynamically generated sysfs names */ + char sysfs_names[ABITUGURU_SYSFS_NAMES_LENGTH]; + + /* Bank 1 data */ + /* number of and addresses of [0] in, [1] temp sensors */ + u8 bank1_sensors[2]; + u8 bank1_address[2][ABIT_UGURU_MAX_BANK1_SENSORS]; + u8 bank1_value[ABIT_UGURU_MAX_BANK1_SENSORS]; + /* This array holds 3 entries per sensor for the bank 1 sensor settings + (flags, min, max for voltage / flags, warn, shutdown for temp). */ + u8 bank1_settings[ABIT_UGURU_MAX_BANK1_SENSORS][3]; + /* Maximum value for each sensor used for scaling in mV/millidegrees + Celsius. */ + int bank1_max_value[ABIT_UGURU_MAX_BANK1_SENSORS]; + + /* Bank 2 data, ABIT_UGURU_MAX_BANK2_SENSORS entries for bank2 */ + u8 bank2_sensors; /* actual number of bank2 sensors found */ + u8 bank2_value[ABIT_UGURU_MAX_BANK2_SENSORS]; + u8 bank2_settings[ABIT_UGURU_MAX_BANK2_SENSORS][2]; /* flags, min */ + + /* Alarms 2 bytes for bank1, 1 byte for bank2 */ + u8 alarms[3]; + + /* Fan PWM (speed control) 5 bytes per PWM */ + u8 pwms; /* actual number of pwms found */ + u8 pwm_settings[ABIT_UGURU_MAX_PWMS][5]; +}; + +/* wait till the uguru is in the specified state */ +static int abituguru_wait(struct abituguru_data *data, u8 state) +{ + int timeout = ABIT_UGURU_WAIT_TIMEOUT; + + while (inb_p(data->addr + ABIT_UGURU_DATA) != state) { + timeout--; + if (timeout == 0) + return -EBUSY; + } + return 0; +} + +/* Put the uguru in ready for input state */ +static int abituguru_ready(struct abituguru_data *data) +{ + int timeout = ABIT_UGURU_READY_TIMEOUT; + + if (data->uguru_ready) + return 0; + + /* Reset? / Prepare for next read/write cycle */ + outb(0x00, data->addr + ABIT_UGURU_DATA); + + /* Wait till the uguru is ready */ + if (abituguru_wait(data, ABIT_UGURU_STATUS_READY)) { + ABIT_UGURU_DEBUG(1, + "timeout exceeded waiting for ready state\n"); + return -EIO; + } + + /* Cmd port MUST be read now and should contain 0xAC */ + while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { + timeout--; + if (timeout == 0) { + ABIT_UGURU_DEBUG(1, + "CMD reg does not hold 0xAC after ready command\n"); + return -EIO; + } + } + + /* After this the ABIT_UGURU_DATA port should contain + ABIT_UGURU_STATUS_INPUT */ + timeout = ABIT_UGURU_READY_TIMEOUT; + while (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT) { + timeout--; + if (timeout == 0) { + ABIT_UGURU_DEBUG(1, + "state != more input after ready command\n"); + return -EIO; + } + } + + data->uguru_ready = 1; + return 0; +} + +/* Send the bank and then sensor address to the uGuru for the next read/write + cycle. This function gets called as the first part of a read/write by + abituguru_read and abituguru_write. This function should never be + called by any other function. */ +static int abituguru_send_address(struct abituguru_data *data, + u8 bank_addr, u8 sensor_addr, int retries) +{ + /* assume the caller does error handling itself if it has not requested + any retries, and thus be quiet. */ + int report_errors = retries; + + for (;;) { + /* Make sure the uguru is ready and then send the bank address, + after this the uguru is no longer "ready". */ + if (abituguru_ready(data) != 0) + return -EIO; + outb(bank_addr, data->addr + ABIT_UGURU_DATA); + data->uguru_ready = 0; + + /* Wait till the uguru is ABIT_UGURU_STATUS_INPUT state again + and send the sensor addr */ + if (abituguru_wait(data, ABIT_UGURU_STATUS_INPUT)) { + if (retries) { + ABIT_UGURU_DEBUG(3, "timeout exceeded " + "waiting for more input state, %d " + "tries remaining\n", retries); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(ABIT_UGURU_RETRY_DELAY); + retries--; + continue; + } + if (report_errors) + ABIT_UGURU_DEBUG(1, "timeout exceeded " + "waiting for more input state " + "(bank: %d)\n", (int)bank_addr); + return -EBUSY; + } + outb(sensor_addr, data->addr + ABIT_UGURU_CMD); + return 0; + } +} + +/* Read count bytes from sensor sensor_addr in bank bank_addr and store the + result in buf, retry the send address part of the read retries times. */ +static int abituguru_read(struct abituguru_data *data, + u8 bank_addr, u8 sensor_addr, u8 *buf, int count, int retries) +{ + int i; + + /* Send the address */ + i = abituguru_send_address(data, bank_addr, sensor_addr, retries); + if (i) + return i; + + /* And read the data */ + for (i = 0; i < count; i++) { + if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { + ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for " + "read state (bank: %d, sensor: %d)\n", + (int)bank_addr, (int)sensor_addr); + break; + } + buf[i] = inb(data->addr + ABIT_UGURU_CMD); + } + + /* Last put the chip back in ready state */ + abituguru_ready(data); + + return i; +} + +/* Write count bytes from buf to sensor sensor_addr in bank bank_addr, the send + address part of the write is always retried ABIT_UGURU_MAX_RETRIES times. */ +static int abituguru_write(struct abituguru_data *data, + u8 bank_addr, u8 sensor_addr, u8 *buf, int count) +{ + int i; + + /* Send the address */ + i = abituguru_send_address(data, bank_addr, sensor_addr, + ABIT_UGURU_MAX_RETRIES); + if (i) + return i; + + /* And write the data */ + for (i = 0; i < count; i++) { + if (abituguru_wait(data, ABIT_UGURU_STATUS_WRITE)) { + ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for " + "write state (bank: %d, sensor: %d)\n", + (int)bank_addr, (int)sensor_addr); + break; + } + outb(buf[i], data->addr + ABIT_UGURU_CMD); + } + + /* Now we need to wait till the chip is ready to be read again, + don't ask why */ + if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { + ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for read state " + "after write (bank: %d, sensor: %d)\n", (int)bank_addr, + (int)sensor_addr); + return -EIO; + } + + /* Cmd port MUST be read now and should contain 0xAC */ + if (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { + ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after write " + "(bank: %d, sensor: %d)\n", (int)bank_addr, + (int)sensor_addr); + return -EIO; + } + + /* Last put the chip back in ready state */ + abituguru_ready(data); + + return i; +} + +/* Detect sensor type. Temp and Volt sensors are enabled with + different masks and will ignore enable masks not meant for them. + This enables us to test what kind of sensor we're dealing with. + By setting the alarm thresholds so that we will always get an + alarm for sensor type X and then enabling the sensor as sensor type + X, if we then get an alarm it is a sensor of type X. */ +static int __devinit +abituguru_detect_bank1_sensor_type(struct abituguru_data *data, + u8 sensor_addr) +{ + u8 val, buf[3]; + int ret = ABIT_UGURU_NC; + + /* First read the sensor and the current settings */ + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, sensor_addr, &val, + 1, ABIT_UGURU_MAX_RETRIES) != 1) + return -ENODEV; + + /* Test val is sane / usable for sensor type detection. */ + if ((val < 10u) || (val > 240u)) { + printk(KERN_WARNING ABIT_UGURU_NAME + ": bank1-sensor: %d reading (%d) too close to limits, " + "unable to determine sensor type, skipping sensor\n", + (int)sensor_addr, (int)val); + /* assume no sensor is there for sensors for which we can't + determine the sensor type because their reading is too close + to their limits, this usually means no sensor is there. */ + return ABIT_UGURU_NC; + } + + ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr); + /* Volt sensor test, enable volt low alarm, set min value ridicously + high. If its a volt sensor this should always give us an alarm. */ + buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE; + buf[1] = 245; + buf[2] = 250; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, + buf, 3) != 3) + return -ENODEV; + /* Now we need 20 ms to give the uguru time to read the sensors + and raise a voltage alarm */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/50); + /* Check for alarm and check the alarm is a volt low alarm. */ + if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + return -ENODEV; + if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, + sensor_addr, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + return -ENODEV; + if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) { + /* Restore original settings */ + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, + sensor_addr, + data->bank1_settings[sensor_addr], + 3) != 3) + return -ENODEV; + ABIT_UGURU_DEBUG(2, " found volt sensor\n"); + return ABIT_UGURU_IN_SENSOR; + } else + ABIT_UGURU_DEBUG(2, " alarm raised during volt " + "sensor test, but volt low flag not set\n"); + } else + ABIT_UGURU_DEBUG(2, " alarm not raised during volt sensor " + "test\n"); + + /* Temp sensor test, enable sensor as a temp sensor, set beep value + ridicously low (but not too low, otherwise uguru ignores it). + If its a temp sensor this should always give us an alarm. */ + buf[0] = ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE; + buf[1] = 5; + buf[2] = 10; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, + buf, 3) != 3) + return -ENODEV; + /* Now we need 50 ms to give the uguru time to read the sensors + and raise a temp alarm */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/20); + /* Check for alarm and check the alarm is a temp high alarm. */ + if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + return -ENODEV; + if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, + sensor_addr, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + return -ENODEV; + if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) { + ret = ABIT_UGURU_TEMP_SENSOR; + ABIT_UGURU_DEBUG(2, " found temp sensor\n"); + } else + ABIT_UGURU_DEBUG(2, " alarm raised during temp " + "sensor test, but temp high flag not set\n"); + } else + ABIT_UGURU_DEBUG(2, " alarm not raised during temp sensor " + "test\n"); + + /* Restore original settings */ + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, + data->bank1_settings[sensor_addr], 3) != 3) + return -ENODEV; + + return ret; +} + +/* These functions try to find out how many sensors there are in bank2 and how + many pwms there are. The purpose of this is to make sure that we don't give + the user the possibility to change settings for non-existent sensors / pwm. + The uGuru will happily read / write whatever memory happens to be after the + memory storing the PWM settings when reading/writing to a PWM which is not + there. Notice even if we detect a PWM which doesn't exist we normally won't + write to it, unless the user tries to change the settings. + + Although the uGuru allows reading (settings) from non existing bank2 + sensors, my version of the uGuru does seem to stop writing to them, the + write function above aborts in this case with: + "CMD reg does not hold 0xAC after write" + + Notice these 2 tests are non destructive iow read-only tests, otherwise + they would defeat their purpose. Although for the bank2_sensors detection a + read/write test would be feasible because of the reaction above, I've + however opted to stay on the safe side. */ +static void __devinit +abituguru_detect_no_bank2_sensors(struct abituguru_data *data) +{ + int i; + + if (fan_sensors) { + data->bank2_sensors = fan_sensors; + ABIT_UGURU_DEBUG(2, "assuming %d fan sensors because of " + "\"fan_sensors\" module param\n", + (int)data->bank2_sensors); + return; + } + + ABIT_UGURU_DEBUG(2, "detecting number of fan sensors\n"); + for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) { + /* 0x89 are the known used bits: + -0x80 enable shutdown + -0x08 enable beep + -0x01 enable alarm + All other bits should be 0, but on some motherboards + 0x40 (bit 6) is also high for some of the fans?? */ + if (data->bank2_settings[i][0] & ~0xC9) { + ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " + "to be a fan sensor: settings[0] = %02X\n", + i, (unsigned int)data->bank2_settings[i][0]); + break; + } + + /* check if the threshold is within the allowed range */ + if (data->bank2_settings[i][1] < + abituguru_bank2_min_threshold) { + ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " + "to be a fan sensor: the threshold (%d) is " + "below the minimum (%d)\n", i, + (int)data->bank2_settings[i][1], + (int)abituguru_bank2_min_threshold); + break; + } + if (data->bank2_settings[i][1] > + abituguru_bank2_max_threshold) { + ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " + "to be a fan sensor: the threshold (%d) is " + "above the maximum (%d)\n", i, + (int)data->bank2_settings[i][1], + (int)abituguru_bank2_max_threshold); + break; + } + } + + data->bank2_sensors = i; + ABIT_UGURU_DEBUG(2, " found: %d fan sensors\n", + (int)data->bank2_sensors); +} + +static void __devinit +abituguru_detect_no_pwms(struct abituguru_data *data) +{ + int i, j; + + if (pwms) { + data->pwms = pwms; + ABIT_UGURU_DEBUG(2, "assuming %d PWM outputs because of " + "\"pwms\" module param\n", (int)data->pwms); + return; + } + + ABIT_UGURU_DEBUG(2, "detecting number of PWM outputs\n"); + for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) { + /* 0x80 is the enable bit and the low + nibble is which temp sensor to use, + the other bits should be 0 */ + if (data->pwm_settings[i][0] & ~0x8F) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: settings[0] = %02X\n", + i, (unsigned int)data->pwm_settings[i][0]); + break; + } + + /* the low nibble must correspond to one of the temp sensors + we've found */ + for (j = 0; j < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]; + j++) { + if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][j] == + (data->pwm_settings[i][0] & 0x0F)) + break; + } + if (j == data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: %d is not a valid temp " + "sensor address\n", i, + data->pwm_settings[i][0] & 0x0F); + break; + } + + /* check if all other settings are within the allowed range */ + for (j = 1; j < 5; j++) { + u8 min; + /* special case pwm1 min pwm% */ + if ((i == 0) && ((j == 1) || (j == 2))) + min = 77; + else + min = abituguru_pwm_min[j]; + if (data->pwm_settings[i][j] < min) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does " + "not seem to be a pwm channel: " + "setting %d (%d) is below the minimum " + "value (%d)\n", i, j, + (int)data->pwm_settings[i][j], + (int)min); + goto abituguru_detect_no_pwms_exit; + } + if (data->pwm_settings[i][j] > abituguru_pwm_max[j]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does " + "not seem to be a pwm channel: " + "setting %d (%d) is above the maximum " + "value (%d)\n", i, j, + (int)data->pwm_settings[i][j], + (int)abituguru_pwm_max[j]); + goto abituguru_detect_no_pwms_exit; + } + } + + /* check that min temp < max temp and min pwm < max pwm */ + if (data->pwm_settings[i][1] >= data->pwm_settings[i][2]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: min pwm (%d) >= " + "max pwm (%d)\n", i, + (int)data->pwm_settings[i][1], + (int)data->pwm_settings[i][2]); + break; + } + if (data->pwm_settings[i][3] >= data->pwm_settings[i][4]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: min temp (%d) >= " + "max temp (%d)\n", i, + (int)data->pwm_settings[i][3], + (int)data->pwm_settings[i][4]); + break; + } + } + +abituguru_detect_no_pwms_exit: + data->pwms = i; + ABIT_UGURU_DEBUG(2, " found: %d PWM outputs\n", (int)data->pwms); +} + +/* Following are the sysfs callback functions. These functions expect: + sensor_device_attribute_2->index: sensor address/offset in the bank + sensor_device_attribute_2->nr: register offset, bitmask or NA. */ +static struct abituguru_data *abituguru_update_device(struct device *dev); + +static ssize_t show_bank1_value(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + return sprintf(buf, "%d\n", (data->bank1_value[attr->index] * + data->bank1_max_value[attr->index] + 128) / 255); +} + +static ssize_t show_bank1_setting(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + (data->bank1_settings[attr->index][attr->nr] * + data->bank1_max_value[attr->index] + 128) / 255); +} + +static ssize_t show_bank2_value(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + return sprintf(buf, "%d\n", (data->bank2_value[attr->index] * + ABIT_UGURU_FAN_MAX + 128) / 255); +} + +static ssize_t show_bank2_setting(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + (data->bank2_settings[attr->index][attr->nr] * + ABIT_UGURU_FAN_MAX + 128) / 255); +} + +static ssize_t store_bank1_setting(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 val = (simple_strtoul(buf, NULL, 10) * 255 + + data->bank1_max_value[attr->index]/2) / + data->bank1_max_value[attr->index]; + ssize_t ret = count; + + mutex_lock(&data->update_lock); + if (data->bank1_settings[attr->index][attr->nr] != val) { + u8 orig_val = data->bank1_settings[attr->index][attr->nr]; + data->bank1_settings[attr->index][attr->nr] = val; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, + attr->index, data->bank1_settings[attr->index], + 3) <= attr->nr) { + data->bank1_settings[attr->index][attr->nr] = orig_val; + ret = -EIO; + } + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t store_bank2_setting(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 val = (simple_strtoul(buf, NULL, 10)*255 + ABIT_UGURU_FAN_MAX/2) / + ABIT_UGURU_FAN_MAX; + ssize_t ret = count; + + /* this check can be done before taking the lock */ + if ((val < abituguru_bank2_min_threshold) || + (val > abituguru_bank2_max_threshold)) + return -EINVAL; + + mutex_lock(&data->update_lock); + if (data->bank2_settings[attr->index][attr->nr] != val) { + u8 orig_val = data->bank2_settings[attr->index][attr->nr]; + data->bank2_settings[attr->index][attr->nr] = val; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK2 + 2, + attr->index, data->bank2_settings[attr->index], + 2) <= attr->nr) { + data->bank2_settings[attr->index][attr->nr] = orig_val; + ret = -EIO; + } + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_bank1_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + /* See if the alarm bit for this sensor is set, and if the + alarm matches the type of alarm we're looking for (for volt + it can be either low or high). The type is stored in a few + readonly bits in the settings part of the relevant sensor. + The bitmask of the type is passed to us in attr->nr. */ + if ((data->alarms[attr->index / 8] & (0x01 << (attr->index % 8))) && + (data->bank1_settings[attr->index][0] & attr->nr)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_bank2_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + if (data->alarms[2] & (0x01 << attr->index)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_bank1_mask(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + if (data->bank1_settings[attr->index][0] & attr->nr) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_bank2_mask(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + if (data->bank2_settings[attr->index][0] & attr->nr) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t store_bank1_mask(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int mask = simple_strtoul(buf, NULL, 10); + ssize_t ret = count; + u8 orig_val; + + mutex_lock(&data->update_lock); + orig_val = data->bank1_settings[attr->index][0]; + + if (mask) + data->bank1_settings[attr->index][0] |= attr->nr; + else + data->bank1_settings[attr->index][0] &= ~attr->nr; + + if ((data->bank1_settings[attr->index][0] != orig_val) && + (abituguru_write(data, + ABIT_UGURU_SENSOR_BANK1 + 2, attr->index, + data->bank1_settings[attr->index], 3) < 1)) { + data->bank1_settings[attr->index][0] = orig_val; + ret = -EIO; + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t store_bank2_mask(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int mask = simple_strtoul(buf, NULL, 10); + ssize_t ret = count; + u8 orig_val; + + mutex_lock(&data->update_lock); + orig_val = data->bank2_settings[attr->index][0]; + + if (mask) + data->bank2_settings[attr->index][0] |= attr->nr; + else + data->bank2_settings[attr->index][0] &= ~attr->nr; + + if ((data->bank2_settings[attr->index][0] != orig_val) && + (abituguru_write(data, + ABIT_UGURU_SENSOR_BANK2 + 2, attr->index, + data->bank2_settings[attr->index], 2) < 1)) { + data->bank2_settings[attr->index][0] = orig_val; + ret = -EIO; + } + mutex_unlock(&data->update_lock); + return ret; +} + +/* Fan PWM (speed control) */ +static ssize_t show_pwm_setting(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", data->pwm_settings[attr->index][attr->nr] * + abituguru_pwm_settings_multiplier[attr->nr]); +} + +static ssize_t store_pwm_setting(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 min, val = (simple_strtoul(buf, NULL, 10) + + abituguru_pwm_settings_multiplier[attr->nr]/2) / + abituguru_pwm_settings_multiplier[attr->nr]; + ssize_t ret = count; + + /* special case pwm1 min pwm% */ + if ((attr->index == 0) && ((attr->nr == 1) || (attr->nr == 2))) + min = 77; + else + min = abituguru_pwm_min[attr->nr]; + + /* this check can be done before taking the lock */ + if ((val < min) || (val > abituguru_pwm_max[attr->nr])) + return -EINVAL; + + mutex_lock(&data->update_lock); + /* this check needs to be done after taking the lock */ + if ((attr->nr & 1) && + (val >= data->pwm_settings[attr->index][attr->nr + 1])) + ret = -EINVAL; + else if (!(attr->nr & 1) && + (val <= data->pwm_settings[attr->index][attr->nr - 1])) + ret = -EINVAL; + else if (data->pwm_settings[attr->index][attr->nr] != val) { + u8 orig_val = data->pwm_settings[attr->index][attr->nr]; + data->pwm_settings[attr->index][attr->nr] = val; + if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, + attr->index, data->pwm_settings[attr->index], + 5) <= attr->nr) { + data->pwm_settings[attr->index][attr->nr] = + orig_val; + ret = -EIO; + } + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_pwm_sensor(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int i; + /* We need to walk to the temp sensor addresses to find what + the userspace id of the configured temp sensor is. */ + for (i = 0; i < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]; i++) + if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][i] == + (data->pwm_settings[attr->index][0] & 0x0F)) + return sprintf(buf, "%d\n", i+1); + + return -ENXIO; +} + +static ssize_t store_pwm_sensor(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + unsigned long val = simple_strtoul(buf, NULL, 10) - 1; + ssize_t ret = count; + + mutex_lock(&data->update_lock); + if (val < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) { + u8 orig_val = data->pwm_settings[attr->index][0]; + u8 address = data->bank1_address[ABIT_UGURU_TEMP_SENSOR][val]; + data->pwm_settings[attr->index][0] &= 0xF0; + data->pwm_settings[attr->index][0] |= address; + if (data->pwm_settings[attr->index][0] != orig_val) { + if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, + attr->index, + data->pwm_settings[attr->index], + 5) < 1) { + data->pwm_settings[attr->index][0] = orig_val; + ret = -EIO; + } + } + } + else + ret = -EINVAL; + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_pwm_enable(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int res = 0; + if (data->pwm_settings[attr->index][0] & ABIT_UGURU_FAN_PWM_ENABLE) + res = 2; + return sprintf(buf, "%d\n", res); +} + +static ssize_t store_pwm_enable(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 orig_val, user_val = simple_strtoul(buf, NULL, 10); + ssize_t ret = count; + + mutex_lock(&data->update_lock); + orig_val = data->pwm_settings[attr->index][0]; + switch (user_val) { + case 0: + data->pwm_settings[attr->index][0] &= + ~ABIT_UGURU_FAN_PWM_ENABLE; + break; + case 2: + data->pwm_settings[attr->index][0] |= + ABIT_UGURU_FAN_PWM_ENABLE; + break; + default: + ret = -EINVAL; + } + if ((data->pwm_settings[attr->index][0] != orig_val) && + (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, + attr->index, data->pwm_settings[attr->index], + 5) < 1)) { + data->pwm_settings[attr->index][0] = orig_val; + ret = -EIO; + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_name(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "%s\n", ABIT_UGURU_NAME); +} + +/* Sysfs attr templates, the real entries are generated automatically. */ +static const +struct sensor_device_attribute_2 abituguru_sysfs_bank1_templ[2][9] = { + { + SENSOR_ATTR_2(in%d_input, 0444, show_bank1_value, NULL, 0, 0), + SENSOR_ATTR_2(in%d_min, 0644, show_bank1_setting, + store_bank1_setting, 1, 0), + SENSOR_ATTR_2(in%d_min_alarm, 0444, show_bank1_alarm, NULL, + ABIT_UGURU_VOLT_LOW_ALARM_FLAG, 0), + SENSOR_ATTR_2(in%d_max, 0644, show_bank1_setting, + store_bank1_setting, 2, 0), + SENSOR_ATTR_2(in%d_max_alarm, 0444, show_bank1_alarm, NULL, + ABIT_UGURU_VOLT_HIGH_ALARM_FLAG, 0), + SENSOR_ATTR_2(in%d_beep, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0), + SENSOR_ATTR_2(in%d_shutdown, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), + SENSOR_ATTR_2(in%d_min_alarm_enable, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_VOLT_LOW_ALARM_ENABLE, 0), + SENSOR_ATTR_2(in%d_max_alarm_enable, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE, 0), + }, { + SENSOR_ATTR_2(temp%d_input, 0444, show_bank1_value, NULL, 0, 0), + SENSOR_ATTR_2(temp%d_alarm, 0444, show_bank1_alarm, NULL, + ABIT_UGURU_TEMP_HIGH_ALARM_FLAG, 0), + SENSOR_ATTR_2(temp%d_max, 0644, show_bank1_setting, + store_bank1_setting, 1, 0), + SENSOR_ATTR_2(temp%d_crit, 0644, show_bank1_setting, + store_bank1_setting, 2, 0), + SENSOR_ATTR_2(temp%d_beep, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0), + SENSOR_ATTR_2(temp%d_shutdown, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), + SENSOR_ATTR_2(temp%d_alarm_enable, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE, 0), + } +}; + +static const struct sensor_device_attribute_2 abituguru_sysfs_fan_templ[6] = { + SENSOR_ATTR_2(fan%d_input, 0444, show_bank2_value, NULL, 0, 0), + SENSOR_ATTR_2(fan%d_alarm, 0444, show_bank2_alarm, NULL, 0, 0), + SENSOR_ATTR_2(fan%d_min, 0644, show_bank2_setting, + store_bank2_setting, 1, 0), + SENSOR_ATTR_2(fan%d_beep, 0644, show_bank2_mask, + store_bank2_mask, ABIT_UGURU_BEEP_ENABLE, 0), + SENSOR_ATTR_2(fan%d_shutdown, 0644, show_bank2_mask, + store_bank2_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), + SENSOR_ATTR_2(fan%d_alarm_enable, 0644, show_bank2_mask, + store_bank2_mask, ABIT_UGURU_FAN_LOW_ALARM_ENABLE, 0), +}; + +static const struct sensor_device_attribute_2 abituguru_sysfs_pwm_templ[6] = { + SENSOR_ATTR_2(pwm%d_enable, 0644, show_pwm_enable, + store_pwm_enable, 0, 0), + SENSOR_ATTR_2(pwm%d_auto_channels_temp, 0644, show_pwm_sensor, + store_pwm_sensor, 0, 0), + SENSOR_ATTR_2(pwm%d_auto_point1_pwm, 0644, show_pwm_setting, + store_pwm_setting, 1, 0), + SENSOR_ATTR_2(pwm%d_auto_point2_pwm, 0644, show_pwm_setting, + store_pwm_setting, 2, 0), + SENSOR_ATTR_2(pwm%d_auto_point1_temp, 0644, show_pwm_setting, + store_pwm_setting, 3, 0), + SENSOR_ATTR_2(pwm%d_auto_point2_temp, 0644, show_pwm_setting, + store_pwm_setting, 4, 0), +}; + +static struct sensor_device_attribute_2 abituguru_sysfs_attr[] = { + SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0), +}; + +static int __devinit abituguru_probe(struct platform_device *pdev) +{ + struct abituguru_data *data; + int i, j, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV; + char *sysfs_filename; + + /* El weirdo probe order, to keep the sysfs order identical to the + BIOS and window-appliction listing order. */ + const u8 probe_order[ABIT_UGURU_MAX_BANK1_SENSORS] = { + 0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, 0x02, + 0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C }; + + if (!(data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL))) + return -ENOMEM; + + data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; + mutex_init(&data->update_lock); + platform_set_drvdata(pdev, data); + + /* See if the uGuru is ready */ + if (inb_p(data->addr + ABIT_UGURU_DATA) == ABIT_UGURU_STATUS_INPUT) + data->uguru_ready = 1; + + /* Completely read the uGuru this has 2 purposes: + - testread / see if one really is there. + - make an in memory copy of all the uguru settings for future use. */ + if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, + data->alarms, 3, ABIT_UGURU_MAX_RETRIES) != 3) + goto abituguru_probe_error; + + for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, i, + &data->bank1_value[i], 1, + ABIT_UGURU_MAX_RETRIES) != 1) + goto abituguru_probe_error; + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1+1, i, + data->bank1_settings[i], 3, + ABIT_UGURU_MAX_RETRIES) != 3) + goto abituguru_probe_error; + } + /* Note: We don't know how many bank2 sensors / pwms there really are, + but in order to "detect" this we need to read the maximum amount + anyways. If we read sensors/pwms not there we'll just read crap + this can't hurt. We need the detection because we don't want + unwanted writes, which will hurt! */ + for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2, i, + &data->bank2_value[i], 1, + ABIT_UGURU_MAX_RETRIES) != 1) + goto abituguru_probe_error; + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2+1, i, + data->bank2_settings[i], 2, + ABIT_UGURU_MAX_RETRIES) != 2) + goto abituguru_probe_error; + } + for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) { + if (abituguru_read(data, ABIT_UGURU_FAN_PWM, i, + data->pwm_settings[i], 5, + ABIT_UGURU_MAX_RETRIES) != 5) + goto abituguru_probe_error; + } + data->last_updated = jiffies; + + /* Detect sensor types and fill the sysfs attr for bank1 */ + sysfs_attr_i = 0; + sysfs_filename = data->sysfs_names; + sysfs_names_free = ABITUGURU_SYSFS_NAMES_LENGTH; + for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { + res = abituguru_detect_bank1_sensor_type(data, probe_order[i]); + if (res < 0) + goto abituguru_probe_error; + if (res == ABIT_UGURU_NC) + continue; + + /* res 1 (temp) sensors have 7 sysfs entries, 0 (in) 9 */ + for (j = 0; j < (res ? 7 : 9); j++) { + used = snprintf(sysfs_filename, sysfs_names_free, + abituguru_sysfs_bank1_templ[res][j].dev_attr. + attr.name, data->bank1_sensors[res] + res) + + 1; + data->sysfs_attr[sysfs_attr_i] = + abituguru_sysfs_bank1_templ[res][j]; + data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = + sysfs_filename; + data->sysfs_attr[sysfs_attr_i].index = probe_order[i]; + sysfs_filename += used; + sysfs_names_free -= used; + sysfs_attr_i++; + } + data->bank1_max_value[probe_order[i]] = + abituguru_bank1_max_value[res]; + data->bank1_address[res][data->bank1_sensors[res]] = + probe_order[i]; + data->bank1_sensors[res]++; + } + /* Detect number of sensors and fill the sysfs attr for bank2 (fans) */ + abituguru_detect_no_bank2_sensors(data); + for (i = 0; i < data->bank2_sensors; i++) { + for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_fan_templ); j++) { + used = snprintf(sysfs_filename, sysfs_names_free, + abituguru_sysfs_fan_templ[j].dev_attr.attr.name, + i + 1) + 1; + data->sysfs_attr[sysfs_attr_i] = + abituguru_sysfs_fan_templ[j]; + data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = + sysfs_filename; + data->sysfs_attr[sysfs_attr_i].index = i; + sysfs_filename += used; + sysfs_names_free -= used; + sysfs_attr_i++; + } + } + /* Detect number of sensors and fill the sysfs attr for pwms */ + abituguru_detect_no_pwms(data); + for (i = 0; i < data->pwms; i++) { + for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_pwm_templ); j++) { + used = snprintf(sysfs_filename, sysfs_names_free, + abituguru_sysfs_pwm_templ[j].dev_attr.attr.name, + i + 1) + 1; + data->sysfs_attr[sysfs_attr_i] = + abituguru_sysfs_pwm_templ[j]; + data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = + sysfs_filename; + data->sysfs_attr[sysfs_attr_i].index = i; + sysfs_filename += used; + sysfs_names_free -= used; + sysfs_attr_i++; + } + } + /* Fail safe check, this should never happen! */ + if (sysfs_names_free < 0) { + printk(KERN_ERR ABIT_UGURU_NAME ": Fatal error ran out of " + "space for sysfs attr names. This should never " + "happen please report to the abituguru maintainer " + "(see MAINTAINERS)\n"); + res = -ENAMETOOLONG; + goto abituguru_probe_error; + } + printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n"); + + /* Register sysfs hooks */ + data->class_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->class_dev)) { + res = PTR_ERR(data->class_dev); + goto abituguru_probe_error; + } + for (i = 0; i < sysfs_attr_i; i++) + device_create_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) + device_create_file(&pdev->dev, + &abituguru_sysfs_attr[i].dev_attr); + + return 0; + +abituguru_probe_error: + kfree(data); + return res; +} + +static int __devexit abituguru_remove(struct platform_device *pdev) +{ + struct abituguru_data *data = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + hwmon_device_unregister(data->class_dev); + kfree(data); + + return 0; +} + +static struct abituguru_data *abituguru_update_device(struct device *dev) +{ + int i, err; + struct abituguru_data *data = dev_get_drvdata(dev); + /* fake a complete successful read if no update necessary. */ + char success = 1; + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + HZ)) { + success = 0; + if ((err = abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, + data->alarms, 3, 0)) != 3) + goto LEAVE_UPDATE; + for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { + if ((err = abituguru_read(data, + ABIT_UGURU_SENSOR_BANK1, i, + &data->bank1_value[i], 1, 0)) != 1) + goto LEAVE_UPDATE; + if ((err = abituguru_read(data, + ABIT_UGURU_SENSOR_BANK1 + 1, i, + data->bank1_settings[i], 3, 0)) != 3) + goto LEAVE_UPDATE; + } + for (i = 0; i < data->bank2_sensors; i++) + if ((err = abituguru_read(data, + ABIT_UGURU_SENSOR_BANK2, i, + &data->bank2_value[i], 1, 0)) != 1) + goto LEAVE_UPDATE; + /* success! */ + success = 1; + data->update_timeouts = 0; +LEAVE_UPDATE: + /* handle timeout condition */ + if (err == -EBUSY) { + /* No overflow please */ + if (data->update_timeouts < 255u) + data->update_timeouts++; + if (data->update_timeouts <= ABIT_UGURU_MAX_TIMEOUTS) { + ABIT_UGURU_DEBUG(3, "timeout exceeded, will " + "try again next update\n"); + /* Just a timeout, fake a successful read */ + success = 1; + } else + ABIT_UGURU_DEBUG(1, "timeout exceeded %d " + "times waiting for more input state\n", + (int)data->update_timeouts); + } + /* On success set last_updated */ + if (success) + data->last_updated = jiffies; + } + mutex_unlock(&data->update_lock); + + if (success) + return data; + else + return NULL; +} + +static struct platform_driver abituguru_driver = { + .driver = { + .owner = THIS_MODULE, + .name = ABIT_UGURU_NAME, + }, + .probe = abituguru_probe, + .remove = __devexit_p(abituguru_remove), +}; + +static int __init abituguru_detect(void) +{ + /* See if there is an uguru there. After a reboot uGuru will hold 0x00 + at DATA and 0xAC, when this driver has already been loaded once + DATA will hold 0x08. For most uGuru's CMD will hold 0xAC in either + scenario but some will hold 0x00. + Some uGuru's initally hold 0x09 at DATA and will only hold 0x08 + after reading CMD first, so CMD must be read first! */ + u8 cmd_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_CMD); + u8 data_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_DATA); + if (((data_val == 0x00) || (data_val == 0x08)) && + ((cmd_val == 0x00) || (cmd_val == 0xAC))) + return ABIT_UGURU_BASE; + + ABIT_UGURU_DEBUG(2, "no Abit uGuru found, data = 0x%02X, cmd = " + "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val); + + if (force) { + printk(KERN_INFO ABIT_UGURU_NAME ": Assuming Abit uGuru is " + "present because of \"force\" parameter\n"); + return ABIT_UGURU_BASE; + } + + /* No uGuru found */ + return -ENODEV; +} + +static struct platform_device *abituguru_pdev; + +static int __init abituguru_init(void) +{ + int address, err; + struct resource res = { .flags = IORESOURCE_IO }; + + address = abituguru_detect(); + if (address < 0) + return address; + + err = platform_driver_register(&abituguru_driver); + if (err) + goto exit; + + abituguru_pdev = platform_device_alloc(ABIT_UGURU_NAME, address); + if (!abituguru_pdev) { + printk(KERN_ERR ABIT_UGURU_NAME + ": Device allocation failed\n"); + err = -ENOMEM; + goto exit_driver_unregister; + } + + res.start = address; + res.end = address + ABIT_UGURU_REGION_LENGTH - 1; + res.name = ABIT_UGURU_NAME; + + err = platform_device_add_resources(abituguru_pdev, &res, 1); + if (err) { + printk(KERN_ERR ABIT_UGURU_NAME + ": Device resource addition failed (%d)\n", err); + goto exit_device_put; + } + + err = platform_device_add(abituguru_pdev); + if (err) { + printk(KERN_ERR ABIT_UGURU_NAME + ": Device addition failed (%d)\n", err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(abituguru_pdev); +exit_driver_unregister: + platform_driver_unregister(&abituguru_driver); +exit: + return err; +} + +static void __exit abituguru_exit(void) +{ + platform_device_unregister(abituguru_pdev); + platform_driver_unregister(&abituguru_driver); +} + +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("Abit uGuru Sensor device"); +MODULE_LICENSE("GPL"); + +module_init(abituguru_init); +module_exit(abituguru_exit); diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 65b2709..facc1cc 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -341,7 +341,7 @@ static ssize_t set_fan_min(struct device /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan divisor. This follows the principle of - least suprise; the user doesn't expect the fan minimum to change just + least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ static ssize_t set_fan_div(struct device *dev, const char *buf, size_t count, int nr) diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 885465d..fd72440 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -99,10 +99,6 @@ #define REGION_LENGTH 2 #define ADDR_REG_OFFSET 0 #define DATA_REG_OFFSET 1 -static struct resource f71805f_resource __initdata = { - .flags = IORESOURCE_IO, -}; - /* * Registers */ @@ -782,6 +778,11 @@ static struct platform_driver f71805f_dr static int __init f71805f_device_add(unsigned short address) { + struct resource res = { + .start = address, + .end = address + REGION_LENGTH - 1, + .flags = IORESOURCE_IO, + }; int err; pdev = platform_device_alloc(DRVNAME, address); @@ -791,10 +792,8 @@ static int __init f71805f_device_add(uns goto exit; } - f71805f_resource.start = address; - f71805f_resource.end = address + REGION_LENGTH - 1; - f71805f_resource.name = pdev->name; - err = platform_device_add_resources(pdev, &f71805f_resource, 1); + res.name = pdev->name; + err = platform_device_add_resources(pdev, &res, 1); if (err) { printk(KERN_ERR DRVNAME ": Device resource addition failed " "(%d)\n", err); diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 1659f6c..42b6328 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -41,7 +41,7 @@ #define HDAPS_NR_PORTS 0x30 /* number o #define HDAPS_PORT_STATE 0x1611 /* device state */ #define HDAPS_PORT_YPOS 0x1612 /* y-axis position */ #define HDAPS_PORT_XPOS 0x1614 /* x-axis position */ -#define HDAPS_PORT_TEMP1 0x1616 /* device temperature, in celcius */ +#define HDAPS_PORT_TEMP1 0x1616 /* device temperature, in Celsius */ #define HDAPS_PORT_YVAR 0x1617 /* y-axis variance (what is this?) */ #define HDAPS_PORT_XVAR 0x1619 /* x-axis variance (what is this?) */ #define HDAPS_PORT_TEMP2 0x161b /* device temperature (again?) */ @@ -522,13 +522,15 @@ static int __init hdaps_init(void) { int ret; - /* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */ + /* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match + "ThinkPad T42p", so the order of the entries matters */ struct dmi_system_id hdaps_whitelist[] = { HDAPS_DMI_MATCH_NORMAL("ThinkPad H"), HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"), HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"), HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"), HDAPS_DMI_MATCH_NORMAL("ThinkPad R52"), + HDAPS_DMI_MATCH_NORMAL("ThinkPad H"), /* R52 (1846AQG) */ HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"), HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"), HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"), @@ -536,9 +538,9 @@ static int __init hdaps_init(void) HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"), HDAPS_DMI_MATCH_LENOVO("ThinkPad T60p"), HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"), - HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"), HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"), HDAPS_DMI_MATCH_LENOVO("ThinkPad X60"), + HDAPS_DMI_MATCH_NORMAL("ThinkPad Z60m"), { .ident = NULL } }; diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index a74a44f..a6764ff 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c @@ -58,11 +58,20 @@ #include doesn't seem to be any named specification for these. The conversion tables are detailed directly in the various Pentium M datasheets: http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm + + The 14 specification corresponds to Intel Core series. There + doesn't seem to be any named specification for these. The conversion + tables are detailed directly in the various Pentium Core datasheets: + http://www.intel.com/design/mobile/datashts/309221.htm + + The 110 (VRM 11) specification corresponds to Intel Conroe based series. + http://www.intel.com/design/processor/applnots/313214.htm */ /* vrm is the VRM/VRD document version multiplied by 10. - val is the 4-, 5- or 6-bit VID code. - Returned value is in mV to avoid floating point in the kernel. */ + val is the 4-bit or more VID code. + Returned value is in mV to avoid floating point in the kernel. + Some VID have some bits in uV scale, this is rounded to mV */ int vid_from_reg(int val, u8 vrm) { int vid; @@ -70,26 +79,36 @@ int vid_from_reg(int val, u8 vrm) switch(vrm) { case 100: /* VRD 10.0 */ + /* compute in uV, round to mV */ + val &= 0x3f; if((val & 0x1f) == 0x1f) return 0; if((val & 0x1f) <= 0x09 || val == 0x0a) - vid = 10875 - (val & 0x1f) * 250; + vid = 1087500 - (val & 0x1f) * 25000; else - vid = 18625 - (val & 0x1f) * 250; + vid = 1862500 - (val & 0x1f) * 25000; if(val & 0x20) - vid -= 125; - vid /= 10; /* only return 3 dec. places for now */ - return vid; + vid -= 12500; + return((vid + 500) / 1000); + case 110: /* Intel Conroe */ + /* compute in uV, round to mV */ + val &= 0xff; + if(((val & 0x7e) == 0xfe) || (!(val & 0x7e))) + return 0; + return((1600000 - (val - 2) * 6250 + 500) / 1000); case 24: /* Opteron processor */ + val &= 0x1f; return(val == 0x1f ? 0 : 1550 - val * 25); case 91: /* VRM 9.1 */ case 90: /* VRM 9.0 */ + val &= 0x1f; return(val == 0x1f ? 0 : 1850 - val * 25); case 85: /* VRM 8.5 */ + val &= 0x1f; return((val & 0x10 ? 25 : 0) + ((val & 0x0f) > 0x04 ? 2050 : 1250) - ((val & 0x0f) * 50)); @@ -98,14 +117,21 @@ int vid_from_reg(int val, u8 vrm) val &= 0x0f; /* fall through */ case 82: /* VRM 8.2 */ + val &= 0x1f; return(val == 0x1f ? 0 : val & 0x10 ? 5100 - (val) * 100 : 2050 - (val) * 50); case 17: /* Intel IMVP-II */ + val &= 0x1f; return(val & 0x10 ? 975 - (val & 0xF) * 25 : 1750 - val * 50); case 13: - return(1708 - (val & 0x3f) * 16); + val &= 0x3f; + return(1708 - val * 16); + case 14: /* Intel Core */ + /* compute in uV, round to mV */ + val &= 0x7f; + return(val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000); default: /* report 0 for unknown */ printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n"); return 0; @@ -138,6 +164,8 @@ static struct vrm_model vrm_models[] = { {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13}, /* Pentium M (130 nm) */ {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */ {X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */ + {X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14}, /* Intel Core (65 nm) */ + {X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110}, /* Intel Conroe */ {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */ {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */ {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */ diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c new file mode 100644 index 0000000..6ba8473 --- /dev/null +++ b/drivers/hwmon/lm70.c @@ -0,0 +1,165 @@ +/* + * lm70.c + * + * The LM70 is a temperature sensor chip from National Semiconductor (NS). + * Copyright (C) 2006 Kaiwan N Billimoria + * + * The LM70 communicates with a host processor via an SPI/Microwire Bus + * interface. The complete datasheet is available at National's website + * here: + * http://www.national.com/pf/LM/LM70.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "lm70" + +struct lm70 { + struct class_device *cdev; + struct semaphore sem; +}; + +/* sysfs hook function */ +static ssize_t lm70_sense_temp(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_device *spi = to_spi_device(dev); + int status, val; + u8 rxbuf[2]; + s16 raw=0; + struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); + + if (down_interruptible(&p_lm70->sem)) + return -ERESTARTSYS; + + /* + * spi_read() requires a DMA-safe buffer; so we use + * spi_write_then_read(), transmitting 0 bytes. + */ + status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2); + if (status < 0) { + printk(KERN_WARNING + "spi_write_then_read failed with status %d\n", status); + goto out; + } + dev_dbg(dev, "rxbuf[1] : 0x%x rxbuf[0] : 0x%x\n", rxbuf[1], rxbuf[0]); + + raw = (rxbuf[1] << 8) + rxbuf[0]; + dev_dbg(dev, "raw=0x%x\n", raw); + + /* + * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's + * complement value. Only the MSB 11 bits (1 sign + 10 temperature + * bits) are meaningful; the LSB 5 bits are to be discarded. + * See the datasheet. + * + * Further, each bit represents 0.25 degrees Celsius; so, multiply + * by 0.25. Also multiply by 1000 to represent in millidegrees + * Celsius. + * So it's equivalent to multiplying by 0.25 * 1000 = 250. + */ + val = ((int)raw/32) * 250; + status = sprintf(buf, "%+d\n", val); /* millidegrees Celsius */ +out: + up(&p_lm70->sem); + return status; +} + +static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL); + +/*----------------------------------------------------------------------*/ + +static int __devinit lm70_probe(struct spi_device *spi) +{ + struct lm70 *p_lm70; + int status; + + p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL); + if (!p_lm70) + return -ENOMEM; + + init_MUTEX(&p_lm70->sem); + + /* sysfs hook */ + p_lm70->cdev = hwmon_device_register(&spi->dev); + if (IS_ERR(p_lm70->cdev)) { + dev_dbg(&spi->dev, "hwmon_device_register failed.\n"); + status = PTR_ERR(p_lm70->cdev); + goto out_dev_reg_failed; + } + dev_set_drvdata(&spi->dev, p_lm70); + + if ((status = device_create_file(&spi->dev, &dev_attr_temp1_input))) { + dev_dbg(&spi->dev, "device_create_file failure.\n"); + goto out_dev_create_file_failed; + } + + return 0; + +out_dev_create_file_failed: + hwmon_device_unregister(p_lm70->cdev); +out_dev_reg_failed: + dev_set_drvdata(&spi->dev, NULL); + kfree(p_lm70); + return status; +} + +static int __exit lm70_remove(struct spi_device *spi) +{ + struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); + + device_remove_file(&spi->dev, &dev_attr_temp1_input); + hwmon_device_unregister(p_lm70->cdev); + dev_set_drvdata(&spi->dev, NULL); + kfree(p_lm70); + + return 0; +} + +static struct spi_driver lm70_driver = { + .driver = { + .name = "lm70", + .owner = THIS_MODULE, + }, + .probe = lm70_probe, + .remove = __devexit_p(lm70_remove), +}; + +static int __init init_lm70(void) +{ + return spi_register_driver(&lm70_driver); +} + +static void __exit cleanup_lm70(void) +{ + spi_unregister_driver(&lm70_driver); +} + +module_init(init_lm70); +module_exit(cleanup_lm70); + +MODULE_AUTHOR("Kaiwan N Billimoria"); +MODULE_DESCRIPTION("National Semiconductor LM70 Linux driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 94be3d7..a6ce7ab 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -358,7 +358,7 @@ static ssize_t show_fan_div(struct devic /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan divisor. This follows the principle of - least suprise; the user doesn't expect the fan minimum to change just + least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ static ssize_t set_fan_div(struct device *dev, const char *buf, size_t count, int nr) diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index f72120d..b4ccdfc 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -253,7 +253,7 @@ set_fan(min2, fan_min[1], LM80_REG_FAN_M /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan divisor. This follows the principle of - least suprise; the user doesn't expect the fan minimum to change just + least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ static ssize_t set_fan_div(struct device *dev, const char *buf, size_t count, int nr) diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index aac4ec2..2137d78 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c @@ -12,6 +12,10 @@ * Since the datasheet omits to give the chip stepping code, I give it * here: 0x03 (at register 0xff). * + * Also supports the LM82 temp sensor, which is basically a stripped down + * model of the LM83. Datasheet is here: + * http://www.national.com/pf/LM/LM82.html + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -52,7 +56,7 @@ static unsigned short normal_i2c[] = { 0 * Insmod parameters */ -I2C_CLIENT_INSMOD_1(lm83); +I2C_CLIENT_INSMOD_2(lm83, lm82); /* * The LM83 registers @@ -283,6 +287,9 @@ static int lm83_detect(struct i2c_adapte if (man_id == 0x01) { /* National Semiconductor */ if (chip_id == 0x03) { kind = lm83; + } else + if (chip_id == 0x01) { + kind = lm82; } } @@ -296,6 +303,9 @@ static int lm83_detect(struct i2c_adapte if (kind == lm83) { name = "lm83"; + } else + if (kind == lm82) { + name = "lm82"; } /* We can fill in the remaining client fields */ @@ -319,32 +329,46 @@ static int lm83_detect(struct i2c_adapte goto exit_detach; } + /* + * The LM82 can only monitor one external diode which is + * at the same register as the LM83 temp3 entry - so we + * declare 1 and 3 common, and then 2 and 4 only for the LM83. + */ + device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr); device_create_file(&new_client->dev, - &sensor_dev_attr_temp2_input.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_temp4_input.dev_attr); + device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr); device_create_file(&new_client->dev, - &sensor_dev_attr_temp2_max.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_temp4_max.dev_attr); + device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr); device_create_file(&new_client->dev, - &sensor_dev_attr_temp2_crit.dev_attr); - device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_temp4_crit.dev_attr); + device_create_file(&new_client->dev, &dev_attr_alarms); + if (kind == lm83) { + device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_input.dev_attr); + device_create_file(&new_client->dev, + &sensor_dev_attr_temp4_input.dev_attr); + + device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_max.dev_attr); + device_create_file(&new_client->dev, + &sensor_dev_attr_temp4_max.dev_attr); + + device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_crit.dev_attr); + device_create_file(&new_client->dev, + &sensor_dev_attr_temp4_crit.dev_attr); + } + return 0; exit_detach: diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index e229daf..e6c1b63 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -421,7 +421,7 @@ static void set_fan_min(struct device *d /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan clock divider. This follows the principle - of least suprise; the user doesn't expect the fan minimum to change just + of least surprise; the user doesn't expect the fan minimum to change just because the divider changed. */ static ssize_t set_fan_div(struct device *dev, const char *buf, size_t count, int nr) diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 6f3fda7..063f71c 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -380,7 +380,7 @@ static ssize_t show_fan_div(struct devic /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan divisor. This follows the principle of - least suprise; the user doesn't expect the fan minimum to change just + least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ static ssize_t set_fan_div(struct device *dev, const char *buf, size_t count, int nr) diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 7732aec..825e8f7 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -207,7 +207,7 @@ static ssize_t set_fan_min(struct device /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan clock divider. This follows the principle - of least suprise; the user doesn't expect the fan minimum to change just + of least surprise; the user doesn't expect the fan minimum to change just because the divider changed. */ static ssize_t set_fan_div(struct device *dev, const char *buf, size_t count, int nr) diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c new file mode 100644 index 0000000..bdc4570 --- /dev/null +++ b/drivers/hwmon/smsc47m192.c @@ -0,0 +1,648 @@ +/* + smsc47m192.c - Support for hardware monitoring block of + SMSC LPC47M192 and LPC47M997 Super I/O chips + + Copyright (C) 2006 Hartmut Rick + + Derived from lm78.c and other chip drivers. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(smsc47m192); + +/* SMSC47M192 registers */ +#define SMSC47M192_REG_IN(nr) ((nr)<6 ? (0x20 + (nr)) : \ + (0x50 + (nr) - 6)) +#define SMSC47M192_REG_IN_MAX(nr) ((nr)<6 ? (0x2b + (nr) * 2) : \ + (0x54 + (((nr) - 6) * 2))) +#define SMSC47M192_REG_IN_MIN(nr) ((nr)<6 ? (0x2c + (nr) * 2) : \ + (0x55 + (((nr) - 6) * 2))) +static u8 SMSC47M192_REG_TEMP[3] = { 0x27, 0x26, 0x52 }; +static u8 SMSC47M192_REG_TEMP_MAX[3] = { 0x39, 0x37, 0x58 }; +static u8 SMSC47M192_REG_TEMP_MIN[3] = { 0x3A, 0x38, 0x59 }; +#define SMSC47M192_REG_TEMP_OFFSET(nr) ((nr)==2 ? 0x1e : 0x1f) +#define SMSC47M192_REG_ALARM1 0x41 +#define SMSC47M192_REG_ALARM2 0x42 +#define SMSC47M192_REG_VID 0x47 +#define SMSC47M192_REG_VID4 0x49 +#define SMSC47M192_REG_CONFIG 0x40 +#define SMSC47M192_REG_SFR 0x4f +#define SMSC47M192_REG_COMPANY_ID 0x3e +#define SMSC47M192_REG_VERSION 0x3f + +/* generalised scaling with integer rounding */ +static inline int SCALE(long val, int mul, int div) +{ + if (val < 0) + return (val * mul - div / 2) / div; + else + return (val * mul + div / 2) / div; +} + +/* Conversions */ + +/* smsc47m192 internally scales voltage measurements */ +static const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 }; + +static inline unsigned int IN_FROM_REG(u8 reg, int n) +{ + return SCALE(reg, nom_mv[n], 192); +} + +static inline u8 IN_TO_REG(unsigned long val, int n) +{ + return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255); +} + +/* TEMP: 0.001 degC units (-128C to +127C) + REG: 1C/bit, two's complement */ +static inline s8 TEMP_TO_REG(int val) +{ + return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000); +} + +static inline int TEMP_FROM_REG(s8 val) +{ + return val * 1000; +} + +struct smsc47m192_data { + struct i2c_client client; + struct class_device *class_dev; + struct semaphore update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + + u8 in[8]; /* Register value */ + u8 in_max[8]; /* Register value */ + u8 in_min[8]; /* Register value */ + s8 temp[3]; /* Register value */ + s8 temp_max[3]; /* Register value */ + s8 temp_min[3]; /* Register value */ + s8 temp_offset[3]; /* Register value */ + u16 alarms; /* Register encoding, combined */ + u8 vid; /* Register encoding, combined */ + u8 vrm; +}; + +static int smsc47m192_attach_adapter(struct i2c_adapter *adapter); +static int smsc47m192_detect(struct i2c_adapter *adapter, int address, + int kind); +static int smsc47m192_detach_client(struct i2c_client *client); +static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); + +static struct i2c_driver smsc47m192_driver = { + .driver = { + .name = "smsc47m192", + }, + .attach_adapter = smsc47m192_attach_adapter, + .detach_client = smsc47m192_detach_client, +}; + +/* Voltages */ +static ssize_t show_in(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr)); +} + +static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr)); +} + +static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr)); +} + +static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + down(&data->update_lock); + data->in_min[nr] = IN_TO_REG(val, nr); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr), + data->in_min[nr]); + up(&data->update_lock); + return count; +} + +static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + down(&data->update_lock); + data->in_max[nr] = IN_TO_REG(val, nr); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr), + data->in_max[nr]); + up(&data->update_lock); + return count; +} + +#define show_in_offset(offset) \ +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ + show_in, NULL, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ + show_in_min, set_in_min, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ + show_in_max, set_in_max, offset); + +show_in_offset(0) +show_in_offset(1) +show_in_offset(2) +show_in_offset(3) +show_in_offset(4) +show_in_offset(5) +show_in_offset(6) +show_in_offset(7) + +/* Temperatures */ +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); +} + +static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); +} + +static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); +} + +static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->temp_min[nr] = TEMP_TO_REG(val); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr], + data->temp_min[nr]); + up(&data->update_lock); + return count; +} + +static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->temp_max[nr] = TEMP_TO_REG(val); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr], + data->temp_max[nr]); + up(&data->update_lock); + return count; +} + +static ssize_t show_temp_offset(struct device *dev, struct device_attribute + *attr, char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr])); +} + +static ssize_t set_temp_offset(struct device *dev, struct device_attribute + *attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->temp_offset[nr] = TEMP_TO_REG(val); + if (nr>1) + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); + else if (data->temp_offset[nr] != 0) { + /* offset[0] and offset[1] share the same register, + SFR bit 4 activates offset[0] */ + i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, + (sfr & 0xef) | (nr==0 ? 0x10 : 0)); + data->temp_offset[1-nr] = 0; + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); + } else if ((sfr & 0x10) == (nr==0 ? 0x10 : 0)) + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(nr), 0); + up(&data->update_lock); + return count; +} + +#define show_temp_index(index) \ +static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, \ + show_temp, NULL, index-1); \ +static SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO | S_IWUSR, \ + show_temp_min, set_temp_min, index-1); \ +static SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO | S_IWUSR, \ + show_temp_max, set_temp_max, index-1); \ +static SENSOR_DEVICE_ATTR(temp##index##_offset, S_IRUGO | S_IWUSR, \ + show_temp_offset, set_temp_offset, index-1); + +show_temp_index(1) +show_temp_index(2) +show_temp_index(3) + +/* VID */ +static ssize_t show_vid(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); +} +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); + +static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", data->vrm); +} + +static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + data->vrm = simple_strtoul(buf, NULL, 10); + return count; +} +static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); + +/* Alarms */ +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms & nr) ? 1 : 0); +} + +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040); +static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 0x4000); +static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 0x8000); +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 0x0008); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 0x0100); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800); + +/* This function is called when: + * smsc47m192_driver is inserted (when this module is loaded), for each + available adapter + * when a new adapter is inserted (and smsc47m192_driver is still present) */ +static int smsc47m192_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, smsc47m192_detect); +} + +static void smsc47m192_init_client(struct i2c_client *client) +{ + int i; + u8 config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); + u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); + + /* select cycle mode (pause 1 sec between updates) */ + i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, + (sfr & 0xfd) | 0x02); + if (!(config & 0x01)) { + /* initialize alarm limits */ + for (i=0; i<8; i++) { + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_IN_MIN(i), 0); + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_IN_MAX(i), 0xff); + } + for (i=0; i<3; i++) { + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_MIN[i], 0x80); + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_MAX[i], 0x7f); + } + + /* start monitoring */ + i2c_smbus_write_byte_data(client, SMSC47M192_REG_CONFIG, + (config & 0xf7) | 0x01); + } +} + +/* This function is called by i2c_probe */ +static int smsc47m192_detect(struct i2c_adapter *adapter, int address, + int kind) +{ + struct i2c_client *client; + struct smsc47m192_data *data; + int err = 0; + int version, config; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + goto exit; + + if (!(data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &smsc47m192_driver; + + if (kind == 0) + kind = smsc47m192; + + /* Detection criteria from sensors_detect script */ + if (kind < 0) { + if (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_COMPANY_ID) == 0x55 + && ((version = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VERSION)) & 0xf0) == 0x20 + && (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VID) & 0x70) == 0x00 + && (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VID4) & 0xfe) == 0x80) { + dev_info(&adapter->dev, + "found SMSC47M192 or SMSC47M997, " + "version 2, stepping A%d\n", version & 0x0f); + } else { + dev_dbg(&adapter->dev, + "SMSC47M192 detection failed at 0x%02x\n", + address); + goto exit_free; + } + } + + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE); + data->vrm = vid_which_vrm(); + init_MUTEX(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + + /* Initialize the SMSC47M192 chip */ + smsc47m192_init_client(client); + + /* Register sysfs hooks */ + data->class_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto exit_detach; + } + + device_create_file(&client->dev, &sensor_dev_attr_in0_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in0_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in0_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in0_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_alarm.dev_attr); + + /* Pin 110 is either in4 (+12V) or VID4 */ + config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); + if (!(config & 0x20)) { + device_create_file(&client->dev, + &sensor_dev_attr_in4_input.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_in4_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_in4_max.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_in4_alarm.dev_attr); + } + device_create_file(&client->dev, &sensor_dev_attr_in5_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in5_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in5_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in5_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp1_offset.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp2_offset.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_alarm.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp2_input_fault.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp3_offset.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_alarm.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp3_input_fault.dev_attr); + device_create_file(&client->dev, &dev_attr_cpu0_vid); + device_create_file(&client->dev, &dev_attr_vrm); + + return 0; + +exit_detach: + i2c_detach_client(client); +exit_free: + kfree(data); +exit: + return err; +} + +static int smsc47m192_detach_client(struct i2c_client *client) +{ + struct smsc47m192_data *data = i2c_get_clientdata(client); + int err; + + hwmon_device_unregister(data->class_dev); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(data); + + return 0; +} + +static struct smsc47m192_data *smsc47m192_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + int i, config; + + down(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); + + dev_dbg(&client->dev, "Starting smsc47m192 update\n"); + + for (i = 0; i <= 7; i++) { + data->in[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN(i)); + data->in_min[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN_MIN(i)); + data->in_max[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN_MAX(i)); + } + for (i = 0; i < 3; i++) { + data->temp[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP[i]); + data->temp_max[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_MAX[i]); + data->temp_min[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_MIN[i]); + } + for (i = 1; i < 3; i++) + data->temp_offset[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(i)); + /* first offset is temp_offset[0] if SFR bit 4 is set, + temp_offset[1] otherwise */ + if (sfr & 0x10) { + data->temp_offset[0] = data->temp_offset[1]; + data->temp_offset[1] = 0; + } else + data->temp_offset[0] = 0; + + data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID) + & 0x0f; + config = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_CONFIG); + if (config & 0x20) + data->vid |= (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VID4) & 0x01) << 4; + data->alarms = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_ALARM1) | + (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_ALARM2) << 8); + + data->last_updated = jiffies; + data->valid = 1; + } + + up(&data->update_lock); + + return data; +} + +static int __init smsc47m192_init(void) +{ + return i2c_add_driver(&smsc47m192_driver); +} + +static void __exit smsc47m192_exit(void) +{ + i2c_del_driver(&smsc47m192_driver); +} + +MODULE_AUTHOR("Hartmut Rick "); +MODULE_DESCRIPTION("SMSC47M192 driver"); +MODULE_LICENSE("GPL"); + +module_init(smsc47m192_init); +module_exit(smsc47m192_exit); diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index b6bd568..40301bc 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -30,10 +30,7 @@ Supports the following chips: Chip #vin #fan #pwm #temp chip_id man_id - w83627ehf - 5 - 3 0x88 0x5ca3 - - This is a preliminary version of the driver, only supporting the - fan and temperature inputs. The chip does much more than that. + w83627ehf 10 5 - 3 0x88 0x5ca3 */ #include @@ -121,6 +118,14 @@ #define W83627EHF_REG_MAN_ID 0x4F static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 }; static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c }; +/* The W83627EHF registers for nr=7,8,9 are in bank 5 */ +#define W83627EHF_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ + (0x554 + (((nr) - 7) * 2))) +#define W83627EHF_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ + (0x555 + (((nr) - 7) * 2))) +#define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ + (0x550 + (nr) - 7)) + #define W83627EHF_REG_TEMP1 0x27 #define W83627EHF_REG_TEMP1_HYST 0x3a #define W83627EHF_REG_TEMP1_OVER 0x39 @@ -136,6 +141,10 @@ #define W83627EHF_REG_VBAT 0x5D #define W83627EHF_REG_DIODE 0x59 #define W83627EHF_REG_SMI_OVT 0x4C +#define W83627EHF_REG_ALARM1 0x459 +#define W83627EHF_REG_ALARM2 0x45A +#define W83627EHF_REG_ALARM3 0x45B + /* * Conversions */ @@ -172,6 +181,20 @@ temp1_to_reg(int temp) return (temp + 500) / 1000; } +/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */ + +static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 }; + +static inline long in_from_reg(u8 reg, u8 nr) +{ + return reg * scale_in[nr]; +} + +static inline u8 in_to_reg(u32 val, u8 nr) +{ + return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255); +} + /* * Data structures and manipulation thereof */ @@ -186,6 +209,9 @@ struct w83627ehf_data { unsigned long last_updated; /* In jiffies */ /* Register values */ + u8 in[10]; /* Register value */ + u8 in_max[10]; /* Register value */ + u8 in_min[10]; /* Register value */ u8 fan[5]; u8 fan_min[5]; u8 fan_div[5]; @@ -196,6 +222,7 @@ struct w83627ehf_data { s16 temp[2]; s16 temp_max[2]; s16 temp_max_hyst[2]; + u32 alarms; }; static inline int is_word_sized(u16 reg) @@ -349,6 +376,16 @@ static struct w83627ehf_data *w83627ehf_ data->fan_div[3] |= (i >> 5) & 0x04; } + /* Measured voltages and limits */ + for (i = 0; i < 10; i++) { + data->in[i] = w83627ehf_read_value(client, + W83627EHF_REG_IN(i)); + data->in_min[i] = w83627ehf_read_value(client, + W83627EHF_REG_IN_MIN(i)); + data->in_max[i] = w83627ehf_read_value(client, + W83627EHF_REG_IN_MAX(i)); + } + /* Measured fan speeds and limits */ for (i = 0; i < 5; i++) { if (!(data->has_fan & (1 << i))) @@ -395,6 +432,13 @@ static struct w83627ehf_data *w83627ehf_ W83627EHF_REG_TEMP_HYST[i]); } + data->alarms = w83627ehf_read_value(client, + W83627EHF_REG_ALARM1) | + (w83627ehf_read_value(client, + W83627EHF_REG_ALARM2) << 8) | + (w83627ehf_read_value(client, + W83627EHF_REG_ALARM3) << 16); + data->last_updated = jiffies; data->valid = 1; } @@ -406,6 +450,109 @@ static struct w83627ehf_data *w83627ehf_ /* * Sysfs callback functions */ +#define show_in_reg(reg) \ +static ssize_t \ +show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct w83627ehf_data *data = w83627ehf_update_device(dev); \ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ + int nr = sensor_attr->index; \ + return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \ +} +show_in_reg(in) +show_in_reg(in_min) +show_in_reg(in_max) + +#define store_in_reg(REG, reg) \ +static ssize_t \ +store_in_##reg (struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct w83627ehf_data *data = i2c_get_clientdata(client); \ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ + int nr = sensor_attr->index; \ + u32 val = simple_strtoul(buf, NULL, 10); \ + \ + mutex_lock(&data->update_lock); \ + data->in_##reg[nr] = in_to_reg(val, nr); \ + w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \ + data->in_##reg[nr]); \ + mutex_unlock(&data->update_lock); \ + return count; \ +} + +store_in_reg(MIN, min) +store_in_reg(MAX, max) + +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct w83627ehf_data *data = w83627ehf_update_device(dev); + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + return sprintf(buf, "%u\n", (data->alarms >> nr) & 0x01); +} + +static struct sensor_device_attribute sda_in_input[] = { + SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), + SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), + SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), + SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), + SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), + SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), + SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), + SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), + SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9), +}; + +static struct sensor_device_attribute sda_in_alarm[] = { + SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), + SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), + SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), + SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), + SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8), + SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21), + SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20), + SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16), + SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17), + SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19), +}; + +static struct sensor_device_attribute sda_in_min[] = { + SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), + SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), + SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), + SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), + SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), + SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), + SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), + SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), + SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), + SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9), +}; + +static struct sensor_device_attribute sda_in_max[] = { + SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), + SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), + SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), + SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), + SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), + SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), + SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), + SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), + SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), + SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), +}; + +static void device_create_file_in(struct device *dev, int i) +{ + device_create_file(dev, &sda_in_input[i].dev_attr); + device_create_file(dev, &sda_in_alarm[i].dev_attr); + device_create_file(dev, &sda_in_min[i].dev_attr); + device_create_file(dev, &sda_in_max[i].dev_attr); +} #define show_fan_reg(reg) \ static ssize_t \ @@ -505,6 +652,14 @@ static struct sensor_device_attribute sd SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4), }; +static struct sensor_device_attribute sda_fan_alarm[] = { + SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6), + SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7), + SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11), + SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 10), + SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23), +}; + static struct sensor_device_attribute sda_fan_min[] = { SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 0), @@ -529,6 +684,7 @@ static struct sensor_device_attribute sd static void device_create_file_fan(struct device *dev, int i) { device_create_file(dev, &sda_fan_input[i].dev_attr); + device_create_file(dev, &sda_fan_alarm[i].dev_attr); device_create_file(dev, &sda_fan_div[i].dev_attr); device_create_file(dev, &sda_fan_min[i].dev_attr); } @@ -616,6 +772,9 @@ static struct sensor_device_attribute sd store_temp_max_hyst, 0), SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, store_temp_max_hyst, 1), + SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), + SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), + SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), }; /* @@ -705,6 +864,9 @@ static int w83627ehf_detect(struct i2c_a goto exit_detach; } + for (i = 0; i < 10; i++) + device_create_file_in(dev, i); + for (i = 0; i < 5; i++) { if (data->has_fan & (1 << i)) device_create_file_fan(dev, i); diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 71fb7f1..79368d5 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -781,7 +781,7 @@ show_fan_div_reg(struct device *dev, cha /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan divisor. This follows the principle of - least suprise; the user doesn't expect the fan minimum to change just + least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ static ssize_t store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index e4c7003..7be469e 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -630,7 +630,7 @@ show_fan_div_reg(struct device *dev, cha /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan divisor. This follows the principle of - least suprise; the user doesn't expect the fan minimum to change just + least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ static ssize_t store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c new file mode 100644 index 0000000..eec43ab --- /dev/null +++ b/drivers/hwmon/w83791d.c @@ -0,0 +1,1255 @@ +/* + w83791d.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + + Copyright (C) 2006 Charles Spirakis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Supports following chips: + + Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + w83791d 10 5 3 3 0x71 0x5ca3 yes no + + The w83791d chip appears to be part way between the 83781d and the + 83792d. Thus, this file is derived from both the w83792d.c and + w83781d.c files, but its output is more along the lines of the + 83781d (which means there are no changes to the user-mode sensors + program which treats the 83791d as an 83781d). +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUMBER_OF_VIN 10 +#define NUMBER_OF_FANIN 5 +#define NUMBER_OF_TEMPIN 3 + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(w83791d); +I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " + "{bus, clientaddr, subclientaddr1, subclientaddr2}"); + +static int reset; +module_param(reset, bool, 0); +MODULE_PARM_DESC(reset, "Set to one to force a hardware chip reset"); + +static int init; +module_param(init, bool, 0); +MODULE_PARM_DESC(init, "Set to one to force extra software initialization"); + +/* The W83791D registers */ +static const u8 W83791D_REG_IN[NUMBER_OF_VIN] = { + 0x20, /* VCOREA in DataSheet */ + 0x21, /* VINR0 in DataSheet */ + 0x22, /* +3.3VIN in DataSheet */ + 0x23, /* VDD5V in DataSheet */ + 0x24, /* +12VIN in DataSheet */ + 0x25, /* -12VIN in DataSheet */ + 0x26, /* -5VIN in DataSheet */ + 0xB0, /* 5VSB in DataSheet */ + 0xB1, /* VBAT in DataSheet */ + 0xB2 /* VINR1 in DataSheet */ +}; + +static const u8 W83791D_REG_IN_MAX[NUMBER_OF_VIN] = { + 0x2B, /* VCOREA High Limit in DataSheet */ + 0x2D, /* VINR0 High Limit in DataSheet */ + 0x2F, /* +3.3VIN High Limit in DataSheet */ + 0x31, /* VDD5V High Limit in DataSheet */ + 0x33, /* +12VIN High Limit in DataSheet */ + 0x35, /* -12VIN High Limit in DataSheet */ + 0x37, /* -5VIN High Limit in DataSheet */ + 0xB4, /* 5VSB High Limit in DataSheet */ + 0xB6, /* VBAT High Limit in DataSheet */ + 0xB8 /* VINR1 High Limit in DataSheet */ +}; +static const u8 W83791D_REG_IN_MIN[NUMBER_OF_VIN] = { + 0x2C, /* VCOREA Low Limit in DataSheet */ + 0x2E, /* VINR0 Low Limit in DataSheet */ + 0x30, /* +3.3VIN Low Limit in DataSheet */ + 0x32, /* VDD5V Low Limit in DataSheet */ + 0x34, /* +12VIN Low Limit in DataSheet */ + 0x36, /* -12VIN Low Limit in DataSheet */ + 0x38, /* -5VIN Low Limit in DataSheet */ + 0xB5, /* 5VSB Low Limit in DataSheet */ + 0xB7, /* VBAT Low Limit in DataSheet */ + 0xB9 /* VINR1 Low Limit in DataSheet */ +}; +static const u8 W83791D_REG_FAN[NUMBER_OF_FANIN] = { + 0x28, /* FAN 1 Count in DataSheet */ + 0x29, /* FAN 2 Count in DataSheet */ + 0x2A, /* FAN 3 Count in DataSheet */ + 0xBA, /* FAN 4 Count in DataSheet */ + 0xBB, /* FAN 5 Count in DataSheet */ +}; +static const u8 W83791D_REG_FAN_MIN[NUMBER_OF_FANIN] = { + 0x3B, /* FAN 1 Count Low Limit in DataSheet */ + 0x3C, /* FAN 2 Count Low Limit in DataSheet */ + 0x3D, /* FAN 3 Count Low Limit in DataSheet */ + 0xBC, /* FAN 4 Count Low Limit in DataSheet */ + 0xBD, /* FAN 5 Count Low Limit in DataSheet */ +}; + +static const u8 W83791D_REG_FAN_CFG[2] = { + 0x84, /* FAN 1/2 configuration */ + 0x95, /* FAN 3 configuration */ +}; + +static const u8 W83791D_REG_FAN_DIV[3] = { + 0x47, /* contains FAN1 and FAN2 Divisor */ + 0x4b, /* contains FAN3 Divisor */ + 0x5C, /* contains FAN4 and FAN5 Divisor */ +}; + +#define W83791D_REG_BANK 0x4E +#define W83791D_REG_TEMP2_CONFIG 0xC2 +#define W83791D_REG_TEMP3_CONFIG 0xCA + +static const u8 W83791D_REG_TEMP1[3] = { + 0x27, /* TEMP 1 in DataSheet */ + 0x39, /* TEMP 1 Over in DataSheet */ + 0x3A, /* TEMP 1 Hyst in DataSheet */ +}; + +static const u8 W83791D_REG_TEMP_ADD[2][6] = { + {0xC0, /* TEMP 2 in DataSheet */ + 0xC1, /* TEMP 2(0.5 deg) in DataSheet */ + 0xC5, /* TEMP 2 Over High part in DataSheet */ + 0xC6, /* TEMP 2 Over Low part in DataSheet */ + 0xC3, /* TEMP 2 Thyst High part in DataSheet */ + 0xC4}, /* TEMP 2 Thyst Low part in DataSheet */ + {0xC8, /* TEMP 3 in DataSheet */ + 0xC9, /* TEMP 3(0.5 deg) in DataSheet */ + 0xCD, /* TEMP 3 Over High part in DataSheet */ + 0xCE, /* TEMP 3 Over Low part in DataSheet */ + 0xCB, /* TEMP 3 Thyst High part in DataSheet */ + 0xCC} /* TEMP 3 Thyst Low part in DataSheet */ +}; + +#define W83791D_REG_BEEP_CONFIG 0x4D + +static const u8 W83791D_REG_BEEP_CTRL[3] = { + 0x56, /* BEEP Control Register 1 */ + 0x57, /* BEEP Control Register 2 */ + 0xA3, /* BEEP Control Register 3 */ +}; + +#define W83791D_REG_CONFIG 0x40 +#define W83791D_REG_VID_FANDIV 0x47 +#define W83791D_REG_DID_VID4 0x49 +#define W83791D_REG_WCHIPID 0x58 +#define W83791D_REG_CHIPMAN 0x4F +#define W83791D_REG_PIN 0x4B +#define W83791D_REG_I2C_SUBADDR 0x4A + +#define W83791D_REG_ALARM1 0xA9 /* realtime status register1 */ +#define W83791D_REG_ALARM2 0xAA /* realtime status register2 */ +#define W83791D_REG_ALARM3 0xAB /* realtime status register3 */ + +#define W83791D_REG_VBAT 0x5D +#define W83791D_REG_I2C_ADDR 0x48 + +/* The SMBus locks itself. The Winbond W83791D has a bank select register + (index 0x4e), but the driver only accesses registers in bank 0. Since + we don't switch banks, we don't need any special code to handle + locking access between bank switches */ +static inline int w83791d_read(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static inline int w83791d_write(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* The analog voltage inputs have 16mV LSB. Since the sysfs output is + in mV as would be measured on the chip input pin, need to just + multiply/divide by 16 to translate from/to register values. */ +#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8) / 16), 0, 255)) +#define IN_FROM_REG(val) ((val) * 16) + +static u8 fan_to_reg(long rpm, int div) +{ + if (rpm == 0) + return 255; + rpm = SENSORS_LIMIT(rpm, 1, 1000000); + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); +} + +#define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \ + ((val) == 255 ? 0 : \ + 1350000 / ((val) * (div)))) + +/* for temp1 which is 8-bit resolution, LSB = 1 degree Celsius */ +#define TEMP1_FROM_REG(val) ((val) * 1000) +#define TEMP1_TO_REG(val) ((val) <= -128000 ? -128 : \ + (val) >= 127000 ? 127 : \ + (val) < 0 ? ((val) - 500) / 1000 : \ + ((val) + 500) / 1000) + +/* for temp2 and temp3 which are 9-bit resolution, LSB = 0.5 degree Celsius + Assumes the top 8 bits are the integral amount and the bottom 8 bits + are the fractional amount. Since we only have 0.5 degree resolution, + the bottom 7 bits will always be zero */ +#define TEMP23_FROM_REG(val) ((val) / 128 * 500) +#define TEMP23_TO_REG(val) ((val) <= -128000 ? 0x8000 : \ + (val) >= 127500 ? 0x7F80 : \ + (val) < 0 ? ((val) - 250) / 500 * 128 : \ + ((val) + 250) / 500 * 128) + + +#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff) +#define BEEP_MASK_FROM_REG(val) ((val) & 0xffffff) + +#define DIV_FROM_REG(val) (1 << (val)) + +static u8 div_to_reg(int nr, long val) +{ + int i; + int max; + + /* first three fan's divisor max out at 8, rest max out at 128 */ + max = (nr < 3) ? 8 : 128; + val = SENSORS_LIMIT(val, 1, max) >> 1; + for (i = 0; i < 7; i++) { + if (val == 0) + break; + val >>= 1; + } + return (u8) i; +} + +struct w83791d_data { + struct i2c_client client; + struct class_device *class_dev; + struct mutex update_lock; + + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + + /* array of 2 pointers to subclients */ + struct i2c_client *lm75[2]; + + /* volts */ + u8 in[NUMBER_OF_VIN]; /* Register value */ + u8 in_max[NUMBER_OF_VIN]; /* Register value */ + u8 in_min[NUMBER_OF_VIN]; /* Register value */ + + /* fans */ + u8 fan[NUMBER_OF_FANIN]; /* Register value */ + u8 fan_min[NUMBER_OF_FANIN]; /* Register value */ + u8 fan_div[NUMBER_OF_FANIN]; /* Register encoding, shifted right */ + + /* Temperature sensors */ + + s8 temp1[3]; /* current, over, thyst */ + s16 temp_add[2][3]; /* fixed point value. Top 8 bits are the + integral part, bottom 8 bits are the + fractional part. We only use the top + 9 bits as the resolution is only + to the 0.5 degree C... + two sensors with three values + (cur, over, hyst) */ + + /* Misc */ + u32 alarms; /* realtime status register encoding,combined */ + u8 beep_enable; /* Global beep enable */ + u32 beep_mask; /* Mask off specific beeps */ + u8 vid; /* Register encoding, combined */ + u8 vrm; /* hwmon-vid */ +}; + +static int w83791d_attach_adapter(struct i2c_adapter *adapter); +static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind); +static int w83791d_detach_client(struct i2c_client *client); + +static int w83791d_read(struct i2c_client *client, u8 register); +static int w83791d_write(struct i2c_client *client, u8 register, u8 value); +static struct w83791d_data *w83791d_update_device(struct device *dev); + +#ifdef DEBUG +static void w83791d_print_debug(struct w83791d_data *data, struct device *dev); +#endif + +static void w83791d_init_client(struct i2c_client *client); + +static struct i2c_driver w83791d_driver = { + .driver = { + .name = "w83791d", + }, + .attach_adapter = w83791d_attach_adapter, + .detach_client = w83791d_detach_client, +}; + +/* following are the sysfs callback functions */ +#define show_in_reg(reg) \ +static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sensor_device_attribute *sensor_attr = \ + to_sensor_dev_attr(attr); \ + struct w83791d_data *data = w83791d_update_device(dev); \ + int nr = sensor_attr->index; \ + return sprintf(buf,"%d\n", IN_FROM_REG(data->reg[nr])); \ +} + +show_in_reg(in); +show_in_reg(in_min); +show_in_reg(in_max); + +#define store_in_reg(REG, reg) \ +static ssize_t store_in_##reg(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct sensor_device_attribute *sensor_attr = \ + to_sensor_dev_attr(attr); \ + struct i2c_client *client = to_i2c_client(dev); \ + struct w83791d_data *data = i2c_get_clientdata(client); \ + unsigned long val = simple_strtoul(buf, NULL, 10); \ + int nr = sensor_attr->index; \ + \ + mutex_lock(&data->update_lock); \ + data->in_##reg[nr] = IN_TO_REG(val); \ + w83791d_write(client, W83791D_REG_IN_##REG[nr], data->in_##reg[nr]); \ + mutex_unlock(&data->update_lock); \ + \ + return count; \ +} +store_in_reg(MIN, min); +store_in_reg(MAX, max); + +static struct sensor_device_attribute sda_in_input[] = { + SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), + SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), + SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), + SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), + SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), + SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), + SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), + SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), + SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9), +}; + +static struct sensor_device_attribute sda_in_min[] = { + SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), + SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), + SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), + SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), + SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), + SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), + SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), + SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), + SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), + SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9), +}; + +static struct sensor_device_attribute sda_in_max[] = { + SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), + SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), + SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), + SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), + SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), + SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), + SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), + SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), + SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), + SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), +}; + +#define show_fan_reg(reg) \ +static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sensor_device_attribute *sensor_attr = \ + to_sensor_dev_attr(attr); \ + struct w83791d_data *data = w83791d_update_device(dev); \ + int nr = sensor_attr->index; \ + return sprintf(buf,"%d\n", \ + FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \ +} + +show_fan_reg(fan); +show_fan_reg(fan_min); + +static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + int nr = sensor_attr->index; + + mutex_lock(&data->update_lock); + data->fan_min[nr] = fan_to_reg(val, DIV_FROM_REG(data->fan_div[nr])); + w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr])); +} + +/* Note: we save and restore the fan minimum here, because its value is + determined in part by the fan divisor. This follows the principle of + least suprise; the user doesn't expect the fan minimum to change just + because the divisor changed. */ +static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + int nr = sensor_attr->index; + unsigned long min; + u8 tmp_fan_div; + u8 fan_div_reg; + int indx = 0; + u8 keep_mask = 0; + u8 new_shift = 0; + + /* Save fan_min */ + min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); + + mutex_lock(&data->update_lock); + data->fan_div[nr] = div_to_reg(nr, simple_strtoul(buf, NULL, 10)); + + switch (nr) { + case 0: + indx = 0; + keep_mask = 0xcf; + new_shift = 4; + break; + case 1: + indx = 0; + keep_mask = 0x3f; + new_shift = 6; + break; + case 2: + indx = 1; + keep_mask = 0x3f; + new_shift = 6; + break; + case 3: + indx = 2; + keep_mask = 0xf8; + new_shift = 0; + break; + case 4: + indx = 2; + keep_mask = 0x8f; + new_shift = 4; + break; +#ifdef DEBUG + default: + dev_warn(dev, "store_fan_div: Unexpected nr seen: %d\n", nr); + count = -EINVAL; + goto err_exit; +#endif + } + + fan_div_reg = w83791d_read(client, W83791D_REG_FAN_DIV[indx]) + & keep_mask; + tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask; + + w83791d_write(client, W83791D_REG_FAN_DIV[indx], + fan_div_reg | tmp_fan_div); + + /* Restore fan_min */ + data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr])); + w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]); + +#ifdef DEBUG +err_exit: +#endif + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute sda_fan_input[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), + SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), + SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), + SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4), +}; + +static struct sensor_device_attribute sda_fan_min[] = { + SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 0), + SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 1), + SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 2), + SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 3), + SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 4), +}; + +static struct sensor_device_attribute sda_fan_div[] = { + SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 0), + SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 1), + SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 2), + SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 3), + SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 4), +}; + +/* read/write the temperature1, includes measured value and limits */ +static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[attr->index])); +} + +static ssize_t store_temp1(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + int nr = attr->index; + + mutex_lock(&data->update_lock); + data->temp1[nr] = TEMP1_TO_REG(val); + w83791d_write(client, W83791D_REG_TEMP1[nr], data->temp1[nr]); + mutex_unlock(&data->update_lock); + return count; +} + +/* read/write temperature2-3, includes measured value and limits */ +static ssize_t show_temp23(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct w83791d_data *data = w83791d_update_device(dev); + int nr = attr->nr; + int index = attr->index; + return sprintf(buf, "%d\n", TEMP23_FROM_REG(data->temp_add[nr][index])); +} + +static ssize_t store_temp23(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + int nr = attr->nr; + int index = attr->index; + + mutex_lock(&data->update_lock); + data->temp_add[nr][index] = TEMP23_TO_REG(val); + w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2], + data->temp_add[nr][index] >> 8); + w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2 + 1], + data->temp_add[nr][index] & 0x80); + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute_2 sda_temp_input[] = { + SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0), + SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0), + SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0), +}; + +static struct sensor_device_attribute_2 sda_temp_max[] = { + SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, + show_temp1, store_temp1, 0, 1), + SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 0, 1), + SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 1, 1), +}; + +static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { + SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, + show_temp1, store_temp1, 0, 2), + SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 0, 2), + SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 1, 2), +}; + + +/* get reatime status of all sensors items: voltage, temp, fan */ +static ssize_t show_alarms_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%u\n", data->alarms); +} + +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); + +/* Beep control */ + +#define GLOBAL_BEEP_ENABLE_SHIFT 15 +#define GLOBAL_BEEP_ENABLE_MASK (1 << GLOBAL_BEEP_ENABLE_SHIFT) + +static ssize_t show_beep_enable(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", data->beep_enable); +} + +static ssize_t show_beep_mask(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", BEEP_MASK_FROM_REG(data->beep_mask)); +} + + +static ssize_t store_beep_mask(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + int i; + + mutex_lock(&data->update_lock); + + /* The beep_enable state overrides any enabling request from + the masks */ + data->beep_mask = BEEP_MASK_TO_REG(val) & ~GLOBAL_BEEP_ENABLE_MASK; + data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT); + + val = data->beep_mask; + + for (i = 0; i < 3; i++) { + w83791d_write(client, W83791D_REG_BEEP_CTRL[i], (val & 0xff)); + val >>= 8; + } + + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t store_beep_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + + data->beep_enable = val ? 1 : 0; + + /* Keep the full mask value in sync with the current enable */ + data->beep_mask &= ~GLOBAL_BEEP_ENABLE_MASK; + data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT); + + /* The global control is in the second beep control register + so only need to update that register */ + val = (data->beep_mask >> 8) & 0xff; + + w83791d_write(client, W83791D_REG_BEEP_CTRL[1], val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute sda_beep_ctrl[] = { + SENSOR_ATTR(beep_enable, S_IRUGO | S_IWUSR, + show_beep_enable, store_beep_enable, 0), + SENSOR_ATTR(beep_mask, S_IRUGO | S_IWUSR, + show_beep_mask, store_beep_mask, 1) +}; + +/* cpu voltage regulation information */ +static ssize_t show_vid_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); +} + +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); + +static ssize_t show_vrm_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", data->vrm); +} + +static ssize_t store_vrm_reg(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + /* No lock needed as vrm is internal to the driver + (not read from a chip register) and so is not + updated in w83791d_update_device() */ + data->vrm = val; + + return count; +} + +static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); + +/* This function is called when: + * w83791d_driver is inserted (when this module is loaded), for each + available adapter + * when a new adapter is inserted (and w83791d_driver is still present) */ +static int w83791d_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, w83791d_detect); +} + + +static int w83791d_create_subclient(struct i2c_adapter *adapter, + struct i2c_client *client, int addr, + struct i2c_client **sub_cli) +{ + int err; + struct i2c_client *sub_client; + + (*sub_cli) = sub_client = + kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!(sub_client)) { + return -ENOMEM; + } + sub_client->addr = 0x48 + addr; + i2c_set_clientdata(sub_client, NULL); + sub_client->adapter = adapter; + sub_client->driver = &w83791d_driver; + strlcpy(sub_client->name, "w83791d subclient", I2C_NAME_SIZE); + if ((err = i2c_attach_client(sub_client))) { + dev_err(&client->dev, "subclient registration " + "at address 0x%x failed\n", sub_client->addr); + kfree(sub_client); + return err; + } + return 0; +} + + +static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address, + int kind, struct i2c_client *client) +{ + struct w83791d_data *data = i2c_get_clientdata(client); + int i, id, err; + u8 val; + + id = i2c_adapter_id(adapter); + if (force_subclients[0] == id && force_subclients[1] == address) { + for (i = 2; i <= 3; i++) { + if (force_subclients[i] < 0x48 || + force_subclients[i] > 0x4f) { + dev_err(&client->dev, + "invalid subclient " + "address %d; must be 0x48-0x4f\n", + force_subclients[i]); + err = -ENODEV; + goto error_sc_0; + } + } + w83791d_write(client, W83791D_REG_I2C_SUBADDR, + (force_subclients[2] & 0x07) | + ((force_subclients[3] & 0x07) << 4)); + } + + val = w83791d_read(client, W83791D_REG_I2C_SUBADDR); + if (!(val & 0x08)) { + err = w83791d_create_subclient(adapter, client, + val & 0x7, &data->lm75[0]); + if (err < 0) + goto error_sc_0; + } + if (!(val & 0x80)) { + if ((data->lm75[0] != NULL) && + ((val & 0x7) == ((val >> 4) & 0x7))) { + dev_err(&client->dev, + "duplicate addresses 0x%x, " + "use force_subclient\n", + data->lm75[0]->addr); + err = -ENODEV; + goto error_sc_1; + } + err = w83791d_create_subclient(adapter, client, + (val >> 4) & 0x7, &data->lm75[1]); + if (err < 0) + goto error_sc_1; + } + + return 0; + +/* Undo inits in case of errors */ + +error_sc_1: + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } +error_sc_0: + return err; +} + + +static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct device *dev; + struct w83791d_data *data; + int i, val1, val2; + int err = 0; + const char *client_name = ""; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + goto error0; + } + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access w83791d_{read,write}_value. */ + if (!(data = kzalloc(sizeof(struct w83791d_data), GFP_KERNEL))) { + err = -ENOMEM; + goto error0; + } + + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &w83791d_driver; + mutex_init(&data->update_lock); + + /* Now, we do the remaining detection. */ + + /* The w83791d may be stuck in some other bank than bank 0. This may + make reading other information impossible. Specify a force=... + parameter, and the Winbond will be reset to the right bank. */ + if (kind < 0) { + if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80) { + dev_dbg(dev, "Detection failed at step 1\n"); + goto error1; + } + val1 = w83791d_read(client, W83791D_REG_BANK); + val2 = w83791d_read(client, W83791D_REG_CHIPMAN); + /* Check for Winbond ID if in bank 0 */ + if (!(val1 & 0x07)) { + /* yes it is Bank0 */ + if (((!(val1 & 0x80)) && (val2 != 0xa3)) || + ((val1 & 0x80) && (val2 != 0x5c))) { + dev_dbg(dev, "Detection failed at step 2\n"); + goto error1; + } + } + /* If Winbond chip, address of chip and W83791D_REG_I2C_ADDR + should match */ + if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address) { + dev_dbg(dev, "Detection failed at step 3\n"); + goto error1; + } + } + + /* We either have a force parameter or we have reason to + believe it is a Winbond chip. Either way, we want bank 0 and + Vendor ID high byte */ + val1 = w83791d_read(client, W83791D_REG_BANK) & 0x78; + w83791d_write(client, W83791D_REG_BANK, val1 | 0x80); + + /* Verify it is a Winbond w83791d */ + if (kind <= 0) { + /* get vendor ID */ + val2 = w83791d_read(client, W83791D_REG_CHIPMAN); + if (val2 != 0x5c) { /* the vendor is NOT Winbond */ + dev_dbg(dev, "Detection failed at step 4\n"); + goto error1; + } + val1 = w83791d_read(client, W83791D_REG_WCHIPID); + if (val1 == 0x71) { + kind = w83791d; + } else { + if (kind == 0) + dev_warn(dev, + "w83791d: Ignoring 'force' parameter " + "for unknown chip at adapter %d, " + "address 0x%02x\n", + i2c_adapter_id(adapter), address); + goto error1; + } + } + + if (kind == w83791d) { + client_name = "w83791d"; + } else { + dev_err(dev, "w83791d: Internal error: unknown kind (%d)?!?", + kind); + goto error1; + } + +#ifdef DEBUG + val1 = w83791d_read(client, W83791D_REG_DID_VID4); + dev_dbg(dev, "Device ID version: %d.%d (0x%02x)\n", + (val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1); +#endif + + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, client_name, I2C_NAME_SIZE); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto error1; + + if ((err = w83791d_detect_subclients(adapter, address, kind, client))) + goto error2; + + /* Initialize the chip */ + w83791d_init_client(client); + + /* If the fan_div is changed, make sure there is a rational + fan_min in place */ + for (i = 0; i < NUMBER_OF_FANIN; i++) { + data->fan_min[i] = w83791d_read(client, W83791D_REG_FAN_MIN[i]); + } + + /* Register sysfs hooks */ + data->class_dev = hwmon_device_register(dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto error3; + } + + for (i = 0; i < NUMBER_OF_VIN; i++) { + device_create_file(dev, &sda_in_input[i].dev_attr); + device_create_file(dev, &sda_in_min[i].dev_attr); + device_create_file(dev, &sda_in_max[i].dev_attr); + } + + for (i = 0; i < NUMBER_OF_FANIN; i++) { + device_create_file(dev, &sda_fan_input[i].dev_attr); + device_create_file(dev, &sda_fan_div[i].dev_attr); + device_create_file(dev, &sda_fan_min[i].dev_attr); + } + + for (i = 0; i < NUMBER_OF_TEMPIN; i++) { + device_create_file(dev, &sda_temp_input[i].dev_attr); + device_create_file(dev, &sda_temp_max[i].dev_attr); + device_create_file(dev, &sda_temp_max_hyst[i].dev_attr); + } + + device_create_file(dev, &dev_attr_alarms); + + for (i = 0; i < ARRAY_SIZE(sda_beep_ctrl); i++) { + device_create_file(dev, &sda_beep_ctrl[i].dev_attr); + } + + device_create_file(dev, &dev_attr_cpu0_vid); + device_create_file(dev, &dev_attr_vrm); + + return 0; + +error3: + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } + if (data->lm75[1] != NULL) { + i2c_detach_client(data->lm75[1]); + kfree(data->lm75[1]); + } +error2: + i2c_detach_client(client); +error1: + kfree(data); +error0: + return err; +} + +static int w83791d_detach_client(struct i2c_client *client) +{ + struct w83791d_data *data = i2c_get_clientdata(client); + int err; + + /* main client */ + if (data) + hwmon_device_unregister(data->class_dev); + + if ((err = i2c_detach_client(client))) + return err; + + /* main client */ + if (data) + kfree(data); + /* subclient */ + else + kfree(client); + + return 0; +} + +static void w83791d_init_client(struct i2c_client *client) +{ + struct w83791d_data *data = i2c_get_clientdata(client); + u8 tmp; + u8 old_beep; + + /* The difference between reset and init is that reset + does a hard reset of the chip via index 0x40, bit 7, + but init simply forces certain registers to have "sane" + values. The hope is that the BIOS has done the right + thing (which is why the default is reset=0, init=0), + but if not, reset is the hard hammer and init + is the soft mallet both of which are trying to whack + things into place... + NOTE: The data sheet makes a distinction between + "power on defaults" and "reset by MR". As far as I can tell, + the hard reset puts everything into a power-on state so I'm + not sure what "reset by MR" means or how it can happen. + */ + if (reset || init) { + /* keep some BIOS settings when we... */ + old_beep = w83791d_read(client, W83791D_REG_BEEP_CONFIG); + + if (reset) { + /* ... reset the chip and ... */ + w83791d_write(client, W83791D_REG_CONFIG, 0x80); + } + + /* ... disable power-on abnormal beep */ + w83791d_write(client, W83791D_REG_BEEP_CONFIG, old_beep | 0x80); + + /* disable the global beep (not done by hard reset) */ + tmp = w83791d_read(client, W83791D_REG_BEEP_CTRL[1]); + w83791d_write(client, W83791D_REG_BEEP_CTRL[1], tmp & 0xef); + + if (init) { + /* Make sure monitoring is turned on for add-ons */ + tmp = w83791d_read(client, W83791D_REG_TEMP2_CONFIG); + if (tmp & 1) { + w83791d_write(client, W83791D_REG_TEMP2_CONFIG, + tmp & 0xfe); + } + + tmp = w83791d_read(client, W83791D_REG_TEMP3_CONFIG); + if (tmp & 1) { + w83791d_write(client, W83791D_REG_TEMP3_CONFIG, + tmp & 0xfe); + } + + /* Start monitoring */ + tmp = w83791d_read(client, W83791D_REG_CONFIG) & 0xf7; + w83791d_write(client, W83791D_REG_CONFIG, tmp | 0x01); + } + } + + data->vrm = vid_which_vrm(); +} + +static struct w83791d_data *w83791d_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + int i, j; + u8 reg_array_tmp[3]; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + (HZ * 3)) + || !data->valid) { + dev_dbg(dev, "Starting w83791d device update\n"); + + /* Update the voltages measured value and limits */ + for (i = 0; i < NUMBER_OF_VIN; i++) { + data->in[i] = w83791d_read(client, + W83791D_REG_IN[i]); + data->in_max[i] = w83791d_read(client, + W83791D_REG_IN_MAX[i]); + data->in_min[i] = w83791d_read(client, + W83791D_REG_IN_MIN[i]); + } + + /* Update the fan counts and limits */ + for (i = 0; i < NUMBER_OF_FANIN; i++) { + /* Update the Fan measured value and limits */ + data->fan[i] = w83791d_read(client, + W83791D_REG_FAN[i]); + data->fan_min[i] = w83791d_read(client, + W83791D_REG_FAN_MIN[i]); + } + + /* Update the fan divisor */ + for (i = 0; i < 3; i++) { + reg_array_tmp[i] = w83791d_read(client, + W83791D_REG_FAN_DIV[i]); + } + data->fan_div[0] = (reg_array_tmp[0] >> 4) & 0x03; + data->fan_div[1] = (reg_array_tmp[0] >> 6) & 0x03; + data->fan_div[2] = (reg_array_tmp[1] >> 6) & 0x03; + data->fan_div[3] = reg_array_tmp[2] & 0x07; + data->fan_div[4] = (reg_array_tmp[2] >> 4) & 0x07; + + /* Update the first temperature sensor */ + for (i = 0; i < 3; i++) { + data->temp1[i] = w83791d_read(client, + W83791D_REG_TEMP1[i]); + } + + /* Update the rest of the temperature sensors */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + data->temp_add[i][j] = + (w83791d_read(client, + W83791D_REG_TEMP_ADD[i][j * 2]) << 8) | + w83791d_read(client, + W83791D_REG_TEMP_ADD[i][j * 2 + 1]); + } + } + + /* Update the realtime status */ + data->alarms = + w83791d_read(client, W83791D_REG_ALARM1) + + (w83791d_read(client, W83791D_REG_ALARM2) << 8) + + (w83791d_read(client, W83791D_REG_ALARM3) << 16); + + /* Update the beep configuration information */ + data->beep_mask = + w83791d_read(client, W83791D_REG_BEEP_CTRL[0]) + + (w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) + + (w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16); + + data->beep_enable = + (data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01; + + /* Update the cpu voltage information */ + i = w83791d_read(client, W83791D_REG_VID_FANDIV); + data->vid = i & 0x0f; + data->vid |= (w83791d_read(client, W83791D_REG_DID_VID4) & 0x01) + << 4; + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + +#ifdef DEBUG + w83791d_print_debug(data, dev); +#endif + + return data; +} + +#ifdef DEBUG +static void w83791d_print_debug(struct w83791d_data *data, struct device *dev) +{ + int i = 0, j = 0; + + dev_dbg(dev, "======Start of w83791d debug values======\n"); + dev_dbg(dev, "%d set of Voltages: ===>\n", NUMBER_OF_VIN); + for (i = 0; i < NUMBER_OF_VIN; i++) { + dev_dbg(dev, "vin[%d] is: 0x%02x\n", i, data->in[i]); + dev_dbg(dev, "vin[%d] min is: 0x%02x\n", i, data->in_min[i]); + dev_dbg(dev, "vin[%d] max is: 0x%02x\n", i, data->in_max[i]); + } + dev_dbg(dev, "%d set of Fan Counts/Divisors: ===>\n", NUMBER_OF_FANIN); + for (i = 0; i < NUMBER_OF_FANIN; i++) { + dev_dbg(dev, "fan[%d] is: 0x%02x\n", i, data->fan[i]); + dev_dbg(dev, "fan[%d] min is: 0x%02x\n", i, data->fan_min[i]); + dev_dbg(dev, "fan_div[%d] is: 0x%02x\n", i, data->fan_div[i]); + } + + /* temperature math is signed, but only print out the + bits that matter */ + dev_dbg(dev, "%d set of Temperatures: ===>\n", NUMBER_OF_TEMPIN); + for (i = 0; i < 3; i++) { + dev_dbg(dev, "temp1[%d] is: 0x%02x\n", i, (u8) data->temp1[i]); + } + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + dev_dbg(dev, "temp_add[%d][%d] is: 0x%04x\n", i, j, + (u16) data->temp_add[i][j]); + } + } + + dev_dbg(dev, "Misc Information: ===>\n"); + dev_dbg(dev, "alarm is: 0x%08x\n", data->alarms); + dev_dbg(dev, "beep_mask is: 0x%08x\n", data->beep_mask); + dev_dbg(dev, "beep_enable is: %d\n", data->beep_enable); + dev_dbg(dev, "vid is: 0x%02x\n", data->vid); + dev_dbg(dev, "vrm is: 0x%02x\n", data->vrm); + dev_dbg(dev, "=======End of w83791d debug values========\n"); + dev_dbg(dev, "\n"); +} +#endif + +static int __init sensors_w83791d_init(void) +{ + return i2c_add_driver(&w83791d_driver); +} + +static void __exit sensors_w83791d_exit(void) +{ + i2c_del_driver(&w83791d_driver); +} + +MODULE_AUTHOR("Charles Spirakis "); +MODULE_DESCRIPTION("W83791D driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_w83791d_init); +module_exit(sensors_w83791d_exit); diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 958602e..e407c74 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -250,8 +250,6 @@ #define TEMP_ADD_TO_REG_HIGH(val) \ : (val)) / 1000, 0, 0xff)) #define TEMP_ADD_TO_REG_LOW(val) ((val%1000) ? 0x80 : 0x00) -#define PWM_FROM_REG(val) (val) -#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255)) #define DIV_FROM_REG(val) (1 << (val)) static inline u8 @@ -291,7 +289,6 @@ struct w83792d_data { u8 pwm[7]; /* We only consider the first 3 set of pwm, although 792 chip has 7 set of pwm. */ u8 pwmenable[3]; - u8 pwm_mode[7]; /* indicates PWM or DC mode: 1->PWM; 0->DC */ u32 alarms; /* realtime status register encoding,combined */ u8 chassis; /* Chassis status */ u8 chassis_clear; /* CLR_CHS, clear chassis intrusion detection */ @@ -375,8 +372,10 @@ static ssize_t store_in_##reg (struct de u32 val; \ \ val = simple_strtoul(buf, NULL, 10); \ + mutex_lock(&data->update_lock); \ data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val)/4, 0, 255); \ w83792d_write_value(client, W83792D_REG_IN_##REG[nr], data->in_##reg[nr]); \ + mutex_unlock(&data->update_lock); \ \ return count; \ } @@ -443,9 +442,11 @@ store_fan_min(struct device *dev, struct u32 val; val = simple_strtoul(buf, NULL, 10); + mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]); + mutex_unlock(&data->update_lock); return count; } @@ -462,7 +463,7 @@ show_fan_div(struct device *dev, struct /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan divisor. This follows the principle of - least suprise; the user doesn't expect the fan minimum to change just + least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr, @@ -478,6 +479,7 @@ store_fan_div(struct device *dev, struct u8 tmp_fan_div; /* Save fan_min */ + mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); @@ -493,6 +495,7 @@ store_fan_div(struct device *dev, struct /* Restore fan_min */ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]); + mutex_unlock(&data->update_lock); return count; } @@ -547,10 +550,11 @@ static ssize_t store_temp1(struct device s32 val; val = simple_strtol(buf, NULL, 10); - + mutex_lock(&data->update_lock); data->temp1[nr] = TEMP1_TO_REG(val); w83792d_write_value(client, W83792D_REG_TEMP1[nr], data->temp1[nr]); + mutex_unlock(&data->update_lock); return count; } @@ -580,13 +584,14 @@ static ssize_t store_temp23(struct devic s32 val; val = simple_strtol(buf, NULL, 10); - + mutex_lock(&data->update_lock); data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val); data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val); w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index], data->temp_add[nr][index]); w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1], data->temp_add[nr][index+1]); + mutex_unlock(&data->update_lock); return count; } @@ -627,7 +632,7 @@ show_pwm(struct device *dev, struct devi struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr-1])); + return sprintf(buf, "%d\n", (data->pwm[nr] & 0x0f) << 4); } static ssize_t @@ -659,14 +664,16 @@ store_pwm(struct device *dev, struct dev const char *buf, size_t count) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index - 1; + int nr = sensor_attr->index; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); - u32 val; + u8 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255) >> 4; - val = simple_strtoul(buf, NULL, 10); - data->pwm[nr] = PWM_TO_REG(val); + mutex_lock(&data->update_lock); + val |= w83792d_read_value(client, W83792D_REG_PWM[nr]) & 0xf0; + data->pwm[nr] = val; w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]); + mutex_unlock(&data->update_lock); return count; } @@ -683,6 +690,10 @@ store_pwmenable(struct device *dev, stru u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp; val = simple_strtoul(buf, NULL, 10); + if (val < 1 || val > 3) + return -EINVAL; + + mutex_lock(&data->update_lock); switch (val) { case 1: data->pwmenable[nr] = 0; /* manual mode */ @@ -693,8 +704,6 @@ store_pwmenable(struct device *dev, stru case 3: data->pwmenable[nr] = 1; /* thermal cruise/Smart Fan I */ break; - default: - return -EINVAL; } cfg1_tmp = data->pwmenable[0]; cfg2_tmp = (data->pwmenable[1]) << 2; @@ -702,14 +711,15 @@ store_pwmenable(struct device *dev, stru cfg4_tmp = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0; fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp; w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp); + mutex_unlock(&data->update_lock); return count; } static struct sensor_device_attribute sda_pwm[] = { - SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), - SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), - SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3), + SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0), + SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), + SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), }; static struct sensor_device_attribute sda_pwm_enable[] = { SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, @@ -728,7 +738,7 @@ show_pwm_mode(struct device *dev, struct struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", data->pwm_mode[nr-1]); + return sprintf(buf, "%d\n", data->pwm[nr] >> 7); } static ssize_t @@ -736,29 +746,35 @@ store_pwm_mode(struct device *dev, struc const char *buf, size_t count) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index - 1; + int nr = sensor_attr->index; struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); u32 val; - u8 pwm_mode_mask = 0; val = simple_strtoul(buf, NULL, 10); - data->pwm_mode[nr] = SENSORS_LIMIT(val, 0, 1); - pwm_mode_mask = w83792d_read_value(client, - W83792D_REG_PWM[nr]) & 0x7f; - w83792d_write_value(client, W83792D_REG_PWM[nr], - ((data->pwm_mode[nr]) << 7) | pwm_mode_mask); + if (val != 0 && val != 1) + return -EINVAL; + + mutex_lock(&data->update_lock); + data->pwm[nr] = w83792d_read_value(client, W83792D_REG_PWM[nr]); + if (val) { /* PWM mode */ + data->pwm[nr] |= 0x80; + } else { /* DC mode */ + data->pwm[nr] &= 0x7f; + } + w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]); + mutex_unlock(&data->update_lock); return count; } static struct sensor_device_attribute sda_pwm_mode[] = { SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, - show_pwm_mode, store_pwm_mode, 1), + show_pwm_mode, store_pwm_mode, 0), SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, - show_pwm_mode, store_pwm_mode, 2), + show_pwm_mode, store_pwm_mode, 1), SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, - show_pwm_mode, store_pwm_mode, 3), + show_pwm_mode, store_pwm_mode, 2), }; @@ -789,12 +805,13 @@ store_chassis_clear(struct device *dev, u8 temp1 = 0, temp2 = 0; val = simple_strtoul(buf, NULL, 10); - + mutex_lock(&data->update_lock); data->chassis_clear = SENSORS_LIMIT(val, 0 ,1); temp1 = ((data->chassis_clear) << 7) & 0x80; temp2 = w83792d_read_value(client, W83792D_REG_CHASSIS_CLR) & 0x7f; w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2); + mutex_unlock(&data->update_lock); return count; } @@ -827,10 +844,12 @@ store_thermal_cruise(struct device *dev, val = simple_strtoul(buf, NULL, 10); target_tmp = val; target_tmp = target_tmp & 0x7f; + mutex_lock(&data->update_lock); target_mask = w83792d_read_value(client, W83792D_REG_THERMAL[nr]) & 0x80; data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255); w83792d_write_value(client, W83792D_REG_THERMAL[nr], (data->thermal_cruise[nr]) | target_mask); + mutex_unlock(&data->update_lock); return count; } @@ -867,6 +886,7 @@ store_tolerance(struct device *dev, stru u8 tol_tmp, tol_mask; val = simple_strtoul(buf, NULL, 10); + mutex_lock(&data->update_lock); tol_mask = w83792d_read_value(client, W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0); tol_tmp = SENSORS_LIMIT(val, 0, 15); @@ -877,6 +897,7 @@ store_tolerance(struct device *dev, stru } w83792d_write_value(client, W83792D_REG_TOLERANCE[nr], tol_mask | tol_tmp); + mutex_unlock(&data->update_lock); return count; } @@ -915,11 +936,13 @@ store_sf2_point(struct device *dev, stru u8 mask_tmp = 0; val = simple_strtoul(buf, NULL, 10); + mutex_lock(&data->update_lock); data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127); mask_tmp = w83792d_read_value(client, W83792D_REG_POINTS[index][nr]) & 0x80; w83792d_write_value(client, W83792D_REG_POINTS[index][nr], mask_tmp|data->sf2_points[index][nr]); + mutex_unlock(&data->update_lock); return count; } @@ -979,6 +1002,7 @@ store_sf2_level(struct device *dev, stru u8 mask_tmp=0, level_tmp=0; val = simple_strtoul(buf, NULL, 10); + mutex_lock(&data->update_lock); data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15); mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr]) & ((nr==3) ? 0xf0 : 0x0f); @@ -988,6 +1012,7 @@ store_sf2_level(struct device *dev, stru level_tmp = data->sf2_levels[index][nr] << 4; } w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], level_tmp | mask_tmp); + mutex_unlock(&data->update_lock); return count; } @@ -1373,7 +1398,7 @@ static struct w83792d_data *w83792d_upda struct i2c_client *client = to_i2c_client(dev); struct w83792d_data *data = i2c_get_clientdata(client); int i, j; - u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp; + u8 reg_array_tmp[4], reg_tmp; mutex_lock(&data->update_lock); @@ -1402,10 +1427,8 @@ static struct w83792d_data *w83792d_upda data->fan_min[i] = w83792d_read_value(client, W83792D_REG_FAN_MIN[i]); /* Update the PWM/DC Value and PWM/DC flag */ - pwm_array_tmp[i] = w83792d_read_value(client, + data->pwm[i] = w83792d_read_value(client, W83792D_REG_PWM[i]); - data->pwm[i] = pwm_array_tmp[i] & 0x0f; - data->pwm_mode[i] = pwm_array_tmp[i] >> 7; } reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG); @@ -1513,7 +1536,6 @@ static void w83792d_print_debug(struct w dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]); dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]); dev_dbg(dev, "pwm[%d] is: 0x%x\n", i, data->pwm[i]); - dev_dbg(dev, "pwm_mode[%d] is: 0x%x\n", i, data->pwm_mode[i]); } dev_dbg(dev, "3 set of Temperatures: =====>\n"); for (i=0; i<3; i++) { diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index d6d4494..884320e 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -163,7 +163,7 @@ config I2C_PXA_SLAVE I2C bus. config I2C_PIIX4 - tristate "Intel PIIX4" + tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)" depends on I2C && PCI help If you say yes to this option, support will be included for the Intel @@ -172,6 +172,9 @@ config I2C_PIIX4 of Broadcom): Intel PIIX4 Intel 440MX + ATI IXP200 + ATI IXP300 + ATI IXP400 Serverworks OSB4 Serverworks CSB5 Serverworks CSB6 @@ -252,12 +255,12 @@ config I2C_POWERMAC will be called i2c-powermac. config I2C_MPC - tristate "MPC107/824x/85xx/52xx" + tristate "MPC107/824x/85xx/52xx/86xx" depends on I2C && PPC32 help If you say yes to this option, support will be included for the built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and - MPC85xx family processors. The driver may also work on 52xx + MPC85xx/MPC8641 family processors. The driver may also work on 52xx family processors, though interrupts are known not to work. This driver can also be built as a module. If so, the module @@ -273,6 +276,17 @@ config I2C_NFORCE2 This driver can also be built as a module. If so, the module will be called i2c-nforce2. +config I2C_OCORES + tristate "OpenCores I2C Controller" + depends on I2C && EXPERIMENTAL + help + If you say yes to this option, support will be included for the + OpenCores I2C controller. For details see + http://www.opencores.org/projects.cgi/web/i2c/overview + + This driver can also be built as a module. If so, the module + will be called i2c-ocores. + config I2C_PARPORT tristate "Parallel port adapter" depends on I2C && PARPORT @@ -500,6 +514,7 @@ config I2C_PCA_ISA tristate "PCA9564 on an ISA bus" depends on I2C select I2C_ALGOPCA + default n help This driver supports ISA boards using the Philips PCA 9564 Parallel bus to I2C bus controller @@ -507,6 +522,11 @@ config I2C_PCA_ISA This driver can also be built as a module. If so, the module will be called i2c-pca-isa. + This device is almost undetectable and using this driver on a + system which doesn't have this device will result in long + delays when I2C/SMBus chip drivers are loaded (e.g. at boot + time). If unsure, say N. + config I2C_MV64XXX tristate "Marvell mv64xxx I2C Controller" depends on I2C && MV64X60 && EXPERIMENTAL diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index b44831d..ac56df5 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powerm obj-$(CONFIG_I2C_MPC) += i2c-mpc.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o +obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index dfca749..3e0d04d 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1,5 +1,5 @@ /* - i801.c - Part of lm_sensors, Linux kernel modules for hardware + i2c-i801.c - Part of lm_sensors, Linux kernel modules for hardware monitoring Copyright (c) 1998 - 2002 Frodo Looijaard , Philip Edelbrock , and Mark D. Studebaker @@ -36,7 +36,7 @@ This driver supports several versions of Intel's I/O Controller Hubs (ICH). For SMBus support, they are similar to the PIIX4 and are part of Intel's '810' and other chipsets. - See the doc/busses/i2c-i801 file for details. + See the file Documentation/i2c/busses/i2c-i801 for details. I2C Block Read and Process Call are not supported. */ @@ -66,9 +66,8 @@ #define SMBAUXSTS (12 + i801_smba) /* IC #define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ /* PCI Address Constants */ -#define SMBBA 0x020 +#define SMBBAR 4 #define SMBHSTCFG 0x040 -#define SMBREV 0x008 /* Host configuration bits for SMBHSTCFG */ #define SMBHSTCFG_HST_EN 1 @@ -92,92 +91,16 @@ #define I801_I2C_BLOCK_LAST 0x38 /* unim #define I801_START 0x40 #define I801_PEC_EN 0x80 /* ICH4 only */ -/* insmod parameters */ - -/* If force_addr is set to anything different from 0, we forcibly enable - the I801 at the given address. VERY DANGEROUS! */ -static u16 force_addr; -module_param(force_addr, ushort, 0); -MODULE_PARM_DESC(force_addr, - "Forcibly enable the I801 at the given address. " - "EXTREMELY DANGEROUS!"); static int i801_transaction(void); static int i801_block_transaction(union i2c_smbus_data *data, char read_write, int command, int hwpec); -static unsigned short i801_smba; +static unsigned long i801_smba; static struct pci_driver i801_driver; static struct pci_dev *I801_dev; static int isich4; -static int i801_setup(struct pci_dev *dev) -{ - int error_return = 0; - unsigned char temp; - - /* Note: we keep on searching until we have found 'function 3' */ - if(PCI_FUNC(dev->devfn) != 3) - return -ENODEV; - - I801_dev = dev; - if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || - (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || - (dev->device == PCI_DEVICE_ID_INTEL_ESB_4)) - isich4 = 1; - else - isich4 = 0; - - /* Determine the address of the SMBus areas */ - if (force_addr) { - i801_smba = force_addr & 0xfff0; - } else { - pci_read_config_word(I801_dev, SMBBA, &i801_smba); - i801_smba &= 0xfff0; - if(i801_smba == 0) { - dev_err(&dev->dev, "SMB base address uninitialized " - "- upgrade BIOS or use force_addr=0xaddr\n"); - return -ENODEV; - } - } - - if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) { - dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n", - i801_smba); - error_return = -EBUSY; - goto END; - } - - pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); - temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ - pci_write_config_byte(I801_dev, SMBHSTCFG, temp); - - /* If force_addr is set, we program the new address here. Just to make - sure, we disable the device first. */ - if (force_addr) { - pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe); - pci_write_config_word(I801_dev, SMBBA, i801_smba); - pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01); - dev_warn(&dev->dev, "WARNING: I801 SMBus interface set to " - "new address %04x!\n", i801_smba); - } else if ((temp & 1) == 0) { - pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1); - dev_warn(&dev->dev, "enabling SMBus device\n"); - } - - if (temp & 0x02) - dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n"); - else - dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n"); - - pci_read_config_byte(I801_dev, SMBREV, &temp); - dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); - dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba); - -END: - return error_return; -} - static int i801_transaction(void) { int temp; @@ -334,8 +257,8 @@ static int i801_block_transaction(union /* We will always wait for a fraction of a second! */ timeout = 0; do { - temp = inb_p(SMBHSTSTS); msleep(1); + temp = inb_p(SMBHSTSTS); } while ((!(temp & 0x80)) && (timeout++ < MAX_TIMEOUT)); @@ -393,8 +316,8 @@ static int i801_block_transaction(union /* wait for INTR bit as advised by Intel */ timeout = 0; do { - temp = inb_p(SMBHSTSTS); msleep(1); + temp = inb_p(SMBHSTSTS); } while ((!(temp & 0x02)) && (timeout++ < MAX_TIMEOUT)); @@ -541,25 +464,76 @@ MODULE_DEVICE_TABLE (pci, i801_ids); static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) { + unsigned char temp; + int err; + + I801_dev = dev; + if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || + (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || + (dev->device == PCI_DEVICE_ID_INTEL_ESB_4)) + isich4 = 1; + else + isich4 = 0; + + err = pci_enable_device(dev); + if (err) { + dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n", + err); + goto exit; + } + + /* Determine the address of the SMBus area */ + i801_smba = pci_resource_start(dev, SMBBAR); + if (!i801_smba) { + dev_err(&dev->dev, "SMBus base address uninitialized, " + "upgrade BIOS\n"); + err = -ENODEV; + goto exit_disable; + } + + err = pci_request_region(dev, SMBBAR, i801_driver.name); + if (err) { + dev_err(&dev->dev, "Failed to request SMBus region " + "0x%lx-0x%lx\n", i801_smba, + pci_resource_end(dev, SMBBAR)); + goto exit_disable; + } - if (i801_setup(dev)) { - dev_warn(&dev->dev, - "I801 not detected, module not inserted.\n"); - return -ENODEV; + pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); + temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ + if (!(temp & SMBHSTCFG_HST_EN)) { + dev_info(&dev->dev, "Enabling SMBus device\n"); + temp |= SMBHSTCFG_HST_EN; } + pci_write_config_byte(I801_dev, SMBHSTCFG, temp); + + if (temp & SMBHSTCFG_SMB_SMI_EN) + dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); + else + dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n"); /* set up the driverfs linkage to our parent device */ i801_adapter.dev.parent = &dev->dev; snprintf(i801_adapter.name, I2C_NAME_SIZE, - "SMBus I801 adapter at %04x", i801_smba); - return i2c_add_adapter(&i801_adapter); + "SMBus I801 adapter at %04lx", i801_smba); + err = i2c_add_adapter(&i801_adapter); + if (err) { + dev_err(&dev->dev, "Failed to add SMBus adapter\n"); + goto exit_disable; + } + +exit_disable: + pci_disable_device(dev); +exit: + return err; } static void __devexit i801_remove(struct pci_dev *dev) { i2c_del_adapter(&i801_adapter); - release_region(i801_smba, (isich4 ? 16 : 8)); + pci_release_region(dev, SMBBAR); + pci_disable_device(dev); } static struct pci_driver i801_driver = { diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 2d80eb2..604b49e 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -31,6 +31,8 @@ nForce3 250Gb MCP 00E4 nForce4 MCP 0052 nForce4 MCP-04 0034 + nForce4 MCP51 0264 + nForce4 MCP55 0368 This driver supports the 2 SMBuses that are included in the MCP of the nForce2/3/4 chipsets. @@ -64,6 +66,7 @@ struct nforce2_smbus { /* * nVidia nForce2 SMBus control register definitions + * (Newer incarnations use standard BARs 4 and 5 instead) */ #define NFORCE_PCI_SMB1 0x50 #define NFORCE_PCI_SMB2 0x54 @@ -259,6 +262,8 @@ static struct pci_device_id nforce2_ids[ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) }, { 0 } }; @@ -266,19 +271,29 @@ static struct pci_device_id nforce2_ids[ MODULE_DEVICE_TABLE (pci, nforce2_ids); -static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg, - struct nforce2_smbus *smbus, char *name) +static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, + int alt_reg, struct nforce2_smbus *smbus, const char *name) { - u16 iobase; int error; - if (pci_read_config_word(dev, reg, &iobase) != PCIBIOS_SUCCESSFUL) { - dev_err(&smbus->adapter.dev, "Error reading PCI config for %s\n", name); - return -1; + smbus->base = pci_resource_start(dev, bar); + if (smbus->base) { + smbus->size = pci_resource_len(dev, bar); + } else { + /* Older incarnations of the device used non-standard BARs */ + u16 iobase; + + if (pci_read_config_word(dev, alt_reg, &iobase) + != PCIBIOS_SUCCESSFUL) { + dev_err(&dev->dev, "Error reading PCI config for %s\n", + name); + return -1; + } + + smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK; + smbus->size = 8; } - smbus->dev = dev; - smbus->base = iobase & 0xfffc; - smbus->size = 8; + smbus->dev = dev; if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) { dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n", @@ -313,12 +328,13 @@ static int __devinit nforce2_probe(struc pci_set_drvdata(dev, smbuses); /* SMBus adapter 1 */ - res1 = nforce2_probe_smb (dev, NFORCE_PCI_SMB1, &smbuses[0], "SMB1"); + res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1"); if (res1 < 0) { dev_err(&dev->dev, "Error probing SMB1.\n"); smbuses[0].base = 0; /* to have a check value */ } - res2 = nforce2_probe_smb (dev, NFORCE_PCI_SMB2, &smbuses[1], "SMB2"); + /* SMBus adapter 2 */ + res2 = nforce2_probe_smb(dev, 5, NFORCE_PCI_SMB2, &smbuses[1], "SMB2"); if (res2 < 0) { dev_err(&dev->dev, "Error probing SMB2.\n"); smbuses[1].base = 0; /* to have a check value */ diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c new file mode 100644 index 0000000..5928240 --- /dev/null +++ b/drivers/i2c/busses/i2c-ocores.c @@ -0,0 +1,341 @@ +/* + * i2c-ocores.c: I2C bus driver for OpenCores I2C controller + * (http://www.opencores.org/projects.cgi/web/i2c/overview). + * + * Peter Korsgaard + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ocores_i2c { + void __iomem *base; + int regstep; + wait_queue_head_t wait; + struct i2c_adapter adap; + struct i2c_msg *msg; + int pos; + int nmsgs; + int state; /* see STATE_ */ +}; + +/* registers */ +#define OCI2C_PRELOW 0 +#define OCI2C_PREHIGH 1 +#define OCI2C_CONTROL 2 +#define OCI2C_DATA 3 +#define OCI2C_CMD 4 /* write only */ +#define OCI2C_STATUS 4 /* read only, same address as OCI2C_CMD */ + +#define OCI2C_CTRL_IEN 0x40 +#define OCI2C_CTRL_EN 0x80 + +#define OCI2C_CMD_START 0x91 +#define OCI2C_CMD_STOP 0x41 +#define OCI2C_CMD_READ 0x21 +#define OCI2C_CMD_WRITE 0x11 +#define OCI2C_CMD_READ_ACK 0x21 +#define OCI2C_CMD_READ_NACK 0x29 +#define OCI2C_CMD_IACK 0x01 + +#define OCI2C_STAT_IF 0x01 +#define OCI2C_STAT_TIP 0x02 +#define OCI2C_STAT_ARBLOST 0x20 +#define OCI2C_STAT_BUSY 0x40 +#define OCI2C_STAT_NACK 0x80 + +#define STATE_DONE 0 +#define STATE_START 1 +#define STATE_WRITE 2 +#define STATE_READ 3 +#define STATE_ERROR 4 + +static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite8(value, i2c->base + reg * i2c->regstep); +} + +static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) +{ + return ioread8(i2c->base + reg * i2c->regstep); +} + +static void ocores_process(struct ocores_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + u8 stat = oc_getreg(i2c, OCI2C_STATUS); + + if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) { + /* stop has been sent */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + wake_up(&i2c->wait); + return; + } + + /* error? */ + if (stat & OCI2C_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return; + } + + if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) { + i2c->state = + (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + + if (stat & OCI2C_STAT_NACK) { + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return; + } + } else + msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA); + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { /* end? */ + /* send start? */ + if (!(msg->flags & I2C_M_NOSTART)) { + u8 addr = (msg->addr << 1); + + if (msg->flags & I2C_M_RD) + addr |= 1; + + i2c->state = STATE_START; + + oc_setreg(i2c, OCI2C_DATA, addr); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + return; + } else + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } else { + i2c->state = STATE_DONE; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return; + } + } + + if (i2c->state == STATE_READ) { + oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ? + OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK); + } else { + oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE); + } +} + +static irqreturn_t ocores_isr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct ocores_i2c *i2c = dev_id; + + ocores_process(i2c); + + return IRQ_HANDLED; +} + +static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct ocores_i2c *i2c = i2c_get_adapdata(adap); + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = STATE_START; + + oc_setreg(i2c, OCI2C_DATA, + (i2c->msg->addr << 1) | + ((i2c->msg->flags & I2C_M_RD) ? 1:0)); + + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + + if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || + (i2c->state == STATE_DONE), HZ)) + return (i2c->state == STATE_DONE) ? num : -EIO; + else + return -ETIMEDOUT; +} + +static void ocores_init(struct ocores_i2c *i2c, + struct ocores_i2c_platform_data *pdata) +{ + int prescale; + u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); + + /* make sure the device is disabled */ + oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); + + prescale = (pdata->clock_khz / (5*100)) - 1; + oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff); + oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8); + + /* Init the device */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN); +} + + +static u32 ocores_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm ocores_algorithm = { + .master_xfer = ocores_xfer, + .functionality = ocores_func, +}; + +static struct i2c_adapter ocores_adapter = { + .owner = THIS_MODULE, + .name = "i2c-ocores", + .class = I2C_CLASS_HWMON, + .algo = &ocores_algorithm, +}; + + +static int __devinit ocores_i2c_probe(struct platform_device *pdev) +{ + struct ocores_i2c *i2c; + struct ocores_i2c_platform_data *pdata; + struct resource *res, *res2; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res2) + return -ENODEV; + + pdata = (struct ocores_i2c_platform_data*) pdev->dev.platform_data; + if (!pdata) + return -ENODEV; + + i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + if (!request_mem_region(res->start, res->end - res->start + 1, + pdev->name)) { + dev_err(&pdev->dev, "Memory region busy\n"); + ret = -EBUSY; + goto request_mem_failed; + } + + i2c->base = ioremap(res->start, res->end - res->start + 1); + if (!i2c->base) { + dev_err(&pdev->dev, "Unable to map registers\n"); + ret = -EIO; + goto map_failed; + } + + i2c->regstep = pdata->regstep; + ocores_init(i2c, pdata); + + init_waitqueue_head(&i2c->wait); + ret = request_irq(res2->start, ocores_isr, 0, pdev->name, i2c); + if (ret) { + dev_err(&pdev->dev, "Cannot claim IRQ\n"); + goto request_irq_failed; + } + + /* hook up driver to tree */ + platform_set_drvdata(pdev, i2c); + i2c->adap = ocores_adapter; + i2c_set_adapdata(&i2c->adap, i2c); + i2c->adap.dev.parent = &pdev->dev; + + /* add i2c adapter to i2c tree */ + ret = i2c_add_adapter(&i2c->adap); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter\n"); + goto add_adapter_failed; + } + + return 0; + +add_adapter_failed: + free_irq(res2->start, i2c); +request_irq_failed: + iounmap(i2c->base); +map_failed: + release_mem_region(res->start, res->end - res->start + 1); +request_mem_failed: + kfree(i2c); + + return ret; +} + +static int __devexit ocores_i2c_remove(struct platform_device* pdev) +{ + struct ocores_i2c *i2c = platform_get_drvdata(pdev); + struct resource *res; + + /* disable i2c logic */ + oc_setreg(i2c, OCI2C_CONTROL, oc_getreg(i2c, OCI2C_CONTROL) + & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); + + /* remove adapter & data */ + i2c_del_adapter(&i2c->adap); + platform_set_drvdata(pdev, NULL); + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res) + free_irq(res->start, i2c); + + iounmap(i2c->base); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) + release_mem_region(res->start, res->end - res->start + 1); + + kfree(i2c); + + return 0; +} + +static struct platform_driver ocores_i2c_driver = { + .probe = ocores_i2c_probe, + .remove = __devexit_p(ocores_i2c_remove), + .driver = { + .owner = THIS_MODULE, + .name = "ocores-i2c", + }, +}; + +static int __init ocores_i2c_init(void) +{ + return platform_driver_register(&ocores_i2c_driver); +} + +static void __exit ocores_i2c_exit(void) +{ + platform_driver_unregister(&ocores_i2c_driver); +} + +module_init(ocores_i2c_init); +module_exit(ocores_i2c_exit); + +MODULE_AUTHOR("Peter Korsgaard "); +MODULE_DESCRIPTION("OpenCores I2C bus driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index d9c7c00..8f2f65b 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -102,13 +102,6 @@ MODULE_PARM_DESC(force_addr, "Forcibly enable the PIIX4 at the given address. " "EXTREMELY DANGEROUS!"); -/* If fix_hstcfg is set to anything different from 0, we reset one of the - registers to be a valid value. */ -static int fix_hstcfg; -module_param (fix_hstcfg, int, 0); -MODULE_PARM_DESC(fix_hstcfg, - "Fix config register. Needed on some boards (Force CPCI735)."); - static int piix4_transaction(void); static unsigned short piix4_smba; @@ -137,7 +130,7 @@ static int __devinit piix4_setup(struct /* Don't access SMBus on IBM systems which get corrupted eeproms */ if (dmi_check_system(piix4_dmi_table) && PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) { - dev_err(&PIIX4_dev->dev, "IBM Laptop detected; this module " + dev_err(&PIIX4_dev->dev, "IBM system detected; this module " "may corrupt your serial eeprom! Refusing to load " "module!\n"); return -EPERM; @@ -166,22 +159,6 @@ static int __devinit piix4_setup(struct pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); - /* Some BIOS will set up the chipset incorrectly and leave a register - in an undefined state (causing I2C to act very strangely). */ - if (temp & 0x02) { - if (fix_hstcfg) { - dev_info(&PIIX4_dev->dev, "Working around buggy BIOS " - "(I2C)\n"); - temp &= 0xfd; - pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp); - } else { - dev_info(&PIIX4_dev->dev, "Unusual config register " - "value\n"); - dev_info(&PIIX4_dev->dev, "Try using fix_hstcfg=1 if " - "you experience problems\n"); - } - } - /* If force_addr is set, we program the new address here. Just to make sure, we disable the PIIX4 first. */ if (force_addr) { @@ -214,7 +191,7 @@ static int __devinit piix4_setup(struct } } - if ((temp & 0x0E) == 8) + if (((temp & 0x0E) == 8) || ((temp & 0x0E) == 2)) dev_dbg(&PIIX4_dev->dev, "Using Interrupt 9 for SMBus.\n"); else if ((temp & 0x0E) == 0) dev_dbg(&PIIX4_dev->dev, "Using Interrupt SMI# for SMBus.\n"); @@ -413,6 +390,12 @@ static struct i2c_adapter piix4_adapter static struct pci_device_id piix4_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3), .driver_data = 3 }, + { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS), + .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4), .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5), diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 766cc96..22a3eda 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -33,7 +33,6 @@ #include #include #include #include -#include #include @@ -85,6 +84,10 @@ struct scx200_acb_iface { u8 *ptr; char needs_reset; unsigned len; + + /* PCI device info */ + struct pci_dev *pdev; + int bar; }; /* Register Definitions */ @@ -381,7 +384,7 @@ static struct i2c_algorithm scx200_acb_a static struct scx200_acb_iface *scx200_acb_list; static DECLARE_MUTEX(scx200_acb_list_mutex); -static int scx200_acb_probe(struct scx200_acb_iface *iface) +static __init int scx200_acb_probe(struct scx200_acb_iface *iface) { u8 val; @@ -417,17 +420,16 @@ static int scx200_acb_probe(struct scx20 return 0; } -static int __init scx200_acb_create(const char *text, int base, int index) +static __init struct scx200_acb_iface *scx200_create_iface(const char *text, + int index) { struct scx200_acb_iface *iface; struct i2c_adapter *adapter; - int rc; iface = kzalloc(sizeof(*iface), GFP_KERNEL); if (!iface) { printk(KERN_ERR NAME ": can't allocate memory\n"); - rc = -ENOMEM; - goto errout; + return NULL; } adapter = &iface->adapter; @@ -440,26 +442,27 @@ static int __init scx200_acb_create(con mutex_init(&iface->mutex); - if (!request_region(base, 8, adapter->name)) { - printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n", - base, base + 8-1); - rc = -EBUSY; - goto errout_free; - } - iface->base = base; + return iface; +} + +static int __init scx200_acb_create(struct scx200_acb_iface *iface) +{ + struct i2c_adapter *adapter; + int rc; + + adapter = &iface->adapter; rc = scx200_acb_probe(iface); if (rc) { printk(KERN_WARNING NAME ": probe failed\n"); - goto errout_release; + return rc; } scx200_acb_reset(iface); if (i2c_add_adapter(adapter) < 0) { printk(KERN_ERR NAME ": failed to register\n"); - rc = -ENODEV; - goto errout_release; + return -ENODEV; } down(&scx200_acb_list_mutex); @@ -468,64 +471,148 @@ static int __init scx200_acb_create(con up(&scx200_acb_list_mutex); return 0; +} - errout_release: - release_region(iface->base, 8); +static __init int scx200_create_pci(const char *text, struct pci_dev *pdev, + int bar) +{ + struct scx200_acb_iface *iface; + int rc; + + iface = scx200_create_iface(text, 0); + + if (iface == NULL) + return -ENOMEM; + + iface->pdev = pdev; + iface->bar = bar; + + pci_enable_device_bars(iface->pdev, 1 << iface->bar); + + rc = pci_request_region(iface->pdev, iface->bar, iface->adapter.name); + + if (rc != 0) { + printk(KERN_ERR NAME ": can't allocate PCI BAR %d\n", + iface->bar); + goto errout_free; + } + + iface->base = pci_resource_start(iface->pdev, iface->bar); + rc = scx200_acb_create(iface); + + if (rc == 0) + return 0; + + pci_release_region(iface->pdev, iface->bar); + pci_dev_put(iface->pdev); errout_free: kfree(iface); - errout: return rc; } -static struct pci_device_id scx200[] = { - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) }, - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) }, - { }, -}; +static int __init scx200_create_isa(const char *text, unsigned long base, + int index) +{ + struct scx200_acb_iface *iface; + int rc; + + iface = scx200_create_iface(text, index); + + if (iface == NULL) + return -ENOMEM; + + if (request_region(base, 8, iface->adapter.name) == 0) { + printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n", + base, base + 8 - 1); + rc = -EBUSY; + goto errout_free; + } + + iface->base = base; + rc = scx200_acb_create(iface); + + if (rc == 0) + return 0; -static struct pci_device_id divil_pci[] = { - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, - { } /* NULL entry */ + release_region(base, 8); + errout_free: + kfree(iface); + return rc; +} + +/* Driver data is an index into the scx200_data array that indicates + * the name and the BAR where the I/O address resource is located. ISA + * devices are flagged with a bar value of -1 */ + +static struct pci_device_id scx200_pci[] = { + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA), + .driver_data = 1 }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA), + .driver_data = 2 } }; -#define MSR_LBAR_SMB 0x5140000B +static struct { + const char *name; + int bar; +} scx200_data[] = { + { "SCx200", -1 }, + { "CS5535", 0 }, + { "CS5536", 0 } +}; -static __init int scx200_add_cs553x(void) +static __init int scx200_scan_pci(void) { - u32 low, hi; - u32 smb_base; - - /* Grab & reserve the SMB I/O range */ - rdmsr(MSR_LBAR_SMB, low, hi); + int data, dev; + int rc = -ENODEV; + struct pci_dev *pdev; + + for(dev = 0; dev < ARRAY_SIZE(scx200_pci); dev++) { + pdev = pci_get_device(scx200_pci[dev].vendor, + scx200_pci[dev].device, NULL); + + if (pdev == NULL) + continue; + + data = scx200_pci[dev].driver_data; + + /* if .bar is greater or equal to zero, this is a + * PCI device - otherwise, we assume + that the ports are ISA based + */ + + if (scx200_data[data].bar >= 0) + rc = scx200_create_pci(scx200_data[data].name, pdev, + scx200_data[data].bar); + else { + int i; + + for (i = 0; i < MAX_DEVICES; ++i) { + if (base[i] == 0) + continue; + + rc = scx200_create_isa(scx200_data[data].name, + base[i], + i); + } + } - /* Check the IO mask and whether SMB is enabled */ - if (hi != 0x0000F001) { - printk(KERN_WARNING NAME ": SMBus not enabled\n"); - return -ENODEV; + break; } - /* SMBus IO size is 8 bytes */ - smb_base = low & 0x0000FFF8; - - return scx200_acb_create("CS5535", smb_base, 0); + return rc; } static int __init scx200_acb_init(void) { - int i; - int rc = -ENODEV; + int rc; pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); - /* Verify that this really is a SCx200 processor */ - if (pci_dev_present(scx200)) { - for (i = 0; i < MAX_DEVICES; ++i) { - if (base[i] > 0) - rc = scx200_acb_create("SCx200", base[i], i); - } - } else if (pci_dev_present(divil_pci)) - rc = scx200_add_cs553x(); + rc = scx200_scan_pci(); /* If at least one bus was created, init must succeed */ if (scx200_acb_list) @@ -543,7 +630,14 @@ static void __exit scx200_acb_cleanup(vo up(&scx200_acb_list_mutex); i2c_del_adapter(&iface->adapter); - release_region(iface->base, 8); + + if (iface->pdev) { + pci_release_region(iface->pdev, iface->bar); + pci_dev_put(iface->pdev); + } + else + release_region(iface->base, 8); + kfree(iface); down(&scx200_acb_list_mutex); } diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 7aa5c38..87ee3ce 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -39,6 +39,7 @@ config SENSORS_EEPROM config SENSORS_PCF8574 tristate "Philips PCF8574 and PCF8574A" depends on I2C && EXPERIMENTAL + default n help If you say yes here you get support for Philips PCF8574 and PCF8574A chips. @@ -46,6 +47,9 @@ config SENSORS_PCF8574 This driver can also be built as a module. If so, the module will be called pcf8574. + These devices are hard to detect and rarely found on mainstream + hardware. If unsure, say N. + config SENSORS_PCA9539 tristate "Philips PCA9539 16-bit I/O port" depends on I2C && EXPERIMENTAL @@ -59,12 +63,16 @@ config SENSORS_PCA9539 config SENSORS_PCF8591 tristate "Philips PCF8591" depends on I2C && EXPERIMENTAL + default n help If you say yes here you get support for Philips PCF8591 chips. This driver can also be built as a module. If so, the module will be called pcf8591. + These devices are hard to detect and rarely found on mainstream + hardware. If unsure, say N. + config ISP1301_OMAP tristate "Philips ISP1301 with OMAP OTG" depends on I2C && ARCH_OMAP_OTG diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c index 99ab4ec..2dd0a34 100644 --- a/drivers/i2c/chips/m41t00.c +++ b/drivers/i2c/chips/m41t00.c @@ -1,11 +1,9 @@ /* - * drivers/i2c/chips/m41t00.c - * - * I2C client/driver for the ST M41T00 Real-Time Clock chip. + * I2C client/driver for the ST M41T00 family of i2c rtc chips. * * Author: Mark A. Greer * - * 2005 (c) MontaVista Software, Inc. This file is licensed under + * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -13,9 +11,6 @@ /* * This i2c client/driver wedges between the drivers/char/genrtc.c RTC * interface and the SMBus interface of the i2c subsystem. - * It would be more efficient to use i2c msgs/i2c_transfer directly but, as - * recommened in .../Documentation/i2c/writing-clients section - * "Sending and receiving", using SMBus level communication is preferred. */ #include @@ -24,56 +19,110 @@ #include #include #include #include -#include #include - +#include +#include #include #include -#define M41T00_DRV_NAME "m41t00" - -static DEFINE_MUTEX(m41t00_mutex); - static struct i2c_driver m41t00_driver; static struct i2c_client *save_client; static unsigned short ignore[] = { I2C_CLIENT_END }; -static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END }; +static unsigned short normal_addr[] = { I2C_CLIENT_END, I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_addr, - .probe = ignore, - .ignore = ignore, + .normal_i2c = normal_addr, + .probe = ignore, + .ignore = ignore, +}; + +struct m41t00_chip_info { + u8 type; + char *name; + u8 read_limit; + u8 sec; /* Offsets for chip regs */ + u8 min; + u8 hour; + u8 day; + u8 mon; + u8 year; + u8 alarm_mon; + u8 alarm_hour; + u8 sqw; + u8 sqw_freq; }; +static struct m41t00_chip_info m41t00_chip_info_tbl[] = { + { + .type = M41T00_TYPE_M41T00, + .name = "m41t00", + .read_limit = 5, + .sec = 0, + .min = 1, + .hour = 2, + .day = 4, + .mon = 5, + .year = 6, + }, + { + .type = M41T00_TYPE_M41T81, + .name = "m41t81", + .read_limit = 1, + .sec = 1, + .min = 2, + .hour = 3, + .day = 5, + .mon = 6, + .year = 7, + .alarm_mon = 0xa, + .alarm_hour = 0xc, + .sqw = 0x13, + }, + { + .type = M41T00_TYPE_M41T85, + .name = "m41t85", + .read_limit = 1, + .sec = 1, + .min = 2, + .hour = 3, + .day = 5, + .mon = 6, + .year = 7, + .alarm_mon = 0xa, + .alarm_hour = 0xc, + .sqw = 0x13, + }, +}; +static struct m41t00_chip_info *m41t00_chip; + ulong m41t00_get_rtc_time(void) { - s32 sec, min, hour, day, mon, year; - s32 sec1, min1, hour1, day1, mon1, year1; - ulong limit = 10; + s32 sec, min, hour, day, mon, year; + s32 sec1, min1, hour1, day1, mon1, year1; + u8 reads = 0; + u8 buf[8], msgbuf[1] = { 0 }; /* offset into rtc's regs */ + struct i2c_msg msgs[] = { + { + .addr = save_client->addr, + .flags = 0, + .len = 1, + .buf = msgbuf, + }, + { + .addr = save_client->addr, + .flags = I2C_M_RD, + .len = 8, + .buf = buf, + }, + }; sec = min = hour = day = mon = year = 0; - sec1 = min1 = hour1 = day1 = mon1 = year1 = 0; - mutex_lock(&m41t00_mutex); do { - if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0) - && ((min = i2c_smbus_read_byte_data(save_client, 1)) - >= 0) - && ((hour = i2c_smbus_read_byte_data(save_client, 2)) - >= 0) - && ((day = i2c_smbus_read_byte_data(save_client, 4)) - >= 0) - && ((mon = i2c_smbus_read_byte_data(save_client, 5)) - >= 0) - && ((year = i2c_smbus_read_byte_data(save_client, 6)) - >= 0) - && ((sec == sec1) && (min == min1) && (hour == hour1) - && (day == day1) && (mon == mon1) - && (year == year1))) - - break; + if (i2c_transfer(save_client->adapter, msgs, 2) < 0) + goto read_err; sec1 = sec; min1 = min; @@ -81,69 +130,88 @@ m41t00_get_rtc_time(void) day1 = day; mon1 = mon; year1 = year; - } while (--limit > 0); - mutex_unlock(&m41t00_mutex); - - if (limit == 0) { - dev_warn(&save_client->dev, - "m41t00: can't read rtc chip\n"); - sec = min = hour = day = mon = year = 0; - } - - sec &= 0x7f; - min &= 0x7f; - hour &= 0x3f; - day &= 0x3f; - mon &= 0x1f; - year &= 0xff; - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); + sec = buf[m41t00_chip->sec] & 0x7f; + min = buf[m41t00_chip->min] & 0x7f; + hour = buf[m41t00_chip->hour] & 0x3f; + day = buf[m41t00_chip->day] & 0x3f; + mon = buf[m41t00_chip->mon] & 0x1f; + year = buf[m41t00_chip->year]; + } while ((++reads < m41t00_chip->read_limit) && ((sec != sec1) + || (min != min1) || (hour != hour1) || (day != day1) + || (mon != mon1) || (year != year1))); + + if ((m41t00_chip->read_limit > 1) && ((sec != sec1) || (min != min1) + || (hour != hour1) || (day != day1) || (mon != mon1) + || (year != year1))) + goto read_err; + + sec = BCD2BIN(sec); + min = BCD2BIN(min); + hour = BCD2BIN(hour); + day = BCD2BIN(day); + mon = BCD2BIN(mon); + year = BCD2BIN(year); year += 1900; if (year < 1970) year += 100; return mktime(year, mon, day, hour, min, sec); + +read_err: + dev_err(&save_client->dev, "m41t00_get_rtc_time: Read error\n"); + return 0; } +EXPORT_SYMBOL_GPL(m41t00_get_rtc_time); static void m41t00_set(void *arg) { struct rtc_time tm; - ulong nowtime = *(ulong *)arg; + int nowtime = *(int *)arg; + s32 sec, min, hour, day, mon, year; + u8 wbuf[9], *buf = &wbuf[1], msgbuf[1] = { 0 }; + struct i2c_msg msgs[] = { + { + .addr = save_client->addr, + .flags = 0, + .len = 1, + .buf = msgbuf, + }, + { + .addr = save_client->addr, + .flags = I2C_M_RD, + .len = 8, + .buf = buf, + }, + }; to_tm(nowtime, &tm); tm.tm_year = (tm.tm_year - 1900) % 100; - BIN_TO_BCD(tm.tm_sec); - BIN_TO_BCD(tm.tm_min); - BIN_TO_BCD(tm.tm_hour); - BIN_TO_BCD(tm.tm_mon); - BIN_TO_BCD(tm.tm_mday); - BIN_TO_BCD(tm.tm_year); - - mutex_lock(&m41t00_mutex); - if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0) - || (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff) - < 0)) - - dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n"); - - mutex_unlock(&m41t00_mutex); - return; + sec = BIN2BCD(tm.tm_sec); + min = BIN2BCD(tm.tm_min); + hour = BIN2BCD(tm.tm_hour); + day = BIN2BCD(tm.tm_mday); + mon = BIN2BCD(tm.tm_mon); + year = BIN2BCD(tm.tm_year); + + /* Read reg values into buf[0..7]/wbuf[1..8] */ + if (i2c_transfer(save_client->adapter, msgs, 2) < 0) { + dev_err(&save_client->dev, "m41t00_set: Read error\n"); + return; + } + + wbuf[0] = 0; /* offset into rtc's regs */ + buf[m41t00_chip->sec] = (buf[m41t00_chip->sec] & ~0x7f) | (sec & 0x7f); + buf[m41t00_chip->min] = (buf[m41t00_chip->min] & ~0x7f) | (min & 0x7f); + buf[m41t00_chip->hour] = (buf[m41t00_chip->hour] & ~0x3f) | (hour& 0x3f); + buf[m41t00_chip->day] = (buf[m41t00_chip->day] & ~0x3f) | (day & 0x3f); + buf[m41t00_chip->mon] = (buf[m41t00_chip->mon] & ~0x1f) | (mon & 0x1f); + + if (i2c_master_send(save_client, wbuf, 9) < 0) + dev_err(&save_client->dev, "m41t00_set: Write error\n"); } static ulong new_time; @@ -162,6 +230,48 @@ m41t00_set_rtc_time(ulong nowtime) return 0; } +EXPORT_SYMBOL_GPL(m41t00_set_rtc_time); + +/* + ***************************************************************************** + * + * platform_data Driver Interface + * + ***************************************************************************** + */ +static int __init +m41t00_platform_probe(struct platform_device *pdev) +{ + struct m41t00_platform_data *pdata; + int i; + + if (pdev && (pdata = pdev->dev.platform_data)) { + normal_addr[0] = pdata->i2c_addr; + + for (i=0; itype) { + m41t00_chip = &m41t00_chip_info_tbl[i]; + m41t00_chip->sqw_freq = pdata->sqw_freq; + return 0; + } + } + return -ENODEV; +} + +static int __exit +m41t00_platform_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver m41t00_platform_driver = { + .probe = m41t00_platform_probe, + .remove = m41t00_platform_remove, + .driver = { + .owner = THIS_MODULE, + .name = M41T00_DRV_NAME, + }, +}; /* ***************************************************************************** @@ -176,23 +286,71 @@ m41t00_probe(struct i2c_adapter *adap, i struct i2c_client *client; int rc; + if (!i2c_check_functionality(adap, I2C_FUNC_I2C + | I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); if (!client) return -ENOMEM; - strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE); + strlcpy(client->name, m41t00_chip->name, I2C_NAME_SIZE); client->addr = addr; client->adapter = adap; client->driver = &m41t00_driver; - if ((rc = i2c_attach_client(client)) != 0) { - kfree(client); - return rc; + if ((rc = i2c_attach_client(client))) + goto attach_err; + + if (m41t00_chip->type != M41T00_TYPE_M41T00) { + /* If asked, disable SQW, set SQW frequency & re-enable */ + if (m41t00_chip->sqw_freq) + if (((rc = i2c_smbus_read_byte_data(client, + m41t00_chip->alarm_mon)) < 0) + || ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->alarm_mon, rc & ~0x40)) <0) + || ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->sqw, + m41t00_chip->sqw_freq)) < 0) + || ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->alarm_mon, rc | 0x40)) <0)) + goto sqw_err; + + /* Make sure HT (Halt Update) bit is cleared */ + if ((rc = i2c_smbus_read_byte_data(client, + m41t00_chip->alarm_hour)) < 0) + goto ht_err; + + if (rc & 0x40) + if ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->alarm_hour, rc & ~0x40))<0) + goto ht_err; } - m41t00_wq = create_singlethread_workqueue("m41t00"); + /* Make sure ST (stop) bit is cleared */ + if ((rc = i2c_smbus_read_byte_data(client, m41t00_chip->sec)) < 0) + goto st_err; + + if (rc & 0x80) + if ((rc = i2c_smbus_write_byte_data(client, m41t00_chip->sec, + rc & ~0x80)) < 0) + goto st_err; + + m41t00_wq = create_singlethread_workqueue(m41t00_chip->name); save_client = client; return 0; + +st_err: + dev_err(&client->dev, "m41t00_probe: Can't clear ST bit\n"); + goto attach_err; +ht_err: + dev_err(&client->dev, "m41t00_probe: Can't clear HT bit\n"); + goto attach_err; +sqw_err: + dev_err(&client->dev, "m41t00_probe: Can't set SQW Frequency\n"); +attach_err: + kfree(client); + return rc; } static int @@ -204,7 +362,7 @@ m41t00_attach(struct i2c_adapter *adap) static int m41t00_detach(struct i2c_client *client) { - int rc; + int rc; if ((rc = i2c_detach_client(client)) == 0) { kfree(client); @@ -225,14 +383,18 @@ static struct i2c_driver m41t00_driver = static int __init m41t00_init(void) { - return i2c_add_driver(&m41t00_driver); + int rc; + + if (!(rc = platform_driver_register(&m41t00_platform_driver))) + rc = i2c_add_driver(&m41t00_driver); + return rc; } static void __exit m41t00_exit(void) { i2c_del_driver(&m41t00_driver); - return; + platform_driver_unregister(&m41t00_platform_driver); } module_init(m41t00_init); diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 45e2cdf..a45155f 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -916,7 +916,7 @@ s32 i2c_smbus_write_word_data(struct i2c } s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, - u8 length, u8 *values) + u8 length, const u8 *values) { union i2c_smbus_data data; @@ -944,7 +944,7 @@ s32 i2c_smbus_read_i2c_block_data(struct } s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, - u8 length, u8 *values) + u8 length, const u8 *values) { union i2c_smbus_data data; diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index ed7eed3..58ccddd 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -426,10 +426,7 @@ static int i2cdev_attach_adapter(struct /* register this i2c device with the driver core */ i2c_dev->adap = adap; - if (adap->dev.parent == &platform_bus) - dev = &adap->dev; - else - dev = adap->dev.parent; + dev = &adap->dev; i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL, MKDEV(I2C_MAJOR, i2c_dev->minor), dev, "i2c-%d", i2c_dev->minor); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index b4a41d6..99fa424 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -395,7 +395,8 @@ static int cdrom_log_sense(ide_drive_t * * we cannot reliably check if drive can auto-close */ if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24) - log = 0; + break; + log = 1; break; case UNIT_ATTENTION: /* @@ -417,6 +418,11 @@ void cdrom_analyze_sense_data(ide_drive_ struct request *failed_command, struct request_sense *sense) { + unsigned long sector; + unsigned long bio_sectors; + unsigned long valid; + struct cdrom_info *info = drive->driver_data; + if (!cdrom_log_sense(drive, failed_command, sense)) return; @@ -429,6 +435,37 @@ void cdrom_analyze_sense_data(ide_drive_ if (sense->sense_key == 0x05 && sense->asc == 0x24) return; + if (sense->error_code == 0x70) { /* Current Error */ + switch(sense->sense_key) { + case MEDIUM_ERROR: + case VOLUME_OVERFLOW: + case ILLEGAL_REQUEST: + if (!sense->valid) + break; + if (failed_command == NULL || + !blk_fs_request(failed_command)) + break; + sector = (sense->information[0] << 24) | + (sense->information[1] << 16) | + (sense->information[2] << 8) | + (sense->information[3]); + + bio_sectors = bio_sectors(failed_command->bio); + if (bio_sectors < 4) + bio_sectors = 4; + if (drive->queue->hardsect_size == 2048) + sector <<= 2; /* Device sector size is 2K */ + sector &= ~(bio_sectors -1); + valid = (sector - failed_command->sector) << 9; + + if (valid < 0) + valid = 0; + if (sector < get_capacity(info->disk) && + drive->probed_capacity - sector < 4 * 75) { + set_capacity(info->disk, sector); + } + } + } #if VERBOSE_IDE_CD_ERRORS { int i; @@ -609,17 +646,23 @@ static void cdrom_end_request (ide_drive sense = failed->sense; failed->sense_len = rq->sense_len; } - + cdrom_analyze_sense_data(drive, failed, sense); /* * now end failed request */ - spin_lock_irqsave(&ide_lock, flags); - end_that_request_chunk(failed, 0, failed->data_len); - end_that_request_last(failed, 0); - spin_unlock_irqrestore(&ide_lock, flags); - } - - cdrom_analyze_sense_data(drive, failed, sense); + if (blk_fs_request(failed)) { + if (ide_end_dequeued_request(drive, failed, 0, + failed->hard_nr_sectors)) + BUG(); + } else { + spin_lock_irqsave(&ide_lock, flags); + end_that_request_chunk(failed, 0, + failed->data_len); + end_that_request_last(failed, 0); + spin_unlock_irqrestore(&ide_lock, flags); + } + } else + cdrom_analyze_sense_data(drive, NULL, sense); } if (!rq->current_nr_sectors && blk_fs_request(rq)) @@ -633,6 +676,13 @@ static void cdrom_end_request (ide_drive ide_end_request(drive, uptodate, nsectors); } +static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat) +{ + if (stat & 0x80) + return; + ide_dump_status(drive, msg, stat); +} + /* Returns 0 if the request should be continued. Returns 1 if the request was ended. */ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) @@ -761,16 +811,16 @@ static int cdrom_decode_status(ide_drive sense_key == DATA_PROTECT) { /* No point in retrying after an illegal request or data protect error.*/ - ide_dump_status (drive, "command error", stat); + ide_dump_status_no_sense (drive, "command error", stat); do_end_request = 1; } else if (sense_key == MEDIUM_ERROR) { /* No point in re-trying a zillion times on a bad * sector... If we got here the error is not correctable */ - ide_dump_status (drive, "media error (bad sector)", stat); + ide_dump_status_no_sense (drive, "media error (bad sector)", stat); do_end_request = 1; } else if (sense_key == BLANK_CHECK) { /* Disk appears blank ?? */ - ide_dump_status (drive, "media error (blank)", stat); + ide_dump_status_no_sense (drive, "media error (blank)", stat); do_end_request = 1; } else if ((err & ~ABRT_ERR) != 0) { /* Go to the default handler @@ -782,13 +832,27 @@ static int cdrom_decode_status(ide_drive do_end_request = 1; } - if (do_end_request) - cdrom_end_request(drive, 0); - - /* If we got a CHECK_CONDITION status, - queue a request sense command. */ - if ((stat & ERR_STAT) != 0) - cdrom_queue_request_sense(drive, NULL, NULL); + /* End a request through request sense analysis when we have + sense data. We need this in order to perform end of media + processing */ + + if (do_end_request) { + if (stat & ERR_STAT) { + unsigned long flags; + spin_lock_irqsave(&ide_lock, flags); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + spin_unlock_irqrestore(&ide_lock, flags); + + cdrom_queue_request_sense(drive, rq->sense, rq); + } else + cdrom_end_request(drive, 0); + } else { + /* If we got a CHECK_CONDITION status, + queue a request sense command. */ + if (stat & ERR_STAT) + cdrom_queue_request_sense(drive, NULL, NULL); + } } else { blk_dump_rq_flags(rq, "ide-cd: bad rq"); cdrom_end_request(drive, 0); @@ -1451,9 +1515,12 @@ static ide_startstop_t cdrom_pc_intr (id } else { confused: printk (KERN_ERR "%s: cdrom_pc_intr: The drive " - "appears confused (ireason = 0x%02x)\n", + "appears confused (ireason = 0x%02x). " + "Trying to recover by ending request.\n", drive->name, ireason); rq->flags |= REQ_FAILED; + cdrom_end_request(drive, 0); + return ide_stopped; } /* Now we wait for another interrupt. */ @@ -1488,8 +1555,7 @@ static ide_startstop_t cdrom_do_packet_c } -static -int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) +static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) { struct request_sense sense; int retries = 10; @@ -1722,8 +1788,7 @@ static ide_startstop_t cdrom_newpc_intr( } } - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL); return ide_started; @@ -2218,6 +2283,9 @@ static int cdrom_read_toc(ide_drive_t *d toc->capacity = 0x1fffff; set_capacity(info->disk, toc->capacity * sectors_per_frame); + /* Save a private copy of te TOC capacity for error handling */ + drive->probed_capacity = toc->capacity * sectors_per_frame; + blk_queue_hardsect_size(drive->queue, sectors_per_frame << SECTOR_BITS); @@ -2340,6 +2408,7 @@ #endif /* not STANDARD_ATAPI */ if (!stat && (last_written > toc->capacity)) { toc->capacity = last_written; set_capacity(info->disk, toc->capacity * sectors_per_frame); + drive->probed_capacity = toc->capacity * sectors_per_frame; } /* Remember that we've read this stuff. */ @@ -2696,14 +2765,11 @@ int ide_cdrom_drive_status (struct cdrom * any other way to detect this... */ if (sense.sense_key == NOT_READY) { - if (sense.asc == 0x3a) { - if (sense.ascq == 1) - return CDS_NO_DISC; - else if (sense.ascq == 0 || sense.ascq == 2) - return CDS_TRAY_OPEN; - } + if (sense.asc == 0x3a && sense.ascq == 1) + return CDS_NO_DISC; + else + return CDS_TRAY_OPEN; } - return CDS_DRIVE_NOT_READY; } diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index a5017de..f033d73 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -37,7 +37,7 @@ * Version 1.15 convert all calls to ide_raw_taskfile * since args will return register content. * Version 1.16 added suspend-resume-checkpower - * Version 1.17 do flush on standy, do flush on ATA < ATA6 + * Version 1.17 do flush on standby, do flush on ATA < ATA6 * fix wcache setup. */ diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index c481be8..783a247 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -206,8 +206,7 @@ int ide_build_sglist(ide_drive_t *drive, ide_hwif_t *hwif = HWIF(drive); struct scatterlist *sg = hwif->sg_table; - if ((rq->flags & REQ_DRIVE_TASKFILE) && rq->nr_sectors > 256) - BUG(); + BUG_ON((rq->flags & REQ_DRIVE_TASKFILE) && rq->nr_sectors > 256); ide_map_sg(drive, rq); @@ -947,8 +946,7 @@ void ide_setup_dma (ide_hwif_t *hwif, un } printk("\n"); - if (!(hwif->dma_master)) - BUG(); + BUG_ON(!hwif->dma_master); } EXPORT_SYMBOL_GPL(ide_setup_dma); diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index a53e3ce..4656587 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -898,8 +898,7 @@ static ide_startstop_t idefloppy_pc_intr "to send us more data than expected " "- discarding data\n"); idefloppy_discard_data(drive,bcount.all); - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, @@ -932,8 +931,7 @@ static ide_startstop_t idefloppy_pc_intr pc->actually_transferred += bcount.all; pc->current_position += bcount.all; - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ return ide_started; } @@ -960,8 +958,7 @@ static ide_startstop_t idefloppy_transfe "issuing a packet command\n"); return ide_do_reset(drive); } - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); /* Set the interrupt routine */ ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Send the actual packet */ @@ -1017,8 +1014,7 @@ static ide_startstop_t idefloppy_transfe * 40 and 50msec work well. idefloppy_pc_intr will not be actually * used until after the packet is moved in about 50 msec. */ - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &idefloppy_pc_intr, /* service routine for packet command */ floppy->ticks, /* wait this long before "failing" */ @@ -1288,7 +1284,7 @@ static ide_startstop_t idefloppy_do_requ debug_log(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n", rq->rq_status, - rq->rq_disk ? rq->rq_disk->disk_name ? "?", + rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->flags, rq->errors); debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, " "current_nr_sectors: %d\n", (long)rq->sector, diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index c01615d..935cb25 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -142,38 +142,41 @@ enum { static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error) { + struct request_pm_state *pm = rq->end_io_data; + if (drive->media != ide_disk) return; - switch (rq->pm->pm_step) { + switch (pm->pm_step) { case ide_pm_flush_cache: /* Suspend step 1 (flush cache) complete */ - if (rq->pm->pm_state == PM_EVENT_FREEZE) - rq->pm->pm_step = ide_pm_state_completed; + if (pm->pm_state == PM_EVENT_FREEZE) + pm->pm_step = ide_pm_state_completed; else - rq->pm->pm_step = idedisk_pm_standby; + pm->pm_step = idedisk_pm_standby; break; case idedisk_pm_standby: /* Suspend step 2 (standby) complete */ - rq->pm->pm_step = ide_pm_state_completed; + pm->pm_step = ide_pm_state_completed; break; case idedisk_pm_idle: /* Resume step 1 (idle) complete */ - rq->pm->pm_step = ide_pm_restore_dma; + pm->pm_step = ide_pm_restore_dma; break; } } static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) { + struct request_pm_state *pm = rq->end_io_data; ide_task_t *args = rq->special; memset(args, 0, sizeof(*args)); if (drive->media != ide_disk) { /* skip idedisk_pm_idle for ATAPI devices */ - if (rq->pm->pm_step == idedisk_pm_idle) - rq->pm->pm_step = ide_pm_restore_dma; + if (pm->pm_step == idedisk_pm_idle) + pm->pm_step = ide_pm_restore_dma; } - switch (rq->pm->pm_step) { + switch (pm->pm_step) { case ide_pm_flush_cache: /* Suspend step 1 (flush cache) */ if (drive->media != ide_disk) break; @@ -215,11 +218,68 @@ static ide_startstop_t ide_start_power_s drive->hwif->ide_dma_check(drive); break; } - rq->pm->pm_step = ide_pm_state_completed; + pm->pm_step = ide_pm_state_completed; return ide_stopped; } /** + * ide_end_dequeued_request - complete an IDE I/O + * @drive: IDE device for the I/O + * @uptodate: + * @nr_sectors: number of sectors completed + * + * Complete an I/O that is no longer on the request queue. This + * typically occurs when we pull the request and issue a REQUEST_SENSE. + * We must still finish the old request but we must not tamper with the + * queue in the meantime. + * + * NOTE: This path does not handle barrier, but barrier is not supported + * on ide-cd anyway. + */ + +int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, + int uptodate, int nr_sectors) +{ + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&ide_lock, flags); + + BUG_ON(!(rq->flags & REQ_STARTED)); + + /* + * if failfast is set on a request, override number of sectors and + * complete the whole request right now + */ + if (blk_noretry_request(rq) && end_io_error(uptodate)) + nr_sectors = rq->hard_nr_sectors; + + if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors) + rq->errors = -EIO; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->ide_dma_on(drive); + } + + if (!end_that_request_first(rq, uptodate, nr_sectors)) { + add_disk_randomness(rq->rq_disk); + if (blk_rq_tagged(rq)) + blk_queue_end_tag(drive->queue, rq); + end_that_request_last(rq, uptodate); + ret = 0; + } + spin_unlock_irqrestore(&ide_lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(ide_end_dequeued_request); + + +/** * ide_complete_pm_request - end the current Power Management request * @drive: target drive * @rq: request @@ -362,12 +422,13 @@ void ide_end_drive_cmd (ide_drive_t *dri } } } else if (blk_pm_request(rq)) { + struct request_pm_state *pm = rq->end_io_data; #ifdef DEBUG_PM printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n", drive->name, rq->pm->pm_step, stat, err); #endif ide_complete_power_step(drive, rq, stat, err); - if (rq->pm->pm_step == ide_pm_state_completed) + if (pm->pm_step == ide_pm_state_completed) ide_complete_pm_request(drive, rq); return; } @@ -871,6 +932,39 @@ #endif return ide_stopped; } +static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) +{ + struct request_pm_state *pm = rq->end_io_data; + + if (blk_pm_suspend_request(rq) && + pm->pm_step == ide_pm_state_start_suspend) + /* Mark drive blocked when starting the suspend sequence. */ + drive->blocked = 1; + else if (blk_pm_resume_request(rq) && + pm->pm_step == ide_pm_state_start_resume) { + /* + * The first thing we do on wakeup is to wait for BSY bit to + * go away (with a looong timeout) as a drive on this hwif may + * just be POSTing itself. + * We do that before even selecting as the "other" device on + * the bus may be broken enough to walk on our toes at this + * point. + */ + int rc; +#ifdef DEBUG_PM + printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); +#endif + rc = ide_wait_not_busy(HWIF(drive), 35000); + if (rc) + printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); + SELECT_DRIVE(drive); + HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); + rc = ide_wait_not_busy(HWIF(drive), 100000); + if (rc) + printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); + } +} + /** * start_request - start of I/O and command issuing for IDE * @@ -909,33 +1003,8 @@ #endif if (block == 0 && drive->remap_0_to_1 == 1) block = 1; /* redirect MBR access to EZ-Drive partn table */ - if (blk_pm_suspend_request(rq) && - rq->pm->pm_step == ide_pm_state_start_suspend) - /* Mark drive blocked when starting the suspend sequence. */ - drive->blocked = 1; - else if (blk_pm_resume_request(rq) && - rq->pm->pm_step == ide_pm_state_start_resume) { - /* - * The first thing we do on wakeup is to wait for BSY bit to - * go away (with a looong timeout) as a drive on this hwif may - * just be POSTing itself. - * We do that before even selecting as the "other" device on - * the bus may be broken enough to walk on our toes at this - * point. - */ - int rc; -#ifdef DEBUG_PM - printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); -#endif - rc = ide_wait_not_busy(HWIF(drive), 35000); - if (rc) - printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); - SELECT_DRIVE(drive); - HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); - rc = ide_wait_not_busy(HWIF(drive), 10000); - if (rc) - printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); - } + if (blk_pm_request(rq)) + ide_check_pm_state(drive, rq); SELECT_DRIVE(drive); if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { @@ -950,13 +1019,14 @@ #endif else if (rq->flags & REQ_DRIVE_TASKFILE) return execute_drive_cmd(drive, rq); else if (blk_pm_request(rq)) { + struct request_pm_state *pm = rq->end_io_data; #ifdef DEBUG_PM printk("%s: start_power_step(step: %d)\n", drive->name, rq->pm->pm_step); #endif startstop = ide_start_power_step(drive, rq); if (startstop == ide_stopped && - rq->pm->pm_step == ide_pm_state_completed) + pm->pm_step == ide_pm_state_completed) ide_complete_pm_request(drive, rq); return startstop; } @@ -1595,7 +1665,7 @@ #endif /* CONFIG_BLK_DEV_IDEPCI */ * Initialize a request before we fill it in and send it down to * ide_do_drive_cmd. Commands must be set up by this function. Right * now it doesn't do a lot, but if that changes abusers will have a - * nasty suprise. + * nasty surprise. */ void ide_init_drive_cmd (struct request *rq) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index b72dde7..97a49e7 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -939,8 +939,7 @@ void ide_execute_command(ide_drive_t *dr spin_lock_irqsave(&ide_lock, flags); - if(hwgroup->handler) - BUG(); + BUG_ON(hwgroup->handler); hwgroup->handler = handler; hwgroup->expiry = expiry; hwgroup->timer.expires = jiffies + timeout; @@ -981,8 +980,7 @@ static ide_startstop_t atapi_reset_pollf printk("%s: ATAPI reset complete\n", drive->name); } else { if (time_before(jiffies, hwgroup->poll_timeout)) { - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); /* continue polling */ return ide_started; @@ -1021,8 +1019,7 @@ static ide_startstop_t reset_pollfunc (i if (!OK_STAT(tmp = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) { if (time_before(jiffies, hwgroup->poll_timeout)) { - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); /* continue polling */ return ide_started; @@ -1138,8 +1135,7 @@ static ide_startstop_t do_reset1 (ide_dr hwgroup = HWGROUP(drive); /* We must not reset with running handlers */ - if(hwgroup->handler != NULL) - BUG(); + BUG_ON(hwgroup->handler != NULL); /* For an ATAPI device, first try an ATAPI SRST. */ if (drive->media != ide_disk && !do_not_try_atapi) { diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 41d46db..7ddb118 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -164,8 +164,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); /* So that we remember to update this if new modes appear */ - if (mode > 4) - BUG(); + BUG_ON(mode > 4); return min(speed, speed_max[mode]); #else /* !CONFIG_BLK_DEV_IDEDMA */ return min(speed, (u8)XFER_PIO_4); @@ -486,7 +485,7 @@ static u8 ide_dump_ata_status(ide_drive_ unsigned long flags; u8 err = 0; - local_irq_set(flags); + local_irq_save(flags); printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); if (stat & BUSY_STAT) printk("Busy "); @@ -568,7 +567,7 @@ static u8 ide_dump_atapi_status(ide_driv status.all = stat; error.all = 0; - local_irq_set(flags); + local_irq_save(flags); printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); if (status.b.bsy) printk("Busy "); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 1b7b4c5..9ebf8ae 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1138,16 +1138,11 @@ #endif /* CONFIG_IDEPCI_SHARE_IRQ */ spin_unlock_irq(&ide_lock); } -#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) +#if !defined(__mc68000__) && !defined(CONFIG_APUS) printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], hwif->io_ports[IDE_DATA_OFFSET]+7, hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq); -#elif defined(__sparc__) - printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %s", hwif->name, - hwif->io_ports[IDE_DATA_OFFSET], - hwif->io_ports[IDE_DATA_OFFSET]+7, - hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq)); #else printk("%s at 0x%08lx on irq %d", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], hwif->irq); diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index f04791a..09f3a7d 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2646,21 +2646,23 @@ #endif /* IDETAPE_DEBUG_LOG */ return __idetape_kmalloc_stage(tape, 0, 0); } -static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n) +static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n) { struct idetape_bh *bh = tape->bh; int count; + int ret = 0; while (n) { #if IDETAPE_DEBUG_BUGS if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_copy_stage_from_user\n"); - return; + return 1; } #endif /* IDETAPE_DEBUG_BUGS */ count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n); - copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count); + if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count)) + ret = 1; n -= count; atomic_add(count, &bh->b_count); buf += count; @@ -2671,23 +2673,26 @@ #endif /* IDETAPE_DEBUG_BUGS */ } } tape->bh = bh; + return ret; } -static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n) +static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n) { struct idetape_bh *bh = tape->bh; int count; + int ret = 0; while (n) { #if IDETAPE_DEBUG_BUGS if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_copy_stage_to_user\n"); - return; + return 1; } #endif /* IDETAPE_DEBUG_BUGS */ count = min(tape->b_count, n); - copy_to_user(buf, tape->b_data, count); + if (copy_to_user(buf, tape->b_data, count)) + ret = 1; n -= count; tape->b_data += count; tape->b_count -= count; @@ -2700,6 +2705,7 @@ #endif /* IDETAPE_DEBUG_BUGS */ } } } + return ret; } static void idetape_init_merge_stage (idetape_tape_t *tape) @@ -3719,6 +3725,7 @@ static ssize_t idetape_chrdev_read (stru struct ide_tape_obj *tape = ide_tape_f(file); ide_drive_t *drive = tape->drive; ssize_t bytes_read,temp, actually_read = 0, rc; + ssize_t ret = 0; #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) @@ -3737,7 +3744,8 @@ #endif /* IDETAPE_DEBUG_LOG */ return (0); if (tape->merge_stage_size) { actually_read = min((unsigned int)(tape->merge_stage_size), (unsigned int)count); - idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read); + if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read)) + ret = -EFAULT; buf += actually_read; tape->merge_stage_size -= actually_read; count -= actually_read; @@ -3746,7 +3754,8 @@ #endif /* IDETAPE_DEBUG_LOG */ bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl); if (bytes_read <= 0) goto finish; - idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read); + if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read)) + ret = -EFAULT; buf += bytes_read; count -= bytes_read; actually_read += bytes_read; @@ -3756,7 +3765,8 @@ #endif /* IDETAPE_DEBUG_LOG */ if (bytes_read <= 0) goto finish; temp = min((unsigned long)count, (unsigned long)bytes_read); - idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp); + if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp)) + ret = -EFAULT; actually_read += temp; tape->merge_stage_size = bytes_read-temp; } @@ -3769,7 +3779,8 @@ #endif idetape_space_over_filemarks(drive, MTFSF, 1); return 0; } - return actually_read; + + return (ret) ? ret : actually_read; } static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, @@ -3777,7 +3788,8 @@ static ssize_t idetape_chrdev_write (str { struct ide_tape_obj *tape = ide_tape_f(file); ide_drive_t *drive = tape->drive; - ssize_t retval, actually_written = 0; + ssize_t actually_written = 0; + ssize_t ret = 0; /* The drive is write protected. */ if (tape->write_prot) @@ -3813,7 +3825,7 @@ #endif /* IDETAPE_DEBUG_BUGS */ * some drives (Seagate STT3401A) will return an error. */ if (drive->dsc_overlap) { - retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh); + ssize_t retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh); if (retval < 0) { __idetape_kfree_stage(tape->merge_stage); tape->merge_stage = NULL; @@ -3834,12 +3846,14 @@ #if IDETAPE_DEBUG_BUGS } #endif /* IDETAPE_DEBUG_BUGS */ actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count); - idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written); + if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written)) + ret = -EFAULT; buf += actually_written; tape->merge_stage_size += actually_written; count -= actually_written; if (tape->merge_stage_size == tape->stage_size) { + ssize_t retval; tape->merge_stage_size = 0; retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl); if (retval <= 0) @@ -3847,7 +3861,9 @@ #endif /* IDETAPE_DEBUG_BUGS */ } } while (count >= tape->stage_size) { - idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size); + ssize_t retval; + if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size)) + ret = -EFAULT; buf += tape->stage_size; count -= tape->stage_size; retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl); @@ -3857,10 +3873,11 @@ #endif /* IDETAPE_DEBUG_BUGS */ } if (count) { actually_written += count; - idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count); + if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count)) + ret = -EFAULT; tape->merge_stage_size += count; } - return (actually_written); + return (ret) ? ret : actually_written; } static int idetape_write_filemark (ide_drive_t *drive) diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 9233b81..a839b2a 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -196,8 +196,7 @@ ide_startstop_t set_geometry_intr (ide_d if (stat & (ERR_STAT|DRQ_STAT)) return ide_error(drive, "set_geometry_intr", stat); - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL); return ide_started; } diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h index 2fcfac6..c0864b1 100644 --- a/drivers/ide/ide-timing.h +++ b/drivers/ide/ide-timing.h @@ -220,6 +220,12 @@ static int ide_timing_compute(ide_drive_ return -EINVAL; /* + * Copy the timing from the table. + */ + + *t = *s; + +/* * If the drive is an EIDE drive, it can tell us it needs extended * PIO/MWDMA cycle timing. */ @@ -247,7 +253,7 @@ static int ide_timing_compute(ide_drive_ * Convert the timing to bus clock counts. */ - ide_timing_quantize(s, t, T, UT); + ide_timing_quantize(t, t, T, UT); /* * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 3fdab56..59fe358 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -726,6 +726,7 @@ void ide_setup_ports ( hw_regs_t *hw, { int i; + memset(hw, 0, sizeof(hw_regs_t)); for (i = 0; i < IDE_NR_PORTS; i++) { if (offsets[i] == -1) { switch(i) { @@ -1225,7 +1226,7 @@ static int generic_ide_suspend(struct de memset(&args, 0, sizeof(args)); rq.flags = REQ_PM_SUSPEND; rq.special = &args; - rq.pm = &rqpm; + rq.end_io_data = &rqpm; rqpm.pm_step = ide_pm_state_start_suspend; rqpm.pm_state = state.event; @@ -1244,7 +1245,7 @@ static int generic_ide_resume(struct dev memset(&args, 0, sizeof(args)); rq.flags = REQ_PM_RESUME; rq.special = &args; - rq.pm = &rqpm; + rq.end_io_data = &rqpm; rqpm.pm_step = ide_pm_state_start_resume; rqpm.pm_state = PM_EVENT_ON; @@ -1366,8 +1367,7 @@ #endif /* CONFIG_IDE_TASK_IOCTL */ ide_abort(drive, "drive reset"); - if(HWGROUP(drive)->handler) - BUG(); + BUG_ON(HWGROUP(drive)->handler); /* Ensure nothing gets queued after we drop the lock. Reset will clear the busy */ diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c index 2a78b79..434a94f 100644 --- a/drivers/ide/legacy/q40ide.c +++ b/drivers/ide/legacy/q40ide.c @@ -80,6 +80,7 @@ void q40_ide_setup_ports ( hw_regs_t *hw { int i; + memset(hw, 0, sizeof(hw_regs_t)); for (i = 0; i < IDE_NR_PORTS; i++) { /* BIG FAT WARNING: assumption: only DATA port is ever used in 16 bit mode */ diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index b22ee54..6e9dbf4 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -74,6 +74,7 @@ static struct amd_ide_chip { { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, AMD_UDMA_133 }, + { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 }, { 0 } }; @@ -488,7 +489,8 @@ static ide_pci_device_t amd74xx_chipsets /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"), /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"), /* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"), - /* 17 */ DECLARE_AMD_DEV("AMD5536"), + /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"), + /* 18 */ DECLARE_AMD_DEV("AMD5536"), }; static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) @@ -525,7 +527,8 @@ #endif { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl); diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 7ce5bf7..22d1754 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -370,7 +370,6 @@ chipset_is_set: if (!(speed)) { /* restore original pci-config space */ pci_write_config_dword(dev, drive_pci, drive_conf); - hwif->tuneproc(drive, 5); return 0; } @@ -415,8 +414,6 @@ static void pdc202xx_old_ide_dma_start(i if (drive->addressing == 1) { struct request *rq = HWGROUP(drive)->rq; ide_hwif_t *hwif = HWIF(drive); -// struct pci_dev *dev = hwif->pci_dev; -// unsgned long high_16 = pci_resource_start(dev, 4); unsigned long high_16 = hwif->dma_master; unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); u32 word_count = 0; @@ -436,7 +433,6 @@ static int pdc202xx_old_ide_dma_end(ide_ { if (drive->addressing == 1) { ide_hwif_t *hwif = HWIF(drive); -// unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4); unsigned long high_16 = hwif->dma_master; unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20); u8 clock = 0; @@ -453,8 +449,6 @@ static int pdc202xx_old_ide_dma_end(ide_ static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); -// struct pci_dev *dev = hwif->pci_dev; -// unsigned long high_16 = pci_resource_start(dev, 4); unsigned long high_16 = hwif->dma_master; u8 dma_stat = hwif->INB(hwif->dma_status); u8 sc1d = hwif->INB((high_16 + 0x001d)); @@ -492,12 +486,7 @@ static int pdc202xx_ide_dma_timeout(ide_ static void pdc202xx_reset_host (ide_hwif_t *hwif) { -#ifdef CONFIG_BLK_DEV_IDEDMA -// unsigned long high_16 = hwif->dma_base - (8*(hwif->channel)); unsigned long high_16 = hwif->dma_master; -#else /* !CONFIG_BLK_DEV_IDEDMA */ - unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4); -#endif /* CONFIG_BLK_DEV_IDEDMA */ u8 udma_speed_flag = hwif->INB(high_16|0x001f); hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f)); @@ -550,31 +539,6 @@ #else #endif } -/* - * Since SUN Cobalt is attempting to do this operation, I should disclose - * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date - * HOTSWAP ATA Infrastructure. - */ -static int pdc202xx_tristate (ide_drive_t * drive, int state) -{ - ide_hwif_t *hwif = HWIF(drive); -// unsigned long high_16 = hwif->dma_base - (8*(hwif->channel)); - unsigned long high_16 = hwif->dma_master; - u8 sc1f = hwif->INB(high_16|0x001f); - - if (!hwif) - return -EINVAL; - -// hwif->bus_state = state; - - if (state) { - hwif->OUTB(sc1f | 0x08, (high_16|0x001f)); - } else { - hwif->OUTB(sc1f & ~0x08, (high_16|0x001f)); - } - return 0; -} - static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev, const char *name) { if (dev->resource[PCI_ROM_RESOURCE].start) { @@ -624,10 +588,8 @@ static void __devinit init_hwif_pdc202xx hwif->tuneproc = &config_chipset_for_pio; hwif->quirkproc = &pdc202xx_quirkproc; - if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) { - hwif->busproc = &pdc202xx_tristate; + if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) hwif->resetproc = &pdc202xx_reset; - } hwif->speedproc = &pdc202xx_tune_chipset; diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index e9b83e1..7fac6f5 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -222,6 +222,8 @@ static void piix_tune_drive (ide_drive_t unsigned long flags; u16 master_data; u8 slave_data; + static DEFINE_SPINLOCK(tune_lock); + /* ISP RTC */ u8 timings[][2] = { { 0, 0 }, { 0, 0 }, @@ -230,7 +232,13 @@ static void piix_tune_drive (ide_drive_t { 2, 3 }, }; pio = ide_get_best_pio_mode(drive, pio, 5, NULL); - spin_lock_irqsave(&ide_lock, flags); + + /* + * Master vs slave is synchronized above us but the slave register is + * shared by the two hwifs so the corner case of two slave timeouts in + * parallel must be locked. + */ + spin_lock_irqsave(&tune_lock, flags); pci_read_config_word(dev, master_port, &master_data); if (is_slave) { master_data = master_data | 0x4000; @@ -250,7 +258,7 @@ static void piix_tune_drive (ide_drive_t pci_write_config_word(dev, master_port, master_data); if (is_slave) pci_write_config_byte(dev, slave_port, slave_data); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&tune_lock, flags); } /** diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 27c9eb9..e125032 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -723,6 +723,12 @@ static ide_pci_device_t sgiioc4_chipsets int ioc4_ide_attach_one(struct ioc4_driver_data *idd) { + /* PCI-RT does not bring out IDE connection. + * Do not attach to this particular IOC4. + */ + if (idd->idd_variant == IOC4_VARIANT_PCI_RT) + return 0; + return pci_init_sgiioc4(idd->idd_pdev, &sgiioc4_chipsets[idd->idd_pci_id->driver_data]); } diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index c26c8ca..fe80295 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -183,8 +183,7 @@ static void trm290_ide_dma_exec_cmd(ide_ { ide_hwif_t *hwif = HWIF(drive); - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); /* paranoia check */ ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ hwif->OUTB(command, IDE_COMMAND_REG); diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 462ed30..c11e3b2 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -694,13 +694,8 @@ static int do_ide_setup_pci_device(struc goto out; } if (noisy) -#ifdef __sparc__ - printk(KERN_INFO "%s: 100%% native mode on irq %s\n", - d->name, __irq_itoa(pciirq)); -#else printk(KERN_INFO "%s: 100%% native mode on irq %d\n", d->name, pciirq); -#endif } /* FIXME: silent failure can happen */ diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig index 39142e2..1867375 100644 --- a/drivers/ieee1394/Kconfig +++ b/drivers/ieee1394/Kconfig @@ -128,8 +128,17 @@ config IEEE1394_SBP2 1394 bus. SBP-2 devices include harddrives and DVD devices. config IEEE1394_SBP2_PHYS_DMA - bool "Enable Phys DMA support for SBP2 (Debug)" - depends on IEEE1394 && IEEE1394_SBP2 + bool "Enable replacement for physical DMA in SBP2" + depends on IEEE1394 && IEEE1394_SBP2 && EXPERIMENTAL && (X86_32 || PPC_32) + help + This builds sbp2 for use with non-OHCI host adapters which do not + support physical DMA or for when ohci1394 is run with phys_dma=0. + Physical DMA is data movement without assistence of the drivers' + interrupt handlers. This option includes the interrupt handlers + that are required in absence of this hardware feature. + + This option is buggy and currently broken on some architectures. + If unsure, say N. config IEEE1394_ETH1394 tristate "Ethernet over 1394" diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c index 1577354..586f71e 100644 --- a/drivers/ieee1394/csr1212.c +++ b/drivers/ieee1394/csr1212.c @@ -779,7 +779,7 @@ static int csr1212_append_new_cache(stru romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1); csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private); - if (csr_addr == ~0ULL) { + if (csr_addr == CSR1212_INVALID_ADDR_SPACE) { return CSR1212_ENOMEM; } if (csr_addr < CSR1212_REGISTER_SPACE_BASE) { diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h index cecd587..17ddd72 100644 --- a/drivers/ieee1394/csr1212.h +++ b/drivers/ieee1394/csr1212.h @@ -192,6 +192,7 @@ #define CSR1212_UNITS_SPACE_OFFSET (CS #define CSR1212_EXTENDED_ROM_SIZE (0x10000 * sizeof(u_int32_t)) +#define CSR1212_INVALID_ADDR_SPACE -1 /* Config ROM image structures */ struct csr1212_bus_info_block_img { diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c index 9fb2769..ca5167d 100644 --- a/drivers/ieee1394/dma.c +++ b/drivers/ieee1394/dma.c @@ -145,12 +145,12 @@ void dma_region_free(struct dma_region * /* find the scatterlist index and remaining offset corresponding to a given offset from the beginning of the buffer */ static inline int dma_region_find(struct dma_region *dma, unsigned long offset, - unsigned long *rem) + unsigned int start, unsigned long *rem) { int i; unsigned long off = offset; - for (i = 0; i < dma->n_dma_pages; i++) { + for (i = start; i < dma->n_dma_pages; i++) { if (off < sg_dma_len(&dma->sglist[i])) { *rem = off; break; @@ -170,7 +170,7 @@ dma_addr_t dma_region_offset_to_bus(stru unsigned long rem = 0; struct scatterlist *sg = - &dma->sglist[dma_region_find(dma, offset, &rem)]; + &dma->sglist[dma_region_find(dma, offset, 0, &rem)]; return sg_dma_address(sg) + rem; } @@ -178,13 +178,13 @@ void dma_region_sync_for_cpu(struct dma_ unsigned long len) { int first, last; - unsigned long rem; + unsigned long rem = 0; if (!len) len = 1; - first = dma_region_find(dma, offset, &rem); - last = dma_region_find(dma, offset + len - 1, &rem); + first = dma_region_find(dma, offset, 0, &rem); + last = dma_region_find(dma, rem + len - 1, first, &rem); pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1, dma->direction); @@ -194,13 +194,13 @@ void dma_region_sync_for_device(struct d unsigned long len) { int first, last; - unsigned long rem; + unsigned long rem = 0; if (!len) len = 1; - first = dma_region_find(dma, offset, &rem); - last = dma_region_find(dma, offset + len - 1, &rem); + first = dma_region_find(dma, offset, 0, &rem); + last = dma_region_find(dma, rem + len - 1, first, &rem); pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first], last - first + 1, dma->direction); diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 30fa0d4..2d5b57b 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -367,7 +367,7 @@ static int eth1394_probe(struct device * spin_lock_init(&node_info->pdg.lock); INIT_LIST_HEAD(&node_info->pdg.list); node_info->pdg.sz = 0; - node_info->fifo = ETHER1394_INVALID_ADDR; + node_info->fifo = CSR1212_INVALID_ADDR_SPACE; ud->device.driver_data = node_info; new_node->ud = ud; @@ -502,10 +502,8 @@ static void ether1394_reset_priv (struct /* Determine speed limit */ for (i = 0; i < host->node_count; i++) - if (max_speed > host->speed_map[NODEID_TO_NODE(host->node_id) * - 64 + i]) - max_speed = host->speed_map[NODEID_TO_NODE(host->node_id) * - 64 + i]; + if (max_speed > host->speed[i]) + max_speed = host->speed[i]; priv->bc_sspd = max_speed; /* We'll use our maxpayload as the default mtu */ @@ -568,13 +566,11 @@ static void ether1394_add_host (struct h if (!(host->config_roms & HPSB_CONFIG_ROM_ENTRY_IP1394)) return; - fifo_addr = hpsb_allocate_and_register_addrspace(ð1394_highlevel, - host, - &addr_ops, - ETHER1394_REGION_ADDR_LEN, - ETHER1394_REGION_ADDR_LEN, - -1, -1); - if (fifo_addr == ~0ULL) + fifo_addr = hpsb_allocate_and_register_addrspace( + ð1394_highlevel, host, &addr_ops, + ETHER1394_REGION_ADDR_LEN, ETHER1394_REGION_ADDR_LEN, + CSR1212_INVALID_ADDR_SPACE, CSR1212_INVALID_ADDR_SPACE); + if (fifo_addr == CSR1212_INVALID_ADDR_SPACE) goto out; /* We should really have our own alloc_hpsbdev() function in @@ -774,7 +770,7 @@ #endif default: ETH1394_PRINT(KERN_DEBUG, dev->name, "unable to resolve type %04x addresses.\n", - eth->h_proto); + ntohs(eth->h_proto)); break; } @@ -796,9 +792,8 @@ static int ether1394_header_cache(struct (16 - ETH1394_HLEN)); struct net_device *dev = neigh->dev; - if (type == __constant_htons(ETH_P_802_3)) { + if (type == htons(ETH_P_802_3)) return -1; - } eth->h_proto = type; memcpy(eth->h_dest, neigh->ha, dev->addr_len); @@ -887,7 +882,7 @@ static inline u16 ether1394_parse_encap( /* If this is an ARP packet, convert it. First, we want to make * use of some of the fields, since they tell us a little bit * about the sending machine. */ - if (ether_type == __constant_htons (ETH_P_ARP)) { + if (ether_type == htons(ETH_P_ARP)) { struct eth1394_arp *arp1394 = (struct eth1394_arp*)skb->data; struct arphdr *arp = (struct arphdr *)skb->data; unsigned char *arp_ptr = (unsigned char *)(arp + 1); @@ -935,7 +930,7 @@ static inline u16 ether1394_parse_encap( *(u32*)arp_ptr = arp1394->sip; /* move sender IP addr */ arp_ptr += arp->ar_pln; /* skip over sender IP addr */ - if (arp->ar_op == 1) + if (arp->ar_op == htons(ARPOP_REQUEST)) /* just set ARP req target unique ID to 0 */ *((u64*)arp_ptr) = 0; else @@ -943,8 +938,8 @@ static inline u16 ether1394_parse_encap( } /* Now add the ethernet header. */ - if (dev->hard_header (skb, dev, __constant_ntohs (ether_type), - &dest_hw, NULL, skb->len) >= 0) + if (dev->hard_header(skb, dev, ntohs(ether_type), &dest_hw, NULL, + skb->len) >= 0) ret = ether1394_type_trans(skb, dev); return ret; @@ -1079,8 +1074,7 @@ static inline int update_partial_datagra /* Move list entry to beginnig of list so that oldest partial * datagrams percolate to the end of the list */ - list_del(lh); - list_add(lh, pdgl); + list_move(lh, pdgl); return 0; } @@ -1395,7 +1389,7 @@ static inline void ether1394_arp_to_1394 /* We need to encapsulate the standard header with our own. We use the * ethernet header's proto for our own. */ static inline unsigned int ether1394_encapsulate_prep(unsigned int max_payload, - int proto, + __be16 proto, union eth1394_hdr *hdr, u16 dg_size, u16 dgl) { @@ -1514,8 +1508,8 @@ static inline void ether1394_prep_gasp_p p->data = ((quadlet_t*)skb->data) - 2; p->data[0] = cpu_to_be32((priv->host->node_id << 16) | ETHER1394_GASP_SPECIFIER_ID_HI); - p->data[1] = __constant_cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) | - ETHER1394_GASP_VERSION); + p->data[1] = cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) | + ETHER1394_GASP_VERSION); /* Setting the node id to ALL_NODES (not LOCAL_BUS | ALL_NODES) * prevents hpsb_send_packet() from setting the speed to an arbitrary @@ -1626,7 +1620,7 @@ static int ether1394_tx (struct sk_buff gfp_t kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; struct eth1394hdr *eth; struct eth1394_priv *priv = netdev_priv(dev); - int proto; + __be16 proto; unsigned long flags; nodeid_t dest_node; eth1394_tx_type tx_type; @@ -1670,9 +1664,9 @@ #endif /* Set the transmission type for the packet. ARP packets and IP * broadcast packets are sent via GASP. */ if (memcmp(eth->h_dest, dev->broadcast, ETH1394_ALEN) == 0 || - proto == __constant_htons(ETH_P_ARP) || - (proto == __constant_htons(ETH_P_IP) && - IN_MULTICAST(__constant_ntohl(skb->nh.iph->daddr)))) { + proto == htons(ETH_P_ARP) || + (proto == htons(ETH_P_IP) && + IN_MULTICAST(ntohl(skb->nh.iph->daddr)))) { tx_type = ETH1394_GASP; dest_node = LOCAL_BUS | ALL_NODES; max_payload = priv->bc_maxpayload - ETHER1394_GASP_OVERHEAD; @@ -1688,7 +1682,7 @@ #endif goto fail; } node_info = (struct eth1394_node_info*)node->ud->device.driver_data; - if (node_info->fifo == ETHER1394_INVALID_ADDR) { + if (node_info->fifo == CSR1212_INVALID_ADDR_SPACE) { ret = -EAGAIN; goto fail; } @@ -1704,7 +1698,7 @@ #endif } /* If this is an ARP packet, convert it */ - if (proto == __constant_htons (ETH_P_ARP)) + if (proto == htons(ETH_P_ARP)) ether1394_arp_to_1394arp (skb, dev); ptask->hdr.words.word1 = 0; diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h index a77213c..c45cbff 100644 --- a/drivers/ieee1394/eth1394.h +++ b/drivers/ieee1394/eth1394.h @@ -32,8 +32,6 @@ #include "ieee1394.h" * S3200 (per Table 16-3 of IEEE 1394b-2002). */ #define ETHER1394_REGION_ADDR_LEN 4096 -#define ETHER1394_INVALID_ADDR ~0ULL - /* GASP identifier numbers for IPv4 over IEEE 1394 */ #define ETHER1394_GASP_SPECIFIER_ID 0x00005E #define ETHER1394_GASP_SPECIFIER_ID_HI ((ETHER1394_GASP_SPECIFIER_ID >> 8) & 0xffff) diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 491e603..25b2260 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -53,7 +53,7 @@ static struct hpsb_address_serve dummy_z static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl, - struct hpsb_host *host) + struct hpsb_host *host) { struct hl_host_info *hi = NULL; @@ -68,24 +68,18 @@ static struct hl_host_info *hl_get_hosti } } read_unlock(&hl->host_info_lock); - return NULL; } - /* Returns a per host/driver data structure that was previously stored by * hpsb_create_hostinfo. */ void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) { struct hl_host_info *hi = hl_get_hostinfo(hl, host); - if (hi) - return hi->data; - - return NULL; + return hi ? hi->data : NULL; } - /* If size is zero, then the return here is only valid for error checking */ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, size_t data_size) @@ -96,8 +90,8 @@ void *hpsb_create_hostinfo(struct hpsb_h hi = hl_get_hostinfo(hl, host); if (hi) { - HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already exists", - hl->name); + HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already" + " exists", hl->name); return NULL; } @@ -120,7 +114,6 @@ void *hpsb_create_hostinfo(struct hpsb_h return data; } - int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void *data) { @@ -132,16 +125,14 @@ int hpsb_set_hostinfo(struct hpsb_highle hi->data = data; return 0; } else - HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo already has data", - hl->name); + HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo " + "already has data", hl->name); } else HPSB_ERR("%s called hpsb_set_hostinfo when no hostinfo exists", hl->name); - return -EINVAL; } - void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) { struct hl_host_info *hi; @@ -154,23 +145,20 @@ void hpsb_destroy_hostinfo(struct hpsb_h write_unlock_irqrestore(&hl->host_info_lock, flags); kfree(hi); } - return; } - -void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned long key) +void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, + unsigned long key) { struct hl_host_info *hi; hi = hl_get_hostinfo(hl, host); if (hi) hi->key = key; - return; } - void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key) { struct hl_host_info *hi; @@ -187,46 +175,41 @@ void *hpsb_get_hostinfo_bykey(struct hps } } read_unlock(&hl->host_info_lock); - return data; } - static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data) { struct hpsb_highlevel *hl = __data; hl->add_host(host); - if (host->update_config_rom) { - if (hpsb_update_config_rom_image(host) < 0) { - HPSB_ERR("Failed to generate Configuration ROM image for host " - "%s-%d", hl->name, host->id); - } - } - + if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0) + HPSB_ERR("Failed to generate Configuration ROM image for host " + "%s-%d", hl->name, host->id); return 0; } void hpsb_register_highlevel(struct hpsb_highlevel *hl) { - INIT_LIST_HEAD(&hl->addr_list); + unsigned long flags; + + INIT_LIST_HEAD(&hl->addr_list); INIT_LIST_HEAD(&hl->host_info_list); rwlock_init(&hl->host_info_lock); down_write(&hl_drivers_sem); - list_add_tail(&hl->hl_list, &hl_drivers); + list_add_tail(&hl->hl_list, &hl_drivers); up_write(&hl_drivers_sem); - write_lock(&hl_irqs_lock); + write_lock_irqsave(&hl_irqs_lock, flags); list_add_tail(&hl->irq_list, &hl_irqs); - write_unlock(&hl_irqs_lock); + write_unlock_irqrestore(&hl_irqs_lock, flags); if (hl->add_host) nodemgr_for_each_host(hl, highlevel_for_each_host_reg); - - return; + return; } static void __delete_addr(struct hpsb_address_serve *as) @@ -236,7 +219,8 @@ static void __delete_addr(struct hpsb_ad kfree(as); } -static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host, int update_cr) +static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host, + int update_cr) { unsigned long flags; struct list_head *lh, *next; @@ -251,7 +235,6 @@ static void __unregister_host(struct hps write_lock_irqsave(&addr_space_lock, flags); list_for_each_safe (lh, next, &hl->addr_list) { as = list_entry(lh, struct hpsb_address_serve, hl_list); - if (as->host == host) __delete_addr(as); } @@ -259,15 +242,12 @@ static void __unregister_host(struct hps /* Now update the config-rom to reflect anything removed by the * highlevel driver. */ - if (update_cr && host->update_config_rom) { - if (hpsb_update_config_rom_image(host) < 0) { - HPSB_ERR("Failed to generate Configuration ROM image for host " - "%s-%d", hl->name, host->id); - } - } + if (update_cr && host->update_config_rom && + hpsb_update_config_rom_image(host) < 0) + HPSB_ERR("Failed to generate Configuration ROM image for host " + "%s-%d", hl->name, host->id); - /* And finally, remove all the host info associated between these - * two. */ + /* Finally remove all the host info associated between these two. */ hpsb_destroy_hostinfo(hl, host); } @@ -276,18 +256,19 @@ static int highlevel_for_each_host_unreg struct hpsb_highlevel *hl = __data; __unregister_host(hl, host, 1); - return 0; } void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) { - write_lock(&hl_irqs_lock); + unsigned long flags; + + write_lock_irqsave(&hl_irqs_lock, flags); list_del(&hl->irq_list); - write_unlock(&hl_irqs_lock); + write_unlock_irqrestore(&hl_irqs_lock, flags); down_write(&hl_drivers_sem); - list_del(&hl->hl_list); + list_del(&hl->hl_list); up_write(&hl_drivers_sem); nodemgr_for_each_host(hl, highlevel_for_each_host_unreg); @@ -301,7 +282,7 @@ u64 hpsb_allocate_and_register_addrspace { struct hpsb_address_serve *as, *a1, *a2; struct list_head *entry; - u64 retval = ~0ULL; + u64 retval = CSR1212_INVALID_ADDR_SPACE; unsigned long flags; u64 align_mask = ~(alignment - 1); @@ -312,14 +293,19 @@ u64 hpsb_allocate_and_register_addrspace return retval; } - if (start == ~0ULL && end == ~0ULL) { - start = CSR1212_ALL_SPACE_BASE + 0xffff00000000ULL; /* ohci1394.c limit */ - end = CSR1212_ALL_SPACE_END; + /* default range, + * avoids controller's posted write area (see OHCI 1.1 clause 1.5) */ + if (start == CSR1212_INVALID_ADDR_SPACE && + end == CSR1212_INVALID_ADDR_SPACE) { + start = host->middle_addr_space; + end = CSR1212_ALL_SPACE_END; } - if (((start|end) & ~align_mask) || (start >= end) || (end > 0x1000000000000ULL)) { - HPSB_ERR("%s called with invalid addresses (start = %012Lx end = %012Lx)", - __FUNCTION__, (unsigned long long)start, (unsigned long long)end); + if (((start|end) & ~align_mask) || (start >= end) || + (end > CSR1212_ALL_SPACE_END)) { + HPSB_ERR("%s called with invalid addresses " + "(start = %012Lx end = %012Lx)", __FUNCTION__, + (unsigned long long)start,(unsigned long long)end); return retval; } @@ -333,20 +319,21 @@ u64 hpsb_allocate_and_register_addrspace as->host = host; write_lock_irqsave(&addr_space_lock, flags); - list_for_each(entry, &host->addr_space) { u64 a1sa, a1ea; u64 a2sa, a2ea; a1 = list_entry(entry, struct hpsb_address_serve, host_list); - a2 = list_entry(entry->next, struct hpsb_address_serve, host_list); + a2 = list_entry(entry->next, struct hpsb_address_serve, + host_list); a1sa = a1->start & align_mask; a1ea = (a1->end + alignment -1) & align_mask; a2sa = a2->start & align_mask; a2ea = (a2->end + alignment -1) & align_mask; - if ((a2sa - a1ea >= size) && (a2sa - start >= size) && (a2sa > start)) { + if ((a2sa - a1ea >= size) && (a2sa - start >= size) && + (a2sa > start)) { as->start = max(start, a1ea); as->end = as->start + size; list_add(&as->host_list, entry); @@ -355,47 +342,45 @@ u64 hpsb_allocate_and_register_addrspace break; } } - write_unlock_irqrestore(&addr_space_lock, flags); - if (retval == ~0ULL) { + if (retval == CSR1212_INVALID_ADDR_SPACE) kfree(as); - } - return retval; } int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, - struct hpsb_address_ops *ops, u64 start, u64 end) + struct hpsb_address_ops *ops, u64 start, u64 end) { - struct hpsb_address_serve *as; + struct hpsb_address_serve *as; struct list_head *lh; - int retval = 0; - unsigned long flags; + int retval = 0; + unsigned long flags; - if (((start|end) & 3) || (start >= end) || (end > 0x1000000000000ULL)) { - HPSB_ERR("%s called with invalid addresses", __FUNCTION__); - return 0; - } + if (((start|end) & 3) || (start >= end) || + (end > CSR1212_ALL_SPACE_END)) { + HPSB_ERR("%s called with invalid addresses", __FUNCTION__); + return 0; + } as = kmalloc(sizeof(*as), GFP_ATOMIC); if (!as) return 0; - INIT_LIST_HEAD(&as->host_list); - INIT_LIST_HEAD(&as->hl_list); - as->op = ops; - as->start = start; - as->end = end; + INIT_LIST_HEAD(&as->host_list); + INIT_LIST_HEAD(&as->hl_list); + as->op = ops; + as->start = start; + as->end = end; as->host = host; write_lock_irqsave(&addr_space_lock, flags); - list_for_each(lh, &host->addr_space) { struct hpsb_address_serve *as_this = list_entry(lh, struct hpsb_address_serve, host_list); struct hpsb_address_serve *as_next = - list_entry(lh->next, struct hpsb_address_serve, host_list); + list_entry(lh->next, struct hpsb_address_serve, + host_list); if (as_this->end > as->start) break; @@ -411,60 +396,51 @@ int hpsb_register_addrspace(struct hpsb_ if (retval == 0) kfree(as); - - return retval; + return retval; } int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, - u64 start) + u64 start) { - int retval = 0; - struct hpsb_address_serve *as; - struct list_head *lh, *next; - unsigned long flags; - - write_lock_irqsave(&addr_space_lock, flags); + int retval = 0; + struct hpsb_address_serve *as; + struct list_head *lh, *next; + unsigned long flags; + write_lock_irqsave(&addr_space_lock, flags); list_for_each_safe (lh, next, &hl->addr_list) { - as = list_entry(lh, struct hpsb_address_serve, hl_list); - if (as->start == start && as->host == host) { + as = list_entry(lh, struct hpsb_address_serve, hl_list); + if (as->start == start && as->host == host) { __delete_addr(as); - retval = 1; - break; - } - } - - write_unlock_irqrestore(&addr_space_lock, flags); - - return retval; + retval = 1; + break; + } + } + write_unlock_irqrestore(&addr_space_lock, flags); + return retval; } int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, - unsigned int channel) + unsigned int channel) { - if (channel > 63) { - HPSB_ERR("%s called with invalid channel", __FUNCTION__); - return -EINVAL; - } - - if (host->iso_listen_count[channel]++ == 0) { - return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); - } - + if (channel > 63) { + HPSB_ERR("%s called with invalid channel", __FUNCTION__); + return -EINVAL; + } + if (host->iso_listen_count[channel]++ == 0) + return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); return 0; } void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, - unsigned int channel) + unsigned int channel) { - if (channel > 63) { - HPSB_ERR("%s called with invalid channel", __FUNCTION__); - return; - } - - if (--host->iso_listen_count[channel] == 0) { - host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel); - } + if (channel > 63) { + HPSB_ERR("%s called with invalid channel", __FUNCTION__); + return; + } + if (--host->iso_listen_count[channel] == 0) + host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel); } static void init_hpsb_highlevel(struct hpsb_host *host) @@ -485,26 +461,24 @@ static void init_hpsb_highlevel(struct h void highlevel_add_host(struct hpsb_host *host) { - struct hpsb_highlevel *hl; + struct hpsb_highlevel *hl; init_hpsb_highlevel(host); down_read(&hl_drivers_sem); - list_for_each_entry(hl, &hl_drivers, hl_list) { + list_for_each_entry(hl, &hl_drivers, hl_list) { if (hl->add_host) hl->add_host(host); - } - up_read(&hl_drivers_sem); - if (host->update_config_rom) { - if (hpsb_update_config_rom_image(host) < 0) - HPSB_ERR("Failed to generate Configuration ROM image for " - "host %s-%d", hl->name, host->id); } + up_read(&hl_drivers_sem); + if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0) + HPSB_ERR("Failed to generate Configuration ROM image for host " + "%s-%d", hl->name, host->id); } void highlevel_remove_host(struct hpsb_host *host) { - struct hpsb_highlevel *hl; + struct hpsb_highlevel *hl; down_read(&hl_drivers_sem); list_for_each_entry(hl, &hl_drivers, hl_list) @@ -514,184 +488,169 @@ void highlevel_remove_host(struct hpsb_h void highlevel_host_reset(struct hpsb_host *host) { - struct hpsb_highlevel *hl; + unsigned long flags; + struct hpsb_highlevel *hl; - read_lock(&hl_irqs_lock); + read_lock_irqsave(&hl_irqs_lock, flags); list_for_each_entry(hl, &hl_irqs, irq_list) { - if (hl->host_reset) - hl->host_reset(host); - } - read_unlock(&hl_irqs_lock); + if (hl->host_reset) + hl->host_reset(host); + } + read_unlock_irqrestore(&hl_irqs_lock, flags); } void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length) { - struct hpsb_highlevel *hl; - int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f; + unsigned long flags; + struct hpsb_highlevel *hl; + int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f; - read_lock(&hl_irqs_lock); + read_lock_irqsave(&hl_irqs_lock, flags); list_for_each_entry(hl, &hl_irqs, irq_list) { - if (hl->iso_receive) - hl->iso_receive(host, channel, data, length); - } - read_unlock(&hl_irqs_lock); + if (hl->iso_receive) + hl->iso_receive(host, channel, data, length); + } + read_unlock_irqrestore(&hl_irqs_lock, flags); } void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, void *data, size_t length) { - struct hpsb_highlevel *hl; - int cts = ((quadlet_t *)data)[0] >> 4; + unsigned long flags; + struct hpsb_highlevel *hl; + int cts = ((quadlet_t *)data)[0] >> 4; - read_lock(&hl_irqs_lock); + read_lock_irqsave(&hl_irqs_lock, flags); list_for_each_entry(hl, &hl_irqs, irq_list) { - if (hl->fcp_request) - hl->fcp_request(host, nodeid, direction, cts, data, + if (hl->fcp_request) + hl->fcp_request(host, nodeid, direction, cts, data, length); - } - read_unlock(&hl_irqs_lock); + } + read_unlock_irqrestore(&hl_irqs_lock, flags); } -int highlevel_read(struct hpsb_host *host, int nodeid, void *data, - u64 addr, unsigned int length, u16 flags) +int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr, + unsigned int length, u16 flags) { - struct hpsb_address_serve *as; - unsigned int partlength; - int rcode = RCODE_ADDRESS_ERROR; - - read_lock(&addr_space_lock); + struct hpsb_address_serve *as; + unsigned int partlength; + int rcode = RCODE_ADDRESS_ERROR; + read_lock(&addr_space_lock); list_for_each_entry(as, &host->addr_space, host_list) { if (as->start > addr) break; - if (as->end > addr) { - partlength = min(as->end - addr, (u64) length); + if (as->end > addr) { + partlength = min(as->end - addr, (u64) length); - if (as->op->read) { - rcode = as->op->read(host, nodeid, data, + if (as->op->read) + rcode = as->op->read(host, nodeid, data, addr, partlength, flags); - } else { - rcode = RCODE_TYPE_ERROR; - } + else + rcode = RCODE_TYPE_ERROR; data += partlength; - length -= partlength; - addr += partlength; - - if ((rcode != RCODE_COMPLETE) || !length) { - break; - } - } - } - - read_unlock(&addr_space_lock); + length -= partlength; + addr += partlength; - if (length && (rcode == RCODE_COMPLETE)) { - rcode = RCODE_ADDRESS_ERROR; - } + if ((rcode != RCODE_COMPLETE) || !length) + break; + } + } + read_unlock(&addr_space_lock); - return rcode; + if (length && (rcode == RCODE_COMPLETE)) + rcode = RCODE_ADDRESS_ERROR; + return rcode; } -int highlevel_write(struct hpsb_host *host, int nodeid, int destid, - void *data, u64 addr, unsigned int length, u16 flags) +int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data, + u64 addr, unsigned int length, u16 flags) { - struct hpsb_address_serve *as; - unsigned int partlength; - int rcode = RCODE_ADDRESS_ERROR; - - read_lock(&addr_space_lock); + struct hpsb_address_serve *as; + unsigned int partlength; + int rcode = RCODE_ADDRESS_ERROR; + read_lock(&addr_space_lock); list_for_each_entry(as, &host->addr_space, host_list) { if (as->start > addr) break; - if (as->end > addr) { - partlength = min(as->end - addr, (u64) length); + if (as->end > addr) { + partlength = min(as->end - addr, (u64) length); - if (as->op->write) { - rcode = as->op->write(host, nodeid, destid, - data, addr, partlength, flags); - } else { - rcode = RCODE_TYPE_ERROR; - } + if (as->op->write) + rcode = as->op->write(host, nodeid, destid, + data, addr, partlength, + flags); + else + rcode = RCODE_TYPE_ERROR; data += partlength; - length -= partlength; - addr += partlength; - - if ((rcode != RCODE_COMPLETE) || !length) { - break; - } - } - } - - read_unlock(&addr_space_lock); + length -= partlength; + addr += partlength; - if (length && (rcode == RCODE_COMPLETE)) { - rcode = RCODE_ADDRESS_ERROR; - } + if ((rcode != RCODE_COMPLETE) || !length) + break; + } + } + read_unlock(&addr_space_lock); - return rcode; + if (length && (rcode == RCODE_COMPLETE)) + rcode = RCODE_ADDRESS_ERROR; + return rcode; } - int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags) + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, + u16 flags) { - struct hpsb_address_serve *as; - int rcode = RCODE_ADDRESS_ERROR; - - read_lock(&addr_space_lock); + struct hpsb_address_serve *as; + int rcode = RCODE_ADDRESS_ERROR; + read_lock(&addr_space_lock); list_for_each_entry(as, &host->addr_space, host_list) { if (as->start > addr) break; - if (as->end > addr) { - if (as->op->lock) { - rcode = as->op->lock(host, nodeid, store, addr, - data, arg, ext_tcode, flags); - } else { - rcode = RCODE_TYPE_ERROR; - } - - break; - } - } - - read_unlock(&addr_space_lock); - - return rcode; + if (as->end > addr) { + if (as->op->lock) + rcode = as->op->lock(host, nodeid, store, addr, + data, arg, ext_tcode, + flags); + else + rcode = RCODE_TYPE_ERROR; + break; + } + } + read_unlock(&addr_space_lock); + return rcode; } int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store, - u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags) + u64 addr, octlet_t data, octlet_t arg, int ext_tcode, + u16 flags) { - struct hpsb_address_serve *as; - int rcode = RCODE_ADDRESS_ERROR; + struct hpsb_address_serve *as; + int rcode = RCODE_ADDRESS_ERROR; - read_lock(&addr_space_lock); + read_lock(&addr_space_lock); list_for_each_entry(as, &host->addr_space, host_list) { if (as->start > addr) break; - if (as->end > addr) { - if (as->op->lock64) { - rcode = as->op->lock64(host, nodeid, store, - addr, data, arg, - ext_tcode, flags); - } else { - rcode = RCODE_TYPE_ERROR; - } - - break; - } - } - - read_unlock(&addr_space_lock); - - return rcode; + if (as->end > addr) { + if (as->op->lock64) + rcode = as->op->lock64(host, nodeid, store, + addr, data, arg, + ext_tcode, flags); + else + rcode = RCODE_TYPE_ERROR; + break; + } + } + read_unlock(&addr_space_lock); + return rcode; } diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index ba09741..ad49c04 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -19,6 +19,7 @@ #include #include #include #include +#include #include "csr1212.h" #include "ieee1394.h" @@ -102,10 +103,10 @@ static int alloc_hostnum_cb(struct hpsb_ * driver specific parts, enable the controller and make it available * to the general subsystem using hpsb_add_host(). * - * Return Value: a pointer to the &hpsb_host if succesful, %NULL if + * Return Value: a pointer to the &hpsb_host if successful, %NULL if * no memory was available. */ -static DECLARE_MUTEX(host_num_alloc); +static DEFINE_MUTEX(host_num_alloc); struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, struct device *dev) @@ -148,7 +149,7 @@ struct hpsb_host *hpsb_alloc_host(struct h->topology_map = h->csr.topology_map + 3; h->speed_map = (u8 *)(h->csr.speed_map + 2); - down(&host_num_alloc); + mutex_lock(&host_num_alloc); while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) hostnum++; @@ -167,7 +168,7 @@ struct hpsb_host *hpsb_alloc_host(struct class_device_register(&h->class_dev); get_device(&h->device); - up(&host_num_alloc); + mutex_unlock(&host_num_alloc); return h; } diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index 07d188c..9ad4b24 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -30,13 +30,14 @@ struct hpsb_host { unsigned char iso_listen_count[64]; - int node_count; /* number of identified nodes on this bus */ - int selfid_count; /* total number of SelfIDs received */ - int nodes_active; /* number of nodes that are actually active */ + int node_count; /* number of identified nodes on this bus */ + int selfid_count; /* total number of SelfIDs received */ + int nodes_active; /* number of nodes with active link layer */ + u8 speed[ALL_NODES]; /* speed between each node and local node */ - nodeid_t node_id; /* node ID of this host */ - nodeid_t irm_id; /* ID of this bus' isochronous resource manager */ - nodeid_t busmgr_id; /* ID of this bus' bus manager */ + nodeid_t node_id; /* node ID of this host */ + nodeid_t irm_id; /* ID of this bus' isochronous resource manager */ + nodeid_t busmgr_id; /* ID of this bus' bus manager */ /* this nodes state */ unsigned in_bus_reset:1; @@ -55,7 +56,7 @@ struct hpsb_host { struct csr_control csr; /* Per node tlabel pool allocation */ - struct hpsb_tlabel_pool tpool[64]; + struct hpsb_tlabel_pool tpool[ALL_NODES]; struct hpsb_host_driver *driver; @@ -72,6 +73,8 @@ struct hpsb_host { unsigned int config_roms; struct list_head addr_space; + u64 low_addr_space; /* upper bound of physical DMA area */ + u64 middle_addr_space; /* upper bound of posted write area */ }; diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index be6854e..49354de 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -33,6 +33,7 @@ #include #include #include #include +#include #include #include @@ -285,9 +286,9 @@ static int check_selfids(struct hpsb_hos static void build_speed_map(struct hpsb_host *host, int nodecount) { - u8 speedcap[nodecount]; u8 cldcnt[nodecount]; u8 *map = host->speed_map; + u8 *speedcap = host->speed; struct selfid *sid; struct ext_selfid *esid; int i, j, n; @@ -354,6 +355,11 @@ static void build_speed_map(struct hpsb_ } } } + + /* assume maximum speed for 1394b PHYs, nodemgr will correct it */ + for (n = 0; n < nodecount; n++) + if (speedcap[n] == 3) + speedcap[n] = IEEE1394_SPEED_MAX; } @@ -554,11 +560,10 @@ int hpsb_send_packet(struct hpsb_packet return 0; } - if (packet->type == hpsb_async && packet->node_id != ALL_NODES) { + if (packet->type == hpsb_async && + NODEID_TO_NODE(packet->node_id) != ALL_NODES) packet->speed_code = - host->speed_map[NODEID_TO_NODE(host->node_id) * 64 - + NODEID_TO_NODE(packet->node_id)]; - } + host->speed[NODEID_TO_NODE(packet->node_id)]; dump_packet("send packet", packet->header, packet->header_size, packet->speed_code); @@ -997,11 +1002,8 @@ void abort_timedouts(unsigned long __opa * packets that have a "complete" function are sent here. This way, the * completion is run out of kernel context, and doesn't block the rest of * the stack. */ -static int khpsbpkt_pid = -1, khpsbpkt_kill; -static DECLARE_COMPLETION(khpsbpkt_complete); +static struct task_struct *khpsbpkt_thread; static struct sk_buff_head hpsbpkt_queue; -static DECLARE_MUTEX_LOCKED(khpsbpkt_sig); - static void queue_packet_complete(struct hpsb_packet *packet) { @@ -1011,9 +1013,7 @@ static void queue_packet_complete(struct } if (packet->complete_routine != NULL) { skb_queue_tail(&hpsbpkt_queue, packet->skb); - - /* Signal the kernel thread to handle this */ - up(&khpsbpkt_sig); + wake_up_process(khpsbpkt_thread); } return; } @@ -1025,19 +1025,9 @@ static int hpsbpkt_thread(void *__hi) void (*complete_routine)(void*); void *complete_data; - daemonize("khpsbpkt"); - current->flags |= PF_NOFREEZE; - while (1) { - if (down_interruptible(&khpsbpkt_sig)) { - printk("khpsbpkt: received unexpected signal?!\n" ); - break; - } - - if (khpsbpkt_kill) - break; - + while (!kthread_should_stop()) { while ((skb = skb_dequeue(&hpsbpkt_queue)) != NULL) { packet = (struct hpsb_packet *)skb->data; @@ -1048,9 +1038,13 @@ static int hpsbpkt_thread(void *__hi) complete_routine(complete_data); } - } - complete_and_exit(&khpsbpkt_complete, 0); + set_current_state(TASK_INTERRUPTIBLE); + if (!skb_peek(&hpsbpkt_queue)) + schedule(); + __set_current_state(TASK_RUNNING); + } + return 0; } static int __init ieee1394_init(void) @@ -1065,10 +1059,10 @@ static int __init ieee1394_init(void) HPSB_ERR("Some features may not be available\n"); } - khpsbpkt_pid = kernel_thread(hpsbpkt_thread, NULL, CLONE_KERNEL); - if (khpsbpkt_pid < 0) { + khpsbpkt_thread = kthread_run(hpsbpkt_thread, NULL, "khpsbpkt"); + if (IS_ERR(khpsbpkt_thread)) { HPSB_ERR("Failed to start hpsbpkt thread!\n"); - ret = -ENOMEM; + ret = PTR_ERR(khpsbpkt_thread); goto exit_cleanup_config_roms; } @@ -1148,10 +1142,7 @@ release_all_bus: release_chrdev: unregister_chrdev_region(IEEE1394_CORE_DEV, 256); exit_release_kernel_thread: - if (khpsbpkt_pid >= 0) { - kill_proc(khpsbpkt_pid, SIGTERM, 1); - wait_for_completion(&khpsbpkt_complete); - } + kthread_stop(khpsbpkt_thread); exit_cleanup_config_roms: hpsb_cleanup_config_roms(); return ret; @@ -1172,12 +1163,7 @@ static void __exit ieee1394_cleanup(void bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]); bus_unregister(&ieee1394_bus_type); - if (khpsbpkt_pid >= 0) { - khpsbpkt_kill = 1; - mb(); - up(&khpsbpkt_sig); - wait_for_completion(&khpsbpkt_complete); - } + kthread_stop(khpsbpkt_thread); hpsb_cleanup_config_roms(); diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index e7b55e8..0ecbf33 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h @@ -139,7 +139,7 @@ int hpsb_bus_reset(struct hpsb_host *hos /* * Hand over received selfid packet to the core. Complement check (second - * quadlet is complement of first) is expected to be done and succesful. + * quadlet is complement of first) is expected to be done and successful. */ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid); diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c index 3fe2f6c..a114b91 100644 --- a/drivers/ieee1394/ieee1394_transactions.c +++ b/drivers/ieee1394/ieee1394_transactions.c @@ -136,8 +136,11 @@ int hpsb_get_tlabel(struct hpsb_packet * { unsigned long flags; struct hpsb_tlabel_pool *tp; + int n = NODEID_TO_NODE(packet->node_id); - tp = &packet->host->tpool[packet->node_id & NODE_MASK]; + if (unlikely(n == ALL_NODES)) + return 0; + tp = &packet->host->tpool[n]; if (irqs_disabled() || in_atomic()) { if (down_trylock(&tp->count)) @@ -175,8 +178,11 @@ void hpsb_free_tlabel(struct hpsb_packet { unsigned long flags; struct hpsb_tlabel_pool *tp; + int n = NODEID_TO_NODE(packet->node_id); - tp = &packet->host->tpool[packet->node_id & NODE_MASK]; + if (unlikely(n == ALL_NODES)) + return; + tp = &packet->host->tpool[n]; BUG_ON(packet->tlabel > 63 || packet->tlabel < 0); diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 082c7fd..50c71e1 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -8,6 +8,7 @@ * directory of the kernel sources for details. */ +#include #include #include #include @@ -38,6 +39,7 @@ struct nodemgr_csr_info { struct hpsb_host *host; nodeid_t nodeid; unsigned int generation; + unsigned int speed_unverified:1; }; @@ -57,23 +59,75 @@ #endif return NULL; } +/* + * Correct the speed map entry. This is necessary + * - for nodes with link speed < phy speed, + * - for 1394b nodes with negotiated phy port speed < IEEE1394_SPEED_MAX. + * A possible speed is determined by trial and error, using quadlet reads. + */ +static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr, + quadlet_t *buffer) +{ + quadlet_t q; + u8 i, *speed, old_speed, good_speed; + int ret; + + speed = ci->host->speed + NODEID_TO_NODE(ci->nodeid); + old_speed = *speed; + good_speed = IEEE1394_SPEED_MAX + 1; + + /* Try every speed from S100 to old_speed. + * If we did it the other way around, a too low speed could be caught + * if the retry succeeded for some other reason, e.g. because the link + * just finished its initialization. */ + for (i = IEEE1394_SPEED_100; i <= old_speed; i++) { + *speed = i; + ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, + &q, sizeof(quadlet_t)); + if (ret) + break; + *buffer = q; + good_speed = i; + } + if (good_speed <= IEEE1394_SPEED_MAX) { + HPSB_DEBUG("Speed probe of node " NODE_BUS_FMT " yields %s", + NODE_BUS_ARGS(ci->host, ci->nodeid), + hpsb_speedto_str[good_speed]); + *speed = good_speed; + ci->speed_unverified = 0; + return 0; + } + *speed = old_speed; + return ret; +} static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, void *buffer, void *__ci) { struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci; - int i, ret = 0; + int i, ret; for (i = 1; ; i++) { ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, buffer, length); - if (!ret || i == 3) + if (!ret) { + ci->speed_unverified = 0; + break; + } + /* Give up after 3rd failure. */ + if (i == 3) break; + /* The ieee1394_core guessed the node's speed capability from + * the self ID. Check whether a lower speed works. */ + if (ci->speed_unverified && length == sizeof(quadlet_t)) { + ret = nodemgr_check_speed(ci, addr, buffer); + if (!ret) + break; + } if (msleep_interruptible(334)) return -EINTR; } - return ret; } @@ -281,10 +335,12 @@ static ssize_t fw_show_ne_bus_options(st static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL); +/* tlabels_free, tlabels_allocations, tlabels_mask are read non-atomically + * here, therefore displayed values may be occasionally wrong. */ static ssize_t fw_show_ne_tlabels_free(struct device *dev, struct device_attribute *attr, char *buf) { struct node_entry *ne = container_of(dev, struct node_entry, device); - return sprintf(buf, "%d\n", atomic_read(&ne->tpool->count.count) + 1); + return sprintf(buf, "%d\n", 64 - bitmap_weight(ne->tpool->pool, 64)); } static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL); @@ -1204,6 +1260,8 @@ static void nodemgr_node_scan_one(struct ci->host = host; ci->nodeid = nodeid; ci->generation = generation; + ci->speed_unverified = + host->speed[NODEID_TO_NODE(nodeid)] > IEEE1394_SPEED_100; /* We need to detect when the ConfigROM's generation has changed, * so we only update the node's info when it needs to be. */ diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 11f1377..3d27841 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -163,7 +163,7 @@ printk(level "%s: fw-host%d: " fmt "\n" /* Module Parameters */ static int phys_dma = 1; -module_param(phys_dma, int, 0644); +module_param(phys_dma, int, 0444); MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1)."); static void dma_trm_tasklet(unsigned long data); @@ -553,7 +553,8 @@ static void ohci_initialize(struct ti_oh * register content. * To actually enable physical responses is the job of our interrupt * handler which programs the physical request filter. */ - reg_write(ohci, OHCI1394_PhyUpperBound, 0x01000000); + reg_write(ohci, OHCI1394_PhyUpperBound, + OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED >> 16); DBGMSG("physUpperBoundOffset=%08x", reg_read(ohci, OHCI1394_PhyUpperBound)); @@ -580,17 +581,14 @@ static void ohci_initialize(struct ti_oh OHCI1394_isochRx | OHCI1394_isochTx | OHCI1394_postedWriteErr | + OHCI1394_cycleTooLong | OHCI1394_cycleInconsistent); /* Enable link */ reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable); buf = reg_read(ohci, OHCI1394_Version); -#ifndef __sparc__ sprintf (irq_buf, "%d", ohci->dev->irq); -#else - sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq)); -#endif PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s] " "MMIO=[%lx-%lx] Max Packet=[%d] IR/IT contexts=[%d/%d]", ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10), @@ -2386,6 +2384,15 @@ static irqreturn_t ohci_irq_handler(int PRINT(KERN_ERR, "physical posted write error"); /* no recovery strategy yet, had to involve protocol drivers */ } + if (event & OHCI1394_cycleTooLong) { + if(printk_ratelimit()) + PRINT(KERN_WARNING, "isochronous cycle too long"); + else + DBGMSG("OHCI1394_cycleTooLong"); + reg_write(ohci, OHCI1394_LinkControlSet, + OHCI1394_LinkControl_CycleMaster); + event &= ~OHCI1394_cycleTooLong; + } if (event & OHCI1394_cycleInconsistent) { /* We subscribe to the cycleInconsistent event only to * clear the corresponding event bit... otherwise, @@ -3404,6 +3411,14 @@ #endif host->csr.max_rec = (reg_read(ohci, OHCI1394_BusOptions) >> 12) & 0xf; host->csr.lnk_spd = reg_read(ohci, OHCI1394_BusOptions) & 0x7; + if (phys_dma) { + host->low_addr_space = + (u64) reg_read(ohci, OHCI1394_PhyUpperBound) << 16; + if (!host->low_addr_space) + host->low_addr_space = OHCI1394_PHYS_UPPER_BOUND_FIXED; + } + host->middle_addr_space = OHCI1394_MIDDLE_ADDRESS_SPACE; + /* Tell the highlevel this host is ready */ if (hpsb_add_host(host)) FAIL(-ENOMEM, "Failed to register host with highlevel"); @@ -3462,24 +3477,13 @@ static void ohci1394_pci_remove(struct p case OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE: /* The ohci_soft_reset() stops all DMA contexts, so we * dont need to do this. */ - /* Free AR dma */ free_dma_rcv_ctx(&ohci->ar_req_context); free_dma_rcv_ctx(&ohci->ar_resp_context); - - /* Free AT dma */ free_dma_trm_ctx(&ohci->at_req_context); free_dma_trm_ctx(&ohci->at_resp_context); - - /* Free IR dma */ free_dma_rcv_ctx(&ohci->ir_legacy_context); - - /* Free IT dma */ free_dma_trm_ctx(&ohci->it_legacy_context); - /* Free IR legacy dma */ - free_dma_rcv_ctx(&ohci->ir_legacy_context); - - case OHCI_INIT_HAVE_SELFID_BUFFER: pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, ohci->selfid_buf_cpu, @@ -3539,6 +3543,7 @@ #ifdef CONFIG_PPC_PMAC } #endif /* CONFIG_PPC_PMAC */ + pci_restore_state(pdev); pci_enable_device(pdev); return 0; @@ -3558,6 +3563,8 @@ #ifdef CONFIG_PPC_PMAC } #endif + pci_save_state(pdev); + return 0; } diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h index 7df0962..fa05f11 100644 --- a/drivers/ieee1394/ohci1394.h +++ b/drivers/ieee1394/ohci1394.h @@ -443,6 +443,16 @@ #define EVT_FLUSHED 0xf /* Send by the #define OHCI1394_TCODE_PHY 0xE +/* Node offset map (phys DMA area, posted write area). + * The value of OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED may be modified but must + * be lower than OHCI1394_MIDDLE_ADDRESS_SPACE. + * OHCI1394_PHYS_UPPER_BOUND_FIXED and OHCI1394_MIDDLE_ADDRESS_SPACE are + * constants given by the OHCI spec. + */ +#define OHCI1394_PHYS_UPPER_BOUND_FIXED 0x000100000000ULL /* 4 GB */ +#define OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED 0x010000000000ULL /* 1 TB */ +#define OHCI1394_MIDDLE_ADDRESS_SPACE 0xffff00000000ULL + void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet, int type, void (*func)(unsigned long), diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c index e2edc41..e29dfd2 100644 --- a/drivers/ieee1394/pcilynx.c +++ b/drivers/ieee1394/pcilynx.c @@ -1252,11 +1252,7 @@ #define FAIL(fmt, args...) do { \ /* Fix buggy cards with autoboot pin not tied low: */ reg_write(lynx, DMA0_CHAN_CTRL, 0); -#ifndef __sparc__ sprintf (irq_buf, "%d", dev->irq); -#else - sprintf (irq_buf, "%s", __irq_itoa(dev->irq)); -#endif if (!request_irq(dev->irq, lynx_irq_handler, SA_SHIRQ, PCILYNX_DRIVER_NAME, lynx)) { diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index f7de546..571ea68 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -132,8 +132,7 @@ static void free_pending_request(struct static void __queue_complete_req(struct pending_request *req) { struct file_info *fi = req->file_info; - list_del(&req->list); - list_add_tail(&req->list, &fi->req_complete); + list_move_tail(&req->list, &fi->req_complete); up(&fi->complete_sem); wake_up_interruptible(&fi->poll_wait_complete); @@ -408,34 +407,34 @@ static void fcp_request(struct hpsb_host #ifdef CONFIG_COMPAT struct compat_raw1394_req { - __u32 type; - __s32 error; - __u32 misc; + __u32 type; + __s32 error; + __u32 misc; - __u32 generation; - __u32 length; + __u32 generation; + __u32 length; - __u64 address; + __u64 address; - __u64 tag; + __u64 tag; - __u64 sendb; - __u64 recvb; -} __attribute__((packed)); + __u64 sendb; + __u64 recvb; +} __attribute__((packed)); static const char __user *raw1394_compat_write(const char __user *buf) { - struct compat_raw1394_req __user *cr = (typeof(cr)) buf; + struct compat_raw1394_req __user *cr = (typeof(cr)) buf; struct raw1394_request __user *r; r = compat_alloc_user_space(sizeof(struct raw1394_request)); #define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x)) if (copy_in_user(r, cr, sizeof(struct compat_raw1394_req)) || - C(address) || - C(tag) || - C(sendb) || - C(recvb)) + C(address) || + C(tag) || + C(sendb) || + C(recvb)) return ERR_PTR(-EFAULT); return (const char __user *)r; } @@ -443,11 +442,11 @@ #undef C #define P(x) __put_user(r->x, &cr->x) -static int +static int raw1394_compat_read(const char __user *buf, struct raw1394_request *r) { - struct compat_raw1394_req __user *cr = (typeof(cr)) r; - if (!access_ok(VERIFY_WRITE,cr,sizeof(struct compat_raw1394_req)) || + struct compat_raw1394_req __user *cr = (typeof(cr)) r; + if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) || P(type) || P(error) || P(misc) || @@ -512,18 +511,17 @@ #endif } #ifdef CONFIG_COMPAT - if (count == sizeof(struct compat_raw1394_req) && - sizeof(struct compat_raw1394_req) != - sizeof(struct raw1394_request)) { + if (count == sizeof(struct compat_raw1394_req) && + sizeof(struct compat_raw1394_req) != + sizeof(struct raw1394_request)) { ret = raw1394_compat_read(buffer, &req->req); - - } else + } else #endif { if (copy_to_user(buffer, &req->req, sizeof(req->req))) { ret = -EFAULT; goto out; - } + } ret = (ssize_t) sizeof(struct raw1394_request); } out: @@ -2348,7 +2346,6 @@ static int state_connected(struct file_i return handle_async_request(fi, req, node); } - static ssize_t raw1394_write(struct file *file, const char __user * buffer, size_t count, loff_t * offset_is_ignored) { @@ -2357,9 +2354,9 @@ static ssize_t raw1394_write(struct file ssize_t retval = 0; #ifdef CONFIG_COMPAT - if (count == sizeof(struct compat_raw1394_req) && - sizeof(struct compat_raw1394_req) != - sizeof(struct raw1394_request)) { + if (count == sizeof(struct compat_raw1394_req) && + sizeof(struct compat_raw1394_req) != + sizeof(struct raw1394_request)) { buffer = raw1394_compat_write(buffer); if (IS_ERR(buffer)) return PTR_ERR(buffer); diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 5413dc4..1d5ceb7 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -127,10 +127,12 @@ MODULE_PARM_DESC(max_sectors, "Change ma * talking to a single sbp2 device at the same time (filesystem coherency, * etc.). If you're running an sbp2 device that supports multiple logins, * and you're either running read-only filesystems or some sort of special - * filesystem supporting multiple hosts (one such filesystem is OpenGFS, - * see opengfs.sourceforge.net for more info), then set exclusive_login - * to zero. Note: The Oxsemi OXFW911 sbp2 chipset supports up to four - * concurrent logins. + * filesystem supporting multiple hosts, e.g. OpenGFS, Oracle Cluster + * File System, or Lustre, then set exclusive_login to zero. + * + * So far only bridges from Oxford Semiconductor are known to support + * concurrent logins. Depending on firmware, four or two concurrent logins + * are possible on OXFW911 and newer Oxsemi bridges. */ static int exclusive_login = 1; module_param(exclusive_login, int, 0644); @@ -306,8 +308,9 @@ static const struct { u32 model_id; unsigned workarounds; } sbp2_workarounds_table[] = { - /* TSB42AA9 */ { + /* DViCO Momobay CX-1 with TSB42AA9 bridge */ { .firmware_revision = 0x002800, + .model_id = 0x001010, .workarounds = SBP2_WORKAROUND_INQUIRY_36 | SBP2_WORKAROUND_MODE_SENSE_8, }, @@ -791,12 +794,12 @@ static struct scsi_id_instance_data *sbp scsi_id->ud = ud; scsi_id->speed_code = IEEE1394_SPEED_100; scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; + scsi_id->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE; atomic_set(&scsi_id->sbp2_login_complete, 0); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); INIT_LIST_HEAD(&scsi_id->scsi_list); spin_lock_init(&scsi_id->sbp2_command_orb_lock); - scsi_id->sbp2_lun = 0; ud->device.driver_data = scsi_id; @@ -844,8 +847,8 @@ #endif scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace( &sbp2_highlevel, ud->ne->host, &sbp2_ops, sizeof(struct sbp2_status_block), sizeof(quadlet_t), - 0x010000000000ULL, CSR1212_ALL_SPACE_END); - if (scsi_id->status_fifo_addr == ~0ULL) { + ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END); + if (scsi_id->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) { SBP2_ERR("failed to allocate status FIFO address range"); goto failed_alloc; } @@ -1087,9 +1090,9 @@ static void sbp2_remove_device(struct sc SBP2_DMA_FREE("single query logins data"); } - if (scsi_id->status_fifo_addr) + if (scsi_id->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE) hpsb_unregister_addrspace(&sbp2_highlevel, hi->host, - scsi_id->status_fifo_addr); + scsi_id->status_fifo_addr); scsi_id->ud->device.driver_data = NULL; @@ -1213,13 +1216,11 @@ static int sbp2_query_logins(struct scsi SBP2_DEBUG("length_max_logins = %x", (unsigned int)scsi_id->query_logins_response->length_max_logins); - SBP2_DEBUG("Query logins to SBP-2 device successful"); - max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins); - SBP2_DEBUG("Maximum concurrent logins supported: %d", max_logins); + SBP2_INFO("Maximum concurrent logins supported: %d", max_logins); active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins); - SBP2_DEBUG("Number of active logins: %d", active_logins); + SBP2_INFO("Number of active logins: %d", active_logins); if (active_logins >= max_logins) { return -EIO; @@ -1648,6 +1649,8 @@ static void sbp2_parse_unit_directory(st } } +#define SBP2_PAYLOAD_TO_BYTES(p) (1 << ((p) + 2)) + /* * This function is called in order to determine the max speed and packet * size we can use in our ORBs. Note, that we (the driver and host) only @@ -1660,13 +1663,12 @@ static void sbp2_parse_unit_directory(st static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id) { struct sbp2scsi_host_info *hi = scsi_id->hi; + u8 payload; SBP2_DEBUG_ENTER(); - /* Initial setting comes from the hosts speed map */ scsi_id->speed_code = - hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64 + - NODEID_TO_NODE(scsi_id->ne->nodeid)]; + hi->host->speed[NODEID_TO_NODE(scsi_id->ne->nodeid)]; /* Bump down our speed if the user requested it */ if (scsi_id->speed_code > max_speed) { @@ -1677,15 +1679,22 @@ static int sbp2_max_speed_and_size(struc /* Payload size is the lesser of what our speed supports and what * our host supports. */ - scsi_id->max_payload_size = - min(sbp2_speedto_max_payload[scsi_id->speed_code], - (u8) (hi->host->csr.max_rec - 1)); + payload = min(sbp2_speedto_max_payload[scsi_id->speed_code], + (u8) (hi->host->csr.max_rec - 1)); + + /* If physical DMA is off, work around limitation in ohci1394: + * packet size must not exceed PAGE_SIZE */ + if (scsi_id->ne->host->low_addr_space < (1ULL << 32)) + while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE && + payload) + payload--; HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]", NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid), hpsb_speedto_str[scsi_id->speed_code], - 1 << ((u32) scsi_id->max_payload_size + 2)); + SBP2_PAYLOAD_TO_BYTES(payload)); + scsi_id->max_payload_size = payload; return 0; } @@ -2113,33 +2122,6 @@ static unsigned int sbp2_status_to_sense } /* - * This function is called after a command is completed, in order to do any necessary SBP-2 - * response data translations for the SCSI stack - */ -static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, - struct scsi_cmnd *SCpnt) -{ - u8 *scsi_buf = SCpnt->request_buffer; - - SBP2_DEBUG_ENTER(); - - if (SCpnt->cmnd[0] == INQUIRY && (SCpnt->cmnd[1] & 3) == 0) { - /* - * Make sure data length is ok. Minimum length is 36 bytes - */ - if (scsi_buf[4] == 0) { - scsi_buf[4] = 36 - 5; - } - - /* - * Fix ansi revision and response data format - */ - scsi_buf[2] |= 2; - scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2; - } -} - -/* * This function deals with status writes from the SBP-2 device */ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid, @@ -2478,13 +2460,6 @@ #endif } /* - * Take care of any sbp2 response data mucking here (RBC stuff, etc.) - */ - if (SCpnt->result == DID_OK << 16) { - sbp2_check_sbp2_response(scsi_id, SCpnt); - } - - /* * If a bus reset is in progress and there was an error, complete * the command as busy so that it will get retried. */ diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index f4ccc9d..b22ce1a 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -52,7 +52,7 @@ struct sbp2_command_orb { u32 data_descriptor_lo; u32 misc; u8 cdb[12]; -}; +} __attribute__((packed)); #define SBP2_LOGIN_REQUEST 0x0 #define SBP2_QUERY_LOGINS_REQUEST 0x1 @@ -80,7 +80,7 @@ struct sbp2_login_orb { u32 passwd_resp_lengths; u32 status_fifo_hi; u32 status_fifo_lo; -}; +} __attribute__((packed)); #define RESPONSE_GET_LOGIN_ID(value) (value & 0xffff) #define RESPONSE_GET_LENGTH(value) ((value >> 16) & 0xffff) @@ -91,7 +91,7 @@ struct sbp2_login_response { u32 command_block_agent_hi; u32 command_block_agent_lo; u32 reconnect_hold; -}; +} __attribute__((packed)); #define ORB_SET_LOGIN_ID(value) (value & 0xffff) @@ -106,7 +106,7 @@ struct sbp2_query_logins_orb { u32 reserved_resp_length; u32 status_fifo_hi; u32 status_fifo_lo; -}; +} __attribute__((packed)); #define RESPONSE_GET_MAX_LOGINS(value) (value & 0xffff) #define RESPONSE_GET_ACTIVE_LOGINS(value) ((RESPONSE_GET_LENGTH(value) - 4) / 12) @@ -116,7 +116,7 @@ struct sbp2_query_logins_response { u32 misc_IDs; u32 initiator_misc_hi; u32 initiator_misc_lo; -}; +} __attribute__((packed)); struct sbp2_reconnect_orb { u32 reserved1; @@ -127,7 +127,7 @@ struct sbp2_reconnect_orb { u32 reserved5; u32 status_fifo_hi; u32 status_fifo_lo; -}; +} __attribute__((packed)); struct sbp2_logout_orb { u32 reserved1; @@ -138,7 +138,7 @@ struct sbp2_logout_orb { u32 reserved5; u32 status_fifo_hi; u32 status_fifo_lo; -}; +} __attribute__((packed)); #define PAGE_TABLE_SET_SEGMENT_BASE_HI(value) (value & 0xffff) #define PAGE_TABLE_SET_SEGMENT_LENGTH(value) ((value & 0xffff) << 16) @@ -146,7 +146,7 @@ #define PAGE_TABLE_SET_SEGMENT_LENGTH(va struct sbp2_unrestricted_page_table { u32 length_segment_base_hi; u32 segment_base_lo; -}; +} __attribute__((packed)); #define RESP_STATUS_REQUEST_COMPLETE 0x0 #define RESP_STATUS_TRANSPORT_FAILURE 0x1 @@ -191,7 +191,7 @@ struct sbp2_status_block { u32 ORB_offset_hi_misc; u32 ORB_offset_lo; u8 command_set_dependent[24]; -}; +} __attribute__((packed)); /* * Miscellaneous SBP2 related config rom defines @@ -395,9 +395,8 @@ static int sbp2_link_orb_command(struct static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)); -static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data); -static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, - struct scsi_cmnd *SCpnt); +static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, + unchar *sense_data); static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, struct unit_directory *ud); static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id); diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 4e3bd62..295d0f8 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -331,7 +331,7 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, spin_lock_init(&d->lock); - PRINT(KERN_INFO, ohci->host->id, "Iso %s DMA: %d buffers " + DBGMSG(ohci->host->id, "Iso %s DMA: %d buffers " "of size %d allocated for a frame size %d, each with %d prgs", (type == OHCI_ISO_RECEIVE) ? "receive" : "transmit", d->num_desc - 1, d->buf_size, d->frame_size, d->nb_cmd); @@ -759,7 +759,7 @@ static int __video1394_ioctl(struct file } else { mask = (u64)0x1<host->id, "mask: %08X%08X usage: %08X%08X\n", + DBGMSG(ohci->host->id, "mask: %08X%08X usage: %08X%08X\n", (u32)(mask>>32),(u32)(mask&0xffffffff), (u32)(ohci->ISO_channel_usage>>32), (u32)(ohci->ISO_channel_usage&0xffffffff)); @@ -805,7 +805,7 @@ static int __video1394_ioctl(struct file v.buf_size = d->buf_size; list_add_tail(&d->link, &ctx->context_list); - PRINT(KERN_INFO, ohci->host->id, + DBGMSG(ohci->host->id, "iso context %d listen on channel %d", d->ctx, v.channel); } @@ -828,7 +828,7 @@ static int __video1394_ioctl(struct file list_add_tail(&d->link, &ctx->context_list); - PRINT(KERN_INFO, ohci->host->id, + DBGMSG(ohci->host->id, "Iso context %d talk on channel %d", d->ctx, v.channel); } @@ -873,7 +873,7 @@ static int __video1394_ioctl(struct file d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel); if (d == NULL) return -ESRCH; - PRINT(KERN_INFO, ohci->host->id, "Iso context %d " + DBGMSG(ohci->host->id, "Iso context %d " "stop talking on channel %d", d->ctx, channel); free_dma_iso_ctx(d); @@ -935,7 +935,7 @@ static int __video1394_ioctl(struct file else { /* Wake up dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - PRINT(KERN_INFO, ohci->host->id, + DBGMSG(ohci->host->id, "Waking up iso dma ctx=%d", d->ctx); reg_write(ohci, d->ctrlSet, 0x1000); } @@ -1106,7 +1106,7 @@ static int __video1394_ioctl(struct file else { /* Wake up dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - PRINT(KERN_INFO, ohci->host->id, + DBGMSG(ohci->host->id, "Waking up iso transmit dma ctx=%d", d->ctx); put_timestamp(ohci, d, d->last_buffer); @@ -1232,7 +1232,7 @@ static int video1394_release(struct inod "is not being used", d->channel); else ohci->ISO_channel_usage &= ~mask; - PRINT(KERN_INFO, ohci->host->id, "On release: Iso %s context " + DBGMSG(ohci->host->id, "On release: Iso %s context " "%d stop listening on channel %d", d->type == OHCI_ISO_RECEIVE ? "receive" : "transmit", d->ctx, d->channel); diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig index afc612b..69a53d4 100644 --- a/drivers/infiniband/Kconfig +++ b/drivers/infiniband/Kconfig @@ -29,6 +29,11 @@ config INFINIBAND_USER_ACCESS libibverbs, libibcm and a hardware driver library from . +config INFINIBAND_ADDR_TRANS + bool + depends on INFINIBAND && INET + default y + source "drivers/infiniband/hw/mthca/Kconfig" source "drivers/infiniband/hw/ipath/Kconfig" @@ -36,4 +41,6 @@ source "drivers/infiniband/ulp/ipoib/Kco source "drivers/infiniband/ulp/srp/Kconfig" +source "drivers/infiniband/ulp/iser/Kconfig" + endmenu diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile index eea2732..c7ff58c 100644 --- a/drivers/infiniband/Makefile +++ b/drivers/infiniband/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_INFINIBAND_MTHCA) += hw/mt obj-$(CONFIG_IPATH_CORE) += hw/ipath/ obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/ obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/ +obj-$(CONFIG_INFINIBAND_ISER) += ulp/iser/ diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile index ec3353f..68e73ec 100644 --- a/drivers/infiniband/core/Makefile +++ b/drivers/infiniband/core/Makefile @@ -1,5 +1,7 @@ +infiniband-$(CONFIG_INFINIBAND_ADDR_TRANS) := ib_addr.o rdma_cm.o + obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \ - ib_cm.o + ib_cm.o $(infiniband-y) obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o @@ -12,8 +14,13 @@ ib_sa-y := sa_query.o ib_cm-y := cm.o +rdma_cm-y := cma.o + +ib_addr-y := addr.o + ib_umad-y := user_mad.o ib_ucm-y := ucm.o -ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_mem.o +ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_mem.o \ + uverbs_marshall.o diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c new file mode 100644 index 0000000..d294bbc --- /dev/null +++ b/drivers/infiniband/core/addr.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2005 Voltaire Inc. All rights reserved. + * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved. + * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved. + * Copyright (c) 2005 Intel Corporation. All rights reserved. + * + * This Software is licensed under one of the following licenses: + * + * 1) under the terms of the "Common Public License 1.0" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/cpl.php. + * + * 2) under the terms of the "The BSD License" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/bsd-license.php. + * + * 3) under the terms of the "GNU General Public License (GPL) Version 2" a + * copy of which is available from the Open Source Initiative, see + * http://www.opensource.org/licenses/gpl-license.php. + * + * Licensee has the right to choose one of the above licenses. + * + * Redistributions of source code must retain the above copyright + * notice and one of the license notices. + * + * Redistributions in binary form must reproduce both the above copyright + * notice, one of the license notices in the documentation + * and/or other materials provided with the distribution. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Sean Hefty"); +MODULE_DESCRIPTION("IB Address Translation"); +MODULE_LICENSE("Dual BSD/GPL"); + +struct addr_req { + struct list_head list; + struct sockaddr src_addr; + struct sockaddr dst_addr; + struct rdma_dev_addr *addr; + void *context; + void (*callback)(int status, struct sockaddr *src_addr, + struct rdma_dev_addr *addr, void *context); + unsigned long timeout; + int status; +}; + +static void process_req(void *data); + +static DEFINE_MUTEX(lock); +static LIST_HEAD(req_list); +static DECLARE_WORK(work, process_req, NULL); +static struct workqueue_struct *addr_wq; + +static int copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, + unsigned char *dst_dev_addr) +{ + switch (dev->type) { + case ARPHRD_INFINIBAND: + dev_addr->dev_type = IB_NODE_CA; + break; + default: + return -EADDRNOTAVAIL; + } + + memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN); + memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN); + if (dst_dev_addr) + memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN); + return 0; +} + +int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) +{ + struct net_device *dev; + u32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr; + int ret; + + dev = ip_dev_find(ip); + if (!dev) + return -EADDRNOTAVAIL; + + ret = copy_addr(dev_addr, dev, NULL); + dev_put(dev); + return ret; +} +EXPORT_SYMBOL(rdma_translate_ip); + +static void set_timeout(unsigned long time) +{ + unsigned long delay; + + cancel_delayed_work(&work); + + delay = time - jiffies; + if ((long)delay <= 0) + delay = 1; + + queue_delayed_work(addr_wq, &work, delay); +} + +static void queue_req(struct addr_req *req) +{ + struct addr_req *temp_req; + + mutex_lock(&lock); + list_for_each_entry_reverse(temp_req, &req_list, list) { + if (time_after(req->timeout, temp_req->timeout)) + break; + } + + list_add(&req->list, &temp_req->list); + + if (req_list.next == &req->list) + set_timeout(req->timeout); + mutex_unlock(&lock); +} + +static void addr_send_arp(struct sockaddr_in *dst_in) +{ + struct rtable *rt; + struct flowi fl; + u32 dst_ip = dst_in->sin_addr.s_addr; + + memset(&fl, 0, sizeof fl); + fl.nl_u.ip4_u.daddr = dst_ip; + if (ip_route_output_key(&rt, &fl)) + return; + + arp_send(ARPOP_REQUEST, ETH_P_ARP, rt->rt_gateway, rt->idev->dev, + rt->rt_src, NULL, rt->idev->dev->dev_addr, NULL); + ip_rt_put(rt); +} + +static int addr_resolve_remote(struct sockaddr_in *src_in, + struct sockaddr_in *dst_in, + struct rdma_dev_addr *addr) +{ + u32 src_ip = src_in->sin_addr.s_addr; + u32 dst_ip = dst_in->sin_addr.s_addr; + struct flowi fl; + struct rtable *rt; + struct neighbour *neigh; + int ret; + + memset(&fl, 0, sizeof fl); + fl.nl_u.ip4_u.daddr = dst_ip; + fl.nl_u.ip4_u.saddr = src_ip; + ret = ip_route_output_key(&rt, &fl); + if (ret) + goto out; + + /* If the device does ARP internally, return 'done' */ + if (rt->idev->dev->flags & IFF_NOARP) { + copy_addr(addr, rt->idev->dev, NULL); + goto put; + } + + neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev); + if (!neigh) { + ret = -ENODATA; + goto put; + } + + if (!(neigh->nud_state & NUD_VALID)) { + ret = -ENODATA; + goto release; + } + + if (!src_ip) { + src_in->sin_family = dst_in->sin_family; + src_in->sin_addr.s_addr = rt->rt_src; + } + + ret = copy_addr(addr, neigh->dev, neigh->ha); +release: + neigh_release(neigh); +put: + ip_rt_put(rt); +out: + return ret; +} + +static void process_req(void *data) +{ + struct addr_req *req, *temp_req; + struct sockaddr_in *src_in, *dst_in; + struct list_head done_list; + + INIT_LIST_HEAD(&done_list); + + mutex_lock(&lock); + list_for_each_entry_safe(req, temp_req, &req_list, list) { + if (req->status) { + src_in = (struct sockaddr_in *) &req->src_addr; + dst_in = (struct sockaddr_in *) &req->dst_addr; + req->status = addr_resolve_remote(src_in, dst_in, + req->addr); + } + if (req->status && time_after(jiffies, req->timeout)) + req->status = -ETIMEDOUT; + else if (req->status == -ENODATA) + continue; + + list_del(&req->list); + list_add_tail(&req->list, &done_list); + } + + if (!list_empty(&req_list)) { + req = list_entry(req_list.next, struct addr_req, list); + set_timeout(req->timeout); + } + mutex_unlock(&lock); + + list_for_each_entry_safe(req, temp_req, &done_list, list) { + list_del(&req->list); + req->callback(req->status, &req->src_addr, req->addr, + req->context); + kfree(req); + } +} + +static int addr_resolve_local(struct sockaddr_in *src_in, + struct sockaddr_in *dst_in, + struct rdma_dev_addr *addr) +{ + struct net_device *dev; + u32 src_ip = src_in->sin_addr.s_addr; + u32 dst_ip = dst_in->sin_addr.s_addr; + int ret; + + dev = ip_dev_find(dst_ip); + if (!dev) + return -EADDRNOTAVAIL; + + if (ZERONET(src_ip)) { + src_in->sin_family = dst_in->sin_family; + src_in->sin_addr.s_addr = dst_ip; + ret = copy_addr(addr, dev, dev->dev_addr); + } else if (LOOPBACK(src_ip)) { + ret = rdma_translate_ip((struct sockaddr *)dst_in, addr); + if (!ret) + memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); + } else { + ret = rdma_translate_ip((struct sockaddr *)src_in, addr); + if (!ret) + memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); + } + + dev_put(dev); + return ret; +} + +int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, + struct rdma_dev_addr *addr, int timeout_ms, + void (*callback)(int status, struct sockaddr *src_addr, + struct rdma_dev_addr *addr, void *context), + void *context) +{ + struct sockaddr_in *src_in, *dst_in; + struct addr_req *req; + int ret = 0; + + req = kmalloc(sizeof *req, GFP_KERNEL); + if (!req) + return -ENOMEM; + memset(req, 0, sizeof *req); + + if (src_addr) + memcpy(&req->src_addr, src_addr, ip_addr_size(src_addr)); + memcpy(&req->dst_addr, dst_addr, ip_addr_size(dst_addr)); + req->addr = addr; + req->callback = callback; + req->context = context; + + src_in = (struct sockaddr_in *) &req->src_addr; + dst_in = (struct sockaddr_in *) &req->dst_addr; + + req->status = addr_resolve_local(src_in, dst_in, addr); + if (req->status == -EADDRNOTAVAIL) + req->status = addr_resolve_remote(src_in, dst_in, addr); + + switch (req->status) { + case 0: + req->timeout = jiffies; + queue_req(req); + break; + case -ENODATA: + req->timeout = msecs_to_jiffies(timeout_ms) + jiffies; + queue_req(req); + addr_send_arp(dst_in); + break; + default: + ret = req->status; + kfree(req); + break; + } + return ret; +} +EXPORT_SYMBOL(rdma_resolve_ip); + +void rdma_addr_cancel(struct rdma_dev_addr *addr) +{ + struct addr_req *req, *temp_req; + + mutex_lock(&lock); + list_for_each_entry_safe(req, temp_req, &req_list, list) { + if (req->addr == addr) { + req->status = -ECANCELED; + req->timeout = jiffies; + list_del(&req->list); + list_add(&req->list, &req_list); + set_timeout(req->timeout); + break; + } + } + mutex_unlock(&lock); +} +EXPORT_SYMBOL(rdma_addr_cancel); + +static int addr_arp_recv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pkt, struct net_device *orig_dev) +{ + struct arphdr *arp_hdr; + + arp_hdr = (struct arphdr *) skb->nh.raw; + + if (arp_hdr->ar_op == htons(ARPOP_REQUEST) || + arp_hdr->ar_op == htons(ARPOP_REPLY)) + set_timeout(jiffies); + + kfree_skb(skb); + return 0; +} + +static struct packet_type addr_arp = { + .type = __constant_htons(ETH_P_ARP), + .func = addr_arp_recv, + .af_packet_priv = (void*) 1, +}; + +static int addr_init(void) +{ + addr_wq = create_singlethread_workqueue("ib_addr_wq"); + if (!addr_wq) + return -ENOMEM; + + dev_add_pack(&addr_arp); + return 0; +} + +static void addr_cleanup(void) +{ + dev_remove_pack(&addr_arp); + destroy_workqueue(addr_wq); +} + +module_init(addr_init); +module_exit(addr_cleanup); diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 50364c0..e05ca2c 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -191,6 +191,24 @@ int ib_find_cached_pkey(struct ib_device } EXPORT_SYMBOL(ib_find_cached_pkey); +int ib_get_cached_lmc(struct ib_device *device, + u8 port_num, + u8 *lmc) +{ + unsigned long flags; + int ret = 0; + + if (port_num < start_port(device) || port_num > end_port(device)) + return -EINVAL; + + read_lock_irqsave(&device->cache.lock, flags); + *lmc = device->cache.lmc_cache[port_num - start_port(device)]; + read_unlock_irqrestore(&device->cache.lock, flags); + + return ret; +} +EXPORT_SYMBOL(ib_get_cached_lmc); + static void ib_cache_update(struct ib_device *device, u8 port) { @@ -251,6 +269,8 @@ static void ib_cache_update(struct ib_de device->cache.pkey_cache[port - start_port(device)] = pkey_cache; device->cache.gid_cache [port - start_port(device)] = gid_cache; + device->cache.lmc_cache[port - start_port(device)] = tprops->lmc; + write_unlock_irq(&device->cache.lock); kfree(old_pkey_cache); @@ -305,7 +325,13 @@ static void ib_cache_setup_one(struct ib kmalloc(sizeof *device->cache.gid_cache * (end_port(device) - start_port(device) + 1), GFP_KERNEL); - if (!device->cache.pkey_cache || !device->cache.gid_cache) { + device->cache.lmc_cache = kmalloc(sizeof *device->cache.lmc_cache * + (end_port(device) - + start_port(device) + 1), + GFP_KERNEL); + + if (!device->cache.pkey_cache || !device->cache.gid_cache || + !device->cache.lmc_cache) { printk(KERN_WARNING "Couldn't allocate cache " "for %s\n", device->name); goto err; @@ -333,6 +359,7 @@ err_cache: err: kfree(device->cache.pkey_cache); kfree(device->cache.gid_cache); + kfree(device->cache.lmc_cache); } static void ib_cache_cleanup_one(struct ib_device *device) @@ -349,6 +376,7 @@ static void ib_cache_cleanup_one(struct kfree(device->cache.pkey_cache); kfree(device->cache.gid_cache); + kfree(device->cache.lmc_cache); } static struct ib_client cache_client = { diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 86fee43..450adfe 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -32,7 +32,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id: cm.c 2821 2005-07-08 17:07:28Z sean.hefty $ + * $Id: cm.c 4311 2005-12-05 18:42:01Z sean.hefty $ */ #include @@ -132,6 +132,7 @@ struct cm_id_private { /* todo: use alternate port on send failure */ struct cm_av av; struct cm_av alt_av; + struct ib_cm_compare_data *compare_data; void *private_data; __be64 tid; @@ -253,23 +254,13 @@ static void cm_set_private_data(struct c cm_id_priv->private_data_len = private_data_len; } -static void cm_set_ah_attr(struct ib_ah_attr *ah_attr, u8 port_num, - u16 dlid, u8 sl, u16 src_path_bits) -{ - memset(ah_attr, 0, sizeof ah_attr); - ah_attr->dlid = dlid; - ah_attr->sl = sl; - ah_attr->src_path_bits = src_path_bits; - ah_attr->port_num = port_num; -} - -static void cm_init_av_for_response(struct cm_port *port, - struct ib_wc *wc, struct cm_av *av) +static void cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc, + struct ib_grh *grh, struct cm_av *av) { av->port = port; av->pkey_index = wc->pkey_index; - cm_set_ah_attr(&av->ah_attr, port->port_num, wc->slid, - wc->sl, wc->dlid_path_bits); + ib_init_ah_from_wc(port->cm_dev->device, port->port_num, wc, + grh, &av->ah_attr); } static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av) @@ -299,9 +290,8 @@ static int cm_init_av_by_path(struct ib_ return ret; av->port = port; - cm_set_ah_attr(&av->ah_attr, av->port->port_num, - be16_to_cpu(path->dlid), path->sl, - be16_to_cpu(path->slid) & 0x7F); + ib_init_ah_from_path(cm_dev->device, port->port_num, path, + &av->ah_attr); av->packet_life_time = path->packet_life_time; return 0; } @@ -357,6 +347,41 @@ static struct cm_id_private * cm_acquire return cm_id_priv; } +static void cm_mask_copy(u8 *dst, u8 *src, u8 *mask) +{ + int i; + + for (i = 0; i < IB_CM_COMPARE_SIZE / sizeof(unsigned long); i++) + ((unsigned long *) dst)[i] = ((unsigned long *) src)[i] & + ((unsigned long *) mask)[i]; +} + +static int cm_compare_data(struct ib_cm_compare_data *src_data, + struct ib_cm_compare_data *dst_data) +{ + u8 src[IB_CM_COMPARE_SIZE]; + u8 dst[IB_CM_COMPARE_SIZE]; + + if (!src_data || !dst_data) + return 0; + + cm_mask_copy(src, src_data->data, dst_data->mask); + cm_mask_copy(dst, dst_data->data, src_data->mask); + return memcmp(src, dst, IB_CM_COMPARE_SIZE); +} + +static int cm_compare_private_data(u8 *private_data, + struct ib_cm_compare_data *dst_data) +{ + u8 src[IB_CM_COMPARE_SIZE]; + + if (!dst_data) + return 0; + + cm_mask_copy(src, private_data, dst_data->mask); + return memcmp(src, dst_data->data, IB_CM_COMPARE_SIZE); +} + static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv) { struct rb_node **link = &cm.listen_service_table.rb_node; @@ -364,14 +389,18 @@ static struct cm_id_private * cm_insert_ struct cm_id_private *cur_cm_id_priv; __be64 service_id = cm_id_priv->id.service_id; __be64 service_mask = cm_id_priv->id.service_mask; + int data_cmp; while (*link) { parent = *link; cur_cm_id_priv = rb_entry(parent, struct cm_id_private, service_node); + data_cmp = cm_compare_data(cm_id_priv->compare_data, + cur_cm_id_priv->compare_data); if ((cur_cm_id_priv->id.service_mask & service_id) == (service_mask & cur_cm_id_priv->id.service_id) && - (cm_id_priv->id.device == cur_cm_id_priv->id.device)) + (cm_id_priv->id.device == cur_cm_id_priv->id.device) && + !data_cmp) return cur_cm_id_priv; if (cm_id_priv->id.device < cur_cm_id_priv->id.device) @@ -380,6 +409,10 @@ static struct cm_id_private * cm_insert_ link = &(*link)->rb_right; else if (service_id < cur_cm_id_priv->id.service_id) link = &(*link)->rb_left; + else if (service_id > cur_cm_id_priv->id.service_id) + link = &(*link)->rb_right; + else if (data_cmp < 0) + link = &(*link)->rb_left; else link = &(*link)->rb_right; } @@ -389,16 +422,20 @@ static struct cm_id_private * cm_insert_ } static struct cm_id_private * cm_find_listen(struct ib_device *device, - __be64 service_id) + __be64 service_id, + u8 *private_data) { struct rb_node *node = cm.listen_service_table.rb_node; struct cm_id_private *cm_id_priv; + int data_cmp; while (node) { cm_id_priv = rb_entry(node, struct cm_id_private, service_node); + data_cmp = cm_compare_private_data(private_data, + cm_id_priv->compare_data); if ((cm_id_priv->id.service_mask & service_id) == cm_id_priv->id.service_id && - (cm_id_priv->id.device == device)) + (cm_id_priv->id.device == device) && !data_cmp) return cm_id_priv; if (device < cm_id_priv->id.device) @@ -407,6 +444,10 @@ static struct cm_id_private * cm_find_li node = node->rb_right; else if (service_id < cm_id_priv->id.service_id) node = node->rb_left; + else if (service_id > cm_id_priv->id.service_id) + node = node->rb_right; + else if (data_cmp < 0) + node = node->rb_left; else node = node->rb_right; } @@ -730,15 +771,14 @@ retest: wait_for_completion(&cm_id_priv->comp); while ((work = cm_dequeue_work(cm_id_priv)) != NULL) cm_free_work(work); - if (cm_id_priv->private_data && cm_id_priv->private_data_len) - kfree(cm_id_priv->private_data); + kfree(cm_id_priv->compare_data); + kfree(cm_id_priv->private_data); kfree(cm_id_priv); } EXPORT_SYMBOL(ib_destroy_cm_id); -int ib_cm_listen(struct ib_cm_id *cm_id, - __be64 service_id, - __be64 service_mask) +int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask, + struct ib_cm_compare_data *compare_data) { struct cm_id_private *cm_id_priv, *cur_cm_id_priv; unsigned long flags; @@ -752,7 +792,19 @@ int ib_cm_listen(struct ib_cm_id *cm_id, return -EINVAL; cm_id_priv = container_of(cm_id, struct cm_id_private, id); - BUG_ON(cm_id->state != IB_CM_IDLE); + if (cm_id->state != IB_CM_IDLE) + return -EINVAL; + + if (compare_data) { + cm_id_priv->compare_data = kzalloc(sizeof *compare_data, + GFP_KERNEL); + if (!cm_id_priv->compare_data) + return -ENOMEM; + cm_mask_copy(cm_id_priv->compare_data->data, + compare_data->data, compare_data->mask); + memcpy(cm_id_priv->compare_data->mask, compare_data->mask, + IB_CM_COMPARE_SIZE); + } cm_id->state = IB_CM_LISTEN; @@ -769,6 +821,8 @@ int ib_cm_listen(struct ib_cm_id *cm_id, if (cur_cm_id_priv) { cm_id->state = IB_CM_IDLE; + kfree(cm_id_priv->compare_data); + cm_id_priv->compare_data = NULL; ret = -EBUSY; } return ret; @@ -1241,7 +1295,8 @@ static struct cm_id_private * cm_match_r /* Find matching listen request. */ listen_cm_id_priv = cm_find_listen(cm_id_priv->id.device, - req_msg->service_id); + req_msg->service_id, + req_msg->private_data); if (!listen_cm_id_priv) { spin_unlock_irqrestore(&cm.lock, flags); cm_issue_rej(work->port, work->mad_recv_wc, @@ -1276,6 +1331,7 @@ static int cm_req_handler(struct cm_work cm_id_priv = container_of(cm_id, struct cm_id_private, id); cm_id_priv->id.remote_id = req_msg->local_comm_id; cm_init_av_for_response(work->port, work->mad_recv_wc->wc, + work->mad_recv_wc->recv_buf.grh, &cm_id_priv->av); cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv-> id.local_id); @@ -2549,7 +2605,7 @@ static void cm_format_sidr_req(struct cm cm_format_mad_hdr(&sidr_req_msg->hdr, CM_SIDR_REQ_ATTR_ID, cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_SIDR)); sidr_req_msg->request_id = cm_id_priv->id.local_id; - sidr_req_msg->pkey = cpu_to_be16(param->pkey); + sidr_req_msg->pkey = cpu_to_be16(param->path->pkey); sidr_req_msg->service_id = param->service_id; if (param->private_data && param->private_data_len) @@ -2641,6 +2697,7 @@ static int cm_sidr_req_handler(struct cm cm_id_priv->av.dgid.global.subnet_prefix = cpu_to_be64(wc->slid); cm_id_priv->av.dgid.global.interface_id = 0; cm_init_av_for_response(work->port, work->mad_recv_wc->wc, + work->mad_recv_wc->recv_buf.grh, &cm_id_priv->av); cm_id_priv->id.remote_id = sidr_req_msg->request_id; cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD; @@ -2654,7 +2711,8 @@ static int cm_sidr_req_handler(struct cm goto out; /* Duplicate message. */ } cur_cm_id_priv = cm_find_listen(cm_id->device, - sidr_req_msg->service_id); + sidr_req_msg->service_id, + sidr_req_msg->private_data); if (!cur_cm_id_priv) { rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table); spin_unlock_irqrestore(&cm.lock, flags); @@ -3291,7 +3349,6 @@ error: static void __exit ib_cm_cleanup(void) { - flush_workqueue(cm.wq); destroy_workqueue(cm.wq); ib_unregister_client(&cm_client); idr_destroy(&cm.local_id_table); diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c new file mode 100644 index 0000000..863f64b --- /dev/null +++ b/drivers/infiniband/core/cma.c @@ -0,0 +1,1927 @@ +/* + * Copyright (c) 2005 Voltaire Inc. All rights reserved. + * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved. + * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved. + * Copyright (c) 2005-2006 Intel Corporation. All rights reserved. + * + * This Software is licensed under one of the following licenses: + * + * 1) under the terms of the "Common Public License 1.0" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/cpl.php. + * + * 2) under the terms of the "The BSD License" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/bsd-license.php. + * + * 3) under the terms of the "GNU General Public License (GPL) Version 2" a + * copy of which is available from the Open Source Initiative, see + * http://www.opensource.org/licenses/gpl-license.php. + * + * Licensee has the right to choose one of the above licenses. + * + * Redistributions of source code must retain the above copyright + * notice and one of the license notices. + * + * Redistributions in binary form must reproduce both the above copyright + * notice, one of the license notices in the documentation + * and/or other materials provided with the distribution. + * + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Sean Hefty"); +MODULE_DESCRIPTION("Generic RDMA CM Agent"); +MODULE_LICENSE("Dual BSD/GPL"); + +#define CMA_CM_RESPONSE_TIMEOUT 20 +#define CMA_MAX_CM_RETRIES 3 + +static void cma_add_one(struct ib_device *device); +static void cma_remove_one(struct ib_device *device); + +static struct ib_client cma_client = { + .name = "cma", + .add = cma_add_one, + .remove = cma_remove_one +}; + +static LIST_HEAD(dev_list); +static LIST_HEAD(listen_any_list); +static DEFINE_MUTEX(lock); +static struct workqueue_struct *cma_wq; +static DEFINE_IDR(sdp_ps); +static DEFINE_IDR(tcp_ps); + +struct cma_device { + struct list_head list; + struct ib_device *device; + __be64 node_guid; + struct completion comp; + atomic_t refcount; + struct list_head id_list; +}; + +enum cma_state { + CMA_IDLE, + CMA_ADDR_QUERY, + CMA_ADDR_RESOLVED, + CMA_ROUTE_QUERY, + CMA_ROUTE_RESOLVED, + CMA_CONNECT, + CMA_DISCONNECT, + CMA_ADDR_BOUND, + CMA_LISTEN, + CMA_DEVICE_REMOVAL, + CMA_DESTROYING +}; + +struct rdma_bind_list { + struct idr *ps; + struct hlist_head owners; + unsigned short port; +}; + +/* + * Device removal can occur at anytime, so we need extra handling to + * serialize notifying the user of device removal with other callbacks. + * We do this by disabling removal notification while a callback is in process, + * and reporting it after the callback completes. + */ +struct rdma_id_private { + struct rdma_cm_id id; + + struct rdma_bind_list *bind_list; + struct hlist_node node; + struct list_head list; + struct list_head listen_list; + struct cma_device *cma_dev; + + enum cma_state state; + spinlock_t lock; + struct completion comp; + atomic_t refcount; + wait_queue_head_t wait_remove; + atomic_t dev_remove; + + int backlog; + int timeout_ms; + struct ib_sa_query *query; + int query_id; + union { + struct ib_cm_id *ib; + } cm_id; + + u32 seq_num; + u32 qp_num; + enum ib_qp_type qp_type; + u8 srq; +}; + +struct cma_work { + struct work_struct work; + struct rdma_id_private *id; + enum cma_state old_state; + enum cma_state new_state; + struct rdma_cm_event event; +}; + +union cma_ip_addr { + struct in6_addr ip6; + struct { + __u32 pad[3]; + __u32 addr; + } ip4; +}; + +struct cma_hdr { + u8 cma_version; + u8 ip_version; /* IP version: 7:4 */ + __u16 port; + union cma_ip_addr src_addr; + union cma_ip_addr dst_addr; +}; + +struct sdp_hh { + u8 bsdh[16]; + u8 sdp_version; /* Major version: 7:4 */ + u8 ip_version; /* IP version: 7:4 */ + u8 sdp_specific1[10]; + __u16 port; + __u16 sdp_specific2; + union cma_ip_addr src_addr; + union cma_ip_addr dst_addr; +}; + +struct sdp_hah { + u8 bsdh[16]; + u8 sdp_version; +}; + +#define CMA_VERSION 0x00 +#define SDP_MAJ_VERSION 0x2 + +static int cma_comp(struct rdma_id_private *id_priv, enum cma_state comp) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&id_priv->lock, flags); + ret = (id_priv->state == comp); + spin_unlock_irqrestore(&id_priv->lock, flags); + return ret; +} + +static int cma_comp_exch(struct rdma_id_private *id_priv, + enum cma_state comp, enum cma_state exch) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&id_priv->lock, flags); + if ((ret = (id_priv->state == comp))) + id_priv->state = exch; + spin_unlock_irqrestore(&id_priv->lock, flags); + return ret; +} + +static enum cma_state cma_exch(struct rdma_id_private *id_priv, + enum cma_state exch) +{ + unsigned long flags; + enum cma_state old; + + spin_lock_irqsave(&id_priv->lock, flags); + old = id_priv->state; + id_priv->state = exch; + spin_unlock_irqrestore(&id_priv->lock, flags); + return old; +} + +static inline u8 cma_get_ip_ver(struct cma_hdr *hdr) +{ + return hdr->ip_version >> 4; +} + +static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver) +{ + hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF); +} + +static inline u8 sdp_get_majv(u8 sdp_version) +{ + return sdp_version >> 4; +} + +static inline u8 sdp_get_ip_ver(struct sdp_hh *hh) +{ + return hh->ip_version >> 4; +} + +static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver) +{ + hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF); +} + +static void cma_attach_to_dev(struct rdma_id_private *id_priv, + struct cma_device *cma_dev) +{ + atomic_inc(&cma_dev->refcount); + id_priv->cma_dev = cma_dev; + id_priv->id.device = cma_dev->device; + list_add_tail(&id_priv->list, &cma_dev->id_list); +} + +static inline void cma_deref_dev(struct cma_device *cma_dev) +{ + if (atomic_dec_and_test(&cma_dev->refcount)) + complete(&cma_dev->comp); +} + +static void cma_detach_from_dev(struct rdma_id_private *id_priv) +{ + list_del(&id_priv->list); + cma_deref_dev(id_priv->cma_dev); + id_priv->cma_dev = NULL; +} + +static int cma_acquire_ib_dev(struct rdma_id_private *id_priv) +{ + struct cma_device *cma_dev; + union ib_gid *gid; + int ret = -ENODEV; + + gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr); + + mutex_lock(&lock); + list_for_each_entry(cma_dev, &dev_list, list) { + ret = ib_find_cached_gid(cma_dev->device, gid, + &id_priv->id.port_num, NULL); + if (!ret) { + cma_attach_to_dev(id_priv, cma_dev); + break; + } + } + mutex_unlock(&lock); + return ret; +} + +static int cma_acquire_dev(struct rdma_id_private *id_priv) +{ + switch (id_priv->id.route.addr.dev_addr.dev_type) { + case IB_NODE_CA: + return cma_acquire_ib_dev(id_priv); + default: + return -ENODEV; + } +} + +static void cma_deref_id(struct rdma_id_private *id_priv) +{ + if (atomic_dec_and_test(&id_priv->refcount)) + complete(&id_priv->comp); +} + +static void cma_release_remove(struct rdma_id_private *id_priv) +{ + if (atomic_dec_and_test(&id_priv->dev_remove)) + wake_up(&id_priv->wait_remove); +} + +struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler, + void *context, enum rdma_port_space ps) +{ + struct rdma_id_private *id_priv; + + id_priv = kzalloc(sizeof *id_priv, GFP_KERNEL); + if (!id_priv) + return ERR_PTR(-ENOMEM); + + id_priv->state = CMA_IDLE; + id_priv->id.context = context; + id_priv->id.event_handler = event_handler; + id_priv->id.ps = ps; + spin_lock_init(&id_priv->lock); + init_completion(&id_priv->comp); + atomic_set(&id_priv->refcount, 1); + init_waitqueue_head(&id_priv->wait_remove); + atomic_set(&id_priv->dev_remove, 0); + INIT_LIST_HEAD(&id_priv->listen_list); + get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num); + + return &id_priv->id; +} +EXPORT_SYMBOL(rdma_create_id); + +static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp) +{ + struct ib_qp_attr qp_attr; + struct rdma_dev_addr *dev_addr; + int ret; + + dev_addr = &id_priv->id.route.addr.dev_addr; + ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num, + ib_addr_get_pkey(dev_addr), + &qp_attr.pkey_index); + if (ret) + return ret; + + qp_attr.qp_state = IB_QPS_INIT; + qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE; + qp_attr.port_num = id_priv->id.port_num; + return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX | IB_QP_PORT); +} + +int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd, + struct ib_qp_init_attr *qp_init_attr) +{ + struct rdma_id_private *id_priv; + struct ib_qp *qp; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (id->device != pd->device) + return -EINVAL; + + qp = ib_create_qp(pd, qp_init_attr); + if (IS_ERR(qp)) + return PTR_ERR(qp); + + switch (id->device->node_type) { + case IB_NODE_CA: + ret = cma_init_ib_qp(id_priv, qp); + break; + default: + ret = -ENOSYS; + break; + } + + if (ret) + goto err; + + id->qp = qp; + id_priv->qp_num = qp->qp_num; + id_priv->qp_type = qp->qp_type; + id_priv->srq = (qp->srq != NULL); + return 0; +err: + ib_destroy_qp(qp); + return ret; +} +EXPORT_SYMBOL(rdma_create_qp); + +void rdma_destroy_qp(struct rdma_cm_id *id) +{ + ib_destroy_qp(id->qp); +} +EXPORT_SYMBOL(rdma_destroy_qp); + +static int cma_modify_qp_rtr(struct rdma_cm_id *id) +{ + struct ib_qp_attr qp_attr; + int qp_attr_mask, ret; + + if (!id->qp) + return 0; + + /* Need to update QP attributes from default values. */ + qp_attr.qp_state = IB_QPS_INIT; + ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask); + if (ret) + return ret; + + ret = ib_modify_qp(id->qp, &qp_attr, qp_attr_mask); + if (ret) + return ret; + + qp_attr.qp_state = IB_QPS_RTR; + ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask); + if (ret) + return ret; + + return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask); +} + +static int cma_modify_qp_rts(struct rdma_cm_id *id) +{ + struct ib_qp_attr qp_attr; + int qp_attr_mask, ret; + + if (!id->qp) + return 0; + + qp_attr.qp_state = IB_QPS_RTS; + ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask); + if (ret) + return ret; + + return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask); +} + +static int cma_modify_qp_err(struct rdma_cm_id *id) +{ + struct ib_qp_attr qp_attr; + + if (!id->qp) + return 0; + + qp_attr.qp_state = IB_QPS_ERR; + return ib_modify_qp(id->qp, &qp_attr, IB_QP_STATE); +} + +int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr, + int *qp_attr_mask) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + switch (id_priv->id.device->node_type) { + case IB_NODE_CA: + ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr, + qp_attr_mask); + if (qp_attr->qp_state == IB_QPS_RTR) + qp_attr->rq_psn = id_priv->seq_num; + break; + default: + ret = -ENOSYS; + break; + } + + return ret; +} +EXPORT_SYMBOL(rdma_init_qp_attr); + +static inline int cma_zero_addr(struct sockaddr *addr) +{ + struct in6_addr *ip6; + + if (addr->sa_family == AF_INET) + return ZERONET(((struct sockaddr_in *) addr)->sin_addr.s_addr); + else { + ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr; + return (ip6->s6_addr32[0] | ip6->s6_addr32[1] | + ip6->s6_addr32[2] | ip6->s6_addr32[3]) == 0; + } +} + +static inline int cma_loopback_addr(struct sockaddr *addr) +{ + return LOOPBACK(((struct sockaddr_in *) addr)->sin_addr.s_addr); +} + +static inline int cma_any_addr(struct sockaddr *addr) +{ + return cma_zero_addr(addr) || cma_loopback_addr(addr); +} + +static inline int cma_any_port(struct sockaddr *addr) +{ + return !((struct sockaddr_in *) addr)->sin_port; +} + +static int cma_get_net_info(void *hdr, enum rdma_port_space ps, + u8 *ip_ver, __u16 *port, + union cma_ip_addr **src, union cma_ip_addr **dst) +{ + switch (ps) { + case RDMA_PS_SDP: + if (sdp_get_majv(((struct sdp_hh *) hdr)->sdp_version) != + SDP_MAJ_VERSION) + return -EINVAL; + + *ip_ver = sdp_get_ip_ver(hdr); + *port = ((struct sdp_hh *) hdr)->port; + *src = &((struct sdp_hh *) hdr)->src_addr; + *dst = &((struct sdp_hh *) hdr)->dst_addr; + break; + default: + if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION) + return -EINVAL; + + *ip_ver = cma_get_ip_ver(hdr); + *port = ((struct cma_hdr *) hdr)->port; + *src = &((struct cma_hdr *) hdr)->src_addr; + *dst = &((struct cma_hdr *) hdr)->dst_addr; + break; + } + + if (*ip_ver != 4 && *ip_ver != 6) + return -EINVAL; + return 0; +} + +static void cma_save_net_info(struct rdma_addr *addr, + struct rdma_addr *listen_addr, + u8 ip_ver, __u16 port, + union cma_ip_addr *src, union cma_ip_addr *dst) +{ + struct sockaddr_in *listen4, *ip4; + struct sockaddr_in6 *listen6, *ip6; + + switch (ip_ver) { + case 4: + listen4 = (struct sockaddr_in *) &listen_addr->src_addr; + ip4 = (struct sockaddr_in *) &addr->src_addr; + ip4->sin_family = listen4->sin_family; + ip4->sin_addr.s_addr = dst->ip4.addr; + ip4->sin_port = listen4->sin_port; + + ip4 = (struct sockaddr_in *) &addr->dst_addr; + ip4->sin_family = listen4->sin_family; + ip4->sin_addr.s_addr = src->ip4.addr; + ip4->sin_port = port; + break; + case 6: + listen6 = (struct sockaddr_in6 *) &listen_addr->src_addr; + ip6 = (struct sockaddr_in6 *) &addr->src_addr; + ip6->sin6_family = listen6->sin6_family; + ip6->sin6_addr = dst->ip6; + ip6->sin6_port = listen6->sin6_port; + + ip6 = (struct sockaddr_in6 *) &addr->dst_addr; + ip6->sin6_family = listen6->sin6_family; + ip6->sin6_addr = src->ip6; + ip6->sin6_port = port; + break; + default: + break; + } +} + +static inline int cma_user_data_offset(enum rdma_port_space ps) +{ + switch (ps) { + case RDMA_PS_SDP: + return 0; + default: + return sizeof(struct cma_hdr); + } +} + +static int cma_notify_user(struct rdma_id_private *id_priv, + enum rdma_cm_event_type type, int status, + void *data, u8 data_len) +{ + struct rdma_cm_event event; + + event.event = type; + event.status = status; + event.private_data = data; + event.private_data_len = data_len; + + return id_priv->id.event_handler(&id_priv->id, &event); +} + +static void cma_cancel_route(struct rdma_id_private *id_priv) +{ + switch (id_priv->id.device->node_type) { + case IB_NODE_CA: + if (id_priv->query) + ib_sa_cancel_query(id_priv->query_id, id_priv->query); + break; + default: + break; + } +} + +static inline int cma_internal_listen(struct rdma_id_private *id_priv) +{ + return (id_priv->state == CMA_LISTEN) && id_priv->cma_dev && + cma_any_addr(&id_priv->id.route.addr.src_addr); +} + +static void cma_destroy_listen(struct rdma_id_private *id_priv) +{ + cma_exch(id_priv, CMA_DESTROYING); + + if (id_priv->cma_dev) { + switch (id_priv->id.device->node_type) { + case IB_NODE_CA: + if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib)) + ib_destroy_cm_id(id_priv->cm_id.ib); + break; + default: + break; + } + cma_detach_from_dev(id_priv); + } + list_del(&id_priv->listen_list); + + cma_deref_id(id_priv); + wait_for_completion(&id_priv->comp); + + kfree(id_priv); +} + +static void cma_cancel_listens(struct rdma_id_private *id_priv) +{ + struct rdma_id_private *dev_id_priv; + + mutex_lock(&lock); + list_del(&id_priv->list); + + while (!list_empty(&id_priv->listen_list)) { + dev_id_priv = list_entry(id_priv->listen_list.next, + struct rdma_id_private, listen_list); + cma_destroy_listen(dev_id_priv); + } + mutex_unlock(&lock); +} + +static void cma_cancel_operation(struct rdma_id_private *id_priv, + enum cma_state state) +{ + switch (state) { + case CMA_ADDR_QUERY: + rdma_addr_cancel(&id_priv->id.route.addr.dev_addr); + break; + case CMA_ROUTE_QUERY: + cma_cancel_route(id_priv); + break; + case CMA_LISTEN: + if (cma_any_addr(&id_priv->id.route.addr.src_addr) && + !id_priv->cma_dev) + cma_cancel_listens(id_priv); + break; + default: + break; + } +} + +static void cma_release_port(struct rdma_id_private *id_priv) +{ + struct rdma_bind_list *bind_list = id_priv->bind_list; + + if (!bind_list) + return; + + mutex_lock(&lock); + hlist_del(&id_priv->node); + if (hlist_empty(&bind_list->owners)) { + idr_remove(bind_list->ps, bind_list->port); + kfree(bind_list); + } + mutex_unlock(&lock); +} + +void rdma_destroy_id(struct rdma_cm_id *id) +{ + struct rdma_id_private *id_priv; + enum cma_state state; + + id_priv = container_of(id, struct rdma_id_private, id); + state = cma_exch(id_priv, CMA_DESTROYING); + cma_cancel_operation(id_priv, state); + + if (id_priv->cma_dev) { + switch (id->device->node_type) { + case IB_NODE_CA: + if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib)) + ib_destroy_cm_id(id_priv->cm_id.ib); + break; + default: + break; + } + mutex_lock(&lock); + cma_detach_from_dev(id_priv); + mutex_unlock(&lock); + } + + cma_release_port(id_priv); + cma_deref_id(id_priv); + wait_for_completion(&id_priv->comp); + + kfree(id_priv->id.route.path_rec); + kfree(id_priv); +} +EXPORT_SYMBOL(rdma_destroy_id); + +static int cma_rep_recv(struct rdma_id_private *id_priv) +{ + int ret; + + ret = cma_modify_qp_rtr(&id_priv->id); + if (ret) + goto reject; + + ret = cma_modify_qp_rts(&id_priv->id); + if (ret) + goto reject; + + ret = ib_send_cm_rtu(id_priv->cm_id.ib, NULL, 0); + if (ret) + goto reject; + + return 0; +reject: + cma_modify_qp_err(&id_priv->id); + ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED, + NULL, 0, NULL, 0); + return ret; +} + +static int cma_verify_rep(struct rdma_id_private *id_priv, void *data) +{ + if (id_priv->id.ps == RDMA_PS_SDP && + sdp_get_majv(((struct sdp_hah *) data)->sdp_version) != + SDP_MAJ_VERSION) + return -EINVAL; + + return 0; +} + +static int cma_rtu_recv(struct rdma_id_private *id_priv) +{ + int ret; + + ret = cma_modify_qp_rts(&id_priv->id); + if (ret) + goto reject; + + return 0; +reject: + cma_modify_qp_err(&id_priv->id); + ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED, + NULL, 0, NULL, 0); + return ret; +} + +static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) +{ + struct rdma_id_private *id_priv = cm_id->context; + enum rdma_cm_event_type event; + u8 private_data_len = 0; + int ret = 0, status = 0; + + atomic_inc(&id_priv->dev_remove); + if (!cma_comp(id_priv, CMA_CONNECT)) + goto out; + + switch (ib_event->event) { + case IB_CM_REQ_ERROR: + case IB_CM_REP_ERROR: + event = RDMA_CM_EVENT_UNREACHABLE; + status = -ETIMEDOUT; + break; + case IB_CM_REP_RECEIVED: + status = cma_verify_rep(id_priv, ib_event->private_data); + if (status) + event = RDMA_CM_EVENT_CONNECT_ERROR; + else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) { + status = cma_rep_recv(id_priv); + event = status ? RDMA_CM_EVENT_CONNECT_ERROR : + RDMA_CM_EVENT_ESTABLISHED; + } else + event = RDMA_CM_EVENT_CONNECT_RESPONSE; + private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE; + break; + case IB_CM_RTU_RECEIVED: + status = cma_rtu_recv(id_priv); + event = status ? RDMA_CM_EVENT_CONNECT_ERROR : + RDMA_CM_EVENT_ESTABLISHED; + break; + case IB_CM_DREQ_ERROR: + status = -ETIMEDOUT; /* fall through */ + case IB_CM_DREQ_RECEIVED: + case IB_CM_DREP_RECEIVED: + if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT)) + goto out; + event = RDMA_CM_EVENT_DISCONNECTED; + break; + case IB_CM_TIMEWAIT_EXIT: + case IB_CM_MRA_RECEIVED: + /* ignore event */ + goto out; + case IB_CM_REJ_RECEIVED: + cma_modify_qp_err(&id_priv->id); + status = ib_event->param.rej_rcvd.reason; + event = RDMA_CM_EVENT_REJECTED; + break; + default: + printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d", + ib_event->event); + goto out; + } + + ret = cma_notify_user(id_priv, event, status, ib_event->private_data, + private_data_len); + if (ret) { + /* Destroy the CM ID by returning a non-zero value. */ + id_priv->cm_id.ib = NULL; + cma_exch(id_priv, CMA_DESTROYING); + cma_release_remove(id_priv); + rdma_destroy_id(&id_priv->id); + return ret; + } +out: + cma_release_remove(id_priv); + return ret; +} + +static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id, + struct ib_cm_event *ib_event) +{ + struct rdma_id_private *id_priv; + struct rdma_cm_id *id; + struct rdma_route *rt; + union cma_ip_addr *src, *dst; + __u16 port; + u8 ip_ver; + + id = rdma_create_id(listen_id->event_handler, listen_id->context, + listen_id->ps); + if (IS_ERR(id)) + return NULL; + + rt = &id->route; + rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1; + rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths, GFP_KERNEL); + if (!rt->path_rec) + goto err; + + if (cma_get_net_info(ib_event->private_data, listen_id->ps, + &ip_ver, &port, &src, &dst)) + goto err; + + cma_save_net_info(&id->route.addr, &listen_id->route.addr, + ip_ver, port, src, dst); + rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path; + if (rt->num_paths == 2) + rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path; + + ib_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid); + ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid); + ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey)); + rt->addr.dev_addr.dev_type = IB_NODE_CA; + + id_priv = container_of(id, struct rdma_id_private, id); + id_priv->state = CMA_CONNECT; + return id_priv; +err: + rdma_destroy_id(id); + return NULL; +} + +static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) +{ + struct rdma_id_private *listen_id, *conn_id; + int offset, ret; + + listen_id = cm_id->context; + atomic_inc(&listen_id->dev_remove); + if (!cma_comp(listen_id, CMA_LISTEN)) { + ret = -ECONNABORTED; + goto out; + } + + conn_id = cma_new_id(&listen_id->id, ib_event); + if (!conn_id) { + ret = -ENOMEM; + goto out; + } + + atomic_inc(&conn_id->dev_remove); + ret = cma_acquire_ib_dev(conn_id); + if (ret) { + ret = -ENODEV; + cma_release_remove(conn_id); + rdma_destroy_id(&conn_id->id); + goto out; + } + + conn_id->cm_id.ib = cm_id; + cm_id->context = conn_id; + cm_id->cm_handler = cma_ib_handler; + + offset = cma_user_data_offset(listen_id->id.ps); + ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0, + ib_event->private_data + offset, + IB_CM_REQ_PRIVATE_DATA_SIZE - offset); + if (ret) { + /* Destroy the CM ID by returning a non-zero value. */ + conn_id->cm_id.ib = NULL; + cma_exch(conn_id, CMA_DESTROYING); + cma_release_remove(conn_id); + rdma_destroy_id(&conn_id->id); + } +out: + cma_release_remove(listen_id); + return ret; +} + +static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr) +{ + return cpu_to_be64(((u64)ps << 16) + + be16_to_cpu(((struct sockaddr_in *) addr)->sin_port)); +} + +static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr, + struct ib_cm_compare_data *compare) +{ + struct cma_hdr *cma_data, *cma_mask; + struct sdp_hh *sdp_data, *sdp_mask; + __u32 ip4_addr; + struct in6_addr ip6_addr; + + memset(compare, 0, sizeof *compare); + cma_data = (void *) compare->data; + cma_mask = (void *) compare->mask; + sdp_data = (void *) compare->data; + sdp_mask = (void *) compare->mask; + + switch (addr->sa_family) { + case AF_INET: + ip4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; + if (ps == RDMA_PS_SDP) { + sdp_set_ip_ver(sdp_data, 4); + sdp_set_ip_ver(sdp_mask, 0xF); + sdp_data->dst_addr.ip4.addr = ip4_addr; + sdp_mask->dst_addr.ip4.addr = ~0; + } else { + cma_set_ip_ver(cma_data, 4); + cma_set_ip_ver(cma_mask, 0xF); + cma_data->dst_addr.ip4.addr = ip4_addr; + cma_mask->dst_addr.ip4.addr = ~0; + } + break; + case AF_INET6: + ip6_addr = ((struct sockaddr_in6 *) addr)->sin6_addr; + if (ps == RDMA_PS_SDP) { + sdp_set_ip_ver(sdp_data, 6); + sdp_set_ip_ver(sdp_mask, 0xF); + sdp_data->dst_addr.ip6 = ip6_addr; + memset(&sdp_mask->dst_addr.ip6, 0xFF, + sizeof sdp_mask->dst_addr.ip6); + } else { + cma_set_ip_ver(cma_data, 6); + cma_set_ip_ver(cma_mask, 0xF); + cma_data->dst_addr.ip6 = ip6_addr; + memset(&cma_mask->dst_addr.ip6, 0xFF, + sizeof cma_mask->dst_addr.ip6); + } + break; + default: + break; + } +} + +static int cma_ib_listen(struct rdma_id_private *id_priv) +{ + struct ib_cm_compare_data compare_data; + struct sockaddr *addr; + __be64 svc_id; + int ret; + + id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_req_handler, + id_priv); + if (IS_ERR(id_priv->cm_id.ib)) + return PTR_ERR(id_priv->cm_id.ib); + + addr = &id_priv->id.route.addr.src_addr; + svc_id = cma_get_service_id(id_priv->id.ps, addr); + if (cma_any_addr(addr)) + ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL); + else { + cma_set_compare_data(id_priv->id.ps, addr, &compare_data); + ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, &compare_data); + } + + if (ret) { + ib_destroy_cm_id(id_priv->cm_id.ib); + id_priv->cm_id.ib = NULL; + } + + return ret; +} + +static int cma_listen_handler(struct rdma_cm_id *id, + struct rdma_cm_event *event) +{ + struct rdma_id_private *id_priv = id->context; + + id->context = id_priv->id.context; + id->event_handler = id_priv->id.event_handler; + return id_priv->id.event_handler(id, event); +} + +static void cma_listen_on_dev(struct rdma_id_private *id_priv, + struct cma_device *cma_dev) +{ + struct rdma_id_private *dev_id_priv; + struct rdma_cm_id *id; + int ret; + + id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps); + if (IS_ERR(id)) + return; + + dev_id_priv = container_of(id, struct rdma_id_private, id); + + dev_id_priv->state = CMA_ADDR_BOUND; + memcpy(&id->route.addr.src_addr, &id_priv->id.route.addr.src_addr, + ip_addr_size(&id_priv->id.route.addr.src_addr)); + + cma_attach_to_dev(dev_id_priv, cma_dev); + list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list); + + ret = rdma_listen(id, id_priv->backlog); + if (ret) + goto err; + + return; +err: + cma_destroy_listen(dev_id_priv); +} + +static void cma_listen_on_all(struct rdma_id_private *id_priv) +{ + struct cma_device *cma_dev; + + mutex_lock(&lock); + list_add_tail(&id_priv->list, &listen_any_list); + list_for_each_entry(cma_dev, &dev_list, list) + cma_listen_on_dev(id_priv, cma_dev); + mutex_unlock(&lock); +} + +static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af) +{ + struct sockaddr_in addr_in; + + memset(&addr_in, 0, sizeof addr_in); + addr_in.sin_family = af; + return rdma_bind_addr(id, (struct sockaddr *) &addr_in); +} + +int rdma_listen(struct rdma_cm_id *id, int backlog) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (id_priv->state == CMA_IDLE) { + ret = cma_bind_any(id, AF_INET); + if (ret) + return ret; + } + + if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_LISTEN)) + return -EINVAL; + + id_priv->backlog = backlog; + if (id->device) { + switch (id->device->node_type) { + case IB_NODE_CA: + ret = cma_ib_listen(id_priv); + if (ret) + goto err; + break; + default: + ret = -ENOSYS; + goto err; + } + } else + cma_listen_on_all(id_priv); + + return 0; +err: + id_priv->backlog = 0; + cma_comp_exch(id_priv, CMA_LISTEN, CMA_ADDR_BOUND); + return ret; +} +EXPORT_SYMBOL(rdma_listen); + +static void cma_query_handler(int status, struct ib_sa_path_rec *path_rec, + void *context) +{ + struct cma_work *work = context; + struct rdma_route *route; + + route = &work->id->id.route; + + if (!status) { + route->num_paths = 1; + *route->path_rec = *path_rec; + } else { + work->old_state = CMA_ROUTE_QUERY; + work->new_state = CMA_ADDR_RESOLVED; + work->event.event = RDMA_CM_EVENT_ROUTE_ERROR; + } + + queue_work(cma_wq, &work->work); +} + +static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, + struct cma_work *work) +{ + struct rdma_dev_addr *addr = &id_priv->id.route.addr.dev_addr; + struct ib_sa_path_rec path_rec; + + memset(&path_rec, 0, sizeof path_rec); + path_rec.sgid = *ib_addr_get_sgid(addr); + path_rec.dgid = *ib_addr_get_dgid(addr); + path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr)); + path_rec.numb_path = 1; + + id_priv->query_id = ib_sa_path_rec_get(id_priv->id.device, + id_priv->id.port_num, &path_rec, + IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID | + IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH, + timeout_ms, GFP_KERNEL, + cma_query_handler, work, &id_priv->query); + + return (id_priv->query_id < 0) ? id_priv->query_id : 0; +} + +static void cma_work_handler(void *data) +{ + struct cma_work *work = data; + struct rdma_id_private *id_priv = work->id; + int destroy = 0; + + atomic_inc(&id_priv->dev_remove); + if (!cma_comp_exch(id_priv, work->old_state, work->new_state)) + goto out; + + if (id_priv->id.event_handler(&id_priv->id, &work->event)) { + cma_exch(id_priv, CMA_DESTROYING); + destroy = 1; + } +out: + cma_release_remove(id_priv); + cma_deref_id(id_priv); + if (destroy) + rdma_destroy_id(&id_priv->id); + kfree(work); +} + +static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms) +{ + struct rdma_route *route = &id_priv->id.route; + struct cma_work *work; + int ret; + + work = kzalloc(sizeof *work, GFP_KERNEL); + if (!work) + return -ENOMEM; + + work->id = id_priv; + INIT_WORK(&work->work, cma_work_handler, work); + work->old_state = CMA_ROUTE_QUERY; + work->new_state = CMA_ROUTE_RESOLVED; + work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; + + route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL); + if (!route->path_rec) { + ret = -ENOMEM; + goto err1; + } + + ret = cma_query_ib_route(id_priv, timeout_ms, work); + if (ret) + goto err2; + + return 0; +err2: + kfree(route->path_rec); + route->path_rec = NULL; +err1: + kfree(work); + return ret; +} + +int rdma_set_ib_paths(struct rdma_cm_id *id, + struct ib_sa_path_rec *path_rec, int num_paths) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_RESOLVED)) + return -EINVAL; + + id->route.path_rec = kmalloc(sizeof *path_rec * num_paths, GFP_KERNEL); + if (!id->route.path_rec) { + ret = -ENOMEM; + goto err; + } + + memcpy(id->route.path_rec, path_rec, sizeof *path_rec * num_paths); + return 0; +err: + cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_ADDR_RESOLVED); + return ret; +} +EXPORT_SYMBOL(rdma_set_ib_paths); + +int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_QUERY)) + return -EINVAL; + + atomic_inc(&id_priv->refcount); + switch (id->device->node_type) { + case IB_NODE_CA: + ret = cma_resolve_ib_route(id_priv, timeout_ms); + break; + default: + ret = -ENOSYS; + break; + } + if (ret) + goto err; + + return 0; +err: + cma_comp_exch(id_priv, CMA_ROUTE_QUERY, CMA_ADDR_RESOLVED); + cma_deref_id(id_priv); + return ret; +} +EXPORT_SYMBOL(rdma_resolve_route); + +static int cma_bind_loopback(struct rdma_id_private *id_priv) +{ + struct cma_device *cma_dev; + struct ib_port_attr port_attr; + union ib_gid *gid; + u16 pkey; + int ret; + u8 p; + + mutex_lock(&lock); + list_for_each_entry(cma_dev, &dev_list, list) + for (p = 1; p <= cma_dev->device->phys_port_cnt; ++p) + if (!ib_query_port (cma_dev->device, p, &port_attr) && + port_attr.state == IB_PORT_ACTIVE) + goto port_found; + + if (!list_empty(&dev_list)) { + p = 1; + cma_dev = list_entry(dev_list.next, struct cma_device, list); + } else { + ret = -ENODEV; + goto out; + } + +port_found: + gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr); + ret = ib_get_cached_gid(cma_dev->device, p, 0, gid); + if (ret) + goto out; + + ret = ib_get_cached_pkey(cma_dev->device, p, 0, &pkey); + if (ret) + goto out; + + ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); + id_priv->id.port_num = p; + cma_attach_to_dev(id_priv, cma_dev); +out: + mutex_unlock(&lock); + return ret; +} + +static void addr_handler(int status, struct sockaddr *src_addr, + struct rdma_dev_addr *dev_addr, void *context) +{ + struct rdma_id_private *id_priv = context; + enum rdma_cm_event_type event; + + atomic_inc(&id_priv->dev_remove); + if (!id_priv->cma_dev && !status) + status = cma_acquire_dev(id_priv); + + if (status) { + if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND)) + goto out; + event = RDMA_CM_EVENT_ADDR_ERROR; + } else { + if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED)) + goto out; + memcpy(&id_priv->id.route.addr.src_addr, src_addr, + ip_addr_size(src_addr)); + event = RDMA_CM_EVENT_ADDR_RESOLVED; + } + + if (cma_notify_user(id_priv, event, status, NULL, 0)) { + cma_exch(id_priv, CMA_DESTROYING); + cma_release_remove(id_priv); + cma_deref_id(id_priv); + rdma_destroy_id(&id_priv->id); + return; + } +out: + cma_release_remove(id_priv); + cma_deref_id(id_priv); +} + +static int cma_resolve_loopback(struct rdma_id_private *id_priv) +{ + struct cma_work *work; + struct sockaddr_in *src_in, *dst_in; + int ret; + + work = kzalloc(sizeof *work, GFP_KERNEL); + if (!work) + return -ENOMEM; + + if (!id_priv->cma_dev) { + ret = cma_bind_loopback(id_priv); + if (ret) + goto err; + } + + ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, + ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr)); + + if (cma_zero_addr(&id_priv->id.route.addr.src_addr)) { + src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr; + dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr; + src_in->sin_family = dst_in->sin_family; + src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr; + } + + work->id = id_priv; + INIT_WORK(&work->work, cma_work_handler, work); + work->old_state = CMA_ADDR_QUERY; + work->new_state = CMA_ADDR_RESOLVED; + work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED; + queue_work(cma_wq, &work->work); + return 0; +err: + kfree(work); + return ret; +} + +static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, + struct sockaddr *dst_addr) +{ + if (src_addr && src_addr->sa_family) + return rdma_bind_addr(id, src_addr); + else + return cma_bind_any(id, dst_addr->sa_family); +} + +int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, + struct sockaddr *dst_addr, int timeout_ms) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (id_priv->state == CMA_IDLE) { + ret = cma_bind_addr(id, src_addr, dst_addr); + if (ret) + return ret; + } + + if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_ADDR_QUERY)) + return -EINVAL; + + atomic_inc(&id_priv->refcount); + memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr)); + if (cma_any_addr(dst_addr)) + ret = cma_resolve_loopback(id_priv); + else + ret = rdma_resolve_ip(&id->route.addr.src_addr, dst_addr, + &id->route.addr.dev_addr, + timeout_ms, addr_handler, id_priv); + if (ret) + goto err; + + return 0; +err: + cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND); + cma_deref_id(id_priv); + return ret; +} +EXPORT_SYMBOL(rdma_resolve_addr); + +static void cma_bind_port(struct rdma_bind_list *bind_list, + struct rdma_id_private *id_priv) +{ + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; + sin->sin_port = htons(bind_list->port); + id_priv->bind_list = bind_list; + hlist_add_head(&id_priv->node, &bind_list->owners); +} + +static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv, + unsigned short snum) +{ + struct rdma_bind_list *bind_list; + int port, start, ret; + + bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL); + if (!bind_list) + return -ENOMEM; + + start = snum ? snum : sysctl_local_port_range[0]; + + do { + ret = idr_get_new_above(ps, bind_list, start, &port); + } while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL)); + + if (ret) + goto err; + + if ((snum && port != snum) || + (!snum && port > sysctl_local_port_range[1])) { + idr_remove(ps, port); + ret = -EADDRNOTAVAIL; + goto err; + } + + bind_list->ps = ps; + bind_list->port = (unsigned short) port; + cma_bind_port(bind_list, id_priv); + return 0; +err: + kfree(bind_list); + return ret; +} + +static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv) +{ + struct rdma_id_private *cur_id; + struct sockaddr_in *sin, *cur_sin; + struct rdma_bind_list *bind_list; + struct hlist_node *node; + unsigned short snum; + + sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; + snum = ntohs(sin->sin_port); + if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + return -EACCES; + + bind_list = idr_find(ps, snum); + if (!bind_list) + return cma_alloc_port(ps, id_priv, snum); + + /* + * We don't support binding to any address if anyone is bound to + * a specific address on the same port. + */ + if (cma_any_addr(&id_priv->id.route.addr.src_addr)) + return -EADDRNOTAVAIL; + + hlist_for_each_entry(cur_id, node, &bind_list->owners, node) { + if (cma_any_addr(&cur_id->id.route.addr.src_addr)) + return -EADDRNOTAVAIL; + + cur_sin = (struct sockaddr_in *) &cur_id->id.route.addr.src_addr; + if (sin->sin_addr.s_addr == cur_sin->sin_addr.s_addr) + return -EADDRINUSE; + } + + cma_bind_port(bind_list, id_priv); + return 0; +} + +static int cma_get_port(struct rdma_id_private *id_priv) +{ + struct idr *ps; + int ret; + + switch (id_priv->id.ps) { + case RDMA_PS_SDP: + ps = &sdp_ps; + break; + case RDMA_PS_TCP: + ps = &tcp_ps; + break; + default: + return -EPROTONOSUPPORT; + } + + mutex_lock(&lock); + if (cma_any_port(&id_priv->id.route.addr.src_addr)) + ret = cma_alloc_port(ps, id_priv, 0); + else + ret = cma_use_port(ps, id_priv); + mutex_unlock(&lock); + + return ret; +} + +int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) +{ + struct rdma_id_private *id_priv; + int ret; + + if (addr->sa_family != AF_INET) + return -EAFNOSUPPORT; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND)) + return -EINVAL; + + if (!cma_any_addr(addr)) { + ret = rdma_translate_ip(addr, &id->route.addr.dev_addr); + if (!ret) + ret = cma_acquire_dev(id_priv); + if (ret) + goto err; + } + + memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr)); + ret = cma_get_port(id_priv); + if (ret) + goto err; + + return 0; +err: + cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE); + return ret; +} +EXPORT_SYMBOL(rdma_bind_addr); + +static int cma_format_hdr(void *hdr, enum rdma_port_space ps, + struct rdma_route *route) +{ + struct sockaddr_in *src4, *dst4; + struct cma_hdr *cma_hdr; + struct sdp_hh *sdp_hdr; + + src4 = (struct sockaddr_in *) &route->addr.src_addr; + dst4 = (struct sockaddr_in *) &route->addr.dst_addr; + + switch (ps) { + case RDMA_PS_SDP: + sdp_hdr = hdr; + if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION) + return -EINVAL; + sdp_set_ip_ver(sdp_hdr, 4); + sdp_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr; + sdp_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr; + sdp_hdr->port = src4->sin_port; + break; + default: + cma_hdr = hdr; + cma_hdr->cma_version = CMA_VERSION; + cma_set_ip_ver(cma_hdr, 4); + cma_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr; + cma_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr; + cma_hdr->port = src4->sin_port; + break; + } + return 0; +} + +static int cma_connect_ib(struct rdma_id_private *id_priv, + struct rdma_conn_param *conn_param) +{ + struct ib_cm_req_param req; + struct rdma_route *route; + void *private_data; + int offset, ret; + + memset(&req, 0, sizeof req); + offset = cma_user_data_offset(id_priv->id.ps); + req.private_data_len = offset + conn_param->private_data_len; + private_data = kzalloc(req.private_data_len, GFP_ATOMIC); + if (!private_data) + return -ENOMEM; + + if (conn_param->private_data && conn_param->private_data_len) + memcpy(private_data + offset, conn_param->private_data, + conn_param->private_data_len); + + id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler, + id_priv); + if (IS_ERR(id_priv->cm_id.ib)) { + ret = PTR_ERR(id_priv->cm_id.ib); + goto out; + } + + route = &id_priv->id.route; + ret = cma_format_hdr(private_data, id_priv->id.ps, route); + if (ret) + goto out; + req.private_data = private_data; + + req.primary_path = &route->path_rec[0]; + if (route->num_paths == 2) + req.alternate_path = &route->path_rec[1]; + + req.service_id = cma_get_service_id(id_priv->id.ps, + &route->addr.dst_addr); + req.qp_num = id_priv->qp_num; + req.qp_type = id_priv->qp_type; + req.starting_psn = id_priv->seq_num; + req.responder_resources = conn_param->responder_resources; + req.initiator_depth = conn_param->initiator_depth; + req.flow_control = conn_param->flow_control; + req.retry_count = conn_param->retry_count; + req.rnr_retry_count = conn_param->rnr_retry_count; + req.remote_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT; + req.local_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT; + req.max_cm_retries = CMA_MAX_CM_RETRIES; + req.srq = id_priv->srq ? 1 : 0; + + ret = ib_send_cm_req(id_priv->cm_id.ib, &req); +out: + kfree(private_data); + return ret; +} + +int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_CONNECT)) + return -EINVAL; + + if (!id->qp) { + id_priv->qp_num = conn_param->qp_num; + id_priv->qp_type = conn_param->qp_type; + id_priv->srq = conn_param->srq; + } + + switch (id->device->node_type) { + case IB_NODE_CA: + ret = cma_connect_ib(id_priv, conn_param); + break; + default: + ret = -ENOSYS; + break; + } + if (ret) + goto err; + + return 0; +err: + cma_comp_exch(id_priv, CMA_CONNECT, CMA_ROUTE_RESOLVED); + return ret; +} +EXPORT_SYMBOL(rdma_connect); + +static int cma_accept_ib(struct rdma_id_private *id_priv, + struct rdma_conn_param *conn_param) +{ + struct ib_cm_rep_param rep; + int ret; + + ret = cma_modify_qp_rtr(&id_priv->id); + if (ret) + return ret; + + memset(&rep, 0, sizeof rep); + rep.qp_num = id_priv->qp_num; + rep.starting_psn = id_priv->seq_num; + rep.private_data = conn_param->private_data; + rep.private_data_len = conn_param->private_data_len; + rep.responder_resources = conn_param->responder_resources; + rep.initiator_depth = conn_param->initiator_depth; + rep.target_ack_delay = CMA_CM_RESPONSE_TIMEOUT; + rep.failover_accepted = 0; + rep.flow_control = conn_param->flow_control; + rep.rnr_retry_count = conn_param->rnr_retry_count; + rep.srq = id_priv->srq ? 1 : 0; + + return ib_send_cm_rep(id_priv->cm_id.ib, &rep); +} + +int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp(id_priv, CMA_CONNECT)) + return -EINVAL; + + if (!id->qp && conn_param) { + id_priv->qp_num = conn_param->qp_num; + id_priv->qp_type = conn_param->qp_type; + id_priv->srq = conn_param->srq; + } + + switch (id->device->node_type) { + case IB_NODE_CA: + if (conn_param) + ret = cma_accept_ib(id_priv, conn_param); + else + ret = cma_rep_recv(id_priv); + break; + default: + ret = -ENOSYS; + break; + } + + if (ret) + goto reject; + + return 0; +reject: + cma_modify_qp_err(id); + rdma_reject(id, NULL, 0); + return ret; +} +EXPORT_SYMBOL(rdma_accept); + +int rdma_reject(struct rdma_cm_id *id, const void *private_data, + u8 private_data_len) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp(id_priv, CMA_CONNECT)) + return -EINVAL; + + switch (id->device->node_type) { + case IB_NODE_CA: + ret = ib_send_cm_rej(id_priv->cm_id.ib, + IB_CM_REJ_CONSUMER_DEFINED, NULL, 0, + private_data, private_data_len); + break; + default: + ret = -ENOSYS; + break; + } + return ret; +} +EXPORT_SYMBOL(rdma_reject); + +int rdma_disconnect(struct rdma_cm_id *id) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp(id_priv, CMA_CONNECT) && + !cma_comp(id_priv, CMA_DISCONNECT)) + return -EINVAL; + + ret = cma_modify_qp_err(id); + if (ret) + goto out; + + switch (id->device->node_type) { + case IB_NODE_CA: + /* Initiate or respond to a disconnect. */ + if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0)) + ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0); + break; + default: + break; + } +out: + return ret; +} +EXPORT_SYMBOL(rdma_disconnect); + +static void cma_add_one(struct ib_device *device) +{ + struct cma_device *cma_dev; + struct rdma_id_private *id_priv; + + cma_dev = kmalloc(sizeof *cma_dev, GFP_KERNEL); + if (!cma_dev) + return; + + cma_dev->device = device; + cma_dev->node_guid = device->node_guid; + if (!cma_dev->node_guid) + goto err; + + init_completion(&cma_dev->comp); + atomic_set(&cma_dev->refcount, 1); + INIT_LIST_HEAD(&cma_dev->id_list); + ib_set_client_data(device, &cma_client, cma_dev); + + mutex_lock(&lock); + list_add_tail(&cma_dev->list, &dev_list); + list_for_each_entry(id_priv, &listen_any_list, list) + cma_listen_on_dev(id_priv, cma_dev); + mutex_unlock(&lock); + return; +err: + kfree(cma_dev); +} + +static int cma_remove_id_dev(struct rdma_id_private *id_priv) +{ + enum cma_state state; + + /* Record that we want to remove the device */ + state = cma_exch(id_priv, CMA_DEVICE_REMOVAL); + if (state == CMA_DESTROYING) + return 0; + + cma_cancel_operation(id_priv, state); + wait_event(id_priv->wait_remove, !atomic_read(&id_priv->dev_remove)); + + /* Check for destruction from another callback. */ + if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL)) + return 0; + + return cma_notify_user(id_priv, RDMA_CM_EVENT_DEVICE_REMOVAL, + 0, NULL, 0); +} + +static void cma_process_remove(struct cma_device *cma_dev) +{ + struct list_head remove_list; + struct rdma_id_private *id_priv; + int ret; + + INIT_LIST_HEAD(&remove_list); + + mutex_lock(&lock); + while (!list_empty(&cma_dev->id_list)) { + id_priv = list_entry(cma_dev->id_list.next, + struct rdma_id_private, list); + + if (cma_internal_listen(id_priv)) { + cma_destroy_listen(id_priv); + continue; + } + + list_del(&id_priv->list); + list_add_tail(&id_priv->list, &remove_list); + atomic_inc(&id_priv->refcount); + mutex_unlock(&lock); + + ret = cma_remove_id_dev(id_priv); + cma_deref_id(id_priv); + if (ret) + rdma_destroy_id(&id_priv->id); + + mutex_lock(&lock); + } + mutex_unlock(&lock); + + cma_deref_dev(cma_dev); + wait_for_completion(&cma_dev->comp); +} + +static void cma_remove_one(struct ib_device *device) +{ + struct cma_device *cma_dev; + + cma_dev = ib_get_client_data(device, &cma_client); + if (!cma_dev) + return; + + mutex_lock(&lock); + list_del(&cma_dev->list); + mutex_unlock(&lock); + + cma_process_remove(cma_dev); + kfree(cma_dev); +} + +static int cma_init(void) +{ + int ret; + + cma_wq = create_singlethread_workqueue("rdma_cm_wq"); + if (!cma_wq) + return -ENOMEM; + + ret = ib_register_client(&cma_client); + if (ret) + goto err; + return 0; + +err: + destroy_workqueue(cma_wq); + return ret; +} + +static void cma_cleanup(void) +{ + ib_unregister_client(&cma_client); + destroy_workqueue(cma_wq); + idr_destroy(&sdp_ps); + idr_destroy(&tcp_ps); +} + +module_init(cma_init); +module_exit(cma_cleanup); diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c index 838bf54..615fe9c 100644 --- a/drivers/infiniband/core/fmr_pool.c +++ b/drivers/infiniband/core/fmr_pool.c @@ -54,7 +54,7 @@ enum { /* * If an FMR is not in use, then the list member will point to either * its pool's free_list (if the FMR can be mapped again; that is, - * remap_count < IB_FMR_MAX_REMAPS) or its pool's dirty_list (if the + * remap_count < pool->max_remaps) or its pool's dirty_list (if the * FMR needs to be unmapped before being remapped). In either of * these cases it is a bug if the ref_count is not 0. In other words, * if ref_count is > 0, then the list member must not be linked into @@ -84,6 +84,7 @@ struct ib_fmr_pool { int pool_size; int max_pages; + int max_remaps; int dirty_watermark; int dirty_len; struct list_head free_list; @@ -214,8 +215,10 @@ struct ib_fmr_pool *ib_create_fmr_pool(s { struct ib_device *device; struct ib_fmr_pool *pool; + struct ib_device_attr *attr; int i; int ret; + int max_remaps; if (!params) return ERR_PTR(-EINVAL); @@ -228,6 +231,26 @@ struct ib_fmr_pool *ib_create_fmr_pool(s return ERR_PTR(-ENOSYS); } + attr = kmalloc(sizeof *attr, GFP_KERNEL); + if (!attr) { + printk(KERN_WARNING "couldn't allocate device attr struct"); + return ERR_PTR(-ENOMEM); + } + + ret = ib_query_device(device, attr); + if (ret) { + printk(KERN_WARNING "couldn't query device"); + kfree(attr); + return ERR_PTR(ret); + } + + if (!attr->max_map_per_fmr) + max_remaps = IB_FMR_MAX_REMAPS; + else + max_remaps = attr->max_map_per_fmr; + + kfree(attr); + pool = kmalloc(sizeof *pool, GFP_KERNEL); if (!pool) { printk(KERN_WARNING "couldn't allocate pool struct"); @@ -258,6 +281,7 @@ struct ib_fmr_pool *ib_create_fmr_pool(s pool->pool_size = 0; pool->max_pages = params->max_pages_per_fmr; + pool->max_remaps = max_remaps; pool->dirty_watermark = params->dirty_watermark; pool->dirty_len = 0; spin_lock_init(&pool->pool_lock); @@ -279,7 +303,7 @@ struct ib_fmr_pool *ib_create_fmr_pool(s struct ib_pool_fmr *fmr; struct ib_fmr_attr attr = { .max_pages = params->max_pages_per_fmr, - .max_maps = IB_FMR_MAX_REMAPS, + .max_maps = pool->max_remaps, .page_shift = params->page_shift }; @@ -489,7 +513,7 @@ int ib_fmr_pool_unmap(struct ib_pool_fmr --fmr->ref_count; if (!fmr->ref_count) { - if (fmr->remap_count < IB_FMR_MAX_REMAPS) { + if (fmr->remap_count < pool->max_remaps) { list_add_tail(&fmr->list, &pool->free_list); } else { list_add_tail(&fmr->list, &pool->dirty_list); diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 5ad41a6..5ed4dab 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -34,6 +34,7 @@ * $Id: mad.c 5596 2006-03-03 01:00:07Z sean.hefty $ */ #include +#include #include "mad_priv.h" #include "mad_rmpp.h" @@ -45,8 +46,7 @@ MODULE_DESCRIPTION("kernel IB MAD API"); MODULE_AUTHOR("Hal Rosenstock"); MODULE_AUTHOR("Sean Hefty"); - -kmem_cache_t *ib_mad_cache; +static kmem_cache_t *ib_mad_cache; static struct list_head ib_mad_port_list; static u32 ib_mad_client_id = 0; @@ -1673,20 +1673,21 @@ static inline int rcv_has_same_class(str rwc->recv_buf.mad->mad_hdr.mgmt_class; } -static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr, +static inline int rcv_has_same_gid(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_send_wr_private *wr, struct ib_mad_recv_wc *rwc ) { struct ib_ah_attr attr; u8 send_resp, rcv_resp; + union ib_gid sgid; + struct ib_device *device = mad_agent_priv->agent.device; + u8 port_num = mad_agent_priv->agent.port_num; + u8 lmc; send_resp = ((struct ib_mad *)(wr->send_buf.mad))-> mad_hdr.method & IB_MGMT_METHOD_RESP; rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP; - if (!send_resp && rcv_resp) - /* is request/response. GID/LIDs are both local (same). */ - return 1; - if (send_resp == rcv_resp) /* both requests, or both responses. GIDs different */ return 0; @@ -1695,48 +1696,78 @@ static inline int rcv_has_same_gid(struc /* Assume not equal, to avoid false positives. */ return 0; - if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH)) - return attr.dlid == rwc->wc->slid; - else if ((attr.ah_flags & IB_AH_GRH) && - (rwc->wc->wc_flags & IB_WC_GRH)) - return memcmp(attr.grh.dgid.raw, - rwc->recv_buf.grh->sgid.raw, 16) == 0; - else + if (!!(attr.ah_flags & IB_AH_GRH) != + !!(rwc->wc->wc_flags & IB_WC_GRH)) /* one has GID, other does not. Assume different */ return 0; + + if (!send_resp && rcv_resp) { + /* is request/response. */ + if (!(attr.ah_flags & IB_AH_GRH)) { + if (ib_get_cached_lmc(device, port_num, &lmc)) + return 0; + return (!lmc || !((attr.src_path_bits ^ + rwc->wc->dlid_path_bits) & + ((1 << lmc) - 1))); + } else { + if (ib_get_cached_gid(device, port_num, + attr.grh.sgid_index, &sgid)) + return 0; + return !memcmp(sgid.raw, rwc->recv_buf.grh->dgid.raw, + 16); + } + } + + if (!(attr.ah_flags & IB_AH_GRH)) + return attr.dlid == rwc->wc->slid; + else + return !memcmp(attr.grh.dgid.raw, rwc->recv_buf.grh->sgid.raw, + 16); +} + +static inline int is_direct(u8 class) +{ + return (class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE); } + struct ib_mad_send_wr_private* ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, - struct ib_mad_recv_wc *mad_recv_wc) + struct ib_mad_recv_wc *wc) { - struct ib_mad_send_wr_private *mad_send_wr; + struct ib_mad_send_wr_private *wr; struct ib_mad *mad; - mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad; + mad = (struct ib_mad *)wc->recv_buf.mad; - list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list, - agent_list) { - if ((mad_send_wr->tid == mad->mad_hdr.tid) && - rcv_has_same_class(mad_send_wr, mad_recv_wc) && - rcv_has_same_gid(mad_send_wr, mad_recv_wc)) - return mad_send_wr; + list_for_each_entry(wr, &mad_agent_priv->wait_list, agent_list) { + if ((wr->tid == mad->mad_hdr.tid) && + rcv_has_same_class(wr, wc) && + /* + * Don't check GID for direct routed MADs. + * These might have permissive LIDs. + */ + (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) || + rcv_has_same_gid(mad_agent_priv, wr, wc))) + return wr; } /* * It's possible to receive the response before we've * been notified that the send has completed */ - list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, - agent_list) { - if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) && - mad_send_wr->tid == mad->mad_hdr.tid && - mad_send_wr->timeout && - rcv_has_same_class(mad_send_wr, mad_recv_wc) && - rcv_has_same_gid(mad_send_wr, mad_recv_wc)) { + list_for_each_entry(wr, &mad_agent_priv->send_list, agent_list) { + if (is_data_mad(mad_agent_priv, wr->send_buf.mad) && + wr->tid == mad->mad_hdr.tid && + wr->timeout && + rcv_has_same_class(wr, wc) && + /* + * Don't check GID for direct routed MADs. + * These might have permissive LIDs. + */ + (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) || + rcv_has_same_gid(mad_agent_priv, wr, wc))) /* Verify request has not been canceled */ - return (mad_send_wr->status == IB_WC_SUCCESS) ? - mad_send_wr : NULL; - } + return (wr->status == IB_WC_SUCCESS) ? wr : NULL; } return NULL; } @@ -1744,11 +1775,9 @@ ib_find_send_mad(struct ib_mad_agent_pri void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr) { mad_send_wr->timeout = 0; - if (mad_send_wr->refcount == 1) { - list_del(&mad_send_wr->agent_list); - list_add_tail(&mad_send_wr->agent_list, + if (mad_send_wr->refcount == 1) + list_move_tail(&mad_send_wr->agent_list, &mad_send_wr->mad_agent_priv->done_list); - } } static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, @@ -2067,8 +2096,7 @@ retry: queued_send_wr = container_of(mad_list, struct ib_mad_send_wr_private, mad_list); - list_del(&mad_list->list); - list_add_tail(&mad_list->list, &send_queue->list); + list_move_tail(&mad_list->list, &send_queue->list); } spin_unlock_irqrestore(&send_queue->lock, flags); diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index b4fa28d..d147f3b 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h @@ -212,8 +212,6 @@ struct ib_mad_port_private { struct ib_mad_qp_info qp_info[IB_MAD_QPS_CORE]; }; -extern kmem_cache_t *ib_mad_cache; - int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr); struct ib_mad_send_wr_private * diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index d4704e0..ebcd5b1 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -665,8 +665,7 @@ static void process_rmpp_ack(struct ib_m goto out; mad_send_wr->refcount++; - list_del(&mad_send_wr->agent_list); - list_add_tail(&mad_send_wr->agent_list, + list_move_tail(&mad_send_wr->agent_list, &mad_send_wr->mad_agent_priv->send_list); } out: diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 501cc05..e911c99 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -47,6 +47,7 @@ #include #include #include +#include MODULE_AUTHOR("Roland Dreier"); MODULE_DESCRIPTION("InfiniBand subnet administration query support"); @@ -441,6 +442,36 @@ void ib_sa_cancel_query(int id, struct i } EXPORT_SYMBOL(ib_sa_cancel_query); +int ib_init_ah_from_path(struct ib_device *device, u8 port_num, + struct ib_sa_path_rec *rec, struct ib_ah_attr *ah_attr) +{ + int ret; + u16 gid_index; + + memset(ah_attr, 0, sizeof *ah_attr); + ah_attr->dlid = be16_to_cpu(rec->dlid); + ah_attr->sl = rec->sl; + ah_attr->src_path_bits = be16_to_cpu(rec->slid) & 0x7f; + ah_attr->port_num = port_num; + + if (rec->hop_limit > 1) { + ah_attr->ah_flags = IB_AH_GRH; + ah_attr->grh.dgid = rec->dgid; + + ret = ib_find_cached_gid(device, &rec->sgid, &port_num, + &gid_index); + if (ret) + return ret; + + ah_attr->grh.sgid_index = gid_index; + ah_attr->grh.flow_label = be32_to_cpu(rec->flow_label); + ah_attr->grh.hop_limit = rec->hop_limit; + ah_attr->grh.traffic_class = rec->traffic_class; + } + return 0; +} +EXPORT_SYMBOL(ib_init_ah_from_path); + static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent) { unsigned long flags; diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 9164a09..c1c6fda 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c @@ -30,7 +30,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id: ucm.c 2594 2005-06-13 19:46:02Z libor $ + * $Id: ucm.c 4311 2005-12-05 18:42:01Z sean.hefty $ */ #include @@ -50,6 +50,7 @@ #include #include #include +#include MODULE_AUTHOR("Libor Michalek"); MODULE_DESCRIPTION("InfiniBand userspace Connection Manager access"); @@ -63,7 +64,7 @@ struct ib_ucm_device { }; struct ib_ucm_file { - struct semaphore mutex; + struct mutex file_mutex; struct file *filp; struct ib_ucm_device *device; @@ -152,7 +153,7 @@ static void ib_ucm_cleanup_events(struct { struct ib_ucm_event *uevent; - down(&ctx->file->mutex); + mutex_lock(&ctx->file->file_mutex); list_del(&ctx->file_list); while (!list_empty(&ctx->events)) { @@ -167,7 +168,7 @@ static void ib_ucm_cleanup_events(struct kfree(uevent); } - up(&ctx->file->mutex); + mutex_unlock(&ctx->file->file_mutex); } static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) @@ -205,36 +206,6 @@ error: return NULL; } -static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath, - struct ib_sa_path_rec *kpath) -{ - if (!kpath || !upath) - return; - - memcpy(upath->dgid, kpath->dgid.raw, sizeof *upath->dgid); - memcpy(upath->sgid, kpath->sgid.raw, sizeof *upath->sgid); - - upath->dlid = kpath->dlid; - upath->slid = kpath->slid; - upath->raw_traffic = kpath->raw_traffic; - upath->flow_label = kpath->flow_label; - upath->hop_limit = kpath->hop_limit; - upath->traffic_class = kpath->traffic_class; - upath->reversible = kpath->reversible; - upath->numb_path = kpath->numb_path; - upath->pkey = kpath->pkey; - upath->sl = kpath->sl; - upath->mtu_selector = kpath->mtu_selector; - upath->mtu = kpath->mtu; - upath->rate_selector = kpath->rate_selector; - upath->rate = kpath->rate; - upath->packet_life_time = kpath->packet_life_time; - upath->preference = kpath->preference; - - upath->packet_life_time_selector = - kpath->packet_life_time_selector; -} - static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq, struct ib_cm_req_event_param *kreq) { @@ -253,8 +224,10 @@ static void ib_ucm_event_req_get(struct ureq->srq = kreq->srq; ureq->port = kreq->port; - ib_ucm_event_path_get(&ureq->primary_path, kreq->primary_path); - ib_ucm_event_path_get(&ureq->alternate_path, kreq->alternate_path); + ib_copy_path_rec_to_user(&ureq->primary_path, kreq->primary_path); + if (kreq->alternate_path) + ib_copy_path_rec_to_user(&ureq->alternate_path, + kreq->alternate_path); } static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep, @@ -324,8 +297,8 @@ static int ib_ucm_event_process(struct i info = evt->param.rej_rcvd.ari; break; case IB_CM_LAP_RECEIVED: - ib_ucm_event_path_get(&uvt->resp.u.lap_resp.path, - evt->param.lap_rcvd.alternate_path); + ib_copy_path_rec_to_user(&uvt->resp.u.lap_resp.path, + evt->param.lap_rcvd.alternate_path); uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE; uvt->resp.present = IB_UCM_PRES_ALTERNATE; break; @@ -402,11 +375,11 @@ static int ib_ucm_event_handler(struct i if (result) goto err2; - down(&ctx->file->mutex); + mutex_lock(&ctx->file->file_mutex); list_add_tail(&uevent->file_list, &ctx->file->events); list_add_tail(&uevent->ctx_list, &ctx->events); wake_up_interruptible(&ctx->file->poll_wait); - up(&ctx->file->mutex); + mutex_unlock(&ctx->file->file_mutex); return 0; err2: @@ -432,7 +405,7 @@ static ssize_t ib_ucm_event(struct ib_uc if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; - down(&file->mutex); + mutex_lock(&file->file_mutex); while (list_empty(&file->events)) { if (file->filp->f_flags & O_NONBLOCK) { @@ -447,9 +420,9 @@ static ssize_t ib_ucm_event(struct ib_uc prepare_to_wait(&file->poll_wait, &wait, TASK_INTERRUPTIBLE); - up(&file->mutex); + mutex_unlock(&file->file_mutex); schedule(); - down(&file->mutex); + mutex_lock(&file->file_mutex); finish_wait(&file->poll_wait, &wait); } @@ -509,7 +482,7 @@ static ssize_t ib_ucm_event(struct ib_uc kfree(uevent->info); kfree(uevent); done: - up(&file->mutex); + mutex_unlock(&file->file_mutex); return result; } @@ -528,9 +501,9 @@ static ssize_t ib_ucm_create_id(struct i if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; - down(&file->mutex); + mutex_lock(&file->file_mutex); ctx = ib_ucm_ctx_alloc(file); - up(&file->mutex); + mutex_unlock(&file->file_mutex); if (!ctx) return -ENOMEM; @@ -637,65 +610,11 @@ static ssize_t ib_ucm_attr_id(struct ib_ return result; } -static void ib_ucm_copy_ah_attr(struct ib_ucm_ah_attr *dest_attr, - struct ib_ah_attr *src_attr) -{ - memcpy(dest_attr->grh_dgid, src_attr->grh.dgid.raw, - sizeof src_attr->grh.dgid); - dest_attr->grh_flow_label = src_attr->grh.flow_label; - dest_attr->grh_sgid_index = src_attr->grh.sgid_index; - dest_attr->grh_hop_limit = src_attr->grh.hop_limit; - dest_attr->grh_traffic_class = src_attr->grh.traffic_class; - - dest_attr->dlid = src_attr->dlid; - dest_attr->sl = src_attr->sl; - dest_attr->src_path_bits = src_attr->src_path_bits; - dest_attr->static_rate = src_attr->static_rate; - dest_attr->is_global = (src_attr->ah_flags & IB_AH_GRH); - dest_attr->port_num = src_attr->port_num; -} - -static void ib_ucm_copy_qp_attr(struct ib_ucm_init_qp_attr_resp *dest_attr, - struct ib_qp_attr *src_attr) -{ - dest_attr->cur_qp_state = src_attr->cur_qp_state; - dest_attr->path_mtu = src_attr->path_mtu; - dest_attr->path_mig_state = src_attr->path_mig_state; - dest_attr->qkey = src_attr->qkey; - dest_attr->rq_psn = src_attr->rq_psn; - dest_attr->sq_psn = src_attr->sq_psn; - dest_attr->dest_qp_num = src_attr->dest_qp_num; - dest_attr->qp_access_flags = src_attr->qp_access_flags; - - dest_attr->max_send_wr = src_attr->cap.max_send_wr; - dest_attr->max_recv_wr = src_attr->cap.max_recv_wr; - dest_attr->max_send_sge = src_attr->cap.max_send_sge; - dest_attr->max_recv_sge = src_attr->cap.max_recv_sge; - dest_attr->max_inline_data = src_attr->cap.max_inline_data; - - ib_ucm_copy_ah_attr(&dest_attr->ah_attr, &src_attr->ah_attr); - ib_ucm_copy_ah_attr(&dest_attr->alt_ah_attr, &src_attr->alt_ah_attr); - - dest_attr->pkey_index = src_attr->pkey_index; - dest_attr->alt_pkey_index = src_attr->alt_pkey_index; - dest_attr->en_sqd_async_notify = src_attr->en_sqd_async_notify; - dest_attr->sq_draining = src_attr->sq_draining; - dest_attr->max_rd_atomic = src_attr->max_rd_atomic; - dest_attr->max_dest_rd_atomic = src_attr->max_dest_rd_atomic; - dest_attr->min_rnr_timer = src_attr->min_rnr_timer; - dest_attr->port_num = src_attr->port_num; - dest_attr->timeout = src_attr->timeout; - dest_attr->retry_cnt = src_attr->retry_cnt; - dest_attr->rnr_retry = src_attr->rnr_retry; - dest_attr->alt_port_num = src_attr->alt_port_num; - dest_attr->alt_timeout = src_attr->alt_timeout; -} - static ssize_t ib_ucm_init_qp_attr(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len) { - struct ib_ucm_init_qp_attr_resp resp; + struct ib_uverbs_qp_attr resp; struct ib_ucm_init_qp_attr cmd; struct ib_ucm_context *ctx; struct ib_qp_attr qp_attr; @@ -718,7 +637,7 @@ static ssize_t ib_ucm_init_qp_attr(struc if (result) goto out; - ib_ucm_copy_qp_attr(&resp, &qp_attr); + ib_copy_qp_attr_to_user(&resp, &qp_attr); if (copy_to_user((void __user *)(unsigned long)cmd.response, &resp, sizeof(resp))) @@ -729,6 +648,17 @@ out: return result; } +static int ucm_validate_listen(__be64 service_id, __be64 service_mask) +{ + service_id &= service_mask; + + if (((service_id & IB_CMA_SERVICE_ID_MASK) == IB_CMA_SERVICE_ID) || + ((service_id & IB_SDP_SERVICE_ID_MASK) == IB_SDP_SERVICE_ID)) + return -EINVAL; + + return 0; +} + static ssize_t ib_ucm_listen(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len) @@ -744,7 +674,13 @@ static ssize_t ib_ucm_listen(struct ib_u if (IS_ERR(ctx)) return PTR_ERR(ctx); - result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask); + result = ucm_validate_listen(cmd.service_id, cmd.service_mask); + if (result) + goto out; + + result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask, + NULL); +out: ib_ucm_ctx_put(ctx); return result; } @@ -793,7 +729,7 @@ static int ib_ucm_alloc_data(const void static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src) { - struct ib_ucm_path_rec ucm_path; + struct ib_user_path_rec upath; struct ib_sa_path_rec *sa_path; *path = NULL; @@ -805,36 +741,14 @@ static int ib_ucm_path_get(struct ib_sa_ if (!sa_path) return -ENOMEM; - if (copy_from_user(&ucm_path, (void __user *)(unsigned long)src, - sizeof(ucm_path))) { + if (copy_from_user(&upath, (void __user *)(unsigned long)src, + sizeof(upath))) { kfree(sa_path); return -EFAULT; } - memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof sa_path->dgid); - memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof sa_path->sgid); - - sa_path->dlid = ucm_path.dlid; - sa_path->slid = ucm_path.slid; - sa_path->raw_traffic = ucm_path.raw_traffic; - sa_path->flow_label = ucm_path.flow_label; - sa_path->hop_limit = ucm_path.hop_limit; - sa_path->traffic_class = ucm_path.traffic_class; - sa_path->reversible = ucm_path.reversible; - sa_path->numb_path = ucm_path.numb_path; - sa_path->pkey = ucm_path.pkey; - sa_path->sl = ucm_path.sl; - sa_path->mtu_selector = ucm_path.mtu_selector; - sa_path->mtu = ucm_path.mtu; - sa_path->rate_selector = ucm_path.rate_selector; - sa_path->rate = ucm_path.rate; - sa_path->packet_life_time = ucm_path.packet_life_time; - sa_path->preference = ucm_path.preference; - - sa_path->packet_life_time_selector = - ucm_path.packet_life_time_selector; - + ib_copy_path_rec_from_user(sa_path, &upath); *path = sa_path; return 0; } @@ -1130,7 +1044,6 @@ static ssize_t ib_ucm_send_sidr_req(stru param.service_id = cmd.sid; param.timeout_ms = cmd.timeout; param.max_cm_retries = cmd.max_cm_retries; - param.pkey = cmd.pkey; ctx = ib_ucm_ctx_get(file, cmd.id); if (!IS_ERR(ctx)) { @@ -1263,7 +1176,7 @@ static int ib_ucm_open(struct inode *ino INIT_LIST_HEAD(&file->ctxs); init_waitqueue_head(&file->poll_wait); - init_MUTEX(&file->mutex); + mutex_init(&file->file_mutex); filp->private_data = file; file->filp = filp; @@ -1277,11 +1190,11 @@ static int ib_ucm_close(struct inode *in struct ib_ucm_file *file = filp->private_data; struct ib_ucm_context *ctx; - down(&file->mutex); + mutex_lock(&file->file_mutex); while (!list_empty(&file->ctxs)) { ctx = list_entry(file->ctxs.next, struct ib_ucm_context, file_list); - up(&file->mutex); + mutex_unlock(&file->file_mutex); mutex_lock(&ctx_id_mutex); idr_remove(&ctx_id_table, ctx->id); @@ -1291,9 +1204,9 @@ static int ib_ucm_close(struct inode *in ib_ucm_cleanup_events(ctx); kfree(ctx); - down(&file->mutex); + mutex_lock(&file->file_mutex); } - up(&file->mutex); + mutex_unlock(&file->file_mutex); kfree(file); return 0; } diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 3372d67..bb9bee5 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -132,7 +132,7 @@ struct ib_ucq_object { u32 async_events_reported; }; -extern struct mutex ib_uverbs_idr_mutex; +extern spinlock_t ib_uverbs_idr_lock; extern struct idr ib_uverbs_pd_idr; extern struct idr ib_uverbs_mr_idr; extern struct idr ib_uverbs_mw_idr; @@ -141,6 +141,8 @@ extern struct idr ib_uverbs_cq_idr; extern struct idr ib_uverbs_qp_idr; extern struct idr ib_uverbs_srq_idr; +void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj); + struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file, int is_async, int *fd); void ib_uverbs_release_event_file(struct kref *ref); diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 9f69bd4..a908a7b 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -50,6 +50,196 @@ #define INIT_UDATA(udata, ibuf, obuf, il (udata)->outlen = (olen); \ } while (0) +/* + * The ib_uobject locking scheme is as follows: + * + * - ib_uverbs_idr_lock protects the uverbs idrs themselves, so it + * needs to be held during all idr operations. When an object is + * looked up, a reference must be taken on the object's kref before + * dropping this lock. + * + * - Each object also has an rwsem. This rwsem must be held for + * reading while an operation that uses the object is performed. + * For example, while registering an MR, the associated PD's + * uobject.mutex must be held for reading. The rwsem must be held + * for writing while initializing or destroying an object. + * + * - In addition, each object has a "live" flag. If this flag is not + * set, then lookups of the object will fail even if it is found in + * the idr. This handles a reader that blocks and does not acquire + * the rwsem until after the object is destroyed. The destroy + * operation will set the live flag to 0 and then drop the rwsem; + * this will allow the reader to acquire the rwsem, see that the + * live flag is 0, and then drop the rwsem and its reference to + * object. The underlying storage will not be freed until the last + * reference to the object is dropped. + */ + +static void init_uobj(struct ib_uobject *uobj, u64 user_handle, + struct ib_ucontext *context) +{ + uobj->user_handle = user_handle; + uobj->context = context; + kref_init(&uobj->ref); + init_rwsem(&uobj->mutex); + uobj->live = 0; +} + +static void release_uobj(struct kref *kref) +{ + kfree(container_of(kref, struct ib_uobject, ref)); +} + +static void put_uobj(struct ib_uobject *uobj) +{ + kref_put(&uobj->ref, release_uobj); +} + +static void put_uobj_read(struct ib_uobject *uobj) +{ + up_read(&uobj->mutex); + put_uobj(uobj); +} + +static void put_uobj_write(struct ib_uobject *uobj) +{ + up_write(&uobj->mutex); + put_uobj(uobj); +} + +static int idr_add_uobj(struct idr *idr, struct ib_uobject *uobj) +{ + int ret; + +retry: + if (!idr_pre_get(idr, GFP_KERNEL)) + return -ENOMEM; + + spin_lock(&ib_uverbs_idr_lock); + ret = idr_get_new(idr, uobj, &uobj->id); + spin_unlock(&ib_uverbs_idr_lock); + + if (ret == -EAGAIN) + goto retry; + + return ret; +} + +void idr_remove_uobj(struct idr *idr, struct ib_uobject *uobj) +{ + spin_lock(&ib_uverbs_idr_lock); + idr_remove(idr, uobj->id); + spin_unlock(&ib_uverbs_idr_lock); +} + +static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id, + struct ib_ucontext *context) +{ + struct ib_uobject *uobj; + + spin_lock(&ib_uverbs_idr_lock); + uobj = idr_find(idr, id); + if (uobj) + kref_get(&uobj->ref); + spin_unlock(&ib_uverbs_idr_lock); + + return uobj; +} + +static struct ib_uobject *idr_read_uobj(struct idr *idr, int id, + struct ib_ucontext *context) +{ + struct ib_uobject *uobj; + + uobj = __idr_get_uobj(idr, id, context); + if (!uobj) + return NULL; + + down_read(&uobj->mutex); + if (!uobj->live) { + put_uobj_read(uobj); + return NULL; + } + + return uobj; +} + +static struct ib_uobject *idr_write_uobj(struct idr *idr, int id, + struct ib_ucontext *context) +{ + struct ib_uobject *uobj; + + uobj = __idr_get_uobj(idr, id, context); + if (!uobj) + return NULL; + + down_write(&uobj->mutex); + if (!uobj->live) { + put_uobj_write(uobj); + return NULL; + } + + return uobj; +} + +static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context) +{ + struct ib_uobject *uobj; + + uobj = idr_read_uobj(idr, id, context); + return uobj ? uobj->object : NULL; +} + +static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context) +{ + return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context); +} + +static void put_pd_read(struct ib_pd *pd) +{ + put_uobj_read(pd->uobject); +} + +static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context) +{ + return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context); +} + +static void put_cq_read(struct ib_cq *cq) +{ + put_uobj_read(cq->uobject); +} + +static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context) +{ + return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context); +} + +static void put_ah_read(struct ib_ah *ah) +{ + put_uobj_read(ah->uobject); +} + +static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context) +{ + return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context); +} + +static void put_qp_read(struct ib_qp *qp) +{ + put_uobj_read(qp->uobject); +} + +static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context) +{ + return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context); +} + +static void put_srq_read(struct ib_srq *srq) +{ + put_uobj_read(srq->uobject); +} + ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len) @@ -80,8 +270,10 @@ ssize_t ib_uverbs_get_context(struct ib_ in_len - sizeof cmd, out_len - sizeof resp); ucontext = ibdev->alloc_ucontext(ibdev, &udata); - if (IS_ERR(ucontext)) - return PTR_ERR(file->ucontext); + if (IS_ERR(ucontext)) { + ret = PTR_ERR(file->ucontext); + goto err; + } ucontext->device = ibdev; INIT_LIST_HEAD(&ucontext->pd_list); @@ -278,7 +470,8 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uve if (!uobj) return -ENOMEM; - uobj->context = file->ucontext; + init_uobj(uobj, 0, file->ucontext); + down_write(&uobj->mutex); pd = file->device->ib_dev->alloc_pd(file->device->ib_dev, file->ucontext, &udata); @@ -291,20 +484,10 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uve pd->uobject = uobj; atomic_set(&pd->usecnt, 0); - mutex_lock(&ib_uverbs_idr_mutex); - -retry: - if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { - ret = -ENOMEM; - goto err_up; - } - - ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id); - - if (ret == -EAGAIN) - goto retry; + uobj->object = pd; + ret = idr_add_uobj(&ib_uverbs_pd_idr, uobj); if (ret) - goto err_up; + goto err_idr; memset(&resp, 0, sizeof resp); resp.pd_handle = uobj->id; @@ -312,26 +495,27 @@ retry: if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { ret = -EFAULT; - goto err_idr; + goto err_copy; } mutex_lock(&file->mutex); list_add_tail(&uobj->list, &file->ucontext->pd_list); mutex_unlock(&file->mutex); - mutex_unlock(&ib_uverbs_idr_mutex); + uobj->live = 1; + + up_write(&uobj->mutex); return in_len; -err_idr: - idr_remove(&ib_uverbs_pd_idr, uobj->id); +err_copy: + idr_remove_uobj(&ib_uverbs_pd_idr, uobj); -err_up: - mutex_unlock(&ib_uverbs_idr_mutex); +err_idr: ib_dealloc_pd(pd); err: - kfree(uobj); + put_uobj_write(uobj); return ret; } @@ -340,37 +524,34 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_u int in_len, int out_len) { struct ib_uverbs_dealloc_pd cmd; - struct ib_pd *pd; struct ib_uobject *uobj; - int ret = -EINVAL; + int ret; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - mutex_lock(&ib_uverbs_idr_mutex); + uobj = idr_write_uobj(&ib_uverbs_pd_idr, cmd.pd_handle, file->ucontext); + if (!uobj) + return -EINVAL; - pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); - if (!pd || pd->uobject->context != file->ucontext) - goto out; + ret = ib_dealloc_pd(uobj->object); + if (!ret) + uobj->live = 0; - uobj = pd->uobject; + put_uobj_write(uobj); - ret = ib_dealloc_pd(pd); if (ret) - goto out; + return ret; - idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); + idr_remove_uobj(&ib_uverbs_pd_idr, uobj); mutex_lock(&file->mutex); list_del(&uobj->list); mutex_unlock(&file->mutex); - kfree(uobj); - -out: - mutex_unlock(&ib_uverbs_idr_mutex); + put_uobj(uobj); - return ret ? ret : in_len; + return in_len; } ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, @@ -410,7 +591,8 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverb if (!obj) return -ENOMEM; - obj->uobject.context = file->ucontext; + init_uobj(&obj->uobject, 0, file->ucontext); + down_write(&obj->uobject.mutex); /* * We ask for writable memory if any access flags other than @@ -427,23 +609,14 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverb obj->umem.virt_base = cmd.hca_va; - mutex_lock(&ib_uverbs_idr_mutex); - - pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); - if (!pd || pd->uobject->context != file->ucontext) { - ret = -EINVAL; - goto err_up; - } - - if (!pd->device->reg_user_mr) { - ret = -ENOSYS; - goto err_up; - } + pd = idr_read_pd(cmd.pd_handle, file->ucontext); + if (!pd) + goto err_release; mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata); if (IS_ERR(mr)) { ret = PTR_ERR(mr); - goto err_up; + goto err_put; } mr->device = pd->device; @@ -452,53 +625,48 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverb atomic_inc(&pd->usecnt); atomic_set(&mr->usecnt, 0); - memset(&resp, 0, sizeof resp); - resp.lkey = mr->lkey; - resp.rkey = mr->rkey; - -retry: - if (!idr_pre_get(&ib_uverbs_mr_idr, GFP_KERNEL)) { - ret = -ENOMEM; - goto err_unreg; - } - - ret = idr_get_new(&ib_uverbs_mr_idr, mr, &obj->uobject.id); - - if (ret == -EAGAIN) - goto retry; + obj->uobject.object = mr; + ret = idr_add_uobj(&ib_uverbs_mr_idr, &obj->uobject); if (ret) goto err_unreg; + memset(&resp, 0, sizeof resp); + resp.lkey = mr->lkey; + resp.rkey = mr->rkey; resp.mr_handle = obj->uobject.id; if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { ret = -EFAULT; - goto err_idr; + goto err_copy; } + put_pd_read(pd); + mutex_lock(&file->mutex); list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); mutex_unlock(&file->mutex); - mutex_unlock(&ib_uverbs_idr_mutex); + obj->uobject.live = 1; + + up_write(&obj->uobject.mutex); return in_len; -err_idr: - idr_remove(&ib_uverbs_mr_idr, obj->uobject.id); +err_copy: + idr_remove_uobj(&ib_uverbs_mr_idr, &obj->uobject); err_unreg: ib_dereg_mr(mr); - atomic_dec(&pd->usecnt); -err_up: - mutex_unlock(&ib_uverbs_idr_mutex); +err_put: + put_pd_read(pd); +err_release: ib_umem_release(file->device->ib_dev, &obj->umem); err_free: - kfree(obj); + put_uobj_write(&obj->uobject); return ret; } @@ -508,37 +676,40 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uve { struct ib_uverbs_dereg_mr cmd; struct ib_mr *mr; + struct ib_uobject *uobj; struct ib_umem_object *memobj; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - mutex_lock(&ib_uverbs_idr_mutex); - - mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); - if (!mr || mr->uobject->context != file->ucontext) - goto out; + uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle, file->ucontext); + if (!uobj) + return -EINVAL; - memobj = container_of(mr->uobject, struct ib_umem_object, uobject); + memobj = container_of(uobj, struct ib_umem_object, uobject); + mr = uobj->object; ret = ib_dereg_mr(mr); + if (!ret) + uobj->live = 0; + + put_uobj_write(uobj); + if (ret) - goto out; + return ret; - idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); + idr_remove_uobj(&ib_uverbs_mr_idr, uobj); mutex_lock(&file->mutex); - list_del(&memobj->uobject.list); + list_del(&uobj->list); mutex_unlock(&file->mutex); ib_umem_release(file->device->ib_dev, &memobj->umem); - kfree(memobj); -out: - mutex_unlock(&ib_uverbs_idr_mutex); + put_uobj(uobj); - return ret ? ret : in_len; + return in_len; } ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file, @@ -577,7 +748,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uv struct ib_uverbs_create_cq cmd; struct ib_uverbs_create_cq_resp resp; struct ib_udata udata; - struct ib_ucq_object *uobj; + struct ib_ucq_object *obj; struct ib_uverbs_event_file *ev_file = NULL; struct ib_cq *cq; int ret; @@ -595,10 +766,13 @@ ssize_t ib_uverbs_create_cq(struct ib_uv if (cmd.comp_vector >= file->device->num_comp_vectors) return -EINVAL; - uobj = kmalloc(sizeof *uobj, GFP_KERNEL); - if (!uobj) + obj = kmalloc(sizeof *obj, GFP_KERNEL); + if (!obj) return -ENOMEM; + init_uobj(&obj->uobject, cmd.user_handle, file->ucontext); + down_write(&obj->uobject.mutex); + if (cmd.comp_channel >= 0) { ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel); if (!ev_file) { @@ -607,72 +781,64 @@ ssize_t ib_uverbs_create_cq(struct ib_uv } } - uobj->uobject.user_handle = cmd.user_handle; - uobj->uobject.context = file->ucontext; - uobj->uverbs_file = file; - uobj->comp_events_reported = 0; - uobj->async_events_reported = 0; - INIT_LIST_HEAD(&uobj->comp_list); - INIT_LIST_HEAD(&uobj->async_list); + obj->uverbs_file = file; + obj->comp_events_reported = 0; + obj->async_events_reported = 0; + INIT_LIST_HEAD(&obj->comp_list); + INIT_LIST_HEAD(&obj->async_list); cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe, file->ucontext, &udata); if (IS_ERR(cq)) { ret = PTR_ERR(cq); - goto err; + goto err_file; } cq->device = file->device->ib_dev; - cq->uobject = &uobj->uobject; + cq->uobject = &obj->uobject; cq->comp_handler = ib_uverbs_comp_handler; cq->event_handler = ib_uverbs_cq_event_handler; cq->cq_context = ev_file; atomic_set(&cq->usecnt, 0); - mutex_lock(&ib_uverbs_idr_mutex); - -retry: - if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { - ret = -ENOMEM; - goto err_up; - } - - ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id); - - if (ret == -EAGAIN) - goto retry; + obj->uobject.object = cq; + ret = idr_add_uobj(&ib_uverbs_cq_idr, &obj->uobject); if (ret) - goto err_up; + goto err_free; memset(&resp, 0, sizeof resp); - resp.cq_handle = uobj->uobject.id; + resp.cq_handle = obj->uobject.id; resp.cqe = cq->cqe; if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { ret = -EFAULT; - goto err_idr; + goto err_copy; } mutex_lock(&file->mutex); - list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); + list_add_tail(&obj->uobject.list, &file->ucontext->cq_list); mutex_unlock(&file->mutex); - mutex_unlock(&ib_uverbs_idr_mutex); + obj->uobject.live = 1; + + up_write(&obj->uobject.mutex); return in_len; -err_idr: - idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); +err_copy: + idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject); + -err_up: - mutex_unlock(&ib_uverbs_idr_mutex); +err_free: ib_destroy_cq(cq); -err: +err_file: if (ev_file) - ib_uverbs_release_ucq(file, ev_file, uobj); - kfree(uobj); + ib_uverbs_release_ucq(file, ev_file, obj); + +err: + put_uobj_write(&obj->uobject); return ret; } @@ -693,11 +859,9 @@ ssize_t ib_uverbs_resize_cq(struct ib_uv (unsigned long) cmd.response + sizeof resp, in_len - sizeof cmd, out_len - sizeof resp); - mutex_lock(&ib_uverbs_idr_mutex); - - cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); - if (!cq || cq->uobject->context != file->ucontext || !cq->device->resize_cq) - goto out; + cq = idr_read_cq(cmd.cq_handle, file->ucontext); + if (!cq) + return -EINVAL; ret = cq->device->resize_cq(cq, cmd.cqe, &udata); if (ret) @@ -711,7 +875,7 @@ ssize_t ib_uverbs_resize_cq(struct ib_uv ret = -EFAULT; out: - mutex_unlock(&ib_uverbs_idr_mutex); + put_cq_read(cq); return ret ? ret : in_len; } @@ -722,6 +886,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uver { struct ib_uverbs_poll_cq cmd; struct ib_uverbs_poll_cq_resp *resp; + struct ib_uobject *uobj; struct ib_cq *cq; struct ib_wc *wc; int ret = 0; @@ -742,15 +907,17 @@ ssize_t ib_uverbs_poll_cq(struct ib_uver goto out_wc; } - mutex_lock(&ib_uverbs_idr_mutex); - cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); - if (!cq || cq->uobject->context != file->ucontext) { + uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext); + if (!uobj) { ret = -EINVAL; goto out; } + cq = uobj->object; resp->count = ib_poll_cq(cq, cmd.ne, wc); + put_uobj_read(uobj); + for (i = 0; i < resp->count; i++) { resp->wc[i].wr_id = wc[i].wr_id; resp->wc[i].status = wc[i].status; @@ -772,7 +939,6 @@ ssize_t ib_uverbs_poll_cq(struct ib_uver ret = -EFAULT; out: - mutex_unlock(&ib_uverbs_idr_mutex); kfree(resp); out_wc: @@ -785,22 +951,23 @@ ssize_t ib_uverbs_req_notify_cq(struct i int out_len) { struct ib_uverbs_req_notify_cq cmd; + struct ib_uobject *uobj; struct ib_cq *cq; - int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - mutex_lock(&ib_uverbs_idr_mutex); - cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); - if (cq && cq->uobject->context == file->ucontext) { - ib_req_notify_cq(cq, cmd.solicited_only ? - IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); - ret = in_len; - } - mutex_unlock(&ib_uverbs_idr_mutex); + uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext); + if (!uobj) + return -EINVAL; + cq = uobj->object; - return ret; + ib_req_notify_cq(cq, cmd.solicited_only ? + IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); + + put_uobj_read(uobj); + + return in_len; } ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, @@ -809,52 +976,50 @@ ssize_t ib_uverbs_destroy_cq(struct ib_u { struct ib_uverbs_destroy_cq cmd; struct ib_uverbs_destroy_cq_resp resp; + struct ib_uobject *uobj; struct ib_cq *cq; - struct ib_ucq_object *uobj; + struct ib_ucq_object *obj; struct ib_uverbs_event_file *ev_file; - u64 user_handle; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - memset(&resp, 0, sizeof resp); - - mutex_lock(&ib_uverbs_idr_mutex); + uobj = idr_write_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext); + if (!uobj) + return -EINVAL; + cq = uobj->object; + ev_file = cq->cq_context; + obj = container_of(cq->uobject, struct ib_ucq_object, uobject); - cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); - if (!cq || cq->uobject->context != file->ucontext) - goto out; + ret = ib_destroy_cq(cq); + if (!ret) + uobj->live = 0; - user_handle = cq->uobject->user_handle; - uobj = container_of(cq->uobject, struct ib_ucq_object, uobject); - ev_file = cq->cq_context; + put_uobj_write(uobj); - ret = ib_destroy_cq(cq); if (ret) - goto out; + return ret; - idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); + idr_remove_uobj(&ib_uverbs_cq_idr, uobj); mutex_lock(&file->mutex); - list_del(&uobj->uobject.list); + list_del(&uobj->list); mutex_unlock(&file->mutex); - ib_uverbs_release_ucq(file, ev_file, uobj); + ib_uverbs_release_ucq(file, ev_file, obj); - resp.comp_events_reported = uobj->comp_events_reported; - resp.async_events_reported = uobj->async_events_reported; + memset(&resp, 0, sizeof resp); + resp.comp_events_reported = obj->comp_events_reported; + resp.async_events_reported = obj->async_events_reported; - kfree(uobj); + put_uobj(uobj); if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) - ret = -EFAULT; - -out: - mutex_unlock(&ib_uverbs_idr_mutex); + return -EFAULT; - return ret ? ret : in_len; + return in_len; } ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, @@ -864,7 +1029,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uv struct ib_uverbs_create_qp cmd; struct ib_uverbs_create_qp_resp resp; struct ib_udata udata; - struct ib_uqp_object *uobj; + struct ib_uqp_object *obj; struct ib_pd *pd; struct ib_cq *scq, *rcq; struct ib_srq *srq; @@ -882,23 +1047,21 @@ ssize_t ib_uverbs_create_qp(struct ib_uv (unsigned long) cmd.response + sizeof resp, in_len - sizeof cmd, out_len - sizeof resp); - uobj = kmalloc(sizeof *uobj, GFP_KERNEL); - if (!uobj) + obj = kmalloc(sizeof *obj, GFP_KERNEL); + if (!obj) return -ENOMEM; - mutex_lock(&ib_uverbs_idr_mutex); + init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext); + down_write(&obj->uevent.uobject.mutex); - pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); - scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); - rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle); - srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL; + pd = idr_read_pd(cmd.pd_handle, file->ucontext); + scq = idr_read_cq(cmd.send_cq_handle, file->ucontext); + rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext); + srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL; - if (!pd || pd->uobject->context != file->ucontext || - !scq || scq->uobject->context != file->ucontext || - !rcq || rcq->uobject->context != file->ucontext || - (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) { + if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) { ret = -EINVAL; - goto err_up; + goto err_put; } attr.event_handler = ib_uverbs_qp_event_handler; @@ -915,16 +1078,14 @@ ssize_t ib_uverbs_create_qp(struct ib_uv attr.cap.max_recv_sge = cmd.max_recv_sge; attr.cap.max_inline_data = cmd.max_inline_data; - uobj->uevent.uobject.user_handle = cmd.user_handle; - uobj->uevent.uobject.context = file->ucontext; - uobj->uevent.events_reported = 0; - INIT_LIST_HEAD(&uobj->uevent.event_list); - INIT_LIST_HEAD(&uobj->mcast_list); + obj->uevent.events_reported = 0; + INIT_LIST_HEAD(&obj->uevent.event_list); + INIT_LIST_HEAD(&obj->mcast_list); qp = pd->device->create_qp(pd, &attr, &udata); if (IS_ERR(qp)) { ret = PTR_ERR(qp); - goto err_up; + goto err_put; } qp->device = pd->device; @@ -932,7 +1093,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uv qp->send_cq = attr.send_cq; qp->recv_cq = attr.recv_cq; qp->srq = attr.srq; - qp->uobject = &uobj->uevent.uobject; + qp->uobject = &obj->uevent.uobject; qp->event_handler = attr.event_handler; qp->qp_context = attr.qp_context; qp->qp_type = attr.qp_type; @@ -942,23 +1103,14 @@ ssize_t ib_uverbs_create_qp(struct ib_uv if (attr.srq) atomic_inc(&attr.srq->usecnt); - memset(&resp, 0, sizeof resp); - resp.qpn = qp->qp_num; - -retry: - if (!idr_pre_get(&ib_uverbs_qp_idr, GFP_KERNEL)) { - ret = -ENOMEM; - goto err_destroy; - } - - ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uevent.uobject.id); - - if (ret == -EAGAIN) - goto retry; + obj->uevent.uobject.object = qp; + ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); if (ret) goto err_destroy; - resp.qp_handle = uobj->uevent.uobject.id; + memset(&resp, 0, sizeof resp); + resp.qpn = qp->qp_num; + resp.qp_handle = obj->uevent.uobject.id; resp.max_recv_sge = attr.cap.max_recv_sge; resp.max_send_sge = attr.cap.max_send_sge; resp.max_recv_wr = attr.cap.max_recv_wr; @@ -968,32 +1120,42 @@ retry: if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { ret = -EFAULT; - goto err_idr; + goto err_copy; } + put_pd_read(pd); + put_cq_read(scq); + put_cq_read(rcq); + if (srq) + put_srq_read(srq); + mutex_lock(&file->mutex); - list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list); + list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list); mutex_unlock(&file->mutex); - mutex_unlock(&ib_uverbs_idr_mutex); + obj->uevent.uobject.live = 1; + + up_write(&obj->uevent.uobject.mutex); return in_len; -err_idr: - idr_remove(&ib_uverbs_qp_idr, uobj->uevent.uobject.id); +err_copy: + idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); err_destroy: ib_destroy_qp(qp); - atomic_dec(&pd->usecnt); - atomic_dec(&attr.send_cq->usecnt); - atomic_dec(&attr.recv_cq->usecnt); - if (attr.srq) - atomic_dec(&attr.srq->usecnt); - -err_up: - mutex_unlock(&ib_uverbs_idr_mutex); - kfree(uobj); +err_put: + if (pd) + put_pd_read(pd); + if (scq) + put_cq_read(scq); + if (rcq) + put_cq_read(rcq); + if (srq) + put_srq_read(srq); + + put_uobj_write(&obj->uevent.uobject); return ret; } @@ -1018,15 +1180,15 @@ ssize_t ib_uverbs_query_qp(struct ib_uve goto out; } - mutex_lock(&ib_uverbs_idr_mutex); - - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); - if (qp && qp->uobject->context == file->ucontext) - ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr); - else + qp = idr_read_qp(cmd.qp_handle, file->ucontext); + if (!qp) { ret = -EINVAL; + goto out; + } - mutex_unlock(&ib_uverbs_idr_mutex); + ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr); + + put_qp_read(qp); if (ret) goto out; @@ -1113,10 +1275,8 @@ ssize_t ib_uverbs_modify_qp(struct ib_uv if (!attr) return -ENOMEM; - mutex_lock(&ib_uverbs_idr_mutex); - - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); - if (!qp || qp->uobject->context != file->ucontext) { + qp = idr_read_qp(cmd.qp_handle, file->ucontext); + if (!qp) { ret = -EINVAL; goto out; } @@ -1168,13 +1328,15 @@ ssize_t ib_uverbs_modify_qp(struct ib_uv attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; ret = ib_modify_qp(qp, attr, cmd.attr_mask); + + put_qp_read(qp); + if (ret) goto out; ret = in_len; out: - mutex_unlock(&ib_uverbs_idr_mutex); kfree(attr); return ret; @@ -1186,8 +1348,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_u { struct ib_uverbs_destroy_qp cmd; struct ib_uverbs_destroy_qp_resp resp; + struct ib_uobject *uobj; struct ib_qp *qp; - struct ib_uqp_object *uobj; + struct ib_uqp_object *obj; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) @@ -1195,43 +1358,43 @@ ssize_t ib_uverbs_destroy_qp(struct ib_u memset(&resp, 0, sizeof resp); - mutex_lock(&ib_uverbs_idr_mutex); - - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); - if (!qp || qp->uobject->context != file->ucontext) - goto out; - - uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); + uobj = idr_write_uobj(&ib_uverbs_qp_idr, cmd.qp_handle, file->ucontext); + if (!uobj) + return -EINVAL; + qp = uobj->object; + obj = container_of(uobj, struct ib_uqp_object, uevent.uobject); - if (!list_empty(&uobj->mcast_list)) { - ret = -EBUSY; - goto out; + if (!list_empty(&obj->mcast_list)) { + put_uobj_write(uobj); + return -EBUSY; } ret = ib_destroy_qp(qp); + if (!ret) + uobj->live = 0; + + put_uobj_write(uobj); + if (ret) - goto out; + return ret; - idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); + idr_remove_uobj(&ib_uverbs_qp_idr, uobj); mutex_lock(&file->mutex); - list_del(&uobj->uevent.uobject.list); + list_del(&uobj->list); mutex_unlock(&file->mutex); - ib_uverbs_release_uevent(file, &uobj->uevent); + ib_uverbs_release_uevent(file, &obj->uevent); - resp.events_reported = uobj->uevent.events_reported; + resp.events_reported = obj->uevent.events_reported; - kfree(uobj); + put_uobj(uobj); if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) - ret = -EFAULT; - -out: - mutex_unlock(&ib_uverbs_idr_mutex); + return -EFAULT; - return ret ? ret : in_len; + return in_len; } ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, @@ -1244,6 +1407,7 @@ ssize_t ib_uverbs_post_send(struct ib_uv struct ib_send_wr *wr = NULL, *last, *next, *bad_wr; struct ib_qp *qp; int i, sg_ind; + int is_ud; ssize_t ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) @@ -1260,12 +1424,11 @@ ssize_t ib_uverbs_post_send(struct ib_uv if (!user_wr) return -ENOMEM; - mutex_lock(&ib_uverbs_idr_mutex); - - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); - if (!qp || qp->uobject->context != file->ucontext) + qp = idr_read_qp(cmd.qp_handle, file->ucontext); + if (!qp) goto out; + is_ud = qp->qp_type == IB_QPT_UD; sg_ind = 0; last = NULL; for (i = 0; i < cmd.wr_count; ++i) { @@ -1273,12 +1436,12 @@ ssize_t ib_uverbs_post_send(struct ib_uv buf + sizeof cmd + i * cmd.wqe_size, cmd.wqe_size)) { ret = -EFAULT; - goto out; + goto out_put; } if (user_wr->num_sge + sg_ind > cmd.sge_count) { ret = -EINVAL; - goto out; + goto out_put; } next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) + @@ -1286,7 +1449,7 @@ ssize_t ib_uverbs_post_send(struct ib_uv GFP_KERNEL); if (!next) { ret = -ENOMEM; - goto out; + goto out_put; } if (!last) @@ -1302,12 +1465,12 @@ ssize_t ib_uverbs_post_send(struct ib_uv next->send_flags = user_wr->send_flags; next->imm_data = (__be32 __force) user_wr->imm_data; - if (qp->qp_type == IB_QPT_UD) { - next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr, - user_wr->wr.ud.ah); + if (is_ud) { + next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah, + file->ucontext); if (!next->wr.ud.ah) { ret = -EINVAL; - goto out; + goto out_put; } next->wr.ud.remote_qpn = user_wr->wr.ud.remote_qpn; next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey; @@ -1344,7 +1507,7 @@ ssize_t ib_uverbs_post_send(struct ib_uv sg_ind * sizeof (struct ib_sge), next->num_sge * sizeof (struct ib_sge))) { ret = -EFAULT; - goto out; + goto out_put; } sg_ind += next->num_sge; } else @@ -1364,15 +1527,18 @@ ssize_t ib_uverbs_post_send(struct ib_uv &resp, sizeof resp)) ret = -EFAULT; -out: - mutex_unlock(&ib_uverbs_idr_mutex); +out_put: + put_qp_read(qp); while (wr) { + if (is_ud && wr->wr.ud.ah) + put_ah_read(wr->wr.ud.ah); next = wr->next; kfree(wr); wr = next; } +out: kfree(user_wr); return ret ? ret : in_len; @@ -1482,14 +1648,15 @@ ssize_t ib_uverbs_post_recv(struct ib_uv if (IS_ERR(wr)) return PTR_ERR(wr); - mutex_lock(&ib_uverbs_idr_mutex); - - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); - if (!qp || qp->uobject->context != file->ucontext) + qp = idr_read_qp(cmd.qp_handle, file->ucontext); + if (!qp) goto out; resp.bad_wr = 0; ret = qp->device->post_recv(qp, wr, &bad_wr); + + put_qp_read(qp); + if (ret) for (next = wr; next; next = next->next) { ++resp.bad_wr; @@ -1503,8 +1670,6 @@ ssize_t ib_uverbs_post_recv(struct ib_uv ret = -EFAULT; out: - mutex_unlock(&ib_uverbs_idr_mutex); - while (wr) { next = wr->next; kfree(wr); @@ -1533,14 +1698,15 @@ ssize_t ib_uverbs_post_srq_recv(struct i if (IS_ERR(wr)) return PTR_ERR(wr); - mutex_lock(&ib_uverbs_idr_mutex); - - srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); - if (!srq || srq->uobject->context != file->ucontext) + srq = idr_read_srq(cmd.srq_handle, file->ucontext); + if (!srq) goto out; resp.bad_wr = 0; ret = srq->device->post_srq_recv(srq, wr, &bad_wr); + + put_srq_read(srq); + if (ret) for (next = wr; next; next = next->next) { ++resp.bad_wr; @@ -1554,8 +1720,6 @@ ssize_t ib_uverbs_post_srq_recv(struct i ret = -EFAULT; out: - mutex_unlock(&ib_uverbs_idr_mutex); - while (wr) { next = wr->next; kfree(wr); @@ -1587,17 +1751,15 @@ ssize_t ib_uverbs_create_ah(struct ib_uv if (!uobj) return -ENOMEM; - mutex_lock(&ib_uverbs_idr_mutex); + init_uobj(uobj, cmd.user_handle, file->ucontext); + down_write(&uobj->mutex); - pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); - if (!pd || pd->uobject->context != file->ucontext) { + pd = idr_read_pd(cmd.pd_handle, file->ucontext); + if (!pd) { ret = -EINVAL; - goto err_up; + goto err; } - uobj->user_handle = cmd.user_handle; - uobj->context = file->ucontext; - attr.dlid = cmd.attr.dlid; attr.sl = cmd.attr.sl; attr.src_path_bits = cmd.attr.src_path_bits; @@ -1613,21 +1775,13 @@ ssize_t ib_uverbs_create_ah(struct ib_uv ah = ib_create_ah(pd, &attr); if (IS_ERR(ah)) { ret = PTR_ERR(ah); - goto err_up; - } - - ah->uobject = uobj; - -retry: - if (!idr_pre_get(&ib_uverbs_ah_idr, GFP_KERNEL)) { - ret = -ENOMEM; - goto err_destroy; + goto err; } - ret = idr_get_new(&ib_uverbs_ah_idr, ah, &uobj->id); + ah->uobject = uobj; + uobj->object = ah; - if (ret == -EAGAIN) - goto retry; + ret = idr_add_uobj(&ib_uverbs_ah_idr, uobj); if (ret) goto err_destroy; @@ -1636,27 +1790,29 @@ retry: if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { ret = -EFAULT; - goto err_idr; + goto err_copy; } + put_pd_read(pd); + mutex_lock(&file->mutex); list_add_tail(&uobj->list, &file->ucontext->ah_list); mutex_unlock(&file->mutex); - mutex_unlock(&ib_uverbs_idr_mutex); + uobj->live = 1; + + up_write(&uobj->mutex); return in_len; -err_idr: - idr_remove(&ib_uverbs_ah_idr, uobj->id); +err_copy: + idr_remove_uobj(&ib_uverbs_ah_idr, uobj); err_destroy: ib_destroy_ah(ah); -err_up: - mutex_unlock(&ib_uverbs_idr_mutex); - - kfree(uobj); +err: + put_uobj_write(uobj); return ret; } @@ -1666,35 +1822,34 @@ ssize_t ib_uverbs_destroy_ah(struct ib_u struct ib_uverbs_destroy_ah cmd; struct ib_ah *ah; struct ib_uobject *uobj; - int ret = -EINVAL; + int ret; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - mutex_lock(&ib_uverbs_idr_mutex); + uobj = idr_write_uobj(&ib_uverbs_ah_idr, cmd.ah_handle, file->ucontext); + if (!uobj) + return -EINVAL; + ah = uobj->object; - ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle); - if (!ah || ah->uobject->context != file->ucontext) - goto out; + ret = ib_destroy_ah(ah); + if (!ret) + uobj->live = 0; - uobj = ah->uobject; + put_uobj_write(uobj); - ret = ib_destroy_ah(ah); if (ret) - goto out; + return ret; - idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle); + idr_remove_uobj(&ib_uverbs_ah_idr, uobj); mutex_lock(&file->mutex); list_del(&uobj->list); mutex_unlock(&file->mutex); - kfree(uobj); + put_uobj(uobj); -out: - mutex_unlock(&ib_uverbs_idr_mutex); - - return ret ? ret : in_len; + return in_len; } ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, @@ -1703,47 +1858,43 @@ ssize_t ib_uverbs_attach_mcast(struct ib { struct ib_uverbs_attach_mcast cmd; struct ib_qp *qp; - struct ib_uqp_object *uobj; + struct ib_uqp_object *obj; struct ib_uverbs_mcast_entry *mcast; - int ret = -EINVAL; + int ret; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - mutex_lock(&ib_uverbs_idr_mutex); - - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); - if (!qp || qp->uobject->context != file->ucontext) - goto out; + qp = idr_read_qp(cmd.qp_handle, file->ucontext); + if (!qp) + return -EINVAL; - uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); + obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); - list_for_each_entry(mcast, &uobj->mcast_list, list) + list_for_each_entry(mcast, &obj->mcast_list, list) if (cmd.mlid == mcast->lid && !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) { ret = 0; - goto out; + goto out_put; } mcast = kmalloc(sizeof *mcast, GFP_KERNEL); if (!mcast) { ret = -ENOMEM; - goto out; + goto out_put; } mcast->lid = cmd.mlid; memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw); ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid); - if (!ret) { - uobj = container_of(qp->uobject, struct ib_uqp_object, - uevent.uobject); - list_add_tail(&mcast->list, &uobj->mcast_list); - } else + if (!ret) + list_add_tail(&mcast->list, &obj->mcast_list); + else kfree(mcast); -out: - mutex_unlock(&ib_uverbs_idr_mutex); +out_put: + put_qp_read(qp); return ret ? ret : in_len; } @@ -1753,7 +1904,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib int out_len) { struct ib_uverbs_detach_mcast cmd; - struct ib_uqp_object *uobj; + struct ib_uqp_object *obj; struct ib_qp *qp; struct ib_uverbs_mcast_entry *mcast; int ret = -EINVAL; @@ -1761,19 +1912,17 @@ ssize_t ib_uverbs_detach_mcast(struct ib if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - mutex_lock(&ib_uverbs_idr_mutex); - - qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); - if (!qp || qp->uobject->context != file->ucontext) - goto out; + qp = idr_read_qp(cmd.qp_handle, file->ucontext); + if (!qp) + return -EINVAL; ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); if (ret) - goto out; + goto out_put; - uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); + obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); - list_for_each_entry(mcast, &uobj->mcast_list, list) + list_for_each_entry(mcast, &obj->mcast_list, list) if (cmd.mlid == mcast->lid && !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) { list_del(&mcast->list); @@ -1781,8 +1930,8 @@ ssize_t ib_uverbs_detach_mcast(struct ib break; } -out: - mutex_unlock(&ib_uverbs_idr_mutex); +out_put: + put_qp_read(qp); return ret ? ret : in_len; } @@ -1794,7 +1943,7 @@ ssize_t ib_uverbs_create_srq(struct ib_u struct ib_uverbs_create_srq cmd; struct ib_uverbs_create_srq_resp resp; struct ib_udata udata; - struct ib_uevent_object *uobj; + struct ib_uevent_object *obj; struct ib_pd *pd; struct ib_srq *srq; struct ib_srq_init_attr attr; @@ -1810,17 +1959,17 @@ ssize_t ib_uverbs_create_srq(struct ib_u (unsigned long) cmd.response + sizeof resp, in_len - sizeof cmd, out_len - sizeof resp); - uobj = kmalloc(sizeof *uobj, GFP_KERNEL); - if (!uobj) + obj = kmalloc(sizeof *obj, GFP_KERNEL); + if (!obj) return -ENOMEM; - mutex_lock(&ib_uverbs_idr_mutex); + init_uobj(&obj->uobject, 0, file->ucontext); + down_write(&obj->uobject.mutex); - pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); - - if (!pd || pd->uobject->context != file->ucontext) { + pd = idr_read_pd(cmd.pd_handle, file->ucontext); + if (!pd) { ret = -EINVAL; - goto err_up; + goto err; } attr.event_handler = ib_uverbs_srq_event_handler; @@ -1829,69 +1978,59 @@ ssize_t ib_uverbs_create_srq(struct ib_u attr.attr.max_sge = cmd.max_sge; attr.attr.srq_limit = cmd.srq_limit; - uobj->uobject.user_handle = cmd.user_handle; - uobj->uobject.context = file->ucontext; - uobj->events_reported = 0; - INIT_LIST_HEAD(&uobj->event_list); + obj->events_reported = 0; + INIT_LIST_HEAD(&obj->event_list); srq = pd->device->create_srq(pd, &attr, &udata); if (IS_ERR(srq)) { ret = PTR_ERR(srq); - goto err_up; + goto err; } srq->device = pd->device; srq->pd = pd; - srq->uobject = &uobj->uobject; + srq->uobject = &obj->uobject; srq->event_handler = attr.event_handler; srq->srq_context = attr.srq_context; atomic_inc(&pd->usecnt); atomic_set(&srq->usecnt, 0); - memset(&resp, 0, sizeof resp); - -retry: - if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) { - ret = -ENOMEM; - goto err_destroy; - } - - ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id); - - if (ret == -EAGAIN) - goto retry; + obj->uobject.object = srq; + ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject); if (ret) goto err_destroy; - resp.srq_handle = uobj->uobject.id; + memset(&resp, 0, sizeof resp); + resp.srq_handle = obj->uobject.id; resp.max_wr = attr.attr.max_wr; resp.max_sge = attr.attr.max_sge; if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { ret = -EFAULT; - goto err_idr; + goto err_copy; } + put_pd_read(pd); + mutex_lock(&file->mutex); - list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); + list_add_tail(&obj->uobject.list, &file->ucontext->srq_list); mutex_unlock(&file->mutex); - mutex_unlock(&ib_uverbs_idr_mutex); + obj->uobject.live = 1; + + up_write(&obj->uobject.mutex); return in_len; -err_idr: - idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id); +err_copy: + idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject); err_destroy: ib_destroy_srq(srq); - atomic_dec(&pd->usecnt); - -err_up: - mutex_unlock(&ib_uverbs_idr_mutex); - kfree(uobj); +err: + put_uobj_write(&obj->uobject); return ret; } @@ -1907,21 +2046,16 @@ ssize_t ib_uverbs_modify_srq(struct ib_u if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - mutex_lock(&ib_uverbs_idr_mutex); - - srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); - if (!srq || srq->uobject->context != file->ucontext) { - ret = -EINVAL; - goto out; - } + srq = idr_read_srq(cmd.srq_handle, file->ucontext); + if (!srq) + return -EINVAL; attr.max_wr = cmd.max_wr; attr.srq_limit = cmd.srq_limit; ret = ib_modify_srq(srq, &attr, cmd.attr_mask); -out: - mutex_unlock(&ib_uverbs_idr_mutex); + put_srq_read(srq); return ret ? ret : in_len; } @@ -1942,18 +2076,16 @@ ssize_t ib_uverbs_query_srq(struct ib_uv if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - mutex_lock(&ib_uverbs_idr_mutex); + srq = idr_read_srq(cmd.srq_handle, file->ucontext); + if (!srq) + return -EINVAL; - srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); - if (srq && srq->uobject->context == file->ucontext) - ret = ib_query_srq(srq, &attr); - else - ret = -EINVAL; + ret = ib_query_srq(srq, &attr); - mutex_unlock(&ib_uverbs_idr_mutex); + put_srq_read(srq); if (ret) - goto out; + return ret; memset(&resp, 0, sizeof resp); @@ -1963,10 +2095,9 @@ ssize_t ib_uverbs_query_srq(struct ib_uv if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) - ret = -EFAULT; + return -EFAULT; -out: - return ret ? ret : in_len; + return in_len; } ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, @@ -1975,45 +2106,45 @@ ssize_t ib_uverbs_destroy_srq(struct ib_ { struct ib_uverbs_destroy_srq cmd; struct ib_uverbs_destroy_srq_resp resp; + struct ib_uobject *uobj; struct ib_srq *srq; - struct ib_uevent_object *uobj; + struct ib_uevent_object *obj; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - mutex_lock(&ib_uverbs_idr_mutex); - - memset(&resp, 0, sizeof resp); + uobj = idr_write_uobj(&ib_uverbs_srq_idr, cmd.srq_handle, file->ucontext); + if (!uobj) + return -EINVAL; + srq = uobj->object; + obj = container_of(uobj, struct ib_uevent_object, uobject); - srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); - if (!srq || srq->uobject->context != file->ucontext) - goto out; + ret = ib_destroy_srq(srq); + if (!ret) + uobj->live = 0; - uobj = container_of(srq->uobject, struct ib_uevent_object, uobject); + put_uobj_write(uobj); - ret = ib_destroy_srq(srq); if (ret) - goto out; + return ret; - idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); + idr_remove_uobj(&ib_uverbs_srq_idr, uobj); mutex_lock(&file->mutex); - list_del(&uobj->uobject.list); + list_del(&uobj->list); mutex_unlock(&file->mutex); - ib_uverbs_release_uevent(file, uobj); + ib_uverbs_release_uevent(file, obj); - resp.events_reported = uobj->events_reported; + memset(&resp, 0, sizeof resp); + resp.events_reported = obj->events_reported; - kfree(uobj); + put_uobj(uobj); if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) ret = -EFAULT; -out: - mutex_unlock(&ib_uverbs_idr_mutex); - return ret ? ret : in_len; } diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index ff092a0..e725ccc 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -66,7 +66,7 @@ #define IB_UVERBS_BASE_DEV MKDEV(IB_UVER static struct class *uverbs_class; -DEFINE_MUTEX(ib_uverbs_idr_mutex); +DEFINE_SPINLOCK(ib_uverbs_idr_lock); DEFINE_IDR(ib_uverbs_pd_idr); DEFINE_IDR(ib_uverbs_mr_idr); DEFINE_IDR(ib_uverbs_mw_idr); @@ -183,47 +183,45 @@ static int ib_uverbs_cleanup_ucontext(st if (!context) return 0; - mutex_lock(&ib_uverbs_idr_mutex); - list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { - struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id); - idr_remove(&ib_uverbs_ah_idr, uobj->id); + struct ib_ah *ah = uobj->object; + + idr_remove_uobj(&ib_uverbs_ah_idr, uobj); ib_destroy_ah(ah); - list_del(&uobj->list); kfree(uobj); } list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) { - struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id); + struct ib_qp *qp = uobj->object; struct ib_uqp_object *uqp = container_of(uobj, struct ib_uqp_object, uevent.uobject); - idr_remove(&ib_uverbs_qp_idr, uobj->id); + + idr_remove_uobj(&ib_uverbs_qp_idr, uobj); ib_uverbs_detach_umcast(qp, uqp); ib_destroy_qp(qp); - list_del(&uobj->list); ib_uverbs_release_uevent(file, &uqp->uevent); kfree(uqp); } list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) { - struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id); + struct ib_cq *cq = uobj->object; struct ib_uverbs_event_file *ev_file = cq->cq_context; struct ib_ucq_object *ucq = container_of(uobj, struct ib_ucq_object, uobject); - idr_remove(&ib_uverbs_cq_idr, uobj->id); + + idr_remove_uobj(&ib_uverbs_cq_idr, uobj); ib_destroy_cq(cq); - list_del(&uobj->list); ib_uverbs_release_ucq(file, ev_file, ucq); kfree(ucq); } list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) { - struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id); + struct ib_srq *srq = uobj->object; struct ib_uevent_object *uevent = container_of(uobj, struct ib_uevent_object, uobject); - idr_remove(&ib_uverbs_srq_idr, uobj->id); + + idr_remove_uobj(&ib_uverbs_srq_idr, uobj); ib_destroy_srq(srq); - list_del(&uobj->list); ib_uverbs_release_uevent(file, uevent); kfree(uevent); } @@ -231,30 +229,27 @@ static int ib_uverbs_cleanup_ucontext(st /* XXX Free MWs */ list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) { - struct ib_mr *mr = idr_find(&ib_uverbs_mr_idr, uobj->id); + struct ib_mr *mr = uobj->object; struct ib_device *mrdev = mr->device; struct ib_umem_object *memobj; - idr_remove(&ib_uverbs_mr_idr, uobj->id); + idr_remove_uobj(&ib_uverbs_mr_idr, uobj); ib_dereg_mr(mr); memobj = container_of(uobj, struct ib_umem_object, uobject); ib_umem_release_on_close(mrdev, &memobj->umem); - list_del(&uobj->list); kfree(memobj); } list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) { - struct ib_pd *pd = idr_find(&ib_uverbs_pd_idr, uobj->id); - idr_remove(&ib_uverbs_pd_idr, uobj->id); + struct ib_pd *pd = uobj->object; + + idr_remove_uobj(&ib_uverbs_pd_idr, uobj); ib_dealloc_pd(pd); - list_del(&uobj->list); kfree(uobj); } - mutex_unlock(&ib_uverbs_idr_mutex); - return context->device->dealloc_ucontext(context); } @@ -820,11 +815,12 @@ static void ib_uverbs_remove_one(struct kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); } -static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) { return get_sb_pseudo(fs_type, "infinibandevent:", NULL, - INFINIBANDEVENTFS_MAGIC); + INFINIBANDEVENTFS_MAGIC, mnt); } static struct file_system_type uverbs_event_fs = { diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c new file mode 100644 index 0000000..ce46b13 --- /dev/null +++ b/drivers/infiniband/core/uverbs_marshall.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2005 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +static void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst, + struct ib_ah_attr *src) +{ + memcpy(dst->grh.dgid, src->grh.dgid.raw, sizeof src->grh.dgid); + dst->grh.flow_label = src->grh.flow_label; + dst->grh.sgid_index = src->grh.sgid_index; + dst->grh.hop_limit = src->grh.hop_limit; + dst->grh.traffic_class = src->grh.traffic_class; + dst->dlid = src->dlid; + dst->sl = src->sl; + dst->src_path_bits = src->src_path_bits; + dst->static_rate = src->static_rate; + dst->is_global = src->ah_flags & IB_AH_GRH ? 1 : 0; + dst->port_num = src->port_num; +} + +void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst, + struct ib_qp_attr *src) +{ + dst->cur_qp_state = src->cur_qp_state; + dst->path_mtu = src->path_mtu; + dst->path_mig_state = src->path_mig_state; + dst->qkey = src->qkey; + dst->rq_psn = src->rq_psn; + dst->sq_psn = src->sq_psn; + dst->dest_qp_num = src->dest_qp_num; + dst->qp_access_flags = src->qp_access_flags; + + dst->max_send_wr = src->cap.max_send_wr; + dst->max_recv_wr = src->cap.max_recv_wr; + dst->max_send_sge = src->cap.max_send_sge; + dst->max_recv_sge = src->cap.max_recv_sge; + dst->max_inline_data = src->cap.max_inline_data; + + ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr); + ib_copy_ah_attr_to_user(&dst->alt_ah_attr, &src->alt_ah_attr); + + dst->pkey_index = src->pkey_index; + dst->alt_pkey_index = src->alt_pkey_index; + dst->en_sqd_async_notify = src->en_sqd_async_notify; + dst->sq_draining = src->sq_draining; + dst->max_rd_atomic = src->max_rd_atomic; + dst->max_dest_rd_atomic = src->max_dest_rd_atomic; + dst->min_rnr_timer = src->min_rnr_timer; + dst->port_num = src->port_num; + dst->timeout = src->timeout; + dst->retry_cnt = src->retry_cnt; + dst->rnr_retry = src->rnr_retry; + dst->alt_port_num = src->alt_port_num; + dst->alt_timeout = src->alt_timeout; +} +EXPORT_SYMBOL(ib_copy_qp_attr_to_user); + +void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst, + struct ib_sa_path_rec *src) +{ + memcpy(dst->dgid, src->dgid.raw, sizeof src->dgid); + memcpy(dst->sgid, src->sgid.raw, sizeof src->sgid); + + dst->dlid = src->dlid; + dst->slid = src->slid; + dst->raw_traffic = src->raw_traffic; + dst->flow_label = src->flow_label; + dst->hop_limit = src->hop_limit; + dst->traffic_class = src->traffic_class; + dst->reversible = src->reversible; + dst->numb_path = src->numb_path; + dst->pkey = src->pkey; + dst->sl = src->sl; + dst->mtu_selector = src->mtu_selector; + dst->mtu = src->mtu; + dst->rate_selector = src->rate_selector; + dst->rate = src->rate; + dst->packet_life_time = src->packet_life_time; + dst->preference = src->preference; + dst->packet_life_time_selector = src->packet_life_time_selector; +} +EXPORT_SYMBOL(ib_copy_path_rec_to_user); + +void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst, + struct ib_user_path_rec *src) +{ + memcpy(dst->dgid.raw, src->dgid, sizeof dst->dgid); + memcpy(dst->sgid.raw, src->sgid, sizeof dst->sgid); + + dst->dlid = src->dlid; + dst->slid = src->slid; + dst->raw_traffic = src->raw_traffic; + dst->flow_label = src->flow_label; + dst->hop_limit = src->hop_limit; + dst->traffic_class = src->traffic_class; + dst->reversible = src->reversible; + dst->numb_path = src->numb_path; + dst->pkey = src->pkey; + dst->sl = src->sl; + dst->mtu_selector = src->mtu_selector; + dst->mtu = src->mtu; + dst->rate_selector = src->rate_selector; + dst->rate = src->rate; + dst->packet_life_time = src->packet_life_time; + dst->preference = src->preference; + dst->packet_life_time_selector = src->packet_life_time_selector; +} +EXPORT_SYMBOL(ib_copy_path_rec_from_user); diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index b78e7dc..468999c 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -125,35 +125,47 @@ struct ib_ah *ib_create_ah(struct ib_pd } EXPORT_SYMBOL(ib_create_ah); -struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, - struct ib_grh *grh, u8 port_num) +int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc, + struct ib_grh *grh, struct ib_ah_attr *ah_attr) { - struct ib_ah_attr ah_attr; u32 flow_class; u16 gid_index; int ret; - memset(&ah_attr, 0, sizeof ah_attr); - ah_attr.dlid = wc->slid; - ah_attr.sl = wc->sl; - ah_attr.src_path_bits = wc->dlid_path_bits; - ah_attr.port_num = port_num; + memset(ah_attr, 0, sizeof *ah_attr); + ah_attr->dlid = wc->slid; + ah_attr->sl = wc->sl; + ah_attr->src_path_bits = wc->dlid_path_bits; + ah_attr->port_num = port_num; if (wc->wc_flags & IB_WC_GRH) { - ah_attr.ah_flags = IB_AH_GRH; - ah_attr.grh.dgid = grh->sgid; + ah_attr->ah_flags = IB_AH_GRH; + ah_attr->grh.dgid = grh->sgid; - ret = ib_find_cached_gid(pd->device, &grh->dgid, &port_num, + ret = ib_find_cached_gid(device, &grh->dgid, &port_num, &gid_index); if (ret) - return ERR_PTR(ret); + return ret; - ah_attr.grh.sgid_index = (u8) gid_index; + ah_attr->grh.sgid_index = (u8) gid_index; flow_class = be32_to_cpu(grh->version_tclass_flow); - ah_attr.grh.flow_label = flow_class & 0xFFFFF; - ah_attr.grh.traffic_class = (flow_class >> 20) & 0xFF; - ah_attr.grh.hop_limit = grh->hop_limit; + ah_attr->grh.flow_label = flow_class & 0xFFFFF; + ah_attr->grh.hop_limit = grh->hop_limit; + ah_attr->grh.traffic_class = (flow_class >> 20) & 0xFF; } + return 0; +} +EXPORT_SYMBOL(ib_init_ah_from_wc); + +struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, + struct ib_grh *grh, u8 port_num) +{ + struct ib_ah_attr ah_attr; + int ret; + + ret = ib_init_ah_from_wc(pd->device, port_num, wc, grh, &ah_attr); + if (ret) + return ERR_PTR(ret); return ib_create_ah(pd, &ah_attr); } diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index e274120..63de304 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -542,13 +542,14 @@ bail: return ret; } -static struct super_block *ipathfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, - void *data) +static int ipathfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) { - ipath_super = get_sb_single(fs_type, flags, data, - ipathfs_fill_super); - return ipath_super; + int ret = get_sb_single(fs_type, flags, data, + ipathfs_fill_super, mnt); + if (ret >= 0) + ipath_super = mnt->mnt_sb; + return ret; } static void ipathfs_kill_super(struct super_block *s) diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c index f7f8391..1a9d0a2 100644 --- a/drivers/infiniband/hw/ipath/ipath_mad.c +++ b/drivers/infiniband/hw/ipath/ipath_mad.c @@ -137,47 +137,11 @@ static int recv_subn_get_guidinfo(struct return reply(smp); } -struct port_info { - __be64 mkey; - __be64 gid_prefix; - __be16 lid; - __be16 sm_lid; - __be32 cap_mask; - __be16 diag_code; - __be16 mkey_lease_period; - u8 local_port_num; - u8 link_width_enabled; - u8 link_width_supported; - u8 link_width_active; - u8 linkspeed_portstate; /* 4 bits, 4 bits */ - u8 portphysstate_linkdown; /* 4 bits, 4 bits */ - u8 mkeyprot_resv_lmc; /* 2 bits, 3, 3 */ - u8 linkspeedactive_enabled; /* 4 bits, 4 bits */ - u8 neighbormtu_mastersmsl; /* 4 bits, 4 bits */ - u8 vlcap_inittype; /* 4 bits, 4 bits */ - u8 vl_high_limit; - u8 vl_arb_high_cap; - u8 vl_arb_low_cap; - u8 inittypereply_mtucap; /* 4 bits, 4 bits */ - u8 vlstallcnt_hoqlife; /* 3 bits, 5 bits */ - u8 operationalvl_pei_peo_fpi_fpo; /* 4 bits, 1, 1, 1, 1 */ - __be16 mkey_violations; - __be16 pkey_violations; - __be16 qkey_violations; - u8 guid_cap; - u8 clientrereg_resv_subnetto; /* 1 bit, 2 bits, 5 */ - u8 resv_resptimevalue; /* 3 bits, 5 bits */ - u8 localphyerrors_overrunerrors; /* 4 bits, 4 bits */ - __be16 max_credit_hint; - u8 resv; - u8 link_roundtrip_latency[3]; -} __attribute__ ((packed)); - static int recv_subn_get_portinfo(struct ib_smp *smp, struct ib_device *ibdev, u8 port) { struct ipath_ibdev *dev; - struct port_info *pip = (struct port_info *)smp->data; + struct ib_port_info *pip = (struct ib_port_info *)smp->data; u16 lid; u8 ibcstat; u8 mtu; @@ -312,7 +276,7 @@ static int recv_subn_set_guidinfo(struct static int recv_subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, u8 port) { - struct port_info *pip = (struct port_info *)smp->data; + struct ib_port_info *pip = (struct ib_port_info *)smp->data; struct ib_event event; struct ipath_ibdev *dev; u32 flags; @@ -445,7 +409,7 @@ static int recv_subn_set_portinfo(struct if (pip->clientrereg_resv_subnetto & 0x80) { clientrereg = 1; - event.event = IB_EVENT_LID_CHANGE; + event.event = IB_EVENT_CLIENT_REREGISTER; ib_dispatch_event(&event); } diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 798e13e..d0f7731 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -174,7 +174,6 @@ enum { struct mthca_cmd_context { struct completion done; - struct timer_list timer; int result; int next; u64 out_param; @@ -362,15 +361,6 @@ void mthca_cmd_event(struct mthca_dev *d complete(&context->done); } -static void event_timeout(unsigned long context_ptr) -{ - struct mthca_cmd_context *context = - (struct mthca_cmd_context *) context_ptr; - - context->result = -EBUSY; - complete(&context->done); -} - static int mthca_cmd_wait(struct mthca_dev *dev, u64 in_param, u64 *out_param, @@ -401,11 +391,10 @@ static int mthca_cmd_wait(struct mthca_d if (err) goto out; - context->timer.expires = jiffies + timeout; - add_timer(&context->timer); - - wait_for_completion(&context->done); - del_timer_sync(&context->timer); + if (!wait_for_completion_timeout(&context->done, timeout)) { + err = -EBUSY; + goto out; + } err = context->result; if (err) @@ -535,10 +524,6 @@ int mthca_cmd_use_events(struct mthca_de for (i = 0; i < dev->cmd.max_cmds; ++i) { dev->cmd.context[i].token = i; dev->cmd.context[i].next = i + 1; - init_timer(&dev->cmd.context[i].timer); - dev->cmd.context[i].timer.data = - (unsigned long) &dev->cmd.context[i]; - dev->cmd.context[i].timer.function = event_timeout; } dev->cmd.context[dev->cmd.max_cmds - 1].next = -1; diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 205854e..3e27a08 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -540,8 +540,17 @@ static inline int mthca_poll_one(struct entry->wr_id = srq->wrid[wqe_index]; mthca_free_srq_wqe(srq, wqe); } else { + s32 wqe; wq = &(*cur_qp)->rq; - wqe_index = be32_to_cpu(cqe->wqe) >> wq->wqe_shift; + wqe = be32_to_cpu(cqe->wqe); + wqe_index = wqe >> wq->wqe_shift; + /* + * WQE addr == base - 1 might be reported in receive completion + * with error instead of (rq size - 1) by Sinai FW 1.0.800 and + * Arbel FW 5.1.400. This bug should be fixed in later FW revs. + */ + if (unlikely(wqe_index < 0)) + wqe_index = wq->max - 1; entry->wr_id = (*cur_qp)->wrid[wqe_index]; } @@ -813,6 +822,7 @@ int mthca_init_cq(struct mthca_dev *dev, spin_lock_init(&cq->lock); cq->refcount = 1; init_waitqueue_head(&cq->wait); + mutex_init(&cq->mutex); memset(cq_context, 0, sizeof *cq_context); cq_context->flags = cpu_to_be32(MTHCA_CQ_STATUS_OK | diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index 99f109c..d536217 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -695,10 +695,6 @@ static void mthca_unmap_reg(struct mthca static int __devinit mthca_map_eq_regs(struct mthca_dev *dev) { - unsigned long mthca_base; - - mthca_base = pci_resource_start(dev->pdev, 0); - if (mthca_is_memfree(dev)) { /* * We assume that the EQ arm and EQ set CI registers diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 4730863..d9bc030 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c @@ -114,14 +114,22 @@ static void smp_snoop(struct ib_device * mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && mad->mad_hdr.method == IB_MGMT_METHOD_SET) { if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) { + struct ib_port_info *pinfo = + (struct ib_port_info *) ((struct ib_smp *) mad)->data; + mthca_update_rate(to_mdev(ibdev), port_num); update_sm_ah(to_mdev(ibdev), port_num, - be16_to_cpup((__be16 *) (mad->data + 58)), - (*(u8 *) (mad->data + 76)) & 0xf); + be16_to_cpu(pinfo->lid), + pinfo->neighbormtu_mastersmsl & 0xf); event.device = ibdev; - event.event = IB_EVENT_LID_CHANGE; event.element.port_num = port_num; + + if(pinfo->clientrereg_resv_subnetto & 0x80) + event.event = IB_EVENT_CLIENT_REREGISTER; + else + event.event = IB_EVENT_LID_CHANGE; + ib_dispatch_event(&event); } diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index a2eae8a..230ae21 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -115,6 +115,16 @@ static int mthca_query_device(struct ib_ props->max_mcast_qp_attach = MTHCA_QP_PER_MGM; props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * props->max_mcast_grp; + /* + * If Sinai memory key optimization is being used, then only + * the 8-bit key portion will change. For other HCAs, the + * unused index bits will also be used for FMR remapping. + */ + if (mdev->mthca_flags & MTHCA_FLAG_SINAI_OPT) + props->max_map_per_fmr = 255; + else + props->max_map_per_fmr = + (1 << (32 - long_log2(mdev->limits.num_mpts))) - 1; err = 0; out: @@ -783,18 +793,24 @@ static int mthca_resize_cq(struct ib_cq if (entries < 1 || entries > dev->limits.max_cqes) return -EINVAL; + mutex_lock(&cq->mutex); + entries = roundup_pow_of_two(entries + 1); - if (entries == ibcq->cqe + 1) - return 0; + if (entries == ibcq->cqe + 1) { + ret = 0; + goto out; + } if (cq->is_kernel) { ret = mthca_alloc_resize_buf(dev, cq, entries); if (ret) - return ret; + goto out; lkey = cq->resize_buf->buf.mr.ibmr.lkey; } else { - if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) - return -EFAULT; + if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { + ret = -EFAULT; + goto out; + } lkey = ucmd.lkey; } @@ -811,7 +827,7 @@ static int mthca_resize_cq(struct ib_cq cq->resize_buf = NULL; spin_unlock_irq(&cq->lock); } - return ret; + goto out; } if (cq->is_kernel) { @@ -838,7 +854,10 @@ static int mthca_resize_cq(struct ib_cq } else ibcq->cqe = entries - 1; - return 0; +out: + mutex_unlock(&cq->mutex); + + return ret; } static int mthca_destroy_cq(struct ib_cq *cq) diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h index 179a8f6..8de2887 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.h +++ b/drivers/infiniband/hw/mthca/mthca_provider.h @@ -214,6 +214,7 @@ struct mthca_cq { int arm_sn; wait_queue_head_t wait; + struct mutex mutex; }; struct mthca_srq { @@ -237,6 +238,7 @@ struct mthca_srq { struct mthca_mr mr; wait_queue_head_t wait; + struct mutex mutex; }; struct mthca_wq { @@ -278,6 +280,7 @@ struct mthca_qp { union mthca_buf queue; wait_queue_head_t wait; + struct mutex mutex; }; struct mthca_sqp { diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 07c13be..16c387d 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -534,7 +534,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct mthca_qp_context *qp_context; u32 sqd_event = 0; u8 status; - int err; + int err = -EINVAL; + + mutex_lock(&qp->mutex); if (attr_mask & IB_QP_CUR_STATE) { cur_state = attr->cur_qp_state; @@ -553,39 +555,41 @@ int mthca_modify_qp(struct ib_qp *ibqp, "%d->%d with attr 0x%08x\n", qp->transport, cur_state, new_state, attr_mask); - return -EINVAL; + goto out; } if ((attr_mask & IB_QP_PKEY_INDEX) && attr->pkey_index >= dev->limits.pkey_table_len) { mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n", attr->pkey_index, dev->limits.pkey_table_len-1); - return -EINVAL; + goto out; } if ((attr_mask & IB_QP_PORT) && (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) { mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num); - return -EINVAL; + goto out; } if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && attr->max_rd_atomic > dev->limits.max_qp_init_rdma) { mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n", attr->max_rd_atomic, dev->limits.max_qp_init_rdma); - return -EINVAL; + goto out; } if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) { mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n", attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift); - return -EINVAL; + goto out; } mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); + if (IS_ERR(mailbox)) { + err = PTR_ERR(mailbox); + goto out; + } qp_param = mailbox->buf; qp_context = &qp_param->context; memset(qp_param, 0, sizeof *qp_param); @@ -618,7 +622,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_2048) { mthca_dbg(dev, "path MTU (%u) is invalid\n", attr->path_mtu); - return -EINVAL; + goto out_mailbox; } qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31; } @@ -672,7 +676,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, if (attr_mask & IB_QP_AV) { if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path, attr_mask & IB_QP_PORT ? attr->port_num : qp->port)) - return -EINVAL; + goto out_mailbox; qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH); } @@ -686,18 +690,18 @@ int mthca_modify_qp(struct ib_qp *ibqp, if (attr->alt_pkey_index >= dev->limits.pkey_table_len) { mthca_dbg(dev, "Alternate P_Key index (%u) too large. max is %d\n", attr->alt_pkey_index, dev->limits.pkey_table_len-1); - return -EINVAL; + goto out_mailbox; } if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) { mthca_dbg(dev, "Alternate port number (%u) is invalid\n", attr->alt_port_num); - return -EINVAL; + goto out_mailbox; } if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path, attr->alt_ah_attr.port_num)) - return -EINVAL; + goto out_mailbox; qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index | attr->alt_port_num << 24); @@ -793,12 +797,12 @@ int mthca_modify_qp(struct ib_qp *ibqp, err = mthca_MODIFY_QP(dev, cur_state, new_state, qp->qpn, 0, mailbox, sqd_event, &status); if (err) - goto out; + goto out_mailbox; if (status) { mthca_warn(dev, "modify QP %d->%d returned status %02x.\n", cur_state, new_state, status); err = -EINVAL; - goto out; + goto out_mailbox; } qp->state = new_state; @@ -853,8 +857,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, } } -out: +out_mailbox: mthca_free_mailbox(dev, mailbox); + +out: + mutex_unlock(&qp->mutex); return err; } @@ -1100,6 +1107,7 @@ static int mthca_alloc_qp_common(struct qp->refcount = 1; init_waitqueue_head(&qp->wait); + mutex_init(&qp->mutex); qp->state = IB_QPS_RESET; qp->atomic_rd_en = 0; qp->resp_depth = 0; diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c index df5e494..f4fddd5 100644 --- a/drivers/infiniband/hw/mthca/mthca_reset.c +++ b/drivers/infiniband/hw/mthca/mthca_reset.c @@ -49,6 +49,12 @@ int mthca_reset(struct mthca_dev *mdev) u32 *hca_header = NULL; u32 *bridge_header = NULL; struct pci_dev *bridge = NULL; + int bridge_pcix_cap = 0; + int hca_pcie_cap = 0; + int hca_pcix_cap = 0; + + u16 devctl; + u16 linkctl; #define MTHCA_RESET_OFFSET 0xf0010 #define MTHCA_RESET_VALUE swab32(1) @@ -110,6 +116,9 @@ #define MTHCA_RESET_VALUE swab32(1) } } + hca_pcix_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX); + hca_pcie_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP); + if (bridge) { bridge_header = kmalloc(256, GFP_KERNEL); if (!bridge_header) { @@ -129,6 +138,13 @@ #define MTHCA_RESET_VALUE swab32(1) goto out; } } + bridge_pcix_cap = pci_find_capability(bridge, PCI_CAP_ID_PCIX); + if (!bridge_pcix_cap) { + err = -ENODEV; + mthca_err(mdev, "Couldn't locate HCA bridge " + "PCI-X capability, aborting.\n"); + goto out; + } } /* actually hit reset */ @@ -178,6 +194,20 @@ #define MTHCA_RESET_VALUE swab32(1) good: /* Now restore the PCI headers */ if (bridge) { + if (pci_write_config_dword(bridge, bridge_pcix_cap + 0x8, + bridge_header[(bridge_pcix_cap + 0x8) / 4])) { + err = -ENODEV; + mthca_err(mdev, "Couldn't restore HCA bridge Upstream " + "split transaction control, aborting.\n"); + goto out; + } + if (pci_write_config_dword(bridge, bridge_pcix_cap + 0xc, + bridge_header[(bridge_pcix_cap + 0xc) / 4])) { + err = -ENODEV; + mthca_err(mdev, "Couldn't restore HCA bridge Downstream " + "split transaction control, aborting.\n"); + goto out; + } /* * Bridge control register is at 0x3e, so we'll * naturally restore it last in this loop. @@ -203,6 +233,35 @@ good: } } + if (hca_pcix_cap) { + if (pci_write_config_dword(mdev->pdev, hca_pcix_cap, + hca_header[hca_pcix_cap / 4])) { + err = -ENODEV; + mthca_err(mdev, "Couldn't restore HCA PCI-X " + "command register, aborting.\n"); + goto out; + } + } + + if (hca_pcie_cap) { + devctl = hca_header[(hca_pcie_cap + PCI_EXP_DEVCTL) / 4]; + if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_DEVCTL, + devctl)) { + err = -ENODEV; + mthca_err(mdev, "Couldn't restore HCA PCI Express " + "Device Control register, aborting.\n"); + goto out; + } + linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4]; + if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_LNKCTL, + linkctl)) { + err = -ENODEV; + mthca_err(mdev, "Couldn't restore HCA PCI Express " + "Link control register, aborting.\n"); + goto out; + } + } + for (i = 0; i < 16; ++i) { if (i * 4 == PCI_COMMAND) continue; diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index b292fef..fab417c 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -243,6 +243,7 @@ int mthca_alloc_srq(struct mthca_dev *de spin_lock_init(&srq->lock); srq->refcount = 1; init_waitqueue_head(&srq->wait); + mutex_init(&srq->mutex); if (mthca_is_memfree(dev)) mthca_arbel_init_srq_context(dev, pd, srq, mailbox->buf); @@ -371,7 +372,11 @@ int mthca_modify_srq(struct ib_srq *ibsr if (attr_mask & IB_SRQ_LIMIT) { if (attr->srq_limit > srq->max) return -EINVAL; + + mutex_lock(&srq->mutex); ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status); + mutex_unlock(&srq->mutex); + if (ret) return ret; if (status) diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 12a1e05..491d2af 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -272,8 +272,7 @@ int ipoib_dev_init(struct net_device *de void ipoib_dev_cleanup(struct net_device *dev); void ipoib_mcast_join_task(void *dev_ptr); -void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid, - struct sk_buff *skb); +void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb); void ipoib_mcast_restart_task(void *dev_ptr); int ipoib_mcast_start_thread(struct net_device *dev); @@ -369,15 +368,26 @@ #define ipoib_dbg_data(priv, format, arg #endif /* CONFIG_INFINIBAND_IPOIB_DEBUG_DATA */ -#define IPOIB_GID_FMT "%x:%x:%x:%x:%x:%x:%x:%x" - -#define IPOIB_GID_ARG(gid) be16_to_cpup((__be16 *) ((gid).raw + 0)), \ - be16_to_cpup((__be16 *) ((gid).raw + 2)), \ - be16_to_cpup((__be16 *) ((gid).raw + 4)), \ - be16_to_cpup((__be16 *) ((gid).raw + 6)), \ - be16_to_cpup((__be16 *) ((gid).raw + 8)), \ - be16_to_cpup((__be16 *) ((gid).raw + 10)), \ - be16_to_cpup((__be16 *) ((gid).raw + 12)), \ - be16_to_cpup((__be16 *) ((gid).raw + 14)) +#define IPOIB_GID_FMT "%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:" \ + "%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x" + +#define IPOIB_GID_RAW_ARG(gid) ((u8 *)(gid))[0], \ + ((u8 *)(gid))[1], \ + ((u8 *)(gid))[2], \ + ((u8 *)(gid))[3], \ + ((u8 *)(gid))[4], \ + ((u8 *)(gid))[5], \ + ((u8 *)(gid))[6], \ + ((u8 *)(gid))[7], \ + ((u8 *)(gid))[8], \ + ((u8 *)(gid))[9], \ + ((u8 *)(gid))[10],\ + ((u8 *)(gid))[11],\ + ((u8 *)(gid))[12],\ + ((u8 *)(gid))[13],\ + ((u8 *)(gid))[14],\ + ((u8 *)(gid))[15] + +#define IPOIB_GID_ARG(gid) IPOIB_GID_RAW_ARG((gid).raw) #endif /* _IPOIB_H */ diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 8406839..5033666 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -84,15 +84,9 @@ void ipoib_free_ah(struct kref *kref) unsigned long flags; - if ((int) priv->tx_tail - (int) ah->last_send >= 0) { - ipoib_dbg(priv, "Freeing ah %p\n", ah->ah); - ib_destroy_ah(ah->ah); - kfree(ah); - } else { - spin_lock_irqsave(&priv->lock, flags); - list_add_tail(&ah->list, &priv->dead_ahs); - spin_unlock_irqrestore(&priv->lock, flags); - } + spin_lock_irqsave(&priv->lock, flags); + list_add_tail(&ah->list, &priv->dead_ahs); + spin_unlock_irqrestore(&priv->lock, flags); } static int ipoib_ib_post_receive(struct net_device *dev, int id) @@ -377,19 +371,16 @@ static void __ipoib_reap_ah(struct net_d struct ipoib_ah *ah, *tah; LIST_HEAD(remove_list); - spin_lock_irq(&priv->lock); + spin_lock_irq(&priv->tx_lock); + spin_lock(&priv->lock); list_for_each_entry_safe(ah, tah, &priv->dead_ahs, list) if ((int) priv->tx_tail - (int) ah->last_send >= 0) { list_del(&ah->list); - list_add_tail(&ah->list, &remove_list); + ib_destroy_ah(ah->ah); + kfree(ah); } - spin_unlock_irq(&priv->lock); - - list_for_each_entry_safe(ah, tah, &remove_list, list) { - ipoib_dbg(priv, "Reaping ah %p\n", ah->ah); - ib_destroy_ah(ah->ah); - kfree(ah); - } + spin_unlock(&priv->lock); + spin_unlock_irq(&priv->tx_lock); } void ipoib_reap_ah(void *dev_ptr) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index cb078a7..1c6ea1c 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -185,8 +185,7 @@ static int ipoib_change_mtu(struct net_d return 0; } -static struct ipoib_path *__path_find(struct net_device *dev, - union ib_gid *gid) +static struct ipoib_path *__path_find(struct net_device *dev, void *gid) { struct ipoib_dev_priv *priv = netdev_priv(dev); struct rb_node *n = priv->path_tree.rb_node; @@ -196,7 +195,7 @@ static struct ipoib_path *__path_find(st while (n) { path = rb_entry(n, struct ipoib_path, rb_node); - ret = memcmp(gid->raw, path->pathrec.dgid.raw, + ret = memcmp(gid, path->pathrec.dgid.raw, sizeof (union ib_gid)); if (ret < 0) @@ -424,8 +423,7 @@ static void path_rec_completion(int stat } } -static struct ipoib_path *path_rec_create(struct net_device *dev, - union ib_gid *gid) +static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid) { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_path *path; @@ -440,7 +438,7 @@ static struct ipoib_path *path_rec_creat INIT_LIST_HEAD(&path->neigh_list); - memcpy(path->pathrec.dgid.raw, gid->raw, sizeof (union ib_gid)); + memcpy(path->pathrec.dgid.raw, gid, sizeof (union ib_gid)); path->pathrec.sgid = priv->local_gid; path->pathrec.pkey = cpu_to_be16(priv->pkey); path->pathrec.numb_path = 1; @@ -498,10 +496,9 @@ static void neigh_add_path(struct sk_buf */ spin_lock(&priv->lock); - path = __path_find(dev, (union ib_gid *) (skb->dst->neighbour->ha + 4)); + path = __path_find(dev, skb->dst->neighbour->ha + 4); if (!path) { - path = path_rec_create(dev, - (union ib_gid *) (skb->dst->neighbour->ha + 4)); + path = path_rec_create(dev, skb->dst->neighbour->ha + 4); if (!path) goto err_path; @@ -551,7 +548,7 @@ static void ipoib_path_lookup(struct sk_ /* Add in the P_Key for multicasts */ skb->dst->neighbour->ha[8] = (priv->pkey >> 8) & 0xff; skb->dst->neighbour->ha[9] = priv->pkey & 0xff; - ipoib_mcast_send(dev, (union ib_gid *) (skb->dst->neighbour->ha + 4), skb); + ipoib_mcast_send(dev, skb->dst->neighbour->ha + 4, skb); } static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, @@ -566,10 +563,9 @@ static void unicast_arp_send(struct sk_b */ spin_lock(&priv->lock); - path = __path_find(dev, (union ib_gid *) (phdr->hwaddr + 4)); + path = __path_find(dev, phdr->hwaddr + 4); if (!path) { - path = path_rec_create(dev, - (union ib_gid *) (phdr->hwaddr + 4)); + path = path_rec_create(dev, phdr->hwaddr + 4); if (path) { /* put pseudoheader back on for next time */ skb_push(skb, sizeof *phdr); @@ -660,7 +656,7 @@ static int ipoib_start_xmit(struct sk_bu phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff; phdr->hwaddr[9] = priv->pkey & 0xff; - ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb); + ipoib_mcast_send(dev, phdr->hwaddr + 4, skb); } else { /* unicast GID -- should be ARP or RARP reply */ @@ -671,7 +667,7 @@ static int ipoib_start_xmit(struct sk_bu skb->dst ? "neigh" : "dst", be16_to_cpup((__be16 *) skb->data), be32_to_cpup((__be32 *) phdr->hwaddr), - IPOIB_GID_ARG(*(union ib_gid *) (phdr->hwaddr + 4))); + IPOIB_GID_RAW_ARG(phdr->hwaddr + 4)); dev_kfree_skb_any(skb); ++priv->stats.tx_dropped; goto out; @@ -754,7 +750,7 @@ static void ipoib_neigh_destructor(struc ipoib_dbg(priv, "neigh_destructor for %06x " IPOIB_GID_FMT "\n", be32_to_cpup((__be32 *) n->ha), - IPOIB_GID_ARG(*((union ib_gid *) (n->ha + 4)))); + IPOIB_GID_RAW_ARG(n->ha + 4)); spin_lock_irqsave(&priv->lock, flags); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 1dae4b2..ab40488 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -154,7 +154,7 @@ static struct ipoib_mcast *ipoib_mcast_a return mcast; } -static struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, union ib_gid *mgid) +static struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, void *mgid) { struct ipoib_dev_priv *priv = netdev_priv(dev); struct rb_node *n = priv->multicast_tree.rb_node; @@ -165,7 +165,7 @@ static struct ipoib_mcast *__ipoib_mcast mcast = rb_entry(n, struct ipoib_mcast, rb_node); - ret = memcmp(mgid->raw, mcast->mcmember.mgid.raw, + ret = memcmp(mgid, mcast->mcmember.mgid.raw, sizeof (union ib_gid)); if (ret < 0) n = n->rb_left; @@ -694,8 +694,7 @@ static int ipoib_mcast_leave(struct net_ return 0; } -void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid, - struct sk_buff *skb) +void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_mcast *mcast; @@ -718,7 +717,7 @@ void ipoib_mcast_send(struct net_device if (!mcast) { /* Let's create a new send only group now */ ipoib_dbg_mcast(priv, "setting up send only multicast group for " - IPOIB_GID_FMT "\n", IPOIB_GID_ARG(*mgid)); + IPOIB_GID_FMT "\n", IPOIB_GID_RAW_ARG(mgid)); mcast = ipoib_mcast_alloc(dev, 0); if (!mcast) { @@ -730,7 +729,7 @@ void ipoib_mcast_send(struct net_device } set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags); - mcast->mcmember.mgid = *mgid; + memcpy(mcast->mcmember.mgid.raw, mgid, sizeof (union ib_gid)); __ipoib_mcast_add(dev, mcast); list_add_tail(&mcast->list, &priv->multicast_list); } @@ -821,7 +820,8 @@ void ipoib_mcast_restart_task(void *dev_ ipoib_mcast_stop_thread(dev, 0); - spin_lock_irqsave(&dev->xmit_lock, flags); + local_irq_save(flags); + netif_tx_lock(dev); spin_lock(&priv->lock); /* @@ -864,8 +864,7 @@ void ipoib_mcast_restart_task(void *dev_ if (mcast) { /* Destroy the send only entry */ - list_del(&mcast->list); - list_add_tail(&mcast->list, &remove_list); + list_move_tail(&mcast->list, &remove_list); rb_replace_node(&mcast->rb_node, &nmcast->rb_node, @@ -890,13 +889,13 @@ void ipoib_mcast_restart_task(void *dev_ rb_erase(&mcast->rb_node, &priv->multicast_tree); /* Move to the remove list */ - list_del(&mcast->list); - list_add_tail(&mcast->list, &remove_list); + list_move_tail(&mcast->list, &remove_list); } } spin_unlock(&priv->lock); - spin_unlock_irqrestore(&dev->xmit_lock, flags); + netif_tx_unlock(dev); + local_irq_restore(flags); /* We have to cancel outside of the spinlock */ list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index 1d49d16..7b717c6 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c @@ -255,7 +255,8 @@ void ipoib_event(struct ib_event_handler record->event == IB_EVENT_PKEY_CHANGE || record->event == IB_EVENT_PORT_ACTIVE || record->event == IB_EVENT_LID_CHANGE || - record->event == IB_EVENT_SM_CHANGE) { + record->event == IB_EVENT_SM_CHANGE || + record->event == IB_EVENT_CLIENT_REREGISTER) { ipoib_dbg(priv, "Port state change event\n"); queue_work(ipoib_workqueue, &priv->flush_task); } diff --git a/drivers/infiniband/ulp/iser/Kconfig b/drivers/infiniband/ulp/iser/Kconfig new file mode 100644 index 0000000..fead87d --- /dev/null +++ b/drivers/infiniband/ulp/iser/Kconfig @@ -0,0 +1,11 @@ +config INFINIBAND_ISER + tristate "ISCSI RDMA Protocol" + depends on INFINIBAND && SCSI + select SCSI_ISCSI_ATTRS + ---help--- + Support for the ISCSI RDMA Protocol over InfiniBand. This + allows you to access storage devices that speak ISER/ISCSI + over InfiniBand. + + The ISER protocol is defined by IETF. + See . diff --git a/drivers/infiniband/ulp/iser/Makefile b/drivers/infiniband/ulp/iser/Makefile new file mode 100644 index 0000000..fe6cd15 --- /dev/null +++ b/drivers/infiniband/ulp/iser/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_INFINIBAND_ISER) += ib_iser.o + +ib_iser-y := iser_verbs.o iser_initiator.o iser_memory.o \ + iscsi_iser.o diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c new file mode 100644 index 0000000..4c3f2de --- /dev/null +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -0,0 +1,790 @@ +/* + * iSCSI Initiator over iSER Data-Path + * + * Copyright (C) 2004 Dmitry Yusupov + * Copyright (C) 2004 Alex Aizman + * Copyright (C) 2005 Mike Christie + * Copyright (c) 2005, 2006 Voltaire, Inc. All rights reserved. + * maintained by openib-general@openib.org + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Credits: + * Christoph Hellwig + * FUJITA Tomonori + * Arne Redlich + * Zhenyu Wang + * Modified by: + * Erez Zilber + * + * + * $Id: iscsi_iser.c 6965 2006-05-07 11:36:20Z ogerlitz $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "iscsi_iser.h" + +static unsigned int iscsi_max_lun = 512; +module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); + +int iser_debug_level = 0; + +MODULE_DESCRIPTION("iSER (iSCSI Extensions for RDMA) Datamover " + "v" DRV_VER " (" DRV_DATE ")"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Alex Nezhinsky, Dan Bar Dov, Or Gerlitz"); + +module_param_named(debug_level, iser_debug_level, int, 0644); +MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0 (default:disabled)"); + +struct iser_global ig; + +void +iscsi_iser_recv(struct iscsi_conn *conn, + struct iscsi_hdr *hdr, char *rx_data, int rx_data_len) +{ + int rc = 0; + uint32_t ret_itt; + int datalen; + int ahslen; + + /* verify PDU length */ + datalen = ntoh24(hdr->dlength); + if (datalen != rx_data_len) { + printk(KERN_ERR "iscsi_iser: datalen %d (hdr) != %d (IB) \n", + datalen, rx_data_len); + rc = ISCSI_ERR_DATALEN; + goto error; + } + + /* read AHS */ + ahslen = hdr->hlength * 4; + + /* verify itt (itt encoding: age+cid+itt) */ + rc = iscsi_verify_itt(conn, hdr, &ret_itt); + + if (!rc) + rc = iscsi_complete_pdu(conn, hdr, rx_data, rx_data_len); + + if (rc && rc != ISCSI_ERR_NO_SCSI_CMD) + goto error; + + return; +error: + iscsi_conn_failure(conn, rc); +} + + +/** + * iscsi_iser_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands + * + **/ +static void +iscsi_iser_cmd_init(struct iscsi_cmd_task *ctask) +{ + struct iscsi_iser_conn *iser_conn = ctask->conn->dd_data; + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + struct scsi_cmnd *sc = ctask->sc; + + iser_ctask->command_sent = 0; + iser_ctask->iser_conn = iser_conn; + + if (sc->sc_data_direction == DMA_TO_DEVICE) { + BUG_ON(ctask->total_length == 0); + /* bytes to be sent via RDMA operations */ + iser_ctask->rdma_data_count = ctask->total_length - + ctask->imm_count - + ctask->unsol_count; + + debug_scsi("cmd [itt %x total %d imm %d unsol_data %d " + "rdma_data %d]\n", + ctask->itt, ctask->total_length, ctask->imm_count, + ctask->unsol_count, iser_ctask->rdma_data_count); + } else + /* bytes to be sent via RDMA operations */ + iser_ctask->rdma_data_count = ctask->total_length; + + iser_ctask_rdma_init(iser_ctask); +} + +/** + * iscsi_mtask_xmit - xmit management(immediate) task + * @conn: iscsi connection + * @mtask: task management task + * + * Notes: + * The function can return -EAGAIN in which case caller must + * call it again later, or recover. '0' return code means successful + * xmit. + * + **/ +static int +iscsi_iser_mtask_xmit(struct iscsi_conn *conn, + struct iscsi_mgmt_task *mtask) +{ + int error = 0; + + debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, mtask->itt); + + error = iser_send_control(conn, mtask); + + /* since iser xmits control with zero copy, mtasks can not be recycled + * right after sending them. + * The recycling scheme is based on whether a response is expected + * - if yes, the mtask is recycled at iscsi_complete_pdu + * - if no, the mtask is recycled at iser_snd_completion + */ + if (error && error != -EAGAIN) + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + + return error; +} + +static int +iscsi_iser_ctask_xmit_unsol_data(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask) +{ + struct iscsi_data hdr; + int error = 0; + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + + /* Send data-out PDUs while there's still unsolicited data to send */ + while (ctask->unsol_count > 0) { + iscsi_prep_unsolicit_data_pdu(ctask, &hdr, + iser_ctask->rdma_data_count); + + debug_scsi("Sending data-out: itt 0x%x, data count %d\n", + hdr.itt, ctask->data_count); + + /* the buffer description has been passed with the command */ + /* Send the command */ + error = iser_send_data_out(conn, ctask, &hdr); + if (error) { + ctask->unsol_datasn--; + goto iscsi_iser_ctask_xmit_unsol_data_exit; + } + ctask->unsol_count -= ctask->data_count; + debug_scsi("Need to send %d more as data-out PDUs\n", + ctask->unsol_count); + } + +iscsi_iser_ctask_xmit_unsol_data_exit: + return error; +} + +static int +iscsi_iser_ctask_xmit(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask) +{ + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + int error = 0; + + debug_scsi("ctask deq [cid %d itt 0x%x]\n", + conn->id, ctask->itt); + + /* + * serialize with TMF AbortTask + */ + if (ctask->mtask) + return error; + + /* Send the cmd PDU */ + if (!iser_ctask->command_sent) { + error = iser_send_command(conn, ctask); + if (error) + goto iscsi_iser_ctask_xmit_exit; + iser_ctask->command_sent = 1; + } + + /* Send unsolicited data-out PDU(s) if necessary */ + if (ctask->unsol_count) + error = iscsi_iser_ctask_xmit_unsol_data(conn, ctask); + + iscsi_iser_ctask_xmit_exit: + if (error && error != -EAGAIN) + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + return error; +} + +static void +iscsi_iser_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +{ + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + + if (iser_ctask->status == ISER_TASK_STATUS_STARTED) { + iser_ctask->status = ISER_TASK_STATUS_COMPLETED; + iser_ctask_rdma_finalize(iser_ctask); + } +} + +static struct iser_conn * +iscsi_iser_ib_conn_lookup(__u64 ep_handle) +{ + struct iser_conn *ib_conn; + struct iser_conn *uib_conn = (struct iser_conn *)(unsigned long)ep_handle; + + mutex_lock(&ig.connlist_mutex); + list_for_each_entry(ib_conn, &ig.connlist, conn_list) { + if (ib_conn == uib_conn) { + mutex_unlock(&ig.connlist_mutex); + return ib_conn; + } + } + mutex_unlock(&ig.connlist_mutex); + iser_err("no conn exists for eph %llx\n",(unsigned long long)ep_handle); + return NULL; +} + +static struct iscsi_cls_conn * +iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) +{ + struct iscsi_conn *conn; + struct iscsi_cls_conn *cls_conn; + struct iscsi_iser_conn *iser_conn; + + cls_conn = iscsi_conn_setup(cls_session, conn_idx); + if (!cls_conn) + return NULL; + conn = cls_conn->dd_data; + + /* + * due to issues with the login code re iser sematics + * this not set in iscsi_conn_setup - FIXME + */ + conn->max_recv_dlength = 128; + + iser_conn = kzalloc(sizeof(*iser_conn), GFP_KERNEL); + if (!iser_conn) + goto conn_alloc_fail; + + /* currently this is the only field which need to be initiated */ + rwlock_init(&iser_conn->lock); + + conn->dd_data = iser_conn; + iser_conn->iscsi_conn = conn; + + return cls_conn; + +conn_alloc_fail: + iscsi_conn_teardown(cls_conn); + return NULL; +} + +static void +iscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_iser_conn *iser_conn = conn->dd_data; + + iscsi_conn_teardown(cls_conn); + kfree(iser_conn); +} + +static int +iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, + struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, + int is_leading) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_iser_conn *iser_conn; + struct iser_conn *ib_conn; + int error; + + error = iscsi_conn_bind(cls_session, cls_conn, is_leading); + if (error) + return error; + + /* the transport ep handle comes from user space so it must be + * verified against the global ib connections list */ + ib_conn = iscsi_iser_ib_conn_lookup(transport_eph); + if (!ib_conn) { + iser_err("can't bind eph %llx\n", + (unsigned long long)transport_eph); + return -EINVAL; + } + /* binds the iSER connection retrieved from the previously + * connected ep_handle to the iSCSI layer connection. exchanges + * connection pointers */ + iser_err("binding iscsi conn %p to iser_conn %p\n",conn,ib_conn); + iser_conn = conn->dd_data; + ib_conn->iser_conn = iser_conn; + iser_conn->ib_conn = ib_conn; + + conn->recv_lock = &iser_conn->lock; + + return 0; +} + +static int +iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + int err; + + err = iscsi_conn_start(cls_conn); + if (err) + return err; + + return iser_conn_set_full_featured_mode(conn); +} + +static void +iscsi_iser_conn_terminate(struct iscsi_conn *conn) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + struct iser_conn *ib_conn = iser_conn->ib_conn; + + BUG_ON(!ib_conn); + /* starts conn teardown process, waits until all previously * + * posted buffers get flushed, deallocates all conn resources */ + iser_conn_terminate(ib_conn); + iser_conn->ib_conn = NULL; + conn->recv_lock = NULL; +} + + +static struct iscsi_transport iscsi_iser_transport; + +static struct iscsi_cls_session * +iscsi_iser_session_create(struct iscsi_transport *iscsit, + struct scsi_transport_template *scsit, + uint32_t initial_cmdsn, uint32_t *hostno) +{ + struct iscsi_cls_session *cls_session; + struct iscsi_session *session; + int i; + uint32_t hn; + struct iscsi_cmd_task *ctask; + struct iscsi_mgmt_task *mtask; + struct iscsi_iser_cmd_task *iser_ctask; + struct iser_desc *desc; + + cls_session = iscsi_session_setup(iscsit, scsit, + sizeof(struct iscsi_iser_cmd_task), + sizeof(struct iser_desc), + initial_cmdsn, &hn); + if (!cls_session) + return NULL; + + *hostno = hn; + session = class_to_transport_session(cls_session); + + /* libiscsi setup itts, data and pool so just set desc fields */ + for (i = 0; i < session->cmds_max; i++) { + ctask = session->cmds[i]; + iser_ctask = ctask->dd_data; + ctask->hdr = (struct iscsi_cmd *)&iser_ctask->desc.iscsi_header; + } + + for (i = 0; i < session->mgmtpool_max; i++) { + mtask = session->mgmt_cmds[i]; + desc = mtask->dd_data; + mtask->hdr = &desc->iscsi_header; + desc->data = mtask->data; + } + + return cls_session; +} + +static int +iscsi_iser_conn_set_param(struct iscsi_cls_conn *cls_conn, + enum iscsi_param param, uint32_t value) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; + + spin_lock_bh(&session->lock); + if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE && + conn->stop_stage != STOP_CONN_RECOVER) { + printk(KERN_ERR "iscsi_iser: can not change parameter [%d]\n", + param); + spin_unlock_bh(&session->lock); + return 0; + } + spin_unlock_bh(&session->lock); + + switch (param) { + case ISCSI_PARAM_MAX_RECV_DLENGTH: + /* TBD */ + break; + case ISCSI_PARAM_MAX_XMIT_DLENGTH: + conn->max_xmit_dlength = value; + break; + case ISCSI_PARAM_HDRDGST_EN: + if (value) { + printk(KERN_ERR "DataDigest wasn't negotiated to None"); + return -EPROTO; + } + break; + case ISCSI_PARAM_DATADGST_EN: + if (value) { + printk(KERN_ERR "DataDigest wasn't negotiated to None"); + return -EPROTO; + } + break; + case ISCSI_PARAM_INITIAL_R2T_EN: + session->initial_r2t_en = value; + break; + case ISCSI_PARAM_IMM_DATA_EN: + session->imm_data_en = value; + break; + case ISCSI_PARAM_FIRST_BURST: + session->first_burst = value; + break; + case ISCSI_PARAM_MAX_BURST: + session->max_burst = value; + break; + case ISCSI_PARAM_PDU_INORDER_EN: + session->pdu_inorder_en = value; + break; + case ISCSI_PARAM_DATASEQ_INORDER_EN: + session->dataseq_inorder_en = value; + break; + case ISCSI_PARAM_ERL: + session->erl = value; + break; + case ISCSI_PARAM_IFMARKER_EN: + if (value) { + printk(KERN_ERR "IFMarker wasn't negotiated to No"); + return -EPROTO; + } + break; + case ISCSI_PARAM_OFMARKER_EN: + if (value) { + printk(KERN_ERR "OFMarker wasn't negotiated to No"); + return -EPROTO; + } + break; + default: + break; + } + + return 0; +} + +static int +iscsi_iser_session_get_param(struct iscsi_cls_session *cls_session, + enum iscsi_param param, uint32_t *value) +{ + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); + + switch (param) { + case ISCSI_PARAM_INITIAL_R2T_EN: + *value = session->initial_r2t_en; + break; + case ISCSI_PARAM_MAX_R2T: + *value = session->max_r2t; + break; + case ISCSI_PARAM_IMM_DATA_EN: + *value = session->imm_data_en; + break; + case ISCSI_PARAM_FIRST_BURST: + *value = session->first_burst; + break; + case ISCSI_PARAM_MAX_BURST: + *value = session->max_burst; + break; + case ISCSI_PARAM_PDU_INORDER_EN: + *value = session->pdu_inorder_en; + break; + case ISCSI_PARAM_DATASEQ_INORDER_EN: + *value = session->dataseq_inorder_en; + break; + case ISCSI_PARAM_ERL: + *value = session->erl; + break; + case ISCSI_PARAM_IFMARKER_EN: + *value = 0; + break; + case ISCSI_PARAM_OFMARKER_EN: + *value = 0; + break; + default: + return ISCSI_ERR_PARAM_NOT_FOUND; + } + + return 0; +} + +static int +iscsi_iser_conn_get_param(struct iscsi_cls_conn *cls_conn, + enum iscsi_param param, uint32_t *value) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + + switch(param) { + case ISCSI_PARAM_MAX_RECV_DLENGTH: + *value = conn->max_recv_dlength; + break; + case ISCSI_PARAM_MAX_XMIT_DLENGTH: + *value = conn->max_xmit_dlength; + break; + case ISCSI_PARAM_HDRDGST_EN: + *value = 0; + break; + case ISCSI_PARAM_DATADGST_EN: + *value = 0; + break; + /*case ISCSI_PARAM_TARGET_RECV_DLENGTH: + *value = conn->target_recv_dlength; + break; + case ISCSI_PARAM_INITIATOR_RECV_DLENGTH: + *value = conn->initiator_recv_dlength; + break;*/ + default: + return ISCSI_ERR_PARAM_NOT_FOUND; + } + + return 0; +} + + +static void +iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + + stats->txdata_octets = conn->txdata_octets; + stats->rxdata_octets = conn->rxdata_octets; + stats->scsicmd_pdus = conn->scsicmd_pdus_cnt; + stats->dataout_pdus = conn->dataout_pdus_cnt; + stats->scsirsp_pdus = conn->scsirsp_pdus_cnt; + stats->datain_pdus = conn->datain_pdus_cnt; /* always 0 */ + stats->r2t_pdus = conn->r2t_pdus_cnt; /* always 0 */ + stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt; + stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; + stats->custom_length = 3; + strcpy(stats->custom[0].desc, "qp_tx_queue_full"); + stats->custom[0].value = 0; /* TB iser_conn->qp_tx_queue_full; */ + strcpy(stats->custom[1].desc, "fmr_map_not_avail"); + stats->custom[1].value = 0; /* TB iser_conn->fmr_map_not_avail */; + strcpy(stats->custom[2].desc, "eh_abort_cnt"); + stats->custom[2].value = conn->eh_abort_cnt; +} + +static int +iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking, + __u64 *ep_handle) +{ + int err; + struct iser_conn *ib_conn; + + err = iser_conn_init(&ib_conn); + if (err) + goto out; + + err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr, non_blocking); + if (!err) + *ep_handle = (__u64)(unsigned long)ib_conn; + +out: + return err; +} + +static int +iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms) +{ + struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle); + int rc; + + if (!ib_conn) + return -EINVAL; + + rc = wait_event_interruptible_timeout(ib_conn->wait, + ib_conn->state == ISER_CONN_UP, + msecs_to_jiffies(timeout_ms)); + + /* if conn establishment failed, return error code to iscsi */ + if (!rc && + (ib_conn->state == ISER_CONN_TERMINATING || + ib_conn->state == ISER_CONN_DOWN)) + rc = -1; + + iser_err("ib conn %p rc = %d\n", ib_conn, rc); + + if (rc > 0) + return 1; /* success, this is the equivalent of POLLOUT */ + else if (!rc) + return 0; /* timeout */ + else + return rc; /* signal */ +} + +static void +iscsi_iser_ep_disconnect(__u64 ep_handle) +{ + struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle); + + if (!ib_conn) + return; + + iser_err("ib conn %p state %d\n",ib_conn, ib_conn->state); + + iser_conn_terminate(ib_conn); +} + +static struct scsi_host_template iscsi_iser_sht = { + .name = "iSCSI Initiator over iSER, v." DRV_VER, + .queuecommand = iscsi_queuecommand, + .can_queue = ISCSI_XMIT_CMDS_MAX - 1, + .sg_tablesize = ISCSI_ISER_SG_TABLESIZE, + .cmd_per_lun = ISCSI_MAX_CMD_PER_LUN, + .eh_abort_handler = iscsi_eh_abort, + .eh_host_reset_handler = iscsi_eh_host_reset, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "iscsi_iser", + .this_id = -1, +}; + +static struct iscsi_transport iscsi_iser_transport = { + .owner = THIS_MODULE, + .name = "iser", + .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T, + .param_mask = ISCSI_MAX_RECV_DLENGTH | + ISCSI_MAX_XMIT_DLENGTH | + ISCSI_HDRDGST_EN | + ISCSI_DATADGST_EN | + ISCSI_INITIAL_R2T_EN | + ISCSI_MAX_R2T | + ISCSI_IMM_DATA_EN | + ISCSI_FIRST_BURST | + ISCSI_MAX_BURST | + ISCSI_PDU_INORDER_EN | + ISCSI_DATASEQ_INORDER_EN, + .host_template = &iscsi_iser_sht, + .conndata_size = sizeof(struct iscsi_conn), + .max_lun = ISCSI_ISER_MAX_LUN, + .max_cmd_len = ISCSI_ISER_MAX_CMD_LEN, + /* session management */ + .create_session = iscsi_iser_session_create, + .destroy_session = iscsi_session_teardown, + /* connection management */ + .create_conn = iscsi_iser_conn_create, + .bind_conn = iscsi_iser_conn_bind, + .destroy_conn = iscsi_iser_conn_destroy, + .set_param = iscsi_iser_conn_set_param, + .get_conn_param = iscsi_iser_conn_get_param, + .get_session_param = iscsi_iser_session_get_param, + .start_conn = iscsi_iser_conn_start, + .stop_conn = iscsi_conn_stop, + /* these are called as part of conn recovery */ + .suspend_conn_recv = NULL, /* FIXME is/how this relvant to iser? */ + .terminate_conn = iscsi_iser_conn_terminate, + /* IO */ + .send_pdu = iscsi_conn_send_pdu, + .get_stats = iscsi_iser_conn_get_stats, + .init_cmd_task = iscsi_iser_cmd_init, + .xmit_cmd_task = iscsi_iser_ctask_xmit, + .xmit_mgmt_task = iscsi_iser_mtask_xmit, + .cleanup_cmd_task = iscsi_iser_cleanup_ctask, + /* recovery */ + .session_recovery_timedout = iscsi_session_recovery_timedout, + + .ep_connect = iscsi_iser_ep_connect, + .ep_poll = iscsi_iser_ep_poll, + .ep_disconnect = iscsi_iser_ep_disconnect +}; + +static int __init iser_init(void) +{ + int err; + + iser_dbg("Starting iSER datamover...\n"); + + if (iscsi_max_lun < 1) { + printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); + return -EINVAL; + } + + iscsi_iser_transport.max_lun = iscsi_max_lun; + + memset(&ig, 0, sizeof(struct iser_global)); + + ig.desc_cache = kmem_cache_create("iser_descriptors", + sizeof (struct iser_desc), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (ig.desc_cache == NULL) + return -ENOMEM; + + /* device init is called only after the first addr resolution */ + mutex_init(&ig.device_list_mutex); + INIT_LIST_HEAD(&ig.device_list); + mutex_init(&ig.connlist_mutex); + INIT_LIST_HEAD(&ig.connlist); + + if (!iscsi_register_transport(&iscsi_iser_transport)) { + iser_err("iscsi_register_transport failed\n"); + err = -EINVAL; + goto register_transport_failure; + } + + return 0; + +register_transport_failure: + kmem_cache_destroy(ig.desc_cache); + + return err; +} + +static void __exit iser_exit(void) +{ + iser_dbg("Removing iSER datamover...\n"); + iscsi_unregister_transport(&iscsi_iser_transport); + kmem_cache_destroy(ig.desc_cache); +} + +module_init(iser_init); +module_exit(iser_exit); diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h new file mode 100644 index 0000000..3350ba6 --- /dev/null +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -0,0 +1,354 @@ +/* + * iSER transport for the Open iSCSI Initiator & iSER transport internals + * + * Copyright (C) 2004 Dmitry Yusupov + * Copyright (C) 2004 Alex Aizman + * Copyright (C) 2005 Mike Christie + * based on code maintained by open-iscsi@googlegroups.com + * + * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: iscsi_iser.h 7051 2006-05-10 12:29:11Z ogerlitz $ + */ +#ifndef __ISCSI_ISER_H__ +#define __ISCSI_ISER_H__ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#define DRV_NAME "iser" +#define PFX DRV_NAME ": " +#define DRV_VER "0.1" +#define DRV_DATE "May 7th, 2006" + +#define iser_dbg(fmt, arg...) \ + do { \ + if (iser_debug_level > 0) \ + printk(KERN_DEBUG PFX "%s:" fmt,\ + __func__ , ## arg); \ + } while (0) + +#define iser_err(fmt, arg...) \ + do { \ + printk(KERN_ERR PFX "%s:" fmt, \ + __func__ , ## arg); \ + } while (0) + + /* support upto 512KB in one RDMA */ +#define ISCSI_ISER_SG_TABLESIZE (0x80000 >> PAGE_SHIFT) +#define ISCSI_ISER_MAX_LUN 256 +#define ISCSI_ISER_MAX_CMD_LEN 16 + +/* QP settings */ +/* Maximal bounds on received asynchronous PDUs */ +#define ISER_MAX_RX_MISC_PDUS 4 /* NOOP_IN(2) , ASYNC_EVENT(2) */ + +#define ISER_MAX_TX_MISC_PDUS 6 /* NOOP_OUT(2), TEXT(1), * + * SCSI_TMFUNC(2), LOGOUT(1) */ + +#define ISER_QP_MAX_RECV_DTOS (ISCSI_XMIT_CMDS_MAX + \ + ISER_MAX_RX_MISC_PDUS + \ + ISER_MAX_TX_MISC_PDUS) + +/* the max TX (send) WR supported by the iSER QP is defined by * + * max_send_wr = T * (1 + D) + C ; D is how many inflight dataouts we expect * + * to have at max for SCSI command. The tx posting & completion handling code * + * supports -EAGAIN scheme where tx is suspended till the QP has room for more * + * send WR. D=8 comes from 64K/8K */ + +#define ISER_INFLIGHT_DATAOUTS 8 + +#define ISER_QP_MAX_REQ_DTOS (ISCSI_XMIT_CMDS_MAX * \ + (1 + ISER_INFLIGHT_DATAOUTS) + \ + ISER_MAX_TX_MISC_PDUS + \ + ISER_MAX_RX_MISC_PDUS) + +#define ISER_VER 0x10 +#define ISER_WSV 0x08 +#define ISER_RSV 0x04 + +struct iser_hdr { + u8 flags; + u8 rsvd[3]; + __be32 write_stag; /* write rkey */ + __be64 write_va; + __be32 read_stag; /* read rkey */ + __be64 read_va; +} __attribute__((packed)); + + +/* Length of an object name string */ +#define ISER_OBJECT_NAME_SIZE 64 + +enum iser_ib_conn_state { + ISER_CONN_INIT, /* descriptor allocd, no conn */ + ISER_CONN_PENDING, /* in the process of being established */ + ISER_CONN_UP, /* up and running */ + ISER_CONN_TERMINATING, /* in the process of being terminated */ + ISER_CONN_DOWN, /* shut down */ + ISER_CONN_STATES_NUM +}; + +enum iser_task_status { + ISER_TASK_STATUS_INIT = 0, + ISER_TASK_STATUS_STARTED, + ISER_TASK_STATUS_COMPLETED +}; + +enum iser_data_dir { + ISER_DIR_IN = 0, /* to initiator */ + ISER_DIR_OUT, /* from initiator */ + ISER_DIRS_NUM +}; + +struct iser_data_buf { + void *buf; /* pointer to the sg list */ + unsigned int size; /* num entries of this sg */ + unsigned long data_len; /* total data len */ + unsigned int dma_nents; /* returned by dma_map_sg */ + char *copy_buf; /* allocated copy buf for SGs unaligned * + * for rdma which are copied */ + struct scatterlist sg_single; /* SG-ified clone of a non SG SC or * + * unaligned SG */ + }; + +/* fwd declarations */ +struct iser_device; +struct iscsi_iser_conn; +struct iscsi_iser_cmd_task; + +struct iser_mem_reg { + u32 lkey; + u32 rkey; + u64 va; + u64 len; + void *mem_h; +}; + +struct iser_regd_buf { + struct iser_mem_reg reg; /* memory registration info */ + void *virt_addr; + struct iser_device *device; /* device->device for dma_unmap */ + dma_addr_t dma_addr; /* if non zero, addr for dma_unmap */ + enum dma_data_direction direction; /* direction for dma_unmap */ + unsigned int data_size; + atomic_t ref_count; /* refcount, freed when dec to 0 */ +}; + +#define MAX_REGD_BUF_VECTOR_LEN 2 + +struct iser_dto { + struct iscsi_iser_cmd_task *ctask; + struct iscsi_iser_conn *conn; + int notify_enable; + + /* vector of registered buffers */ + unsigned int regd_vector_len; + struct iser_regd_buf *regd[MAX_REGD_BUF_VECTOR_LEN]; + + /* offset into the registered buffer may be specified */ + unsigned int offset[MAX_REGD_BUF_VECTOR_LEN]; + + /* a smaller size may be specified, if 0, then full size is used */ + unsigned int used_sz[MAX_REGD_BUF_VECTOR_LEN]; +}; + +enum iser_desc_type { + ISCSI_RX, + ISCSI_TX_CONTROL , + ISCSI_TX_SCSI_COMMAND, + ISCSI_TX_DATAOUT +}; + +struct iser_desc { + struct iser_hdr iser_header; + struct iscsi_hdr iscsi_header; + struct iser_regd_buf hdr_regd_buf; + void *data; /* used by RX & TX_CONTROL */ + struct iser_regd_buf data_regd_buf; /* used by RX & TX_CONTROL */ + enum iser_desc_type type; + struct iser_dto dto; +}; + +struct iser_device { + struct ib_device *ib_device; + struct ib_pd *pd; + struct ib_cq *cq; + struct ib_mr *mr; + struct tasklet_struct cq_tasklet; + struct list_head ig_list; /* entry in ig devices list */ + int refcount; +}; + +struct iser_conn { + struct iscsi_iser_conn *iser_conn; /* iser conn for upcalls */ + enum iser_ib_conn_state state; /* rdma connection state */ + spinlock_t lock; /* used for state changes */ + struct iser_device *device; /* device context */ + struct rdma_cm_id *cma_id; /* CMA ID */ + struct ib_qp *qp; /* QP */ + struct ib_fmr_pool *fmr_pool; /* pool of IB FMRs */ + int disc_evt_flag; /* disconn event delivered */ + wait_queue_head_t wait; /* waitq for conn/disconn */ + atomic_t post_recv_buf_count; /* posted rx count */ + atomic_t post_send_buf_count; /* posted tx count */ + struct work_struct comperror_work; /* conn term sleepable ctx*/ + char name[ISER_OBJECT_NAME_SIZE]; + struct iser_page_vec *page_vec; /* represents SG to fmr maps* + * maps serialized as tx is*/ + struct list_head conn_list; /* entry in ig conn list */ +}; + +struct iscsi_iser_conn { + struct iscsi_conn *iscsi_conn;/* ptr to iscsi conn */ + struct iser_conn *ib_conn; /* iSER IB conn */ + + rwlock_t lock; +}; + +struct iscsi_iser_cmd_task { + struct iser_desc desc; + struct iscsi_iser_conn *iser_conn; + int rdma_data_count;/* RDMA bytes */ + enum iser_task_status status; + int command_sent; /* set if command sent */ + int dir[ISER_DIRS_NUM]; /* set if dir use*/ + struct iser_regd_buf rdma_regd[ISER_DIRS_NUM];/* regd rdma buf */ + struct iser_data_buf data[ISER_DIRS_NUM]; /* orig. data des*/ + struct iser_data_buf data_copy[ISER_DIRS_NUM];/* contig. copy */ +}; + +struct iser_page_vec { + u64 *pages; + int length; + int offset; + int data_size; +}; + +struct iser_global { + struct mutex device_list_mutex;/* */ + struct list_head device_list; /* all iSER devices */ + struct mutex connlist_mutex; + struct list_head connlist; /* all iSER IB connections */ + + kmem_cache_t *desc_cache; +}; + +extern struct iser_global ig; +extern int iser_debug_level; + +/* allocate connection resources needed for rdma functionality */ +int iser_conn_set_full_featured_mode(struct iscsi_conn *conn); + +int iser_send_control(struct iscsi_conn *conn, + struct iscsi_mgmt_task *mtask); + +int iser_send_command(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask); + +int iser_send_data_out(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask, + struct iscsi_data *hdr); + +void iscsi_iser_recv(struct iscsi_conn *conn, + struct iscsi_hdr *hdr, + char *rx_data, + int rx_data_len); + +int iser_conn_init(struct iser_conn **ib_conn); + +void iser_conn_terminate(struct iser_conn *ib_conn); + +void iser_conn_release(struct iser_conn *ib_conn); + +void iser_rcv_completion(struct iser_desc *desc, + unsigned long dto_xfer_len); + +void iser_snd_completion(struct iser_desc *desc); + +void iser_ctask_rdma_init(struct iscsi_iser_cmd_task *ctask); + +void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *ctask); + +void iser_dto_buffs_release(struct iser_dto *dto); + +int iser_regd_buff_release(struct iser_regd_buf *regd_buf); + +void iser_reg_single(struct iser_device *device, + struct iser_regd_buf *regd_buf, + enum dma_data_direction direction); + +int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *ctask, + enum iser_data_dir cmd_dir); + +void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *ctask, + enum iser_data_dir cmd_dir); + +int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *ctask, + enum iser_data_dir cmd_dir); + +int iser_connect(struct iser_conn *ib_conn, + struct sockaddr_in *src_addr, + struct sockaddr_in *dst_addr, + int non_blocking); + +int iser_reg_page_vec(struct iser_conn *ib_conn, + struct iser_page_vec *page_vec, + struct iser_mem_reg *mem_reg); + +void iser_unreg_mem(struct iser_mem_reg *mem_reg); + +int iser_post_recv(struct iser_desc *rx_desc); +int iser_post_send(struct iser_desc *tx_desc); + +int iser_conn_state_comp(struct iser_conn *ib_conn, + enum iser_ib_conn_state comp); +#endif diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c new file mode 100644 index 0000000..ccf56f6 --- /dev/null +++ b/drivers/infiniband/ulp/iser/iser_initiator.c @@ -0,0 +1,738 @@ +/* + * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: iser_initiator.c 6964 2006-05-07 11:11:43Z ogerlitz $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iscsi_iser.h" + +/* Constant PDU lengths calculations */ +#define ISER_TOTAL_HEADERS_LEN (sizeof (struct iser_hdr) + \ + sizeof (struct iscsi_hdr)) + +/* iser_dto_add_regd_buff - increments the reference count for * + * the registered buffer & adds it to the DTO object */ +static void iser_dto_add_regd_buff(struct iser_dto *dto, + struct iser_regd_buf *regd_buf, + unsigned long use_offset, + unsigned long use_size) +{ + int add_idx; + + atomic_inc(®d_buf->ref_count); + + add_idx = dto->regd_vector_len; + dto->regd[add_idx] = regd_buf; + dto->used_sz[add_idx] = use_size; + dto->offset[add_idx] = use_offset; + + dto->regd_vector_len++; +} + +static int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask, + struct iser_data_buf *data, + enum iser_data_dir iser_dir, + enum dma_data_direction dma_dir) +{ + struct device *dma_device; + + iser_ctask->dir[iser_dir] = 1; + dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; + + data->dma_nents = dma_map_sg(dma_device, data->buf, data->size, dma_dir); + if (data->dma_nents == 0) { + iser_err("dma_map_sg failed!!!\n"); + return -EINVAL; + } + return 0; +} + +static void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask) +{ + struct device *dma_device; + struct iser_data_buf *data; + + dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; + + if (iser_ctask->dir[ISER_DIR_IN]) { + data = &iser_ctask->data[ISER_DIR_IN]; + dma_unmap_sg(dma_device, data->buf, data->size, DMA_FROM_DEVICE); + } + + if (iser_ctask->dir[ISER_DIR_OUT]) { + data = &iser_ctask->data[ISER_DIR_OUT]; + dma_unmap_sg(dma_device, data->buf, data->size, DMA_TO_DEVICE); + } +} + +/* Register user buffer memory and initialize passive rdma + * dto descriptor. Total data size is stored in + * iser_ctask->data[ISER_DIR_IN].data_len + */ +static int iser_prepare_read_cmd(struct iscsi_cmd_task *ctask, + unsigned int edtl) + +{ + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + struct iser_regd_buf *regd_buf; + int err; + struct iser_hdr *hdr = &iser_ctask->desc.iser_header; + struct iser_data_buf *buf_in = &iser_ctask->data[ISER_DIR_IN]; + + err = iser_dma_map_task_data(iser_ctask, + buf_in, + ISER_DIR_IN, + DMA_FROM_DEVICE); + if (err) + return err; + + if (edtl > iser_ctask->data[ISER_DIR_IN].data_len) { + iser_err("Total data length: %ld, less than EDTL: " + "%d, in READ cmd BHS itt: %d, conn: 0x%p\n", + iser_ctask->data[ISER_DIR_IN].data_len, edtl, + ctask->itt, iser_ctask->iser_conn); + return -EINVAL; + } + + err = iser_reg_rdma_mem(iser_ctask,ISER_DIR_IN); + if (err) { + iser_err("Failed to set up Data-IN RDMA\n"); + return err; + } + regd_buf = &iser_ctask->rdma_regd[ISER_DIR_IN]; + + hdr->flags |= ISER_RSV; + hdr->read_stag = cpu_to_be32(regd_buf->reg.rkey); + hdr->read_va = cpu_to_be64(regd_buf->reg.va); + + iser_dbg("Cmd itt:%d READ tags RKEY:%#.4X VA:%#llX\n", + ctask->itt, regd_buf->reg.rkey, + (unsigned long long)regd_buf->reg.va); + + return 0; +} + +/* Register user buffer memory and initialize passive rdma + * dto descriptor. Total data size is stored in + * ctask->data[ISER_DIR_OUT].data_len + */ +static int +iser_prepare_write_cmd(struct iscsi_cmd_task *ctask, + unsigned int imm_sz, + unsigned int unsol_sz, + unsigned int edtl) +{ + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + struct iser_regd_buf *regd_buf; + int err; + struct iser_dto *send_dto = &iser_ctask->desc.dto; + struct iser_hdr *hdr = &iser_ctask->desc.iser_header; + struct iser_data_buf *buf_out = &iser_ctask->data[ISER_DIR_OUT]; + + err = iser_dma_map_task_data(iser_ctask, + buf_out, + ISER_DIR_OUT, + DMA_TO_DEVICE); + if (err) + return err; + + if (edtl > iser_ctask->data[ISER_DIR_OUT].data_len) { + iser_err("Total data length: %ld, less than EDTL: %d, " + "in WRITE cmd BHS itt: %d, conn: 0x%p\n", + iser_ctask->data[ISER_DIR_OUT].data_len, + edtl, ctask->itt, ctask->conn); + return -EINVAL; + } + + err = iser_reg_rdma_mem(iser_ctask,ISER_DIR_OUT); + if (err != 0) { + iser_err("Failed to register write cmd RDMA mem\n"); + return err; + } + + regd_buf = &iser_ctask->rdma_regd[ISER_DIR_OUT]; + + if (unsol_sz < edtl) { + hdr->flags |= ISER_WSV; + hdr->write_stag = cpu_to_be32(regd_buf->reg.rkey); + hdr->write_va = cpu_to_be64(regd_buf->reg.va + unsol_sz); + + iser_dbg("Cmd itt:%d, WRITE tags, RKEY:%#.4X " + "VA:%#llX + unsol:%d\n", + ctask->itt, regd_buf->reg.rkey, + (unsigned long long)regd_buf->reg.va, unsol_sz); + } + + if (imm_sz > 0) { + iser_dbg("Cmd itt:%d, WRITE, adding imm.data sz: %d\n", + ctask->itt, imm_sz); + iser_dto_add_regd_buff(send_dto, + regd_buf, + 0, + imm_sz); + } + + return 0; +} + +/** + * iser_post_receive_control - allocates, initializes and posts receive DTO. + */ +static int iser_post_receive_control(struct iscsi_conn *conn) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + struct iser_desc *rx_desc; + struct iser_regd_buf *regd_hdr; + struct iser_regd_buf *regd_data; + struct iser_dto *recv_dto = NULL; + struct iser_device *device = iser_conn->ib_conn->device; + int rx_data_size, err = 0; + + rx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO); + if (rx_desc == NULL) { + iser_err("Failed to alloc desc for post recv\n"); + return -ENOMEM; + } + rx_desc->type = ISCSI_RX; + + /* for the login sequence we must support rx of upto 8K; login is done + * after conn create/bind (connect) and conn stop/bind (reconnect), + * what's common for both schemes is that the connection is not started + */ + if (conn->c_stage != ISCSI_CONN_STARTED) + rx_data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; + else /* FIXME till user space sets conn->max_recv_dlength correctly */ + rx_data_size = 128; + + rx_desc->data = kmalloc(rx_data_size, GFP_NOIO); + if (rx_desc->data == NULL) { + iser_err("Failed to alloc data buf for post recv\n"); + err = -ENOMEM; + goto post_rx_kmalloc_failure; + } + + recv_dto = &rx_desc->dto; + recv_dto->conn = iser_conn; + recv_dto->regd_vector_len = 0; + + regd_hdr = &rx_desc->hdr_regd_buf; + memset(regd_hdr, 0, sizeof(struct iser_regd_buf)); + regd_hdr->device = device; + regd_hdr->virt_addr = rx_desc; /* == &rx_desc->iser_header */ + regd_hdr->data_size = ISER_TOTAL_HEADERS_LEN; + + iser_reg_single(device, regd_hdr, DMA_FROM_DEVICE); + + iser_dto_add_regd_buff(recv_dto, regd_hdr, 0, 0); + + regd_data = &rx_desc->data_regd_buf; + memset(regd_data, 0, sizeof(struct iser_regd_buf)); + regd_data->device = device; + regd_data->virt_addr = rx_desc->data; + regd_data->data_size = rx_data_size; + + iser_reg_single(device, regd_data, DMA_FROM_DEVICE); + + iser_dto_add_regd_buff(recv_dto, regd_data, 0, 0); + + err = iser_post_recv(rx_desc); + if (!err) + return 0; + + /* iser_post_recv failed */ + iser_dto_buffs_release(recv_dto); + kfree(rx_desc->data); +post_rx_kmalloc_failure: + kmem_cache_free(ig.desc_cache, rx_desc); + return err; +} + +/* creates a new tx descriptor and adds header regd buffer */ +static void iser_create_send_desc(struct iscsi_iser_conn *iser_conn, + struct iser_desc *tx_desc) +{ + struct iser_regd_buf *regd_hdr = &tx_desc->hdr_regd_buf; + struct iser_dto *send_dto = &tx_desc->dto; + + memset(regd_hdr, 0, sizeof(struct iser_regd_buf)); + regd_hdr->device = iser_conn->ib_conn->device; + regd_hdr->virt_addr = tx_desc; /* == &tx_desc->iser_header */ + regd_hdr->data_size = ISER_TOTAL_HEADERS_LEN; + + send_dto->conn = iser_conn; + send_dto->notify_enable = 1; + send_dto->regd_vector_len = 0; + + memset(&tx_desc->iser_header, 0, sizeof(struct iser_hdr)); + tx_desc->iser_header.flags = ISER_VER; + + iser_dto_add_regd_buff(send_dto, regd_hdr, 0, 0); +} + +/** + * iser_conn_set_full_featured_mode - (iSER API) + */ +int iser_conn_set_full_featured_mode(struct iscsi_conn *conn) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + + int i; + /* no need to keep it in a var, we are after login so if this should + * be negotiated, by now the result should be available here */ + int initial_post_recv_bufs_num = ISER_MAX_RX_MISC_PDUS; + + iser_dbg("Initially post: %d\n", initial_post_recv_bufs_num); + + /* Check that there is no posted recv or send buffers left - */ + /* they must be consumed during the login phase */ + BUG_ON(atomic_read(&iser_conn->ib_conn->post_recv_buf_count) != 0); + BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0); + + /* Initial post receive buffers */ + for (i = 0; i < initial_post_recv_bufs_num; i++) { + if (iser_post_receive_control(conn) != 0) { + iser_err("Failed to post recv bufs at:%d conn:0x%p\n", + i, conn); + return -ENOMEM; + } + } + iser_dbg("Posted %d post recv bufs, conn:0x%p\n", i, conn); + return 0; +} + +static int +iser_check_xmit(struct iscsi_conn *conn, void *task) +{ + int rc = 0; + struct iscsi_iser_conn *iser_conn = conn->dd_data; + + write_lock_bh(conn->recv_lock); + if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) == + ISER_QP_MAX_REQ_DTOS) { + iser_dbg("%ld can't xmit task %p, suspending tx\n",jiffies,task); + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + rc = -EAGAIN; + } + write_unlock_bh(conn->recv_lock); + return rc; +} + + +/** + * iser_send_command - send command PDU + */ +int iser_send_command(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + struct iser_dto *send_dto = NULL; + unsigned long edtl; + int err = 0; + struct iser_data_buf *data_buf; + + struct iscsi_cmd *hdr = ctask->hdr; + struct scsi_cmnd *sc = ctask->sc; + + if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { + iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn); + return -EPERM; + } + if (iser_check_xmit(conn, ctask)) + return -EAGAIN; + + edtl = ntohl(hdr->data_length); + + /* build the tx desc regd header and add it to the tx desc dto */ + iser_ctask->desc.type = ISCSI_TX_SCSI_COMMAND; + send_dto = &iser_ctask->desc.dto; + send_dto->ctask = iser_ctask; + iser_create_send_desc(iser_conn, &iser_ctask->desc); + + if (hdr->flags & ISCSI_FLAG_CMD_READ) + data_buf = &iser_ctask->data[ISER_DIR_IN]; + else + data_buf = &iser_ctask->data[ISER_DIR_OUT]; + + if (sc->use_sg) { /* using a scatter list */ + data_buf->buf = sc->request_buffer; + data_buf->size = sc->use_sg; + } else if (sc->request_bufflen) { + /* using a single buffer - convert it into one entry SG */ + sg_init_one(&data_buf->sg_single, + sc->request_buffer, sc->request_bufflen); + data_buf->buf = &data_buf->sg_single; + data_buf->size = 1; + } + + data_buf->data_len = sc->request_bufflen; + + if (hdr->flags & ISCSI_FLAG_CMD_READ) { + err = iser_prepare_read_cmd(ctask, edtl); + if (err) + goto send_command_error; + } + if (hdr->flags & ISCSI_FLAG_CMD_WRITE) { + err = iser_prepare_write_cmd(ctask, + ctask->imm_count, + ctask->imm_count + + ctask->unsol_count, + edtl); + if (err) + goto send_command_error; + } + + iser_reg_single(iser_conn->ib_conn->device, + send_dto->regd[0], DMA_TO_DEVICE); + + if (iser_post_receive_control(conn) != 0) { + iser_err("post_recv failed!\n"); + err = -ENOMEM; + goto send_command_error; + } + + iser_ctask->status = ISER_TASK_STATUS_STARTED; + + err = iser_post_send(&iser_ctask->desc); + if (!err) + return 0; + +send_command_error: + iser_dto_buffs_release(send_dto); + iser_err("conn %p failed ctask->itt %d err %d\n",conn, ctask->itt, err); + return err; +} + +/** + * iser_send_data_out - send data out PDU + */ +int iser_send_data_out(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask, + struct iscsi_data *hdr) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + struct iser_desc *tx_desc = NULL; + struct iser_dto *send_dto = NULL; + unsigned long buf_offset; + unsigned long data_seg_len; + unsigned int itt; + int err = 0; + + if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { + iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn); + return -EPERM; + } + + if (iser_check_xmit(conn, ctask)) + return -EAGAIN; + + itt = ntohl(hdr->itt); + data_seg_len = ntoh24(hdr->dlength); + buf_offset = ntohl(hdr->offset); + + iser_dbg("%s itt %d dseg_len %d offset %d\n", + __func__,(int)itt,(int)data_seg_len,(int)buf_offset); + + tx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO); + if (tx_desc == NULL) { + iser_err("Failed to alloc desc for post dataout\n"); + return -ENOMEM; + } + + tx_desc->type = ISCSI_TX_DATAOUT; + memcpy(&tx_desc->iscsi_header, hdr, sizeof(struct iscsi_hdr)); + + /* build the tx desc regd header and add it to the tx desc dto */ + send_dto = &tx_desc->dto; + send_dto->ctask = iser_ctask; + iser_create_send_desc(iser_conn, tx_desc); + + iser_reg_single(iser_conn->ib_conn->device, + send_dto->regd[0], DMA_TO_DEVICE); + + /* all data was registered for RDMA, we can use the lkey */ + iser_dto_add_regd_buff(send_dto, + &iser_ctask->rdma_regd[ISER_DIR_OUT], + buf_offset, + data_seg_len); + + if (buf_offset + data_seg_len > iser_ctask->data[ISER_DIR_OUT].data_len) { + iser_err("Offset:%ld & DSL:%ld in Data-Out " + "inconsistent with total len:%ld, itt:%d\n", + buf_offset, data_seg_len, + iser_ctask->data[ISER_DIR_OUT].data_len, itt); + err = -EINVAL; + goto send_data_out_error; + } + iser_dbg("data-out itt: %d, offset: %ld, sz: %ld\n", + itt, buf_offset, data_seg_len); + + + err = iser_post_send(tx_desc); + if (!err) + return 0; + +send_data_out_error: + iser_dto_buffs_release(send_dto); + kmem_cache_free(ig.desc_cache, tx_desc); + iser_err("conn %p failed err %d\n",conn, err); + return err; +} + +int iser_send_control(struct iscsi_conn *conn, + struct iscsi_mgmt_task *mtask) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + struct iser_desc *mdesc = mtask->dd_data; + struct iser_dto *send_dto = NULL; + unsigned int itt; + unsigned long data_seg_len; + int err = 0; + unsigned char opcode; + struct iser_regd_buf *regd_buf; + struct iser_device *device; + + if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { + iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn); + return -EPERM; + } + + if (iser_check_xmit(conn,mtask)) + return -EAGAIN; + + /* build the tx desc regd header and add it to the tx desc dto */ + mdesc->type = ISCSI_TX_CONTROL; + send_dto = &mdesc->dto; + send_dto->ctask = NULL; + iser_create_send_desc(iser_conn, mdesc); + + device = iser_conn->ib_conn->device; + + iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE); + + itt = ntohl(mtask->hdr->itt); + opcode = mtask->hdr->opcode & ISCSI_OPCODE_MASK; + data_seg_len = ntoh24(mtask->hdr->dlength); + + if (data_seg_len > 0) { + regd_buf = &mdesc->data_regd_buf; + memset(regd_buf, 0, sizeof(struct iser_regd_buf)); + regd_buf->device = device; + regd_buf->virt_addr = mtask->data; + regd_buf->data_size = mtask->data_count; + iser_reg_single(device, regd_buf, + DMA_TO_DEVICE); + iser_dto_add_regd_buff(send_dto, regd_buf, + 0, + data_seg_len); + } + + if (iser_post_receive_control(conn) != 0) { + iser_err("post_rcv_buff failed!\n"); + err = -ENOMEM; + goto send_control_error; + } + + err = iser_post_send(mdesc); + if (!err) + return 0; + +send_control_error: + iser_dto_buffs_release(send_dto); + iser_err("conn %p failed err %d\n",conn, err); + return err; +} + +/** + * iser_rcv_dto_completion - recv DTO completion + */ +void iser_rcv_completion(struct iser_desc *rx_desc, + unsigned long dto_xfer_len) +{ + struct iser_dto *dto = &rx_desc->dto; + struct iscsi_iser_conn *conn = dto->conn; + struct iscsi_session *session = conn->iscsi_conn->session; + struct iscsi_cmd_task *ctask; + struct iscsi_iser_cmd_task *iser_ctask; + struct iscsi_hdr *hdr; + char *rx_data = NULL; + int rx_data_len = 0; + unsigned int itt; + unsigned char opcode; + + hdr = &rx_desc->iscsi_header; + + iser_dbg("op 0x%x itt 0x%x\n", hdr->opcode,hdr->itt); + + if (dto_xfer_len > ISER_TOTAL_HEADERS_LEN) { /* we have data */ + rx_data_len = dto_xfer_len - ISER_TOTAL_HEADERS_LEN; + rx_data = dto->regd[1]->virt_addr; + rx_data += dto->offset[1]; + } + + opcode = hdr->opcode & ISCSI_OPCODE_MASK; + + if (opcode == ISCSI_OP_SCSI_CMD_RSP) { + itt = hdr->itt & ISCSI_ITT_MASK; /* mask out cid and age bits */ + if (!(itt < session->cmds_max)) + iser_err("itt can't be matched to task!!!" + "conn %p opcode %d cmds_max %d itt %d\n", + conn->iscsi_conn,opcode,session->cmds_max,itt); + /* use the mapping given with the cmds array indexed by itt */ + ctask = (struct iscsi_cmd_task *)session->cmds[itt]; + iser_ctask = ctask->dd_data; + iser_dbg("itt %d ctask %p\n",itt,ctask); + iser_ctask->status = ISER_TASK_STATUS_COMPLETED; + iser_ctask_rdma_finalize(iser_ctask); + } + + iser_dto_buffs_release(dto); + + iscsi_iser_recv(conn->iscsi_conn, hdr, rx_data, rx_data_len); + + kfree(rx_desc->data); + kmem_cache_free(ig.desc_cache, rx_desc); + + /* decrementing conn->post_recv_buf_count only --after-- freeing the * + * task eliminates the need to worry on tasks which are completed in * + * parallel to the execution of iser_conn_term. So the code that waits * + * for the posted rx bufs refcount to become zero handles everything */ + atomic_dec(&conn->ib_conn->post_recv_buf_count); +} + +void iser_snd_completion(struct iser_desc *tx_desc) +{ + struct iser_dto *dto = &tx_desc->dto; + struct iscsi_iser_conn *iser_conn = dto->conn; + struct iscsi_conn *conn = iser_conn->iscsi_conn; + struct iscsi_mgmt_task *mtask; + + iser_dbg("Initiator, Data sent dto=0x%p\n", dto); + + iser_dto_buffs_release(dto); + + if (tx_desc->type == ISCSI_TX_DATAOUT) + kmem_cache_free(ig.desc_cache, tx_desc); + + atomic_dec(&iser_conn->ib_conn->post_send_buf_count); + + write_lock(conn->recv_lock); + if (conn->suspend_tx) { + iser_dbg("%ld resuming tx\n",jiffies); + clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + scsi_queue_work(conn->session->host, &conn->xmitwork); + } + write_unlock(conn->recv_lock); + + if (tx_desc->type == ISCSI_TX_CONTROL) { + /* this arithmetic is legal by libiscsi dd_data allocation */ + mtask = (void *) ((long)(void *)tx_desc - + sizeof(struct iscsi_mgmt_task)); + if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) { + struct iscsi_session *session = conn->session; + + spin_lock(&conn->session->lock); + list_del(&mtask->running); + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + sizeof(void*)); + spin_unlock(&session->lock); + } + } +} + +void iser_ctask_rdma_init(struct iscsi_iser_cmd_task *iser_ctask) + +{ + iser_ctask->status = ISER_TASK_STATUS_INIT; + + iser_ctask->dir[ISER_DIR_IN] = 0; + iser_ctask->dir[ISER_DIR_OUT] = 0; + + iser_ctask->data[ISER_DIR_IN].data_len = 0; + iser_ctask->data[ISER_DIR_OUT].data_len = 0; + + memset(&iser_ctask->rdma_regd[ISER_DIR_IN], 0, + sizeof(struct iser_regd_buf)); + memset(&iser_ctask->rdma_regd[ISER_DIR_OUT], 0, + sizeof(struct iser_regd_buf)); +} + +void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask) +{ + int deferred; + + /* if we were reading, copy back to unaligned sglist, + * anyway dma_unmap and free the copy + */ + if (iser_ctask->data_copy[ISER_DIR_IN].copy_buf != NULL) + iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_IN); + if (iser_ctask->data_copy[ISER_DIR_OUT].copy_buf != NULL) + iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_OUT); + + if (iser_ctask->dir[ISER_DIR_IN]) { + deferred = iser_regd_buff_release + (&iser_ctask->rdma_regd[ISER_DIR_IN]); + if (deferred) { + iser_err("References remain for BUF-IN rdma reg\n"); + BUG(); + } + } + + if (iser_ctask->dir[ISER_DIR_OUT]) { + deferred = iser_regd_buff_release + (&iser_ctask->rdma_regd[ISER_DIR_OUT]); + if (deferred) { + iser_err("References remain for BUF-OUT rdma reg\n"); + BUG(); + } + } + + iser_dma_unmap_task_data(iser_ctask); +} + +void iser_dto_buffs_release(struct iser_dto *dto) +{ + int i; + + for (i = 0; i < dto->regd_vector_len; i++) + iser_regd_buff_release(dto->regd[i]); +} + diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c new file mode 100644 index 0000000..31950a5 --- /dev/null +++ b/drivers/infiniband/ulp/iser/iser_memory.c @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: iser_memory.c 6964 2006-05-07 11:11:43Z ogerlitz $ + */ +#include +#include +#include +#include +#include +#include +#include + +#include "iscsi_iser.h" + +#define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */ +/** + * Decrements the reference count for the + * registered buffer & releases it + * + * returns 0 if released, 1 if deferred + */ +int iser_regd_buff_release(struct iser_regd_buf *regd_buf) +{ + struct device *dma_device; + + if ((atomic_read(®d_buf->ref_count) == 0) || + atomic_dec_and_test(®d_buf->ref_count)) { + /* if we used the dma mr, unreg is just NOP */ + if (regd_buf->reg.rkey != 0) + iser_unreg_mem(®d_buf->reg); + + if (regd_buf->dma_addr) { + dma_device = regd_buf->device->ib_device->dma_device; + dma_unmap_single(dma_device, + regd_buf->dma_addr, + regd_buf->data_size, + regd_buf->direction); + } + /* else this regd buf is associated with task which we */ + /* dma_unmap_single/sg later */ + return 0; + } else { + iser_dbg("Release deferred, regd.buff: 0x%p\n", regd_buf); + return 1; + } +} + +/** + * iser_reg_single - fills registered buffer descriptor with + * registration information + */ +void iser_reg_single(struct iser_device *device, + struct iser_regd_buf *regd_buf, + enum dma_data_direction direction) +{ + dma_addr_t dma_addr; + + dma_addr = dma_map_single(device->ib_device->dma_device, + regd_buf->virt_addr, + regd_buf->data_size, direction); + BUG_ON(dma_mapping_error(dma_addr)); + + regd_buf->reg.lkey = device->mr->lkey; + regd_buf->reg.rkey = 0; /* indicate there's no need to unreg */ + regd_buf->reg.len = regd_buf->data_size; + regd_buf->reg.va = dma_addr; + + regd_buf->dma_addr = dma_addr; + regd_buf->direction = direction; +} + +/** + * iser_start_rdma_unaligned_sg + */ +int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, + enum iser_data_dir cmd_dir) +{ + int dma_nents; + struct device *dma_device; + char *mem = NULL; + struct iser_data_buf *data = &iser_ctask->data[cmd_dir]; + unsigned long cmd_data_len = data->data_len; + + if (cmd_data_len > ISER_KMALLOC_THRESHOLD) + mem = (void *)__get_free_pages(GFP_NOIO, + long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); + else + mem = kmalloc(cmd_data_len, GFP_NOIO); + + if (mem == NULL) { + iser_err("Failed to allocate mem size %d %d for copying sglist\n", + data->size,(int)cmd_data_len); + return -ENOMEM; + } + + if (cmd_dir == ISER_DIR_OUT) { + /* copy the unaligned sg the buffer which is used for RDMA */ + struct scatterlist *sg = (struct scatterlist *)data->buf; + int i; + char *p, *from; + + for (p = mem, i = 0; i < data->size; i++) { + from = kmap_atomic(sg[i].page, KM_USER0); + memcpy(p, + from + sg[i].offset, + sg[i].length); + kunmap_atomic(from, KM_USER0); + p += sg[i].length; + } + } + + sg_init_one(&iser_ctask->data_copy[cmd_dir].sg_single, mem, cmd_data_len); + iser_ctask->data_copy[cmd_dir].buf = + &iser_ctask->data_copy[cmd_dir].sg_single; + iser_ctask->data_copy[cmd_dir].size = 1; + + iser_ctask->data_copy[cmd_dir].copy_buf = mem; + + dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; + + if (cmd_dir == ISER_DIR_OUT) + dma_nents = dma_map_sg(dma_device, + &iser_ctask->data_copy[cmd_dir].sg_single, + 1, DMA_TO_DEVICE); + else + dma_nents = dma_map_sg(dma_device, + &iser_ctask->data_copy[cmd_dir].sg_single, + 1, DMA_FROM_DEVICE); + + BUG_ON(dma_nents == 0); + + iser_ctask->data_copy[cmd_dir].dma_nents = dma_nents; + return 0; +} + +/** + * iser_finalize_rdma_unaligned_sg + */ +void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, + enum iser_data_dir cmd_dir) +{ + struct device *dma_device; + struct iser_data_buf *mem_copy; + unsigned long cmd_data_len; + + dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; + mem_copy = &iser_ctask->data_copy[cmd_dir]; + + if (cmd_dir == ISER_DIR_OUT) + dma_unmap_sg(dma_device, &mem_copy->sg_single, 1, + DMA_TO_DEVICE); + else + dma_unmap_sg(dma_device, &mem_copy->sg_single, 1, + DMA_FROM_DEVICE); + + if (cmd_dir == ISER_DIR_IN) { + char *mem; + struct scatterlist *sg; + unsigned char *p, *to; + unsigned int sg_size; + int i; + + /* copy back read RDMA to unaligned sg */ + mem = mem_copy->copy_buf; + + sg = (struct scatterlist *)iser_ctask->data[ISER_DIR_IN].buf; + sg_size = iser_ctask->data[ISER_DIR_IN].size; + + for (p = mem, i = 0; i < sg_size; i++){ + to = kmap_atomic(sg[i].page, KM_SOFTIRQ0); + memcpy(to + sg[i].offset, + p, + sg[i].length); + kunmap_atomic(to, KM_SOFTIRQ0); + p += sg[i].length; + } + } + + cmd_data_len = iser_ctask->data[cmd_dir].data_len; + + if (cmd_data_len > ISER_KMALLOC_THRESHOLD) + free_pages((unsigned long)mem_copy->copy_buf, + long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); + else + kfree(mem_copy->copy_buf); + + mem_copy->copy_buf = NULL; +} + +/** + * iser_sg_to_page_vec - Translates scatterlist entries to physical addresses + * and returns the length of resulting physical address array (may be less than + * the original due to possible compaction). + * + * we build a "page vec" under the assumption that the SG meets the RDMA + * alignment requirements. Other then the first and last SG elements, all + * the "internal" elements can be compacted into a list whose elements are + * dma addresses of physical pages. The code supports also the weird case + * where --few fragments of the same page-- are present in the SG as + * consecutive elements. Also, it handles one entry SG. + */ +static int iser_sg_to_page_vec(struct iser_data_buf *data, + struct iser_page_vec *page_vec) +{ + struct scatterlist *sg = (struct scatterlist *)data->buf; + dma_addr_t first_addr, last_addr, page; + int start_aligned, end_aligned; + unsigned int cur_page = 0; + unsigned long total_sz = 0; + int i; + + /* compute the offset of first element */ + page_vec->offset = (u64) sg[0].offset; + + for (i = 0; i < data->dma_nents; i++) { + total_sz += sg_dma_len(&sg[i]); + + first_addr = sg_dma_address(&sg[i]); + last_addr = first_addr + sg_dma_len(&sg[i]); + + start_aligned = !(first_addr & ~PAGE_MASK); + end_aligned = !(last_addr & ~PAGE_MASK); + + /* continue to collect page fragments till aligned or SG ends */ + while (!end_aligned && (i + 1 < data->dma_nents)) { + i++; + total_sz += sg_dma_len(&sg[i]); + last_addr = sg_dma_address(&sg[i]) + sg_dma_len(&sg[i]); + end_aligned = !(last_addr & ~PAGE_MASK); + } + + first_addr = first_addr & PAGE_MASK; + + for (page = first_addr; page < last_addr; page += PAGE_SIZE) + page_vec->pages[cur_page++] = page; + + } + page_vec->data_size = total_sz; + iser_dbg("page_vec->data_size:%d cur_page %d\n", page_vec->data_size,cur_page); + return cur_page; +} + +#define MASK_4K ((1UL << 12) - 1) /* 0xFFF */ +#define IS_4K_ALIGNED(addr) ((((unsigned long)addr) & MASK_4K) == 0) + +/** + * iser_data_buf_aligned_len - Tries to determine the maximal correctly aligned + * for RDMA sub-list of a scatter-gather list of memory buffers, and returns + * the number of entries which are aligned correctly. Supports the case where + * consecutive SG elements are actually fragments of the same physcial page. + */ +static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data) +{ + struct scatterlist *sg; + dma_addr_t end_addr, next_addr; + int i, cnt; + unsigned int ret_len = 0; + + sg = (struct scatterlist *)data->buf; + + for (cnt = 0, i = 0; i < data->dma_nents; i++, cnt++) { + /* iser_dbg("Checking sg iobuf [%d]: phys=0x%08lX " + "offset: %ld sz: %ld\n", i, + (unsigned long)page_to_phys(sg[i].page), + (unsigned long)sg[i].offset, + (unsigned long)sg[i].length); */ + end_addr = sg_dma_address(&sg[i]) + + sg_dma_len(&sg[i]); + /* iser_dbg("Checking sg iobuf end address " + "0x%08lX\n", end_addr); */ + if (i + 1 < data->dma_nents) { + next_addr = sg_dma_address(&sg[i+1]); + /* are i, i+1 fragments of the same page? */ + if (end_addr == next_addr) + continue; + else if (!IS_4K_ALIGNED(end_addr)) { + ret_len = cnt + 1; + break; + } + } + } + if (i == data->dma_nents) + ret_len = cnt; /* loop ended */ + iser_dbg("Found %d aligned entries out of %d in sg:0x%p\n", + ret_len, data->dma_nents, data); + return ret_len; +} + +static void iser_data_buf_dump(struct iser_data_buf *data) +{ + struct scatterlist *sg = (struct scatterlist *)data->buf; + int i; + + for (i = 0; i < data->size; i++) + iser_err("sg[%d] dma_addr:0x%lX page:0x%p " + "off:%d sz:%d dma_len:%d\n", + i, (unsigned long)sg_dma_address(&sg[i]), + sg[i].page, sg[i].offset, + sg[i].length,sg_dma_len(&sg[i])); +} + +static void iser_dump_page_vec(struct iser_page_vec *page_vec) +{ + int i; + + iser_err("page vec length %d data size %d\n", + page_vec->length, page_vec->data_size); + for (i = 0; i < page_vec->length; i++) + iser_err("%d %lx\n",i,(unsigned long)page_vec->pages[i]); +} + +static void iser_page_vec_build(struct iser_data_buf *data, + struct iser_page_vec *page_vec) +{ + int page_vec_len = 0; + + page_vec->length = 0; + page_vec->offset = 0; + + iser_dbg("Translating sg sz: %d\n", data->dma_nents); + page_vec_len = iser_sg_to_page_vec(data,page_vec); + iser_dbg("sg len %d page_vec_len %d\n", data->dma_nents,page_vec_len); + + page_vec->length = page_vec_len; + + if (page_vec_len * PAGE_SIZE < page_vec->data_size) { + iser_err("page_vec too short to hold this SG\n"); + iser_data_buf_dump(data); + iser_dump_page_vec(page_vec); + BUG(); + } +} + +/** + * iser_reg_rdma_mem - Registers memory intended for RDMA, + * obtaining rkey and va + * + * returns 0 on success, errno code on failure + */ +int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask, + enum iser_data_dir cmd_dir) +{ + struct iser_conn *ib_conn = iser_ctask->iser_conn->ib_conn; + struct iser_data_buf *mem = &iser_ctask->data[cmd_dir]; + struct iser_regd_buf *regd_buf; + int aligned_len; + int err; + + regd_buf = &iser_ctask->rdma_regd[cmd_dir]; + + aligned_len = iser_data_buf_aligned_len(mem); + if (aligned_len != mem->size) { + iser_err("rdma alignment violation %d/%d aligned\n", + aligned_len, mem->size); + iser_data_buf_dump(mem); + /* allocate copy buf, if we are writing, copy the */ + /* unaligned scatterlist, dma map the copy */ + if (iser_start_rdma_unaligned_sg(iser_ctask, cmd_dir) != 0) + return -ENOMEM; + mem = &iser_ctask->data_copy[cmd_dir]; + } + + iser_page_vec_build(mem, ib_conn->page_vec); + err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, ®d_buf->reg); + if (err) + return err; + + /* take a reference on this regd buf such that it will not be released * + * (eg in send dto completion) before we get the scsi response */ + atomic_inc(®d_buf->ref_count); + return 0; +} diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c new file mode 100644 index 0000000..ff117bb --- /dev/null +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -0,0 +1,827 @@ +/* + * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: iser_verbs.c 7051 2006-05-10 12:29:11Z ogerlitz $ + */ +#include +#include +#include +#include +#include +#include + +#include "iscsi_iser.h" + +#define ISCSI_ISER_MAX_CONN 8 +#define ISER_MAX_CQ_LEN ((ISER_QP_MAX_RECV_DTOS + \ + ISER_QP_MAX_REQ_DTOS) * \ + ISCSI_ISER_MAX_CONN) + +static void iser_cq_tasklet_fn(unsigned long data); +static void iser_cq_callback(struct ib_cq *cq, void *cq_context); +static void iser_comp_error_worker(void *data); + +static void iser_cq_event_callback(struct ib_event *cause, void *context) +{ + iser_err("got cq event %d \n", cause->event); +} + +static void iser_qp_event_callback(struct ib_event *cause, void *context) +{ + iser_err("got qp event %d\n",cause->event); +} + +/** + * iser_create_device_ib_res - creates Protection Domain (PD), Completion + * Queue (CQ), DMA Memory Region (DMA MR) with the device associated with + * the adapator. + * + * returns 0 on success, -1 on failure + */ +static int iser_create_device_ib_res(struct iser_device *device) +{ + device->pd = ib_alloc_pd(device->ib_device); + if (IS_ERR(device->pd)) + goto pd_err; + + device->cq = ib_create_cq(device->ib_device, + iser_cq_callback, + iser_cq_event_callback, + (void *)device, + ISER_MAX_CQ_LEN); + if (IS_ERR(device->cq)) + goto cq_err; + + if (ib_req_notify_cq(device->cq, IB_CQ_NEXT_COMP)) + goto cq_arm_err; + + tasklet_init(&device->cq_tasklet, + iser_cq_tasklet_fn, + (unsigned long)device); + + device->mr = ib_get_dma_mr(device->pd, + IB_ACCESS_LOCAL_WRITE); + if (IS_ERR(device->mr)) + goto dma_mr_err; + + return 0; + +dma_mr_err: + tasklet_kill(&device->cq_tasklet); +cq_arm_err: + ib_destroy_cq(device->cq); +cq_err: + ib_dealloc_pd(device->pd); +pd_err: + iser_err("failed to allocate an IB resource\n"); + return -1; +} + +/** + * iser_free_device_ib_res - destory/dealloc/dereg the DMA MR, + * CQ and PD created with the device associated with the adapator. + */ +static void iser_free_device_ib_res(struct iser_device *device) +{ + BUG_ON(device->mr == NULL); + + tasklet_kill(&device->cq_tasklet); + + (void)ib_dereg_mr(device->mr); + (void)ib_destroy_cq(device->cq); + (void)ib_dealloc_pd(device->pd); + + device->mr = NULL; + device->cq = NULL; + device->pd = NULL; +} + +/** + * iser_create_ib_conn_res - Creates FMR pool and Queue-Pair (QP) + * + * returns 0 on success, -1 on failure + */ +static int iser_create_ib_conn_res(struct iser_conn *ib_conn) +{ + struct iser_device *device; + struct ib_qp_init_attr init_attr; + int ret; + struct ib_fmr_pool_param params; + + BUG_ON(ib_conn->device == NULL); + + device = ib_conn->device; + + ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) + + (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)), + GFP_KERNEL); + if (!ib_conn->page_vec) { + ret = -ENOMEM; + goto alloc_err; + } + ib_conn->page_vec->pages = (u64 *) (ib_conn->page_vec + 1); + + params.page_shift = PAGE_SHIFT; + /* when the first/last SG element are not start/end * + * page aligned, the map whould be of N+1 pages */ + params.max_pages_per_fmr = ISCSI_ISER_SG_TABLESIZE + 1; + /* make the pool size twice the max number of SCSI commands * + * the ML is expected to queue, watermark for unmap at 50% */ + params.pool_size = ISCSI_XMIT_CMDS_MAX * 2; + params.dirty_watermark = ISCSI_XMIT_CMDS_MAX; + params.cache = 0; + params.flush_function = NULL; + params.access = (IB_ACCESS_LOCAL_WRITE | + IB_ACCESS_REMOTE_WRITE | + IB_ACCESS_REMOTE_READ); + + ib_conn->fmr_pool = ib_create_fmr_pool(device->pd, ¶ms); + if (IS_ERR(ib_conn->fmr_pool)) { + ret = PTR_ERR(ib_conn->fmr_pool); + goto fmr_pool_err; + } + + memset(&init_attr, 0, sizeof init_attr); + + init_attr.event_handler = iser_qp_event_callback; + init_attr.qp_context = (void *)ib_conn; + init_attr.send_cq = device->cq; + init_attr.recv_cq = device->cq; + init_attr.cap.max_send_wr = ISER_QP_MAX_REQ_DTOS; + init_attr.cap.max_recv_wr = ISER_QP_MAX_RECV_DTOS; + init_attr.cap.max_send_sge = MAX_REGD_BUF_VECTOR_LEN; + init_attr.cap.max_recv_sge = 2; + init_attr.sq_sig_type = IB_SIGNAL_REQ_WR; + init_attr.qp_type = IB_QPT_RC; + + ret = rdma_create_qp(ib_conn->cma_id, device->pd, &init_attr); + if (ret) + goto qp_err; + + ib_conn->qp = ib_conn->cma_id->qp; + iser_err("setting conn %p cma_id %p: fmr_pool %p qp %p\n", + ib_conn, ib_conn->cma_id, + ib_conn->fmr_pool, ib_conn->cma_id->qp); + return ret; + +qp_err: + (void)ib_destroy_fmr_pool(ib_conn->fmr_pool); +fmr_pool_err: + kfree(ib_conn->page_vec); +alloc_err: + iser_err("unable to alloc mem or create resource, err %d\n", ret); + return ret; +} + +/** + * releases the FMR pool, QP and CMA ID objects, returns 0 on success, + * -1 on failure + */ +static int iser_free_ib_conn_res(struct iser_conn *ib_conn) +{ + BUG_ON(ib_conn == NULL); + + iser_err("freeing conn %p cma_id %p fmr pool %p qp %p\n", + ib_conn, ib_conn->cma_id, + ib_conn->fmr_pool, ib_conn->qp); + + /* qp is created only once both addr & route are resolved */ + if (ib_conn->fmr_pool != NULL) + ib_destroy_fmr_pool(ib_conn->fmr_pool); + + if (ib_conn->qp != NULL) + rdma_destroy_qp(ib_conn->cma_id); + + if (ib_conn->cma_id != NULL) + rdma_destroy_id(ib_conn->cma_id); + + ib_conn->fmr_pool = NULL; + ib_conn->qp = NULL; + ib_conn->cma_id = NULL; + kfree(ib_conn->page_vec); + + return 0; +} + +/** + * based on the resolved device node GUID see if there already allocated + * device for this device. If there's no such, create one. + */ +static +struct iser_device *iser_device_find_by_ib_device(struct rdma_cm_id *cma_id) +{ + struct list_head *p_list; + struct iser_device *device = NULL; + + mutex_lock(&ig.device_list_mutex); + + p_list = ig.device_list.next; + while (p_list != &ig.device_list) { + device = list_entry(p_list, struct iser_device, ig_list); + /* find if there's a match using the node GUID */ + if (device->ib_device->node_guid == cma_id->device->node_guid) + break; + } + + if (device == NULL) { + device = kzalloc(sizeof *device, GFP_KERNEL); + if (device == NULL) + goto out; + /* assign this device to the device */ + device->ib_device = cma_id->device; + /* init the device and link it into ig device list */ + if (iser_create_device_ib_res(device)) { + kfree(device); + device = NULL; + goto out; + } + list_add(&device->ig_list, &ig.device_list); + } +out: + BUG_ON(device == NULL); + device->refcount++; + mutex_unlock(&ig.device_list_mutex); + return device; +} + +/* if there's no demand for this device, release it */ +static void iser_device_try_release(struct iser_device *device) +{ + mutex_lock(&ig.device_list_mutex); + device->refcount--; + iser_err("device %p refcount %d\n",device,device->refcount); + if (!device->refcount) { + iser_free_device_ib_res(device); + list_del(&device->ig_list); + kfree(device); + } + mutex_unlock(&ig.device_list_mutex); +} + +int iser_conn_state_comp(struct iser_conn *ib_conn, + enum iser_ib_conn_state comp) +{ + int ret; + + spin_lock_bh(&ib_conn->lock); + ret = (ib_conn->state == comp); + spin_unlock_bh(&ib_conn->lock); + return ret; +} + +static int iser_conn_state_comp_exch(struct iser_conn *ib_conn, + enum iser_ib_conn_state comp, + enum iser_ib_conn_state exch) +{ + int ret; + + spin_lock_bh(&ib_conn->lock); + if ((ret = (ib_conn->state == comp))) + ib_conn->state = exch; + spin_unlock_bh(&ib_conn->lock); + return ret; +} + +/** + * triggers start of the disconnect procedures and wait for them to be done + */ +void iser_conn_terminate(struct iser_conn *ib_conn) +{ + int err = 0; + + /* change the ib conn state only if the conn is UP, however always call + * rdma_disconnect since this is the only way to cause the CMA to change + * the QP state to ERROR + */ + + iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, ISER_CONN_TERMINATING); + err = rdma_disconnect(ib_conn->cma_id); + if (err) + iser_err("Failed to disconnect, conn: 0x%p err %d\n", + ib_conn,err); + + wait_event_interruptible(ib_conn->wait, + ib_conn->state == ISER_CONN_DOWN); + + iser_conn_release(ib_conn); +} + +static void iser_connect_error(struct rdma_cm_id *cma_id) +{ + struct iser_conn *ib_conn; + ib_conn = (struct iser_conn *)cma_id->context; + + ib_conn->state = ISER_CONN_DOWN; + wake_up_interruptible(&ib_conn->wait); +} + +static void iser_addr_handler(struct rdma_cm_id *cma_id) +{ + struct iser_device *device; + struct iser_conn *ib_conn; + int ret; + + device = iser_device_find_by_ib_device(cma_id); + ib_conn = (struct iser_conn *)cma_id->context; + ib_conn->device = device; + + ret = rdma_resolve_route(cma_id, 1000); + if (ret) { + iser_err("resolve route failed: %d\n", ret); + iser_connect_error(cma_id); + } + return; +} + +static void iser_route_handler(struct rdma_cm_id *cma_id) +{ + struct rdma_conn_param conn_param; + int ret; + + ret = iser_create_ib_conn_res((struct iser_conn *)cma_id->context); + if (ret) + goto failure; + + iser_dbg("path.mtu is %d setting it to %d\n", + cma_id->route.path_rec->mtu, IB_MTU_1024); + + /* we must set the MTU to 1024 as this is what the target is assuming */ + if (cma_id->route.path_rec->mtu > IB_MTU_1024) + cma_id->route.path_rec->mtu = IB_MTU_1024; + + memset(&conn_param, 0, sizeof conn_param); + conn_param.responder_resources = 4; + conn_param.initiator_depth = 1; + conn_param.retry_count = 7; + conn_param.rnr_retry_count = 6; + + ret = rdma_connect(cma_id, &conn_param); + if (ret) { + iser_err("failure connecting: %d\n", ret); + goto failure; + } + + return; +failure: + iser_connect_error(cma_id); +} + +static void iser_connected_handler(struct rdma_cm_id *cma_id) +{ + struct iser_conn *ib_conn; + + ib_conn = (struct iser_conn *)cma_id->context; + ib_conn->state = ISER_CONN_UP; + wake_up_interruptible(&ib_conn->wait); +} + +static void iser_disconnected_handler(struct rdma_cm_id *cma_id) +{ + struct iser_conn *ib_conn; + + ib_conn = (struct iser_conn *)cma_id->context; + ib_conn->disc_evt_flag = 1; + + /* getting here when the state is UP means that the conn is being * + * terminated asynchronously from the iSCSI layer's perspective. */ + if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, + ISER_CONN_TERMINATING)) + iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn, + ISCSI_ERR_CONN_FAILED); + + /* Complete the termination process if no posts are pending */ + if ((atomic_read(&ib_conn->post_recv_buf_count) == 0) && + (atomic_read(&ib_conn->post_send_buf_count) == 0)) { + ib_conn->state = ISER_CONN_DOWN; + wake_up_interruptible(&ib_conn->wait); + } +} + +static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) +{ + int ret = 0; + + iser_err("event %d conn %p id %p\n",event->event,cma_id->context,cma_id); + + switch (event->event) { + case RDMA_CM_EVENT_ADDR_RESOLVED: + iser_addr_handler(cma_id); + break; + case RDMA_CM_EVENT_ROUTE_RESOLVED: + iser_route_handler(cma_id); + break; + case RDMA_CM_EVENT_ESTABLISHED: + iser_connected_handler(cma_id); + break; + case RDMA_CM_EVENT_ADDR_ERROR: + case RDMA_CM_EVENT_ROUTE_ERROR: + case RDMA_CM_EVENT_CONNECT_ERROR: + case RDMA_CM_EVENT_UNREACHABLE: + case RDMA_CM_EVENT_REJECTED: + iser_err("event: %d, error: %d\n", event->event, event->status); + iser_connect_error(cma_id); + break; + case RDMA_CM_EVENT_DISCONNECTED: + iser_disconnected_handler(cma_id); + break; + case RDMA_CM_EVENT_DEVICE_REMOVAL: + BUG(); + break; + case RDMA_CM_EVENT_CONNECT_RESPONSE: + BUG(); + break; + case RDMA_CM_EVENT_CONNECT_REQUEST: + default: + break; + } + return ret; +} + +int iser_conn_init(struct iser_conn **ibconn) +{ + struct iser_conn *ib_conn; + + ib_conn = kzalloc(sizeof *ib_conn, GFP_KERNEL); + if (!ib_conn) { + iser_err("can't alloc memory for struct iser_conn\n"); + return -ENOMEM; + } + ib_conn->state = ISER_CONN_INIT; + init_waitqueue_head(&ib_conn->wait); + atomic_set(&ib_conn->post_recv_buf_count, 0); + atomic_set(&ib_conn->post_send_buf_count, 0); + INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker, + ib_conn); + INIT_LIST_HEAD(&ib_conn->conn_list); + spin_lock_init(&ib_conn->lock); + + *ibconn = ib_conn; + return 0; +} + + /** + * starts the process of connecting to the target + * sleeps untill the connection is established or rejected + */ +int iser_connect(struct iser_conn *ib_conn, + struct sockaddr_in *src_addr, + struct sockaddr_in *dst_addr, + int non_blocking) +{ + struct sockaddr *src, *dst; + int err = 0; + + sprintf(ib_conn->name,"%d.%d.%d.%d:%d", + NIPQUAD(dst_addr->sin_addr.s_addr), dst_addr->sin_port); + + /* the device is known only --after-- address resolution */ + ib_conn->device = NULL; + + iser_err("connecting to: %d.%d.%d.%d, port 0x%x\n", + NIPQUAD(dst_addr->sin_addr), dst_addr->sin_port); + + ib_conn->state = ISER_CONN_PENDING; + + ib_conn->cma_id = rdma_create_id(iser_cma_handler, + (void *)ib_conn, + RDMA_PS_TCP); + if (IS_ERR(ib_conn->cma_id)) { + err = PTR_ERR(ib_conn->cma_id); + iser_err("rdma_create_id failed: %d\n", err); + goto id_failure; + } + + src = (struct sockaddr *)src_addr; + dst = (struct sockaddr *)dst_addr; + err = rdma_resolve_addr(ib_conn->cma_id, src, dst, 1000); + if (err) { + iser_err("rdma_resolve_addr failed: %d\n", err); + goto addr_failure; + } + + if (!non_blocking) { + wait_event_interruptible(ib_conn->wait, + (ib_conn->state != ISER_CONN_PENDING)); + + if (ib_conn->state != ISER_CONN_UP) { + err = -EIO; + goto connect_failure; + } + } + + mutex_lock(&ig.connlist_mutex); + list_add(&ib_conn->conn_list, &ig.connlist); + mutex_unlock(&ig.connlist_mutex); + return 0; + +id_failure: + ib_conn->cma_id = NULL; +addr_failure: + ib_conn->state = ISER_CONN_DOWN; +connect_failure: + iser_conn_release(ib_conn); + return err; +} + +/** + * Frees all conn objects and deallocs conn descriptor + */ +void iser_conn_release(struct iser_conn *ib_conn) +{ + struct iser_device *device = ib_conn->device; + + BUG_ON(ib_conn->state != ISER_CONN_DOWN); + + mutex_lock(&ig.connlist_mutex); + list_del(&ib_conn->conn_list); + mutex_unlock(&ig.connlist_mutex); + + iser_free_ib_conn_res(ib_conn); + ib_conn->device = NULL; + /* on EVENT_ADDR_ERROR there's no device yet for this conn */ + if (device != NULL) + iser_device_try_release(device); + kfree(ib_conn); +} + + +/** + * iser_reg_page_vec - Register physical memory + * + * returns: 0 on success, errno code on failure + */ +int iser_reg_page_vec(struct iser_conn *ib_conn, + struct iser_page_vec *page_vec, + struct iser_mem_reg *mem_reg) +{ + struct ib_pool_fmr *mem; + u64 io_addr; + u64 *page_list; + int status; + + page_list = page_vec->pages; + io_addr = page_list[0]; + + mem = ib_fmr_pool_map_phys(ib_conn->fmr_pool, + page_list, + page_vec->length, + &io_addr); + + if (IS_ERR(mem)) { + status = (int)PTR_ERR(mem); + iser_err("ib_fmr_pool_map_phys failed: %d\n", status); + return status; + } + + mem_reg->lkey = mem->fmr->lkey; + mem_reg->rkey = mem->fmr->rkey; + mem_reg->len = page_vec->length * PAGE_SIZE; + mem_reg->va = io_addr; + mem_reg->mem_h = (void *)mem; + + mem_reg->va += page_vec->offset; + mem_reg->len = page_vec->data_size; + + iser_dbg("PHYSICAL Mem.register, [PHYS p_array: 0x%p, sz: %d, " + "entry[0]: (0x%08lx,%ld)] -> " + "[lkey: 0x%08X mem_h: 0x%p va: 0x%08lX sz: %ld]\n", + page_vec, page_vec->length, + (unsigned long)page_vec->pages[0], + (unsigned long)page_vec->data_size, + (unsigned int)mem_reg->lkey, mem_reg->mem_h, + (unsigned long)mem_reg->va, (unsigned long)mem_reg->len); + return 0; +} + +/** + * Unregister (previosuly registered) memory. + */ +void iser_unreg_mem(struct iser_mem_reg *reg) +{ + int ret; + + iser_dbg("PHYSICAL Mem.Unregister mem_h %p\n",reg->mem_h); + + ret = ib_fmr_pool_unmap((struct ib_pool_fmr *)reg->mem_h); + if (ret) + iser_err("ib_fmr_pool_unmap failed %d\n", ret); + + reg->mem_h = NULL; +} + +/** + * iser_dto_to_iov - builds IOV from a dto descriptor + */ +static void iser_dto_to_iov(struct iser_dto *dto, struct ib_sge *iov, int iov_len) +{ + int i; + struct ib_sge *sge; + struct iser_regd_buf *regd_buf; + + if (dto->regd_vector_len > iov_len) { + iser_err("iov size %d too small for posting dto of len %d\n", + iov_len, dto->regd_vector_len); + BUG(); + } + + for (i = 0; i < dto->regd_vector_len; i++) { + sge = &iov[i]; + regd_buf = dto->regd[i]; + + sge->addr = regd_buf->reg.va; + sge->length = regd_buf->reg.len; + sge->lkey = regd_buf->reg.lkey; + + if (dto->used_sz[i] > 0) /* Adjust size */ + sge->length = dto->used_sz[i]; + + /* offset and length should not exceed the regd buf length */ + if (sge->length + dto->offset[i] > regd_buf->reg.len) { + iser_err("Used len:%ld + offset:%d, exceed reg.buf.len:" + "%ld in dto:0x%p [%d], va:0x%08lX\n", + (unsigned long)sge->length, dto->offset[i], + (unsigned long)regd_buf->reg.len, dto, i, + (unsigned long)sge->addr); + BUG(); + } + + sge->addr += dto->offset[i]; /* Adjust offset */ + } +} + +/** + * iser_post_recv - Posts a receive buffer. + * + * returns 0 on success, -1 on failure + */ +int iser_post_recv(struct iser_desc *rx_desc) +{ + int ib_ret, ret_val = 0; + struct ib_recv_wr recv_wr, *recv_wr_failed; + struct ib_sge iov[2]; + struct iser_conn *ib_conn; + struct iser_dto *recv_dto = &rx_desc->dto; + + /* Retrieve conn */ + ib_conn = recv_dto->conn->ib_conn; + + iser_dto_to_iov(recv_dto, iov, 2); + + recv_wr.next = NULL; + recv_wr.sg_list = iov; + recv_wr.num_sge = recv_dto->regd_vector_len; + recv_wr.wr_id = (unsigned long)rx_desc; + + atomic_inc(&ib_conn->post_recv_buf_count); + ib_ret = ib_post_recv(ib_conn->qp, &recv_wr, &recv_wr_failed); + if (ib_ret) { + iser_err("ib_post_recv failed ret=%d\n", ib_ret); + atomic_dec(&ib_conn->post_recv_buf_count); + ret_val = -1; + } + + return ret_val; +} + +/** + * iser_start_send - Initiate a Send DTO operation + * + * returns 0 on success, -1 on failure + */ +int iser_post_send(struct iser_desc *tx_desc) +{ + int ib_ret, ret_val = 0; + struct ib_send_wr send_wr, *send_wr_failed; + struct ib_sge iov[MAX_REGD_BUF_VECTOR_LEN]; + struct iser_conn *ib_conn; + struct iser_dto *dto = &tx_desc->dto; + + ib_conn = dto->conn->ib_conn; + + iser_dto_to_iov(dto, iov, MAX_REGD_BUF_VECTOR_LEN); + + send_wr.next = NULL; + send_wr.wr_id = (unsigned long)tx_desc; + send_wr.sg_list = iov; + send_wr.num_sge = dto->regd_vector_len; + send_wr.opcode = IB_WR_SEND; + send_wr.send_flags = dto->notify_enable ? IB_SEND_SIGNALED : 0; + + atomic_inc(&ib_conn->post_send_buf_count); + + ib_ret = ib_post_send(ib_conn->qp, &send_wr, &send_wr_failed); + if (ib_ret) { + iser_err("Failed to start SEND DTO, dto: 0x%p, IOV len: %d\n", + dto, dto->regd_vector_len); + iser_err("ib_post_send failed, ret:%d\n", ib_ret); + atomic_dec(&ib_conn->post_send_buf_count); + ret_val = -1; + } + + return ret_val; +} + +static void iser_comp_error_worker(void *data) +{ + struct iser_conn *ib_conn = data; + + /* getting here when the state is UP means that the conn is being * + * terminated asynchronously from the iSCSI layer's perspective. */ + if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, + ISER_CONN_TERMINATING)) + iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn, + ISCSI_ERR_CONN_FAILED); + + /* complete the termination process if disconnect event was delivered * + * note there are no more non completed posts to the QP */ + if (ib_conn->disc_evt_flag) { + ib_conn->state = ISER_CONN_DOWN; + wake_up_interruptible(&ib_conn->wait); + } +} + +static void iser_handle_comp_error(struct iser_desc *desc) +{ + struct iser_dto *dto = &desc->dto; + struct iser_conn *ib_conn = dto->conn->ib_conn; + + iser_dto_buffs_release(dto); + + if (desc->type == ISCSI_RX) { + kfree(desc->data); + kmem_cache_free(ig.desc_cache, desc); + atomic_dec(&ib_conn->post_recv_buf_count); + } else { /* type is TX control/command/dataout */ + if (desc->type == ISCSI_TX_DATAOUT) + kmem_cache_free(ig.desc_cache, desc); + atomic_dec(&ib_conn->post_send_buf_count); + } + + if (atomic_read(&ib_conn->post_recv_buf_count) == 0 && + atomic_read(&ib_conn->post_send_buf_count) == 0) + schedule_work(&ib_conn->comperror_work); +} + +static void iser_cq_tasklet_fn(unsigned long data) +{ + struct iser_device *device = (struct iser_device *)data; + struct ib_cq *cq = device->cq; + struct ib_wc wc; + struct iser_desc *desc; + unsigned long xfer_len; + + while (ib_poll_cq(cq, 1, &wc) == 1) { + desc = (struct iser_desc *) (unsigned long) wc.wr_id; + BUG_ON(desc == NULL); + + if (wc.status == IB_WC_SUCCESS) { + if (desc->type == ISCSI_RX) { + xfer_len = (unsigned long)wc.byte_len; + iser_rcv_completion(desc, xfer_len); + } else /* type == ISCSI_TX_CONTROL/SCSI_CMD/DOUT */ + iser_snd_completion(desc); + } else { + iser_err("comp w. error op %d status %d\n",desc->type,wc.status); + iser_handle_comp_error(desc); + } + } + /* #warning "it is assumed here that arming CQ only once its empty" * + * " would not cause interrupts to be missed" */ + ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); +} + +static void iser_cq_callback(struct ib_cq *cq, void *cq_context) +{ + struct iser_device *device = (struct iser_device *)cq_context; + + tasklet_schedule(&device->cq_tasklet); +} diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 9cbdffa..4e22afe 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -62,6 +62,13 @@ MODULE_DESCRIPTION("InfiniBand SCSI RDMA "v" DRV_VERSION " (" DRV_RELDATE ")"); MODULE_LICENSE("Dual BSD/GPL"); +static int srp_sg_tablesize = SRP_DEF_SG_TABLESIZE; +static int srp_max_iu_len; + +module_param(srp_sg_tablesize, int, 0444); +MODULE_PARM_DESC(srp_sg_tablesize, + "Max number of gather/scatter entries per I/O (default is 12)"); + static int topspin_workarounds = 1; module_param(topspin_workarounds, int, 0444); @@ -105,7 +112,8 @@ static struct srp_iu *srp_alloc_iu(struc if (!iu->buf) goto out_free_iu; - iu->dma = dma_map_single(host->dev->dma_device, iu->buf, size, direction); + iu->dma = dma_map_single(host->dev->dev->dma_device, + iu->buf, size, direction); if (dma_mapping_error(iu->dma)) goto out_free_buf; @@ -127,7 +135,8 @@ static void srp_free_iu(struct srp_host if (!iu) return; - dma_unmap_single(host->dev->dma_device, iu->dma, iu->size, iu->direction); + dma_unmap_single(host->dev->dev->dma_device, + iu->dma, iu->size, iu->direction); kfree(iu->buf); kfree(iu); } @@ -147,7 +156,7 @@ static int srp_init_qp(struct srp_target if (!attr) return -ENOMEM; - ret = ib_find_cached_pkey(target->srp_host->dev, + ret = ib_find_cached_pkey(target->srp_host->dev->dev, target->srp_host->port, be16_to_cpu(target->path.pkey), &attr->pkey_index); @@ -179,7 +188,7 @@ static int srp_create_target_ib(struct s if (!init_attr) return -ENOMEM; - target->cq = ib_create_cq(target->srp_host->dev, srp_completion, + target->cq = ib_create_cq(target->srp_host->dev->dev, srp_completion, NULL, target, SRP_CQ_SIZE); if (IS_ERR(target->cq)) { ret = PTR_ERR(target->cq); @@ -198,7 +207,7 @@ static int srp_create_target_ib(struct s init_attr->send_cq = target->cq; init_attr->recv_cq = target->cq; - target->qp = ib_create_qp(target->srp_host->pd, init_attr); + target->qp = ib_create_qp(target->srp_host->dev->pd, init_attr); if (IS_ERR(target->qp)) { ret = PTR_ERR(target->qp); ib_destroy_cq(target->cq); @@ -250,7 +259,7 @@ static int srp_lookup_path(struct srp_ta init_completion(&target->done); - target->path_query_id = ib_sa_path_rec_get(target->srp_host->dev, + target->path_query_id = ib_sa_path_rec_get(target->srp_host->dev->dev, target->srp_host->port, &target->path, IB_SA_PATH_REC_DGID | @@ -309,10 +318,32 @@ static int srp_send_req(struct srp_targe req->priv.opcode = SRP_LOGIN_REQ; req->priv.tag = 0; - req->priv.req_it_iu_len = cpu_to_be32(SRP_MAX_IU_LEN); + req->priv.req_it_iu_len = cpu_to_be32(srp_max_iu_len); req->priv.req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT); - memcpy(req->priv.initiator_port_id, target->srp_host->initiator_port_id, 16); + /* + * In the published SRP specification (draft rev. 16a), the + * port identifier format is 8 bytes of ID extension followed + * by 8 bytes of GUID. Older drafts put the two halves in the + * opposite order, so that the GUID comes first. + * + * Targets conforming to these obsolete drafts can be + * recognized by the I/O Class they report. + */ + if (target->io_class == SRP_REV10_IB_IO_CLASS) { + memcpy(req->priv.initiator_port_id, + target->srp_host->initiator_port_id + 8, 8); + memcpy(req->priv.initiator_port_id + 8, + target->srp_host->initiator_port_id, 8); + memcpy(req->priv.target_port_id, &target->ioc_guid, 8); + memcpy(req->priv.target_port_id + 8, &target->id_ext, 8); + } else { + memcpy(req->priv.initiator_port_id, + target->srp_host->initiator_port_id, 16); + memcpy(req->priv.target_port_id, &target->id_ext, 8); + memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8); + } + /* * Topspin/Cisco SRP targets will reject our login unless we * zero out the first 8 bytes of our initiator port ID. The @@ -325,8 +356,6 @@ static int srp_send_req(struct srp_targe (unsigned long long) be64_to_cpu(target->ioc_guid)); memset(req->priv.initiator_port_id, 0, 8); } - memcpy(req->priv.target_port_id, &target->id_ext, 8); - memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8); status = ib_send_cm_req(target->cm_id, &req->param); @@ -359,9 +388,9 @@ static void srp_remove_work(void *target target->state = SRP_TARGET_REMOVED; spin_unlock_irq(target->scsi_host->host_lock); - mutex_lock(&target->srp_host->target_mutex); + spin_lock(&target->srp_host->target_lock); list_del(&target->list); - mutex_unlock(&target->srp_host->target_mutex); + spin_unlock(&target->srp_host->target_lock); scsi_remove_host(target->scsi_host); ib_destroy_cm_id(target->cm_id); @@ -421,6 +450,11 @@ static void srp_unmap_data(struct scsi_c scmnd->sc_data_direction != DMA_FROM_DEVICE)) return; + if (req->fmr) { + ib_fmr_pool_unmap(req->fmr); + req->fmr = NULL; + } + /* * This handling of non-SG commands can be killed when the * SCSI midlayer no longer generates non-SG commands. @@ -433,18 +467,30 @@ static void srp_unmap_data(struct scsi_c scat = &req->fake_sg; } - dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents, + dma_unmap_sg(target->srp_host->dev->dev->dma_device, scat, nents, scmnd->sc_data_direction); } +static void srp_remove_req(struct srp_target_port *target, struct srp_request *req) +{ + srp_unmap_data(req->scmnd, target, req); + list_move_tail(&req->list, &target->free_reqs); +} + +static void srp_reset_req(struct srp_target_port *target, struct srp_request *req) +{ + req->scmnd->result = DID_RESET << 16; + req->scmnd->scsi_done(req->scmnd); + srp_remove_req(target, req); +} + static int srp_reconnect_target(struct srp_target_port *target) { struct ib_cm_id *new_cm_id; struct ib_qp_attr qp_attr; - struct srp_request *req; + struct srp_request *req, *tmp; struct ib_wc wc; int ret; - int i; spin_lock_irq(target->scsi_host->host_lock); if (target->state != SRP_TARGET_LIVE) { @@ -459,7 +505,7 @@ static int srp_reconnect_target(struct s * Now get a new local CM ID so that we avoid confusing the * target in case things are really fouled up. */ - new_cm_id = ib_create_cm_id(target->srp_host->dev, + new_cm_id = ib_create_cm_id(target->srp_host->dev->dev, srp_cm_handler, target); if (IS_ERR(new_cm_id)) { ret = PTR_ERR(new_cm_id); @@ -480,19 +526,12 @@ static int srp_reconnect_target(struct s while (ib_poll_cq(target->cq, 1, &wc) > 0) ; /* nothing */ - list_for_each_entry(req, &target->req_queue, list) { - req->scmnd->result = DID_RESET << 16; - req->scmnd->scsi_done(req->scmnd); - srp_unmap_data(req->scmnd, target, req); - } + list_for_each_entry_safe(req, tmp, &target->req_queue, list) + srp_reset_req(target, req); target->rx_head = 0; target->tx_head = 0; target->tx_tail = 0; - INIT_LIST_HEAD(&target->free_reqs); - INIT_LIST_HEAD(&target->req_queue); - for (i = 0; i < SRP_SQ_SIZE; ++i) - list_add_tail(&target->req_ring[i].list, &target->free_reqs); ret = srp_connect_target(target); if (ret) @@ -528,14 +567,79 @@ err: return ret; } +static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat, + int sg_cnt, struct srp_request *req, + struct srp_direct_buf *buf) +{ + u64 io_addr = 0; + u64 *dma_pages; + u32 len; + int page_cnt; + int i, j; + int ret; + + if (!dev->fmr_pool) + return -ENODEV; + + len = page_cnt = 0; + for (i = 0; i < sg_cnt; ++i) { + if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) { + if (i > 0) + return -EINVAL; + else + ++page_cnt; + } + if ((sg_dma_address(&scat[i]) + sg_dma_len(&scat[i])) & + ~dev->fmr_page_mask) { + if (i < sg_cnt - 1) + return -EINVAL; + else + ++page_cnt; + } + + len += sg_dma_len(&scat[i]); + } + + page_cnt += len >> dev->fmr_page_shift; + if (page_cnt > SRP_FMR_SIZE) + return -ENOMEM; + + dma_pages = kmalloc(sizeof (u64) * page_cnt, GFP_ATOMIC); + if (!dma_pages) + return -ENOMEM; + + page_cnt = 0; + for (i = 0; i < sg_cnt; ++i) + for (j = 0; j < sg_dma_len(&scat[i]); j += dev->fmr_page_size) + dma_pages[page_cnt++] = + (sg_dma_address(&scat[i]) & dev->fmr_page_mask) + j; + + req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool, + dma_pages, page_cnt, &io_addr); + if (IS_ERR(req->fmr)) { + ret = PTR_ERR(req->fmr); + goto out; + } + + buf->va = cpu_to_be64(sg_dma_address(&scat[0]) & ~dev->fmr_page_mask); + buf->key = cpu_to_be32(req->fmr->fmr->rkey); + buf->len = cpu_to_be32(len); + + ret = 0; + +out: + kfree(dma_pages); + + return ret; +} + static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, struct srp_request *req) { struct scatterlist *scat; struct srp_cmd *cmd = req->cmd->buf; int len, nents, count; - int i; - u8 fmt; + u8 fmt = SRP_DATA_DESC_DIRECT; if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE) return sizeof (struct srp_cmd); @@ -560,53 +664,63 @@ static int srp_map_data(struct scsi_cmnd sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen); } - count = dma_map_sg(target->srp_host->dev->dma_device, scat, nents, - scmnd->sc_data_direction); + count = dma_map_sg(target->srp_host->dev->dev->dma_device, + scat, nents, scmnd->sc_data_direction); + + fmt = SRP_DATA_DESC_DIRECT; + len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf); if (count == 1) { + /* + * The midlayer only generated a single gather/scatter + * entry, or DMA mapping coalesced everything to a + * single entry. So a direct descriptor along with + * the DMA MR suffices. + */ struct srp_direct_buf *buf = (void *) cmd->add_data; - fmt = SRP_DATA_DESC_DIRECT; - buf->va = cpu_to_be64(sg_dma_address(scat)); - buf->key = cpu_to_be32(target->srp_host->mr->rkey); + buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey); buf->len = cpu_to_be32(sg_dma_len(scat)); - - len = sizeof (struct srp_cmd) + - sizeof (struct srp_direct_buf); - } else { + } else if (srp_map_fmr(target->srp_host->dev, scat, count, req, + (void *) cmd->add_data)) { + /* + * FMR mapping failed, and the scatterlist has more + * than one entry. Generate an indirect memory + * descriptor. + */ struct srp_indirect_buf *buf = (void *) cmd->add_data; u32 datalen = 0; + int i; fmt = SRP_DATA_DESC_INDIRECT; + len = sizeof (struct srp_cmd) + + sizeof (struct srp_indirect_buf) + + count * sizeof (struct srp_direct_buf); + + for (i = 0; i < count; ++i) { + buf->desc_list[i].va = + cpu_to_be64(sg_dma_address(&scat[i])); + buf->desc_list[i].key = + cpu_to_be32(target->srp_host->dev->mr->rkey); + buf->desc_list[i].len = + cpu_to_be32(sg_dma_len(&scat[i])); + datalen += sg_dma_len(&scat[i]); + } if (scmnd->sc_data_direction == DMA_TO_DEVICE) cmd->data_out_desc_cnt = count; else cmd->data_in_desc_cnt = count; - buf->table_desc.va = cpu_to_be64(req->cmd->dma + - sizeof *cmd + - sizeof *buf); + buf->table_desc.va = + cpu_to_be64(req->cmd->dma + sizeof *cmd + sizeof *buf); buf->table_desc.key = - cpu_to_be32(target->srp_host->mr->rkey); + cpu_to_be32(target->srp_host->dev->mr->rkey); buf->table_desc.len = cpu_to_be32(count * sizeof (struct srp_direct_buf)); - for (i = 0; i < count; ++i) { - buf->desc_list[i].va = cpu_to_be64(sg_dma_address(&scat[i])); - buf->desc_list[i].key = - cpu_to_be32(target->srp_host->mr->rkey); - buf->desc_list[i].len = cpu_to_be32(sg_dma_len(&scat[i])); - - datalen += sg_dma_len(&scat[i]); - } - buf->len = cpu_to_be32(datalen); - - len = sizeof (struct srp_cmd) + - sizeof (struct srp_indirect_buf) + - count * sizeof (struct srp_direct_buf); } if (scmnd->sc_data_direction == DMA_TO_DEVICE) @@ -617,12 +731,6 @@ static int srp_map_data(struct scsi_cmnd return len; } -static void srp_remove_req(struct srp_target_port *target, struct srp_request *req) -{ - srp_unmap_data(req->scmnd, target, req); - list_move_tail(&req->list, &target->free_reqs); -} - static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) { struct srp_request *req; @@ -689,7 +797,7 @@ static void srp_handle_recv(struct srp_t iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV]; - dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma, + dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma, target->max_ti_iu_len, DMA_FROM_DEVICE); opcode = *(u8 *) iu->buf; @@ -726,7 +834,7 @@ static void srp_handle_recv(struct srp_t break; } - dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma, + dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma, target->max_ti_iu_len, DMA_FROM_DEVICE); } @@ -770,7 +878,7 @@ static int __srp_post_recv(struct srp_ta list.addr = iu->dma; list.length = iu->size; - list.lkey = target->srp_host->mr->lkey; + list.lkey = target->srp_host->dev->mr->lkey; wr.next = NULL; wr.sg_list = &list; @@ -805,12 +913,8 @@ static struct srp_iu *__srp_get_tx_iu(st if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE) return NULL; - if (unlikely(target->req_lim < 1)) { - if (printk_ratelimit()) - printk(KERN_DEBUG PFX "Target has req_lim %d\n", - target->req_lim); - return NULL; - } + if (unlikely(target->req_lim < 1)) + ++target->zero_req_lim; return target->tx_ring[target->tx_head & SRP_SQ_SIZE]; } @@ -828,7 +932,7 @@ static int __srp_post_send(struct srp_ta list.addr = iu->dma; list.length = len; - list.lkey = target->srp_host->mr->lkey; + list.lkey = target->srp_host->dev->mr->lkey; wr.next = NULL; wr.wr_id = target->tx_head & SRP_SQ_SIZE; @@ -870,8 +974,8 @@ static int srp_queuecommand(struct scsi_ if (!iu) goto err; - dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma, - SRP_MAX_IU_LEN, DMA_TO_DEVICE); + dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma, + srp_max_iu_len, DMA_TO_DEVICE); req = list_entry(target->free_reqs.next, struct srp_request, list); @@ -903,8 +1007,8 @@ static int srp_queuecommand(struct scsi_ goto err_unmap; } - dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma, - SRP_MAX_IU_LEN, DMA_TO_DEVICE); + dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma, + srp_max_iu_len, DMA_TO_DEVICE); if (__srp_post_send(target, iu, len)) { printk(KERN_ERR PFX "Send failed\n"); @@ -936,7 +1040,7 @@ static int srp_alloc_iu_bufs(struct srp_ for (i = 0; i < SRP_SQ_SIZE + 1; ++i) { target->tx_ring[i] = srp_alloc_iu(target->srp_host, - SRP_MAX_IU_LEN, + srp_max_iu_len, GFP_KERNEL, DMA_TO_DEVICE); if (!target->tx_ring[i]) goto err; @@ -1107,11 +1211,10 @@ static int srp_cm_handler(struct ib_cm_i srp_cm_rej_handler(cm_id, event, target); break; - case IB_CM_MRA_RECEIVED: - printk(KERN_ERR PFX "MRA received\n"); - break; - - case IB_CM_DREP_RECEIVED: + case IB_CM_DREQ_RECEIVED: + printk(KERN_WARNING PFX "DREQ received - connection closed\n"); + if (ib_send_cm_drep(cm_id, NULL, 0)) + printk(KERN_ERR PFX "Sending CM DREP failed\n"); break; case IB_CM_TIMEWAIT_EXIT: @@ -1121,6 +1224,11 @@ static int srp_cm_handler(struct ib_cm_i target->status = 0; break; + case IB_CM_MRA_RECEIVED: + case IB_CM_DREQ_ERROR: + case IB_CM_DREP_RECEIVED: + break; + default: printk(KERN_WARNING PFX "Unhandled CM event %d\n", event->event); break; @@ -1239,11 +1347,8 @@ static int srp_reset_device(struct scsi_ spin_lock_irq(target->scsi_host->host_lock); list_for_each_entry_safe(req, tmp, &target->req_queue, list) - if (req->scmnd->device == scmnd->device) { - req->scmnd->result = DID_RESET << 16; - req->scmnd->scsi_done(req->scmnd); - srp_remove_req(target, req); - } + if (req->scmnd->device == scmnd->device) + srp_reset_req(target, req); spin_unlock_irq(target->scsi_host->host_lock); @@ -1329,11 +1434,23 @@ static ssize_t show_dgid(struct class_de be16_to_cpu(((__be16 *) target->path.dgid.raw)[7])); } +static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf) +{ + struct srp_target_port *target = host_to_target(class_to_shost(cdev)); + + if (target->state == SRP_TARGET_DEAD || + target->state == SRP_TARGET_REMOVED) + return -ENODEV; + + return sprintf(buf, "%d\n", target->zero_req_lim); +} + static CLASS_DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL); static CLASS_DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL); static CLASS_DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL); static CLASS_DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); static CLASS_DEVICE_ATTR(dgid, S_IRUGO, show_dgid, NULL); +static CLASS_DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL); static struct class_device_attribute *srp_host_attrs[] = { &class_device_attr_id_ext, @@ -1341,6 +1458,7 @@ static struct class_device_attribute *sr &class_device_attr_service_id, &class_device_attr_pkey, &class_device_attr_dgid, + &class_device_attr_zero_req_lim, NULL }; @@ -1354,7 +1472,6 @@ static struct scsi_host_template srp_tem .eh_host_reset_handler = srp_reset_host, .can_queue = SRP_SQ_SIZE, .this_id = -1, - .sg_tablesize = SRP_MAX_INDIRECT, .cmd_per_lun = SRP_SQ_SIZE, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = srp_host_attrs @@ -1365,18 +1482,17 @@ static int srp_add_target(struct srp_hos sprintf(target->target_name, "SRP.T10:%016llX", (unsigned long long) be64_to_cpu(target->id_ext)); - if (scsi_add_host(target->scsi_host, host->dev->dma_device)) + if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device)) return -ENODEV; - mutex_lock(&host->target_mutex); + spin_lock(&host->target_lock); list_add_tail(&target->list, &host->target_list); - mutex_unlock(&host->target_mutex); + spin_unlock(&host->target_lock); target->state = SRP_TARGET_LIVE; - /* XXX: are we supposed to have a definition of SCAN_WILD_CARD ?? */ scsi_scan_target(&target->scsi_host->shost_gendev, - 0, target->scsi_id, ~0, 0); + 0, target->scsi_id, SCAN_WILD_CARD, 0); return 0; } @@ -1410,6 +1526,8 @@ enum { SRP_OPT_PKEY = 1 << 3, SRP_OPT_SERVICE_ID = 1 << 4, SRP_OPT_MAX_SECT = 1 << 5, + SRP_OPT_MAX_CMD_PER_LUN = 1 << 6, + SRP_OPT_IO_CLASS = 1 << 7, SRP_OPT_ALL = (SRP_OPT_ID_EXT | SRP_OPT_IOC_GUID | SRP_OPT_DGID | @@ -1418,13 +1536,15 @@ enum { }; static match_table_t srp_opt_tokens = { - { SRP_OPT_ID_EXT, "id_ext=%s" }, - { SRP_OPT_IOC_GUID, "ioc_guid=%s" }, - { SRP_OPT_DGID, "dgid=%s" }, - { SRP_OPT_PKEY, "pkey=%x" }, - { SRP_OPT_SERVICE_ID, "service_id=%s" }, - { SRP_OPT_MAX_SECT, "max_sect=%d" }, - { SRP_OPT_ERR, NULL } + { SRP_OPT_ID_EXT, "id_ext=%s" }, + { SRP_OPT_IOC_GUID, "ioc_guid=%s" }, + { SRP_OPT_DGID, "dgid=%s" }, + { SRP_OPT_PKEY, "pkey=%x" }, + { SRP_OPT_SERVICE_ID, "service_id=%s" }, + { SRP_OPT_MAX_SECT, "max_sect=%d" }, + { SRP_OPT_MAX_CMD_PER_LUN, "max_cmd_per_lun=%d" }, + { SRP_OPT_IO_CLASS, "io_class=%x" }, + { SRP_OPT_ERR, NULL } }; static int srp_parse_options(const char *buf, struct srp_target_port *target) @@ -1500,6 +1620,29 @@ static int srp_parse_options(const char target->scsi_host->max_sectors = token; break; + case SRP_OPT_MAX_CMD_PER_LUN: + if (match_int(args, &token)) { + printk(KERN_WARNING PFX "bad max cmd_per_lun parameter '%s'\n", p); + goto out; + } + target->scsi_host->cmd_per_lun = min(token, SRP_SQ_SIZE); + break; + + case SRP_OPT_IO_CLASS: + if (match_hex(args, &token)) { + printk(KERN_WARNING PFX "bad IO class parameter '%s' \n", p); + goto out; + } + if (token != SRP_REV10_IB_IO_CLASS && + token != SRP_REV16A_IB_IO_CLASS) { + printk(KERN_WARNING PFX "unknown IO class parameter value" + " %x specified (use %x or %x).\n", + token, SRP_REV10_IB_IO_CLASS, SRP_REV16A_IB_IO_CLASS); + goto out; + } + target->io_class = token; + break; + default: printk(KERN_WARNING PFX "unknown parameter or missing value " "'%s' in target creation request\n", p); @@ -1542,6 +1685,7 @@ static ssize_t srp_create_target(struct target = host_to_target(target_host); memset(target, 0, sizeof *target); + target->io_class = SRP_REV16A_IB_IO_CLASS; target->scsi_host = target_host; target->srp_host = host; @@ -1558,7 +1702,7 @@ static ssize_t srp_create_target(struct if (ret) goto err; - ib_get_cached_gid(host->dev, host->port, 0, &target->path.sgid); + ib_get_cached_gid(host->dev->dev, host->port, 0, &target->path.sgid); printk(KERN_DEBUG PFX "new target: id_ext %016llx ioc_guid %016llx pkey %04x " "service_id %016llx dgid %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", @@ -1579,7 +1723,7 @@ static ssize_t srp_create_target(struct if (ret) goto err; - target->cm_id = ib_create_cm_id(host->dev, srp_cm_handler, target); + target->cm_id = ib_create_cm_id(host->dev->dev, srp_cm_handler, target); if (IS_ERR(target->cm_id)) { ret = PTR_ERR(target->cm_id); goto err_free; @@ -1619,7 +1763,7 @@ static ssize_t show_ibdev(struct class_d struct srp_host *host = container_of(class_dev, struct srp_host, class_dev); - return sprintf(buf, "%s\n", host->dev->name); + return sprintf(buf, "%s\n", host->dev->dev->name); } static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); @@ -1634,7 +1778,7 @@ static ssize_t show_port(struct class_de static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); -static struct srp_host *srp_add_port(struct ib_device *device, u8 port) +static struct srp_host *srp_add_port(struct srp_device *device, u8 port) { struct srp_host *host; @@ -1643,32 +1787,21 @@ static struct srp_host *srp_add_port(str return NULL; INIT_LIST_HEAD(&host->target_list); - mutex_init(&host->target_mutex); + spin_lock_init(&host->target_lock); init_completion(&host->released); host->dev = device; host->port = port; host->initiator_port_id[7] = port; - memcpy(host->initiator_port_id + 8, &device->node_guid, 8); - - host->pd = ib_alloc_pd(device); - if (IS_ERR(host->pd)) - goto err_free; - - host->mr = ib_get_dma_mr(host->pd, - IB_ACCESS_LOCAL_WRITE | - IB_ACCESS_REMOTE_READ | - IB_ACCESS_REMOTE_WRITE); - if (IS_ERR(host->mr)) - goto err_pd; + memcpy(host->initiator_port_id + 8, &device->dev->node_guid, 8); host->class_dev.class = &srp_class; - host->class_dev.dev = device->dma_device; + host->class_dev.dev = device->dev->dma_device; snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d", - device->name, port); + device->dev->name, port); if (class_device_register(&host->class_dev)) - goto err_mr; + goto free_host; if (class_device_create_file(&host->class_dev, &class_device_attr_add_target)) goto err_class; if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev)) @@ -1681,13 +1814,7 @@ static struct srp_host *srp_add_port(str err_class: class_device_unregister(&host->class_dev); -err_mr: - ib_dereg_mr(host->mr); - -err_pd: - ib_dealloc_pd(host->pd); - -err_free: +free_host: kfree(host); return NULL; @@ -1695,15 +1822,62 @@ err_free: static void srp_add_one(struct ib_device *device) { - struct list_head *dev_list; + struct srp_device *srp_dev; + struct ib_device_attr *dev_attr; + struct ib_fmr_pool_param fmr_param; struct srp_host *host; int s, e, p; - dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); - if (!dev_list) + dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); + if (!dev_attr) return; - INIT_LIST_HEAD(dev_list); + if (ib_query_device(device, dev_attr)) { + printk(KERN_WARNING PFX "Query device failed for %s\n", + device->name); + goto free_attr; + } + + srp_dev = kmalloc(sizeof *srp_dev, GFP_KERNEL); + if (!srp_dev) + goto free_attr; + + /* + * Use the smallest page size supported by the HCA, down to a + * minimum of 512 bytes (which is the smallest sector that a + * SCSI command will ever carry). + */ + srp_dev->fmr_page_shift = max(9, ffs(dev_attr->page_size_cap) - 1); + srp_dev->fmr_page_size = 1 << srp_dev->fmr_page_shift; + srp_dev->fmr_page_mask = ~((unsigned long) srp_dev->fmr_page_size - 1); + + INIT_LIST_HEAD(&srp_dev->dev_list); + + srp_dev->dev = device; + srp_dev->pd = ib_alloc_pd(device); + if (IS_ERR(srp_dev->pd)) + goto free_dev; + + srp_dev->mr = ib_get_dma_mr(srp_dev->pd, + IB_ACCESS_LOCAL_WRITE | + IB_ACCESS_REMOTE_READ | + IB_ACCESS_REMOTE_WRITE); + if (IS_ERR(srp_dev->mr)) + goto err_pd; + + memset(&fmr_param, 0, sizeof fmr_param); + fmr_param.pool_size = SRP_FMR_POOL_SIZE; + fmr_param.dirty_watermark = SRP_FMR_DIRTY_SIZE; + fmr_param.cache = 1; + fmr_param.max_pages_per_fmr = SRP_FMR_SIZE; + fmr_param.page_shift = srp_dev->fmr_page_shift; + fmr_param.access = (IB_ACCESS_LOCAL_WRITE | + IB_ACCESS_REMOTE_WRITE | + IB_ACCESS_REMOTE_READ); + + srp_dev->fmr_pool = ib_create_fmr_pool(srp_dev->pd, &fmr_param); + if (IS_ERR(srp_dev->fmr_pool)) + srp_dev->fmr_pool = NULL; if (device->node_type == IB_NODE_SWITCH) { s = 0; @@ -1714,25 +1888,35 @@ static void srp_add_one(struct ib_device } for (p = s; p <= e; ++p) { - host = srp_add_port(device, p); + host = srp_add_port(srp_dev, p); if (host) - list_add_tail(&host->list, dev_list); + list_add_tail(&host->list, &srp_dev->dev_list); } - ib_set_client_data(device, &srp_client, dev_list); + ib_set_client_data(device, &srp_client, srp_dev); + + goto free_attr; + +err_pd: + ib_dealloc_pd(srp_dev->pd); + +free_dev: + kfree(srp_dev); + +free_attr: + kfree(dev_attr); } static void srp_remove_one(struct ib_device *device) { - struct list_head *dev_list; + struct srp_device *srp_dev; struct srp_host *host, *tmp_host; LIST_HEAD(target_list); struct srp_target_port *target, *tmp_target; - unsigned long flags; - dev_list = ib_get_client_data(device, &srp_client); + srp_dev = ib_get_client_data(device, &srp_client); - list_for_each_entry_safe(host, tmp_host, dev_list, list) { + list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) { class_device_unregister(&host->class_dev); /* * Wait for the sysfs entry to go away, so that no new @@ -1744,15 +1928,13 @@ static void srp_remove_one(struct ib_dev * Mark all target ports as removed, so we stop queueing * commands and don't try to reconnect. */ - mutex_lock(&host->target_mutex); - list_for_each_entry_safe(target, tmp_target, - &host->target_list, list) { - spin_lock_irqsave(target->scsi_host->host_lock, flags); - if (target->state != SRP_TARGET_REMOVED) - target->state = SRP_TARGET_REMOVED; - spin_unlock_irqrestore(target->scsi_host->host_lock, flags); + spin_lock(&host->target_lock); + list_for_each_entry(target, &host->target_list, list) { + spin_lock_irq(target->scsi_host->host_lock); + target->state = SRP_TARGET_REMOVED; + spin_unlock_irq(target->scsi_host->host_lock); } - mutex_unlock(&host->target_mutex); + spin_unlock(&host->target_lock); /* * Wait for any reconnection tasks that may have @@ -1770,18 +1952,26 @@ static void srp_remove_one(struct ib_dev scsi_host_put(target->scsi_host); } - ib_dereg_mr(host->mr); - ib_dealloc_pd(host->pd); kfree(host); } - kfree(dev_list); + if (srp_dev->fmr_pool) + ib_destroy_fmr_pool(srp_dev->fmr_pool); + ib_dereg_mr(srp_dev->mr); + ib_dealloc_pd(srp_dev->pd); + + kfree(srp_dev); } static int __init srp_init_module(void) { int ret; + srp_template.sg_tablesize = srp_sg_tablesize; + srp_max_iu_len = (sizeof (struct srp_cmd) + + sizeof (struct srp_indirect_buf) + + srp_sg_tablesize * 16); + ret = class_register(&srp_class); if (ret) { printk(KERN_ERR PFX "couldn't register class infiniband_srp\n"); diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index c5cd43a..5b581fb 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -46,6 +46,7 @@ #include #include #include #include +#include enum { SRP_PATH_REC_TIMEOUT_MS = 1000, @@ -55,20 +56,21 @@ enum { SRP_DLID_REDIRECT = 2, SRP_MAX_LUN = 512, - SRP_MAX_IU_LEN = 256, + SRP_DEF_SG_TABLESIZE = 12, SRP_RQ_SHIFT = 6, SRP_RQ_SIZE = 1 << SRP_RQ_SHIFT, SRP_SQ_SIZE = SRP_RQ_SIZE - 1, SRP_CQ_SIZE = SRP_SQ_SIZE + SRP_RQ_SIZE, - SRP_TAG_TSK_MGMT = 1 << (SRP_RQ_SHIFT + 1) + SRP_TAG_TSK_MGMT = 1 << (SRP_RQ_SHIFT + 1), + + SRP_FMR_SIZE = 256, + SRP_FMR_POOL_SIZE = 1024, + SRP_FMR_DIRTY_SIZE = SRP_FMR_POOL_SIZE / 4 }; #define SRP_OP_RECV (1 << 31) -#define SRP_MAX_INDIRECT ((SRP_MAX_IU_LEN - \ - sizeof (struct srp_cmd) - \ - sizeof (struct srp_indirect_buf)) / 16) enum srp_target_state { SRP_TARGET_LIVE, @@ -77,15 +79,24 @@ enum srp_target_state { SRP_TARGET_REMOVED }; -struct srp_host { - u8 initiator_port_id[16]; +struct srp_device { + struct list_head dev_list; struct ib_device *dev; - u8 port; struct ib_pd *pd; struct ib_mr *mr; + struct ib_fmr_pool *fmr_pool; + int fmr_page_shift; + int fmr_page_size; + unsigned long fmr_page_mask; +}; + +struct srp_host { + u8 initiator_port_id[16]; + struct srp_device *dev; + u8 port; struct class_device class_dev; struct list_head target_list; - struct mutex target_mutex; + spinlock_t target_lock; struct completion released; struct list_head list; }; @@ -95,6 +106,7 @@ struct srp_request { struct scsi_cmnd *scmnd; struct srp_iu *cmd; struct srp_iu *tsk_mgmt; + struct ib_pool_fmr *fmr; /* * Fake scatterlist used when scmnd->use_sg==0. Can be killed * when the SCSI midlayer no longer generates non-SG commands. @@ -110,6 +122,7 @@ struct srp_target_port { __be64 id_ext; __be64 ioc_guid; __be64 service_id; + u16 io_class; struct srp_host *srp_host; struct Scsi_Host *scsi_host; char target_name[32]; @@ -126,6 +139,8 @@ struct srp_target_port { int max_ti_iu_len; s32 req_lim; + int zero_req_lim; + unsigned rx_head; struct srp_iu *rx_ring[SRP_RQ_SIZE]; diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index ba325f1..a29d5ce 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -78,14 +78,19 @@ static int evdev_fasync(int fd, struct f { int retval; struct evdev_list *list = file->private_data; + retval = fasync_helper(fd, file, on, &list->fasync); + return retval < 0 ? retval : 0; } -static int evdev_flush(struct file * file) +static int evdev_flush(struct file *file, fl_owner_t id) { struct evdev_list *list = file->private_data; - if (!list->evdev->exist) return -ENODEV; + + if (!list->evdev->exist) + return -ENODEV; + return input_flush_device(&list->evdev->handle, file); } @@ -300,6 +305,7 @@ static ssize_t evdev_read(struct file * static unsigned int evdev_poll(struct file *file, poll_table *wait) { struct evdev_list *list = file->private_data; + poll_wait(file, &list->evdev->wait, wait); return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) | (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); diff --git a/drivers/input/input.c b/drivers/input/input.c index 3038c26..de2e754 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -28,20 +28,6 @@ MODULE_AUTHOR("Vojtech Pavlik event) dev->event(dev, type, code, value); + if (dev->event) + dev->event(dev, type, code, value); break; case SYN_REPORT: - if (dev->sync) return; + if (dev->sync) + return; dev->sync = 1; break; } @@ -136,7 +124,8 @@ void input_event(struct input_dev *dev, if (code > MSC_MAX || !test_bit(code, dev->mscbit)) return; - if (dev->event) dev->event(dev, type, code, value); + if (dev->event) + dev->event(dev, type, code, value); break; @@ -146,7 +135,9 @@ void input_event(struct input_dev *dev, return; change_bit(code, dev->led); - if (dev->event) dev->event(dev, type, code, value); + + if (dev->event) + dev->event(dev, type, code, value); break; @@ -158,21 +149,25 @@ void input_event(struct input_dev *dev, if (!!test_bit(code, dev->snd) != !!value) change_bit(code, dev->snd); - if (dev->event) dev->event(dev, type, code, value); + if (dev->event) + dev->event(dev, type, code, value); break; case EV_REP: - if (code > REP_MAX || value < 0 || dev->rep[code] == value) return; + if (code > REP_MAX || value < 0 || dev->rep[code] == value) + return; dev->rep[code] = value; - if (dev->event) dev->event(dev, type, code, value); + if (dev->event) + dev->event(dev, type, code, value); break; case EV_FF: - if (dev->event) dev->event(dev, type, code, value); + if (dev->event) + dev->event(dev, type, code, value); break; } @@ -186,6 +181,7 @@ void input_event(struct input_dev *dev, if (handle->open) handle->handler->event(handle, type, code, value); } +EXPORT_SYMBOL(input_event); static void input_repeat_key(unsigned long data) { @@ -208,6 +204,7 @@ int input_accept_process(struct input_ha return 0; } +EXPORT_SYMBOL(input_accept_process); int input_grab_device(struct input_handle *handle) { @@ -217,12 +214,14 @@ int input_grab_device(struct input_handl handle->dev->grab = handle; return 0; } +EXPORT_SYMBOL(input_grab_device); void input_release_device(struct input_handle *handle) { if (handle->dev->grab == handle) handle->dev->grab = NULL; } +EXPORT_SYMBOL(input_release_device); int input_open_device(struct input_handle *handle) { @@ -245,6 +244,7 @@ int input_open_device(struct input_handl return err; } +EXPORT_SYMBOL(input_open_device); int input_flush_device(struct input_handle* handle, struct file* file) { @@ -253,6 +253,7 @@ int input_flush_device(struct input_hand return 0; } +EXPORT_SYMBOL(input_flush_device); void input_close_device(struct input_handle *handle) { @@ -268,6 +269,7 @@ void input_close_device(struct input_han mutex_unlock(&dev->mutex); } +EXPORT_SYMBOL(input_close_device); static void input_link_handle(struct input_handle *handle) { @@ -335,9 +337,11 @@ static inline void input_wakeup_procfs_r static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait) { int state = input_devices_state; + poll_wait(file, &input_devices_poll_wait, wait); if (state != input_devices_state) return POLLIN | POLLRDNORM; + return 0; } @@ -629,7 +633,7 @@ static ssize_t input_dev_show_modalias(s len = input_print_modalias(buf, PAGE_SIZE, id, 1); - return max_t(int, len, PAGE_SIZE); + return min_t(int, len, PAGE_SIZE); } static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); @@ -862,6 +866,7 @@ struct class input_class = { .release = input_dev_release, .uevent = input_dev_uevent, }; +EXPORT_SYMBOL_GPL(input_class); struct input_dev *input_allocate_device(void) { @@ -872,12 +877,27 @@ struct input_dev *input_allocate_device( dev->dynalloc = 1; dev->cdev.class = &input_class; class_device_initialize(&dev->cdev); + mutex_init(&dev->mutex); INIT_LIST_HEAD(&dev->h_list); INIT_LIST_HEAD(&dev->node); } return dev; } +EXPORT_SYMBOL(input_allocate_device); + +void input_free_device(struct input_dev *dev) +{ + if (dev) { + + mutex_lock(&dev->mutex); + dev->name = dev->phys = dev->uniq = NULL; + mutex_unlock(&dev->mutex); + + input_put_device(dev); + } +} +EXPORT_SYMBOL(input_free_device); int input_register_device(struct input_dev *dev) { @@ -895,7 +915,6 @@ int input_register_device(struct input_d return -EINVAL; } - mutex_init(&dev->mutex); set_bit(EV_SYN, dev->evbit); /* @@ -956,12 +975,14 @@ int input_register_device(struct input_d fail1: class_device_del(&dev->cdev); return error; } +EXPORT_SYMBOL(input_register_device); void input_unregister_device(struct input_dev *dev) { - struct list_head * node, * next; + struct list_head *node, *next; - if (!dev) return; + if (!dev) + return; del_timer_sync(&dev->timer); @@ -979,8 +1000,13 @@ void input_unregister_device(struct inpu sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group); class_device_unregister(&dev->cdev); + mutex_lock(&dev->mutex); + dev->name = dev->phys = dev->uniq = NULL; + mutex_unlock(&dev->mutex); + input_wakeup_procfs_readers(); } +EXPORT_SYMBOL(input_unregister_device); void input_register_handler(struct input_handler *handler) { @@ -988,7 +1014,8 @@ void input_register_handler(struct input struct input_handle *handle; struct input_device_id *id; - if (!handler) return; + if (!handler) + return; INIT_LIST_HEAD(&handler->h_list); @@ -1005,10 +1032,11 @@ void input_register_handler(struct input input_wakeup_procfs_readers(); } +EXPORT_SYMBOL(input_register_handler); void input_unregister_handler(struct input_handler *handler) { - struct list_head * node, * next; + struct list_head *node, *next; list_for_each_safe(node, next, &handler->h_list) { struct input_handle * handle = to_handle_h(node); @@ -1024,6 +1052,7 @@ void input_unregister_handler(struct inp input_wakeup_procfs_readers(); } +EXPORT_SYMBOL(input_unregister_handler); static int input_open_file(struct inode *inode, struct file *file) { diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 949bdce..d671575 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -81,10 +81,7 @@ static int joydev_correct(int value, str return 0; } - if (value < -32767) return -32767; - if (value > 32767) return 32767; - - return value; + return value < -32767 ? -32767 : (value > 32767 ? 32767 : value); } static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) @@ -96,7 +93,8 @@ static void joydev_event(struct input_ha switch (type) { case EV_KEY: - if (code < BTN_MISC || value == 2) return; + if (code < BTN_MISC || value == 2) + return; event.type = JS_EVENT_BUTTON; event.number = joydev->keymap[code - BTN_MISC]; event.value = value; @@ -106,7 +104,8 @@ static void joydev_event(struct input_ha event.type = JS_EVENT_AXIS; event.number = joydev->absmap[code]; event.value = joydev_correct(value, joydev->corr + event.number); - if (event.value == joydev->abs[event.number]) return; + if (event.value == joydev->abs[event.number]) + return; joydev->abs[event.number] = event.value; break; @@ -134,7 +133,9 @@ static int joydev_fasync(int fd, struct { int retval; struct joydev_list *list = file->private_data; + retval = fasync_helper(fd, file, on, &list->fasync); + return retval < 0 ? retval : 0; } @@ -222,12 +223,12 @@ static ssize_t joydev_read(struct file * return sizeof(struct JS_DATA_TYPE); } - if (list->startup == joydev->nabs + joydev->nkey - && list->head == list->tail && (file->f_flags & O_NONBLOCK)) - return -EAGAIN; + if (list->startup == joydev->nabs + joydev->nkey && + list->head == list->tail && (file->f_flags & O_NONBLOCK)) + return -EAGAIN; retval = wait_event_interruptible(list->joydev->wait, - !list->joydev->exist || + !list->joydev->exist || list->startup < joydev->nabs + joydev->nkey || list->head != list->tail); @@ -276,8 +277,9 @@ static ssize_t joydev_read(struct file * static unsigned int joydev_poll(struct file *file, poll_table *wait) { struct joydev_list *list = file->private_data; + poll_wait(file, &list->joydev->wait, wait); - return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ? + return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ? (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); } @@ -291,20 +293,26 @@ static int joydev_ioctl_common(struct jo case JS_SET_CAL: return copy_from_user(&joydev->glue.JS_CORR, argp, sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; + case JS_GET_CAL: return copy_to_user(argp, &joydev->glue.JS_CORR, sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; + case JS_SET_TIMEOUT: return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); + case JS_GET_TIMEOUT: return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); case JSIOCGVERSION: return put_user(JS_VERSION, (__u32 __user *) argp); + case JSIOCGAXES: return put_user(joydev->nabs, (__u8 __user *) argp); + case JSIOCGBUTTONS: return put_user(joydev->nkey, (__u8 __user *) argp); + case JSIOCSCORR: if (copy_from_user(joydev->corr, argp, sizeof(joydev->corr[0]) * joydev->nabs)) @@ -314,38 +322,49 @@ static int joydev_ioctl_common(struct jo joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); } return 0; + case JSIOCGCORR: return copy_to_user(argp, joydev->corr, sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; + case JSIOCSAXMAP: if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) return -EFAULT; for (i = 0; i < joydev->nabs; i++) { - if (joydev->abspam[i] > ABS_MAX) return -EINVAL; + if (joydev->abspam[i] > ABS_MAX) + return -EINVAL; joydev->absmap[joydev->abspam[i]] = i; } return 0; + case JSIOCGAXMAP: return copy_to_user(argp, joydev->abspam, sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; + case JSIOCSBTNMAP: if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) return -EFAULT; for (i = 0; i < joydev->nkey; i++) { - if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL; + if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) + return -EINVAL; joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; } return 0; + case JSIOCGBTNMAP: return copy_to_user(argp, joydev->keypam, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; + default: if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) { int len; - if (!dev->name) return 0; + if (!dev->name) + return 0; len = strlen(dev->name) + 1; - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - if (copy_to_user(argp, dev->name, len)) return -EFAULT; + if (len > _IOC_SIZE(cmd)) + len = _IOC_SIZE(cmd); + if (copy_to_user(argp, dev->name, len)) + return -EFAULT; return len; } } @@ -362,7 +381,9 @@ static long joydev_compat_ioctl(struct f struct JS_DATA_SAVE_TYPE_32 ds32; int err; - if (!joydev->exist) return -ENODEV; + if (!joydev->exist) + return -ENODEV; + switch(cmd) { case JS_SET_TIMELIMIT: err = get_user(tmp32, (s32 __user *) arg); @@ -395,8 +416,7 @@ static long joydev_compat_ioctl(struct f ds32.JS_SAVE = joydev->glue.JS_SAVE; ds32.JS_CORR = joydev->glue.JS_CORR; - err = copy_to_user(argp, &ds32, - sizeof(ds32)) ? -EFAULT : 0; + err = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0; break; default: @@ -412,7 +432,8 @@ static int joydev_ioctl(struct inode *in struct joydev *joydev = list->joydev; void __user *argp = (void __user *)arg; - if (!joydev->exist) return -ENODEV; + if (!joydev->exist) + return -ENODEV; switch(cmd) { case JS_SET_TIMELIMIT: @@ -546,8 +567,8 @@ static struct input_device_id joydev_bla .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, .evbit = { BIT(EV_KEY) }, .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, - }, /* Avoid itouchpads, touchscreens and tablets */ - { }, /* Terminating entry */ + }, /* Avoid itouchpads, touchscreens and tablets */ + { } /* Terminating entry */ }; static struct input_device_id joydev_ids[] = { @@ -566,7 +587,7 @@ static struct input_device_id joydev_ids .evbit = { BIT(EV_ABS) }, .absbit = { BIT(ABS_THROTTLE) }, }, - { }, /* Terminating entry */ + { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(input, joydev_ids); @@ -579,7 +600,7 @@ static struct input_handler joydev_handl .minor = JOYDEV_MINOR_BASE, .name = "joydev", .id_table = joydev_ids, - .blacklist = joydev_blacklist, + .blacklist = joydev_blacklist, }; static int __init joydev_init(void) diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index 4612d13..b11a4bb 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c @@ -306,7 +306,7 @@ static int a3d_connect(struct gameport * gameport_set_poll_handler(gameport, a3d_poll); gameport_set_poll_interval(gameport, 20); - sprintf(a3d->phys, "%s/input0", gameport->phys); + snprintf(a3d->phys, sizeof(a3d->phys), "%s/input0", gameport->phys); input_dev->name = a3d_names[a3d->mode]; input_dev->phys = a3d->phys; diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 3121961..01dc0b1 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -408,21 +408,23 @@ #endif static void analog_name(struct analog *analog) { - sprintf(analog->name, "Analog %d-axis %d-button", - hweight8(analog->mask & ANALOG_AXES_STD), - hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 + - hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4); + snprintf(analog->name, sizeof(analog->name), "Analog %d-axis %d-button", + hweight8(analog->mask & ANALOG_AXES_STD), + hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 + + hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4); if (analog->mask & ANALOG_HATS_ALL) - sprintf(analog->name, "%s %d-hat", - analog->name, hweight16(analog->mask & ANALOG_HATS_ALL)); + snprintf(analog->name, sizeof(analog->name), "%s %d-hat", + analog->name, hweight16(analog->mask & ANALOG_HATS_ALL)); if (analog->mask & ANALOG_HAT_FCS) - strcat(analog->name, " FCS"); + strlcat(analog->name, " FCS", sizeof(analog->name)); if (analog->mask & ANALOG_ANY_CHF) - strcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF"); + strlcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF", + sizeof(analog->name)); - strcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick"); + strlcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick", + sizeof(analog->name)); } /* @@ -435,7 +437,8 @@ static int analog_init_device(struct ana int i, j, t, v, w, x, y, z; analog_name(analog); - sprintf(analog->phys, "%s/input%d", port->gameport->phys, index); + snprintf(analog->phys, sizeof(analog->phys), + "%s/input%d", port->gameport->phys, index); analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn; analog->dev = input_dev = input_allocate_device(); diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index 1909f7e..d5e42eb 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c @@ -202,7 +202,8 @@ static int cobra_connect(struct gameport goto fail3; } - sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i); + snprintf(cobra->phys[i], sizeof(cobra->phys[i]), + "%s/input%d", gameport->phys, i); input_dev->name = "Creative Labs Blaster GamePad Cobra"; input_dev->phys = cobra->phys[i]; diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index e618946..6f31f05 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -620,7 +620,8 @@ static struct db9 __init *db9_probe(int goto err_unreg_devs; } - sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i); + snprintf(db9->phys[i], sizeof(db9->phys[i]), + "%s/input%d", db9->pd->port->name, i); input_dev->name = db9_mode->name; input_dev->phys = db9->phys[i]; diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index ecbdb6b..fe12aa3 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -761,7 +761,8 @@ static struct gc __init *gc_probe(int pa if (!pads[i]) continue; - sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i); + snprintf(gc->phys[i], sizeof(gc->phys[i]), + "%s/input%d", gc->pd->port->name, i); err = gc_setup_pad(gc, i, pads[i]); if (err) goto err_unreg_devs; diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index 8a3ad45..e4a699f 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c @@ -298,7 +298,7 @@ #endif gameport_set_poll_handler(gameport, gf2k_poll); gameport_set_poll_interval(gameport, 20); - sprintf(gf2k->phys, "%s/input0", gameport->phys); + snprintf(gf2k->phys, sizeof(gf2k->phys), "%s/input0", gameport->phys); gf2k->length = gf2k_lens[gf2k->id]; diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index 20cb98a..17a90c4 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c @@ -354,7 +354,8 @@ static int grip_connect(struct gameport goto fail3; } - sprintf(grip->phys[i], "%s/input%d", gameport->phys, i); + snprintf(grip->phys[i], sizeof(grip->phys[i]), + "%s/input%d", gameport->phys, i); input_dev->name = grip_name[grip->mode[i]]; input_dev->phys = grip->phys[i]; diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index 6e2c721..840ed9b 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c @@ -222,7 +222,7 @@ static int guillemot_connect(struct game gameport_set_poll_handler(gameport, guillemot_poll); gameport_set_poll_interval(gameport, 20); - sprintf(guillemot->phys, "%s/input0", gameport->phys); + snprintf(guillemot->phys, sizeof(guillemot->phys), "%s/input0", gameport->phys); guillemot->type = guillemot_type + i; input_dev->name = guillemot_type[i].name; diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c index 2b8e845..50c9076 100644 --- a/drivers/input/joystick/iforce/iforce-ff.c +++ b/drivers/input/joystick/iforce/iforce-ff.c @@ -47,7 +47,7 @@ static int make_magnitude_modifier(struc iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { mutex_unlock(&iforce->mem_mutex); - return -ENOMEM; + return -ENOSPC; } mutex_unlock(&iforce->mem_mutex); } @@ -80,7 +80,7 @@ static int make_period_modifier(struct i iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { mutex_unlock(&iforce->mem_mutex); - return -ENOMEM; + return -ENOSPC; } mutex_unlock(&iforce->mem_mutex); } @@ -120,7 +120,7 @@ static int make_envelope_modifier(struct iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { mutex_unlock(&iforce->mem_mutex); - return -ENOMEM; + return -ENOSPC; } mutex_unlock(&iforce->mem_mutex); } @@ -157,7 +157,7 @@ static int make_condition_modifier(struc iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { mutex_unlock(&iforce->mem_mutex); - return -ENOMEM; + return -ENOSPC; } mutex_unlock(&iforce->mem_mutex); } diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index ab0a26b..6d99e3c 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -86,7 +86,7 @@ static struct iforce_device iforce_devic static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - struct iforce* iforce = (struct iforce*)(dev->private); + struct iforce* iforce = dev->private; unsigned char data[3]; if (type != EV_FF) @@ -138,7 +138,7 @@ static int iforce_input_event(struct inp */ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect) { - struct iforce* iforce = (struct iforce*)(dev->private); + struct iforce* iforce = dev->private; int id; int ret; int is_update; @@ -218,7 +218,7 @@ static int iforce_upload_effect(struct i */ static int iforce_erase_effect(struct input_dev *dev, int effect_id) { - struct iforce* iforce = (struct iforce*)(dev->private); + struct iforce* iforce = dev->private; int err = 0; struct iforce_core_effect* core_effect; diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index c4ed017..bbfeb9c 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c @@ -251,7 +251,7 @@ static int interact_connect(struct gamep gameport_set_poll_handler(gameport, interact_poll); gameport_set_poll_interval(gameport, 20); - sprintf(interact->phys, "%s/input0", gameport->phys); + snprintf(interact->phys, sizeof(interact->phys), "%s/input0", gameport->phys); interact->type = i; interact->length = interact_type[i].length; diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c index ca3cc23..168b106 100644 --- a/drivers/input/joystick/magellan.c +++ b/drivers/input/joystick/magellan.c @@ -162,7 +162,7 @@ static int magellan_connect(struct serio goto fail; magellan->dev = input_dev; - sprintf(magellan->phys, "%s/input0", serio->phys); + snprintf(magellan->phys, sizeof(magellan->phys), "%s/input0", serio->phys); input_dev->name = "LogiCad3D Magellan / SpaceMouse"; input_dev->phys = magellan->phys; diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 95c0de7..e58b22c 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -541,7 +541,7 @@ static void sw_print_packet(char *name, * Unfortunately I don't know how to do this for the other SW types. */ -static void sw_3dp_id(unsigned char *buf, char *comment) +static void sw_3dp_id(unsigned char *buf, char *comment, size_t size) { int i; char pnp[8], rev[9]; @@ -554,7 +554,7 @@ static void sw_3dp_id(unsigned char *buf pnp[7] = rev[8] = 0; - sprintf(comment, " [PnP %d.%02d id %s rev %s]", + snprintf(comment, size, " [PnP %d.%02d id %s rev %s]", (int) ((sw_get_bits(buf, 8, 6, 1) << 6) | /* Two 6-bit values */ sw_get_bits(buf, 16, 6, 1)) / 100, (int) ((sw_get_bits(buf, 8, 6, 1) << 6) | @@ -695,7 +695,7 @@ static int sw_connect(struct gameport *g sw->type = SW_ID_FFP; sprintf(comment, " [AC %s]", sw_get_bits(idbuf,38,1,3) ? "off" : "on"); } else - sw->type = SW_ID_PP; + sw->type = SW_ID_PP; break; case 66: sw->bits = 3; @@ -703,7 +703,8 @@ static int sw_connect(struct gameport *g sw->length = 22; case 64: sw->type = SW_ID_3DP; - if (j == 160) sw_3dp_id(idbuf, comment); + if (j == 160) + sw_3dp_id(idbuf, comment, sizeof(comment)); break; } } @@ -733,8 +734,10 @@ #endif for (i = 0; i < sw->number; i++) { int bits, code; - sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]); - sprintf(sw->phys[i], "%s/input%d", gameport->phys, i); + snprintf(sw->name, sizeof(sw->name), + "Microsoft SideWinder %s", sw_name[sw->type]); + snprintf(sw->phys[i], sizeof(sw->phys[i]), + "%s/input%d", gameport->phys, i); sw->dev[i] = input_dev = input_allocate_device(); if (!input_dev) { diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index d6f8db8..75eb5ca 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -220,7 +220,7 @@ static int spaceball_connect(struct seri goto fail; spaceball->dev = input_dev; - sprintf(spaceball->phys, "%s/input0", serio->phys); + snprintf(spaceball->phys, sizeof(spaceball->phys), "%s/input0", serio->phys); input_dev->name = spaceball_names[id]; input_dev->phys = spaceball->phys; diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index 7c123a0..3e2782e 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c @@ -177,7 +177,7 @@ static int spaceorb_connect(struct serio goto fail; spaceorb->dev = input_dev; - sprintf(spaceorb->phys, "%s/input0", serio->phys); + snprintf(spaceorb->phys, sizeof(spaceorb->phys), "%s/input0", serio->phys); input_dev->name = "SpaceTec SpaceOrb 360 / Avenger"; input_dev->phys = spaceorb->phys; diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c index 0a9ed1d..011ec48 100644 --- a/drivers/input/joystick/stinger.c +++ b/drivers/input/joystick/stinger.c @@ -148,7 +148,7 @@ static int stinger_connect(struct serio goto fail; stinger->dev = input_dev; - sprintf(stinger->phys, "%s/serio0", serio->phys); + snprintf(stinger->phys, sizeof(stinger->phys), "%s/serio0", serio->phys); input_dev->name = "Gravis Stinger"; input_dev->phys = stinger->phys; diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c index 7f8b009..076f237 100644 --- a/drivers/input/joystick/twidjoy.c +++ b/drivers/input/joystick/twidjoy.c @@ -199,7 +199,7 @@ static int twidjoy_connect(struct serio goto fail; twidjoy->dev = input_dev; - sprintf(twidjoy->phys, "%s/input0", serio->phys); + snprintf(twidjoy->phys, sizeof(twidjoy->phys), "%s/input0", serio->phys); input_dev->name = "Handykey Twiddler"; input_dev->phys = twidjoy->phys; diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c index 1849b17..f9c1a03 100644 --- a/drivers/input/joystick/warrior.c +++ b/drivers/input/joystick/warrior.c @@ -154,7 +154,7 @@ static int warrior_connect(struct serio goto fail; warrior->dev = input_dev; - sprintf(warrior->phys, "%s/input0", serio->phys); + snprintf(warrior->phys, sizeof(warrior->phys), "%s/input0", serio->phys); input_dev->name = "Logitech WingMan Warrior"; input_dev->phys = warrior->phys; diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c index 4c8fb1f..f1f9db9 100644 --- a/drivers/input/keyboard/amikbd.c +++ b/drivers/input/keyboard/amikbd.c @@ -36,6 +36,7 @@ #include #include #include #include +#include #include #include @@ -45,7 +46,7 @@ MODULE_AUTHOR("Vojtech Pavlik >= 1; if (scancode < 0x78) { /* scancodes < 0x78 are keys */ - - scancode = amikbd_keycode[scancode]; - input_regs(amikbd_dev, fp); - if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */ + if (scancode == 98) { /* CapsLock is a toggle switch key on Amiga */ input_report_key(amikbd_dev, scancode, 1); input_report_key(amikbd_dev, scancode, 0); } else { @@ -191,7 +189,7 @@ static irqreturn_t amikbd_interrupt(int static int __init amikbd_init(void) { - int i; + int i, j; if (!AMIGAHW_PRESENT(AMI_KEYBOARD)) return -EIO; @@ -214,14 +212,26 @@ static int __init amikbd_init(void) amikbd_dev->id.version = 0x0100; amikbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - amikbd_dev->keycode = amikbd_keycode; - amikbd_dev->keycodesize = sizeof(unsigned char); - amikbd_dev->keycodemax = ARRAY_SIZE(amikbd_keycode); for (i = 0; i < 0x78; i++) - if (amikbd_keycode[i]) - set_bit(amikbd_keycode[i], amikbd_dev->keybit); - + set_bit(i, amikbd_dev->keybit); + + for (i = 0; i < MAX_NR_KEYMAPS; i++) { + static u_short temp_map[NR_KEYS] __initdata; + if (!key_maps[i]) + continue; + memset(temp_map, 0, sizeof(temp_map)); + for (j = 0; j < 0x78; j++) { + if (!amikbd_keycode[j]) + continue; + temp_map[j] = key_maps[i][amikbd_keycode[j]]; + } + for (j = 0; j < NR_KEYS; j++) { + if (!temp_map[j]) + temp_map[j] = 0xf200; + } + memcpy(key_maps[i], temp_map, sizeof(temp_map)); + } ciaa.cra &= ~0x41; /* serial data in, turn off TA */ request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt); diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index fad04b6..ffde8f8 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -55,7 +55,7 @@ static int atkbd_softraw = 1; module_param_named(softraw, atkbd_softraw, bool, 0); MODULE_PARM_DESC(softraw, "Use software generated rawmode"); -static int atkbd_scroll = 0; +static int atkbd_scroll; module_param_named(scroll, atkbd_scroll, bool, 0); MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards"); @@ -150,8 +150,8 @@ #define ATKBD_RET_BAT 0xaa #define ATKBD_RET_EMUL0 0xe0 #define ATKBD_RET_EMUL1 0xe1 #define ATKBD_RET_RELEASE 0xf0 -#define ATKBD_RET_HANGUEL 0xf1 -#define ATKBD_RET_HANJA 0xf2 +#define ATKBD_RET_HANJA 0xf1 +#define ATKBD_RET_HANGEUL 0xf2 #define ATKBD_RET_ERR 0xff #define ATKBD_KEY_UNKNOWN 0 @@ -170,6 +170,13 @@ #define ATKBD_SPECIAL 248 #define ATKBD_LED_EVENT_BIT 0 #define ATKBD_REP_EVENT_BIT 1 +#define ATKBD_XL_ERR 0x01 +#define ATKBD_XL_BAT 0x02 +#define ATKBD_XL_ACK 0x04 +#define ATKBD_XL_NAK 0x08 +#define ATKBD_XL_HANGEUL 0x10 +#define ATKBD_XL_HANJA 0x20 + static struct { unsigned char keycode; unsigned char set2; @@ -211,8 +218,7 @@ struct atkbd { unsigned char emul; unsigned char resend; unsigned char release; - unsigned char bat_xl; - unsigned char err_xl; + unsigned long xl_bit; unsigned int last; unsigned long time; @@ -245,17 +251,65 @@ ATKBD_DEFINE_ATTR(set); ATKBD_DEFINE_ATTR(softrepeat); ATKBD_DEFINE_ATTR(softraw); +static const unsigned int xl_table[] = { + ATKBD_RET_BAT, ATKBD_RET_ERR, ATKBD_RET_ACK, + ATKBD_RET_NAK, ATKBD_RET_HANJA, ATKBD_RET_HANGEUL, +}; -static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int code, int value) +/* + * Checks if we should mangle the scancode to extract 'release' bit + * in translated mode. + */ +static int atkbd_need_xlate(unsigned long xl_bit, unsigned char code) { - input_regs(dev, regs); - if (value == 3) { - input_report_key(dev, code, 1); - input_sync(dev); - input_report_key(dev, code, 0); - } else - input_event(dev, EV_KEY, code, value); - input_sync(dev); + int i; + + if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1) + return 0; + + for (i = 0; i < ARRAY_SIZE(xl_table); i++) + if (code == xl_table[i]) + return test_bit(i, &xl_bit); + + return 1; +} + +/* + * Calculates new value of xl_bit so the driver can distinguish + * between make/break pair of scancodes for select keys and PS/2 + * protocol responses. + */ +static void atkbd_calculate_xl_bit(struct atkbd *atkbd, unsigned char code) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(xl_table); i++) { + if (!((code ^ xl_table[i]) & 0x7f)) { + if (code & 0x80) + __clear_bit(i, &atkbd->xl_bit); + else + __set_bit(i, &atkbd->xl_bit); + break; + } + } +} + +/* + * Encode the scancode, 0xe0 prefix, and high bit into a single integer, + * keeping kernel 2.4 compatibility for set 2 + */ +static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code) +{ + if (atkbd->set == 3) { + if (atkbd->emul == 1) + code |= 0x100; + } else { + code = (code & 0x7f) | ((code & 0x80) << 1); + if (atkbd->emul == 1) + code |= 0x80; + } + + return code; } /* @@ -267,9 +321,11 @@ static irqreturn_t atkbd_interrupt(struc unsigned int flags, struct pt_regs *regs) { struct atkbd *atkbd = serio_get_drvdata(serio); + struct input_dev *dev = atkbd->dev; unsigned int code = data; - int scroll = 0, hscroll = 0, click = -1; + int scroll = 0, hscroll = 0, click = -1, add_release_event = 0; int value; + unsigned char keycode; #ifdef ATKBD_DEBUG printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags); @@ -298,25 +354,17 @@ #endif if (!atkbd->enabled) goto out; - input_event(atkbd->dev, EV_MSC, MSC_RAW, code); + input_event(dev, EV_MSC, MSC_RAW, code); if (atkbd->translated) { - if (atkbd->emul || - (code != ATKBD_RET_EMUL0 && code != ATKBD_RET_EMUL1 && - code != ATKBD_RET_HANGUEL && code != ATKBD_RET_HANJA && - (code != ATKBD_RET_ERR || atkbd->err_xl) && - (code != ATKBD_RET_BAT || atkbd->bat_xl))) { + if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) { atkbd->release = code >> 7; code &= 0x7f; } - if (!atkbd->emul) { - if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f)) - atkbd->bat_xl = !(data >> 7); - if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f)) - atkbd->err_xl = !(data >> 7); - } + if (!atkbd->emul) + atkbd_calculate_xl_bit(atkbd, data); } switch (code) { @@ -333,47 +381,48 @@ #endif case ATKBD_RET_RELEASE: atkbd->release = 1; goto out; - case ATKBD_RET_HANGUEL: - atkbd_report_key(atkbd->dev, regs, KEY_HANGUEL, 3); + case ATKBD_RET_ACK: + case ATKBD_RET_NAK: + printk(KERN_WARNING "atkbd.c: Spurious %s on %s. " + "Some program might be trying access hardware directly.\n", + data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); goto out; + case ATKBD_RET_HANGEUL: case ATKBD_RET_HANJA: - atkbd_report_key(atkbd->dev, regs, KEY_HANJA, 3); - goto out; + /* + * These keys do not report release and thus need to be + * flagged properly + */ + add_release_event = 1; + break; case ATKBD_RET_ERR: printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys); goto out; } - if (atkbd->set != 3) - code = (code & 0x7f) | ((code & 0x80) << 1); - if (atkbd->emul) { - if (--atkbd->emul) - goto out; - code |= (atkbd->set != 3) ? 0x80 : 0x100; - } + code = atkbd_compat_scancode(atkbd, code); + + if (atkbd->emul && --atkbd->emul) + goto out; - if (atkbd->keycode[code] != ATKBD_KEY_NULL) - input_event(atkbd->dev, EV_MSC, MSC_SCAN, code); + keycode = atkbd->keycode[code]; - switch (atkbd->keycode[code]) { + if (keycode != ATKBD_KEY_NULL) + input_event(dev, EV_MSC, MSC_SCAN, code); + + switch (keycode) { case ATKBD_KEY_NULL: break; case ATKBD_KEY_UNKNOWN: - if (data == ATKBD_RET_ACK || data == ATKBD_RET_NAK) { - printk(KERN_WARNING "atkbd.c: Spurious %s on %s. Some program, " - "like XFree86, might be trying access hardware directly.\n", - data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); - } else { - printk(KERN_WARNING "atkbd.c: Unknown key %s " - "(%s set %d, code %#x on %s).\n", - atkbd->release ? "released" : "pressed", - atkbd->translated ? "translated" : "raw", - atkbd->set, code, serio->phys); - printk(KERN_WARNING "atkbd.c: Use 'setkeycodes %s%02x ' " - "to make it known.\n", - code & 0x80 ? "e0" : "", code & 0x7f); - } - input_sync(atkbd->dev); + printk(KERN_WARNING + "atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n", + atkbd->release ? "released" : "pressed", + atkbd->translated ? "translated" : "raw", + atkbd->set, code, serio->phys); + printk(KERN_WARNING + "atkbd.c: Use 'setkeycodes %s%02x ' to make it known.\n", + code & 0x80 ? "e0" : "", code & 0x7f); + input_sync(dev); break; case ATKBD_SCR_1: scroll = 1 - atkbd->release * 2; @@ -397,33 +446,35 @@ #endif hscroll = 1; break; default: - value = atkbd->release ? 0 : - (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev->key))); - - switch (value) { /* Workaround Toshiba laptop multiple keypress */ - case 0: - atkbd->last = 0; - break; - case 1: - atkbd->last = code; - atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev->rep[REP_DELAY]) / 2; - break; - case 2: - if (!time_after(jiffies, atkbd->time) && atkbd->last == code) - value = 1; - break; + if (atkbd->release) { + value = 0; + atkbd->last = 0; + } else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) { + /* Workaround Toshiba laptop multiple keypress */ + value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2; + } else { + value = 1; + atkbd->last = code; + atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2; } - atkbd_report_key(atkbd->dev, regs, atkbd->keycode[code], value); + input_regs(dev, regs); + input_report_key(dev, keycode, value); + input_sync(dev); + + if (value && add_release_event) { + input_report_key(dev, keycode, 0); + input_sync(dev); + } } if (atkbd->scroll) { - input_regs(atkbd->dev, regs); + input_regs(dev, regs); if (click != -1) - input_report_key(atkbd->dev, BTN_MIDDLE, click); - input_report_rel(atkbd->dev, REL_WHEEL, scroll); - input_report_rel(atkbd->dev, REL_HWHEEL, hscroll); - input_sync(atkbd->dev); + input_report_key(dev, BTN_MIDDLE, click); + input_report_rel(dev, REL_WHEEL, scroll); + input_report_rel(dev, REL_HWHEEL, hscroll); + input_sync(dev); } atkbd->release = 0; @@ -764,6 +815,9 @@ static void atkbd_set_keycode_table(stru for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++) atkbd->keycode[atkbd_scroll_keys[i].set2] = atkbd_scroll_keys[i].keycode; } + + atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANGEUL)] = KEY_HANGUEL; + atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANJA)] = KEY_HANJA; } /* @@ -776,12 +830,15 @@ static void atkbd_set_device_attrs(struc int i; if (atkbd->extra) - sprintf(atkbd->name, "AT Set 2 Extra keyboard"); + snprintf(atkbd->name, sizeof(atkbd->name), + "AT Set 2 Extra keyboard"); else - sprintf(atkbd->name, "AT %s Set %d keyboard", - atkbd->translated ? "Translated" : "Raw", atkbd->set); + snprintf(atkbd->name, sizeof(atkbd->name), + "AT %s Set %d keyboard", + atkbd->translated ? "Translated" : "Raw", atkbd->set); - sprintf(atkbd->phys, "%s/input0", atkbd->ps2dev.serio->phys); + snprintf(atkbd->phys, sizeof(atkbd->phys), + "%s/input0", atkbd->ps2dev.serio->phys); input_dev->name = atkbd->name; input_dev->phys = atkbd->phys; diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 77c4d96..5174224 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -384,18 +384,21 @@ lkkbd_detection_done (struct lkkbd *lk) */ switch (lk->id[4]) { case 1: - sprintf (lk->name, "DEC LK201 keyboard"); + strlcpy (lk->name, "DEC LK201 keyboard", + sizeof (lk->name)); if (lk201_compose_is_alt) lk->keycode[0xb1] = KEY_LEFTALT; break; case 2: - sprintf (lk->name, "DEC LK401 keyboard"); + strlcpy (lk->name, "DEC LK401 keyboard", + sizeof (lk->name)); break; default: - sprintf (lk->name, "Unknown DEC keyboard"); + strlcpy (lk->name, "Unknown DEC keyboard", + sizeof (lk->name)); printk (KERN_ERR "lkkbd: keyboard on %s is unknown, " "please report to Jan-Benedict Glaw " "\n", lk->phys); diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index d10983c..40a3f55 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c @@ -96,7 +96,7 @@ static int nkbd_connect(struct serio *se nkbd->serio = serio; nkbd->dev = input_dev; - sprintf(nkbd->phys, "%s/input0", serio->phys); + snprintf(nkbd->phys, sizeof(nkbd->phys), "%s/input0", serio->phys); memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode)); input_dev->name = "Newton Keyboard"; diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index b15b6d8..9dbd7b8 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -263,7 +263,7 @@ static int sunkbd_connect(struct serio * goto fail; } - sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type); + snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type); memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode)); input_dev->name = sunkbd->name; diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index 4135e3e..0821d53 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c @@ -100,7 +100,7 @@ static int xtkbd_connect(struct serio *s xtkbd->serio = serio; xtkbd->dev = input_dev; - sprintf(xtkbd->phys, "%s/input0", serio->phys); + snprintf(xtkbd->phys, sizeof(xtkbd->phys), "%s/input0", serio->phys); memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode)); input_dev->name = "XT Keyboard"; diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 4bad588..a6dfc74 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -26,7 +26,7 @@ config INPUT_PCSPKR config INPUT_SPARCSPKR tristate "SPARC Speaker support" - depends on PCI && SPARC + depends on PCI && SPARC64 help Say Y here if you want the standard Speaker on Sparc PCI systems to be used for bells and whistles. diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index f0fd2c4..42c11fb 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -2,7 +2,7 @@ * Driver for PC-speaker like devices found on various Sparc systems. * * Copyright (c) 2002 Vojtech Pavlik - * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2002, 2006 David S. Miller (davem@davemloft.net) */ #include #include @@ -13,21 +13,23 @@ #include #include #include -#ifdef CONFIG_SPARC64 #include -#endif -MODULE_AUTHOR("David S. Miller "); +MODULE_AUTHOR("David S. Miller "); MODULE_DESCRIPTION("Sparc Speaker beeper driver"); MODULE_LICENSE("GPL"); -const char *beep_name; -static unsigned long beep_iobase; -static int (*beep_event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); -static DEFINE_SPINLOCK(beep_lock); +struct sparcspkr_state { + const char *name; + unsigned long iobase; + int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); + spinlock_t lock; + struct input_dev *input_dev; +}; static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { + struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev); unsigned int count = 0; unsigned long flags; @@ -43,24 +45,24 @@ static int ebus_spkr_event(struct input_ if (value > 20 && value < 32767) count = 1193182 / value; - spin_lock_irqsave(&beep_lock, flags); + spin_lock_irqsave(&state->lock, flags); /* EBUS speaker only has on/off state, the frequency does not * appear to be programmable. */ - if (beep_iobase & 0x2UL) - outb(!!count, beep_iobase); + if (state->iobase & 0x2UL) + outb(!!count, state->iobase); else - outl(!!count, beep_iobase); + outl(!!count, state->iobase); - spin_unlock_irqrestore(&beep_lock, flags); + spin_unlock_irqrestore(&state->lock, flags); return 0; } -#ifdef CONFIG_SPARC64 static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { + struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev); unsigned int count = 0; unsigned long flags; @@ -76,29 +78,29 @@ static int isa_spkr_event(struct input_d if (value > 20 && value < 32767) count = 1193182 / value; - spin_lock_irqsave(&beep_lock, flags); + spin_lock_irqsave(&state->lock, flags); if (count) { /* enable counter 2 */ - outb(inb(beep_iobase + 0x61) | 3, beep_iobase + 0x61); + outb(inb(state->iobase + 0x61) | 3, state->iobase + 0x61); /* set command for counter 2, 2 byte write */ - outb(0xB6, beep_iobase + 0x43); + outb(0xB6, state->iobase + 0x43); /* select desired HZ */ - outb(count & 0xff, beep_iobase + 0x42); - outb((count >> 8) & 0xff, beep_iobase + 0x42); + outb(count & 0xff, state->iobase + 0x42); + outb((count >> 8) & 0xff, state->iobase + 0x42); } else { /* disable counter 2 */ - outb(inb_p(beep_iobase + 0x61) & 0xFC, beep_iobase + 0x61); + outb(inb_p(state->iobase + 0x61) & 0xFC, state->iobase + 0x61); } - spin_unlock_irqrestore(&beep_lock, flags); + spin_unlock_irqrestore(&state->lock, flags); return 0; } -#endif -static int __devinit sparcspkr_probe(struct platform_device *dev) +static int __devinit sparcspkr_probe(struct device *dev) { + struct sparcspkr_state *state = dev_get_drvdata(dev); struct input_dev *input_dev; int error; @@ -106,18 +108,18 @@ static int __devinit sparcspkr_probe(str if (!input_dev) return -ENOMEM; - input_dev->name = beep_name; + input_dev->name = state->name; input_dev->phys = "sparc/input0"; input_dev->id.bustype = BUS_ISA; input_dev->id.vendor = 0x001f; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; - input_dev->cdev.dev = &dev->dev; + input_dev->cdev.dev = dev; input_dev->evbit[0] = BIT(EV_SND); input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); - input_dev->event = beep_event; + input_dev->event = state->event; error = input_register_device(input_dev); if (error) { @@ -125,111 +127,137 @@ static int __devinit sparcspkr_probe(str return error; } - platform_set_drvdata(dev, input_dev); + state->input_dev = input_dev; return 0; } -static int __devexit sparcspkr_remove(struct platform_device *dev) +static int __devexit sparcspkr_remove(struct of_device *dev) { - struct input_dev *input_dev = platform_get_drvdata(dev); + struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); + struct input_dev *input_dev = state->input_dev; - input_unregister_device(input_dev); - platform_set_drvdata(dev, NULL); /* turn off the speaker */ - beep_event(NULL, EV_SND, SND_BELL, 0); + state->event(input_dev, EV_SND, SND_BELL, 0); + + input_unregister_device(input_dev); + + dev_set_drvdata(&dev->dev, NULL); + kfree(state); return 0; } -static void sparcspkr_shutdown(struct platform_device *dev) +static int sparcspkr_shutdown(struct of_device *dev) { + struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); + struct input_dev *input_dev = state->input_dev; + /* turn off the speaker */ - beep_event(NULL, EV_SND, SND_BELL, 0); + state->event(input_dev, EV_SND, SND_BELL, 0); + + return 0; +} + +static int __devinit ebus_beep_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct linux_ebus_device *edev = to_ebus_device(&dev->dev); + struct sparcspkr_state *state; + int err; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->name = "Sparc EBUS Speaker"; + state->iobase = edev->resource[0].start; + state->event = ebus_spkr_event; + spin_lock_init(&state->lock); + + dev_set_drvdata(&dev->dev, state); + + err = sparcspkr_probe(&dev->dev); + if (err) { + dev_set_drvdata(&dev->dev, NULL); + kfree(state); + } + + return 0; } -static struct platform_driver sparcspkr_platform_driver = { - .driver = { - .name = "sparcspkr", - .owner = THIS_MODULE, +static struct of_device_id ebus_beep_match[] = { + { + .name = "beep", }, - .probe = sparcspkr_probe, - .remove = __devexit_p(sparcspkr_remove), - .shutdown = sparcspkr_shutdown, + {}, }; -static struct platform_device *sparcspkr_platform_device; +static struct of_platform_driver ebus_beep_driver = { + .name = "beep", + .match_table = ebus_beep_match, + .probe = ebus_beep_probe, + .remove = sparcspkr_remove, + .shutdown = sparcspkr_shutdown, +}; -static int __init sparcspkr_drv_init(void) +static int __devinit isa_beep_probe(struct of_device *dev, const struct of_device_id *match) { - int error; + struct sparc_isa_device *idev = to_isa_device(&dev->dev); + struct sparcspkr_state *state; + int err; - error = platform_driver_register(&sparcspkr_platform_driver); - if (error) - return error; + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; - sparcspkr_platform_device = platform_device_alloc("sparcspkr", -1); - if (!sparcspkr_platform_device) { - error = -ENOMEM; - goto err_unregister_driver; - } + state->name = "Sparc ISA Speaker"; + state->iobase = idev->resource.start; + state->event = isa_spkr_event; + spin_lock_init(&state->lock); + + dev_set_drvdata(&dev->dev, state); - error = platform_device_add(sparcspkr_platform_device); - if (error) - goto err_free_device; + err = sparcspkr_probe(&dev->dev); + if (err) { + dev_set_drvdata(&dev->dev, NULL); + kfree(state); + } return 0; +} - err_free_device: - platform_device_put(sparcspkr_platform_device); - err_unregister_driver: - platform_driver_unregister(&sparcspkr_platform_driver); +static struct of_device_id isa_beep_match[] = { + { + .name = "dma", + }, + {}, +}; - return error; -} +static struct of_platform_driver isa_beep_driver = { + .name = "beep", + .match_table = isa_beep_match, + .probe = isa_beep_probe, + .remove = sparcspkr_remove, + .shutdown = sparcspkr_shutdown, +}; static int __init sparcspkr_init(void) { - struct linux_ebus *ebus; - struct linux_ebus_device *edev; -#ifdef CONFIG_SPARC64 - struct sparc_isa_bridge *isa_br; - struct sparc_isa_device *isa_dev; -#endif - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "beep")) { - beep_name = "Sparc EBUS Speaker"; - beep_event = ebus_spkr_event; - beep_iobase = edev->resource[0].start; - return sparcspkr_drv_init(); - } - } - } -#ifdef CONFIG_SPARC64 - for_each_isa(isa_br) { - for_each_isadev(isa_dev, isa_br) { - /* A hack, the beep device's base lives in - * the DMA isa node. - */ - if (!strcmp(isa_dev->prom_name, "dma")) { - beep_name = "Sparc ISA Speaker"; - beep_event = isa_spkr_event, - beep_iobase = isa_dev->resource.start; - return sparcspkr_drv_init(); - } - } + int err = of_register_driver(&ebus_beep_driver, &ebus_bus_type); + + if (!err) { + err = of_register_driver(&isa_beep_driver, &isa_bus_type); + if (err) + of_unregister_driver(&ebus_beep_driver); } -#endif - return -ENODEV; + return err; } static void __exit sparcspkr_exit(void) { - platform_device_unregister(sparcspkr_platform_device); - platform_driver_unregister(&sparcspkr_platform_driver); + of_unregister_driver(&ebus_beep_driver); + of_unregister_driver(&isa_beep_driver); } module_init(sparcspkr_init); diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index a0e2e79..070d753 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -470,7 +470,7 @@ int alps_init(struct psmouse *psmouse) dev1->keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); } - sprintf(priv->phys, "%s/input1", psmouse->ps2dev.serio->phys); + snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); dev2->phys = priv->phys; dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; dev2->id.bustype = BUS_I8042; diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 136321a..8bc9f51 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -150,9 +150,20 @@ static psmouse_ret_t psmouse_process_byt */ if (psmouse->type == PSMOUSE_IMEX) { - input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); - input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); - input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); + switch (packet[3] & 0xC0) { + case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */ + input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); + break; + case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */ + input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); + break; + case 0x00: + case 0xC0: + input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); + input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); + input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); + break; + } } /* @@ -466,9 +477,25 @@ static int im_explorer_detect(struct psm if (param[0] != 4) return -1; +/* Magic to enable horizontal scrolling on IntelliMouse 4.0 */ + param[0] = 200; + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + param[0] = 80; + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + param[0] = 40; + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + + param[0] = 200; + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + param[0] = 200; + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + param[0] = 60; + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + if (set_properties) { set_bit(BTN_MIDDLE, psmouse->dev->keybit); set_bit(REL_WHEEL, psmouse->dev->relbit); + set_bit(REL_HWHEEL, psmouse->dev->relbit); set_bit(BTN_SIDE, psmouse->dev->keybit); set_bit(BTN_EXTRA, psmouse->dev->keybit); @@ -1057,8 +1084,8 @@ static int psmouse_switch_protocol(struc if (psmouse->resync_time && psmouse->poll(psmouse)) psmouse->resync_time = 0; - sprintf(psmouse->devname, "%s %s %s", - psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); + snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", + psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); input_dev->name = psmouse->devname; input_dev->phys = psmouse->phys; @@ -1099,7 +1126,7 @@ static int psmouse_connect(struct serio ps2_init(&psmouse->ps2dev, serio); INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse); psmouse->dev = input_dev; - sprintf(psmouse->phys, "%s/input0", serio->phys); + snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c index 2f9a04a..a897424 100644 --- a/drivers/input/mouse/sermouse.c +++ b/drivers/input/mouse/sermouse.c @@ -254,7 +254,7 @@ static int sermouse_connect(struct serio goto fail; sermouse->dev = input_dev; - sprintf(sermouse->phys, "%s/input0", serio->phys); + snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys); sermouse->type = serio->id.proto; input_dev->name = sermouse_protocols[sermouse->type]; diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index 36e9442..7b85bc2 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c @@ -153,22 +153,25 @@ vsxxxaa_detection_done (struct vsxxxaa * { switch (mouse->type) { case 0x02: - sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse"); + strlcpy (mouse->name, "DEC VSXXX-AA/-GA mouse", + sizeof (mouse->name)); break; case 0x04: - sprintf (mouse->name, "DEC VSXXX-AB digitizer"); + strlcpy (mouse->name, "DEC VSXXX-AB digitizer", + sizeof (mouse->name)); break; default: - sprintf (mouse->name, "unknown DEC pointer device " - "(type = 0x%02x)", mouse->type); + snprintf (mouse->name, sizeof (mouse->name), + "unknown DEC pointer device (type = 0x%02x)", + mouse->type); break; } - printk (KERN_INFO "Found %s version 0x%02x from country 0x%02x " - "on port %s\n", mouse->name, mouse->version, - mouse->country, mouse->phys); + printk (KERN_INFO + "Found %s version 0x%02x from country 0x%02x on port %s\n", + mouse->name, mouse->version, mouse->country, mouse->phys); } /* @@ -503,8 +506,9 @@ vsxxxaa_connect (struct serio *serio, st mouse->dev = input_dev; mouse->serio = serio; - sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer"); - sprintf (mouse->phys, "%s/input0", serio->phys); + strlcat (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer", + sizeof (mouse->name)); + snprintf (mouse->phys, sizeof (mouse->phys), "%s/input0", serio->phys); input_dev->name = mouse->name; input_dev->phys = mouse->phys; diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index b685a50..eb721b1 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -123,7 +123,9 @@ static void mousedev_touchpad_event(stru if (mousedev->touch) { size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; - if (size == 0) size = 256 * 2; + if (size == 0) + size = 256 * 2; + switch (code) { case ABS_X: fx(0) = value; @@ -155,18 +157,24 @@ static void mousedev_abs_event(struct in switch (code) { case ABS_X: size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; - if (size == 0) size = xres ? : 1; - if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X]; - if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X]; + if (size == 0) + size = xres ? : 1; + if (value > dev->absmax[ABS_X]) + value = dev->absmax[ABS_X]; + if (value < dev->absmin[ABS_X]) + value = dev->absmin[ABS_X]; mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size; mousedev->packet.abs_event = 1; break; case ABS_Y: size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; - if (size == 0) size = yres ? : 1; - if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y]; - if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y]; + if (size == 0) + size = yres ? : 1; + if (value > dev->absmax[ABS_Y]) + value = dev->absmax[ABS_Y]; + if (value < dev->absmin[ABS_Y]) + value = dev->absmin[ABS_Y]; mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size; mousedev->packet.abs_event = 1; break; @@ -202,7 +210,7 @@ static void mousedev_key_event(struct mo case BTN_SIDE: index = 3; break; case BTN_4: case BTN_EXTRA: index = 4; break; - default: return; + default: return; } if (value) { @@ -285,10 +293,9 @@ static void mousedev_touchpad_touch(stru mousedev->touch = mousedev->pkt_count = 0; mousedev->frac_dx = 0; mousedev->frac_dy = 0; - } - else - if (!mousedev->touch) - mousedev->touch = jiffies; + + } else if (!mousedev->touch) + mousedev->touch = jiffies; } static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) @@ -327,7 +334,7 @@ static void mousedev_event(struct input_ mousedev->pkt_count++; /* Input system eats duplicate events, but we need all of them * to do correct averaging so apply present one forward - */ + */ fx(0) = fx(1); fy(0) = fy(1); } @@ -346,7 +353,9 @@ static int mousedev_fasync(int fd, struc { int retval; struct mousedev_list *list = file->private_data; + retval = fasync_helper(fd, file, on, &list->fasync); + return retval < 0 ? retval : 0; } @@ -507,14 +516,16 @@ static ssize_t mousedev_write(struct fil list->imexseq = 0; list->mode = MOUSEDEV_EMUL_EXPS; } - } else list->imexseq = 0; + } else + list->imexseq = 0; if (c == mousedev_imps_seq[list->impsseq]) { if (++list->impsseq == MOUSEDEV_SEQ_LEN) { list->impsseq = 0; list->mode = MOUSEDEV_EMUL_IMPS; } - } else list->impsseq = 0; + } else + list->impsseq = 0; list->ps2[0] = 0xfa; @@ -598,6 +609,7 @@ static ssize_t mousedev_read(struct file static unsigned int mousedev_poll(struct file *file, poll_table *wait) { struct mousedev_list *list = file->private_data; + poll_wait(file, &list->mousedev->wait, wait); return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) | (list->mousedev->exist ? 0 : (POLLHUP | POLLERR)); diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index ed9446f..6d66351 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h @@ -74,7 +74,7 @@ #else for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "8042")) + if (!strcmp(edev->prom_node->name, "8042")) goto edev_found; } } @@ -82,14 +82,14 @@ #else edev_found: for_each_edevchild(edev, child) { - if (!strcmp(child->prom_name, OBP_PS2KBD_NAME1) || - !strcmp(child->prom_name, OBP_PS2KBD_NAME2)) { + if (!strcmp(child->prom_node->name, OBP_PS2KBD_NAME1) || + !strcmp(child->prom_node->name, OBP_PS2KBD_NAME2)) { i8042_kbd_irq = child->irqs[0]; kbd_iobase = ioremap(child->resource[0].start, 8); } - if (!strcmp(child->prom_name, OBP_PS2MS_NAME1) || - !strcmp(child->prom_name, OBP_PS2MS_NAME2)) + if (!strcmp(child->prom_node->name, OBP_PS2MS_NAME1) || + !strcmp(child->prom_node->name, OBP_PS2MS_NAME2)) i8042_aux_irq = child->irqs[0]; } if (i8042_kbd_irq == -1 || diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 161afdd..386023c 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -773,8 +773,7 @@ static int __devinit ads7846_probe(struc ts->last_msg = m; - if (request_irq(spi->irq, ads7846_irq, - SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, + if (request_irq(spi->irq, ads7846_irq, SA_TRIGGER_FALLING, spi->dev.driver->name, ts)) { dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); err = -EBUSY; diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index 466da19..b769b21 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c @@ -129,7 +129,7 @@ static int gunze_connect(struct serio *s gunze->serio = serio; gunze->dev = input_dev; - sprintf(gunze->phys, "%s/input0", serio->phys); + snprintf(gunze->phys, sizeof(serio->phys), "%s/input0", serio->phys); input_dev->private = gunze; input_dev->name = "Gunze AHL-51S TouchScreen"; diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index a18d56b..2de2139 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c @@ -363,7 +363,7 @@ static int h3600ts_connect(struct serio ts->serio = serio; ts->dev = input_dev; - sprintf(ts->phys, "%s/input0", serio->phys); + snprintf(ts->phys, sizeof(ts->phys), "%s/input0", serio->phys); input_dev->name = "H3600 TouchScreen"; input_dev->phys = ts->phys; @@ -399,16 +399,14 @@ static int h3600ts_connect(struct serio set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, - SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, - "h3600_action", &ts->dev)) { + SA_SHIRQ | SA_INTERRUPT, "h3600_action", &ts->dev)) { printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); err = -EBUSY; goto fail2; } if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, - SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, - "h3600_suspend", &ts->dev)) { + SA_SHIRQ | SA_INTERRUPT, "h3600_suspend", &ts->dev)) { printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); err = -EBUSY; goto fail3; diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index 1d0d37e..8647a90 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c @@ -143,7 +143,7 @@ static int mtouch_connect(struct serio * mtouch->serio = serio; mtouch->dev = input_dev; - sprintf(mtouch->phys, "%s/input0", serio->phys); + snprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys); input_dev->private = mtouch; input_dev->name = "MicroTouch Serial TouchScreen"; diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c index d678d14..5f9ecad 100644 --- a/drivers/input/tsdev.c +++ b/drivers/input/tsdev.c @@ -35,7 +35,7 @@ * e-mail - mail your message to . */ -#define TSDEV_MINOR_BASE 128 +#define TSDEV_MINOR_BASE 128 #define TSDEV_MINORS 32 /* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */ #define TSDEV_MINOR_MASK 15 @@ -230,6 +230,7 @@ static ssize_t tsdev_read(struct file *f static unsigned int tsdev_poll(struct file *file, poll_table * wait) { struct tsdev_list *list = file->private_data; + poll_wait(file, &list->tsdev->wait, wait); return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) | (list->tsdev->exist ? 0 : (POLLHUP | POLLERR)); @@ -248,11 +249,13 @@ static int tsdev_ioctl(struct inode *ino sizeof (struct ts_calibration))) retval = -EFAULT; break; + case TS_SET_CAL: if (copy_from_user (&tsdev->cal, (void __user *)arg, sizeof (struct ts_calibration))) retval = -EFAULT; break; + default: retval = -EINVAL; break; @@ -284,9 +287,11 @@ static void tsdev_event(struct input_han case ABS_X: tsdev->x = value; break; + case ABS_Y: tsdev->y = value; break; + case ABS_PRESSURE: if (value > handle->dev->absmax[ABS_PRESSURE]) value = handle->dev->absmax[ABS_PRESSURE]; @@ -307,6 +312,7 @@ static void tsdev_event(struct input_han else if (tsdev->x > xres) tsdev->x = xres; break; + case REL_Y: tsdev->y += value; if (tsdev->y < 0) @@ -323,6 +329,7 @@ static void tsdev_event(struct input_han case 0: tsdev->pressure = 0; break; + case 1: if (!tsdev->pressure) tsdev->pressure = 1; @@ -370,9 +377,8 @@ static struct input_handle *tsdev_connec struct class_device *cdev; int minor, delta; - for (minor = 0; minor < TSDEV_MINORS/2 && tsdev_table[minor]; - minor++); - if (minor >= TSDEV_MINORS/2) { + for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++); + if (minor >= TSDEV_MINORS / 2) { printk(KERN_ERR "tsdev: You have way too many touchscreens\n"); return NULL; @@ -444,22 +450,22 @@ static struct input_device_id tsdev_ids[ .evbit = { BIT(EV_KEY) | BIT(EV_REL) }, .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) }, .relbit = { BIT(REL_X) | BIT(REL_Y) }, - },/* A mouse like device, at least one button, two relative axes */ + }, /* A mouse like device, at least one button, two relative axes */ { .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .evbit = { BIT(EV_KEY) | BIT(EV_ABS) }, .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, - },/* A tablet like device, at least touch detection, two absolute axes */ + }, /* A tablet like device, at least touch detection, two absolute axes */ { .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, .evbit = { BIT(EV_ABS) }, .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) }, - },/* A tablet like device with several gradations of pressure */ + }, /* A tablet like device with several gradations of pressure */ - {},/* Terminating entry */ + {} /* Terminating entry */ }; MODULE_DEVICE_TABLE(input, tsdev_ids); diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 173c899..2e541fa 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -87,6 +87,11 @@ struct capincci; #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE struct capiminor; +struct datahandle_queue { + struct list_head list; + u16 datahandle; +}; + struct capiminor { struct list_head list; struct capincci *nccip; @@ -109,12 +114,9 @@ struct capiminor { int outbytes; /* transmit path */ - struct datahandle_queue { - struct datahandle_queue *next; - u16 datahandle; - } *ackqueue; + struct list_head ackqueue; int nack; - + spinlock_t ackqlock; }; #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -156,48 +158,54 @@ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE static int capincci_add_ack(struct capiminor *mp, u16 datahandle) { - struct datahandle_queue *n, **pp; + struct datahandle_queue *n; + unsigned long flags; n = kmalloc(sizeof(*n), GFP_ATOMIC); - if (!n) { - printk(KERN_ERR "capi: alloc datahandle failed\n"); - return -1; + if (unlikely(!n)) { + printk(KERN_ERR "capi: alloc datahandle failed\n"); + return -1; } - n->next = NULL; n->datahandle = datahandle; - for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) ; - *pp = n; + INIT_LIST_HEAD(&n->list); + spin_lock_irqsave(&mp->ackqlock, flags); + list_add_tail(&n->list, &mp->ackqueue); mp->nack++; + spin_unlock_irqrestore(&mp->ackqlock, flags); return 0; } static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) { - struct datahandle_queue **pp, *p; + struct datahandle_queue *p, *tmp; + unsigned long flags; - for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) { - if ((*pp)->datahandle == datahandle) { - p = *pp; - *pp = (*pp)->next; + spin_lock_irqsave(&mp->ackqlock, flags); + list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { + if (p->datahandle == datahandle) { + list_del(&p->list); kfree(p); mp->nack--; + spin_unlock_irqrestore(&mp->ackqlock, flags); return 0; } } + spin_unlock_irqrestore(&mp->ackqlock, flags); return -1; } static void capiminor_del_all_ack(struct capiminor *mp) { - struct datahandle_queue **pp, *p; + struct datahandle_queue *p, *tmp; + unsigned long flags; - pp = &mp->ackqueue; - while (*pp) { - p = *pp; - *pp = (*pp)->next; + spin_lock_irqsave(&mp->ackqlock, flags); + list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { + list_del(&p->list); kfree(p); mp->nack--; } + spin_unlock_irqrestore(&mp->ackqlock, flags); } @@ -220,6 +228,8 @@ static struct capiminor *capiminor_alloc mp->ncci = ncci; mp->msgid = 0; atomic_set(&mp->ttyopencount,0); + INIT_LIST_HEAD(&mp->ackqueue); + spin_lock_init(&mp->ackqlock); skb_queue_head_init(&mp->inqueue); skb_queue_head_init(&mp->outqueue); diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 0a37ade..9ea6bd0 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -121,10 +121,10 @@ fail: return -ENOMEM; } -static struct super_block *capifs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int capifs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, capifs_fill_super); + return get_sb_single(fs_type, flags, data, capifs_fill_super, mnt); } static struct file_system_type capifs_fs_type = { diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index f1a1f9a..1f5ebe9 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c @@ -592,7 +592,7 @@ static int put_address(char *st, u_char } /* put_address */ /*************************************/ -/* report a succesfull interrogation */ +/* report a successful interrogation */ /*************************************/ static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs) { char *src = ic->parm.dss1_io.data; diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index eb41aba..8a45715 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -65,23 +65,22 @@ static struct usb_device_id gigaset_tabl MODULE_DEVICE_TABLE(usb, gigaset_table); -/*======================= local function prototypes =============================*/ +/*======================= local function prototypes ==========================*/ -/* This function is called if a new device is connected to the USB port. It - * checks whether this new device belongs to this driver. - */ +/* function called if a new device belonging to this driver is connected */ static int gigaset_probe(struct usb_interface *interface, const struct usb_device_id *id); /* Function will be called if the device is unplugged */ static void gigaset_disconnect(struct usb_interface *interface); -static void read_ctrl_callback(struct urb *, struct pt_regs *); +static int atread_submit(struct cardstate *, int); static void stopurbs(struct bas_bc_state *); +static int req_submit(struct bc_state *, int, int, int); static int atwrite_submit(struct cardstate *, unsigned char *, int); static int start_cbsend(struct cardstate *); -/*==============================================================================*/ +/*============================================================================*/ struct bas_cardstate { struct usb_device *udev; /* USB device pointer */ @@ -91,6 +90,7 @@ struct bas_cardstate { struct urb *urb_ctrl; /* control pipe default URB */ struct usb_ctrlrequest dr_ctrl; struct timer_list timer_ctrl; /* control request timeout */ + int retry_ctrl; struct timer_list timer_atrdy; /* AT command ready timeout */ struct urb *urb_cmd_out; /* for sending AT commands */ @@ -307,6 +307,7 @@ static int gigaset_set_line_ctrl(struct * hang up any existing connection because of an unrecoverable error * This function may be called from any context and takes care of scheduling * the necessary actions for execution outside of interrupt context. + * cs->lock must not be held. * argument: * B channel control structure */ @@ -325,14 +326,17 @@ static inline void error_hangup(struct b /* error_reset * reset Gigaset device because of an unrecoverable error - * This function may be called from any context, and should take care of + * This function may be called from any context, and takes care of * scheduling the necessary actions for execution outside of interrupt context. - * Right now, it just generates a kernel message calling for help. + * cs->lock must not be held. * argument: * controller state structure */ static inline void error_reset(struct cardstate *cs) { + /* close AT command channel to recover (ignore errors) */ + req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT); + //FIXME try to recover without bothering the user dev_err(cs->dev, "unrecoverable error - please disconnect Gigaset base to reset\n"); @@ -403,14 +407,30 @@ static void cmd_in_timeout(unsigned long { struct cardstate *cs = (struct cardstate *) data; struct bas_cardstate *ucs = cs->hw.bas; + int rc; if (!ucs->rcvbuf_size) { gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); return; } - dev_err(cs->dev, "timeout reading AT response\n"); - error_reset(cs); //FIXME retry? + if (ucs->retry_cmd_in++ < BAS_RETRY) { + dev_notice(cs->dev, "control read: timeout, retry %d\n", + ucs->retry_cmd_in); + rc = atread_submit(cs, BAS_TIMEOUT); + if (rc >= 0 || rc == -ENODEV) + /* resubmitted or disconnected */ + /* - bypass regular exit block */ + return; + } else { + dev_err(cs->dev, + "control read: timeout, giving up after %d tries\n", + ucs->retry_cmd_in); + } + kfree(ucs->rcvbuf); + ucs->rcvbuf = NULL; + ucs->rcvbuf_size = 0; + error_reset(cs); } /* set/clear bits in base connection state, return previous state @@ -428,6 +448,96 @@ inline static int update_basstate(struct return state; } +/* read_ctrl_callback + * USB completion handler for control pipe input + * called by the USB subsystem in interrupt context + * parameter: + * urb USB request block + * urb->context = inbuf structure for controller state + */ +static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) +{ + struct inbuf_t *inbuf = urb->context; + struct cardstate *cs = inbuf->cs; + struct bas_cardstate *ucs = cs->hw.bas; + int have_data = 0; + unsigned numbytes; + int rc; + + update_basstate(ucs, 0, BS_ATRDPEND); + + if (!ucs->rcvbuf_size) { + dev_warn(cs->dev, "%s: no receive in progress\n", __func__); + return; + } + + del_timer(&ucs->timer_cmd_in); + + switch (urb->status) { + case 0: /* normal completion */ + numbytes = urb->actual_length; + if (unlikely(numbytes != ucs->rcvbuf_size)) { + dev_warn(cs->dev, + "control read: received %d chars, expected %d\n", + numbytes, ucs->rcvbuf_size); + if (numbytes > ucs->rcvbuf_size) + numbytes = ucs->rcvbuf_size; + } + + /* copy received bytes to inbuf */ + have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes); + + if (unlikely(numbytes < ucs->rcvbuf_size)) { + /* incomplete - resubmit for remaining bytes */ + ucs->rcvbuf_size -= numbytes; + ucs->retry_cmd_in = 0; + rc = atread_submit(cs, BAS_TIMEOUT); + if (rc >= 0 || rc == -ENODEV) + /* resubmitted or disconnected */ + /* - bypass regular exit block */ + return; + error_reset(cs); + } + break; + + case -ENOENT: /* cancelled */ + case -ECONNRESET: /* cancelled (async) */ + case -EINPROGRESS: /* pending */ + case -ENODEV: /* device removed */ + case -ESHUTDOWN: /* device shut down */ + /* no action necessary */ + gig_dbg(DEBUG_USBREQ, "%s: %s", + __func__, get_usb_statmsg(urb->status)); + break; + + default: /* severe trouble */ + dev_warn(cs->dev, "control read: %s\n", + get_usb_statmsg(urb->status)); + if (ucs->retry_cmd_in++ < BAS_RETRY) { + dev_notice(cs->dev, "control read: retry %d\n", + ucs->retry_cmd_in); + rc = atread_submit(cs, BAS_TIMEOUT); + if (rc >= 0 || rc == -ENODEV) + /* resubmitted or disconnected */ + /* - bypass regular exit block */ + return; + } else { + dev_err(cs->dev, + "control read: giving up after %d tries\n", + ucs->retry_cmd_in); + } + error_reset(cs); + } + + kfree(ucs->rcvbuf); + ucs->rcvbuf = NULL; + ucs->rcvbuf_size = 0; + if (have_data) { + gig_dbg(DEBUG_INTR, "%s-->BH", __func__); + gigaset_schedule_event(cs); + } +} + /* atread_submit * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout * parameters: @@ -466,7 +576,7 @@ static int atread_submit(struct cardstat if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) { update_basstate(ucs, 0, BS_ATRDPEND); dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", - get_usb_statmsg(ret)); + get_usb_rcmsg(ret)); return ret; } @@ -611,9 +721,12 @@ static void read_int_callback(struct urb kfree(ucs->rcvbuf); ucs->rcvbuf = NULL; ucs->rcvbuf_size = 0; - if (rc != -ENODEV) + if (rc != -ENODEV) { //FIXME corrective action? + spin_unlock_irqrestore(&cs->lock, flags); error_reset(cs); + break; + } } spin_unlock_irqrestore(&cs->lock, flags); break; @@ -643,97 +756,6 @@ resubmit: } } -/* read_ctrl_callback - * USB completion handler for control pipe input - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block - * urb->context = inbuf structure for controller state - */ -static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) -{ - struct inbuf_t *inbuf = urb->context; - struct cardstate *cs = inbuf->cs; - struct bas_cardstate *ucs = cs->hw.bas; - int have_data = 0; - unsigned numbytes; - int rc; - - update_basstate(ucs, 0, BS_ATRDPEND); - - if (!ucs->rcvbuf_size) { - dev_warn(cs->dev, "%s: no receive in progress\n", __func__); - return; - } - - del_timer(&ucs->timer_cmd_in); - - switch (urb->status) { - case 0: /* normal completion */ - numbytes = urb->actual_length; - if (unlikely(numbytes == 0)) { - dev_warn(cs->dev, - "control read: empty block received\n"); - goto retry; - } - if (unlikely(numbytes != ucs->rcvbuf_size)) { - dev_warn(cs->dev, - "control read: received %d chars, expected %d\n", - numbytes, ucs->rcvbuf_size); - if (numbytes > ucs->rcvbuf_size) - numbytes = ucs->rcvbuf_size; - } - - /* copy received bytes to inbuf */ - have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes); - - if (unlikely(numbytes < ucs->rcvbuf_size)) { - /* incomplete - resubmit for remaining bytes */ - ucs->rcvbuf_size -= numbytes; - ucs->retry_cmd_in = 0; - goto retry; - } - break; - - case -ENOENT: /* cancelled */ - case -ECONNRESET: /* cancelled (async) */ - case -EINPROGRESS: /* pending */ - case -ENODEV: /* device removed */ - case -ESHUTDOWN: /* device shut down */ - /* no action necessary */ - gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(urb->status)); - break; - - default: /* severe trouble */ - dev_warn(cs->dev, "control read: %s\n", - get_usb_statmsg(urb->status)); - retry: - if (ucs->retry_cmd_in++ < BAS_RETRY) { - dev_notice(cs->dev, "control read: retry %d\n", - ucs->retry_cmd_in); - rc = atread_submit(cs, BAS_TIMEOUT); - if (rc >= 0 || rc == -ENODEV) - /* resubmitted or disconnected */ - /* - bypass regular exit block */ - return; - } else { - dev_err(cs->dev, - "control read: giving up after %d tries\n", - ucs->retry_cmd_in); - } - error_reset(cs); - } - - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - if (have_data) { - gig_dbg(DEBUG_INTR, "%s-->BH", __func__); - gigaset_schedule_event(cs); - } -} - /* read_iso_callback * USB completion handler for B channel isochronous input * called by the USB subsystem in interrupt context @@ -1378,6 +1400,7 @@ static void req_timeout(unsigned long da case HD_CLOSE_B1CHANNEL: dev_err(bcs->cs->dev, "timeout closing channel %d\n", bcs->channel + 1); + error_reset(bcs->cs); break; default: @@ -1396,22 +1419,61 @@ static void req_timeout(unsigned long da static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs) { struct bas_cardstate *ucs = urb->context; + int rc; unsigned long flags; - spin_lock_irqsave(&ucs->lock, flags); - if (urb->status && ucs->pending) { - dev_err(&ucs->interface->dev, - "control request 0x%02x failed: %s\n", - ucs->pending, get_usb_statmsg(urb->status)); - del_timer(&ucs->timer_ctrl); - ucs->pending = 0; - } - /* individual handling of specific request types */ - switch (ucs->pending) { - case HD_DEVICE_INIT_ACK: /* no reply expected */ - ucs->pending = 0; + /* check status */ + switch (urb->status) { + case 0: /* normal completion */ + spin_lock_irqsave(&ucs->lock, flags); + switch (ucs->pending) { + case HD_DEVICE_INIT_ACK: /* no reply expected */ + del_timer(&ucs->timer_ctrl); + ucs->pending = 0; + break; + } + spin_unlock_irqrestore(&ucs->lock, flags); + return; + + case -ENOENT: /* cancelled */ + case -ECONNRESET: /* cancelled (async) */ + case -EINPROGRESS: /* pending */ + case -ENODEV: /* device removed */ + case -ESHUTDOWN: /* device shut down */ + /* ignore silently */ + gig_dbg(DEBUG_USBREQ, "%s: %s", + __func__, get_usb_statmsg(urb->status)); break; + + default: /* any failure */ + if (++ucs->retry_ctrl > BAS_RETRY) { + dev_err(&ucs->interface->dev, + "control request 0x%02x failed: %s\n", + ucs->dr_ctrl.bRequest, + get_usb_statmsg(urb->status)); + break; /* give up */ + } + dev_notice(&ucs->interface->dev, + "control request 0x%02x: %s, retry %d\n", + ucs->dr_ctrl.bRequest, get_usb_statmsg(urb->status), + ucs->retry_ctrl); + /* urb->dev is clobbered by USB subsystem */ + urb->dev = ucs->udev; + rc = usb_submit_urb(urb, SLAB_ATOMIC); + if (unlikely(rc)) { + dev_err(&ucs->interface->dev, + "could not resubmit request 0x%02x: %s\n", + ucs->dr_ctrl.bRequest, get_usb_rcmsg(rc)); + break; + } + /* resubmitted */ + return; } + + /* failed, clear pending request */ + spin_lock_irqsave(&ucs->lock, flags); + del_timer(&ucs->timer_ctrl); + ucs->pending = 0; spin_unlock_irqrestore(&ucs->lock, flags); } @@ -1455,9 +1517,11 @@ static int req_submit(struct bc_state *b usb_sndctrlpipe(ucs->udev, 0), (unsigned char*) &ucs->dr_ctrl, NULL, 0, write_ctrl_callback, ucs); - if ((ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC)) != 0) { + ucs->retry_ctrl = 0; + ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC); + if (unlikely(ret)) { dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n", - req, get_usb_statmsg(ret)); + req, get_usb_rcmsg(ret)); spin_unlock_irqrestore(&ucs->lock, flags); return ret; } diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index e55767b..acb7e26 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -460,6 +460,9 @@ void gigaset_freecs(struct cardstate *cs switch (cs->cs_init) { default: + /* clear device sysfs */ + gigaset_free_dev_sysfs(cs); + gigaset_if_free(cs); gig_dbg(DEBUG_INIT, "clearing hw"); @@ -699,6 +702,7 @@ struct cardstate *gigaset_initcs(struct cs->open_count = 0; cs->dev = NULL; cs->tty = NULL; + cs->class = NULL; cs->cidmode = cidmode != 0; //if(onechannel) { //FIXME @@ -760,6 +764,9 @@ struct cardstate *gigaset_initcs(struct gigaset_if_init(cs); + /* set up device sysfs */ + gigaset_init_dev_sysfs(cs); + spin_lock_irqsave(&cs->lock, flags); cs->running = 1; spin_unlock_irqrestore(&cs->lock, flags); @@ -902,9 +909,6 @@ int gigaset_start(struct cardstate *cs) wait_event(cs->waitqueue, !cs->waiting); - /* set up device sysfs */ - gigaset_init_dev_sysfs(cs); - mutex_unlock(&cs->mutex); return 1; @@ -969,9 +973,6 @@ void gigaset_stop(struct cardstate *cs) //FIXME } - /* clear device sysfs */ - gigaset_free_dev_sysfs(cs); - cleanup_cs(cs); exit: diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index 18e05c0..44f02db 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -1262,7 +1262,8 @@ static void do_action(int action, struct break; case ACT_HUPMODEM: /* send "+++" (hangup in unimodem mode) */ - cs->ops->write_cmd(cs, "+++", 3, NULL); + if (cs->connected) + cs->ops->write_cmd(cs, "+++", 3, NULL); break; case ACT_RING: /* get fresh AT state structure for new CID */ @@ -1294,7 +1295,6 @@ static void do_action(int action, struct break; case ACT_ICALL: handle_icall(cs, bcs, p_at_state); - at_state = *p_at_state; break; case ACT_FAILSDOWN: dev_warn(cs->dev, "Could not shut down the device.\n"); @@ -1334,10 +1334,8 @@ static void do_action(int action, struct */ at_state->pending_commands |= PC_DLE0; atomic_set(&cs->commands_pending, 1); - } else { + } else disconnect(p_at_state); - at_state = *p_at_state; - } break; case ACT_FAKEDLE0: at_state->int_var[VAR_ZDLE] = 0; @@ -1354,10 +1352,8 @@ static void do_action(int action, struct at_state->cid = -1; if (bcs && cs->onechannel) at_state->pending_commands |= PC_DLE0; - else { + else disconnect(p_at_state); - at_state = *p_at_state; - } schedule_init(cs, MS_RECOVER); break; case ACT_FAILDLE0: @@ -1410,7 +1406,6 @@ static void do_action(int action, struct case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL processing */ disconnect(p_at_state); - at_state = *p_at_state; break; case ACT_ABORTDIAL: /* error/timeout during dial preparation */ diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 22b9693..8d63d82 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -445,6 +445,7 @@ struct cardstate { struct gigaset_driver *driver; unsigned minor_index; struct device *dev; + struct class_device *class; const struct gigaset_ops *ops; diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 08e4c4e..74fd234 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -625,7 +625,14 @@ void gigaset_if_init(struct cardstate *c return; tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs); - tty_register_device(drv->tty, cs->minor_index, NULL); + cs->class = tty_register_device(drv->tty, cs->minor_index, NULL); + + if (!IS_ERR(cs->class)) + class_set_devdata(cs->class, cs); + else { + warn("could not register device to the tty subsystem"); + cs->class = NULL; + } } void gigaset_if_free(struct cardstate *cs) @@ -638,6 +645,7 @@ void gigaset_if_free(struct cardstate *c tasklet_disable(&cs->if_wake_tasklet); tasklet_kill(&cs->if_wake_tasklet); + cs->class = NULL; tty_unregister_device(drv->tty, cs->minor_index); } diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index d267a63..9ae3a7f 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c @@ -16,12 +16,11 @@ #include "gigaset.h" #include -static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t show_cidmode(struct class_device *class, char *buf) { int ret; unsigned long flags; - struct cardstate *cs = dev_get_drvdata(dev); + struct cardstate *cs = class_get_devdata(class); spin_lock_irqsave(&cs->lock, flags); ret = sprintf(buf, "%u\n", cs->cidmode); @@ -30,10 +29,10 @@ static ssize_t show_cidmode(struct devic return ret; } -static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, +static ssize_t set_cidmode(struct class_device *class, const char *buf, size_t count) { - struct cardstate *cs = dev_get_drvdata(dev); + struct cardstate *cs = class_get_devdata(class); long int value; char *end; @@ -65,18 +64,24 @@ static ssize_t set_cidmode(struct device return count; } -static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode); +static CLASS_DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode); /* free sysfs for device */ void gigaset_free_dev_sysfs(struct cardstate *cs) { + if (!cs->class) + return; + gig_dbg(DEBUG_INIT, "removing sysfs entries"); - device_remove_file(cs->dev, &dev_attr_cidmode); + class_device_remove_file(cs->class, &class_device_attr_cidmode); } /* initialize sysfs for device */ void gigaset_init_dev_sysfs(struct cardstate *cs) { + if (!cs->class) + return; + gig_dbg(DEBUG_INIT, "setting up sysfs"); - device_create_file(cs->dev, &dev_attr_cidmode); + class_device_create_file(cs->class, &class_device_attr_cidmode); } diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c index abecabf..aacbf0d 100644 --- a/drivers/isdn/hisax/q931.c +++ b/drivers/isdn/hisax/q931.c @@ -1402,12 +1402,12 @@ dlogframe(struct IsdnCardState *cs, stru } /* No, locate it in the table */ if (cset == 0) { - for (i = 0; i < IESIZE; i++) + for (i = 0; i < IESIZE_NI1; i++) if (*buf == ielist_ni1[i].nr) break; /* When not found, give appropriate msg */ - if (i != IESIZE) { + if (i != IESIZE_NI1) { dp += sprintf(dp, " %s\n", ielist_ni1[i].descr); dp += ielist_ni1[i].f(dp, buf); } else diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 22759c0..b26e509 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -933,7 +933,7 @@ #endif count_put = count_pull; if(count_put > 1) tty_insert_flip_string(tty, skb->data, count_put - 1); - last = skb->data[count_put] - 1; + last = skb->data[count_put - 1]; len -= count_put; #ifdef CONFIG_ISDN_AUDIO } @@ -1177,9 +1177,8 @@ isdn_write(struct file *file, const char goto out; } chidx = isdn_minor2chan(minor); - while (isdn_writebuf_stub(drvidx, chidx, buf, count) != count) + while ((retval = isdn_writebuf_stub(drvidx, chidx, buf, count)) == 0) interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]); - retval = count; goto out; } if (minor <= ISDN_MINOR_CTRLMAX) { @@ -1951,9 +1950,10 @@ isdn_writebuf_stub(int drvidx, int chan, struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC); if (!skb) - return 0; + return -ENOMEM; skb_reserve(skb, hl); - copy_from_user(skb_put(skb, len), buf, len); + if (copy_from_user(skb_put(skb, len), buf, len)) + return -EFAULT; ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb); if (ret <= 0) dev_kfree_skb(skb); diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c index f4f7122..57c4ab9 100644 --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c @@ -97,6 +97,7 @@ int sc_ioctl(int card, scs_ioctl *data) case SCIOCSTART: { + kfree(rcvmsg); pr_debug("%s: SCIOSTART: ioctl received\n", sc_adapter[card]->devicename); if(sc_adapter[card]->EngineUp) { diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 6265062..9650998 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -63,6 +63,12 @@ config LEDS_S3C24XX This option enables support for LEDs connected to GPIO lines on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440. +config LEDS_AMS_DELTA + tristate "LED Support for the Amstrad Delta (E3)" + depends LEDS_CLASS && MACH_AMS_DELTA + help + This option enables support for the LEDs on Amstrad Delta (E3). + comment "LED Triggers" config LEDS_TRIGGERS @@ -87,5 +93,14 @@ config LEDS_TRIGGER_IDE_DISK This allows LEDs to be controlled by IDE disk activity. If unsure, say Y. +config LEDS_TRIGGER_HEARTBEAT + tristate "LED Heartbeat Trigger" + depends LEDS_TRIGGERS + help + This allows LEDs to be controlled by a CPU load average. + The flash frequency is a hyperbolic function of the 1-minute + load average. + If unsure, say Y. + endmenu diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 40f0426..88d3b6e 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -11,7 +11,9 @@ obj-$(CONFIG_LEDS_SPITZ) += leds-spitz. obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o +obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o +obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c new file mode 100644 index 0000000..e9f0611 --- /dev/null +++ b/drivers/leds/leds-ams-delta.c @@ -0,0 +1,162 @@ +/* + * LEDs driver for Amstrad Delta (E3) + * + * Copyright (C) 2006 Jonathan McDowell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +/* + * Our context + */ +struct ams_delta_led { + struct led_classdev cdev; + u8 bitmask; +}; + +static void ams_delta_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct ams_delta_led *led_dev = + container_of(led_cdev, struct ams_delta_led, cdev); + + if (value) + ams_delta_latch1_write(led_dev->bitmask, led_dev->bitmask); + else + ams_delta_latch1_write(led_dev->bitmask, 0); +} + +static struct ams_delta_led ams_delta_leds[] = { + { + .cdev = { + .name = "ams-delta:camera", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_CAMERA, + }, + { + .cdev = { + .name = "ams-delta:advert", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_ADVERT, + }, + { + .cdev = { + .name = "ams-delta:email", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_EMAIL, + }, + { + .cdev = { + .name = "ams-delta:handsfree", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_HANDSFREE, + }, + { + .cdev = { + .name = "ams-delta:voicemail", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_VOICEMAIL, + }, + { + .cdev = { + .name = "ams-delta:voice", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_VOICE, + }, +}; + +#ifdef CONFIG_PM +static int ams_delta_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++) + led_classdev_suspend(&ams_delta_leds[i].cdev); + + return 0; +} + +static int ams_delta_led_resume(struct platform_device *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++) + led_classdev_resume(&ams_delta_leds[i].cdev); + + return 0; +} +#else +#define ams_delta_led_suspend NULL +#define ams_delta_led_resume NULL +#endif + +static int ams_delta_led_probe(struct platform_device *pdev) +{ + int i; + int ret; + + for (i = ret = 0; ret >= 0 && i < ARRAY_SIZE(ams_delta_leds); i++) { + ret = led_classdev_register(&pdev->dev, + &ams_delta_leds[i].cdev); + } + + if (ret < 0 && i > 1) { + for (i = i - 2; i >= 0; i--) + led_classdev_unregister(&ams_delta_leds[i].cdev); + } + + return ret; +} + +static int ams_delta_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = ARRAY_SIZE(ams_delta_leds) - 1; i >= 0; i--) + led_classdev_unregister(&ams_delta_leds[i].cdev); + + return 0; +} + +static struct platform_driver ams_delta_led_driver = { + .probe = ams_delta_led_probe, + .remove = ams_delta_led_remove, + .suspend = ams_delta_led_suspend, + .resume = ams_delta_led_resume, + .driver = { + .name = "ams-delta-led", + }, +}; + +static int __init ams_delta_led_init(void) +{ + return platform_driver_register(&ams_delta_led_driver); +} + +static void __exit ams_delta_led_exit(void) +{ + return platform_driver_unregister(&ams_delta_led_driver); +} + +module_init(ams_delta_led_init); +module_exit(ams_delta_led_exit); + +MODULE_AUTHOR("Jonathan McDowell "); +MODULE_DESCRIPTION("Amstrad Delta LED driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c index 749a86c..8419e29 100644 --- a/drivers/leds/leds-locomo.c +++ b/drivers/leds/leds-locomo.c @@ -45,11 +45,13 @@ static void locomoled_brightness_set1(st static struct led_classdev locomo_led0 = { .name = "locomo:amber", + .default_trigger = "sharpsl-charge", .brightness_set = locomoled_brightness_set0, }; static struct led_classdev locomo_led1 = { .name = "locomo:green", + .default_trigger = "nand-disk", .brightness_set = locomoled_brightness_set1, }; diff --git a/drivers/leds/ledtrig-heartbeat.c b/drivers/leds/ledtrig-heartbeat.c new file mode 100644 index 0000000..4bf8cec --- /dev/null +++ b/drivers/leds/ledtrig-heartbeat.c @@ -0,0 +1,118 @@ +/* + * LED Heartbeat Trigger + * + * Copyright (C) 2006 Atsushi Nemoto + * + * Based on Richard Purdie's ledtrig-timer.c and some arch's + * CONFIG_HEARTBEAT code. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include +#include "leds.h" + +struct heartbeat_trig_data { + unsigned int phase; + unsigned int period; + struct timer_list timer; +}; + +static void led_heartbeat_function(unsigned long data) +{ + struct led_classdev *led_cdev = (struct led_classdev *) data; + struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + unsigned long brightness = LED_OFF; + unsigned long delay = 0; + + /* acts like an actual heart beat -- ie thump-thump-pause... */ + switch (heartbeat_data->phase) { + case 0: + /* + * The hyperbolic function below modifies the + * heartbeat period length in dependency of the + * current (1min) load. It goes through the points + * f(0)=1260, f(1)=860, f(5)=510, f(inf)->300. + */ + heartbeat_data->period = 300 + + (6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT)); + heartbeat_data->period = + msecs_to_jiffies(heartbeat_data->period); + delay = msecs_to_jiffies(70); + heartbeat_data->phase++; + brightness = LED_FULL; + break; + case 1: + delay = heartbeat_data->period / 4 - msecs_to_jiffies(70); + heartbeat_data->phase++; + break; + case 2: + delay = msecs_to_jiffies(70); + heartbeat_data->phase++; + brightness = LED_FULL; + break; + default: + delay = heartbeat_data->period - heartbeat_data->period / 4 - + msecs_to_jiffies(70); + heartbeat_data->phase = 0; + break; + } + + led_set_brightness(led_cdev, brightness); + mod_timer(&heartbeat_data->timer, jiffies + delay); +} + +static void heartbeat_trig_activate(struct led_classdev *led_cdev) +{ + struct heartbeat_trig_data *heartbeat_data; + + heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); + if (!heartbeat_data) + return; + + led_cdev->trigger_data = heartbeat_data; + setup_timer(&heartbeat_data->timer, + led_heartbeat_function, (unsigned long) led_cdev); + heartbeat_data->phase = 0; + led_heartbeat_function(heartbeat_data->timer.data); +} + +static void heartbeat_trig_deactivate(struct led_classdev *led_cdev) +{ + struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + + if (heartbeat_data) { + del_timer_sync(&heartbeat_data->timer); + kfree(heartbeat_data); + } +} + +static struct led_trigger heartbeat_led_trigger = { + .name = "heartbeat", + .activate = heartbeat_trig_activate, + .deactivate = heartbeat_trig_deactivate, +}; + +static int __init heartbeat_trig_init(void) +{ + return led_trigger_register(&heartbeat_led_trigger); +} + +static void __exit heartbeat_trig_exit(void) +{ + led_trigger_unregister(&heartbeat_led_trigger); +} + +module_init(heartbeat_trig_init); +module_exit(heartbeat_trig_exit); + +MODULE_AUTHOR("Atsushi Nemoto "); +MODULE_DESCRIPTION("Heartbeat LED trigger"); +MODULE_LICENSE("GPL"); diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 12ad462..37cd6ee 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig @@ -99,17 +99,22 @@ config PMAC_MEDIABAY devices are not fully supported in the bay as I never had one to try with -# made a separate option since backlight may end up beeing used -# on non-powerbook machines (but only on PMU based ones AFAIK) config PMAC_BACKLIGHT bool "Backlight control for LCD screens" depends on ADB_PMU && (BROKEN || !PPC64) help - Say Y here to build in code to manage the LCD backlight on a - Macintosh PowerBook. With this code, the backlight will be turned - on and off appropriately on power-management and lid-open/lid-closed - events; also, the PowerBook button device will be enabled so you can - change the screen brightness. + Say Y here to enable Macintosh specific extensions of the generic + backlight code. With this enabled, the brightness keys on older + PowerBooks will be enabled so you can change the screen brightness. + Newer models should use an userspace daemon like pbbuttonsd. + +config PMAC_BACKLIGHT_LEGACY + bool "Provide legacy ioctl's on /dev/pmu for the backlight" + depends on PMAC_BACKLIGHT && (BROKEN || !PPC64) + help + Say Y if you want to enable legacy ioctl's on /dev/pmu. This is for + programs which use this old interface. New and updated programs + should use the backlight classes in sysfs. config ADB_MACIO bool "Include MacIO (CHRP) ADB driver" @@ -171,6 +176,7 @@ config THERM_PM72 config WINDFARM tristate "New PowerMac thermal control infrastructure" + depends on PPC config WINDFARM_PM81 tristate "Support for thermal management on iMac G5" diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index 6081acd..45a268f 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile @@ -11,7 +11,8 @@ obj-$(CONFIG_MAC_EMUMOUSEBTN) += mac_hid obj-$(CONFIG_INPUT_ADBHID) += adbhid.o obj-$(CONFIG_ANSLCD) += ans-lcd.o -obj-$(CONFIG_ADB_PMU) += via-pmu.o +obj-$(CONFIG_ADB_PMU) += via-pmu.o via-pmu-event.o +obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o obj-$(CONFIG_ADB_CUDA) += via-cuda.o obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o obj-$(CONFIG_PMAC_SMU) += smu.o diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 394334e..cbfbbe2 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -179,7 +179,7 @@ u8 adb_to_linux_keycodes[128] = { /* 0x65 */ KEY_F9, /* 67 */ /* 0x66 */ KEY_HANJA, /* 123 */ /* 0x67 */ KEY_F11, /* 87 */ - /* 0x68 */ KEY_HANGUEL, /* 122 */ + /* 0x68 */ KEY_HANGEUL, /* 122 */ /* 0x69 */ KEY_SYSRQ, /* 99 */ /* 0x6a */ 0, /* 0x6b */ KEY_SCROLLLOCK, /* 70 */ @@ -503,9 +503,7 @@ adbhid_buttons_input(unsigned char *data case 0x1f: /* Powerbook button device */ { int down = (data[1] == (data[1] & 0xf)); -#ifdef CONFIG_PMAC_BACKLIGHT - int backlight = get_backlight_level(); -#endif + /* * XXX: Where is the contrast control for the passive? * -- Cort @@ -530,29 +528,17 @@ #endif case 0xa: /* brightness decrease */ #ifdef CONFIG_PMAC_BACKLIGHT - if (!disable_kernel_backlight) { - if (down && backlight >= 0) { - if (backlight > BACKLIGHT_OFF) - set_backlight_level(backlight-1); - else - set_backlight_level(BACKLIGHT_OFF); - } - } -#endif /* CONFIG_PMAC_BACKLIGHT */ + if (!disable_kernel_backlight && down) + pmac_backlight_key_down(); +#endif input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); break; case 0x9: /* brightness increase */ #ifdef CONFIG_PMAC_BACKLIGHT - if (!disable_kernel_backlight) { - if (down && backlight >= 0) { - if (backlight < BACKLIGHT_MAX) - set_backlight_level(backlight+1); - else - set_backlight_level(BACKLIGHT_MAX); - } - } -#endif /* CONFIG_PMAC_BACKLIGHT */ + if (!disable_kernel_backlight && down) + pmac_backlight_key_up(); +#endif input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down); break; diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c new file mode 100644 index 0000000..b42d05f --- /dev/null +++ b/drivers/macintosh/via-pmu-backlight.c @@ -0,0 +1,150 @@ +/* + * Backlight code for via-pmu + * + * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi. + * Copyright (C) 2001-2002 Benjamin Herrenschmidt + * Copyright (C) 2006 Michael Hanselmann + * + */ + +#include +#include +#include +#include +#include + +#define MAX_PMU_LEVEL 0xFF + +static struct device_node *vias; +static struct backlight_properties pmu_backlight_data; + +static int pmu_backlight_get_level_brightness(struct fb_info *info, + int level) +{ + int pmulevel; + + /* Get and convert the value */ + mutex_lock(&info->bl_mutex); + pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; + mutex_unlock(&info->bl_mutex); + + if (pmulevel < 0) + pmulevel = 0; + else if (pmulevel > MAX_PMU_LEVEL) + pmulevel = MAX_PMU_LEVEL; + + return pmulevel; +} + +static int pmu_backlight_update_status(struct backlight_device *bd) +{ + struct fb_info *info = class_get_devdata(&bd->class_dev); + struct adb_request req; + int pmulevel, level = bd->props->brightness; + + if (vias == NULL) + return -ENODEV; + + if (bd->props->power != FB_BLANK_UNBLANK || + bd->props->fb_blank != FB_BLANK_UNBLANK) + level = 0; + + pmulevel = pmu_backlight_get_level_brightness(info, level); + + pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); + pmu_wait_complete(&req); + + pmu_request(&req, NULL, 2, PMU_POWER_CTRL, + PMU_POW_BACKLIGHT | (level > 0 ? PMU_POW_ON : PMU_POW_OFF)); + pmu_wait_complete(&req); + + return 0; +} + +static int pmu_backlight_get_brightness(struct backlight_device *bd) +{ + return bd->props->brightness; +} + +static struct backlight_properties pmu_backlight_data = { + .owner = THIS_MODULE, + .get_brightness = pmu_backlight_get_brightness, + .update_status = pmu_backlight_update_status, + .max_brightness = (FB_BACKLIGHT_LEVELS - 1), +}; + +void __init pmu_backlight_init(struct device_node *in_vias) +{ + struct backlight_device *bd; + struct fb_info *info; + char name[10]; + int level, autosave; + + vias = in_vias; + + /* Special case for the old PowerBook since I can't test on it */ + autosave = + machine_is_compatible("AAPL,3400/2400") || + machine_is_compatible("AAPL,3500"); + + if (!autosave && + !pmac_has_backlight_type("pmu") && + !machine_is_compatible("AAPL,PowerBook1998") && + !machine_is_compatible("PowerBook1,1")) + return; + + /* Actually, this is a hack, but I don't know of a better way + * to get the first framebuffer device. + */ + info = registered_fb[0]; + if (!info) { + printk("pmubl: No framebuffer found\n"); + goto error; + } + + snprintf(name, sizeof(name), "pmubl%d", info->node); + + bd = backlight_device_register(name, info, &pmu_backlight_data); + if (IS_ERR(bd)) { + printk("pmubl: Backlight registration failed\n"); + goto error; + } + + mutex_lock(&info->bl_mutex); + info->bl_dev = bd; + fb_bl_default_curve(info, 0x7F, 0x46, 0x0E); + mutex_unlock(&info->bl_mutex); + + level = pmu_backlight_data.max_brightness; + + if (autosave) { + /* read autosaved value if available */ + struct adb_request req; + pmu_request(&req, NULL, 2, 0xd9, 0); + pmu_wait_complete(&req); + + mutex_lock(&info->bl_mutex); + level = pmac_backlight_curve_lookup(info, + (req.reply[0] >> 4) * + pmu_backlight_data.max_brightness / 15); + mutex_unlock(&info->bl_mutex); + } + + up(&bd->sem); + bd->props->brightness = level; + bd->props->power = FB_BLANK_UNBLANK; + bd->props->update_status(bd); + down(&bd->sem); + + mutex_lock(&pmac_backlight_mutex); + if (!pmac_backlight) + pmac_backlight = bd; + mutex_unlock(&pmac_backlight_mutex); + + printk("pmubl: Backlight initialized (%s)\n", name); + + return; + +error: + return; +} diff --git a/drivers/macintosh/via-pmu-event.c b/drivers/macintosh/via-pmu-event.c new file mode 100644 index 0000000..25cd565 --- /dev/null +++ b/drivers/macintosh/via-pmu-event.c @@ -0,0 +1,80 @@ +/* + * via-pmu event device for reporting some events that come through the PMU + * + * Copyright 2006 Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include "via-pmu-event.h" + +static struct input_dev *pmu_input_dev; + +static int __init via_pmu_event_init(void) +{ + int err; + + /* do other models report button/lid status? */ + if (pmu_get_model() != PMU_KEYLARGO_BASED) + return -ENODEV; + + pmu_input_dev = input_allocate_device(); + if (!pmu_input_dev) + return -ENOMEM; + + pmu_input_dev->name = "PMU"; + pmu_input_dev->id.bustype = BUS_HOST; + pmu_input_dev->id.vendor = 0x0001; + pmu_input_dev->id.product = 0x0001; + pmu_input_dev->id.version = 0x0100; + + set_bit(EV_KEY, pmu_input_dev->evbit); + set_bit(EV_SW, pmu_input_dev->evbit); + set_bit(KEY_POWER, pmu_input_dev->keybit); + set_bit(SW_LID, pmu_input_dev->swbit); + + err = input_register_device(pmu_input_dev); + if (err) + input_free_device(pmu_input_dev); + return err; +} + +void via_pmu_event(int key, int down) +{ + + if (unlikely(!pmu_input_dev)) + return; + + switch (key) { + case PMU_EVT_POWER: + input_report_key(pmu_input_dev, KEY_POWER, down); + break; + case PMU_EVT_LID: + input_report_switch(pmu_input_dev, SW_LID, down); + break; + default: + /* no such key handled */ + return; + } + + input_sync(pmu_input_dev); +} + +late_initcall(via_pmu_event_init); diff --git a/drivers/macintosh/via-pmu-event.h b/drivers/macintosh/via-pmu-event.h new file mode 100644 index 0000000..72c54de --- /dev/null +++ b/drivers/macintosh/via-pmu-event.h @@ -0,0 +1,8 @@ +#ifndef __VIA_PMU_EVENT_H +#define __VIA_PMU_EVENT_H + +#define PMU_EVT_POWER 0 +#define PMU_EVT_LID 1 +extern void via_pmu_event(int key, int down); + +#endif /* __VIA_PMU_EVENT_H */ diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 0b5ff55..1ab4f16 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -69,6 +69,8 @@ #ifdef CONFIG_PPC32 #include #endif +#include "via-pmu-event.h" + /* Some compile options */ #undef SUSPEND_USES_PMU #define DEBUG_SLEEP @@ -144,7 +146,6 @@ static int data_index; static int data_len; static volatile int adb_int_pending; static volatile int disable_poll; -static struct adb_request bright_req_1, bright_req_2; static struct device_node *vias; static int pmu_kind = PMU_UNKNOWN; static int pmu_fully_inited = 0; @@ -161,7 +162,7 @@ static int drop_interrupts; #if defined(CONFIG_PM) && defined(CONFIG_PPC32) static int option_lid_wakeup = 1; #endif /* CONFIG_PM && CONFIG_PPC32 */ -#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT) +#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY) static int sleep_in_progress; #endif static unsigned long async_req_locks; @@ -208,10 +209,6 @@ static int proc_get_info(char *page, cha int count, int *eof, void *data); static int proc_get_irqstats(char *page, char **start, off_t off, int count, int *eof, void *data); -#ifdef CONFIG_PMAC_BACKLIGHT -static int pmu_set_backlight_level(int level, void* data); -static int pmu_set_backlight_enable(int on, int level, void* data); -#endif /* CONFIG_PMAC_BACKLIGHT */ static void pmu_pass_intr(unsigned char *data, int len); static int proc_get_batt(char *page, char **start, off_t off, int count, int *eof, void *data); @@ -292,13 +289,6 @@ static char *pbook_type[] = { "Core99" }; -#ifdef CONFIG_PMAC_BACKLIGHT -static struct backlight_controller pmu_backlight_controller = { - pmu_set_backlight_enable, - pmu_set_backlight_level -}; -#endif /* CONFIG_PMAC_BACKLIGHT */ - int __init find_via_pmu(void) { u64 taddr; @@ -417,8 +407,6 @@ static int __init via_pmu_start(void) if (vias == NULL) return -ENODEV; - bright_req_1.complete = 1; - bright_req_2.complete = 1; batt_req.complete = 1; #ifndef CONFIG_PPC_MERGE @@ -483,9 +471,9 @@ static int __init via_pmu_dev_init(void) return -ENODEV; #ifdef CONFIG_PMAC_BACKLIGHT - /* Enable backlight */ - register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); -#endif /* CONFIG_PMAC_BACKLIGHT */ + /* Initialize backlight */ + pmu_backlight_init(vias); +#endif #ifdef CONFIG_PPC32 if (machine_is_compatible("AAPL,3400/2400") || @@ -1424,7 +1412,7 @@ #ifdef CONFIG_PMAC_BACKLIGHT #ifdef CONFIG_INPUT_ADBHID if (!disable_kernel_backlight) #endif /* CONFIG_INPUT_ADBHID */ - set_backlight_level(data[1] >> 4); + pmac_backlight_set_legacy_brightness(data[1] >> 4); #endif /* CONFIG_PMAC_BACKLIGHT */ } /* Tick interrupt */ @@ -1441,6 +1429,12 @@ #endif /* CONFIG_PMAC_BACKLIGHT */ if (pmu_battery_count) query_battery_state(); pmu_pass_intr(data, len); + /* len == 6 is probably a bad check. But how do I + * know what PMU versions send what events here? */ + if (len == 6) { + via_pmu_event(PMU_EVT_POWER, !!(data[1]&8)); + via_pmu_event(PMU_EVT_LID, data[1]&1); + } } else { pmu_pass_intr(data, len); } @@ -1674,61 +1668,6 @@ gpio1_interrupt(int irq, void *arg, stru return IRQ_NONE; } -#ifdef CONFIG_PMAC_BACKLIGHT -static int backlight_to_bright[] = { - 0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e, - 0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e -}; - -static int -pmu_set_backlight_enable(int on, int level, void* data) -{ - struct adb_request req; - - if (vias == NULL) - return -ENODEV; - - if (on) { - pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, - backlight_to_bright[level]); - pmu_wait_complete(&req); - } - pmu_request(&req, NULL, 2, PMU_POWER_CTRL, - PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF)); - pmu_wait_complete(&req); - - return 0; -} - -static void -pmu_bright_complete(struct adb_request *req) -{ - if (req == &bright_req_1) - clear_bit(1, &async_req_locks); - if (req == &bright_req_2) - clear_bit(2, &async_req_locks); -} - -static int -pmu_set_backlight_level(int level, void* data) -{ - if (vias == NULL) - return -ENODEV; - - if (test_and_set_bit(1, &async_req_locks)) - return -EAGAIN; - pmu_request(&bright_req_1, pmu_bright_complete, 2, PMU_BACKLIGHT_BRIGHT, - backlight_to_bright[level]); - if (test_and_set_bit(2, &async_req_locks)) - return -EAGAIN; - pmu_request(&bright_req_2, pmu_bright_complete, 2, PMU_POWER_CTRL, - PMU_POW_BACKLIGHT | (level > BACKLIGHT_OFF ? - PMU_POW_ON : PMU_POW_OFF)); - - return 0; -} -#endif /* CONFIG_PMAC_BACKLIGHT */ - void pmu_enable_irled(int on) { @@ -2145,9 +2084,8 @@ pmac_suspend_devices(void) return -EBUSY; } - /* Wait for completion of async backlight requests */ - while (!bright_req_1.complete || !bright_req_2.complete || - !batt_req.complete) + /* Wait for completion of async requests */ + while (!batt_req.complete) pmu_poll(); /* Giveup the lazy FPU & vec so we don't have to back them @@ -2268,7 +2206,7 @@ static int powerbook_sleep_grackle(void) _set_L2CR(save_l2cr); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context.id, current->active_mm->pgd); /* Power things up */ pmu_unlock(); @@ -2366,7 +2304,7 @@ powerbook_sleep_Core99(void) _set_L3CR(save_l3cr); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context.id, current->active_mm->pgd); /* Tell PMU we are ready */ pmu_unlock(); @@ -2678,26 +2616,34 @@ #if defined(CONFIG_PM) && defined(CONFIG return put_user(1, argp); #endif /* CONFIG_PM && CONFIG_PPC32 */ -#ifdef CONFIG_PMAC_BACKLIGHT - /* Backlight should have its own device or go via - * the fbdev - */ +#ifdef CONFIG_PMAC_BACKLIGHT_LEGACY + /* Compatibility ioctl's for backlight */ case PMU_IOC_GET_BACKLIGHT: + { + int brightness; + if (sleep_in_progress) return -EBUSY; - error = get_backlight_level(); - if (error < 0) - return error; - return put_user(error, argp); + + brightness = pmac_backlight_get_legacy_brightness(); + if (brightness < 0) + return brightness; + else + return put_user(brightness, argp); + + } case PMU_IOC_SET_BACKLIGHT: { - __u32 value; + int brightness; + if (sleep_in_progress) return -EBUSY; - error = get_user(value, argp); - if (!error) - error = set_backlight_level(value); - break; + + error = get_user(brightness, argp); + if (error) + return error; + + return pmac_backlight_set_legacy_brightness(brightness); } #ifdef CONFIG_INPUT_ADBHID case PMU_IOC_GRAB_BACKLIGHT: { @@ -2713,7 +2659,7 @@ #ifdef CONFIG_INPUT_ADBHID return 0; } #endif /* CONFIG_INPUT_ADBHID */ -#endif /* CONFIG_PMAC_BACKLIGHT */ +#endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */ case PMU_IOC_GET_MODEL: return put_user(pmu_kind, argp); case PMU_IOC_HAS_ADB: diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index ac25a48..bf869ed 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -90,7 +90,7 @@ config MD_RAID10 depends on BLK_DEV_MD && EXPERIMENTAL ---help--- RAID-10 provides a combination of striping (RAID-0) and - mirroring (RAID-1) with easier configuration and more flexable + mirroring (RAID-1) with easier configuration and more flexible layout. Unlike RAID-0, but like RAID-1, RAID-10 requires all devices to be the same size (or at least, only as much as the smallest device @@ -104,8 +104,8 @@ config MD_RAID10 If unsure, say Y. -config MD_RAID5 - tristate "RAID-4/RAID-5 mode" +config MD_RAID456 + tristate "RAID-4/RAID-5/RAID-6 mode" depends on BLK_DEV_MD ---help--- A RAID-5 set of N drives with a capacity of C MB per drive provides @@ -116,20 +116,28 @@ config MD_RAID5 while a RAID-5 set distributes the parity across the drives in one of the available parity distribution methods. + A RAID-6 set of N drives with a capacity of C MB per drive + provides the capacity of C * (N - 2) MB, and protects + against a failure of any two drives. For a given sector + (row) number, (N - 2) drives contain data sectors, and two + drives contains two independent redundancy syndromes. Like + RAID-5, RAID-6 distributes the syndromes across the drives + in one of the available parity distribution methods. + Information about Software RAID on Linux is contained in the Software-RAID mini-HOWTO, available from . There you will also learn where to get the supporting user space utilities raidtools. - If you want to use such a RAID-4/RAID-5 set, say Y. To + If you want to use such a RAID-4/RAID-5/RAID-6 set, say Y. To compile this code as a module, choose M here: the module - will be called raid5. + will be called raid456. If unsure, say Y. config MD_RAID5_RESHAPE bool "Support adding drives to a raid-5 array (experimental)" - depends on MD_RAID5 && EXPERIMENTAL + depends on MD_RAID456 && EXPERIMENTAL ---help--- A RAID-5 set can be expanded by adding extra drives. This requires "restriping" the array which means (almost) every @@ -139,7 +147,7 @@ config MD_RAID5_RESHAPE is online. However it is still EXPERIMENTAL code. It should work, but please be sure that you have backups. - You will need mdadm verion 2.4.1 or later to use this + You will need mdadm version 2.4.1 or later to use this feature safely. During the early stage of reshape there is a critical section where live data is being over-written. A crash during this time needs extra care for recovery. The @@ -154,28 +162,6 @@ config MD_RAID5_RESHAPE There should be enough spares already present to make the new array workable. -config MD_RAID6 - tristate "RAID-6 mode" - depends on BLK_DEV_MD - ---help--- - A RAID-6 set of N drives with a capacity of C MB per drive - provides the capacity of C * (N - 2) MB, and protects - against a failure of any two drives. For a given sector - (row) number, (N - 2) drives contain data sectors, and two - drives contains two independent redundancy syndromes. Like - RAID-5, RAID-6 distributes the syndromes across the drives - in one of the available parity distribution methods. - - RAID-6 requires mdadm-1.5.0 or later, available at: - - ftp://ftp.kernel.org/pub/linux/utils/raid/mdadm/ - - If you want to use such a RAID-6 set, say Y. To compile - this code as a module, choose M here: the module will be - called raid6. - - If unsure, say Y. - config MD_MULTIPATH tristate "Multipath I/O support" depends on BLK_DEV_MD @@ -235,7 +221,7 @@ config DM_SNAPSHOT tristate "Snapshot target (EXPERIMENTAL)" depends on BLK_DEV_DM && EXPERIMENTAL ---help--- - Allow volume managers to take writeable snapshots of a device. + Allow volume managers to take writable snapshots of a device. config DM_MIRROR tristate "Mirror target (EXPERIMENTAL)" diff --git a/drivers/md/Makefile b/drivers/md/Makefile index d3efedf..34957a6 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile @@ -8,7 +8,7 @@ dm-multipath-objs := dm-hw-handler.o dm- dm-snapshot-objs := dm-snap.o dm-exception-store.o dm-mirror-objs := dm-log.o dm-raid1.o md-mod-objs := md.o bitmap.o -raid6-objs := raid6main.o raid6algos.o raid6recov.o raid6tables.o \ +raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \ raid6int1.o raid6int2.o raid6int4.o \ raid6int8.o raid6int16.o raid6int32.o \ raid6altivec1.o raid6altivec2.o raid6altivec4.o \ @@ -25,8 +25,7 @@ obj-$(CONFIG_MD_LINEAR) += linear.o obj-$(CONFIG_MD_RAID0) += raid0.o obj-$(CONFIG_MD_RAID1) += raid1.o obj-$(CONFIG_MD_RAID10) += raid10.o -obj-$(CONFIG_MD_RAID5) += raid5.o xor.o -obj-$(CONFIG_MD_RAID6) += raid6.o xor.o +obj-$(CONFIG_MD_RAID456) += raid456.o xor.o obj-$(CONFIG_MD_MULTIPATH) += multipath.o obj-$(CONFIG_MD_FAULTY) += faulty.o obj-$(CONFIG_BLK_DEV_MD) += md-mod.o diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index f8ffaee..ebbd2d8 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -7,7 +7,6 @@ * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.: * - added disk storage for bitmap * - changes to allow various bitmap chunk sizes - * - added bitmap daemon (to asynchronously clear bitmap bits from disk) */ /* @@ -15,9 +14,6 @@ * * flush after percent set rather than just time based. (maybe both). * wait if count gets too high, wake when it drops to half. - * allow bitmap to be mirrored with superblock (before or after...) - * allow hot-add to re-instate a current device. - * allow hot-add of bitmap after quiessing device */ #include @@ -73,24 +69,6 @@ static inline char * bmname(struct bitma /* - * test if the bitmap is active - */ -int bitmap_active(struct bitmap *bitmap) -{ - unsigned long flags; - int res = 0; - - if (!bitmap) - return res; - spin_lock_irqsave(&bitmap->lock, flags); - res = bitmap->flags & BITMAP_ACTIVE; - spin_unlock_irqrestore(&bitmap->lock, flags); - return res; -} - -#define WRITE_POOL_SIZE 256 - -/* * just a placeholder - calls kmalloc for bitmap pages */ static unsigned char *bitmap_alloc_page(struct bitmap *bitmap) @@ -269,6 +247,8 @@ static struct page *read_sb_page(mddev_t if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) { page->index = index; + attach_page_buffers(page, NULL); /* so that free_buffer will + * quietly no-op */ return page; } } @@ -300,77 +280,132 @@ static int write_sb_page(mddev_t *mddev, */ static int write_page(struct bitmap *bitmap, struct page *page, int wait) { - int ret = -ENOMEM; + struct buffer_head *bh; if (bitmap->file == NULL) return write_sb_page(bitmap->mddev, bitmap->offset, page, wait); - flush_dcache_page(page); /* make sure visible to anyone reading the file */ + bh = page_buffers(page); - if (wait) - lock_page(page); - else { - if (TestSetPageLocked(page)) - return -EAGAIN; /* already locked */ - if (PageWriteback(page)) { - unlock_page(page); - return -EAGAIN; - } + while (bh && bh->b_blocknr) { + atomic_inc(&bitmap->pending_writes); + set_buffer_locked(bh); + set_buffer_mapped(bh); + submit_bh(WRITE, bh); + bh = bh->b_this_page; } - ret = page->mapping->a_ops->prepare_write(bitmap->file, page, 0, PAGE_SIZE); - if (!ret) - ret = page->mapping->a_ops->commit_write(bitmap->file, page, 0, - PAGE_SIZE); - if (ret) { - unlock_page(page); - return ret; + if (wait) { + wait_event(bitmap->write_wait, + atomic_read(&bitmap->pending_writes)==0); + return (bitmap->flags & BITMAP_WRITE_ERROR) ? -EIO : 0; } + return 0; +} - set_page_dirty(page); /* force it to be written out */ - - if (!wait) { - /* add to list to be waited for by daemon */ - struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO); - item->page = page; - get_page(page); - spin_lock(&bitmap->write_lock); - list_add(&item->list, &bitmap->complete_pages); - spin_unlock(&bitmap->write_lock); - md_wakeup_thread(bitmap->writeback_daemon); +static void end_bitmap_write(struct buffer_head *bh, int uptodate) +{ + struct bitmap *bitmap = bh->b_private; + unsigned long flags; + + if (!uptodate) { + spin_lock_irqsave(&bitmap->lock, flags); + bitmap->flags |= BITMAP_WRITE_ERROR; + spin_unlock_irqrestore(&bitmap->lock, flags); + } + if (atomic_dec_and_test(&bitmap->pending_writes)) + wake_up(&bitmap->write_wait); +} + +/* copied from buffer.c */ +static void +__clear_page_buffers(struct page *page) +{ + ClearPagePrivate(page); + set_page_private(page, 0); + page_cache_release(page); +} +static void free_buffers(struct page *page) +{ + struct buffer_head *bh = page_buffers(page); + + while (bh) { + struct buffer_head *next = bh->b_this_page; + free_buffer_head(bh); + bh = next; } - return write_one_page(page, wait); + __clear_page_buffers(page); + put_page(page); } -/* read a page from a file, pinning it into cache, and return bytes_read */ +/* read a page from a file. + * We both read the page, and attach buffers to the page to record the + * address of each block (using bmap). These addresses will be used + * to write the block later, completely bypassing the filesystem. + * This usage is similar to how swap files are handled, and allows us + * to write to a file with no concerns of memory allocation failing. + */ static struct page *read_page(struct file *file, unsigned long index, - unsigned long *bytes_read) + struct bitmap *bitmap, + unsigned long count) { - struct inode *inode = file->f_mapping->host; struct page *page = NULL; - loff_t isize = i_size_read(inode); - unsigned long end_index = isize >> PAGE_SHIFT; + struct inode *inode = file->f_dentry->d_inode; + struct buffer_head *bh; + sector_t block; PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_SIZE, (unsigned long long)index << PAGE_SHIFT); - page = read_cache_page(inode->i_mapping, index, - (filler_t *)inode->i_mapping->a_ops->readpage, file); + page = alloc_page(GFP_KERNEL); + if (!page) + page = ERR_PTR(-ENOMEM); if (IS_ERR(page)) goto out; - wait_on_page_locked(page); - if (!PageUptodate(page) || PageError(page)) { + + bh = alloc_page_buffers(page, 1<i_blkbits, 0); + if (!bh) { put_page(page); - page = ERR_PTR(-EIO); + page = ERR_PTR(-ENOMEM); goto out; } + attach_page_buffers(page, bh); + block = index << (PAGE_SHIFT - inode->i_blkbits); + while (bh) { + if (count == 0) + bh->b_blocknr = 0; + else { + bh->b_blocknr = bmap(inode, block); + if (bh->b_blocknr == 0) { + /* Cannot use this file! */ + free_buffers(page); + page = ERR_PTR(-EINVAL); + goto out; + } + bh->b_bdev = inode->i_sb->s_bdev; + if (count < (1<i_blkbits)) + count = 0; + else + count -= (1<i_blkbits); + + bh->b_end_io = end_bitmap_write; + bh->b_private = bitmap; + atomic_inc(&bitmap->pending_writes); + set_buffer_locked(bh); + set_buffer_mapped(bh); + submit_bh(READ, bh); + } + block++; + bh = bh->b_this_page; + } + page->index = index; - if (index > end_index) /* we have read beyond EOF */ - *bytes_read = 0; - else if (index == end_index) /* possible short read */ - *bytes_read = isize & ~PAGE_MASK; - else - *bytes_read = PAGE_SIZE; /* got a full page */ + wait_event(bitmap->write_wait, + atomic_read(&bitmap->pending_writes)==0); + if (bitmap->flags & BITMAP_WRITE_ERROR) { + free_buffers(page); + page = ERR_PTR(-EIO); + } out: if (IS_ERR(page)) printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n", @@ -441,16 +476,14 @@ static int bitmap_read_sb(struct bitmap char *reason = NULL; bitmap_super_t *sb; unsigned long chunksize, daemon_sleep, write_behind; - unsigned long bytes_read; unsigned long long events; int err = -EINVAL; /* page 0 is the superblock, read it... */ if (bitmap->file) - bitmap->sb_page = read_page(bitmap->file, 0, &bytes_read); + bitmap->sb_page = read_page(bitmap->file, 0, bitmap, PAGE_SIZE); else { bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0); - bytes_read = PAGE_SIZE; } if (IS_ERR(bitmap->sb_page)) { err = PTR_ERR(bitmap->sb_page); @@ -460,13 +493,6 @@ static int bitmap_read_sb(struct bitmap sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); - if (bytes_read < sizeof(*sb)) { /* short read */ - printk(KERN_INFO "%s: bitmap file superblock truncated\n", - bmname(bitmap)); - err = -ENOSPC; - goto out; - } - chunksize = le32_to_cpu(sb->chunksize); daemon_sleep = le32_to_cpu(sb->daemon_sleep); write_behind = le32_to_cpu(sb->write_behind); @@ -550,7 +576,6 @@ static void bitmap_mask_state(struct bit spin_unlock_irqrestore(&bitmap->lock, flags); return; } - get_page(bitmap->sb_page); spin_unlock_irqrestore(&bitmap->lock, flags); sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); switch (op) { @@ -561,7 +586,6 @@ static void bitmap_mask_state(struct bit default: BUG(); } kunmap_atomic(sb, KM_USER0); - put_page(bitmap->sb_page); } /* @@ -614,48 +638,17 @@ static void bitmap_file_unmap(struct bit while (pages--) if (map[pages]->index != 0) /* 0 is sb_page, release it below */ - put_page(map[pages]); + free_buffers(map[pages]); kfree(map); kfree(attr); - safe_put_page(sb_page); -} - -static void bitmap_stop_daemon(struct bitmap *bitmap); - -/* dequeue the next item in a page list -- don't call from irq context */ -static struct page_list *dequeue_page(struct bitmap *bitmap) -{ - struct page_list *item = NULL; - struct list_head *head = &bitmap->complete_pages; - - spin_lock(&bitmap->write_lock); - if (list_empty(head)) - goto out; - item = list_entry(head->prev, struct page_list, list); - list_del(head->prev); -out: - spin_unlock(&bitmap->write_lock); - return item; -} - -static void drain_write_queues(struct bitmap *bitmap) -{ - struct page_list *item; - - while ((item = dequeue_page(bitmap))) { - /* don't bother to wait */ - put_page(item->page); - mempool_free(item, bitmap->write_pool); - } - - wake_up(&bitmap->write_wait); + if (sb_page) + free_buffers(sb_page); } static void bitmap_file_put(struct bitmap *bitmap) { struct file *file; - struct inode *inode; unsigned long flags; spin_lock_irqsave(&bitmap->lock, flags); @@ -663,17 +656,14 @@ static void bitmap_file_put(struct bitma bitmap->file = NULL; spin_unlock_irqrestore(&bitmap->lock, flags); - bitmap_stop_daemon(bitmap); - - drain_write_queues(bitmap); - + if (file) + wait_event(bitmap->write_wait, + atomic_read(&bitmap->pending_writes)==0); bitmap_file_unmap(bitmap); if (file) { - inode = file->f_mapping->host; - spin_lock(&inode->i_lock); - atomic_set(&inode->i_writecount, 1); /* allow writes again */ - spin_unlock(&inode->i_lock); + struct inode *inode = file->f_dentry->d_inode; + invalidate_inode_pages(inode->i_mapping); fput(file); } } @@ -708,26 +698,27 @@ static void bitmap_file_kick(struct bitm } enum bitmap_page_attr { - BITMAP_PAGE_DIRTY = 1, // there are set bits that need to be synced - BITMAP_PAGE_CLEAN = 2, // there are bits that might need to be cleared - BITMAP_PAGE_NEEDWRITE=4, // there are cleared bits that need to be synced + BITMAP_PAGE_DIRTY = 0, // there are set bits that need to be synced + BITMAP_PAGE_CLEAN = 1, // there are bits that might need to be cleared + BITMAP_PAGE_NEEDWRITE=2, // there are cleared bits that need to be synced }; static inline void set_page_attr(struct bitmap *bitmap, struct page *page, enum bitmap_page_attr attr) { - bitmap->filemap_attr[page->index] |= attr; + __set_bit((page->index<<2) + attr, bitmap->filemap_attr); } static inline void clear_page_attr(struct bitmap *bitmap, struct page *page, enum bitmap_page_attr attr) { - bitmap->filemap_attr[page->index] &= ~attr; + __clear_bit((page->index<<2) + attr, bitmap->filemap_attr); } -static inline unsigned long get_page_attr(struct bitmap *bitmap, struct page *page) +static inline unsigned long test_page_attr(struct bitmap *bitmap, struct page *page, + enum bitmap_page_attr attr) { - return bitmap->filemap_attr[page->index]; + return test_bit((page->index<<2) + attr, bitmap->filemap_attr); } /* @@ -751,11 +742,6 @@ static void bitmap_file_set_bit(struct b page = filemap_get_page(bitmap, chunk); bit = file_page_offset(chunk); - - /* make sure the page stays cached until it gets written out */ - if (! (get_page_attr(bitmap, page) & BITMAP_PAGE_DIRTY)) - get_page(page); - /* set the bit */ kaddr = kmap_atomic(page, KM_USER0); if (bitmap->flags & BITMAP_HOSTENDIAN) @@ -775,7 +761,8 @@ static void bitmap_file_set_bit(struct b * sync the dirty pages of the bitmap file to disk */ int bitmap_unplug(struct bitmap *bitmap) { - unsigned long i, attr, flags; + unsigned long i, flags; + int dirty, need_write; struct page *page; int wait = 0; int err; @@ -792,35 +779,26 @@ int bitmap_unplug(struct bitmap *bitmap) return 0; } page = bitmap->filemap[i]; - attr = get_page_attr(bitmap, page); + dirty = test_page_attr(bitmap, page, BITMAP_PAGE_DIRTY); + need_write = test_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); clear_page_attr(bitmap, page, BITMAP_PAGE_DIRTY); clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); - if ((attr & BITMAP_PAGE_DIRTY)) + if (dirty) wait = 1; spin_unlock_irqrestore(&bitmap->lock, flags); - if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE)) { + if (dirty | need_write) err = write_page(bitmap, page, 0); - if (err == -EAGAIN) { - if (attr & BITMAP_PAGE_DIRTY) - err = write_page(bitmap, page, 1); - else - err = 0; - } - if (err) - return 1; - } } if (wait) { /* if any writes were performed, we need to wait on them */ - if (bitmap->file) { - spin_lock_irq(&bitmap->write_lock); - wait_event_lock_irq(bitmap->write_wait, - list_empty(&bitmap->complete_pages), bitmap->write_lock, - wake_up_process(bitmap->writeback_daemon->tsk)); - spin_unlock_irq(&bitmap->write_lock); - } else + if (bitmap->file) + wait_event(bitmap->write_wait, + atomic_read(&bitmap->pending_writes)==0); + else md_super_wait(bitmap->mddev); } + if (bitmap->flags & BITMAP_WRITE_ERROR) + bitmap_file_kick(bitmap); return 0; } @@ -842,7 +820,7 @@ static int bitmap_init_from_disk(struct struct page *page = NULL, *oldpage = NULL; unsigned long num_pages, bit_cnt = 0; struct file *file; - unsigned long bytes, offset, dummy; + unsigned long bytes, offset; int outofdate; int ret = -ENOSPC; void *paddr; @@ -879,7 +857,12 @@ #endif if (!bitmap->filemap) goto out; - bitmap->filemap_attr = kzalloc(sizeof(long) * num_pages, GFP_KERNEL); + /* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */ + bitmap->filemap_attr = kzalloc( + (((num_pages*4/8)+sizeof(unsigned long)-1) + /sizeof(unsigned long)) + *sizeof(unsigned long), + GFP_KERNEL); if (!bitmap->filemap_attr) goto out; @@ -890,7 +873,12 @@ #endif index = file_page_index(i); bit = file_page_offset(i); if (index != oldindex) { /* this is a new page, read it in */ + int count; /* unmap the old page, we're done with it */ + if (index == num_pages-1) + count = bytes - index * PAGE_SIZE; + else + count = PAGE_SIZE; if (index == 0) { /* * if we're here then the superblock page @@ -900,7 +888,7 @@ #endif page = bitmap->sb_page; offset = sizeof(bitmap_super_t); } else if (file) { - page = read_page(file, index, &dummy); + page = read_page(file, index, bitmap, count); offset = 0; } else { page = read_sb_page(bitmap->mddev, bitmap->offset, index); @@ -971,12 +959,11 @@ void bitmap_write_all(struct bitmap *bit /* We don't actually write all bitmap blocks here, * just flag them as needing to be written */ + int i; - unsigned long chunks = bitmap->chunks; - unsigned long bytes = (chunks+7)/8 + sizeof(bitmap_super_t); - unsigned long num_pages = (bytes + PAGE_SIZE-1) / PAGE_SIZE; - while (num_pages--) - bitmap->filemap_attr[num_pages] |= BITMAP_PAGE_NEEDWRITE; + for (i=0; i < bitmap->file_pages; i++) + set_page_attr(bitmap, bitmap->filemap[i], + BITMAP_PAGE_NEEDWRITE); } @@ -1007,7 +994,6 @@ int bitmap_daemon_work(struct bitmap *bi struct page *page = NULL, *lastpage = NULL; int err = 0; int blocks; - int attr; void *paddr; if (bitmap == NULL) @@ -1029,43 +1015,34 @@ int bitmap_daemon_work(struct bitmap *bi if (page != lastpage) { /* skip this page unless it's marked as needing cleaning */ - if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) { - if (attr & BITMAP_PAGE_NEEDWRITE) { - get_page(page); + if (!test_page_attr(bitmap, page, BITMAP_PAGE_CLEAN)) { + int need_write = test_page_attr(bitmap, page, + BITMAP_PAGE_NEEDWRITE); + if (need_write) clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); - } + spin_unlock_irqrestore(&bitmap->lock, flags); - if (attr & BITMAP_PAGE_NEEDWRITE) { + if (need_write) { switch (write_page(bitmap, page, 0)) { - case -EAGAIN: - set_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); - break; case 0: break; default: bitmap_file_kick(bitmap); } - put_page(page); } continue; } /* grab the new page, sync and release the old */ - get_page(page); if (lastpage != NULL) { - if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) { + if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) { clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); spin_unlock_irqrestore(&bitmap->lock, flags); err = write_page(bitmap, lastpage, 0); - if (err == -EAGAIN) { - err = 0; - set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); - } } else { set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); spin_unlock_irqrestore(&bitmap->lock, flags); } - put_page(lastpage); if (err) bitmap_file_kick(bitmap); } else @@ -1107,131 +1084,19 @@ int bitmap_daemon_work(struct bitmap *bi /* now sync the final page */ if (lastpage != NULL) { spin_lock_irqsave(&bitmap->lock, flags); - if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) { + if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) { clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); spin_unlock_irqrestore(&bitmap->lock, flags); err = write_page(bitmap, lastpage, 0); - if (err == -EAGAIN) { - set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); - err = 0; - } } else { set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); spin_unlock_irqrestore(&bitmap->lock, flags); } - - put_page(lastpage); } return err; } -static void daemon_exit(struct bitmap *bitmap, mdk_thread_t **daemon) -{ - mdk_thread_t *dmn; - unsigned long flags; - - /* if no one is waiting on us, we'll free the md thread struct - * and exit, otherwise we let the waiter clean things up */ - spin_lock_irqsave(&bitmap->lock, flags); - if ((dmn = *daemon)) { /* no one is waiting, cleanup and exit */ - *daemon = NULL; - spin_unlock_irqrestore(&bitmap->lock, flags); - kfree(dmn); - complete_and_exit(NULL, 0); /* do_exit not exported */ - } - spin_unlock_irqrestore(&bitmap->lock, flags); -} - -static void bitmap_writeback_daemon(mddev_t *mddev) -{ - struct bitmap *bitmap = mddev->bitmap; - struct page *page; - struct page_list *item; - int err = 0; - - if (signal_pending(current)) { - printk(KERN_INFO - "%s: bitmap writeback daemon got signal, exiting...\n", - bmname(bitmap)); - err = -EINTR; - goto out; - } - if (bitmap == NULL) - /* about to be stopped. */ - return; - - PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap)); - /* wait on bitmap page writebacks */ - while ((item = dequeue_page(bitmap))) { - page = item->page; - mempool_free(item, bitmap->write_pool); - PRINTK("wait on page writeback: %p\n", page); - wait_on_page_writeback(page); - PRINTK("finished page writeback: %p\n", page); - - err = PageError(page); - put_page(page); - if (err) { - printk(KERN_WARNING "%s: bitmap file writeback " - "failed (page %lu): %d\n", - bmname(bitmap), page->index, err); - bitmap_file_kick(bitmap); - goto out; - } - } - out: - wake_up(&bitmap->write_wait); - if (err) { - printk(KERN_INFO "%s: bitmap writeback daemon exiting (%d)\n", - bmname(bitmap), err); - daemon_exit(bitmap, &bitmap->writeback_daemon); - } -} - -static mdk_thread_t *bitmap_start_daemon(struct bitmap *bitmap, - void (*func)(mddev_t *), char *name) -{ - mdk_thread_t *daemon; - char namebuf[32]; - -#ifdef INJECT_FATAL_FAULT_2 - daemon = NULL; -#else - sprintf(namebuf, "%%s_%s", name); - daemon = md_register_thread(func, bitmap->mddev, namebuf); -#endif - if (!daemon) { - printk(KERN_ERR "%s: failed to start bitmap daemon\n", - bmname(bitmap)); - return ERR_PTR(-ECHILD); - } - - md_wakeup_thread(daemon); /* start it running */ - - PRINTK("%s: %s daemon (pid %d) started...\n", - bmname(bitmap), name, daemon->tsk->pid); - - return daemon; -} - -static void bitmap_stop_daemon(struct bitmap *bitmap) -{ - /* the daemon can't stop itself... it'll just exit instead... */ - if (bitmap->writeback_daemon && ! IS_ERR(bitmap->writeback_daemon) && - current->pid != bitmap->writeback_daemon->tsk->pid) { - mdk_thread_t *daemon; - unsigned long flags; - - spin_lock_irqsave(&bitmap->lock, flags); - daemon = bitmap->writeback_daemon; - bitmap->writeback_daemon = NULL; - spin_unlock_irqrestore(&bitmap->lock, flags); - if (daemon && ! IS_ERR(daemon)) - md_unregister_thread(daemon); /* destroy the thread */ - } -} - static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, sector_t offset, int *blocks, int create) @@ -1500,8 +1365,6 @@ static void bitmap_free(struct bitmap *b /* free all allocated memory */ - mempool_destroy(bitmap->write_pool); - if (bp) /* deallocate the page memory */ for (k = 0; k < pages; k++) if (bp[k].map && !bp[k].hijacked) @@ -1549,20 +1412,20 @@ int bitmap_create(mddev_t *mddev) return -ENOMEM; spin_lock_init(&bitmap->lock); - bitmap->mddev = mddev; - - spin_lock_init(&bitmap->write_lock); - INIT_LIST_HEAD(&bitmap->complete_pages); + atomic_set(&bitmap->pending_writes, 0); init_waitqueue_head(&bitmap->write_wait); - bitmap->write_pool = mempool_create_kmalloc_pool(WRITE_POOL_SIZE, - sizeof(struct page_list)); - err = -ENOMEM; - if (!bitmap->write_pool) - goto error; + + bitmap->mddev = mddev; bitmap->file = file; bitmap->offset = mddev->bitmap_offset; - if (file) get_file(file); + if (file) { + get_file(file); + do_sync_file_range(file, 0, LLONG_MAX, + SYNC_FILE_RANGE_WAIT_BEFORE | + SYNC_FILE_RANGE_WRITE | + SYNC_FILE_RANGE_WAIT_AFTER); + } /* read superblock from bitmap file (this sets bitmap->chunksize) */ err = bitmap_read_sb(bitmap); if (err) @@ -1594,8 +1457,6 @@ #endif if (!bitmap->bp) goto error; - bitmap->flags |= BITMAP_ACTIVE; - /* now that we have some pages available, initialize the in-memory * bitmap from the on-disk bitmap */ start = 0; @@ -1613,15 +1474,6 @@ #endif mddev->bitmap = bitmap; - if (file) - /* kick off the bitmap writeback daemon */ - bitmap->writeback_daemon = - bitmap_start_daemon(bitmap, - bitmap_writeback_daemon, - "bitmap_wb"); - - if (IS_ERR(bitmap->writeback_daemon)) - return PTR_ERR(bitmap->writeback_daemon); mddev->thread->timeout = bitmap->daemon_sleep * HZ; return bitmap_update_sb(bitmap); @@ -1638,4 +1490,3 @@ EXPORT_SYMBOL(bitmap_start_sync); EXPORT_SYMBOL(bitmap_end_sync); EXPORT_SYMBOL(bitmap_unplug); EXPORT_SYMBOL(bitmap_close_sync); -EXPORT_SYMBOL(bitmap_daemon_work); diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 61a590b..6022ed1 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -20,7 +20,7 @@ #include #include "dm.h" -#define PFX "crypt: " +#define DM_MSG_PREFIX "crypt" /* * per bio private data @@ -125,19 +125,19 @@ static int crypt_iv_essiv_ctr(struct cry u8 *salt; if (opts == NULL) { - ti->error = PFX "Digest algorithm missing for ESSIV mode"; + ti->error = "Digest algorithm missing for ESSIV mode"; return -EINVAL; } /* Hash the cipher key with the given hash algorithm */ hash_tfm = crypto_alloc_tfm(opts, CRYPTO_TFM_REQ_MAY_SLEEP); if (hash_tfm == NULL) { - ti->error = PFX "Error initializing ESSIV hash"; + ti->error = "Error initializing ESSIV hash"; return -EINVAL; } if (crypto_tfm_alg_type(hash_tfm) != CRYPTO_ALG_TYPE_DIGEST) { - ti->error = PFX "Expected digest algorithm for ESSIV hash"; + ti->error = "Expected digest algorithm for ESSIV hash"; crypto_free_tfm(hash_tfm); return -EINVAL; } @@ -145,7 +145,7 @@ static int crypt_iv_essiv_ctr(struct cry saltsize = crypto_tfm_alg_digestsize(hash_tfm); salt = kmalloc(saltsize, GFP_KERNEL); if (salt == NULL) { - ti->error = PFX "Error kmallocing salt storage in ESSIV"; + ti->error = "Error kmallocing salt storage in ESSIV"; crypto_free_tfm(hash_tfm); return -ENOMEM; } @@ -159,20 +159,20 @@ static int crypt_iv_essiv_ctr(struct cry CRYPTO_TFM_MODE_ECB | CRYPTO_TFM_REQ_MAY_SLEEP); if (essiv_tfm == NULL) { - ti->error = PFX "Error allocating crypto tfm for ESSIV"; + ti->error = "Error allocating crypto tfm for ESSIV"; kfree(salt); return -EINVAL; } if (crypto_tfm_alg_blocksize(essiv_tfm) != crypto_tfm_alg_ivsize(cc->tfm)) { - ti->error = PFX "Block size of ESSIV cipher does " + ti->error = "Block size of ESSIV cipher does " "not match IV size of block cipher"; crypto_free_tfm(essiv_tfm); kfree(salt); return -EINVAL; } if (crypto_cipher_setkey(essiv_tfm, salt, saltsize) < 0) { - ti->error = PFX "Failed to set key for ESSIV cipher"; + ti->error = "Failed to set key for ESSIV cipher"; crypto_free_tfm(essiv_tfm); kfree(salt); return -EINVAL; @@ -521,7 +521,7 @@ static int crypt_ctr(struct dm_target *t unsigned long long tmpll; if (argc != 5) { - ti->error = PFX "Not enough arguments"; + ti->error = "Not enough arguments"; return -EINVAL; } @@ -532,21 +532,21 @@ static int crypt_ctr(struct dm_target *t ivmode = strsep(&ivopts, ":"); if (tmp) - DMWARN(PFX "Unexpected additional cipher options"); + DMWARN("Unexpected additional cipher options"); key_size = strlen(argv[1]) >> 1; cc = kmalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL); if (cc == NULL) { ti->error = - PFX "Cannot allocate transparent encryption context"; + "Cannot allocate transparent encryption context"; return -ENOMEM; } cc->key_size = key_size; if ((!key_size && strcmp(argv[1], "-") != 0) || (key_size && crypt_decode_key(cc->key, argv[1], key_size) < 0)) { - ti->error = PFX "Error decoding key"; + ti->error = "Error decoding key"; goto bad1; } @@ -562,22 +562,22 @@ static int crypt_ctr(struct dm_target *t else if (strcmp(chainmode, "ecb") == 0) crypto_flags = CRYPTO_TFM_MODE_ECB; else { - ti->error = PFX "Unknown chaining mode"; + ti->error = "Unknown chaining mode"; goto bad1; } if (crypto_flags != CRYPTO_TFM_MODE_ECB && !ivmode) { - ti->error = PFX "This chaining mode requires an IV mechanism"; + ti->error = "This chaining mode requires an IV mechanism"; goto bad1; } tfm = crypto_alloc_tfm(cipher, crypto_flags | CRYPTO_TFM_REQ_MAY_SLEEP); if (!tfm) { - ti->error = PFX "Error allocating crypto tfm"; + ti->error = "Error allocating crypto tfm"; goto bad1; } if (crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER) { - ti->error = PFX "Expected cipher algorithm"; + ti->error = "Expected cipher algorithm"; goto bad2; } @@ -595,7 +595,7 @@ static int crypt_ctr(struct dm_target *t else if (strcmp(ivmode, "essiv") == 0) cc->iv_gen_ops = &crypt_iv_essiv_ops; else { - ti->error = PFX "Invalid IV mode"; + ti->error = "Invalid IV mode"; goto bad2; } @@ -610,7 +610,7 @@ static int crypt_ctr(struct dm_target *t else { cc->iv_size = 0; if (cc->iv_gen_ops) { - DMWARN(PFX "Selected cipher does not support IVs"); + DMWARN("Selected cipher does not support IVs"); if (cc->iv_gen_ops->dtr) cc->iv_gen_ops->dtr(cc); cc->iv_gen_ops = NULL; @@ -619,36 +619,36 @@ static int crypt_ctr(struct dm_target *t cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool); if (!cc->io_pool) { - ti->error = PFX "Cannot allocate crypt io mempool"; + ti->error = "Cannot allocate crypt io mempool"; goto bad3; } cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0); if (!cc->page_pool) { - ti->error = PFX "Cannot allocate page mempool"; + ti->error = "Cannot allocate page mempool"; goto bad4; } if (tfm->crt_cipher.cit_setkey(tfm, cc->key, key_size) < 0) { - ti->error = PFX "Error setting key"; + ti->error = "Error setting key"; goto bad5; } if (sscanf(argv[2], "%llu", &tmpll) != 1) { - ti->error = PFX "Invalid iv_offset sector"; + ti->error = "Invalid iv_offset sector"; goto bad5; } cc->iv_offset = tmpll; if (sscanf(argv[4], "%llu", &tmpll) != 1) { - ti->error = PFX "Invalid device sector"; + ti->error = "Invalid device sector"; goto bad5; } cc->start = tmpll; if (dm_get_device(ti, argv[3], cc->start, ti->len, dm_table_get_mode(ti->table), &cc->dev)) { - ti->error = PFX "Device lookup failed"; + ti->error = "Device lookup failed"; goto bad5; } @@ -657,7 +657,7 @@ static int crypt_ctr(struct dm_target *t *(ivopts - 1) = ':'; cc->iv_mode = kmalloc(strlen(ivmode) + 1, GFP_KERNEL); if (!cc->iv_mode) { - ti->error = PFX "Error kmallocing iv_mode string"; + ti->error = "Error kmallocing iv_mode string"; goto bad5; } strcpy(cc->iv_mode, ivmode); @@ -918,13 +918,13 @@ static int __init dm_crypt_init(void) _kcryptd_workqueue = create_workqueue("kcryptd"); if (!_kcryptd_workqueue) { r = -ENOMEM; - DMERR(PFX "couldn't create kcryptd"); + DMERR("couldn't create kcryptd"); goto bad1; } r = dm_register_target(&crypt_target); if (r < 0) { - DMERR(PFX "register failed %d", r); + DMERR("register failed %d", r); goto bad2; } @@ -942,7 +942,7 @@ static void __exit dm_crypt_exit(void) int r = dm_unregister_target(&crypt_target); if (r < 0) - DMERR(PFX "unregister failed %d", r); + DMERR("unregister failed %d", r); destroy_workqueue(_kcryptd_workqueue); kmem_cache_destroy(_crypt_io_pool); diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c index c706767..2a374cc 100644 --- a/drivers/md/dm-emc.c +++ b/drivers/md/dm-emc.c @@ -12,6 +12,8 @@ #include "dm-hw-handler.h" #include #include +#define DM_MSG_PREFIX "multipath emc" + struct emc_handler { spinlock_t lock; @@ -66,7 +68,7 @@ static struct bio *get_failover_bio(stru bio = bio_alloc(GFP_ATOMIC, 1); if (!bio) { - DMERR("dm-emc: get_failover_bio: bio_alloc() failed."); + DMERR("get_failover_bio: bio_alloc() failed."); return NULL; } @@ -78,13 +80,13 @@ static struct bio *get_failover_bio(stru page = alloc_page(GFP_ATOMIC); if (!page) { - DMERR("dm-emc: get_failover_bio: alloc_page() failed."); + DMERR("get_failover_bio: alloc_page() failed."); bio_put(bio); return NULL; } if (bio_add_page(bio, page, data_size, 0) != data_size) { - DMERR("dm-emc: get_failover_bio: alloc_page() failed."); + DMERR("get_failover_bio: alloc_page() failed."); __free_page(page); bio_put(bio); return NULL; @@ -103,7 +105,7 @@ static struct request *get_failover_req( /* FIXME: Figure out why it fails with GFP_ATOMIC. */ rq = blk_get_request(q, WRITE, __GFP_WAIT); if (!rq) { - DMERR("dm-emc: get_failover_req: blk_get_request failed"); + DMERR("get_failover_req: blk_get_request failed"); return NULL; } @@ -160,7 +162,7 @@ static struct request *emc_trespass_get( bio = get_failover_bio(path, data_size); if (!bio) { - DMERR("dm-emc: emc_trespass_get: no bio"); + DMERR("emc_trespass_get: no bio"); return NULL; } @@ -173,7 +175,7 @@ static struct request *emc_trespass_get( /* get request for block layer packet command */ rq = get_failover_req(h, bio, path); if (!rq) { - DMERR("dm-emc: emc_trespass_get: no rq"); + DMERR("emc_trespass_get: no rq"); free_bio(bio); return NULL; } @@ -200,18 +202,18 @@ static void emc_pg_init(struct hw_handle * initial state passed into us and then get an update here. */ if (!q) { - DMINFO("dm-emc: emc_pg_init: no queue"); + DMINFO("emc_pg_init: no queue"); goto fail_path; } /* FIXME: The request should be pre-allocated. */ rq = emc_trespass_get(hwh->context, path); if (!rq) { - DMERR("dm-emc: emc_pg_init: no rq"); + DMERR("emc_pg_init: no rq"); goto fail_path; } - DMINFO("dm-emc: emc_pg_init: sending switch-over command"); + DMINFO("emc_pg_init: sending switch-over command"); elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1); return; @@ -241,18 +243,18 @@ static int emc_create(struct hw_handler hr = 0; short_trespass = 0; } else if (argc != 2) { - DMWARN("dm-emc hwhandler: incorrect number of arguments"); + DMWARN("incorrect number of arguments"); return -EINVAL; } else { if ((sscanf(argv[0], "%u", &short_trespass) != 1) || (short_trespass > 1)) { - DMWARN("dm-emc: invalid trespass mode selected"); + DMWARN("invalid trespass mode selected"); return -EINVAL; } if ((sscanf(argv[1], "%u", &hr) != 1) || (hr > 1)) { - DMWARN("dm-emc: invalid honor reservation flag selected"); + DMWARN("invalid honor reservation flag selected"); return -EINVAL; } } @@ -264,14 +266,14 @@ static int emc_create(struct hw_handler hwh->context = h; if ((h->short_trespass = short_trespass)) - DMWARN("dm-emc: short trespass command will be send"); + DMWARN("short trespass command will be send"); else - DMWARN("dm-emc: long trespass command will be send"); + DMWARN("long trespass command will be send"); if ((h->hr = hr)) - DMWARN("dm-emc: honor reservation bit will be set"); + DMWARN("honor reservation bit will be set"); else - DMWARN("dm-emc: honor reservation bit will not be set (default)"); + DMWARN("honor reservation bit will not be set (default)"); return 0; } @@ -336,9 +338,9 @@ static int __init dm_emc_init(void) int r = dm_register_hw_handler(&emc_hwh); if (r < 0) - DMERR("emc: register failed %d", r); + DMERR("register failed %d", r); - DMINFO("dm-emc version 0.0.3 loaded"); + DMINFO("version 0.0.3 loaded"); return r; } @@ -348,7 +350,7 @@ static void __exit dm_emc_exit(void) int r = dm_unregister_hw_handler(&emc_hwh); if (r < 0) - DMERR("emc: unregister failed %d", r); + DMERR("unregister failed %d", r); } module_init(dm_emc_init); diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index cc07bbe..d12379b 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -16,6 +16,8 @@ #include #include #include +#define DM_MSG_PREFIX "snapshots" + /*----------------------------------------------------------------- * Persistent snapshots, by persistent we mean that the snapshot * will survive a reboot. @@ -91,7 +93,6 @@ struct pstore { struct dm_snapshot *snap; /* up pointer to my snapshot */ int version; int valid; - uint32_t chunk_size; uint32_t exceptions_per_area; /* @@ -133,7 +134,7 @@ static int alloc_area(struct pstore *ps) int r = -ENOMEM; size_t len; - len = ps->chunk_size << SECTOR_SHIFT; + len = ps->snap->chunk_size << SECTOR_SHIFT; /* * Allocate the chunk_size block of memory that will hold @@ -160,8 +161,8 @@ static int chunk_io(struct pstore *ps, u unsigned long bits; where.bdev = ps->snap->cow->bdev; - where.sector = ps->chunk_size * chunk; - where.count = ps->chunk_size; + where.sector = ps->snap->chunk_size * chunk; + where.count = ps->snap->chunk_size; return dm_io_sync_vm(1, &where, rw, ps->area, &bits); } @@ -188,7 +189,7 @@ static int area_io(struct pstore *ps, ui static int zero_area(struct pstore *ps, uint32_t area) { - memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT); + memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); return area_io(ps, area, WRITE); } @@ -196,6 +197,7 @@ static int read_header(struct pstore *ps { int r; struct disk_header *dh; + chunk_t chunk_size; r = chunk_io(ps, 0, READ); if (r) @@ -210,8 +212,29 @@ static int read_header(struct pstore *ps *new_snapshot = 0; ps->valid = le32_to_cpu(dh->valid); ps->version = le32_to_cpu(dh->version); - ps->chunk_size = le32_to_cpu(dh->chunk_size); - + chunk_size = le32_to_cpu(dh->chunk_size); + if (ps->snap->chunk_size != chunk_size) { + DMWARN("chunk size %llu in device metadata overrides " + "table chunk size of %llu.", + (unsigned long long)chunk_size, + (unsigned long long)ps->snap->chunk_size); + + /* We had a bogus chunk_size. Fix stuff up. */ + dm_io_put(sectors_to_pages(ps->snap->chunk_size)); + free_area(ps); + + ps->snap->chunk_size = chunk_size; + ps->snap->chunk_mask = chunk_size - 1; + ps->snap->chunk_shift = ffs(chunk_size) - 1; + + r = alloc_area(ps); + if (r) + return r; + + r = dm_io_get(sectors_to_pages(chunk_size)); + if (r) + return r; + } } else { DMWARN("Invalid/corrupt snapshot"); r = -ENXIO; @@ -224,13 +247,13 @@ static int write_header(struct pstore *p { struct disk_header *dh; - memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT); + memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); dh = (struct disk_header *) ps->area; dh->magic = cpu_to_le32(SNAP_MAGIC); dh->valid = cpu_to_le32(ps->valid); dh->version = cpu_to_le32(ps->version); - dh->chunk_size = cpu_to_le32(ps->chunk_size); + dh->chunk_size = cpu_to_le32(ps->snap->chunk_size); return chunk_io(ps, 0, WRITE); } @@ -365,7 +388,7 @@ static void persistent_destroy(struct ex { struct pstore *ps = get_info(store); - dm_io_put(sectors_to_pages(ps->chunk_size)); + dm_io_put(sectors_to_pages(ps->snap->chunk_size)); vfree(ps->callbacks); free_area(ps); kfree(ps); @@ -384,6 +407,16 @@ static int persistent_read_metadata(stru return r; /* + * Now we know correct chunk_size, complete the initialisation. + */ + ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) / + sizeof(struct disk_exception); + ps->callbacks = dm_vcalloc(ps->exceptions_per_area, + sizeof(*ps->callbacks)); + if (!ps->callbacks) + return -ENOMEM; + + /* * Do we need to setup a new snapshot ? */ if (new_snapshot) { @@ -533,9 +566,6 @@ int dm_create_persistent(struct exceptio ps->snap = store->snap; ps->valid = 1; ps->version = SNAPSHOT_DISK_VERSION; - ps->chunk_size = chunk_size; - ps->exceptions_per_area = (chunk_size << SECTOR_SHIFT) / - sizeof(struct disk_exception); ps->next_free = 2; /* skipping the header and first area */ ps->current_committed = 0; @@ -543,18 +573,9 @@ int dm_create_persistent(struct exceptio if (r) goto bad; - /* - * Allocate space for all the callbacks. - */ ps->callback_count = 0; atomic_set(&ps->pending_count, 0); - ps->callbacks = dm_vcalloc(ps->exceptions_per_area, - sizeof(*ps->callbacks)); - - if (!ps->callbacks) { - r = -ENOMEM; - goto bad; - } + ps->callbacks = NULL; store->destroy = persistent_destroy; store->read_metadata = persistent_read_metadata; diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 8edd643..3edb347 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. - * Copyright (C) 2004 - 2005 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004 - 2006 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ @@ -19,6 +19,7 @@ #include #include +#define DM_MSG_PREFIX "ioctl" #define DM_DRIVER_EMAIL "dm-devel@redhat.com" /*----------------------------------------------------------------- @@ -48,7 +49,7 @@ #define MASK_BUCKETS (NUM_BUCKETS - 1) static struct list_head _name_buckets[NUM_BUCKETS]; static struct list_head _uuid_buckets[NUM_BUCKETS]; -static void dm_hash_remove_all(void); +static void dm_hash_remove_all(int keep_open_devices); /* * Guards access to both hash tables. @@ -73,7 +74,7 @@ static int dm_hash_init(void) static void dm_hash_exit(void) { - dm_hash_remove_all(); + dm_hash_remove_all(0); devfs_remove(DM_DIR); } @@ -102,8 +103,10 @@ static struct hash_cell *__get_name_cell unsigned int h = hash_str(str); list_for_each_entry (hc, _name_buckets + h, name_list) - if (!strcmp(hc->name, str)) + if (!strcmp(hc->name, str)) { + dm_get(hc->md); return hc; + } return NULL; } @@ -114,8 +117,10 @@ static struct hash_cell *__get_uuid_cell unsigned int h = hash_str(str); list_for_each_entry (hc, _uuid_buckets + h, uuid_list) - if (!strcmp(hc->uuid, str)) + if (!strcmp(hc->uuid, str)) { + dm_get(hc->md); return hc; + } return NULL; } @@ -191,7 +196,7 @@ static int unregister_with_devfs(struct */ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md) { - struct hash_cell *cell; + struct hash_cell *cell, *hc; /* * Allocate the new cells. @@ -204,14 +209,19 @@ static int dm_hash_insert(const char *na * Insert the cell into both hash tables. */ down_write(&_hash_lock); - if (__get_name_cell(name)) + hc = __get_name_cell(name); + if (hc) { + dm_put(hc->md); goto bad; + } list_add(&cell->name_list, _name_buckets + hash_str(name)); if (uuid) { - if (__get_uuid_cell(uuid)) { + hc = __get_uuid_cell(uuid); + if (hc) { list_del(&cell->name_list); + dm_put(hc->md); goto bad; } list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid)); @@ -251,19 +261,41 @@ static void __hash_remove(struct hash_ce free_cell(hc); } -static void dm_hash_remove_all(void) +static void dm_hash_remove_all(int keep_open_devices) { - int i; + int i, dev_skipped, dev_removed; struct hash_cell *hc; struct list_head *tmp, *n; down_write(&_hash_lock); + +retry: + dev_skipped = dev_removed = 0; for (i = 0; i < NUM_BUCKETS; i++) { list_for_each_safe (tmp, n, _name_buckets + i) { hc = list_entry(tmp, struct hash_cell, name_list); + + if (keep_open_devices && + dm_lock_for_deletion(hc->md)) { + dev_skipped++; + continue; + } __hash_remove(hc); + dev_removed = 1; } } + + /* + * Some mapped devices may be using other mapped devices, so if any + * still exist, repeat until we make no further progress. + */ + if (dev_skipped) { + if (dev_removed) + goto retry; + + DMWARN("remove_all left %d open device(s)", dev_skipped); + } + up_write(&_hash_lock); } @@ -289,6 +321,7 @@ static int dm_hash_rename(const char *ol if (hc) { DMWARN("asked to rename to an already existing name %s -> %s", old, new); + dm_put(hc->md); up_write(&_hash_lock); kfree(new_name); return -EBUSY; @@ -328,6 +361,7 @@ static int dm_hash_rename(const char *ol dm_table_put(table); } + dm_put(hc->md); up_write(&_hash_lock); kfree(old_name); return 0; @@ -344,7 +378,7 @@ typedef int (*ioctl_fn)(struct dm_ioctl static int remove_all(struct dm_ioctl *param, size_t param_size) { - dm_hash_remove_all(); + dm_hash_remove_all(1); param->data_size = 0; return 0; } @@ -524,7 +558,6 @@ static int __dev_status(struct mapped_de { struct gendisk *disk = dm_disk(md); struct dm_table *table; - struct block_device *bdev; param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG | DM_ACTIVE_PRESENT_FLAG); @@ -534,20 +567,12 @@ static int __dev_status(struct mapped_de param->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor)); - if (!(param->flags & DM_SKIP_BDGET_FLAG)) { - bdev = bdget_disk(disk, 0); - if (!bdev) - return -ENXIO; - - /* - * Yes, this will be out of date by the time it gets back - * to userland, but it is still very useful for - * debugging. - */ - param->open_count = bdev->bd_openers; - bdput(bdev); - } else - param->open_count = -1; + /* + * Yes, this will be out of date by the time it gets back + * to userland, but it is still very useful for + * debugging. + */ + param->open_count = dm_open_count(md); if (disk->policy) param->flags |= DM_READONLY_FLAG; @@ -567,7 +592,7 @@ static int __dev_status(struct mapped_de static int dev_create(struct dm_ioctl *param, size_t param_size) { - int r; + int r, m = DM_ANY_MINOR; struct mapped_device *md; r = check_name(param->name); @@ -575,10 +600,9 @@ static int dev_create(struct dm_ioctl *p return r; if (param->flags & DM_PERSISTENT_DEV_FLAG) - r = dm_create_with_minor(MINOR(huge_decode_dev(param->dev)), &md); - else - r = dm_create(&md); + m = MINOR(huge_decode_dev(param->dev)); + r = dm_create(m, &md); if (r) return r; @@ -611,10 +635,8 @@ static struct hash_cell *__find_device_h return __get_name_cell(param->name); md = dm_get_md(huge_decode_dev(param->dev)); - if (md) { + if (md) mdptr = dm_get_mdptr(md); - dm_put(md); - } return mdptr; } @@ -628,7 +650,6 @@ static struct mapped_device *find_device hc = __find_device_hash_cell(param); if (hc) { md = hc->md; - dm_get(md); /* * Sneakily write in both the name and the uuid @@ -653,6 +674,8 @@ static struct mapped_device *find_device static int dev_remove(struct dm_ioctl *param, size_t param_size) { struct hash_cell *hc; + struct mapped_device *md; + int r; down_write(&_hash_lock); hc = __find_device_hash_cell(param); @@ -663,8 +686,22 @@ static int dev_remove(struct dm_ioctl *p return -ENXIO; } + md = hc->md; + + /* + * Ensure the device is not open and nothing further can open it. + */ + r = dm_lock_for_deletion(md); + if (r) { + DMWARN("unable to remove open device %s", hc->name); + up_write(&_hash_lock); + dm_put(md); + return r; + } + __hash_remove(hc); up_write(&_hash_lock); + dm_put(md); param->data_size = 0; return 0; } @@ -790,7 +827,6 @@ static int do_resume(struct dm_ioctl *pa } md = hc->md; - dm_get(md); new_map = hc->new_map; hc->new_map = NULL; @@ -1078,6 +1114,7 @@ static int table_clear(struct dm_ioctl * { int r; struct hash_cell *hc; + struct mapped_device *md; down_write(&_hash_lock); @@ -1096,7 +1133,9 @@ static int table_clear(struct dm_ioctl * param->flags &= ~DM_INACTIVE_PRESENT_FLAG; r = __dev_status(hc->md, param); + md = hc->md; up_write(&_hash_lock); + dm_put(md); return r; } diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index daf586c..47b3c62 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -12,6 +12,8 @@ #include #include #include +#define DM_MSG_PREFIX "linear" + /* * Linear: maps a linear range of a device. */ @@ -29,7 +31,7 @@ static int linear_ctr(struct dm_target * unsigned long long tmp; if (argc != 2) { - ti->error = "dm-linear: Invalid argument count"; + ti->error = "Invalid argument count"; return -EINVAL; } @@ -111,7 +113,7 @@ int __init dm_linear_init(void) int r = dm_register_target(&linear_target); if (r < 0) - DMERR("linear: register failed %d", r); + DMERR("register failed %d", r); return r; } @@ -121,5 +123,5 @@ void dm_linear_exit(void) int r = dm_unregister_target(&linear_target); if (r < 0) - DMERR("linear: unregister failed %d", r); + DMERR("unregister failed %d", r); } diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index d73779a..64b764b 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -12,6 +12,8 @@ #include #include "dm-log.h" #include "dm-io.h" +#define DM_MSG_PREFIX "mirror log" + static LIST_HEAD(_log_types); static DEFINE_SPINLOCK(_lock); @@ -155,8 +157,6 @@ struct log_c { struct io_region header_location; struct log_header *disk_header; - - struct io_region bits_location; }; /* @@ -241,43 +241,21 @@ static inline int write_header(struct lo } /*---------------------------------------------------------------- - * Bits IO - *--------------------------------------------------------------*/ -static int read_bits(struct log_c *log) -{ - int r; - unsigned long ebits; - - r = dm_io_sync_vm(1, &log->bits_location, READ, - log->clean_bits, &ebits); - if (r) - return r; - - return 0; -} - -static int write_bits(struct log_c *log) -{ - unsigned long ebits; - return dm_io_sync_vm(1, &log->bits_location, WRITE, - log->clean_bits, &ebits); -} - -/*---------------------------------------------------------------- * core log constructor/destructor * * argv contains region_size followed optionally by [no]sync *--------------------------------------------------------------*/ #define BYTE_SHIFT 3 -static int core_ctr(struct dirty_log *log, struct dm_target *ti, - unsigned int argc, char **argv) +static int create_log_context(struct dirty_log *log, struct dm_target *ti, + unsigned int argc, char **argv, + struct dm_dev *dev) { enum sync sync = DEFAULTSYNC; struct log_c *lc; uint32_t region_size; unsigned int region_count; - size_t bitset_size; + size_t bitset_size, buf_size; if (argc < 1 || argc > 2) { DMWARN("wrong number of arguments to mirror log"); @@ -319,22 +297,53 @@ static int core_ctr(struct dirty_log *lo * Work out how many "unsigned long"s we need to hold the bitset. */ bitset_size = dm_round_up(region_count, - sizeof(unsigned long) << BYTE_SHIFT); + sizeof(*lc->clean_bits) << BYTE_SHIFT); bitset_size >>= BYTE_SHIFT; - lc->bitset_uint32_count = bitset_size / 4; - lc->clean_bits = vmalloc(bitset_size); - if (!lc->clean_bits) { - DMWARN("couldn't allocate clean bitset"); - kfree(lc); - return -ENOMEM; + lc->bitset_uint32_count = bitset_size / sizeof(*lc->clean_bits); + + /* + * Disk log? + */ + if (!dev) { + lc->clean_bits = vmalloc(bitset_size); + if (!lc->clean_bits) { + DMWARN("couldn't allocate clean bitset"); + kfree(lc); + return -ENOMEM; + } + lc->disk_header = NULL; + } else { + lc->log_dev = dev; + lc->header_location.bdev = lc->log_dev->bdev; + lc->header_location.sector = 0; + + /* + * Buffer holds both header and bitset. + */ + buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + + bitset_size, ti->limits.hardsect_size); + lc->header_location.count = buf_size >> SECTOR_SHIFT; + + lc->disk_header = vmalloc(buf_size); + if (!lc->disk_header) { + DMWARN("couldn't allocate disk log buffer"); + kfree(lc); + return -ENOMEM; + } + + lc->clean_bits = (void *)lc->disk_header + + (LOG_OFFSET << SECTOR_SHIFT); } + memset(lc->clean_bits, -1, bitset_size); lc->sync_bits = vmalloc(bitset_size); if (!lc->sync_bits) { DMWARN("couldn't allocate sync bitset"); - vfree(lc->clean_bits); + if (!dev) + vfree(lc->clean_bits); + vfree(lc->disk_header); kfree(lc); return -ENOMEM; } @@ -345,25 +354,40 @@ static int core_ctr(struct dirty_log *lo if (!lc->recovering_bits) { DMWARN("couldn't allocate sync bitset"); vfree(lc->sync_bits); - vfree(lc->clean_bits); + if (!dev) + vfree(lc->clean_bits); + vfree(lc->disk_header); kfree(lc); return -ENOMEM; } memset(lc->recovering_bits, 0, bitset_size); lc->sync_search = 0; log->context = lc; + return 0; } -static void core_dtr(struct dirty_log *log) +static int core_ctr(struct dirty_log *log, struct dm_target *ti, + unsigned int argc, char **argv) +{ + return create_log_context(log, ti, argc, argv, NULL); +} + +static void destroy_log_context(struct log_c *lc) { - struct log_c *lc = (struct log_c *) log->context; - vfree(lc->clean_bits); vfree(lc->sync_bits); vfree(lc->recovering_bits); kfree(lc); } +static void core_dtr(struct dirty_log *log) +{ + struct log_c *lc = (struct log_c *) log->context; + + vfree(lc->clean_bits); + destroy_log_context(lc); +} + /*---------------------------------------------------------------- * disk log constructor/destructor * @@ -373,8 +397,6 @@ static int disk_ctr(struct dirty_log *lo unsigned int argc, char **argv) { int r; - size_t size; - struct log_c *lc; struct dm_dev *dev; if (argc < 2 || argc > 3) { @@ -387,49 +409,22 @@ static int disk_ctr(struct dirty_log *lo if (r) return r; - r = core_ctr(log, ti, argc - 1, argv + 1); + r = create_log_context(log, ti, argc - 1, argv + 1, dev); if (r) { dm_put_device(ti, dev); return r; } - lc = (struct log_c *) log->context; - lc->log_dev = dev; - - /* setup the disk header fields */ - lc->header_location.bdev = lc->log_dev->bdev; - lc->header_location.sector = 0; - lc->header_location.count = 1; - - /* - * We can't read less than this amount, even though we'll - * not be using most of this space. - */ - lc->disk_header = vmalloc(1 << SECTOR_SHIFT); - if (!lc->disk_header) - goto bad; - - /* setup the disk bitset fields */ - lc->bits_location.bdev = lc->log_dev->bdev; - lc->bits_location.sector = LOG_OFFSET; - - size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t), - 1 << SECTOR_SHIFT); - lc->bits_location.count = size >> SECTOR_SHIFT; return 0; - - bad: - dm_put_device(ti, lc->log_dev); - core_dtr(log); - return -ENOMEM; } static void disk_dtr(struct dirty_log *log) { struct log_c *lc = (struct log_c *) log->context; + dm_put_device(lc->ti, lc->log_dev); vfree(lc->disk_header); - core_dtr(log); + destroy_log_context(lc); } static int count_bits32(uint32_t *addr, unsigned size) @@ -454,12 +449,7 @@ static int disk_resume(struct dirty_log if (r) return r; - /* read the bits */ - r = read_bits(lc); - if (r) - return r; - - /* set or clear any new bits */ + /* set or clear any new bits -- device has grown */ if (lc->sync == NOSYNC) for (i = lc->header.nr_regions; i < lc->region_count; i++) /* FIXME: amazingly inefficient */ @@ -469,15 +459,14 @@ static int disk_resume(struct dirty_log /* FIXME: amazingly inefficient */ log_clear_bit(lc, lc->clean_bits, i); + /* clear any old bits -- device has shrunk */ + for (i = lc->region_count; i % (sizeof(*lc->clean_bits) << BYTE_SHIFT); i++) + log_clear_bit(lc, lc->clean_bits, i); + /* copy clean across to sync */ memcpy(lc->sync_bits, lc->clean_bits, size); lc->sync_count = count_bits32(lc->clean_bits, lc->bitset_uint32_count); - /* write the bits */ - r = write_bits(lc); - if (r) - return r; - /* set the correct number of regions in the header */ lc->header.nr_regions = lc->region_count; @@ -518,7 +507,7 @@ static int disk_flush(struct dirty_log * if (!lc->touched) return 0; - r = write_bits(lc); + r = write_header(lc); if (!r) lc->touched = 0; diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 1816f30..217615b 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -21,6 +21,7 @@ #include #include #include +#define DM_MSG_PREFIX "multipath" #define MESG_STR(x) x, sizeof(x) /* Path properties */ @@ -446,8 +447,6 @@ struct param { char *error; }; -#define ESTR(s) ("dm-multipath: " s) - static int read_param(struct param *param, char *str, unsigned *v, char **error) { if (!str || @@ -495,12 +494,12 @@ static int parse_path_selector(struct ar unsigned ps_argc; static struct param _params[] = { - {0, 1024, ESTR("invalid number of path selector args")}, + {0, 1024, "invalid number of path selector args"}, }; pst = dm_get_path_selector(shift(as)); if (!pst) { - ti->error = ESTR("unknown path selector type"); + ti->error = "unknown path selector type"; return -EINVAL; } @@ -511,7 +510,7 @@ static int parse_path_selector(struct ar r = pst->create(&pg->ps, ps_argc, as->argv); if (r) { dm_put_path_selector(pst); - ti->error = ESTR("path selector constructor failed"); + ti->error = "path selector constructor failed"; return r; } @@ -529,7 +528,7 @@ static struct pgpath *parse_path(struct /* we need at least a path arg */ if (as->argc < 1) { - ti->error = ESTR("no device given"); + ti->error = "no device given"; return NULL; } @@ -540,7 +539,7 @@ static struct pgpath *parse_path(struct r = dm_get_device(ti, shift(as), ti->begin, ti->len, dm_table_get_mode(ti->table), &p->path.dev); if (r) { - ti->error = ESTR("error getting device"); + ti->error = "error getting device"; goto bad; } @@ -562,8 +561,8 @@ static struct priority_group *parse_prio struct dm_target *ti) { static struct param _params[] = { - {1, 1024, ESTR("invalid number of paths")}, - {0, 1024, ESTR("invalid number of selector args")} + {1, 1024, "invalid number of paths"}, + {0, 1024, "invalid number of selector args"} }; int r; @@ -572,13 +571,13 @@ static struct priority_group *parse_prio if (as->argc < 2) { as->argc = 0; - ti->error = ESTR("not enough priority group aruments"); + ti->error = "not enough priority group aruments"; return NULL; } pg = alloc_priority_group(); if (!pg) { - ti->error = ESTR("couldn't allocate priority group"); + ti->error = "couldn't allocate priority group"; return NULL; } pg->m = m; @@ -633,7 +632,7 @@ static int parse_hw_handler(struct arg_s unsigned hw_argc; static struct param _params[] = { - {0, 1024, ESTR("invalid number of hardware handler args")}, + {0, 1024, "invalid number of hardware handler args"}, }; r = read_param(_params, shift(as), &hw_argc, &ti->error); @@ -645,14 +644,14 @@ static int parse_hw_handler(struct arg_s hwht = dm_get_hw_handler(shift(as)); if (!hwht) { - ti->error = ESTR("unknown hardware handler type"); + ti->error = "unknown hardware handler type"; return -EINVAL; } r = hwht->create(&m->hw_handler, hw_argc - 1, as->argv); if (r) { dm_put_hw_handler(hwht); - ti->error = ESTR("hardware handler constructor failed"); + ti->error = "hardware handler constructor failed"; return r; } @@ -669,7 +668,7 @@ static int parse_features(struct arg_set unsigned argc; static struct param _params[] = { - {0, 1, ESTR("invalid number of feature args")}, + {0, 1, "invalid number of feature args"}, }; r = read_param(_params, shift(as), &argc, &ti->error); @@ -692,8 +691,8 @@ static int multipath_ctr(struct dm_targe { /* target parameters */ static struct param _params[] = { - {1, 1024, ESTR("invalid number of priority groups")}, - {1, 1024, ESTR("invalid initial priority group number")}, + {1, 1024, "invalid number of priority groups"}, + {1, 1024, "invalid initial priority group number"}, }; int r; @@ -707,7 +706,7 @@ static int multipath_ctr(struct dm_targe m = alloc_multipath(); if (!m) { - ti->error = ESTR("can't allocate multipath"); + ti->error = "can't allocate multipath"; return -EINVAL; } @@ -746,7 +745,7 @@ static int multipath_ctr(struct dm_targe } if (pg_count != m->nr_priority_groups) { - ti->error = ESTR("priority group count mismatch"); + ti->error = "priority group count mismatch"; r = -EINVAL; goto bad; } @@ -807,7 +806,7 @@ static int fail_path(struct pgpath *pgpa if (!pgpath->path.is_active) goto out; - DMWARN("dm-multipath: Failing path %s.", pgpath->path.dev->name); + DMWARN("Failing path %s.", pgpath->path.dev->name); pgpath->pg->ps.type->fail_path(&pgpath->pg->ps, &pgpath->path); pgpath->path.is_active = 0; @@ -1250,7 +1249,7 @@ static int multipath_message(struct dm_t r = dm_get_device(ti, argv[1], ti->begin, ti->len, dm_table_get_mode(ti->table), &dev); if (r) { - DMWARN("dm-multipath message: error getting device %s", + DMWARN("message: error getting device %s", argv[1]); return -EINVAL; } @@ -1309,7 +1308,7 @@ static int __init dm_multipath_init(void return -ENOMEM; } - DMINFO("dm-multipath version %u.%u.%u loaded", + DMINFO("version %u.%u.%u loaded", multipath_target.version[0], multipath_target.version[1], multipath_target.version[2]); diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index d12cf3e..be48ced 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -20,6 +20,8 @@ #include #include #include +#define DM_MSG_PREFIX "raid1" + static struct workqueue_struct *_kmirrord_wq; static struct work_struct _kmirrord_work; @@ -106,12 +108,42 @@ struct region { struct bio_list delayed_bios; }; + +/*----------------------------------------------------------------- + * Mirror set structures. + *---------------------------------------------------------------*/ +struct mirror { + atomic_t error_count; + struct dm_dev *dev; + sector_t offset; +}; + +struct mirror_set { + struct dm_target *ti; + struct list_head list; + struct region_hash rh; + struct kcopyd_client *kcopyd_client; + + spinlock_t lock; /* protects the next two lists */ + struct bio_list reads; + struct bio_list writes; + + /* recovery */ + region_t nr_regions; + int in_sync; + + struct mirror *default_mirror; /* Default mirror */ + + unsigned int nr_mirrors; + struct mirror mirror[0]; +}; + /* * Conversion fns */ static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio) { - return bio->bi_sector >> rh->region_shift; + return (bio->bi_sector - rh->ms->ti->begin) >> rh->region_shift; } static inline sector_t region_to_sector(struct region_hash *rh, region_t region) @@ -458,11 +490,9 @@ static int __rh_recovery_prepare(struct /* Already quiesced ? */ if (atomic_read(®->pending)) list_del_init(®->list); + else + list_move(®->list, &rh->quiesced_regions); - else { - list_del_init(®->list); - list_add(®->list, &rh->quiesced_regions); - } spin_unlock_irq(&rh->region_lock); return 1; @@ -541,35 +571,6 @@ static void rh_start_recovery(struct reg wake(); } -/*----------------------------------------------------------------- - * Mirror set structures. - *---------------------------------------------------------------*/ -struct mirror { - atomic_t error_count; - struct dm_dev *dev; - sector_t offset; -}; - -struct mirror_set { - struct dm_target *ti; - struct list_head list; - struct region_hash rh; - struct kcopyd_client *kcopyd_client; - - spinlock_t lock; /* protects the next two lists */ - struct bio_list reads; - struct bio_list writes; - - /* recovery */ - region_t nr_regions; - int in_sync; - - struct mirror *default_mirror; /* Default mirror */ - - unsigned int nr_mirrors; - struct mirror mirror[0]; -}; - /* * Every mirror should look like this one. */ @@ -603,7 +604,7 @@ static void recovery_complete(int read_e struct region *reg = (struct region *) context; /* FIXME: better error handling */ - rh_recovery_end(reg, read_err || write_err); + rh_recovery_end(reg, !(read_err || write_err)); } static int recover(struct mirror_set *ms, struct region *reg) @@ -893,7 +894,7 @@ static struct mirror_set *alloc_context( ms = kmalloc(len, GFP_KERNEL); if (!ms) { - ti->error = "dm-mirror: Cannot allocate mirror context"; + ti->error = "Cannot allocate mirror context"; return NULL; } @@ -907,7 +908,7 @@ static struct mirror_set *alloc_context( ms->default_mirror = &ms->mirror[DEFAULT_MIRROR]; if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { - ti->error = "dm-mirror: Error creating dirty region hash"; + ti->error = "Error creating dirty region hash"; kfree(ms); return NULL; } @@ -937,14 +938,14 @@ static int get_mirror(struct mirror_set unsigned long long offset; if (sscanf(argv[1], "%llu", &offset) != 1) { - ti->error = "dm-mirror: Invalid offset"; + ti->error = "Invalid offset"; return -EINVAL; } if (dm_get_device(ti, argv[0], offset, ti->len, dm_table_get_mode(ti->table), &ms->mirror[mirror].dev)) { - ti->error = "dm-mirror: Device lookup failure"; + ti->error = "Device lookup failure"; return -ENXIO; } @@ -981,30 +982,30 @@ static struct dirty_log *create_dirty_lo struct dirty_log *dl; if (argc < 2) { - ti->error = "dm-mirror: Insufficient mirror log arguments"; + ti->error = "Insufficient mirror log arguments"; return NULL; } if (sscanf(argv[1], "%u", ¶m_count) != 1) { - ti->error = "dm-mirror: Invalid mirror log argument count"; + ti->error = "Invalid mirror log argument count"; return NULL; } *args_used = 2 + param_count; if (argc < *args_used) { - ti->error = "dm-mirror: Insufficient mirror log arguments"; + ti->error = "Insufficient mirror log arguments"; return NULL; } dl = dm_create_dirty_log(argv[0], ti, param_count, argv + 2); if (!dl) { - ti->error = "dm-mirror: Error creating mirror dirty log"; + ti->error = "Error creating mirror dirty log"; return NULL; } if (!_check_region_size(ti, dl->type->get_region_size(dl))) { - ti->error = "dm-mirror: Invalid region size"; + ti->error = "Invalid region size"; dm_destroy_dirty_log(dl); return NULL; } @@ -1038,7 +1039,7 @@ static int mirror_ctr(struct dm_target * if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 || nr_mirrors < 2 || nr_mirrors > KCOPYD_MAX_REGIONS + 1) { - ti->error = "dm-mirror: Invalid number of mirrors"; + ti->error = "Invalid number of mirrors"; dm_destroy_dirty_log(dl); return -EINVAL; } @@ -1046,7 +1047,7 @@ static int mirror_ctr(struct dm_target * argv++, argc--; if (argc != nr_mirrors * 2) { - ti->error = "dm-mirror: Wrong number of mirror arguments"; + ti->error = "Wrong number of mirror arguments"; dm_destroy_dirty_log(dl); return -EINVAL; } @@ -1115,7 +1116,7 @@ static int mirror_map(struct dm_target * struct mirror *m; struct mirror_set *ms = ti->private; - map_context->ll = bio->bi_sector >> ms->rh.region_shift; + map_context->ll = bio_to_region(&ms->rh, bio); if (rw == WRITE) { queue_bio(ms, bio, rw); @@ -1221,7 +1222,7 @@ static int mirror_status(struct dm_targe static struct target_type mirror_target = { .name = "mirror", - .version = {1, 0, 1}, + .version = {1, 0, 2}, .module = THIS_MODULE, .ctr = mirror_ctr, .dtr = mirror_dtr, diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c index d002486..c5a16c5 100644 --- a/drivers/md/dm-round-robin.c +++ b/drivers/md/dm-round-robin.c @@ -14,6 +14,8 @@ #include "dm-path-selector.h" #include +#define DM_MSG_PREFIX "multipath round-robin" + /*----------------------------------------------------------------- * Path-handling code, paths are held in lists *---------------------------------------------------------------*/ @@ -191,9 +193,9 @@ static int __init dm_rr_init(void) int r = dm_register_path_selector(&rr_ps); if (r < 0) - DMERR("round-robin: register failed %d", r); + DMERR("register failed %d", r); - DMINFO("dm-round-robin version 1.0.0 loaded"); + DMINFO("version 1.0.0 loaded"); return r; } diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 08312b4..8eea0dd 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -23,6 +23,8 @@ #include "dm-snap.h" #include "dm-bio-list.h" #include "kcopyd.h" +#define DM_MSG_PREFIX "snapshots" + /* * The percentage increment we will wake up users at */ @@ -117,7 +119,7 @@ static int init_origin_hash(void) _origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head), GFP_KERNEL); if (!_origins) { - DMERR("Device mapper: Snapshot: unable to allocate memory"); + DMERR("unable to allocate memory"); return -ENOMEM; } @@ -412,7 +414,7 @@ static int snapshot_ctr(struct dm_target int blocksize; if (argc < 4) { - ti->error = "dm-snapshot: requires exactly 4 arguments"; + ti->error = "requires exactly 4 arguments"; r = -EINVAL; goto bad1; } @@ -530,7 +532,7 @@ static int snapshot_ctr(struct dm_target } ti->private = s; - ti->split_io = chunk_size; + ti->split_io = s->chunk_size; return 0; @@ -1127,7 +1129,7 @@ static int origin_ctr(struct dm_target * struct dm_dev *dev; if (argc != 1) { - ti->error = "dm-origin: incorrect number of arguments"; + ti->error = "origin: incorrect number of arguments"; return -EINVAL; } @@ -1204,7 +1206,7 @@ static int origin_status(struct dm_targe static struct target_type origin_target = { .name = "snapshot-origin", - .version = {1, 1, 0}, + .version = {1, 4, 0}, .module = THIS_MODULE, .ctr = origin_ctr, .dtr = origin_dtr, @@ -1215,7 +1217,7 @@ static struct target_type origin_target static struct target_type snapshot_target = { .name = "snapshot", - .version = {1, 1, 0}, + .version = {1, 4, 0}, .module = THIS_MODULE, .ctr = snapshot_ctr, .dtr = snapshot_dtr, @@ -1236,7 +1238,7 @@ static int __init dm_snapshot_init(void) r = dm_register_target(&origin_target); if (r < 0) { - DMERR("Device mapper: Origin: register failed %d\n", r); + DMERR("Origin target register failed %d", r); goto bad1; } diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 08328a8..6c29fce 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -12,6 +12,8 @@ #include #include #include +#define DM_MSG_PREFIX "striped" + struct stripe { struct dm_dev *dev; sector_t physical_start; @@ -78,19 +80,19 @@ static int stripe_ctr(struct dm_target * unsigned int i; if (argc < 2) { - ti->error = "dm-stripe: Not enough arguments"; + ti->error = "Not enough arguments"; return -EINVAL; } stripes = simple_strtoul(argv[0], &end, 10); if (*end) { - ti->error = "dm-stripe: Invalid stripe count"; + ti->error = "Invalid stripe count"; return -EINVAL; } chunk_size = simple_strtoul(argv[1], &end, 10); if (*end) { - ti->error = "dm-stripe: Invalid chunk_size"; + ti->error = "Invalid chunk_size"; return -EINVAL; } @@ -99,19 +101,19 @@ static int stripe_ctr(struct dm_target * */ if (!chunk_size || (chunk_size & (chunk_size - 1)) || (chunk_size < (PAGE_SIZE >> SECTOR_SHIFT))) { - ti->error = "dm-stripe: Invalid chunk size"; + ti->error = "Invalid chunk size"; return -EINVAL; } if (ti->len & (chunk_size - 1)) { - ti->error = "dm-stripe: Target length not divisible by " + ti->error = "Target length not divisible by " "chunk size"; return -EINVAL; } width = ti->len; if (sector_div(width, stripes)) { - ti->error = "dm-stripe: Target length not divisible by " + ti->error = "Target length not divisible by " "number of stripes"; return -EINVAL; } @@ -120,14 +122,14 @@ static int stripe_ctr(struct dm_target * * Do we have enough arguments for that many stripes ? */ if (argc != (2 + 2 * stripes)) { - ti->error = "dm-stripe: Not enough destinations " + ti->error = "Not enough destinations " "specified"; return -EINVAL; } sc = alloc_context(stripes); if (!sc) { - ti->error = "dm-stripe: Memory allocation for striped context " + ti->error = "Memory allocation for striped context " "failed"; return -ENOMEM; } @@ -149,8 +151,7 @@ static int stripe_ctr(struct dm_target * r = get_stripe(ti, sc, i, argv); if (r < 0) { - ti->error = "dm-stripe: Couldn't parse stripe " - "destination"; + ti->error = "Couldn't parse stripe destination"; while (i--) dm_put_device(ti, sc->stripe[i].dev); kfree(sc); @@ -227,7 +228,7 @@ int __init dm_stripe_init(void) r = dm_register_target(&stripe_target); if (r < 0) - DMWARN("striped target registration failed"); + DMWARN("target registration failed"); return r; } @@ -235,7 +236,7 @@ int __init dm_stripe_init(void) void dm_stripe_exit(void) { if (dm_unregister_target(&stripe_target)) - DMWARN("striped target unregistration failed"); + DMWARN("target unregistration failed"); return; } diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 8f56a54..75fe949 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -17,6 +17,8 @@ #include #include #include +#define DM_MSG_PREFIX "table" + #define MAX_DEPTH 16 #define NODE_SIZE L1_CACHE_BYTES #define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t)) @@ -237,6 +239,44 @@ int dm_table_create(struct dm_table **re return 0; } +int dm_create_error_table(struct dm_table **result, struct mapped_device *md) +{ + struct dm_table *t; + sector_t dev_size = 1; + int r; + + /* + * Find current size of device. + * Default to 1 sector if inactive. + */ + t = dm_get_table(md); + if (t) { + dev_size = dm_table_get_size(t); + dm_table_put(t); + } + + r = dm_table_create(&t, FMODE_READ, 1, md); + if (r) + return r; + + r = dm_table_add_target(t, "error", 0, dev_size, NULL); + if (r) + goto out; + + r = dm_table_complete(t); + if (r) + goto out; + + *result = t; + +out: + if (r) + dm_table_put(t); + + return r; +} +EXPORT_SYMBOL_GPL(dm_create_error_table); + static void free_devices(struct list_head *devices) { struct list_head *tmp, *next; @@ -590,6 +630,12 @@ int dm_split_args(int *argc, char ***arg unsigned array_size = 0; *argc = 0; + + if (!input) { + *argvp = NULL; + return 0; + } + argv = realloc_argv(&array_size, argv); if (!argv) return -ENOMEM; @@ -671,15 +717,14 @@ int dm_table_add_target(struct dm_table memset(tgt, 0, sizeof(*tgt)); if (!len) { - tgt->error = "zero-length target"; - DMERR("%s", tgt->error); + DMERR("%s: zero-length target", dm_device_name(t->md)); return -EINVAL; } tgt->type = dm_get_target_type(type); if (!tgt->type) { - tgt->error = "unknown target type"; - DMERR("%s", tgt->error); + DMERR("%s: %s: unknown target type", dm_device_name(t->md), + type); return -EINVAL; } @@ -716,7 +761,7 @@ int dm_table_add_target(struct dm_table return 0; bad: - DMERR("%s", tgt->error); + DMERR("%s: %s: %s", dm_device_name(t->md), type, tgt->error); dm_put_target_type(tgt->type); return r; } @@ -802,7 +847,7 @@ sector_t dm_table_get_size(struct dm_tab struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index) { - if (index > t->num_targets) + if (index >= t->num_targets) return NULL; return t->targets + index; diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c index 64fd8e7..477a041 100644 --- a/drivers/md/dm-target.c +++ b/drivers/md/dm-target.c @@ -12,6 +12,8 @@ #include #include #include +#define DM_MSG_PREFIX "target" + struct tt_internal { struct target_type tt; diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c index 51c0639..ea569f7 100644 --- a/drivers/md/dm-zero.c +++ b/drivers/md/dm-zero.c @@ -10,13 +10,15 @@ #include #include #include +#define DM_MSG_PREFIX "zero" + /* * Construct a dummy mapping that only returns zeros */ static int zero_ctr(struct dm_target *ti, unsigned int argc, char **argv) { if (argc != 0) { - ti->error = "dm-zero: No arguments required"; + ti->error = "No arguments required"; return -EINVAL; } @@ -60,7 +62,7 @@ static int __init dm_zero_init(void) int r = dm_register_target(&zero_target); if (r < 0) - DMERR("zero: register failed %d", r); + DMERR("register failed %d", r); return r; } @@ -70,7 +72,7 @@ static void __exit dm_zero_exit(void) int r = dm_unregister_target(&zero_target); if (r < 0) - DMERR("zero: unregister failed %d", r); + DMERR("unregister failed %d", r); } module_init(dm_zero_init) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 4d710b7..3ed2e53 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. - * Copyright (C) 2004 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ @@ -21,11 +21,14 @@ #include #include #include +#define DM_MSG_PREFIX "core" + static const char *_name = DM_NAME; static unsigned int major = 0; static unsigned int _major = 0; +static DEFINE_SPINLOCK(_minor_lock); /* * One of these is allocated per bio. */ @@ -49,23 +52,28 @@ struct target_io { union map_info *dm_get_mapinfo(struct bio *bio) { - if (bio && bio->bi_private) - return &((struct target_io *)bio->bi_private)->info; - return NULL; + if (bio && bio->bi_private) + return &((struct target_io *)bio->bi_private)->info; + return NULL; } +#define MINOR_ALLOCED ((void *)-1) + /* * Bits for the md->flags field. */ #define DMF_BLOCK_IO 0 #define DMF_SUSPENDED 1 #define DMF_FROZEN 2 +#define DMF_FREEING 3 +#define DMF_DELETING 4 struct mapped_device { struct rw_semaphore io_lock; struct semaphore suspend_lock; rwlock_t map_lock; atomic_t holders; + atomic_t open_count; unsigned long flags; @@ -218,9 +226,25 @@ static int dm_blk_open(struct inode *ino { struct mapped_device *md; + spin_lock(&_minor_lock); + md = inode->i_bdev->bd_disk->private_data; + if (!md) + goto out; + + if (test_bit(DMF_FREEING, &md->flags) || + test_bit(DMF_DELETING, &md->flags)) { + md = NULL; + goto out; + } + dm_get(md); - return 0; + atomic_inc(&md->open_count); + +out: + spin_unlock(&_minor_lock); + + return md ? 0 : -ENXIO; } static int dm_blk_close(struct inode *inode, struct file *file) @@ -228,10 +252,35 @@ static int dm_blk_close(struct inode *in struct mapped_device *md; md = inode->i_bdev->bd_disk->private_data; + atomic_dec(&md->open_count); dm_put(md); return 0; } +int dm_open_count(struct mapped_device *md) +{ + return atomic_read(&md->open_count); +} + +/* + * Guarantees nothing is using the device before it's deleted. + */ +int dm_lock_for_deletion(struct mapped_device *md) +{ + int r = 0; + + spin_lock(&_minor_lock); + + if (dm_open_count(md)) + r = -EBUSY; + else + set_bit(DMF_DELETING, &md->flags); + + spin_unlock(&_minor_lock); + + return r; +} + static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) { struct mapped_device *md = bdev->bd_disk->private_data; @@ -456,8 +505,8 @@ static void __map_bio(struct dm_target * if (r > 0) { /* the bio has been remapped so dispatch it */ - blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone, - tio->io->bio->bi_bdev->bd_dev, sector, + blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone, + tio->io->bio->bi_bdev->bd_dev, sector, clone->bi_sector); generic_make_request(clone); @@ -744,43 +793,39 @@ static int dm_any_congested(void *conges /*----------------------------------------------------------------- * An IDR is used to keep track of allocated minor numbers. *---------------------------------------------------------------*/ -static DEFINE_MUTEX(_minor_lock); static DEFINE_IDR(_minor_idr); -static void free_minor(unsigned int minor) +static void free_minor(int minor) { - mutex_lock(&_minor_lock); + spin_lock(&_minor_lock); idr_remove(&_minor_idr, minor); - mutex_unlock(&_minor_lock); + spin_unlock(&_minor_lock); } /* * See if the device with a specific minor # is free. */ -static int specific_minor(struct mapped_device *md, unsigned int minor) +static int specific_minor(struct mapped_device *md, int minor) { int r, m; if (minor >= (1 << MINORBITS)) return -EINVAL; - mutex_lock(&_minor_lock); + r = idr_pre_get(&_minor_idr, GFP_KERNEL); + if (!r) + return -ENOMEM; + + spin_lock(&_minor_lock); if (idr_find(&_minor_idr, minor)) { r = -EBUSY; goto out; } - r = idr_pre_get(&_minor_idr, GFP_KERNEL); - if (!r) { - r = -ENOMEM; - goto out; - } - - r = idr_get_new_above(&_minor_idr, md, minor, &m); - if (r) { + r = idr_get_new_above(&_minor_idr, MINOR_ALLOCED, minor, &m); + if (r) goto out; - } if (m != minor) { idr_remove(&_minor_idr, m); @@ -789,24 +834,21 @@ static int specific_minor(struct mapped_ } out: - mutex_unlock(&_minor_lock); + spin_unlock(&_minor_lock); return r; } -static int next_free_minor(struct mapped_device *md, unsigned int *minor) +static int next_free_minor(struct mapped_device *md, int *minor) { - int r; - unsigned int m; - - mutex_lock(&_minor_lock); + int r, m; r = idr_pre_get(&_minor_idr, GFP_KERNEL); - if (!r) { - r = -ENOMEM; - goto out; - } + if (!r) + return -ENOMEM; + + spin_lock(&_minor_lock); - r = idr_get_new(&_minor_idr, md, &m); + r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m); if (r) { goto out; } @@ -820,7 +862,7 @@ static int next_free_minor(struct mapped *minor = m; out: - mutex_unlock(&_minor_lock); + spin_unlock(&_minor_lock); return r; } @@ -829,18 +871,25 @@ static struct block_device_operations dm /* * Allocate and initialise a blank device with a given minor. */ -static struct mapped_device *alloc_dev(unsigned int minor, int persistent) +static struct mapped_device *alloc_dev(int minor) { int r; struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL); + void *old_md; if (!md) { DMWARN("unable to allocate device, out of memory."); return NULL; } + if (!try_module_get(THIS_MODULE)) + goto bad0; + /* get a minor number for the dev */ - r = persistent ? specific_minor(md, minor) : next_free_minor(md, &minor); + if (minor == DM_ANY_MINOR) + r = next_free_minor(md, &minor); + else + r = specific_minor(md, minor); if (r < 0) goto bad1; @@ -849,6 +898,7 @@ static struct mapped_device *alloc_dev(u init_MUTEX(&md->suspend_lock); rwlock_init(&md->map_lock); atomic_set(&md->holders, 1); + atomic_set(&md->open_count, 0); atomic_set(&md->event_nr, 0); md->queue = blk_alloc_queue(GFP_KERNEL); @@ -875,6 +925,10 @@ static struct mapped_device *alloc_dev(u if (!md->disk) goto bad4; + atomic_set(&md->pending, 0); + init_waitqueue_head(&md->wait); + init_waitqueue_head(&md->eventq); + md->disk->major = _major; md->disk->first_minor = minor; md->disk->fops = &dm_blk_dops; @@ -884,9 +938,12 @@ static struct mapped_device *alloc_dev(u add_disk(md->disk); format_dev_t(md->name, MKDEV(_major, minor)); - atomic_set(&md->pending, 0); - init_waitqueue_head(&md->wait); - init_waitqueue_head(&md->eventq); + /* Populate the mapping, nobody knows we exist yet */ + spin_lock(&_minor_lock); + old_md = idr_replace(&_minor_idr, md, minor); + spin_unlock(&_minor_lock); + + BUG_ON(old_md != MINOR_ALLOCED); return md; @@ -898,13 +955,15 @@ static struct mapped_device *alloc_dev(u blk_cleanup_queue(md->queue); free_minor(minor); bad1: + module_put(THIS_MODULE); + bad0: kfree(md); return NULL; } static void free_dev(struct mapped_device *md) { - unsigned int minor = md->disk->first_minor; + int minor = md->disk->first_minor; if (md->suspended_bdev) { thaw_bdev(md->suspended_bdev, NULL); @@ -914,8 +973,14 @@ static void free_dev(struct mapped_devic mempool_destroy(md->io_pool); del_gendisk(md->disk); free_minor(minor); + + spin_lock(&_minor_lock); + md->disk->private_data = NULL; + spin_unlock(&_minor_lock); + put_disk(md->disk); blk_cleanup_queue(md->queue); + module_put(THIS_MODULE); kfree(md); } @@ -984,12 +1049,11 @@ static void __unbind(struct mapped_devic /* * Constructor for a new device. */ -static int create_aux(unsigned int minor, int persistent, - struct mapped_device **result) +int dm_create(int minor, struct mapped_device **result) { struct mapped_device *md; - md = alloc_dev(minor, persistent); + md = alloc_dev(minor); if (!md) return -ENXIO; @@ -997,16 +1061,6 @@ static int create_aux(unsigned int minor return 0; } -int dm_create(struct mapped_device **result) -{ - return create_aux(0, 0, result); -} - -int dm_create_with_minor(unsigned int minor, struct mapped_device **result) -{ - return create_aux(minor, 1, result); -} - static struct mapped_device *dm_find_md(dev_t dev) { struct mapped_device *md; @@ -1015,13 +1069,18 @@ static struct mapped_device *dm_find_md( if (MAJOR(dev) != _major || minor >= (1 << MINORBITS)) return NULL; - mutex_lock(&_minor_lock); + spin_lock(&_minor_lock); md = idr_find(&_minor_idr, minor); - if (!md || (dm_disk(md)->first_minor != minor)) + if (md && (md == MINOR_ALLOCED || + (dm_disk(md)->first_minor != minor) || + test_bit(DMF_FREEING, &md->flags))) { md = NULL; + goto out; + } - mutex_unlock(&_minor_lock); +out: + spin_unlock(&_minor_lock); return md; } @@ -1051,12 +1110,23 @@ void dm_get(struct mapped_device *md) atomic_inc(&md->holders); } +const char *dm_device_name(struct mapped_device *md) +{ + return md->name; +} +EXPORT_SYMBOL_GPL(dm_device_name); + void dm_put(struct mapped_device *md) { struct dm_table *map; - if (atomic_dec_and_test(&md->holders)) { + BUG_ON(test_bit(DMF_FREEING, &md->flags)); + + if (atomic_dec_and_lock(&md->holders, &_minor_lock)) { map = dm_get_table(md); + idr_replace(&_minor_idr, MINOR_ALLOCED, dm_disk(md)->first_minor); + set_bit(DMF_FREEING, &md->flags); + spin_unlock(&_minor_lock); if (!dm_suspended(md)) { dm_table_presuspend_targets(map); dm_table_postsuspend_targets(map); diff --git a/drivers/md/dm.h b/drivers/md/dm.h index fd90bc8..3c03c0e 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -2,7 +2,7 @@ * Internal header file for device mapper * * Copyright (C) 2001, 2002 Sistina Software - * Copyright (C) 2004 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. * * This file is released under the LGPL. */ @@ -17,9 +17,10 @@ #include #include #define DM_NAME "device-mapper" -#define DMWARN(f, x...) printk(KERN_WARNING DM_NAME ": " f "\n" , ## x) -#define DMERR(f, x...) printk(KERN_ERR DM_NAME ": " f "\n" , ## x) -#define DMINFO(f, x...) printk(KERN_INFO DM_NAME ": " f "\n" , ## x) + +#define DMERR(f, arg...) printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg) +#define DMWARN(f, arg...) printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg) +#define DMINFO(f, arg...) printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg) #define DMEMIT(x...) sz += ((sz >= maxlen) ? \ 0 : scnprintf(result + sz, maxlen - sz, x)) @@ -39,83 +40,16 @@ struct dm_dev { }; struct dm_table; -struct mapped_device; - -/*----------------------------------------------------------------- - * Functions for manipulating a struct mapped_device. - * Drop the reference with dm_put when you finish with the object. - *---------------------------------------------------------------*/ -int dm_create(struct mapped_device **md); -int dm_create_with_minor(unsigned int minor, struct mapped_device **md); -void dm_set_mdptr(struct mapped_device *md, void *ptr); -void *dm_get_mdptr(struct mapped_device *md); -struct mapped_device *dm_get_md(dev_t dev); - -/* - * Reference counting for md. - */ -void dm_get(struct mapped_device *md); -void dm_put(struct mapped_device *md); - -/* - * A device can still be used while suspended, but I/O is deferred. - */ -int dm_suspend(struct mapped_device *md, int with_lockfs); -int dm_resume(struct mapped_device *md); - -/* - * The device must be suspended before calling this method. - */ -int dm_swap_table(struct mapped_device *md, struct dm_table *t); - -/* - * Drop a reference on the table when you've finished with the - * result. - */ -struct dm_table *dm_get_table(struct mapped_device *md); - -/* - * Event functions. - */ -uint32_t dm_get_event_nr(struct mapped_device *md); -int dm_wait_event(struct mapped_device *md, int event_nr); - -/* - * Info functions. - */ -struct gendisk *dm_disk(struct mapped_device *md); -int dm_suspended(struct mapped_device *md); - -/* - * Geometry functions. - */ -int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo); -int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo); /*----------------------------------------------------------------- - * Functions for manipulating a table. Tables are also reference - * counted. + * Internal table functions. *---------------------------------------------------------------*/ -int dm_table_create(struct dm_table **result, int mode, - unsigned num_targets, struct mapped_device *md); - -void dm_table_get(struct dm_table *t); -void dm_table_put(struct dm_table *t); - -int dm_table_add_target(struct dm_table *t, const char *type, - sector_t start, sector_t len, char *params); -int dm_table_complete(struct dm_table *t); void dm_table_event_callback(struct dm_table *t, void (*fn)(void *), void *context); -void dm_table_event(struct dm_table *t); -sector_t dm_table_get_size(struct dm_table *t); struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index); struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector); void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q); -unsigned int dm_table_get_num_targets(struct dm_table *t); struct list_head *dm_table_get_devices(struct dm_table *t); -int dm_table_get_mode(struct dm_table *t); -struct mapped_device *dm_table_get_md(struct dm_table *t); void dm_table_presuspend_targets(struct dm_table *t); void dm_table_postsuspend_targets(struct dm_table *t); void dm_table_resume_targets(struct dm_table *t); @@ -133,7 +67,6 @@ void dm_put_target_type(struct target_ty int dm_target_iterate(void (*iter_func)(struct target_type *tt, void *param), void *param); - /*----------------------------------------------------------------- * Useful inlines. *---------------------------------------------------------------*/ @@ -191,5 +124,7 @@ void dm_stripe_exit(void); void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size); union map_info *dm_get_mapinfo(struct bio *bio); +int dm_open_count(struct mapped_device *md); +int dm_lock_for_deletion(struct mapped_device *md); #endif diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index 72480a4..73ab875 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c @@ -314,7 +314,7 @@ static void complete_io(unsigned long er if (error) { if (job->rw == WRITE) - job->write_err &= error; + job->write_err |= error; else job->read_err = 1; @@ -460,7 +460,7 @@ static void segment_complete(int read_er job->read_err = 1; if (write_err) - job->write_err &= write_err; + job->write_err |= write_err; /* * Only dispatch more work if there hasn't been an error. diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 7775854..ff83c9b 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -111,7 +111,7 @@ static int linear_issue_flush(request_qu return ret; } -static int linear_run (mddev_t *mddev) +static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) { linear_conf_t *conf; dev_info_t **table; @@ -121,20 +121,21 @@ static int linear_run (mddev_t *mddev) sector_t curr_offset; struct list_head *tmp; - conf = kzalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t), + conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t), GFP_KERNEL); if (!conf) - goto out; + return NULL; + mddev->private = conf; cnt = 0; - mddev->array_size = 0; + conf->array_size = 0; ITERATE_RDEV(mddev,rdev,tmp) { int j = rdev->raid_disk; dev_info_t *disk = conf->disks + j; - if (j < 0 || j > mddev->raid_disks || disk->rdev) { + if (j < 0 || j > raid_disks || disk->rdev) { printk("linear: disk numbering problem. Aborting!\n"); goto out; } @@ -152,11 +153,11 @@ static int linear_run (mddev_t *mddev) blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); disk->size = rdev->size; - mddev->array_size += rdev->size; + conf->array_size += rdev->size; cnt++; } - if (cnt != mddev->raid_disks) { + if (cnt != raid_disks) { printk("linear: not enough drives present. Aborting!\n"); goto out; } @@ -200,7 +201,7 @@ static int linear_run (mddev_t *mddev) unsigned round; unsigned long base; - sz = mddev->array_size >> conf->preshift; + sz = conf->array_size >> conf->preshift; sz += 1; /* force round-up */ base = conf->hash_spacing >> conf->preshift; round = sector_div(sz, base); @@ -247,14 +248,56 @@ static int linear_run (mddev_t *mddev) BUG_ON(table - conf->hash_table > nb_zone); + return conf; + +out: + kfree(conf); + return NULL; +} + +static int linear_run (mddev_t *mddev) +{ + linear_conf_t *conf; + + conf = linear_conf(mddev, mddev->raid_disks); + + if (!conf) + return 1; + mddev->private = conf; + mddev->array_size = conf->array_size; + blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); mddev->queue->unplug_fn = linear_unplug; mddev->queue->issue_flush_fn = linear_issue_flush; return 0; +} -out: - kfree(conf); - return 1; +static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev) +{ + /* Adding a drive to a linear array allows the array to grow. + * It is permitted if the new drive has a matching superblock + * already on it, with raid_disk equal to raid_disks. + * It is achieved by creating a new linear_private_data structure + * and swapping it in in-place of the current one. + * The current one is never freed until the array is stopped. + * This avoids races. + */ + linear_conf_t *newconf; + + if (rdev->raid_disk != mddev->raid_disks) + return -EINVAL; + + newconf = linear_conf(mddev,mddev->raid_disks+1); + + if (!newconf) + return -ENOMEM; + + newconf->prev = mddev_to_conf(mddev); + mddev->private = newconf; + mddev->raid_disks++; + mddev->array_size = newconf->array_size; + set_capacity(mddev->gendisk, mddev->array_size << 1); + return 0; } static int linear_stop (mddev_t *mddev) @@ -262,8 +305,12 @@ static int linear_stop (mddev_t *mddev) linear_conf_t *conf = mddev_to_conf(mddev); blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ - kfree(conf->hash_table); - kfree(conf); + do { + linear_conf_t *t = conf->prev; + kfree(conf->hash_table); + kfree(conf); + conf = t; + } while (conf); return 0; } @@ -360,6 +407,7 @@ static struct mdk_personality linear_per .run = linear_run, .stop = linear_stop, .status = linear_status, + .hot_add_disk = linear_add, }; static int __init linear_init (void) diff --git a/drivers/md/md.c b/drivers/md/md.c index f19b874..306268e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -44,6 +44,7 @@ #include /* for in #include #include #include +#include #include @@ -72,6 +73,10 @@ #endif static LIST_HEAD(pers_list); static DEFINE_SPINLOCK(pers_lock); +static void md_print_devices(void); + +#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); } + /* * Current RAID-1,4,5 parallel reconstruction 'guaranteed speed limit' * is 1000 KB/sec, so the extra system load does not show up that much. @@ -170,7 +175,7 @@ EXPORT_SYMBOL_GPL(md_new_event); /* Alternate version that can be called from interrupts * when calling sysfs_notify isn't needed. */ -void md_new_event_inintr(mddev_t *mddev) +static void md_new_event_inintr(mddev_t *mddev) { atomic_inc(&md_event_count); wake_up(&md_event_waiters); @@ -732,6 +737,7 @@ static int super_90_validate(mddev_t *md { mdp_disk_t *desc; mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page); + __u64 ev1 = md_event(sb); rdev->raid_disk = -1; rdev->flags = 0; @@ -748,7 +754,7 @@ static int super_90_validate(mddev_t *md mddev->layout = sb->layout; mddev->raid_disks = sb->raid_disks; mddev->size = sb->size; - mddev->events = md_event(sb); + mddev->events = ev1; mddev->bitmap_offset = 0; mddev->default_bitmap_offset = MD_SB_BYTES >> 9; @@ -797,7 +803,6 @@ static int super_90_validate(mddev_t *md } else if (mddev->pers == NULL) { /* Insist on good event counter while assembling */ - __u64 ev1 = md_event(sb); ++ev1; if (ev1 < mddev->events) return -EINVAL; @@ -805,19 +810,21 @@ static int super_90_validate(mddev_t *md /* if adding to array with a bitmap, then we can accept an * older device ... but not too old. */ - __u64 ev1 = md_event(sb); if (ev1 < mddev->bitmap->events_cleared) return 0; - } else /* just a hot-add of a new device, leave raid_disk at -1 */ - return 0; + } else { + if (ev1 < mddev->events) + /* just a hot-add of a new device, leave raid_disk at -1 */ + return 0; + } if (mddev->level != LEVEL_MULTIPATH) { desc = sb->disks + rdev->desc_nr; if (desc->state & (1<flags); - else if (desc->state & (1<raid_disk < mddev->raid_disks) { + else if (desc->state & (1<raid_disk < mddev->raid_disks */) { set_bit(In_sync, &rdev->flags); rdev->raid_disk = desc->raid_disk; } @@ -1100,6 +1107,7 @@ static int super_1_load(mdk_rdev_t *rdev static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) { struct mdp_superblock_1 *sb = (struct mdp_superblock_1*)page_address(rdev->sb_page); + __u64 ev1 = le64_to_cpu(sb->events); rdev->raid_disk = -1; rdev->flags = 0; @@ -1115,7 +1123,7 @@ static int super_1_validate(mddev_t *mdd mddev->layout = le32_to_cpu(sb->layout); mddev->raid_disks = le32_to_cpu(sb->raid_disks); mddev->size = le64_to_cpu(sb->size)/2; - mddev->events = le64_to_cpu(sb->events); + mddev->events = ev1; mddev->bitmap_offset = 0; mddev->default_bitmap_offset = 1024 >> 9; @@ -1149,7 +1157,6 @@ static int super_1_validate(mddev_t *mdd } else if (mddev->pers == NULL) { /* Insist of good event counter while assembling */ - __u64 ev1 = le64_to_cpu(sb->events); ++ev1; if (ev1 < mddev->events) return -EINVAL; @@ -1157,12 +1164,13 @@ static int super_1_validate(mddev_t *mdd /* If adding to array with a bitmap, then we can accept an * older device, but not too old. */ - __u64 ev1 = le64_to_cpu(sb->events); if (ev1 < mddev->bitmap->events_cleared) return 0; - } else /* just a hot-add of a new device, leave raid_disk at -1 */ - return 0; - + } else { + if (ev1 < mddev->events) + /* just a hot-add of a new device, leave raid_disk at -1 */ + return 0; + } if (mddev->level != LEVEL_MULTIPATH) { int role; rdev->desc_nr = le32_to_cpu(sb->dev_number); @@ -1174,7 +1182,11 @@ static int super_1_validate(mddev_t *mdd set_bit(Faulty, &rdev->flags); break; default: - set_bit(In_sync, &rdev->flags); + if ((le32_to_cpu(sb->feature_map) & + MD_FEATURE_RECOVERY_OFFSET)) + rdev->recovery_offset = le64_to_cpu(sb->recovery_offset); + else + set_bit(In_sync, &rdev->flags); rdev->raid_disk = role; break; } @@ -1198,6 +1210,7 @@ static void super_1_sync(mddev_t *mddev, sb->feature_map = 0; sb->pad0 = 0; + sb->recovery_offset = cpu_to_le64(0); memset(sb->pad1, 0, sizeof(sb->pad1)); memset(sb->pad2, 0, sizeof(sb->pad2)); memset(sb->pad3, 0, sizeof(sb->pad3)); @@ -1218,6 +1231,14 @@ static void super_1_sync(mddev_t *mddev, sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset); sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); } + + if (rdev->raid_disk >= 0 && + !test_bit(In_sync, &rdev->flags) && + rdev->recovery_offset > 0) { + sb->feature_map |= cpu_to_le32(MD_FEATURE_RECOVERY_OFFSET); + sb->recovery_offset = cpu_to_le64(rdev->recovery_offset); + } + if (mddev->reshape_position != MaxSector) { sb->feature_map |= cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE); sb->reshape_position = cpu_to_le64(mddev->reshape_position); @@ -1242,11 +1263,12 @@ static void super_1_sync(mddev_t *mddev, sb->dev_roles[i] = cpu_to_le16(0xfffe); else if (test_bit(In_sync, &rdev2->flags)) sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk); + else if (rdev2->raid_disk >= 0 && rdev2->recovery_offset > 0) + sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk); else sb->dev_roles[i] = cpu_to_le16(0xffff); } - sb->recovery_offset = cpu_to_le64(0); /* not supported yet */ sb->sb_csum = calc_sb_1_csum(sb); } @@ -1507,7 +1529,7 @@ static void print_rdev(mdk_rdev_t *rdev) printk(KERN_INFO "md: no rdev superblock!\n"); } -void md_print_devices(void) +static void md_print_devices(void) { struct list_head *tmp, *tmp2; mdk_rdev_t *rdev; @@ -1536,15 +1558,30 @@ void md_print_devices(void) } -static void sync_sbs(mddev_t * mddev) +static void sync_sbs(mddev_t * mddev, int nospares) { + /* Update each superblock (in-memory image), but + * if we are allowed to, skip spares which already + * have the right event counter, or have one earlier + * (which would mean they aren't being marked as dirty + * with the rest of the array) + */ mdk_rdev_t *rdev; struct list_head *tmp; ITERATE_RDEV(mddev,rdev,tmp) { - super_types[mddev->major_version]. - sync_super(mddev, rdev); - rdev->sb_loaded = 1; + if (rdev->sb_events == mddev->events || + (nospares && + rdev->raid_disk < 0 && + (rdev->sb_events&1)==0 && + rdev->sb_events+1 == mddev->events)) { + /* Don't update this superblock */ + rdev->sb_loaded = 2; + } else { + super_types[mddev->major_version]. + sync_super(mddev, rdev); + rdev->sb_loaded = 1; + } } } @@ -1554,12 +1591,42 @@ void md_update_sb(mddev_t * mddev) struct list_head *tmp; mdk_rdev_t *rdev; int sync_req; + int nospares = 0; repeat: spin_lock_irq(&mddev->write_lock); sync_req = mddev->in_sync; mddev->utime = get_seconds(); - mddev->events ++; + if (mddev->sb_dirty == 3) + /* just a clean<-> dirty transition, possibly leave spares alone, + * though if events isn't the right even/odd, we will have to do + * spares after all + */ + nospares = 1; + + /* If this is just a dirty<->clean transition, and the array is clean + * and 'events' is odd, we can roll back to the previous clean state */ + if (mddev->sb_dirty == 3 + && (mddev->in_sync && mddev->recovery_cp == MaxSector) + && (mddev->events & 1)) + mddev->events--; + else { + /* otherwise we have to go forward and ... */ + mddev->events ++; + if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */ + /* .. if the array isn't clean, insist on an odd 'events' */ + if ((mddev->events&1)==0) { + mddev->events++; + nospares = 0; + } + } else { + /* otherwise insist on an even 'events' (for clean states) */ + if ((mddev->events&1)) { + mddev->events++; + nospares = 0; + } + } + } if (!mddev->events) { /* @@ -1571,7 +1638,7 @@ repeat: mddev->events --; } mddev->sb_dirty = 2; - sync_sbs(mddev); + sync_sbs(mddev, nospares); /* * do not write anything to disk if using @@ -1593,6 +1660,8 @@ repeat: ITERATE_RDEV(mddev,rdev,tmp) { char b[BDEVNAME_SIZE]; dprintk(KERN_INFO "md: "); + if (rdev->sb_loaded != 1) + continue; /* no noise on spare devices */ if (test_bit(Faulty, &rdev->flags)) dprintk("(skipping faulty "); @@ -1604,6 +1673,7 @@ repeat: dprintk(KERN_INFO "(write) %s's sb offset: %llu\n", bdevname(rdev->bdev,b), (unsigned long long)rdev->sb_offset); + rdev->sb_events = mddev->events; } else dprintk(")\n"); @@ -1667,6 +1737,10 @@ state_show(mdk_rdev_t *rdev, char *page) len += sprintf(page+len, "%sin_sync",sep); sep = ","; } + if (test_bit(WriteMostly, &rdev->flags)) { + len += sprintf(page+len, "%swrite_mostly",sep); + sep = ","; + } if (!test_bit(Faulty, &rdev->flags) && !test_bit(In_sync, &rdev->flags)) { len += sprintf(page+len, "%sspare", sep); @@ -1675,8 +1749,40 @@ state_show(mdk_rdev_t *rdev, char *page) return len+sprintf(page+len, "\n"); } +static ssize_t +state_store(mdk_rdev_t *rdev, const char *buf, size_t len) +{ + /* can write + * faulty - simulates and error + * remove - disconnects the device + * writemostly - sets write_mostly + * -writemostly - clears write_mostly + */ + int err = -EINVAL; + if (cmd_match(buf, "faulty") && rdev->mddev->pers) { + md_error(rdev->mddev, rdev); + err = 0; + } else if (cmd_match(buf, "remove")) { + if (rdev->raid_disk >= 0) + err = -EBUSY; + else { + mddev_t *mddev = rdev->mddev; + kick_rdev_from_array(rdev); + md_update_sb(mddev); + md_new_event(mddev); + err = 0; + } + } else if (cmd_match(buf, "writemostly")) { + set_bit(WriteMostly, &rdev->flags); + err = 0; + } else if (cmd_match(buf, "-writemostly")) { + clear_bit(WriteMostly, &rdev->flags); + err = 0; + } + return err ? err : len; +} static struct rdev_sysfs_entry -rdev_state = __ATTR_RO(state); +rdev_state = __ATTR(state, 0644, state_show, state_store); static ssize_t super_show(mdk_rdev_t *rdev, char *page) @@ -1873,6 +1979,7 @@ static mdk_rdev_t *md_import_device(dev_ rdev->desc_nr = -1; rdev->flags = 0; rdev->data_offset = 0; + rdev->sb_events = 0; atomic_set(&rdev->nr_pending, 0); atomic_set(&rdev->read_errors, 0); atomic_set(&rdev->corrected_errors, 0); @@ -1978,6 +2085,54 @@ static void analyze_sbs(mddev_t * mddev) } static ssize_t +safe_delay_show(mddev_t *mddev, char *page) +{ + int msec = (mddev->safemode_delay*1000)/HZ; + return sprintf(page, "%d.%03d\n", msec/1000, msec%1000); +} +static ssize_t +safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len) +{ + int scale=1; + int dot=0; + int i; + unsigned long msec; + char buf[30]; + char *e; + /* remove a period, and count digits after it */ + if (len >= sizeof(buf)) + return -EINVAL; + strlcpy(buf, cbuf, len); + buf[len] = 0; + for (i=0; isafemode_delay = 0; + else { + mddev->safemode_delay = (msec*HZ)/1000; + if (mddev->safemode_delay == 0) + mddev->safemode_delay = 1; + } + return len; +} +static struct md_sysfs_entry md_safe_delay = +__ATTR(safe_mode_delay, 0644,safe_delay_show, safe_delay_store); + +static ssize_t level_show(mddev_t *mddev, char *page) { struct mdk_personality *p = mddev->pers; @@ -2012,6 +2167,32 @@ level_store(mddev_t *mddev, const char * static struct md_sysfs_entry md_level = __ATTR(level, 0644, level_show, level_store); + +static ssize_t +layout_show(mddev_t *mddev, char *page) +{ + /* just a number, not meaningful for all levels */ + return sprintf(page, "%d\n", mddev->layout); +} + +static ssize_t +layout_store(mddev_t *mddev, const char *buf, size_t len) +{ + char *e; + unsigned long n = simple_strtoul(buf, &e, 10); + if (mddev->pers) + return -EBUSY; + + if (!*buf || (*e && *e != '\n')) + return -EINVAL; + + mddev->layout = n; + return len; +} +static struct md_sysfs_entry md_layout = +__ATTR(layout, 0655, layout_show, layout_store); + + static ssize_t raid_disks_show(mddev_t *mddev, char *page) { @@ -2067,6 +2248,200 @@ static struct md_sysfs_entry md_chunk_si __ATTR(chunk_size, 0644, chunk_size_show, chunk_size_store); static ssize_t +resync_start_show(mddev_t *mddev, char *page) +{ + return sprintf(page, "%llu\n", (unsigned long long)mddev->recovery_cp); +} + +static ssize_t +resync_start_store(mddev_t *mddev, const char *buf, size_t len) +{ + /* can only set chunk_size if array is not yet active */ + char *e; + unsigned long long n = simple_strtoull(buf, &e, 10); + + if (mddev->pers) + return -EBUSY; + if (!*buf || (*e && *e != '\n')) + return -EINVAL; + + mddev->recovery_cp = n; + return len; +} +static struct md_sysfs_entry md_resync_start = +__ATTR(resync_start, 0644, resync_start_show, resync_start_store); + +/* + * The array state can be: + * + * clear + * No devices, no size, no level + * Equivalent to STOP_ARRAY ioctl + * inactive + * May have some settings, but array is not active + * all IO results in error + * When written, doesn't tear down array, but just stops it + * suspended (not supported yet) + * All IO requests will block. The array can be reconfigured. + * Writing this, if accepted, will block until array is quiessent + * readonly + * no resync can happen. no superblocks get written. + * write requests fail + * read-auto + * like readonly, but behaves like 'clean' on a write request. + * + * clean - no pending writes, but otherwise active. + * When written to inactive array, starts without resync + * If a write request arrives then + * if metadata is known, mark 'dirty' and switch to 'active'. + * if not known, block and switch to write-pending + * If written to an active array that has pending writes, then fails. + * active + * fully active: IO and resync can be happening. + * When written to inactive array, starts with resync + * + * write-pending + * clean, but writes are blocked waiting for 'active' to be written. + * + * active-idle + * like active, but no writes have been seen for a while (100msec). + * + */ +enum array_state { clear, inactive, suspended, readonly, read_auto, clean, active, + write_pending, active_idle, bad_word}; +static char *array_states[] = { + "clear", "inactive", "suspended", "readonly", "read-auto", "clean", "active", + "write-pending", "active-idle", NULL }; + +static int match_word(const char *word, char **list) +{ + int n; + for (n=0; list[n]; n++) + if (cmd_match(word, list[n])) + break; + return n; +} + +static ssize_t +array_state_show(mddev_t *mddev, char *page) +{ + enum array_state st = inactive; + + if (mddev->pers) + switch(mddev->ro) { + case 1: + st = readonly; + break; + case 2: + st = read_auto; + break; + case 0: + if (mddev->in_sync) + st = clean; + else if (mddev->safemode) + st = active_idle; + else + st = active; + } + else { + if (list_empty(&mddev->disks) && + mddev->raid_disks == 0 && + mddev->size == 0) + st = clear; + else + st = inactive; + } + return sprintf(page, "%s\n", array_states[st]); +} + +static int do_md_stop(mddev_t * mddev, int ro); +static int do_md_run(mddev_t * mddev); +static int restart_array(mddev_t *mddev); + +static ssize_t +array_state_store(mddev_t *mddev, const char *buf, size_t len) +{ + int err = -EINVAL; + enum array_state st = match_word(buf, array_states); + switch(st) { + case bad_word: + break; + case clear: + /* stopping an active array */ + if (mddev->pers) { + if (atomic_read(&mddev->active) > 1) + return -EBUSY; + err = do_md_stop(mddev, 0); + } + break; + case inactive: + /* stopping an active array */ + if (mddev->pers) { + if (atomic_read(&mddev->active) > 1) + return -EBUSY; + err = do_md_stop(mddev, 2); + } + break; + case suspended: + break; /* not supported yet */ + case readonly: + if (mddev->pers) + err = do_md_stop(mddev, 1); + else { + mddev->ro = 1; + err = do_md_run(mddev); + } + break; + case read_auto: + /* stopping an active array */ + if (mddev->pers) { + err = do_md_stop(mddev, 1); + if (err == 0) + mddev->ro = 2; /* FIXME mark devices writable */ + } else { + mddev->ro = 2; + err = do_md_run(mddev); + } + break; + case clean: + if (mddev->pers) { + restart_array(mddev); + spin_lock_irq(&mddev->write_lock); + if (atomic_read(&mddev->writes_pending) == 0) { + mddev->in_sync = 1; + mddev->sb_dirty = 1; + } + spin_unlock_irq(&mddev->write_lock); + } else { + mddev->ro = 0; + mddev->recovery_cp = MaxSector; + err = do_md_run(mddev); + } + break; + case active: + if (mddev->pers) { + restart_array(mddev); + mddev->sb_dirty = 0; + wake_up(&mddev->sb_wait); + err = 0; + } else { + mddev->ro = 0; + err = do_md_run(mddev); + } + break; + case write_pending: + case active_idle: + /* these cannot be set */ + break; + } + if (err) + return err; + else + return len; +} +static struct md_sysfs_entry md_array_state = __ATTR(array_state, 0644, array_state_show, array_state_store); + +static ssize_t null_show(mddev_t *mddev, char *page) { return -EINVAL; @@ -2428,11 +2803,15 @@ __ATTR(suspend_hi, S_IRUGO|S_IWUSR, susp static struct attribute *md_default_attrs[] = { &md_level.attr, + &md_layout.attr, &md_raid_disks.attr, &md_chunk_size.attr, &md_size.attr, + &md_resync_start.attr, &md_metadata.attr, &md_new_device.attr, + &md_safe_delay.attr, + &md_array_state.attr, NULL, }; @@ -2553,8 +2932,6 @@ static struct kobject *md_probe(dev_t de return NULL; } -void md_wakeup_thread(mdk_thread_t *thread); - static void md_safemode_timeout(unsigned long data) { mddev_t *mddev = (mddev_t *) data; @@ -2708,7 +3085,7 @@ #endif mddev->safemode = 0; mddev->safemode_timer.function = md_safemode_timeout; mddev->safemode_timer.data = (unsigned long) mddev; - mddev->safemode_delay = (20 * HZ)/1000 +1; /* 20 msec delay */ + mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */ mddev->in_sync = 1; ITERATE_RDEV(mddev,rdev,tmp) @@ -2736,6 +3113,36 @@ #endif mddev->queue->queuedata = mddev; mddev->queue->make_request_fn = mddev->pers->make_request; + /* If there is a partially-recovered drive we need to + * start recovery here. If we leave it to md_check_recovery, + * it will remove the drives and not do the right thing + */ + if (mddev->degraded) { + struct list_head *rtmp; + int spares = 0; + ITERATE_RDEV(mddev,rdev,rtmp) + if (rdev->raid_disk >= 0 && + !test_bit(In_sync, &rdev->flags) && + !test_bit(Faulty, &rdev->flags)) + /* complete an interrupted recovery */ + spares++; + if (spares && mddev->pers->sync_request) { + mddev->recovery = 0; + set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); + mddev->sync_thread = md_register_thread(md_do_sync, + mddev, + "%s_resync"); + if (!mddev->sync_thread) { + printk(KERN_ERR "%s: could not start resync" + " thread...\n", + mdname(mddev)); + /* leave the spares where they are, it shouldn't hurt */ + mddev->recovery = 0; + } else + md_wakeup_thread(mddev->sync_thread); + } + } + mddev->changed = 1; md_new_event(mddev); return 0; @@ -2769,18 +3176,47 @@ static int restart_array(mddev_t *mddev) */ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); + md_wakeup_thread(mddev->sync_thread); err = 0; - } else { - printk(KERN_ERR "md: %s has no personality assigned.\n", - mdname(mddev)); + } else err = -EINVAL; - } out: return err; } -static int do_md_stop(mddev_t * mddev, int ro) +/* similar to deny_write_access, but accounts for our holding a reference + * to the file ourselves */ +static int deny_bitmap_write_access(struct file * file) +{ + struct inode *inode = file->f_mapping->host; + + spin_lock(&inode->i_lock); + if (atomic_read(&inode->i_writecount) > 1) { + spin_unlock(&inode->i_lock); + return -ETXTBSY; + } + atomic_set(&inode->i_writecount, -1); + spin_unlock(&inode->i_lock); + + return 0; +} + +static void restore_bitmap_write_access(struct file *file) +{ + struct inode *inode = file->f_mapping->host; + + spin_lock(&inode->i_lock); + atomic_set(&inode->i_writecount, 1); + spin_unlock(&inode->i_lock); +} + +/* mode: + * 0 - completely stop and dis-assemble array + * 1 - switch to readonly + * 2 - stop but do not disassemble array + */ +static int do_md_stop(mddev_t * mddev, int mode) { int err = 0; struct gendisk *disk = mddev->gendisk; @@ -2792,6 +3228,7 @@ static int do_md_stop(mddev_t * mddev, i } if (mddev->sync_thread) { + set_bit(MD_RECOVERY_FROZEN, &mddev->recovery); set_bit(MD_RECOVERY_INTR, &mddev->recovery); md_unregister_thread(mddev->sync_thread); mddev->sync_thread = NULL; @@ -2801,12 +3238,15 @@ static int do_md_stop(mddev_t * mddev, i invalidate_partition(disk, 0); - if (ro) { + switch(mode) { + case 1: /* readonly */ err = -ENXIO; if (mddev->ro==1) goto out; mddev->ro = 1; - } else { + break; + case 0: /* disassemble */ + case 2: /* stop */ bitmap_flush(mddev); md_super_wait(mddev); if (mddev->ro) @@ -2821,19 +3261,20 @@ static int do_md_stop(mddev_t * mddev, i if (mddev->ro) mddev->ro = 0; } - if (!mddev->in_sync) { + if (!mddev->in_sync || mddev->sb_dirty) { /* mark array as shutdown cleanly */ mddev->in_sync = 1; md_update_sb(mddev); } - if (ro) + if (mode == 1) set_disk_ro(disk, 1); + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); } /* * Free resources if final stop */ - if (!ro) { + if (mode == 0) { mdk_rdev_t *rdev; struct list_head *tmp; struct gendisk *disk; @@ -2841,7 +3282,7 @@ static int do_md_stop(mddev_t * mddev, i bitmap_destroy(mddev); if (mddev->bitmap_file) { - atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1); + restore_bitmap_write_access(mddev->bitmap_file); fput(mddev->bitmap_file); mddev->bitmap_file = NULL; } @@ -2857,11 +3298,15 @@ static int do_md_stop(mddev_t * mddev, i export_array(mddev); mddev->array_size = 0; + mddev->size = 0; + mddev->raid_disks = 0; + mddev->recovery_cp = 0; + disk = mddev->gendisk; if (disk) set_capacity(disk, 0); mddev->changed = 1; - } else + } else if (mddev->pers) printk(KERN_INFO "md: %s switched to read-only mode.\n", mdname(mddev)); err = 0; @@ -3264,6 +3709,17 @@ static int add_new_disk(mddev_t * mddev, rdev->raid_disk = -1; err = bind_rdev_to_array(rdev, mddev); + if (!err && !mddev->pers->hot_remove_disk) { + /* If there is hot_add_disk but no hot_remove_disk + * then added disks for geometry changes, + * and should be added immediately. + */ + super_types[mddev->major_version]. + validate_super(mddev, rdev); + err = mddev->pers->hot_add_disk(mddev, rdev); + if (err) + unbind_rdev_from_array(rdev); + } if (err) export_rdev(rdev); @@ -3434,23 +3890,6 @@ abort_export: return err; } -/* similar to deny_write_access, but accounts for our holding a reference - * to the file ourselves */ -static int deny_bitmap_write_access(struct file * file) -{ - struct inode *inode = file->f_mapping->host; - - spin_lock(&inode->i_lock); - if (atomic_read(&inode->i_writecount) > 1) { - spin_unlock(&inode->i_lock); - return -ETXTBSY; - } - atomic_set(&inode->i_writecount, -1); - spin_unlock(&inode->i_lock); - - return 0; -} - static int set_bitmap_file(mddev_t *mddev, int fd) { int err; @@ -3491,12 +3930,17 @@ static int set_bitmap_file(mddev_t *mdde mddev->pers->quiesce(mddev, 1); if (fd >= 0) err = bitmap_create(mddev); - if (fd < 0 || err) + if (fd < 0 || err) { bitmap_destroy(mddev); + fd = -1; /* make sure to put the file */ + } mddev->pers->quiesce(mddev, 0); - } else if (fd < 0) { - if (mddev->bitmap_file) + } + if (fd < 0) { + if (mddev->bitmap_file) { + restore_bitmap_write_access(mddev->bitmap_file); fput(mddev->bitmap_file); + } mddev->bitmap_file = NULL; } @@ -3977,11 +4421,6 @@ #endif goto done_unlock; default: - if (_IOC_TYPE(cmd) == MD_MAJOR) - printk(KERN_WARNING "md: %s(pid %d) used" - " obsolete MD ioctl, upgrade your" - " software to use new ictls.\n", - current->comm, current->pid); err = -EINVAL; goto abort_unlock; } @@ -4586,7 +5025,7 @@ void md_write_start(mddev_t *mddev, stru spin_lock_irq(&mddev->write_lock); if (mddev->in_sync) { mddev->in_sync = 0; - mddev->sb_dirty = 1; + mddev->sb_dirty = 3; md_wakeup_thread(mddev->thread); } spin_unlock_irq(&mddev->write_lock); @@ -4599,7 +5038,7 @@ void md_write_end(mddev_t *mddev) if (atomic_dec_and_test(&mddev->writes_pending)) { if (mddev->safemode == 2) md_wakeup_thread(mddev->thread); - else + else if (mddev->safemode_delay) mod_timer(&mddev->safemode_timer, jiffies + mddev->safemode_delay); } } @@ -4620,10 +5059,14 @@ void md_do_sync(mddev_t *mddev) struct list_head *tmp; sector_t last_check; int skipped = 0; + struct list_head *rtmp; + mdk_rdev_t *rdev; /* just incase thread restarts... */ if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) return; + if (mddev->ro) /* never try to sync a read-only array */ + return; /* we overload curr_resync somewhat here. * 0 == not engaged in resync at all @@ -4682,17 +5125,30 @@ void md_do_sync(mddev_t *mddev) } } while (mddev->curr_resync < 2); + j = 0; if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { /* resync follows the size requested by the personality, * which defaults to physical size, but can be virtual size */ max_sectors = mddev->resync_max_sectors; mddev->resync_mismatches = 0; + /* we don't use the checkpoint if there's a bitmap */ + if (!mddev->bitmap && + !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) + j = mddev->recovery_cp; } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) max_sectors = mddev->size << 1; - else + else { /* recovery follows the physical size of devices */ max_sectors = mddev->size << 1; + j = MaxSector; + ITERATE_RDEV(mddev,rdev,rtmp) + if (rdev->raid_disk >= 0 && + !test_bit(Faulty, &rdev->flags) && + !test_bit(In_sync, &rdev->flags) && + rdev->recovery_offset < j) + j = rdev->recovery_offset; + } printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev)); printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:" @@ -4702,12 +5158,7 @@ void md_do_sync(mddev_t *mddev) speed_max(mddev)); is_mddev_idle(mddev); /* this also initializes IO event counters */ - /* we don't use the checkpoint if there's a bitmap */ - if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap - && ! test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) - j = mddev->recovery_cp; - else - j = 0; + io_sectors = 0; for (m = 0; m < SYNC_MARKS; m++) { mark[m] = jiffies; @@ -4828,15 +5279,28 @@ void md_do_sync(mddev_t *mddev) if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && - mddev->curr_resync > 2 && - mddev->curr_resync >= mddev->recovery_cp) { - if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { - printk(KERN_INFO - "md: checkpointing recovery of %s.\n", - mdname(mddev)); - mddev->recovery_cp = mddev->curr_resync; - } else - mddev->recovery_cp = MaxSector; + mddev->curr_resync > 2) { + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { + if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { + if (mddev->curr_resync >= mddev->recovery_cp) { + printk(KERN_INFO + "md: checkpointing recovery of %s.\n", + mdname(mddev)); + mddev->recovery_cp = mddev->curr_resync; + } + } else + mddev->recovery_cp = MaxSector; + } else { + if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) + mddev->curr_resync = MaxSector; + ITERATE_RDEV(mddev,rdev,rtmp) + if (rdev->raid_disk >= 0 && + !test_bit(Faulty, &rdev->flags) && + !test_bit(In_sync, &rdev->flags) && + rdev->recovery_offset < mddev->curr_resync) + rdev->recovery_offset = mddev->curr_resync; + mddev->sb_dirty = 1; + } } skip: @@ -4908,7 +5372,7 @@ void md_check_recovery(mddev_t *mddev) if (mddev->safemode && !atomic_read(&mddev->writes_pending) && !mddev->in_sync && mddev->recovery_cp == MaxSector) { mddev->in_sync = 1; - mddev->sb_dirty = 1; + mddev->sb_dirty = 3; } if (mddev->safemode == 1) mddev->safemode = 0; @@ -4957,6 +5421,8 @@ void md_check_recovery(mddev_t *mddev) clear_bit(MD_RECOVERY_INTR, &mddev->recovery); clear_bit(MD_RECOVERY_DONE, &mddev->recovery); + if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery)) + goto unlock; /* no recovery is running. * remove any failed drives, then * add spares if possible. @@ -4979,6 +5445,7 @@ void md_check_recovery(mddev_t *mddev) ITERATE_RDEV(mddev,rdev,rtmp) if (rdev->raid_disk < 0 && !test_bit(Faulty, &rdev->flags)) { + rdev->recovery_offset = 0; if (mddev->pers->hot_add_disk(mddev,rdev)) { char nm[20]; sprintf(nm, "rd%d", rdev->raid_disk); @@ -5216,7 +5683,6 @@ EXPORT_SYMBOL(md_write_end); EXPORT_SYMBOL(md_register_thread); EXPORT_SYMBOL(md_unregister_thread); EXPORT_SYMBOL(md_wakeup_thread); -EXPORT_SYMBOL(md_print_devices); EXPORT_SYMBOL(md_check_recovery); MODULE_LICENSE("GPL"); MODULE_ALIAS("md"); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 4070eff..cead918 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -374,26 +374,26 @@ static int raid1_end_write_request(struc * already. */ if (atomic_dec_and_test(&r1_bio->remaining)) { - if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { + if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) reschedule_retry(r1_bio); - goto out; - } - /* it really is the end of this request */ - if (test_bit(R1BIO_BehindIO, &r1_bio->state)) { - /* free extra copy of the data pages */ - int i = bio->bi_vcnt; - while (i--) - safe_put_page(bio->bi_io_vec[i].bv_page); + else { + /* it really is the end of this request */ + if (test_bit(R1BIO_BehindIO, &r1_bio->state)) { + /* free extra copy of the data pages */ + int i = bio->bi_vcnt; + while (i--) + safe_put_page(bio->bi_io_vec[i].bv_page); + } + /* clear the bitmap if all writes complete successfully */ + bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector, + r1_bio->sectors, + !test_bit(R1BIO_Degraded, &r1_bio->state), + behind); + md_write_end(r1_bio->mddev); + raid_end_bio_io(r1_bio); } - /* clear the bitmap if all writes complete successfully */ - bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector, - r1_bio->sectors, - !test_bit(R1BIO_Degraded, &r1_bio->state), - behind); - md_write_end(r1_bio->mddev); - raid_end_bio_io(r1_bio); } - out: + if (to_put) bio_put(to_put); @@ -1625,6 +1625,12 @@ static sector_t sync_request(mddev_t *md /* before building a request, check if we can skip these blocks.. * This call the bitmap_start_sync doesn't actually record anything */ + if (mddev->bitmap == NULL && + mddev->recovery_cp == MaxSector && + conf->fullsync == 0) { + *skipped = 1; + return max_sector - sector_nr; + } if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) && !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { /* We can skip this block, and probably several more */ @@ -1888,7 +1894,8 @@ static int run(mddev_t *mddev) disk = conf->mirrors + i; - if (!disk->rdev) { + if (!disk->rdev || + !test_bit(In_sync, &disk->rdev->flags)) { disk->head_position = 0; mddev->degraded++; } diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 1440935..7f63628 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -29,6 +29,7 @@ #include * raid_disks * near_copies (stored in low byte of layout) * far_copies (stored in second byte of layout) + * far_offset (stored in bit 16 of layout ) * * The data to be stored is divided into chunks using chunksize. * Each device is divided into far_copies sections. @@ -36,10 +37,14 @@ #include * near_copies copies of each chunk is stored (each on a different drive). * The starting device for each section is offset near_copies from the starting * device of the previous section. - * Thus there are (near_copies*far_copies) of each chunk, and each is on a different + * Thus they are (near_copies*far_copies) of each chunk, and each is on a different * drive. * near_copies and far_copies must be at least one, and their product is at most * raid_disks. + * + * If far_offset is true, then the far_copies are handled a bit differently. + * The copies are still in different stripes, but instead of be very far apart + * on disk, there are adjacent stripes. */ /* @@ -357,8 +362,7 @@ static int raid10_end_write_request(stru * With this layout, and block is never stored twice on the one device. * * raid10_find_phys finds the sector offset of a given virtual sector - * on each device that it is on. If a block isn't on a device, - * that entry in the array is set to MaxSector. + * on each device that it is on. * * raid10_find_virt does the reverse mapping, from a device and a * sector offset to a virtual address @@ -381,6 +385,8 @@ static void raid10_find_phys(conf_t *con chunk *= conf->near_copies; stripe = chunk; dev = sector_div(stripe, conf->raid_disks); + if (conf->far_offset) + stripe *= conf->far_copies; sector += stripe << conf->chunk_shift; @@ -414,16 +420,24 @@ static sector_t raid10_find_virt(conf_t { sector_t offset, chunk, vchunk; - while (sector > conf->stride) { - sector -= conf->stride; - if (dev < conf->near_copies) - dev += conf->raid_disks - conf->near_copies; - else - dev -= conf->near_copies; - } - offset = sector & conf->chunk_mask; - chunk = sector >> conf->chunk_shift; + if (conf->far_offset) { + int fc; + chunk = sector >> conf->chunk_shift; + fc = sector_div(chunk, conf->far_copies); + dev -= fc * conf->near_copies; + if (dev < 0) + dev += conf->raid_disks; + } else { + while (sector > conf->stride) { + sector -= conf->stride; + if (dev < conf->near_copies) + dev += conf->raid_disks - conf->near_copies; + else + dev -= conf->near_copies; + } + chunk = sector >> conf->chunk_shift; + } vchunk = chunk * conf->raid_disks + dev; sector_div(vchunk, conf->near_copies); return (vchunk << conf->chunk_shift) + offset; @@ -900,9 +914,12 @@ static void status(struct seq_file *seq, seq_printf(seq, " %dK chunks", mddev->chunk_size/1024); if (conf->near_copies > 1) seq_printf(seq, " %d near-copies", conf->near_copies); - if (conf->far_copies > 1) - seq_printf(seq, " %d far-copies", conf->far_copies); - + if (conf->far_copies > 1) { + if (conf->far_offset) + seq_printf(seq, " %d offset-copies", conf->far_copies); + else + seq_printf(seq, " %d far-copies", conf->far_copies); + } seq_printf(seq, " [%d/%d] [", conf->raid_disks, conf->working_disks); for (i = 0; i < conf->raid_disks; i++) @@ -1915,7 +1932,7 @@ static int run(mddev_t *mddev) mirror_info_t *disk; mdk_rdev_t *rdev; struct list_head *tmp; - int nc, fc; + int nc, fc, fo; sector_t stride, size; if (mddev->chunk_size == 0) { @@ -1925,8 +1942,9 @@ static int run(mddev_t *mddev) nc = mddev->layout & 255; fc = (mddev->layout >> 8) & 255; + fo = mddev->layout & (1<<16); if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks || - (mddev->layout >> 16)) { + (mddev->layout >> 17)) { printk(KERN_ERR "raid10: %s: unsupported raid10 layout: 0x%8x\n", mdname(mddev), mddev->layout); goto out; @@ -1958,12 +1976,16 @@ static int run(mddev_t *mddev) conf->near_copies = nc; conf->far_copies = fc; conf->copies = nc*fc; + conf->far_offset = fo; conf->chunk_mask = (sector_t)(mddev->chunk_size>>9)-1; conf->chunk_shift = ffz(~mddev->chunk_size) - 9; - stride = mddev->size >> (conf->chunk_shift-1); - sector_div(stride, fc); - conf->stride = stride << conf->chunk_shift; - + if (fo) + conf->stride = 1 << conf->chunk_shift; + else { + stride = mddev->size >> (conf->chunk_shift-1); + sector_div(stride, fc); + conf->stride = stride << conf->chunk_shift; + } conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc, r10bio_pool_free, conf); if (!conf->r10bio_pool) { @@ -2015,7 +2037,8 @@ static int run(mddev_t *mddev) disk = conf->mirrors + i; - if (!disk->rdev) { + if (!disk->rdev || + !test_bit(In_sync, &rdev->flags)) { disk->head_position = 0; mddev->degraded++; } @@ -2037,7 +2060,13 @@ static int run(mddev_t *mddev) /* * Ok, everything is just fine now */ - size = conf->stride * conf->raid_disks; + if (conf->far_offset) { + size = mddev->size >> (conf->chunk_shift-1); + size *= conf->raid_disks; + size <<= conf->chunk_shift; + sector_div(size, conf->far_copies); + } else + size = conf->stride * conf->raid_disks; sector_div(size, conf->near_copies); mddev->array_size = size/2; mddev->resync_max_sectors = size; @@ -2050,7 +2079,7 @@ static int run(mddev_t *mddev) * maybe... */ { - int stripe = conf->raid_disks * mddev->chunk_size / PAGE_SIZE; + int stripe = conf->raid_disks * (mddev->chunk_size / PAGE_SIZE); stripe /= conf->near_copies; if (mddev->queue->backing_dev_info.ra_pages < 2* stripe) mddev->queue->backing_dev_info.ra_pages = 2* stripe; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 3184360..f920e50 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2,8 +2,11 @@ * raid5.c : Multiple Devices driver for Linux * Copyright (C) 1996, 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman * Copyright (C) 1999, 2000 Ingo Molnar + * Copyright (C) 2002, 2003 H. Peter Anvin * - * RAID-5 management functions. + * RAID-4/5/6 management functions. + * Thanks to Penguin Computing for making the RAID-6 development possible + * by donating a test server! * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,11 +22,11 @@ #include #include #include -#include #include #include #include #include +#include "raid6.h" #include @@ -68,6 +71,16 @@ #define inline #define __inline__ #endif +#if !RAID6_USE_EMPTY_ZERO_PAGE +/* In .bss so it's zeroed */ +const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256))); +#endif + +static inline int raid6_next_disk(int disk, int raid_disks) +{ + disk++; + return (disk < raid_disks) ? disk : 0; +} static void print_raid5_conf (raid5_conf_t *conf); static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) @@ -104,7 +117,7 @@ static void release_stripe(struct stripe { raid5_conf_t *conf = sh->raid_conf; unsigned long flags; - + spin_lock_irqsave(&conf->device_lock, flags); __release_stripe(conf, sh); spin_unlock_irqrestore(&conf->device_lock, flags); @@ -117,7 +130,7 @@ static inline void remove_hash(struct st hlist_del_init(&sh->hash); } -static void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) +static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) { struct hlist_head *hp = stripe_hash(conf, sh->sector); @@ -190,7 +203,7 @@ static void init_stripe(struct stripe_he (unsigned long long)sh->sector); remove_hash(sh); - + sh->sector = sector; sh->pd_idx = pd_idx; sh->state = 0; @@ -269,8 +282,9 @@ static struct stripe_head *get_active_st } else { if (!test_bit(STRIPE_HANDLE, &sh->state)) atomic_inc(&conf->active_stripes); - if (!list_empty(&sh->lru)) - list_del_init(&sh->lru); + if (list_empty(&sh->lru)) + BUG(); + list_del_init(&sh->lru); } } } while (sh == NULL); @@ -321,10 +335,9 @@ static int grow_stripes(raid5_conf_t *co return 1; conf->slab_cache = sc; conf->pool_size = devs; - while (num--) { + while (num--) if (!grow_one_stripe(conf)) return 1; - } return 0; } @@ -631,8 +644,7 @@ static void raid5_build_block (struct st dev->req.bi_private = sh; dev->flags = 0; - if (i != sh->pd_idx) - dev->sector = compute_blocknr(sh, i); + dev->sector = compute_blocknr(sh, i); } static void error(mddev_t *mddev, mdk_rdev_t *rdev) @@ -659,7 +671,7 @@ static void error(mddev_t *mddev, mdk_rd " Operation continuing on %d devices\n", bdevname(rdev->bdev,b), conf->working_disks); } -} +} /* * Input: a 'big' sector number, @@ -697,9 +709,12 @@ static sector_t raid5_compute_sector(sec /* * Select the parity disk based on the user selected algorithm. */ - if (conf->level == 4) + switch(conf->level) { + case 4: *pd_idx = data_disks; - else switch (conf->algorithm) { + break; + case 5: + switch (conf->algorithm) { case ALGORITHM_LEFT_ASYMMETRIC: *pd_idx = data_disks - stripe % raid_disks; if (*dd_idx >= *pd_idx) @@ -721,6 +736,39 @@ static sector_t raid5_compute_sector(sec default: printk(KERN_ERR "raid5: unsupported algorithm %d\n", conf->algorithm); + } + break; + case 6: + + /**** FIX THIS ****/ + switch (conf->algorithm) { + case ALGORITHM_LEFT_ASYMMETRIC: + *pd_idx = raid_disks - 1 - (stripe % raid_disks); + if (*pd_idx == raid_disks-1) + (*dd_idx)++; /* Q D D D P */ + else if (*dd_idx >= *pd_idx) + (*dd_idx) += 2; /* D D P Q D */ + break; + case ALGORITHM_RIGHT_ASYMMETRIC: + *pd_idx = stripe % raid_disks; + if (*pd_idx == raid_disks-1) + (*dd_idx)++; /* Q D D D P */ + else if (*dd_idx >= *pd_idx) + (*dd_idx) += 2; /* D D P Q D */ + break; + case ALGORITHM_LEFT_SYMMETRIC: + *pd_idx = raid_disks - 1 - (stripe % raid_disks); + *dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks; + break; + case ALGORITHM_RIGHT_SYMMETRIC: + *pd_idx = stripe % raid_disks; + *dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks; + break; + default: + printk (KERN_CRIT "raid6: unsupported algorithm %d\n", + conf->algorithm); + } + break; } /* @@ -742,12 +790,17 @@ static sector_t compute_blocknr(struct s int chunk_number, dummy1, dummy2, dd_idx = i; sector_t r_sector; + chunk_offset = sector_div(new_sector, sectors_per_chunk); stripe = new_sector; BUG_ON(new_sector != stripe); - - switch (conf->algorithm) { + if (i == sh->pd_idx) + return 0; + switch(conf->level) { + case 4: break; + case 5: + switch (conf->algorithm) { case ALGORITHM_LEFT_ASYMMETRIC: case ALGORITHM_RIGHT_ASYMMETRIC: if (i > sh->pd_idx) @@ -761,7 +814,37 @@ static sector_t compute_blocknr(struct s break; default: printk(KERN_ERR "raid5: unsupported algorithm %d\n", + conf->algorithm); + } + break; + case 6: + data_disks = raid_disks - 2; + if (i == raid6_next_disk(sh->pd_idx, raid_disks)) + return 0; /* It is the Q disk */ + switch (conf->algorithm) { + case ALGORITHM_LEFT_ASYMMETRIC: + case ALGORITHM_RIGHT_ASYMMETRIC: + if (sh->pd_idx == raid_disks-1) + i--; /* Q D D D P */ + else if (i > sh->pd_idx) + i -= 2; /* D D P Q D */ + break; + case ALGORITHM_LEFT_SYMMETRIC: + case ALGORITHM_RIGHT_SYMMETRIC: + if (sh->pd_idx == raid_disks-1) + i--; /* Q D D D P */ + else { + /* D D P Q D */ + if (i < sh->pd_idx) + i += raid_disks; + i -= (sh->pd_idx + 2); + } + break; + default: + printk (KERN_CRIT "raid6: unsupported algorithm %d\n", conf->algorithm); + } + break; } chunk_number = stripe * data_disks + i; @@ -778,10 +861,11 @@ static sector_t compute_blocknr(struct s /* - * Copy data between a page in the stripe cache, and a bio. - * There are no alignment or size guarantees between the page or the - * bio except that there is some overlap. - * All iovecs in the bio must be considered. + * Copy data between a page in the stripe cache, and one or more bion + * The page could align with the middle of the bio, or there could be + * several bion, each with several bio_vecs, which cover part of the page + * Multiple bion are linked together on bi_next. There may be extras + * at the end of this list. We ignore them. */ static void copy_data(int frombio, struct bio *bio, struct page *page, @@ -810,7 +894,7 @@ static void copy_data(int frombio, struc if (len > 0 && page_offset + len > STRIPE_SIZE) clen = STRIPE_SIZE - page_offset; else clen = len; - + if (clen > 0) { char *ba = __bio_kmap_atomic(bio, i, KM_USER0); if (frombio) @@ -862,14 +946,14 @@ static void compute_block(struct stripe_ set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); } -static void compute_parity(struct stripe_head *sh, int method) +static void compute_parity5(struct stripe_head *sh, int method) { raid5_conf_t *conf = sh->raid_conf; int i, pd_idx = sh->pd_idx, disks = sh->disks, count; void *ptr[MAX_XOR_BLOCKS]; struct bio *chosen; - PRINTK("compute_parity, stripe %llu, method %d\n", + PRINTK("compute_parity5, stripe %llu, method %d\n", (unsigned long long)sh->sector, method); count = 1; @@ -956,9 +1040,195 @@ static void compute_parity(struct stripe clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags); } +static void compute_parity6(struct stripe_head *sh, int method) +{ + raid6_conf_t *conf = sh->raid_conf; + int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = conf->raid_disks, count; + struct bio *chosen; + /**** FIX THIS: This could be very bad if disks is close to 256 ****/ + void *ptrs[disks]; + + qd_idx = raid6_next_disk(pd_idx, disks); + d0_idx = raid6_next_disk(qd_idx, disks); + + PRINTK("compute_parity, stripe %llu, method %d\n", + (unsigned long long)sh->sector, method); + + switch(method) { + case READ_MODIFY_WRITE: + BUG(); /* READ_MODIFY_WRITE N/A for RAID-6 */ + case RECONSTRUCT_WRITE: + for (i= disks; i-- ;) + if ( i != pd_idx && i != qd_idx && sh->dev[i].towrite ) { + chosen = sh->dev[i].towrite; + sh->dev[i].towrite = NULL; + + if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) + wake_up(&conf->wait_for_overlap); + + if (sh->dev[i].written) BUG(); + sh->dev[i].written = chosen; + } + break; + case CHECK_PARITY: + BUG(); /* Not implemented yet */ + } + + for (i = disks; i--;) + if (sh->dev[i].written) { + sector_t sector = sh->dev[i].sector; + struct bio *wbi = sh->dev[i].written; + while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) { + copy_data(1, wbi, sh->dev[i].page, sector); + wbi = r5_next_bio(wbi, sector); + } + + set_bit(R5_LOCKED, &sh->dev[i].flags); + set_bit(R5_UPTODATE, &sh->dev[i].flags); + } + +// switch(method) { +// case RECONSTRUCT_WRITE: +// case CHECK_PARITY: +// case UPDATE_PARITY: + /* Note that unlike RAID-5, the ordering of the disks matters greatly. */ + /* FIX: Is this ordering of drives even remotely optimal? */ + count = 0; + i = d0_idx; + do { + ptrs[count++] = page_address(sh->dev[i].page); + if (count <= disks-2 && !test_bit(R5_UPTODATE, &sh->dev[i].flags)) + printk("block %d/%d not uptodate on parity calc\n", i,count); + i = raid6_next_disk(i, disks); + } while ( i != d0_idx ); +// break; +// } + + raid6_call.gen_syndrome(disks, STRIPE_SIZE, ptrs); + + switch(method) { + case RECONSTRUCT_WRITE: + set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags); + set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags); + set_bit(R5_LOCKED, &sh->dev[pd_idx].flags); + set_bit(R5_LOCKED, &sh->dev[qd_idx].flags); + break; + case UPDATE_PARITY: + set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags); + set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags); + break; + } +} + + +/* Compute one missing block */ +static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero) +{ + raid6_conf_t *conf = sh->raid_conf; + int i, count, disks = conf->raid_disks; + void *ptr[MAX_XOR_BLOCKS], *p; + int pd_idx = sh->pd_idx; + int qd_idx = raid6_next_disk(pd_idx, disks); + + PRINTK("compute_block_1, stripe %llu, idx %d\n", + (unsigned long long)sh->sector, dd_idx); + + if ( dd_idx == qd_idx ) { + /* We're actually computing the Q drive */ + compute_parity6(sh, UPDATE_PARITY); + } else { + ptr[0] = page_address(sh->dev[dd_idx].page); + if (!nozero) memset(ptr[0], 0, STRIPE_SIZE); + count = 1; + for (i = disks ; i--; ) { + if (i == dd_idx || i == qd_idx) + continue; + p = page_address(sh->dev[i].page); + if (test_bit(R5_UPTODATE, &sh->dev[i].flags)) + ptr[count++] = p; + else + printk("compute_block() %d, stripe %llu, %d" + " not present\n", dd_idx, + (unsigned long long)sh->sector, i); + + check_xor(); + } + if (count != 1) + xor_block(count, STRIPE_SIZE, ptr); + if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); + else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); + } +} + +/* Compute two missing blocks */ +static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2) +{ + raid6_conf_t *conf = sh->raid_conf; + int i, count, disks = conf->raid_disks; + int pd_idx = sh->pd_idx; + int qd_idx = raid6_next_disk(pd_idx, disks); + int d0_idx = raid6_next_disk(qd_idx, disks); + int faila, failb; + + /* faila and failb are disk numbers relative to d0_idx */ + /* pd_idx become disks-2 and qd_idx become disks-1 */ + faila = (dd_idx1 < d0_idx) ? dd_idx1+(disks-d0_idx) : dd_idx1-d0_idx; + failb = (dd_idx2 < d0_idx) ? dd_idx2+(disks-d0_idx) : dd_idx2-d0_idx; + + BUG_ON(faila == failb); + if ( failb < faila ) { int tmp = faila; faila = failb; failb = tmp; } + + PRINTK("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n", + (unsigned long long)sh->sector, dd_idx1, dd_idx2, faila, failb); + + if ( failb == disks-1 ) { + /* Q disk is one of the missing disks */ + if ( faila == disks-2 ) { + /* Missing P+Q, just recompute */ + compute_parity6(sh, UPDATE_PARITY); + return; + } else { + /* We're missing D+Q; recompute D from P */ + compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1, 0); + compute_parity6(sh, UPDATE_PARITY); /* Is this necessary? */ + return; + } + } + + /* We're missing D+P or D+D; build pointer table */ + { + /**** FIX THIS: This could be very bad if disks is close to 256 ****/ + void *ptrs[disks]; + + count = 0; + i = d0_idx; + do { + ptrs[count++] = page_address(sh->dev[i].page); + i = raid6_next_disk(i, disks); + if (i != dd_idx1 && i != dd_idx2 && + !test_bit(R5_UPTODATE, &sh->dev[i].flags)) + printk("compute_2 with missing block %d/%d\n", count, i); + } while ( i != d0_idx ); + + if ( failb == disks-2 ) { + /* We're missing D+P. */ + raid6_datap_recov(disks, STRIPE_SIZE, faila, ptrs); + } else { + /* We're missing D+D. */ + raid6_2data_recov(disks, STRIPE_SIZE, faila, failb, ptrs); + } + + /* Both the above update both missing blocks */ + set_bit(R5_UPTODATE, &sh->dev[dd_idx1].flags); + set_bit(R5_UPTODATE, &sh->dev[dd_idx2].flags); + } +} + + + /* * Each stripe/dev can have one or more bion attached. - * toread/towrite point to the first in a chain. + * toread/towrite point to the first in a chain. * The bi_next chain must be in order. */ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite) @@ -1031,6 +1301,13 @@ static int add_stripe_bio(struct stripe_ static void end_reshape(raid5_conf_t *conf); +static int page_is_zero(struct page *p) +{ + char *a = page_address(p); + return ((*(u32*)a) == 0 && + memcmp(a, a+4, STRIPE_SIZE-4)==0); +} + static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks) { int sectors_per_chunk = conf->chunk_size >> 9; @@ -1062,7 +1339,7 @@ static int stripe_to_pdidx(sector_t stri * */ -static void handle_stripe(struct stripe_head *sh) +static void handle_stripe5(struct stripe_head *sh) { raid5_conf_t *conf = sh->raid_conf; int disks = sh->disks; @@ -1394,7 +1671,7 @@ #endif if (locked == 0 && (rcw == 0 ||rmw == 0) && !test_bit(STRIPE_BIT_DELAY, &sh->state)) { PRINTK("Computing parity...\n"); - compute_parity(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE); + compute_parity5(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE); /* now every locked buffer is ready to be written */ for (i=disks; i--;) if (test_bit(R5_LOCKED, &sh->dev[i].flags)) { @@ -1421,13 +1698,10 @@ #endif !test_bit(STRIPE_INSYNC, &sh->state)) { set_bit(STRIPE_HANDLE, &sh->state); if (failed == 0) { - char *pagea; BUG_ON(uptodate != disks); - compute_parity(sh, CHECK_PARITY); + compute_parity5(sh, CHECK_PARITY); uptodate--; - pagea = page_address(sh->dev[sh->pd_idx].page); - if ((*(u32*)pagea) == 0 && - !memcmp(pagea, pagea+4, STRIPE_SIZE-4)) { + if (page_is_zero(sh->dev[sh->pd_idx].page)) { /* parity is correct (on disc, not in buffer any more) */ set_bit(STRIPE_INSYNC, &sh->state); } else { @@ -1487,7 +1761,7 @@ #endif /* Need to write out all blocks after computing parity */ sh->disks = conf->raid_disks; sh->pd_idx = stripe_to_pdidx(sh->sector, conf, conf->raid_disks); - compute_parity(sh, RECONSTRUCT_WRITE); + compute_parity5(sh, RECONSTRUCT_WRITE); for (i= conf->raid_disks; i--;) { set_bit(R5_LOCKED, &sh->dev[i].flags); locked++; @@ -1615,6 +1889,569 @@ #endif } } +static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) +{ + raid6_conf_t *conf = sh->raid_conf; + int disks = conf->raid_disks; + struct bio *return_bi= NULL; + struct bio *bi; + int i; + int syncing; + int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0; + int non_overwrite = 0; + int failed_num[2] = {0, 0}; + struct r5dev *dev, *pdev, *qdev; + int pd_idx = sh->pd_idx; + int qd_idx = raid6_next_disk(pd_idx, disks); + int p_failed, q_failed; + + PRINTK("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d, qd_idx=%d\n", + (unsigned long long)sh->sector, sh->state, atomic_read(&sh->count), + pd_idx, qd_idx); + + spin_lock(&sh->lock); + clear_bit(STRIPE_HANDLE, &sh->state); + clear_bit(STRIPE_DELAYED, &sh->state); + + syncing = test_bit(STRIPE_SYNCING, &sh->state); + /* Now to look around and see what can be done */ + + rcu_read_lock(); + for (i=disks; i--; ) { + mdk_rdev_t *rdev; + dev = &sh->dev[i]; + clear_bit(R5_Insync, &dev->flags); + + PRINTK("check %d: state 0x%lx read %p write %p written %p\n", + i, dev->flags, dev->toread, dev->towrite, dev->written); + /* maybe we can reply to a read */ + if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) { + struct bio *rbi, *rbi2; + PRINTK("Return read for disc %d\n", i); + spin_lock_irq(&conf->device_lock); + rbi = dev->toread; + dev->toread = NULL; + if (test_and_clear_bit(R5_Overlap, &dev->flags)) + wake_up(&conf->wait_for_overlap); + spin_unlock_irq(&conf->device_lock); + while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) { + copy_data(0, rbi, dev->page, dev->sector); + rbi2 = r5_next_bio(rbi, dev->sector); + spin_lock_irq(&conf->device_lock); + if (--rbi->bi_phys_segments == 0) { + rbi->bi_next = return_bi; + return_bi = rbi; + } + spin_unlock_irq(&conf->device_lock); + rbi = rbi2; + } + } + + /* now count some things */ + if (test_bit(R5_LOCKED, &dev->flags)) locked++; + if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++; + + + if (dev->toread) to_read++; + if (dev->towrite) { + to_write++; + if (!test_bit(R5_OVERWRITE, &dev->flags)) + non_overwrite++; + } + if (dev->written) written++; + rdev = rcu_dereference(conf->disks[i].rdev); + if (!rdev || !test_bit(In_sync, &rdev->flags)) { + /* The ReadError flag will just be confusing now */ + clear_bit(R5_ReadError, &dev->flags); + clear_bit(R5_ReWrite, &dev->flags); + } + if (!rdev || !test_bit(In_sync, &rdev->flags) + || test_bit(R5_ReadError, &dev->flags)) { + if ( failed < 2 ) + failed_num[failed] = i; + failed++; + } else + set_bit(R5_Insync, &dev->flags); + } + rcu_read_unlock(); + PRINTK("locked=%d uptodate=%d to_read=%d" + " to_write=%d failed=%d failed_num=%d,%d\n", + locked, uptodate, to_read, to_write, failed, + failed_num[0], failed_num[1]); + /* check if the array has lost >2 devices and, if so, some requests might + * need to be failed + */ + if (failed > 2 && to_read+to_write+written) { + for (i=disks; i--; ) { + int bitmap_end = 0; + + if (test_bit(R5_ReadError, &sh->dev[i].flags)) { + mdk_rdev_t *rdev; + rcu_read_lock(); + rdev = rcu_dereference(conf->disks[i].rdev); + if (rdev && test_bit(In_sync, &rdev->flags)) + /* multiple read failures in one stripe */ + md_error(conf->mddev, rdev); + rcu_read_unlock(); + } + + spin_lock_irq(&conf->device_lock); + /* fail all writes first */ + bi = sh->dev[i].towrite; + sh->dev[i].towrite = NULL; + if (bi) { to_write--; bitmap_end = 1; } + + if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) + wake_up(&conf->wait_for_overlap); + + while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){ + struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); + clear_bit(BIO_UPTODATE, &bi->bi_flags); + if (--bi->bi_phys_segments == 0) { + md_write_end(conf->mddev); + bi->bi_next = return_bi; + return_bi = bi; + } + bi = nextbi; + } + /* and fail all 'written' */ + bi = sh->dev[i].written; + sh->dev[i].written = NULL; + if (bi) bitmap_end = 1; + while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) { + struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector); + clear_bit(BIO_UPTODATE, &bi->bi_flags); + if (--bi->bi_phys_segments == 0) { + md_write_end(conf->mddev); + bi->bi_next = return_bi; + return_bi = bi; + } + bi = bi2; + } + + /* fail any reads if this device is non-operational */ + if (!test_bit(R5_Insync, &sh->dev[i].flags) || + test_bit(R5_ReadError, &sh->dev[i].flags)) { + bi = sh->dev[i].toread; + sh->dev[i].toread = NULL; + if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) + wake_up(&conf->wait_for_overlap); + if (bi) to_read--; + while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){ + struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); + clear_bit(BIO_UPTODATE, &bi->bi_flags); + if (--bi->bi_phys_segments == 0) { + bi->bi_next = return_bi; + return_bi = bi; + } + bi = nextbi; + } + } + spin_unlock_irq(&conf->device_lock); + if (bitmap_end) + bitmap_endwrite(conf->mddev->bitmap, sh->sector, + STRIPE_SECTORS, 0, 0); + } + } + if (failed > 2 && syncing) { + md_done_sync(conf->mddev, STRIPE_SECTORS,0); + clear_bit(STRIPE_SYNCING, &sh->state); + syncing = 0; + } + + /* + * might be able to return some write requests if the parity blocks + * are safe, or on a failed drive + */ + pdev = &sh->dev[pd_idx]; + p_failed = (failed >= 1 && failed_num[0] == pd_idx) + || (failed >= 2 && failed_num[1] == pd_idx); + qdev = &sh->dev[qd_idx]; + q_failed = (failed >= 1 && failed_num[0] == qd_idx) + || (failed >= 2 && failed_num[1] == qd_idx); + + if ( written && + ( p_failed || ((test_bit(R5_Insync, &pdev->flags) + && !test_bit(R5_LOCKED, &pdev->flags) + && test_bit(R5_UPTODATE, &pdev->flags))) ) && + ( q_failed || ((test_bit(R5_Insync, &qdev->flags) + && !test_bit(R5_LOCKED, &qdev->flags) + && test_bit(R5_UPTODATE, &qdev->flags))) ) ) { + /* any written block on an uptodate or failed drive can be + * returned. Note that if we 'wrote' to a failed drive, + * it will be UPTODATE, but never LOCKED, so we don't need + * to test 'failed' directly. + */ + for (i=disks; i--; ) + if (sh->dev[i].written) { + dev = &sh->dev[i]; + if (!test_bit(R5_LOCKED, &dev->flags) && + test_bit(R5_UPTODATE, &dev->flags) ) { + /* We can return any write requests */ + int bitmap_end = 0; + struct bio *wbi, *wbi2; + PRINTK("Return write for stripe %llu disc %d\n", + (unsigned long long)sh->sector, i); + spin_lock_irq(&conf->device_lock); + wbi = dev->written; + dev->written = NULL; + while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) { + wbi2 = r5_next_bio(wbi, dev->sector); + if (--wbi->bi_phys_segments == 0) { + md_write_end(conf->mddev); + wbi->bi_next = return_bi; + return_bi = wbi; + } + wbi = wbi2; + } + if (dev->towrite == NULL) + bitmap_end = 1; + spin_unlock_irq(&conf->device_lock); + if (bitmap_end) + bitmap_endwrite(conf->mddev->bitmap, sh->sector, + STRIPE_SECTORS, + !test_bit(STRIPE_DEGRADED, &sh->state), 0); + } + } + } + + /* Now we might consider reading some blocks, either to check/generate + * parity, or to satisfy requests + * or to load a block that is being partially written. + */ + if (to_read || non_overwrite || (to_write && failed) || (syncing && (uptodate < disks))) { + for (i=disks; i--;) { + dev = &sh->dev[i]; + if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) && + (dev->toread || + (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) || + syncing || + (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) || + (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write)) + ) + ) { + /* we would like to get this block, possibly + * by computing it, but we might not be able to + */ + if (uptodate == disks-1) { + PRINTK("Computing stripe %llu block %d\n", + (unsigned long long)sh->sector, i); + compute_block_1(sh, i, 0); + uptodate++; + } else if ( uptodate == disks-2 && failed >= 2 ) { + /* Computing 2-failure is *very* expensive; only do it if failed >= 2 */ + int other; + for (other=disks; other--;) { + if ( other == i ) + continue; + if ( !test_bit(R5_UPTODATE, &sh->dev[other].flags) ) + break; + } + BUG_ON(other < 0); + PRINTK("Computing stripe %llu blocks %d,%d\n", + (unsigned long long)sh->sector, i, other); + compute_block_2(sh, i, other); + uptodate += 2; + } else if (test_bit(R5_Insync, &dev->flags)) { + set_bit(R5_LOCKED, &dev->flags); + set_bit(R5_Wantread, &dev->flags); +#if 0 + /* if I am just reading this block and we don't have + a failed drive, or any pending writes then sidestep the cache */ + if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext && + ! syncing && !failed && !to_write) { + sh->bh_cache[i]->b_page = sh->bh_read[i]->b_page; + sh->bh_cache[i]->b_data = sh->bh_read[i]->b_data; + } +#endif + locked++; + PRINTK("Reading block %d (sync=%d)\n", + i, syncing); + } + } + } + set_bit(STRIPE_HANDLE, &sh->state); + } + + /* now to consider writing and what else, if anything should be read */ + if (to_write) { + int rcw=0, must_compute=0; + for (i=disks ; i--;) { + dev = &sh->dev[i]; + /* Would I have to read this buffer for reconstruct_write */ + if (!test_bit(R5_OVERWRITE, &dev->flags) + && i != pd_idx && i != qd_idx + && (!test_bit(R5_LOCKED, &dev->flags) +#if 0 + || sh->bh_page[i] != bh->b_page +#endif + ) && + !test_bit(R5_UPTODATE, &dev->flags)) { + if (test_bit(R5_Insync, &dev->flags)) rcw++; + else { + PRINTK("raid6: must_compute: disk %d flags=%#lx\n", i, dev->flags); + must_compute++; + } + } + } + PRINTK("for sector %llu, rcw=%d, must_compute=%d\n", + (unsigned long long)sh->sector, rcw, must_compute); + set_bit(STRIPE_HANDLE, &sh->state); + + if (rcw > 0) + /* want reconstruct write, but need to get some data */ + for (i=disks; i--;) { + dev = &sh->dev[i]; + if (!test_bit(R5_OVERWRITE, &dev->flags) + && !(failed == 0 && (i == pd_idx || i == qd_idx)) + && !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) && + test_bit(R5_Insync, &dev->flags)) { + if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) + { + PRINTK("Read_old stripe %llu block %d for Reconstruct\n", + (unsigned long long)sh->sector, i); + set_bit(R5_LOCKED, &dev->flags); + set_bit(R5_Wantread, &dev->flags); + locked++; + } else { + PRINTK("Request delayed stripe %llu block %d for Reconstruct\n", + (unsigned long long)sh->sector, i); + set_bit(STRIPE_DELAYED, &sh->state); + set_bit(STRIPE_HANDLE, &sh->state); + } + } + } + /* now if nothing is locked, and if we have enough data, we can start a write request */ + if (locked == 0 && rcw == 0 && + !test_bit(STRIPE_BIT_DELAY, &sh->state)) { + if ( must_compute > 0 ) { + /* We have failed blocks and need to compute them */ + switch ( failed ) { + case 0: BUG(); + case 1: compute_block_1(sh, failed_num[0], 0); break; + case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break; + default: BUG(); /* This request should have been failed? */ + } + } + + PRINTK("Computing parity for stripe %llu\n", (unsigned long long)sh->sector); + compute_parity6(sh, RECONSTRUCT_WRITE); + /* now every locked buffer is ready to be written */ + for (i=disks; i--;) + if (test_bit(R5_LOCKED, &sh->dev[i].flags)) { + PRINTK("Writing stripe %llu block %d\n", + (unsigned long long)sh->sector, i); + locked++; + set_bit(R5_Wantwrite, &sh->dev[i].flags); + } + /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */ + set_bit(STRIPE_INSYNC, &sh->state); + + if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) { + atomic_dec(&conf->preread_active_stripes); + if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) + md_wakeup_thread(conf->mddev->thread); + } + } + } + + /* maybe we need to check and possibly fix the parity for this stripe + * Any reads will already have been scheduled, so we just see if enough data + * is available + */ + if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) { + int update_p = 0, update_q = 0; + struct r5dev *dev; + + set_bit(STRIPE_HANDLE, &sh->state); + + BUG_ON(failed>2); + BUG_ON(uptodate < disks); + /* Want to check and possibly repair P and Q. + * However there could be one 'failed' device, in which + * case we can only check one of them, possibly using the + * other to generate missing data + */ + + /* If !tmp_page, we cannot do the calculations, + * but as we have set STRIPE_HANDLE, we will soon be called + * by stripe_handle with a tmp_page - just wait until then. + */ + if (tmp_page) { + if (failed == q_failed) { + /* The only possible failed device holds 'Q', so it makes + * sense to check P (If anything else were failed, we would + * have used P to recreate it). + */ + compute_block_1(sh, pd_idx, 1); + if (!page_is_zero(sh->dev[pd_idx].page)) { + compute_block_1(sh,pd_idx,0); + update_p = 1; + } + } + if (!q_failed && failed < 2) { + /* q is not failed, and we didn't use it to generate + * anything, so it makes sense to check it + */ + memcpy(page_address(tmp_page), + page_address(sh->dev[qd_idx].page), + STRIPE_SIZE); + compute_parity6(sh, UPDATE_PARITY); + if (memcmp(page_address(tmp_page), + page_address(sh->dev[qd_idx].page), + STRIPE_SIZE)!= 0) { + clear_bit(STRIPE_INSYNC, &sh->state); + update_q = 1; + } + } + if (update_p || update_q) { + conf->mddev->resync_mismatches += STRIPE_SECTORS; + if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) + /* don't try to repair!! */ + update_p = update_q = 0; + } + + /* now write out any block on a failed drive, + * or P or Q if they need it + */ + + if (failed == 2) { + dev = &sh->dev[failed_num[1]]; + locked++; + set_bit(R5_LOCKED, &dev->flags); + set_bit(R5_Wantwrite, &dev->flags); + } + if (failed >= 1) { + dev = &sh->dev[failed_num[0]]; + locked++; + set_bit(R5_LOCKED, &dev->flags); + set_bit(R5_Wantwrite, &dev->flags); + } + + if (update_p) { + dev = &sh->dev[pd_idx]; + locked ++; + set_bit(R5_LOCKED, &dev->flags); + set_bit(R5_Wantwrite, &dev->flags); + } + if (update_q) { + dev = &sh->dev[qd_idx]; + locked++; + set_bit(R5_LOCKED, &dev->flags); + set_bit(R5_Wantwrite, &dev->flags); + } + clear_bit(STRIPE_DEGRADED, &sh->state); + + set_bit(STRIPE_INSYNC, &sh->state); + } + } + + if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) { + md_done_sync(conf->mddev, STRIPE_SECTORS,1); + clear_bit(STRIPE_SYNCING, &sh->state); + } + + /* If the failed drives are just a ReadError, then we might need + * to progress the repair/check process + */ + if (failed <= 2 && ! conf->mddev->ro) + for (i=0; idev[failed_num[i]]; + if (test_bit(R5_ReadError, &dev->flags) + && !test_bit(R5_LOCKED, &dev->flags) + && test_bit(R5_UPTODATE, &dev->flags) + ) { + if (!test_bit(R5_ReWrite, &dev->flags)) { + set_bit(R5_Wantwrite, &dev->flags); + set_bit(R5_ReWrite, &dev->flags); + set_bit(R5_LOCKED, &dev->flags); + } else { + /* let's read it back */ + set_bit(R5_Wantread, &dev->flags); + set_bit(R5_LOCKED, &dev->flags); + } + } + } + spin_unlock(&sh->lock); + + while ((bi=return_bi)) { + int bytes = bi->bi_size; + + return_bi = bi->bi_next; + bi->bi_next = NULL; + bi->bi_size = 0; + bi->bi_end_io(bi, bytes, 0); + } + for (i=disks; i-- ;) { + int rw; + struct bio *bi; + mdk_rdev_t *rdev; + if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) + rw = 1; + else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags)) + rw = 0; + else + continue; + + bi = &sh->dev[i].req; + + bi->bi_rw = rw; + if (rw) + bi->bi_end_io = raid5_end_write_request; + else + bi->bi_end_io = raid5_end_read_request; + + rcu_read_lock(); + rdev = rcu_dereference(conf->disks[i].rdev); + if (rdev && test_bit(Faulty, &rdev->flags)) + rdev = NULL; + if (rdev) + atomic_inc(&rdev->nr_pending); + rcu_read_unlock(); + + if (rdev) { + if (syncing) + md_sync_acct(rdev->bdev, STRIPE_SECTORS); + + bi->bi_bdev = rdev->bdev; + PRINTK("for %llu schedule op %ld on disc %d\n", + (unsigned long long)sh->sector, bi->bi_rw, i); + atomic_inc(&sh->count); + bi->bi_sector = sh->sector + rdev->data_offset; + bi->bi_flags = 1 << BIO_UPTODATE; + bi->bi_vcnt = 1; + bi->bi_max_vecs = 1; + bi->bi_idx = 0; + bi->bi_io_vec = &sh->dev[i].vec; + bi->bi_io_vec[0].bv_len = STRIPE_SIZE; + bi->bi_io_vec[0].bv_offset = 0; + bi->bi_size = STRIPE_SIZE; + bi->bi_next = NULL; + if (rw == WRITE && + test_bit(R5_ReWrite, &sh->dev[i].flags)) + atomic_add(STRIPE_SECTORS, &rdev->corrected_errors); + generic_make_request(bi); + } else { + if (rw == 1) + set_bit(STRIPE_DEGRADED, &sh->state); + PRINTK("skip op %ld on disc %d for sector %llu\n", + bi->bi_rw, i, (unsigned long long)sh->sector); + clear_bit(R5_LOCKED, &sh->dev[i].flags); + set_bit(STRIPE_HANDLE, &sh->state); + } + } +} + +static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) +{ + if (sh->raid_conf->level == 6) + handle_stripe6(sh, tmp_page); + else + handle_stripe5(sh); +} + + + static void raid5_activate_delayed(raid5_conf_t *conf) { if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { @@ -1753,7 +2590,7 @@ static int make_request(request_queue_t for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { DEFINE_WAIT(w); - int disks; + int disks, data_disks; retry: prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); @@ -1781,7 +2618,9 @@ static int make_request(request_queue_t } spin_unlock_irq(&conf->device_lock); } - new_sector = raid5_compute_sector(logical_sector, disks, disks - 1, + data_disks = disks - conf->max_degraded; + + new_sector = raid5_compute_sector(logical_sector, disks, data_disks, &dd_idx, &pd_idx, conf); PRINTK("raid5: make_request, sector %llu logical %llu\n", (unsigned long long)new_sector, @@ -1833,7 +2672,7 @@ static int make_request(request_queue_t } finish_wait(&conf->wait_for_overlap, &w); raid5_plug_device(conf); - handle_stripe(sh); + handle_stripe(sh, NULL); release_stripe(sh); } else { /* cannot get stripe for read-ahead, just give-up */ @@ -1849,7 +2688,7 @@ static int make_request(request_queue_t if (remaining == 0) { int bytes = bi->bi_size; - if ( bio_data_dir(bi) == WRITE ) + if ( rw == WRITE ) md_write_end(mddev); bi->bi_size = 0; bi->bi_end_io(bi, bytes, 0); @@ -1857,17 +2696,142 @@ static int make_request(request_queue_t return 0; } -/* FIXME go_faster isn't used */ -static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster) +static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped) { + /* reshaping is quite different to recovery/resync so it is + * handled quite separately ... here. + * + * On each call to sync_request, we gather one chunk worth of + * destination stripes and flag them as expanding. + * Then we find all the source stripes and request reads. + * As the reads complete, handle_stripe will copy the data + * into the destination stripe and release that stripe. + */ raid5_conf_t *conf = (raid5_conf_t *) mddev->private; struct stripe_head *sh; int pd_idx; sector_t first_sector, last_sector; + int raid_disks; + int data_disks; + int i; + int dd_idx; + sector_t writepos, safepos, gap; + + if (sector_nr == 0 && + conf->expand_progress != 0) { + /* restarting in the middle, skip the initial sectors */ + sector_nr = conf->expand_progress; + sector_div(sector_nr, conf->raid_disks-1); + *skipped = 1; + return sector_nr; + } + + /* we update the metadata when there is more than 3Meg + * in the block range (that is rather arbitrary, should + * probably be time based) or when the data about to be + * copied would over-write the source of the data at + * the front of the range. + * i.e. one new_stripe forward from expand_progress new_maps + * to after where expand_lo old_maps to + */ + writepos = conf->expand_progress + + conf->chunk_size/512*(conf->raid_disks-1); + sector_div(writepos, conf->raid_disks-1); + safepos = conf->expand_lo; + sector_div(safepos, conf->previous_raid_disks-1); + gap = conf->expand_progress - conf->expand_lo; + + if (writepos >= safepos || + gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) { + /* Cannot proceed until we've updated the superblock... */ + wait_event(conf->wait_for_overlap, + atomic_read(&conf->reshape_stripes)==0); + mddev->reshape_position = conf->expand_progress; + mddev->sb_dirty = 1; + md_wakeup_thread(mddev->thread); + wait_event(mddev->sb_wait, mddev->sb_dirty == 0 || + kthread_should_stop()); + spin_lock_irq(&conf->device_lock); + conf->expand_lo = mddev->reshape_position; + spin_unlock_irq(&conf->device_lock); + wake_up(&conf->wait_for_overlap); + } + + for (i=0; i < conf->chunk_size/512; i+= STRIPE_SECTORS) { + int j; + int skipped = 0; + pd_idx = stripe_to_pdidx(sector_nr+i, conf, conf->raid_disks); + sh = get_active_stripe(conf, sector_nr+i, + conf->raid_disks, pd_idx, 0); + set_bit(STRIPE_EXPANDING, &sh->state); + atomic_inc(&conf->reshape_stripes); + /* If any of this stripe is beyond the end of the old + * array, then we need to zero those blocks + */ + for (j=sh->disks; j--;) { + sector_t s; + if (j == sh->pd_idx) + continue; + s = compute_blocknr(sh, j); + if (s < (mddev->array_size<<1)) { + skipped = 1; + continue; + } + memset(page_address(sh->dev[j].page), 0, STRIPE_SIZE); + set_bit(R5_Expanded, &sh->dev[j].flags); + set_bit(R5_UPTODATE, &sh->dev[j].flags); + } + if (!skipped) { + set_bit(STRIPE_EXPAND_READY, &sh->state); + set_bit(STRIPE_HANDLE, &sh->state); + } + release_stripe(sh); + } + spin_lock_irq(&conf->device_lock); + conf->expand_progress = (sector_nr + i)*(conf->raid_disks-1); + spin_unlock_irq(&conf->device_lock); + /* Ok, those stripe are ready. We can start scheduling + * reads on the source stripes. + * The source stripes are determined by mapping the first and last + * block on the destination stripes. + */ + raid_disks = conf->previous_raid_disks; + data_disks = raid_disks - 1; + first_sector = + raid5_compute_sector(sector_nr*(conf->raid_disks-1), + raid_disks, data_disks, + &dd_idx, &pd_idx, conf); + last_sector = + raid5_compute_sector((sector_nr+conf->chunk_size/512) + *(conf->raid_disks-1) -1, + raid_disks, data_disks, + &dd_idx, &pd_idx, conf); + if (last_sector >= (mddev->size<<1)) + last_sector = (mddev->size<<1)-1; + while (first_sector <= last_sector) { + pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks); + sh = get_active_stripe(conf, first_sector, + conf->previous_raid_disks, pd_idx, 0); + set_bit(STRIPE_EXPAND_SOURCE, &sh->state); + set_bit(STRIPE_HANDLE, &sh->state); + release_stripe(sh); + first_sector += STRIPE_SECTORS; + } + return conf->chunk_size>>9; +} + +/* FIXME go_faster isn't used */ +static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster) +{ + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + struct stripe_head *sh; + int pd_idx; int raid_disks = conf->raid_disks; - int data_disks = raid_disks-1; + int data_disks = raid_disks - conf->max_degraded; sector_t max_sector = mddev->size << 1; int sync_blocks; + int still_degraded = 0; + int i; if (sector_nr >= max_sector) { /* just being told to finish up .. nothing much to do */ @@ -1880,134 +2844,22 @@ static sector_t sync_request(mddev_t *md if (mddev->curr_resync < max_sector) /* aborted */ bitmap_end_sync(mddev->bitmap, mddev->curr_resync, &sync_blocks, 1); - else /* compelted sync */ + else /* completed sync */ conf->fullsync = 0; bitmap_close_sync(mddev->bitmap); return 0; } - if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) { - /* reshaping is quite different to recovery/resync so it is - * handled quite separately ... here. - * - * On each call to sync_request, we gather one chunk worth of - * destination stripes and flag them as expanding. - * Then we find all the source stripes and request reads. - * As the reads complete, handle_stripe will copy the data - * into the destination stripe and release that stripe. - */ - int i; - int dd_idx; - sector_t writepos, safepos, gap; - - if (sector_nr == 0 && - conf->expand_progress != 0) { - /* restarting in the middle, skip the initial sectors */ - sector_nr = conf->expand_progress; - sector_div(sector_nr, conf->raid_disks-1); - *skipped = 1; - return sector_nr; - } - - /* we update the metadata when there is more than 3Meg - * in the block range (that is rather arbitrary, should - * probably be time based) or when the data about to be - * copied would over-write the source of the data at - * the front of the range. - * i.e. one new_stripe forward from expand_progress new_maps - * to after where expand_lo old_maps to - */ - writepos = conf->expand_progress + - conf->chunk_size/512*(conf->raid_disks-1); - sector_div(writepos, conf->raid_disks-1); - safepos = conf->expand_lo; - sector_div(safepos, conf->previous_raid_disks-1); - gap = conf->expand_progress - conf->expand_lo; - - if (writepos >= safepos || - gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) { - /* Cannot proceed until we've updated the superblock... */ - wait_event(conf->wait_for_overlap, - atomic_read(&conf->reshape_stripes)==0); - mddev->reshape_position = conf->expand_progress; - mddev->sb_dirty = 1; - md_wakeup_thread(mddev->thread); - wait_event(mddev->sb_wait, mddev->sb_dirty == 0 || - kthread_should_stop()); - spin_lock_irq(&conf->device_lock); - conf->expand_lo = mddev->reshape_position; - spin_unlock_irq(&conf->device_lock); - wake_up(&conf->wait_for_overlap); - } - - for (i=0; i < conf->chunk_size/512; i+= STRIPE_SECTORS) { - int j; - int skipped = 0; - pd_idx = stripe_to_pdidx(sector_nr+i, conf, conf->raid_disks); - sh = get_active_stripe(conf, sector_nr+i, - conf->raid_disks, pd_idx, 0); - set_bit(STRIPE_EXPANDING, &sh->state); - atomic_inc(&conf->reshape_stripes); - /* If any of this stripe is beyond the end of the old - * array, then we need to zero those blocks - */ - for (j=sh->disks; j--;) { - sector_t s; - if (j == sh->pd_idx) - continue; - s = compute_blocknr(sh, j); - if (s < (mddev->array_size<<1)) { - skipped = 1; - continue; - } - memset(page_address(sh->dev[j].page), 0, STRIPE_SIZE); - set_bit(R5_Expanded, &sh->dev[j].flags); - set_bit(R5_UPTODATE, &sh->dev[j].flags); - } - if (!skipped) { - set_bit(STRIPE_EXPAND_READY, &sh->state); - set_bit(STRIPE_HANDLE, &sh->state); - } - release_stripe(sh); - } - spin_lock_irq(&conf->device_lock); - conf->expand_progress = (sector_nr + i)*(conf->raid_disks-1); - spin_unlock_irq(&conf->device_lock); - /* Ok, those stripe are ready. We can start scheduling - * reads on the source stripes. - * The source stripes are determined by mapping the first and last - * block on the destination stripes. - */ - raid_disks = conf->previous_raid_disks; - data_disks = raid_disks - 1; - first_sector = - raid5_compute_sector(sector_nr*(conf->raid_disks-1), - raid_disks, data_disks, - &dd_idx, &pd_idx, conf); - last_sector = - raid5_compute_sector((sector_nr+conf->chunk_size/512) - *(conf->raid_disks-1) -1, - raid_disks, data_disks, - &dd_idx, &pd_idx, conf); - if (last_sector >= (mddev->size<<1)) - last_sector = (mddev->size<<1)-1; - while (first_sector <= last_sector) { - pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks); - sh = get_active_stripe(conf, first_sector, - conf->previous_raid_disks, pd_idx, 0); - set_bit(STRIPE_EXPAND_SOURCE, &sh->state); - set_bit(STRIPE_HANDLE, &sh->state); - release_stripe(sh); - first_sector += STRIPE_SECTORS; - } - return conf->chunk_size>>9; - } - /* if there is 1 or more failed drives and we are trying + if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) + return reshape_request(mddev, sector_nr, skipped); + + /* if there is too many failed drives and we are trying * to resync, then assert that we are finished, because there is * nothing we can do. */ - if (mddev->degraded >= 1 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { + if (mddev->degraded >= conf->max_degraded && + test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { sector_t rv = (mddev->size << 1) - sector_nr; *skipped = 1; return rv; @@ -2026,17 +2878,26 @@ static sector_t sync_request(mddev_t *md if (sh == NULL) { sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 0); /* make sure we don't swamp the stripe cache if someone else - * is trying to get access + * is trying to get access */ schedule_timeout_uninterruptible(1); } - bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0); - spin_lock(&sh->lock); + /* Need to check if array will still be degraded after recovery/resync + * We don't need to check the 'failed' flag as when that gets set, + * recovery aborts. + */ + for (i=0; iraid_disks; i++) + if (conf->disks[i].rdev == NULL) + still_degraded = 1; + + bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded); + + spin_lock(&sh->lock); set_bit(STRIPE_SYNCING, &sh->state); clear_bit(STRIPE_INSYNC, &sh->state); spin_unlock(&sh->lock); - handle_stripe(sh); + handle_stripe(sh, NULL); release_stripe(sh); return STRIPE_SECTORS; @@ -2091,7 +2952,7 @@ static void raid5d (mddev_t *mddev) spin_unlock_irq(&conf->device_lock); handled++; - handle_stripe(sh); + handle_stripe(sh, conf->spare_page); release_stripe(sh); spin_lock_irq(&conf->device_lock); @@ -2181,8 +3042,8 @@ static int run(mddev_t *mddev) struct disk_info *disk; struct list_head *tmp; - if (mddev->level != 5 && mddev->level != 4) { - printk(KERN_ERR "raid5: %s: raid level not set to 4/5 (%d)\n", + if (mddev->level != 5 && mddev->level != 4 && mddev->level != 6) { + printk(KERN_ERR "raid5: %s: raid level not set to 4/5/6 (%d)\n", mdname(mddev), mddev->level); return -EIO; } @@ -2251,6 +3112,11 @@ static int run(mddev_t *mddev) if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL) goto abort; + if (mddev->level == 6) { + conf->spare_page = alloc_page(GFP_KERNEL); + if (!conf->spare_page) + goto abort; + } spin_lock_init(&conf->device_lock); init_waitqueue_head(&conf->wait_for_stripe); init_waitqueue_head(&conf->wait_for_overlap); @@ -2282,12 +3148,16 @@ static int run(mddev_t *mddev) } /* - * 0 for a fully functional array, 1 for a degraded array. + * 0 for a fully functional array, 1 or 2 for a degraded array. */ mddev->degraded = conf->failed_disks = conf->raid_disks - conf->working_disks; conf->mddev = mddev; conf->chunk_size = mddev->chunk_size; conf->level = mddev->level; + if (conf->level == 6) + conf->max_degraded = 2; + else + conf->max_degraded = 1; conf->algorithm = mddev->layout; conf->max_nr_stripes = NR_STRIPES; conf->expand_progress = mddev->reshape_position; @@ -2296,6 +3166,11 @@ static int run(mddev_t *mddev) mddev->size &= ~(mddev->chunk_size/1024 -1); mddev->resync_max_sectors = mddev->size << 1; + if (conf->level == 6 && conf->raid_disks < 4) { + printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n", + mdname(mddev), conf->raid_disks); + goto abort; + } if (!conf->chunk_size || conf->chunk_size % 4) { printk(KERN_ERR "raid5: invalid chunk size %d for %s\n", conf->chunk_size, mdname(mddev)); @@ -2307,14 +3182,14 @@ static int run(mddev_t *mddev) conf->algorithm, mdname(mddev)); goto abort; } - if (mddev->degraded > 1) { + if (mddev->degraded > conf->max_degraded) { printk(KERN_ERR "raid5: not enough operational devices for %s" " (%d/%d failed)\n", mdname(mddev), conf->failed_disks, conf->raid_disks); goto abort; } - if (mddev->degraded == 1 && + if (mddev->degraded > 0 && mddev->recovery_cp != MaxSector) { if (mddev->ok_start_degraded) printk(KERN_WARNING @@ -2379,11 +3254,12 @@ static int run(mddev_t *mddev) } /* read-ahead size must cover two whole stripes, which is - * 2 * (n-1) * chunksize where 'n' is the number of raid devices + * 2 * (datadisks) * chunksize where 'n' is the number of raid devices */ { - int stripe = (mddev->raid_disks-1) * mddev->chunk_size - / PAGE_SIZE; + int data_disks = conf->previous_raid_disks - conf->max_degraded; + int stripe = data_disks * + (mddev->chunk_size / PAGE_SIZE); if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe) mddev->queue->backing_dev_info.ra_pages = 2 * stripe; } @@ -2393,12 +3269,14 @@ static int run(mddev_t *mddev) mddev->queue->unplug_fn = raid5_unplug_device; mddev->queue->issue_flush_fn = raid5_issue_flush; - mddev->array_size = mddev->size * (conf->previous_raid_disks - 1); + mddev->array_size = mddev->size * (conf->previous_raid_disks - + conf->max_degraded); return 0; abort: if (conf) { print_raid5_conf(conf); + safe_put_page(conf->spare_page); kfree(conf->disks); kfree(conf->stripe_hashtbl); kfree(conf); @@ -2427,23 +3305,23 @@ static int stop(mddev_t *mddev) } #if RAID5_DEBUG -static void print_sh (struct stripe_head *sh) +static void print_sh (struct seq_file *seq, struct stripe_head *sh) { int i; - printk("sh %llu, pd_idx %d, state %ld.\n", - (unsigned long long)sh->sector, sh->pd_idx, sh->state); - printk("sh %llu, count %d.\n", - (unsigned long long)sh->sector, atomic_read(&sh->count)); - printk("sh %llu, ", (unsigned long long)sh->sector); + seq_printf(seq, "sh %llu, pd_idx %d, state %ld.\n", + (unsigned long long)sh->sector, sh->pd_idx, sh->state); + seq_printf(seq, "sh %llu, count %d.\n", + (unsigned long long)sh->sector, atomic_read(&sh->count)); + seq_printf(seq, "sh %llu, ", (unsigned long long)sh->sector); for (i = 0; i < sh->disks; i++) { - printk("(cache%d: %p %ld) ", - i, sh->dev[i].page, sh->dev[i].flags); + seq_printf(seq, "(cache%d: %p %ld) ", + i, sh->dev[i].page, sh->dev[i].flags); } - printk("\n"); + seq_printf(seq, "\n"); } -static void printall (raid5_conf_t *conf) +static void printall (struct seq_file *seq, raid5_conf_t *conf) { struct stripe_head *sh; struct hlist_node *hn; @@ -2454,7 +3332,7 @@ static void printall (raid5_conf_t *conf hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) { if (sh->raid_conf != conf) continue; - print_sh(sh); + print_sh(seq, sh); } } spin_unlock_irq(&conf->device_lock); @@ -2474,9 +3352,8 @@ static void status (struct seq_file *seq test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_"); seq_printf (seq, "]"); #if RAID5_DEBUG -#define D(x) \ - seq_printf (seq, "<"#x":%d>", atomic_read(&conf->x)) - printall(conf); + seq_printf (seq, "\n"); + printall(seq, conf); #endif } @@ -2560,14 +3437,20 @@ static int raid5_add_disk(mddev_t *mddev int disk; struct disk_info *p; - if (mddev->degraded > 1) + if (mddev->degraded > conf->max_degraded) /* no point adding a device */ return 0; /* - * find the disk ... + * find the disk ... but prefer rdev->saved_raid_disk + * if possible. */ - for (disk=0; disk < conf->raid_disks; disk++) + if (rdev->saved_raid_disk >= 0 && + conf->disks[rdev->saved_raid_disk].rdev == NULL) + disk = rdev->saved_raid_disk; + else + disk = 0; + for ( ; disk < conf->raid_disks; disk++) if ((p=conf->disks + disk)->rdev == NULL) { clear_bit(In_sync, &rdev->flags); rdev->raid_disk = disk; @@ -2590,8 +3473,10 @@ static int raid5_resize(mddev_t *mddev, * any io in the removed space completes, but it hardly seems * worth it. */ + raid5_conf_t *conf = mddev_to_conf(mddev); + sectors &= ~((sector_t)mddev->chunk_size/512 - 1); - mddev->array_size = (sectors * (mddev->raid_disks-1))>>1; + mddev->array_size = (sectors * (mddev->raid_disks-conf->max_degraded))>>1; set_capacity(mddev->gendisk, mddev->array_size << 1); mddev->changed = 1; if (sectors/2 > mddev->size && mddev->recovery_cp == MaxSector) { @@ -2680,6 +3565,7 @@ static int raid5_start_reshape(mddev_t * set_bit(In_sync, &rdev->flags); conf->working_disks++; added_devices++; + rdev->recovery_offset = 0; sprintf(nm, "rd%d", rdev->raid_disk); sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); } else @@ -2731,6 +3617,17 @@ static void end_reshape(raid5_conf_t *co conf->expand_progress = MaxSector; spin_unlock_irq(&conf->device_lock); conf->mddev->reshape_position = MaxSector; + + /* read-ahead size must cover two whole stripes, which is + * 2 * (datadisks) * chunksize where 'n' is the number of raid devices + */ + { + int data_disks = conf->previous_raid_disks - conf->max_degraded; + int stripe = data_disks * + (conf->mddev->chunk_size / PAGE_SIZE); + if (conf->mddev->queue->backing_dev_info.ra_pages < 2 * stripe) + conf->mddev->queue->backing_dev_info.ra_pages = 2 * stripe; + } } } @@ -2762,6 +3659,23 @@ static void raid5_quiesce(mddev_t *mddev } } +static struct mdk_personality raid6_personality = +{ + .name = "raid6", + .level = 6, + .owner = THIS_MODULE, + .make_request = make_request, + .run = run, + .stop = stop, + .status = status, + .error_handler = error, + .hot_add_disk = raid5_add_disk, + .hot_remove_disk= raid5_remove_disk, + .spare_active = raid5_spare_active, + .sync_request = sync_request, + .resize = raid5_resize, + .quiesce = raid5_quiesce, +}; static struct mdk_personality raid5_personality = { .name = "raid5", @@ -2804,6 +3718,12 @@ static struct mdk_personality raid4_pers static int __init raid5_init(void) { + int e; + + e = raid6_select_algo(); + if ( e ) + return e; + register_md_personality(&raid6_personality); register_md_personality(&raid5_personality); register_md_personality(&raid4_personality); return 0; @@ -2811,6 +3731,7 @@ static int __init raid5_init(void) static void raid5_exit(void) { + unregister_md_personality(&raid6_personality); unregister_md_personality(&raid5_personality); unregister_md_personality(&raid4_personality); } @@ -2823,3 +3744,10 @@ MODULE_ALIAS("md-raid5"); MODULE_ALIAS("md-raid4"); MODULE_ALIAS("md-level-5"); MODULE_ALIAS("md-level-4"); +MODULE_ALIAS("md-personality-8"); /* RAID6 */ +MODULE_ALIAS("md-raid6"); +MODULE_ALIAS("md-level-6"); + +/* This used to be two separate modules, they were: */ +MODULE_ALIAS("raid5"); +MODULE_ALIAS("raid6"); diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c index 51c63c0..9265761 100644 --- a/drivers/md/raid6algos.c +++ b/drivers/md/raid6algos.c @@ -139,15 +139,14 @@ int __init raid6_select_algo(void) } } - if ( best ) + if (best) { printk("raid6: using algorithm %s (%ld MB/s)\n", best->name, (bestperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2)); - else + raid6_call = *best; + } else printk("raid6: Yikes! No algorithm found!\n"); - raid6_call = *best; - free_pages((unsigned long)syndromes, 1); return best ? 0 : -EINVAL; diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c deleted file mode 100644 index bc69355..0000000 --- a/drivers/md/raid6main.c +++ /dev/null @@ -1,2427 +0,0 @@ -/* - * raid6main.c : Multiple Devices driver for Linux - * Copyright (C) 1996, 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman - * Copyright (C) 1999, 2000 Ingo Molnar - * Copyright (C) 2002, 2003 H. Peter Anvin - * - * RAID-6 management functions. This code is derived from raid5.c. - * Last merge from raid5.c bkcvs version 1.79 (kernel 2.6.1). - * - * Thanks to Penguin Computing for making the RAID-6 development possible - * by donating a test server! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example /usr/src/linux/COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include -#include -#include -#include -#include -#include -#include "raid6.h" - -#include - -/* - * Stripe cache - */ - -#define NR_STRIPES 256 -#define STRIPE_SIZE PAGE_SIZE -#define STRIPE_SHIFT (PAGE_SHIFT - 9) -#define STRIPE_SECTORS (STRIPE_SIZE>>9) -#define IO_THRESHOLD 1 -#define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head)) -#define HASH_MASK (NR_HASH - 1) - -#define stripe_hash(conf, sect) (&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])) - -/* bio's attached to a stripe+device for I/O are linked together in bi_sector - * order without overlap. There may be several bio's per stripe+device, and - * a bio could span several devices. - * When walking this list for a particular stripe+device, we must never proceed - * beyond a bio that extends past this device, as the next bio might no longer - * be valid. - * This macro is used to determine the 'next' bio in the list, given the sector - * of the current stripe+device - */ -#define r5_next_bio(bio, sect) ( ( (bio)->bi_sector + ((bio)->bi_size>>9) < sect + STRIPE_SECTORS) ? (bio)->bi_next : NULL) -/* - * The following can be used to debug the driver - */ -#define RAID6_DEBUG 0 /* Extremely verbose printk */ -#define RAID6_PARANOIA 1 /* Check spinlocks */ -#define RAID6_DUMPSTATE 0 /* Include stripe cache state in /proc/mdstat */ -#if RAID6_PARANOIA && defined(CONFIG_SMP) -# define CHECK_DEVLOCK() assert_spin_locked(&conf->device_lock) -#else -# define CHECK_DEVLOCK() -#endif - -#define PRINTK(x...) ((void)(RAID6_DEBUG && printk(KERN_DEBUG x))) -#if RAID6_DEBUG -#undef inline -#undef __inline__ -#define inline -#define __inline__ -#endif - -#if !RAID6_USE_EMPTY_ZERO_PAGE -/* In .bss so it's zeroed */ -const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256))); -#endif - -static inline int raid6_next_disk(int disk, int raid_disks) -{ - disk++; - return (disk < raid_disks) ? disk : 0; -} - -static void print_raid6_conf (raid6_conf_t *conf); - -static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh) -{ - if (atomic_dec_and_test(&sh->count)) { - BUG_ON(!list_empty(&sh->lru)); - BUG_ON(atomic_read(&conf->active_stripes)==0); - if (test_bit(STRIPE_HANDLE, &sh->state)) { - if (test_bit(STRIPE_DELAYED, &sh->state)) - list_add_tail(&sh->lru, &conf->delayed_list); - else if (test_bit(STRIPE_BIT_DELAY, &sh->state) && - conf->seq_write == sh->bm_seq) - list_add_tail(&sh->lru, &conf->bitmap_list); - else { - clear_bit(STRIPE_BIT_DELAY, &sh->state); - list_add_tail(&sh->lru, &conf->handle_list); - } - md_wakeup_thread(conf->mddev->thread); - } else { - if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) { - atomic_dec(&conf->preread_active_stripes); - if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) - md_wakeup_thread(conf->mddev->thread); - } - list_add_tail(&sh->lru, &conf->inactive_list); - atomic_dec(&conf->active_stripes); - if (!conf->inactive_blocked || - atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4)) - wake_up(&conf->wait_for_stripe); - } - } -} -static void release_stripe(struct stripe_head *sh) -{ - raid6_conf_t *conf = sh->raid_conf; - unsigned long flags; - - spin_lock_irqsave(&conf->device_lock, flags); - __release_stripe(conf, sh); - spin_unlock_irqrestore(&conf->device_lock, flags); -} - -static inline void remove_hash(struct stripe_head *sh) -{ - PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector); - - hlist_del_init(&sh->hash); -} - -static inline void insert_hash(raid6_conf_t *conf, struct stripe_head *sh) -{ - struct hlist_head *hp = stripe_hash(conf, sh->sector); - - PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector); - - CHECK_DEVLOCK(); - hlist_add_head(&sh->hash, hp); -} - - -/* find an idle stripe, make sure it is unhashed, and return it. */ -static struct stripe_head *get_free_stripe(raid6_conf_t *conf) -{ - struct stripe_head *sh = NULL; - struct list_head *first; - - CHECK_DEVLOCK(); - if (list_empty(&conf->inactive_list)) - goto out; - first = conf->inactive_list.next; - sh = list_entry(first, struct stripe_head, lru); - list_del_init(first); - remove_hash(sh); - atomic_inc(&conf->active_stripes); -out: - return sh; -} - -static void shrink_buffers(struct stripe_head *sh, int num) -{ - struct page *p; - int i; - - for (i=0; idev[i].page; - if (!p) - continue; - sh->dev[i].page = NULL; - put_page(p); - } -} - -static int grow_buffers(struct stripe_head *sh, int num) -{ - int i; - - for (i=0; idev[i].page = page; - } - return 0; -} - -static void raid6_build_block (struct stripe_head *sh, int i); - -static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) -{ - raid6_conf_t *conf = sh->raid_conf; - int disks = conf->raid_disks, i; - - BUG_ON(atomic_read(&sh->count) != 0); - BUG_ON(test_bit(STRIPE_HANDLE, &sh->state)); - - CHECK_DEVLOCK(); - PRINTK("init_stripe called, stripe %llu\n", - (unsigned long long)sh->sector); - - remove_hash(sh); - - sh->sector = sector; - sh->pd_idx = pd_idx; - sh->state = 0; - - for (i=disks; i--; ) { - struct r5dev *dev = &sh->dev[i]; - - if (dev->toread || dev->towrite || dev->written || - test_bit(R5_LOCKED, &dev->flags)) { - PRINTK("sector=%llx i=%d %p %p %p %d\n", - (unsigned long long)sh->sector, i, dev->toread, - dev->towrite, dev->written, - test_bit(R5_LOCKED, &dev->flags)); - BUG(); - } - dev->flags = 0; - raid6_build_block(sh, i); - } - insert_hash(conf, sh); -} - -static struct stripe_head *__find_stripe(raid6_conf_t *conf, sector_t sector) -{ - struct stripe_head *sh; - struct hlist_node *hn; - - CHECK_DEVLOCK(); - PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); - hlist_for_each_entry (sh, hn, stripe_hash(conf, sector), hash) - if (sh->sector == sector) - return sh; - PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); - return NULL; -} - -static void unplug_slaves(mddev_t *mddev); - -static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector, - int pd_idx, int noblock) -{ - struct stripe_head *sh; - - PRINTK("get_stripe, sector %llu\n", (unsigned long long)sector); - - spin_lock_irq(&conf->device_lock); - - do { - wait_event_lock_irq(conf->wait_for_stripe, - conf->quiesce == 0, - conf->device_lock, /* nothing */); - sh = __find_stripe(conf, sector); - if (!sh) { - if (!conf->inactive_blocked) - sh = get_free_stripe(conf); - if (noblock && sh == NULL) - break; - if (!sh) { - conf->inactive_blocked = 1; - wait_event_lock_irq(conf->wait_for_stripe, - !list_empty(&conf->inactive_list) && - (atomic_read(&conf->active_stripes) - < (conf->max_nr_stripes *3/4) - || !conf->inactive_blocked), - conf->device_lock, - unplug_slaves(conf->mddev); - ); - conf->inactive_blocked = 0; - } else - init_stripe(sh, sector, pd_idx); - } else { - if (atomic_read(&sh->count)) { - BUG_ON(!list_empty(&sh->lru)); - } else { - if (!test_bit(STRIPE_HANDLE, &sh->state)) - atomic_inc(&conf->active_stripes); - BUG_ON(list_empty(&sh->lru)); - list_del_init(&sh->lru); - } - } - } while (sh == NULL); - - if (sh) - atomic_inc(&sh->count); - - spin_unlock_irq(&conf->device_lock); - return sh; -} - -static int grow_one_stripe(raid6_conf_t *conf) -{ - struct stripe_head *sh; - sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL); - if (!sh) - return 0; - memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev)); - sh->raid_conf = conf; - spin_lock_init(&sh->lock); - - if (grow_buffers(sh, conf->raid_disks)) { - shrink_buffers(sh, conf->raid_disks); - kmem_cache_free(conf->slab_cache, sh); - return 0; - } - /* we just created an active stripe so... */ - atomic_set(&sh->count, 1); - atomic_inc(&conf->active_stripes); - INIT_LIST_HEAD(&sh->lru); - release_stripe(sh); - return 1; -} - -static int grow_stripes(raid6_conf_t *conf, int num) -{ - kmem_cache_t *sc; - int devs = conf->raid_disks; - - sprintf(conf->cache_name[0], "raid6/%s", mdname(conf->mddev)); - - sc = kmem_cache_create(conf->cache_name[0], - sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), - 0, 0, NULL, NULL); - if (!sc) - return 1; - conf->slab_cache = sc; - while (num--) - if (!grow_one_stripe(conf)) - return 1; - return 0; -} - -static int drop_one_stripe(raid6_conf_t *conf) -{ - struct stripe_head *sh; - spin_lock_irq(&conf->device_lock); - sh = get_free_stripe(conf); - spin_unlock_irq(&conf->device_lock); - if (!sh) - return 0; - BUG_ON(atomic_read(&sh->count)); - shrink_buffers(sh, conf->raid_disks); - kmem_cache_free(conf->slab_cache, sh); - atomic_dec(&conf->active_stripes); - return 1; -} - -static void shrink_stripes(raid6_conf_t *conf) -{ - while (drop_one_stripe(conf)) - ; - - if (conf->slab_cache) - kmem_cache_destroy(conf->slab_cache); - conf->slab_cache = NULL; -} - -static int raid6_end_read_request(struct bio * bi, unsigned int bytes_done, - int error) -{ - struct stripe_head *sh = bi->bi_private; - raid6_conf_t *conf = sh->raid_conf; - int disks = conf->raid_disks, i; - int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); - - if (bi->bi_size) - return 1; - - for (i=0 ; idev[i].req) - break; - - PRINTK("end_read_request %llu/%d, count: %d, uptodate %d.\n", - (unsigned long long)sh->sector, i, atomic_read(&sh->count), - uptodate); - if (i == disks) { - BUG(); - return 0; - } - - if (uptodate) { -#if 0 - struct bio *bio; - unsigned long flags; - spin_lock_irqsave(&conf->device_lock, flags); - /* we can return a buffer if we bypassed the cache or - * if the top buffer is not in highmem. If there are - * multiple buffers, leave the extra work to - * handle_stripe - */ - buffer = sh->bh_read[i]; - if (buffer && - (!PageHighMem(buffer->b_page) - || buffer->b_page == bh->b_page ) - ) { - sh->bh_read[i] = buffer->b_reqnext; - buffer->b_reqnext = NULL; - } else - buffer = NULL; - spin_unlock_irqrestore(&conf->device_lock, flags); - if (sh->bh_page[i]==bh->b_page) - set_buffer_uptodate(bh); - if (buffer) { - if (buffer->b_page != bh->b_page) - memcpy(buffer->b_data, bh->b_data, bh->b_size); - buffer->b_end_io(buffer, 1); - } -#else - set_bit(R5_UPTODATE, &sh->dev[i].flags); -#endif - if (test_bit(R5_ReadError, &sh->dev[i].flags)) { - printk(KERN_INFO "raid6: read error corrected!!\n"); - clear_bit(R5_ReadError, &sh->dev[i].flags); - clear_bit(R5_ReWrite, &sh->dev[i].flags); - } - if (atomic_read(&conf->disks[i].rdev->read_errors)) - atomic_set(&conf->disks[i].rdev->read_errors, 0); - } else { - int retry = 0; - clear_bit(R5_UPTODATE, &sh->dev[i].flags); - atomic_inc(&conf->disks[i].rdev->read_errors); - if (conf->mddev->degraded) - printk(KERN_WARNING "raid6: read error not correctable.\n"); - else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) - /* Oh, no!!! */ - printk(KERN_WARNING "raid6: read error NOT corrected!!\n"); - else if (atomic_read(&conf->disks[i].rdev->read_errors) - > conf->max_nr_stripes) - printk(KERN_WARNING - "raid6: Too many read errors, failing device.\n"); - else - retry = 1; - if (retry) - set_bit(R5_ReadError, &sh->dev[i].flags); - else { - clear_bit(R5_ReadError, &sh->dev[i].flags); - clear_bit(R5_ReWrite, &sh->dev[i].flags); - md_error(conf->mddev, conf->disks[i].rdev); - } - } - rdev_dec_pending(conf->disks[i].rdev, conf->mddev); -#if 0 - /* must restore b_page before unlocking buffer... */ - if (sh->bh_page[i] != bh->b_page) { - bh->b_page = sh->bh_page[i]; - bh->b_data = page_address(bh->b_page); - clear_buffer_uptodate(bh); - } -#endif - clear_bit(R5_LOCKED, &sh->dev[i].flags); - set_bit(STRIPE_HANDLE, &sh->state); - release_stripe(sh); - return 0; -} - -static int raid6_end_write_request (struct bio *bi, unsigned int bytes_done, - int error) -{ - struct stripe_head *sh = bi->bi_private; - raid6_conf_t *conf = sh->raid_conf; - int disks = conf->raid_disks, i; - unsigned long flags; - int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); - - if (bi->bi_size) - return 1; - - for (i=0 ; idev[i].req) - break; - - PRINTK("end_write_request %llu/%d, count %d, uptodate: %d.\n", - (unsigned long long)sh->sector, i, atomic_read(&sh->count), - uptodate); - if (i == disks) { - BUG(); - return 0; - } - - spin_lock_irqsave(&conf->device_lock, flags); - if (!uptodate) - md_error(conf->mddev, conf->disks[i].rdev); - - rdev_dec_pending(conf->disks[i].rdev, conf->mddev); - - clear_bit(R5_LOCKED, &sh->dev[i].flags); - set_bit(STRIPE_HANDLE, &sh->state); - __release_stripe(conf, sh); - spin_unlock_irqrestore(&conf->device_lock, flags); - return 0; -} - - -static sector_t compute_blocknr(struct stripe_head *sh, int i); - -static void raid6_build_block (struct stripe_head *sh, int i) -{ - struct r5dev *dev = &sh->dev[i]; - int pd_idx = sh->pd_idx; - int qd_idx = raid6_next_disk(pd_idx, sh->raid_conf->raid_disks); - - bio_init(&dev->req); - dev->req.bi_io_vec = &dev->vec; - dev->req.bi_vcnt++; - dev->req.bi_max_vecs++; - dev->vec.bv_page = dev->page; - dev->vec.bv_len = STRIPE_SIZE; - dev->vec.bv_offset = 0; - - dev->req.bi_sector = sh->sector; - dev->req.bi_private = sh; - - dev->flags = 0; - if (i != pd_idx && i != qd_idx) - dev->sector = compute_blocknr(sh, i); -} - -static void error(mddev_t *mddev, mdk_rdev_t *rdev) -{ - char b[BDEVNAME_SIZE]; - raid6_conf_t *conf = (raid6_conf_t *) mddev->private; - PRINTK("raid6: error called\n"); - - if (!test_bit(Faulty, &rdev->flags)) { - mddev->sb_dirty = 1; - if (test_bit(In_sync, &rdev->flags)) { - conf->working_disks--; - mddev->degraded++; - conf->failed_disks++; - clear_bit(In_sync, &rdev->flags); - /* - * if recovery was running, make sure it aborts. - */ - set_bit(MD_RECOVERY_ERR, &mddev->recovery); - } - set_bit(Faulty, &rdev->flags); - printk (KERN_ALERT - "raid6: Disk failure on %s, disabling device." - " Operation continuing on %d devices\n", - bdevname(rdev->bdev,b), conf->working_disks); - } -} - -/* - * Input: a 'big' sector number, - * Output: index of the data and parity disk, and the sector # in them. - */ -static sector_t raid6_compute_sector(sector_t r_sector, unsigned int raid_disks, - unsigned int data_disks, unsigned int * dd_idx, - unsigned int * pd_idx, raid6_conf_t *conf) -{ - long stripe; - unsigned long chunk_number; - unsigned int chunk_offset; - sector_t new_sector; - int sectors_per_chunk = conf->chunk_size >> 9; - - /* First compute the information on this sector */ - - /* - * Compute the chunk number and the sector offset inside the chunk - */ - chunk_offset = sector_div(r_sector, sectors_per_chunk); - chunk_number = r_sector; - if ( r_sector != chunk_number ) { - printk(KERN_CRIT "raid6: ERROR: r_sector = %llu, chunk_number = %lu\n", - (unsigned long long)r_sector, (unsigned long)chunk_number); - BUG(); - } - - /* - * Compute the stripe number - */ - stripe = chunk_number / data_disks; - - /* - * Compute the data disk and parity disk indexes inside the stripe - */ - *dd_idx = chunk_number % data_disks; - - /* - * Select the parity disk based on the user selected algorithm. - */ - - /**** FIX THIS ****/ - switch (conf->algorithm) { - case ALGORITHM_LEFT_ASYMMETRIC: - *pd_idx = raid_disks - 1 - (stripe % raid_disks); - if (*pd_idx == raid_disks-1) - (*dd_idx)++; /* Q D D D P */ - else if (*dd_idx >= *pd_idx) - (*dd_idx) += 2; /* D D P Q D */ - break; - case ALGORITHM_RIGHT_ASYMMETRIC: - *pd_idx = stripe % raid_disks; - if (*pd_idx == raid_disks-1) - (*dd_idx)++; /* Q D D D P */ - else if (*dd_idx >= *pd_idx) - (*dd_idx) += 2; /* D D P Q D */ - break; - case ALGORITHM_LEFT_SYMMETRIC: - *pd_idx = raid_disks - 1 - (stripe % raid_disks); - *dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks; - break; - case ALGORITHM_RIGHT_SYMMETRIC: - *pd_idx = stripe % raid_disks; - *dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks; - break; - default: - printk (KERN_CRIT "raid6: unsupported algorithm %d\n", - conf->algorithm); - } - - PRINTK("raid6: chunk_number = %lu, pd_idx = %u, dd_idx = %u\n", - chunk_number, *pd_idx, *dd_idx); - - /* - * Finally, compute the new sector number - */ - new_sector = (sector_t) stripe * sectors_per_chunk + chunk_offset; - return new_sector; -} - - -static sector_t compute_blocknr(struct stripe_head *sh, int i) -{ - raid6_conf_t *conf = sh->raid_conf; - int raid_disks = conf->raid_disks, data_disks = raid_disks - 2; - sector_t new_sector = sh->sector, check; - int sectors_per_chunk = conf->chunk_size >> 9; - sector_t stripe; - int chunk_offset; - int chunk_number, dummy1, dummy2, dd_idx = i; - sector_t r_sector; - int i0 = i; - - chunk_offset = sector_div(new_sector, sectors_per_chunk); - stripe = new_sector; - if ( new_sector != stripe ) { - printk(KERN_CRIT "raid6: ERROR: new_sector = %llu, stripe = %lu\n", - (unsigned long long)new_sector, (unsigned long)stripe); - BUG(); - } - - switch (conf->algorithm) { - case ALGORITHM_LEFT_ASYMMETRIC: - case ALGORITHM_RIGHT_ASYMMETRIC: - if (sh->pd_idx == raid_disks-1) - i--; /* Q D D D P */ - else if (i > sh->pd_idx) - i -= 2; /* D D P Q D */ - break; - case ALGORITHM_LEFT_SYMMETRIC: - case ALGORITHM_RIGHT_SYMMETRIC: - if (sh->pd_idx == raid_disks-1) - i--; /* Q D D D P */ - else { - /* D D P Q D */ - if (i < sh->pd_idx) - i += raid_disks; - i -= (sh->pd_idx + 2); - } - break; - default: - printk (KERN_CRIT "raid6: unsupported algorithm %d\n", - conf->algorithm); - } - - PRINTK("raid6: compute_blocknr: pd_idx = %u, i0 = %u, i = %u\n", sh->pd_idx, i0, i); - - chunk_number = stripe * data_disks + i; - r_sector = (sector_t)chunk_number * sectors_per_chunk + chunk_offset; - - check = raid6_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf); - if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) { - printk(KERN_CRIT "raid6: compute_blocknr: map not correct\n"); - return 0; - } - return r_sector; -} - - - -/* - * Copy data between a page in the stripe cache, and one or more bion - * The page could align with the middle of the bio, or there could be - * several bion, each with several bio_vecs, which cover part of the page - * Multiple bion are linked together on bi_next. There may be extras - * at the end of this list. We ignore them. - */ -static void copy_data(int frombio, struct bio *bio, - struct page *page, - sector_t sector) -{ - char *pa = page_address(page); - struct bio_vec *bvl; - int i; - int page_offset; - - if (bio->bi_sector >= sector) - page_offset = (signed)(bio->bi_sector - sector) * 512; - else - page_offset = (signed)(sector - bio->bi_sector) * -512; - bio_for_each_segment(bvl, bio, i) { - int len = bio_iovec_idx(bio,i)->bv_len; - int clen; - int b_offset = 0; - - if (page_offset < 0) { - b_offset = -page_offset; - page_offset += b_offset; - len -= b_offset; - } - - if (len > 0 && page_offset + len > STRIPE_SIZE) - clen = STRIPE_SIZE - page_offset; - else clen = len; - - if (clen > 0) { - char *ba = __bio_kmap_atomic(bio, i, KM_USER0); - if (frombio) - memcpy(pa+page_offset, ba+b_offset, clen); - else - memcpy(ba+b_offset, pa+page_offset, clen); - __bio_kunmap_atomic(ba, KM_USER0); - } - if (clen < len) /* hit end of page */ - break; - page_offset += len; - } -} - -#define check_xor() do { \ - if (count == MAX_XOR_BLOCKS) { \ - xor_block(count, STRIPE_SIZE, ptr); \ - count = 1; \ - } \ - } while(0) - -/* Compute P and Q syndromes */ -static void compute_parity(struct stripe_head *sh, int method) -{ - raid6_conf_t *conf = sh->raid_conf; - int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = conf->raid_disks, count; - struct bio *chosen; - /**** FIX THIS: This could be very bad if disks is close to 256 ****/ - void *ptrs[disks]; - - qd_idx = raid6_next_disk(pd_idx, disks); - d0_idx = raid6_next_disk(qd_idx, disks); - - PRINTK("compute_parity, stripe %llu, method %d\n", - (unsigned long long)sh->sector, method); - - switch(method) { - case READ_MODIFY_WRITE: - BUG(); /* READ_MODIFY_WRITE N/A for RAID-6 */ - case RECONSTRUCT_WRITE: - for (i= disks; i-- ;) - if ( i != pd_idx && i != qd_idx && sh->dev[i].towrite ) { - chosen = sh->dev[i].towrite; - sh->dev[i].towrite = NULL; - - if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) - wake_up(&conf->wait_for_overlap); - - BUG_ON(sh->dev[i].written); - sh->dev[i].written = chosen; - } - break; - case CHECK_PARITY: - BUG(); /* Not implemented yet */ - } - - for (i = disks; i--;) - if (sh->dev[i].written) { - sector_t sector = sh->dev[i].sector; - struct bio *wbi = sh->dev[i].written; - while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) { - copy_data(1, wbi, sh->dev[i].page, sector); - wbi = r5_next_bio(wbi, sector); - } - - set_bit(R5_LOCKED, &sh->dev[i].flags); - set_bit(R5_UPTODATE, &sh->dev[i].flags); - } - -// switch(method) { -// case RECONSTRUCT_WRITE: -// case CHECK_PARITY: -// case UPDATE_PARITY: - /* Note that unlike RAID-5, the ordering of the disks matters greatly. */ - /* FIX: Is this ordering of drives even remotely optimal? */ - count = 0; - i = d0_idx; - do { - ptrs[count++] = page_address(sh->dev[i].page); - if (count <= disks-2 && !test_bit(R5_UPTODATE, &sh->dev[i].flags)) - printk("block %d/%d not uptodate on parity calc\n", i,count); - i = raid6_next_disk(i, disks); - } while ( i != d0_idx ); -// break; -// } - - raid6_call.gen_syndrome(disks, STRIPE_SIZE, ptrs); - - switch(method) { - case RECONSTRUCT_WRITE: - set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags); - set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags); - set_bit(R5_LOCKED, &sh->dev[pd_idx].flags); - set_bit(R5_LOCKED, &sh->dev[qd_idx].flags); - break; - case UPDATE_PARITY: - set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags); - set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags); - break; - } -} - -/* Compute one missing block */ -static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero) -{ - raid6_conf_t *conf = sh->raid_conf; - int i, count, disks = conf->raid_disks; - void *ptr[MAX_XOR_BLOCKS], *p; - int pd_idx = sh->pd_idx; - int qd_idx = raid6_next_disk(pd_idx, disks); - - PRINTK("compute_block_1, stripe %llu, idx %d\n", - (unsigned long long)sh->sector, dd_idx); - - if ( dd_idx == qd_idx ) { - /* We're actually computing the Q drive */ - compute_parity(sh, UPDATE_PARITY); - } else { - ptr[0] = page_address(sh->dev[dd_idx].page); - if (!nozero) memset(ptr[0], 0, STRIPE_SIZE); - count = 1; - for (i = disks ; i--; ) { - if (i == dd_idx || i == qd_idx) - continue; - p = page_address(sh->dev[i].page); - if (test_bit(R5_UPTODATE, &sh->dev[i].flags)) - ptr[count++] = p; - else - printk("compute_block() %d, stripe %llu, %d" - " not present\n", dd_idx, - (unsigned long long)sh->sector, i); - - check_xor(); - } - if (count != 1) - xor_block(count, STRIPE_SIZE, ptr); - if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); - else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); - } -} - -/* Compute two missing blocks */ -static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2) -{ - raid6_conf_t *conf = sh->raid_conf; - int i, count, disks = conf->raid_disks; - int pd_idx = sh->pd_idx; - int qd_idx = raid6_next_disk(pd_idx, disks); - int d0_idx = raid6_next_disk(qd_idx, disks); - int faila, failb; - - /* faila and failb are disk numbers relative to d0_idx */ - /* pd_idx become disks-2 and qd_idx become disks-1 */ - faila = (dd_idx1 < d0_idx) ? dd_idx1+(disks-d0_idx) : dd_idx1-d0_idx; - failb = (dd_idx2 < d0_idx) ? dd_idx2+(disks-d0_idx) : dd_idx2-d0_idx; - - BUG_ON(faila == failb); - if ( failb < faila ) { int tmp = faila; faila = failb; failb = tmp; } - - PRINTK("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n", - (unsigned long long)sh->sector, dd_idx1, dd_idx2, faila, failb); - - if ( failb == disks-1 ) { - /* Q disk is one of the missing disks */ - if ( faila == disks-2 ) { - /* Missing P+Q, just recompute */ - compute_parity(sh, UPDATE_PARITY); - return; - } else { - /* We're missing D+Q; recompute D from P */ - compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1, 0); - compute_parity(sh, UPDATE_PARITY); /* Is this necessary? */ - return; - } - } - - /* We're missing D+P or D+D; build pointer table */ - { - /**** FIX THIS: This could be very bad if disks is close to 256 ****/ - void *ptrs[disks]; - - count = 0; - i = d0_idx; - do { - ptrs[count++] = page_address(sh->dev[i].page); - i = raid6_next_disk(i, disks); - if (i != dd_idx1 && i != dd_idx2 && - !test_bit(R5_UPTODATE, &sh->dev[i].flags)) - printk("compute_2 with missing block %d/%d\n", count, i); - } while ( i != d0_idx ); - - if ( failb == disks-2 ) { - /* We're missing D+P. */ - raid6_datap_recov(disks, STRIPE_SIZE, faila, ptrs); - } else { - /* We're missing D+D. */ - raid6_2data_recov(disks, STRIPE_SIZE, faila, failb, ptrs); - } - - /* Both the above update both missing blocks */ - set_bit(R5_UPTODATE, &sh->dev[dd_idx1].flags); - set_bit(R5_UPTODATE, &sh->dev[dd_idx2].flags); - } -} - - -/* - * Each stripe/dev can have one or more bion attached. - * toread/towrite point to the first in a chain. - * The bi_next chain must be in order. - */ -static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite) -{ - struct bio **bip; - raid6_conf_t *conf = sh->raid_conf; - int firstwrite=0; - - PRINTK("adding bh b#%llu to stripe s#%llu\n", - (unsigned long long)bi->bi_sector, - (unsigned long long)sh->sector); - - - spin_lock(&sh->lock); - spin_lock_irq(&conf->device_lock); - if (forwrite) { - bip = &sh->dev[dd_idx].towrite; - if (*bip == NULL && sh->dev[dd_idx].written == NULL) - firstwrite = 1; - } else - bip = &sh->dev[dd_idx].toread; - while (*bip && (*bip)->bi_sector < bi->bi_sector) { - if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector) - goto overlap; - bip = &(*bip)->bi_next; - } - if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9)) - goto overlap; - - BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next); - if (*bip) - bi->bi_next = *bip; - *bip = bi; - bi->bi_phys_segments ++; - spin_unlock_irq(&conf->device_lock); - spin_unlock(&sh->lock); - - PRINTK("added bi b#%llu to stripe s#%llu, disk %d.\n", - (unsigned long long)bi->bi_sector, - (unsigned long long)sh->sector, dd_idx); - - if (conf->mddev->bitmap && firstwrite) { - sh->bm_seq = conf->seq_write; - bitmap_startwrite(conf->mddev->bitmap, sh->sector, - STRIPE_SECTORS, 0); - set_bit(STRIPE_BIT_DELAY, &sh->state); - } - - if (forwrite) { - /* check if page is covered */ - sector_t sector = sh->dev[dd_idx].sector; - for (bi=sh->dev[dd_idx].towrite; - sector < sh->dev[dd_idx].sector + STRIPE_SECTORS && - bi && bi->bi_sector <= sector; - bi = r5_next_bio(bi, sh->dev[dd_idx].sector)) { - if (bi->bi_sector + (bi->bi_size>>9) >= sector) - sector = bi->bi_sector + (bi->bi_size>>9); - } - if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS) - set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags); - } - return 1; - - overlap: - set_bit(R5_Overlap, &sh->dev[dd_idx].flags); - spin_unlock_irq(&conf->device_lock); - spin_unlock(&sh->lock); - return 0; -} - - -static int page_is_zero(struct page *p) -{ - char *a = page_address(p); - return ((*(u32*)a) == 0 && - memcmp(a, a+4, STRIPE_SIZE-4)==0); -} -/* - * handle_stripe - do things to a stripe. - * - * We lock the stripe and then examine the state of various bits - * to see what needs to be done. - * Possible results: - * return some read request which now have data - * return some write requests which are safely on disc - * schedule a read on some buffers - * schedule a write of some buffers - * return confirmation of parity correctness - * - * Parity calculations are done inside the stripe lock - * buffers are taken off read_list or write_list, and bh_cache buffers - * get BH_Lock set before the stripe lock is released. - * - */ - -static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) -{ - raid6_conf_t *conf = sh->raid_conf; - int disks = conf->raid_disks; - struct bio *return_bi= NULL; - struct bio *bi; - int i; - int syncing; - int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0; - int non_overwrite = 0; - int failed_num[2] = {0, 0}; - struct r5dev *dev, *pdev, *qdev; - int pd_idx = sh->pd_idx; - int qd_idx = raid6_next_disk(pd_idx, disks); - int p_failed, q_failed; - - PRINTK("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d, qd_idx=%d\n", - (unsigned long long)sh->sector, sh->state, atomic_read(&sh->count), - pd_idx, qd_idx); - - spin_lock(&sh->lock); - clear_bit(STRIPE_HANDLE, &sh->state); - clear_bit(STRIPE_DELAYED, &sh->state); - - syncing = test_bit(STRIPE_SYNCING, &sh->state); - /* Now to look around and see what can be done */ - - rcu_read_lock(); - for (i=disks; i--; ) { - mdk_rdev_t *rdev; - dev = &sh->dev[i]; - clear_bit(R5_Insync, &dev->flags); - - PRINTK("check %d: state 0x%lx read %p write %p written %p\n", - i, dev->flags, dev->toread, dev->towrite, dev->written); - /* maybe we can reply to a read */ - if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) { - struct bio *rbi, *rbi2; - PRINTK("Return read for disc %d\n", i); - spin_lock_irq(&conf->device_lock); - rbi = dev->toread; - dev->toread = NULL; - if (test_and_clear_bit(R5_Overlap, &dev->flags)) - wake_up(&conf->wait_for_overlap); - spin_unlock_irq(&conf->device_lock); - while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) { - copy_data(0, rbi, dev->page, dev->sector); - rbi2 = r5_next_bio(rbi, dev->sector); - spin_lock_irq(&conf->device_lock); - if (--rbi->bi_phys_segments == 0) { - rbi->bi_next = return_bi; - return_bi = rbi; - } - spin_unlock_irq(&conf->device_lock); - rbi = rbi2; - } - } - - /* now count some things */ - if (test_bit(R5_LOCKED, &dev->flags)) locked++; - if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++; - - - if (dev->toread) to_read++; - if (dev->towrite) { - to_write++; - if (!test_bit(R5_OVERWRITE, &dev->flags)) - non_overwrite++; - } - if (dev->written) written++; - rdev = rcu_dereference(conf->disks[i].rdev); - if (!rdev || !test_bit(In_sync, &rdev->flags)) { - /* The ReadError flag will just be confusing now */ - clear_bit(R5_ReadError, &dev->flags); - clear_bit(R5_ReWrite, &dev->flags); - } - if (!rdev || !test_bit(In_sync, &rdev->flags) - || test_bit(R5_ReadError, &dev->flags)) { - if ( failed < 2 ) - failed_num[failed] = i; - failed++; - } else - set_bit(R5_Insync, &dev->flags); - } - rcu_read_unlock(); - PRINTK("locked=%d uptodate=%d to_read=%d" - " to_write=%d failed=%d failed_num=%d,%d\n", - locked, uptodate, to_read, to_write, failed, - failed_num[0], failed_num[1]); - /* check if the array has lost >2 devices and, if so, some requests might - * need to be failed - */ - if (failed > 2 && to_read+to_write+written) { - for (i=disks; i--; ) { - int bitmap_end = 0; - - if (test_bit(R5_ReadError, &sh->dev[i].flags)) { - mdk_rdev_t *rdev; - rcu_read_lock(); - rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && test_bit(In_sync, &rdev->flags)) - /* multiple read failures in one stripe */ - md_error(conf->mddev, rdev); - rcu_read_unlock(); - } - - spin_lock_irq(&conf->device_lock); - /* fail all writes first */ - bi = sh->dev[i].towrite; - sh->dev[i].towrite = NULL; - if (bi) { to_write--; bitmap_end = 1; } - - if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) - wake_up(&conf->wait_for_overlap); - - while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){ - struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); - clear_bit(BIO_UPTODATE, &bi->bi_flags); - if (--bi->bi_phys_segments == 0) { - md_write_end(conf->mddev); - bi->bi_next = return_bi; - return_bi = bi; - } - bi = nextbi; - } - /* and fail all 'written' */ - bi = sh->dev[i].written; - sh->dev[i].written = NULL; - if (bi) bitmap_end = 1; - while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) { - struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector); - clear_bit(BIO_UPTODATE, &bi->bi_flags); - if (--bi->bi_phys_segments == 0) { - md_write_end(conf->mddev); - bi->bi_next = return_bi; - return_bi = bi; - } - bi = bi2; - } - - /* fail any reads if this device is non-operational */ - if (!test_bit(R5_Insync, &sh->dev[i].flags) || - test_bit(R5_ReadError, &sh->dev[i].flags)) { - bi = sh->dev[i].toread; - sh->dev[i].toread = NULL; - if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) - wake_up(&conf->wait_for_overlap); - if (bi) to_read--; - while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){ - struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); - clear_bit(BIO_UPTODATE, &bi->bi_flags); - if (--bi->bi_phys_segments == 0) { - bi->bi_next = return_bi; - return_bi = bi; - } - bi = nextbi; - } - } - spin_unlock_irq(&conf->device_lock); - if (bitmap_end) - bitmap_endwrite(conf->mddev->bitmap, sh->sector, - STRIPE_SECTORS, 0, 0); - } - } - if (failed > 2 && syncing) { - md_done_sync(conf->mddev, STRIPE_SECTORS,0); - clear_bit(STRIPE_SYNCING, &sh->state); - syncing = 0; - } - - /* - * might be able to return some write requests if the parity blocks - * are safe, or on a failed drive - */ - pdev = &sh->dev[pd_idx]; - p_failed = (failed >= 1 && failed_num[0] == pd_idx) - || (failed >= 2 && failed_num[1] == pd_idx); - qdev = &sh->dev[qd_idx]; - q_failed = (failed >= 1 && failed_num[0] == qd_idx) - || (failed >= 2 && failed_num[1] == qd_idx); - - if ( written && - ( p_failed || ((test_bit(R5_Insync, &pdev->flags) - && !test_bit(R5_LOCKED, &pdev->flags) - && test_bit(R5_UPTODATE, &pdev->flags))) ) && - ( q_failed || ((test_bit(R5_Insync, &qdev->flags) - && !test_bit(R5_LOCKED, &qdev->flags) - && test_bit(R5_UPTODATE, &qdev->flags))) ) ) { - /* any written block on an uptodate or failed drive can be - * returned. Note that if we 'wrote' to a failed drive, - * it will be UPTODATE, but never LOCKED, so we don't need - * to test 'failed' directly. - */ - for (i=disks; i--; ) - if (sh->dev[i].written) { - dev = &sh->dev[i]; - if (!test_bit(R5_LOCKED, &dev->flags) && - test_bit(R5_UPTODATE, &dev->flags) ) { - /* We can return any write requests */ - int bitmap_end = 0; - struct bio *wbi, *wbi2; - PRINTK("Return write for stripe %llu disc %d\n", - (unsigned long long)sh->sector, i); - spin_lock_irq(&conf->device_lock); - wbi = dev->written; - dev->written = NULL; - while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) { - wbi2 = r5_next_bio(wbi, dev->sector); - if (--wbi->bi_phys_segments == 0) { - md_write_end(conf->mddev); - wbi->bi_next = return_bi; - return_bi = wbi; - } - wbi = wbi2; - } - if (dev->towrite == NULL) - bitmap_end = 1; - spin_unlock_irq(&conf->device_lock); - if (bitmap_end) - bitmap_endwrite(conf->mddev->bitmap, sh->sector, - STRIPE_SECTORS, - !test_bit(STRIPE_DEGRADED, &sh->state), 0); - } - } - } - - /* Now we might consider reading some blocks, either to check/generate - * parity, or to satisfy requests - * or to load a block that is being partially written. - */ - if (to_read || non_overwrite || (to_write && failed) || (syncing && (uptodate < disks))) { - for (i=disks; i--;) { - dev = &sh->dev[i]; - if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) && - (dev->toread || - (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) || - syncing || - (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) || - (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write)) - ) - ) { - /* we would like to get this block, possibly - * by computing it, but we might not be able to - */ - if (uptodate == disks-1) { - PRINTK("Computing stripe %llu block %d\n", - (unsigned long long)sh->sector, i); - compute_block_1(sh, i, 0); - uptodate++; - } else if ( uptodate == disks-2 && failed >= 2 ) { - /* Computing 2-failure is *very* expensive; only do it if failed >= 2 */ - int other; - for (other=disks; other--;) { - if ( other == i ) - continue; - if ( !test_bit(R5_UPTODATE, &sh->dev[other].flags) ) - break; - } - BUG_ON(other < 0); - PRINTK("Computing stripe %llu blocks %d,%d\n", - (unsigned long long)sh->sector, i, other); - compute_block_2(sh, i, other); - uptodate += 2; - } else if (test_bit(R5_Insync, &dev->flags)) { - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantread, &dev->flags); -#if 0 - /* if I am just reading this block and we don't have - a failed drive, or any pending writes then sidestep the cache */ - if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext && - ! syncing && !failed && !to_write) { - sh->bh_cache[i]->b_page = sh->bh_read[i]->b_page; - sh->bh_cache[i]->b_data = sh->bh_read[i]->b_data; - } -#endif - locked++; - PRINTK("Reading block %d (sync=%d)\n", - i, syncing); - } - } - } - set_bit(STRIPE_HANDLE, &sh->state); - } - - /* now to consider writing and what else, if anything should be read */ - if (to_write) { - int rcw=0, must_compute=0; - for (i=disks ; i--;) { - dev = &sh->dev[i]; - /* Would I have to read this buffer for reconstruct_write */ - if (!test_bit(R5_OVERWRITE, &dev->flags) - && i != pd_idx && i != qd_idx - && (!test_bit(R5_LOCKED, &dev->flags) -#if 0 - || sh->bh_page[i] != bh->b_page -#endif - ) && - !test_bit(R5_UPTODATE, &dev->flags)) { - if (test_bit(R5_Insync, &dev->flags)) rcw++; - else { - PRINTK("raid6: must_compute: disk %d flags=%#lx\n", i, dev->flags); - must_compute++; - } - } - } - PRINTK("for sector %llu, rcw=%d, must_compute=%d\n", - (unsigned long long)sh->sector, rcw, must_compute); - set_bit(STRIPE_HANDLE, &sh->state); - - if (rcw > 0) - /* want reconstruct write, but need to get some data */ - for (i=disks; i--;) { - dev = &sh->dev[i]; - if (!test_bit(R5_OVERWRITE, &dev->flags) - && !(failed == 0 && (i == pd_idx || i == qd_idx)) - && !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) && - test_bit(R5_Insync, &dev->flags)) { - if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) - { - PRINTK("Read_old stripe %llu block %d for Reconstruct\n", - (unsigned long long)sh->sector, i); - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantread, &dev->flags); - locked++; - } else { - PRINTK("Request delayed stripe %llu block %d for Reconstruct\n", - (unsigned long long)sh->sector, i); - set_bit(STRIPE_DELAYED, &sh->state); - set_bit(STRIPE_HANDLE, &sh->state); - } - } - } - /* now if nothing is locked, and if we have enough data, we can start a write request */ - if (locked == 0 && rcw == 0 && - !test_bit(STRIPE_BIT_DELAY, &sh->state)) { - if ( must_compute > 0 ) { - /* We have failed blocks and need to compute them */ - switch ( failed ) { - case 0: BUG(); - case 1: compute_block_1(sh, failed_num[0], 0); break; - case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break; - default: BUG(); /* This request should have been failed? */ - } - } - - PRINTK("Computing parity for stripe %llu\n", (unsigned long long)sh->sector); - compute_parity(sh, RECONSTRUCT_WRITE); - /* now every locked buffer is ready to be written */ - for (i=disks; i--;) - if (test_bit(R5_LOCKED, &sh->dev[i].flags)) { - PRINTK("Writing stripe %llu block %d\n", - (unsigned long long)sh->sector, i); - locked++; - set_bit(R5_Wantwrite, &sh->dev[i].flags); - } - /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */ - set_bit(STRIPE_INSYNC, &sh->state); - - if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) { - atomic_dec(&conf->preread_active_stripes); - if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) - md_wakeup_thread(conf->mddev->thread); - } - } - } - - /* maybe we need to check and possibly fix the parity for this stripe - * Any reads will already have been scheduled, so we just see if enough data - * is available - */ - if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) { - int update_p = 0, update_q = 0; - struct r5dev *dev; - - set_bit(STRIPE_HANDLE, &sh->state); - - BUG_ON(failed>2); - BUG_ON(uptodate < disks); - /* Want to check and possibly repair P and Q. - * However there could be one 'failed' device, in which - * case we can only check one of them, possibly using the - * other to generate missing data - */ - - /* If !tmp_page, we cannot do the calculations, - * but as we have set STRIPE_HANDLE, we will soon be called - * by stripe_handle with a tmp_page - just wait until then. - */ - if (tmp_page) { - if (failed == q_failed) { - /* The only possible failed device holds 'Q', so it makes - * sense to check P (If anything else were failed, we would - * have used P to recreate it). - */ - compute_block_1(sh, pd_idx, 1); - if (!page_is_zero(sh->dev[pd_idx].page)) { - compute_block_1(sh,pd_idx,0); - update_p = 1; - } - } - if (!q_failed && failed < 2) { - /* q is not failed, and we didn't use it to generate - * anything, so it makes sense to check it - */ - memcpy(page_address(tmp_page), - page_address(sh->dev[qd_idx].page), - STRIPE_SIZE); - compute_parity(sh, UPDATE_PARITY); - if (memcmp(page_address(tmp_page), - page_address(sh->dev[qd_idx].page), - STRIPE_SIZE)!= 0) { - clear_bit(STRIPE_INSYNC, &sh->state); - update_q = 1; - } - } - if (update_p || update_q) { - conf->mddev->resync_mismatches += STRIPE_SECTORS; - if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) - /* don't try to repair!! */ - update_p = update_q = 0; - } - - /* now write out any block on a failed drive, - * or P or Q if they need it - */ - - if (failed == 2) { - dev = &sh->dev[failed_num[1]]; - locked++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); - } - if (failed >= 1) { - dev = &sh->dev[failed_num[0]]; - locked++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); - } - - if (update_p) { - dev = &sh->dev[pd_idx]; - locked ++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); - } - if (update_q) { - dev = &sh->dev[qd_idx]; - locked++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); - } - clear_bit(STRIPE_DEGRADED, &sh->state); - - set_bit(STRIPE_INSYNC, &sh->state); - } - } - - if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) { - md_done_sync(conf->mddev, STRIPE_SECTORS,1); - clear_bit(STRIPE_SYNCING, &sh->state); - } - - /* If the failed drives are just a ReadError, then we might need - * to progress the repair/check process - */ - if (failed <= 2 && ! conf->mddev->ro) - for (i=0; idev[failed_num[i]]; - if (test_bit(R5_ReadError, &dev->flags) - && !test_bit(R5_LOCKED, &dev->flags) - && test_bit(R5_UPTODATE, &dev->flags) - ) { - if (!test_bit(R5_ReWrite, &dev->flags)) { - set_bit(R5_Wantwrite, &dev->flags); - set_bit(R5_ReWrite, &dev->flags); - set_bit(R5_LOCKED, &dev->flags); - } else { - /* let's read it back */ - set_bit(R5_Wantread, &dev->flags); - set_bit(R5_LOCKED, &dev->flags); - } - } - } - spin_unlock(&sh->lock); - - while ((bi=return_bi)) { - int bytes = bi->bi_size; - - return_bi = bi->bi_next; - bi->bi_next = NULL; - bi->bi_size = 0; - bi->bi_end_io(bi, bytes, 0); - } - for (i=disks; i-- ;) { - int rw; - struct bio *bi; - mdk_rdev_t *rdev; - if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) - rw = 1; - else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags)) - rw = 0; - else - continue; - - bi = &sh->dev[i].req; - - bi->bi_rw = rw; - if (rw) - bi->bi_end_io = raid6_end_write_request; - else - bi->bi_end_io = raid6_end_read_request; - - rcu_read_lock(); - rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && test_bit(Faulty, &rdev->flags)) - rdev = NULL; - if (rdev) - atomic_inc(&rdev->nr_pending); - rcu_read_unlock(); - - if (rdev) { - if (syncing) - md_sync_acct(rdev->bdev, STRIPE_SECTORS); - - bi->bi_bdev = rdev->bdev; - PRINTK("for %llu schedule op %ld on disc %d\n", - (unsigned long long)sh->sector, bi->bi_rw, i); - atomic_inc(&sh->count); - bi->bi_sector = sh->sector + rdev->data_offset; - bi->bi_flags = 1 << BIO_UPTODATE; - bi->bi_vcnt = 1; - bi->bi_max_vecs = 1; - bi->bi_idx = 0; - bi->bi_io_vec = &sh->dev[i].vec; - bi->bi_io_vec[0].bv_len = STRIPE_SIZE; - bi->bi_io_vec[0].bv_offset = 0; - bi->bi_size = STRIPE_SIZE; - bi->bi_next = NULL; - if (rw == WRITE && - test_bit(R5_ReWrite, &sh->dev[i].flags)) - atomic_add(STRIPE_SECTORS, &rdev->corrected_errors); - generic_make_request(bi); - } else { - if (rw == 1) - set_bit(STRIPE_DEGRADED, &sh->state); - PRINTK("skip op %ld on disc %d for sector %llu\n", - bi->bi_rw, i, (unsigned long long)sh->sector); - clear_bit(R5_LOCKED, &sh->dev[i].flags); - set_bit(STRIPE_HANDLE, &sh->state); - } - } -} - -static void raid6_activate_delayed(raid6_conf_t *conf) -{ - if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) { - while (!list_empty(&conf->delayed_list)) { - struct list_head *l = conf->delayed_list.next; - struct stripe_head *sh; - sh = list_entry(l, struct stripe_head, lru); - list_del_init(l); - clear_bit(STRIPE_DELAYED, &sh->state); - if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) - atomic_inc(&conf->preread_active_stripes); - list_add_tail(&sh->lru, &conf->handle_list); - } - } -} - -static void activate_bit_delay(raid6_conf_t *conf) -{ - /* device_lock is held */ - struct list_head head; - list_add(&head, &conf->bitmap_list); - list_del_init(&conf->bitmap_list); - while (!list_empty(&head)) { - struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru); - list_del_init(&sh->lru); - atomic_inc(&sh->count); - __release_stripe(conf, sh); - } -} - -static void unplug_slaves(mddev_t *mddev) -{ - raid6_conf_t *conf = mddev_to_conf(mddev); - int i; - - rcu_read_lock(); - for (i=0; iraid_disks; i++) { - mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { - request_queue_t *r_queue = bdev_get_queue(rdev->bdev); - - atomic_inc(&rdev->nr_pending); - rcu_read_unlock(); - - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); - - rdev_dec_pending(rdev, mddev); - rcu_read_lock(); - } - } - rcu_read_unlock(); -} - -static void raid6_unplug_device(request_queue_t *q) -{ - mddev_t *mddev = q->queuedata; - raid6_conf_t *conf = mddev_to_conf(mddev); - unsigned long flags; - - spin_lock_irqsave(&conf->device_lock, flags); - - if (blk_remove_plug(q)) { - conf->seq_flush++; - raid6_activate_delayed(conf); - } - md_wakeup_thread(mddev->thread); - - spin_unlock_irqrestore(&conf->device_lock, flags); - - unplug_slaves(mddev); -} - -static int raid6_issue_flush(request_queue_t *q, struct gendisk *disk, - sector_t *error_sector) -{ - mddev_t *mddev = q->queuedata; - raid6_conf_t *conf = mddev_to_conf(mddev); - int i, ret = 0; - - rcu_read_lock(); - for (i=0; iraid_disks && ret == 0; i++) { - mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !test_bit(Faulty, &rdev->flags)) { - struct block_device *bdev = rdev->bdev; - request_queue_t *r_queue = bdev_get_queue(bdev); - - if (!r_queue->issue_flush_fn) - ret = -EOPNOTSUPP; - else { - atomic_inc(&rdev->nr_pending); - rcu_read_unlock(); - ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, - error_sector); - rdev_dec_pending(rdev, mddev); - rcu_read_lock(); - } - } - } - rcu_read_unlock(); - return ret; -} - -static inline void raid6_plug_device(raid6_conf_t *conf) -{ - spin_lock_irq(&conf->device_lock); - blk_plug_device(conf->mddev->queue); - spin_unlock_irq(&conf->device_lock); -} - -static int make_request (request_queue_t *q, struct bio * bi) -{ - mddev_t *mddev = q->queuedata; - raid6_conf_t *conf = mddev_to_conf(mddev); - const unsigned int raid_disks = conf->raid_disks; - const unsigned int data_disks = raid_disks - 2; - unsigned int dd_idx, pd_idx; - sector_t new_sector; - sector_t logical_sector, last_sector; - struct stripe_head *sh; - const int rw = bio_data_dir(bi); - - if (unlikely(bio_barrier(bi))) { - bio_endio(bi, bi->bi_size, -EOPNOTSUPP); - return 0; - } - - md_write_start(mddev, bi); - - disk_stat_inc(mddev->gendisk, ios[rw]); - disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi)); - - logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1); - last_sector = bi->bi_sector + (bi->bi_size>>9); - - bi->bi_next = NULL; - bi->bi_phys_segments = 1; /* over-loaded to count active stripes */ - - for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { - DEFINE_WAIT(w); - - new_sector = raid6_compute_sector(logical_sector, - raid_disks, data_disks, &dd_idx, &pd_idx, conf); - - PRINTK("raid6: make_request, sector %llu logical %llu\n", - (unsigned long long)new_sector, - (unsigned long long)logical_sector); - - retry: - prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); - sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK)); - if (sh) { - if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) { - /* Add failed due to overlap. Flush everything - * and wait a while - */ - raid6_unplug_device(mddev->queue); - release_stripe(sh); - schedule(); - goto retry; - } - finish_wait(&conf->wait_for_overlap, &w); - raid6_plug_device(conf); - handle_stripe(sh, NULL); - release_stripe(sh); - } else { - /* cannot get stripe for read-ahead, just give-up */ - clear_bit(BIO_UPTODATE, &bi->bi_flags); - finish_wait(&conf->wait_for_overlap, &w); - break; - } - - } - spin_lock_irq(&conf->device_lock); - if (--bi->bi_phys_segments == 0) { - int bytes = bi->bi_size; - - if (rw == WRITE ) - md_write_end(mddev); - bi->bi_size = 0; - bi->bi_end_io(bi, bytes, 0); - } - spin_unlock_irq(&conf->device_lock); - return 0; -} - -/* FIXME go_faster isn't used */ -static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster) -{ - raid6_conf_t *conf = (raid6_conf_t *) mddev->private; - struct stripe_head *sh; - int sectors_per_chunk = conf->chunk_size >> 9; - sector_t x; - unsigned long stripe; - int chunk_offset; - int dd_idx, pd_idx; - sector_t first_sector; - int raid_disks = conf->raid_disks; - int data_disks = raid_disks - 2; - sector_t max_sector = mddev->size << 1; - int sync_blocks; - int still_degraded = 0; - int i; - - if (sector_nr >= max_sector) { - /* just being told to finish up .. nothing much to do */ - unplug_slaves(mddev); - - if (mddev->curr_resync < max_sector) /* aborted */ - bitmap_end_sync(mddev->bitmap, mddev->curr_resync, - &sync_blocks, 1); - else /* completed sync */ - conf->fullsync = 0; - bitmap_close_sync(mddev->bitmap); - - return 0; - } - /* if there are 2 or more failed drives and we are trying - * to resync, then assert that we are finished, because there is - * nothing we can do. - */ - if (mddev->degraded >= 2 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { - sector_t rv = (mddev->size << 1) - sector_nr; - *skipped = 1; - return rv; - } - if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) && - !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) && - !conf->fullsync && sync_blocks >= STRIPE_SECTORS) { - /* we can skip this block, and probably more */ - sync_blocks /= STRIPE_SECTORS; - *skipped = 1; - return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */ - } - - x = sector_nr; - chunk_offset = sector_div(x, sectors_per_chunk); - stripe = x; - BUG_ON(x != stripe); - - first_sector = raid6_compute_sector((sector_t)stripe*data_disks*sectors_per_chunk - + chunk_offset, raid_disks, data_disks, &dd_idx, &pd_idx, conf); - sh = get_active_stripe(conf, sector_nr, pd_idx, 1); - if (sh == NULL) { - sh = get_active_stripe(conf, sector_nr, pd_idx, 0); - /* make sure we don't swamp the stripe cache if someone else - * is trying to get access - */ - schedule_timeout_uninterruptible(1); - } - /* Need to check if array will still be degraded after recovery/resync - * We don't need to check the 'failed' flag as when that gets set, - * recovery aborts. - */ - for (i=0; iraid_disks; i++) - if (conf->disks[i].rdev == NULL) - still_degraded = 1; - - bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded); - - spin_lock(&sh->lock); - set_bit(STRIPE_SYNCING, &sh->state); - clear_bit(STRIPE_INSYNC, &sh->state); - spin_unlock(&sh->lock); - - handle_stripe(sh, NULL); - release_stripe(sh); - - return STRIPE_SECTORS; -} - -/* - * This is our raid6 kernel thread. - * - * We scan the hash table for stripes which can be handled now. - * During the scan, completed stripes are saved for us by the interrupt - * handler, so that they will not have to wait for our next wakeup. - */ -static void raid6d (mddev_t *mddev) -{ - struct stripe_head *sh; - raid6_conf_t *conf = mddev_to_conf(mddev); - int handled; - - PRINTK("+++ raid6d active\n"); - - md_check_recovery(mddev); - - handled = 0; - spin_lock_irq(&conf->device_lock); - while (1) { - struct list_head *first; - - if (conf->seq_flush - conf->seq_write > 0) { - int seq = conf->seq_flush; - spin_unlock_irq(&conf->device_lock); - bitmap_unplug(mddev->bitmap); - spin_lock_irq(&conf->device_lock); - conf->seq_write = seq; - activate_bit_delay(conf); - } - - if (list_empty(&conf->handle_list) && - atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD && - !blk_queue_plugged(mddev->queue) && - !list_empty(&conf->delayed_list)) - raid6_activate_delayed(conf); - - if (list_empty(&conf->handle_list)) - break; - - first = conf->handle_list.next; - sh = list_entry(first, struct stripe_head, lru); - - list_del_init(first); - atomic_inc(&sh->count); - BUG_ON(atomic_read(&sh->count)!= 1); - spin_unlock_irq(&conf->device_lock); - - handled++; - handle_stripe(sh, conf->spare_page); - release_stripe(sh); - - spin_lock_irq(&conf->device_lock); - } - PRINTK("%d stripes handled\n", handled); - - spin_unlock_irq(&conf->device_lock); - - unplug_slaves(mddev); - - PRINTK("--- raid6d inactive\n"); -} - -static ssize_t -raid6_show_stripe_cache_size(mddev_t *mddev, char *page) -{ - raid6_conf_t *conf = mddev_to_conf(mddev); - if (conf) - return sprintf(page, "%d\n", conf->max_nr_stripes); - else - return 0; -} - -static ssize_t -raid6_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len) -{ - raid6_conf_t *conf = mddev_to_conf(mddev); - char *end; - int new; - if (len >= PAGE_SIZE) - return -EINVAL; - if (!conf) - return -ENODEV; - - new = simple_strtoul(page, &end, 10); - if (!*page || (*end && *end != '\n') ) - return -EINVAL; - if (new <= 16 || new > 32768) - return -EINVAL; - while (new < conf->max_nr_stripes) { - if (drop_one_stripe(conf)) - conf->max_nr_stripes--; - else - break; - } - while (new > conf->max_nr_stripes) { - if (grow_one_stripe(conf)) - conf->max_nr_stripes++; - else break; - } - return len; -} - -static struct md_sysfs_entry -raid6_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR, - raid6_show_stripe_cache_size, - raid6_store_stripe_cache_size); - -static ssize_t -stripe_cache_active_show(mddev_t *mddev, char *page) -{ - raid6_conf_t *conf = mddev_to_conf(mddev); - if (conf) - return sprintf(page, "%d\n", atomic_read(&conf->active_stripes)); - else - return 0; -} - -static struct md_sysfs_entry -raid6_stripecache_active = __ATTR_RO(stripe_cache_active); - -static struct attribute *raid6_attrs[] = { - &raid6_stripecache_size.attr, - &raid6_stripecache_active.attr, - NULL, -}; -static struct attribute_group raid6_attrs_group = { - .name = NULL, - .attrs = raid6_attrs, -}; - -static int run(mddev_t *mddev) -{ - raid6_conf_t *conf; - int raid_disk, memory; - mdk_rdev_t *rdev; - struct disk_info *disk; - struct list_head *tmp; - - if (mddev->level != 6) { - PRINTK("raid6: %s: raid level not set to 6 (%d)\n", mdname(mddev), mddev->level); - return -EIO; - } - - mddev->private = kzalloc(sizeof (raid6_conf_t), GFP_KERNEL); - if ((conf = mddev->private) == NULL) - goto abort; - conf->disks = kzalloc(mddev->raid_disks * sizeof(struct disk_info), - GFP_KERNEL); - if (!conf->disks) - goto abort; - - conf->mddev = mddev; - - if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL) - goto abort; - - conf->spare_page = alloc_page(GFP_KERNEL); - if (!conf->spare_page) - goto abort; - - spin_lock_init(&conf->device_lock); - init_waitqueue_head(&conf->wait_for_stripe); - init_waitqueue_head(&conf->wait_for_overlap); - INIT_LIST_HEAD(&conf->handle_list); - INIT_LIST_HEAD(&conf->delayed_list); - INIT_LIST_HEAD(&conf->bitmap_list); - INIT_LIST_HEAD(&conf->inactive_list); - atomic_set(&conf->active_stripes, 0); - atomic_set(&conf->preread_active_stripes, 0); - - PRINTK("raid6: run(%s) called.\n", mdname(mddev)); - - ITERATE_RDEV(mddev,rdev,tmp) { - raid_disk = rdev->raid_disk; - if (raid_disk >= mddev->raid_disks - || raid_disk < 0) - continue; - disk = conf->disks + raid_disk; - - disk->rdev = rdev; - - if (test_bit(In_sync, &rdev->flags)) { - char b[BDEVNAME_SIZE]; - printk(KERN_INFO "raid6: device %s operational as raid" - " disk %d\n", bdevname(rdev->bdev,b), - raid_disk); - conf->working_disks++; - } - } - - conf->raid_disks = mddev->raid_disks; - - /* - * 0 for a fully functional array, 1 or 2 for a degraded array. - */ - mddev->degraded = conf->failed_disks = conf->raid_disks - conf->working_disks; - conf->mddev = mddev; - conf->chunk_size = mddev->chunk_size; - conf->level = mddev->level; - conf->algorithm = mddev->layout; - conf->max_nr_stripes = NR_STRIPES; - - /* device size must be a multiple of chunk size */ - mddev->size &= ~(mddev->chunk_size/1024 -1); - mddev->resync_max_sectors = mddev->size << 1; - - if (conf->raid_disks < 4) { - printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n", - mdname(mddev), conf->raid_disks); - goto abort; - } - if (!conf->chunk_size || conf->chunk_size % 4) { - printk(KERN_ERR "raid6: invalid chunk size %d for %s\n", - conf->chunk_size, mdname(mddev)); - goto abort; - } - if (conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) { - printk(KERN_ERR - "raid6: unsupported parity algorithm %d for %s\n", - conf->algorithm, mdname(mddev)); - goto abort; - } - if (mddev->degraded > 2) { - printk(KERN_ERR "raid6: not enough operational devices for %s" - " (%d/%d failed)\n", - mdname(mddev), conf->failed_disks, conf->raid_disks); - goto abort; - } - - if (mddev->degraded > 0 && - mddev->recovery_cp != MaxSector) { - if (mddev->ok_start_degraded) - printk(KERN_WARNING "raid6: starting dirty degraded array:%s" - "- data corruption possible.\n", - mdname(mddev)); - else { - printk(KERN_ERR "raid6: cannot start dirty degraded array" - " for %s\n", mdname(mddev)); - goto abort; - } - } - - { - mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6"); - if (!mddev->thread) { - printk(KERN_ERR - "raid6: couldn't allocate thread for %s\n", - mdname(mddev)); - goto abort; - } - } - - memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + - conf->raid_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024; - if (grow_stripes(conf, conf->max_nr_stripes)) { - printk(KERN_ERR - "raid6: couldn't allocate %dkB for buffers\n", memory); - shrink_stripes(conf); - md_unregister_thread(mddev->thread); - goto abort; - } else - printk(KERN_INFO "raid6: allocated %dkB for %s\n", - memory, mdname(mddev)); - - if (mddev->degraded == 0) - printk(KERN_INFO "raid6: raid level %d set %s active with %d out of %d" - " devices, algorithm %d\n", conf->level, mdname(mddev), - mddev->raid_disks-mddev->degraded, mddev->raid_disks, - conf->algorithm); - else - printk(KERN_ALERT "raid6: raid level %d set %s active with %d" - " out of %d devices, algorithm %d\n", conf->level, - mdname(mddev), mddev->raid_disks - mddev->degraded, - mddev->raid_disks, conf->algorithm); - - print_raid6_conf(conf); - - /* read-ahead size must cover two whole stripes, which is - * 2 * (n-2) * chunksize where 'n' is the number of raid devices - */ - { - int stripe = (mddev->raid_disks-2) * mddev->chunk_size - / PAGE_SIZE; - if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe) - mddev->queue->backing_dev_info.ra_pages = 2 * stripe; - } - - /* Ok, everything is just fine now */ - sysfs_create_group(&mddev->kobj, &raid6_attrs_group); - - mddev->array_size = mddev->size * (mddev->raid_disks - 2); - - mddev->queue->unplug_fn = raid6_unplug_device; - mddev->queue->issue_flush_fn = raid6_issue_flush; - return 0; -abort: - if (conf) { - print_raid6_conf(conf); - safe_put_page(conf->spare_page); - kfree(conf->stripe_hashtbl); - kfree(conf->disks); - kfree(conf); - } - mddev->private = NULL; - printk(KERN_ALERT "raid6: failed to run raid set %s\n", mdname(mddev)); - return -EIO; -} - - - -static int stop (mddev_t *mddev) -{ - raid6_conf_t *conf = (raid6_conf_t *) mddev->private; - - md_unregister_thread(mddev->thread); - mddev->thread = NULL; - shrink_stripes(conf); - kfree(conf->stripe_hashtbl); - blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ - sysfs_remove_group(&mddev->kobj, &raid6_attrs_group); - kfree(conf); - mddev->private = NULL; - return 0; -} - -#if RAID6_DUMPSTATE -static void print_sh (struct seq_file *seq, struct stripe_head *sh) -{ - int i; - - seq_printf(seq, "sh %llu, pd_idx %d, state %ld.\n", - (unsigned long long)sh->sector, sh->pd_idx, sh->state); - seq_printf(seq, "sh %llu, count %d.\n", - (unsigned long long)sh->sector, atomic_read(&sh->count)); - seq_printf(seq, "sh %llu, ", (unsigned long long)sh->sector); - for (i = 0; i < sh->raid_conf->raid_disks; i++) { - seq_printf(seq, "(cache%d: %p %ld) ", - i, sh->dev[i].page, sh->dev[i].flags); - } - seq_printf(seq, "\n"); -} - -static void printall (struct seq_file *seq, raid6_conf_t *conf) -{ - struct stripe_head *sh; - struct hlist_node *hn; - int i; - - spin_lock_irq(&conf->device_lock); - for (i = 0; i < NR_HASH; i++) { - sh = conf->stripe_hashtbl[i]; - hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) { - if (sh->raid_conf != conf) - continue; - print_sh(seq, sh); - } - } - spin_unlock_irq(&conf->device_lock); -} -#endif - -static void status (struct seq_file *seq, mddev_t *mddev) -{ - raid6_conf_t *conf = (raid6_conf_t *) mddev->private; - int i; - - seq_printf (seq, " level %d, %dk chunk, algorithm %d", mddev->level, mddev->chunk_size >> 10, mddev->layout); - seq_printf (seq, " [%d/%d] [", conf->raid_disks, conf->working_disks); - for (i = 0; i < conf->raid_disks; i++) - seq_printf (seq, "%s", - conf->disks[i].rdev && - test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_"); - seq_printf (seq, "]"); -#if RAID6_DUMPSTATE - seq_printf (seq, "\n"); - printall(seq, conf); -#endif -} - -static void print_raid6_conf (raid6_conf_t *conf) -{ - int i; - struct disk_info *tmp; - - printk("RAID6 conf printout:\n"); - if (!conf) { - printk("(conf==NULL)\n"); - return; - } - printk(" --- rd:%d wd:%d fd:%d\n", conf->raid_disks, - conf->working_disks, conf->failed_disks); - - for (i = 0; i < conf->raid_disks; i++) { - char b[BDEVNAME_SIZE]; - tmp = conf->disks + i; - if (tmp->rdev) - printk(" disk %d, o:%d, dev:%s\n", - i, !test_bit(Faulty, &tmp->rdev->flags), - bdevname(tmp->rdev->bdev,b)); - } -} - -static int raid6_spare_active(mddev_t *mddev) -{ - int i; - raid6_conf_t *conf = mddev->private; - struct disk_info *tmp; - - for (i = 0; i < conf->raid_disks; i++) { - tmp = conf->disks + i; - if (tmp->rdev - && !test_bit(Faulty, &tmp->rdev->flags) - && !test_bit(In_sync, &tmp->rdev->flags)) { - mddev->degraded--; - conf->failed_disks--; - conf->working_disks++; - set_bit(In_sync, &tmp->rdev->flags); - } - } - print_raid6_conf(conf); - return 0; -} - -static int raid6_remove_disk(mddev_t *mddev, int number) -{ - raid6_conf_t *conf = mddev->private; - int err = 0; - mdk_rdev_t *rdev; - struct disk_info *p = conf->disks + number; - - print_raid6_conf(conf); - rdev = p->rdev; - if (rdev) { - if (test_bit(In_sync, &rdev->flags) || - atomic_read(&rdev->nr_pending)) { - err = -EBUSY; - goto abort; - } - p->rdev = NULL; - synchronize_rcu(); - if (atomic_read(&rdev->nr_pending)) { - /* lost the race, try later */ - err = -EBUSY; - p->rdev = rdev; - } - } - -abort: - - print_raid6_conf(conf); - return err; -} - -static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) -{ - raid6_conf_t *conf = mddev->private; - int found = 0; - int disk; - struct disk_info *p; - - if (mddev->degraded > 2) - /* no point adding a device */ - return 0; - /* - * find the disk ... but prefer rdev->saved_raid_disk - * if possible. - */ - if (rdev->saved_raid_disk >= 0 && - conf->disks[rdev->saved_raid_disk].rdev == NULL) - disk = rdev->saved_raid_disk; - else - disk = 0; - for ( ; disk < mddev->raid_disks; disk++) - if ((p=conf->disks + disk)->rdev == NULL) { - clear_bit(In_sync, &rdev->flags); - rdev->raid_disk = disk; - found = 1; - if (rdev->saved_raid_disk != disk) - conf->fullsync = 1; - rcu_assign_pointer(p->rdev, rdev); - break; - } - print_raid6_conf(conf); - return found; -} - -static int raid6_resize(mddev_t *mddev, sector_t sectors) -{ - /* no resync is happening, and there is enough space - * on all devices, so we can resize. - * We need to make sure resync covers any new space. - * If the array is shrinking we should possibly wait until - * any io in the removed space completes, but it hardly seems - * worth it. - */ - sectors &= ~((sector_t)mddev->chunk_size/512 - 1); - mddev->array_size = (sectors * (mddev->raid_disks-2))>>1; - set_capacity(mddev->gendisk, mddev->array_size << 1); - mddev->changed = 1; - if (sectors/2 > mddev->size && mddev->recovery_cp == MaxSector) { - mddev->recovery_cp = mddev->size << 1; - set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - } - mddev->size = sectors /2; - mddev->resync_max_sectors = sectors; - return 0; -} - -static void raid6_quiesce(mddev_t *mddev, int state) -{ - raid6_conf_t *conf = mddev_to_conf(mddev); - - switch(state) { - case 1: /* stop all writes */ - spin_lock_irq(&conf->device_lock); - conf->quiesce = 1; - wait_event_lock_irq(conf->wait_for_stripe, - atomic_read(&conf->active_stripes) == 0, - conf->device_lock, /* nothing */); - spin_unlock_irq(&conf->device_lock); - break; - - case 0: /* re-enable writes */ - spin_lock_irq(&conf->device_lock); - conf->quiesce = 0; - wake_up(&conf->wait_for_stripe); - spin_unlock_irq(&conf->device_lock); - break; - } -} - -static struct mdk_personality raid6_personality = -{ - .name = "raid6", - .level = 6, - .owner = THIS_MODULE, - .make_request = make_request, - .run = run, - .stop = stop, - .status = status, - .error_handler = error, - .hot_add_disk = raid6_add_disk, - .hot_remove_disk= raid6_remove_disk, - .spare_active = raid6_spare_active, - .sync_request = sync_request, - .resize = raid6_resize, - .quiesce = raid6_quiesce, -}; - -static int __init raid6_init(void) -{ - int e; - - e = raid6_select_algo(); - if ( e ) - return e; - - return register_md_personality(&raid6_personality); -} - -static void raid6_exit (void) -{ - unregister_md_personality(&raid6_personality); -} - -module_init(raid6_init); -module_exit(raid6_exit); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("md-personality-8"); /* RAID6 */ -MODULE_ALIAS("md-raid6"); -MODULE_ALIAS("md-level-6"); diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 344d83a..ef52e6d 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -25,7 +25,7 @@ config VIDEO_DEV module will be called videodev. config VIDEO_V4L1 - boolean "Enable Video For Linux API 1 (DEPRECATED)" + bool "Enable Video For Linux API 1 (DEPRECATED)" depends on VIDEO_DEV select VIDEO_V4L1_COMPAT default y @@ -36,7 +36,7 @@ config VIDEO_V4L1 If you are unsure as to whether this is required, answer Y. config VIDEO_V4L1_COMPAT - boolean "Enable Video For Linux API 1 compatible Layer" + bool "Enable Video For Linux API 1 compatible Layer" depends on VIDEO_DEV default y ---help--- diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index 61b8961..8e74482 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile @@ -1,5 +1,5 @@ saa7146-objs := saa7146_i2c.o saa7146_core.o -saa7146_vv-objs := saa7146_vv_ksyms.o saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o +saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o ir-common-objs := ir-functions.o ir-keymaps.o obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c index 397cff8..8eaa88f 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/common/ir-functions.c @@ -269,4 +269,3 @@ EXPORT_SYMBOL_GPL(ir_decode_pulsedistanc * c-basic-offset: 8 * End: */ - diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index a294d5c..ca98d94 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -618,7 +618,7 @@ IR_KEYTAB_TYPE ir_codes_em_terratec[IR_K EXPORT_SYMBOL_GPL(ir_codes_em_terratec); -IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = { +IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = { [ 0x3a ] = KEY_0, [ 0x31 ] = KEY_1, [ 0x32 ] = KEY_2, @@ -670,7 +670,7 @@ IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[ [ 0x27 ] = KEY_RECORD, }; -EXPORT_SYMBOL_GPL(ir_codes_em_pinnacle_usb); +EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey); IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { [ 0x0f ] = KEY_0, @@ -1263,34 +1263,51 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTA [ 0x0f ] = KEY_9, [ 0x00 ] = KEY_POWER, - [ 0x02 ] = KEY_TUNER, /* TV/FM */ - [ 0x1e ] = KEY_VIDEO, + [ 0x1b ] = KEY_AUDIO, /* Audio Source */ + [ 0x02 ] = KEY_TUNER, /* TV/FM, not on Y0400052 */ + [ 0x1e ] = KEY_VIDEO, /* Video Source */ + [ 0x16 ] = KEY_INFO, /* Display information */ [ 0x04 ] = KEY_VOLUMEUP, [ 0x08 ] = KEY_VOLUMEDOWN, [ 0x0c ] = KEY_CHANNELUP, [ 0x10 ] = KEY_CHANNELDOWN, [ 0x03 ] = KEY_ZOOM, /* fullscreen */ - [ 0x1f ] = KEY_SUBTITLE, /* closed caption/teletext */ + [ 0x1f ] = KEY_TEXT, /* closed caption/teletext */ [ 0x20 ] = KEY_SLEEP, + [ 0x29 ] = KEY_CLEAR, /* boss key */ [ 0x14 ] = KEY_MUTE, [ 0x2b ] = KEY_RED, [ 0x2c ] = KEY_GREEN, [ 0x2d ] = KEY_YELLOW, [ 0x2e ] = KEY_BLUE, - [ 0x18 ] = KEY_KPPLUS, /* fine tune + */ - [ 0x19 ] = KEY_KPMINUS, /* fine tune - */ + [ 0x18 ] = KEY_KPPLUS, /* fine tune + , not on Y040052 */ + [ 0x19 ] = KEY_KPMINUS, /* fine tune - , not on Y040052 */ + [ 0x2a ] = KEY_MEDIA, /* PIP (Picture in picture */ [ 0x21 ] = KEY_DOT, [ 0x13 ] = KEY_ENTER, - [ 0x22 ] = KEY_BACK, + [ 0x11 ] = KEY_LAST, /* Recall (last channel */ + [ 0x22 ] = KEY_PREVIOUS, [ 0x23 ] = KEY_PLAYPAUSE, [ 0x24 ] = KEY_NEXT, + [ 0x25 ] = KEY_ARCHIVE, /* Time Shifting */ [ 0x26 ] = KEY_STOP, - [ 0x27 ] = KEY_RECORD + [ 0x27 ] = KEY_RECORD, + [ 0x28 ] = KEY_SAVE, /* Screenshot */ + [ 0x2f ] = KEY_MENU, + [ 0x30 ] = KEY_CANCEL, + [ 0x31 ] = KEY_CHANNEL, /* Channel Surf */ + [ 0x32 ] = KEY_SUBTITLE, + [ 0x33 ] = KEY_LANGUAGE, + [ 0x34 ] = KEY_REWIND, + [ 0x35 ] = KEY_FASTFORWARD, + [ 0x36 ] = KEY_TV, + [ 0x37 ] = KEY_RADIO, /* FM */ + [ 0x38 ] = KEY_DVD }; EXPORT_SYMBOL_GPL(ir_codes_winfast); -IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { +IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = { [ 0x59 ] = KEY_MUTE, [ 0x4a ] = KEY_POWER, @@ -1348,7 +1365,7 @@ IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYT [ 0x0a ] = KEY_BACKSPACE, }; -EXPORT_SYMBOL_GPL(ir_codes_pinnacle); +EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color); /* Hauppauge: the newer, gray remotes (seems there are multiple * slightly different versions), shipped with cx88+ivtv cards. @@ -1413,3 +1430,46 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); +IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { + [ 0x1d ] = KEY_SWITCHVIDEOMODE, /* switch inputs */ + [ 0x2a ] = KEY_FRONT, + + [ 0x3e ] = KEY_1, + [ 0x02 ] = KEY_2, + [ 0x06 ] = KEY_3, + [ 0x0a ] = KEY_4, + [ 0x0e ] = KEY_5, + [ 0x12 ] = KEY_6, + [ 0x16 ] = KEY_7, + [ 0x1a ] = KEY_8, + [ 0x1e ] = KEY_9, + [ 0x3a ] = KEY_0, + [ 0x22 ] = KEY_NUMLOCK, /* -/-- */ + [ 0x20 ] = KEY_REFRESH, + + [ 0x03 ] = KEY_BRIGHTNESSDOWN, + [ 0x28 ] = KEY_AUDIO, + [ 0x3c ] = KEY_UP, + [ 0x3f ] = KEY_LEFT, + [ 0x2e ] = KEY_MUTE, + [ 0x3b ] = KEY_RIGHT, + [ 0x00 ] = KEY_DOWN, + [ 0x07 ] = KEY_BRIGHTNESSUP, + [ 0x2c ] = KEY_TEXT, + + [ 0x37 ] = KEY_RECORD, + [ 0x17 ] = KEY_PLAY, + [ 0x13 ] = KEY_PAUSE, + [ 0x26 ] = KEY_STOP, + [ 0x18 ] = KEY_FASTFORWARD, + [ 0x14 ] = KEY_REWIND, + [ 0x33 ] = KEY_ZOOM, + [ 0x32 ] = KEY_KEYBOARD, + [ 0x30 ] = KEY_GOTO, /* Pointing arrow */ + [ 0x36 ] = KEY_MACRO, /* Maximize/Minimize (yellow) */ + [ 0x0b ] = KEY_RADIO, + [ 0x10 ] = KEY_POWER, + +}; + +EXPORT_SYMBOL_GPL(ir_codes_npgtech); diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 523ab38..0027acc 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -501,6 +501,7 @@ int saa7146_vv_init(struct saa7146_dev* return 0; } +EXPORT_SYMBOL_GPL(saa7146_vv_init); int saa7146_vv_release(struct saa7146_dev* dev) { @@ -515,6 +516,7 @@ int saa7146_vv_release(struct saa7146_de return 0; } +EXPORT_SYMBOL_GPL(saa7146_vv_release); int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, char *name, int type) @@ -553,6 +555,7 @@ int saa7146_register_device(struct video *vid = vfd; return 0; } +EXPORT_SYMBOL_GPL(saa7146_register_device); int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev) { @@ -571,6 +574,7 @@ int saa7146_unregister_device(struct vid return 0; } +EXPORT_SYMBOL_GPL(saa7146_unregister_device); static int __init saa7146_vv_init_module(void) { diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c index 33bec8a..2092e6c 100644 --- a/drivers/media/common/saa7146_hlp.c +++ b/drivers/media/common/saa7146_hlp.c @@ -641,6 +641,7 @@ void saa7146_set_hps_source_and_sync(str vv->current_hps_source = source; vv->current_hps_sync = sync; } +EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync); int saa7146_enable_overlay(struct saa7146_fh *fh) { diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index e7079d1..8393d47 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -318,6 +318,7 @@ int saa7146_start_preview(struct saa7146 return 0; } +EXPORT_SYMBOL_GPL(saa7146_start_preview); int saa7146_stop_preview(struct saa7146_fh *fh) { @@ -352,6 +353,7 @@ int saa7146_stop_preview(struct saa7146_ return 0; } +EXPORT_SYMBOL_GPL(saa7146_stop_preview); static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) { diff --git a/drivers/media/common/saa7146_vv_ksyms.c b/drivers/media/common/saa7146_vv_ksyms.c deleted file mode 100644 index 62226eb..0000000 --- a/drivers/media/common/saa7146_vv_ksyms.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -EXPORT_SYMBOL_GPL(saa7146_start_preview); -EXPORT_SYMBOL_GPL(saa7146_stop_preview); - -EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync); -EXPORT_SYMBOL_GPL(saa7146_register_device); -EXPORT_SYMBOL_GPL(saa7146_unregister_device); - -EXPORT_SYMBOL_GPL(saa7146_vv_init); -EXPORT_SYMBOL_GPL(saa7146_vv_release); diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 9c7f122..3be87c7 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -14,6 +14,7 @@ #include "bcm3510.h" #include "stv0297.h" #include "mt312.h" #include "lgdt330x.h" +#include "lg_h06xf.h" #include "dvb-pll.h" /* lnb control */ @@ -166,11 +167,12 @@ static int samsung_tbmu24112_set_symbol_ return 0; } -static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) +static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { u8 buf[4]; u32 div; struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + struct flexcop_device *fc = fe->dvb->priv; div = params->frequency / 125; @@ -181,8 +183,11 @@ static int samsung_tbmu24112_pll_set(str if (params->frequency < 1500000) buf[3] |= 0x10; - if (i2c_transfer(i2c, &msg, 1) != 1) + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) { return -EIO; + } return 0; } @@ -241,7 +246,6 @@ static struct stv0299_config samsung_tbm .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 100, .set_symbol_rate = samsung_tbmu24112_set_symbol_rate, - .pll_set = samsung_tbmu24112_pll_set, }; /* dvb-t mt352 */ @@ -264,11 +268,14 @@ static int samsung_tdtc9251dh0_demod_ini return 0; } -static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) +static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len) { u32 div; unsigned char bs = 0; + if (buf_len < 5) + return -EINVAL; + #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */ div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; @@ -276,19 +283,18 @@ static int samsung_tdtc9251dh0_pll_set(s if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a; if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08; - pllbuf[0] = 0xc2; /* Note: non-linux standard PLL i2c address */ + pllbuf[0] = 0x61; pllbuf[1] = div >> 8; pllbuf[2] = div & 0xff; pllbuf[3] = 0xcc; pllbuf[4] = bs; - return 0; + return 5; } static struct mt352_config samsung_tdtc9251dh0_config = { .demod_address = 0x0f, .demod_init = samsung_tdtc9251dh0_demod_init, - .pll_set = samsung_tdtc9251dh0_pll_set, }; static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name) @@ -297,56 +303,21 @@ static int flexcop_fe_request_firmware(s return request_firmware(fw, name, fc->dev); } -static int lgdt3303_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) +static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct flexcop_device *fc = fe->dvb->priv; - u8 buf[4]; - struct i2c_msg msg = - { .addr = 0x61, .flags = 0, .buf = buf, .len = 4 }; - int err; - - dvb_pll_configure(&dvb_pll_tdvs_tua6034,buf, params->frequency, 0); - dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", - __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); - if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) { - printk(KERN_WARNING "lgdt3303: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - buf[0] = 0x86 | 0x18; - buf[1] = 0x50; - msg.len = 2; - if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) { - printk(KERN_WARNING "lgdt3303: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - return 0; + return lg_h06xf_pll_set(fe, &fc->i2c_adap, params); } static struct lgdt330x_config air2pc_atsc_hd5000_config = { .demod_address = 0x59, .demod_chip = LGDT3303, .serial_mpeg = 0x04, - .pll_set = lgdt3303_pll_set, .clock_polarity_flip = 1, }; static struct nxt200x_config samsung_tbmv_config = { .demod_address = 0x0a, - .pll_address = 0xc2, - .pll_desc = &dvb_pll_samsung_tbmv, }; static struct bcm3510_config air2pc_atsc_first_gen_config = { @@ -354,7 +325,7 @@ static struct bcm3510_config air2pc_atsc .request_firmware = flexcop_fe_request_firmware, }; -static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { u8 buf[4]; u32 div; @@ -371,6 +342,8 @@ static int skystar23_samsung_tbdu18132_p if (params->frequency < 1550000) buf[3] |= 0x02; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -379,9 +352,52 @@ static int skystar23_samsung_tbdu18132_p static struct mt312_config skystar23_samsung_tbdu18132_config = { .demod_address = 0x0e, - .pll_set = skystar23_samsung_tbdu18132_pll_set, }; +static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + struct flexcop_device *fc = fe->dvb->priv; + u8 buf[4]; + u16 div; + int ret; + +/* 62.5 kHz * 10 */ +#define REF_FREQ 625 +#define FREQ_OFFSET 36125 + + div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10) / REF_FREQ; // 4 MHz = 4000 KHz + + buf[0] = (u8)( div >> 8) & 0x7f; + buf[1] = (u8) div & 0xff; + +/* F(osc) = N * Reference Freq. (62.5 kHz) + * byte 2 : 0 N14 N13 N12 N11 N10 N9 N8 + * byte 3 : N7 N6 N5 N4 N3 N2 N1 N0 + * byte 4 : 1 * * AGD R3 R2 R1 R0 + * byte 5 : C1 * RE RTS BS4 BS3 BS2 BS1 + * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */ + buf[2] = 0x95; + +// Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5 +// 47 - 153 0 * 0 0 0 0 0 1 0x01 +// 153 - 430 0 * 0 0 0 0 1 0 0x02 +// 430 - 822 0 * 0 0 1 0 0 0 0x08 +// 822 - 862 1 * 0 0 1 0 0 0 0x88 + + if (fep->frequency <= 153000000) buf[3] = 0x01; + else if (fep->frequency <= 430000000) buf[3] = 0x02; + else if (fep->frequency <= 822000000) buf[3] = 0x08; + else buf[3] = 0x88; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]); + ret = fc->i2c_request(fc,FC_WRITE,FC_I2C_PORT_TUNER,0x61,buf[0],&buf[1],3); + deb_tuner("tuner write returned: %d\n",ret); + + return 0; +} static u8 alps_tdee4_stv0297_inittab[] = { 0x80, 0x01, @@ -490,7 +506,9 @@ int flexcop_frontend_init(struct flexcop /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */ if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) { - ops = fc->fe->ops; + ops = &fc->fe->ops; + + ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params; ops->set_voltage = flexcop_set_voltage; @@ -503,16 +521,19 @@ int flexcop_frontend_init(struct flexcop /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */ if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) { fc->dev_type = FC_AIR_DVB; + fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); } else /* try the air atsc 2nd generation (nxt2002) */ if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC2; + dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv); info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); } else /* try the air atsc 3nd generation (lgdt3303) */ if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC3; + fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); } else /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ @@ -523,11 +544,14 @@ int flexcop_frontend_init(struct flexcop /* try the cable dvb (stv0297) */ if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_CABLE; + fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address); } else /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) { - ops = fc->fe->ops; + ops = &fc->fe->ops; + + ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params; ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; ops->diseqc_send_burst = flexcop_diseqc_send_burst; @@ -547,7 +571,7 @@ int flexcop_frontend_init(struct flexcop } else { if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { err("frontend registration failed!"); - ops = fc->fe->ops; + ops = &fc->fe->ops; if (ops->release != NULL) ops->release(fc->fe); fc->fe = NULL; diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 9bc40bd..f040417 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c @@ -242,19 +242,16 @@ static int flexcop_pci_dma_init(struct f if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0) return ret; - if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) - goto dma1_free; + if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) { + flexcop_dma_free(&fc_pci->dma[0]); + return ret; + } flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1); flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2); fc_pci->init_state |= FC_PCI_DMA_INIT; - goto success; -dma1_free: - flexcop_dma_free(&fc_pci->dma[0]); - -success: return ret; } @@ -303,7 +300,7 @@ static int flexcop_pci_init(struct flexc spin_lock_init(&fc_pci->irq_lock); fc_pci->init_state |= FC_PCI_INIT; - goto success; + return ret; err_pci_iounmap: pci_iounmap(fc_pci->pdev, fc_pci->io_mem); @@ -312,8 +309,6 @@ err_pci_release_regions: pci_release_regions(fc_pci->pdev); err_pci_disable_device: pci_disable_device(fc_pci->pdev); - -success: return ret; } @@ -378,14 +373,14 @@ static int flexcop_pci_probe(struct pci_ INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci); - goto success; + return ret; + err_fc_exit: flexcop_device_exit(fc); err_pci_exit: flexcop_pci_exit(fc_pci); err_kfree: flexcop_device_kfree(fc); -success: return ret; } diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c index 06ec9ff..515954f 100644 --- a/drivers/media/dvb/b2c2/flexcop-usb.c +++ b/drivers/media/dvb/b2c2/flexcop-usb.c @@ -433,11 +433,10 @@ static int flexcop_usb_transfer_init(str flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS); flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1); - ret = 0; - goto success; + return 0; + urb_error: flexcop_usb_transfer_exit(fc_usb); -success: return ret; } @@ -515,15 +514,14 @@ static int flexcop_usb_probe(struct usb_ goto err_fc_exit; info("%s successfully initialized and connected.",DRIVER_NAME); - ret = 0; - goto success; + return 0; + err_fc_exit: flexcop_device_exit(fc); err_usb_exit: flexcop_usb_exit(fc_usb); err_kfree: flexcop_device_kfree(fc); -success: return ret; } diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c index 56ba524..29ec418 100644 --- a/drivers/media/dvb/b2c2/flexcop.c +++ b/drivers/media/dvb/b2c2/flexcop.c @@ -67,7 +67,7 @@ static int flexcop_dvb_stop_feed(struct static int flexcop_dvb_init(struct flexcop_device *fc) { int ret; - if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner)) < 0) { + if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) { err("error registering DVB adapter"); return ret; } @@ -116,7 +116,7 @@ static int flexcop_dvb_init(struct flexc dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx); fc->init_state |= FC_STATE_DVB_INIT; - goto success; + return 0; err_connect_frontend: fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend); @@ -129,9 +129,6 @@ err_dmx_dev: err_dmx: dvb_unregister_adapter(&fc->dvb_adapter); return ret; - -success: - return 0; } static void flexcop_dvb_exit(struct flexcop_device *fc) @@ -279,11 +276,10 @@ int flexcop_device_initialize(struct fle flexcop_device_name(fc,"initialization of","complete"); - ret = 0; - goto success; + return 0; + error: flexcop_device_exit(fc); -success: return ret; } EXPORT_SYMBOL(flexcop_device_initialize); diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index 5500f8a..761fa6e 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -63,8 +63,6 @@ MODULE_PARM_DESC(debug, "Turn on/off deb int bt878_num; struct bt878 bt878[BT878_MAX]; -EXPORT_SYMBOL(bt878_debug); -EXPORT_SYMBOL(bt878_verbose); EXPORT_SYMBOL(bt878_num); EXPORT_SYMBOL(bt878); @@ -393,7 +391,9 @@ static struct cards card_list[] __devini { 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" }, { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, - { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, + { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV" }, + { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini" }, + { 0, -1, NULL } }; @@ -417,6 +417,11 @@ #endif printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n", bt878_num); + if (bt878_num >= BT878_MAX) { + printk(KERN_ERR "bt878: Too many devices inserted\n"); + result = -ENOMEM; + goto fail0; + } if (pci_enable_device(dev)) return -EIO; diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 1cfa5e5..d687a14 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -38,6 +38,10 @@ static unsigned int dst_addons; module_param(dst_addons, int, 0644); MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)"); +static unsigned int dst_algo; +module_param(dst_algo, int, 0644); +MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)"); + #define HAS_LOCK 1 #define ATTEMPT_TUNE 2 #define HAS_POWER 4 @@ -47,20 +51,24 @@ #define DST_NOTICE 1 #define DST_INFO 2 #define DST_DEBUG 3 -#define dprintk(x, y, z, format, arg...) do { \ - if (z) { \ - if ((x > DST_ERROR) && (x > y)) \ - printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg); \ - else if ((x > DST_NOTICE) && (x > y)) \ - printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg); \ - else if ((x > DST_INFO) && (x > y)) \ - printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg); \ - else if ((x > DST_DEBUG) && (x > y)) \ - printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg); \ - } else { \ - if (x > y) \ - printk(format, ##arg); \ - } \ +#define dprintk(x, y, z, format, arg...) do { \ + if (z) { \ + if ((x > DST_ERROR) && (x > y)) \ + printk(KERN_ERR "dst(%d) %s: " format "\n", \ + state->bt->nr, __func__ , ##arg); \ + else if ((x > DST_NOTICE) && (x > y)) \ + printk(KERN_NOTICE "dst(%d) %s: " format "\n", \ + state->bt->nr, __func__ , ##arg); \ + else if ((x > DST_INFO) && (x > y)) \ + printk(KERN_INFO "dst(%d) %s: " format "\n", \ + state->bt->nr, __func__ , ##arg); \ + else if ((x > DST_DEBUG) && (x > y)) \ + printk(KERN_DEBUG "dst(%d) %s: " format "\n", \ + state->bt->nr, __func__ , ##arg); \ + } else { \ + if (x > y) \ + printk(format, ##arg); \ + } \ } while(0) @@ -110,7 +118,7 @@ int dst_gpio_inb(struct dst_state *state *result = 0; if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) { - dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)\n", err); + dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)", err); return -EREMOTEIO; } *result = (u8) rd_packet.rd.value; @@ -363,6 +371,17 @@ static int dst_set_freq(struct dst_state state->tx_tuna[2] = (freq >> 16) & 0xff; state->tx_tuna[3] = (freq >> 8) & 0xff; state->tx_tuna[4] = (u8) freq; + } else if (state->dst_type == DST_TYPE_IS_ATSC) { + freq = freq / 1000; + if (freq < 51000 || freq > 858000) + return -EINVAL; + state->tx_tuna[2] = (freq >> 16) & 0xff; + state->tx_tuna[3] = (freq >> 8) & 0xff; + state->tx_tuna[4] = (u8) freq; + state->tx_tuna[5] = 0x00; /* ATSC */ + state->tx_tuna[6] = 0x00; + if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG) + state->tx_tuna[7] = 0x00; /* Digital */ } else return -EINVAL; @@ -447,29 +466,41 @@ static int dst_set_symbolrate(struct dst } dprintk(verbose, DST_INFO, 1, "set symrate %u", srate); srate /= 1000; - if (state->type_flags & DST_TYPE_HAS_SYMDIV) { - sval = srate; - sval <<= 20; - do_div(sval, 88000); - symcalc = (u32) sval; - dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc); - state->tx_tuna[5] = (u8) (symcalc >> 12); - state->tx_tuna[6] = (u8) (symcalc >> 4); - state->tx_tuna[7] = (u8) (symcalc << 4); - } else { - state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f; - state->tx_tuna[6] = (u8) (srate >> 8); - state->tx_tuna[7] = (u8) srate; - } - state->tx_tuna[8] &= ~0x20; - if (state->type_flags & DST_TYPE_HAS_OBS_REGS) { - if (srate > 8000) - state->tx_tuna[8] |= 0x20; + if (state->dst_type == DST_TYPE_IS_SAT) { + if (state->type_flags & DST_TYPE_HAS_SYMDIV) { + sval = srate; + sval <<= 20; + do_div(sval, 88000); + symcalc = (u32) sval; + dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc); + state->tx_tuna[5] = (u8) (symcalc >> 12); + state->tx_tuna[6] = (u8) (symcalc >> 4); + state->tx_tuna[7] = (u8) (symcalc << 4); + } else { + state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f; + state->tx_tuna[6] = (u8) (srate >> 8); + state->tx_tuna[7] = (u8) srate; + } + state->tx_tuna[8] &= ~0x20; + if (state->type_flags & DST_TYPE_HAS_OBS_REGS) { + if (srate > 8000) + state->tx_tuna[8] |= 0x20; + } + } else if (state->dst_type == DST_TYPE_IS_CABLE) { + dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name); + if (!strncmp(state->fw_name, "DCTNEW", 6)) { + state->tx_tuna[5] = (u8) (srate >> 8); + state->tx_tuna[6] = (u8) srate; + state->tx_tuna[7] = 0x00; + } else if (!strncmp(state->fw_name, "DCT-CI", 6)) { + state->tx_tuna[5] = 0x00; + state->tx_tuna[6] = (u8) (srate >> 8); + state->tx_tuna[7] = (u8) srate; + } } return 0; } - static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation) { if (state->dst_type != DST_TYPE_IS_CABLE) @@ -490,7 +521,10 @@ static int dst_set_modulation(struct dst state->tx_tuna[8] = 0x80; break; case QAM_256: - state->tx_tuna[8] = 0x00; + if (!strncmp(state->fw_name, "DCTNEW", 6)) + state->tx_tuna[8] = 0xff; + else if (!strncmp(state->fw_name, "DCT-CI", 6)) + state->tx_tuna[8] = 0x00; break; case QPSK: case QAM_AUTO: @@ -523,13 +557,19 @@ u8 dst_check_sum(u8 *buf, u32 len) } EXPORT_SYMBOL(dst_check_sum); -static void dst_type_flags_print(u32 type_flags) +static void dst_type_flags_print(struct dst_state *state) { + u32 type_flags = state->type_flags; + dprintk(verbose, DST_ERROR, 0, "DST type flags :"); - if (type_flags & DST_TYPE_HAS_NEWTUNE) - dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_NEWTUNE); + if (type_flags & DST_TYPE_HAS_TS188) + dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188); + if (type_flags & DST_TYPE_HAS_NEWTUNE_2) + dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2); if (type_flags & DST_TYPE_HAS_TS204) dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204); + if (type_flags & DST_TYPE_HAS_VLF) + dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF); if (type_flags & DST_TYPE_HAS_SYMDIV) dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV); if (type_flags & DST_TYPE_HAS_FW_1) @@ -542,7 +582,7 @@ static void dst_type_flags_print(u32 typ } -static int dst_type_print(u8 type) +static int dst_type_print(struct dst_state *state, u8 type) { char *otype; switch (type) { @@ -558,6 +598,10 @@ static int dst_type_print(u8 type) otype = "cable"; break; + case DST_TYPE_IS_ATSC: + otype = "atsc"; + break; + default: dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type); return -EINVAL; @@ -567,6 +611,127 @@ static int dst_type_print(u8 type) return 0; } +struct tuner_types tuner_list[] = { + { + .tuner_type = TUNER_TYPE_L64724, + .tuner_name = "L 64724", + .board_name = "UNKNOWN", + .fw_name = "UNKNOWN" + }, + + { + .tuner_type = TUNER_TYPE_STV0299, + .tuner_name = "STV 0299", + .board_name = "VP1020", + .fw_name = "DST-MOT" + }, + + { + .tuner_type = TUNER_TYPE_STV0299, + .tuner_name = "STV 0299", + .board_name = "VP1020", + .fw_name = "DST-03T" + }, + + { + .tuner_type = TUNER_TYPE_MB86A15, + .tuner_name = "MB 86A15", + .board_name = "VP1022", + .fw_name = "DST-03T" + }, + + { + .tuner_type = TUNER_TYPE_MB86A15, + .tuner_name = "MB 86A15", + .board_name = "VP1025", + .fw_name = "DST-03T" + }, + + { + .tuner_type = TUNER_TYPE_STV0299, + .tuner_name = "STV 0299", + .board_name = "VP1030", + .fw_name = "DST-CI" + }, + + { + .tuner_type = TUNER_TYPE_STV0299, + .tuner_name = "STV 0299", + .board_name = "VP1030", + .fw_name = "DSTMCI" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP2021", + .fw_name = "DCTNEW" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP2030", + .fw_name = "DCT-CI" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP2031", + .fw_name = "DCT-CI" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP2040", + .fw_name = "DCT-CI" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP3020", + .fw_name = "DTTFTA" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP3021", + .fw_name = "DTTFTA" + }, + + { + .tuner_type = TUNER_TYPE_TDA10046, + .tuner_name = "TDA10046", + .board_name = "VP3040", + .fw_name = "DTT-CI" + }, + + { + .tuner_type = TUNER_TYPE_UNKNOWN, + .tuner_name = "UNKNOWN", + .board_name = "VP3051", + .fw_name = "DTTNXT" + }, + + { + .tuner_type = TUNER_TYPE_NXT200x, + .tuner_name = "NXT200x", + .board_name = "VP3220", + .fw_name = "ATSCDI" + }, + + { + .tuner_type = TUNER_TYPE_NXT200x, + .tuner_name = "NXT200x", + .board_name = "VP3250", + .fw_name = "ATSCAD" + }, +}; + /* Known cards list Satellite @@ -608,7 +773,8 @@ static struct dst_types dst_tlist[] = { .offset = 0, .dst_type = DST_TYPE_IS_SAT, .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS, - .dst_feature = 0 + .dst_feature = 0, + .tuner_type = 0 }, /* obsolete */ { @@ -616,15 +782,17 @@ static struct dst_types dst_tlist[] = { .offset = 0, .dst_type = DST_TYPE_IS_SAT, .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1, - .dst_feature = 0 + .dst_feature = 0, + .tuner_type = 0 }, /* obsolete */ { .device_id = "DST-030", .offset = 0, .dst_type = DST_TYPE_IS_SAT, - .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1, - .dst_feature = 0 + .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1, + .dst_feature = 0, + .tuner_type = 0 }, /* obsolete */ { @@ -633,7 +801,8 @@ static struct dst_types dst_tlist[] = { .dst_type = DST_TYPE_IS_SAT, .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2, .dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5 - | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO + | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO, + .tuner_type = TUNER_TYPE_MULTI }, { @@ -641,57 +810,63 @@ static struct dst_types dst_tlist[] = { .offset = 0, .dst_type = DST_TYPE_IS_SAT, .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1, - .dst_feature = 0 + .dst_feature = 0, + .tuner_type = 0 }, /* obsolete */ { .device_id = "DST-CI", .offset = 1, .dst_type = DST_TYPE_IS_SAT, - .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1, - .dst_feature = DST_TYPE_HAS_CA + .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1, + .dst_feature = DST_TYPE_HAS_CA, + .tuner_type = 0 }, /* An OEM board */ { .device_id = "DSTMCI", .offset = 1, .dst_type = DST_TYPE_IS_SAT, - .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT, + .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF, .dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 - | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC + | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC, + .tuner_type = TUNER_TYPE_MULTI }, { .device_id = "DSTFCI", .offset = 1, .dst_type = DST_TYPE_IS_SAT, - .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1, - .dst_feature = 0 + .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1, + .dst_feature = 0, + .tuner_type = 0 }, /* unknown to vendor */ { .device_id = "DCT-CI", .offset = 1, .dst_type = DST_TYPE_IS_CABLE, - .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1 - | DST_TYPE_HAS_FW_2, - .dst_feature = DST_TYPE_HAS_CA + .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF, + .dst_feature = DST_TYPE_HAS_CA, + .tuner_type = 0 }, { .device_id = "DCTNEW", .offset = 1, .dst_type = DST_TYPE_IS_CABLE, - .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD, - .dst_feature = 0 + .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE, + .dst_feature = 0, + .tuner_type = 0 }, { .device_id = "DTT-CI", .offset = 1, .dst_type = DST_TYPE_IS_TERR, - .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE, - .dst_feature = DST_TYPE_HAS_CA + .type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF, + .dst_feature = DST_TYPE_HAS_CA, + .tuner_type = 0 }, { @@ -699,7 +874,8 @@ static struct dst_types dst_tlist[] = { .offset = 1, .dst_type = DST_TYPE_IS_TERR, .type_flags = DST_TYPE_HAS_FW_2, - .dst_feature = 0 + .dst_feature = 0, + .tuner_type = 0 }, { @@ -707,7 +883,8 @@ static struct dst_types dst_tlist[] = { .offset = 1, .dst_type = DST_TYPE_IS_TERR, .type_flags = DST_TYPE_HAS_FW_2, - .dst_feature = DST_TYPE_HAS_ANALOG + .dst_feature = DST_TYPE_HAS_ANALOG, + .tuner_type = 0 }, { @@ -715,15 +892,17 @@ static struct dst_types dst_tlist[] = { .offset = 1, .dst_type = DST_TYPE_IS_ATSC, .type_flags = DST_TYPE_HAS_FW_2, - .dst_feature = 0 + .dst_feature = 0, + .tuner_type = 0 }, { .device_id = "ATSCAD", .offset = 1, .dst_type = DST_TYPE_IS_ATSC, - .type_flags = DST_TYPE_HAS_FW_2, - .dst_feature = 0 + .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD, + .dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG, + .tuner_type = 0 }, { } @@ -768,6 +947,9 @@ static int dst_fw_ver(struct dst_state * static int dst_card_type(struct dst_state *state) { + int j; + struct tuner_types *p_tuner_list = NULL; + u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; get_type[7] = dst_check_sum(get_type, 7); if (dst_command(state, get_type, 8) < 0) { @@ -775,9 +957,17 @@ static int dst_card_type(struct dst_stat return -1; } memset(&state->card_info, '\0', 8); - memcpy(&state->card_info, &state->rxbuffer, 8); + memcpy(&state->card_info, &state->rxbuffer, 7); dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]); + for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) { + if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) { + state->tuner_type = p_tuner_list->tuner_type; + dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]", + p_tuner_list->tuner_name, p_tuner_list->tuner_type); + } + } + return 0; } @@ -790,12 +980,64 @@ static int dst_get_vendor(struct dst_sta return -1; } memset(&state->vendor, '\0', 8); - memcpy(&state->vendor, &state->rxbuffer, 8); + memcpy(&state->vendor, &state->rxbuffer, 7); dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]); return 0; } +static void debug_dst_buffer(struct dst_state *state) +{ + int i; + + if (verbose > 2) { + printk("%s: [", __func__); + for (i = 0; i < 8; i++) + printk(" %02x", state->rxbuffer[i]); + printk("]\n"); + } +} + +static int dst_check_stv0299(struct dst_state *state) +{ + u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + check_stv0299[7] = dst_check_sum(check_stv0299, 7); + if (dst_command(state, check_stv0299, 8) < 0) { + dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed"); + return -1; + } + debug_dst_buffer(state); + + if (memcmp(&check_stv0299, &state->rxbuffer, 8)) { + dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM"); + state->tuner_type = TUNER_TYPE_STV0299; + return 0; + } + + return -1; +} + +static int dst_check_mb86a15(struct dst_state *state) +{ + u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + check_mb86a15[7] = dst_check_sum(check_mb86a15, 7); + if (dst_command(state, check_mb86a15, 8) < 0) { + dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed"); + return -1; + } + debug_dst_buffer(state); + + if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) { + dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM"); + state->tuner_type = TUNER_TYPE_MB86A15; + return 0; + } + + return -1; +} + static int dst_get_tuner_info(struct dst_state *state) { u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -803,60 +1045,59 @@ static int dst_get_tuner_info(struct dst get_tuner_1[7] = dst_check_sum(get_tuner_1, 7); get_tuner_2[7] = dst_check_sum(get_tuner_2, 7); + dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE"); if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { - if (dst_command(state, get_tuner_2, 8) < 0) { - dprintk(verbose, DST_INFO, 1, "Unsupported Command"); - return -1; + if (dst_command(state, get_tuner_1, 8) < 0) { + dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported"); + goto force; } } else { - if (dst_command(state, get_tuner_1, 8) < 0) { - dprintk(verbose, DST_INFO, 1, "Unsupported Command"); - return -1; + if (dst_command(state, get_tuner_2, 8) < 0) { + dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported"); + goto force; } } memset(&state->board_info, '\0', 8); memcpy(&state->board_info, &state->rxbuffer, 8); if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { - if (state->board_info[1] == 0x0b) { - if (state->type_flags & DST_TYPE_HAS_TS204) - state->type_flags &= ~DST_TYPE_HAS_TS204; - state->type_flags |= DST_TYPE_HAS_NEWTUNE; - dprintk(verbose, DST_INFO, 1, "DST type has TS=188"); - } else { - if (state->type_flags & DST_TYPE_HAS_NEWTUNE) - state->type_flags &= ~DST_TYPE_HAS_NEWTUNE; - state->type_flags |= DST_TYPE_HAS_TS204; - dprintk(verbose, DST_INFO, 1, "DST type has TS=204"); - } - } else { - if (state->board_info[0] == 0xbc) { - if (state->type_flags & DST_TYPE_HAS_TS204) - state->type_flags &= ~DST_TYPE_HAS_TS204; - state->type_flags |= DST_TYPE_HAS_NEWTUNE; - dprintk(verbose, DST_INFO, 1, "DST type has TS=188, Daughterboard=[%d]", state->board_info[1]); - - } else if (state->board_info[0] == 0xcc) { - if (state->type_flags & DST_TYPE_HAS_NEWTUNE) - state->type_flags &= ~DST_TYPE_HAS_NEWTUNE; - state->type_flags |= DST_TYPE_HAS_TS204; - dprintk(verbose, DST_INFO, 1, "DST type has TS=204 Daughterboard=[%d]", state->board_info[1]); + dprintk(verbose, DST_ERROR, 1, "DST type has TS=188"); + } + if (state->board_info[0] == 0xbc) { + if (state->type_flags != DST_TYPE_IS_ATSC) + state->type_flags |= DST_TYPE_HAS_TS188; + else + state->type_flags |= DST_TYPE_HAS_NEWTUNE_2; + + if (state->board_info[1] == 0x01) { + state->dst_hw_cap |= DST_TYPE_HAS_DBOARD; + dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard"); } } return 0; +force: + if (!strncmp(state->fw_name, "DCT-CI", 6)) { + state->type_flags |= DST_TYPE_HAS_TS204; + dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name); + } + + return -1; } static int dst_get_device_id(struct dst_state *state) { u8 reply; - int i; - struct dst_types *p_dst_type; + int i, j; + struct dst_types *p_dst_type = NULL; + struct tuner_types *p_tuner_list = NULL; + u8 use_dst_type = 0; u32 use_type_flags = 0; static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}; + state->tuner_type = 0; device_type[7] = dst_check_sum(device_type, 7); if (write_dst(state, device_type, FIXED_COMM)) @@ -888,8 +1129,34 @@ static int dst_get_device_id(struct dst_ /* Card capabilities */ state->dst_hw_cap = p_dst_type->dst_feature; - dprintk(verbose, DST_ERROR, 1, "Recognise [%s]\n", p_dst_type->device_id); - + dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id); + strncpy(&state->fw_name[0], p_dst_type->device_id, 6); + /* Multiple tuners */ + if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) { + switch (use_dst_type) { + case DST_TYPE_IS_SAT: + /* STV0299 check */ + if (dst_check_stv0299(state) < 0) { + dprintk(verbose, DST_ERROR, 1, "Unsupported"); + state->tuner_type = TUNER_TYPE_MB86A15; + } + break; + default: + break; + } + if (dst_check_mb86a15(state) < 0) + dprintk(verbose, DST_ERROR, 1, "Unsupported"); + /* Single tuner */ + } else { + state->tuner_type = p_dst_type->tuner_type; + } + for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) { + if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) && + p_tuner_list->tuner_type == state->tuner_type) { + dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]", + p_dst_type->device_id, p_tuner_list->tuner_name); + } + } break; } } @@ -900,10 +1167,10 @@ static int dst_get_device_id(struct dst_ use_dst_type = DST_TYPE_IS_SAT; use_type_flags = DST_TYPE_HAS_SYMDIV; } - dst_type_print(use_dst_type); + dst_type_print(state, use_dst_type); state->type_flags = use_type_flags; state->dst_type = use_dst_type; - dst_type_flags_print(state->type_flags); + dst_type_flags_print(state); return 0; } @@ -911,15 +1178,15 @@ static int dst_get_device_id(struct dst_ static int dst_probe(struct dst_state *state) { mutex_init(&state->dst_mutex); - if ((rdc_8820_reset(state)) < 0) { - dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed."); - return -1; - } - if (dst_addons & DST_TYPE_HAS_CA) + if (dst_addons & DST_TYPE_HAS_CA) { + if ((rdc_8820_reset(state)) < 0) { + dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed."); + return -1; + } msleep(4000); - else + } else { msleep(100); - + } if ((dst_comm_init(state)) < 0) { dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed."); return -1; @@ -931,7 +1198,6 @@ static int dst_probe(struct dst_state *s } if (dst_get_mac(state) < 0) { dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command"); - return 0; } if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) { if (dst_get_tuner_info(state) < 0) @@ -1048,6 +1314,10 @@ static int dst_get_signal(struct dst_sta state->decode_lock = (state->rxbuffer[1]) ? 1 : 0; state->decode_strength = state->rxbuffer[4] << 8; state->decode_snr = state->rxbuffer[3] << 8; + } else if (state->dst_type == DST_TYPE_IS_ATSC) { + state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0; + state->decode_strength = state->rxbuffer[4] << 8; + state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3]; } state->cur_jiff = jiffies; } @@ -1078,8 +1348,9 @@ static int dst_get_tuna(struct dst_state state->diseq_flags &= ~(HAS_LOCK); if (!dst_wait_dst_ready(state, NO_DELAY)) return -EIO; - if (state->type_flags & DST_TYPE_HAS_NEWTUNE) - /* how to get variable length reply ???? */ + if ((state->type_flags & DST_TYPE_HAS_VLF) && + !(state->dst_type == DST_TYPE_IS_ATSC)) + retval = read_dst(state, state->rx_tuna, 10); else retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM); @@ -1087,7 +1358,10 @@ static int dst_get_tuna(struct dst_state dprintk(verbose, DST_DEBUG, 1, "read not successful"); return retval; } - if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { + if ((state->type_flags & DST_TYPE_HAS_VLF) && + !(state->dst_type == DST_TYPE_IS_CABLE) && + !(state->dst_type == DST_TYPE_IS_ATSC)) { + if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) { dprintk(verbose, DST_INFO, 1, "checksum failure ? "); return -EIO; @@ -1133,7 +1407,10 @@ static int dst_write_tuna(struct dvb_fro dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed."); goto error; } - if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { +// if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { + if ((state->type_flags & DST_TYPE_HAS_VLF) && + (!(state->dst_type == DST_TYPE_IS_ATSC))) { + state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9); retval = write_dst(state, &state->tx_tuna[0], 10); } else { @@ -1189,9 +1466,12 @@ static int dst_set_diseqc(struct dvb_fro if (state->dst_type != DST_TYPE_IS_SAT) return 0; - if (cmd->msg_len == 0 || cmd->msg_len > 4) + if (cmd->msg_len > 0 && cmd->msg_len < 5) + memcpy(&paket[3], cmd->msg, cmd->msg_len); + else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5) + memcpy(&paket[2], cmd->msg, cmd->msg_len); + else return -EINVAL; - memcpy(&paket[3], cmd->msg, cmd->msg_len); paket[7] = dst_check_sum(&paket[0], 7); dst_command(state, paket, 8); return 0; @@ -1287,8 +1567,9 @@ static int dst_init(struct dvb_frontend static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 }; static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; - static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; + static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; + static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; state->inversion = INVERSION_OFF; state->voltage = SEC_VOLTAGE_13; @@ -1298,11 +1579,13 @@ static int dst_init(struct dvb_frontend state->bandwidth = BANDWIDTH_7_MHZ; state->cur_jiff = jiffies; if (state->dst_type == DST_TYPE_IS_SAT) - memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204)); + memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204)); else if (state->dst_type == DST_TYPE_IS_TERR) - memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204)); + memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204)); else if (state->dst_type == DST_TYPE_IS_CABLE) - memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204)); + memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204)); + else if (state->dst_type == DST_TYPE_IS_ATSC) + memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner)); return 0; } @@ -1341,7 +1624,36 @@ static int dst_read_snr(struct dvb_front return 0; } -static int dst_set_frontend(struct dvb_frontend* fe, +static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) +{ + struct dst_state *state = fe->demodulator_priv; + + if (p != NULL) { + dst_set_freq(state, p->frequency); + dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency); + + if (state->dst_type == DST_TYPE_IS_SAT) { + if (state->type_flags & DST_TYPE_HAS_OBS_REGS) + dst_set_inversion(state, p->inversion); + dst_set_fec(state, p->u.qpsk.fec_inner); + dst_set_symbolrate(state, p->u.qpsk.symbol_rate); + dst_set_polarization(state); + dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate); + + } else if (state->dst_type == DST_TYPE_IS_TERR) + dst_set_bandwidth(state, p->u.ofdm.bandwidth); + else if (state->dst_type == DST_TYPE_IS_CABLE) { + dst_set_fec(state, p->u.qam.fec_inner); + dst_set_symbolrate(state, p->u.qam.symbol_rate); + dst_set_modulation(state, p->u.qam.modulation); + } + dst_write_tuna(fe); + } + + return 0; +} + +static int dst_tune_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* p, unsigned int mode_flags, int *delay, @@ -1378,6 +1690,11 @@ static int dst_set_frontend(struct dvb_f return 0; } +static int dst_get_tuning_algo(struct dvb_frontend *fe) +{ + return dst_algo; +} + static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { struct dst_state *state = fe->demodulator_priv; @@ -1408,6 +1725,7 @@ static void dst_release(struct dvb_front static struct dvb_frontend_ops dst_dvbt_ops; static struct dvb_frontend_ops dst_dvbs_ops; static struct dvb_frontend_ops dst_dvbc_ops; +static struct dvb_frontend_ops dst_atsc_ops; struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter) { @@ -1417,24 +1735,25 @@ struct dst_state *dst_attach(struct dst_ return NULL; } /* determine settings based on type */ + /* create dvb_frontend */ switch (state->dst_type) { case DST_TYPE_IS_TERR: - memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops)); + memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops)); break; case DST_TYPE_IS_CABLE: - memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops)); + memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops)); break; case DST_TYPE_IS_SAT: - memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops)); + memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops)); + break; + case DST_TYPE_IS_ATSC: + memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops)); break; default: dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist."); kfree(state); return NULL; } - - /* create dvb_frontend */ - state->frontend.ops = &state->ops; state->frontend.demodulator_priv = state; return state; /* Manu (DST is a card not a frontend) */ @@ -1455,8 +1774,10 @@ static struct dvb_frontend_ops dst_dvbt_ .release = dst_release, .init = dst_init, - .tune = dst_set_frontend, + .tune = dst_tune_frontend, + .set_frontend = dst_set_frontend, .get_frontend = dst_get_frontend, + .get_frontend_algo = dst_get_tuning_algo, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, .read_snr = dst_read_snr, @@ -1479,8 +1800,10 @@ static struct dvb_frontend_ops dst_dvbs_ .release = dst_release, .init = dst_init, - .tune = dst_set_frontend, + .tune = dst_tune_frontend, + .set_frontend = dst_set_frontend, .get_frontend = dst_get_frontend, + .get_frontend_algo = dst_get_tuning_algo, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, .read_snr = dst_read_snr, @@ -1506,13 +1829,38 @@ static struct dvb_frontend_ops dst_dvbc_ .release = dst_release, .init = dst_init, - .tune = dst_set_frontend, + .tune = dst_tune_frontend, + .set_frontend = dst_set_frontend, + .get_frontend = dst_get_frontend, + .get_frontend_algo = dst_get_tuning_algo, + .read_status = dst_read_status, + .read_signal_strength = dst_read_signal_strength, + .read_snr = dst_read_snr, +}; + +static struct dvb_frontend_ops dst_atsc_ops = { + .info = { + .name = "DST ATSC", + .type = FE_ATSC, + .frequency_stepsize = 62500, + .frequency_min = 510000000, + .frequency_max = 858000000, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB + }, + + .release = dst_release, + .init = dst_init, + .tune = dst_tune_frontend, + .set_frontend = dst_set_frontend, .get_frontend = dst_get_frontend, + .get_frontend_algo = dst_get_tuning_algo, .read_status = dst_read_status, .read_signal_strength = dst_read_signal_strength, .read_snr = dst_read_snr, }; -MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver"); +MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver"); MODULE_AUTHOR("Jamie Honan, Manu Abraham"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index f6b49a8..fa923b9 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -68,6 +68,13 @@ static int ca_set_pid(void) return -EOPNOTSUPP; } +static void put_command_and_length(u8 *data, int command, int length) +{ + data[0] = (command >> 16) & 0xff; + data[1] = (command >> 8) & 0xff; + data[2] = command & 0xff; + data[3] = length; +} static void put_checksum(u8 *check_string, int length) { @@ -124,15 +131,18 @@ static int dst_put_ci(struct dst_state * u8 dst_ca_comm_err = 0; while (dst_ca_comm_err < RETRIES) { - dst_comm_init(state); dprintk(verbose, DST_CA_NOTICE, 1, " Put Command"); if (dst_ci_command(state, data, ca_string, len, read)) { // If error dst_error_recovery(state); dst_ca_comm_err++; // work required here. + } else { + break; } - break; } + if(dst_ca_comm_err == RETRIES) + return -1; + return 0; } @@ -140,6 +150,7 @@ static int dst_put_ci(struct dst_state * static int ca_get_app_info(struct dst_state *state) { + int length, str_length; static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff}; put_checksum(&command[0], command[0]); @@ -154,6 +165,68 @@ static int ca_get_app_info(struct dst_st (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12])); dprintk(verbose, DST_CA_INFO, 1, " =================================================================================================="); + // Transform dst message to correct application_info message + length = state->messages[5]; + str_length = length - 6; + if (str_length < 0) { + str_length = 0; + dprintk(verbose, DST_CA_ERROR, 1, "Invalid string length returned in ca_get_app_info(). Recovering."); + } + + // First, the command and length fields + put_command_and_length(&state->messages[0], CA_APP_INFO, length); + + // Copy application_type, application_manufacturer and manufacturer_code + memcpy(&state->messages[4], &state->messages[7], 5); + + // Set string length and copy string + state->messages[9] = str_length; + memcpy(&state->messages[10], &state->messages[12], str_length); + + return 0; +} + +static int ca_get_ca_info(struct dst_state *state) +{ + int srcPtr, dstPtr, i, num_ids; + static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff}; + const int in_system_id_pos = 8, out_system_id_pos = 4, in_num_ids_pos = 7; + + put_checksum(&slot_command[0], slot_command[0]); + if ((dst_put_ci(state, slot_command, sizeof (slot_command), state->messages, GET_REPLY)) < 0) { + dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !"); + return -1; + } + dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !"); + + // Print raw data + dprintk(verbose, DST_CA_INFO, 0, " DST data = ["); + for (i = 0; i < state->messages[0] + 1; i++) { + dprintk(verbose, DST_CA_INFO, 0, " 0x%02x", state->messages[i]); + } + dprintk(verbose, DST_CA_INFO, 0, "]\n"); + + // Set the command and length of the output + num_ids = state->messages[in_num_ids_pos]; + if (num_ids >= 100) { + num_ids = 100; + dprintk(verbose, DST_CA_ERROR, 1, "Invalid number of ids (>100). Recovering."); + } + put_command_and_length(&state->messages[0], CA_INFO, num_ids * 2); + + dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = ["); + srcPtr = in_system_id_pos; + dstPtr = out_system_id_pos; + for(i = 0; i < num_ids; i++) { + dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x", state->messages[srcPtr + 0], state->messages[srcPtr + 1]); + // Append to output + state->messages[dstPtr + 0] = state->messages[srcPtr + 0]; + state->messages[dstPtr + 1] = state->messages[srcPtr + 1]; + srcPtr += 2; + dstPtr += 2; + } + dprintk(verbose, DST_CA_INFO, 0, "]\n"); + return 0; } @@ -174,7 +247,7 @@ static int ca_get_slot_caps(struct dst_s dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]); dprintk(verbose, DST_CA_INFO, 0, "===================================\n"); - for (i = 0; i < 8; i++) + for (i = 0; i < slot_cap[0] + 1; i++) dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]); dprintk(verbose, DST_CA_INFO, 0, "\n"); @@ -260,6 +333,11 @@ static int ca_get_message(struct dst_sta if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) ) return -EFAULT; break; + case CA_INFO: + memcpy(p_ca_message->msg, state->messages, 128); + if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) ) + return -EFAULT; + break; } } @@ -302,7 +380,7 @@ static int write_to_8820(struct dst_stat rdc_reset_state(state); return -1; } - dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes."); + dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success."); return 0; } @@ -340,6 +418,7 @@ static int debug_string(u8 *msg, u32 len return 0; } + static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query) { u32 length = 0; @@ -455,6 +534,16 @@ static int ca_send_message(struct dst_st } dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !"); break; + case CA_INFO_ENQUIRY: + dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information"); + + if ((ca_get_ca_info(state)) < 0) { + dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !"); + result = -1; + goto free_mem_and_exit; + } + dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !"); + break; } } free_mem_and_exit: @@ -473,18 +562,15 @@ static int dst_ca_ioctl(struct inode *in void __user *arg = (void __user *)ioctl_arg; int result = 0; - if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) { - dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); - return -ENOMEM; - } - if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) { + p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL); + p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL); + p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL); + if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) { dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); - return -ENOMEM; - } - if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) { - dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); - return -ENOMEM; + result = -ENOMEM; + goto free_mem_and_exit; } + /* We have now only the standard ioctl's, the driver is upposed to handle internals. */ switch (cmd) { case CA_SEND_MSG: @@ -582,7 +668,7 @@ static int dst_ca_release(struct inode * static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset) { - int bytes_read = 0; + ssize_t bytes_read = 0; dprintk(verbose, DST_CA_DEBUG, 1, " Device read."); diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h index 51d4e04..0677b04 100644 --- a/drivers/media/dvb/bt8xx/dst_common.h +++ b/drivers/media/dvb/bt8xx/dst_common.h @@ -42,7 +42,7 @@ #define DST_TYPE_IS_TERR 1 #define DST_TYPE_IS_CABLE 2 #define DST_TYPE_IS_ATSC 3 -#define DST_TYPE_HAS_NEWTUNE 1 +#define DST_TYPE_HAS_TS188 1 #define DST_TYPE_HAS_TS204 2 #define DST_TYPE_HAS_SYMDIV 4 #define DST_TYPE_HAS_FW_1 8 @@ -52,6 +52,9 @@ #define DST_TYPE_HAS_FW_BUILD 64 #define DST_TYPE_HAS_OBS_REGS 128 #define DST_TYPE_HAS_INC_COUNT 256 #define DST_TYPE_HAS_MULTI_FE 512 +#define DST_TYPE_HAS_NEWTUNE_2 1024 +#define DST_TYPE_HAS_DBOARD 2048 +#define DST_TYPE_HAS_VLF 4096 /* Card capability list */ @@ -64,6 +67,20 @@ #define DST_TYPE_HAS_CA 32 #define DST_TYPE_HAS_ANALOG 64 /* Analog inputs */ #define DST_TYPE_HAS_SESSION 128 +#define TUNER_TYPE_MULTI 1 +#define TUNER_TYPE_UNKNOWN 2 +/* DVB-S */ +#define TUNER_TYPE_L64724 4 +#define TUNER_TYPE_STV0299 8 +#define TUNER_TYPE_MB86A15 16 + +/* DVB-T */ +#define TUNER_TYPE_TDA10046 32 + +/* ATSC */ +#define TUNER_TYPE_NXT200x 64 + + #define RDC_8820_PIO_0_DISABLE 0 #define RDC_8820_PIO_0_ENABLE 1 #define RDC_8820_INT 2 @@ -84,8 +101,6 @@ struct dst_state { struct bt878* bt; - struct dvb_frontend_ops ops; - /* configuration settings */ const struct dst_config* config; @@ -121,8 +136,17 @@ struct dst_state { u8 card_info[8]; u8 vendor[8]; u8 board_info[8]; - + u32 tuner_type; + char *tuner_name; struct mutex dst_mutex; + u8 fw_name[8]; +}; + +struct tuner_types { + u32 tuner_type; + char *tuner_name; + char *board_name; + char *fw_name; }; struct dst_types { @@ -131,6 +155,7 @@ struct dst_types { u8 dst_type; u32 type_flags; u32 dst_feature; + u32 tuner_type; }; struct dst_config diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index ccc7b2e..b715b97 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -147,12 +147,15 @@ static int thomson_dtt7579_demod_init(st return 0; } -static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) +static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len) { u32 div; unsigned char bs = 0; unsigned char cp = 0; + if (buf_len < 5) + return -EINVAL; + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; if (params->frequency < 542000000) @@ -169,22 +172,25 @@ static int thomson_dtt7579_pll_set(struc else bs = 0x08; - pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address + pllbuf[0] = 0x60; pllbuf[1] = div >> 8; pllbuf[2] = div & 0xff; pllbuf[3] = cp; pllbuf[4] = bs; - return 0; + return 5; } static struct mt352_config thomson_dtt7579_config = { .demod_address = 0x0f, .demod_init = thomson_dtt7579_demod_init, - .pll_set = thomson_dtt7579_pll_set, }; -static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static struct zl10353_config thomson_dtt7579_zl10353_config = { + .demod_address = 0x0f, +}; + +static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { u32 freq = params->frequency; @@ -237,7 +243,7 @@ static int cx24108_pll_set(struct dvb_fr return 0; } -static int pinnsat_pll_init(struct dvb_frontend* fe) +static int pinnsat_tuner_init(struct dvb_frontend* fe) { struct dvb_bt8xx_card *card = fe->dvb->priv; @@ -247,7 +253,7 @@ static int pinnsat_pll_init(struct dvb_f return 0; } -static int pinnsat_pll_sleep(struct dvb_frontend* fe) +static int pinnsat_tuner_sleep(struct dvb_frontend* fe) { struct dvb_bt8xx_card *card = fe->dvb->priv; @@ -258,12 +264,9 @@ static int pinnsat_pll_sleep(struct dvb_ static struct cx24110_config pctvsat_config = { .demod_address = 0x55, - .pll_init = pinnsat_pll_init, - .pll_set = cx24108_pll_set, - .pll_sleep = pinnsat_pll_sleep, }; -static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; u8 cfg, cpump, band_select; @@ -297,6 +300,8 @@ static int microtune_mt7202dtf_pll_set(s data[2] = ((div >> 10) & 0x60) | cfg; data[3] = (cpump << 6) | band_select; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(card->i2c_adapter, &msg, 1); return (div * 166666 - 36000000); } @@ -310,7 +315,6 @@ static int microtune_mt7202dtf_request_f static struct sp887x_config microtune_mt7202dtf_config = { .demod_address = 0x70, - .pll_set = microtune_mt7202dtf_pll_set, .request_firmware = microtune_mt7202dtf_request_firmware, }; @@ -337,12 +341,14 @@ static int advbt771_samsung_tdtc9251dh0_ return 0; } -static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) +static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len) { u32 div; unsigned char bs = 0; unsigned char cp = 0; + if (buf_len < 5) return -EINVAL; + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; if (params->frequency < 150000000) @@ -383,19 +389,18 @@ static int advbt771_samsung_tdtc9251dh0_ else bs = 0x08; - pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address + pllbuf[0] = 0x61; pllbuf[1] = div >> 8; pllbuf[2] = div & 0xff; pllbuf[3] = cp; pllbuf[4] = bs; - return 0; + return 5; } static struct mt352_config advbt771_samsung_tdtc9251dh0_config = { .demod_address = 0x0f, .demod_init = advbt771_samsung_tdtc9251dh0_demod_init, - .pll_set = advbt771_samsung_tdtc9251dh0_pll_set, }; static struct dst_config dst_config = { @@ -455,7 +460,7 @@ static struct or51211_config or51211_con .sleep = or51211_sleep, }; -static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; u8 buf[4]; @@ -478,6 +483,8 @@ static int vp3021_alps_tded4_pll_set(str else return -EINVAL; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(card->i2c_adapter, &msg, 1); return 0; } @@ -485,7 +492,6 @@ static int vp3021_alps_tded4_pll_set(str static struct nxt6000_config vp3021_alps_tded4_config = { .demod_address = 0x0a, .clock_inversion = 1, - .pll_set = vp3021_alps_tded4_pll_set, }; static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe) @@ -506,14 +512,17 @@ static int digitv_alps_tded4_demod_init( return 0; } -static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) +static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len) { u32 div; struct dvb_ofdm_parameters *op = ¶ms->u.ofdm; + if (buf_len < 5) + return -EINVAL; + div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6; - pllbuf[0] = 0xc2; + pllbuf[0] = 0x61; pllbuf[1] = (div >> 8) & 0x7F; pllbuf[2] = div & 0xFF; pllbuf[3] = 0x85; @@ -530,7 +539,7 @@ static int digitv_alps_tded4_pll_set(str if (op->bandwidth == 8) pllbuf[4] |= 0x04; - return 0; + return 5; } static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt) @@ -557,43 +566,18 @@ static void digitv_alps_tded4_reset(stru static struct mt352_config digitv_alps_tded4_config = { .demod_address = 0x0a, .demod_init = digitv_alps_tded4_demod_init, - .pll_set = digitv_alps_tded4_pll_set, }; -static int tdvs_tua6034_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv; - u8 buf[4]; - struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; - int err; - - dvb_pll_configure(&dvb_pll_tdvs_tua6034, buf, params->frequency, 0); - dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", - __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); - if ((err = i2c_transfer(card->i2c_adapter, &msg, 1)) != 1) { - printk(KERN_WARNING "dvb-bt8xx: %s error " - "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, buf[0], buf[1], err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - /* Set the Auxiliary Byte. */ - buf[2] &= ~0x20; - buf[2] |= 0x18; - buf[3] = 0x50; - i2c_transfer(card->i2c_adapter, &msg, 1); - - return 0; + return lg_h06xf_pll_set(fe, card->i2c_adapter, params); } static struct lgdt330x_config tdvs_tua6034_config = { .demod_address = 0x0e, .demod_chip = LGDT3303, .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ - .pll_set = tdvs_tua6034_pll_set, }; static void lgdt330x_reset(struct dvb_bt8xx_card *bt) @@ -617,17 +601,25 @@ static void frontend_init(struct dvb_bt8 switch(type) { case BTTV_BOARD_DVICO_DVBT_LITE: card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter); + + if (card->fe == NULL) + card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config, + card->i2c_adapter); + if (card->fe != NULL) { - card->fe->ops->info.frequency_min = 174000000; - card->fe->ops->info.frequency_max = 862000000; + card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs; + card->fe->ops.info.frequency_min = 174000000; + card->fe->ops.info.frequency_max = 862000000; } break; case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE: lgdt330x_reset(card); card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter); - if (card->fe != NULL) + if (card->fe != NULL) { + card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params; dprintk ("dvb_bt8xx: lgdt330x detected\n"); + } break; case BTTV_BOARD_NEBULA_DIGITV: @@ -640,6 +632,7 @@ static void frontend_init(struct dvb_bt8 digitv_alps_tded4_reset(card); card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter); if (card->fe != NULL) { + card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params; dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n"); break; } @@ -648,19 +641,25 @@ static void frontend_init(struct dvb_bt8 digitv_alps_tded4_reset(card); card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter); - if (card->fe != NULL) + if (card->fe != NULL) { + card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs; dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n"); + } break; case BTTV_BOARD_AVDVBT_761: card->fe = sp887x_attach(µtune_mt7202dtf_config, card->i2c_adapter); + if (card->fe) { + card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params; + } break; case BTTV_BOARD_AVDVBT_771: card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter); if (card->fe != NULL) { - card->fe->ops->info.frequency_min = 174000000; - card->fe->ops->info.frequency_max = 862000000; + card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs; + card->fe->ops.info.frequency_min = 174000000; + card->fe->ops.info.frequency_max = 862000000; } break; @@ -687,6 +686,11 @@ static void frontend_init(struct dvb_bt8 case BTTV_BOARD_PINNACLESAT: card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter); + if (card->fe) { + card->fe->ops.tuner_ops.init = pinnsat_tuner_init; + card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep; + card->fe->ops.tuner_ops.set_params = cx24108_tuner_set_params; + } break; case BTTV_BOARD_PC_HDTV: @@ -703,8 +707,8 @@ static void frontend_init(struct dvb_bt8 else if (dvb_register_frontend(&card->dvb_adapter, card->fe)) { printk("dvb-bt8xx: Frontend registration failed!\n"); - if (card->fe->ops->release) - card->fe->ops->release(card->fe); + if (card->fe->ops.release) + card->fe->ops.release(card->fe); card->fe = NULL; } } @@ -713,7 +717,7 @@ static int __devinit dvb_bt8xx_load_card { int result; - if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) { + if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) { printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result); return result; } diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h index 00dd9fa..4745a90 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -37,6 +37,8 @@ #include "nxt6000.h" #include "cx24110.h" #include "or51211.h" #include "lgdt330x.h" +#include "lg_h06xf.h" +#include "zl10353.h" struct dvb_bt8xx_card { struct mutex lock; diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig index 6018fcd..b5cdd57 100644 --- a/drivers/media/dvb/cinergyT2/Kconfig +++ b/drivers/media/dvb/cinergyT2/Kconfig @@ -64,7 +64,7 @@ config DVB_CINERGYT2_QUERY_INTERVAL config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE bool "Register the onboard IR Remote Control Receiver as Input Device" depends on DVB_CINERGYT2_TUNING - default "yes" + default y help Enable this option if you want to use the onboard Infrared Remote Control Receiver as Linux-Input device. diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 9325d03..1b89536 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -544,15 +544,19 @@ static unsigned int cinergyt2_poll (stru { struct dvb_device *dvbdev = file->private_data; struct cinergyt2 *cinergyt2 = dvbdev->priv; + unsigned int mask = 0; if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) return -ERESTARTSYS; poll_wait(file, &cinergyt2->poll_wq, wait); + if (cinergyt2->pending_fe_events != 0) + mask |= (POLLIN | POLLRDNORM | POLLPRI); + mutex_unlock(&cinergyt2->sem); - return (POLLIN | POLLRDNORM | POLLPRI); + return mask; } @@ -902,7 +906,7 @@ static int cinergyt2_probe (struct usb_i return -ENOMEM; } - if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE)) < 0) { + if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) { kfree(cinergyt2); return err; } diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile index 7adb50c..1105465 100644 --- a/drivers/media/dvb/dvb-core/Makefile +++ b/drivers/media/dvb/dvb-core/Makefile @@ -2,8 +2,8 @@ # # Makefile for the kernel DVB device drivers. # -dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ - dvb_ca_en50221.o dvb_frontend.o \ - dvb_net.o dvb_ringbuffer.o +dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ + dvb_ca_en50221.o dvb_frontend.o \ + dvb_net.o dvb_ringbuffer.o dvb_math.o obj-$(CONFIG_DVB_CORE) += dvb-core.o diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 04578df..988499d 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -872,9 +872,6 @@ static int dvb_demux_do_ioctl(struct ino mutex_unlock(&dmxdevfilter->mutex); break; - case DMX_GET_EVENT: - break; - case DMX_GET_PES_PIDS: if (!dmxdev->demux->get_pes_pids) { ret = -EINVAL; diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index 00347a7..2a03bf5 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -1060,8 +1060,18 @@ static int dvb_ca_en50221_thread(void *d break; case DVB_CA_SLOTSTATE_VALIDATE: - if (dvb_ca_en50221_parse_attributes(ca, slot) - != 0) { + if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { + /* we need this extra check for annoying interfaces like the budget-av */ + if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && + (ca->pub->poll_slot_status)) { + int status = ca->pub->poll_slot_status(ca->pub, slot, 0); + if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + } + printk("dvb_ca adapter %d: Invalid PC card inserted :(\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; @@ -1108,6 +1118,17 @@ static int dvb_ca_en50221_thread(void *d case DVB_CA_SLOTSTATE_LINKINIT: if (dvb_ca_en50221_link_init(ca, slot) != 0) { + /* we need this extra check for annoying interfaces like the budget-av */ + if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && + (ca->pub->poll_slot_status)) { + int status = ca->pub->poll_slot_status(ca->pub, slot, 0); + if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + } + printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num); ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dvb_ca_en50221_thread_update_delay(ca); diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index 83ec5e0..fcff5ea 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -473,7 +473,7 @@ void dvb_dmx_swfilter_204(struct dvb_dem goto bailout; } memcpy(&demux->tsbuf[i], buf, j); - if ((demux->tsbuf[0] == 0x47) | (demux->tsbuf[0] == 0xB8)) { + if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) { memcpy(tmppack, demux->tsbuf, 188); if (tmppack[0] == 0xB8) tmppack[0] = 0x47; @@ -484,7 +484,7 @@ void dvb_dmx_swfilter_204(struct dvb_dem } while (p < count) { - if ((buf[p] == 0x47) | (buf[p] == 0xB8)) { + if ((buf[p] == 0x47) || (buf[p] == 0xB8)) { if (count - p >= 204) { memcpy(tmppack, &buf[p], 188); if (tmppack[0] == 0xB8) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index a051790..5e8bb41 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -56,7 +56,7 @@ MODULE_PARM_DESC(dvb_force_auto_inversio module_param(dvb_override_tune_delay, int, 0644); MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); module_param(dvb_powerdown_on_sleep, int, 0644); -MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volatage off on sleep (default)"); +MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)"); #define dprintk if (dvb_frontend_debug) printk @@ -72,6 +72,8 @@ #define FESTATE_WAITFORLOCK (FESTATE_TUN #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST) #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW) #define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW) + +#define FE_ALGO_HW 1 /* * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling. * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune. @@ -151,8 +153,8 @@ static void dvb_frontend_add_event(struc sizeof (struct dvb_frontend_parameters)); if (status & FE_HAS_LOCK) - if (fe->ops->get_frontend) - fe->ops->get_frontend(fe, &e->parameters); + if (fe->ops.get_frontend) + fe->ops.get_frontend(fe, &e->parameters); events->eventw = wp; @@ -211,10 +213,15 @@ static void dvb_frontend_init(struct dvb { dprintk ("DVB: initialising frontend %i (%s)...\n", fe->dvb->num, - fe->ops->info.name); - - if (fe->ops->init) - fe->ops->init(fe); + fe->ops.info.name); + + if (fe->ops.init) + fe->ops.init(fe); + if (fe->ops.tuner_ops.init) { + fe->ops.tuner_ops.init(fe); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } } void dvb_frontend_reinitialise(struct dvb_frontend *fe) @@ -259,7 +266,7 @@ static int dvb_frontend_swzigzag_autotun u32 original_frequency = fepriv->parameters.frequency; /* are we using autoinversion? */ - autoinversion = ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && + autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && (fepriv->parameters.inversion == INVERSION_AUTO)); /* setup parameters correctly */ @@ -329,8 +336,8 @@ static int dvb_frontend_swzigzag_autotun fepriv->parameters.frequency += fepriv->lnb_drift; if (autoinversion) fepriv->parameters.inversion = fepriv->inversion; - if (fe->ops->set_frontend) - fe->ops->set_frontend(fe, &fepriv->parameters); + if (fe->ops.set_frontend) + fe->ops.set_frontend(fe, &fepriv->parameters); fepriv->parameters.frequency = original_frequency; fepriv->parameters.inversion = original_inversion; @@ -354,8 +361,8 @@ static void dvb_frontend_swzigzag(struct /* in SCAN mode, we just set the frontend when asked and leave it alone */ if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { if (fepriv->state & FESTATE_RETUNE) { - if (fe->ops->set_frontend) - fe->ops->set_frontend(fe, &fepriv->parameters); + if (fe->ops.set_frontend) + fe->ops.set_frontend(fe, &fepriv->parameters); fepriv->state = FESTATE_TUNED; } fepriv->delay = 3*HZ; @@ -367,8 +374,8 @@ static void dvb_frontend_swzigzag(struct if (fepriv->state & FESTATE_RETUNE) { s = 0; } else { - if (fe->ops->read_status) - fe->ops->read_status(fe, &s); + if (fe->ops.read_status) + fe->ops.read_status(fe, &s); if (s != fepriv->status) { dvb_frontend_add_event(fe, s); fepriv->status = s; @@ -381,7 +388,7 @@ static void dvb_frontend_swzigzag(struct fepriv->state = FESTATE_TUNED; /* if we're tuned, then we have determined the correct inversion */ - if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && + if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && (fepriv->parameters.inversion == INVERSION_AUTO)) { fepriv->parameters.inversion = fepriv->inversion; } @@ -405,7 +412,7 @@ static void dvb_frontend_swzigzag(struct /* don't actually do anything if we're in the LOSTLOCK state, * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ if ((fepriv->state & FESTATE_LOSTLOCK) && - (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { + (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); return; } @@ -540,39 +547,45 @@ static int dvb_frontend_thread(void *dat if (fepriv->reinitialise) { dvb_frontend_init(fe); if (fepriv->tone != -1) { - fe->ops->set_tone(fe, fepriv->tone); + fe->ops.set_tone(fe, fepriv->tone); } if (fepriv->voltage != -1) { - fe->ops->set_voltage(fe, fepriv->voltage); + fe->ops.set_voltage(fe, fepriv->voltage); } fepriv->reinitialise = 0; } /* do an iteration of the tuning loop */ - if (fe->ops->tune) { - /* have we been asked to retune? */ - params = NULL; - if (fepriv->state & FESTATE_RETUNE) { - params = &fepriv->parameters; - fepriv->state = FESTATE_TUNED; - } + if (fe->ops.get_frontend_algo) { + if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) { + /* have we been asked to retune? */ + params = NULL; + if (fepriv->state & FESTATE_RETUNE) { + params = &fepriv->parameters; + fepriv->state = FESTATE_TUNED; + } - fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); - if (s != fepriv->status) { - dvb_frontend_add_event(fe, s); - fepriv->status = s; + fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); + if (s != fepriv->status) { + dvb_frontend_add_event(fe, s); + fepriv->status = s; + } } - } else { + } else dvb_frontend_swzigzag(fe); - } } if (dvb_shutdown_timeout) { if (dvb_powerdown_on_sleep) - if (fe->ops->set_voltage) - fe->ops->set_voltage(fe, SEC_VOLTAGE_OFF); - if (fe->ops->sleep) - fe->ops->sleep(fe); + if (fe->ops.set_voltage) + fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); + if (fe->ops.tuner_ops.sleep) { + fe->ops.tuner_ops.sleep(fe); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + if (fe->ops.sleep) + fe->ops.sleep(fe); } fepriv->thread_pid = 0; @@ -724,7 +737,7 @@ static int dvb_frontend_ioctl(struct ino switch (cmd) { case FE_GET_INFO: { struct dvb_frontend_info* info = parg; - memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info)); + memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't * do it, it is done for it. */ @@ -744,58 +757,58 @@ static int dvb_frontend_ioctl(struct ino break; } - if (fe->ops->read_status) - err = fe->ops->read_status(fe, status); + if (fe->ops.read_status) + err = fe->ops.read_status(fe, status); break; } case FE_READ_BER: - if (fe->ops->read_ber) - err = fe->ops->read_ber(fe, (__u32*) parg); + if (fe->ops.read_ber) + err = fe->ops.read_ber(fe, (__u32*) parg); break; case FE_READ_SIGNAL_STRENGTH: - if (fe->ops->read_signal_strength) - err = fe->ops->read_signal_strength(fe, (__u16*) parg); + if (fe->ops.read_signal_strength) + err = fe->ops.read_signal_strength(fe, (__u16*) parg); break; case FE_READ_SNR: - if (fe->ops->read_snr) - err = fe->ops->read_snr(fe, (__u16*) parg); + if (fe->ops.read_snr) + err = fe->ops.read_snr(fe, (__u16*) parg); break; case FE_READ_UNCORRECTED_BLOCKS: - if (fe->ops->read_ucblocks) - err = fe->ops->read_ucblocks(fe, (__u32*) parg); + if (fe->ops.read_ucblocks) + err = fe->ops.read_ucblocks(fe, (__u32*) parg); break; case FE_DISEQC_RESET_OVERLOAD: - if (fe->ops->diseqc_reset_overload) { - err = fe->ops->diseqc_reset_overload(fe); + if (fe->ops.diseqc_reset_overload) { + err = fe->ops.diseqc_reset_overload(fe); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } break; case FE_DISEQC_SEND_MASTER_CMD: - if (fe->ops->diseqc_send_master_cmd) { - err = fe->ops->diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg); + if (fe->ops.diseqc_send_master_cmd) { + err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } break; case FE_DISEQC_SEND_BURST: - if (fe->ops->diseqc_send_burst) { - err = fe->ops->diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg); + if (fe->ops.diseqc_send_burst) { + err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } break; case FE_SET_TONE: - if (fe->ops->set_tone) { - err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg); + if (fe->ops.set_tone) { + err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg); fepriv->tone = (fe_sec_tone_mode_t) parg; fepriv->state = FESTATE_DISEQC; fepriv->status = 0; @@ -803,8 +816,8 @@ static int dvb_frontend_ioctl(struct ino break; case FE_SET_VOLTAGE: - if (fe->ops->set_voltage) { - err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg); + if (fe->ops.set_voltage) { + err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg); fepriv->voltage = (fe_sec_voltage_t) parg; fepriv->state = FESTATE_DISEQC; fepriv->status = 0; @@ -812,11 +825,11 @@ static int dvb_frontend_ioctl(struct ino break; case FE_DISHNETWORK_SEND_LEGACY_CMD: - if (fe->ops->dishnetwork_send_legacy_command) { - err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned long) parg); + if (fe->ops.dishnetwork_send_legacy_command) { + err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg); fepriv->state = FESTATE_DISEQC; fepriv->status = 0; - } else if (fe->ops->set_voltage) { + } else if (fe->ops.set_voltage) { /* * NOTE: This is a fallback condition. Some frontends * (stv0299 for instance) take longer than 8msec to @@ -846,7 +859,7 @@ static int dvb_frontend_ioctl(struct ino /* before sending a command, initialize by sending * a 32ms 18V to the switch */ - fe->ops->set_voltage(fe, SEC_VOLTAGE_18); + fe->ops.set_voltage(fe, SEC_VOLTAGE_18); dvb_frontend_sleep_until(&nexttime, 32000); for (i = 0; i < 9; i++) { @@ -854,7 +867,7 @@ static int dvb_frontend_ioctl(struct ino do_gettimeofday(&tv[i + 1]); if ((cmd & 0x01) != last) { /* set voltage to (last ? 13V : 18V) */ - fe->ops->set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); + fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); last = (last) ? 0 : 1; } cmd = cmd >> 1; @@ -874,13 +887,13 @@ static int dvb_frontend_ioctl(struct ino break; case FE_DISEQC_RECV_SLAVE_REPLY: - if (fe->ops->diseqc_recv_slave_reply) - err = fe->ops->diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg); + if (fe->ops.diseqc_recv_slave_reply) + err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg); break; case FE_ENABLE_HIGH_LNB_VOLTAGE: - if (fe->ops->enable_high_lnb_voltage) - err = fe->ops->enable_high_lnb_voltage(fe, (long) parg); + if (fe->ops.enable_high_lnb_voltage) + err = fe->ops.enable_high_lnb_voltage(fe, (long) parg); break; case FE_SET_FRONTEND: { @@ -898,7 +911,7 @@ static int dvb_frontend_ioctl(struct ino fepriv->parameters.inversion = INVERSION_AUTO; fetunesettings.parameters.inversion = INVERSION_AUTO; } - if (fe->ops->info.type == FE_OFDM) { + if (fe->ops.info.type == FE_OFDM) { /* without hierachical coding code_rate_LP is irrelevant, * so we tolerate the otherwise invalid FEC_NONE setting */ if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE && @@ -907,13 +920,13 @@ static int dvb_frontend_ioctl(struct ino } /* get frontend-specific tuning settings */ - if (fe->ops->get_tune_settings && (fe->ops->get_tune_settings(fe, &fetunesettings) == 0)) { + if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) { fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000; fepriv->max_drift = fetunesettings.max_drift; fepriv->step_size = fetunesettings.step_size; } else { /* default values */ - switch(fe->ops->info.type) { + switch(fe->ops.info.type) { case FE_QPSK: fepriv->min_delay = HZ/20; fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000; @@ -928,11 +941,13 @@ static int dvb_frontend_ioctl(struct ino case FE_OFDM: fepriv->min_delay = HZ/20; - fepriv->step_size = fe->ops->info.frequency_stepsize * 2; - fepriv->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1; + fepriv->step_size = fe->ops.info.frequency_stepsize * 2; + fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; break; case FE_ATSC: - printk("dvb-core: FE_ATSC not handled yet.\n"); + fepriv->min_delay = HZ/20; + fepriv->step_size = 0; + fepriv->max_drift = 0; break; } } @@ -952,9 +967,9 @@ static int dvb_frontend_ioctl(struct ino break; case FE_GET_FRONTEND: - if (fe->ops->get_frontend) { + if (fe->ops.get_frontend) { memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters)); - err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg); + err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg); } break; @@ -1067,7 +1082,7 @@ int dvb_register_frontend(struct dvb_ada printk ("DVB: registering frontend %i (%s)...\n", fe->dvb->num, - fe->ops->info.name); + fe->ops.info.name); dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, fe, DVB_DEVICE_FRONTEND); @@ -1085,10 +1100,15 @@ int dvb_unregister_frontend(struct dvb_f mutex_lock(&frontend_mutex); dvb_unregister_device (fepriv->dvbdev); dvb_frontend_stop (fe); - if (fe->ops->release) - fe->ops->release(fe); + if (fe->ops.tuner_ops.release) { + fe->ops.tuner_ops.release(fe); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + if (fe->ops.release) + fe->ops.release(fe); else - printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name); + printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops.info.name); /* fe is invalid now */ kfree(fepriv); mutex_unlock(&frontend_mutex); diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 5926a3b..2887e2b 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -49,6 +49,44 @@ struct dvb_frontend_tune_settings { struct dvb_frontend; +struct dvb_tuner_info { + char name[128]; + + u32 frequency_min; + u32 frequency_max; + u32 frequency_step; + + u32 bandwidth_min; + u32 bandwidth_max; + u32 bandwidth_step; +}; + +struct dvb_tuner_ops { + + struct dvb_tuner_info info; + + int (*release)(struct dvb_frontend *fe); + int (*init)(struct dvb_frontend *fe); + int (*sleep)(struct dvb_frontend *fe); + + /** This is for simple PLLs - set all parameters in one go. */ + int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p); + + /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */ + int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len); + + int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency); + int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth); + +#define TUNER_STATUS_LOCKED 1 + int (*get_status)(struct dvb_frontend *fe, u32 *status); + + /** These are provided seperately from set_params in order to facilitate silicon + * tuners which require sophisticated tuning loops, controlling each parameter seperately. */ + int (*set_frequency)(struct dvb_frontend *fe, u32 frequency); + int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth); +}; + struct dvb_frontend_ops { struct dvb_frontend_info info; @@ -64,6 +102,8 @@ struct dvb_frontend_ops { unsigned int mode_flags, int *delay, fe_status_t *status); + /* get frontend tuning algorithm from the module */ + int (*get_frontend_algo)(struct dvb_frontend *fe); /* these two are only used for the swzigzag code */ int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); @@ -86,6 +126,8 @@ struct dvb_frontend_ops { int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg); int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd); int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable); + + struct dvb_tuner_ops tuner_ops; }; #define MAX_EVENT 8 @@ -100,9 +142,10 @@ struct dvb_fe_events { }; struct dvb_frontend { - struct dvb_frontend_ops* ops; + struct dvb_frontend_ops ops; struct dvb_adapter *dvb; void* demodulator_priv; + void* tuner_priv; void* frontend_priv; void* misc_priv; }; diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb/dvb-core/dvb_math.c new file mode 100644 index 0000000..beb7c93 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_math.c @@ -0,0 +1,145 @@ +/* + * dvb-math provides some complex fixed-point math + * operations shared between the dvb related stuff + * + * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "dvb_math.h" + +static const unsigned short logtable[256] = { + 0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7, + 0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508, + 0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6, + 0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37, + 0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f, + 0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41, + 0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1, + 0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142, + 0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68, + 0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355, + 0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c, + 0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490, + 0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3, + 0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507, + 0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe, + 0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca, + 0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c, + 0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7, + 0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c, + 0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c, + 0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a, + 0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065, + 0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730, + 0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc, + 0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469, + 0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9, + 0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c, + 0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765, + 0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83, + 0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387, + 0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973, + 0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47 +}; + +unsigned int intlog2(u32 value) +{ + /** + * returns: log2(value) * 2^24 + * wrong result if value = 0 (log2(0) is undefined) + */ + unsigned int msb; + unsigned int logentry; + unsigned int significand; + unsigned int interpolation; + + if (unlikely(value == 0)) { + WARN_ON(1); + return 0; + } + + /* first detect the msb (count begins at 0) */ + msb = fls(value) - 1; + + /** + * now we use a logtable after the following method: + * + * log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24 + * where x = msb and therefore 1 <= y < 2 + * first y is determined by shifting the value left + * so that msb is bit 31 + * 0x00231f56 -> 0x8C7D5800 + * the result is y * 2^31 -> "significand" + * then the highest 9 bits are used for a table lookup + * the highest bit is discarded because it's always set + * the highest nine bits in our example are 100011000 + * so we would use the entry 0x18 + */ + significand = value << (31 - msb); + logentry = (significand >> 23) & 0xff; + + /** + * last step we do is interpolation because of the + * limitations of the log table the error is that part of + * the significand which isn't used for lookup then we + * compute the ratio between the error and the next table entry + * and interpolate it between the log table entry used and the + * next one the biggest error possible is 0x7fffff + * (in our example it's 0x7D5800) + * needed value for next table entry is 0x800000 + * so the interpolation is + * (error / 0x800000) * (logtable_next - logtable_current) + * in the implementation the division is moved to the end for + * better accuracy there is also an overflow correction if + * logtable_next is 256 + */ + interpolation = ((significand & 0x7fffff) * + ((logtable[(logentry + 1) & 0xff] - + logtable[logentry]) & 0xffff)) >> 15; + + /* now we return the result */ + return ((msb << 24) + (logtable[logentry] << 8) + interpolation); +} +EXPORT_SYMBOL(intlog2); + +unsigned int intlog10(u32 value) +{ + /** + * returns: log10(value) * 2^24 + * wrong result if value = 0 (log10(0) is undefined) + */ + u64 log; + + if (unlikely(value == 0)) { + WARN_ON(1); + return 0; + } + + log = intlog2(value); + + /** + * we use the following method: + * log10(x) = log2(x) * log10(2) + */ + + return (log * 646456993) >> 31; +} +EXPORT_SYMBOL(intlog10); diff --git a/drivers/media/dvb/dvb-core/dvb_math.h b/drivers/media/dvb/dvb-core/dvb_math.h new file mode 100644 index 0000000..aecc867 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_math.h @@ -0,0 +1,58 @@ +/* + * dvb-math provides some complex fixed-point math + * operations shared between the dvb related stuff + * + * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DVB_MATH_H +#define __DVB_MATH_H + +#include + +/** + * computes log2 of a value; the result is shifted left by 24 bits + * + * to use rational values you can use the following method: + * intlog2(value) = intlog2(value * 2^x) - x * 2^24 + * + * example: intlog2(8) will give 3 << 24 = 3 * 2^24 + * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24 + * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24 + * + * @param value The value (must be != 0) + * @return log2(value) * 2^24 + */ +extern unsigned int intlog2(u32 value); + +/** + * computes log10 of a value; the result is shifted left by 24 bits + * + * to use rational values you can use the following method: + * intlog10(value) = intlog10(value * 10^x) - x * 2^24 + * + * example: intlog10(1000) will give 3 << 24 = 3 * 2^24 + * due to the implementation intlog10(1000) might be not exactly 3 * 2^24 + * + * look at intlog2 for similar examples + * + * @param value The value (must be != 0) + * @return log10(value) * 2^24 + */ +extern unsigned int intlog10(u32 value); + +#endif diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 2f0f358..8859ab7 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -12,7 +12,7 @@ * Hilmar Linder * and Wolfram Stering * - * ULE Decaps according to draft-ietf-ipdvb-ule-03.txt. + * ULE Decaps according to RFC 4326. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -42,6 +42,9 @@ * Bugfixes and robustness improvements. * Filtering on dest MAC addresses, if present (D-Bit = 0) * ULE_DEBUG compile-time option. + * Apr 2006: cp v3: Bugfixes and compliency with RFC 4326 (ULE) by + * Christian Praehauser , + * Paris Lodron University of Salzburg. */ /* @@ -49,9 +52,6 @@ * * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero. * - * TS_FEED callback is called once for every single TS cell although it is - * registered (in dvb_net_feed_start()) for 100 TS cells (used for dvb_net_ule()). - * */ #include @@ -89,6 +89,9 @@ #undef ULE_DEBUG #ifdef ULE_DEBUG +#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" +#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5] + #define isprint(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) static void hexdump( const unsigned char *buf, unsigned short len ) @@ -214,6 +217,8 @@ #define TS_AF_D 0x10 #define ULE_TEST 0 #define ULE_BRIDGED 1 +#define ULE_OPTEXTHDR_PADDING 0 + static int ule_test_sndu( struct dvb_net_priv *p ) { return -1; @@ -221,14 +226,28 @@ static int ule_test_sndu( struct dvb_net static int ule_bridged_sndu( struct dvb_net_priv *p ) { - /* BRIDGE SNDU handling sucks in draft-ietf-ipdvb-ule-03.txt. - * This has to be the last extension header, otherwise it won't work. - * Blame the authors! + struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr; + if(ntohs(hdr->h_proto) < 1536) { + int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data); + /* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */ + if(framelen != ntohs(hdr->h_proto)) { + return -1; + } + } + /* Note: + * From RFC4326: + * "A bridged SNDU is a Mandatory Extension Header of Type 1. + * It must be the final (or only) extension header specified in the header chain of a SNDU." + * The 'ule_bridged' flag will cause the extension header processing loop to terminate. */ p->ule_bridged = 1; return 0; } +static int ule_exthdr_padding(struct dvb_net_priv *p) +{ + return 0; +} /** Handle ULE extension headers. * Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding. @@ -242,7 +261,8 @@ static int handle_one_ule_extension( str { [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL, }; /* Table of optional extension header handlers. The header type is the index. */ - static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = { NULL, }; + static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = + { [0] = ule_exthdr_padding, [1] = NULL, }; int ext_len = 0; unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8; @@ -253,25 +273,31 @@ static int handle_one_ule_extension( str /* Mandatory extension header */ if (ule_mandatory_ext_handlers[htype]) { ext_len = ule_mandatory_ext_handlers[htype]( p ); - p->ule_next_hdr += ext_len; - if (! p->ule_bridged) { - p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr ); - p->ule_next_hdr += 2; - } else { - p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)) ); - /* This assures the extension handling loop will terminate. */ + if(ext_len >= 0) { + p->ule_next_hdr += ext_len; + if (!p->ule_bridged) { + p->ule_sndu_type = ntohs(*(unsigned short *)p->ule_next_hdr); + p->ule_next_hdr += 2; + } else { + p->ule_sndu_type = ntohs(*(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN))); + /* This assures the extension handling loop will terminate. */ + } } + // else: extension handler failed or SNDU should be discarded } else ext_len = -1; /* SNDU has to be discarded. */ } else { /* Optional extension header. Calculate the length. */ - ext_len = hlen << 2; + ext_len = hlen << 1; /* Process the optional extension header according to its type. */ if (ule_optional_ext_handlers[htype]) (void)ule_optional_ext_handlers[htype]( p ); p->ule_next_hdr += ext_len; - p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr ); - p->ule_next_hdr += 2; + p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr-2) ); + /* + * note: the length of the next header type is included in the + * length of THIS optional extension header + */ } return ext_len; @@ -284,8 +310,14 @@ static int handle_ule_extensions( struct p->ule_next_hdr = p->ule_skb->data; do { l = handle_one_ule_extension( p ); - if (l == -1) return -1; /* Stop extension header processing and discard SNDU. */ + if (l < 0) + return l; /* Stop extension header processing and discard SNDU. */ total_ext_len += l; +#ifdef ULE_DEBUG + dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, " + "l=%i, total_ext_len=%i\n", p->ule_next_hdr, + (int) p->ule_sndu_type, l, total_ext_len); +#endif } while (p->ule_sndu_type < 1536); @@ -355,8 +387,8 @@ #endif if (priv->ule_skb) { dev_kfree_skb( priv->ule_skb ); /* Prepare for next SNDU. */ - ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; - ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; + priv->stats.rx_errors++; + priv->stats.rx_frame_errors++; } reset_ule(priv); priv->need_pusi = 1; @@ -396,27 +428,25 @@ #endif } } - /* Check continuity counter. */ if (new_ts) { + /* Check continuity counter. */ if ((ts[3] & 0x0F) == priv->tscc) priv->tscc = (priv->tscc + 1) & 0x0F; else { /* TS discontinuity handling: */ printk(KERN_WARNING "%lu: TS discontinuity: got %#x, " - "exptected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc); + "expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc); /* Drop partly decoded SNDU, reset state, resync on PUSI. */ if (priv->ule_skb) { dev_kfree_skb( priv->ule_skb ); /* Prepare for next SNDU. */ // reset_ule(priv); moved to below. - ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; - ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; + priv->stats.rx_errors++; + priv->stats.rx_frame_errors++; } reset_ule(priv); /* skip to next PUSI. */ priv->need_pusi = 1; - ts += TS_SZ; - priv->ts_count++; continue; } /* If we still have an incomplete payload, but PUSI is @@ -425,7 +455,7 @@ #endif * cells (continuity counter wrap). */ if (ts[1] & TS_PUSI) { if (! priv->need_pusi) { - if (*from_where > 181) { + if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) { /* Pointer field is invalid. Drop this TS cell and any started ULE SNDU. */ printk(KERN_WARNING "%lu: Invalid pointer " "field: %u.\n", priv->ts_count, *from_where); @@ -438,8 +468,6 @@ #endif } reset_ule(priv); priv->need_pusi = 1; - ts += TS_SZ; - priv->ts_count++; continue; } /* Skip pointer field (we're processing a @@ -452,8 +480,8 @@ #endif if (priv->ule_sndu_remain > 183) { /* Current SNDU lacks more data than there could be available in the * current TS cell. */ - ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; - ((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++; + priv->stats.rx_errors++; + priv->stats.rx_length_errors++; printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but " "got PUSI (pf %d, ts_remain %d). Flushing incomplete payload.\n", priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain); @@ -492,9 +520,11 @@ #endif } else priv->ule_dbit = 0; - if (priv->ule_sndu_len > 32763) { + if (priv->ule_sndu_len < 5) { printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. " "Resyncing.\n", priv->ts_count, priv->ule_sndu_len); + priv->stats.rx_errors++; + priv->stats.rx_length_errors++; priv->ule_sndu_len = 0; priv->need_pusi = 1; new_ts = 1; @@ -608,58 +638,103 @@ #ifdef ULE_DEBUG ule_dump = 1; #endif - ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; - ((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++; + priv->stats.rx_errors++; + priv->stats.rx_crc_errors++; dev_kfree_skb(priv->ule_skb); } else { /* CRC32 verified OK. */ + u8 dest_addr[ETH_ALEN]; + static const u8 bc_addr[ETH_ALEN] = + { [ 0 ... ETH_ALEN-1] = 0xff }; + + /* CRC32 was OK. Remove it from skb. */ + priv->ule_skb->tail -= 4; + priv->ule_skb->len -= 4; + + if (!priv->ule_dbit) { + /* + * The destination MAC address is the + * next data in the skb. It comes + * before any extension headers. + * + * Check if the payload of this SNDU + * should be passed up the stack. + */ + register int drop = 0; + if (priv->rx_mode != RX_MODE_PROMISC) { + if (priv->ule_skb->data[0] & 0x01) { + /* multicast or broadcast */ + if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) { + /* multicast */ + if (priv->rx_mode == RX_MODE_MULTI) { + int i; + for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++) + ; + if (i == priv->multi_num) + drop = 1; + } else if (priv->rx_mode != RX_MODE_ALL_MULTI) + drop = 1; /* no broadcast; */ + /* else: all multicast mode: accept all multicast packets */ + } + /* else: broadcast */ + } + else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN)) + drop = 1; + /* else: destination address matches the MAC address of our receiver device */ + } + /* else: promiscious mode; pass everything up the stack */ + + if (drop) { +#ifdef ULE_DEBUG + dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n", + MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr)); +#endif + dev_kfree_skb(priv->ule_skb); + goto sndu_done; + } + else + { + memcpy(dest_addr, priv->ule_skb->data, ETH_ALEN); + skb_pull(priv->ule_skb, ETH_ALEN); + } + } + /* Handle ULE Extension Headers. */ if (priv->ule_sndu_type < 1536) { /* There is an extension header. Handle it accordingly. */ - int l = handle_ule_extensions( priv ); + int l = handle_ule_extensions(priv); if (l < 0) { /* Mandatory extension header unknown or TEST SNDU. Drop it. */ // printk( KERN_WARNING "Dropping SNDU, extension headers.\n" ); - dev_kfree_skb( priv->ule_skb ); + dev_kfree_skb(priv->ule_skb); goto sndu_done; } - skb_pull( priv->ule_skb, l ); + skb_pull(priv->ule_skb, l); } - /* CRC32 was OK. Remove it from skb. */ - priv->ule_skb->tail -= 4; - priv->ule_skb->len -= 4; - - /* Filter on receiver's destination MAC address, if present. */ - if (!priv->ule_dbit) { - /* The destination MAC address is the next data in the skb. */ - if (memcmp( priv->ule_skb->data, dev->dev_addr, ETH_ALEN )) { - /* MAC addresses don't match. Drop SNDU. */ - // printk( KERN_WARNING "Dropping SNDU, MAC address.\n" ); - dev_kfree_skb( priv->ule_skb ); - goto sndu_done; - } - if (! priv->ule_bridged) { - skb_push( priv->ule_skb, ETH_ALEN + 2 ); - ethh = (struct ethhdr *)priv->ule_skb->data; - memcpy( ethh->h_dest, ethh->h_source, ETH_ALEN ); - memset( ethh->h_source, 0, ETH_ALEN ); - ethh->h_proto = htons( priv->ule_sndu_type ); - } else { - /* Skip the Receiver destination MAC address. */ - skb_pull( priv->ule_skb, ETH_ALEN ); - } - } else { - if (! priv->ule_bridged) { - skb_push( priv->ule_skb, ETH_HLEN ); - ethh = (struct ethhdr *)priv->ule_skb->data; - memcpy( ethh->h_dest, dev->dev_addr, ETH_ALEN ); - memset( ethh->h_source, 0, ETH_ALEN ); - ethh->h_proto = htons( priv->ule_sndu_type ); - } else { - /* skb is in correct state; nothing to do. */ + /* + * Construct/assure correct ethernet header. + * Note: in bridged mode (priv->ule_bridged != + * 0) we already have the (original) ethernet + * header at the start of the payload (after + * optional dest. address and any extension + * headers). + */ + + if (!priv->ule_bridged) { + skb_push(priv->ule_skb, ETH_HLEN); + ethh = (struct ethhdr *)priv->ule_skb->data; + if (!priv->ule_dbit) { + /* dest_addr buffer is only valid if priv->ule_dbit == 0 */ + memcpy(ethh->h_dest, dest_addr, ETH_ALEN); + memset(ethh->h_source, 0, ETH_ALEN); } + else /* zeroize source and dest */ + memset( ethh, 0, ETH_ALEN*2 ); + + ethh->h_proto = htons(priv->ule_sndu_type); } + /* else: skb is in correct state; nothing to do. */ priv->ule_bridged = 0; /* Stuff into kernel's protocol stack. */ @@ -668,8 +743,8 @@ #endif * receive the packet anyhow. */ /* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) priv->ule_skb->pkt_type = PACKET_HOST; */ - ((struct dvb_net_priv *) dev->priv)->stats.rx_packets++; - ((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += priv->ule_skb->len; + priv->stats.rx_packets++; + priv->stats.rx_bytes += priv->ule_skb->len; netif_rx(priv->ule_skb); } sndu_done: @@ -944,7 +1019,7 @@ static int dvb_net_feed_start(struct net dprintk("%s: start filtering\n", __FUNCTION__); priv->secfeed->start_filtering(priv->secfeed); } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) { - struct timespec timeout = { 0, 30000000 }; // 30 msec + struct timespec timeout = { 0, 10000000 }; // 10 msec /* we have payloads encapsulated in TS */ dprintk("%s: alloc tsfeed\n", __FUNCTION__); @@ -956,10 +1031,13 @@ static int dvb_net_feed_start(struct net /* Set netdevice pointer for ts decaps callback. */ priv->tsfeed->priv = (void *)dev; - ret = priv->tsfeed->set(priv->tsfeed, priv->pid, - TS_PACKET, DMX_TS_PES_OTHER, + ret = priv->tsfeed->set(priv->tsfeed, + priv->pid, /* pid */ + TS_PACKET, /* type */ + DMX_TS_PES_OTHER, /* pes type */ 32768, /* circular buffer size */ - timeout); + timeout /* timeout */ + ); if (ret < 0) { printk("%s: could not set ts feed\n", dev->name); @@ -1052,7 +1130,7 @@ static void wq_set_multicast_list (void dvb_net_feed_stop(dev); priv->rx_mode = RX_MODE_UNI; - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); if (dev->flags & IFF_PROMISC) { dprintk("%s: promiscuous mode\n", dev->name); @@ -1077,7 +1155,7 @@ static void wq_set_multicast_list (void } } - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); dvb_net_feed_start(dev); } diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 3852430..134c2bb 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -236,7 +236,7 @@ int dvb_register_device(struct dvb_adapt "dvb/adapter%d/%s%d", adap->num, dnames[type], id); class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), - NULL, "dvb%d.%s%d", adap->num, dnames[type], id); + adap->device, "dvb%d.%s%d", adap->num, dnames[type], id); dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", adap->num, dnames[type], id, nums2minor(adap->num, type, id), @@ -285,7 +285,7 @@ skip: } -int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module) +int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device) { int num; @@ -306,6 +306,7 @@ int dvb_register_adapter(struct dvb_adap adap->num = num; adap->name = name; adap->module = module; + adap->device = device; list_add_tail (&adap->list_head, &dvb_adapter_list); diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h index 74ed585..d7a976d 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.h +++ b/drivers/media/dvb/dvb-core/dvbdev.h @@ -51,6 +51,8 @@ struct dvb_adapter { u8 proposed_mac [6]; void* priv; + struct device *device; + struct module *module; }; @@ -76,7 +78,7 @@ struct dvb_device { }; -extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module); +extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device); extern int dvb_unregister_adapter (struct dvb_adapter *adap); extern int dvb_register_device (struct dvb_adapter *adap, diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index e388fb1..3bc6722 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -88,6 +88,7 @@ config DVB_USB_CXUSB select DVB_CX22702 select DVB_LGDT330X select DVB_MT352 + select DVB_ZL10353 help Say Y here to support the Conexant USB2.0 hybrid reference design. Currently, only DVB and ATSC modes are supported, analog mode @@ -130,6 +131,15 @@ config DVB_USB_VP702X DVB-S USB2.0 receivers. +config DVB_USB_GP8PSK + tristate "GENPIX 8PSK->USB module support" + depends on DVB_USB + help + Say Y here to support the + GENPIX 8psk module + + DVB-S USB2.0 receivers. + config DVB_USB_NOVA_T_USB2 tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" depends on DVB_USB diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 2dc9aad..9643f56 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -7,6 +7,9 @@ obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb- dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o +dvb-usb-gp8psk-objs = gp8psk.o gp8psk-fe.o +obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o + dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 1f0d3e9..ae23bdd 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -27,8 +27,10 @@ #include "cxusb.h" #include "cx22702.h" #include "lgdt330x.h" +#include "lg_h06xf.h" #include "mt352.h" #include "mt352_priv.h" +#include "zl10353.h" /* debug */ int dvb_usb_cxusb_debug; @@ -322,32 +324,37 @@ static int cxusb_mt352_demod_init(struct return 0; } +static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fep) +{ + struct dvb_usb_device *d = fe->dvb->priv; + return lg_h06xf_pll_set(fe, &d->i2c_adap, fep); +} + static struct cx22702_config cxusb_cx22702_config = { .demod_address = 0x63, .output_mode = CX22702_PARALLEL_OUTPUT, - - .pll_init = dvb_usb_pll_init_i2c, - .pll_set = dvb_usb_pll_set_i2c, }; static struct lgdt330x_config cxusb_lgdt3303_config = { .demod_address = 0x0e, .demod_chip = LGDT3303, - .pll_set = dvb_usb_pll_set_i2c, }; static struct mt352_config cxusb_dee1601_config = { .demod_address = 0x0f, .demod_init = cxusb_dee1601_demod_init, - .pll_set = dvb_usb_pll_set, }; -struct mt352_config cxusb_mt352_config = { +static struct zl10353_config cxusb_zl10353_dee1601_config = { + .demod_address = 0x0f, +}; + +static struct mt352_config cxusb_mt352_config = { /* used in both lgz201 and th7579 */ .demod_address = 0x0f, .demod_init = cxusb_mt352_demod_init, - .pll_set = dvb_usb_pll_set, }; /* Callbacks for DVB USB */ @@ -357,17 +364,10 @@ static int cxusb_fmd1216me_tuner_attach( d->pll_addr = 0x61; memcpy(d->pll_init, bpll, 4); d->pll_desc = &dvb_pll_fmd1216me; - return 0; -} -static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d) -{ - u8 bpll[4] = { 0x00, 0x00, 0x18, 0x50 }; - /* bpll[2] : unset bit 3, set bits 4&5 - bpll[3] : 0x50 - digital, 0x20 - analog */ - d->pll_addr = 0x61; - memcpy(d->pll_init, bpll, 4); - d->pll_desc = &dvb_pll_tdvs_tua6034; + d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c; + d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c; + return 0; } @@ -375,6 +375,7 @@ static int cxusb_dee1601_tuner_attach(st { d->pll_addr = 0x61; d->pll_desc = &dvb_pll_thomson_dtt7579; + d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; return 0; } @@ -382,6 +383,7 @@ static int cxusb_lgz201_tuner_attach(str { d->pll_addr = 0x61; d->pll_desc = &dvb_pll_lg_z201; + d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; return 0; } @@ -389,6 +391,13 @@ static int cxusb_dtt7579_tuner_attach(st { d->pll_addr = 0x60; d->pll_desc = &dvb_pll_thomson_dtt7579; + d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; + return 0; +} + +static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_device *d) +{ + d->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params; return 0; } @@ -439,7 +448,8 @@ static int cxusb_dee1601_frontend_attach cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0); - if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) + if (((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) || + ((d->fe = zl10353_attach(&cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL)) return 0; return -EIO; @@ -555,7 +565,7 @@ static struct dvb_usb_properties cxusb_b .streaming_ctrl = cxusb_streaming_ctrl, .power_ctrl = cxusb_bluebird_power_ctrl, .frontend_attach = cxusb_lgdt3303_frontend_attach, - .tuner_attach = cxusb_lgh064f_tuner_attach, + .tuner_attach = cxusb_lgdt3303_tuner_attach, .i2c_algo = &cxusb_i2c_algo, diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c index 2d52b76..abd75b4 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -173,11 +173,10 @@ int dibusb_dib3000mc_frontend_attach(str struct dib3000_config demod_cfg; struct dibusb_state *st = d->priv; - demod_cfg.pll_set = dvb_usb_pll_set_i2c; - demod_cfg.pll_init = dvb_usb_pll_init_i2c; - for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++) if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) { + d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c; + d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c; d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl; return 0; } @@ -190,6 +189,10 @@ int dibusb_dib3000mc_tuner_attach (struc { d->pll_addr = 0x60; d->pll_desc = &dvb_pll_env57h1xd5; + + d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c; + d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c; + return 0; } EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach); diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c index dd5a131..f4c45f3 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c @@ -20,11 +20,12 @@ static int dibusb_dib3000mb_frontend_att struct dibusb_state *st = d->priv; demod_cfg.demod_address = 0x8; - demod_cfg.pll_set = dvb_usb_pll_set_i2c; - demod_cfg.pll_init = dvb_usb_pll_init_i2c; - if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) + if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) { + d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c; + d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c; return -ENODEV; + } d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl; diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 91136c0..c14d9ef 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -112,27 +112,30 @@ static int digitv_mt352_demod_init(struc static struct mt352_config digitv_mt352_config = { .demod_init = digitv_mt352_demod_init, - .pll_set = dvb_usb_pll_set, }; -static int digitv_nxt6000_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) +static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) { struct dvb_usb_device *d = fe->dvb->priv; u8 b[5]; - dvb_usb_pll_set(fe,fep,b); + dvb_usb_tuner_calc_regs(fe,fep,b, 5); return digitv_ctrl_msg(d,USB_WRITE_TUNER,0,&b[1],4,NULL,0); } static struct nxt6000_config digitv_nxt6000_config = { .clock_inversion = 1, - .pll_set = digitv_nxt6000_pll_set, }; static int digitv_frontend_attach(struct dvb_usb_device *d) { - if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL || - (d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) + if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL) { + d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; return 0; + } + if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) { + d->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params; + return 0; + } return -EIO; } diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c index cd21ddb..17413ad 100644 --- a/drivers/media/dvb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c @@ -18,7 +18,6 @@ struct dtt200u_fe_state { struct dvb_frontend_parameters fep; struct dvb_frontend frontend; - struct dvb_frontend_ops ops; }; static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat) @@ -163,16 +162,13 @@ struct dvb_frontend* dtt200u_fe_attach(s deb_info("attaching frontend dtt200u\n"); state->d = d; - memcpy(&state->ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops)); - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; - goto success; + return &state->frontend; error: return NULL; -success: - return &state->frontend; } static struct dvb_frontend_ops dtt200u_fe_ops = { diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c index 6fa9210..ec63170 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c @@ -82,7 +82,7 @@ int dvb_usb_dvb_init(struct dvb_usb_devi int ret; if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name, - d->owner)) < 0) { + d->owner, &d->udev->dev)) < 0) { deb_info("dvb_register_adapter failed: error %d", ret); goto err; } @@ -121,16 +121,15 @@ int dvb_usb_dvb_init(struct dvb_usb_devi dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx); - goto success; + d->state |= DVB_USB_STATE_DVB; + return 0; + err_dmx_dev: dvb_dmx_release(&d->demux); err_dmx: dvb_unregister_adapter(&d->dvb_adap); err: return ret; -success: - d->state |= DVB_USB_STATE_DVB; - return 0; } int dvb_usb_dvb_exit(struct dvb_usb_device *d) @@ -184,13 +183,13 @@ int dvb_usb_fe_init(struct dvb_usb_devic /* re-assign sleep and wakeup functions */ if (d->fe != NULL) { - d->fe_init = d->fe->ops->init; d->fe->ops->init = dvb_usb_fe_wakeup; - d->fe_sleep = d->fe->ops->sleep; d->fe->ops->sleep = dvb_usb_fe_sleep; + d->fe_init = d->fe->ops.init; d->fe->ops.init = dvb_usb_fe_wakeup; + d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep; if (dvb_register_frontend(&d->dvb_adap, d->fe)) { err("Frontend registration failed."); - if (d->fe->ops->release) - d->fe->ops->release(d->fe); + if (d->fe->ops.release) + d->fe->ops.release(d->fe); d->fe = NULL; return -ENODEV; } diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c index 9b25453..6b611a7 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c @@ -46,7 +46,7 @@ int dvb_usb_i2c_exit(struct dvb_usb_devi return 0; } -int dvb_usb_pll_init_i2c(struct dvb_frontend *fe) +int dvb_usb_tuner_init_i2c(struct dvb_frontend *fe) { struct dvb_usb_device *d = fe->dvb->priv; struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 }; @@ -63,6 +63,8 @@ int dvb_usb_pll_init_i2c(struct dvb_fron deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1], d->pll_init[2],d->pll_init[3]); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) { err("tuner i2c write failed for pll_init."); ret = -EREMOTEIO; @@ -73,38 +75,42 @@ int dvb_usb_pll_init_i2c(struct dvb_fron d->tuner_pass_ctrl(fe,0,d->pll_addr); return ret; } -EXPORT_SYMBOL(dvb_usb_pll_init_i2c); +EXPORT_SYMBOL(dvb_usb_tuner_init_i2c); -int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5]) +int dvb_usb_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 *b, int buf_len) { struct dvb_usb_device *d = fe->dvb->priv; + if (buf_len != 5) + return -EINVAL; if (d->pll_desc == NULL) return 0; deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc); - b[0] = d->pll_addr << 1; + b[0] = d->pll_addr; dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth); deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]); - return 0; + return 5; } -EXPORT_SYMBOL(dvb_usb_pll_set); +EXPORT_SYMBOL(dvb_usb_tuner_calc_regs); -int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) +int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) { struct dvb_usb_device *d = fe->dvb->priv; int ret = 0; u8 b[5]; struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 }; - dvb_usb_pll_set(fe,fep,b); + dvb_usb_tuner_calc_regs(fe,fep,b,5); if (d->tuner_pass_ctrl) d->tuner_pass_ctrl(fe,1,d->pll_addr); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) { err("tuner i2c write failed for pll_set."); ret = -EREMOTEIO; @@ -116,4 +122,4 @@ int dvb_usb_pll_set_i2c(struct dvb_front return ret; } -EXPORT_SYMBOL(dvb_usb_pll_set_i2c); +EXPORT_SYMBOL(dvb_usb_tuner_set_params_i2c); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index cb23904..9569891 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -31,6 +31,7 @@ #define USB_VID_PINNACLE 0x2304 #define USB_VID_VISIONPLUS 0x13d3 #define USB_VID_TWINHAN 0x1822 #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 +#define USB_VID_GENPIX 0x09c0 /* Product IDs */ #define USB_PID_ADSTECH_USB2_COLD 0xa333 @@ -104,5 +105,6 @@ #define USB_PID_KYE_DVB_T_COLD 0x701e #define USB_PID_KYE_DVB_T_WARM 0x701f #define USB_PID_PCTV_200E 0x020e #define USB_PID_PCTV_400E 0x020f - +#define USB_PID_GENPIX_8PSK_COLD 0x0200 +#define USB_PID_GENPIX_8PSK_WARM 0x0201 #endif diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index fead958..4cf9f89 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -330,9 +330,9 @@ extern int dvb_usb_generic_write(struct extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *); /* commonly used pll init and set functions */ -extern int dvb_usb_pll_init_i2c(struct dvb_frontend *); -extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]); -extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *); +extern int dvb_usb_tuner_init_i2c(struct dvb_frontend *); +extern int dvb_usb_tuner_calc_regs(struct dvb_frontend *, struct dvb_frontend_parameters *, u8 *buf, int buf_len); +extern int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *); /* commonly used firmware download types and function */ struct hexline { diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c new file mode 100644 index 0000000..6ccbdc9 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c @@ -0,0 +1,272 @@ +/* DVB USB compliant Linux driver for the + * - GENPIX 8pks/qpsk USB2.0 DVB-S module + * + * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com) + * + * Thanks to GENPIX for the sample code used to implement this module. + * + * This module is based off the vp7045 and vp702x modules + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 2. + * + * see Documentation/dvb/README.dvb-usb for more information + */ +#include "gp8psk.h" + +struct gp8psk_fe_state { + struct dvb_frontend fe; + + struct dvb_usb_device *d; + + u16 snr; + + unsigned long next_snr_check; +}; + +static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) +{ + struct gp8psk_fe_state *st = fe->demodulator_priv; + u8 lock; + + if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1)) + return -EINVAL; + + if (lock) + *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER; + else + *status = 0; + + return 0; +} + +/* not supported by this Frontend */ +static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber) +{ + (void) fe; + *ber = 0; + return 0; +} + +/* not supported by this Frontend */ +static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) +{ + (void) fe; + *unc = 0; + return 0; +} + +static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr) +{ + struct gp8psk_fe_state *st = fe->demodulator_priv; + u8 buf[2]; + + if (time_after(jiffies,st->next_snr_check)) { + gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2); + *snr = (int)(buf[1]) << 8 | buf[0]; + /* snr is reported in dBu*256 */ + /* snr / 38.4 ~= 100% strength */ + /* snr * 17 returns 100% strength as 65535 */ + if (*snr <= 3855) + *snr = (*snr<<4) + *snr; // snr * 17 + else + *snr = 65535; + st->next_snr_check = jiffies + (10*HZ)/1000; + } else { + *snr = st->snr; + } + return 0; +} + +static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) +{ + return gp8psk_fe_read_snr(fe, strength); +} + +static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) +{ + tune->min_delay_ms = 800; + return 0; +} + +static int gp8psk_fe_set_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + struct gp8psk_fe_state *state = fe->demodulator_priv; + u8 cmd[10]; + u32 freq = fep->frequency * 1000; + + cmd[4] = freq & 0xff; + cmd[5] = (freq >> 8) & 0xff; + cmd[6] = (freq >> 16) & 0xff; + cmd[7] = (freq >> 24) & 0xff; + + switch(fe->ops.info.type) { + case FE_QPSK: + cmd[0] = fep->u.qpsk.symbol_rate & 0xff; + cmd[1] = (fep->u.qpsk.symbol_rate >> 8) & 0xff; + cmd[2] = (fep->u.qpsk.symbol_rate >> 16) & 0xff; + cmd[3] = (fep->u.qpsk.symbol_rate >> 24) & 0xff; + cmd[8] = ADV_MOD_DVB_QPSK; + cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/ + break; + default: + // other modes are unsuported right now + cmd[0] = 0; + cmd[1] = 0; + cmd[2] = 0; + cmd[3] = 0; + cmd[8] = 0; + cmd[9] = 0; + break; + } + + gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10); + + state->next_snr_check = jiffies; + + return 0; +} + +static int gp8psk_fe_get_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + return 0; +} + + +static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd *m) +{ + struct gp8psk_fe_state *st = fe->demodulator_priv; + + deb_fe("%s\n",__FUNCTION__); + + if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0, + m->msg, m->msg_len)) { + return -EINVAL; + } + return 0; +} + +static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe, + fe_sec_mini_cmd_t burst) +{ + struct gp8psk_fe_state *st = fe->demodulator_priv; + u8 cmd; + + deb_fe("%s\n",__FUNCTION__); + + /* These commands are certainly wrong */ + cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01; + + if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0, + &cmd, 0)) { + return -EINVAL; + } + return 0; +} + +static int gp8psk_fe_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct gp8psk_fe_state* state = fe->demodulator_priv; + + if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE, + (tone == SEC_TONE_ON), 0, NULL, 0)) { + return -EINVAL; + } + return 0; +} + +static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) +{ + struct gp8psk_fe_state* state = fe->demodulator_priv; + + if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, + voltage == SEC_VOLTAGE_18, 0, NULL, 0)) { + return -EINVAL; + } + return 0; +} + +static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd) +{ + struct gp8psk_fe_state* state = fe->demodulator_priv; + u8 cmd = sw_cmd & 0x7f; + + if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0, + NULL, 0)) { + return -EINVAL; + } + if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80), + 0, NULL, 0)) { + return -EINVAL; + } + + return 0; +} + +static void gp8psk_fe_release(struct dvb_frontend* fe) +{ + struct gp8psk_fe_state *state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops gp8psk_fe_ops; + +struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d) +{ + struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL); + if (s == NULL) + goto error; + + s->d = d; + memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops)); + s->fe.demodulator_priv = s; + + goto success; +error: + return NULL; +success: + return &s->fe; +} + + +static struct dvb_frontend_ops gp8psk_fe_ops = { + .info = { + .name = "Genpix 8psk-USB DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 100, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, /* ppm */ + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK + }, + + .release = gp8psk_fe_release, + + .init = NULL, + .sleep = NULL, + + .set_frontend = gp8psk_fe_set_frontend, + .get_frontend = gp8psk_fe_get_frontend, + .get_tune_settings = gp8psk_fe_get_tune_settings, + + .read_status = gp8psk_fe_read_status, + .read_ber = gp8psk_fe_read_ber, + .read_signal_strength = gp8psk_fe_read_signal_strength, + .read_snr = gp8psk_fe_read_snr, + .read_ucblocks = gp8psk_fe_read_unc_blocks, + + .diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg, + .diseqc_send_burst = gp8psk_fe_send_diseqc_burst, + .set_tone = gp8psk_fe_set_tone, + .set_voltage = gp8psk_fe_set_voltage, + .dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd, +}; diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c new file mode 100644 index 0000000..9a98f3f --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gp8psk.c @@ -0,0 +1,256 @@ +/* DVB USB compliant Linux driver for the + * - GENPIX 8pks/qpsk USB2.0 DVB-S module + * + * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com) + * + * Thanks to GENPIX for the sample code used to implement this module. + * + * This module is based off the vp7045 and vp702x modules + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 2. + * + * see Documentation/dvb/README.dvb-usb for more information + */ +#include "gp8psk.h" + +/* debug */ +static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw"; +int dvb_usb_gp8psk_debug; +module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); + +int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) +{ + int ret = 0,try = 0; + + if ((ret = mutex_lock_interruptible(&d->usb_mutex))) + return ret; + + while (ret >= 0 && ret != blen && try < 3) { + ret = usb_control_msg(d->udev, + usb_rcvctrlpipe(d->udev,0), + req, + USB_TYPE_VENDOR | USB_DIR_IN, + value,index,b,blen, + 2000); + deb_info("reading number %d (ret: %d)\n",try,ret); + try++; + } + + if (ret < 0 || ret != blen) { + warn("usb in operation failed."); + ret = -EIO; + } else + ret = 0; + + deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index); + debug_dump(b,blen,deb_xfer); + + mutex_unlock(&d->usb_mutex); + + return ret; +} + +int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, + u16 index, u8 *b, int blen) +{ + int ret; + + deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); + debug_dump(b,blen,deb_xfer); + + if ((ret = mutex_lock_interruptible(&d->usb_mutex))) + return ret; + + if (usb_control_msg(d->udev, + usb_sndctrlpipe(d->udev,0), + req, + USB_TYPE_VENDOR | USB_DIR_OUT, + value,index,b,blen, + 2000) != blen) { + warn("usb out operation failed."); + ret = -EIO; + } else + ret = 0; + mutex_unlock(&d->usb_mutex); + + return ret; +} + +static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) +{ + int ret; + const struct firmware *fw = NULL; + u8 *ptr, *buf; + if ((ret = request_firmware(&fw, bcm4500_firmware, + &d->udev->dev)) != 0) { + err("did not find the bcm4500 firmware file. (%s) " + "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)", + bcm4500_firmware,ret); + return ret; + } + + ret = -EINVAL; + + if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0)) + goto out_rel_fw; + + info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware); + + ptr = fw->data; + buf = kmalloc(512, GFP_KERNEL | GFP_DMA); + + while (ptr[0] != 0xff) { + u16 buflen = ptr[0] + 4; + if (ptr + buflen >= fw->data + fw->size) { + err("failed to load bcm4500 firmware."); + goto out_free; + } + memcpy(buf, ptr, buflen); + if (dvb_usb_generic_write(d, buf, buflen)) { + err("failed to load bcm4500 firmware."); + goto out_free; + } + ptr += buflen; + } + + ret = 0; + +out_free: + kfree(buf); +out_rel_fw: + release_firmware(fw); + + return ret; +} + +static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + u8 status, buf; + if (onoff) { + gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1); + if (! (status & 0x01)) /* started */ + if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1)) + return -EINVAL; + + if (! (status & 0x02)) /* BCM4500 firmware loaded */ + if(gp8psk_load_bcm4500fw(d)) + return EINVAL; + + if (! (status & 0x04)) /* LNB Power */ + if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0, + &buf, 1)) + return EINVAL; + + /* Set DVB mode */ + if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0)) + return -EINVAL; + gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1); + } else { + /* Turn off LNB power */ + if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1)) + return EINVAL; + /* Turn off 8psk power */ + if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) + return -EINVAL; + + } + return 0; +} + + +static int gp8psk_streaming_ctrl(struct dvb_usb_device *d, int onoff) +{ + return gp8psk_usb_out_op(d, ARM_TRANSFER, onoff, 0 , NULL, 0); +} + +static int gp8psk_frontend_attach(struct dvb_usb_device *d) +{ + d->fe = gp8psk_fe_attach(d); + + return 0; +} + +static struct dvb_usb_properties gp8psk_properties; + +static int gp8psk_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL); +} + +static struct usb_device_id gp8psk_usb_table [] = { + { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) }, + { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) }, + { 0 }, +}; +MODULE_DEVICE_TABLE(usb, gp8psk_usb_table); + +static struct dvb_usb_properties gp8psk_properties = { + .caps = 0, + + .usb_ctrl = CYPRESS_FX2, + .firmware = "dvb-usb-gp8psk-01.fw", + + .streaming_ctrl = gp8psk_streaming_ctrl, + .power_ctrl = gp8psk_power_ctrl, + .frontend_attach = gp8psk_frontend_attach, + + .generic_bulk_ctrl_endpoint = 0x01, + /* parameter for the MPEG2-data transfer */ + .urb = { + .type = DVB_USB_BULK, + .count = 7, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, + + .num_device_descs = 1, + .devices = { + { .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver", + .cold_ids = { &gp8psk_usb_table[0], NULL }, + .warm_ids = { &gp8psk_usb_table[1], NULL }, + }, + { 0 }, + } +}; + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver gp8psk_usb_driver = { + .name = "dvb_usb_gp8psk", + .probe = gp8psk_usb_probe, + .disconnect = dvb_usb_device_exit, + .id_table = gp8psk_usb_table, +}; + +/* module stuff */ +static int __init gp8psk_usb_module_init(void) +{ + int result; + if ((result = usb_register(&gp8psk_usb_driver))) { + err("usb_register failed. (%d)",result); + return result; + } + + return 0; +} + +static void __exit gp8psk_usb_module_exit(void) +{ + /* deregister this driver from the USB subsystem */ + usb_deregister(&gp8psk_usb_driver); +} + +module_init(gp8psk_usb_module_init); +module_exit(gp8psk_usb_module_exit); + +MODULE_AUTHOR("Alan Nisota "); +MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h new file mode 100644 index 0000000..3eba706 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gp8psk.h @@ -0,0 +1,79 @@ +/* DVB USB compliant Linux driver for the + * - GENPIX 8pks/qpsk USB2.0 DVB-S module + * + * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com) + * + * Thanks to GENPIX for the sample code used to implement this module. + * + * This module is based off the vp7045 and vp702x modules + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 2. + * + * see Documentation/dvb/README.dvb-usb for more information + */ +#ifndef _DVB_USB_GP8PSK_H_ +#define _DVB_USB_GP8PSK_H_ + +#define DVB_USB_LOG_PREFIX "gp8psk" +#include "dvb-usb.h" + +extern int dvb_usb_gp8psk_debug; +#define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args) +#define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args) +#define deb_rc(args...) dprintk(dvb_usb_gp8psk_debug,0x04,args) +#define deb_fe(args...) dprintk(dvb_usb_gp8psk_debug,0x08,args) +/* gp8psk commands */ + +/* Twinhan Vendor requests */ +#define TH_COMMAND_IN 0xC0 +#define TH_COMMAND_OUT 0xC1 + +/* command bytes */ +#define GET_8PSK_CONFIG 0x80 +#define SET_8PSK_CONFIG 0x81 +#define ARM_TRANSFER 0x85 +#define TUNE_8PSK 0x86 +#define GET_SIGNAL_STRENGTH 0x87 +#define LOAD_BCM4500 0x88 +#define BOOT_8PSK 0x89 +#define START_INTERSIL 0x8A +#define SET_LNB_VOLTAGE 0x8B +#define SET_22KHZ_TONE 0x8C +#define SEND_DISEQC_COMMAND 0x8D +#define SET_DVB_MODE 0x8E +#define SET_DN_SWITCH 0x8F +#define GET_SIGNAL_LOCK 0x90 + +/* Satellite modulation modes */ +#define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */ +#define ADV_MOD_TURBO_QPSK 1 /* Turbo QPSK */ +#define ADV_MOD_TURBO_8PSK 2 /* Turbo 8PSK (also used for Trellis 8PSK) */ +#define ADV_MOD_TURBO_16QAM 3 /* Turbo 16QAM (also used for Trellis 8PSK) */ + +#define ADV_MOD_DCII_C_QPSK 4 /* Digicipher II Combo */ +#define ADV_MOD_DCII_I_QPSK 5 /* Digicipher II I-stream */ +#define ADV_MOD_DCII_Q_QPSK 6 /* Digicipher II Q-stream */ +#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */ +#define ADV_MOD_DSS_QPSK 8 /* DSS (DIRECTV) QPSK */ +#define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */ + +#define GET_USB_SPEED 0x07 + #define USB_SPEED_LOW 0 + #define USB_SPEED_FULL 1 + #define USB_SPEED_HIGH 2 + +#define RESET_FX2 0x13 + +#define FW_VERSION_READ 0x0B +#define VENDOR_STRING_READ 0x0C +#define PRODUCT_STRING_READ 0x0D +#define FW_BCD_VERSION_READ 0x14 + +extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d); +extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); +extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, + u16 index, u8 *b, int blen); + +#endif diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c index 14f1911..97d74da 100644 --- a/drivers/media/dvb/dvb-usb/umt-010.c +++ b/drivers/media/dvb/dvb-usb/umt-010.c @@ -57,7 +57,6 @@ static int umt_mt352_frontend_attach(str memset(&umt_config,0,sizeof(struct mt352_config)); umt_config.demod_init = umt_mt352_demod_init; umt_config.demod_address = 0xf; - umt_config.pll_set = dvb_usb_pll_set; d->fe = mt352_attach(&umt_config, &d->i2c_adap); @@ -68,6 +67,7 @@ static int umt_tuner_attach (struct dvb_ { d->pll_addr = 0x61; d->pll_desc = &dvb_pll_tua6034; + d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; return 0; } diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c index 2a89f8c..d4da494 100644 --- a/drivers/media/dvb/dvb-usb/vp702x-fe.c +++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c @@ -287,17 +287,16 @@ struct dvb_frontend * vp702x_fe_attach(s goto error; s->d = d; - s->fe.ops = &vp702x_fe_ops; + + memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops)); s->fe.demodulator_priv = s; s->lnb_buf[1] = SET_LNB_POWER; s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */ - goto success; + return &s->fe; error: return NULL; -success: - return &s->fe; } diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c index 9999336..8452eef 100644 --- a/drivers/media/dvb/dvb-usb/vp7045-fe.c +++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c @@ -23,8 +23,6 @@ #include "vp7045.h" struct vp7045_fe_state { struct dvb_frontend fe; - struct dvb_frontend_ops ops; - struct dvb_usb_device *d; }; @@ -151,15 +149,12 @@ struct dvb_frontend * vp7045_fe_attach(s goto error; s->d = d; - memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops)); - s->fe.ops = &s->ops; + memcpy(&s->fe.ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops)); s->fe.demodulator_priv = s; - goto success; + return &s->fe; error: return NULL; -success: - return &s->fe; } diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 37d5e0a..0ef361f 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -157,7 +157,7 @@ config DVB_STV0297 help A DVB-C tuner module. Say Y when you want to support this frontend. -comment "ATSC (North American/Korean Terresterial DTV) frontends" +comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends" depends on DVB_CORE config DVB_NXT200X @@ -216,4 +216,20 @@ config DVB_LGDT330X An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. + +comment "Miscellaneous devices" + depends on DVB_CORE + +config DVB_LNBP21 + tristate "LNBP21 SEC controller" + depends on DVB_CORE + help + An SEC control chip. + +config DVB_ISL6421 + tristate "ISL6421 SEC controller" + depends on DVB_CORE + help + An SEC control chip. + endmenu diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index d09b607..5222245 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -31,3 +31,5 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o obj-$(CONFIG_DVB_S5H1420) += s5h1420.o obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o obj-$(CONFIG_DVB_CX24123) += cx24123.o +obj-$(CONFIG_DVB_LNBP21) += lnbp21.o +obj-$(CONFIG_DVB_ISL6421) += isl6421.o diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c index 1708a1d..baeb311 100644 --- a/drivers/media/dvb/frontends/bcm3510.c +++ b/drivers/media/dvb/frontends/bcm3510.c @@ -48,7 +48,6 @@ #include "bcm3510_priv.h" struct bcm3510_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; const struct bcm3510_config* config; struct dvb_frontend frontend; @@ -791,10 +790,9 @@ struct dvb_frontend* bcm3510_attach(cons state->config = config; state->i2c = i2c; - memcpy(&state->ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops)); /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; mutex_init(&state->hab_mutex); diff --git a/drivers/media/dvb/frontends/bsbe1.h b/drivers/media/dvb/frontends/bsbe1.h index 78573b2..d8f6573 100644 --- a/drivers/media/dvb/frontends/bsbe1.h +++ b/drivers/media/dvb/frontends/bsbe1.h @@ -89,12 +89,13 @@ static int alps_bsbe1_set_symbol_rate(st return 0; } -static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params) +static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { int ret; u8 data[4]; u32 div; struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; + struct i2c_adapter *i2c = fe->tuner_priv; if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; @@ -105,6 +106,8 @@ static int alps_bsbe1_pll_set(struct dvb data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); ret = i2c_transfer(i2c, &msg, 1); return (ret != 1) ? -EIO : 0; } @@ -117,7 +120,6 @@ static struct stv0299_config alps_bsbe1_ .skip_reinit = 0, .min_delay_ms = 100, .set_symbol_rate = alps_bsbe1_set_symbol_rate, - .pll_set = alps_bsbe1_pll_set, }; #endif diff --git a/drivers/media/dvb/frontends/bsru6.h b/drivers/media/dvb/frontends/bsru6.h index 2a5366c..e231cd8 100644 --- a/drivers/media/dvb/frontends/bsru6.h +++ b/drivers/media/dvb/frontends/bsru6.h @@ -101,11 +101,12 @@ static int alps_bsru6_set_symbol_rate(st return 0; } -static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params) +static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { u8 buf[4]; u32 div; struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; + struct i2c_adapter *i2c = fe->tuner_priv; if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; @@ -119,6 +120,8 @@ static int alps_bsru6_pll_set(struct dvb if (params->frequency > 1530000) buf[3] = 0xc0; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO; return 0; @@ -134,7 +137,6 @@ static struct stv0299_config alps_bsru6_ .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 100, .set_symbol_rate = alps_bsru6_set_symbol_rate, - .pll_set = alps_bsru6_pll_set, }; #endif diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c index 755f774..3c7c09a 100644 --- a/drivers/media/dvb/frontends/cx22700.c +++ b/drivers/media/dvb/frontends/cx22700.c @@ -34,8 +34,6 @@ struct cx22700_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; - const struct cx22700_config* config; struct dvb_frontend frontend; @@ -247,12 +245,6 @@ static int cx22700_init (struct dvb_fron cx22700_writereg (state, 0x00, 0x01); - if (state->config->pll_init) { - cx22700_writereg (state, 0x0a, 0x00); /* open i2c bus switch */ - state->config->pll_init(fe); - cx22700_writereg (state, 0x0a, 0x01); /* close i2c bus switch */ - } - return 0; } @@ -333,9 +325,11 @@ static int cx22700_set_frontend(struct d cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/ cx22700_writereg (state, 0x00, 0x00); - cx22700_writereg (state, 0x0a, 0x00); /* open i2c bus switch */ - state->config->pll_set(fe, p); - cx22700_writereg (state, 0x0a, 0x01); /* close i2c bus switch */ + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } + cx22700_set_inversion (state, p->inversion); cx22700_set_tps (state, &p->u.ofdm); cx22700_writereg (state, 0x37, 0x01); /* PAL loop filter off */ @@ -353,6 +347,17 @@ static int cx22700_get_frontend(struct d return cx22700_get_tps (state, &p->u.ofdm); } +static int cx22700_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct cx22700_state* state = fe->demodulator_priv; + + if (enable) { + return cx22700_writereg(state, 0x0a, 0x00); + } else { + return cx22700_writereg(state, 0x0a, 0x01); + } +} + static int cx22700_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { fesettings->min_delay_ms = 150; @@ -381,13 +386,12 @@ struct dvb_frontend* cx22700_attach(cons /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &cx22700_ops, sizeof(struct dvb_frontend_ops)); /* check if the demod is there */ if (cx22700_readreg(state, 0x07) < 0) goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &cx22700_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -413,6 +417,7 @@ static struct dvb_frontend_ops cx22700_o .release = cx22700_release, .init = cx22700_init, + .i2c_gate_ctrl = cx22700_i2c_gate_ctrl, .set_frontend = cx22700_set_frontend, .get_frontend = cx22700_get_frontend, diff --git a/drivers/media/dvb/frontends/cx22700.h b/drivers/media/dvb/frontends/cx22700.h index c9145b4..dcd8979 100644 --- a/drivers/media/dvb/frontends/cx22700.h +++ b/drivers/media/dvb/frontends/cx22700.h @@ -29,10 +29,6 @@ struct cx22700_config { /* the demodulator's i2c address */ u8 demod_address; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config, diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c index 0fc899f..4106d46 100644 --- a/drivers/media/dvb/frontends/cx22702.c +++ b/drivers/media/dvb/frontends/cx22702.c @@ -40,8 +40,6 @@ struct cx22702_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; - /* configuration settings */ const struct cx22702_config* config; @@ -211,22 +209,10 @@ static int cx22702_set_tps (struct dvb_f u8 val; struct cx22702_state* state = fe->demodulator_priv; - /* set PLL */ - cx22702_i2c_gate_ctrl(fe, 1); - if (state->config->pll_set) { - state->config->pll_set(fe, p); - } else if (state->config->pll_desc) { - u8 pllbuf[4]; - struct i2c_msg msg = { .addr = state->config->pll_address, - .buf = pllbuf, .len = 4 }; - dvb_pll_configure(state->config->pll_desc, pllbuf, - p->frequency, - p->u.ofdm.bandwidth); - i2c_transfer(state->i2c, &msg, 1); - } else { - BUG(); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); } - cx22702_i2c_gate_ctrl(fe, 0); /* set inversion */ cx22702_set_inversion (state, p->inversion); @@ -358,10 +344,6 @@ static int cx22702_init (struct dvb_fron cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02); - /* init PLL */ - if (state->config->pll_init) - state->config->pll_init(fe); - cx22702_i2c_gate_ctrl(fe, 0); return 0; @@ -495,7 +477,6 @@ struct dvb_frontend* cx22702_attach(cons /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &cx22702_ops, sizeof(struct dvb_frontend_ops)); state->prevUCBlocks = 0; /* check if the demod is there */ @@ -503,7 +484,7 @@ struct dvb_frontend* cx22702_attach(cons goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &cx22702_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -530,6 +511,7 @@ static struct dvb_frontend_ops cx22702_o .release = cx22702_release, .init = cx22702_init, + .i2c_gate_ctrl = cx22702_i2c_gate_ctrl, .set_frontend = cx22702_set_tps, .get_frontend = cx22702_get_frontend, @@ -540,7 +522,6 @@ static struct dvb_frontend_ops cx22702_o .read_signal_strength = cx22702_read_signal_strength, .read_snr = cx22702_read_snr, .read_ucblocks = cx22702_read_ucblocks, - .i2c_gate_ctrl = cx22702_i2c_gate_ctrl, }; module_param(debug, int, 0644); diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h index 5633976..7f2f241 100644 --- a/drivers/media/dvb/frontends/cx22702.h +++ b/drivers/media/dvb/frontends/cx22702.h @@ -39,13 +39,6 @@ struct cx22702_config #define CX22702_PARALLEL_OUTPUT 0 #define CX22702_SERIAL_OUTPUT 1 u8 output_mode; - - /* PLL maintenance */ - u8 pll_address; - struct dvb_pll_desc *pll_desc; - - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index f3edf8b..ce3c739 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c @@ -36,8 +36,6 @@ struct cx24110_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; - const struct cx24110_config* config; struct dvb_frontend frontend; @@ -250,7 +248,7 @@ static int cx24110_set_symbolrate (struc static const u32 bands[]={5000000UL,15000000UL,90999000UL/2}; int i; -dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate); + dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate); if (srate>90999000UL/2) srate=90999000UL/2; if (srate<500000) @@ -366,17 +364,6 @@ static int cx24110_initfe(struct dvb_fro cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data); }; - if (state->config->pll_init) state->config->pll_init(fe); - - return 0; -} - -static int cx24110_sleep(struct dvb_frontend *fe) -{ - struct cx24110_state *state = fe->demodulator_priv; - - if (state->config->pll_sleep) - return state->config->pll_sleep(fe); return 0; } @@ -548,7 +535,12 @@ static int cx24110_set_frontend(struct d { struct cx24110_state *state = fe->demodulator_priv; - state->config->pll_set(fe, p); + + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } + cx24110_set_inversion (state, p->inversion); cx24110_set_fec (state, p->u.qpsk.fec_inner); cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate); @@ -612,7 +604,6 @@ struct dvb_frontend* cx24110_attach(cons /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &cx24110_ops, sizeof(struct dvb_frontend_ops)); state->lastber = 0; state->lastbler = 0; state->lastesn0 = 0; @@ -622,7 +613,7 @@ struct dvb_frontend* cx24110_attach(cons if ((ret != 0x5a) && (ret != 0x69)) goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &cx24110_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -651,7 +642,6 @@ static struct dvb_frontend_ops cx24110_o .release = cx24110_release, .init = cx24110_initfe, - .sleep = cx24110_sleep, .set_frontend = cx24110_set_frontend, .get_frontend = cx24110_get_frontend, .read_status = cx24110_read_status, diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h index 609ac64..b354a64 100644 --- a/drivers/media/dvb/frontends/cx24110.h +++ b/drivers/media/dvb/frontends/cx24110.h @@ -31,11 +31,6 @@ struct cx24110_config { /* the demodulator's i2c address */ u8 demod_address; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); - int (*pll_sleep)(struct dvb_frontend* fe); }; extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index 691dc84..f2f795c 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c @@ -41,14 +41,12 @@ #define dprintk(args...) \ struct cx24123_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; const struct cx24123_config* config; struct dvb_frontend frontend; u32 lastber; u16 snr; - u8 lnbreg; /* Some PLL specifics for tuning */ u32 VCAarg; @@ -249,29 +247,6 @@ static int cx24123_writereg(struct cx241 return 0; } -static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data) -{ - u8 buf[] = { reg, data }; - /* fixme: put the intersil addr int the config */ - struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 }; - int err; - - if (debug>1) - printk("cx24123: %s: writeln addr=0x08, reg 0x%02x, value 0x%02x\n", - __FUNCTION__,reg, data); - - if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { - printk("%s: writelnbreg error (err == %i, reg == 0x%02x," - " data == 0x%02x)\n", __FUNCTION__, err, reg, data); - return -EREMOTEIO; - } - - /* cache the write, no way to read back */ - state->lnbreg = data; - - return 0; -} - static int cx24123_readreg(struct cx24123_state* state, u8 reg) { int ret; @@ -295,11 +270,6 @@ static int cx24123_readreg(struct cx2412 return b1[0]; } -static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg) -{ - return state->lnbreg; -} - static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion) { u8 nom_reg = cx24123_readreg(state, 0x0e); @@ -458,8 +428,8 @@ static int cx24123_set_symbolrate(struct u8 pll_mult; /* check if symbol rate is within limits */ - if ((srate > state->ops.info.symbol_rate_max) || - (srate < state->ops.info.symbol_rate_min)) + if ((srate > state->frontend.ops.info.symbol_rate_max) || + (srate < state->frontend.ops.info.symbol_rate_min)) return -EOPNOTSUPP;; /* choose the sampling rate high enough for the required operation, @@ -687,13 +657,6 @@ static int cx24123_initfe(struct dvb_fro for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++) cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data); - if (state->config->pll_init) - state->config->pll_init(fe); - - /* Configure the LNB for 14V */ - if (state->config->use_isl6421) - cx24123_writelnbreg(state, 0x0, 0x2a); - return 0; } @@ -702,50 +665,18 @@ static int cx24123_set_voltage(struct dv struct cx24123_state *state = fe->demodulator_priv; u8 val; - switch (state->config->use_isl6421) { - - case 1: + val = cx24123_readreg(state, 0x29) & ~0x40; - val = cx24123_readlnbreg(state, 0x0); - - switch (voltage) { - case SEC_VOLTAGE_13: - dprintk("%s: isl6421 voltage = 13V\n",__FUNCTION__); - return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */ - case SEC_VOLTAGE_18: - dprintk("%s: isl6421 voltage = 18V\n",__FUNCTION__); - return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */ - case SEC_VOLTAGE_OFF: - dprintk("%s: isl5421 voltage off\n",__FUNCTION__); - return cx24123_writelnbreg(state, 0x0, val & 0x30); - default: - return -EINVAL; - }; - - case 0: - - val = cx24123_readreg(state, 0x29); - - switch (voltage) { - case SEC_VOLTAGE_13: - dprintk("%s: setting voltage 13V\n", __FUNCTION__); - if (state->config->enable_lnb_voltage) - state->config->enable_lnb_voltage(fe, 1); - return cx24123_writereg(state, 0x29, val | 0x80); - case SEC_VOLTAGE_18: - dprintk("%s: setting voltage 18V\n", __FUNCTION__); - if (state->config->enable_lnb_voltage) - state->config->enable_lnb_voltage(fe, 1); - return cx24123_writereg(state, 0x29, val & 0x7f); - case SEC_VOLTAGE_OFF: - dprintk("%s: setting voltage off\n", __FUNCTION__); - if (state->config->enable_lnb_voltage) - state->config->enable_lnb_voltage(fe, 0); - return 0; - default: - return -EINVAL; - }; - } + switch (voltage) { + case SEC_VOLTAGE_13: + dprintk("%s: setting voltage 13V\n", __FUNCTION__); + return cx24123_writereg(state, 0x29, val | 0x80); + case SEC_VOLTAGE_18: + dprintk("%s: setting voltage 18V\n", __FUNCTION__); + return cx24123_writereg(state, 0x29, val & 0x7f); + default: + return -EINVAL; + }; return 0; } @@ -766,27 +697,20 @@ static void cx24123_wait_for_diseqc(stru static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) { struct cx24123_state *state = fe->demodulator_priv; - int i, val; + int i, val, tone; dprintk("%s:\n",__FUNCTION__); - /* check if continuous tone has been stopped */ - if (state->config->use_isl6421) - val = cx24123_readlnbreg(state, 0x00) & 0x10; - else - val = cx24123_readreg(state, 0x29) & 0x10; - - - if (val) { - printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); - return -ENOTSUPP; - } + /* stop continuous tone if enabled */ + tone = cx24123_readreg(state, 0x29); + if (tone & 0x10) + cx24123_writereg(state, 0x29, tone & ~0x50); /* wait for diseqc queue ready */ cx24123_wait_for_diseqc(state); /* select tone mode */ - cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8); + cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb); for (i = 0; i < cmd->msg_len; i++) cx24123_writereg(state, 0x2C + i, cmd->msg[i]); @@ -797,36 +721,33 @@ static int cx24123_send_diseqc_msg(struc /* wait for diseqc message to finish sending */ cx24123_wait_for_diseqc(state); + /* restart continuous tone if enabled */ + if (tone & 0x10) { + cx24123_writereg(state, 0x29, tone & ~0x40); + } + return 0; } static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) { struct cx24123_state *state = fe->demodulator_priv; - int val; + int val, tone; dprintk("%s:\n", __FUNCTION__); - /* check if continuous tone has been stoped */ - if (state->config->use_isl6421) - val = cx24123_readlnbreg(state, 0x00) & 0x10; - else - val = cx24123_readreg(state, 0x29) & 0x10; - - - if (val) { - printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); - return -ENOTSUPP; - } + /* stop continuous tone if enabled */ + tone = cx24123_readreg(state, 0x29); + if (tone & 0x10) + cx24123_writereg(state, 0x29, tone & ~0x50); + /* wait for diseqc queue ready */ cx24123_wait_for_diseqc(state); /* select tone mode */ - val = cx24123_readreg(state, 0x2a) & 0xf8; - cx24123_writereg(state, 0x2a, val | 0x04); - + cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4); + msleep(30); val = cx24123_readreg(state, 0x29); - if (burst == SEC_MINI_A) cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00)); else if (burst == SEC_MINI_B) @@ -835,7 +756,12 @@ static int cx24123_diseqc_send_burst(str return -EINVAL; cx24123_wait_for_diseqc(state); + cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb); + /* restart continuous tone if enabled */ + if (tone & 0x10) { + cx24123_writereg(state, 0x29, tone & ~0x40); + } return 0; } @@ -976,38 +902,21 @@ static int cx24123_set_tone(struct dvb_f struct cx24123_state *state = fe->demodulator_priv; u8 val; - switch (state->config->use_isl6421) { - case 1: - - val = cx24123_readlnbreg(state, 0x0); - - switch (tone) { - case SEC_TONE_ON: - dprintk("%s: isl6421 sec tone on\n",__FUNCTION__); - return cx24123_writelnbreg(state, 0x0, val | 0x10); - case SEC_TONE_OFF: - dprintk("%s: isl6421 sec tone off\n",__FUNCTION__); - return cx24123_writelnbreg(state, 0x0, val & 0x2f); - default: - printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); - return -EINVAL; - } - - case 0: + /* wait for diseqc queue ready */ + cx24123_wait_for_diseqc(state); - val = cx24123_readreg(state, 0x29); + val = cx24123_readreg(state, 0x29) & ~0x40; - switch (tone) { - case SEC_TONE_ON: - dprintk("%s: setting tone on\n", __FUNCTION__); - return cx24123_writereg(state, 0x29, val | 0x10); - case SEC_TONE_OFF: - dprintk("%s: setting tone off\n",__FUNCTION__); - return cx24123_writereg(state, 0x29, val & 0xef); - default: - printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); - return -EINVAL; - } + switch (tone) { + case SEC_TONE_ON: + dprintk("%s: setting tone on\n", __FUNCTION__); + return cx24123_writereg(state, 0x29, val | 0x10); + case SEC_TONE_OFF: + dprintk("%s: setting tone off\n",__FUNCTION__); + return cx24123_writereg(state, 0x29, val & 0xef); + default: + printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); + return -EINVAL; } return 0; @@ -1040,10 +949,8 @@ struct dvb_frontend* cx24123_attach(cons /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops)); state->lastber = 0; state->snr = 0; - state->lnbreg = 0; state->VCAarg = 0; state->VGAarg = 0; state->bandselectarg = 0; @@ -1059,7 +966,7 @@ struct dvb_frontend* cx24123_attach(cons } /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h index 0c922b5..9606f82 100644 --- a/drivers/media/dvb/frontends/cx24123.h +++ b/drivers/media/dvb/frontends/cx24123.h @@ -28,21 +28,8 @@ struct cx24123_config /* the demodulator's i2c address */ u8 demod_address; - /* - cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip - for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits - from register 0x29 of the CX24123 demodulator - */ - int use_isl6421; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); - /* Need to set device param for start_dma */ int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); - - void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on); }; extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, diff --git a/drivers/media/dvb/frontends/dib3000-common.h b/drivers/media/dvb/frontends/dib3000-common.h index c31d6df..be1c0d3 100644 --- a/drivers/media/dvb/frontends/dib3000-common.h +++ b/drivers/media/dvb/frontends/dib3000-common.h @@ -38,8 +38,6 @@ #define warn(format, arg...) printk(KERN struct dib3000_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; - /* configuration settings */ struct dib3000_config config; diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h index 2d5475b..ec92762 100644 --- a/drivers/media/dvb/frontends/dib3000.h +++ b/drivers/media/dvb/frontends/dib3000.h @@ -30,10 +30,6 @@ struct dib3000_config { /* the demodulator's i2c address */ u8 demod_address; - - /* PLL maintenance and the i2c address of the PLL */ - int (*pll_init)(struct dvb_frontend *fe); - int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params); }; struct dib_fe_xfer_ops diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c index ae589ad..7c6dc7e 100644 --- a/drivers/media/dvb/frontends/dib3000mb.c +++ b/drivers/media/dvb/frontends/dib3000mb.c @@ -60,8 +60,9 @@ static int dib3000mb_set_frontend(struct fe_code_rate_t fe_cr = FEC_NONE; int search_state, seq; - if (tuner && state->config.pll_set) { - state->config.pll_set(fe, fep); + if (tuner && fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, fep); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); deb_setf("bandwidth: "); switch (ofdm->bandwidth) { @@ -386,9 +387,6 @@ static int dib3000mb_fe_init(struct dvb_ wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF); - if (state->config.pll_init) - state->config.pll_init(fe); - return 0; } @@ -707,7 +705,6 @@ struct dvb_frontend* dib3000mb_attach(co /* setup the state */ state->i2c = i2c; memcpy(&state->config,config,sizeof(struct dib3000_config)); - memcpy(&state->ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops)); /* check for the correct demod */ if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM) @@ -717,7 +714,7 @@ struct dvb_frontend* dib3000mb_attach(co goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; /* set the xfer operations */ diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c index 3b303db..6c3be25 100644 --- a/drivers/media/dvb/frontends/dib3000mc.c +++ b/drivers/media/dvb/frontends/dib3000mc.c @@ -462,8 +462,9 @@ static int dib3000mc_set_frontend(struct int search_state,auto_val; u16 val; - if (tuner && state->config.pll_set) { /* initial call from dvb */ - state->config.pll_set(fe,fep); + if (tuner && fe->ops.tuner_ops.set_params) { /* initial call from dvb */ + fe->ops.tuner_ops.set_params(fe, fep); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); state->last_tuned_freq = fep->frequency; // if (!scanboost) { @@ -642,9 +643,6 @@ static int dib3000mc_fe_init(struct dvb_ set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF); - if (state->config.pll_init) - state->config.pll_init(fe); - deb_info("init end\n"); return 0; } @@ -839,7 +837,6 @@ struct dvb_frontend* dib3000mc_attach(co /* setup the state */ state->i2c = i2c; memcpy(&state->config,config,sizeof(struct dib3000_config)); - memcpy(&state->ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops)); /* check for the correct demod */ if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM) @@ -859,7 +856,7 @@ struct dvb_frontend* dib3000mc_attach(co } /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; /* set the xfer operations */ @@ -876,6 +873,7 @@ error: kfree(state); return NULL; } +EXPORT_SYMBOL(dib3000mc_attach); static struct dvb_frontend_ops dib3000mc_ops = { @@ -914,5 +912,3 @@ static struct dvb_frontend_ops dib3000mc MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(dib3000mc_attach); diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 791706e..a189683 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -227,10 +227,10 @@ struct dvb_pll_desc dvb_pll_tua6034 = { EXPORT_SYMBOL(dvb_pll_tua6034); /* Infineon TUA6034 - * used in LG TDVS H061F and LG TDVS H062F + * used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F */ -struct dvb_pll_desc dvb_pll_tdvs_tua6034 = { - .name = "LG/Infineon TUA6034", +struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = { + .name = "LG TDVS-H06xF", .min = 54000000, .max = 863000000, .count = 3, @@ -240,7 +240,7 @@ struct dvb_pll_desc dvb_pll_tdvs_tua6034 { 999999999, 44000000, 62500, 0xce, 0x04 }, }, }; -EXPORT_SYMBOL(dvb_pll_tdvs_tua6034); +EXPORT_SYMBOL(dvb_pll_lg_tdvs_h06xf); /* Philips FMD1216ME * used in Medion Hybrid PCMCIA card and USB Box @@ -419,6 +419,19 @@ struct dvb_pll_desc dvb_pll_thomson_fe66 }; EXPORT_SYMBOL(dvb_pll_thomson_fe6600); +struct dvb_pll_priv { + /* i2c details */ + int pll_i2c_address; + struct i2c_adapter *i2c; + + /* the PLL descriptor */ + struct dvb_pll_desc *pll_desc; + + /* cached frequency/bandwidth */ + u32 frequency; + u32 bandwidth; +}; + /* ----------------------------------------------------------- */ /* code */ @@ -443,7 +456,8 @@ int dvb_pll_configure(struct dvb_pll_des if (debug) printk("pll: %s: freq=%d bw=%d | i=%d/%d\n", desc->name, freq, bandwidth, i, desc->count); - BUG_ON(i == desc->count); + if (i == desc->count) + return -EINVAL; div = (freq + desc->entries[i].offset) / desc->entries[i].stepsize; buf[0] = div >> 8; @@ -462,6 +476,163 @@ int dvb_pll_configure(struct dvb_pll_des } EXPORT_SYMBOL(dvb_pll_configure); +static int dvb_pll_release(struct dvb_frontend *fe) +{ + if (fe->tuner_priv) + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static int dvb_pll_sleep(struct dvb_frontend *fe) +{ + struct dvb_pll_priv *priv = fe->tuner_priv; + u8 buf[4]; + struct i2c_msg msg = + { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) }; + int i; + int result; + + for (i = 0; i < priv->pll_desc->count; i++) { + if (priv->pll_desc->entries[i].limit == 0) + break; + } + if (i == priv->pll_desc->count) + return 0; + + buf[0] = 0; + buf[1] = 0; + buf[2] = priv->pll_desc->entries[i].config; + buf[3] = priv->pll_desc->entries[i].cb; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { + return result; + } + + return 0; +} + +static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct dvb_pll_priv *priv = fe->tuner_priv; + u8 buf[4]; + struct i2c_msg msg = + { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) }; + int result; + u32 div; + int i; + u32 bandwidth = 0; + + if (priv->i2c == NULL) + return -EINVAL; + + // DVBT bandwidth only just now + if (fe->ops.info.type == FE_OFDM) { + bandwidth = params->u.ofdm.bandwidth; + } + + if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0) + return result; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { + return result; + } + + // calculate the frequency we set it to + for (i = 0; i < priv->pll_desc->count; i++) { + if (params->frequency > priv->pll_desc->entries[i].limit) + continue; + break; + } + div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize; + priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset; + priv->bandwidth = bandwidth; + + return 0; +} + +static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) +{ + struct dvb_pll_priv *priv = fe->tuner_priv; + int result; + u32 div; + int i; + u32 bandwidth = 0; + + if (buf_len < 5) + return -EINVAL; + + // DVBT bandwidth only just now + if (fe->ops.info.type == FE_OFDM) { + bandwidth = params->u.ofdm.bandwidth; + } + + if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0) + return result; + buf[0] = priv->pll_i2c_address; + + // calculate the frequency we set it to + for (i = 0; i < priv->pll_desc->count; i++) { + if (params->frequency > priv->pll_desc->entries[i].limit) + continue; + break; + } + div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize; + priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset; + priv->bandwidth = bandwidth; + + return 5; +} + +static int dvb_pll_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct dvb_pll_priv *priv = fe->tuner_priv; + *frequency = priv->frequency; + return 0; +} + +static int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct dvb_pll_priv *priv = fe->tuner_priv; + *bandwidth = priv->bandwidth; + return 0; +} + +static struct dvb_tuner_ops dvb_pll_tuner_ops = { + .release = dvb_pll_release, + .sleep = dvb_pll_sleep, + .set_params = dvb_pll_set_params, + .calc_regs = dvb_pll_calc_regs, + .get_frequency = dvb_pll_get_frequency, + .get_bandwidth = dvb_pll_get_bandwidth, +}; + +int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc) +{ + struct dvb_pll_priv *priv = NULL; + + priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + priv->pll_i2c_address = pll_addr; + priv->i2c = i2c; + priv->pll_desc = desc; + + memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops)); + strncpy(fe->ops.tuner_ops.info.name, desc->name, 128); + fe->ops.tuner_ops.info.frequency_min = desc->min; + fe->ops.tuner_ops.info.frequency_min = desc->max; + + fe->tuner_priv = priv; + return 0; +} +EXPORT_SYMBOL(dvb_pll_attach); + MODULE_DESCRIPTION("dvb pll library"); MODULE_AUTHOR("Gerd Knorr"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h index 2b84617..66361cd 100644 --- a/drivers/media/dvb/frontends/dvb-pll.h +++ b/drivers/media/dvb/frontends/dvb-pll.h @@ -5,6 +5,9 @@ #ifndef __DVB_PLL_H__ #define __DVB_PLL_H__ +#include +#include "dvb_frontend.h" + struct dvb_pll_desc { char *name; u32 min; @@ -31,7 +34,7 @@ extern struct dvb_pll_desc dvb_pll_unkno extern struct dvb_pll_desc dvb_pll_tua6010xs; extern struct dvb_pll_desc dvb_pll_env57h1xd5; extern struct dvb_pll_desc dvb_pll_tua6034; -extern struct dvb_pll_desc dvb_pll_tdvs_tua6034; +extern struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf; extern struct dvb_pll_desc dvb_pll_tda665x; extern struct dvb_pll_desc dvb_pll_fmd1216me; extern struct dvb_pll_desc dvb_pll_tded4; @@ -44,7 +47,18 @@ extern struct dvb_pll_desc dvb_pll_phili extern struct dvb_pll_desc dvb_pll_thomson_fe6600; -int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, +extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, u32 freq, int bandwidth); +/** + * Attach a dvb-pll to the supplied frontend structure. + * + * @param fe Frontend to attach to. + * @param pll_addr i2c address of the PLL (if used). + * @param i2c i2c adapter to use (set to NULL if not used). + * @param desc dvb_pll_desc to use. + * @return 0 on success, nonzero on failure. + */ +extern int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc); + #endif diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c index 645946a..6271b1e 100644 --- a/drivers/media/dvb/frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c @@ -30,7 +30,6 @@ #include "dvb_dummy_fe.h" struct dvb_dummy_fe_state { - struct dvb_frontend_ops ops; struct dvb_frontend frontend; }; @@ -77,6 +76,11 @@ static int dvb_dummy_fe_get_frontend(str static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { + if (fe->ops->tuner_ops->set_params) { + fe->ops->tuner_ops->set_params(fe, p); + if (fe->ops->i2c_gate_ctrl) fe->ops->i2c_gate_ctrl(fe, 0); + } + return 0; } @@ -116,11 +120,8 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_a state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); if (state == NULL) goto error; - /* setup the state */ - memcpy(&state->ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops)); - /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -139,11 +140,8 @@ struct dvb_frontend* dvb_dummy_fe_qpsk_a state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); if (state == NULL) goto error; - /* setup the state */ - memcpy(&state->ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops)); - /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -162,11 +160,8 @@ struct dvb_frontend* dvb_dummy_fe_qam_at state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); if (state == NULL) goto error; - /* setup the state */ - memcpy(&state->ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops)); - /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c new file mode 100644 index 0000000..58c34db --- /dev/null +++ b/drivers/media/dvb/frontends/isl6421.c @@ -0,0 +1,149 @@ +/* + * isl6421.h - driver for lnb supply and control ic ISL6421 + * + * Copyright (C) 2006 Andrew de Quincey + * Copyright (C) 2006 Oliver Endriss + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "isl6421.h" + +struct isl6421 { + u8 config; + u8 override_or; + u8 override_and; + struct i2c_adapter *i2c; + u8 i2c_addr; + void (*release_chain)(struct dvb_frontend* fe); +}; + +static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv; + struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0, + .buf = &isl6421->config, + .len = sizeof(isl6421->config) }; + + isl6421->config &= ~(ISL6421_VSEL1 | ISL6421_EN1); + + switch(voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + isl6421->config |= ISL6421_EN1; + break; + case SEC_VOLTAGE_18: + isl6421->config |= (ISL6421_EN1 | ISL6421_VSEL1); + break; + default: + return -EINVAL; + }; + + isl6421->config |= isl6421->override_or; + isl6421->config &= isl6421->override_and; + + return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) +{ + struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv; + struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0, + .buf = &isl6421->config, + .len = sizeof(isl6421->config) }; + + if (arg) + isl6421->config |= ISL6421_LLC1; + else + isl6421->config &= ~ISL6421_LLC1; + + isl6421->config |= isl6421->override_or; + isl6421->config &= isl6421->override_and; + + return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static void isl6421_release(struct dvb_frontend *fe) +{ + struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv; + + /* power off */ + isl6421_set_voltage(fe, SEC_VOLTAGE_OFF); + + /* free data & call next release routine */ + fe->ops.release = isl6421->release_chain; + kfree(fe->misc_priv); + fe->misc_priv = NULL; + if (fe->ops.release) + fe->ops.release(fe); +} + +int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, + u8 override_set, u8 override_clear) +{ + struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL); + if (!isl6421) + return -ENOMEM; + + /* default configuration */ + isl6421->config = ISL6421_ISEL1; + isl6421->i2c = i2c; + isl6421->i2c_addr = i2c_addr; + fe->misc_priv = isl6421; + + /* bits which should be forced to '1' */ + isl6421->override_or = override_set; + + /* bits which should be forced to '0' */ + isl6421->override_and = ~override_clear; + + /* detect if it is present or not */ + if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) { + kfree(isl6421); + fe->misc_priv = NULL; + return -EIO; + } + + /* install release callback */ + isl6421->release_chain = fe->ops.release; + fe->ops.release = isl6421_release; + + /* override frontend ops */ + fe->ops.set_voltage = isl6421_set_voltage; + fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage; + + return 0; +} +EXPORT_SYMBOL(isl6421_attach); + +MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421"); +MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb/frontends/isl6421.h new file mode 100644 index 0000000..675f80a --- /dev/null +++ b/drivers/media/dvb/frontends/isl6421.h @@ -0,0 +1,46 @@ +/* + * isl6421.h - driver for lnb supply and control ic ISL6421 + * + * Copyright (C) 2006 Andrew de Quincey + * Copyright (C) 2006 Oliver Endriss + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ + +#ifndef _ISL6421_H +#define _ISL6421_H + +#include + +/* system register bits */ +#define ISL6421_OLF1 0x01 +#define ISL6421_EN1 0x02 +#define ISL6421_VSEL1 0x04 +#define ISL6421_LLC1 0x08 +#define ISL6421_ENT1 0x10 +#define ISL6421_ISEL1 0x20 +#define ISL6421_DCL 0x40 + +/* override_set and override_clear control which system register bits (above) to always set & clear */ +extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, + u8 override_set, u8 override_clear); + +#endif diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c index 1c7c912..f3bc82e 100644 --- a/drivers/media/dvb/frontends/l64781.c +++ b/drivers/media/dvb/frontends/l64781.c @@ -32,7 +32,6 @@ #include "l64781.h" struct l64781_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; const struct l64781_config* config; struct dvb_frontend frontend; @@ -141,7 +140,10 @@ static int apply_frontend_param (struct u8 val0x06; int bw = p->bandwidth - BANDWIDTH_8_MHZ; - state->config->pll_set(fe, param); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } if (param->inversion != INVERSION_ON && param->inversion != INVERSION_OFF) @@ -463,8 +465,6 @@ static int l64781_init(struct dvb_fronte /* Everything is two's complement, soft bit and CSI_OUT too */ l64781_writereg (state, 0x1e, 0x09); - if (state->config->pll_init) state->config->pll_init(fe); - /* delay a bit after first init attempt */ if (state->first) { state->first = 0; @@ -508,7 +508,6 @@ struct dvb_frontend* l64781_attach(const /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &l64781_ops, sizeof(struct dvb_frontend_ops)); state->first = 1; /** @@ -554,7 +553,7 @@ struct dvb_frontend* l64781_attach(const } /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &l64781_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; diff --git a/drivers/media/dvb/frontends/l64781.h b/drivers/media/dvb/frontends/l64781.h index 947f65f..83b8bc2 100644 --- a/drivers/media/dvb/frontends/l64781.h +++ b/drivers/media/dvb/frontends/l64781.h @@ -29,10 +29,6 @@ struct l64781_config { /* the demodulator's i2c address */ u8 demod_address; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h new file mode 100644 index 0000000..754d51d --- /dev/null +++ b/drivers/media/dvb/frontends/lg_h06xf.h @@ -0,0 +1,64 @@ +/* + * lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _LG_H06XF_H_ +#define _LG_H06XF_H_ +#include "dvb-pll.h" + +static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap, + struct dvb_frontend_parameters* params) +{ + u8 buf[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + int err; + + dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "lg_h06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + /* Set the Auxiliary Byte. */ + buf[0] = buf[2]; + buf[0] &= ~0x20; + buf[0] |= 0x18; + buf[1] = 0x50; + msg.len = 2; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "lg_h06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + return 0; +} +#endif diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 4691ac5..6e8ad17 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -29,6 +29,7 @@ * DViCO FusionHDTV 5 Lite * DViCO FusionHDTV 5 USB Gold * Air2PC/AirStar 2 ATSC 3rd generation (HD5000) + * pcHDTV HD5500 * * TODO: * signal strength always returns 0. @@ -59,7 +60,6 @@ if (debug) printk(KERN_DEBUG "lgdt330x: struct lgdt330x_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; /* Configuration settings */ const struct lgdt330x_config* config; @@ -399,8 +399,10 @@ static int lgdt330x_set_parameters(struc } /* Tune to the specified frequency */ - if (state->config->pll_set) - state->config->pll_set(fe, param); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } /* Keep track of the new frequency */ /* FIXME this is the wrong way to do this... */ @@ -672,6 +674,7 @@ static int lgdt3303_read_snr(struct dvb_ if (state->current_modulation == VSB_8) { + i2c_read_demod_bytes(state, 0x6e, buf, 5); /* Phase Tracker Mean-Square Error Register for VSB */ noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4]; } else { @@ -721,16 +724,19 @@ struct dvb_frontend* lgdt330x_attach(con /* Setup the state */ state->config = config; state->i2c = i2c; + + /* Create dvb_frontend */ switch (config->demod_chip) { case LGDT3302: - memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops)); + memcpy(&state->frontend.ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops)); break; case LGDT3303: - memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops)); + memcpy(&state->frontend.ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops)); break; default: goto error; } + state->frontend.demodulator_priv = state; /* Verify communication with demod chip */ if (i2c_read_demod_bytes(state, 2, buf, 1)) @@ -739,9 +745,6 @@ struct dvb_frontend* lgdt330x_attach(con state->current_frequency = -1; state->current_modulation = -1; - /* Create dvb_frontend */ - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; return &state->frontend; error: diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h index 2a6529c..bad903c 100644 --- a/drivers/media/dvb/frontends/lgdt330x.h +++ b/drivers/media/dvb/frontends/lgdt330x.h @@ -43,7 +43,6 @@ struct lgdt330x_config /* PLL interface */ int (*pll_rf_set) (struct dvb_frontend* fe, int index); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); /* Need to set device param for start_dma */ int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c new file mode 100644 index 0000000..e933edc --- /dev/null +++ b/drivers/media/dvb/frontends/lnbp21.c @@ -0,0 +1,145 @@ +/* + * lnbp21.h - driver for lnb supply and control ic lnbp21 + * + * Copyright (C) 2006 Oliver Endriss + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "lnbp21.h" + +struct lnbp21 { + u8 config; + u8 override_or; + u8 override_and; + struct i2c_adapter *i2c; + void (*release_chain)(struct dvb_frontend* fe); +}; + +static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + struct i2c_msg msg = { .addr = 0x08, .flags = 0, + .buf = &lnbp21->config, + .len = sizeof(lnbp21->config) }; + + lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN); + + switch(voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + lnbp21->config |= LNBP21_EN; + break; + case SEC_VOLTAGE_18: + lnbp21->config |= (LNBP21_EN | LNBP21_VSEL); + break; + default: + return -EINVAL; + }; + + lnbp21->config |= lnbp21->override_or; + lnbp21->config &= lnbp21->override_and; + + return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + struct i2c_msg msg = { .addr = 0x08, .flags = 0, + .buf = &lnbp21->config, + .len = sizeof(lnbp21->config) }; + + if (arg) + lnbp21->config |= LNBP21_LLC; + else + lnbp21->config &= ~LNBP21_LLC; + + lnbp21->config |= lnbp21->override_or; + lnbp21->config &= lnbp21->override_and; + + return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static void lnbp21_release(struct dvb_frontend *fe) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + + /* LNBP power off */ + lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF); + + /* free data & call next release routine */ + fe->ops.release = lnbp21->release_chain; + kfree(fe->misc_priv); + fe->misc_priv = NULL; + if (fe->ops.release) + fe->ops.release(fe); +} + +int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) +{ + struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL); + if (!lnbp21) + return -ENOMEM; + + /* default configuration */ + lnbp21->config = LNBP21_ISEL; + lnbp21->i2c = i2c; + fe->misc_priv = lnbp21; + + /* bits which should be forced to '1' */ + lnbp21->override_or = override_set; + + /* bits which should be forced to '0' */ + lnbp21->override_and = ~override_clear; + + /* detect if it is present or not */ + if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) { + kfree(lnbp21); + fe->misc_priv = NULL; + return -EIO; + } + + /* install release callback */ + lnbp21->release_chain = fe->ops.release; + fe->ops.release = lnbp21_release; + + /* override frontend ops */ + fe->ops.set_voltage = lnbp21_set_voltage; + fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; + + return 0; +} +EXPORT_SYMBOL(lnbp21_attach); + +MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21"); +MODULE_AUTHOR("Oliver Endriss"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb/frontends/lnbp21.h index 0dcbe61..047a4ab 100644 --- a/drivers/media/dvb/frontends/lnbp21.h +++ b/drivers/media/dvb/frontends/lnbp21.h @@ -27,7 +27,7 @@ #ifndef _LNBP21_H #define _LNBP21_H -/* system register */ +/* system register bits */ #define LNBP21_OLF 0x01 #define LNBP21_OTF 0x02 #define LNBP21_EN 0x04 @@ -37,103 +37,9 @@ #define LNBP21_TEN 0x20 #define LNBP21_ISEL 0x40 #define LNBP21_PCL 0x80 -struct lnbp21 { - u8 config; - u8 override_or; - u8 override_and; - struct i2c_adapter *i2c; - void (*release_chain)(struct dvb_frontend* fe); -}; +#include -static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -{ - struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, - .buf = &lnbp21->config, - .len = sizeof(lnbp21->config) }; - - lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN); - - switch(voltage) { - case SEC_VOLTAGE_OFF: - break; - case SEC_VOLTAGE_13: - lnbp21->config |= LNBP21_EN; - break; - case SEC_VOLTAGE_18: - lnbp21->config |= (LNBP21_EN | LNBP21_VSEL); - break; - default: - return -EINVAL; - }; - - lnbp21->config |= lnbp21->override_or; - lnbp21->config &= lnbp21->override_and; - - return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; -} - -static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) -{ - struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, - .buf = &lnbp21->config, - .len = sizeof(lnbp21->config) }; - - if (arg) - lnbp21->config |= LNBP21_LLC; - else - lnbp21->config &= ~LNBP21_LLC; - - lnbp21->config |= lnbp21->override_or; - lnbp21->config &= lnbp21->override_and; - - return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; -} - -static void lnbp21_exit(struct dvb_frontend *fe) -{ - struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; - - /* LNBP power off */ - lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF); - - /* free data & call next release routine */ - fe->ops->release = lnbp21->release_chain; - kfree(fe->misc_priv); - fe->misc_priv = NULL; - if (fe->ops->release) - fe->ops->release(fe); -} - -static int lnbp21_init(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) -{ - struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL); - - if (!lnbp21) - return -ENOMEM; - - /* default configuration */ - lnbp21->config = LNBP21_ISEL; - - /* bits which should be forced to '1' */ - lnbp21->override_or = override_set; - - /* bits which should be forced to '0' */ - lnbp21->override_and = ~override_clear; - - /* install release callback */ - lnbp21->release_chain = fe->ops->release; - fe->ops->release = lnbp21_exit; - - /* override frontend ops */ - fe->ops->set_voltage = lnbp21_set_voltage; - fe->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; - - lnbp21->i2c = i2c; - fe->misc_priv = lnbp21; - - return lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF); -} +/* override_set and override_clear control which system register bits (above) to always set & clear */ +extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear); #endif diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index d3aea83..1ef8218 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -39,7 +39,6 @@ #include "mt312.h" struct mt312_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; /* configuration settings */ const struct mt312_config* config; struct dvb_frontend frontend; @@ -277,12 +276,6 @@ static int mt312_initfe(struct dvb_front if ((ret = mt312_writereg(state, CS_SW_LIM, 0x69)) < 0) return ret; - if (state->config->pll_init) { - mt312_writereg(state, GPP_CTRL, 0x40); - state->config->pll_init(fe); - mt312_writereg(state, GPP_CTRL, 0x00); - } - return 0; } @@ -477,16 +470,16 @@ static int mt312_set_frontend(struct dvb dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency); - if ((p->frequency < fe->ops->info.frequency_min) - || (p->frequency > fe->ops->info.frequency_max)) + if ((p->frequency < fe->ops.info.frequency_min) + || (p->frequency > fe->ops.info.frequency_max)) return -EINVAL; if ((p->inversion < INVERSION_OFF) || (p->inversion > INVERSION_ON)) return -EINVAL; - if ((p->u.qpsk.symbol_rate < fe->ops->info.symbol_rate_min) - || (p->u.qpsk.symbol_rate > fe->ops->info.symbol_rate_max)) + if ((p->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) + || (p->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) return -EINVAL; if ((p->u.qpsk.fec_inner < FEC_NONE) @@ -529,9 +522,10 @@ static int mt312_set_frontend(struct dvb return -EINVAL; } - mt312_writereg(state, GPP_CTRL, 0x40); - state->config->pll_set(fe, p); - mt312_writereg(state, GPP_CTRL, 0x00); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } /* sr = (u16)(sr * 256.0 / 1000000.0) */ sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625); @@ -578,6 +572,17 @@ static int mt312_get_frontend(struct dvb return 0; } +static int mt312_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct mt312_state* state = fe->demodulator_priv; + + if (enable) { + return mt312_writereg(state, GPP_CTRL, 0x40); + } else { + return mt312_writereg(state, GPP_CTRL, 0x00); + } +} + static int mt312_sleep(struct dvb_frontend* fe) { struct mt312_state *state = fe->demodulator_priv; @@ -633,6 +638,7 @@ static struct dvb_frontend_ops vp310_mt3 .init = mt312_initfe, .sleep = mt312_sleep, + .i2c_gate_ctrl = mt312_i2c_gate_ctrl, .set_frontend = mt312_set_frontend, .get_frontend = mt312_get_frontend, @@ -663,19 +669,22 @@ struct dvb_frontend* vp310_mt312_attach( /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); /* check if the demod is there */ if (mt312_readreg(state, ID, &state->id) < 0) goto error; + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + switch (state->id) { case ID_VP310: - strcpy(state->ops.info.name, "Zarlink VP310 DVB-S"); + strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S"); state->frequency = 90; break; case ID_MT312: - strcpy(state->ops.info.name, "Zarlink MT312 DVB-S"); + strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S"); state->frequency = 60; break; default: @@ -683,9 +692,6 @@ struct dvb_frontend* vp310_mt312_attach( goto error; } - /* create dvb_frontend */ - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; return &state->frontend; error: diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h index 074d844..666a1bd 100644 --- a/drivers/media/dvb/frontends/mt312.h +++ b/drivers/media/dvb/frontends/mt312.h @@ -32,10 +32,6 @@ struct mt312_config { /* the demodulator's i2c address */ u8 demod_address; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config, diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c index aaaec90..5de7376 100644 --- a/drivers/media/dvb/frontends/mt352.c +++ b/drivers/media/dvb/frontends/mt352.c @@ -45,7 +45,6 @@ #include "mt352.h" struct mt352_state { struct i2c_adapter* i2c; struct dvb_frontend frontend; - struct dvb_frontend_ops ops; /* configuration settings */ struct mt352_config config; @@ -286,16 +285,25 @@ static int mt352_set_parameters(struct d mt352_calc_nominal_rate(state, op->bandwidth, buf+4); mt352_calc_input_freq(state, buf+6); - state->config.pll_set(fe, param, buf+8); - mt352_write(fe, buf, sizeof(buf)); if (state->config.no_tuner) { - /* start decoding */ + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + mt352_write(fe, buf, 8); mt352_write(fe, fsm_go, 2); } else { - /* start tuning */ - mt352_write(fe, tuner_go, 2); + if (fe->ops.tuner_ops.calc_regs) { + fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5); + buf[8] <<= 1; + mt352_write(fe, buf, sizeof(buf)); + mt352_write(fe, tuner_go, 2); + } } + return 0; } @@ -541,13 +549,12 @@ struct dvb_frontend* mt352_attach(const /* setup the state */ state->i2c = i2c; memcpy(&state->config,config,sizeof(struct mt352_config)); - memcpy(&state->ops, &mt352_ops, sizeof(struct dvb_frontend_ops)); /* check if the demod is there */ if (mt352_read_register(state, CHIP_ID) != ID_MT352) goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &mt352_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; diff --git a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb/frontends/mt352.h index 03040cd..9e7ff4b 100644 --- a/drivers/media/dvb/frontends/mt352.h +++ b/drivers/media/dvb/frontends/mt352.h @@ -49,12 +49,6 @@ struct mt352_config /* Initialise the demodulator and PLL. Cannot be NULL */ int (*demod_init)(struct dvb_frontend* fe); - - /* PLL setup - fill out the supplied 5 byte buffer with your PLL settings. - * byte0: Set to pll i2c address (nonlinux; left shifted by 1) - * byte1-4: PLL configuration. - */ - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf); }; extern struct dvb_frontend* mt352_attach(const struct mt352_config* config, diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index 9e35353..55671cb 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c @@ -55,7 +55,6 @@ #include "nxt200x.h" struct nxt200x_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; const struct nxt200x_config* config; struct dvb_frontend frontend; @@ -333,17 +332,17 @@ static int nxt200x_writetuner (struct nx dprintk("%s\n", __FUNCTION__); - dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]); + dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]); /* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip. * direct write is required for Philips TUV1236D and ALPS TDHU2 */ switch (state->demod_chip) { case NXT2004: - if (i2c_writebytes(state, state->config->pll_address, data, 4)) + if (i2c_writebytes(state, data[0], data+1, 4)) printk(KERN_WARNING "nxt200x: error writing to tuner\n"); /* wait until we have a lock */ while (count < 20) { - i2c_readbytes(state, state->config->pll_address, &buf, 1); + i2c_readbytes(state, data[0], &buf, 1); if (buf & 0x40) return 0; msleep(100); @@ -361,10 +360,10 @@ static int nxt200x_writetuner (struct nx nxt200x_writebytes(state, 0x34, &buf, 1); /* write actual tuner bytes */ - nxt200x_writebytes(state, 0x36, data, 4); + nxt200x_writebytes(state, 0x36, data+1, 4); /* set tuner i2c address */ - buf = state->config->pll_address; + buf = data[0] << 1; nxt200x_writebytes(state, 0x35, &buf, 1); /* write UC Opmode to begin transfer */ @@ -534,7 +533,7 @@ static int nxt200x_setup_frontend_parame struct dvb_frontend_parameters *p) { struct nxt200x_state* state = fe->demodulator_priv; - u8 buf[4]; + u8 buf[5]; /* stop the micro first */ nxt200x_microcontroller_stop(state); @@ -548,7 +547,9 @@ static int nxt200x_setup_frontend_parame } /* get tuning information */ - dvb_pll_configure(state->config->pll_desc, buf, p->frequency, 0); + if (fe->ops.tuner_ops.calc_regs) { + fe->ops.tuner_ops.calc_regs(fe, p, buf, 5); + } /* set additional params */ switch (p->u.vsb.modulation) { @@ -1159,7 +1160,6 @@ struct dvb_frontend* nxt200x_attach(cons /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops)); state->initialised = 0; /* read card id */ @@ -1198,7 +1198,7 @@ struct dvb_frontend* nxt200x_attach(cons } /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h index 1d9d70b..34d6173 100644 --- a/drivers/media/dvb/frontends/nxt200x.h +++ b/drivers/media/dvb/frontends/nxt200x.h @@ -38,10 +38,6 @@ struct nxt200x_config /* the demodulator's i2c address */ u8 demod_address; - /* tuner information */ - u8 pll_address; - struct dvb_pll_desc *pll_desc; - /* used to set pll input */ int (*set_pll_input)(u8* buf, int input); diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c index a16eeba..d313d7d 100644 --- a/drivers/media/dvb/frontends/nxt6000.c +++ b/drivers/media/dvb/frontends/nxt6000.c @@ -33,7 +33,6 @@ #include "nxt6000.h" struct nxt6000_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; /* configuration settings */ const struct nxt6000_config* config; struct dvb_frontend frontend; @@ -207,12 +206,6 @@ static void nxt6000_setup(struct dvb_fro nxt6000_writereg(state, SUB_DIAG_MODE_SEL, 0); nxt6000_writereg(state, TS_FORMAT, 0); - - if (state->config->pll_init) { - nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ - state->config->pll_init(fe); - nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ - } } static void nxt6000_dump_status(struct nxt6000_state *state) @@ -469,9 +462,10 @@ static int nxt6000_set_frontend(struct d struct nxt6000_state* state = fe->demodulator_priv; int result; - nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ - state->config->pll_set(fe, param); - nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */ + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } if ((result = nxt6000_set_bandwidth(state, param->u.ofdm.bandwidth)) < 0) return result; @@ -532,6 +526,17 @@ static int nxt6000_fe_get_tune_settings( return 0; } +static int nxt6000_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct nxt6000_state* state = fe->demodulator_priv; + + if (enable) { + return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); + } else { + return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00); + } +} + static struct dvb_frontend_ops nxt6000_ops; struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, @@ -546,13 +551,12 @@ struct dvb_frontend* nxt6000_attach(cons /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops)); /* check if the demod is there */ if (nxt6000_readreg(state, OFDM_MSC_REV) != NXT6000ASICDEVICE) goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -584,6 +588,7 @@ static struct dvb_frontend_ops nxt6000_o .release = nxt6000_release, .init = nxt6000_init, + .i2c_gate_ctrl = nxt6000_i2c_gate_ctrl, .get_tune_settings = nxt6000_fe_get_tune_settings, diff --git a/drivers/media/dvb/frontends/nxt6000.h b/drivers/media/dvb/frontends/nxt6000.h index b7d9bea..117031d 100644 --- a/drivers/media/dvb/frontends/nxt6000.h +++ b/drivers/media/dvb/frontends/nxt6000.h @@ -31,10 +31,6 @@ struct nxt6000_config /* should clock inversion be used? */ u8 clock_inversion:1; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c index 80e0f28..d20ab30 100644 --- a/drivers/media/dvb/frontends/or51132.c +++ b/drivers/media/dvb/frontends/or51132.c @@ -54,7 +54,6 @@ #define dprintk(args...) \ struct or51132_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; /* Configuration settings */ const struct or51132_config* config; @@ -106,9 +105,8 @@ static int or51132_load_firmware (struct { struct or51132_state* state = fe->demodulator_priv; static u8 run_buf[] = {0x7F,0x01}; - static u8 get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00}; - u8 rec_buf[14]; - u8 cmd_buf[14]; + u8 rec_buf[8]; + u8 cmd_buf[3]; u32 firmwareAsize, firmwareBsize; int i,ret; @@ -157,7 +155,6 @@ static int or51132_load_firmware (struct cmd_buf[0] = 0x10; cmd_buf[1] = 0x10; cmd_buf[2] = 0x00; - cmd_buf[3] = 0x00; msleep(20); /* 20ms */ if ((ret = i2c_writebytes(state,state->config->demod_address, cmd_buf,3))) { @@ -167,8 +164,6 @@ static int or51132_load_firmware (struct cmd_buf[0] = 0x04; cmd_buf[1] = 0x17; - cmd_buf[2] = 0x00; - cmd_buf[3] = 0x00; msleep(20); /* 20ms */ if ((ret = i2c_writebytes(state,state->config->demod_address, cmd_buf,2))) { @@ -178,8 +173,6 @@ static int or51132_load_firmware (struct cmd_buf[0] = 0x00; cmd_buf[1] = 0x00; - cmd_buf[2] = 0x00; - cmd_buf[3] = 0x00; msleep(20); /* 20ms */ if ((ret = i2c_writebytes(state,state->config->demod_address, cmd_buf,2))) { @@ -189,7 +182,11 @@ static int or51132_load_firmware (struct for(i=0;i<4;i++) { msleep(20); /* 20ms */ - get_ver_buf[4] = i+1; + /* Once upon a time, this command might have had something + to do with getting the firmware version, but it's + not used anymore: + {0x04,0x00,0x30,0x00,i+1} */ + /* Read 8 bytes, two bytes at a time */ if ((ret = i2c_readbytes(state,state->config->demod_address, &rec_buf[i*2],2))) { printk(KERN_WARNING @@ -208,7 +205,6 @@ static int or51132_load_firmware (struct cmd_buf[0] = 0x10; cmd_buf[1] = 0x00; cmd_buf[2] = 0x00; - cmd_buf[3] = 0x00; msleep(20); /* 20ms */ if ((ret = i2c_writebytes(state,state->config->demod_address, cmd_buf,3))) { @@ -243,7 +239,7 @@ static int or51132_sleep(struct dvb_fron static int or51132_setmode(struct dvb_frontend* fe) { struct or51132_state* state = fe->demodulator_priv; - unsigned char cmd_buf[4]; + unsigned char cmd_buf[3]; dprintk("setmode %d\n",(int)state->current_modulation); /* set operation mode in Receiver 1 register; */ @@ -263,7 +259,6 @@ static int or51132_setmode(struct dvb_fr default: printk("setmode:Modulation set to unsupported value\n"); }; - cmd_buf[3] = 0x00; if (i2c_writebytes(state,state->config->demod_address, cmd_buf,3)) { printk(KERN_WARNING "or51132: set_mode error 1\n"); @@ -301,7 +296,6 @@ static int or51132_setmode(struct dvb_fr default: printk("setmode: Modulation set to unsupported value\n"); }; - cmd_buf[3] = 0x00; msleep(20); /* 20ms */ if (i2c_writebytes(state,state->config->demod_address, cmd_buf,3)) { @@ -313,52 +307,65 @@ static int or51132_setmode(struct dvb_fr return 0; } +/* Some modulations use the same firmware. This classifies modulations + by the firmware they use. */ +#define MOD_FWCLASS_UNKNOWN 0 +#define MOD_FWCLASS_VSB 1 +#define MOD_FWCLASS_QAM 2 +static int modulation_fw_class(fe_modulation_t modulation) +{ + switch(modulation) { + case VSB_8: + return MOD_FWCLASS_VSB; + case QAM_AUTO: + case QAM_64: + case QAM_256: + return MOD_FWCLASS_QAM; + default: + return MOD_FWCLASS_UNKNOWN; + } +} + static int or51132_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *param) { int ret; - u8 buf[4]; struct or51132_state* state = fe->demodulator_priv; const struct firmware *fw; - - /* Change only if we are actually changing the modulation */ - if (state->current_modulation != param->u.vsb.modulation) { - switch(param->u.vsb.modulation) { - case VSB_8: + const char *fwname; + int clock_mode; + + /* Upload new firmware only if we need a different one */ + if (modulation_fw_class(state->current_modulation) != + modulation_fw_class(param->u.vsb.modulation)) { + switch(modulation_fw_class(param->u.vsb.modulation)) { + case MOD_FWCLASS_VSB: dprintk("set_parameters VSB MODE\n"); - printk("or51132: Waiting for firmware upload(%s)...\n", - OR51132_VSB_FIRMWARE); - ret = request_firmware(&fw, OR51132_VSB_FIRMWARE, - &state->i2c->dev); - if (ret){ - printk(KERN_WARNING "or51132: No firmware up" - "loaded(timeout or file not found?)\n"); - return ret; - } + fwname = OR51132_VSB_FIRMWARE; + /* Set non-punctured clock for VSB */ - state->config->set_ts_params(fe, 0); + clock_mode = 0; break; - case QAM_AUTO: - case QAM_64: - case QAM_256: + case MOD_FWCLASS_QAM: dprintk("set_parameters QAM MODE\n"); - printk("or51132: Waiting for firmware upload(%s)...\n", - OR51132_QAM_FIRMWARE); - ret = request_firmware(&fw, OR51132_QAM_FIRMWARE, - &state->i2c->dev); - if (ret){ - printk(KERN_WARNING "or51132: No firmware up" - "loaded(timeout or file not found?)\n"); - return ret; - } + fwname = OR51132_QAM_FIRMWARE; + /* Set punctured clock for QAM */ - state->config->set_ts_params(fe, 1); + clock_mode = 1; break; default: - printk("or51132:Modulation type(%d) UNSUPPORTED\n", + printk("or51132: Modulation type(%d) UNSUPPORTED\n", param->u.vsb.modulation); return -1; - }; + } + printk("or51132: Waiting for firmware upload(%s)...\n", + fwname); + ret = request_firmware(&fw, fwname, &state->i2c->dev); + if (ret) { + printk(KERN_WARNING "or51132: No firmware up" + "loaded(timeout or file not found?)\n"); + return ret; + } ret = or51132_load_firmware(fe, fw); release_firmware(fw); if (ret) { @@ -367,18 +374,18 @@ static int or51132_set_parameters(struct return ret; } printk("or51132: Firmware upload complete.\n"); - + state->config->set_ts_params(fe, clock_mode); + } + /* Change only if we are actually changing the modulation */ + if (state->current_modulation != param->u.vsb.modulation) { state->current_modulation = param->u.vsb.modulation; or51132_setmode(fe); } - dvb_pll_configure(state->config->pll_desc, buf, - param->frequency, 0); - dprintk("set_parameters tuner bytes: 0x%02x 0x%02x " - "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]); - if (i2c_writebytes(state, state->config->pll_address ,buf, 4)) - printk(KERN_WARNING "or51132: set_parameters error " - "writing to tuner\n"); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } /* Set to current mode */ or51132_setmode(fe); @@ -388,6 +395,44 @@ static int or51132_set_parameters(struct return 0; } +static int or51132_get_parameters(struct dvb_frontend* fe, + struct dvb_frontend_parameters *param) +{ + struct or51132_state* state = fe->demodulator_priv; + u8 buf[2]; + + /* Receiver Status */ + buf[0]=0x04; + buf[1]=0x00; + msleep(30); /* 30ms */ + if (i2c_writebytes(state,state->config->demod_address,buf,2)) { + printk(KERN_WARNING "or51132: get_parameters write error\n"); + return -EREMOTEIO; + } + msleep(30); /* 30ms */ + if (i2c_readbytes(state,state->config->demod_address,buf,2)) { + printk(KERN_WARNING "or51132: get_parameters read error\n"); + return -EREMOTEIO; + } + switch(buf[0]) { + case 0x06: param->u.vsb.modulation = VSB_8; break; + case 0x43: param->u.vsb.modulation = QAM_64; break; + case 0x45: param->u.vsb.modulation = QAM_256; break; + default: + printk(KERN_WARNING "or51132: unknown status 0x%02x\n", + buf[0]); + return -EREMOTEIO; + } + + /* FIXME: Read frequency from frontend, take AFC into account */ + param->frequency = state->current_frequency; + + /* FIXME: How to read inversion setting? Receiver 6 register? */ + param->inversion = INVERSION_AUTO; + + return 0; +} + static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status) { struct or51132_state* state = fe->demodulator_priv; @@ -572,12 +617,11 @@ struct dvb_frontend* or51132_attach(cons /* Setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &or51132_ops, sizeof(struct dvb_frontend_ops)); state->current_frequency = -1; state->current_modulation = -1; /* Create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -590,7 +634,7 @@ static struct dvb_frontend_ops or51132_o .info = { .name = "Oren OR51132 VSB/QAM Frontend", - .type = FE_ATSC, + .type = FE_ATSC, .frequency_min = 44000000, .frequency_max = 958000000, .frequency_stepsize = 166666, @@ -606,6 +650,7 @@ static struct dvb_frontend_ops or51132_o .sleep = or51132_sleep, .set_frontend = or51132_set_parameters, + .get_frontend = or51132_get_parameters, .get_tune_settings = or51132_get_tune_settings, .read_status = or51132_read_status, diff --git a/drivers/media/dvb/frontends/or51132.h b/drivers/media/dvb/frontends/or51132.h index 622cdd1..8965888 100644 --- a/drivers/media/dvb/frontends/or51132.h +++ b/drivers/media/dvb/frontends/or51132.h @@ -29,8 +29,6 @@ struct or51132_config { /* The demodulator's i2c address */ u8 demod_address; - u8 pll_address; - struct dvb_pll_desc *pll_desc; /* Need to set device param for start_dma */ int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c index 7c3aed1..26bed61 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb/frontends/or51211.c @@ -54,7 +54,6 @@ static u8 cmd_buf[] = {0x04,0x01,0x50,0x struct or51211_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; /* Configuration settings */ const struct or51211_config* config; @@ -585,12 +584,11 @@ struct dvb_frontend* or51211_attach(cons /* Setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &or51211_ops, sizeof(struct dvb_frontend_ops)); state->initialized = 0; state->current_frequency = 0; /* Create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &or51211_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index d694775..2c2c344 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c @@ -38,7 +38,6 @@ #define TONE_FREQ 22000 struct s5h1420_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; const struct s5h1420_config* config; struct dvb_frontend frontend; @@ -584,7 +583,6 @@ static int s5h1420_set_frontend(struct d struct s5h1420_state* state = fe->demodulator_priv; int frequency_delta; struct dvb_frontend_tune_settings fesettings; - u32 tmp; /* check if we should do a fast-tune */ memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters)); @@ -596,10 +594,17 @@ static int s5h1420_set_frontend(struct d (state->fec_inner == p->u.qpsk.fec_inner) && (state->symbol_rate == p->u.qpsk.symbol_rate)) { - if (state->config->pll_set) { - s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1); - state->config->pll_set(fe, p, &tmp); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } + if (fe->ops.tuner_ops.get_frequency) { + u32 tmp; + fe->ops.tuner_ops.get_frequency(fe, &tmp); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); s5h1420_setfreqoffset(state, p->frequency - tmp); + } else { + s5h1420_setfreqoffset(state, 0); } return 0; } @@ -646,9 +651,9 @@ static int s5h1420_set_frontend(struct d s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1); /* set tuner PLL */ - if (state->config->pll_set) { - s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1); - state->config->pll_set(fe, p, &tmp); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); s5h1420_setfreqoffset(state, 0); } @@ -708,6 +713,17 @@ static int s5h1420_get_tune_settings(str return 0; } +static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct s5h1420_state* state = fe->demodulator_priv; + + if (enable) { + return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1); + } else { + return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe); + } +} + static int s5h1420_init (struct dvb_frontend* fe) { struct s5h1420_state* state = fe->demodulator_priv; @@ -717,13 +733,6 @@ static int s5h1420_init (struct dvb_fron msleep(10); s5h1420_reset(state); - /* init PLL */ - if (state->config->pll_init) { - s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1); - state->config->pll_init(fe); - s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe); - } - return 0; } @@ -756,7 +765,6 @@ struct dvb_frontend* s5h1420_attach(cons /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops)); state->postlocked = 0; state->fclk = 88000000; state->tunedfreq = 0; @@ -769,7 +777,7 @@ struct dvb_frontend* s5h1420_attach(cons goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -800,6 +808,7 @@ static struct dvb_frontend_ops s5h1420_o .init = s5h1420_init, .sleep = s5h1420_sleep, + .i2c_gate_ctrl = s5h1420_i2c_gate_ctrl, .set_frontend = s5h1420_set_frontend, .get_frontend = s5h1420_get_frontend, diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h index 73296f1..4e39015 100644 --- a/drivers/media/dvb/frontends/s5h1420.h +++ b/drivers/media/dvb/frontends/s5h1420.h @@ -32,10 +32,6 @@ struct s5h1420_config /* does the inversion require inversion? */ u8 invert:1; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout); }; extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c index 73829e6..44ec5b9 100644 --- a/drivers/media/dvb/frontends/sp8870.c +++ b/drivers/media/dvb/frontends/sp8870.c @@ -44,8 +44,6 @@ struct sp8870_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; - const struct sp8870_config* config; struct dvb_frontend frontend; @@ -262,9 +260,10 @@ static int sp8870_set_frontend_parameter sp8870_microcontroller_stop(state); // set tuner parameters - sp8870_writereg(state, 0x206, 0x001); - state->config->pll_set(fe, p); - sp8870_writereg(state, 0x206, 0x000); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } // sample rate correction bit [23..17] sp8870_writereg(state, 0x0319, 0x000A); @@ -349,13 +348,6 @@ static int sp8870_init (struct dvb_front sp8870_writereg(state, 0x0D00, 0x010); sp8870_writereg(state, 0x0D01, 0x000); - /* setup PLL */ - if (state->config->pll_init) { - sp8870_writereg(state, 0x206, 0x001); - state->config->pll_init(fe); - sp8870_writereg(state, 0x206, 0x000); - } - return 0; } @@ -541,6 +533,17 @@ static int sp8870_get_tune_settings(stru return 0; } +static int sp8870_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct sp8870_state* state = fe->demodulator_priv; + + if (enable) { + return sp8870_writereg(state, 0x206, 0x001); + } else { + return sp8870_writereg(state, 0x206, 0x000); + } +} + static void sp8870_release(struct dvb_frontend* fe) { struct sp8870_state* state = fe->demodulator_priv; @@ -561,14 +564,13 @@ struct dvb_frontend* sp8870_attach(const /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &sp8870_ops, sizeof(struct dvb_frontend_ops)); state->initialised = 0; /* check if the demod is there */ if (sp8870_readreg(state, 0x0200) < 0) goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &sp8870_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -597,6 +599,7 @@ static struct dvb_frontend_ops sp8870_op .init = sp8870_init, .sleep = sp8870_sleep, + .i2c_gate_ctrl = sp8870_i2c_gate_ctrl, .set_frontend = sp8870_set_frontend, .get_tune_settings = sp8870_get_tune_settings, diff --git a/drivers/media/dvb/frontends/sp8870.h b/drivers/media/dvb/frontends/sp8870.h index f3b555d..93afbb9 100644 --- a/drivers/media/dvb/frontends/sp8870.h +++ b/drivers/media/dvb/frontends/sp8870.h @@ -31,10 +31,6 @@ struct sp8870_config /* the demodulator's i2c address */ u8 demod_address; - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); - /* request firmware for device */ int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c index eb8a602..b0a2b02 100644 --- a/drivers/media/dvb/frontends/sp887x.c +++ b/drivers/media/dvb/frontends/sp887x.c @@ -24,7 +24,6 @@ #include "sp887x.h" struct sp887x_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; const struct sp887x_config* config; struct dvb_frontend frontend; @@ -208,15 +207,6 @@ static int sp887x_initial_setup (struct /* bit 0x010: enable data valid signal */ sp887x_writereg(state, 0xd00, 0x010); sp887x_writereg(state, 0x0d1, 0x000); - - /* setup the PLL */ - if (state->config->pll_init) { - sp887x_writereg(state, 0x206, 0x001); - state->config->pll_init(fe); - sp887x_writereg(state, 0x206, 0x000); - } - - printk ("done.\n"); return 0; }; @@ -362,9 +352,16 @@ static int sp887x_setup_frontend_paramet sp887x_microcontroller_stop(state); /* setup the PLL */ - sp887x_writereg(state, 0x206, 0x001); - actual_freq = state->config->pll_set(fe, p); - sp887x_writereg(state, 0x206, 0x000); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } + if (fe->ops.tuner_ops.get_frequency) { + fe->ops.tuner_ops.get_frequency(fe, &actual_freq); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } else { + actual_freq = p->frequency; + } /* read status reg in order to clear demodulator_priv; + + if (enable) { + return sp887x_writereg(state, 0x206, 0x001); + } else { + return sp887x_writereg(state, 0x206, 0x000); + } +} + static int sp887x_sleep(struct dvb_frontend* fe) { struct sp887x_state* state = fe->demodulator_priv; @@ -555,14 +563,13 @@ struct dvb_frontend* sp887x_attach(const /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &sp887x_ops, sizeof(struct dvb_frontend_ops)); state->initialised = 0; /* check if the demod is there */ if (sp887x_readreg(state, 0x0200) < 0) goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &sp887x_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -589,6 +596,7 @@ static struct dvb_frontend_ops sp887x_op .init = sp887x_init, .sleep = sp887x_sleep, + .i2c_gate_ctrl = sp887x_i2c_gate_ctrl, .set_frontend = sp887x_setup_frontend_parameters, .get_tune_settings = sp887x_get_tune_settings, diff --git a/drivers/media/dvb/frontends/sp887x.h b/drivers/media/dvb/frontends/sp887x.h index 6a05d8f..c44b0eb 100644 --- a/drivers/media/dvb/frontends/sp887x.h +++ b/drivers/media/dvb/frontends/sp887x.h @@ -13,12 +13,6 @@ struct sp887x_config /* the demodulator's i2c address */ u8 demod_address; - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - - /* this should return the actual frequency tuned to */ - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); - /* request firmware for device */ int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c index eb15676..1ca6424 100644 --- a/drivers/media/dvb/frontends/stv0297.c +++ b/drivers/media/dvb/frontends/stv0297.c @@ -32,7 +32,6 @@ #include "stv0297.h" struct stv0297_state { struct i2c_adapter *i2c; - struct dvb_frontend_ops ops; const struct stv0297_config *config; struct dvb_frontend frontend; @@ -68,19 +67,25 @@ static int stv0297_readreg(struct stv029 int ret; u8 b0[] = { reg }; u8 b1[] = { 0 }; - struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = - 1}, - {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1} - }; + struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1}, + {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1} + }; // this device needs a STOP between the register and data - if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret); - return -1; - } - if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret); - return -1; + if (state->config->stop_during_read) { + if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) { + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret); + return -1; + } + if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) { + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret); + return -1; + } + } else { + if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) { + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret); + return -1; + } } return b1[0]; @@ -107,13 +112,20 @@ static int stv0297_readregs(struct stv02 }; // this device needs a STOP between the register and data - if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret); - return -1; - } - if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) { - dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret); - return -1; + if (state->config->stop_during_read) { + if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) { + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret); + return -1; + } + if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) { + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret); + return -1; + } + } else { + if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) { + dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret); + return -1; + } } return 0; @@ -276,12 +288,14 @@ static int stv0297_set_inversion(struct return 0; } -int stv0297_enable_plli2c(struct dvb_frontend *fe) +static int stv0297_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) { struct stv0297_state *state = fe->demodulator_priv; - stv0297_writereg(state, 0x87, 0x78); - stv0297_writereg(state, 0x86, 0xc8); + if (enable) { + stv0297_writereg(state, 0x87, 0x78); + stv0297_writereg(state, 0x86, 0xc8); + } return 0; } @@ -296,9 +310,6 @@ static int stv0297_init(struct dvb_front stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]); msleep(200); - if (state->config->pll_init) - state->config->pll_init(fe); - return 0; } @@ -389,7 +400,7 @@ static int stv0297_set_frontend(struct d case QAM_32: case QAM_64: delay = 100; - sweeprate = 1500; + sweeprate = 1000; break; case QAM_128: @@ -421,7 +432,10 @@ static int stv0297_set_frontend(struct d } stv0297_init(fe); - state->config->pll_set(fe, p); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } /* clear software interrupts */ stv0297_writereg(state, 0x82, 0x0); @@ -634,7 +648,6 @@ struct dvb_frontend *stv0297_attach(cons /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops)); state->base_freq = 0; /* check if the demod is there */ @@ -642,7 +655,7 @@ struct dvb_frontend *stv0297_attach(cons goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &stv0297_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -668,6 +681,7 @@ static struct dvb_frontend_ops stv0297_o .init = stv0297_init, .sleep = stv0297_sleep, + .i2c_gate_ctrl = stv0297_i2c_gate_ctrl, .set_frontend = stv0297_set_frontend, .get_frontend = stv0297_get_frontend, @@ -684,4 +698,3 @@ MODULE_AUTHOR("Dennis Noermann and Andre MODULE_LICENSE("GPL"); EXPORT_SYMBOL(stv0297_attach); -EXPORT_SYMBOL(stv0297_enable_plli2c); diff --git a/drivers/media/dvb/frontends/stv0297.h b/drivers/media/dvb/frontends/stv0297.h index 9e53f01..1da5384 100644 --- a/drivers/media/dvb/frontends/stv0297.h +++ b/drivers/media/dvb/frontends/stv0297.h @@ -38,13 +38,11 @@ struct stv0297_config /* does the "inversion" need inverted? */ u8 invert:1; - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); + /* set to 1 if the device requires an i2c STOP during reading */ + u8 stop_during_read:1; }; extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, struct i2c_adapter* i2c); -extern int stv0297_enable_plli2c(struct dvb_frontend* fe); #endif // STV0297_H diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 5bcd00f..96648a7 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c @@ -56,7 +56,6 @@ #include "stv0299.h" struct stv0299_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; const struct stv0299_config* config; struct dvb_frontend frontend; @@ -131,13 +130,6 @@ static int stv0299_readregs (struct stv0 return ret == 2 ? 0 : ret; } -int stv0299_enable_plli2c (struct dvb_frontend* fe) -{ - struct stv0299_state* state = fe->demodulator_priv; - - return stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ -} - static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec) { dprintk ("%s\n", __FUNCTION__); @@ -457,12 +449,6 @@ static int stv0299_init (struct dvb_fron for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2) stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]); - if (state->config->pll_init) { - stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ - state->config->pll_init(fe, state->i2c); - stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ - } - return 0; } @@ -560,9 +546,10 @@ static int stv0299_set_frontend(struct d if (state->config->invert) invval = (~invval) & 1; stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval); - stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ - state->config->pll_set(fe, state->i2c, p); - stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */ + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } stv0299_set_FEC (state, p->u.qpsk.fec_inner); stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate); @@ -611,6 +598,19 @@ static int stv0299_sleep(struct dvb_fron return 0; } +static int stv0299_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct stv0299_state* state = fe->demodulator_priv; + + if (enable) { + stv0299_writeregI(state, 0x05, 0xb5); + } else { + stv0299_writeregI(state, 0x05, 0x35); + } + udelay(1); + return 0; +} + static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { struct stv0299_state* state = fe->demodulator_priv; @@ -647,7 +647,6 @@ struct dvb_frontend* stv0299_attach(cons /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &stv0299_ops, sizeof(struct dvb_frontend_ops)); state->initialised = 0; state->tuner_frequency = 0; state->symbol_rate = 0; @@ -664,7 +663,7 @@ struct dvb_frontend* stv0299_attach(cons if (id != 0xa1 && id != 0x80) goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &stv0299_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -695,6 +694,7 @@ static struct dvb_frontend_ops stv0299_o .init = stv0299_init, .sleep = stv0299_sleep, + .i2c_gate_ctrl = stv0299_i2c_gate_ctrl, .set_frontend = stv0299_set_frontend, .get_frontend = stv0299_get_frontend, @@ -721,9 +721,8 @@ MODULE_PARM_DESC(debug, "Turn on/off fro MODULE_DESCRIPTION("ST STV0299 DVB Demodulator driver"); MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, " - "Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy"); + "Andreas Oberritter, Andrew de Quincey, Kenneth Aafly"); MODULE_LICENSE("GPL"); -EXPORT_SYMBOL(stv0299_enable_plli2c); EXPORT_SYMBOL(stv0299_writereg); EXPORT_SYMBOL(stv0299_attach); diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h index 32c87b4..1504828 100644 --- a/drivers/media/dvb/frontends/stv0299.h +++ b/drivers/media/dvb/frontends/stv0299.h @@ -87,14 +87,9 @@ struct stv0299_config /* Set the symbol rate */ int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio); - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend *fe, struct i2c_adapter *i2c); - int (*pll_set)(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params); }; extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data); -extern int stv0299_enable_plli2c (struct dvb_frontend* fe); extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, struct i2c_adapter* i2c); diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 21255ca..e83ff21 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -36,7 +36,6 @@ #include "tda10021.h" struct tda10021_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; /* configuration settings */ const struct tda10021_config* config; struct dvb_frontend frontend; @@ -90,6 +89,14 @@ static int tda10021_writereg (struct tda return (ret != 1) ? -EREMOTEIO : 0; } +int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data) +{ + struct tda10021_state* state = fe->demodulator_priv; + + return tda10021_writereg(state, reg, data); +} +EXPORT_SYMBOL(tda10021_write_byte); + static u8 tda10021_readreg (struct tda10021_state* state, u8 reg) { u8 b0 [] = { reg }; @@ -225,13 +232,6 @@ static int tda10021_init (struct dvb_fro //Activate PLL tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef); - - if (state->config->pll_init) { - lock_tuner(state); - state->config->pll_init(fe); - unlock_tuner(state); - } - return 0; } @@ -259,9 +259,10 @@ static int tda10021_set_parameters (stru //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate); - lock_tuner(state); - state->config->pll_set(fe, p); - unlock_tuner(state); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } tda10021_set_symbolrate (state, p->u.qam.symbol_rate); tda10021_writereg (state, 0x34, state->pwm); @@ -376,6 +377,18 @@ static int tda10021_get_frontend(struct return 0; } +static int tda10021_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct tda10021_state* state = fe->demodulator_priv; + + if (enable) { + lock_tuner(state); + } else { + unlock_tuner(state); + } + return 0; +} + static int tda10021_sleep(struct dvb_frontend* fe) { struct tda10021_state* state = fe->demodulator_priv; @@ -407,7 +420,6 @@ struct dvb_frontend* tda10021_attach(con /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &tda10021_ops, sizeof(struct dvb_frontend_ops)); state->pwm = pwm; state->reg0 = tda10021_inittab[0]; @@ -415,7 +427,7 @@ struct dvb_frontend* tda10021_attach(con if ((tda10021_readreg(state, 0x1a) & 0xf0) != 0x70) goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &tda10021_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -448,6 +460,7 @@ #if 0 .init = tda10021_init, .sleep = tda10021_sleep, + .i2c_gate_ctrl = tda10021_i2c_gate_ctrl, .set_frontend = tda10021_set_parameters, .get_frontend = tda10021_get_frontend, diff --git a/drivers/media/dvb/frontends/tda10021.h b/drivers/media/dvb/frontends/tda10021.h index 53be939..b1df425 100644 --- a/drivers/media/dvb/frontends/tda10021.h +++ b/drivers/media/dvb/frontends/tda10021.h @@ -30,13 +30,11 @@ struct tda10021_config { /* the demodulator's i2c address */ u8 demod_address; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config, struct i2c_adapter* i2c, u8 pwm); +extern int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data); + #endif // TDA10021_H diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index b83dafa..59a2ed6 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -47,7 +47,6 @@ enum tda1004x_demod { struct tda1004x_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; const struct tda1004x_config* config; struct dvb_frontend frontend; @@ -600,13 +599,6 @@ static int tda10045_init(struct dvb_fron tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC - // Init the PLL - if (state->config->pll_init) { - tda1004x_enable_tuner_i2c(state); - state->config->pll_init(fe); - tda1004x_disable_tuner_i2c(state); - } - // tda setup tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream @@ -635,16 +627,6 @@ static int tda10046_init(struct dvb_fron return -EIO; } - // Init the tuner PLL - if (state->config->pll_init) { - tda1004x_enable_tuner_i2c(state); - if (state->config->pll_init(fe)) { - printk(KERN_ERR "tda1004x: pll init failed\n"); - return -EIO; - } - tda1004x_disable_tuner_i2c(state); - } - // tda setup tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream @@ -712,12 +694,10 @@ static int tda1004x_set_fe(struct dvb_fr } // set frequency - tda1004x_enable_tuner_i2c(state); - if (state->config->pll_set(fe, fe_params)) { - printk(KERN_ERR "tda1004x: pll set failed\n"); - return -EIO; + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, fe_params); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); } - tda1004x_disable_tuner_i2c(state); // Hardcoded to use auto as much as possible on the TDA10045 as it // is very unreliable if AUTO mode is _not_ used. @@ -1183,16 +1163,6 @@ static int tda1004x_sleep(struct dvb_fro break; case TDA1004X_DEMOD_TDA10046: - if (state->config->pll_sleep != NULL) { - tda1004x_enable_tuner_i2c(state); - state->config->pll_sleep(fe); - if (state->config->if_freq != TDA10046_FREQ_052) { - /* special hack for Philips EUROPA Based boards: - * keep the I2c bridge open for tuner access in analog mode - */ - tda1004x_disable_tuner_i2c(state); - } - } /* set outputs to tristate */ tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff); tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1); @@ -1202,6 +1172,17 @@ static int tda1004x_sleep(struct dvb_fro return 0; } +static int tda1004x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct tda1004x_state* state = fe->demodulator_priv; + + if (enable) { + return tda1004x_enable_tuner_i2c(state); + } else { + return tda1004x_disable_tuner_i2c(state); + } +} + static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings) { fesettings->min_delay_ms = 800; @@ -1235,6 +1216,7 @@ static struct dvb_frontend_ops tda10045_ .init = tda10045_init, .sleep = tda1004x_sleep, + .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl, .set_frontend = tda1004x_set_fe, .get_frontend = tda1004x_get_fe, @@ -1260,7 +1242,6 @@ struct dvb_frontend* tda10045_attach(con /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops)); state->demod_type = TDA1004X_DEMOD_TDA10045; /* check if the demod is there */ @@ -1270,7 +1251,7 @@ struct dvb_frontend* tda10045_attach(con } /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &tda10045_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; } @@ -1293,6 +1274,7 @@ static struct dvb_frontend_ops tda10046_ .init = tda10046_init, .sleep = tda1004x_sleep, + .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl, .set_frontend = tda1004x_set_fe, .get_frontend = tda1004x_get_fe, @@ -1318,7 +1300,6 @@ struct dvb_frontend* tda10046_attach(con /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops)); state->demod_type = TDA1004X_DEMOD_TDA10046; /* check if the demod is there */ @@ -1328,7 +1309,7 @@ struct dvb_frontend* tda10046_attach(con } /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &tda10046_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; } diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index cc0c4af..b877b23 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h @@ -66,11 +66,6 @@ struct tda1004x_config /* AGC configuration */ enum tda10046_agc agc_config; - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - void (*pll_sleep)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); - /* request firmware for device */ /* set this to NULL if the card has a firmware EEPROM */ int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c index 91baa9c..3aa45eb 100644 --- a/drivers/media/dvb/frontends/tda8083.c +++ b/drivers/media/dvb/frontends/tda8083.c @@ -37,7 +37,6 @@ #include "tda8083.h" struct tda8083_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; /* configuration settings */ const struct tda8083_config* config; struct dvb_frontend frontend; @@ -293,7 +292,11 @@ static int tda8083_set_frontend(struct d { struct tda8083_state* state = fe->demodulator_priv; - state->config->pll_set(fe, p); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } + tda8083_set_inversion (state, p->inversion); tda8083_set_fec (state, p->u.qpsk.fec_inner); tda8083_set_symbolrate (state, p->u.qpsk.symbol_rate); @@ -334,8 +337,6 @@ static int tda8083_init(struct dvb_front for (i=0; i<44; i++) tda8083_writereg (state, i, tda8083_init_tab[i]); - if (state->config->pll_init) state->config->pll_init(fe); - tda8083_writereg (state, 0x00, 0x3c); tda8083_writereg (state, 0x00, 0x04); @@ -395,13 +396,12 @@ struct dvb_frontend* tda8083_attach(cons /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &tda8083_ops, sizeof(struct dvb_frontend_ops)); /* check if the demod is there */ if ((tda8083_readreg(state, 0x00)) != 0x05) goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &tda8083_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; diff --git a/drivers/media/dvb/frontends/tda8083.h b/drivers/media/dvb/frontends/tda8083.h index 4666633..e7a48f6 100644 --- a/drivers/media/dvb/frontends/tda8083.h +++ b/drivers/media/dvb/frontends/tda8083.h @@ -33,10 +33,6 @@ struct tda8083_config { /* the demodulator's i2c address */ u8 demod_address; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config, diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c index ad8647a..6bffe85 100644 --- a/drivers/media/dvb/frontends/ves1820.c +++ b/drivers/media/dvb/frontends/ves1820.c @@ -35,7 +35,6 @@ #include "ves1820.h" struct ves1820_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; /* configuration settings */ const struct ves1820_config* config; struct dvb_frontend frontend; @@ -204,9 +203,6 @@ static int ves1820_init(struct dvb_front ves1820_writereg(state, 0x34, state->pwm); - if (state->config->pll_init) - state->config->pll_init(fe); - return 0; } @@ -223,7 +219,11 @@ static int ves1820_set_parameters(struct if (real_qam < 0 || real_qam > 4) return -EINVAL; - state->config->pll_set(fe, p); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } + ves1820_set_symbolrate(state, p->u.qam.symbol_rate); ves1820_writereg(state, 0x34, state->pwm); @@ -380,7 +380,6 @@ struct dvb_frontend* ves1820_attach(cons goto error; /* setup the state */ - memcpy(&state->ops, &ves1820_ops, sizeof(struct dvb_frontend_ops)); state->reg0 = ves1820_inittab[0]; state->config = config; state->i2c = i2c; @@ -393,12 +392,12 @@ struct dvb_frontend* ves1820_attach(cons if (verbose) printk("ves1820: pwm=0x%02x\n", state->pwm); - state->ops.info.symbol_rate_min = (state->config->xin / 2) / 64; /* SACLK/64 == (XIN/2)/64 */ - state->ops.info.symbol_rate_max = (state->config->xin / 2) / 4; /* SACLK/4 */ - /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &ves1820_ops, sizeof(struct dvb_frontend_ops)); + state->frontend.ops.info.symbol_rate_min = (state->config->xin / 2) / 64; /* SACLK/64 == (XIN/2)/64 */ + state->frontend.ops.info.symbol_rate_max = (state->config->xin / 2) / 4; /* SACLK/4 */ state->frontend.demodulator_priv = state; + return &state->frontend; error: diff --git a/drivers/media/dvb/frontends/ves1820.h b/drivers/media/dvb/frontends/ves1820.h index 355f130..520f095 100644 --- a/drivers/media/dvb/frontends/ves1820.h +++ b/drivers/media/dvb/frontends/ves1820.h @@ -39,10 +39,6 @@ struct ves1820_config /* SELAGC control */ u8 selagc:1; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config, diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c index 821df8e..54d7b07 100644 --- a/drivers/media/dvb/frontends/ves1x93.c +++ b/drivers/media/dvb/frontends/ves1x93.c @@ -36,7 +36,6 @@ #include "ves1x93.h" struct ves1x93_state { struct i2c_adapter* i2c; - struct dvb_frontend_ops ops; /* configuration settings */ const struct ves1x93_config* config; struct dvb_frontend frontend; @@ -278,12 +277,6 @@ static int ves1x93_init (struct dvb_fron } } - if (state->config->pll_init) { - ves1x93_writereg(state, 0x00, 0x11); - state->config->pll_init(fe); - ves1x93_writereg(state, 0x00, 0x01); - } - return 0; } @@ -395,9 +388,10 @@ static int ves1x93_set_frontend(struct d { struct ves1x93_state* state = fe->demodulator_priv; - ves1x93_writereg(state, 0x00, 0x11); - state->config->pll_set(fe, p); - ves1x93_writereg(state, 0x00, 0x01); + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, p); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } ves1x93_set_inversion (state, p->inversion); ves1x93_set_fec (state, p->u.qpsk.fec_inner); ves1x93_set_symbolrate (state, p->u.qpsk.symbol_rate); @@ -442,6 +436,17 @@ static void ves1x93_release(struct dvb_f kfree(state); } +static int ves1x93_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct ves1x93_state* state = fe->demodulator_priv; + + if (enable) { + return ves1x93_writereg(state, 0x00, 0x11); + } else { + return ves1x93_writereg(state, 0x00, 0x01); + } +} + static struct dvb_frontend_ops ves1x93_ops; struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, @@ -457,7 +462,6 @@ struct dvb_frontend* ves1x93_attach(cons /* setup the state */ state->config = config; state->i2c = i2c; - memcpy(&state->ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops)); state->inversion = INVERSION_OFF; /* check if the demod is there + identify it */ @@ -492,7 +496,7 @@ struct dvb_frontend* ves1x93_attach(cons } /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; @@ -523,6 +527,7 @@ static struct dvb_frontend_ops ves1x93_o .init = ves1x93_init, .sleep = ves1x93_sleep, + .i2c_gate_ctrl = ves1x93_i2c_gate_ctrl, .set_frontend = ves1x93_set_frontend, .get_frontend = ves1x93_get_frontend, diff --git a/drivers/media/dvb/frontends/ves1x93.h b/drivers/media/dvb/frontends/ves1x93.h index 1627e37..ba88ae0 100644 --- a/drivers/media/dvb/frontends/ves1x93.h +++ b/drivers/media/dvb/frontends/ves1x93.h @@ -38,10 +38,6 @@ struct ves1x93_config /* should PWM be inverted? */ u8 invert_pwm:1; - - /* PLL maintenance */ - int (*pll_init)(struct dvb_frontend* fe); - int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index d7d9f59..2b95e8b 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -34,7 +34,6 @@ #include "zl10353.h" struct zl10353_state { struct i2c_adapter *i2c; struct dvb_frontend frontend; - struct dvb_frontend_ops ops; struct zl10353_config config; }; @@ -126,6 +125,7 @@ static int zl10353_set_parameters(struct struct dvb_frontend_parameters *param) { struct zl10353_state *state = fe->demodulator_priv; + u8 pllbuf[6] = { 0x67 }; /* These settings set "auto-everything" and start the FSM. */ @@ -142,7 +142,30 @@ static int zl10353_set_parameters(struct zl10353_single_write(fe, 0x66, 0xE9); zl10353_single_write(fe, 0x62, 0x0A); - state->config.pll_set(fe, param, pllbuf + 1); + // if there is no attached secondary tuner, we call set_params to program + // a potential tuner attached somewhere else + if (state->config.no_tuner) { + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, param); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); + } + } + + // if pllbuf is defined, retrieve the settings + if (fe->ops.tuner_ops.calc_regs) { + fe->ops.tuner_ops.calc_regs(fe, param, pllbuf+1, 5); + pllbuf[1] <<= 1; + } else { + // fake pllbuf settings + pllbuf[1] = 0x61 << 1; + pllbuf[2] = 0; + pllbuf[3] = 0; + pllbuf[3] = 0; + pllbuf[4] = 0; + } + + // there is no call to _just_ start decoding, so we send the pllbuf anyway + // even if there isn't a PLL attached to the secondary bus zl10353_write(fe, pllbuf, sizeof(pllbuf)); zl10353_single_write(fe, 0x70, 0x01); @@ -254,14 +277,13 @@ struct dvb_frontend *zl10353_attach(cons /* setup the state */ state->i2c = i2c; memcpy(&state->config, config, sizeof(struct zl10353_config)); - memcpy(&state->ops, &zl10353_ops, sizeof(struct dvb_frontend_ops)); /* check if the demod is there */ if (zl10353_read_register(state, CHIP_ID) != ID_ZL10353) goto error; /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &zl10353_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h index 5cc4ae7..9770cb8 100644 --- a/drivers/media/dvb/frontends/zl10353.h +++ b/drivers/media/dvb/frontends/zl10353.h @@ -29,10 +29,8 @@ struct zl10353_config /* demodulator's I2C address */ u8 demod_address; - /* function which configures the PLL buffer (for secondary I2C - * connected tuner) or tunes the PLL (for direct connected tuner) */ - int (*pll_set)(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params, u8 *pllbuf); + /* set if no pll is connected to the secondary i2c bus */ + int no_tuner; }; extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config, diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c index 1c5316e..acabea0 100644 --- a/drivers/media/dvb/pluto2/pluto2.c +++ b/drivers/media/dvb/pluto2/pluto2.c @@ -424,8 +424,8 @@ static inline u32 divide(u32 numerator, } /* LG Innotek TDTE-E001P (Infineon TUA6034) */ -static int lg_tdtpe001p_pll_set(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p) +static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) { struct pluto *pluto = frontend_to_pluto(fe); struct i2c_msg msg; @@ -473,6 +473,8 @@ static int lg_tdtpe001p_pll_set(struct d msg.buf = buf; msg.len = sizeof(buf); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); ret = i2c_transfer(&pluto->i2c_adap, &msg, 1); if (ret < 0) return ret; @@ -497,8 +499,6 @@ static struct tda1004x_config pluto2_fe_ .xtal_freq = TDA10046_XTAL_16M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, - .pll_set = lg_tdtpe001p_pll_set, - .pll_sleep = NULL, .request_firmware = pluto2_request_firmware, }; @@ -511,11 +511,12 @@ static int __devinit frontend_init(struc dev_err(&pluto->pdev->dev, "could not attach frontend\n"); return -ENODEV; } + pluto->fe->ops.tuner_ops.set_params = lg_tdtpe001p_tuner_set_params; ret = dvb_register_frontend(&pluto->dvb_adapter, pluto->fe); if (ret < 0) { - if (pluto->fe->ops->release) - pluto->fe->ops->release(pluto->fe); + if (pluto->fe->ops.release) + pluto->fe->ops.release(pluto->fe); return ret; } @@ -647,7 +648,7 @@ static int __devinit pluto2_probe(struct goto err_pluto_hw_exit; /* dvb */ - ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE); + ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev); if (ret < 0) goto err_i2c_bit_del_bus; diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index b5ac7df..987881f 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -10,6 +10,7 @@ config DVB_AV7110 select DVB_SP8870 select DVB_STV0297 select DVB_L64781 + select DVB_LNBP21 help Support for SAA7146 and AV7110 based DVB cards as produced by Fujitsu-Siemens, Technotrend, Hauppauge and others. @@ -67,6 +68,7 @@ config DVB_BUDGET select DVB_TDA8083 select DVB_TDA10021 select DVB_S5H1420 + select DVB_LNBP21 help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -84,6 +86,7 @@ config DVB_BUDGET_CI select DVB_STV0297 select DVB_STV0299 select DVB_TDA1004X + select DVB_LNBP21 help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile index a690730..aa85ecd 100644 --- a/drivers/media/dvb/ttpci/Makefile +++ b/drivers/media/dvb/ttpci/Makefile @@ -15,9 +15,9 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-c hostprogs-y := fdump -ifdef CONFIG_DVB_AV7110_FIRMWARE -$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h +ifeq ($(CONFIG_DVB_AV7110_FIRMWARE),y) +$(obj)/av7110.o: $(obj)/av7110_firm.h -$(obj)/av7110_firm.h: +$(obj)/av7110_firm.h: $(obj)/fdump $(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@ endif diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index d028245..7a5c99c 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -152,13 +152,9 @@ static void init_av7110_av(struct av7110 /* remaining inits according to card and frontend type */ av7110->analog_tuner_flags = 0; av7110->current_input = 0; - if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) { - printk("dvb-ttpci: MSP3415 audio DAC @ card %d\n", - av7110->dvb_adapter.num); - av7110->adac_type = DVB_ADAC_MSP34x5; + if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on - } - else if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) { + if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) { printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n", av7110->dvb_adapter.num); av7110->adac_type = DVB_ADAC_CRYSTAL; @@ -1552,7 +1548,7 @@ static int get_firmware(struct av7110* a #endif -static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = (struct av7110*) fe->dvb->priv; u8 pwr = 0; @@ -1575,6 +1571,8 @@ static int alps_bsrv2_pll_set(struct dvb // NOTE: since we're using a prescaler of 2, we set the // divisor frequency to 62.5kHz and divide by 125 above + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -1584,10 +1582,9 @@ static struct ves1x93_config alps_bsrv2_ .demod_address = 0x08, .xin = 90100000UL, .invert_pwm = 0, - .pll_set = alps_bsrv2_pll_set, }; -static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = fe->dvb->priv; u32 div; @@ -1601,6 +1598,8 @@ static int alps_tdbe2_pll_set(struct dvb data[2] = 0x85 | ((div >> 10) & 0x60); data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -1611,14 +1610,12 @@ static struct ves1820_config alps_tdbe2_ .xin = 57840000UL, .invert = 1, .selagc = VES1820_SELAGC_SIGNAMPERR, - .pll_set = alps_tdbe2_pll_set, }; -static int grundig_29504_451_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) +static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = fe->dvb->priv; u32 div; @@ -1631,6 +1628,8 @@ static int grundig_29504_451_pll_set(str data[2] = 0x8e; data[3] = 0x00; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -1638,13 +1637,11 @@ static int grundig_29504_451_pll_set(str static struct tda8083_config grundig_29504_451_config = { .demod_address = 0x68, - .pll_set = grundig_29504_451_pll_set, }; -static int philips_cd1516_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) +static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = fe->dvb->priv; u32 div; @@ -1659,6 +1656,8 @@ static int philips_cd1516_pll_set(struct data[2] = 0x8e; data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -1669,12 +1668,11 @@ static struct ves1820_config philips_cd1 .xin = 57840000UL, .invert = 1, .selagc = VES1820_SELAGC_SIGNAMPERR, - .pll_set = philips_cd1516_pll_set, }; -static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = fe->dvb->priv; u32 div, pwr; @@ -1693,6 +1691,8 @@ static int alps_tdlb7_pll_set(struct dvb data[2] = 0x85; data[3] = pwr << 6; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -1708,7 +1708,6 @@ static int alps_tdlb7_request_firmware(s static struct sp8870_config alps_tdlb7_config = { .demod_address = 0x71, - .pll_set = alps_tdlb7_pll_set, .request_firmware = alps_tdlb7_request_firmware, }; @@ -1806,7 +1805,7 @@ static u8 nexusca_stv0297_inittab[] = { 0xff, 0xff, }; -static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = fe->dvb->priv; u32 div; @@ -1832,7 +1831,8 @@ static int nexusca_stv0297_pll_set(struc else return -EINVAL; - stv0297_enable_plli2c(fe); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) { printk("nexusca: pll transfer failed!\n"); return -EIO; @@ -1840,8 +1840,8 @@ static int nexusca_stv0297_pll_set(struc // wait for PLL lock for(i = 0; i < 20; i++) { - - stv0297_enable_plli2c(fe); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1) if (data[0] & 0x40) break; msleep(10); @@ -1855,12 +1855,12 @@ static struct stv0297_config nexusca_stv .demod_address = 0x1C, .inittab = nexusca_stv0297_inittab, .invert = 1, - .pll_set = nexusca_stv0297_pll_set, + .stop_during_read = 1, }; -static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params) { struct av7110* av7110 = (struct av7110*) fe->dvb->priv; u32 div; @@ -1887,13 +1887,14 @@ static int grundig_29504_401_pll_set(str data[2] = ((div >> 10) & 0x60) | cfg; data[3] = (cpump << 6) | band_select; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } static struct l64781_config grundig_29504_401_config = { .demod_address = 0x55, - .pll_set = grundig_29504_401_pll_set, }; @@ -2079,6 +2080,9 @@ static int frontend_init(struct av7110 * case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??)) av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap, read_pwm(av7110)); + if (av7110->fe) { + av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params; + } break; } @@ -2091,9 +2095,10 @@ static int frontend_init(struct av7110 * // try the ALPS BSRV2 first of all av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap); if (av7110->fe) { - av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; - av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; - av7110->fe->ops->set_tone = av7110_set_tone; + av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params; + av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops.set_tone = av7110_set_tone; av7110->recover = dvb_s_recover; break; } @@ -2101,9 +2106,12 @@ static int frontend_init(struct av7110 * // try the ALPS BSRU6 now av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap); if (av7110->fe) { - av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; - av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; - av7110->fe->ops->set_tone = av7110_set_tone; + av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; + av7110->fe->tuner_priv = &av7110->i2c_adap; + + av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops.set_tone = av7110_set_tone; av7110->recover = dvb_s_recover; break; } @@ -2111,9 +2119,10 @@ static int frontend_init(struct av7110 * // Try the grundig 29504-451 av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); if (av7110->fe) { - av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; - av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; - av7110->fe->ops->set_tone = av7110_set_tone; + av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params; + av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops.set_tone = av7110_set_tone; av7110->recover = dvb_s_recover; break; } @@ -2124,11 +2133,17 @@ static int frontend_init(struct av7110 * /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */ av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap, read_pwm(av7110)); + if (av7110->fe) { + av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params; + } break; case 0x0003: /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */ av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); + if (av7110->fe) { + av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params; + } break; } break; @@ -2137,20 +2152,27 @@ static int frontend_init(struct av7110 * // ALPS TDLB7 av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params; + } break; case 0x0002: // Hauppauge/TT DVB-C premium rev2.X av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); + if (av7110->fe) { + av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params; + } break; case 0x0004: // Galaxis DVB-S rev1.3 /* ALPS BSRV2 */ av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap); if (av7110->fe) { - av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; - av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; - av7110->fe->ops->set_tone = av7110_set_tone; + av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params; + av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops.set_tone = av7110_set_tone; av7110->recover = dvb_s_recover; } break; @@ -2159,9 +2181,10 @@ static int frontend_init(struct av7110 * /* Grundig 29504-451 */ av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); if (av7110->fe) { - av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; - av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst; - av7110->fe->ops->set_tone = av7110_set_tone; + av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params; + av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; + av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst; + av7110->fe->ops.set_tone = av7110_set_tone; av7110->recover = dvb_s_recover; } break; @@ -2169,12 +2192,17 @@ static int frontend_init(struct av7110 * case 0x0008: // Hauppauge/TT DVB-T av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap); + if (av7110->fe) { + av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; + } break; case 0x000A: // Hauppauge/TT Nexus-CA rev1.X av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap); if (av7110->fe) { + av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params; + /* set TDA9819 into DVB mode */ saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD) saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) @@ -2189,13 +2217,16 @@ static int frontend_init(struct av7110 * /* ALPS BSBE1 */ av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap); if (av7110->fe) { - if (lnbp21_init(av7110->fe, &av7110->i2c_adap, 0, 0)) { + av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params; + av7110->fe->tuner_priv = &av7110->i2c_adap; + + if (lnbp21_attach(av7110->fe, &av7110->i2c_adap, 0, 0)) { printk("dvb-ttpci: LNBP21 not found!\n"); - if (av7110->fe->ops->release) - av7110->fe->ops->release(av7110->fe); + if (av7110->fe->ops.release) + av7110->fe->ops.release(av7110->fe); av7110->fe = NULL; } else { - av7110->fe->ops->dishnetwork_send_legacy_command = NULL; + av7110->fe->ops.dishnetwork_send_legacy_command = NULL; av7110->recover = dvb_s_recover; } } @@ -2212,21 +2243,21 @@ static int frontend_init(struct av7110 * av7110->dev->pci->subsystem_vendor, av7110->dev->pci->subsystem_device); } else { - FE_FUNC_OVERRIDE(av7110->fe->ops->init, av7110->fe_init, av7110_fe_init); - FE_FUNC_OVERRIDE(av7110->fe->ops->read_status, av7110->fe_read_status, av7110_fe_read_status); - FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload); - FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd); - FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst); - FE_FUNC_OVERRIDE(av7110->fe->ops->set_tone, av7110->fe_set_tone, av7110_fe_set_tone); - FE_FUNC_OVERRIDE(av7110->fe->ops->set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;) - FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command); - FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend); + FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init); + FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status); + FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload); + FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd); + FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst); + FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone); + FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;) + FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command); + FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend); ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe); if (ret < 0) { printk("av7110: Frontend registration failed!\n"); - if (av7110->fe->ops->release) - av7110->fe->ops->release(av7110->fe); + if (av7110->fe->ops.release) + av7110->fe->ops.release(av7110->fe); av7110->fe = NULL; } } @@ -2413,7 +2444,7 @@ #endif goto err_kfree_0; ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name, - THIS_MODULE); + THIS_MODULE, &dev->pci->dev); if (ret < 0) goto err_put_firmware_1; diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c index 2eff09f..0f3a044 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c @@ -318,7 +318,17 @@ int av7110_set_volume(struct av7110 *av7 msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */ msp_writereg(av7110, MSP_WR_DSP, 0x0006, val); /* headphonesr */ return 0; + + case DVB_ADAC_MSP34x5: + vol = (volleft > volright) ? volleft : volright; + val = (vol * 0x73 / 255) << 8; + if (vol > 0) + balance = ((volright - volleft) * 127) / vol; + msp_writereg(av7110, MSP_WR_DSP, 0x0001, balance << 8); + msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */ + return 0; } + return 0; } @@ -1267,23 +1277,32 @@ static int dvb_audio_ioctl(struct inode switch(av7110->audiostate.channel_select) { case AUDIO_STEREO: ret = audcom(av7110, AUDIO_CMD_STEREO); - if (!ret) + if (!ret) { if (av7110->adac_type == DVB_ADAC_CRYSTAL) i2c_writereg(av7110, 0x20, 0x02, 0x49); + else if (av7110->adac_type == DVB_ADAC_MSP34x5) + msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); + } break; case AUDIO_MONO_LEFT: ret = audcom(av7110, AUDIO_CMD_MONO_L); - if (!ret) + if (!ret) { if (av7110->adac_type == DVB_ADAC_CRYSTAL) i2c_writereg(av7110, 0x20, 0x02, 0x4a); + else if (av7110->adac_type == DVB_ADAC_MSP34x5) + msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0200); + } break; case AUDIO_MONO_RIGHT: ret = audcom(av7110, AUDIO_CMD_MONO_R); - if (!ret) + if (!ret) { if (av7110->adac_type == DVB_ADAC_CRYSTAL) i2c_writereg(av7110, 0x20, 0x02, 0x45); + else if (av7110->adac_type == DVB_ADAC_MSP34x5) + msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0210); + } break; default: diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c index 603a22e..6405546 100644 --- a/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/drivers/media/dvb/ttpci/av7110_v4l.c @@ -42,7 +42,18 @@ #include "av7110_av.h" int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val) { u8 msg[5] = { dev, reg >> 8, reg & 0xff, val >> 8 , val & 0xff }; - struct i2c_msg msgs = { .flags = 0, .addr = 0x40, .len = 5, .buf = msg }; + struct i2c_msg msgs = { .flags = 0, .len = 5, .buf = msg }; + + switch (av7110->adac_type) { + case DVB_ADAC_MSP34x0: + msgs.addr = 0x40; + break; + case DVB_ADAC_MSP34x5: + msgs.addr = 0x42; + break; + default: + return 0; + } if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) { dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n", @@ -57,10 +68,23 @@ static int msp_readreg(struct av7110 *av u8 msg1[3] = { dev, reg >> 8, reg & 0xff }; u8 msg2[2]; struct i2c_msg msgs[2] = { - { .flags = 0, .addr = 0x40, .len = 3, .buf = msg1 }, - { .flags = I2C_M_RD, .addr = 0x40, .len = 2, .buf = msg2 } + { .flags = 0 , .len = 3, .buf = msg1 }, + { .flags = I2C_M_RD, .len = 2, .buf = msg2 } }; + switch (av7110->adac_type) { + case DVB_ADAC_MSP34x0: + msgs[0].addr = 0x40; + msgs[1].addr = 0x40; + break; + case DVB_ADAC_MSP34x5: + msgs[0].addr = 0x42; + msgs[1].addr = 0x42; + break; + default: + return 0; + } + if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) { dprintk(1, "dvb-ttpci: failed @ card %d, %u\n", av7110->dvb_adapter.num, reg); @@ -678,17 +702,23 @@ int av7110_init_analog_module(struct av7 { u16 version1, version2; - if (i2c_writereg(av7110, 0x80, 0x0, 0x80) != 1 - || i2c_writereg(av7110, 0x80, 0x0, 0) != 1) + if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 && + i2c_writereg(av7110, 0x80, 0x0, 0) == 1) { + printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n", + av7110->dvb_adapter.num); + av7110->adac_type = DVB_ADAC_MSP34x0; + } else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 && + i2c_writereg(av7110, 0x84, 0x0, 0) == 1) { + printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3415\n", + av7110->dvb_adapter.num); + av7110->adac_type = DVB_ADAC_MSP34x5; + } else return -ENODEV; - printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n", - av7110->dvb_adapter.num); - av7110->adac_type = DVB_ADAC_MSP34x0; msleep(100); // the probing above resets the msp... msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1); msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2); - dprintk(1, "dvb-ttpci: @ card %d MSP3400 version 0x%04x 0x%04x\n", + dprintk(1, "dvb-ttpci: @ card %d MSP34xx version 0x%04x 0x%04x\n", av7110->dvb_adapter.num, version1, version2); msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00); msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone @@ -697,7 +727,7 @@ int av7110_init_analog_module(struct av7 msp_writereg(av7110, MSP_WR_DSP, 0x0004, 0x7f00); // loudspeaker volume msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume - msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x4800); // prescale SCART + msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) { INFO(("saa7113 not accessible.\n")); diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 8a7cd7d..6163cb0 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -50,6 +50,12 @@ #include "dvb_ca_en50221.h" #define DEBICICAM 0x02420000 +#define SLOTSTATUS_NONE 1 +#define SLOTSTATUS_PRESENT 2 +#define SLOTSTATUS_RESET 4 +#define SLOTSTATUS_READY 8 +#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) + struct budget_av { struct budget budget; struct video_device *vd; @@ -58,8 +64,15 @@ struct budget_av { struct tasklet_struct ciintf_irq_tasklet; int slot_status; struct dvb_ca_en50221 ca; + u8 reinitialise_demod:1; + u8 tda10021_poclkp:1; + u8 tda10021_ts_enabled; + int (*tda10021_set_frontend)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p); }; +static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot); + + /* GPIO Connections: * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*! * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory @@ -129,9 +142,10 @@ static int ciintf_read_attribute_mem(str udelay(1); result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1); - - if (result == -ETIMEDOUT) - budget_av->slot_status = 0; + if (result == -ETIMEDOUT) { + ciintf_slot_shutdown(ca, slot); + printk(KERN_INFO "budget-av: cam ejected 1\n"); + } return result; } @@ -147,9 +161,10 @@ static int ciintf_write_attribute_mem(st udelay(1); result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1); - - if (result == -ETIMEDOUT) - budget_av->slot_status = 0; + if (result == -ETIMEDOUT) { + ciintf_slot_shutdown(ca, slot); + printk(KERN_INFO "budget-av: cam ejected 2\n"); + } return result; } @@ -165,9 +180,11 @@ static int ciintf_read_cam_control(struc udelay(1); result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0); - - if (result == -ETIMEDOUT) - budget_av->slot_status = 0; + if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) { + ciintf_slot_shutdown(ca, slot); + printk(KERN_INFO "budget-av: cam ejected 3\n"); + return -ETIMEDOUT; + } return result; } @@ -183,9 +200,10 @@ static int ciintf_write_cam_control(stru udelay(1); result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0); - - if (result == -ETIMEDOUT) - budget_av->slot_status = 0; + if (result == -ETIMEDOUT) { + ciintf_slot_shutdown(ca, slot); + printk(KERN_INFO "budget-av: cam ejected 5\n"); + } return result; } @@ -193,12 +211,12 @@ static int ciintf_slot_reset(struct dvb_ { struct budget_av *budget_av = (struct budget_av *) ca->data; struct saa7146_dev *saa = budget_av->budget.dev; - int timeout = 50; // 5 seconds (4.4.6 Ready) if (slot != 0) return -EINVAL; dprintk(1, "ciintf_slot_reset\n"); + budget_av->slot_status = SLOTSTATUS_RESET; saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */ @@ -208,20 +226,17 @@ static int ciintf_slot_reset(struct dvb_ msleep(20); /* 20 ms Vcc settling time */ saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */ + ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); + msleep(20); - /* This should have been based on pin 16 READY of the pcmcia port, - * but AFAICS it is not routed to the saa7146 */ - while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d) - msleep(100); - - /* reinitialise the frontend */ - dvb_frontend_reinitialise(budget_av->budget.dvb_frontend); + /* reinitialise the frontend if necessary */ + if (budget_av->reinitialise_demod) + dvb_frontend_reinitialise(budget_av->budget.dvb_frontend); - if (timeout <= 0) - { - printk(KERN_ERR "budget-av: cam reset failed (timeout).\n"); - saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */ - return -ETIMEDOUT; + /* set tda10021 back to original clock configuration on reset */ + if (budget_av->tda10021_poclkp) { + tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0); + budget_av->tda10021_ts_enabled = 0; } return 0; @@ -238,7 +253,13 @@ static int ciintf_slot_shutdown(struct d dprintk(1, "ciintf_slot_shutdown\n"); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); - budget_av->slot_status = 0; + budget_av->slot_status = SLOTSTATUS_NONE; + + /* set tda10021 back to original clock configuration when cam removed */ + if (budget_av->tda10021_poclkp) { + tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0); + budget_av->tda10021_ts_enabled = 0; + } return 0; } @@ -253,6 +274,13 @@ static int ciintf_slot_ts_enable(struct dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA); + + /* tda10021 seems to need a different TS clock config when data is routed to the CAM */ + if (budget_av->tda10021_poclkp) { + tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1); + budget_av->tda10021_ts_enabled = 1; + } + return 0; } @@ -260,50 +288,61 @@ static int ciintf_poll_slot_status(struc { struct budget_av *budget_av = (struct budget_av *) ca->data; struct saa7146_dev *saa = budget_av->budget.dev; - int cam_present = 0; + int result; if (slot != 0) return -EINVAL; - if (!budget_av->slot_status) - { - // first of all test the card detect line + /* test the card detect line - needs to be done carefully + * since it never goes high for some CAMs on this interface (e.g. topuptv) */ + if (budget_av->slot_status == SLOTSTATUS_NONE) { saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); udelay(1); - if (saa7146_read(saa, PSR) & MASK_06) - { - cam_present = 1; + if (saa7146_read(saa, PSR) & MASK_06) { + if (budget_av->slot_status == SLOTSTATUS_NONE) { + budget_av->slot_status = SLOTSTATUS_PRESENT; + printk(KERN_INFO "budget-av: cam inserted A\n"); + } } saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); + } - // that is unreliable however, so try and read from IO memory - if (!cam_present) - { - saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); - if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT) - { - cam_present = 1; + /* We also try and read from IO memory to work round the above detection bug. If + * there is no CAM, we will get a timeout. Only done if there is no cam + * present, since this test actually breaks some cams :( + * + * if the CI interface is not open, we also do the above test since we + * don't care if the cam has problems - we'll be resetting it on open() anyway */ + if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) { + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); + result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1); + if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) { + budget_av->slot_status = SLOTSTATUS_PRESENT; + printk(KERN_INFO "budget-av: cam inserted B\n"); + } else if (result < 0) { + if (budget_av->slot_status != SLOTSTATUS_NONE) { + ciintf_slot_shutdown(ca, slot); + printk(KERN_INFO "budget-av: cam ejected 5\n"); + return 0; } } + } - // did we find something? - if (cam_present) { - printk(KERN_INFO "budget-av: cam inserted\n"); - budget_av->slot_status = 1; - } - } else if (!open) { - saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); - if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT) - { - printk(KERN_INFO "budget-av: cam ejected\n"); - saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */ - budget_av->slot_status = 0; + /* read from attribute memory in reset/ready state to know when the CAM is ready */ + if (budget_av->slot_status == SLOTSTATUS_RESET) { + result = ciintf_read_attribute_mem(ca, slot, 0); + if (result == 0x1d) { + budget_av->slot_status = SLOTSTATUS_READY; } } - if (budget_av->slot_status == 1) - return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; - + /* work out correct return code */ + if (budget_av->slot_status != SLOTSTATUS_NONE) { + if (budget_av->slot_status & SLOTSTATUS_READY) { + return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; + } + return DVB_CA_EN50221_POLL_CAM_PRESENT; + } return 0; } @@ -333,6 +372,8 @@ static int ciintf_init(struct budget_av budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable; budget_av->ca.poll_slot_status = ciintf_poll_slot_status; budget_av->ca.data = budget_av; + budget_av->budget.ci_present = 1; + budget_av->slot_status = SLOTSTATUS_NONE; if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter, &budget_av->ca, 0, 1)) != 0) { @@ -341,7 +382,6 @@ static int ciintf_init(struct budget_av } printk(KERN_INFO "budget-av: ci interface initialised.\n"); - budget_av->budget.ci_present = 1; return 0; error: @@ -472,12 +512,12 @@ static int philips_su1278_ty_ci_set_symb return 0; } -static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe, - struct i2c_adapter *i2c, - struct dvb_frontend_parameters *params) +static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { u32 div; u8 buf[4]; + struct budget *budget = (struct budget *) fe->dvb->priv; struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) }; if ((params->frequency < 950000) || (params->frequency > 2150000)) @@ -501,7 +541,9 @@ static int philips_su1278_ty_ci_pll_set( else if (params->frequency < 2150000) buf[3] |= 0xC0; - if (i2c_transfer(i2c, &msg, 1) != 1) + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } @@ -509,9 +551,8 @@ static int philips_su1278_ty_ci_pll_set( #define MIN2(a,b) ((a) < (b) ? (a) : (b)) #define MIN3(a,b,c) MIN2(MIN2(a,b),c) -static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe, - struct i2c_adapter *i2c, - struct dvb_frontend_parameters *params) +static int philips_su1278sh2_tua6100_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { u8 reg0 [2] = { 0x00, 0x00 }; u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 }; @@ -521,6 +562,7 @@ static int philips_su1278sh2_tua6100_pll int R, A, N, P, M; struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 }; int freq = params->frequency; + struct budget *budget = (struct budget *) fe->dvb->priv; first_ZF = (freq) / 1000; @@ -620,21 +662,25 @@ static int philips_su1278sh2_tua6100_pll reg0[1] |= 0x03; /* already enabled - do not reenable i2c repeater or TX fails */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); msg.buf = reg0; msg.len = sizeof(reg0); - if (i2c_transfer(i2c, &msg, 1) != 1) + if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) return -EIO; - stv0299_enable_plli2c(fe); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); msg.buf = reg1; msg.len = sizeof(reg1); - if (i2c_transfer(i2c, &msg, 1) != 1) + if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) return -EIO; - stv0299_enable_plli2c(fe); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); msg.buf = reg2; msg.len = sizeof(reg2); - if (i2c_transfer(i2c, &msg, 1) != 1) + if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -692,7 +738,6 @@ static struct stv0299_config typhoon_con .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, - .pll_set = philips_su1278_ty_ci_pll_set, }; @@ -706,7 +751,6 @@ static struct stv0299_config cinergy_120 .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, - .pll_set = philips_su1278_ty_ci_pll_set, }; static struct stv0299_config cinergy_1200s_1894_0010_config = { @@ -719,10 +763,9 @@ static struct stv0299_config cinergy_120 .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate, - .pll_set = philips_su1278sh2_tua6100_pll_set, }; -static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct budget *budget = (struct budget *) fe->dvb->priv; u8 buf[4]; @@ -738,6 +781,8 @@ #define TUNER_MUL 62500 buf[3] = (params->frequency < 150000000 ? 0x01 : params->frequency < 445000000 ? 0x02 : 0x04); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -745,19 +790,20 @@ #define TUNER_MUL 62500 static struct tda10021_config philips_cu1216_config = { .demod_address = 0x0c, - .pll_set = philips_cu1216_pll_set, }; -static int philips_tu1216_pll_init(struct dvb_frontend *fe) +static int philips_tu1216_tuner_init(struct dvb_frontend *fe) { struct budget *budget = (struct budget *) fe->dvb->priv; static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab }; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) }; // setup PLL configuration + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(1); @@ -765,7 +811,7 @@ static int philips_tu1216_pll_init(struc return 0; } -static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct budget *budget = (struct budget *) fe->dvb->priv; u8 tuner_buf[4]; @@ -839,6 +885,8 @@ static int philips_tu1216_pll_set(struct tuner_buf[2] = 0xca; tuner_buf[3] = (cp << 5) | (filter << 3) | band; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) return -EIO; @@ -862,9 +910,6 @@ static struct tda1004x_config philips_tu .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, - .pll_init = philips_tu1216_pll_init, - .pll_set = philips_tu1216_pll_set, - .pll_sleep = NULL, .request_firmware = philips_tu1216_request_firmware, }; @@ -911,13 +956,13 @@ static u8 philips_sd1878_inittab[] = { 0xff, 0xff }; -static int philips_sd1878_tda8261_pll_set(struct dvb_frontend *fe, - struct i2c_adapter *i2c, - struct dvb_frontend_parameters *params) +static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { u8 buf[4]; int rc; struct i2c_msg tuner_msg = {.addr=0x60,.flags=0,.buf=buf,.len=sizeof(buf)}; + struct budget *budget = (struct budget *) fe->dvb->priv; if((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; @@ -926,7 +971,9 @@ static int philips_sd1878_tda8261_pll_se params->frequency, 0); if(rc < 0) return rc; - if(i2c_transfer(i2c, &tuner_msg, 1) != 1) + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if(i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1) return -EIO; return 0; @@ -969,7 +1016,7 @@ static int philips_sd1878_ci_set_symbol_ static struct stv0299_config philips_sd1878_config = { .demod_address = 0x68, - .inittab = philips_sd1878_inittab, + .inittab = philips_sd1878_inittab, .mclk = 88000000UL, .invert = 0, .skip_reinit = 0, @@ -977,7 +1024,6 @@ static struct stv0299_config philips_sd1 .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = philips_sd1878_ci_set_symbol_rate, - .pll_set = philips_sd1878_tda8261_pll_set, }; static u8 read_pwm(struct budget_av *budget_av) @@ -1003,6 +1049,7 @@ #define SUBID_DVBS_CYNERGY1200N 0x1155 #define SUBID_DVBS_TV_STAR 0x0014 #define SUBID_DVBS_TV_STAR_CI 0x0016 +#define SUBID_DVBS_EASYWATCH_1 0x001a #define SUBID_DVBS_EASYWATCH 0x001e #define SUBID_DVBC_KNC1 0x0020 #define SUBID_DVBC_KNC1_PLUS 0x0021 @@ -1012,17 +1059,36 @@ #define SUBID_DVBT_KNC1_PLUS 0x0031 #define SUBID_DVBT_KNC1 0x0030 #define SUBID_DVBT_CINERGY1200 0x1157 + +static int tda10021_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct budget_av* budget_av = fe->dvb->priv; + int result; + + result = budget_av->tda10021_set_frontend(fe, p); + if (budget_av->tda10021_ts_enabled) { + tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1); + } else { + tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0); + } + + return result; +} + static void frontend_init(struct budget_av *budget_av) { struct saa7146_dev * saa = budget_av->budget.dev; struct dvb_frontend * fe = NULL; + /* Enable / PowerON Frontend */ + saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); + + /* additional setup necessary for the PLUS cards */ switch (saa->pci->subsystem_device) { case SUBID_DVBS_KNC1_PLUS: case SUBID_DVBC_KNC1_PLUS: case SUBID_DVBT_KNC1_PLUS: - // Enable / PowerON Frontend - saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI); break; } @@ -1030,12 +1096,19 @@ static void frontend_init(struct budget_ switch (saa->pci->subsystem_device) { case SUBID_DVBS_KNC1: + case SUBID_DVBS_EASYWATCH_1: if (saa->pci->subsystem_vendor == 0x1894) { fe = stv0299_attach(&cinergy_1200s_1894_0010_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops.tuner_ops.set_params = philips_su1278sh2_tua6100_tuner_set_params; + } } else { fe = stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; + } } break; @@ -1045,41 +1118,53 @@ static void frontend_init(struct budget_ case SUBID_DVBS_EASYWATCH: fe = stv0299_attach(&philips_sd1878_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops.tuner_ops.set_params = philips_sd1878_tda8261_tuner_set_params; + } break; case SUBID_DVBS_KNC1_PLUS: case SUBID_DVBS_TYPHOON: fe = stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; + } break; case SUBID_DVBS_CINERGY1200: fe = stv0299_attach(&cinergy_1200s_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; + } break; case SUBID_DVBC_KNC1: case SUBID_DVBC_KNC1_PLUS: + case SUBID_DVBC_CINERGY1200: + budget_av->reinitialise_demod = 1; fe = tda10021_attach(&philips_cu1216_config, &budget_av->budget.i2c_adap, read_pwm(budget_av)); + if (fe) { + budget_av->tda10021_poclkp = 1; + budget_av->tda10021_set_frontend = fe->ops.set_frontend; + fe->ops.set_frontend = tda10021_set_frontend; + fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params; + } break; case SUBID_DVBT_KNC1: case SUBID_DVBT_KNC1_PLUS: - fe = tda10046_attach(&philips_tu1216_config, - &budget_av->budget.i2c_adap); - break; - - case SUBID_DVBC_CINERGY1200: - fe = tda10021_attach(&philips_cu1216_config, - &budget_av->budget.i2c_adap, - read_pwm(budget_av)); - break; - case SUBID_DVBT_CINERGY1200: + budget_av->reinitialise_demod = 1; fe = tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap); + if (fe) { + fe->ops.tuner_ops.init = philips_tu1216_tuner_init; + fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params; + } break; } @@ -1098,8 +1183,8 @@ static void frontend_init(struct budget_ if (dvb_register_frontend(&budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) { printk(KERN_ERR "budget-av: Frontend registration failed!\n"); - if (budget_av->budget.dvb_frontend->ops->release) - budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend); + if (budget_av->budget.dvb_frontend->ops.release) + budget_av->budget.dvb_frontend->ops.release(budget_av->budget.dvb_frontend); budget_av->budget.dvb_frontend = NULL; } } @@ -1293,6 +1378,7 @@ MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BU MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T); MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR); MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR); +MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S); MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP); MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP); MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP); @@ -1309,6 +1395,7 @@ static struct pci_device_id pci_tbl[] = MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014), MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016), MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), + MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a), MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030), diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index e64a609..4b966ee 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -620,10 +620,10 @@ static int philips_su1278_tt_set_symbol_ return 0; } -static int philips_su1278_tt_pll_set(struct dvb_frontend *fe, - struct i2c_adapter *i2c, - struct dvb_frontend_parameters *params) +static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { + struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; u32 div; u8 buf[4]; struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; @@ -649,7 +649,9 @@ static int philips_su1278_tt_pll_set(str else if (params->frequency < 2150000) buf[3] |= 0xC0; - if (i2c_transfer(i2c, &msg, 1) != 1) + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1) return -EIO; return 0; } @@ -665,12 +667,11 @@ static struct stv0299_config philips_su1 .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 50, .set_symbol_rate = philips_su1278_tt_set_symbol_rate, - .pll_set = philips_su1278_tt_pll_set, }; -static int philips_tdm1316l_pll_init(struct dvb_frontend *fe) +static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe) { struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; @@ -679,6 +680,8 @@ static int philips_tdm1316l_pll_init(str sizeof(td1316_init) }; // setup PLL configuration + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(1); @@ -687,14 +690,18 @@ static int philips_tdm1316l_pll_init(str tuner_msg.addr = 0x65; tuner_msg.buf = disable_mc44BC374c; tuner_msg.len = sizeof(disable_mc44BC374c); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1); } return 0; } -static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; u8 tuner_buf[4]; @@ -770,6 +777,8 @@ static int philips_tdm1316l_pll_set(stru tuner_buf[2] = 0xca; tuner_buf[3] = (cp << 5) | (filter << 3) | band; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) return -EIO; @@ -793,13 +802,10 @@ static struct tda1004x_config philips_td .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, - .pll_init = philips_tdm1316l_pll_init, - .pll_set = philips_tdm1316l_pll_set, - .pll_sleep = NULL, .request_firmware = philips_tdm1316l_request_firmware, }; -static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv; u8 tuner_buf[5]; @@ -857,13 +863,15 @@ static int dvbc_philips_tdm1316l_pll_set tuner_buf[3] = (cp << 5) | (filter << 3) | band; tuner_buf[4] = 0x80; - stv0297_enable_plli2c(fe); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(50); - stv0297_enable_plli2c(fe); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) return -EIO; @@ -969,7 +977,7 @@ static struct stv0297_config dvbc_philip .demod_address = 0x1c, .inittab = dvbc_philips_tdm1316l_inittab, .invert = 0, - .pll_set = dvbc_philips_tdm1316l_pll_set, + .stop_during_read = 1, }; @@ -982,6 +990,8 @@ static void frontend_init(struct budget_ budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; + budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap; break; } break; @@ -990,6 +1000,7 @@ static void frontend_init(struct budget_ budget_ci->budget.dvb_frontend = stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params; break; } break; @@ -999,6 +1010,7 @@ static void frontend_init(struct budget_ budget_ci->budget.dvb_frontend = stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params; break; } break; @@ -1008,6 +1020,8 @@ static void frontend_init(struct budget_ budget_ci->budget.dvb_frontend = tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init; + budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params; break; } break; @@ -1017,6 +1031,8 @@ static void frontend_init(struct budget_ budget_ci->budget.dvb_frontend = tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { + budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init; + budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params; break; } break; @@ -1024,11 +1040,14 @@ static void frontend_init(struct budget_ case 0x1017: // TT S-1500 PCI budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { - budget_ci->budget.dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; - if (lnbp21_init(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) { + budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params; + budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap; + + budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; + if (lnbp21_attach(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) { printk("%s: No LNBP21 found!\n", __FUNCTION__); - if (budget_ci->budget.dvb_frontend->ops->release) - budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend); + if (budget_ci->budget.dvb_frontend->ops.release) + budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend); budget_ci->budget.dvb_frontend = NULL; } } @@ -1046,8 +1065,8 @@ static void frontend_init(struct budget_ if (dvb_register_frontend (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) { printk("budget-ci: Frontend registration failed!\n"); - if (budget_ci->budget.dvb_frontend->ops->release) - budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend); + if (budget_ci->budget.dvb_frontend->ops.release) + budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend); budget_ci->budget.dvb_frontend = NULL; } } diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index ea2066d..e4cf777 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -400,7 +400,9 @@ int ttpci_budget_init(struct budget *bud budget->dev->name, budget->buffer_width, budget->buffer_height); printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size); - dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner); + if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) { + return ret; + } /* set dd1 stream a & b */ saa7146_write(dev, DD1_STREAM_B, 0x00000000); diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index 1b3aaac..ee60ce9 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -258,7 +258,7 @@ static int budget_patch_diseqc_send_burs return 0; } -static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; u8 pwr = 0; @@ -281,7 +281,10 @@ static int alps_bsrv2_pll_set(struct dvb // NOTE: since we're using a prescaler of 2, we set the // divisor frequency to 62.5kHz and divide by 125 above - if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) + return -EIO; return 0; } @@ -289,10 +292,9 @@ static struct ves1x93_config alps_bsrv2_ .demod_address = 0x08, .xin = 90100000UL, .invert_pwm = 0, - .pll_set = alps_bsrv2_pll_set, }; -static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; u32 div; @@ -305,13 +307,15 @@ static int grundig_29504_451_pll_set(str data[2] = 0x8e; data[3] = 0x00; - if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) + return -EIO; return 0; } static struct tda8083_config grundig_29504_451_config = { .demod_address = 0x68, - .pll_set = grundig_29504_451_pll_set, }; static void frontend_init(struct budget_patch* budget) @@ -323,27 +327,32 @@ static void frontend_init(struct budget_ // try the ALPS BSRV2 first of all budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap); if (budget->dvb_frontend) { - budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd; - budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst; - budget->dvb_frontend->ops->set_tone = budget_patch_set_tone; + budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params; + budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd; + budget->dvb_frontend->ops.diseqc_send_burst = budget_patch_diseqc_send_burst; + budget->dvb_frontend->ops.set_tone = budget_patch_set_tone; break; } // try the ALPS BSRU6 now budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); if (budget->dvb_frontend) { - budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; - budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; - budget->dvb_frontend->ops->set_tone = budget_set_tone; + budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; + budget->dvb_frontend->tuner_priv = &budget->i2c_adap; + + budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; + budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; + budget->dvb_frontend->ops.set_tone = budget_set_tone; break; } // Try the grundig 29504-451 budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); if (budget->dvb_frontend) { - budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; - budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; - budget->dvb_frontend->ops->set_tone = budget_set_tone; + budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params; + budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; + budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; + budget->dvb_frontend->ops.set_tone = budget_set_tone; break; } break; @@ -358,8 +367,8 @@ static void frontend_init(struct budget_ } else { if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) { printk("budget-av: Frontend registration failed!\n"); - if (budget->dvb_frontend->ops->release) - budget->dvb_frontend->ops->release(budget->dvb_frontend); + if (budget->dvb_frontend->ops.release) + budget->dvb_frontend->ops.release(budget->dvb_frontend); budget->dvb_frontend = NULL; } } diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index c23c02d..35761f1 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -186,7 +186,7 @@ static int budget_diseqc_send_burst(stru return 0; } -static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; u8 pwr = 0; @@ -209,6 +209,8 @@ static int alps_bsrv2_pll_set(struct dvb // NOTE: since we're using a prescaler of 2, we set the // divisor frequency to 62.5kHz and divide by 125 above + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } @@ -218,10 +220,9 @@ static struct ves1x93_config alps_bsrv2_ .demod_address = 0x08, .xin = 90100000UL, .invert_pwm = 0, - .pll_set = alps_bsrv2_pll_set, }; -static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; u32 div; @@ -235,6 +236,8 @@ static int alps_tdbe2_pll_set(struct dvb data[2] = 0x85 | ((div >> 10) & 0x60); data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } @@ -244,10 +247,9 @@ static struct ves1820_config alps_tdbe2_ .xin = 57840000UL, .invert = 1, .selagc = VES1820_SELAGC_SIGNAMPERR, - .pll_set = alps_tdbe2_pll_set, }; -static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; u32 div; @@ -274,16 +276,17 @@ static int grundig_29504_401_pll_set(str data[2] = ((div >> 10) & 0x60) | cfg; data[3] = (cpump << 6) | band_select; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } static struct l64781_config grundig_29504_401_config = { .demod_address = 0x55, - .pll_set = grundig_29504_401_pll_set, }; -static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; u32 div; @@ -296,16 +299,17 @@ static int grundig_29504_451_pll_set(str data[2] = 0x8e; data[3] = 0x00; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } static struct tda8083_config grundig_29504_451_config = { .demod_address = 0x68, - .pll_set = grundig_29504_451_pll_set, }; -static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout) +static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct budget* budget = (struct budget*) fe->dvb->priv; u32 div; @@ -326,16 +330,16 @@ static int s5h1420_pll_set(struct dvb_fr else data[3] = 0xc0; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; - *freqout = div * 1000; return 0; } static struct s5h1420_config s5h1420_config = { .demod_address = 0x53, .invert = 1, - .pll_set = s5h1420_pll_set, }; static u8 read_pwm(struct budget* budget) @@ -359,18 +363,21 @@ static void frontend_init(struct budget // try the ALPS BSRV2 first of all budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap); if (budget->dvb_frontend) { - budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; - budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; - budget->dvb_frontend->ops->set_tone = budget_set_tone; + budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params; + budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; + budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; + budget->dvb_frontend->ops.set_tone = budget_set_tone; break; } // try the ALPS BSRU6 now budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); if (budget->dvb_frontend) { - budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; - budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; - budget->dvb_frontend->ops->set_tone = budget_set_tone; + budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; + budget->dvb_frontend->tuner_priv = &budget->i2c_adap; + budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; + budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; + budget->dvb_frontend->ops.set_tone = budget_set_tone; break; } break; @@ -378,35 +385,45 @@ static void frontend_init(struct budget case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659)) budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget)); - if (budget->dvb_frontend) break; + if (budget->dvb_frontend) { + budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params; + break; + } break; case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060)) budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap); - if (budget->dvb_frontend) break; + if (budget->dvb_frontend) { + budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; + break; + } break; case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059)) budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); if (budget->dvb_frontend) { - budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage; - budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; + budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; + budget->dvb_frontend->tuner_priv = &budget->i2c_adap; + budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; + budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; } break; case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522)) budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); if (budget->dvb_frontend) { - budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage; - budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL; + budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params; + budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; + budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; } break; case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260)) budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap); if (budget->dvb_frontend) { - if (lnbp21_init(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) { + budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params; + if (lnbp21_attach(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) { printk("%s: No LNBP21 found!\n", __FUNCTION__); goto error_out; } @@ -428,8 +445,8 @@ static void frontend_init(struct budget error_out: printk("budget: Frontend registration failed!\n"); - if (budget->dvb_frontend->ops->release) - budget->dvb_frontend->ops->release(budget->dvb_frontend); + if (budget->dvb_frontend->ops.release) + budget->dvb_frontend->ops.release(budget->dvb_frontend); budget->dvb_frontend = NULL; return; } diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig index 914587d..92c7cdc 100644 --- a/drivers/media/dvb/ttusb-budget/Kconfig +++ b/drivers/media/dvb/ttusb-budget/Kconfig @@ -6,6 +6,8 @@ config DVB_TTUSB_BUDGET select DVB_VES1820 select DVB_TDA8083 select DVB_STV0299 + select DVB_STV0297 + select DVB_LNBP21 help Support for external USB adapters designed by Technotrend and produced by Hauppauge, shipped under the brand name 'Nova-USB'. diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 6ceae38..14559ef 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -30,6 +30,8 @@ #include "cx22700.h" #include "tda1004x.h" #include "stv0299.h" #include "tda8083.h" +#include "stv0297.h" +#include "lnbp21.h" #include #include @@ -486,31 +488,6 @@ static int ttusb_send_diseqc(struct dvb_ } #endif -static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) -{ - struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; - int ret; - u8 data[1]; - struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = data, .len = sizeof(data) }; - - switch(voltage) { - case SEC_VOLTAGE_OFF: - data[0] = 0x00; - break; - case SEC_VOLTAGE_13: - data[0] = 0x44; - break; - case SEC_VOLTAGE_18: - data[0] = 0x4c; - break; - default: - return -EINVAL; - }; - - ret = i2c_transfer(&ttusb->i2c_adap, &msg, 1); - return (ret != 1) ? -EIO : 0; -} - static int ttusb_update_lnb(struct ttusb *ttusb) { u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1, @@ -1048,7 +1025,7 @@ static u32 functionality(struct i2c_adap -static int alps_tdmb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_tdmb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; u8 data[4]; @@ -1062,20 +1039,21 @@ static int alps_tdmb7_pll_set(struct dvb data[2] = ((div >> 10) & 0x60) | 0x85; data[3] = params->frequency < 592000000 ? 0x40 : 0x80; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO; return 0; } static struct cx22700_config alps_tdmb7_config = { .demod_address = 0x43, - .pll_set = alps_tdmb7_pll_set, }; -static int philips_tdm1316l_pll_init(struct dvb_frontend* fe) +static int philips_tdm1316l_tuner_init(struct dvb_frontend* fe) { struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; @@ -1083,6 +1061,8 @@ static int philips_tdm1316l_pll_init(str struct i2c_msg tuner_msg = { .addr=0x60, .flags=0, .buf=td1316_init, .len=sizeof(td1316_init) }; // setup PLL configuration + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(1); @@ -1090,6 +1070,8 @@ static int philips_tdm1316l_pll_init(str tuner_msg.addr = 0x65; tuner_msg.buf = disable_mc44BC374c; tuner_msg.len = sizeof(disable_mc44BC374c); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) { i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1); } @@ -1097,7 +1079,7 @@ static int philips_tdm1316l_pll_init(str return 0; } -static int philips_tdm1316l_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; u8 tuner_buf[4]; @@ -1157,6 +1139,8 @@ static int philips_tdm1316l_pll_set(stru tuner_buf[2] = 0xca; tuner_buf[3] = (cp << 5) | (filter << 3) | band; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO; @@ -1176,8 +1160,6 @@ static struct tda1004x_config philips_td .demod_address = 0x8, .invert = 1, .invert_oclk = 0, - .pll_init = philips_tdm1316l_pll_init, - .pll_set = philips_tdm1316l_pll_set, .request_firmware = philips_tdm1316l_request_firmware, }; @@ -1299,7 +1281,7 @@ static int alps_stv0299_set_symbol_rate( return 0; } -static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params) +static int philips_tsa5059_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; u8 buf[4]; @@ -1322,7 +1304,9 @@ static int philips_tsa5059_pll_set(struc if (ttusb->revision == TTUSB_REV_2_2) buf[3] |= 0x20; - if (i2c_transfer(i2c, &msg, 1) != 1) + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO; return 0; @@ -1338,10 +1322,9 @@ static struct stv0299_config alps_stv029 .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 100, .set_symbol_rate = alps_stv0299_set_symbol_rate, - .pll_set = philips_tsa5059_pll_set, }; -static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv; u8 buf[4]; @@ -1355,6 +1338,8 @@ static int ttusb_novas_grundig_29504_491 buf[2] = 0x8e; buf[3] = 0x00; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO; @@ -1364,10 +1349,9 @@ static int ttusb_novas_grundig_29504_491 static struct tda8083_config ttusb_novas_grundig_29504_491_config = { .demod_address = 0x68, - .pll_set = ttusb_novas_grundig_29504_491_pll_set, }; -static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) +static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) { struct ttusb* ttusb = fe->dvb->priv; u32 div; @@ -1381,6 +1365,8 @@ static int alps_tdbe2_pll_set(struct dvb data[2] = 0x85 | ((div >> 10) & 0x60); data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer (&ttusb->i2c_adap, &msg, 1) != 1) return -EIO; @@ -1393,7 +1379,6 @@ static struct ves1820_config alps_tdbe2_ .xin = 57840000UL, .invert = 1, .selagc = VES1820_SELAGC_SIGNAMPERR, - .pll_set = alps_tdbe2_pll_set, }; static u8 read_pwm(struct ttusb* ttusb) @@ -1410,6 +1395,174 @@ static u8 read_pwm(struct ttusb* ttusb) } +static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct ttusb *ttusb = (struct ttusb *) fe->dvb->priv; + u8 tuner_buf[5]; + struct i2c_msg tuner_msg = {.addr = 0x60, + .flags = 0, + .buf = tuner_buf, + .len = sizeof(tuner_buf) }; + int tuner_frequency = 0; + u8 band, cp, filter; + + // determine charge pump + tuner_frequency = params->frequency; + if (tuner_frequency < 87000000) {return -EINVAL;} + else if (tuner_frequency < 130000000) {cp = 3; band = 1;} + else if (tuner_frequency < 160000000) {cp = 5; band = 1;} + else if (tuner_frequency < 200000000) {cp = 6; band = 1;} + else if (tuner_frequency < 290000000) {cp = 3; band = 2;} + else if (tuner_frequency < 420000000) {cp = 5; band = 2;} + else if (tuner_frequency < 480000000) {cp = 6; band = 2;} + else if (tuner_frequency < 620000000) {cp = 3; band = 4;} + else if (tuner_frequency < 830000000) {cp = 5; band = 4;} + else if (tuner_frequency < 895000000) {cp = 7; band = 4;} + else {return -EINVAL;} + + // assume PLL filter should always be 8MHz for the moment. + filter = 1; + + // calculate divisor + // (Finput + Fif)/Fref; Fif = 36125000 Hz, Fref = 62500 Hz + tuner_frequency = ((params->frequency + 36125000) / 62500); + + // setup tuner buffer + tuner_buf[0] = tuner_frequency >> 8; + tuner_buf[1] = tuner_frequency & 0xff; + tuner_buf[2] = 0xc8; + tuner_buf[3] = (cp << 5) | (filter << 3) | band; + tuner_buf[4] = 0x80; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) { + printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 1\n"); + return -EIO; + } + + msleep(50); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) { + printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 2\n"); + return -EIO; + } + + msleep(1); + + return 0; +} + +static u8 dvbc_philips_tdm1316l_inittab[] = { + 0x80, 0x21, + 0x80, 0x20, + 0x81, 0x01, + 0x81, 0x00, + 0x00, 0x09, + 0x01, 0x69, + 0x03, 0x00, + 0x04, 0x00, + 0x07, 0x00, + 0x08, 0x00, + 0x20, 0x00, + 0x21, 0x40, + 0x22, 0x00, + 0x23, 0x00, + 0x24, 0x40, + 0x25, 0x88, + 0x30, 0xff, + 0x31, 0x00, + 0x32, 0xff, + 0x33, 0x00, + 0x34, 0x50, + 0x35, 0x7f, + 0x36, 0x00, + 0x37, 0x20, + 0x38, 0x00, + 0x40, 0x1c, + 0x41, 0xff, + 0x42, 0x29, + 0x43, 0x20, + 0x44, 0xff, + 0x45, 0x00, + 0x46, 0x00, + 0x49, 0x04, + 0x4a, 0xff, + 0x4b, 0x7f, + 0x52, 0x30, + 0x55, 0xae, + 0x56, 0x47, + 0x57, 0xe1, + 0x58, 0x3a, + 0x5a, 0x1e, + 0x5b, 0x34, + 0x60, 0x00, + 0x63, 0x00, + 0x64, 0x00, + 0x65, 0x00, + 0x66, 0x00, + 0x67, 0x00, + 0x68, 0x00, + 0x69, 0x00, + 0x6a, 0x02, + 0x6b, 0x00, + 0x70, 0xff, + 0x71, 0x00, + 0x72, 0x00, + 0x73, 0x00, + 0x74, 0x0c, + 0x80, 0x00, + 0x81, 0x00, + 0x82, 0x00, + 0x83, 0x00, + 0x84, 0x04, + 0x85, 0x80, + 0x86, 0x24, + 0x87, 0x78, + 0x88, 0x00, + 0x89, 0x00, + 0x90, 0x01, + 0x91, 0x01, + 0xa0, 0x00, + 0xa1, 0x00, + 0xa2, 0x00, + 0xb0, 0x91, + 0xb1, 0x0b, + 0xc0, 0x4b, + 0xc1, 0x00, + 0xc2, 0x00, + 0xd0, 0x00, + 0xd1, 0x00, + 0xd2, 0x00, + 0xd3, 0x00, + 0xd4, 0x00, + 0xd5, 0x00, + 0xde, 0x00, + 0xdf, 0x00, + 0x61, 0x38, + 0x62, 0x0a, + 0x53, 0x13, + 0x59, 0x08, + 0x55, 0x00, + 0x56, 0x40, + 0x57, 0x08, + 0x58, 0x3d, + 0x88, 0x10, + 0xa0, 0x00, + 0xa0, 0x00, + 0xa0, 0x00, + 0xa0, 0x04, + 0xff, 0xff, +}; + +static struct stv0297_config dvbc_philips_tdm1316l_config = { + .demod_address = 0x1c, + .inittab = dvbc_philips_tdm1316l_inittab, + .invert = 0, +}; + static void frontend_init(struct ttusb* ttusb) { switch(le16_to_cpu(ttusb->dev->descriptor.idProduct)) { @@ -1417,11 +1570,13 @@ static void frontend_init(struct ttusb* // try the stv0299 based first ttusb->fe = stv0299_attach(&alps_stv0299_config, &ttusb->i2c_adap); if (ttusb->fe != NULL) { + ttusb->fe->ops.tuner_ops.set_params = philips_tsa5059_tuner_set_params; + if(ttusb->revision == TTUSB_REV_2_2) { // ALPS BSBE1 alps_stv0299_config.inittab = alps_bsbe1_inittab; - ttusb->fe->ops->set_voltage = lnbp21_set_voltage; + lnbp21_attach(ttusb->fe, &ttusb->i2c_adap, 0, 0); } else { // ALPS BSRU6 - ttusb->fe->ops->set_voltage = ttusb_set_voltage; + ttusb->fe->ops.set_voltage = ttusb_set_voltage; } break; } @@ -1429,28 +1584,41 @@ static void frontend_init(struct ttusb* // Grundig 29504-491 ttusb->fe = tda8083_attach(&ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap); if (ttusb->fe != NULL) { - ttusb->fe->ops->set_voltage = ttusb_set_voltage; + ttusb->fe->ops.tuner_ops.set_params = ttusb_novas_grundig_29504_491_tuner_set_params; + ttusb->fe->ops.set_voltage = ttusb_set_voltage; break; } - break; case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659)) ttusb->fe = ves1820_attach(&alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb)); - if (ttusb->fe != NULL) + if (ttusb->fe != NULL) { + ttusb->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params; + break; + } + + ttusb->fe = stv0297_attach(&dvbc_philips_tdm1316l_config, &ttusb->i2c_adap); + if (ttusb->fe != NULL) { + ttusb->fe->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params; break; + } break; case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??)) // try the ALPS TDMB7 first ttusb->fe = cx22700_attach(&alps_tdmb7_config, &ttusb->i2c_adap); - if (ttusb->fe != NULL) + if (ttusb->fe != NULL) { + ttusb->fe->ops.tuner_ops.set_params = alps_tdmb7_tuner_set_params; break; + } // Philips td1316 ttusb->fe = tda10046_attach(&philips_tdm1316l_config, &ttusb->i2c_adap); - if (ttusb->fe != NULL) + if (ttusb->fe != NULL) { + ttusb->fe->ops.tuner_ops.init = philips_tdm1316l_tuner_init; + ttusb->fe->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params; break; + } break; } @@ -1461,8 +1629,8 @@ static void frontend_init(struct ttusb* } else { if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) { printk("dvb-ttusb-budget: Frontend registration failed!\n"); - if (ttusb->fe->ops->release) - ttusb->fe->ops->release(ttusb->fe); + if (ttusb->fe->ops.release) + ttusb->fe->ops.release(ttusb->fe); ttusb->fe = NULL; } } @@ -1507,7 +1675,7 @@ static int ttusb_probe(struct usb_interf mutex_unlock(&ttusb->semi2c); - if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE)) < 0) { + if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE, &udev->dev)) < 0) { ttusb_free_iso_urbs(ttusb); kfree(ttusb); return result; diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 44dea32..6c1cb77 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -1432,7 +1432,7 @@ static int ttusb_dec_init_dvb(struct ttu dprintk("%s\n", __FUNCTION__); if ((result = dvb_register_adapter(&dec->adapter, - dec->model_name, THIS_MODULE)) < 0) { + dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) { printk("%s: dvb_register_adapter failed: error %d\n", __FUNCTION__, result); @@ -1657,8 +1657,8 @@ static int ttusb_dec_probe(struct usb_in } else { if (dvb_register_frontend(&dec->adapter, dec->fe)) { printk("budget-ci: Frontend registration failed!\n"); - if (dec->fe->ops->release) - dec->fe->ops->release(dec->fe); + if (dec->fe->ops.release) + dec->fe->ops.release(dec->fe); dec->fe = NULL; } } diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c index a5a4617..42f39a8 100644 --- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c +++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c @@ -28,8 +28,6 @@ #define LOF_LO 9750000 struct ttusbdecfe_state { - struct dvb_frontend_ops ops; - /* configuration settings */ const struct ttusbdecfe_config* config; @@ -203,10 +201,9 @@ struct dvb_frontend* ttusbdecfe_dvbt_att /* setup the state */ state->config = config; - memcpy(&state->ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops)); /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; } @@ -226,10 +223,9 @@ struct dvb_frontend* ttusbdecfe_dvbs_att state->config = config; state->voltage = 0; state->hi_band = 0; - memcpy(&state->ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops)); /* create dvb_frontend */ - state->frontend.ops = &state->ops; + memcpy(&state->frontend.ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; return &state->frontend; } diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 3fff757..de3128a 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -136,7 +136,7 @@ config RADIO_GEMTEK_PCI Choose Y here if you have this PCI FM radio card. In order to control your radio card, you will need to use programs - that are compatible with the Video for Linux API. Information on + that are compatible with the Video for Linux API. Information on this API and pointers to "v4l" programs may be found at . diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 8b35194..e95b680 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -20,3 +20,5 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemt obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o + +EXTRA_CFLAGS += -Isound diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c index dc292da..c4312fa 100644 --- a/drivers/media/radio/miropcm20-radio.c +++ b/drivers/media/radio/miropcm20-radio.c @@ -16,13 +16,14 @@ /* What ever you think about the ACI, version 0x07 is not very well! * I can't get frequency, 'tuner status', 'tuner flags' or mute/mono - * conditions... Robert + * conditions... Robert */ #include #include #include -#include "../../../sound/oss/aci.h" +#include +#include "oss/aci.h" #include "miropcm20-rds-core.h" static int radio_nr = -1; @@ -123,7 +124,7 @@ static int pcm20_do_ioctl(struct inode * struct video_device *dev = video_devdata(file); struct pcm20_device *pcm20 = dev->priv; int i; - + switch(cmd) { case VIDIOCGCAP: @@ -139,7 +140,7 @@ static int pcm20_do_ioctl(struct inode * case VIDIOCGTUNER: { struct video_tuner *v = arg; - if(v->tuner) /* Only 1 tuner */ + if(v->tuner) /* Only 1 tuner */ return -EINVAL; v->rangelow=87*16000; v->rangehigh=108*16000; @@ -172,7 +173,7 @@ static int pcm20_do_ioctl(struct inode * return i; } case VIDIOCGAUDIO: - { + { struct video_audio *v = arg; memset(v,0, sizeof(*v)); v->flags=VIDEO_AUDIO_MUTABLE; @@ -183,12 +184,12 @@ static int pcm20_do_ioctl(struct inode * v->mode|=VIDEO_SOUND_MONO; /* v->step=2048; */ strcpy(v->name, "Radio"); - return 0; + return 0; } case VIDIOCSAUDIO: { struct video_audio *v = arg; - if(v->audio) + if(v->audio) return -EINVAL; pcm20_mute(pcm20, !!(v->flags&VIDEO_AUDIO_MUTE)); @@ -237,7 +238,7 @@ static int __init pcm20_init(void) { if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO, radio_nr)==-1) goto video_register_device; - + if(attach_aci_rds()<0) goto attach_aci_rds; diff --git a/drivers/media/radio/miropcm20-rds-core.c b/drivers/media/radio/miropcm20-rds-core.c index b602c73..9428d8b 100644 --- a/drivers/media/radio/miropcm20-rds-core.c +++ b/drivers/media/radio/miropcm20-rds-core.c @@ -21,7 +21,7 @@ #include #include #include -#include "../../../sound/oss/aci.h" +#include "oss/aci.h" #include "miropcm20-rds-core.h" #define DEBUG 0 @@ -33,24 +33,24 @@ #define RDS_DATAMASK (1 << RDS_DA #define RDS_BUSYMASK 0x10 /* Bit 4 */ #define RDS_CLOCKMASK 0x08 /* Bit 3 */ -#define RDS_DATA(x) (((x) >> RDS_DATASHIFT) & 1) +#define RDS_DATA(x) (((x) >> RDS_DATASHIFT) & 1) #if DEBUG static void print_matrix(char array[], unsigned int length) { - int i, j; - - for (i=0; i=0; j--) { - printk("%d", (array[i] >> j) & 0x1); - } - if (i%8 == 0) - printk(" byte-border\n"); - else - printk("\n"); - } + int i, j; + + for (i=0; i=0; j--) { + printk("%d", (array[i] >> j) & 0x1); + } + if (i%8 == 0) + printk(" byte-border\n"); + else + printk("\n"); + } } #endif /* DEBUG */ @@ -114,7 +114,7 @@ static int rds_write(unsigned char cmd) { unsigned char sendbuffer[8]; int i; - + if (byte2trans(cmd, sendbuffer, 8) != 0){ return -1; } else { @@ -151,7 +151,7 @@ static int rds_read(unsigned char databu I have to waitread() here */ if (rds_waitread() < 0) return -1; - + memset(databuffer, 0, datasize); for (i=0; i< READSIZE; i++) @@ -194,7 +194,7 @@ int aci_rds_cmd(unsigned char cmd, unsig ret = 0; mutex_unlock(&aci_rds_mutex); - + return ret; } EXPORT_SYMBOL(aci_rds_cmd); diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c index e092140..87b37b7 100644 --- a/drivers/media/radio/miropcm20-rds.c +++ b/drivers/media/radio/miropcm20-rds.c @@ -48,7 +48,7 @@ static int rds_f_release(struct inode *i static void print_matrix(char *ch, char out[]) { - int j; + int j; for (j=7; j>=0; j--) { out[7-j] = ((*ch >> j) & 0x1) + '0'; diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 557fb5c..df22a58 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -24,7 +24,7 @@ * out(port, start_increasing_volume); * wait(a_wee_while); * out(port, stop_changing_the_volume); - * + * */ #include /* Modules */ @@ -34,6 +34,7 @@ #include /* udelay */ #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ +#include #include /* CONFIG_RADIO_RTRACK_PORT */ #include /* Lock for the I/O */ @@ -41,7 +42,7 @@ #ifndef CONFIG_RADIO_RTRACK_PORT #define CONFIG_RADIO_RTRACK_PORT -1 #endif -static int io = CONFIG_RADIO_RTRACK_PORT; +static int io = CONFIG_RADIO_RTRACK_PORT; static int radio_nr = -1; static struct mutex lock; @@ -93,12 +94,12 @@ static int rt_setvol(struct rt_device *d int i; mutex_lock(&lock); - + if(vol == dev->curvol) { /* requested volume = current */ if (dev->muted) { /* user is unmuting the card */ dev->muted = 0; outb (0xd8, io); /* enable card */ - } + } mutex_unlock(&lock); return 0; } @@ -114,10 +115,10 @@ static int rt_setvol(struct rt_device *d dev->muted = 0; if(vol > dev->curvol) - for(i = dev->curvol; i < vol; i++) + for(i = dev->curvol; i < vol; i++) rt_incvol(); else - for(i = dev->curvol; i > vol; i--) + for(i = dev->curvol; i > vol; i--) rt_decvol(); dev->curvol = vol; @@ -125,7 +126,7 @@ static int rt_setvol(struct rt_device *d return 0; } -/* the 128+64 on these outb's is to keep the volume stable while tuning +/* the 128+64 on these outb's is to keep the volume stable while tuning * without them, the volume _will_ creep up with each frequency change * and bit 4 (+16) is to keep the signal strength meter enabled */ @@ -140,7 +141,7 @@ static void send_0_byte(int port, struct outb_p(128+64+16+8+ 1, port); /* on + wr-enable + data low */ outb_p(128+64+16+8+2+1, port); /* clock */ } - sleep_delay(1000); + sleep_delay(1000); } static void send_1_byte(int port, struct rt_device *dev) @@ -148,13 +149,13 @@ static void send_1_byte(int port, struct if ((dev->curvol == 0) || (dev->muted)) { outb_p(128+64+16+4 +1, port); /* wr-enable+data high */ outb_p(128+64+16+4+2+1, port); /* clock */ - } + } else { outb_p(128+64+16+8+4 +1, port); /* on+wr-enable+data high */ outb_p(128+64+16+8+4+2+1, port); /* clock */ } - sleep_delay(1000); + sleep_delay(1000); } static int rt_setfreq(struct rt_device *dev, unsigned long freq) @@ -167,9 +168,9 @@ static int rt_setfreq(struct rt_device * freq += 171200; /* Add 10.7 MHz IF */ freq /= 800; /* Convert to 50 kHz units */ - + mutex_lock(&lock); /* Stop other ops interfering */ - + send_0_byte (io, dev); /* 0: LSB of frequency */ for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ @@ -195,7 +196,7 @@ static int rt_setfreq(struct rt_device * outb (0xd0, io); /* volume steady + sigstr */ else outb (0xd8, io); /* volume steady + sigstr + on */ - + mutex_unlock(&lock); return 0; @@ -213,7 +214,7 @@ static int rt_do_ioctl(struct inode *ino { struct video_device *dev = video_devdata(file); struct rt_device *rt=dev->priv; - + switch(cmd) { case VIDIOCGCAP: @@ -229,7 +230,7 @@ static int rt_do_ioctl(struct inode *ino case VIDIOCGTUNER: { struct video_tuner *v = arg; - if(v->tuner) /* Only 1 tuner */ + if(v->tuner) /* Only 1 tuner */ return -EINVAL; v->rangelow=(87*16000); v->rangehigh=(108*16000); @@ -261,21 +262,21 @@ static int rt_do_ioctl(struct inode *ino return 0; } case VIDIOCGAUDIO: - { + { struct video_audio *v = arg; memset(v,0, sizeof(*v)); v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME; v->volume=rt->curvol * 6554; v->step=6554; strcpy(v->name, "Radio"); - return 0; + return 0; } case VIDIOCSAUDIO: { struct video_audio *v = arg; - if(v->audio) + if(v->audio) return -EINVAL; - if(v->flags&VIDEO_AUDIO_MUTE) + if(v->flags&VIDEO_AUDIO_MUTE) rt_mute(rt); else rt_setvol(rt,v->volume/6554); @@ -298,7 +299,7 @@ static struct file_operations rtrack_fop .owner = THIS_MODULE, .open = video_exclusive_open, .release = video_exclusive_release, - .ioctl = rt_ioctl, + .ioctl = rt_ioctl, .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; @@ -320,14 +321,14 @@ static int __init rtrack_init(void) return -EINVAL; } - if (!request_region(io, 2, "rtrack")) + if (!request_region(io, 2, "rtrack")) { printk(KERN_ERR "rtrack: port 0x%x already in use\n", io); return -EBUSY; } rtrack_radio.priv=&rtrack_unit; - + if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr)==-1) { release_region(io, 2); @@ -336,10 +337,10 @@ static int __init rtrack_init(void) printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n"); /* Set up the I/O locking */ - + mutex_init(&lock); - - /* mute card - prevents noisy bootups */ + + /* mute card - prevents noisy bootups */ /* this ensures that the volume is all the way down */ outb(0x48, io); /* volume down but still "on" */ diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 83bdae2..95e6322 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -1,11 +1,11 @@ -/* radio-aztech.c - Aztech radio card driver for Linux 2.2 +/* radio-aztech.c - Aztech radio card driver for Linux 2.2 * - * Adapted to support the Video for Linux API by + * Adapted to support the Video for Linux API by * Russell Kroll . Based on original tuner code by: * * Quay Ly * Donald Song - * Jason Lewis (jlewis@twilight.vtc.vsc.edu) + * Jason Lewis (jlewis@twilight.vtc.vsc.edu) * Scott McGrath (smcgrath@twilight.vtc.vsc.edu) * William McGrath (wmcgrath@twilight.vtc.vsc.edu) * @@ -31,6 +31,7 @@ #include /* udelay */ #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ +#include #include /* CONFIG_RADIO_AZTECH_PORT */ /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ @@ -39,7 +40,7 @@ #ifndef CONFIG_RADIO_AZTECH_PORT #define CONFIG_RADIO_AZTECH_PORT -1 #endif -static int io = CONFIG_RADIO_AZTECH_PORT; +static int io = CONFIG_RADIO_AZTECH_PORT; static int radio_nr = -1; static int radio_wait_time = 1000; static struct mutex lock; @@ -53,15 +54,15 @@ struct az_device static int volconvert(int level) { - level>>=14; /* Map 16bits down to 2 bit */ - level&=3; - + level>>=14; /* Map 16bits down to 2 bit */ + level&=3; + /* convert to card-friendly values */ - switch (level) + switch (level) { - case 0: + case 0: return 0; - case 1: + case 1: return 1; case 2: return 4; @@ -121,9 +122,9 @@ static int az_setfreq(struct az_device * frequency += 171200; /* Add 10.7 MHz IF */ frequency /= 800; /* Convert to 50 kHz units */ - + mutex_lock(&lock); - + send_0_byte (dev); /* 0: LSB of frequency */ for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ @@ -151,7 +152,7 @@ static int az_setfreq(struct az_device * udelay (radio_wait_time); outb_p(128+64+volconvert(dev->curvol), io); - + mutex_unlock(&lock); return 0; @@ -162,7 +163,7 @@ static int az_do_ioctl(struct inode *ino { struct video_device *dev = video_devdata(file); struct az_device *az = dev->priv; - + switch(cmd) { case VIDIOCGCAP: @@ -178,7 +179,7 @@ static int az_do_ioctl(struct inode *ino case VIDIOCGTUNER: { struct video_tuner *v = arg; - if(v->tuner) /* Only 1 tuner */ + if(v->tuner) /* Only 1 tuner */ return -EINVAL; v->rangelow=(87*16000); v->rangehigh=(108*16000); @@ -211,7 +212,7 @@ static int az_do_ioctl(struct inode *ino return 0; } case VIDIOCGAUDIO: - { + { struct video_audio *v = arg; memset(v,0, sizeof(*v)); v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME; @@ -222,17 +223,17 @@ static int az_do_ioctl(struct inode *ino v->volume=az->curvol; v->step=16384; strcpy(v->name, "Radio"); - return 0; + return 0; } case VIDIOCSAUDIO: { struct video_audio *v = arg; - if(v->audio) + if(v->audio) return -EINVAL; az->curvol=v->volume; az->stereo=(v->mode&VIDEO_SOUND_STEREO)?1:0; - if(v->flags&VIDEO_AUDIO_MUTE) + if(v->flags&VIDEO_AUDIO_MUTE) az_setvol(az,0); else az_setvol(az,az->curvol); @@ -277,7 +278,7 @@ static int __init aztech_init(void) return -EINVAL; } - if (!request_region(io, 2, "aztech")) + if (!request_region(io, 2, "aztech")) { printk(KERN_ERR "aztech: port 0x%x already in use\n", io); return -EBUSY; @@ -285,13 +286,13 @@ static int __init aztech_init(void) mutex_init(&lock); aztech_radio.priv=&aztech_unit; - + if(video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr)==-1) { release_region(io,2); return -EINVAL; } - + printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); /* mute card - prevents noisy bootups */ outb (0, io); diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index f1b5ac8..8641aec 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -8,7 +8,7 @@ * Russell Kroll (rkroll@exploits.org) * Quay Ly * Donald Song - * Jason Lewis (jlewis@twilight.vtc.vsc.edu) + * Jason Lewis (jlewis@twilight.vtc.vsc.edu) * Scott McGrath (smcgrath@twilight.vtc.vsc.edu) * William McGrath (wmcgrath@twilight.vtc.vsc.edu) * @@ -34,6 +34,7 @@ #include /* udelay */ #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ +#include #include #include @@ -55,29 +56,29 @@ static int cadet_probe(void); /* * Signal Strength Threshold Values - * The V4L API spec does not define any particular unit for the signal + * The V4L API spec does not define any particular unit for the signal * strength value. These values are in microvolts of RF at the tuner's input. */ static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}}; static int cadet_getrds(void) { - int rdsstat=0; + int rdsstat=0; spin_lock(&cadet_io_lock); - outb(3,io); /* Select Decoder Control/Status */ + outb(3,io); /* Select Decoder Control/Status */ outb(inb(io+1)&0x7f,io+1); /* Reset RDS detection */ spin_unlock(&cadet_io_lock); - + msleep(100); - spin_lock(&cadet_io_lock); - outb(3,io); /* Select Decoder Control/Status */ + spin_lock(&cadet_io_lock); + outb(3,io); /* Select Decoder Control/Status */ if((inb(io+1)&0x80)!=0) { - rdsstat|=VIDEO_TUNER_RDS_ON; + rdsstat|=VIDEO_TUNER_RDS_ON; } if((inb(io+1)&0x10)!=0) { - rdsstat|=VIDEO_TUNER_MBS_ON; + rdsstat|=VIDEO_TUNER_MBS_ON; } spin_unlock(&cadet_io_lock); return rdsstat; @@ -86,49 +87,49 @@ static int cadet_getrds(void) static int cadet_getstereo(void) { int ret = 0; - if(curtuner != 0) /* Only FM has stereo capability! */ - return 0; + if(curtuner != 0) /* Only FM has stereo capability! */ + return 0; spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ + outb(7,io); /* Select tuner control */ if( (inb(io+1) & 0x40) == 0) - ret = 1; - spin_unlock(&cadet_io_lock); - return ret; + ret = 1; + spin_unlock(&cadet_io_lock); + return ret; } static unsigned cadet_gettune(void) { - int curvol,i; + int curvol,i; unsigned fifo=0; - /* - * Prepare for read - */ + /* + * Prepare for read + */ spin_lock(&cadet_io_lock); - - outb(7,io); /* Select tuner control */ - curvol=inb(io+1); /* Save current volume/mute setting */ - outb(0x00,io+1); /* Ensure WRITE-ENABLE is LOW */ + + outb(7,io); /* Select tuner control */ + curvol=inb(io+1); /* Save current volume/mute setting */ + outb(0x00,io+1); /* Ensure WRITE-ENABLE is LOW */ tunestat=0xffff; - /* - * Read the shift register - */ - for(i=0;i<25;i++) { - fifo=(fifo<<1)|((inb(io+1)>>7)&0x01); - if(i<24) { - outb(0x01,io+1); + /* + * Read the shift register + */ + for(i=0;i<25;i++) { + fifo=(fifo<<1)|((inb(io+1)>>7)&0x01); + if(i<24) { + outb(0x01,io+1); tunestat&=inb(io+1); - outb(0x00,io+1); - } - } - - /* - * Restore volume/mute setting - */ - outb(curvol,io+1); + outb(0x00,io+1); + } + } + + /* + * Restore volume/mute setting + */ + outb(curvol,io+1); spin_unlock(&cadet_io_lock); return fifo; @@ -136,43 +137,43 @@ static unsigned cadet_gettune(void) static unsigned cadet_getfreq(void) { - int i; - unsigned freq=0,test,fifo=0; + int i; + unsigned freq=0,test,fifo=0; /* * Read current tuning */ fifo=cadet_gettune(); - /* - * Convert to actual frequency - */ + /* + * Convert to actual frequency + */ if(curtuner==0) { /* FM */ - test=12500; - for(i=0;i<14;i++) { - if((fifo&0x01)!=0) { - freq+=test; - } - test=test<<1; - fifo=fifo>>1; - } - freq-=10700000; /* IF frequency is 10.7 MHz */ - freq=(freq*16)/1000000; /* Make it 1/16 MHz */ + test=12500; + for(i=0;i<14;i++) { + if((fifo&0x01)!=0) { + freq+=test; + } + test=test<<1; + fifo=fifo>>1; + } + freq-=10700000; /* IF frequency is 10.7 MHz */ + freq=(freq*16)/1000000; /* Make it 1/16 MHz */ } if(curtuner==1) { /* AM */ - freq=((fifo&0x7fff)-2010)*16; + freq=((fifo&0x7fff)-2010)*16; } - return freq; + return freq; } static void cadet_settune(unsigned fifo) { - int i; - unsigned test; + int i; + unsigned test; spin_lock(&cadet_io_lock); - + outb(7,io); /* Select tuner control */ /* * Write the shift register @@ -183,7 +184,7 @@ static void cadet_settune(unsigned fifo) outb(7,io); /* Select tuner control */ outb(test,io+1); /* Initialize for write */ for(i=0;i<25;i++) { - test|=0x01; /* Toggle SCK High */ + test|=0x01; /* Toggle SCK High */ outb(test,io+1); test&=0xfe; /* Toggle SCK Low */ outb(test,io+1); @@ -196,57 +197,57 @@ static void cadet_settune(unsigned fifo) static void cadet_setfreq(unsigned freq) { - unsigned fifo; - int i,j,test; - int curvol; + unsigned fifo; + int i,j,test; + int curvol; - /* - * Formulate a fifo command - */ + /* + * Formulate a fifo command + */ fifo=0; if(curtuner==0) { /* FM */ - test=102400; - freq=(freq*1000)/16; /* Make it kHz */ - freq+=10700; /* IF is 10700 kHz */ - for(i=0;i<14;i++) { - fifo=fifo<<1; - if(freq>=test) { - fifo|=0x01; - freq-=test; - } - test=test>>1; - } + test=102400; + freq=(freq*1000)/16; /* Make it kHz */ + freq+=10700; /* IF is 10700 kHz */ + for(i=0;i<14;i++) { + fifo=fifo<<1; + if(freq>=test) { + fifo|=0x01; + freq-=test; + } + test=test>>1; + } } if(curtuner==1) { /* AM */ - fifo=(freq/16)+2010; /* Make it kHz */ + fifo=(freq/16)+2010; /* Make it kHz */ fifo|=0x100000; /* Select AM Band */ } - /* - * Save current volume/mute setting - */ + /* + * Save current volume/mute setting + */ spin_lock(&cadet_io_lock); outb(7,io); /* Select tuner control */ - curvol=inb(io+1); - spin_unlock(&cadet_io_lock); + curvol=inb(io+1); + spin_unlock(&cadet_io_lock); /* * Tune the card */ for(j=3;j>-1;j--) { - cadet_settune(fifo|(j<<16)); - - spin_lock(&cadet_io_lock); + cadet_settune(fifo|(j<<16)); + + spin_lock(&cadet_io_lock); outb(7,io); /* Select tuner control */ outb(curvol,io+1); spin_unlock(&cadet_io_lock); - + msleep(100); cadet_gettune(); if((tunestat & 0x40) == 0) { /* Tuned */ - sigstrength=sigtable[curtuner][j]; + sigstrength=sigtable[curtuner][j]; return; } } @@ -257,28 +258,28 @@ static void cadet_setfreq(unsigned freq) static int cadet_getvol(void) { int ret = 0; - + spin_lock(&cadet_io_lock); - - outb(7,io); /* Select tuner control */ - if((inb(io + 1) & 0x20) != 0) - ret = 0xffff; - - spin_unlock(&cadet_io_lock); - return ret; + + outb(7,io); /* Select tuner control */ + if((inb(io + 1) & 0x20) != 0) + ret = 0xffff; + + spin_unlock(&cadet_io_lock); + return ret; } static void cadet_setvol(int vol) { spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - if(vol>0) - outb(0x20,io+1); - else - outb(0x00,io+1); + outb(7,io); /* Select tuner control */ + if(vol>0) + outb(0x20,io+1); + else + outb(0x00,io+1); spin_unlock(&cadet_io_lock); -} +} static void cadet_handler(unsigned long data) { @@ -288,15 +289,15 @@ static void cadet_handler(unsigned long if(spin_trylock(&cadet_io_lock)) { - outb(0x3,io); /* Select RDS Decoder Control */ + outb(0x3,io); /* Select RDS Decoder Control */ if((inb(io+1)&0x20)!=0) { - printk(KERN_CRIT "cadet: RDS fifo overflow\n"); + printk(KERN_CRIT "cadet: RDS fifo overflow\n"); } outb(0x80,io); /* Select RDS fifo */ while((inb(io)&0x80)!=0) { - rdsbuf[rdsin]=inb(io+1); + rdsbuf[rdsin]=inb(io+1); if(rdsin==rdsout) - printk(KERN_WARNING "cadet: RDS buffer overflow\n"); + printk(KERN_WARNING "cadet: RDS buffer overflow\n"); else rdsin++; } @@ -307,9 +308,9 @@ static void cadet_handler(unsigned long * Service pending read */ if( rdsin!=rdsout) - wake_up_interruptible(&read_queue); + wake_up_interruptible(&read_queue); - /* + /* * Clean up and exit */ init_timer(&readtimer); @@ -324,12 +325,12 @@ static void cadet_handler(unsigned long static ssize_t cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { - int i=0; + int i=0; unsigned char readbuf[RDS_BUFFER]; - if(rdsstat==0) { + if(rdsstat==0) { spin_lock(&cadet_io_lock); - rdsstat=1; + rdsstat=1; outb(0x80,io); /* Select RDS fifo */ spin_unlock(&cadet_io_lock); init_timer(&readtimer); @@ -339,15 +340,15 @@ static ssize_t cadet_read(struct file *f add_timer(&readtimer); } if(rdsin==rdsout) { - if (file->f_flags & O_NONBLOCK) - return -EWOULDBLOCK; - interruptible_sleep_on(&read_queue); - } + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + interruptible_sleep_on(&read_queue); + } while( ituner) { - case 0: - strcpy(v->name,"FM"); - v->rangelow=1400; /* 87.5 MHz */ - v->rangehigh=1728; /* 108.0 MHz */ - v->flags=0; - v->mode=0; - v->mode|=VIDEO_MODE_AUTO; - v->signal=sigstrength; - if(cadet_getstereo()==1) { - v->flags|=VIDEO_TUNER_STEREO_ON; - } + case 0: + strcpy(v->name,"FM"); + v->rangelow=1400; /* 87.5 MHz */ + v->rangehigh=1728; /* 108.0 MHz */ + v->flags=0; + v->mode=0; + v->mode|=VIDEO_MODE_AUTO; + v->signal=sigstrength; + if(cadet_getstereo()==1) { + v->flags|=VIDEO_TUNER_STEREO_ON; + } v->flags|=cadet_getrds(); - break; - case 1: - strcpy(v->name,"AM"); - v->rangelow=8320; /* 520 kHz */ - v->rangehigh=26400; /* 1650 kHz */ - v->flags=0; - v->flags|=VIDEO_TUNER_LOW; - v->mode=0; - v->mode|=VIDEO_MODE_AUTO; - v->signal=sigstrength; - break; + break; + case 1: + strcpy(v->name,"AM"); + v->rangelow=8320; /* 520 kHz */ + v->rangehigh=26400; /* 1650 kHz */ + v->flags=0; + v->flags|=VIDEO_TUNER_LOW; + v->mode=0; + v->mode|=VIDEO_MODE_AUTO; + v->signal=sigstrength; + break; } return 0; } @@ -407,49 +408,49 @@ static int cadet_do_ioctl(struct inode * if((v->tuner<0)||(v->tuner>1)) { return -EINVAL; } - curtuner=v->tuner; + curtuner=v->tuner; return 0; } case VIDIOCGFREQ: { - unsigned long *freq = arg; + unsigned long *freq = arg; *freq = cadet_getfreq(); return 0; } case VIDIOCSFREQ: { - unsigned long *freq = arg; + unsigned long *freq = arg; if((curtuner==0)&&((*freq<1400)||(*freq>1728))) { - return -EINVAL; + return -EINVAL; } if((curtuner==1)&&((*freq<8320)||(*freq>26400))) { - return -EINVAL; + return -EINVAL; } cadet_setfreq(*freq); return 0; } case VIDIOCGAUDIO: - { + { struct video_audio *v = arg; memset(v,0, sizeof(*v)); v->flags=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME; if(cadet_getstereo()==0) { - v->mode=VIDEO_SOUND_MONO; + v->mode=VIDEO_SOUND_MONO; } else { v->mode=VIDEO_SOUND_STEREO; } v->volume=cadet_getvol(); v->step=0xffff; strcpy(v->name, "Radio"); - return 0; + return 0; } case VIDIOCSAUDIO: { struct video_audio *v = arg; - if(v->audio) + if(v->audio) return -EINVAL; cadet_setvol(v->volume); - if(v->flags&VIDEO_AUDIO_MUTE) + if(v->flags&VIDEO_AUDIO_MUTE) cadet_setvol(0); else cadet_setvol(0xffff); @@ -539,16 +540,16 @@ static struct pnp_driver cadet_pnp_drive static int cadet_probe(void) { - static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e}; + static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e}; int i; for(i=0;i<8;i++) { - io=iovals[i]; + io=iovals[i]; if (request_region(io, 2, "cadet-probe")) { - cadet_setfreq(1410); + cadet_setfreq(1410); if(cadet_getfreq()==1410) { release_region(io, 2); - return io; + return io; } release_region(io, 2); } @@ -556,7 +557,7 @@ static int cadet_probe(void) return -1; } -/* +/* * io should only be set if the user has used something like * isapnp (the userspace program) to initialize this card for us */ @@ -564,7 +565,7 @@ static int cadet_probe(void) static int __init cadet_init(void) { spin_lock_init(&cadet_io_lock); - + /* * If a probe was requested then probe ISAPnP first (safest) */ @@ -579,12 +580,12 @@ static int __init cadet_init(void) /* * Else we bail out */ - - if(io < 0) { -#ifdef MODULE + + if(io < 0) { +#ifdef MODULE printk(KERN_ERR "You must set an I/O address with io=0x???\n"); #endif - goto fail; + goto fail; } if (!request_region(io,2,"cadet")) goto fail; diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index 8e499b8..9f249e7 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -1,6 +1,6 @@ /* *************************************************************************** - * + * * radio-gemtek-pci.c - Gemtek PCI Radio driver * (C) 2001 Vladimir Shebordaev * @@ -31,7 +31,7 @@ * radio device driver. * * Please, let me know if this piece of code was useful :) - * + * * TODO: multiple device support and portability were not tested * *************************************************************************** @@ -44,6 +44,7 @@ #include #include #include #include +#include #include #include @@ -69,18 +70,18 @@ #ifndef TRUE #define TRUE (1) #endif -#ifndef FALSE +#ifndef FALSE #define FALSE (0) #endif struct gemtek_pci_card { struct video_device *videodev; - + u32 iobase; u32 length; u8 chiprev; u16 model; - + u32 current_frequency; u8 mute; }; @@ -96,7 +97,7 @@ static inline u8 gemtek_pci_out( u16 val return (u8)value; } -#define _b0( v ) *((u8 *)&v) +#define _b0( v ) *((u8 *)&v) static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep ) { register u8 byte = *last_byte; @@ -104,7 +105,7 @@ static void __gemtek_pci_cmd( u16 value, if ( !value ) { if ( !keep ) value = (u16)port; - byte &= 0xfd; + byte &= 0xfd; } else byte |= 2; @@ -116,7 +117,7 @@ static void __gemtek_pci_cmd( u16 value, byte &= 0xfe; _b0( value ) = byte; outw( value, port ); - + *last_byte = byte; } @@ -193,13 +194,13 @@ static int gemtek_pci_do_ioctl(struct in c->audios = 1; strcpy( c->name, "Gemtek PCI Radio" ); return 0; - } + } case VIDIOCGTUNER: { struct video_tuner *t = arg; - if ( t->tuner ) + if ( t->tuner ) return -EINVAL; t->rangelow = GEMTEK_PCI_RANGE_LOW; @@ -228,7 +229,7 @@ static int gemtek_pci_do_ioctl(struct in case VIDIOCSFREQ: { unsigned long *freq = arg; - + if ( (*freq < GEMTEK_PCI_RANGE_LOW) || (*freq > GEMTEK_PCI_RANGE_HIGH) ) return -EINVAL; @@ -239,9 +240,9 @@ static int gemtek_pci_do_ioctl(struct in return 0; } - + case VIDIOCGAUDIO: - { + { struct video_audio *a = arg; memset( a, 0, sizeof( *a ) ); @@ -249,17 +250,17 @@ static int gemtek_pci_do_ioctl(struct in a->volume = 1; a->step = 65535; strcpy( a->name, "Radio" ); - return 0; + return 0; } case VIDIOCSAUDIO: { struct video_audio *a = arg; - if ( a->audio ) + if ( a->audio ) return -EINVAL; - if ( a->flags & VIDEO_AUDIO_MUTE ) + if ( a->flags & VIDEO_AUDIO_MUTE ) gemtek_pci_mute( card ); else gemtek_pci_unmute( card ); @@ -323,9 +324,9 @@ static int __devinit gemtek_pci_probe( s return -ENOMEM; } - if ( pci_enable_device( pci_dev ) ) + if ( pci_enable_device( pci_dev ) ) goto err_pci; - + card->iobase = pci_resource_start( pci_dev, 0 ); card->length = pci_resource_len( pci_dev, 0 ); @@ -338,7 +339,7 @@ static int __devinit gemtek_pci_probe( s pci_read_config_word( pci_dev, PCI_SUBSYSTEM_ID, &card->model ); pci_set_drvdata( pci_dev, card ); - + if ( (devradio = kmalloc( sizeof( struct video_device ), GFP_KERNEL )) == NULL ) { printk( KERN_ERR "gemtek_pci: out of memory\n" ); goto err_video; @@ -354,7 +355,7 @@ static int __devinit gemtek_pci_probe( s devradio->priv = card; gemtek_pci_mute( card ); - printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", + printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", card->chiprev, card->iobase, card->iobase + card->length - 1 ); return 0; @@ -364,7 +365,7 @@ err_video: err_pci: kfree( card ); - return -ENODEV; + return -ENODEV; } static void __devexit gemtek_pci_remove( struct pci_dev *pci_dev ) @@ -375,12 +376,12 @@ static void __devexit gemtek_pci_remove( kfree( card->videodev ); release_region( card->iobase, card->length ); - + if ( mx ) gemtek_pci_mute( card ); kfree( card ); - + pci_set_drvdata( pci_dev, NULL ); } diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 47173be..162f37d 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -6,7 +6,7 @@ * Besides the protocol changes, this is mostly a copy of: * * RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff - * + * * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood * Converted to new API by Alan Cox * Various bugfixes and enhancements by Russell Kroll @@ -22,6 +22,7 @@ #include /* udelay */ #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ +#include #include /* CONFIG_RADIO_GEMTEK_PORT */ #include @@ -29,7 +30,7 @@ #ifndef CONFIG_RADIO_GEMTEK_PORT #define CONFIG_RADIO_GEMTEK_PORT -1 #endif -static int io = CONFIG_RADIO_GEMTEK_PORT; +static int io = CONFIG_RADIO_GEMTEK_PORT; static int radio_nr = -1; static spinlock_t lock; @@ -48,7 +49,7 @@ struct gemtek_device */ static void gemtek_mute(struct gemtek_device *dev) { - if(dev->muted) + if(dev->muted) return; spin_lock(&lock); outb(0x10, io); @@ -94,20 +95,20 @@ static int gemtek_setfreq(struct gemtek_ freq /= 100000; spin_lock(&lock); - + /* 2 start bits */ outb_p(0x03, io); udelay(5); outb_p(0x07, io); udelay(5); - /* 28 frequency bits (lsb first) */ + /* 28 frequency bits (lsb first) */ for (i = 0; i < 14; i++) if (freq & (1 << i)) one(); else zero(); - /* 36 unknown bits */ + /* 36 unknown bits */ for (i = 0; i < 11; i++) zero(); one(); @@ -123,7 +124,7 @@ static int gemtek_setfreq(struct gemtek_ udelay(5); spin_unlock(&lock); - + return 0; } @@ -159,7 +160,7 @@ static int gemtek_do_ioctl(struct inode case VIDIOCGTUNER: { struct video_tuner *v = arg; - if(v->tuner) /* Only 1 tuner */ + if(v->tuner) /* Only 1 tuner */ return -EINVAL; v->rangelow=87*16000; v->rangehigh=108*16000; @@ -193,25 +194,25 @@ static int gemtek_do_ioctl(struct inode return 0; } case VIDIOCGAUDIO: - { + { struct video_audio *v = arg; memset(v,0, sizeof(*v)); v->flags|=VIDEO_AUDIO_MUTABLE; v->volume=1; v->step=65535; strcpy(v->name, "Radio"); - return 0; + return 0; } case VIDIOCSAUDIO: { struct video_audio *v = arg; - if(v->audio) + if(v->audio) return -EINVAL; - if(v->flags&VIDEO_AUDIO_MUTE) + if(v->flags&VIDEO_AUDIO_MUTE) gemtek_mute(rt); else - gemtek_unmute(rt); + gemtek_unmute(rt); return 0; } @@ -254,14 +255,14 @@ static int __init gemtek_init(void) return -EINVAL; } - if (!request_region(io, 4, "gemtek")) + if (!request_region(io, 4, "gemtek")) { printk(KERN_ERR "gemtek: port 0x%x already in use\n", io); return -EBUSY; } gemtek_radio.priv=&gemtek_unit; - + if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr)==-1) { release_region(io, 4); @@ -274,7 +275,7 @@ static int __init gemtek_init(void) /* this is _maybe_ unnecessary */ outb(0x01, io); - /* mute card - prevents noisy bootups */ + /* mute card - prevents noisy bootups */ gemtek_unit.muted = 0; gemtek_mute(&gemtek_unit); diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 39c1d91..fcfa6c9 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -2,7 +2,7 @@ * (c) 2000 A. Tlalka, atlka@pg.gda.pl * Notes on the hardware * - * + Frequency control is done digitally + * + Frequency control is done digitally * + No volume control - only mute/unmute - you have to use Aux line volume * control on Maestro card to set the volume * + Radio status (tuned/not_tuned and stereo/mono) is valid some time after @@ -26,7 +26,7 @@ #include #include #include #include - +#include #define DRIVER_VERSION "0.05" @@ -103,7 +103,7 @@ static struct video_device maestro_radio struct radio_device { u16 io, /* base of Maestro card radio io (GPIO_DATA)*/ muted, /* VIDEO_AUDIO_MUTE */ - stereo, /* VIDEO_TUNER_STEREO_ON */ + stereo, /* VIDEO_TUNER_STEREO_ON */ tuned; /* signal strength (0 or 0xffff) */ struct mutex lock; }; @@ -122,14 +122,14 @@ static u32 radio_bits_get(struct radio_d for (l=24;l--;) { outw(STR_CLK, io); /* HI state */ udelay(2); - if(!l) + if(!l) dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff; outw(0, io); /* LO state */ udelay(2); data <<= 1; /* shift data */ rdata = inw(io); if(!l) - dev->stereo = rdata & STR_MOST ? + dev->stereo = rdata & STR_MOST ? 0 : VIDEO_TUNER_STEREO_ON; else if(rdata & STR_DATA) diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index f0bf47b..f93d7af 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -1,15 +1,15 @@ -/* - * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux +/* + * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux * (C) 2001 Dimitromanolakis Apostolos * * Based in the radio Maestro PCI driver. Actually it uses the same chip * for radio but different pci controller. * * I didn't have any specs I reversed engineered the protocol from - * the windows driver (radio.dll). + * the windows driver (radio.dll). * * The card uses the TEA5757 chip that includes a search function but it - * is useless as I haven't found any way to read back the frequency. If + * is useless as I haven't found any way to read back the frequency. If * anybody does please mail me. * * For the pdf file see: @@ -24,7 +24,7 @@ * - tiding up * - removed support for multiple devices as it didn't work anyway * - * BUGS: + * BUGS: * - card unmutes if you change frequency * */ @@ -41,6 +41,7 @@ #include #include #include +#include /* version 0.75 Sun Feb 4 22:51:27 EET 2001 */ #define DRIVER_VERSION "0.75" @@ -80,7 +81,7 @@ static struct file_operations maxiradio_ .owner = THIS_MODULE, .open = video_exclusive_open, .release = video_exclusive_release, - .ioctl = radio_ioctl, + .ioctl = radio_ioctl, .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; @@ -97,11 +98,11 @@ static struct radio_device { __u16 io, /* base of radio io */ muted, /* VIDEO_AUDIO_MUTE */ - stereo, /* VIDEO_TUNER_STEREO_ON */ + stereo, /* VIDEO_TUNER_STEREO_ON */ tuned; /* signal strength (0 or 0xffff) */ - + unsigned long freq; - + struct mutex lock; } radio_unit = {0, 0, 0, 0, }; @@ -114,7 +115,7 @@ static void outbit(unsigned long bit, __ outb( power|wren|data|clk ,io); udelay(4); outb( power|wren|data ,io); udelay(4); } - else + else { outb( power|wren ,io); udelay(4); outb( power|wren|clk ,io); udelay(4); @@ -132,12 +133,12 @@ static void set_freq(__u16 io, __u32 dat { unsigned long int si; int bl; - + /* TEA5757 shift register bits (see pdf) */ - outbit(0,io); // 24 search + outbit(0,io); // 24 search outbit(1,io); // 23 search up/down - + outbit(0,io); // 22 stereo/mono outbit(0,io); // 21 band @@ -145,24 +146,24 @@ static void set_freq(__u16 io, __u32 dat outbit(0,io); // 19 port ? outbit(0,io); // 18 port ? - + outbit(0,io); // 17 search level outbit(0,io); // 16 search level - + si = 0x8000; for(bl = 1; bl <= 16 ; bl++) { outbit(data & si,io); si >>=1; } - + outb(power,io); } static int get_stereo(__u16 io) -{ +{ outb(power,io); udelay(4); return !(inb(io) & mo_st); } static int get_tune(__u16 io) -{ +{ outb(power+clk,io); udelay(4); return !(inb(io) & mo_st); } @@ -177,7 +178,7 @@ static inline int radio_function(struct switch(cmd) { case VIDIOCGCAP: { struct video_capability *v = arg; - + memset(v,0,sizeof(*v)); strcpy(v->name, "Maxi Radio FM2000 radio"); v->type=VID_TYPE_TUNER; @@ -186,22 +187,22 @@ static inline int radio_function(struct } case VIDIOCGTUNER: { struct video_tuner *v = arg; - + if(v->tuner) return -EINVAL; - + card->stereo = 0xffff * get_stereo(card->io); card->tuned = 0xffff * get_tune(card->io); - + v->flags = VIDEO_TUNER_LOW | card->stereo; v->signal = card->tuned; - + strcpy(v->name, "FM"); - + v->rangelow = FREQ_LO; v->rangehigh = FREQ_HI; v->mode = VIDEO_MODE_AUTO; - + return 0; } case VIDIOCSTUNER: { @@ -212,13 +213,13 @@ static inline int radio_function(struct } case VIDIOCGFREQ: { unsigned long *freq = arg; - + *freq = card->freq; return 0; } case VIDIOCSFREQ: { unsigned long *freq = arg; - + if (*freq < FREQ_LO || *freq > FREQ_HI) return -EINVAL; card->freq = *freq; @@ -226,18 +227,18 @@ static inline int radio_function(struct msleep(125); return 0; } - case VIDIOCGAUDIO: { + case VIDIOCGAUDIO: { struct video_audio *v = arg; memset(v,0,sizeof(*v)); strcpy(v->name, "Radio"); v->flags=VIDEO_AUDIO_MUTABLE | card->muted; v->mode=VIDEO_SOUND_STEREO; - return 0; + return 0; } - + case VIDIOCSAUDIO: { struct video_audio *v = arg; - + if(v->audio) return -EINVAL; card->muted = v->flags & VIDEO_AUDIO_MUTE; @@ -249,13 +250,13 @@ static inline int radio_function(struct } case VIDIOCGUNIT: { struct video_unit *v = arg; - + v->video=VIDEO_NO_UNIT; v->vbi=VIDEO_NO_UNIT; v->radio=dev->minor; v->audio=0; v->teletext=VIDEO_NO_UNIT; - return 0; + return 0; } default: return -ENOIOCTLCMD; } @@ -267,7 +268,7 @@ static int radio_ioctl(struct inode *ino struct video_device *dev = video_devdata(file); struct radio_device *card=dev->priv; int ret; - + mutex_lock(&card->lock); ret = video_usercopy(inode, file, cmd, arg, radio_function); mutex_unlock(&card->lock); @@ -282,21 +283,21 @@ MODULE_LICENSE("GPL"); static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { if(!request_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) { - printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n"); - goto err_out; + pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) { + printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n"); + goto err_out; } if (pci_enable_device(pdev)) - goto err_out_free_region; + goto err_out_free_region; radio_unit.io = pci_resource_start(pdev, 0); mutex_init(&radio_unit.lock); maxiradio_radio.priv = &radio_unit; if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) { - printk("radio-maxiradio: can't register device!"); - goto err_out_free_region; + printk("radio-maxiradio: can't register device!"); + goto err_out_free_region; } printk(KERN_INFO "radio-maxiradio: version " diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index 28a47c9..5b68ac4 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -1,5 +1,5 @@ /* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff - * + * * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood * Converted to new API by Alan Cox * Various bugfixes and enhancements by Russell Kroll @@ -15,6 +15,7 @@ #include /* udelay */ #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ +#include #include /* CONFIG_RADIO_RTRACK2_PORT */ #include @@ -22,7 +23,7 @@ #ifndef CONFIG_RADIO_RTRACK2_PORT #define CONFIG_RADIO_RTRACK2_PORT -1 #endif -static int io = CONFIG_RADIO_RTRACK2_PORT; +static int io = CONFIG_RADIO_RTRACK2_PORT; static int radio_nr = -1; static spinlock_t lock; @@ -38,7 +39,7 @@ struct rt_device static void rt_mute(struct rt_device *dev) { - if(dev->muted) + if(dev->muted) return; spin_lock(&lock); outb(1, io); @@ -58,14 +59,14 @@ static void rt_unmute(struct rt_device * static void zero(void) { - outb_p(1, io); + outb_p(1, io); outb_p(3, io); outb_p(1, io); } static void one(void) { - outb_p(5, io); + outb_p(5, io); outb_p(7, io); outb_p(5, io); } @@ -75,7 +76,7 @@ static int rt_setfreq(struct rt_device * int i; freq = freq / 200 + 856; - + spin_lock(&lock); outb_p(0xc8, io); @@ -94,7 +95,7 @@ static int rt_setfreq(struct rt_device * outb_p(0xc8, io); if (!dev->muted) outb_p(0, io); - + spin_unlock(&lock); return 0; } @@ -127,7 +128,7 @@ static int rt_do_ioctl(struct inode *ino case VIDIOCGTUNER: { struct video_tuner *v = arg; - if(v->tuner) /* Only 1 tuner */ + if(v->tuner) /* Only 1 tuner */ return -EINVAL; v->rangelow=88*16000; v->rangehigh=108*16000; @@ -159,25 +160,25 @@ static int rt_do_ioctl(struct inode *ino return 0; } case VIDIOCGAUDIO: - { + { struct video_audio *v = arg; memset(v,0, sizeof(*v)); v->flags|=VIDEO_AUDIO_MUTABLE; v->volume=1; v->step=65535; strcpy(v->name, "Radio"); - return 0; + return 0; } case VIDIOCSAUDIO: { struct video_audio *v = arg; - if(v->audio) + if(v->audio) return -EINVAL; - if(v->flags&VIDEO_AUDIO_MUTE) + if(v->flags&VIDEO_AUDIO_MUTE) rt_mute(rt); else - rt_unmute(rt); + rt_unmute(rt); return 0; } @@ -219,7 +220,7 @@ static int __init rtrack2_init(void) printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n"); return -EINVAL; } - if (!request_region(io, 4, "rtrack2")) + if (!request_region(io, 4, "rtrack2")) { printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io); return -EBUSY; @@ -227,16 +228,16 @@ static int __init rtrack2_init(void) rtrack2_radio.priv=&rtrack2_unit; - spin_lock_init(&lock); + spin_lock_init(&lock); if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr)==-1) { release_region(io, 4); return -EINVAL; } - + printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n"); - /* mute card - prevents noisy bootups */ + /* mute card - prevents noisy bootups */ outb(1, io); rtrack2_unit.muted = 1; diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 53073b4..efee6e3 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -12,7 +12,7 @@ * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); * No volume control - only mute/unmute - you have to use line volume * control on SB-part of SF16FMI - * + * */ #include /* __setup */ @@ -21,6 +21,7 @@ #include /* Initdata * #include /* request_region */ #include /* udelay */ #include /* kernel radio structs */ +#include #include #include /* outb, outb_p */ #include /* copy to/from user */ @@ -29,19 +30,19 @@ #include struct fmi_device { int port; - int curvol; /* 1 or 0 */ - unsigned long curfreq; /* freq in kHz */ - __u32 flags; + int curvol; /* 1 or 0 */ + unsigned long curfreq; /* freq in kHz */ + __u32 flags; }; -static int io = -1; +static int io = -1; static int radio_nr = -1; static struct pnp_dev *dev = NULL; static struct mutex lock; /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ /* It is only useful to give freq in intervall of 800 (=0.05Mhz), - * other bits will be truncated, e.g 92.7400016 -> 92.7, but + * other bits will be truncated, e.g 92.7400016 -> 92.7, but * 92.7400017 -> 92.75 */ #define RSF16_ENCODE(x) ((x)/800+214) @@ -51,7 +52,7 @@ #define RSF16_MAXFREQ 108*16000 static void outbits(int bits, unsigned int data, int port) { while(bits--) { - if(data & 1) { + if(data & 1) { outb(5, port); udelay(6); outb(7, port); @@ -101,7 +102,7 @@ static inline int fmi_getsigstr(struct f int res; int myport = dev->port; - + mutex_lock(&lock); val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */ outb(val, myport); @@ -109,7 +110,7 @@ static inline int fmi_getsigstr(struct f msleep(143); /* was schedule_timeout(HZ/7) */ res = (int)inb(myport+1); outb(val, myport); - + mutex_unlock(&lock); return (res & 2) ? 0 : 0xFFFF; } @@ -119,7 +120,7 @@ static int fmi_do_ioctl(struct inode *in { struct video_device *dev = video_devdata(file); struct fmi_device *fmi=dev->priv; - + switch(cmd) { case VIDIOCGCAP: @@ -174,18 +175,18 @@ static int fmi_do_ioctl(struct inode *in return -EINVAL; /*rounding in steps of 800 to match th freq that will be used */ - fmi->curfreq = (*freq/800)*800; + fmi->curfreq = (*freq/800)*800; fmi_setfreq(fmi); return 0; } case VIDIOCGAUDIO: - { + { struct video_audio *v = arg; memset(v,0,sizeof(*v)); v->flags=( (!fmi->curvol)*VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); strcpy(v->name, "Radio"); v->mode=VIDEO_SOUND_STEREO; - return 0; + return 0; } case VIDIOCSAUDIO: { @@ -193,19 +194,19 @@ static int fmi_do_ioctl(struct inode *in if(v->audio) return -EINVAL; fmi->curvol= v->flags&VIDEO_AUDIO_MUTE ? 0 : 1; - fmi->curvol ? + fmi->curvol ? fmi_unmute(fmi->port) : fmi_mute(fmi->port); return 0; } - case VIDIOCGUNIT: + case VIDIOCGUNIT: { - struct video_unit *v = arg; + struct video_unit *v = arg; v->video=VIDEO_NO_UNIT; v->vbi=VIDEO_NO_UNIT; v->radio=dev->minor; v->audio=0; /* How do we find out this??? */ v->teletext=VIDEO_NO_UNIT; - return 0; + return 0; } default: return -ENOIOCTLCMD; @@ -295,14 +296,14 @@ static int __init fmi_init(void) fmi_unit.curfreq = 0; fmi_unit.flags = VIDEO_TUNER_LOW; fmi_radio.priv = &fmi_unit; - + mutex_init(&lock); - + if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) == -1) { release_region(io, 2); return -EINVAL; } - + printk(KERN_INFO "SF16FMx radio card driver at 0x%x\n", io); /* mute card - prevents noisy bootups */ fmi_mute(io); diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index bcebd8c..3483b2c 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -19,6 +19,7 @@ #include /* udelay */ #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ +#include #include static struct mutex lock; @@ -202,7 +203,7 @@ static int fmr2_setvolume(struct fmr2_de } static int fmr2_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) + unsigned int cmd, void *arg) { struct video_device *dev = video_devdata(file); struct fmr2_device *fmr2 = dev->priv; @@ -344,7 +345,7 @@ #endif } static int fmr2_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { return video_usercopy(inode, file, cmd, arg, fmr2_do_ioctl); } diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index fcfde2e..dfba4ae 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -2,11 +2,11 @@ * (c) 1999 R. Offermanns (rolf@offermanns.de) * based on the aimslab radio driver from M. Kirkwood * many thanks to Michael Becker and Friedhelm Birth (from TerraTec) - * + * * * History: * 1999-05-21 First preview release - * + * * Notes on the hardware: * There are two "main" chips on the card: * - Philips OM5610 (http://www-us.semiconductors.philips.com/acrobat/datasheets/OM5610_2.pdf) @@ -20,7 +20,7 @@ * (as soon i have understand how to get started :) * If you can help me out with that, please contact me!! * - * + * */ #include /* Modules */ @@ -30,6 +30,7 @@ #include /* udelay */ #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ +#include #include /* CONFIG_RADIO_TERRATEC_PORT */ #include @@ -49,7 +50,7 @@ #define CLK_ON 0x08 #define WRT_EN 0x10 /*******************************************************************/ -static int io = CONFIG_RADIO_TERRATEC_PORT; +static int io = CONFIG_RADIO_TERRATEC_PORT; static int radio_nr = -1; static spinlock_t lock; @@ -88,15 +89,15 @@ static void tt_mute(struct tt_device *de static int tt_setvol(struct tt_device *dev, int vol) { - + // printk(KERN_ERR "setvol called, vol = %d\n", vol); if(vol == dev->curvol) { /* requested volume = current */ if (dev->muted) { /* user is unmuting the card */ dev->muted = 0; cardWriteVol(vol); /* enable card */ - } - + } + return 0; } @@ -107,9 +108,9 @@ static int tt_setvol(struct tt_device *d } dev->muted = 0; - + cardWriteVol(vol); - + dev->curvol = vol; return 0; @@ -121,13 +122,13 @@ static int tt_setvol(struct tt_device *d /* many more or less strange things are going on here, but hey, it works :) */ static int tt_setfreq(struct tt_device *dev, unsigned long freq1) -{ +{ int freq; int i; int p; int temp; long rest; - + unsigned char buffer[25]; /* we have to bit shift 25 registers */ freq = freq1/160; /* convert the freq. to a nice to handle value */ for(i=24;i>-1;i--) @@ -142,9 +143,9 @@ static int tt_setfreq(struct tt_device * { if (rest%temp == rest) buffer[i] = 0; - else + else { - buffer[i] = 1; + buffer[i] = 1; rest = rest-temp; } i--; @@ -153,10 +154,10 @@ static int tt_setfreq(struct tt_device * } spin_lock(&lock); - + for (i=24;i>-1;i--) /* bit shift the values to the radiocard */ { - if (buffer[i]==1) + if (buffer[i]==1) { outb(WRT_EN|DATA, BASEPORT); outb(WRT_EN|DATA|CLK_ON , BASEPORT); @@ -168,11 +169,11 @@ static int tt_setfreq(struct tt_device * outb(WRT_EN|0x00|CLK_ON , BASEPORT); } } - outb(0x00, BASEPORT); - + outb(0x00, BASEPORT); + spin_unlock(&lock); - - return 0; + + return 0; } static int tt_getsigstr(struct tt_device *dev) /* TODO */ @@ -190,7 +191,7 @@ static int tt_do_ioctl(struct inode *ino { struct video_device *dev = video_devdata(file); struct tt_device *tt=dev->priv; - + switch(cmd) { case VIDIOCGCAP: @@ -206,7 +207,7 @@ static int tt_do_ioctl(struct inode *ino case VIDIOCGTUNER: { struct video_tuner *v = arg; - if(v->tuner) /* Only 1 tuner */ + if(v->tuner) /* Only 1 tuner */ return -EINVAL; v->rangelow=(87*16000); v->rangehigh=(108*16000); @@ -238,21 +239,21 @@ static int tt_do_ioctl(struct inode *ino return 0; } case VIDIOCGAUDIO: - { + { struct video_audio *v = arg; memset(v,0, sizeof(*v)); v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME; v->volume=tt->curvol * 6554; v->step=6554; strcpy(v->name, "Radio"); - return 0; + return 0; } case VIDIOCSAUDIO: { struct video_audio *v = arg; - if(v->audio) + if(v->audio) return -EINVAL; - if(v->flags&VIDEO_AUDIO_MUTE) + if(v->flags&VIDEO_AUDIO_MUTE) tt_mute(tt); else tt_setvol(tt,v->volume/6554); @@ -296,25 +297,25 @@ static int __init terratec_init(void) printk(KERN_ERR "You must set an I/O address with io=0x???\n"); return -EINVAL; } - if (!request_region(io, 2, "terratec")) + if (!request_region(io, 2, "terratec")) { printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io); return -EBUSY; } terratec_radio.priv=&terratec_unit; - + spin_lock_init(&lock); - + if(video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr)==-1) { release_region(io,2); return -EINVAL; } - + printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver.\n"); - /* mute card - prevents noisy bootups */ + /* mute card - prevents noisy bootups */ /* this ensures that the volume is all the way down */ cardWriteVol(0); @@ -334,7 +335,7 @@ static void __exit terratec_cleanup_modu { video_unregister_device(&terratec_radio); release_region(io,2); - printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n"); + printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n"); } module_init(terratec_init); diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c index 5a099a5..8da4bad 100644 --- a/drivers/media/radio/radio-trust.c +++ b/drivers/media/radio/radio-trust.c @@ -1,14 +1,14 @@ -/* radio-trust.c - Trust FM Radio card driver for Linux 2.2 +/* radio-trust.c - Trust FM Radio card driver for Linux 2.2 * by Eric Lammerts * * Based on radio-aztech.c. Original notes: * - * Adapted to support the Video for Linux API by + * Adapted to support the Video for Linux API by * Russell Kroll . Based on original tuner code by: * * Quay Ly * Donald Song - * Jason Lewis (jlewis@twilight.vtc.vsc.edu) + * Jason Lewis (jlewis@twilight.vtc.vsc.edu) * Scott McGrath (smcgrath@twilight.vtc.vsc.edu) * William McGrath (wmcgrath@twilight.vtc.vsc.edu) * @@ -22,6 +22,7 @@ #include #include #include #include +#include #include /* CONFIG_RADIO_TRUST_PORT */ /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ @@ -30,7 +31,7 @@ #ifndef CONFIG_RADIO_TRUST_PORT #define CONFIG_RADIO_TRUST_PORT -1 #endif -static int io = CONFIG_RADIO_TRUST_PORT; +static int io = CONFIG_RADIO_TRUST_PORT; static int radio_nr = -1; static int ioval = 0xf; static __u16 curvol; @@ -135,7 +136,7 @@ static void tr_setmute(int mute) static int tr_getsigstr(void) { int i, v; - + for(i = 0, v = 0; i < 100; i++) v |= inb(io); return (v & 1)? 0 : 0xffff; } @@ -175,7 +176,7 @@ static int tr_do_ioctl(struct inode *ino { struct video_tuner *v = arg; - if(v->tuner) /* Only 1 tuner */ + if(v->tuner) /* Only 1 tuner */ return -EINVAL; v->rangelow = 87500 * 16; @@ -211,28 +212,28 @@ static int tr_do_ioctl(struct inode *ino return 0; } case VIDIOCGAUDIO: - { + { struct video_audio *v = arg; memset(v,0, sizeof(*v)); v->flags = VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE; + VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE; v->mode = curstereo? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; v->volume = curvol * 2048; v->step = 2048; v->bass = curbass * 4370; v->treble = curtreble * 4370; - + strcpy(v->name, "Trust FM Radio"); - return 0; + return 0; } case VIDIOCSAUDIO: { struct video_audio *v = arg; - if(v->audio) + if(v->audio) return -EINVAL; - tr_setvol(v->volume); + tr_setvol(v->volume); tr_setbass(v->bass); tr_settreble(v->treble); tr_setstereo(v->mode & VIDEO_SOUND_STEREO); @@ -292,7 +293,7 @@ static int __init trust_init(void) write_i2c(2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ write_i2c(2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ - tr_setvol(0x8000); + tr_setvol(0x8000); tr_setbass(0x8000); tr_settreble(0x8000); tr_setstereo(1); diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index e509558..edd0122 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c @@ -36,6 +36,7 @@ #include /* radio card #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ +#include #include /* CONFIG_RADIO_TYPHOON_* */ #define BANNER "Typhoon Radio Card driver v0.1\n" @@ -361,8 +362,8 @@ #endif /* MODULE */ #ifdef CONFIG_RADIO_TYPHOON_PROC_FS if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL, - typhoon_get_info)) - printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n"); + typhoon_get_info)) + printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n"); #endif return 0; diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 7bf1a42..59b86a6 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -1,7 +1,7 @@ /* zoltrix radio plus driver for Linux radio support * (c) 1998 C. van Schaik * - * BUGS + * BUGS * Due to the inconsistency in reading from the signal flags * it is difficult to get an accurate tuned signal. * @@ -14,7 +14,7 @@ * * 1999-05-06 - (C. van Schaik) * - Make signal strength and stereo scans - * kinder to cpu while in delay + * kinder to cpu while in delay * 1999-01-05 - (C. van Schaik) * - Changed tuning to 1/160Mhz accuracy * - Added stereo support @@ -33,6 +33,7 @@ #include /* udelay, msle #include /* outb, outb_p */ #include /* copy to/from user */ #include /* kernel radio structs */ +#include #include /* CONFIG_RADIO_ZOLTRIX_PORT */ #ifndef CONFIG_RADIO_ZOLTRIX_PORT @@ -105,7 +106,7 @@ static int zol_setfreq(struct zol_device i = 45; mutex_lock(&dev->lock); - + outb(0, io); outb(0, io); inb(io + 3); /* Zoltrix needs to be read to confirm */ @@ -139,8 +140,8 @@ static int zol_setfreq(struct zol_device udelay(1000); inb(io+2); - udelay(1000); - + udelay(1000); + if (dev->muted) { outb(0, io); @@ -148,12 +149,12 @@ static int zol_setfreq(struct zol_device inb(io + 3); udelay(1000); } - + mutex_unlock(&dev->lock); - + if(!dev->muted) { - zol_setvol(dev, dev->curvol); + zol_setvol(dev, dev->curvol); } return 0; } @@ -174,14 +175,14 @@ static int zol_getsigstr(struct zol_devi b = inb(io); mutex_unlock(&dev->lock); - + if (a != b) return (0); - if ((a == 0xcf) || (a == 0xdf) /* I found this out by playing */ + if ((a == 0xcf) || (a == 0xdf) /* I found this out by playing */ || (a == 0xef)) /* with a binary scanner on the card io */ return (1); - return (0); + return (0); } static int zol_is_stereo (struct zol_device *dev) @@ -189,7 +190,7 @@ static int zol_is_stereo (struct zol_dev int x1, x2; mutex_lock(&dev->lock); - + outb(0x00, io); outb(dev->curvol, io); msleep(20); @@ -199,7 +200,7 @@ static int zol_is_stereo (struct zol_dev x2 = inb(io); mutex_unlock(&dev->lock); - + if ((x1 == x2) && (x1 == 0xcf)) return 1; return 0; @@ -226,7 +227,7 @@ static int zol_do_ioctl(struct inode *in case VIDIOCGTUNER: { struct video_tuner *v = arg; - if (v->tuner) + if (v->tuner) return -EINVAL; strcpy(v->name, "FM"); v->rangelow = (int) (88.0 * 16000); @@ -351,7 +352,7 @@ static int __init zoltrix_init(void) printk(KERN_INFO "Zoltrix Radio Plus card driver.\n"); mutex_init(&zoltrix_unit.lock); - + /* mute card - prevents noisy bootups */ /* this ensures that the volume is all the way down */ diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 6b41970..e429049 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -224,6 +224,12 @@ config VIDEO_ZORAN_LML33R10 support for the Linux Media Labs LML33R10 MJPEG capture/playback card. +config VIDEO_ZORAN_AVS6EYES + tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" + depends on VIDEO_ZORAN && EXPERIMENTAL && VIDEO_V4L1 + help + Support for the AverMedia 6 Eyes video surveillance card. + config VIDEO_ZR36120 tristate "Zoran ZR36120/36125 Video For Linux" depends on PCI && I2C && VIDEO_V4L1 && BROKEN @@ -306,17 +312,6 @@ config VIDEO_HEXIUM_GEMINI source "drivers/media/video/cx88/Kconfig" -config VIDEO_OVCAMCHIP - tristate "OmniVision Camera Chip support" - depends on I2C && VIDEO_V4L1 - ---help--- - Support for the OmniVision OV6xxx and OV7xxx series of camera chips. - This driver is intended to be used with the ov511 and w9968cf USB - camera drivers. - - To compile this driver as a module, choose M here: the - module will be called ovcamchip. - config VIDEO_M32R_AR tristate "AR devices" depends on M32R && VIDEO_V4L1 @@ -357,6 +352,15 @@ config VIDEO_CS53L32A To compile this driver as a module, choose M here: the module will be called cs53l32a. +config VIDEO_TLV320AIC23B + tristate "Texas Instruments TLV320AIC23B audio codec" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + ---help--- + Support for the Texas Instruments TLV320AIC23B audio codec. + + To compile this driver as a module, choose M here: the + module will be called tlv320aic23b. + config VIDEO_WM8775 tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer" depends on VIDEO_DEV && I2C && EXPERIMENTAL @@ -377,13 +381,25 @@ config VIDEO_WM8739 To compile this driver as a module, choose M here: the module will be called wm8739. +config VIDEO_CX2341X + tristate "Conexant CX2341x MPEG encoders" + depends on VIDEO_V4L2 && EXPERIMENTAL + ---help--- + Support for the Conexant CX23416 MPEG encoders + and CX23415 MPEG encoder/decoders. + + This module currently supports the encoding functions only. + + To compile this driver as a module, choose M here: the + module will be called cx2341x. + source "drivers/media/video/cx25840/Kconfig" config VIDEO_SAA711X - tristate "Philips SAA7113/4/5 video decoders (OBSOLETED)" - depends on VIDEO_V4L1 && I2C && EXPERIMENTAL + tristate "Philips SAA7113/4/5 video decoders" + depends on VIDEO_DEV && I2C && EXPERIMENTAL ---help--- - Old support for the Philips SAA7113/4 video decoders. + Support for the Philips SAA7113/4/5 video decoders. To compile this driver as a module, choose M here: the module will be called saa7115. @@ -447,6 +463,35 @@ source "drivers/media/video/usbvideo/Kco source "drivers/media/video/et61x251/Kconfig" +config VIDEO_OVCAMCHIP + tristate "OmniVision Camera Chip support" + depends on I2C && VIDEO_V4L1 + ---help--- + Support for the OmniVision OV6xxx and OV7xxx series of camera chips. + This driver is intended to be used with the ov511 and w9968cf USB + camera drivers. + + To compile this driver as a module, choose M here: the + module will be called ovcamchip. + +config USB_W9968CF + tristate "USB W996[87]CF JPEG Dual Mode Camera support" + depends on USB && VIDEO_V4L1 && I2C + select VIDEO_OVCAMCHIP + ---help--- + Say Y here if you want support for cameras based on OV681 or + Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. + + This driver has an optional plugin, which is distributed as a + separate module only (released under GPL). It allows to use higher + resolutions and framerates, but cannot be included in the official + Linux kernel for performance purposes. + + See for more info. + + To compile this driver as a module, choose M here: the + module will be called w9968cf. + config USB_OV511 tristate "USB OV511 Camera support" depends on USB && VIDEO_V4L1 @@ -483,24 +528,6 @@ config USB_STV680 To compile this driver as a module, choose M here: the module will be called stv680. -config USB_W9968CF - tristate "USB W996[87]CF JPEG Dual Mode Camera support" - depends on USB && VIDEO_V4L1 && I2C - select VIDEO_OVCAMCHIP - ---help--- - Say Y here if you want support for cameras based on OV681 or - Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. - - This driver has an optional plugin, which is distributed as a - separate module only (released under GPL). It allows to use higher - resolutions and framerates, but cannot be included in the official - Linux kernel for performance purposes. - - See for more info. - - To compile this driver as a module, choose M here: the - module will be called w9968cf. - source "drivers/media/video/zc0301/Kconfig" source "drivers/media/video/pwc/Kconfig" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index e5bf268..6c401b4 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -6,7 +6,7 @@ zoran-objs := zr36120.o zr36120_i2c zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ - mt20xx.o tda8290.o tea5767.o + mt20xx.o tda8290.o tea5767.o tda9887.o msp3400-objs := msp3400-driver.o msp3400-kthreads.o @@ -33,6 +33,7 @@ obj-$(CONFIG_VIDEO_ZORAN_DC30) += adv717 zr36016.o obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o zr36060.o obj-$(CONFIG_VIDEO_ZORAN_LML33R10) += saa7114.o adv7170.o zr36060.o +obj-$(CONFIG_VIDEO_ZORAN_AVS6EYES) += bt866.o ks0127.o zr36060.o obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o obj-$(CONFIG_VIDEO_PMS) += pms.o obj-$(CONFIG_VIDEO_PLANB) += planb.o @@ -48,6 +49,7 @@ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o +obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o obj-$(CONFIG_VIDEO_WM8775) += wm8775.o obj-$(CONFIG_VIDEO_WM8739) += wm8739.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ @@ -58,7 +60,7 @@ obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hex obj-$(CONFIG_VIDEO_DPC) += saa7111.o dpc7146.o obj-$(CONFIG_TUNER_3036) += tuner-3036.o -obj-$(CONFIG_VIDEO_TUNER) += tuner.o tda9887.o +obj-$(CONFIG_VIDEO_TUNER) += tuner.o obj-$(CONFIG_VIDEO_BUF) += video-buf.o obj-$(CONFIG_VIDEO_BUF_DVB) += video-buf-dvb.o obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o @@ -71,6 +73,7 @@ obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o +obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_DSBR) += dsbr100.o diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index dbe0251..6e08e32 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -31,6 +31,7 @@ #include #include #include #include +#include #include #include @@ -212,7 +213,7 @@ void init_iic(void) ar_outl(0x0300, PLDI2CMOD); /* I2CMOD ACK/8b-data/7b-addr/auto */ ar_outl(0x1, PLDI2CACK); /* I2CACK ACK */ - /* I2C CLK */ + /* I2C CLK */ /* 50MH-100k */ if (freq == 75) { ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */ diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c new file mode 100644 index 0000000..05e42bb --- /dev/null +++ b/drivers/media/video/bt866.c @@ -0,0 +1,377 @@ +/* + bt866 - BT866 Digital Video Encoder (Rockwell Part) + + Copyright (C) 1999 Mike Bernson + Copyright (C) 1998 Dave Perks + + Modifications for LML33/DC10plus unified driver + Copyright (C) 2000 Serguei Miridonov + + This code was modify/ported from the saa7111 driver written + by Dave Perks. + + This code was adapted for the bt866 by Christer Weinigel and ported + to 2.6 by Martin Samuelsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +MODULE_LICENSE("GPL"); + +#define BT866_DEVNAME "bt866" +#define I2C_BT866 0x88 + +MODULE_LICENSE("GPL"); + +#define DEBUG(x) /* Debug driver */ + +/* ----------------------------------------------------------------------- */ + +struct bt866 { + struct i2c_client *i2c; + int addr; + unsigned char reg[128]; + + int norm; + int enable; + int bright; + int contrast; + int hue; + int sat; +}; + +static int bt866_write(struct bt866 *dev, + unsigned char subaddr, unsigned char data); + +static int bt866_do_command(struct bt866 *encoder, + unsigned int cmd, void *arg) +{ + switch (cmd) { + case ENCODER_GET_CAPABILITIES: + { + struct video_encoder_capability *cap = arg; + + DEBUG(printk + (KERN_INFO "%s: get capabilities\n", + encoder->i2c->name)); + + cap->flags + = VIDEO_ENCODER_PAL + | VIDEO_ENCODER_NTSC + | VIDEO_ENCODER_CCIR; + cap->inputs = 2; + cap->outputs = 1; + } + break; + + case ENCODER_SET_NORM: + { + int *iarg = arg; + + DEBUG(printk(KERN_INFO "%s: set norm %d\n", + encoder->i2c->name, *iarg)); + + switch (*iarg) { + + case VIDEO_MODE_NTSC: + break; + + case VIDEO_MODE_PAL: + break; + + default: + return -EINVAL; + + } + encoder->norm = *iarg; + } + break; + + case ENCODER_SET_INPUT: + { + int *iarg = arg; + static const __u8 init[] = { + 0xc8, 0xcc, /* CRSCALE */ + 0xca, 0x91, /* CBSCALE */ + 0xcc, 0x24, /* YC16 | OSDNUM */ + 0xda, 0x00, /* */ + 0xdc, 0x24, /* SETMODE | PAL */ + 0xde, 0x02, /* EACTIVE */ + + /* overlay colors */ + 0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */ + 0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */ + 0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */ + 0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */ + 0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */ + 0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */ + 0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */ + 0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */ + + 0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */ + 0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */ + 0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */ + 0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */ + 0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */ + 0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */ + 0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */ + 0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */ + }; + int i; + u8 val; + + for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2) + bt866_write(encoder, init[i], init[i+1]); + + val = encoder->reg[0xdc]; + + if (*iarg == 0) + val |= 0x40; /* CBSWAP */ + else + val &= ~0x40; /* !CBSWAP */ + + bt866_write(encoder, 0xdc, val); + + val = encoder->reg[0xcc]; + if (*iarg == 2) + val |= 0x01; /* OSDBAR */ + else + val &= ~0x01; /* !OSDBAR */ + bt866_write(encoder, 0xcc, val); + + DEBUG(printk(KERN_INFO "%s: set input %d\n", + encoder->i2c->name, *iarg)); + + switch (*iarg) { + case 0: + break; + case 1: + break; + default: + return -EINVAL; + + } + } + break; + + case ENCODER_SET_OUTPUT: + { + int *iarg = arg; + + DEBUG(printk(KERN_INFO "%s: set output %d\n", + encoder->i2c->name, *iarg)); + + /* not much choice of outputs */ + if (*iarg != 0) + return -EINVAL; + } + break; + + case ENCODER_ENABLE_OUTPUT: + { + int *iarg = arg; + encoder->enable = !!*iarg; + + DEBUG(printk + (KERN_INFO "%s: enable output %d\n", + encoder->i2c->name, encoder->enable)); + } + break; + + case 4711: + { + int *iarg = arg; + __u8 val; + + printk("bt866: square = %d\n", *iarg); + + val = encoder->reg[0xdc]; + if (*iarg) + val |= 1; /* SQUARE */ + else + val &= ~1; /* !SQUARE */ + bt866_write(encoder, 0xdc, val); + break; + } + + default: + return -EINVAL; + } + + return 0; +} + +static int bt866_write(struct bt866 *encoder, + unsigned char subaddr, unsigned char data) +{ + unsigned char buffer[2]; + int err; + + buffer[0] = subaddr; + buffer[1] = data; + + encoder->reg[subaddr] = data; + + DEBUG(printk + ("%s: write 0x%02X = 0x%02X\n", + encoder->i2c->name, subaddr, data)); + + for (err = 0; err < 3;) { + if (i2c_master_send(encoder->i2c, buffer, 2) == 2) + break; + err++; + printk(KERN_WARNING "%s: I/O error #%d " + "(write 0x%02x/0x%02x)\n", + encoder->i2c->name, err, encoder->addr, subaddr); + schedule_timeout_interruptible(HZ/10); + } + if (err == 3) { + printk(KERN_WARNING "%s: giving up\n", + encoder->i2c->name); + return -1; + } + + return 0; +} + +static int bt866_attach(struct i2c_adapter *adapter); +static int bt866_detach(struct i2c_client *client); +static int bt866_command(struct i2c_client *client, + unsigned int cmd, void *arg); + + +/* Addresses to scan */ +static unsigned short normal_i2c[] = {I2C_BT866>>1, I2C_CLIENT_END}; +static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; +static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; + +static struct i2c_client_address_data addr_data = { + normal_i2c, + probe, + ignore, +}; + +static struct i2c_driver i2c_driver_bt866 = { + .driver.name = BT866_DEVNAME, + .id = I2C_DRIVERID_BT866, + .attach_adapter = bt866_attach, + .detach_client = bt866_detach, + .command = bt866_command +}; + + +static struct i2c_client bt866_client_tmpl = +{ + .name = "(nil)", + .addr = 0, + .adapter = NULL, + .driver = &i2c_driver_bt866, + .usage_count = 0 +}; + +static int bt866_found_proc(struct i2c_adapter *adapter, + int addr, int kind) +{ + struct bt866 *encoder; + struct i2c_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (client == NULL) + return -ENOMEM; + memcpy(client, &bt866_client_tmpl, sizeof(*client)); + + encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); + if (encoder == NULL) { + kfree(client); + return -ENOMEM; + } + + i2c_set_clientdata(client, encoder); + client->adapter = adapter; + client->addr = addr; + sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id); + + encoder->i2c = client; + encoder->addr = addr; + //encoder->encoder_type = ENCODER_TYPE_UNKNOWN; + + /* initialize */ + + i2c_attach_client(client); + + return 0; +} + +static int bt866_attach(struct i2c_adapter *adapter) +{ + if (adapter->id == I2C_HW_B_ZR36067) + return i2c_probe(adapter, &addr_data, bt866_found_proc); + return 0; +} + +static int bt866_detach(struct i2c_client *client) +{ + struct bt866 *encoder = i2c_get_clientdata(client); + + i2c_detach_client(client); + kfree(encoder); + kfree(client); + + return 0; +} + +static int bt866_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct bt866 *encoder = i2c_get_clientdata(client); + return bt866_do_command(encoder, cmd, arg); +} + +static int __devinit bt866_init(void) +{ + i2c_add_driver(&i2c_driver_bt866); + return 0; +} + +static void __devexit bt866_exit(void) +{ + i2c_del_driver(&i2c_driver_bt866); +} + +module_init(bt866_init); +module_exit(bt866_exit); diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 2b64aa8..e68a6d2 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -269,7 +269,7 @@ static struct CARD { { 0x41a0a051, BTTV_BOARD_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" }, { 0x18501f7f, BTTV_BOARD_FLYVIDEO_98, "Lifeview Flyvideo 98" }, - { 0x010115cb, BTTV_BOARD_GMV1, "AG GMV1" }, + { 0x010115cb, BTTV_BOARD_GMV1, "AG GMV1" }, { 0x010114c7, BTTV_BOARD_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" }, { 0x10b42636, BTTV_BOARD_HAUPPAUGE878, "STB ???" }, @@ -309,6 +309,7 @@ static struct CARD { { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" }, { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, + { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, { 0, -1, NULL } }; @@ -1903,7 +1904,7 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, }, [BTTV_BOARD_OSPREY2x0] = { - .name = "Osprey 210/220", /* 0x1(A|B)-04C0-C1 */ + .name = "Osprey 210/220/230", /* 0x1(A|B)-04C0-C1 */ .video_inputs = 2, .audio_inputs = 1, .tuner = -1, @@ -2745,7 +2746,7 @@ struct tvcard bttv_tvcards[] = { /* Michael Krufky */ .name = "DViCO FusionHDTV 5 Lite", .tuner = 0, - .tuner_type = TUNER_LG_TDVS_H062F, + .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */ .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .video_inputs = 3, @@ -2762,7 +2763,7 @@ struct tvcard bttv_tvcards[] = { }, /* ---- card 0x88---------------------------------- */ [BTTV_BOARD_ACORP_Y878F] = { - /* Mauro Carvalho Chehab */ + /* Mauro Carvalho Chehab */ .name = "Acorp Y878F", .video_inputs = 3, .audio_inputs = 1, @@ -3790,6 +3791,7 @@ static void __devinit osprey_eeprom(stru break; case 0x0060: case 0x0070: + case 0x00A0: btv->c.type = BTTV_BOARD_OSPREY2x0; /* enable output on select control lines */ gpio_inout(0xffffff,0x000303); @@ -4846,7 +4848,7 @@ static void picolo_tetra_muxsel (struct * * The IVC120G security card has 4 i2c controlled TDA8540 matrix * swichers to provide 16 channels to MUX0. The TDA8540's have - * 4 indepedant outputs and as such the IVC120G also has the + * 4 independent outputs and as such the IVC120G also has the * optional "Monitor Out" bus. This allows the card to be looking * at one input while the monitor is looking at another. * diff --git a/drivers/media/video/bt8xx/bttv-gpio.c b/drivers/media/video/bt8xx/bttv-gpio.c index c4d5e2b..ba081f6 100644 --- a/drivers/media/video/bt8xx/bttv-gpio.c +++ b/drivers/media/video/bt8xx/bttv-gpio.c @@ -118,20 +118,6 @@ int bttv_sub_del_devices(struct bttv_cor return 0; } -void bttv_gpio_irq(struct bttv_core *core) -{ - struct bttv_sub_driver *drv; - struct bttv_sub_device *dev; - struct list_head *item; - - list_for_each(item,&core->subs) { - dev = list_entry(item,struct bttv_sub_device,list); - drv = to_bttv_sub_drv(dev->dev.driver); - if (drv && drv->gpio_irq) - drv->gpio_irq(dev); - } -} - /* ----------------------------------------------------------------------- */ /* external: sub-driver register/unregister */ diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 69efa0e..b41f81d 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -355,7 +355,7 @@ int bttv_input_init(struct bttv *btv) if (ir->rc5_gpio) { u32 gpio; - /* enable remote irq */ + /* enable remote irq */ bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4); gpio = bttv_gpio_read(&btv->c); bttv_gpio_write(&btv->c, gpio & ~(1 << 4)); diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 3a23265..f9c9e3c 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -350,7 +350,6 @@ struct bttv_sub_driver { char wanted[BUS_ID_SIZE]; int (*probe)(struct bttv_sub_device *sub); void (*remove)(struct bttv_sub_device *sub); - void (*gpio_irq)(struct bttv_sub_device *sub); }; #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index ee989d2..d295601 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -33,6 +33,7 @@ #include #include #include #include +#include #include #include #include @@ -214,7 +215,6 @@ extern struct videobuf_queue_ops bttv_vb extern struct bus_type bttv_sub_bus_type; int bttv_sub_add_device(struct bttv_core *core, char *name); int bttv_sub_del_devices(struct bttv_core *core); -void bttv_gpio_irq(struct bttv_core *core); /* ---------------------------------------------------------- */ diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index cf61c59..7d0b6e5 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -73,6 +73,7 @@ #include #include #include #include +#include #include #include @@ -759,7 +760,7 @@ static int qcam_do_ioctl(struct inode *i { struct video_picture *p = arg; if(p->palette!=VIDEO_PALETTE_GREY) - return -EINVAL; + return -EINVAL; if(p->depth!=4 && p->depth!=6) return -EINVAL; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 22a7386..a3989bd 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -34,6 +34,7 @@ #include #include #include #include +#include #include #include diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 85d84e8..95c5ace 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -47,13 +47,6 @@ #endif #include "cpia.h" -#ifdef CONFIG_VIDEO_CPIA_PP -extern int cpia_pp_init(void); -#endif -#ifdef CONFIG_VIDEO_CPIA_USB -extern int cpia_usb_init(void); -#endif - static int video_nr = -1; #ifdef MODULE @@ -67,10 +60,10 @@ #endif static unsigned short colorspace_conv; module_param(colorspace_conv, ushort, 0444); MODULE_PARM_DESC(colorspace_conv, - " Colorspace conversion:" - "\n 0 = disable, 1 = enable" - "\n Default value is 0" - ); + " Colorspace conversion:" + "\n 0 = disable, 1 = enable" + "\n Default value is 0" + ); #define ABOUT "V4L-Driver for Vision CPiA based cameras" @@ -4047,13 +4040,6 @@ #ifdef CONFIG_PROC_FS proc_cpia_create(); #endif -#ifdef CONFIG_VIDEO_CPIA_PP - cpia_pp_init(); -#endif -#ifdef CONFIG_VIDEO_CPIA_USB - cpia_usb_init(); -#endif - return 0; } diff --git a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h index dde27a6..6eaa692 100644 --- a/drivers/media/video/cpia.h +++ b/drivers/media/video/cpia.h @@ -45,6 +45,7 @@ #ifdef __KERNEL__ #include #include +#include #include #include #include @@ -247,7 +248,7 @@ #define FRAME_NUM 2 /* double buffering struct cam_data { struct list_head cam_data_list; - struct mutex busy_lock; /* guard against SMP multithreading */ + struct mutex busy_lock; /* guard against SMP multithreading */ struct cpia_camera_ops *ops; /* lowlevel driver operations */ void *lowlevel_data; /* private data for lowlevel driver */ u8 *raw_image; /* buffer for raw image data */ diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h index 1764991..c5ecb2b 100644 --- a/drivers/media/video/cpia2/cpia2.h +++ b/drivers/media/video/cpia2/cpia2.h @@ -33,6 +33,7 @@ #define __CPIA2_H__ #include #include +#include #include #include diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 481e178..d129db5 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -343,7 +343,9 @@ static int cpia2_close(struct inode *ino cpia2_free_buffers(cam); if (!cam->present) { video_unregister_device(dev); + mutex_unlock(&cam->busy_lock); kfree(cam); + return 0; } } @@ -1167,9 +1169,9 @@ static int ioctl_g_ctrl(void *arg,struct } else { if(cam->params.flicker_control.cam_register & CPIA2_VP_FLICKER_MODES_50HZ) { - mode = FLICKER_50; + mode = FLICKER_50; } else { - mode = FLICKER_60; + mode = FLICKER_60; } } for(i=0; i + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +MODULE_DESCRIPTION("cx23415/6 driver"); +MODULE_AUTHOR("Hans Verkuil"); +MODULE_LICENSE("GPL"); + +static int debug = 0; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + +const u32 cx2341x_mpeg_ctrls[] = { + V4L2_CID_MPEG_CLASS, + V4L2_CID_MPEG_STREAM_TYPE, + V4L2_CID_MPEG_STREAM_VBI_FMT, + V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, + V4L2_CID_MPEG_AUDIO_ENCODING, + V4L2_CID_MPEG_AUDIO_L2_BITRATE, + V4L2_CID_MPEG_AUDIO_MODE, + V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, + V4L2_CID_MPEG_AUDIO_EMPHASIS, + V4L2_CID_MPEG_AUDIO_CRC, + V4L2_CID_MPEG_VIDEO_ENCODING, + V4L2_CID_MPEG_VIDEO_ASPECT, + V4L2_CID_MPEG_VIDEO_B_FRAMES, + V4L2_CID_MPEG_VIDEO_GOP_SIZE, + V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, + V4L2_CID_MPEG_VIDEO_PULLDOWN, + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, + V4L2_CID_MPEG_VIDEO_BITRATE, + V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, + V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, + V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE, + V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, + V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE, + V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE, + V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE, + V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER, + V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE, + V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM, + V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP, + V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, + V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP, + 0 +}; + + +/* Map the control ID to the correct field in the cx2341x_mpeg_params + struct. Return -EINVAL if the ID is unknown, else return 0. */ +static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params, + struct v4l2_ext_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + ctrl->value = params->audio_sampling_freq; + break; + case V4L2_CID_MPEG_AUDIO_ENCODING: + ctrl->value = params->audio_encoding; + break; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + ctrl->value = params->audio_l2_bitrate; + break; + case V4L2_CID_MPEG_AUDIO_MODE: + ctrl->value = params->audio_mode; + break; + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + ctrl->value = params->audio_mode_extension; + break; + case V4L2_CID_MPEG_AUDIO_EMPHASIS: + ctrl->value = params->audio_emphasis; + break; + case V4L2_CID_MPEG_AUDIO_CRC: + ctrl->value = params->audio_crc; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + ctrl->value = params->video_encoding; + break; + case V4L2_CID_MPEG_VIDEO_ASPECT: + ctrl->value = params->video_aspect; + break; + case V4L2_CID_MPEG_VIDEO_B_FRAMES: + ctrl->value = params->video_b_frames; + break; + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + ctrl->value = params->video_gop_size; + break; + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + ctrl->value = params->video_gop_closure; + break; + case V4L2_CID_MPEG_VIDEO_PULLDOWN: + ctrl->value = params->video_pulldown; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + ctrl->value = params->video_bitrate_mode; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + ctrl->value = params->video_bitrate; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + ctrl->value = params->video_bitrate_peak; + break; + case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: + ctrl->value = params->video_temporal_decimation; + break; + case V4L2_CID_MPEG_STREAM_TYPE: + ctrl->value = params->stream_type; + break; + case V4L2_CID_MPEG_STREAM_VBI_FMT: + ctrl->value = params->stream_vbi_fmt; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + ctrl->value = params->video_spatial_filter_mode; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: + ctrl->value = params->video_spatial_filter; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + ctrl->value = params->video_luma_spatial_filter_type; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + ctrl->value = params->video_chroma_spatial_filter_type; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + ctrl->value = params->video_temporal_filter_mode; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: + ctrl->value = params->video_temporal_filter; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + ctrl->value = params->video_median_filter_type; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: + ctrl->value = params->video_luma_median_filter_top; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: + ctrl->value = params->video_luma_median_filter_bottom; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: + ctrl->value = params->video_chroma_median_filter_top; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: + ctrl->value = params->video_chroma_median_filter_bottom; + break; + default: + return -EINVAL; + } + return 0; +} + +/* Map the control ID to the correct field in the cx2341x_mpeg_params + struct. Return -EINVAL if the ID is unknown, else return 0. */ +static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, + struct v4l2_ext_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + params->audio_sampling_freq = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_ENCODING: + params->audio_encoding = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + params->audio_l2_bitrate = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_MODE: + params->audio_mode = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + params->audio_mode_extension = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_EMPHASIS: + params->audio_emphasis = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_CRC: + params->audio_crc = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_ASPECT: + params->video_aspect = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_B_FRAMES: { + int b = ctrl->value + 1; + int gop = params->video_gop_size; + params->video_b_frames = ctrl->value; + params->video_gop_size = b * ((gop + b - 1) / b); + /* Max GOP size = 34 */ + while (params->video_gop_size > 34) + params->video_gop_size -= b; + break; + } + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: { + int b = params->video_b_frames + 1; + int gop = ctrl->value; + params->video_gop_size = b * ((gop + b - 1) / b); + /* Max GOP size = 34 */ + while (params->video_gop_size > 34) + params->video_gop_size -= b; + ctrl->value = params->video_gop_size; + break; + } + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + params->video_gop_closure = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_PULLDOWN: + params->video_pulldown = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + /* MPEG-1 only allows CBR */ + if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 && + ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + return -EINVAL; + params->video_bitrate_mode = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + params->video_bitrate = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + params->video_bitrate_peak = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: + params->video_temporal_decimation = ctrl->value; + break; + case V4L2_CID_MPEG_STREAM_TYPE: + params->stream_type = ctrl->value; + params->video_encoding = + (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS || + params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ? + V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2; + if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) { + /* MPEG-1 implies CBR */ + params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; + } + break; + case V4L2_CID_MPEG_STREAM_VBI_FMT: + params->stream_vbi_fmt = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + params->video_spatial_filter_mode = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: + params->video_spatial_filter = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + params->video_luma_spatial_filter_type = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + params->video_chroma_spatial_filter_type = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + params->video_temporal_filter_mode = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: + params->video_temporal_filter = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + params->video_median_filter_type = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: + params->video_luma_median_filter_top = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: + params->video_luma_median_filter_bottom = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: + params->video_chroma_median_filter_top = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: + params->video_chroma_median_filter_bottom = ctrl->value; + break; + default: + return -EINVAL; + } + return 0; +} + +static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) +{ + const char *name; + + qctrl->flags = 0; + switch (qctrl->id) { + /* MPEG controls */ + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + name = "Spatial Filter Mode"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: + name = "Spatial Filter"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + name = "Spatial Luma Filter Type"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + name = "Spatial Chroma Filter Type"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + name = "Temporal Filter Mode"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: + name = "Temporal Filter"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + name = "Median Filter Type"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: + name = "Median Luma Filter Maximum"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: + name = "Median Luma Filter Minimum"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: + name = "Median Chroma Filter Maximum"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: + name = "Median Chroma Filter Minimum"; + break; + + default: + return v4l2_ctrl_query_fill(qctrl, min, max, step, def); + } + switch (qctrl->id) { + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + qctrl->type = V4L2_CTRL_TYPE_MENU; + min = 0; + step = 1; + break; + default: + qctrl->type = V4L2_CTRL_TYPE_INTEGER; + break; + } + switch (qctrl->id) { + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + qctrl->flags |= V4L2_CTRL_FLAG_UPDATE; + break; + } + qctrl->minimum = min; + qctrl->maximum = max; + qctrl->step = step; + qctrl->default_value = def; + qctrl->reserved[0] = qctrl->reserved[1] = 0; + snprintf(qctrl->name, sizeof(qctrl->name), name); + return 0; +} + +int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl) +{ + int err; + + switch (qctrl->id) { + case V4L2_CID_MPEG_AUDIO_ENCODING: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2); + + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_L2_BITRATE_192K, + V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, + V4L2_MPEG_AUDIO_L2_BITRATE_224K); + + case V4L2_CID_MPEG_AUDIO_L1_BITRATE: + case V4L2_CID_MPEG_AUDIO_L3_BITRATE: + return -EINVAL; + + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + err = v4l2_ctrl_query_fill_std(qctrl); + if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return err; + + case V4L2_CID_MPEG_VIDEO_ENCODING: + /* this setting is read-only for the cx2341x since the + V4L2_CID_MPEG_STREAM_TYPE really determines the + MPEG-1/2 setting */ + err = v4l2_ctrl_query_fill_std(qctrl); + if (err == 0) + qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + return err; + + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + err = v4l2_ctrl_query_fill_std(qctrl); + if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return err; + + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + err = v4l2_ctrl_query_fill_std(qctrl); + if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return err; + + case V4L2_CID_MPEG_STREAM_VBI_FMT: + if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI) + return v4l2_ctrl_query_fill_std(qctrl); + return cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_STREAM_VBI_FMT_NONE, + V4L2_MPEG_STREAM_VBI_FMT_NONE, 1, + V4L2_MPEG_STREAM_VBI_FMT_NONE); + + /* CX23415/6 specific */ + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + return cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL); + + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: + cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF); + if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF); + if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + return cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL); + + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: + cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + return cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF); + + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: + cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: + cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: + cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: + cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + default: + return v4l2_ctrl_query_fill_std(qctrl); + + } +} + +const char **cx2341x_ctrl_get_menu(u32 id) +{ + static const char *mpeg_stream_type[] = { + "MPEG-2 Program Stream", + "", + "MPEG-1 System Stream", + "MPEG-2 DVD-compatible Stream", + "MPEG-1 VCD-compatible Stream", + "MPEG-2 SVCD-compatible Stream", + NULL + }; + + static const char *cx2341x_video_spatial_filter_mode_menu[] = { + "Manual", + "Auto", + NULL + }; + + static const char *cx2341x_video_luma_spatial_filter_type_menu[] = { + "Off", + "1D Horizontal", + "1D Vertical", + "2D H/V Separable", + "2D Symmetric non-separable", + NULL + }; + + static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = { + "Off", + "1D Horizontal", + NULL + }; + + static const char *cx2341x_video_temporal_filter_mode_menu[] = { + "Manual", + "Auto", + NULL + }; + + static const char *cx2341x_video_median_filter_type_menu[] = { + "Off", + "Horizontal", + "Vertical", + "Horizontal/Vertical", + "Diagonal", + NULL + }; + + switch (id) { + case V4L2_CID_MPEG_STREAM_TYPE: + return mpeg_stream_type; + case V4L2_CID_MPEG_AUDIO_L1_BITRATE: + case V4L2_CID_MPEG_AUDIO_L3_BITRATE: + return NULL; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + return cx2341x_video_spatial_filter_mode_menu; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + return cx2341x_video_luma_spatial_filter_type_menu; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + return cx2341x_video_chroma_spatial_filter_type_menu; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + return cx2341x_video_temporal_filter_mode_menu; + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + return cx2341x_video_median_filter_type_menu; + default: + return v4l2_ctrl_get_menu(id); + } +} + +static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) +{ + params->audio_properties = (params->audio_sampling_freq << 0) | + ((3 - params->audio_encoding) << 2) | + ((1 + params->audio_l2_bitrate) << 4) | + (params->audio_mode << 8) | + (params->audio_mode_extension << 10) | + (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ? + 3 : + params->audio_emphasis) << 12) | + (params->audio_crc << 14); +} + +int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, + struct v4l2_ext_controls *ctrls, int cmd) +{ + int err = 0; + int i; + + if (cmd == VIDIOC_G_EXT_CTRLS) { + for (i = 0; i < ctrls->count; i++) { + struct v4l2_ext_control *ctrl = ctrls->controls + i; + + err = cx2341x_get_ctrl(params, ctrl); + if (err) { + ctrls->error_idx = i; + break; + } + } + return err; + } + for (i = 0; i < ctrls->count; i++) { + struct v4l2_ext_control *ctrl = ctrls->controls + i; + struct v4l2_queryctrl qctrl; + const char **menu_items = NULL; + + qctrl.id = ctrl->id; + err = cx2341x_ctrl_query(params, &qctrl); + if (err) + break; + if (qctrl.type == V4L2_CTRL_TYPE_MENU) + menu_items = cx2341x_ctrl_get_menu(qctrl.id); + err = v4l2_ctrl_check(ctrl, &qctrl, menu_items); + if (err) + break; + err = cx2341x_set_ctrl(params, ctrl); + if (err) + break; + } + if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && + params->video_bitrate_peak < params->video_bitrate) { + err = -ERANGE; + ctrls->error_idx = ctrls->count; + } + if (err) { + ctrls->error_idx = i; + } + else { + cx2341x_calc_audio_properties(params); + } + return err; +} + +void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p) +{ + static struct cx2341x_mpeg_params default_params = { + /* misc */ + .capabilities = 0, + .port = CX2341X_PORT_MEMORY, + .width = 720, + .height = 480, + .is_50hz = 0, + + /* stream */ + .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS, + .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE, + + /* audio */ + .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, + .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K, + .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO, + .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, + .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE, + .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE, + + /* video */ + .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2, + .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3, + .video_b_frames = 2, + .video_gop_size = 12, + .video_gop_closure = 1, + .video_pulldown = 0, + .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .video_bitrate = 6000000, + .video_bitrate_peak = 8000000, + .video_temporal_decimation = 0, + + /* encoding filters */ + .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, + .video_spatial_filter = 0, + .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR, + .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, + .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, + .video_temporal_filter = 0, + .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, + .video_luma_median_filter_top = 255, + .video_luma_median_filter_bottom = 0, + .video_chroma_median_filter_top = 255, + .video_chroma_median_filter_bottom = 0, + }; + + *p = default_params; + cx2341x_calc_audio_properties(p); +} + +static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...) +{ + u32 data[CX2341X_MBOX_MAX_DATA]; + va_list vargs; + int i; + + va_start(vargs, args); + + for (i = 0; i < args; i++) { + data[i] = va_arg(vargs, int); + } + va_end(vargs); + return func(priv, cmd, args, 0, data); +} + +int cx2341x_update(void *priv, cx2341x_mbox_func func, + const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new) +{ + static int mpeg_stream_type[] = { + 0, /* MPEG-2 PS */ + 1, /* MPEG-2 TS */ + 2, /* MPEG-1 SS */ + 14, /* DVD */ + 11, /* VCD */ + 12, /* SVCD */ + }; + + int err = 0; + + cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0); + + if (old == NULL || old->is_50hz != new->is_50hz) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz); + if (err) return err; + } + + if (old == NULL || old->width != new->width || old->height != new->height || + old->video_encoding != new->video_encoding) { + u16 w = new->width; + u16 h = new->height; + + if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) { + w /= 2; + h /= 2; + } + err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w); + if (err) return err; + } + + if (old == NULL || old->stream_type != new->stream_type) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]); + if (err) return err; + } + if (old == NULL || old->video_aspect != new->video_aspect) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect); + if (err) return err; + } + if (old == NULL || old->video_b_frames != new->video_b_frames || + old->video_gop_size != new->video_gop_size) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2, + new->video_gop_size, new->video_b_frames + 1); + if (err) return err; + } + if (old == NULL || old->video_gop_closure != new->video_gop_closure) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure); + if (err) return err; + } + if (old == NULL || old->video_pulldown != new->video_pulldown) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown); + if (err) return err; + } + if (old == NULL || old->audio_properties != new->audio_properties) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties); + if (err) return err; + } + if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode || + old->video_bitrate != new->video_bitrate || + old->video_bitrate_peak != new->video_bitrate_peak) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5, + new->video_bitrate_mode, new->video_bitrate, + new->video_bitrate_peak / 400, 0, 0); + if (err) return err; + } + if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode || + old->video_temporal_filter_mode != new->video_temporal_filter_mode || + old->video_median_filter_type != new->video_median_filter_type) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2, + new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1), + new->video_median_filter_type); + if (err) return err; + } + if (old == NULL || + old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom || + old->video_luma_median_filter_top != new->video_luma_median_filter_top || + old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom || + old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4, + new->video_luma_median_filter_bottom, + new->video_luma_median_filter_top, + new->video_chroma_median_filter_bottom, + new->video_chroma_median_filter_top); + if (err) return err; + } + if (old == NULL || + old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type || + old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2, + new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type); + if (err) return err; + } + if (old == NULL || + old->video_spatial_filter != new->video_spatial_filter || + old->video_temporal_filter != new->video_temporal_filter) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2, + new->video_spatial_filter, new->video_temporal_filter); + if (err) return err; + } + if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1, + new->video_temporal_decimation); + if (err) return err; + } + return 0; +} + +static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id) +{ + const char **menu = cx2341x_ctrl_get_menu(id); + struct v4l2_ext_control ctrl; + + if (menu == NULL) + goto invalid; + ctrl.id = id; + if (cx2341x_get_ctrl(p, &ctrl)) + goto invalid; + while (ctrl.value-- && *menu) menu++; + if (*menu == NULL) + goto invalid; + return *menu; + +invalid: + return ""; +} + +void cx2341x_log_status(struct cx2341x_mpeg_params *p, int card_id) +{ + int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; + + /* Stream */ + printk(KERN_INFO "cx2341x-%d: Stream: %s\n", + card_id, + cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE)); + + /* Video */ + printk(KERN_INFO "cx2341x-%d: Video: %dx%d, %d fps\n", + card_id, + p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1), + p->is_50hz ? 25 : 30); + printk(KERN_INFO "cx2341x-%d: Video: %s, %s, %s, %d", + card_id, + cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING), + cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT), + cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE), + p->video_bitrate); + if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { + printk(", Peak %d", p->video_bitrate_peak); + } + printk("\n"); + printk(KERN_INFO "cx2341x-%d: Video: GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n", + card_id, + p->video_gop_size, p->video_b_frames, + p->video_gop_closure ? "" : "No ", + p->video_pulldown ? "" : "No "); + if (p->video_temporal_decimation) { + printk(KERN_INFO "cx2341x-%d: Video: Temporal Decimation %d\n", + card_id, p->video_temporal_decimation); + } + + /* Audio */ + printk(KERN_INFO "cx2341x-%d: Audio: %s, %s, %s, %s", + card_id, + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ), + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING), + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE), + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE)); + if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) { + printk(", %s", + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION)); + } + printk(", %s, %s\n", + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS), + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC)); + + /* Encoding filters */ + printk(KERN_INFO "cx2341x-%d: Spatial Filter: %s, Luma %s, Chroma %s, %d\n", + card_id, + cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE), + cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE), + cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE), + p->video_spatial_filter); + printk(KERN_INFO "cx2341x-%d: Temporal Filter: %s, %d\n", + card_id, + cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE), + p->video_temporal_filter); + printk(KERN_INFO "cx2341x-%d: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n", + card_id, + cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE), + p->video_luma_median_filter_bottom, + p->video_luma_median_filter_top, + p->video_chroma_median_filter_bottom, + p->video_chroma_median_filter_top); +} + +EXPORT_SYMBOL(cx2341x_fill_defaults); +EXPORT_SYMBOL(cx2341x_ctrl_query); +EXPORT_SYMBOL(cx2341x_ctrl_get_menu); +EXPORT_SYMBOL(cx2341x_ext_ctrls); +EXPORT_SYMBOL(cx2341x_update); +EXPORT_SYMBOL(cx2341x_log_status); +EXPORT_SYMBOL(cx2341x_mpeg_ctrls); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ + diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index 9a4b813..f897c1e 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c @@ -30,9 +30,6 @@ static int set_audclk_freq(struct i2c_cl if (freq != 32000 && freq != 44100 && freq != 48000) return -EINVAL; - /* assert soft reset */ - cx25840_and_or(client, 0x810, ~0x1, 0x01); - /* common for all inputs and rates */ /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ cx25840_write(client, 0x127, 0x50); @@ -46,6 +43,9 @@ static int set_audclk_freq(struct i2c_cl /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0xee39bb01); + if (state->is_cx25836) + break; + /* src3/4/6_ctl = 0x0801f77f */ cx25840_write4(client, 0x900, 0x7ff70108); cx25840_write4(client, 0x904, 0x7ff70108); @@ -59,6 +59,9 @@ static int set_audclk_freq(struct i2c_cl /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0xd66bec00); + if (state->is_cx25836) + break; + /* src3/4/6_ctl = 0x08016d59 */ cx25840_write4(client, 0x900, 0x596d0108); cx25840_write4(client, 0x904, 0x596d0108); @@ -72,6 +75,9 @@ static int set_audclk_freq(struct i2c_cl /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0xe5d69800); + if (state->is_cx25836) + break; + /* src3/4/6_ctl = 0x08014faa */ cx25840_write4(client, 0x900, 0xaa4f0108); cx25840_write4(client, 0x904, 0xaa4f0108); @@ -87,6 +93,9 @@ static int set_audclk_freq(struct i2c_cl /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0x69082a01); + if (state->is_cx25836) + break; + /* src1_ctl = 0x08010000 */ cx25840_write4(client, 0x8f8, 0x00000108); @@ -106,6 +115,9 @@ static int set_audclk_freq(struct i2c_cl /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0xd66bec00); + if (state->is_cx25836) + break; + /* src1_ctl = 0x08010000 */ cx25840_write4(client, 0x8f8, 0xcd600108); @@ -122,6 +134,9 @@ static int set_audclk_freq(struct i2c_cl /* AUX_PLL_FRAC */ cx25840_write4(client, 0x110, 0xe5d69800); + if (state->is_cx25836) + break; + /* src1_ctl = 0x08010000 */ cx25840_write4(client, 0x8f8, 0x00800108); @@ -133,9 +148,6 @@ static int set_audclk_freq(struct i2c_cl } } - /* deassert soft reset */ - cx25840_and_or(client, 0x810, ~0x1, 0x00); - state->audclk_freq = freq; return 0; @@ -148,6 +160,10 @@ void cx25840_audio_set_path(struct i2c_c /* stop microcontroller */ cx25840_and_or(client, 0x803, ~0x10, 0); + /* assert soft reset */ + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 0x01); + /* Mute everything to prevent the PFFT! */ cx25840_write(client, 0x8d3, 0x1f); @@ -161,13 +177,19 @@ void cx25840_audio_set_path(struct i2c_c } else { /* Set Path1 to Analog Demod Main Channel */ cx25840_write4(client, 0x8d0, 0x7038061f); + } + set_audclk_freq(client, state->audclk_freq); + + /* deassert soft reset */ + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 0x00); + + if (state->aud_input != CX25840_AUDIO_SERIAL) { /* When the microcontroller detects the * audio format, it will unmute the lines */ cx25840_and_or(client, 0x803, ~0x10, 0x10); } - - set_audclk_freq(client, state->audclk_freq); } static int get_volume(struct i2c_client *client) @@ -291,11 +313,25 @@ static void set_mute(struct i2c_client * int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) { + struct cx25840_state *state = i2c_get_clientdata(client); struct v4l2_control *ctrl = arg; + int retval; switch (cmd) { case VIDIOC_INT_AUDIO_CLOCK_FREQ: - return set_audclk_freq(client, *(u32 *)arg); + if (state->aud_input != CX25840_AUDIO_SERIAL) { + cx25840_and_or(client, 0x803, ~0x10, 0); + cx25840_write(client, 0x8d3, 0x1f); + } + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 1); + retval = set_audclk_freq(client, *(u32 *)arg); + if (!state->is_cx25836) + cx25840_and_or(client, 0x810, ~0x1, 0); + if (state->aud_input != CX25840_AUDIO_SERIAL) { + cx25840_and_or(client, 0x803, ~0x10, 0x10); + } + return retval; case VIDIOC_G_CTRL: switch (ctrl->id) { diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index a961bb2..5c2036b 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -10,6 +10,9 @@ * * VBI support by Hans Verkuil . * + * NTSC sliced VBI support by Christopher Neufeld + * with additional fixes by Hans Verkuil . + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -43,7 +46,7 @@ MODULE_LICENSE("GPL"); static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; -static int cx25840_debug; +int cx25840_debug; module_param_named(debug,cx25840_debug, int, 0644); @@ -105,7 +108,7 @@ u32 cx25840_read4(struct i2c_client * cl (buffer[2] << 8) | buffer[3]; } -int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask, +int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask, u8 or_value) { return cx25840_write(client, addr, @@ -117,7 +120,8 @@ int cx25840_and_or(struct i2c_client *cl static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input, enum cx25840_audio_input aud_input); -static void log_status(struct i2c_client *client); +static void log_audio_status(struct i2c_client *client); +static void log_video_status(struct i2c_client *client); /* ----------------------------------------------------------------------- */ @@ -147,6 +151,33 @@ static void init_dll2(struct i2c_client cx25840_write(client, 0x15d, 0xe1); } +static void cx25836_initialize(struct i2c_client *client) +{ + /* reset configuration is described on page 3-77 of the CX25836 datasheet */ + /* 2. */ + cx25840_and_or(client, 0x000, ~0x01, 0x01); + cx25840_and_or(client, 0x000, ~0x01, 0x00); + /* 3a. */ + cx25840_and_or(client, 0x15a, ~0x70, 0x00); + /* 3b. */ + cx25840_and_or(client, 0x15b, ~0x1e, 0x06); + /* 3c. */ + cx25840_and_or(client, 0x159, ~0x02, 0x02); + /* 3d. */ + /* There should be a 10-us delay here, but since the + i2c bus already has a 10-us delay we don't need to do + anything */ + /* 3e. */ + cx25840_and_or(client, 0x159, ~0x02, 0x00); + /* 3f. */ + cx25840_and_or(client, 0x159, ~0xc0, 0xc0); + /* 3g. */ + cx25840_and_or(client, 0x159, ~0x01, 0x00); + cx25840_and_or(client, 0x159, ~0x01, 0x01); + /* 3h. */ + cx25840_and_or(client, 0x15b, ~0x1e, 0x10); +} + static void cx25840_initialize(struct i2c_client *client, int loadfw) { struct cx25840_state *state = i2c_get_clientdata(client); @@ -220,17 +251,7 @@ static void input_change(struct i2c_clie cx25840_and_or(client, 0x401, ~0x60, 0); cx25840_and_or(client, 0x401, ~0x60, 0x60); - /* Note: perhaps V4L2_STD_PAL_M should be handled as V4L2_STD_NTSC - instead of V4L2_STD_PAL. Someone needs to test this. */ - if (std & V4L2_STD_PAL) { - /* Follow tuner change procedure for PAL */ - cx25840_write(client, 0x808, 0xff); - cx25840_write(client, 0x80b, 0x10); - } else if (std & V4L2_STD_SECAM) { - /* Select autodetect for SECAM */ - cx25840_write(client, 0x808, 0xff); - cx25840_write(client, 0x80b, 0x10); - } else if (std & V4L2_STD_NTSC) { + if (std & V4L2_STD_525_60) { /* Certain Hauppauge PVR150 models have a hardware bug that causes audio to drop out. For these models the audio standard must be set explicitly. @@ -249,6 +270,14 @@ static void input_change(struct i2c_clie cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6); } cx25840_write(client, 0x80b, 0x00); + } else if (std & V4L2_STD_PAL) { + /* Follow tuner change procedure for PAL */ + cx25840_write(client, 0x808, 0xff); + cx25840_write(client, 0x80b, 0x10); + } else if (std & V4L2_STD_SECAM) { + /* Select autodetect for SECAM */ + cx25840_write(client, 0x808, 0xff); + cx25840_write(client, 0x80b, 0x10); } if (cx25840_read(client, 0x803) & 0x10) { @@ -319,8 +348,10 @@ static int set_input(struct i2c_client * state->vid_input = vid_input; state->aud_input = aud_input; - cx25840_audio_set_path(client); - input_change(client); + if (!state->is_cx25836) { + cx25840_audio_set_path(client); + input_change(client); + } return 0; } @@ -354,6 +385,8 @@ static int set_v4lstd(struct i2c_client } } + v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt); + /* Follow step 9 of section 3.16 in the cx25840 datasheet. Without this PAL may display a vertical ghosting effect. This happens for example with the Yuan MPC622. */ @@ -370,6 +403,7 @@ static int set_v4lstd(struct i2c_client v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) { + struct cx25840_state *state = i2c_get_clientdata(client); /* check VID_FMT_SEL first */ u8 fmt = cx25840_read(client, 0x400) & 0xf; @@ -383,7 +417,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2 { /* if the audio std is A2-M, then this is the South Korean NTSC standard */ - if (cx25840_read(client, 0x805) == 2) + if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2) return V4L2_STD_NTSC_M_KR; return V4L2_STD_NTSC_M; } @@ -456,6 +490,8 @@ static int set_v4lctrl(struct i2c_client case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: + if (state->is_cx25836) + return -EINVAL; return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); default: @@ -490,6 +526,8 @@ static int get_v4lctrl(struct i2c_client case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_MUTE: + if (state->is_cx25836) + return -EINVAL; return cx25840_audio(client, VIDIOC_G_CTRL, ctrl); default: return -EINVAL; @@ -579,91 +617,6 @@ static int set_v4lfmt(struct i2c_client /* ----------------------------------------------------------------------- */ -static struct v4l2_queryctrl cx25840_qctrl[] = { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 128, - .flags = 0, - }, { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 64, - .flags = 0, - }, { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 64, - .flags = 0, - }, { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Hue", - .minimum = -128, - .maximum = 127, - .step = 1, - .default_value = 0, - .flags = 0, - }, { - .id = V4L2_CID_AUDIO_VOLUME, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 58880, - .flags = 0, - }, { - .id = V4L2_CID_AUDIO_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Balance", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - .flags = 0, - }, { - .id = V4L2_CID_AUDIO_MUTE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - .flags = 0, - }, { - .id = V4L2_CID_AUDIO_BASS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Bass", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - }, { - .id = V4L2_CID_AUDIO_TREBLE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Treble", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - }, -}; - -/* ----------------------------------------------------------------------- */ - static int cx25840_command(struct i2c_client *client, unsigned int cmd, void *arg) { @@ -706,8 +659,8 @@ #endif case VIDIOC_STREAMON: v4l_dbg(1, cx25840_debug, client, "enable output\n"); - cx25840_write(client, 0x115, 0x8c); - cx25840_write(client, 0x116, 0x07); + cx25840_write(client, 0x115, state->is_cx25836 ? 0x0c : 0x8c); + cx25840_write(client, 0x116, state->is_cx25836 ? 0x04 : 0x07); break; case VIDIOC_STREAMOFF: @@ -717,7 +670,9 @@ #endif break; case VIDIOC_LOG_STATUS: - log_status(client); + log_video_status(client); + if (!state->is_cx25836) + log_audio_status(client); break; case VIDIOC_G_CTRL: @@ -729,13 +684,29 @@ #endif case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *qc = arg; - int i; - for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++) - if (qc->id && qc->id == cx25840_qctrl[i].id) { - memcpy(qc, &cx25840_qctrl[i], sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill_std(qc); + default: + break; + } + if (state->is_cx25836) + return -EINVAL; + + switch (qc->id) { + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_MUTE: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + return v4l2_ctrl_query_fill_std(qc); + default: + return -EINVAL; + } return -EINVAL; } @@ -760,31 +731,41 @@ #endif return set_input(client, route->input, state->aud_input); case VIDIOC_INT_G_AUDIO_ROUTING: + if (state->is_cx25836) + return -EINVAL; route->input = state->aud_input; route->output = 0; break; case VIDIOC_INT_S_AUDIO_ROUTING: + if (state->is_cx25836) + return -EINVAL; return set_input(client, state->vid_input, route->input); case VIDIOC_S_FREQUENCY: - input_change(client); + if (!state->is_cx25836) { + input_change(client); + } break; case VIDIOC_G_TUNER: { - u8 mode = cx25840_read(client, 0x804); - u8 vpres = cx25840_read(client, 0x80a) & 0x10; + u8 vpres = cx25840_read(client, 0x40e) & 0x20; + u8 mode; int val = 0; if (state->radio) break; + vt->signal = vpres ? 0xffff : 0x0; + if (state->is_cx25836) + break; + vt->capability |= V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; - vt->signal = vpres ? 0xffff : 0x0; + mode = cx25840_read(client, 0x804); /* get rxsubchans and audmode */ if ((mode & 0xf) == 1) @@ -804,7 +785,7 @@ #endif } case VIDIOC_S_TUNER: - if (state->radio) + if (state->radio || state->is_cx25836) break; switch (vt->audmode) { @@ -846,12 +827,14 @@ #endif return set_v4lfmt(client, (struct v4l2_format *)arg); case VIDIOC_INT_RESET: - cx25840_initialize(client, 0); + if (state->is_cx25836) + cx25836_initialize(client); + else + cx25840_initialize(client, 0); break; case VIDIOC_INT_G_CHIP_IDENT: - *(enum v4l2_chip_ident *)arg = - V4L2_IDENT_CX25840 + ((cx25840_read(client, 0x100) >> 4) & 0xf); + *(enum v4l2_chip_ident *)arg = state->id; break; default: @@ -870,6 +853,7 @@ static int cx25840_detect_client(struct { struct i2c_client *client; struct cx25840_state *state; + enum v4l2_chip_ident id; u16 device_id; /* Check if the adapter supports the needed features @@ -878,10 +862,11 @@ static int cx25840_detect_client(struct if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) return 0; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == 0) + state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); + if (state == 0) return -ENOMEM; + client = &state->c; client->addr = address; client->adapter = adapter; client->driver = &i2c_driver_cx25840; @@ -893,10 +878,18 @@ static int cx25840_detect_client(struct device_id |= cx25840_read(client, 0x100); /* The high byte of the device ID should be - * 0x84 if chip is present */ - if ((device_id & 0xff00) != 0x8400) { + * 0x83 for the cx2583x and 0x84 for the cx2584x */ + if ((device_id & 0xff00) == 0x8300) { + id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; + state->is_cx25836 = 1; + } + else if ((device_id & 0xff00) == 0x8400) { + id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); + state->is_cx25836 = 0; + } + else { v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n"); - kfree(client); + kfree(state); return 0; } @@ -905,21 +898,19 @@ static int cx25840_detect_client(struct (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3, address << 1, adapter->name); - state = kmalloc(sizeof(struct cx25840_state), GFP_KERNEL); - if (state == NULL) { - kfree(client); - return -ENOMEM; - } - i2c_set_clientdata(client, state); - memset(state, 0, sizeof(struct cx25840_state)); state->vid_input = CX25840_COMPOSITE7; state->aud_input = CX25840_AUDIO8; state->audclk_freq = 48000; state->pvr150_workaround = 0; state->audmode = V4L2_TUNER_MODE_LANG1; + state->vbi_line_offset = 8; + state->id = id; - cx25840_initialize(client, 1); + if (state->is_cx25836) + cx25836_initialize(client); + else + cx25840_initialize(client, 1); i2c_attach_client(client); @@ -944,7 +935,6 @@ static int cx25840_detach_client(struct } kfree(state); - kfree(client); return 0; } @@ -977,7 +967,7 @@ module_exit(m__exit); /* ----------------------------------------------------------------------- */ -static void log_status(struct i2c_client *client) +static void log_video_status(struct i2c_client *client) { static const char *const fmt_strs[] = { "0x0", @@ -989,9 +979,36 @@ static void log_status(struct i2c_client }; struct cx25840_state *state = i2c_get_clientdata(client); - u8 microctrl_vidfmt = cx25840_read(client, 0x80a); u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; u8 gen_stat1 = cx25840_read(client, 0x40d); + u8 gen_stat2 = cx25840_read(client, 0x40e); + int vid_input = state->vid_input; + + v4l_info(client, "Video signal: %spresent\n", + (gen_stat2 & 0x20) ? "" : "not "); + v4l_info(client, "Detected format: %s\n", + fmt_strs[gen_stat1 & 0xf]); + + v4l_info(client, "Specified standard: %s\n", + vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); + + if (vid_input >= CX25840_COMPOSITE1 && + vid_input <= CX25840_COMPOSITE8) { + v4l_info(client, "Specified video input: Composite %d\n", + vid_input - CX25840_COMPOSITE1 + 1); + } else { + v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n", + (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8); + } + + v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq); +} + +/* ----------------------------------------------------------------------- */ + +static void log_audio_status(struct i2c_client *client) +{ + struct cx25840_state *state = i2c_get_clientdata(client); u8 download_ctl = cx25840_read(client, 0x803); u8 mod_det_stat0 = cx25840_read(client, 0x804); u8 mod_det_stat1 = cx25840_read(client, 0x805); @@ -999,15 +1016,9 @@ static void log_status(struct i2c_client u8 pref_mode = cx25840_read(client, 0x809); u8 afc0 = cx25840_read(client, 0x80b); u8 mute_ctl = cx25840_read(client, 0x8d3); - int vid_input = state->vid_input; int aud_input = state->aud_input; char *p; - v4l_info(client, "Video signal: %spresent\n", - (microctrl_vidfmt & 0x10) ? "" : "not "); - v4l_info(client, "Detected format: %s\n", - fmt_strs[gen_stat1 & 0xf]); - switch (mod_det_stat0) { case 0x00: p = "mono"; break; case 0x01: p = "stereo"; break; @@ -1107,25 +1118,12 @@ static void log_status(struct i2c_client v4l_info(client, "Configured audio system: %s\n", p); } - v4l_info(client, "Specified standard: %s\n", - vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); - - if (vid_input >= CX25840_COMPOSITE1 && - vid_input <= CX25840_COMPOSITE8) { - v4l_info(client, "Specified video input: Composite %d\n", - vid_input - CX25840_COMPOSITE1 + 1); - } else { - v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n", - (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8); - } if (aud_input) { v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input); } else { v4l_info(client, "Specified audio input: External\n"); } - v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq); - switch (pref_mode & 0xf) { case 0: p = "mono/language A"; break; case 1: p = "language B"; break; diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h index 1736929..2804906 100644 --- a/drivers/media/video/cx25840/cx25840-core.h +++ b/drivers/media/video/cx25840/cx25840-core.h @@ -24,6 +24,8 @@ #define _CX25840_CORE_H_ #include #include +extern int cx25840_debug; + /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is present in Hauppauge PVR-150 (and possibly PVR-500) cards that have certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The @@ -33,12 +35,16 @@ #include #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0) struct cx25840_state { + struct i2c_client c; int pvr150_workaround; int radio; enum cx25840_video_input vid_input; enum cx25840_audio_input aud_input; u32 audclk_freq; int audmode; + int vbi_line_offset; + enum v4l2_chip_ident id; + int is_cx25836; }; /* ----------------------------------------------------------------------- */ @@ -47,7 +53,7 @@ int cx25840_write(struct i2c_client *cli int cx25840_write4(struct i2c_client *client, u16 addr, u32 value); u8 cx25840_read(struct i2c_client *client, u16 addr); u32 cx25840_read4(struct i2c_client *client, u16 addr); -int cx25840_and_or(struct i2c_client *client, u16 addr, u8 mask, u8 value); +int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value); v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client); /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 57feca2..6cc8bf2 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c @@ -84,67 +84,140 @@ static int decode_vps(u8 * dst, u8 * p) void cx25840_vbi_setup(struct i2c_client *client) { + struct cx25840_state *state = i2c_get_clientdata(client); v4l2_std_id std = cx25840_get_v4lstd(client); + int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation; + int luma_lpf,uv_lpf, comb; + u32 pll_int,pll_frac,pll_post; + /* datasheet startup, step 8d */ if (std & ~V4L2_STD_NTSC) { - /* datasheet startup, step 8d */ cx25840_write(client, 0x49f, 0x11); + } else { + cx25840_write(client, 0x49f, 0x14); + } - cx25840_write(client, 0x470, 0x84); - cx25840_write(client, 0x471, 0x00); - cx25840_write(client, 0x472, 0x2d); - cx25840_write(client, 0x473, 0x5d); - - cx25840_write(client, 0x474, 0x24); - cx25840_write(client, 0x475, 0x40); - cx25840_write(client, 0x476, 0x24); - cx25840_write(client, 0x477, 0x28); - - cx25840_write(client, 0x478, 0x1f); - cx25840_write(client, 0x479, 0x02); + if (std & V4L2_STD_625_50) { + hblank=0x084; + hactive=0x2d0; + burst=0x5d; + vblank=0x024; + vactive=0x244; + vblank656=0x28; + src_decimation=0x21f; + luma_lpf=2; if (std & V4L2_STD_SECAM) { - cx25840_write(client, 0x47a, 0x80); - cx25840_write(client, 0x47b, 0x00); - cx25840_write(client, 0x47c, 0x5f); - cx25840_write(client, 0x47d, 0x42); + uv_lpf=0; + comb=0; + sc=0x0a425f; } else { - cx25840_write(client, 0x47a, 0x90); - cx25840_write(client, 0x47b, 0x20); - cx25840_write(client, 0x47c, 0x63); - cx25840_write(client, 0x47d, 0x82); + uv_lpf=1; + comb=0x20; + sc=0x0a8263; } - - cx25840_write(client, 0x47e, 0x0a); - cx25840_write(client, 0x47f, 0x01); } else { - /* datasheet startup, step 8d */ - cx25840_write(client, 0x49f, 0x14); + hactive=720; + hblank=122; + vactive=487; + luma_lpf=1; + uv_lpf=1; + + src_decimation=0x21f; + if (std == V4L2_STD_PAL_M) { + vblank=20; + vblank656=24; + burst=0x61; + comb=0x20; + + sc=555452; + } else { + vblank=26; + vblank656=26; + burst=0x5b; + comb=0x66; + sc=556063; + } + } + + /* DEBUG: Displays configured PLL frequency */ + pll_int=cx25840_read(client, 0x108); + pll_frac=cx25840_read4(client, 0x10c)&0x1ffffff; + pll_post=cx25840_read(client, 0x109); + v4l_dbg(1, cx25840_debug, client, + "PLL regs = int: %u, frac: %u, post: %u\n", + pll_int,pll_frac,pll_post); + + if (pll_post) { + int fin, fsc; + int pll= (28636363L*((((u64)pll_int)<<25L)+pll_frac)) >>25L; + + pll/=pll_post; + v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n", + pll/1000000, pll%1000000); + v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n", + pll/8000000, (pll/8)%1000000); + + fin=((u64)src_decimation*pll)>>12; + v4l_dbg(1, cx25840_debug, client, "ADC Sampling freq = " + "%d.%06d MHz\n", + fin/1000000,fin%1000000); + + fsc= (((u64)sc)*pll) >> 24L; + v4l_dbg(1, cx25840_debug, client, "Chroma sub-carrier freq = " + "%d.%06d MHz\n", + fsc/1000000,fsc%1000000); + + v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, " + "vblank %i , vactive %i, vblank656 %i, src_dec %i," + "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x," + " sc 0x%06x\n", + hblank, hactive, vblank, vactive, vblank656, + src_decimation, burst, luma_lpf, uv_lpf, comb, sc); + } + + /* Sets horizontal blanking delay and active lines */ + cx25840_write(client, 0x470, hblank); + cx25840_write(client, 0x471, 0xff&(((hblank>>8)&0x3)|(hactive <<4))); + cx25840_write(client, 0x472, hactive>>4); + + /* Sets burst gate delay */ + cx25840_write(client, 0x473, burst); - cx25840_write(client, 0x470, 0x7a); - cx25840_write(client, 0x471, 0x00); - cx25840_write(client, 0x472, 0x2d); - cx25840_write(client, 0x473, 0x5b); + /* Sets vertical blanking delay and active duration */ + cx25840_write(client, 0x474, vblank); + cx25840_write(client, 0x475, 0xff&(((vblank>>8)&0x3)|(vactive <<4))); + cx25840_write(client, 0x476, vactive>>4); + cx25840_write(client, 0x477, vblank656); - cx25840_write(client, 0x474, 0x1a); - cx25840_write(client, 0x475, 0x70); - cx25840_write(client, 0x476, 0x1e); - cx25840_write(client, 0x477, 0x1e); + /* Sets src decimation rate */ + cx25840_write(client, 0x478, 0xff&src_decimation); + cx25840_write(client, 0x479, 0xff&(src_decimation>>8)); - cx25840_write(client, 0x478, 0x1f); - cx25840_write(client, 0x479, 0x02); - cx25840_write(client, 0x47a, 0x50); - cx25840_write(client, 0x47b, 0x66); + /* Sets Luma and UV Low pass filters */ + cx25840_write(client, 0x47a, luma_lpf<<6|((uv_lpf<<4)&0x30)); - cx25840_write(client, 0x47c, 0x1f); - cx25840_write(client, 0x47d, 0x7c); - cx25840_write(client, 0x47e, 0x08); + /* Enables comb filters */ + cx25840_write(client, 0x47b, comb); + + /* Sets SC Step*/ + cx25840_write(client, 0x47c, sc); + cx25840_write(client, 0x47d, 0xff&sc>>8); + cx25840_write(client, 0x47e, 0xff&sc>>16); + + /* Sets VBI parameters */ + if (std & V4L2_STD_625_50) { + cx25840_write(client, 0x47f, 0x01); + state->vbi_line_offset = 5; + } else { cx25840_write(client, 0x47f, 0x00); + state->vbi_line_offset = 8; } } int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) { + struct cx25840_state *state = i2c_get_clientdata(client); struct v4l2_format *fmt; struct v4l2_sliced_vbi_format *svbi; @@ -182,7 +255,7 @@ int cx25840_vbi(struct i2c_client *clien case VIDIOC_S_FMT: { - int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); + int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); int vbi_offset = is_pal ? 1 : 0; int i, x; u8 lcr[24]; @@ -211,7 +284,7 @@ int cx25840_vbi(struct i2c_client *clien cx25840_vbi_setup(client); /* Sliced VBI */ - cx25840_write(client, 0x404, 0x36); /* Ancillery data */ + cx25840_write(client, 0x404, 0x32); /* Ancillary data */ cx25840_write(client, 0x406, 0x13); cx25840_write(client, 0x47f, vbi_offset); @@ -248,8 +321,18 @@ int cx25840_vbi(struct i2c_client *clien } } - for (x = 1, i = 0x424; i <= 0x434; i++, x++) { - cx25840_write(client, i, lcr[6 + x]); + if (is_pal) { + for (x = 1, i = 0x424; i <= 0x434; i++, x++) { + cx25840_write(client, i, lcr[6 + x]); + } + } + else { + for (x = 1, i = 0x424; i <= 0x430; i++, x++) { + cx25840_write(client, i, lcr[9 + x]); + } + for (i = 0x431; i <= 0x434; i++) { + cx25840_write(client, i, 0); + } } cx25840_write(client, 0x43c, 0x16); @@ -257,7 +340,7 @@ int cx25840_vbi(struct i2c_client *clien if (is_pal) { cx25840_write(client, 0x474, 0x2a); } else { - cx25840_write(client, 0x474, 0x1a + 6); + cx25840_write(client, 0x474, 0x22); } break; } @@ -278,7 +361,7 @@ int cx25840_vbi(struct i2c_client *clien id1 = p[-1]; id2 = p[0] & 0xf; l = p[2] & 0x3f; - l += 5; + l += state->vbi_line_offset; p += 4; switch (id2) { diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 6302739..80e23ee 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -35,13 +35,25 @@ config VIDEO_CX88_ALSA To compile this driver as a module, choose M here: the module will be called cx88-alsa. +config VIDEO_CX88_BLACKBIRD + tristate "Blackbird MPEG encoder support (cx2388x + cx23416)" + depends on VIDEO_CX88 + select VIDEO_CX2341X + ---help--- + This adds support for MPEG encoder cards based on the + Blackbird reference design, using the Conexant 2388x + and 23416 chips. + + To compile this driver as a module, choose M here: the + module will be called cx88-blackbird. + config VIDEO_CX88_DVB tristate "DVB/ATSC Support for cx2388x based TV cards" depends on VIDEO_CX88 && DVB_CORE select VIDEO_BUF_DVB ---help--- This adds support for DVB/ATSC cards based on the - Connexant 2388x chip. + Conexant 2388x chip. To compile this driver as a module, choose M here: the module will be called cx88-dvb. @@ -61,6 +73,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS select DVB_LGDT330X select DVB_NXT200X select DVB_CX24123 + select DVB_ISL6421 ---help--- This builds cx88-dvb with all currently supported frontend demodulators. If you wish to tweak your configuration, and @@ -139,6 +152,7 @@ config VIDEO_CX88_DVB_CX24123 default y depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS select DVB_CX24123 + select DVB_ISL6421 ---help--- This adds DVB-S support for cards based on the Connexant 2388x chip and the CX24123 demodulator. diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 0dcd09b..352b919 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -3,9 +3,10 @@ cx88xx-objs := cx88-cards.o cx88-core.o cx8800-objs := cx88-video.o cx88-vbi.o cx8802-objs := cx88-mpeg.o -obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o -obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o +obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o +obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o +obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o EXTRA_CFLAGS += -Idrivers/media/video diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 320b3d9..2194cbe 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -4,7 +4,7 @@ * PCI function #1 of the cx2388x. * * (c) 2005,2006 Ricardo Cerqueira - * (c) 2005 Mauro Carvalho Chehab + * (c) 2005 Mauro Carvalho Chehab * Based on a dummy cx88 module by Gerd Knorr * Based on dummy.c by Jaroslav Kysela * @@ -111,7 +111,7 @@ MODULE_PARM_DESC(index, "Index value for MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards"); MODULE_AUTHOR("Ricardo Cerqueira"); -MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Conexant,23881}," "{{Conexant,23882}," @@ -696,7 +696,6 @@ static int __devinit snd_cx88_create(str chip->irq = -1; spin_lock_init(&chip->reg_lock); - cx88_reset(core); chip->core = core; /* get irq */ diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index e100d8e..78df666 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -30,9 +30,10 @@ #include #include #include #include +#include +#include #include "cx88.h" -#include MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards"); MODULE_AUTHOR("Jelle Foks , Gerd Knorr [SuSE Labs]"); @@ -53,7 +54,6 @@ static LIST_HEAD(cx8802_devlist); /* ------------------------------------------------------------------ */ -#define BLACKBIRD_FIRM_ENC_FILENAME "blackbird-fw-enc.bin" #define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024 /* defines below are from ivtv-driver.h */ @@ -63,8 +63,6 @@ #define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFF /* Firmware API commands */ #define IVTV_API_STD_TIMEOUT 500 -#define BLACKBIRD_API_PING 0x80 -#define BLACKBIRD_API_BEGIN_CAPTURE 0x81 enum blackbird_capture_type { BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_CAPTURE, @@ -78,205 +76,29 @@ enum blackbird_capture_bits { BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08, BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE = 0x10 }; -#define BLACKBIRD_API_END_CAPTURE 0x82 enum blackbird_capture_end { BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */ BLACKBIRD_END_NOW, /* stop immediately, no irq */ }; -#define BLACKBIRD_API_SET_AUDIO_ID 0x89 -#define BLACKBIRD_API_SET_VIDEO_ID 0x8B -#define BLACKBIRD_API_SET_PCR_ID 0x8D -#define BLACKBIRD_API_SET_FRAMERATE 0x8F enum blackbird_framerate { BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */ BLACKBIRD_FRAMERATE_PAL_25 /* PAL: 25fps */ }; -#define BLACKBIRD_API_SET_RESOLUTION 0x91 -#define BLACKBIRD_API_SET_VIDEO_BITRATE 0x95 -enum blackbird_video_bitrate_type { - BLACKBIRD_VIDEO_VBR, - BLACKBIRD_VIDEO_CBR -}; -#define BLACKBIRD_PEAK_RATE_DIVISOR 400 -enum blackbird_mux_rate { - BLACKBIRD_MUX_RATE_DEFAULT, - /* dvd mux rate: multiply by 400 to get the actual rate */ - BLACKBIRD_MUX_RATE_DVD = 25200 -}; -#define BLACKBIRD_API_SET_GOP_STRUCTURE 0x97 -#define BLACKBIRD_API_SET_ASPECT_RATIO 0x99 -enum blackbird_aspect_ratio { - BLACKBIRD_ASPECT_RATIO_FORBIDDEN, - BLACKBIRD_ASPECT_RATIO_1_1_SQUARE, - BLACKBIRD_ASPECT_RATIO_4_3, - BLACKBIRD_ASPECT_RATIO_16_9, - BLACKBIRD_ASPECT_RATIO_221_100, - BLACKBIRD_ASPECT_RATIO_RESERVED -}; -#define BLACKBIRD_API_SET_DNR_MODE 0x9B -enum blackbird_dnr_bits { - BLACKBIRD_DNR_BITS_MANUAL, - BLACKBIRD_DNR_BITS_AUTO_SPATIAL, - BLACKBIRD_DNR_BITS_AUTO_TEMPORAL, - BLACKBIRD_DNR_BITS_AUTO -}; -enum blackbird_median_filter { - BLACKBIRD_MEDIAN_FILTER_DISABLED, - BLACKBIRD_MEDIAN_FILTER_HORIZONTAL, - BLACKBIRD_MEDIAN_FILTER_VERTICAL, - BLACKBIRD_MEDIAN_FILTER_HV, - BLACKBIRD_MEDIAN_FILTER_DIAGONAL -}; -#define BLACKBIRD_API_SET_MANUAL_DNR 0x9D -#define BLACKBIRD_API_SET_DNR_MEDIAN 0x9F -#define BLACKBIRD_API_SET_SPATIAL_FILTER 0xA1 -enum blackbird_spatial_filter_luma { - BLACKBIRD_SPATIAL_FILTER_LUMA_DISABLED, - BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ, - BLACKBIRD_SPATIAL_FILTER_LUMA_1D_VERT, - BLACKBIRD_SPATIAL_FILTER_LUMA_2D_HV, /* separable, default */ - BLACKBIRD_SPATIAL_FILTER_LUMA_2D_SYMM /* symmetric non-separable */ -}; -enum blackbird_spatial_filter_chroma { - BLACKBIRD_SPATIAL_FILTER_CHROMA_DISABLED, - BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ /* default */ -}; -#define BLACKBIRD_API_SET_3_2_PULLDOWN 0xB1 -enum blackbird_pulldown { - BLACKBIRD_3_2_PULLDOWN_DISABLED, - BLACKBIRD_3_2_PULLDOWN_ENABLED -}; -#define BLACKBIRD_API_SET_VBI_LINE_NO 0xB7 -enum blackbird_vbi_line_bits { - BLACKBIRD_VBI_LINE_BITS_TOP_FIELD, - BLACKBIRD_VBI_LINE_BITS_BOT_FIELD = (1 << 31), - BLACKBIRD_VBI_LINE_BITS_ALL_LINES = 0xFFFFFFFF -}; -enum blackbird_vbi_line { - BLACKBIRD_VBI_LINE_DISABLED, - BLACKBIRD_VBI_LINE_ENABLED -}; -enum blackbird_vbi_slicing { - BLACKBIRD_VBI_SLICING_NONE, - BLACKBIRD_VBI_SLICING_CLOSED_CAPTION -}; -#define BLACKBIRD_API_SET_STREAM_TYPE 0xB9 -enum blackbird_stream_type { - BLACKBIRD_STREAM_PROGRAM, - BLACKBIRD_STREAM_TRANSPORT, - BLACKBIRD_STREAM_MPEG1, - BLACKBIRD_STREAM_PES_AV, - BLACKBIRD_STREAM_UNKNOWN4, - BLACKBIRD_STREAM_PES_VIDEO, - BLACKBIRD_STREAM_UNKNOWN6, - BLACKBIRD_STREAM_PES_AUDIO, - BLACKBIRD_STREAM_UNKNOWN8, - BLACKBIRD_STREAM_UNKNOWN9, /* audio/pcm ? */ - BLACKBIRD_STREAM_DVD, - BLACKBIRD_STREAM_VCD, - BLACKBIRD_STREAM_UNKNOWN12 /* svcd/xvcd ? */ -}; -#define BLACKBIRD_API_SET_OUTPUT_PORT 0xBB enum blackbird_stream_port { BLACKBIRD_OUTPUT_PORT_MEMORY, BLACKBIRD_OUTPUT_PORT_STREAMING, BLACKBIRD_OUTPUT_PORT_SERIAL }; -#define BLACKBIRD_API_SET_AUDIO_PARAMS 0xBD -enum blackbird_audio_bits_sample_rate { - BLACKBIRD_AUDIO_BITS_44100HZ, - BLACKBIRD_AUDIO_BITS_48000HZ, - BLACKBIRD_AUDIO_BITS_32000HZ, - BLACKBIRD_AUDIO_BITS_RESERVED_HZ, -}; -enum blackbird_audio_bits_encoding { - BLACKBIRD_AUDIO_BITS_LAYER_1 = 0x1 << 2, - BLACKBIRD_AUDIO_BITS_LAYER_2 = 0x2 << 2, -}; -enum blackbird_audio_bits_bitrate_layer_1 { - BLACKBIRD_AUDIO_BITS_LAYER_1_FREE_FORMAT, - BLACKBIRD_AUDIO_BITS_LAYER_1_32 = 0x01 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_64 = 0x02 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_96 = 0x03 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_128 = 0x04 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_160 = 0x05 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_192 = 0x06 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_224 = 0x07 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_256 = 0x08 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_288 = 0x09 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_320 = 0x0A << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_352 = 0x0B << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_384 = 0x0C << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_416 = 0x0D << 4, - BLACKBIRD_AUDIO_BITS_LAYER_1_448 = 0x0E << 4, -}; -enum blackbird_audio_bits_bitrate_layer_2 { - BLACKBIRD_AUDIO_BITS_LAYER_2_FREE_FORMAT, - BLACKBIRD_AUDIO_BITS_LAYER_2_32 = 0x01 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_48 = 0x02 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_56 = 0x03 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_64 = 0x04 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_80 = 0x05 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_96 = 0x06 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_112 = 0x07 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_128 = 0x08 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_160 = 0x09 << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_192 = 0x0A << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_224 = 0x0B << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_256 = 0x0C << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_320 = 0x0D << 4, - BLACKBIRD_AUDIO_BITS_LAYER_2_384 = 0x0E << 4, -}; -enum blackbird_audio_bits_mode { - BLACKBIRD_AUDIO_BITS_STEREO, - BLACKBIRD_AUDIO_BITS_JOINT_STEREO = 0x1 << 8, - BLACKBIRD_AUDIO_BITS_DUAL = 0x2 << 8, - BLACKBIRD_AUDIO_BITS_MONO = 0x3 << 8, -}; -enum blackbird_audio_bits_mode_extension { - BLACKBIRD_AUDIO_BITS_BOUND_4, - BLACKBIRD_AUDIO_BITS_BOUND_8 = 0x1 << 10, - BLACKBIRD_AUDIO_BITS_BOUND_12 = 0x2 << 10, - BLACKBIRD_AUDIO_BITS_BOUND_16 = 0x3 << 10, -}; -enum blackbird_audio_bits_emphasis { - BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE, - BLACKBIRD_AUDIO_BITS_EMPHASIS_50_15 = 0x1 << 12, - BLACKBIRD_AUDIO_BITS_EMPHASIS_RESERVED = 0x2 << 12, - BLACKBIRD_AUDIO_BITS_EMPHASIS_CCITT_J17 = 0x3 << 12, -}; -enum blackbird_audio_bits_crc { - BLACKBIRD_AUDIO_BITS_CRC_OFF, - BLACKBIRD_AUDIO_BITS_CRC_ON = 0x1 << 14, -}; -enum blackbird_audio_bits_copyright { - BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF, - BLACKBIRD_AUDIO_BITS_COPYRIGHT_ON = 0x1 << 15, -}; -enum blackbird_audio_bits_original { - BLACKBIRD_AUDIO_BITS_COPY, - BLACKBIRD_AUDIO_BITS_ORIGINAL = 0x1 << 16, -}; -#define BLACKBIRD_API_HALT 0xC3 -#define BLACKBIRD_API_GET_VERSION 0xC4 -#define BLACKBIRD_API_SET_GOP_CLOSURE 0xC5 -enum blackbird_gop_closure { - BLACKBIRD_GOP_CLOSURE_OFF, - BLACKBIRD_GOP_CLOSURE_ON, -}; -#define BLACKBIRD_API_DATA_XFER_STATUS 0xC6 enum blackbird_data_xfer_status { BLACKBIRD_MORE_BUFFERS_FOLLOW, BLACKBIRD_LAST_BUFFER, }; -#define BLACKBIRD_API_PROGRAM_INDEX_INFO 0xC7 enum blackbird_picture_mask { BLACKBIRD_PICTURE_MASK_NONE, BLACKBIRD_PICTURE_MASK_I_FRAMES, BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3, BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7, }; -#define BLACKBIRD_API_SET_VBI_PARAMS 0xC8 enum blackbird_vbi_mode_bits { BLACKBIRD_VBI_BITS_SLICED, BLACKBIRD_VBI_BITS_RAW, @@ -288,33 +110,23 @@ enum blackbird_vbi_insertion_bits { BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1, BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1, }; -#define BLACKBIRD_API_SET_DMA_BLOCK_SIZE 0xC9 enum blackbird_dma_unit { BLACKBIRD_DMA_BYTES, BLACKBIRD_DMA_FRAMES, }; -#define BLACKBIRD_API_DMA_TRANSFER_INFO 0xCA -#define BLACKBIRD_API_DMA_TRANSFER_STAT 0xCB enum blackbird_dma_transfer_status_bits { BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01, BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04, BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10, }; -#define BLACKBIRD_API_SET_DMA2HOST_ADDR 0xCC -#define BLACKBIRD_API_INIT_VIDEO_INPUT 0xCD -#define BLACKBIRD_API_SET_FRAMESKIP 0xD0 -#define BLACKBIRD_API_PAUSE 0xD2 enum blackbird_pause { BLACKBIRD_PAUSE_ENCODING, BLACKBIRD_RESUME_ENCODING, }; -#define BLACKBIRD_API_REFRESH_INPUT 0xD3 -#define BLACKBIRD_API_SET_COPYRIGHT 0xD4 enum blackbird_copyright { BLACKBIRD_COPYRIGHT_OFF, BLACKBIRD_COPYRIGHT_ON, }; -#define BLACKBIRD_API_SET_NOTIFICATION 0xD5 enum blackbird_notification_type { BLACKBIRD_NOTIFICATION_REFRESH, }; @@ -325,7 +137,6 @@ enum blackbird_notification_status { enum blackbird_notification_mailbox { BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1, }; -#define BLACKBIRD_API_SET_CAPTURE_LINES 0xD6 enum blackbird_field1_lines { BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */ BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */ @@ -336,12 +147,10 @@ enum blackbird_field2_lines { BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */ BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */ }; -#define BLACKBIRD_API_SET_CUSTOM_DATA 0xD7 enum blackbird_custom_data_type { BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, BLACKBIRD_CUSTOM_PRIVATE_PACKET, }; -#define BLACKBIRD_API_MUTE_VIDEO 0xD9 enum blackbird_mute { BLACKBIRD_UNMUTE, BLACKBIRD_MUTE, @@ -356,7 +165,6 @@ enum blackbird_mute_video_shift { BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16, BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24, }; -#define BLACKBIRD_API_MUTE_AUDIO 0xDA /* Registers */ #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/) @@ -498,15 +306,12 @@ static int register_read(struct cx88_cor /* ------------------------------------------------------------------ */ -/* We don't need to call the API often, so using just one mailbox will probably suffice */ -static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command, - u32 inputcnt, u32 outputcnt, ...) +static int blackbird_mbox_func(void *priv, int command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]) { + struct cx8802_dev *dev = priv; unsigned long timeout; u32 value, flag, retval; int i; - va_list args; - va_start(args, outputcnt); dprintk(1,"%s: 0x%X\n", __FUNCTION__, command); @@ -530,12 +335,11 @@ static int blackbird_api_cmd(struct cx88 /* write command + args + fill remaining with zeros */ memory_write(dev->core, dev->mailbox + 1, command); /* command code */ memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */ - for (i = 0; i < inputcnt ; i++) { - value = va_arg(args, int); - memory_write(dev->core, dev->mailbox + 4 + i, value); - dprintk(1, "API Input %d = %d\n", i, value); + for (i = 0; i < in; i++) { + memory_write(dev->core, dev->mailbox + 4 + i, data[i]); + dprintk(1, "API Input %d = %d\n", i, data[i]); } - for (; i < 16 ; i++) + for (; i < CX2341X_MBOX_MAX_DATA; i++) memory_write(dev->core, dev->mailbox + 4 + i, 0); flag |= 3; /* tell 'em we're done writing */ @@ -555,12 +359,10 @@ static int blackbird_api_cmd(struct cx88 } /* read output values */ - for (i = 0; i < outputcnt ; i++) { - int *vptr = va_arg(args, int *); - memory_read(dev->core, dev->mailbox + 4 + i, vptr); - dprintk(1, "API Output %d = %d\n", i, *vptr); + for (i = 0; i < out; i++) { + memory_read(dev->core, dev->mailbox + 4 + i, data + i); + dprintk(1, "API Output %d = %d\n", i, data[i]); } - va_end(args); memory_read(dev->core, dev->mailbox + 2, &retval); dprintk(1, "API result = %d\n",retval); @@ -569,7 +371,29 @@ static int blackbird_api_cmd(struct cx88 memory_write(dev->core, dev->mailbox, flag); return retval; } +/* ------------------------------------------------------------------ */ + +/* We don't need to call the API often, so using just one mailbox will probably suffice */ +static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command, + u32 inputcnt, u32 outputcnt, ...) +{ + u32 data[CX2341X_MBOX_MAX_DATA]; + va_list vargs; + int i, err; + va_start(vargs, outputcnt); + + for (i = 0; i < inputcnt; i++) { + data[i] = va_arg(vargs, int); + } + err = blackbird_mbox_func(dev, command, inputcnt, outputcnt, data); + for (i = 0; i < outputcnt; i++) { + int *vptr = va_arg(vargs, int *); + *vptr = data[i]; + } + va_end(vargs); + return err; +} static int blackbird_find_mailbox(struct cx8802_dev *dev) { @@ -614,13 +438,13 @@ static int blackbird_load_firmware(struc if (retval < 0) dprintk(0, "Error with register_write\n"); - retval = request_firmware(&firmware, BLACKBIRD_FIRM_ENC_FILENAME, + retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME, &dev->pci->dev); if (retval != 0) { dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n", - BLACKBIRD_FIRM_ENC_FILENAME); + CX2341X_FIRM_ENC_FILENAME); dprintk(0, "Please fix your hotplug setup, the board will " "not work without firmware loaded!\n"); return -1; @@ -686,12 +510,19 @@ DB* DVD | MPEG2 | 720x576PAL | CBR | *DB: "DirectBurn" */ -static struct blackbird_dnr default_dnr_params = { - .mode = BLACKBIRD_DNR_BITS_MANUAL, - .type = BLACKBIRD_MEDIAN_FILTER_DISABLED, - .spatial = 0, - .temporal = 0 -}; +static void blackbird_codec_settings(struct cx8802_dev *dev) +{ + /* assign frame size */ + blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, + dev->height, dev->width); + + dev->params.width = dev->width; + dev->params.height = dev->height; + dev->params.is_50hz = (dev->core->tvnorm->id & V4L2_STD_625_50) != 0; + + cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params); +} + static struct v4l2_mpeg_compression default_mpeg_params = { .st_type = V4L2_MPEG_PS_2, .st_bitrate = { @@ -712,7 +543,7 @@ static struct v4l2_mpeg_compression defa .target = 224, .max = 224 }, - .au_sample_rate = 44100, + .au_sample_rate = 48000, .au_pesid = 0, .vi_type = V4L2_MPEG_VI_2, .vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3, @@ -723,524 +554,13 @@ static struct v4l2_mpeg_compression defa .max = 6000 }, .vi_frame_rate = 25, - .vi_frames_per_gop = 15, + .vi_frames_per_gop = 12, .vi_bframes_count = 2, .vi_pesid = 0, - .closed_gops = 0, + .closed_gops = 1, .pulldown = 0 }; -static enum blackbird_stream_type mpeg_stream_types[] = { - [V4L2_MPEG_SS_1] = BLACKBIRD_STREAM_MPEG1, - [V4L2_MPEG_PS_2] = BLACKBIRD_STREAM_PROGRAM, - [V4L2_MPEG_TS_2] = BLACKBIRD_STREAM_TRANSPORT, - [V4L2_MPEG_PS_DVD] = BLACKBIRD_STREAM_DVD, -}; -static enum blackbird_aspect_ratio mpeg_stream_ratios[] = { - [V4L2_MPEG_ASPECT_SQUARE] = BLACKBIRD_ASPECT_RATIO_1_1_SQUARE, - [V4L2_MPEG_ASPECT_4_3] = BLACKBIRD_ASPECT_RATIO_4_3, - [V4L2_MPEG_ASPECT_16_9] = BLACKBIRD_ASPECT_RATIO_16_9, - [V4L2_MPEG_ASPECT_1_221] = BLACKBIRD_ASPECT_RATIO_221_100, -}; -static enum blackbird_video_bitrate_type mpeg_video_bitrates[] = { - [V4L2_BITRATE_NONE] = BLACKBIRD_VIDEO_CBR, - [V4L2_BITRATE_CBR] = BLACKBIRD_VIDEO_CBR, - [V4L2_BITRATE_VBR] = BLACKBIRD_VIDEO_VBR, -}; -/* find the best layer I/II bitrate to fit a given numeric value */ -struct bitrate_bits { - u32 bits; /* layer bits for the best fit */ - u32 rate; /* actual numeric value for the layer best fit */ -}; -struct bitrate_approximation { - u32 target; /* numeric value of the rate we want */ - struct bitrate_bits layer[2]; -}; -static struct bitrate_approximation mpeg_audio_bitrates[] = { - /* target layer[0].bits layer[0].rate layer[1].bits layer[1].rate */ - { 0, { { 0, 0, }, { 0, 0, }, }, }, - { 32, { { BLACKBIRD_AUDIO_BITS_LAYER_1_32 , 32, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_32 , 32, }, }, }, - { 48, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_48 , 48, }, }, }, - { 56, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_56 , 56, }, }, }, - { 64, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 , 64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_64 , 64, }, }, }, - { 80, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 , 96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_80 , 80, }, }, }, - { 96, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 , 96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_96 , 96, }, }, }, - { 112, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_112, 112, }, }, }, - { 128, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_128, 128, }, }, }, - { 160, { { BLACKBIRD_AUDIO_BITS_LAYER_1_160, 160, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_160, 160, }, }, }, - { 192, { { BLACKBIRD_AUDIO_BITS_LAYER_1_192, 192, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_192, 192, }, }, }, - { 224, { { BLACKBIRD_AUDIO_BITS_LAYER_1_224, 224, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_224, 224, }, }, }, - { 256, { { BLACKBIRD_AUDIO_BITS_LAYER_1_256, 256, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_256, 256, }, }, }, - { 288, { { BLACKBIRD_AUDIO_BITS_LAYER_1_288, 288, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, }, - { 320, { { BLACKBIRD_AUDIO_BITS_LAYER_1_320, 320, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, }, - { 352, { { BLACKBIRD_AUDIO_BITS_LAYER_1_352, 352, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, - { 384, { { BLACKBIRD_AUDIO_BITS_LAYER_1_384, 384, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, - { 416, { { BLACKBIRD_AUDIO_BITS_LAYER_1_416, 416, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, - { 448, { { BLACKBIRD_AUDIO_BITS_LAYER_1_448, 448, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, }, -}; -static const int BITRATES_SIZE = ARRAY_SIZE(mpeg_audio_bitrates); - -static void blackbird_set_default_params(struct cx8802_dev *dev) -{ - struct v4l2_mpeg_compression *params = &dev->params; - u32 au_params; - - /* assign stream type */ - if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) ) - params->st_type = V4L2_MPEG_PS_2; - if( params->st_type == V4L2_MPEG_SS_1 ) - params->vi_type = V4L2_MPEG_VI_1; - else - params->vi_type = V4L2_MPEG_VI_2; - blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]); - - /* assign framerate */ - if( params->vi_frame_rate <= 25 ) - { - params->vi_frame_rate = 25; - blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25); - } - else - { - params->vi_frame_rate = 30; - blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30); - } - - /* assign aspect ratio */ - if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) ) - params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3; - blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]); - - /* assign gop properties */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1); - - /* assign gop closure */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops); - - /* assign 3 2 pulldown */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown); - - /* make sure the params are within bounds */ - if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) - params->vi_bitrate.mode = V4L2_BITRATE_NONE; - if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) - params->vi_bitrate.mode = V4L2_BITRATE_NONE; - if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) - params->au_bitrate.mode = V4L2_BITRATE_NONE; - - /* assign audio properties */ - /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ - au_params = BLACKBIRD_AUDIO_BITS_STEREO | - /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */ - BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE | - BLACKBIRD_AUDIO_BITS_CRC_OFF | - BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF | - BLACKBIRD_AUDIO_BITS_COPY | - 0; - if( params->au_sample_rate <= 32000 ) - { - params->au_sample_rate = 32000; - au_params |= BLACKBIRD_AUDIO_BITS_32000HZ; - } - else if( params->au_sample_rate <= 44100 ) - { - params->au_sample_rate = 44100; - au_params |= BLACKBIRD_AUDIO_BITS_44100HZ; - } - else - { - params->au_sample_rate = 48000; - au_params |= BLACKBIRD_AUDIO_BITS_48000HZ; - } - if( params->au_type == V4L2_MPEG_AU_2_I ) - { - au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1; - } - else - { - /* TODO: try to handle the other formats more gracefully */ - params->au_type = V4L2_MPEG_AU_2_II; - au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2; - } - if( params->au_bitrate.mode ) - { - int layer; - - if( params->au_bitrate.mode == V4L2_BITRATE_CBR ) - params->au_bitrate.max = params->vi_bitrate.target; - else - params->au_bitrate.target = params->vi_bitrate.max; - - layer = params->au_type; - if( params->au_bitrate.target == 0 ) - { - /* TODO: use the minimum possible bitrate instead of 0 ? */ - au_params |= 0; - } - else if( params->au_bitrate.target >= - mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) - { - /* clamp the bitrate to the max supported by the standard */ - params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; - params->au_bitrate.max = params->au_bitrate.target; - au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits; - } - else - { - /* round up to the nearest supported bitrate */ - int i; - for(i = 1; i < BITRATES_SIZE; i++) - { - if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate && - params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate ) - { - params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate; - params->au_bitrate.max = params->au_bitrate.target; - au_params |= mpeg_audio_bitrates[i].layer[layer].bits; - break; - } - } - } - } - else - { - /* TODO: ??? */ - params->au_bitrate.target = params->au_bitrate.max = 0; - au_params |= 0; - } - blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, au_params ); - - /* assign bitrates */ - if( params->vi_bitrate.mode ) - { - /* bitrate is set, let's figure out the cbr/vbr mess */ - if( params->vi_bitrate.max < params->vi_bitrate.target ) - { - if( params->vi_bitrate.mode == V4L2_BITRATE_CBR ) - params->vi_bitrate.max = params->vi_bitrate.target; - else - params->vi_bitrate.target = params->vi_bitrate.max; - } - } - else - { - if( params->st_bitrate.max < params->st_bitrate.target ) - { - if( params->st_bitrate.mode == V4L2_BITRATE_VBR ) - params->st_bitrate.target = params->st_bitrate.max; - else - params->st_bitrate.max = params->st_bitrate.target; - } - /* calculate vi_bitrate = st_bitrate - au_bitrate */ - params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max; - params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target; - } - blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0, - mpeg_video_bitrates[params->vi_bitrate.mode], - params->vi_bitrate.target * 1000, /* kbps -> bps */ - params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */ - BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */ - - /* TODO: implement the stream ID stuff: - ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, - ps_size, au_pesid, vi_pesid - */ -} -#define CHECK_PARAM( name ) ( dev->params.name != params->name ) -#define IF_PARAM( name ) if( CHECK_PARAM( name ) ) -#define UPDATE_PARAM( name ) dev->params.name = params->name -void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression *params) -{ - u32 au_params; - - /* assign stream type */ - if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) ) - params->st_type = V4L2_MPEG_PS_2; - if( params->st_type == V4L2_MPEG_SS_1 ) - params->vi_type = V4L2_MPEG_VI_1; - else - params->vi_type = V4L2_MPEG_VI_2; - if( CHECK_PARAM( st_type ) || CHECK_PARAM( vi_type ) ) - { - UPDATE_PARAM( st_type ); - UPDATE_PARAM( vi_type ); - blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]); - } - - /* assign framerate */ - if( params->vi_frame_rate <= 25 ) - params->vi_frame_rate = 25; - else - params->vi_frame_rate = 30; - IF_PARAM( vi_frame_rate ) - { - UPDATE_PARAM( vi_frame_rate ); - if( params->vi_frame_rate == 25 ) - blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25); - else - blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30); - } - - /* assign aspect ratio */ - if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) ) - params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3; - IF_PARAM( vi_aspect_ratio ) - { - UPDATE_PARAM( vi_aspect_ratio ); - blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]); - } - - /* assign gop properties */ - if( CHECK_PARAM( vi_frames_per_gop ) || CHECK_PARAM( vi_bframes_count ) ) - { - UPDATE_PARAM( vi_frames_per_gop ); - UPDATE_PARAM( vi_bframes_count ); - blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1); - } - - /* assign gop closure */ - IF_PARAM( closed_gops ) - { - UPDATE_PARAM( closed_gops ); - blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops); - } - - /* assign 3 2 pulldown */ - IF_PARAM( pulldown ) - { - UPDATE_PARAM( pulldown ); - blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown); - } - - /* make sure the params are within bounds */ - if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) - params->vi_bitrate.mode = V4L2_BITRATE_NONE; - if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) - params->vi_bitrate.mode = V4L2_BITRATE_NONE; - if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) ) - params->au_bitrate.mode = V4L2_BITRATE_NONE; - - /* assign audio properties */ - /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ - au_params = BLACKBIRD_AUDIO_BITS_STEREO | - /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */ - BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE | - BLACKBIRD_AUDIO_BITS_CRC_OFF | - BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF | - BLACKBIRD_AUDIO_BITS_COPY | - 0; - if( params->au_sample_rate < 32000 ) - { - params->au_sample_rate = 32000; - au_params |= BLACKBIRD_AUDIO_BITS_32000HZ; - } - else if( params->au_sample_rate < 44100 ) - { - params->au_sample_rate = 44100; - au_params |= BLACKBIRD_AUDIO_BITS_44100HZ; - } - else - { - params->au_sample_rate = 48000; - au_params |= BLACKBIRD_AUDIO_BITS_48000HZ; - } - if( params->au_type == V4L2_MPEG_AU_2_I ) - { - au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1; - } - else - { - /* TODO: try to handle the other formats more gracefully */ - params->au_type = V4L2_MPEG_AU_2_II; - au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2; - } - if( params->au_bitrate.mode ) - { - int layer; - - if( params->au_bitrate.mode == V4L2_BITRATE_CBR ) - params->au_bitrate.max = params->vi_bitrate.target; - else - params->au_bitrate.target = params->vi_bitrate.max; - - layer = params->au_type; - if( params->au_bitrate.target == 0 ) - { - /* TODO: use the minimum possible bitrate instead of 0 ? */ - au_params |= 0; - } - else if( params->au_bitrate.target >= - mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) - { - /* clamp the bitrate to the max supported by the standard */ - params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; - params->au_bitrate.max = params->au_bitrate.target; - au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits; - } - else - { - /* round up to the nearest supported bitrate */ - int i; - for(i = 1; i < BITRATES_SIZE; i++) - { - if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate && - params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate ) - { - params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate; - params->au_bitrate.max = params->au_bitrate.target; - au_params |= mpeg_audio_bitrates[i].layer[layer].bits; - break; - } - } - } - } - else - { - /* TODO: ??? */ - params->au_bitrate.target = params->au_bitrate.max = 0; - au_params |= 0; - } - if( CHECK_PARAM( au_type ) || CHECK_PARAM( au_sample_rate ) - || CHECK_PARAM( au_bitrate.mode ) || CHECK_PARAM( au_bitrate.max ) - || CHECK_PARAM( au_bitrate.target ) - ) - { - UPDATE_PARAM( au_type ); - UPDATE_PARAM( au_sample_rate ); - UPDATE_PARAM( au_bitrate ); - blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, au_params ); - } - - /* assign bitrates */ - if( params->vi_bitrate.mode ) - { - /* bitrate is set, let's figure out the cbr/vbr mess */ - if( params->vi_bitrate.max < params->vi_bitrate.target ) - { - if( params->vi_bitrate.mode == V4L2_BITRATE_CBR ) - params->vi_bitrate.max = params->vi_bitrate.target; - else - params->vi_bitrate.target = params->vi_bitrate.max; - } - } - else - { - if( params->st_bitrate.max < params->st_bitrate.target ) - { - if( params->st_bitrate.mode == V4L2_BITRATE_VBR ) - params->st_bitrate.target = params->st_bitrate.max; - else - params->st_bitrate.max = params->st_bitrate.target; - } - /* calculate vi_bitrate = st_bitrate - au_bitrate */ - params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max; - params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target; - } - UPDATE_PARAM( st_bitrate ); - if( CHECK_PARAM( vi_bitrate.mode ) || CHECK_PARAM( vi_bitrate.max ) - || CHECK_PARAM( vi_bitrate.target ) - ) - { - UPDATE_PARAM( vi_bitrate ); - blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0, - mpeg_video_bitrates[params->vi_bitrate.mode], - params->vi_bitrate.target * 1000, /* kbps -> bps */ - params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */ - BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */ - } - - /* TODO: implement the stream ID stuff: - ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, - ps_size, au_pesid, vi_pesid - */ - UPDATE_PARAM( ts_pid_pmt ); - UPDATE_PARAM( ts_pid_audio ); - UPDATE_PARAM( ts_pid_video ); - UPDATE_PARAM( ts_pid_pcr ); - UPDATE_PARAM( ps_size ); - UPDATE_PARAM( au_pesid ); - UPDATE_PARAM( vi_pesid ); -} - -static void blackbird_set_default_dnr_params(struct cx8802_dev *dev) -{ - /* assign dnr filter mode */ - if( dev->dnr_params.mode > BLACKBIRD_DNR_BITS_AUTO ) - dev->dnr_params.mode = BLACKBIRD_DNR_BITS_MANUAL; - if( dev->dnr_params.type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL ) - dev->dnr_params.type = BLACKBIRD_MEDIAN_FILTER_DISABLED; - blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0, - dev->dnr_params.mode, - dev->dnr_params.type - ); - - /* assign dnr filter props*/ - if( dev->dnr_params.spatial > 15 ) - dev->dnr_params.spatial = 15; - if( dev->dnr_params.temporal > 31 ) - dev->dnr_params.temporal = 31; - blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, - dev->dnr_params.spatial, - dev->dnr_params.temporal - ); -} -#define CHECK_DNR_PARAM( name ) ( dev->dnr_params.name != dnr_params->name ) -#define UPDATE_DNR_PARAM( name ) dev->dnr_params.name = dnr_params->name -void blackbird_set_dnr_params(struct cx8802_dev *dev, struct blackbird_dnr* dnr_params) -{ - /* assign dnr filter mode */ - /* clamp values */ - if( dnr_params->mode > BLACKBIRD_DNR_BITS_AUTO ) - dnr_params->mode = BLACKBIRD_DNR_BITS_MANUAL; - if( dnr_params->type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL ) - dnr_params->type = BLACKBIRD_MEDIAN_FILTER_DISABLED; - /* check if the params actually changed */ - if( CHECK_DNR_PARAM( mode ) || CHECK_DNR_PARAM( type ) ) - { - UPDATE_DNR_PARAM( mode ); - UPDATE_DNR_PARAM( type ); - blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0, dnr_params->mode, dnr_params->type); - } - - /* assign dnr filter props*/ - if( dnr_params->spatial > 15 ) - dnr_params->spatial = 15; - if( dnr_params->temporal > 31 ) - dnr_params->temporal = 31; - if( CHECK_DNR_PARAM( spatial ) || CHECK_DNR_PARAM( temporal ) ) - { - UPDATE_DNR_PARAM( spatial ); - UPDATE_DNR_PARAM( temporal ); - blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, dnr_params->spatial, dnr_params->temporal); - } -} - -static void blackbird_codec_settings(struct cx8802_dev *dev) -{ - - /* assign output port */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */ - - /* assign frame size */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_RESOLUTION, 2, 0, - dev->height, dev->width); - - /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MEDIAN, 4, 0, 0, 255, 0, 255); - - /* assign spatial filter type: luma_t: horiz_only, chroma_t: horiz_only */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_SPATIAL_FILTER, 2, 0, - BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ, - BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ - ); - - /* assign frame drop rate */ - /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); */ - - blackbird_set_default_params(dev); - blackbird_set_default_dnr_params(dev); -} - static int blackbird_initialize_codec(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; @@ -1248,7 +568,7 @@ static int blackbird_initialize_codec(st int retval; dprintk(1,"Initialize codec\n"); - retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */ + retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ if (retval < 0) { /* ping was not successful, reset and upload firmware */ cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ @@ -1263,13 +583,13 @@ static int blackbird_initialize_codec(st if (dev->mailbox < 0) return -1; - retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */ + retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ if (retval < 0) { dprintk(0, "ERROR: Firmware ping failed!\n"); return -1; } - retval = blackbird_api_cmd(dev, BLACKBIRD_API_GET_VERSION, 0, 1, &version); + retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version); if (retval < 0) { dprintk(0, "ERROR: Firmware get encoder version failed!\n"); return -1; @@ -1289,35 +609,35 @@ static int blackbird_initialize_codec(st /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef); blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0); blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_CAPTURE_LINES, 2, 0, + blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, BLACKBIRD_FIELD1_SAA7115, - BLACKBIRD_FIELD1_SAA7115 + BLACKBIRD_FIELD2_SAA7115 ); /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */ - blackbird_api_cmd(dev, BLACKBIRD_API_SET_CUSTOM_DATA, 12, 0, + blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); /* initialize the video input */ - blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0); + blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); msleep(1); - blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE); + blackbird_api_cmd(dev, CX2341X_ENC_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE); msleep(1); - blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE); + blackbird_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE); msleep(1); /* start capturing to the host interface */ - /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); */ - blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, + /* blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, 0, 0x13); */ + blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_BITS_NONE ); msleep(10); - blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0); + blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0); return 0; } @@ -1485,27 +805,61 @@ static int mpeg_do_ioctl(struct inode *i { struct v4l2_mpeg_compression *f = arg; - memcpy(f,&dev->params,sizeof(*f)); + printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. " + "Replace with VIDIOC_G_EXT_CTRLS!"); + memcpy(f,&default_mpeg_params,sizeof(*f)); return 0; } case VIDIOC_S_MPEGCOMP: + printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. " + "Replace with VIDIOC_S_EXT_CTRLS!"); + return 0; + case VIDIOC_G_EXT_CTRLS: { - struct v4l2_mpeg_compression *f = arg; + struct v4l2_ext_controls *f = arg; + + if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + return cx2341x_ext_ctrls(&dev->params, f, cmd); + } + case VIDIOC_S_EXT_CTRLS: + case VIDIOC_TRY_EXT_CTRLS: + { + struct v4l2_ext_controls *f = arg; + struct cx2341x_mpeg_params p; + int err; - blackbird_set_params(dev, f); + if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + p = dev->params; + err = cx2341x_ext_ctrls(&p, f, cmd); + if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) { + err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p); + dev->params = p; + } + return err; + } + case VIDIOC_S_FREQUENCY: + { + blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, + BLACKBIRD_END_NOW, + BLACKBIRD_MPEG_CAPTURE, + BLACKBIRD_RAW_BITS_NONE); + + cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); + + blackbird_initialize_codec(dev); + cx88_set_scale(dev->core, dev->width, dev->height, + fh->mpegq.field); return 0; } default: - return cx88_do_ioctl( inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook ); + return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); } return 0; } -int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg); -unsigned int (*cx88_ioctl_translator)(unsigned int cmd); - static unsigned int mpeg_translate_ioctl(unsigned int cmd) { return cmd; @@ -1514,8 +868,8 @@ static unsigned int mpeg_translate_ioctl static int mpeg_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - cmd = cx88_ioctl_translator( cmd ); - return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook); + cmd = mpeg_translate_ioctl( cmd ); + return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl); } static int mpeg_open(struct inode *inode, struct file *file) @@ -1562,13 +916,14 @@ static int mpeg_release(struct inode *in { struct cx8802_fh *fh = file->private_data; - /* blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ - blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0, + /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ + blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_BITS_NONE ); + cx8802_cancel_buffers(fh->dev); /* stop mpeg capture */ if (fh->mpegq.streaming) videobuf_streamoff(&fh->mpegq); @@ -1683,19 +1038,13 @@ static int __devinit blackbird_probe(str dev->core = core; dev->width = 720; dev->height = 576; - memcpy(&dev->params,&default_mpeg_params,sizeof(default_mpeg_params)); - memcpy(&dev->dnr_params,&default_dnr_params,sizeof(default_dnr_params)); - - if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) { - - if (core->tuner_formats & V4L2_STD_525_60) { - dev->height = 480; - dev->params.vi_frame_rate = 30; - } else { - dev->height = 576; - dev->params.vi_frame_rate = 25; - } + cx2341x_fill_defaults(&dev->params); + dev->params.port = CX2341X_PORT_STREAMING; + if (core->tvnorm->id & V4L2_STD_525_60) { + dev->height = 480; + } else { + dev->height = 576; } err = cx8802_init_common(dev); @@ -1766,8 +1115,6 @@ #ifdef SNAPSHOT printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); #endif - cx88_ioctl_hook = mpeg_do_ioctl; - cx88_ioctl_translator = mpeg_translate_ioctl; return pci_register_driver(&blackbird_pci_driver); } @@ -1779,11 +1126,6 @@ static void blackbird_fini(void) module_init(blackbird_init); module_exit(blackbird_fini); -EXPORT_SYMBOL(cx88_ioctl_hook); -EXPORT_SYMBOL(cx88_ioctl_translator); -EXPORT_SYMBOL(blackbird_set_params); -EXPORT_SYMBOL(blackbird_set_dnr_params); - /* ----------------------------------------------------------- */ /* * Local variables: diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index f80154b..f9d68f2 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -114,7 +114,7 @@ struct cx88_board cx88_boards[] = { .radio = { .type = CX88_RADIO, .gpio0 = 0xff10, - }, + }, }, [CX88_BOARD_ATI_WONDER_PRO] = { .name = "ATI TV Wonder Pro", @@ -267,7 +267,7 @@ struct cx88_board cx88_boards[] = { .gpio1 = 0x00007004, .gpio2 = 0x0035d700, .gpio3 = 0x02000000, - }, + }, }, [CX88_BOARD_LEADTEK_PVR2000] = { // gpio values for PAL version from regspy by DScaler @@ -413,7 +413,7 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x000027df, - },{ + },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x000027df, @@ -536,7 +536,7 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x000027df, - },{ + },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x000027df, @@ -759,7 +759,7 @@ struct cx88_board cx88_boards[] = { }, [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = { .name = "DViCO FusionHDTV 5 Gold", - .tuner_type = TUNER_LG_TDVS_H062F, + .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H062F */ .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -1050,11 +1050,7 @@ struct cx88_board cx88_boards[] = { .dvb = 1, }, [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { - /* FIXME: Standard video using the cx88 broadcast decoder is - * working, but blackbird isn't working yet, audio is only - * working correctly for television mode. S-Video and Composite - * are working for video-only, so I have them disabled for now. - */ + /* FIXME: Audio not working for s-video / composite inputs. */ .name = "KWorld HardwareMpegTV XPert", .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, @@ -1065,12 +1061,21 @@ struct cx88_board cx88_boards[] = { .vmux = 0, .gpio0 = 0x3de2, .gpio2 = 0x00ff, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x3de6, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x3de6, }}, .radio = { .type = CX88_RADIO, .gpio0 = 0x3de6, .gpio2 = 0x00ff, }, + .blackbird = 1, }, [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = { .name = "DViCO FusionHDTV DVB-T Hybrid", @@ -1093,7 +1098,102 @@ struct cx88_board cx88_boards[] = { }}, .dvb = 1, }, - + [CX88_BOARD_PCHDTV_HD5500] = { + .name = "pcHDTV HD5500 HDTV", + .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x87fd, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x87f9, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x87f9, + }}, + .dvb = 1, + }, + [CX88_BOARD_KWORLD_MCE200_DELUXE] = { + /* FIXME: tested TV input only, disabled composite, + svideo and radio until they can be tested also. */ + .name = "Kworld MCE 200 Deluxe", + .tuner_type = TUNER_TENA_9533_DI, + .radio_type = UNSET, + .tda9887_conf = TDA9887_PRESENT, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0000BDE6 + }}, + .blackbird = 1, + }, + [CX88_BOARD_PIXELVIEW_PLAYTV_P7000] = { + /* FIXME: SVideo, Composite and FM inputs are untested */ + .name = "PixelView PlayTV P7000", + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE | + TDA9887_PORT2_ACTIVE, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x5da6, + }}, + .blackbird = 1, + }, + [CX88_BOARD_NPGTECH_REALTV_TOP10FM] = { + .name = "NPG Tech Real TV FM Top 10", + .tuner_type = TUNER_TNF_5335MF, /* Actually a TNF9535 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0788, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x078b, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x078b, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x074a, + }, + }, + [CX88_BOARD_WINFAST_DTV2000H] = { + /* video inputs and radio still in testing */ + .name = "WinFast DTV2000 H", + .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00017304, + .gpio1 = 0x00008203, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + }}, + .dvb = 1, + }, }; const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); @@ -1311,6 +1411,34 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x18ac, .subdevice = 0xdb44, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID, + },{ + .subvendor = 0x7063, + .subdevice = 0x5500, + .card = CX88_BOARD_PCHDTV_HD5500, + },{ + .subvendor = 0x17de, + .subdevice = 0x0841, + .card = CX88_BOARD_KWORLD_MCE200_DELUXE, + },{ + .subvendor = 0x1822, + .subdevice = 0x0019, + .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO, + },{ + .subvendor = 0x1554, + .subdevice = 0x4813, + .card = CX88_BOARD_PIXELVIEW_PLAYTV_P7000, + },{ + .subvendor = 0x14f1, + .subdevice = 0x0842, + .card = CX88_BOARD_NPGTECH_REALTV_TOP10FM, + },{ + .subvendor = 0x107d, + .subdevice = 0x665e, + .card = CX88_BOARD_WINFAST_DTV2000H, + },{ + .subvendor = 0x18ac, + .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */ + .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q, }, }; const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); @@ -1572,11 +1700,6 @@ void cx88_card_setup(struct cx88_core *c /* ------------------------------------------------------------------ */ EXPORT_SYMBOL(cx88_boards); -EXPORT_SYMBOL(cx88_bcount); -EXPORT_SYMBOL(cx88_subids); -EXPORT_SYMBOL(cx88_idcount); -EXPORT_SYMBOL(cx88_card_list); -EXPORT_SYMBOL(cx88_card_setup); /* * Local variables: diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index e1092d5..26f4c0f 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -677,7 +677,7 @@ static unsigned int inline norm_htotal(s static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm) { - return (norm->id & V4L2_STD_625_50) ? 511 : 288; + return (norm->id & V4L2_STD_625_50) ? 511 : 400; } int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height, @@ -932,9 +932,9 @@ int cx88_set_tvnorm(struct cx88_core *co htotal, cx_read(MO_HTOTAL), (u32)tmp64); cx_write(MO_HTOTAL, htotal); - // vbi stuff - cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */ - norm_vbipack(norm))); + // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes + // the effective vbi offset ~244 samples, the same as the Bt8x8 + cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm)); // this is needed as well to set all tvnorm parameter cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED); @@ -1181,8 +1181,6 @@ EXPORT_SYMBOL(cx88_set_scale); EXPORT_SYMBOL(cx88_vdev_init); EXPORT_SYMBOL(cx88_core_get); EXPORT_SYMBOL(cx88_core_put); -EXPORT_SYMBOL(cx88_start_audio_dma); -EXPORT_SYMBOL(cx88_stop_audio_dma); /* * Local variables: diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 3619a44..dce1fed 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -51,6 +51,7 @@ # include "or51132.h" #endif #ifdef HAVE_LGDT330X # include "lgdt330x.h" +# include "lg_h06xf.h" #endif #ifdef HAVE_NXT200X # include "nxt200x.h" @@ -58,6 +59,7 @@ #endif #ifdef HAVE_CX24123 # include "cx24123.h" #endif +#include "isl6421.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe "); @@ -113,21 +115,6 @@ static struct videobuf_queue_ops dvb_qop /* ------------------------------------------------------------------ */ -#if defined(HAVE_MT352) || defined(HAVE_ZL10353) -static int zarlink_pll_set(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params, - u8 *pllbuf) -{ - struct cx8802_dev *dev = fe->dvb->priv; - - pllbuf[0] = dev->core->pll_addr << 1; - dvb_pll_configure(dev->core->pll_desc, pllbuf + 1, - params->frequency, - params->u.ofdm.bandwidth); - return 0; -} -#endif - #ifdef HAVE_MT352 static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) { @@ -196,19 +183,16 @@ static int dntv_live_dvbt_demod_init(str static struct mt352_config dvico_fusionhdtv = { .demod_address = 0x0F, .demod_init = dvico_fusionhdtv_demod_init, - .pll_set = zarlink_pll_set, }; static struct mt352_config dntv_live_dvbt_config = { .demod_address = 0x0f, .demod_init = dntv_live_dvbt_demod_init, - .pll_set = zarlink_pll_set, }; static struct mt352_config dvico_fusionhdtv_dual = { .demod_address = 0x0F, .demod_init = dvico_dual_demod_init, - .pll_set = zarlink_pll_set, }; #ifdef HAVE_VP3054_I2C @@ -246,6 +230,8 @@ static int philips_fmd1216_pll_init(stru .buf = fmd1216_init, .len = sizeof(fmd1216_init) }; int err; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { if (err < 0) return err; @@ -256,14 +242,14 @@ static int philips_fmd1216_pll_init(stru return 0; } -static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params, - u8* pllbuf) +static int dntv_live_dvbt_pro_tuner_set_params(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) { struct cx8802_dev *dev= fe->dvb->priv; + u8 buf[4]; struct i2c_msg msg = { .addr = dev->core->pll_addr, .flags = 0, - .buf = pllbuf+1, .len = 4 }; + .buf = buf, .len = 4 }; int err; /* Switch PLL to DVB mode */ @@ -272,14 +258,16 @@ static int dntv_live_dvbt_pro_pll_set(st return err; /* Tune PLL */ - pllbuf[0] = dev->core->pll_addr << 1; - dvb_pll_configure(dev->core->pll_desc, pllbuf+1, + dvb_pll_configure(dev->core->pll_desc, buf, params->frequency, params->u.ofdm.bandwidth); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "cx88-dvb: %s error " "(addr %02x <- %02x, err = %i)\n", - __FUNCTION__, pllbuf[0], pllbuf[1], err); + __FUNCTION__, dev->core->pll_addr, buf[0], err); if (err < 0) return err; else @@ -293,27 +281,27 @@ static struct mt352_config dntv_live_dvb .demod_address = 0x0f, .no_tuner = 1, .demod_init = dntv_live_dvbt_pro_demod_init, - .pll_set = dntv_live_dvbt_pro_pll_set, }; #endif #endif #ifdef HAVE_ZL10353 -static int dvico_hybrid_tune_pll(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params, - u8 *pllbuf) +static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) { + u8 pllbuf[4]; struct cx8802_dev *dev= fe->dvb->priv; struct i2c_msg msg = { .addr = dev->core->pll_addr, .flags = 0, - .buf = pllbuf + 1, .len = 4 }; + .buf = pllbuf, .len = 4 }; int err; - pllbuf[0] = dev->core->pll_addr << 1; - dvb_pll_configure(dev->core->pll_desc, pllbuf + 1, + dvb_pll_configure(dev->core->pll_desc, pllbuf, params->frequency, params->u.ofdm.bandwidth); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) { printk(KERN_WARNING "cx88-dvb: %s error " "(addr %02x <- %02x, err = %i)\n", @@ -329,12 +317,11 @@ static int dvico_hybrid_tune_pll(struct static struct zl10353_config dvico_fusionhdtv_hybrid = { .demod_address = 0x0F, - .pll_set = dvico_hybrid_tune_pll, + .no_tuner = 1, }; static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { .demod_address = 0x0F, - .pll_set = zarlink_pll_set, }; #endif @@ -342,21 +329,15 @@ #ifdef HAVE_CX22702 static struct cx22702_config connexant_refboard_config = { .demod_address = 0x43, .output_mode = CX22702_SERIAL_OUTPUT, - .pll_address = 0x60, - .pll_desc = &dvb_pll_thomson_dtt7579, }; static struct cx22702_config hauppauge_novat_config = { .demod_address = 0x43, .output_mode = CX22702_SERIAL_OUTPUT, - .pll_address = 0x61, - .pll_desc = &dvb_pll_thomson_dtt759x, }; static struct cx22702_config hauppauge_hvr1100_config = { .demod_address = 0x63, .output_mode = CX22702_SERIAL_OUTPUT, - .pll_address = 0x61, - .pll_desc = &dvb_pll_fmd1216me, }; #endif @@ -371,15 +352,13 @@ static int or51132_set_ts_param(struct d static struct or51132_config pchdtv_hd3000 = { .demod_address = 0x15, - .pll_address = 0x61, - .pll_desc = &dvb_pll_thomson_dtt761x, .set_ts_params = or51132_set_ts_param, }; #endif #ifdef HAVE_LGDT330X -static int lgdt330x_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params) +static int lgdt3302_tuner_set_params(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) { /* FIXME make this routine use the tuner-simple code. * It could probably be shared with a number of ATSC @@ -392,12 +371,12 @@ static int lgdt330x_pll_set(struct dvb_f { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 }; int err; - /* Put the analog decoder in standby to keep it quiet */ - cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); - dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) { printk(KERN_WARNING "cx88-dvb: %s error " "(addr %02x <- %02x, err = %i)\n", @@ -407,16 +386,21 @@ static int lgdt330x_pll_set(struct dvb_f else return -EREMOTEIO; } - if (core->tuner_type == TUNER_LG_TDVS_H062F) { - /* Set the Auxiliary Byte. */ - buf[2] &= ~0x20; - buf[2] |= 0x18; - buf[3] = 0x50; - i2c_transfer(&core->i2c_adap, &msg, 1); - } return 0; } +static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) +{ + struct cx8802_dev *dev= fe->dvb->priv; + struct cx88_core *core = dev->core; + + /* Put the analog decoder in standby to keep it quiet */ + cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); + + return lg_h06xf_pll_set(fe, &core->i2c_adap, params); +} + static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) { struct cx8802_dev *dev= fe->dvb->priv; @@ -444,7 +428,6 @@ static struct lgdt330x_config fusionhdtv .demod_address = 0x0e, .demod_chip = LGDT3302, .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ - .pll_set = lgdt330x_pll_set, .set_ts_params = lgdt330x_set_ts_param, }; @@ -452,7 +435,13 @@ static struct lgdt330x_config fusionhdtv .demod_address = 0x0e, .demod_chip = LGDT3303, .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ - .pll_set = lgdt330x_pll_set, + .set_ts_params = lgdt330x_set_ts_param, +}; + +static struct lgdt330x_config pchdtv_hd5500 = { + .demod_address = 0x59, + .demod_chip = LGDT3303, + .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ .set_ts_params = lgdt330x_set_ts_param, }; #endif @@ -477,8 +466,6 @@ static int nxt200x_set_pll_input(u8* buf static struct nxt200x_config ati_hdtvwonder = { .demod_address = 0x0a, - .pll_address = 0x61, - .pll_desc = &dvb_pll_tuv1236d, .set_pll_input = nxt200x_set_pll_input, .set_ts_params = nxt200x_set_ts_param, }; @@ -493,28 +480,30 @@ static int cx24123_set_ts_param(struct d return 0; } -static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on) +static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) { struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; - if (on) - cx_write(MO_GP0_IO, 0x000006f9); - else + if (voltage == SEC_VOLTAGE_OFF) { cx_write(MO_GP0_IO, 0x000006fB); + } else { + cx_write(MO_GP0_IO, 0x000006f9); + } + + if (core->prev_set_voltage) + return core->prev_set_voltage(fe, voltage); + return 0; } static struct cx24123_config hauppauge_novas_config = { .demod_address = 0x55, - .use_isl6421 = 1, .set_ts_params = cx24123_set_ts_param, }; static struct cx24123_config kworld_dvbs_100_config = { .demod_address = 0x15, - .use_isl6421 = 0, .set_ts_params = cx24123_set_ts_param, - .enable_lnb_voltage = cx24123_enable_lnb_voltage, }; #endif @@ -530,6 +519,11 @@ #ifdef HAVE_CX22702 case CX88_BOARD_HAUPPAUGE_DVB_T1: dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_pll_attach(dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_thomson_dtt759x); + } break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: case CX88_BOARD_CONEXANT_DVB_T1: @@ -537,44 +531,92 @@ #ifdef HAVE_CX22702 case CX88_BOARD_WINFAST_DTV1000: dev->dvb.frontend = cx22702_attach(&connexant_refboard_config, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_pll_attach(dev->dvb.frontend, 0x60, + &dev->core->i2c_adap, + &dvb_pll_thomson_dtt7579); + } break; + case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_pll_attach(dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_fmd1216me); + } break; #endif #if defined(HAVE_MT352) || defined(HAVE_ZL10353) case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: - dev->core->pll_addr = 0x60; - dev->core->pll_desc = &dvb_pll_thomson_dtt7579; #ifdef HAVE_MT352 dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, &dev->core->i2c_adap); - if (dev->dvb.frontend != NULL) + if (dev->dvb.frontend != NULL) { + dvb_pll_attach(dev->dvb.frontend, 0x60, + &dev->core->i2c_adap, + &dvb_pll_thomson_dtt7579); break; + } #endif #ifdef HAVE_ZL10353 /* ZL10353 replaces MT352 on later cards */ dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_pll_attach(dev->dvb.frontend, 0x60, + &dev->core->i2c_adap, + &dvb_pll_thomson_dtt7579); + } +#endif + break; + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: +#ifdef HAVE_MT352 + /* The tin box says DEE1601, but it seems to be DTT7579 + * compatible, with a slightly different MT352 AGC gain. */ + dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual, + &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_pll_attach(dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_thomson_dtt7579); + break; + } +#endif +#ifdef HAVE_ZL10353 + /* ZL10353 replaces MT352 on later cards */ + dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1, + &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_pll_attach(dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_thomson_dtt7579); + } #endif break; #endif /* HAVE_MT352 || HAVE_ZL10353 */ #ifdef HAVE_MT352 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: - dev->core->pll_addr = 0x61; - dev->core->pll_desc = &dvb_pll_lg_z201; dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_pll_attach(dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_lg_z201); + } break; case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_ADSTECH_DVB_T_PCI: - dev->core->pll_addr = 0x61; - dev->core->pll_desc = &dvb_pll_unknown_1; dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_pll_attach(dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_unknown_1); + } break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: #ifdef HAVE_VP3054_I2C @@ -582,18 +624,13 @@ #ifdef HAVE_VP3054_I2C dev->core->pll_desc = &dvb_pll_fmd1216me; dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config, &((struct vp3054_i2c_state *)dev->card_priv)->adap); + if (dev->dvb.frontend != NULL) { + dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params; + } #else printk("%s: built without vp3054 support\n", dev->core->name); #endif break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: - /* The tin box says DEE1601, but it seems to be DTT7579 - * compatible, with a slightly different MT352 AGC gain. */ - dev->core->pll_addr = 0x61; - dev->core->pll_desc = &dvb_pll_thomson_dtt7579; - dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual, - &dev->core->i2c_adap); - break; #endif #ifdef HAVE_ZL10353 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: @@ -601,12 +638,20 @@ #ifdef HAVE_ZL10353 dev->core->pll_desc = &dvb_pll_thomson_fe6600; dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params; + } break; #endif #ifdef HAVE_OR51132 case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = or51132_attach(&pchdtv_hd3000, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_pll_attach(dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_thomson_dtt761x); + } break; #endif #ifdef HAVE_LGDT330X @@ -627,6 +672,9 @@ #ifdef HAVE_LGDT330X dev->core->pll_desc = &dvb_pll_microtune_4042; dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; + } } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: @@ -643,6 +691,9 @@ #ifdef HAVE_LGDT330X dev->core->pll_desc = &dvb_pll_thomson_dtt761x; dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; + } } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: @@ -655,10 +706,28 @@ #ifdef HAVE_LGDT330X mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); - dev->core->pll_addr = 0x61; - dev->core->pll_desc = &dvb_pll_tdvs_tua6034; dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; + } + } + break; + case CX88_BOARD_PCHDTV_HD5500: + dev->ts_gen_cntrl = 0x08; + { + /* Do a hardware reset of chip before using it. */ + struct cx88_core *core = dev->core; + + cx_clear(MO_GP0_IO, 1); + mdelay(100); + cx_set(MO_GP0_IO, 1); + mdelay(200); + dev->dvb.frontend = lgdt330x_attach(&pchdtv_hd5500, + &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; + } } break; #endif @@ -666,6 +735,11 @@ #ifdef HAVE_NXT200X case CX88_BOARD_ATI_HDTVWONDER: dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder, &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + dvb_pll_attach(dev->dvb.frontend, 0x61, + &dev->core->i2c_adap, + &dvb_pll_tuv1236d); + } break; #endif #ifdef HAVE_CX24123 @@ -673,10 +747,18 @@ #ifdef HAVE_CX24123 case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config, &dev->core->i2c_adap); + if (dev->dvb.frontend) { + isl6421_attach(dev->dvb.frontend, &dev->core->i2c_adap, + 0x08, 0x00, 0x00); + } break; case CX88_BOARD_KWORLD_DVBS_100: dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config, &dev->core->i2c_adap); + if (dev->dvb.frontend) { + dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; + dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; + } break; #endif default: @@ -690,15 +772,15 @@ #endif } if (dev->core->pll_desc) { - dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min; - dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max; + dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; + dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; } /* Put the analog decoder in standby to keep it quiet */ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); /* register everything */ - return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); + return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); } /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index f720901..7066380 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -138,13 +138,13 @@ void cx88_call_i2c_clients(struct cx88_c return; if (core->dvbdev) { - if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl) - core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); + if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) + core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); i2c_clients_command(&core->i2c_adap, cmd, arg); - if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl) - core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0); + if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) + core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0); } else i2c_clients_command(&core->i2c_adap, cmd, arg); } @@ -234,7 +234,6 @@ int cx88_i2c_init(struct cx88_core *core /* ----------------------------------------------------------------------- */ EXPORT_SYMBOL(cx88_call_i2c_clients); -EXPORT_SYMBOL(cx88_i2c_init); /* * Local variables: diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 78a63b7..72b630a 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -70,14 +70,33 @@ #define ir_dprintk(fmt, arg...) if (ir_d static void cx88_ir_handle_key(struct cx88_IR *ir) { struct cx88_core *core = ir->core; - u32 gpio, data; + u32 gpio, data, auxgpio; /* read gpio value */ gpio = cx_read(ir->gpio_addr); + if (core->board == CX88_BOARD_NPGTECH_REALTV_TOP10FM) { + /* This board apparently uses a combination of 2 GPIO + to represent the keys. Additionally, the second GPIO + can be used for parity. + + Example: + + for key "5" + gpio = 0x758, auxgpio = 0xe5 or 0xf5 + for key "Power" + gpio = 0x758, auxgpio = 0xed or 0xfd + */ + + auxgpio = cx_read(MO_GP1_IO); + /* Take out the parity part */ + gpio+=(gpio & 0x7fd) + (auxgpio & 0xef); + } else + auxgpio = gpio; + if (ir->polling) { - if (ir->last_gpio == gpio) + if (ir->last_gpio == auxgpio) return; - ir->last_gpio = gpio; + ir->last_gpio = auxgpio; } /* extract data */ @@ -172,12 +191,13 @@ int cx88_ir_init(struct cx88_core *core, ir_type = IR_TYPE_RC5; ir->sampling = 1; break; + case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_WINFAST2000XP_EXPERT: ir_codes = ir_codes_winfast; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; ir->mask_keyup = 0x100; - ir->polling = 1; /* ms */ + ir->polling = 50; /* ms */ break; case CX88_BOARD_IODATA_GVBCTV7E: ir_codes = ir_codes_iodata_bctv7e; @@ -228,6 +248,12 @@ int cx88_ir_init(struct cx88_core *core, ir_type = IR_TYPE_PD; ir->sampling = 0xff00; /* address */ break; + case CX88_BOARD_NPGTECH_REALTV_TOP10FM: + ir_codes = ir_codes_npgtech; + ir->gpio_addr = MO_GP0_IO; + ir->mask_keycode = 0xfa; + ir->polling = 50; /* ms */ + break; } if (NULL == ir_codes) { diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 7d16888..a9d7795 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -54,7 +54,7 @@ static int cx8802_start_dma(struct cx880 { struct cx88_core *core = dev->core; - dprintk(0, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field); + dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field); /* setup fifo + format */ cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], @@ -76,6 +76,7 @@ static int cx8802_start_dma(struct cx880 case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: + case CX88_BOARD_PCHDTV_HD5500: cx_write(TS_SOP_STAT, 1<<13); break; case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: @@ -109,7 +110,7 @@ static int cx8802_start_dma(struct cx880 q->count = 1; /* enable irqs */ - dprintk( 0, "setting the interrupt mask\n" ); + dprintk( 1, "setting the interrupt mask\n" ); cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04); cx_set(MO_TS_INTMSK, 0x1f0011); @@ -122,7 +123,7 @@ static int cx8802_start_dma(struct cx880 static int cx8802_stop_dma(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; - dprintk( 0, "cx8802_stop_dma\n" ); + dprintk( 1, "cx8802_stop_dma\n" ); /* stop dma */ cx_clear(MO_TS_DMACNTRL, 0x11); @@ -142,10 +143,43 @@ static int cx8802_restart_queue(struct c struct cx88_buffer *buf; struct list_head *item; - dprintk( 0, "cx8802_restart_queue\n" ); + dprintk( 1, "cx8802_restart_queue\n" ); if (list_empty(&q->active)) { - dprintk( 0, "cx8802_restart_queue: queue is empty\n" ); + struct cx88_buffer *prev; + prev = NULL; + + dprintk(1, "cx8802_restart_queue: queue is empty\n" ); + + for (;;) { + if (list_empty(&q->queued)) + return 0; + buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); + if (NULL == prev) { + list_del(&buf->vb.queue); + list_add_tail(&buf->vb.queue,&q->active); + cx8802_start_dma(dev, q, buf); + buf->vb.state = STATE_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(1,"[%p/%d] restart_queue - first active\n", + buf,buf->vb.i); + + } else if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_del(&buf->vb.queue); + list_add_tail(&buf->vb.queue,&q->active); + buf->vb.state = STATE_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + dprintk(1,"[%p/%d] restart_queue - move to active\n", + buf,buf->vb.i); + } else { + return 0; + } + prev = buf; + } return 0; } @@ -204,13 +238,13 @@ void cx8802_buf_queue(struct cx8802_dev buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma); if (list_empty(&cx88q->active)) { - dprintk( 0, "queue is empty - first active\n" ); + dprintk( 1, "queue is empty - first active\n" ); list_add_tail(&buf->vb.queue,&cx88q->active); cx8802_start_dma(dev, cx88q, buf); buf->vb.state = STATE_ACTIVE; buf->count = cx88q->count++; mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(0,"[%p/%d] %s - first active\n", + dprintk(1,"[%p/%d] %s - first active\n", buf, buf->vb.i, __FUNCTION__); } else { @@ -244,7 +278,7 @@ static void do_cancel_buffers(struct cx8 } if (restart) { - dprintk(0, "restarting queue\n" ); + dprintk(1, "restarting queue\n" ); cx8802_restart_queue(dev,q); } spin_unlock_irqrestore(&dev->slock,flags); diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 641a0c5..5785c34 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -52,6 +52,7 @@ #include #include #include #include +#include #include #include "cx88.h" @@ -137,21 +138,28 @@ static void set_audio_finish(struct cx88 { u32 volume; -#ifndef USING_CX88_ALSA +#ifndef CONFIG_VIDEO_CX88_ALSA /* restart dma; This avoids buzz in NICAM and is good in others */ cx88_stop_audio_dma(core); #endif cx_write(AUD_RATE_THRES_DMD, 0x000000C0); -#ifndef USING_CX88_ALSA +#ifndef CONFIG_VIDEO_CX88_ALSA cx88_start_audio_dma(core); #endif if (cx88_boards[core->board].blackbird) { /* sets sound input from external adc */ - if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) + switch (core->board) { + case CX88_BOARD_HAUPPAUGE_ROSLYN: + case CX88_BOARD_KWORLD_MCE200_DELUXE: + case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT: + case CX88_BOARD_PIXELVIEW_PLAYTV_P7000: + case CX88_BOARD_ASUS_PVR_416: cx_clear(AUD_CTL, EN_I2SIN_ENABLE); - else + break; + default: cx_set(AUD_CTL, EN_I2SIN_ENABLE); + } cx_write(AUD_I2SINPUTCNTL, 4); cx_write(AUD_BAUDRATE, 1); @@ -718,7 +726,7 @@ static void set_audio_standard_FM(struct /* ----------------------------------------------------------- */ -int cx88_detect_nicam(struct cx88_core *core) +static int cx88_detect_nicam(struct cx88_core *core) { int i, j = 0; diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index 846faad..aa2a697 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c @@ -34,8 +34,8 @@ void cx8800_vbi_fmt(struct cx8800_dev *d if (dev->core->tvnorm->id & V4L2_STD_525_60) { /* ntsc */ f->fmt.vbi.sampling_rate = 28636363; - f->fmt.vbi.start[0] = 10 -1; - f->fmt.vbi.start[1] = 273 -1; + f->fmt.vbi.start[0] = 10; + f->fmt.vbi.start[1] = 273; } else if (dev->core->tvnorm->id & V4L2_STD_625_50) { /* pal */ diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 694d1d8..dcda529 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -494,8 +494,7 @@ static int restart_video_queue(struct cx return 0; buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); if (NULL == prev) { - list_del(&buf->vb.queue); - list_add_tail(&buf->vb.queue,&q->active); + list_move_tail(&buf->vb.queue, &q->active); start_video_dma(dev, q, buf); buf->vb.state = STATE_ACTIVE; buf->count = q->count++; @@ -506,8 +505,7 @@ static int restart_video_queue(struct cx } else if (prev->vb.width == buf->vb.width && prev->vb.height == buf->vb.height && prev->fmt == buf->fmt) { - list_del(&buf->vb.queue); - list_add_tail(&buf->vb.queue,&q->active); + list_move_tail(&buf->vb.queue, &q->active); buf->vb.state = STATE_ACTIVE; buf->count = q->count++; prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 326a25f..9a9a0fc 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -25,9 +25,11 @@ #include #include #include +#include #include #include #include +#include #include #include "btcx-risc.h" @@ -35,7 +37,7 @@ #include "cx88-reg.h" #include #include -#define CX88_VERSION_CODE KERNEL_VERSION(0,0,5) +#define CX88_VERSION_CODE KERNEL_VERSION(0,0,6) #ifndef TRUE # define TRUE (1==1) @@ -189,6 +191,11 @@ #define CX88_BOARD_KWORLD_DVB_T_CX22702 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44 #define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46 +#define CX88_BOARD_PCHDTV_HD5500 47 +#define CX88_BOARD_KWORLD_MCE200_DELUXE 48 +#define CX88_BOARD_PIXELVIEW_PLAYTV_P7000 49 +#define CX88_BOARD_NPGTECH_REALTV_TOP10FM 50 +#define CX88_BOARD_WINFAST_DTV2000H 51 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, @@ -296,6 +303,7 @@ struct cx88_core { /* config info -- dvb */ struct dvb_pll_desc *pll_desc; unsigned int pll_addr; + int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); /* state info */ struct task_struct *kthread; @@ -391,14 +399,6 @@ struct cx8802_suspend_state { int disabled; }; -/* TODO: move this to struct v4l2_mpeg_compression ? */ -struct blackbird_dnr { - u32 mode; - u32 type; - u32 spatial; - u32 temporal; -}; - struct cx8802_dev { struct cx88_core *core; spinlock_t slock; @@ -432,8 +432,7 @@ struct cx8802_dev { unsigned char ts_gen_cntrl; /* mpeg params */ - struct v4l2_mpeg_compression params; - struct blackbird_dnr dnr_params; + struct cx2341x_mpeg_params params; }; /* ----------------------------------------------------------- */ @@ -564,7 +563,6 @@ void cx88_newstation(struct cx88_core *c void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t); void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); int cx88_audio_thread(void *data); -int cx88_detect_nicam(struct cx88_core *core); /* ----------------------------------------------------------- */ /* cx88-input.c */ @@ -593,16 +591,6 @@ extern int cx88_do_ioctl(struct inode *i struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl); -/* ----------------------------------------------------------- */ -/* cx88-blackbird.c */ -extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg); -extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd); -void blackbird_set_params(struct cx8802_dev *dev, - struct v4l2_mpeg_compression *params); -void blackbird_set_dnr_params(struct cx8802_dev *dev, - struct blackbird_dnr* dnr_params); - /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/dsbr100.c b/drivers/media/video/dsbr100.c index 3b4e998..f7e33f9 100644 --- a/drivers/media/video/dsbr100.c +++ b/drivers/media/video/dsbr100.c @@ -72,6 +72,7 @@ #include #include #include #include +#include #include #include diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 3ba3439..ed882eb 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -3,7 +3,7 @@ Copyright (C) 2005 Ludovico Cavedon Markus Rechberger - Mauro Carvalho Chehab + Mauro Carvalho Chehab Sascha Sommer This program is free software; you can redistribute it and/or modify @@ -29,6 +29,8 @@ #include #include #include #include +#include +#include #include #include #include @@ -46,11 +48,11 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA7113, .input = {{ .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, + .vmux = SAA7115_COMPOSITE0, .amux = 1, },{ .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, + .vmux = SAA7115_SVIDEO3, .amux = 1, }}, }, @@ -64,11 +66,11 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA7113, .input = {{ .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, + .vmux = SAA7115_COMPOSITE0, .amux = 1, },{ .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, + .vmux = SAA7115_SVIDEO3, .amux = 1, }}, }, @@ -82,11 +84,11 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA7113, .input = {{ .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, + .vmux = SAA7115_COMPOSITE0, .amux = 1, },{ .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, + .vmux = SAA7115_SVIDEO3, .amux = 1, }}, }, @@ -100,15 +102,15 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA7113, .input = {{ .type = EM28XX_VMUX_TELEVISION, - .vmux = 2, + .vmux = SAA7115_COMPOSITE2, .amux = 1, },{ .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, + .vmux = SAA7115_COMPOSITE0, .amux = 1, },{ .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, + .vmux = SAA7115_SVIDEO3, .amux = 1, }}, }, @@ -122,15 +124,15 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA7113, .input = {{ .type = EM28XX_VMUX_TELEVISION, - .vmux = 2, + .vmux = SAA7115_COMPOSITE2, .amux = 0, },{ .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, + .vmux = SAA7115_COMPOSITE0, .amux = 1, },{ .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, + .vmux = SAA7115_SVIDEO3, .amux = 1, }}, }, @@ -146,11 +148,11 @@ struct em28xx_board em28xx_boards[] = { /*FIXME: S-Video not tested */ .input = {{ .type = EM28XX_VMUX_TELEVISION, - .vmux = 0, + .vmux = TVP5150_COMPOSITE0, .amux = MSP_INPUT_DEFAULT, },{ .type = EM28XX_VMUX_SVIDEO, - .vmux = 2, + .vmux = TVP5150_SVIDEO, .amux = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, MSP_DSP_IN_SCART, MSP_DSP_IN_SCART), }}, @@ -165,15 +167,15 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA7114, .input = {{ .type = EM28XX_VMUX_TELEVISION, - .vmux = 4, + .vmux = SAA7115_COMPOSITE4, .amux = 0, },{ .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, + .vmux = SAA7115_COMPOSITE0, .amux = 1, },{ .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, + .vmux = SAA7115_SVIDEO3, .amux = 1, }}, }, @@ -188,15 +190,15 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA7113, .input = {{ .type = EM28XX_VMUX_TELEVISION, - .vmux = 2, + .vmux = SAA7115_COMPOSITE2, .amux = 0, },{ .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, + .vmux = SAA7115_COMPOSITE0, .amux = 1, },{ .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, + .vmux = SAA7115_SVIDEO3, .amux = 1, }}, }, @@ -211,15 +213,15 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA7113, .input = {{ .type = EM28XX_VMUX_TELEVISION, - .vmux = 2, + .vmux = SAA7115_COMPOSITE2, .amux = 0, },{ .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, + .vmux = SAA7115_COMPOSITE0, .amux = 1, },{ .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, + .vmux = SAA7115_SVIDEO3, .amux = 1, }}, }, @@ -234,15 +236,15 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA7113, .input = {{ .type = EM28XX_VMUX_TELEVISION, - .vmux = 2, + .vmux = SAA7115_COMPOSITE2, .amux = 0, },{ .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, + .vmux = SAA7115_COMPOSITE0, .amux = 1, },{ .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, + .vmux = SAA7115_SVIDEO3, .amux = 1, }}, }, @@ -254,11 +256,11 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA7113, .input = {{ .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, + .vmux = SAA7115_COMPOSITE0, .amux = 1, },{ .type = EM28XX_VMUX_SVIDEO, - .vmux = 9, + .vmux = SAA7115_SVIDEO3, .amux = 1, }}, }, @@ -324,8 +326,4 @@ #endif } } -EXPORT_SYMBOL(em28xx_boards); -EXPORT_SYMBOL(em28xx_bcount); -EXPORT_SYMBOL(em28xx_id_table); - MODULE_DEVICE_TABLE (usb, em28xx_id_table); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index e5ee8bc..4350cc7 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -3,7 +3,7 @@ Copyright (C) 2005 Ludovico Cavedon Markus Rechberger - Mauro Carvalho Chehab + Mauro Carvalho Chehab Sascha Sommer This program is free software; you can redistribute it and/or modify @@ -317,8 +317,8 @@ int em28xx_outfmt_set_yuv422(struct em28 return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1); } -int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin, - u8 ymax) +static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, + u8 ymin, u8 ymax) { em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax); @@ -328,7 +328,7 @@ int em28xx_accumulator_set(struct em28xx return em28xx_write_regs(dev, YMAX_REG, &ymax, 1); } -int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, +static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, u16 width, u16 height) { u8 cwidth = width; @@ -345,7 +345,7 @@ int em28xx_capture_area_set(struct em28x return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1); } -int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) +static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) { u8 mode; /* the em2800 scaler only supports scaling down to 50% */ @@ -534,7 +534,7 @@ static inline void em28xx_isoc_video_cop * em28xx_isoIrq() * handles the incoming isoc urbs and fills the frames from our inqueue */ -void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs) +static void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs) { struct em28xx *dev = urb->context; int i, status; diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 5b6cece..d829d8f 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -3,7 +3,7 @@ Copyright (C) 2005 Ludovico Cavedon Markus Rechberger - Mauro Carvalho Chehab + Mauro Carvalho Chehab Sascha Sommer This program is free software; you can redistribute it and/or modify @@ -399,17 +399,6 @@ static u32 functionality(struct i2c_adap return I2C_FUNC_SMBUS_EMUL; } -#ifndef I2C_PEC -static void inc_use(struct i2c_adapter *adap) -{ - MOD_INC_USE_COUNT; -} - -static void dec_use(struct i2c_adapter *adap) -{ - MOD_DEC_USE_COUNT; -} -#endif static int em28xx_set_tuner(int check_eeprom, struct i2c_client *client) { @@ -436,9 +425,19 @@ static int attach_inform(struct i2c_clie struct em28xx *dev = client->adapter->algo_data; switch (client->addr << 1) { - case 0x86: + case 0x43: + case 0x4b: + { + struct tuner_setup tun_setup; + + tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; + tun_setup.type = TUNER_TDA9887; + tun_setup.addr = client->addr; + + em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); em28xx_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf); break; + } case 0x42: dprintk1(1,"attach_inform: saa7114 detected.\n"); break; @@ -464,6 +463,7 @@ static int attach_inform(struct i2c_clie case 0xba: dprintk1(1,"attach_inform: tvp5150 detected.\n"); break; + default: dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1); dev->tuner_addr = client->addr; @@ -480,12 +480,7 @@ static struct i2c_algorithm em28xx_algo }; static struct i2c_adapter em28xx_adap_template = { -#ifdef I2C_PEC .owner = THIS_MODULE, -#else - .inc_use = inc_use, - .dec_use = dec_use, -#endif .class = I2C_CLASS_TV_ANALOG, .name = "em28xx", .id = I2C_HW_B_EM28XX, diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 31e89e4..3ffb568 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -3,7 +3,7 @@ Copyright (C) 2005 Ludovico Cavedon Markus Rechberger - Mauro Carvalho Chehab + Mauro Carvalho Chehab Sascha Sommer This program is free software; you can redistribute it and/or modify @@ -105,7 +105,7 @@ static int get_key_em_haup(struct IR_i2c return 1; } -static int get_key_pinnacle_usb(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char buf[3]; @@ -148,8 +148,8 @@ void em28xx_set_ir(struct em28xx * dev,s snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)"); break; case (EM2820_BOARD_PINNACLE_USB_2): - ir->ir_codes = ir_codes_em_pinnacle_usb; - ir->get_key = get_key_pinnacle_usb; + ir->ir_codes = ir_codes_pinnacle_grey; + ir->get_key = get_key_pinnacle_usb_grey; snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)"); break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index cf7cdf9..9286090 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -3,7 +3,7 @@ Copyright (C) 2005 Ludovico Cavedon Markus Rechberger - Mauro Carvalho Chehab + Mauro Carvalho Chehab Sascha Sommer Some parts based on SN9C10x PC Camera Controllers GPL driver made @@ -42,7 +42,7 @@ #include #define DRIVER_AUTHOR "Ludovico Cavedon , " \ "Markus Rechberger , " \ - "Mauro Carvalho Chehab , " \ + "Mauro Carvalho Chehab , " \ "Sascha Sommer " #define DRIVER_NAME "em28xx" @@ -170,8 +170,12 @@ static int em28xx_config(struct em28xx * static void em28xx_config_i2c(struct em28xx *dev) { struct v4l2_frequency f; + struct v4l2_routing route; + + route.input = INPUT(dev->ctl_input)->vmux; + route.output = 0; em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL); - em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &dev->ctl_input); + em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); /* configure tuner */ @@ -206,19 +210,19 @@ static void em28xx_empty_framequeues(str static void video_mux(struct em28xx *dev, int index) { - int input, ainput; + int ainput; + struct v4l2_routing route; - input = INPUT(index)->vmux; + route.input = INPUT(index)->vmux; + route.output = 0; dev->ctl_input = index; dev->ctl_ainput = INPUT(index)->amux; - em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &input); + em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); - em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput); + em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,route.input,dev->ctl_ainput); if (dev->has_msp34xx) { - struct v4l2_routing route; - if (dev->i2s_speed) em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed); route.input = dev->ctl_ainput; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index e1ddc2f..d8fcc9e 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -3,7 +3,7 @@ Copyright (C) 2005 Markus Rechberger Ludovico Cavedon - Mauro Carvalho Chehab + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer @@ -319,13 +319,7 @@ int em28xx_audio_analog_set(struct em28x int em28xx_colorlevels_set_default(struct em28xx *dev); int em28xx_capture_start(struct em28xx *dev, int start); int em28xx_outfmt_set_yuv422(struct em28xx *dev); -int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin, - u8 ymax); -int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, - u16 width, u16 height); -int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v); int em28xx_resolution_set(struct em28xx *dev); -void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs); int em28xx_init_isoc(struct em28xx *dev); void em28xx_uninit_isoc(struct em28xx *dev); int em28xx_set_alternate(struct em28xx *dev); diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index dfc9dd7..8992b6e 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -2341,11 +2341,9 @@ static int et61x251_ioctl_v4l2(struct in case VIDIOC_G_CTRL: return et61x251_vidioc_g_ctrl(cam, arg); - case VIDIOC_S_CTRL_OLD: case VIDIOC_S_CTRL: return et61x251_vidioc_s_ctrl(cam, arg); - case VIDIOC_CROPCAP_OLD: case VIDIOC_CROPCAP: return et61x251_vidioc_cropcap(cam, arg); @@ -2392,7 +2390,6 @@ static int et61x251_ioctl_v4l2(struct in case VIDIOC_G_PARM: return et61x251_vidioc_g_parm(cam, arg); - case VIDIOC_S_PARM_OLD: case VIDIOC_S_PARM: return et61x251_vidioc_s_parm(cam, arg); diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 7e66d83..fba30a4 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -150,12 +150,11 @@ static int get_key_knc1(struct IR_i2c *i return 1; } -/* The new pinnacle PCTV remote (with the colored buttons) +/* Common (grey or coloured) pinnacle PCTV remote handling * - * Ricardo Cerqueira */ - -int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, + int parity_offset, int marker, int code_modulo) { unsigned char b[4]; unsigned int start = 0,parity = 0,code = 0; @@ -167,9 +166,9 @@ int get_key_pinnacle(struct IR_i2c *ir, } for (start = 0; start<4; start++) { - if (b[start] == 0x80) { - code=b[(start+3)%4]; - parity=b[(start+2)%4]; + if (b[start] == marker) { + code=b[(start+parity_offset+1)%4]; + parity=b[(start+parity_offset)%4]; } } @@ -181,16 +180,14 @@ int get_key_pinnacle(struct IR_i2c *ir, if (ir->old == parity) return 0; - ir->old = parity; - /* Reduce code value to fit inside IR_KEYTAB_SIZE - * - * this is the only value that results in 42 unique - * codes < 128 - */ + /* drop special codes when a key is held down a long time for the grey controller + In this case, the second bit of the code is asserted */ + if (marker == 0xfe && (code & 0x40)) + return 0; - code %= 0x88; + code %= code_modulo; *ir_raw = code; *ir_key = code; @@ -200,7 +197,40 @@ int get_key_pinnacle(struct IR_i2c *ir, return 1; } -EXPORT_SYMBOL_GPL(get_key_pinnacle); +/* The grey pinnacle PCTV remote + * + * There are one issue with this remote: + * - I2c packet does not change when the same key is pressed quickly. The workaround + * is to hold down each key for about half a second, so that another code is generated + * in the i2c packet, and the function can distinguish key presses. + * + * Sylvain Pasche + */ +int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + + return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff); +} + +EXPORT_SYMBOL_GPL(get_key_pinnacle_grey); + + +/* The new pinnacle PCTV remote (with the colored buttons) + * + * Ricardo Cerqueira + */ +int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +{ + /* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE + * + * this is the only value that results in 42 unique + * codes < 128 + */ + + return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88); +} + +EXPORT_SYMBOL_GPL(get_key_pinnacle_color); /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c new file mode 100644 index 0000000..3bf7ac4 --- /dev/null +++ b/drivers/media/video/ks0127.c @@ -0,0 +1,846 @@ +/* + * Video Capture Driver (Video for Linux 1/2) + * for the Matrox Marvel G200,G400 and Rainbow Runner-G series + * + * This module is an interface to the KS0127 video decoder chip. + * + * Copyright (C) 1999 Ryan Drake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + ***************************************************************************** + * + * Modified and extended by + * Mike Bernson + * Gerard v.d. Horst + * Leon van Stuivenberg + * Gernot Ziegler + * + * Version History: + * V1.0 Ryan Drake Initial version by Ryan Drake + * V1.1 Gerard v.d. Horst Added some debugoutput, reset the video-standard + */ + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include "ks0127.h" + +#include +#include + +#define dprintk if (debug) printk + +/* i2c identification */ +#define I2C_KS0127_ADDON 0xD8 +#define I2C_KS0127_ONBOARD 0xDA + +#define KS_TYPE_UNKNOWN 0 +#define KS_TYPE_0122S 1 +#define KS_TYPE_0127 2 +#define KS_TYPE_0127B 3 + +/* ks0127 control registers */ +#define KS_STAT 0x00 +#define KS_CMDA 0x01 +#define KS_CMDB 0x02 +#define KS_CMDC 0x03 +#define KS_CMDD 0x04 +#define KS_HAVB 0x05 +#define KS_HAVE 0x06 +#define KS_HS1B 0x07 +#define KS_HS1E 0x08 +#define KS_HS2B 0x09 +#define KS_HS2E 0x0a +#define KS_AGC 0x0b +#define KS_HXTRA 0x0c +#define KS_CDEM 0x0d +#define KS_PORTAB 0x0e +#define KS_LUMA 0x0f +#define KS_CON 0x10 +#define KS_BRT 0x11 +#define KS_CHROMA 0x12 +#define KS_CHROMB 0x13 +#define KS_DEMOD 0x14 +#define KS_SAT 0x15 +#define KS_HUE 0x16 +#define KS_VERTIA 0x17 +#define KS_VERTIB 0x18 +#define KS_VERTIC 0x19 +#define KS_HSCLL 0x1a +#define KS_HSCLH 0x1b +#define KS_VSCLL 0x1c +#define KS_VSCLH 0x1d +#define KS_OFMTA 0x1e +#define KS_OFMTB 0x1f +#define KS_VBICTL 0x20 +#define KS_CCDAT2 0x21 +#define KS_CCDAT1 0x22 +#define KS_VBIL30 0x23 +#define KS_VBIL74 0x24 +#define KS_VBIL118 0x25 +#define KS_VBIL1512 0x26 +#define KS_TTFRAM 0x27 +#define KS_TESTA 0x28 +#define KS_UVOFFH 0x29 +#define KS_UVOFFL 0x2a +#define KS_UGAIN 0x2b +#define KS_VGAIN 0x2c +#define KS_VAVB 0x2d +#define KS_VAVE 0x2e +#define KS_CTRACK 0x2f +#define KS_POLCTL 0x30 +#define KS_REFCOD 0x31 +#define KS_INVALY 0x32 +#define KS_INVALU 0x33 +#define KS_INVALV 0x34 +#define KS_UNUSEY 0x35 +#define KS_UNUSEU 0x36 +#define KS_UNUSEV 0x37 +#define KS_USRSAV 0x38 +#define KS_USREAV 0x39 +#define KS_SHS1A 0x3a +#define KS_SHS1B 0x3b +#define KS_SHS1C 0x3c +#define KS_CMDE 0x3d +#define KS_VSDEL 0x3e +#define KS_CMDF 0x3f +#define KS_GAMMA0 0x40 +#define KS_GAMMA1 0x41 +#define KS_GAMMA2 0x42 +#define KS_GAMMA3 0x43 +#define KS_GAMMA4 0x44 +#define KS_GAMMA5 0x45 +#define KS_GAMMA6 0x46 +#define KS_GAMMA7 0x47 +#define KS_GAMMA8 0x48 +#define KS_GAMMA9 0x49 +#define KS_GAMMA10 0x4a +#define KS_GAMMA11 0x4b +#define KS_GAMMA12 0x4c +#define KS_GAMMA13 0x4d +#define KS_GAMMA14 0x4e +#define KS_GAMMA15 0x4f +#define KS_GAMMA16 0x50 +#define KS_GAMMA17 0x51 +#define KS_GAMMA18 0x52 +#define KS_GAMMA19 0x53 +#define KS_GAMMA20 0x54 +#define KS_GAMMA21 0x55 +#define KS_GAMMA22 0x56 +#define KS_GAMMA23 0x57 +#define KS_GAMMA24 0x58 +#define KS_GAMMA25 0x59 +#define KS_GAMMA26 0x5a +#define KS_GAMMA27 0x5b +#define KS_GAMMA28 0x5c +#define KS_GAMMA29 0x5d +#define KS_GAMMA30 0x5e +#define KS_GAMMA31 0x5f +#define KS_GAMMAD0 0x60 +#define KS_GAMMAD1 0x61 +#define KS_GAMMAD2 0x62 +#define KS_GAMMAD3 0x63 +#define KS_GAMMAD4 0x64 +#define KS_GAMMAD5 0x65 +#define KS_GAMMAD6 0x66 +#define KS_GAMMAD7 0x67 +#define KS_GAMMAD8 0x68 +#define KS_GAMMAD9 0x69 +#define KS_GAMMAD10 0x6a +#define KS_GAMMAD11 0x6b +#define KS_GAMMAD12 0x6c +#define KS_GAMMAD13 0x6d +#define KS_GAMMAD14 0x6e +#define KS_GAMMAD15 0x6f +#define KS_GAMMAD16 0x70 +#define KS_GAMMAD17 0x71 +#define KS_GAMMAD18 0x72 +#define KS_GAMMAD19 0x73 +#define KS_GAMMAD20 0x74 +#define KS_GAMMAD21 0x75 +#define KS_GAMMAD22 0x76 +#define KS_GAMMAD23 0x77 +#define KS_GAMMAD24 0x78 +#define KS_GAMMAD25 0x79 +#define KS_GAMMAD26 0x7a +#define KS_GAMMAD27 0x7b +#define KS_GAMMAD28 0x7c +#define KS_GAMMAD29 0x7d +#define KS_GAMMAD30 0x7e +#define KS_GAMMAD31 0x7f + + +/**************************************************************************** +* mga_dev : represents one ks0127 chip. +****************************************************************************/ + +struct adjust { + int contrast; + int bright; + int hue; + int ugain; + int vgain; +}; + +struct ks0127 { + struct i2c_client *client; + unsigned char addr; + int format_width; + int format_height; + int cap_width; + int cap_height; + int norm; + int ks_type; + u8 regs[256]; +}; + + +static int debug; /* insmod parameter */ + +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug output"); +MODULE_LICENSE("GPL"); + +static u8 reg_defaults[64]; + + + +static void init_reg_defaults(void) +{ + u8 *table = reg_defaults; + + table[KS_CMDA] = 0x2c; /* VSE=0, CCIR 601, autodetect standard */ + table[KS_CMDB] = 0x12; /* VALIGN=0, AGC control and input */ + table[KS_CMDC] = 0x00; /* Test options */ + /* clock & input select, write 1 to PORTA */ + table[KS_CMDD] = 0x01; + table[KS_HAVB] = 0x00; /* HAV Start Control */ + table[KS_HAVE] = 0x00; /* HAV End Control */ + table[KS_HS1B] = 0x10; /* HS1 Start Control */ + table[KS_HS1E] = 0x00; /* HS1 End Control */ + table[KS_HS2B] = 0x00; /* HS2 Start Control */ + table[KS_HS2E] = 0x00; /* HS2 End Control */ + table[KS_AGC] = 0x53; /* Manual setting for AGC */ + table[KS_HXTRA] = 0x00; /* Extra Bits for HAV and HS1/2 */ + table[KS_CDEM] = 0x00; /* Chroma Demodulation Control */ + table[KS_PORTAB] = 0x0f; /* port B is input, port A output GPPORT */ + table[KS_LUMA] = 0x01; /* Luma control */ + table[KS_CON] = 0x00; /* Contrast Control */ + table[KS_BRT] = 0x00; /* Brightness Control */ + table[KS_CHROMA] = 0x2a; /* Chroma control A */ + table[KS_CHROMB] = 0x90; /* Chroma control B */ + table[KS_DEMOD] = 0x00; /* Chroma Demodulation Control & Status */ + table[KS_SAT] = 0x00; /* Color Saturation Control*/ + table[KS_HUE] = 0x00; /* Hue Control */ + table[KS_VERTIA] = 0x00; /* Vertical Processing Control A */ + /* Vertical Processing Control B, luma 1 line delayed */ + table[KS_VERTIB] = 0x12; + table[KS_VERTIC] = 0x0b; /* Vertical Processing Control C */ + table[KS_HSCLL] = 0x00; /* Horizontal Scaling Ratio Low */ + table[KS_HSCLH] = 0x00; /* Horizontal Scaling Ratio High */ + table[KS_VSCLL] = 0x00; /* Vertical Scaling Ratio Low */ + table[KS_VSCLH] = 0x00; /* Vertical Scaling Ratio High */ + /* 16 bit YCbCr 4:2:2 output; I can't make the bt866 like 8 bit /Sam */ + table[KS_OFMTA] = 0x30; + table[KS_OFMTB] = 0x00; /* Output Control B */ + /* VBI Decoder Control; 4bit fmt: avoid Y overflow */ + table[KS_VBICTL] = 0x5d; + table[KS_CCDAT2] = 0x00; /* Read Only register */ + table[KS_CCDAT1] = 0x00; /* Read Only register */ + table[KS_VBIL30] = 0xa8; /* VBI data decoding options */ + table[KS_VBIL74] = 0xaa; /* VBI data decoding options */ + table[KS_VBIL118] = 0x2a; /* VBI data decoding options */ + table[KS_VBIL1512] = 0x00; /* VBI data decoding options */ + table[KS_TTFRAM] = 0x00; /* Teletext frame alignment pattern */ + table[KS_TESTA] = 0x00; /* test register, shouldn't be written */ + table[KS_UVOFFH] = 0x00; /* UV Offset Adjustment High */ + table[KS_UVOFFL] = 0x00; /* UV Offset Adjustment Low */ + table[KS_UGAIN] = 0x00; /* U Component Gain Adjustment */ + table[KS_VGAIN] = 0x00; /* V Component Gain Adjustment */ + table[KS_VAVB] = 0x07; /* VAV Begin */ + table[KS_VAVE] = 0x00; /* VAV End */ + table[KS_CTRACK] = 0x00; /* Chroma Tracking Control */ + table[KS_POLCTL] = 0x41; /* Timing Signal Polarity Control */ + table[KS_REFCOD] = 0x80; /* Reference Code Insertion Control */ + table[KS_INVALY] = 0x10; /* Invalid Y Code */ + table[KS_INVALU] = 0x80; /* Invalid U Code */ + table[KS_INVALV] = 0x80; /* Invalid V Code */ + table[KS_UNUSEY] = 0x10; /* Unused Y Code */ + table[KS_UNUSEU] = 0x80; /* Unused U Code */ + table[KS_UNUSEV] = 0x80; /* Unused V Code */ + table[KS_USRSAV] = 0x00; /* reserved */ + table[KS_USREAV] = 0x00; /* reserved */ + table[KS_SHS1A] = 0x00; /* User Defined SHS1 A */ + /* User Defined SHS1 B, ALT656=1 on 0127B */ + table[KS_SHS1B] = 0x80; + table[KS_SHS1C] = 0x00; /* User Defined SHS1 C */ + table[KS_CMDE] = 0x00; /* Command Register E */ + table[KS_VSDEL] = 0x00; /* VS Delay Control */ + /* Command Register F, update -immediately- */ + /* (there might come no vsync)*/ + table[KS_CMDF] = 0x02; +} + + +/* We need to manually read because of a bug in the KS0127 chip. + * + * An explanation from kayork@mail.utexas.edu: + * + * During I2C reads, the KS0127 only samples for a stop condition + * during the place where the acknoledge bit should be. Any standard + * I2C implementation (correctly) throws in another clock transition + * at the 9th bit, and the KS0127 will not recognize the stop condition + * and will continue to clock out data. + * + * So we have to do the read ourself. Big deal. + workaround in i2c-algo-bit + */ + + +static u8 ks0127_read(struct ks0127 *ks, u8 reg) +{ + struct i2c_client *c = ks->client; + char val = 0; + struct i2c_msg msgs[] = { + {c->addr, 0, sizeof(reg), ®}, + {c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val}}; + int ret; + + ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + dprintk("ks0127_write error\n"); + + return val; +} + + +static void ks0127_write(struct ks0127 *ks, u8 reg, u8 val) +{ + char msg[] = {reg, val}; + + if (i2c_master_send(ks->client, msg, sizeof(msg)) != sizeof(msg)) + dprintk("ks0127_write error\n"); + + ks->regs[reg] = val; +} + + +/* generic bit-twiddling */ +static void ks0127_and_or(struct ks0127 *ks, u8 reg, u8 and_v, u8 or_v) +{ + u8 val = ks->regs[reg]; + val = (val & and_v) | or_v; + ks0127_write(ks, reg, val); +} + + + +/**************************************************************************** +* ks0127 private api +****************************************************************************/ +static void ks0127_reset(struct ks0127* ks) +{ + int i; + u8 *table = reg_defaults; + + ks->ks_type = KS_TYPE_UNKNOWN; + + dprintk("ks0127: reset\n"); + msleep(1); + + /* initialize all registers to known values */ + /* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */ + + for(i = 1; i < 33; i++) + ks0127_write(ks, i, table[i]); + + for(i = 35; i < 40; i++) + ks0127_write(ks, i, table[i]); + + for(i = 41; i < 56; i++) + ks0127_write(ks, i, table[i]); + + for(i = 58; i < 64; i++) + ks0127_write(ks, i, table[i]); + + + if ((ks0127_read(ks, KS_STAT) & 0x80) == 0) { + ks->ks_type = KS_TYPE_0122S; + dprintk("ks0127: ks0122s Found\n"); + return; + } + + switch(ks0127_read(ks, KS_CMDE) & 0x0f) { + + case 0: + ks->ks_type = KS_TYPE_0127; + dprintk("ks0127: ks0127 found\n"); + break; + + case 9: + ks->ks_type = KS_TYPE_0127B; + dprintk("ks0127: ks0127B Revision A found\n"); + break; + + default: + dprintk("ks0127: unknown revision\n"); + break; + } +} + +static int ks0127_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct ks0127 *ks = i2c_get_clientdata(client); + + int *iarg = (int*)arg; + + int status; + + if (!ks) + return -ENODEV; + + switch (cmd) { + + case DECODER_INIT: + dprintk("ks0127: command DECODER_INIT\n"); + ks0127_reset(ks); + break; + + case DECODER_SET_INPUT: + switch(*iarg) { + case KS_INPUT_COMPOSITE_1: + case KS_INPUT_COMPOSITE_2: + case KS_INPUT_COMPOSITE_3: + case KS_INPUT_COMPOSITE_4: + case KS_INPUT_COMPOSITE_5: + case KS_INPUT_COMPOSITE_6: + dprintk("ks0127: command DECODER_SET_INPUT %d: " + "Composite\n", *iarg); + /* autodetect 50/60 Hz */ + ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); + /* VSE=0 */ + ks0127_and_or(ks, KS_CMDA, ~0x40, 0x00); + /* set input line */ + ks0127_and_or(ks, KS_CMDB, 0xb0, *iarg); + /* non-freerunning mode */ + ks0127_and_or(ks, KS_CMDC, 0x70, 0x0a); + /* analog input */ + ks0127_and_or(ks, KS_CMDD, 0x03, 0x00); + /* enable chroma demodulation */ + ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00); + /* chroma trap, HYBWR=1 */ + ks0127_and_or(ks, KS_LUMA, 0x00, + (reg_defaults[KS_LUMA])|0x0c); + /* scaler fullbw, luma comb off */ + ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81); + /* manual chroma comb .25 .5 .25 */ + ks0127_and_or(ks, KS_VERTIC, 0x0f, 0x90); + + /* chroma path delay */ + ks0127_and_or(ks, KS_CHROMB, 0x0f, 0x90); + + ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]); + ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]); + ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]); + ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]); + break; + + case KS_INPUT_SVIDEO_1: + case KS_INPUT_SVIDEO_2: + case KS_INPUT_SVIDEO_3: + dprintk("ks0127: command DECODER_SET_INPUT %d: " + "S-Video\n", *iarg); + /* autodetect 50/60 Hz */ + ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); + /* VSE=0 */ + ks0127_and_or(ks, KS_CMDA, ~0x40, 0x00); + /* set input line */ + ks0127_and_or(ks, KS_CMDB, 0xb0, *iarg); + /* non-freerunning mode */ + ks0127_and_or(ks, KS_CMDC, 0x70, 0x0a); + /* analog input */ + ks0127_and_or(ks, KS_CMDD, 0x03, 0x00); + /* enable chroma demodulation */ + ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00); + ks0127_and_or(ks, KS_LUMA, 0x00, + reg_defaults[KS_LUMA]); + /* disable luma comb */ + ks0127_and_or(ks, KS_VERTIA, 0x08, + (reg_defaults[KS_VERTIA]&0xf0)|0x01); + ks0127_and_or(ks, KS_VERTIC, 0x0f, + reg_defaults[KS_VERTIC]&0xf0); + + ks0127_and_or(ks, KS_CHROMB, 0x0f, + reg_defaults[KS_CHROMB]&0xf0); + + ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]); + ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]); + ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]); + ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]); + break; + + case KS_INPUT_YUV656: + dprintk("ks0127: command DECODER_SET_INPUT 15: " + "YUV656\n"); + if (ks->norm == VIDEO_MODE_NTSC || + ks->norm == KS_STD_PAL_M) + /* force 60 Hz */ + ks0127_and_or(ks, KS_CMDA, 0xfc, 0x03); + else + /* force 50 Hz */ + ks0127_and_or(ks, KS_CMDA, 0xfc, 0x02); + + ks0127_and_or(ks, KS_CMDA, 0xff, 0x40); /* VSE=1 */ + /* set input line and VALIGN */ + ks0127_and_or(ks, KS_CMDB, 0xb0, (*iarg | 0x40)); + /* freerunning mode, */ + /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/ + ks0127_and_or(ks, KS_CMDC, 0x70, 0x87); + /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */ + ks0127_and_or(ks, KS_CMDD, 0x03, 0x08); + /* disable chroma demodulation */ + ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x30); + /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */ + ks0127_and_or(ks, KS_LUMA, 0x00, 0x71); + ks0127_and_or(ks, KS_VERTIC, 0x0f, + reg_defaults[KS_VERTIC]&0xf0); + + /* scaler fullbw, luma comb off */ + ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81); + + ks0127_and_or(ks, KS_CHROMB, 0x0f, + reg_defaults[KS_CHROMB]&0xf0); + + ks0127_and_or(ks, KS_CON, 0x00, 0x00); + ks0127_and_or(ks, KS_BRT, 0x00, 32); /* spec: 34 */ + /* spec: 229 (e5) */ + ks0127_and_or(ks, KS_SAT, 0x00, 0xe8); + ks0127_and_or(ks, KS_HUE, 0x00, 0); + + ks0127_and_or(ks, KS_UGAIN, 0x00, 238); + ks0127_and_or(ks, KS_VGAIN, 0x00, 0x00); + + /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */ + ks0127_and_or(ks, KS_UVOFFH, 0x00, 0x4f); + ks0127_and_or(ks, KS_UVOFFL, 0x00, 0x00); + break; + + default: + dprintk("ks0127: command DECODER_SET_INPUT: " + "Unknown input %d\n", *iarg); + break; + } + + /* hack: CDMLPF sometimes spontaneously switches on; */ + /* force back off */ + ks0127_write(ks, KS_DEMOD, reg_defaults[KS_DEMOD]); + break; + + case DECODER_SET_OUTPUT: + switch(*iarg) { + case KS_OUTPUT_YUV656E: + dprintk("ks0127: command DECODER_SET_OUTPUT: " + "OUTPUT_YUV656E (Missing)\n"); + return -EINVAL; + break; + + case KS_OUTPUT_EXV: + dprintk("ks0127: command DECODER_SET_OUTPUT: " + "OUTPUT_EXV\n"); + ks0127_and_or(ks, KS_OFMTA, 0xf0, 0x09); + break; + } + break; + + case DECODER_SET_NORM: //sam This block mixes old and new norm names... + /* Set to automatic SECAM/Fsc mode */ + ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00); + + ks->norm = *iarg; + switch(*iarg) + { + /* this is untested !! */ + /* It just detects PAL_N/NTSC_M (no special frequencies) */ + /* And you have to set the standard a second time afterwards */ + case VIDEO_MODE_AUTO: + dprintk("ks0127: command DECODER_SET_NORM: AUTO\n"); + + /* The chip determines the format */ + /* based on the current field rate */ + ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); + ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); + /* This is wrong for PAL ! As I said, */ + /* you need to set the standard once again !! */ + ks->format_height = 240; + ks->format_width = 704; + break; + + case VIDEO_MODE_NTSC: + dprintk("ks0127: command DECODER_SET_NORM: NTSC_M\n"); + ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); + ks->format_height = 240; + ks->format_width = 704; + break; + + case KS_STD_NTSC_N: + dprintk("ks0127: command KS0127_SET_STANDARD: " + "NTSC_N (fixme)\n"); + ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40); + ks->format_height = 240; + ks->format_width = 704; + break; + + case VIDEO_MODE_PAL: + dprintk("ks0127: command DECODER_SET_NORM: PAL_N\n"); + ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); + ks->format_height = 290; + ks->format_width = 704; + break; + + case KS_STD_PAL_M: + dprintk("ks0127: command KS0127_SET_STANDARD: " + "PAL_M (fixme)\n"); + ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40); + ks->format_height = 290; + ks->format_width = 704; + break; + + case VIDEO_MODE_SECAM: + dprintk("ks0127: command KS0127_SET_STANDARD: " + "SECAM\n"); + ks->format_height = 290; + ks->format_width = 704; + + /* set to secam autodetection */ + ks0127_and_or(ks, KS_CHROMA, 0xdf, 0x20); + ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00); + schedule_timeout_interruptible(HZ/10+1); + + /* did it autodetect? */ + if (ks0127_read(ks, KS_DEMOD) & 0x40) + break; + + /* force to secam mode */ + ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x0f); + break; + + default: + dprintk("ks0127: command DECODER_SET_NORM: " + "Unknown norm %d\n", *iarg); + break; + } + break; + + case DECODER_SET_PICTURE: + dprintk("ks0127: command DECODER_SET_PICTURE " + "not yet supported (fixme)\n"); + return -EINVAL; + + //sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE + //sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE + //sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? + //sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE + //sam todo: KS0127_SET_AGC_MODE: + //sam todo: KS0127_SET_AGC: + //sam todo: KS0127_SET_CHROMA_MODE: + //sam todo: KS0127_SET_PIXCLK_MODE: + //sam todo: KS0127_SET_GAMMA_MODE: + //sam todo: KS0127_SET_UGAIN: + //sam todo: KS0127_SET_VGAIN: + //sam todo: KS0127_SET_INVALY: + //sam todo: KS0127_SET_INVALU: + //sam todo: KS0127_SET_INVALV: + //sam todo: KS0127_SET_UNUSEY: + //sam todo: KS0127_SET_UNUSEU: + //sam todo: KS0127_SET_UNUSEV: + //sam todo: KS0127_SET_VSALIGN_MODE: + + case DECODER_ENABLE_OUTPUT: + { + + int *iarg = arg; + int enable = (*iarg != 0); + if (enable) { + dprintk("ks0127: command " + "DECODER_ENABLE_OUTPUT on " + "(%d)\n", enable); + /* All output pins on */ + ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30); + /* Obey the OEN pin */ + ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00); + } else { + dprintk("ks0127: command " + "DECODER_ENABLE_OUTPUT off " + "(%d)\n", enable); + /* Video output pins off */ + ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00); + /* Ignore the OEN pin */ + ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80); + } + } + break; + + //sam todo: KS0127_SET_OUTPUT_MODE: + //sam todo: KS0127_SET_WIDTH: + //sam todo: KS0127_SET_HEIGHT: + //sam todo: KS0127_SET_HSCALE: + + case DECODER_GET_STATUS: + dprintk("ks0127: command DECODER_GET_STATUS\n"); + *iarg = 0; + status = ks0127_read(ks, KS_STAT); + if (!(status & 0x20)) /* NOVID not set */ + *iarg = (*iarg & DECODER_STATUS_GOOD); + if ((status & 0x01)) /* CLOCK set */ + *iarg = (*iarg & DECODER_STATUS_COLOR); + if ((status & 0x08)) /* PALDET set */ + *iarg = (*iarg & DECODER_STATUS_PAL); + else + *iarg = (*iarg & DECODER_STATUS_NTSC); + break; + + //Catch any unknown command + default: + dprintk("ks0127: command unknown: %04X\n", cmd); + return -EINVAL; + } + return 0; +} + + + + +static int ks0127_probe(struct i2c_adapter *adapter); +static int ks0127_detach(struct i2c_client *client); +static int ks0127_command(struct i2c_client *client, + unsigned int cmd, void *arg); + + + +/* Addresses to scan */ +static unsigned short normal_i2c[] = {I2C_KS0127_ADDON>>1, + I2C_KS0127_ONBOARD>>1, I2C_CLIENT_END}; +static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; +static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; +static struct i2c_client_address_data addr_data = { + normal_i2c, + probe, + ignore, +}; + +static struct i2c_driver i2c_driver_ks0127 = { + .driver.name = "ks0127", + .id = I2C_DRIVERID_KS0127, + .attach_adapter = ks0127_probe, + .detach_client = ks0127_detach, + .command = ks0127_command +}; + +static struct i2c_client ks0127_client_tmpl = +{ + .name = "(ks0127 unset)", + .addr = 0, + .adapter = NULL, + .driver = &i2c_driver_ks0127, + .usage_count = 0 +}; + +static int ks0127_found_proc(struct i2c_adapter *adapter, int addr, int kind) +{ + struct ks0127 *ks; + struct i2c_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (client == NULL) + return -ENOMEM; + memcpy(client, &ks0127_client_tmpl, sizeof(*client)); + + ks = kzalloc(sizeof(*ks), GFP_KERNEL); + if (ks == NULL) { + kfree(client); + return -ENOMEM; + } + + i2c_set_clientdata(client, ks); + client->adapter = adapter; + client->addr = addr; + sprintf(client->name, "ks0127-%02x", adapter->id); + + ks->client = client; + ks->addr = addr; + ks->ks_type = KS_TYPE_UNKNOWN; + + /* power up */ + ks0127_write(ks, KS_CMDA, 0x2c); + mdelay(10); + + /* reset the device */ + ks0127_reset(ks); + printk(KERN_INFO "ks0127: attach: %s video decoder\n", + ks->addr==(I2C_KS0127_ADDON>>1) ? "addon" : "on-board"); + + i2c_attach_client(client); + return 0; +} + + +static int ks0127_probe(struct i2c_adapter *adapter) +{ + if (adapter->id == I2C_HW_B_ZR36067) + return i2c_probe(adapter, &addr_data, ks0127_found_proc); + return 0; +} + +static int ks0127_detach(struct i2c_client *client) +{ + struct ks0127 *ks = i2c_get_clientdata(client); + + ks0127_write(ks, KS_OFMTA, 0x20); /*tristate*/ + ks0127_write(ks, KS_CMDA, 0x2c | 0x80); /* power down */ + + i2c_detach_client(client); + kfree(ks); + kfree(client); + + dprintk("ks0127: detach\n"); + return 0; +} + + +static int __devinit ks0127_init_module(void) +{ + init_reg_defaults(); + i2c_add_driver(&i2c_driver_ks0127); + return 0; +} + +static void __devexit ks0127_cleanup_module(void) +{ + i2c_del_driver(&i2c_driver_ks0127); +} + + +module_init(ks0127_init_module); +module_exit(ks0127_cleanup_module); diff --git a/drivers/media/video/ks0127.h b/drivers/media/video/ks0127.h new file mode 100644 index 0000000..1ec5788 --- /dev/null +++ b/drivers/media/video/ks0127.h @@ -0,0 +1,53 @@ +/* + * Video Capture Driver ( Video for Linux 1/2 ) + * for the Matrox Marvel G200,G400 and Rainbow Runner-G series + * + * This module is an interface to the KS0127 video decoder chip. + * + * Copyright (C) 1999 Ryan Drake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef KS0127_H +#define KS0127_H + +#include + +/* input channels */ +#define KS_INPUT_COMPOSITE_1 0 +#define KS_INPUT_COMPOSITE_2 1 +#define KS_INPUT_COMPOSITE_3 2 +#define KS_INPUT_COMPOSITE_4 4 +#define KS_INPUT_COMPOSITE_5 5 +#define KS_INPUT_COMPOSITE_6 6 + +#define KS_INPUT_SVIDEO_1 8 +#define KS_INPUT_SVIDEO_2 9 +#define KS_INPUT_SVIDEO_3 10 + +#define KS_INPUT_YUV656 15 +#define KS_INPUT_COUNT 10 + +/* output channels */ +#define KS_OUTPUT_YUV656E 0 +#define KS_OUTPUT_EXV 1 + +/* video standards */ +#define KS_STD_NTSC_N 112 /* 50 Hz NTSC */ +#define KS_STD_PAL_M 113 /* 60 Hz PAL */ + +#endif /* KS0127_H */ + diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 850bee9..f68ca7d 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -32,6 +32,7 @@ #include #include #include #include +#include #include #include #include @@ -1682,13 +1683,13 @@ static unsigned int meye_poll(struct fil static void meye_vm_open(struct vm_area_struct *vma) { - int idx = (int)vma->vm_private_data; + long idx = (long)vma->vm_private_data; meye.vma_use_count[idx]++; } static void meye_vm_close(struct vm_area_struct *vma) { - int idx = (int)vma->vm_private_data; + long idx = (long)vma->vm_private_data; meye.vma_use_count[idx]--; } diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index b806999..dbb75a7 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -385,67 +385,6 @@ static int msp_mode_v4l1_to_v4l2(int mod return V4L2_TUNER_MODE_MONO; } -static struct v4l2_queryctrl msp_qctrl_std[] = { - { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 58880, - .flags = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - .flags = 0, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, -}; - -static struct v4l2_queryctrl msp_qctrl_sound_processing[] = { - { - .id = V4L2_CID_AUDIO_BALANCE, - .name = "Balance", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - .flags = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_BASS, - .name = "Bass", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_TREBLE, - .name = "Treble", - .minimum = 0, - .maximum = 65535, - .step = 65535/100, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_LOUDNESS, - .name = "Loudness", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - .flags = 0, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, -}; - - static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) { struct msp_state *state = i2c_get_clientdata(client); @@ -674,22 +613,31 @@ static int msp_command(struct i2c_client int sc1_out = rt->output & 0xf; int sc2_out = (rt->output >> 4) & 0xf; u16 val, reg; + int i; + int extern_input = 1; if (state->routing.input == rt->input && state->routing.output == rt->output) break; state->routing = *rt; + /* check if the tuner input is used */ + for (i = 0; i < 5; i++) { + if (((rt->input >> (4 + i * 4)) & 0xf) == 0) + extern_input = 0; + } + if (extern_input) + state->mode = MSP_MODE_EXTERN; + else + state->mode = MSP_MODE_AM_DETECT; msp_set_scart(client, sc_in, 0); msp_set_scart(client, sc1_out, 1); msp_set_scart(client, sc2_out, 2); msp_set_audmode(client); reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb; val = msp_read_dem(client, reg); - if (tuner != ((val >> 8) & 1)) { - msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8)); - /* wake thread when a new tuner input is chosen */ - msp_wake_thread(client); - } + msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8)); + /* wake thread when a new input is chosen */ + msp_wake_thread(client); break; } @@ -744,21 +692,25 @@ static int msp_command(struct i2c_client case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *qc = arg; - int i; - for (i = 0; i < ARRAY_SIZE(msp_qctrl_std); i++) - if (qc->id && qc->id == msp_qctrl_std[i].id) { - memcpy(qc, &msp_qctrl_std[i], sizeof(*qc)); - return 0; - } + switch (qc->id) { + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill_std(qc); + default: + break; + } if (!state->has_sound_processing) return -EINVAL; - for (i = 0; i < ARRAY_SIZE(msp_qctrl_sound_processing); i++) - if (qc->id && qc->id == msp_qctrl_sound_processing[i].id) { - memcpy(qc, &msp_qctrl_sound_processing[i], sizeof(*qc)); - return 0; - } - return -EINVAL; + switch (qc->id) { + case V4L2_CID_AUDIO_LOUDNESS: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + return v4l2_ctrl_query_fill_std(qc); + default: + return -EINVAL; + } } case VIDIOC_G_CTRL: @@ -794,7 +746,9 @@ static int msp_command(struct i2c_client case MSP_MODE_EXTERN: p = "External input"; break; default: p = "unknown"; break; } - if (state->opmode == OPMODE_MANUAL) { + if (state->mode == MSP_MODE_EXTERN) { + v4l_info(client, "Mode: %s\n", p); + } else if (state->opmode == OPMODE_MANUAL) { v4l_info(client, "Mode: %s (%s%s)\n", p, (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 633a102..f2fd919 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -244,19 +244,21 @@ static void msp3400c_set_audmode(struct the hardware does not support SAP. So the rxsubchans combination of STEREO | LANG2 does not occur. */ - /* switch to mono if only mono is available */ - if (state->rxsubchans == V4L2_TUNER_SUB_MONO) - audmode = V4L2_TUNER_MODE_MONO; - /* if bilingual */ - else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) { - /* and mono or stereo, then fallback to lang1 */ - if (audmode == V4L2_TUNER_MODE_MONO || - audmode == V4L2_TUNER_MODE_STEREO) - audmode = V4L2_TUNER_MODE_LANG1; + if (state->mode != MSP_MODE_EXTERN) { + /* switch to mono if only mono is available */ + if (state->rxsubchans == V4L2_TUNER_SUB_MONO) + audmode = V4L2_TUNER_MODE_MONO; + /* if bilingual */ + else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) { + /* and mono or stereo, then fallback to lang1 */ + if (audmode == V4L2_TUNER_MODE_MONO || + audmode == V4L2_TUNER_MODE_STEREO) + audmode = V4L2_TUNER_MODE_LANG1; + } + /* if stereo, and audmode is not mono, then switch to stereo */ + else if (audmode != V4L2_TUNER_MODE_MONO) + audmode = V4L2_TUNER_MODE_STEREO; } - /* if stereo, and audmode is not mono, then switch to stereo */ - else if (audmode != V4L2_TUNER_MODE_MONO) - audmode = V4L2_TUNER_MODE_STEREO; /* switch demodulator */ switch (state->mode) { @@ -481,6 +483,7 @@ int msp3400c_thread(void *data) /* no carrier scan, just unmute */ v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); state->scan_in_progress = 0; + state->rxsubchans = V4L2_TUNER_SUB_STEREO; msp_set_audio(client); continue; } @@ -947,6 +950,14 @@ int msp34xxg_thread(void *data) if (kthread_should_stop()) break; + if (state->mode == MSP_MODE_EXTERN) { + /* no carrier scan needed, just unmute */ + v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); + state->scan_in_progress = 0; + msp_set_audio(client); + continue; + } + /* setup the chip*/ msp34xxg_reset(client); state->std = state->radio ? 0x40 : msp_standard; @@ -978,6 +989,11 @@ int msp34xxg_thread(void *data) v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n", msp_standard_std_name(state->std), state->std); + if (state->std == 9) { + /* AM NICAM mode */ + msp_write_dsp(client, 0x0e, 0x7c00); + } + /* unmute: dispatch sound to scart output, set scart volume */ msp_set_audio(client); diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index fdc8e3f..a988df2 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -3239,7 +3239,7 @@ ov511_move_data(struct usb_ov511 *ov, un RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); if (frame->scanstate == STATE_LINES) { - int nextf; + int nextf; frame->grabstate = FRAME_DONE; wake_up_interruptible(&frame->wq); @@ -3405,7 +3405,7 @@ eof: RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw); if (frame->scanstate == STATE_LINES) { - int nextf; + int nextf; frame->grabstate = FRAME_DONE; wake_up_interruptible(&frame->wq); diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h index 12b3d51..68b082b 100644 --- a/drivers/media/video/ov511.h +++ b/drivers/media/video/ov511.h @@ -3,6 +3,7 @@ #define __LINUX_OV511_H #include #include +#include #include #include #include diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index d9e3cad..3484e36 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -40,6 +40,7 @@ #include #include #include #include +#include #include #include #include diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 09835ca..5d681fa 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -30,6 +30,7 @@ #include #include #include #include +#include #include #include @@ -804,7 +805,7 @@ static int pms_do_ioctl(struct inode *in struct video_picture *p = arg; if(!((p->palette==VIDEO_PALETTE_RGB565 && p->depth==16) ||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15))) - return -EINVAL; + return -EINVAL; pd->picture= *p; /* diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig index 53cbc95..697145e 100644 --- a/drivers/media/video/pwc/Kconfig +++ b/drivers/media/video/pwc/Kconfig @@ -7,6 +7,7 @@ config USB_PWC * Philips PCA645, PCA646 * Philips PCVC675, PCVC680, PCVC690 * Philips PCVC720/40, PCVC730, PCVC740, PCVC750 + * Philips SPC900NC * Askey VC010 * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' and 'Orbit'/'Sphere' @@ -19,10 +20,18 @@ config USB_PWC and never will be, but the 665 and 720/20 are supported by other drivers. - See for more information and - installation instructions. + Some newer logitech webcams are not handled by this driver but by the + Usb Video Class driver (linux-uvc). The built-in microphone is enabled by selecting USB Audio support. To compile this driver as a module, choose M here: the module will be called pwc. + +config USB_PWC_DEBUG + bool "USB Philips Cameras verbose debug" + depends USB_PWC + help + Say Y here in order to have the pwc driver generate verbose debugging + messages. + A special module options 'trace' is used to control the verbosity. diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile index 33d6012..9db2260 100644 --- a/drivers/media/video/pwc/Makefile +++ b/drivers/media/video/pwc/Makefile @@ -1,3 +1,12 @@ -pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o +pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o +pwc-objs += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o obj-$(CONFIG_USB_PWC) += pwc.o + +ifeq ($(CONFIG_USB_PWC_DEBUG),y) +EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=1 +else +EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=0 +endif + + diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 4ba549b..0bd1155 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c @@ -2,7 +2,7 @@ Functions that send various control messages to the webcam, including video modes. (C) 1999-2003 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) + (C) 2004-2006 Luc Saillard (luc@saillard.org) NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx driver and thus may have bugs that are not present in the original version. @@ -41,12 +41,14 @@ #ifdef __KERNEL__ #include #endif #include +#include #include "pwc.h" -#include "pwc-ioctl.h" #include "pwc-uncompress.h" #include "pwc-kiara.h" #include "pwc-timon.h" +#include "pwc-dec1.h" +#include "pwc-dec23.h" /* Request types: video */ #define SET_LUM_CTL 0x01 @@ -57,6 +59,10 @@ #define SET_STATUS_CTL 0x05 #define GET_STATUS_CTL 0x06 #define SET_EP_STREAM_CTL 0x07 #define GET_EP_STREAM_CTL 0x08 +#define GET_XX_CTL 0x09 +#define SET_XX_CTL 0x0A +#define GET_XY_CTL 0x0B +#define SET_XY_CTL 0x0C #define SET_MPT_CTL 0x0D #define GET_MPT_CTL 0x0E @@ -93,12 +99,20 @@ #define READ_AGC_FORMATTER 0x0500 #define READ_SHUTTER_FORMATTER 0x0600 #define READ_RED_GAIN_FORMATTER 0x0700 #define READ_BLUE_GAIN_FORMATTER 0x0800 +#define GET_STATUS_B00 0x0B00 #define SENSOR_TYPE_FORMATTER1 0x0C00 +#define GET_STATUS_3000 0x3000 #define READ_RAW_Y_MEAN_FORMATTER 0x3100 #define SET_POWER_SAVE_MODE_FORMATTER 0x3200 #define MIRROR_IMAGE_FORMATTER 0x3300 #define LED_FORMATTER 0x3400 +#define LOWLIGHT 0x3500 +#define GET_STATUS_3600 0x3600 #define SENSOR_TYPE_FORMATTER2 0x3700 +#define GET_STATUS_3800 0x3800 +#define GET_STATUS_4000 0x4000 +#define GET_STATUS_4100 0x4100 /* Get */ +#define CTL_STATUS_4200 0x4200 /* [GS] 1 */ /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ #define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100 @@ -138,6 +152,7 @@ static struct Nala_table_entry Nala_tabl #include "pwc-nala.h" }; +static void pwc_set_image_buffer_size(struct pwc_device *pdev); /****************************************************************************/ @@ -159,31 +174,7 @@ #define RecvControlMsg(request, value, b &buf, buflen, 500) -#if PWC_DEBUG -void pwc_hexdump(void *p, int len) -{ - int i; - unsigned char *s; - char buf[100], *d; - - s = (unsigned char *)p; - d = buf; - *d = '\0'; - Debug("Doing hexdump @ %p, %d bytes.\n", p, len); - for (i = 0; i < len; i++) { - d += sprintf(d, "%02X ", *s++); - if ((i & 0xF) == 0xF) { - Debug("%s\n", buf); - d = buf; - *d = '\0'; - } - } - if ((i & 0xF) != 0) - Debug("%s\n", buf); -} -#endif - -static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen) +static int send_video_command(struct usb_device *udev, int index, void *buf, int buflen) { return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), @@ -196,7 +187,7 @@ static inline int send_video_command(str -static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) +static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) { unsigned char buf[3]; int ret, fps; @@ -229,34 +220,14 @@ static inline int set_video_mode_Nala(st if (pEntry->alternate == 0) return -EINVAL; - if (pEntry->compressed) - return -ENOENT; /* Not supported. */ - memcpy(buf, pEntry->mode, 3); ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); if (ret < 0) { - Debug("Failed to send video command... %d\n", ret); + PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret); return ret; } if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW) - { - switch(pdev->type) { - case 645: - case 646: -/* pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ - break; - - case 675: - case 680: - case 690: - case 720: - case 730: - case 740: - case 750: -/* pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ - break; - } - } + pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); pdev->cmd_len = 3; memcpy(pdev->cmd_buf, buf, 3); @@ -283,7 +254,7 @@ static inline int set_video_mode_Nala(st } -static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) +static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) { unsigned char buf[13]; const struct Timon_table_entry *pChoose; @@ -315,8 +286,8 @@ static inline int set_video_mode_Timon(s if (ret < 0) return ret; -/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) - pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ + if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) + pwc_dec23_init(pdev, pdev->type, buf); pdev->cmd_len = 13; memcpy(pdev->cmd_buf, buf, 13); @@ -336,7 +307,7 @@ static inline int set_video_mode_Timon(s } -static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) +static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) { const struct Kiara_table_entry *pChoose = NULL; int fps, ret; @@ -350,21 +321,14 @@ static inline int set_video_mode_Kiara(s fps = (frames / 5) - 1; /* special case: VGA @ 5 fps and snapshot is raw bayer mode */ - if (size == PSZ_VGA && frames == 5 && snapshot) + if (size == PSZ_VGA && frames == 5 && snapshot && pdev->vpalette == VIDEO_PALETTE_RAW) { /* Only available in case the raw palette is selected or we have the decompressor available. This mode is only available in compressed form */ - if (pdev->vpalette == VIDEO_PALETTE_RAW) - { - Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette); - pChoose = &RawEntry; - } - else - { - Info("VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.\n"); - } + PWC_DEBUG_SIZE("Choosing VGA/5 BAYER mode.\n"); + pChoose = &RawEntry; } else { @@ -372,6 +336,7 @@ static inline int set_video_mode_Kiara(s if the preferred ratio is not available. Skip this step when using RAW modes. */ + snapshot = 0; while (compression <= 3) { pChoose = &Kiara_table[size][fps][compression]; if (pChoose->alternate != 0) @@ -382,7 +347,7 @@ static inline int set_video_mode_Kiara(s if (pChoose == NULL || pChoose->alternate == 0) return -ENOENT; /* Not supported. */ - Debug("Using alternate setting %d.\n", pChoose->alternate); + PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate); /* usb_control_msg won't take staticly allocated arrays as argument?? */ memcpy(buf, pChoose->mode, 12); @@ -394,8 +359,8 @@ static inline int set_video_mode_Kiara(s if (ret < 0) return ret; -/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) - pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ + if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) + pwc_dec23_init(pdev, pdev->type, buf); pdev->cmd_len = 12; memcpy(pdev->cmd_buf, buf, 12); @@ -410,49 +375,13 @@ static inline int set_video_mode_Kiara(s pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4; else pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; + PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vsnapshot=%d, vbandlength=%d\n", + pdev->frame_size,pdev->vframes,pdev->vsize,pdev->vsnapshot,pdev->vbandlength); return 0; } -static void pwc_set_image_buffer_size(struct pwc_device *pdev) -{ - int i, factor = 0, filler = 0; - - /* for PALETTE_YUV420P */ - switch(pdev->vpalette) - { - case VIDEO_PALETTE_YUV420P: - factor = 6; - filler = 128; - break; - case VIDEO_PALETTE_RAW: - factor = 6; /* can be uncompressed YUV420P */ - filler = 0; - break; - } - - /* Set sizes in bytes */ - pdev->image.size = pdev->image.x * pdev->image.y * factor / 4; - pdev->view.size = pdev->view.x * pdev->view.y * factor / 4; - - /* Align offset, or you'll get some very weird results in - YUV420 mode... x must be multiple of 4 (to get the Y's in - place), and y even (or you'll mixup U & V). This is less of a - problem for YUV420P. - */ - pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC; - pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE; - - /* Fill buffers with gray or black */ - for (i = 0; i < MAX_IMAGES; i++) { - if (pdev->image_ptr[i] != NULL) - memset(pdev->image_ptr[i], filler, pdev->view.size); - } -} - - - /** @pdev: device structure @width: viewport width @@ -465,50 +394,78 @@ int pwc_set_video_mode(struct pwc_device { int ret, size; - Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette); + PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette); size = pwc_decode_size(pdev, width, height); if (size < 0) { - Debug("Could not find suitable size.\n"); + PWC_DEBUG_MODULE("Could not find suitable size.\n"); return -ERANGE; } - Debug("decode_size = %d.\n", size); + PWC_TRACE("decode_size = %d.\n", size); - ret = -EINVAL; - switch(pdev->type) { - case 645: - case 646: + if (DEVICE_USE_CODEC1(pdev->type)) { ret = set_video_mode_Nala(pdev, size, frames); - break; - case 675: - case 680: - case 690: - ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot); - break; - - case 720: - case 730: - case 740: - case 750: + } else if (DEVICE_USE_CODEC3(pdev->type)) { ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot); - break; + + } else { + ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot); } if (ret < 0) { - if (ret == -ENOENT) - Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames); - else { - Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); - } + PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); return ret; } pdev->view.x = width; pdev->view.y = height; pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; pwc_set_image_buffer_size(pdev); - Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y); + PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y); return 0; } +#define BLACK_Y 0 +#define BLACK_U 128 +#define BLACK_V 128 + +static void pwc_set_image_buffer_size(struct pwc_device *pdev) +{ + int i, factor = 0; + + /* for PALETTE_YUV420P */ + switch(pdev->vpalette) + { + case VIDEO_PALETTE_YUV420P: + factor = 6; + break; + case VIDEO_PALETTE_RAW: + factor = 6; /* can be uncompressed YUV420P */ + break; + } + + /* Set sizes in bytes */ + pdev->image.size = pdev->image.x * pdev->image.y * factor / 4; + pdev->view.size = pdev->view.x * pdev->view.y * factor / 4; + + /* Align offset, or you'll get some very weird results in + YUV420 mode... x must be multiple of 4 (to get the Y's in + place), and y even (or you'll mixup U & V). This is less of a + problem for YUV420P. + */ + pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC; + pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE; + + /* Fill buffers with black colors */ + for (i = 0; i < pwc_mbufs; i++) { + unsigned char *p = pdev->image_data + pdev->images[i].offset; + memset(p, BLACK_Y, pdev->view.x * pdev->view.y); + p += pdev->view.x * pdev->view.y; + memset(p, BLACK_U, pdev->view.x * pdev->view.y/4); + p += pdev->view.x * pdev->view.y/4; + memset(p, BLACK_V, pdev->view.x * pdev->view.y/4); + } +} + + /* BRIGHTNESS */ @@ -520,7 +477,7 @@ int pwc_get_brightness(struct pwc_device ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); if (ret < 0) return ret; - return buf << 9; + return buf; } int pwc_set_brightness(struct pwc_device *pdev, int value) @@ -545,7 +502,7 @@ int pwc_get_contrast(struct pwc_device * ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1); if (ret < 0) return ret; - return buf << 10; + return buf; } int pwc_set_contrast(struct pwc_device *pdev, int value) @@ -570,7 +527,7 @@ int pwc_get_gamma(struct pwc_device *pde ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1); if (ret < 0) return ret; - return buf << 11; + return buf; } int pwc_set_gamma(struct pwc_device *pdev, int value) @@ -588,37 +545,47 @@ int pwc_set_gamma(struct pwc_device *pde /* SATURATION */ -int pwc_get_saturation(struct pwc_device *pdev) +/* return a value between [-100 , 100] */ +int pwc_get_saturation(struct pwc_device *pdev, int *value) { char buf; - int ret; + int ret, saturation_register; if (pdev->type < 675) - return -1; - ret = RecvControlMsg(GET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1); + return -EINVAL; + if (pdev->type < 730) + saturation_register = SATURATION_MODE_FORMATTER2; + else + saturation_register = SATURATION_MODE_FORMATTER1; + ret = RecvControlMsg(GET_CHROM_CTL, saturation_register, 1); if (ret < 0) return ret; - return 32768 + buf * 327; + *value = (signed)buf; + return 0; } +/* @param value saturation color between [-100 , 100] */ int pwc_set_saturation(struct pwc_device *pdev, int value) { char buf; + int saturation_register; if (pdev->type < 675) return -EINVAL; - if (value < 0) - value = 0; - if (value > 0xffff) - value = 0xffff; - /* saturation ranges from -100 to +100 */ - buf = (value - 32768) / 327; - return SendControlMsg(SET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1); + if (value < -100) + value = -100; + if (value > 100) + value = 100; + if (pdev->type < 730) + saturation_register = SATURATION_MODE_FORMATTER2; + else + saturation_register = SATURATION_MODE_FORMATTER1; + return SendControlMsg(SET_CHROM_CTL, saturation_register, 1); } /* AGC */ -static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value) +int pwc_set_agc(struct pwc_device *pdev, int mode, int value) { char buf; int ret; @@ -643,7 +610,7 @@ static inline int pwc_set_agc(struct pwc return 0; } -static inline int pwc_get_agc(struct pwc_device *pdev, int *value) +int pwc_get_agc(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; @@ -673,7 +640,7 @@ static inline int pwc_get_agc(struct pwc return 0; } -static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) +int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) { char buf[2]; int speed, ret; @@ -691,23 +658,16 @@ static inline int pwc_set_shutter_speed( value = 0; if (value > 0xffff) value = 0xffff; - switch(pdev->type) { - case 675: - case 680: - case 690: + + if (DEVICE_USE_CODEC2(pdev->type)) { /* speed ranges from 0x0 to 0x290 (656) */ speed = (value / 100); buf[1] = speed >> 8; buf[0] = speed & 0xff; - break; - case 720: - case 730: - case 740: - case 750: + } else if (DEVICE_USE_CODEC3(pdev->type)) { /* speed seems to range from 0x0 to 0xff */ buf[1] = 0; buf[0] = value >> 8; - break; } ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2); @@ -715,6 +675,25 @@ static inline int pwc_set_shutter_speed( return ret; } +/* This function is not exported to v4l1, so output values between 0 -> 256 */ +int pwc_get_shutter_speed(struct pwc_device *pdev, int *value) +{ + unsigned char buf[2]; + int ret; + + ret = RecvControlMsg(GET_STATUS_CTL, READ_SHUTTER_FORMATTER, 2); + if (ret < 0) + return ret; + *value = buf[0] + (buf[1] << 8); + if (DEVICE_USE_CODEC2(pdev->type)) { + /* speed ranges from 0x0 to 0x290 (656) */ + *value *= 256/656; + } else if (DEVICE_USE_CODEC3(pdev->type)) { + /* speed seems to range from 0x0 to 0xff */ + } + return 0; +} + /* POWER */ @@ -736,19 +715,19 @@ int pwc_camera_power(struct pwc_device * /* private calls */ -static inline int pwc_restore_user(struct pwc_device *pdev) +int pwc_restore_user(struct pwc_device *pdev) { char buf; /* dummy */ return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0); } -static inline int pwc_save_user(struct pwc_device *pdev) +int pwc_save_user(struct pwc_device *pdev) { char buf; /* dummy */ return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0); } -static inline int pwc_restore_factory(struct pwc_device *pdev) +int pwc_restore_factory(struct pwc_device *pdev) { char buf; /* dummy */ return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0); @@ -766,7 +745,7 @@ static inline int pwc_restore_factory(st * 03: manual * 04: auto */ -static inline int pwc_set_awb(struct pwc_device *pdev, int mode) +int pwc_set_awb(struct pwc_device *pdev, int mode) { char buf; int ret; @@ -786,7 +765,7 @@ static inline int pwc_set_awb(struct pwc return 0; } -static inline int pwc_get_awb(struct pwc_device *pdev) +int pwc_get_awb(struct pwc_device *pdev) { unsigned char buf; int ret; @@ -798,7 +777,7 @@ static inline int pwc_get_awb(struct pwc return buf; } -static inline int pwc_set_red_gain(struct pwc_device *pdev, int value) +int pwc_set_red_gain(struct pwc_device *pdev, int value) { unsigned char buf; @@ -811,7 +790,7 @@ static inline int pwc_set_red_gain(struc return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); } -static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value) +int pwc_get_red_gain(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; @@ -824,7 +803,7 @@ static inline int pwc_get_red_gain(struc } -static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value) +int pwc_set_blue_gain(struct pwc_device *pdev, int value) { unsigned char buf; @@ -837,7 +816,7 @@ static inline int pwc_set_blue_gain(stru return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); } -static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value) +int pwc_get_blue_gain(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; @@ -854,7 +833,7 @@ static inline int pwc_get_blue_gain(stru internal red/blue gains, which may be different from the manual gains set or read above. */ -static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value) +static int pwc_read_red_gain(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; @@ -866,7 +845,7 @@ static inline int pwc_read_red_gain(stru return 0; } -static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value) +static int pwc_read_blue_gain(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; @@ -879,7 +858,7 @@ static inline int pwc_read_blue_gain(str } -static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed) +static int pwc_set_wb_speed(struct pwc_device *pdev, int speed) { unsigned char buf; @@ -888,7 +867,7 @@ static inline int pwc_set_wb_speed(struc return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); } -static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value) +static int pwc_get_wb_speed(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; @@ -901,7 +880,7 @@ static inline int pwc_get_wb_speed(struc } -static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay) +static int pwc_set_wb_delay(struct pwc_device *pdev, int delay) { unsigned char buf; @@ -910,7 +889,7 @@ static inline int pwc_set_wb_delay(struc return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); } -static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value) +static int pwc_get_wb_delay(struct pwc_device *pdev, int *value) { unsigned char buf; int ret; @@ -965,7 +944,7 @@ static int pwc_get_leds(struct pwc_devic return 0; } -static inline int pwc_set_contour(struct pwc_device *pdev, int contour) +int pwc_set_contour(struct pwc_device *pdev, int contour) { unsigned char buf; int ret; @@ -990,7 +969,7 @@ static inline int pwc_set_contour(struct return 0; } -static inline int pwc_get_contour(struct pwc_device *pdev, int *contour) +int pwc_get_contour(struct pwc_device *pdev, int *contour) { unsigned char buf; int ret; @@ -1012,7 +991,7 @@ static inline int pwc_get_contour(struct } -static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight) +int pwc_set_backlight(struct pwc_device *pdev, int backlight) { unsigned char buf; @@ -1023,7 +1002,7 @@ static inline int pwc_set_backlight(stru return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); } -static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight) +int pwc_get_backlight(struct pwc_device *pdev, int *backlight) { int ret; unsigned char buf; @@ -1031,12 +1010,35 @@ static inline int pwc_get_backlight(stru ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); if (ret < 0) return ret; - *backlight = buf; + *backlight = !!buf; return 0; } +int pwc_set_colour_mode(struct pwc_device *pdev, int colour) +{ + unsigned char buf; -static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker) + if (colour) + buf = 0xff; + else + buf = 0x0; + return SendControlMsg(SET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1); +} + +int pwc_get_colour_mode(struct pwc_device *pdev, int *colour) +{ + int ret; + unsigned char buf; + + ret = RecvControlMsg(GET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1); + if (ret < 0) + return ret; + *colour = !!buf; + return 0; +} + + +int pwc_set_flicker(struct pwc_device *pdev, int flicker) { unsigned char buf; @@ -1047,7 +1049,7 @@ static inline int pwc_set_flicker(struct return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); } -static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker) +int pwc_get_flicker(struct pwc_device *pdev, int *flicker) { int ret; unsigned char buf; @@ -1055,12 +1057,11 @@ static inline int pwc_get_flicker(struct ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); if (ret < 0) return ret; - *flicker = buf; + *flicker = !!buf; return 0; } - -static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise) +int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise) { unsigned char buf; @@ -1072,7 +1073,7 @@ static inline int pwc_set_dynamic_noise( return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); } -static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) +int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) { int ret; unsigned char buf; @@ -1084,7 +1085,7 @@ static inline int pwc_get_dynamic_noise( return 0; } -static int pwc_mpt_reset(struct pwc_device *pdev, int flags) +static int _pwc_mpt_reset(struct pwc_device *pdev, int flags) { unsigned char buf; @@ -1092,7 +1093,18 @@ static int pwc_mpt_reset(struct pwc_devi return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1); } -static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) +int pwc_mpt_reset(struct pwc_device *pdev, int flags) +{ + int ret; + ret = _pwc_mpt_reset(pdev, flags); + if (ret >= 0) { + pdev->pan_angle = 0; + pdev->tilt_angle = 0; + } + return ret; +} + +static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) { unsigned char buf[4]; @@ -1110,7 +1122,35 @@ static inline int pwc_mpt_set_angle(stru return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4); } -static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status) +int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) +{ + int ret; + + /* check absolute ranges */ + if (pan < pdev->angle_range.pan_min || + pan > pdev->angle_range.pan_max || + tilt < pdev->angle_range.tilt_min || + tilt > pdev->angle_range.tilt_max) + return -ERANGE; + + /* go to relative range, check again */ + pan -= pdev->pan_angle; + tilt -= pdev->tilt_angle; + /* angles are specified in degrees * 100, thus the limit = 36000 */ + if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000) + return -ERANGE; + + ret = _pwc_mpt_set_angle(pdev, pan, tilt); + if (ret >= 0) { + pdev->pan_angle += pan; + pdev->tilt_angle += tilt; + } + if (ret == -EPIPE) /* stall -> out of range */ + ret = -ERANGE; + return ret; +} + +static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status) { int ret; unsigned char buf[5]; @@ -1151,6 +1191,26 @@ int pwc_get_cmos_sensor(struct pwc_devic /* End of Add-Ons */ /* ************************************************* */ +/* Linux 2.5.something and 2.6 pass direct pointers to arguments of + ioctl() calls. With 2.4, you have to do tedious copy_from_user() + and copy_to_user() calls. With these macros we circumvent this, + and let me maintain only one source file. The functionality is + exactly the same otherwise. + */ + + +/* define local variable for arg */ +#define ARG_DEF(ARG_type, ARG_name)\ + ARG_type *ARG_name = arg; +/* copy arg to local variable */ +#define ARG_IN(ARG_name) /* nothing */ +/* argument itself (referenced) */ +#define ARGR(ARG_name) (*ARG_name) +/* argument address */ +#define ARGA(ARG_name) ARG_name +/* copy local variable to arg */ +#define ARG_OUT(ARG_name) /* nothing */ + int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) { @@ -1180,206 +1240,243 @@ int pwc_ioctl(struct pwc_device *pdev, u case VIDIOCPWCSCQUAL: { - int *qual = arg; + ARG_DEF(int, qual) - if (*qual < 0 || *qual > 3) + ARG_IN(qual) + if (ARGR(qual) < 0 || ARGR(qual) > 3) ret = -EINVAL; else - ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot); + ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); if (ret >= 0) - pdev->vcompression = *qual; + pdev->vcompression = ARGR(qual); break; } case VIDIOCPWCGCQUAL: { - int *qual = arg; - *qual = pdev->vcompression; + ARG_DEF(int, qual) + + ARGR(qual) = pdev->vcompression; + ARG_OUT(qual) break; } case VIDIOCPWCPROBE: { - struct pwc_probe *probe = arg; - strcpy(probe->name, pdev->vdev->name); - probe->type = pdev->type; + ARG_DEF(struct pwc_probe, probe) + + strcpy(ARGR(probe).name, pdev->vdev->name); + ARGR(probe).type = pdev->type; + ARG_OUT(probe) break; } case VIDIOCPWCGSERIAL: { - struct pwc_serial *serial = arg; - strcpy(serial->serial, pdev->serial); + ARG_DEF(struct pwc_serial, serial) + + strcpy(ARGR(serial).serial, pdev->serial); + ARG_OUT(serial) break; } case VIDIOCPWCSAGC: { - int *agc = arg; - if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc)) + ARG_DEF(int, agc) + + ARG_IN(agc) + if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc))) ret = -EINVAL; break; } case VIDIOCPWCGAGC: { - int *agc = arg; + ARG_DEF(int, agc) - if (pwc_get_agc(pdev, agc)) + if (pwc_get_agc(pdev, ARGA(agc))) ret = -EINVAL; + ARG_OUT(agc) break; } case VIDIOCPWCSSHUTTER: { - int *shutter_speed = arg; - ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed); + ARG_DEF(int, shutter_speed) + + ARG_IN(shutter_speed) + ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed)); break; } case VIDIOCPWCSAWB: { - struct pwc_whitebalance *wb = arg; + ARG_DEF(struct pwc_whitebalance, wb) - ret = pwc_set_awb(pdev, wb->mode); - if (ret >= 0 && wb->mode == PWC_WB_MANUAL) { - pwc_set_red_gain(pdev, wb->manual_red); - pwc_set_blue_gain(pdev, wb->manual_blue); + ARG_IN(wb) + ret = pwc_set_awb(pdev, ARGR(wb).mode); + if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) { + pwc_set_red_gain(pdev, ARGR(wb).manual_red); + pwc_set_blue_gain(pdev, ARGR(wb).manual_blue); } break; } case VIDIOCPWCGAWB: { - struct pwc_whitebalance *wb = arg; + ARG_DEF(struct pwc_whitebalance, wb) - memset(wb, 0, sizeof(struct pwc_whitebalance)); - wb->mode = pwc_get_awb(pdev); - if (wb->mode < 0) + memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance)); + ARGR(wb).mode = pwc_get_awb(pdev); + if (ARGR(wb).mode < 0) ret = -EINVAL; else { - if (wb->mode == PWC_WB_MANUAL) { - ret = pwc_get_red_gain(pdev, &wb->manual_red); + if (ARGR(wb).mode == PWC_WB_MANUAL) { + ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red); if (ret < 0) break; - ret = pwc_get_blue_gain(pdev, &wb->manual_blue); + ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue); if (ret < 0) break; } - if (wb->mode == PWC_WB_AUTO) { - ret = pwc_read_red_gain(pdev, &wb->read_red); + if (ARGR(wb).mode == PWC_WB_AUTO) { + ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red); if (ret < 0) break; - ret = pwc_read_blue_gain(pdev, &wb->read_blue); + ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue); if (ret < 0) break; } } + ARG_OUT(wb) break; } case VIDIOCPWCSAWBSPEED: { - struct pwc_wb_speed *wbs = arg; + ARG_DEF(struct pwc_wb_speed, wbs) - if (wbs->control_speed > 0) { - ret = pwc_set_wb_speed(pdev, wbs->control_speed); + if (ARGR(wbs).control_speed > 0) { + ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed); } - if (wbs->control_delay > 0) { - ret = pwc_set_wb_delay(pdev, wbs->control_delay); + if (ARGR(wbs).control_delay > 0) { + ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay); } break; } case VIDIOCPWCGAWBSPEED: { - struct pwc_wb_speed *wbs = arg; + ARG_DEF(struct pwc_wb_speed, wbs) - ret = pwc_get_wb_speed(pdev, &wbs->control_speed); + ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed); if (ret < 0) break; - ret = pwc_get_wb_delay(pdev, &wbs->control_delay); + ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay); if (ret < 0) break; + ARG_OUT(wbs) break; } case VIDIOCPWCSLED: { - struct pwc_leds *leds = arg; - ret = pwc_set_leds(pdev, leds->led_on, leds->led_off); - break; + ARG_DEF(struct pwc_leds, leds) + + ARG_IN(leds) + ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off); + break; } case VIDIOCPWCGLED: { - struct pwc_leds *leds = arg; - ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off); + ARG_DEF(struct pwc_leds, leds) + + ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off); + ARG_OUT(leds) break; } case VIDIOCPWCSCONTOUR: { - int *contour = arg; - ret = pwc_set_contour(pdev, *contour); + ARG_DEF(int, contour) + + ARG_IN(contour) + ret = pwc_set_contour(pdev, ARGR(contour)); break; } case VIDIOCPWCGCONTOUR: { - int *contour = arg; - ret = pwc_get_contour(pdev, contour); + ARG_DEF(int, contour) + + ret = pwc_get_contour(pdev, ARGA(contour)); + ARG_OUT(contour) break; } case VIDIOCPWCSBACKLIGHT: { - int *backlight = arg; - ret = pwc_set_backlight(pdev, *backlight); + ARG_DEF(int, backlight) + + ARG_IN(backlight) + ret = pwc_set_backlight(pdev, ARGR(backlight)); break; } case VIDIOCPWCGBACKLIGHT: { - int *backlight = arg; - ret = pwc_get_backlight(pdev, backlight); + ARG_DEF(int, backlight) + + ret = pwc_get_backlight(pdev, ARGA(backlight)); + ARG_OUT(backlight) break; } case VIDIOCPWCSFLICKER: { - int *flicker = arg; - ret = pwc_set_flicker(pdev, *flicker); + ARG_DEF(int, flicker) + + ARG_IN(flicker) + ret = pwc_set_flicker(pdev, ARGR(flicker)); break; } case VIDIOCPWCGFLICKER: { - int *flicker = arg; - ret = pwc_get_flicker(pdev, flicker); + ARG_DEF(int, flicker) + + ret = pwc_get_flicker(pdev, ARGA(flicker)); + ARG_OUT(flicker) break; } case VIDIOCPWCSDYNNOISE: { - int *dynnoise = arg; - ret = pwc_set_dynamic_noise(pdev, *dynnoise); + ARG_DEF(int, dynnoise) + + ARG_IN(dynnoise) + ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise)); break; } case VIDIOCPWCGDYNNOISE: { - int *dynnoise = arg; - ret = pwc_get_dynamic_noise(pdev, dynnoise); + ARG_DEF(int, dynnoise) + + ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise)); + ARG_OUT(dynnoise); break; } case VIDIOCPWCGREALSIZE: { - struct pwc_imagesize *size = arg; - size->width = pdev->image.x; - size->height = pdev->image.y; + ARG_DEF(struct pwc_imagesize, size) + + ARGR(size).width = pdev->image.x; + ARGR(size).height = pdev->image.y; + ARG_OUT(size) break; } @@ -1387,14 +1484,10 @@ int pwc_ioctl(struct pwc_device *pdev, u { if (pdev->features & FEATURE_MOTOR_PANTILT) { - int *flags = arg; + ARG_DEF(int, flags) - ret = pwc_mpt_reset(pdev, *flags); - if (ret >= 0) - { - pdev->pan_angle = 0; - pdev->tilt_angle = 0; - } + ARG_IN(flags) + ret = pwc_mpt_reset(pdev, ARGR(flags)); } else { @@ -1407,8 +1500,10 @@ int pwc_ioctl(struct pwc_device *pdev, u { if (pdev->features & FEATURE_MOTOR_PANTILT) { - struct pwc_mpt_range *range = arg; - *range = pdev->angle_range; + ARG_DEF(struct pwc_mpt_range, range) + + ARGR(range) = pdev->angle_range; + ARG_OUT(range) } else { @@ -1423,48 +1518,23 @@ int pwc_ioctl(struct pwc_device *pdev, u if (pdev->features & FEATURE_MOTOR_PANTILT) { - struct pwc_mpt_angles *angles = arg; + ARG_DEF(struct pwc_mpt_angles, angles) + + ARG_IN(angles) /* The camera can only set relative angles, so do some calculations when getting an absolute angle . */ - if (angles->absolute) + if (ARGR(angles).absolute) { - new_pan = angles->pan; - new_tilt = angles->tilt; + new_pan = ARGR(angles).pan; + new_tilt = ARGR(angles).tilt; } else { - new_pan = pdev->pan_angle + angles->pan; - new_tilt = pdev->tilt_angle + angles->tilt; - } - /* check absolute ranges */ - if (new_pan < pdev->angle_range.pan_min || - new_pan > pdev->angle_range.pan_max || - new_tilt < pdev->angle_range.tilt_min || - new_tilt > pdev->angle_range.tilt_max) - { - ret = -ERANGE; - } - else - { - /* go to relative range, check again */ - new_pan -= pdev->pan_angle; - new_tilt -= pdev->tilt_angle; - /* angles are specified in degrees * 100, thus the limit = 36000 */ - if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000) - ret = -ERANGE; - } - if (ret == 0) /* no errors so far */ - { - ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt); - if (ret >= 0) - { - pdev->pan_angle += new_pan; - pdev->tilt_angle += new_tilt; - } - if (ret == -EPIPE) /* stall -> out of range */ - ret = -ERANGE; + new_pan = pdev->pan_angle + ARGR(angles).pan; + new_tilt = pdev->tilt_angle + ARGR(angles).tilt; } + ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt); } else { @@ -1478,11 +1548,12 @@ int pwc_ioctl(struct pwc_device *pdev, u if (pdev->features & FEATURE_MOTOR_PANTILT) { - struct pwc_mpt_angles *angles = arg; + ARG_DEF(struct pwc_mpt_angles, angles) - angles->absolute = 1; - angles->pan = pdev->pan_angle; - angles->tilt = pdev->tilt_angle; + ARGR(angles).absolute = 1; + ARGR(angles).pan = pdev->pan_angle; + ARGR(angles).tilt = pdev->tilt_angle; + ARG_OUT(angles) } else { @@ -1495,8 +1566,10 @@ int pwc_ioctl(struct pwc_device *pdev, u { if (pdev->features & FEATURE_MOTOR_PANTILT) { - struct pwc_mpt_status *status = arg; - ret = pwc_mpt_get_status(pdev, status); + ARG_DEF(struct pwc_mpt_status, status) + + ret = pwc_mpt_get_status(pdev, ARGA(status)); + ARG_OUT(status) } else { @@ -1507,22 +1580,24 @@ int pwc_ioctl(struct pwc_device *pdev, u case VIDIOCPWCGVIDCMD: { - struct pwc_video_command *cmd = arg; - - cmd->type = pdev->type; - cmd->release = pdev->release; - cmd->command_len = pdev->cmd_len; - memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len); - cmd->bandlength = pdev->vbandlength; - cmd->frame_size = pdev->frame_size; + ARG_DEF(struct pwc_video_command, cmd); + + ARGR(cmd).type = pdev->type; + ARGR(cmd).release = pdev->release; + ARGR(cmd).command_len = pdev->cmd_len; + memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len); + ARGR(cmd).bandlength = pdev->vbandlength; + ARGR(cmd).frame_size = pdev->frame_size; + ARG_OUT(cmd) break; } /* case VIDIOCPWCGVIDTABLE: { - struct pwc_table_init_buffer *table = arg; - table->len = pdev->cmd_len; - memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size); + ARG_DEF(struct pwc_table_init_buffer, table); + ARGR(table).len = pdev->cmd_len; + memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size); + ARG_OUT(table) break; } */ @@ -1538,4 +1613,4 @@ int pwc_ioctl(struct pwc_device *pdev, u } - +/* vim: set cinoptions= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ diff --git a/drivers/media/video/pwc/pwc-dec1.c b/drivers/media/video/pwc/pwc-dec1.c new file mode 100644 index 0000000..c29593f --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec1.c @@ -0,0 +1,50 @@ +/* Linux driver for Philips webcam + Decompression for chipset version 1 + (C) 2004-2006 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + +#include "pwc-dec1.h" + + +void pwc_dec1_init(int type, int release, void *buffer, void *table) +{ + +} + +void pwc_dec1_exit(void) +{ + + + +} + +int pwc_dec1_alloc(struct pwc_device *pwc) +{ + pwc->decompress_data = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL); + if (pwc->decompress_data == NULL) + return -ENOMEM; + return 0; +} + diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/video/pwc/pwc-dec1.h new file mode 100644 index 0000000..8b62ddc --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec1.h @@ -0,0 +1,43 @@ +/* Linux driver for Philips webcam + (C) 2004-2006 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + +#ifndef PWC_DEC1_H +#define PWC_DEC1_H + +#include "pwc.h" + +struct pwc_dec1_private +{ + int version; + +}; + +int pwc_dec1_alloc(struct pwc_device *pwc); +void pwc_dec1_init(int type, int release, void *buffer, void *private_data); +void pwc_dec1_exit(void); + +#endif + diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c new file mode 100644 index 0000000..9e2d91f --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec23.c @@ -0,0 +1,941 @@ +/* Linux driver for Philips webcam + Decompression for chipset version 2 et 3 + (C) 2004-2006 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "pwc-timon.h" +#include "pwc-kiara.h" +#include "pwc-dec23.h" +#include + +#include + +/* + * USE_LOOKUP_TABLE_TO_CLAMP + * 0: use a C version of this tests: { a<0?0:(a>255?255:a) } + * 1: use a faster lookup table for cpu with a big cache (intel) + */ +#define USE_LOOKUP_TABLE_TO_CLAMP 1 +/* + * UNROLL_LOOP_FOR_COPYING_BLOCK + * 0: use a loop for a smaller code (but little slower) + * 1: when unrolling the loop, gcc produces some faster code (perhaps only + * valid for intel processor class). Activating this option, automaticaly + * activate USE_LOOKUP_TABLE_TO_CLAMP + */ +#define UNROLL_LOOP_FOR_COPY 1 +#if UNROLL_LOOP_FOR_COPY +# undef USE_LOOKUP_TABLE_TO_CLAMP +# define USE_LOOKUP_TABLE_TO_CLAMP 1 +#endif + +/* + * ENABLE_BAYER_DECODER + * 0: bayer decoder is not build (save some space) + * 1: bayer decoder is build and can be used + */ +#define ENABLE_BAYER_DECODER 0 + +static void build_subblock_pattern(struct pwc_dec23_private *pdec) +{ + static const unsigned int initial_values[12] = { + -0x526500, -0x221200, 0x221200, 0x526500, + -0x3de200, 0x3de200, + -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480, + -0x12c200, 0x12c200 + + }; + static const unsigned int values_derivated[12] = { + 0xa4ca, 0x4424, -0x4424, -0xa4ca, + 0x7bc4, -0x7bc4, + 0xdb69, 0x5aba, -0x5aba, -0xdb69, + 0x2584, -0x2584 + }; + unsigned int temp_values[12]; + int i, j; + + memcpy(temp_values, initial_values, sizeof(initial_values)); + for (i = 0; i < 256; i++) { + for (j = 0; j < 12; j++) { + pdec->table_subblock[i][j] = temp_values[j]; + temp_values[j] += values_derivated[j]; + } + } +} + +static void build_bit_powermask_table(struct pwc_dec23_private *pdec) +{ + unsigned char *p; + unsigned int bit, byte, mask, val; + unsigned int bitpower = 1; + + for (bit = 0; bit < 8; bit++) { + mask = bitpower - 1; + p = pdec->table_bitpowermask[bit]; + for (byte = 0; byte < 256; byte++) { + val = (byte & mask); + if (byte & bitpower) + val = -val; + *p++ = val; + } + bitpower<<=1; + } +} + + +static void build_table_color(const unsigned int romtable[16][8], + unsigned char p0004[16][1024], + unsigned char p8004[16][256]) +{ + int compression_mode, j, k, bit, pw; + unsigned char *p0, *p8; + const unsigned int *r; + + /* We have 16 compressions tables */ + for (compression_mode = 0; compression_mode < 16; compression_mode++) { + p0 = p0004[compression_mode]; + p8 = p8004[compression_mode]; + r = romtable[compression_mode]; + + for (j = 0; j < 8; j++, r++, p0 += 128) { + + for (k = 0; k < 16; k++) { + if (k == 0) + bit = 1; + else if (k >= 1 && k < 3) + bit = (r[0] >> 15) & 7; + else if (k >= 3 && k < 6) + bit = (r[0] >> 12) & 7; + else if (k >= 6 && k < 10) + bit = (r[0] >> 9) & 7; + else if (k >= 10 && k < 13) + bit = (r[0] >> 6) & 7; + else if (k >= 13 && k < 15) + bit = (r[0] >> 3) & 7; + else + bit = (r[0]) & 7; + if (k == 0) + *p8++ = 8; + else + *p8++ = j - bit; + *p8++ = bit; + + pw = 1 << bit; + p0[k + 0x00] = (1 * pw) + 0x80; + p0[k + 0x10] = (2 * pw) + 0x80; + p0[k + 0x20] = (3 * pw) + 0x80; + p0[k + 0x30] = (4 * pw) + 0x80; + p0[k + 0x40] = (-1 * pw) + 0x80; + p0[k + 0x50] = (-2 * pw) + 0x80; + p0[k + 0x60] = (-3 * pw) + 0x80; + p0[k + 0x70] = (-4 * pw) + 0x80; + } /* end of for (k=0; k<16; k++, p8++) */ + } /* end of for (j=0; j<8; j++ , table++) */ + } /* end of foreach compression_mode */ +} + +/* + * + */ +static void fill_table_dc00_d800(struct pwc_dec23_private *pdec) +{ +#define SCALEBITS 15 +#define ONE_HALF (1UL << (SCALEBITS - 1)) + int i; + unsigned int offset1 = ONE_HALF; + unsigned int offset2 = 0x0000; + + for (i=0; i<256; i++) { + pdec->table_dc00[i] = offset1 & ~(ONE_HALF); + pdec->table_d800[i] = offset2; + + offset1 += 0x7bc4; + offset2 += 0x7bc4; + } +} + +/* + * To decode the stream: + * if look_bits(2) == 0: # op == 2 in the lookup table + * skip_bits(2) + * end of the stream + * elif look_bits(3) == 7: # op == 1 in the lookup table + * skip_bits(3) + * yyyy = get_bits(4) + * xxxx = get_bits(8) + * else: # op == 0 in the lookup table + * skip_bits(x) + * + * For speedup processing, we build a lookup table and we takes the first 6 bits. + * + * struct { + * unsigned char op; // operation to execute + * unsigned char bits; // bits use to perform operation + * unsigned char offset1; // offset to add to access in the table_0004 % 16 + * unsigned char offset2; // offset to add to access in the table_0004 + * } + * + * How to build this table ? + * op == 2 when (i%4)==0 + * op == 1 when (i%8)==7 + * op == 0 otherwise + * + */ +static const unsigned char hash_table_ops[64*4] = { + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x10, + 0x00, 0x06, 0x01, 0x30, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x01, 0x20, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x50, + 0x00, 0x05, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x03, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x10, + 0x00, 0x06, 0x02, 0x10, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x01, 0x60, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x50, + 0x00, 0x05, 0x02, 0x40, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x03, 0x40, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x10, + 0x00, 0x06, 0x01, 0x70, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x01, 0x20, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x50, + 0x00, 0x05, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x03, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x10, + 0x00, 0x06, 0x02, 0x50, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x01, 0x60, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x50, + 0x00, 0x05, 0x02, 0x40, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x03, 0x40, + 0x01, 0x00, 0x00, 0x00 +}; + +/* + * + */ +static const unsigned int MulIdx[16][16] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,}, + {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,}, + {4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,}, + {6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,}, + {4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,}, + {1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,}, + {0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,}, + {0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,}, + {1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,}, + {7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,}, + {4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,}, + {7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,}, + {1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,}, + {1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,}, + {10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10} +}; + +#if USE_LOOKUP_TABLE_TO_CLAMP +#define MAX_OUTER_CROP_VALUE (512) +static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE]; +#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)]) +#else +#define CLAMP(x) ((x)>255?255:((x)<0?0:x)) +#endif + + +/* If the type or the command change, we rebuild the lookup table */ +int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd) +{ + int flags, version, shift, i; + struct pwc_dec23_private *pdec; + + if (pwc->decompress_data == NULL) { + pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); + if (pdec == NULL) + return -ENOMEM; + pwc->decompress_data = pdec; + } + pdec = pwc->decompress_data; + + if (DEVICE_USE_CODEC3(type)) { + flags = cmd[2] & 0x18; + if (flags == 8) + pdec->nbits = 7; /* More bits, mean more bits to encode the stream, but better quality */ + else if (flags == 0x10) + pdec->nbits = 8; + else + pdec->nbits = 6; + + version = cmd[2] >> 5; + build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1); + build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2); + + } else { + + flags = cmd[2] & 6; + if (flags == 2) + pdec->nbits = 7; + else if (flags == 4) + pdec->nbits = 8; + else + pdec->nbits = 6; + + version = cmd[2] >> 3; + build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1); + build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2); + } + + /* Informations can be coded on a variable number of bits but never less than 8 */ + shift = 8 - pdec->nbits; + pdec->scalebits = SCALEBITS - shift; + pdec->nbitsmask = 0xFF >> shift; + + fill_table_dc00_d800(pdec); + build_subblock_pattern(pdec); + build_bit_powermask_table(pdec); + +#if USE_LOOKUP_TABLE_TO_CLAMP + /* Build the static table to clamp value [0-255] */ + for (i=0;i> scalebits]; + *d++ = cm[c[1] >> scalebits]; + *d++ = cm[c[2] >> scalebits]; + *d++ = cm[c[3] >> scalebits]; + + d = dst + bytes_per_line; + *d++ = cm[c[4] >> scalebits]; + *d++ = cm[c[5] >> scalebits]; + *d++ = cm[c[6] >> scalebits]; + *d++ = cm[c[7] >> scalebits]; + + d = dst + bytes_per_line*2; + *d++ = cm[c[8] >> scalebits]; + *d++ = cm[c[9] >> scalebits]; + *d++ = cm[c[10] >> scalebits]; + *d++ = cm[c[11] >> scalebits]; + + d = dst + bytes_per_line*3; + *d++ = cm[c[12] >> scalebits]; + *d++ = cm[c[13] >> scalebits]; + *d++ = cm[c[14] >> scalebits]; + *d++ = cm[c[15] >> scalebits]; +#else + int i; + const int *c = src; + unsigned char *d = dst; + for (i = 0; i < 4; i++, c++) + *d++ = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line; + for (i = 0; i < 4; i++, c++) + *d++ = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line*2; + for (i = 0; i < 4; i++, c++) + *d++ = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line*3; + for (i = 0; i < 4; i++, c++) + *d++ = CLAMP((*c) >> scalebits); +#endif +} + +/* + * Copy the 4x4 image block to a CrCb plane buffer + * + */ +static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) +{ +#if UNROLL_LOOP_FOR_COPY + /* Unroll all loops */ + const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; + const int *c = src; + unsigned char *d = dst; + + *d++ = cm[c[0] >> scalebits]; + *d++ = cm[c[4] >> scalebits]; + *d++ = cm[c[1] >> scalebits]; + *d++ = cm[c[5] >> scalebits]; + *d++ = cm[c[2] >> scalebits]; + *d++ = cm[c[6] >> scalebits]; + *d++ = cm[c[3] >> scalebits]; + *d++ = cm[c[7] >> scalebits]; + + d = dst + bytes_per_line; + *d++ = cm[c[12] >> scalebits]; + *d++ = cm[c[8] >> scalebits]; + *d++ = cm[c[13] >> scalebits]; + *d++ = cm[c[9] >> scalebits]; + *d++ = cm[c[14] >> scalebits]; + *d++ = cm[c[10] >> scalebits]; + *d++ = cm[c[15] >> scalebits]; + *d++ = cm[c[11] >> scalebits]; +#else + int i; + const int *c1 = src; + const int *c2 = src + 4; + unsigned char *d = dst; + + for (i = 0; i < 4; i++, c1++, c2++) { + *d++ = CLAMP((*c1) >> scalebits); + *d++ = CLAMP((*c2) >> scalebits); + } + c1 = src + 12; + d = dst + bytes_per_line; + for (i = 0; i < 4; i++, c1++, c2++) { + *d++ = CLAMP((*c1) >> scalebits); + *d++ = CLAMP((*c2) >> scalebits); + } +#endif +} + +#if ENABLE_BAYER_DECODER +/* + * Format: 8x2 pixels + * . G . G . G . G . G . G . G + * . . . . . . . . . . . . . . + * . G . G . G . G . G . G . G + * . . . . . . . . . . . . . . + * or + * . . . . . . . . . . . . . . + * G . G . G . G . G . G . G . + * . . . . . . . . . . . . . . + * G . G . G . G . G . G . G . +*/ +static void copy_image_block_Green(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) +{ +#if UNROLL_LOOP_FOR_COPY + /* Unroll all loops */ + const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; + unsigned char *d = dst; + const int *c = src; + + d[0] = cm[c[0] >> scalebits]; + d[2] = cm[c[1] >> scalebits]; + d[4] = cm[c[2] >> scalebits]; + d[6] = cm[c[3] >> scalebits]; + d[8] = cm[c[4] >> scalebits]; + d[10] = cm[c[5] >> scalebits]; + d[12] = cm[c[6] >> scalebits]; + d[14] = cm[c[7] >> scalebits]; + + d = dst + bytes_per_line; + d[0] = cm[c[8] >> scalebits]; + d[2] = cm[c[9] >> scalebits]; + d[4] = cm[c[10] >> scalebits]; + d[6] = cm[c[11] >> scalebits]; + d[8] = cm[c[12] >> scalebits]; + d[10] = cm[c[13] >> scalebits]; + d[12] = cm[c[14] >> scalebits]; + d[14] = cm[c[15] >> scalebits]; +#else + int i; + unsigned char *d; + const int *c = src; + + d = dst; + for (i = 0; i < 8; i++, c++) + d[i*2] = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line; + for (i = 0; i < 8; i++, c++) + d[i*2] = CLAMP((*c) >> scalebits); +#endif +} +#endif + +#if ENABLE_BAYER_DECODER +/* + * Format: 4x4 pixels + * R . R . R . R + * . B . B . B . + * R . R . R . R + * . B . B . B . + */ +static void copy_image_block_RedBlue(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) +{ +#if UNROLL_LOOP_FOR_COPY + /* Unroll all loops */ + const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; + unsigned char *d = dst; + const int *c = src; + + d[0] = cm[c[0] >> scalebits]; + d[2] = cm[c[1] >> scalebits]; + d[4] = cm[c[2] >> scalebits]; + d[6] = cm[c[3] >> scalebits]; + + d = dst + bytes_per_line; + d[1] = cm[c[4] >> scalebits]; + d[3] = cm[c[5] >> scalebits]; + d[5] = cm[c[6] >> scalebits]; + d[7] = cm[c[7] >> scalebits]; + + d = dst + bytes_per_line*2; + d[0] = cm[c[8] >> scalebits]; + d[2] = cm[c[9] >> scalebits]; + d[4] = cm[c[10] >> scalebits]; + d[6] = cm[c[11] >> scalebits]; + + d = dst + bytes_per_line*3; + d[1] = cm[c[12] >> scalebits]; + d[3] = cm[c[13] >> scalebits]; + d[5] = cm[c[14] >> scalebits]; + d[7] = cm[c[15] >> scalebits]; +#else + int i; + unsigned char *d; + const int *c = src; + + d = dst; + for (i = 0; i < 4; i++, c++) + d[i*2] = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line; + for (i = 0; i < 4; i++, c++) + d[i*2+1] = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line*2; + for (i = 0; i < 4; i++, c++) + d[i*2] = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line*3; + for (i = 0; i < 4; i++, c++) + d[i*2+1] = CLAMP((*c) >> scalebits); +#endif +} +#endif + +/* + * To manage the stream, we keep bits in a 32 bits register. + * fill_nbits(n): fill the reservoir with at least n bits + * skip_bits(n): discard n bits from the reservoir + * get_bits(n): fill the reservoir, returns the first n bits and discard the + * bits from the reservoir. + * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir + * contains at least n bits. bits returned is discarded. + */ +#define fill_nbits(pdec, nbits_wanted) do { \ + while (pdec->nbits_in_reservoir<(nbits_wanted)) \ + { \ + pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \ + pdec->nbits_in_reservoir += 8; \ + } \ +} while(0); + +#define skip_nbits(pdec, nbits_to_skip) do { \ + pdec->reservoir >>= (nbits_to_skip); \ + pdec->nbits_in_reservoir -= (nbits_to_skip); \ +} while(0); + +#define get_nbits(pdec, nbits_wanted, result) do { \ + fill_nbits(pdec, nbits_wanted); \ + result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \ + skip_nbits(pdec, nbits_wanted); \ +} while(0); + +#define __get_nbits(pdec, nbits_wanted, result) do { \ + result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \ + skip_nbits(pdec, nbits_wanted); \ +} while(0); + +#define look_nbits(pdec, nbits_wanted) \ + ((pdec->reservoir) & ((1U<<(nbits_wanted))-1)) + +/* + * Decode a 4x4 pixel block + */ +static void decode_block(struct pwc_dec23_private *pdec, + const unsigned char *ptable0004, + const unsigned char *ptable8004) +{ + unsigned int primary_color; + unsigned int channel_v, offset1, op; + int i; + + fill_nbits(pdec, 16); + __get_nbits(pdec, pdec->nbits, primary_color); + + if (look_nbits(pdec,2) == 0) { + skip_nbits(pdec, 2); + /* Very simple, the color is the same for all pixels of the square */ + for (i = 0; i < 16; i++) + pdec->temp_colors[i] = pdec->table_dc00[primary_color]; + + return; + } + + /* This block is encoded with small pattern */ + for (i = 0; i < 16; i++) + pdec->temp_colors[i] = pdec->table_d800[primary_color]; + + __get_nbits(pdec, 3, channel_v); + channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2); + + ptable0004 += (channel_v * 128); + ptable8004 += (channel_v * 32); + + offset1 = 0; + do + { + unsigned int htable_idx, rows = 0; + const unsigned int *block; + + /* [ zzzz y x x ] + * xx == 00 :=> end of the block def, remove the two bits from the stream + * yxx == 111 + * yxx == any other value + * + */ + fill_nbits(pdec, 16); + htable_idx = look_nbits(pdec, 6); + op = hash_table_ops[htable_idx * 4]; + + if (op == 2) { + skip_nbits(pdec, 2); + + } else if (op == 1) { + /* 15bits [ xxxx xxxx yyyy 111 ] + * yyy => offset in the table8004 + * xxx => offset in the tabled004 (tree) + */ + unsigned int mask, shift; + unsigned int nbits, col1; + unsigned int yyyy; + + skip_nbits(pdec, 3); + /* offset1 += yyyy */ + __get_nbits(pdec, 4, yyyy); + offset1 += 1 + yyyy; + offset1 &= 0x0F; + nbits = ptable8004[offset1 * 2]; + + /* col1 = xxxx xxxx */ + __get_nbits(pdec, nbits+1, col1); + + /* Bit mask table */ + mask = pdec->table_bitpowermask[nbits][col1]; + shift = ptable8004[offset1 * 2 + 1]; + rows = ((mask << shift) + 0x80) & 0xFF; + + block = pdec->table_subblock[rows]; + for (i = 0; i < 16; i++) + pdec->temp_colors[i] += block[MulIdx[offset1][i]]; + + } else { + /* op == 0 + * offset1 is coded on 3 bits + */ + unsigned int shift; + + offset1 += hash_table_ops [htable_idx * 4 + 2]; + offset1 &= 0x0F; + + rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]]; + block = pdec->table_subblock[rows]; + for (i = 0; i < 16; i++) + pdec->temp_colors[i] += block[MulIdx[offset1][i]]; + + shift = hash_table_ops[htable_idx * 4 + 1]; + skip_nbits(pdec, shift); + } + + } while (op != 2); + +} + +static void DecompressBand23(struct pwc_dec23_private *pdec, + const unsigned char *rawyuv, + unsigned char *planar_y, + unsigned char *planar_u, + unsigned char *planar_v, + unsigned int compressed_image_width, + unsigned int real_image_width) +{ + int compression_index, nblocks; + const unsigned char *ptable0004; + const unsigned char *ptable8004; + + pdec->reservoir = 0; + pdec->nbits_in_reservoir = 0; + pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */ + + get_nbits(pdec, 4, compression_index); + + /* pass 1: uncompress Y component */ + nblocks = compressed_image_width / 4; + + ptable0004 = pdec->table_0004_pass1[compression_index]; + ptable8004 = pdec->table_8004_pass1[compression_index]; + + /* Each block decode a square of 4x4 */ + while (nblocks) { + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits); + planar_y += 4; + nblocks--; + } + + /* pass 2: uncompress UV component */ + nblocks = compressed_image_width / 8; + + ptable0004 = pdec->table_0004_pass2[compression_index]; + ptable8004 = pdec->table_8004_pass2[compression_index]; + + /* Each block decode a square of 4x4 */ + while (nblocks) { + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits); + + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits); + + planar_v += 8; + planar_u += 8; + nblocks -= 2; + } + +} + +#if ENABLE_BAYER_DECODER +/* + * Size need to be a multiple of 8 in width + * + * Return a block of four line encoded like this: + * + * G R G R G R G R G R G R G R G R + * B G B G B G B G B G B G B G B G + * G R G R G R G R G R G R G R G R + * B G B G B G B G B G B G B G B G + * + */ +static void DecompressBandBayer(struct pwc_dec23_private *pdec, + const unsigned char *rawyuv, + unsigned char *rgbbayer, + unsigned int compressed_image_width, + unsigned int real_image_width) +{ + int compression_index, nblocks; + const unsigned char *ptable0004; + const unsigned char *ptable8004; + unsigned char *dest; + + pdec->reservoir = 0; + pdec->nbits_in_reservoir = 0; + pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */ + + get_nbits(pdec, 4, compression_index); + + /* pass 1: uncompress RB component */ + nblocks = compressed_image_width / 4; + + ptable0004 = pdec->table_0004_pass1[compression_index]; + ptable8004 = pdec->table_8004_pass1[compression_index]; + dest = rgbbayer; + + /* Each block decode a square of 4x4 */ + while (nblocks) { + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits); + dest += 8; + nblocks--; + } + + /* pass 2: uncompress G component */ + nblocks = compressed_image_width / 8; + + ptable0004 = pdec->table_0004_pass2[compression_index]; + ptable8004 = pdec->table_8004_pass2[compression_index]; + + /* Each block decode a square of 4x4 */ + while (nblocks) { + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits); + + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits); + + rgbbayer += 16; + nblocks -= 2; + } +} +#endif + + +/** + * + * Uncompress a pwc23 buffer. + * + * pwc.view: size of the image wanted + * pwc.image: size of the image returned by the camera + * pwc.offset: (x,y) to displayer image in the view + * + * src: raw data + * dst: image output + * flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER + */ +void pwc_dec23_decompress(const struct pwc_device *pwc, + const void *src, + void *dst, + int flags) +{ + int bandlines_left, stride, bytes_per_block; + + bandlines_left = pwc->image.y / 4; + bytes_per_block = pwc->view.x * 4; + + if (flags & PWCX_FLAG_BAYER) { +#if ENABLE_BAYER_DECODER + /* RGB Bayer format */ + unsigned char *rgbout; + + stride = pwc->view.x * pwc->offset.y; + rgbout = dst + stride + pwc->offset.x; + + + while (bandlines_left--) { + + DecompressBandBayer(pwc->decompress_data, + src, + rgbout, + pwc->image.x, pwc->view.x); + + src += pwc->vbandlength; + rgbout += bytes_per_block; + + } +#else + memset(dst, 0, pwc->view.x * pwc->view.y); +#endif + + } else { + /* YUV420P image format */ + unsigned char *pout_planar_y; + unsigned char *pout_planar_u; + unsigned char *pout_planar_v; + unsigned int plane_size; + + plane_size = pwc->view.x * pwc->view.y; + + /* offset in Y plane */ + stride = pwc->view.x * pwc->offset.y; + pout_planar_y = dst + stride + pwc->offset.x; + + /* offsets in U/V planes */ + stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2; + pout_planar_u = dst + plane_size + stride; + pout_planar_v = dst + plane_size + plane_size / 4 + stride; + + while (bandlines_left--) { + + DecompressBand23(pwc->decompress_data, + src, + pout_planar_y, pout_planar_u, pout_planar_v, + pwc->image.x, pwc->view.x); + src += pwc->vbandlength; + pout_planar_y += bytes_per_block; + pout_planar_u += pwc->view.x; + pout_planar_v += pwc->view.x; + + } + + } + +} + +void pwc_dec23_exit(void) +{ + /* Do nothing */ + +} + +/** + * Allocate a private structure used by lookup table. + * You must call kfree() to free the memory allocated. + */ +int pwc_dec23_alloc(struct pwc_device *pwc) +{ + pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); + if (pwc->decompress_data == NULL) + return -ENOMEM; + return 0; +} + +/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h new file mode 100644 index 0000000..1c55298 --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec23.h @@ -0,0 +1,67 @@ +/* Linux driver for Philips webcam + (C) 2004-2006 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef PWC_DEC23_H +#define PWC_DEC23_H + +#include "pwc.h" + +struct pwc_dec23_private +{ + unsigned int scalebits; + unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */ + + unsigned int reservoir; + unsigned int nbits_in_reservoir; + const unsigned char *stream; + int temp_colors[16]; + + unsigned char table_0004_pass1[16][1024]; + unsigned char table_0004_pass2[16][1024]; + unsigned char table_8004_pass1[16][256]; + unsigned char table_8004_pass2[16][256]; + unsigned int table_subblock[256][12]; + + unsigned char table_bitpowermask[8][256]; + unsigned int table_d800[256]; + unsigned int table_dc00[256]; + +}; + + +int pwc_dec23_alloc(struct pwc_device *pwc); +int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd); +void pwc_dec23_exit(void); +void pwc_dec23_decompress(const struct pwc_device *pwc, + const void *src, + void *dst, + int flags); + + + +#endif + + +/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ + diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 4141829..47d0d83 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -1,7 +1,7 @@ /* Linux driver for Philips webcam USB and Video4Linux interface part. (C) 1999-2004 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) + (C) 2004-2006 Luc Saillard (luc@saillard.org) NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx driver and thus may have bugs that are not present in the original version. @@ -62,18 +62,21 @@ #include #include #include #include +#include #include +#include #include "pwc.h" -#include "pwc-ioctl.h" #include "pwc-kiara.h" #include "pwc-timon.h" +#include "pwc-dec23.h" +#include "pwc-dec1.h" #include "pwc-uncompress.h" /* Function prototypes and driver templates */ /* hotplug device table support */ -static struct usb_device_id pwc_device_table [] = { +static const struct usb_device_id pwc_device_table [] = { { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */ { USB_DEVICE(0x0471, 0x0303) }, { USB_DEVICE(0x0471, 0x0304) }, @@ -81,9 +84,10 @@ static struct usb_device_id pwc_device_t { USB_DEVICE(0x0471, 0x0308) }, { USB_DEVICE(0x0471, 0x030C) }, { USB_DEVICE(0x0471, 0x0310) }, - { USB_DEVICE(0x0471, 0x0311) }, + { USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */ { USB_DEVICE(0x0471, 0x0312) }, { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ + { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */ { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ @@ -94,8 +98,9 @@ static struct usb_device_id pwc_device_t { USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */ { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */ { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */ - { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */ - { USB_DEVICE(0x055D, 0x9001) }, + { USB_DEVICE(0x055D, 0x9000) }, /* Samsung MPC-C10 */ + { USB_DEVICE(0x055D, 0x9001) }, /* Samsung MPC-C30 */ + { USB_DEVICE(0x055D, 0x9002) }, /* Samsung SNC-35E (Ver3.0) */ { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */ { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */ @@ -122,11 +127,13 @@ #define MAX_ISOC_ERRORS 20 static int default_size = PSZ_QCIF; static int default_fps = 10; static int default_fbufs = 3; /* Default number of frame buffers */ -static int default_mbufs = 2; /* Default number of mmap() buffers */ - int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX; + int pwc_mbufs = 2; /* Default number of mmap() buffers */ +#if CONFIG_PWC_DEBUG + int pwc_trace = PWC_DEBUG_LEVEL; +#endif static int power_save = 0; static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ -static int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */ +static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */ static struct { int type; char serial_number[30]; @@ -138,7 +145,7 @@ static struct { static int pwc_video_open(struct inode *inode, struct file *file); static int pwc_video_close(struct inode *inode, struct file *file); -static ssize_t pwc_video_read(struct file *file, char __user * buf, +static ssize_t pwc_video_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); static unsigned int pwc_video_poll(struct file *file, poll_table *wait); static int pwc_video_ioctl(struct inode *inode, struct file *file, @@ -153,7 +160,6 @@ static struct file_operations pwc_fops = .poll = pwc_video_poll, .mmap = pwc_video_mmap, .ioctl = pwc_video_ioctl, - .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; static struct video_device pwc_template = { @@ -203,52 +209,44 @@ static struct video_device pwc_template /* Here we want the physical address of the memory. * This is used when initializing the contents of the area. */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} -static void * rvmalloc(unsigned long size) + +static void *pwc_rvmalloc(unsigned long size) { void * mem; unsigned long adr; - size=PAGE_ALIGN(size); mem=vmalloc_32(size); - if (mem) - { - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr=(unsigned long) mem; - while (size > 0) - { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - } + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr=(unsigned long) mem; + while (size > 0) + { + SetPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } return mem; } -static void rvfree(void * mem, unsigned long size) +static void pwc_rvfree(void * mem, unsigned long size) { unsigned long adr; - if (mem) - { - adr=(unsigned long) mem; - while ((long) size > 0) - { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - vfree(mem); - } + if (!mem) + return; + + adr=(unsigned long) mem; + while ((long) size > 0) + { + ClearPageReserved(vmalloc_to_page((void *)adr)); + adr += PAGE_SIZE; + size -= PAGE_SIZE; + } + vfree(mem); } @@ -256,100 +254,83 @@ static void rvfree(void * mem, unsigned static int pwc_allocate_buffers(struct pwc_device *pdev) { - int i; + int i, err; void *kbuf; - Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev); + PWC_DEBUG_MEMORY(">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev); if (pdev == NULL) return -ENXIO; -#ifdef PWC_MAGIC - if (pdev->magic != PWC_MAGIC) { - Err("allocate_buffers(): magic failed.\n"); - return -ENXIO; - } -#endif - /* Allocate Isochronous pipe buffers */ + /* Allocate Isochronuous pipe buffers */ for (i = 0; i < MAX_ISO_BUFS; i++) { if (pdev->sbuf[i].data == NULL) { - kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL); + kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL); if (kbuf == NULL) { - Err("Failed to allocate iso buffer %d.\n", i); + PWC_ERROR("Failed to allocate iso buffer %d.\n", i); return -ENOMEM; } - Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf); + PWC_DEBUG_MEMORY("Allocated iso buffer at %p.\n", kbuf); pdev->sbuf[i].data = kbuf; - memset(kbuf, 0, ISO_BUFFER_SIZE); } } /* Allocate frame buffer structure */ if (pdev->fbuf == NULL) { - kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL); + kbuf = kzalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL); if (kbuf == NULL) { - Err("Failed to allocate frame buffer structure.\n"); + PWC_ERROR("Failed to allocate frame buffer structure.\n"); return -ENOMEM; } - Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf); + PWC_DEBUG_MEMORY("Allocated frame buffer structure at %p.\n", kbuf); pdev->fbuf = kbuf; - memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf)); } + /* create frame buffers, and make circular ring */ for (i = 0; i < default_fbufs; i++) { if (pdev->fbuf[i].data == NULL) { kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ if (kbuf == NULL) { - Err("Failed to allocate frame buffer %d.\n", i); + PWC_ERROR("Failed to allocate frame buffer %d.\n", i); return -ENOMEM; } - Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf); + PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf); pdev->fbuf[i].data = kbuf; - memset(kbuf, 128, PWC_FRAME_SIZE); + memset(kbuf, 0, PWC_FRAME_SIZE); } } /* Allocate decompressor table space */ - kbuf = NULL; - switch (pdev->type) - { - case 675: - case 680: - case 690: - case 720: - case 730: - case 740: - case 750: -#if 0 - Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private)); - kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */ - break; - case 645: - case 646: - /* TODO & FIXME */ - kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); - break; -#endif - ; - } - pdev->decompress_data = kbuf; + if (DEVICE_USE_CODEC1(pdev->type)) + err = pwc_dec1_alloc(pdev); + else + err = pwc_dec23_alloc(pdev); + + if (err) { + PWC_ERROR("Failed to allocate decompress table.\n"); + return err; + } /* Allocate image buffer; double buffer for mmap() */ - kbuf = rvmalloc(default_mbufs * pdev->len_per_image); + kbuf = pwc_rvmalloc(pwc_mbufs * pdev->len_per_image); if (kbuf == NULL) { - Err("Failed to allocate image buffer(s). needed (%d)\n",default_mbufs * pdev->len_per_image); + PWC_ERROR("Failed to allocate image buffer(s). needed (%d)\n", + pwc_mbufs * pdev->len_per_image); return -ENOMEM; } - Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf); + PWC_DEBUG_MEMORY("Allocated image buffer at %p.\n", kbuf); pdev->image_data = kbuf; - for (i = 0; i < default_mbufs; i++) - pdev->image_ptr[i] = kbuf + i * pdev->len_per_image; - for (; i < MAX_IMAGES; i++) - pdev->image_ptr[i] = NULL; + for (i = 0; i < pwc_mbufs; i++) { + pdev->images[i].offset = i * pdev->len_per_image; + pdev->images[i].vma_use_count = 0; + } + for (; i < MAX_IMAGES; i++) { + pdev->images[i].offset = 0; + } kbuf = NULL; - Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n"); + PWC_DEBUG_MEMORY("<< pwc_allocate_buffers()\n"); return 0; } @@ -357,21 +338,14 @@ static void pwc_free_buffers(struct pwc_ { int i; - Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev); + PWC_DEBUG_MEMORY("Entering free_buffers(%p).\n", pdev); if (pdev == NULL) return; -#ifdef PWC_MAGIC - if (pdev->magic != PWC_MAGIC) { - Err("free_buffers(): magic failed.\n"); - return; - } -#endif - /* Release Iso-pipe buffers */ for (i = 0; i < MAX_ISO_BUFS; i++) if (pdev->sbuf[i].data != NULL) { - Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data); + PWC_DEBUG_MEMORY("Freeing ISO buffer at %p.\n", pdev->sbuf[i].data); kfree(pdev->sbuf[i].data); pdev->sbuf[i].data = NULL; } @@ -380,7 +354,7 @@ #endif if (pdev->fbuf != NULL) { for (i = 0; i < default_fbufs; i++) { if (pdev->fbuf[i].data != NULL) { - Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data); + PWC_DEBUG_MEMORY("Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data); vfree(pdev->fbuf[i].data); pdev->fbuf[i].data = NULL; } @@ -391,20 +365,19 @@ #endif /* Intermediate decompression buffer & tables */ if (pdev->decompress_data != NULL) { - Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data); + PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n", pdev->decompress_data); kfree(pdev->decompress_data); pdev->decompress_data = NULL; } - pdev->decompressor = NULL; /* Release image buffers */ if (pdev->image_data != NULL) { - Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data); - rvfree(pdev->image_data, default_mbufs * pdev->len_per_image); + PWC_DEBUG_MEMORY("Freeing image buffer at %p.\n", pdev->image_data); + pwc_rvfree(pdev->image_data, pwc_mbufs * pdev->len_per_image); } pdev->image_data = NULL; - Trace(TRACE_MEMORY, "Leaving free_buffers().\n"); + PWC_DEBUG_MEMORY("Leaving free_buffers().\n"); } /* The frame & image buffer mess. @@ -464,7 +437,7 @@ #endif /** \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first. */ -static inline int pwc_next_fill_frame(struct pwc_device *pdev) +static int pwc_next_fill_frame(struct pwc_device *pdev) { int ret; unsigned long flags; @@ -489,23 +462,17 @@ static inline int pwc_next_fill_frame(st } else { /* Hmm. Take it from the full list */ -#if PWC_DEBUG /* sanity check */ if (pdev->full_frames == NULL) { - Err("Neither empty or full frames available!\n"); + PWC_ERROR("Neither empty or full frames available!\n"); spin_unlock_irqrestore(&pdev->ptrlock, flags); return -EINVAL; } -#endif pdev->fill_frame = pdev->full_frames; pdev->full_frames = pdev->full_frames->next; ret = 1; } pdev->fill_frame->next = NULL; -#if PWC_DEBUG - Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence); - pdev->fill_frame->sequence = pdev->sequence++; -#endif spin_unlock_irqrestore(&pdev->ptrlock, flags); return ret; } @@ -521,6 +488,8 @@ static void pwc_reset_buffers(struct pwc int i; unsigned long flags; + PWC_DEBUG_MEMORY(">> %s __enter__\n", __FUNCTION__); + spin_lock_irqsave(&pdev->ptrlock, flags); pdev->full_frames = NULL; pdev->full_frames_tail = NULL; @@ -540,13 +509,15 @@ static void pwc_reset_buffers(struct pwc pdev->image_read_pos = 0; pdev->fill_image = 0; spin_unlock_irqrestore(&pdev->ptrlock, flags); + + PWC_DEBUG_MEMORY("<< %s __leaving__\n", __FUNCTION__); } /** \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers. */ -static int pwc_handle_frame(struct pwc_device *pdev) +int pwc_handle_frame(struct pwc_device *pdev) { int ret = 0; unsigned long flags; @@ -556,41 +527,40 @@ static int pwc_handle_frame(struct pwc_d we can release the lock after this without problems */ if (pdev->read_frame != NULL) { /* This can't theoretically happen */ - Err("Huh? Read frame still in use?\n"); + PWC_ERROR("Huh? Read frame still in use?\n"); + spin_unlock_irqrestore(&pdev->ptrlock, flags); + return ret; + } + + + if (pdev->full_frames == NULL) { + PWC_ERROR("Woops. No frames ready.\n"); } else { - if (pdev->full_frames == NULL) { - Err("Woops. No frames ready.\n"); + pdev->read_frame = pdev->full_frames; + pdev->full_frames = pdev->full_frames->next; + pdev->read_frame->next = NULL; + } + + if (pdev->read_frame != NULL) { + /* Decompression is a lenghty process, so it's outside of the lock. + This gives the isoc_handler the opportunity to fill more frames + in the mean time. + */ + spin_unlock_irqrestore(&pdev->ptrlock, flags); + ret = pwc_decompress(pdev); + spin_lock_irqsave(&pdev->ptrlock, flags); + + /* We're done with read_buffer, tack it to the end of the empty buffer list */ + if (pdev->empty_frames == NULL) { + pdev->empty_frames = pdev->read_frame; + pdev->empty_frames_tail = pdev->empty_frames; } else { - pdev->read_frame = pdev->full_frames; - pdev->full_frames = pdev->full_frames->next; - pdev->read_frame->next = NULL; - } - - if (pdev->read_frame != NULL) { -#if PWC_DEBUG - Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence); -#endif - /* Decompression is a lenghty process, so it's outside of the lock. - This gives the isoc_handler the opportunity to fill more frames - in the mean time. - */ - spin_unlock_irqrestore(&pdev->ptrlock, flags); - ret = pwc_decompress(pdev); - spin_lock_irqsave(&pdev->ptrlock, flags); - - /* We're done with read_buffer, tack it to the end of the empty buffer list */ - if (pdev->empty_frames == NULL) { - pdev->empty_frames = pdev->read_frame; - pdev->empty_frames_tail = pdev->empty_frames; - } - else { - pdev->empty_frames_tail->next = pdev->read_frame; - pdev->empty_frames_tail = pdev->read_frame; - } - pdev->read_frame = NULL; + pdev->empty_frames_tail->next = pdev->read_frame; + pdev->empty_frames_tail = pdev->read_frame; } + pdev->read_frame = NULL; } spin_unlock_irqrestore(&pdev->ptrlock, flags); return ret; @@ -599,12 +569,114 @@ #endif /** \brief Advance pointers of image buffer (after each user request) */ -static inline void pwc_next_image(struct pwc_device *pdev) +void pwc_next_image(struct pwc_device *pdev) { pdev->image_used[pdev->fill_image] = 0; - pdev->fill_image = (pdev->fill_image + 1) % default_mbufs; + pdev->fill_image = (pdev->fill_image + 1) % pwc_mbufs; } +/** + * Print debug information when a frame is discarded because all of our buffer + * is full + */ +static void pwc_frame_dumped(struct pwc_device *pdev) +{ + pdev->vframes_dumped++; + if (pdev->vframe_count < FRAME_LOWMARK) + return; + + if (pdev->vframes_dumped < 20) + PWC_DEBUG_FLOW("Dumping frame %d\n", pdev->vframe_count); + else if (pdev->vframes_dumped == 20) + PWC_DEBUG_FLOW("Dumping frame %d (last message)\n", + pdev->vframe_count); +} + +static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf) +{ + int awake = 0; + + /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus + frames on the USB wire after an exposure change. This conditition is + however detected in the cam and a bit is set in the header. + */ + if (pdev->type == 730) { + unsigned char *ptr = (unsigned char *)fbuf->data; + + if (ptr[1] == 1 && ptr[0] & 0x10) { + PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n"); + pdev->drop_frames += 2; + pdev->vframes_error++; + } + if ((ptr[0] ^ pdev->vmirror) & 0x01) { + if (ptr[0] & 0x01) { + pdev->snapshot_button_status = 1; + PWC_TRACE("Snapshot button pressed.\n"); + } + else { + PWC_TRACE("Snapshot button released.\n"); + } + } + if ((ptr[0] ^ pdev->vmirror) & 0x02) { + if (ptr[0] & 0x02) + PWC_TRACE("Image is mirrored.\n"); + else + PWC_TRACE("Image is normal.\n"); + } + pdev->vmirror = ptr[0] & 0x03; + /* Sometimes the trailer of the 730 is still sent as a 4 byte packet + after a short frame; this condition is filtered out specifically. A 4 byte + frame doesn't make sense anyway. + So we get either this sequence: + drop_bit set -> 4 byte frame -> short frame -> good frame + Or this one: + drop_bit set -> short frame -> good frame + So we drop either 3 or 2 frames in all! + */ + if (fbuf->filled == 4) + pdev->drop_frames++; + } + else if (pdev->type == 740 || pdev->type == 720) { + unsigned char *ptr = (unsigned char *)fbuf->data; + if ((ptr[0] ^ pdev->vmirror) & 0x01) { + if (ptr[0] & 0x01) { + pdev->snapshot_button_status = 1; + PWC_TRACE("Snapshot button pressed.\n"); + } + else + PWC_TRACE("Snapshot button released.\n"); + } + pdev->vmirror = ptr[0] & 0x03; + } + + /* In case we were instructed to drop the frame, do so silently. + The buffer pointers are not updated either (but the counters are reset below). + */ + if (pdev->drop_frames > 0) + pdev->drop_frames--; + else { + /* Check for underflow first */ + if (fbuf->filled < pdev->frame_total_size) { + PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);" + " discarded.\n", fbuf->filled); + pdev->vframes_error++; + } + else { + /* Send only once per EOF */ + awake = 1; /* delay wake_ups */ + + /* Find our next frame to fill. This will always succeed, since we + * nick a frame from either empty or full list, but if we had to + * take it from the full list, it means a frame got dropped. + */ + if (pwc_next_fill_frame(pdev)) + pwc_frame_dumped(pdev); + + } + } /* !drop_frames */ + pdev->vframe_count++; + return awake; +} /* This gets called for the Isochronous pipe (video). This is done in * interrupt time, so it has to be fast, not crash, and not stall. Neat. @@ -620,17 +692,12 @@ static void pwc_isoc_handler(struct urb awake = 0; pdev = (struct pwc_device *)urb->context; if (pdev == NULL) { - Err("isoc_handler() called with NULL device?!\n"); - return; - } -#ifdef PWC_MAGIC - if (pdev->magic != PWC_MAGIC) { - Err("isoc_handler() called with bad magic!\n"); + PWC_ERROR("isoc_handler() called with NULL device?!\n"); return; } -#endif + if (urb->status == -ENOENT || urb->status == -ECONNRESET) { - Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); + PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); return; } if (urb->status != -EINPROGRESS && urb->status != 0) { @@ -645,13 +712,13 @@ #endif case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break; case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break; } - Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); + PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); /* Give up after a number of contiguous errors on the USB bus. Appearantly something is wrong so we simulate an unplug event. */ if (++pdev->visoc_errors > MAX_ISOC_ERRORS) { - Info("Too many ISOC errors, bailing out.\n"); + PWC_INFO("Too many ISOC errors, bailing out.\n"); pdev->error_status = EIO; awake = 1; wake_up_interruptible(&pdev->frameq); @@ -661,7 +728,7 @@ #endif fbuf = pdev->fill_frame; if (fbuf == NULL) { - Err("pwc_isoc_handler without valid fill frame.\n"); + PWC_ERROR("pwc_isoc_handler without valid fill frame.\n"); awake = 1; goto handler_end; } @@ -688,7 +755,7 @@ #endif /* ...copy data to frame buffer, if possible */ if (flen + fbuf->filled > pdev->frame_total_size) { - Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size); + PWC_DEBUG_FLOW("Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size); pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */ pdev->vframes_error++; } @@ -704,96 +771,28 @@ #endif /* Shorter packet... We probably have the end of an image-frame; wake up read() process and let select()/poll() do something. Decompression is done in user time over there. - */ + */ if (pdev->vsync == 2) { - /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus - frames on the USB wire after an exposure change. This conditition is - however detected in the cam and a bit is set in the header. - */ - if (pdev->type == 730) { - unsigned char *ptr = (unsigned char *)fbuf->data; - - if (ptr[1] == 1 && ptr[0] & 0x10) { -#if PWC_DEBUG - Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence); -#endif - pdev->drop_frames += 2; - pdev->vframes_error++; - } - if ((ptr[0] ^ pdev->vmirror) & 0x01) { - if (ptr[0] & 0x01) - Info("Snapshot button pressed.\n"); - else - Info("Snapshot button released.\n"); - } - if ((ptr[0] ^ pdev->vmirror) & 0x02) { - if (ptr[0] & 0x02) - Info("Image is mirrored.\n"); - else - Info("Image is normal.\n"); - } - pdev->vmirror = ptr[0] & 0x03; - /* Sometimes the trailer of the 730 is still sent as a 4 byte packet - after a short frame; this condition is filtered out specifically. A 4 byte - frame doesn't make sense anyway. - So we get either this sequence: - drop_bit set -> 4 byte frame -> short frame -> good frame - Or this one: - drop_bit set -> short frame -> good frame - So we drop either 3 or 2 frames in all! - */ - if (fbuf->filled == 4) - pdev->drop_frames++; + if (pwc_rcv_short_packet(pdev, fbuf)) { + awake = 1; + fbuf = pdev->fill_frame; } - - /* In case we were instructed to drop the frame, do so silently. - The buffer pointers are not updated either (but the counters are reset below). - */ - if (pdev->drop_frames > 0) - pdev->drop_frames--; - else { - /* Check for underflow first */ - if (fbuf->filled < pdev->frame_total_size) { - Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled); - pdev->vframes_error++; - } - else { - /* Send only once per EOF */ - awake = 1; /* delay wake_ups */ - - /* Find our next frame to fill. This will always succeed, since we - * nick a frame from either empty or full list, but if we had to - * take it from the full list, it means a frame got dropped. - */ - if (pwc_next_fill_frame(pdev)) { - pdev->vframes_dumped++; - if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) { - if (pdev->vframes_dumped < 20) - Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count); - if (pdev->vframes_dumped == 20) - Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count); - } - } - fbuf = pdev->fill_frame; - } - } /* !drop_frames */ - pdev->vframe_count++; } fbuf->filled = 0; fillptr = fbuf->data; pdev->vsync = 1; - } /* .. flen < last_packet_size */ + } + pdev->vlast_packet_size = flen; } /* ..status == 0 */ -#if PWC_DEBUG - /* This is normally not interesting to the user, unless you are really debugging something */ else { + /* This is normally not interesting to the user, unless + * you are really debugging something */ static int iso_error = 0; iso_error++; if (iso_error < 20) - Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst); + PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst); } -#endif } handler_end: @@ -803,11 +802,11 @@ handler_end: urb->dev = pdev->udev; i = usb_submit_urb(urb, GFP_ATOMIC); if (i != 0) - Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i); + PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i); } -static int pwc_isoc_init(struct pwc_device *pdev) +int pwc_isoc_init(struct pwc_device *pdev) { struct usb_device *udev; struct urb *urb; @@ -826,7 +825,6 @@ static int pwc_isoc_init(struct pwc_devi /* Get the current alternate interface, adjust packet size */ if (!udev->actconfig) return -EFAULT; - intf = usb_ifnum_to_if(udev, 0); if (intf) idesc = usb_altnum_to_altsetting(intf, pdev->valternate); @@ -836,20 +834,21 @@ static int pwc_isoc_init(struct pwc_devi /* Search video endpoint */ pdev->vmax_packet_size = -1; - for (i = 0; i < idesc->desc.bNumEndpoints; i++) + for (i = 0; i < idesc->desc.bNumEndpoints; i++) { if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) { pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize); break; } + } if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { - Err("Failed to find packet size for video endpoint in current alternate setting.\n"); + PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n"); return -ENFILE; /* Odd error, that should be noticeable */ } /* Set alternate interface */ ret = 0; - Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate); + PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate); ret = usb_set_interface(pdev->udev, 0, pdev->valternate); if (ret < 0) return ret; @@ -857,12 +856,12 @@ static int pwc_isoc_init(struct pwc_devi for (i = 0; i < MAX_ISO_BUFS; i++) { urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); if (urb == NULL) { - Err("Failed to allocate urb %d\n", i); + PWC_ERROR("Failed to allocate urb %d\n", i); ret = -ENOMEM; break; } pdev->sbuf[i].urb = urb; - Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb); + PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb); } if (ret) { /* De-allocate in reverse order */ @@ -899,24 +898,26 @@ static int pwc_isoc_init(struct pwc_devi for (i = 0; i < MAX_ISO_BUFS; i++) { ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL); if (ret) - Err("isoc_init() submit_urb %d failed with error %d\n", i, ret); + PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret); else - Trace(TRACE_MEMORY, "URB 0x%p submitted.\n", pdev->sbuf[i].urb); + PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb); } /* All is done... */ pdev->iso_init = 1; - Trace(TRACE_OPEN, "<< pwc_isoc_init()\n"); + PWC_DEBUG_OPEN("<< pwc_isoc_init()\n"); return 0; } -static void pwc_isoc_cleanup(struct pwc_device *pdev) +void pwc_isoc_cleanup(struct pwc_device *pdev) { int i; - Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n"); + PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n"); if (pdev == NULL) return; + if (pdev->iso_init == 0) + return; /* Unlinking ISOC buffers one by one */ for (i = 0; i < MAX_ISO_BUFS; i++) { @@ -925,10 +926,10 @@ static void pwc_isoc_cleanup(struct pwc_ urb = pdev->sbuf[i].urb; if (urb != 0) { if (pdev->iso_init) { - Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb); + PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb); usb_kill_urb(urb); } - Trace(TRACE_MEMORY, "Freeing URB\n"); + PWC_DEBUG_MEMORY("Freeing URB\n"); usb_free_urb(urb); pdev->sbuf[i].urb = NULL; } @@ -938,12 +939,12 @@ static void pwc_isoc_cleanup(struct pwc_ is signalled by EPIPE) */ if (pdev->error_status && pdev->error_status != EPIPE) { - Trace(TRACE_OPEN, "Setting alternate interface 0.\n"); + PWC_DEBUG_OPEN("Setting alternate interface 0.\n"); usb_set_interface(pdev->udev, 0, 0); } pdev->iso_init = 0; - Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n"); + PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); } int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot) @@ -957,18 +958,18 @@ int pwc_try_video_mode(struct pwc_device /* Try to set video mode... */ start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); if (ret) { - Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n"); + PWC_DEBUG_FLOW("pwc_set_video_mode attempt 1 failed.\n"); /* That failed... restore old mode (we know that worked) */ start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); if (start) { - Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n"); + PWC_DEBUG_FLOW("pwc_set_video_mode attempt 2 failed.\n"); } } if (start == 0) { if (pwc_isoc_init(pdev) < 0) { - Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n"); + PWC_WARNING("Failed to restart ISOC transfers in pwc_try_video_mode.\n"); ret = -EAGAIN; /* let's try again, who knows if it works a second time */ } } @@ -976,54 +977,129 @@ int pwc_try_video_mode(struct pwc_device return ret; /* Return original error code */ } +/********* + * sysfs + *********/ +static struct pwc_device *cd_to_pwc(struct class_device *cd) +{ + struct video_device *vdev = to_video_device(cd); + return video_get_drvdata(vdev); +} + +static ssize_t show_pan_tilt(struct class_device *class_dev, char *buf) +{ + struct pwc_device *pdev = cd_to_pwc(class_dev); + return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle); +} + +static ssize_t store_pan_tilt(struct class_device *class_dev, const char *buf, + size_t count) +{ + struct pwc_device *pdev = cd_to_pwc(class_dev); + int pan, tilt; + int ret = -EINVAL; + + if (strncmp(buf, "reset", 5) == 0) + ret = pwc_mpt_reset(pdev, 0x3); + + else if (sscanf(buf, "%d %d", &pan, &tilt) > 0) + ret = pwc_mpt_set_angle(pdev, pan, tilt); + + if (ret < 0) + return ret; + return strlen(buf); +} +static CLASS_DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt, + store_pan_tilt); + +static ssize_t show_snapshot_button_status(struct class_device *class_dev, char *buf) +{ + struct pwc_device *pdev = cd_to_pwc(class_dev); + int status = pdev->snapshot_button_status; + pdev->snapshot_button_status = 0; + return sprintf(buf, "%d\n", status); +} + +static CLASS_DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status, + NULL); + +static void pwc_create_sysfs_files(struct video_device *vdev) +{ + struct pwc_device *pdev = video_get_drvdata(vdev); + if (pdev->features & FEATURE_MOTOR_PANTILT) + video_device_create_file(vdev, &class_device_attr_pan_tilt); + video_device_create_file(vdev, &class_device_attr_button); +} + +static void pwc_remove_sysfs_files(struct video_device *vdev) +{ + struct pwc_device *pdev = video_get_drvdata(vdev); + if (pdev->features & FEATURE_MOTOR_PANTILT) + video_device_remove_file(vdev, &class_device_attr_pan_tilt); + video_device_remove_file(vdev, &class_device_attr_button); +} + +#if CONFIG_PWC_DEBUG +static const char *pwc_sensor_type_to_string(unsigned int sensor_type) +{ + switch(sensor_type) { + case 0x00: + return "Hyundai CMOS sensor"; + case 0x20: + return "Sony CCD sensor + TDA8787"; + case 0x2E: + return "Sony CCD sensor + Exas 98L59"; + case 0x2F: + return "Sony CCD sensor + ADI 9804"; + case 0x30: + return "Sharp CCD sensor + TDA8787"; + case 0x3E: + return "Sharp CCD sensor + Exas 98L59"; + case 0x3F: + return "Sharp CCD sensor + ADI 9804"; + case 0x40: + return "UPA 1021 sensor"; + case 0x100: + return "VGA sensor"; + case 0x101: + return "PAL MR sensor"; + default: + return "unknown type of sensor"; + } +} +#endif /***************************************************************************/ /* Video4Linux functions */ static int pwc_video_open(struct inode *inode, struct file *file) { - int i; + int i, ret; struct video_device *vdev = video_devdata(file); struct pwc_device *pdev; - Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev); + PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev); pdev = (struct pwc_device *)vdev->priv; if (pdev == NULL) BUG(); - if (pdev->vopen) + if (pdev->vopen) { + PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n"); return -EBUSY; + } down(&pdev->modlock); if (!pdev->usb_init) { - Trace(TRACE_OPEN, "Doing first time initialization.\n"); + PWC_DEBUG_OPEN("Doing first time initialization.\n"); pdev->usb_init = 1; - if (pwc_trace & TRACE_OPEN) + /* Query sensor type */ + ret = pwc_get_cmos_sensor(pdev, &i); + if (ret >= 0) { - /* Query sensor type */ - const char *sensor_type = NULL; - int ret; - - ret = pwc_get_cmos_sensor(pdev, &i); - if (ret >= 0) - { - switch(i) { - case 0x00: sensor_type = "Hyundai CMOS sensor"; break; - case 0x20: sensor_type = "Sony CCD sensor + TDA8787"; break; - case 0x2E: sensor_type = "Sony CCD sensor + Exas 98L59"; break; - case 0x2F: sensor_type = "Sony CCD sensor + ADI 9804"; break; - case 0x30: sensor_type = "Sharp CCD sensor + TDA8787"; break; - case 0x3E: sensor_type = "Sharp CCD sensor + Exas 98L59"; break; - case 0x3F: sensor_type = "Sharp CCD sensor + ADI 9804"; break; - case 0x40: sensor_type = "UPA 1021 sensor"; break; - case 0x100: sensor_type = "VGA sensor"; break; - case 0x101: sensor_type = "PAL MR sensor"; break; - default: sensor_type = "unknown type of sensor"; break; - } - } - if (sensor_type != NULL) - Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i); + PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n", + pdev->vdev->name, + pwc_sensor_type_to_string(i), i); } } @@ -1031,34 +1107,32 @@ static int pwc_video_open(struct inode * if (power_save) { i = pwc_camera_power(pdev, 1); if (i < 0) - Info("Failed to restore power to the camera! (%d)\n", i); + PWC_DEBUG_OPEN("Failed to restore power to the camera! (%d)\n", i); } /* Set LED on/off time */ if (pwc_set_leds(pdev, led_on, led_off) < 0) - Info("Failed to set LED on/off time.\n"); + PWC_DEBUG_OPEN("Failed to set LED on/off time.\n"); pwc_construct(pdev); /* set min/max sizes correct */ /* So far, so good. Allocate memory. */ i = pwc_allocate_buffers(pdev); if (i < 0) { - Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n"); + PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n"); + pwc_free_buffers(pdev); up(&pdev->modlock); return i; } /* Reset buffers & parameters */ pwc_reset_buffers(pdev); - for (i = 0; i < default_mbufs; i++) + for (i = 0; i < pwc_mbufs; i++) pdev->image_used[i] = 0; pdev->vframe_count = 0; pdev->vframes_dumped = 0; pdev->vframes_error = 0; pdev->visoc_errors = 0; pdev->error_status = 0; -#if PWC_DEBUG - pdev->sequence = 0; -#endif pwc_construct(pdev); /* set min/max sizes correct */ /* Set some defaults */ @@ -1070,29 +1144,44 @@ #endif */ i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0); if (i) { - Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n"); - if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750) - i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0); + unsigned int default_resolution; + PWC_DEBUG_OPEN("First attempt at set_video_mode failed.\n"); + if (pdev->type>= 730) + default_resolution = PSZ_QSIF; else - i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0); + default_resolution = PSZ_QCIF; + + i = pwc_set_video_mode(pdev, + pwc_image_sizes[default_resolution].x, + pwc_image_sizes[default_resolution].y, + 10, + pdev->vcompression, + 0); } if (i) { - Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n"); + PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n"); + pwc_free_buffers(pdev); up(&pdev->modlock); return i; } i = pwc_isoc_init(pdev); if (i) { - Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i); + PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i); + pwc_isoc_cleanup(pdev); + pwc_free_buffers(pdev); up(&pdev->modlock); return i; } + /* Initialize the webcam to sane value */ + pwc_set_brightness(pdev, 0x7fff); + pwc_set_agc(pdev, 1, 0); + pdev->vopen++; file->private_data = vdev; up(&pdev->modlock); - Trace(TRACE_OPEN, "<< video_open() returns 0.\n"); + PWC_DEBUG_OPEN("<< video_open() returns 0.\n"); return 0; } @@ -1103,35 +1192,23 @@ static int pwc_video_close(struct inode struct pwc_device *pdev; int i; - Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev); + PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); pdev = (struct pwc_device *)vdev->priv; if (pdev->vopen == 0) - Info("video_close() called on closed device?\n"); + PWC_DEBUG_MODULE("video_close() called on closed device?\n"); /* Dump statistics, but only if a reasonable amount of frames were processed (to prevent endless log-entries in case of snap-shot programs) */ if (pdev->vframe_count > 20) - Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error); + PWC_DEBUG_MODULE("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error); - switch (pdev->type) - { - case 675: - case 680: - case 690: - case 720: - case 730: - case 740: - case 750: -/* pwc_dec23_exit(); *//* Timon & Kiara */ - break; - case 645: - case 646: -/* pwc_dec1_exit(); */ - break; - } + if (DEVICE_USE_CODEC1(pdev->type)) + pwc_dec1_exit(); + else + pwc_dec23_exit(); pwc_isoc_cleanup(pdev); pwc_free_buffers(pdev); @@ -1140,15 +1217,15 @@ static int pwc_video_close(struct inode if (pdev->error_status != EPIPE) { /* Turn LEDs off */ if (pwc_set_leds(pdev, 0, 0) < 0) - Info("Failed to set LED on/off time.\n"); + PWC_DEBUG_MODULE("Failed to set LED on/off time.\n"); if (power_save) { i = pwc_camera_power(pdev, 0); if (i < 0) - Err("Failed to power down camera (%d)\n", i); + PWC_ERROR("Failed to power down camera (%d)\n", i); } } - pdev->vopen = 0; - Trace(TRACE_OPEN, "<< video_close()\n"); + pdev->vopen--; + PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); return 0; } @@ -1164,7 +1241,7 @@ static int pwc_video_close(struct inode device is tricky anyhow. */ -static ssize_t pwc_video_read(struct file *file, char __user * buf, +static ssize_t pwc_video_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct video_device *vdev = file->private_data; @@ -1172,8 +1249,10 @@ static ssize_t pwc_video_read(struct fil int noblock = file->f_flags & O_NONBLOCK; DECLARE_WAITQUEUE(wait, current); int bytes_to_read; + void *image_buffer_addr; - Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count); + PWC_DEBUG_READ("pwc_video_read(vdev=0x%p, buf=%p, count=%zd) called.\n", + vdev, buf, count); if (vdev == NULL) return -EFAULT; pdev = vdev->priv; @@ -1214,16 +1293,19 @@ static ssize_t pwc_video_read(struct fil return -EFAULT; } - Trace(TRACE_READ, "Copying data to user space.\n"); + PWC_DEBUG_READ("Copying data to user space.\n"); if (pdev->vpalette == VIDEO_PALETTE_RAW) - bytes_to_read = pdev->frame_size; + bytes_to_read = pdev->frame_size + sizeof(struct pwc_raw_frame); else bytes_to_read = pdev->view.size; /* copy bytes to user space; we allow for partial reads */ if (count + pdev->image_read_pos > bytes_to_read) count = bytes_to_read - pdev->image_read_pos; - if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count)) + image_buffer_addr = pdev->image_data; + image_buffer_addr += pdev->images[pdev->fill_image].offset; + image_buffer_addr += pdev->image_read_pos; + if (copy_to_user(buf, image_buffer_addr, count)) return -EFAULT; pdev->image_read_pos += count; if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */ @@ -1253,370 +1335,56 @@ static unsigned int pwc_video_poll(struc return 0; } -static int pwc_video_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct video_device *vdev = file->private_data; - struct pwc_device *pdev; - DECLARE_WAITQUEUE(wait, current); - - if (vdev == NULL) - return -EFAULT; - pdev = vdev->priv; - if (pdev == NULL) - return -EFAULT; - - switch (cmd) { - /* Query cabapilities */ - case VIDIOCGCAP: - { - struct video_capability *caps = arg; - - strcpy(caps->name, vdev->name); - caps->type = VID_TYPE_CAPTURE; - caps->channels = 1; - caps->audios = 1; - caps->minwidth = pdev->view_min.x; - caps->minheight = pdev->view_min.y; - caps->maxwidth = pdev->view_max.x; - caps->maxheight = pdev->view_max.y; - break; - } - - /* Channel functions (simulate 1 channel) */ - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - - if (v->channel != 0) - return -EINVAL; - v->flags = 0; - v->tuners = 0; - v->type = VIDEO_TYPE_CAMERA; - strcpy(v->name, "Webcam"); - return 0; - } - - case VIDIOCSCHAN: - { - /* The spec says the argument is an integer, but - the bttv driver uses a video_channel arg, which - makes sense becasue it also has the norm flag. - */ - struct video_channel *v = arg; - if (v->channel != 0) - return -EINVAL; - return 0; - } - - - /* Picture functions; contrast etc. */ - case VIDIOCGPICT: - { - struct video_picture *p = arg; - int val; - - val = pwc_get_brightness(pdev); - if (val >= 0) - p->brightness = val; - else - p->brightness = 0xffff; - val = pwc_get_contrast(pdev); - if (val >= 0) - p->contrast = val; - else - p->contrast = 0xffff; - /* Gamma, Whiteness, what's the difference? :) */ - val = pwc_get_gamma(pdev); - if (val >= 0) - p->whiteness = val; - else - p->whiteness = 0xffff; - val = pwc_get_saturation(pdev); - if (val >= 0) - p->colour = val; - else - p->colour = 0xffff; - p->depth = 24; - p->palette = pdev->vpalette; - p->hue = 0xFFFF; /* N/A */ - break; - } - - case VIDIOCSPICT: - { - struct video_picture *p = arg; - /* - * FIXME: Suppose we are mid read - ANSWER: No problem: the firmware of the camera - can handle brightness/contrast/etc - changes at _any_ time, and the palette - is used exactly once in the uncompress - routine. - */ - pwc_set_brightness(pdev, p->brightness); - pwc_set_contrast(pdev, p->contrast); - pwc_set_gamma(pdev, p->whiteness); - pwc_set_saturation(pdev, p->colour); - if (p->palette && p->palette != pdev->vpalette) { - switch (p->palette) { - case VIDEO_PALETTE_YUV420P: - case VIDEO_PALETTE_RAW: - pdev->vpalette = p->palette; - return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); - break; - default: - return -EINVAL; - break; - } - } - break; - } - - /* Window/size parameters */ - case VIDIOCGWIN: - { - struct video_window *vw = arg; - - vw->x = 0; - vw->y = 0; - vw->width = pdev->view.x; - vw->height = pdev->view.y; - vw->chromakey = 0; - vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | - (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0); - break; - } - - case VIDIOCSWIN: - { - struct video_window *vw = arg; - int fps, snapshot, ret; - - fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; - snapshot = vw->flags & PWC_FPS_SNAPSHOT; - if (fps == 0) - fps = pdev->vframes; - if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot) - return 0; - ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot); - if (ret) - return ret; - break; - } - - /* We don't have overlay support (yet) */ - case VIDIOCGFBUF: - { - struct video_buffer *vb = arg; - - memset(vb,0,sizeof(*vb)); - break; - } - - /* mmap() functions */ - case VIDIOCGMBUF: - { - /* Tell the user program how much memory is needed for a mmap() */ - struct video_mbuf *vm = arg; - int i; - - memset(vm, 0, sizeof(*vm)); - vm->size = default_mbufs * pdev->len_per_image; - vm->frames = default_mbufs; /* double buffering should be enough for most applications */ - for (i = 0; i < default_mbufs; i++) - vm->offsets[i] = i * pdev->len_per_image; - break; - } - - case VIDIOCMCAPTURE: - { - /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */ - struct video_mmap *vm = arg; - - Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format); - if (vm->frame < 0 || vm->frame >= default_mbufs) - return -EINVAL; - - /* xawtv is nasty. It probes the available palettes - by setting a very small image size and trying - various palettes... The driver doesn't support - such small images, so I'm working around it. - */ - if (vm->format) - { - switch (vm->format) - { - case VIDEO_PALETTE_YUV420P: - case VIDEO_PALETTE_RAW: - break; - default: - return -EINVAL; - break; - } - } - - if ((vm->width != pdev->view.x || vm->height != pdev->view.y) && - (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) { - int ret; - - Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n"); - ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot); - if (ret) - return ret; - } /* ... size mismatch */ - - /* FIXME: should we lock here? */ - if (pdev->image_used[vm->frame]) - return -EBUSY; /* buffer wasn't available. Bummer */ - pdev->image_used[vm->frame] = 1; - - /* Okay, we're done here. In the SYNC call we wait until a - frame comes available, then expand image into the given - buffer. - In contrast to the CPiA cam the Philips cams deliver a - constant stream, almost like a grabber card. Also, - we have separate buffers for the rawdata and the image, - meaning we can nearly always expand into the requested buffer. - */ - Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n"); - break; - } - - case VIDIOCSYNC: - { - /* The doc says: "Whenever a buffer is used it should - call VIDIOCSYNC to free this frame up and continue." - - The only odd thing about this whole procedure is - that MCAPTURE flags the buffer as "in use", and - SYNC immediately unmarks it, while it isn't - after SYNC that you know that the buffer actually - got filled! So you better not start a CAPTURE in - the same frame immediately (use double buffering). - This is not a problem for this cam, since it has - extra intermediate buffers, but a hardware - grabber card will then overwrite the buffer - you're working on. - */ - int *mbuf = arg; - int ret; - - Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", *mbuf); - - /* bounds check */ - if (*mbuf < 0 || *mbuf >= default_mbufs) - return -EINVAL; - /* check if this buffer was requested anyway */ - if (pdev->image_used[*mbuf] == 0) - return -EINVAL; - - /* Add ourselves to the frame wait-queue. - - FIXME: needs auditing for safety. - QUESTION: In what respect? I think that using the - frameq is safe now. - */ - add_wait_queue(&pdev->frameq, &wait); - while (pdev->full_frames == NULL) { - if (pdev->error_status) { - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - return -pdev->error_status; - } - - if (signal_pending(current)) { - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - return -ERESTARTSYS; - } - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - } - remove_wait_queue(&pdev->frameq, &wait); - set_current_state(TASK_RUNNING); - - /* The frame is ready. Expand in the image buffer - requested by the user. I don't care if you - mmap() 5 buffers and request data in this order: - buffer 4 2 3 0 1 2 3 0 4 3 1 . . . - Grabber hardware may not be so forgiving. - */ - Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n"); - pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */ - /* Decompress, etc */ - ret = pwc_handle_frame(pdev); - pdev->image_used[*mbuf] = 0; - if (ret) - return -EFAULT; - break; - } - - case VIDIOCGAUDIO: - { - struct video_audio *v = arg; - - strcpy(v->name, "Microphone"); - v->audio = -1; /* unknown audio minor */ - v->flags = 0; - v->mode = VIDEO_SOUND_MONO; - v->volume = 0; - v->bass = 0; - v->treble = 0; - v->balance = 0x8000; - v->step = 1; - break; - } - - case VIDIOCSAUDIO: - { - /* Dummy: nothing can be set */ - break; - } - - case VIDIOCGUNIT: - { - struct video_unit *vu = arg; - - vu->video = pdev->vdev->minor & 0x3F; - vu->audio = -1; /* not known yet */ - vu->vbi = -1; - vu->radio = -1; - vu->teletext = -1; - break; - } - default: - return pwc_ioctl(pdev, cmd, arg); - } /* ..switch */ - return 0; -} - static int pwc_video_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl); } - static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) { struct video_device *vdev = file->private_data; struct pwc_device *pdev; - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; + unsigned long start; + unsigned long size; + unsigned long page, pos = 0; + int index; - Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size); + PWC_DEBUG_MEMORY(">> %s\n", __FUNCTION__); pdev = vdev->priv; + size = vma->vm_end - vma->vm_start; + start = vma->vm_start; - vma->vm_flags |= VM_IO; + /* Find the idx buffer for this mapping */ + for (index = 0; index < pwc_mbufs; index++) { + pos = pdev->images[index].offset; + if ((pos>>PAGE_SHIFT) == vma->vm_pgoff) + break; + } + if (index == MAX_IMAGES) + return -EINVAL; + if (index == 0) { + /* + * Special case for v4l1. In v4l1, we map only one big buffer, + * but in v4l2 each buffer is mapped + */ + unsigned long total_size; + total_size = pwc_mbufs * pdev->len_per_image; + if (size != pdev->len_per_image && size != total_size) { + PWC_ERROR("Wrong size (%lu) needed to be len_per_image=%d or total_size=%lu\n", + size, pdev->len_per_image, total_size); + return -EINVAL; + } + } else if (size > pdev->len_per_image) + return -EINVAL; - pos = (unsigned long)pdev->image_data; + vma->vm_flags |= VM_IO; /* from 2.6.9-acX */ + + pos += (unsigned long)pdev->image_data; while (size > 0) { page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; - start += PAGE_SIZE; pos += PAGE_SIZE; if (size > PAGE_SIZE) @@ -1624,7 +1392,6 @@ static int pwc_video_mmap(struct file *f else size = 0; } - return 0; } @@ -1645,10 +1412,12 @@ static int usb_pwc_probe(struct usb_inte int video_nr = -1; /* default: use next available device */ char serial_number[30], *name; + vendor_id = le16_to_cpu(udev->descriptor.idVendor); + product_id = le16_to_cpu(udev->descriptor.idProduct); + /* Check if we can handle this device */ - Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), + PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n", + vendor_id, product_id, intf->altsetting->desc.bInterfaceNumber); /* the interfaces are probed one by one. We are only interested in the @@ -1658,61 +1427,63 @@ static int usb_pwc_probe(struct usb_inte if (intf->altsetting->desc.bInterfaceNumber > 0) return -ENODEV; - vendor_id = le16_to_cpu(udev->descriptor.idVendor); - product_id = le16_to_cpu(udev->descriptor.idProduct); - if (vendor_id == 0x0471) { switch (product_id) { case 0x0302: - Info("Philips PCA645VC USB webcam detected.\n"); + PWC_INFO("Philips PCA645VC USB webcam detected.\n"); name = "Philips 645 webcam"; type_id = 645; break; case 0x0303: - Info("Philips PCA646VC USB webcam detected.\n"); + PWC_INFO("Philips PCA646VC USB webcam detected.\n"); name = "Philips 646 webcam"; type_id = 646; break; case 0x0304: - Info("Askey VC010 type 2 USB webcam detected.\n"); + PWC_INFO("Askey VC010 type 2 USB webcam detected.\n"); name = "Askey VC010 webcam"; type_id = 646; break; case 0x0307: - Info("Philips PCVC675K (Vesta) USB webcam detected.\n"); + PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n"); name = "Philips 675 webcam"; type_id = 675; break; case 0x0308: - Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n"); + PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n"); name = "Philips 680 webcam"; type_id = 680; break; case 0x030C: - Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n"); + PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n"); name = "Philips 690 webcam"; type_id = 690; break; case 0x0310: - Info("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n"); + PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n"); name = "Philips 730 webcam"; type_id = 730; break; case 0x0311: - Info("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n"); + PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n"); name = "Philips 740 webcam"; type_id = 740; break; case 0x0312: - Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n"); + PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n"); name = "Philips 750 webcam"; type_id = 750; break; case 0x0313: - Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n"); + PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n"); name = "Philips 720K/40 webcam"; type_id = 720; break; + case 0x0329: + PWC_INFO("Philips SPC 900NC USB webcam detected.\n"); + name = "Philips SPC 900NC webcam"; + type_id = 720; + break; default: return -ENODEV; break; @@ -1721,7 +1492,7 @@ static int usb_pwc_probe(struct usb_inte else if (vendor_id == 0x069A) { switch(product_id) { case 0x0001: - Info("Askey VC010 type 1 USB webcam detected.\n"); + PWC_INFO("Askey VC010 type 1 USB webcam detected.\n"); name = "Askey VC010 webcam"; type_id = 645; break; @@ -1733,32 +1504,33 @@ static int usb_pwc_probe(struct usb_inte else if (vendor_id == 0x046d) { switch(product_id) { case 0x08b0: - Info("Logitech QuickCam Pro 3000 USB webcam detected.\n"); + PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n"); name = "Logitech QuickCam Pro 3000"; type_id = 740; /* CCD sensor */ break; case 0x08b1: - Info("Logitech QuickCam Notebook Pro USB webcam detected.\n"); + PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n"); name = "Logitech QuickCam Notebook Pro"; type_id = 740; /* CCD sensor */ break; case 0x08b2: - Info("Logitech QuickCam 4000 Pro USB webcam detected.\n"); + PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n"); name = "Logitech QuickCam Pro 4000"; type_id = 740; /* CCD sensor */ break; case 0x08b3: - Info("Logitech QuickCam Zoom USB webcam detected.\n"); + PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n"); name = "Logitech QuickCam Zoom"; type_id = 740; /* CCD sensor */ break; case 0x08B4: - Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n"); + PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n"); name = "Logitech QuickCam Zoom"; type_id = 740; /* CCD sensor */ + power_save = 1; break; case 0x08b5: - Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n"); + PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n"); name = "Logitech QuickCam Orbit"; type_id = 740; /* CCD sensor */ features |= FEATURE_MOTOR_PANTILT; @@ -1766,7 +1538,7 @@ static int usb_pwc_probe(struct usb_inte case 0x08b6: case 0x08b7: case 0x08b8: - Info("Logitech QuickCam detected (reserved ID).\n"); + PWC_INFO("Logitech QuickCam detected (reserved ID).\n"); name = "Logitech QuickCam (res.)"; type_id = 730; /* Assuming CMOS */ break; @@ -1782,15 +1554,20 @@ static int usb_pwc_probe(struct usb_inte */ switch(product_id) { case 0x9000: - Info("Samsung MPC-C10 USB webcam detected.\n"); + PWC_INFO("Samsung MPC-C10 USB webcam detected.\n"); name = "Samsung MPC-C10"; type_id = 675; break; case 0x9001: - Info("Samsung MPC-C30 USB webcam detected.\n"); + PWC_INFO("Samsung MPC-C30 USB webcam detected.\n"); name = "Samsung MPC-C30"; type_id = 675; break; + case 0x9002: + PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n"); + name = "Samsung MPC-C30"; + type_id = 740; + break; default: return -ENODEV; break; @@ -1799,12 +1576,12 @@ static int usb_pwc_probe(struct usb_inte else if (vendor_id == 0x041e) { switch(product_id) { case 0x400c: - Info("Creative Labs Webcam 5 detected.\n"); + PWC_INFO("Creative Labs Webcam 5 detected.\n"); name = "Creative Labs Webcam 5"; type_id = 730; break; case 0x4011: - Info("Creative Labs Webcam Pro Ex detected.\n"); + PWC_INFO("Creative Labs Webcam Pro Ex detected.\n"); name = "Creative Labs Webcam Pro Ex"; type_id = 740; break; @@ -1816,7 +1593,7 @@ static int usb_pwc_probe(struct usb_inte else if (vendor_id == 0x04cc) { switch(product_id) { case 0x8116: - Info("Sotec Afina Eye USB webcam detected.\n"); + PWC_INFO("Sotec Afina Eye USB webcam detected.\n"); name = "Sotec Afina Eye"; type_id = 730; break; @@ -1829,7 +1606,7 @@ static int usb_pwc_probe(struct usb_inte switch(product_id) { case 0x8116: /* This is essentially the same cam as the Sotec Afina Eye */ - Info("AME Co. Afina Eye USB webcam detected.\n"); + PWC_INFO("AME Co. Afina Eye USB webcam detected.\n"); name = "AME Co. Afina Eye"; type_id = 750; break; @@ -1842,12 +1619,12 @@ static int usb_pwc_probe(struct usb_inte else if (vendor_id == 0x0d81) { switch(product_id) { case 0x1900: - Info("Visionite VCS-UC300 USB webcam detected.\n"); + PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n"); name = "Visionite VCS-UC300"; type_id = 740; /* CCD sensor */ break; case 0x1910: - Info("Visionite VCS-UM100 USB webcam detected.\n"); + PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n"); name = "Visionite VCS-UM100"; type_id = 730; /* CMOS sensor */ break; @@ -1861,15 +1638,15 @@ static int usb_pwc_probe(struct usb_inte memset(serial_number, 0, 30); usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29); - Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number); + PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number); if (udev->descriptor.bNumConfigurations > 1) - Info("Warning: more than 1 configuration available.\n"); + PWC_WARNING("Warning: more than 1 configuration available.\n"); /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */ pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL); if (pdev == NULL) { - Err("Oops, could not allocate memory for pwc_device.\n"); + PWC_ERROR("Oops, could not allocate memory for pwc_device.\n"); return -ENOMEM; } pdev->type = type_id; @@ -1900,17 +1677,18 @@ static int usb_pwc_probe(struct usb_inte pdev->vdev = video_device_alloc(); if (pdev->vdev == 0) { - Err("Err, cannot allocate video_device struture. Failing probe."); + PWC_ERROR("Err, cannot allocate video_device struture. Failing probe."); kfree(pdev); return -ENOMEM; } memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template)); + pdev->vdev->dev = &(udev->dev); strcpy(pdev->vdev->name, name); pdev->vdev->owner = THIS_MODULE; video_set_drvdata(pdev->vdev, pdev); pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); - Trace(TRACE_PROBE, "Release: %04x\n", pdev->release); + PWC_DEBUG_PROBE("Release: %04x\n", pdev->release); /* Now search device_hint[] table for a match, so we can hint a node number. */ for (hint = 0; hint < MAX_DEV_HINTS; hint++) { @@ -1918,10 +1696,10 @@ static int usb_pwc_probe(struct usb_inte (device_hint[hint].pdev == NULL)) { /* so far, so good... try serial number */ if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) { - /* match! */ - video_nr = device_hint[hint].device_node; - Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr); - break; + /* match! */ + video_nr = device_hint[hint].device_node; + PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr); + break; } } } @@ -1929,21 +1707,27 @@ static int usb_pwc_probe(struct usb_inte pdev->vdev->release = video_device_release; i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); if (i < 0) { - Err("Failed to register as video device (%d).\n", i); + PWC_ERROR("Failed to register as video device (%d).\n", i); video_device_release(pdev->vdev); /* Drip... drip... drip... */ kfree(pdev); /* Oops, no memory leaks please */ return -EIO; } else { - Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F); + PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F); } /* occupy slot */ if (hint < MAX_DEV_HINTS) device_hint[hint].pdev = pdev; - Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev); + PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev); usb_set_intfdata (intf, pdev); + pwc_create_sysfs_files(pdev->vdev); + + /* Set the leds off */ + pwc_set_leds(pdev, 0, 0); + pwc_camera_power(pdev, 0); + return 0; } @@ -1957,27 +1741,21 @@ static void usb_pwc_disconnect(struct us pdev = usb_get_intfdata (intf); usb_set_intfdata (intf, NULL); if (pdev == NULL) { - Err("pwc_disconnect() Called without private pointer.\n"); + PWC_ERROR("pwc_disconnect() Called without private pointer.\n"); goto disconnect_out; } if (pdev->udev == NULL) { - Err("pwc_disconnect() already called for %p\n", pdev); + PWC_ERROR("pwc_disconnect() already called for %p\n", pdev); goto disconnect_out; } if (pdev->udev != interface_to_usbdev(intf)) { - Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n"); - goto disconnect_out; - } -#ifdef PWC_MAGIC - if (pdev->magic != PWC_MAGIC) { - Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n"); + PWC_ERROR("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n"); goto disconnect_out; } -#endif /* We got unplugged; this is signalled by an EPIPE error code */ if (pdev->vopen) { - Info("Disconnected while webcam is in use!\n"); + PWC_INFO("Disconnected while webcam is in use!\n"); pdev->error_status = EPIPE; } @@ -1987,7 +1765,8 @@ #endif while (pdev->vopen) schedule(); /* Device is now closed, so we can safely unregister it */ - Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n"); + PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); + pwc_remove_sysfs_files(pdev->vdev); video_unregister_device(pdev->vdev); /* Free memory (don't set pdev to 0 just yet) */ @@ -2021,58 +1800,64 @@ static int pwc_atoi(const char *s) * Initialization code & module stuff */ -static char size[10]; -static int fps = 0; -static int fbufs = 0; -static int mbufs = 0; -static int trace = -1; +static char *size; +static int fps; +static int fbufs; +static int mbufs; static int compression = -1; static int leds[2] = { -1, -1 }; -static char *dev_hint[MAX_DEV_HINTS] = { }; +static int leds_nargs; +static char *dev_hint[MAX_DEV_HINTS]; +static int dev_hint_nargs; + +module_param(size, charp, 0444); +module_param(fps, int, 0444); +module_param(fbufs, int, 0444); +module_param(mbufs, int, 0444); +#if CONFIG_PWC_DEBUG +module_param_named(trace, pwc_trace, int, 0644); +#endif +module_param(power_save, int, 0444); +module_param(compression, int, 0444); +module_param_array(leds, int, &leds_nargs, 0444); +module_param_array(dev_hint, charp, &dev_hint_nargs, 0444); -module_param_string(size, size, sizeof(size), 0); MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga"); -module_param(fps, int, 0000); MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); -module_param(fbufs, int, 0000); MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve"); -module_param(mbufs, int, 0000); MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers"); -module_param(trace, int, 0000); MODULE_PARM_DESC(trace, "For debugging purposes"); -module_param(power_save, bool, 0000); MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off"); -module_param(compression, int, 0000); MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); -module_param_array(leds, int, NULL, 0000); MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); -module_param_array(dev_hint, charp, NULL, 0000); MODULE_PARM_DESC(dev_hint, "Device node hints"); MODULE_DESCRIPTION("Philips & OEM USB webcam driver"); MODULE_AUTHOR("Luc Saillard "); MODULE_LICENSE("GPL"); +MODULE_ALIAS("pwcx"); +MODULE_VERSION( PWC_VERSION ); static int __init usb_pwc_init(void) { int i, sz; char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" }; - Info("Philips webcam module version " PWC_VERSION " loaded.\n"); - Info("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n"); - Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n"); - Info("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n"); + PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n"); + PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n"); + PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n"); + PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n"); if (fps) { if (fps < 4 || fps > 30) { - Err("Framerate out of bounds (4-30).\n"); + PWC_ERROR("Framerate out of bounds (4-30).\n"); return -EINVAL; } default_fps = fps; - Info("Default framerate set to %d.\n", default_fps); + PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps); } - if (size[0]) { + if (size) { /* string; try matching with array */ for (sz = 0; sz < PSZ_MAX; sz++) { if (!strcmp(sizenames[sz], size)) { /* Found! */ @@ -2081,41 +1866,42 @@ static int __init usb_pwc_init(void) } } if (sz == PSZ_MAX) { - Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n"); + PWC_ERROR("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n"); return -EINVAL; } - Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y); + PWC_DEBUG_MODULE("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y); } if (mbufs) { if (mbufs < 1 || mbufs > MAX_IMAGES) { - Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES); + PWC_ERROR("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES); return -EINVAL; } - default_mbufs = mbufs; - Info("Number of image buffers set to %d.\n", default_mbufs); + pwc_mbufs = mbufs; + PWC_DEBUG_MODULE("Number of image buffers set to %d.\n", pwc_mbufs); } if (fbufs) { if (fbufs < 2 || fbufs > MAX_FRAMES) { - Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES); + PWC_ERROR("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES); return -EINVAL; } default_fbufs = fbufs; - Info("Number of frame buffers set to %d.\n", default_fbufs); + PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs); } - if (trace >= 0) { - Info("Trace options: 0x%04x\n", trace); - pwc_trace = trace; +#if CONFIG_PWC_DEBUG + if (pwc_trace >= 0) { + PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace); } +#endif if (compression >= 0) { if (compression > 3) { - Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n"); + PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n"); return -EINVAL; } pwc_preferred_compression = compression; - Info("Preferred compression set to %d.\n", pwc_preferred_compression); + PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression); } if (power_save) - Info("Enabling power save on open/close.\n"); + PWC_DEBUG_MODULE("Enabling power save on open/close.\n"); if (leds[0] >= 0) led_on = leds[0]; if (leds[1] >= 0) @@ -2146,14 +1932,14 @@ static int __init usb_pwc_init(void) dot++; /* Few sanity checks */ if (*dot != '\0' && dot > colon) { - Err("Malformed camera hint: the colon must be after the dot.\n"); + PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n"); return -EINVAL; } if (*colon == '\0') { /* No colon */ if (*dot != '\0') { - Err("Malformed camera hint: no colon + device node given.\n"); + PWC_ERROR("Malformed camera hint: no colon + device node given.\n"); return -EINVAL; } else { @@ -2178,28 +1964,27 @@ static int __init usb_pwc_init(void) device_hint[i].serial_number[k] = '\0'; } } -#if PWC_DEBUG - Debug("device_hint[%d]:\n", i); - Debug(" type : %d\n", device_hint[i].type); - Debug(" serial# : %s\n", device_hint[i].serial_number); - Debug(" node : %d\n", device_hint[i].device_node); -#endif + PWC_TRACE("device_hint[%d]:\n", i); + PWC_TRACE(" type : %d\n", device_hint[i].type); + PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number); + PWC_TRACE(" node : %d\n", device_hint[i].device_node); } else device_hint[i].type = 0; /* not filled */ } /* ..for MAX_DEV_HINTS */ - Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver); + PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver); return usb_register(&pwc_driver); } static void __exit usb_pwc_exit(void) { - Trace(TRACE_MODULE, "Deregistering driver.\n"); + PWC_DEBUG_MODULE("Deregistering driver.\n"); usb_deregister(&pwc_driver); - Info("Philips webcam module removed.\n"); + PWC_INFO("Philips webcam module removed.\n"); } module_init(usb_pwc_init); module_exit(usb_pwc_exit); +/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ diff --git a/drivers/media/video/pwc/pwc-kiara.c b/drivers/media/video/pwc/pwc-kiara.c index 4c96037..fec39cc 100644 --- a/drivers/media/video/pwc/pwc-kiara.c +++ b/drivers/media/video/pwc/pwc-kiara.c @@ -1,5 +1,5 @@ /* Linux driver for Philips webcam - (C) 2004 Luc Saillard (luc@saillard.org) + (C) 2004-2006 Luc Saillard (luc@saillard.org) NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx driver and thus may have bugs that are not present in the original version. @@ -316,3 +316,576 @@ const struct Kiara_table_entry Kiara_tab }, }; + +/* + * Rom table for kiara chips + * + * 32 roms tables (one for each resolution ?) + * 2 tables per roms (one for each passes) (Y, and U&V) + * 128 bytes per passes + */ + +const unsigned int KiaraRomTable [8][2][16][8] = +{ + { /* version 0 */ + { /* version 0, passes 0 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000001,0x00000001}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000009,0x00000009,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00000009,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000249,0x0000024a,0x00000049}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000249,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000249, + 0x00000249,0x0000124a,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000249, + 0x0000124a,0x00009252,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00009252,0x00009292,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009292,0x00009292,0x00009493,0x000124db}, + {0x00000000,0x00000000,0x00000249,0x0000924a, + 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x0000a493,0x000124db,0x000124db,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x000124db,0x000126dc,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000124db,0x000136e4,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 0, passes 1 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}, + {0x00000000,0x00000000,0x00000001,0x00000009, + 0x00000009,0x00000009,0x00000009,0x00000001}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000249,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00001252}, + {0x00000000,0x00000000,0x00000049,0x00001249, + 0x0000124a,0x0000124a,0x00001252,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009252,0x00009252,0x00009292,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x0000924a, + 0x00009292,0x00009292,0x00009292,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x00009292, + 0x00009492,0x00009493,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x0000a493,0x000124db,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00009252,0x00009493, + 0x000126dc,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000136e4,0x000136e4,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 1 */ + { /* version 1, passes 0 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000001}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000009,0x00000009,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00001252}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x0000124a,0x00009252,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009252,0x00009292,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009252,0x00009292,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x0000924a, + 0x00009252,0x00009493,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x0000924a, + 0x00009292,0x00009493,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x00009252, + 0x00009492,0x00009493,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x000124db,0x000124db,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000126dc,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 1, passes 1 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}, + {0x00000000,0x00000000,0x00000049,0x00000009, + 0x00000049,0x00000009,0x00000001,0x00000000}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000000}, + {0x00000000,0x00000000,0x00000249,0x00000049, + 0x00000249,0x00000049,0x0000024a,0x00000001}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00000001}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00000001}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x0000024a,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x0000024a,0x00000009}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x00009252,0x00001252,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x00009292,0x00001252,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x00009292,0x00001252,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009292,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x0000924a,0x0000924a, + 0x00009492,0x00009493,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 2 */ + { /* version 2, passes 0 */ + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x0000124a,0x00001252,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x00009252,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x0000124a,0x00009292,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009252,0x00009493,0x00009493,0x0000a49b}, + {0x00000000,0x00000000,0x00000249,0x0000924a, + 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009292,0x00009493,0x0000a49b,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x000124db,0x000124db,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x0000a493,0x000124db,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x000136e4}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000136e4,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x00009252,0x000124db, + 0x000126dc,0x0001b724,0x0001b725,0x0001b925}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 2, passes 1 */ + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00000249, + 0x0000124a,0x0000124a,0x00001252,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x00009292,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009292,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x0000a49b,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009493,0x0000a49b,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009493,0x0000a49b,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x0000a49b,0x0000a49b,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x00009252,0x0000a49b, + 0x0001249b,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 3 */ + { /* version 3, passes 0 */ + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x000124db,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000126dc,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000136e4,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000136e4,0x0001b725,0x0001b925}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x000136e4,0x0001b925,0x00025bb6,0x00024b77}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 3, passes 1 */ + {0x00000000,0x00000000,0x00001249,0x00000249, + 0x0000124a,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x00009493,0x0000a49b,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x0000a49b,0x000126dc,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00009492,0x0000a49b, + 0x000136e4,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x0001b724,0x0001b724,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 4 */ + { /* version 4, passes 0 */ + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000249,0x00000049, + 0x00000249,0x00000249,0x0000024a,0x00000049}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x00009252,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009493,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009292,0x00009493,0x00009493,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000124db,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0001249b,0x000126dc,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00009252,0x00009493, + 0x000124db,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009252,0x0000a49b, + 0x000124db,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00009492,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 4, passes 1 */ + {0x00000000,0x00000000,0x00000249,0x00000049, + 0x00000009,0x00000009,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000049,0x00000049,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x00000249,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x0000124a,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009252,0x0000124a,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x00009252,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x00009292,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x00009292,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x00009493,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000124db,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009252,0x000124db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 5 */ + { /* version 5, passes 0 */ + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x0000a49b,0x000124db,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b725,0x000136e4}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, + {0x00000000,0x00000000,0x00009492,0x0000a49b, + 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b925,0x0001c96e,0x0001b925}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 5, passes 1 */ + {0x00000000,0x00000000,0x00001249,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009252,0x00009252,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x0000a49b,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000124db,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000124db,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x000126dc,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009292,0x000124db, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 6 */ + { /* version 6, passes 0 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000136e4,0x0001b724,0x0001b92d,0x000136e4}, + {0x00000000,0x00000000,0x00009492,0x0000a49b, + 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, + {0x00000000,0x00000000,0x00012492,0x000126db, + 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 6, passes 1 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x00009252,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x00009292,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x0000a49b,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000124db,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 7 */ + { /* version 7, passes 0 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x0000a49b, + 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000136e4,0x0001b725,0x000124db}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x000124db, + 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b724,0x0001c96e,0x000136e4}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001b924,0x0001c92d,0x00024b76,0x0002496e}, + {0x00000000,0x00000000,0x00012492,0x000136db, + 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 7, passes 1 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x00009492,0x00009292,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x0000a49b,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x000124db,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000136db, + 0x0001b724,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000136db, + 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00009292,0x000136db, + 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009492,0x000136db, + 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00012492,0x0001b6db, + 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + } +}; + diff --git a/drivers/media/video/pwc/pwc-kiara.h b/drivers/media/video/pwc/pwc-kiara.h index 12929ab..0bdb225 100644 --- a/drivers/media/video/pwc/pwc-kiara.h +++ b/drivers/media/video/pwc/pwc-kiara.h @@ -1,5 +1,5 @@ /* Linux driver for Philips webcam - (C) 2004 Luc Saillard (luc@saillard.org) + (C) 2004-2006 Luc Saillard (luc@saillard.org) NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx driver and thus may have bugs that are not present in the original version. @@ -27,7 +27,7 @@ #ifndef PWC_KIARA_H #define PWC_KIARA_H -#include "pwc-ioctl.h" +#include struct Kiara_table_entry { @@ -37,8 +37,8 @@ struct Kiara_table_entry unsigned char mode[12]; /* precomputed mode settings for cam */ }; -const extern struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4]; -const extern unsigned int KiaraRomTable[8][2][16][8]; +extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4]; +extern const unsigned int KiaraRomTable[8][2][16][8]; #endif diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c index 58fe797..589c687 100644 --- a/drivers/media/video/pwc/pwc-misc.c +++ b/drivers/media/video/pwc/pwc-misc.c @@ -1,7 +1,7 @@ /* Linux driver for Philips webcam Various miscellaneous functions and tables. (C) 1999-2003 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) + (C) 2004-2006 Luc Saillard (luc@saillard.org) NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx driver and thus may have bugs that are not present in the original version. @@ -24,18 +24,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include #include "pwc.h" -struct pwc_coord pwc_image_sizes[PSZ_MAX] = +const struct pwc_coord pwc_image_sizes[PSZ_MAX] = { - { 128, 96, 0 }, - { 160, 120, 0 }, - { 176, 144, 0 }, - { 320, 240, 0 }, - { 352, 288, 0 }, - { 640, 480, 0 }, + { 128, 96, 0 }, /* sqcif */ + { 160, 120, 0 }, /* qsif */ + { 176, 144, 0 }, /* qcif */ + { 320, 240, 0 }, /* sif */ + { 352, 288, 0 }, /* cif */ + { 640, 480, 0 }, /* vga */ }; /* x,y -> PSZ_ */ @@ -52,7 +51,7 @@ int pwc_decode_size(struct pwc_device *p { if (width > pdev->abs_max.x || height > pdev->abs_max.y) { - Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n"); + PWC_DEBUG_SIZE("VIDEO_PALETTE_RAW: going beyond abs_max.\n"); return -1; } } @@ -60,7 +59,7 @@ int pwc_decode_size(struct pwc_device *p { if (width > pdev->view_max.x || height > pdev->view_max.y) { - Debug("VIDEO_PALETTE_ not RAW: going beyond view_max.\n"); + PWC_DEBUG_SIZE("VIDEO_PALETTE_not RAW: going beyond view_max.\n"); return -1; } } @@ -81,9 +80,8 @@ int pwc_decode_size(struct pwc_device *p /* initialize variables depending on type and decompressor*/ void pwc_construct(struct pwc_device *pdev) { - switch(pdev->type) { - case 645: - case 646: + if (DEVICE_USE_CODEC1(pdev->type)) { + pdev->view_min.x = 128; pdev->view_min.y = 96; pdev->view_max.x = 352; @@ -95,10 +93,23 @@ void pwc_construct(struct pwc_device *pd pdev->vendpoint = 4; pdev->frame_header_size = 0; pdev->frame_trailer_size = 0; - break; - case 675: - case 680: - case 690: + + } else if (DEVICE_USE_CODEC3(pdev->type)) { + + pdev->view_min.x = 160; + pdev->view_min.y = 120; + pdev->view_max.x = 640; + pdev->view_max.y = 480; + pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; + pdev->abs_max.x = 640; + pdev->abs_max.y = 480; + pdev->vcinterface = 3; + pdev->vendpoint = 5; + pdev->frame_header_size = TOUCAM_HEADER_SIZE; + pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE; + + } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ { + pdev->view_min.x = 128; pdev->view_min.y = 96; /* Anthill bug #38: PWC always reports max size, even without PWCX */ @@ -111,30 +122,12 @@ void pwc_construct(struct pwc_device *pd pdev->vendpoint = 4; pdev->frame_header_size = 0; pdev->frame_trailer_size = 0; - break; - case 720: - case 730: - case 740: - case 750: - pdev->view_min.x = 160; - pdev->view_min.y = 120; - pdev->view_max.x = 640; - pdev->view_max.y = 480; - pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; - pdev->abs_max.x = 640; - pdev->abs_max.y = 480; - pdev->vcinterface = 3; - pdev->vendpoint = 5; - pdev->frame_header_size = TOUCAM_HEADER_SIZE; - pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE; - break; } - Debug("type = %d\n",pdev->type); pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */ pdev->view_min.size = pdev->view_min.x * pdev->view_min.y; pdev->view_max.size = pdev->view_max.x * pdev->view_max.y; /* length of image, in YUV format; always allocate enough memory. */ - pdev->len_per_image = (pdev->abs_max.x * pdev->abs_max.y * 3) / 2; + pdev->len_per_image = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2); } diff --git a/drivers/media/video/pwc/pwc-timon.c b/drivers/media/video/pwc/pwc-timon.c index 175250d..be65bdc 100644 --- a/drivers/media/video/pwc/pwc-timon.c +++ b/drivers/media/video/pwc/pwc-timon.c @@ -1,5 +1,5 @@ /* Linux driver for Philips webcam - (C) 2004 Luc Saillard (luc@saillard.org) + (C) 2004-2006 Luc Saillard (luc@saillard.org) NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx driver and thus may have bugs that are not present in the original version. @@ -314,3 +314,1133 @@ const struct Timon_table_entry Timon_tab }, }; +/* + * 16 versions: + * 2 tables (one for Y, and one for U&V) + * 16 levels of details per tables + * 8 blocs + */ + +const unsigned int TimonRomTable [16][2][16][8] = +{ + { /* version 0 */ + { /* version 0, passes 0 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000001}, + {0x00000000,0x00000000,0x00000001,0x00000001, + 0x00000001,0x00000001,0x00000001,0x00000001}, + {0x00000000,0x00000000,0x00000001,0x00000001, + 0x00000001,0x00000009,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00000009,0x00000001, + 0x00000009,0x00000009,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000009,0x00000009,0x00000049,0x00000009}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000009,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000009,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000249,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000249,0x00000249,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000249,0x0000124a,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000249, + 0x00000249,0x0000124a,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x0000124a,0x00009252,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 0, passes 1 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}, + {0x00000000,0x00000000,0x00000001,0x00000001, + 0x00000001,0x00000001,0x00000000,0x00000000}, + {0x00000000,0x00000000,0x00000009,0x00000001, + 0x00000001,0x00000009,0x00000000,0x00000000}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000009,0x00000009,0x00000000,0x00000000}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000009,0x00000009,0x00000001,0x00000000}, + {0x00000000,0x00000000,0x00000049,0x00000009, + 0x00000009,0x00000049,0x00000001,0x00000001}, + {0x00000000,0x00000000,0x00000049,0x00000009, + 0x00000009,0x00000049,0x00000001,0x00000001}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000009,0x00000001}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000009,0x00000001}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000009,0x00000001}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000249,0x00000049,0x00000009}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000249,0x00000049,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00000049, + 0x00000249,0x00000249,0x00000049,0x00000009}, + {0x00000000,0x00000000,0x00001249,0x00000249, + 0x0000124a,0x0000124a,0x0000024a,0x00000049}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 1 */ + { /* version 1, passes 0 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000001}, + {0x00000000,0x00000000,0x00000001,0x00000001, + 0x00000001,0x00000009,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000009,0x00000009,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000009,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000009,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000249,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00001252}, + {0x00000000,0x00000000,0x00000049,0x00000249, + 0x00000249,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00000049,0x00000249, + 0x0000124a,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x0000124a,0x00009252,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009252,0x00009252,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x0000924a, + 0x00009292,0x00009493,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 1, passes 1 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000009,0x00000001,0x00000001,0x00000000}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000009,0x00000009,0x00000001,0x00000000}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000009,0x00000001,0x00000000}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000001,0x00000001}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000009,0x00000001}, + {0x00000000,0x00000000,0x00000249,0x00000049, + 0x00000049,0x00000249,0x00000009,0x00000001}, + {0x00000000,0x00000000,0x00000249,0x00000049, + 0x00000249,0x00000249,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x00000049,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x0000124a,0x00000049,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x0000124a,0x00000049,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x0000124a,0x0000024a,0x00000049}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x0000024a,0x00000049}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x0000024a,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009252,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 2 */ + { /* version 2, passes 0 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000001}, + {0x00000000,0x00000000,0x00000009,0x00000009, + 0x00000009,0x00000009,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000049,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00001252}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x0000124a,0x00009252,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009252,0x00009292,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009252,0x00009292,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x0000924a, + 0x00009252,0x00009493,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x0000924a, + 0x00009292,0x00009493,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x00009252, + 0x00009492,0x00009493,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x000124db,0x000124db,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000126dc,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 2, passes 1 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}, + {0x00000000,0x00000000,0x00000049,0x00000009, + 0x00000049,0x00000009,0x00000001,0x00000000}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000000}, + {0x00000000,0x00000000,0x00000249,0x00000049, + 0x00000249,0x00000049,0x0000024a,0x00000001}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00000001}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00000001}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x0000024a,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x0000024a,0x00000009}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x00009252,0x00001252,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x00009292,0x00001252,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x00009292,0x00001252,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009292,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x0000924a,0x0000924a, + 0x00009492,0x00009493,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 3 */ + { /* version 3, passes 0 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000001}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000049,0x00000249, + 0x00000249,0x00000249,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x00009252,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x0000124a,0x00009292,0x00009292,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009252,0x00009292,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009292,0x00009493,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x00009252, + 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x00009292,0x0000a49b,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x0000a49b,0x000124db,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x0000a493,0x0000a49b,0x000124db,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0001249b,0x000126dc,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000136e4,0x0001b725,0x000136e4}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 3, passes 1 */ + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000}, + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000001,0x00000000}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x00000049,0x00000001}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x0000124a,0x00001252,0x00000001}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x00001252,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x0000124a,0x00009252,0x00009292,0x00000009}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x00009252,0x00009292,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009252,0x00009292,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009493,0x00009292,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009493,0x00009292,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009493,0x00009493,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009292,0x00009493,0x00009493,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x00009493,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x00009492,0x0000a49b,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x00009292, + 0x0000a493,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 4 */ + { /* version 4, passes 0 */ + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x0000124a,0x00001252,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x00009252,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x0000124a,0x00009292,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009252,0x00009493,0x00009493,0x0000a49b}, + {0x00000000,0x00000000,0x00000249,0x0000924a, + 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009292,0x00009493,0x0000a49b,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x000124db,0x000124db,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x0000a493,0x000124db,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x000136e4}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000136e4,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x00009252,0x000124db, + 0x000126dc,0x0001b724,0x0001b725,0x0001b925}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 4, passes 1 */ + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00000249, + 0x0000124a,0x0000124a,0x00001252,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x00009292,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009292,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x0000a49b,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009493,0x0000a49b,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009493,0x0000a49b,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x0000a49b,0x0000a49b,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x00009252,0x0000a49b, + 0x0001249b,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 5 */ + { /* version 5, passes 0 */ + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x0000124a,0x00001252,0x00009292}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x0000124a,0x00009292,0x00009292,0x00009493}, + {0x00000000,0x00000000,0x00000249,0x0000924a, + 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x0000a49b,0x000124db,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x0000a493,0x000124db,0x000124db,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0001249b,0x000126dc,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000126dc,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b724,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 5, passes 1 */ + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009493,0x00009493,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009493,0x00009493,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009493,0x0000a49b,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x00009493,0x000124db,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x00009493,0x000124db,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x0000a49b,0x000124db,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x0000a49b,0x000124db,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000124db,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000124db,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000124db,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009252,0x000124db, + 0x000126dc,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 6 */ + { /* version 6, passes 0 */ + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x0000124a,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x000124db,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000126dc,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000136e4,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000136e4,0x0001b725,0x0001b925}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x000136e4,0x0001b925,0x00025bb6,0x00024b77}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 6, passes 1 */ + {0x00000000,0x00000000,0x00001249,0x00000249, + 0x0000124a,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x00009493,0x0000a49b,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x0000a49b,0x000126dc,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00009492,0x0000a49b, + 0x000136e4,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x0001b724,0x0001b724,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 7 */ + { /* version 7, passes 0 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009493,0x0000a49b,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x0000a493,0x0000a49b,0x000124db,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x000136e4}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00001249,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000136e4,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000136e4,0x0001b725,0x0001b925}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x00009292,0x000124db, + 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b724,0x0001c96e,0x0002496e}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x000136e4,0x0001b925,0x0001c96e,0x0002496e}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b724,0x0002496d,0x00025bb6,0x00025bbf}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 7, passes 1 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x00009493,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x000124db,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000124db,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x000124db,0x000136e4,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x000124db,0x000136e4,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000124db,0x000136e4,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x000136e4,0x0001b724,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00012492,0x000126db, + 0x0001b724,0x0001b925,0x0001b725,0x000136e4}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 8 */ + { /* version 8, passes 0 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009292,0x00009493,0x0000a49b,0x000124db}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x0000a493,0x000124db,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x000136e4}, + {0x00000000,0x00000000,0x00001249,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000136e4,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000136e4,0x0001b725,0x0001b925}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, + {0x00000000,0x00000000,0x00009252,0x000124db, + 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, + {0x00000000,0x00000000,0x00009292,0x000124db, + 0x000126dc,0x0001b925,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b925,0x00024b76,0x00024b77}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x000136e4,0x0001b925,0x00024b76,0x00025bbf}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x000136e4,0x0001c92d,0x00024b76,0x00025bbf}, + {0x00000000,0x00000000,0x00012492,0x000136db, + 0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 8, passes 1 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009493,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x000124db,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x000124db,0x000136e4,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000126dc,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00009292,0x000124db, + 0x000136e4,0x0001b724,0x0001b725,0x000136e4}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x000136e4,0x0001b925,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x000136e4,0x0001b925,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b724,0x0002496d,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 9 */ + { /* version 9, passes 0 */ + {0x00000000,0x00000000,0x00000049,0x00000049, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00000249,0x00000049, + 0x00000249,0x00000249,0x0000024a,0x00000049}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x0000124a,0x00009252,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009493,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009292,0x00009493,0x00009493,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000124db,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0001249b,0x000126dc,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00009252,0x00009493, + 0x000124db,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009252,0x0000a49b, + 0x000124db,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00009492,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 9, passes 1 */ + {0x00000000,0x00000000,0x00000249,0x00000049, + 0x00000009,0x00000009,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000049,0x00000049,0x00000009,0x00000009}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x00000249,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x0000124a,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009252,0x0000124a,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x00009252,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x00009292,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x00009292,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x00009493,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000124db,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009252,0x000124db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 10 */ + { /* version 10, passes 0 */ + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00000249,0x00001249, + 0x00009252,0x00009292,0x00009292,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x00009493,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x000124db,0x000124db,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000124db,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0001249b,0x000126dc,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000126dc,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009252,0x0000a49b, + 0x000124db,0x000136e4,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x00009492,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b92d,0x0001b724}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000126dc,0x0001b925,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x000136e4,0x0002496d,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 10, passes 1 */ + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000049,0x00000049,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x00000249,0x00000049,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x00009252,0x0000024a,0x00000049}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009493,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00009252, + 0x00009492,0x00009493,0x00001252,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x00009493,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x00009492,0x00009493,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x00009493,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009252,0x000126db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 11 */ + { /* version 11, passes 0 */ + {0x00000000,0x00000000,0x00000249,0x00000249, + 0x00000249,0x00000249,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x0000a49b,0x000124db,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b725,0x000136e4}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, + {0x00000000,0x00000000,0x00009492,0x0000a49b, + 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b925,0x0001c96e,0x0001b925}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 11, passes 1 */ + {0x00000000,0x00000000,0x00001249,0x00000249, + 0x00000249,0x00000249,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009252,0x00009252,0x0000024a,0x0000024a}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x0000a49b,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x0000a49b,0x00009292,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000124db,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000124db,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x000126dc,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009292,0x000124db, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 12 */ + { /* version 12, passes 0 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000136e4,0x0001b724,0x0001b92d,0x000136e4}, + {0x00000000,0x00000000,0x00009492,0x0000a49b, + 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, + {0x00000000,0x00000000,0x00012492,0x000126db, + 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 12, passes 1 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x00001249,0x00009292, + 0x00009492,0x00009252,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x00009292,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x0000a49b,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000124db,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000124db,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00009492,0x000126db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 13 */ + { /* version 13, passes 0 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x00009252,0x00009292,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x000124db,0x000126dc,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x0000a49b, + 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x000136e4,0x0001b725,0x000124db}, + {0x00000000,0x00000000,0x00009292,0x0000a49b, + 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, + {0x00000000,0x00000000,0x00009292,0x000124db, + 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b724,0x0001c96e,0x000136e4}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001b924,0x0001c92d,0x00024b76,0x0002496e}, + {0x00000000,0x00000000,0x00012492,0x000136db, + 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 13, passes 1 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x00009492,0x00009292,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x0000a49b,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x000124db,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000136db, + 0x0001b724,0x000124db,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000136db, + 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00009292,0x000136db, + 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x00009492,0x000136db, + 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00012492,0x0001b6db, + 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 14 */ + { /* version 14, passes 0 */ + {0x00000000,0x00000000,0x00001249,0x0000924a, + 0x00009292,0x00009493,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00001249,0x0000a49b, + 0x0000a493,0x000124db,0x000126dc,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x000136e4,0x0001b725,0x000124db}, + {0x00000000,0x00000000,0x00009292,0x000124db, + 0x000126dc,0x0001b724,0x0001b92d,0x000126dc}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b724,0x0001b92d,0x000126dc}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001c92d,0x0001c96e,0x000136e4}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x0001b724,0x0001c92d,0x00024b76,0x0001b925}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b924,0x0002496d,0x00024b76,0x00024b77}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf}, + {0x00000000,0x00000000,0x00012492,0x0001b6db, + 0x00024924,0x0002db6d,0x00036db6,0x0002efff}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 14, passes 1 */ + {0x00000000,0x00000000,0x00001249,0x00001249, + 0x0000124a,0x0000124a,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x00009493, + 0x0000a493,0x00009292,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x0000a49b,0x00001252,0x00001252}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000136e4,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000136e4,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x000136e4,0x00009493,0x00009292}, + {0x00000000,0x00000000,0x00009492,0x000136db, + 0x0001b724,0x000136e4,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x00009492,0x000136db, + 0x0001b724,0x000136e4,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x00009492,0x000136db, + 0x0001b724,0x000136e4,0x0000a49b,0x00009493}, + {0x00000000,0x00000000,0x00009492,0x000136db, + 0x0001b724,0x000136e4,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b724,0x000136e4,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b724,0x000136e4,0x000124db,0x0000a49b}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b724,0x000136e4,0x000126dc,0x000124db}, + {0x00000000,0x00000000,0x00012492,0x0001b6db, + 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + }, + { /* version 15 */ + { /* version 15, passes 0 */ + {0x00000000,0x00000000,0x00001249,0x00009493, + 0x0000a493,0x0000a49b,0x000124db,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0001249b,0x000126dc,0x000136e4,0x000124db}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x0001b724,0x0001b92d,0x000126dc}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x000136e4,0x0001b925,0x0001c96e,0x000136e4}, + {0x00000000,0x00000000,0x00009492,0x000124db, + 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, + {0x00000000,0x00000000,0x0000a492,0x000124db, + 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, + {0x00000000,0x00000000,0x0000a492,0x000126db, + 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001b924,0x0002496d,0x00024b76,0x0002496e}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001c924,0x00024b6d,0x00025bb6,0x00024b77}, + {0x00000000,0x00000000,0x00012492,0x000136db, + 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, + {0x00000000,0x00000000,0x00012492,0x0001b6db, + 0x00024924,0x0002db6d,0x00036db6,0x0002efff}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + }, + { /* version 15, passes 1 */ + {0x00000000,0x00000000,0x0000924a,0x0000924a, + 0x00009292,0x00009292,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x0000a49b, + 0x0000a493,0x000124db,0x00009292,0x00009292}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000124db,0x0001b724,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000126dc,0x0001b724,0x00009493,0x00009493}, + {0x00000000,0x00000000,0x0000924a,0x000124db, + 0x000136e4,0x0001b724,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00009292,0x000136db, + 0x0001b724,0x0001b724,0x0000a49b,0x0000a49b}, + {0x00000000,0x00000000,0x00009492,0x000136db, + 0x0001c924,0x0001b724,0x000124db,0x000124db}, + {0x00000000,0x00000000,0x00009492,0x000136db, + 0x0001c924,0x0001b724,0x000124db,0x000124db}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001c924,0x0001b724,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001c924,0x0001b925,0x000126dc,0x000126dc}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001c924,0x0001b925,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001c924,0x0001b925,0x000136e4,0x000136e4}, + {0x00000000,0x00000000,0x0000a492,0x000136db, + 0x0001c924,0x0001b925,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x00012492,0x000136db, + 0x0001c924,0x0001b925,0x0001b725,0x0001b724}, + {0x00000000,0x00000000,0x00012492,0x0001b6db, + 0x00024924,0x0002496d,0x0001b92d,0x0001b925}, + {0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000} + } + } +}; diff --git a/drivers/media/video/pwc/pwc-timon.h b/drivers/media/video/pwc/pwc-timon.h index a86b378..eef9e2c 100644 --- a/drivers/media/video/pwc/pwc-timon.h +++ b/drivers/media/video/pwc/pwc-timon.h @@ -1,5 +1,5 @@ /* Linux driver for Philips webcam - (C) 2004 Luc Saillard (luc@saillard.org) + (C) 2004-2006 Luc Saillard (luc@saillard.org) NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx driver and thus may have bugs that are not present in the original version. @@ -42,7 +42,7 @@ #ifndef PWC_TIMON_H #define PWC_TIMON_H -#include "pwc-ioctl.h" +#include struct Timon_table_entry { @@ -52,8 +52,8 @@ struct Timon_table_entry unsigned char mode[13]; /* precomputed mode settings for cam */ }; -const extern struct Timon_table_entry Timon_table[PSZ_MAX][6][4]; -const extern unsigned int TimonRomTable [16][2][16][8]; +extern const struct Timon_table_entry Timon_table[PSZ_MAX][6][4]; +extern const unsigned int TimonRomTable [16][2][16][8]; #endif diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c index b37a89a..5d82028 100644 --- a/drivers/media/video/pwc/pwc-uncompress.c +++ b/drivers/media/video/pwc/pwc-uncompress.c @@ -1,7 +1,7 @@ /* Linux driver for Philips webcam Decompression frontend. (C) 1999-2003 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) + (C) 2004-2006 Luc Saillard (luc@saillard.org) NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx driver and thus may have bugs that are not present in the original version. @@ -22,6 +22,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + vim: set ts=8: */ #include @@ -29,6 +31,8 @@ #include #include "pwc.h" #include "pwc-uncompress.h" +#include "pwc-dec1.h" +#include "pwc-dec23.h" int pwc_decompress(struct pwc_device *pdev) { @@ -40,107 +44,95 @@ int pwc_decompress(struct pwc_device *pd if (pdev == NULL) return -EFAULT; -#if defined(__KERNEL__) && defined(PWC_MAGIC) - if (pdev->magic != PWC_MAGIC) { - Err("pwc_decompress(): magic failed.\n"); - return -EFAULT; - } -#endif fbuf = pdev->read_frame; if (fbuf == NULL) return -EFAULT; - image = pdev->image_ptr[pdev->fill_image]; - if (!image) - return -EFAULT; + image = pdev->image_data; + image += pdev->images[pdev->fill_image].offset; yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ /* Raw format; that's easy... */ if (pdev->vpalette == VIDEO_PALETTE_RAW) { - memcpy(image, yuv, pdev->frame_size); + struct pwc_raw_frame *raw_frame = image; + raw_frame->type = cpu_to_le16(pdev->type); + raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength); + /* cmd_buf is always 4 bytes, but sometimes, only the + * first 3 bytes is filled (Nala case). We can + * determine this using the type of the webcam */ + memcpy(raw_frame->cmd, pdev->cmd_buf, 4); + memcpy(raw_frame+1, yuv, pdev->frame_size); return 0; } if (pdev->vbandlength == 0) { - /* Uncompressed mode. We copy the data into the output buffer, - using the viewport size (which may be larger than the image - size). Unfortunately we have to do a bit of byte stuffing - to get the desired output format/size. + /* Uncompressed mode. + * We copy the data into the output buffer, using the viewport + * size (which may be larger than the image size). + * Unfortunately we have to do a bit of byte stuffing to get + * the desired output format/size. + * + * We do some byte shuffling here to go from the + * native format to YUV420P. */ - /* - * We do some byte shuffling here to go from the - * native format to YUV420P. - */ - src = (u16 *)yuv; - n = pdev->view.x * pdev->view.y; - - /* offset in Y plane */ - stride = pdev->view.x * pdev->offset.y + pdev->offset.x; - dsty = (u16 *)(image + stride); - - /* offsets in U/V planes */ - stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; - dstu = (u16 *)(image + n + stride); - dstv = (u16 *)(image + n + n / 4 + stride); - - /* increment after each line */ - stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ - - for (line = 0; line < pdev->image.y; line++) { - for (col = 0; col < pdev->image.x; col += 4) { - *dsty++ = *src++; - *dsty++ = *src++; - if (line & 1) - *dstv++ = *src++; - else - *dstu++ = *src++; - } - dsty += stride; + src = (u16 *)yuv; + n = pdev->view.x * pdev->view.y; + + /* offset in Y plane */ + stride = pdev->view.x * pdev->offset.y + pdev->offset.x; + dsty = (u16 *)(image + stride); + + /* offsets in U/V planes */ + stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; + dstu = (u16 *)(image + n + stride); + dstv = (u16 *)(image + n + n / 4 + stride); + + /* increment after each line */ + stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ + + for (line = 0; line < pdev->image.y; line++) { + for (col = 0; col < pdev->image.x; col += 4) { + *dsty++ = *src++; + *dsty++ = *src++; if (line & 1) - dstv += (stride >> 1); + *dstv++ = *src++; else - dstu += (stride >> 1); + *dstu++ = *src++; } + dsty += stride; + if (line & 1) + dstv += (stride >> 1); + else + dstu += (stride >> 1); + } + + return 0; } - else { - /* Compressed; the decompressor routines will write the data - in planar format immediately. - */ - int flags; - - flags = PWCX_FLAG_PLANAR; - if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) - { - printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n"); - flags |= PWCX_FLAG_BAYER; - return -ENXIO; /* No such device or address: missing decompressor */ - } - -#if 0 - switch (pdev->type) - { - case 675: - case 680: - case 690: - case 720: - case 730: - case 740: - case 750: - pwc_dec23_decompress(&pdev->image, &pdev->view, - &pdev->offset, yuv, image, flags, - pdev->decompress_data, pdev->vbandlength); - break; - case 645: - case 646: - /* TODO & FIXME */ - return -ENXIO; /* Missing decompressor */ - break; - } -#endif + + /* + * Compressed; + * the decompressor routines will write the data in planar format + * immediately. + */ + if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) { + PWC_ERROR("Mode Bayer is not supported for now\n"); + /* flags |= PWCX_FLAG_BAYER; */ + return -ENXIO; /* No such device or address: missing decompressor */ + } + + if (DEVICE_USE_CODEC1(pdev->type)) { + + /* TODO & FIXME */ + PWC_ERROR("This chipset is not supported for now\n"); + return -ENXIO; /* No such device or address: missing decompressor */ + + } else { + pwc_dec23_decompress(pdev, yuv, image, PWCX_FLAG_PLANAR); } return 0; } +/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ diff --git a/drivers/media/video/pwc/pwc-uncompress.h b/drivers/media/video/pwc/pwc-uncompress.h index f75e1b6..041227f 100644 --- a/drivers/media/video/pwc/pwc-uncompress.h +++ b/drivers/media/video/pwc/pwc-uncompress.h @@ -1,5 +1,5 @@ /* (C) 1999-2003 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) + (C) 2004-2006 Luc Saillard (luc@saillard.org) NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx driver and thus may have bugs that are not present in the original version. @@ -32,7 +32,7 @@ #define PWC_UNCOMPRESS_H #include -#include "pwc-ioctl.h" +#include /* from pwc-dec.h */ #define PWCX_FLAG_PLANAR 0x0001 diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c new file mode 100644 index 0000000..b7eb3ce --- /dev/null +++ b/drivers/media/video/pwc/pwc-v4l.c @@ -0,0 +1,1202 @@ +/* Linux driver for Philips webcam + USB and Video4Linux interface part. + (C) 1999-2004 Nemosoft Unv. + (C) 2004-2006 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to . + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pwc.h" + +static struct v4l2_queryctrl pwc_controls[] = { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 128, + .step = 1, + .default_value = 64, + }, + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 64, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = -100, + .maximum = 100, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_GAMMA, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gamma", + .minimum = 0, + .maximum = 32, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Gain", + .minimum = 0, + .maximum = 256, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Gain", + .minimum = 0, + .maximum = 256, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_AUTO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto White Balance", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Shutter Speed (Exposure)", + .minimum = 0, + .maximum = 256, + .step = 1, + .default_value = 200, + }, + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Gain Enabled", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain Level", + .minimum = 0, + .maximum = 256, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_SAVE_USER, + .type = V4L2_CTRL_TYPE_BUTTON, + .name = "Save User Settings", + .minimum = 0, + .maximum = 0, + .step = 0, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_RESTORE_USER, + .type = V4L2_CTRL_TYPE_BUTTON, + .name = "Restore User Settings", + .minimum = 0, + .maximum = 0, + .step = 0, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_RESTORE_FACTORY, + .type = V4L2_CTRL_TYPE_BUTTON, + .name = "Restore Factory Settings", + .minimum = 0, + .maximum = 0, + .step = 0, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_COLOUR_MODE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Colour mode", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_AUTOCONTOUR, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto contour", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_CONTOUR, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contour", + .minimum = 0, + .maximum = 63, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_BACKLIGHT, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Backlight compensation", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_FLICKERLESS, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flickerless", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_NOISE_REDUCTION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Noise reduction", + .minimum = 0, + .maximum = 3, + .step = 1, + .default_value = 0, + }, +}; + + +static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f) +{ + memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); + f->fmt.pix.width = pdev->view.x; + f->fmt.pix.height = pdev->view.y; + f->fmt.pix.field = V4L2_FIELD_NONE; + if (pdev->vpalette == VIDEO_PALETTE_YUV420P) { + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; + f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + } else { + /* vbandlength contains 4 lines ... */ + f->fmt.pix.bytesperline = pdev->vbandlength/4; + f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame); + if (DEVICE_USE_CODEC1(pdev->type)) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC1; + else + f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC2; + } + PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() " + "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n", + f->fmt.pix.width, + f->fmt.pix.height, + f->fmt.pix.bytesperline, + f->fmt.pix.sizeimage, + (f->fmt.pix.pixelformat)&255, + (f->fmt.pix.pixelformat>>8)&255, + (f->fmt.pix.pixelformat>>16)&255, + (f->fmt.pix.pixelformat>>24)&255); +} + +/* ioctl(VIDIOC_TRY_FMT) */ +static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) +{ + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); + return -EINVAL; + } + + switch (f->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_YUV420: + break; + case V4L2_PIX_FMT_PWC1: + if (DEVICE_USE_CODEC23(pdev->type)) { + PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n"); + return -EINVAL; + } + break; + case V4L2_PIX_FMT_PWC2: + if (DEVICE_USE_CODEC1(pdev->type)) { + PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n"); + return -EINVAL; + } + break; + default: + PWC_DEBUG_IOCTL("Unsupported pixel format\n"); + return -EINVAL; + + } + + if (f->fmt.pix.width > pdev->view_max.x) + f->fmt.pix.width = pdev->view_max.x; + else if (f->fmt.pix.width < pdev->view_min.x) + f->fmt.pix.width = pdev->view_min.x; + + if (f->fmt.pix.height > pdev->view_max.y) + f->fmt.pix.height = pdev->view_max.y; + else if (f->fmt.pix.height < pdev->view_min.y) + f->fmt.pix.height = pdev->view_min.y; + + return 0; +} + +/* ioctl(VIDIOC_SET_FMT) */ +static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f) +{ + int ret, fps, snapshot, compression, pixelformat; + + ret = pwc_vidioc_try_fmt(pdev, f); + if (ret<0) + return ret; + + pixelformat = f->fmt.pix.pixelformat; + compression = pdev->vcompression; + snapshot = 0; + fps = pdev->vframes; + if (f->fmt.pix.priv) { + compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT; + snapshot = !!(f->fmt.pix.priv & PWC_FPS_SNAPSHOT); + fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; + if (fps == 0) + fps = pdev->vframes; + } + + if (pixelformat == V4L2_PIX_FMT_YUV420) + pdev->vpalette = VIDEO_PALETTE_YUV420P; + else + pdev->vpalette = VIDEO_PALETTE_RAW; + + PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d " + "compression=%d snapshot=%d format=%c%c%c%c\n", + f->fmt.pix.width, f->fmt.pix.height, fps, + compression, snapshot, + (pixelformat)&255, + (pixelformat>>8)&255, + (pixelformat>>16)&255, + (pixelformat>>24)&255); + + ret = pwc_try_video_mode(pdev, + f->fmt.pix.width, + f->fmt.pix.height, + fps, + compression, + snapshot); + + PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret); + + if (ret) + return ret; + + pwc_vidioc_fill_fmt(pdev, f); + + return 0; + +} + +int pwc_video_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct video_device *vdev = video_devdata(file); + struct pwc_device *pdev; + DECLARE_WAITQUEUE(wait, current); + + if (vdev == NULL) + return -EFAULT; + pdev = vdev->priv; + if (pdev == NULL) + return -EFAULT; + +#if CONFIG_PWC_DEBUG + if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) + v4l_printk_ioctl(cmd); +#endif + + + switch (cmd) { + /* Query cabapilities */ + case VIDIOCGCAP: + { + struct video_capability *caps = arg; + + strcpy(caps->name, vdev->name); + caps->type = VID_TYPE_CAPTURE; + caps->channels = 1; + caps->audios = 1; + caps->minwidth = pdev->view_min.x; + caps->minheight = pdev->view_min.y; + caps->maxwidth = pdev->view_max.x; + caps->maxheight = pdev->view_max.y; + break; + } + + /* Channel functions (simulate 1 channel) */ + case VIDIOCGCHAN: + { + struct video_channel *v = arg; + + if (v->channel != 0) + return -EINVAL; + v->flags = 0; + v->tuners = 0; + v->type = VIDEO_TYPE_CAMERA; + strcpy(v->name, "Webcam"); + return 0; + } + + case VIDIOCSCHAN: + { + /* The spec says the argument is an integer, but + the bttv driver uses a video_channel arg, which + makes sense becasue it also has the norm flag. + */ + struct video_channel *v = arg; + if (v->channel != 0) + return -EINVAL; + return 0; + } + + + /* Picture functions; contrast etc. */ + case VIDIOCGPICT: + { + struct video_picture *p = arg; + int val; + + val = pwc_get_brightness(pdev); + if (val >= 0) + p->brightness = (val<<9); + else + p->brightness = 0xffff; + val = pwc_get_contrast(pdev); + if (val >= 0) + p->contrast = (val<<10); + else + p->contrast = 0xffff; + /* Gamma, Whiteness, what's the difference? :) */ + val = pwc_get_gamma(pdev); + if (val >= 0) + p->whiteness = (val<<11); + else + p->whiteness = 0xffff; + if (pwc_get_saturation(pdev, &val)<0) + p->colour = 0xffff; + else + p->colour = 32768 + val * 327; + p->depth = 24; + p->palette = pdev->vpalette; + p->hue = 0xFFFF; /* N/A */ + break; + } + + case VIDIOCSPICT: + { + struct video_picture *p = arg; + /* + * FIXME: Suppose we are mid read + ANSWER: No problem: the firmware of the camera + can handle brightness/contrast/etc + changes at _any_ time, and the palette + is used exactly once in the uncompress + routine. + */ + pwc_set_brightness(pdev, p->brightness); + pwc_set_contrast(pdev, p->contrast); + pwc_set_gamma(pdev, p->whiteness); + pwc_set_saturation(pdev, (p->colour-32768)/327); + if (p->palette && p->palette != pdev->vpalette) { + switch (p->palette) { + case VIDEO_PALETTE_YUV420P: + case VIDEO_PALETTE_RAW: + pdev->vpalette = p->palette; + return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); + break; + default: + return -EINVAL; + break; + } + } + break; + } + + /* Window/size parameters */ + case VIDIOCGWIN: + { + struct video_window *vw = arg; + + vw->x = 0; + vw->y = 0; + vw->width = pdev->view.x; + vw->height = pdev->view.y; + vw->chromakey = 0; + vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | + (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0); + break; + } + + case VIDIOCSWIN: + { + struct video_window *vw = arg; + int fps, snapshot, ret; + + fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; + snapshot = vw->flags & PWC_FPS_SNAPSHOT; + if (fps == 0) + fps = pdev->vframes; + if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot) + return 0; + ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot); + if (ret) + return ret; + break; + } + + /* We don't have overlay support (yet) */ + case VIDIOCGFBUF: + { + struct video_buffer *vb = arg; + + memset(vb,0,sizeof(*vb)); + break; + } + + /* mmap() functions */ + case VIDIOCGMBUF: + { + /* Tell the user program how much memory is needed for a mmap() */ + struct video_mbuf *vm = arg; + int i; + + memset(vm, 0, sizeof(*vm)); + vm->size = pwc_mbufs * pdev->len_per_image; + vm->frames = pwc_mbufs; /* double buffering should be enough for most applications */ + for (i = 0; i < pwc_mbufs; i++) + vm->offsets[i] = i * pdev->len_per_image; + break; + } + + case VIDIOCMCAPTURE: + { + /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */ + struct video_mmap *vm = arg; + + PWC_DEBUG_READ("VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format); + if (vm->frame < 0 || vm->frame >= pwc_mbufs) + return -EINVAL; + + /* xawtv is nasty. It probes the available palettes + by setting a very small image size and trying + various palettes... The driver doesn't support + such small images, so I'm working around it. + */ + if (vm->format) + { + switch (vm->format) + { + case VIDEO_PALETTE_YUV420P: + case VIDEO_PALETTE_RAW: + break; + default: + return -EINVAL; + break; + } + } + + if ((vm->width != pdev->view.x || vm->height != pdev->view.y) && + (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) { + int ret; + + PWC_DEBUG_OPEN("VIDIOCMCAPTURE: changing size to please xawtv :-(.\n"); + ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot); + if (ret) + return ret; + } /* ... size mismatch */ + + /* FIXME: should we lock here? */ + if (pdev->image_used[vm->frame]) + return -EBUSY; /* buffer wasn't available. Bummer */ + pdev->image_used[vm->frame] = 1; + + /* Okay, we're done here. In the SYNC call we wait until a + frame comes available, then expand image into the given + buffer. + In contrast to the CPiA cam the Philips cams deliver a + constant stream, almost like a grabber card. Also, + we have separate buffers for the rawdata and the image, + meaning we can nearly always expand into the requested buffer. + */ + PWC_DEBUG_READ("VIDIOCMCAPTURE done.\n"); + break; + } + + case VIDIOCSYNC: + { + /* The doc says: "Whenever a buffer is used it should + call VIDIOCSYNC to free this frame up and continue." + + The only odd thing about this whole procedure is + that MCAPTURE flags the buffer as "in use", and + SYNC immediately unmarks it, while it isn't + after SYNC that you know that the buffer actually + got filled! So you better not start a CAPTURE in + the same frame immediately (use double buffering). + This is not a problem for this cam, since it has + extra intermediate buffers, but a hardware + grabber card will then overwrite the buffer + you're working on. + */ + int *mbuf = arg; + int ret; + + PWC_DEBUG_READ("VIDIOCSYNC called (%d).\n", *mbuf); + + /* bounds check */ + if (*mbuf < 0 || *mbuf >= pwc_mbufs) + return -EINVAL; + /* check if this buffer was requested anyway */ + if (pdev->image_used[*mbuf] == 0) + return -EINVAL; + + /* Add ourselves to the frame wait-queue. + + FIXME: needs auditing for safety. + QUESTION: In what respect? I think that using the + frameq is safe now. + */ + add_wait_queue(&pdev->frameq, &wait); + while (pdev->full_frames == NULL) { + /* Check for unplugged/etc. here */ + if (pdev->error_status) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -pdev->error_status; + } + + if (signal_pending(current)) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -ERESTARTSYS; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + + /* The frame is ready. Expand in the image buffer + requested by the user. I don't care if you + mmap() 5 buffers and request data in this order: + buffer 4 2 3 0 1 2 3 0 4 3 1 . . . + Grabber hardware may not be so forgiving. + */ + PWC_DEBUG_READ("VIDIOCSYNC: frame ready.\n"); + pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */ + /* Decompress, etc */ + ret = pwc_handle_frame(pdev); + pdev->image_used[*mbuf] = 0; + if (ret) + return -EFAULT; + break; + } + + case VIDIOCGAUDIO: + { + struct video_audio *v = arg; + + strcpy(v->name, "Microphone"); + v->audio = -1; /* unknown audio minor */ + v->flags = 0; + v->mode = VIDEO_SOUND_MONO; + v->volume = 0; + v->bass = 0; + v->treble = 0; + v->balance = 0x8000; + v->step = 1; + break; + } + + case VIDIOCSAUDIO: + { + /* Dummy: nothing can be set */ + break; + } + + case VIDIOCGUNIT: + { + struct video_unit *vu = arg; + + vu->video = pdev->vdev->minor & 0x3F; + vu->audio = -1; /* not known yet */ + vu->vbi = -1; + vu->radio = -1; + vu->teletext = -1; + break; + } + + /* V4L2 Layer */ + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = arg; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCAP) This application "\ + "try to use the v4l2 layer\n"); + strcpy(cap->driver,PWC_NAME); + strlcpy(cap->card, vdev->name, sizeof(cap->card)); + usb_make_path(pdev->udev,cap->bus_info,sizeof(cap->bus_info)); + cap->version = PWC_VERSION_CODE; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + return 0; + } + + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *i = arg; + + if ( i->index ) /* Only one INPUT is supported */ + return -EINVAL; + + memset(i, 0, sizeof(struct v4l2_input)); + strcpy(i->name, "usb"); + return 0; + } + + case VIDIOC_G_INPUT: + { + int *i = arg; + *i = 0; /* Only one INPUT is supported */ + return 0; + } + case VIDIOC_S_INPUT: + { + int *i = arg; + + if ( *i ) { /* Only one INPUT is supported */ + PWC_DEBUG_IOCTL("Only one input source is"\ + " supported with this webcam.\n"); + return -EINVAL; + } + return 0; + } + + /* TODO: */ + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *c = arg; + int i; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) query id=%d\n", c->id); + for (i=0; iid) { + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n"); + memcpy(c,&pwc_controls[i],sizeof(struct v4l2_queryctrl)); + return 0; + } + } + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) not found\n"); + + return -EINVAL; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *c = arg; + int ret; + + switch (c->id) + { + case V4L2_CID_BRIGHTNESS: + c->value = pwc_get_brightness(pdev); + if (c->value<0) + return -EINVAL; + return 0; + case V4L2_CID_CONTRAST: + c->value = pwc_get_contrast(pdev); + if (c->value<0) + return -EINVAL; + return 0; + case V4L2_CID_SATURATION: + ret = pwc_get_saturation(pdev, &c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_GAMMA: + c->value = pwc_get_gamma(pdev); + if (c->value<0) + return -EINVAL; + return 0; + case V4L2_CID_RED_BALANCE: + ret = pwc_get_red_gain(pdev, &c->value); + if (ret<0) + return -EINVAL; + c->value >>= 8; + return 0; + case V4L2_CID_BLUE_BALANCE: + ret = pwc_get_blue_gain(pdev, &c->value); + if (ret<0) + return -EINVAL; + c->value >>= 8; + return 0; + case V4L2_CID_AUTO_WHITE_BALANCE: + ret = pwc_get_awb(pdev); + if (ret<0) + return -EINVAL; + c->value = (ret == PWC_WB_MANUAL)?0:1; + return 0; + case V4L2_CID_GAIN: + ret = pwc_get_agc(pdev, &c->value); + if (ret<0) + return -EINVAL; + c->value >>= 8; + return 0; + case V4L2_CID_AUTOGAIN: + ret = pwc_get_agc(pdev, &c->value); + if (ret<0) + return -EINVAL; + c->value = (c->value < 0)?1:0; + return 0; + case V4L2_CID_EXPOSURE: + ret = pwc_get_shutter_speed(pdev, &c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_COLOUR_MODE: + ret = pwc_get_colour_mode(pdev, &c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_AUTOCONTOUR: + ret = pwc_get_contour(pdev, &c->value); + if (ret < 0) + return -EINVAL; + c->value=(c->value == -1?1:0); + return 0; + case V4L2_CID_PRIVATE_CONTOUR: + ret = pwc_get_contour(pdev, &c->value); + if (ret < 0) + return -EINVAL; + c->value >>= 10; + return 0; + case V4L2_CID_PRIVATE_BACKLIGHT: + ret = pwc_get_backlight(pdev, &c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_FLICKERLESS: + ret = pwc_get_flicker(pdev, &c->value); + if (ret < 0) + return -EINVAL; + c->value=(c->value?1:0); + return 0; + case V4L2_CID_PRIVATE_NOISE_REDUCTION: + ret = pwc_get_dynamic_noise(pdev, &c->value); + if (ret < 0) + return -EINVAL; + return 0; + + case V4L2_CID_PRIVATE_SAVE_USER: + case V4L2_CID_PRIVATE_RESTORE_USER: + case V4L2_CID_PRIVATE_RESTORE_FACTORY: + return -EINVAL; + } + return -EINVAL; + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *c = arg; + int ret; + + switch (c->id) + { + case V4L2_CID_BRIGHTNESS: + c->value <<= 9; + ret = pwc_set_brightness(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_CONTRAST: + c->value <<= 10; + ret = pwc_set_contrast(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_SATURATION: + ret = pwc_set_saturation(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_GAMMA: + c->value <<= 11; + ret = pwc_set_gamma(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_RED_BALANCE: + c->value <<= 8; + ret = pwc_set_red_gain(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_BLUE_BALANCE: + c->value <<= 8; + ret = pwc_set_blue_gain(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_AUTO_WHITE_BALANCE: + c->value = (c->value == 0)?PWC_WB_MANUAL:PWC_WB_AUTO; + ret = pwc_set_awb(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_EXPOSURE: + c->value <<= 8; + ret = pwc_set_shutter_speed(pdev, c->value?0:1, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_AUTOGAIN: + /* autogain off means nothing without a gain */ + if (c->value == 0) + return 0; + ret = pwc_set_agc(pdev, c->value, 0); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_GAIN: + c->value <<= 8; + ret = pwc_set_agc(pdev, 0, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_SAVE_USER: + if (pwc_save_user(pdev)) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_RESTORE_USER: + if (pwc_restore_user(pdev)) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_RESTORE_FACTORY: + if (pwc_restore_factory(pdev)) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_COLOUR_MODE: + ret = pwc_set_colour_mode(pdev, c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_AUTOCONTOUR: + c->value=(c->value == 1)?-1:0; + ret = pwc_set_contour(pdev, c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_CONTOUR: + c->value <<= 10; + ret = pwc_set_contour(pdev, c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_BACKLIGHT: + ret = pwc_set_backlight(pdev, c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_FLICKERLESS: + ret = pwc_set_flicker(pdev, c->value); + if (ret < 0) + return -EINVAL; + case V4L2_CID_PRIVATE_NOISE_REDUCTION: + ret = pwc_set_dynamic_noise(pdev, c->value); + if (ret < 0) + return -EINVAL; + return 0; + + } + return -EINVAL; + } + + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *f = arg; + int index; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + /* We only support two format: the raw format, and YUV */ + index = f->index; + memset(f,0,sizeof(struct v4l2_fmtdesc)); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->index = index; + switch(index) + { + case 0: + /* RAW format */ + f->pixelformat = pdev->type<=646?V4L2_PIX_FMT_PWC1:V4L2_PIX_FMT_PWC2; + f->flags = V4L2_FMT_FLAG_COMPRESSED; + strlcpy(f->description,"Raw Philips Webcam",sizeof(f->description)); + break; + case 1: + f->pixelformat = V4L2_PIX_FMT_YUV420; + strlcpy(f->description,"4:2:0, planar, Y-Cb-Cr",sizeof(f->description)); + break; + default: + return -EINVAL; + } + return 0; + } + + case VIDIOC_G_FMT: + { + struct v4l2_format *f = arg; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",pdev->image.x,pdev->image.y); + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + pwc_vidioc_fill_fmt(pdev, f); + + return 0; + } + + case VIDIOC_TRY_FMT: + return pwc_vidioc_try_fmt(pdev, arg); + + case VIDIOC_S_FMT: + return pwc_vidioc_set_fmt(pdev, arg); + + case VIDIOC_G_STD: + { + v4l2_std_id *std = arg; + *std = V4L2_STD_UNKNOWN; + return 0; + } + + case VIDIOC_S_STD: + { + v4l2_std_id *std = arg; + if (*std != V4L2_STD_UNKNOWN) + return -EINVAL; + return 0; + } + + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *std = arg; + if (std->index != 0) + return -EINVAL; + std->id = V4L2_STD_UNKNOWN; + strncpy(std->name, "webcam", sizeof(std->name)); + return 0; + } + + case VIDIOC_REQBUFS: + { + struct v4l2_requestbuffers *rb = arg; + int nbuffers; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n",rb->count); + if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (rb->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + nbuffers = rb->count; + if (nbuffers < 2) + nbuffers = 2; + else if (nbuffers > pwc_mbufs) + nbuffers = pwc_mbufs; + /* Force to use our # of buffers */ + rb->count = pwc_mbufs; + return 0; + } + + case VIDIOC_QUERYBUF: + { + struct v4l2_buffer *buf = arg; + int index; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n",buf->index); + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n"); + return -EINVAL; + } + if (buf->memory != V4L2_MEMORY_MMAP) { + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad memory type\n"); + return -EINVAL; + } + index = buf->index; + if (index < 0 || index >= pwc_mbufs) { + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index); + return -EINVAL; + } + + memset(buf, 0, sizeof(struct v4l2_buffer)); + buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf->index = index; + buf->m.offset = index * pdev->len_per_image; + if (pdev->vpalette == VIDEO_PALETTE_RAW) + buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame); + else + buf->bytesused = pdev->view.size; + buf->field = V4L2_FIELD_NONE; + buf->memory = V4L2_MEMORY_MMAP; + //buf->flags = V4L2_BUF_FLAG_MAPPED; + buf->length = pdev->len_per_image; + + PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n",buf->index); + PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n",buf->m.offset); + PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n",buf->bytesused); + + return 0; + } + + case VIDIOC_QBUF: + { + struct v4l2_buffer *buf = arg; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n",buf->index); + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (buf->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + if (buf->index < 0 || buf->index >= pwc_mbufs) + return -EINVAL; + + buf->flags |= V4L2_BUF_FLAG_QUEUED; + buf->flags &= ~V4L2_BUF_FLAG_DONE; + + return 0; + } + + case VIDIOC_DQBUF: + { + struct v4l2_buffer *buf = arg; + int ret; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n"); + + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + /* Add ourselves to the frame wait-queue. + + FIXME: needs auditing for safety. + QUESTION: In what respect? I think that using the + frameq is safe now. + */ + add_wait_queue(&pdev->frameq, &wait); + while (pdev->full_frames == NULL) { + if (pdev->error_status) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -pdev->error_status; + } + + if (signal_pending(current)) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -ERESTARTSYS; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n"); + /* Decompress data in pdev->images[pdev->fill_image] */ + ret = pwc_handle_frame(pdev); + if (ret) + return -EFAULT; + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n"); + + buf->index = pdev->fill_image; + if (pdev->vpalette == VIDEO_PALETTE_RAW) + buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame); + else + buf->bytesused = pdev->view.size; + buf->flags = V4L2_BUF_FLAG_MAPPED; + buf->field = V4L2_FIELD_NONE; + do_gettimeofday(&buf->timestamp); + buf->sequence = 0; + buf->memory = V4L2_MEMORY_MMAP; + buf->m.offset = pdev->fill_image * pdev->len_per_image; + buf->length = buf->bytesused; + pwc_next_image(pdev); + + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n",buf->index); + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n",buf->length); + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n",buf->m.offset); + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n",buf->bytesused); + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n"); + return 0; + + } + + case VIDIOC_STREAMON: + { + /* WARNING: pwc_try_video_mode() called pwc_isoc_init */ + pwc_isoc_init(pdev); + return 0; + } + + case VIDIOC_STREAMOFF: + { + pwc_isoc_cleanup(pdev); + return 0; + } + + default: + return pwc_ioctl(pdev, cmd, arg); + } /* ..switch */ + return 0; +} + +/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 1b0ee0c..629f79e 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h @@ -1,5 +1,5 @@ /* (C) 1999-2003 Nemosoft Unv. - (C) 2004 Luc Saillard (luc@saillard.org) + (C) 2004-2006 Luc Saillard (luc@saillard.org) NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx driver and thus may have bugs that are not present in the original version. @@ -29,51 +29,87 @@ #include #include #include #include -#include #include #include +#include #include #include +#include +#include #include "pwc-uncompress.h" -#include "pwc-ioctl.h" - -/* Defines and structures for the Philips webcam */ -/* Used for checking memory corruption/pointer validation */ -#define PWC_MAGIC 0x89DC10ABUL -#undef PWC_MAGIC +#include /* Turn some debugging options on/off */ -#define PWC_DEBUG 0 +#ifndef CONFIG_PWC_DEBUG +#define CONFIG_PWC_DEBUG 1 +#endif + +/* Version block */ +#define PWC_MAJOR 10 +#define PWC_MINOR 0 +#define PWC_EXTRAMINOR 12 +#define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR) +#define PWC_VERSION "10.0.12" +#define PWC_NAME "pwc" +#define PFX PWC_NAME ": " + /* Trace certain actions in the driver */ -#define TRACE_MODULE 0x0001 -#define TRACE_PROBE 0x0002 -#define TRACE_OPEN 0x0004 -#define TRACE_READ 0x0008 -#define TRACE_MEMORY 0x0010 -#define TRACE_FLOW 0x0020 -#define TRACE_SIZE 0x0040 -#define TRACE_PWCX 0x0080 -#define TRACE_SEQUENCE 0x1000 - -#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A) -#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A) -#define Info(A...) printk(KERN_INFO PWC_NAME " " A) -#define Err(A...) printk(KERN_ERR PWC_NAME " " A) +#define PWC_DEBUG_LEVEL_MODULE (1<<0) +#define PWC_DEBUG_LEVEL_PROBE (1<<1) +#define PWC_DEBUG_LEVEL_OPEN (1<<2) +#define PWC_DEBUG_LEVEL_READ (1<<3) +#define PWC_DEBUG_LEVEL_MEMORY (1<<4) +#define PWC_DEBUG_LEVEL_FLOW (1<<5) +#define PWC_DEBUG_LEVEL_SIZE (1<<6) +#define PWC_DEBUG_LEVEL_IOCTL (1<<7) +#define PWC_DEBUG_LEVEL_TRACE (1<<8) + +#define PWC_DEBUG_MODULE(fmt, args...) PWC_DEBUG(MODULE, fmt, ##args) +#define PWC_DEBUG_PROBE(fmt, args...) PWC_DEBUG(PROBE, fmt, ##args) +#define PWC_DEBUG_OPEN(fmt, args...) PWC_DEBUG(OPEN, fmt, ##args) +#define PWC_DEBUG_READ(fmt, args...) PWC_DEBUG(READ, fmt, ##args) +#define PWC_DEBUG_MEMORY(fmt, args...) PWC_DEBUG(MEMORY, fmt, ##args) +#define PWC_DEBUG_FLOW(fmt, args...) PWC_DEBUG(FLOW, fmt, ##args) +#define PWC_DEBUG_SIZE(fmt, args...) PWC_DEBUG(SIZE, fmt, ##args) +#define PWC_DEBUG_IOCTL(fmt, args...) PWC_DEBUG(IOCTL, fmt, ##args) +#define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args) + + +#if CONFIG_PWC_DEBUG + +#define PWC_DEBUG_LEVEL (PWC_DEBUG_LEVEL_MODULE) + +#define PWC_DEBUG(level, fmt, args...) do {\ + if ((PWC_DEBUG_LEVEL_ ##level) & pwc_trace) \ + printk(KERN_DEBUG PFX fmt, ##args); \ + } while(0) + +#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args) +#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args) +#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args) +#define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args) + +#else /* if ! CONFIG_PWC_DEBUG */ + +#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args) +#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args) +#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args) +#define PWC_TRACE(fmt, args...) do { } while(0) +#define PWC_DEBUG(level, fmt, args...) do { } while(0) + +#define pwc_trace 0 +#endif /* Defines for ToUCam cameras */ #define TOUCAM_HEADER_SIZE 8 #define TOUCAM_TRAILER_SIZE 4 #define FEATURE_MOTOR_PANTILT 0x0001 - -/* Version block */ -#define PWC_MAJOR 9 -#define PWC_MINOR 0 -#define PWC_VERSION "9.0.2-unofficial" -#define PWC_NAME "pwc" +#define FEATURE_CODEC1 0x0002 +#define FEATURE_CODEC2 0x0004 /* Turn certain features on/off */ #define PWC_INT_PIPE 0 @@ -95,6 +131,18 @@ #define PWC_FRAME_SIZE (460800 + TOUCA /* Absolute maximum number of buffers available for mmap() */ #define MAX_IMAGES 10 +/* Some macros to quickly find the type of a webcam */ +#define DEVICE_USE_CODEC1(x) ((x)<675) +#define DEVICE_USE_CODEC2(x) ((x)>=675 && (x)<700) +#define DEVICE_USE_CODEC3(x) ((x)>=700) +#define DEVICE_USE_CODEC23(x) ((x)>=675) + + +#ifndef V4L2_PIX_FMT_PWC1 +#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1') +#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2') +#endif + /* The following structures were based on cpia.h. Why reinvent the wheel? :-) */ struct pwc_iso_buf { @@ -110,17 +158,19 @@ struct pwc_frame_buf void *data; volatile int filled; /* number of bytes filled */ struct pwc_frame_buf *next; /* list */ -#if PWC_DEBUG - int sequence; /* Sequence number */ -#endif +}; + +/* additionnal informations used when dealing image between kernel and userland */ +struct pwc_imgbuf +{ + unsigned long offset; /* offset of this buffer in the big array of image_data */ + int vma_use_count; /* count the number of time this memory is mapped */ }; struct pwc_device { struct video_device *vdev; -#ifdef PWC_MAGIC - int magic; -#endif + /* Pointer to our usb_device */ struct usb_device *udev; @@ -177,12 +227,8 @@ #endif int frame_size; int frame_total_size; /* including header & trailer */ int drop_frames; -#if PWC_DEBUG - int sequence; /* Debugging aid */ -#endif /* 3: decompression */ - struct pwc_decompressor *decompressor; /* function block with decompression routines */ void *decompress_data; /* private data for decompression engine */ /* 4: image */ @@ -198,7 +244,7 @@ #endif struct pwc_coord offset; /* offset within the viewport */ void *image_data; /* total buffer, which is subdivided into ... */ - void *image_ptr[MAX_IMAGES]; /* ...several images... */ + struct pwc_imgbuf images[MAX_IMAGES];/* ...several images... */ int fill_image; /* ...which are rotated. */ int len_per_image; /* length per image */ int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */ @@ -211,6 +257,7 @@ #endif struct pwc_mpt_range angle_range; int pan_angle; /* in degrees * 100 */ int tilt_angle; /* absolute angle; 0,0 is home position */ + int snapshot_button_status; /* set to 1 when the user push the button, reset to 0 when this value is read */ /*** Misc. data ***/ wait_queue_head_t frameq; /* When waiting for a frame to finish... */ @@ -219,20 +266,26 @@ #if PWC_INT_PIPE #endif }; - #ifdef __cplusplus extern "C" { #endif -/* Global variable */ +/* Global variables */ +#if CONFIG_PWC_DEBUG extern int pwc_trace; +#endif +extern int pwc_mbufs; /** functions in pwc-if.c */ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot); +int pwc_handle_frame(struct pwc_device *pdev); +void pwc_next_image(struct pwc_device *pdev); +int pwc_isoc_init(struct pwc_device *pdev); +void pwc_isoc_cleanup(struct pwc_device *pdev); /** Functions in pwc-misc.c */ /* sizes in pixels */ -extern struct pwc_coord pwc_image_sizes[PSZ_MAX]; +extern const struct pwc_coord pwc_image_sizes[PSZ_MAX]; int pwc_decode_size(struct pwc_device *pdev, int width, int height); void pwc_construct(struct pwc_device *pdev); @@ -240,6 +293,9 @@ void pwc_construct(struct pwc_device *pd /** Functions in pwc-ctrl.c */ /* Request a certain video mode. Returns < 0 if not possible */ extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot); +/* Calculate the number of bytes per image (not frame) */ +extern int pwc_mpt_reset(struct pwc_device *pdev, int flags); +extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt); /* Various controls; should be obvious. Value 0..65535, or < 0 on error */ extern int pwc_get_brightness(struct pwc_device *pdev); @@ -248,10 +304,36 @@ extern int pwc_get_contrast(struct pwc_d extern int pwc_set_contrast(struct pwc_device *pdev, int value); extern int pwc_get_gamma(struct pwc_device *pdev); extern int pwc_set_gamma(struct pwc_device *pdev, int value); -extern int pwc_get_saturation(struct pwc_device *pdev); +extern int pwc_get_saturation(struct pwc_device *pdev, int *value); extern int pwc_set_saturation(struct pwc_device *pdev, int value); extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value); extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor); +extern int pwc_restore_user(struct pwc_device *pdev); +extern int pwc_save_user(struct pwc_device *pdev); +extern int pwc_restore_factory(struct pwc_device *pdev); + +/* exported for use by v4l2 controls */ +extern int pwc_get_red_gain(struct pwc_device *pdev, int *value); +extern int pwc_set_red_gain(struct pwc_device *pdev, int value); +extern int pwc_get_blue_gain(struct pwc_device *pdev, int *value); +extern int pwc_set_blue_gain(struct pwc_device *pdev, int value); +extern int pwc_get_awb(struct pwc_device *pdev); +extern int pwc_set_awb(struct pwc_device *pdev, int mode); +extern int pwc_set_agc(struct pwc_device *pdev, int mode, int value); +extern int pwc_get_agc(struct pwc_device *pdev, int *value); +extern int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value); +extern int pwc_get_shutter_speed(struct pwc_device *pdev, int *value); + +extern int pwc_set_colour_mode(struct pwc_device *pdev, int colour); +extern int pwc_get_colour_mode(struct pwc_device *pdev, int *colour); +extern int pwc_set_contour(struct pwc_device *pdev, int contour); +extern int pwc_get_contour(struct pwc_device *pdev, int *contour); +extern int pwc_set_backlight(struct pwc_device *pdev, int backlight); +extern int pwc_get_backlight(struct pwc_device *pdev, int *backlight); +extern int pwc_set_flicker(struct pwc_device *pdev, int flicker); +extern int pwc_get_flicker(struct pwc_device *pdev, int *flicker); +extern int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise); +extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise); /* Power down or up the camera; not supported by all models */ extern int pwc_camera_power(struct pwc_device *pdev, int power); @@ -259,6 +341,9 @@ extern int pwc_camera_power(struct pwc_d /* Private ioctl()s; see pwc-ioctl.h */ extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg); +/** Functions in pwc-v4l.c */ +extern int pwc_video_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg); /** pwc-uncompress.c */ /* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */ @@ -270,3 +355,4 @@ #endif #endif +/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index dd830e0..59a1872 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -46,6 +46,7 @@ #include #include #include #include +#include #include #include "saa5246a.h" diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 531e946..19a8d65 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -56,6 +56,7 @@ #include #include #include #include +#include #include diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 41d951d..676b997 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -43,6 +43,7 @@ #include #define I2C_NAME(s) (s)->name #include +#include #include static int debug = 0; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index dceebc0..b59c117 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -72,6 +72,10 @@ struct saa7115_state { int sat; enum v4l2_chip_ident ident; u32 audclk_freq; + u32 crystal_freq; + u8 ucgc; + u8 cgcdiv; + u8 apll; }; /* ----------------------------------------------------------------------- */ @@ -375,10 +379,6 @@ static const unsigned char saa7113_init_ }; static const unsigned char saa7115_init_misc[] = { - 0x38, 0x03, /* audio stuff */ - 0x39, 0x10, - 0x3a, 0x08, - 0x81, 0x01, /* reg 0x15,0x16 define blanking window */ 0x82, 0x00, 0x83, 0x01, /* I port settings */ @@ -584,6 +584,7 @@ static int saa7115_set_audio_clock_freq( u32 acni; u32 hz; u64 f; + u8 acc = 0; /* reg 0x3a, audio clock control */ v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq); @@ -591,18 +592,34 @@ static int saa7115_set_audio_clock_freq( if (freq < 32000 || freq > 48000) return -EINVAL; + /* The saa7113 has no audio clock */ + if (state->ident == V4L2_IDENT_SAA7113) + return 0; + /* hz is the refresh rate times 100 */ hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000; /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */ acpf = (25600 * freq) / hz; /* acni = (256 * freq * 2^23) / crystal_frequency = (freq * 2^(8+23)) / crystal_frequency = - (freq << 31) / 32.11 MHz */ + (freq << 31) / crystal_frequency */ f = freq; f = f << 31; - do_div(f, 32110000); + do_div(f, state->crystal_freq); acni = f; + if (state->ucgc) { + acpf = acpf * state->cgcdiv / 16; + acni = acni * state->cgcdiv / 16; + acc = 0x80; + if (state->cgcdiv == 3) + acc |= 0x40; + } + if (state->apll) + acc |= 0x08; + saa7115_write(client, 0x38, 0x03); + saa7115_write(client, 0x39, 0x10); + saa7115_write(client, 0x3a, acc); saa7115_write(client, 0x30, acpf & 0xff); saa7115_write(client, 0x31, (acpf >> 8) & 0xff); saa7115_write(client, 0x32, (acpf >> 16) & 0x03); @@ -1073,48 +1090,6 @@ static void saa7115_decode_vbi_line(stru /* ============ SAA7115 AUDIO settings (end) ============= */ -static struct v4l2_queryctrl saa7115_qctrl[] = { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 128, - .flags = 0, - }, { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 64, - .flags = 0, - }, { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 64, - .flags = 0, - }, { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Hue", - .minimum = -128, - .maximum = 127, - .step = 1, - .default_value = 0, - .flags = 0, - }, -}; - -/* ----------------------------------------------------------------------- */ - static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct saa7115_state *state = i2c_get_clientdata(client); @@ -1158,14 +1133,16 @@ static int saa7115_command(struct i2c_cl case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *qc = arg; - int i; - for (i = 0; i < ARRAY_SIZE(saa7115_qctrl); i++) - if (qc->id && qc->id == saa7115_qctrl[i].id) { - memcpy(qc, &saa7115_qctrl[i], sizeof(*qc)); - return 0; - } - return -EINVAL; + switch (qc->id) { + case V4L2_CID_BRIGHTNESS: + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill_std(qc); + default: + return -EINVAL; + } } case VIDIOC_G_STD: @@ -1221,34 +1198,6 @@ static int saa7115_command(struct i2c_cl break; } - case VIDIOC_G_INPUT: - *(int *)arg = state->input; - break; - - case VIDIOC_S_INPUT: - v4l_dbg(1, debug, client, "decoder set input %d\n", *iarg); - /* inputs from 0-9 are available */ - if (*iarg < 0 || *iarg > 9) { - return -EINVAL; - } - - if (state->input == *iarg) - break; - v4l_dbg(1, debug, client, "now setting %s input\n", - *iarg >= 6 ? "S-Video" : "Composite"); - state->input = *iarg; - - /* select mode */ - saa7115_write(client, 0x02, - (saa7115_read(client, 0x02) & 0xf0) | - state->input); - - /* bypass chrominance trap for modes 6..9 */ - saa7115_write(client, 0x09, - (saa7115_read(client, 0x09) & 0x7f) | - (state->input < 6 ? 0x0 : 0x80)); - break; - case VIDIOC_STREAMON: case VIDIOC_STREAMOFF: v4l_dbg(1, debug, client, "%s output\n", @@ -1260,6 +1209,21 @@ static int saa7115_command(struct i2c_cl } break; + case VIDIOC_INT_S_CRYSTAL_FREQ: + { + struct v4l2_crystal_freq *freq = arg; + + if (freq->freq != SAA7115_FREQ_32_11_MHZ && + freq->freq != SAA7115_FREQ_24_576_MHZ) + return -EINVAL; + state->crystal_freq = freq->freq; + state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4; + state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0; + state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0; + saa7115_set_audio_clock_freq(client, state->audclk_freq); + break; + } + case VIDIOC_INT_DECODE_VBI_LINE: saa7115_decode_vbi_line(client, arg); break; @@ -1401,10 +1365,13 @@ static int saa7115_attach(struct i2c_ada v4l_dbg(1, debug, client, "writing init values\n"); /* init to 60hz/48khz */ - if (state->ident == V4L2_IDENT_SAA7113) + if (state->ident == V4L2_IDENT_SAA7113) { + state->crystal_freq = SAA7115_FREQ_24_576_MHZ; saa7115_writeregs(client, saa7113_init_auto_input); - else + } else { + state->crystal_freq = SAA7115_FREQ_32_11_MHZ; saa7115_writeregs(client, saa7115_init_auto_input); + } saa7115_writeregs(client, saa7115_init_misc); saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index c271e2e..ad401bd 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -270,7 +270,7 @@ static const char * const wss_strs[] = { "letterbox 16:9 top", "invalid", "invalid", - "16:9 full format anamorphic" + "16:9 full format anamorphic", "4:3 full format", "invalid", "invalid", diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 0e0ba50..de7b9e6 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -39,6 +39,23 @@ enum saa6752hs_videoformat { SAA6752HS_VF_UNKNOWN, }; +struct saa6752hs_mpeg_params { + /* transport streams */ + __u16 ts_pid_pmt; + __u16 ts_pid_audio; + __u16 ts_pid_video; + __u16 ts_pid_pcr; + + /* audio */ + enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; + + /* video */ + enum v4l2_mpeg_video_aspect vi_aspect; + enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode; + __u32 vi_bitrate; + __u32 vi_bitrate_peak; +}; + static const struct v4l2_format v4l2_format_table[] = { [SAA6752HS_VF_D1] = @@ -55,18 +72,19 @@ static const struct v4l2_format v4l2_for struct saa6752hs_state { struct i2c_client client; - struct v4l2_mpeg_compression params; + struct v4l2_mpeg_compression old_params; + struct saa6752hs_mpeg_params params; enum saa6752hs_videoformat video_format; v4l2_std_id standard; }; enum saa6752hs_command { SAA6752HS_COMMAND_RESET = 0, - SAA6752HS_COMMAND_STOP = 1, - SAA6752HS_COMMAND_START = 2, - SAA6752HS_COMMAND_PAUSE = 3, - SAA6752HS_COMMAND_RECONFIGURE = 4, - SAA6752HS_COMMAND_SLEEP = 5, + SAA6752HS_COMMAND_STOP = 1, + SAA6752HS_COMMAND_START = 2, + SAA6752HS_COMMAND_PAUSE = 3, + SAA6752HS_COMMAND_RECONFIGURE = 4, + SAA6752HS_COMMAND_SLEEP = 5, SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6, SAA6752HS_COMMAND_MAX @@ -129,7 +147,22 @@ static u8 PMT[] = { 0x00, 0x00, 0x00, 0x00 /* CRC32 */ }; -static struct v4l2_mpeg_compression param_defaults = +static struct saa6752hs_mpeg_params param_defaults = +{ + .ts_pid_pmt = 16, + .ts_pid_video = 260, + .ts_pid_audio = 256, + .ts_pid_pcr = 259, + + .vi_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3, + .vi_bitrate = 4000, + .vi_bitrate_peak = 6000, + .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + + .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, +}; + +static struct v4l2_mpeg_compression old_param_defaults = { .st_type = V4L2_MPEG_TS_2, .st_bitrate = { @@ -228,45 +261,57 @@ static int saa6752hs_chip_command(struct static int saa6752hs_set_bitrate(struct i2c_client* client, - struct v4l2_mpeg_compression* params) + struct saa6752hs_mpeg_params* params) { u8 buf[3]; + int tot_bitrate; /* set the bitrate mode */ buf[0] = 0x71; - buf[1] = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? 0 : 1; + buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1; i2c_master_send(client, buf, 2); /* set the video bitrate */ - if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) { + if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { /* set the target bitrate */ buf[0] = 0x80; - buf[1] = params->vi_bitrate.target >> 8; - buf[2] = params->vi_bitrate.target & 0xff; + buf[1] = params->vi_bitrate >> 8; + buf[2] = params->vi_bitrate & 0xff; i2c_master_send(client, buf, 3); /* set the max bitrate */ buf[0] = 0x81; - buf[1] = params->vi_bitrate.max >> 8; - buf[2] = params->vi_bitrate.max & 0xff; + buf[1] = params->vi_bitrate_peak >> 8; + buf[2] = params->vi_bitrate_peak & 0xff; i2c_master_send(client, buf, 3); + tot_bitrate = params->vi_bitrate_peak; } else { /* set the target bitrate (no max bitrate for CBR) */ buf[0] = 0x81; - buf[1] = params->vi_bitrate.target >> 8; - buf[2] = params->vi_bitrate.target & 0xff; + buf[1] = params->vi_bitrate >> 8; + buf[2] = params->vi_bitrate & 0xff; i2c_master_send(client, buf, 3); + tot_bitrate = params->vi_bitrate; } /* set the audio bitrate */ buf[0] = 0x94; - buf[1] = (256 == params->au_bitrate.target) ? 0 : 1; + buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1; i2c_master_send(client, buf, 2); + tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384; + + /* Note: the total max bitrate is determined by adding the video and audio + bitrates together and also adding an extra 768kbit/s to stay on the + safe side. If more control should be required, then an extra MPEG control + should be added. */ + tot_bitrate += 768; + if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX) + tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX; /* set the total bitrate */ buf[0] = 0xb1; - buf[1] = params->st_bitrate.target >> 8; - buf[2] = params->st_bitrate.target & 0xff; + buf[1] = tot_bitrate >> 8; + buf[2] = tot_bitrate & 0xff; i2c_master_send(client, buf, 3); return 0; @@ -318,50 +363,188 @@ static void saa6752hs_set_subsampling(st } -static void saa6752hs_set_params(struct i2c_client* client, +static void saa6752hs_old_set_params(struct i2c_client* client, struct v4l2_mpeg_compression* params) { struct saa6752hs_state *h = i2c_get_clientdata(client); /* check PIDs */ - if (params->ts_pid_pmt <= MPEG_PID_MAX) + if (params->ts_pid_pmt <= MPEG_PID_MAX) { + h->old_params.ts_pid_pmt = params->ts_pid_pmt; h->params.ts_pid_pmt = params->ts_pid_pmt; - if (params->ts_pid_pcr <= MPEG_PID_MAX) + } + if (params->ts_pid_pcr <= MPEG_PID_MAX) { + h->old_params.ts_pid_pcr = params->ts_pid_pcr; h->params.ts_pid_pcr = params->ts_pid_pcr; - if (params->ts_pid_video <= MPEG_PID_MAX) + } + if (params->ts_pid_video <= MPEG_PID_MAX) { + h->old_params.ts_pid_video = params->ts_pid_video; h->params.ts_pid_video = params->ts_pid_video; - if (params->ts_pid_audio <= MPEG_PID_MAX) + } + if (params->ts_pid_audio <= MPEG_PID_MAX) { + h->old_params.ts_pid_audio = params->ts_pid_audio; h->params.ts_pid_audio = params->ts_pid_audio; + } /* check bitrate parameters */ if ((params->vi_bitrate.mode == V4L2_BITRATE_CBR) || - (params->vi_bitrate.mode == V4L2_BITRATE_VBR)) - h->params.vi_bitrate.mode = params->vi_bitrate.mode; + (params->vi_bitrate.mode == V4L2_BITRATE_VBR)) { + h->old_params.vi_bitrate.mode = params->vi_bitrate.mode; + h->params.vi_bitrate_mode = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR : V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; + } if (params->vi_bitrate.mode != V4L2_BITRATE_NONE) - h->params.st_bitrate.target = params->st_bitrate.target; + h->old_params.st_bitrate.target = params->st_bitrate.target; if (params->vi_bitrate.mode != V4L2_BITRATE_NONE) - h->params.vi_bitrate.target = params->vi_bitrate.target; + h->old_params.vi_bitrate.target = params->vi_bitrate.target; if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) - h->params.vi_bitrate.max = params->vi_bitrate.max; + h->old_params.vi_bitrate.max = params->vi_bitrate.max; if (params->au_bitrate.mode != V4L2_BITRATE_NONE) - h->params.au_bitrate.target = params->au_bitrate.target; + h->old_params.au_bitrate.target = params->au_bitrate.target; /* aspect ratio */ if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3 || - params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9) - h->params.vi_aspect_ratio = params->vi_aspect_ratio; + params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9) { + h->old_params.vi_aspect_ratio = params->vi_aspect_ratio; + if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3) + h->params.vi_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3; + else + h->params.vi_aspect = V4L2_MPEG_VIDEO_ASPECT_16x9; + } /* range checks */ - if (h->params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX) - h->params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX; - if (h->params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX) - h->params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX; - if (h->params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX) - h->params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX; - if (h->params.au_bitrate.target <= 256) - h->params.au_bitrate.target = 256; + if (h->old_params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX) + h->old_params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX; + if (h->old_params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX) + h->old_params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX; + if (h->old_params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX) + h->old_params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX; + h->params.vi_bitrate = params->vi_bitrate.target; + h->params.vi_bitrate_peak = params->vi_bitrate.max; + if (h->old_params.au_bitrate.target <= 256) { + h->old_params.au_bitrate.target = 256; + h->params.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K; + } + else { + h->old_params.au_bitrate.target = 384; + h->params.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_384K; + } +} + +static int handle_ctrl(struct saa6752hs_mpeg_params *params, + struct v4l2_ext_control *ctrl, int cmd) +{ + int old = 0, new; + int set = cmd == VIDIOC_S_EXT_CTRLS; + + new = ctrl->value; + switch (ctrl->id) { + case V4L2_CID_MPEG_STREAM_TYPE: + old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; + if (set && new != old) + return -ERANGE; + new = old; + break; + case V4L2_CID_MPEG_STREAM_PID_PMT: + old = params->ts_pid_pmt; + if (set && new > MPEG_PID_MAX) + return -ERANGE; + if (new > MPEG_PID_MAX) + new = MPEG_PID_MAX; + params->ts_pid_pmt = new; + break; + case V4L2_CID_MPEG_STREAM_PID_AUDIO: + old = params->ts_pid_audio; + if (set && new > MPEG_PID_MAX) + return -ERANGE; + if (new > MPEG_PID_MAX) + new = MPEG_PID_MAX; + params->ts_pid_audio = new; + break; + case V4L2_CID_MPEG_STREAM_PID_VIDEO: + old = params->ts_pid_video; + if (set && new > MPEG_PID_MAX) + return -ERANGE; + if (new > MPEG_PID_MAX) + new = MPEG_PID_MAX; + params->ts_pid_video = new; + break; + case V4L2_CID_MPEG_STREAM_PID_PCR: + old = params->ts_pid_pcr; + if (set && new > MPEG_PID_MAX) + return -ERANGE; + if (new > MPEG_PID_MAX) + new = MPEG_PID_MAX; + params->ts_pid_pcr = new; + break; + case V4L2_CID_MPEG_AUDIO_ENCODING: + old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2; + if (set && new != old) + return -ERANGE; + new = old; + break; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + old = params->au_l2_bitrate; + if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K && + new != V4L2_MPEG_AUDIO_L2_BITRATE_384K) + return -ERANGE; + if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K) + new = V4L2_MPEG_AUDIO_L2_BITRATE_256K; + else + new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; + params->au_l2_bitrate = new; + break; + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; + if (set && new != old) + return -ERANGE; + new = old; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; + if (set && new != old) + return -ERANGE; + new = old; + break; + case V4L2_CID_MPEG_VIDEO_ASPECT: + old = params->vi_aspect; + if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 && + new != V4L2_MPEG_VIDEO_ASPECT_4x3) + return -ERANGE; + if (new != V4L2_MPEG_VIDEO_ASPECT_16x9) + new = V4L2_MPEG_VIDEO_ASPECT_4x3; + params->vi_aspect = new; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + old = params->vi_bitrate * 1000; + new = 1000 * (new / 1000); + if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + return -ERANGE; + if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; + params->vi_bitrate = new / 1000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + old = params->vi_bitrate_peak * 1000; + new = 1000 * (new / 1000); + if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + return -ERANGE; + if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) + new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; + params->vi_bitrate_peak = new / 1000; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + old = params->vi_bitrate_mode; + params->vi_bitrate_mode = new; + break; + default: + return -EINVAL; + } + if (cmd == VIDIOC_G_EXT_CTRLS) + ctrl->value = old; else - h->params.au_bitrate.target = 384; + ctrl->value = new; + return 0; } static int saa6752hs_init(struct i2c_client* client) @@ -395,22 +578,22 @@ static int saa6752hs_init(struct i2c_cli buf[2] = 0x0D; i2c_master_send(client,buf,3); - /* Set minimum Q-scale {4} */ + /* Set minimum Q-scale {4} */ buf[0] = 0x82; buf[1] = 0x04; i2c_master_send(client,buf,2); - /* Set maximum Q-scale {12} */ + /* Set maximum Q-scale {12} */ buf[0] = 0x83; buf[1] = 0x0C; i2c_master_send(client,buf,2); - /* Set Output Protocol */ + /* Set Output Protocol */ buf[0] = 0xD0; buf[1] = 0x81; i2c_master_send(client,buf,2); - /* Set video output stream format {TS} */ + /* Set video output stream format {TS} */ buf[0] = 0xB0; buf[1] = 0x05; i2c_master_send(client,buf,2); @@ -441,7 +624,7 @@ static int saa6752hs_init(struct i2c_cli localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF; localPMT[sizeof(PMT) - 1] = crc & 0xFF; - /* Set Audio PID */ + /* Set Audio PID */ buf[0] = 0xC1; buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF; buf[2] = h->params.ts_pid_audio & 0xFF; @@ -489,11 +672,11 @@ static int saa6752hs_init(struct i2c_cli buf[3] = 0x82; buf[4] = 0xB0; buf[5] = buf2[0]; - switch(h->params.vi_aspect_ratio) { - case V4L2_MPEG_ASPECT_16_9: + switch(h->params.vi_aspect) { + case V4L2_MPEG_VIDEO_ASPECT_16x9: buf[6] = buf2[1] | 0x40; break; - case V4L2_MPEG_ASPECT_4_3: + case V4L2_MPEG_VIDEO_ASPECT_4x3: default: buf[6] = buf2[1] & 0xBF; break; @@ -515,6 +698,7 @@ static int saa6752hs_attach(struct i2c_a return -ENOMEM; h->client = client_template; h->params = param_defaults; + h->old_params = old_param_defaults; h->client.adapter = adap; h->client.addr = addr; @@ -550,20 +734,45 @@ static int saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct saa6752hs_state *h = i2c_get_clientdata(client); - struct v4l2_mpeg_compression *params = arg; + struct v4l2_ext_controls *ctrls = arg; + struct v4l2_mpeg_compression *old_params = arg; + struct saa6752hs_mpeg_params params; int err = 0; + int i; switch (cmd) { case VIDIOC_S_MPEGCOMP: - if (NULL == params) { + if (NULL == old_params) { /* apply settings and start encoder */ saa6752hs_init(client); break; } - saa6752hs_set_params(client, params); + saa6752hs_old_set_params(client, old_params); /* fall through */ case VIDIOC_G_MPEGCOMP: - *params = h->params; + *old_params = h->old_params; + break; + case VIDIOC_S_EXT_CTRLS: + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + if (ctrls->count == 0) { + /* apply settings and start encoder */ + saa6752hs_init(client); + break; + } + /* fall through */ + case VIDIOC_TRY_EXT_CTRLS: + case VIDIOC_G_EXT_CTRLS: + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + params = h->params; + for (i = 0; i < ctrls->count; i++) { + if ((err = handle_ctrl(¶ms, ctrls->controls + i, cmd))) { + ctrls->error_idx = i; + return err; + } + } + h->params = params; break; case VIDIOC_G_FMT: { diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index bb3e0ba..d77e6a8 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -818,7 +818,7 @@ static int snd_saa7134_capsrc_put(struct break; } - /* output xbar always main channel */ + /* output xbar always main channel */ saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); if (left || right) { // We've got data, turn the input on diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 86eae35..927413a 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2160,7 +2160,7 @@ struct saa7134_board saa7134_boards[] = .radio = { .name = name_radio, .amux = LINE2, - }, + }, }, [SAA7134_BOARD_GOTVIEW_7135] = { /* Mike Baikov */ @@ -2842,6 +2842,55 @@ struct saa7134_board saa7134_boards[] = .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ }, }, + [SAA7134_BOARD_FLYVIDEO3000_NTSC] = { + /* "Zac Bowling" */ + .name = "LifeView FlyVIDEO3000 (NTSC)", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_NTSC, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + + .gpiomask = 0xe000, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .gpio = 0x8000, + .tv = 1, + },{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .gpio = 0x0000, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 0, + .amux = LINE2, + .gpio = 0x4000, + },{ + .name = name_comp2, + .vmux = 3, + .amux = LINE2, + .gpio = 0x4000, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + .gpio = 0x4000, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x2000, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio = 0x8000, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -2901,6 +2950,12 @@ struct pci_device_id saa7134_pci_tbl[] = },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x5169, + .subdevice = 0x0138, + .driver_data = SAA7134_BOARD_FLYVIDEO3000_NTSC, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x5168, .subdevice = 0x0138, .driver_data = SAA7134_BOARD_FLYVIDEO3000, @@ -3459,6 +3514,7 @@ int saa7134_board_init1(struct saa7134_d switch (dev->board) { case SAA7134_BOARD_FLYVIDEO2000: case SAA7134_BOARD_FLYVIDEO3000: + case SAA7134_BOARD_FLYVIDEO3000_NTSC: dev->has_remote = SAA7134_REMOTE_GPIO; board_flyvideo(dev); break; diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 222a36c..279828b 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -132,9 +132,8 @@ static int mt352_aver777_init(struct dvb return 0; } -static int mt352_pinnacle_pll_set(struct dvb_frontend* fe, - struct dvb_frontend_parameters* params, - u8* pllbuf) +static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, + struct dvb_frontend_parameters* params) { u8 off[] = { 0x00, 0xf1}; u8 on[] = { 0x00, 0x71}; @@ -147,30 +146,31 @@ static int mt352_pinnacle_pll_set(struct f.tuner = 0; f.type = V4L2_TUNER_DIGITAL_TV; f.frequency = params->frequency / 1000 * 16 / 1000; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &msg, 1); saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f); msg.buf = on; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &msg, 1); pinnacle_antenna_pwr(dev, antenna_pwr); /* mt352 setup */ - mt352_pinnacle_init(fe); - pllbuf[0] = 0xc2; - pllbuf[1] = 0x00; - pllbuf[2] = 0x00; - pllbuf[3] = 0x80; - pllbuf[4] = 0x00; - return 0; + return mt352_pinnacle_init(fe); } -static int mt352_aver777_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf) +static int mt352_aver777_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len) { - pllbuf[0] = 0xc2; + if (buf_len < 5) + return -EINVAL; + + pllbuf[0] = 0x61; dvb_pll_configure(&dvb_pll_philips_td1316, pllbuf+1, params->frequency, params->u.ofdm.bandwidth); - return 0; + return 5; } static struct mt352_config pinnacle_300i = { @@ -179,13 +179,11 @@ static struct mt352_config pinnacle_300i .if2 = 36150, .no_tuner = 1, .demod_init = mt352_pinnacle_init, - .pll_set = mt352_pinnacle_pll_set, }; static struct mt352_config avermedia_777 = { .demod_address = 0xf, .demod_init = mt352_aver777_init, - .pll_set = mt352_aver777_pll_set, }; #endif @@ -268,6 +266,8 @@ static int philips_tda6651_pll_set(u8 ad tuner_buf[2] = 0xca; tuner_buf[3] = (cp << 5) | (filter << 3) | band; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(1); @@ -281,6 +281,8 @@ static int philips_tda6651_pll_init(u8 a struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) }; /* setup PLL configuration */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(1); @@ -290,12 +292,12 @@ static int philips_tda6651_pll_init(u8 a /* ------------------------------------------------------------------ */ -static int philips_tu1216_pll_60_init(struct dvb_frontend *fe) +static int philips_tu1216_tuner_60_init(struct dvb_frontend *fe) { return philips_tda6651_pll_init(0x60, fe); } -static int philips_tu1216_pll_60_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { return philips_tda6651_pll_set(0x60, fe, params); } @@ -315,20 +317,17 @@ static struct tda1004x_config philips_tu .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, - .pll_init = philips_tu1216_pll_60_init, - .pll_set = philips_tu1216_pll_60_set, - .pll_sleep = NULL, .request_firmware = philips_tu1216_request_firmware, }; /* ------------------------------------------------------------------ */ -static int philips_tu1216_pll_61_init(struct dvb_frontend *fe) +static int philips_tu1216_tuner_61_init(struct dvb_frontend *fe) { return philips_tda6651_pll_init(0x61, fe); } -static int philips_tu1216_pll_61_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_tu1216_tuner_61_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { return philips_tda6651_pll_set(0x61, fe, params); } @@ -341,21 +340,20 @@ static struct tda1004x_config philips_tu .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, - .pll_init = philips_tu1216_pll_61_init, - .pll_set = philips_tu1216_pll_61_set, - .pll_sleep = NULL, .request_firmware = philips_tu1216_request_firmware, }; /* ------------------------------------------------------------------ */ -static int philips_europa_pll_init(struct dvb_frontend *fe) +static int philips_europa_tuner_init(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab }; struct i2c_msg init_msg = {.addr = 0x61,.flags = 0,.buf = msg,.len = sizeof(msg) }; /* setup PLL configuration */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) return -EIO; msleep(1); @@ -365,18 +363,20 @@ static int philips_europa_pll_init(struc init_msg.len = 0x02; msg[0] = 0x00; msg[1] = 0x40; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1) return -EIO; return 0; } -static int philips_td1316_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { return philips_tda6651_pll_set(0x61, fe, params); } -static void philips_europa_analog(struct dvb_frontend *fe) +static int philips_europa_tuner_sleep(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; /* this message actually turns the tuner back to analog mode */ @@ -391,7 +391,20 @@ static void philips_europa_analog(struct analog_msg.len = 0x02; msg[0] = 0x00; msg[1] = 0x14; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &analog_msg, 1); + return 0; +} + +static int philips_europa_demod_sleep(struct dvb_frontend *fe) +{ + struct saa7134_dev *dev = fe->dvb->priv; + + if (dev->original_demod_sleep) + dev->original_demod_sleep(fe); + fe->ops.i2c_gate_ctrl(fe, 1); + return 0; } static struct tda1004x_config philips_europa_config = { @@ -402,21 +415,20 @@ static struct tda1004x_config philips_eu .xtal_freq = TDA10046_XTAL_4M, .agc_config = TDA10046_AGC_IFO_AUTO_POS, .if_freq = TDA10046_FREQ_052, - .pll_init = philips_europa_pll_init, - .pll_set = philips_td1316_pll_set, - .pll_sleep = philips_europa_analog, .request_firmware = NULL, }; /* ------------------------------------------------------------------ */ -static int philips_fmd1216_pll_init(struct dvb_frontend *fe) +static int philips_fmd1216_tuner_init(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; /* this message is to set up ATC and ALC */ static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 }; struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) }; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) return -EIO; msleep(1); @@ -424,22 +436,27 @@ static int philips_fmd1216_pll_init(stru return 0; } -static void philips_fmd1216_analog(struct dvb_frontend *fe) +static int philips_fmd1216_tuner_sleep(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; /* this message actually turns the tuner back to analog mode */ static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0x60 }; struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) }; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); msleep(1); fmd1216_init[2] = 0x86; fmd1216_init[3] = 0x54; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); msleep(1); + return 0; } -static int philips_fmd1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_fmd1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct saa7134_dev *dev = fe->dvb->priv; u8 tuner_buf[4]; @@ -516,6 +533,8 @@ static int philips_fmd1216_pll_set(struc tuner_buf[2] = 0x80 | (cp << 6) | (mode << 3) | 4; tuner_buf[3] = 0x40 | band; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) return -EIO; return 0; @@ -528,9 +547,6 @@ static struct tda1004x_config medion_car .xtal_freq = TDA10046_XTAL_16M, .agc_config = TDA10046_AGC_IFO_AUTO_NEG, .if_freq = TDA10046_FREQ_3613, - .pll_init = philips_fmd1216_pll_init, - .pll_set = philips_fmd1216_pll_set, - .pll_sleep = philips_fmd1216_analog, .request_firmware = NULL, }; @@ -578,12 +594,12 @@ static struct tda827x_data tda827x_dvbt[ { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} }; -static int philips_tda827x_pll_init(struct dvb_frontend *fe) +static int philips_tda827x_tuner_init(struct dvb_frontend *fe) { return 0; } -static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_tda827x_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct saa7134_dev *dev = fe->dvb->priv; u8 tuner_buf[14]; @@ -630,6 +646,8 @@ static int philips_tda827x_pll_set(struc tuner_buf[13] = 0x40; tuner_msg.len = 14; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) return -EIO; @@ -638,18 +656,23 @@ static int philips_tda827x_pll_set(struc tuner_buf[0] = 0x30; tuner_buf[1] = 0x50 + tda827x_dvbt[i].cp; tuner_msg.len = 2; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); return 0; } -static void philips_tda827x_pll_sleep(struct dvb_frontend *fe) +static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827x_sleep[] = { 0x30, 0xd0}; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep, .len = sizeof(tda827x_sleep) }; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); + return 0; } static struct tda1004x_config tda827x_lifeview_config = { @@ -659,9 +682,6 @@ static struct tda1004x_config tda827x_li .xtal_freq = TDA10046_XTAL_16M, .agc_config = TDA10046_AGC_TDA827X, .if_freq = TDA10046_FREQ_045, - .pll_init = philips_tda827x_pll_init, - .pll_set = philips_tda827x_pll_set, - .pll_sleep = philips_tda827x_pll_sleep, .request_firmware = NULL, }; @@ -753,6 +773,8 @@ static int philips_tda827xa_pll_set(u8 a tuner_buf[12] = 0x00; tuner_buf[13] = 0x39; // lpsel msg.len = 14; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) return -EIO; @@ -760,10 +782,14 @@ static int philips_tda827xa_pll_set(u8 a msg.len = 2; reg2[0] = 0x60; reg2[1] = 0x3c; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &msg, 1); reg2[0] = 0xa0; reg2[1] = 0x40; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &msg, 1); msleep(2); @@ -771,36 +797,43 @@ static int philips_tda827xa_pll_set(u8 a reg2[0] = 0x30; reg2[1] = 0x10 + tda827xa_dvbt[i].scr; msg.len = 2; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &msg, 1); msleep(550); reg2[0] = 0x50; reg2[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &msg, 1); return 0; } -static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe) +static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827xa_sleep[] = { 0x30, 0x90}; struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep, .len = sizeof(tda827xa_sleep) }; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); - + return 0; } /* ------------------------------------------------------------------ */ -static int philips_tiger_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { int ret; struct saa7134_dev *dev = fe->dvb->priv; static u8 tda8290_close[] = { 0x21, 0xc0}; static u8 tda8290_open[] = { 0x21, 0x80}; struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2}; + /* close tda8290 i2c bridge */ tda8290_msg.buf = tda8290_close; ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1); @@ -816,7 +849,7 @@ static int philips_tiger_pll_set(struct return ret; } -static int philips_tiger_dvb_mode(struct dvb_frontend *fe) +static int philips_tiger_tuner_init(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; static u8 data[] = { 0x3c, 0x33, 0x6a}; @@ -827,14 +860,15 @@ static int philips_tiger_dvb_mode(struct return 0; } -static void philips_tiger_analog_mode(struct dvb_frontend *fe) +static int philips_tiger_tuner_sleep(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; static u8 data[] = { 0x3c, 0x33, 0x68}; struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; i2c_transfer(&dev->i2c_adap, &msg, 1); - philips_tda827xa_pll_sleep( 0x61, fe); + philips_tda827xa_tuner_sleep( 0x61, fe); + return 0; } static struct tda1004x_config philips_tiger_config = { @@ -844,15 +878,12 @@ static struct tda1004x_config philips_ti .xtal_freq = TDA10046_XTAL_16M, .agc_config = TDA10046_AGC_TDA827X, .if_freq = TDA10046_FREQ_045, - .pll_init = philips_tiger_dvb_mode, - .pll_set = philips_tiger_pll_set, - .pll_sleep = philips_tiger_analog_mode, .request_firmware = NULL, }; /* ------------------------------------------------------------------ */ -static int lifeview_trio_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int lifeview_trio_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { int ret; @@ -860,16 +891,12 @@ static int lifeview_trio_pll_set(struct return ret; } -static int lifeview_trio_dvb_mode(struct dvb_frontend *fe) +static int lifeview_trio_tuner_sleep(struct dvb_frontend *fe) { + philips_tda827xa_tuner_sleep(0x60, fe); return 0; } -static void lifeview_trio_analog_mode(struct dvb_frontend *fe) -{ - philips_tda827xa_pll_sleep(0x60, fe); -} - static struct tda1004x_config lifeview_trio_config = { .demod_address = 0x09, .invert = 1, @@ -877,15 +904,12 @@ static struct tda1004x_config lifeview_t .xtal_freq = TDA10046_XTAL_16M, .agc_config = TDA10046_AGC_TDA827X_GPL, .if_freq = TDA10046_FREQ_045, - .pll_init = lifeview_trio_dvb_mode, - .pll_set = lifeview_trio_pll_set, - .pll_sleep = lifeview_trio_analog_mode, .request_firmware = NULL, }; /* ------------------------------------------------------------------ */ -static int ads_duo_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int ads_duo_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { int ret; @@ -893,7 +917,7 @@ static int ads_duo_pll_set(struct dvb_fr return ret; } -static int ads_duo_dvb_mode(struct dvb_frontend *fe) +static int ads_duo_tuner_init(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; /* route TDA8275a AGC input to the channel decoder */ @@ -901,12 +925,13 @@ static int ads_duo_dvb_mode(struct dvb_f return 0; } -static void ads_duo_analog_mode(struct dvb_frontend *fe) +static int ads_duo_tuner_sleep(struct dvb_frontend *fe) { struct saa7134_dev *dev = fe->dvb->priv; /* route TDA8275a AGC input to the analog IF chip*/ saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x20); - philips_tda827xa_pll_sleep( 0x61, fe); + philips_tda827xa_tuner_sleep( 0x61, fe); + return 0; } static struct tda1004x_config ads_tech_duo_config = { @@ -916,31 +941,24 @@ static struct tda1004x_config ads_tech_d .xtal_freq = TDA10046_XTAL_16M, .agc_config = TDA10046_AGC_TDA827X_GPL, .if_freq = TDA10046_FREQ_045, - .pll_init = ads_duo_dvb_mode, - .pll_set = ads_duo_pll_set, - .pll_sleep = ads_duo_analog_mode, .request_firmware = NULL, }; /* ------------------------------------------------------------------ */ -static int tevion_dvb220rf_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int tevion_dvb220rf_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { int ret; ret = philips_tda827xa_pll_set(0x60, fe, params); return ret; } -static int tevion_dvb220rf_pll_init(struct dvb_frontend *fe) +static int tevion_dvb220rf_tuner_sleep(struct dvb_frontend *fe) { + philips_tda827xa_tuner_sleep( 0x61, fe); return 0; } -static void tevion_dvb220rf_pll_sleep(struct dvb_frontend *fe) -{ - philips_tda827xa_pll_sleep( 0x61, fe); -} - static struct tda1004x_config tevion_dvbt220rf_config = { .demod_address = 0x08, .invert = 1, @@ -948,9 +966,6 @@ static struct tda1004x_config tevion_dvb .xtal_freq = TDA10046_XTAL_16M, .agc_config = TDA10046_AGC_TDA827X, .if_freq = TDA10046_FREQ_045, - .pll_init = tevion_dvb220rf_pll_init, - .pll_set = tevion_dvb220rf_pll_set, - .pll_sleep = tevion_dvb220rf_pll_sleep, .request_firmware = NULL, }; @@ -961,8 +976,6 @@ #endif #ifdef HAVE_NXT200X static struct nxt200x_config avertvhda180 = { .demod_address = 0x0a, - .pll_address = 0x61, - .pll_desc = &dvb_pll_tdhu2, }; static int nxt200x_set_pll_input(u8 *buf, int input) @@ -976,8 +989,6 @@ static int nxt200x_set_pll_input(u8 *buf static struct nxt200x_config kworldatsc110 = { .demod_address = 0x0a, - .pll_address = 0x61, - .pll_desc = &dvb_pll_tuv1236d, .set_pll_input = nxt200x_set_pll_input, }; #endif @@ -1003,78 +1014,158 @@ #ifdef HAVE_MT352 printk("%s: pinnacle 300i dvb setup\n",dev->name); dev->dvb.frontend = mt352_attach(&pinnacle_300i, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params; + } break; case SAA7134_BOARD_AVERMEDIA_777: printk("%s: avertv 777 dvb setup\n",dev->name); dev->dvb.frontend = mt352_attach(&avermedia_777, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.calc_regs = mt352_aver777_tuner_calc_regs; + } break; #endif #ifdef HAVE_TDA1004X case SAA7134_BOARD_MD7134: dev->dvb.frontend = tda10046_attach(&medion_cardbus, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init; + dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params; + } break; case SAA7134_BOARD_PHILIPS_TOUGH: dev->dvb.frontend = tda10046_attach(&philips_tu1216_60_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_60_init; + dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_60_set_params; + } break; case SAA7134_BOARD_FLYDVBTDUO: dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init; + dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params; + } break; case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init; + dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params; + } break; case SAA7134_BOARD_PHILIPS_EUROPA: dev->dvb.frontend = tda10046_attach(&philips_europa_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; + dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; + dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init; + dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; + } break; case SAA7134_BOARD_VIDEOMATE_DVBT_300: dev->dvb.frontend = tda10046_attach(&philips_europa_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init; + dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; + } break; case SAA7134_BOARD_VIDEOMATE_DVBT_200: dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_61_init; + dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_61_set_params; + } break; case SAA7134_BOARD_PHILIPS_TIGER: dev->dvb.frontend = tda10046_attach(&philips_tiger_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; + dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; + } break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: dev->dvb.frontend = tda10046_attach(&philips_tiger_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init; + dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params; + } break; case SAA7134_BOARD_FLYDVBT_LR301: dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init; + dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params; + } break; case SAA7134_BOARD_FLYDVB_TRIO: dev->dvb.frontend = tda10046_attach(&lifeview_trio_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params; + } break; case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init; + dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = ads_duo_tuner_set_params; + } break; case SAA7134_BOARD_TEVION_DVBT_220RF: dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.sleep = tevion_dvb220rf_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = tevion_dvb220rf_tuner_set_params; + } break; case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS: dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config, &dev->i2c_adap); + if (dev->dvb.frontend) { + dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init; + dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep; + dev->dvb.frontend->ops.tuner_ops.set_params = ads_duo_tuner_set_params; + } break; #endif #ifdef HAVE_NXT200X case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: dev->dvb.frontend = nxt200x_attach(&avertvhda180, &dev->i2c_adap); + if (dev->dvb.frontend) { + dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tdhu2); + } break; case SAA7134_BOARD_KWORLD_ATSC110: dev->dvb.frontend = nxt200x_attach(&kworldatsc110, &dev->i2c_adap); + if (dev->dvb.frontend) { + dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tuv1236d); + } break; #endif default: @@ -1088,7 +1179,7 @@ #endif } /* register everything else */ - return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); + return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev); } static int dvb_fini(struct saa7134_dev *dev) diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 1d972ed..65d0440 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -64,8 +64,10 @@ static void ts_reset_encoder(struct saa7 static int ts_init_encoder(struct saa7134_dev* dev) { + struct v4l2_ext_controls ctrls = { V4L2_CTRL_CLASS_MPEG, 0 }; + ts_reset_encoder(dev); - saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL); + saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, &ctrls); dev->empress_started = 1; return 0; } @@ -162,6 +164,7 @@ static int ts_do_ioctl(struct inode *ino unsigned int cmd, void *arg) { struct saa7134_dev *dev = file->private_data; + struct v4l2_ext_controls *ctrls = arg; if (debug > 1) v4l_print_ioctl(dev->name,cmd); @@ -278,12 +281,31 @@ static int ts_do_ioctl(struct inode *ino return saa7134_common_ioctl(dev, cmd, arg); case VIDIOC_S_MPEGCOMP: + printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. " + "Replace with VIDIOC_S_EXT_CTRLS!"); saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, arg); ts_init_encoder(dev); return 0; case VIDIOC_G_MPEGCOMP: + printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. " + "Replace with VIDIOC_G_EXT_CTRLS!"); saa7134_i2c_call_clients(dev, VIDIOC_G_MPEGCOMP, arg); return 0; + case VIDIOC_S_EXT_CTRLS: + /* count == 0 is abused in saa6752hs.c, so that special + case is handled here explicitly. */ + if (ctrls->count == 0) + return 0; + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, arg); + ts_init_encoder(dev); + return 0; + case VIDIOC_G_EXT_CTRLS: + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + saa7134_i2c_call_clients(dev, VIDIOC_G_EXT_CTRLS, arg); + return 0; default: return -ENOIOCTLCMD; diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 1426e4c..7c59549 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -37,6 +37,10 @@ static unsigned int ir_debug = 0; module_param(ir_debug, int, 0644); MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); +static int pinnacle_remote = 0; +module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */ +MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)"); + #define dprintk(fmt, arg...) if (ir_debug) \ printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg) #define i2cdprintk(fmt, arg...) if (ir_debug) \ @@ -316,8 +320,13 @@ void saa7134_set_i2c_ir(struct saa7134_d switch (dev->board) { case SAA7134_BOARD_PINNACLE_PCTV_110i: snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); - ir->get_key = get_key_pinnacle; - ir->ir_codes = ir_codes_pinnacle; + if (pinnacle_remote == 0) { + ir->get_key = get_key_pinnacle_color; + ir->ir_codes = ir_codes_pinnacle_color; + } else { + ir->get_key = get_key_pinnacle_grey; + ir->ir_codes = ir_codes_pinnacle_grey; + } break; case SAA7134_BOARD_UPMOST_PURPLE_TV: snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV"); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 353af3a..d5ee99c 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -221,6 +222,7 @@ #define SAA7134_BOARD_AVERMEDIA_A169_B 9 #define SAA7134_BOARD_AVERMEDIA_A169_B1 92 #define SAA7134_BOARD_MD7134_BRIDGE_2 93 #define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94 +#define SAA7134_BOARD_FLYVIDEO3000_NTSC 95 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 @@ -531,6 +533,7 @@ #endif /* SAA7134_MPEG_DVB only */ struct videobuf_dvb dvb; + int (*original_demod_sleep)(struct dvb_frontend* fe); }; /* ----------------------------------------------------------- */ diff --git a/drivers/media/video/se401.h b/drivers/media/video/se401.h index a7a216b..c0891b3 100644 --- a/drivers/media/video/se401.h +++ b/drivers/media/video/se401.h @@ -4,6 +4,7 @@ #define __LINUX_se401_H #include #include +#include #include #include diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index ea4394d..48d138a 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -2608,11 +2608,9 @@ static int sn9c102_ioctl_v4l2(struct ino case VIDIOC_G_CTRL: return sn9c102_vidioc_g_ctrl(cam, arg); - case VIDIOC_S_CTRL_OLD: case VIDIOC_S_CTRL: return sn9c102_vidioc_s_ctrl(cam, arg); - case VIDIOC_CROPCAP_OLD: case VIDIOC_CROPCAP: return sn9c102_vidioc_cropcap(cam, arg); @@ -2659,7 +2657,6 @@ static int sn9c102_ioctl_v4l2(struct ino case VIDIOC_G_PARM: return sn9c102_vidioc_g_parm(cam, arg); - case VIDIOC_S_PARM_OLD: case VIDIOC_S_PARM: return sn9c102_vidioc_s_parm(cam, arg); diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 07476c7..6be9c11 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c @@ -42,6 +42,7 @@ #include #include #include #include +#include #include "saa7146.h" #include "saa7146reg.h" diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index b38bda8..351b182 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -66,6 +66,7 @@ #include #include #include #include +#include #include #include diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 103ccb9..827633b 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -26,6 +26,7 @@ #include #include #include #include +#include #include #include #include @@ -163,7 +164,7 @@ static void do_tda9875_init(struct i2c_c struct tda9875 *t = i2c_get_clientdata(client); dprintk("In tda9875_init\n"); tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/ - tda9875_write(client, TDA9875_MSR, 0x03 ); /* Monitor 0b00000XXX*/ + tda9875_write(client, TDA9875_MSR, 0x03 ); /* Monitor 0b00000XXX*/ tda9875_write(client, TDA9875_C1MSB, 0x00 ); /*Car1(FM) MSB XMHz*/ tda9875_write(client, TDA9875_C1MIB, 0x00 ); /*Car1(FM) MIB XMHz*/ tda9875_write(client, TDA9875_C1LSB, 0x00 ); /*Car1(FM) LSB XMHz*/ diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 0d54f6c..b6ae969 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -18,49 +18,21 @@ #include TDA9886 (PAL, SECAM, NTSC) TDA9887 (PAL, SECAM, NTSC, FM Radio) - found on: - - Pinnacle PCTV (Jul.2002 Version with MT2032, bttv) - TDA9887 (world), TDA9885 (USA) - Note: OP2 of tda988x must be set to 1, else MT2032 is disabled! - - KNC One TV-Station RDS (saa7134) - - Hauppauge PVR-150/500 (possibly more) + Used as part of several tuners */ +#define tda9887_info(fmt, arg...) do {\ + printk(KERN_INFO "%s %d-%04x (tda9887): " fmt, t->i2c.name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) +#define tda9887_dbg(fmt, arg...) do {\ + if (tuner_debug) \ + printk(KERN_INFO "%s %d-%04x (tda9887): " fmt, t->i2c.name, \ + i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0) -/* Addresses to scan */ -static unsigned short normal_i2c[] = { - 0x84 >>1, - 0x86 >>1, - 0x96 >>1, - I2C_CLIENT_END, -}; -I2C_CLIENT_INSMOD; - -/* insmod options */ -static unsigned int debug = 0; -module_param(debug, int, 0644); -MODULE_LICENSE("GPL"); /* ---------------------------------------------------------------------- */ #define UNSET (-1U) -#define tda9887_info(fmt, arg...) do {\ - printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ - i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) -#define tda9887_dbg(fmt, arg...) do {\ - if (debug) \ - printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ - i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) - -struct tda9887 { - struct i2c_client client; - v4l2_std_id std; - enum tuner_mode mode; - unsigned int config; - unsigned int using_v4l2; - unsigned int radio_mode; - unsigned char data[4]; -}; struct tvnorm { v4l2_std_id std; @@ -70,9 +42,6 @@ struct tvnorm { unsigned char e; }; -static struct i2c_driver driver; -static struct i2c_client client_template; - /* ---------------------------------------------------------------------- */ // @@ -281,7 +250,7 @@ static struct tvnorm radio_mono = { /* ---------------------------------------------------------------------- */ -static void dump_read_message(struct tda9887 *t, unsigned char *buf) +static void dump_read_message(struct tuner *t, unsigned char *buf) { static char *afc[16] = { "- 12.5 kHz", @@ -309,7 +278,7 @@ static void dump_read_message(struct tda tda9887_info(" vfi level : %s\n", (buf[0] & 0x80) ? "high" : "low"); } -static void dump_write_message(struct tda9887 *t, unsigned char *buf) +static void dump_write_message(struct tuner *t, unsigned char *buf) { static char *sound[4] = { "AM/TV", @@ -405,13 +374,13 @@ static void dump_write_message(struct td /* ---------------------------------------------------------------------- */ -static int tda9887_set_tvnorm(struct tda9887 *t, char *buf) +static int tda9887_set_tvnorm(struct tuner *t, char *buf) { struct tvnorm *norm = NULL; int i; - if (t->mode == T_RADIO) { - if (t->radio_mode == V4L2_TUNER_MODE_MONO) + if (t->mode == V4L2_TUNER_RADIO) { + if (t->audmode == V4L2_TUNER_MODE_MONO) norm = &radio_mono; else norm = &radio_stereo; @@ -445,7 +414,7 @@ module_param(port2, int, 0644); module_param(qss, int, 0644); module_param(adjust, int, 0644); -static int tda9887_set_insmod(struct tda9887 *t, char *buf) +static int tda9887_set_insmod(struct tuner *t, char *buf) { if (UNSET != port1) { if (port1) @@ -474,27 +443,27 @@ static int tda9887_set_insmod(struct tda return 0; } -static int tda9887_set_config(struct tda9887 *t, char *buf) +static int tda9887_set_config(struct tuner *t, char *buf) { - if (t->config & TDA9887_PORT1_ACTIVE) + if (t->tda9887_config & TDA9887_PORT1_ACTIVE) buf[1] &= ~cOutputPort1Inactive; - if (t->config & TDA9887_PORT1_INACTIVE) + if (t->tda9887_config & TDA9887_PORT1_INACTIVE) buf[1] |= cOutputPort1Inactive; - if (t->config & TDA9887_PORT2_ACTIVE) + if (t->tda9887_config & TDA9887_PORT2_ACTIVE) buf[1] &= ~cOutputPort2Inactive; - if (t->config & TDA9887_PORT2_INACTIVE) + if (t->tda9887_config & TDA9887_PORT2_INACTIVE) buf[1] |= cOutputPort2Inactive; - if (t->config & TDA9887_QSS) + if (t->tda9887_config & TDA9887_QSS) buf[1] |= cQSS; - if (t->config & TDA9887_INTERCARRIER) + if (t->tda9887_config & TDA9887_INTERCARRIER) buf[1] &= ~cQSS; - if (t->config & TDA9887_AUTOMUTE) + if (t->tda9887_config & TDA9887_AUTOMUTE) buf[1] |= cAutoMuteFmActive; - if (t->config & TDA9887_DEEMPHASIS_MASK) { + if (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) { buf[2] &= ~0x60; - switch (t->config & TDA9887_DEEMPHASIS_MASK) { + switch (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) { case TDA9887_DEEMPHASIS_NONE: buf[2] |= cDeemphasisOFF; break; @@ -506,153 +475,36 @@ static int tda9887_set_config(struct tda break; } } - if (t->config & TDA9887_TOP_SET) { + if (t->tda9887_config & TDA9887_TOP_SET) { buf[2] &= ~cTopMask; - buf[2] |= (t->config >> 8) & cTopMask; + buf[2] |= (t->tda9887_config >> 8) & cTopMask; } - if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) + if ((t->tda9887_config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) buf[1] &= ~cQSS; return 0; } /* ---------------------------------------------------------------------- */ -static char pal[] = "--"; -static char secam[] = "--"; -static char ntsc[] = "-"; - -module_param_string(pal, pal, sizeof(pal), 0644); -module_param_string(secam, secam, sizeof(secam), 0644); -module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); - -static int tda9887_fixup_std(struct tda9887 *t) -{ - /* get more precise norm info from insmod option */ - if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) { - switch (pal[0]) { - case 'b': - case 'B': - case 'g': - case 'G': - case 'h': - case 'H': - case 'n': - case 'N': - if (pal[1] == 'c' || pal[1] == 'C') { - tda9887_dbg("insmod fixup: PAL => PAL-Nc\n"); - t->std = V4L2_STD_PAL_Nc; - } else { - tda9887_dbg("insmod fixup: PAL => PAL-BGHN\n"); - t->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N; - } - break; - case 'i': - case 'I': - tda9887_dbg("insmod fixup: PAL => PAL-I\n"); - t->std = V4L2_STD_PAL_I; - break; - case 'd': - case 'D': - case 'k': - case 'K': - tda9887_dbg("insmod fixup: PAL => PAL-DK\n"); - t->std = V4L2_STD_PAL_DK; - break; - case 'm': - case 'M': - tda9887_dbg("insmod fixup: PAL => PAL-M\n"); - t->std = V4L2_STD_PAL_M; - break; - case '-': - /* default parameter, do nothing */ - break; - default: - tda9887_info("pal= argument not recognised\n"); - break; - } - } - if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { - switch (secam[0]) { - case 'b': - case 'B': - case 'g': - case 'G': - case 'h': - case 'H': - tda9887_dbg("insmod fixup: SECAM => SECAM-BGH\n"); - t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; - break; - case 'd': - case 'D': - case 'k': - case 'K': - tda9887_dbg("insmod fixup: SECAM => SECAM-DK\n"); - t->std = V4L2_STD_SECAM_DK; - break; - case 'l': - case 'L': - if (secam[1] == 'c' || secam[1] == 'C') { - tda9887_dbg("insmod fixup: SECAM => SECAM-L'\n"); - t->std = V4L2_STD_SECAM_LC; - } else { - tda9887_dbg("insmod fixup: SECAM => SECAM-L\n"); - t->std = V4L2_STD_SECAM_L; - } - break; - case '-': - /* default parameter, do nothing */ - break; - default: - tda9887_info("secam= argument not recognised\n"); - break; - } - } - if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) { - switch (ntsc[0]) { - case 'm': - case 'M': - tda9887_dbg("insmod fixup: NTSC => NTSC-M\n"); - t->std = V4L2_STD_NTSC_M; - break; - case 'j': - case 'J': - tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); - t->std = V4L2_STD_NTSC_M_JP; - break; - case 'k': - case 'K': - tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); - t->std = V4L2_STD_NTSC_M_KR; - break; - case '-': - /* default parameter, do nothing */ - break; - default: - tda9887_info("ntsc= argument not recognised\n"); - break; - } - } - return 0; -} - -static int tda9887_status(struct tda9887 *t) +static int tda9887_status(struct tuner *t) { unsigned char buf[1]; int rc; memset(buf,0,sizeof(buf)); - if (1 != (rc = i2c_master_recv(&t->client,buf,1))) + if (1 != (rc = i2c_master_recv(&t->i2c,buf,1))) tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); dump_read_message(t, buf); return 0; } -static int tda9887_configure(struct tda9887 *t) +static void tda9887_configure(struct i2c_client *client) { + struct tuner *t = i2c_get_clientdata(client); int rc; - memset(t->data,0,sizeof(t->data)); - tda9887_set_tvnorm(t,t->data); + memset(t->tda9887_data,0,sizeof(t->tda9887_data)); + tda9887_set_tvnorm(t,t->tda9887_data); /* A note on the port settings: These settings tend to depend on the specifics of the board. @@ -667,249 +519,84 @@ static int tda9887_configure(struct tda9 the ports should be set to active (0), but, again, that may differ depending on the precise hardware configuration. */ - t->data[1] |= cOutputPort1Inactive; - t->data[1] |= cOutputPort2Inactive; + t->tda9887_data[1] |= cOutputPort1Inactive; + t->tda9887_data[1] |= cOutputPort2Inactive; - tda9887_set_config(t,t->data); - tda9887_set_insmod(t,t->data); + tda9887_set_config(t,t->tda9887_data); + tda9887_set_insmod(t,t->tda9887_data); if (t->mode == T_STANDBY) { - t->data[1] |= cForcedMuteAudioON; + t->tda9887_data[1] |= cForcedMuteAudioON; } tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", - t->data[1],t->data[2],t->data[3]); - if (debug > 1) - dump_write_message(t, t->data); + t->tda9887_data[1],t->tda9887_data[2],t->tda9887_data[3]); + if (tuner_debug > 1) + dump_write_message(t, t->tda9887_data); - if (4 != (rc = i2c_master_send(&t->client,t->data,4))) + if (4 != (rc = i2c_master_send(&t->i2c,t->tda9887_data,4))) tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); - if (debug > 2) { + if (tuner_debug > 2) { msleep_interruptible(1000); tda9887_status(t); } - return 0; } /* ---------------------------------------------------------------------- */ -static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) +static void tda9887_tuner_status(struct i2c_client *client) { - struct tda9887 *t; - - client_template.adapter = adap; - client_template.addr = addr; - - if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL))) - return -ENOMEM; - - t->client = client_template; - t->std = 0; - t->radio_mode = V4L2_TUNER_MODE_STEREO; - - tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); - - i2c_set_clientdata(&t->client, t); - i2c_attach_client(&t->client); - - return 0; + struct tuner *t = i2c_get_clientdata(client); + tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->tda9887_data[1], t->tda9887_data[2], t->tda9887_data[3]); } -static int tda9887_probe(struct i2c_adapter *adap) +static int tda9887_get_afc(struct i2c_client *client) { - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, tda9887_attach); - return 0; -} + struct tuner *t = i2c_get_clientdata(client); + static int AFC_BITS_2_kHz[] = { + -12500, -37500, -62500, -97500, + -112500, -137500, -162500, -187500, + 187500, 162500, 137500, 112500, + 97500 , 62500, 37500 , 12500 + }; + int afc=0; + __u8 reg = 0; -static int tda9887_detach(struct i2c_client *client) -{ - struct tda9887 *t = i2c_get_clientdata(client); + if (1 == i2c_master_recv(&t->i2c,®,1)) + afc = AFC_BITS_2_kHz[(reg>>1)&0x0f]; - i2c_detach_client(client); - kfree(t); - return 0; + return afc; } -#define SWITCH_V4L2 if (!t->using_v4l2 && debug) \ - tda9887_info("switching to v4l2\n"); \ - t->using_v4l2 = 1; -#define CHECK_V4L2 if (t->using_v4l2) { if (debug) \ - tda9887_info("ignore v4l1 call\n"); \ - return 0; } - -static int -tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) +static void tda9887_standby(struct i2c_client *client) { - struct tda9887 *t = i2c_get_clientdata(client); - - switch (cmd) { - - /* --- configuration --- */ - case AUDC_SET_RADIO: - { - t->mode = T_RADIO; - tda9887_configure(t); - break; - } - case TUNER_SET_STANDBY: - { - t->mode = T_STANDBY; - tda9887_configure(t); - break; - } - case TDA9887_SET_CONFIG: - { - int *i = arg; - - t->config = *i; - tda9887_configure(t); - break; - } - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCSCHAN: - { - static const v4l2_std_id map[] = { - [ VIDEO_MODE_PAL ] = V4L2_STD_PAL, - [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M, - [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM, - [ 4 /* bttv */ ] = V4L2_STD_PAL_M, - [ 5 /* bttv */ ] = V4L2_STD_PAL_N, - [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP, - }; - struct video_channel *vc = arg; - - CHECK_V4L2; - t->mode = T_ANALOG_TV; - if (vc->norm < ARRAY_SIZE(map)) - t->std = map[vc->norm]; - tda9887_fixup_std(t); - tda9887_configure(t); - break; - } - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; - - SWITCH_V4L2; - t->mode = T_ANALOG_TV; - t->std = *id; - tda9887_fixup_std(t); - tda9887_configure(t); - break; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; - - SWITCH_V4L2; - if (V4L2_TUNER_ANALOG_TV == f->type) { - if (t->mode == T_ANALOG_TV) - return 0; - t->mode = T_ANALOG_TV; - } - if (V4L2_TUNER_RADIO == f->type) { - if (t->mode == T_RADIO) - return 0; - t->mode = T_RADIO; - } - tda9887_configure(t); - break; - } - case VIDIOC_G_TUNER: - { - static int AFC_BITS_2_kHz[] = { - -12500, -37500, -62500, -97500, - -112500, -137500, -162500, -187500, - 187500, 162500, 137500, 112500, - 97500 , 62500, 37500 , 12500 - }; - struct v4l2_tuner* tuner = arg; - - if (t->mode == T_RADIO) { - __u8 reg = 0; - tuner->afc=0; - if (1 == i2c_master_recv(&t->client,®,1)) - tuner->afc = AFC_BITS_2_kHz[(reg>>1)&0x0f]; - } - break; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner* tuner = arg; - - if (t->mode == T_RADIO) { - t->radio_mode = tuner->audmode; - tda9887_configure (t); - } - break; - } - case VIDIOC_LOG_STATUS: - { - tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->data[1], t->data[2], t->data[3]); - break; - } - default: - /* nothing */ - break; - } - return 0; + tda9887_configure(client); } -static int tda9887_suspend(struct device * dev, pm_message_t state) +static void tda9887_set_freq(struct i2c_client *client, unsigned int freq) { - struct i2c_client *c = container_of(dev, struct i2c_client, dev); - struct tda9887 *t = i2c_get_clientdata(c); - - tda9887_dbg("suspend\n"); - return 0; + tda9887_configure(client); } -static int tda9887_resume(struct device * dev) +int tda9887_tuner_init(struct i2c_client *c) { - struct i2c_client *c = container_of(dev, struct i2c_client, dev); - struct tda9887 *t = i2c_get_clientdata(c); + struct tuner *t = i2c_get_clientdata(c); - tda9887_dbg("resume\n"); - tda9887_configure(t); - return 0; -} + strlcpy(c->name, "tda9887", sizeof(c->name)); -/* ----------------------------------------------------------------------- */ - -static struct i2c_driver driver = { - .id = I2C_DRIVERID_TDA9887, - .attach_adapter = tda9887_probe, - .detach_client = tda9887_detach, - .command = tda9887_command, - .driver = { - .name = "tda9887", - .suspend = tda9887_suspend, - .resume = tda9887_resume, - }, -}; -static struct i2c_client client_template = -{ - .name = "tda9887", - .driver = &driver, -}; + tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr, + t->i2c.driver->driver.name); -static int __init tda9887_init_module(void) -{ - return i2c_add_driver(&driver); -} + t->set_tv_freq = tda9887_set_freq; + t->set_radio_freq = tda9887_set_freq; + t->standby = tda9887_standby; + t->tuner_status=tda9887_tuner_status; + t->get_afc=tda9887_get_afc; -static void __exit tda9887_cleanup_module(void) -{ - i2c_del_driver(&driver); + return 0; } -module_init(tda9887_init_module); -module_exit(tda9887_cleanup_module); - /* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index c2b98f8..d1c4178 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -3,7 +3,7 @@ * I2C address is allways 0xC0. * * - * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br) + * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@infradead.org) * This code is placed under the terms of the GNU General Public License * * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c new file mode 100644 index 0000000..76b2e96 --- /dev/null +++ b/drivers/media/video/tlv320aic23b.c @@ -0,0 +1,217 @@ +/* + * tlv320aic23b - driver version 0.0.1 + * + * Copyright (C) 2006 Scott Alfter + * + * Based on wm8775 driver + * + * Copyright (C) 2004 Ulf Eklund + * Copyright (C) 2005 Hans Verkuil + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("tlv320aic23b driver"); +MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil"); +MODULE_LICENSE("GPL"); + +static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END }; + + +I2C_CLIENT_INSMOD; + +/* ----------------------------------------------------------------------- */ + +struct tlv320aic23b_state { + u8 muted; +}; + +static int tlv320aic23b_write(struct i2c_client *client, int reg, u16 val) +{ + int i; + + if ((reg < 0 || reg > 9) && (reg != 15)) { + v4l_err(client, "Invalid register R%d\n", reg); + return -1; + } + + for (i = 0; i < 3; i++) { + if (i2c_smbus_write_byte_data(client, (reg << 1) | + (val >> 8), val & 0xff) == 0) { + return 0; + } + } + v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg); + return -1; +} + +static int tlv320aic23b_command(struct i2c_client *client, unsigned int cmd, + void *arg) +{ + struct tlv320aic23b_state *state = i2c_get_clientdata(client); + struct v4l2_control *ctrl = arg; + u32* freq = arg; + + switch (cmd) { + case VIDIOC_INT_AUDIO_CLOCK_FREQ: + switch (*freq) { + case 32000: /* set sample rate to 32 kHz */ + tlv320aic23b_write(client, 8, 0x018); + break; + case 44100: /* set sample rate to 44.1 kHz */ + tlv320aic23b_write(client, 8, 0x022); + break; + case 48000: /* set sample rate to 48 kHz */ + tlv320aic23b_write(client, 8, 0x000); + break; + default: + return -EINVAL; + } + break; + + case VIDIOC_G_CTRL: + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + ctrl->value = state->muted; + break; + + case VIDIOC_S_CTRL: + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + state->muted = ctrl->value; + tlv320aic23b_write(client, 0, 0x180); /* mute both channels */ + /* set gain on both channels to +3.0 dB */ + if (!state->muted) + tlv320aic23b_write(client, 0, 0x119); + break; + + case VIDIOC_LOG_STATUS: + v4l_info(client, "Input: %s\n", + state->muted ? "muted" : "active"); + break; + + default: + return -EINVAL; + } + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ + +/* + * Generic i2c probe + * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' + */ + +static struct i2c_driver i2c_driver; + +static int tlv320aic23b_attach(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct tlv320aic23b_state *state; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (client == 0) + return -ENOMEM; + + client->addr = address; + client->adapter = adapter; + client->driver = &i2c_driver; + snprintf(client->name, sizeof(client->name) - 1, "tlv320aic23b"); + + v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + + state = kmalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL); + if (state == NULL) { + kfree(client); + return -ENOMEM; + } + state->muted = 0; + i2c_set_clientdata(client, state); + + /* initialize tlv320aic23b */ + tlv320aic23b_write(client, 15, 0x000); /* RESET */ + tlv320aic23b_write(client, 6, 0x00A); /* turn off DAC & mic input */ + tlv320aic23b_write(client, 7, 0x049); /* left-justified, 24-bit, master mode */ + tlv320aic23b_write(client, 0, 0x119); /* set gain on both channels to +3.0 dB */ + tlv320aic23b_write(client, 8, 0x000); /* set sample rate to 48 kHz */ + tlv320aic23b_write(client, 9, 0x001); /* activate digital interface */ + + i2c_attach_client(client); + + return 0; +} + +static int tlv320aic23b_probe(struct i2c_adapter *adapter) +{ + if (adapter->class & I2C_CLASS_TV_ANALOG) + return i2c_probe(adapter, &addr_data, tlv320aic23b_attach); + return 0; +} + +static int tlv320aic23b_detach(struct i2c_client *client) +{ + int err; + + err = i2c_detach_client(client); + if (err) { + return err; + } + kfree(client); + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ +static struct i2c_driver i2c_driver = { + .driver = { + .name = "tlv320aic23b", + }, + .id = I2C_DRIVERID_TLV320AIC23B, + .attach_adapter = tlv320aic23b_probe, + .detach_client = tlv320aic23b_detach, + .command = tlv320aic23b_command, +}; + + +static int __init tlv320aic23b_init_module(void) +{ + return i2c_add_driver(&i2c_driver); +} + +static void __exit tlv320aic23b_cleanup_module(void) +{ + i2c_del_driver(&i2c_driver); +} + +module_init(tlv320aic23b_init_module); +module_exit(tlv320aic23b_cleanup_module); diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c index 74ab48c..bdf506e 100644 --- a/drivers/media/video/tuner-3036.c +++ b/drivers/media/video/tuner-3036.c @@ -25,6 +25,7 @@ #include #include #include +#include #include diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 1013b4d..a26ded7 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -199,7 +199,7 @@ static void set_type(struct i2c_client * i2c_master_send(c, buffer, 4); default_tuner_init(c); break; - case TUNER_LG_TDVS_H062F: + case TUNER_LG_TDVS_H06XF: /* Set the Auxiliary Byte. */ buffer[2] &= ~0x20; buffer[2] |= 0x18; @@ -215,6 +215,9 @@ static void set_type(struct i2c_client * i2c_master_send(c,buffer,4); default_tuner_init(c); break; + case TUNER_TDA9887: + tda9887_tuner_init(c); + break; default: default_tuner_init(c); break; @@ -241,6 +244,8 @@ static void set_addr(struct i2c_client * { struct tuner *t = i2c_get_clientdata(c); + tuner_dbg("set addr for type %i\n", t->type); + if ( t->type == UNSET && ((tun_setup->addr == ADDR_UNSET && (t->mode_mask & tun_setup->mode_mask)) || tun_setup->addr == c->addr)) { @@ -436,6 +441,7 @@ static int tuner_attach(struct i2c_adapt t->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */ t->audmode = V4L2_TUNER_MODE_STEREO; t->mode_mask = T_UNINITIALIZED; + t->tuner_status = tuner_status; if (tuner_debug_old) { tuner_debug = tuner_debug_old; printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n"); @@ -462,10 +468,14 @@ static int tuner_attach(struct i2c_adapt case 0x4b: /* If chip is not tda8290, don't register. since it can be tda9887*/ - if (tda8290_probe(&t->i2c) != 0) { - tuner_dbg("chip at addr %x is not a tda8290\n", addr); - kfree(t); - return 0; + if (tda8290_probe(&t->i2c) == 0) { + tuner_dbg("chip at addr %x is a tda8290\n", addr); + } else { + /* Default is being tda9887 */ + t->type = TUNER_TDA9887; + t->mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; + t->mode = T_STANDBY; + goto register_client; } break; case 0x60: @@ -592,6 +602,7 @@ static int tuner_command(struct i2c_clie case TUNER_SET_STANDBY: if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) return 0; + t->mode = T_STANDBY; if (t->standby) t->standby (client); break; @@ -604,6 +615,14 @@ static int tuner_command(struct i2c_clie /* Should be implemented, since bttv calls it */ tuner_dbg("VIDIOCSAUDIO not implemented.\n"); break; + case TDA9887_SET_CONFIG: + { + int *i = arg; + + t->tda9887_config = *i; + set_freq(client, t->tv_freq); + break; + } /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ @@ -711,14 +730,10 @@ static int tuner_command(struct i2c_clie { struct v4l2_frequency *f = arg; + if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") + == EINVAL) + return 0; switch_v4l2(); - if ((V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode) - || (V4L2_TUNER_DIGITAL_TV == f->type - && V4L2_TUNER_DIGITAL_TV != t->mode)) { - if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") - == EINVAL) - return 0; - } set_freq(client,f->frequency); break; @@ -744,6 +759,8 @@ static int tuner_command(struct i2c_clie switch_v4l2(); tuner->type = t->mode; + if (t->get_afc) + tuner->afc=t->get_afc(client); if (t->mode == V4L2_TUNER_ANALOG_TV) tuner->capability |= V4L2_TUNER_CAP_NORM; if (t->mode != V4L2_TUNER_RADIO) { @@ -787,7 +804,8 @@ static int tuner_command(struct i2c_clie break; } case VIDIOC_LOG_STATUS: - tuner_status(client); + if (t->tuner_status) + t->tuner_status(client); break; } diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index 5d7abed..6da6f82 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -105,7 +105,7 @@ static int tuner_stereo(struct i2c_clien switch (t->type) { case TUNER_PHILIPS_FM1216ME_MK3: - case TUNER_PHILIPS_FM1236_MK3: + case TUNER_PHILIPS_FM1236_MK3: case TUNER_PHILIPS_FM1256_IH3: stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); break; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index a1ae036..9d9226c 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -874,7 +874,7 @@ static struct tuner_params tuner_philips }; -/* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */ +/* ------ TUNER_LG_TDVS_H06XF - LG INNOTEK / INFINEON ATSC ----- */ static struct tuner_range tuner_tua6034_ntsc_ranges[] = { { 16 * 165.00 /*MHz*/, 0x8e, 0x01 }, @@ -883,7 +883,7 @@ static struct tuner_range tuner_tua6034_ }; -static struct tuner_params tuner_tua6034_params[] = { +static struct tuner_params tuner_lg_tdvs_h06xf_params[] = { { .type = TUNER_PARAM_TYPE_NTSC, .ranges = tuner_tua6034_ntsc_ranges, @@ -1024,6 +1024,22 @@ static struct tuner_params tuner_thomson }, }; +/* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */ + +static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = { + { 16 * 146.25 /*MHz*/, 0xce, 0x01, }, + { 16 * 428.50 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x08, }, +}; + +static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = { + { + .type = TUNER_PARAM_TYPE_PAL, + .ranges = tuner_samsung_tcpg_6121p30a_pal_ranges, + .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_pal_ranges), + }, +}; + /* --------------------------------------------------------------------- */ struct tunertype tuners[] = { @@ -1354,10 +1370,10 @@ struct tunertype tuners[] = { .params = tuner_philips_fmd1216me_mk3_params, .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params), }, - [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */ - .name = "LG TDVS-H062F/TUA6034", - .params = tuner_tua6034_params, - .count = ARRAY_SIZE(tuner_tua6034_params), + [TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */ + .name = "LG TDVS-H06xF", /* H061F, H062F & H064F */ + .params = tuner_lg_tdvs_h06xf_params, + .count = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params), }, [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */ .name = "Ymec TVF66T5-B/DFF", @@ -1400,6 +1416,16 @@ struct tunertype tuners[] = { .params = tuner_thomson_fe6600_params, .count = ARRAY_SIZE(tuner_thomson_fe6600_params), }, + [TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */ + .name = "Samsung TCPG 6121P30A", + .params = tuner_samsung_tcpg_6121p30a_params, + .count = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_params), + }, + [TUNER_TDA9887] = { /* Philips TDA 9887 IF PLL Demodulator. + This chip is part of some modern tuners */ + .name = "Philips TDA988[5,6,7] IF PLL Demodulator", + /* see tda9887.c for details */ + }, }; unsigned const int tuner_count = ARRAY_SIZE(tuners); diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index b463e99..30f8d80 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -200,7 +200,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "Philips FQ1286A MK4"}, { TUNER_ABSENT, "Philips FQ1216ME MK5"}, { TUNER_ABSENT, "Philips FQ1236 MK5"}, - { TUNER_ABSENT, "Samsung TCPG_6121P30A"}, + { TUNER_SAMSUNG_TCPG_6121P30A, "Samsung TCPG 6121P30A"}, { TUNER_TCL_2002MB, "TCL 2002MB_3H"}, { TUNER_ABSENT, "TCL 2002MI_3H"}, { TUNER_TCL_2002N, "TCL 2002N 5H"}, diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index 9e86cae..1654576 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c @@ -198,10 +198,6 @@ static int tvmixer_open(struct inode *in /* lock bttv in memory while the mixer is in use */ file->private_data = mix; -#ifndef I2C_PEC - if (client->adapter->inc_use) - client->adapter->inc_use(client->adapter); -#endif if (client->adapter->owner) try_module_get(client->adapter->owner); return 0; @@ -217,10 +213,6 @@ static int tvmixer_release(struct inode return -ENODEV; } -#ifndef I2C_PEC - if (client->adapter->dec_use) - client->adapter->dec_use(client->adapter); -#endif if (client->adapter->owner) module_put(client->adapter->owner); return 0; diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index dab4973..b167ffa 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -10,6 +10,7 @@ #include #include #include #include +#include #include "tvp5150_reg.h" @@ -89,7 +90,7 @@ struct tvp5150 { struct i2c_client *client; v4l2_std_id norm; /* Current set standard */ - int input; + struct v4l2_routing route; int enable; int bright; int contrast; @@ -283,29 +284,26 @@ static void dump_reg(struct i2c_client * /**************************************************************************** Basic functions ****************************************************************************/ -enum tvp5150_input { - TVP5150_ANALOG_CH0 = 0, - TVP5150_SVIDEO = 1, - TVP5150_ANALOG_CH1 = 2, - TVP5150_BLACK_SCREEN = 8 -}; -static inline void tvp5150_selmux(struct i2c_client *c, - enum tvp5150_input input) +static inline void tvp5150_selmux(struct i2c_client *c) { int opmode=0; - struct tvp5150 *decoder = i2c_get_clientdata(c); + int input = 0; - if (!decoder->enable) - input |= TVP5150_BLACK_SCREEN; + if ((decoder->route.output & TVP5150_BLACK_SCREEN) || !decoder->enable) + input = 8; switch (input) { - case TVP5150_ANALOG_CH0: - case TVP5150_ANALOG_CH1: + case TVP5150_COMPOSITE1: + input |= 2; + /* fall through */ + case TVP5150_COMPOSITE0: opmode=0x30; /* TV Mode */ break; + case TVP5150_SVIDEO: default: + input |= 1; opmode=0; /* Auto Mode */ break; } @@ -790,7 +788,7 @@ static inline void tvp5150_reset(struct tvp5150_vdp_init(c, vbi_ram_default); /* Selects decoder input */ - tvp5150_selmux(c, decoder->input); + tvp5150_selmux(c); /* Initializes TVP5150 to stream enabled values */ tvp5150_write_inittab(c, tvp5150_init_enable); @@ -860,6 +858,21 @@ static int tvp5150_command(struct i2c_cl case VIDIOC_INT_RESET: tvp5150_reset(c); break; + case VIDIOC_INT_G_VIDEO_ROUTING: + { + struct v4l2_routing *route = arg; + + *route = decoder->route; + break; + } + case VIDIOC_INT_S_VIDEO_ROUTING: + { + struct v4l2_routing *route = arg; + + decoder->route = *route; + tvp5150_selmux(c); + break; + } case VIDIOC_S_STD: if (decoder->norm == *(v4l2_std_id *)arg) break; @@ -1063,7 +1076,7 @@ static int tvp5150_detect_client(struct rv = i2c_attach_client(c); core->norm = V4L2_STD_ALL; /* Default is autodetect */ - core->input = 2; + core->route.input = TVP5150_COMPOSITE1; core->enable = 1; core->bright = 32768; core->contrast = 32768; diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig index 39269a2..59fb899 100644 --- a/drivers/media/video/usbvideo/Kconfig +++ b/drivers/media/video/usbvideo/Kconfig @@ -36,3 +36,15 @@ config USB_KONICAWC To compile this driver as a module, choose M here: the module will be called konicawc. + +config USB_QUICKCAM_MESSENGER + tristate "USB Logitech Quickcam Messenger" + depends on USB && VIDEO_DEV + select VIDEO_USBVIDEO + ---help--- + Say Y or M here to enable support for the USB Logitech Quickcam + Messenger webcam. + + To compile this driver as a module, choose M here: the + module will be called quickcam_messenger. + diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile index bb52eb8..4a1b144 100644 --- a/drivers/media/video/usbvideo/Makefile +++ b/drivers/media/video/usbvideo/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_VIDEO_USBVIDEO) += usbvi obj-$(CONFIG_USB_IBMCAM) += ibmcam.o ultracam.o obj-$(CONFIG_USB_KONICAWC) += konicawc.o obj-$(CONFIG_USB_VICAM) += vicam.o +obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += quickcam_messenger.o diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index c11f5d4..6f31ecc 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c @@ -15,8 +15,7 @@ #include #include #include -#include -#include +#include #include "usbvideo.h" diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c new file mode 100644 index 0000000..56e01b6 --- /dev/null +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -0,0 +1,1120 @@ +/* + * Driver for Logitech Quickcam Messenger usb video camera + * Copyright (C) Jaya Kumar + * + * This work was sponsored by CIS(M) Sdn Bhd. + * History: + * 05/08/2006 - Jaya Kumar + * I wrote this based on the konicawc by Simon Evans. + * - + * Full credit for reverse engineering and creating an initial + * working linux driver for the VV6422 goes to the qce-ga project by + * Tuukka Toivonen, Jochen Hoenicke, Peter McConnell, + * Cristiano De Michele, Georg Acher, Jean-Frederic Clere as well as + * others. + * --- + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include + +#include "usbvideo.h" +#include "quickcam_messenger.h" + +/* + * Version Information + */ + +#ifdef CONFIG_USB_DEBUG +static int debug; +#define DEBUG(n, format, arg...) \ + if (n <= debug) { \ + printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \ + } +#else +#define DEBUG(n, arg...) +static const int debug = 0; +#endif + +#define DRIVER_VERSION "v0.01" +#define DRIVER_DESC "Logitech Quickcam Messenger USB" + +#define USB_LOGITECH_VENDOR_ID 0x046D +#define USB_QCM_PRODUCT_ID 0x08F0 + +#define MAX_CAMERAS 1 + +#define MAX_COLOUR 32768 +#define MAX_HUE 32768 +#define MAX_BRIGHTNESS 32768 +#define MAX_CONTRAST 32768 +#define MAX_WHITENESS 32768 + +static int size = SIZE_320X240; +static int colour = MAX_COLOUR; +static int hue = MAX_HUE; +static int brightness = MAX_BRIGHTNESS; +static int contrast = MAX_CONTRAST; +static int whiteness = MAX_WHITENESS; + +static struct usbvideo *cams; + +static struct usb_device_id qcm_table [] = { + { USB_DEVICE(USB_LOGITECH_VENDOR_ID, USB_QCM_PRODUCT_ID) }, + { } +}; +MODULE_DEVICE_TABLE(usb, qcm_table); + +#ifdef CONFIG_INPUT +static void qcm_register_input(struct qcm *cam, struct usb_device *dev) +{ + struct input_dev *input_dev; + + usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); + strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); + + cam->input = input_dev = input_allocate_device(); + if (!input_dev) { + warn("insufficient mem for cam input device"); + return; + } + + input_dev->name = "QCM button"; + input_dev->phys = cam->input_physname; + usb_to_input_id(dev, &input_dev->id); + input_dev->cdev.dev = &dev->dev; + + input_dev->evbit[0] = BIT(EV_KEY); + input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); + + input_dev->private = cam; + + input_register_device(cam->input); +} + +static void qcm_unregister_input(struct qcm *cam) +{ + if (cam->input) { + input_unregister_device(cam->input); + cam->input = NULL; + } +} + +static void qcm_report_buttonstat(struct qcm *cam) +{ + if (cam->input) { + input_report_key(cam->input, BTN_0, cam->button_sts); + input_sync(cam->input); + } +} + +static void qcm_int_irq(struct urb *urb, struct pt_regs *regs) +{ + int ret; + struct uvd *uvd = urb->context; + struct qcm *cam; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return; + + if (!uvd->streaming) + return; + + uvd->stats.urb_count++; + + if (urb->status < 0) + uvd->stats.iso_err_count++; + else { + if (urb->actual_length > 0 ) { + cam = (struct qcm *) uvd->user_data; + if (cam->button_sts_buf == 0x88) + cam->button_sts = 0x0; + else if (cam->button_sts_buf == 0x80) + cam->button_sts = 0x1; + qcm_report_buttonstat(cam); + } + } + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret < 0) + err("usb_submit_urb error (%d)", ret); +} + +static int qcm_setup_input_int(struct qcm *cam, struct uvd *uvd) +{ + int errflag; + usb_fill_int_urb(cam->button_urb, uvd->dev, + usb_rcvintpipe(uvd->dev, uvd->video_endp + 1), + &cam->button_sts_buf, + 1, + qcm_int_irq, + uvd, 16); + + errflag = usb_submit_urb(cam->button_urb, GFP_KERNEL); + if (errflag) + err ("usb_submit_int ret %d", errflag); + return errflag; +} + +static void qcm_stop_int_data(struct qcm *cam) +{ + usb_kill_urb(cam->button_urb); +} + +static int qcm_alloc_int_urb(struct qcm *cam) +{ + cam->button_urb = usb_alloc_urb(0, GFP_KERNEL); + + if (!cam->button_urb) + return -ENOMEM; + + return 0; +} + +static void qcm_free_int(struct qcm *cam) +{ + if (cam->button_urb) + usb_free_urb(cam->button_urb); +} +#endif /* CONFIG_INPUT */ + +static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val) +{ + int ret; + + /* we'll wait up to 3 slices but no more */ + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, + reg, 0, &val, 1, 3*HZ); + return ret; +} + +static int qcm_stv_setw(struct usb_device *dev, u16 reg, u16 val) +{ + int ret; + + /* we'll wait up to 3 slices but no more */ + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, + reg, 0, &val, 2, 3*HZ); + return ret; +} + +static int qcm_stv_getw(struct usb_device *dev, unsigned short reg, + __le16 *val) +{ + int ret; + + /* we'll wait up to 3 slices but no more */ + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + 0x04, USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, + reg, 0, val, 2, 3*HZ); + return ret; +} + +static int qcm_camera_on(struct uvd *uvd) +{ + int ret; + CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x01)); + return 0; +} + +static int qcm_camera_off(struct uvd *uvd) +{ + int ret; + CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00)); + return 0; +} + +static void qcm_hsv2rgb(u16 hue, u16 sat, u16 val, u16 *r, u16 *g, u16 *b) +{ + unsigned int segment, valsat; + signed int h = (signed int) hue; + unsigned int s = (sat - 32768) * 2; /* rescale */ + unsigned int v = val; + unsigned int p; + + /* + the registers controling gain are 8 bit of which + we affect only the last 4 bits with our gain. + we know that if saturation is 0, (unsaturated) then + we're grayscale (center axis of the colour cone) so + we set rgb=value. we use a formula obtained from + wikipedia to map the cone to the RGB plane. it's + as follows for the human value case of h=0..360, + s=0..1, v=0..1 + h_i = h/60 % 6 , f = h/60 - h_i , p = v(1-s) + q = v(1 - f*s) , t = v(1 - (1-f)s) + h_i==0 => r=v , g=t, b=p + h_i==1 => r=q , g=v, b=p + h_i==2 => r=p , g=v, b=t + h_i==3 => r=p , g=q, b=v + h_i==4 => r=t , g=p, b=v + h_i==5 => r=v , g=p, b=q + the bottom side (the point) and the stuff just up + of that is black so we simplify those two cases. + */ + if (sat < 32768) { + /* anything less than this is unsaturated */ + *r = val; + *g = val; + *b = val; + return; + } + if (val <= (0xFFFF/8)) { + /* anything less than this is black */ + *r = 0; + *g = 0; + *b = 0; + return; + } + + /* the rest of this code is copying tukkat's + implementation of the hsv2rgb conversion as taken + from qc-usb-messenger code. the 10923 is 0xFFFF/6 + to divide the cone into 6 sectors. */ + + segment = (h + 10923) & 0xFFFF; + segment = segment*3 >> 16; /* 0..2: 0=R, 1=G, 2=B */ + hue -= segment * 21845; /* -10923..10923 */ + h = hue; + h *= 3; + valsat = v*s >> 16; /* 0..65534 */ + p = v - valsat; + if (h >= 0) { + unsigned int t = v - (valsat * (32769 - h) >> 15); + switch (segment) { + case 0: /* R-> */ + *r = v; + *g = t; + *b = p; + break; + case 1: /* G-> */ + *r = p; + *g = v; + *b = t; + break; + case 2: /* B-> */ + *r = t; + *g = p; + *b = v; + break; + } + } else { + unsigned int q = v - (valsat * (32769 + h) >> 15); + switch (segment) { + case 0: /* ->R */ + *r = v; + *g = p; + *b = q; + break; + case 1: /* ->G */ + *r = q; + *g = v; + *b = p; + break; + case 2: /* ->B */ + *r = p; + *g = q; + *b = v; + break; + } + } +} + +static int qcm_sensor_set_gains(struct uvd *uvd, u16 hue, + u16 saturation, u16 value) +{ + int ret; + u16 r=0,g=0,b=0; + + /* this code is based on qc-usb-messenger */ + qcm_hsv2rgb(hue, saturation, value, &r, &g, &b); + + r >>= 12; + g >>= 12; + b >>= 12; + + /* min val is 8 */ + r = max((u16) 8, r); + g = max((u16) 8, g); + b = max((u16) 8, b); + + r |= 0x30; + g |= 0x30; + b |= 0x30; + + /* set the r,g,b gain registers */ + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x0509, r)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050A, g)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050B, b)); + + /* doing as qc-usb did */ + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050C, 0x2A)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050D, 0x01)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); + + return 0; +} + +static int qcm_sensor_set_exposure(struct uvd *uvd, int exposure) +{ + int ret; + int formedval; + + /* calculation was from qc-usb-messenger driver */ + formedval = ( exposure >> 12 ); + + /* max value for formedval is 14 */ + formedval = min(formedval, 14); + + CHECK_RET(ret, qcm_stv_setb(uvd->dev, + 0x143A, 0xF0 | formedval)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); + return 0; +} + +static int qcm_sensor_setlevels(struct uvd *uvd, int brightness, int contrast, + int hue, int colour) +{ + int ret; + /* brightness is exposure, contrast is gain, colour is saturation */ + CHECK_RET(ret, + qcm_sensor_set_exposure(uvd, brightness)); + CHECK_RET(ret, qcm_sensor_set_gains(uvd, hue, colour, contrast)); + + return 0; +} + +static int qcm_sensor_setsize(struct uvd *uvd, u8 size) +{ + int ret; + + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x1505, size)); + return 0; +} + +static int qcm_sensor_set_shutter(struct uvd *uvd, int whiteness) +{ + int ret; + /* some rescaling as done by the qc-usb-messenger code */ + if (whiteness > 0xC000) + whiteness = 0xC000 + (whiteness & 0x3FFF)*8; + + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143D, + (whiteness >> 8) & 0xFF)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143E, + (whiteness >> 16) & 0x03)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); + + return 0; +} + +static int qcm_sensor_init(struct uvd *uvd) +{ + struct qcm *cam = (struct qcm *) uvd->user_data; + int ret; + int i; + + for (i=0; i < sizeof(regval_table)/sizeof(regval_table[0]) ; i++) { + CHECK_RET(ret, qcm_stv_setb(uvd->dev, + regval_table[i].reg, + regval_table[i].val)); + } + + CHECK_RET(ret, qcm_stv_setw(uvd->dev, 0x15c1, + cpu_to_le16(ISOC_PACKET_SIZE))); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x15c3, 0x08)); + CHECK_RET(ret, ret = qcm_stv_setb(uvd->dev, 0x143f, 0x01)); + + CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00)); + + CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); + + CHECK_RET(ret, qcm_sensor_setlevels(uvd, uvd->vpic.brightness, + uvd->vpic.contrast, uvd->vpic.hue, uvd->vpic.colour)); + + CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness)); + CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); + + return 0; +} + +static int qcm_set_camera_size(struct uvd *uvd) +{ + int ret; + struct qcm *cam = (struct qcm *) uvd->user_data; + + CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); + cam->width = camera_sizes[cam->size].width; + cam->height = camera_sizes[cam->size].height; + uvd->videosize = VIDEOSIZE(cam->width, cam->height); + + return 0; +} + +static int qcm_setup_on_open(struct uvd *uvd) +{ + int ret; + + CHECK_RET(ret, qcm_sensor_set_gains(uvd, uvd->vpic.hue, + uvd->vpic.colour, uvd->vpic.contrast)); + CHECK_RET(ret, qcm_sensor_set_exposure(uvd, uvd->vpic.brightness)); + CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness)); + CHECK_RET(ret, qcm_set_camera_size(uvd)); + CHECK_RET(ret, qcm_camera_on(uvd)); + return 0; +} + +static void qcm_adjust_picture(struct uvd *uvd) +{ + int ret; + struct qcm *cam = (struct qcm *) uvd->user_data; + + ret = qcm_camera_off(uvd); + if (ret) { + err("can't turn camera off. abandoning pic adjustment"); + return; + } + + /* if there's been a change in contrast, hue, or + colour then we need to recalculate hsv in order + to update gains */ + if ((cam->contrast != uvd->vpic.contrast) || + (cam->hue != uvd->vpic.hue) || + (cam->colour != uvd->vpic.colour)) { + cam->contrast = uvd->vpic.contrast; + cam->hue = uvd->vpic.hue; + cam->colour = uvd->vpic.colour; + ret = qcm_sensor_set_gains(uvd, cam->hue, cam->colour, + cam->contrast); + if (ret) { + err("can't set gains. abandoning pic adjustment"); + return; + } + } + + if (cam->brightness != uvd->vpic.brightness) { + cam->brightness = uvd->vpic.brightness; + ret = qcm_sensor_set_exposure(uvd, cam->brightness); + if (ret) { + err("can't set exposure. abandoning pic adjustment"); + return; + } + } + + if (cam->whiteness != uvd->vpic.whiteness) { + cam->whiteness = uvd->vpic.whiteness; + qcm_sensor_set_shutter(uvd, cam->whiteness); + if (ret) { + err("can't set shutter. abandoning pic adjustment"); + return; + } + } + + ret = qcm_camera_on(uvd); + if (ret) { + err("can't reenable camera. pic adjustment failed"); + return; + } +} + +static int qcm_process_frame(struct uvd *uvd, u8 *cdata, int framelen) +{ + int datalen; + int totaldata; + struct framehdr { + __be16 id; + __be16 len; + }; + struct framehdr *fhdr; + + totaldata = 0; + while (framelen) { + fhdr = (struct framehdr *) cdata; + datalen = be16_to_cpu(fhdr->len); + framelen -= 4; + cdata += 4; + + if ((fhdr->id) == cpu_to_be16(0x8001)) { + RingQueue_Enqueue(&uvd->dp, marker, 4); + totaldata += 4; + continue; + } + if ((fhdr->id & cpu_to_be16(0xFF00)) == cpu_to_be16(0x0200)) { + RingQueue_Enqueue(&uvd->dp, cdata, datalen); + totaldata += datalen; + } + framelen -= datalen; + cdata += datalen; + } + return totaldata; +} + +static int qcm_compress_iso(struct uvd *uvd, struct urb *dataurb) +{ + int totlen; + int i; + unsigned char *cdata; + + totlen=0; + for (i = 0; i < dataurb->number_of_packets; i++) { + int n = dataurb->iso_frame_desc[i].actual_length; + int st = dataurb->iso_frame_desc[i].status; + + cdata = dataurb->transfer_buffer + + dataurb->iso_frame_desc[i].offset; + + if (st < 0) { + warn("Data error: packet=%d. len=%d. status=%d.", + i, n, st); + uvd->stats.iso_err_count++; + continue; + } + if (!n) + continue; + + totlen += qcm_process_frame(uvd, cdata, n); + } + return totlen; +} + +static void resubmit_urb(struct uvd *uvd, struct urb *urb) +{ + int ret; + + urb->dev = uvd->dev; + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + err("usb_submit_urb error (%d)", ret); +} + +static void qcm_isoc_irq(struct urb *urb, struct pt_regs *regs) +{ + int len; + struct uvd *uvd = urb->context; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return; + + if (!uvd->streaming) + return; + + uvd->stats.urb_count++; + + if (!urb->actual_length) { + resubmit_urb(uvd, urb); + return; + } + + len = qcm_compress_iso(uvd, urb); + resubmit_urb(uvd, urb); + uvd->stats.urb_length = len; + uvd->stats.data_count += len; + if (len) + RingQueue_WakeUpInterruptible(&uvd->dp); +} + +static int qcm_start_data(struct uvd *uvd) +{ + struct qcm *cam = (struct qcm *) uvd->user_data; + int i; + int errflag; + int pktsz; + int err; + + pktsz = uvd->iso_packet_len; + if (!CAMERA_IS_OPERATIONAL(uvd)) { + err("Camera is not operational"); + return -EFAULT; + } + + err = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltActive); + if (err < 0) { + err("usb_set_interface error"); + uvd->last_error = err; + return -EBUSY; + } + + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + int j, k; + struct urb *urb = uvd->sbuf[i].urb; + urb->dev = uvd->dev; + urb->context = uvd; + urb->pipe = usb_rcvisocpipe(uvd->dev, uvd->video_endp); + urb->interval = 1; + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = uvd->sbuf[i].data; + urb->complete = qcm_isoc_irq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC; + for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = pktsz; + } + } + + uvd->streaming = 1; + uvd->curframe = -1; + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + errflag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); + if (errflag) + err ("usb_submit_isoc(%d) ret %d", i, errflag); + } + + CHECK_RET(err, qcm_setup_input_int(cam, uvd)); + CHECK_RET(err, qcm_camera_on(uvd)); + return 0; +} + +static void qcm_stop_data(struct uvd *uvd) +{ + struct qcm *cam = (struct qcm *) uvd->user_data; + int i, j; + int ret; + + if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) + return; + + ret = qcm_camera_off(uvd); + if (ret) + warn("couldn't turn the cam off."); + + uvd->streaming = 0; + + /* Unschedule all of the iso td's */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) + usb_kill_urb(uvd->sbuf[i].urb); + + qcm_stop_int_data(cam); + + if (!uvd->remove_pending) { + /* Set packet size to 0 */ + j = usb_set_interface(uvd->dev, uvd->iface, + uvd->ifaceAltInactive); + if (j < 0) { + err("usb_set_interface() error %d.", j); + uvd->last_error = j; + } + } +} + +static void qcm_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) +{ + struct qcm *cam = (struct qcm *) uvd->user_data; + int x; + struct rgb *rgbL0; + struct rgb *rgbL1; + struct bayL0 *bayL0; + struct bayL1 *bayL1; + int hor,ver,hordel,verdel; + assert(frame != NULL); + + switch (cam->size) { + case SIZE_160X120: + hor = 162; ver = 124; hordel = 1; verdel = 2; + break; + case SIZE_320X240: + default: + hor = 324; ver = 248; hordel = 2; verdel = 4; + break; + } + + if (frame->scanstate == ScanState_Scanning) { + while (RingQueue_GetLength(&uvd->dp) >= + 4 + (hor*verdel + hordel)) { + if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) && + (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 3) == 0xff)) { + frame->curline = 0; + frame->scanstate = ScanState_Lines; + frame->frameState = FrameState_Grabbing; + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4); + /* + * if we're starting, we need to discard the first + * 4 lines of y bayer data + * and the first 2 gr elements of x bayer data + */ + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, + (hor*verdel + hordel)); + break; + } + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); + } + } + + if (frame->scanstate == ScanState_Scanning) + return; + + /* now we can start processing bayer data so long as we have at least + * 2 lines worth of data. this is the simplest demosaicing method that + * I could think of. I use each 2x2 bayer element without interpolation + * to generate 4 rgb pixels. + */ + while ( frame->curline < cam->height && + (RingQueue_GetLength(&uvd->dp) >= hor*2)) { + /* get 2 lines of bayer for demosaicing + * into 2 lines of RGB */ + RingQueue_Dequeue(&uvd->dp, cam->scratch, hor*2); + bayL0 = (struct bayL0 *) cam->scratch; + bayL1 = (struct bayL1 *) (cam->scratch + hor); + /* frame->curline is the rgb y line */ + rgbL0 = (struct rgb *) + ( frame->data + (cam->width*3*frame->curline)); + /* w/2 because we're already doing 2 pixels */ + rgbL1 = rgbL0 + (cam->width/2); + + for (x=0; x < cam->width; x+=2) { + rgbL0->r = bayL0->r; + rgbL0->g = bayL0->g; + rgbL0->b = bayL1->b; + + rgbL0->r2 = bayL0->r; + rgbL0->g2 = bayL1->g; + rgbL0->b2 = bayL1->b; + + rgbL1->r = bayL0->r; + rgbL1->g = bayL1->g; + rgbL1->b = bayL1->b; + + rgbL1->r2 = bayL0->r; + rgbL1->g2 = bayL1->g; + rgbL1->b2 = bayL1->b; + + rgbL0++; + rgbL1++; + + bayL0++; + bayL1++; + } + + frame->seqRead_Length += cam->width*3*2; + frame->curline += 2; + } + /* See if we filled the frame */ + if (frame->curline == cam->height) { + frame->frameState = FrameState_Done_Hold; + frame->curline = 0; + uvd->curframe = -1; + uvd->stats.frame_num++; + } +} + +/* taken from konicawc */ +static int qcm_set_video_mode(struct uvd *uvd, struct video_window *vw) +{ + int ret; + int newsize; + int oldsize; + int x = vw->width; + int y = vw->height; + struct qcm *cam = (struct qcm *) uvd->user_data; + + if (x > 0 && y > 0) { + DEBUG(2, "trying to find size %d,%d", x, y); + for (newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) { + if ((camera_sizes[newsize].width == x) && + (camera_sizes[newsize].height == y)) + break; + } + } else + newsize = cam->size; + + if (newsize > MAX_FRAME_SIZE) { + DEBUG(1, "couldn't find size %d,%d", x, y); + return -EINVAL; + } + + if (newsize == cam->size) { + DEBUG(1, "Nothing to do"); + return 0; + } + + qcm_stop_data(uvd); + + if (cam->size != newsize) { + oldsize = cam->size; + cam->size = newsize; + ret = qcm_set_camera_size(uvd); + if (ret) { + err("Couldn't set camera size, err=%d",ret); + /* restore the original size */ + cam->size = oldsize; + return ret; + } + } + + /* Flush the input queue and clear any current frame in progress */ + + RingQueue_Flush(&uvd->dp); + if (uvd->curframe != -1) { + uvd->frame[uvd->curframe].curline = 0; + uvd->frame[uvd->curframe].seqRead_Length = 0; + uvd->frame[uvd->curframe].seqRead_Index = 0; + } + + CHECK_RET(ret, qcm_start_data(uvd)); + return 0; +} + +static int qcm_configure_video(struct uvd *uvd) +{ + int ret; + memset(&uvd->vpic, 0, sizeof(uvd->vpic)); + memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); + + uvd->vpic.colour = colour; + uvd->vpic.hue = hue; + uvd->vpic.brightness = brightness; + uvd->vpic.contrast = contrast; + uvd->vpic.whiteness = whiteness; + uvd->vpic.depth = 24; + uvd->vpic.palette = VIDEO_PALETTE_RGB24; + + memset(&uvd->vcap, 0, sizeof(uvd->vcap)); + strcpy(uvd->vcap.name, "QCM USB Camera"); + uvd->vcap.type = VID_TYPE_CAPTURE; + uvd->vcap.channels = 1; + uvd->vcap.audios = 0; + + uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width; + uvd->vcap.minheight = camera_sizes[SIZE_160X120].height; + uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width; + uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height; + + memset(&uvd->vchan, 0, sizeof(uvd->vchan)); + uvd->vchan.flags = 0 ; + uvd->vchan.tuners = 0; + uvd->vchan.channel = 0; + uvd->vchan.type = VIDEO_TYPE_CAMERA; + strcpy(uvd->vchan.name, "Camera"); + + CHECK_RET(ret, qcm_sensor_init(uvd)); + return 0; +} + +static int qcm_probe(struct usb_interface *intf, + const struct usb_device_id *devid) +{ + int err; + struct uvd *uvd; + struct usb_device *dev = interface_to_usbdev(intf); + struct qcm *cam; + size_t buffer_size; + unsigned char video_ep; + struct usb_host_interface *interface; + struct usb_endpoint_descriptor *endpoint; + int i,j; + unsigned int ifacenum, ifacenum_inact=0; + __le16 sensor_id; + + /* we don't support multiconfig cams */ + if (dev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + /* first check for the video interface and not + * the audio interface */ + interface = &intf->cur_altsetting[0]; + if ((interface->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) + || (interface->desc.bInterfaceSubClass != + USB_CLASS_VENDOR_SPEC)) + return -ENODEV; + + /* + walk through each endpoint in each setting in the interface + stop when we find the one that's an isochronous IN endpoint. + */ + for (i=0; i < intf->num_altsetting; i++) { + interface = &intf->cur_altsetting[i]; + ifacenum = interface->desc.bAlternateSetting; + /* walk the end points */ + for (j=0; j < interface->desc.bNumEndpoints; j++) { + endpoint = &interface->endpoint[j].desc; + + if ((endpoint->bEndpointAddress & + USB_ENDPOINT_DIR_MASK) != USB_DIR_IN) + continue; /* not input then not good */ + + buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + if (!buffer_size) { + ifacenum_inact = ifacenum; + continue; /* 0 pkt size is not what we want */ + } + + if ((endpoint->bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC) { + video_ep = endpoint->bEndpointAddress; + /* break out of the search */ + goto good_videoep; + } + } + } + /* failed out since nothing useful was found */ + err("No suitable endpoint was found\n"); + return -ENODEV; + +good_videoep: + /* disable isochronous stream before doing anything else */ + err = qcm_stv_setb(dev, STV_ISO_ENABLE, 0); + if (err < 0) { + err("Failed to disable sensor stream"); + return -EIO; + } + + /* + Check that this is the same unknown sensor that is known to work. This + sensor is suspected to be the ST VV6422C001. I'll check the same value + that the qc-usb driver checks. This value is probably not even the + sensor ID since it matches the USB dev ID. Oh well. If it doesn't + match, it's probably a diff sensor so exit and apologize. + */ + err = qcm_stv_getw(dev, CMOS_SENSOR_IDREV, &sensor_id); + if (err < 0) { + err("Couldn't read sensor values. Err %d\n",err); + return err; + } + if (sensor_id != cpu_to_le16(0x08F0)) { + err("Sensor ID %x != %x. Unsupported. Sorry\n", + le16_to_cpu(sensor_id), (0x08F0)); + return -ENODEV; + } + + uvd = usbvideo_AllocateDevice(cams); + if (!uvd) + return -ENOMEM; + + cam = (struct qcm *) uvd->user_data; + + /* buf for doing demosaicing */ + cam->scratch = kmalloc(324*2, GFP_KERNEL); + if (!cam->scratch) /* uvd freed in dereg */ + return -ENOMEM; + + /* yes, if we fail after here, cam->scratch gets freed + by qcm_free_uvd */ + + err = qcm_alloc_int_urb(cam); + if (err < 0) + return err; + + /* yes, if we fail after here, int urb gets freed + by qcm_free_uvd */ + + RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); + cam->width = camera_sizes[size].width; + cam->height = camera_sizes[size].height; + cam->size = size; + + uvd->debug = debug; + uvd->flags = 0; + uvd->dev = dev; + uvd->iface = intf->altsetting->desc.bInterfaceNumber; + uvd->ifaceAltActive = ifacenum; + uvd->ifaceAltInactive = ifacenum_inact; + uvd->video_endp = video_ep; + uvd->iso_packet_len = buffer_size; + uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; + uvd->defaultPalette = VIDEO_PALETTE_RGB24; + uvd->canvas = VIDEOSIZE(320, 240); + uvd->videosize = VIDEOSIZE(cam->width, cam->height); + err = qcm_configure_video(uvd); + if (err) { + err("failed to configure video settings"); + return err; + } + + err = usbvideo_RegisterVideoDevice(uvd); + if (err) { /* the uvd gets freed in Deregister */ + err("usbvideo_RegisterVideoDevice() failed."); + return err; + } + + uvd->max_frame_size = (320 * 240 * 3); + qcm_register_input(cam, dev); + usb_set_intfdata(intf, uvd); + return 0; +} + +static void qcm_free_uvd(struct uvd *uvd) +{ + struct qcm *cam = (struct qcm *) uvd->user_data; + + kfree(cam->scratch); + qcm_unregister_input(cam); + qcm_free_int(cam); +} + +static struct usbvideo_cb qcm_driver = { + .probe = qcm_probe, + .setupOnOpen = qcm_setup_on_open, + .processData = qcm_process_isoc, + .setVideoMode = qcm_set_video_mode, + .startDataPump = qcm_start_data, + .stopDataPump = qcm_stop_data, + .adjustPicture = qcm_adjust_picture, + .userFree = qcm_free_uvd +}; + +static int __init qcm_init(void) +{ + info(DRIVER_DESC " " DRIVER_VERSION); + + return usbvideo_register( + &cams, + MAX_CAMERAS, + sizeof(struct qcm), + "QCM", + &qcm_driver, + THIS_MODULE, + qcm_table); +} + +static void __exit qcm_exit(void) +{ + usbvideo_Deregister(&cams); +} + +module_param(size, int, 0); +MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 320x240"); +module_param(colour, int, 0); +MODULE_PARM_DESC(colour, "Initial colour"); +module_param(hue, int, 0); +MODULE_PARM_DESC(hue, "Initial hue"); +module_param(brightness, int, 0); +MODULE_PARM_DESC(brightness, "Initial brightness"); +module_param(contrast, int, 0); +MODULE_PARM_DESC(contrast, "Initial contrast"); +module_param(whiteness, int, 0); +MODULE_PARM_DESC(whiteness, "Initial whiteness"); + +#ifdef CONFIG_USB_DEBUG +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); +#endif + +module_init(qcm_init); +module_exit(qcm_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jaya Kumar"); +MODULE_DESCRIPTION("QCM USB Camera"); +MODULE_SUPPORTED_DEVICE("QCM USB Camera"); diff --git a/drivers/media/video/usbvideo/quickcam_messenger.h b/drivers/media/video/usbvideo/quickcam_messenger.h new file mode 100644 index 0000000..baab9c0 --- /dev/null +++ b/drivers/media/video/usbvideo/quickcam_messenger.h @@ -0,0 +1,126 @@ +#ifndef quickcam_messenger_h +#define quickcam_messenger_h + +#ifndef CONFIG_INPUT +/* if we're not using input we dummy out these functions */ +#define qcm_register_input(...) +#define qcm_unregister_input(...) +#define qcm_report_buttonstat(...) +#define qcm_setup_input_int(...) 0 +#define qcm_stop_int_data(...) +#define qcm_alloc_int_urb(...) 0 +#define qcm_free_int(...) +#endif + + +#define CHECK_RET(ret, expr) \ + if ((ret = expr) < 0) return ret + +/* Control Registers for the STVV6422 ASIC + * - this define is taken from the qc-usb-messenger code + */ +#define STV_ISO_ENABLE 0x1440 +#define ISOC_PACKET_SIZE 1023 + +/* Chip identification number including revision indicator */ +#define CMOS_SENSOR_IDREV 0xE00A + +struct rgb { + u8 b; + u8 g; + u8 r; + u8 b2; + u8 g2; + u8 r2; +}; + +struct bayL0 { +#ifdef __BIG_ENDIAN + u8 r; + u8 g; +#elif __LITTLE_ENDIAN + u8 g; + u8 r; +#else +#error not byte order defined +#endif +}; + +struct bayL1 { +#ifdef __BIG_ENDIAN + u8 g; + u8 b; +#elif __LITTLE_ENDIAN + u8 b; + u8 g; +#else +#error not byte order defined +#endif +}; + +struct cam_size { + u16 width; + u16 height; + u8 cmd; +}; + +static const struct cam_size camera_sizes[] = { + { 160, 120, 0xf }, + { 320, 240, 0x2 }, +}; + +enum frame_sizes { + SIZE_160X120 = 0, + SIZE_320X240 = 1, +}; + +#define MAX_FRAME_SIZE SIZE_320X240 + +struct qcm { + u16 colour; + u16 hue; + u16 brightness; + u16 contrast; + u16 whiteness; + + u8 size; + int height; + int width; + u8 *scratch; + struct urb *button_urb; + u8 button_sts; + u8 button_sts_buf; + +#ifdef CONFIG_INPUT + struct input_dev *input; + char input_physname[64]; +#endif +}; + +struct regval { + u16 reg; + u8 val; +}; +/* this table is derived from the +qc-usb-messenger code */ +static const struct regval regval_table[] = { + { STV_ISO_ENABLE, 0x00 }, + { 0x1436, 0x00 }, { 0x1432, 0x03 }, + { 0x143a, 0xF9 }, { 0x0509, 0x38 }, + { 0x050a, 0x38 }, { 0x050b, 0x38 }, + { 0x050c, 0x2A }, { 0x050d, 0x01 }, + { 0x1431, 0x00 }, { 0x1433, 0x34 }, + { 0x1438, 0x18 }, { 0x1439, 0x00 }, + { 0x143b, 0x05 }, { 0x143c, 0x00 }, + { 0x143e, 0x01 }, { 0x143d, 0x00 }, + { 0x1442, 0xe2 }, { 0x1500, 0xd0 }, + { 0x1500, 0xd0 }, { 0x1500, 0x50 }, + { 0x1501, 0xaf }, { 0x1502, 0xc2 }, + { 0x1503, 0x45 }, { 0x1505, 0x02 }, + { 0x150e, 0x8e }, { 0x150f, 0x37 }, + { 0x15c0, 0x00 }, +}; + +static const unsigned char marker[] = { 0x00, 0xff, 0x00, 0xFF }; + +#endif /* quickcam_messenger_h */ diff --git a/drivers/media/video/usbvideo/usbvideo.h b/drivers/media/video/usbvideo/usbvideo.h index 3cbf4fc..49dbee5 100644 --- a/drivers/media/video/usbvideo/usbvideo.h +++ b/drivers/media/video/usbvideo/usbvideo.h @@ -18,6 +18,7 @@ #define usbvideo_h #include #include +#include #include #include diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 474a29b..19d3c20 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -32,6 +32,7 @@ #include #include #include #include +#include #include #include diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index d330fa9..f4b3d64 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -59,6 +59,7 @@ #include #include #include #include +#define __OLD_VIDIOC_ /* To allow fixing old calls*/ #include #ifdef CONFIG_KMOD @@ -293,7 +294,10 @@ static const char *v4l2_ioctls[] = { #if 1 [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP", #endif - [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS" + [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS", + [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS", + [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS", + [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS" }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) @@ -331,7 +335,8 @@ #endif [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING", [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING", [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING", - [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING" + [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING", + [_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)] = "VIDIOC_INT_S_CRYSTAL_FREQ" }; #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls) @@ -423,7 +428,9 @@ void v4l_printk_ioctl_arg(char *s,unsign case TUNER_SET_TYPE_ADDR: case TUNER_SET_STANDBY: case TDA9887_SET_CONFIG: +#ifdef __OLD_VIDIOC_ case VIDIOC_OVERLAY_OLD: +#endif case VIDIOC_STREAMOFF: case VIDIOC_G_OUTPUT: case VIDIOC_S_OUTPUT: @@ -439,7 +446,9 @@ void v4l_printk_ioctl_arg(char *s,unsign case VIDIOC_G_AUDIO: case VIDIOC_S_AUDIO: case VIDIOC_ENUMAUDIO: +#ifdef __OLD_VIDIOC_ case VIDIOC_G_AUDIO_OLD: +#endif { struct v4l2_audio *p=arg; @@ -450,7 +459,9 @@ void v4l_printk_ioctl_arg(char *s,unsign case VIDIOC_G_AUDOUT: case VIDIOC_S_AUDOUT: case VIDIOC_ENUMAUDOUT: +#ifdef __OLD_VIDIOC_ case VIDIOC_G_AUDOUT_OLD: +#endif { struct v4l2_audioout *p=arg; printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", s, @@ -478,9 +489,9 @@ void v4l_printk_ioctl_arg(char *s,unsign prt_names(p->memory,v4l2_memory_names), p->m.userptr); printk ("%s: timecode= %02d:%02d:%02d type=%d, " - "flags=0x%08x, frames=%d, userbits=0x%p\n", + "flags=0x%08x, frames=%d, userbits=0x%08x\n", s,tc->hours,tc->minutes,tc->seconds, - tc->type, tc->flags, tc->frames, tc->userbits); + tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits); break; } case VIDIOC_QUERYCAP: @@ -495,12 +506,31 @@ void v4l_printk_ioctl_arg(char *s,unsign } case VIDIOC_G_CTRL: case VIDIOC_S_CTRL: +#ifdef __OLD_VIDIOC_ case VIDIOC_S_CTRL_OLD: +#endif { struct v4l2_control *p=arg; printk ("%s: id=%d, value=%d\n", s, p->id, p->value); break; } + case VIDIOC_G_EXT_CTRLS: + case VIDIOC_S_EXT_CTRLS: + case VIDIOC_TRY_EXT_CTRLS: + { + struct v4l2_ext_controls *p = arg; + int i; + + printk("%s: ctrl_class=%d, count=%d\n", s, p->ctrl_class, p->count); + for (i = 0; i < p->count; i++) { + struct v4l2_ext_control *c = &p->controls[i]; + if (cmd == VIDIOC_G_EXT_CTRLS) + printk("%s: id=%d\n", s, c->id); + else + printk("%s: id=%d, value=%d\n", s, c->id, c->value); + } + break; + } case VIDIOC_G_CROP: case VIDIOC_S_CROP: { @@ -510,7 +540,9 @@ void v4l_printk_ioctl_arg(char *s,unsign break; } case VIDIOC_CROPCAP: +#ifdef __OLD_VIDIOC_ case VIDIOC_CROPCAP_OLD: +#endif { struct v4l2_cropcap *p=arg; /*FIXME: Should also show rect structs */ @@ -667,6 +699,12 @@ void v4l_printk_ioctl_arg(char *s,unsign printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output); break; } + case VIDIOC_INT_S_CRYSTAL_FREQ: + { + struct v4l2_crystal_freq *p=arg; + printk ("%s: freq=%u, flags=0x%x\n", s, p->freq, p->flags); + break; + } case VIDIOC_G_SLICED_VBI_CAP: { struct v4l2_sliced_vbi_cap *p=arg; @@ -696,7 +734,9 @@ void v4l_printk_ioctl_arg(char *s,unsign } case VIDIOC_G_PARM: case VIDIOC_S_PARM: +#ifdef __OLD_VIDIOC_ case VIDIOC_S_PARM_OLD: +#endif { struct v4l2_streamparm *p=arg; printk ("%s: type=%d\n", s, p->type); @@ -915,6 +955,498 @@ void v4l_printk_ioctl_arg(char *s,unsign /* ----------------------------------------------------------------- */ +/* Helper functions for control handling */ + +/* Check for correctness of the ctrl's value based on the data from + struct v4l2_queryctrl and the available menu items. Note that + menu_items may be NULL, in that case it is ignored. */ +int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, + const char **menu_items) +{ + if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED) + return -EINVAL; + if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED) + return -EBUSY; + if (qctrl->type == V4L2_CTRL_TYPE_BUTTON || + qctrl->type == V4L2_CTRL_TYPE_INTEGER64 || + qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) + return 0; + if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum) + return -ERANGE; + if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) { + if (menu_items[ctrl->value] == NULL || + menu_items[ctrl->value][0] == '\0') + return -EINVAL; + } + return 0; +} + +/* Returns NULL or a character pointer array containing the menu for + the given control ID. The pointer array ends with a NULL pointer. + An empty string signifies a menu entry that is invalid. This allows + drivers to disable certain options if it is not supported. */ +const char **v4l2_ctrl_get_menu(u32 id) +{ + static const char *mpeg_audio_sampling_freq[] = { + "44.1 kHz", + "48 kHz", + "32 kHz", + NULL + }; + static const char *mpeg_audio_encoding[] = { + "Layer I", + "Layer II", + "Layer III", + NULL + }; + static const char *mpeg_audio_l1_bitrate[] = { + "32 kbps", + "64 kbps", + "96 kbps", + "128 kbps", + "160 kbps", + "192 kbps", + "224 kbps", + "256 kbps", + "288 kbps", + "320 kbps", + "352 kbps", + "384 kbps", + "416 kbps", + "448 kbps", + NULL + }; + static const char *mpeg_audio_l2_bitrate[] = { + "32 kbps", + "48 kbps", + "56 kbps", + "64 kbps", + "80 kbps", + "96 kbps", + "112 kbps", + "128 kbps", + "160 kbps", + "192 kbps", + "224 kbps", + "256 kbps", + "320 kbps", + "384 kbps", + NULL + }; + static const char *mpeg_audio_l3_bitrate[] = { + "32 kbps", + "40 kbps", + "48 kbps", + "56 kbps", + "64 kbps", + "80 kbps", + "96 kbps", + "112 kbps", + "128 kbps", + "160 kbps", + "192 kbps", + "224 kbps", + "256 kbps", + "320 kbps", + NULL + }; + static const char *mpeg_audio_mode[] = { + "Stereo", + "Joint Stereo", + "Dual", + "Mono", + NULL + }; + static const char *mpeg_audio_mode_extension[] = { + "Bound 4", + "Bound 8", + "Bound 12", + "Bound 16", + NULL + }; + static const char *mpeg_audio_emphasis[] = { + "No Emphasis", + "50/15 us", + "CCITT J17", + NULL + }; + static const char *mpeg_audio_crc[] = { + "No CRC", + "16-bit CRC", + NULL + }; + static const char *mpeg_video_encoding[] = { + "MPEG-1", + "MPEG-2", + NULL + }; + static const char *mpeg_video_aspect[] = { + "1x1", + "4x3", + "16x9", + "2.21x1", + NULL + }; + static const char *mpeg_video_bitrate_mode[] = { + "Variable Bitrate", + "Constant Bitrate", + NULL + }; + static const char *mpeg_stream_type[] = { + "MPEG-2 Program Stream", + "MPEG-2 Transport Stream", + "MPEG-1 System Stream", + "MPEG-2 DVD-compatible Stream", + "MPEG-1 VCD-compatible Stream", + "MPEG-2 SVCD-compatible Stream", + NULL + }; + static const char *mpeg_stream_vbi_fmt[] = { + "No VBI", + "VBI in private packets, IVTV format", + NULL + }; + + switch (id) { + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + return mpeg_audio_sampling_freq; + case V4L2_CID_MPEG_AUDIO_ENCODING: + return mpeg_audio_encoding; + case V4L2_CID_MPEG_AUDIO_L1_BITRATE: + return mpeg_audio_l1_bitrate; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + return mpeg_audio_l2_bitrate; + case V4L2_CID_MPEG_AUDIO_L3_BITRATE: + return mpeg_audio_l3_bitrate; + case V4L2_CID_MPEG_AUDIO_MODE: + return mpeg_audio_mode; + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + return mpeg_audio_mode_extension; + case V4L2_CID_MPEG_AUDIO_EMPHASIS: + return mpeg_audio_emphasis; + case V4L2_CID_MPEG_AUDIO_CRC: + return mpeg_audio_crc; + case V4L2_CID_MPEG_VIDEO_ENCODING: + return mpeg_video_encoding; + case V4L2_CID_MPEG_VIDEO_ASPECT: + return mpeg_video_aspect; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + return mpeg_video_bitrate_mode; + case V4L2_CID_MPEG_STREAM_TYPE: + return mpeg_stream_type; + case V4L2_CID_MPEG_STREAM_VBI_FMT: + return mpeg_stream_vbi_fmt; + default: + return NULL; + } +} + +/* Fill in a struct v4l2_queryctrl */ +int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) +{ + const char *name; + + qctrl->flags = 0; + switch (qctrl->id) { + /* USER controls */ + case V4L2_CID_USER_CLASS: name = "User Controls"; break; + case V4L2_CID_AUDIO_VOLUME: name = "Volume"; break; + case V4L2_CID_AUDIO_MUTE: name = "Mute"; break; + case V4L2_CID_AUDIO_BALANCE: name = "Balance"; break; + case V4L2_CID_AUDIO_BASS: name = "Bass"; break; + case V4L2_CID_AUDIO_TREBLE: name = "Treble"; break; + case V4L2_CID_AUDIO_LOUDNESS: name = "Loudness"; break; + case V4L2_CID_BRIGHTNESS: name = "Brightness"; break; + case V4L2_CID_CONTRAST: name = "Contrast"; break; + case V4L2_CID_SATURATION: name = "Saturation"; break; + case V4L2_CID_HUE: name = "Hue"; break; + + /* MPEG controls */ + case V4L2_CID_MPEG_CLASS: name = "MPEG Encoder Controls"; break; + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: name = "Audio Sampling Frequency"; break; + case V4L2_CID_MPEG_AUDIO_ENCODING: name = "Audio Encoding Layer"; break; + case V4L2_CID_MPEG_AUDIO_L1_BITRATE: name = "Audio Layer I Bitrate"; break; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: name = "Audio Layer II Bitrate"; break; + case V4L2_CID_MPEG_AUDIO_L3_BITRATE: name = "Audio Layer III Bitrate"; break; + case V4L2_CID_MPEG_AUDIO_MODE: name = "Audio Stereo Mode"; break; + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: name = "Audio Stereo Mode Extension"; break; + case V4L2_CID_MPEG_AUDIO_EMPHASIS: name = "Audio Emphasis"; break; + case V4L2_CID_MPEG_AUDIO_CRC: name = "Audio CRC"; break; + case V4L2_CID_MPEG_VIDEO_ENCODING: name = "Video Encoding"; break; + case V4L2_CID_MPEG_VIDEO_ASPECT: name = "Video Aspect"; break; + case V4L2_CID_MPEG_VIDEO_B_FRAMES: name = "Video B Frames"; break; + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: name = "Video GOP Size"; break; + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: name = "Video GOP Closure"; break; + case V4L2_CID_MPEG_VIDEO_PULLDOWN: name = "Video Pulldown"; break; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: name = "Video Bitrate Mode"; break; + case V4L2_CID_MPEG_VIDEO_BITRATE: name = "Video Bitrate"; break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: name = "Video Peak Bitrate"; break; + case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: name = "Video Temporal Decimation"; break; + case V4L2_CID_MPEG_STREAM_TYPE: name = "Stream Type"; break; + case V4L2_CID_MPEG_STREAM_PID_PMT: name = "Stream PMT Program ID"; break; + case V4L2_CID_MPEG_STREAM_PID_AUDIO: name = "Stream Audio Program ID"; break; + case V4L2_CID_MPEG_STREAM_PID_VIDEO: name = "Stream Video Program ID"; break; + case V4L2_CID_MPEG_STREAM_PID_PCR: name = "Stream PCR Program ID"; break; + case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: name = "Stream PES Audio ID"; break; + case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: name = "Stream PES Video ID"; break; + case V4L2_CID_MPEG_STREAM_VBI_FMT: name = "Stream VBI Format"; break; + + default: + return -EINVAL; + } + switch (qctrl->id) { + case V4L2_CID_AUDIO_MUTE: + case V4L2_CID_AUDIO_LOUDNESS: + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + case V4L2_CID_MPEG_VIDEO_PULLDOWN: + qctrl->type = V4L2_CTRL_TYPE_BOOLEAN; + min = 0; + max = step = 1; + break; + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + case V4L2_CID_MPEG_AUDIO_ENCODING: + case V4L2_CID_MPEG_AUDIO_L1_BITRATE: + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + case V4L2_CID_MPEG_AUDIO_L3_BITRATE: + case V4L2_CID_MPEG_AUDIO_MODE: + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + case V4L2_CID_MPEG_AUDIO_EMPHASIS: + case V4L2_CID_MPEG_AUDIO_CRC: + case V4L2_CID_MPEG_VIDEO_ENCODING: + case V4L2_CID_MPEG_VIDEO_ASPECT: + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + case V4L2_CID_MPEG_STREAM_TYPE: + case V4L2_CID_MPEG_STREAM_VBI_FMT: + qctrl->type = V4L2_CTRL_TYPE_MENU; + step = 1; + break; + case V4L2_CID_USER_CLASS: + case V4L2_CID_MPEG_CLASS: + qctrl->type = V4L2_CTRL_TYPE_CTRL_CLASS; + qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + min = max = step = def = 0; + break; + default: + qctrl->type = V4L2_CTRL_TYPE_INTEGER; + break; + } + switch (qctrl->id) { + case V4L2_CID_MPEG_AUDIO_ENCODING: + case V4L2_CID_MPEG_AUDIO_MODE: + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + case V4L2_CID_MPEG_VIDEO_B_FRAMES: + case V4L2_CID_MPEG_STREAM_TYPE: + qctrl->flags |= V4L2_CTRL_FLAG_UPDATE; + break; + case V4L2_CID_AUDIO_VOLUME: + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + case V4L2_CID_BRIGHTNESS: + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + break; + } + qctrl->minimum = min; + qctrl->maximum = max; + qctrl->step = step; + qctrl->default_value = def; + qctrl->reserved[0] = qctrl->reserved[1] = 0; + snprintf(qctrl->name, sizeof(qctrl->name), name); + return 0; +} + +/* Fill in a struct v4l2_queryctrl with standard values based on + the control ID. */ +int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) +{ + switch (qctrl->id) { + /* USER controls */ + case V4L2_CID_USER_CLASS: + case V4L2_CID_MPEG_CLASS: + return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 58880); + case V4L2_CID_AUDIO_MUTE: + case V4L2_CID_AUDIO_LOUDNESS: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); + case V4L2_CID_AUDIO_BALANCE: + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 32768); + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128); + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(qctrl, 0, 127, 1, 64); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(qctrl, -128, 127, 1, 0); + + /* MPEG controls */ + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); + case V4L2_CID_MPEG_AUDIO_ENCODING: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_ENCODING_LAYER_1, + V4L2_MPEG_AUDIO_ENCODING_LAYER_3, 1, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2); + case V4L2_CID_MPEG_AUDIO_L1_BITRATE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_L1_BITRATE_32K, + V4L2_MPEG_AUDIO_L1_BITRATE_448K, 1, + V4L2_MPEG_AUDIO_L1_BITRATE_256K); + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_L2_BITRATE_32K, + V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, + V4L2_MPEG_AUDIO_L2_BITRATE_224K); + case V4L2_CID_MPEG_AUDIO_L3_BITRATE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_L3_BITRATE_32K, + V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1, + V4L2_MPEG_AUDIO_L3_BITRATE_192K); + case V4L2_CID_MPEG_AUDIO_MODE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_MODE_STEREO, + V4L2_MPEG_AUDIO_MODE_MONO, 1, + V4L2_MPEG_AUDIO_MODE_STEREO); + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4); + case V4L2_CID_MPEG_AUDIO_EMPHASIS: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_EMPHASIS_NONE, + V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1, + V4L2_MPEG_AUDIO_EMPHASIS_NONE); + case V4L2_CID_MPEG_AUDIO_CRC: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_CRC_NONE, + V4L2_MPEG_AUDIO_CRC_CRC16, 1, + V4L2_MPEG_AUDIO_CRC_NONE); + case V4L2_CID_MPEG_VIDEO_ENCODING: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_ENCODING_MPEG_1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2); + case V4L2_CID_MPEG_VIDEO_ASPECT: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_ASPECT_1x1, + V4L2_MPEG_VIDEO_ASPECT_221x100, 1, + V4L2_MPEG_VIDEO_ASPECT_4x3); + case V4L2_CID_MPEG_VIDEO_B_FRAMES: + return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2); + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, 12); + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1); + case V4L2_CID_MPEG_VIDEO_PULLDOWN: + return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0); + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); + case V4L2_CID_MPEG_VIDEO_BITRATE: + return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); + case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: + return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); + case V4L2_CID_MPEG_STREAM_TYPE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_STREAM_TYPE_MPEG2_PS, + V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1, + V4L2_MPEG_STREAM_TYPE_MPEG2_PS); + case V4L2_CID_MPEG_STREAM_PID_PMT: + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16); + case V4L2_CID_MPEG_STREAM_PID_AUDIO: + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260); + case V4L2_CID_MPEG_STREAM_PID_VIDEO: + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256); + case V4L2_CID_MPEG_STREAM_PID_PCR: + return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259); + case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: + return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); + case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: + return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0); + case V4L2_CID_MPEG_STREAM_VBI_FMT: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_STREAM_VBI_FMT_NONE, + V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1, + V4L2_MPEG_STREAM_VBI_FMT_NONE); + default: + return -EINVAL; + } +} + +/* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and + the menu. The qctrl pointer may be NULL, in which case it is ignored. */ +int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, + const char **menu_items) +{ + int i; + + if (menu_items == NULL || + (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum))) + return -EINVAL; + for (i = 0; i < qmenu->index && menu_items[i]; i++) ; + if (menu_items[i] == NULL || menu_items[i][0] == '\0') + return -EINVAL; + snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]); + qmenu->reserved = 0; + return 0; +} + +/* ctrl_classes points to an array of u32 pointers, the last element is + a NULL pointer. Each u32 array is a 0-terminated array of control IDs. + Each array must be sorted low to high and belong to the same control + class. The array of u32 pointer must also be sorted, from low class IDs + to high class IDs. + + This function returns the first ID that follows after the given ID. + When no more controls are available 0 is returned. */ +u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) +{ + u32 ctrl_class; + const u32 *pctrl; + + /* if no query is desired, then just return the control ID */ + if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) + return id; + if (ctrl_classes == NULL) + return 0; + id &= V4L2_CTRL_ID_MASK; + ctrl_class = V4L2_CTRL_ID2CLASS(id); + id++; /* select next control */ + /* find first class that matches (or is greater than) the class of + the ID */ + while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) < ctrl_class) + ctrl_classes++; + /* no more classes */ + if (*ctrl_classes == NULL) + return 0; + pctrl = *ctrl_classes; + /* find first ctrl within the class that is >= ID */ + while (*pctrl && *pctrl < id) pctrl++; + if (*pctrl) + return *pctrl; + /* we are at the end of the controls of the current class. */ + /* continue with next class if available */ + ctrl_classes++; + if (*ctrl_classes == NULL) + return 0; + return **ctrl_classes; +} + +/* ----------------------------------------------------------------- */ + EXPORT_SYMBOL(v4l2_video_std_construct); EXPORT_SYMBOL(v4l2_prio_init); @@ -929,6 +1461,13 @@ EXPORT_SYMBOL(v4l2_type_names); EXPORT_SYMBOL(v4l_printk_ioctl); EXPORT_SYMBOL(v4l_printk_ioctl_arg); +EXPORT_SYMBOL(v4l2_ctrl_next); +EXPORT_SYMBOL(v4l2_ctrl_check); +EXPORT_SYMBOL(v4l2_ctrl_get_menu); +EXPORT_SYMBOL(v4l2_ctrl_query_menu); +EXPORT_SYMBOL(v4l2_ctrl_query_fill); +EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); + /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c index caf3e7e..7ee8a53 100644 --- a/drivers/media/video/video-buf-dvb.c +++ b/drivers/media/video/video-buf-dvb.c @@ -135,14 +135,15 @@ static int videobuf_dvb_stop_feed(struct int videobuf_dvb_register(struct videobuf_dvb *dvb, struct module *module, - void *adapter_priv) + void *adapter_priv, + struct device *device) { int result; mutex_init(&dvb->lock); /* register adapter */ - result = dvb_register_adapter(&dvb->adapter, dvb->name, module); + result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device); if (result < 0) { printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", dvb->name, result); diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 5f87dd5..2dfa7f2 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1,20 +1,31 @@ /* - * Video capture interface for Linux + * Video capture interface for Linux version 2 * - * A generic video device interface for the LINUX operating system - * using a set of device structures/vectors for low level operations. + * A generic video device interface for the LINUX operating system + * using a set of device structures/vectors for low level operations. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. * - * Author: Alan Cox, + * Authors: Alan Cox, (version 1) + * Mauro Carvalho Chehab (version 2) * * Fixes: 20000516 Claudio Matsuoka * - Added procfs support */ +#define dbgarg(cmd, fmt, arg...) \ + if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \ + printk (KERN_DEBUG "%s: ", vfd->name); \ + v4l_printk_ioctl(cmd); \ + printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); + +#define dbgarg2(fmt, arg...) \ + if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \ + printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg); + #include #include #include @@ -30,7 +41,13 @@ #include #include #include +#define __OLD_VIDIOC_ /* To allow fixing old calls*/ +#include + +#ifdef CONFIG_VIDEO_V4L1 #include +#endif +#include #define VIDEO_NUM_DEVICES 256 #define VIDEO_NAME "video4linux" @@ -41,7 +58,8 @@ #define VIDEO_NAME "video4l static ssize_t show_name(struct class_device *cd, char *buf) { - struct video_device *vfd = container_of(cd, struct video_device, class_dev); + struct video_device *vfd = container_of(cd, struct video_device, + class_dev); return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name); } @@ -62,7 +80,8 @@ void video_device_release(struct video_d static void video_release(struct class_device *cd) { - struct video_device *vfd = container_of(cd, struct video_device, class_dev); + struct video_device *vfd = container_of(cd, struct video_device, + class_dev); #if 1 /* needed until all drivers are fixed */ @@ -90,7 +109,7 @@ struct video_device* video_devdata(struc } /* - * Open a video device. + * Open a video device - FIXME: Obsoleted */ static int video_open(struct inode *inode, struct file *file) { @@ -130,6 +149,7 @@ static int video_open(struct inode *inod * helper function -- handles userspace copying for ioctl arguments */ +#ifdef __OLD_VIDIOC_ static unsigned int video_fix_command(unsigned int cmd) { @@ -155,7 +175,11 @@ video_fix_command(unsigned int cmd) } return cmd; } +#endif +/* + * Obsolete usercopy function - Should be removed soon + */ int video_usercopy(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, @@ -166,8 +190,15 @@ video_usercopy(struct inode *inode, stru void *mbuf = NULL; void *parg = NULL; int err = -EINVAL; + int is_ext_ctrl; + size_t ctrls_size = 0; + void __user *user_ptr = NULL; +#ifdef __OLD_VIDIOC_ cmd = video_fix_command(cmd); +#endif + is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS || + cmd == VIDIOC_TRY_EXT_CTRLS); /* Copy arguments into temp kernel buffer */ switch (_IOC_DIR(cmd)) { @@ -193,14 +224,43 @@ video_usercopy(struct inode *inode, stru goto out; break; } + if (is_ext_ctrl) { + struct v4l2_ext_controls *p = parg; + + /* In case of an error, tell the caller that it wasn't + a specific control that caused it. */ + p->error_idx = p->count; + user_ptr = (void __user *)p->controls; + if (p->count) { + ctrls_size = sizeof(struct v4l2_ext_control) * p->count; + /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */ + mbuf = kmalloc(ctrls_size, GFP_KERNEL); + err = -ENOMEM; + if (NULL == mbuf) + goto out_ext_ctrl; + err = -EFAULT; + if (copy_from_user(mbuf, user_ptr, ctrls_size)) + goto out_ext_ctrl; + p->controls = mbuf; + } + } /* call driver */ err = func(inode, file, cmd, parg); if (err == -ENOIOCTLCMD) err = -EINVAL; + if (is_ext_ctrl) { + struct v4l2_ext_controls *p = parg; + + p->controls = (void *)user_ptr; + if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size)) + err = -EFAULT; + goto out_ext_ctrl; + } if (err < 0) goto out; +out_ext_ctrl: /* Copy results into user buffer */ switch (_IOC_DIR(cmd)) { @@ -218,6 +278,7 @@ out: /* * open/release helper functions -- handle exclusive opens + * Should be removed soon */ int video_exclusive_open(struct inode *inode, struct file *file) { @@ -242,6 +303,1184 @@ int video_exclusive_release(struct inode return 0; } +static char *v4l2_memory_names[] = { + [V4L2_MEMORY_MMAP] = "mmap", + [V4L2_MEMORY_USERPTR] = "userptr", + [V4L2_MEMORY_OVERLAY] = "overlay", +}; + + +/* FIXME: Those stuff are replicated also on v4l2-common.c */ +static char *v4l2_type_names_FIXME[] = { + [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", + [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", + [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", + [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", + [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", + [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out", + [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-capture", + [V4L2_BUF_TYPE_PRIVATE] = "private", +}; + +static char *v4l2_field_names_FIXME[] = { + [V4L2_FIELD_ANY] = "any", + [V4L2_FIELD_NONE] = "none", + [V4L2_FIELD_TOP] = "top", + [V4L2_FIELD_BOTTOM] = "bottom", + [V4L2_FIELD_INTERLACED] = "interlaced", + [V4L2_FIELD_SEQ_TB] = "seq-tb", + [V4L2_FIELD_SEQ_BT] = "seq-bt", + [V4L2_FIELD_ALTERNATE] = "alternate", +}; + +#define prt_names(a,arr) (((a)>=0)&&((a)timecode; + + dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " + "bytesused=%d, flags=0x%08d, " + "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n", + (p->timestamp.tv_sec/3600), + (int)(p->timestamp.tv_sec/60)%60, + (int)(p->timestamp.tv_sec%60), + p->timestamp.tv_usec, + p->index, + prt_names(p->type,v4l2_type_names_FIXME), + p->bytesused,p->flags, + p->field,p->sequence, + prt_names(p->memory,v4l2_memory_names), + p->m.userptr); + dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " + "flags=0x%08d, frames=%d, userbits=0x%08x\n", + tc->hours,tc->minutes,tc->seconds, + tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits); +} + +static inline void dbgrect(struct video_device *vfd, char *s, + struct v4l2_rect *r) +{ + dbgarg2 ("%sRect start at %dx%d, size= %dx%d\n", s, r->left, r->top, + r->width, r->height); +}; + +static inline void v4l_print_pix_fmt (struct video_device *vfd, + struct v4l2_pix_format *fmt) +{ + dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, " + "bytesperline=%d sizeimage=%d, colorspace=%d\n", + fmt->width,fmt->height,fmt->pixelformat, + prt_names(fmt->field,v4l2_field_names_FIXME), + fmt->bytesperline,fmt->sizeimage,fmt->colorspace); +}; + + +static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type) +{ + switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (vfd->vidioc_try_fmt_cap) + return (0); + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (vfd->vidioc_try_fmt_overlay) + return (0); + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (vfd->vidioc_try_fmt_vbi) + return (0); + break; + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + if (vfd->vidioc_try_fmt_vbi_output) + return (0); + break; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (vfd->vidioc_try_fmt_vbi_capture) + return (0); + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (vfd->vidioc_try_fmt_video_output) + return (0); + break; + case V4L2_BUF_TYPE_VBI_OUTPUT: + if (vfd->vidioc_try_fmt_vbi_output) + return (0); + break; + case V4L2_BUF_TYPE_PRIVATE: + if (vfd->vidioc_try_fmt_type_private) + return (0); + break; + } + return (-EINVAL); +} + +static int __video_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct video_device *vfd = video_devdata(file); + void *fh = file->private_data; + int ret = -EINVAL; + + if ( (vfd->debug & V4L2_DEBUG_IOCTL) && + !(vfd->debug | V4L2_DEBUG_IOCTL_ARG)) { + v4l_print_ioctl(vfd->name, cmd); + } + + switch(cmd) { + /* --- capabilities ------------------------------------------ */ + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = (struct v4l2_capability*)arg; + memset(cap, 0, sizeof(*cap)); + + if (!vfd->vidioc_querycap) + break; + + ret=vfd->vidioc_querycap(file, fh, cap); + if (!ret) + dbgarg (cmd, "driver=%s, card=%s, bus=%s, " + "version=0x%08x, " + "capabilities=0x%08x\n", + cap->driver,cap->card,cap->bus_info, + cap->version, + cap->capabilities); + break; + } + + /* --- priority ------------------------------------------ */ + case VIDIOC_G_PRIORITY: + { + enum v4l2_priority *p=arg; + + if (!vfd->vidioc_g_priority) + break; + ret=vfd->vidioc_g_priority(file, fh, p); + if (!ret) + dbgarg(cmd, "priority is %d\n", *p); + break; + } + case VIDIOC_S_PRIORITY: + { + enum v4l2_priority *p=arg; + + if (!vfd->vidioc_s_priority) + break; + dbgarg(cmd, "setting priority to %d\n", *p); + ret=vfd->vidioc_s_priority(file, fh, *p); + break; + } + + /* --- capture ioctls ---------------------------------------- */ + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *f = arg; + enum v4l2_buf_type type; + unsigned int index; + + index = f->index; + type = f->type; + memset(f,0,sizeof(*f)); + f->index = index; + f->type = type; + + switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (vfd->vidioc_enum_fmt_cap) + ret=vfd->vidioc_enum_fmt_cap(file, fh, f); + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (vfd->vidioc_enum_fmt_overlay) + ret=vfd->vidioc_enum_fmt_overlay(file, fh, f); + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (vfd->vidioc_enum_fmt_vbi) + ret=vfd->vidioc_enum_fmt_vbi(file, fh, f); + break; + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + if (vfd->vidioc_enum_fmt_vbi_output) + ret=vfd->vidioc_enum_fmt_vbi_output(file, + fh, f); + break; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (vfd->vidioc_enum_fmt_vbi_capture) + ret=vfd->vidioc_enum_fmt_vbi_capture(file, + fh, f); + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (vfd->vidioc_enum_fmt_video_output) + ret=vfd->vidioc_enum_fmt_video_output(file, + fh, f); + break; + case V4L2_BUF_TYPE_VBI_OUTPUT: + if (vfd->vidioc_enum_fmt_vbi_output) + ret=vfd->vidioc_enum_fmt_vbi_output(file, + fh, f); + break; + case V4L2_BUF_TYPE_PRIVATE: + if (vfd->vidioc_enum_fmt_type_private) + ret=vfd->vidioc_enum_fmt_type_private(file, + fh, f); + break; + } + if (!ret) + dbgarg (cmd, "index=%d, type=%d, flags=%d, " + "description=%s," + " pixelformat=0x%8x\n", + f->index, f->type, f->flags, + f->description, + f->pixelformat); + + break; + } + case VIDIOC_G_FMT: + { + struct v4l2_format *f = (struct v4l2_format *)arg; + enum v4l2_buf_type type=f->type; + + memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); + f->type=type; + + /* FIXME: Should be one dump per type */ + dbgarg (cmd, "type=%s\n", prt_names(type, + v4l2_type_names_FIXME)); + + switch (type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (vfd->vidioc_g_fmt_cap) + ret=vfd->vidioc_g_fmt_cap(file, fh, f); + if (!ret) + v4l_print_pix_fmt(vfd,&f->fmt.pix); + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (vfd->vidioc_g_fmt_overlay) + ret=vfd->vidioc_g_fmt_overlay(file, fh, f); + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (vfd->vidioc_g_fmt_vbi) + ret=vfd->vidioc_g_fmt_vbi(file, fh, f); + break; + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + if (vfd->vidioc_g_fmt_vbi_output) + ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f); + break; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (vfd->vidioc_g_fmt_vbi_capture) + ret=vfd->vidioc_g_fmt_vbi_capture(file, fh, f); + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (vfd->vidioc_g_fmt_video_output) + ret=vfd->vidioc_g_fmt_video_output(file, + fh, f); + break; + case V4L2_BUF_TYPE_VBI_OUTPUT: + if (vfd->vidioc_g_fmt_vbi_output) + ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f); + break; + case V4L2_BUF_TYPE_PRIVATE: + if (vfd->vidioc_g_fmt_type_private) + ret=vfd->vidioc_g_fmt_type_private(file, + fh, f); + break; + } + + break; + } + case VIDIOC_S_FMT: + { + struct v4l2_format *f = (struct v4l2_format *)arg; + + /* FIXME: Should be one dump per type */ + dbgarg (cmd, "type=%s\n", prt_names(f->type, + v4l2_type_names_FIXME)); + + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + v4l_print_pix_fmt(vfd,&f->fmt.pix); + if (vfd->vidioc_s_fmt_cap) + ret=vfd->vidioc_s_fmt_cap(file, fh, f); + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (vfd->vidioc_s_fmt_overlay) + ret=vfd->vidioc_s_fmt_overlay(file, fh, f); + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (vfd->vidioc_s_fmt_vbi) + ret=vfd->vidioc_s_fmt_vbi(file, fh, f); + break; + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + if (vfd->vidioc_s_fmt_vbi_output) + ret=vfd->vidioc_s_fmt_vbi_output(file, fh, f); + break; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (vfd->vidioc_s_fmt_vbi_capture) + ret=vfd->vidioc_s_fmt_vbi_capture(file, fh, f); + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (vfd->vidioc_s_fmt_video_output) + ret=vfd->vidioc_s_fmt_video_output(file, + fh, f); + break; + case V4L2_BUF_TYPE_VBI_OUTPUT: + if (vfd->vidioc_s_fmt_vbi_output) + ret=vfd->vidioc_s_fmt_vbi_output(file, + fh, f); + break; + case V4L2_BUF_TYPE_PRIVATE: + if (vfd->vidioc_s_fmt_type_private) + ret=vfd->vidioc_s_fmt_type_private(file, + fh, f); + break; + } + break; + } + case VIDIOC_TRY_FMT: + { + struct v4l2_format *f = (struct v4l2_format *)arg; + + /* FIXME: Should be one dump per type */ + dbgarg (cmd, "type=%s\n", prt_names(f->type, + v4l2_type_names_FIXME)); + switch (f->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (vfd->vidioc_try_fmt_cap) + ret=vfd->vidioc_try_fmt_cap(file, fh, f); + if (!ret) + v4l_print_pix_fmt(vfd,&f->fmt.pix); + break; + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (vfd->vidioc_try_fmt_overlay) + ret=vfd->vidioc_try_fmt_overlay(file, fh, f); + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (vfd->vidioc_try_fmt_vbi) + ret=vfd->vidioc_try_fmt_vbi(file, fh, f); + break; + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + if (vfd->vidioc_try_fmt_vbi_output) + ret=vfd->vidioc_try_fmt_vbi_output(file, + fh, f); + break; + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (vfd->vidioc_try_fmt_vbi_capture) + ret=vfd->vidioc_try_fmt_vbi_capture(file, + fh, f); + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (vfd->vidioc_try_fmt_video_output) + ret=vfd->vidioc_try_fmt_video_output(file, + fh, f); + break; + case V4L2_BUF_TYPE_VBI_OUTPUT: + if (vfd->vidioc_try_fmt_vbi_output) + ret=vfd->vidioc_try_fmt_vbi_output(file, + fh, f); + break; + case V4L2_BUF_TYPE_PRIVATE: + if (vfd->vidioc_try_fmt_type_private) + ret=vfd->vidioc_try_fmt_type_private(file, + fh, f); + break; + } + + break; + } + /* FIXME: Those buf reqs could be handled here, + with some changes on videobuf to allow its header to be included at + videodev2.h or being merged at videodev2. + */ + case VIDIOC_REQBUFS: + { + struct v4l2_requestbuffers *p=arg; + + if (!vfd->vidioc_reqbufs) + break; + ret = check_fmt (vfd, p->type); + if (ret) + break; + + ret=vfd->vidioc_reqbufs(file, fh, p); + dbgarg (cmd, "count=%d, type=%s, memory=%s\n", + p->count, + prt_names(p->type,v4l2_type_names_FIXME), + prt_names(p->memory,v4l2_memory_names)); + break; + } + case VIDIOC_QUERYBUF: + { + struct v4l2_buffer *p=arg; + + if (!vfd->vidioc_querybuf) + break; + ret = check_fmt (vfd, p->type); + if (ret) + break; + + ret=vfd->vidioc_querybuf(file, fh, p); + if (!ret) + dbgbuf(cmd,vfd,p); + break; + } + case VIDIOC_QBUF: + { + struct v4l2_buffer *p=arg; + + if (!vfd->vidioc_qbuf) + break; + ret = check_fmt (vfd, p->type); + if (ret) + break; + + ret=vfd->vidioc_qbuf(file, fh, p); + if (!ret) + dbgbuf(cmd,vfd,p); + break; + } + case VIDIOC_DQBUF: + { + struct v4l2_buffer *p=arg; + if (!vfd->vidioc_qbuf) + break; + ret = check_fmt (vfd, p->type); + if (ret) + break; + + ret=vfd->vidioc_qbuf(file, fh, p); + if (!ret) + dbgbuf(cmd,vfd,p); + break; + } + case VIDIOC_OVERLAY: + { + int *i = arg; + + if (!vfd->vidioc_overlay) + break; + dbgarg (cmd, "value=%d\n",*i); + ret=vfd->vidioc_overlay(file, fh, *i); + break; + } +#ifdef HAVE_V4L1 + /* --- streaming capture ------------------------------------- */ + case VIDIOCGMBUF: + { + struct video_mbuf *p=arg; + + memset(p,0,sizeof(p)); + + if (!vfd->vidiocgmbuf) + break; + ret=vfd->vidiocgmbuf(file, fh, p); + if (!ret) + dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n", + p->size, p->frames, + (unsigned long)p->offsets); + break; + } +#endif + case VIDIOC_G_FBUF: + { + struct v4l2_framebuffer *p=arg; + if (!vfd->vidioc_g_fbuf) + break; + ret=vfd->vidioc_g_fbuf(file, fh, arg); + if (!ret) { + dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n", + p->capability,p->flags, + (unsigned long)p->base); + v4l_print_pix_fmt (vfd, &p->fmt); + } + break; + } + case VIDIOC_S_FBUF: + { + struct v4l2_framebuffer *p=arg; + if (!vfd->vidioc_s_fbuf) + break; + + dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n", + p->capability,p->flags,(unsigned long)p->base); + v4l_print_pix_fmt (vfd, &p->fmt); + ret=vfd->vidioc_s_fbuf(file, fh, arg); + + break; + } + case VIDIOC_STREAMON: + { + enum v4l2_buf_type i = *(int *)arg; + if (!vfd->vidioc_streamon) + break; + dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME)); + ret=vfd->vidioc_streamon(file, fh,i); + break; + } + case VIDIOC_STREAMOFF: + { + enum v4l2_buf_type i = *(int *)arg; + + if (!vfd->vidioc_streamoff) + break; + dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME)); + ret=vfd->vidioc_streamoff(file, fh, i); + break; + } + /* ---------- tv norms ---------- */ + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *p = arg; + unsigned int index = p->index; + + if (!vfd->tvnormsize) { + printk (KERN_WARNING "%s: no TV norms defined!\n", + vfd->name); + break; + } + + if (index<=0 || index >= vfd->tvnormsize) { + ret=-EINVAL; + break; + } + v4l2_video_std_construct(p, vfd->tvnorms[p->index].id, + vfd->tvnorms[p->index].name); + p->index = index; + + dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " + "framelines=%d\n", p->index, + (unsigned long long)p->id, p->name, + p->frameperiod.numerator, + p->frameperiod.denominator, + p->framelines); + + ret=0; + break; + } + case VIDIOC_G_STD: + { + v4l2_std_id *id = arg; + + *id = vfd->current_norm; + + dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); + + ret=0; + break; + } + case VIDIOC_S_STD: + { + v4l2_std_id *id = arg; + unsigned int i; + + if (!vfd->tvnormsize) { + printk (KERN_WARNING "%s: no TV norms defined!\n", + vfd->name); + break; + } + + dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); + + /* First search for exact match */ + for (i = 0; i < vfd->tvnormsize; i++) + if (*id == vfd->tvnorms[i].id) + break; + /* Then for a generic video std that contains desired std */ + if (i == vfd->tvnormsize) + for (i = 0; i < vfd->tvnormsize; i++) + if (*id & vfd->tvnorms[i].id) + break; + if (i == vfd->tvnormsize) { + break; + } + + /* Calls the specific handler */ + if (vfd->vidioc_s_std) + ret=vfd->vidioc_s_std(file, fh, i); + else + ret=-EINVAL; + + /* Updates standard information */ + if (!ret) + vfd->current_norm=*id; + + break; + } + case VIDIOC_QUERYSTD: + { + v4l2_std_id *p=arg; + + if (!vfd->vidioc_querystd) + break; + ret=vfd->vidioc_querystd(file, fh, arg); + if (!ret) + dbgarg (cmd, "detected std=%Lu\n", + (unsigned long long)*p); + break; + } + /* ------ input switching ---------- */ + /* FIXME: Inputs can be handled inside videodev2 */ + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *p=arg; + int i=p->index; + + if (!vfd->vidioc_enum_input) + break; + memset(p, 0, sizeof(*p)); + p->index=i; + + ret=vfd->vidioc_enum_input(file, fh, p); + if (!ret) + dbgarg (cmd, "index=%d, name=%s, type=%d, " + "audioset=%d, " + "tuner=%d, std=%Ld, status=%d\n", + p->index,p->name,p->type,p->audioset, + p->tuner, + (unsigned long long)p->std, + p->status); + break; + } + case VIDIOC_G_INPUT: + { + unsigned int *i = arg; + + if (!vfd->vidioc_g_input) + break; + ret=vfd->vidioc_g_input(file, fh, i); + if (!ret) + dbgarg (cmd, "value=%d\n",*i); + break; + } + case VIDIOC_S_INPUT: + { + unsigned int *i = arg; + + if (!vfd->vidioc_s_input) + break; + dbgarg (cmd, "value=%d\n",*i); + ret=vfd->vidioc_s_input(file, fh, *i); + break; + } + + /* ------ output switching ---------- */ + case VIDIOC_G_OUTPUT: + { + unsigned int *i = arg; + + if (!vfd->vidioc_g_output) + break; + ret=vfd->vidioc_g_output(file, fh, i); + if (!ret) + dbgarg (cmd, "value=%d\n",*i); + break; + } + case VIDIOC_S_OUTPUT: + { + unsigned int *i = arg; + + if (!vfd->vidioc_s_output) + break; + dbgarg (cmd, "value=%d\n",*i); + ret=vfd->vidioc_s_output(file, fh, *i); + break; + } + + /* --- controls ---------------------------------------------- */ + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *p=arg; + + if (!vfd->vidioc_queryctrl) + break; + ret=vfd->vidioc_queryctrl(file, fh, p); + + if (!ret) + dbgarg (cmd, "id=%d, type=%d, name=%s, " + "min/max=%d/%d," + " step=%d, default=%d, flags=0x%08x\n", + p->id,p->type,p->name,p->minimum, + p->maximum,p->step,p->default_value, + p->flags); + break; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *p = arg; + + if (!vfd->vidioc_g_ctrl) + break; + dbgarg(cmd, "Enum for index=%d\n", p->id); + + ret=vfd->vidioc_g_ctrl(file, fh, p); + if (!ret) + dbgarg2 ( "id=%d, value=%d\n", p->id, p->value); + break; + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *p = arg; + + if (!vfd->vidioc_s_ctrl) + break; + dbgarg (cmd, "id=%d, value=%d\n", p->id, p->value); + + ret=vfd->vidioc_s_ctrl(file, fh, p); + break; + } + case VIDIOC_G_EXT_CTRLS: + { + struct v4l2_ext_controls *p = arg; + + if (vfd->vidioc_g_ext_ctrls) { + dbgarg(cmd, "count=%d\n", p->count); + + ret=vfd->vidioc_g_ext_ctrls(file, fh, p); + } + break; + } + case VIDIOC_S_EXT_CTRLS: + { + struct v4l2_ext_controls *p = arg; + + if (vfd->vidioc_s_ext_ctrls) { + dbgarg(cmd, "count=%d\n", p->count); + + ret=vfd->vidioc_s_ext_ctrls(file, fh, p); + } + break; + } + case VIDIOC_TRY_EXT_CTRLS: + { + struct v4l2_ext_controls *p = arg; + + if (vfd->vidioc_try_ext_ctrls) { + dbgarg(cmd, "count=%d\n", p->count); + + ret=vfd->vidioc_try_ext_ctrls(file, fh, p); + } + break; + } + case VIDIOC_QUERYMENU: + { + struct v4l2_querymenu *p=arg; + if (!vfd->vidioc_querymenu) + break; + ret=vfd->vidioc_querymenu(file, fh, p); + if (!ret) + dbgarg (cmd, "id=%d, index=%d, name=%s\n", + p->id,p->index,p->name); + break; + } + /* --- audio ---------------------------------------------- */ + case VIDIOC_ENUMAUDIO: + { + struct v4l2_audio *p=arg; + + if (!vfd->vidioc_enumaudio) + break; + dbgarg(cmd, "Enum for index=%d\n", p->index); + ret=vfd->vidioc_enumaudio(file, fh, p); + if (!ret) + dbgarg2("index=%d, name=%s, capability=%d, " + "mode=%d\n",p->index,p->name, + p->capability, p->mode); + break; + } + case VIDIOC_G_AUDIO: + { + struct v4l2_audio *p=arg; + + if (!vfd->vidioc_g_audio) + break; + dbgarg(cmd, "Get for index=%d\n", p->index); + ret=vfd->vidioc_g_audio(file, fh, p); + if (!ret) + dbgarg2("index=%d, name=%s, capability=%d, " + "mode=%d\n",p->index, + p->name,p->capability, p->mode); + break; + } + case VIDIOC_S_AUDIO: + { + struct v4l2_audio *p=arg; + + if (!vfd->vidioc_s_audio) + break; + dbgarg(cmd, "index=%d, name=%s, capability=%d, " + "mode=%d\n", p->index, p->name, + p->capability, p->mode); + ret=vfd->vidioc_s_audio(file, fh, p); + break; + } + case VIDIOC_ENUMAUDOUT: + { + struct v4l2_audioout *p=arg; + + if (!vfd->vidioc_enumaudout) + break; + dbgarg(cmd, "Enum for index=%d\n", p->index); + ret=vfd->vidioc_enumaudout(file, fh, p); + if (!ret) + dbgarg2("index=%d, name=%s, capability=%d, " + "mode=%d\n", p->index, p->name, + p->capability,p->mode); + break; + } + case VIDIOC_G_AUDOUT: + { + struct v4l2_audioout *p=arg; + + if (!vfd->vidioc_g_audout) + break; + dbgarg(cmd, "Enum for index=%d\n", p->index); + ret=vfd->vidioc_g_audout(file, fh, p); + if (!ret) + dbgarg2("index=%d, name=%s, capability=%d, " + "mode=%d\n", p->index, p->name, + p->capability,p->mode); + break; + } + case VIDIOC_S_AUDOUT: + { + struct v4l2_audioout *p=arg; + + if (!vfd->vidioc_s_audout) + break; + dbgarg(cmd, "index=%d, name=%s, capability=%d, " + "mode=%d\n", p->index, p->name, + p->capability,p->mode); + + ret=vfd->vidioc_s_audout(file, fh, p); + break; + } + case VIDIOC_G_MODULATOR: + { + struct v4l2_modulator *p=arg; + if (!vfd->vidioc_g_modulator) + break; + ret=vfd->vidioc_g_modulator(file, fh, p); + if (!ret) + dbgarg(cmd, "index=%d, name=%s, " + "capability=%d, rangelow=%d," + " rangehigh=%d, txsubchans=%d\n", + p->index, p->name,p->capability, + p->rangelow, p->rangehigh, + p->txsubchans); + break; + } + case VIDIOC_S_MODULATOR: + { + struct v4l2_modulator *p=arg; + if (!vfd->vidioc_s_modulator) + break; + dbgarg(cmd, "index=%d, name=%s, capability=%d, " + "rangelow=%d, rangehigh=%d, txsubchans=%d\n", + p->index, p->name,p->capability,p->rangelow, + p->rangehigh,p->txsubchans); + ret=vfd->vidioc_s_modulator(file, fh, p); + break; + } + case VIDIOC_G_CROP: + { + struct v4l2_crop *p=arg; + if (!vfd->vidioc_g_crop) + break; + ret=vfd->vidioc_g_crop(file, fh, p); + if (!ret) { + dbgarg(cmd, "type=%d\n", p->type); + dbgrect(vfd, "", &p->c); + } + break; + } + case VIDIOC_S_CROP: + { + struct v4l2_crop *p=arg; + if (!vfd->vidioc_s_crop) + break; + dbgarg(cmd, "type=%d\n", p->type); + dbgrect(vfd, "", &p->c); + ret=vfd->vidioc_s_crop(file, fh, p); + break; + } + case VIDIOC_CROPCAP: + { + struct v4l2_cropcap *p=arg; + /*FIXME: Should also show v4l2_fract pixelaspect */ + if (!vfd->vidioc_cropcap) + break; + dbgarg(cmd, "type=%d\n", p->type); + dbgrect(vfd, "bounds ", &p->bounds); + dbgrect(vfd, "defrect ", &p->defrect); + ret=vfd->vidioc_cropcap(file, fh, p); + break; + } + case VIDIOC_G_MPEGCOMP: + { + struct v4l2_mpeg_compression *p=arg; + + /*FIXME: Several fields not shown */ + if (!vfd->vidioc_g_mpegcomp) + break; + ret=vfd->vidioc_g_mpegcomp(file, fh, p); + if (!ret) + dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d," + " ts_pid_video=%d, ts_pid_pcr=%d, " + "ps_size=%d, au_sample_rate=%d, " + "au_pesid=%c, vi_frame_rate=%d, " + "vi_frames_per_gop=%d, " + "vi_bframes_count=%d, vi_pesid=%c\n", + p->ts_pid_pmt,p->ts_pid_audio, + p->ts_pid_video,p->ts_pid_pcr, + p->ps_size, p->au_sample_rate, + p->au_pesid, p->vi_frame_rate, + p->vi_frames_per_gop, + p->vi_bframes_count, p->vi_pesid); + break; + } + case VIDIOC_S_MPEGCOMP: + { + struct v4l2_mpeg_compression *p=arg; + /*FIXME: Several fields not shown */ + if (!vfd->vidioc_s_mpegcomp) + break; + dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d, " + "ts_pid_video=%d, ts_pid_pcr=%d, ps_size=%d, " + "au_sample_rate=%d, au_pesid=%c, " + "vi_frame_rate=%d, vi_frames_per_gop=%d, " + "vi_bframes_count=%d, vi_pesid=%c\n", + p->ts_pid_pmt,p->ts_pid_audio, p->ts_pid_video, + p->ts_pid_pcr, p->ps_size, p->au_sample_rate, + p->au_pesid, p->vi_frame_rate, + p->vi_frames_per_gop, p->vi_bframes_count, + p->vi_pesid); + ret=vfd->vidioc_s_mpegcomp(file, fh, p); + break; + } + case VIDIOC_G_JPEGCOMP: + { + struct v4l2_jpegcompression *p=arg; + if (!vfd->vidioc_g_jpegcomp) + break; + ret=vfd->vidioc_g_jpegcomp(file, fh, p); + if (!ret) + dbgarg (cmd, "quality=%d, APPn=%d, " + "APP_len=%d, COM_len=%d, " + "jpeg_markers=%d\n", + p->quality,p->APPn,p->APP_len, + p->COM_len,p->jpeg_markers); + break; + } + case VIDIOC_S_JPEGCOMP: + { + struct v4l2_jpegcompression *p=arg; + if (!vfd->vidioc_g_jpegcomp) + break; + dbgarg (cmd, "quality=%d, APPn=%d, APP_len=%d, " + "COM_len=%d, jpeg_markers=%d\n", + p->quality,p->APPn,p->APP_len, + p->COM_len,p->jpeg_markers); + ret=vfd->vidioc_s_jpegcomp(file, fh, p); + break; + } + case VIDIOC_G_PARM: + { + struct v4l2_streamparm *p=arg; + if (!vfd->vidioc_g_parm) + break; + ret=vfd->vidioc_g_parm(file, fh, p); + dbgarg (cmd, "type=%d\n", p->type); + break; + } + case VIDIOC_S_PARM: + { + struct v4l2_streamparm *p=arg; + if (!vfd->vidioc_s_parm) + break; + dbgarg (cmd, "type=%d\n", p->type); + ret=vfd->vidioc_s_parm(file, fh, p); + break; + } + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *p=arg; + if (!vfd->vidioc_g_tuner) + break; + ret=vfd->vidioc_g_tuner(file, fh, p); + if (!ret) + dbgarg (cmd, "index=%d, name=%s, type=%d, " + "capability=%d, rangelow=%d, " + "rangehigh=%d, signal=%d, afc=%d, " + "rxsubchans=%d, audmode=%d\n", + p->index, p->name, p->type, + p->capability, p->rangelow, + p->rangehigh, p->rxsubchans, + p->audmode, p->signal, p->afc); + break; + } + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *p=arg; + if (!vfd->vidioc_s_tuner) + break; + dbgarg (cmd, "index=%d, name=%s, type=%d, " + "capability=%d, rangelow=%d, rangehigh=%d, " + "signal=%d, afc=%d, rxsubchans=%d, " + "audmode=%d\n",p->index, p->name, p->type, + p->capability, p->rangelow,p->rangehigh, + p->rxsubchans, p->audmode, p->signal, + p->afc); + ret=vfd->vidioc_s_tuner(file, fh, p); + break; + } + case VIDIOC_G_FREQUENCY: + { + struct v4l2_frequency *p=arg; + if (!vfd->vidioc_g_frequency) + break; + ret=vfd->vidioc_g_frequency(file, fh, p); + if (!ret) + dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", + p->tuner,p->type,p->frequency); + break; + } + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *p=arg; + if (!vfd->vidioc_s_frequency) + break; + dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", + p->tuner,p->type,p->frequency); + ret=vfd->vidioc_s_frequency(file, fh, p); + break; + } + case VIDIOC_G_SLICED_VBI_CAP: + { + struct v4l2_sliced_vbi_cap *p=arg; + if (!vfd->vidioc_g_sliced_vbi_cap) + break; + ret=vfd->vidioc_g_sliced_vbi_cap(file, fh, p); + if (!ret) + dbgarg (cmd, "service_set=%d\n", p->service_set); + break; + } + case VIDIOC_LOG_STATUS: + { + if (!vfd->vidioc_log_status) + break; + ret=vfd->vidioc_log_status(file, fh); + break; + } + + /* --- Others --------------------------------------------- */ + + default: + ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl); + } + + if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { + if (ret<0) { + printk ("%s: err:\n", vfd->name); + v4l_print_ioctl(vfd->name, cmd); + } + } + + return ret; +} + +int video_ioctl2 (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + int is_ext_ctrl; + size_t ctrls_size = 0; + void __user *user_ptr = NULL; + +#ifdef __OLD_VIDIOC_ + cmd = video_fix_command(cmd); +#endif + is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS || + cmd == VIDIOC_TRY_EXT_CTRLS); + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + parg = NULL; + break; + case _IOC_READ: + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + + err = -EFAULT; + if (_IOC_DIR(cmd) & _IOC_WRITE) + if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + if (is_ext_ctrl) { + struct v4l2_ext_controls *p = parg; + + /* In case of an error, tell the caller that it wasn't + a specific control that caused it. */ + p->error_idx = p->count; + user_ptr = (void __user *)p->controls; + if (p->count) { + ctrls_size = sizeof(struct v4l2_ext_control) * p->count; + /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */ + mbuf = kmalloc(ctrls_size, GFP_KERNEL); + err = -ENOMEM; + if (NULL == mbuf) + goto out_ext_ctrl; + err = -EFAULT; + if (copy_from_user(mbuf, user_ptr, ctrls_size)) + goto out_ext_ctrl; + p->controls = mbuf; + } + } + + /* Handles IOCTL */ + err = __video_do_ioctl(inode, file, cmd, parg); + if (err == -ENOIOCTLCMD) + err = -EINVAL; + if (is_ext_ctrl) { + struct v4l2_ext_controls *p = parg; + + p->controls = (void *)user_ptr; + if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size)) + err = -EFAULT; + goto out_ext_ctrl; + } + if (err < 0) + goto out; + +out_ext_ctrl: + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) + { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + kfree(mbuf); + return err; +} + + static struct file_operations video_fops; /** @@ -371,7 +1610,9 @@ void video_unregister_device(struct vide mutex_unlock(&videodev_lock); } - +/* + * Video fs operations + */ static struct file_operations video_fops= { .owner = THIS_MODULE, @@ -387,7 +1628,7 @@ static int __init videodev_init(void) { int ret; - printk(KERN_INFO "Linux video capture interface: v1.00\n"); + printk(KERN_INFO "Linux video capture interface: v2.00\n"); if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) { printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR); return -EIO; @@ -418,11 +1659,12 @@ EXPORT_SYMBOL(video_devdata); EXPORT_SYMBOL(video_usercopy); EXPORT_SYMBOL(video_exclusive_open); EXPORT_SYMBOL(video_exclusive_release); +EXPORT_SYMBOL(video_ioctl2); EXPORT_SYMBOL(video_device_alloc); EXPORT_SYMBOL(video_device_release); -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("Device registrar for Video4Linux drivers"); +MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab "); +MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index a8c1014..268e69f 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 779db26..41d23c8 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -48,34 +48,15 @@ #define BUFFER_TIMEOUT msecs_to_jiff #include "font.h" -#ifndef kzalloc -#define kzalloc(size, flags) \ -({ \ - void *__ret = kmalloc(size, flags); \ - if (__ret) \ - memset(__ret, 0, size); \ - __ret; \ -}) -#endif - -MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); -MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); -MODULE_LICENSE("Dual BSD/GPL"); - #define VIVI_MAJOR_VERSION 0 #define VIVI_MINOR_VERSION 4 #define VIVI_RELEASE 0 #define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) -static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ -module_param(video_nr, int, 0); - -static int debug = 0; -module_param(debug, int, 0); - -static unsigned int vid_limit = 16; -module_param(vid_limit,int,0644); -MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); +/* Declare static vars that will be used as parameters */ +static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ +static struct video_device vivi; /* Video device */ +static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ /* supported controls */ static struct v4l2_queryctrl vivi_qctrl[] = { @@ -129,10 +110,10 @@ static struct v4l2_queryctrl vivi_qctrl[ static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; -#define dprintk(level,fmt, arg...) \ - do { \ - if (debug >= (level)) \ - printk(KERN_DEBUG "vivi: " fmt , ## arg); \ +#define dprintk(level,fmt, arg...) \ + do { \ + if (vivi.debug >= (level)) \ + printk(KERN_DEBUG "vivi: " fmt , ## arg); \ } while (0) /* ------------------------------------------------------------------ @@ -190,7 +171,7 @@ struct vivi_dev { /* various device info */ unsigned int resources; - struct video_device video_dev; + struct video_device vfd; struct vivi_dmaqueue vidq; @@ -248,7 +229,8 @@ #define TSTAMP_MIN_Y 24 #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 #define TSTAMP_MIN_X 64 -void prep_to_addr(struct sg_to_addr to_addr[],struct videobuf_buffer *vb) +static void prep_to_addr(struct sg_to_addr to_addr[], + struct videobuf_buffer *vb) { int i, pos=0; @@ -259,7 +241,7 @@ void prep_to_addr(struct sg_to_addr to_a } } -inline int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) +static int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) { int p1=0,p2=pages-1,p3=pages/2; @@ -280,8 +262,8 @@ inline int get_addr_pos(int pos, int pag return (p1); } -void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, - int hmax, int line, char *timestr) +static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, + int hmax, int line, char *timestr) { int w,i,j,pos=inipos,pgpos,oldpg,y; char *p,*s,*basep; @@ -491,7 +473,7 @@ static void vivi_thread_tick(struct vivi dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc); } -void vivi_sleep(struct vivi_dmaqueue *dma_q) +static void vivi_sleep(struct vivi_dmaqueue *dma_q) { int timeout; DECLARE_WAITQUEUE(wait, current); @@ -526,7 +508,7 @@ void vivi_sleep(struct vivi_dmaqueue *d try_to_freeze(); } -int vivi_thread(void *data) +static int vivi_thread(void *data) { struct vivi_dmaqueue *dma_q=data; @@ -542,7 +524,7 @@ int vivi_thread(void *data) return 0; } -int vivi_start_thread(struct vivi_dmaqueue *dma_q) +static int vivi_start_thread(struct vivi_dmaqueue *dma_q) { dma_q->frame=0; dma_q->ini_jiffies=jiffies; @@ -560,7 +542,7 @@ int vivi_start_thread(struct vivi_dmaque return 0; } -void vivi_stop_thread(struct vivi_dmaqueue *dma_q) +static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) { dprintk(1,"%s\n",__FUNCTION__); /* shutdown control thread */ @@ -666,8 +648,7 @@ buffer_setup(struct videobuf_queue *vq, return 0; } -void -free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) +static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) { dprintk(1,"%s\n",__FUNCTION__); @@ -791,8 +772,8 @@ static void buffer_release(struct videob free_buffer(vq,buf); } -int vivi_map_sg (void *dev, struct scatterlist *sg, int nents, - int direction) +static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents, + int direction) { int i; @@ -808,15 +789,15 @@ int vivi_map_sg (void *dev, struct scatt return nents; } -int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages, - int direction) +static int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages, + int direction) { dprintk(1,"%s\n",__FUNCTION__); return 0; } -int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist,int nr_pages, - int direction) +static int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist, int nr_pages, + int direction) { // dprintk(1,"%s\n",__FUNCTION__); @@ -840,7 +821,80 @@ static struct videobuf_queue_ops vivi_vi IOCTL handling ------------------------------------------------------------------*/ -static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, + +static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) +{ + /* is it free? */ + down(&dev->lock); + if (dev->resources) { + /* no, someone else uses it */ + up(&dev->lock); + return 0; + } + /* it's free, grab it */ + dev->resources =1; + dprintk(1,"res: get\n"); + up(&dev->lock); + return 1; +} + +static int res_locked(struct vivi_dev *dev) +{ + return (dev->resources); +} + +static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) +{ + down(&dev->lock); + dev->resources = 0; + dprintk(1,"res: put\n"); + up(&dev->lock); +} + +/* ------------------------------------------------------------------ + IOCTL vidioc handling + ------------------------------------------------------------------*/ +static int vidioc_querycap (struct file *file, void *priv, + struct v4l2_capability *cap) +{ + strcpy(cap->driver, "vivi"); + strcpy(cap->card, "vivi"); + cap->version = VIVI_VERSION; + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + return 0; +} + +static int vidioc_enum_fmt_cap (struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (f->index > 0) + return -EINVAL; + + strlcpy(f->description,format.name,sizeof(f->description)); + f->pixelformat = format.fourcc; + return 0; +} + +static int vidioc_g_fmt_cap (struct file *file, void *priv, + struct v4l2_format *f) +{ + struct vivi_fh *fh=priv; + + f->fmt.pix.width = fh->width; + f->fmt.pix.height = fh->height; + f->fmt.pix.field = fh->vb_vidq.field; + f->fmt.pix.pixelformat = fh->fmt->fourcc; + f->fmt.pix.bytesperline = + (f->fmt.pix.width * fh->fmt->depth) >> 3; + f->fmt.pix.sizeimage = + f->fmt.pix.height * f->fmt.pix.bytesperline; + + return (0); +} + +static int vidioc_try_fmt_cap (struct file *file, void *priv, struct v4l2_format *f) { struct vivi_fmt *fmt; @@ -848,7 +902,8 @@ static int vivi_try_fmt(struct vivi_dev unsigned int maxw, maxh; if (format.fourcc != f->fmt.pix.pixelformat) { - dprintk(1,"Fourcc format invalid.\n"); + dprintk(1,"Fourcc format (0x%08x) invalid. Driver accepts " + "only 0x%08x\n",f->fmt.pix.pixelformat,format.fourcc); return -EINVAL; } fmt=&format; @@ -884,356 +939,196 @@ static int vivi_try_fmt(struct vivi_dev return 0; } -static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) +/*FIXME: This seems to be generic enough to be at videodev2 */ +static int vidioc_s_fmt_cap (struct file *file, void *priv, + struct v4l2_format *f) { - /* is it free? */ - down(&dev->lock); - if (dev->resources) { - /* no, someone else uses it */ - up(&dev->lock); - return 0; - } - /* it's free, grab it */ - dev->resources =1; - dprintk(1,"res: get\n"); - up(&dev->lock); - return 1; + struct vivi_fh *fh=priv; + int ret = vidioc_try_fmt_cap(file,fh,f); + if (ret < 0) + return (ret); + + fh->fmt = &format; + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vb_vidq.field = f->fmt.pix.field; + fh->type = f->type; + + return (0); } -static inline int res_locked(struct vivi_dev *dev) +static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) { - return (dev->resources); -} + struct vivi_fh *fh=priv; -static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) -{ - down(&dev->lock); - dev->resources = 0; - dprintk(1,"res: put\n"); - up(&dev->lock); + return (videobuf_reqbufs(&fh->vb_vidq, p)); } -static int vivi_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) +static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) { - struct vivi_fh *fh = file->private_data; - struct vivi_dev *dev = fh->dev; - int ret=0; + struct vivi_fh *fh=priv; - if (debug) { - if (_IOC_DIR(cmd) & _IOC_WRITE) - v4l_printk_ioctl_arg("vivi(w)",cmd, arg); - else if (!_IOC_DIR(cmd) & _IOC_READ) { - v4l_print_ioctl("vivi", cmd); - } - } + return (videobuf_querybuf(&fh->vb_vidq, p)); +} - switch(cmd) { - /* --- capabilities ------------------------------------------ */ - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = (struct v4l2_capability*)arg; - - memset(cap, 0, sizeof(*cap)); - - strcpy(cap->driver, "vivi"); - strcpy(cap->card, "vivi"); - cap->version = VIVI_VERSION; - cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE; - break; - } - /* --- capture ioctls ---------------------------------------- */ - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *f = arg; - enum v4l2_buf_type type; - unsigned int index; +static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct vivi_fh *fh=priv; - index = f->index; - type = f->type; + return (videobuf_qbuf(&fh->vb_vidq, p)); +} - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - ret=-EINVAL; - break; - } +static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct vivi_fh *fh=priv; - switch (type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (index > 0){ - ret=-EINVAL; - break; - } - memset(f,0,sizeof(*f)); + return (videobuf_dqbuf(&fh->vb_vidq, p, + file->f_flags & O_NONBLOCK)); +} - f->index = index; - f->type = type; - strlcpy(f->description,format.name,sizeof(f->description)); - f->pixelformat = format.fourcc; - break; - default: - ret=-EINVAL; - } - break; +#ifdef HAVE_V4L1 +static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) +{ + struct vivi_fh *fh=priv; + struct videobuf_queue *q=&fh->vb_vidq; + struct v4l2_requestbuffers req; + unsigned int i, ret; + + req.type = q->type; + req.count = 8; + req.memory = V4L2_MEMORY_MMAP; + ret = videobuf_reqbufs(q,&req); + if (ret < 0) + return (ret); + + mbuf->frames = req.count; + mbuf->size = 0; + for (i = 0; i < mbuf->frames; i++) { + mbuf->offsets[i] = q->bufs[i]->boff; + mbuf->size += q->bufs[i]->bsize; } - case VIDIOC_G_FMT: - { - struct v4l2_format *f = (struct v4l2_format *)arg; + return (0); +} +#endif - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - ret=-EINVAL; - break; - } +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct vivi_fh *fh=priv; + struct vivi_dev *dev = fh->dev; - memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); - f->fmt.pix.width = fh->width; - f->fmt.pix.height = fh->height; - f->fmt.pix.field = fh->vb_vidq.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fh->fmt->depth) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; - break; - } - case VIDIOC_S_FMT: - { - struct v4l2_format *f = arg; + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dprintk(1,"Only capture supported.\n"); - ret=-EINVAL; - break; - } + if (!res_get(dev,fh)) + return -EBUSY; + return (videobuf_streamon(&fh->vb_vidq)); +} - ret = vivi_try_fmt(dev,fh,f); - if (ret < 0) - break; +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct vivi_fh *fh=priv; + struct vivi_dev *dev = fh->dev; - fh->fmt = &format; - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vb_vidq.field = f->fmt.pix.field; - fh->type = f->type; + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; - break; - } - case VIDIOC_TRY_FMT: - { - struct v4l2_format *f = arg; - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - ret=-EINVAL; - break; - } + videobuf_streamoff(&fh->vb_vidq); + res_free(dev,fh); - ret=vivi_try_fmt(dev,fh,f); - break; - } - case VIDIOC_REQBUFS: - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - ret=-EINVAL; - break; - } - ret=videobuf_reqbufs(&fh->vb_vidq, arg); - break; - case VIDIOC_QUERYBUF: - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - ret=-EINVAL; - break; - } - ret=videobuf_querybuf(&fh->vb_vidq, arg); - break; - case VIDIOC_QBUF: - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - ret=-EINVAL; - break; - } - ret=videobuf_qbuf(&fh->vb_vidq, arg); - break; - case VIDIOC_DQBUF: - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - ret=-EINVAL; - break; - } - ret=videobuf_dqbuf(&fh->vb_vidq, arg, - file->f_flags & O_NONBLOCK); - break; -#ifdef HAVE_V4L1 - /* --- streaming capture ------------------------------------- */ - case VIDIOCGMBUF: - { - struct video_mbuf *mbuf = arg; - struct videobuf_queue *q=&fh->vb_vidq; - struct v4l2_requestbuffers req; - unsigned int i; - - memset(&req,0,sizeof(req)); - req.type = q->type; - req.count = 8; - req.memory = V4L2_MEMORY_MMAP; - ret = videobuf_reqbufs(q,&req); - if (ret < 0) - break; - memset(mbuf,0,sizeof(*mbuf)); - mbuf->frames = req.count; - mbuf->size = 0; - for (i = 0; i < mbuf->frames; i++) { - mbuf->offsets[i] = q->bufs[i]->boff; - mbuf->size += q->bufs[i]->bsize; - } - break; - } -#endif - case VIDIOC_STREAMON: - { - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (!res_get(dev,fh)) - return -EBUSY; - ret=videobuf_streamon(&fh->vb_vidq); - break; - } - case VIDIOC_STREAMOFF: + return (0); +} + +static struct v4l2_tvnorm tvnorms[] = { { - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - ret=-EINVAL; - break; - } - ret = videobuf_streamoff(&fh->vb_vidq); - if (ret < 0) - break; - res_free(dev,fh); - break; + .name = "NTSC-M", + .id = V4L2_STD_NTSC_M, } - /* ---------- tv norms ---------- */ - case VIDIOC_ENUMSTD: - { - struct v4l2_standard *e = arg; +}; - if (e->index>0) { - ret=-EINVAL; - break; - } - ret = v4l2_video_std_construct(e, V4L2_STD_NTSC_M, "NTSC-M"); +static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a) +{ - /* Allows vivi to use different fps from video std */ - e->frameperiod.numerator = WAKE_NUMERATOR; - e->frameperiod.denominator = WAKE_DENOMINATOR; + return 0; +} - break; - } - case VIDIOC_G_STD: - { - v4l2_std_id *id = arg; +/* only one input in this sample driver */ +static int vidioc_enum_input (struct file *file, void *priv, + struct v4l2_input *inp) +{ + if (inp->index != 0) + return -EINVAL; - *id = V4L2_STD_NTSC_M; - break; - } - case VIDIOC_S_STD: - { - break; - } - /* ------ input switching ---------- */ - case VIDIOC_ENUMINPUT: - { /* only one input in this sample driver */ - struct v4l2_input *inp = arg; + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_NTSC_M; + strcpy(inp->name,"Camera"); - if (inp->index != 0) { - ret=-EINVAL; - break; - } - memset(inp, 0, sizeof(*inp)); + return (0); +} - inp->index = 0; - inp->type = V4L2_INPUT_TYPE_CAMERA; - inp->std = V4L2_STD_NTSC_M; - strcpy(inp->name,"Camera"); - break; - } - case VIDIOC_G_INPUT: - { - unsigned int *i = arg; +static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) +{ + *i = 0; - *i = 0; - break; - } - case VIDIOC_S_INPUT: - { - unsigned int *i = arg; + return (0); +} +static int vidioc_s_input (struct file *file, void *priv, unsigned int i) +{ + if (i > 0) + return -EINVAL; - if (*i > 0) - ret=-EINVAL; - break; - } + return (0); +} /* --- controls ---------------------------------------------- */ - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - int i; - - for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) - if (qc->id && qc->id == vivi_qctrl[i].id) { - memcpy(qc, &(vivi_qctrl[i]), - sizeof(*qc)); - break; - } +static int vidioc_queryctrl (struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int i; - ret=-EINVAL; - break; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - int i; + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + if (qc->id && qc->id == vivi_qctrl[i].id) { + memcpy(qc, &(vivi_qctrl[i]), + sizeof(*qc)); + return (0); + } - for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) - if (ctrl->id == vivi_qctrl[i].id) { - ctrl->value=qctl_regs[i]; - break; - } + return -EINVAL; +} - ret=-EINVAL; - break; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - int i; - for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) - if (ctrl->id == vivi_qctrl[i].id) { - if (ctrl->value < - vivi_qctrl[i].minimum - || ctrl->value > - vivi_qctrl[i].maximum) { - ret=-ERANGE; - break; - } - qctl_regs[i]=ctrl->value; - break; - } - ret=-EINVAL; - break; - } - default: - ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,vivi_do_ioctl); - } +static int vidioc_g_ctrl (struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + int i; - if (debug) { - if (ret<0) { - v4l_print_ioctl("vivi(err)", cmd); - dprintk(1,"errcode=%d\n",ret); - } else if (_IOC_DIR(cmd) & _IOC_READ) - v4l_printk_ioctl_arg("vivi(r)",cmd, arg); - } + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + if (ctrl->id == vivi_qctrl[i].id) { + ctrl->value=qctl_regs[i]; + return (0); + } - return ret; + return -EINVAL; } - -static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int vidioc_s_ctrl (struct file *file, void *priv, + struct v4l2_control *ctrl) { - return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl); + int i; + + for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) + if (ctrl->id == vivi_qctrl[i].id) { + if (ctrl->value < + vivi_qctrl[i].minimum + || ctrl->value > + vivi_qctrl[i].maximum) { + return (-ERANGE); + } + qctl_regs[i]=ctrl->value; + return (0); + } + return -EINVAL; } /* ------------------------------------------------------------------ @@ -1255,7 +1150,7 @@ static int vivi_open(struct inode *inode list_for_each(list,&vivi_devlist) { h = list_entry(list, struct vivi_dev, vivi_devlist); - if (h->video_dev.minor == minor) { + if (h->vfd.minor == minor) { dev = h; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; } @@ -1264,6 +1159,7 @@ static int vivi_open(struct inode *inode return -ENODEV; + /* If more than one user, mutex should be added */ dev->users++; @@ -1279,6 +1175,7 @@ static int vivi_open(struct inode *inode file->private_data = fh; fh->dev = dev; + fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fh->fmt = &format; fh->width = 640; @@ -1314,7 +1211,7 @@ static int vivi_open(struct inode *inode static ssize_t vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { - struct vivi_fh *fh = file->private_data; + struct vivi_fh *fh = file->private_data; if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (res_locked(fh->dev)) @@ -1328,8 +1225,8 @@ vivi_read(struct file *file, char __user static unsigned int vivi_poll(struct file *file, struct poll_table_struct *wait) { - struct vivi_fh *fh = file->private_data; - struct vivi_buffer *buf; + struct vivi_fh *fh = file->private_data; + struct vivi_buffer *buf; dprintk(1,"%s\n",__FUNCTION__); @@ -1358,8 +1255,8 @@ vivi_poll(struct file *file, struct poll static int vivi_release(struct inode *inode, struct file *file) { - struct vivi_fh *fh = file->private_data; - struct vivi_dev *dev = fh->dev; + struct vivi_fh *fh = file->private_data; + struct vivi_dev *dev = fh->dev; struct vivi_dmaqueue *vidq = &dev->vidq; int minor = iminor(inode); @@ -1379,7 +1276,7 @@ static int vivi_release(struct inode *in static int vivi_mmap(struct file *file, struct vm_area_struct * vma) { - struct vivi_fh *fh = file->private_data; + struct vivi_fh *fh = file->private_data; int ret; dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma); @@ -1400,20 +1297,44 @@ static struct file_operations vivi_fops .release = vivi_release, .read = vivi_read, .poll = vivi_poll, - .ioctl = vivi_ioctl, + .ioctl = video_ioctl2, /* V4L2 ioctl handler */ .mmap = vivi_mmap, .llseek = no_llseek, }; static struct video_device vivi = { - .name = "VTM Virtual Video Capture Board", + .name = "vivi", .type = VID_TYPE_CAPTURE, .hardware = 0, .fops = &vivi_fops, .minor = -1, // .release = video_device_release, + + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, + .vidioc_g_fmt_cap = vidioc_g_fmt_cap, + .vidioc_try_fmt_cap = vidioc_try_fmt_cap, + .vidioc_s_fmt_cap = vidioc_s_fmt_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, +#ifdef HAVE_V4L1 + .vidiocgmbuf = vidiocgmbuf, +#endif + .tvnorms = tvnorms, + .tvnormsize = ARRAY_SIZE(tvnorms), }; -/* ------------------------------------------------------------------ +/* ----------------------------------------------------------------- Initialization and module stuff ------------------------------------------------------------------*/ @@ -1457,3 +1378,16 @@ static void __exit vivi_exit(void) module_init(vivi_init); module_exit(vivi_exit); + +MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); +MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); +MODULE_LICENSE("Dual BSD/GPL"); + +module_param(video_nr, int, 0); + +module_param_named(debug,vivi.debug, int, 0644); +MODULE_PARM_DESC(debug,"activates debug info"); + +module_param(vid_limit,int,0644); +MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); + diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 40b205b..1eca7e6 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -34,6 +34,7 @@ #include #define I2C_NAME(x) (x)->name #include +#include #include #define I2C_VPX3220 0x86 diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 80ef8a1..4bdc886 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -58,6 +58,7 @@ #include #include #include #include +#include #include //#define DEBUG // Undef me for production diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig index 115833e..a859a69 100644 --- a/drivers/media/video/zc0301/Kconfig +++ b/drivers/media/video/zc0301/Kconfig @@ -1,9 +1,9 @@ config USB_ZC0301 - tristate "USB ZC0301 Image Processor and Control Chip support" + tristate "USB ZC0301[P] Image Processor and Control Chip support" depends on USB && VIDEO_V4L1 ---help--- - Say Y here if you want support for cameras based on the ZC0301 - Image Processor and Control Chip. + Say Y here if you want support for cameras based on the ZC0301 or + ZC0301P Image Processors and Control Chips. See for more info. diff --git a/drivers/media/video/zc0301/Makefile b/drivers/media/video/zc0301/Makefile index d749199..d9e6d97 100644 --- a/drivers/media/video/zc0301/Makefile +++ b/drivers/media/video/zc0301/Makefile @@ -1,3 +1,3 @@ -zc0301-objs := zc0301_core.o zc0301_pas202bcb.o +zc0301-objs := zc0301_core.o zc0301_pb0330.o zc0301_pas202bcb.o obj-$(CONFIG_USB_ZC0301) += zc0301.o diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 0fad397..1b2be2d 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Video4Linux2 driver for ZC0301 Image Processor and Control Chip * + * Video4Linux2 driver for ZC0301[P] Image Processor and Control Chip * * * * Copyright (C) 2006 by Luca Risolia * * * @@ -47,13 +47,13 @@ #include "zc0301.h" /*****************************************************************************/ -#define ZC0301_MODULE_NAME "V4L2 driver for ZC0301 " \ +#define ZC0301_MODULE_NAME "V4L2 driver for ZC0301[P] " \ "Image Processor and Control Chip" #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" #define ZC0301_AUTHOR_EMAIL "" #define ZC0301_MODULE_LICENSE "GPL" -#define ZC0301_MODULE_VERSION "1:1.03" -#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 3) +#define ZC0301_MODULE_VERSION "1:1.05" +#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 5) /*****************************************************************************/ @@ -427,10 +427,11 @@ resubmit_urb: static int zc0301_start_transfer(struct zc0301_device* cam) { struct usb_device *udev = cam->usbdev; + struct usb_host_interface* altsetting = usb_altnum_to_altsetting( + usb_ifnum_to_if(udev, 0), + ZC0301_ALTERNATE_SETTING); + const unsigned int psz = altsetting->endpoint[0].desc.wMaxPacketSize; struct urb* urb; - const unsigned int wMaxPacketSize[] = {0, 128, 192, 256, 384, - 512, 768, 1023}; - const unsigned int psz = wMaxPacketSize[ZC0301_ALTERNATE_SETTING]; s8 i, j; int err = 0; @@ -1772,11 +1773,9 @@ static int zc0301_ioctl_v4l2(struct inod case VIDIOC_G_CTRL: return zc0301_vidioc_g_ctrl(cam, arg); - case VIDIOC_S_CTRL_OLD: case VIDIOC_S_CTRL: return zc0301_vidioc_s_ctrl(cam, arg); - case VIDIOC_CROPCAP_OLD: case VIDIOC_CROPCAP: return zc0301_vidioc_cropcap(cam, arg); @@ -1823,7 +1822,6 @@ static int zc0301_ioctl_v4l2(struct inod case VIDIOC_G_PARM: return zc0301_vidioc_g_parm(cam, arg); - case VIDIOC_S_PARM_OLD: case VIDIOC_S_PARM: return zc0301_vidioc_s_parm(cam, arg); @@ -1914,7 +1912,7 @@ zc0301_usb_probe(struct usb_interface* i mutex_init(&cam->dev_mutex); - DBG(2, "ZC0301 Image Processor and Control Chip detected " + DBG(2, "ZC0301[P] Image Processor and Control Chip detected " "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); for (i = 0; zc0301_sensor_table[i]; i++) { @@ -1936,7 +1934,7 @@ zc0301_usb_probe(struct usb_interface* i cam->state |= DEV_MISCONFIGURED; } - strcpy(cam->v4ldev->name, "ZC0301 PC Camera"); + strcpy(cam->v4ldev->name, "ZC0301[P] PC Camera"); cam->v4ldev->owner = THIS_MODULE; cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; cam->v4ldev->hardware = 0; diff --git a/drivers/media/video/zc0301/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c index eaadf02..ecfd39a 100644 --- a/drivers/media/video/zc0301/zc0301_pas202bcb.c +++ b/drivers/media/video/zc0301/zc0301_pas202bcb.c @@ -1,10 +1,10 @@ /*************************************************************************** - * Plug-in for PAS202BCB image sensor connected to the ZC030! Image * + * Plug-in for PAS202BCB image sensor connected to the ZC0301[P] Image * * Processor and Control Chip * * * * Copyright (C) 2006 by Luca Risolia * * * - * Initialization values of the ZC0301 have been taken from the SPCA5XX * + * Initialization values of the ZC0301[P] have been taken from the SPCA5XX * * driver maintained by Michel Xhaard * * * * This program is free software; you can redistribute it and/or modify * diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c new file mode 100644 index 0000000..ed8542e --- /dev/null +++ b/drivers/media/video/zc0301/zc0301_pb0330.c @@ -0,0 +1,187 @@ +/*************************************************************************** + * Plug-in for PB-0330 image sensor connected to the ZC0301[P] Image * + * Processor and Control Chip * + * * + * Copyright (C) 2006 by Luca Risolia * + * * + * Initialization values of the ZC0301[P] have been taken from the SPCA5XX * + * driver maintained by Michel Xhaard * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + ***************************************************************************/ + +#include +#include "zc0301_sensor.h" + + +static struct zc0301_sensor pb0330; + + +static int pb0330_init(struct zc0301_device* cam) +{ + int err = 0; + + err += zc0301_write_reg(cam, 0x0000, 0x01); + err += zc0301_write_reg(cam, 0x0008, 0x03); + err += zc0301_write_reg(cam, 0x0010, 0x0A); + err += zc0301_write_reg(cam, 0x0002, 0x00); + err += zc0301_write_reg(cam, 0x0003, 0x02); + err += zc0301_write_reg(cam, 0x0004, 0x80); + err += zc0301_write_reg(cam, 0x0005, 0x01); + err += zc0301_write_reg(cam, 0x0006, 0xE0); + err += zc0301_write_reg(cam, 0x0001, 0x01); + err += zc0301_write_reg(cam, 0x0012, 0x05); + err += zc0301_write_reg(cam, 0x0012, 0x07); + err += zc0301_write_reg(cam, 0x0098, 0x00); + err += zc0301_write_reg(cam, 0x009A, 0x00); + err += zc0301_write_reg(cam, 0x011A, 0x00); + err += zc0301_write_reg(cam, 0x011C, 0x00); + err += zc0301_write_reg(cam, 0x0012, 0x05); + + err += zc0301_i2c_write(cam, 0x01, 0x0006); + err += zc0301_i2c_write(cam, 0x02, 0x0011); + err += zc0301_i2c_write(cam, 0x03, 0x01E7); + err += zc0301_i2c_write(cam, 0x04, 0x0287); + err += zc0301_i2c_write(cam, 0x06, 0x0003); + err += zc0301_i2c_write(cam, 0x07, 0x3002); + err += zc0301_i2c_write(cam, 0x20, 0x1100); + err += zc0301_i2c_write(cam, 0x2F, 0xF7B0); + err += zc0301_i2c_write(cam, 0x30, 0x0005); + err += zc0301_i2c_write(cam, 0x31, 0x0000); + err += zc0301_i2c_write(cam, 0x34, 0x0100); + err += zc0301_i2c_write(cam, 0x35, 0x0060); + err += zc0301_i2c_write(cam, 0x3D, 0x068F); + err += zc0301_i2c_write(cam, 0x40, 0x01E0); + err += zc0301_i2c_write(cam, 0x58, 0x0078); + err += zc0301_i2c_write(cam, 0x62, 0x0411); + + err += zc0301_write_reg(cam, 0x0087, 0x10); + err += zc0301_write_reg(cam, 0x0101, 0x37); + err += zc0301_write_reg(cam, 0x0012, 0x05); + err += zc0301_write_reg(cam, 0x0100, 0x0D); + err += zc0301_write_reg(cam, 0x0189, 0x06); + err += zc0301_write_reg(cam, 0x01AD, 0x00); + err += zc0301_write_reg(cam, 0x01C5, 0x03); + err += zc0301_write_reg(cam, 0x01CB, 0x13); + err += zc0301_write_reg(cam, 0x0250, 0x08); + err += zc0301_write_reg(cam, 0x0301, 0x08); + err += zc0301_write_reg(cam, 0x01A8, 0x60); + err += zc0301_write_reg(cam, 0x018D, 0x6C); + err += zc0301_write_reg(cam, 0x01AD, 0x09); + err += zc0301_write_reg(cam, 0x01AE, 0x15); + err += zc0301_write_reg(cam, 0x010A, 0x50); + err += zc0301_write_reg(cam, 0x010B, 0xF8); + err += zc0301_write_reg(cam, 0x010C, 0xF8); + err += zc0301_write_reg(cam, 0x010D, 0xF8); + err += zc0301_write_reg(cam, 0x010E, 0x50); + err += zc0301_write_reg(cam, 0x010F, 0xF8); + err += zc0301_write_reg(cam, 0x0110, 0xF8); + err += zc0301_write_reg(cam, 0x0111, 0xF8); + err += zc0301_write_reg(cam, 0x0112, 0x50); + err += zc0301_write_reg(cam, 0x0008, 0x03); + err += zc0301_write_reg(cam, 0x01C6, 0x08); + err += zc0301_write_reg(cam, 0x01CB, 0x0F); + err += zc0301_write_reg(cam, 0x010A, 0x50); + err += zc0301_write_reg(cam, 0x010B, 0xF8); + err += zc0301_write_reg(cam, 0x010C, 0xF8); + err += zc0301_write_reg(cam, 0x010D, 0xF8); + err += zc0301_write_reg(cam, 0x010E, 0x50); + err += zc0301_write_reg(cam, 0x010F, 0xF8); + err += zc0301_write_reg(cam, 0x0110, 0xF8); + err += zc0301_write_reg(cam, 0x0111, 0xF8); + err += zc0301_write_reg(cam, 0x0112, 0x50); + err += zc0301_write_reg(cam, 0x0180, 0x00); + err += zc0301_write_reg(cam, 0x0019, 0x00); + + err += zc0301_i2c_write(cam, 0x05, 0x0066); + err += zc0301_i2c_write(cam, 0x09, 0x02B2); + err += zc0301_i2c_write(cam, 0x10, 0x0002); + + err += zc0301_write_reg(cam, 0x011D, 0x60); + err += zc0301_write_reg(cam, 0x0190, 0x00); + err += zc0301_write_reg(cam, 0x0191, 0x07); + err += zc0301_write_reg(cam, 0x0192, 0x8C); + err += zc0301_write_reg(cam, 0x0195, 0x00); + err += zc0301_write_reg(cam, 0x0196, 0x00); + err += zc0301_write_reg(cam, 0x0197, 0x8A); + err += zc0301_write_reg(cam, 0x018C, 0x10); + err += zc0301_write_reg(cam, 0x018F, 0x20); + err += zc0301_write_reg(cam, 0x01A9, 0x14); + err += zc0301_write_reg(cam, 0x01AA, 0x24); + err += zc0301_write_reg(cam, 0x001D, 0xD7); + err += zc0301_write_reg(cam, 0x001E, 0xF0); + err += zc0301_write_reg(cam, 0x001F, 0xF8); + err += zc0301_write_reg(cam, 0x0020, 0xFF); + err += zc0301_write_reg(cam, 0x01AD, 0x09); + err += zc0301_write_reg(cam, 0x01AE, 0x15); + err += zc0301_write_reg(cam, 0x0180, 0x40); + err += zc0301_write_reg(cam, 0x0180, 0x42); + + msleep(100); + + return err; +} + + +static struct zc0301_sensor pb0330 = { + .name = "PB-0330", + .init = &pb0330_init, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_JPEG, + .priv = 8, + }, +}; + + +int zc0301_probe_pb0330(struct zc0301_device* cam) +{ + int r0, err = 0; + + err += zc0301_write_reg(cam, 0x0000, 0x01); + err += zc0301_write_reg(cam, 0x0010, 0x0a); + err += zc0301_write_reg(cam, 0x0001, 0x01); + err += zc0301_write_reg(cam, 0x0012, 0x03); + err += zc0301_write_reg(cam, 0x0012, 0x01); + + msleep(10); + + r0 = zc0301_i2c_read(cam, 0x00, 2); + + if (r0 < 0 || err) + return -EIO; + + if (r0 != 0x8243) + return -ENODEV; + + zc0301_attach_sensor(cam, &pb0330); + + return 0; +} diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h index 1f95c28..4363a91 100644 --- a/drivers/media/video/zc0301/zc0301_sensor.h +++ b/drivers/media/video/zc0301/zc0301_sensor.h @@ -1,5 +1,5 @@ /*************************************************************************** - * API for image sensors connected to the ZC030! Image Processor and * + * API for image sensors connected to the ZC0301 Image Processor and * * Control Chip * * * * Copyright (C) 2006 by Luca Risolia * @@ -35,11 +35,13 @@ struct zc0301_sensor; /*****************************************************************************/ extern int zc0301_probe_pas202bcb(struct zc0301_device* cam); +extern int zc0301_probe_pb0330(struct zc0301_device* cam); #define ZC0301_SENSOR_TABLE \ /* Weak detections must go at the end of the list */ \ static int (*zc0301_sensor_table[])(struct zc0301_device*) = { \ &zc0301_probe_pas202bcb, \ + &zc0301_probe_pb0330, \ NULL, \ }; @@ -58,14 +60,28 @@ #define ZC0301_USB_DEVICE(vend, prod, in #define ZC0301_ID_TABLE \ static const struct usb_device_id zc0301_id_table[] = { \ - { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, \ + { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, /* ICM105 */ \ { ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131B */ \ + { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131 */ \ + { ZC0301_USB_DEVICE(0x041e, 0x401f, 0xff), }, /* TAS5130 */ \ + { ZC0301_USB_DEVICE(0x041e, 0x4022, 0xff), }, \ { ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */ \ { ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \ + { ZC0301_USB_DEVICE(0x041e, 0x4036, 0xff), }, /* HV7131 */ \ + { ZC0301_USB_DEVICE(0x041e, 0x403a, 0xff), }, /* HV7131 */ \ + { ZC0301_USB_DEVICE(0x0458, 0x7007, 0xff), }, /* TAS5130 */ \ + { ZC0301_USB_DEVICE(0x0458, 0x700C, 0xff), }, /* TAS5130 */ \ + { ZC0301_USB_DEVICE(0x0458, 0x700f, 0xff), }, /* TAS5130 */ \ + { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ + { ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */ \ + { ZC0301_USB_DEVICE(0x055f, 0xd004, 0xff), }, /* TAS5130 */ \ + { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \ - { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \ + { ZC0301_USB_DEVICE(0x0ac8, 0x301b, 0xff), }, /* PB-0330/HV7131 */ \ + { ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */ \ + { ZC0301_USB_DEVICE(0x10fd, 0x0128, 0xff), }, /* TAS5130 */ \ + { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130 */ \ + { ZC0301_USB_DEVICE(0x10fd, 0x804e, 0xff), }, /* TAS5130 */ \ { } \ }; diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index 0166f55..ffcda95 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran.h @@ -159,7 +159,7 @@ #define BUZ_MASK_STAT_COM 3 #define BUZ_MAX_FRAME 256 /* Must be a power of 2 */ #define BUZ_MASK_FRAME 255 /* Must be BUZ_MAX_FRAME-1 */ -#define BUZ_MAX_INPUT 8 +#define BUZ_MAX_INPUT 16 #if VIDEO_MAX_FRAME <= 32 # define V4L_MAX_FRAME 32 @@ -191,6 +191,9 @@ enum card_type { /* Iomega */ BUZ, + /* AverMedia */ + AVS6EYES, + /* total number of cards */ NUM_CARDS }; @@ -379,6 +382,9 @@ struct card_info { /* is the /GWS line conected? */ u8 gws_not_connected; + /* avs6eyes mux setting */ + u8 input_mux; + void (*init) (struct zoran * zr); }; diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index 0a85c9e..958c1e6 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c @@ -27,6 +27,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + #include #include #include @@ -38,6 +40,7 @@ #include #include #include #include +#include #include #include #include @@ -93,6 +96,11 @@ module_param(default_input, int, 0); MODULE_PARM_DESC(default_input, "Default input (0=Composite, 1=S-Video, 2=Internal)"); +static int default_mux = 1; /* 6 Eyes input selection */ +module_param(default_mux, int, 0); +MODULE_PARM_DESC(default_mux, + "Default 6 Eyes mux setting (Input selection)"); + static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */ module_param(default_norm, int, 0); MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); @@ -301,6 +309,30 @@ lml33_init (struct zoran *zr) GPIO(zr, 2, 1); // Set Composite input/output } +static void +avs6eyes_init (struct zoran *zr) +{ + // AverMedia 6-Eyes original driver by Christer Weinigel + + // Lifted straight from Christer's old driver and + // modified slightly by Martin Samuelsson. + + int mux = default_mux; /* 1 = BT866, 7 = VID1 */ + + GPIO(zr, 4, 1); /* Bt866 SLEEP on */ + udelay(2); + + GPIO(zr, 0, 1); /* ZR36060 /RESET on */ + GPIO(zr, 1, 0); /* ZR36060 /SLEEP on */ + GPIO(zr, 2, mux & 1); /* MUX S0 */ + GPIO(zr, 3, 0); /* /FRAME on */ + GPIO(zr, 4, 0); /* Bt866 SLEEP off */ + GPIO(zr, 5, mux & 2); /* MUX S1 */ + GPIO(zr, 6, 0); /* ? */ + GPIO(zr, 7, mux & 4); /* MUX S2 */ + +} + static char * i2cid_to_modulename (u16 i2c_id) { @@ -391,6 +423,14 @@ static struct tvnorm f60sqpixel_dc10 = { static struct tvnorm f50ccir601_lm33r10 = { 864, 720, 74+54, 804, 625, 576, 18 }; static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 }; +/* FIXME: The ks0127 seem incapable of swapping U and V, too, which is why I + * copy Maxim's left shift hack for the 6 Eyes. + * + * Christer's driver used the unshifted norms, though... + * /Sam */ +static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 }; +static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 }; + static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { { .type = DC10_old, @@ -419,6 +459,7 @@ static struct card_info zoran_cards[NUM_ .gpcs = { -1, 0 }, .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, .gws_not_connected = 0, + .input_mux = 0, .init = &dc10_init, }, { .type = DC10_new, @@ -445,6 +486,7 @@ static struct card_info zoran_cards[NUM_ .gpcs = { -1, 1}, .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 }, .gws_not_connected = 0, + .input_mux = 0, .init = &dc10plus_init, }, { .type = DC10plus, @@ -474,6 +516,7 @@ static struct card_info zoran_cards[NUM_ .gpcs = { -1, 1 }, .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 }, .gws_not_connected = 0, + .input_mux = 0, .init = &dc10plus_init, }, { .type = DC30, @@ -502,6 +545,7 @@ static struct card_info zoran_cards[NUM_ .gpcs = { -1, 0 }, .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, .gws_not_connected = 0, + .input_mux = 0, .init = &dc10_init, }, { .type = DC30plus, @@ -532,6 +576,7 @@ static struct card_info zoran_cards[NUM_ .gpcs = { -1, 0 }, .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, .gws_not_connected = 0, + .input_mux = 0, .init = &dc10_init, }, { .type = LML33, @@ -558,6 +603,7 @@ static struct card_info zoran_cards[NUM_ .gpcs = { 3, 1 }, .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, .gws_not_connected = 1, + .input_mux = 0, .init = &lml33_init, }, { .type = LML33R10, @@ -586,6 +632,7 @@ static struct card_info zoran_cards[NUM_ .gpcs = { 3, 1 }, .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, .gws_not_connected = 1, + .input_mux = 0, .init = &lml33_init, }, { .type = BUZ, @@ -614,8 +661,49 @@ static struct card_info zoran_cards[NUM_ .gpcs = { 3, 1 }, .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, .gws_not_connected = 1, + .input_mux = 0, .init = &buz_init, + }, { + .type = AVS6EYES, + .name = "6-Eyes", + /* AverMedia chose not to brand the 6-Eyes. Thus it + can't be autodetected, and requires card=x. */ + .vendor_id = -1, + .device_id = -1, + .i2c_decoder = I2C_DRIVERID_KS0127, + .i2c_encoder = I2C_DRIVERID_BT866, + .video_codec = CODEC_TYPE_ZR36060, + + .inputs = 10, + .input = { + { 0, "Composite 1" }, + { 1, "Composite 2" }, + { 2, "Composite 3" }, + { 4, "Composite 4" }, + { 5, "Composite 5" }, + { 6, "Composite 6" }, + { 8, "S-Video 1" }, + { 9, "S-Video 2" }, + {10, "S-Video 3" }, + {15, "YCbCr" } + }, + .norms = 2, + .tvn = { + &f50ccir601_avs6eyes, + &f60ccir601_avs6eyes, + NULL + }, + .jpeg_int = ZR36057_ISR_GIRQ1, + .vsync_int = ZR36057_ISR_GIRQ0, + .gpio = { 1, 0, 3, -1, -1, -1, -1, -1 },// Validity unknown /Sam + .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, // Validity unknown /Sam + .gpcs = { 3, 1 }, // Validity unknown /Sam + .vfe_pol = { 1, 0, 0, 0, 0, 1, 0, 0 }, // Validity unknown /Sam + .gws_not_connected = 1, + .input_mux = 1, + .init = &avs6eyes_init, } + }; /* diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index c690b2e..02168d9 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -536,7 +536,7 @@ zr36057_overlay (struct zoran *zr, * All error messages are internal driver checking only! */ /* video display top and bottom registers */ - reg = (u32) zr->buffer.base + + reg = (long) zr->buffer.base + zr->overlay_settings.x * ((zr->overlay_settings.format->depth + 7) / 8) + zr->overlay_settings.y * diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index b5a576a..9711f62 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -73,6 +73,7 @@ #define ZORAN_VID_TYPE ( \ ) #include +#include #include "videocodec.h" #include @@ -2047,7 +2048,7 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr)); memset(vcap, 0, sizeof(struct video_capability)); - strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)); + strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)-1); vcap->type = ZORAN_VID_TYPE; vcap->channels = zr->card.inputs; @@ -2689,8 +2690,8 @@ #ifdef HAVE_V4L2 dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCAP\n", ZR_DEVNAME(zr)); memset(cap, 0, sizeof(*cap)); - strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)); - strncpy(cap->driver, "zoran", sizeof(cap->driver)); + strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1); + strncpy(cap->driver, "zoran", sizeof(cap->driver)-1); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(zr->pci_dev)); cap->version = @@ -2742,7 +2743,7 @@ #ifdef HAVE_V4L2 memset(fmt, 0, sizeof(*fmt)); fmt->index = index; fmt->type = type; - strncpy(fmt->description, zoran_formats[i].name, 31); + strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1); fmt->pixelformat = zoran_formats[i].fourcc; if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; @@ -3566,16 +3567,16 @@ #ifdef HAVE_V4L2 switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - strncpy(ctrl->name, "Brightness", 31); + strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1); break; case V4L2_CID_CONTRAST: - strncpy(ctrl->name, "Contrast", 31); + strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1); break; case V4L2_CID_SATURATION: - strncpy(ctrl->name, "Saturation", 31); + strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1); break; case V4L2_CID_HUE: - strncpy(ctrl->name, "Hue", 31); + strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1); break; } @@ -3693,7 +3694,7 @@ #ifdef HAVE_V4L2 &caps); if (caps.flags & VIDEO_DECODER_AUTO) { std->id = V4L2_STD_ALL; - strncpy(std->name, "Autodetect", 31); + strncpy(std->name, "Autodetect", sizeof(std->name)-1); return 0; } else return -EINVAL; @@ -3701,21 +3702,21 @@ #ifdef HAVE_V4L2 switch (std->index) { case 0: std->id = V4L2_STD_PAL; - strncpy(std->name, "PAL", 31); + strncpy(std->name, "PAL", sizeof(std->name)-1); std->frameperiod.numerator = 1; std->frameperiod.denominator = 25; std->framelines = zr->card.tvn[0]->Ht; break; case 1: std->id = V4L2_STD_NTSC; - strncpy(std->name, "NTSC", 31); + strncpy(std->name, "NTSC", sizeof(std->name)-1); std->frameperiod.numerator = 1001; std->frameperiod.denominator = 30000; std->framelines = zr->card.tvn[1]->Ht; break; case 2: std->id = V4L2_STD_SECAM; - strncpy(std->name, "SECAM", 31); + strncpy(std->name, "SECAM", sizeof(std->name)-1); std->frameperiod.numerator = 1; std->frameperiod.denominator = 25; std->framelines = zr->card.tvn[2]->Ht; @@ -3871,7 +3872,7 @@ #ifdef HAVE_V4L2 memset(outp, 0, sizeof(*outp)); outp->index = 0; outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; - strncpy(outp->name, "Autodetect", 31); + strncpy(outp->name, "Autodetect", sizeof(outp->name)-1); return 0; } diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c index a00fae9..f4ffe79 100644 --- a/drivers/media/video/zoran_procfs.c +++ b/drivers/media/video/zoran_procfs.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "videocodec.h" diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index a300840..12dd8d4 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -63,9 +63,6 @@ #include #ifdef CONFIG_MTRR #include #endif -#ifdef __sparc__ -#include /* needed for __irq_itoa() proto */ -#endif #include "mptbase.h" @@ -1188,7 +1185,6 @@ #endif ioc->pcidev = pdev; ioc->diagPending = 0; spin_lock_init(&ioc->diagLock); - spin_lock_init(&ioc->fc_rescan_work_lock); spin_lock_init(&ioc->initializing_hba_lock); /* Initialize the event logging. @@ -1386,39 +1382,6 @@ #endif /* Set lookup ptr. */ list_add_tail(&ioc->list, &ioc_list); - ioc->pci_irq = -1; - if (pdev->irq) { - if (mpt_msi_enable && !pci_enable_msi(pdev)) - printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name); - - r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc); - - if (r < 0) { -#ifndef __sparc__ - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n", - ioc->name, pdev->irq); -#else - printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n", - ioc->name, __irq_itoa(pdev->irq)); -#endif - list_del(&ioc->list); - iounmap(mem); - kfree(ioc); - return -EBUSY; - } - - ioc->pci_irq = pdev->irq; - - pci_set_master(pdev); /* ?? */ - pci_set_drvdata(pdev, ioc); - -#ifndef __sparc__ - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq)); -#else - dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq))); -#endif - } - /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. */ mpt_detect_bound_ports(ioc, pdev); @@ -1428,11 +1391,7 @@ #endif printk(KERN_WARNING MYNAM ": WARNING - %s did not initialize properly! (%d)\n", ioc->name, r); - list_del(&ioc->list); - free_irq(ioc->pci_irq, ioc); - if (mpt_msi_enable) - pci_disable_msi(pdev); if (ioc->alt_ioc) ioc->alt_ioc->alt_ioc = NULL; iounmap(mem); @@ -1651,6 +1610,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3 int handlers; int ret = 0; int reset_alt_ioc_active = 0; + int irq_allocated = 0; printk(KERN_INFO MYNAM ": Initiating %s %s\n", ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); @@ -1734,6 +1694,36 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3 } } + /* + * Device is reset now. It must have de-asserted the interrupt line + * (if it was asserted) and it should be safe to register for the + * interrupt now. + */ + if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { + ioc->pci_irq = -1; + if (ioc->pcidev->irq) { + if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev)) + printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", + ioc->name); + rc = request_irq(ioc->pcidev->irq, mpt_interrupt, + SA_SHIRQ, ioc->name, ioc); + if (rc < 0) { + printk(MYIOC_s_ERR_FMT "Unable to allocate " + "interrupt %d!\n", ioc->name, + ioc->pcidev->irq); + if (mpt_msi_enable) + pci_disable_msi(ioc->pcidev); + return -EBUSY; + } + irq_allocated = 1; + ioc->pci_irq = ioc->pcidev->irq; + pci_set_master(ioc->pcidev); /* ?? */ + pci_set_drvdata(ioc->pcidev, ioc); + dprintk((KERN_INFO MYNAM ": %s installed at interrupt " + "%d\n", ioc->name, ioc->pcidev->irq)); + } + } + /* Prime reply & request queues! * (mucho alloc's) Must be done prior to * init as upper addresses are needed for init. @@ -1833,7 +1823,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3 ret = mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); if(ret != 0) - return -1; + goto out; } /* Find IM volumes @@ -1841,14 +1831,6 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3 mpt_findImVolumes(ioc); } else if (ioc->bus_type == FC) { - /* - * Pre-fetch FC port WWN and stuff... - * (FCPortPage0_t stuff) - */ - for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) mptbase_GetFcPortPage0(ioc, ii); - } - if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) && (ioc->lan_cnfg_page0.Header.PageLength == 0)) { /* @@ -1914,6 +1896,12 @@ #endif /* FIXME? Examine results here? */ } +out: + if ((ret != 0) && irq_allocated) { + free_irq(ioc->pci_irq, ioc); + if (mpt_msi_enable) + pci_disable_msi(ioc->pcidev); + } return ret; } @@ -2288,7 +2276,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay (1); /* 1 msec delay */ } @@ -2676,7 +2664,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF state = mpt_GetIocState(ioc, 1); while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) { if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay(1); } @@ -2928,7 +2916,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw /* wait 1 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay (1); } @@ -2945,7 +2933,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw } /* wait .1 sec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (100); + msleep (100); } else { mdelay (100); } @@ -3035,7 +3023,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw /* wait 1 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1); + msleep (1); } else { mdelay (1); } @@ -3083,7 +3071,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw return 0; } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (10); + msleep (10); } else { mdelay (10); } @@ -3134,7 +3122,7 @@ KickStart(MPT_ADAPTER *ioc, int force, i SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1000); + msleep (1000); } else { mdelay (1000); } @@ -3156,7 +3144,7 @@ KickStart(MPT_ADAPTER *ioc, int force, i return hard_reset_done; } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (10); + msleep (10); } else { mdelay (10); } @@ -3227,7 +3215,7 @@ #endif /* wait 100 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (100); + msleep (100); } else { mdelay (100); } @@ -3306,7 +3294,7 @@ #endif /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1000); + msleep (1000); } else { mdelay (1000); } @@ -3334,7 +3322,7 @@ #endif /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1000); + msleep (1000); } else { mdelay (1000); } @@ -3368,7 +3356,7 @@ #endif /* wait 100 msec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (100); + msleep (100); } else { mdelay (100); } @@ -3462,7 +3450,7 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_ } if (sleepFlag == CAN_SLEEP) { - msleep_interruptible(1); + msleep(1); } else { mdelay (1); /* 1 msec delay */ } @@ -3902,7 +3890,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) break; - msleep_interruptible (1); + msleep (1); count++; } } else { @@ -3951,7 +3939,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int intstat = CHIPREG_READ32(&ioc->chip->IntStatus); if (intstat & MPI_HIS_DOORBELL_INTERRUPT) break; - msleep_interruptible(1); + msleep(1); count++; } } else { @@ -4174,108 +4162,6 @@ GetLanConfigPages(MPT_ADAPTER *ioc) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* - * mptbase_GetFcPortPage0 - Fetch FCPort config Page0. - * @ioc: Pointer to MPT_ADAPTER structure - * @portnum: IOC Port number - * - * Return: 0 for success - * -ENOMEM if no memory available - * -EPERM if not allowed due to ISR context - * -EAGAIN if no msg frames currently available - * -EFAULT for non-successful reply or no reply (timeout) - */ -int -mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) -{ - ConfigPageHeader_t hdr; - CONFIGPARMS cfg; - FCPortPage0_t *ppage0_alloc; - FCPortPage0_t *pp0dest; - dma_addr_t page0_dma; - int data_sz; - int copy_sz; - int rc; - int count = 400; - - - /* Get FCPort Page 0 header */ - hdr.PageVersion = 0; - hdr.PageLength = 0; - hdr.PageNumber = 0; - hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; - cfg.cfghdr.hdr = &hdr; - cfg.physAddr = -1; - cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; - cfg.pageAddr = portnum; - cfg.timeout = 0; - - if ((rc = mpt_config(ioc, &cfg)) != 0) - return rc; - - if (hdr.PageLength == 0) - return 0; - - data_sz = hdr.PageLength * 4; - rc = -ENOMEM; - ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); - if (ppage0_alloc) { - - try_again: - memset((u8 *)ppage0_alloc, 0, data_sz); - cfg.physAddr = page0_dma; - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - - if ((rc = mpt_config(ioc, &cfg)) == 0) { - /* save the data */ - pp0dest = &ioc->fc_port_page0[portnum]; - copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz); - memcpy(pp0dest, ppage0_alloc, copy_sz); - - /* - * Normalize endianness of structure data, - * by byte-swapping all > 1 byte fields! - */ - pp0dest->Flags = le32_to_cpu(pp0dest->Flags); - pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier); - pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low); - pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High); - pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low); - pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High); - pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass); - pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds); - pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed); - pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize); - pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low); - pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High); - pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low); - pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High); - pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); - pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); - - /* - * if still doing discovery, - * hang loose a while until finished - */ - if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { - if (count-- > 0) { - msleep_interruptible(100); - goto try_again; - } - printk(MYIOC_s_INFO_FMT "Firmware discovery not" - " complete.\n", - ioc->name); - } - } - - pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); - } - - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table * @ioc: Pointer to MPT_ADAPTER structure * @sas_address: 64bit SAS Address for operation. @@ -5647,11 +5533,7 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, a[5], a[4], a[3], a[2], a[1], a[0]); } -#ifndef __sparc__ y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq); -#else - y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq)); -#endif if (!ioc->active) y += sprintf(buffer+len+y, " (disabled)"); @@ -6483,7 +6365,6 @@ EXPORT_SYMBOL(mpt_findImVolumes); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mptbase_sas_persist_operation); -EXPORT_SYMBOL(mptbase_GetFcPortPage0); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index f673cca..4720f9a 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -76,8 +76,8 @@ #ifndef COPYRIGHT #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.03.09" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.09" +#define MPT_LINUX_VERSION_COMMON "3.03.10" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.10" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -487,6 +487,15 @@ typedef struct _RaidCfgData { int isRaid; /* bit field, 1 if RAID */ }RaidCfgData; +typedef struct _FcCfgData { + /* will ultimately hold fc_port_page0 also */ + struct { + FCPortPage1_t *data; + dma_addr_t dma; + int pg_sz; + } fc_port_page1[2]; +} FcCfgData; + #define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */ #define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */ @@ -565,6 +574,7 @@ typedef struct _MPT_ADAPTER SpiCfgData spi_data; /* Scsi config. data */ RaidCfgData raid_data; /* Raid config. data */ SasCfgData sas_data; /* Sas config. data */ + FcCfgData fc_data; /* Fc config. data */ MPT_IOCTL *ioctl; /* ioctl data pointer */ struct proc_dir_entry *ioc_dentry; struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ @@ -625,6 +635,7 @@ #endif int num_ports; struct work_struct mptscsih_persistTask; + struct work_struct fc_setup_reset_work; struct list_head fc_rports; spinlock_t fc_rescan_work_lock; int fc_rescan_work_count; @@ -1027,7 +1038,6 @@ extern void mpt_alloc_fw_memory(MPT_ADA extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); extern int mpt_findImVolumes(MPT_ADAPTER *ioc); extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); -extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); /* * Public data decl's... diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 8564877..74714e5 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -169,13 +169,6 @@ static struct fc_function_template mptfc }; -/* FIXME! values controlling firmware RESCAN event - * need to be set low to allow dev_loss_tmo to - * work as expected. Currently, firmware doesn't - * notify driver of RESCAN event until some number - * of seconds elapse. This value can be set via - * lsiutil. - */ static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) { @@ -587,15 +580,266 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void #ifdef DMPT_DEBUG_FC if (unlikely(err)) { dfcprintk ((MYIOC_s_INFO_FMT - "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n", + "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n", ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name, ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no, - SCpnt->device->id,SCpnt->device->lun)); + SCpnt->device->id,SCpnt->device->lun,err)); } #endif return err; } +/* + * mptfc_GetFcPortPage0 - Fetch FCPort config Page0. + * @ioc: Pointer to MPT_ADAPTER structure + * @portnum: IOC Port number + * + * Return: 0 for success + * -ENOMEM if no memory available + * -EPERM if not allowed due to ISR context + * -EAGAIN if no msg frames currently available + * -EFAULT for non-successful reply or no reply (timeout) + * -EINVAL portnum arg out of range (hardwired to two elements) + */ +static int +mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) +{ + ConfigPageHeader_t hdr; + CONFIGPARMS cfg; + FCPortPage0_t *ppage0_alloc; + FCPortPage0_t *pp0dest; + dma_addr_t page0_dma; + int data_sz; + int copy_sz; + int rc; + int count = 400; + + if (portnum > 1) + return -EINVAL; + + /* Get FCPort Page 0 header */ + hdr.PageVersion = 0; + hdr.PageLength = 0; + hdr.PageNumber = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + cfg.pageAddr = portnum; + cfg.timeout = 0; + + if ((rc = mpt_config(ioc, &cfg)) != 0) + return rc; + + if (hdr.PageLength == 0) + return 0; + + data_sz = hdr.PageLength * 4; + rc = -ENOMEM; + ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); + if (ppage0_alloc) { + + try_again: + memset((u8 *)ppage0_alloc, 0, data_sz); + cfg.physAddr = page0_dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if ((rc = mpt_config(ioc, &cfg)) == 0) { + /* save the data */ + pp0dest = &ioc->fc_port_page0[portnum]; + copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz); + memcpy(pp0dest, ppage0_alloc, copy_sz); + + /* + * Normalize endianness of structure data, + * by byte-swapping all > 1 byte fields! + */ + pp0dest->Flags = le32_to_cpu(pp0dest->Flags); + pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier); + pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low); + pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High); + pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low); + pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High); + pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass); + pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds); + pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed); + pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize); + pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low); + pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High); + pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low); + pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High); + pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); + pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); + + /* + * if still doing discovery, + * hang loose a while until finished + */ + if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { + if (count-- > 0) { + msleep(100); + goto try_again; + } + printk(MYIOC_s_INFO_FMT "Firmware discovery not" + " complete.\n", + ioc->name); + } + } + + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); + } + + return rc; +} + +static int +mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum) +{ + ConfigPageHeader_t hdr; + CONFIGPARMS cfg; + int rc; + + if (portnum > 1) + return -EINVAL; + + if (!(ioc->fc_data.fc_port_page1[portnum].data)) + return -EINVAL; + + /* get fcport page 1 header */ + hdr.PageVersion = 0; + hdr.PageLength = 0; + hdr.PageNumber = 1; + hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + cfg.pageAddr = portnum; + cfg.timeout = 0; + + if ((rc = mpt_config(ioc, &cfg)) != 0) + return rc; + + if (hdr.PageLength == 0) + return -ENODEV; + + if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz) + return -EINVAL; + + cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + cfg.dir = 1; + + rc = mpt_config(ioc, &cfg); + + return rc; +} + +static int +mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum) +{ + ConfigPageHeader_t hdr; + CONFIGPARMS cfg; + FCPortPage1_t *page1_alloc; + dma_addr_t page1_dma; + int data_sz; + int rc; + + if (portnum > 1) + return -EINVAL; + + /* get fcport page 1 header */ + hdr.PageVersion = 0; + hdr.PageLength = 0; + hdr.PageNumber = 1; + hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; + cfg.cfghdr.hdr = &hdr; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + cfg.pageAddr = portnum; + cfg.timeout = 0; + + if ((rc = mpt_config(ioc, &cfg)) != 0) + return rc; + + if (hdr.PageLength == 0) + return -ENODEV; + +start_over: + + if (ioc->fc_data.fc_port_page1[portnum].data == NULL) { + data_sz = hdr.PageLength * 4; + if (data_sz < sizeof(FCPortPage1_t)) + data_sz = sizeof(FCPortPage1_t); + + page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev, + data_sz, + &page1_dma); + if (!page1_alloc) + return -ENOMEM; + } + else { + page1_alloc = ioc->fc_data.fc_port_page1[portnum].data; + page1_dma = ioc->fc_data.fc_port_page1[portnum].dma; + data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz; + if (hdr.PageLength * 4 > data_sz) { + ioc->fc_data.fc_port_page1[portnum].data = NULL; + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) + page1_alloc, page1_dma); + goto start_over; + } + } + + memset(page1_alloc,0,data_sz); + + cfg.physAddr = page1_dma; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + if ((rc = mpt_config(ioc, &cfg)) == 0) { + ioc->fc_data.fc_port_page1[portnum].data = page1_alloc; + ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz; + ioc->fc_data.fc_port_page1[portnum].dma = page1_dma; + } + else { + ioc->fc_data.fc_port_page1[portnum].data = NULL; + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) + page1_alloc, page1_dma); + } + + return rc; +} + +static void +mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc) +{ + int ii; + FCPortPage1_t *pp1; + + #define MPTFC_FW_DEVICE_TIMEOUT (1) + #define MPTFC_FW_IO_PEND_TIMEOUT (1) + #define ON_FLAGS (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY) + #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS) + + for (ii=0; iifacts.NumberOfPorts; ii++) { + if (mptfc_GetFcPortPage1(ioc, ii) != 0) + continue; + pp1 = ioc->fc_data.fc_port_page1[ii].data; + if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT) + && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT) + && ((pp1->Flags & ON_FLAGS) == ON_FLAGS) + && ((pp1->Flags & OFF_FLAGS) == 0)) + continue; + pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT; + pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT; + pp1->Flags &= ~OFF_FLAGS; + pp1->Flags |= ON_FLAGS; + mptfc_WriteFcPortPage1(ioc, ii); + } +} + + static void mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) { @@ -629,6 +873,31 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,in } static void +mptfc_setup_reset(void *arg) +{ + MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + u64 pn; + struct mptfc_rport_info *ri; + + /* reset about to happen, delete (block) all rports */ + list_for_each_entry(ri, &ioc->fc_rports, list) { + if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { + ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED; + fc_remote_port_delete(ri->rport); /* won't sleep */ + ri->rport = NULL; + + pn = (u64)ri->pg0.WWPN.High << 32 | + (u64)ri->pg0.WWPN.Low; + dfcprintk ((MYIOC_s_INFO_FMT + "mptfc_setup_reset.%d: %llx deleted\n", + ioc->name, + ioc->sh->host_no, + (unsigned long long)pn)); + } + } +} + +static void mptfc_rescan_devices(void *arg) { MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; @@ -651,7 +920,7 @@ mptfc_rescan_devices(void *arg) * will reregister existing rports */ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) mptbase_GetFcPortPage0(ioc, ii); + (void) mptfc_GetFcPortPage0(ioc, ii); mptfc_init_host_attr(ioc,ii); /* refresh */ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); } @@ -753,7 +1022,9 @@ mptfc_probe(struct pci_dev *pdev, const goto out_mptfc_probe; } + spin_lock_init(&ioc->fc_rescan_work_lock); INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); + INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc); spin_lock_irqsave(&ioc->FreeQlock, flags); @@ -889,6 +1160,15 @@ mptfc_probe(struct pci_dev *pdev, const goto out_mptfc_probe; /* + * Pre-fetch FC port WWN and stuff... + * (FCPortPage0_t stuff) + */ + for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { + (void) mptfc_GetFcPortPage0(ioc, ii); + } + mptfc_SetFcPortPage1_defaults(ioc); + + /* * scan for rports - * by doing it via the workqueue, some locking is eliminated */ @@ -917,6 +1197,81 @@ #ifdef CONFIG_PM #endif }; +static int +mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) +{ + MPT_SCSI_HOST *hd; + u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; + unsigned long flags; + int rc=1; + + devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", + ioc->name, event)); + + if (ioc->sh == NULL || + ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) + return 1; + + switch (event) { + case MPI_EVENT_RESCAN: + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_q) { + if (ioc->fc_rescan_work_count++ == 0) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_rescan_work); + } + } + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + break; + default: + rc = mptscsih_event_process(ioc,pEvReply); + break; + } + return rc; +} + +static int +mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) +{ + int rc; + unsigned long flags; + + rc = mptscsih_ioc_reset(ioc,reset_phase); + if (rc == 0) + return rc; + + + dtmprintk((KERN_WARNING MYNAM + ": IOC %s_reset routed to FC host driver!\n", + reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); + + if (reset_phase == MPT_IOC_SETUP_RESET) { + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_q) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_setup_reset_work); + } + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + } + + else if (reset_phase == MPT_IOC_PRE_RESET) { + } + + else { /* MPT_IOC_POST_RESET */ + mptfc_SetFcPortPage1_defaults(ioc); + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_q) { + if (ioc->fc_rescan_work_count++ == 0) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_rescan_work); + } + } + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + } + return 1; +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptfc_init - Register MPT adapter(s) as SCSI host(s) with @@ -931,8 +1286,8 @@ mptfc_init(void) show_mptmod_ver(my_NAME, my_VERSION); - /* sanity check module parameter */ - if (mptfc_dev_loss_tmo == 0) + /* sanity check module parameters */ + if (mptfc_dev_loss_tmo <= 0) mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; mptfc_transport_template = @@ -945,12 +1300,12 @@ mptfc_init(void) mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); - if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { + if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) { devtverboseprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } - if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) { + if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) { dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); } @@ -975,6 +1330,7 @@ mptfc_remove(struct pci_dev *pdev) struct mptfc_rport_info *p, *n; struct workqueue_struct *work_q; unsigned long flags; + int ii; /* destroy workqueue */ if ((work_q=ioc->fc_rescan_work_q)) { @@ -991,6 +1347,16 @@ mptfc_remove(struct pci_dev *pdev) kfree(p); } + for (ii=0; iifacts.NumberOfPorts; ii++) { + if (ioc->fc_data.fc_port_page1[ii].data) { + pci_free_consistent(ioc->pcidev, + ioc->fc_data.fc_port_page1[ii].pg_sz, + (u8 *) ioc->fc_data.fc_port_page1[ii].data, + ioc->fc_data.fc_port_page1[ii].dma); + ioc->fc_data.fc_port_page1[ii].data = NULL; + } + } + mptscsih_remove(pdev); } diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 84fa271..8242b16 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1922,7 +1922,7 @@ mptscsih_tm_wait_for_completion(MPT_SCSI break; } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - msleep_interruptible(250); + msleep(250); } while (--loop_count); return status; @@ -2521,18 +2521,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int hd->cmdPtr = NULL; } - /* 7. FC: Rescan for blocked rports which might have returned. - */ - if (ioc->bus_type == FC) { - spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); - if (ioc->fc_rescan_work_q) { - if (ioc->fc_rescan_work_count++ == 0) { - queue_work(ioc->fc_rescan_work_q, - &ioc->fc_rescan_work); - } - } - spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); - } dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); } @@ -2546,7 +2534,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, { MPT_SCSI_HOST *hd; u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; - unsigned long flags; devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); @@ -2569,14 +2556,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, break; case MPI_EVENT_RESCAN: /* 06 */ - spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); - if (ioc->fc_rescan_work_q) { - if (ioc->fc_rescan_work_count++ == 0) { - queue_work(ioc->fc_rescan_work_q, - &ioc->fc_rescan_work); - } - } - spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); break; /* diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index c08ddac..6ebf382 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -65,9 +65,7 @@ #include #include #include #include -#include #include -#include #define OSM_NAME "scsi-osm" #define OSM_VERSION "1.316" @@ -588,6 +586,7 @@ static int i2o_scsi_queuecommand(struct mptr = &msg->body[0]; +#if 0 /* this code can't work */ #ifdef CONFIG_I2O_EXT_ADAPTEC if (c->adaptec) { u32 adpt_flags = 0; @@ -625,6 +624,7 @@ #ifdef CONFIG_I2O_EXT_ADAPTEC *mptr++ = cpu_to_le32(adpt_flags | tid); } #endif +#endif msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); msg->u.s.icntxt = cpu_to_le32(i2o_scsi_driver.context); diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index aff83f9..c8426a9 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -420,8 +420,10 @@ static int ucb1x00_detect_irq(struct ucb unsigned long mask; mask = probe_irq_on(); - if (!mask) + if (!mask) { + probe_irq_off(mask); return NO_IRQ; + } /* * Enable the ADC interrupt. diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index 26a230b..4a35caf 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c @@ -90,10 +90,11 @@ static void ibmasmfs_create_files (struc static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent); -static struct super_block *ibmasmfs_get_super(struct file_system_type *fst, - int flags, const char *name, void *data) +static int ibmasmfs_get_super(struct file_system_type *fst, + int flags, const char *name, void *data, + struct vfsmount *mnt) { - return get_sb_single(fst, flags, data, ibmasmfs_fill_super); + return get_sb_single(fst, flags, data, ibmasmfs_fill_super, mnt); } static struct super_operations ibmasmfs_s_ops = { diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index 88f0eef..3228516 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c @@ -81,13 +81,6 @@ #define DRIVER_NAME "at91_mci" #undef SUPPORT_4WIRE -#ifdef CONFIG_MMC_DEBUG -#define DBG(fmt...) \ - printk(fmt) -#else -#define DBG(fmt...) do { } while (0) -#endif - static struct clk *mci_clk; #define FL_SENT_COMMAND (1 << 0) @@ -202,50 +195,50 @@ static void at91mci_pre_dma_read(struct struct mmc_command *cmd; struct mmc_data *data; - DBG("pre dma read\n"); + pr_debug("pre dma read\n"); cmd = host->cmd; if (!cmd) { - DBG("no command\n"); + pr_debug("no command\n"); return; } data = cmd->data; if (!data) { - DBG("no data\n"); + pr_debug("no data\n"); return; } for (i = 0; i < 2; i++) { /* nothing left to transfer */ if (host->transfer_index >= data->sg_len) { - DBG("Nothing left to transfer (index = %d)\n", host->transfer_index); + pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index); break; } /* Check to see if this needs filling */ if (i == 0) { if (at91_mci_read(AT91_PDC_RCR) != 0) { - DBG("Transfer active in current\n"); + pr_debug("Transfer active in current\n"); continue; } } else { if (at91_mci_read(AT91_PDC_RNCR) != 0) { - DBG("Transfer active in next\n"); + pr_debug("Transfer active in next\n"); continue; } } /* Setup the next transfer */ - DBG("Using transfer index %d\n", host->transfer_index); + pr_debug("Using transfer index %d\n", host->transfer_index); sg = &data->sg[host->transfer_index++]; - DBG("sg = %p\n", sg); + pr_debug("sg = %p\n", sg); sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE); - DBG("dma address = %08X, length = %d\n", sg->dma_address, sg->length); + pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length); if (i == 0) { at91_mci_write(AT91_PDC_RPR, sg->dma_address); @@ -257,7 +250,7 @@ static void at91mci_pre_dma_read(struct } } - DBG("pre dma read done\n"); + pr_debug("pre dma read done\n"); } /* @@ -268,17 +261,17 @@ static void at91mci_post_dma_read(struct struct mmc_command *cmd; struct mmc_data *data; - DBG("post dma read\n"); + pr_debug("post dma read\n"); cmd = host->cmd; if (!cmd) { - DBG("no command\n"); + pr_debug("no command\n"); return; } data = cmd->data; if (!data) { - DBG("no data\n"); + pr_debug("no data\n"); return; } @@ -289,17 +282,17 @@ static void at91mci_post_dma_read(struct struct scatterlist *sg; - DBG("finishing index %d\n", host->in_use_index); + pr_debug("finishing index %d\n", host->in_use_index); sg = &data->sg[host->in_use_index++]; - DBG("Unmapping page %08X\n", sg->dma_address); + pr_debug("Unmapping page %08X\n", sg->dma_address); dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE); /* Swap the contents of the buffer */ buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; - DBG("buffer = %p, length = %d\n", buffer, sg->length); + pr_debug("buffer = %p, length = %d\n", buffer, sg->length); data->bytes_xfered += sg->length; @@ -320,7 +313,7 @@ static void at91mci_post_dma_read(struct at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); } - DBG("post dma read done\n"); + pr_debug("post dma read done\n"); } /* @@ -331,7 +324,7 @@ static void at91_mci_handle_transmitted( struct mmc_command *cmd; struct mmc_data *data; - DBG("Handling the transmit\n"); + pr_debug("Handling the transmit\n"); /* Disable the transfer */ at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS); @@ -387,12 +380,12 @@ static unsigned int at91_mci_send_comman /* Not sure if this is needed */ #if 0 if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) { - DBG("Clearing timeout\n"); + pr_debug("Clearing timeout\n"); at91_mci_write(AT91_MCI_ARGR, 0); at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD); while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) { /* spin */ - DBG("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR)); + pr_debug("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR)); } } #endif @@ -411,7 +404,7 @@ #endif } if (data) { - block_length = 1 << data->blksz_bits; + block_length = data->blksz; blocks = data->blocks; /* always set data start - also set direction flag for read */ @@ -439,7 +432,7 @@ #endif /* * Set the arguments and send the command */ - DBG("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n", + pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n", cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR)); if (!data) { @@ -491,7 +484,7 @@ #endif at91mci_sg_to_dma(host, data); - DBG("Transmitting %d bytes\n", host->total_length); + pr_debug("Transmitting %d bytes\n", host->total_length); at91_mci_write(AT91_PDC_TPR, host->physical_address); at91_mci_write(AT91_PDC_TCR, host->total_length / 4); @@ -525,7 +518,7 @@ static void at91mci_process_command(stru ier = at91_mci_send_command(host, cmd); - DBG("setting ier to %08X\n", ier); + pr_debug("setting ier to %08X\n", ier); /* Stop on errors or the required value */ at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier); @@ -570,7 +563,7 @@ static void at91mci_completed_command(st status = at91_mci_read(AT91_MCI_SR); - DBG("Status = %08X [%08X %08X %08X %08X]\n", + pr_debug("Status = %08X [%08X %08X %08X %08X]\n", status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE | @@ -590,7 +583,7 @@ static void at91mci_completed_command(st else cmd->error = MMC_ERR_FAILED; - DBG("Error detected and set to %d (cmd = %d, retries = %d)\n", + pr_debug("Error detected and set to %d (cmd = %d, retries = %d)\n", cmd->error, cmd->opcode, cmd->retries); } } @@ -621,10 +614,7 @@ static void at91_mci_set_ios(struct mmc_ struct at91mci_host *host = mmc_priv(mmc); unsigned long at91_master_clock = clk_get_rate(mci_clk); - if (host) - host->bus_mode = ios->bus_mode; - else - printk("MMC: No host for bus_mode\n"); + host->bus_mode = ios->bus_mode; if (ios->clock == 0) { /* Disable the MCI controller */ @@ -640,15 +630,15 @@ static void at91_mci_set_ios(struct mmc_ else clkdiv = (at91_master_clock / ios->clock) / 2; - DBG("clkdiv = %d. mcck = %ld\n", clkdiv, + pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv, at91_master_clock / (2 * (clkdiv + 1))); } if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) { - DBG("MMC: Setting controller bus width to 4\n"); + pr_debug("MMC: Setting controller bus width to 4\n"); at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS); } else { - DBG("MMC: Setting controller bus width to 1\n"); + pr_debug("MMC: Setting controller bus width to 1\n"); at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); } @@ -656,7 +646,7 @@ static void at91_mci_set_ios(struct mmc_ at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv); /* maybe switch power to the card */ - if (host && host->board->vcc_pin) { + if (host->board->vcc_pin) { switch (ios->power_mode) { case MMC_POWER_OFF: at91_set_gpio_output(host->board->vcc_pin, 0); @@ -679,11 +669,8 @@ static irqreturn_t at91_mci_irq(int irq, unsigned int int_status; - if (host == NULL) - return IRQ_HANDLED; - int_status = at91_mci_read(AT91_MCI_SR); - DBG("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR), + pr_debug("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR), int_status & at91_mci_read(AT91_MCI_IMR)); if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000) @@ -692,75 +679,75 @@ static irqreturn_t at91_mci_irq(int irq, int_status &= at91_mci_read(AT91_MCI_IMR); if (int_status & AT91_MCI_UNRE) - DBG("MMC: Underrun error\n"); + pr_debug("MMC: Underrun error\n"); if (int_status & AT91_MCI_OVRE) - DBG("MMC: Overrun error\n"); + pr_debug("MMC: Overrun error\n"); if (int_status & AT91_MCI_DTOE) - DBG("MMC: Data timeout\n"); + pr_debug("MMC: Data timeout\n"); if (int_status & AT91_MCI_DCRCE) - DBG("MMC: CRC error in data\n"); + pr_debug("MMC: CRC error in data\n"); if (int_status & AT91_MCI_RTOE) - DBG("MMC: Response timeout\n"); + pr_debug("MMC: Response timeout\n"); if (int_status & AT91_MCI_RENDE) - DBG("MMC: Response end bit error\n"); + pr_debug("MMC: Response end bit error\n"); if (int_status & AT91_MCI_RCRCE) - DBG("MMC: Response CRC error\n"); + pr_debug("MMC: Response CRC error\n"); if (int_status & AT91_MCI_RDIRE) - DBG("MMC: Response direction error\n"); + pr_debug("MMC: Response direction error\n"); if (int_status & AT91_MCI_RINDE) - DBG("MMC: Response index error\n"); + pr_debug("MMC: Response index error\n"); /* Only continue processing if no errors */ if (!completed) { if (int_status & AT91_MCI_TXBUFE) { - DBG("TX buffer empty\n"); + pr_debug("TX buffer empty\n"); at91_mci_handle_transmitted(host); } if (int_status & AT91_MCI_RXBUFF) { - DBG("RX buffer full\n"); + pr_debug("RX buffer full\n"); at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY); } if (int_status & AT91_MCI_ENDTX) { - DBG("Transmit has ended\n"); + pr_debug("Transmit has ended\n"); } if (int_status & AT91_MCI_ENDRX) { - DBG("Receive has ended\n"); + pr_debug("Receive has ended\n"); at91mci_post_dma_read(host); } if (int_status & AT91_MCI_NOTBUSY) { - DBG("Card is ready\n"); + pr_debug("Card is ready\n"); at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY); } if (int_status & AT91_MCI_DTIP) { - DBG("Data transfer in progress\n"); + pr_debug("Data transfer in progress\n"); } if (int_status & AT91_MCI_BLKE) { - DBG("Block transfer has ended\n"); + pr_debug("Block transfer has ended\n"); } if (int_status & AT91_MCI_TXRDY) { - DBG("Ready to transmit\n"); + pr_debug("Ready to transmit\n"); } if (int_status & AT91_MCI_RXRDY) { - DBG("Ready to receive\n"); + pr_debug("Ready to receive\n"); } if (int_status & AT91_MCI_CMDRDY) { - DBG("Command ready\n"); + pr_debug("Command ready\n"); completed = 1; } } at91_mci_write(AT91_MCI_IDR, int_status); if (completed) { - DBG("Completed command\n"); + pr_debug("Completed command\n"); at91_mci_write(AT91_MCI_IDR, 0xffffffff); at91mci_completed_command(host); } @@ -779,10 +766,10 @@ static irqreturn_t at91_mmc_det_irq(int */ if (present != host->present) { host->present = present; - DBG("%s: card %s\n", mmc_hostname(host->mmc), + pr_debug("%s: card %s\n", mmc_hostname(host->mmc), present ? "insert" : "remove"); if (!present) { - DBG("****** Resetting SD-card bus width ******\n"); + pr_debug("****** Resetting SD-card bus width ******\n"); at91_mci_write(AT91_MCI_SDCR, 0); } mmc_detect_change(host->mmc, msecs_to_jiffies(100)); @@ -822,13 +809,13 @@ static int at91_mci_probe(struct platfor struct at91mci_host *host; int ret; - DBG("Probe MCI devices\n"); + pr_debug("Probe MCI devices\n"); at91_mci_disable(); at91_mci_enable(); mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); if (!mmc) { - DBG("Failed to allocate mmc host\n"); + pr_debug("Failed to allocate mmc host\n"); return -ENOMEM; } @@ -854,8 +841,9 @@ #endif * Get Clock */ mci_clk = clk_get(&pdev->dev, "mci_clk"); - if (!mci_clk) { + if (IS_ERR(mci_clk)) { printk(KERN_ERR "AT91 MMC: no clock defined.\n"); + mmc_free_host(mmc); return -ENODEV; } clk_enable(mci_clk); /* Enable the peripheral clock */ @@ -865,7 +853,10 @@ #endif */ ret = request_irq(AT91_ID_MCI, at91_mci_irq, SA_SHIRQ, DRIVER_NAME, host); if (ret) { - DBG("Failed to request MCI interrupt\n"); + printk(KERN_ERR "Failed to request MCI interrupt\n"); + clk_disable(mci_clk); + clk_put(mci_clk); + mmc_free_host(mmc); return ret; } @@ -886,12 +877,12 @@ #endif */ if (host->board->det_pin) { ret = request_irq(host->board->det_pin, at91_mmc_det_irq, - SA_SAMPLE_RANDOM, DRIVER_NAME, host); + 0, DRIVER_NAME, host); if (ret) - DBG("couldn't allocate MMC detect irq\n"); + printk(KERN_ERR "couldn't allocate MMC detect irq\n"); } - DBG(KERN_INFO "Added MCI driver\n"); + pr_debug(KERN_INFO "Added MCI driver\n"); return 0; } @@ -924,7 +915,7 @@ static int at91_mci_remove(struct platfo platform_set_drvdata(pdev, NULL); - DBG("Removed\n"); + pr_debug("MCI Removed\n"); return 0; } diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c index a4eb1d0..5c62f4e 100644 --- a/drivers/mmc/imxmmc.c +++ b/drivers/mmc/imxmmc.c @@ -228,7 +228,7 @@ static int imxmci_busy_wait_for_status(s static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) { unsigned int nob = data->blocks; - unsigned int blksz = 1 << data->blksz_bits; + unsigned int blksz = data->blksz; unsigned int datasz = nob * blksz; int i; diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index becb3c6..c25244b 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -584,10 +584,10 @@ mmc_omap_prepare_dma(struct mmc_omap_hos int sync_dev = 0; data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA; - frame = 1 << data->blksz_bits; + frame = data->blksz; count = sg_dma_len(sg); - if ((data->blocks == 1) && (count > (1 << data->blksz_bits))) + if ((data->blocks == 1) && (count > data->blksz)) count = frame; host->dma_len = count; @@ -776,7 +776,7 @@ mmc_omap_prepare_data(struct mmc_omap_ho } - block_size = 1 << data->blksz_bits; + block_size = data->blksz; OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1); OMAP_MMC_WRITE(host->base, BLEN, block_size - 1); diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index b005328..8e9100b 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -268,7 +268,7 @@ static void sdhci_prepare_data(struct sd } DBG("blksz %04x blks %04x flags %08x\n", - 1 << data->blksz_bits, data->blocks, data->flags); + data->blksz, data->blocks, data->flags); DBG("tsac %d ms nsac %d clk\n", data->timeout_ns / 1000000, data->timeout_clks); @@ -282,7 +282,7 @@ static void sdhci_prepare_data(struct sd writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE); - writew(1 << data->blksz_bits, host->ioaddr + SDHCI_BLOCK_SIZE); + writew(data->blksz, host->ioaddr + SDHCI_BLOCK_SIZE); writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT); if (host->flags & SDHCI_USE_DMA) { @@ -294,7 +294,7 @@ static void sdhci_prepare_data(struct sd writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS); } else { - host->size = (1 << data->blksz_bits) * data->blocks; + host->size = data->blksz * data->blocks; host->cur_sg = data->sg; host->num_sg = data->sg_len; @@ -335,7 +335,7 @@ static void sdhci_finish_data(struct sdh blocks = 0; else blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT); - data->bytes_xfered = (1 << data->blksz_bits) * (data->blocks - blocks); + data->bytes_xfered = data->blksz * (data->blocks - blocks); if ((data->error == MMC_ERR_NONE) && blocks) { printk(KERN_ERR "%s: Controller signalled completion even " @@ -1073,7 +1073,7 @@ static int __devinit sdhci_probe_slot(st tasklet_init(&host->finish_tasklet, sdhci_tasklet_finish, (unsigned long)host); - setup_timer(&host->timer, sdhci_timeout_timer, (int)host); + setup_timer(&host->timer, sdhci_timeout_timer, (long)host); ret = request_irq(host->irq, sdhci_irq, SA_SHIRQ, host->slot_descr, host); diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index f6b775e..1344ad7 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -78,7 +78,7 @@ config MTD_REDBOOT_DIRECTORY_BLOCK option. The option specifies which Flash sectors holds the RedBoot - partition table. A zero or positive value gives an absolete + partition table. A zero or positive value gives an absolute erase block number. A negative value specifies a number of sectors before the end of the device. @@ -86,14 +86,14 @@ config MTD_REDBOOT_DIRECTORY_BLOCK block and "-2" means the penultimate block. config MTD_REDBOOT_PARTS_UNALLOCATED - bool " Include unallocated flash regions" + bool "Include unallocated flash regions" depends on MTD_REDBOOT_PARTS help If you need to register each unallocated flash region as a MTD 'partition', enable this option. config MTD_REDBOOT_PARTS_READONLY - bool " Force read-only for RedBoot system images" + bool "Force read-only for RedBoot system images" depends on MTD_REDBOOT_PARTS help If you need to force read-only for 'RedBoot', 'RedBoot Config' and @@ -103,7 +103,7 @@ config MTD_CMDLINE_PARTS bool "Command line partition table parsing" depends on MTD_PARTITIONS = "y" ---help--- - Allow generic configuration of the MTD paritition tables via the kernel + Allow generic configuration of the MTD partition tables via the kernel command line. Multiple flash resources are supported for hardware where different kinds of flash memory are available. diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index a7ec595..6d8f30d 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig @@ -30,7 +30,6 @@ config MTD_JEDECPROBE config MTD_GEN_PROBE tristate - select OBSOLETE_INTERMODULE config MTD_CFI_ADV_OPTIONS bool "Flash chip driver advanced configuration options" diff --git a/drivers/mtd/chips/Makefile b/drivers/mtd/chips/Makefile index 8afe309..75bc1c2 100644 --- a/drivers/mtd/chips/Makefile +++ b/drivers/mtd/chips/Makefile @@ -3,13 +3,6 @@ # linux/drivers/chips/Makefile # # $Id: Makefile.common,v 1.5 2005/11/07 11:14:22 gleixner Exp $ -# *** BIG UGLY NOTE *** -# -# The removal of get_module_symbol() and replacement with -# inter_module_register() et al has introduced a link order dependency -# here where previously there was none. We now have to ensure that -# the CFI command set drivers are linked before gen_probe.o - obj-$(CONFIG_MTD) += chipreg.o obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o obj-$(CONFIG_MTD_CFI) += cfi_probe.o diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c index 5711561..16eaca6 100644 --- a/drivers/mtd/chips/amd_flash.c +++ b/drivers/mtd/chips/amd_flash.c @@ -97,7 +97,6 @@ struct amd_flash_private { int interleave; int numchips; unsigned long chipshift; -// const char *im_name; struct flchip chips[0]; }; @@ -131,12 +130,6 @@ static struct mtd_chip_driver amd_flash_ .module = THIS_MODULE }; - - -static const char im_name[] = "amd_flash"; - - - static inline __u32 wide_read(struct map_info *map, __u32 addr) { if (map->buswidth == 1) { @@ -737,6 +730,7 @@ static struct mtd_info *amd_flash_probe( offset += dev_size; } mtd->type = MTD_NORFLASH; + mtd->writesize = 1; mtd->flags = MTD_CAP_NORFLASH; mtd->name = map->name; mtd->erase = amd_flash_erase; diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 1c074d6..0d43581 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -331,13 +331,6 @@ read_pri_intelext(struct map_info *map, return extp; } -/* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The - * addresses passed back in cfi are valid as long as the use count of - * this module is non-zero, i.e. between inter_module_get and - * inter_module_put. Keith Owens 29 Oct 2000. - */ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) { struct cfi_private *cfi = map->fldrv_priv; @@ -406,7 +399,7 @@ #endif for (i=0; i< cfi->numchips; i++) { cfi->chips[i].word_write_time = 1<cfiq->WordWriteTimeoutTyp; cfi->chips[i].buffer_write_time = 1<cfiq->BufWriteTimeoutTyp; - cfi->chips[i].erase_time = 1<cfiq->BlockEraseTimeoutTyp; + cfi->chips[i].erase_time = 1000<cfiq->BlockEraseTimeoutTyp; cfi->chips[i].ref_point_counter = 0; init_waitqueue_head(&(cfi->chips[i].wq)); } @@ -415,6 +408,11 @@ #endif return cfi_intelext_setup(mtd); } +struct mtd_info *cfi_cmdset_0003(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0001"))); +struct mtd_info *cfi_cmdset_0200(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0001"))); +EXPORT_SYMBOL_GPL(cfi_cmdset_0001); +EXPORT_SYMBOL_GPL(cfi_cmdset_0003); +EXPORT_SYMBOL_GPL(cfi_cmdset_0200); static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd) { @@ -547,12 +545,12 @@ static int cfi_intelext_partition_fixup( if (extp->MinorVersion >= '4') { struct cfi_intelext_programming_regioninfo *prinfo; prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs]; - MTD_PROGREGION_SIZE(mtd) = cfi->interleave << prinfo->ProgRegShift; + mtd->writesize = cfi->interleave << prinfo->ProgRegShift; MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid; MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid; - mtd->flags |= MTD_PROGRAM_REGIONS; + mtd->flags &= ~MTD_BIT_WRITEABLE; printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n", - map->name, MTD_PROGREGION_SIZE(mtd), + map->name, mtd->writesize, MTD_PROGREGION_CTRLMODE_VALID(mtd), MTD_PROGREGION_CTRLMODE_INVALID(mtd)); } @@ -896,26 +894,33 @@ static void __xipram xip_enable(struct m /* * When a delay is required for the flash operation to complete, the - * xip_udelay() function is polling for both the given timeout and pending - * (but still masked) hardware interrupts. Whenever there is an interrupt - * pending then the flash erase or write operation is suspended, array mode - * restored and interrupts unmasked. Task scheduling might also happen at that - * point. The CPU eventually returns from the interrupt or the call to - * schedule() and the suspended flash operation is resumed for the remaining - * of the delay period. + * xip_wait_for_operation() function is polling for both the given timeout + * and pending (but still masked) hardware interrupts. Whenever there is an + * interrupt pending then the flash erase or write operation is suspended, + * array mode restored and interrupts unmasked. Task scheduling might also + * happen at that point. The CPU eventually returns from the interrupt or + * the call to schedule() and the suspended flash operation is resumed for + * the remaining of the delay period. * * Warning: this function _will_ fool interrupt latency tracing tools. */ -static void __xipram xip_udelay(struct map_info *map, struct flchip *chip, - unsigned long adr, int usec) +static int __xipram xip_wait_for_operation( + struct map_info *map, struct flchip *chip, + unsigned long adr, int *chip_op_time ) { struct cfi_private *cfi = map->fldrv_priv; struct cfi_pri_intelext *cfip = cfi->cmdset_priv; map_word status, OK = CMD(0x80); - unsigned long suspended, start = xip_currtime(); + unsigned long usec, suspended, start, done; flstate_t oldstate, newstate; + start = xip_currtime(); + usec = *chip_op_time * 8; + if (usec == 0) + usec = 500000; + done = 0; + do { cpu_relax(); if (xip_irqpending() && cfip && @@ -932,9 +937,9 @@ static void __xipram xip_udelay(struct m * we resume the whole thing at once). Yes, it * can happen! */ + usec -= done; map_write(map, CMD(0xb0), adr); map_write(map, CMD(0x70), adr); - usec -= xip_elapsed_since(start); suspended = xip_currtime(); do { if (xip_elapsed_since(suspended) > 100000) { @@ -944,7 +949,7 @@ static void __xipram xip_udelay(struct m * This is a critical error but there * is not much we can do here. */ - return; + return -EIO; } status = map_read(map, adr); } while (!map_word_andequal(map, status, OK, OK)); @@ -1004,65 +1009,107 @@ static void __xipram xip_udelay(struct m xip_cpu_idle(); } status = map_read(map, adr); + done = xip_elapsed_since(start); } while (!map_word_andequal(map, status, OK, OK) - && xip_elapsed_since(start) < usec); -} + && done < usec); -#define UDELAY(map, chip, adr, usec) xip_udelay(map, chip, adr, usec) + return (done >= usec) ? -ETIME : 0; +} /* * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while * the flash is actively programming or erasing since we have to poll for * the operation to complete anyway. We can't do that in a generic way with * a XIP setup so do it before the actual flash operation in this case - * and stub it out from INVALIDATE_CACHE_UDELAY. + * and stub it out from INVAL_CACHE_AND_WAIT. */ #define XIP_INVAL_CACHED_RANGE(map, from, size) \ INVALIDATE_CACHED_RANGE(map, from, size) -#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec) \ - UDELAY(map, chip, cmd_adr, usec) - -/* - * Extra notes: - * - * Activating this XIP support changes the way the code works a bit. For - * example the code to suspend the current process when concurrent access - * happens is never executed because xip_udelay() will always return with the - * same chip state as it was entered with. This is why there is no care for - * the presence of add_wait_queue() or schedule() calls from within a couple - * xip_disable()'d areas of code, like in do_erase_oneblock for example. - * The queueing and scheduling are always happening within xip_udelay(). - * - * Similarly, get_chip() and put_chip() just happen to always be executed - * with chip->state set to FL_READY (or FL_XIP_WHILE_*) where flash state - * is in array mode, therefore never executing many cases therein and not - * causing any problem with XIP. - */ +#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \ + xip_wait_for_operation(map, chip, cmd_adr, p_usec) #else #define xip_disable(map, chip, adr) #define xip_enable(map, chip, adr) #define XIP_INVAL_CACHED_RANGE(x...) +#define INVAL_CACHE_AND_WAIT inval_cache_and_wait_for_operation + +static int inval_cache_and_wait_for_operation( + struct map_info *map, struct flchip *chip, + unsigned long cmd_adr, unsigned long inval_adr, int inval_len, + int *chip_op_time ) +{ + struct cfi_private *cfi = map->fldrv_priv; + map_word status, status_OK = CMD(0x80); + int z, chip_state = chip->state; + unsigned long timeo; + + spin_unlock(chip->mutex); + if (inval_len) + INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len); + if (*chip_op_time) + cfi_udelay(*chip_op_time); + spin_lock(chip->mutex); + + timeo = *chip_op_time * 8 * HZ / 1000000; + if (timeo < HZ/2) + timeo = HZ/2; + timeo += jiffies; + + z = 0; + for (;;) { + if (chip->state != chip_state) { + /* Someone's suspended the operation: sleep */ + DECLARE_WAITQUEUE(wait, current); + + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + (HZ / 2); /* FIXME */ + spin_lock(chip->mutex); + continue; + } -#define UDELAY(map, chip, adr, usec) \ -do { \ - spin_unlock(chip->mutex); \ - cfi_udelay(usec); \ - spin_lock(chip->mutex); \ -} while (0) - -#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec) \ -do { \ - spin_unlock(chip->mutex); \ - INVALIDATE_CACHED_RANGE(map, adr, len); \ - cfi_udelay(usec); \ - spin_lock(chip->mutex); \ -} while (0) + status = map_read(map, cmd_adr); + if (map_word_andequal(map, status, status_OK, status_OK)) + break; + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + map_write(map, CMD(0x70), cmd_adr); + chip->state = FL_STATUS; + return -ETIME; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + z++; + spin_unlock(chip->mutex); + cfi_udelay(1); + spin_lock(chip->mutex); + } + + if (!z) { + if (!--(*chip_op_time)) + *chip_op_time = 1; + } else if (z > 1) + ++(*chip_op_time); + + /* Done and happy. */ + chip->state = FL_STATUS; + return 0; +} #endif +#define WAIT_TIMEOUT(map, chip, adr, udelay) \ + ({ int __udelay = (udelay); \ + INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); }) + + static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) { unsigned long cmd_addr; @@ -1252,14 +1299,11 @@ static int __xipram do_write_oneword(str unsigned long adr, map_word datum, int mode) { struct cfi_private *cfi = map->fldrv_priv; - map_word status, status_OK, write_cmd; - unsigned long timeo; - int z, ret=0; + map_word status, write_cmd; + int ret=0; adr += chip->start; - /* Let's determine those according to the interleave only once */ - status_OK = CMD(0x80); switch (mode) { case FL_WRITING: write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41); @@ -1285,57 +1329,17 @@ static int __xipram do_write_oneword(str map_write(map, datum, adr); chip->state = mode; - INVALIDATE_CACHE_UDELAY(map, chip, adr, - adr, map_bankwidth(map), - chip->word_write_time); - - timeo = jiffies + (HZ/2); - z = 0; - for (;;) { - if (chip->state != mode) { - /* Someone's suspended the write. Sleep */ - DECLARE_WAITQUEUE(wait, current); - - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); - timeo = jiffies + (HZ / 2); /* FIXME */ - spin_lock(chip->mutex); - continue; - } - - status = map_read(map, adr); - if (map_word_andequal(map, status, status_OK, status_OK)) - break; - - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { - map_write(map, CMD(0x70), adr); - chip->state = FL_STATUS; - xip_enable(map, chip, adr); - printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); - ret = -EIO; - goto out; - } - - /* Latency issues. Drop the lock, wait a while and retry */ - z++; - UDELAY(map, chip, adr, 1); - } - if (!z) { - chip->word_write_time--; - if (!chip->word_write_time) - chip->word_write_time = 1; + ret = INVAL_CACHE_AND_WAIT(map, chip, adr, + adr, map_bankwidth(map), + &chip->word_write_time); + if (ret) { + xip_enable(map, chip, adr); + printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); + goto out; } - if (z > 1) - chip->word_write_time++; - - /* Done and happy. */ - chip->state = FL_STATUS; /* check for errors */ + status = map_read(map, adr); if (map_word_bitsset(map, status, CMD(0x1a))) { unsigned long chipstatus = MERGESTATUS(status); @@ -1452,9 +1456,9 @@ static int __xipram do_write_buffer(stru unsigned long *pvec_seek, int len) { struct cfi_private *cfi = map->fldrv_priv; - map_word status, status_OK, write_cmd, datum; - unsigned long cmd_adr, timeo; - int wbufsize, z, ret=0, word_gap, words; + map_word status, write_cmd, datum; + unsigned long cmd_adr; + int ret, wbufsize, word_gap, words; const struct kvec *vec; unsigned long vec_seek; @@ -1463,7 +1467,6 @@ static int __xipram do_write_buffer(stru cmd_adr = adr & ~(wbufsize-1); /* Let's determine this according to the interleave only once */ - status_OK = CMD(0x80); write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9); spin_lock(chip->mutex); @@ -1477,12 +1480,14 @@ static int __xipram do_write_buffer(stru ENABLE_VPP(map); xip_disable(map, chip, cmd_adr); - /* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set + /* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set [...], the device will not accept any more Write to Buffer commands". So we must check here and reset those bits if they're set. Otherwise we're just pissing in the wind */ - if (chip->state != FL_STATUS) + if (chip->state != FL_STATUS) { map_write(map, CMD(0x70), cmd_adr); + chip->state = FL_STATUS; + } status = map_read(map, cmd_adr); if (map_word_bitsset(map, status, CMD(0x30))) { xip_enable(map, chip, cmd_adr); @@ -1493,32 +1498,20 @@ static int __xipram do_write_buffer(stru } chip->state = FL_WRITING_TO_BUFFER; - - z = 0; - for (;;) { - map_write(map, write_cmd, cmd_adr); - + map_write(map, write_cmd, cmd_adr); + ret = WAIT_TIMEOUT(map, chip, cmd_adr, 0); + if (ret) { + /* Argh. Not ready for write to buffer */ + map_word Xstatus = map_read(map, cmd_adr); + map_write(map, CMD(0x70), cmd_adr); + chip->state = FL_STATUS; status = map_read(map, cmd_adr); - if (map_word_andequal(map, status, status_OK, status_OK)) - break; - - UDELAY(map, chip, cmd_adr, 1); - - if (++z > 20) { - /* Argh. Not ready for write to buffer */ - map_word Xstatus; - map_write(map, CMD(0x70), cmd_adr); - chip->state = FL_STATUS; - Xstatus = map_read(map, cmd_adr); - /* Odd. Clear status bits */ - map_write(map, CMD(0x50), cmd_adr); - map_write(map, CMD(0x70), cmd_adr); - xip_enable(map, chip, cmd_adr); - printk(KERN_ERR "%s: Chip not ready for buffer write. status = %lx, Xstatus = %lx\n", - map->name, status.x[0], Xstatus.x[0]); - ret = -EIO; - goto out; - } + map_write(map, CMD(0x50), cmd_adr); + map_write(map, CMD(0x70), cmd_adr); + xip_enable(map, chip, cmd_adr); + printk(KERN_ERR "%s: Chip not ready for buffer write. Xstatus = %lx, status = %lx\n", + map->name, Xstatus.x[0], status.x[0]); + goto out; } /* Figure out the number of words to write */ @@ -1573,56 +1566,19 @@ static int __xipram do_write_buffer(stru map_write(map, CMD(0xd0), cmd_adr); chip->state = FL_WRITING; - INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, - adr, len, - chip->buffer_write_time); - - timeo = jiffies + (HZ/2); - z = 0; - for (;;) { - if (chip->state != FL_WRITING) { - /* Someone's suspended the write. Sleep */ - DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); - timeo = jiffies + (HZ / 2); /* FIXME */ - spin_lock(chip->mutex); - continue; - } - - status = map_read(map, cmd_adr); - if (map_word_andequal(map, status, status_OK, status_OK)) - break; - - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { - map_write(map, CMD(0x70), cmd_adr); - chip->state = FL_STATUS; - xip_enable(map, chip, cmd_adr); - printk(KERN_ERR "%s: buffer write error (status timeout)\n", map->name); - ret = -EIO; - goto out; - } - - /* Latency issues. Drop the lock, wait a while and retry */ - z++; - UDELAY(map, chip, cmd_adr, 1); - } - if (!z) { - chip->buffer_write_time--; - if (!chip->buffer_write_time) - chip->buffer_write_time = 1; + ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, + adr, len, + &chip->buffer_write_time); + if (ret) { + map_write(map, CMD(0x70), cmd_adr); + chip->state = FL_STATUS; + xip_enable(map, chip, cmd_adr); + printk(KERN_ERR "%s: buffer write error (status timeout)\n", map->name); + goto out; } - if (z > 1) - chip->buffer_write_time++; - - /* Done and happy. */ - chip->state = FL_STATUS; /* check for errors */ + status = map_read(map, cmd_adr); if (map_word_bitsset(map, status, CMD(0x1a))) { unsigned long chipstatus = MERGESTATUS(status); @@ -1693,6 +1649,11 @@ static int cfi_intelext_writev (struct m if (chipnum == cfi->numchips) return 0; } + + /* Be nice and reschedule with the chip in a usable state for other + processes. */ + cond_resched(); + } while (len); return 0; @@ -1713,17 +1674,12 @@ static int __xipram do_erase_oneblock(st unsigned long adr, int len, void *thunk) { struct cfi_private *cfi = map->fldrv_priv; - map_word status, status_OK; - unsigned long timeo; + map_word status; int retries = 3; - DECLARE_WAITQUEUE(wait, current); - int ret = 0; + int ret; adr += chip->start; - /* Let's determine this according to the interleave only once */ - status_OK = CMD(0x80); - retry: spin_lock(chip->mutex); ret = get_chip(map, chip, adr, FL_ERASING); @@ -1745,48 +1701,15 @@ static int __xipram do_erase_oneblock(st chip->state = FL_ERASING; chip->erase_suspended = 0; - INVALIDATE_CACHE_UDELAY(map, chip, adr, - adr, len, - chip->erase_time*1000/2); - - /* FIXME. Use a timer to check this, and return immediately. */ - /* Once the state machine's known to be working I'll do that */ - - timeo = jiffies + (HZ*20); - for (;;) { - if (chip->state != FL_ERASING) { - /* Someone's suspended the erase. Sleep */ - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); - spin_lock(chip->mutex); - continue; - } - if (chip->erase_suspended) { - /* This erase was suspended and resumed. - Adjust the timeout */ - timeo = jiffies + (HZ*20); /* FIXME */ - chip->erase_suspended = 0; - } - - status = map_read(map, adr); - if (map_word_andequal(map, status, status_OK, status_OK)) - break; - - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { - map_write(map, CMD(0x70), adr); - chip->state = FL_STATUS; - xip_enable(map, chip, adr); - printk(KERN_ERR "%s: block erase error: (status timeout)\n", map->name); - ret = -EIO; - goto out; - } - - /* Latency issues. Drop the lock, wait a while and retry */ - UDELAY(map, chip, adr, 1000000/HZ); + ret = INVAL_CACHE_AND_WAIT(map, chip, adr, + adr, len, + &chip->erase_time); + if (ret) { + map_write(map, CMD(0x70), adr); + chip->state = FL_STATUS; + xip_enable(map, chip, adr); + printk(KERN_ERR "%s: block erase error: (status timeout)\n", map->name); + goto out; } /* We've broken this before. It doesn't hurt to be safe */ @@ -1815,7 +1738,6 @@ static int __xipram do_erase_oneblock(st ret = -EIO; } else if (chipstatus & 0x20 && retries--) { printk(KERN_DEBUG "block erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus); - timeo = jiffies + HZ; put_chip(map, chip, adr); spin_unlock(chip->mutex); goto retry; @@ -1921,15 +1843,11 @@ static int __xipram do_xxlock_oneblock(s { struct cfi_private *cfi = map->fldrv_priv; struct cfi_pri_intelext *extp = cfi->cmdset_priv; - map_word status, status_OK; - unsigned long timeo = jiffies + HZ; + int udelay; int ret; adr += chip->start; - /* Let's determine this according to the interleave only once */ - status_OK = CMD(0x80); - spin_lock(chip->mutex); ret = get_chip(map, chip, adr, FL_LOCKING); if (ret) { @@ -1954,41 +1872,21 @@ static int __xipram do_xxlock_oneblock(s * If Instant Individual Block Locking supported then no need * to delay. */ + udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0; - if (!extp || !(extp->FeatureSupport & (1 << 5))) - UDELAY(map, chip, adr, 1000000/HZ); - - /* FIXME. Use a timer to check this, and return immediately. */ - /* Once the state machine's known to be working I'll do that */ - - timeo = jiffies + (HZ*20); - for (;;) { - - status = map_read(map, adr); - if (map_word_andequal(map, status, status_OK, status_OK)) - break; - - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { - map_write(map, CMD(0x70), adr); - chip->state = FL_STATUS; - xip_enable(map, chip, adr); - printk(KERN_ERR "%s: block unlock error: (status timeout)\n", map->name); - put_chip(map, chip, adr); - spin_unlock(chip->mutex); - return -EIO; - } - - /* Latency issues. Drop the lock, wait a while and retry */ - UDELAY(map, chip, adr, 1); + ret = WAIT_TIMEOUT(map, chip, adr, udelay); + if (ret) { + map_write(map, CMD(0x70), adr); + chip->state = FL_STATUS; + xip_enable(map, chip, adr); + printk(KERN_ERR "%s: block unlock error: (status timeout)\n", map->name); + goto out; } - /* Done and happy. */ - chip->state = FL_STATUS; xip_enable(map, chip, adr); - put_chip(map, chip, adr); +out: put_chip(map, chip, adr); spin_unlock(chip->mutex); - return 0; + return ret; } static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len) @@ -2445,28 +2343,8 @@ static void cfi_intelext_destroy(struct kfree(mtd->eraseregions); } -static char im_name_0001[] = "cfi_cmdset_0001"; -static char im_name_0003[] = "cfi_cmdset_0003"; -static char im_name_0200[] = "cfi_cmdset_0200"; - -static int __init cfi_intelext_init(void) -{ - inter_module_register(im_name_0001, THIS_MODULE, &cfi_cmdset_0001); - inter_module_register(im_name_0003, THIS_MODULE, &cfi_cmdset_0001); - inter_module_register(im_name_0200, THIS_MODULE, &cfi_cmdset_0001); - return 0; -} - -static void __exit cfi_intelext_exit(void) -{ - inter_module_unregister(im_name_0001); - inter_module_unregister(im_name_0003); - inter_module_unregister(im_name_0200); -} - -module_init(cfi_intelext_init); -module_exit(cfi_intelext_exit); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse et al."); MODULE_DESCRIPTION("MTD chip driver for Intel/Sharp flash chips"); +MODULE_ALIAS("cfi_cmdset_0003"); +MODULE_ALIAS("cfi_cmdset_0200"); diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index aed10bd..1e01ad3 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -236,6 +236,7 @@ struct mtd_info *cfi_cmdset_0002(struct mtd->resume = cfi_amdstd_resume; mtd->flags = MTD_CAP_NORFLASH; mtd->name = map->name; + mtd->writesize = 1; if (cfi->cfi_mode==CFI_MODE_CFI){ unsigned char bootloc; @@ -326,7 +327,7 @@ #endif return cfi_amdstd_setup(mtd); } - +EXPORT_SYMBOL_GPL(cfi_cmdset_0002); static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) { @@ -1758,25 +1759,6 @@ static void cfi_amdstd_destroy(struct mt kfree(mtd->eraseregions); } -static char im_name[]="cfi_cmdset_0002"; - - -static int __init cfi_amdstd_init(void) -{ - inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002); - return 0; -} - - -static void __exit cfi_amdstd_exit(void) -{ - inter_module_unregister(im_name); -} - - -module_init(cfi_amdstd_init); -module_exit(cfi_amdstd_exit); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Crossnet Co. et al."); MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips"); diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 0807c1c..fae70a5 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -162,6 +162,7 @@ #endif return cfi_staa_setup(map); } +EXPORT_SYMBOL_GPL(cfi_cmdset_0020); static struct mtd_info *cfi_staa_setup(struct map_info *map) { @@ -237,9 +238,8 @@ static struct mtd_info *cfi_staa_setup(s mtd->unlock = cfi_staa_unlock; mtd->suspend = cfi_staa_suspend; mtd->resume = cfi_staa_resume; - mtd->flags = MTD_CAP_NORFLASH; - mtd->flags |= MTD_ECC; /* FIXME: Not all STMicro flashes have this */ - mtd->eccsize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */ + mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE; + mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */ map->fldrv = &cfi_staa_chipdrv; __module_get(THIS_MODULE); mtd->name = map->name; @@ -1410,20 +1410,4 @@ static void cfi_staa_destroy(struct mtd_ kfree(cfi); } -static char im_name[]="cfi_cmdset_0020"; - -static int __init cfi_staa_init(void) -{ - inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0020); - return 0; -} - -static void __exit cfi_staa_exit(void) -{ - inter_module_unregister(im_name); -} - -module_init(cfi_staa_init); -module_exit(cfi_staa_exit); - MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index e636aa8..4bf9f8c 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c @@ -349,12 +349,12 @@ #endif else printk("No Vpp line\n"); - printk("Typical byte/word write timeout: %d µs\n", 1<WordWriteTimeoutTyp); - printk("Maximum byte/word write timeout: %d µs\n", (1<WordWriteTimeoutMax) * (1<WordWriteTimeoutTyp)); + printk("Typical byte/word write timeout: %d µs\n", 1<WordWriteTimeoutTyp); + printk("Maximum byte/word write timeout: %d µs\n", (1<WordWriteTimeoutMax) * (1<WordWriteTimeoutTyp)); if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) { - printk("Typical full buffer write timeout: %d µs\n", 1<BufWriteTimeoutTyp); - printk("Maximum full buffer write timeout: %d µs\n", (1<BufWriteTimeoutMax) * (1<BufWriteTimeoutTyp)); + printk("Typical full buffer write timeout: %d µs\n", 1<BufWriteTimeoutTyp); + printk("Maximum full buffer write timeout: %d µs\n", (1<BufWriteTimeoutMax) * (1<BufWriteTimeoutTyp)); } else printk("Full buffer write not supported\n"); diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index 41bd59d..cdb0f59 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c @@ -37,8 +37,15 @@ struct mtd_info *mtd_do_chip_probe(struc if (!mtd) mtd = check_cmd_set(map, 0); /* Then the secondary */ - if (mtd) + if (mtd) { + if (mtd->size > map->size) { + printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n", + (unsigned long)mtd->size >> 10, + (unsigned long)map->size >> 10); + mtd->size = map->size; + } return mtd; + } printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n"); @@ -100,7 +107,12 @@ #endif * Align bitmap storage size to full byte. */ max_chips = map->size >> cfi.chipshift; - mapsize = (max_chips / 8) + ((max_chips % 8) ? 1 : 0); + if (!max_chips) { + printk(KERN_WARNING "NOR chip too large to fit in mapping. Attempting to cope...\n"); + max_chips = 1; + } + + mapsize = (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG; chip_map = kmalloc(mapsize, GFP_KERNEL); if (!chip_map) { printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name); @@ -194,25 +206,28 @@ static inline struct mtd_info *cfi_cmdse { struct cfi_private *cfi = map->fldrv_priv; __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID; -#if defined(CONFIG_MODULES) && defined(HAVE_INTER_MODULE) - char probename[32]; +#ifdef CONFIG_MODULES + char probename[16+sizeof(MODULE_SYMBOL_PREFIX)]; cfi_cmdset_fn_t *probe_function; - sprintf(probename, "cfi_cmdset_%4.4X", type); + sprintf(probename, MODULE_SYMBOL_PREFIX "cfi_cmdset_%4.4X", type); - probe_function = inter_module_get_request(probename, probename); + probe_function = __symbol_get(probename); + if (!probe_function) { + request_module(probename + sizeof(MODULE_SYMBOL_PREFIX) - 1); + probe_function = __symbol_get(probename); + } if (probe_function) { struct mtd_info *mtd; mtd = (*probe_function)(map, primary); /* If it was happy, it'll have increased its own use count */ - inter_module_put(probename); + symbol_put_addr(probe_function); return mtd; } #endif - printk(KERN_NOTICE "Support for command set %04X not present\n", - type); + printk(KERN_NOTICE "Support for command set %04X not present\n", type); return NULL; } @@ -226,12 +241,8 @@ static struct mtd_info *check_cmd_set(st return NULL; switch(type){ - /* Urgh. Ifdefs. The version with weak symbols was - * _much_ nicer. Shame it didn't seem to work on - * anything but x86, really. - * But we can't rely in inter_module_get() because - * that'd mean we depend on link order. - */ + /* We need these for the !CONFIG_MODULES case, + because symbol_get() doesn't work there */ #ifdef CONFIG_MTD_CFI_INTELEXT case 0x0001: case 0x0003: @@ -246,9 +257,9 @@ #ifdef CONFIG_MTD_CFI_STAA case 0x0020: return cfi_cmdset_0020(map, primary); #endif + default: + return cfi_cmdset_unknown(map, primary); } - - return cfi_cmdset_unknown(map, primary); } MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c index bd2e876..7639257 100644 --- a/drivers/mtd/chips/map_ram.c +++ b/drivers/mtd/chips/map_ram.c @@ -70,7 +70,7 @@ #endif mtd->read = mapram_read; mtd->write = mapram_write; mtd->sync = mapram_nop; - mtd->flags = MTD_CAP_RAM | MTD_VOLATILE; + mtd->flags = MTD_CAP_RAM; mtd->erasesize = PAGE_SIZE; while(mtd->size & (mtd->erasesize - 1)) diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c index 624c12c..bc6ee9e 100644 --- a/drivers/mtd/chips/map_rom.c +++ b/drivers/mtd/chips/map_rom.c @@ -46,9 +46,7 @@ static struct mtd_info *map_rom_probe(st mtd->write = maprom_write; mtd->sync = maprom_nop; mtd->flags = MTD_CAP_ROM; - mtd->erasesize = 131072; - while(mtd->size & (mtd->erasesize - 1)) - mtd->erasesize >>= 1; + mtd->erasesize = map->size; __module_get(THIS_MODULE); return mtd; diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c index 3cc0b23..967abbe 100644 --- a/drivers/mtd/chips/sharp.c +++ b/drivers/mtd/chips/sharp.c @@ -140,6 +140,7 @@ static struct mtd_info *sharp_probe(stru mtd->suspend = sharp_suspend; mtd->resume = sharp_resume; mtd->flags = MTD_CAP_NORFLASH; + mtd->writesize = 1; mtd->name = map->name; memset(sharp, 0, sizeof(*sharp)); diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 7fac438..16c02b5 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -47,6 +47,11 @@ config MTD_MS02NV accelerator. Say Y here if you have a DECstation 5000/2x0 or a DECsystem 5900 equipped with such a module. + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read . The module will + be called ms02-nv.o. + config MTD_DATAFLASH tristate "Support for AT45xxx DataFlash" depends on MTD && SPI_MASTER && EXPERIMENTAL @@ -209,7 +214,6 @@ config MTD_DOC2001PLUS config MTD_DOCPROBE tristate select MTD_DOCECC - select OBSOLETE_INTERMODULE config MTD_DOCECC tristate diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index b657367..0f788d5 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -3,13 +3,6 @@ # linux/drivers/devices/Makefile # # $Id: Makefile.common,v 1.7 2004/12/22 17:51:15 joern Exp $ -# *** BIG UGLY NOTE *** -# -# The removal of get_module_symbol() and replacement with -# inter_module_register() et al has introduced a link order dependency -# here where previously there was none. We now have to ensure that -# doc200[01].o are linked before docprobe.o - obj-$(CONFIG_MTD_DOC2000) += doc2000.o obj-$(CONFIG_MTD_DOC2001) += doc2001.o obj-$(CONFIG_MTD_DOC2001PLUS) += doc2001plus.o diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 4160b83..0d98c22 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -4,7 +4,7 @@ * block2mtd.c - create an mtd from a block device * * Copyright (C) 2001,2002 Simon Evans - * Copyright (C) 2004,2005 Jörn Engel + * Copyright (C) 2004-2006 Jörn Engel * * Licence: GPL */ @@ -331,7 +331,6 @@ static struct block2mtd_dev *add_device( dev->mtd.writev = default_mtd_writev; dev->mtd.sync = block2mtd_sync; dev->mtd.read = block2mtd_read; - dev->mtd.readv = default_mtd_readv; dev->mtd.priv = dev; dev->mtd.owner = THIS_MODULE; @@ -351,6 +350,12 @@ devinit_err: } +/* This function works similar to reguler strtoul. In addition, it + * allows some suffixes for a more human-readable number format: + * ki, Ki, kiB, KiB - multiply result with 1024 + * Mi, MiB - multiply result with 1024^2 + * Gi, GiB - multiply result with 1024^3 + */ static int ustrtoul(const char *cp, char **endp, unsigned int base) { unsigned long result = simple_strtoul(cp, endp, base); @@ -359,11 +364,16 @@ static int ustrtoul(const char *cp, char result *= 1024; case 'M': result *= 1024; + case 'K': case 'k': result *= 1024; /* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */ - if ((*endp)[1] == 'i') - (*endp) += 2; + if ((*endp)[1] == 'i') { + if ((*endp)[2] == 'B') + (*endp) += 3; + else + (*endp) += 2; + } } return result; } @@ -418,7 +428,8 @@ #define parse_err(fmt, args...) do { \ static int block2mtd_setup(const char *val, struct kernel_param *kp) { - char buf[80+12], *str=buf; /* 80 for device, 12 for erase size */ + char buf[80+12]; /* 80 for device, 12 for erase size */ + char *str = buf; char *token[2]; char *name; size_t erase_size = PAGE_SIZE; @@ -430,7 +441,7 @@ static int block2mtd_setup(const char *v strcpy(str, val); kill_final_newline(str); - for (i=0; i<2; i++) + for (i = 0; i < 2; i++) token[i] = strsep(&str, ","); if (str) @@ -449,8 +460,10 @@ static int block2mtd_setup(const char *v if (token[1]) { ret = parse_num(&erase_size, token[1]); - if (ret) + if (ret) { + kfree(name); parse_err("illegal erase size"); + } } add_device(name, erase_size); diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index 23e7a5c..c54e404 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c @@ -59,13 +59,10 @@ static int doc_read_ecc(struct mtd_info size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); -static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t *retlen, - u_char *eccbuf, struct nand_oobinfo *oobsel); -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, u_char *buf); -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, const u_char *buf); +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops); +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops); static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf); static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); @@ -517,16 +514,9 @@ static int DoC2k_is_alias(struct DiskOnC return retval; } -static const char im_name[] = "DoC2k_init"; - -/* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The - * addresses passed back in mtd are valid as long as the use count of - * this module is non-zero, i.e. between inter_module_get and - * inter_module_put. Keith Owens 29 Oct 2000. - */ -static void DoC2k_init(struct mtd_info *mtd) +/* This routine is found from the docprobe code by symbol_get(), + * which will bump the use count of this module. */ +void DoC2k_init(struct mtd_info *mtd) { struct DiskOnChip *this = mtd->priv; struct DiskOnChip *old = NULL; @@ -586,7 +576,7 @@ static void DoC2k_init(struct mtd_info * mtd->ecctype = MTD_ECC_RS_DiskOnChip; mtd->size = 0; mtd->erasesize = 0; - mtd->oobblock = 512; + mtd->writesize = 512; mtd->oobsize = 16; mtd->owner = THIS_MODULE; mtd->erase = doc_erase; @@ -594,9 +584,6 @@ static void DoC2k_init(struct mtd_info * mtd->unpoint = NULL; mtd->read = doc_read; mtd->write = doc_write; - mtd->read_ecc = doc_read_ecc; - mtd->write_ecc = doc_write_ecc; - mtd->writev_ecc = doc_writev_ecc; mtd->read_oob = doc_read_oob; mtd->write_oob = doc_write_oob; mtd->sync = NULL; @@ -623,6 +610,7 @@ static void DoC2k_init(struct mtd_info * return; } } +EXPORT_SYMBOL_GPL(DoC2k_init); static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) @@ -971,72 +959,18 @@ #endif return 0; } -static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t *retlen, - u_char *eccbuf, struct nand_oobinfo *oobsel) -{ - static char static_buf[512]; - static DEFINE_MUTEX(writev_buf_mutex); - - size_t totretlen = 0; - size_t thisvecofs = 0; - int ret= 0; - - mutex_lock(&writev_buf_mutex); - - while(count) { - size_t thislen, thisretlen; - unsigned char *buf; - - buf = vecs->iov_base + thisvecofs; - thislen = vecs->iov_len - thisvecofs; - - - if (thislen >= 512) { - thislen = thislen & ~(512-1); - thisvecofs += thislen; - } else { - /* Not enough to fill a page. Copy into buf */ - memcpy(static_buf, buf, thislen); - buf = &static_buf[thislen]; - - while(count && thislen < 512) { - vecs++; - count--; - thisvecofs = min((512-thislen), vecs->iov_len); - memcpy(buf, vecs->iov_base, thisvecofs); - thislen += thisvecofs; - buf += thisvecofs; - } - buf = static_buf; - } - if (count && thisvecofs == vecs->iov_len) { - thisvecofs = 0; - vecs++; - count--; - } - ret = doc_write_ecc(mtd, to, thislen, &thisretlen, buf, eccbuf, oobsel); - - totretlen += thisretlen; - - if (ret || thisretlen != thislen) - break; - - to += thislen; - } - - mutex_unlock(&writev_buf_mutex); - *retlen = totretlen; - return ret; -} - - -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t * retlen, u_char * buf) +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops) { struct DiskOnChip *this = mtd->priv; int len256 = 0, ret; struct Nand *mychip; + uint8_t *buf = ops->oobbuf; + size_t len = ops->len; + + BUG_ON(ops->mode != MTD_OOB_PLACE); + + ofs += ops->ooboffs; mutex_lock(&this->lock); @@ -1077,7 +1011,7 @@ static int doc_read_oob(struct mtd_info DoC_ReadBuf(this, &buf[len256], len - len256); - *retlen = len; + ops->retlen = len; /* Reading the full OOB data drops us off of the end of the page, * causing the flash device to go into busy mode, so we need * to wait until ready 11.4.1 and Toshiba TC58256FT docs */ @@ -1192,17 +1126,20 @@ static int doc_write_oob_nolock(struct m } -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t * retlen, const u_char * buf) +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops) { - struct DiskOnChip *this = mtd->priv; - int ret; + struct DiskOnChip *this = mtd->priv; + int ret; - mutex_lock(&this->lock); - ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf); + BUG_ON(ops->mode != MTD_OOB_PLACE); + + mutex_lock(&this->lock); + ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len, + &ops->retlen, ops->oobbuf); - mutex_unlock(&this->lock); - return ret; + mutex_unlock(&this->lock); + return ret; } static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) @@ -1277,12 +1214,6 @@ static int doc_erase(struct mtd_info *mt * ****************************************************************************/ -static int __init init_doc2000(void) -{ - inter_module_register(im_name, THIS_MODULE, &DoC2k_init); - return 0; -} - static void __exit cleanup_doc2000(void) { struct mtd_info *mtd; @@ -1298,11 +1229,9 @@ static void __exit cleanup_doc2000(void) kfree(this->chips); kfree(mtd); } - inter_module_unregister(im_name); } module_exit(cleanup_doc2000); -module_init(init_doc2000); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse et al."); diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index 681a9c7..0cf022a 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c @@ -43,10 +43,10 @@ static int doc_read_ecc(struct mtd_info static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, u_char *buf); -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, const u_char *buf); +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops); +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops); static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); static struct mtd_info *docmillist = NULL; @@ -324,16 +324,9 @@ static int DoCMil_is_alias(struct DiskOn return retval; } -static const char im_name[] = "DoCMil_init"; - -/* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The - * addresses passed back in mtd are valid as long as the use count of - * this module is non-zero, i.e. between inter_module_get and - * inter_module_put. Keith Owens 29 Oct 2000. - */ -static void DoCMil_init(struct mtd_info *mtd) +/* This routine is found from the docprobe code by symbol_get(), + * which will bump the use count of this module. */ +void DoCMil_init(struct mtd_info *mtd) { struct DiskOnChip *this = mtd->priv; struct DiskOnChip *old = NULL; @@ -368,7 +361,7 @@ static void DoCMil_init(struct mtd_info /* FIXME: erase size is not always 8KiB */ mtd->erasesize = 0x2000; - mtd->oobblock = 512; + mtd->writesize = 512; mtd->oobsize = 16; mtd->owner = THIS_MODULE; mtd->erase = doc_erase; @@ -376,8 +369,6 @@ static void DoCMil_init(struct mtd_info mtd->unpoint = NULL; mtd->read = doc_read; mtd->write = doc_write; - mtd->read_ecc = doc_read_ecc; - mtd->write_ecc = doc_write_ecc; mtd->read_oob = doc_read_oob; mtd->write_oob = doc_write_oob; mtd->sync = NULL; @@ -401,6 +392,7 @@ static void DoCMil_init(struct mtd_info return; } } +EXPORT_SYMBOL_GPL(DoCMil_init); static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) @@ -670,8 +662,8 @@ #endif return ret; } -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, u_char *buf) +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops) { #ifndef USE_MEMCPY int i; @@ -680,6 +672,12 @@ #endif struct DiskOnChip *this = mtd->priv; void __iomem *docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; + uint8_t *buf = ops->oobbuf; + size_t len = ops->len; + + BUG_ON(ops->mode != MTD_OOB_PLACE); + + ofs += ops->ooboffs; /* Find the chip which is to be used and select it */ if (this->curfloor != mychip->floor) { @@ -716,13 +714,13 @@ #else #endif buf[len - 1] = ReadDOC(docptr, LastDataRead); - *retlen = len; + ops->retlen = len; return 0; } -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, const u_char *buf) +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops) { #ifndef USE_MEMCPY int i; @@ -732,6 +730,12 @@ #endif struct DiskOnChip *this = mtd->priv; void __iomem *docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; + uint8_t *buf = ops->oobbuf; + size_t len = ops->len; + + BUG_ON(ops->mode != MTD_OOB_PLACE); + + ofs += ops->ooboffs; /* Find the chip which is to be used and select it */ if (this->curfloor != mychip->floor) { @@ -783,12 +787,12 @@ #endif if (ReadDOC(docptr, Mil_CDSN_IO) & 1) { printk("Error programming oob data\n"); /* FIXME: implement Bad Block Replacement (in nftl.c ??) */ - *retlen = 0; + ops->retlen = 0; ret = -EIO; } dummy = ReadDOC(docptr, LastDataRead); - *retlen = len; + ops->retlen = len; return ret; } @@ -856,12 +860,6 @@ int doc_erase (struct mtd_info *mtd, str * ****************************************************************************/ -static int __init init_doc2001(void) -{ - inter_module_register(im_name, THIS_MODULE, &DoCMil_init); - return 0; -} - static void __exit cleanup_doc2001(void) { struct mtd_info *mtd; @@ -877,11 +875,9 @@ static void __exit cleanup_doc2001(void) kfree(this->chips); kfree(mtd); } - inter_module_unregister(im_name); } module_exit(cleanup_doc2001); -module_init(init_doc2001); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse et al."); diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 5f57f29..66cb1e5 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c @@ -47,10 +47,10 @@ static int doc_read_ecc(struct mtd_info static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, u_char *buf); -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, const u_char *buf); +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops); +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops); static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); static struct mtd_info *docmilpluslist = NULL; @@ -447,16 +447,9 @@ static int DoCMilPlus_is_alias(struct Di return retval; } -static const char im_name[] = "DoCMilPlus_init"; - -/* This routine is made available to other mtd code via - * inter_module_register. It must only be accessed through - * inter_module_get which will bump the use count of this module. The - * addresses passed back in mtd are valid as long as the use count of - * this module is non-zero, i.e. between inter_module_get and - * inter_module_put. Keith Owens 29 Oct 2000. - */ -static void DoCMilPlus_init(struct mtd_info *mtd) +/* This routine is found from the docprobe code by symbol_get(), + * which will bump the use count of this module. */ +void DoCMilPlus_init(struct mtd_info *mtd) { struct DiskOnChip *this = mtd->priv; struct DiskOnChip *old = NULL; @@ -490,7 +483,7 @@ static void DoCMilPlus_init(struct mtd_i mtd->size = 0; mtd->erasesize = 0; - mtd->oobblock = 512; + mtd->writesize = 512; mtd->oobsize = 16; mtd->owner = THIS_MODULE; mtd->erase = doc_erase; @@ -498,8 +491,6 @@ static void DoCMilPlus_init(struct mtd_i mtd->unpoint = NULL; mtd->read = doc_read; mtd->write = doc_write; - mtd->read_ecc = doc_read_ecc; - mtd->write_ecc = doc_write_ecc; mtd->read_oob = doc_read_oob; mtd->write_oob = doc_write_oob; mtd->sync = NULL; @@ -524,6 +515,7 @@ static void DoCMilPlus_init(struct mtd_i return; } } +EXPORT_SYMBOL_GPL(DoCMilPlus_init); #if 0 static int doc_dumpblk(struct mtd_info *mtd, loff_t from) @@ -876,14 +868,20 @@ #endif return ret; } -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, u_char *buf) +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops) { loff_t fofs, base; struct DiskOnChip *this = mtd->priv; void __iomem * docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; size_t i, size, got, want; + uint8_t *buf = ops->oobbuf; + size_t len = ops->len; + + BUG_ON(ops->mode != MTD_OOB_PLACE); + + ofs += ops->ooboffs; DoC_CheckASIC(docptr); @@ -949,12 +947,12 @@ static int doc_read_oob(struct mtd_info /* Disable flash internally */ WriteDOC(0, docptr, Mplus_FlashSelect); - *retlen = len; + ops->retlen = len; return 0; } -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, - size_t *retlen, const u_char *buf) +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, + struct mtd_oob_ops *ops) { volatile char dummy; loff_t fofs, base; @@ -963,6 +961,12 @@ static int doc_write_oob(struct mtd_info struct Nand *mychip = &this->chips[ofs >> this->chipshift]; size_t i, size, got, want; int ret = 0; + uint8_t *buf = ops->oobbuf; + size_t len = ops->len; + + BUG_ON(ops->mode != MTD_OOB_PLACE); + + ofs += ops->ooboffs; DoC_CheckASIC(docptr); @@ -1038,7 +1042,7 @@ static int doc_write_oob(struct mtd_info printk("MTD: Error 0x%x programming oob at 0x%x\n", dummy, (int)ofs); /* FIXME: implement Bad Block Replacement */ - *retlen = 0; + ops->retlen = 0; ret = -EIO; } dummy = ReadDOC(docptr, Mplus_LastDataRead); @@ -1051,7 +1055,7 @@ static int doc_write_oob(struct mtd_info /* Disable flash internally */ WriteDOC(0, docptr, Mplus_FlashSelect); - *retlen = len; + ops->retlen = len; return ret; } @@ -1122,12 +1126,6 @@ int doc_erase(struct mtd_info *mtd, stru * ****************************************************************************/ -static int __init init_doc2001plus(void) -{ - inter_module_register(im_name, THIS_MODULE, &DoCMilPlus_init); - return 0; -} - static void __exit cleanup_doc2001plus(void) { struct mtd_info *mtd; @@ -1143,11 +1141,9 @@ static void __exit cleanup_doc2001plus(v kfree(this->chips); kfree(mtd); } - inter_module_unregister(im_name); } module_exit(cleanup_doc2001plus); -module_init(init_doc2001plus); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Greg Ungerer et al."); diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index 13178b9..593bb03 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c @@ -231,6 +231,10 @@ #endif static int docfound; +extern void DoC2k_init(struct mtd_info *); +extern void DoCMil_init(struct mtd_info *); +extern void DoCMilPlus_init(struct mtd_info *); + static void __init DoC_Probe(unsigned long physadr) { void __iomem *docptr; @@ -239,8 +243,6 @@ static void __init DoC_Probe(unsigned lo int ChipID; char namebuf[15]; char *name = namebuf; - char *im_funcname = NULL; - char *im_modname = NULL; void (*initroutine)(struct mtd_info *) = NULL; docptr = ioremap(physadr, DOC_IOREMAP_LEN); @@ -278,41 +280,33 @@ static void __init DoC_Probe(unsigned lo switch(ChipID) { case DOC_ChipID_Doc2kTSOP: name="2000 TSOP"; - im_funcname = "DoC2k_init"; - im_modname = "doc2000"; + initroutine = symbol_request(DoC2k_init); break; case DOC_ChipID_Doc2k: name="2000"; - im_funcname = "DoC2k_init"; - im_modname = "doc2000"; + initroutine = symbol_request(DoC2k_init); break; case DOC_ChipID_DocMil: name="Millennium"; #ifdef DOC_SINGLE_DRIVER - im_funcname = "DoC2k_init"; - im_modname = "doc2000"; + initroutine = symbol_request(DoC2k_init); #else - im_funcname = "DoCMil_init"; - im_modname = "doc2001"; + initroutine = symbol_request(DoCMil_init); #endif /* DOC_SINGLE_DRIVER */ break; case DOC_ChipID_DocMilPlus16: case DOC_ChipID_DocMilPlus32: name="MillenniumPlus"; - im_funcname = "DoCMilPlus_init"; - im_modname = "doc2001plus"; + initroutine = symbol_request(DoCMilPlus_init); break; } - if (im_funcname) - initroutine = inter_module_get_request(im_funcname, im_modname); - if (initroutine) { (*initroutine)(mtd); - inter_module_put(im_funcname); + symbol_put_addr(initroutine); return; } printk(KERN_NOTICE "Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr); diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c index 29b0dda..4ea50a1 100644 --- a/drivers/mtd/devices/lart.c +++ b/drivers/mtd/devices/lart.c @@ -635,6 +635,7 @@ int __init lart_flash_init (void) printk ("%s: This looks like a LART board to me.\n",module_name); mtd.name = module_name; mtd.type = MTD_NORFLASH; + mtd.writesize = 1; mtd.flags = MTD_CAP_NORFLASH; mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN; mtd.erasesize = FLASH_BLOCKSIZE_MAIN; diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 04e65d5..a846614 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -465,6 +465,7 @@ static int __devinit m25p_probe(struct s flash->mtd.name = spi->dev.bus_id; flash->mtd.type = MTD_NORFLASH; + flash->mtd.writesize = 1; flash->mtd.flags = MTD_CAP_NORFLASH; flash->mtd.size = info->sector_size * info->n_sectors; flash->mtd.erasesize = info->sector_size; diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c index 485f663..4ab7670 100644 --- a/drivers/mtd/devices/ms02-nv.c +++ b/drivers/mtd/devices/ms02-nv.c @@ -219,7 +219,7 @@ static int __init ms02nv_init_one(ulong mp->uaddr = phys_to_virt(fixaddr); mtd->type = MTD_RAM; - mtd->flags = MTD_CAP_RAM | MTD_XIP; + mtd->flags = MTD_CAP_RAM; mtd->size = fixsize; mtd->name = (char *)ms02nv_name; mtd->owner = THIS_MODULE; diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index 1443117..b4438ea 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c @@ -106,6 +106,7 @@ int mtdram_init_device(struct mtd_info * mtd->type = MTD_RAM; mtd->flags = MTD_CAP_RAM; mtd->size = size; + mtd->writesize = 1; mtd->erasesize = MTDRAM_ERASE_SIZE; mtd->priv = mapped_address; diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index e8685ee..e09e416 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c @@ -1,8 +1,8 @@ /** * $Id: phram.c,v 1.16 2005/11/07 11:14:25 gleixner Exp $ * - * Copyright (c) ???? Jochen Schäuble - * Copyright (c) 2003-2004 Jörn Engel + * Copyright (c) ???? Jochen Schäuble + * Copyright (c) 2003-2004 Jörn Engel * * Usage: * @@ -142,7 +142,7 @@ static int register_device(char *name, u new->mtd.name = name; new->mtd.size = len; - new->mtd.flags = MTD_CAP_RAM | MTD_ERASEABLE | MTD_VOLATILE; + new->mtd.flags = MTD_CAP_RAM; new->mtd.erase = phram_erase; new->mtd.point = phram_point; new->mtd.unpoint = phram_unpoint; @@ -266,12 +266,16 @@ static int phram_setup(const char *val, return 0; ret = parse_num32(&start, token[1]); - if (ret) + if (ret) { + kfree(name); parse_err("illegal start address\n"); + } ret = parse_num32(&len, token[2]); - if (ret) + if (ret) { + kfree(name); parse_err("illegal device length\n"); + } register_device(name, start, len); @@ -296,5 +300,5 @@ module_init(init_phram); module_exit(cleanup_phram); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jörn Engel "); +MODULE_AUTHOR("Jörn Engel "); MODULE_DESCRIPTION("MTD driver for physical RAM"); diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 6faee6c..b3f665e 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -200,8 +200,7 @@ static int register_device(char *name, u (*curmtd)->mtdinfo->name = name; (*curmtd)->mtdinfo->size = length; - (*curmtd)->mtdinfo->flags = MTD_CLEAR_BITS | MTD_SET_BITS | - MTD_WRITEB_WRITEABLE | MTD_VOLATILE | MTD_CAP_RAM; + (*curmtd)->mtdinfo->flags = MTD_CAP_RAM; (*curmtd)->mtdinfo->erase = slram_erase; (*curmtd)->mtdinfo->point = slram_point; (*curmtd)->mtdinfo->unpoint = slram_unpoint; diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index a3b9247..1e21a2c 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -36,6 +36,7 @@ #include #include #include #include +#include #include #include #include @@ -79,14 +80,12 @@ static void inftl_add_mtd(struct mtd_blk inftl->mbd.devnum = -1; inftl->mbd.blksize = 512; inftl->mbd.tr = tr; - memcpy(&inftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo)); - inftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY; - if (INFTL_mount(inftl) < 0) { + if (INFTL_mount(inftl) < 0) { printk(KERN_WARNING "INFTL: could not mount device\n"); kfree(inftl); return; - } + } /* OK, it's a new one. Set up all the data structures. */ @@ -152,6 +151,69 @@ static void inftl_remove_dev(struct mtd_ */ /* + * Read oob data from flash + */ +int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, + size_t *retlen, uint8_t *buf) +{ + struct mtd_oob_ops ops; + int res; + + ops.mode = MTD_OOB_PLACE; + ops.ooboffs = offs & (mtd->writesize - 1); + ops.ooblen = len; + ops.oobbuf = buf; + ops.datbuf = NULL; + ops.len = len; + + res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); + *retlen = ops.retlen; + return res; +} + +/* + * Write oob data to flash + */ +int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, + size_t *retlen, uint8_t *buf) +{ + struct mtd_oob_ops ops; + int res; + + ops.mode = MTD_OOB_PLACE; + ops.ooboffs = offs & (mtd->writesize - 1); + ops.ooblen = len; + ops.oobbuf = buf; + ops.datbuf = NULL; + ops.len = len; + + res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); + *retlen = ops.retlen; + return res; +} + +/* + * Write data and oob to flash + */ +static int inftl_write(struct mtd_info *mtd, loff_t offs, size_t len, + size_t *retlen, uint8_t *buf, uint8_t *oob) +{ + struct mtd_oob_ops ops; + int res; + + ops.mode = MTD_OOB_PLACE; + ops.ooboffs = offs; + ops.ooblen = mtd->oobsize; + ops.oobbuf = oob; + ops.datbuf = buf; + ops.len = len; + + res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); + *retlen = ops.retlen; + return res; +} + +/* * INFTL_findfreeblock: Find a free Erase Unit on the INFTL partition. * This function is used when the give Virtual Unit Chain. */ @@ -198,10 +260,11 @@ static u16 INFTL_foldchain(struct INFTLr u16 BlockMap[MAX_SECTORS_PER_UNIT]; unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT]; unsigned int thisEUN, prevEUN, status; + struct mtd_info *mtd = inftl->mbd.mtd; int block, silly; unsigned int targetEUN; struct inftl_oob oob; - size_t retlen; + size_t retlen; DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d," "pending=%d)\n", inftl, thisVUC, pendingblock); @@ -221,18 +284,18 @@ static u16 INFTL_foldchain(struct INFTLr * Scan to find the Erase Unit which holds the actual data for each * 512-byte block within the Chain. */ - silly = MAX_LOOPS; + silly = MAX_LOOPS; while (thisEUN < inftl->nb_blocks) { for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) { if ((BlockMap[block] != 0xffff) || BlockDeleted[block]) continue; - if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) - + (block * SECTORSIZE), 16 , &retlen, - (char *)&oob) < 0) + if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) + + (block * SECTORSIZE), 16, &retlen, + (char *)&oob) < 0) status = SECTOR_IGNORE; else - status = oob.b.Status | oob.b.Status1; + status = oob.b.Status | oob.b.Status1; switch(status) { case SECTOR_FREE: @@ -282,29 +345,31 @@ static u16 INFTL_foldchain(struct INFTLr continue; } - /* + /* * Copy only in non free block (free blocks can only * happen in case of media errors or deleted blocks). */ - if (BlockMap[block] == BLOCK_NIL) - continue; - - ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize * - BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE, - &retlen, movebuf); - if (ret < 0) { - ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize * - BlockMap[block]) + (block * SECTORSIZE), - SECTORSIZE, &retlen, movebuf); + if (BlockMap[block] == BLOCK_NIL) + continue; + + ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) + + (block * SECTORSIZE), SECTORSIZE, &retlen, + movebuf); + if (ret < 0 && ret != -EUCLEAN) { + ret = mtd->read(mtd, + (inftl->EraseSize * BlockMap[block]) + + (block * SECTORSIZE), SECTORSIZE, + &retlen, movebuf); if (ret != -EIO) - DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went " - "away on retry?\n"); - } - memset(&oob, 0xff, sizeof(struct inftl_oob)); - oob.b.Status = oob.b.Status1 = SECTOR_USED; - MTD_WRITEECC(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) + - (block * SECTORSIZE), SECTORSIZE, &retlen, - movebuf, (char *)&oob, &inftl->oobinfo); + DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went " + "away on retry?\n"); + } + memset(&oob, 0xff, sizeof(struct inftl_oob)); + oob.b.Status = oob.b.Status1 = SECTOR_USED; + + inftl_write(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) + + (block * SECTORSIZE), SECTORSIZE, &retlen, + movebuf, (char *)&oob); } /* @@ -329,17 +394,17 @@ static u16 INFTL_foldchain(struct INFTLr if (thisEUN == targetEUN) break; - if (INFTL_formatblock(inftl, thisEUN) < 0) { + if (INFTL_formatblock(inftl, thisEUN) < 0) { /* * Could not erase : mark block as reserved. */ inftl->PUtable[thisEUN] = BLOCK_RESERVED; - } else { + } else { /* Correctly erased : mark it as free */ inftl->PUtable[thisEUN] = BLOCK_FREE; inftl->PUtable[prevEUN] = BLOCK_NIL; inftl->numfreeEUNs++; - } + } } return targetEUN; @@ -415,6 +480,7 @@ static inline u16 INFTL_findwriteunit(st unsigned int thisVUC = block / (inftl->EraseSize / SECTORSIZE); unsigned int thisEUN, writeEUN, prev_block, status; unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize -1); + struct mtd_info *mtd = inftl->mbd.mtd; struct inftl_oob oob; struct inftl_bci bci; unsigned char anac, nacs, parity; @@ -434,10 +500,10 @@ static inline u16 INFTL_findwriteunit(st silly = MAX_LOOPS; while (thisEUN <= inftl->lastEUN) { - MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + - blockofs, 8, &retlen, (char *)&bci); + inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) + + blockofs, 8, &retlen, (char *)&bci); - status = bci.Status | bci.Status1; + status = bci.Status | bci.Status1; DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in " "EUN %d is %x\n", block , writeEUN, status); @@ -522,8 +588,8 @@ #endif nacs = 0; thisEUN = inftl->VUtable[thisVUC]; if (thisEUN != BLOCK_NIL) { - MTD_READOOB(inftl->mbd.mtd, thisEUN * inftl->EraseSize - + 8, 8, &retlen, (char *)&oob.u); + inftl_read_oob(mtd, thisEUN * inftl->EraseSize + + 8, 8, &retlen, (char *)&oob.u); anac = oob.u.a.ANAC + 1; nacs = oob.u.a.NACs + 1; } @@ -544,8 +610,8 @@ #endif oob.u.a.parityPerField = parity; oob.u.a.discarded = 0xaa; - MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + 8, 8, - &retlen, (char *)&oob.u); + inftl_write_oob(mtd, writeEUN * inftl->EraseSize + 8, 8, + &retlen, (char *)&oob.u); /* Also back up header... */ oob.u.b.virtualUnitNo = cpu_to_le16(thisVUC); @@ -555,8 +621,8 @@ #endif oob.u.b.parityPerField = parity; oob.u.b.discarded = 0xaa; - MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + - SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u); + inftl_write_oob(mtd, writeEUN * inftl->EraseSize + + SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u); inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC]; inftl->VUtable[thisVUC] = writeEUN; @@ -576,6 +642,7 @@ #endif */ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC) { + struct mtd_info *mtd = inftl->mbd.mtd; unsigned char BlockUsed[MAX_SECTORS_PER_UNIT]; unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT]; unsigned int thisEUN, status; @@ -606,9 +673,9 @@ static void INFTL_trydeletechain(struct if (BlockUsed[block] || BlockDeleted[block]) continue; - if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) - + (block * SECTORSIZE), 8 , &retlen, - (char *)&bci) < 0) + if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) + + (block * SECTORSIZE), 8 , &retlen, + (char *)&bci) < 0) status = SECTOR_IGNORE; else status = bci.Status | bci.Status1; @@ -670,12 +737,12 @@ static void INFTL_trydeletechain(struct DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n", thisEUN, thisVUC); - if (INFTL_formatblock(inftl, thisEUN) < 0) { + if (INFTL_formatblock(inftl, thisEUN) < 0) { /* * Could not erase : mark block as reserved. */ inftl->PUtable[thisEUN] = BLOCK_RESERVED; - } else { + } else { /* Correctly erased : mark it as free */ inftl->PUtable[thisEUN] = BLOCK_FREE; inftl->numfreeEUNs++; @@ -697,6 +764,7 @@ static int INFTL_deleteblock(struct INFT { unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)]; unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1); + struct mtd_info *mtd = inftl->mbd.mtd; unsigned int status; int silly = MAX_LOOPS; size_t retlen; @@ -706,8 +774,8 @@ static int INFTL_deleteblock(struct INFT "block=%d)\n", inftl, block); while (thisEUN < inftl->nb_blocks) { - if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + - blockofs, 8, &retlen, (char *)&bci) < 0) + if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) + + blockofs, 8, &retlen, (char *)&bci) < 0) status = SECTOR_IGNORE; else status = bci.Status | bci.Status1; @@ -741,10 +809,10 @@ foundit: if (thisEUN != BLOCK_NIL) { loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs; - if (MTD_READOOB(inftl->mbd.mtd, ptr, 8, &retlen, (char *)&bci) < 0) + if (inftl_read_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0) return -EIO; bci.Status = bci.Status1 = SECTOR_DELETED; - if (MTD_WRITEOOB(inftl->mbd.mtd, ptr, 8, &retlen, (char *)&bci) < 0) + if (inftl_write_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0) return -EIO; INFTL_trydeletechain(inftl, block / (inftl->EraseSize / SECTORSIZE)); } @@ -784,9 +852,10 @@ static int inftl_writeblock(struct mtd_b memset(&oob, 0xff, sizeof(struct inftl_oob)); oob.b.Status = oob.b.Status1 = SECTOR_USED; - MTD_WRITEECC(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) + - blockofs, SECTORSIZE, &retlen, (char *)buffer, - (char *)&oob, &inftl->oobinfo); + + inftl_write(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) + + blockofs, SECTORSIZE, &retlen, (char *)buffer, + (char *)&oob); /* * need to write SECTOR_USED flags since they are not written * in mtd_writeecc @@ -804,17 +873,18 @@ static int inftl_readblock(struct mtd_bl struct INFTLrecord *inftl = (void *)mbd; unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)]; unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1); - unsigned int status; + struct mtd_info *mtd = inftl->mbd.mtd; + unsigned int status; int silly = MAX_LOOPS; - struct inftl_bci bci; + struct inftl_bci bci; size_t retlen; DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld," "buffer=%p)\n", inftl, block, buffer); while (thisEUN < inftl->nb_blocks) { - if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + - blockofs, 8, &retlen, (char *)&bci) < 0) + if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) + + blockofs, 8, &retlen, (char *)&bci) < 0) status = SECTOR_IGNORE; else status = bci.Status | bci.Status1; @@ -850,10 +920,12 @@ foundit: /* The requested block is not on the media, return all 0x00 */ memset(buffer, 0, SECTORSIZE); } else { - size_t retlen; + size_t retlen; loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs; - if (MTD_READ(inftl->mbd.mtd, ptr, SECTORSIZE, &retlen, - buffer)) + int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer); + + /* Handle corrected bit flips gracefully */ + if (ret < 0 && ret != -EUCLEAN) return -EIO; } return 0; diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index 43fdc94..8f6006f 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c @@ -43,6 +43,11 @@ #include char inftlmountrev[]="$Revision: 1.18 $"; +extern int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, + size_t *retlen, uint8_t *buf); +extern int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, + size_t *retlen, uint8_t *buf); + /* * find_boot_record: Find the INFTL Media Header and its Spare copy which * contains the various device information of the INFTL partition and @@ -57,6 +62,7 @@ static int find_boot_record(struct INFTL unsigned int i, block; u8 buf[SECTORSIZE]; struct INFTLMediaHeader *mh = &inftl->MediaHdr; + struct mtd_info *mtd = inftl->mbd.mtd; struct INFTLPartition *ip; size_t retlen; @@ -80,8 +86,8 @@ static int find_boot_record(struct INFTL * Check for BNAND header first. Then whinge if it's found * but later checks fail. */ - ret = MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize, - SECTORSIZE, &retlen, buf); + ret = mtd->read(mtd, block * inftl->EraseSize, + SECTORSIZE, &retlen, buf); /* We ignore ret in case the ECC of the MediaHeader is invalid (which is apparently acceptable) */ if (retlen != SECTORSIZE) { @@ -106,8 +112,9 @@ static int find_boot_record(struct INFTL } /* To be safer with BIOS, also use erase mark as discriminant */ - if ((ret = MTD_READOOB(inftl->mbd.mtd, block * inftl->EraseSize + - SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0)) { + if ((ret = inftl_read_oob(mtd, block * inftl->EraseSize + + SECTORSIZE + 8, 8, &retlen, + (char *)&h1) < 0)) { printk(KERN_WARNING "INFTL: ANAND header found at " "0x%x in mtd%d, but OOB data read failed " "(err %d)\n", block * inftl->EraseSize, @@ -123,8 +130,8 @@ static int find_boot_record(struct INFTL memcpy(mh, buf, sizeof(struct INFTLMediaHeader)); /* Read the spare media header at offset 4096 */ - MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize + 4096, - SECTORSIZE, &retlen, buf); + mtd->read(mtd, block * inftl->EraseSize + 4096, + SECTORSIZE, &retlen, buf); if (retlen != SECTORSIZE) { printk(KERN_WARNING "INFTL: Unable to read spare " "Media Header\n"); @@ -233,7 +240,7 @@ #endif */ instr->addr = ip->Reserved0 * inftl->EraseSize; instr->len = inftl->EraseSize; - MTD_ERASE(inftl->mbd.mtd, instr); + mtd->erase(mtd, instr); } if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) { printk(KERN_WARNING "INFTL: Media Header " @@ -350,21 +357,21 @@ static int check_free_sectors(struct INF int len, int check_oob) { u8 buf[SECTORSIZE + inftl->mbd.mtd->oobsize]; + struct mtd_info *mtd = inftl->mbd.mtd; size_t retlen; int i; - DEBUG(MTD_DEBUG_LEVEL3, "INFTL: check_free_sectors(inftl=%p," - "address=0x%x,len=%d,check_oob=%d)\n", inftl, - address, len, check_oob); - for (i = 0; i < len; i += SECTORSIZE) { - if (MTD_READECC(inftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &inftl->oobinfo) < 0) + if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf)) return -1; if (memcmpb(buf, 0xff, SECTORSIZE) != 0) return -1; if (check_oob) { - if (memcmpb(buf + SECTORSIZE, 0xff, inftl->mbd.mtd->oobsize) != 0) + if(inftl_read_oob(mtd, address, mtd->oobsize, + &retlen, &buf[SECTORSIZE]) < 0) + return -1; + if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0) return -1; } address += SECTORSIZE; @@ -387,6 +394,7 @@ int INFTL_formatblock(struct INFTLrecord size_t retlen; struct inftl_unittail uci; struct erase_info *instr = &inftl->instr; + struct mtd_info *mtd = inftl->mbd.mtd; int physblock; DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=%p," @@ -404,8 +412,9 @@ int INFTL_formatblock(struct INFTLrecord /* Erase one physical eraseblock at a time, even though the NAND api allows us to group them. This way we if we have a failure, we can mark only the failed block in the bbt. */ - for (physblock = 0; physblock < inftl->EraseSize; physblock += instr->len, instr->addr += instr->len) { - MTD_ERASE(inftl->mbd.mtd, instr); + for (physblock = 0; physblock < inftl->EraseSize; + physblock += instr->len, instr->addr += instr->len) { + mtd->erase(inftl->mbd.mtd, instr); if (instr->state == MTD_ERASE_FAILED) { printk(KERN_WARNING "INFTL: error while formatting block %d\n", @@ -414,10 +423,10 @@ int INFTL_formatblock(struct INFTLrecord } /* - * Check the "freeness" of Erase Unit before updating metadata. - * FixMe: is this check really necessary? Since we have check the - * return code after the erase operation. - */ + * Check the "freeness" of Erase Unit before updating metadata. + * FixMe: is this check really necessary? Since we have check + * the return code after the erase operation. + */ if (check_free_sectors(inftl, instr->addr, instr->len, 1) != 0) goto fail; } @@ -429,8 +438,7 @@ int INFTL_formatblock(struct INFTLrecord uci.Reserved[2] = 0; uci.Reserved[3] = 0; instr->addr = block * inftl->EraseSize + SECTORSIZE * 2; - if (MTD_WRITEOOB(inftl->mbd.mtd, instr->addr + - 8, 8, &retlen, (char *)&uci) < 0) + if (inftl_write_oob(mtd, instr->addr + 8, 8, &retlen, (char *)&uci) < 0) goto fail; return 0; fail: @@ -549,6 +557,7 @@ void INFTL_dumpVUchains(struct INFTLreco int INFTL_mount(struct INFTLrecord *s) { + struct mtd_info *mtd = s->mbd.mtd; unsigned int block, first_block, prev_block, last_block; unsigned int first_logical_block, logical_block, erase_mark; int chain_length, do_format_chain; @@ -607,10 +616,11 @@ int INFTL_mount(struct INFTLrecord *s) break; } - if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, - 8, &retlen, (char *)&h0) < 0 || - MTD_READOOB(s->mbd.mtd, block * s->EraseSize + - 2 * SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0) { + if (inftl_read_oob(mtd, block * s->EraseSize + 8, + 8, &retlen, (char *)&h0) < 0 || + inftl_read_oob(mtd, block * s->EraseSize + + 2 * SECTORSIZE + 8, 8, &retlen, + (char *)&h1) < 0) { /* Should never happen? */ do_format_chain++; break; diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 7abd7fe..83d0b2a 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -37,7 +37,7 @@ config MTD_PHYSMAP_START config MTD_PHYSMAP_LEN hex "Physical length of flash mapping" depends on MTD_PHYSMAP - default "0x4000000" + default "0" help This is the total length of the mapping of the flash chips on your particular board. If there is space, or aliases, in the @@ -78,7 +78,7 @@ config MTD_PNC2000 config MTD_SC520CDP tristate "CFI Flash device mapped on AMD SC520 CDP" - depends on X86 && MTD_CFI + depends on X86 && MTD_CFI && MTD_CONCAT help The SC520 CDP board has two banks of CFI-compliant chips and one Dual-in-line JEDEC chip. This 'mapping' driver supports that @@ -109,7 +109,7 @@ config MTD_TS5500 mtd1 allows you to reprogram your BIOS. BE VERY CAREFUL. Note that jumper 3 ("Write Enable Drive A") must be set - otherwise detection won't succeeed. + otherwise detection won't succeed. config MTD_SBC_GXX tristate "CFI Flash device mapped on Arcom SBC-GXx boards" @@ -200,8 +200,8 @@ config MTD_TSUNAMI Support for the flash chip on Tsunami TIG bus. config MTD_LASAT - tristate "Flash chips on LASAT board" - depends on LASAT + tristate "LASAT flash device" + depends on LASAT && MTD_CFI help Support for the flash chips on the Lasat 100 and 200 boards. @@ -212,7 +212,7 @@ config MTD_NETtel Support for flash chips on NETtel/SecureEdge/SnapGear boards. config MTD_ALCHEMY - tristate ' AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support' + tristate "AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support" depends on SOC_AU1X00 help Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards @@ -561,7 +561,6 @@ config MTD_PCMCIA config MTD_PCMCIA_ANONYMOUS bool "Use PCMCIA MTD drivers for anonymous PCMCIA cards" depends on MTD_PCMCIA - default N help If this option is enabled, PCMCIA cards which do not report anything about themselves are assumed to be MTD cards. diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c index fd0f0d3..92b5d88 100644 --- a/drivers/mtd/maps/cfi_flagadm.c +++ b/drivers/mtd/maps/cfi_flagadm.c @@ -1,5 +1,5 @@ /* - * Copyright © 2001 Flaga hf. Medical Devices, Kári Davíðsson + * Copyright © 2001 Flaga hf. Medical Devices, Kári Davíðsson * * $Id: cfi_flagadm.c,v 1.15 2005/11/07 11:14:26 gleixner Exp $ * @@ -135,5 +135,5 @@ module_exit(cleanup_flagadm); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kári Davíðsson "); +MODULE_AUTHOR("Kári Davíðsson "); MODULE_DESCRIPTION("MTD map driver for Flaga digital module"); diff --git a/drivers/mtd/maps/dbox2-flash.c b/drivers/mtd/maps/dbox2-flash.c index 652813c..85c2a9e 100644 --- a/drivers/mtd/maps/dbox2-flash.c +++ b/drivers/mtd/maps/dbox2-flash.c @@ -122,5 +122,5 @@ module_exit(cleanup_dbox2_flash); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kári Davíðsson , Bastian Blank , Alexander Wild "); +MODULE_AUTHOR("Kári Davíðsson , Bastian Blank , Alexander Wild "); MODULE_DESCRIPTION("MTD map driver for D-Box 2 board"); diff --git a/drivers/mtd/maps/mtx-1_flash.c b/drivers/mtd/maps/mtx-1_flash.c index d1e66e1..5c25d4e 100644 --- a/drivers/mtd/maps/mtx-1_flash.c +++ b/drivers/mtd/maps/mtx-1_flash.c @@ -4,7 +4,7 @@ * $Id: mtx-1_flash.c,v 1.2 2005/11/07 11:14:27 gleixner Exp $ * * (C) 2005 Bruno Randolf - * (C) 2005 Jörn Engel + * (C) 2005 Jörn Engel * */ diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c index 54a3102..0994b5b 100644 --- a/drivers/mtd/maps/nettel.c +++ b/drivers/mtd/maps/nettel.c @@ -20,6 +20,8 @@ #include #include #include #include +#include +#include #include /****************************************************************************/ @@ -188,7 +190,7 @@ int nettel_eraseconfig(void) set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&wait_q, &wait); - ret = MTD_ERASE(mtd, &nettel_erase); + ret = mtd->erase(mtd, &nettel_erase); if (ret) { set_current_state(TASK_RUNNING); remove_wait_queue(&wait_q, &wait); diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index d27f412..c861134 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -713,6 +713,7 @@ static void pcmciamtd_detach(struct pcmc if(dev->mtd_info) { del_mtd_device(dev->mtd_info); + map_destroy(dev->mtd_info); info("mtd%d: Removed", dev->mtd_info->index); } diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index f49ebc3..433c3ca 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -14,112 +14,229 @@ #include #include #include #include -#include +#include +#include #include #include #include #include #include +#include -static struct mtd_info *mymtd; - -struct map_info physmap_map = { - .name = "phys_mapped_flash", - .phys = CONFIG_MTD_PHYSMAP_START, - .size = CONFIG_MTD_PHYSMAP_LEN, - .bankwidth = CONFIG_MTD_PHYSMAP_BANKWIDTH, +struct physmap_flash_info { + struct mtd_info *mtd; + struct map_info map; + struct resource *res; +#ifdef CONFIG_MTD_PARTITIONS + int nr_parts; + struct mtd_partition *parts; +#endif }; + +static int physmap_flash_remove(struct platform_device *dev) +{ + struct physmap_flash_info *info; + struct physmap_flash_data *physmap_data; + + info = platform_get_drvdata(dev); + if (info == NULL) + return 0; + platform_set_drvdata(dev, NULL); + + physmap_data = dev->dev.platform_data; + + if (info->mtd != NULL) { #ifdef CONFIG_MTD_PARTITIONS -static struct mtd_partition *mtd_parts; -static int mtd_parts_nb; + if (info->nr_parts) { + del_mtd_partitions(info->mtd); + kfree(info->parts); + } else if (physmap_data->nr_parts) { + del_mtd_partitions(info->mtd); + } else { + del_mtd_device(info->mtd); + } +#else + del_mtd_device(info->mtd); +#endif + map_destroy(info->mtd); + } -static int num_physmap_partitions; -static struct mtd_partition *physmap_partitions; + if (info->map.virt != NULL) + iounmap((void *)info->map.virt); -static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL}; + if (info->res != NULL) { + release_resource(info->res); + kfree(info->res); + } -void physmap_set_partitions(struct mtd_partition *parts, int num_parts) -{ - physmap_partitions=parts; - num_physmap_partitions=num_parts; + return 0; } -#endif /* CONFIG_MTD_PARTITIONS */ -static int __init init_physmap(void) +static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL }; +#ifdef CONFIG_MTD_PARTITIONS +static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; +#endif + +static int physmap_flash_probe(struct platform_device *dev) { - static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL }; - const char **type; + struct physmap_flash_data *physmap_data; + struct physmap_flash_info *info; + const char **probe_type; + int err; + + physmap_data = dev->dev.platform_data; + if (physmap_data == NULL) + return -ENODEV; + + printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", + (unsigned long long)dev->resource->end - dev->resource->start + 1, + (unsigned long long)dev->resource->start); + + info = kmalloc(sizeof(struct physmap_flash_info), GFP_KERNEL); + if (info == NULL) { + err = -ENOMEM; + goto err_out; + } + memset(info, 0, sizeof(*info)); - printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys); - physmap_map.virt = ioremap(physmap_map.phys, physmap_map.size); + platform_set_drvdata(dev, info); - if (!physmap_map.virt) { - printk("Failed to ioremap\n"); - return -EIO; + info->res = request_mem_region(dev->resource->start, + dev->resource->end - dev->resource->start + 1, + dev->dev.bus_id); + if (info->res == NULL) { + dev_err(&dev->dev, "Could not reserve memory region\n"); + err = -ENOMEM; + goto err_out; } - simple_map_init(&physmap_map); + info->map.name = dev->dev.bus_id; + info->map.phys = dev->resource->start; + info->map.size = dev->resource->end - dev->resource->start + 1; + info->map.bankwidth = physmap_data->width; + info->map.set_vpp = physmap_data->set_vpp; + + info->map.virt = ioremap(info->map.phys, info->map.size); + if (info->map.virt == NULL) { + dev_err(&dev->dev, "Failed to ioremap flash region\n"); + err = EIO; + goto err_out; + } - mymtd = NULL; - type = rom_probe_types; - for(; !mymtd && *type; type++) { - mymtd = do_map_probe(*type, &physmap_map); + simple_map_init(&info->map); + + probe_type = rom_probe_types; + for (; info->mtd == NULL && *probe_type != NULL; probe_type++) + info->mtd = do_map_probe(*probe_type, &info->map); + if (info->mtd == NULL) { + dev_err(&dev->dev, "map_probe failed\n"); + err = -ENXIO; + goto err_out; } - if (mymtd) { - mymtd->owner = THIS_MODULE; + info->mtd->owner = THIS_MODULE; #ifdef CONFIG_MTD_PARTITIONS - mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes, - &mtd_parts, 0); + err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0); + if (err > 0) { + add_mtd_partitions(info->mtd, info->parts, err); + return 0; + } - if (mtd_parts_nb > 0) - { - add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb); - return 0; - } + if (physmap_data->nr_parts) { + printk(KERN_NOTICE "Using physmap partition information\n"); + add_mtd_partitions(info->mtd, physmap_data->parts, + physmap_data->nr_parts); + return 0; + } +#endif + + add_mtd_device(info->mtd); + return 0; + +err_out: + physmap_flash_remove(dev); + return err; +} + +static struct platform_driver physmap_flash_driver = { + .probe = physmap_flash_probe, + .remove = physmap_flash_remove, + .driver = { + .name = "physmap-flash", + }, +}; - if (num_physmap_partitions != 0) - { - printk(KERN_NOTICE - "Using physmap partition definition\n"); - add_mtd_partitions (mymtd, physmap_partitions, num_physmap_partitions); - return 0; - } +#ifdef CONFIG_MTD_PHYSMAP_LEN +#if CONFIG_MTD_PHYSMAP_LEN != 0 +#warning using PHYSMAP compat code +#define PHYSMAP_COMPAT +#endif #endif - add_mtd_device(mymtd); - return 0; - } +#ifdef PHYSMAP_COMPAT +static struct physmap_flash_data physmap_flash_data = { + .width = CONFIG_MTD_PHYSMAP_BANKWIDTH, +}; - iounmap(physmap_map.virt); - return -ENXIO; -} +static struct resource physmap_flash_resource = { + .start = CONFIG_MTD_PHYSMAP_START, + .end = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN, + .flags = IORESOURCE_MEM, +}; -static void __exit cleanup_physmap(void) +static struct platform_device physmap_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &physmap_flash_data, + }, + .num_resources = 1, + .resource = &physmap_flash_resource, +}; + +void physmap_configure(unsigned long addr, unsigned long size, + int bankwidth, void (*set_vpp)(struct map_info *, int)) { + physmap_flash_resource.start = addr; + physmap_flash_resource.end = addr + size - 1; + physmap_flash_data.width = bankwidth; + physmap_flash_data.set_vpp = set_vpp; +} + #ifdef CONFIG_MTD_PARTITIONS - if (mtd_parts_nb) { - del_mtd_partitions(mymtd); - kfree(mtd_parts); - } else if (num_physmap_partitions) { - del_mtd_partitions(mymtd); - } else { - del_mtd_device(mymtd); - } -#else - del_mtd_device(mymtd); +void physmap_set_partitions(struct mtd_partition *parts, int num_parts) +{ + physmap_flash_data.nr_parts = num_parts; + physmap_flash_data.parts = parts; +} +#endif #endif - map_destroy(mymtd); - iounmap(physmap_map.virt); - physmap_map.virt = NULL; +static int __init physmap_init(void) +{ + int err; + + err = platform_driver_register(&physmap_flash_driver); +#ifdef PHYSMAP_COMPAT + if (err == 0) + platform_device_register(&physmap_flash); +#endif + + return err; } -module_init(init_physmap); -module_exit(cleanup_physmap); +static void __exit physmap_exit(void) +{ +#ifdef PHYSMAP_COMPAT + platform_device_unregister(&physmap_flash); +#endif + platform_driver_unregister(&physmap_flash_driver); +} +module_init(physmap_init); +module_exit(physmap_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse "); diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 0758cb1..24a0315 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c @@ -18,6 +18,7 @@ #include #include #include #include +#include #include #include @@ -30,146 +31,140 @@ #define UFLASH_DEVNAME "userflash" #define UFLASH_WINDOW_SIZE 0x200000 #define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */ -MODULE_AUTHOR - ("Eric Brower "); -MODULE_DESCRIPTION - ("User-programmable flash device on Sun Microsystems boardsets"); -MODULE_SUPPORTED_DEVICE - ("userflash"); -MODULE_LICENSE - ("GPL"); +MODULE_AUTHOR("Eric Brower "); +MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets"); +MODULE_SUPPORTED_DEVICE("userflash"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("2.0"); static LIST_HEAD(device_list); struct uflash_dev { - char * name; /* device name */ + char *name; /* device name */ struct map_info map; /* mtd map info */ - struct mtd_info * mtd; /* mtd info */ - struct list_head list; + struct mtd_info *mtd; /* mtd info */ }; struct map_info uflash_map_templ = { - .name = "SUNW,???-????", - .size = UFLASH_WINDOW_SIZE, - .bankwidth = UFLASH_BUSWIDTH, + .name = "SUNW,???-????", + .size = UFLASH_WINDOW_SIZE, + .bankwidth = UFLASH_BUSWIDTH, }; -int uflash_devinit(struct linux_ebus_device* edev) +int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp) { - int iTmp, nregs; - struct linux_prom_registers regs[2]; - struct uflash_dev *pdev; - - iTmp = prom_getproperty( - edev->prom_node, "reg", (void *)regs, sizeof(regs)); - if ((iTmp % sizeof(regs[0])) != 0) { - printk("%s: Strange reg property size %d\n", - UFLASH_DEVNAME, iTmp); - return -ENODEV; - } + struct uflash_dev *up; + struct resource *res; - nregs = iTmp / sizeof(regs[0]); + res = &edev->resource[0]; - if (nregs != 1) { + if (edev->num_addrs != 1) { /* Non-CFI userflash device-- once I find one we * can work on supporting it. */ printk("%s: unsupported device at 0x%lx (%d regs): " \ "email ebrower@usa.net\n", - UFLASH_DEVNAME, edev->resource[0].start, nregs); + dp->full_name, res->start, edev->num_addrs); + return -ENODEV; } - if(0 == (pdev = kmalloc(sizeof(struct uflash_dev), GFP_KERNEL))) { - printk("%s: unable to kmalloc new device\n", UFLASH_DEVNAME); - return(-ENOMEM); - } + up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL); + if (!up) + return -ENOMEM; /* copy defaults and tweak parameters */ - memcpy(&pdev->map, &uflash_map_templ, sizeof(uflash_map_templ)); - pdev->map.size = regs[0].reg_size; - - iTmp = prom_getproplen(edev->prom_node, "model"); - pdev->name = kmalloc(iTmp, GFP_KERNEL); - prom_getstring(edev->prom_node, "model", pdev->name, iTmp); - if(0 != pdev->name && 0 < strlen(pdev->name)) { - pdev->map.name = pdev->name; - } - pdev->map.phys = edev->resource[0].start; - pdev->map.virt = ioremap_nocache(edev->resource[0].start, pdev->map.size); - if(0 == pdev->map.virt) { - printk("%s: failed to map device\n", __FUNCTION__); - kfree(pdev->name); - kfree(pdev); - return(-1); + memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ)); + up->map.size = (res->end - res->start) + 1UL; + + up->name = of_get_property(dp, "model", NULL); + if (up->name && 0 < strlen(up->name)) + up->map.name = up->name; + + up->map.phys = res->start; + + up->map.virt = ioremap_nocache(res->start, up->map.size); + if (!up->map.virt) { + printk("%s: Failed to map device.\n", dp->full_name); + kfree(up); + + return -EINVAL; } - simple_map_init(&pdev->map); + simple_map_init(&up->map); /* MTD registration */ - pdev->mtd = do_map_probe("cfi_probe", &pdev->map); - if(0 == pdev->mtd) { - iounmap(pdev->map.virt); - kfree(pdev->name); - kfree(pdev); - return(-ENXIO); + up->mtd = do_map_probe("cfi_probe", &up->map); + if (!up->mtd) { + iounmap(up->map.virt); + kfree(up); + + return -ENXIO; } - list_add(&pdev->list, &device_list); + up->mtd->owner = THIS_MODULE; - pdev->mtd->owner = THIS_MODULE; + add_mtd_device(up->mtd); - add_mtd_device(pdev->mtd); - return(0); + dev_set_drvdata(&edev->ofdev.dev, up); + + return 0; } -static int __init uflash_init(void) +static int __devinit uflash_probe(struct of_device *dev, const struct of_device_id *match) { - struct linux_ebus *ebus = NULL; - struct linux_ebus_device *edev = NULL; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, UFLASH_OBPNAME)) { - if(0 > prom_getproplen(edev->prom_node, "user")) { - DEBUG(2, "%s: ignoring device at 0x%lx\n", - UFLASH_DEVNAME, edev->resource[0].start); - } else { - uflash_devinit(edev); - } - } - } - } + struct linux_ebus_device *edev = to_ebus_device(&dev->dev); + struct device_node *dp = dev->node; - if(list_empty(&device_list)) { - printk("%s: unable to locate device\n", UFLASH_DEVNAME); + if (of_find_property(dp, "user", NULL)) return -ENODEV; - } - return(0); + + return uflash_devinit(edev, dp); } -static void __exit uflash_cleanup(void) +static int __devexit uflash_remove(struct of_device *dev) { - struct list_head *udevlist; - struct uflash_dev *udev; - - list_for_each(udevlist, &device_list) { - udev = list_entry(udevlist, struct uflash_dev, list); - DEBUG(2, "%s: removing device %s\n", - UFLASH_DEVNAME, udev->name); - - if(0 != udev->mtd) { - del_mtd_device(udev->mtd); - map_destroy(udev->mtd); - } - if(0 != udev->map.virt) { - iounmap(udev->map.virt); - udev->map.virt = NULL; - } - kfree(udev->name); - kfree(udev); + struct uflash_dev *up = dev_get_drvdata(&dev->dev); + + if (up->mtd) { + del_mtd_device(up->mtd); + map_destroy(up->mtd); } + if (up->map.virt) { + iounmap(up->map.virt); + up->map.virt = NULL; + } + + kfree(up); + + return 0; +} + +static struct of_device_id uflash_match[] = { + { + .name = UFLASH_OBPNAME, + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, uflash_match); + +static struct of_platform_driver uflash_driver = { + .name = UFLASH_DEVNAME, + .match_table = uflash_match, + .probe = uflash_probe, + .remove = __devexit_p(uflash_remove), +}; + +static int __init uflash_init(void) +{ + return of_register_driver(&uflash_driver, &ebus_bus_type); +} + +static void __exit uflash_exit(void) +{ + of_unregister_driver(&uflash_driver); } module_init(uflash_init); -module_exit(uflash_cleanup); +module_exit(uflash_exit); diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index 2cef280..e5c7846 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -71,7 +71,7 @@ static int erase_write (struct mtd_info set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&wait_q, &wait); - ret = MTD_ERASE(mtd, &erase); + ret = mtd->erase(mtd, &erase); if (ret) { set_current_state(TASK_RUNNING); remove_wait_queue(&wait_q, &wait); @@ -88,7 +88,7 @@ static int erase_write (struct mtd_info * Next, writhe data to flash. */ - ret = MTD_WRITE (mtd, pos, len, &retlen, buf); + ret = mtd->write(mtd, pos, len, &retlen, buf); if (ret) return ret; if (retlen != len) @@ -138,7 +138,7 @@ static int do_cached_write (struct mtdbl mtd->name, pos, len); if (!sect_size) - return MTD_WRITE (mtd, pos, len, &retlen, buf); + return mtd->write(mtd, pos, len, &retlen, buf); while (len > 0) { unsigned long sect_start = (pos/sect_size)*sect_size; @@ -170,7 +170,8 @@ static int do_cached_write (struct mtdbl mtdblk->cache_offset != sect_start) { /* fill the cache with the current sector */ mtdblk->cache_state = STATE_EMPTY; - ret = MTD_READ(mtd, sect_start, sect_size, &retlen, mtdblk->cache_data); + ret = mtd->read(mtd, sect_start, sect_size, + &retlen, mtdblk->cache_data); if (ret) return ret; if (retlen != sect_size) @@ -207,7 +208,7 @@ static int do_cached_read (struct mtdblk mtd->name, pos, len); if (!sect_size) - return MTD_READ (mtd, pos, len, &retlen, buf); + return mtd->read(mtd, pos, len, &retlen, buf); while (len > 0) { unsigned long sect_start = (pos/sect_size)*sect_size; @@ -226,7 +227,7 @@ static int do_cached_read (struct mtdblk mtdblk->cache_offset == sect_start) { memcpy (buf, mtdblk->cache_data + offset, size); } else { - ret = MTD_READ (mtd, pos, size, &retlen, buf); + ret = mtd->read(mtd, pos, size, &retlen, buf); if (ret) return ret; if (retlen != size) @@ -288,8 +289,7 @@ static int mtdblock_open(struct mtd_blkt mutex_init(&mtdblk->cache_mutex); mtdblk->cache_state = STATE_EMPTY; - if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM && - mtdblk->mtd->erasesize) { + if ( !(mtdblk->mtd->flags & MTD_NO_ERASE) && mtdblk->mtd->erasesize) { mtdblk->cache_size = mtdblk->mtd->erasesize; mtdblk->cache_data = NULL; } diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c index 0c830ba..29563ed 100644 --- a/drivers/mtd/mtdblock_ro.c +++ b/drivers/mtd/mtdblock_ro.c @@ -45,9 +45,7 @@ static void mtdblock_add_mtd(struct mtd_ dev->blksize = 512; dev->size = mtd->size >> 9; dev->tr = tr; - if ((mtd->flags & (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE)) != - (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE)) - dev->readonly = 1; + dev->readonly = 1; add_mtd_blktrans_dev(dev); } diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 6f04458..aa18d45 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -49,24 +49,18 @@ static struct mtd_notifier notifier = { }; /* - * We use file->private_data to store a pointer to the MTDdevice. - * Since alighment is at least 32 bits, we have 2 bits free for OTP - * modes as well. + * Data structure to hold the pointer to the mtd device as well + * as mode information ofr various use cases. */ - -#define TO_MTD(file) (struct mtd_info *)((long)((file)->private_data) & ~3L) - -#define MTD_MODE_OTP_FACT 1 -#define MTD_MODE_OTP_USER 2 -#define MTD_MODE(file) ((long)((file)->private_data) & 3) - -#define SET_MTD_MODE(file, mode) \ - do { long __p = (long)((file)->private_data); \ - (file)->private_data = (void *)((__p & ~3L) | mode); } while (0) +struct mtd_file_info { + struct mtd_info *mtd; + enum mtd_file_modes mode; +}; static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) { - struct mtd_info *mtd = TO_MTD(file); + struct mtd_file_info *mfi = file->private_data; + struct mtd_info *mtd = mfi->mtd; switch (orig) { case 0: @@ -97,6 +91,7 @@ static int mtd_open(struct inode *inode, int minor = iminor(inode); int devnum = minor >> 1; struct mtd_info *mtd; + struct mtd_file_info *mfi; DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n"); @@ -117,14 +112,20 @@ static int mtd_open(struct inode *inode, return -ENODEV; } - file->private_data = mtd; - /* You can't open it RW if it's not a writeable device */ if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) { put_mtd_device(mtd); return -EACCES; } + mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); + if (!mfi) { + put_mtd_device(mtd); + return -ENOMEM; + } + mfi->mtd = mtd; + file->private_data = mfi; + return 0; } /* mtd_open */ @@ -132,16 +133,17 @@ static int mtd_open(struct inode *inode, static int mtd_close(struct inode *inode, struct file *file) { - struct mtd_info *mtd; + struct mtd_file_info *mfi = file->private_data; + struct mtd_info *mtd = mfi->mtd; DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n"); - mtd = TO_MTD(file); - if (mtd->sync) mtd->sync(mtd); put_mtd_device(mtd); + file->private_data = NULL; + kfree(mfi); return 0; } /* mtd_close */ @@ -153,7 +155,8 @@ #define MAX_KMALLOC_SIZE 0x20000 static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos) { - struct mtd_info *mtd = TO_MTD(file); + struct mtd_file_info *mfi = file->private_data; + struct mtd_info *mtd = mfi->mtd; size_t retlen=0; size_t total_retlen=0; int ret=0; @@ -170,36 +173,58 @@ static ssize_t mtd_read(struct file *fil /* FIXME: Use kiovec in 2.5 to lock down the user's buffers and pass them directly to the MTD functions */ + + if (count > MAX_KMALLOC_SIZE) + kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL); + else + kbuf=kmalloc(count, GFP_KERNEL); + + if (!kbuf) + return -ENOMEM; + while (count) { + if (count > MAX_KMALLOC_SIZE) len = MAX_KMALLOC_SIZE; else len = count; - kbuf=kmalloc(len,GFP_KERNEL); - if (!kbuf) - return -ENOMEM; - - switch (MTD_MODE(file)) { - case MTD_MODE_OTP_FACT: + switch (mfi->mode) { + case MTD_MODE_OTP_FACTORY: ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf); break; case MTD_MODE_OTP_USER: ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); break; + case MTD_MODE_RAW: + { + struct mtd_oob_ops ops; + + ops.mode = MTD_OOB_RAW; + ops.datbuf = kbuf; + ops.oobbuf = NULL; + ops.len = len; + + ret = mtd->read_oob(mtd, *ppos, &ops); + retlen = ops.retlen; + break; + } default: - ret = MTD_READ(mtd, *ppos, len, &retlen, kbuf); + ret = mtd->read(mtd, *ppos, len, &retlen, kbuf); } /* Nand returns -EBADMSG on ecc errors, but it returns * the data. For our userspace tools it is important * to dump areas with ecc errors ! + * For kernel internal usage it also might return -EUCLEAN + * to signal the caller that a bitflip has occured and has + * been corrected by the ECC algorithm. * Userspace software which accesses NAND this way * must be aware of the fact that it deals with NAND */ - if (!ret || (ret == -EBADMSG)) { + if (!ret || (ret == -EUCLEAN) || (ret == -EBADMSG)) { *ppos += retlen; if (copy_to_user(buf, kbuf, retlen)) { - kfree(kbuf); + kfree(kbuf); return -EFAULT; } else @@ -215,15 +240,16 @@ static ssize_t mtd_read(struct file *fil return ret; } - kfree(kbuf); } + kfree(kbuf); return total_retlen; } /* mtd_read */ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos) { - struct mtd_info *mtd = TO_MTD(file); + struct mtd_file_info *mfi = file->private_data; + struct mtd_info *mtd = mfi->mtd; char *kbuf; size_t retlen; size_t total_retlen=0; @@ -241,25 +267,28 @@ static ssize_t mtd_write(struct file *fi if (!count) return 0; + if (count > MAX_KMALLOC_SIZE) + kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL); + else + kbuf=kmalloc(count, GFP_KERNEL); + + if (!kbuf) + return -ENOMEM; + while (count) { + if (count > MAX_KMALLOC_SIZE) len = MAX_KMALLOC_SIZE; else len = count; - kbuf=kmalloc(len,GFP_KERNEL); - if (!kbuf) { - printk("kmalloc is null\n"); - return -ENOMEM; - } - if (copy_from_user(kbuf, buf, len)) { kfree(kbuf); return -EFAULT; } - switch (MTD_MODE(file)) { - case MTD_MODE_OTP_FACT: + switch (mfi->mode) { + case MTD_MODE_OTP_FACTORY: ret = -EROFS; break; case MTD_MODE_OTP_USER: @@ -269,6 +298,21 @@ static ssize_t mtd_write(struct file *fi } ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); break; + + case MTD_MODE_RAW: + { + struct mtd_oob_ops ops; + + ops.mode = MTD_OOB_RAW; + ops.datbuf = kbuf; + ops.oobbuf = NULL; + ops.len = len; + + ret = mtd->write_oob(mtd, *ppos, &ops); + retlen = ops.retlen; + break; + } + default: ret = (*(mtd->write))(mtd, *ppos, len, &retlen, kbuf); } @@ -282,10 +326,9 @@ static ssize_t mtd_write(struct file *fi kfree(kbuf); return ret; } - - kfree(kbuf); } + kfree(kbuf); return total_retlen; } /* mtd_write */ @@ -299,13 +342,45 @@ static void mtdchar_erase_callback (stru wake_up((wait_queue_head_t *)instr->priv); } +#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP) +static int otp_select_filemode(struct mtd_file_info *mfi, int mode) +{ + struct mtd_info *mtd = mfi->mtd; + int ret = 0; + + switch (mode) { + case MTD_OTP_FACTORY: + if (!mtd->read_fact_prot_reg) + ret = -EOPNOTSUPP; + else + mfi->mode = MTD_MODE_OTP_FACTORY; + break; + case MTD_OTP_USER: + if (!mtd->read_fact_prot_reg) + ret = -EOPNOTSUPP; + else + mfi->mode = MTD_MODE_OTP_USER; + break; + default: + ret = -EINVAL; + case MTD_OTP_OFF: + break; + } + return ret; +} +#else +# define otp_select_filemode(f,m) -EOPNOTSUPP +#endif + static int mtd_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) { - struct mtd_info *mtd = TO_MTD(file); + struct mtd_file_info *mfi = file->private_data; + struct mtd_info *mtd = mfi->mtd; void __user *argp = (void __user *)arg; int ret = 0; u_long size; + struct mtd_info_user info; DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n"); @@ -341,7 +416,15 @@ static int mtd_ioctl(struct inode *inode } case MEMGETINFO: - if (copy_to_user(argp, mtd, sizeof(struct mtd_info_user))) + info.type = mtd->type; + info.flags = mtd->flags; + info.size = mtd->size; + info.erasesize = mtd->erasesize; + info.writesize = mtd->writesize; + info.oobsize = mtd->oobsize; + info.ecctype = mtd->ecctype; + info.eccsize = mtd->eccsize; + if (copy_to_user(argp, &info, sizeof(struct mtd_info_user))) return -EFAULT; break; @@ -400,8 +483,7 @@ static int mtd_ioctl(struct inode *inode case MEMWRITEOOB: { struct mtd_oob_buf buf; - void *databuf; - ssize_t retlen; + struct mtd_oob_ops ops; if(!(file->f_mode & 2)) return -EPERM; @@ -409,7 +491,7 @@ static int mtd_ioctl(struct inode *inode if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) return -EFAULT; - if (buf.length > 0x4096) + if (buf.length > 4096) return -EINVAL; if (!mtd->write_oob) @@ -421,21 +503,32 @@ static int mtd_ioctl(struct inode *inode if (ret) return ret; - databuf = kmalloc(buf.length, GFP_KERNEL); - if (!databuf) + ops.len = buf.length; + ops.ooblen = buf.length; + ops.ooboffs = buf.start & (mtd->oobsize - 1); + ops.datbuf = NULL; + ops.mode = MTD_OOB_PLACE; + + if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs)) + return -EINVAL; + + ops.oobbuf = kmalloc(buf.length, GFP_KERNEL); + if (!ops.oobbuf) return -ENOMEM; - if (copy_from_user(databuf, buf.ptr, buf.length)) { - kfree(databuf); + if (copy_from_user(ops.oobbuf, buf.ptr, buf.length)) { + kfree(ops.oobbuf); return -EFAULT; } - ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf); + buf.start &= ~(mtd->oobsize - 1); + ret = mtd->write_oob(mtd, buf.start, &ops); - if (copy_to_user(argp + sizeof(uint32_t), &retlen, sizeof(uint32_t))) + if (copy_to_user(argp + sizeof(uint32_t), &ops.retlen, + sizeof(uint32_t))) ret = -EFAULT; - kfree(databuf); + kfree(ops.oobbuf); break; } @@ -443,13 +536,12 @@ static int mtd_ioctl(struct inode *inode case MEMREADOOB: { struct mtd_oob_buf buf; - void *databuf; - ssize_t retlen; + struct mtd_oob_ops ops; if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) return -EFAULT; - if (buf.length > 0x4096) + if (buf.length > 4096) return -EINVAL; if (!mtd->read_oob) @@ -457,22 +549,32 @@ static int mtd_ioctl(struct inode *inode else ret = access_ok(VERIFY_WRITE, buf.ptr, buf.length) ? 0 : -EFAULT; - if (ret) return ret; - databuf = kmalloc(buf.length, GFP_KERNEL); - if (!databuf) + ops.len = buf.length; + ops.ooblen = buf.length; + ops.ooboffs = buf.start & (mtd->oobsize - 1); + ops.datbuf = NULL; + ops.mode = MTD_OOB_PLACE; + + if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs)) + return -EINVAL; + + ops.oobbuf = kmalloc(buf.length, GFP_KERNEL); + if (!ops.oobbuf) return -ENOMEM; - ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf); + buf.start &= ~(mtd->oobsize - 1); + ret = mtd->read_oob(mtd, buf.start, &ops); - if (put_user(retlen, (uint32_t __user *)argp)) + if (put_user(ops.retlen, (uint32_t __user *)argp)) ret = -EFAULT; - else if (retlen && copy_to_user(buf.ptr, databuf, retlen)) + else if (ops.retlen && copy_to_user(buf.ptr, ops.oobbuf, + ops.retlen)) ret = -EFAULT; - kfree(databuf); + kfree(ops.oobbuf); break; } @@ -504,16 +606,22 @@ static int mtd_ioctl(struct inode *inode break; } - case MEMSETOOBSEL: - { - if (copy_from_user(&mtd->oobinfo, argp, sizeof(struct nand_oobinfo))) - return -EFAULT; - break; - } - + /* Legacy interface */ case MEMGETOOBSEL: { - if (copy_to_user(argp, &(mtd->oobinfo), sizeof(struct nand_oobinfo))) + struct nand_oobinfo oi; + + if (!mtd->ecclayout) + return -EOPNOTSUPP; + if (mtd->ecclayout->eccbytes > ARRAY_SIZE(oi.eccpos)) + return -EINVAL; + + oi.useecc = MTD_NANDECC_AUTOPLACE; + memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos)); + memcpy(&oi.oobfree, mtd->ecclayout->oobfree, + sizeof(oi.oobfree)); + + if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo))) return -EFAULT; break; } @@ -544,31 +652,17 @@ static int mtd_ioctl(struct inode *inode break; } -#ifdef CONFIG_MTD_OTP +#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP) case OTPSELECT: { int mode; if (copy_from_user(&mode, argp, sizeof(int))) return -EFAULT; - SET_MTD_MODE(file, 0); - switch (mode) { - case MTD_OTP_FACTORY: - if (!mtd->read_fact_prot_reg) - ret = -EOPNOTSUPP; - else - SET_MTD_MODE(file, MTD_MODE_OTP_FACT); - break; - case MTD_OTP_USER: - if (!mtd->read_fact_prot_reg) - ret = -EOPNOTSUPP; - else - SET_MTD_MODE(file, MTD_MODE_OTP_USER); - break; - default: - ret = -EINVAL; - case MTD_OTP_OFF: - break; - } + + mfi->mode = MTD_MODE_NORMAL; + + ret = otp_select_filemode(mfi, mode); + file->f_pos = 0; break; } @@ -580,8 +674,8 @@ #ifdef CONFIG_MTD_OTP if (!buf) return -ENOMEM; ret = -EOPNOTSUPP; - switch (MTD_MODE(file)) { - case MTD_MODE_OTP_FACT: + switch (mfi->mode) { + case MTD_MODE_OTP_FACTORY: if (mtd->get_fact_prot_info) ret = mtd->get_fact_prot_info(mtd, buf, 4096); break; @@ -589,6 +683,8 @@ #ifdef CONFIG_MTD_OTP if (mtd->get_user_prot_info) ret = mtd->get_user_prot_info(mtd, buf, 4096); break; + default: + break; } if (ret >= 0) { if (cmd == OTPGETREGIONCOUNT) { @@ -607,7 +703,7 @@ #ifdef CONFIG_MTD_OTP { struct otp_info info; - if (MTD_MODE(file) != MTD_MODE_OTP_USER) + if (mfi->mode != MTD_MODE_OTP_USER) return -EINVAL; if (copy_from_user(&info, argp, sizeof(info))) return -EFAULT; @@ -618,6 +714,49 @@ #ifdef CONFIG_MTD_OTP } #endif + case ECCGETLAYOUT: + { + if (!mtd->ecclayout) + return -EOPNOTSUPP; + + if (copy_to_user(argp, &mtd->ecclayout, + sizeof(struct nand_ecclayout))) + return -EFAULT; + break; + } + + case ECCGETSTATS: + { + if (copy_to_user(argp, &mtd->ecc_stats, + sizeof(struct mtd_ecc_stats))) + return -EFAULT; + break; + } + + case MTDFILEMODE: + { + mfi->mode = 0; + + switch(arg) { + case MTD_MODE_OTP_FACTORY: + case MTD_MODE_OTP_USER: + ret = otp_select_filemode(mfi, arg); + break; + + case MTD_MODE_RAW: + if (!mtd->read_oob || !mtd->write_oob) + return -EOPNOTSUPP; + mfi->mode = arg; + + case MTD_MODE_NORMAL: + break; + default: + ret = -EINVAL; + } + file->f_pos = 0; + break; + } + default: ret = -ENOTTY; } diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 9af8403..1fea631 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -19,6 +19,8 @@ #include #include #include +#include + /* * Our storage structure: * Subdev points to an array of pointers to struct mtd_info objects @@ -54,7 +56,7 @@ concat_read(struct mtd_info *mtd, loff_t size_t * retlen, u_char * buf) { struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; + int ret = 0, err; int i; *retlen = 0; @@ -78,19 +80,29 @@ concat_read(struct mtd_info *mtd, loff_t err = subdev->read(subdev, from, size, &retsize, buf); - if (err) - break; + /* Save information about bitflips! */ + if (unlikely(err)) { + if (err == -EBADMSG) { + mtd->ecc_stats.failed++; + ret = err; + } else if (err == -EUCLEAN) { + mtd->ecc_stats.corrected++; + /* Do not overwrite -EBADMSG !! */ + if (!ret) + ret = err; + } else + return err; + } *retlen += retsize; len -= size; if (len == 0) - break; + return ret; - err = -EINVAL; buf += size; from = 0; } - return err; + return -EINVAL; } static int @@ -141,211 +153,185 @@ concat_write(struct mtd_info *mtd, loff_ } static int -concat_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, - size_t * retlen, u_char * buf, u_char * eccbuf, - struct nand_oobinfo *oobsel) +concat_writev(struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t * retlen) { struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; + struct kvec *vecs_copy; + unsigned long entry_low, entry_high; + size_t total_len = 0; int i; + int err = -EINVAL; - *retlen = 0; - - for (i = 0; i < concat->num_subdev; i++) { - struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; - - if (from >= subdev->size) { - /* Not destined for this subdev */ - size = 0; - from -= subdev->size; - continue; - } - - if (from + len > subdev->size) - /* First part goes into this subdev */ - size = subdev->size - from; - else - /* Entire transaction goes into this subdev */ - size = len; + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; - if (subdev->read_ecc) - err = subdev->read_ecc(subdev, from, size, - &retsize, buf, eccbuf, oobsel); - else - err = -EINVAL; + *retlen = 0; - if (err) - break; + /* Calculate total length of data */ + for (i = 0; i < count; i++) + total_len += vecs[i].iov_len; - *retlen += retsize; - len -= size; - if (len == 0) - break; + /* Do not allow write past end of device */ + if ((to + total_len) > mtd->size) + return -EINVAL; - err = -EINVAL; - buf += size; - if (eccbuf) { - eccbuf += subdev->oobsize; - /* in nand.c at least, eccbufs are - tagged with 2 (int)eccstatus'; we - must account for these */ - eccbuf += 2 * (sizeof (int)); - } - from = 0; + /* Check alignment */ + if (mtd->writesize > 1) { + loff_t __to = to; + if (do_div(__to, mtd->writesize) || (total_len % mtd->writesize)) + return -EINVAL; } - return err; -} -static int -concat_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, - size_t * retlen, const u_char * buf, u_char * eccbuf, - struct nand_oobinfo *oobsel) -{ - struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; - int i; - - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - - *retlen = 0; + /* make a copy of vecs */ + vecs_copy = kmalloc(sizeof(struct kvec) * count, GFP_KERNEL); + if (!vecs_copy) + return -ENOMEM; + memcpy(vecs_copy, vecs, sizeof(struct kvec) * count); + entry_low = 0; for (i = 0; i < concat->num_subdev; i++) { struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; + size_t size, wsize, retsize, old_iov_len; if (to >= subdev->size) { - size = 0; to -= subdev->size; continue; } - if (to + len > subdev->size) - size = subdev->size - to; - else - size = len; + + size = min(total_len, (size_t)(subdev->size - to)); + wsize = size; /* store for future use */ + + entry_high = entry_low; + while (entry_high < count) { + if (size <= vecs_copy[entry_high].iov_len) + break; + size -= vecs_copy[entry_high++].iov_len; + } + + old_iov_len = vecs_copy[entry_high].iov_len; + vecs_copy[entry_high].iov_len = size; if (!(subdev->flags & MTD_WRITEABLE)) err = -EROFS; - else if (subdev->write_ecc) - err = subdev->write_ecc(subdev, to, size, - &retsize, buf, eccbuf, oobsel); else - err = -EINVAL; + err = subdev->writev(subdev, &vecs_copy[entry_low], + entry_high - entry_low + 1, to, &retsize); + + vecs_copy[entry_high].iov_len = old_iov_len - size; + vecs_copy[entry_high].iov_base += size; + + entry_low = entry_high; if (err) break; *retlen += retsize; - len -= size; - if (len == 0) + total_len -= wsize; + + if (total_len == 0) break; err = -EINVAL; - buf += size; - if (eccbuf) - eccbuf += subdev->oobsize; to = 0; } + + kfree(vecs_copy); return err; } static int -concat_read_oob(struct mtd_info *mtd, loff_t from, size_t len, - size_t * retlen, u_char * buf) +concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; - int i; + struct mtd_oob_ops devops = *ops; + int i, err, ret = 0; - *retlen = 0; + ops->retlen = 0; for (i = 0; i < concat->num_subdev; i++) { struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; if (from >= subdev->size) { - /* Not destined for this subdev */ - size = 0; from -= subdev->size; continue; } - if (from + len > subdev->size) - /* First part goes into this subdev */ - size = subdev->size - from; - else - /* Entire transaction goes into this subdev */ - size = len; - if (subdev->read_oob) - err = subdev->read_oob(subdev, from, size, - &retsize, buf); - else - err = -EINVAL; + /* partial read ? */ + if (from + devops.len > subdev->size) + devops.len = subdev->size - from; + + err = subdev->read_oob(subdev, from, &devops); + ops->retlen += devops.retlen; + + /* Save information about bitflips! */ + if (unlikely(err)) { + if (err == -EBADMSG) { + mtd->ecc_stats.failed++; + ret = err; + } else if (err == -EUCLEAN) { + mtd->ecc_stats.corrected++; + /* Do not overwrite -EBADMSG !! */ + if (!ret) + ret = err; + } else + return err; + } - if (err) - break; + devops.len = ops->len - ops->retlen; + if (!devops.len) + return ret; - *retlen += retsize; - len -= size; - if (len == 0) - break; + if (devops.datbuf) + devops.datbuf += devops.retlen; + if (devops.oobbuf) + devops.oobbuf += devops.ooblen; - err = -EINVAL; - buf += size; from = 0; } - return err; + return -EINVAL; } static int -concat_write_oob(struct mtd_info *mtd, loff_t to, size_t len, - size_t * retlen, const u_char * buf) +concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) { struct mtd_concat *concat = CONCAT(mtd); - int err = -EINVAL; - int i; + struct mtd_oob_ops devops = *ops; + int i, err; if (!(mtd->flags & MTD_WRITEABLE)) return -EROFS; - *retlen = 0; + ops->retlen = 0; for (i = 0; i < concat->num_subdev; i++) { struct mtd_info *subdev = concat->subdev[i]; - size_t size, retsize; if (to >= subdev->size) { - size = 0; to -= subdev->size; continue; } - if (to + len > subdev->size) - size = subdev->size - to; - else - size = len; - if (!(subdev->flags & MTD_WRITEABLE)) - err = -EROFS; - else if (subdev->write_oob) - err = subdev->write_oob(subdev, to, size, &retsize, - buf); - else - err = -EINVAL; + /* partial write ? */ + if (to + devops.len > subdev->size) + devops.len = subdev->size - to; + err = subdev->write_oob(subdev, to, &devops); + ops->retlen += devops.retlen; if (err) - break; + return err; - *retlen += retsize; - len -= size; - if (len == 0) - break; + devops.len = ops->len - ops->retlen; + if (!devops.len) + return 0; - err = -EINVAL; - buf += size; + if (devops.datbuf) + devops.datbuf += devops.retlen; + if (devops.oobbuf) + devops.oobbuf += devops.ooblen; to = 0; } - return err; + return -EINVAL; } static void concat_erase_callback(struct erase_info *instr) @@ -636,6 +622,60 @@ static void concat_resume(struct mtd_inf } } +static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs) +{ + struct mtd_concat *concat = CONCAT(mtd); + int i, res = 0; + + if (!concat->subdev[0]->block_isbad) + return res; + + if (ofs > mtd->size) + return -EINVAL; + + for (i = 0; i < concat->num_subdev; i++) { + struct mtd_info *subdev = concat->subdev[i]; + + if (ofs >= subdev->size) { + ofs -= subdev->size; + continue; + } + + res = subdev->block_isbad(subdev, ofs); + break; + } + + return res; +} + +static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + struct mtd_concat *concat = CONCAT(mtd); + int i, err = -EINVAL; + + if (!concat->subdev[0]->block_markbad) + return 0; + + if (ofs > mtd->size) + return -EINVAL; + + for (i = 0; i < concat->num_subdev; i++) { + struct mtd_info *subdev = concat->subdev[i]; + + if (ofs >= subdev->size) { + ofs -= subdev->size; + continue; + } + + err = subdev->block_markbad(subdev, ofs); + if (!err) + mtd->ecc_stats.badblocks++; + break; + } + + return err; +} + /* * This function constructs a virtual MTD device by concatenating * num_devs MTD devices. A pointer to the new device object is @@ -677,18 +717,22 @@ struct mtd_info *mtd_concat_create(struc concat->mtd.flags = subdev[0]->flags; concat->mtd.size = subdev[0]->size; concat->mtd.erasesize = subdev[0]->erasesize; - concat->mtd.oobblock = subdev[0]->oobblock; + concat->mtd.writesize = subdev[0]->writesize; concat->mtd.oobsize = subdev[0]->oobsize; concat->mtd.ecctype = subdev[0]->ecctype; concat->mtd.eccsize = subdev[0]->eccsize; - if (subdev[0]->read_ecc) - concat->mtd.read_ecc = concat_read_ecc; - if (subdev[0]->write_ecc) - concat->mtd.write_ecc = concat_write_ecc; + if (subdev[0]->writev) + concat->mtd.writev = concat_writev; if (subdev[0]->read_oob) concat->mtd.read_oob = concat_read_oob; if (subdev[0]->write_oob) concat->mtd.write_oob = concat_write_oob; + if (subdev[0]->block_isbad) + concat->mtd.block_isbad = concat_block_isbad; + if (subdev[0]->block_markbad) + concat->mtd.block_markbad = concat_block_markbad; + + concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks; concat->subdev[0] = subdev[0]; @@ -717,12 +761,12 @@ struct mtd_info *mtd_concat_create(struc subdev[i]->flags & MTD_WRITEABLE; } concat->mtd.size += subdev[i]->size; - if (concat->mtd.oobblock != subdev[i]->oobblock || + concat->mtd.ecc_stats.badblocks += + subdev[i]->ecc_stats.badblocks; + if (concat->mtd.writesize != subdev[i]->writesize || concat->mtd.oobsize != subdev[i]->oobsize || concat->mtd.ecctype != subdev[i]->ecctype || concat->mtd.eccsize != subdev[i]->eccsize || - !concat->mtd.read_ecc != !subdev[i]->read_ecc || - !concat->mtd.write_ecc != !subdev[i]->write_ecc || !concat->mtd.read_oob != !subdev[i]->read_oob || !concat->mtd.write_oob != !subdev[i]->write_oob) { kfree(concat); @@ -734,14 +778,11 @@ struct mtd_info *mtd_concat_create(struc } + concat->mtd.ecclayout = subdev[0]->ecclayout; + concat->num_subdev = num_devs; concat->mtd.name = name; - /* - * NOTE: for now, we do not provide any readv()/writev() methods - * because they are messy to implement and they are not - * used to a great extent anyway. - */ concat->mtd.erase = concat_erase; concat->mtd.read = concat_read; concat->mtd.write = concat_write; diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 9905870..16a952d 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -47,6 +47,7 @@ int add_mtd_device(struct mtd_info *mtd) { int i; + BUG_ON(mtd->writesize == 0); mutex_lock(&mtd_table_mutex); for (i=0; i < MAX_MTD_DEVICES; i++) @@ -254,37 +255,6 @@ int default_mtd_writev(struct mtd_info * return ret; } - -/* default_mtd_readv - default mtd readv method for MTD devices that dont - * implement their own - */ - -int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, - unsigned long count, loff_t from, size_t *retlen) -{ - unsigned long i; - size_t totlen = 0, thislen; - int ret = 0; - - if(!mtd->read) { - ret = -EIO; - } else { - for (i=0; iread(mtd, from, vecs[i].iov_len, &thislen, vecs[i].iov_base); - totlen += thislen; - if (ret || thislen != vecs[i].iov_len) - break; - from += vecs[i].iov_len; - } - } - if (retlen) - *retlen = totlen; - return ret; -} - - EXPORT_SYMBOL(add_mtd_device); EXPORT_SYMBOL(del_mtd_device); EXPORT_SYMBOL(get_mtd_device); @@ -292,7 +262,6 @@ EXPORT_SYMBOL(put_mtd_device); EXPORT_SYMBOL(register_mtd_user); EXPORT_SYMBOL(unregister_mtd_user); EXPORT_SYMBOL(default_mtd_writev); -EXPORT_SYMBOL(default_mtd_readv); #ifdef CONFIG_PROC_FS diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 9939591..77a7123 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -51,16 +51,21 @@ static int part_read (struct mtd_info *m size_t *retlen, u_char *buf) { struct mtd_part *part = PART(mtd); + int res; + if (from >= mtd->size) len = 0; else if (from + len > mtd->size) len = mtd->size - from; - if (part->master->read_ecc == NULL) - return part->master->read (part->master, from + part->offset, - len, retlen, buf); - else - return part->master->read_ecc (part->master, from + part->offset, - len, retlen, buf, NULL, &mtd->oobinfo); + res = part->master->read (part->master, from + part->offset, + len, retlen, buf); + if (unlikely(res)) { + if (res == -EUCLEAN) + mtd->ecc_stats.corrected++; + if (res == -EBADMSG) + mtd->ecc_stats.failed++; + } + return res; } static int part_point (struct mtd_info *mtd, loff_t from, size_t len, @@ -74,6 +79,7 @@ static int part_point (struct mtd_info * return part->master->point (part->master, from + part->offset, len, retlen, buf); } + static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) { struct mtd_part *part = PART(mtd); @@ -81,31 +87,25 @@ static void part_unpoint (struct mtd_inf part->master->unpoint (part->master, addr, from + part->offset, len); } - -static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel) +static int part_read_oob(struct mtd_info *mtd, loff_t from, + struct mtd_oob_ops *ops) { struct mtd_part *part = PART(mtd); - if (oobsel == NULL) - oobsel = &mtd->oobinfo; - if (from >= mtd->size) - len = 0; - else if (from + len > mtd->size) - len = mtd->size - from; - return part->master->read_ecc (part->master, from + part->offset, - len, retlen, buf, eccbuf, oobsel); -} + int res; -static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - struct mtd_part *part = PART(mtd); if (from >= mtd->size) - len = 0; - else if (from + len > mtd->size) - len = mtd->size - from; - return part->master->read_oob (part->master, from + part->offset, - len, retlen, buf); + return -EINVAL; + if (from + ops->len > mtd->size) + return -EINVAL; + res = part->master->read_oob(part->master, from + part->offset, ops); + + if (unlikely(res)) { + if (res == -EUCLEAN) + mtd->ecc_stats.corrected++; + if (res == -EBADMSG) + mtd->ecc_stats.failed++; + } + return res; } static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, @@ -148,44 +148,23 @@ static int part_write (struct mtd_info * len = 0; else if (to + len > mtd->size) len = mtd->size - to; - if (part->master->write_ecc == NULL) - return part->master->write (part->master, to + part->offset, - len, retlen, buf); - else - return part->master->write_ecc (part->master, to + part->offset, - len, retlen, buf, NULL, &mtd->oobinfo); - + return part->master->write (part->master, to + part->offset, + len, retlen, buf); } -static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, - u_char *eccbuf, struct nand_oobinfo *oobsel) +static int part_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops) { struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - if (oobsel == NULL) - oobsel = &mtd->oobinfo; - if (to >= mtd->size) - len = 0; - else if (to + len > mtd->size) - len = mtd->size - to; - return part->master->write_ecc (part->master, to + part->offset, - len, retlen, buf, eccbuf, oobsel); -} -static int part_write_oob (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - struct mtd_part *part = PART(mtd); if (!(mtd->flags & MTD_WRITEABLE)) return -EROFS; + if (to >= mtd->size) - len = 0; - else if (to + len > mtd->size) - len = mtd->size - to; - return part->master->write_oob (part->master, to + part->offset, - len, retlen, buf); + return -EINVAL; + if (to + ops->len > mtd->size) + return -EINVAL; + return part->master->write_oob(part->master, to + part->offset, ops); } static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, @@ -208,52 +187,8 @@ static int part_writev (struct mtd_info struct mtd_part *part = PART(mtd); if (!(mtd->flags & MTD_WRITEABLE)) return -EROFS; - if (part->master->writev_ecc == NULL) - return part->master->writev (part->master, vecs, count, + return part->master->writev (part->master, vecs, count, to + part->offset, retlen); - else - return part->master->writev_ecc (part->master, vecs, count, - to + part->offset, retlen, - NULL, &mtd->oobinfo); -} - -static int part_readv (struct mtd_info *mtd, struct kvec *vecs, - unsigned long count, loff_t from, size_t *retlen) -{ - struct mtd_part *part = PART(mtd); - if (part->master->readv_ecc == NULL) - return part->master->readv (part->master, vecs, count, - from + part->offset, retlen); - else - return part->master->readv_ecc (part->master, vecs, count, - from + part->offset, retlen, - NULL, &mtd->oobinfo); -} - -static int part_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t *retlen, - u_char *eccbuf, struct nand_oobinfo *oobsel) -{ - struct mtd_part *part = PART(mtd); - if (!(mtd->flags & MTD_WRITEABLE)) - return -EROFS; - if (oobsel == NULL) - oobsel = &mtd->oobinfo; - return part->master->writev_ecc (part->master, vecs, count, - to + part->offset, retlen, - eccbuf, oobsel); -} - -static int part_readv_ecc (struct mtd_info *mtd, struct kvec *vecs, - unsigned long count, loff_t from, size_t *retlen, - u_char *eccbuf, struct nand_oobinfo *oobsel) -{ - struct mtd_part *part = PART(mtd); - if (oobsel == NULL) - oobsel = &mtd->oobinfo; - return part->master->readv_ecc (part->master, vecs, count, - from + part->offset, retlen, - eccbuf, oobsel); } static int part_erase (struct mtd_info *mtd, struct erase_info *instr) @@ -329,12 +264,17 @@ static int part_block_isbad (struct mtd_ static int part_block_markbad (struct mtd_info *mtd, loff_t ofs) { struct mtd_part *part = PART(mtd); + int res; + if (!(mtd->flags & MTD_WRITEABLE)) return -EROFS; if (ofs >= mtd->size) return -EINVAL; ofs += part->offset; - return part->master->block_markbad(part->master, ofs); + res = part->master->block_markbad(part->master, ofs); + if (!res) + mtd->ecc_stats.badblocks++; + return res; } /* @@ -398,7 +338,7 @@ int add_mtd_partitions(struct mtd_info * slave->mtd.type = master->type; slave->mtd.flags = master->flags & ~parts[i].mask_flags; slave->mtd.size = parts[i].size; - slave->mtd.oobblock = master->oobblock; + slave->mtd.writesize = master->writesize; slave->mtd.oobsize = master->oobsize; slave->mtd.ecctype = master->ecctype; slave->mtd.eccsize = master->eccsize; @@ -415,10 +355,6 @@ int add_mtd_partitions(struct mtd_info * slave->mtd.unpoint = part_unpoint; } - if (master->read_ecc) - slave->mtd.read_ecc = part_read_ecc; - if (master->write_ecc) - slave->mtd.write_ecc = part_write_ecc; if (master->read_oob) slave->mtd.read_oob = part_read_oob; if (master->write_oob) @@ -443,12 +379,6 @@ int add_mtd_partitions(struct mtd_info * } if (master->writev) slave->mtd.writev = part_writev; - if (master->readv) - slave->mtd.readv = part_readv; - if (master->writev_ecc) - slave->mtd.writev_ecc = part_writev_ecc; - if (master->readv_ecc) - slave->mtd.readv_ecc = part_readv_ecc; if (master->lock) slave->mtd.lock = part_lock; if (master->unlock) @@ -528,8 +458,17 @@ int add_mtd_partitions(struct mtd_info * parts[i].name); } - /* copy oobinfo from master */ - memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo)); + slave->mtd.ecclayout = master->ecclayout; + if (master->block_isbad) { + uint32_t offs = 0; + + while(offs < slave->mtd.size) { + if (master->block_isbad(master, + offs + slave->offset)) + slave->mtd.ecc_stats.badblocks++; + offs += slave->mtd.erasesize; + } + } if(parts[i].mtdp) { /* store the object pointer (caller may or may not register it */ diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index cfe288a..3db77ee 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -23,6 +23,14 @@ config MTD_NAND_VERIFY_WRITE device thinks the write was successful, a bit could have been flipped accidentaly due to device wear or something else. +config MTD_NAND_ECC_SMC + bool "NAND ECC Smart Media byte order" + depends on MTD_NAND + default n + help + Software ECC according to the Smart Media Specification. + The original Linux implementation had byte 0 and 1 swapped. + config MTD_NAND_AUTCPU12 tristate "SmartMediaCard on autronix autcpu12 board" depends on MTD_NAND && ARCH_AUTCPU12 @@ -49,12 +57,24 @@ config MTD_NAND_SPIA help If you had to ask, you don't have one. Say 'N'. +config MTD_NAND_AMS_DELTA + tristate "NAND Flash device on Amstrad E3" + depends on MACH_AMS_DELTA && MTD_NAND + help + Support for NAND flash on Amstrad E3 (Delta). + config MTD_NAND_TOTO tristate "NAND Flash device on TOTO board" - depends on ARCH_OMAP && MTD_NAND + depends on ARCH_OMAP && MTD_NAND && BROKEN help Support for NAND flash on Texas Instruments Toto platform. +config MTD_NAND_TS7250 + tristate "NAND Flash device on TS-7250 board" + depends on MACH_TS72XX && MTD_NAND + help + Support for NAND flash on Technologic Systems TS-7250 platform. + config MTD_NAND_IDS tristate @@ -76,7 +96,7 @@ config MTD_NAND_RTC_FROM4 config MTD_NAND_PPCHAMELEONEVB tristate "NAND Flash device on PPChameleonEVB board" - depends on PPCHAMELEONEVB && MTD_NAND + depends on PPCHAMELEONEVB && MTD_NAND && BROKEN help This enables the NAND flash driver on the PPChameleon EVB Board. @@ -87,7 +107,7 @@ config MTD_NAND_S3C2410 This enables the NAND flash controller on the S3C2410 and S3C2440 SoCs - No board specfic support is done by this driver, each board + No board specific support is done by this driver, each board must advertise a platform_device for the driver to attach. config MTD_NAND_S3C2410_DEBUG @@ -109,6 +129,22 @@ config MTD_NAND_S3C2410_HWECC currently not be able to switch to software, as there is no implementation for ECC method used by the S3C2410 +config MTD_NAND_NDFC + tristate "NDFC NanD Flash Controller" + depends on MTD_NAND && 44x + help + NDFC Nand Flash Controllers are integrated in EP44x SoCs + +config MTD_NAND_S3C2410_CLKSTOP + bool "S3C2410 NAND IDLE clock stop" + depends on MTD_NAND_S3C2410 + default n + help + Stop the clock to the NAND controller when there is no chip + selected to save power. This will mean there is a small delay + when the is NAND chip selected or released, but will save + approximately 5mA of power when there is nothing happening. + config MTD_NAND_DISKONCHIP tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" depends on MTD_NAND && EXPERIMENTAL @@ -183,11 +219,24 @@ config MTD_NAND_SHARPSL tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" depends on MTD_NAND && ARCH_PXA +config MTD_NAND_CS553X + tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" + depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH) + help + The CS553x companion chips for the AMD Geode processor + include NAND flash controllers with built-in hardware ECC + capabilities; enabling this option will allow you to use + these. The driver will check the MSRs to verify that the + controller is enabled for NAND, and currently requires that + the controller be in MMIO mode. + + If you say "m", the module will be called "cs553x_nand.ko". + config MTD_NAND_NANDSIM tristate "Support for NAND Flash Simulator" depends on MTD_NAND && MTD_PARTITIONS help - The simulator may simulate verious NAND flash chips for the + The simulator may simulate various NAND flash chips for the MTD nand layer. endmenu diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 4174202..f747593 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_MTD_NAND) += nand.o nand_ obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o obj-$(CONFIG_MTD_NAND_SPIA) += spia.o +obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o obj-$(CONFIG_MTD_NAND_TOTO) += toto.o obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o @@ -17,6 +18,9 @@ obj-$(CONFIG_MTD_NAND_DISKONCHIP) += dis obj-$(CONFIG_MTD_NAND_H1900) += h1910.o obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o +obj-$(CONFIG_MTD_NAND_TS7250) += ts7250.o obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o +obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o +obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o nand-objs = nand_base.o nand_bbt.o diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c new file mode 100644 index 0000000..d7897dc --- /dev/null +++ b/drivers/mtd/nand/ams-delta.c @@ -0,0 +1,237 @@ +/* + * drivers/mtd/nand/ams-delta.c + * + * Copyright (C) 2006 Jonathan McDowell + * + * Derived from drivers/mtd/toto.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the NAND flash device found on the + * Amstrad E3 (Delta). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * MTD structure for E3 (Delta) + */ +static struct mtd_info *ams_delta_mtd = NULL; + +#define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP) + +/* + * Define partitions for flash devices + */ + +static struct mtd_partition partition_info[] = { + { .name = "Kernel", + .offset = 0, + .size = 3 * SZ_1M + SZ_512K }, + { .name = "u-boot", + .offset = 3 * SZ_1M + SZ_512K, + .size = SZ_256K }, + { .name = "u-boot params", + .offset = 3 * SZ_1M + SZ_512K + SZ_256K, + .size = SZ_256K }, + { .name = "Amstrad LDR", + .offset = 4 * SZ_1M, + .size = SZ_256K }, + { .name = "File system", + .offset = 4 * SZ_1M + 1 * SZ_256K, + .size = 27 * SZ_1M }, + { .name = "PBL reserved", + .offset = 32 * SZ_1M - 3 * SZ_256K, + .size = 3 * SZ_256K }, +}; + +static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) +{ + struct nand_chip *this = mtd->priv; + + omap_writew(0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL)); + omap_writew(byte, this->IO_ADDR_W); + ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0); + ndelay(40); + ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, + AMS_DELTA_LATCH2_NAND_NWE); +} + +static u_char ams_delta_read_byte(struct mtd_info *mtd) +{ + u_char res; + struct nand_chip *this = mtd->priv; + + ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0); + ndelay(40); + omap_writew(~0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL)); + res = omap_readw(this->IO_ADDR_R); + ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, + AMS_DELTA_LATCH2_NAND_NRE); + + return res; +} + +static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf, + int len) +{ + int i; + + for (i=0; i bit 2 + * NAND_CLE: bit 1 -> bit 7 + * NAND_ALE: bit 2 -> bit 6 + */ +static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ + + if (ctrl & NAND_CTRL_CHANGE) { + unsigned long bits; + + bits = (~ctrl & NAND_NCE) << 2; + bits |= (ctrl & NAND_CLE) << 7; + bits |= (ctrl & NAND_ALE) << 6; + + ams_delta_latch2_write(0xC2, bits); + } + + if (cmd != NAND_CMD_NONE) + ams_delta_write_byte(mtd, cmd); +} + +static int ams_delta_nand_ready(struct mtd_info *mtd) +{ + return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB); +} + +/* + * Main initialization routine + */ +static int __init ams_delta_init(void) +{ + struct nand_chip *this; + int err = 0; + + /* Allocate memory for MTD device structure and private data */ + ams_delta_mtd = kmalloc(sizeof(struct mtd_info) + + sizeof(struct nand_chip), GFP_KERNEL); + if (!ams_delta_mtd) { + printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n"); + err = -ENOMEM; + goto out; + } + + ams_delta_mtd->owner = THIS_MODULE; + + /* Get pointer to private data */ + this = (struct nand_chip *) (&ams_delta_mtd[1]); + + /* Initialize structures */ + memset(ams_delta_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); + + /* Link the private data with the MTD structure */ + ams_delta_mtd->priv = this; + + /* Set address of NAND IO lines */ + this->IO_ADDR_R = (OMAP_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH); + this->IO_ADDR_W = (OMAP_MPUIO_BASE + OMAP_MPUIO_OUTPUT); + this->read_byte = ams_delta_read_byte; + this->write_buf = ams_delta_write_buf; + this->read_buf = ams_delta_read_buf; + this->verify_buf = ams_delta_verify_buf; + this->cmd_ctrl = ams_delta_hwcontrol; + if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) { + this->dev_ready = ams_delta_nand_ready; + } else { + this->dev_ready = NULL; + printk(KERN_NOTICE "Couldn't request gpio for Delta NAND ready.\n"); + } + /* 25 us command delay time */ + this->chip_delay = 30; + this->ecc.mode = NAND_ECC_SOFT; + + /* Set chip enabled, but */ + ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE | + AMS_DELTA_LATCH2_NAND_NWE | + AMS_DELTA_LATCH2_NAND_NCE | + AMS_DELTA_LATCH2_NAND_NWP); + + /* Scan to find existance of the device */ + if (nand_scan(ams_delta_mtd, 1)) { + err = -ENXIO; + goto out_mtd; + } + + /* Register the partitions */ + add_mtd_partitions(ams_delta_mtd, partition_info, + ARRAY_SIZE(partition_info)); + + goto out; + + out_mtd: + kfree(ams_delta_mtd); + out: + return err; +} + +module_init(ams_delta_init); + +/* + * Clean up routine + */ +static void __exit ams_delta_cleanup(void) +{ + /* Release resources, unregister device */ + nand_release(ams_delta_mtd); + + /* Free the MTD device structure */ + kfree(ams_delta_mtd); +} +module_exit(ams_delta_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jonathan McDowell "); +MODULE_DESCRIPTION("Glue layer for NAND flash on Amstrad E3 (Delta)"); diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index bde3550..3122833 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -38,22 +39,21 @@ #endif */ static struct mtd_info *au1550_mtd = NULL; static void __iomem *p_nand; -static int nand_width = 1; /* default x8*/ +static int nand_width = 1; /* default x8 */ +static void (*au1550_write_byte)(struct mtd_info *, u_char); /* * Define partitions for flash device */ static const struct mtd_partition partition_info[] = { { - .name = "NAND FS 0", - .offset = 0, - .size = 8*1024*1024 - }, + .name = "NAND FS 0", + .offset = 0, + .size = 8 * 1024 * 1024}, { - .name = "NAND FS 1", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL - } + .name = "NAND FS 1", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL} }; /** @@ -130,21 +130,6 @@ static u16 au_read_word(struct mtd_info } /** - * au_write_word - write one word to the chip - * @mtd: MTD device structure - * @word: data word to write - * - * write function for 16bit buswith without - * endianess conversion - */ -static void au_write_word(struct mtd_info *mtd, u16 word) -{ - struct nand_chip *this = mtd->priv; - writew(word, this->IO_ADDR_W); - au_sync(); -} - -/** * au_write_buf - write buffer to chip * @mtd: MTD device structure * @buf: data buffer @@ -157,7 +142,7 @@ static void au_write_buf(struct mtd_info int i; struct nand_chip *this = mtd->priv; - for (i=0; iIO_ADDR_W); au_sync(); } @@ -176,7 +161,7 @@ static void au_read_buf(struct mtd_info int i; struct nand_chip *this = mtd->priv; - for (i=0; iIO_ADDR_R); au_sync(); } @@ -195,7 +180,7 @@ static int au_verify_buf(struct mtd_info int i; struct nand_chip *this = mtd->priv; - for (i=0; iIO_ADDR_R)) return -EFAULT; au_sync(); @@ -219,7 +204,7 @@ static void au_write_buf16(struct mtd_in u16 *p = (u16 *) buf; len >>= 1; - for (i=0; iIO_ADDR_W); au_sync(); } @@ -241,7 +226,7 @@ static void au_read_buf16(struct mtd_inf u16 *p = (u16 *) buf; len >>= 1; - for (i=0; iIO_ADDR_R); au_sync(); } @@ -262,7 +247,7 @@ static int au_verify_buf16(struct mtd_in u16 *p = (u16 *) buf; len >>= 1; - for (i=0; iIO_ADDR_R)) return -EFAULT; au_sync(); @@ -270,32 +255,52 @@ static int au_verify_buf16(struct mtd_in return 0; } +/* Select the chip by setting nCE to low */ +#define NAND_CTL_SETNCE 1 +/* Deselect the chip by setting nCE to high */ +#define NAND_CTL_CLRNCE 2 +/* Select the command latch by setting CLE to high */ +#define NAND_CTL_SETCLE 3 +/* Deselect the command latch by setting CLE to low */ +#define NAND_CTL_CLRCLE 4 +/* Select the address latch by setting ALE to high */ +#define NAND_CTL_SETALE 5 +/* Deselect the address latch by setting ALE to low */ +#define NAND_CTL_CLRALE 6 static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) { register struct nand_chip *this = mtd->priv; - switch(cmd){ + switch (cmd) { - case NAND_CTL_SETCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; break; - case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break; + case NAND_CTL_SETCLE: + this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; + break; + + case NAND_CTL_CLRCLE: + this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; + break; + + case NAND_CTL_SETALE: + this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; + break; - case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break; case NAND_CTL_CLRALE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; - /* FIXME: Nobody knows why this is neccecary, + /* FIXME: Nobody knows why this is necessary, * but it works only that way */ udelay(1); break; case NAND_CTL_SETNCE: /* assert (force assert) chip enable */ - au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break; + au_writel((1 << (4 + NAND_CS)), MEM_STNDCTL); break; case NAND_CTL_CLRNCE: - /* deassert chip enable */ - au_writel(0, MEM_STNDCTL); break; + /* deassert chip enable */ + au_writel(0, MEM_STNDCTL); break; } @@ -312,69 +317,200 @@ int au1550_device_ready(struct mtd_info return ret; } +/** + * au1550_select_chip - control -CE line + * Forbid driving -CE manually permitting the NAND controller to do this. + * Keeping -CE asserted during the whole sector reads interferes with the + * NOR flash and PCMCIA drivers as it causes contention on the static bus. + * We only have to hold -CE low for the NAND read commands since the flash + * chip needs it to be asserted during chip not ready time but the NAND + * controller keeps it released. + * + * @mtd: MTD device structure + * @chip: chipnumber to select, -1 for deselect + */ +static void au1550_select_chip(struct mtd_info *mtd, int chip) +{ +} + +/** + * au1550_command - Send command to NAND device + * @mtd: MTD device structure + * @command: the command to be sent + * @column: the column address for this command, -1 if none + * @page_addr: the page address for this command, -1 if none + */ +static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) +{ + register struct nand_chip *this = mtd->priv; + int ce_override = 0, i; + ulong flags; + + /* Begin command latch cycle */ + au1550_hwcontrol(mtd, NAND_CTL_SETCLE); + /* + * Write out the command to the device. + */ + if (command == NAND_CMD_SEQIN) { + int readcmd; + + if (column >= mtd->writesize) { + /* OOB area */ + column -= mtd->writesize; + readcmd = NAND_CMD_READOOB; + } else if (column < 256) { + /* First 256 bytes --> READ0 */ + readcmd = NAND_CMD_READ0; + } else { + column -= 256; + readcmd = NAND_CMD_READ1; + } + au1550_write_byte(mtd, readcmd); + } + au1550_write_byte(mtd, command); + + /* Set ALE and clear CLE to start address cycle */ + au1550_hwcontrol(mtd, NAND_CTL_CLRCLE); + + if (column != -1 || page_addr != -1) { + au1550_hwcontrol(mtd, NAND_CTL_SETALE); + + /* Serially input address */ + if (column != -1) { + /* Adjust columns for 16 bit buswidth */ + if (this->options & NAND_BUSWIDTH_16) + column >>= 1; + au1550_write_byte(mtd, column); + } + if (page_addr != -1) { + au1550_write_byte(mtd, (u8)(page_addr & 0xff)); + + if (command == NAND_CMD_READ0 || + command == NAND_CMD_READ1 || + command == NAND_CMD_READOOB) { + /* + * NAND controller will release -CE after + * the last address byte is written, so we'll + * have to forcibly assert it. No interrupts + * are allowed while we do this as we don't + * want the NOR flash or PCMCIA drivers to + * steal our precious bytes of data... + */ + ce_override = 1; + local_irq_save(flags); + au1550_hwcontrol(mtd, NAND_CTL_SETNCE); + } + + au1550_write_byte(mtd, (u8)(page_addr >> 8)); + + /* One more address cycle for devices > 32MiB */ + if (this->chipsize > (32 << 20)) + au1550_write_byte(mtd, (u8)((page_addr >> 16) & 0x0f)); + } + /* Latch in address */ + au1550_hwcontrol(mtd, NAND_CTL_CLRALE); + } + + /* + * Program and erase have their own busy handlers. + * Status and sequential in need no delay. + */ + switch (command) { + + case NAND_CMD_PAGEPROG: + case NAND_CMD_ERASE1: + case NAND_CMD_ERASE2: + case NAND_CMD_SEQIN: + case NAND_CMD_STATUS: + return; + + case NAND_CMD_RESET: + break; + + case NAND_CMD_READ0: + case NAND_CMD_READ1: + case NAND_CMD_READOOB: + /* Check if we're really driving -CE low (just in case) */ + if (unlikely(!ce_override)) + break; + + /* Apply a short delay always to ensure that we do wait tWB. */ + ndelay(100); + /* Wait for a chip to become ready... */ + for (i = this->chip_delay; !this->dev_ready(mtd) && i > 0; --i) + udelay(1); + + /* Release -CE and re-enable interrupts. */ + au1550_hwcontrol(mtd, NAND_CTL_CLRNCE); + local_irq_restore(flags); + return; + } + /* Apply this short delay always to ensure that we do wait tWB. */ + ndelay(100); + + while(!this->dev_ready(mtd)); +} + + /* * Main initialization routine */ -int __init au1xxx_nand_init (void) +static int __init au1xxx_nand_init(void) { struct nand_chip *this; - u16 boot_swapboot = 0; /* default value */ + u16 boot_swapboot = 0; /* default value */ int retval; u32 mem_staddr; u32 nand_phys; /* Allocate memory for MTD device structure and private data */ - au1550_mtd = kmalloc (sizeof(struct mtd_info) + - sizeof (struct nand_chip), GFP_KERNEL); + au1550_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!au1550_mtd) { - printk ("Unable to allocate NAND MTD dev structure.\n"); + printk("Unable to allocate NAND MTD dev structure.\n"); return -ENOMEM; } /* Get pointer to private data */ - this = (struct nand_chip *) (&au1550_mtd[1]); + this = (struct nand_chip *)(&au1550_mtd[1]); /* Initialize structures */ - memset((char *) au1550_mtd, 0, sizeof(struct mtd_info)); - memset((char *) this, 0, sizeof(struct nand_chip)); + memset(au1550_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ au1550_mtd->priv = this; + au1550_mtd->owner = THIS_MODULE; - /* disable interrupts */ - au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL); - - /* disable NAND boot */ - au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL); + /* MEM_STNDCTL: disable ints, disable nand boot */ + au_writel(0, MEM_STNDCTL); #ifdef CONFIG_MIPS_PB1550 /* set gpio206 high */ - au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR); + au_writel(au_readl(GPIO2_DIR) & ~(1 << 6), GPIO2_DIR); - boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) | - ((bcsr->status >> 6) & 0x1); + boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | ((bcsr->status >> 6) & 0x1); switch (boot_swapboot) { - case 0: - case 2: - case 8: - case 0xC: - case 0xD: - /* x16 NAND Flash */ - nand_width = 0; - break; - case 1: - case 9: - case 3: - case 0xE: - case 0xF: - /* x8 NAND Flash */ - nand_width = 1; - break; - default: - printk("Pb1550 NAND: bad boot:swap\n"); - retval = -EINVAL; - goto outmem; + case 0: + case 2: + case 8: + case 0xC: + case 0xD: + /* x16 NAND Flash */ + nand_width = 0; + break; + case 1: + case 9: + case 3: + case 0xE: + case 0xF: + /* x8 NAND Flash */ + nand_width = 1; + break; + default: + printk("Pb1550 NAND: bad boot:swap\n"); + retval = -EINVAL; + goto outmem; } #endif @@ -424,21 +560,22 @@ #endif /* make controller and MTD agree */ if (NAND_CS == 0) - nand_width = au_readl(MEM_STCFG0) & (1<<22); + nand_width = au_readl(MEM_STCFG0) & (1 << 22); if (NAND_CS == 1) - nand_width = au_readl(MEM_STCFG1) & (1<<22); + nand_width = au_readl(MEM_STCFG1) & (1 << 22); if (NAND_CS == 2) - nand_width = au_readl(MEM_STCFG2) & (1<<22); + nand_width = au_readl(MEM_STCFG2) & (1 << 22); if (NAND_CS == 3) - nand_width = au_readl(MEM_STCFG3) & (1<<22); - + nand_width = au_readl(MEM_STCFG3) & (1 << 22); /* Set address of hardware control function */ - this->hwcontrol = au1550_hwcontrol; this->dev_ready = au1550_device_ready; + this->select_chip = au1550_select_chip; + this->cmdfunc = au1550_command; + /* 30 us command delay time */ this->chip_delay = 30; - this->eccmode = NAND_ECC_SOFT; + this->ecc.mode = NAND_ECC_SOFT; this->options = NAND_NO_AUTOINCR; @@ -446,15 +583,14 @@ #endif this->options |= NAND_BUSWIDTH_16; this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte; - this->write_byte = (!nand_width) ? au_write_byte16 : au_write_byte; - this->write_word = au_write_word; + au1550_write_byte = (!nand_width) ? au_write_byte16 : au_write_byte; this->read_word = au_read_word; this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf; this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf; this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf; /* Scan to find existence of the device */ - if (nand_scan (au1550_mtd, 1)) { + if (nand_scan(au1550_mtd, 1)) { retval = -ENXIO; goto outio; } @@ -465,10 +601,10 @@ #endif return 0; outio: - iounmap ((void *)p_nand); + iounmap((void *)p_nand); outmem: - kfree (au1550_mtd); + kfree(au1550_mtd); return retval; } @@ -477,22 +613,21 @@ module_init(au1xxx_nand_init); /* * Clean up routine */ -#ifdef MODULE -static void __exit au1550_cleanup (void) +static void __exit au1550_cleanup(void) { - struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1]; + struct nand_chip *this = (struct nand_chip *)&au1550_mtd[1]; /* Release resources, unregister device */ - nand_release (au1550_mtd); + nand_release(au1550_mtd); /* Free the MTD device structure */ - kfree (au1550_mtd); + kfree(au1550_mtd); /* Unmap */ - iounmap ((void *)p_nand); + iounmap((void *)p_nand); } + module_exit(au1550_cleanup); -#endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Embedded Edge, LLC"); diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index a3c7fea..fe94ae9 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c @@ -4,7 +4,7 @@ * Copyright (c) 2002 Thomas Gleixner * * Derived from drivers/mtd/spia.c - * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) + * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) * * $Id: autcpu12.c,v 1.23 2005/11/07 11:14:30 gleixner Exp $ * @@ -42,12 +42,7 @@ #include * MTD structure for AUTCPU12 board */ static struct mtd_info *autcpu12_mtd = NULL; - -static int autcpu12_io_base = CS89712_VIRT_BASE; -static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC; -static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET; -static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET; -static void __iomem * autcpu12_fio_base; +static void __iomem *autcpu12_fio_base; /* * Define partitions for flash devices @@ -94,108 +89,131 @@ #define NUM_PARTITIONS64K 2 #define NUM_PARTITIONS128K 2 /* * hardware specific access to control-lines -*/ -static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd) + * + * ALE bit 4 autcpu12_pedr + * CLE bit 5 autcpu12_pedr + * NCE bit 0 fio_ctrl + * + */ +static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) { + struct nand_chip *chip = mtd->priv; - switch(cmd){ - - case NAND_CTL_SETCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |= AUTCPU12_SMC_CLE; break; - case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_CLE; break; + if (ctrl & NAND_CTRL_CHANGE) { + void __iomem *addr + unsigned char bits; - case NAND_CTL_SETALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |= AUTCPU12_SMC_ALE; break; - case NAND_CTL_CLRALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_ALE; break; + addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET; + bits = (ctrl & NAND_CLE) << 4; + bits |= (ctrl & NAND_ALE) << 2; + writeb((readb(addr) & ~0x30) | bits, addr); - case NAND_CTL_SETNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x01; break; - case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x00; break; + addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET; + writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr); } + + if (cmd != NAND_CMD_NONE) + writeb(cmd, chip->IO_ADDR_W); } /* -* read device ready pin -*/ + * read device ready pin + */ int autcpu12_device_ready(struct mtd_info *mtd) { + void __iomem *addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET; - return ( (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0; - + return readb(addr) & AUTCPU12_SMC_RDY; } /* * Main initialization routine */ -int __init autcpu12_init (void) +static int __init autcpu12_init(void) { struct nand_chip *this; int err = 0; /* Allocate memory for MTD device structure and private data */ - autcpu12_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), - GFP_KERNEL); + autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), + GFP_KERNEL); if (!autcpu12_mtd) { - printk ("Unable to allocate AUTCPU12 NAND MTD device structure.\n"); + printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n"); err = -ENOMEM; goto out; } /* map physical adress */ - autcpu12_fio_base = ioremap(autcpu12_fio_pbase,SZ_1K); - if(!autcpu12_fio_base){ + autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K); + if (!autcpu12_fio_base) { printk("Ioremap autcpu12 SmartMedia Card failed\n"); err = -EIO; goto out_mtd; } /* Get pointer to private data */ - this = (struct nand_chip *) (&autcpu12_mtd[1]); + this = (struct nand_chip *)(&autcpu12_mtd[1]); /* Initialize structures */ - memset((char *) autcpu12_mtd, 0, sizeof(struct mtd_info)); - memset((char *) this, 0, sizeof(struct nand_chip)); + memset(autcpu12_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ autcpu12_mtd->priv = this; + autcpu12_mtd->owner = THIS_MODULE; /* Set address of NAND IO lines */ this->IO_ADDR_R = autcpu12_fio_base; this->IO_ADDR_W = autcpu12_fio_base; - this->hwcontrol = autcpu12_hwcontrol; + this->cmd_ctrl = autcpu12_hwcontrol; this->dev_ready = autcpu12_device_ready; /* 20 us command delay time */ this->chip_delay = 20; - this->eccmode = NAND_ECC_SOFT; + this->ecc.mode = NAND_ECC_SOFT; /* Enable the following for a flash based bad block table */ /* - this->options = NAND_USE_FLASH_BBT; - */ + this->options = NAND_USE_FLASH_BBT; + */ this->options = NAND_USE_FLASH_BBT; /* Scan to find existance of the device */ - if (nand_scan (autcpu12_mtd, 1)) { + if (nand_scan(autcpu12_mtd, 1)) { err = -ENXIO; goto out_ior; } /* Register the partitions */ - switch(autcpu12_mtd->size){ - case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break; - case SZ_32M: add_mtd_partitions(autcpu12_mtd, partition_info32k, NUM_PARTITIONS32K); break; - case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break; - case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break; - default: { - printk ("Unsupported SmartMedia device\n"); + switch (autcpu12_mtd->size) { + case SZ_16M: + add_mtd_partitions(autcpu12_mtd, partition_info16k, + NUM_PARTITIONS16K); + break; + case SZ_32M: + add_mtd_partitions(autcpu12_mtd, partition_info32k, + NUM_PARTITIONS32K); + break; + case SZ_64M: + add_mtd_partitions(autcpu12_mtd, partition_info64k, + NUM_PARTITIONS64K); + break; + case SZ_128M: + add_mtd_partitions(autcpu12_mtd, partition_info128k, + NUM_PARTITIONS128K); + break; + default: + printk("Unsupported SmartMedia device\n"); err = -ENXIO; goto out_ior; - } } goto out; -out_ior: - iounmap((void *)autcpu12_fio_base); -out_mtd: - kfree (autcpu12_mtd); -out: + out_ior: + iounmap(autcpu12_fio_base); + out_mtd: + kfree(autcpu12_mtd); + out: return err; } @@ -204,20 +222,19 @@ module_init(autcpu12_init); /* * Clean up routine */ -#ifdef MODULE -static void __exit autcpu12_cleanup (void) +static void __exit autcpu12_cleanup(void) { /* Release resources, unregister device */ - nand_release (autcpu12_mtd); + nand_release(autcpu12_mtd); /* unmap physical adress */ - iounmap((void *)autcpu12_fio_base); + iounmap(autcpu12_fio_base); /* Free the MTD device structure */ - kfree (autcpu12_mtd); + kfree(autcpu12_mtd); } + module_exit(autcpu12_cleanup); -#endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Thomas Gleixner "); diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c new file mode 100644 index 0000000..e0a1d38 --- /dev/null +++ b/drivers/mtd/nand/cs553x_nand.c @@ -0,0 +1,353 @@ +/* + * drivers/mtd/nand/cs553x_nand.c + * + * (C) 2005, 2006 Red Hat Inc. + * + * Author: David Woodhouse + * Tom Sylla + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the NAND flash controller found on + * the AMD CS5535/CS5536 companion chipsets for the Geode processor. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define NR_CS553X_CONTROLLERS 4 + +#define MSR_DIVIL_GLD_CAP 0x51400000 /* DIVIL capabilitiies */ +#define CAP_CS5535 0x2df000ULL +#define CAP_CS5536 0x5df500ULL + +/* NAND Timing MSRs */ +#define MSR_NANDF_DATA 0x5140001b /* NAND Flash Data Timing MSR */ +#define MSR_NANDF_CTL 0x5140001c /* NAND Flash Control Timing */ +#define MSR_NANDF_RSVD 0x5140001d /* Reserved */ + +/* NAND BAR MSRs */ +#define MSR_DIVIL_LBAR_FLSH0 0x51400010 /* Flash Chip Select 0 */ +#define MSR_DIVIL_LBAR_FLSH1 0x51400011 /* Flash Chip Select 1 */ +#define MSR_DIVIL_LBAR_FLSH2 0x51400012 /* Flash Chip Select 2 */ +#define MSR_DIVIL_LBAR_FLSH3 0x51400013 /* Flash Chip Select 3 */ + /* Each made up of... */ +#define FLSH_LBAR_EN (1ULL<<32) +#define FLSH_NOR_NAND (1ULL<<33) /* 1 for NAND */ +#define FLSH_MEM_IO (1ULL<<34) /* 1 for MMIO */ + /* I/O BARs have BASE_ADDR in bits 15:4, IO_MASK in 47:36 */ + /* MMIO BARs have BASE_ADDR in bits 31:12, MEM_MASK in 63:44 */ + +/* Pin function selection MSR (IDE vs. flash on the IDE pins) */ +#define MSR_DIVIL_BALL_OPTS 0x51400015 +#define PIN_OPT_IDE (1<<0) /* 0 for flash, 1 for IDE */ + +/* Registers within the NAND flash controller BAR -- memory mapped */ +#define MM_NAND_DATA 0x00 /* 0 to 0x7ff, in fact */ +#define MM_NAND_CTL 0x800 /* Any even address 0x800-0x80e */ +#define MM_NAND_IO 0x801 /* Any odd address 0x801-0x80f */ +#define MM_NAND_STS 0x810 +#define MM_NAND_ECC_LSB 0x811 +#define MM_NAND_ECC_MSB 0x812 +#define MM_NAND_ECC_COL 0x813 +#define MM_NAND_LAC 0x814 +#define MM_NAND_ECC_CTL 0x815 + +/* Registers within the NAND flash controller BAR -- I/O mapped */ +#define IO_NAND_DATA 0x00 /* 0 to 3, in fact */ +#define IO_NAND_CTL 0x04 +#define IO_NAND_IO 0x05 +#define IO_NAND_STS 0x06 +#define IO_NAND_ECC_CTL 0x08 +#define IO_NAND_ECC_LSB 0x09 +#define IO_NAND_ECC_MSB 0x0a +#define IO_NAND_ECC_COL 0x0b +#define IO_NAND_LAC 0x0c + +#define CS_NAND_CTL_DIST_EN (1<<4) /* Enable NAND Distract interrupt */ +#define CS_NAND_CTL_RDY_INT_MASK (1<<3) /* Enable RDY/BUSY# interrupt */ +#define CS_NAND_CTL_ALE (1<<2) +#define CS_NAND_CTL_CLE (1<<1) +#define CS_NAND_CTL_CE (1<<0) /* Keep low; 1 to reset */ + +#define CS_NAND_STS_FLASH_RDY (1<<3) +#define CS_NAND_CTLR_BUSY (1<<2) +#define CS_NAND_CMD_COMP (1<<1) +#define CS_NAND_DIST_ST (1<<0) + +#define CS_NAND_ECC_PARITY (1<<2) +#define CS_NAND_ECC_CLRECC (1<<1) +#define CS_NAND_ECC_ENECC (1<<0) + +static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + + while (unlikely(len > 0x800)) { + memcpy_fromio(buf, this->IO_ADDR_R, 0x800); + buf += 0x800; + len -= 0x800; + } + memcpy_fromio(buf, this->IO_ADDR_R, len); +} + +static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + + while (unlikely(len > 0x800)) { + memcpy_toio(this->IO_ADDR_R, buf, 0x800); + buf += 0x800; + len -= 0x800; + } + memcpy_toio(this->IO_ADDR_R, buf, len); +} + +static unsigned char cs553x_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + return readb(this->IO_ADDR_R); +} + +static void cs553x_write_byte(struct mtd_info *mtd, u_char byte) +{ + struct nand_chip *this = mtd->priv; + int i = 100000; + + while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) { + udelay(1); + i--; + } + writeb(byte, this->IO_ADDR_W + 0x801); +} + +static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + void __iomem *mmio_base = this->IO_ADDR_R; + if (ctrl & NAND_CTRL_CHANGE) { + unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01; + writeb(ctl, mmio_base + MM_NAND_CTL); + } + if (cmd != NAND_CMD_NONE) + cs553x_write_byte(mtd, cmd); +} + +static int cs553x_device_ready(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + void __iomem *mmio_base = this->IO_ADDR_R; + unsigned char foo = readb(mmio_base + MM_NAND_STS); + + return (foo & CS_NAND_STS_FLASH_RDY) && !(foo & CS_NAND_CTLR_BUSY); +} + +static void cs_enable_hwecc(struct mtd_info *mtd, int mode) +{ + struct nand_chip *this = mtd->priv; + void __iomem *mmio_base = this->IO_ADDR_R; + + writeb(0x07, mmio_base + MM_NAND_ECC_CTL); +} + +static int cs_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) +{ + uint32_t ecc; + struct nand_chip *this = mtd->priv; + void __iomem *mmio_base = this->IO_ADDR_R; + + ecc = readl(mmio_base + MM_NAND_STS); + + ecc_code[1] = ecc >> 8; + ecc_code[0] = ecc >> 16; + ecc_code[2] = ecc >> 24; + return 0; +} + +static struct mtd_info *cs553x_mtd[4]; + +static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) +{ + int err = 0; + struct nand_chip *this; + struct mtd_info *new_mtd; + + printk(KERN_NOTICE "Probing CS553x NAND controller CS#%d at %sIO 0x%08lx\n", cs, mmio?"MM":"P", adr); + + if (!mmio) { + printk(KERN_NOTICE "PIO mode not yet implemented for CS553X NAND controller\n"); + return -ENXIO; + } + + /* Allocate memory for MTD device structure and private data */ + new_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); + if (!new_mtd) { + printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n"); + err = -ENOMEM; + goto out; + } + + /* Get pointer to private data */ + this = (struct nand_chip *)(&new_mtd[1]); + + /* Initialize structures */ + memset(new_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); + + /* Link the private data with the MTD structure */ + new_mtd->priv = this; + new_mtd->owner = THIS_MODULE; + + /* map physical address */ + this->IO_ADDR_R = this->IO_ADDR_W = ioremap(adr, 4096); + if (!this->IO_ADDR_R) { + printk(KERN_WARNING "ioremap cs553x NAND @0x%08lx failed\n", adr); + err = -EIO; + goto out_mtd; + } + + this->cmd_ctrl = cs553x_hwcontrol; + this->dev_ready = cs553x_device_ready; + this->read_byte = cs553x_read_byte; + this->read_buf = cs553x_read_buf; + this->write_buf = cs553x_write_buf; + + this->chip_delay = 0; + + this->ecc.mode = NAND_ECC_HW; + this->ecc.size = 256; + this->ecc.bytes = 3; + this->ecc.hwctl = cs_enable_hwecc; + this->ecc.calculate = cs_calculate_ecc; + this->ecc.correct = nand_correct_data; + + /* Enable the following for a flash based bad block table */ + this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR; + + /* Scan to find existance of the device */ + if (nand_scan(new_mtd, 1)) { + err = -ENXIO; + goto out_ior; + } + + cs553x_mtd[cs] = new_mtd; + goto out; + +out_ior: + iounmap((void *)this->IO_ADDR_R); +out_mtd: + kfree(new_mtd); +out: + return err; +} + +static int is_geode(void) +{ + /* These are the CPUs which will have a CS553[56] companion chip */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && + boot_cpu_data.x86 == 5 && + boot_cpu_data.x86_model == 10) + return 1; /* Geode LX */ + + if ((boot_cpu_data.x86_vendor == X86_VENDOR_NSC || + boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX) && + boot_cpu_data.x86 == 5 && + boot_cpu_data.x86_model == 5) + return 1; /* Geode GX (née GX2) */ + + return 0; +} + +static int __init cs553x_init(void) +{ + int err = -ENXIO; + int i; + uint64_t val; + + /* If the CPU isn't a Geode GX or LX, abort */ + if (!is_geode()) + return -ENXIO; + + /* If it doesn't have the CS553[56], abort */ + rdmsrl(MSR_DIVIL_GLD_CAP, val); + val &= ~0xFFULL; + if (val != CAP_CS5535 && val != CAP_CS5536) + return -ENXIO; + + /* If it doesn't have the NAND controller enabled, abort */ + rdmsrl(MSR_DIVIL_BALL_OPTS, val); + if (val & 1) { + printk(KERN_INFO "CS553x NAND controller: Flash I/O not enabled in MSR_DIVIL_BALL_OPTS.\n"); + return -ENXIO; + } + + for (i = 0; i < NR_CS553X_CONTROLLERS; i++) { + rdmsrl(MSR_DIVIL_LBAR_FLSH0 + i, val); + + if ((val & (FLSH_LBAR_EN|FLSH_NOR_NAND)) == (FLSH_LBAR_EN|FLSH_NOR_NAND)) + err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF); + } + + /* Register all devices together here. This means we can easily hack it to + do mtdconcat etc. if we want to. */ + for (i = 0; i < NR_CS553X_CONTROLLERS; i++) { + if (cs553x_mtd[i]) { + add_mtd_device(cs553x_mtd[i]); + + /* If any devices registered, return success. Else the last error. */ + err = 0; + } + } + + return err; +} + +module_init(cs553x_init); + +static void __exit cs553x_cleanup(void) +{ + int i; + + for (i = 0; i < NR_CS553X_CONTROLLERS; i++) { + struct mtd_info *mtd = cs553x_mtd[i]; + struct nand_chip *this; + void __iomem *mmio_base; + + if (!mtd) + break; + + this = cs553x_mtd[i]->priv; + mmio_base = this->IO_ADDR_R; + + /* Release resources, unregister device */ + nand_release(cs553x_mtd[i]); + cs553x_mtd[i] = NULL; + + /* unmap physical adress */ + iounmap(mmio_base); + + /* Free the MTD device structure */ + kfree(mtd); + } +} + +module_exit(cs553x_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Woodhouse "); +MODULE_DESCRIPTION("NAND controller driver for AMD CS5535/CS5536 companion chip"); diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index ec5e45e..6107f53 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -58,10 +58,10 @@ #elif defined(__PPC__) 0xe4000000, #elif defined(CONFIG_MOMENCO_OCELOT) 0x2f000000, - 0xff000000, + 0xff000000, #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C) - 0xff000000, -##else + 0xff000000, +#else #warning Unknown architecture for DiskOnChip. No default probe locations defined #endif 0xffffffff }; @@ -73,7 +73,7 @@ struct doc_priv { unsigned long physadr; u_char ChipID; u_char CDSNControl; - int chips_per_floor; /* The number of chips detected on each floor */ + int chips_per_floor; /* The number of chips detected on each floor */ int curfloor; int curchip; int mh0_page; @@ -84,6 +84,7 @@ struct doc_priv { /* This is the syndrome computed by the HW ecc generator upon reading an empty page, one with all 0xff for data and stored ecc code. */ static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a }; + /* This is the ecc value computed by the HW ecc generator upon writing an empty page, one with all 0xff for data. */ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 }; @@ -94,28 +95,29 @@ #define DoC_is_MillenniumPlus(doc) ((doc #define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil) #define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k) -static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd); +static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int bitmask); static void doc200x_select_chip(struct mtd_info *mtd, int chip); -static int debug=0; +static int debug = 0; module_param(debug, int, 0); -static int try_dword=1; +static int try_dword = 1; module_param(try_dword, int, 0); -static int no_ecc_failures=0; +static int no_ecc_failures = 0; module_param(no_ecc_failures, int, 0); -static int no_autopart=0; +static int no_autopart = 0; module_param(no_autopart, int, 0); -static int show_firmware_partition=0; +static int show_firmware_partition = 0; module_param(show_firmware_partition, int, 0); #ifdef MTD_NAND_DISKONCHIP_BBTWRITE -static int inftl_bbt_write=1; +static int inftl_bbt_write = 1; #else -static int inftl_bbt_write=0; +static int inftl_bbt_write = 0; #endif module_param(inftl_bbt_write, int, 0); @@ -123,7 +125,6 @@ static unsigned long doc_config_location module_param(doc_config_location, ulong, 0); MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip"); - /* Sector size for HW ECC */ #define SECTOR_SIZE 512 /* The sector bytes are packed into NB_DATA 10 bit words */ @@ -147,7 +148,7 @@ static struct rs_control *rs_decoder; * some comments, improved a minor bit and converted it to make use * of the generic Reed-Solomon libary. tglx */ -static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) +static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) { int i, j, nerr, errpos[8]; uint8_t parity; @@ -168,18 +169,18 @@ static int doc_ecc_decode (struct rs_con * s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0] * where x = alpha^(FCR + i) */ - for(j = 1; j < NROOTS; j++) { - if(ds[j] == 0) + for (j = 1; j < NROOTS; j++) { + if (ds[j] == 0) continue; tmp = rs->index_of[ds[j]]; - for(i = 0; i < NROOTS; i++) + for (i = 0; i < NROOTS; i++) s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; } /* Calc s[i] = s[i] / alpha^(v + i) */ for (i = 0; i < NROOTS; i++) { if (syn[i]) - syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); + syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); } /* Call the decoder library */ nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval); @@ -193,7 +194,7 @@ static int doc_ecc_decode (struct rs_con * but they are given by the design of the de/encoder circuit * in the DoC ASIC's. */ - for(i = 0;i < nerr; i++) { + for (i = 0; i < nerr; i++) { int index, bitpos, pos = 1015 - errpos[i]; uint8_t val; if (pos >= NB_DATA && pos < 1019) @@ -205,8 +206,7 @@ static int doc_ecc_decode (struct rs_con can be modified since pos is even */ index = (pos >> 3) ^ 1; bitpos = pos & 7; - if ((index >= 0 && index < SECTOR_SIZE) || - index == (SECTOR_SIZE + 1)) { + if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) { val = (uint8_t) (errval[i] >> (2 + bitpos)); parity ^= val; if (index < SECTOR_SIZE) @@ -216,9 +216,8 @@ static int doc_ecc_decode (struct rs_con bitpos = (bitpos + 10) & 7; if (bitpos == 0) bitpos = 8; - if ((index >= 0 && index < SECTOR_SIZE) || - index == (SECTOR_SIZE + 1)) { - val = (uint8_t)(errval[i] << (8 - bitpos)); + if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) { + val = (uint8_t) (errval[i] << (8 - bitpos)); parity ^= val; if (index < SECTOR_SIZE) data[index] ^= val; @@ -250,10 +249,11 @@ #define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_F /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ static int _DoC_WaitReady(struct doc_priv *doc) { - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; unsigned long timeo = jiffies + (HZ * 10); - if(debug) printk("_DoC_WaitReady...\n"); + if (debug) + printk("_DoC_WaitReady...\n"); /* Out-of-line routine to wait for chip response */ if (DoC_is_MillenniumPlus(doc)) { while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { @@ -280,7 +280,7 @@ static int _DoC_WaitReady(struct doc_pri static inline int DoC_WaitReady(struct doc_priv *doc) { - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int ret = 0; if (DoC_is_MillenniumPlus(doc)) { @@ -298,7 +298,8 @@ static inline int DoC_WaitReady(struct d DoC_Delay(doc, 2); } - if(debug) printk("DoC_WaitReady OK\n"); + if (debug) + printk("DoC_WaitReady OK\n"); return ret; } @@ -306,9 +307,10 @@ static void doc2000_write_byte(struct mt { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; - if(debug)printk("write_byte %02x\n", datum); + if (debug) + printk("write_byte %02x\n", datum); WriteDOC(datum, docptr, CDSNSlowIO); WriteDOC(datum, docptr, 2k_CDSN_IO); } @@ -317,77 +319,78 @@ static u_char doc2000_read_byte(struct m { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; u_char ret; ReadDOC(docptr, CDSNSlowIO); DoC_Delay(doc, 2); ret = ReadDOC(docptr, 2k_CDSN_IO); - if (debug) printk("read_byte returns %02x\n", ret); + if (debug) + printk("read_byte returns %02x\n", ret); return ret; } -static void doc2000_writebuf(struct mtd_info *mtd, - const u_char *buf, int len) +static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; - if (debug)printk("writebuf of %d bytes: ", len); - for (i=0; i < len; i++) { + if (debug) + printk("writebuf of %d bytes: ", len); + for (i = 0; i < len; i++) { WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i); if (debug && i < 16) printk("%02x ", buf[i]); } - if (debug) printk("\n"); + if (debug) + printk("\n"); } -static void doc2000_readbuf(struct mtd_info *mtd, - u_char *buf, int len) +static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; - int i; + void __iomem *docptr = doc->virtadr; + int i; - if (debug)printk("readbuf of %d bytes: ", len); + if (debug) + printk("readbuf of %d bytes: ", len); - for (i=0; i < len; i++) { + for (i = 0; i < len; i++) { buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i); } } -static void doc2000_readbuf_dword(struct mtd_info *mtd, - u_char *buf, int len) +static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; - int i; + void __iomem *docptr = doc->virtadr; + int i; - if (debug) printk("readbuf_dword of %d bytes: ", len); + if (debug) + printk("readbuf_dword of %d bytes: ", len); - if (unlikely((((unsigned long)buf)|len) & 3)) { - for (i=0; i < len; i++) { - *(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i); + if (unlikely((((unsigned long)buf) | len) & 3)) { + for (i = 0; i < len; i++) { + *(uint8_t *) (&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i); } } else { - for (i=0; i < len; i+=4) { - *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i); + for (i = 0; i < len; i += 4) { + *(uint32_t *) (&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i); } } } -static int doc2000_verifybuf(struct mtd_info *mtd, - const u_char *buf, int len) +static int doc2000_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; - for (i=0; i < len; i++) + for (i = 0; i < len; i++) if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO)) return -EFAULT; return 0; @@ -400,12 +403,10 @@ static uint16_t __init doc200x_ident_chi uint16_t ret; doc200x_select_chip(mtd, nr); - doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); - this->write_byte(mtd, NAND_CMD_READID); - doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); - doc200x_hwcontrol(mtd, NAND_CTL_SETALE); - this->write_byte(mtd, 0); - doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); + doc200x_hwcontrol(mtd, NAND_CMD_READID, + NAND_CTRL_CLE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* We cant' use dev_ready here, but at least we wait for the * command to complete @@ -423,12 +424,11 @@ static uint16_t __init doc200x_ident_chi } ident; void __iomem *docptr = doc->virtadr; - doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); - doc2000_write_byte(mtd, NAND_CMD_READID); - doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); - doc200x_hwcontrol(mtd, NAND_CTL_SETALE); - doc2000_write_byte(mtd, 0); - doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); + doc200x_hwcontrol(mtd, NAND_CMD_READID, + NAND_CTRL_CLE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(mtd, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); udelay(50); @@ -464,7 +464,7 @@ static void __init doc2000_count_chips(s printk(KERN_DEBUG "Detected %d chips per floor.\n", i); } -static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state) +static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this) { struct doc_priv *doc = this->priv; @@ -482,7 +482,7 @@ static void doc2001_write_byte(struct mt { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; WriteDOC(datum, docptr, CDSNSlowIO); WriteDOC(datum, docptr, Mil_CDSN_IO); @@ -493,7 +493,7 @@ static u_char doc2001_read_byte(struct m { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; //ReadDOC(docptr, CDSNSlowIO); /* 11.4.5 -- delay twice to allow extended length cycle */ @@ -503,50 +503,47 @@ static u_char doc2001_read_byte(struct m return ReadDOC(docptr, LastDataRead); } -static void doc2001_writebuf(struct mtd_info *mtd, - const u_char *buf, int len) +static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; - for (i=0; i < len; i++) + for (i = 0; i < len; i++) WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); /* Terminate write pipeline */ WriteDOC(0x00, docptr, WritePipeTerm); } -static void doc2001_readbuf(struct mtd_info *mtd, - u_char *buf, int len) +static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; /* Start read pipeline */ ReadDOC(docptr, ReadPipeInit); - for (i=0; i < len-1; i++) + for (i = 0; i < len - 1; i++) buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff)); /* Terminate read pipeline */ buf[i] = ReadDOC(docptr, LastDataRead); } -static int doc2001_verifybuf(struct mtd_info *mtd, - const u_char *buf, int len) +static int doc2001_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; /* Start read pipeline */ ReadDOC(docptr, ReadPipeInit); - for (i=0; i < len-1; i++) + for (i = 0; i < len - 1; i++) if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { ReadDOC(docptr, LastDataRead); return i; @@ -560,87 +557,90 @@ static u_char doc2001plus_read_byte(stru { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; u_char ret; - ReadDOC(docptr, Mplus_ReadPipeInit); - ReadDOC(docptr, Mplus_ReadPipeInit); - ret = ReadDOC(docptr, Mplus_LastDataRead); - if (debug) printk("read_byte returns %02x\n", ret); + ReadDOC(docptr, Mplus_ReadPipeInit); + ReadDOC(docptr, Mplus_ReadPipeInit); + ret = ReadDOC(docptr, Mplus_LastDataRead); + if (debug) + printk("read_byte returns %02x\n", ret); return ret; } -static void doc2001plus_writebuf(struct mtd_info *mtd, - const u_char *buf, int len) +static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; - if (debug)printk("writebuf of %d bytes: ", len); - for (i=0; i < len; i++) { + if (debug) + printk("writebuf of %d bytes: ", len); + for (i = 0; i < len; i++) { WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); if (debug && i < 16) printk("%02x ", buf[i]); } - if (debug) printk("\n"); + if (debug) + printk("\n"); } -static void doc2001plus_readbuf(struct mtd_info *mtd, - u_char *buf, int len) +static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; - if (debug)printk("readbuf of %d bytes: ", len); + if (debug) + printk("readbuf of %d bytes: ", len); /* Start read pipeline */ ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit); - for (i=0; i < len-2; i++) { + for (i = 0; i < len - 2; i++) { buf[i] = ReadDOC(docptr, Mil_CDSN_IO); if (debug && i < 16) printk("%02x ", buf[i]); } /* Terminate read pipeline */ - buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead); + buf[len - 2] = ReadDOC(docptr, Mplus_LastDataRead); if (debug && i < 16) - printk("%02x ", buf[len-2]); - buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead); + printk("%02x ", buf[len - 2]); + buf[len - 1] = ReadDOC(docptr, Mplus_LastDataRead); if (debug && i < 16) - printk("%02x ", buf[len-1]); - if (debug) printk("\n"); + printk("%02x ", buf[len - 1]); + if (debug) + printk("\n"); } -static int doc2001plus_verifybuf(struct mtd_info *mtd, - const u_char *buf, int len) +static int doc2001plus_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; - if (debug)printk("verifybuf of %d bytes: ", len); + if (debug) + printk("verifybuf of %d bytes: ", len); /* Start read pipeline */ ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit); - for (i=0; i < len-2; i++) + for (i = 0; i < len - 2; i++) if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { ReadDOC(docptr, Mplus_LastDataRead); ReadDOC(docptr, Mplus_LastDataRead); return i; } - if (buf[len-2] != ReadDOC(docptr, Mplus_LastDataRead)) - return len-2; - if (buf[len-1] != ReadDOC(docptr, Mplus_LastDataRead)) - return len-1; + if (buf[len - 2] != ReadDOC(docptr, Mplus_LastDataRead)) + return len - 2; + if (buf[len - 1] != ReadDOC(docptr, Mplus_LastDataRead)) + return len - 1; return 0; } @@ -648,10 +648,11 @@ static void doc2001plus_select_chip(stru { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int floor = 0; - if(debug)printk("select chip (%d)\n", chip); + if (debug) + printk("select chip (%d)\n", chip); if (chip == -1) { /* Disable flash internally */ @@ -660,7 +661,7 @@ static void doc2001plus_select_chip(stru } floor = chip / doc->chips_per_floor; - chip -= (floor * doc->chips_per_floor); + chip -= (floor * doc->chips_per_floor); /* Assert ChipEnable and deassert WriteProtect */ WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect); @@ -674,72 +675,61 @@ static void doc200x_select_chip(struct m { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int floor = 0; - if(debug)printk("select chip (%d)\n", chip); + if (debug) + printk("select chip (%d)\n", chip); if (chip == -1) return; floor = chip / doc->chips_per_floor; - chip -= (floor * doc->chips_per_floor); + chip -= (floor * doc->chips_per_floor); /* 11.4.4 -- deassert CE before changing chip */ - doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE); + doc200x_hwcontrol(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); WriteDOC(floor, docptr, FloorSelect); WriteDOC(chip, docptr, CDSNDeviceSelect); - doc200x_hwcontrol(mtd, NAND_CTL_SETNCE); + doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); doc->curchip = chip; doc->curfloor = floor; } -static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd) +#define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE) + +static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; - switch(cmd) { - case NAND_CTL_SETNCE: - doc->CDSNControl |= CDSN_CTRL_CE; - break; - case NAND_CTL_CLRNCE: - doc->CDSNControl &= ~CDSN_CTRL_CE; - break; - case NAND_CTL_SETCLE: - doc->CDSNControl |= CDSN_CTRL_CLE; - break; - case NAND_CTL_CLRCLE: - doc->CDSNControl &= ~CDSN_CTRL_CLE; - break; - case NAND_CTL_SETALE: - doc->CDSNControl |= CDSN_CTRL_ALE; - break; - case NAND_CTL_CLRALE: - doc->CDSNControl &= ~CDSN_CTRL_ALE; - break; - case NAND_CTL_SETWP: - doc->CDSNControl |= CDSN_CTRL_WP; - break; - case NAND_CTL_CLRWP: - doc->CDSNControl &= ~CDSN_CTRL_WP; - break; + if (ctrl & NAND_CTRL_CHANGE) { + doc->CDSNControl &= ~CDSN_CTRL_MSK; + doc->CDSNControl |= ctrl & CDSN_CTRL_MSK; + if (debug) + printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); + WriteDOC(doc->CDSNControl, docptr, CDSNControl); + /* 11.4.3 -- 4 NOPs after CSDNControl write */ + DoC_Delay(doc, 4); + } + if (cmd != NAND_CMD_NONE) { + if (DoC_is_2000(doc)) + doc2000_write_byte(mtd, cmd); + else + doc2001_write_byte(mtd, cmd); } - if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); - WriteDOC(doc->CDSNControl, docptr, CDSNControl); - /* 11.4.3 -- 4 NOPs after CSDNControl write */ - DoC_Delay(doc, 4); } -static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) +static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; /* * Must terminate write pipeline before sending any commands @@ -756,9 +746,9 @@ static void doc2001plus_command (struct if (command == NAND_CMD_SEQIN) { int readcmd; - if (column >= mtd->oobblock) { + if (column >= mtd->writesize) { /* OOB area */ - column -= mtd->oobblock; + column -= mtd->writesize; readcmd = NAND_CMD_READOOB; } else if (column < 256) { /* First 256 bytes --> READ0 */ @@ -782,25 +772,26 @@ static void doc2001plus_command (struct WriteDOC(column, docptr, Mplus_FlashAddress); } if (page_addr != -1) { - WriteDOC((unsigned char) (page_addr & 0xff), docptr, Mplus_FlashAddress); - WriteDOC((unsigned char) ((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress); + WriteDOC((unsigned char)(page_addr & 0xff), docptr, Mplus_FlashAddress); + WriteDOC((unsigned char)((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress); /* One more address cycle for higher density devices */ if (this->chipsize & 0x0c000000) { - WriteDOC((unsigned char) ((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress); + WriteDOC((unsigned char)((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress); printk("high density\n"); } } WriteDOC(0, docptr, Mplus_WritePipeTerm); WriteDOC(0, docptr, Mplus_WritePipeTerm); /* deassert ALE */ - if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || command == NAND_CMD_READOOB || command == NAND_CMD_READID) + if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || + command == NAND_CMD_READOOB || command == NAND_CMD_READID) WriteDOC(0, docptr, Mplus_FlashControl); } /* * program and erase have their own busy handlers * status and sequential in needs no delay - */ + */ switch (command) { case NAND_CMD_PAGEPROG: @@ -817,55 +808,57 @@ static void doc2001plus_command (struct WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd); WriteDOC(0, docptr, Mplus_WritePipeTerm); WriteDOC(0, docptr, Mplus_WritePipeTerm); - while ( !(this->read_byte(mtd) & 0x40)); + while (!(this->read_byte(mtd) & 0x40)) ; return; - /* This applies to read commands */ + /* This applies to read commands */ default: /* * If we don't have access to the busy pin, we apply the given * command delay - */ + */ if (!this->dev_ready) { - udelay (this->chip_delay); + udelay(this->chip_delay); return; } } /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ - ndelay (100); + ndelay(100); /* wait until command is processed */ - while (!this->dev_ready(mtd)); + while (!this->dev_ready(mtd)) ; } static int doc200x_dev_ready(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; if (DoC_is_MillenniumPlus(doc)) { /* 11.4.2 -- must NOP four times before checking FR/B# */ DoC_Delay(doc, 4); if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { - if(debug) + if (debug) printk("not ready\n"); return 0; } - if (debug)printk("was ready\n"); + if (debug) + printk("was ready\n"); return 1; } else { /* 11.4.2 -- must NOP four times before checking FR/B# */ DoC_Delay(doc, 4); if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { - if(debug) + if (debug) printk("not ready\n"); return 0; } /* 11.4.2 -- Must NOP twice if it's ready */ DoC_Delay(doc, 2); - if (debug)printk("was ready\n"); + if (debug) + printk("was ready\n"); return 1; } } @@ -881,10 +874,10 @@ static void doc200x_enable_hwecc(struct { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; /* Prime the ECC engine */ - switch(mode) { + switch (mode) { case NAND_ECC_READ: WriteDOC(DOC_ECC_RESET, docptr, ECCConf); WriteDOC(DOC_ECC_EN, docptr, ECCConf); @@ -900,10 +893,10 @@ static void doc2001plus_enable_hwecc(str { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; /* Prime the ECC engine */ - switch(mode) { + switch (mode) { case NAND_ECC_READ: WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf); @@ -916,12 +909,11 @@ static void doc2001plus_enable_hwecc(str } /* This code is only called on write */ -static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, - unsigned char *ecc_code) +static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; int i; int emptymatch = 1; @@ -961,7 +953,8 @@ #if 0 often. It could be optimized away by examining the data in the writebuf routine, and remembering the result. */ for (i = 0; i < 512; i++) { - if (dat[i] == 0xff) continue; + if (dat[i] == 0xff) + continue; emptymatch = 0; break; } @@ -969,17 +962,20 @@ #if 0 /* If emptymatch still =1, we do have an all-0xff data buffer. Return all-0xff ecc value instead of the computed one, so it'll look just like a freshly-erased page. */ - if (emptymatch) memset(ecc_code, 0xff, 6); + if (emptymatch) + memset(ecc_code, 0xff, 6); #endif return 0; } -static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) +static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, + u_char *read_ecc, u_char *isnull) { int i, ret = 0; struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - void __iomem *docptr = doc->virtadr; + void __iomem *docptr = doc->virtadr; + uint8_t calc_ecc[6]; volatile u_char dummy; int emptymatch = 1; @@ -1012,18 +1008,20 @@ static int doc200x_correct_data(struct m all-0xff data and stored ecc block. Check the stored ecc. */ if (emptymatch) { for (i = 0; i < 6; i++) { - if (read_ecc[i] == 0xff) continue; + if (read_ecc[i] == 0xff) + continue; emptymatch = 0; break; } } /* If emptymatch still =1, check the data block. */ if (emptymatch) { - /* Note: this somewhat expensive test should not be triggered - often. It could be optimized away by examining the data in - the readbuf routine, and remembering the result. */ + /* Note: this somewhat expensive test should not be triggered + often. It could be optimized away by examining the data in + the readbuf routine, and remembering the result. */ for (i = 0; i < 512; i++) { - if (dat[i] == 0xff) continue; + if (dat[i] == 0xff) + continue; emptymatch = 0; break; } @@ -1032,7 +1030,8 @@ static int doc200x_correct_data(struct m erased block, in which case the ECC will not come out right. We'll suppress the error and tell the caller everything's OK. Because it is. */ - if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc); + if (!emptymatch) + ret = doc_ecc_decode(rs_decoder, dat, calc_ecc); if (ret > 0) printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); } @@ -1059,11 +1058,10 @@ static int doc200x_correct_data(struct m * safer. The only problem with it is that any code that parses oobfree must * be able to handle out-of-order segments. */ -static struct nand_oobinfo doc200x_oobinfo = { - .useecc = MTD_NANDECC_AUTOPLACE, - .eccbytes = 6, - .eccpos = {0, 1, 2, 3, 4, 5}, - .oobfree = { {8, 8}, {6, 2} } +static struct nand_ecclayout doc200x_oobinfo = { + .eccbytes = 6, + .eccpos = {0, 1, 2, 3, 4, 5}, + .oobfree = {{8, 8}, {6, 2}} }; /* Find the (I)NFTL Media Header, and optionally also the mirror media header. @@ -1072,8 +1070,7 @@ static struct nand_oobinfo doc200x_oobin either "ANAND" or "BNAND". If findmirror=1, also look for the mirror media header. The page #s of the found media headers are placed in mh0_page and mh1_page in the DOC private structure. */ -static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, - const char *id, int findmirror) +static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; @@ -1082,17 +1079,19 @@ static int __init find_media_headers(str size_t retlen; for (offs = 0; offs < mtd->size; offs += mtd->erasesize) { - ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); - if (retlen != mtd->oobblock) continue; + ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); + if (retlen != mtd->writesize) + continue; if (ret) { - printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", - offs); + printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", offs); } - if (memcmp(buf, id, 6)) continue; + if (memcmp(buf, id, 6)) + continue; printk(KERN_INFO "Found DiskOnChip %s Media Header at 0x%x\n", id, offs); if (doc->mh0_page == -1) { doc->mh0_page = offs >> this->page_shift; - if (!findmirror) return 1; + if (!findmirror) + return 1; continue; } doc->mh1_page = offs >> this->page_shift; @@ -1105,8 +1104,8 @@ static int __init find_media_headers(str /* Only one mediaheader was found. We want buf to contain a mediaheader on return, so we'll have to re-read the one we found. */ offs = doc->mh0_page << this->page_shift; - ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); - if (retlen != mtd->oobblock) { + ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); + if (retlen != mtd->writesize) { /* Insanity. Give up. */ printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n"); return 0; @@ -1114,8 +1113,7 @@ static int __init find_media_headers(str return 1; } -static inline int __init nftl_partscan(struct mtd_info *mtd, - struct mtd_partition *parts) +static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; @@ -1127,13 +1125,14 @@ static inline int __init nftl_partscan(s unsigned blocks, maxblocks; int offs, numheaders; - buf = kmalloc(mtd->oobblock, GFP_KERNEL); + buf = kmalloc(mtd->writesize, GFP_KERNEL); if (!buf) { printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); return 0; } - if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out; - mh = (struct NFTLMediaHeader *) buf; + if (!(numheaders = find_media_headers(mtd, buf, "ANAND", 1))) + goto out; + mh = (struct NFTLMediaHeader *)buf; mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits); mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN); @@ -1155,8 +1154,8 @@ static inline int __init nftl_partscan(s /* Auto-determine UnitSizeFactor. The constraints are: - There can be at most 32768 virtual blocks. - There can be at most (virtual block size - page size) - virtual blocks (because MediaHeader+BBT must fit in 1). - */ + virtual blocks (because MediaHeader+BBT must fit in 1). + */ mh->UnitSizeFactor = 0xff; while (blocks > maxblocks) { blocks >>= 1; @@ -1211,14 +1210,13 @@ static inline int __init nftl_partscan(s } ret = numparts; -out: + out: kfree(buf); return ret; } /* This is a stripped-down copy of the code in inftlmount.c */ -static inline int __init inftl_partscan(struct mtd_info *mtd, - struct mtd_partition *parts) +static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts) { struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; @@ -1235,15 +1233,16 @@ static inline int __init inftl_partscan( if (inftl_bbt_write) end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift); - buf = kmalloc(mtd->oobblock, GFP_KERNEL); + buf = kmalloc(mtd->writesize, GFP_KERNEL); if (!buf) { printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); return 0; } - if (!find_media_headers(mtd, buf, "BNAND", 0)) goto out; + if (!find_media_headers(mtd, buf, "BNAND", 0)) + goto out; doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift); - mh = (struct INFTLMediaHeader *) buf; + mh = (struct INFTLMediaHeader *)buf; mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks); mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions); @@ -1319,8 +1318,10 @@ static inline int __init inftl_partscan( parts[numparts].offset = ip->firstUnit << vshift; parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift; numparts++; - if (ip->lastUnit > lastvunit) lastvunit = ip->lastUnit; - if (ip->flags & INFTL_LAST) break; + if (ip->lastUnit > lastvunit) + lastvunit = ip->lastUnit; + if (ip->flags & INFTL_LAST) + break; } lastvunit++; if ((lastvunit << vshift) < end) { @@ -1330,7 +1331,7 @@ static inline int __init inftl_partscan( numparts++; } ret = numparts; -out: + out: kfree(buf); return ret; } @@ -1342,11 +1343,12 @@ static int __init nftl_scan_bbt(struct m struct doc_priv *doc = this->priv; struct mtd_partition parts[2]; - memset((char *) parts, 0, sizeof(parts)); + memset((char *)parts, 0, sizeof(parts)); /* On NFTL, we have to find the media headers before we can read the BBTs, since they're stored in the media header eraseblocks. */ numparts = nftl_partscan(mtd, parts); - if (!numparts) return -EIO; + if (!numparts) + return -EIO; this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT | NAND_BBT_SAVECONTENT | NAND_BBT_WRITE | NAND_BBT_VERSION; @@ -1393,8 +1395,7 @@ static int __init inftl_scan_bbt(struct this->bbt_td->pages[0] = 2; this->bbt_md = NULL; } else { - this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | - NAND_BBT_VERSION; + this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION; if (inftl_bbt_write) this->bbt_td->options |= NAND_BBT_WRITE; this->bbt_td->offs = 8; @@ -1404,8 +1405,7 @@ static int __init inftl_scan_bbt(struct this->bbt_td->reserved_block_code = 0x01; this->bbt_td->pattern = "MSYS_BBT"; - this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | - NAND_BBT_VERSION; + this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION; if (inftl_bbt_write) this->bbt_md->options |= NAND_BBT_WRITE; this->bbt_md->offs = 8; @@ -1420,12 +1420,13 @@ static int __init inftl_scan_bbt(struct At least as nand_bbt.c is currently written. */ if ((ret = nand_scan_bbt(mtd, NULL))) return ret; - memset((char *) parts, 0, sizeof(parts)); + memset((char *)parts, 0, sizeof(parts)); numparts = inftl_partscan(mtd, parts); /* At least for now, require the INFTL Media Header. We could probably do without it for non-INFTL use, since all it gives us is autopartitioning, but I want to give it more thought. */ - if (!numparts) return -EIO; + if (!numparts) + return -EIO; add_mtd_device(mtd); #ifdef CONFIG_MTD_PARTITIONS if (!no_autopart) @@ -1439,7 +1440,6 @@ static inline int __init doc2000_init(st struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - this->write_byte = doc2000_write_byte; this->read_byte = doc2000_read_byte; this->write_buf = doc2000_writebuf; this->read_buf = doc2000_readbuf; @@ -1457,7 +1457,6 @@ static inline int __init doc2001_init(st struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - this->write_byte = doc2001_write_byte; this->read_byte = doc2001_read_byte; this->write_buf = doc2001_writebuf; this->read_buf = doc2001_readbuf; @@ -1489,16 +1488,15 @@ static inline int __init doc2001plus_ini struct nand_chip *this = mtd->priv; struct doc_priv *doc = this->priv; - this->write_byte = NULL; this->read_byte = doc2001plus_read_byte; this->write_buf = doc2001plus_writebuf; this->read_buf = doc2001plus_readbuf; this->verify_buf = doc2001plus_verifybuf; this->scan_bbt = inftl_scan_bbt; - this->hwcontrol = NULL; + this->cmd_ctrl = NULL; this->select_chip = doc2001plus_select_chip; this->cmdfunc = doc2001plus_command; - this->enable_hwecc = doc2001plus_enable_hwecc; + this->ecc.hwctl = doc2001plus_enable_hwecc; doc->chips_per_floor = 1; mtd->name = "DiskOnChip Millennium Plus"; @@ -1535,20 +1533,16 @@ static int __init doc_probe(unsigned lon save_control = ReadDOC(virtadr, DOCControl); /* Reset the DiskOnChip ASIC */ - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, - virtadr, DOCControl); - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, - virtadr, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl); /* Enable the DiskOnChip ASIC */ - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, - virtadr, DOCControl); - WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, - virtadr, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl); ChipID = ReadDOC(virtadr, ChipID); - switch(ChipID) { + switch (ChipID) { case DOC_ChipID_Doc2k: reg = DoC_2k_ECCStatus; break; @@ -1564,15 +1558,13 @@ static int __init doc_probe(unsigned lon ReadDOC(virtadr, Mplus_Power); /* Reset the Millennium Plus ASIC */ - tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | - DOC_MODE_BDECT; + tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT; WriteDOC(tmp, virtadr, Mplus_DOCControl); WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); mdelay(1); /* Enable the Millennium Plus ASIC */ - tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | - DOC_MODE_BDECT; + tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT; WriteDOC(tmp, virtadr, Mplus_DOCControl); WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); mdelay(1); @@ -1596,7 +1588,7 @@ static int __init doc_probe(unsigned lon goto notfound; } /* Check the TOGGLE bit in the ECC register */ - tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; + tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; tmpb = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; tmpc = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; if ((tmp == tmpb) || (tmp != tmpc)) { @@ -1626,11 +1618,11 @@ static int __init doc_probe(unsigned lon if (ChipID == DOC_ChipID_DocMilPlus16) { WriteDOC(~newval, virtadr, Mplus_AliasResolution); oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); - WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it + WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it } else { WriteDOC(~newval, virtadr, AliasResolution); oldval = ReadDOC(doc->virtadr, AliasResolution); - WriteDOC(newval, virtadr, AliasResolution); // restore it + WriteDOC(newval, virtadr, AliasResolution); // restore it } newval = ~newval; if (oldval == newval) { @@ -1642,10 +1634,8 @@ static int __init doc_probe(unsigned lon printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr); len = sizeof(struct mtd_info) + - sizeof(struct nand_chip) + - sizeof(struct doc_priv) + - (2 * sizeof(struct nand_bbt_descr)); - mtd = kmalloc(len, GFP_KERNEL); + sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr)); + mtd = kmalloc(len, GFP_KERNEL); if (!mtd) { printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); ret = -ENOMEM; @@ -1663,17 +1653,19 @@ static int __init doc_probe(unsigned lon nand->priv = doc; nand->select_chip = doc200x_select_chip; - nand->hwcontrol = doc200x_hwcontrol; + nand->cmd_ctrl = doc200x_hwcontrol; nand->dev_ready = doc200x_dev_ready; nand->waitfunc = doc200x_wait; nand->block_bad = doc200x_block_bad; - nand->enable_hwecc = doc200x_enable_hwecc; - nand->calculate_ecc = doc200x_calculate_ecc; - nand->correct_data = doc200x_correct_data; + nand->ecc.hwctl = doc200x_enable_hwecc; + nand->ecc.calculate = doc200x_calculate_ecc; + nand->ecc.correct = doc200x_correct_data; - nand->autooob = &doc200x_oobinfo; - nand->eccmode = NAND_ECC_HW6_512; - nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME; + nand->ecc.layout = &doc200x_oobinfo; + nand->ecc.mode = NAND_ECC_HW_SYNDROME; + nand->ecc.size = 512; + nand->ecc.bytes = 6; + nand->options = NAND_USE_FLASH_BBT; doc->physadr = physadr; doc->virtadr = virtadr; @@ -1707,18 +1699,18 @@ static int __init doc_probe(unsigned lon doclist = mtd; return 0; -notfound: + notfound: /* Put back the contents of the DOCControl register, in case it's not actually a DiskOnChip. */ WriteDOC(save_control, virtadr, DOCControl); -fail: + fail: iounmap(virtadr); return ret; } static void release_nanddoc(void) { - struct mtd_info *mtd, *nextmtd; + struct mtd_info *mtd, *nextmtd; struct nand_chip *nand; struct doc_priv *doc; @@ -1747,8 +1739,8 @@ static int __init init_nanddoc(void) * generator polinomial degree = 4 */ rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS); - if (!rs_decoder) { - printk (KERN_ERR "DiskOnChip: Could not create a RS decoder\n"); + if (!rs_decoder) { + printk(KERN_ERR "DiskOnChip: Could not create a RS decoder\n"); return -ENOMEM; } @@ -1758,7 +1750,7 @@ static int __init init_nanddoc(void) if (ret < 0) goto outerr; } else { - for (i=0; (doc_locations[i] != 0xffffffff); i++) { + for (i = 0; (doc_locations[i] != 0xffffffff); i++) { doc_probe(doc_locations[i]); } } @@ -1770,7 +1762,7 @@ static int __init init_nanddoc(void) goto outerr; } return 0; -outerr: + outerr: free_rs(rs_decoder); return ret; } diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c index 9b1fd2f..516c0e5 100644 --- a/drivers/mtd/nand/edb7312.c +++ b/drivers/mtd/nand/edb7312.c @@ -1,7 +1,7 @@ /* * drivers/mtd/nand/edb7312.c * - * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) + * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) * * Derived from drivers/mtd/nand/autcpu12.c * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) @@ -25,7 +25,7 @@ #include #include #include #include -#include /* for CLPS7111_VIRT_BASE */ +#include /* for CLPS7111_VIRT_BASE */ #include #include @@ -54,51 +54,45 @@ #define EP7312_PXDDR 0x0041 /* */ static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE; -static void __iomem * ep7312_pxdr = (void __iomem *) EP7312_PXDR; -static void __iomem * ep7312_pxddr = (void __iomem *) EP7312_PXDDR; +static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR; +static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR; #ifdef CONFIG_MTD_PARTITIONS /* * Define static partitions for flash device */ static struct mtd_partition partition_info[] = { - { .name = "EP7312 Nand Flash", - .offset = 0, - .size = 8*1024*1024 } + {.name = "EP7312 Nand Flash", + .offset = 0, + .size = 8 * 1024 * 1024} }; + #define NUM_PARTITIONS 1 #endif - /* * hardware specific access to control-lines + * + * NAND_NCE: bit 0 -> bit 7 + * NAND_CLE: bit 1 -> bit 4 + * NAND_ALE: bit 2 -> bit 5 */ -static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd) +static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { - switch(cmd) { - - case NAND_CTL_SETCLE: - clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr); - break; - case NAND_CTL_CLRCLE: - clps_writeb(clps_readb(ep7312_pxdr) & ~0x10, ep7312_pxdr); - break; - - case NAND_CTL_SETALE: - clps_writeb(clps_readb(ep7312_pxdr) | 0x20, ep7312_pxdr); - break; - case NAND_CTL_CLRALE: - clps_writeb(clps_readb(ep7312_pxdr) & ~0x20, ep7312_pxdr); - break; - - case NAND_CTL_SETNCE: - clps_writeb((clps_readb(ep7312_pxdr) | 0x80) & ~0x40, ep7312_pxdr); - break; - case NAND_CTL_CLRNCE: - clps_writeb((clps_readb(ep7312_pxdr) | 0x80) | 0x40, ep7312_pxdr); - break; + struct nand_chip *chip = mtd->priv; + + if (ctrl & NAND_CTRL_CHANGE) { + unsigned char bits; + + bits = (ctrl & (NAND_CLE | NAND_ALE)) << 3; + bits = (ctrl & NAND_NCE) << 7; + + clps_writeb((clps_readb(ep7312_pxdr) & 0xB0) | 0x10, + ep7312_pxdr); } + if (cmd != NAND_CMD_NONE) + writeb(cmd, chip->IO_ADDR_W); } /* @@ -108,6 +102,7 @@ static int ep7312_device_ready(struct mt { return 1; } + #ifdef CONFIG_MTD_PARTITIONS const char *part_probes[] = { "cmdlinepart", NULL }; #endif @@ -115,18 +110,16 @@ #endif /* * Main initialization routine */ -static int __init ep7312_init (void) +static int __init ep7312_init(void) { struct nand_chip *this; const char *part_type = 0; int mtd_parts_nb = 0; struct mtd_partition *mtd_parts = 0; - void __iomem * ep7312_fio_base; + void __iomem *ep7312_fio_base; /* Allocate memory for MTD device structure and private data */ - ep7312_mtd = kmalloc(sizeof(struct mtd_info) + - sizeof(struct nand_chip), - GFP_KERNEL); + ep7312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!ep7312_mtd) { printk("Unable to allocate EDB7312 NAND MTD device structure.\n"); return -ENOMEM; @@ -134,21 +127,22 @@ static int __init ep7312_init (void) /* map physical adress */ ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K); - if(!ep7312_fio_base) { + if (!ep7312_fio_base) { printk("ioremap EDB7312 NAND flash failed\n"); kfree(ep7312_mtd); return -EIO; } /* Get pointer to private data */ - this = (struct nand_chip *) (&ep7312_mtd[1]); + this = (struct nand_chip *)(&ep7312_mtd[1]); /* Initialize structures */ - memset((char *) ep7312_mtd, 0, sizeof(struct mtd_info)); - memset((char *) this, 0, sizeof(struct nand_chip)); + memset(ep7312_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ ep7312_mtd->priv = this; + ep7312_mtd->owner = THIS_MODULE; /* * Set GPIO Port B control register so that the pins are configured @@ -159,22 +153,20 @@ static int __init ep7312_init (void) /* insert callbacks */ this->IO_ADDR_R = ep7312_fio_base; this->IO_ADDR_W = ep7312_fio_base; - this->hwcontrol = ep7312_hwcontrol; + this->cmd_ctrl = ep7312_hwcontrol; this->dev_ready = ep7312_device_ready; /* 15 us command delay time */ this->chip_delay = 15; /* Scan to find existence of the device */ - if (nand_scan (ep7312_mtd, 1)) { + if (nand_scan(ep7312_mtd, 1)) { iounmap((void *)ep7312_fio_base); - kfree (ep7312_mtd); + kfree(ep7312_mtd); return -ENXIO; } - #ifdef CONFIG_MTD_PARTITIONS ep7312_mtd->name = "edb7312-nand"; - mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, - &mtd_parts, 0); + mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0); if (mtd_parts_nb > 0) part_type = "command line"; else @@ -193,24 +185,23 @@ #endif /* Return happy */ return 0; } + module_init(ep7312_init); /* * Clean up routine */ -static void __exit ep7312_cleanup (void) +static void __exit ep7312_cleanup(void) { - struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1]; + struct nand_chip *this = (struct nand_chip *)&ep7312_mtd[1]; /* Release resources, unregister device */ - nand_release (ap7312_mtd); - - /* Free internal data buffer */ - kfree (this->data_buf); + nand_release(ap7312_mtd); /* Free the MTD device structure */ - kfree (ep7312_mtd); + kfree(ep7312_mtd); } + module_exit(ep7312_cleanup); MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c index f68f7a9..2d585d2 100644 --- a/drivers/mtd/nand/h1910.c +++ b/drivers/mtd/nand/h1910.c @@ -4,7 +4,7 @@ * Copyright (C) 2003 Joshua Wise (joshua@joshuawise.com) * * Derived from drivers/mtd/nand/edb7312.c - * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) + * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) * * $Id: h1910.c,v 1.6 2005/11/07 11:14:30 gleixner Exp $ @@ -26,7 +26,7 @@ #include #include #include #include -#include /* for CLPS7111_VIRT_BASE */ +#include /* for CLPS7111_VIRT_BASE */ #include #include #include @@ -45,47 +45,29 @@ #ifdef CONFIG_MTD_PARTITIONS * Define static partitions for flash device */ static struct mtd_partition partition_info[] = { - { name: "h1910 NAND Flash", - offset: 0, - size: 16*1024*1024 } + {name:"h1910 NAND Flash", + offset:0, + size:16 * 1024 * 1024} }; + #define NUM_PARTITIONS 1 #endif - /* * hardware specific access to control-lines + * + * NAND_NCE: bit 0 - don't care + * NAND_CLE: bit 1 - address bit 2 + * NAND_ALE: bit 2 - address bit 3 */ -static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) +static void h1910_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) { - struct nand_chip* this = (struct nand_chip *) (mtd->priv); - - switch(cmd) { - - case NAND_CTL_SETCLE: - this->IO_ADDR_R |= (1 << 2); - this->IO_ADDR_W |= (1 << 2); - break; - case NAND_CTL_CLRCLE: - this->IO_ADDR_R &= ~(1 << 2); - this->IO_ADDR_W &= ~(1 << 2); - break; - - case NAND_CTL_SETALE: - this->IO_ADDR_R |= (1 << 3); - this->IO_ADDR_W |= (1 << 3); - break; - case NAND_CTL_CLRALE: - this->IO_ADDR_R &= ~(1 << 3); - this->IO_ADDR_W &= ~(1 << 3); - break; - - case NAND_CTL_SETNCE: - break; - case NAND_CTL_CLRNCE: - break; - } + struct nand_chip *chip = mtd->priv; + + if (cmd != NAND_CMD_NONE) + writeb(cmd, chip->IO_ADDR_W | ((ctrl & 0x6) << 1)); } /* @@ -101,7 +83,7 @@ #endif /* * Main initialization routine */ -static int __init h1910_init (void) +static int __init h1910_init(void) { struct nand_chip *this; const char *part_type = 0; @@ -119,24 +101,23 @@ static int __init h1910_init (void) } /* Allocate memory for MTD device structure and private data */ - h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + - sizeof(struct nand_chip), - GFP_KERNEL); + h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!h1910_nand_mtd) { printk("Unable to allocate h1910 NAND MTD device structure.\n"); - iounmap ((void *) nandaddr); + iounmap((void *)nandaddr); return -ENOMEM; } /* Get pointer to private data */ - this = (struct nand_chip *) (&h1910_nand_mtd[1]); + this = (struct nand_chip *)(&h1910_nand_mtd[1]); /* Initialize structures */ - memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info)); - memset((char *) this, 0, sizeof(struct nand_chip)); + memset(h1910_nand_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ h1910_nand_mtd->priv = this; + h1910_nand_mtd->owner = THIS_MODULE; /* * Enable VPEN @@ -146,31 +127,28 @@ static int __init h1910_init (void) /* insert callbacks */ this->IO_ADDR_R = nandaddr; this->IO_ADDR_W = nandaddr; - this->hwcontrol = h1910_hwcontrol; + this->cmd_ctrl = h1910_hwcontrol; this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */ /* 15 us command delay time */ this->chip_delay = 50; - this->eccmode = NAND_ECC_SOFT; + this->ecc.mode = NAND_ECC_SOFT; this->options = NAND_NO_AUTOINCR; /* Scan to find existence of the device */ - if (nand_scan (h1910_nand_mtd, 1)) { + if (nand_scan(h1910_nand_mtd, 1)) { printk(KERN_NOTICE "No NAND device - returning -ENXIO\n"); - kfree (h1910_nand_mtd); - iounmap ((void *) nandaddr); + kfree(h1910_nand_mtd); + iounmap((void *)nandaddr); return -ENXIO; } - #ifdef CONFIG_MTD_CMDLINE_PARTS - mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, - "h1910-nand"); + mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, "h1910-nand"); if (mtd_parts_nb > 0) - part_type = "command line"; + part_type = "command line"; else - mtd_parts_nb = 0; + mtd_parts_nb = 0; #endif - if (mtd_parts_nb == 0) - { + if (mtd_parts_nb == 0) { mtd_parts = partition_info; mtd_parts_nb = NUM_PARTITIONS; part_type = "static"; @@ -183,24 +161,26 @@ #endif /* Return happy */ return 0; } + module_init(h1910_init); /* * Clean up routine */ -static void __exit h1910_cleanup (void) +static void __exit h1910_cleanup(void) { - struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1]; + struct nand_chip *this = (struct nand_chip *)&h1910_nand_mtd[1]; /* Release resources, unregister device */ - nand_release (h1910_nand_mtd); + nand_release(h1910_nand_mtd); /* Release io resource */ - iounmap ((void *) this->IO_ADDR_W); + iounmap((void *)this->IO_ADDR_W); /* Free the MTD device structure */ - kfree (h1910_nand_mtd); + kfree(h1910_nand_mtd); } + module_exit(h1910_cleanup); MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 95e96fa..27083ed 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -10,67 +10,31 @@ * http://www.linux-mtd.infradead.org/tech/nand.html * * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) - * 2002 Thomas Gleixner (tglx@linutronix.de) + * 2002-2006 Thomas Gleixner (tglx@linutronix.de) * - * 02-08-2004 tglx: support for strange chips, which cannot auto increment - * pages on read / read_oob - * - * 03-17-2004 tglx: Check ready before auto increment check. Simon Bayes - * pointed this out, as he marked an auto increment capable chip - * as NOAUTOINCR in the board driver. - * Make reads over block boundaries work too - * - * 04-14-2004 tglx: first working version for 2k page size chips - * - * 05-19-2004 tglx: Basic support for Renesas AG-AND chips - * - * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared - * among multiple independend devices. Suggestions and initial patch - * from Ben Dooks - * - * 12-05-2004 dmarlin: add workaround for Renesas AG-AND chips "disturb" issue. - * Basically, any block not rewritten may lose data when surrounding blocks - * are rewritten many times. JFFS2 ensures this doesn't happen for blocks - * it uses, but the Bad Block Table(s) may not be rewritten. To ensure they - * do not lose data, force them to be rewritten when some of the surrounding - * blocks are erased. Rather than tracking a specific nearby block (which - * could itself go bad), use a page address 'mask' to select several blocks - * in the same area, and rewrite the BBT when any of them are erased. - * - * 01-03-2005 dmarlin: added support for the device recovery command sequence for Renesas - * AG-AND chips. If there was a sudden loss of power during an erase operation, - * a "device recovery" operation must be performed when power is restored - * to ensure correct operation. - * - * 01-20-2005 dmarlin: added support for optional hardware specific callback routine to - * perform extra error status checks on erase and write failures. This required - * adding a wrapper function for nand_read_ecc. - * - * 08-20-2005 vwool: suspend/resume added - * - * Credits: + * Credits: * David Woodhouse for adding multichip support * * Aleph One Ltd. and Toby Churchill Ltd. for supporting the * rework for 2K page size chips * - * TODO: + * TODO: * Enable cached programming for 2k page size chips * Check, if mtd->ecctype should be set to MTD_ECC_HW * if we have HW ecc support. * The AG-AND chips have nice features for speed improvement, * which are not supported yet. Read / program 4 pages in one go. * - * $Id: nand_base.c,v 1.150 2005/09/15 13:58:48 vwool Exp $ - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */ +#include #include #include +#include #include #include #include @@ -88,75 +52,46 @@ #include #endif /* Define default oob placement schemes for large and small page devices */ -static struct nand_oobinfo nand_oob_8 = { - .useecc = MTD_NANDECC_AUTOPLACE, +static struct nand_ecclayout nand_oob_8 = { .eccbytes = 3, .eccpos = {0, 1, 2}, - .oobfree = { {3, 2}, {6, 2} } + .oobfree = { + {.offset = 3, + .length = 2}, + {.offset = 6, + .length = 2}} }; -static struct nand_oobinfo nand_oob_16 = { - .useecc = MTD_NANDECC_AUTOPLACE, +static struct nand_ecclayout nand_oob_16 = { .eccbytes = 6, .eccpos = {0, 1, 2, 3, 6, 7}, - .oobfree = { {8, 8} } + .oobfree = { + {.offset = 8, + . length = 8}} }; -static struct nand_oobinfo nand_oob_64 = { - .useecc = MTD_NANDECC_AUTOPLACE, +static struct nand_ecclayout nand_oob_64 = { .eccbytes = 24, .eccpos = { - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63}, - .oobfree = { {2, 38} } + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63}, + .oobfree = { + {.offset = 2, + .length = 38}} }; -/* This is used for padding purposes in nand_write_oob */ -static u_char ffchars[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -}; +static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, + int new_state); + +static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops); /* - * NAND low-level MTD interface functions + * For devices which display every fart in the system on a seperate LED. Is + * compiled away when LED support is disabled. */ -static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len); -static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len); -static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len); - -static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf); -static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, - size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel); -static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf); -static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf); -static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, - size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel); -static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf); -static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t * retlen); -static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); -static int nand_erase (struct mtd_info *mtd, struct erase_info *instr); -static void nand_sync (struct mtd_info *mtd); - -/* Some internal functions */ -static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, - struct nand_oobinfo *oobsel, int mode); -#ifdef CONFIG_MTD_NAND_VERIFY_WRITE -static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, - u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode); -#else -#define nand_verify_pages(...) (0) -#endif - -static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); +DEFINE_LED_TRIGGER(nand_led_trigger); /** * nand_release_device - [GENERIC] release chip @@ -164,27 +99,19 @@ static int nand_get_device (struct nand_ * * Deselect, release chip lock and wake up anyone waiting on the device */ -static void nand_release_device (struct mtd_info *mtd) +static void nand_release_device(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; /* De-select the NAND device */ - this->select_chip(mtd, -1); - - if (this->controller) { - /* Release the controller and the chip */ - spin_lock(&this->controller->lock); - this->controller->active = NULL; - this->state = FL_READY; - wake_up(&this->controller->wq); - spin_unlock(&this->controller->lock); - } else { - /* Release the chip */ - spin_lock(&this->chip_lock); - this->state = FL_READY; - wake_up(&this->wq); - spin_unlock(&this->chip_lock); - } + chip->select_chip(mtd, -1); + + /* Release the controller and the chip */ + spin_lock(&chip->controller->lock); + chip->controller->active = NULL; + chip->state = FL_READY; + wake_up(&chip->controller->wq); + spin_unlock(&chip->controller->lock); } /** @@ -193,23 +120,10 @@ static void nand_release_device (struct * * Default read function for 8bit buswith */ -static u_char nand_read_byte(struct mtd_info *mtd) -{ - struct nand_chip *this = mtd->priv; - return readb(this->IO_ADDR_R); -} - -/** - * nand_write_byte - [DEFAULT] write one byte to the chip - * @mtd: MTD device structure - * @byte: pointer to data byte to write - * - * Default write function for 8it buswith - */ -static void nand_write_byte(struct mtd_info *mtd, u_char byte) +static uint8_t nand_read_byte(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; - writeb(byte, this->IO_ADDR_W); + struct nand_chip *chip = mtd->priv; + return readb(chip->IO_ADDR_R); } /** @@ -219,24 +133,10 @@ static void nand_write_byte(struct mtd_i * Default read function for 16bit buswith with * endianess conversion */ -static u_char nand_read_byte16(struct mtd_info *mtd) +static uint8_t nand_read_byte16(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; - return (u_char) cpu_to_le16(readw(this->IO_ADDR_R)); -} - -/** - * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip - * @mtd: MTD device structure - * @byte: pointer to data byte to write - * - * Default write function for 16bit buswith with - * endianess conversion - */ -static void nand_write_byte16(struct mtd_info *mtd, u_char byte) -{ - struct nand_chip *this = mtd->priv; - writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); + struct nand_chip *chip = mtd->priv; + return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R)); } /** @@ -248,22 +148,8 @@ static void nand_write_byte16(struct mtd */ static u16 nand_read_word(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; - return readw(this->IO_ADDR_R); -} - -/** - * nand_write_word - [DEFAULT] write one word to the chip - * @mtd: MTD device structure - * @word: data word to write - * - * Default write function for 16bit buswith without - * endianess conversion - */ -static void nand_write_word(struct mtd_info *mtd, u16 word) -{ - struct nand_chip *this = mtd->priv; - writew(word, this->IO_ADDR_W); + struct nand_chip *chip = mtd->priv; + return readw(chip->IO_ADDR_R); } /** @@ -273,15 +159,15 @@ static void nand_write_word(struct mtd_i * * Default select function for 1 chip devices. */ -static void nand_select_chip(struct mtd_info *mtd, int chip) +static void nand_select_chip(struct mtd_info *mtd, int chipnr) { - struct nand_chip *this = mtd->priv; - switch(chip) { + struct nand_chip *chip = mtd->priv; + + switch (chipnr) { case -1: - this->hwcontrol(mtd, NAND_CTL_CLRNCE); + chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); break; case 0: - this->hwcontrol(mtd, NAND_CTL_SETNCE); break; default: @@ -297,13 +183,13 @@ static void nand_select_chip(struct mtd_ * * Default write function for 8bit buswith */ -static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; - for (i=0; iIO_ADDR_W); + for (i = 0; i < len; i++) + writeb(buf[i], chip->IO_ADDR_W); } /** @@ -314,13 +200,13 @@ static void nand_write_buf(struct mtd_in * * Default read function for 8bit buswith */ -static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; - for (i=0; iIO_ADDR_R); + for (i = 0; i < len; i++) + buf[i] = readb(chip->IO_ADDR_R); } /** @@ -331,15 +217,14 @@ static void nand_read_buf(struct mtd_inf * * Default verify function for 8bit buswith */ -static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) +static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; - for (i=0; iIO_ADDR_R)) + for (i = 0; i < len; i++) + if (buf[i] != readb(chip->IO_ADDR_R)) return -EFAULT; - return 0; } @@ -351,15 +236,15 @@ static int nand_verify_buf(struct mtd_in * * Default write function for 16bit buswith */ -static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) +static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; u16 *p = (u16 *) buf; len >>= 1; - for (i=0; iIO_ADDR_W); + for (i = 0; i < len; i++) + writew(p[i], chip->IO_ADDR_W); } @@ -371,15 +256,15 @@ static void nand_write_buf16(struct mtd_ * * Default read function for 16bit buswith */ -static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len) +static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; u16 *p = (u16 *) buf; len >>= 1; - for (i=0; iIO_ADDR_R); + for (i = 0; i < len; i++) + p[i] = readw(chip->IO_ADDR_R); } /** @@ -390,15 +275,15 @@ static void nand_read_buf16(struct mtd_i * * Default verify function for 16bit buswith */ -static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) +static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) { int i; - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; u16 *p = (u16 *) buf; len >>= 1; - for (i=0; iIO_ADDR_R)) + for (i = 0; i < len; i++) + if (p[i] != readw(chip->IO_ADDR_R)) return -EFAULT; return 0; @@ -415,38 +300,37 @@ static int nand_verify_buf16(struct mtd_ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) { int page, chipnr, res = 0; - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; u16 bad; if (getchip) { - page = (int)(ofs >> this->page_shift); - chipnr = (int)(ofs >> this->chip_shift); + page = (int)(ofs >> chip->page_shift); + chipnr = (int)(ofs >> chip->chip_shift); - /* Grab the lock and see if the device is available */ - nand_get_device (this, mtd, FL_READING); + nand_get_device(chip, mtd, FL_READING); /* Select the NAND device */ - this->select_chip(mtd, chipnr); + chip->select_chip(mtd, chipnr); } else - page = (int) ofs; + page = (int)ofs; - if (this->options & NAND_BUSWIDTH_16) { - this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask); - bad = cpu_to_le16(this->read_word(mtd)); - if (this->badblockpos & 0x1) + if (chip->options & NAND_BUSWIDTH_16) { + chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE, + page & chip->pagemask); + bad = cpu_to_le16(chip->read_word(mtd)); + if (chip->badblockpos & 0x1) bad >>= 8; if ((bad & 0xFF) != 0xff) res = 1; } else { - this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask); - if (this->read_byte(mtd) != 0xff) + chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, + page & chip->pagemask); + if (chip->read_byte(mtd) != 0xff) res = 1; } - if (getchip) { - /* Deselect and wake up anyone waiting on the device */ + if (getchip) nand_release_device(mtd); - } return res; } @@ -461,23 +345,33 @@ static int nand_block_bad(struct mtd_inf */ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) { - struct nand_chip *this = mtd->priv; - u_char buf[2] = {0, 0}; - size_t retlen; - int block; + struct nand_chip *chip = mtd->priv; + uint8_t buf[2] = { 0, 0 }; + int block, ret; /* Get block number */ - block = ((int) ofs) >> this->bbt_erase_shift; - if (this->bbt) - this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); + block = ((int)ofs) >> chip->bbt_erase_shift; + if (chip->bbt) + chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); /* Do we have a flash based bad block table ? */ - if (this->options & NAND_USE_FLASH_BBT) - return nand_update_bbt (mtd, ofs); + if (chip->options & NAND_USE_FLASH_BBT) + ret = nand_update_bbt(mtd, ofs); + else { + /* We write two bytes, so we dont have to mess with 16 bit + * access + */ + ofs += mtd->oobsize; + chip->ops.len = 2; + chip->ops.datbuf = NULL; + chip->ops.oobbuf = buf; + chip->ops.ooboffs = chip->badblockpos & ~0x01; - /* We write two bytes, so we dont have to mess with 16 bit access */ - ofs += mtd->oobsize + (this->badblockpos & ~0x01); - return nand_write_oob (mtd, ofs , 2, &retlen, buf); + ret = nand_do_write_oob(mtd, ofs, &chip->ops); + } + if (!ret) + mtd->ecc_stats.badblocks++; + return ret; } /** @@ -487,12 +381,12 @@ static int nand_default_block_markbad(st * * The function expects, that the device is already selected */ -static int nand_check_wp (struct mtd_info *mtd) +static int nand_check_wp(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; /* Check the WP bit */ - this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); - return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; + chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); + return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; } /** @@ -505,32 +399,31 @@ static int nand_check_wp (struct mtd_inf * Check, if the block is bad. Either by reading the bad block table or * calling of the scan function. */ -static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) +static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, + int allowbbt) { - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; - if (!this->bbt) - return this->block_bad(mtd, ofs, getchip); + if (!chip->bbt) + return chip->block_bad(mtd, ofs, getchip); /* Return info from the table */ - return nand_isbad_bbt (mtd, ofs, allowbbt); + return nand_isbad_bbt(mtd, ofs, allowbbt); } -DEFINE_LED_TRIGGER(nand_led_trigger); - /* * Wait for the ready pin, after a command * The timeout is catched later. */ static void nand_wait_ready(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; - unsigned long timeo = jiffies + 2; + struct nand_chip *chip = mtd->priv; + unsigned long timeo = jiffies + 2; led_trigger_event(nand_led_trigger, LED_FULL); /* wait until command is processed or timeout occures */ do { - if (this->dev_ready(mtd)) + if (chip->dev_ready(mtd)) break; touch_softlockup_watchdog(); } while (time_before(jiffies, timeo)); @@ -547,21 +440,21 @@ static void nand_wait_ready(struct mtd_i * Send command to NAND device. This function is used for small page * devices (256/512 Bytes per page) */ -static void nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) +static void nand_command(struct mtd_info *mtd, unsigned int command, + int column, int page_addr) { - register struct nand_chip *this = mtd->priv; + register struct nand_chip *chip = mtd->priv; + int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE; - /* Begin command latch cycle */ - this->hwcontrol(mtd, NAND_CTL_SETCLE); /* * Write out the command to the device. */ if (command == NAND_CMD_SEQIN) { int readcmd; - if (column >= mtd->oobblock) { + if (column >= mtd->writesize) { /* OOB area */ - column -= mtd->oobblock; + column -= mtd->writesize; readcmd = NAND_CMD_READOOB; } else if (column < 256) { /* First 256 bytes --> READ0 */ @@ -570,38 +463,37 @@ static void nand_command (struct mtd_inf column -= 256; readcmd = NAND_CMD_READ1; } - this->write_byte(mtd, readcmd); + chip->cmd_ctrl(mtd, readcmd, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; } - this->write_byte(mtd, command); - - /* Set ALE and clear CLE to start address cycle */ - this->hwcontrol(mtd, NAND_CTL_CLRCLE); + chip->cmd_ctrl(mtd, command, ctrl); - if (column != -1 || page_addr != -1) { - this->hwcontrol(mtd, NAND_CTL_SETALE); - - /* Serially input address */ - if (column != -1) { - /* Adjust columns for 16 bit buswidth */ - if (this->options & NAND_BUSWIDTH_16) - column >>= 1; - this->write_byte(mtd, column); - } - if (page_addr != -1) { - this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); - this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); - /* One more address cycle for devices > 32MiB */ - if (this->chipsize > (32 << 20)) - this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); - } - /* Latch in address */ - this->hwcontrol(mtd, NAND_CTL_CLRALE); + /* + * Address cycle, when necessary + */ + ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; + /* Serially input address */ + if (column != -1) { + /* Adjust columns for 16 bit buswidth */ + if (chip->options & NAND_BUSWIDTH_16) + column >>= 1; + chip->cmd_ctrl(mtd, column, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; + } + if (page_addr != -1) { + chip->cmd_ctrl(mtd, page_addr, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; + chip->cmd_ctrl(mtd, page_addr >> 8, ctrl); + /* One more address cycle for devices > 32MiB */ + if (chip->chipsize > (32 << 20)) + chip->cmd_ctrl(mtd, page_addr >> 16, ctrl); } + chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* * program and erase have their own busy handlers * status and sequential in needs no delay - */ + */ switch (command) { case NAND_CMD_PAGEPROG: @@ -612,29 +504,30 @@ static void nand_command (struct mtd_inf return; case NAND_CMD_RESET: - if (this->dev_ready) + if (chip->dev_ready) break; - udelay(this->chip_delay); - this->hwcontrol(mtd, NAND_CTL_SETCLE); - this->write_byte(mtd, NAND_CMD_STATUS); - this->hwcontrol(mtd, NAND_CTL_CLRCLE); - while ( !(this->read_byte(mtd) & NAND_STATUS_READY)); + udelay(chip->chip_delay); + chip->cmd_ctrl(mtd, NAND_CMD_STATUS, + NAND_CTRL_CLE | NAND_CTRL_CHANGE); + chip->cmd_ctrl(mtd, + NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); + while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ; return; - /* This applies to read commands */ + /* This applies to read commands */ default: /* * If we don't have access to the busy pin, we apply the given * command delay - */ - if (!this->dev_ready) { - udelay (this->chip_delay); + */ + if (!chip->dev_ready) { + udelay(chip->chip_delay); return; } } /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ - ndelay (100); + ndelay(100); nand_wait_ready(mtd); } @@ -646,50 +539,49 @@ static void nand_command (struct mtd_inf * @column: the column address for this command, -1 if none * @page_addr: the page address for this command, -1 if none * - * Send command to NAND device. This is the version for the new large page devices - * We dont have the seperate regions as we have in the small page devices. - * We must emulate NAND_CMD_READOOB to keep the code compatible. + * Send command to NAND device. This is the version for the new large page + * devices We dont have the separate regions as we have in the small page + * devices. We must emulate NAND_CMD_READOOB to keep the code compatible. * */ -static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, int page_addr) +static void nand_command_lp(struct mtd_info *mtd, unsigned int command, + int column, int page_addr) { - register struct nand_chip *this = mtd->priv; + register struct nand_chip *chip = mtd->priv; /* Emulate NAND_CMD_READOOB */ if (command == NAND_CMD_READOOB) { - column += mtd->oobblock; + column += mtd->writesize; command = NAND_CMD_READ0; } - - /* Begin command latch cycle */ - this->hwcontrol(mtd, NAND_CTL_SETCLE); - /* Write out the command to the device. */ - this->write_byte(mtd, (command & 0xff)); - /* End command latch cycle */ - this->hwcontrol(mtd, NAND_CTL_CLRCLE); + /* Command latch cycle */ + chip->cmd_ctrl(mtd, command & 0xff, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); if (column != -1 || page_addr != -1) { - this->hwcontrol(mtd, NAND_CTL_SETALE); + int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE; /* Serially input address */ if (column != -1) { /* Adjust columns for 16 bit buswidth */ - if (this->options & NAND_BUSWIDTH_16) + if (chip->options & NAND_BUSWIDTH_16) column >>= 1; - this->write_byte(mtd, column & 0xff); - this->write_byte(mtd, column >> 8); + chip->cmd_ctrl(mtd, column, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; + chip->cmd_ctrl(mtd, column >> 8, ctrl); } if (page_addr != -1) { - this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); - this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); + chip->cmd_ctrl(mtd, page_addr, ctrl); + chip->cmd_ctrl(mtd, page_addr >> 8, + NAND_NCE | NAND_ALE); /* One more address cycle for devices > 128MiB */ - if (this->chipsize > (128 << 20)) - this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0xff)); + if (chip->chipsize > (128 << 20)) + chip->cmd_ctrl(mtd, page_addr >> 16, + NAND_NCE | NAND_ALE); } - /* Latch in address */ - this->hwcontrol(mtd, NAND_CTL_CLRALE); } + chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* * program and erase have their own busy handlers @@ -702,55 +594,62 @@ static void nand_command_lp (struct mtd_ case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: case NAND_CMD_SEQIN: + case NAND_CMD_RNDIN: case NAND_CMD_STATUS: case NAND_CMD_DEPLETE1: return; - /* - * read error status commands require only a short delay - */ + /* + * read error status commands require only a short delay + */ case NAND_CMD_STATUS_ERROR: case NAND_CMD_STATUS_ERROR0: case NAND_CMD_STATUS_ERROR1: case NAND_CMD_STATUS_ERROR2: case NAND_CMD_STATUS_ERROR3: - udelay(this->chip_delay); + udelay(chip->chip_delay); return; case NAND_CMD_RESET: - if (this->dev_ready) + if (chip->dev_ready) break; - udelay(this->chip_delay); - this->hwcontrol(mtd, NAND_CTL_SETCLE); - this->write_byte(mtd, NAND_CMD_STATUS); - this->hwcontrol(mtd, NAND_CTL_CLRCLE); - while ( !(this->read_byte(mtd) & NAND_STATUS_READY)); + udelay(chip->chip_delay); + chip->cmd_ctrl(mtd, NAND_CMD_STATUS, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->cmd_ctrl(mtd, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); + while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ; + return; + + case NAND_CMD_RNDOUT: + /* No ready / busy check necessary */ + chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->cmd_ctrl(mtd, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); return; case NAND_CMD_READ0: - /* Begin command latch cycle */ - this->hwcontrol(mtd, NAND_CTL_SETCLE); - /* Write out the start read command */ - this->write_byte(mtd, NAND_CMD_READSTART); - /* End command latch cycle */ - this->hwcontrol(mtd, NAND_CTL_CLRCLE); - /* Fall through into ready check */ - - /* This applies to read commands */ + chip->cmd_ctrl(mtd, NAND_CMD_READSTART, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->cmd_ctrl(mtd, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); + + /* This applies to read commands */ default: /* * If we don't have access to the busy pin, we apply the given * command delay - */ - if (!this->dev_ready) { - udelay (this->chip_delay); + */ + if (!chip->dev_ready) { + udelay(chip->chip_delay); return; } } /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ - ndelay (100); + ndelay(100); nand_wait_ready(mtd); } @@ -763,34 +662,28 @@ static void nand_command_lp (struct mtd_ * * Get the device and lock it for exclusive access */ -static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) +static int +nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state) { - struct nand_chip *active; - spinlock_t *lock; - wait_queue_head_t *wq; - DECLARE_WAITQUEUE (wait, current); - - lock = (this->controller) ? &this->controller->lock : &this->chip_lock; - wq = (this->controller) ? &this->controller->wq : &this->wq; -retry: - active = this; + spinlock_t *lock = &chip->controller->lock; + wait_queue_head_t *wq = &chip->controller->wq; + DECLARE_WAITQUEUE(wait, current); + retry: spin_lock(lock); /* Hardware controller shared among independend devices */ - if (this->controller) { - if (this->controller->active) - active = this->controller->active; - else - this->controller->active = this; - } - if (active == this && this->state == FL_READY) { - this->state = new_state; + /* Hardware controller shared among independend devices */ + if (!chip->controller->active) + chip->controller->active = chip; + + if (chip->controller->active == chip && chip->state == FL_READY) { + chip->state = new_state; spin_unlock(lock); return 0; } if (new_state == FL_PM_SUSPENDED) { spin_unlock(lock); - return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN; + return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN; } set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(wq, &wait); @@ -804,540 +697,339 @@ retry: * nand_wait - [DEFAULT] wait until the command is done * @mtd: MTD device structure * @this: NAND chip structure - * @state: state to select the max. timeout value * * Wait for command done. This applies to erase and program only * Erase can take up to 400ms and program up to 20ms according to * general NAND and SmartMedia specs * */ -static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) +static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) { - unsigned long timeo = jiffies; - int status; + unsigned long timeo = jiffies; + int status, state = chip->state; if (state == FL_ERASING) - timeo += (HZ * 400) / 1000; + timeo += (HZ * 400) / 1000; else - timeo += (HZ * 20) / 1000; + timeo += (HZ * 20) / 1000; led_trigger_event(nand_led_trigger, LED_FULL); /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ - ndelay (100); + ndelay(100); - if ((state == FL_ERASING) && (this->options & NAND_IS_AND)) - this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1); + if ((state == FL_ERASING) && (chip->options & NAND_IS_AND)) + chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1); else - this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); + chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); while (time_before(jiffies, timeo)) { - /* Check, if we were interrupted */ - if (this->state != state) - return 0; - - if (this->dev_ready) { - if (this->dev_ready(mtd)) + if (chip->dev_ready) { + if (chip->dev_ready(mtd)) break; } else { - if (this->read_byte(mtd) & NAND_STATUS_READY) + if (chip->read_byte(mtd) & NAND_STATUS_READY) break; } cond_resched(); } led_trigger_event(nand_led_trigger, LED_OFF); - status = (int) this->read_byte(mtd); + status = (int)chip->read_byte(mtd); return status; } /** - * nand_write_page - [GENERIC] write one page - * @mtd: MTD device structure - * @this: NAND chip structure - * @page: startpage inside the chip, must be called with (page & this->pagemask) - * @oob_buf: out of band data buffer - * @oobsel: out of band selecttion structre - * @cached: 1 = enable cached programming if supported by chip - * - * Nand_page_program function is used for write and writev ! - * This function will always program a full page of data - * If you call it with a non page aligned buffer, you're lost :) - * - * Cached programming is not supported yet. + * nand_read_page_raw - [Intern] read raw page data without ecc + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data */ -static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, - u_char *oob_buf, struct nand_oobinfo *oobsel, int cached) +static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf) { - int i, status; - u_char ecc_code[32]; - int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; - int *oob_config = oobsel->eccpos; - int datidx = 0, eccidx = 0, eccsteps = this->eccsteps; - int eccbytes = 0; - - /* FIXME: Enable cached programming */ - cached = 0; + chip->read_buf(mtd, buf, mtd->writesize); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + return 0; +} - /* Send command to begin auto page programming */ - this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page); +/** + * nand_read_page_swecc - {REPLACABLE] software ecc based page read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data + */ +static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint8_t *p = buf; + uint8_t *ecc_calc = chip->buffers.ecccalc; + uint8_t *ecc_code = chip->buffers.ecccode; + int *eccpos = chip->ecc.layout->eccpos; - /* Write out complete page of data, take care of eccmode */ - switch (eccmode) { - /* No ecc, write all */ - case NAND_ECC_NONE: - printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n"); - this->write_buf(mtd, this->data_poi, mtd->oobblock); - break; + nand_read_page_raw(mtd, chip, buf); - /* Software ecc 3/256, write all */ - case NAND_ECC_SOFT: - for (; eccsteps; eccsteps--) { - this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code); - for (i = 0; i < 3; i++, eccidx++) - oob_buf[oob_config[eccidx]] = ecc_code[i]; - datidx += this->eccsize; - } - this->write_buf(mtd, this->data_poi, mtd->oobblock); - break; - default: - eccbytes = this->eccbytes; - for (; eccsteps; eccsteps--) { - /* enable hardware ecc logic for write */ - this->enable_hwecc(mtd, NAND_ECC_WRITE); - this->write_buf(mtd, &this->data_poi[datidx], this->eccsize); - this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code); - for (i = 0; i < eccbytes; i++, eccidx++) - oob_buf[oob_config[eccidx]] = ecc_code[i]; - /* If the hardware ecc provides syndromes then - * the ecc code must be written immidiately after - * the data bytes (words) */ - if (this->options & NAND_HWECC_SYNDROME) - this->write_buf(mtd, ecc_code, eccbytes); - datidx += this->eccsize; - } - break; - } + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) + chip->ecc.calculate(mtd, p, &ecc_calc[i]); - /* Write out OOB data */ - if (this->options & NAND_HWECC_SYNDROME) - this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes); - else - this->write_buf(mtd, oob_buf, mtd->oobsize); + for (i = 0; i < chip->ecc.total; i++) + ecc_code[i] = chip->oob_poi[eccpos[i]]; - /* Send command to actually program the data */ - this->cmdfunc (mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1); + eccsteps = chip->ecc.steps; + p = buf; - if (!cached) { - /* call wait ready function */ - status = this->waitfunc (mtd, this, FL_WRITING); + for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + int stat; - /* See if operation failed and additional status checks are available */ - if ((status & NAND_STATUS_FAIL) && (this->errstat)) { - status = this->errstat(mtd, this, FL_WRITING, status, page); - } - - /* See if device thinks it succeeded */ - if (status & NAND_STATUS_FAIL) { - DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page); - return -EIO; - } - } else { - /* FIXME: Implement cached programming ! */ - /* wait until cache is ready*/ - // status = this->waitfunc (mtd, this, FL_CACHEDRPG); + stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + if (stat == -1) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; } return 0; } -#ifdef CONFIG_MTD_NAND_VERIFY_WRITE /** - * nand_verify_pages - [GENERIC] verify the chip contents after a write - * @mtd: MTD device structure - * @this: NAND chip structure - * @page: startpage inside the chip, must be called with (page & this->pagemask) - * @numpages: number of pages to verify - * @oob_buf: out of band data buffer - * @oobsel: out of band selecttion structre - * @chipnr: number of the current chip - * @oobmode: 1 = full buffer verify, 0 = ecc only + * nand_read_page_hwecc - {REPLACABLE] hardware ecc based page read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data * - * The NAND device assumes that it is always writing to a cleanly erased page. - * Hence, it performs its internal write verification only on bits that - * transitioned from 1 to 0. The device does NOT verify the whole page on a - * byte by byte basis. It is possible that the page was not completely erased - * or the page is becoming unusable due to wear. The read with ECC would catch - * the error later when the ECC page check fails, but we would rather catch - * it early in the page write stage. Better to write no data than invalid data. + * Not for syndrome calculating ecc controllers which need a special oob layout */ -static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, - u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode) +static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf) { - int i, j, datidx = 0, oobofs = 0, res = -EIO; - int eccsteps = this->eccsteps; - int hweccbytes; - u_char oobdata[64]; - - hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0; - - /* Send command to read back the first page */ - this->cmdfunc (mtd, NAND_CMD_READ0, 0, page); - - for(;;) { - for (j = 0; j < eccsteps; j++) { - /* Loop through and verify the data */ - if (this->verify_buf(mtd, &this->data_poi[datidx], mtd->eccsize)) { - DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); - goto out; - } - datidx += mtd->eccsize; - /* Have we a hw generator layout ? */ - if (!hweccbytes) - continue; - if (this->verify_buf(mtd, &this->oob_buf[oobofs], hweccbytes)) { - DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); - goto out; - } - oobofs += hweccbytes; - } + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint8_t *p = buf; + uint8_t *ecc_calc = chip->buffers.ecccalc; + uint8_t *ecc_code = chip->buffers.ecccode; + int *eccpos = chip->ecc.layout->eccpos; + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->read_buf(mtd, p, eccsize); + chip->ecc.calculate(mtd, p, &ecc_calc[i]); + } + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - /* check, if we must compare all data or if we just have to - * compare the ecc bytes - */ - if (oobmode) { - if (this->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) { - DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); - goto out; - } - } else { - /* Read always, else autoincrement fails */ - this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps); - - if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) { - int ecccnt = oobsel->eccbytes; - - for (i = 0; i < ecccnt; i++) { - int idx = oobsel->eccpos[i]; - if (oobdata[idx] != oob_buf[oobofs + idx] ) { - DEBUG (MTD_DEBUG_LEVEL0, - "%s: Failed ECC write " - "verify, page 0x%08x, " "%6i bytes were succesful\n", __FUNCTION__, page, i); - goto out; - } - } - } - } - oobofs += mtd->oobsize - hweccbytes * eccsteps; - page++; - numpages--; - - /* Apply delay or wait for ready/busy pin - * Do this before the AUTOINCR check, so no problems - * arise if a chip which does auto increment - * is marked as NOAUTOINCR by the board driver. - * Do this also before returning, so the chip is - * ready for the next command. - */ - if (!this->dev_ready) - udelay (this->chip_delay); - else - nand_wait_ready(mtd); + for (i = 0; i < chip->ecc.total; i++) + ecc_code[i] = chip->oob_poi[eccpos[i]]; - /* All done, return happy */ - if (!numpages) - return 0; + eccsteps = chip->ecc.steps; + p = buf; + for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + int stat; - /* Check, if the chip supports auto page increment */ - if (!NAND_CANAUTOINCR(this)) - this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); + stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + if (stat == -1) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; } - /* - * Terminate the read command. We come here in case of an error - * So we must issue a reset command. - */ -out: - this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1); - return res; + return 0; } -#endif /** - * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc - * @mtd: MTD device structure - * @from: offset to read from - * @len: number of bytes to read - * @retlen: pointer to variable to store the number of read bytes - * @buf: the databuffer to put data + * nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: buffer to store read data * - * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL - * and flags = 0xff + * The hw generator calculates the error syndrome automatically. Therefor + * we need a special oob layout and handling. */ -static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) +static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf) { - return nand_do_read_ecc (mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff); -} + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint8_t *p = buf; + uint8_t *oob = chip->oob_poi; + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + int stat; + + chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->read_buf(mtd, p, eccsize); + + if (chip->ecc.prepad) { + chip->read_buf(mtd, oob, chip->ecc.prepad); + oob += chip->ecc.prepad; + } + + chip->ecc.hwctl(mtd, NAND_ECC_READSYN); + chip->read_buf(mtd, oob, eccbytes); + stat = chip->ecc.correct(mtd, p, oob, NULL); + + if (stat == -1) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; + + oob += eccbytes; + + if (chip->ecc.postpad) { + chip->read_buf(mtd, oob, chip->ecc.postpad); + oob += chip->ecc.postpad; + } + } + + /* Calculate remaining oob bytes */ + i = mtd->oobsize - (oob - chip->oob_poi); + if (i) + chip->read_buf(mtd, oob, i); + return 0; +} /** - * nand_read_ecc - [MTD Interface] MTD compability function for nand_do_read_ecc - * @mtd: MTD device structure - * @from: offset to read from - * @len: number of bytes to read - * @retlen: pointer to variable to store the number of read bytes - * @buf: the databuffer to put data - * @oob_buf: filesystem supplied oob data buffer - * @oobsel: oob selection structure - * - * This function simply calls nand_do_read_ecc with flags = 0xff + * nand_transfer_oob - [Internal] Transfer oob to client buffer + * @chip: nand chip structure + * @ops: oob ops structure */ -static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, - size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel) +static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, + struct mtd_oob_ops *ops) { - /* use userspace supplied oobinfo, if zero */ - if (oobsel == NULL) - oobsel = &mtd->oobinfo; - return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff); + size_t len = ops->ooblen; + + switch(ops->mode) { + + case MTD_OOB_PLACE: + case MTD_OOB_RAW: + memcpy(oob, chip->oob_poi + ops->ooboffs, len); + return oob + len; + + case MTD_OOB_AUTO: { + struct nand_oobfree *free = chip->ecc.layout->oobfree; + uint32_t boffs = 0, roffs = ops->ooboffs; + size_t bytes = 0; + + for(; free->length && len; free++, len -= bytes) { + /* Read request not from offset 0 ? */ + if (unlikely(roffs)) { + if (roffs >= free->length) { + roffs -= free->length; + continue; + } + boffs = free->offset + roffs; + bytes = min_t(size_t, len, + (free->length - roffs)); + roffs = 0; + } else { + bytes = min_t(size_t, len, free->length); + boffs = free->offset; + } + memcpy(oob, chip->oob_poi + boffs, bytes); + oob += bytes; + } + return oob; + } + default: + BUG(); + } + return NULL; } - /** - * nand_do_read_ecc - [MTD Interface] Read data with ECC + * nand_do_read_ops - [Internal] Read data with ECC + * * @mtd: MTD device structure * @from: offset to read from - * @len: number of bytes to read - * @retlen: pointer to variable to store the number of read bytes - * @buf: the databuffer to put data - * @oob_buf: filesystem supplied oob data buffer (can be NULL) - * @oobsel: oob selection structure - * @flags: flag to indicate if nand_get_device/nand_release_device should be preformed - * and how many corrected error bits are acceptable: - * bits 0..7 - number of tolerable errors - * bit 8 - 0 == do not get/release chip, 1 == get/release chip * - * NAND read with ECC + * Internal function. Called with chip held. */ -int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, - size_t * retlen, u_char * buf, u_char * oob_buf, - struct nand_oobinfo *oobsel, int flags) +static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, + struct mtd_oob_ops *ops) { + int chipnr, page, realpage, col, bytes, aligned; + struct nand_chip *chip = mtd->priv; + struct mtd_ecc_stats stats; + int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; + int sndcmd = 1; + int ret = 0; + uint32_t readlen = ops->len; + uint8_t *bufpoi, *oob, *buf; - int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1; - int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0; - struct nand_chip *this = mtd->priv; - u_char *data_poi, *oob_data = oob_buf; - u_char ecc_calc[32]; - u_char ecc_code[32]; - int eccmode, eccsteps; - int *oob_config, datidx; - int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; - int eccbytes; - int compareecc = 1; - int oobreadlen; - - - DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); - - /* Do not allow reads past end of device */ - if ((from + len) > mtd->size) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n"); - *retlen = 0; - return -EINVAL; - } - - /* Grab the lock and see if the device is available */ - if (flags & NAND_GET_DEVICE) - nand_get_device (this, mtd, FL_READING); - - /* Autoplace of oob data ? Use the default placement scheme */ - if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) - oobsel = this->autooob; - - eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; - oob_config = oobsel->eccpos; - - /* Select the NAND device */ - chipnr = (int)(from >> this->chip_shift); - this->select_chip(mtd, chipnr); - - /* First we calculate the starting page */ - realpage = (int) (from >> this->page_shift); - page = realpage & this->pagemask; - - /* Get raw starting column */ - col = from & (mtd->oobblock - 1); - - end = mtd->oobblock; - ecc = this->eccsize; - eccbytes = this->eccbytes; - - if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME)) - compareecc = 0; - - oobreadlen = mtd->oobsize; - if (this->options & NAND_HWECC_SYNDROME) - oobreadlen -= oobsel->eccbytes; + stats = mtd->ecc_stats; - /* Loop until all data read */ - while (read < len) { + chipnr = (int)(from >> chip->chip_shift); + chip->select_chip(mtd, chipnr); - int aligned = (!col && (len - read) >= end); - /* - * If the read is not page aligned, we have to read into data buffer - * due to ecc, else we read into return buffer direct - */ - if (aligned) - data_poi = &buf[read]; - else - data_poi = this->data_buf; + realpage = (int)(from >> chip->page_shift); + page = realpage & chip->pagemask; - /* Check, if we have this page in the buffer - * - * FIXME: Make it work when we must provide oob data too, - * check the usage of data_buf oob field - */ - if (realpage == this->pagebuf && !oob_buf) { - /* aligned read ? */ - if (aligned) - memcpy (data_poi, this->data_buf, end); - goto readdata; - } + col = (int)(from & (mtd->writesize - 1)); + chip->oob_poi = chip->buffers.oobrbuf; - /* Check, if we must send the read command */ - if (sndcmd) { - this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); - sndcmd = 0; - } + buf = ops->datbuf; + oob = ops->oobbuf; - /* get oob area, if we have no oob buffer from fs-driver */ - if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE || - oobsel->useecc == MTD_NANDECC_AUTOPL_USR) - oob_data = &this->data_buf[end]; + while(1) { + bytes = min(mtd->writesize - col, readlen); + aligned = (bytes == mtd->writesize); - eccsteps = this->eccsteps; + /* Is the current page in the buffer ? */ + if (realpage != chip->pagebuf || oob) { + bufpoi = aligned ? buf : chip->buffers.databuf; - switch (eccmode) { - case NAND_ECC_NONE: { /* No ECC, Read in a page */ - static unsigned long lastwhinge = 0; - if ((lastwhinge / HZ) != (jiffies / HZ)) { - printk (KERN_WARNING "Reading data from NAND FLASH without ECC is not recommended\n"); - lastwhinge = jiffies; + if (likely(sndcmd)) { + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + sndcmd = 0; } - this->read_buf(mtd, data_poi, end); - break; - } - case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */ - this->read_buf(mtd, data_poi, end); - for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc) - this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); - break; + /* Now read the page into the buffer */ + ret = chip->ecc.read_page(mtd, chip, bufpoi); + if (ret < 0) + break; - default: - for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) { - this->enable_hwecc(mtd, NAND_ECC_READ); - this->read_buf(mtd, &data_poi[datidx], ecc); - - /* HW ecc with syndrome calculation must read the - * syndrome from flash immidiately after the data */ - if (!compareecc) { - /* Some hw ecc generators need to know when the - * syndrome is read from flash */ - this->enable_hwecc(mtd, NAND_ECC_READSYN); - this->read_buf(mtd, &oob_data[i], eccbytes); - /* We calc error correction directly, it checks the hw - * generator for an error, reads back the syndrome and - * does the error correction on the fly */ - ecc_status = this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]); - if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " - "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr); - ecc_failed++; - } - } else { - this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); - } + /* Transfer not aligned data */ + if (!aligned) { + chip->pagebuf = realpage; + memcpy(buf, chip->buffers.databuf + col, bytes); } - break; - } - - /* read oobdata */ - this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen); - - /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */ - if (!compareecc) - goto readoob; - - /* Pick the ECC bytes out of the oob data */ - for (j = 0; j < oobsel->eccbytes; j++) - ecc_code[j] = oob_data[oob_config[j]]; - /* correct data, if neccecary */ - for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) { - ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]); + buf += bytes; - /* Get next chunk of ecc bytes */ - j += eccbytes; - - /* Check, if we have a fs supplied oob-buffer, - * This is the legacy mode. Used by YAFFS1 - * Should go away some day - */ - if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) { - int *p = (int *)(&oob_data[mtd->oobsize]); - p[i] = ecc_status; + if (unlikely(oob)) { + /* Raw mode does data:oob:data:oob */ + if (ops->mode != MTD_OOB_RAW) + oob = nand_transfer_oob(chip, oob, ops); + else + buf = nand_transfer_oob(chip, buf, ops); } - if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page); - ecc_failed++; + if (!(chip->options & NAND_NO_READRDY)) { + /* + * Apply delay or wait for ready/busy pin. Do + * this before the AUTOINCR check, so no + * problems arise if a chip which does auto + * increment is marked as NOAUTOINCR by the + * board driver. + */ + if (!chip->dev_ready) + udelay(chip->chip_delay); + else + nand_wait_ready(mtd); } + } else { + memcpy(buf, chip->buffers.databuf + col, bytes); + buf += bytes; } - readoob: - /* check, if we have a fs supplied oob-buffer */ - if (oob_buf) { - /* without autoplace. Legacy mode used by YAFFS1 */ - switch(oobsel->useecc) { - case MTD_NANDECC_AUTOPLACE: - case MTD_NANDECC_AUTOPL_USR: - /* Walk through the autoplace chunks */ - for (i = 0; oobsel->oobfree[i][1]; i++) { - int from = oobsel->oobfree[i][0]; - int num = oobsel->oobfree[i][1]; - memcpy(&oob_buf[oob], &oob_data[from], num); - oob += num; - } - break; - case MTD_NANDECC_PLACE: - /* YAFFS1 legacy mode */ - oob_data += this->eccsteps * sizeof (int); - default: - oob_data += mtd->oobsize; - } - } - readdata: - /* Partial page read, transfer data into fs buffer */ - if (!aligned) { - for (j = col; j < end && read < len; j++) - buf[read++] = data_poi[j]; - this->pagebuf = realpage; - } else - read += mtd->oobblock; - - /* Apply delay or wait for ready/busy pin - * Do this before the AUTOINCR check, so no problems - * arise if a chip which does auto increment - * is marked as NOAUTOINCR by the board driver. - */ - if (!this->dev_ready) - udelay (this->chip_delay); - else - nand_wait_ready(mtd); + readlen -= bytes; - if (read == len) + if (!readlen) break; /* For subsequent reads align to page boundary. */ @@ -1345,701 +1037,775 @@ int nand_do_read_ecc (struct mtd_info *m /* Increment page address */ realpage++; - page = realpage & this->pagemask; + page = realpage & chip->pagemask; /* Check, if we cross a chip boundary */ if (!page) { chipnr++; - this->select_chip(mtd, -1); - this->select_chip(mtd, chipnr); + chip->select_chip(mtd, -1); + chip->select_chip(mtd, chipnr); } + /* Check, if the chip supports auto page increment * or if we have hit a block boundary. - */ - if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) + */ + if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) sndcmd = 1; } - /* Deselect and wake up anyone waiting on the device */ - if (flags & NAND_GET_DEVICE) - nand_release_device(mtd); + ops->retlen = ops->len - (size_t) readlen; - /* - * Return success, if no ECC failures, else -EBADMSG - * fs driver will take care of that, because - * retlen == desired len and result == -EBADMSG - */ - *retlen = read; - return ecc_failed ? -EBADMSG : 0; + if (ret) + return ret; + + if (mtd->ecc_stats.failed - stats.failed) + return -EBADMSG; + + return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; } /** - * nand_read_oob - [MTD Interface] NAND read out-of-band + * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc * @mtd: MTD device structure * @from: offset to read from * @len: number of bytes to read * @retlen: pointer to variable to store the number of read bytes * @buf: the databuffer to put data * - * NAND read out-of-band data from the spare area + * Get hold of the chip and call nand_do_read */ -static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) +static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, uint8_t *buf) { - int i, col, page, chipnr; - struct nand_chip *this = mtd->priv; - int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; + struct nand_chip *chip = mtd->priv; + int ret; - DEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); + /* Do not allow reads past end of device */ + if ((from + len) > mtd->size) + return -EINVAL; + if (!len) + return 0; - /* Shift to get page */ - page = (int)(from >> this->page_shift); - chipnr = (int)(from >> this->chip_shift); + nand_get_device(chip, mtd, FL_READING); - /* Mask to get column */ - col = from & (mtd->oobsize - 1); + chip->ops.len = len; + chip->ops.datbuf = buf; + chip->ops.oobbuf = NULL; - /* Initialize return length value */ - *retlen = 0; + ret = nand_do_read_ops(mtd, from, &chip->ops); - /* Do not allow reads past end of device */ - if ((from + len) > mtd->size) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n"); - *retlen = 0; - return -EINVAL; + nand_release_device(mtd); + + *retlen = chip->ops.retlen; + return ret; +} + +/** + * nand_read_oob_std - [REPLACABLE] the most common OOB data read function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to read + * @sndcmd: flag whether to issue read command or not + */ +static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, + int page, int sndcmd) +{ + if (sndcmd) { + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + sndcmd = 0; } + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + return sndcmd; +} - /* Grab the lock and see if the device is available */ - nand_get_device (this, mtd , FL_READING); +/** + * nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC + * with syndromes + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to read + * @sndcmd: flag whether to issue read command or not + */ +static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, + int page, int sndcmd) +{ + uint8_t *buf = chip->oob_poi; + int length = mtd->oobsize; + int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; + int eccsize = chip->ecc.size; + uint8_t *bufpoi = buf; + int i, toread, sndrnd = 0, pos; + + chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page); + for (i = 0; i < chip->ecc.steps; i++) { + if (sndrnd) { + pos = eccsize + i * (eccsize + chunk); + if (mtd->writesize > 512) + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, pos, -1); + else + chip->cmdfunc(mtd, NAND_CMD_READ0, pos, page); + } else + sndrnd = 1; + toread = min_t(int, length, chunk); + chip->read_buf(mtd, bufpoi, toread); + bufpoi += toread; + length -= toread; + } + if (length > 0) + chip->read_buf(mtd, bufpoi, length); - /* Select the NAND device */ - this->select_chip(mtd, chipnr); + return 1; +} + +/** + * nand_write_oob_std - [REPLACABLE] the most common OOB data write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to write + */ +static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, + int page) +{ + int status = 0; + const uint8_t *buf = chip->oob_poi; + int length = mtd->oobsize; + + chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page); + chip->write_buf(mtd, buf, length); + /* Send command to program the OOB data */ + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + + status = chip->waitfunc(mtd, chip); + + return status; +} + +/** + * nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC + * with syndrome - only for large page flash ! + * @mtd: mtd info structure + * @chip: nand chip info structure + * @page: page number to write + */ +static int nand_write_oob_syndrome(struct mtd_info *mtd, + struct nand_chip *chip, int page) +{ + int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; + int eccsize = chip->ecc.size, length = mtd->oobsize; + int i, len, pos, status = 0, sndcmd = 0, steps = chip->ecc.steps; + const uint8_t *bufpoi = chip->oob_poi; - /* Send the read command */ - this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask); /* - * Read the data, if we read more than one page - * oob data, let the device transfer the data ! + * data-ecc-data-ecc ... ecc-oob + * or + * data-pad-ecc-pad-data-pad .... ecc-pad-oob */ - i = 0; - while (i < len) { - int thislen = mtd->oobsize - col; - thislen = min_t(int, thislen, len); - this->read_buf(mtd, &buf[i], thislen); - i += thislen; - - /* Read more ? */ - if (i < len) { - page++; - col = 0; - - /* Check, if we cross a chip boundary */ - if (!(page & this->pagemask)) { - chipnr++; - this->select_chip(mtd, -1); - this->select_chip(mtd, chipnr); - } - - /* Apply delay or wait for ready/busy pin - * Do this before the AUTOINCR check, so no problems - * arise if a chip which does auto increment - * is marked as NOAUTOINCR by the board driver. - */ - if (!this->dev_ready) - udelay (this->chip_delay); - else - nand_wait_ready(mtd); + if (!chip->ecc.prepad && !chip->ecc.postpad) { + pos = steps * (eccsize + chunk); + steps = 0; + } else + pos = eccsize + chunk; - /* Check, if the chip supports auto page increment - * or if we have hit a block boundary. - */ - if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) { - /* For subsequent page reads set offset to 0 */ - this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask); + chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page); + for (i = 0; i < steps; i++) { + if (sndcmd) { + if (mtd->writesize <= 512) { + uint32_t fill = 0xFFFFFFFF; + + len = eccsize; + while (len > 0) { + int num = min_t(int, len, 4); + chip->write_buf(mtd, (uint8_t *)&fill, + num); + len -= num; + } + } else { + pos = eccsize + i * (eccsize + chunk); + chip->cmdfunc(mtd, NAND_CMD_RNDIN, pos, -1); } - } + } else + sndcmd = 1; + len = min_t(int, length, chunk); + chip->write_buf(mtd, bufpoi, len); + bufpoi += len; + length -= len; } + if (length > 0) + chip->write_buf(mtd, bufpoi, length); - /* Deselect and wake up anyone waiting on the device */ - nand_release_device(mtd); + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + status = chip->waitfunc(mtd, chip); - /* Return happy */ - *retlen = len; - return 0; + return status & NAND_STATUS_FAIL ? -EIO : 0; } /** - * nand_read_raw - [GENERIC] Read raw data including oob into buffer + * nand_do_read_oob - [Intern] NAND read out-of-band * @mtd: MTD device structure - * @buf: temporary buffer * @from: offset to read from - * @len: number of bytes to read - * @ooblen: number of oob data bytes to read + * @ops: oob operations description structure * - * Read raw data including oob into buffer + * NAND read out-of-band data from the spare area */ -int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen) +static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, + struct mtd_oob_ops *ops) { - struct nand_chip *this = mtd->priv; - int page = (int) (from >> this->page_shift); - int chip = (int) (from >> this->chip_shift); - int sndcmd = 1; - int cnt = 0; - int pagesize = mtd->oobblock + mtd->oobsize; - int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; + int page, realpage, chipnr, sndcmd = 1; + struct nand_chip *chip = mtd->priv; + int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; + int readlen = ops->len; + uint8_t *buf = ops->oobbuf; - /* Do not allow reads past end of device */ - if ((from + len) > mtd->size) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt read beyond end of device\n"); - return -EINVAL; - } + DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n", + (unsigned long long)from, readlen); - /* Grab the lock and see if the device is available */ - nand_get_device (this, mtd , FL_READING); + chipnr = (int)(from >> chip->chip_shift); + chip->select_chip(mtd, chipnr); - this->select_chip (mtd, chip); + /* Shift to get page */ + realpage = (int)(from >> chip->page_shift); + page = realpage & chip->pagemask; - /* Add requested oob length */ - len += ooblen; + chip->oob_poi = chip->buffers.oobrbuf; - while (len) { - if (sndcmd) - this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask); - sndcmd = 0; + while(1) { + sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); + buf = nand_transfer_oob(chip, buf, ops); - this->read_buf (mtd, &buf[cnt], pagesize); + readlen -= ops->ooblen; + if (!readlen) + break; - len -= pagesize; - cnt += pagesize; - page++; + if (!(chip->options & NAND_NO_READRDY)) { + /* + * Apply delay or wait for ready/busy pin. Do this + * before the AUTOINCR check, so no problems arise if a + * chip which does auto increment is marked as + * NOAUTOINCR by the board driver. + */ + if (!chip->dev_ready) + udelay(chip->chip_delay); + else + nand_wait_ready(mtd); + } - if (!this->dev_ready) - udelay (this->chip_delay); - else - nand_wait_ready(mtd); + /* Increment page address */ + realpage++; - /* Check, if the chip supports auto page increment */ - if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) + page = realpage & chip->pagemask; + /* Check, if we cross a chip boundary */ + if (!page) { + chipnr++; + chip->select_chip(mtd, -1); + chip->select_chip(mtd, chipnr); + } + + /* Check, if the chip supports auto page increment + * or if we have hit a block boundary. + */ + if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) sndcmd = 1; } - /* Deselect and wake up anyone waiting on the device */ - nand_release_device(mtd); + ops->retlen = ops->len; return 0; } - /** - * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer + * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band * @mtd: MTD device structure - * @fsbuf: buffer given by fs driver - * @oobsel: out of band selection structre - * @autoplace: 1 = place given buffer into the oob bytes - * @numpages: number of pages to prepare - * - * Return: - * 1. Filesystem buffer available and autoplacement is off, - * return filesystem buffer - * 2. No filesystem buffer or autoplace is off, return internal - * buffer - * 3. Filesystem buffer is given and autoplace selected - * put data from fs buffer into internal buffer and - * retrun internal buffer - * - * Note: The internal buffer is filled with 0xff. This must - * be done only once, when no autoplacement happens - * Autoplacement sets the buffer dirty flag, which - * forces the 0xff fill before using the buffer again. + * @from: offset to read from + * @ops: oob operation description structure * -*/ -static u_char * nand_prepare_oobbuf (struct mtd_info *mtd, u_char *fsbuf, struct nand_oobinfo *oobsel, - int autoplace, int numpages) + * NAND read data and/or out-of-band data + */ +static int nand_read_oob(struct mtd_info *mtd, loff_t from, + struct mtd_oob_ops *ops) { - struct nand_chip *this = mtd->priv; - int i, len, ofs; - - /* Zero copy fs supplied buffer */ - if (fsbuf && !autoplace) - return fsbuf; - - /* Check, if the buffer must be filled with ff again */ - if (this->oobdirty) { - memset (this->oob_buf, 0xff, - mtd->oobsize << (this->phys_erase_shift - this->page_shift)); - this->oobdirty = 0; + int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf) = NULL; + struct nand_chip *chip = mtd->priv; + int ret = -ENOTSUPP; + + ops->retlen = 0; + + /* Do not allow reads past end of device */ + if ((from + ops->len) > mtd->size) { + DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " + "Attempt read beyond end of device\n"); + return -EINVAL; } - /* If we have no autoplacement or no fs buffer use the internal one */ - if (!autoplace || !fsbuf) - return this->oob_buf; - - /* Walk through the pages and place the data */ - this->oobdirty = 1; - ofs = 0; - while (numpages--) { - for (i = 0, len = 0; len < mtd->oobavail; i++) { - int to = ofs + oobsel->oobfree[i][0]; - int num = oobsel->oobfree[i][1]; - memcpy (&this->oob_buf[to], fsbuf, num); - len += num; - fsbuf += num; - } - ofs += mtd->oobavail; + nand_get_device(chip, mtd, FL_READING); + + switch(ops->mode) { + case MTD_OOB_PLACE: + case MTD_OOB_AUTO: + break; + + case MTD_OOB_RAW: + /* Replace the read_page algorithm temporary */ + read_page = chip->ecc.read_page; + chip->ecc.read_page = nand_read_page_raw; + break; + + default: + goto out; } - return this->oob_buf; + + if (!ops->datbuf) + ret = nand_do_read_oob(mtd, from, ops); + else + ret = nand_do_read_ops(mtd, from, ops); + + if (unlikely(ops->mode == MTD_OOB_RAW)) + chip->ecc.read_page = read_page; + out: + nand_release_device(mtd); + return ret; } -#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0 /** - * nand_write - [MTD Interface] compability function for nand_write_ecc - * @mtd: MTD device structure - * @to: offset to write to - * @len: number of bytes to write - * @retlen: pointer to variable to store the number of written bytes - * @buf: the data to write - * - * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL - * -*/ -static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf) + * nand_write_page_raw - [Intern] raw page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + */ +static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf) { - return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL)); + chip->write_buf(mtd, buf, mtd->writesize); + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); } /** - * nand_write_ecc - [MTD Interface] NAND write with ECC - * @mtd: MTD device structure - * @to: offset to write to - * @len: number of bytes to write - * @retlen: pointer to variable to store the number of written bytes - * @buf: the data to write - * @eccbuf: filesystem supplied oob data buffer - * @oobsel: oob selection structure - * - * NAND write with ECC + * nand_write_page_swecc - {REPLACABLE] software ecc based page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer */ -static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, - size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel) +static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf) { - int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr; - int autoplace = 0, numpages, totalpages; - struct nand_chip *this = mtd->priv; - u_char *oobbuf, *bufstart; - int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint8_t *ecc_calc = chip->buffers.ecccalc; + const uint8_t *p = buf; + int *eccpos = chip->ecc.layout->eccpos; - DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); + /* Software ecc calculation */ + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) + chip->ecc.calculate(mtd, p, &ecc_calc[i]); - /* Initialize retlen, in case of early exit */ - *retlen = 0; + for (i = 0; i < chip->ecc.total; i++) + chip->oob_poi[eccpos[i]] = ecc_calc[i]; - /* Do not allow write past end of device */ - if ((to + len) > mtd->size) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n"); - return -EINVAL; - } + nand_write_page_raw(mtd, chip, buf); +} - /* reject writes, which are not page aligned */ - if (NOTALIGNED (to) || NOTALIGNED(len)) { - printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); - return -EINVAL; +/** + * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + */ +static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint8_t *ecc_calc = chip->buffers.ecccalc; + const uint8_t *p = buf; + int *eccpos = chip->ecc.layout->eccpos; + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + chip->write_buf(mtd, p, eccsize); + chip->ecc.calculate(mtd, p, &ecc_calc[i]); } - /* Grab the lock and see if the device is available */ - nand_get_device (this, mtd, FL_WRITING); + for (i = 0; i < chip->ecc.total; i++) + chip->oob_poi[eccpos[i]] = ecc_calc[i]; - /* Calculate chipnr */ - chipnr = (int)(to >> this->chip_shift); - /* Select the NAND device */ - this->select_chip(mtd, chipnr); + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); +} - /* Check, if it is write protected */ - if (nand_check_wp(mtd)) - goto out; +/** + * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write + * @mtd: mtd info structure + * @chip: nand chip info structure + * @buf: data buffer + * + * The hw generator calculates the error syndrome automatically. Therefor + * we need a special oob layout and handling. + */ +static void nand_write_page_syndrome(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + const uint8_t *p = buf; + uint8_t *oob = chip->oob_poi; - /* if oobsel is NULL, use chip defaults */ - if (oobsel == NULL) - oobsel = &mtd->oobinfo; + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - /* Autoplace of oob data ? Use the default placement scheme */ - if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { - oobsel = this->autooob; - autoplace = 1; - } - if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) - autoplace = 1; + chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + chip->write_buf(mtd, p, eccsize); - /* Setup variables and oob buffer */ - totalpages = len >> this->page_shift; - page = (int) (to >> this->page_shift); - /* Invalidate the page cache, if we write to the cached page */ - if (page <= this->pagebuf && this->pagebuf < (page + totalpages)) - this->pagebuf = -1; - - /* Set it relative to chip */ - page &= this->pagemask; - startpage = page; - /* Calc number of pages we can write in one go */ - numpages = min (ppblock - (startpage & (ppblock - 1)), totalpages); - oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, autoplace, numpages); - bufstart = (u_char *)buf; - - /* Loop until all data is written */ - while (written < len) { - - this->data_poi = (u_char*) &buf[written]; - /* Write one page. If this is the last page to write - * or the last page in this block, then use the - * real pageprogram command, else select cached programming - * if supported by the chip. - */ - ret = nand_write_page (mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0)); - if (ret) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret); - goto out; + if (chip->ecc.prepad) { + chip->write_buf(mtd, oob, chip->ecc.prepad); + oob += chip->ecc.prepad; } - /* Next oob page */ - oob += mtd->oobsize; - /* Update written bytes count */ - written += mtd->oobblock; - if (written == len) - goto cmp; - /* Increment page address */ - page++; - - /* Have we hit a block boundary ? Then we have to verify and - * if verify is ok, we have to setup the oob buffer for - * the next pages. - */ - if (!(page & (ppblock - 1))){ - int ofs; - this->data_poi = bufstart; - ret = nand_verify_pages (mtd, this, startpage, - page - startpage, - oobbuf, oobsel, chipnr, (eccbuf != NULL)); - if (ret) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); - goto out; - } - *retlen = written; - - ofs = autoplace ? mtd->oobavail : mtd->oobsize; - if (eccbuf) - eccbuf += (page - startpage) * ofs; - totalpages -= page - startpage; - numpages = min (totalpages, ppblock); - page &= this->pagemask; - startpage = page; - oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, - autoplace, numpages); - oob = 0; - /* Check, if we cross a chip boundary */ - if (!page) { - chipnr++; - this->select_chip(mtd, -1); - this->select_chip(mtd, chipnr); - } + chip->ecc.calculate(mtd, p, oob); + chip->write_buf(mtd, oob, eccbytes); + oob += eccbytes; + + if (chip->ecc.postpad) { + chip->write_buf(mtd, oob, chip->ecc.postpad); + oob += chip->ecc.postpad; } } - /* Verify the remaining pages */ -cmp: - this->data_poi = bufstart; - ret = nand_verify_pages (mtd, this, startpage, totalpages, - oobbuf, oobsel, chipnr, (eccbuf != NULL)); - if (!ret) - *retlen = written; - else - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); -out: - /* Deselect and wake up anyone waiting on the device */ - nand_release_device(mtd); - - return ret; + /* Calculate remaining oob bytes */ + i = mtd->oobsize - (oob - chip->oob_poi); + if (i) + chip->write_buf(mtd, oob, i); } - /** - * nand_write_oob - [MTD Interface] NAND write out-of-band + * nand_write_page - [INTERNAL] write one page * @mtd: MTD device structure - * @to: offset to write to - * @len: number of bytes to write - * @retlen: pointer to variable to store the number of written bytes + * @chip: NAND chip descriptor * @buf: the data to write - * - * NAND write out-of-band + * @page: page number to write + * @cached: cached programming */ -static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf) +static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf, int page, int cached) { - int column, page, status, ret = -EIO, chipnr; - struct nand_chip *this = mtd->priv; + int status; - DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); + chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); - /* Shift to get page */ - page = (int) (to >> this->page_shift); - chipnr = (int) (to >> this->chip_shift); + chip->ecc.write_page(mtd, chip, buf); - /* Mask to get column */ - column = to & (mtd->oobsize - 1); + /* + * Cached progamming disabled for now, Not sure if its worth the + * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s) + */ + cached = 0; - /* Initialize return length value */ - *retlen = 0; + if (!cached || !(chip->options & NAND_CACHEPRG)) { - /* Do not allow write past end of page */ - if ((column + len) > mtd->oobsize) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n"); - return -EINVAL; + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + status = chip->waitfunc(mtd, chip); + /* + * See if operation failed and additional status checks are + * available + */ + if ((status & NAND_STATUS_FAIL) && (chip->errstat)) + status = chip->errstat(mtd, chip, FL_WRITING, status, + page); + + if (status & NAND_STATUS_FAIL) + return -EIO; + } else { + chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1); + status = chip->waitfunc(mtd, chip); } - /* Grab the lock and see if the device is available */ - nand_get_device (this, mtd, FL_WRITING); +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE + /* Send command to read back the data */ + chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); - /* Select the NAND device */ - this->select_chip(mtd, chipnr); + if (chip->verify_buf(mtd, buf, mtd->writesize)) + return -EIO; +#endif + return 0; +} + +/** + * nand_fill_oob - [Internal] Transfer client buffer to oob + * @chip: nand chip structure + * @oob: oob data buffer + * @ops: oob ops structure + */ +static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, + struct mtd_oob_ops *ops) +{ + size_t len = ops->ooblen; + + switch(ops->mode) { + + case MTD_OOB_PLACE: + case MTD_OOB_RAW: + memcpy(chip->oob_poi + ops->ooboffs, oob, len); + return oob + len; + + case MTD_OOB_AUTO: { + struct nand_oobfree *free = chip->ecc.layout->oobfree; + uint32_t boffs = 0, woffs = ops->ooboffs; + size_t bytes = 0; + + for(; free->length && len; free++, len -= bytes) { + /* Write request not from offset 0 ? */ + if (unlikely(woffs)) { + if (woffs >= free->length) { + woffs -= free->length; + continue; + } + boffs = free->offset + woffs; + bytes = min_t(size_t, len, + (free->length - woffs)); + woffs = 0; + } else { + bytes = min_t(size_t, len, free->length); + boffs = free->offset; + } + memcpy(chip->oob_poi + woffs, oob, bytes); + oob += bytes; + } + return oob; + } + default: + BUG(); + } + return NULL; +} + +#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 + +/** + * nand_do_write_ops - [Internal] NAND write with ECC + * @mtd: MTD device structure + * @to: offset to write to + * @ops: oob operations description structure + * + * NAND write with ECC + */ +static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops) +{ + int chipnr, realpage, page, blockmask; + struct nand_chip *chip = mtd->priv; + uint32_t writelen = ops->len; + uint8_t *oob = ops->oobbuf; + uint8_t *buf = ops->datbuf; + int bytes = mtd->writesize; + int ret; - /* Reset the chip. Some chips (like the Toshiba TC5832DC found - in one of my DiskOnChip 2000 test units) will clear the whole - data page too if we don't do this. I have no clue why, but - I seem to have 'fixed' it in the doc2000 driver in - August 1999. dwmw2. */ - this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); + ops->retlen = 0; + + /* reject writes, which are not page aligned */ + if (NOTALIGNED(to) || NOTALIGNED(ops->len)) { + printk(KERN_NOTICE "nand_write: " + "Attempt to write not page aligned data\n"); + return -EINVAL; + } + + if (!writelen) + return 0; /* Check, if it is write protected */ if (nand_check_wp(mtd)) - goto out; + return -EIO; - /* Invalidate the page cache, if we write to the cached page */ - if (page == this->pagebuf) - this->pagebuf = -1; - - if (NAND_MUST_PAD(this)) { - /* Write out desired data */ - this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page & this->pagemask); - /* prepad 0xff for partial programming */ - this->write_buf(mtd, ffchars, column); - /* write data */ - this->write_buf(mtd, buf, len); - /* postpad 0xff for partial programming */ - this->write_buf(mtd, ffchars, mtd->oobsize - (len+column)); - } else { - /* Write out desired data */ - this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock + column, page & this->pagemask); - /* write data */ - this->write_buf(mtd, buf, len); - } - /* Send command to program the OOB data */ - this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1); + chipnr = (int)(to >> chip->chip_shift); + chip->select_chip(mtd, chipnr); - status = this->waitfunc (mtd, this, FL_WRITING); + realpage = (int)(to >> chip->page_shift); + page = realpage & chip->pagemask; + blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; - /* See if device thinks it succeeded */ - if (status & NAND_STATUS_FAIL) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page); - ret = -EIO; - goto out; - } - /* Return happy */ - *retlen = len; + /* Invalidate the page cache, when we write to the cached page */ + if (to <= (chip->pagebuf << chip->page_shift) && + (chip->pagebuf << chip->page_shift) < (to + ops->len)) + chip->pagebuf = -1; -#ifdef CONFIG_MTD_NAND_VERIFY_WRITE - /* Send command to read back the data */ - this->cmdfunc (mtd, NAND_CMD_READOOB, column, page & this->pagemask); + chip->oob_poi = chip->buffers.oobwbuf; - if (this->verify_buf(mtd, buf, len)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page); - ret = -EIO; - goto out; + while(1) { + int cached = writelen > bytes && page != blockmask; + + if (unlikely(oob)) + oob = nand_fill_oob(chip, oob, ops); + + ret = nand_write_page(mtd, chip, buf, page, cached); + if (ret) + break; + + writelen -= bytes; + if (!writelen) + break; + + buf += bytes; + realpage++; + + page = realpage & chip->pagemask; + /* Check, if we cross a chip boundary */ + if (!page) { + chipnr++; + chip->select_chip(mtd, -1); + chip->select_chip(mtd, chipnr); + } } -#endif - ret = 0; -out: - /* Deselect and wake up anyone waiting on the device */ - nand_release_device(mtd); + if (unlikely(oob)) + memset(chip->oob_poi, 0xff, mtd->oobsize); + + ops->retlen = ops->len - writelen; return ret; } - /** - * nand_writev - [MTD Interface] compabilty function for nand_writev_ecc + * nand_write - [MTD Interface] NAND write with ECC * @mtd: MTD device structure - * @vecs: the iovectors to write - * @count: number of vectors * @to: offset to write to + * @len: number of bytes to write * @retlen: pointer to variable to store the number of written bytes + * @buf: the data to write * - * NAND write with kvec. This just calls the ecc function + * NAND write with ECC */ -static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, - loff_t to, size_t * retlen) +static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const uint8_t *buf) { - return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL)); + struct nand_chip *chip = mtd->priv; + int ret; + + /* Do not allow reads past end of device */ + if ((to + len) > mtd->size) + return -EINVAL; + if (!len) + return 0; + + nand_get_device(chip, mtd, FL_WRITING); + + chip->ops.len = len; + chip->ops.datbuf = (uint8_t *)buf; + chip->ops.oobbuf = NULL; + + ret = nand_do_write_ops(mtd, to, &chip->ops); + + nand_release_device(mtd); + + *retlen = chip->ops.retlen; + return ret; } /** - * nand_writev_ecc - [MTD Interface] write with iovec with ecc + * nand_do_write_oob - [MTD Interface] NAND write out-of-band * @mtd: MTD device structure - * @vecs: the iovectors to write - * @count: number of vectors * @to: offset to write to - * @retlen: pointer to variable to store the number of written bytes - * @eccbuf: filesystem supplied oob data buffer - * @oobsel: oob selection structure + * @ops: oob operation description structure * - * NAND write with iovec with ecc + * NAND write out-of-band */ -static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, - loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) +static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops) { - int i, page, len, total_len, ret = -EIO, written = 0, chipnr; - int oob, numpages, autoplace = 0, startpage; - struct nand_chip *this = mtd->priv; - int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); - u_char *oobbuf, *bufstart; - - /* Preset written len for early exit */ - *retlen = 0; - - /* Calculate total length of data */ - total_len = 0; - for (i = 0; i < count; i++) - total_len += (int) vecs[i].iov_len; + int chipnr, page, status; + struct nand_chip *chip = mtd->priv; - DEBUG (MTD_DEBUG_LEVEL3, - "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count); + DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", + (unsigned int)to, (int)ops->len); /* Do not allow write past end of page */ - if ((to + total_len) > mtd->size) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_writev: Attempted write past end of device\n"); + if ((ops->ooboffs + ops->len) > mtd->oobsize) { + DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " + "Attempt to write past end of page\n"); return -EINVAL; } - /* reject writes, which are not page aligned */ - if (NOTALIGNED (to) || NOTALIGNED(total_len)) { - printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); - return -EINVAL; - } + chipnr = (int)(to >> chip->chip_shift); + chip->select_chip(mtd, chipnr); - /* Grab the lock and see if the device is available */ - nand_get_device (this, mtd, FL_WRITING); + /* Shift to get page */ + page = (int)(to >> chip->page_shift); - /* Get the current chip-nr */ - chipnr = (int) (to >> this->chip_shift); - /* Select the NAND device */ - this->select_chip(mtd, chipnr); + /* + * Reset the chip. Some chips (like the Toshiba TC5832DC found in one + * of my DiskOnChip 2000 test units) will clear the whole data page too + * if we don't do this. I have no clue why, but I seem to have 'fixed' + * it in the doc2000 driver in August 1999. dwmw2. + */ + chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); /* Check, if it is write protected */ if (nand_check_wp(mtd)) - goto out; + return -EROFS; - /* if oobsel is NULL, use chip defaults */ - if (oobsel == NULL) - oobsel = &mtd->oobinfo; + /* Invalidate the page cache, if we write to the cached page */ + if (page == chip->pagebuf) + chip->pagebuf = -1; - /* Autoplace of oob data ? Use the default placement scheme */ - if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { - oobsel = this->autooob; - autoplace = 1; - } - if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR) - autoplace = 1; + chip->oob_poi = chip->buffers.oobwbuf; + memset(chip->oob_poi, 0xff, mtd->oobsize); + nand_fill_oob(chip, ops->oobbuf, ops); + status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); + memset(chip->oob_poi, 0xff, mtd->oobsize); - /* Setup start page */ - page = (int) (to >> this->page_shift); - /* Invalidate the page cache, if we write to the cached page */ - if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift)) - this->pagebuf = -1; + if (status) + return status; - startpage = page & this->pagemask; + ops->retlen = ops->len; - /* Loop until all kvec' data has been written */ - len = 0; - while (count) { - /* If the given tuple is >= pagesize then - * write it out from the iov - */ - if ((vecs->iov_len - len) >= mtd->oobblock) { - /* Calc number of pages we can write - * out of this iov in one go */ - numpages = (vecs->iov_len - len) >> this->page_shift; - /* Do not cross block boundaries */ - numpages = min (ppblock - (startpage & (ppblock - 1)), numpages); - oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages); - bufstart = (u_char *)vecs->iov_base; - bufstart += len; - this->data_poi = bufstart; - oob = 0; - for (i = 1; i <= numpages; i++) { - /* Write one page. If this is the last page to write - * then use the real pageprogram command, else select - * cached programming if supported by the chip. - */ - ret = nand_write_page (mtd, this, page & this->pagemask, - &oobbuf[oob], oobsel, i != numpages); - if (ret) - goto out; - this->data_poi += mtd->oobblock; - len += mtd->oobblock; - oob += mtd->oobsize; - page++; - } - /* Check, if we have to switch to the next tuple */ - if (len >= (int) vecs->iov_len) { - vecs++; - len = 0; - count--; - } - } else { - /* We must use the internal buffer, read data out of each - * tuple until we have a full page to write - */ - int cnt = 0; - while (cnt < mtd->oobblock) { - if (vecs->iov_base != NULL && vecs->iov_len) - this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++]; - /* Check, if we have to switch to the next tuple */ - if (len >= (int) vecs->iov_len) { - vecs++; - len = 0; - count--; - } - } - this->pagebuf = page; - this->data_poi = this->data_buf; - bufstart = this->data_poi; - numpages = 1; - oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages); - ret = nand_write_page (mtd, this, page & this->pagemask, - oobbuf, oobsel, 0); - if (ret) - goto out; - page++; - } + return 0; +} - this->data_poi = bufstart; - ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0); - if (ret) - goto out; +/** + * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band + * @mtd: MTD device structure + * @from: offset to read from + * @ops: oob operation description structure + */ +static int nand_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops) +{ + void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, + const uint8_t *buf) = NULL; + struct nand_chip *chip = mtd->priv; + int ret = -ENOTSUPP; - written += mtd->oobblock * numpages; - /* All done ? */ - if (!count) - break; + ops->retlen = 0; - startpage = page & this->pagemask; - /* Check, if we cross a chip boundary */ - if (!startpage) { - chipnr++; - this->select_chip(mtd, -1); - this->select_chip(mtd, chipnr); - } + /* Do not allow writes past end of device */ + if ((to + ops->len) > mtd->size) { + DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " + "Attempt read beyond end of device\n"); + return -EINVAL; } - ret = 0; -out: - /* Deselect and wake up anyone waiting on the device */ - nand_release_device(mtd); - *retlen = written; + nand_get_device(chip, mtd, FL_WRITING); + + switch(ops->mode) { + case MTD_OOB_PLACE: + case MTD_OOB_AUTO: + break; + + case MTD_OOB_RAW: + /* Replace the write_page algorithm temporary */ + write_page = chip->ecc.write_page; + chip->ecc.write_page = nand_write_page_raw; + break; + + default: + goto out; + } + + if (!ops->datbuf) + ret = nand_do_write_oob(mtd, to, ops); + else + ret = nand_do_write_ops(mtd, to, ops); + + if (unlikely(ops->mode == MTD_OOB_RAW)) + chip->ecc.write_page = write_page; + out: + nand_release_device(mtd); return ret; } @@ -2050,12 +1816,12 @@ out: * * Standard erase command for NAND chips */ -static void single_erase_cmd (struct mtd_info *mtd, int page) +static void single_erase_cmd(struct mtd_info *mtd, int page) { - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; /* Send commands to erase a block */ - this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page); - this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1); + chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); + chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); } /** @@ -2066,15 +1832,15 @@ static void single_erase_cmd (struct mtd * AND multi block erase command function * Erase 4 consecutive blocks */ -static void multi_erase_cmd (struct mtd_info *mtd, int page) +static void multi_erase_cmd(struct mtd_info *mtd, int page) { - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; /* Send commands to erase a block */ - this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++); - this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++); - this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++); - this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page); - this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1); + chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++); + chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++); + chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++); + chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); + chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); } /** @@ -2084,79 +1850,82 @@ static void multi_erase_cmd (struct mtd_ * * Erase one ore more blocks */ -static int nand_erase (struct mtd_info *mtd, struct erase_info *instr) +static int nand_erase(struct mtd_info *mtd, struct erase_info *instr) { - return nand_erase_nand (mtd, instr, 0); + return nand_erase_nand(mtd, instr, 0); } #define BBT_PAGE_MASK 0xffffff3f /** - * nand_erase_intern - [NAND Interface] erase block(s) + * nand_erase_nand - [Internal] erase block(s) * @mtd: MTD device structure * @instr: erase instruction * @allowbbt: allow erasing the bbt area * * Erase one ore more blocks */ -int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt) +int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, + int allowbbt) { int page, len, status, pages_per_block, ret, chipnr; - struct nand_chip *this = mtd->priv; - int rewrite_bbt[NAND_MAX_CHIPS]={0}; /* flags to indicate the page, if bbt needs to be rewritten. */ - unsigned int bbt_masked_page; /* bbt mask to compare to page being erased. */ - /* It is used to see if the current page is in the same */ - /* 256 block group and the same bank as the bbt. */ + struct nand_chip *chip = mtd->priv; + int rewrite_bbt[NAND_MAX_CHIPS]={0}; + unsigned int bbt_masked_page = 0xffffffff; - DEBUG (MTD_DEBUG_LEVEL3, - "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len); + DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n", + (unsigned int)instr->addr, (unsigned int)instr->len); /* Start address must align on block boundary */ - if (instr->addr & ((1 << this->phys_erase_shift) - 1)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n"); + if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) { + DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n"); return -EINVAL; } /* Length must align on block boundary */ - if (instr->len & ((1 << this->phys_erase_shift) - 1)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n"); + if (instr->len & ((1 << chip->phys_erase_shift) - 1)) { + DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: " + "Length not block aligned\n"); return -EINVAL; } /* Do not allow erase past end of device */ if ((instr->len + instr->addr) > mtd->size) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n"); + DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: " + "Erase past end of device\n"); return -EINVAL; } instr->fail_addr = 0xffffffff; /* Grab the lock and see if the device is available */ - nand_get_device (this, mtd, FL_ERASING); + nand_get_device(chip, mtd, FL_ERASING); /* Shift to get first page */ - page = (int) (instr->addr >> this->page_shift); - chipnr = (int) (instr->addr >> this->chip_shift); + page = (int)(instr->addr >> chip->page_shift); + chipnr = (int)(instr->addr >> chip->chip_shift); /* Calculate pages in each block */ - pages_per_block = 1 << (this->phys_erase_shift - this->page_shift); + pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); /* Select the NAND device */ - this->select_chip(mtd, chipnr); + chip->select_chip(mtd, chipnr); - /* Check the WP bit */ /* Check, if it is write protected */ if (nand_check_wp(mtd)) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n"); + DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: " + "Device is write protected!!!\n"); instr->state = MTD_ERASE_FAILED; goto erase_exit; } - /* if BBT requires refresh, set the BBT page mask to see if the BBT should be rewritten */ - if (this->options & BBT_AUTO_REFRESH) { - bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK; - } else { - bbt_masked_page = 0xffffffff; /* should not match anything */ - } + /* + * If BBT requires refresh, set the BBT page mask to see if the BBT + * should be rewritten. Otherwise the mask is set to 0xffffffff which + * can not be matched. This is also done when the bbt is actually + * erased to avoid recusrsive updates + */ + if (chip->options & BBT_AUTO_REFRESH && !allowbbt) + bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK; /* Loop through the pages */ len = instr->len; @@ -2164,64 +1933,77 @@ int nand_erase_nand (struct mtd_info *mt instr->state = MTD_ERASING; while (len) { - /* Check if we have a bad block, we do not erase bad blocks ! */ - if (nand_block_checkbad(mtd, ((loff_t) page) << this->page_shift, 0, allowbbt)) { - printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page); + /* + * heck if we have a bad block, we do not erase bad blocks ! + */ + if (nand_block_checkbad(mtd, ((loff_t) page) << + chip->page_shift, 0, allowbbt)) { + printk(KERN_WARNING "nand_erase: attempt to erase a " + "bad block at page 0x%08x\n", page); instr->state = MTD_ERASE_FAILED; goto erase_exit; } - /* Invalidate the page cache, if we erase the block which contains - the current cached page */ - if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block)) - this->pagebuf = -1; + /* + * Invalidate the page cache, if we erase the block which + * contains the current cached page + */ + if (page <= chip->pagebuf && chip->pagebuf < + (page + pages_per_block)) + chip->pagebuf = -1; - this->erase_cmd (mtd, page & this->pagemask); + chip->erase_cmd(mtd, page & chip->pagemask); - status = this->waitfunc (mtd, this, FL_ERASING); + status = chip->waitfunc(mtd, chip); - /* See if operation failed and additional status checks are available */ - if ((status & NAND_STATUS_FAIL) && (this->errstat)) { - status = this->errstat(mtd, this, FL_ERASING, status, page); - } + /* + * See if operation failed and additional status checks are + * available + */ + if ((status & NAND_STATUS_FAIL) && (chip->errstat)) + status = chip->errstat(mtd, chip, FL_ERASING, + status, page); /* See if block erase succeeded */ if (status & NAND_STATUS_FAIL) { - DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page); + DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: " + "Failed erase, page 0x%08x\n", page); instr->state = MTD_ERASE_FAILED; - instr->fail_addr = (page << this->page_shift); + instr->fail_addr = (page << chip->page_shift); goto erase_exit; } - /* if BBT requires refresh, set the BBT rewrite flag to the page being erased */ - if (this->options & BBT_AUTO_REFRESH) { - if (((page & BBT_PAGE_MASK) == bbt_masked_page) && - (page != this->bbt_td->pages[chipnr])) { - rewrite_bbt[chipnr] = (page << this->page_shift); - } - } + /* + * If BBT requires refresh, set the BBT rewrite flag to the + * page being erased + */ + if (bbt_masked_page != 0xffffffff && + (page & BBT_PAGE_MASK) == bbt_masked_page) + rewrite_bbt[chipnr] = (page << chip->page_shift); /* Increment page address and decrement length */ - len -= (1 << this->phys_erase_shift); + len -= (1 << chip->phys_erase_shift); page += pages_per_block; /* Check, if we cross a chip boundary */ - if (len && !(page & this->pagemask)) { + if (len && !(page & chip->pagemask)) { chipnr++; - this->select_chip(mtd, -1); - this->select_chip(mtd, chipnr); - - /* if BBT requires refresh and BBT-PERCHIP, - * set the BBT page mask to see if this BBT should be rewritten */ - if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) { - bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK; - } + chip->select_chip(mtd, -1); + chip->select_chip(mtd, chipnr); + /* + * If BBT requires refresh and BBT-PERCHIP, set the BBT + * page mask to see if this BBT should be rewritten + */ + if (bbt_masked_page != 0xffffffff && + (chip->bbt_td->options & NAND_BBT_PERCHIP)) + bbt_masked_page = chip->bbt_td->pages[chipnr] & + BBT_PAGE_MASK; } } instr->state = MTD_ERASE_DONE; -erase_exit: + erase_exit: ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; /* Do call back function */ @@ -2231,16 +2013,21 @@ erase_exit: /* Deselect and wake up anyone waiting on the device */ nand_release_device(mtd); - /* if BBT requires refresh and erase was successful, rewrite any selected bad block tables */ - if ((this->options & BBT_AUTO_REFRESH) && (!ret)) { - for (chipnr = 0; chipnr < this->numchips; chipnr++) { - if (rewrite_bbt[chipnr]) { - /* update the BBT for chip */ - DEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n", - chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]); - nand_update_bbt (mtd, rewrite_bbt[chipnr]); - } - } + /* + * If BBT requires refresh and erase was successful, rewrite any + * selected bad block tables + */ + if (bbt_masked_page == 0xffffffff || ret) + return ret; + + for (chipnr = 0; chipnr < chip->numchips; chipnr++) { + if (!rewrite_bbt[chipnr]) + continue; + /* update the BBT for chip */ + DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt " + "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr], + chip->bbt_td->pages[chipnr]); + nand_update_bbt(mtd, rewrite_bbt[chipnr]); } /* Return more or less happy */ @@ -2253,51 +2040,50 @@ erase_exit: * * Sync is actually a wait for chip ready function */ -static void nand_sync (struct mtd_info *mtd) +static void nand_sync(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; - DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n"); + DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n"); /* Grab the lock and see if the device is available */ - nand_get_device (this, mtd, FL_SYNCING); + nand_get_device(chip, mtd, FL_SYNCING); /* Release it and go back */ - nand_release_device (mtd); + nand_release_device(mtd); } - /** - * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad + * nand_block_isbad - [MTD Interface] Check if block at offset is bad * @mtd: MTD device structure * @ofs: offset relative to mtd start */ -static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs) +static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) { /* Check for invalid offset */ - if (ofs > mtd->size) + if (offs > mtd->size) return -EINVAL; - return nand_block_checkbad (mtd, ofs, 1, 0); + return nand_block_checkbad(mtd, offs, 1, 0); } /** - * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad + * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad * @mtd: MTD device structure * @ofs: offset relative to mtd start */ -static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs) +static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) { - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; int ret; - if ((ret = nand_block_isbad(mtd, ofs))) { - /* If it was bad already, return success and do nothing. */ + if ((ret = nand_block_isbad(mtd, ofs))) { + /* If it was bad already, return success and do nothing. */ if (ret > 0) return 0; - return ret; - } + return ret; + } - return this->block_markbad(mtd, ofs); + return chip->block_markbad(mtd, ofs); } /** @@ -2306,9 +2092,9 @@ static int nand_block_markbad (struct mt */ static int nand_suspend(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; - return nand_get_device (this, mtd, FL_PM_SUSPENDED); + return nand_get_device(chip, mtd, FL_PM_SUSPENDED); } /** @@ -2317,373 +2103,385 @@ static int nand_suspend(struct mtd_info */ static void nand_resume(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; - if (this->state == FL_PM_SUSPENDED) + if (chip->state == FL_PM_SUSPENDED) nand_release_device(mtd); else - printk(KERN_ERR "resume() called for the chip which is not " - "in suspended state\n"); - + printk(KERN_ERR "nand_resume() called for a chip which is not " + "in suspended state\n"); } - -/** - * nand_scan - [NAND Interface] Scan for the NAND device - * @mtd: MTD device structure - * @maxchips: Number of chips to scan for - * - * This fills out all the not initialized function pointers - * with the defaults. - * The flash ID is read and the mtd/chip structures are - * filled with the appropriate values. Buffers are allocated if - * they are not provided by the board driver - * +/* + * Set default functions */ -int nand_scan (struct mtd_info *mtd, int maxchips) +static void nand_set_defaults(struct nand_chip *chip, int busw) { - int i, nand_maf_id, nand_dev_id, busw, maf_id; - struct nand_chip *this = mtd->priv; - - /* Get buswidth to select the correct functions*/ - busw = this->options & NAND_BUSWIDTH_16; - /* check for proper chip_delay setup, set 20us if not */ - if (!this->chip_delay) - this->chip_delay = 20; + if (!chip->chip_delay) + chip->chip_delay = 20; /* check, if a user supplied command function given */ - if (this->cmdfunc == NULL) - this->cmdfunc = nand_command; + if (chip->cmdfunc == NULL) + chip->cmdfunc = nand_command; /* check, if a user supplied wait function given */ - if (this->waitfunc == NULL) - this->waitfunc = nand_wait; - - if (!this->select_chip) - this->select_chip = nand_select_chip; - if (!this->write_byte) - this->write_byte = busw ? nand_write_byte16 : nand_write_byte; - if (!this->read_byte) - this->read_byte = busw ? nand_read_byte16 : nand_read_byte; - if (!this->write_word) - this->write_word = nand_write_word; - if (!this->read_word) - this->read_word = nand_read_word; - if (!this->block_bad) - this->block_bad = nand_block_bad; - if (!this->block_markbad) - this->block_markbad = nand_default_block_markbad; - if (!this->write_buf) - this->write_buf = busw ? nand_write_buf16 : nand_write_buf; - if (!this->read_buf) - this->read_buf = busw ? nand_read_buf16 : nand_read_buf; - if (!this->verify_buf) - this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf; - if (!this->scan_bbt) - this->scan_bbt = nand_default_bbt; + if (chip->waitfunc == NULL) + chip->waitfunc = nand_wait; + + if (!chip->select_chip) + chip->select_chip = nand_select_chip; + if (!chip->read_byte) + chip->read_byte = busw ? nand_read_byte16 : nand_read_byte; + if (!chip->read_word) + chip->read_word = nand_read_word; + if (!chip->block_bad) + chip->block_bad = nand_block_bad; + if (!chip->block_markbad) + chip->block_markbad = nand_default_block_markbad; + if (!chip->write_buf) + chip->write_buf = busw ? nand_write_buf16 : nand_write_buf; + if (!chip->read_buf) + chip->read_buf = busw ? nand_read_buf16 : nand_read_buf; + if (!chip->verify_buf) + chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf; + if (!chip->scan_bbt) + chip->scan_bbt = nand_default_bbt; + + if (!chip->controller) { + chip->controller = &chip->hwcontrol; + spin_lock_init(&chip->controller->lock); + init_waitqueue_head(&chip->controller->wq); + } + +} + +/* + * Get the flash and manufacturer id and lookup if the type is supported + */ +static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, + struct nand_chip *chip, + int busw, int *maf_id) +{ + struct nand_flash_dev *type = NULL; + int i, dev_id, maf_idx; /* Select the device */ - this->select_chip(mtd, 0); + chip->select_chip(mtd, 0); /* Send the command for reading device ID */ - this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1); + chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); /* Read manufacturer and device IDs */ - nand_maf_id = this->read_byte(mtd); - nand_dev_id = this->read_byte(mtd); + *maf_id = chip->read_byte(mtd); + dev_id = chip->read_byte(mtd); - /* Print and store flash device information */ + /* Lookup the flash id */ for (i = 0; nand_flash_ids[i].name != NULL; i++) { + if (dev_id == nand_flash_ids[i].id) { + type = &nand_flash_ids[i]; + break; + } + } - if (nand_dev_id != nand_flash_ids[i].id) - continue; + if (!type) + return ERR_PTR(-ENODEV); + + if (!mtd->name) + mtd->name = type->name; + + chip->chipsize = type->chipsize << 20; + + /* Newer devices have all the information in additional id bytes */ + if (!type->pagesize) { + int extid; + /* The 3rd id byte contains non relevant data ATM */ + extid = chip->read_byte(mtd); + /* The 4th id byte is the important one */ + extid = chip->read_byte(mtd); + /* Calc pagesize */ + mtd->writesize = 1024 << (extid & 0x3); + extid >>= 2; + /* Calc oobsize */ + mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9); + extid >>= 2; + /* Calc blocksize. Blocksize is multiples of 64KiB */ + mtd->erasesize = (64 * 1024) << (extid & 0x03); + extid >>= 2; + /* Get buswidth information */ + busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; - if (!mtd->name) mtd->name = nand_flash_ids[i].name; - this->chipsize = nand_flash_ids[i].chipsize << 20; - - /* New devices have all the information in additional id bytes */ - if (!nand_flash_ids[i].pagesize) { - int extid; - /* The 3rd id byte contains non relevant data ATM */ - extid = this->read_byte(mtd); - /* The 4th id byte is the important one */ - extid = this->read_byte(mtd); - /* Calc pagesize */ - mtd->oobblock = 1024 << (extid & 0x3); - extid >>= 2; - /* Calc oobsize */ - mtd->oobsize = (8 << (extid & 0x01)) * (mtd->oobblock >> 9); - extid >>= 2; - /* Calc blocksize. Blocksize is multiples of 64KiB */ - mtd->erasesize = (64 * 1024) << (extid & 0x03); - extid >>= 2; - /* Get buswidth information */ - busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + } else { + /* + * Old devices have chip data hardcoded in the device id table + */ + mtd->erasesize = type->erasesize; + mtd->writesize = type->pagesize; + mtd->oobsize = mtd->writesize / 32; + busw = type->options & NAND_BUSWIDTH_16; + } - } else { - /* Old devices have this data hardcoded in the - * device id table */ - mtd->erasesize = nand_flash_ids[i].erasesize; - mtd->oobblock = nand_flash_ids[i].pagesize; - mtd->oobsize = mtd->oobblock / 32; - busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16; - } + /* Try to identify manufacturer */ + for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) { + if (nand_manuf_ids[maf_idx].id == *maf_id) + break; + } - /* Try to identify manufacturer */ - for (maf_id = 0; nand_manuf_ids[maf_id].id != 0x0; maf_id++) { - if (nand_manuf_ids[maf_id].id == nand_maf_id) - break; - } + /* + * Check, if buswidth is correct. Hardware drivers should set + * chip correct ! + */ + if (busw != (chip->options & NAND_BUSWIDTH_16)) { + printk(KERN_INFO "NAND device: Manufacturer ID:" + " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, + dev_id, nand_manuf_ids[maf_idx].name, mtd->name); + printk(KERN_WARNING "NAND bus width %d instead %d bit\n", + (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, + busw ? 16 : 8); + return ERR_PTR(-EINVAL); + } - /* Check, if buswidth is correct. Hardware drivers should set - * this correct ! */ - if (busw != (this->options & NAND_BUSWIDTH_16)) { - printk (KERN_INFO "NAND device: Manufacturer ID:" - " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, - nand_manuf_ids[maf_id].name , mtd->name); - printk (KERN_WARNING - "NAND bus width %d instead %d bit\n", - (this->options & NAND_BUSWIDTH_16) ? 16 : 8, - busw ? 16 : 8); - this->select_chip(mtd, -1); - return 1; - } + /* Calculate the address shift from the page size */ + chip->page_shift = ffs(mtd->writesize) - 1; + /* Convert chipsize to number of pages per chip -1. */ + chip->pagemask = (chip->chipsize >> chip->page_shift) - 1; - /* Calculate the address shift from the page size */ - this->page_shift = ffs(mtd->oobblock) - 1; - this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1; - this->chip_shift = ffs(this->chipsize) - 1; - - /* Set the bad block position */ - this->badblockpos = mtd->oobblock > 512 ? - NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; - - /* Get chip options, preserve non chip based options */ - this->options &= ~NAND_CHIPOPTIONS_MSK; - this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK; - /* Set this as a default. Board drivers can override it, if neccecary */ - this->options |= NAND_NO_AUTOINCR; - /* Check if this is a not a samsung device. Do not clear the options - * for chips which are not having an extended id. - */ - if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize) - this->options &= ~NAND_SAMSUNG_LP_OPTIONS; + chip->bbt_erase_shift = chip->phys_erase_shift = + ffs(mtd->erasesize) - 1; + chip->chip_shift = ffs(chip->chipsize) - 1; - /* Check for AND chips with 4 page planes */ - if (this->options & NAND_4PAGE_ARRAY) - this->erase_cmd = multi_erase_cmd; - else - this->erase_cmd = single_erase_cmd; + /* Set the bad block position */ + chip->badblockpos = mtd->writesize > 512 ? + NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; - /* Do not replace user supplied command function ! */ - if (mtd->oobblock > 512 && this->cmdfunc == nand_command) - this->cmdfunc = nand_command_lp; + /* Get chip options, preserve non chip based options */ + chip->options &= ~NAND_CHIPOPTIONS_MSK; + chip->options |= type->options & NAND_CHIPOPTIONS_MSK; - printk (KERN_INFO "NAND device: Manufacturer ID:" - " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, - nand_manuf_ids[maf_id].name , nand_flash_ids[i].name); - break; - } + /* + * Set chip as a default. Board drivers can override it, if necessary + */ + chip->options |= NAND_NO_AUTOINCR; + + /* Check if chip is a not a samsung device. Do not clear the + * options for chips which are not having an extended id. + */ + if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) + chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; + + /* Check for AND chips with 4 page planes */ + if (chip->options & NAND_4PAGE_ARRAY) + chip->erase_cmd = multi_erase_cmd; + else + chip->erase_cmd = single_erase_cmd; + + /* Do not replace user supplied command function ! */ + if (mtd->writesize > 512 && chip->cmdfunc == nand_command) + chip->cmdfunc = nand_command_lp; + + printk(KERN_INFO "NAND device: Manufacturer ID:" + " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id, + nand_manuf_ids[maf_idx].name, type->name); + + return type; +} + +/* module_text_address() isn't exported, and it's mostly a pointless + test if this is a module _anyway_ -- they'd have to try _really_ hard + to call us from in-kernel code if the core NAND support is modular. */ +#ifdef MODULE +#define caller_is_module() (1) +#else +#define caller_is_module() \ + module_text_address((unsigned long)__builtin_return_address(0)) +#endif - if (!nand_flash_ids[i].name) { - printk (KERN_WARNING "No NAND device found!!!\n"); - this->select_chip(mtd, -1); - return 1; +/** + * nand_scan - [NAND Interface] Scan for the NAND device + * @mtd: MTD device structure + * @maxchips: Number of chips to scan for + * + * This fills out all the uninitialized function pointers + * with the defaults. + * The flash ID is read and the mtd/chip structures are + * filled with the appropriate values. + * The mtd->owner field must be set to the module of the caller + * + */ +int nand_scan(struct mtd_info *mtd, int maxchips) +{ + int i, busw, nand_maf_id; + struct nand_chip *chip = mtd->priv; + struct nand_flash_dev *type; + + /* Many callers got this wrong, so check for it for a while... */ + if (!mtd->owner && caller_is_module()) { + printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n"); + BUG(); } - for (i=1; i < maxchips; i++) { - this->select_chip(mtd, i); + /* Get buswidth to select the correct functions */ + busw = chip->options & NAND_BUSWIDTH_16; + /* Set the default functions */ + nand_set_defaults(chip, busw); - /* Send the command for reading device ID */ - this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1); + /* Read the flash type */ + type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id); + + if (IS_ERR(type)) { + printk(KERN_WARNING "No NAND device found!!!\n"); + chip->select_chip(mtd, -1); + return PTR_ERR(type); + } + /* Check for a chip array */ + for (i = 1; i < maxchips; i++) { + chip->select_chip(mtd, i); + /* Send the command for reading device ID */ + chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); /* Read manufacturer and device IDs */ - if (nand_maf_id != this->read_byte(mtd) || - nand_dev_id != this->read_byte(mtd)) + if (nand_maf_id != chip->read_byte(mtd) || + type->id != chip->read_byte(mtd)) break; } if (i > 1) printk(KERN_INFO "%d NAND chips detected\n", i); - /* Allocate buffers, if neccecary */ - if (!this->oob_buf) { - size_t len; - len = mtd->oobsize << (this->phys_erase_shift - this->page_shift); - this->oob_buf = kmalloc (len, GFP_KERNEL); - if (!this->oob_buf) { - printk (KERN_ERR "nand_scan(): Cannot allocate oob_buf\n"); - return -ENOMEM; - } - this->options |= NAND_OOBBUF_ALLOC; - } + /* Store the number of chips and calc total size for mtd */ + chip->numchips = i; + mtd->size = i * chip->chipsize; - if (!this->data_buf) { - size_t len; - len = mtd->oobblock + mtd->oobsize; - this->data_buf = kmalloc (len, GFP_KERNEL); - if (!this->data_buf) { - if (this->options & NAND_OOBBUF_ALLOC) - kfree (this->oob_buf); - printk (KERN_ERR "nand_scan(): Cannot allocate data_buf\n"); - return -ENOMEM; - } - this->options |= NAND_DATABUF_ALLOC; - } + /* Preset the internal oob write buffer */ + memset(chip->buffers.oobwbuf, 0xff, mtd->oobsize); - /* Store the number of chips and calc total size for mtd */ - this->numchips = i; - mtd->size = i * this->chipsize; - /* Convert chipsize to number of pages per chip -1. */ - this->pagemask = (this->chipsize >> this->page_shift) - 1; - /* Preset the internal oob buffer */ - memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift)); - - /* If no default placement scheme is given, select an - * appropriate one */ - if (!this->autooob) { - /* Select the appropriate default oob placement scheme for - * placement agnostic filesystems */ + /* + * If no default placement scheme is given, select an appropriate one + */ + if (!chip->ecc.layout) { switch (mtd->oobsize) { case 8: - this->autooob = &nand_oob_8; + chip->ecc.layout = &nand_oob_8; break; case 16: - this->autooob = &nand_oob_16; + chip->ecc.layout = &nand_oob_16; break; case 64: - this->autooob = &nand_oob_64; + chip->ecc.layout = &nand_oob_64; break; default: - printk (KERN_WARNING "No oob scheme defined for oobsize %d\n", - mtd->oobsize); + printk(KERN_WARNING "No oob scheme defined for " + "oobsize %d\n", mtd->oobsize); BUG(); } } - /* The number of bytes available for the filesystem to place fs dependend - * oob data */ - mtd->oobavail = 0; - for (i = 0; this->autooob->oobfree[i][1]; i++) - mtd->oobavail += this->autooob->oobfree[i][1]; - /* - * check ECC mode, default to software - * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize - * fallback to software ECC - */ - this->eccsize = 256; /* set default eccsize */ - this->eccbytes = 3; - - switch (this->eccmode) { - case NAND_ECC_HW12_2048: - if (mtd->oobblock < 2048) { - printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n", - mtd->oobblock); - this->eccmode = NAND_ECC_SOFT; - this->calculate_ecc = nand_calculate_ecc; - this->correct_data = nand_correct_data; - } else - this->eccsize = 2048; - break; - - case NAND_ECC_HW3_512: - case NAND_ECC_HW6_512: - case NAND_ECC_HW8_512: - if (mtd->oobblock == 256) { - printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n"); - this->eccmode = NAND_ECC_SOFT; - this->calculate_ecc = nand_calculate_ecc; - this->correct_data = nand_correct_data; - } else - this->eccsize = 512; /* set eccsize to 512 */ - break; + * check ECC mode, default to software if 3byte/512byte hardware ECC is + * selected and we have 256 byte pagesize fallback to software ECC + */ + switch (chip->ecc.mode) { + case NAND_ECC_HW: + /* Use standard hwecc read page function ? */ + if (!chip->ecc.read_page) + chip->ecc.read_page = nand_read_page_hwecc; + if (!chip->ecc.write_page) + chip->ecc.write_page = nand_write_page_hwecc; + if (!chip->ecc.read_oob) + chip->ecc.read_oob = nand_read_oob_std; + if (!chip->ecc.write_oob) + chip->ecc.write_oob = nand_write_oob_std; + + case NAND_ECC_HW_SYNDROME: + if (!chip->ecc.calculate || !chip->ecc.correct || + !chip->ecc.hwctl) { + printk(KERN_WARNING "No ECC functions supplied, " + "Hardware ECC not possible\n"); + BUG(); + } + /* Use standard syndrome read/write page function ? */ + if (!chip->ecc.read_page) + chip->ecc.read_page = nand_read_page_syndrome; + if (!chip->ecc.write_page) + chip->ecc.write_page = nand_write_page_syndrome; + if (!chip->ecc.read_oob) + chip->ecc.read_oob = nand_read_oob_syndrome; + if (!chip->ecc.write_oob) + chip->ecc.write_oob = nand_write_oob_syndrome; + + if (mtd->writesize >= chip->ecc.size) + break; + printk(KERN_WARNING "%d byte HW ECC not possible on " + "%d byte page size, fallback to SW ECC\n", + chip->ecc.size, mtd->writesize); + chip->ecc.mode = NAND_ECC_SOFT; - case NAND_ECC_HW3_256: + case NAND_ECC_SOFT: + chip->ecc.calculate = nand_calculate_ecc; + chip->ecc.correct = nand_correct_data; + chip->ecc.read_page = nand_read_page_swecc; + chip->ecc.write_page = nand_write_page_swecc; + chip->ecc.read_oob = nand_read_oob_std; + chip->ecc.write_oob = nand_write_oob_std; + chip->ecc.size = 256; + chip->ecc.bytes = 3; break; case NAND_ECC_NONE: - printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n"); - this->eccmode = NAND_ECC_NONE; + printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " + "This is not recommended !!\n"); + chip->ecc.read_page = nand_read_page_raw; + chip->ecc.write_page = nand_write_page_raw; + chip->ecc.read_oob = nand_read_oob_std; + chip->ecc.write_oob = nand_write_oob_std; + chip->ecc.size = mtd->writesize; + chip->ecc.bytes = 0; break; - - case NAND_ECC_SOFT: - this->calculate_ecc = nand_calculate_ecc; - this->correct_data = nand_correct_data; - break; - default: - printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode); - BUG(); - } - - /* Check hardware ecc function availability and adjust number of ecc bytes per - * calculation step - */ - switch (this->eccmode) { - case NAND_ECC_HW12_2048: - this->eccbytes += 4; - case NAND_ECC_HW8_512: - this->eccbytes += 2; - case NAND_ECC_HW6_512: - this->eccbytes += 3; - case NAND_ECC_HW3_512: - case NAND_ECC_HW3_256: - if (this->calculate_ecc && this->correct_data && this->enable_hwecc) - break; - printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n"); + printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n", + chip->ecc.mode); BUG(); } - mtd->eccsize = this->eccsize; - - /* Set the number of read / write steps for one page to ensure ECC generation */ - switch (this->eccmode) { - case NAND_ECC_HW12_2048: - this->eccsteps = mtd->oobblock / 2048; - break; - case NAND_ECC_HW3_512: - case NAND_ECC_HW6_512: - case NAND_ECC_HW8_512: - this->eccsteps = mtd->oobblock / 512; - break; - case NAND_ECC_HW3_256: - case NAND_ECC_SOFT: - this->eccsteps = mtd->oobblock / 256; - break; + /* + * The number of bytes available for a client to place data into + * the out of band area + */ + chip->ecc.layout->oobavail = 0; + for (i = 0; chip->ecc.layout->oobfree[i].length; i++) + chip->ecc.layout->oobavail += + chip->ecc.layout->oobfree[i].length; - case NAND_ECC_NONE: - this->eccsteps = 1; - break; + /* + * Set the number of read / write steps for one page depending on ECC + * mode + */ + chip->ecc.steps = mtd->writesize / chip->ecc.size; + if(chip->ecc.steps * chip->ecc.size != mtd->writesize) { + printk(KERN_WARNING "Invalid ecc parameters\n"); + BUG(); } + chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; - /* Initialize state, waitqueue and spinlock */ - this->state = FL_READY; - init_waitqueue_head (&this->wq); - spin_lock_init (&this->chip_lock); + /* Initialize state */ + chip->state = FL_READY; /* De-select the device */ - this->select_chip(mtd, -1); + chip->select_chip(mtd, -1); /* Invalidate the pagebuffer reference */ - this->pagebuf = -1; + chip->pagebuf = -1; /* Fill in remaining MTD driver data */ mtd->type = MTD_NANDFLASH; - mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; + mtd->flags = MTD_CAP_NANDFLASH; mtd->ecctype = MTD_ECC_SW; mtd->erase = nand_erase; mtd->point = NULL; mtd->unpoint = NULL; mtd->read = nand_read; mtd->write = nand_write; - mtd->read_ecc = nand_read_ecc; - mtd->write_ecc = nand_write_ecc; mtd->read_oob = nand_read_oob; mtd->write_oob = nand_write_oob; - mtd->readv = NULL; - mtd->writev = nand_writev; - mtd->writev_ecc = nand_writev_ecc; mtd->sync = nand_sync; mtd->lock = NULL; mtd->unlock = NULL; @@ -2692,47 +2490,38 @@ int nand_scan (struct mtd_info *mtd, int mtd->block_isbad = nand_block_isbad; mtd->block_markbad = nand_block_markbad; - /* and make the autooob the default one */ - memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); - - mtd->owner = THIS_MODULE; + /* propagate ecc.layout to mtd_info */ + mtd->ecclayout = chip->ecc.layout; /* Check, if we should skip the bad block table scan */ - if (this->options & NAND_SKIP_BBTSCAN) + if (chip->options & NAND_SKIP_BBTSCAN) return 0; /* Build bad block table */ - return this->scan_bbt (mtd); + return chip->scan_bbt(mtd); } /** * nand_release - [NAND Interface] Free resources held by the NAND device * @mtd: MTD device structure */ -void nand_release (struct mtd_info *mtd) +void nand_release(struct mtd_info *mtd) { - struct nand_chip *this = mtd->priv; + struct nand_chip *chip = mtd->priv; #ifdef CONFIG_MTD_PARTITIONS /* Deregister partitions */ - del_mtd_partitions (mtd); + del_mtd_partitions(mtd); #endif /* Deregister the device */ - del_mtd_device (mtd); + del_mtd_device(mtd); /* Free bad block table memory */ - kfree (this->bbt); - /* Buffer allocated by nand_scan ? */ - if (this->options & NAND_OOBBUF_ALLOC) - kfree (this->oob_buf); - /* Buffer allocated by nand_scan ? */ - if (this->options & NAND_DATABUF_ALLOC) - kfree (this->data_buf); + kfree(chip->bbt); } -EXPORT_SYMBOL_GPL (nand_scan); -EXPORT_SYMBOL_GPL (nand_release); - +EXPORT_SYMBOL_GPL(nand_scan); +EXPORT_SYMBOL_GPL(nand_release); static int __init nand_base_init(void) { @@ -2748,6 +2537,6 @@ static void __exit nand_base_exit(void) module_init(nand_base_init); module_exit(nand_base_exit); -MODULE_LICENSE ("GPL"); -MODULE_AUTHOR ("Steven J. Hill , Thomas Gleixner "); -MODULE_DESCRIPTION ("Generic NAND flash driver code"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Steven J. Hill , Thomas Gleixner "); +MODULE_DESCRIPTION("Generic NAND flash driver code"); diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index ca28699..a612c4e 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -48,7 +48,7 @@ * * Following assumptions are made: * - bbts start at a page boundary, if autolocated on a block boundary - * - the space neccecary for a bbt in FLASH does not exceed a block boundary + * - the space necessary for a bbt in FLASH does not exceed a block boundary * */ @@ -60,7 +60,7 @@ #include #include #include #include - +#include /** * check_pattern - [GENERIC] check if a pattern is in the buffer @@ -75,7 +75,7 @@ #include * pattern area contain 0xff * */ -static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) +static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) { int i, end = 0; uint8_t *p = buf; @@ -116,7 +116,7 @@ static int check_pattern (uint8_t *buf, * no optional empty check * */ -static int check_short_pattern (uint8_t *buf, struct nand_bbt_descr *td) +static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td) { int i; uint8_t *p = buf; @@ -142,8 +142,8 @@ static int check_short_pattern (uint8_t * Read the bad block table starting from page. * */ -static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, - int bits, int offs, int reserved_block_code) +static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, + int bits, int offs, int reserved_block_code) { int res, i, j, act = 0; struct nand_chip *this = mtd->priv; @@ -152,17 +152,17 @@ static int read_bbt (struct mtd_info *mt uint8_t msk = (uint8_t) ((1 << bits) - 1); totlen = (num * bits) >> 3; - from = ((loff_t)page) << this->page_shift; + from = ((loff_t) page) << this->page_shift; while (totlen) { - len = min (totlen, (size_t) (1 << this->bbt_erase_shift)); - res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob); + len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); + res = mtd->read(mtd, from, len, &retlen, buf); if (res < 0) { if (retlen != len) { - printk (KERN_INFO "nand_bbt: Error reading bad block table\n"); + printk(KERN_INFO "nand_bbt: Error reading bad block table\n"); return res; } - printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); + printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); } /* Analyse data */ @@ -172,22 +172,23 @@ static int read_bbt (struct mtd_info *mt uint8_t tmp = (dat >> j) & msk; if (tmp == msk) continue; - if (reserved_block_code && - (tmp == reserved_block_code)) { - printk (KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n", - ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); + if (reserved_block_code && (tmp == reserved_block_code)) { + printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n", + ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06); + mtd->ecc_stats.bbtblocks++; continue; } /* Leave it for now, if its matured we can move this * message to MTD_DEBUG_LEVEL0 */ - printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n", - ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); + printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n", + ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); /* Factory marked bad or worn out ? */ if (tmp == 0) this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); else this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06); + mtd->ecc_stats.badblocks++; } } totlen -= len; @@ -207,7 +208,7 @@ static int read_bbt (struct mtd_info *mt * Read the bad block table for all chips starting at a given page * We assume that the bbt bits are in consecutive order. */ -static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip) +static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip) { struct nand_chip *this = mtd->priv; int res = 0, i; @@ -231,6 +232,42 @@ static int read_abs_bbt (struct mtd_info return 0; } +/* + * Scan read raw data from flash + */ +static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, + size_t len) +{ + struct mtd_oob_ops ops; + + ops.mode = MTD_OOB_RAW; + ops.ooboffs = 0; + ops.ooblen = mtd->oobsize; + ops.oobbuf = buf; + ops.datbuf = buf; + ops.len = len; + + return mtd->read_oob(mtd, offs, &ops); +} + +/* + * Scan write data with oob to flash + */ +static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len, + uint8_t *buf, uint8_t *oob) +{ + struct mtd_oob_ops ops; + + ops.mode = MTD_OOB_PLACE; + ops.ooboffs = 0; + ops.ooblen = mtd->oobsize; + ops.datbuf = buf; + ops.oobbuf = oob; + ops.len = len; + + return mtd->write_oob(mtd, offs, &ops); +} + /** * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page * @mtd: MTD device structure @@ -242,28 +279,85 @@ static int read_abs_bbt (struct mtd_info * We assume that the bbt bits are in consecutive order. * */ -static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, - struct nand_bbt_descr *md) +static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, + struct nand_bbt_descr *td, struct nand_bbt_descr *md) { struct nand_chip *this = mtd->priv; /* Read the primary version, if available */ if (td->options & NAND_BBT_VERSION) { - nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); - td->version[0] = buf[mtd->oobblock + td->veroffs]; - printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]); + scan_read_raw(mtd, buf, td->pages[0] << this->page_shift, + mtd->writesize); + td->version[0] = buf[mtd->writesize + td->veroffs]; + printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", + td->pages[0], td->version[0]); } /* Read the mirror version, if available */ if (md && (md->options & NAND_BBT_VERSION)) { - nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); - md->version[0] = buf[mtd->oobblock + md->veroffs]; - printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); + scan_read_raw(mtd, buf, md->pages[0] << this->page_shift, + mtd->writesize); + md->version[0] = buf[mtd->writesize + md->veroffs]; + printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", + md->pages[0], md->version[0]); } - return 1; } +/* + * Scan a given block full + */ +static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, + loff_t offs, uint8_t *buf, size_t readlen, + int scanlen, int len) +{ + int ret, j; + + ret = scan_read_raw(mtd, buf, offs, readlen); + if (ret) + return ret; + + for (j = 0; j < len; j++, buf += scanlen) { + if (check_pattern(buf, scanlen, mtd->writesize, bd)) + return 1; + } + return 0; +} + +/* + * Scan a given block partially + */ +static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, + loff_t offs, uint8_t *buf, int len) +{ + struct mtd_oob_ops ops; + int j, ret; + + ops.len = mtd->oobsize; + ops.ooblen = mtd->oobsize; + ops.oobbuf = buf; + ops.ooboffs = 0; + ops.datbuf = NULL; + ops.mode = MTD_OOB_PLACE; + + for (j = 0; j < len; j++) { + /* + * Read the full oob until read_oob is fixed to + * handle single byte reads for 16 bit + * buswidth + */ + ret = mtd->read_oob(mtd, offs, &ops); + if (ret) + return ret; + + if (check_short_pattern(buf, bd)) + return 1; + + offs += mtd->writesize; + } + return 0; +} + /** * create_bbt - [GENERIC] Create a bad block table by scanning the device * @mtd: MTD device structure @@ -275,15 +369,16 @@ static int read_abs_bbts (struct mtd_inf * Create a bad block table by scanning the device * for the given good/bad block identify pattern */ -static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip) +static int create_bbt(struct mtd_info *mtd, uint8_t *buf, + struct nand_bbt_descr *bd, int chip) { struct nand_chip *this = mtd->priv; - int i, j, numblocks, len, scanlen; + int i, numblocks, len, scanlen; int startblock; loff_t from; - size_t readlen, ooblen; + size_t readlen; - printk (KERN_INFO "Scanning device for bad blocks\n"); + printk(KERN_INFO "Scanning device for bad blocks\n"); if (bd->options & NAND_BBT_SCANALLPAGES) len = 1 << (this->bbt_erase_shift - this->page_shift); @@ -296,25 +391,24 @@ static int create_bbt (struct mtd_info * if (!(bd->options & NAND_BBT_SCANEMPTY)) { /* We need only read few bytes from the OOB area */ - scanlen = ooblen = 0; + scanlen = 0; readlen = bd->len; } else { /* Full page content should be read */ - scanlen = mtd->oobblock + mtd->oobsize; - readlen = len * mtd->oobblock; - ooblen = len * mtd->oobsize; + scanlen = mtd->writesize + mtd->oobsize; + readlen = len * mtd->writesize; } if (chip == -1) { - /* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it - * makes shifting and masking less painful */ + /* Note that numblocks is 2 * (real numblocks) here, see i+=2 + * below as it makes shifting and masking less painful */ numblocks = mtd->size >> (this->bbt_erase_shift - 1); startblock = 0; from = 0; } else { if (chip >= this->numchips) { - printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n", - chip + 1, this->numchips); + printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n", + chip + 1, this->numchips); return -EINVAL; } numblocks = this->chipsize >> (this->bbt_erase_shift - 1); @@ -326,36 +420,22 @@ static int create_bbt (struct mtd_info * for (i = startblock; i < numblocks;) { int ret; - if (bd->options & NAND_BBT_SCANEMPTY) - if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen))) - return ret; - - for (j = 0; j < len; j++) { - if (!(bd->options & NAND_BBT_SCANEMPTY)) { - size_t retlen; - - /* Read the full oob until read_oob is fixed to - * handle single byte reads for 16 bit buswidth */ - ret = mtd->read_oob(mtd, from + j * mtd->oobblock, - mtd->oobsize, &retlen, buf); - if (ret) - return ret; - - if (check_short_pattern (buf, bd)) { - this->bbt[i >> 3] |= 0x03 << (i & 0x6); - printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", - i >> 1, (unsigned int) from); - break; - } - } else { - if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { - this->bbt[i >> 3] |= 0x03 << (i & 0x6); - printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", - i >> 1, (unsigned int) from); - break; - } - } + if (bd->options & NAND_BBT_SCANALLPAGES) + ret = scan_block_full(mtd, bd, from, buf, readlen, + scanlen, len); + else + ret = scan_block_fast(mtd, bd, from, buf, len); + + if (ret < 0) + return ret; + + if (ret) { + this->bbt[i >> 3] |= 0x03 << (i & 0x6); + printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", + i >> 1, (unsigned int)from); + mtd->ecc_stats.badblocks++; } + i += 2; from += (1 << this->bbt_erase_shift); } @@ -374,22 +454,23 @@ static int create_bbt (struct mtd_info * * block. * If the option NAND_BBT_PERCHIP is given, each chip is searched * for a bbt, which contains the bad block information of this chip. - * This is neccecary to provide support for certain DOC devices. + * This is necessary to provide support for certain DOC devices. * * The bbt ident pattern resides in the oob area of the first page * in a block. */ -static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) +static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) { struct nand_chip *this = mtd->priv; int i, chips; int bits, startblock, block, dir; - int scanlen = mtd->oobblock + mtd->oobsize; + int scanlen = mtd->writesize + mtd->oobsize; int bbtblocks; + int blocktopage = this->bbt_erase_shift - this->page_shift; /* Search direction top -> down ? */ if (td->options & NAND_BBT_LASTBLOCK) { - startblock = (mtd->size >> this->bbt_erase_shift) -1; + startblock = (mtd->size >> this->bbt_erase_shift) - 1; dir = -1; } else { startblock = 0; @@ -415,13 +496,16 @@ static int search_bbt (struct mtd_info * td->pages[i] = -1; /* Scan the maximum number of blocks */ for (block = 0; block < td->maxblocks; block++) { + int actblock = startblock + dir * block; + loff_t offs = actblock << this->bbt_erase_shift; + /* Read first page */ - nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize); - if (!check_pattern(buf, scanlen, mtd->oobblock, td)) { - td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift); + scan_read_raw(mtd, buf, offs, mtd->writesize); + if (!check_pattern(buf, scanlen, mtd->writesize, td)) { + td->pages[i] = actblock << blocktopage; if (td->options & NAND_BBT_VERSION) { - td->version[i] = buf[mtd->oobblock + td->veroffs]; + td->version[i] = buf[mtd->writesize + td->veroffs]; } break; } @@ -431,9 +515,10 @@ static int search_bbt (struct mtd_info * /* Check, if we found a bbt for each requested chip */ for (i = 0; i < chips; i++) { if (td->pages[i] == -1) - printk (KERN_WARNING "Bad block table not found for chip %d\n", i); + printk(KERN_WARNING "Bad block table not found for chip %d\n", i); else - printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]); + printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], + td->version[i]); } return 0; } @@ -447,21 +532,19 @@ static int search_bbt (struct mtd_info * * * Search and read the bad block table(s) */ -static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, - struct nand_bbt_descr *td, struct nand_bbt_descr *md) +static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md) { /* Search the primary table */ - search_bbt (mtd, buf, td); + search_bbt(mtd, buf, td); /* Search the mirror table */ if (md) - search_bbt (mtd, buf, md); + search_bbt(mtd, buf, md); /* Force result check */ return 1; } - /** * write_bbt - [GENERIC] (Re)write the bad block table * @@ -474,25 +557,31 @@ static int search_read_bbts (struct mtd_ * (Re)write the bad block table * */ -static int write_bbt (struct mtd_info *mtd, uint8_t *buf, - struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) +static int write_bbt(struct mtd_info *mtd, uint8_t *buf, + struct nand_bbt_descr *td, struct nand_bbt_descr *md, + int chipsel) { struct nand_chip *this = mtd->priv; - struct nand_oobinfo oobinfo; struct erase_info einfo; int i, j, res, chip = 0; int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; - int nrchips, bbtoffs, pageoffs; + int nrchips, bbtoffs, pageoffs, ooboffs; uint8_t msk[4]; uint8_t rcode = td->reserved_block_code; size_t retlen, len = 0; loff_t to; + struct mtd_oob_ops ops; + + ops.ooblen = mtd->oobsize; + ops.ooboffs = 0; + ops.datbuf = NULL; + ops.mode = MTD_OOB_PLACE; if (!rcode) rcode = 0xff; /* Write bad block table per chip rather than per device ? */ if (td->options & NAND_BBT_PERCHIP) { - numblocks = (int) (this->chipsize >> this->bbt_erase_shift); + numblocks = (int)(this->chipsize >> this->bbt_erase_shift); /* Full device write or specific chip ? */ if (chipsel == -1) { nrchips = this->numchips; @@ -501,7 +590,7 @@ static int write_bbt (struct mtd_info *m chip = chipsel; } } else { - numblocks = (int) (mtd->size >> this->bbt_erase_shift); + numblocks = (int)(mtd->size >> this->bbt_erase_shift); nrchips = 1; } @@ -530,27 +619,38 @@ static int write_bbt (struct mtd_info *m for (i = 0; i < td->maxblocks; i++) { int block = startblock + dir * i; /* Check, if the block is bad */ - switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) { + switch ((this->bbt[block >> 2] >> + (2 * (block & 0x03))) & 0x03) { case 0x01: case 0x03: continue; } - page = block << (this->bbt_erase_shift - this->page_shift); + page = block << + (this->bbt_erase_shift - this->page_shift); /* Check, if the block is used by the mirror table */ if (!md || md->pages[chip] != page) goto write; } - printk (KERN_ERR "No space left to write bad block table\n"); + printk(KERN_ERR "No space left to write bad block table\n"); return -ENOSPC; -write: + write: /* Set up shift count and masks for the flash table */ bits = td->options & NAND_BBT_NRBITS_MSK; + msk[2] = ~rcode; switch (bits) { - case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break; - case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break; - case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break; - case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break; + case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; + msk[3] = 0x01; + break; + case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; + msk[3] = 0x03; + break; + case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; + msk[3] = 0x0f; + break; + case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; + msk[3] = 0xff; + break; default: return -EINVAL; } @@ -558,82 +658,92 @@ write: to = ((loff_t) page) << this->page_shift; - memcpy (&oobinfo, this->autooob, sizeof(oobinfo)); - oobinfo.useecc = MTD_NANDECC_PLACEONLY; - /* Must we save the block contents ? */ if (td->options & NAND_BBT_SAVECONTENT) { /* Make it block aligned */ to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1)); len = 1 << this->bbt_erase_shift; - res = mtd->read_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo); + res = mtd->read(mtd, to, len, &retlen, buf); if (res < 0) { if (retlen != len) { - printk (KERN_INFO "nand_bbt: Error reading block for writing the bad block table\n"); + printk(KERN_INFO "nand_bbt: Error " + "reading block for writing " + "the bad block table\n"); return res; } - printk (KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n"); + printk(KERN_WARNING "nand_bbt: ECC error " + "while reading block for writing " + "bad block table\n"); } + /* Read oob data */ + ops.len = (len >> this->page_shift) * mtd->oobsize; + ops.oobbuf = &buf[len]; + res = mtd->read_oob(mtd, to + mtd->writesize, &ops); + if (res < 0 || ops.retlen != ops.len) + goto outerr; + /* Calc the byte offset in the buffer */ pageoffs = page - (int)(to >> this->page_shift); offs = pageoffs << this->page_shift; /* Preset the bbt area with 0xff */ - memset (&buf[offs], 0xff, (size_t)(numblocks >> sft)); - /* Preset the bbt's oob area with 0xff */ - memset (&buf[len + pageoffs * mtd->oobsize], 0xff, - ((len >> this->page_shift) - pageoffs) * mtd->oobsize); - if (td->options & NAND_BBT_VERSION) { - buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip]; - } + memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); + ooboffs = len + (pageoffs * mtd->oobsize); + } else { /* Calc length */ len = (size_t) (numblocks >> sft); /* Make it page aligned ! */ - len = (len + (mtd->oobblock-1)) & ~(mtd->oobblock-1); + len = (len + (mtd->writesize - 1)) & + ~(mtd->writesize - 1); /* Preset the buffer with 0xff */ - memset (buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize); + memset(buf, 0xff, len + + (len >> this->page_shift)* mtd->oobsize); offs = 0; + ooboffs = len; /* Pattern is located in oob area of first page */ - memcpy (&buf[len + td->offs], td->pattern, td->len); - if (td->options & NAND_BBT_VERSION) { - buf[len + td->veroffs] = td->version[chip]; - } + memcpy(&buf[ooboffs + td->offs], td->pattern, td->len); } + if (td->options & NAND_BBT_VERSION) + buf[ooboffs + td->veroffs] = td->version[chip]; + /* walk through the memory table */ - for (i = 0; i < numblocks; ) { + for (i = 0; i < numblocks;) { uint8_t dat; dat = this->bbt[bbtoffs + (i >> 2)]; - for (j = 0; j < 4; j++ , i++) { + for (j = 0; j < 4; j++, i++) { int sftcnt = (i << (3 - sft)) & sftmsk; /* Do not store the reserved bbt blocks ! */ - buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt); + buf[offs + (i >> sft)] &= + ~(msk[dat & 0x03] << sftcnt); dat >>= 2; } } - memset (&einfo, 0, sizeof (einfo)); + memset(&einfo, 0, sizeof(einfo)); einfo.mtd = mtd; - einfo.addr = (unsigned long) to; + einfo.addr = (unsigned long)to; einfo.len = 1 << this->bbt_erase_shift; - res = nand_erase_nand (mtd, &einfo, 1); - if (res < 0) { - printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res); - return res; - } + res = nand_erase_nand(mtd, &einfo, 1); + if (res < 0) + goto outerr; - res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo); - if (res < 0) { - printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res); - return res; - } - printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", - (unsigned int) to, td->version[chip]); + res = scan_write_bbt(mtd, to, len, buf, &buf[len]); + if (res < 0) + goto outerr; + + printk(KERN_DEBUG "Bad block table written to 0x%08x, version " + "0x%02X\n", (unsigned int)to, td->version[chip]); /* Mark it as used */ td->pages[chip] = page; } return 0; + + outerr: + printk(KERN_WARNING + "nand_bbt: Error while writing bad block table %d\n", res); + return res; } /** @@ -644,27 +754,27 @@ write: * The function creates a memory based bbt by scanning the device * for manufacturer / software marked good / bad blocks */ -static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) +static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) { struct nand_chip *this = mtd->priv; bd->options &= ~NAND_BBT_SCANEMPTY; - return create_bbt (mtd, this->data_buf, bd, -1); + return create_bbt(mtd, this->buffers.databuf, bd, -1); } /** - * check_create - [GENERIC] create and write bbt(s) if neccecary + * check_create - [GENERIC] create and write bbt(s) if necessary * @mtd: MTD device structure * @buf: temporary buffer * @bd: descriptor for the good/bad block search pattern * * The function checks the results of the previous call to read_bbt - * and creates / updates the bbt(s) if neccecary - * Creation is neccecary if no bbt was found for the chip/device - * Update is neccecary if one of the tables is missing or the + * and creates / updates the bbt(s) if necessary + * Creation is necessary if no bbt was found for the chip/device + * Update is necessary if one of the tables is missing or the * version nr. of one table is less than the other */ -static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd) +static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd) { int i, chips, writeops, chipsel, res; struct nand_chip *this = mtd->priv; @@ -732,35 +842,35 @@ static int check_create (struct mtd_info rd = td; goto writecheck; } -create: + create: /* Create the bad block table by scanning the device ? */ if (!(td->options & NAND_BBT_CREATE)) continue; /* Create the table in memory by scanning the chip(s) */ - create_bbt (mtd, buf, bd, chipsel); + create_bbt(mtd, buf, bd, chipsel); td->version[i] = 1; if (md) md->version[i] = 1; -writecheck: + writecheck: /* read back first ? */ if (rd) - read_abs_bbt (mtd, buf, rd, chipsel); + read_abs_bbt(mtd, buf, rd, chipsel); /* If they weren't versioned, read both. */ if (rd2) - read_abs_bbt (mtd, buf, rd2, chipsel); + read_abs_bbt(mtd, buf, rd2, chipsel); /* Write the bad block table to the device ? */ if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { - res = write_bbt (mtd, buf, td, md, chipsel); + res = write_bbt(mtd, buf, td, md, chipsel); if (res < 0) return res; } /* Write the mirror bad block table to the device ? */ if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { - res = write_bbt (mtd, buf, md, td, chipsel); + res = write_bbt(mtd, buf, md, td, chipsel); if (res < 0) return res; } @@ -777,7 +887,7 @@ writecheck: * accidental erasures / writes. The regions are identified by * the mark 0x02. */ -static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) +static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) { struct nand_chip *this = mtd->priv; int i, j, chips, block, nrblocks, update; @@ -795,7 +905,8 @@ static void mark_bbt_region (struct mtd_ for (i = 0; i < chips; i++) { if ((td->options & NAND_BBT_ABSPAGE) || !(td->options & NAND_BBT_WRITE)) { - if (td->pages[i] == -1) continue; + if (td->pages[i] == -1) + continue; block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); block <<= 1; oldval = this->bbt[(block >> 3)]; @@ -815,7 +926,8 @@ static void mark_bbt_region (struct mtd_ oldval = this->bbt[(block >> 3)]; newval = oldval | (0x2 << (block & 0x06)); this->bbt[(block >> 3)] = newval; - if (oldval != newval) update = 1; + if (oldval != newval) + update = 1; block += 2; } /* If we want reserved blocks to be recorded to flash, and some @@ -840,7 +952,7 @@ static void mark_bbt_region (struct mtd_ * by calling the nand_free_bbt function. * */ -int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) +int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) { struct nand_chip *this = mtd->priv; int len, res = 0; @@ -850,21 +962,21 @@ int nand_scan_bbt (struct mtd_info *mtd, len = mtd->size >> (this->bbt_erase_shift + 2); /* Allocate memory (2bit per block) */ - this->bbt = kmalloc (len, GFP_KERNEL); + this->bbt = kmalloc(len, GFP_KERNEL); if (!this->bbt) { - printk (KERN_ERR "nand_scan_bbt: Out of memory\n"); + printk(KERN_ERR "nand_scan_bbt: Out of memory\n"); return -ENOMEM; } /* Clear the memory bad block table */ - memset (this->bbt, 0x00, len); + memset(this->bbt, 0x00, len); /* If no primary table decriptor is given, scan the device * to build a memory based bad block table */ if (!td) { if ((res = nand_memory_bbt(mtd, bd))) { - printk (KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n"); - kfree (this->bbt); + printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n"); + kfree(this->bbt); this->bbt = NULL; } return res; @@ -873,35 +985,34 @@ int nand_scan_bbt (struct mtd_info *mtd, /* Allocate a temporary buffer for one eraseblock incl. oob */ len = (1 << this->bbt_erase_shift); len += (len >> this->page_shift) * mtd->oobsize; - buf = kmalloc (len, GFP_KERNEL); + buf = vmalloc(len); if (!buf) { - printk (KERN_ERR "nand_bbt: Out of memory\n"); - kfree (this->bbt); + printk(KERN_ERR "nand_bbt: Out of memory\n"); + kfree(this->bbt); this->bbt = NULL; return -ENOMEM; } /* Is the bbt at a given page ? */ if (td->options & NAND_BBT_ABSPAGE) { - res = read_abs_bbts (mtd, buf, td, md); + res = read_abs_bbts(mtd, buf, td, md); } else { /* Search the bad block table using a pattern in oob */ - res = search_read_bbts (mtd, buf, td, md); + res = search_read_bbts(mtd, buf, td, md); } if (res) - res = check_create (mtd, buf, bd); + res = check_create(mtd, buf, bd); /* Prevent the bbt regions from erasing / writing */ - mark_bbt_region (mtd, td); + mark_bbt_region(mtd, td); if (md) - mark_bbt_region (mtd, md); + mark_bbt_region(mtd, md); - kfree (buf); + vfree(buf); return res; } - /** * nand_update_bbt - [NAND Interface] update bad block table(s) * @mtd: MTD device structure @@ -909,7 +1020,7 @@ int nand_scan_bbt (struct mtd_info *mtd, * * The function updates the bad block table(s) */ -int nand_update_bbt (struct mtd_info *mtd, loff_t offs) +int nand_update_bbt(struct mtd_info *mtd, loff_t offs) { struct nand_chip *this = mtd->priv; int len, res = 0, writeops = 0; @@ -925,9 +1036,9 @@ int nand_update_bbt (struct mtd_info *mt /* Allocate a temporary buffer for one eraseblock incl. oob */ len = (1 << this->bbt_erase_shift); len += (len >> this->page_shift) * mtd->oobsize; - buf = kmalloc (len, GFP_KERNEL); + buf = kmalloc(len, GFP_KERNEL); if (!buf) { - printk (KERN_ERR "nand_update_bbt: Out of memory\n"); + printk(KERN_ERR "nand_update_bbt: Out of memory\n"); return -ENOMEM; } @@ -935,7 +1046,7 @@ int nand_update_bbt (struct mtd_info *mt /* Do we have a bbt per chip ? */ if (td->options & NAND_BBT_PERCHIP) { - chip = (int) (offs >> this->chip_shift); + chip = (int)(offs >> this->chip_shift); chipsel = chip; } else { chip = 0; @@ -948,17 +1059,17 @@ int nand_update_bbt (struct mtd_info *mt /* Write the bad block table to the device ? */ if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { - res = write_bbt (mtd, buf, td, md, chipsel); + res = write_bbt(mtd, buf, td, md, chipsel); if (res < 0) goto out; } /* Write the mirror bad block table to the device ? */ if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { - res = write_bbt (mtd, buf, md, td, chipsel); + res = write_bbt(mtd, buf, md, td, chipsel); } -out: - kfree (buf); + out: + kfree(buf); return res; } @@ -981,14 +1092,14 @@ static struct nand_bbt_descr largepage_m }; static struct nand_bbt_descr smallpage_flashbased = { - .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES, + .options = NAND_BBT_SCAN2NDPAGE, .offs = 5, .len = 1, .pattern = scan_ff_pattern }; static struct nand_bbt_descr largepage_flashbased = { - .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES, + .options = NAND_BBT_SCAN2NDPAGE, .offs = 0, .len = 2, .pattern = scan_ff_pattern @@ -1036,7 +1147,7 @@ static struct nand_bbt_descr bbt_mirror_ * support for the device and calls the nand_scan_bbt function * */ -int nand_default_bbt (struct mtd_info *mtd) +int nand_default_bbt(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; @@ -1046,7 +1157,7 @@ int nand_default_bbt (struct mtd_info *m * of the good / bad information, so we _must_ store * this information in a good / bad table during * startup - */ + */ if (this->options & NAND_IS_AND) { /* Use the default pattern descriptors */ if (!this->bbt_td) { @@ -1054,10 +1165,9 @@ int nand_default_bbt (struct mtd_info *m this->bbt_md = &bbt_mirror_descr; } this->options |= NAND_USE_FLASH_BBT; - return nand_scan_bbt (mtd, &agand_flashbased); + return nand_scan_bbt(mtd, &agand_flashbased); } - /* Is a flash based bad block table requested ? */ if (this->options & NAND_USE_FLASH_BBT) { /* Use the default pattern descriptors */ @@ -1066,18 +1176,17 @@ int nand_default_bbt (struct mtd_info *m this->bbt_md = &bbt_mirror_descr; } if (!this->badblock_pattern) { - this->badblock_pattern = (mtd->oobblock > 512) ? - &largepage_flashbased : &smallpage_flashbased; + this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased; } } else { this->bbt_td = NULL; this->bbt_md = NULL; if (!this->badblock_pattern) { - this->badblock_pattern = (mtd->oobblock > 512) ? - &largepage_memorybased : &smallpage_memorybased; + this->badblock_pattern = (mtd->writesize > 512) ? + &largepage_memorybased : &smallpage_memorybased; } } - return nand_scan_bbt (mtd, this->badblock_pattern); + return nand_scan_bbt(mtd, this->badblock_pattern); } /** @@ -1087,26 +1196,29 @@ int nand_default_bbt (struct mtd_info *m * @allowbbt: allow access to bad block table region * */ -int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt) +int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) { struct nand_chip *this = mtd->priv; int block; - uint8_t res; + uint8_t res; /* Get block number * 2 */ - block = (int) (offs >> (this->bbt_erase_shift - 1)); + block = (int)(offs >> (this->bbt_erase_shift - 1)); res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; - DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", - (unsigned int)offs, block >> 1, res); + DEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", + (unsigned int)offs, block >> 1, res); switch ((int)res) { - case 0x00: return 0; - case 0x01: return 1; - case 0x02: return allowbbt ? 0 : 1; + case 0x00: + return 0; + case 0x01: + return 1; + case 0x02: + return allowbbt ? 0 : 1; } return 1; } -EXPORT_SYMBOL (nand_scan_bbt); -EXPORT_SYMBOL (nand_default_bbt); +EXPORT_SYMBOL(nand_scan_bbt); +EXPORT_SYMBOL(nand_default_bbt); diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index 40ac909..2a163e4 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c @@ -7,6 +7,8 @@ * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) * Toshiba America Electronics Components, Inc. * + * Copyright (C) 2006 Thomas Gleixner + * * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $ * * This file is free software; you can redistribute it and/or modify it @@ -62,90 +64,76 @@ static const u_char nand_ecc_precalc_tab 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 }; - /** - * nand_trans_result - [GENERIC] create non-inverted ECC - * @reg2: line parity reg 2 - * @reg3: line parity reg 3 - * @ecc_code: ecc - * - * Creates non-inverted ECC code from line parity - */ -static void nand_trans_result(u_char reg2, u_char reg3, - u_char *ecc_code) -{ - u_char a, b, i, tmp1, tmp2; - - /* Initialize variables */ - a = b = 0x80; - tmp1 = tmp2 = 0; - - /* Calculate first ECC byte */ - for (i = 0; i < 4; i++) { - if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ - tmp1 |= b; - b >>= 1; - if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ - tmp1 |= b; - b >>= 1; - a >>= 1; - } - - /* Calculate second ECC byte */ - b = 0x80; - for (i = 0; i < 4; i++) { - if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */ - tmp2 |= b; - b >>= 1; - if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ - tmp2 |= b; - b >>= 1; - a >>= 1; - } - - /* Store two of the ECC bytes */ - ecc_code[0] = tmp1; - ecc_code[1] = tmp2; -} - -/** - * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block + * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code + * for 256 byte block * @mtd: MTD block structure * @dat: raw data * @ecc_code: buffer for ECC */ -int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) +int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, + u_char *ecc_code) { - u_char idx, reg1, reg2, reg3; - int j; + uint8_t idx, reg1, reg2, reg3, tmp1, tmp2; + int i; /* Initialize variables */ reg1 = reg2 = reg3 = 0; - ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; /* Build up column parity */ - for(j = 0; j < 256; j++) { - + for(i = 0; i < 256; i++) { /* Get CP0 - CP5 from table */ - idx = nand_ecc_precalc_table[dat[j]]; + idx = nand_ecc_precalc_table[*dat++]; reg1 ^= (idx & 0x3f); /* All bit XOR = 1 ? */ if (idx & 0x40) { - reg3 ^= (u_char) j; - reg2 ^= ~((u_char) j); + reg3 ^= (uint8_t) i; + reg2 ^= ~((uint8_t) i); } } /* Create non-inverted ECC code from line parity */ - nand_trans_result(reg2, reg3, ecc_code); + tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */ + tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */ + tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */ + tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */ + tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */ + tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */ + tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */ + tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */ + + tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */ + tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */ + tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */ + tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */ + tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */ + tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */ + tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */ + tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */ /* Calculate final ECC code */ - ecc_code[0] = ~ecc_code[0]; - ecc_code[1] = ~ecc_code[1]; +#ifdef CONFIG_NAND_ECC_SMC + ecc_code[0] = ~tmp2; + ecc_code[1] = ~tmp1; +#else + ecc_code[0] = ~tmp1; + ecc_code[1] = ~tmp2; +#endif ecc_code[2] = ((~reg1) << 2) | 0x03; + return 0; } +EXPORT_SYMBOL(nand_calculate_ecc); + +static inline int countbits(uint32_t byte) +{ + int res = 0; + + for (;byte; byte >>= 1) + res += byte & 0x01; + return res; +} /** * nand_correct_data - [NAND Interface] Detect and correct bit error(s) @@ -156,93 +144,54 @@ int nand_calculate_ecc(struct mtd_info * * * Detect and correct a 1 bit error for 256 byte block */ -int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) +int nand_correct_data(struct mtd_info *mtd, u_char *dat, + u_char *read_ecc, u_char *calc_ecc) { - u_char a, b, c, d1, d2, d3, add, bit, i; + uint8_t s0, s1, s2; + +#ifdef CONFIG_NAND_ECC_SMC + s0 = calc_ecc[0] ^ read_ecc[0]; + s1 = calc_ecc[1] ^ read_ecc[1]; + s2 = calc_ecc[2] ^ read_ecc[2]; +#else + s1 = calc_ecc[0] ^ read_ecc[0]; + s0 = calc_ecc[1] ^ read_ecc[1]; + s2 = calc_ecc[2] ^ read_ecc[2]; +#endif + if ((s0 | s1 | s2) == 0) + return 0; - /* Do error detection */ - d1 = calc_ecc[0] ^ read_ecc[0]; - d2 = calc_ecc[1] ^ read_ecc[1]; - d3 = calc_ecc[2] ^ read_ecc[2]; + /* Check for a single bit error */ + if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 && + ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 && + ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) { - if ((d1 | d2 | d3) == 0) { - /* No errors */ - return 0; - } - else { - a = (d1 ^ (d1 >> 1)) & 0x55; - b = (d2 ^ (d2 >> 1)) & 0x55; - c = (d3 ^ (d3 >> 1)) & 0x54; - - /* Found and will correct single bit error in the data */ - if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { - c = 0x80; - add = 0; - a = 0x80; - for (i=0; i<4; i++) { - if (d1 & c) - add |= a; - c >>= 2; - a >>= 1; - } - c = 0x80; - for (i=0; i<4; i++) { - if (d2 & c) - add |= a; - c >>= 2; - a >>= 1; - } - bit = 0; - b = 0x04; - c = 0x80; - for (i=0; i<3; i++) { - if (d3 & c) - bit |= b; - c >>= 2; - b >>= 1; - } - b = 0x01; - a = dat[add]; - a ^= (b << bit); - dat[add] = a; - return 1; - } - else { - i = 0; - while (d1) { - if (d1 & 0x01) - ++i; - d1 >>= 1; - } - while (d2) { - if (d2 & 0x01) - ++i; - d2 >>= 1; - } - while (d3) { - if (d3 & 0x01) - ++i; - d3 >>= 1; - } - if (i == 1) { - /* ECC Code Error Correction */ - read_ecc[0] = calc_ecc[0]; - read_ecc[1] = calc_ecc[1]; - read_ecc[2] = calc_ecc[2]; - return 2; - } - else { - /* Uncorrectable Error */ - return -1; - } - } + uint32_t byteoffs, bitnum; + + byteoffs = (s1 << 0) & 0x80; + byteoffs |= (s1 << 1) & 0x40; + byteoffs |= (s1 << 2) & 0x20; + byteoffs |= (s1 << 3) & 0x10; + + byteoffs |= (s0 >> 4) & 0x08; + byteoffs |= (s0 >> 3) & 0x04; + byteoffs |= (s0 >> 2) & 0x02; + byteoffs |= (s0 >> 1) & 0x01; + + bitnum = (s2 >> 5) & 0x04; + bitnum |= (s2 >> 4) & 0x02; + bitnum |= (s2 >> 3) & 0x01; + + dat[byteoffs] ^= (1 << bitnum); + + return 1; } - /* Should never happen */ + if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1) + return 1; + return -1; } - -EXPORT_SYMBOL(nand_calculate_ecc); EXPORT_SYMBOL(nand_correct_data); MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index dbc7e55..2e2cdf2 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -18,99 +18,110 @@ #include * Name. ID code, pagesize, chipsize in MegaByte, eraseblock size, * options * -* Pagesize; 0, 256, 512 -* 0 get this information from the extended chip ID +* Pagesize; 0, 256, 512 +* 0 get this information from the extended chip ID + 256 256 Byte page size * 512 512 Byte page size */ struct nand_flash_dev nand_flash_ids[] = { - {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, - {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0}, - {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0}, - {"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0}, - {"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0}, - {"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0}, - {"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0}, - {"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0}, - {"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0}, - {"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0}, - - {"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0}, - {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0}, - {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16}, - {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16}, - - {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0}, - {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0}, - {"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16}, - {"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16}, - - {"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0}, - {"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0}, - {"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16}, - {"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16}, - - {"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0}, - {"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0}, - {"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16}, - {"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16}, - - {"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0}, - {"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0}, - {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0}, - {"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16}, - {"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16}, - {"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16}, - {"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16}, - - {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0}, - - /* These are the new chips with large page size. The pagesize - * and the erasesize is determined from the extended id bytes - */ + {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, + {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0}, + {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0}, + {"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0}, + {"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0}, + {"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0}, + {"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0}, + {"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0}, + {"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0}, + {"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0}, + + {"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0}, + {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0}, + {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16}, + {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16}, + + {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0}, + {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0}, + {"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16}, + {"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16}, + + {"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0}, + {"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0}, + {"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16}, + {"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16}, + + {"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0}, + {"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0}, + {"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16}, + {"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16}, + + {"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0}, + {"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0}, + {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0}, + {"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16}, + {"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16}, + {"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16}, + {"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16}, + + {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0}, + + /* + * These are the new chips with large page size. The pagesize and the + * erasesize is determined from the extended id bytes + */ +#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR) +#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16) + /*512 Megabit */ - {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, - {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS}, + {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS}, + {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16}, + {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16}, /* 1 Gigabit */ - {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, - {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS}, + {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, LP_OPTIONS}, + {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16}, + {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16}, /* 2 Gigabit */ - {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, - {"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, LP_OPTIONS}, + {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, LP_OPTIONS}, + {"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, LP_OPTIONS16}, + {"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, LP_OPTIONS16}, /* 4 Gigabit */ - {"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, - {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + {"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, LP_OPTIONS}, + {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, LP_OPTIONS}, + {"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, LP_OPTIONS16}, + {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, LP_OPTIONS16}, /* 8 Gigabit */ - {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, - {"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, + {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, LP_OPTIONS}, + {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, LP_OPTIONS}, + {"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, LP_OPTIONS16}, + {"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, LP_OPTIONS16}, /* 16 Gigabit */ - {"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, - {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, - {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, - - /* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout ! - * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes - * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 - * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go - * There are more speed improvements for reads and writes possible, but not implemented now + {"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, LP_OPTIONS}, + {"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, LP_OPTIONS}, + {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16}, + {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, + + /* + * Renesas AND 1 Gigabit. Those chips do not support extended id and + * have a strange page/block layout ! The chosen minimum erasesize is + * 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page + * planes 1 block = 2 pages, but due to plane arrangement the blocks + * 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 Anyway JFFS2 would + * increase the eraseblock size so we chose a combined one which can be + * erased in one go There are more speed improvements for reads and + * writes possible, but not implemented now */ - {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH}, + {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, + NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY | + BBT_AUTO_REFRESH + }, {NULL,} }; @@ -125,13 +136,13 @@ struct nand_manufacturers nand_manuf_ids {NAND_MFR_NATIONAL, "National"}, {NAND_MFR_RENESAS, "Renesas"}, {NAND_MFR_STMICRO, "ST Micro"}, - {NAND_MFR_HYNIX, "Hynix"}, + {NAND_MFR_HYNIX, "Hynix"}, {0x0, "Unknown"} }; -EXPORT_SYMBOL (nand_manuf_ids); -EXPORT_SYMBOL (nand_flash_ids); +EXPORT_SYMBOL(nand_manuf_ids); +EXPORT_SYMBOL(nand_flash_ids); -MODULE_LICENSE ("GPL"); -MODULE_AUTHOR ("Thomas Gleixner "); -MODULE_DESCRIPTION ("Nand device & manufacturer ID's"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Thomas Gleixner "); +MODULE_DESCRIPTION("Nand device & manufacturer IDs"); diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index a0af92c..ebd64ab 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -369,7 +369,7 @@ init_nandsim(struct mtd_info *mtd) /* Initialize the NAND flash parameters */ ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8; ns->geom.totsz = mtd->size; - ns->geom.pgsz = mtd->oobblock; + ns->geom.pgsz = mtd->writesize; ns->geom.oobsz = mtd->oobsize; ns->geom.secsz = mtd->erasesize; ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; @@ -1071,68 +1071,6 @@ switch_state(struct nandsim *ns) } } -static void -ns_hwcontrol(struct mtd_info *mtd, int cmd) -{ - struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; - - switch (cmd) { - - /* set CLE line high */ - case NAND_CTL_SETCLE: - NS_DBG("ns_hwcontrol: start command latch cycles\n"); - ns->lines.cle = 1; - break; - - /* set CLE line low */ - case NAND_CTL_CLRCLE: - NS_DBG("ns_hwcontrol: stop command latch cycles\n"); - ns->lines.cle = 0; - break; - - /* set ALE line high */ - case NAND_CTL_SETALE: - NS_DBG("ns_hwcontrol: start address latch cycles\n"); - ns->lines.ale = 1; - break; - - /* set ALE line low */ - case NAND_CTL_CLRALE: - NS_DBG("ns_hwcontrol: stop address latch cycles\n"); - ns->lines.ale = 0; - break; - - /* set WP line high */ - case NAND_CTL_SETWP: - NS_DBG("ns_hwcontrol: enable write protection\n"); - ns->lines.wp = 1; - break; - - /* set WP line low */ - case NAND_CTL_CLRWP: - NS_DBG("ns_hwcontrol: disable write protection\n"); - ns->lines.wp = 0; - break; - - /* set CE line low */ - case NAND_CTL_SETNCE: - NS_DBG("ns_hwcontrol: enable chip\n"); - ns->lines.ce = 1; - break; - - /* set CE line high */ - case NAND_CTL_CLRNCE: - NS_DBG("ns_hwcontrol: disable chip\n"); - ns->lines.ce = 0; - break; - - default: - NS_ERR("hwcontrol: unknown command\n"); - } - - return; -} - static u_char ns_nand_read_byte(struct mtd_info *mtd) { @@ -1359,6 +1297,18 @@ ns_nand_write_byte(struct mtd_info *mtd, return; } +static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask) +{ + struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv; + + ns->lines.cle = bitmask & NAND_CLE ? 1 : 0; + ns->lines.ale = bitmask & NAND_ALE ? 1 : 0; + ns->lines.ce = bitmask & NAND_NCE ? 1 : 0; + + if (cmd != NAND_CMD_NONE) + ns_nand_write_byte(mtd, cmd); +} + static int ns_device_ready(struct mtd_info *mtd) { @@ -1377,17 +1327,6 @@ ns_nand_read_word(struct mtd_info *mtd) } static void -ns_nand_write_word(struct mtd_info *mtd, uint16_t word) -{ - struct nand_chip *chip = (struct nand_chip *)mtd->priv; - - NS_DBG("write_word\n"); - - chip->write_byte(mtd, word & 0xFF); - chip->write_byte(mtd, word >> 8); -} - -static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; @@ -1514,16 +1453,14 @@ static int __init ns_init_module(void) /* * Register simulator's callbacks. */ - chip->hwcontrol = ns_hwcontrol; + chip->cmd_ctrl = ns_hwcontrol; chip->read_byte = ns_nand_read_byte; chip->dev_ready = ns_device_ready; - chip->write_byte = ns_nand_write_byte; chip->write_buf = ns_nand_write_buf; chip->read_buf = ns_nand_read_buf; chip->verify_buf = ns_nand_verify_buf; - chip->write_word = ns_nand_write_word; chip->read_word = ns_nand_read_word; - chip->eccmode = NAND_ECC_SOFT; + chip->ecc.mode = NAND_ECC_SOFT; chip->options |= NAND_SKIP_BBTSCAN; /* @@ -1546,6 +1483,8 @@ static int __init ns_init_module(void) chip->options |= NAND_BUSWIDTH_16; } + nsmtd->owner = THIS_MODULE; + if ((retval = nand_scan(nsmtd, 1)) != 0) { NS_ERR("can't register NAND Simulator\n"); if (retval > 0) diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c new file mode 100644 index 0000000..fe8d385 --- /dev/null +++ b/drivers/mtd/nand/ndfc.c @@ -0,0 +1,311 @@ +/* + * drivers/mtd/ndfc.c + * + * Overview: + * Platform independend driver for NDFC (NanD Flash Controller) + * integrated into EP440 cores + * + * Author: Thomas Gleixner + * + * Copyright 2006 IBM + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct ndfc_nand_mtd { + struct mtd_info mtd; + struct nand_chip chip; + struct platform_nand_chip *pl_chip; +}; + +static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS]; + +struct ndfc_controller { + void __iomem *ndfcbase; + struct nand_hw_control ndfc_control; + atomic_t childs_active; +}; + +static struct ndfc_controller ndfc_ctrl; + +static void ndfc_select_chip(struct mtd_info *mtd, int chip) +{ + uint32_t ccr; + struct ndfc_controller *ndfc = &ndfc_ctrl; + struct nand_chip *nandchip = mtd->priv; + struct ndfc_nand_mtd *nandmtd = nandchip->priv; + struct platform_nand_chip *pchip = nandmtd->pl_chip; + + ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR); + if (chip >= 0) { + ccr &= ~NDFC_CCR_BS_MASK; + ccr |= NDFC_CCR_BS(chip + pchip->chip_offset); + } else + ccr |= NDFC_CCR_RESET_CE; + writel(ccr, ndfc->ndfcbase + NDFC_CCR); +} + +static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *chip = mtd->priv; + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_CMD); + else + writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_ALE); +} + +static int ndfc_ready(struct mtd_info *mtd) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + + return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; +} + +static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) +{ + uint32_t ccr; + struct ndfc_controller *ndfc = &ndfc_ctrl; + + ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR); + ccr |= NDFC_CCR_RESET_ECC; + __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR); + wmb(); +} + +static int ndfc_calculate_ecc(struct mtd_info *mtd, + const u_char *dat, u_char *ecc_code) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + uint32_t ecc; + uint8_t *p = (uint8_t *)&ecc; + + wmb(); + ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC); + ecc_code[0] = p[1]; + ecc_code[1] = p[2]; + ecc_code[2] = p[3]; + + return 0; +} + +/* + * Speedups for buffer read/write/verify + * + * NDFC allows 32bit read/write of data. So we can speed up the buffer + * functions. No further checking, as nand_base will always read/write + * page aligned. + */ +static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + uint32_t *p = (uint32_t *) buf; + + for(;len > 0; len -= 4) + *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA); +} + +static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + uint32_t *p = (uint32_t *) buf; + + for(;len > 0; len -= 4) + __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA); +} + +static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + uint32_t *p = (uint32_t *) buf; + + for(;len > 0; len -= 4) + if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA)) + return -EFAULT; + return 0; +} + +/* + * Initialize chip structure + */ +static void ndfc_chip_init(struct ndfc_nand_mtd *mtd) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + struct nand_chip *chip = &mtd->chip; + + chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; + chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA; + chip->cmd_ctrl = ndfc_hwcontrol; + chip->dev_ready = ndfc_ready; + chip->select_chip = ndfc_select_chip; + chip->chip_delay = 50; + chip->priv = mtd; + chip->options = mtd->pl_chip->options; + chip->controller = &ndfc->ndfc_control; + chip->read_buf = ndfc_read_buf; + chip->write_buf = ndfc_write_buf; + chip->verify_buf = ndfc_verify_buf; + chip->ecc.correct = nand_correct_data; + chip->ecc.hwctl = ndfc_enable_hwecc; + chip->ecc.calculate = ndfc_calculate_ecc; + chip->ecc.mode = NAND_ECC_HW; + chip->ecc.size = 256; + chip->ecc.bytes = 3; + chip->ecclayout = mtd->pl_chip->ecclayout; + mtd->mtd.priv = chip; + mtd->mtd.owner = THIS_MODULE; +} + +static int ndfc_chip_probe(struct platform_device *pdev) +{ + struct platform_nand_chip *nc = pdev->dev.platform_data; + struct ndfc_chip_settings *settings = nc->priv; + struct ndfc_controller *ndfc = &ndfc_ctrl; + struct ndfc_nand_mtd *nandmtd; + + if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS) + return -EINVAL; + + /* Set the bank settings */ + __raw_writel(settings->bank_settings, + ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2)); + + nandmtd = &ndfc_mtd[pdev->id]; + if (nandmtd->pl_chip) + return -EBUSY; + + nandmtd->pl_chip = nc; + ndfc_chip_init(nandmtd); + + /* Scan for chips */ + if (nand_scan(&nandmtd->mtd, nc->nr_chips)) { + nandmtd->pl_chip = NULL; + return -ENODEV; + } + +#ifdef CONFIG_MTD_PARTITIONS + printk("Number of partitions %d\n", nc->nr_partitions); + if (nc->nr_partitions) { + /* Add the full device, so complete dumps can be made */ + add_mtd_device(&nandmtd->mtd); + add_mtd_partitions(&nandmtd->mtd, nc->partitions, + nc->nr_partitions); + + } else +#else + add_mtd_device(&nandmtd->mtd); +#endif + + atomic_inc(&ndfc->childs_active); + return 0; +} + +static int ndfc_chip_remove(struct platform_device *pdev) +{ + return 0; +} + +static int ndfc_nand_probe(struct platform_device *pdev) +{ + struct platform_nand_ctrl *nc = pdev->dev.platform_data; + struct ndfc_controller_settings *settings = nc->priv; + struct resource *res = pdev->resource; + struct ndfc_controller *ndfc = &ndfc_ctrl; + unsigned long long phys = settings->ndfc_erpn | res->start; + + ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1); + if (!ndfc->ndfcbase) { + printk(KERN_ERR "NDFC: ioremap failed\n"); + return -EIO; + } + + __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR); + + spin_lock_init(&ndfc->ndfc_control.lock); + init_waitqueue_head(&ndfc->ndfc_control.wq); + + platform_set_drvdata(pdev, ndfc); + + printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n", + __raw_readl(ndfc->ndfcbase + NDFC_REVID)); + + return 0; +} + +static int ndfc_nand_remove(struct platform_device *pdev) +{ + struct ndfc_controller *ndfc = platform_get_drvdata(pdev); + + if (atomic_read(&ndfc->childs_active)) + return -EBUSY; + + if (ndfc) { + platform_set_drvdata(pdev, NULL); + iounmap(ndfc_ctrl.ndfcbase); + ndfc_ctrl.ndfcbase = NULL; + } + return 0; +} + +/* driver device registration */ + +static struct platform_driver ndfc_chip_driver = { + .probe = ndfc_chip_probe, + .remove = ndfc_chip_remove, + .driver = { + .name = "ndfc-chip", + .owner = THIS_MODULE, + }, +}; + +static struct platform_driver ndfc_nand_driver = { + .probe = ndfc_nand_probe, + .remove = ndfc_nand_remove, + .driver = { + .name = "ndfc-nand", + .owner = THIS_MODULE, + }, +}; + +static int __init ndfc_nand_init(void) +{ + int ret; + + spin_lock_init(&ndfc_ctrl.ndfc_control.lock); + init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq); + + ret = platform_driver_register(&ndfc_nand_driver); + if (!ret) + ret = platform_driver_register(&ndfc_chip_driver); + return ret; +} + +static void __exit ndfc_nand_exit(void) +{ + platform_driver_unregister(&ndfc_chip_driver); + platform_driver_unregister(&ndfc_nand_driver); +} + +module_init(ndfc_nand_init); +module_exit(ndfc_nand_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Thomas Gleixner "); +MODULE_DESCRIPTION("Platform driver for NDFC"); diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c index 91a95f3..22fa65c 100644 --- a/drivers/mtd/nand/ppchameleonevb.c +++ b/drivers/mtd/nand/ppchameleonevb.c @@ -58,21 +58,21 @@ #define NAND_EVB_RB_GPIO_PIN (0x8000000 /* * MTD structure for PPChameleonEVB board */ -static struct mtd_info *ppchameleon_mtd = NULL; +static struct mtd_info *ppchameleon_mtd = NULL; static struct mtd_info *ppchameleonevb_mtd = NULL; /* * Module stuff */ -static unsigned long ppchameleon_fio_pbase = CFG_NAND0_PADDR; +static unsigned long ppchameleon_fio_pbase = CFG_NAND0_PADDR; static unsigned long ppchameleonevb_fio_pbase = CFG_NAND1_PADDR; #ifdef MODULE module_param(ppchameleon_fio_pbase, ulong, 0); module_param(ppchameleonevb_fio_pbase, ulong, 0); #else -__setup("ppchameleon_fio_pbase=",ppchameleon_fio_pbase); -__setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase); +__setup("ppchameleon_fio_pbase=", ppchameleon_fio_pbase); +__setup("ppchameleonevb_fio_pbase=", ppchameleonevb_fio_pbase); #endif #ifdef CONFIG_MTD_PARTITIONS @@ -80,82 +80,96 @@ #ifdef CONFIG_MTD_PARTITIONS * Define static partitions for flash devices */ static struct mtd_partition partition_info_hi[] = { - { name: "PPChameleon HI Nand Flash", - offset: 0, - size: 128*1024*1024 } + { .name = "PPChameleon HI Nand Flash", + offset = 0, + .size = 128 * 1024 * 1024 + } }; static struct mtd_partition partition_info_me[] = { - { name: "PPChameleon ME Nand Flash", - offset: 0, - size: 32*1024*1024 } + { .name = "PPChameleon ME Nand Flash", + .offset = 0, + .size = 32 * 1024 * 1024 + } }; static struct mtd_partition partition_info_evb[] = { - { name: "PPChameleonEVB Nand Flash", - offset: 0, - size: 32*1024*1024 } + { .name = "PPChameleonEVB Nand Flash", + .offset = 0, + .size = 32 * 1024 * 1024 + } }; #define NUM_PARTITIONS 1 -extern int parse_cmdline_partitions(struct mtd_info *master, - struct mtd_partition **pparts, - const char *mtd_id); +extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id); #endif - /* * hardware specific access to control-lines */ -static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd) +static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd, + unsigned int ctrl) { - switch(cmd) { - - case NAND_CTL_SETCLE: - MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR); - break; - case NAND_CTL_CLRCLE: - MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR); - break; - case NAND_CTL_SETALE: - MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR); - break; - case NAND_CTL_CLRALE: - MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR); - break; - case NAND_CTL_SETNCE: + struct nand_chip *chip = mtd->priv; + + if (ctrl & NAND_CTRL_CHANGE) { +#error Missing headerfiles. No way to fix this. -tglx + switch (cmd) { + case NAND_CTL_SETCLE: + MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR); + break; + case NAND_CTL_CLRCLE: + MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR); + break; + case NAND_CTL_SETALE: + MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR); + break; + case NAND_CTL_CLRALE: + MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR); + break; + case NAND_CTL_SETNCE: MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR); - break; - case NAND_CTL_CLRNCE: + break; + case NAND_CTL_CLRNCE: MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR); - break; + break; + } } + if (cmd != NAND_CMD_NONE) + writeb(cmd, chip->IO_ADDR_W); } -static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd) +static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd, + unsigned int ctrl) { - switch(cmd) { - - case NAND_CTL_SETCLE: - MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR); - break; - case NAND_CTL_CLRCLE: - MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR); - break; - case NAND_CTL_SETALE: - MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR); - break; - case NAND_CTL_CLRALE: - MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR); - break; - case NAND_CTL_SETNCE: - MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR); - break; - case NAND_CTL_CLRNCE: - MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR); - break; + struct nand_chip *chip = mtd->priv; + + if (ctrl & NAND_CTRL_CHANGE) { +#error Missing headerfiles. No way to fix this. -tglx + switch (cmd) { + case NAND_CTL_SETCLE: + MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR); + break; + case NAND_CTL_CLRCLE: + MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR); + break; + case NAND_CTL_SETALE: + MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR); + break; + case NAND_CTL_CLRALE: + MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR); + break; + case NAND_CTL_SETNCE: + MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR); + break; + case NAND_CTL_CLRNCE: + MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR); + break; + } } + if (cmd != NAND_CMD_NONE) + writeb(cmd, chip->IO_ADDR_W); } #ifdef USE_READY_BUSY_PIN @@ -164,15 +178,15 @@ #ifdef USE_READY_BUSY_PIN */ static int ppchameleon_device_ready(struct mtd_info *minfo) { - if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_RB_GPIO_PIN) + if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_RB_GPIO_PIN) return 1; return 0; } static int ppchameleonevb_device_ready(struct mtd_info *minfo) { - if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN) - return 1; + if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN) + return 1; return 0; } #endif @@ -185,7 +199,7 @@ #endif /* * Main initialization routine */ -static int __init ppchameleonevb_init (void) +static int __init ppchameleonevb_init(void) { struct nand_chip *this; const char *part_type = 0; @@ -194,13 +208,11 @@ static int __init ppchameleonevb_init (v void __iomem *ppchameleon_fio_base; void __iomem *ppchameleonevb_fio_base; - /********************************* * Processor module NAND (if any) * *********************************/ /* Allocate memory for MTD device structure and private data */ - ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + - sizeof(struct nand_chip), GFP_KERNEL); + ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!ppchameleon_mtd) { printk("Unable to allocate PPChameleon NAND MTD device structure.\n"); return -ENOMEM; @@ -208,63 +220,65 @@ static int __init ppchameleonevb_init (v /* map physical address */ ppchameleon_fio_base = ioremap(ppchameleon_fio_pbase, SZ_4M); - if(!ppchameleon_fio_base) { + if (!ppchameleon_fio_base) { printk("ioremap PPChameleon NAND flash failed\n"); kfree(ppchameleon_mtd); return -EIO; } /* Get pointer to private data */ - this = (struct nand_chip *) (&ppchameleon_mtd[1]); + this = (struct nand_chip *)(&ppchameleon_mtd[1]); /* Initialize structures */ - memset((char *) ppchameleon_mtd, 0, sizeof(struct mtd_info)); - memset((char *) this, 0, sizeof(struct nand_chip)); + memset(ppchameleon_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ ppchameleon_mtd->priv = this; + ppchameleon_mtd->owner = THIS_MODULE; - /* Initialize GPIOs */ + /* Initialize GPIOs */ /* Pin mapping for NAND chip */ /* - CE GPIO_01 - CLE GPIO_02 - ALE GPIO_03 - R/B GPIO_04 - */ + CE GPIO_01 + CLE GPIO_02 + ALE GPIO_03 + R/B GPIO_04 + */ /* output select */ - out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xC0FFFFFF); + out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xC0FFFFFF); /* three-state select */ - out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xC0FFFFFF); + out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xC0FFFFFF); /* enable output driver */ - out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN); + out_be32((volatile unsigned *)GPIO0_TCR, + in_be32((volatile unsigned *)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN); #ifdef USE_READY_BUSY_PIN /* three-state select */ - out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFF3FFFFF); + out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFF3FFFFF); /* high-impedecence */ - out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_RB_GPIO_PIN)); + out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_RB_GPIO_PIN)); /* input select */ - out_be32((volatile unsigned*)GPIO0_ISR1H, (in_be32((volatile unsigned*)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000); + out_be32((volatile unsigned *)GPIO0_ISR1H, + (in_be32((volatile unsigned *)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000); #endif /* insert callbacks */ this->IO_ADDR_R = ppchameleon_fio_base; this->IO_ADDR_W = ppchameleon_fio_base; - this->hwcontrol = ppchameleon_hwcontrol; + this->cmd_ctrl = ppchameleon_hwcontrol; #ifdef USE_READY_BUSY_PIN this->dev_ready = ppchameleon_device_ready; #endif this->chip_delay = NAND_BIG_DELAY_US; /* ECC mode */ - this->eccmode = NAND_ECC_SOFT; + this->ecc.mode = NAND_ECC_SOFT; /* Scan to find existence of the device (it could not be mounted) */ - if (nand_scan (ppchameleon_mtd, 1)) { + if (nand_scan(ppchameleon_mtd, 1)) { iounmap((void *)ppchameleon_fio_base); - kfree (ppchameleon_mtd); + kfree(ppchameleon_mtd); goto nand_evb_init; } - #ifndef USE_READY_BUSY_PIN /* Adjust delay if necessary */ if (ppchameleon_mtd->size == NAND_SMALL_SIZE) @@ -275,12 +289,11 @@ #ifdef CONFIG_MTD_PARTITIONS ppchameleon_mtd->name = "ppchameleon-nand"; mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0); if (mtd_parts_nb > 0) - part_type = "command line"; + part_type = "command line"; else - mtd_parts_nb = 0; + mtd_parts_nb = 0; #endif - if (mtd_parts_nb == 0) - { + if (mtd_parts_nb == 0) { if (ppchameleon_mtd->size == NAND_SMALL_SIZE) mtd_parts = partition_info_me; else @@ -293,13 +306,12 @@ #endif printk(KERN_NOTICE "Using %s partition definition\n", part_type); add_mtd_partitions(ppchameleon_mtd, mtd_parts, mtd_parts_nb); -nand_evb_init: + nand_evb_init: /**************************** * EVB NAND (always present) * ****************************/ /* Allocate memory for MTD device structure and private data */ - ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + - sizeof(struct nand_chip), GFP_KERNEL); + ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!ppchameleonevb_mtd) { printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n"); return -ENOMEM; @@ -307,77 +319,76 @@ nand_evb_init: /* map physical address */ ppchameleonevb_fio_base = ioremap(ppchameleonevb_fio_pbase, SZ_4M); - if(!ppchameleonevb_fio_base) { + if (!ppchameleonevb_fio_base) { printk("ioremap PPChameleonEVB NAND flash failed\n"); kfree(ppchameleonevb_mtd); return -EIO; } /* Get pointer to private data */ - this = (struct nand_chip *) (&ppchameleonevb_mtd[1]); + this = (struct nand_chip *)(&ppchameleonevb_mtd[1]); /* Initialize structures */ - memset((char *) ppchameleonevb_mtd, 0, sizeof(struct mtd_info)); - memset((char *) this, 0, sizeof(struct nand_chip)); + memset(ppchameleonevb_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ ppchameleonevb_mtd->priv = this; - /* Initialize GPIOs */ + /* Initialize GPIOs */ /* Pin mapping for NAND chip */ /* - CE GPIO_14 - CLE GPIO_15 - ALE GPIO_16 - R/B GPIO_31 - */ + CE GPIO_14 + CLE GPIO_15 + ALE GPIO_16 + R/B GPIO_31 + */ /* output select */ - out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xFFFFFFF0); - out_be32((volatile unsigned*)GPIO0_OSRL, in_be32((volatile unsigned*)GPIO0_OSRL) & 0x3FFFFFFF); + out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xFFFFFFF0); + out_be32((volatile unsigned *)GPIO0_OSRL, in_be32((volatile unsigned *)GPIO0_OSRL) & 0x3FFFFFFF); /* three-state select */ - out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0); - out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF); + out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFFFFFFF0); + out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0x3FFFFFFF); /* enable output driver */ - out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | + out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN); #ifdef USE_READY_BUSY_PIN /* three-state select */ - out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0xFFFFFFFC); + out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0xFFFFFFFC); /* high-impedecence */ - out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN)); + out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN)); /* input select */ - out_be32((volatile unsigned*)GPIO0_ISR1L, (in_be32((volatile unsigned*)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001); + out_be32((volatile unsigned *)GPIO0_ISR1L, + (in_be32((volatile unsigned *)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001); #endif /* insert callbacks */ this->IO_ADDR_R = ppchameleonevb_fio_base; this->IO_ADDR_W = ppchameleonevb_fio_base; - this->hwcontrol = ppchameleonevb_hwcontrol; + this->cmd_ctrl = ppchameleonevb_hwcontrol; #ifdef USE_READY_BUSY_PIN this->dev_ready = ppchameleonevb_device_ready; #endif this->chip_delay = NAND_SMALL_DELAY_US; /* ECC mode */ - this->eccmode = NAND_ECC_SOFT; + this->ecc.mode = NAND_ECC_SOFT; /* Scan to find existence of the device */ - if (nand_scan (ppchameleonevb_mtd, 1)) { + if (nand_scan(ppchameleonevb_mtd, 1)) { iounmap((void *)ppchameleonevb_fio_base); - kfree (ppchameleonevb_mtd); + kfree(ppchameleonevb_mtd); return -ENXIO; } - #ifdef CONFIG_MTD_PARTITIONS ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME; mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0); if (mtd_parts_nb > 0) - part_type = "command line"; + part_type = "command line"; else - mtd_parts_nb = 0; + mtd_parts_nb = 0; #endif - if (mtd_parts_nb == 0) - { + if (mtd_parts_nb == 0) { mtd_parts = partition_info_evb; mtd_parts_nb = NUM_PARTITIONS; part_type = "static"; @@ -390,18 +401,19 @@ #endif /* Return happy */ return 0; } + module_init(ppchameleonevb_init); /* * Clean up routine */ -static void __exit ppchameleonevb_cleanup (void) +static void __exit ppchameleonevb_cleanup(void) { struct nand_chip *this; /* Release resources, unregister device(s) */ - nand_release (ppchameleon_mtd); - nand_release (ppchameleonevb_mtd); + nand_release(ppchameleon_mtd); + nand_release(ppchameleonevb_mtd); /* Release iomaps */ this = (struct nand_chip *) &ppchameleon_mtd[1]; diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c index 4129c03..f8c4964 100644 --- a/drivers/mtd/nand/rtc_from4.c +++ b/drivers/mtd/nand/rtc_from4.c @@ -97,12 +97,12 @@ #define RTC_FROM4_NO_VIRTBLOCKS 0 static void __iomem *rtc_from4_fio_base = (void *)P2SEGADDR(RTC_FROM4_FIO_BASE); static const struct mtd_partition partition_info[] = { - { - .name = "Renesas flash partition 1", - .offset = 0, - .size = MTDPART_SIZ_FULL - }, + { + .name = "Renesas flash partition 1", + .offset = 0, + .size = MTDPART_SIZ_FULL}, }; + #define NUM_PARTITIONS 1 /* @@ -111,8 +111,8 @@ #define NUM_PARTITIONS 1 * NAND_BBT_CREATE and/or NAND_BBT_WRITE * */ -static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; -static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; +static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' }; +static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' }; static struct nand_bbt_descr rtc_from4_bbt_main_descr = { .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE @@ -134,8 +134,6 @@ static struct nand_bbt_descr rtc_from4_b .pattern = mirror_pattern }; - - #ifdef RTC_FROM4_HWECC /* the Reed Solomon control structure */ @@ -144,15 +142,14 @@ static struct rs_control *rs_decoder; /* * hardware specific Out Of Band information */ -static struct nand_oobinfo rtc_from4_nand_oobinfo = { - .useecc = MTD_NANDECC_AUTOPLACE, +static struct nand_ecclayout rtc_from4_nand_oobinfo = { .eccbytes = 32, .eccpos = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31}, - .oobfree = { {32, 32} } + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31}, + .oobfree = {{32, 32}} }; /* Aargh. I missed the reversed bit order, when I @@ -162,44 +159,42 @@ static struct nand_oobinfo rtc_from4_nan * of the ecc byte which we get from the FPGA */ static uint8_t revbits[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, }; #endif - - /* * rtc_from4_hwcontrol - hardware specific access to control-lines * @mtd: MTD device structure @@ -212,35 +207,20 @@ #endif * Address lines (A24-A22), so no action is required here. * */ -static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd) +static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) { - struct nand_chip* this = (struct nand_chip *) (mtd->priv); - - switch(cmd) { + struct nand_chip *chip = (mtd->priv); - case NAND_CTL_SETCLE: - this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE); - break; - case NAND_CTL_CLRCLE: - this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE); - break; - - case NAND_CTL_SETALE: - this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE); - break; - case NAND_CTL_CLRALE: - this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE); - break; + if (cmd == NAND_CMD_NONE) + return; - case NAND_CTL_SETNCE: - break; - case NAND_CTL_CLRNCE: - break; - - } + if (ctrl & NAND_CLE) + writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_CLE); + else + writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_ALE); } - /* * rtc_from4_nand_select_chip - hardware specific chip select * @mtd: MTD device structure @@ -252,26 +232,25 @@ static void rtc_from4_hwcontrol(struct m */ static void rtc_from4_nand_select_chip(struct mtd_info *mtd, int chip) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd->priv; this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R & ~RTC_FROM4_NAND_ADDR_MASK); this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_NAND_ADDR_MASK); - switch(chip) { + switch (chip) { - case 0: /* select slot 3 chip */ + case 0: /* select slot 3 chip */ this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT3); this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT3); - break; - case 1: /* select slot 4 chip */ + break; + case 1: /* select slot 4 chip */ this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT4); this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT4); - break; + break; - } + } } - /* * rtc_from4_nand_device_ready - hardware specific ready/busy check * @mtd: MTD device structure @@ -290,7 +269,6 @@ static int rtc_from4_nand_device_ready(s } - /* * deplete - code to perform device recovery in case there was a power loss * @mtd: MTD device structure @@ -306,24 +284,23 @@ static int rtc_from4_nand_device_ready(s */ static void deplete(struct mtd_info *mtd, int chip) { - struct nand_chip *this = mtd->priv; + struct nand_chip *this = mtd->priv; - /* wait until device is ready */ - while (!this->dev_ready(mtd)); + /* wait until device is ready */ + while (!this->dev_ready(mtd)) ; this->select_chip(mtd, chip); /* Send the commands for device recovery, phase 1 */ - this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000); - this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1); + this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000); + this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1); /* Send the commands for device recovery, phase 2 */ - this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004); - this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1); + this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004); + this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1); } - #ifdef RTC_FROM4_HWECC /* * rtc_from4_enable_hwecc - hardware specific hardware ECC enable function @@ -335,39 +312,35 @@ #ifdef RTC_FROM4_HWECC */ static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode) { - volatile unsigned short * rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL); + volatile unsigned short *rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL); unsigned short status; switch (mode) { - case NAND_ECC_READ : - status = RTC_FROM4_RS_ECC_CTL_CLR - | RTC_FROM4_RS_ECC_CTL_FD_E; + case NAND_ECC_READ: + status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_FD_E; *rs_ecc_ctl = status; break; - case NAND_ECC_READSYN : - status = 0x00; + case NAND_ECC_READSYN: + status = 0x00; *rs_ecc_ctl = status; break; - case NAND_ECC_WRITE : - status = RTC_FROM4_RS_ECC_CTL_CLR - | RTC_FROM4_RS_ECC_CTL_GEN - | RTC_FROM4_RS_ECC_CTL_FD_E; + case NAND_ECC_WRITE: + status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_GEN | RTC_FROM4_RS_ECC_CTL_FD_E; *rs_ecc_ctl = status; break; - default: + default: BUG(); break; } } - /* * rtc_from4_calculate_ecc - hardware specific code to read ECC code * @mtd: MTD device structure @@ -383,7 +356,7 @@ static void rtc_from4_enable_hwecc(struc */ static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) { - volatile unsigned short * rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN); + volatile unsigned short *rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN); unsigned short value; int i; @@ -395,7 +368,6 @@ static void rtc_from4_calculate_ecc(stru ecc_code[7] |= 0x0f; /* set the last four bits (not used) */ } - /* * rtc_from4_correct_data - hardware specific code to correct data using ECC code * @mtd: MTD device structure @@ -414,7 +386,7 @@ static int rtc_from4_correct_data(struct unsigned short status; uint16_t par[6], syn[6]; uint8_t ecc[8]; - volatile unsigned short *rs_ecc; + volatile unsigned short *rs_ecc; status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CHK)); @@ -424,23 +396,18 @@ static int rtc_from4_correct_data(struct /* Read the syndrom pattern from the FPGA and correct the bitorder */ rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC); - for (i = 0; i < 8; i++) { - ecc[i] = revbits[(*rs_ecc) & 0xFF]; - rs_ecc++; - } + for (i = 0; i < 8; i++) { + ecc[i] = revbits[(*rs_ecc) & 0xFF]; + rs_ecc++; + } /* convert into 6 10bit syndrome fields */ - par[5] = rs_decoder->index_of[(((uint16_t)ecc[0] >> 0) & 0x0ff) | - (((uint16_t)ecc[1] << 8) & 0x300)]; - par[4] = rs_decoder->index_of[(((uint16_t)ecc[1] >> 2) & 0x03f) | - (((uint16_t)ecc[2] << 6) & 0x3c0)]; - par[3] = rs_decoder->index_of[(((uint16_t)ecc[2] >> 4) & 0x00f) | - (((uint16_t)ecc[3] << 4) & 0x3f0)]; - par[2] = rs_decoder->index_of[(((uint16_t)ecc[3] >> 6) & 0x003) | - (((uint16_t)ecc[4] << 2) & 0x3fc)]; - par[1] = rs_decoder->index_of[(((uint16_t)ecc[5] >> 0) & 0x0ff) | - (((uint16_t)ecc[6] << 8) & 0x300)]; - par[0] = (((uint16_t)ecc[6] >> 2) & 0x03f) | (((uint16_t)ecc[7] << 6) & 0x3c0); + par[5] = rs_decoder->index_of[(((uint16_t) ecc[0] >> 0) & 0x0ff) | (((uint16_t) ecc[1] << 8) & 0x300)]; + par[4] = rs_decoder->index_of[(((uint16_t) ecc[1] >> 2) & 0x03f) | (((uint16_t) ecc[2] << 6) & 0x3c0)]; + par[3] = rs_decoder->index_of[(((uint16_t) ecc[2] >> 4) & 0x00f) | (((uint16_t) ecc[3] << 4) & 0x3f0)]; + par[2] = rs_decoder->index_of[(((uint16_t) ecc[3] >> 6) & 0x003) | (((uint16_t) ecc[4] << 2) & 0x3fc)]; + par[1] = rs_decoder->index_of[(((uint16_t) ecc[5] >> 0) & 0x0ff) | (((uint16_t) ecc[6] << 8) & 0x300)]; + par[0] = (((uint16_t) ecc[6] >> 2) & 0x03f) | (((uint16_t) ecc[7] << 6) & 0x3c0); /* Convert to computable syndrome */ for (i = 0; i < 6; i++) { @@ -453,16 +420,14 @@ static int rtc_from4_correct_data(struct syn[i] = rs_decoder->index_of[syn[i]]; } - /* Let the library code do its magic.*/ - res = decode_rs8(rs_decoder, (uint8_t *)buf, par, 512, syn, 0, NULL, 0xff, NULL); + /* Let the library code do its magic. */ + res = decode_rs8(rs_decoder, (uint8_t *) buf, par, 512, syn, 0, NULL, 0xff, NULL); if (res > 0) { - DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " - "ECC corrected %d errors on read\n", res); + DEBUG(MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res); } return res; } - /** * rtc_from4_errstat - perform additional error status checks * @mtd: MTD device structure @@ -478,54 +443,66 @@ static int rtc_from4_correct_data(struct * note: see pages 34..37 of data sheet for details. * */ -static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page) +static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, + int state, int status, int page) { - int er_stat=0; - int rtn, retlen; - size_t len; + int er_stat = 0; + int rtn, retlen; + size_t len; uint8_t *buf; - int i; - - this->cmdfunc (mtd, NAND_CMD_STATUS_CLEAR, -1, -1); - - if (state == FL_ERASING) { - for (i=0; i<4; i++) { - if (status & 1<<(i+1)) { - this->cmdfunc (mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1); - rtn = this->read_byte(mtd); - this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1); - if (!(rtn & ERR_STAT_ECC_AVAILABLE)) { - er_stat |= 1<<(i+1); /* err_ecc_not_avail */ - } - } + int i; + + this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1); + + if (state == FL_ERASING) { + + for (i = 0; i < 4; i++) { + if (!(status & 1 << (i + 1))) + continue; + this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1), + -1, -1); + rtn = this->read_byte(mtd); + this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1); + + /* err_ecc_not_avail */ + if (!(rtn & ERR_STAT_ECC_AVAILABLE)) + er_stat |= 1 << (i + 1); } + } else if (state == FL_WRITING) { + + unsigned long corrected = mtd->ecc_stats.corrected; + /* single bank write logic */ - this->cmdfunc (mtd, NAND_CMD_STATUS_ERROR, -1, -1); + this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1); rtn = this->read_byte(mtd); - this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1); + this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1); + if (!(rtn & ERR_STAT_ECC_AVAILABLE)) { - er_stat |= 1<<1; /* err_ecc_not_avail */ - } else { - len = mtd->oobblock; - buf = kmalloc (len, GFP_KERNEL); - if (!buf) { - printk (KERN_ERR "rtc_from4_errstat: Out of memory!\n"); - er_stat = 1; /* if we can't check, assume failed */ - } else { - /* recovery read */ - /* page read */ - rtn = nand_do_read_ecc (mtd, page, len, &retlen, buf, NULL, this->autooob, 1); - if (rtn) { /* if read failed or > 1-bit error corrected */ - er_stat |= 1<<1; /* ECC read failed */ - } - kfree(buf); - } + /* err_ecc_not_avail */ + er_stat |= 1 << 1; + goto out; + } + + len = mtd->writesize; + buf = kmalloc(len, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n"); + er_stat = 1; + goto out; } + + /* recovery read */ + rtn = nand_do_read(mtd, page, len, &retlen, buf); + + /* if read failed or > 1-bit error corrected */ + if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) { + er_stat |= 1 << 1; + kfree(buf); } rtn = status; - if (er_stat == 0) { /* if ECC is available */ + if (er_stat == 0) { /* if ECC is available */ rtn = (status & ~NAND_STATUS_FAIL); /* clear the error bit */ } @@ -533,33 +510,32 @@ static int rtc_from4_errstat(struct mtd_ } #endif - /* * Main initialization routine */ -int __init rtc_from4_init (void) +static int __init rtc_from4_init(void) { struct nand_chip *this; unsigned short bcr1, bcr2, wcr2; int i; /* Allocate memory for MTD device structure and private data */ - rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip), - GFP_KERNEL); + rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!rtc_from4_mtd) { - printk ("Unable to allocate Renesas NAND MTD device structure.\n"); + printk("Unable to allocate Renesas NAND MTD device structure.\n"); return -ENOMEM; } /* Get pointer to private data */ - this = (struct nand_chip *) (&rtc_from4_mtd[1]); + this = (struct nand_chip *)(&rtc_from4_mtd[1]); /* Initialize structures */ - memset((char *) rtc_from4_mtd, 0, sizeof(struct mtd_info)); - memset((char *) this, 0, sizeof(struct nand_chip)); + memset(rtc_from4_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ rtc_from4_mtd->priv = this; + rtc_from4_mtd->owner = THIS_MODULE; /* set area 5 as PCMCIA mode to clear the spec of tDH(Data hold time;9ns min) */ bcr1 = *SH77X9_BCR1 & ~0x0002; @@ -580,9 +556,9 @@ int __init rtc_from4_init (void) this->IO_ADDR_R = rtc_from4_fio_base; this->IO_ADDR_W = rtc_from4_fio_base; /* Set address of hardware control function */ - this->hwcontrol = rtc_from4_hwcontrol; + this->cmd_ctrl = rtc_from4_hwcontrol; /* Set address of chip select function */ - this->select_chip = rtc_from4_nand_select_chip; + this->select_chip = rtc_from4_nand_select_chip; /* command delay time (in us) */ this->chip_delay = 100; /* return the status of the Ready/Busy line */ @@ -591,19 +567,20 @@ int __init rtc_from4_init (void) #ifdef RTC_FROM4_HWECC printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n"); - this->eccmode = NAND_ECC_HW8_512; - this->options |= NAND_HWECC_SYNDROME; + this->ecc.mode = NAND_ECC_HW_SYNDROME; + this->ecc.size = 512; + this->ecc.bytes = 8; /* return the status of extra status and ECC checks */ this->errstat = rtc_from4_errstat; /* set the nand_oobinfo to support FPGA H/W error detection */ - this->autooob = &rtc_from4_nand_oobinfo; - this->enable_hwecc = rtc_from4_enable_hwecc; - this->calculate_ecc = rtc_from4_calculate_ecc; - this->correct_data = rtc_from4_correct_data; + this->ecc.layout = &rtc_from4_nand_oobinfo; + this->ecc.hwctl = rtc_from4_enable_hwecc; + this->ecc.calculate = rtc_from4_calculate_ecc; + this->ecc.correct = rtc_from4_correct_data; #else printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n"); - this->eccmode = NAND_ECC_SOFT; + this->ecc.mode = NAND_ECC_SOFT; #endif /* set the bad block tables to support debugging */ @@ -617,7 +594,7 @@ #endif } /* Perform 'device recovery' for each chip in case there was a power loss. */ - for (i=0; i < this->numchips; i++) { + for (i = 0; i < this->numchips; i++) { deplete(rtc_from4_mtd, i); } @@ -643,7 +620,7 @@ #ifdef RTC_FROM4_HWECC */ rs_decoder = init_rs(10, 0x409, 0, 1, 6); if (!rs_decoder) { - printk (KERN_ERR "Could not create a RS decoder\n"); + printk(KERN_ERR "Could not create a RS decoder\n"); nand_release(rtc_from4_mtd); kfree(rtc_from4_mtd); return -ENOMEM; @@ -652,20 +629,19 @@ #endif /* Return happy */ return 0; } -module_init(rtc_from4_init); +module_init(rtc_from4_init); /* * Clean up routine */ -#ifdef MODULE -static void __exit rtc_from4_cleanup (void) +static void __exit rtc_from4_cleanup(void) { /* Release resource, unregister partitions */ nand_release(rtc_from4_mtd); /* Free the MTD device structure */ - kfree (rtc_from4_mtd); + kfree(rtc_from4_mtd); #ifdef RTC_FROM4_HWECC /* Free the reed solomon resources */ @@ -674,10 +650,9 @@ #ifdef RTC_FROM4_HWECC } #endif } + module_exit(rtc_from4_cleanup); -#endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("d.marlin -#include - #ifdef CONFIG_MTD_NAND_S3C2410_DEBUG #define DEBUG #endif @@ -73,14 +71,20 @@ #else static int hardware_ecc = 0; #endif +#ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP +static int clock_stop = 1; +#else +static const int clock_stop = 0; +#endif + + /* new oob placement block for use with hardware ecc generation */ -static struct nand_oobinfo nand_hw_eccoob = { - .useecc = MTD_NANDECC_AUTOPLACE, - .eccbytes = 3, - .eccpos = {0, 1, 2 }, - .oobfree = { {8, 8} } +static struct nand_ecclayout nand_hw_eccoob = { + .eccbytes = 3, + .eccpos = {0, 1, 2}, + .oobfree = {{8, 8}} }; /* controller and mtd information */ @@ -135,6 +139,11 @@ static struct s3c2410_platform_nand *to_ return dev->dev.platform_data; } +static inline int allow_clk_stop(struct s3c2410_nand_info *info) +{ + return clock_stop; +} + /* timing calculations */ #define NS_IN_KHZ 1000000 @@ -149,8 +158,7 @@ static int s3c2410_nand_calc_rate(int wa pr_debug("result %d from %ld, %d\n", result, clk, wanted); if (result > max) { - printk("%d ns is too big for current clock rate %ld\n", - wanted, clk); + printk("%d ns is too big for current clock rate %ld\n", wanted, clk); return -1; } @@ -164,8 +172,7 @@ #define to_ns(ticks,clk) (((ticks) * NS_ /* controller setup */ -static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, - struct platform_device *pdev) +static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, struct platform_device *pdev) { struct s3c2410_platform_nand *plat = to_nand_plat(pdev); unsigned long clkrate = clk_get_rate(info->clk); @@ -177,7 +184,7 @@ static int s3c2410_nand_inithw(struct s3 clkrate /= 1000; /* turn clock into kHz for ease of use */ if (plat != NULL) { - tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4); + tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4); twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8); twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8); } else { @@ -193,19 +200,22 @@ static int s3c2410_nand_inithw(struct s3 } printk(KERN_INFO PFX "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n", - tacls, to_ns(tacls, clkrate), - twrph0, to_ns(twrph0, clkrate), - twrph1, to_ns(twrph1, clkrate)); + tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate)); if (!info->is_s3c2440) { - cfg = S3C2410_NFCONF_EN; - cfg |= S3C2410_NFCONF_TACLS(tacls-1); - cfg |= S3C2410_NFCONF_TWRPH0(twrph0-1); - cfg |= S3C2410_NFCONF_TWRPH1(twrph1-1); + cfg = S3C2410_NFCONF_EN; + cfg |= S3C2410_NFCONF_TACLS(tacls - 1); + cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1); + cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1); } else { - cfg = S3C2440_NFCONF_TACLS(tacls-1); - cfg |= S3C2440_NFCONF_TWRPH0(twrph0-1); - cfg |= S3C2440_NFCONF_TWRPH1(twrph1-1); + cfg = S3C2440_NFCONF_TACLS(tacls - 1); + cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1); + cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1); + + /* enable the controller and de-assert nFCE */ + + writel(S3C2440_NFCONT_ENABLE | S3C2440_NFCONT_ENABLE, + info->regs + S3C2440_NFCONT); } pr_debug(PFX "NF_CONF is 0x%lx\n", cfg); @@ -229,7 +239,10 @@ static void s3c2410_nand_select_chip(str info = nmtd->info; bit = (info->is_s3c2440) ? S3C2440_NFCONT_nFCE : S3C2410_NFCONF_nFCE; - reg = info->regs+((info->is_s3c2440) ? S3C2440_NFCONT:S3C2410_NFCONF); + reg = info->regs + ((info->is_s3c2440) ? S3C2440_NFCONT : S3C2410_NFCONF); + + if (chip != -1 && allow_clk_stop(info)) + clk_enable(info->clk); cur = readl(reg); @@ -243,77 +256,51 @@ static void s3c2410_nand_select_chip(str if (info->platform != NULL) { if (info->platform->select_chip != NULL) - (info->platform->select_chip)(nmtd->set, chip); + (info->platform->select_chip) (nmtd->set, chip); } cur &= ~bit; } writel(cur, reg); + + if (chip == -1 && allow_clk_stop(info)) + clk_disable(info->clk); } -/* command and control functions - * - * Note, these all use tglx's method of changing the IO_ADDR_W field - * to make the code simpler, and use the nand layer's code to issue the - * command and address sequences via the proper IO ports. +/* s3c2410_nand_hwcontrol * + * Issue command and address cycles to the chip */ -static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd) +static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) { struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); - struct nand_chip *chip = mtd->priv; - - switch (cmd) { - case NAND_CTL_SETNCE: - case NAND_CTL_CLRNCE: - printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__); - break; - - case NAND_CTL_SETCLE: - chip->IO_ADDR_W = info->regs + S3C2410_NFCMD; - break; - - case NAND_CTL_SETALE: - chip->IO_ADDR_W = info->regs + S3C2410_NFADDR; - break; - - /* NAND_CTL_CLRCLE: */ - /* NAND_CTL_CLRALE: */ - default: - chip->IO_ADDR_W = info->regs + S3C2410_NFDATA; - break; - } + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + writeb(cmd, info->regs + S3C2410_NFCMD); + else + writeb(cmd, info->regs + S3C2410_NFADDR); } /* command and control functions */ -static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd) +static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) { struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); - struct nand_chip *chip = mtd->priv; - - switch (cmd) { - case NAND_CTL_SETNCE: - case NAND_CTL_CLRNCE: - printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__); - break; - - case NAND_CTL_SETCLE: - chip->IO_ADDR_W = info->regs + S3C2440_NFCMD; - break; - - case NAND_CTL_SETALE: - chip->IO_ADDR_W = info->regs + S3C2440_NFADDR; - break; - - /* NAND_CTL_CLRCLE: */ - /* NAND_CTL_CLRALE: */ - default: - chip->IO_ADDR_W = info->regs + S3C2440_NFDATA; - break; - } + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + writeb(cmd, info->regs + S3C2440_NFCMD); + else + writeb(cmd, info->regs + S3C2440_NFADDR); } /* s3c2410_nand_devready() @@ -330,22 +317,16 @@ static int s3c2410_nand_devready(struct return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY; } - /* ECC handling functions */ -static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, - u_char *read_ecc, u_char *calc_ecc) +static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { - pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", - mtd, dat, read_ecc, calc_ecc); + pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", mtd, dat, read_ecc, calc_ecc); pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n", - read_ecc[0], read_ecc[1], read_ecc[2], - calc_ecc[0], calc_ecc[1], calc_ecc[2]); + read_ecc[0], read_ecc[1], read_ecc[2], calc_ecc[0], calc_ecc[1], calc_ecc[2]); - if (read_ecc[0] == calc_ecc[0] && - read_ecc[1] == calc_ecc[1] && - read_ecc[2] == calc_ecc[2]) + if (read_ecc[0] == calc_ecc[0] && read_ecc[1] == calc_ecc[1] && read_ecc[2] == calc_ecc[2]) return 0; /* we curently have no method for correcting the error */ @@ -378,8 +359,7 @@ static void s3c2440_nand_enable_hwecc(st writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT); } -static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, - const u_char *dat, u_char *ecc_code) +static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) { struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); @@ -387,15 +367,12 @@ static int s3c2410_nand_calculate_ecc(st ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1); ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2); - pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", - ecc_code[0], ecc_code[1], ecc_code[2]); + pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]); return 0; } - -static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, - const u_char *dat, u_char *ecc_code) +static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) { struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); unsigned long ecc = readl(info->regs + S3C2440_NFMECC0); @@ -404,13 +381,11 @@ static int s3c2440_nand_calculate_ecc(st ecc_code[1] = ecc >> 8; ecc_code[2] = ecc >> 16; - pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", - ecc_code[0], ecc_code[1], ecc_code[2]); + pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]); return 0; } - /* over-ride the standard functions for a little more speed. We can * use read/write block to move the data buffers to/from the controller */ @@ -421,8 +396,7 @@ static void s3c2410_nand_read_buf(struct readsb(this->IO_ADDR_R, buf, len); } -static void s3c2410_nand_write_buf(struct mtd_info *mtd, - const u_char *buf, int len) +static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; writesb(this->IO_ADDR_W, buf, len); @@ -459,7 +433,8 @@ static int s3c2410_nand_remove(struct pl /* free the common resources */ if (info->clk != NULL && !IS_ERR(info->clk)) { - clk_disable(info->clk); + if (!allow_clk_stop(info)) + clk_disable(info->clk); clk_put(info->clk); } @@ -488,9 +463,7 @@ static int s3c2410_nand_add_partition(st return add_mtd_device(&mtd->mtd); if (set->nr_partitions > 0 && set->partitions != NULL) { - return add_mtd_partitions(&mtd->mtd, - set->partitions, - set->nr_partitions); + return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions); } return add_mtd_device(&mtd->mtd); @@ -517,7 +490,7 @@ static void s3c2410_nand_init_chip(struc chip->IO_ADDR_R = info->regs + S3C2410_NFDATA; chip->IO_ADDR_W = info->regs + S3C2410_NFDATA; - chip->hwcontrol = s3c2410_nand_hwcontrol; + chip->cmd_ctrl = s3c2410_nand_hwcontrol; chip->dev_ready = s3c2410_nand_devready; chip->write_buf = s3c2410_nand_write_buf; chip->read_buf = s3c2410_nand_read_buf; @@ -530,26 +503,29 @@ static void s3c2410_nand_init_chip(struc if (info->is_s3c2440) { chip->IO_ADDR_R = info->regs + S3C2440_NFDATA; chip->IO_ADDR_W = info->regs + S3C2440_NFDATA; - chip->hwcontrol = s3c2440_nand_hwcontrol; + chip->cmd_ctrl = s3c2440_nand_hwcontrol; } nmtd->info = info; nmtd->mtd.priv = chip; + nmtd->mtd.owner = THIS_MODULE; nmtd->set = set; if (hardware_ecc) { - chip->correct_data = s3c2410_nand_correct_data; - chip->enable_hwecc = s3c2410_nand_enable_hwecc; - chip->calculate_ecc = s3c2410_nand_calculate_ecc; - chip->eccmode = NAND_ECC_HW3_512; - chip->autooob = &nand_hw_eccoob; + chip->ecc.correct = s3c2410_nand_correct_data; + chip->ecc.hwctl = s3c2410_nand_enable_hwecc; + chip->ecc.calculate = s3c2410_nand_calculate_ecc; + chip->ecc.mode = NAND_ECC_HW; + chip->ecc.size = 512; + chip->ecc.bytes = 3; + chip->ecc.layout = &nand_hw_eccoob; if (info->is_s3c2440) { - chip->enable_hwecc = s3c2440_nand_enable_hwecc; - chip->calculate_ecc = s3c2440_nand_calculate_ecc; + chip->ecc.hwctl = s3c2440_nand_enable_hwecc; + chip->ecc.calculate = s3c2440_nand_calculate_ecc; } } else { - chip->eccmode = NAND_ECC_SOFT; + chip->ecc.mode = NAND_ECC_SOFT; } } @@ -654,13 +630,11 @@ static int s3c24xx_nand_probe(struct pla nmtd = info->mtds; for (setno = 0; setno < nr_sets; setno++, nmtd++) { - pr_debug("initialising set %d (%p, info %p)\n", - setno, nmtd, info); + pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info); s3c2410_nand_init_chip(info, nmtd, sets); - nmtd->scan_res = nand_scan(&nmtd->mtd, - (sets) ? sets->nr_chips : 1); + nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1); if (nmtd->scan_res == 0) { s3c2410_nand_add_partition(info, nmtd, sets); @@ -670,6 +644,11 @@ static int s3c24xx_nand_probe(struct pla sets++; } + if (allow_clk_stop(info)) { + dev_info(&pdev->dev, "clock idle support enabled\n"); + clk_disable(info->clk); + } + pr_debug("initialised ok\n"); return 0; @@ -681,6 +660,41 @@ static int s3c24xx_nand_probe(struct pla return err; } +/* PM Support */ +#ifdef CONFIG_PM + +static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm) +{ + struct s3c2410_nand_info *info = platform_get_drvdata(dev); + + if (info) { + if (!allow_clk_stop(info)) + clk_disable(info->clk); + } + + return 0; +} + +static int s3c24xx_nand_resume(struct platform_device *dev) +{ + struct s3c2410_nand_info *info = platform_get_drvdata(dev); + + if (info) { + clk_enable(info->clk); + s3c2410_nand_inithw(info, dev); + + if (allow_clk_stop(info)) + clk_disable(info->clk); + } + + return 0; +} + +#else +#define s3c24xx_nand_suspend NULL +#define s3c24xx_nand_resume NULL +#endif + /* driver device registration */ static int s3c2410_nand_probe(struct platform_device *dev) @@ -696,6 +710,8 @@ static int s3c2440_nand_probe(struct pla static struct platform_driver s3c2410_nand_driver = { .probe = s3c2410_nand_probe, .remove = s3c2410_nand_remove, + .suspend = s3c24xx_nand_suspend, + .resume = s3c24xx_nand_resume, .driver = { .name = "s3c2410-nand", .owner = THIS_MODULE, @@ -705,6 +721,8 @@ static struct platform_driver s3c2410_na static struct platform_driver s3c2440_nand_driver = { .probe = s3c2440_nand_probe, .remove = s3c2410_nand_remove, + .suspend = s3c24xx_nand_suspend, + .resume = s3c24xx_nand_resume, .driver = { .name = "s3c2440-nand", .owner = THIS_MODULE, diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 1924a4f..2174365 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -46,7 +46,6 @@ #define FLALE (1 << 2) #define FLCLE (1 << 1) #define FLCE0 (1 << 0) - /* * MTD structure for SharpSL */ @@ -60,50 +59,44 @@ #define DEFAULT_NUM_PARTITIONS 3 static int nr_partitions; static struct mtd_partition sharpsl_nand_default_partition_info[] = { { - .name = "System Area", - .offset = 0, - .size = 7 * 1024 * 1024, - }, + .name = "System Area", + .offset = 0, + .size = 7 * 1024 * 1024, + }, { - .name = "Root Filesystem", - .offset = 7 * 1024 * 1024, - .size = 30 * 1024 * 1024, - }, + .name = "Root Filesystem", + .offset = 7 * 1024 * 1024, + .size = 30 * 1024 * 1024, + }, { - .name = "Home Filesystem", - .offset = MTDPART_OFS_APPEND , - .size = MTDPART_SIZ_FULL , - }, + .name = "Home Filesystem", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, }; /* * hardware specific access to control-lines + * ctrl: + * NAND_CNE: bit 0 -> bit 0 & 4 + * NAND_CLE: bit 1 -> bit 1 + * NAND_ALE: bit 2 -> bit 2 + * */ -static void -sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd) +static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) { - switch (cmd) { - case NAND_CTL_SETCLE: - writeb(readb(FLASHCTL) | FLCLE, FLASHCTL); - break; - case NAND_CTL_CLRCLE: - writeb(readb(FLASHCTL) & ~FLCLE, FLASHCTL); - break; - - case NAND_CTL_SETALE: - writeb(readb(FLASHCTL) | FLALE, FLASHCTL); - break; - case NAND_CTL_CLRALE: - writeb(readb(FLASHCTL) & ~FLALE, FLASHCTL); - break; - - case NAND_CTL_SETNCE: - writeb(readb(FLASHCTL) & ~(FLCE0|FLCE1), FLASHCTL); - break; - case NAND_CTL_CLRNCE: - writeb(readb(FLASHCTL) | (FLCE0|FLCE1), FLASHCTL); - break; + struct nand_chip *chip = mtd->priv; + + if (ctrl & NAND_CTRL_CHANGE) { + unsigned char bits = ctrl & 0x07; + + bits |= (ctrl & 0x01) << 4; + writeb((readb(FLASHCTL) & 0x17) | bits, FLASHCTL); } + + if (cmd != NAND_CMD_NONE) + writeb(cmd, chip->IO_ADDR_W); } static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; @@ -122,31 +115,26 @@ static struct nand_bbt_descr sharpsl_aki .pattern = scan_ff_pattern }; -static struct nand_oobinfo akita_oobinfo = { - .useecc = MTD_NANDECC_AUTOPLACE, +static struct nand_ecclayout akita_oobinfo = { .eccbytes = 24, .eccpos = { - 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11, - 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, - 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37}, - .oobfree = { {0x08, 0x09} } + 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11, + 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, + 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37}, + .oobfree = {{0x08, 0x09}} }; -static int -sharpsl_nand_dev_ready(struct mtd_info* mtd) +static int sharpsl_nand_dev_ready(struct mtd_info *mtd) { return !((readb(FLASHCTL) & FLRYBY) == 0); } -static void -sharpsl_nand_enable_hwecc(struct mtd_info* mtd, int mode) +static void sharpsl_nand_enable_hwecc(struct mtd_info *mtd, int mode) { - writeb(0 ,ECCCLRR); + writeb(0, ECCCLRR); } -static int -sharpsl_nand_calculate_ecc(struct mtd_info* mtd, const u_char* dat, - u_char* ecc_code) +static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code) { ecc_code[0] = ~readb(ECCLPUB); ecc_code[1] = ~readb(ECCLPLB); @@ -154,47 +142,44 @@ sharpsl_nand_calculate_ecc(struct mtd_in return readb(ECCCNTR) != 0; } - #ifdef CONFIG_MTD_PARTITIONS const char *part_probes[] = { "cmdlinepart", NULL }; #endif - /* * Main initialization routine */ -int __init -sharpsl_nand_init(void) +static int __init sharpsl_nand_init(void) { struct nand_chip *this; - struct mtd_partition* sharpsl_partition_info; + struct mtd_partition *sharpsl_partition_info; int err = 0; /* Allocate memory for MTD device structure and private data */ - sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), - GFP_KERNEL); + sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!sharpsl_mtd) { - printk ("Unable to allocate SharpSL NAND MTD device structure.\n"); + printk("Unable to allocate SharpSL NAND MTD device structure.\n"); return -ENOMEM; } /* map physical adress */ sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000); - if(!sharpsl_io_base){ + if (!sharpsl_io_base) { printk("ioremap to access Sharp SL NAND chip failed\n"); kfree(sharpsl_mtd); return -EIO; } /* Get pointer to private data */ - this = (struct nand_chip *) (&sharpsl_mtd[1]); + this = (struct nand_chip *)(&sharpsl_mtd[1]); /* Initialize structures */ - memset((char *) sharpsl_mtd, 0, sizeof(struct mtd_info)); - memset((char *) this, 0, sizeof(struct nand_chip)); + memset(sharpsl_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ sharpsl_mtd->priv = this; + sharpsl_mtd->owner = THIS_MODULE; /* * PXA initialize @@ -205,23 +190,25 @@ sharpsl_nand_init(void) this->IO_ADDR_R = FLASHIO; this->IO_ADDR_W = FLASHIO; /* Set address of hardware control function */ - this->hwcontrol = sharpsl_nand_hwcontrol; + this->cmd_ctrl = sharpsl_nand_hwcontrol; this->dev_ready = sharpsl_nand_dev_ready; /* 15 us command delay time */ this->chip_delay = 15; /* set eccmode using hardware ECC */ - this->eccmode = NAND_ECC_HW3_256; + this->ecc.mode = NAND_ECC_HW; + this->ecc.size = 256; + this->ecc.bytes = 3; this->badblock_pattern = &sharpsl_bbt; if (machine_is_akita() || machine_is_borzoi()) { this->badblock_pattern = &sharpsl_akita_bbt; - this->autooob = &akita_oobinfo; + this->ecc.layout = &akita_oobinfo; } - this->enable_hwecc = sharpsl_nand_enable_hwecc; - this->calculate_ecc = sharpsl_nand_calculate_ecc; - this->correct_data = nand_correct_data; + this->ecc.hwctl = sharpsl_nand_enable_hwecc; + this->ecc.calculate = sharpsl_nand_calculate_ecc; + this->ecc.correct = nand_correct_data; /* Scan to find existence of the device */ - err=nand_scan(sharpsl_mtd,1); + err = nand_scan(sharpsl_mtd, 1); if (err) { iounmap(sharpsl_io_base); kfree(sharpsl_mtd); @@ -230,24 +217,23 @@ sharpsl_nand_init(void) /* Register the partitions */ sharpsl_mtd->name = "sharpsl-nand"; - nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, - &sharpsl_partition_info, 0); + nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, &sharpsl_partition_info, 0); if (nr_partitions <= 0) { nr_partitions = DEFAULT_NUM_PARTITIONS; sharpsl_partition_info = sharpsl_nand_default_partition_info; if (machine_is_poodle()) { - sharpsl_partition_info[1].size=30 * 1024 * 1024; + sharpsl_partition_info[1].size = 22 * 1024 * 1024; } else if (machine_is_corgi() || machine_is_shepherd()) { - sharpsl_partition_info[1].size=25 * 1024 * 1024; + sharpsl_partition_info[1].size = 25 * 1024 * 1024; } else if (machine_is_husky()) { - sharpsl_partition_info[1].size=53 * 1024 * 1024; + sharpsl_partition_info[1].size = 53 * 1024 * 1024; } else if (machine_is_spitz()) { - sharpsl_partition_info[1].size=5 * 1024 * 1024; + sharpsl_partition_info[1].size = 5 * 1024 * 1024; } else if (machine_is_akita()) { - sharpsl_partition_info[1].size=58 * 1024 * 1024; + sharpsl_partition_info[1].size = 58 * 1024 * 1024; } else if (machine_is_borzoi()) { - sharpsl_partition_info[1].size=32 * 1024 * 1024; + sharpsl_partition_info[1].size = 32 * 1024 * 1024; } } @@ -261,15 +247,15 @@ sharpsl_nand_init(void) /* Return happy */ return 0; } + module_init(sharpsl_nand_init); /* * Clean up routine */ -#ifdef MODULE static void __exit sharpsl_nand_cleanup(void) { - struct nand_chip *this = (struct nand_chip *) &sharpsl_mtd[1]; + struct nand_chip *this = (struct nand_chip *)&sharpsl_mtd[1]; /* Release resources, unregister device */ nand_release(sharpsl_mtd); @@ -279,8 +265,8 @@ static void __exit sharpsl_nand_cleanup( /* Free the MTD device structure */ kfree(sharpsl_mtd); } + module_exit(sharpsl_nand_cleanup); -#endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Richard Purdie "); diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c index 9cf1ce7..1f6d429 100644 --- a/drivers/mtd/nand/spia.c +++ b/drivers/mtd/nand/spia.c @@ -39,16 +39,16 @@ static struct mtd_info *spia_mtd = NULL; */ #define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */ #define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */ -#define SPIA_PEDR 0x0080 /* - * IO offset to Port E data register - * where the CLE, ALE and NCE pins - * are wired to. - */ -#define SPIA_PEDDR 0x00c0 /* - * IO offset to Port E data direction - * register so we can control the IO - * lines. - */ +#define SPIA_PEDR 0x0080 /* + * IO offset to Port E data register + * where the CLE, ALE and NCE pins + * are wired to. + */ +#define SPIA_PEDDR 0x00c0 /* + * IO offset to Port E data direction + * register so we can control the IO + * lines. + */ /* * Module stuff @@ -69,79 +69,84 @@ module_param(spia_peddr, int, 0); */ static const struct mtd_partition partition_info[] = { { - .name = "SPIA flash partition 1", - .offset = 0, - .size = 2*1024*1024 - }, + .name = "SPIA flash partition 1", + .offset = 0, + .size = 2 * 1024 * 1024}, { - .name = "SPIA flash partition 2", - .offset = 2*1024*1024, - .size = 6*1024*1024 - } + .name = "SPIA flash partition 2", + .offset = 2 * 1024 * 1024, + .size = 6 * 1024 * 1024} }; -#define NUM_PARTITIONS 2 +#define NUM_PARTITIONS 2 /* * hardware specific access to control-lines -*/ -static void spia_hwcontrol(struct mtd_info *mtd, int cmd){ - - switch(cmd){ + * + * ctrl: + * NAND_CNE: bit 0 -> bit 2 + * NAND_CLE: bit 1 -> bit 0 + * NAND_ALE: bit 2 -> bit 1 + */ +static void spia_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct nand_chip *chip = mtd->priv; - case NAND_CTL_SETCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x01; break; - case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x01; break; + if (ctrl & NAND_CTRL_CHANGE) { + void __iomem *addr = spia_io_base + spia_pedr; + unsigned char bits; - case NAND_CTL_SETALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x02; break; - case NAND_CTL_CLRALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x02; break; + bits = (ctrl & NAND_CNE) << 2; + bits |= (ctrl & NAND_CLE | NAND_ALE) >> 1; + writeb((readb(addr) & ~0x7) | bits, addr); + } - case NAND_CTL_SETNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x04; break; - case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x04; break; - } + if (cmd != NAND_CMD_NONE) + writeb(cmd, chip->IO_ADDR_W); } /* * Main initialization routine */ -int __init spia_init (void) +static int __init spia_init(void) { struct nand_chip *this; /* Allocate memory for MTD device structure and private data */ - spia_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), - GFP_KERNEL); + spia_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!spia_mtd) { - printk ("Unable to allocate SPIA NAND MTD device structure.\n"); + printk("Unable to allocate SPIA NAND MTD device structure.\n"); return -ENOMEM; } /* Get pointer to private data */ - this = (struct nand_chip *) (&spia_mtd[1]); + this = (struct nand_chip *)(&spia_mtd[1]); /* Initialize structures */ - memset((char *) spia_mtd, 0, sizeof(struct mtd_info)); - memset((char *) this, 0, sizeof(struct nand_chip)); + memset(spia_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ spia_mtd->priv = this; + spia_mtd->owner = THIS_MODULE; /* * Set GPIO Port E control register so that the pins are configured * to be outputs for controlling the NAND flash. */ - (*(volatile unsigned char *) (spia_io_base + spia_peddr)) = 0x07; + (*(volatile unsigned char *)(spia_io_base + spia_peddr)) = 0x07; /* Set address of NAND IO lines */ - this->IO_ADDR_R = (void __iomem *) spia_fio_base; - this->IO_ADDR_W = (void __iomem *) spia_fio_base; + this->IO_ADDR_R = (void __iomem *)spia_fio_base; + this->IO_ADDR_W = (void __iomem *)spia_fio_base; /* Set address of hardware control function */ - this->hwcontrol = spia_hwcontrol; + this->cmd_ctrl = spia_hwcontrol; /* 15 us command delay time */ this->chip_delay = 15; /* Scan to find existence of the device */ - if (nand_scan (spia_mtd, 1)) { - kfree (spia_mtd); + if (nand_scan(spia_mtd, 1)) { + kfree(spia_mtd); return -ENXIO; } @@ -151,22 +156,22 @@ int __init spia_init (void) /* Return happy */ return 0; } + module_init(spia_init); /* * Clean up routine */ -#ifdef MODULE -static void __exit spia_cleanup (void) +static void __exit spia_cleanup(void) { /* Release resources, unregister device */ - nand_release (spia_mtd); + nand_release(spia_mtd); /* Free the MTD device structure */ - kfree (spia_mtd); + kfree(spia_mtd); } + module_exit(spia_cleanup); -#endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Steven J. Hill #include #include +#define CONFIG_NAND_WORKAROUND 1 + /* * MTD structure for TOTO board */ @@ -39,25 +41,6 @@ static struct mtd_info *toto_mtd = NULL; static unsigned long toto_io_base = OMAP_FLASH_1_BASE; -#define CONFIG_NAND_WORKAROUND 1 - -#define NAND_NCE 0x4000 -#define NAND_CLE 0x1000 -#define NAND_ALE 0x0002 -#define NAND_MASK (NAND_CLE | NAND_ALE | NAND_NCE) - -#define T_NAND_CTL_CLRALE(iob) gpiosetout(NAND_ALE, 0) -#define T_NAND_CTL_SETALE(iob) gpiosetout(NAND_ALE, NAND_ALE) -#ifdef CONFIG_NAND_WORKAROUND /* "some" dev boards busted, blue wired to rts2 :( */ -#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0); rts2setout(2, 2) -#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0) -#else -#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0) -#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE) -#endif -#define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0) -#define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE) - /* * Define partitions for flash devices */ @@ -91,91 +74,110 @@ static struct mtd_partition partition_in #define NUM_PARTITIONS32M 3 #define NUM_PARTITIONS64M 4 + /* * hardware specific access to control-lines -*/ - -static void toto_hwcontrol(struct mtd_info *mtd, int cmd) + * + * ctrl: + * NAND_NCE: bit 0 -> bit 14 (0x4000) + * NAND_CLE: bit 1 -> bit 12 (0x1000) + * NAND_ALE: bit 2 -> bit 1 (0x0002) + */ +static void toto_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) { + struct nand_chip *chip = mtd->priv; + + if (ctrl & NAND_CTRL_CHANGE) { + unsigned long bits; - udelay(1); /* hopefully enough time for tc make proceding write to clear */ - switch(cmd){ + /* hopefully enough time for tc make proceding write to clear */ + udelay(1); - case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break; - case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break; + bits = (~ctrl & NAND_NCE) << 14; + bits |= (ctrl & NAND_CLE) << 12; + bits |= (ctrl & NAND_ALE) >> 1; - case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break; - case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break; +#warning Wild guess as gpiosetout() is nowhere defined in the kernel source - tglx + gpiosetout(0x5002, bits); - case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break; - case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break; +#ifdef CONFIG_NAND_WORKAROUND + /* "some" dev boards busted, blue wired to rts2 :( */ + rts2setout(2, (ctrl & NAND_CLE) << 1); +#endif + /* allow time to ensure gpio state to over take memory write */ + udelay(1); } - udelay(1); /* allow time to ensure gpio state to over take memory write */ + + if (cmd != NAND_CMD_NONE) + writeb(cmd, chip->IO_ADDR_W); } /* * Main initialization routine */ -int __init toto_init (void) +static int __init toto_init(void) { struct nand_chip *this; int err = 0; /* Allocate memory for MTD device structure and private data */ - toto_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), - GFP_KERNEL); + toto_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!toto_mtd) { - printk (KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n"); + printk(KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n"); err = -ENOMEM; goto out; } /* Get pointer to private data */ - this = (struct nand_chip *) (&toto_mtd[1]); + this = (struct nand_chip *)(&toto_mtd[1]); /* Initialize structures */ - memset((char *) toto_mtd, 0, sizeof(struct mtd_info)); - memset((char *) this, 0, sizeof(struct nand_chip)); + memset(toto_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ toto_mtd->priv = this; + toto_mtd->owner = THIS_MODULE; /* Set address of NAND IO lines */ this->IO_ADDR_R = toto_io_base; this->IO_ADDR_W = toto_io_base; - this->hwcontrol = toto_hwcontrol; + this->cmd_ctrl = toto_hwcontrol; this->dev_ready = NULL; /* 25 us command delay time */ this->chip_delay = 30; - this->eccmode = NAND_ECC_SOFT; + this->ecc.mode = NAND_ECC_SOFT; - /* Scan to find existance of the device */ - if (nand_scan (toto_mtd, 1)) { + /* Scan to find existance of the device */ + if (nand_scan(toto_mtd, 1)) { err = -ENXIO; goto out_mtd; } /* Register the partitions */ - switch(toto_mtd->size){ - case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; - case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break; - default: { - printk (KERN_WARNING "Unsupported Nand device\n"); + switch (toto_mtd->size) { + case SZ_64M: + add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); + break; + case SZ_32M: + add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); + break; + default:{ + printk(KERN_WARNING "Unsupported Nand device\n"); err = -ENXIO; goto out_buf; } } - gpioreserve(NAND_MASK); /* claim our gpios */ - archflashwp(0,0); /* open up flash for writing */ + gpioreserve(NAND_MASK); /* claim our gpios */ + archflashwp(0, 0); /* open up flash for writing */ goto out; -out_buf: - kfree (this->data_buf); -out_mtd: - kfree (toto_mtd); -out: + out_mtd: + kfree(toto_mtd); + out: return err; } @@ -184,20 +186,21 @@ module_init(toto_init); /* * Clean up routine */ -static void __exit toto_cleanup (void) +static void __exit toto_cleanup(void) { /* Release resources, unregister device */ - nand_release (toto_mtd); + nand_release(toto_mtd); /* Free the MTD device structure */ - kfree (toto_mtd); + kfree(toto_mtd); /* stop flash writes */ - archflashwp(0,1); + archflashwp(0, 1); /* release gpios to system */ - gpiorelease(NAND_MASK); + gpiorelease(NAND_MASK); } + module_exit(toto_cleanup); MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c new file mode 100644 index 0000000..a0b4b1e --- /dev/null +++ b/drivers/mtd/nand/ts7250.c @@ -0,0 +1,206 @@ +/* + * drivers/mtd/nand/ts7250.c + * + * Copyright (C) 2004 Technologic Systems (support@embeddedARM.com) + * + * Derived from drivers/mtd/nand/edb7312.c + * Copyright (C) 2004 Marius Gröger (mag@sysgo.de) + * + * Derived from drivers/mtd/nand/autcpu12.c + * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) + * + * $Id: ts7250.c,v 1.4 2004/12/30 22:02:07 joff Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the NAND flash device found on the + * TS-7250 board which utilizes a Samsung 32 Mbyte part. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * MTD structure for TS7250 board + */ +static struct mtd_info *ts7250_mtd = NULL; + +#ifdef CONFIG_MTD_PARTITIONS +static const char *part_probes[] = { "cmdlinepart", NULL }; + +#define NUM_PARTITIONS 3 + +/* + * Define static partitions for flash device + */ +static struct mtd_partition partition_info32[] = { + { + .name = "TS-BOOTROM", + .offset = 0x00000000, + .size = 0x00004000, + }, { + .name = "Linux", + .offset = 0x00004000, + .size = 0x01d00000, + }, { + .name = "RedBoot", + .offset = 0x01d04000, + .size = 0x002fc000, + }, +}; + +/* + * Define static partitions for flash device + */ +static struct mtd_partition partition_info128[] = { + { + .name = "TS-BOOTROM", + .offset = 0x00000000, + .size = 0x00004000, + }, { + .name = "Linux", + .offset = 0x00004000, + .size = 0x07d00000, + }, { + .name = "RedBoot", + .offset = 0x07d04000, + .size = 0x002fc000, + }, +}; +#endif + + +/* + * hardware specific access to control-lines + * + * ctrl: + * NAND_NCE: bit 0 -> bit 2 + * NAND_CLE: bit 1 -> bit 1 + * NAND_ALE: bit 2 -> bit 0 + */ +static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *chip = mtd->priv; + + if (ctrl & NAND_CTRL_CHANGE) { + unsigned long addr = TS72XX_NAND_CONTROL_VIRT_BASE; + unsigned char bits; + + bits = (ctrl & NAND_CNE) << 2; + bits |= ctrl & NAND_CLE; + bits |= (ctrl & NAND_ALE) >> 2; + + __raw_writeb((__raw_readb(addr) & ~0x7) | bits, addr); + } + + if (cmd != NAND_CMD_NONE) + writeb(cmd, chip->IO_ADDR_W); +} + +/* + * read device ready pin + */ +static int ts7250_device_ready(struct mtd_info *mtd) +{ + return __raw_readb(TS72XX_NAND_BUSY_VIRT_BASE) & 0x20; +} + +/* + * Main initialization routine + */ +static int __init ts7250_init(void) +{ + struct nand_chip *this; + const char *part_type = 0; + int mtd_parts_nb = 0; + struct mtd_partition *mtd_parts = 0; + + if (!machine_is_ts72xx() || board_is_ts7200()) + return -ENXIO; + + /* Allocate memory for MTD device structure and private data */ + ts7250_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); + if (!ts7250_mtd) { + printk("Unable to allocate TS7250 NAND MTD device structure.\n"); + return -ENOMEM; + } + + /* Get pointer to private data */ + this = (struct nand_chip *)(&ts7250_mtd[1]); + + /* Initialize structures */ + memset(ts7250_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); + + /* Link the private data with the MTD structure */ + ts7250_mtd->priv = this; + ts7250_mtd->owner = THIS_MODULE; + + /* insert callbacks */ + this->IO_ADDR_R = (void *)TS72XX_NAND_DATA_VIRT_BASE; + this->IO_ADDR_W = (void *)TS72XX_NAND_DATA_VIRT_BASE; + this->cmd_ctrl = ts7250_hwcontrol; + this->dev_ready = ts7250_device_ready; + this->chip_delay = 15; + this->ecc.mode = NAND_ECC_SOFT; + + printk("Searching for NAND flash...\n"); + /* Scan to find existence of the device */ + if (nand_scan(ts7250_mtd, 1)) { + kfree(ts7250_mtd); + return -ENXIO; + } +#ifdef CONFIG_MTD_PARTITIONS + ts7250_mtd->name = "ts7250-nand"; + mtd_parts_nb = parse_mtd_partitions(ts7250_mtd, part_probes, &mtd_parts, 0); + if (mtd_parts_nb > 0) + part_type = "command line"; + else + mtd_parts_nb = 0; +#endif + if (mtd_parts_nb == 0) { + mtd_parts = partition_info32; + if (ts7250_mtd->size >= (128 * 0x100000)) + mtd_parts = partition_info128; + mtd_parts_nb = NUM_PARTITIONS; + part_type = "static"; + } + + /* Register the partitions */ + printk(KERN_NOTICE "Using %s partition definition\n", part_type); + add_mtd_partitions(ts7250_mtd, mtd_parts, mtd_parts_nb); + + /* Return happy */ + return 0; +} + +module_init(ts7250_init); + +/* + * Clean up routine + */ +static void __exit ts7250_cleanup(void) +{ + /* Unregister the device */ + del_mtd_device(ts7250_mtd); + + /* Free the MTD device structure */ + kfree(ts7250_mtd); +} + +module_exit(ts7250_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jesse Off "); +MODULE_DESCRIPTION("MTD map driver for Technologic Systems TS-7250 board"); diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index d7cd5fa..dc75735 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -70,8 +70,6 @@ static void nftl_add_mtd(struct mtd_blkt nftl->mbd.devnum = -1; nftl->mbd.blksize = 512; nftl->mbd.tr = tr; - memcpy(&nftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo)); - nftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY; if (NFTL_mount(nftl) < 0) { printk(KERN_WARNING "NFTL: could not mount device\n"); @@ -136,6 +134,69 @@ static void nftl_remove_dev(struct mtd_b kfree(nftl); } +/* + * Read oob data from flash + */ +int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, + size_t *retlen, uint8_t *buf) +{ + struct mtd_oob_ops ops; + int res; + + ops.mode = MTD_OOB_PLACE; + ops.ooboffs = offs & (mtd->writesize - 1); + ops.ooblen = len; + ops.oobbuf = buf; + ops.datbuf = NULL; + ops.len = len; + + res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); + *retlen = ops.retlen; + return res; +} + +/* + * Write oob data to flash + */ +int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, + size_t *retlen, uint8_t *buf) +{ + struct mtd_oob_ops ops; + int res; + + ops.mode = MTD_OOB_PLACE; + ops.ooboffs = offs & (mtd->writesize - 1); + ops.ooblen = len; + ops.oobbuf = buf; + ops.datbuf = NULL; + ops.len = len; + + res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); + *retlen = ops.retlen; + return res; +} + +/* + * Write data and oob to flash + */ +static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len, + size_t *retlen, uint8_t *buf, uint8_t *oob) +{ + struct mtd_oob_ops ops; + int res; + + ops.mode = MTD_OOB_PLACE; + ops.ooboffs = offs; + ops.ooblen = mtd->oobsize; + ops.oobbuf = oob; + ops.datbuf = buf; + ops.len = len; + + res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); + *retlen = ops.retlen; + return res; +} + #ifdef CONFIG_NFTL_RW /* Actual NFTL access routines */ @@ -185,6 +246,7 @@ static u16 NFTL_findfreeblock(struct NFT static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) { + struct mtd_info *mtd = nftl->mbd.mtd; u16 BlockMap[MAX_SECTORS_PER_UNIT]; unsigned char BlockLastState[MAX_SECTORS_PER_UNIT]; unsigned char BlockFreeFound[MAX_SECTORS_PER_UNIT]; @@ -194,7 +256,7 @@ static u16 NFTL_foldchain (struct NFTLre unsigned int targetEUN; struct nftl_oob oob; int inplace = 1; - size_t retlen; + size_t retlen; memset(BlockMap, 0xff, sizeof(BlockMap)); memset(BlockFreeFound, 0, sizeof(BlockFreeFound)); @@ -210,21 +272,21 @@ static u16 NFTL_foldchain (struct NFTLre /* Scan to find the Erase Unit which holds the actual data for each 512-byte block within the Chain. */ - silly = MAX_LOOPS; + silly = MAX_LOOPS; targetEUN = BLOCK_NIL; while (thisEUN <= nftl->lastEUN ) { - unsigned int status, foldmark; + unsigned int status, foldmark; targetEUN = thisEUN; for (block = 0; block < nftl->EraseSize / 512; block ++) { - MTD_READOOB(nftl->mbd.mtd, - (thisEUN * nftl->EraseSize) + (block * 512), - 16 , &retlen, (char *)&oob); + nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) + + (block * 512), 16 , &retlen, + (char *)&oob); if (block == 2) { - foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1; - if (foldmark == FOLD_MARK_IN_PROGRESS) { - DEBUG(MTD_DEBUG_LEVEL1, - "Write Inhibited on EUN %d\n", thisEUN); + foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1; + if (foldmark == FOLD_MARK_IN_PROGRESS) { + DEBUG(MTD_DEBUG_LEVEL1, + "Write Inhibited on EUN %d\n", thisEUN); inplace = 0; } else { /* There's no other reason not to do inplace, @@ -233,7 +295,7 @@ static u16 NFTL_foldchain (struct NFTLre inplace = 1; } } - status = oob.b.Status | oob.b.Status1; + status = oob.b.Status | oob.b.Status1; BlockLastState[block] = status; switch(status) { @@ -328,15 +390,15 @@ static u16 NFTL_foldchain (struct NFTLre return BLOCK_NIL; } } else { - /* We put a fold mark in the chain we are folding only if - we fold in place to help the mount check code. If we do - not fold in place, it is possible to find the valid - chain by selecting the longer one */ - oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS); - oob.u.c.unused = 0xffffffff; - MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, - 8, &retlen, (char *)&oob.u); - } + /* We put a fold mark in the chain we are folding only if we + fold in place to help the mount check code. If we do not fold in + place, it is possible to find the valid chain by selecting the + longer one */ + oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS); + oob.u.c.unused = 0xffffffff; + nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, + 8, &retlen, (char *)&oob.u); + } /* OK. We now know the location of every block in the Virtual Unit Chain, and the Erase Unit into which we are supposed to be copying. @@ -353,33 +415,33 @@ static u16 NFTL_foldchain (struct NFTLre continue; } - /* copy only in non free block (free blocks can only + /* copy only in non free block (free blocks can only happen in case of media errors or deleted blocks) */ - if (BlockMap[block] == BLOCK_NIL) - continue; - - ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), - 512, &retlen, movebuf); - if (ret < 0) { - ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) - + (block * 512), 512, &retlen, - movebuf); - if (ret != -EIO) - printk("Error went away on retry.\n"); - } + if (BlockMap[block] == BLOCK_NIL) + continue; + + ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512), + 512, &retlen, movebuf); + if (ret < 0 && ret != -EUCLEAN) { + ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) + + (block * 512), 512, &retlen, + movebuf); + if (ret != -EIO) + printk("Error went away on retry.\n"); + } memset(&oob, 0xff, sizeof(struct nftl_oob)); oob.b.Status = oob.b.Status1 = SECTOR_USED; - MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512), - 512, &retlen, movebuf, (char *)&oob, &nftl->oobinfo); + + nftl_write(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + + (block * 512), 512, &retlen, movebuf, (char *)&oob); } - /* add the header so that it is now a valid chain */ - oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum - = cpu_to_le16(thisVUC); - oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; + /* add the header so that it is now a valid chain */ + oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); + oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; - MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8, - 8, &retlen, (char *)&oob.u); + nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8, + 8, &retlen, (char *)&oob.u); /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */ @@ -396,18 +458,18 @@ static u16 NFTL_foldchain (struct NFTLre while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) { unsigned int EUNtmp; - EUNtmp = nftl->ReplUnitTable[thisEUN]; + EUNtmp = nftl->ReplUnitTable[thisEUN]; - if (NFTL_formatblock(nftl, thisEUN) < 0) { + if (NFTL_formatblock(nftl, thisEUN) < 0) { /* could not erase : mark block as reserved */ nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED; - } else { + } else { /* correctly erased : mark it as free */ nftl->ReplUnitTable[thisEUN] = BLOCK_FREE; nftl->numfreeEUNs++; - } - thisEUN = EUNtmp; + } + thisEUN = EUNtmp; } /* Make this the new start of chain for thisVUC */ @@ -473,6 +535,7 @@ static inline u16 NFTL_findwriteunit(str { u16 lastEUN; u16 thisVUC = block / (nftl->EraseSize / 512); + struct mtd_info *mtd = nftl->mbd.mtd; unsigned int writeEUN; unsigned long blockofs = (block * 512) & (nftl->EraseSize -1); size_t retlen; @@ -489,21 +552,22 @@ static inline u16 NFTL_findwriteunit(str */ lastEUN = BLOCK_NIL; writeEUN = nftl->EUNtable[thisVUC]; - silly = MAX_LOOPS; + silly = MAX_LOOPS; while (writeEUN <= nftl->lastEUN) { struct nftl_bci bci; size_t retlen; - unsigned int status; + unsigned int status; lastEUN = writeEUN; - MTD_READOOB(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs, - 8, &retlen, (char *)&bci); + nftl_read_oob(mtd, + (writeEUN * nftl->EraseSize) + blockofs, + 8, &retlen, (char *)&bci); DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n", block , writeEUN, le16_to_cpu(bci.Status)); - status = bci.Status | bci.Status1; + status = bci.Status | bci.Status1; switch(status) { case SECTOR_FREE: return writeEUN; @@ -574,10 +638,10 @@ static inline u16 NFTL_findwriteunit(str /* We've found a free block. Insert it into the chain. */ if (lastEUN != BLOCK_NIL) { - thisVUC |= 0x8000; /* It's a replacement block */ + thisVUC |= 0x8000; /* It's a replacement block */ } else { - /* The first block in a new chain */ - nftl->EUNtable[thisVUC] = writeEUN; + /* The first block in a new chain */ + nftl->EUNtable[thisVUC] = writeEUN; } /* set up the actual EUN we're writing into */ @@ -585,29 +649,29 @@ static inline u16 NFTL_findwriteunit(str nftl->ReplUnitTable[writeEUN] = BLOCK_NIL; /* ... and on the flash itself */ - MTD_READOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8, - &retlen, (char *)&oob.u); + nftl_read_oob(mtd, writeEUN * nftl->EraseSize + 8, 8, + &retlen, (char *)&oob.u); oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); - MTD_WRITEOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8, - &retlen, (char *)&oob.u); + nftl_write_oob(mtd, writeEUN * nftl->EraseSize + 8, 8, + &retlen, (char *)&oob.u); - /* we link the new block to the chain only after the + /* we link the new block to the chain only after the block is ready. It avoids the case where the chain could point to a free block */ - if (lastEUN != BLOCK_NIL) { + if (lastEUN != BLOCK_NIL) { /* Both in our cache... */ nftl->ReplUnitTable[lastEUN] = writeEUN; /* ... and on the flash itself */ - MTD_READOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8, - 8, &retlen, (char *)&oob.u); + nftl_read_oob(mtd, (lastEUN * nftl->EraseSize) + 8, + 8, &retlen, (char *)&oob.u); oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = cpu_to_le16(writeEUN); - MTD_WRITEOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8, - 8, &retlen, (char *)&oob.u); + nftl_write_oob(mtd, (lastEUN * nftl->EraseSize) + 8, + 8, &retlen, (char *)&oob.u); } return writeEUN; @@ -639,10 +703,9 @@ static int nftl_writeblock(struct mtd_bl memset(&oob, 0xff, sizeof(struct nftl_oob)); oob.b.Status = oob.b.Status1 = SECTOR_USED; - MTD_WRITEECC(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs, - 512, &retlen, (char *)buffer, (char *)&oob, &nftl->oobinfo); - /* need to write SECTOR_USED flags since they are not written in mtd_writeecc */ + nftl_write(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs, + 512, &retlen, (char *)buffer, (char *)&oob); return 0; } #endif /* CONFIG_NFTL_RW */ @@ -651,20 +714,22 @@ static int nftl_readblock(struct mtd_blk char *buffer) { struct NFTLrecord *nftl = (void *)mbd; + struct mtd_info *mtd = nftl->mbd.mtd; u16 lastgoodEUN; u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)]; unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1); - unsigned int status; + unsigned int status; int silly = MAX_LOOPS; - size_t retlen; - struct nftl_bci bci; + size_t retlen; + struct nftl_bci bci; lastgoodEUN = BLOCK_NIL; - if (thisEUN != BLOCK_NIL) { + if (thisEUN != BLOCK_NIL) { while (thisEUN < nftl->nb_blocks) { - if (MTD_READOOB(nftl->mbd.mtd, (thisEUN * nftl->EraseSize) + blockofs, - 8, &retlen, (char *)&bci) < 0) + if (nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) + + blockofs, 8, &retlen, + (char *)&bci) < 0) status = SECTOR_IGNORE; else status = bci.Status | bci.Status1; @@ -694,7 +759,7 @@ static int nftl_readblock(struct mtd_blk } thisEUN = nftl->ReplUnitTable[thisEUN]; } - } + } the_end: if (lastgoodEUN == BLOCK_NIL) { @@ -703,7 +768,9 @@ static int nftl_readblock(struct mtd_blk } else { loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs; size_t retlen; - if (MTD_READ(nftl->mbd.mtd, ptr, 512, &retlen, buffer)) + int res = mtd->read(mtd, ptr, 512, &retlen, buffer); + + if (res < 0 && res != -EUCLEAN) return -EIO; } return 0; diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index 3b104eb..067262e 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c @@ -33,6 +33,11 @@ #define SECTORSIZE 512 char nftlmountrev[]="$Revision: 1.41 $"; +extern int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, + size_t *retlen, uint8_t *buf); +extern int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, + size_t *retlen, uint8_t *buf); + /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the * various device information of the NFTL partition and Bad Unit Table. Update * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[] @@ -45,6 +50,7 @@ static int find_boot_record(struct NFTLr size_t retlen; u8 buf[SECTORSIZE]; struct NFTLMediaHeader *mh = &nftl->MediaHdr; + struct mtd_info *mtd = nftl->mbd.mtd; unsigned int i; /* Assume logical EraseSize == physical erasesize for starting the scan. @@ -65,7 +71,8 @@ static int find_boot_record(struct NFTLr /* Check for ANAND header first. Then can whinge if it's found but later checks fail */ - ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf); + ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE, + &retlen, buf); /* We ignore ret in case the ECC of the MediaHeader is invalid (which is apparently acceptable) */ if (retlen != SECTORSIZE) { @@ -90,8 +97,9 @@ #endif } /* To be safer with BIOS, also use erase mark as discriminant */ - if ((ret = MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, - 8, &retlen, (char *)&h1) < 0)) { + if ((ret = nftl_read_oob(mtd, block * nftl->EraseSize + + SECTORSIZE + 8, 8, &retlen, + (char *)&h1) < 0)) { printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n", block * nftl->EraseSize, nftl->mbd.mtd->index, ret); continue; @@ -109,8 +117,8 @@ #if 0 /* Some people seem to have device } /* Finally reread to check ECC */ - if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, - &retlen, buf, (char *)&oob, NULL) < 0)) { + if ((ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE, + &retlen, buf) < 0)) { printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n", block * nftl->EraseSize, nftl->mbd.mtd->index, ret); continue; @@ -228,9 +236,9 @@ #if 0 The new DiskOnChip driver already scanned the bad block table. Just query it. if ((i & (SECTORSIZE - 1)) == 0) { /* read one sector for every SECTORSIZE of blocks */ - if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize + - i + SECTORSIZE, SECTORSIZE, &retlen, buf, - (char *)&oob, NULL)) < 0) { + if ((ret = mtd->read(nftl->mbd.mtd, block * nftl->EraseSize + + i + SECTORSIZE, SECTORSIZE, &retlen, + buf)) < 0) { printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n", ret); kfree(nftl->ReplUnitTable); @@ -268,18 +276,22 @@ static int memcmpb(void *a, int c, int n static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, int check_oob) { - int i; - size_t retlen; u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize]; + struct mtd_info *mtd = nftl->mbd.mtd; + size_t retlen; + int i; for (i = 0; i < len; i += SECTORSIZE) { - if (MTD_READECC(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &nftl->oobinfo) < 0) + if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf)) return -1; if (memcmpb(buf, 0xff, SECTORSIZE) != 0) return -1; if (check_oob) { - if (memcmpb(buf + SECTORSIZE, 0xff, nftl->mbd.mtd->oobsize) != 0) + if(nftl_read_oob(mtd, address, mtd->oobsize, + &retlen, &buf[SECTORSIZE]) < 0) + return -1; + if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0) return -1; } address += SECTORSIZE; @@ -301,10 +313,11 @@ int NFTL_formatblock(struct NFTLrecord * unsigned int nb_erases, erase_mark; struct nftl_uci1 uci; struct erase_info *instr = &nftl->instr; + struct mtd_info *mtd = nftl->mbd.mtd; /* Read the Unit Control Information #1 for Wear-Leveling */ - if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, - 8, &retlen, (char *)&uci) < 0) + if (nftl_read_oob(mtd, block * nftl->EraseSize + SECTORSIZE + 8, + 8, &retlen, (char *)&uci) < 0) goto default_uci1; erase_mark = le16_to_cpu ((uci.EraseMark | uci.EraseMark1)); @@ -321,7 +334,7 @@ int NFTL_formatblock(struct NFTLrecord * instr->mtd = nftl->mbd.mtd; instr->addr = block * nftl->EraseSize; instr->len = nftl->EraseSize; - MTD_ERASE(nftl->mbd.mtd, instr); + mtd->erase(mtd, instr); if (instr->state == MTD_ERASE_FAILED) { printk("Error while formatting block %d\n", block); @@ -343,8 +356,8 @@ int NFTL_formatblock(struct NFTLrecord * goto fail; uci.WearInfo = le32_to_cpu(nb_erases); - if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&uci) < 0) + if (nftl_write_oob(mtd, block * nftl->EraseSize + SECTORSIZE + + 8, 8, &retlen, (char *)&uci) < 0) goto fail; return 0; fail: @@ -365,6 +378,7 @@ fail: * case. */ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block) { + struct mtd_info *mtd = nftl->mbd.mtd; unsigned int block, i, status; struct nftl_bci bci; int sectors_per_block; @@ -374,8 +388,9 @@ static void check_sectors_in_chain(struc block = first_block; for (;;) { for (i = 0; i < sectors_per_block; i++) { - if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i * SECTORSIZE, - 8, &retlen, (char *)&bci) < 0) + if (nftl_read_oob(mtd, + block * nftl->EraseSize + i * SECTORSIZE, + 8, &retlen, (char *)&bci) < 0) status = SECTOR_IGNORE; else status = bci.Status | bci.Status1; @@ -394,9 +409,10 @@ static void check_sectors_in_chain(struc /* sector not free actually : mark it as SECTOR_IGNORE */ bci.Status = SECTOR_IGNORE; bci.Status1 = SECTOR_IGNORE; - MTD_WRITEOOB(nftl->mbd.mtd, - block * nftl->EraseSize + i * SECTORSIZE, - 8, &retlen, (char *)&bci); + nftl_write_oob(mtd, block * + nftl->EraseSize + + i * SECTORSIZE, 8, + &retlen, (char *)&bci); } break; default: @@ -481,13 +497,14 @@ static void format_chain(struct NFTLreco * 1. */ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) { + struct mtd_info *mtd = nftl->mbd.mtd; struct nftl_uci1 h1; unsigned int erase_mark; size_t retlen; /* check erase mark. */ - if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&h1) < 0) + if (nftl_read_oob(mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, + &retlen, (char *)&h1) < 0) return -1; erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1)); @@ -501,8 +518,9 @@ static int check_and_mark_free_block(str h1.EraseMark = cpu_to_le16(ERASE_MARK); h1.EraseMark1 = cpu_to_le16(ERASE_MARK); h1.WearInfo = cpu_to_le32(0); - if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&h1) < 0) + if (nftl_write_oob(mtd, + block * nftl->EraseSize + SECTORSIZE + 8, 8, + &retlen, (char *)&h1) < 0) return -1; } else { #if 0 @@ -513,8 +531,8 @@ #if 0 SECTORSIZE, 0) != 0) return -1; - if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i, - 16, &retlen, buf) < 0) + if (nftl_read_oob(mtd, block * nftl->EraseSize + i, + 16, &retlen, buf) < 0) return -1; if (i == SECTORSIZE) { /* skip erase mark */ @@ -540,11 +558,12 @@ #endif */ static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block) { + struct mtd_info *mtd = nftl->mbd.mtd; struct nftl_uci2 uci; size_t retlen; - if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8, - 8, &retlen, (char *)&uci) < 0) + if (nftl_read_oob(mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8, + 8, &retlen, (char *)&uci) < 0) return 0; return le16_to_cpu((uci.FoldMark | uci.FoldMark1)); @@ -558,6 +577,7 @@ int NFTL_mount(struct NFTLrecord *s) int chain_length, do_format_chain; struct nftl_uci0 h0; struct nftl_uci1 h1; + struct mtd_info *mtd = s->mbd.mtd; size_t retlen; /* search for NFTL MediaHeader and Spare NFTL Media Header */ @@ -582,10 +602,13 @@ int NFTL_mount(struct NFTLrecord *s) for (;;) { /* read the block header. If error, we format the chain */ - if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8, - &retlen, (char *)&h0) < 0 || - MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8, - &retlen, (char *)&h1) < 0) { + if (nftl_read_oob(mtd, + block * s->EraseSize + 8, 8, + &retlen, (char *)&h0) < 0 || + nftl_read_oob(mtd, + block * s->EraseSize + + SECTORSIZE + 8, 8, + &retlen, (char *)&h1) < 0) { s->ReplUnitTable[block] = BLOCK_NIL; do_format_chain = 1; break; diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 126ff6b..5930a03 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig @@ -29,6 +29,20 @@ config MTD_ONENAND_GENERIC help Support for OneNAND flash via platform device driver. +config MTD_ONENAND_OTP + bool "OneNAND OTP Support" + depends on MTD_ONENAND + help + One Block of the NAND Flash Array memory is reserved as + a One-Time Programmable Block memory area. + Also, 1st Block of NAND Flash Array can be used as OTP. + + The OTP block can be read, programmed and locked using the same + operations as any other NAND Flash Array memory block. + OTP block cannot be erased. + + OTP block is fully-guaranteed to be a valid block. + config MTD_ONENAND_SYNC_READ bool "OneNAND Sync. Burst Read Support" depends on ARCH_OMAP diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index a53a73f..84ec40d 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -23,8 +23,7 @@ #include /** * onenand_oob_64 - oob info for large (2KB) page */ -static struct nand_oobinfo onenand_oob_64 = { - .useecc = MTD_NANDECC_AUTOPLACE, +static struct nand_ecclayout onenand_oob_64 = { .eccbytes = 20, .eccpos = { 8, 9, 10, 11, 12, @@ -34,14 +33,14 @@ static struct nand_oobinfo onenand_oob_6 }, .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2}, - {24, 3}, {46, 2}, {40, 3}, {62, 2} } + {34, 3}, {46, 2}, {50, 3}, {62, 2} + } }; /** * onenand_oob_32 - oob info for middle (1KB) page */ -static struct nand_oobinfo onenand_oob_32 = { - .useecc = MTD_NANDECC_AUTOPLACE, +static struct nand_ecclayout onenand_oob_32 = { .eccbytes = 10, .eccpos = { 8, 9, 10, 11, 12, @@ -190,7 +189,7 @@ static int onenand_buffer_address(int da static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len) { struct onenand_chip *this = mtd->priv; - int value, readcmd = 0; + int value, readcmd = 0, block_cmd = 0; int block, page; /* Now we use page size operation */ int sectors = 4, count = 4; @@ -206,6 +205,8 @@ static int onenand_command(struct mtd_in case ONENAND_CMD_ERASE: case ONENAND_CMD_BUFFERRAM: + case ONENAND_CMD_OTP_ACCESS: + block_cmd = 1; block = (int) (addr >> this->erase_shift); page = -1; break; @@ -233,6 +234,12 @@ static int onenand_command(struct mtd_in /* Write 'DFS, FBA' of Flash */ value = onenand_block_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); + + if (block_cmd) { + /* Select DataRAM for DDP */ + value = onenand_bufferram_address(this, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); + } } if (page != -1) { @@ -301,6 +308,7 @@ static int onenand_wait(struct mtd_info if (state != FL_READING) cond_resched(); + touch_softlockup_watchdog(); } /* To get correct interrupt status in timeout case */ interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); @@ -344,7 +352,7 @@ static inline int onenand_bufferram_offs if (ONENAND_CURRENT_BUFFERRAM(this)) { if (area == ONENAND_DATARAM) - return mtd->oobblock; + return mtd->writesize; if (area == ONENAND_SPARERAM) return mtd->oobsize; } @@ -372,6 +380,17 @@ static int onenand_read_bufferram(struct bufferram += onenand_bufferram_offset(mtd, area); + if (ONENAND_CHECK_BYTE_ACCESS(count)) { + unsigned short word; + + /* Align with word(16-bit) size */ + count--; + + /* Read word and save byte */ + word = this->read_word(bufferram + offset + count); + buffer[count] = (word & 0xff); + } + memcpy(buffer, bufferram + offset, count); return 0; @@ -399,6 +418,17 @@ static int onenand_sync_read_bufferram(s this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ); + if (ONENAND_CHECK_BYTE_ACCESS(count)) { + unsigned short word; + + /* Align with word(16-bit) size */ + count--; + + /* Read word and save byte */ + word = this->read_word(bufferram + offset + count); + buffer[count] = (word & 0xff); + } + memcpy(buffer, bufferram + offset, count); this->mmcontrol(mtd, 0); @@ -426,6 +456,22 @@ static int onenand_write_bufferram(struc bufferram += onenand_bufferram_offset(mtd, area); + if (ONENAND_CHECK_BYTE_ACCESS(count)) { + unsigned short word; + int byte_offset; + + /* Align with word(16-bit) size */ + count--; + + /* Calculate byte access offset */ + byte_offset = offset + count; + + /* Read word and save byte */ + word = this->read_word(bufferram + byte_offset); + word = (word & ~0xff) | buffer[count]; + this->write_word(word, bufferram + byte_offset); + } + memcpy(bufferram + offset, buffer, count); return 0; @@ -549,31 +595,28 @@ static void onenand_release_device(struc } /** - * onenand_read_ecc - [MTD Interface] Read data with ECC + * onenand_read - [MTD Interface] Read data from flash * @param mtd MTD device structure * @param from offset to read from * @param len number of bytes to read * @param retlen pointer to variable to store the number of read bytes * @param buf the databuffer to put data - * @param oob_buf filesystem supplied oob data buffer - * @param oobsel oob selection structure * - * OneNAND read with ECC - */ -static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf, - u_char *oob_buf, struct nand_oobinfo *oobsel) + * Read with ecc +*/ +static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) { struct onenand_chip *this = mtd->priv; int read = 0, column; int thislen; int ret = 0; - DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); + DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); /* Do not allow reads past end of device */ if ((from + len) > mtd->size) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: Attempt read beyond end of device\n"); + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: Attempt read beyond end of device\n"); *retlen = 0; return -EINVAL; } @@ -584,14 +627,14 @@ static int onenand_read_ecc(struct mtd_i /* TODO handling oob */ while (read < len) { - thislen = min_t(int, mtd->oobblock, len - read); + thislen = min_t(int, mtd->writesize, len - read); - column = from & (mtd->oobblock - 1); - if (column + thislen > mtd->oobblock) - thislen = mtd->oobblock - column; + column = from & (mtd->writesize - 1); + if (column + thislen > mtd->writesize) + thislen = mtd->writesize - column; if (!onenand_check_bufferram(mtd, from)) { - this->command(mtd, ONENAND_CMD_READ, from, mtd->oobblock); + this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize); ret = this->wait(mtd, FL_READING); /* First copy data and check return value for ECC handling */ @@ -606,7 +649,7 @@ static int onenand_read_ecc(struct mtd_i break; if (ret) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: read failed = %d\n", ret); + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret); goto out; } @@ -628,23 +671,7 @@ out: } /** - * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc - * @param mtd MTD device structure - * @param from offset to read from - * @param len number of bytes to read - * @param retlen pointer to variable to store the number of read bytes - * @param buf the databuffer to put data - * - * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL -*/ -static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL); -} - -/** - * onenand_read_oob - [MTD Interface] OneNAND read out-of-band + * onenand_do_read_oob - [MTD Interface] OneNAND read out-of-band * @param mtd MTD device structure * @param from offset to read from * @param len number of bytes to read @@ -653,8 +680,8 @@ static int onenand_read(struct mtd_info * * OneNAND read out-of-band data from the spare area */ -static int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) +int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) { struct onenand_chip *this = mtd->priv; int read = 0, thislen, column; @@ -704,7 +731,7 @@ static int onenand_read_oob(struct mtd_i /* Read more? */ if (read < len) { /* Page size */ - from += mtd->oobblock; + from += mtd->writesize; column = 0; } } @@ -717,8 +744,53 @@ out: return ret; } +/** + * onenand_read_oob - [MTD Interface] NAND write data and/or out-of-band + * @mtd: MTD device structure + * @from: offset to read from + * @ops: oob operation description structure + */ +static int onenand_read_oob(struct mtd_info *mtd, loff_t from, + struct mtd_oob_ops *ops) +{ + BUG_ON(ops->mode != MTD_OOB_PLACE); + + return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->len, + &ops->retlen, ops->oobbuf); +} + #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE /** + * onenand_verify_oob - [GENERIC] verify the oob contents after a write + * @param mtd MTD device structure + * @param buf the databuffer to verify + * @param to offset to read from + * @param len number of bytes to read and compare + * + */ +static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to, int len) +{ + struct onenand_chip *this = mtd->priv; + char *readp = this->page_buf; + int column = to & (mtd->oobsize - 1); + int status, i; + + this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize); + onenand_update_bufferram(mtd, to, 0); + status = this->wait(mtd, FL_READING); + if (status) + return status; + + this->read_bufferram(mtd, ONENAND_SPARERAM, readp, column, len); + + for(i = 0; i < len; i++) + if (buf[i] != 0xFF && buf[i] != readp[i]) + return -EBADMSG; + + return 0; +} + +/** * onenand_verify_page - [GENERIC] verify the chip contents after a write * @param mtd MTD device structure * @param buf the databuffer to verify @@ -731,7 +803,7 @@ static int onenand_verify_page(struct mt void __iomem *dataram0, *dataram1; int ret = 0; - this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock); + this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize); ret = this->wait(mtd, FL_READING); if (ret) @@ -741,53 +813,51 @@ static int onenand_verify_page(struct mt /* Check, if the two dataram areas are same */ dataram0 = this->base + ONENAND_DATARAM; - dataram1 = dataram0 + mtd->oobblock; + dataram1 = dataram0 + mtd->writesize; - if (memcmp(dataram0, dataram1, mtd->oobblock)) + if (memcmp(dataram0, dataram1, mtd->writesize)) return -EBADMSG; return 0; } #else #define onenand_verify_page(...) (0) +#define onenand_verify_oob(...) (0) #endif -#define NOTALIGNED(x) ((x & (mtd->oobblock - 1)) != 0) +#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0) /** - * onenand_write_ecc - [MTD Interface] OneNAND write with ECC + * onenand_write - [MTD Interface] write buffer to FLASH * @param mtd MTD device structure * @param to offset to write to * @param len number of bytes to write * @param retlen pointer to variable to store the number of written bytes * @param buf the data to write - * @param eccbuf filesystem supplied oob data buffer - * @param oobsel oob selection structure * - * OneNAND write with ECC + * Write with ECC */ -static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, - u_char *eccbuf, struct nand_oobinfo *oobsel) +static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) { struct onenand_chip *this = mtd->priv; int written = 0; int ret = 0; - DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); + DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); /* Initialize retlen, in case of early exit */ *retlen = 0; /* Do not allow writes past end of device */ if (unlikely((to + len) > mtd->size)) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt write to past end of device\n"); + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt write to past end of device\n"); return -EINVAL; } /* Reject writes, which are not page aligned */ if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt to write not page aligned data\n"); + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt to write not page aligned data\n"); return -EINVAL; } @@ -796,20 +866,20 @@ static int onenand_write_ecc(struct mtd_ /* Loop until all data write */ while (written < len) { - int thislen = min_t(int, mtd->oobblock, len - written); + int thislen = min_t(int, mtd->writesize, len - written); - this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock); + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize); this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen); this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); - this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock); + this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize); onenand_update_bufferram(mtd, to, 1); ret = this->wait(mtd, FL_WRITING); if (ret) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: write filaed %d\n", ret); + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret); goto out; } @@ -818,7 +888,7 @@ static int onenand_write_ecc(struct mtd_ /* Only check verify write turn on */ ret = onenand_verify_page(mtd, (u_char *) buf, to); if (ret) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: verify failed %d\n", ret); + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret); goto out; } @@ -839,24 +909,7 @@ out: } /** - * onenand_write - [MTD Interface] compability function for onenand_write_ecc - * @param mtd MTD device structure - * @param to offset to write to - * @param len number of bytes to write - * @param retlen pointer to variable to store the number of written bytes - * @param buf the data to write - * - * This function simply calls onenand_write_ecc - * with oob buffer and oobsel = NULL - */ -static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL); -} - -/** - * onenand_write_oob - [MTD Interface] OneNAND write out-of-band + * onenand_do_write_oob - [Internal] OneNAND write out-of-band * @param mtd MTD device structure * @param to offset to write to * @param len number of bytes to write @@ -865,11 +918,11 @@ static int onenand_write(struct mtd_info * * OneNAND write out-of-band */ -static int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) +static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) { struct onenand_chip *this = mtd->priv; - int column, status; + int column, ret = 0; int written = 0; DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); @@ -894,16 +947,27 @@ static int onenand_write_oob(struct mtd_ this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize); - this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); - this->write_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); + /* We send data to spare ram with oobsize + * to prevent byte access */ + memset(this->page_buf, 0xff, mtd->oobsize); + memcpy(this->page_buf + column, buf, thislen); + this->write_bufferram(mtd, ONENAND_SPARERAM, this->page_buf, 0, mtd->oobsize); this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize); onenand_update_bufferram(mtd, to, 0); - status = this->wait(mtd, FL_WRITING); - if (status) + ret = this->wait(mtd, FL_WRITING); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: write filaed %d\n", ret); + goto out; + } + + ret = onenand_verify_oob(mtd, buf, to, thislen); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: verify failed %d\n", ret); goto out; + } written += thislen; @@ -920,145 +984,22 @@ out: *retlen = written; - return 0; + return ret; } /** - * onenand_writev_ecc - [MTD Interface] write with iovec with ecc - * @param mtd MTD device structure - * @param vecs the iovectors to write - * @param count number of vectors - * @param to offset to write to - * @param retlen pointer to variable to store the number of written bytes - * @param eccbuf filesystem supplied oob data buffer - * @param oobsel oob selection structure - * - * OneNAND write with iovec with ecc + * onenand_write_oob - [MTD Interface] NAND write data and/or out-of-band + * @mtd: MTD device structure + * @from: offset to read from + * @ops: oob operation description structure */ -static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t *retlen, - u_char *eccbuf, struct nand_oobinfo *oobsel) +static int onenand_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops) { - struct onenand_chip *this = mtd->priv; - unsigned char *pbuf; - size_t total_len, len; - int i, written = 0; - int ret = 0; - - /* Preset written len for early exit */ - *retlen = 0; - - /* Calculate total length of data */ - total_len = 0; - for (i = 0; i < count; i++) - total_len += vecs[i].iov_len; - - DEBUG(MTD_DEBUG_LEVEL3, "onenand_writev_ecc: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count); - - /* Do not allow write past end of the device */ - if (unlikely((to + total_len) > mtd->size)) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempted write past end of device\n"); - return -EINVAL; - } - - /* Reject writes, which are not page aligned */ - if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(total_len))) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempt to write not page aligned data\n"); - return -EINVAL; - } - - /* Grab the lock and see if the device is available */ - onenand_get_device(mtd, FL_WRITING); - - /* TODO handling oob */ - - /* Loop until all keve's data has been written */ - len = 0; - while (count) { - pbuf = this->page_buf; - /* - * If the given tuple is >= pagesize then - * write it out from the iov - */ - if ((vecs->iov_len - len) >= mtd->oobblock) { - pbuf = vecs->iov_base + len; - - len += mtd->oobblock; - - /* Check, if we have to switch to the next tuple */ - if (len >= (int) vecs->iov_len) { - vecs++; - len = 0; - count--; - } - } else { - int cnt = 0, thislen; - while (cnt < mtd->oobblock) { - thislen = min_t(int, mtd->oobblock - cnt, vecs->iov_len - len); - memcpy(this->page_buf + cnt, vecs->iov_base + len, thislen); - cnt += thislen; - len += thislen; - - /* Check, if we have to switch to the next tuple */ - if (len >= (int) vecs->iov_len) { - vecs++; - len = 0; - count--; - } - } - } - - this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock); + BUG_ON(ops->mode != MTD_OOB_PLACE); - this->write_bufferram(mtd, ONENAND_DATARAM, pbuf, 0, mtd->oobblock); - this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); - - this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock); - - onenand_update_bufferram(mtd, to, 1); - - ret = this->wait(mtd, FL_WRITING); - if (ret) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: write failed %d\n", ret); - goto out; - } - - - /* Only check verify write turn on */ - ret = onenand_verify_page(mtd, (u_char *) pbuf, to); - if (ret) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: verify failed %d\n", ret); - goto out; - } - - written += mtd->oobblock; - - to += mtd->oobblock; - } - -out: - /* Deselect and wakt up anyone waiting on the device */ - onenand_release_device(mtd); - - *retlen = written; - - return 0; -} - -/** - * onenand_writev - [MTD Interface] compabilty function for onenand_writev_ecc - * @param mtd MTD device structure - * @param vecs the iovectors to write - * @param count number of vectors - * @param to offset to write to - * @param retlen pointer to variable to store the number of written bytes - * - * OneNAND write with kvec. This just calls the ecc function - */ -static int onenand_writev(struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t *retlen) -{ - return onenand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL); + return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->len, + &ops->retlen, ops->oobbuf); } /** @@ -1227,7 +1168,7 @@ static int onenand_default_block_markbad /* We write two bytes, so we dont have to mess with 16 bit access */ ofs += mtd->oobsize + (bbm->badblockpos & ~0x01); - return mtd->write_oob(mtd, ofs , 2, &retlen, buf); + return onenand_do_write_oob(mtd, ofs , 2, &retlen, buf); } /** @@ -1324,6 +1265,304 @@ static int onenand_unlock(struct mtd_inf return 0; } +#ifdef CONFIG_MTD_ONENAND_OTP + +/* Interal OTP operation */ +typedef int (*otp_op_t)(struct mtd_info *mtd, loff_t form, size_t len, + size_t *retlen, u_char *buf); + +/** + * do_otp_read - [DEFAULT] Read OTP block area + * @param mtd MTD device structure + * @param from The offset to read + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of readbytes + * @param buf the databuffer to put/get data + * + * Read OTP block area. + */ +static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct onenand_chip *this = mtd->priv; + int ret; + + /* Enter OTP access mode */ + this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); + this->wait(mtd, FL_OTPING); + + ret = mtd->read(mtd, from, len, retlen, buf); + + /* Exit OTP access mode */ + this->command(mtd, ONENAND_CMD_RESET, 0, 0); + this->wait(mtd, FL_RESETING); + + return ret; +} + +/** + * do_otp_write - [DEFAULT] Write OTP block area + * @param mtd MTD device structure + * @param from The offset to write + * @param len number of bytes to write + * @param retlen pointer to variable to store the number of write bytes + * @param buf the databuffer to put/get data + * + * Write OTP block area. + */ +static int do_otp_write(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct onenand_chip *this = mtd->priv; + unsigned char *pbuf = buf; + int ret; + + /* Force buffer page aligned */ + if (len < mtd->writesize) { + memcpy(this->page_buf, buf, len); + memset(this->page_buf + len, 0xff, mtd->writesize - len); + pbuf = this->page_buf; + len = mtd->writesize; + } + + /* Enter OTP access mode */ + this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); + this->wait(mtd, FL_OTPING); + + ret = mtd->write(mtd, from, len, retlen, pbuf); + + /* Exit OTP access mode */ + this->command(mtd, ONENAND_CMD_RESET, 0, 0); + this->wait(mtd, FL_RESETING); + + return ret; +} + +/** + * do_otp_lock - [DEFAULT] Lock OTP block area + * @param mtd MTD device structure + * @param from The offset to lock + * @param len number of bytes to lock + * @param retlen pointer to variable to store the number of lock bytes + * @param buf the databuffer to put/get data + * + * Lock OTP block area. + */ +static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct onenand_chip *this = mtd->priv; + int ret; + + /* Enter OTP access mode */ + this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); + this->wait(mtd, FL_OTPING); + + ret = onenand_do_write_oob(mtd, from, len, retlen, buf); + + /* Exit OTP access mode */ + this->command(mtd, ONENAND_CMD_RESET, 0, 0); + this->wait(mtd, FL_RESETING); + + return ret; +} + +/** + * onenand_otp_walk - [DEFAULT] Handle OTP operation + * @param mtd MTD device structure + * @param from The offset to read/write + * @param len number of bytes to read/write + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put/get data + * @param action do given action + * @param mode specify user and factory + * + * Handle OTP operation. + */ +static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf, + otp_op_t action, int mode) +{ + struct onenand_chip *this = mtd->priv; + int otp_pages; + int density; + int ret = 0; + + *retlen = 0; + + density = this->device_id >> ONENAND_DEVICE_DENSITY_SHIFT; + if (density < ONENAND_DEVICE_DENSITY_512Mb) + otp_pages = 20; + else + otp_pages = 10; + + if (mode == MTD_OTP_FACTORY) { + from += mtd->writesize * otp_pages; + otp_pages = 64 - otp_pages; + } + + /* Check User/Factory boundary */ + if (((mtd->writesize * otp_pages) - (from + len)) < 0) + return 0; + + while (len > 0 && otp_pages > 0) { + if (!action) { /* OTP Info functions */ + struct otp_info *otpinfo; + + len -= sizeof(struct otp_info); + if (len <= 0) + return -ENOSPC; + + otpinfo = (struct otp_info *) buf; + otpinfo->start = from; + otpinfo->length = mtd->writesize; + otpinfo->locked = 0; + + from += mtd->writesize; + buf += sizeof(struct otp_info); + *retlen += sizeof(struct otp_info); + } else { + size_t tmp_retlen; + int size = len; + + ret = action(mtd, from, len, &tmp_retlen, buf); + + buf += size; + len -= size; + *retlen += size; + + if (ret < 0) + return ret; + } + otp_pages--; + } + + return 0; +} + +/** + * onenand_get_fact_prot_info - [MTD Interface] Read factory OTP info + * @param mtd MTD device structure + * @param buf the databuffer to put/get data + * @param len number of bytes to read + * + * Read factory OTP info. + */ +static int onenand_get_fact_prot_info(struct mtd_info *mtd, + struct otp_info *buf, size_t len) +{ + size_t retlen; + int ret; + + ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_FACTORY); + + return ret ? : retlen; +} + +/** + * onenand_read_fact_prot_reg - [MTD Interface] Read factory OTP area + * @param mtd MTD device structure + * @param from The offset to read + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put/get data + * + * Read factory OTP area. + */ +static int onenand_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, + size_t len, size_t *retlen, u_char *buf) +{ + return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_FACTORY); +} + +/** + * onenand_get_user_prot_info - [MTD Interface] Read user OTP info + * @param mtd MTD device structure + * @param buf the databuffer to put/get data + * @param len number of bytes to read + * + * Read user OTP info. + */ +static int onenand_get_user_prot_info(struct mtd_info *mtd, + struct otp_info *buf, size_t len) +{ + size_t retlen; + int ret; + + ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_USER); + + return ret ? : retlen; +} + +/** + * onenand_read_user_prot_reg - [MTD Interface] Read user OTP area + * @param mtd MTD device structure + * @param from The offset to read + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put/get data + * + * Read user OTP area. + */ +static int onenand_read_user_prot_reg(struct mtd_info *mtd, loff_t from, + size_t len, size_t *retlen, u_char *buf) +{ + return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_USER); +} + +/** + * onenand_write_user_prot_reg - [MTD Interface] Write user OTP area + * @param mtd MTD device structure + * @param from The offset to write + * @param len number of bytes to write + * @param retlen pointer to variable to store the number of write bytes + * @param buf the databuffer to put/get data + * + * Write user OTP area. + */ +static int onenand_write_user_prot_reg(struct mtd_info *mtd, loff_t from, + size_t len, size_t *retlen, u_char *buf) +{ + return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_write, MTD_OTP_USER); +} + +/** + * onenand_lock_user_prot_reg - [MTD Interface] Lock user OTP area + * @param mtd MTD device structure + * @param from The offset to lock + * @param len number of bytes to unlock + * + * Write lock mark on spare area in page 0 in OTP block + */ +static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, + size_t len) +{ + unsigned char oob_buf[64]; + size_t retlen; + int ret; + + memset(oob_buf, 0xff, mtd->oobsize); + /* + * Note: OTP lock operation + * OTP block : 0xXXFC + * 1st block : 0xXXF3 (If chip support) + * Both : 0xXXF0 (If chip support) + */ + oob_buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC; + + /* + * Write lock mark to 8th word of sector0 of page0 of the spare0. + * We write 16 bytes spare area instead of 2 bytes. + */ + from = 0; + len = 16; + + ret = onenand_otp_walk(mtd, from, len, &retlen, oob_buf, do_otp_lock, MTD_OTP_USER); + + return ret ? : retlen; +} +#endif /* CONFIG_MTD_ONENAND_OTP */ + /** * onenand_print_device_info - Print device ID * @param device device ID @@ -1423,15 +1662,15 @@ static int onenand_probe(struct mtd_info /* OneNAND page size & block size */ /* The data buffer size is equal to page size */ - mtd->oobblock = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); - mtd->oobsize = mtd->oobblock >> 5; + mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); + mtd->oobsize = mtd->writesize >> 5; /* Pagers per block is always 64 in OneNAND */ - mtd->erasesize = mtd->oobblock << 6; + mtd->erasesize = mtd->writesize << 6; this->erase_shift = ffs(mtd->erasesize) - 1; - this->page_shift = ffs(mtd->oobblock) - 1; + this->page_shift = ffs(mtd->writesize) - 1; this->ppb_shift = (this->erase_shift - this->page_shift); - this->page_mask = (mtd->erasesize / mtd->oobblock) - 1; + this->page_mask = (mtd->erasesize / mtd->writesize) - 1; /* REVIST: Multichip handling */ @@ -1475,7 +1714,6 @@ static void onenand_resume(struct mtd_in "in suspended state\n"); } - /** * onenand_scan - [OneNAND Interface] Scan for the OneNAND device * @param mtd MTD device structure @@ -1522,7 +1760,7 @@ int onenand_scan(struct mtd_info *mtd, i /* Allocate buffers, if necessary */ if (!this->page_buf) { size_t len; - len = mtd->oobblock + mtd->oobsize; + len = mtd->writesize + mtd->oobsize; this->page_buf = kmalloc(len, GFP_KERNEL); if (!this->page_buf) { printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n"); @@ -1537,40 +1775,42 @@ int onenand_scan(struct mtd_info *mtd, i switch (mtd->oobsize) { case 64: - this->autooob = &onenand_oob_64; + this->ecclayout = &onenand_oob_64; break; case 32: - this->autooob = &onenand_oob_32; + this->ecclayout = &onenand_oob_32; break; default: printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n", mtd->oobsize); /* To prevent kernel oops */ - this->autooob = &onenand_oob_32; + this->ecclayout = &onenand_oob_32; break; } - memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); + mtd->ecclayout = this->ecclayout; /* Fill in remaining MTD driver data */ mtd->type = MTD_NANDFLASH; - mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; + mtd->flags = MTD_CAP_NANDFLASH; mtd->ecctype = MTD_ECC_SW; mtd->erase = onenand_erase; mtd->point = NULL; mtd->unpoint = NULL; mtd->read = onenand_read; mtd->write = onenand_write; - mtd->read_ecc = onenand_read_ecc; - mtd->write_ecc = onenand_write_ecc; mtd->read_oob = onenand_read_oob; mtd->write_oob = onenand_write_oob; - mtd->readv = NULL; - mtd->readv_ecc = NULL; - mtd->writev = onenand_writev; - mtd->writev_ecc = onenand_writev_ecc; +#ifdef CONFIG_MTD_ONENAND_OTP + mtd->get_fact_prot_info = onenand_get_fact_prot_info; + mtd->read_fact_prot_reg = onenand_read_fact_prot_reg; + mtd->get_user_prot_info = onenand_get_user_prot_info; + mtd->read_user_prot_reg = onenand_read_user_prot_reg; + mtd->write_user_prot_reg = onenand_write_user_prot_reg; + mtd->lock_user_prot_reg = onenand_lock_user_prot_reg; +#endif mtd->sync = onenand_sync; mtd->lock = NULL; mtd->unlock = onenand_unlock; diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index 4510d33..1b00dac 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -17,6 +17,9 @@ #include #include #include +extern int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); + /** * check_short_pattern - [GENERIC] check if a pattern is in the buffer * @param buf the buffer to search @@ -87,13 +90,13 @@ static int create_bbt(struct mtd_info *m /* No need to read pages fully, * just read required OOB bytes */ - ret = mtd->read_oob(mtd, from + j * mtd->oobblock + bd->offs, - readlen, &retlen, &buf[0]); + ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs, + readlen, &retlen, &buf[0]); if (ret) return ret; - if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { + if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) { bbm->bbt[i >> 3] |= 0x03 << (i & 0x6); printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", i >> 1, (unsigned int) from); diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index c077d2e..5b58523 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c @@ -1,5 +1,5 @@ /* - * $Id: redboot.c,v 1.19 2005/12/01 10:03:51 dwmw2 Exp $ + * $Id: redboot.c,v 1.21 2006/03/30 18:34:37 bjd Exp $ * * Parse RedBoot-style Flash Image System (FIS) tables and * produce a Linux partition array to match. @@ -15,14 +15,14 @@ #include struct fis_image_desc { unsigned char name[16]; // Null terminated name - unsigned long flash_base; // Address within FLASH of image - unsigned long mem_base; // Address in memory where it executes - unsigned long size; // Length of image - unsigned long entry_point; // Execution entry point - unsigned long data_length; // Length of actual data - unsigned char _pad[256-(16+7*sizeof(unsigned long))]; - unsigned long desc_cksum; // Checksum over image descriptor - unsigned long file_cksum; // Checksum over image data + uint32_t flash_base; // Address within FLASH of image + uint32_t mem_base; // Address in memory where it executes + uint32_t size; // Length of image + uint32_t entry_point; // Execution entry point + uint32_t data_length; // Length of actual data + unsigned char _pad[256-(16+7*sizeof(uint32_t))]; + uint32_t desc_cksum; // Checksum over image descriptor + uint32_t file_cksum; // Checksum over image data }; struct fis_list { diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index a3e00a4..fa4362f 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c @@ -3,7 +3,7 @@ * * Copyright (C) 2005 Sean Young * - * $Id: rfd_ftl.c,v 1.5 2005/11/07 11:14:21 gleixner Exp $ + * $Id: rfd_ftl.c,v 1.8 2006/01/15 12:51:44 sean Exp $ * * This type of flash translation layer (FTL) is used by the Embedded BIOS * by General Software. It is known as the Resident Flash Disk (RFD), see: @@ -61,6 +61,7 @@ struct block { BLOCK_OK, BLOCK_ERASING, BLOCK_ERASED, + BLOCK_UNUSED, BLOCK_FAILED } state; int free_sectors; @@ -99,10 +100,8 @@ static int build_block_map(struct partit block->offset = part->block_size * block_no; if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) { - block->state = BLOCK_ERASED; /* assumption */ - block->free_sectors = part->data_sectors_per_block; - part->reserved_block = block_no; - return 1; + block->state = BLOCK_UNUSED; + return -ENOENT; } block->state = BLOCK_OK; @@ -124,7 +123,7 @@ static int build_block_map(struct partit entry = 0; if (entry >= part->sector_count) { - printk(KERN_NOTICE PREFIX + printk(KERN_WARNING PREFIX "'%s': unit #%d: entry %d corrupt, " "sector %d out of range\n", part->mbd.mtd->name, block_no, i, entry); @@ -132,7 +131,7 @@ static int build_block_map(struct partit } if (part->sector_map[entry] != -1) { - printk(KERN_NOTICE PREFIX + printk(KERN_WARNING PREFIX "'%s': more than one entry for sector %d\n", part->mbd.mtd->name, entry); part->errors = 1; @@ -167,7 +166,7 @@ static int scan_header(struct partition /* each erase block has three bytes header, followed by the map */ part->header_sectors_per_block = ((HEADER_MAP_OFFSET + sectors_per_block) * - sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE; + sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE; part->data_sectors_per_block = sectors_per_block - part->header_sectors_per_block; @@ -226,7 +225,7 @@ static int scan_header(struct partition } if (part->reserved_block == -1) { - printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n", + printk(KERN_WARNING PREFIX "'%s': no empty erase unit found\n", part->mbd.mtd->name); part->errors = 1; @@ -315,7 +314,7 @@ static void erase_callback(struct erase_ rc = -EIO; if (rc) { - printk(KERN_NOTICE PREFIX "'%s': unable to write RFD " + printk(KERN_ERR PREFIX "'%s': unable to write RFD " "header at 0x%lx\n", part->mbd.mtd->name, part->blocks[i].offset); @@ -348,7 +347,7 @@ static int erase_block(struct partition rc = part->mbd.mtd->erase(part->mbd.mtd, erase); if (rc) { - printk(KERN_WARNING PREFIX "erase of region %x,%x on '%s' " + printk(KERN_ERR PREFIX "erase of region %x,%x on '%s' " "failed\n", erase->addr, erase->len, part->mbd.mtd->name); kfree(erase); @@ -383,7 +382,7 @@ static int move_block_contents(struct pa rc = -EIO; if (rc) { - printk(KERN_NOTICE PREFIX "error reading '%s' at " + printk(KERN_ERR PREFIX "error reading '%s' at " "0x%lx\n", part->mbd.mtd->name, part->blocks[block_no].offset); @@ -423,7 +422,7 @@ static int move_block_contents(struct pa rc = -EIO; if (rc) { - printk(KERN_NOTICE PREFIX "'%s': Unable to " + printk(KERN_ERR PREFIX "'%s': Unable to " "read sector for relocation\n", part->mbd.mtd->name); @@ -520,7 +519,7 @@ static int reclaim_block(struct partitio * because if we fill that one up first it'll have the most chance of having * the least live sectors at reclaim. */ -static int find_free_block(const struct partition *part) +static int find_free_block(struct partition *part) { int block, stop; @@ -533,6 +532,9 @@ static int find_free_block(const struct block != part->reserved_block) return block; + if (part->blocks[block].state == BLOCK_UNUSED) + erase_block(part, block); + if (++block >= part->total_blocks) block = 0; @@ -541,7 +543,7 @@ static int find_free_block(const struct return -1; } -static int find_writeable_block(struct partition *part, u_long *old_sector) +static int find_writable_block(struct partition *part, u_long *old_sector) { int rc, block; size_t retlen; @@ -570,7 +572,7 @@ static int find_writeable_block(struct p rc = -EIO; if (rc) { - printk(KERN_NOTICE PREFIX "'%s': unable to read header at " + printk(KERN_ERR PREFIX "'%s': unable to read header at " "0x%lx\n", part->mbd.mtd->name, part->blocks[block].offset); goto err; @@ -602,7 +604,7 @@ static int mark_sector_deleted(struct pa rc = -EIO; if (rc) { - printk(KERN_WARNING PREFIX "error writing '%s' at " + printk(KERN_ERR PREFIX "error writing '%s' at " "0x%lx\n", part->mbd.mtd->name, addr); if (rc) goto err; @@ -652,7 +654,7 @@ static int do_writesect(struct mtd_blktr if (part->current_block == -1 || !part->blocks[part->current_block].free_sectors) { - rc = find_writeable_block(part, old_addr); + rc = find_writable_block(part, old_addr); if (rc) goto err; } @@ -675,7 +677,7 @@ static int do_writesect(struct mtd_blktr rc = -EIO; if (rc) { - printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n", + printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n", part->mbd.mtd->name, addr); if (rc) goto err; @@ -695,7 +697,7 @@ static int do_writesect(struct mtd_blktr rc = -EIO; if (rc) { - printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n", + printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n", part->mbd.mtd->name, addr); if (rc) goto err; @@ -776,7 +778,7 @@ static void rfd_ftl_add_mtd(struct mtd_b part->block_size = block_size; else { if (!mtd->erasesize) { - printk(KERN_NOTICE PREFIX "please provide block_size"); + printk(KERN_WARNING PREFIX "please provide block_size"); return; } else @@ -791,8 +793,8 @@ static void rfd_ftl_add_mtd(struct mtd_b if (!(mtd->flags & MTD_WRITEABLE)) part->mbd.readonly = 1; else if (part->errors) { - printk(KERN_NOTICE PREFIX "'%s': errors found, " - "setting read-only", mtd->name); + printk(KERN_WARNING PREFIX "'%s': errors found, " + "setting read-only\n", mtd->name); part->mbd.readonly = 1; } diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index f6d51ce..07136ec 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -508,11 +508,11 @@ static int el_start_xmit(struct sk_buff * speak of. We simply pull the packet out of its PIO buffer (which is slow) * and queue it for the kernel. Then we reset the card for the next packet. * - * We sometimes get suprise interrupts late both because the SMP IRQ delivery + * We sometimes get surprise interrupts late both because the SMP IRQ delivery * is message passing and because the card sometimes seems to deliver late. I * think if it is part way through a receive and the mode is changed it carries * on receiving and sends us an interrupt. We have to band aid all these cases - * to get a sensible 150kbytes/second performance. Even then you want a small + * to get a sensible 150kBytes/second performance. Even then you want a small * TCP window. */ @@ -909,7 +909,7 @@ MODULE_PARM_DESC(irq, "EtherLink IRQ num * here also causes the module to be unloaded */ -int init_module(void) +int __init init_module(void) { dev_3c501 = el1_probe(-1); if (IS_ERR(dev_3c501)) diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index dcc98af..cb5ef75 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -688,7 +688,7 @@ MODULE_LICENSE("GPL"); /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ -int +int __init init_module(void) { struct net_device *dev; diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index 111601c..19c0b85 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -1633,7 +1633,7 @@ MODULE_PARM_DESC(io, "EtherLink Plus I/O MODULE_PARM_DESC(irq, "EtherLink Plus IRQ number(s) (assigned)"); MODULE_PARM_DESC(dma, "EtherLink Plus DMA channel(s)"); -int init_module(void) +int __init init_module(void) { int this_dev, found = 0; diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index 4db8289..6039049 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -932,7 +932,7 @@ module_param(irq, int, 0); MODULE_PARM_DESC(io, "EtherLink16 I/O base address"); MODULE_PARM_DESC(irq, "(ignored)"); -int init_module(void) +int __init init_module(void) { if (io == 0) printk("3c507: You should not use auto-probing with insmod!\n"); diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index b40885d..4bf8510 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -1277,7 +1277,7 @@ MODULE_PARM_DESC(io, "EtherLink/MC I/O b MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)"); MODULE_LICENSE("GPL"); -int init_module(void) +int __init init_module(void) { int this_dev,found = 0; diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index 6db3301..157eda5 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -1031,8 +1031,7 @@ static int mc32_send_packet(struct sk_bu return 1; } - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) { + if (skb_padto(skb, ETH_ZLEN)) { netif_wake_queue(dev); return 0; } @@ -1646,7 +1645,7 @@ static struct net_device *this_device; * insmod multiple modules for now but it's a hack. */ -int init_module(void) +int __init init_module(void) { this_device = mc32_probe(-1); if (IS_ERR(this_device)) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 274b013..e277789 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1382,17 +1382,12 @@ static int __devinit vortex_probe1(struc for (i = 0; i < 6; i++) iowrite8(dev->dev_addr[i], ioaddr + i); -#ifdef __sparc__ - if (print_info) - printk(", IRQ %s\n", __irq_itoa(dev->irq)); -#else if (print_info) printk(", IRQ %d\n", dev->irq); /* Tell them about an invalid IRQ. */ if (dev->irq <= 0 || dev->irq >= NR_IRQS) printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n", dev->irq); -#endif EL3WINDOW(4); step = (ioread8(ioaddr + Wn4_NetDiag) & 0x1e) >> 1; diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 066e22b..0cdc830 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -19,11 +19,11 @@ See the file COPYING in this distribution for more information. Contributors: - + Wake-on-LAN support - Felipe Damasio PCI suspend/resume - Felipe Damasio LinkChg interrupt - Felipe Damasio - + TODO: * Test Tx checksumming thoroughly * Implement dev->tx_timeout @@ -401,6 +401,11 @@ static void cp_clean_rings (struct cp_pr #ifdef CONFIG_NET_POLL_CONTROLLER static void cp_poll_controller(struct net_device *dev); #endif +static int cp_get_eeprom_len(struct net_device *dev); +static int cp_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data); +static int cp_set_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data); static struct pci_device_id cp_pci_tbl[] = { { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139, @@ -461,7 +466,7 @@ #endif /* CP_VLAN_TAG_USED */ static inline void cp_set_rxbufsize (struct cp_private *cp) { unsigned int mtu = cp->dev->mtu; - + if (mtu > ETH_DATA_LEN) /* MTU + ethernet header + FCS + optional VLAN tag */ cp->rx_buf_sz = mtu + ETH_HLEN + 8; @@ -510,7 +515,7 @@ static void cp_rx_err_acct (struct cp_pr static inline unsigned int cp_rx_csum_ok (u32 status) { unsigned int protocol = (status >> 16) & 0x3; - + if (likely((protocol == RxProtoTCP) && (!(status & TCPFail)))) return 1; else if ((protocol == RxProtoUDP) && (!(status & UDPFail))) @@ -792,7 +797,7 @@ #endif entry = cp->tx_head; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; if (dev->features & NETIF_F_TSO) - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; if (skb_shinfo(skb)->nr_frags == 0) { struct cp_desc *txd = &cp->tx_ring[entry]; @@ -1061,7 +1066,7 @@ static void cp_init_hw (struct cp_privat cpw8(Config3, PARMEnable); cp->wol_enabled = 0; - cpw8(Config5, cpr8(Config5) & PMEStatus); + cpw8(Config5, cpr8(Config5) & PMEStatus); cpw32_f(HiTxRingAddr, 0); cpw32_f(HiTxRingAddr + 4, 0); @@ -1351,7 +1356,7 @@ static void netdev_get_wol (struct cp_pr WAKE_MCAST | WAKE_UCAST; /* We don't need to go on if WOL is disabled */ if (!cp->wol_enabled) return; - + options = cpr8 (Config3); if (options & LinkUp) wol->wolopts |= WAKE_PHY; if (options & MagicPacket) wol->wolopts |= WAKE_MAGIC; @@ -1577,6 +1582,9 @@ static struct ethtool_ops cp_ethtool_ops .get_strings = cp_get_strings, .get_ethtool_stats = cp_get_ethtool_stats, .get_perm_addr = ethtool_op_get_perm_addr, + .get_eeprom_len = cp_get_eeprom_len, + .get_eeprom = cp_get_eeprom, + .set_eeprom = cp_set_eeprom, }; static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) @@ -1612,24 +1620,32 @@ #define EE_ENB (0x80 | EE_CS) #define eeprom_delay() readl(ee_addr) /* The EEPROM commands include the alway-set leading bit. */ +#define EE_EXTEND_CMD (4) #define EE_WRITE_CMD (5) #define EE_READ_CMD (6) #define EE_ERASE_CMD (7) -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len) -{ - int i; - unsigned retval = 0; - void __iomem *ee_addr = ioaddr + Cfg9346; - int read_cmd = location | (EE_READ_CMD << addr_len); +#define EE_EWDS_ADDR (0) +#define EE_WRAL_ADDR (1) +#define EE_ERAL_ADDR (2) +#define EE_EWEN_ADDR (3) +#define CP_EEPROM_MAGIC PCI_DEVICE_ID_REALTEK_8139 + +static void eeprom_cmd_start(void __iomem *ee_addr) +{ writeb (EE_ENB & ~EE_CS, ee_addr); writeb (EE_ENB, ee_addr); eeprom_delay (); +} + +static void eeprom_cmd(void __iomem *ee_addr, int cmd, int cmd_len) +{ + int i; - /* Shift the read command bits out. */ - for (i = 4 + addr_len; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + /* Shift the command bits out. */ + for (i = cmd_len - 1; i >= 0; i--) { + int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0; writeb (EE_ENB | dataval, ee_addr); eeprom_delay (); writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); @@ -1637,6 +1653,33 @@ static int read_eeprom (void __iomem *io } writeb (EE_ENB, ee_addr); eeprom_delay (); +} + +static void eeprom_cmd_end(void __iomem *ee_addr) +{ + writeb (~EE_CS, ee_addr); + eeprom_delay (); +} + +static void eeprom_extend_cmd(void __iomem *ee_addr, int extend_cmd, + int addr_len) +{ + int cmd = (EE_EXTEND_CMD << addr_len) | (extend_cmd << (addr_len - 2)); + + eeprom_cmd_start(ee_addr); + eeprom_cmd(ee_addr, cmd, 3 + addr_len); + eeprom_cmd_end(ee_addr); +} + +static u16 read_eeprom (void __iomem *ioaddr, int location, int addr_len) +{ + int i; + u16 retval = 0; + void __iomem *ee_addr = ioaddr + Cfg9346; + int read_cmd = location | (EE_READ_CMD << addr_len); + + eeprom_cmd_start(ee_addr); + eeprom_cmd(ee_addr, read_cmd, 3 + addr_len); for (i = 16; i > 0; i--) { writeb (EE_ENB | EE_SHIFT_CLK, ee_addr); @@ -1648,13 +1691,125 @@ static int read_eeprom (void __iomem *io eeprom_delay (); } - /* Terminate the EEPROM access. */ - writeb (~EE_CS, ee_addr); - eeprom_delay (); + eeprom_cmd_end(ee_addr); return retval; } +static void write_eeprom(void __iomem *ioaddr, int location, u16 val, + int addr_len) +{ + int i; + void __iomem *ee_addr = ioaddr + Cfg9346; + int write_cmd = location | (EE_WRITE_CMD << addr_len); + + eeprom_extend_cmd(ee_addr, EE_EWEN_ADDR, addr_len); + + eeprom_cmd_start(ee_addr); + eeprom_cmd(ee_addr, write_cmd, 3 + addr_len); + eeprom_cmd(ee_addr, val, 16); + eeprom_cmd_end(ee_addr); + + eeprom_cmd_start(ee_addr); + for (i = 0; i < 20000; i++) + if (readb(ee_addr) & EE_DATA_READ) + break; + eeprom_cmd_end(ee_addr); + + eeprom_extend_cmd(ee_addr, EE_EWDS_ADDR, addr_len); +} + +static int cp_get_eeprom_len(struct net_device *dev) +{ + struct cp_private *cp = netdev_priv(dev); + int size; + + spin_lock_irq(&cp->lock); + size = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 256 : 128; + spin_unlock_irq(&cp->lock); + + return size; +} + +static int cp_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct cp_private *cp = netdev_priv(dev); + unsigned int addr_len; + u16 val; + u32 offset = eeprom->offset >> 1; + u32 len = eeprom->len; + u32 i = 0; + + eeprom->magic = CP_EEPROM_MAGIC; + + spin_lock_irq(&cp->lock); + + addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6; + + if (eeprom->offset & 1) { + val = read_eeprom(cp->regs, offset, addr_len); + data[i++] = (u8)(val >> 8); + offset++; + } + + while (i < len - 1) { + val = read_eeprom(cp->regs, offset, addr_len); + data[i++] = (u8)val; + data[i++] = (u8)(val >> 8); + offset++; + } + + if (i < len) { + val = read_eeprom(cp->regs, offset, addr_len); + data[i] = (u8)val; + } + + spin_unlock_irq(&cp->lock); + return 0; +} + +static int cp_set_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct cp_private *cp = netdev_priv(dev); + unsigned int addr_len; + u16 val; + u32 offset = eeprom->offset >> 1; + u32 len = eeprom->len; + u32 i = 0; + + if (eeprom->magic != CP_EEPROM_MAGIC) + return -EINVAL; + + spin_lock_irq(&cp->lock); + + addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6; + + if (eeprom->offset & 1) { + val = read_eeprom(cp->regs, offset, addr_len) & 0xff; + val |= (u16)data[i++] << 8; + write_eeprom(cp->regs, offset, val, addr_len); + offset++; + } + + while (i < len - 1) { + val = (u16)data[i++]; + val |= (u16)data[i++] << 8; + write_eeprom(cp->regs, offset, val, addr_len); + offset++; + } + + if (i < len) { + val = read_eeprom(cp->regs, offset, addr_len) & 0xff00; + val |= (u16)data[i]; + write_eeprom(cp->regs, offset, val, addr_len); + } + + spin_unlock_irq(&cp->lock); + return 0; +} + /* Put the board into D3cold state and wait for WakeUp signal */ static void cp_set_d3_state (struct cp_private *cp) { @@ -1919,7 +2074,7 @@ static int cp_resume (struct pci_dev *pd mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE); spin_unlock_irqrestore (&cp->lock, flags); - + return 0; } #endif /* CONFIG_PM */ diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index feae783..abd6261 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -165,7 +165,7 @@ static int multicast_filter_limit = 32; static int debug = -1; /* - * Receive ring size + * Receive ring size * Warning: 64K ring has hardware issues and may lock up. */ #if defined(CONFIG_SH_DREAMCAST) @@ -257,7 +257,7 @@ static struct pci_device_id rtl8139_pci_ {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, - {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, + {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, #ifdef CONFIG_SH_SECUREEDGE5410 /* Bogus 8139 silicon reports 8129 without external PROM :-( */ @@ -1824,7 +1824,7 @@ #ifdef CONFIG_8139_OLD_RX_RESET int tmp_work; #endif - if (netif_msg_rx_err (tp)) + if (netif_msg_rx_err (tp)) printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n", dev->name, rx_status); tp->stats.rx_errors++; @@ -1944,7 +1944,7 @@ static int rtl8139_rx(struct net_device RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); - while (netif_running(dev) && received < budget + while (netif_running(dev) && received < budget && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { u32 ring_offset = cur_rx % RX_BUF_LEN; u32 rx_status; @@ -2031,7 +2031,7 @@ #endif netif_receive_skb (skb); } else { - if (net_ratelimit()) + if (net_ratelimit()) printk (KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); @@ -2158,13 +2158,13 @@ static irqreturn_t rtl8139_interrupt (in status = RTL_R16 (IntrStatus); /* shared irq? */ - if (unlikely((status & rtl8139_intr_mask) == 0)) + if (unlikely((status & rtl8139_intr_mask) == 0)) goto out; handled = 1; /* h/w no longer present (hotplug?) or major error, bail */ - if (unlikely(status == 0xFFFF)) + if (unlikely(status == 0xFFFF)) goto out; /* close possible race's with dev_close */ diff --git a/drivers/net/82596.c b/drivers/net/82596.c index da0c878..8a9f7d6 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -1070,8 +1070,7 @@ static int i596_start_xmit(struct sk_buf skb->len, (unsigned int)skb->data)); if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/8390.c b/drivers/net/8390.c index f870274..86be96a 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -275,12 +275,14 @@ static int ei_start_xmit(struct sk_buff struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); int send_length = skb->len, output_page; unsigned long flags; + char buf[ETH_ZLEN]; + char *data = skb->data; if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; + memset(buf, 0, ETH_ZLEN); /* more efficient than doing just the needed bits */ + memcpy(buf, data, skb->len); send_length = ETH_ZLEN; + data = buf; } /* Mask interrupts from the ethercard. @@ -347,7 +349,7 @@ static int ei_start_xmit(struct sk_buff * trigger the send later, upon receiving a Tx done interrupt. */ - ei_block_output(dev, send_length, skb->data, output_page); + ei_block_output(dev, send_length, data, output_page); if (! ei_local->txing) { diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index bdaaad8..3918990 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -447,6 +447,7 @@ config MIPS_GT96100ETH config MIPS_AU1X00_ENET bool "MIPS AU1000 Ethernet support" depends on NET_ETHERNET && SOC_AU1X00 + select PHYLIB select CRC32 help If you have an Alchemy Semi AU1X00 based system @@ -853,6 +854,17 @@ config SMC9194 . The module will be called smc9194. +config NET_NETX + tristate "NetX Ethernet support" + select MII + depends on NET_ETHERNET && ARCH_NETX + help + This is support for the Hilscher netX builtin Ethernet ports + + To compile this driver as a module, choose M here and read + . The module + will be called netx-eth. + config DM9000 tristate "DM9000 support" depends on (ARM || MIPS) && NET_ETHERNET @@ -865,6 +877,22 @@ config DM9000 . The module will be called dm9000. +config SMC911X + tristate "SMSC LAN911[5678] support" + select CRC32 + select MII + depends on NET_ETHERNET && ARCH_PXA + help + This is a driver for SMSC's LAN911x series of Ethernet chipsets + including the new LAN9115, LAN9116, LAN9117, and LAN9118. + Say Y if you want it compiled into the kernel, + and read the Ethernet-HOWTO, available from + . + + This driver is also available as a module. The module will be + called smc911x. If you want to compile it as a module, say M + here and read + config NET_VENDOR_RACAL bool "Racal-Interlan (Micom) NI cards" depends on NET_ETHERNET && ISA @@ -1359,8 +1387,8 @@ config APRICOT called apricot. config B44 - tristate "Broadcom 4400 ethernet support (EXPERIMENTAL)" - depends on NET_PCI && PCI && EXPERIMENTAL + tristate "Broadcom 4400 ethernet support" + depends on NET_PCI && PCI select MII help If you have a network (Ethernet) controller of this type, say Y and @@ -2163,6 +2191,8 @@ config TIGON3 config BNX2 tristate "Broadcom NetXtremeII support" depends on PCI + select CRC32 + select ZLIB_INFLATE help This driver supports Broadcom NetXtremeII gigabit Ethernet cards. @@ -2171,7 +2201,7 @@ config BNX2 config SPIDER_NET tristate "Spider Gigabit Ethernet driver" - depends on PCI && PPC_CELL + depends on PCI && PPC_IBM_CELL_BLADE select FW_LOADER help This driver supports the Gigabit Ethernet chips present on the @@ -2179,11 +2209,11 @@ config SPIDER_NET config GIANFAR tristate "Gianfar Ethernet" - depends on 85xx || 83xx + depends on 85xx || 83xx || PPC_86xx select PHYLIB help - This driver supports the Gigabit TSEC on the MPC85xx - family of chips, and the FEC on the 8540 + This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx, + and MPC86xx family of chips, and the FEC on the 8540. config GFAR_NAPI bool "NAPI Support" @@ -2311,6 +2341,23 @@ config S2IO_NAPI If in doubt, say N. +config MYRI10GE + tristate "Myricom Myri-10G Ethernet support" + depends on PCI + select FW_LOADER + select CRC32 + ---help--- + This driver supports Myricom Myri-10G Dual Protocol interface in + Ethernet mode. If the eeprom on your board is not recent enough, + you will need a newer firmware image. + You may get this image or more information, at: + + + + To compile this driver as a module, choose M here and read + . The module + will be called myri10ge. + endmenu source "drivers/net/tokenring/Kconfig" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index b90468a..c91e951 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -187,12 +187,15 @@ obj-$(CONFIG_MACSONIC) += macsonic.o obj-$(CONFIG_MACMACE) += macmace.o obj-$(CONFIG_MAC89x0) += mac89x0.o obj-$(CONFIG_TUN) += tun.o +obj-$(CONFIG_NET_NETX) += netx-eth.o obj-$(CONFIG_DL2K) += dl2k.o obj-$(CONFIG_R8169) += r8169.o obj-$(CONFIG_AMD8111_ETH) += amd8111e.o obj-$(CONFIG_IBMVETH) += ibmveth.o obj-$(CONFIG_S2IO) += s2io.o +obj-$(CONFIG_MYRI10GE) += myri10ge/ obj-$(CONFIG_SMC91X) += smc91x.o +obj-$(CONFIG_SMC911X) += smc911x.o obj-$(CONFIG_DM9000) += dm9000.o obj-$(CONFIG_FEC_8XX) += fec_8xx/ diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 79bb56b..71165ac 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -573,8 +573,7 @@ static int lance_start_xmit (struct sk_b if (len < ETH_ZLEN) { len = ETH_ZLEN; - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; } diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index b508812..23ff22b 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -579,11 +579,7 @@ #endif } printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr); -#ifdef __sparc__ - printk("irq %s\n", __irq_itoa(pdev->irq)); -#else - printk("irq %i\n", pdev->irq); -#endif + printk("irq %d\n", pdev->irq); #ifdef CONFIG_ACENIC_OMIT_TIGON_I if ((readl(&ap->regs->HostCtrl) >> 28) == 4) { diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index d1b6b1f..a9bb7a4 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -607,8 +607,7 @@ #endif /* FIXME: is the 79C960 new enough to do its own padding right ? */ if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; len = ETH_ZLEN; } diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 5503dc8..613005a 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -43,7 +43,9 @@ #define DRV_NAME "at91_ether" #define DRV_VERSION "1.0" static struct net_device *at91_dev; -static struct clk *ether_clk; + +static struct timer_list check_timer; +#define LINK_POLL_INTERVAL (HZ) /* ..................................................................... */ @@ -143,7 +145,7 @@ static void read_phy(unsigned char phy_a * MAC accordingly. * If no link or auto-negotiation is busy, then no changes are made. */ -static void update_linkspeed(struct net_device *dev) +static void update_linkspeed(struct net_device *dev, int silent) { struct at91_private *lp = (struct at91_private *) dev->priv; unsigned int bmsr, bmcr, lpa, mac_cfg; @@ -151,7 +153,8 @@ static void update_linkspeed(struct net_ if (!mii_link_ok(&lp->mii)) { /* no link */ netif_carrier_off(dev); - printk(KERN_INFO "%s: Link down.\n", dev->name); + if (!silent) + printk(KERN_INFO "%s: Link down.\n", dev->name); return; } @@ -186,7 +189,8 @@ static void update_linkspeed(struct net_ } at91_emac_write(AT91_EMAC_CFG, mac_cfg); - printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); + if (!silent) + printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); netif_carrier_on(dev); } @@ -226,7 +230,7 @@ static irqreturn_t at91ether_phy_interru goto done; } - update_linkspeed(dev); + update_linkspeed(dev, 0); done: disable_mdi(); @@ -243,14 +247,17 @@ static void enable_phyirq(struct net_dev unsigned int dsintr, irq_number; int status; - if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */ - return; - if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */ - return; - if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */ + irq_number = lp->board_data.phy_irq_pin; + if (!irq_number) { + /* + * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L), + * or board does not have it connected. + */ + check_timer.expires = jiffies + LINK_POLL_INTERVAL; + add_timer(&check_timer); return; + } - irq_number = lp->board_data.phy_irq_pin; status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev); if (status) { printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status); @@ -292,12 +299,11 @@ static void disable_phyirq(struct net_de unsigned int dsintr; unsigned int irq_number; - if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */ - return; - if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */ - return; - if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */ + irq_number = lp->board_data.phy_irq_pin; + if (!irq_number) { + del_timer_sync(&check_timer); return; + } spin_lock_irq(&lp->lock); enable_mdi(); @@ -326,7 +332,6 @@ static void disable_phyirq(struct net_de disable_mdi(); spin_unlock_irq(&lp->lock); - irq_number = lp->board_data.phy_irq_pin; free_irq(irq_number, dev); /* Free interrupt handler */ } @@ -355,6 +360,18 @@ static void reset_phy(struct net_device } #endif +static void at91ether_check_link(unsigned long dev_id) +{ + struct net_device *dev = (struct net_device *) dev_id; + + enable_mdi(); + update_linkspeed(dev, 1); + disable_mdi(); + + check_timer.expires = jiffies + LINK_POLL_INTERVAL; + add_timer(&check_timer); +} + /* ......................... ADDRESS MANAGEMENT ........................ */ /* @@ -501,7 +518,7 @@ static int hash_get_index(__u8 *addr) hash_index |= (bitval << j); } - return hash_index; + return hash_index; } /* @@ -557,10 +574,8 @@ static void at91ether_set_rx_mode(struct at91_emac_write(AT91_EMAC_CFG, cfg); } - /* ......................... ETHTOOL SUPPORT ........................... */ - static int mdio_read(struct net_device *dev, int phy_id, int location) { unsigned int value; @@ -642,6 +657,22 @@ static struct ethtool_ops at91ether_etht .get_link = ethtool_op_get_link, }; +static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct at91_private *lp = (struct at91_private *) dev->priv; + int res; + + if (!netif_running(dev)) + return -EINVAL; + + spin_lock_irq(&lp->lock); + enable_mdi(); + res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL); + disable_mdi(); + spin_unlock_irq(&lp->lock); + + return res; +} /* ................................ MAC ................................ */ @@ -685,10 +716,10 @@ static int at91ether_open(struct net_dev struct at91_private *lp = (struct at91_private *) dev->priv; unsigned long ctl; - if (!is_valid_ether_addr(dev->dev_addr)) - return -EADDRNOTAVAIL; + if (!is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; - clk_enable(ether_clk); /* Re-enable Peripheral clock */ + clk_enable(lp->ether_clk); /* Re-enable Peripheral clock */ /* Clear internal statistics */ ctl = at91_emac_read(AT91_EMAC_CTL); @@ -708,7 +739,7 @@ static int at91ether_open(struct net_dev /* Determine current link speed */ spin_lock_irq(&lp->lock); enable_mdi(); - update_linkspeed(dev); + update_linkspeed(dev, 0); disable_mdi(); spin_unlock_irq(&lp->lock); @@ -722,6 +753,7 @@ static int at91ether_open(struct net_dev */ static int at91ether_close(struct net_device *dev) { + struct at91_private *lp = (struct at91_private *) dev->priv; unsigned long ctl; /* Disable Receiver and Transmitter */ @@ -738,7 +770,7 @@ static int at91ether_close(struct net_de netif_stop_queue(dev); - clk_disable(ether_clk); /* Disable Peripheral clock */ + clk_disable(lp->ether_clk); /* Disable Peripheral clock */ return 0; } @@ -870,7 +902,7 @@ static irqreturn_t at91ether_interrupt(i if (intstatus & AT91_EMAC_RCOM) /* Receive complete */ at91ether_rx(dev); - if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */ + if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */ /* The TCOM bit is set even if the transmission failed. */ if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY)) lp->stats.tx_errors += 1; @@ -899,7 +931,8 @@ static irqreturn_t at91ether_interrupt(i /* * Initialize the ethernet interface */ -static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address, struct platform_device *pdev) +static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address, + struct platform_device *pdev, struct clk *ether_clk) { struct at91_eth_data *board_data = pdev->dev.platform_data; struct net_device *dev; @@ -933,6 +966,7 @@ static int __init at91ether_setup(unsign return -ENOMEM; } lp->board_data = *board_data; + lp->ether_clk = ether_clk; platform_set_drvdata(pdev, dev); spin_lock_init(&lp->lock); @@ -945,6 +979,7 @@ static int __init at91ether_setup(unsign dev->set_multicast_list = at91ether_set_rx_mode; dev->set_mac_address = set_mac_address; dev->ethtool_ops = &at91ether_ethtool_ops; + dev->do_ioctl = at91ether_ioctl; SET_NETDEV_DEV(dev, &pdev->dev); @@ -975,6 +1010,9 @@ static int __init at91ether_setup(unsign lp->mii.dev = dev; /* Support for ethtool */ lp->mii.mdio_read = mdio_read; lp->mii.mdio_write = mdio_write; + lp->mii.phy_id = phy_address; + lp->mii.phy_id_mask = 0x1f; + lp->mii.reg_num_mask = 0x1f; lp->phy_type = phy_type; /* Type of PHY connected */ lp->phy_address = phy_address; /* MDI address of PHY */ @@ -992,11 +1030,18 @@ static int __init at91ether_setup(unsign /* Determine current link speed */ spin_lock_irq(&lp->lock); enable_mdi(); - update_linkspeed(dev); + update_linkspeed(dev, 0); disable_mdi(); spin_unlock_irq(&lp->lock); netif_carrier_off(dev); /* will be enabled in open() */ + /* If board has no PHY IRQ, use a timer to poll the PHY */ + if (!lp->board_data.phy_irq_pin) { + init_timer(&check_timer); + check_timer.data = (unsigned long)dev; + check_timer.function = at91ether_check_link; + } + /* Display ethernet banner */ printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%02x:%02x:%02x:%02x:%02x:%02x)\n", dev->name, (uint) dev->base_addr, dev->irq, @@ -1005,7 +1050,7 @@ static int __init at91ether_setup(unsign dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) - printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)"); + printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)"); else if (phy_type == MII_LXT971A_ID) printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name); else if (phy_type == MII_RTL8201_ID) @@ -1031,9 +1076,10 @@ static int __init at91ether_probe(struct int detected = -1; unsigned long phy_id; unsigned short phy_address = 0; + struct clk *ether_clk; ether_clk = clk_get(&pdev->dev, "ether_clk"); - if (!ether_clk) { + if (IS_ERR(ether_clk)) { printk(KERN_ERR "at91_ether: no clock defined\n"); return -ENODEV; } @@ -1056,7 +1102,7 @@ static int __init at91ether_probe(struct case MII_DP83847_ID: /* National Semiconductor DP83847: */ case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */ case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */ - detected = at91ether_setup(phy_id, phy_address, pdev); + detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk); break; } @@ -1075,17 +1121,61 @@ static int __devexit at91ether_remove(st unregister_netdev(at91_dev); free_irq(at91_dev->irq, at91_dev); dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); - clk_put(ether_clk); + clk_put(lp->ether_clk); free_netdev(at91_dev); at91_dev = NULL; return 0; } +#ifdef CONFIG_PM + +static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + struct at91_private *lp = (struct at91_private *) at91_dev->priv; + struct net_device *net_dev = platform_get_drvdata(pdev); + int phy_irq = lp->board_data.phy_irq_pin; + + if (netif_running(net_dev)) { + if (phy_irq) + disable_irq(phy_irq); + + netif_stop_queue(net_dev); + netif_device_detach(net_dev); + + clk_disable(lp->ether_clk); + } + return 0; +} + +static int at91ether_resume(struct platform_device *pdev) +{ + struct at91_private *lp = (struct at91_private *) at91_dev->priv; + struct net_device *net_dev = platform_get_drvdata(pdev); + int phy_irq = lp->board_data.phy_irq_pin; + + if (netif_running(net_dev)) { + clk_enable(lp->ether_clk); + + netif_device_attach(net_dev); + netif_start_queue(net_dev); + + if (phy_irq) + enable_irq(phy_irq); + } + return 0; +} + +#else +#define at91ether_suspend NULL +#define at91ether_resume NULL +#endif + static struct platform_driver at91ether_driver = { .probe = at91ether_probe, .remove = __devexit_p(at91ether_remove), - /* FIXME: support suspend and resume */ + .suspend = at91ether_suspend, + .resume = at91ether_resume, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/arm/at91_ether.h index 9885735..d1e72e0 100644 --- a/drivers/net/arm/at91_ether.h +++ b/drivers/net/arm/at91_ether.h @@ -80,6 +80,7 @@ struct at91_private struct net_device_stats stats; struct mii_if_info mii; /* ethtool support */ struct at91_eth_data board_data; /* board-specific configuration */ + struct clk *ether_clk; /* clock */ /* PHY */ unsigned long phy_type; /* type of PHY (PHY_ID) */ diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c index 36475eb..312955d 100644 --- a/drivers/net/arm/ether1.c +++ b/drivers/net/arm/ether1.c @@ -700,8 +700,7 @@ ether1_sendpacket (struct sk_buff *skb, } if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) goto out; } diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index f1d5b10..0810741 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c @@ -518,8 +518,7 @@ ether3_sendpacket(struct sk_buff *skb, s length = (length + 1) & ~1; if (length != skb->len) { - skb = skb_padto(skb, length); - if (skb == NULL) + if (skb_padto(skb, length)) goto out; } diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c index 442b2cb..91783a8 100644 --- a/drivers/net/atarilance.c +++ b/drivers/net/atarilance.c @@ -804,8 +804,7 @@ static int lance_start_xmit( struct sk_b ++len; if (len > skb->len) { - skb = skb_padto(skb, len); - if (skb == NULL) + if (skb_padto(skb, len)) return 0; } diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 14dbad1..038d5fc 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -2,13 +2,16 @@ * * Alchemy Au1x00 ethernet driver * - * Copyright 2001,2002,2003 MontaVista Software Inc. + * Copyright 2001-2003, 2006 MontaVista Software Inc. * Copyright 2002 TimeSys Corp. * Added ethtool/mii-tool support, * Copyright 2004 Matt Porter * Update: 2004 Bjoern Riemer, riemer@fokus.fraunhofer.de * or riemer@riemer-nt.de: fixed the link beat detection with * ioctls (SIOCGMIIPHY) + * Copyright 2006 Herbert Valerio Riedel + * converted to use linux-2.6.x's PHY framework + * * Author: MontaVista Software, Inc. * ppopov@mvista.com or source@mvista.com * @@ -53,6 +56,7 @@ #include #include #include #include +#include #include #include #include @@ -68,7 +72,7 @@ #else static int au1000_debug = 3; #endif -#define DRV_NAME "au1000eth" +#define DRV_NAME "au1000_eth" #define DRV_VERSION "1.5" #define DRV_AUTHOR "Pete Popov " #define DRV_DESC "Au1xxx on-chip Ethernet driver" @@ -80,7 +84,7 @@ MODULE_LICENSE("GPL"); // prototypes static void hard_stop(struct net_device *); static void enable_rx_tx(struct net_device *dev); -static struct net_device * au1000_probe(u32 ioaddr, int irq, int port_num); +static struct net_device * au1000_probe(int port_num); static int au1000_init(struct net_device *); static int au1000_open(struct net_device *); static int au1000_close(struct net_device *); @@ -88,17 +92,15 @@ static int au1000_tx(struct sk_buff *, s static int au1000_rx(struct net_device *); static irqreturn_t au1000_interrupt(int, void *, struct pt_regs *); static void au1000_tx_timeout(struct net_device *); -static int au1000_set_config(struct net_device *dev, struct ifmap *map); static void set_rx_mode(struct net_device *); static struct net_device_stats *au1000_get_stats(struct net_device *); -static void au1000_timer(unsigned long); static int au1000_ioctl(struct net_device *, struct ifreq *, int); static int mdio_read(struct net_device *, int, int); static void mdio_write(struct net_device *, int, int, u16); -static void dump_mii(struct net_device *dev, int phy_id); +static void au1000_adjust_link(struct net_device *); +static void enable_mac(struct net_device *, int); // externs -extern void ack_rise_edge_irq(unsigned int); extern int get_ethernet_addr(char *ethernet_addr); extern void str2eaddr(unsigned char *ea, unsigned char *str); extern char * __init prom_getcmdline(void); @@ -126,705 +128,83 @@ static unsigned char au1000_mac_addr[6] 0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00 }; -#define nibswap(x) ((((x) >> 4) & 0x0f) | (((x) << 4) & 0xf0)) -#define RUN_AT(x) (jiffies + (x)) - -// For reading/writing 32-bit words from/to DMA memory -#define cpu_to_dma32 cpu_to_be32 -#define dma32_to_cpu be32_to_cpu - struct au1000_private *au_macs[NUM_ETH_INTERFACES]; -/* FIXME - * All of the PHY code really should be detached from the MAC - * code. +/* + * board-specific configurations + * + * PHY detection algorithm + * + * If AU1XXX_PHY_STATIC_CONFIG is undefined, the PHY setup is + * autodetected: + * + * mii_probe() first searches the current MAC's MII bus for a PHY, + * selecting the first (or last, if AU1XXX_PHY_SEARCH_HIGHEST_ADDR is + * defined) PHY address not already claimed by another netdev. + * + * If nothing was found that way when searching for the 2nd ethernet + * controller's PHY and AU1XXX_PHY1_SEARCH_ON_MAC0 is defined, then + * the first MII bus is searched as well for an unclaimed PHY; this is + * needed in case of a dual-PHY accessible only through the MAC0's MII + * bus. + * + * Finally, if no PHY is found, then the corresponding ethernet + * controller is not registered to the network subsystem. */ -/* Default advertise */ -#define GENMII_DEFAULT_ADVERTISE \ - ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \ - ADVERTISED_Autoneg - -#define GENMII_DEFAULT_FEATURES \ - SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \ - SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \ - SUPPORTED_Autoneg - -int bcm_5201_init(struct net_device *dev, int phy_addr) -{ - s16 data; - - /* Stop auto-negotiation */ - data = mdio_read(dev, phy_addr, MII_CONTROL); - mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO); - - /* Set advertisement to 10/100 and Half/Full duplex - * (full capabilities) */ - data = mdio_read(dev, phy_addr, MII_ANADV); - data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T; - mdio_write(dev, phy_addr, MII_ANADV, data); - - /* Restart auto-negotiation */ - data = mdio_read(dev, phy_addr, MII_CONTROL); - data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO; - mdio_write(dev, phy_addr, MII_CONTROL, data); - - if (au1000_debug > 4) - dump_mii(dev, phy_addr); - return 0; -} - -int bcm_5201_reset(struct net_device *dev, int phy_addr) -{ - s16 mii_control, timeout; - - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET); - mdelay(1); - for (timeout = 100; timeout > 0; --timeout) { - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - if ((mii_control & MII_CNTL_RESET) == 0) - break; - mdelay(1); - } - if (mii_control & MII_CNTL_RESET) { - printk(KERN_ERR "%s PHY reset timeout !\n", dev->name); - return -1; - } - return 0; -} - -int -bcm_5201_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed) -{ - u16 mii_data; - struct au1000_private *aup; - - if (!dev) { - printk(KERN_ERR "bcm_5201_status error: NULL dev\n"); - return -1; - } - aup = (struct au1000_private *) dev->priv; - - mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS); - if (mii_data & MII_STAT_LINK) { - *link = 1; - mii_data = mdio_read(dev, aup->phy_addr, MII_AUX_CNTRL); - if (mii_data & MII_AUX_100) { - if (mii_data & MII_AUX_FDX) { - *speed = IF_PORT_100BASEFX; - dev->if_port = IF_PORT_100BASEFX; - } - else { - *speed = IF_PORT_100BASETX; - dev->if_port = IF_PORT_100BASETX; - } - } - else { - *speed = IF_PORT_10BASET; - dev->if_port = IF_PORT_10BASET; - } - - } - else { - *link = 0; - *speed = 0; - dev->if_port = IF_PORT_UNKNOWN; - } - return 0; -} - -int lsi_80227_init(struct net_device *dev, int phy_addr) -{ - if (au1000_debug > 4) - printk("lsi_80227_init\n"); - - /* restart auto-negotiation */ - mdio_write(dev, phy_addr, MII_CONTROL, - MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO); // | MII_CNTL_FDX); - mdelay(1); - - /* set up LEDs to correct display */ -#ifdef CONFIG_MIPS_MTX1 - mdio_write(dev, phy_addr, 17, 0xff80); -#else - mdio_write(dev, phy_addr, 17, 0xffc0); -#endif - - if (au1000_debug > 4) - dump_mii(dev, phy_addr); - return 0; -} - -int lsi_80227_reset(struct net_device *dev, int phy_addr) -{ - s16 mii_control, timeout; - - if (au1000_debug > 4) { - printk("lsi_80227_reset\n"); - dump_mii(dev, phy_addr); - } - - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET); - mdelay(1); - for (timeout = 100; timeout > 0; --timeout) { - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - if ((mii_control & MII_CNTL_RESET) == 0) - break; - mdelay(1); - } - if (mii_control & MII_CNTL_RESET) { - printk(KERN_ERR "%s PHY reset timeout !\n", dev->name); - return -1; - } - return 0; -} - -int -lsi_80227_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed) -{ - u16 mii_data; - struct au1000_private *aup; - - if (!dev) { - printk(KERN_ERR "lsi_80227_status error: NULL dev\n"); - return -1; - } - aup = (struct au1000_private *) dev->priv; - - mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS); - if (mii_data & MII_STAT_LINK) { - *link = 1; - mii_data = mdio_read(dev, aup->phy_addr, MII_LSI_PHY_STAT); - if (mii_data & MII_LSI_PHY_STAT_SPD) { - if (mii_data & MII_LSI_PHY_STAT_FDX) { - *speed = IF_PORT_100BASEFX; - dev->if_port = IF_PORT_100BASEFX; - } - else { - *speed = IF_PORT_100BASETX; - dev->if_port = IF_PORT_100BASETX; - } - } - else { - *speed = IF_PORT_10BASET; - dev->if_port = IF_PORT_10BASET; - } - - } - else { - *link = 0; - *speed = 0; - dev->if_port = IF_PORT_UNKNOWN; - } - return 0; -} - -int am79c901_init(struct net_device *dev, int phy_addr) -{ - printk("am79c901_init\n"); - return 0; -} - -int am79c901_reset(struct net_device *dev, int phy_addr) -{ - printk("am79c901_reset\n"); - return 0; -} - -int -am79c901_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed) -{ - return 0; -} - -int am79c874_init(struct net_device *dev, int phy_addr) -{ - s16 data; - - /* 79c874 has quit resembled bit assignments to BCM5201 */ - if (au1000_debug > 4) - printk("am79c847_init\n"); - - /* Stop auto-negotiation */ - data = mdio_read(dev, phy_addr, MII_CONTROL); - mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO); - - /* Set advertisement to 10/100 and Half/Full duplex - * (full capabilities) */ - data = mdio_read(dev, phy_addr, MII_ANADV); - data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T; - mdio_write(dev, phy_addr, MII_ANADV, data); - - /* Restart auto-negotiation */ - data = mdio_read(dev, phy_addr, MII_CONTROL); - data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO; - - mdio_write(dev, phy_addr, MII_CONTROL, data); - - if (au1000_debug > 4) dump_mii(dev, phy_addr); - return 0; -} - -int am79c874_reset(struct net_device *dev, int phy_addr) -{ - s16 mii_control, timeout; - - if (au1000_debug > 4) - printk("am79c874_reset\n"); - - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET); - mdelay(1); - for (timeout = 100; timeout > 0; --timeout) { - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - if ((mii_control & MII_CNTL_RESET) == 0) - break; - mdelay(1); - } - if (mii_control & MII_CNTL_RESET) { - printk(KERN_ERR "%s PHY reset timeout !\n", dev->name); - return -1; - } - return 0; -} - -int -am79c874_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed) -{ - u16 mii_data; - struct au1000_private *aup; - - // printk("am79c874_status\n"); - if (!dev) { - printk(KERN_ERR "am79c874_status error: NULL dev\n"); - return -1; - } - - aup = (struct au1000_private *) dev->priv; - mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS); - - if (mii_data & MII_STAT_LINK) { - *link = 1; - mii_data = mdio_read(dev, aup->phy_addr, MII_AMD_PHY_STAT); - if (mii_data & MII_AMD_PHY_STAT_SPD) { - if (mii_data & MII_AMD_PHY_STAT_FDX) { - *speed = IF_PORT_100BASEFX; - dev->if_port = IF_PORT_100BASEFX; - } - else { - *speed = IF_PORT_100BASETX; - dev->if_port = IF_PORT_100BASETX; - } - } - else { - *speed = IF_PORT_10BASET; - dev->if_port = IF_PORT_10BASET; - } - - } - else { - *link = 0; - *speed = 0; - dev->if_port = IF_PORT_UNKNOWN; - } - return 0; -} - -int lxt971a_init(struct net_device *dev, int phy_addr) -{ - if (au1000_debug > 4) - printk("lxt971a_init\n"); - - /* restart auto-negotiation */ - mdio_write(dev, phy_addr, MII_CONTROL, - MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO | MII_CNTL_FDX); - - /* set up LEDs to correct display */ - mdio_write(dev, phy_addr, 20, 0x0422); - - if (au1000_debug > 4) - dump_mii(dev, phy_addr); - return 0; -} - -int lxt971a_reset(struct net_device *dev, int phy_addr) -{ - s16 mii_control, timeout; - - if (au1000_debug > 4) { - printk("lxt971a_reset\n"); - dump_mii(dev, phy_addr); - } - - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET); - mdelay(1); - for (timeout = 100; timeout > 0; --timeout) { - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - if ((mii_control & MII_CNTL_RESET) == 0) - break; - mdelay(1); - } - if (mii_control & MII_CNTL_RESET) { - printk(KERN_ERR "%s PHY reset timeout !\n", dev->name); - return -1; - } - return 0; -} - -int -lxt971a_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed) -{ - u16 mii_data; - struct au1000_private *aup; - - if (!dev) { - printk(KERN_ERR "lxt971a_status error: NULL dev\n"); - return -1; - } - aup = (struct au1000_private *) dev->priv; - - mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS); - if (mii_data & MII_STAT_LINK) { - *link = 1; - mii_data = mdio_read(dev, aup->phy_addr, MII_INTEL_PHY_STAT); - if (mii_data & MII_INTEL_PHY_STAT_SPD) { - if (mii_data & MII_INTEL_PHY_STAT_FDX) { - *speed = IF_PORT_100BASEFX; - dev->if_port = IF_PORT_100BASEFX; - } - else { - *speed = IF_PORT_100BASETX; - dev->if_port = IF_PORT_100BASETX; - } - } - else { - *speed = IF_PORT_10BASET; - dev->if_port = IF_PORT_10BASET; - } - - } - else { - *link = 0; - *speed = 0; - dev->if_port = IF_PORT_UNKNOWN; - } - return 0; -} - -int ks8995m_init(struct net_device *dev, int phy_addr) -{ - s16 data; - -// printk("ks8995m_init\n"); - /* Stop auto-negotiation */ - data = mdio_read(dev, phy_addr, MII_CONTROL); - mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO); - - /* Set advertisement to 10/100 and Half/Full duplex - * (full capabilities) */ - data = mdio_read(dev, phy_addr, MII_ANADV); - data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T; - mdio_write(dev, phy_addr, MII_ANADV, data); - - /* Restart auto-negotiation */ - data = mdio_read(dev, phy_addr, MII_CONTROL); - data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO; - mdio_write(dev, phy_addr, MII_CONTROL, data); - - if (au1000_debug > 4) dump_mii(dev, phy_addr); - - return 0; -} - -int ks8995m_reset(struct net_device *dev, int phy_addr) -{ - s16 mii_control, timeout; - -// printk("ks8995m_reset\n"); - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET); - mdelay(1); - for (timeout = 100; timeout > 0; --timeout) { - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - if ((mii_control & MII_CNTL_RESET) == 0) - break; - mdelay(1); - } - if (mii_control & MII_CNTL_RESET) { - printk(KERN_ERR "%s PHY reset timeout !\n", dev->name); - return -1; - } - return 0; -} - -int ks8995m_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed) -{ - u16 mii_data; - struct au1000_private *aup; - - if (!dev) { - printk(KERN_ERR "ks8995m_status error: NULL dev\n"); - return -1; - } - aup = (struct au1000_private *) dev->priv; - - mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS); - if (mii_data & MII_STAT_LINK) { - *link = 1; - mii_data = mdio_read(dev, aup->phy_addr, MII_AUX_CNTRL); - if (mii_data & MII_AUX_100) { - if (mii_data & MII_AUX_FDX) { - *speed = IF_PORT_100BASEFX; - dev->if_port = IF_PORT_100BASEFX; - } - else { - *speed = IF_PORT_100BASETX; - dev->if_port = IF_PORT_100BASETX; - } - } - else { - *speed = IF_PORT_10BASET; - dev->if_port = IF_PORT_10BASET; - } - - } - else { - *link = 0; - *speed = 0; - dev->if_port = IF_PORT_UNKNOWN; - } - return 0; -} - -int -smsc_83C185_init (struct net_device *dev, int phy_addr) -{ - s16 data; - - if (au1000_debug > 4) - printk("smsc_83C185_init\n"); - - /* Stop auto-negotiation */ - data = mdio_read(dev, phy_addr, MII_CONTROL); - mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO); - - /* Set advertisement to 10/100 and Half/Full duplex - * (full capabilities) */ - data = mdio_read(dev, phy_addr, MII_ANADV); - data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T; - mdio_write(dev, phy_addr, MII_ANADV, data); - - /* Restart auto-negotiation */ - data = mdio_read(dev, phy_addr, MII_CONTROL); - data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO; - - mdio_write(dev, phy_addr, MII_CONTROL, data); - - if (au1000_debug > 4) dump_mii(dev, phy_addr); - return 0; -} - -int -smsc_83C185_reset (struct net_device *dev, int phy_addr) -{ - s16 mii_control, timeout; - - if (au1000_debug > 4) - printk("smsc_83C185_reset\n"); - - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET); - mdelay(1); - for (timeout = 100; timeout > 0; --timeout) { - mii_control = mdio_read(dev, phy_addr, MII_CONTROL); - if ((mii_control & MII_CNTL_RESET) == 0) - break; - mdelay(1); - } - if (mii_control & MII_CNTL_RESET) { - printk(KERN_ERR "%s PHY reset timeout !\n", dev->name); - return -1; - } - return 0; -} - -int -smsc_83C185_status (struct net_device *dev, int phy_addr, u16 *link, u16 *speed) -{ - u16 mii_data; - struct au1000_private *aup; - - if (!dev) { - printk(KERN_ERR "smsc_83C185_status error: NULL dev\n"); - return -1; - } - - aup = (struct au1000_private *) dev->priv; - mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS); - - if (mii_data & MII_STAT_LINK) { - *link = 1; - mii_data = mdio_read(dev, aup->phy_addr, 0x1f); - if (mii_data & (1<<3)) { - if (mii_data & (1<<4)) { - *speed = IF_PORT_100BASEFX; - dev->if_port = IF_PORT_100BASEFX; - } - else { - *speed = IF_PORT_100BASETX; - dev->if_port = IF_PORT_100BASETX; - } - } - else { - *speed = IF_PORT_10BASET; - dev->if_port = IF_PORT_10BASET; - } - } - else { - *link = 0; - *speed = 0; - dev->if_port = IF_PORT_UNKNOWN; - } - return 0; -} - - -#ifdef CONFIG_MIPS_BOSPORUS -int stub_init(struct net_device *dev, int phy_addr) -{ - //printk("PHY stub_init\n"); - return 0; -} - -int stub_reset(struct net_device *dev, int phy_addr) -{ - //printk("PHY stub_reset\n"); - return 0; -} - -int -stub_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed) -{ - //printk("PHY stub_status\n"); - *link = 1; - /* hmmm, revisit */ - *speed = IF_PORT_100BASEFX; - dev->if_port = IF_PORT_100BASEFX; - return 0; -} -#endif - -struct phy_ops bcm_5201_ops = { - bcm_5201_init, - bcm_5201_reset, - bcm_5201_status, -}; - -struct phy_ops am79c874_ops = { - am79c874_init, - am79c874_reset, - am79c874_status, -}; - -struct phy_ops am79c901_ops = { - am79c901_init, - am79c901_reset, - am79c901_status, -}; - -struct phy_ops lsi_80227_ops = { - lsi_80227_init, - lsi_80227_reset, - lsi_80227_status, -}; +/* autodetection defaults */ +#undef AU1XXX_PHY_SEARCH_HIGHEST_ADDR +#define AU1XXX_PHY1_SEARCH_ON_MAC0 -struct phy_ops lxt971a_ops = { - lxt971a_init, - lxt971a_reset, - lxt971a_status, -}; +/* static PHY setup + * + * most boards PHY setup should be detectable properly with the + * autodetection algorithm in mii_probe(), but in some cases (e.g. if + * you have a switch attached, or want to use the PHY's interrupt + * notification capabilities) you can provide a static PHY + * configuration here + * + * IRQs may only be set, if a PHY address was configured + * If a PHY address is given, also a bus id is required to be set + * + * ps: make sure the used irqs are configured properly in the board + * specific irq-map + */ -struct phy_ops ks8995m_ops = { - ks8995m_init, - ks8995m_reset, - ks8995m_status, -}; +#if defined(CONFIG_MIPS_BOSPORUS) +/* + * Micrel/Kendin 5 port switch attached to MAC0, + * MAC0 is associated with PHY address 5 (== WAN port) + * MAC1 is not associated with any PHY, since it's connected directly + * to the switch. + * no interrupts are used + */ +# define AU1XXX_PHY_STATIC_CONFIG -struct phy_ops smsc_83C185_ops = { - smsc_83C185_init, - smsc_83C185_reset, - smsc_83C185_status, -}; +# define AU1XXX_PHY0_ADDR 5 +# define AU1XXX_PHY0_BUSID 0 +# undef AU1XXX_PHY0_IRQ -#ifdef CONFIG_MIPS_BOSPORUS -struct phy_ops stub_ops = { - stub_init, - stub_reset, - stub_status, -}; +# undef AU1XXX_PHY1_ADDR +# undef AU1XXX_PHY1_BUSID +# undef AU1XXX_PHY1_IRQ #endif -static struct mii_chip_info { - const char * name; - u16 phy_id0; - u16 phy_id1; - struct phy_ops *phy_ops; - int dual_phy; -} mii_chip_table[] = { - {"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0}, - {"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0}, - {"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1}, - {"NS DP83847 PHY", 0x2000, 0x5c30, &bcm_5201_ops ,0}, - {"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0}, - {"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0}, - {"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0}, - {"Intel LXT971A Dual Speed PHY",0x0013,0x78e2, &lxt971a_ops,0}, - {"Kendin KS8995M 10/100 BaseT PHY",0x0022,0x1450, &ks8995m_ops,0}, - {"SMSC LAN83C185 10/100 BaseT PHY",0x0007,0xc0a3, &smsc_83C185_ops,0}, -#ifdef CONFIG_MIPS_BOSPORUS - {"Stub", 0x1234, 0x5678, &stub_ops }, +#if defined(AU1XXX_PHY0_BUSID) && (AU1XXX_PHY0_BUSID > 0) +# error MAC0-associated PHY attached 2nd MACs MII bus not supported yet #endif - {0,}, -}; -static int mdio_read(struct net_device *dev, int phy_id, int reg) +/* + * MII operations + */ +static int mdio_read(struct net_device *dev, int phy_addr, int reg) { struct au1000_private *aup = (struct au1000_private *) dev->priv; - volatile u32 *mii_control_reg; - volatile u32 *mii_data_reg; + volatile u32 *const mii_control_reg = &aup->mac->mii_control; + volatile u32 *const mii_data_reg = &aup->mac->mii_data; u32 timedout = 20; u32 mii_control; - #ifdef CONFIG_BCM5222_DUAL_PHY - /* First time we probe, it's for the mac0 phy. - * Since we haven't determined yet that we have a dual phy, - * aup->mii->mii_control_reg won't be setup and we'll - * default to the else statement. - * By the time we probe for the mac1 phy, the mii_control_reg - * will be setup to be the address of the mac0 phy control since - * both phys are controlled through mac0. - */ - if (aup->mii && aup->mii->mii_control_reg) { - mii_control_reg = aup->mii->mii_control_reg; - mii_data_reg = aup->mii->mii_data_reg; - } - else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) { - /* assume both phys are controlled through mac0 */ - mii_control_reg = au_macs[0]->mii->mii_control_reg; - mii_data_reg = au_macs[0]->mii->mii_data_reg; - } - else - #endif - { - /* default control and data reg addresses */ - mii_control_reg = &aup->mac->mii_control; - mii_data_reg = &aup->mac->mii_data; - } - while (*mii_control_reg & MAC_MII_BUSY) { mdelay(1); if (--timedout == 0) { @@ -835,7 +215,7 @@ static int mdio_read(struct net_device * } mii_control = MAC_SET_MII_SELECT_REG(reg) | - MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_READ; + MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_READ; *mii_control_reg = mii_control; @@ -851,32 +231,14 @@ static int mdio_read(struct net_device * return (int)*mii_data_reg; } -static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 value) +static void mdio_write(struct net_device *dev, int phy_addr, int reg, u16 value) { struct au1000_private *aup = (struct au1000_private *) dev->priv; - volatile u32 *mii_control_reg; - volatile u32 *mii_data_reg; + volatile u32 *const mii_control_reg = &aup->mac->mii_control; + volatile u32 *const mii_data_reg = &aup->mac->mii_data; u32 timedout = 20; u32 mii_control; - #ifdef CONFIG_BCM5222_DUAL_PHY - if (aup->mii && aup->mii->mii_control_reg) { - mii_control_reg = aup->mii->mii_control_reg; - mii_data_reg = aup->mii->mii_data_reg; - } - else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) { - /* assume both phys are controlled through mac0 */ - mii_control_reg = au_macs[0]->mii->mii_control_reg; - mii_data_reg = au_macs[0]->mii->mii_data_reg; - } - else - #endif - { - /* default control and data reg addresses */ - mii_control_reg = &aup->mac->mii_control; - mii_data_reg = &aup->mac->mii_data; - } - while (*mii_control_reg & MAC_MII_BUSY) { mdelay(1); if (--timedout == 0) { @@ -887,165 +249,145 @@ static void mdio_write(struct net_device } mii_control = MAC_SET_MII_SELECT_REG(reg) | - MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_WRITE; + MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_WRITE; *mii_data_reg = value; *mii_control_reg = mii_control; } +static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum) +{ + /* WARNING: bus->phy_map[phy_addr].attached_dev == dev does + * _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus) */ + struct net_device *const dev = bus->priv; + + enable_mac(dev, 0); /* make sure the MAC associated with this + * mii_bus is enabled */ + return mdio_read(dev, phy_addr, regnum); +} -static void dump_mii(struct net_device *dev, int phy_id) +static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, + u16 value) { - int i, val; + struct net_device *const dev = bus->priv; - for (i = 0; i < 7; i++) { - if ((val = mdio_read(dev, phy_id, i)) >= 0) - printk("%s: MII Reg %d=%x\n", dev->name, i, val); - } - for (i = 16; i < 25; i++) { - if ((val = mdio_read(dev, phy_id, i)) >= 0) - printk("%s: MII Reg %d=%x\n", dev->name, i, val); - } + enable_mac(dev, 0); /* make sure the MAC associated with this + * mii_bus is enabled */ + mdio_write(dev, phy_addr, regnum, value); + return 0; } -static int mii_probe (struct net_device * dev) +static int mdiobus_reset(struct mii_bus *bus) { - struct au1000_private *aup = (struct au1000_private *) dev->priv; - int phy_addr; -#ifdef CONFIG_MIPS_BOSPORUS - int phy_found=0; -#endif + struct net_device *const dev = bus->priv; - /* search for total of 32 possible mii phy addresses */ - for (phy_addr = 0; phy_addr < 32; phy_addr++) { - u16 mii_status; - u16 phy_id0, phy_id1; - int i; + enable_mac(dev, 0); /* make sure the MAC associated with this + * mii_bus is enabled */ + return 0; +} - #ifdef CONFIG_BCM5222_DUAL_PHY - /* Mask the already found phy, try next one */ - if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) { - if (au_macs[0]->phy_addr == phy_addr) - continue; - } - #endif - - mii_status = mdio_read(dev, phy_addr, MII_STATUS); - if (mii_status == 0xffff || mii_status == 0x0000) - /* the mii is not accessable, try next one */ - continue; - - phy_id0 = mdio_read(dev, phy_addr, MII_PHY_ID0); - phy_id1 = mdio_read(dev, phy_addr, MII_PHY_ID1); - - /* search our mii table for the current mii */ - for (i = 0; mii_chip_table[i].phy_id1; i++) { - if (phy_id0 == mii_chip_table[i].phy_id0 && - phy_id1 == mii_chip_table[i].phy_id1) { - struct mii_phy * mii_phy = aup->mii; - - printk(KERN_INFO "%s: %s at phy address %d\n", - dev->name, mii_chip_table[i].name, - phy_addr); -#ifdef CONFIG_MIPS_BOSPORUS - phy_found = 1; -#endif - mii_phy->chip_info = mii_chip_table+i; - aup->phy_addr = phy_addr; - aup->want_autoneg = 1; - aup->phy_ops = mii_chip_table[i].phy_ops; - aup->phy_ops->phy_init(dev,phy_addr); - - // Check for dual-phy and then store required - // values and set indicators. We need to do - // this now since mdio_{read,write} need the - // control and data register addresses. - #ifdef CONFIG_BCM5222_DUAL_PHY - if ( mii_chip_table[i].dual_phy) { - - /* assume both phys are controlled - * through MAC0. Board specific? */ - - /* sanity check */ - if (!au_macs[0] || !au_macs[0]->mii) - return -1; - aup->mii->mii_control_reg = (u32 *) - &au_macs[0]->mac->mii_control; - aup->mii->mii_data_reg = (u32 *) - &au_macs[0]->mac->mii_data; - } - #endif - goto found; - } +static int mii_probe (struct net_device *dev) +{ + struct au1000_private *const aup = (struct au1000_private *) dev->priv; + struct phy_device *phydev = NULL; + +#if defined(AU1XXX_PHY_STATIC_CONFIG) + BUG_ON(aup->mac_id < 0 || aup->mac_id > 1); + + if(aup->mac_id == 0) { /* get PHY0 */ +# if defined(AU1XXX_PHY0_ADDR) + phydev = au_macs[AU1XXX_PHY0_BUSID]->mii_bus.phy_map[AU1XXX_PHY0_ADDR]; +# else + printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n", + dev->name); + return 0; +# endif /* defined(AU1XXX_PHY0_ADDR) */ + } else if (aup->mac_id == 1) { /* get PHY1 */ +# if defined(AU1XXX_PHY1_ADDR) + phydev = au_macs[AU1XXX_PHY1_BUSID]->mii_bus.phy_map[AU1XXX_PHY1_ADDR]; +# else + printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n", + dev->name); + return 0; +# endif /* defined(AU1XXX_PHY1_ADDR) */ + } + +#else /* defined(AU1XXX_PHY_STATIC_CONFIG) */ + int phy_addr; + + /* find the first (lowest address) PHY on the current MAC's MII bus */ + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) + if (aup->mii_bus.phy_map[phy_addr]) { + phydev = aup->mii_bus.phy_map[phy_addr]; +# if !defined(AU1XXX_PHY_SEARCH_HIGHEST_ADDR) + break; /* break out with first one found */ +# endif } - } -found: - -#ifdef CONFIG_MIPS_BOSPORUS - /* This is a workaround for the Micrel/Kendin 5 port switch - The second MAC doesn't see a PHY connected... so we need to - trick it into thinking we have one. - - If this kernel is run on another Au1500 development board - the stub will be found as well as the actual PHY. However, - the last found PHY will be used... usually at Addr 31 (Db1500). - */ - if ( (!phy_found) ) - { - u16 phy_id0, phy_id1; - int i; - phy_id0 = 0x1234; - phy_id1 = 0x5678; - - /* search our mii table for the current mii */ - for (i = 0; mii_chip_table[i].phy_id1; i++) { - if (phy_id0 == mii_chip_table[i].phy_id0 && - phy_id1 == mii_chip_table[i].phy_id1) { - struct mii_phy * mii_phy; - - printk(KERN_INFO "%s: %s at phy address %d\n", - dev->name, mii_chip_table[i].name, - phy_addr); - mii_phy = kmalloc(sizeof(struct mii_phy), - GFP_KERNEL); - if (mii_phy) { - mii_phy->chip_info = mii_chip_table+i; - aup->phy_addr = phy_addr; - mii_phy->next = aup->mii; - aup->phy_ops = - mii_chip_table[i].phy_ops; - aup->mii = mii_phy; - aup->phy_ops->phy_init(dev,phy_addr); - } else { - printk(KERN_ERR "%s: out of memory\n", - dev->name); - return -1; - } - mii_phy->chip_info = mii_chip_table+i; - aup->phy_addr = phy_addr; - aup->phy_ops = mii_chip_table[i].phy_ops; - aup->phy_ops->phy_init(dev,phy_addr); - break; - } +# if defined(AU1XXX_PHY1_SEARCH_ON_MAC0) + /* try harder to find a PHY */ + if (!phydev && (aup->mac_id == 1)) { + /* no PHY found, maybe we have a dual PHY? */ + printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, " + "let's see if it's attached to MAC0...\n"); + + BUG_ON(!au_macs[0]); + + /* find the first (lowest address) non-attached PHY on + * the MAC0 MII bus */ + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { + struct phy_device *const tmp_phydev = + au_macs[0]->mii_bus.phy_map[phy_addr]; + + if (!tmp_phydev) + continue; /* no PHY here... */ + + if (tmp_phydev->attached_dev) + continue; /* already claimed by MAC0 */ + + phydev = tmp_phydev; + break; /* found it */ } } - if (aup->mac_id == 0) { - /* the Bosporus phy responds to addresses 0-5 but - * 5 is the correct one. - */ - aup->phy_addr = 5; - } -#endif +# endif /* defined(AU1XXX_PHY1_SEARCH_OTHER_BUS) */ - if (aup->mii->chip_info == NULL) { - printk(KERN_ERR "%s: Au1x No known MII transceivers found!\n", - dev->name); +#endif /* defined(AU1XXX_PHY_STATIC_CONFIG) */ + if (!phydev) { + printk (KERN_ERR DRV_NAME ":%s: no PHY found\n", dev->name); return -1; } - printk(KERN_INFO "%s: Using %s as default\n", - dev->name, aup->mii->chip_info->name); + /* now we are supposed to have a proper phydev, to attach to... */ + BUG_ON(!phydev); + BUG_ON(phydev->attached_dev); + + phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0); + + if (IS_ERR(phydev)) { + printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); + return PTR_ERR(phydev); + } + + /* mask with MAC supported features */ + phydev->supported &= (SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full + | SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full + | SUPPORTED_Autoneg + /* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */ + | SUPPORTED_MII + | SUPPORTED_TP); + + phydev->advertising = phydev->supported; + + aup->old_link = 0; + aup->old_speed = 0; + aup->old_duplex = -1; + aup->phy_dev = phydev; + + printk(KERN_INFO "%s: attached PHY driver [%s] " + "(mii_bus:phy_addr=%s, irq=%d)\n", + dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); return 0; } @@ -1097,35 +439,38 @@ static void hard_stop(struct net_device au_sync_delay(10); } - -static void reset_mac(struct net_device *dev) +static void enable_mac(struct net_device *dev, int force_reset) { - int i; - u32 flags; + unsigned long flags; struct au1000_private *aup = (struct au1000_private *) dev->priv; - if (au1000_debug > 4) - printk(KERN_INFO "%s: reset mac, aup %x\n", - dev->name, (unsigned)aup); - spin_lock_irqsave(&aup->lock, flags); - if (aup->timer.function == &au1000_timer) {/* check if timer initted */ - del_timer(&aup->timer); - } - hard_stop(dev); - #ifdef CONFIG_BCM5222_DUAL_PHY - if (aup->mac_id != 0) { - #endif - /* If BCM5222, we can't leave MAC0 in reset because then - * we can't access the dual phy for ETH1 */ + if(force_reset || (!aup->mac_enabled)) { *aup->enable = MAC_EN_CLOCK_ENABLE; au_sync_delay(2); - *aup->enable = 0; + *aup->enable = (MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2 + | MAC_EN_CLOCK_ENABLE); au_sync_delay(2); - #ifdef CONFIG_BCM5222_DUAL_PHY + + aup->mac_enabled = 1; } - #endif + + spin_unlock_irqrestore(&aup->lock, flags); +} + +static void reset_mac_unlocked(struct net_device *dev) +{ + struct au1000_private *const aup = (struct au1000_private *) dev->priv; + int i; + + hard_stop(dev); + + *aup->enable = MAC_EN_CLOCK_ENABLE; + au_sync_delay(2); + *aup->enable = 0; + au_sync_delay(2); + aup->tx_full = 0; for (i = 0; i < NUM_RX_DMA; i++) { /* reset control bits */ @@ -1135,9 +480,26 @@ static void reset_mac(struct net_device /* reset control bits */ aup->tx_dma_ring[i]->buff_stat &= ~0xf; } - spin_unlock_irqrestore(&aup->lock, flags); + + aup->mac_enabled = 0; + } +static void reset_mac(struct net_device *dev) +{ + struct au1000_private *const aup = (struct au1000_private *) dev->priv; + unsigned long flags; + + if (au1000_debug > 4) + printk(KERN_INFO "%s: reset mac, aup %x\n", + dev->name, (unsigned)aup); + + spin_lock_irqsave(&aup->lock, flags); + + reset_mac_unlocked (dev); + + spin_unlock_irqrestore(&aup->lock, flags); +} /* * Setup the receive and transmit "rings". These pointers are the addresses @@ -1160,12 +522,27 @@ setup_hw_rings(struct au1000_private *au } static struct { - int port; u32 base_addr; u32 macen_addr; int irq; struct net_device *dev; -} iflist[2]; +} iflist[2] = { +#ifdef CONFIG_SOC_AU1000 + {AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT}, + {AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT} +#endif +#ifdef CONFIG_SOC_AU1100 + {AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT} +#endif +#ifdef CONFIG_SOC_AU1500 + {AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT}, + {AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT} +#endif +#ifdef CONFIG_SOC_AU1550 + {AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT}, + {AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT} +#endif +}; static int num_ifs; @@ -1176,58 +553,14 @@ static int num_ifs; */ static int __init au1000_init_module(void) { - struct cpuinfo_mips *c = ¤t_cpu_data; int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4); struct net_device *dev; int i, found_one = 0; - switch (c->cputype) { -#ifdef CONFIG_SOC_AU1000 - case CPU_AU1000: - num_ifs = 2 - ni; - iflist[0].base_addr = AU1000_ETH0_BASE; - iflist[1].base_addr = AU1000_ETH1_BASE; - iflist[0].macen_addr = AU1000_MAC0_ENABLE; - iflist[1].macen_addr = AU1000_MAC1_ENABLE; - iflist[0].irq = AU1000_MAC0_DMA_INT; - iflist[1].irq = AU1000_MAC1_DMA_INT; - break; -#endif -#ifdef CONFIG_SOC_AU1100 - case CPU_AU1100: - num_ifs = 1 - ni; - iflist[0].base_addr = AU1100_ETH0_BASE; - iflist[0].macen_addr = AU1100_MAC0_ENABLE; - iflist[0].irq = AU1100_MAC0_DMA_INT; - break; -#endif -#ifdef CONFIG_SOC_AU1500 - case CPU_AU1500: - num_ifs = 2 - ni; - iflist[0].base_addr = AU1500_ETH0_BASE; - iflist[1].base_addr = AU1500_ETH1_BASE; - iflist[0].macen_addr = AU1500_MAC0_ENABLE; - iflist[1].macen_addr = AU1500_MAC1_ENABLE; - iflist[0].irq = AU1500_MAC0_DMA_INT; - iflist[1].irq = AU1500_MAC1_DMA_INT; - break; -#endif -#ifdef CONFIG_SOC_AU1550 - case CPU_AU1550: - num_ifs = 2 - ni; - iflist[0].base_addr = AU1550_ETH0_BASE; - iflist[1].base_addr = AU1550_ETH1_BASE; - iflist[0].macen_addr = AU1550_MAC0_ENABLE; - iflist[1].macen_addr = AU1550_MAC1_ENABLE; - iflist[0].irq = AU1550_MAC0_DMA_INT; - iflist[1].irq = AU1550_MAC1_DMA_INT; - break; -#endif - default: - num_ifs = 0; - } + num_ifs = NUM_ETH_INTERFACES - ni; + for(i = 0; i < num_ifs; i++) { - dev = au1000_probe(iflist[i].base_addr, iflist[i].irq, i); + dev = au1000_probe(i); iflist[i].dev = dev; if (dev) found_one++; @@ -1237,178 +570,31 @@ #endif return 0; } -static int au1000_setup_aneg(struct net_device *dev, u32 advertise) -{ - struct au1000_private *aup = (struct au1000_private *)dev->priv; - u16 ctl, adv; - - /* Setup standard advertise */ - adv = mdio_read(dev, aup->phy_addr, MII_ADVERTISE); - adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); - if (advertise & ADVERTISED_10baseT_Half) - adv |= ADVERTISE_10HALF; - if (advertise & ADVERTISED_10baseT_Full) - adv |= ADVERTISE_10FULL; - if (advertise & ADVERTISED_100baseT_Half) - adv |= ADVERTISE_100HALF; - if (advertise & ADVERTISED_100baseT_Full) - adv |= ADVERTISE_100FULL; - mdio_write(dev, aup->phy_addr, MII_ADVERTISE, adv); - - /* Start/Restart aneg */ - ctl = mdio_read(dev, aup->phy_addr, MII_BMCR); - ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); - mdio_write(dev, aup->phy_addr, MII_BMCR, ctl); - - return 0; -} +/* + * ethtool operations + */ -static int au1000_setup_forced(struct net_device *dev, int speed, int fd) +static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct au1000_private *aup = (struct au1000_private *)dev->priv; - u16 ctl; - - ctl = mdio_read(dev, aup->phy_addr, MII_BMCR); - ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE); - - /* First reset the PHY */ - mdio_write(dev, aup->phy_addr, MII_BMCR, ctl | BMCR_RESET); - - /* Select speed & duplex */ - switch (speed) { - case SPEED_10: - break; - case SPEED_100: - ctl |= BMCR_SPEED100; - break; - case SPEED_1000: - default: - return -EINVAL; - } - if (fd == DUPLEX_FULL) - ctl |= BMCR_FULLDPLX; - mdio_write(dev, aup->phy_addr, MII_BMCR, ctl); - return 0; -} + if (aup->phy_dev) + return phy_ethtool_gset(aup->phy_dev, cmd); - -static void -au1000_start_link(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct au1000_private *aup = (struct au1000_private *)dev->priv; - u32 advertise; - int autoneg; - int forced_speed; - int forced_duplex; - - /* Default advertise */ - advertise = GENMII_DEFAULT_ADVERTISE; - autoneg = aup->want_autoneg; - forced_speed = SPEED_100; - forced_duplex = DUPLEX_FULL; - - /* Setup link parameters */ - if (cmd) { - if (cmd->autoneg == AUTONEG_ENABLE) { - advertise = cmd->advertising; - autoneg = 1; - } else { - autoneg = 0; - - forced_speed = cmd->speed; - forced_duplex = cmd->duplex; - } - } - - /* Configure PHY & start aneg */ - aup->want_autoneg = autoneg; - if (autoneg) - au1000_setup_aneg(dev, advertise); - else - au1000_setup_forced(dev, forced_speed, forced_duplex); - mod_timer(&aup->timer, jiffies + HZ); + return -EINVAL; } -static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct au1000_private *aup = (struct au1000_private *)dev->priv; - u16 link, speed; - - cmd->supported = GENMII_DEFAULT_FEATURES; - cmd->advertising = GENMII_DEFAULT_ADVERTISE; - cmd->port = PORT_MII; - cmd->transceiver = XCVR_EXTERNAL; - cmd->phy_address = aup->phy_addr; - spin_lock_irq(&aup->lock); - cmd->autoneg = aup->want_autoneg; - aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed); - if ((speed == IF_PORT_100BASETX) || (speed == IF_PORT_100BASEFX)) - cmd->speed = SPEED_100; - else if (speed == IF_PORT_10BASET) - cmd->speed = SPEED_10; - if (link && (dev->if_port == IF_PORT_100BASEFX)) - cmd->duplex = DUPLEX_FULL; - else - cmd->duplex = DUPLEX_HALF; - spin_unlock_irq(&aup->lock); - return 0; -} -static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct au1000_private *aup = (struct au1000_private *)dev->priv; - unsigned long features = GENMII_DEFAULT_FEATURES; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE) - return -EINVAL; - if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0) - return -EINVAL; - if (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) - return -EINVAL; - if (cmd->autoneg == AUTONEG_DISABLE) - switch (cmd->speed) { - case SPEED_10: - if (cmd->duplex == DUPLEX_HALF && - (features & SUPPORTED_10baseT_Half) == 0) - return -EINVAL; - if (cmd->duplex == DUPLEX_FULL && - (features & SUPPORTED_10baseT_Full) == 0) - return -EINVAL; - break; - case SPEED_100: - if (cmd->duplex == DUPLEX_HALF && - (features & SUPPORTED_100baseT_Half) == 0) - return -EINVAL; - if (cmd->duplex == DUPLEX_FULL && - (features & SUPPORTED_100baseT_Full) == 0) - return -EINVAL; - break; - default: - return -EINVAL; - } - else if ((features & SUPPORTED_Autoneg) == 0) - return -EINVAL; - - spin_lock_irq(&aup->lock); - au1000_start_link(dev, cmd); - spin_unlock_irq(&aup->lock); - return 0; -} + if (!capable(CAP_NET_ADMIN)) + return -EPERM; -static int au1000_nway_reset(struct net_device *dev) -{ - struct au1000_private *aup = (struct au1000_private *)dev->priv; + if (aup->phy_dev) + return phy_ethtool_sset(aup->phy_dev, cmd); - if (!aup->want_autoneg) - return -EINVAL; - spin_lock_irq(&aup->lock); - au1000_start_link(dev, NULL); - spin_unlock_irq(&aup->lock); - return 0; + return -EINVAL; } static void @@ -1423,21 +609,14 @@ au1000_get_drvinfo(struct net_device *de info->regdump_len = 0; } -static u32 au1000_get_link(struct net_device *dev) -{ - return netif_carrier_ok(dev); -} - static struct ethtool_ops au1000_ethtool_ops = { .get_settings = au1000_get_settings, .set_settings = au1000_set_settings, .get_drvinfo = au1000_get_drvinfo, - .nway_reset = au1000_nway_reset, - .get_link = au1000_get_link + .get_link = ethtool_op_get_link, }; -static struct net_device * -au1000_probe(u32 ioaddr, int irq, int port_num) +static struct net_device * au1000_probe(int port_num) { static unsigned version_printed = 0; struct au1000_private *aup = NULL; @@ -1445,106 +624,115 @@ au1000_probe(u32 ioaddr, int irq, int po db_dest_t *pDB, *pDBfree; char *pmac, *argptr; char ethaddr[6]; - int i, err; + int irq, i, err; + u32 base, macen; + + if (port_num >= NUM_ETH_INTERFACES) + return NULL; + + base = CPHYSADDR(iflist[port_num].base_addr ); + macen = CPHYSADDR(iflist[port_num].macen_addr); + irq = iflist[port_num].irq; - if (!request_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE, "Au1x00 ENET")) + if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") || + !request_mem_region(macen, 4, "Au1x00 ENET")) return NULL; - if (version_printed++ == 0) + if (version_printed++ == 0) printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR); dev = alloc_etherdev(sizeof(struct au1000_private)); if (!dev) { - printk (KERN_ERR "au1000 eth: alloc_etherdev failed\n"); + printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME); return NULL; } - if ((err = register_netdev(dev))) { - printk(KERN_ERR "Au1x_eth Cannot register net device err %d\n", - err); + if ((err = register_netdev(dev)) != 0) { + printk(KERN_ERR "%s: Cannot register net device, error %d\n", + DRV_NAME, err); free_netdev(dev); return NULL; } - printk("%s: Au1x Ethernet found at 0x%x, irq %d\n", - dev->name, ioaddr, irq); + printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n", + dev->name, base, irq); aup = dev->priv; /* Allocate the data buffers */ /* Snooping works fine with eth on all au1xxx */ - aup->vaddr = (u32)dma_alloc_noncoherent(NULL, - MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS), - &aup->dma_addr, - 0); + aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE * + (NUM_TX_BUFFS + NUM_RX_BUFFS), + &aup->dma_addr, 0); if (!aup->vaddr) { free_netdev(dev); - release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE); + release_mem_region( base, MAC_IOSIZE); + release_mem_region(macen, 4); return NULL; } /* aup->mac is the base address of the MAC's registers */ - aup->mac = (volatile mac_reg_t *)((unsigned long)ioaddr); + aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr; + /* Setup some variables for quick register address access */ - if (ioaddr == iflist[0].base_addr) - { - /* check env variables first */ - if (!get_ethernet_addr(ethaddr)) { + aup->enable = (volatile u32 *)iflist[port_num].macen_addr; + aup->mac_id = port_num; + au_macs[port_num] = aup; + + if (port_num == 0) { + /* Check the environment variables first */ + if (get_ethernet_addr(ethaddr) == 0) memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr)); - } else { + else { /* Check command line */ argptr = prom_getcmdline(); - if ((pmac = strstr(argptr, "ethaddr=")) == NULL) { - printk(KERN_INFO "%s: No mac address found\n", - dev->name); - /* use the hard coded mac addresses */ - } else { + if ((pmac = strstr(argptr, "ethaddr=")) == NULL) + printk(KERN_INFO "%s: No MAC address found\n", + dev->name); + /* Use the hard coded MAC addresses */ + else { str2eaddr(ethaddr, pmac + strlen("ethaddr=")); memcpy(au1000_mac_addr, ethaddr, - sizeof(au1000_mac_addr)); + sizeof(au1000_mac_addr)); } } - aup->enable = (volatile u32 *) - ((unsigned long)iflist[0].macen_addr); - memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr)); + setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR); - aup->mac_id = 0; - au_macs[0] = aup; - } - else - if (ioaddr == iflist[1].base_addr) - { - aup->enable = (volatile u32 *) - ((unsigned long)iflist[1].macen_addr); - memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr)); - dev->dev_addr[4] += 0x10; + } else if (port_num == 1) setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR); - aup->mac_id = 1; - au_macs[1] = aup; - } - else - { - printk(KERN_ERR "%s: bad ioaddr\n", dev->name); - } - - /* bring the device out of reset, otherwise probing the mii - * will hang */ - *aup->enable = MAC_EN_CLOCK_ENABLE; - au_sync_delay(2); - *aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | - MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE; - au_sync_delay(2); - aup->mii = kmalloc(sizeof(struct mii_phy), GFP_KERNEL); - if (!aup->mii) { - printk(KERN_ERR "%s: out of memory\n", dev->name); - goto err_out; - } - aup->mii->next = NULL; - aup->mii->chip_info = NULL; - aup->mii->status = 0; - aup->mii->mii_control_reg = 0; - aup->mii->mii_data_reg = 0; + /* + * Assign to the Ethernet ports two consecutive MAC addresses + * to match those that are printed on their stickers + */ + memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr)); + dev->dev_addr[5] += port_num; + + *aup->enable = 0; + aup->mac_enabled = 0; + + aup->mii_bus.priv = dev; + aup->mii_bus.read = mdiobus_read; + aup->mii_bus.write = mdiobus_write; + aup->mii_bus.reset = mdiobus_reset; + aup->mii_bus.name = "au1000_eth_mii"; + aup->mii_bus.id = aup->mac_id; + aup->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); + for(i = 0; i < PHY_MAX_ADDR; ++i) + aup->mii_bus.irq[i] = PHY_POLL; + + /* if known, set corresponding PHY IRQs */ +#if defined(AU1XXX_PHY_STATIC_CONFIG) +# if defined(AU1XXX_PHY0_IRQ) + if (AU1XXX_PHY0_BUSID == aup->mii_bus.id) + aup->mii_bus.irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ; +# endif +# if defined(AU1XXX_PHY1_IRQ) + if (AU1XXX_PHY1_BUSID == aup->mii_bus.id) + aup->mii_bus.irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ; +# endif +#endif + mdiobus_register(&aup->mii_bus); if (mii_probe(dev) != 0) { goto err_out; @@ -1581,7 +769,7 @@ au1000_probe(u32 ioaddr, int irq, int po } spin_lock_init(&aup->lock); - dev->base_addr = ioaddr; + dev->base_addr = base; dev->irq = irq; dev->open = au1000_open; dev->hard_start_xmit = au1000_tx; @@ -1590,7 +778,6 @@ au1000_probe(u32 ioaddr, int irq, int po dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &au1000_ioctl; SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops); - dev->set_config = &au1000_set_config; dev->tx_timeout = au1000_tx_timeout; dev->watchdog_timeo = ETH_TX_TIMEOUT; @@ -1606,7 +793,7 @@ err_out: /* here we should have a valid dev plus aup-> register addresses * so we can reset the mac properly.*/ reset_mac(dev); - kfree(aup->mii); + for (i = 0; i < NUM_RX_DMA; i++) { if (aup->rx_db_inuse[i]) ReleaseDB(aup, aup->rx_db_inuse[i]); @@ -1615,13 +802,12 @@ err_out: if (aup->tx_db_inuse[i]) ReleaseDB(aup, aup->tx_db_inuse[i]); } - dma_free_noncoherent(NULL, - MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS), - (void *)aup->vaddr, - aup->dma_addr); + dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), + (void *)aup->vaddr, aup->dma_addr); unregister_netdev(dev); free_netdev(dev); - release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE); + release_mem_region( base, MAC_IOSIZE); + release_mem_region(macen, 4); return NULL; } @@ -1640,19 +826,14 @@ static int au1000_init(struct net_device u32 flags; int i; u32 control; - u16 link, speed; if (au1000_debug > 4) printk("%s: au1000_init\n", dev->name); - spin_lock_irqsave(&aup->lock, flags); - /* bring the device out of reset */ - *aup->enable = MAC_EN_CLOCK_ENABLE; - au_sync_delay(2); - *aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | - MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE; - au_sync_delay(20); + enable_mac(dev, 1); + + spin_lock_irqsave(&aup->lock, flags); aup->mac->control = 0; aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2; @@ -1668,12 +849,16 @@ static int au1000_init(struct net_device } au_sync(); - aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed); - control = MAC_DISABLE_RX_OWN | MAC_RX_ENABLE | MAC_TX_ENABLE; + control = MAC_RX_ENABLE | MAC_TX_ENABLE; #ifndef CONFIG_CPU_LITTLE_ENDIAN control |= MAC_BIG_ENDIAN; #endif - if (link && (dev->if_port == IF_PORT_100BASEFX)) { + if (aup->phy_dev) { + if (aup->phy_dev->link && (DUPLEX_FULL == aup->phy_dev->duplex)) + control |= MAC_FULL_DUPLEX; + else + control |= MAC_DISABLE_RX_OWN; + } else { /* PHY-less op, assume full-duplex */ control |= MAC_FULL_DUPLEX; } @@ -1685,57 +870,84 @@ #endif return 0; } -static void au1000_timer(unsigned long data) +static void +au1000_adjust_link(struct net_device *dev) { - struct net_device *dev = (struct net_device *)data; struct au1000_private *aup = (struct au1000_private *) dev->priv; - unsigned char if_port; - u16 link, speed; + struct phy_device *phydev = aup->phy_dev; + unsigned long flags; - if (!dev) { - /* fatal error, don't restart the timer */ - printk(KERN_ERR "au1000_timer error: NULL dev\n"); - return; - } + int status_change = 0; - if_port = dev->if_port; - if (aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed) == 0) { - if (link) { - if (!netif_carrier_ok(dev)) { - netif_carrier_on(dev); - printk(KERN_INFO "%s: link up\n", dev->name); - } - } - else { - if (netif_carrier_ok(dev)) { - netif_carrier_off(dev); - dev->if_port = 0; - printk(KERN_INFO "%s: link down\n", dev->name); - } + BUG_ON(!aup->phy_dev); + + spin_lock_irqsave(&aup->lock, flags); + + if (phydev->link && (aup->old_speed != phydev->speed)) { + // speed changed + + switch(phydev->speed) { + case SPEED_10: + case SPEED_100: + break; + default: + printk(KERN_WARNING + "%s: Speed (%d) is not 10/100 ???\n", + dev->name, phydev->speed); + break; } + + aup->old_speed = phydev->speed; + + status_change = 1; } - if (link && (dev->if_port != if_port) && - (dev->if_port != IF_PORT_UNKNOWN)) { + if (phydev->link && (aup->old_duplex != phydev->duplex)) { + // duplex mode changed + + /* switching duplex mode requires to disable rx and tx! */ hard_stop(dev); - if (dev->if_port == IF_PORT_100BASEFX) { - printk(KERN_INFO "%s: going to full duplex\n", - dev->name); - aup->mac->control |= MAC_FULL_DUPLEX; - au_sync_delay(1); - } - else { - aup->mac->control &= ~MAC_FULL_DUPLEX; - au_sync_delay(1); - } + + if (DUPLEX_FULL == phydev->duplex) + aup->mac->control = ((aup->mac->control + | MAC_FULL_DUPLEX) + & ~MAC_DISABLE_RX_OWN); + else + aup->mac->control = ((aup->mac->control + & ~MAC_FULL_DUPLEX) + | MAC_DISABLE_RX_OWN); + au_sync_delay(1); + enable_rx_tx(dev); + aup->old_duplex = phydev->duplex; + + status_change = 1; } - aup->timer.expires = RUN_AT((1*HZ)); - aup->timer.data = (unsigned long)dev; - aup->timer.function = &au1000_timer; /* timer handler */ - add_timer(&aup->timer); + if(phydev->link != aup->old_link) { + // link state changed + if (phydev->link) // link went up + netif_schedule(dev); + else { // link went down + aup->old_speed = 0; + aup->old_duplex = -1; + } + + aup->old_link = phydev->link; + status_change = 1; + } + + spin_unlock_irqrestore(&aup->lock, flags); + + if (status_change) { + if (phydev->link) + printk(KERN_INFO "%s: link up (%d/%s)\n", + dev->name, phydev->speed, + DUPLEX_FULL == phydev->duplex ? "Full" : "Half"); + else + printk(KERN_INFO "%s: link down\n", dev->name); + } } static int au1000_open(struct net_device *dev) @@ -1746,25 +958,26 @@ static int au1000_open(struct net_device if (au1000_debug > 4) printk("%s: open: dev=%p\n", dev->name, dev); + if ((retval = request_irq(dev->irq, &au1000_interrupt, 0, + dev->name, dev))) { + printk(KERN_ERR "%s: unable to get IRQ %d\n", + dev->name, dev->irq); + return retval; + } + if ((retval = au1000_init(dev))) { printk(KERN_ERR "%s: error in au1000_init\n", dev->name); free_irq(dev->irq, dev); return retval; } - netif_start_queue(dev); - if ((retval = request_irq(dev->irq, &au1000_interrupt, 0, - dev->name, dev))) { - printk(KERN_ERR "%s: unable to get IRQ %d\n", - dev->name, dev->irq); - return retval; + if (aup->phy_dev) { + /* cause the PHY state machine to schedule a link state check */ + aup->phy_dev->state = PHY_CHANGELINK; + phy_start(aup->phy_dev); } - init_timer(&aup->timer); /* used in ioctl() */ - aup->timer.expires = RUN_AT((3*HZ)); - aup->timer.data = (unsigned long)dev; - aup->timer.function = &au1000_timer; /* timer handler */ - add_timer(&aup->timer); + netif_start_queue(dev); if (au1000_debug > 4) printk("%s: open: Initialization done.\n", dev->name); @@ -1774,16 +987,19 @@ static int au1000_open(struct net_device static int au1000_close(struct net_device *dev) { - u32 flags; - struct au1000_private *aup = (struct au1000_private *) dev->priv; + unsigned long flags; + struct au1000_private *const aup = (struct au1000_private *) dev->priv; if (au1000_debug > 4) printk("%s: close: dev=%p\n", dev->name, dev); - reset_mac(dev); + if (aup->phy_dev) + phy_stop(aup->phy_dev); spin_lock_irqsave(&aup->lock, flags); - + + reset_mac_unlocked (dev); + /* stop the device */ netif_stop_queue(dev); @@ -1805,21 +1021,18 @@ static void __exit au1000_cleanup_module if (dev) { aup = (struct au1000_private *) dev->priv; unregister_netdev(dev); - kfree(aup->mii); - for (j = 0; j < NUM_RX_DMA; j++) { + for (j = 0; j < NUM_RX_DMA; j++) if (aup->rx_db_inuse[j]) ReleaseDB(aup, aup->rx_db_inuse[j]); - } - for (j = 0; j < NUM_TX_DMA; j++) { + for (j = 0; j < NUM_TX_DMA; j++) if (aup->tx_db_inuse[j]) ReleaseDB(aup, aup->tx_db_inuse[j]); - } - dma_free_noncoherent(NULL, - MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS), - (void *)aup->vaddr, - aup->dma_addr); + dma_free_noncoherent(NULL, MAX_BUF_SIZE * + (NUM_TX_BUFFS + NUM_RX_BUFFS), + (void *)aup->vaddr, aup->dma_addr); + release_mem_region(dev->base_addr, MAC_IOSIZE); + release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4); free_netdev(dev); - release_mem_region(CPHYSADDR(iflist[i].base_addr), MAC_IOSIZE); } } } @@ -1830,7 +1043,7 @@ static void update_tx_stats(struct net_d struct net_device_stats *ps = &aup->stats; if (status & TX_FRAME_ABORTED) { - if (dev->if_port == IF_PORT_100BASEFX) { + if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) { if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) { /* any other tx errors are only valid * in half duplex mode */ @@ -2104,126 +1317,15 @@ static void set_rx_mode(struct net_devic } } - static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct au1000_private *aup = (struct au1000_private *)dev->priv; - u16 *data = (u16 *)&rq->ifr_ifru; - - switch(cmd) { - case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ - case SIOCGMIIPHY: - if (!netif_running(dev)) return -EINVAL; - data[0] = aup->phy_addr; - case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - case SIOCGMIIREG: - data[3] = mdio_read(dev, data[0], data[1]); - return 0; - case SIOCDEVPRIVATE+2: /* Write the specified MII register */ - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mdio_write(dev, data[0], data[1],data[2]); - return 0; - default: - return -EOPNOTSUPP; - } - -} - - -static int au1000_set_config(struct net_device *dev, struct ifmap *map) -{ - struct au1000_private *aup = (struct au1000_private *) dev->priv; - u16 control; - if (au1000_debug > 4) { - printk("%s: set_config called: dev->if_port %d map->port %x\n", - dev->name, dev->if_port, map->port); - } + if (!netif_running(dev)) return -EINVAL; - switch(map->port){ - case IF_PORT_UNKNOWN: /* use auto here */ - printk(KERN_INFO "%s: config phy for aneg\n", - dev->name); - dev->if_port = map->port; - /* Link Down: the timer will bring it up */ - netif_carrier_off(dev); - - /* read current control */ - control = mdio_read(dev, aup->phy_addr, MII_CONTROL); - control &= ~(MII_CNTL_FDX | MII_CNTL_F100); - - /* enable auto negotiation and reset the negotiation */ - mdio_write(dev, aup->phy_addr, MII_CONTROL, - control | MII_CNTL_AUTO | - MII_CNTL_RST_AUTO); + if (!aup->phy_dev) return -EINVAL; // PHY not controllable - break; - - case IF_PORT_10BASET: /* 10BaseT */ - printk(KERN_INFO "%s: config phy for 10BaseT\n", - dev->name); - dev->if_port = map->port; - - /* Link Down: the timer will bring it up */ - netif_carrier_off(dev); - - /* set Speed to 10Mbps, Half Duplex */ - control = mdio_read(dev, aup->phy_addr, MII_CONTROL); - control &= ~(MII_CNTL_F100 | MII_CNTL_AUTO | - MII_CNTL_FDX); - - /* disable auto negotiation and force 10M/HD mode*/ - mdio_write(dev, aup->phy_addr, MII_CONTROL, control); - break; - - case IF_PORT_100BASET: /* 100BaseT */ - case IF_PORT_100BASETX: /* 100BaseTx */ - printk(KERN_INFO "%s: config phy for 100BaseTX\n", - dev->name); - dev->if_port = map->port; - - /* Link Down: the timer will bring it up */ - netif_carrier_off(dev); - - /* set Speed to 100Mbps, Half Duplex */ - /* disable auto negotiation and enable 100MBit Mode */ - control = mdio_read(dev, aup->phy_addr, MII_CONTROL); - control &= ~(MII_CNTL_AUTO | MII_CNTL_FDX); - control |= MII_CNTL_F100; - mdio_write(dev, aup->phy_addr, MII_CONTROL, control); - break; - - case IF_PORT_100BASEFX: /* 100BaseFx */ - printk(KERN_INFO "%s: config phy for 100BaseFX\n", - dev->name); - dev->if_port = map->port; - - /* Link Down: the timer will bring it up */ - netif_carrier_off(dev); - - /* set Speed to 100Mbps, Full Duplex */ - /* disable auto negotiation and enable 100MBit Mode */ - control = mdio_read(dev, aup->phy_addr, MII_CONTROL); - control &= ~MII_CNTL_AUTO; - control |= MII_CNTL_F100 | MII_CNTL_FDX; - mdio_write(dev, aup->phy_addr, MII_CONTROL, control); - break; - case IF_PORT_10BASE2: /* 10Base2 */ - case IF_PORT_AUI: /* AUI */ - /* These Modes are not supported (are they?)*/ - printk(KERN_ERR "%s: 10Base2/AUI not supported", - dev->name); - return -EOPNOTSUPP; - break; - - default: - printk(KERN_ERR "%s: Invalid media selected", - dev->name); - return -EINVAL; - } - return 0; + return phy_mii_ioctl(aup->phy_dev, if_mii(rq), cmd); } static struct net_device_stats *au1000_get_stats(struct net_device *dev) diff --git a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h index 7f9326e..41c2f84 100644 --- a/drivers/net/au1000_eth.h +++ b/drivers/net/au1000_eth.h @@ -40,120 +40,6 @@ #define MAC_MIN_PKT_SIZE 64 #define MULTICAST_FILTER_LIMIT 64 -/* FIXME - * The PHY defines should be in a separate file. - */ - -/* MII register offsets */ -#define MII_CONTROL 0x0000 -#define MII_STATUS 0x0001 -#define MII_PHY_ID0 0x0002 -#define MII_PHY_ID1 0x0003 -#define MII_ANADV 0x0004 -#define MII_ANLPAR 0x0005 -#define MII_AEXP 0x0006 -#define MII_ANEXT 0x0007 -#define MII_LSI_PHY_CONFIG 0x0011 -/* Status register */ -#define MII_LSI_PHY_STAT 0x0012 -#define MII_AMD_PHY_STAT MII_LSI_PHY_STAT -#define MII_INTEL_PHY_STAT 0x0011 - -#define MII_AUX_CNTRL 0x0018 -/* mii registers specific to AMD 79C901 */ -#define MII_STATUS_SUMMARY = 0x0018 - -/* MII Control register bit definitions. */ -#define MII_CNTL_FDX 0x0100 -#define MII_CNTL_RST_AUTO 0x0200 -#define MII_CNTL_ISOLATE 0x0400 -#define MII_CNTL_PWRDWN 0x0800 -#define MII_CNTL_AUTO 0x1000 -#define MII_CNTL_F100 0x2000 -#define MII_CNTL_LPBK 0x4000 -#define MII_CNTL_RESET 0x8000 - -/* MII Status register bit */ -#define MII_STAT_EXT 0x0001 -#define MII_STAT_JAB 0x0002 -#define MII_STAT_LINK 0x0004 -#define MII_STAT_CAN_AUTO 0x0008 -#define MII_STAT_FAULT 0x0010 -#define MII_STAT_AUTO_DONE 0x0020 -#define MII_STAT_CAN_T 0x0800 -#define MII_STAT_CAN_T_FDX 0x1000 -#define MII_STAT_CAN_TX 0x2000 -#define MII_STAT_CAN_TX_FDX 0x4000 -#define MII_STAT_CAN_T4 0x8000 - - -#define MII_ID1_OUI_LO 0xFC00 /* low bits of OUI mask */ -#define MII_ID1_MODEL 0x03F0 /* model number */ -#define MII_ID1_REV 0x000F /* model number */ - -/* MII NWAY Register Bits ... - valid for the ANAR (Auto-Negotiation Advertisement) and - ANLPAR (Auto-Negotiation Link Partner) registers */ -#define MII_NWAY_NODE_SEL 0x001f -#define MII_NWAY_CSMA_CD 0x0001 -#define MII_NWAY_T 0x0020 -#define MII_NWAY_T_FDX 0x0040 -#define MII_NWAY_TX 0x0080 -#define MII_NWAY_TX_FDX 0x0100 -#define MII_NWAY_T4 0x0200 -#define MII_NWAY_PAUSE 0x0400 -#define MII_NWAY_RF 0x2000 /* Remote Fault */ -#define MII_NWAY_ACK 0x4000 /* Remote Acknowledge */ -#define MII_NWAY_NP 0x8000 /* Next Page (Enable) */ - -/* mii stsout register bits */ -#define MII_STSOUT_LINK_FAIL 0x4000 -#define MII_STSOUT_SPD 0x0080 -#define MII_STSOUT_DPLX 0x0040 - -/* mii stsics register bits */ -#define MII_STSICS_SPD 0x8000 -#define MII_STSICS_DPLX 0x4000 -#define MII_STSICS_LINKSTS 0x0001 - -/* mii stssum register bits */ -#define MII_STSSUM_LINK 0x0008 -#define MII_STSSUM_DPLX 0x0004 -#define MII_STSSUM_AUTO 0x0002 -#define MII_STSSUM_SPD 0x0001 - -/* lsi phy status register */ -#define MII_LSI_PHY_STAT_FDX 0x0040 -#define MII_LSI_PHY_STAT_SPD 0x0080 - -/* amd phy status register */ -#define MII_AMD_PHY_STAT_FDX 0x0800 -#define MII_AMD_PHY_STAT_SPD 0x0400 - -/* intel phy status register */ -#define MII_INTEL_PHY_STAT_FDX 0x0200 -#define MII_INTEL_PHY_STAT_SPD 0x4000 - -/* Auxilliary Control/Status Register */ -#define MII_AUX_FDX 0x0001 -#define MII_AUX_100 0x0002 -#define MII_AUX_F100 0x0004 -#define MII_AUX_ANEG 0x0008 - -typedef struct mii_phy { - struct mii_phy * next; - struct mii_chip_info * chip_info; - u16 status; - u32 *mii_control_reg; - u32 *mii_data_reg; -} mii_phy_t; - -struct phy_ops { - int (*phy_init) (struct net_device *, int); - int (*phy_reset) (struct net_device *, int); - int (*phy_status) (struct net_device *, int, u16 *, u16 *); -}; - /* * Data Buffer Descriptor. Data buffers must be aligned on 32 byte * boundary for both, receive and transmit. @@ -200,7 +86,6 @@ typedef struct mac_reg { struct au1000_private { - db_dest_t *pDBfree; db_dest_t db[NUM_RX_BUFFS+NUM_TX_BUFFS]; volatile rx_dma_t *rx_dma_ring[NUM_RX_DMA]; @@ -213,8 +98,15 @@ struct au1000_private { u32 tx_full; int mac_id; - mii_phy_t *mii; - struct phy_ops *phy_ops; + + int mac_enabled; /* whether MAC is currently enabled and running (req. for mdio) */ + + int old_link; /* used by au1000_adjust_link */ + int old_speed; + int old_duplex; + + struct phy_device *phy_dev; + struct mii_bus mii_bus; /* These variables are just for quick access to certain regs addresses. */ volatile mac_reg_t *mac; /* mac registers */ @@ -223,14 +115,6 @@ struct au1000_private { u32 vaddr; /* virtual address of rx/tx buffers */ dma_addr_t dma_addr; /* dma address of rx/tx buffers */ - u8 *hash_table; - u32 hash_mode; - u32 intr_work_done; /* number of Rx and Tx pkts processed in the isr */ - int phy_addr; /* phy address */ - u32 options; /* User-settable misc. driver options. */ - u32 drv_flags; - int want_autoneg; struct net_device_stats stats; - struct timer_list timer; spinlock_t lock; /* Serialise access to device */ }; diff --git a/drivers/net/b44.c b/drivers/net/b44.c index d8233e0..a7e4ba5 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -29,8 +29,8 @@ #include "b44.h" #define DRV_MODULE_NAME "b44" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.00" -#define DRV_MODULE_RELDATE "Apr 7, 2006" +#define DRV_MODULE_VERSION "1.01" +#define DRV_MODULE_RELDATE "Jun 16, 2006" #define B44_DEF_MSG_ENABLE \ (NETIF_MSG_DRV | \ @@ -75,6 +75,15 @@ #define TX_PKT_BUF_SZ (B44_MAX_MTU + ET /* minimum number of free TX descriptors required to wake up TX process */ #define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4) +/* b44 internal pattern match filter info */ +#define B44_PATTERN_BASE 0x400 +#define B44_PATTERN_SIZE 0x80 +#define B44_PMASK_BASE 0x600 +#define B44_PMASK_SIZE 0x10 +#define B44_MAX_PATTERNS 16 +#define B44_ETHIPV6UDP_HLEN 62 +#define B44_ETHIPV4UDP_HLEN 42 + static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; @@ -101,7 +110,7 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl); static void b44_halt(struct b44 *); static void b44_init_rings(struct b44 *); -static void b44_init_hw(struct b44 *); +static void b44_init_hw(struct b44 *, int); static int dma_desc_align_mask; static int dma_desc_sync_size; @@ -873,7 +882,7 @@ static int b44_poll(struct net_device *n spin_lock_irq(&bp->lock); b44_halt(bp); b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); netif_wake_queue(bp->dev); spin_unlock_irq(&bp->lock); done = 1; @@ -942,7 +951,7 @@ static void b44_tx_timeout(struct net_de b44_halt(bp); b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); spin_unlock_irq(&bp->lock); @@ -1059,7 +1068,7 @@ static int b44_change_mtu(struct net_dev b44_halt(bp); dev->mtu = new_mtu; b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); spin_unlock_irq(&bp->lock); b44_enable_ints(bp); @@ -1356,13 +1365,15 @@ static int b44_set_mac_addr(struct net_d * packet processing. Invoked with bp->lock held. */ static void __b44_set_rx_mode(struct net_device *); -static void b44_init_hw(struct b44 *bp) +static void b44_init_hw(struct b44 *bp, int full_reset) { u32 val; b44_chip_reset(bp); - b44_phy_reset(bp); - b44_setup_phy(bp); + if (full_reset) { + b44_phy_reset(bp); + b44_setup_phy(bp); + } /* Enable CRC32, set proper LED modes and power on PHY */ bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL); @@ -1376,16 +1387,21 @@ static void b44_init_hw(struct b44 *bp) bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN); bw32(bp, B44_TX_WMARK, 56); /* XXX magic */ - bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE); - bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset); - bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | - (bp->rx_offset << DMARX_CTRL_ROSHIFT))); - bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); + if (full_reset) { + bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE); + bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset); + bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | + (bp->rx_offset << DMARX_CTRL_ROSHIFT))); + bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); - bw32(bp, B44_DMARX_PTR, bp->rx_pending); - bp->rx_prod = bp->rx_pending; + bw32(bp, B44_DMARX_PTR, bp->rx_pending); + bp->rx_prod = bp->rx_pending; - bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); + bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); + } else { + bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | + (bp->rx_offset << DMARX_CTRL_ROSHIFT))); + } val = br32(bp, B44_ENET_CTRL); bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE)); @@ -1401,7 +1417,7 @@ static int b44_open(struct net_device *d goto out; b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); b44_check_phy(bp); @@ -1450,6 +1466,140 @@ static void b44_poll_controller(struct n } #endif +static void bwfilter_table(struct b44 *bp, u8 *pp, u32 bytes, u32 table_offset) +{ + u32 i; + u32 *pattern = (u32 *) pp; + + for (i = 0; i < bytes; i += sizeof(u32)) { + bw32(bp, B44_FILT_ADDR, table_offset + i); + bw32(bp, B44_FILT_DATA, pattern[i / sizeof(u32)]); + } +} + +static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset) +{ + int magicsync = 6; + int k, j, len = offset; + int ethaddr_bytes = ETH_ALEN; + + memset(ppattern + offset, 0xff, magicsync); + for (j = 0; j < magicsync; j++) + set_bit(len++, (unsigned long *) pmask); + + for (j = 0; j < B44_MAX_PATTERNS; j++) { + if ((B44_PATTERN_SIZE - len) >= ETH_ALEN) + ethaddr_bytes = ETH_ALEN; + else + ethaddr_bytes = B44_PATTERN_SIZE - len; + if (ethaddr_bytes <=0) + break; + for (k = 0; k< ethaddr_bytes; k++) { + ppattern[offset + magicsync + + (j * ETH_ALEN) + k] = macaddr[k]; + len++; + set_bit(len, (unsigned long *) pmask); + } + } + return len - 1; +} + +/* Setup magic packet patterns in the b44 WOL + * pattern matching filter. + */ +static void b44_setup_pseudo_magicp(struct b44 *bp) +{ + + u32 val; + int plen0, plen1, plen2; + u8 *pwol_pattern; + u8 pwol_mask[B44_PMASK_SIZE]; + + pwol_pattern = kmalloc(B44_PATTERN_SIZE, GFP_KERNEL); + if (!pwol_pattern) { + printk(KERN_ERR PFX "Memory not available for WOL\n"); + return; + } + + /* Ipv4 magic packet pattern - pattern 0.*/ + memset(pwol_pattern, 0, B44_PATTERN_SIZE); + memset(pwol_mask, 0, B44_PMASK_SIZE); + plen0 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask, + B44_ETHIPV4UDP_HLEN); + + bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, B44_PATTERN_BASE); + bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, B44_PMASK_BASE); + + /* Raw ethernet II magic packet pattern - pattern 1 */ + memset(pwol_pattern, 0, B44_PATTERN_SIZE); + memset(pwol_mask, 0, B44_PMASK_SIZE); + plen1 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask, + ETH_HLEN); + + bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, + B44_PATTERN_BASE + B44_PATTERN_SIZE); + bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, + B44_PMASK_BASE + B44_PMASK_SIZE); + + /* Ipv6 magic packet pattern - pattern 2 */ + memset(pwol_pattern, 0, B44_PATTERN_SIZE); + memset(pwol_mask, 0, B44_PMASK_SIZE); + plen2 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask, + B44_ETHIPV6UDP_HLEN); + + bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, + B44_PATTERN_BASE + B44_PATTERN_SIZE + B44_PATTERN_SIZE); + bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, + B44_PMASK_BASE + B44_PMASK_SIZE + B44_PMASK_SIZE); + + kfree(pwol_pattern); + + /* set these pattern's lengths: one less than each real length */ + val = plen0 | (plen1 << 8) | (plen2 << 16) | WKUP_LEN_ENABLE_THREE; + bw32(bp, B44_WKUP_LEN, val); + + /* enable wakeup pattern matching */ + val = br32(bp, B44_DEVCTRL); + bw32(bp, B44_DEVCTRL, val | DEVCTRL_PFE); + +} + +static void b44_setup_wol(struct b44 *bp) +{ + u32 val; + u16 pmval; + + bw32(bp, B44_RXCONFIG, RXCONFIG_ALLMULTI); + + if (bp->flags & B44_FLAG_B0_ANDLATER) { + + bw32(bp, B44_WKUP_LEN, WKUP_LEN_DISABLE); + + val = bp->dev->dev_addr[2] << 24 | + bp->dev->dev_addr[3] << 16 | + bp->dev->dev_addr[4] << 8 | + bp->dev->dev_addr[5]; + bw32(bp, B44_ADDR_LO, val); + + val = bp->dev->dev_addr[0] << 8 | + bp->dev->dev_addr[1]; + bw32(bp, B44_ADDR_HI, val); + + val = br32(bp, B44_DEVCTRL); + bw32(bp, B44_DEVCTRL, val | DEVCTRL_MPM | DEVCTRL_PFE); + + } else { + b44_setup_pseudo_magicp(bp); + } + + val = br32(bp, B44_SBTMSLOW); + bw32(bp, B44_SBTMSLOW, val | SBTMSLOW_PE); + + pci_read_config_word(bp->pdev, SSB_PMCSR, &pmval); + pci_write_config_word(bp->pdev, SSB_PMCSR, pmval | SSB_PE); + +} + static int b44_close(struct net_device *dev) { struct b44 *bp = netdev_priv(dev); @@ -1475,6 +1625,11 @@ #endif netif_poll_enable(dev); + if (bp->flags & B44_FLAG_WOL_ENABLE) { + b44_init_hw(bp, 0); + b44_setup_wol(bp); + } + b44_free_consistent(bp); return 0; @@ -1620,8 +1775,6 @@ static int b44_get_settings(struct net_d { struct b44 *bp = netdev_priv(dev); - if (!netif_running(dev)) - return -EAGAIN; cmd->supported = (SUPPORTED_Autoneg); cmd->supported |= (SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | @@ -1649,6 +1802,12 @@ static int b44_get_settings(struct net_d XCVR_INTERNAL : XCVR_EXTERNAL; cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ? AUTONEG_DISABLE : AUTONEG_ENABLE; + if (cmd->autoneg == AUTONEG_ENABLE) + cmd->advertising |= ADVERTISED_Autoneg; + if (!netif_running(dev)){ + cmd->speed = 0; + cmd->duplex = 0xff; + } cmd->maxtxpkt = 0; cmd->maxrxpkt = 0; return 0; @@ -1658,9 +1817,6 @@ static int b44_set_settings(struct net_d { struct b44 *bp = netdev_priv(dev); - if (!netif_running(dev)) - return -EAGAIN; - /* We do not support gigabit. */ if (cmd->autoneg == AUTONEG_ENABLE) { if (cmd->advertising & @@ -1677,28 +1833,39 @@ static int b44_set_settings(struct net_d spin_lock_irq(&bp->lock); if (cmd->autoneg == AUTONEG_ENABLE) { - bp->flags &= ~B44_FLAG_FORCE_LINK; - bp->flags &= ~(B44_FLAG_ADV_10HALF | + bp->flags &= ~(B44_FLAG_FORCE_LINK | + B44_FLAG_100_BASE_T | + B44_FLAG_FULL_DUPLEX | + B44_FLAG_ADV_10HALF | B44_FLAG_ADV_10FULL | B44_FLAG_ADV_100HALF | B44_FLAG_ADV_100FULL); - if (cmd->advertising & ADVERTISE_10HALF) - bp->flags |= B44_FLAG_ADV_10HALF; - if (cmd->advertising & ADVERTISE_10FULL) - bp->flags |= B44_FLAG_ADV_10FULL; - if (cmd->advertising & ADVERTISE_100HALF) - bp->flags |= B44_FLAG_ADV_100HALF; - if (cmd->advertising & ADVERTISE_100FULL) - bp->flags |= B44_FLAG_ADV_100FULL; + if (cmd->advertising == 0) { + bp->flags |= (B44_FLAG_ADV_10HALF | + B44_FLAG_ADV_10FULL | + B44_FLAG_ADV_100HALF | + B44_FLAG_ADV_100FULL); + } else { + if (cmd->advertising & ADVERTISED_10baseT_Half) + bp->flags |= B44_FLAG_ADV_10HALF; + if (cmd->advertising & ADVERTISED_10baseT_Full) + bp->flags |= B44_FLAG_ADV_10FULL; + if (cmd->advertising & ADVERTISED_100baseT_Half) + bp->flags |= B44_FLAG_ADV_100HALF; + if (cmd->advertising & ADVERTISED_100baseT_Full) + bp->flags |= B44_FLAG_ADV_100FULL; + } } else { bp->flags |= B44_FLAG_FORCE_LINK; + bp->flags &= ~(B44_FLAG_100_BASE_T | B44_FLAG_FULL_DUPLEX); if (cmd->speed == SPEED_100) bp->flags |= B44_FLAG_100_BASE_T; if (cmd->duplex == DUPLEX_FULL) bp->flags |= B44_FLAG_FULL_DUPLEX; } - b44_setup_phy(bp); + if (netif_running(dev)) + b44_setup_phy(bp); spin_unlock_irq(&bp->lock); @@ -1734,7 +1901,7 @@ static int b44_set_ringparam(struct net_ b44_halt(bp); b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); netif_wake_queue(bp->dev); spin_unlock_irq(&bp->lock); @@ -1777,7 +1944,7 @@ static int b44_set_pauseparam(struct net if (bp->flags & B44_FLAG_PAUSE_AUTO) { b44_halt(bp); b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); } else { __b44_set_flow_ctrl(bp, bp->flags); } @@ -1819,12 +1986,40 @@ static void b44_get_ethtool_stats(struct spin_unlock_irq(&bp->lock); } +static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct b44 *bp = netdev_priv(dev); + + wol->supported = WAKE_MAGIC; + if (bp->flags & B44_FLAG_WOL_ENABLE) + wol->wolopts = WAKE_MAGIC; + else + wol->wolopts = 0; + memset(&wol->sopass, 0, sizeof(wol->sopass)); +} + +static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct b44 *bp = netdev_priv(dev); + + spin_lock_irq(&bp->lock); + if (wol->wolopts & WAKE_MAGIC) + bp->flags |= B44_FLAG_WOL_ENABLE; + else + bp->flags &= ~B44_FLAG_WOL_ENABLE; + spin_unlock_irq(&bp->lock); + + return 0; +} + static struct ethtool_ops b44_ethtool_ops = { .get_drvinfo = b44_get_drvinfo, .get_settings = b44_get_settings, .set_settings = b44_set_settings, .nway_reset = b44_nway_reset, .get_link = ethtool_op_get_link, + .get_wol = b44_get_wol, + .set_wol = b44_set_wol, .get_ringparam = b44_get_ringparam, .set_ringparam = b44_set_ringparam, .get_pauseparam = b44_get_pauseparam, @@ -1903,6 +2098,10 @@ static int __devinit b44_get_invariants( /* XXX - really required? bp->flags |= B44_FLAG_BUGGY_TXPTR; */ + + if (ssb_get_core_rev(bp) >= 7) + bp->flags |= B44_FLAG_B0_ANDLATER; + out: return err; } @@ -2103,6 +2302,10 @@ static int b44_suspend(struct pci_dev *p spin_unlock_irq(&bp->lock); free_irq(dev->irq, dev); + if (bp->flags & B44_FLAG_WOL_ENABLE) { + b44_init_hw(bp, 0); + b44_setup_wol(bp); + } pci_disable_device(pdev); return 0; } @@ -2125,7 +2328,7 @@ static int b44_resume(struct pci_dev *pd spin_lock_irq(&bp->lock); b44_init_rings(bp); - b44_init_hw(bp); + b44_init_hw(bp, 1); netif_device_attach(bp->dev); spin_unlock_irq(&bp->lock); diff --git a/drivers/net/b44.h b/drivers/net/b44.h index b178662..4944507 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -24,6 +24,9 @@ #define WKUP_LEN_D2 0x00000000 #define WKUP_LEN_P3_MASK 0x7f000000 /* Pattern 3 */ #define WKUP_LEN_P3_SHIFT 24 #define WKUP_LEN_D3 0x80000000 +#define WKUP_LEN_DISABLE 0x80808080 +#define WKUP_LEN_ENABLE_TWO 0x80800000 +#define WKUP_LEN_ENABLE_THREE 0x80000000 #define B44_ISTAT 0x0020UL /* Interrupt Status */ #define ISTAT_LS 0x00000020 /* Link Change (B0 only) */ #define ISTAT_PME 0x00000040 /* Power Management Event */ @@ -264,6 +267,8 @@ #define SBIDHIGH_VC_MASK 0xffff0000 /* #define SBIDHIGH_VC_SHIFT 16 /* SSB PCI config space registers. */ +#define SSB_PMCSR 0x44 +#define SSB_PE 0x100 #define SSB_BAR0_WIN 0x80 #define SSB_BAR1_WIN 0x84 #define SSB_SPROM_CONTROL 0x88 @@ -420,6 +425,7 @@ struct b44 { u32 dma_offset; u32 flags; +#define B44_FLAG_B0_ANDLATER 0x00000001 #define B44_FLAG_BUGGY_TXPTR 0x00000002 #define B44_FLAG_REORDER_BUG 0x00000004 #define B44_FLAG_PAUSE_AUTO 0x00008000 @@ -435,6 +441,7 @@ #define B44_FLAG_ADV_100FULL 0x08000000 #define B44_FLAG_INTERNAL_PHY 0x10000000 #define B44_FLAG_RX_RING_HACK 0x20000000 #define B44_FLAG_TX_RING_HACK 0x40000000 +#define B44_FLAG_WOL_ENABLE 0x80000000 u32 rx_offset; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 54161ae..7635736 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -32,6 +32,7 @@ #include #include #include #include +#include #include #include #include @@ -49,14 +50,15 @@ #include #include #include #include +#include #include "bnx2.h" #include "bnx2_fw.h" #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.40" -#define DRV_MODULE_RELDATE "May 22, 2006" +#define DRV_MODULE_VERSION "1.4.42" +#define DRV_MODULE_RELDATE "June 12, 2006" #define RUN_AT(x) (jiffies + (x)) @@ -1638,7 +1640,7 @@ bnx2_tx_int(struct bnx2 *bp) skb = tx_buf->skb; #ifdef BCM_TSO /* partial BD completions possible with TSO packets */ - if (skb_shinfo(skb)->tso_size) { + if (skb_shinfo(skb)->gso_size) { u16 last_idx, last_ring_idx; last_idx = sw_cons + @@ -1820,7 +1822,7 @@ reuse_rx: skb->protocol = eth_type_trans(skb, bp->dev); if ((len > (bp->dev->mtu + ETH_HLEN)) && - (htons(skb->protocol) != 0x8100)) { + (ntohs(skb->protocol) != 0x8100)) { dev_kfree_skb_irq(skb); goto next_rx; @@ -2009,7 +2011,7 @@ bnx2_poll(struct net_device *dev, int *b return 1; } -/* Called with rtnl_lock from vlan functions and also dev->xmit_lock +/* Called with rtnl_lock from vlan functions and also netif_tx_lock * from set_multicast. */ static void @@ -2083,6 +2085,92 @@ #endif spin_unlock_bh(&bp->phy_lock); } +#define FW_BUF_SIZE 0x8000 + +static int +bnx2_gunzip_init(struct bnx2 *bp) +{ + if ((bp->gunzip_buf = vmalloc(FW_BUF_SIZE)) == NULL) + goto gunzip_nomem1; + + if ((bp->strm = kmalloc(sizeof(*bp->strm), GFP_KERNEL)) == NULL) + goto gunzip_nomem2; + + bp->strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); + if (bp->strm->workspace == NULL) + goto gunzip_nomem3; + + return 0; + +gunzip_nomem3: + kfree(bp->strm); + bp->strm = NULL; + +gunzip_nomem2: + vfree(bp->gunzip_buf); + bp->gunzip_buf = NULL; + +gunzip_nomem1: + printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for " + "uncompression.\n", bp->dev->name); + return -ENOMEM; +} + +static void +bnx2_gunzip_end(struct bnx2 *bp) +{ + kfree(bp->strm->workspace); + + kfree(bp->strm); + bp->strm = NULL; + + if (bp->gunzip_buf) { + vfree(bp->gunzip_buf); + bp->gunzip_buf = NULL; + } +} + +static int +bnx2_gunzip(struct bnx2 *bp, u8 *zbuf, int len, void **outbuf, int *outlen) +{ + int n, rc; + + /* check gzip header */ + if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED)) + return -EINVAL; + + n = 10; + +#define FNAME 0x8 + if (zbuf[3] & FNAME) + while ((zbuf[n++] != 0) && (n < len)); + + bp->strm->next_in = zbuf + n; + bp->strm->avail_in = len - n; + bp->strm->next_out = bp->gunzip_buf; + bp->strm->avail_out = FW_BUF_SIZE; + + rc = zlib_inflateInit2(bp->strm, -MAX_WBITS); + if (rc != Z_OK) + return rc; + + rc = zlib_inflate(bp->strm, Z_FINISH); + + *outlen = FW_BUF_SIZE - bp->strm->avail_out; + *outbuf = bp->gunzip_buf; + + if ((rc != Z_OK) && (rc != Z_STREAM_END)) + printk(KERN_ERR PFX "%s: Firmware decompression error: %s\n", + bp->dev->name, bp->strm->msg); + + zlib_inflateEnd(bp->strm); + + if (rc == Z_STREAM_END) + return 0; + + return rc; +} + static void load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len, u32 rv2p_proc) @@ -2092,9 +2180,9 @@ load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_ for (i = 0; i < rv2p_code_len; i += 8) { - REG_WR(bp, BNX2_RV2P_INSTR_HIGH, *rv2p_code); + REG_WR(bp, BNX2_RV2P_INSTR_HIGH, cpu_to_le32(*rv2p_code)); rv2p_code++; - REG_WR(bp, BNX2_RV2P_INSTR_LOW, *rv2p_code); + REG_WR(bp, BNX2_RV2P_INSTR_LOW, cpu_to_le32(*rv2p_code)); rv2p_code++; if (rv2p_proc == RV2P_PROC1) { @@ -2134,7 +2222,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_ int j; for (j = 0; j < (fw->text_len / 4); j++, offset += 4) { - REG_WR_IND(bp, offset, fw->text[j]); + REG_WR_IND(bp, offset, cpu_to_le32(fw->text[j])); } } @@ -2190,15 +2278,32 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_ REG_WR_IND(bp, cpu_reg->mode, val); } -static void +static int bnx2_init_cpus(struct bnx2 *bp) { struct cpu_reg cpu_reg; struct fw_info fw; + int rc = 0; + void *text; + u32 text_len; + + if ((rc = bnx2_gunzip_init(bp)) != 0) + return rc; /* Initialize the RV2P processor. */ - load_rv2p_fw(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), RV2P_PROC1); - load_rv2p_fw(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), RV2P_PROC2); + rc = bnx2_gunzip(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), &text, + &text_len); + if (rc) + goto init_cpu_err; + + load_rv2p_fw(bp, text, text_len, RV2P_PROC1); + + rc = bnx2_gunzip(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), &text, + &text_len); + if (rc) + goto init_cpu_err; + + load_rv2p_fw(bp, text, text_len, RV2P_PROC2); /* Initialize the RX Processor. */ cpu_reg.mode = BNX2_RXP_CPU_MODE; @@ -2222,7 +2327,13 @@ bnx2_init_cpus(struct bnx2 *bp) fw.text_addr = bnx2_RXP_b06FwTextAddr; fw.text_len = bnx2_RXP_b06FwTextLen; fw.text_index = 0; - fw.text = bnx2_RXP_b06FwText; + + rc = bnx2_gunzip(bp, bnx2_RXP_b06FwText, sizeof(bnx2_RXP_b06FwText), + &text, &text_len); + if (rc) + goto init_cpu_err; + + fw.text = text; fw.data_addr = bnx2_RXP_b06FwDataAddr; fw.data_len = bnx2_RXP_b06FwDataLen; @@ -2268,7 +2379,13 @@ bnx2_init_cpus(struct bnx2 *bp) fw.text_addr = bnx2_TXP_b06FwTextAddr; fw.text_len = bnx2_TXP_b06FwTextLen; fw.text_index = 0; - fw.text = bnx2_TXP_b06FwText; + + rc = bnx2_gunzip(bp, bnx2_TXP_b06FwText, sizeof(bnx2_TXP_b06FwText), + &text, &text_len); + if (rc) + goto init_cpu_err; + + fw.text = text; fw.data_addr = bnx2_TXP_b06FwDataAddr; fw.data_len = bnx2_TXP_b06FwDataLen; @@ -2314,7 +2431,13 @@ bnx2_init_cpus(struct bnx2 *bp) fw.text_addr = bnx2_TPAT_b06FwTextAddr; fw.text_len = bnx2_TPAT_b06FwTextLen; fw.text_index = 0; - fw.text = bnx2_TPAT_b06FwText; + + rc = bnx2_gunzip(bp, bnx2_TPAT_b06FwText, sizeof(bnx2_TPAT_b06FwText), + &text, &text_len); + if (rc) + goto init_cpu_err; + + fw.text = text; fw.data_addr = bnx2_TPAT_b06FwDataAddr; fw.data_len = bnx2_TPAT_b06FwDataLen; @@ -2360,7 +2483,13 @@ bnx2_init_cpus(struct bnx2 *bp) fw.text_addr = bnx2_COM_b06FwTextAddr; fw.text_len = bnx2_COM_b06FwTextLen; fw.text_index = 0; - fw.text = bnx2_COM_b06FwText; + + rc = bnx2_gunzip(bp, bnx2_COM_b06FwText, sizeof(bnx2_COM_b06FwText), + &text, &text_len); + if (rc) + goto init_cpu_err; + + fw.text = text; fw.data_addr = bnx2_COM_b06FwDataAddr; fw.data_len = bnx2_COM_b06FwDataLen; @@ -2384,6 +2513,9 @@ bnx2_init_cpus(struct bnx2 *bp) load_cpu_fw(bp, &cpu_reg, &fw); +init_cpu_err: + bnx2_gunzip_end(bp); + return rc; } static int @@ -3256,7 +3388,9 @@ #endif * context block must have already been enabled. */ bnx2_init_context(bp); - bnx2_init_cpus(bp); + if ((rc = bnx2_init_cpus(bp)) != 0) + return rc; + bnx2_init_nvram(bp); bnx2_set_mac_addr(bp); @@ -3556,7 +3690,9 @@ bnx2_reset_nic(struct bnx2 *bp, u32 rese if (rc) return rc; - bnx2_init_chip(bp); + if ((rc = bnx2_init_chip(bp)) != 0) + return rc; + bnx2_init_tx_ring(bp); bnx2_init_rx_ring(bp); return 0; @@ -4034,6 +4170,8 @@ bnx2_timer(unsigned long data) msg = (u32) ++bp->fw_drv_pulse_wr_seq; REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg); + bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); + if ((bp->phy_flags & PHY_SERDES_FLAG) && (CHIP_NUM(bp) == CHIP_NUM_5706)) { @@ -4252,7 +4390,7 @@ bnx2_vlan_rx_kill_vid(struct net_device } #endif -/* Called with dev->xmit_lock. +/* Called with netif_tx_lock. * hard_start_xmit is pseudo-lockless - a lock is only required when * the tx queue is full. This way, we get the benefit of lockless * operations most of the time without the complexities to handle @@ -4290,7 +4428,7 @@ bnx2_start_xmit(struct sk_buff *skb, str (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); } #ifdef BCM_TSO - if ((mss = skb_shinfo(skb)->tso_size) && + if ((mss = skb_shinfo(skb)->gso_size) && (skb->len > (bp->dev->mtu + ETH_HLEN))) { u32 tcp_opt_len, ip_tcp_len; @@ -4310,7 +4448,7 @@ #ifdef BCM_TSO ip_tcp_len = (skb->nh.iph->ihl << 2) + sizeof(struct tcphdr); skb->nh.iph->check = 0; - skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len); + skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len); skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr, @@ -4504,6 +4642,10 @@ bnx2_get_stats(struct net_device *dev) net_stats->tx_aborted_errors + net_stats->tx_carrier_errors; + net_stats->rx_missed_errors = + (unsigned long) (stats_blk->stat_IfInMBUFDiscards + + stats_blk->stat_FwRxDrop); + return net_stats; } @@ -4986,7 +5128,7 @@ bnx2_set_rx_csum(struct net_device *dev, return 0; } -#define BNX2_NUM_STATS 45 +#define BNX2_NUM_STATS 46 static struct { char string[ETH_GSTRING_LEN]; @@ -5036,6 +5178,7 @@ static struct { { "rx_mac_ctrl_frames" }, { "rx_filtered_packets" }, { "rx_discards" }, + { "rx_fw_discards" }, }; #define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4) @@ -5086,6 +5229,7 @@ static const unsigned long bnx2_stats_of STATS_OFFSET32(stat_MacControlFramesReceived), STATS_OFFSET32(stat_IfInFramesL2FilterDiscards), STATS_OFFSET32(stat_IfInMBUFDiscards), + STATS_OFFSET32(stat_FwRxDrop), }; /* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are @@ -5096,7 +5240,7 @@ static u8 bnx2_5706_stats_len_arr[BNX2_N 4,0,4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4, + 4,4,4,4,4,4, }; static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = { @@ -5104,7 +5248,7 @@ static u8 bnx2_5708_stats_len_arr[BNX2_N 4,4,4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4, + 4,4,4,4,4,4, }; #define BNX2_NUM_TESTS 6 @@ -5634,7 +5778,9 @@ bnx2_init_board(struct pci_dev *pdev, st } } - if (CHIP_NUM(bp) == CHIP_NUM_5708) + if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || + (CHIP_ID(bp) == CHIP_ID_5708_B0) || + (CHIP_ID(bp) == CHIP_ID_5708_B1)) bp->flags |= NO_WOL_FLAG; if (CHIP_ID(bp) == CHIP_ID_5706_A0) { diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index b87925f..5845e33 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -231,6 +231,7 @@ struct statistics_block { u32 stat_GenStat13; u32 stat_GenStat14; u32 stat_GenStat15; + u32 stat_FwRxDrop; }; @@ -3481,6 +3482,8 @@ #define BNX2_COM_COMQ_FTQ_CTL_CUR_DEPTH #define BNX2_COM_SCRATCH 0x00120000 +#define BNX2_FW_RX_DROP_COUNT 0x00120084 + /* * cp_reg definition @@ -3747,7 +3750,12 @@ #define RX_COPY_THRESH 92 #define DMA_READ_CHANS 5 #define DMA_WRITE_CHANS 3 -#define BCM_PAGE_BITS 12 +/* Use CPU native page size up to 16K for the ring sizes. */ +#if (PAGE_SHIFT > 14) +#define BCM_PAGE_BITS 14 +#else +#define BCM_PAGE_BITS PAGE_SHIFT +#endif #define BCM_PAGE_SIZE (1 << BCM_PAGE_BITS) #define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd)) @@ -3770,7 +3778,7 @@ #define NEXT_RX_BD(x) (((x) & (MAX_RX_DE #define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx) -#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> 8) +#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4)) #define RX_IDX(x) ((x) & MAX_RX_DESC_CNT) /* Context size. */ @@ -4048,6 +4056,9 @@ #define SERDES_AN_TIMEOUT (HZ / 3) u32 flash_size; int status_stats_size; + + struct z_stream_s *strm; + void *gunzip_buf; }; static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset); diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h index 8158974..2d753dc 100644 --- a/drivers/net/bnx2_fw.h +++ b/drivers/net/bnx2_fw.h @@ -7,7 +7,7 @@ * the Free Software Foundation, except as noted below. * * This file contains firmware data derived from proprietary unpublished - * source code, Copyright (c) 2004, 2005 Broadcom Corporation. + * source code, Copyright (c) 2004, 2005, 2006 Broadcom Corporation. * * Permission is hereby granted for the distribution of this firmware data * in hexadecimal or equivalent format, provided this copyright notice is @@ -28,943 +28,641 @@ static const u32 bnx2_COM_b06FwBssAddr = static const int bnx2_COM_b06FwBssLen = 0x88; static const u32 bnx2_COM_b06FwSbssAddr = 0x08005840; static const int bnx2_COM_b06FwSbssLen = 0x1c; -static u32 bnx2_COM_b06FwText[(0x57bc/4) + 1] = { - 0x0a00022d, 0x00000000, 0x00000000, 0x0000000d, 0x636f6d20, 0x322e352e, - 0x38000000, 0x02050802, 0x00000000, 0x00000003, 0x00000014, 0x00000032, - 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000010, 0x000003e8, 0x0000ea60, 0x00000001, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000002, 0x00000020, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24425840, - 0x3c030800, 0x246358e8, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004, - 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x261008b4, 0x3c1c0800, - 0x279c5840, 0x0e0002f7, 0x00000000, 0x0000000d, 0x27bdffe8, 0x3c1a8000, - 0x3c020008, 0x0342d825, 0x3c036010, 0xafbf0010, 0x8c655000, 0x3c020800, - 0x24470f30, 0x3c040800, 0x24865860, 0x2402ff7f, 0x00a22824, 0x34a5380c, - 0xac655000, 0x00002821, 0x24020037, 0x24030c80, 0xaf420008, 0xaf430024, - 0xacc70000, 0x24a50001, 0x2ca20016, 0x1440fffc, 0x24c60004, 0x24845860, - 0x3c020800, 0x24420f3c, 0x3c030800, 0x24630e2c, 0xac820004, 0x3c020800, - 0x24420a2c, 0x3c050800, 0x24a51268, 0xac82000c, 0x3c020800, 0x244243dc, - 0xac830008, 0x3c030800, 0x24633698, 0xac820014, 0x3c020800, 0x24423c24, - 0xac830018, 0xac83001c, 0x3c030800, 0x24630f44, 0xac820024, 0x3c020800, - 0x244243ac, 0xac83002c, 0x3c030800, 0x246343cc, 0xac820030, 0x3c020800, - 0x244242f0, 0xac830034, 0x3c030800, 0x24633d78, 0xac82003c, 0x3c020800, - 0x24420fd4, 0xac850010, 0xac850020, 0xac830040, 0x0e0010b7, 0xac820050, - 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafb00010, 0x27500100, - 0xafbf0018, 0xafb10014, 0x9203000b, 0x24020003, 0x1462005b, 0x96110008, - 0x32220001, 0x10400009, 0x27430080, 0x8e020000, 0x96040014, 0x000211c2, - 0x00021040, 0x00621821, 0xa4640000, 0x0a0002d0, 0x3c020800, 0x3c020800, - 0x8c430020, 0x1060002a, 0x3c030800, 0x0e00148e, 0x00000000, 0x97420108, - 0x8f850018, 0x9743010c, 0x3042003e, 0x00021400, 0x00621825, 0xaca30000, - 0x8f840018, 0x8f420100, 0xac820004, 0x97430116, 0x9742010e, 0x8f840018, - 0x00031c00, 0x00431025, 0xac820008, 0x97430110, 0x97440112, 0x8f850018, - 0x00031c00, 0x00832025, 0xaca4000c, 0x97420114, 0x8f840018, 0x3042ffff, - 0xac820010, 0x8f830018, 0xac600014, 0x8f820018, 0x3c030800, 0xac400018, - 0x946258ce, 0x8f840018, 0x3c032000, 0x00431025, 0xac82001c, 0x0e0014cc, - 0x24040001, 0x3c030800, 0x8c620040, 0x24420001, 0xac620040, 0x3c020800, - 0x8c430044, 0x32240004, 0x24630001, 0x10800017, 0xac430044, 0x8f4202b8, - 0x04430007, 0x8e020020, 0x3c040800, 0x8c830060, 0x24020001, 0x24630001, - 0x0a0002f2, 0xac830060, 0x3c060800, 0x8cc4005c, 0xaf420280, 0x96030016, - 0x00001021, 0xa7430284, 0x8e050004, 0x24840001, 0x3c031000, 0xaf450288, - 0xaf4302b8, 0x0a0002f2, 0xacc4005c, 0x32220002, 0x0a0002f2, 0x0002102b, - 0x3c026000, 0xac400808, 0x0000000d, 0x00001021, 0x8fbf0018, 0x8fb10014, - 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffc8, 0xafbf0034, 0xafbe0030, - 0xafb7002c, 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c, 0xafb20018, - 0xafb10014, 0x0e000244, 0xafb00010, 0x3c170800, 0x3c160800, 0x24110020, - 0x24150030, 0x2794000c, 0x27930008, 0x3c124000, 0x3c1e0800, 0x8f820004, - 0x3c040800, 0x8c830020, 0x10430005, 0x8ee200a4, 0xaf830004, 0x0e001593, - 0x00000000, 0x8ee200a4, 0x8ec300a0, 0x10430004, 0x26c400a0, 0x94820002, - 0xa742009e, 0xaee300a4, 0x8f500000, 0x32020007, 0x1040ffee, 0x32020001, - 0x1040002c, 0x32020002, 0x8f420100, 0xaf420020, 0x8f430104, 0xaf4300a8, - 0x9342010b, 0x93630000, 0x306300ff, 0x10710005, 0x304400ff, 0x10750006, - 0x2c820016, 0x0a000333, 0x00000000, 0xaf940000, 0x0a000334, 0x2c820016, - 0xaf930000, 0x0a000334, 0x00000000, 0xaf800000, 0x14400005, 0x00041880, - 0x0e0003cc, 0x00000000, 0x0a000340, 0x00000000, 0x3c020800, 0x24425860, - 0x00621821, 0x8c620000, 0x0040f809, 0x00000000, 0x10400005, 0x3c030800, - 0x8f420104, 0x3c016020, 0xac220014, 0x3c030800, 0x8c620034, 0xaf520138, - 0x24420001, 0xac620034, 0x32020002, 0x1040001a, 0x32020004, 0x8f420140, - 0xaf420020, 0x93630000, 0x306300ff, 0x10710005, 0x00000000, 0x10750006, - 0x00000000, 0x0a00035d, 0x00000000, 0xaf940000, 0x0a00035e, 0x00000000, - 0xaf930000, 0x0a00035e, 0x00000000, 0xaf800000, 0x0e000c7b, 0x00000000, - 0x3c040800, 0x8c820038, 0xaf520178, 0x24420001, 0xac820038, 0x32020004, - 0x1040ffa4, 0x00000000, 0x8f420180, 0xaf420020, 0x93630000, 0x306300ff, - 0x10710005, 0x00000000, 0x10750006, 0x00000000, 0x0a000378, 0x00000000, - 0xaf940000, 0x0a000379, 0x00000000, 0xaf930000, 0x0a000379, 0x00000000, - 0xaf800000, 0x8f430180, 0x24020f00, 0x14620005, 0x00000000, 0x8f420188, - 0xa742009c, 0x0a000387, 0x8fc2003c, 0x93620000, 0x14510004, 0x8fc2003c, - 0x0e000bad, 0x00000000, 0x8fc2003c, 0xaf5201b8, 0x24420001, 0x0a00030b, - 0xafc2003c, 0x27bdffe8, 0xafbf0010, 0x97420108, 0x24033000, 0x30447000, - 0x10830016, 0x28823001, 0x10400007, 0x24024000, 0x1080000b, 0x24022000, - 0x1082000c, 0x00000000, 0x0a0003b3, 0x00000000, 0x10820010, 0x24025000, - 0x10820012, 0x00000000, 0x0a0003b3, 0x00000000, 0x0000000d, 0x0a0003b5, - 0x00001021, 0x0e000442, 0x00000000, 0x0a0003b6, 0x8fbf0010, 0x0e00041a, - 0x00000000, 0x0a0003b5, 0x00001021, 0x0e000669, 0x00000000, 0x0a0003b5, - 0x00001021, 0x0e001467, 0x00000000, 0x0a0003b5, 0x00001021, 0x0000000d, - 0x00001021, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x93620000, 0x24030020, - 0x304400ff, 0x10830005, 0x24020030, 0x10820007, 0x00000000, 0x0a0003c9, - 0x00000000, 0x2782000c, 0xaf820000, 0x03e00008, 0x00000000, 0x27820008, - 0xaf820000, 0x03e00008, 0x00000000, 0xaf800000, 0x03e00008, 0x00000000, - 0x0000000d, 0x03e00008, 0x00001021, 0x03e00008, 0x00001021, 0x27440100, - 0x94830008, 0x30620004, 0x10400017, 0x30620002, 0x8f4202b8, 0x04430007, - 0x8c820020, 0x3c040800, 0x8c830060, 0x24020001, 0x24630001, 0x03e00008, - 0xac830060, 0xaf420280, 0x94830016, 0x3c060800, 0xa7430284, 0x8c850004, - 0x8cc4005c, 0x00001021, 0x3c031000, 0x24840001, 0xaf450288, 0xaf4302b8, - 0x03e00008, 0xacc4005c, 0x14400003, 0x3c040800, 0x03e00008, 0x00001021, - 0x8c830084, 0x24020001, 0x24630001, 0x03e00008, 0xac830084, 0x27450100, - 0x3c040800, 0x8c820088, 0x94a3000c, 0x24420001, 0x007a1821, 0xac820088, - 0x8ca40018, 0x90664000, 0xaf440038, 0x8ca2001c, 0x2403fff8, 0x00063600, - 0x00431024, 0x34420004, 0x3c030005, 0xaf42003c, 0xaf430030, 0x00000000, - 0x00000000, 0x00000000, 0xaf460404, 0x00000000, 0x00000000, 0x00000000, - 0x3c020006, 0x34420001, 0xaf420030, 0x00000000, 0x00000000, 0x00000000, - 0x8f420000, 0x30420010, 0x1040fffd, 0x00001021, 0x03e00008, 0x00000000, - 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x1060001e, - 0xafbf0014, 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020018, 0xac620000, - 0x8f840018, 0x9602000c, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, - 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f840018, - 0x3c026000, 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, - 0x8f850018, 0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, - 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010, - 0x27500100, 0xafbf0014, 0x92020009, 0x14400003, 0x3c020800, 0x0a00046c, - 0x24020001, 0x8c430020, 0x1060001f, 0x00001021, 0x0e00148e, 0x00000000, - 0x8f830018, 0x8e020018, 0xac620000, 0x8f840018, 0x9602000c, 0xac820004, - 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, - 0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, 0x8c434448, 0xac830018, - 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018, 0x00021400, 0x00441025, - 0x24040001, 0x0e0014cc, 0xaca2001c, 0x00001021, 0x8fbf0014, 0x8fb00010, - 0x03e00008, 0x27bd0018, 0x3c0b0800, 0x8d6808b0, 0x3c070800, 0x24e700b0, - 0x00084900, 0x01271821, 0xac640000, 0x93620005, 0x97660008, 0x00e95021, - 0x93630023, 0x9364003f, 0x25080001, 0x00021600, 0x00063400, 0x00461025, - 0x00031a00, 0x00431025, 0x00822025, 0xad440004, 0x9362007e, 0x9366007f, - 0x8f630178, 0x9364007a, 0x00021600, 0x00063400, 0x00461025, 0x00031a00, - 0x00431025, 0x00822025, 0xad440008, 0x93620080, 0x9363007d, 0x3108007f, - 0x01403821, 0xad6808b0, 0x00021600, 0x00031c00, 0x00431025, 0x00451025, - 0x03e00008, 0xace2000c, 0x27bdffb8, 0xafb3002c, 0x00009821, 0xafbe0040, - 0x0000f021, 0xafb50034, 0x27550100, 0xafbf0044, 0xafb7003c, 0xafb60038, - 0xafb40030, 0xafb20028, 0xafb10024, 0xafb00020, 0xafa00010, 0xafa00014, - 0x96a20008, 0x8f540100, 0x8eb10018, 0x30420001, 0x10400037, 0x02a0b821, - 0x8f630054, 0x2622ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, - 0x00000000, 0x2400015c, 0x0a0004e5, 0x00002021, 0x8f62004c, 0x02221023, - 0x18400028, 0x00002021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, - 0x308400ff, 0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, 0xac62008c, - 0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, - 0x00021023, 0x30420005, 0x0a0004e5, 0x34440004, 0x27660100, 0x00041080, - 0x00c21021, 0x8c430000, 0x02231823, 0x04600004, 0x24820001, 0x30440007, - 0x1485fff9, 0x00041080, 0x10870007, 0x3c030800, 0xa3640121, 0x8c620094, - 0x24040005, 0x24420001, 0x0a0004e5, 0xac620094, 0x24040004, 0x00809821, - 0x9362003f, 0x304400ff, 0x38830016, 0x2c630001, 0x38820010, 0x2c420001, - 0x00621825, 0x1460000c, 0x24020001, 0x38830008, 0x2c630001, 0x38820014, - 0x2c420001, 0x00621825, 0x14600005, 0x24020001, 0x24020012, 0x14820002, - 0x00001021, 0x24020001, 0x10400009, 0x00000000, 0x8ea20020, 0x8f630040, - 0x0040b021, 0x00431023, 0x5c400010, 0x8f760040, 0x0a000511, 0x00000000, - 0x9343010b, 0x24020004, 0x1462000a, 0x8eb60020, 0x8f630040, 0x3c021000, - 0x00761823, 0x0043102a, 0x10400004, 0x00000000, 0x0000000d, 0x00000000, - 0x240002fa, 0x9343010b, 0x24020004, 0x5462000b, 0x96a20008, 0x24020001, - 0xafa20010, 0x96a20008, 0x24030001, 0xafa30018, 0x8eb2001c, 0x36730002, - 0x30420020, 0x0a000526, 0xafa20014, 0x36730080, 0x30420002, 0x10400003, - 0xafa00018, 0x0a000526, 0x8eb2001c, 0x8eb20014, 0x2402fffb, 0x02628024, - 0x1200002a, 0x3c030800, 0x8c620030, 0x02021024, 0x10400026, 0x3c020800, - 0x8c430020, 0x10600024, 0x32620004, 0x0e00148e, 0x00000000, 0x8f830018, - 0x8f420100, 0xac620000, 0x8f840018, 0x02401821, 0x32620002, 0xac900004, - 0x8f840018, 0x54400001, 0x02c01821, 0xac830008, 0x8f830018, 0x8ee20020, - 0xac62000c, 0x8f840018, 0x8f620040, 0xac820010, 0x8f830018, 0x8ee20018, - 0xac620014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, - 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, 0x0e0014cc, - 0xaca3001c, 0x32620004, 0x10400063, 0x00003821, 0x3c029000, 0x34420001, - 0x3c038000, 0x02821025, 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, - 0x1440fffd, 0x00000000, 0x93620023, 0x30420080, 0x10400011, 0x00000000, - 0x8f65005c, 0x8f63004c, 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, - 0x00a2102b, 0x54400006, 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, - 0xaf710064, 0x3c023fff, 0x0a000580, 0x3442ffff, 0x8f62005c, 0x02221023, - 0x04400011, 0x00000000, 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, - 0x3442ffff, 0xaf710064, 0x00a32823, 0x00852821, 0x0045102b, 0x10400004, - 0x02251021, 0x3c053fff, 0x34a5ffff, 0x02251021, 0xaf62005c, 0x24070001, - 0xaf71004c, 0x8f620054, 0x16220005, 0x00000000, 0x93620023, 0x30420040, - 0x10400017, 0x24020001, 0x9762006a, 0x00022880, 0x50a00001, 0x24050001, - 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, - 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, - 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, - 0xaf62000c, 0x93620082, 0x30420080, 0x50400001, 0xa3600081, 0x3c028000, - 0x34420001, 0x02821025, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004, - 0x00000000, 0x0e0013c4, 0x00000000, 0x00403821, 0x54e00001, 0x241e0001, - 0x8f700040, 0x8f620040, 0x14520003, 0x00521023, 0x0a0005bf, 0x00001021, - 0x28420001, 0x10400041, 0x8fa20010, 0x0e000fae, 0x02402021, 0xaf720040, - 0x9362003e, 0x30420001, 0x1440000b, 0x3c029000, 0x93620022, 0x24420001, - 0xa3620022, 0x93630022, 0x3c020800, 0x8c440098, 0x0064182b, 0x14600027, - 0x3c020800, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, - 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, - 0x34420001, 0xa362007d, 0x8f640074, 0x34630001, 0x02831825, 0xaf430020, - 0x04810006, 0x3c038000, 0x02802021, 0x0e000470, 0x24050273, 0x0a0005f2, - 0x24050001, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, - 0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x24050001, 0x24020001, 0xa7620012, - 0xa3600022, 0x0a0005fe, 0x2ca20001, 0x9743007a, 0x9444002a, 0x00002821, - 0x00641821, 0x3063fffe, 0xa7630012, 0x2ca20001, 0x00021023, 0x03c2f024, - 0x8fa20010, 0x10400004, 0x8fa30014, 0x0e0013c1, 0x00000000, 0x8fa30014, - 0x10600003, 0x00000000, 0x0e0010eb, 0x00000000, 0x13c0001f, 0x3c029000, - 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, - 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, - 0x34630001, 0x02831825, 0xaf430020, 0x04810006, 0x3c038000, 0x02802021, - 0x0e000470, 0x2405036c, 0x0a00062b, 0x8fa20018, 0x8f4201f8, 0x00431024, - 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4, 0xaf4301f8, - 0x8fa20018, 0x5040002f, 0x96a20008, 0x8f620048, 0x8f630024, 0x00761821, - 0xaf630048, 0x9764003c, 0x00501023, 0x0044102b, 0x10400025, 0x3c029000, - 0x34420001, 0x3c040800, 0x8c830080, 0x8f450100, 0x3c068000, 0x24630001, - 0x00a21025, 0xac830080, 0xaf420020, 0x8f420020, 0x00461024, 0x1440fffd, - 0x00000000, 0x9362007d, 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, - 0x34630001, 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, - 0x0e000470, 0x2405038a, 0x0a00065b, 0x96a20008, 0x8f4201f8, 0x00431024, - 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, - 0x96a20008, 0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 0x8fb60038, 0x8fb50034, - 0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 0x00021042, - 0x30420001, 0x03e00008, 0x27bd0048, 0x27bdffe0, 0xafbf0018, 0x97420108, - 0x24030019, 0x304400ff, 0x10830065, 0x2882001a, 0x1040001a, 0x2882000a, - 0x1040000f, 0x28820008, 0x10400040, 0x24020001, 0x1082003a, 0x28820002, - 0x50400005, 0x24020006, 0x10800032, 0x3c026000, 0x0a0006fb, 0x00000000, - 0x1082003d, 0x00000000, 0x0a0006fb, 0x00000000, 0x2402000b, 0x10820044, - 0x2882000b, 0x1440004b, 0x2402000e, 0x10820045, 0x00000000, 0x0a0006fb, - 0x00000000, 0x24020020, 0x10820062, 0x28820021, 0x1040000e, 0x2402001c, - 0x1082004c, 0x2882001d, 0x10400005, 0x2402001b, 0x10820043, 0x00000000, - 0x0a0006fb, 0x00000000, 0x2402001f, 0x10820050, 0x00000000, 0x0a0006fb, - 0x00000000, 0x240200c1, 0x10820042, 0x288200c2, 0x10400005, 0x24020080, - 0x10820021, 0x00000000, 0x0a0006fb, 0x00000000, 0x240200c2, 0x1082003d, - 0x240200c9, 0x50820049, 0xafa00010, 0x0a0006fb, 0x00000000, 0x0e001163, - 0xac400808, 0x0a0006fd, 0x8fbf0018, 0x3c026000, 0x8c444448, 0x3c030800, - 0xac640064, 0x0e001163, 0x00000000, 0x3c026000, 0x8c444448, 0x3c030800, - 0x0a0006fc, 0xac640068, 0x8f440100, 0x0e0006ff, 0x00000000, 0x3c026000, - 0x8c444448, 0x3c030800, 0x0a0006fc, 0xac64006c, 0x0e001191, 0x00000000, - 0x0a0006fd, 0x8fbf0018, 0x8f440100, 0x0e0011bb, 0x00000000, 0x0a0006fd, - 0x8fbf0018, 0x0e001202, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0000000d, - 0x0a0006fd, 0x8fbf0018, 0x0e000826, 0x00000000, 0x0a0006fd, 0x8fbf0018, - 0x8f440100, 0x0e001264, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e00134e, - 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e00087c, 0x27440100, 0x0a0006fd, - 0x8fbf0018, 0x8f640040, 0x0e000fae, 0x00000000, 0x0a0006fd, 0x8fbf0018, - 0x8f440100, 0x0e001059, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e001417, - 0x00000000, 0x0a0006fd, 0x8fbf0018, 0xafa00014, 0x8f440100, 0x8f450118, - 0x8f46011c, 0x0e001439, 0x8f470120, 0x0a0006fd, 0x8fbf0018, 0x0000000d, - 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, 0x9742010c, - 0x1440005e, 0x00803821, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020, - 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, - 0x30420010, 0x14400026, 0x3c030800, 0x8f630074, 0x3c027fff, 0x3442ffff, - 0x00621824, 0xaf630074, 0x93620005, 0x34420001, 0xa3620005, 0x8f63004c, - 0x8f620054, 0x10620021, 0x24040001, 0x9762006a, 0x00022880, 0x50a00001, - 0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, - 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, - 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, - 0x00a21021, 0xaf62000c, 0x0a00073d, 0x24040001, 0x8c6200a8, 0x00002021, - 0x24420001, 0xac6200a8, 0x0000000d, 0x00000000, 0x2400044d, 0x3c028000, - 0x34420001, 0x00e21025, 0xaf420020, 0x1080001f, 0x3c029000, 0x34420001, - 0x00e21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, - 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001, - 0x00e31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00e02021, 0x0e000470, - 0x24050455, 0x0a000761, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd, - 0x24020002, 0x3c031000, 0xaf4701c0, 0xa34201c4, 0xaf4301f8, 0x0e001163, - 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffd8, 0xafbf0024, - 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x93630005, - 0x00809821, 0x24020030, 0x30630030, 0x146200ac, 0x00a0a021, 0x3c020800, - 0x8c430020, 0x106000a6, 0x00000000, 0x0e00148e, 0x00000000, 0x8f830018, - 0xac730000, 0x936200c4, 0x30420002, 0x10400004, 0x24020001, 0x8f830018, - 0x0a000784, 0x00000000, 0x8f830018, 0x24020003, 0xac620004, 0x8f6200dc, - 0x8f630040, 0x00431023, 0x18400004, 0x00000000, 0x0000000d, 0x00000000, - 0x24000509, 0x8f840018, 0x8f6200dc, 0xac820008, 0x8f830018, 0xac60000c, - 0x8f820018, 0xac400010, 0x8f830018, 0x8f62004c, 0x3c100800, 0xac620014, - 0x8f850018, 0x3c026000, 0x8c434448, 0x261258c0, 0x00002021, 0xaca30018, - 0x9642000e, 0x8f850018, 0x3c034010, 0x00431025, 0x0e0014cc, 0xaca2001c, - 0x8f830018, 0xac730000, 0x9362003e, 0x9363003f, 0x8f840018, 0x00021200, - 0x00621825, 0xac830004, 0x93620081, 0x93630082, 0x8f840018, 0x00021600, - 0x00031c00, 0x00431025, 0xac820008, 0x8f830018, 0x8f620040, 0xac62000c, - 0x8f840018, 0x8f620048, 0xac820010, 0x8f71004c, 0x8f820018, 0xac510014, - 0x8f620050, 0x8f850018, 0x00401821, 0x02221023, 0x5c400001, 0x02201821, - 0x00002021, 0xaca30018, 0x9642000e, 0x8f850018, 0x3c03c00b, 0x00431025, - 0x0e0014cc, 0xaca2001c, 0x8f620054, 0x8f840018, 0x00401821, 0x02221023, - 0x5c400001, 0x02201821, 0xac830000, 0x8f840018, 0x8f630058, 0xac830004, - 0x93620023, 0x30420010, 0x10400004, 0x00000000, 0x8f830018, 0x0a0007dd, - 0x8f620148, 0x8f830018, 0x8f62005c, 0xac620008, 0x8f830018, 0x8f620060, - 0xac62000c, 0x8f840018, 0x8f620064, 0xac820010, 0x97630068, 0x9762006a, - 0x8f840018, 0x00031c00, 0x00431025, 0xac820014, 0x8f850018, 0x00002021, - 0x2402ffff, 0x260358c0, 0xaca20018, 0x9462000e, 0x8f850018, 0x3c03c00c, - 0x00431025, 0x0e0014cc, 0xaca2001c, 0x8f840018, 0x8f630018, 0xac830000, - 0x936200c4, 0x30420002, 0x10400006, 0x00000000, 0x976200c8, 0x8f830018, - 0x3042ffff, 0x0a000803, 0xac620004, 0x8f820018, 0xac400004, 0x8f830018, - 0x8f62006c, 0xac620008, 0x8f840018, 0x8f6200dc, 0xac82000c, 0x8f830018, - 0xac600010, 0x93620005, 0x8f830018, 0x00021600, 0x00541025, 0xac620014, - 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x260258c0, 0xaca30018, - 0x9443000e, 0x8f850018, 0x3c02400d, 0x00621825, 0x0e0014cc, 0xaca3001c, - 0x0e00122e, 0x02602021, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, - 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0028, 0x27bdffe0, 0xafb00010, - 0x27500100, 0xafbf0018, 0xafb10014, 0x9603000c, 0x240200c1, 0x54620024, - 0x8e040000, 0x3c029000, 0x8f450100, 0x34420001, 0x3c038000, 0x00a21025, - 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, - 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, 0x34630001, 0x00a31825, - 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, 0x0e000470, 0x240505b2, - 0x0a000878, 0x8fbf0018, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, - 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, 0x0a000878, 0x8fbf0018, - 0x8f65004c, 0x24060001, 0x0e0012a3, 0x240705be, 0x3c020800, 0x8c430020, - 0x9611000c, 0x1060001d, 0x8e100000, 0x0e00148e, 0x00000000, 0x8f820018, - 0xac500000, 0x8f840018, 0x00111400, 0xac820004, 0x8f830018, 0xac600008, - 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f840018, 0x240205c1, - 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, - 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024019, 0x00621825, 0x0e0014cc, - 0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, - 0x27bdffb0, 0xafb5003c, 0x0000a821, 0xafbe0048, 0x0000f021, 0xafb70044, - 0x0000b821, 0xafb30034, 0x00009821, 0xafb60040, 0x0080b021, 0xafbf004c, - 0xafb40038, 0xafb20030, 0xafb1002c, 0xafb00028, 0xafa00010, 0x8f620040, - 0x8ec30014, 0x96d1000c, 0x00431023, 0x04410025, 0x8ed40000, 0x32220401, - 0x1040030c, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, - 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, - 0x34420004, 0xa362007d, 0x8f640074, 0x34630001, 0x02831825, 0xaf430020, - 0x04810006, 0x3c038000, 0x02802021, 0x0e000470, 0x24050664, 0x0a000ba2, - 0x8fbf004c, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, - 0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x0a000ba2, 0x8fbf004c, 0x32220010, - 0x1040006b, 0x00003021, 0x9362003f, 0x92c6000f, 0x304500ff, 0x24c3fff8, - 0x2c62000f, 0x10400057, 0x3c020800, 0x244257c0, 0x00031880, 0x00621821, - 0x8c640000, 0x00800008, 0x00000000, 0x38a20012, 0x0a000924, 0x0002a82b, - 0x2402000e, 0x14a20004, 0x2402000c, 0x24150001, 0x0a000924, 0x24060010, - 0x10a20049, 0x38a30010, 0x2c630001, 0x38a20016, 0x2c420001, 0x00621825, - 0x1460004d, 0x0000a821, 0x24020014, 0x10a2004a, 0x00000000, 0x0000000d, - 0x00000000, 0x2400069c, 0x0a000924, 0x0000a821, 0x24020016, 0x14a20005, - 0x2402000c, 0x24150001, 0x24060010, 0x0a000924, 0x3231fffd, 0x10a20032, - 0x38a30010, 0x2c630001, 0x38a2000e, 0x2c420001, 0x00621825, 0x14600036, - 0x0000a821, 0x24020014, 0x14a20003, 0x24150001, 0x0a000924, 0x24060012, - 0x0000000d, 0x00000000, 0x240006bc, 0x0a000924, 0x0000a821, 0x2402000e, - 0x14a20004, 0x24020016, 0x24150001, 0x0a000924, 0x3231fffb, 0x14a20004, - 0x24020014, 0x24150001, 0x0a000924, 0x3231fffd, 0x54a20013, 0x92c2000e, - 0x24150001, 0x24060012, 0x0a000924, 0x3231fffd, 0x2402000c, 0x54a2000c, - 0x92c2000e, 0x92c3000e, 0x2402000a, 0x10620005, 0x24150001, 0x0000000d, - 0x00000000, 0x240006e8, 0x24150001, 0x0a000924, 0x24060014, 0x92c2000e, - 0x14a20003, 0x00000000, 0x0a000924, 0x24150001, 0x10a6ffc1, 0x24020012, - 0x10a20005, 0x0000a821, 0x0000000d, 0x00000000, 0x24000704, 0x0000a821, - 0x12a00022, 0x32220004, 0x10400002, 0x24020001, 0xafa20010, 0x32230102, - 0x24020002, 0x1462000f, 0x00000000, 0x92c2000a, 0x30420020, 0x1440000b, - 0x00000000, 0x8f630048, 0x8f620040, 0x14620004, 0x00000000, 0x8f620048, - 0x24420001, 0xaf620048, 0x8f620040, 0x24420001, 0xaf620040, 0xa366003f, - 0x38c30012, 0x2c630001, 0x38c20010, 0x2c420001, 0x00621825, 0x10600005, - 0x3c030800, 0x8c620074, 0x24420001, 0x0e00140d, 0xac620074, 0x32220040, - 0x32230020, 0xafa30020, 0x32230080, 0xafa30024, 0x32230001, 0xafa30018, - 0x32230008, 0xafa3001c, 0x32230100, 0x104000c4, 0xafa30014, 0x8ec60010, - 0x8f630054, 0x24c2ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, - 0x00000000, 0x2400015c, 0x0a000989, 0x00009021, 0x8f62004c, 0x00c21023, - 0x18400028, 0x00009021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, - 0x308400ff, 0x24420001, 0x30a500ff, 0x00804021, 0x1485000b, 0xac62008c, - 0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, - 0x00021023, 0x30420005, 0x0a000989, 0x34520004, 0x27670100, 0x00041080, - 0x00e21021, 0x8c430000, 0x00c31823, 0x04600004, 0x24820001, 0x30440007, - 0x1485fff9, 0x00041080, 0x10880007, 0x3c030800, 0xa3640121, 0x8c620094, - 0x24120005, 0x24420001, 0x0a000989, 0xac620094, 0x24120004, 0x32420001, - 0x10400021, 0x3c020800, 0x8c430020, 0x8ed00000, 0x1060001c, 0x8ed30010, - 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, - 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, - 0xac600010, 0x8f820018, 0xac530014, 0x8f850018, 0x3c026000, 0x8c434448, - 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, - 0x00621825, 0x0e0014cc, 0xaca3001c, 0x24130001, 0x32420004, 0x10400068, - 0x00003821, 0x3c029000, 0x8ec60010, 0x34420001, 0x3c038000, 0x02821025, - 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, - 0x93620023, 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c, - 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006, - 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, 0xaf660064, 0x3c023fff, - 0x0a0009da, 0x3442ffff, 0x8f62005c, 0x00c21023, 0x04400011, 0x00000000, - 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf660064, - 0x00a32823, 0x00852821, 0x0045102b, 0x10400004, 0x00c51021, 0x3c053fff, - 0x34a5ffff, 0x00c51021, 0xaf62005c, 0x24070001, 0xaf66004c, 0x8fa20010, - 0x10400003, 0x00000000, 0xaf660050, 0xaf660054, 0x8f620054, 0x14c20005, - 0x00000000, 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a, - 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800, - 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, - 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, - 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x93620082, 0x30420080, - 0x50400001, 0xa3600081, 0x3c028000, 0x34420001, 0x02821025, 0xaf420020, - 0x9363007e, 0x9362007a, 0x10620005, 0x00e0b821, 0x0e0013c4, 0x00000000, - 0x00403821, 0x00e0b821, 0x8fa30020, 0x10600009, 0x8fa20010, 0x8ec20018, - 0xaf620018, 0x8ec3001c, 0xaf63001c, 0x8ec20020, 0x24170001, 0xaf620058, - 0x8fa20010, 0x10400057, 0x8fa30024, 0x93620023, 0x30420040, 0x10400053, - 0x00000000, 0x16600021, 0x3c120800, 0x8e420020, 0x8f70004c, 0x1040001e, - 0x24130001, 0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, - 0x24020001, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, - 0x8f830018, 0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000, - 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, - 0x3c024010, 0x00621825, 0xaca3001c, 0x0e0014cc, 0x24130001, 0x8e420020, - 0x1040001c, 0x8ed00000, 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, - 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, - 0x8f820018, 0xac400010, 0x8f830018, 0x24020798, 0xac620014, 0x8f850018, - 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, - 0x8f850018, 0x3c024019, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, - 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, - 0x1440fffd, 0x24020001, 0xaf62000c, 0x93630023, 0x3c028000, 0x34420001, - 0x02821025, 0x306300bf, 0xa3630023, 0xaf420020, 0x8fa30024, 0x10600012, - 0x8fa30018, 0x9362007c, 0x24420001, 0xa362007c, 0x9363007e, 0x9362007a, - 0x1462000b, 0x8fa30018, 0x9362007c, 0x3c030800, 0x8c640024, 0x0044102b, - 0x14400005, 0x8fa30018, 0x0e0013c4, 0x00000000, 0x02e2b825, 0x8fa30018, - 0x3062ffff, 0x10400003, 0x32220200, 0x0a000a94, 0x241e0004, 0x10400003, - 0x00000000, 0x241e0040, 0x24170001, 0x12a000d0, 0x32220002, 0x104000cf, - 0x8fa2001c, 0x92c2000a, 0x30420002, 0x5040003b, 0x92c2000a, 0x93620023, - 0x30420008, 0x54400037, 0x92c2000a, 0x3c020800, 0x8c430020, 0x10600023, - 0x3c029000, 0x0e00148e, 0x00000000, 0x8f840018, 0x8ec30000, 0xac830000, - 0x92c2000a, 0x8f830018, 0x00021600, 0xac620004, 0x8f840018, 0x8f620040, - 0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, 0x9362003f, 0x8f840018, - 0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018, - 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, - 0x3c02401a, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001, - 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, - 0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x34630008, - 0xa3630023, 0xaf420020, 0x92c2000a, 0x30420020, 0x1040008e, 0x8fa2001c, - 0x93620023, 0x30420001, 0x14400035, 0x3c020800, 0x8c430020, 0x10600023, - 0x3c029000, 0x0e00148e, 0x00000000, 0x8f840018, 0x8ec30000, 0xac830000, - 0x92c2000a, 0x8f830018, 0x00021600, 0xac620004, 0x8f840018, 0x8f620040, - 0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, 0x9362003f, 0x8f840018, - 0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018, - 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, - 0x3c02401a, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001, - 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, - 0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x34630001, - 0xa3630023, 0xaf420020, 0x93620023, 0x30420040, 0x10400052, 0x8fa2001c, - 0x16600020, 0x3c120800, 0x8e420020, 0x8f70004c, 0x1040003c, 0x3c029000, - 0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, 0x24020001, - 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, - 0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448, - 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, - 0x00621825, 0x0e0014cc, 0xaca3001c, 0x8e420020, 0x1040001e, 0x3c029000, - 0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, 0x3c02008d, - 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, - 0xac600010, 0x8f840018, 0x240207ee, 0xac820014, 0x8f850018, 0x3c026000, - 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, - 0x3c024019, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001, - 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, - 0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x306300bf, - 0xa3630023, 0xaf420020, 0x8fa2001c, 0x1040000e, 0x8fa20014, 0x92c2000a, - 0xa3620082, 0x57c00005, 0x37de0008, 0x8fa30014, 0x10600004, 0x00000000, - 0x37de0008, 0x0a000b75, 0x24170001, 0x0e0012cf, 0x02802021, 0x8fa20014, - 0x10400003, 0x00000000, 0x37de0010, 0x24170001, 0x12e00020, 0x3c029000, - 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, - 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x03c21025, 0xa362007d, - 0x8f640074, 0x34630001, 0x02831825, 0xaf430020, 0x04810006, 0x3c038000, - 0x02802021, 0x0e000470, 0x2405082a, 0x0a000b9b, 0x00000000, 0x8f4201f8, - 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4, - 0xaf4301f8, 0x9363003f, 0x24020012, 0x14620004, 0x8fbf004c, 0x0e00140d, - 0x00000000, 0x8fbf004c, 0x8fbe0048, 0x8fb70044, 0x8fb60040, 0x8fb5003c, - 0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x03e00008, - 0x27bd0050, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f500180, 0x97420184, - 0x30420200, 0x14400015, 0x00000000, 0x8f430188, 0x3c02ff00, 0x00621824, - 0x3c020200, 0x10620031, 0x0043102b, 0x14400007, 0x3c020300, 0x1060000b, - 0x3c020100, 0x1062000d, 0x00000000, 0x0a000c2c, 0x00000000, 0x10620027, - 0x3c020400, 0x1062003e, 0x02002021, 0x0a000c2c, 0x00000000, 0x0e000c31, - 0x02002021, 0x0a000c2e, 0x8fbf0014, 0x93620005, 0x30420020, 0x1440005e, - 0x8fbf0014, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000, - 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000, - 0x34630001, 0x02031825, 0x34420020, 0xa3620005, 0xaf430020, 0x93620005, - 0x30420020, 0x14400003, 0x02002021, 0x0000000d, 0x02002021, 0x0e000766, - 0x24055854, 0x0a000c2e, 0x8fbf0014, 0x93620005, 0x30420001, 0x1040003f, - 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000, 0x8f420020, - 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, 0x34420004, 0xa3620023, - 0x93630005, 0x3c048000, 0x3c020800, 0x306300fe, 0xa3630005, 0x8c430020, - 0x34840001, 0x02042025, 0x0a000c0a, 0xaf440020, 0x00002821, 0x00003021, - 0x0e000fb1, 0x240708d9, 0x3c020800, 0x8c430020, 0x10600023, 0x8fbf0014, - 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x93630082, 0x9362003f, - 0x8f840018, 0x00031a00, 0x00431025, 0xac820004, 0x8f830018, 0xac600008, - 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, - 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, - 0x944358ce, 0x8f850018, 0x3c02400a, 0x00621825, 0x0e0014cc, 0xaca3001c, - 0x0a000c2e, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, 0x03e00008, - 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x8f420188, 0x00803021, 0x93640000, - 0x24030020, 0x00021402, 0x10830008, 0x304500ff, 0x3c036018, 0x8c625000, - 0x34420400, 0xac625000, 0x0000000d, 0x00000000, 0x24000955, 0x9363003f, - 0x24020012, 0x14620023, 0x3c029000, 0x34420001, 0x3c038000, 0x00c21025, - 0xaf650178, 0xa365007a, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, - 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001, - 0x00c31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00c02021, 0x0e000470, - 0x24050963, 0x0a000c79, 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd, - 0x24020002, 0x3c031000, 0xaf4601c0, 0xa34201c4, 0xaf4301f8, 0x0a000c79, - 0x8fbf0010, 0x9362007e, 0x1445000e, 0x00000000, 0x8f620178, 0x1045000b, - 0x00000000, 0x8f820000, 0xaf650178, 0x8f660178, 0x8f440180, 0x8f65004c, - 0x8c430000, 0x0060f809, 0x30c600ff, 0x0a000c79, 0x8fbf0010, 0xaf650178, - 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x93630000, - 0x24020020, 0x10620005, 0x00000000, 0x93630000, 0x24020030, 0x1462004d, - 0x8fbf0010, 0x93420148, 0x2444ffff, 0x2c830005, 0x10600047, 0x3c020800, - 0x24425800, 0x00041880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000, - 0x8f430144, 0x8f62000c, 0x14620006, 0x24020001, 0xaf62000c, 0x0e000d59, - 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x8f62000c, 0x0a000cca, 0x00000000, - 0x97630010, 0x8f420144, 0x14430006, 0x24020001, 0xa7620010, 0x0e00137a, - 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620010, 0x0a000cca, 0x00000000, - 0x97630012, 0x8f420144, 0x14430006, 0x24020001, 0xa7620012, 0x0e001395, - 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620012, 0x0a000cca, 0x00000000, - 0x97630014, 0x8f420144, 0x14430006, 0x24020001, 0xa7620014, 0x0e0013bb, - 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620014, 0x0a000cca, 0x00000000, - 0x97630016, 0x8f420144, 0x14430006, 0x24020001, 0xa7620016, 0x0e0013be, - 0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620016, 0x14400006, 0x8fbf0010, - 0x3c030800, 0x8c620070, 0x24420001, 0xac620070, 0x8fbf0010, 0x03e00008, - 0x27bd0018, 0x27bdffe0, 0x3c029000, 0xafbf001c, 0xafb20018, 0xafb10014, - 0xafb00010, 0x8f500140, 0x34420001, 0x3c038000, 0x02021025, 0xaf420020, - 0x8f420020, 0x00431024, 0x1440fffd, 0x24020012, 0x24030080, 0xa362003f, - 0xa3630082, 0x93620023, 0x30420040, 0x10400007, 0x00008821, 0x93620023, - 0x24110001, 0x304200bf, 0xa3620023, 0x0a000cf0, 0x3c028000, 0x3c028000, - 0x34420001, 0x3c039000, 0x34630001, 0x3c048000, 0x02021025, 0x02031825, - 0xaf420020, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000, - 0x9362007d, 0x3c038000, 0x34420020, 0xa362007d, 0x8f640074, 0x34630001, - 0x02031825, 0xaf430020, 0x04810006, 0x3c038000, 0x02002021, 0x0e000470, - 0x24050a63, 0x0a000d13, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd, - 0x24020002, 0x3c031000, 0xaf5001c0, 0xa34201c4, 0xaf4301f8, 0x1220003f, - 0x3c120800, 0x8e420020, 0x8f71004c, 0x1040003c, 0x8fbf001c, 0x0e00148e, - 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, 0xac820004, - 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, - 0x8f820018, 0xac510014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, - 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, - 0x0e0014cc, 0xaca3001c, 0x8e420020, 0x1040001e, 0x8fbf001c, 0x0e00148e, - 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x3c02008d, 0xac820004, - 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, - 0x8f840018, 0x24020a6a, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, - 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024019, - 0x00621825, 0x0e0014cc, 0xaca3001c, 0x8fbf001c, 0x8fb20018, 0x8fb10014, - 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, 0x93620081, - 0x3c030800, 0x8c640048, 0x0044102b, 0x14400005, 0x00000000, 0x0e000cd3, - 0x00000000, 0x0a000da4, 0x8fbf0010, 0x93620081, 0x24420001, 0x0e0013c4, - 0xa3620081, 0x9763006a, 0x00032880, 0x14a00002, 0x00403821, 0x24050001, - 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, - 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, - 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, - 0xaf62000c, 0x10e00021, 0x3c029000, 0x8f450140, 0x34420001, 0x3c038000, - 0x00a21025, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, - 0x9362007d, 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, 0x34630001, - 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, 0x0e000470, - 0x24050a92, 0x0a000da4, 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd, - 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, 0x8fbf0010, - 0x03e00008, 0x27bd0018, 0x27bdffd8, 0xafb3001c, 0x27530100, 0xafbf0024, - 0xafb40020, 0xafb20018, 0xafb10014, 0xafb00010, 0x96620008, 0x3c140800, - 0x8f520100, 0x30420001, 0x104000da, 0x00000000, 0x8e700018, 0x8f630054, - 0x2602ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, 0x00000000, - 0x2400015c, 0x0a000dea, 0x00008821, 0x8f62004c, 0x02021023, 0x18400028, - 0x00008821, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, 0x308400ff, - 0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, 0xac62008c, 0x3c040800, - 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, 0x00021023, - 0x30420005, 0x0a000dea, 0x34510004, 0x27660100, 0x00041080, 0x00c21021, - 0x8c430000, 0x02031823, 0x04600004, 0x24820001, 0x30440007, 0x1485fff9, - 0x00041080, 0x10870007, 0x3c030800, 0xa3640121, 0x8c620094, 0x24110005, - 0x24420001, 0x0a000dea, 0xac620094, 0x24110004, 0x32220001, 0x1040001e, - 0x8e820020, 0x1040001d, 0x32220004, 0x0e00148e, 0x00000000, 0x8f820018, - 0xac520000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018, 0xac600008, - 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac500014, - 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, - 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, 0x0e0014cc, 0xaca3001c, - 0x32220004, 0x10400081, 0x00003821, 0x3c029000, 0x34420001, 0x3c038000, - 0x02421025, 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, - 0x00000000, 0x93620023, 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, - 0x8f63004c, 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, - 0x54400006, 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, 0xaf700064, - 0x3c023fff, 0x0a000e37, 0x3442ffff, 0x8f62005c, 0x02021023, 0x04400011, - 0x00000000, 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, - 0xaf700064, 0x00a32823, 0x00852821, 0x0045102b, 0x10400004, 0x02051021, - 0x3c053fff, 0x34a5ffff, 0x02051021, 0xaf62005c, 0x24070001, 0xaf70004c, - 0x8f620054, 0x16020005, 0x00000000, 0x93620023, 0x30420040, 0x10400017, - 0x24020001, 0x9762006a, 0x00022880, 0x50a00001, 0x24050001, 0x97630068, - 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, - 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, - 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, - 0x93620082, 0x30420080, 0x50400001, 0xa3600081, 0x3c028000, 0x34420001, - 0x02421025, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004, 0x00000000, - 0x0e0013c4, 0x00000000, 0x00403821, 0x10e0001f, 0x3c029000, 0x34420001, - 0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, - 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001, - 0x02431825, 0xaf430020, 0x04810006, 0x3c038000, 0x02402021, 0x0e000470, - 0x24050b3d, 0x0a000e8d, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd, - 0x24020002, 0x3c031000, 0xaf5201c0, 0xa34201c4, 0xaf4301f8, 0x9342010b, - 0x9343010b, 0x8e820020, 0x27500100, 0x38630006, 0x10400029, 0x2c710001, - 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, - 0x96020008, 0xac820004, 0x8f830018, 0x8e020014, 0xac620008, 0x8f850018, - 0x3c026000, 0x8c434448, 0xaca3000c, 0x8f840018, 0x96020012, 0xac820010, - 0x8f850018, 0x8e030020, 0xaca30014, 0x9602000c, 0x9603000e, 0x8f840018, - 0x00021400, 0x00431025, 0xac820018, 0x12200005, 0x3c020800, 0x944358ce, - 0x8f840018, 0x0a000eb8, 0x3c024013, 0x944358ce, 0x8f840018, 0x3c024014, - 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8e700014, 0x8f620040, - 0x14500003, 0x00501023, 0x0a000ec3, 0x00001021, 0x28420001, 0x1040003a, - 0x00000000, 0x0e000fae, 0x02002021, 0xaf700040, 0x9362003e, 0x30420001, - 0x1440000b, 0x3c029000, 0x93620022, 0x24420001, 0xa3620022, 0x93630022, - 0x3c020800, 0x8c440098, 0x0064182b, 0x14600025, 0x3c020800, 0x3c029000, - 0x34420001, 0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, - 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x34420001, 0xa362007d, - 0x8f640074, 0x34630001, 0x02431825, 0xaf430020, 0x04810006, 0x3c038000, - 0x02402021, 0x0e000470, 0x24050273, 0x0a000ef6, 0x24020001, 0x8f4201f8, - 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5201c0, 0xa34201c4, - 0xaf4301f8, 0x24020001, 0xa7620012, 0x0a000efe, 0xa3600022, 0x9743007a, - 0x9444002a, 0x00641821, 0x3063fffe, 0xa7630012, 0x97420108, 0x8fbf0024, - 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00021042, - 0x30420001, 0x03e00008, 0x27bd0028, 0x27bdffe0, 0xafb20018, 0x3c120800, - 0x8e420020, 0xafb00010, 0x27500100, 0xafbf001c, 0x10400046, 0xafb10014, - 0x0e00148e, 0x00000000, 0x8f840018, 0x8e020000, 0xac820000, 0x936300b1, - 0x936200c5, 0x8f850018, 0x00031e00, 0x00021400, 0x34420100, 0x00621825, - 0xaca30004, 0x8f840018, 0x8e02001c, 0xac820008, 0x8f830018, 0x8f620048, - 0xac62000c, 0x8f840018, 0x96020012, 0xac820010, 0x8f830018, 0x8f620040, - 0x24040001, 0xac620014, 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800, - 0x245158c0, 0xaca30018, 0x9623000e, 0x8f850018, 0x3c024016, 0x00621825, - 0x0e0014cc, 0xaca3001c, 0x96030008, 0x30630010, 0x1060001c, 0x8e420020, - 0x1040001a, 0x8e100000, 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, - 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, - 0x8f820018, 0xac400010, 0x8f830018, 0xac600014, 0x8f850018, 0x3c036000, - 0x8c634448, 0x24040001, 0xaca30018, 0x9622000e, 0x8f850018, 0x3c034015, - 0x00431025, 0x0e0014cc, 0xaca2001c, 0x00001021, 0x8fbf001c, 0x8fb20018, - 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe0, 0xafb20018, - 0x3c120800, 0x8e420020, 0xafb00010, 0x27500100, 0xafbf001c, 0x10400041, - 0xafb10014, 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, - 0x8f840018, 0x24020100, 0xac820004, 0x8f830018, 0x8e02001c, 0xac620008, - 0x8f840018, 0x8e020018, 0xac82000c, 0x8f830018, 0x96020012, 0xac620010, - 0x8f840018, 0x96020008, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, - 0x24040001, 0x3c020800, 0x245158c0, 0xaca30018, 0x9623000e, 0x8f850018, - 0x3c024017, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x96030008, 0x30630010, - 0x1060001c, 0x8e420020, 0x1040001a, 0x8e100000, 0x0e00148e, 0x00000000, - 0x8f820018, 0xac500000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, - 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018, 0xac600014, - 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001, 0xaca30018, 0x9622000e, - 0x8f850018, 0x3c034015, 0x00431025, 0x0e0014cc, 0xaca2001c, 0x00001021, - 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, - 0x27bdfff0, 0x03e00008, 0x27bd0010, 0x27bdffd0, 0xafb10014, 0x00808821, - 0xafb40020, 0x00c0a021, 0xafbf0028, 0xafb50024, 0xafb3001c, 0xafb20018, - 0xafb00010, 0x93620023, 0x00e0a821, 0x30420040, 0x1040003e, 0x30b3ffff, - 0x3c120800, 0x8e420020, 0x1040003a, 0x8f70004c, 0x0e00148e, 0x00000000, - 0x8f820018, 0xac510000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018, - 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, - 0x24040001, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800, - 0x245058c0, 0xaca30018, 0x9603000e, 0x8f850018, 0x3c024010, 0x00621825, - 0x0e0014cc, 0xaca3001c, 0x8e430020, 0x1060001b, 0x00000000, 0x0e00148e, - 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x3c02008d, 0xac820004, - 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, - 0x8f820018, 0xac550014, 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001, - 0xaca30018, 0x9602000e, 0x8f850018, 0x3c034019, 0x00431025, 0x0e0014cc, - 0xaca2001c, 0x93620023, 0x30420020, 0x14400003, 0x3c120800, 0x1280003f, - 0x3c029000, 0x8e420020, 0x8f70004c, 0x1040003b, 0x3c029000, 0x0e00148e, - 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x24020001, 0xac820004, - 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, - 0x8f820018, 0x24040001, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448, - 0x3c020800, 0x245058c0, 0xaca30018, 0x9603000e, 0x8f850018, 0x3c024010, - 0x00621825, 0x0e0014cc, 0xaca3001c, 0x8e430020, 0x1060001c, 0x3c029000, - 0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x00131400, - 0xac820004, 0x8f830018, 0xac750008, 0x8f820018, 0xac40000c, 0x8f830018, - 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c036000, 0x8c634448, - 0x24040001, 0xaca30018, 0x9602000e, 0x8f850018, 0x3c03401b, 0x00431025, - 0x0e0014cc, 0xaca2001c, 0x3c029000, 0x34420001, 0x02221025, 0xaf420020, - 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93630023, - 0x3c028000, 0x34420001, 0x02221025, 0x8fbf0028, 0x8fb50024, 0x8fb40020, - 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3063009f, 0xa3630023, - 0xaf420020, 0x03e00008, 0x27bd0030, 0x27bdffe0, 0xafb10014, 0x27510100, - 0x3c029000, 0x34420001, 0xafb00010, 0x00808021, 0x02021025, 0x3c038000, - 0xafbf0018, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, - 0xa7600008, 0x8f63005c, 0x3c028000, 0x34420001, 0xaf630148, 0x8f640050, - 0x02021025, 0x3c039000, 0xaf64017c, 0xaf420020, 0x8f450100, 0x34630001, - 0x3c048000, 0x00a31825, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, - 0x00000000, 0x9362007d, 0x3c038000, 0x34420001, 0xa362007d, 0x8f640074, - 0x34630001, 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, - 0x0e000470, 0x24050de5, 0x0a001093, 0x3c020800, 0x8f4201f8, 0x00431024, - 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, - 0x3c020800, 0x8c430020, 0x1060001e, 0x8fbf0018, 0x0e00148e, 0x00000000, - 0x8f830018, 0xac700000, 0x9622000c, 0x8f840018, 0x00021400, 0xac820004, - 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, - 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, - 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02401f, 0x00621825, - 0x0e0014cc, 0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, - 0x27bd0020, 0x3c020800, 0x24424c3c, 0xaf82000c, 0x03e00008, 0x00000000, - 0x27bdffe8, 0xafb00010, 0x27500100, 0xafbf0014, 0x8e02001c, 0x14400003, - 0x3c020800, 0x0000000d, 0x3c020800, 0x8c430020, 0x10600020, 0x00001021, - 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, - 0x8e02001c, 0xac820004, 0x8f830018, 0xac600008, 0x8f840018, 0x8e020018, - 0xac82000c, 0x8f850018, 0x96020012, 0xaca20010, 0x8f830018, 0x3c026000, - 0xac600014, 0x8f840018, 0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, - 0x8f840018, 0x3c024012, 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, - 0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, - 0x97430078, 0x9444002e, 0x00001021, 0x00641821, 0x3063fffe, 0x03e00008, - 0xa7630010, 0x27bdfff0, 0x00001021, 0x03e00008, 0x27bd0010, 0x8f420100, - 0x34420001, 0xaf4200a4, 0x03e00008, 0x00001021, 0x27bdffe0, 0xafbf0018, - 0xafb10014, 0xafb00010, 0x9362007e, 0x30d000ff, 0x16020031, 0x00808821, - 0x8f620178, 0x1602002e, 0x00000000, 0x9362007f, 0x1602002b, 0x00000000, - 0x9362007a, 0x16020004, 0x00000000, 0x0000000d, 0x00000000, 0x240009d2, - 0x0e0013e6, 0x00000000, 0x3c039000, 0x34630001, 0x3c048000, 0x02231825, - 0xa370007a, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000, - 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001, 0x02231825, - 0xaf430020, 0x04810006, 0x3c038000, 0x02202021, 0x0e000470, 0x240509dd, - 0x0a001138, 0x8fbf0018, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, - 0x3c031000, 0xaf5101c0, 0xa34201c4, 0xaf4301f8, 0x0a001138, 0x8fbf0018, - 0x0000000d, 0x00000000, 0x240009e2, 0x8fbf0018, 0x8fb10014, 0x8fb00010, - 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x30a500ff, 0x3c029000, 0x34420001, - 0x00803821, 0x00e21025, 0x3c038000, 0xafbf0010, 0xaf420020, 0x8f420020, - 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x00a21025, - 0xa362007d, 0x8f640074, 0x34630001, 0x00e31825, 0xaf430020, 0x04810006, - 0x3c038000, 0x00e02021, 0x0e000470, 0x00c02821, 0x0a001161, 0x8fbf0010, - 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4701c0, - 0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800, - 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x10600024, 0xafbf0014, - 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, - 0x8e020004, 0xac820004, 0x8f830018, 0x8e020018, 0xac620008, 0x8f840018, - 0x8e03001c, 0xac83000c, 0x9602000c, 0x9203000a, 0x8f840018, 0x00021400, - 0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, - 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018, - 0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, 0x8fbf0014, - 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8, - 0xafb00010, 0x27500100, 0x10600020, 0xafbf0014, 0x0e00148e, 0x00000000, - 0x8f820018, 0xac400000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, - 0x8f830018, 0xac60000c, 0x9602000c, 0x9603000e, 0x8f840018, 0x00021400, - 0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, - 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018, - 0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, 0x8fbf0014, - 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010, 0x27500100, - 0xafbf0014, 0x9602000c, 0x10400024, 0x00802821, 0x3c020800, 0x8c430020, - 0x1060003a, 0x8fbf0014, 0x0e00148e, 0x00000000, 0x8f840018, 0x8e030000, - 0xac830000, 0x9602000c, 0x8f840018, 0x00021400, 0xac820004, 0x8f830018, - 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, - 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, - 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02400b, 0x00621825, 0x0e0014cc, - 0xaca3001c, 0x0a0011ff, 0x8fbf0014, 0x93620005, 0x30420010, 0x14400015, - 0x3c029000, 0x34420001, 0x00a21025, 0xaf420020, 0x3c038000, 0x8f420020, - 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x93620005, 0x34630001, - 0x00a02021, 0x00a31825, 0x24055852, 0x34420010, 0xa3620005, 0x0e000766, - 0xaf430020, 0x0a0011ff, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, - 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, - 0x27500100, 0x10600022, 0xafbf0014, 0x0e00148e, 0x00000000, 0x8f840018, - 0x8e020004, 0xac820000, 0x9603000c, 0x9762002c, 0x8f840018, 0x00031c00, - 0x00431025, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, - 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, - 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, - 0x3c02400e, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x0e00122e, 0x8e040000, - 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c038000, 0x8f420278, - 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf440240, 0xa3420244, - 0x03e00008, 0xaf430278, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014, - 0x00808821, 0xafb20018, 0x00c09021, 0xafb00010, 0x30b0ffff, 0x1060001c, - 0xafbf001c, 0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, - 0x00101400, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, - 0x8f830018, 0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000, - 0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024019, - 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018, - 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x27450100, - 0xafbf0010, 0x94a3000c, 0x240200c1, 0x14620031, 0x00803021, 0x3c029000, - 0x34420001, 0x00c21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, - 0x1440fffd, 0x3c028000, 0x34420001, 0x3c049000, 0x34840001, 0x3c058000, - 0x24030012, 0x00c21025, 0x00c42025, 0xa363003f, 0xaf420020, 0xaf440020, - 0x8f420020, 0x00451024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, - 0x34420020, 0xa362007d, 0x8f640074, 0x34630001, 0x00c31825, 0xaf430020, - 0x04810006, 0x3c038000, 0x00c02021, 0x0e000470, 0x24050906, 0x0a0012a1, - 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, - 0xaf4601c0, 0xa34201c4, 0xaf4301f8, 0x0a0012a1, 0x8fbf0010, 0x00c02021, - 0x94a5000c, 0x24060001, 0x0e000fb1, 0x2407090e, 0x8fbf0010, 0x03e00008, - 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb00010, 0x00808021, - 0xafb20018, 0x00a09021, 0xafb10014, 0x30d100ff, 0x1060001c, 0xafbf001c, - 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, - 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, - 0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000, 0x8c434448, - 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024010, 0x00621825, - 0xac83001c, 0x0e0014cc, 0x02202021, 0x8fbf001c, 0x8fb20018, 0x8fb10014, - 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014, 0xafb00010, - 0x93620005, 0x30420001, 0x10400036, 0x00808021, 0x3c029000, 0x34420001, - 0x02021025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, - 0x00000000, 0x93620023, 0x34420004, 0xa3620023, 0x93630005, 0x3c048000, - 0x3c020800, 0x306300fe, 0xa3630005, 0x8c430020, 0x34840001, 0x02042025, - 0xaf440020, 0x10600020, 0x8fbf0014, 0x0e00148e, 0x00000000, 0x8f820018, - 0xac500000, 0x93630082, 0x9362003f, 0x8f840018, 0x00031a00, 0x00431025, - 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, - 0xac600010, 0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, 0x8c434448, - 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c02400a, 0x00621825, - 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf0014, 0x8fb00010, 0x03e00008, - 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014, 0x00808821, - 0xafb20018, 0x00a09021, 0xafb00010, 0x30d000ff, 0x1060002f, 0xafbf001c, - 0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f830018, 0xac700004, - 0x8f820018, 0xac520008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, - 0x9763006a, 0x00032880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, - 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, - 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, - 0x8f830018, 0x2402fffe, 0x00822824, 0x3c026000, 0xac650014, 0x8f840018, - 0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024011, - 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018, - 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014, - 0xafb00010, 0x8f440100, 0x27500100, 0x8f650050, 0x0e0010fc, 0x9206001b, - 0x3c020800, 0x8c430020, 0x1060001d, 0x8e100018, 0x0e00148e, 0x00000000, - 0x8f840018, 0x8f420100, 0xac820000, 0x8f830018, 0xac700004, 0x8f840018, - 0x8f620050, 0xac820008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, - 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018, 0x8c434448, 0x24040001, - 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02401c, 0x00621825, - 0x0e0014cc, 0xaca3001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, - 0x8f430238, 0x3c020800, 0x04610013, 0x8c44009c, 0x2406fffe, 0x3c050800, - 0x3c038000, 0x2484ffff, 0x14800009, 0x00000000, 0x97420078, 0x8ca3007c, - 0x24420001, 0x00461024, 0x24630001, 0xa7620010, 0x03e00008, 0xaca3007c, - 0x8f420238, 0x00431024, 0x1440fff3, 0x2484ffff, 0x8f420140, 0x3c031000, - 0xaf420200, 0x03e00008, 0xaf430238, 0x27bdffe8, 0x3c029000, 0xafbf0010, - 0x8f450140, 0x34420001, 0x3c038000, 0x00a21025, 0xaf420020, 0x8f420020, - 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x34420001, - 0xa362007d, 0x8f640074, 0x34630001, 0x00a31825, 0xaf430020, 0x04810006, - 0x3c038000, 0x00a02021, 0x0e000470, 0x24050ac7, 0x0a0013b9, 0x8fbf0010, - 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, - 0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x0000000d, - 0x03e00008, 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x24020001, - 0x03e00008, 0xa7620010, 0x9362003f, 0x304400ff, 0x3883000e, 0x2c630001, - 0x38820010, 0x2c420001, 0x00621825, 0x14600003, 0x24020012, 0x14820003, - 0x00000000, 0x03e00008, 0x00001021, 0x9363007e, 0x9362007a, 0x14620006, - 0x00000000, 0x9363007e, 0x24020001, 0x24630001, 0x03e00008, 0xa363007e, - 0x9362007e, 0x8f630178, 0x304200ff, 0x14430006, 0x00000000, 0x9363000b, - 0x24020001, 0x24630001, 0x03e00008, 0xa363000b, 0x03e00008, 0x00001021, - 0x9362000b, 0x10400023, 0x00001021, 0xa360000b, 0x9362003f, 0x304400ff, - 0x3883000e, 0x2c630001, 0x38820010, 0x2c420001, 0x00621825, 0x14600017, - 0x00001821, 0x24020012, 0x10820014, 0x00000000, 0x9363007e, 0x9362007a, - 0x14620007, 0x00000000, 0x9362007e, 0x24030001, 0x24420001, 0xa362007e, - 0x03e00008, 0x00601021, 0x9362007e, 0x8f630178, 0x304200ff, 0x14430005, - 0x00001821, 0x9362000b, 0x24030001, 0x24420001, 0xa362000b, 0x03e00008, - 0x00601021, 0x03e00008, 0x00000000, 0x24040001, 0xaf64000c, 0x8f6300dc, - 0x8f6200cc, 0x50620001, 0xa7640010, 0xa7640012, 0xa7640014, 0x03e00008, - 0xa7640016, 0x3c020800, 0x8c430020, 0x27bdffe8, 0x1060001b, 0xafbf0010, - 0x0e00148e, 0x00000000, 0x8f820018, 0xac400000, 0x8f830018, 0xac600004, - 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, - 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, 0x8c434448, 0x3c020800, - 0xac830018, 0x944358ce, 0x8f840018, 0x3c024020, 0x00621825, 0xac83001c, - 0x0e0014cc, 0x24040001, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800, - 0x8c430020, 0x27bdffe0, 0xafb00010, 0x00a08021, 0xafb10014, 0x00c08821, - 0xafb20018, 0x00e09021, 0x1060001e, 0xafbf001c, 0x0e00148e, 0x00000000, - 0x8f840018, 0x8f420100, 0xac820000, 0x8f830018, 0xac700004, 0x8f820018, - 0xac510008, 0x8f830018, 0xac72000c, 0x8f840018, 0x8fa20030, 0xac820010, - 0x8f830018, 0x8fa20034, 0xac620014, 0x8f840018, 0x3c026000, 0x8c434448, - 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c0240c9, 0x00621825, - 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018, 0x8fb10014, - 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c020800, 0x8c430020, 0x27bdffe8, - 0xafb00010, 0x27500100, 0x1060001d, 0xafbf0014, 0x0e00148e, 0x00000000, - 0x8f830018, 0x8e020004, 0xac620000, 0x8f840018, 0x8e020018, 0xac820004, - 0x8f850018, 0x8e020000, 0xaca20008, 0x8f830018, 0xac60000c, 0x8f820018, - 0xac400010, 0x8f830018, 0xac600014, 0x8f820018, 0xac400018, 0x96030008, - 0x3c020800, 0x944458ce, 0x8f850018, 0x00031c00, 0x00641825, 0x24040001, - 0x0e0014cc, 0xaca3001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, - 0x3c060800, 0x24c558c0, 0x3c02000a, 0x03421821, 0x94640006, 0x94a2000a, - 0x00441023, 0x00021400, 0x00021c03, 0x04610006, 0xa4a40006, 0x0000000d, - 0x00000000, 0x2400005a, 0x0a0014a3, 0x24020001, 0x8f820014, 0x0062102b, - 0x14400002, 0x00001021, 0x24020001, 0x304200ff, 0x1040001c, 0x274a0400, - 0x3c07000a, 0x3c020800, 0x244558c0, 0x94a9000a, 0x8f880014, 0x03471021, - 0x94430006, 0x00402021, 0xa4a30006, 0x94820006, 0xa4a20006, 0x01221023, - 0x00021400, 0x00021403, 0x04410006, 0x0048102b, 0x0000000d, 0x00000000, - 0x2400005a, 0x0a0014be, 0x24020001, 0x14400002, 0x00001021, 0x24020001, - 0x304200ff, 0x1440ffec, 0x03471021, 0x24c458c0, 0x8c820010, 0xaf420038, - 0x8c830014, 0x3c020005, 0xaf43003c, 0xaf420030, 0xaf800010, 0xaf8a0018, - 0x03e00008, 0x00000000, 0x27bdffe0, 0x8f820010, 0x8f850018, 0x3c070800, - 0x24e858c0, 0xafbf001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x9503000a, - 0x8d060014, 0x00009021, 0x309000ff, 0x00e08821, 0x24420001, 0x24a50020, - 0x24630001, 0xaf820010, 0xaf850018, 0xa503000a, 0x24c30020, 0x3c028000, - 0x04c10007, 0xad030014, 0x00621024, 0x14400005, 0x262258c0, 0x8d020010, - 0x24420001, 0xad020010, 0x262258c0, 0x9444000a, 0x94450018, 0x0010102b, - 0x00a41826, 0x2c630001, 0x00621825, 0x1060001c, 0x3c030006, 0x8f820010, - 0x24120001, 0x00021140, 0x00431025, 0xaf420030, 0x00000000, 0x00000000, - 0x00000000, 0x27450400, 0x8f420000, 0x30420010, 0x1040fffd, 0x262258c0, - 0x9444000a, 0x94430018, 0xaf800010, 0xaf850018, 0x14830012, 0x262758c0, - 0x0e00155a, 0x00000000, 0x1600000e, 0x262758c0, 0x0e00148e, 0x00000000, - 0x0a001517, 0x262758c0, 0x00041c00, 0x00031c03, 0x00051400, 0x00021403, - 0x00621823, 0x18600002, 0x3c026000, 0xac400808, 0x262758c0, 0x94e2000e, - 0x94e3000c, 0x24420001, 0xa4e2000e, 0x3042ffff, 0x50430001, 0xa4e0000e, - 0x12000005, 0x3c02000a, 0x94e2000a, 0xa74200a2, 0x0a001554, 0x02401021, - 0x03421821, 0x94640006, 0x94e2000a, 0x00441023, 0x00021400, 0x00021c03, - 0x04610006, 0xa4e40006, 0x0000000d, 0x00000000, 0x2400005a, 0x0a001536, - 0x24020001, 0x8f820014, 0x0062102b, 0x14400002, 0x00001021, 0x24020001, - 0x304200ff, 0x1040001b, 0x3c020800, 0x3c06000a, 0x244558c0, 0x94a8000a, - 0x8f870014, 0x03461021, 0x94430006, 0x00402021, 0xa4a30006, 0x94820006, - 0xa4a20006, 0x01021023, 0x00021400, 0x00021403, 0x04410006, 0x0047102b, - 0x0000000d, 0x00000000, 0x2400005a, 0x0a001550, 0x24020001, 0x14400002, - 0x00001021, 0x24020001, 0x304200ff, 0x1440ffec, 0x03461021, 0x02401021, - 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, - 0x3c020800, 0x244558c0, 0x94a3001a, 0x8ca40024, 0x00403021, 0x000318c0, - 0x00832021, 0xaf44003c, 0x8ca20020, 0xaf420038, 0x3c020050, 0x34420008, - 0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x8f420000, 0x30420020, - 0x1040fffd, 0x00000000, 0x8f430400, 0x24c658c0, 0xacc30010, 0x8f420404, - 0x3c030020, 0xacc20014, 0xaf430030, 0x94c40018, 0x94c3001c, 0x94c2001a, - 0x94c5001e, 0x00832021, 0x24420001, 0xa4c2001a, 0x3042ffff, 0x14450002, - 0xa4c40018, 0xa4c0001a, 0x03e00008, 0x00000000, 0x8f820010, 0x3c030006, - 0x00021140, 0x00431025, 0xaf420030, 0x00000000, 0x00000000, 0x00000000, - 0x27430400, 0x8f420000, 0x30420010, 0x1040fffd, 0x00000000, 0xaf800010, - 0xaf830018, 0x03e00008, 0x00000000, 0x27bdffe8, 0xafb00010, 0x3c100800, - 0x261058c0, 0x3c05000a, 0x02002021, 0x03452821, 0xafbf0014, 0x0e0015b0, - 0x2406000a, 0x96020002, 0x9603001e, 0x3042000f, 0x24420003, 0x00431804, - 0x24027fff, 0x0043102b, 0xaf830014, 0x10400004, 0x00000000, 0x0000000d, - 0x00000000, 0x24000043, 0x0e00155a, 0x00000000, 0x8fbf0014, 0x8fb00010, - 0x03e00008, 0x27bd0018, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, - 0x24a50004, 0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, - 0x0a0015c1, 0x00a01021, 0xac860000, 0x00000000, 0x00000000, 0x24840004, - 0x00a01021, 0x1440fffa, 0x24a5ffff, 0x03e00008, 0x00000000, 0x3c036000, - 0x8c642b7c, 0x3c036010, 0x8c6553fc, 0x00041582, 0x00042302, 0x308403ff, - 0x00052d82, 0x00441026, 0x0002102b, 0x0005282b, 0x00451025, 0x1440000d, - 0x3c020050, 0x34420004, 0xaf400038, 0xaf40003c, 0xaf420030, 0x00000000, - 0x00000000, 0x8f420000, 0x30420020, 0x1040fffd, 0x3c020020, 0xaf420030, - 0x0000000d, 0x03e00008, 0x00000000, 0x3c020050, 0x34420004, 0xaf440038, - 0xaf45003c, 0xaf420030, 0x00000000, 0x00000000, 0x8f420000, 0x30420020, - 0x1040fffd, 0x3c020020, 0xaf420030, 0x03e00008, 0x00000000, 0x00000000}; +static u8 bnx2_COM_b06FwText[] = { + 0x1f, 0x8b, 0x08, 0x08, 0x09, 0x83, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5b, 0x7d, 0x6c, + 0x5b, 0xd7, 0x75, 0x3f, 0xef, 0xf1, 0x51, 0x7a, 0x96, 0x68, 0xf9, 0x99, + 0x7e, 0x96, 0x59, 0x4f, 0xb1, 0x49, 0xf1, 0xc9, 0xd2, 0x62, 0x2d, 0x63, + 0x34, 0x35, 0xd1, 0x3a, 0x26, 0x66, 0x48, 0xda, 0x71, 0x36, 0x67, 0xa0, + 0x1d, 0x05, 0x51, 0x51, 0xaf, 0xd0, 0x48, 0xd9, 0xcd, 0xb2, 0x0c, 0x73, + 0x96, 0xb4, 0x70, 0xbc, 0xb4, 0xa1, 0x25, 0x79, 0xf5, 0x06, 0x45, 0xcf, + 0xb3, 0x34, 0x39, 0xc0, 0x82, 0x41, 0x10, 0x9d, 0x3a, 0x7f, 0x30, 0xa5, + 0xed, 0x7c, 0x19, 0xe8, 0x12, 0x29, 0xb2, 0x93, 0xb5, 0x43, 0xd0, 0xa6, + 0x68, 0xff, 0xe8, 0x8a, 0x6e, 0x30, 0x52, 0x0c, 0xf3, 0x3a, 0xa0, 0x30, + 0xfa, 0xc7, 0xe6, 0x2d, 0x1f, 0xdc, 0xef, 0xdc, 0x77, 0x1f, 0xf9, 0x48, + 0x51, 0x96, 0x1c, 0x34, 0x5d, 0xb7, 0x99, 0x80, 0xf0, 0xde, 0xbd, 0xf7, + 0xbc, 0x7b, 0xcf, 0x3d, 0xdf, 0xe7, 0xdc, 0xab, 0x5f, 0x53, 0xa9, 0x85, + 0xe4, 0x6f, 0x2d, 0xfe, 0xc2, 0x7f, 0xf4, 0xc7, 0xb9, 0xdb, 0x3e, 0x7d, + 0x5b, 0x1f, 0x5e, 0x07, 0x54, 0xdd, 0xaf, 0x72, 0xbf, 0x0f, 0x7f, 0x26, + 0xfe, 0xfa, 0xe4, 0x7b, 0xa3, 0x9f, 0x81, 0xbf, 0x2b, 0x18, 0x1c, 0xfe, + 0x09, 0x91, 0xb2, 0x0c, 0x8c, 0xf7, 0x57, 0x2e, 0x5f, 0x7f, 0x9c, 0x17, + 0x0e, 0xaf, 0x62, 0x9e, 0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf, + 0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf, 0xff, 0x3f, 0x3f, 0x9f, 0x13, 0x72, + 0x88, 0x98, 0x85, 0xff, 0x48, 0x57, 0xe3, 0x89, 0xa1, 0xa4, 0x45, 0xba, + 0x2f, 0x7e, 0x65, 0x28, 0x67, 0x11, 0x25, 0x8a, 0xdb, 0xc3, 0x29, 0xfa, + 0xb0, 0x9c, 0x37, 0x35, 0xe2, 0xfe, 0x5b, 0xe2, 0x1f, 0x3c, 0xfd, 0xfa, + 0x9d, 0x91, 0xab, 0xb3, 0x3e, 0xd2, 0x8d, 0xf8, 0xcb, 0xba, 0xb1, 0x8d, + 0xf4, 0x0e, 0x7c, 0xf3, 0x5c, 0xf7, 0x7f, 0xa8, 0xd4, 0xe6, 0xce, 0x75, + 0xa5, 0xfc, 0x7a, 0x37, 0xe5, 0x37, 0xc7, 0x75, 0x52, 0xe3, 0x5d, 0x3f, + 0x48, 0xfa, 0x8c, 0x61, 0x5f, 0xdc, 0xa0, 0xf9, 0x12, 0x65, 0x0e, 0x4c, + 0xf0, 0x1a, 0xb1, 0x75, 0xf7, 0x62, 0x2e, 0x2d, 0x3e, 0x3c, 0xf4, 0x67, + 0xd6, 0xd3, 0x65, 0xd5, 0xb2, 0x7a, 0xe6, 0x28, 0x30, 0xf0, 0x7c, 0x3f, + 0xc6, 0x8b, 0x91, 0x1e, 0xa2, 0x3b, 0x49, 0xb5, 0xf2, 0x01, 0x9f, 0xa5, + 0x53, 0xb2, 0x64, 0x51, 0xaa, 0x44, 0xf4, 0x77, 0x45, 0x85, 0x9e, 0xb7, + 0xda, 0x69, 0xae, 0xf7, 0x83, 0x72, 0x02, 0xb8, 0xbc, 0x6d, 0x0d, 0x0f, + 0x8d, 0x5b, 0x3c, 0x57, 0x7c, 0x9d, 0x83, 0x6f, 0x6f, 0x5b, 0xce, 0xd2, + 0x68, 0xb4, 0xc8, 0x7d, 0xbd, 0x2d, 0xdc, 0xe7, 0x8f, 0x3f, 0x1c, 0x7c, + 0xde, 0x0a, 0xc8, 0xbe, 0x1f, 0xa5, 0x92, 0x98, 0x6f, 0xac, 0xc8, 0xb0, + 0xcf, 0xde, 0x91, 0xb3, 0x4c, 0xd9, 0x6f, 0xc5, 0x93, 0x56, 0x08, 0xfd, + 0x1d, 0x72, 0x2c, 0xbd, 0x2e, 0x67, 0x59, 0x72, 0xac, 0x88, 0x6f, 0x7a, + 0x65, 0xff, 0x3b, 0xa9, 0x9c, 0x15, 0x93, 0xfd, 0x57, 0x93, 0x49, 0xab, + 0x5f, 0xf6, 0x1f, 0xbe, 0x2b, 0x67, 0xc5, 0x65, 0xff, 0xf7, 0x81, 0x8b, + 0x41, 0xc7, 0x8a, 0x61, 0xfc, 0x25, 0x30, 0xfe, 0x9a, 0x41, 0x6d, 0x19, + 0x8c, 0x61, 0xef, 0xb6, 0x4e, 0x97, 0x7d, 0x21, 0x7a, 0xbd, 0xfb, 0x32, + 0x68, 0x63, 0xd0, 0xd9, 0x12, 0x29, 0x99, 0xee, 0x10, 0x68, 0x62, 0xd2, + 0xb9, 0x52, 0x2b, 0xf9, 0x4e, 0xfa, 0xb0, 0xe7, 0xcf, 0x51, 0xd6, 0xd4, + 0x69, 0xfd, 0x8c, 0x42, 0x9d, 0x7d, 0x6b, 0x28, 0x61, 0xe4, 0x29, 0xd5, + 0x8d, 0x28, 0x6e, 0xd2, 0x24, 0x6d, 0x66, 0x71, 0xbd, 0x8a, 0x1e, 0x95, + 0x22, 0xa1, 0x2c, 0x28, 0x3c, 0x72, 0xfa, 0x5d, 0x8e, 0x39, 0xb1, 0x26, + 0xff, 0x85, 0x29, 0x35, 0x71, 0x2b, 0x0d, 0x1b, 0x8c, 0x0f, 0x80, 0x05, + 0x1f, 0x74, 0x25, 0x79, 0x2a, 0x44, 0xc7, 0xec, 0x80, 0x92, 0x3a, 0x75, + 0x37, 0x25, 0x63, 0x64, 0xaa, 0xd4, 0x25, 0xbe, 0x2d, 0x14, 0x43, 0x34, + 0x6e, 0x93, 0x92, 0xb4, 0x99, 0x5e, 0xed, 0x18, 0x6f, 0x13, 0xb0, 0xe8, + 0xeb, 0xf0, 0x51, 0x97, 0x91, 0x22, 0x9d, 0x71, 0x46, 0x7f, 0x50, 0x49, + 0x8b, 0x39, 0x44, 0x7f, 0x78, 0x8c, 0x02, 0x74, 0xba, 0x68, 0x4a, 0xd8, + 0x72, 0x39, 0x19, 0x33, 0x00, 0x07, 0xda, 0xd9, 0x26, 0x0d, 0xe3, 0x39, + 0x6a, 0xf3, 0xfa, 0x21, 0xc8, 0xcc, 0xb7, 0x87, 0xb2, 0xd3, 0x62, 0xbe, + 0xb0, 0x2f, 0xce, 0xf3, 0x75, 0x00, 0xee, 0x1d, 0xe0, 0xa5, 0x90, 0x26, + 0x78, 0x95, 0xa0, 0xec, 0x84, 0x02, 0x79, 0xc2, 0x53, 0xd0, 0x2d, 0x0d, + 0xfc, 0x35, 0xb2, 0xfa, 0x14, 0xca, 0x59, 0x9b, 0x28, 0x6f, 0xa0, 0x5d, + 0xbc, 0xa0, 0x26, 0xed, 0x66, 0x4a, 0x69, 0x61, 0xec, 0x5f, 0xc8, 0x0a, + 0x8d, 0xe1, 0x1b, 0xd5, 0x62, 0x98, 0x9f, 0x61, 0xef, 0xc3, 0x82, 0xfe, + 0x4d, 0xf1, 0xfd, 0x74, 0x69, 0x22, 0xaf, 0x26, 0x4b, 0xed, 0xe4, 0x9b, + 0x89, 0x40, 0x9a, 0xc7, 0xd5, 0xd4, 0x19, 0x8d, 0xfc, 0x93, 0x0a, 0x41, + 0x3e, 0x0c, 0x5f, 0xfc, 0xb8, 0xba, 0xb3, 0x74, 0x41, 0x4d, 0x95, 0xf8, + 0x1b, 0xc0, 0x16, 0x55, 0xd0, 0x96, 0xdf, 0xb7, 0x83, 0x96, 0x34, 0xac, + 0xc6, 0x75, 0x3d, 0x51, 0x64, 0x99, 0xe5, 0x6f, 0xc1, 0x0f, 0xec, 0xe5, + 0x9c, 0x0d, 0xfe, 0x08, 0x7e, 0x85, 0xc1, 0xaf, 0x6f, 0x82, 0x5f, 0xfd, + 0xe0, 0x53, 0x8c, 0xde, 0x28, 0xf5, 0xd2, 0x6b, 0xa5, 0x1e, 0x7a, 0x15, + 0x32, 0xf9, 0x4a, 0x29, 0x4c, 0x2f, 0x97, 0x3a, 0xe8, 0xa5, 0x52, 0x88, + 0xce, 0x0b, 0x1e, 0xa6, 0x21, 0xff, 0x82, 0xaf, 0xfa, 0x26, 0xf0, 0xa4, + 0x1d, 0x3c, 0x59, 0x0f, 0x79, 0xd9, 0x08, 0xf9, 0x9b, 0xee, 0xd6, 0x69, + 0xaa, 0x9b, 0x12, 0x41, 0xf4, 0x6f, 0x89, 0x6b, 0x82, 0x4e, 0x1a, 0xc6, + 0xc7, 0x26, 0xfc, 0x94, 0x32, 0x4e, 0xd3, 0x7b, 0x93, 0x1a, 0x8d, 0x95, + 0xa6, 0x36, 0x3a, 0x7c, 0xe3, 0xf6, 0x2c, 0x5d, 0x44, 0x5f, 0xca, 0x98, + 0xa5, 0x4b, 0xdb, 0x54, 0x1a, 0x9d, 0xfe, 0x1b, 0x4a, 0x9e, 0x39, 0x4d, + 0x3f, 0xfe, 0x3a, 0x51, 0x06, 0x34, 0x51, 0xfb, 0x7e, 0x5a, 0x4e, 0x18, + 0xa0, 0x45, 0x5f, 0xaf, 0x90, 0x08, 0xb5, 0x8f, 0x79, 0x19, 0x86, 0xae, + 0x68, 0x4a, 0xca, 0x7e, 0x01, 0xfa, 0xd2, 0xaa, 0x24, 0xa7, 0x88, 0x72, + 0x53, 0x65, 0xca, 0xc5, 0xfc, 0xf4, 0x98, 0x51, 0xa6, 0x74, 0xac, 0x89, + 0xbe, 0x68, 0xb4, 0xd3, 0x68, 0xef, 0x6f, 0xf8, 0xdc, 0x5c, 0x65, 0xba, + 0xd4, 0x8f, 0x77, 0xee, 0x23, 0x9a, 0x12, 0xef, 0x4e, 0x7f, 0xbe, 0xe4, + 0xa7, 0x84, 0x99, 0x0f, 0x69, 0xf4, 0x8e, 0xcf, 0xc1, 0x29, 0xe1, 0x8e, + 0x81, 0x57, 0xc3, 0xb0, 0x0f, 0x8e, 0x0c, 0x66, 0x27, 0xd6, 0x5c, 0x4b, + 0x88, 0x6e, 0xc0, 0x0b, 0xd9, 0xd3, 0x18, 0x8f, 0x61, 0x25, 0x6e, 0x52, + 0xa7, 0xd0, 0x8d, 0x7e, 0xc0, 0x0c, 0x28, 0xfb, 0x4a, 0xcc, 0x6b, 0xbc, + 0x17, 0x19, 0xd7, 0xcd, 0x80, 0xd5, 0xf0, 0x4c, 0x48, 0x9c, 0xbd, 0x78, + 0xf2, 0x5c, 0x8c, 0x27, 0x3f, 0x7f, 0xcf, 0x83, 0xe7, 0xe7, 0x2b, 0xef, + 0x53, 0x9e, 0xf7, 0x7c, 0xe9, 0x4f, 0x03, 0x0e, 0x7e, 0x4c, 0xcf, 0x01, + 0x1a, 0x9d, 0x38, 0x2c, 0xd7, 0xc2, 0x7b, 0x91, 0xd7, 0x38, 0x0d, 0x3a, + 0x09, 0xc8, 0x15, 0xd6, 0x3a, 0xec, 0x59, 0xeb, 0x49, 0xcf, 0x5a, 0x4f, + 0x7a, 0xd6, 0xca, 0x83, 0xb6, 0xb4, 0x4e, 0xb5, 0xfc, 0xd0, 0x51, 0xee, + 0x39, 0x8e, 0x39, 0x9f, 0x03, 0x5f, 0xbe, 0x0a, 0x98, 0x38, 0x2d, 0xda, + 0xa0, 0xc7, 0x94, 0x46, 0x7b, 0x4d, 0x7e, 0x7f, 0xb1, 0xd5, 0xc1, 0x8b, + 0xdf, 0x2f, 0x48, 0x9c, 0x5a, 0x1d, 0xb8, 0xd2, 0x15, 0xa1, 0xff, 0xf3, + 0x25, 0xd6, 0x4f, 0x8a, 0xf9, 0x2c, 0x3a, 0x94, 0x8e, 0xb5, 0xd3, 0x98, + 0xa1, 0xc4, 0x46, 0x7b, 0x9a, 0x99, 0x8e, 0x09, 0xd5, 0x6a, 0x85, 0x0e, + 0x50, 0x58, 0x65, 0xdb, 0x25, 0xf0, 0x7b, 0x49, 0xe2, 0x61, 0x70, 0x3b, + 0xa3, 0x5a, 0xc1, 0xba, 0x7e, 0x96, 0xdf, 0x57, 0xf0, 0xce, 0x32, 0x9c, + 0xd4, 0x9c, 0xb5, 0x5f, 0x45, 0x9b, 0xed, 0xce, 0x66, 0xd9, 0x76, 0xc7, + 0xff, 0xa0, 0xa9, 0xb6, 0xfd, 0x05, 0xb3, 0xb6, 0xed, 0xea, 0x82, 0xd7, + 0x66, 0xf1, 0xde, 0xc2, 0xe4, 0xb3, 0x58, 0x8e, 0xfc, 0xc0, 0x35, 0x06, + 0x3d, 0x6c, 0x96, 0x38, 0x7c, 0x4b, 0xe2, 0x00, 0x5c, 0x01, 0x37, 0x5a, + 0xe2, 0x6f, 0x04, 0x4b, 0xea, 0xda, 0x4c, 0x43, 0xf7, 0x7d, 0xad, 0x18, + 0xbf, 0xec, 0xe3, 0x75, 0xdc, 0x27, 0x29, 0x69, 0xe8, 0xc9, 0xd8, 0xb4, + 0x46, 0xd9, 0xd8, 0x26, 0x21, 0xd7, 0xd9, 0x58, 0xd5, 0x06, 0x8c, 0x4e, + 0xd4, 0xdb, 0x00, 0xfe, 0x8e, 0x6d, 0x80, 0xa3, 0xfb, 0x63, 0xd3, 0x6c, + 0x0b, 0x1c, 0xdd, 0x3f, 0x36, 0xc1, 0x36, 0x41, 0xcc, 0x09, 0xfd, 0x67, + 0x3b, 0xe0, 0xda, 0x00, 0xfe, 0x86, 0x6d, 0x80, 0x0f, 0xf2, 0xcd, 0xf3, + 0xb9, 0x6b, 0x8f, 0xd7, 0xcd, 0x3b, 0xce, 0xb6, 0x45, 0xd9, 0xd9, 0xcd, + 0x30, 0xc7, 0xb1, 0x76, 0x80, 0x0a, 0xd3, 0xcc, 0xc3, 0x48, 0xe8, 0x08, + 0x1d, 0x17, 0x36, 0xef, 0xf4, 0x04, 0x25, 0x0e, 0x9e, 0x18, 0xa0, 0x34, + 0x6c, 0xc0, 0xdc, 0xc4, 0xb5, 0x32, 0xf8, 0x78, 0x47, 0x13, 0x59, 0xb0, + 0x75, 0xf0, 0x93, 0xfd, 0x7e, 0xf2, 0xc5, 0xe3, 0x90, 0xb7, 0x98, 0xf0, + 0x5d, 0xd5, 0x9f, 0xa6, 0xed, 0xaa, 0x69, 0x37, 0xc1, 0x3f, 0x62, 0xde, + 0xfe, 0x98, 0x90, 0x4d, 0xef, 0x2f, 0x09, 0x1b, 0x94, 0x8c, 0x7d, 0x08, + 0xf9, 0x75, 0x69, 0xe4, 0xea, 0x1f, 0xdb, 0xfa, 0x2b, 0x1e, 0x1f, 0xb2, + 0x05, 0x76, 0xdf, 0x84, 0x3c, 0xb9, 0x76, 0x9f, 0xed, 0x71, 0x88, 0x6d, + 0x26, 0xf4, 0x8d, 0x6d, 0x70, 0x80, 0xd4, 0x19, 0x4d, 0xda, 0x69, 0x5d, + 0xda, 0xe9, 0x00, 0x6c, 0x34, 0xb7, 0x0d, 0xd9, 0x36, 0x45, 0x1b, 0xf6, + 0x1a, 0xf6, 0x70, 0x77, 0x3a, 0x35, 0xc1, 0xfe, 0x10, 0xbe, 0x7b, 0x86, + 0x75, 0xf8, 0xdb, 0x43, 0x23, 0xd3, 0xc2, 0x07, 0xb0, 0xff, 0x80, 0x65, + 0x66, 0x1b, 0xce, 0xb6, 0x1c, 0xfb, 0x2e, 0x62, 0xdd, 0x8a, 0xad, 0x64, + 0x39, 0xf1, 0xe2, 0xc5, 0x38, 0xad, 0x21, 0xf5, 0xa4, 0x43, 0x6b, 0x35, + 0xfe, 0xa8, 0x46, 0x2d, 0x4c, 0x63, 0xc6, 0x7f, 0x2b, 0x70, 0xe6, 0x7d, + 0xfd, 0x4f, 0xe0, 0xcc, 0xeb, 0xd6, 0xe3, 0x4d, 0x7a, 0x6b, 0xfc, 0xac, + 0xfe, 0xf0, 0x33, 0xa4, 0x37, 0xc7, 0xcf, 0xd2, 0xbf, 0x58, 0x74, 0x9f, + 0x0e, 0x3f, 0xdb, 0xad, 0xc0, 0xcf, 0x16, 0xa1, 0xef, 0x53, 0x3a, 0x1d, + 0x3c, 0x15, 0xc9, 0xfc, 0x2b, 0x45, 0x61, 0x3f, 0x76, 0xd0, 0xc8, 0x94, + 0x42, 0x7a, 0x17, 0xb5, 0xc3, 0x7f, 0xf4, 0x37, 0x61, 0xfe, 0x5d, 0x44, + 0x9b, 0x1d, 0xbf, 0xd9, 0x15, 0x1e, 0x05, 0xff, 0xd3, 0x2f, 0x7e, 0x05, + 0xdf, 0x3c, 0x4d, 0x07, 0xa7, 0x0e, 0x2b, 0x39, 0xfb, 0x08, 0xe0, 0x97, + 0x83, 0xd5, 0x01, 0x9b, 0x07, 0xec, 0x97, 0x31, 0xef, 0xd3, 0xa4, 0xdf, + 0x1e, 0x19, 0x48, 0x28, 0xc0, 0xe3, 0x45, 0x01, 0x2f, 0x7d, 0x71, 0x97, + 0xb1, 0x53, 0xf0, 0x3f, 0x40, 0xef, 0x15, 0x2f, 0x80, 0xbe, 0xbd, 0xf0, + 0x39, 0x91, 0x67, 0x61, 0x93, 0xe1, 0x8f, 0x22, 0x57, 0x31, 0x2d, 0x7c, + 0x11, 0x29, 0x0f, 0x76, 0xa7, 0x41, 0xef, 0x38, 0xfc, 0xd3, 0x00, 0xfc, + 0x53, 0x0c, 0xbe, 0xa9, 0x07, 0x7e, 0xc9, 0x82, 0x5f, 0x0a, 0x83, 0x1f, + 0x06, 0xcd, 0xc2, 0x47, 0xcd, 0x42, 0xfe, 0xe7, 0x66, 0x48, 0x19, 0x04, + 0xad, 0xcf, 0xc1, 0x3f, 0x26, 0x63, 0x77, 0x42, 0xcf, 0x22, 0x17, 0x66, + 0xd5, 0x41, 0xca, 0xc1, 0x9f, 0x77, 0x6e, 0x8b, 0x62, 0xbd, 0x26, 0x4a, + 0x84, 0x5c, 0x1d, 0xe5, 0xdf, 0x7e, 0x85, 0xac, 0x7f, 0x06, 0xef, 0x22, + 0x61, 0xa2, 0x3d, 0x94, 0xb5, 0xa3, 0x46, 0xa7, 0xda, 0x03, 0x18, 0x6e, + 0x87, 0x95, 0x03, 0x53, 0x11, 0x05, 0xfb, 0x03, 0xcd, 0x27, 0x60, 0xeb, + 0xcb, 0x34, 0x1e, 0x63, 0x3d, 0x29, 0xd3, 0xf3, 0xb1, 0xc8, 0x40, 0x9e, + 0x5a, 0xe9, 0x98, 0x39, 0x21, 0x7c, 0xbc, 0x16, 0x3f, 0x21, 0x74, 0x2c, + 0x67, 0xe1, 0x59, 0xec, 0x54, 0xb2, 0x53, 0xbc, 0x7e, 0x14, 0x5a, 0xee, + 0xc7, 0x93, 0xe7, 0x07, 0xdd, 0xfa, 0x49, 0x39, 0xd8, 0x9d, 0x87, 0x77, + 0x88, 0x18, 0x8b, 0x58, 0x39, 0x35, 0x11, 0x0d, 0x45, 0x55, 0x8d, 0x86, + 0x35, 0x85, 0x46, 0x61, 0x6f, 0xd2, 0xb1, 0xff, 0x2c, 0x1f, 0x33, 0x79, + 0xbc, 0x99, 0xbe, 0x2a, 0xfc, 0x0d, 0xd6, 0x2e, 0x4c, 0x63, 0x5d, 0x3f, + 0xf8, 0xcb, 0xeb, 0xf2, 0x3c, 0x68, 0xc3, 0xf6, 0x6b, 0x56, 0xe4, 0xd9, + 0x3c, 0xed, 0x00, 0x6d, 0xd9, 0x66, 0xc1, 0x3e, 0x0c, 0x60, 0xed, 0x5e, + 0xd8, 0x4f, 0x3c, 0x93, 0xbd, 0x1c, 0x07, 0x05, 0x68, 0xd8, 0x64, 0x79, + 0xd4, 0xe5, 0x98, 0xe9, 0x19, 0xf3, 0xcb, 0xb1, 0x20, 0xfe, 0xe0, 0x7f, + 0x4d, 0x96, 0x19, 0x6e, 0x73, 0x4c, 0xc6, 0x34, 0x09, 0xd3, 0xdc, 0x64, + 0x02, 0x34, 0x8b, 0x9c, 0x4d, 0x10, 0xd3, 0x0c, 0x46, 0x7b, 0x7f, 0x82, + 0xbe, 0x64, 0xaf, 0xf7, 0x3b, 0xb6, 0xb0, 0x55, 0x49, 0xc1, 0x17, 0xa8, + 0x56, 0x0b, 0x7c, 0x45, 0x98, 0x5e, 0x15, 0xb0, 0x64, 0xa8, 0xf1, 0x68, + 0xe8, 0x4b, 0x74, 0xab, 0xb0, 0x11, 0x09, 0xc3, 0x4b, 0xe3, 0xff, 0x52, + 0xc9, 0x72, 0xbf, 0x69, 0xa5, 0xec, 0x20, 0xf3, 0x89, 0xd7, 0x33, 0x68, + 0xae, 0xe4, 0xbc, 0xfb, 0x10, 0xa3, 0x16, 0x60, 0x6b, 0xce, 0x4f, 0xaa, + 0xf4, 0xf8, 0x1d, 0xf0, 0x65, 0xb1, 0x6d, 0x58, 0xcb, 0xc4, 0x78, 0x1e, + 0x6d, 0x15, 0x6d, 0xe8, 0x99, 0x11, 0x02, 0x8f, 0xb9, 0x9f, 0xe1, 0x4c, + 0xfc, 0xbd, 0xcf, 0xb1, 0x75, 0x3e, 0xab, 0xde, 0x4a, 0x14, 0x64, 0x7a, + 0xc5, 0x40, 0x2b, 0xcb, 0x50, 0xd5, 0x6d, 0xc2, 0x5f, 0x3b, 0xb6, 0xc4, + 0x82, 0x2e, 0xc2, 0xe6, 0xf6, 0x79, 0x75, 0x91, 0xe3, 0x09, 0x57, 0x17, + 0x23, 0xa1, 0x84, 0x0a, 0x5b, 0xdc, 0xa7, 0xd1, 0x09, 0xd1, 0x56, 0x28, + 0x31, 0x18, 0x09, 0x2d, 0xa8, 0x1c, 0x4b, 0x33, 0x6c, 0x18, 0xf1, 0x4a, + 0x40, 0xc2, 0x22, 0x9e, 0xb3, 0xdd, 0x98, 0x30, 0x84, 0x7e, 0x53, 0xf4, + 0x1f, 0xab, 0xe8, 0xa8, 0x13, 0xff, 0xa9, 0x88, 0x11, 0x0b, 0x88, 0x11, + 0x53, 0x42, 0x47, 0x8d, 0x04, 0x72, 0x04, 0xd0, 0xdc, 0xd1, 0xcf, 0x42, + 0x91, 0x71, 0xc9, 0xb1, 0x5c, 0x0e, 0x00, 0x99, 0x13, 0x8e, 0x7d, 0xa4, + 0x3c, 0xc7, 0x91, 0xa3, 0xea, 0x53, 0x34, 0x5c, 0x60, 0x3f, 0x8e, 0x3f, + 0x9b, 0x6d, 0x2d, 0xec, 0xa3, 0xf0, 0xc5, 0x51, 0xf0, 0x39, 0x0f, 0x1a, + 0xac, 0x97, 0x74, 0xdd, 0x4f, 0x07, 0xec, 0x3d, 0xa0, 0x79, 0x9c, 0x46, + 0x4e, 0x8d, 0xb0, 0xcc, 0xf6, 0x14, 0x28, 0xd2, 0x73, 0x8c, 0xb6, 0x1b, + 0x73, 0x2c, 0xdf, 0x83, 0xe5, 0x1d, 0xe0, 0x85, 0xd0, 0x51, 0xc8, 0x20, + 0x65, 0x0b, 0x23, 0xf4, 0x58, 0x89, 0xfb, 0xf2, 0xa0, 0x1d, 0xe2, 0xda, + 0xfe, 0xfd, 0x52, 0xce, 0x31, 0x9f, 0xe6, 0xce, 0x37, 0x22, 0xe7, 0x63, + 0x38, 0x86, 0xe1, 0x6f, 0xaa, 0xf3, 0xee, 0x14, 0x3c, 0x8d, 0x18, 0x5d, + 0x6a, 0x79, 0x87, 0x1f, 0xe3, 0xcf, 0xf7, 0xf3, 0x3b, 0xe6, 0x81, 0xef, + 0x6f, 0xb6, 0xf6, 0x00, 0x76, 0x10, 0x73, 0xfa, 0xa9, 0xb3, 0xdd, 0xc5, + 0x37, 0x81, 0xb5, 0xd9, 0xcf, 0x31, 0x9f, 0x1f, 0xa1, 0xec, 0xa9, 0x7c, + 0x8f, 0x0a, 0x19, 0x9b, 0xcd, 0x28, 0xe4, 0xb7, 0x1e, 0xa6, 0xdc, 0xa9, + 0xa3, 0x6c, 0x37, 0x40, 0xab, 0x3d, 0xb4, 0x6b, 0x22, 0xd2, 0x73, 0x80, + 0x34, 0xb1, 0xce, 0x5b, 0x24, 0xe8, 0x1f, 0x9b, 0x15, 0xbe, 0x20, 0x43, + 0xe9, 0x89, 0xed, 0xa1, 0x4b, 0xe8, 0x1b, 0x1e, 0x8c, 0x84, 0x17, 0xe8, + 0x09, 0xd0, 0xe5, 0x23, 0xf8, 0x22, 0xab, 0x67, 0x0c, 0x3a, 0x84, 0x9c, + 0x0a, 0xeb, 0x8f, 0x4a, 0xda, 0xe0, 0xbb, 0xcc, 0x51, 0xd0, 0x8f, 0xf2, + 0x0e, 0x4d, 0x99, 0x9e, 0x4c, 0xcb, 0xaf, 0xc0, 0xf6, 0x1c, 0x11, 0xb1, + 0x4b, 0x56, 0xd0, 0xee, 0xd2, 0x06, 0x47, 0x0e, 0x60, 0x8b, 0x30, 0xef, + 0xe5, 0x41, 0x85, 0xb6, 0x20, 0x4e, 0x3f, 0x24, 0x78, 0xeb, 0xa3, 0x7d, + 0x66, 0xd4, 0xd8, 0x47, 0xf3, 0x7e, 0x27, 0x56, 0xc0, 0x3c, 0x3d, 0xf7, + 0x60, 0x0f, 0x90, 0x53, 0xfb, 0xeb, 0xeb, 0xa8, 0x2d, 0x12, 0x4e, 0xa8, + 0x09, 0xfa, 0x93, 0xd2, 0xdd, 0xe4, 0xe8, 0x77, 0x2b, 0xdb, 0x7e, 0xf0, + 0xb0, 0xd3, 0x69, 0x5b, 0x78, 0x16, 0x3a, 0xb1, 0x1e, 0xe3, 0xfe, 0xac, + 0xc0, 0x7d, 0x84, 0xba, 0xa1, 0x6b, 0x22, 0x8f, 0x39, 0x51, 0x8b, 0x17, + 0xf3, 0xbc, 0x9e, 0xcf, 0x5f, 0xc6, 0x3c, 0xdc, 0xcf, 0x70, 0x78, 0x2f, + 0x3c, 0x41, 0x23, 0x90, 0xc7, 0x5c, 0x7f, 0x57, 0x68, 0x0c, 0xdf, 0xa4, + 0x4a, 0x4d, 0x74, 0x54, 0xe3, 0xf1, 0x48, 0x38, 0xaf, 0x1e, 0x42, 0xdc, + 0xf3, 0xb8, 0xea, 0xb7, 0x7e, 0xe6, 0x67, 0xbf, 0xe3, 0xb7, 0xae, 0x29, + 0xd5, 0xb9, 0x10, 0x87, 0x8a, 0xdc, 0x60, 0x41, 0x19, 0x2c, 0x5d, 0x52, + 0x92, 0x85, 0x6b, 0x4a, 0xaa, 0xc4, 0x30, 0x8e, 0xce, 0x67, 0xcf, 0x74, + 0x82, 0x4e, 0x1f, 0x89, 0xef, 0xe6, 0x7a, 0x8f, 0x50, 0xea, 0xd4, 0xad, + 0x94, 0x9e, 0xe6, 0xbc, 0x34, 0x02, 0x7c, 0x3f, 0x2a, 0xe7, 0x62, 0x41, + 0xca, 0x9d, 0xe1, 0x31, 0xb6, 0x5f, 0xd6, 0xd5, 0x45, 0x1f, 0xef, 0x9f, + 0xf9, 0x6f, 0x52, 0xc1, 0x7e, 0x53, 0xd2, 0x8f, 0xdf, 0x7d, 0x9c, 0x93, + 0xe1, 0xf7, 0x6f, 0x86, 0xd3, 0xb7, 0x95, 0x16, 0x36, 0xdc, 0xc8, 0x3e, + 0x57, 0xb3, 0xc7, 0x47, 0x7d, 0x7e, 0x6b, 0x7b, 0x13, 0xb5, 0x84, 0x80, + 0xc3, 0x4a, 0x7b, 0x64, 0x98, 0x5f, 0x87, 0x1c, 0xb0, 0x4d, 0xd9, 0x0d, + 0x7e, 0x5a, 0x6c, 0xc3, 0x60, 0x93, 0x76, 0x53, 0xae, 0xc4, 0xb2, 0x1d, + 0x35, 0x32, 0x90, 0xb1, 0x34, 0x75, 0xb1, 0x1e, 0xb9, 0xba, 0x07, 0xdb, + 0x9d, 0x87, 0xed, 0x46, 0x3c, 0x64, 0x53, 0xbe, 0x29, 0xce, 0x36, 0xbc, + 0x0b, 0xb2, 0x85, 0xbe, 0x62, 0x55, 0x17, 0x77, 0x2d, 0xc1, 0x5d, 0x5b, + 0xc2, 0xa3, 0x02, 0xd5, 0xe2, 0x3f, 0x4b, 0x8c, 0xff, 0x5f, 0x00, 0xff, + 0xcf, 0x01, 0x7f, 0xc6, 0xa9, 0x31, 0xfe, 0x3b, 0x2b, 0xf8, 0x33, 0x0c, + 0xfc, 0x1c, 0x64, 0xf1, 0x0d, 0xe8, 0xe2, 0x6b, 0x36, 0x7c, 0x9d, 0x0d, + 0xff, 0x67, 0xc3, 0xdf, 0xd9, 0xf0, 0x8b, 0x36, 0x7c, 0x1e, 0xf6, 0x74, + 0x0e, 0x36, 0xe9, 0xac, 0x9d, 0x34, 0x58, 0x9f, 0x92, 0x31, 0xf6, 0x9d, + 0xbb, 0x65, 0xde, 0x1d, 0x92, 0x71, 0xf7, 0xa7, 0x64, 0x2c, 0x7b, 0x00, + 0xb1, 0xec, 0x66, 0x1a, 0xed, 0xe1, 0x9c, 0xa4, 0x05, 0xcf, 0x75, 0x78, + 0x22, 0x6e, 0xed, 0x49, 0x48, 0xbd, 0xfc, 0x0c, 0x62, 0x5c, 0xd8, 0xff, + 0x1e, 0xe4, 0x37, 0x19, 0xc4, 0x6a, 0x56, 0x1f, 0xc7, 0xe5, 0xb0, 0x65, + 0xef, 0x37, 0x39, 0x76, 0xfe, 0x2e, 0x19, 0x03, 0xbb, 0xed, 0x56, 0xc0, + 0xa4, 0xd1, 0xd7, 0x8a, 0x6f, 0x7e, 0x07, 0xb2, 0xdf, 0x86, 0xf6, 0xce, + 0x3a, 0x18, 0xe4, 0xb3, 0x56, 0x16, 0x7d, 0x11, 0xc0, 0xb4, 0x61, 0x9d, + 0x0e, 0xb4, 0xf7, 0xa0, 0x7d, 0x8b, 0xb3, 0x8e, 0xf1, 0x2b, 0x68, 0xa7, + 0xea, 0xbe, 0xd9, 0x8a, 0xbe, 0x4c, 0x5d, 0xdf, 0x9b, 0xe8, 0x4b, 0xa2, + 0x6f, 0x51, 0x7e, 0x97, 0x47, 0x3b, 0x52, 0x07, 0xb3, 0x88, 0x3e, 0xc6, + 0xf1, 0x5b, 0x78, 0xde, 0x47, 0xa3, 0x19, 0x8e, 0x03, 0xdc, 0xb1, 0xdc, + 0x7a, 0x6a, 0xe3, 0xdc, 0xf7, 0x43, 0x21, 0x3b, 0xf3, 0xd2, 0x46, 0xa7, + 0x27, 0xd8, 0x4f, 0x8c, 0x20, 0xee, 0xe1, 0x71, 0xe1, 0x9c, 0x3c, 0xfd, + 0x1f, 0x00, 0xf6, 0x61, 0x8c, 0x21, 0x56, 0xb7, 0xcb, 0x4d, 0x8d, 0xc7, + 0x1f, 0xc5, 0xf8, 0x5f, 0xca, 0x6f, 0x2b, 0x73, 0x03, 0xfe, 0x1b, 0x75, + 0x7d, 0x6a, 0xb0, 0xb6, 0xbd, 0xd6, 0xf3, 0xbe, 0x4d, 0x5f, 0xfa, 0xfd, + 0x48, 0x1d, 0xfc, 0xef, 0x6e, 0xa8, 0x6d, 0x3f, 0xc5, 0xdf, 0x20, 0x87, + 0x70, 0xdb, 0x09, 0xc8, 0x1d, 0xdb, 0xa4, 0xfa, 0x79, 0x3e, 0x6b, 0xd4, + 0xf6, 0x6d, 0x32, 0x6b, 0xdb, 0x1c, 0x27, 0x31, 0x5c, 0x08, 0xf2, 0xde, + 0xa1, 0xec, 0xb2, 0x7f, 0x13, 0xe3, 0x61, 0xe5, 0x5e, 0xdb, 0x8b, 0x67, + 0x48, 0xe6, 0x46, 0xe1, 0x4a, 0xcc, 0x3b, 0x5f, 0x0a, 0x40, 0xae, 0x3e, + 0x0f, 0x9e, 0x73, 0xdc, 0x53, 0xd5, 0xf1, 0xf7, 0x68, 0x39, 0x1d, 0x67, + 0x1f, 0xc0, 0x31, 0xfe, 0x36, 0x11, 0x1f, 0xfb, 0xe2, 0x4f, 0x70, 0x0c, + 0xf6, 0xb4, 0xe3, 0x5b, 0x2c, 0xf8, 0x43, 0xb4, 0x4b, 0x7e, 0xc7, 0x6e, + 0x22, 0x9f, 0xc8, 0x16, 0xd8, 0x9f, 0xb1, 0x0f, 0x89, 0xc0, 0x4e, 0xb3, + 0x1f, 0xfd, 0x24, 0x7d, 0xc6, 0x5d, 0xcd, 0x6c, 0xfb, 0x34, 0xeb, 0x05, + 0xc4, 0x0b, 0x1c, 0xe7, 0xb1, 0xed, 0xc6, 0x7b, 0xd1, 0x8d, 0x57, 0xee, + 0xd7, 0xc8, 0xaa, 0xfa, 0x11, 0x67, 0x8f, 0x5b, 0x59, 0x37, 0x56, 0xb1, + 0xef, 0xc6, 0xb6, 0xed, 0xc7, 0x75, 0xb6, 0xe1, 0xb2, 0xb0, 0x0d, 0x0f, + 0x6a, 0x7e, 0xeb, 0xf7, 0x9b, 0x1d, 0x79, 0x6d, 0x6c, 0x1b, 0xee, 0xad, + 0xd8, 0x06, 0x57, 0x5e, 0xbd, 0x79, 0xeb, 0x0f, 0xc0, 0x1b, 0x0b, 0xbc, + 0xa9, 0xaf, 0xd5, 0x70, 0x8e, 0xe2, 0x87, 0x1f, 0xe2, 0x18, 0x91, 0x73, + 0xd9, 0x18, 0xe5, 0x62, 0x45, 0xc4, 0x6a, 0x91, 0xd9, 0xd9, 0x4a, 0x8e, + 0xf5, 0x35, 0x69, 0xbb, 0x6b, 0xe2, 0x22, 0x7a, 0xbc, 0x78, 0x09, 0xf8, + 0x73, 0xbc, 0xa5, 0x49, 0x1b, 0xc1, 0xfd, 0xe3, 0x12, 0x47, 0x7e, 0xe7, + 0x3a, 0x1e, 0x7c, 0x69, 0xf1, 0x47, 0xe0, 0x15, 0xc7, 0x7d, 0x51, 0x27, + 0xde, 0xab, 0x89, 0xa9, 0xd7, 0xf8, 0xc9, 0xe2, 0x78, 0x89, 0x61, 0x74, + 0x19, 0x2f, 0x05, 0x64, 0x5e, 0x63, 0xc8, 0x3c, 0x87, 0x63, 0x6d, 0xae, + 0xb1, 0xd6, 0xc7, 0x50, 0x0b, 0x43, 0xc1, 0x6d, 0xcc, 0x13, 0x8e, 0xa1, + 0xda, 0x28, 0x39, 0xe3, 0xc4, 0x50, 0x4e, 0x9d, 0xcd, 0xcd, 0x71, 0x5c, + 0x5c, 0xd9, 0x0f, 0xef, 0xc0, 0x3e, 0x45, 0x9e, 0x14, 0x74, 0xea, 0x7f, + 0x1a, 0xec, 0xf6, 0x51, 0xf4, 0x8f, 0xba, 0xfd, 0x9e, 0x5c, 0xc3, 0xc5, + 0x85, 0x7d, 0xbd, 0x1b, 0xd3, 0xed, 0x96, 0x31, 0x1d, 0x62, 0x18, 0xdb, + 0xc9, 0xbb, 0xf6, 0x16, 0x33, 0xe8, 0xe3, 0x75, 0x11, 0x1b, 0x12, 0xc7, + 0x49, 0x90, 0xaf, 0xfd, 0x91, 0x50, 0x58, 0xad, 0xc7, 0xab, 0x75, 0xa1, + 0x16, 0xaf, 0x41, 0xf1, 0xdd, 0xf8, 0x92, 0xef, 0x48, 0xc4, 0x92, 0xe3, + 0xf6, 0x10, 0xe8, 0xc5, 0xf8, 0xb9, 0xba, 0xe1, 0xc6, 0xc9, 0x8c, 0xd3, + 0x3f, 0x82, 0xc6, 0xbb, 0x15, 0xfe, 0x7e, 0xcc, 0xde, 0x2f, 0xe8, 0x96, + 0x15, 0xb8, 0x0e, 0x7b, 0x70, 0x1d, 0x91, 0xb8, 0xb2, 0x2e, 0xb0, 0x7e, + 0x78, 0x6b, 0x9a, 0xa6, 0xd8, 0x1b, 0x70, 0x0e, 0xf3, 0xb9, 0xb9, 0x6a, + 0x2d, 0x0c, 0xf9, 0xb6, 0xc1, 0x1f, 0x02, 0xd7, 0xac, 0x88, 0x43, 0x03, + 0x0b, 0xf5, 0x34, 0x1c, 0xc7, 0x5a, 0x88, 0xdb, 0x81, 0x8f, 0xcb, 0xf3, + 0x26, 0x89, 0xcf, 0x37, 0xc5, 0xdc, 0x63, 0xa2, 0x06, 0xea, 0xd3, 0x39, + 0x77, 0xc9, 0x0a, 0xde, 0x69, 0x92, 0x77, 0x8f, 0x56, 0xf0, 0x73, 0x78, + 0x1c, 0x90, 0x74, 0xe5, 0xdc, 0x95, 0x75, 0x5a, 0xf0, 0xa7, 0x9d, 0x73, + 0xd3, 0x41, 0x6a, 0x14, 0x23, 0x2f, 0x0c, 0xa9, 0xdb, 0x1c, 0x3a, 0x3a, + 0x31, 0xf2, 0xda, 0xba, 0x18, 0xf9, 0xb6, 0x20, 0xc7, 0x5a, 0xc3, 0x50, + 0x82, 0x79, 0xf8, 0xba, 0x97, 0x6d, 0xc8, 0x36, 0x70, 0x3d, 0x5f, 0x53, + 0xbb, 0xec, 0x59, 0xa6, 0xd6, 0x1c, 0x20, 0xdf, 0x0c, 0xfb, 0x0e, 0x0b, + 0x79, 0x06, 0x91, 0x36, 0xc9, 0x3a, 0xcb, 0xbe, 0xbd, 0x1a, 0x67, 0xcf, + 0x51, 0xa3, 0x18, 0xfb, 0x46, 0xfd, 0xfa, 0x79, 0xbf, 0xdf, 0x3a, 0xac, + 0x3b, 0x36, 0x73, 0x25, 0xbf, 0xee, 0xc2, 0xed, 0x41, 0x9c, 0xad, 0x50, + 0x93, 0x55, 0xc0, 0xfe, 0xde, 0xf0, 0x37, 0x5b, 0xae, 0x2e, 0x06, 0x68, + 0xfd, 0xcc, 0x2d, 0x42, 0x1f, 0x8d, 0xc9, 0xaa, 0x3e, 0x8e, 0x82, 0x37, + 0x19, 0xa7, 0x06, 0x60, 0xae, 0xa7, 0xeb, 0xd7, 0x0b, 0xc6, 0xed, 0x37, + 0xfd, 0xaa, 0xe5, 0xca, 0xc0, 0xf5, 0xf2, 0x91, 0x4f, 0xd5, 0xd1, 0xba, + 0x51, 0x4d, 0xf8, 0x2c, 0xe8, 0x1a, 0x47, 0xde, 0x1d, 0x79, 0x81, 0x10, + 0x3b, 0x39, 0x79, 0x78, 0x1a, 0xb9, 0x77, 0xe4, 0x02, 0xe7, 0xe3, 0x6e, + 0x7e, 0xfe, 0x6a, 0x29, 0x72, 0x36, 0x8f, 0x9c, 0x79, 0x1e, 0x39, 0xf9, + 0xcb, 0xc8, 0xc9, 0xcf, 0x97, 0x7a, 0x41, 0xff, 0x1e, 0x99, 0x8f, 0xb3, + 0x8e, 0x99, 0x74, 0x11, 0xb9, 0xd3, 0x77, 0x67, 0xd8, 0x46, 0x74, 0xd1, + 0x3d, 0xc8, 0x35, 0xbe, 0x3f, 0xa9, 0x68, 0x9d, 0x7d, 0x01, 0x5f, 0xc2, + 0xb8, 0x91, 0x38, 0x71, 0x29, 0x4f, 0x1a, 0xc7, 0x8a, 0x23, 0x4d, 0x7e, + 0x6b, 0xae, 0x95, 0x5a, 0xf6, 0x2c, 0xcb, 0x93, 0x6a, 0xac, 0xe8, 0xc2, + 0x19, 0xd4, 0xd9, 0xf7, 0x87, 0x9c, 0xdb, 0xc4, 0x48, 0xe4, 0xd3, 0xeb, + 0xe8, 0xed, 0x93, 0x65, 0xda, 0x19, 0xbb, 0x56, 0xbe, 0x68, 0xad, 0xa3, + 0x6c, 0xef, 0x43, 0x32, 0x97, 0x5c, 0x78, 0x28, 0x69, 0xe5, 0x43, 0x3e, + 0xf7, 0x7c, 0x62, 0x42, 0x47, 0x84, 0xc8, 0xbf, 0x20, 0xcd, 0x0d, 0x20, + 0x71, 0x6e, 0xd9, 0xfe, 0x02, 0x1f, 0x10, 0xb1, 0x6d, 0x9c, 0x33, 0x03, + 0xa2, 0xd6, 0xb6, 0xd1, 0xe2, 0x7e, 0x03, 0xfc, 0xbe, 0x8f, 0xe6, 0x90, + 0x43, 0x14, 0x44, 0x1e, 0xde, 0x0e, 0x78, 0x37, 0x0f, 0xbf, 0x1f, 0xb9, + 0x01, 0xd3, 0xd8, 0x04, 0xfc, 0x6f, 0x03, 0xc6, 0x6b, 0x43, 0x9f, 0x6b, + 0x22, 0xf1, 0x3d, 0x8f, 0xb7, 0x13, 0xd7, 0x65, 0xab, 0xf3, 0xf2, 0x9c, + 0x3c, 0xf6, 0x61, 0xf9, 0xf6, 0xbe, 0x3e, 0xcf, 0xdc, 0x6d, 0x9e, 0xb9, + 0xef, 0xf0, 0xcc, 0xed, 0xc3, 0xb7, 0x2e, 0x3e, 0x41, 0x7c, 0xeb, 0xae, + 0xf1, 0xb7, 0x9e, 0x35, 0x5c, 0xdc, 0xdb, 0x3d, 0xb8, 0xbf, 0x8f, 0xf9, + 0xb9, 0xcf, 0xf4, 0xf4, 0xf1, 0x9a, 0x1b, 0x68, 0x6e, 0xb0, 0x8d, 0x16, + 0x4f, 0x72, 0x5f, 0xd0, 0x83, 0x0b, 0xe3, 0x17, 0x90, 0x63, 0x6d, 0x74, + 0xf1, 0x64, 0x8b, 0xc0, 0x9b, 0xfd, 0xf9, 0xc6, 0xca, 0x9a, 0x57, 0xb0, + 0xa6, 0x3b, 0x97, 0x89, 0x6f, 0x19, 0x96, 0xf1, 0xe3, 0x31, 0xee, 0xe3, + 0xb1, 0x37, 0xcb, 0x5f, 0x33, 0x82, 0xce, 0x9e, 0x0d, 0xc6, 0xcd, 0xfd, + 0x56, 0x6b, 0x26, 0x8b, 0xdb, 0x9d, 0x34, 0x1b, 0xd4, 0xc0, 0x37, 0x55, + 0xfa, 0x28, 0xae, 0x23, 0xa8, 0x4a, 0xb4, 0x8f, 0xf9, 0xbc, 0x4e, 0xd6, + 0xaf, 0x5b, 0x30, 0x6f, 0xd8, 0xcd, 0xd1, 0x88, 0xe5, 0x38, 0x27, 0xec, + 0xbe, 0x26, 0xc7, 0xd9, 0xee, 0xb3, 0xdf, 0xc7, 0x53, 0xc8, 0xaa, 0x3c, + 0xaf, 0x29, 0xed, 0xa0, 0x83, 0x50, 0xcf, 0x8b, 0xb2, 0x9e, 0xb2, 0xe8, + 0xad, 0x99, 0x18, 0x4e, 0x1c, 0xe3, 0x9c, 0xed, 0xac, 0x85, 0xfe, 0xe0, + 0xbd, 0x98, 0x00, 0x1e, 0x61, 0x8a, 0xe2, 0xaf, 0x50, 0xca, 0xe3, 0x69, + 0xe1, 0xa9, 0xe0, 0xc9, 0xf5, 0x0c, 0x1d, 0x4f, 0xe8, 0x18, 0xec, 0x53, + 0xb4, 0xef, 0x92, 0x93, 0x3f, 0x41, 0x37, 0xde, 0x9e, 0x74, 0xea, 0x51, + 0x8b, 0xd6, 0x72, 0xf5, 0xa8, 0x3f, 0x67, 0x9e, 0x9c, 0x70, 0xeb, 0x51, + 0x8b, 0x24, 0xea, 0x51, 0x27, 0x56, 0xa8, 0x47, 0x25, 0x56, 0x5f, 0x8f, + 0xe2, 0xf9, 0x35, 0xda, 0xd7, 0x4f, 0xca, 0x17, 0x64, 0x3d, 0xea, 0x3d, + 0x72, 0xea, 0x51, 0x17, 0xa9, 0x71, 0x3d, 0xea, 0x78, 0x5d, 0x3d, 0x2a, + 0x28, 0xea, 0x51, 0x3c, 0x8f, 0x53, 0x8f, 0x12, 0xed, 0xbe, 0x88, 0xa7, + 0xee, 0x42, 0xf4, 0xee, 0x64, 0x07, 0x68, 0x66, 0xd0, 0xf7, 0x1a, 0xda, + 0x34, 0x45, 0xc8, 0xdb, 0x4a, 0x35, 0xd0, 0x07, 0x6e, 0xb8, 0xbe, 0xa2, + 0xd0, 0x06, 0xcc, 0x9b, 0xec, 0x7b, 0xd8, 0x53, 0x63, 0x61, 0x9a, 0xff, + 0x62, 0xea, 0x2c, 0x07, 0x45, 0x9d, 0xe5, 0x87, 0x6b, 0xbc, 0x75, 0x96, + 0x45, 0xba, 0x7e, 0x9d, 0xe5, 0x60, 0x83, 0x3a, 0xcb, 0x5b, 0x54, 0xad, + 0xb3, 0xbc, 0x45, 0xd5, 0x3a, 0xcb, 0xc1, 0x12, 0xe7, 0xe2, 0x3e, 0x89, + 0x5f, 0x06, 0xed, 0x41, 0xf1, 0xc7, 0xb5, 0x97, 0xc5, 0xca, 0x1e, 0x7e, + 0xd9, 0x6a, 0x2f, 0x6c, 0x03, 0x22, 0x17, 0x2e, 0xd7, 0xd4, 0x5e, 0xb8, + 0x0d, 0x9d, 0xb1, 0xd7, 0x08, 0x19, 0x99, 0x83, 0x7f, 0x5f, 0x9c, 0x0c, + 0x61, 0xce, 0x0e, 0xf8, 0x8c, 0x0e, 0xe4, 0x06, 0x61, 0xb4, 0x15, 0xda, + 0x64, 0x0d, 0xa1, 0x8f, 0xc7, 0xd9, 0x0e, 0x43, 0xb7, 0x6c, 0x77, 0x7f, + 0x0f, 0x48, 0x1a, 0x44, 0x68, 0xb8, 0x9d, 0xf4, 0x20, 0xfb, 0x8e, 0xc9, + 0x3d, 0x74, 0xc8, 0xde, 0x22, 0xf6, 0xbd, 0xc1, 0xaa, 0x95, 0xb9, 0xc1, + 0x1b, 0x90, 0xb9, 0xcc, 0xaa, 0x65, 0x8e, 0xe5, 0xcd, 0x39, 0xf7, 0xdd, + 0x60, 0xf1, 0xfa, 0x1d, 0x02, 0xa7, 0x77, 0x1b, 0xc8, 0xfb, 0x18, 0xec, + 0x8e, 0x33, 0xbf, 0x2e, 0xd7, 0xab, 0x8f, 0x87, 0x9f, 0x6d, 0x66, 0xff, + 0xbd, 0x72, 0x3d, 0xb1, 0xde, 0x7f, 0xaf, 0xe4, 0x47, 0x15, 0x61, 0x93, + 0xb3, 0x25, 0xae, 0xed, 0x7b, 0xf9, 0x33, 0x8f, 0x9c, 0x00, 0x7d, 0x42, + 0x0f, 0x98, 0xae, 0x41, 0xf0, 0x01, 0xeb, 0xd8, 0x4f, 0xc9, 0x5a, 0x16, + 0x9e, 0x05, 0x97, 0x7f, 0xad, 0xb0, 0x99, 0xee, 0x18, 0xdb, 0x01, 0x0b, + 0xfe, 0x8f, 0xeb, 0x28, 0x7c, 0x8e, 0xca, 0xfd, 0x2e, 0x5f, 0xbb, 0x2e, + 0xbc, 0xa7, 0x72, 0xbb, 0x5c, 0xce, 0x8a, 0x7a, 0x2d, 0xa9, 0x9d, 0x7d, + 0xd3, 0x2d, 0x6c, 0x6b, 0xb6, 0x58, 0xae, 0xcc, 0x26, 0xf0, 0xce, 0x7c, + 0x7d, 0x17, 0x36, 0x9c, 0xcf, 0xaa, 0xbf, 0x23, 0x6a, 0x04, 0x73, 0x36, + 0xdb, 0x6b, 0x8e, 0x41, 0x7f, 0x0b, 0xb2, 0xc4, 0xef, 0x51, 0x71, 0x2e, + 0x21, 0x6a, 0xf8, 0x83, 0xdc, 0x76, 0xed, 0x4a, 0x94, 0xed, 0x30, 0xf6, + 0x5c, 0xa5, 0x31, 0xe2, 0x23, 0xc8, 0x0c, 0xc7, 0xb1, 0x0c, 0xe7, 0xc6, + 0x9e, 0x9a, 0xa7, 0x66, 0xab, 0xcb, 0xb8, 0x88, 0x75, 0x39, 0x00, 0x9a, + 0xed, 0x10, 0x31, 0xea, 0xb8, 0x5d, 0xa6, 0xea, 0x19, 0x3f, 0xd3, 0xdc, + 0x39, 0xe7, 0x3f, 0x66, 0x2f, 0x47, 0xfb, 0xcd, 0x37, 0x48, 0x7b, 0x47, + 0x1f, 0x6b, 0xe9, 0xae, 0x23, 0x7e, 0x71, 0xe9, 0xee, 0xfa, 0xa8, 0x49, + 0x49, 0x83, 0xa8, 0xac, 0x2b, 0x7e, 0x5a, 0x9e, 0x29, 0xfd, 0x5f, 0xd8, + 0xaf, 0xe2, 0xd9, 0xaf, 0xab, 0xbb, 0xfb, 0xe4, 0x7e, 0xc3, 0x75, 0xba, + 0x1b, 0x97, 0x75, 0xb9, 0x5f, 0x84, 0xee, 0xba, 0x7b, 0xe2, 0xb5, 0xb7, + 0x5c, 0x67, 0xdd, 0x67, 0x48, 0x8d, 0xaf, 0x14, 0x7b, 0xff, 0xb4, 0xf9, + 0xe3, 0xc5, 0xde, 0x1f, 0x87, 0x9e, 0x5e, 0xbd, 0x65, 0x1a, 0xb6, 0x89, + 0xb8, 0xc2, 0xd1, 0x1f, 0xd8, 0xe3, 0x82, 0x9f, 0x16, 0x1e, 0xd2, 0xe9, + 0x9f, 0xee, 0xe4, 0xfa, 0xac, 0x26, 0x73, 0x7c, 0x6e, 0x7f, 0xb1, 0x95, + 0x63, 0xab, 0x4d, 0xd6, 0x77, 0x44, 0x6e, 0x95, 0x57, 0x4d, 0x8f, 0x1f, + 0x31, 0x30, 0xce, 0x63, 0x61, 0xba, 0x1c, 0xbc, 0x91, 0xb8, 0xbc, 0xcb, + 0x58, 0xf4, 0xad, 0x26, 0x2e, 0xbf, 0x55, 0xf7, 0x5b, 0x7f, 0xdd, 0x7a, + 0xbd, 0x3a, 0x47, 0x35, 0x2e, 0xe7, 0x7c, 0x3e, 0xe8, 0xd4, 0x18, 0x4c, + 0x8e, 0xcf, 0xd7, 0x4a, 0x9e, 0xf0, 0x3b, 0x72, 0x11, 0x1b, 0x79, 0x08, + 0x64, 0xfc, 0x55, 0xc8, 0xca, 0x2b, 0x36, 0xf2, 0x0e, 0x1b, 0xf9, 0x88, + 0x8d, 0xdc, 0xc3, 0x46, 0xee, 0x61, 0xf7, 0xc8, 0x1c, 0x26, 0x23, 0xeb, + 0x56, 0x7c, 0x46, 0xcb, 0xf9, 0x61, 0x5e, 0xc9, 0xd8, 0xe3, 0x7c, 0x1f, + 0x41, 0x4d, 0xc6, 0x36, 0xca, 0x78, 0xf0, 0x38, 0xdf, 0x77, 0x28, 0xab, + 0x71, 0xae, 0x45, 0x91, 0xaa, 0xc6, 0x6f, 0x87, 0x8f, 0xda, 0x0e, 0xbc, + 0x9a, 0x79, 0xdc, 0xa7, 0xc6, 0x5b, 0x99, 0x76, 0x8a, 0x1a, 0x5f, 0x2b, + 0xcf, 0x0d, 0x7a, 0x03, 0x0e, 0xfe, 0xdd, 0xdc, 0xd6, 0xd4, 0xf8, 0xdd, + 0xec, 0xd3, 0xc2, 0xa4, 0xba, 0xfd, 0xb7, 0x07, 0x98, 0xae, 0xa4, 0xde, + 0x16, 0xe0, 0xb8, 0x76, 0xde, 0xf6, 0x8b, 0x3b, 0x05, 0xc9, 0x18, 0xd7, + 0xcc, 0xb8, 0x5d, 0xa5, 0xab, 0xba, 0x2c, 0x5d, 0xfd, 0x95, 0xfa, 0x3f, + 0xd3, 0xd2, 0xc7, 0x70, 0xa2, 0x36, 0xc6, 0x34, 0x75, 0xe7, 0xe3, 0xf3, + 0x66, 0x5e, 0x47, 0xdc, 0x63, 0xc0, 0xf3, 0x60, 0x33, 0xb5, 0x0d, 0x0e, + 0xf9, 0x2d, 0xef, 0xba, 0x6c, 0x43, 0x76, 0x90, 0x37, 0xc7, 0x5a, 0x7e, + 0xcd, 0xa8, 0x38, 0x1b, 0x49, 0xf6, 0x47, 0x85, 0xec, 0xb0, 0xac, 0x69, + 0xe2, 0xce, 0xd5, 0x47, 0xe2, 0x1e, 0x09, 0xcb, 0x19, 0xcb, 0xf2, 0x78, + 0x7f, 0x57, 0x58, 0x53, 0x5b, 0xb0, 0x46, 0x98, 0xd2, 0x25, 0x71, 0x56, + 0x80, 0x7c, 0xe9, 0xdc, 0x3a, 0x6a, 0xfb, 0x07, 0xbd, 0x9a, 0xc7, 0x46, + 0x9d, 0xb3, 0x7a, 0xbb, 0xde, 0xff, 0x8d, 0x8a, 0x73, 0x65, 0xc7, 0x06, + 0xb9, 0xe7, 0xc3, 0xab, 0x3b, 0xff, 0xbe, 0xbe, 0x3e, 0xb5, 0xd4, 0xd7, + 0x0d, 0x24, 0x0d, 0x98, 0x36, 0x8d, 0xcf, 0xee, 0xe7, 0x4b, 0x7c, 0xaf, + 0x25, 0x12, 0xe3, 0xdc, 0x6d, 0x44, 0xdc, 0xf9, 0x50, 0x21, 0x85, 0x3a, + 0x8d, 0x19, 0x9c, 0xf3, 0x85, 0x86, 0x7d, 0x71, 0xca, 0x64, 0x27, 0x48, + 0x43, 0xac, 0x98, 0xa9, 0xd6, 0x03, 0x1f, 0x5c, 0x43, 0x96, 0x2b, 0x97, + 0x51, 0xce, 0x1f, 0x6a, 0xce, 0xed, 0x16, 0xe9, 0xb0, 0x72, 0xa0, 0x74, + 0x84, 0x0e, 0x34, 0x8c, 0x29, 0x1b, 0xd7, 0x03, 0x2f, 0xd6, 0xd5, 0x14, + 0x16, 0x44, 0x4d, 0x21, 0xb7, 0xc6, 0x6f, 0x3d, 0x19, 0x70, 0xee, 0xb5, + 0x34, 0xd6, 0x93, 0x5d, 0x15, 0x3d, 0x71, 0xe1, 0xf8, 0x2c, 0xbe, 0x8d, + 0x76, 0x8a, 0xb5, 0x0e, 0x2b, 0x59, 0xbb, 0x95, 0x76, 0x1a, 0x0e, 0xd6, + 0xa3, 0x36, 0xe3, 0x75, 0x58, 0x39, 0x68, 0xe7, 0x95, 0xb4, 0xa8, 0x3d, + 0x70, 0x8c, 0xbf, 0xe6, 0xda, 0x30, 0x95, 0xe9, 0xed, 0x98, 0xfb, 0x3d, + 0xc3, 0x78, 0x6b, 0x8a, 0x2e, 0x9d, 0xf8, 0x2e, 0x51, 0x58, 0xe6, 0x6f, + 0xce, 0x7c, 0xb9, 0x29, 0xae, 0x25, 0xde, 0x8f, 0xfd, 0x33, 0xfc, 0x6e, + 0x25, 0x39, 0x55, 0x2e, 0xa7, 0x31, 0x3e, 0xd6, 0x7b, 0xaf, 0xc8, 0x8d, + 0xd4, 0x38, 0x0d, 0x71, 0x8e, 0xac, 0x2d, 0xc9, 0x91, 0xd3, 0xd0, 0x35, + 0xc4, 0x20, 0x76, 0x13, 0xbe, 0x75, 0xe3, 0x91, 0xcf, 0xae, 0x75, 0x64, + 0xe4, 0xbb, 0x12, 0x0f, 0x1e, 0xff, 0xfb, 0x80, 0x7b, 0x0f, 0x28, 0x77, + 0x2a, 0x8d, 0xfd, 0x37, 0x51, 0xca, 0x74, 0xf2, 0xbb, 0xec, 0x99, 0x23, + 0x1b, 0x6a, 0xe1, 0xd1, 0x77, 0xca, 0x85, 0x0f, 0xd6, 0xc1, 0xf3, 0x19, + 0xd7, 0x5f, 0xd5, 0xc1, 0x07, 0x3d, 0xf0, 0x66, 0x1d, 0x3c, 0xe2, 0xae, + 0x33, 0xdf, 0xa8, 0x83, 0x37, 0x3d, 0xf0, 0xed, 0x75, 0xf0, 0xed, 0x80, + 0x7f, 0xa3, 0x0e, 0x1e, 0x7d, 0xa7, 0x90, 0x13, 0x08, 0xda, 0x70, 0x8c, + 0x74, 0x48, 0xe6, 0x89, 0x78, 0x2e, 0xb9, 0x1f, 0xc9, 0xf2, 0xd3, 0x01, + 0x1a, 0x7b, 0xeb, 0xb5, 0x09, 0xd8, 0xa8, 0xaa, 0x4c, 0x39, 0xfa, 0xea, + 0x95, 0x25, 0x96, 0xbd, 0x3c, 0xe4, 0x15, 0x7a, 0x54, 0x80, 0x3e, 0x15, + 0x5c, 0x5f, 0xca, 0x77, 0xaa, 0x22, 0xc7, 0x1d, 0x3d, 0x56, 0x68, 0xbd, + 0x35, 0x2f, 0x73, 0x91, 0xab, 0x8c, 0x3b, 0xfc, 0x86, 0xeb, 0x3b, 0xe8, + 0x84, 0x63, 0x57, 0x58, 0xbf, 0x79, 0x7e, 0x69, 0x5f, 0x4a, 0x2c, 0x87, + 0xce, 0x3a, 0xe9, 0x25, 0x32, 0x1b, 0x5e, 0x52, 0x77, 0xf1, 0xd5, 0xd9, + 0x77, 0x12, 0xf6, 0x3d, 0xd7, 0xe2, 0xb7, 0x36, 0xac, 0xbd, 0x9e, 0x7d, + 0xcf, 0x78, 0xec, 0x7b, 0x38, 0x58, 0xf5, 0xf9, 0x8f, 0x09, 0x9f, 0xdf, + 0xd1, 0xc0, 0x66, 0xac, 0xde, 0xe7, 0xef, 0xfd, 0xd8, 0x3e, 0x7f, 0xb9, + 0x75, 0x57, 0xe3, 0xf3, 0x1f, 0x69, 0xf9, 0x78, 0x3e, 0x9f, 0xd7, 0xac, + 0xaf, 0x65, 0x7a, 0xcf, 0x59, 0x8e, 0xca, 0x18, 0x7b, 0xb7, 0x27, 0xc6, + 0x66, 0xfc, 0xbe, 0x27, 0xef, 0x02, 0x9e, 0x5e, 0xeb, 0xc8, 0xdb, 0x51, + 0x19, 0xa7, 0x73, 0xec, 0x8d, 0xf7, 0xc2, 0x23, 0x90, 0xd1, 0x7c, 0x8f, + 0x8f, 0x54, 0x9a, 0x35, 0x9d, 0xb3, 0xed, 0x9f, 0x6f, 0xae, 0x17, 0xa1, + 0xcb, 0xc2, 0x9f, 0x24, 0x3e, 0x81, 0x5a, 0xea, 0x49, 0xc8, 0x8f, 0xbb, + 0xaf, 0x95, 0x6a, 0xa9, 0xf5, 0xe7, 0x1f, 0x7c, 0xee, 0x41, 0xca, 0x03, + 0x95, 0x73, 0x10, 0xaf, 0x4e, 0xe9, 0x94, 0x9d, 0x21, 0xdd, 0x8c, 0x93, + 0xb2, 0x8f, 0x71, 0x8e, 0xfd, 0xb0, 0x52, 0x6f, 0x3f, 0x24, 0x6b, 0x30, + 0xea, 0xb2, 0x77, 0x82, 0x7e, 0x02, 0x7c, 0x58, 0xaf, 0x9c, 0x1a, 0x8c, + 0xea, 0xdc, 0x09, 0x3a, 0xfe, 0xf3, 0xbb, 0x13, 0xc4, 0xf3, 0x6b, 0xb4, + 0xb7, 0xc1, 0x9d, 0x20, 0xdf, 0x2a, 0xef, 0x04, 0xad, 0x17, 0x35, 0x18, + 0x9e, 0xc7, 0xa9, 0xc1, 0x70, 0xbb, 0xb3, 0x8f, 0xe5, 0x3a, 0x4c, 0xa3, + 0x93, 0xb7, 0x88, 0x7b, 0xa8, 0x9d, 0x7d, 0xb5, 0xf2, 0xbd, 0xef, 0x13, + 0x8d, 0xa5, 0x79, 0xbd, 0xa3, 0x0d, 0xef, 0xb6, 0x24, 0x3f, 0xc1, 0x9a, + 0xcb, 0x21, 0x51, 0x73, 0xb9, 0xb3, 0xcd, 0x5b, 0x73, 0x51, 0x57, 0xb8, + 0xdb, 0x72, 0xa8, 0x41, 0xcd, 0xc5, 0xef, 0xb9, 0xdb, 0xe2, 0xf7, 0xdc, + 0x6d, 0x39, 0x24, 0xeb, 0x2b, 0xea, 0x2f, 0xd1, 0xdd, 0x96, 0xe4, 0x8a, + 0x77, 0x5b, 0xb6, 0x4a, 0x7d, 0xf5, 0xc2, 0xaf, 0xfe, 0xbc, 0x32, 0x55, + 0x67, 0xe7, 0x13, 0xc2, 0xce, 0xdf, 0xd5, 0xea, 0xb7, 0x9e, 0x69, 0xbb, + 0x9e, 0x9d, 0xdf, 0x57, 0xd1, 0x53, 0xbe, 0xa3, 0xcd, 0x77, 0xbe, 0x58, + 0x16, 0xf9, 0x7c, 0xa6, 0x89, 0x72, 0x03, 0xbf, 0x2a, 0x68, 0xf6, 0x58, + 0x6f, 0xed, 0x99, 0x63, 0xf5, 0x5e, 0xa4, 0xee, 0xb9, 0x17, 0x69, 0xa2, + 0x5f, 0xaf, 0xab, 0x87, 0x04, 0xe4, 0xdd, 0x7e, 0xf8, 0xc2, 0x19, 0x43, + 0xda, 0x5e, 0xc4, 0x70, 0x98, 0xae, 0x50, 0xe4, 0x3b, 0x95, 0x6d, 0xe4, + 0x9b, 0x71, 0xce, 0x4b, 0x54, 0x11, 0x63, 0x42, 0x8e, 0x8b, 0x7e, 0xe1, + 0x6f, 0xd4, 0xb8, 0x23, 0xb3, 0xe3, 0xf6, 0x05, 0xe0, 0xbf, 0x21, 0x51, + 0x6d, 0x9b, 0x95, 0x5a, 0xce, 0x58, 0xe5, 0x0e, 0xbf, 0x09, 0xfb, 0xe0, + 0xdc, 0x07, 0xca, 0x98, 0x7c, 0x67, 0xe4, 0x62, 0x5b, 0xf5, 0x3e, 0xd0, + 0x67, 0xa4, 0x9c, 0x3a, 0xf7, 0x81, 0x48, 0x4d, 0x40, 0x3e, 0x6e, 0xe4, + 0x3e, 0x50, 0xd7, 0x92, 0xfb, 0x40, 0x2b, 0xf3, 0x66, 0xe9, 0x7d, 0xa0, + 0xc6, 0xfc, 0xe1, 0xfb, 0x40, 0xff, 0xde, 0xe6, 0xdc, 0x43, 0x5d, 0x89, + 0x3f, 0x6e, 0x9c, 0xf4, 0x11, 0xe0, 0xf9, 0x3e, 0x50, 0xe5, 0x1e, 0x90, + 0xe7, 0x0e, 0x10, 0xdf, 0x25, 0x59, 0xee, 0x0c, 0xce, 0x7b, 0xff, 0xa4, + 0xa7, 0x72, 0xff, 0xe4, 0x7c, 0xc9, 0xf5, 0xed, 0xee, 0xb9, 0x1c, 0xc7, + 0x39, 0xbb, 0x44, 0x8e, 0x7a, 0xae, 0x54, 0x5b, 0xc3, 0x60, 0xbe, 0x8f, + 0x16, 0xcf, 0x81, 0x3e, 0x6f, 0x89, 0xdc, 0x00, 0x7c, 0xde, 0xe2, 0x23, + 0xe6, 0x1d, 0x29, 0xa0, 0x8b, 0x38, 0xcb, 0x75, 0xf8, 0xdd, 0x21, 0x64, + 0xc1, 0x91, 0x8b, 0xdd, 0x9e, 0xf3, 0xd0, 0xaa, 0x1c, 0x38, 0x67, 0xba, + 0x0e, 0xef, 0x6a, 0x65, 0x46, 0x9c, 0xdd, 0x0c, 0xed, 0xb5, 0x9c, 0xf3, + 0xc6, 0xa8, 0x38, 0xb7, 0x6d, 0xaf, 0xb3, 0x5b, 0x3a, 0xe4, 0x06, 0x31, + 0x67, 0x8c, 0xeb, 0xd5, 0x8c, 0xfb, 0x66, 0xc1, 0xe3, 0x46, 0x67, 0x71, + 0x2b, 0xd7, 0xf1, 0xdc, 0x9a, 0x0a, 0x21, 0x97, 0xd8, 0x9d, 0xce, 0x09, + 0xbb, 0xe9, 0xac, 0xdd, 0x29, 0xd6, 0xde, 0x58, 0x77, 0x96, 0xcd, 0x72, + 0xb5, 0x5c, 0x4c, 0x70, 0x3d, 0x9a, 0xde, 0xb3, 0x84, 0xa6, 0xb5, 0xba, + 0x84, 0xdc, 0xb5, 0x62, 0xe3, 0x3b, 0x2a, 0xba, 0x34, 0x2e, 0xee, 0x21, + 0xbb, 0xe7, 0xb5, 0x0e, 0xfd, 0xaa, 0xba, 0xb7, 0x5c, 0x3c, 0x53, 0x4f, + 0xbf, 0x4d, 0xff, 0x4b, 0xe8, 0x77, 0x15, 0xf4, 0xe3, 0x77, 0x03, 0xef, + 0xef, 0x8a, 0x7a, 0xc0, 0xb9, 0x52, 0xe4, 0x78, 0x9e, 0x38, 0x4e, 0x88, + 0xcc, 0x2e, 0x50, 0x0f, 0xe8, 0xc8, 0xff, 0xeb, 0xe2, 0xde, 0x9d, 0x60, + 0xfa, 0xb2, 0x7d, 0x8f, 0xbc, 0x70, 0x99, 0xd8, 0xc6, 0xdf, 0x8d, 0x7d, + 0x94, 0xcb, 0x2f, 0xc5, 0x5c, 0xfa, 0xb3, 0xee, 0x73, 0x9d, 0xaa, 0x76, + 0x5f, 0x7b, 0x57, 0xed, 0x53, 0x1d, 0xf9, 0xcc, 0x34, 0x90, 0xcf, 0x8c, + 0xdc, 0xa3, 0x6f, 0xa6, 0x71, 0xbc, 0x9a, 0x9a, 0xfc, 0xef, 0x5e, 0xae, + 0x26, 0xb6, 0x8d, 0x22, 0x0a, 0xbf, 0xac, 0xd7, 0x4e, 0xe3, 0xa4, 0x61, + 0x93, 0x3a, 0xad, 0x69, 0xd2, 0x60, 0xc7, 0x4b, 0x12, 0x29, 0xa5, 0xa4, + 0x52, 0x55, 0x45, 0x60, 0xa9, 0x21, 0x4e, 0xda, 0x0a, 0x71, 0x70, 0x0b, + 0x48, 0x51, 0xc5, 0x21, 0x4d, 0xd3, 0x7b, 0x85, 0x84, 0x54, 0xa1, 0x8a, + 0x46, 0x4e, 0x02, 0x15, 0x4a, 0xe5, 0x0a, 0x96, 0x72, 0x41, 0xa2, 0xd8, + 0x8e, 0x02, 0x52, 0x2a, 0xf7, 0xca, 0x85, 0xba, 0xbf, 0x08, 0x89, 0x03, + 0x70, 0x06, 0x29, 0x2a, 0x3f, 0xe2, 0xc0, 0x8d, 0x1b, 0x54, 0x5d, 0xde, + 0x37, 0xb3, 0x63, 0xaf, 0x77, 0xd7, 0x8e, 0x03, 0x11, 0x07, 0x27, 0xbb, + 0xf6, 0xcc, 0xce, 0xec, 0xcc, 0x37, 0x6f, 0xbe, 0xf7, 0x37, 0xfd, 0xbe, + 0x78, 0x8d, 0x5a, 0xdb, 0x5b, 0xf3, 0x55, 0xec, 0xe7, 0xaf, 0x37, 0x18, + 0x57, 0xed, 0xba, 0xe4, 0xa9, 0xf5, 0xe3, 0x9a, 0x72, 0xd9, 0x1b, 0xf0, + 0xfe, 0xc7, 0x68, 0x51, 0xd8, 0x86, 0x94, 0xad, 0xee, 0xc5, 0x40, 0x9b, + 0xd9, 0xff, 0x33, 0x16, 0x03, 0x3e, 0x9b, 0x68, 0xad, 0x6d, 0x8a, 0xed, + 0x71, 0xd9, 0x16, 0xde, 0xda, 0xc2, 0xb6, 0x10, 0x3c, 0x16, 0xfd, 0x9e, + 0xb1, 0xa8, 0xc9, 0xea, 0xa1, 0x16, 0xed, 0x74, 0x88, 0x21, 0xbf, 0x9d, + 0x67, 0x6c, 0x05, 0xca, 0xce, 0x4f, 0x5d, 0x36, 0x3c, 0xe0, 0x73, 0xdc, + 0x59, 0xeb, 0xc0, 0x27, 0xb5, 0x9d, 0x1a, 0x51, 0xed, 0x01, 0x8f, 0xc9, + 0xc5, 0x45, 0x82, 0xbe, 0x86, 0x36, 0xe3, 0x82, 0xe3, 0xfa, 0x39, 0x14, + 0x8f, 0xf1, 0xfa, 0x1b, 0x88, 0xe5, 0x70, 0xda, 0x3f, 0xd9, 0x76, 0xae, + 0x9c, 0xe5, 0xbd, 0x42, 0xd4, 0x63, 0xbd, 0xef, 0x52, 0xdb, 0x82, 0xa8, + 0x27, 0xe3, 0x20, 0x1c, 0x1d, 0xd0, 0xe1, 0xe2, 0x8d, 0x74, 0x3f, 0xff, + 0x9e, 0x13, 0xcc, 0xdd, 0x7f, 0xdd, 0x1d, 0x36, 0x3f, 0x34, 0x64, 0xae, + 0xde, 0x56, 0xdc, 0x5d, 0xd9, 0x89, 0x06, 0x85, 0xaf, 0xc1, 0xad, 0x7b, + 0x41, 0x76, 0x5d, 0xe0, 0x3d, 0x7c, 0xa8, 0xba, 0x7f, 0xef, 0x84, 0x7d, + 0xe8, 0x99, 0x16, 0x62, 0x1d, 0x44, 0x8e, 0xe5, 0x2b, 0x53, 0xc8, 0x45, + 0xaa, 0xe6, 0xef, 0x78, 0xf3, 0x3c, 0x20, 0x3f, 0x55, 0x9e, 0x87, 0xca, + 0x23, 0xc5, 0x7b, 0x24, 0x02, 0xf2, 0x3c, 0xdc, 0x32, 0x18, 0xf5, 0xea, + 0xdf, 0xc3, 0x2d, 0x7f, 0x57, 0x1c, 0xf9, 0x5b, 0xf0, 0xd8, 0xe3, 0x97, + 0xf3, 0x6a, 0x2d, 0x20, 0xe7, 0x43, 0xf1, 0x94, 0xde, 0x00, 0x9e, 0x12, + 0x9c, 0xeb, 0xa1, 0xa5, 0x2f, 0xf2, 0x5e, 0x7e, 0x08, 0x7b, 0xb9, 0x51, + 0x8b, 0xe9, 0x95, 0x72, 0xf0, 0xdc, 0x3a, 0x64, 0xa2, 0xca, 0xb9, 0x81, + 0x5c, 0x44, 0x2c, 0x3c, 0xe6, 0xba, 0xe4, 0x60, 0x11, 0xbf, 0xa9, 0x58, + 0x52, 0xa5, 0x47, 0xbd, 0x23, 0xf2, 0x0c, 0xbe, 0x1b, 0x3f, 0xcc, 0x1c, + 0x18, 0xf2, 0x13, 0x76, 0xa6, 0x43, 0x0e, 0x1f, 0xbe, 0xcc, 0xbf, 0x8d, + 0x39, 0xd7, 0x92, 0x8b, 0xca, 0x6b, 0xa5, 0x4b, 0xfd, 0xd0, 0x41, 0xe6, + 0x6f, 0x0e, 0x2f, 0xad, 0xb3, 0x41, 0xc4, 0x53, 0xda, 0xdb, 0x74, 0xa1, + 0xd8, 0x0c, 0x83, 0xf5, 0xf8, 0x4b, 0x79, 0x38, 0x4f, 0x42, 0x70, 0x9e, + 0x9f, 0x3a, 0xc2, 0xe6, 0x44, 0x4f, 0xb3, 0x38, 0x9c, 0x53, 0x55, 0xfc, + 0xa9, 0x72, 0xaa, 0x6f, 0x8f, 0x3a, 0x10, 0xa7, 0xe6, 0xc7, 0x04, 0xe6, + 0x1f, 0xfa, 0x9c, 0x5a, 0x87, 0xd0, 0xeb, 0x10, 0xf3, 0x87, 0x76, 0x8d, + 0x06, 0x6b, 0xb0, 0x66, 0x13, 0x2f, 0x50, 0x2b, 0xb1, 0x7f, 0xc9, 0xd1, + 0x0a, 0x9d, 0xed, 0x69, 0xa6, 0xf3, 0x9e, 0x08, 0xd4, 0x79, 0x83, 0x72, + 0xa4, 0xcc, 0x80, 0x1c, 0x29, 0x37, 0x0e, 0x75, 0x17, 0x0e, 0xe3, 0x2e, + 0x2e, 0x30, 0xc0, 0xdc, 0xb9, 0x8b, 0xf1, 0x04, 0xee, 0x1c, 0xa5, 0xd0, + 0x07, 0x6e, 0xee, 0xec, 0xf7, 0x13, 0x49, 0x5c, 0xfe, 0xdb, 0xdc, 0xa9, + 0xa0, 0x7e, 0x27, 0x7c, 0xfd, 0x86, 0x1c, 0x9f, 0x6c, 0xc8, 0x13, 0x82, + 0x38, 0xfe, 0x4e, 0xf7, 0xd3, 0xbb, 0xf6, 0xd1, 0xa6, 0x09, 0xfd, 0x70, + 0x74, 0xb1, 0xba, 0xee, 0x5f, 0xf0, 0xd9, 0xb9, 0xc1, 0x67, 0x43, 0xc2, + 0x27, 0xd7, 0x25, 0xf6, 0x90, 0x9d, 0x93, 0x61, 0x9d, 0x1e, 0x19, 0x66, + 0xf7, 0xd4, 0xec, 0xfc, 0x88, 0x21, 0xec, 0x73, 0x74, 0x0e, 0xb9, 0xef, + 0x14, 0x1a, 0xc6, 0xa5, 0xe2, 0x3b, 0xe9, 0x1b, 0x38, 0x77, 0x04, 0xb2, + 0x1b, 0xf2, 0xfc, 0xf4, 0x6c, 0xd8, 0x34, 0x1c, 0x1f, 0x03, 0xfc, 0x08, + 0xc0, 0xa9, 0x7a, 0x7e, 0x90, 0x0d, 0x3d, 0x68, 0x0e, 0x87, 0x7c, 0x73, + 0x28, 0xf1, 0x06, 0x6e, 0x8f, 0x58, 0xbc, 0x83, 0x9e, 0x38, 0xc5, 0x9d, + 0x18, 0x93, 0xee, 0x80, 0x78, 0x41, 0xc4, 0xfa, 0xf9, 0xfa, 0xcb, 0xef, + 0x7c, 0x51, 0xf3, 0xaf, 0xad, 0x49, 0x6d, 0xba, 0x3c, 0xad, 0x4d, 0x15, + 0x51, 0xee, 0xa2, 0x56, 0xdb, 0x97, 0x36, 0x5d, 0x1c, 0x11, 0x7c, 0x30, + 0x79, 0xad, 0x42, 0x78, 0x4f, 0xdb, 0xbe, 0x25, 0xb8, 0xed, 0x80, 0x0f, + 0xab, 0x8a, 0x73, 0x18, 0x2d, 0xbc, 0x97, 0xb4, 0xbd, 0xb8, 0xb9, 0x8e, + 0x5b, 0xbe, 0x3f, 0x1d, 0x20, 0xdf, 0x9b, 0xd9, 0x0a, 0x91, 0xbf, 0x29, + 0xe2, 0xb2, 0xa9, 0x68, 0x21, 0xde, 0xf1, 0x30, 0xe2, 0x7b, 0xe1, 0xd7, + 0xa8, 0x62, 0xe1, 0x6e, 0x30, 0x16, 0xaa, 0xf6, 0x60, 0x1d, 0xb9, 0xa3, + 0x2c, 0x8b, 0xc3, 0xe9, 0x5e, 0x0a, 0x99, 0x28, 0xff, 0x6c, 0xe2, 0x3e, + 0x1d, 0x73, 0x78, 0x09, 0xfc, 0x3c, 0xb2, 0xde, 0x4c, 0x0b, 0x76, 0xe1, + 0x60, 0x7f, 0x46, 0x84, 0x65, 0xf3, 0x67, 0xbd, 0xad, 0xf9, 0x33, 0x54, + 0x39, 0xd4, 0xed, 0xa2, 0x35, 0x0b, 0x71, 0x92, 0xf0, 0x2f, 0x75, 0x77, + 0xb4, 0x9b, 0x41, 0xf2, 0x4f, 0xc5, 0x7e, 0x82, 0x1f, 0xc9, 0xb9, 0xba, + 0x41, 0x98, 0x3b, 0x9b, 0xbe, 0x6f, 0x30, 0x57, 0xdb, 0xb1, 0x29, 0x37, + 0x9f, 0x2b, 0xc3, 0x33, 0x57, 0xd8, 0x8b, 0x9a, 0xcd, 0x95, 0xf2, 0x43, + 0x2a, 0xdf, 0xdc, 0x51, 0xc8, 0x93, 0x45, 0xf7, 0x5c, 0xed, 0x8c, 0x7f, + 0x4e, 0xce, 0xd9, 0x4e, 0xfb, 0xe0, 0x1a, 0x8f, 0x43, 0x34, 0xd0, 0x76, + 0x12, 0x2c, 0x33, 0xfc, 0x6b, 0xeb, 0x86, 0x5c, 0x5b, 0xcc, 0x2b, 0x9e, + 0x6f, 0xb8, 0xb6, 0xb0, 0x0f, 0x5c, 0x70, 0xf6, 0x81, 0xd3, 0x3e, 0x7d, + 0x51, 0xd9, 0xbc, 0xff, 0xab, 0xed, 0x0d, 0xcf, 0x7d, 0x22, 0xce, 0xe9, + 0xc8, 0x91, 0xdc, 0x47, 0xce, 0x37, 0xe4, 0x61, 0x3d, 0xdb, 0x5c, 0xa7, + 0x6a, 0xee, 0x91, 0x73, 0x01, 0x79, 0x99, 0xa5, 0xf3, 0xf9, 0xc7, 0x06, + 0x75, 0xf7, 0x53, 0xa4, 0x1a, 0xd3, 0x72, 0x40, 0xf0, 0x61, 0xb7, 0xbe, + 0xbc, 0xec, 0xe4, 0x28, 0xe6, 0x5c, 0x63, 0xb0, 0x9c, 0xcf, 0x36, 0x89, + 0xa7, 0x6f, 0x25, 0x9e, 0x63, 0xc0, 0x23, 0x37, 0xbd, 0x73, 0x35, 0xa1, + 0x65, 0xf2, 0xa8, 0xb3, 0x87, 0xce, 0xea, 0x9f, 0xf0, 0x18, 0x3d, 0xb1, + 0x23, 0xe2, 0x9c, 0x11, 0xe0, 0xd2, 0xb6, 0x97, 0xcd, 0x0e, 0x5a, 0x94, + 0x7e, 0x46, 0x9a, 0xfa, 0xf8, 0x12, 0x15, 0x85, 0x7f, 0x0b, 0xb9, 0x51, + 0xb0, 0x71, 0xc3, 0x47, 0x87, 0xe7, 0xf0, 0xf7, 0x1b, 0x13, 0x8e, 0xcc, + 0xfd, 0x93, 0x31, 0x8c, 0x7a, 0x38, 0x0b, 0x01, 0xeb, 0x9d, 0x34, 0xc9, + 0x31, 0xb9, 0x1d, 0x71, 0x4e, 0x80, 0x8c, 0xcd, 0xbb, 0x5d, 0xde, 0x8e, + 0x4f, 0xa1, 0x55, 0xbd, 0xe4, 0xeb, 0x68, 0xd8, 0xfc, 0x72, 0xcf, 0xf6, + 0x7d, 0x0a, 0x2a, 0x77, 0x5f, 0x71, 0x58, 0x75, 0x2d, 0x73, 0x69, 0xc1, + 0x99, 0xe7, 0xd7, 0x55, 0xde, 0x6d, 0x77, 0x40, 0xde, 0x6d, 0x88, 0xe6, + 0x84, 0xaf, 0x2e, 0x44, 0x39, 0x47, 0x37, 0x93, 0x9c, 0x5a, 0xd9, 0x6a, + 0x23, 0x4e, 0xfc, 0x29, 0xee, 0xdd, 0x39, 0xf9, 0x7c, 0x5f, 0x04, 0xcf, + 0x46, 0x4e, 0xb5, 0x2d, 0x62, 0xf1, 0x33, 0xa2, 0x5c, 0xa7, 0xa7, 0x1c, + 0xdf, 0x17, 0xd5, 0x33, 0x3b, 0xb9, 0x7c, 0x8a, 0x64, 0x0e, 0x7d, 0x27, + 0xcd, 0x15, 0x9b, 0xf5, 0x6b, 0x1f, 0xe2, 0x81, 0xe3, 0xf0, 0x95, 0x0a, + 0xbf, 0x95, 0xa1, 0xfa, 0x80, 0x3e, 0xb5, 0x57, 0xfb, 0x04, 0xf9, 0x14, + 0x12, 0x7e, 0x05, 0xbe, 0x76, 0xda, 0x99, 0x23, 0x77, 0xbf, 0xc2, 0xdc, + 0x2f, 0x3c, 0xa7, 0xd3, 0x55, 0xb6, 0xd3, 0x55, 0xb6, 0x36, 0x5e, 0x3a, + 0xeb, 0x54, 0x0b, 0xe5, 0x1f, 0x59, 0x2f, 0xfd, 0x56, 0xd8, 0xe6, 0xe6, + 0xb3, 0x06, 0x2d, 0xac, 0xf7, 0xf2, 0x27, 0xc6, 0x1f, 0x94, 0xdb, 0xcb, + 0xff, 0xdd, 0x9c, 0xa2, 0x5f, 0xc4, 0x02, 0xb6, 0xce, 0x07, 0x83, 0xf1, + 0x1f, 0xbc, 0x6e, 0x13, 0x01, 0xeb, 0xb6, 0xf9, 0xbe, 0x22, 0xf7, 0x93, + 0xe4, 0x95, 0x8a, 0x23, 0xaf, 0x36, 0x69, 0xd0, 0x27, 0xa7, 0x82, 0xd6, + 0x29, 0xfa, 0x78, 0xca, 0xe9, 0xe3, 0x9b, 0xa2, 0x3f, 0xe3, 0x54, 0xa8, + 0xe6, 0x0d, 0x1f, 0xe1, 0xeb, 0x98, 0xb2, 0xd1, 0x35, 0x90, 0xab, 0xdf, + 0x6c, 0x43, 0xc6, 0x04, 0x71, 0xb2, 0x03, 0x01, 0xfa, 0x80, 0xee, 0xd2, + 0x07, 0xe2, 0x55, 0x7d, 0x60, 0x45, 0xe8, 0x09, 0xbb, 0x1c, 0x1d, 0x34, + 0xd8, 0x16, 0x97, 0xcb, 0xe3, 0xcc, 0x1b, 0xd8, 0xf8, 0xa4, 0x1d, 0x7d, + 0xda, 0xaa, 0x9e, 0x99, 0xc3, 0xba, 0x65, 0x8d, 0x4b, 0xfb, 0xe5, 0x09, + 0xce, 0xac, 0xa8, 0xcc, 0x3e, 0x30, 0xa3, 0xa4, 0xa5, 0x93, 0xf1, 0xa9, + 0x50, 0x84, 0x16, 0xac, 0x28, 0x15, 0xac, 0x14, 0x73, 0x70, 0xf0, 0xe3, + 0xd0, 0x80, 0x46, 0x11, 0x96, 0x35, 0x11, 0x2a, 0x95, 0x94, 0x4e, 0x76, + 0x86, 0xc8, 0x2c, 0xc6, 0xa4, 0x0d, 0x9b, 0x71, 0x9a, 0x1f, 0x33, 0xe6, + 0x49, 0x43, 0xcc, 0x8b, 0x93, 0xa3, 0x0e, 0x0c, 0x8a, 0x38, 0x4b, 0xfd, + 0xe5, 0x91, 0x28, 0xb5, 0xa7, 0xa5, 0xcd, 0x68, 0x86, 0xdb, 0xf8, 0xc2, + 0x8a, 0xd1, 0x95, 0x7c, 0xd2, 0x38, 0xc1, 0xed, 0x64, 0xac, 0x64, 0x62, + 0x92, 0x9f, 0x5d, 0x2c, 0x45, 0x28, 0x67, 0x45, 0xa8, 0x50, 0x4a, 0x19, + 0x43, 0x6d, 0xa2, 0xcd, 0x18, 0xda, 0x7c, 0x49, 0x1f, 0x33, 0x4e, 0x92, + 0xbb, 0xcd, 0xaf, 0x9c, 0x36, 0xbd, 0x6d, 0xfd, 0x61, 0xe3, 0xfe, 0x44, + 0xa8, 0x32, 0x7b, 0x9f, 0xf1, 0x92, 0x5b, 0x9d, 0x60, 0xd9, 0x14, 0x13, + 0x67, 0xdb, 0x68, 0xe9, 0x34, 0xcb, 0x1d, 0x9c, 0x6d, 0x61, 0xd0, 0x62, + 0x39, 0x4e, 0xef, 0x57, 0xed, 0x07, 0x12, 0x43, 0x39, 0x91, 0x43, 0x84, + 0x33, 0x17, 0x2a, 0xb3, 0xbf, 0x9b, 0x5e, 0x7f, 0x3f, 0xeb, 0x5b, 0x1f, + 0xc5, 0x28, 0x72, 0x15, 0x71, 0xdd, 0x36, 0x5d, 0x1b, 0x4f, 0x5e, 0xd9, + 0x14, 0x79, 0x68, 0x09, 0x5a, 0x33, 0xa5, 0x3c, 0xcd, 0x71, 0xf9, 0x15, + 0x94, 0x5b, 0x4b, 0xd0, 0x3d, 0x91, 0x8f, 0xd6, 0x4e, 0x77, 0xf4, 0x18, + 0x85, 0x6e, 0x9a, 0xc6, 0xbc, 0xf0, 0x0b, 0x57, 0x66, 0x87, 0x86, 0x0d, + 0xd2, 0xae, 0xa2, 0x1e, 0xff, 0xbf, 0x89, 0xfb, 0x28, 0x61, 0x7e, 0x66, + 0xac, 0x31, 0x5e, 0x49, 0xc3, 0xf1, 0x12, 0x64, 0xf3, 0x41, 0x89, 0xa5, + 0x39, 0x23, 0x42, 0xd0, 0x5f, 0x61, 0x7b, 0xeb, 0x35, 0x27, 0x7b, 0xa4, + 0xfe, 0xe4, 0x3b, 0x9b, 0x43, 0x9f, 0x19, 0x71, 0x9f, 0xcf, 0x51, 0x7b, + 0x66, 0xc6, 0x92, 0xef, 0xb9, 0x52, 0xee, 0xa5, 0x25, 0x6e, 0x7b, 0x64, + 0xf8, 0x8c, 0x73, 0xa6, 0x0f, 0xff, 0xd9, 0x8b, 0x7b, 0x85, 0xb7, 0x7d, + 0x7d, 0x14, 0xc5, 0x3d, 0x0d, 0xe8, 0x3c, 0xc7, 0xb0, 0xe9, 0x87, 0xc5, + 0xb8, 0xa7, 0xe2, 0x98, 0xcb, 0xb9, 0xb8, 0x3a, 0x97, 0x08, 0x65, 0xba, + 0xe9, 0x91, 0xd5, 0x45, 0x3f, 0x8b, 0xf3, 0x47, 0xf8, 0xba, 0x84, 0x9c, + 0xa3, 0x36, 0xca, 0x64, 0xbb, 0x69, 0xb3, 0x14, 0x66, 0x71, 0x05, 0xec, + 0x44, 0xb9, 0x4c, 0x81, 0xa6, 0xd6, 0x5f, 0xeb, 0x83, 0x1f, 0x66, 0x52, + 0xab, 0x61, 0xe9, 0x51, 0x00, 0x96, 0x7e, 0xa9, 0xc3, 0xd2, 0xd1, 0xbe, + 0xe6, 0x58, 0xea, 0x77, 0x62, 0xd6, 0xa3, 0x14, 0x71, 0x70, 0xf4, 0x39, + 0xe3, 0xe8, 0x3d, 0xc6, 0xd1, 0xf1, 0x06, 0x38, 0xd2, 0x3c, 0x38, 0x3a, + 0x51, 0x87, 0xa3, 0x6c, 0x5f, 0x33, 0x1c, 0x1d, 0x0f, 0xa1, 0xff, 0xcd, + 0xd6, 0x32, 0xfa, 0xb0, 0x9f, 0x39, 0xbd, 0x49, 0xa5, 0xd5, 0xe4, 0xf8, + 0x24, 0x55, 0x90, 0x73, 0x92, 0x58, 0xa2, 0xb4, 0xe0, 0x76, 0x05, 0x81, + 0xbf, 0x2c, 0x8f, 0xc9, 0xae, 0x06, 0xe7, 0xaa, 0x24, 0x9c, 0x79, 0x93, + 0x73, 0x99, 0xc9, 0x57, 0x66, 0x1f, 0x32, 0x36, 0xee, 0x6d, 0xe8, 0x3a, + 0x7e, 0x0b, 0xb1, 0x8c, 0xbc, 0xbb, 0x81, 0x73, 0x5b, 0xe2, 0x74, 0xdf, + 0x1a, 0xa0, 0x7b, 0xd6, 0x7e, 0xba, 0x6b, 0x0d, 0xd2, 0x03, 0x0b, 0x6d, + 0x60, 0x0e, 0xf8, 0x5e, 0xcc, 0x81, 0x46, 0x33, 0x31, 0x2e, 0x53, 0xda, + 0x4f, 0x95, 0x92, 0xc2, 0x35, 0xb0, 0x03, 0x0c, 0x35, 0xc6, 0x4e, 0xa6, + 0x0e, 0x3b, 0xb2, 0x0e, 0x30, 0xb3, 0xe4, 0xb7, 0xad, 0xed, 0x32, 0xf8, + 0x5d, 0x0d, 0xc6, 0x56, 0x58, 0xc4, 0x91, 0x24, 0x47, 0x67, 0x42, 0x90, + 0x59, 0xb7, 0x18, 0x53, 0x3c, 0x17, 0x3c, 0x7e, 0xda, 0xf5, 0x41, 0x96, + 0x39, 0x4f, 0x09, 0x1b, 0xf4, 0x94, 0xa9, 0xc7, 0x33, 0x64, 0x5f, 0xd6, + 0xcc, 0x31, 0x91, 0xeb, 0xb6, 0x54, 0xf6, 0x9e, 0x31, 0x91, 0xe1, 0xb1, + 0x57, 0x78, 0xf4, 0xca, 0xa1, 0x76, 0xaa, 0x38, 0x31, 0x4c, 0x85, 0x55, + 0xdb, 0x7e, 0xc8, 0xfc, 0x7f, 0xcd, 0x84, 0xcc, 0xfe, 0xdb, 0xae, 0xc4, + 0x74, 0x5a, 0x36, 0x55, 0xdf, 0xee, 0x08, 0x7c, 0x31, 0x47, 0xa4, 0x77, + 0x37, 0xaa, 0xaf, 0xc4, 0xbf, 0xe3, 0xbb, 0xbf, 0x04, 0x97, 0x59, 0xab, + 0x96, 0x85, 0xed, 0xf8, 0xd2, 0xd8, 0xc2, 0x2a, 0xce, 0x7e, 0x7b, 0xfc, + 0xea, 0xf9, 0xd5, 0x5c, 0x1f, 0x4b, 0xd8, 0x94, 0x4e, 0x76, 0x68, 0x79, + 0x3c, 0xf7, 0x5c, 0x98, 0x86, 0x19, 0x97, 0x38, 0x83, 0x6b, 0x6c, 0x34, + 0x2c, 0xce, 0x38, 0xd9, 0xcd, 0x78, 0xc8, 0x0a, 0x3b, 0xfd, 0xd4, 0x91, + 0x09, 0x9a, 0x2c, 0xa7, 0xf9, 0x53, 0x3f, 0x7e, 0xb5, 0xb9, 0xe3, 0xe1, + 0x48, 0xe3, 0x37, 0x37, 0xff, 0xa8, 0xd5, 0x9d, 0xe6, 0xba, 0x33, 0x5b, + 0xd6, 0x55, 0xe7, 0x12, 0xfd, 0x03, 0x69, 0xae, 0x1b, 0xa3, 0xbc, 0x57, + 0x00, 0x00, 0x00 }; static u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x0 }; static u32 bnx2_COM_b06FwRodata[(0x58/4) + 1] = { @@ -989,952 +687,368 @@ static u32 bnx2_RXP_b06FwBssAddr = 0x080 static int bnx2_RXP_b06FwBssLen = 0x13a4; static u32 bnx2_RXP_b06FwSbssAddr = 0x080058e0; static int bnx2_RXP_b06FwSbssLen = 0x1c; -static u32 bnx2_RXP_b06FwText[(0x588c/4) + 1] = { - 0x0a000c61, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x322e362e, - 0x31000000, 0x02060103, 0x00000000, 0x0000000d, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, - 0x3c020800, 0x244258e0, 0x3c030800, 0x24636ca4, 0xac400000, 0x0043202b, - 0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, - 0x26103184, 0x3c1c0800, 0x279c58e0, 0x0e00104a, 0x00000000, 0x0000000d, - 0x27bdffe8, 0xafb00010, 0xafbf0014, 0x0e000f1d, 0x00808021, 0x1440000d, - 0x00000000, 0x8f820010, 0x10400005, 0x00000000, 0x9743011c, 0x9742011e, - 0x0a000c89, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, - 0xaf830004, 0x8f840008, 0x3c020020, 0x34424000, 0x00821824, 0x54620004, - 0x3c020020, 0x8f820014, 0x0a000c9a, 0x34421000, 0x34428000, 0x00821824, - 0x14620004, 0x00000000, 0x8f820014, 0x34428000, 0xaf820014, 0x8f820008, - 0x9743010c, 0x00403021, 0x30421000, 0x10400010, 0x3069ffff, 0x30c20020, - 0x1440000e, 0x24070005, 0x3c021000, 0x00c21024, 0x10400009, 0x3c030dff, - 0x3463ffff, 0x3c020e00, 0x00c21024, 0x0062182b, 0x50600004, 0x24070001, - 0x0a000cb2, 0x3c020800, 0x24070001, 0x3c020800, 0x8c430034, 0x1460001d, - 0x00405821, 0x8f820014, 0x30424000, 0x1440001a, 0x3c020001, 0x3c021f01, - 0x00c24024, 0x3c031000, 0x15030015, 0x3c020001, 0x31220200, 0x14400012, - 0x3c020001, 0x9744010e, 0x24020003, 0xa342018b, 0x97850016, 0x24020002, - 0x34e30002, 0xaf400180, 0xa742018c, 0xa7430188, 0x24840004, 0x30a5bfff, - 0xa744018e, 0xa74501a6, 0xaf4801b8, 0x0a000f19, 0x00001021, 0x3c020001, - 0x00c21024, 0x1040002f, 0x00000000, 0x9742010e, 0x3c038000, 0x3046ffff, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9784000a, - 0x8f850004, 0x8f870014, 0x24020080, 0x24030002, 0xaf420180, 0x24020003, - 0xa743018c, 0xa746018e, 0xa7420188, 0x30e28000, 0xa7440190, 0x1040000c, - 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, - 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014, - 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, - 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, - 0x00001021, 0x8f820014, 0x30434000, 0x10600016, 0x00404021, 0x3c020f00, - 0x00c21024, 0x14400012, 0x00000000, 0x93420116, 0x34424000, 0x03421821, - 0x94650002, 0x2ca21389, 0x1040000b, 0x3c020800, 0x24425900, 0x00051942, - 0x00031880, 0x00621821, 0x30a5001f, 0x8c640000, 0x24020001, 0x00a21004, - 0x00822024, 0x02048025, 0x12000030, 0x3c021000, 0x9742010e, 0x34e80002, - 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180, - 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000, - 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, - 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, - 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, - 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, - 0xaf4201b8, 0x0a000f19, 0x00001021, 0x00c21024, 0x104000c0, 0x3c020800, - 0x8c430030, 0x10600037, 0x31024000, 0x10400035, 0x3c030f00, 0x00c31824, - 0x3c020100, 0x0043102b, 0x14400031, 0x3c030800, 0x9742010e, 0x34e80002, - 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020080, - 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000, - 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, - 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, - 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, - 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, - 0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800, 0x8c620024, 0x30420008, - 0x10400035, 0x34ea0002, 0x3c020f00, 0x00c21024, 0x14400032, 0x8d620034, - 0x31220200, 0x1040002f, 0x8d620034, 0x9742010e, 0x30e8fffb, 0x3c038000, - 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, - 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180, 0x24030002, - 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000, 0xa7440190, - 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, - 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024, - 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, - 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, - 0x8d620034, 0x8f860008, 0x10400012, 0x30c20100, 0x10400010, 0x3c020f00, - 0x00c21024, 0x3c030200, 0x1043000c, 0x3c020800, 0x8c430038, 0x8f840004, - 0x3c020800, 0x2442003c, 0x2463ffff, 0x00832024, 0x00822021, 0x90830000, - 0x24630004, 0x0a000de1, 0x000329c0, 0x00000000, 0x00061602, 0x3042000f, - 0x000229c0, 0x3c04fc00, 0x00441021, 0x3c030300, 0x0062182b, 0x50600001, - 0x24050800, 0x9742010e, 0x3148ffff, 0x3c038000, 0x24420004, 0x3046ffff, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a, - 0x8f840004, 0x8f870014, 0x24020002, 0xaf450180, 0xa742018c, 0xa746018e, - 0xa7480188, 0x30e28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, - 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, - 0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, - 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, - 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x8f424000, - 0x30420100, 0x104000d5, 0x3c020800, 0x8c440024, 0x24030001, 0x1483002f, - 0x00405021, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3045ffff, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a, - 0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c, 0xa745018e, - 0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, - 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, - 0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016, 0x9743010c, - 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, - 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x30820001, - 0x1040002e, 0x30eb0004, 0x9742010e, 0x30e9fffb, 0x3c038000, 0x24420004, - 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, - 0x9783000a, 0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c, - 0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8, - 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, - 0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016, - 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, - 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x3127ffff, 0x8d420024, - 0x30420004, 0x10400030, 0x8d420024, 0x9742010e, 0x30e9fffb, 0x3c038000, - 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, - 0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020100, 0x24030002, - 0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000, 0xa7440190, - 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, - 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x01021024, - 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, - 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, - 0x3127ffff, 0x8d420024, 0x30420008, 0x1040002d, 0x00000000, 0x9742010e, - 0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020180, - 0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000, - 0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, - 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, - 0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, - 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, - 0xaf4201b8, 0x15600041, 0x00001021, 0x27440180, 0x3c038000, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b, - 0xa4800010, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800, - 0x8c620024, 0x30420001, 0x1040002e, 0x00001021, 0x9742010e, 0x34e70002, - 0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x24020003, 0xa342018b, 0x9783000a, 0x8f840004, 0x8f860014, 0x24020002, - 0xaf400180, 0xa742018c, 0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190, - 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, - 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024, - 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, - 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, - 0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x8f4b0070, - 0x93420112, 0x8f840008, 0x00022882, 0x30820100, 0x14400003, 0x24a30003, - 0x03e00008, 0x00001021, 0x30824000, 0x10400010, 0x27424000, 0x00031880, - 0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021, - 0x8c490000, 0x93430116, 0x27424000, 0x306300fc, 0x00431021, 0x8c4a0000, - 0x0a000f45, 0x3c030800, 0x30822000, 0x1040ffea, 0x00031880, 0x27424000, - 0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021, - 0x8c490000, 0x00005021, 0x3c030800, 0x24680100, 0x00071602, 0x00021080, - 0x00481021, 0x8c460000, 0x00071b82, 0x306303fc, 0x01031821, 0x8c640400, - 0x00071182, 0x304203fc, 0x01021021, 0x8c450800, 0x30e300ff, 0x00031880, - 0x01031821, 0x00091602, 0x00021080, 0x01021021, 0x00c43026, 0x8c640c00, - 0x8c431000, 0x00c53026, 0x00091382, 0x304203fc, 0x01021021, 0x8c451400, - 0x312200ff, 0x00021080, 0x01021021, 0x00c43026, 0x00c33026, 0x00091982, - 0x306303fc, 0x01031821, 0x8c641800, 0x8c431c00, 0x00c53026, 0x00c43026, - 0x11400015, 0x00c33026, 0x000a1602, 0x00021080, 0x01021021, 0x8c432000, - 0x000a1382, 0x304203fc, 0x01021021, 0x8c452400, 0x314200ff, 0x00021080, - 0x01021021, 0x00c33026, 0x000a1982, 0x306303fc, 0x01031821, 0x8c642800, - 0x8c432c00, 0x00c53026, 0x00c43026, 0x00c33026, 0x8f430070, 0x3c050800, - 0x8ca43100, 0x2c820020, 0x10400008, 0x006b5823, 0x3c020800, 0x24423104, - 0x00041880, 0x00621821, 0x24820001, 0xac6b0000, 0xaca23100, 0xaf860004, - 0x03e00008, 0x24020001, 0x27bdffe8, 0xafbf0010, 0x8f460128, 0x8f840010, - 0xaf460020, 0x8f450104, 0x8f420100, 0x24030800, 0xaf850008, 0xaf820014, - 0xaf4301b8, 0x1080000a, 0x3c020800, 0x8c430034, 0x10600007, 0x30a22000, - 0x10400005, 0x34a30100, 0x8f82000c, 0xaf830008, 0x24420001, 0xaf82000c, - 0x3c020800, 0x8c4300c0, 0x10600006, 0x3c030800, 0x8c6200c4, 0x24040001, - 0x24420001, 0x0a000fd5, 0xac6200c4, 0x8f820008, 0x3c030010, 0x00431024, - 0x14400009, 0x3c02001f, 0x3c030800, 0x8c620020, 0x00002021, 0x24420001, - 0x0e000c78, 0xac620020, 0x0a000fd5, 0x00402021, 0x3442ff00, 0x14c20009, - 0x2403bfff, 0x3c030800, 0x8c620020, 0x24040001, 0x24420001, 0x0e000c78, - 0xac620020, 0x0a000fd5, 0x00402021, 0x8f820014, 0x00431024, 0x14400006, - 0x00000000, 0xaf400048, 0x0e0011a9, 0xaf400040, 0x0a000fd5, 0x00402021, - 0x0e001563, 0x00000000, 0x00402021, 0x10800005, 0x3c024000, 0x8f430124, - 0x3c026020, 0xac430014, 0x3c024000, 0xaf420138, 0x00000000, 0x8fbf0010, - 0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010, - 0x8f420140, 0xaf420020, 0x8f430148, 0x3c027000, 0x00621824, 0x3c023000, - 0x10620021, 0x0043102b, 0x14400006, 0x3c024000, 0x3c022000, 0x10620009, - 0x3c024000, 0x0a001040, 0x00000000, 0x10620045, 0x3c025000, 0x10620047, - 0x3c024000, 0x0a001040, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x00000000, 0x8f420148, 0x24030002, 0xa083000b, - 0x00021402, 0xa4820008, 0x8f430148, 0xa4830010, 0x8f420144, 0x3c031000, - 0xac820024, 0xaf4301b8, 0x0a001040, 0x3c024000, 0x8f420148, 0x24030002, - 0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003, - 0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001027, 0x3c038000, - 0x12020007, 0x00000000, 0x0a001034, 0x00000000, 0x0e00112c, 0x00000000, - 0x0a001025, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000, - 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008, - 0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8, - 0x0a001040, 0x3c024000, 0x0000000d, 0x00000000, 0x240002bf, 0x0a001040, - 0x3c024000, 0x0e001441, 0x00000000, 0x0a001040, 0x3c024000, 0x0e0015ea, - 0x00000000, 0x3c024000, 0xaf420178, 0x00000000, 0x8fbf0018, 0x8fb10014, - 0x8fb00010, 0x03e00008, 0x27bd0020, 0x24020800, 0x03e00008, 0xaf4201b8, - 0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, - 0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000, - 0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800, - 0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001, - 0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000, - 0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c, - 0x8e021980, 0x34420200, 0xae021980, 0x8f500000, 0x32020003, 0x1040fffd, - 0x32020001, 0x10400004, 0x32020002, 0x0e000f92, 0x00000000, 0x32020002, - 0x1040fff6, 0x00000000, 0x0e000fe0, 0x00000000, 0x0a001071, 0x00000000, - 0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, - 0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000, - 0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800, - 0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001, - 0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000, - 0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c, - 0x8e021980, 0x8fbf0014, 0x34420200, 0xae021980, 0x8fb00010, 0x03e00008, - 0x27bd0018, 0x00804821, 0x30a5ffff, 0x30c6ffff, 0x30e7ffff, 0x3c038000, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a, - 0x8f840004, 0x8f880014, 0xaf490180, 0xa745018c, 0xa746018e, 0xa7470188, - 0x31028000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc, - 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, - 0x34427fff, 0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, - 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, - 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, - 0xa083000b, 0xa4800010, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, - 0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, - 0x8f420148, 0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148, - 0xa4830010, 0x8f420144, 0x3c031000, 0xac820024, 0x03e00008, 0xaf4301b8, - 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002, - 0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003, - 0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001117, 0x3c038000, - 0x12020007, 0x00000000, 0x0a001124, 0x00000000, 0x0e00112c, 0x00000000, - 0x0a001115, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000, - 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008, - 0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8, - 0x0a001128, 0x8fbf0018, 0x0000000d, 0x00000000, 0x240002bf, 0x8fbf0018, - 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389, - 0x1040000d, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880, - 0x00a32821, 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025, - 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389, - 0x1040000e, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880, - 0x00a32821, 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827, - 0x00832024, 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x9482000c, - 0x24870014, 0x00021302, 0x00021080, 0x00824021, 0x00e8182b, 0x1060004f, - 0x00000000, 0x90e30000, 0x2c620009, 0x10400047, 0x3c020800, 0x24425890, - 0x00031880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000, 0x0a0011a4, - 0x24e70001, 0x90e30001, 0x2402000a, 0x54620024, 0x01003821, 0x01071023, - 0x2c42000a, 0x54400020, 0x01003821, 0x3c050800, 0x8ca26c98, 0x24e70002, - 0x34420100, 0xaca26c98, 0x90e30000, 0x90e20001, 0x90e40002, 0x90e60003, - 0x24e70004, 0x24a56c98, 0x00031e00, 0x00021400, 0x00621825, 0x00042200, - 0x00641825, 0x00661825, 0xaca30004, 0x90e20000, 0x90e30001, 0x90e40002, - 0x90e60003, 0x24e70004, 0x00021600, 0x00031c00, 0x00431025, 0x00042200, - 0x00441025, 0x00461025, 0x0a0011a4, 0xaca20008, 0x90e30001, 0x24020004, - 0x1062000e, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020003, - 0x10620008, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020002, - 0x14620003, 0x01001021, 0x00601021, 0x00e21021, 0x0a0011a4, 0x00403821, - 0x90e20001, 0x0a0011a4, 0x00e23821, 0x01003821, 0x00e8102b, 0x5440ffb4, - 0x90e30000, 0x03e00008, 0x24020001, 0x27bdff90, 0x3c030800, 0xafbf006c, - 0xafbe0068, 0xafb70064, 0xafb60060, 0xafb5005c, 0xafb40058, 0xafb30054, - 0xafb20050, 0xafb1004c, 0xafb00048, 0xac606c98, 0x93620023, 0x30420010, - 0x1440027c, 0x24020001, 0x93420116, 0x93630005, 0x34424000, 0x30630001, - 0x14600005, 0x0342b021, 0x0e0015e0, 0x00000000, 0x0a001436, 0x8fbf006c, - 0x93420112, 0x8f430104, 0x3c040020, 0x34424000, 0x00641824, 0x10600012, - 0x03422821, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040, 0x24030008, 0x240240c1, - 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000, 0x0a0011f1, 0xa0a3000a, - 0x8f420104, 0x3c030040, 0x00431024, 0x1040001d, 0x3c038000, 0x27450180, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, - 0x8f640040, 0x24030010, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a3000a, - 0x24030008, 0xa0a2000b, 0x3c021000, 0xa4a30010, 0xa0a00012, 0xa0a00013, - 0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, 0xaca40018, 0x0e0015e0, - 0xaf4201b8, 0x0a001436, 0x8fbf006c, 0x8f820000, 0x10400016, 0x00000000, - 0x8f420104, 0x3c030001, 0x00431024, 0x10400011, 0x00000000, 0x8ca3000c, - 0x8f620030, 0x1462022d, 0x24020001, 0x8ca30010, 0x8f62002c, 0x14620229, - 0x24020001, 0x9763003a, 0x96c20000, 0x14430225, 0x24020001, 0x97630038, - 0x96c20002, 0x14430221, 0x24020001, 0xaf400048, 0xaf400054, 0xaf400040, - 0x8f740040, 0x8f650048, 0x00b43023, 0x04c10004, 0x00000000, 0x0000000d, - 0x00000000, 0x240001af, 0x9742011a, 0x3052ffff, 0x12400004, 0x8ed30004, - 0x02721021, 0x0a001228, 0x2451ffff, 0x02608821, 0x92d7000d, 0xa7a00020, - 0xa3a0001a, 0xafa00028, 0x9362003f, 0x32e30004, 0x1060003a, 0x305000ff, - 0x24040012, 0x16040006, 0x24020001, 0x3c040800, 0x8c830028, 0x24630001, - 0x0a001328, 0xac830028, 0x8f620044, 0x16620010, 0x27a60010, 0x27450180, - 0x3c038000, 0x2402001a, 0xa7a20020, 0x24020020, 0xafb40028, 0xa3b00022, - 0xa3a40023, 0xa3a2001a, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, - 0x0a00130d, 0x00000000, 0x8f620044, 0x02621023, 0x0440001a, 0x02651023, - 0x044100d9, 0x24020001, 0x3c020800, 0x8c4300d8, 0x10600004, 0x24020001, - 0xa7a20020, 0x0a00125e, 0xafb40028, 0x2402001a, 0xa7a20020, 0x24020020, - 0xafb40028, 0xa3b00022, 0xa3a40023, 0xa3a2001a, 0x27a60010, 0x27450180, - 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, - 0x00000000, 0x0a001328, 0x24020001, 0x0293f023, 0x1bc00016, 0x025e102a, - 0x54400007, 0x32f700fe, 0x57d2000f, 0x027e9821, 0x32e20001, 0x5440000c, - 0x027e9821, 0x32f700fe, 0x0240f021, 0x3c040800, 0x8c8300c8, 0x00009021, - 0x24020001, 0xa7a20020, 0xafb40028, 0x24630001, 0x0a001282, 0xac8300c8, - 0x025e1023, 0x0a001282, 0x3052ffff, 0x0000f021, 0x24a2ffff, 0x02221823, - 0x1860001f, 0x0072102a, 0x54400019, 0x00a08821, 0x97a20020, 0x3c040800, - 0x8c8300cc, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020, 0x02741026, - 0x2c420001, 0xac8300cc, 0x2cc30001, 0x00431024, 0x1440000a, 0x02401821, - 0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, - 0x00000000, 0x0a00130d, 0x00000000, 0x00a08821, 0x02431023, 0x3052ffff, - 0x0a0012ae, 0x32f700f6, 0x02741023, 0x18400008, 0x97a20020, 0x3c040800, - 0x8c8300d4, 0xafb30028, 0x34420400, 0x24630001, 0xa7a20020, 0xac8300d4, - 0x32e20002, 0x1040001c, 0x32e20010, 0x8f620044, 0x1662000d, 0x27a60010, - 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000, - 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000, - 0x54400003, 0x8ed50008, 0x0a001328, 0x24020001, 0x8f630054, 0x26a2ffff, - 0x00431023, 0x18400011, 0x27a60010, 0x97a20020, 0x3c040800, 0x8c8300d0, - 0x27450180, 0x3c078000, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020, - 0xac8300d0, 0x8f4201b8, 0x00471024, 0x1440fffd, 0x00000000, 0x0a00130d, - 0x00000000, 0x32e20020, 0x10400011, 0x00000000, 0x96c20012, 0x0052102b, - 0x10400008, 0x97a20020, 0x96d20012, 0x12400003, 0x02721021, 0x0a0012f2, - 0x2451ffff, 0x02608821, 0x97a20020, 0x93a3001a, 0x34420008, 0x34630004, - 0xa7a20020, 0xa3a3001a, 0x8f420104, 0x3c030080, 0x00431024, 0x10400037, - 0x3a03000a, 0x0e001151, 0x02c02021, 0x24030002, 0x1443002b, 0x3c030800, - 0x27a60010, 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, - 0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, - 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, 0x90c4000a, - 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, 0x90c30012, - 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, 0x8cc20024, - 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, 0x3c031000, - 0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a001436, 0x8fbf006c, - 0x8c626c98, 0x30420100, 0x10400003, 0x24636c98, 0x8c620004, 0xaf62017c, - 0x3a03000a, 0x2c630001, 0x3a02000c, 0x2c420001, 0x00621825, 0x14600003, - 0x2402000e, 0x56020030, 0x00009021, 0x52400008, 0x96c4000e, 0x12400004, - 0xa7b20040, 0x02721021, 0x0a001343, 0x2451ffff, 0x02608821, 0x96c4000e, - 0x93630035, 0x8f62004c, 0x00642004, 0x00952021, 0x00821023, 0x18400015, - 0x00000000, 0x8f620018, 0x02621023, 0x1c400015, 0x97a20020, 0x8f620018, - 0x1662001c, 0x00000000, 0x8f62001c, 0x02a21023, 0x1c40000e, 0x97a20020, - 0x8f62001c, 0x16a20015, 0x00000000, 0x8f620058, 0x00821023, 0x18400011, - 0x97a20020, 0x0a001364, 0xafb10028, 0x8f620058, 0x00821023, 0x0441000b, - 0x97a20020, 0xafb10028, 0xafb30034, 0xafb50038, 0xafa4003c, 0x34420020, - 0x0a00136d, 0xa7a20020, 0x02809821, 0x02608821, 0x8f640058, 0x8f62004c, - 0x02a21023, 0x18400009, 0x00000000, 0x8f620054, 0x02a21023, 0x1c400005, - 0x97a20020, 0xafb10028, 0xafb50024, 0x0a001385, 0x34420040, 0x9742011a, - 0x1440000c, 0x24020014, 0x8f620058, 0x14820009, 0x24020014, 0x8f63004c, - 0x8f620054, 0x10620004, 0x97a20020, 0xafb10028, 0x34420080, 0xa7a20020, - 0x24020014, 0x1202000a, 0x2a020015, 0x10400005, 0x2402000c, 0x12020006, - 0x32e20001, 0x0a0013c6, 0x00000000, 0x24020016, 0x16020035, 0x32e20001, - 0x8f620084, 0x24420001, 0x16a20031, 0x32e20001, 0x24020014, 0x12020021, - 0x2a020015, 0x10400005, 0x2402000c, 0x12020008, 0x32e20001, 0x0a0013c6, - 0x00000000, 0x24020016, 0x1202000c, 0x32e20001, 0x0a0013c6, 0x00000000, - 0x97a30020, 0x2402000e, 0xafb10028, 0xa3b00022, 0xa3a20023, 0xafb50024, - 0x34630054, 0x0a0013c5, 0xa7a30020, 0x97a20020, 0x93a4001a, 0x24030010, - 0xafb10028, 0xa3b00022, 0xa3a30023, 0xafb50024, 0x3442005d, 0x34840002, - 0xa7a20020, 0x0a0013c5, 0xa3a4001a, 0x97a20020, 0x24030012, 0xa3a30023, - 0x93a3001a, 0xafb10028, 0xa3b00022, 0xafb50024, 0x3042fffe, 0x3442005c, - 0x34630002, 0xa7a20020, 0xa3a3001a, 0x32e20001, 0x10400030, 0x2402000c, - 0x12020013, 0x2a02000d, 0x10400005, 0x2402000a, 0x12020008, 0x97a20020, - 0x0a0013f8, 0x32e20009, 0x2402000e, 0x1202001b, 0x32e20009, 0x0a0013f9, - 0x0002102b, 0x93a4001a, 0x24030008, 0xafb10028, 0xa3b00022, 0xa3a30023, - 0x0a0013f4, 0x34420013, 0x97a30020, 0x30620004, 0x14400005, 0x93a2001a, - 0x3463001b, 0xa7a30020, 0x0a0013e7, 0x24030016, 0x3463001b, 0xa7a30020, - 0x24030010, 0xafb10028, 0xa3b00022, 0xa3a30023, 0x34420002, 0x0a0013f7, - 0xa3a2001a, 0x97a20020, 0x93a4001a, 0x24030010, 0xafb10028, 0xa3b00022, - 0xa3a30023, 0x3442001b, 0x34840002, 0xa7a20020, 0xa3a4001a, 0x32e20009, - 0x0002102b, 0x00021023, 0x30420007, 0x12400015, 0x34450003, 0x8f820018, - 0x24030800, 0x27440180, 0x24420001, 0xaf820018, 0x24020004, 0xaf4301b8, - 0xa4850008, 0xa082000b, 0x93430120, 0x00003021, 0x3c021000, 0xa492000e, - 0xac950024, 0xac930028, 0x007e1821, 0xa483000c, 0xaf4201b8, 0x0a001413, - 0x97a20020, 0x24060001, 0x97a20020, 0x10400020, 0x27450180, 0x3c038000, - 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, - 0x8fa30028, 0x240240c1, 0xa4a20008, 0xaca30018, 0x93a4001a, 0x24020002, - 0xa0a2000b, 0xa0a4000a, 0x97a20020, 0xa4a20010, 0x93a30022, 0xa0a30012, - 0x93a20023, 0xa0a20013, 0x8fa30024, 0xaca30014, 0x8fa20034, 0xaca20024, - 0x8fa30038, 0xaca30028, 0x8fa2003c, 0x3c031000, 0xaca2002c, 0xaf4301b8, - 0x00c01021, 0x8fbf006c, 0x8fbe0068, 0x8fb70064, 0x8fb60060, 0x8fb5005c, - 0x8fb40058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, 0x03e00008, - 0x27bd0070, 0x8f470140, 0x8f460148, 0x3c028000, 0x00c24024, 0x00062c02, - 0x30a300ff, 0x24020019, 0x106200e7, 0x27440180, 0x2862001a, 0x1040001f, - 0x24020008, 0x106200be, 0x28620009, 0x1040000d, 0x24020001, 0x10620046, - 0x28620002, 0x50400005, 0x24020006, 0x1060002e, 0x00a01821, 0x0a00155e, - 0x00000000, 0x1062005b, 0x00a01821, 0x0a00155e, 0x00000000, 0x2402000b, - 0x10620084, 0x2862000c, 0x10400005, 0x24020009, 0x106200bc, 0x00061c02, - 0x0a00155e, 0x00000000, 0x2402000e, 0x106200b7, 0x00061c02, 0x0a00155e, - 0x00000000, 0x28620021, 0x10400009, 0x2862001f, 0x104000c1, 0x2402001b, - 0x106200bf, 0x2402001c, 0x1062009a, 0x00061c02, 0x0a00155e, 0x00000000, - 0x240200c2, 0x106200ca, 0x286200c3, 0x10400005, 0x24020080, 0x1062005a, - 0x00a01821, 0x0a00155e, 0x00000000, 0x240200c9, 0x106200cd, 0x30c5ffff, - 0x0a00155e, 0x00000000, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, - 0x24020001, 0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a, - 0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024, - 0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808, 0x11000009, 0x00a01821, - 0x3c020800, 0x24030002, 0xa0436c88, 0x24426c88, 0xac470008, 0x8f430144, - 0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, - 0x24020002, 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b, - 0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x3c026000, - 0xaf4301b8, 0x03e00008, 0xac400808, 0x3c080800, 0x3c058000, 0x8f4201b8, - 0x00451024, 0x1440fffd, 0x00000000, 0xac870000, 0x91026c88, 0x00002821, - 0x10400002, 0x25076c88, 0x8ce50008, 0xac850004, 0xa4830008, 0x91036c88, - 0x24020002, 0xa082000b, 0xa4860010, 0x34630001, 0xa083000a, 0x8f420144, - 0xac820024, 0x91036c88, 0x10600002, 0x00001021, 0x8ce20004, 0xac820028, - 0x3c021000, 0xaf4201b8, 0x3c026000, 0xa1006c88, 0x03e00008, 0xac400808, - 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xa082000b, - 0xa4830008, 0xa4860010, 0x8f420144, 0x3c031000, 0xa4820012, 0x03e00008, - 0xaf4301b8, 0x30c2ffff, 0x14400028, 0x00061c02, 0x93620005, 0x30420004, - 0x14400020, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020, 0x3c038000, - 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000, - 0x34630001, 0x00e31825, 0x34420004, 0xa3620005, 0xaf430020, 0x93620005, - 0x30420004, 0x14400003, 0x3c038000, 0x0000000d, 0x3c038000, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x24020005, 0x3c031000, 0xac870000, 0xa082000b, - 0xaf4301b8, 0x0a00150d, 0x00061c02, 0x0000000d, 0x03e00008, 0x00000000, - 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001, - 0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a, 0xa083000b, - 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024, 0x03e00008, - 0xaf4201b8, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, - 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b, 0xa4860010, - 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x03e00008, 0xaf4301b8, - 0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001, - 0xa4830008, 0x24030002, 0xa082000a, 0x3c021000, 0xac870000, 0xac800004, - 0xa083000b, 0xa4860010, 0xac800024, 0xac800028, 0x03e00008, 0xaf4201b8, - 0x00a01821, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, - 0xac870000, 0xac800004, 0xa4830008, 0xa080000a, 0x0a001518, 0xa082000b, - 0x8f440144, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, - 0x240340c9, 0xaf470180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4401a4, - 0xaf4501a8, 0xaf4001ac, 0x03e00008, 0xaf4201b8, 0x0000000d, 0x03e00008, - 0x00000000, 0x03e00008, 0x00000000, 0x8f420100, 0x3042003e, 0x14400011, - 0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, 0x10400005, 0x00000000, - 0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, 0xaf400054, 0xaf400040, - 0x8f420100, 0x30423800, 0x54400001, 0xaf400044, 0x24020001, 0x03e00008, - 0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, - 0x240340c9, 0xaf440180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4501a4, - 0xaf4601a8, 0xaf4701ac, 0x03e00008, 0xaf4201b8, 0x3c029000, 0x34420001, - 0x00822025, 0xaf440020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, - 0x00000000, 0x03e00008, 0x00000000, 0x3c028000, 0x34420001, 0x00822025, - 0x03e00008, 0xaf440020, 0x308600ff, 0x27450180, 0x3c038000, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040, - 0x24030008, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000, - 0xa0a6000a, 0xa4a30010, 0xa0a00012, 0xa0a00013, 0xaca00014, 0xaca00024, - 0xaca00028, 0xaca0002c, 0xaca40018, 0x03e00008, 0xaf4201b8, 0x24020001, - 0xacc40000, 0x03e00008, 0xa4e50000, 0x24020001, 0xaf400044, 0x03e00008, - 0xaf400050, 0x00803021, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, - 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, - 0xa4a20008, 0xaca30018, 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, - 0x94c20010, 0xa4a20010, 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, - 0x8cc30014, 0xaca30014, 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, - 0x8cc2002c, 0x3c031000, 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044, - 0x03e00008, 0xaf400050, 0x27bdffe8, 0xafbf0010, 0x0e001047, 0x00000000, - 0x00002021, 0x0e000c78, 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018, - 0x8f460148, 0x27450180, 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8, - 0x00431024, 0x1440fffd, 0x00000000, 0x8f440140, 0x00061202, 0x304200ff, - 0x00061c02, 0xaca20004, 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b, - 0xaca30024, 0x10e0000a, 0xaca40000, 0x28e20004, 0x14400005, 0x24020001, - 0x24020005, 0x54e20005, 0xa0a0000a, 0x24020001, 0x0a001609, 0xa0a2000a, - 0xa0a0000a, 0x3c021000, 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021, - 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, - 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00161f, 0x00a01021, - 0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa, - 0x24a5ffff, 0x03e00008, 0x00000000, 0x00000000 }; +static u8 bnx2_RXP_b06FwText[] = { + 0x1f, 0x8b, 0x08, 0x08, 0x07, 0x87, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x5d, 0x6c, + 0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x43, 0x71, 0x49, 0x91, 0xd4, 0x70, 0xb9, + 0x62, 0x57, 0x12, 0x65, 0xed, 0x8a, 0x43, 0x71, 0x6d, 0x31, 0xce, 0x50, + 0x58, 0xdb, 0x82, 0xb1, 0x48, 0xc7, 0xb3, 0xa4, 0xc8, 0x24, 0x02, 0x42, + 0x1b, 0x42, 0xab, 0xa4, 0xa9, 0xc1, 0x90, 0x72, 0x91, 0x22, 0x2c, 0xa0, + 0x1a, 0x79, 0xf0, 0x43, 0x10, 0x2f, 0x56, 0x3f, 0xa6, 0xd1, 0x8d, 0x96, + 0xb6, 0x1c, 0x53, 0x08, 0x82, 0x82, 0xe5, 0x52, 0x52, 0x0b, 0x2c, 0xb4, + 0x96, 0xed, 0x36, 0x7e, 0xa8, 0x23, 0x9a, 0x92, 0x8d, 0xa6, 0x68, 0x81, + 0x22, 0xad, 0xd1, 0xf4, 0x4d, 0x95, 0x9a, 0x4a, 0x75, 0x5f, 0xd4, 0xa2, + 0x48, 0xda, 0x46, 0xcd, 0xf4, 0xfb, 0xee, 0xcc, 0x88, 0xd4, 0x9a, 0xb2, + 0x2c, 0x3b, 0x0d, 0x62, 0x74, 0x0e, 0x30, 0xd8, 0xb9, 0x7f, 0xe7, 0xef, + 0x9e, 0x73, 0xee, 0x39, 0x77, 0x28, 0x7d, 0xa5, 0x43, 0xda, 0x25, 0x84, + 0x4e, 0x3c, 0x99, 0xc3, 0xcf, 0x3c, 0xfd, 0xe0, 0xc3, 0x0f, 0xee, 0xc1, + 0xeb, 0xb0, 0xa1, 0x6d, 0xd0, 0xa3, 0xfe, 0x18, 0x62, 0x88, 0x21, 0x86, + 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, + 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, + 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, + 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, + 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0xff, 0xef, 0x60, 0x88, 0x58, + 0xfc, 0xed, 0x0c, 0x1f, 0x49, 0xe8, 0x85, 0xcb, 0x07, 0x3d, 0x5b, 0x12, + 0x46, 0x61, 0x69, 0x66, 0xda, 0x16, 0x71, 0xeb, 0xbb, 0x33, 0x45, 0xf9, + 0x1f, 0xbf, 0x94, 0x32, 0x85, 0xfd, 0xdb, 0x0b, 0x37, 0x9f, 0x7d, 0xf3, + 0x91, 0xec, 0x8d, 0x05, 0x43, 0x12, 0x56, 0xe1, 0xe8, 0xb0, 0xb5, 0x4b, + 0x12, 0x7d, 0x58, 0xf3, 0xdd, 0xc1, 0xcf, 0x59, 0xd2, 0x15, 0xe1, 0xba, + 0xee, 0xbf, 0x39, 0x68, 0xc9, 0x2b, 0x8d, 0x94, 0x5c, 0x68, 0x6c, 0xdf, + 0x24, 0x5d, 0xd9, 0x52, 0x09, 0xfd, 0x6e, 0x8a, 0xe3, 0x96, 0x94, 0xab, + 0x2d, 0xe2, 0x2a, 0xba, 0x7d, 0x5a, 0x71, 0xfe, 0x3e, 0xcd, 0x9b, 0x7f, + 0x9e, 0xff, 0x1e, 0x24, 0xa5, 0xcb, 0x7d, 0x68, 0xf7, 0xa1, 0xcd, 0xf7, + 0x81, 0xf4, 0x94, 0x98, 0x72, 0xa4, 0x91, 0x90, 0xa3, 0xd5, 0x8c, 0xe8, + 0x05, 0x71, 0xbd, 0xbc, 0x9d, 0x2e, 0xa3, 0x6f, 0xea, 0x00, 0xdb, 0x29, + 0xe0, 0xf9, 0x0e, 0xd7, 0x59, 0x5e, 0x5e, 0x4a, 0xb7, 0xc6, 0x14, 0x0d, + 0x8e, 0xb1, 0x0f, 0xbf, 0x58, 0x5f, 0xae, 0x76, 0x00, 0x6f, 0xd6, 0x71, + 0x41, 0xdc, 0x73, 0x2c, 0xd0, 0xf6, 0xfd, 0xdf, 0x75, 0x32, 0xb2, 0xe2, + 0x74, 0x81, 0xa7, 0x16, 0x69, 0xb5, 0xc5, 0xd2, 0x0b, 0xb6, 0xb5, 0x22, + 0x6d, 0x1c, 0xeb, 0x34, 0x0a, 0xbe, 0x3f, 0x9d, 0x97, 0xae, 0xa0, 0x6f, + 0xb7, 0xe2, 0x63, 0x72, 0x42, 0xc3, 0xbc, 0x57, 0x49, 0x0f, 0x3a, 0xe2, + 0x3b, 0x7f, 0xf3, 0x52, 0xac, 0x6c, 0x97, 0xc9, 0x54, 0xf6, 0xa0, 0x1b, + 0xd0, 0x74, 0x3d, 0x67, 0x2b, 0x70, 0x6a, 0xe0, 0x4f, 0xdb, 0x81, 0xf5, + 0xee, 0x0a, 0x68, 0x1a, 0x85, 0xcd, 0x62, 0x6c, 0x66, 0x9f, 0xe8, 0x3b, + 0x87, 0x93, 0xe1, 0x78, 0x97, 0x36, 0x32, 0x6f, 0x88, 0x6e, 0xff, 0x81, + 0xe6, 0xd5, 0x7a, 0xe5, 0xd8, 0xbc, 0x8e, 0x77, 0x5d, 0xae, 0xe6, 0x4b, + 0x9a, 0xdb, 0xa8, 0x68, 0xde, 0xd9, 0x59, 0xad, 0x78, 0xd6, 0x94, 0xa3, + 0xb6, 0x7f, 0xe1, 0xb4, 0x73, 0x42, 0x1b, 0x39, 0x7b, 0x46, 0x1b, 0x3d, + 0xfb, 0x86, 0x36, 0xde, 0xd8, 0xb2, 0x49, 0xda, 0xb3, 0xd0, 0x1e, 0x71, + 0x90, 0xbf, 0x4f, 0x87, 0xba, 0xec, 0xa2, 0xde, 0x4a, 0xe4, 0x7d, 0x9f, + 0xf3, 0x86, 0xe6, 0x55, 0x6d, 0x8b, 0xfb, 0xe6, 0xa6, 0x22, 0x1a, 0xed, + 0x72, 0x74, 0xde, 0x94, 0x63, 0xd5, 0x94, 0x3c, 0x57, 0x2d, 0x29, 0x5a, + 0x86, 0x5d, 0xd2, 0xbc, 0x06, 0xc7, 0x2b, 0xa0, 0x75, 0x42, 0xdb, 0x07, + 0x9a, 0xde, 0x59, 0x29, 0x5d, 0x71, 0xe6, 0x40, 0xaf, 0x03, 0x78, 0xff, + 0x58, 0x1b, 0x6d, 0xf4, 0x6a, 0xde, 0xc9, 0x9b, 0xe2, 0x39, 0x59, 0xeb, + 0x4b, 0x62, 0xba, 0xb0, 0x01, 0xc8, 0x0c, 0xfd, 0x38, 0xd0, 0x49, 0xca, + 0xf7, 0xf5, 0x82, 0xff, 0x2c, 0x74, 0x6f, 0x5d, 0xa1, 0xfc, 0x8d, 0x5e, + 0x29, 0xcf, 0x53, 0xd7, 0xa6, 0x36, 0x52, 0xf5, 0x2f, 0x78, 0x8e, 0xf4, + 0x19, 0xe2, 0xfb, 0x47, 0x9d, 0x81, 0xf4, 0x21, 0x39, 0x03, 0xdc, 0x75, + 0xad, 0xd8, 0xa0, 0xae, 0xc1, 0xdf, 0x2d, 0x39, 0x02, 0xbd, 0x15, 0x9d, + 0x5e, 0x99, 0xb4, 0xb2, 0x2e, 0xf6, 0x68, 0x53, 0x20, 0x57, 0x32, 0xb4, + 0x17, 0xd2, 0xe7, 0xde, 0x67, 0xd3, 0x9e, 0xa1, 0xcb, 0x53, 0x2f, 0x3d, + 0xdf, 0xb3, 0x38, 0xb4, 0x91, 0x32, 0x43, 0xff, 0xf2, 0x45, 0xcf, 0xf6, + 0xb6, 0xb4, 0x48, 0x29, 0x6d, 0x48, 0x16, 0xfb, 0xb4, 0x43, 0x4e, 0x3b, + 0x22, 0x87, 0x2a, 0xd0, 0x8d, 0x6d, 0x5a, 0x8b, 0x62, 0x67, 0xca, 0x32, + 0x50, 0x32, 0x75, 0x74, 0x26, 0x49, 0x97, 0x3a, 0xd2, 0xe5, 0x7a, 0x9e, + 0x7a, 0xa2, 0x3d, 0x7f, 0x28, 0x5d, 0x69, 0xab, 0xba, 0x5a, 0xd5, 0xd3, + 0xf8, 0x2f, 0x5d, 0x4f, 0xd4, 0xc9, 0x72, 0x28, 0xb7, 0x03, 0xdc, 0x8f, + 0x40, 0x5f, 0xe2, 0xea, 0xc3, 0x0f, 0xb1, 0x6f, 0x93, 0x51, 0xb0, 0xd3, + 0x17, 0x61, 0x14, 0x7a, 0x61, 0x37, 0x64, 0x19, 0xa6, 0xee, 0xe0, 0xc3, + 0x1f, 0x49, 0x5e, 0xf9, 0xd5, 0x90, 0x97, 0xfc, 0xdb, 0x32, 0x55, 0x49, + 0x80, 0x06, 0x65, 0xd4, 0xe5, 0xbd, 0x7c, 0x64, 0x1b, 0x7b, 0x20, 0x5f, + 0x5e, 0xa6, 0xbe, 0x45, 0x7f, 0xa2, 0xfd, 0xf3, 0x9d, 0xb2, 0xfe, 0xcc, + 0xbf, 0xee, 0x7c, 0x92, 0xf6, 0x96, 0x7c, 0x27, 0xe4, 0x78, 0x35, 0xc9, + 0x3d, 0xd4, 0x56, 0x54, 0x6c, 0x8a, 0x64, 0x14, 0xdd, 0x28, 0x74, 0x48, + 0x51, 0xed, 0xf7, 0x5e, 0xd0, 0x43, 0x2c, 0xa8, 0xf2, 0xbd, 0xa0, 0x64, + 0x9b, 0xb6, 0xed, 0xcc, 0x11, 0xc9, 0xc2, 0xbe, 0x45, 0x8e, 0xcc, 0x99, + 0x32, 0x6d, 0xff, 0x63, 0xa7, 0xb4, 0x2f, 0xdf, 0x6f, 0xa8, 0xb8, 0xae, + 0xf7, 0x6e, 0x90, 0x4d, 0xe0, 0x77, 0xf9, 0x7e, 0x5d, 0xe4, 0xa6, 0x59, + 0xc8, 0x5a, 0x23, 0x08, 0xf6, 0x46, 0x81, 0xb1, 0x4c, 0x43, 0x2c, 0x93, + 0x44, 0x8b, 0x4d, 0x7d, 0xf9, 0xfe, 0xf8, 0xf0, 0xdd, 0xf5, 0x75, 0x64, + 0x9e, 0xb4, 0xa9, 0x2f, 0xc6, 0xa8, 0x12, 0xf4, 0xc1, 0xf8, 0x74, 0xbb, + 0xae, 0x8a, 0xa1, 0xae, 0x46, 0xfe, 0xef, 0xed, 0xc2, 0xf5, 0xaa, 0xa2, + 0x79, 0xce, 0xbb, 0xa1, 0x2f, 0xd8, 0x32, 0x02, 0x7f, 0x37, 0xec, 0x4f, + 0xcb, 0x91, 0x54, 0x76, 0xc2, 0x95, 0xc0, 0xe6, 0xaf, 0xad, 0xb1, 0xf9, + 0xd1, 0xbb, 0xc8, 0x75, 0x3c, 0x94, 0xcb, 0x0d, 0xe5, 0x1a, 0x85, 0x5c, + 0x63, 0x90, 0x6b, 0xe5, 0x23, 0xc8, 0xb5, 0xf2, 0x91, 0xe5, 0xd2, 0xa4, + 0xec, 0x3c, 0x08, 0x5a, 0xa6, 0xfc, 0xab, 0x13, 0xd8, 0xf2, 0xbf, 0x38, + 0x9f, 0x14, 0x19, 0x7c, 0x7f, 0x70, 0xd8, 0x16, 0xef, 0x5b, 0xe0, 0xd5, + 0x71, 0x40, 0x8b, 0xef, 0xef, 0x97, 0xe1, 0x6e, 0xfe, 0x38, 0x8b, 0x7d, + 0x5d, 0xcf, 0x1f, 0x29, 0x87, 0x3e, 0x7c, 0xef, 0xfe, 0xa8, 0x6b, 0x1f, + 0x55, 0x0e, 0xc6, 0x9c, 0x4f, 0x35, 0x9d, 0xab, 0x1f, 0x56, 0x86, 0xf5, + 0x63, 0xca, 0x2f, 0x4f, 0x86, 0xc7, 0x64, 0x72, 0x33, 0xed, 0xa9, 0xa4, + 0x8d, 0x0c, 0x92, 0xef, 0xb5, 0xfc, 0x4a, 0x26, 0xe0, 0x0d, 0x39, 0xd1, + 0xd2, 0x46, 0x39, 0xb2, 0x60, 0x49, 0x69, 0xe9, 0x4e, 0x71, 0x57, 0x03, + 0x6f, 0xb4, 0x47, 0xf6, 0x7d, 0xd2, 0x7c, 0x2a, 0xc8, 0x2b, 0x2e, 0x54, + 0x91, 0x83, 0x56, 0x13, 0x72, 0xd9, 0x48, 0xcb, 0x9b, 0x83, 0x87, 0xe5, + 0xf3, 0xd5, 0x24, 0xe8, 0x31, 0x9f, 0x2c, 0xe7, 0x10, 0x17, 0xb5, 0xb2, + 0x63, 0x08, 0x79, 0xaf, 0xd9, 0x9c, 0x13, 0xc4, 0x96, 0x72, 0x10, 0x83, + 0x5d, 0x6f, 0x50, 0xe5, 0x14, 0x90, 0x4f, 0x64, 0x0c, 0xb1, 0xb7, 0x66, + 0xb3, 0xcd, 0xfe, 0xa0, 0xef, 0xb3, 0x95, 0x5e, 0xad, 0xc8, 0xbc, 0x64, + 0xf0, 0xa6, 0x4c, 0x3b, 0x41, 0xdf, 0xe7, 0x2a, 0xa3, 0x9b, 0x98, 0x1f, + 0x1a, 0x05, 0xc9, 0x94, 0x9d, 0xf7, 0x7c, 0xd7, 0xba, 0x7d, 0xcd, 0xfa, + 0x78, 0xb2, 0x13, 0x81, 0xce, 0x45, 0xfb, 0xaa, 0xad, 0xf7, 0xb6, 0x4a, + 0x09, 0x27, 0x5d, 0xd6, 0x1a, 0x47, 0xe7, 0xbe, 0x4a, 0x79, 0x5b, 0xab, + 0xdc, 0x34, 0x80, 0x3f, 0x6d, 0x68, 0x62, 0x1e, 0xaa, 0x94, 0xbb, 0xd9, + 0xa6, 0xbe, 0x74, 0x4d, 0x12, 0xa3, 0x15, 0x5f, 0xae, 0x3a, 0x41, 0xee, + 0x63, 0x68, 0x7a, 0x6f, 0x5b, 0xb8, 0x56, 0xd7, 0x76, 0x39, 0x97, 0x44, + 0x3a, 0x0e, 0x55, 0xc4, 0x2a, 0x56, 0x76, 0x39, 0x6f, 0x4b, 0xb9, 0xa7, + 0x6d, 0x75, 0x5d, 0x8a, 0xeb, 0x76, 0x0e, 0xaf, 0x9d, 0xbb, 0xcb, 0xb9, + 0x28, 0xe5, 0x2d, 0x6d, 0xab, 0xb4, 0xd2, 0x58, 0xdb, 0x17, 0xac, 0xe5, + 0xf8, 0x66, 0x71, 0xbb, 0x39, 0x47, 0xef, 0x6d, 0xbf, 0x45, 0x43, 0x32, + 0xc5, 0x4a, 0xb9, 0xa7, 0x7d, 0x15, 0xaf, 0x4d, 0xbc, 0xde, 0x1a, 0xbc, + 0xc4, 0xd9, 0xbe, 0x8a, 0x33, 0x07, 0x9c, 0x43, 0xab, 0x38, 0x39, 0x7e, + 0x58, 0x8a, 0x38, 0xd3, 0x5a, 0x0a, 0x32, 0xbc, 0x54, 0xc9, 0x48, 0x79, + 0x28, 0x01, 0xdd, 0xf7, 0x1f, 0xfc, 0x9a, 0xaa, 0x43, 0xcc, 0x61, 0x0f, + 0xba, 0x32, 0x55, 0x5e, 0x87, 0xd8, 0x08, 0xdb, 0xf8, 0x5a, 0x5d, 0x86, + 0x17, 0xeb, 0xa6, 0x1c, 0x6f, 0x70, 0xbf, 0x98, 0xe3, 0x05, 0x75, 0xc6, + 0x85, 0x46, 0x4e, 0xdb, 0x87, 0xbd, 0x66, 0x9d, 0xb0, 0xaf, 0x61, 0x6a, + 0xa3, 0x3c, 0x1f, 0x80, 0x97, 0x76, 0x7e, 0xac, 0x41, 0xdb, 0x79, 0x03, + 0xb6, 0x41, 0xce, 0xa3, 0x9c, 0xbd, 0x95, 0xb9, 0x53, 0x66, 0xd1, 0x51, + 0x75, 0x88, 0x56, 0xcb, 0x77, 0x20, 0x07, 0x4d, 0xa0, 0xd6, 0x80, 0xcd, + 0xdb, 0x78, 0x6f, 0x70, 0xde, 0x32, 0xe6, 0x6d, 0xe0, 0x3c, 0xec, 0xcd, + 0x25, 0xe5, 0x0f, 0xa6, 0xcd, 0xf1, 0x77, 0xb1, 0xc7, 0x68, 0xd7, 0x59, + 0x57, 0x58, 0x02, 0x5f, 0xc1, 0x3e, 0xa2, 0x6e, 0x48, 0xed, 0x60, 0x7e, + 0x8f, 0xb9, 0x19, 0xcc, 0xcd, 0x66, 0x18, 0xcf, 0x3d, 0xfb, 0x99, 0x0e, + 0xe9, 0x42, 0xbb, 0xce, 0x35, 0xd9, 0x0c, 0x72, 0x5b, 0xdf, 0xcb, 0xb7, + 0xc9, 0x4a, 0xca, 0xbf, 0x60, 0xd8, 0xd1, 0xdc, 0x08, 0x6f, 0xf3, 0x5c, + 0xe6, 0xc5, 0xc4, 0xbd, 0x21, 0xcc, 0x83, 0xc7, 0xc5, 0x6d, 0xfc, 0x49, + 0xb7, 0x74, 0xb9, 0xf8, 0x8d, 0xe6, 0x4c, 0x6f, 0x0e, 0x6a, 0x2e, 0xbe, + 0xb7, 0x50, 0x3e, 0x17, 0xe7, 0xa1, 0x56, 0xac, 0x66, 0x26, 0x59, 0x1f, + 0x15, 0xeb, 0x6c, 0xef, 0x85, 0x3f, 0x04, 0x75, 0xd7, 0x85, 0x5b, 0xbe, + 0x70, 0x19, 0x7a, 0x4b, 0x43, 0x6f, 0x29, 0x39, 0xdf, 0x60, 0x9d, 0xe6, + 0x42, 0x5f, 0x19, 0xf1, 0x1a, 0xe3, 0x58, 0x2b, 0x87, 0x81, 0x03, 0x3a, + 0x17, 0x47, 0x2f, 0x64, 0x65, 0xca, 0xda, 0x1d, 0xf1, 0x00, 0x5c, 0x88, + 0x1f, 0x85, 0x36, 0xf4, 0xf1, 0x1d, 0x9a, 0x53, 0xff, 0x86, 0x7f, 0x94, + 0xed, 0x09, 0xbd, 0x30, 0xd6, 0xd4, 0xbf, 0x6e, 0xfc, 0xa1, 0x1c, 0x68, + 0x33, 0x06, 0x31, 0xfe, 0xe8, 0xa8, 0xf3, 0x18, 0x8b, 0x48, 0xd7, 0x92, + 0x23, 0x4b, 0x23, 0xdc, 0x37, 0x8b, 0xf1, 0xa7, 0x5c, 0xe7, 0x9e, 0x29, + 0x5c, 0xc0, 0x19, 0xad, 0xf1, 0xfd, 0x11, 0x87, 0x6b, 0x7c, 0x99, 0x70, + 0x3a, 0xc4, 0x48, 0x96, 0xb4, 0xc7, 0x07, 0x11, 0x7b, 0x1e, 0xe0, 0x3e, + 0x32, 0x06, 0x6d, 0x17, 0xb0, 0xea, 0xb4, 0x3c, 0x3c, 0xc8, 0x75, 0xa0, + 0xdd, 0x2a, 0x7a, 0x92, 0x34, 0xf3, 0x21, 0x4f, 0x43, 0xdd, 0x81, 0xbe, + 0x06, 0xac, 0x40, 0x7f, 0x9f, 0xe9, 0x5e, 0xd5, 0x1f, 0xd7, 0x35, 0xf3, + 0xcb, 0x18, 0x96, 0x90, 0x81, 0x33, 0x1b, 0x65, 0xe7, 0xa2, 0x25, 0xf6, + 0x99, 0x55, 0xfe, 0x76, 0x9e, 0x5b, 0xcb, 0x5f, 0xf4, 0x7f, 0x15, 0x5c, + 0xd0, 0xc5, 0x8e, 0xfa, 0x1e, 0x4b, 0x05, 0xb8, 0xa3, 0xf6, 0x7b, 0xe1, + 0x5e, 0xf1, 0xfd, 0x99, 0x70, 0x4f, 0xb0, 0x07, 0x88, 0x95, 0xe7, 0x6f, + 0xc5, 0xa9, 0x0c, 0xf6, 0x06, 0xb6, 0xa7, 0xe2, 0x11, 0xe3, 0x18, 0xed, + 0xbb, 0x63, 0xd2, 0x2c, 0xb0, 0x8e, 0xe6, 0x3e, 0xc9, 0x44, 0xb9, 0x22, + 0xa5, 0xad, 0x85, 0x67, 0x7d, 0xd8, 0xcf, 0xa4, 0xa5, 0x6c, 0xaf, 0x63, + 0xaf, 0x97, 0x37, 0xa0, 0x1b, 0x8c, 0xc1, 0x26, 0xf5, 0x42, 0x42, 0x8a, + 0x8d, 0x44, 0xc2, 0x3c, 0x31, 0xf0, 0x23, 0xcf, 0x48, 0x24, 0xf4, 0x13, + 0x81, 0x9d, 0x4d, 0xd6, 0x6f, 0x20, 0x56, 0x6a, 0x72, 0x74, 0xe8, 0x86, + 0xcf, 0x1a, 0xd8, 0xdb, 0x0b, 0x9b, 0x1b, 0x82, 0xcf, 0x80, 0x8f, 0x72, + 0xa3, 0xa3, 0x37, 0xe0, 0xed, 0x2b, 0x11, 0x8f, 0xa6, 0x8e, 0xdc, 0xd3, + 0xcb, 0xfb, 0xbe, 0x51, 0xd8, 0x90, 0x98, 0xce, 0x8f, 0x6f, 0xd1, 0xcf, + 0xed, 0xdf, 0x62, 0x9c, 0x2b, 0x6d, 0x01, 0x3e, 0xdd, 0xcb, 0xe3, 0xf7, + 0x9c, 0xc8, 0x44, 0x15, 0x3a, 0xdf, 0x03, 0x3d, 0x59, 0xf0, 0xc5, 0x3d, + 0xa6, 0xca, 0xd1, 0xf5, 0x3d, 0x2f, 0x6e, 0x0a, 0x70, 0xf0, 0xfd, 0x27, + 0x7e, 0x70, 0x86, 0x5e, 0x0e, 0xfb, 0x7e, 0x3f, 0xdc, 0x87, 0x5f, 0x45, + 0xb9, 0x78, 0x5e, 0x44, 0xb2, 0xad, 0x3d, 0x37, 0xb2, 0xe3, 0x25, 0x9c, + 0x33, 0xa7, 0x1d, 0xdf, 0x7f, 0x07, 0xcf, 0x35, 0xa7, 0xd9, 0x46, 0xde, + 0x7f, 0xf6, 0x31, 0x07, 0xf8, 0x2c, 0xce, 0xbd, 0xd1, 0xa6, 0xb3, 0xff, + 0x5e, 0xcf, 0xbd, 0x7b, 0x3f, 0xfb, 0xc9, 0xf3, 0x1d, 0x7d, 0xef, 0x03, + 0xce, 0xfe, 0x0f, 0x5c, 0x77, 0x0f, 0x3e, 0x1b, 0xd8, 0x6d, 0xb1, 0xd1, + 0x1c, 0x5f, 0xee, 0xd5, 0x7f, 0x7f, 0xad, 0xfb, 0x76, 0xff, 0xb5, 0xbb, + 0x6f, 0xf7, 0xdf, 0xcd, 0xdd, 0xbf, 0x18, 0xff, 0xcd, 0x01, 0x0f, 0x7d, + 0x70, 0xad, 0xff, 0xae, 0xe7, 0x93, 0xd4, 0xf7, 0xf3, 0x3d, 0xe5, 0xa1, + 0xce, 0x30, 0x1f, 0x52, 0xe7, 0xf5, 0x17, 0xa7, 0x6d, 0xef, 0x7e, 0x53, + 0x4a, 0xb9, 0x16, 0xc9, 0xe6, 0x6a, 0xb2, 0x43, 0x8e, 0x3b, 0x22, 0x4b, + 0xaa, 0x16, 0x31, 0x51, 0x8b, 0x0f, 0xa0, 0x3e, 0x0b, 0xf4, 0xba, 0xa4, + 0xf4, 0xf2, 0x02, 0x78, 0x89, 0xf0, 0x74, 0xdd, 0x05, 0x0f, 0x71, 0x10, + 0x17, 0xf1, 0x0c, 0xe2, 0x7c, 0xb7, 0xd7, 0xc1, 0x85, 0x73, 0xea, 0x25, + 0xd4, 0x64, 0xb6, 0xde, 0xa3, 0x07, 0x67, 0xb2, 0x5b, 0x96, 0xdd, 0xe9, + 0xeb, 0xf2, 0x05, 0x9e, 0x59, 0x0a, 0xae, 0xce, 0x21, 0x56, 0x0f, 0x8d, + 0x85, 0x75, 0xd2, 0xdc, 0x41, 0xcf, 0x8e, 0xee, 0x49, 0x78, 0x47, 0x92, + 0x90, 0x92, 0x9a, 0xb5, 0x04, 0x1d, 0x68, 0x72, 0x0d, 0x67, 0xd0, 0xd5, + 0xb9, 0x76, 0xe0, 0x45, 0xee, 0x77, 0x20, 0xbb, 0x57, 0xb4, 0x7e, 0xab, + 0x55, 0x6b, 0x87, 0x2f, 0x65, 0xc4, 0x55, 0x6d, 0x9e, 0xd3, 0xa7, 0x66, + 0x16, 0x2b, 0xc8, 0x03, 0x6d, 0x9c, 0xaf, 0x79, 0xbc, 0xd7, 0x49, 0x43, + 0x93, 0x2b, 0x73, 0xba, 0xfc, 0xd3, 0x9c, 0x21, 0xff, 0x8c, 0x3a, 0xf4, + 0x9a, 0x7d, 0x6a, 0xe6, 0xb4, 0x2d, 0xf7, 0x81, 0xd5, 0xf0, 0x0e, 0x4f, + 0x76, 0x9a, 0x42, 0x5b, 0x1d, 0x48, 0xff, 0x8e, 0x20, 0xff, 0xc1, 0x9a, + 0x2b, 0x73, 0xa4, 0xb5, 0x76, 0x8d, 0xf4, 0x22, 0x1f, 0x83, 0x5d, 0x0f, + 0x30, 0x27, 0xe2, 0x7c, 0xd4, 0xab, 0x03, 0xd6, 0x3e, 0xc5, 0x5b, 0x42, + 0x16, 0xeb, 0x9c, 0x6f, 0x82, 0xb7, 0x2e, 0x9c, 0x31, 0x59, 0x6b, 0x52, + 0xfe, 0xb0, 0x5b, 0xe5, 0xaa, 0x1a, 0xfb, 0x0d, 0xb5, 0xc7, 0xef, 0xef, + 0xe7, 0xde, 0x1b, 0x32, 0x95, 0x62, 0x9b, 0x63, 0x59, 0xd4, 0x9c, 0xc4, + 0x97, 0xdd, 0xeb, 0x0a, 0x79, 0x0e, 0xde, 0xaf, 0x08, 0x65, 0xdb, 0x6d, + 0x5d, 0x97, 0xd7, 0x7d, 0xf7, 0x00, 0xe5, 0x89, 0x72, 0x8b, 0x39, 0x9f, + 0xb1, 0xd8, 0x28, 0xcc, 0xc0, 0x8e, 0xbf, 0x2a, 0xdf, 0x6f, 0x1c, 0x92, + 0xef, 0x35, 0x26, 0xe5, 0xcf, 0x1a, 0x5f, 0x96, 0x3f, 0x6d, 0x1c, 0x94, + 0xd7, 0x1b, 0x07, 0xe4, 0xb5, 0xc6, 0x84, 0xbc, 0xda, 0xd8, 0x0f, 0x1b, + 0x1f, 0x87, 0x8d, 0x9f, 0x9a, 0x99, 0xac, 0xf7, 0xcb, 0xd4, 0x49, 0xc4, + 0x20, 0xe7, 0x1b, 0xba, 0xba, 0xe3, 0xb3, 0xe9, 0xe7, 0x2d, 0x32, 0xad, + 0xee, 0xaf, 0x34, 0xe4, 0x89, 0x2d, 0xbc, 0x2b, 0x7c, 0xc5, 0x33, 0x2e, + 0x87, 0xf1, 0xe8, 0xe1, 0x94, 0xb4, 0x03, 0xbf, 0xca, 0x4b, 0x4d, 0x9e, + 0xdb, 0x62, 0x86, 0xf7, 0x9c, 0x87, 0x24, 0xc9, 0xfb, 0xb0, 0x9c, 0x67, + 0xa0, 0xde, 0x5e, 0xd7, 0x27, 0x73, 0xb4, 0x65, 0xe8, 0xc6, 0x95, 0x43, + 0xb0, 0x53, 0xc3, 0x7e, 0xcb, 0xa5, 0x1e, 0x16, 0x97, 0x28, 0xf7, 0x46, + 0x59, 0x5c, 0xa0, 0x6f, 0xff, 0x1b, 0x64, 0x6c, 0x97, 0xda, 0x82, 0x89, + 0xb9, 0x6e, 0x98, 0xab, 0x6c, 0xa7, 0x3d, 0x00, 0x1f, 0xf1, 0x7e, 0x10, + 0x4e, 0xab, 0x09, 0x27, 0xf1, 0x24, 0x54, 0x0c, 0x08, 0x70, 0x5b, 0x52, + 0x5b, 0x4a, 0xca, 0xc2, 0x42, 0x0f, 0x9e, 0x94, 0x2c, 0xd4, 0x6d, 0x3c, + 0x39, 0x3c, 0x43, 0x78, 0xd2, 0xb0, 0x53, 0xca, 0xc8, 0xd8, 0x12, 0xc9, + 0x88, 0x78, 0x5c, 0xed, 0x0d, 0x6b, 0x2a, 0xf2, 0xa3, 0x85, 0xfc, 0x74, + 0x87, 0x7d, 0x1d, 0x52, 0xab, 0x38, 0x32, 0x55, 0xfd, 0x94, 0x3e, 0xa5, + 0x74, 0x07, 0xfc, 0x95, 0x21, 0xb4, 0xef, 0x0f, 0xdb, 0x8f, 0xca, 0xf4, + 0xbc, 0xc8, 0xca, 0xcb, 0x03, 0x7a, 0x51, 0xb5, 0xf7, 0xa2, 0xad, 0xa3, + 0x9d, 0x0d, 0xdb, 0xcc, 0x8f, 0x0e, 0xe0, 0x71, 0xd5, 0xf3, 0xf5, 0xea, + 0xb8, 0x3c, 0x55, 0xed, 0x77, 0x5e, 0x87, 0xcd, 0xbd, 0x65, 0x46, 0xf7, + 0xd2, 0x04, 0x24, 0x79, 0xf6, 0x56, 0x75, 0xf7, 0xf1, 0x04, 0xe2, 0xad, + 0x9b, 0x34, 0xe5, 0x6f, 0x4f, 0x64, 0xad, 0xa7, 0xf5, 0x5c, 0x52, 0xda, + 0x7d, 0xff, 0x71, 0x3b, 0x3b, 0x3b, 0xa9, 0x77, 0xca, 0xdf, 0xbf, 0x98, + 0x91, 0x85, 0xb3, 0x5b, 0x65, 0xa1, 0x06, 0x99, 0x1a, 0xbf, 0x8e, 0x7d, + 0x35, 0xe5, 0xea, 0x9e, 0x47, 0xb1, 0x27, 0x8c, 0x5d, 0x49, 0xe4, 0x6c, + 0x1b, 0xc4, 0xec, 0x25, 0x5d, 0x49, 0x98, 0x85, 0x9c, 0x1c, 0x81, 0xdf, + 0x4f, 0xdb, 0xb9, 0x1e, 0x69, 0xc7, 0x7b, 0x7d, 0x04, 0x7c, 0x5b, 0x32, + 0xd5, 0x6b, 0xc9, 0x99, 0xc1, 0x68, 0xff, 0xb6, 0x62, 0x6e, 0x46, 0x16, + 0xcf, 0x66, 0xf0, 0x9b, 0x83, 0xfd, 0xec, 0x94, 0x57, 0x6a, 0xfd, 0xb2, + 0x54, 0xdb, 0x2a, 0x8b, 0xb5, 0xe6, 0x7d, 0xe8, 0xec, 0x09, 0xe2, 0x1d, + 0xf1, 0xf4, 0x5b, 0x53, 0xfa, 0x56, 0x71, 0xcd, 0x7e, 0xeb, 0x29, 0xfd, + 0x1f, 0xe4, 0x31, 0x33, 0xa0, 0xa9, 0x17, 0x7e, 0xa4, 0xee, 0x84, 0x26, + 0x79, 0xf6, 0x2a, 0xbc, 0x4f, 0x26, 0x49, 0xfb, 0xf5, 0xc6, 0x07, 0xd1, + 0x59, 0xcb, 0xcf, 0x9d, 0x68, 0x52, 0x06, 0xe2, 0xec, 0xbf, 0x71, 0x52, + 0xef, 0x95, 0xe5, 0x6d, 0x0f, 0x58, 0x4f, 0xea, 0xad, 0x88, 0x01, 0x3f, + 0x97, 0x9f, 0xee, 0xd9, 0x24, 0x3f, 0xfc, 0xcd, 0xec, 0xa9, 0x6f, 0x22, + 0xd9, 0xbf, 0xb2, 0xa7, 0x83, 0x71, 0x01, 0xef, 0xec, 0xcf, 0xde, 0x70, + 0x75, 0xea, 0xe1, 0x2f, 0xa0, 0x87, 0xec, 0x9c, 0xba, 0x9b, 0x56, 0x3c, + 0x90, 0x3e, 0xf5, 0x52, 0x06, 0x6f, 0x18, 0xab, 0xf7, 0x03, 0x57, 0x59, + 0xe9, 0xf9, 0x09, 0x27, 0x7b, 0x03, 0xe9, 0xb0, 0xbf, 0x68, 0xf7, 0xa7, + 0x77, 0xea, 0x3b, 0x64, 0x32, 0xfd, 0x80, 0xf5, 0xb4, 0x6c, 0x21, 0xce, + 0xd9, 0x05, 0xc1, 0xda, 0x79, 0xe2, 0xfb, 0x2b, 0xe0, 0x0b, 0x70, 0x28, + 0xff, 0x51, 0x38, 0x77, 0x59, 0x5f, 0xd7, 0x79, 0xc6, 0x63, 0x0c, 0x71, + 0xe1, 0xe2, 0x10, 0x65, 0x40, 0x82, 0x95, 0xca, 0xa6, 0x5d, 0xfd, 0xc3, + 0xc8, 0x47, 0xfc, 0xfd, 0x56, 0x51, 0x27, 0x0f, 0xe7, 0xc0, 0xcb, 0x4f, + 0xc0, 0x7f, 0x3f, 0x70, 0xa2, 0xf6, 0x48, 0x47, 0x74, 0xff, 0x4e, 0xd1, + 0x7d, 0xad, 0x21, 0xe6, 0x2a, 0x5d, 0xf4, 0xd5, 0x75, 0xc8, 0xdd, 0x07, + 0x7b, 0xb5, 0xf0, 0xcb, 0xbd, 0xe9, 0x0c, 0xf7, 0x98, 0xeb, 0x22, 0xba, + 0x11, 0xbf, 0x5c, 0x73, 0x27, 0x1e, 0xee, 0x75, 0x3e, 0xea, 0xd4, 0x03, + 0x09, 0x79, 0xf7, 0x44, 0xb4, 0x37, 0x07, 0x64, 0xba, 0x0a, 0xdd, 0xed, + 0xea, 0x0f, 0xfc, 0x27, 0x1d, 0xf1, 0x40, 0xde, 0xff, 0x06, 0xbc, 0x07, + 0xb8, 0x5b, 0x0b, 0xcd, 0xba, 0xc3, 0x58, 0x3d, 0xa0, 0x31, 0xb6, 0x0e, + 0x4f, 0x57, 0xf6, 0x44, 0xbe, 0x98, 0x84, 0x5f, 0xed, 0xb6, 0x9e, 0x10, + 0xd6, 0x63, 0xc4, 0x9b, 0x94, 0x1f, 0xbe, 0x0c, 0x1e, 0x92, 0xf4, 0x93, + 0x7f, 0x5f, 0xe3, 0x27, 0x1c, 0xdb, 0x2a, 0x35, 0xd4, 0xd4, 0x5e, 0xde, + 0x94, 0x69, 0x25, 0x03, 0xda, 0x35, 0xfa, 0x77, 0x29, 0xf4, 0xef, 0x47, + 0x80, 0xa3, 0x5d, 0x8c, 0x47, 0x1f, 0xc7, 0x59, 0x9d, 0xcd, 0x2c, 0xeb, + 0xcc, 0x03, 0x76, 0x4b, 0x51, 0xdd, 0x4f, 0xdf, 0x8b, 0xee, 0xa2, 0xd8, + 0x94, 0x96, 0x8b, 0x95, 0x28, 0x2e, 0xa5, 0x71, 0x9e, 0xb4, 0xcb, 0xa5, + 0xb9, 0x28, 0xe6, 0xb5, 0xcb, 0x12, 0xf2, 0x9a, 0x95, 0x97, 0x2c, 0x8c, + 0x25, 0xe5, 0xe2, 0x5c, 0x12, 0x31, 0xab, 0x47, 0x56, 0xe6, 0x7a, 0x30, + 0x96, 0xc2, 0xba, 0x14, 0xe6, 0xdb, 0xb2, 0x52, 0xb1, 0x81, 0x27, 0x87, + 0x76, 0x0e, 0xed, 0x21, 0xb9, 0xa4, 0xbe, 0x17, 0x30, 0x2f, 0x18, 0x42, + 0xdc, 0x62, 0x5e, 0x30, 0x82, 0x18, 0x32, 0x81, 0x27, 0x8a, 0x5d, 0xa7, + 0x66, 0xa6, 0x2a, 0xbc, 0x73, 0x84, 0x0e, 0xac, 0x53, 0x33, 0xd3, 0xb6, + 0x89, 0xba, 0xed, 0x1b, 0xda, 0x54, 0x83, 0x72, 0x41, 0xb7, 0x43, 0x1d, + 0xa2, 0x3f, 0x4a, 0x9b, 0xe4, 0x79, 0x67, 0x20, 0xc6, 0x77, 0x01, 0x9f, + 0x23, 0xfa, 0x6f, 0xd0, 0x17, 0xa0, 0xc3, 0x27, 0xba, 0xe4, 0xd2, 0xcb, + 0x8c, 0x35, 0xae, 0xbc, 0x7a, 0x96, 0x3a, 0x2c, 0xf6, 0xac, 0xea, 0x90, + 0x63, 0x0f, 0xe1, 0x8c, 0xd8, 0x0f, 0x7b, 0x32, 0x33, 0x87, 0x90, 0xcb, + 0x7c, 0x1b, 0xf6, 0x59, 0x66, 0xcd, 0x9d, 0x0e, 0x6a, 0x84, 0x20, 0x06, + 0xa0, 0xdd, 0x47, 0x5d, 0xb1, 0xdd, 0x07, 0xbb, 0xe3, 0x58, 0x9f, 0x1a, + 0x5b, 0x04, 0x8e, 0x60, 0x8c, 0xed, 0xcd, 0xb2, 0xa8, 0xc6, 0x0e, 0xaa, + 0xb1, 0xb2, 0xb2, 0x0f, 0x8e, 0x1d, 0x52, 0xb1, 0xe9, 0x7c, 0x23, 0xea, + 0xdf, 0x88, 0x58, 0xc2, 0x7e, 0xf6, 0xe5, 0x61, 0xeb, 0x7b, 0x71, 0xae, + 0x15, 0x64, 0xa9, 0x81, 0x3a, 0x30, 0xff, 0x7b, 0x98, 0xcb, 0x3d, 0xc8, + 0x9e, 0x2a, 0xe9, 0xe4, 0xf1, 0x20, 0xce, 0x83, 0xfd, 0x21, 0xad, 0xb6, + 0x90, 0xaf, 0x03, 0x61, 0xbb, 0x25, 0xa4, 0x4d, 0x3c, 0x36, 0x70, 0x1c, + 0xc3, 0x5a, 0x17, 0x38, 0x18, 0x63, 0x11, 0x23, 0x52, 0x29, 0xe8, 0x82, + 0x34, 0xdb, 0xa4, 0xac, 0xde, 0xf7, 0xc3, 0x76, 0xb9, 0x16, 0x3a, 0xb4, + 0xa2, 0x75, 0xa5, 0x70, 0xcf, 0x53, 0xea, 0x9c, 0xd1, 0x93, 0x9b, 0xc3, + 0x9c, 0x10, 0x7a, 0x45, 0x9c, 0xd5, 0x93, 0x8c, 0x37, 0xef, 0x84, 0x76, + 0xda, 0x8b, 0xbe, 0x87, 0x44, 0xef, 0x65, 0xdf, 0x51, 0xe0, 0x61, 0xed, + 0x3c, 0x0c, 0x99, 0xd9, 0xe6, 0xfa, 0x6c, 0xd3, 0xfa, 0xc4, 0x3a, 0xeb, + 0x3b, 0x9a, 0xfa, 0x32, 0x52, 0x9b, 0xef, 0x52, 0xf1, 0xf2, 0x7c, 0x18, + 0x2f, 0x17, 0x6b, 0x94, 0x05, 0x7e, 0x96, 0x7f, 0x5b, 0xe9, 0xa2, 0x76, + 0x36, 0xb0, 0xf5, 0xa5, 0x93, 0x3c, 0x17, 0x57, 0xe7, 0xd5, 0xd4, 0xbc, + 0xdf, 0x06, 0xff, 0xba, 0x1c, 0x55, 0x32, 0x70, 0x3e, 0xe6, 0xd5, 0x02, + 0xbf, 0x31, 0x6c, 0xce, 0xa1, 0x8f, 0x44, 0x6b, 0x38, 0xff, 0xe7, 0xa8, + 0x55, 0xbe, 0xac, 0xd6, 0xac, 0xfa, 0x0c, 0xf9, 0x71, 0x42, 0x9e, 0x7b, + 0xc0, 0x5f, 0x67, 0x28, 0x43, 0x7b, 0x28, 0x03, 0xf1, 0xfd, 0x27, 0x70, + 0xb7, 0x61, 0x1e, 0x79, 0xdd, 0x86, 0x3e, 0xbe, 0xff, 0x17, 0xfa, 0x76, + 0x23, 0xff, 0x23, 0x6f, 0x89, 0x26, 0xde, 0xfe, 0x03, 0x63, 0x3d, 0x4a, + 0xb7, 0x35, 0xd4, 0x26, 0x53, 0xbc, 0xef, 0x48, 0xe1, 0x1c, 0x38, 0xb9, + 0x4d, 0xd1, 0xad, 0x9d, 0xbd, 0x86, 0xf1, 0x5e, 0xac, 0x89, 0xda, 0xcd, + 0xb2, 0xe9, 0x58, 0xfb, 0x53, 0x25, 0xcf, 0x62, 0xed, 0x4e, 0xf2, 0x6f, + 0x5b, 0x23, 0x3b, 0xe5, 0x26, 0x4f, 0xe4, 0xa7, 0x1f, 0x4f, 0x2b, 0x72, + 0x21, 0xd8, 0x6d, 0xd2, 0x90, 0xd1, 0x7c, 0x9a, 0xdf, 0xf9, 0x12, 0xbc, + 0x17, 0x1d, 0x19, 0xe4, 0x9e, 0xa1, 0xdd, 0x60, 0x4e, 0x47, 0x7f, 0x4b, + 0xc8, 0x31, 0xd4, 0x24, 0xe5, 0x85, 0x8c, 0x56, 0x3c, 0x99, 0x45, 0x16, + 0xad, 0xbe, 0xd5, 0xc9, 0x8b, 0x4b, 0xb6, 0x7c, 0x1b, 0x7e, 0x7a, 0xb2, + 0x9e, 0x4d, 0x7f, 0x13, 0xf9, 0xc1, 0x91, 0x25, 0xe6, 0x13, 0x3d, 0x29, + 0x65, 0x9b, 0xf3, 0x9a, 0x6c, 0x60, 0x4c, 0x9b, 0x47, 0x7e, 0x6a, 0xdd, + 0x2d, 0x47, 0x82, 0x9f, 0x57, 0xd7, 0xc6, 0x0c, 0xca, 0xb1, 0x36, 0x66, + 0x10, 0x0f, 0x63, 0xc6, 0x4e, 0xec, 0x13, 0x63, 0x06, 0xf6, 0xff, 0x24, + 0x63, 0x86, 0x8d, 0x75, 0x8c, 0x19, 0x79, 0x59, 0xac, 0x32, 0x66, 0xec, + 0x45, 0x9b, 0x31, 0xa3, 0x80, 0x76, 0x10, 0x2f, 0x16, 0x55, 0xbc, 0xc8, + 0x5a, 0xcb, 0xc2, 0x38, 0x81, 0x3c, 0xb1, 0x8a, 0x3c, 0xb1, 0x8a, 0x3c, + 0xb1, 0x8a, 0x3c, 0xb1, 0x8a, 0x3c, 0x11, 0xb6, 0xfe, 0x5a, 0x15, 0x79, + 0x22, 0xfc, 0xe7, 0x3c, 0x72, 0x92, 0xa0, 0xa6, 0x38, 0x8c, 0x9a, 0xc2, + 0xd5, 0xc6, 0xaa, 0xe3, 0xda, 0xbe, 0x2a, 0x6a, 0x43, 0xf5, 0x9d, 0x58, + 0x1f, 0xda, 0x80, 0xba, 0xa8, 0xe6, 0x6c, 0x01, 0x5f, 0xd7, 0xe0, 0x1b, + 0xd4, 0xd3, 0x56, 0x99, 0xca, 0xed, 0x80, 0x7c, 0xd8, 0x7f, 0xfb, 0xfb, + 0xe8, 0x43, 0x3e, 0x9f, 0x63, 0x0d, 0xc2, 0x78, 0xb5, 0x0f, 0x6d, 0x1d, + 0x6d, 0xec, 0xe9, 0x04, 0x7c, 0xc4, 0x7e, 0x90, 0xf9, 0x62, 0x7a, 0x41, + 0x9e, 0xdc, 0x1c, 0xd8, 0xf4, 0x6f, 0x31, 0x27, 0x5e, 0xd3, 0xde, 0x88, + 0x39, 0xf0, 0x17, 0xd8, 0x97, 0x5a, 0x03, 0x5c, 0xba, 0xfd, 0xe7, 0xc4, + 0xd1, 0xb7, 0xe1, 0xd6, 0x1c, 0xda, 0xd5, 0xf7, 0x9a, 0xfa, 0xb2, 0x98, + 0xcf, 0xef, 0xe2, 0x3b, 0xf0, 0xfb, 0x16, 0x7e, 0x61, 0x77, 0xf6, 0x05, + 0xcc, 0xe9, 0xc3, 0xef, 0x77, 0x9a, 0xe6, 0x42, 0x0a, 0xfb, 0x2f, 0xd1, + 0x77, 0x31, 0xa4, 0xc1, 0x6f, 0x89, 0x5f, 0x6a, 0xe2, 0xe3, 0x07, 0xe8, + 0xfb, 0x6b, 0xf4, 0xf9, 0xfe, 0xdb, 0x4e, 0xd4, 0x27, 0xa5, 0x96, 0x70, + 0xef, 0x46, 0xd5, 0xde, 0x69, 0xca, 0xe6, 0x8f, 0x2c, 0xe9, 0xaa, 0x0e, + 0x7a, 0xae, 0x8e, 0xea, 0x08, 0x71, 0xbe, 0xbc, 0x10, 0xd4, 0xad, 0xc7, + 0x51, 0x73, 0x16, 0xab, 0xb4, 0x91, 0x1c, 0xfa, 0x6d, 0x9c, 0x69, 0x32, + 0x69, 0xdc, 0xaa, 0x63, 0x13, 0x89, 0xc9, 0x7a, 0x9b, 0x48, 0x37, 0x69, + 0x32, 0x4f, 0x22, 0x8e, 0xd9, 0x99, 0xe2, 0xc2, 0xec, 0x8c, 0x07, 0x9c, + 0x63, 0x75, 0xae, 0xe5, 0x3c, 0x93, 0xf7, 0x63, 0x4d, 0x74, 0x69, 0x13, + 0x60, 0x06, 0xf4, 0x9e, 0xab, 0x93, 0x7e, 0x40, 0xb3, 0xac, 0x68, 0xda, + 0xe8, 0x8f, 0xea, 0xc7, 0x1c, 0x6a, 0x5d, 0x99, 0x64, 0xed, 0x5c, 0x0c, + 0x69, 0xba, 0x75, 0x49, 0x24, 0x0a, 0xcd, 0xf8, 0x82, 0x8c, 0xf3, 0xb9, + 0xfa, 0xec, 0x8c, 0xfe, 0x42, 0x36, 0xc7, 0x3b, 0x11, 0xd7, 0x9a, 0x9d, + 0x69, 0x1d, 0x48, 0xc8, 0x8f, 0x91, 0xbb, 0x1d, 0x53, 0x34, 0x66, 0x67, + 0x8c, 0x17, 0x02, 0x5b, 0x0c, 0xe8, 0xe0, 0x3c, 0xc9, 0xb7, 0x43, 0x4e, + 0xd2, 0x62, 0x4d, 0x1d, 0x8c, 0x4f, 0xaa, 0x7a, 0xd1, 0x94, 0x2b, 0x15, + 0x45, 0x3b, 0xac, 0xdb, 0xc9, 0xc3, 0xec, 0x8c, 0xfc, 0xd1, 0x2d, 0x1e, + 0xd6, 0x91, 0x87, 0x78, 0x49, 0x27, 0xd0, 0x5b, 0xc0, 0x7f, 0x12, 0xf5, + 0x7b, 0x54, 0xab, 0xfb, 0xfe, 0x8a, 0x93, 0x43, 0x5c, 0xe0, 0x3e, 0xb6, + 0xa8, 0x3c, 0xd7, 0x73, 0x32, 0xbc, 0xef, 0x9b, 0xe3, 0xdf, 0x39, 0x78, + 0xf9, 0x01, 0xd4, 0x4d, 0xbc, 0x1b, 0xa4, 0x7f, 0xe1, 0xf7, 0x36, 0xff, + 0xe2, 0x7c, 0xf6, 0x93, 0xe7, 0x81, 0xf4, 0x55, 0xf0, 0xe7, 0xe5, 0xd1, + 0x87, 0x58, 0x51, 0x6c, 0x44, 0xb8, 0x78, 0xc7, 0xce, 0x39, 0x2a, 0xff, + 0x6e, 0xf2, 0xd1, 0x96, 0xf0, 0xdc, 0xa5, 0x8e, 0xc8, 0x27, 0xf9, 0xe9, + 0x84, 0x4d, 0x90, 0x17, 0xce, 0x8f, 0xee, 0x25, 0xd8, 0xfe, 0xb8, 0x36, + 0x12, 0xdd, 0xa9, 0x7d, 0x9c, 0x3d, 0x8f, 0x74, 0x76, 0x37, 0x7e, 0x88, + 0x83, 0xb4, 0x23, 0xbe, 0x22, 0x9e, 0x88, 0x8f, 0xfc, 0x44, 0xbc, 0x28, + 0x1b, 0x5d, 0x97, 0x9f, 0x60, 0x5d, 0xc0, 0x4f, 0x69, 0x21, 0x0d, 0x9d, + 0x90, 0xa7, 0x11, 0x6d, 0xa4, 0xba, 0xde, 0x1d, 0xc7, 0x0f, 0x5c, 0xc6, + 0xd5, 0xb1, 0x06, 0xef, 0xa1, 0x48, 0x97, 0x7f, 0x3b, 0xb2, 0xa4, 0x8d, + 0x34, 0xf8, 0x9d, 0xa9, 0xae, 0xb9, 0x8d, 0x88, 0xde, 0x5a, 0x9d, 0x46, + 0xbf, 0xbc, 0x2b, 0xff, 0x0c, 0xf6, 0xa9, 0x3b, 0xf8, 0xbb, 0x14, 0x55, + 0x47, 0xb1, 0x6f, 0xb9, 0xd5, 0x73, 0xa2, 0xbf, 0xd3, 0xd9, 0x1f, 0xe6, + 0x43, 0x51, 0x6d, 0x1c, 0xd5, 0x59, 0xea, 0x9e, 0x7d, 0xaf, 0xe7, 0x68, + 0xc8, 0x4f, 0x99, 0x33, 0x05, 0x3a, 0x08, 0xf1, 0xde, 0x91, 0xcf, 0x91, + 0x26, 0x3e, 0x47, 0xc1, 0xe7, 0x3e, 0xf0, 0x39, 0x76, 0x8b, 0xcf, 0x5b, + 0xb6, 0x97, 0x29, 0xc3, 0xf6, 0x46, 0xd6, 0xb5, 0xbd, 0x55, 0x3a, 0xab, + 0x73, 0x83, 0xfb, 0x9a, 0x91, 0x86, 0x2f, 0xc7, 0x9d, 0x8f, 0x53, 0x37, + 0xb7, 0xcb, 0x99, 0x85, 0xbb, 0xd5, 0xb7, 0x11, 0xaf, 0x2a, 0x77, 0x94, + 0x4b, 0xf5, 0x80, 0x9f, 0x1f, 0x2f, 0xb1, 0x3d, 0x12, 0xea, 0x8a, 0x3a, + 0xcb, 0x3a, 0x25, 0xb9, 0x1b, 0x2f, 0xbf, 0xf8, 0x9c, 0x76, 0xa5, 0x12, + 0x9d, 0x4f, 0x5a, 0x78, 0xc6, 0xae, 0xe5, 0x29, 0xfa, 0x6e, 0x32, 0x66, + 0x45, 0xf7, 0x67, 0x22, 0xfc, 0xfe, 0xc0, 0xef, 0x75, 0x6b, 0xbf, 0x13, + 0xf0, 0x7c, 0x8a, 0x78, 0xd7, 0x53, 0x3c, 0x9f, 0xc6, 0x9c, 0x66, 0x19, + 0x5c, 0xd8, 0xa4, 0x9e, 0xe4, 0x98, 0xe7, 0xd0, 0x2f, 0x4c, 0xd0, 0x0c, + 0xee, 0xdd, 0x6a, 0x4b, 0xbe, 0x5c, 0x74, 0x36, 0x06, 0xe7, 0x28, 0x64, + 0xba, 0x6c, 0xf1, 0xfe, 0x0a, 0x31, 0x8c, 0x67, 0x83, 0xb2, 0xb5, 0x16, + 0xf5, 0x5c, 0x39, 0xd0, 0x0e, 0x1d, 0xb3, 0xdd, 0xd6, 0xcb, 0xfb, 0x0a, + 0xca, 0xbc, 0xa0, 0xf6, 0x21, 0xd2, 0x71, 0xf4, 0x7d, 0xae, 0x55, 0x96, + 0xc3, 0xbb, 0xad, 0xc5, 0x8a, 0xef, 0xbf, 0x83, 0x3c, 0xfc, 0x34, 0x74, + 0x5f, 0xae, 0xff, 0xcc, 0x5f, 0x4e, 0xf1, 0x6f, 0xa5, 0x22, 0x9b, 0xd8, + 0xd1, 0xcb, 0x7b, 0x20, 0xf8, 0x96, 0x1c, 0xaf, 0x87, 0x65, 0xbf, 0x70, + 0x9c, 0x7d, 0xff, 0x0d, 0xbe, 0x7d, 0xff, 0xf4, 0xaa, 0x9d, 0x02, 0xfe, + 0x17, 0x33, 0xe1, 0x9b, 0xdd, 0x90, 0x58, 0x00, 0x00, 0x00 }; static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 }; static u32 bnx2_RXP_b06FwRodata[(0x28/4) + 1] = { @@ -1943,387 +1057,264 @@ static u32 bnx2_RXP_b06FwRodata[(0x28/4) static u32 bnx2_RXP_b06FwBss[(0x13a4/4) + 1] = { 0x0 }; static u32 bnx2_RXP_b06FwSbss[(0x1c/4) + 1] = { 0x0 }; -static u32 bnx2_rv2p_proc1[] = { - 0x00000008, 0xac000001, 0x0000000c, 0x2f800001, 0x00000010, 0x213f0004, - 0x00000010, 0x20bf002c, 0x00000010, 0x203f0143, 0x00000018, 0x8000fffd, - 0x00000010, 0xb1b8b017, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000, - 0x00000000, 0x2c380000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000, - 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x00000008, 0x02000002, - 0x00000010, 0x91de0000, 0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08, - 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000008, 0x2d800150, - 0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000010, 0x2c620002, - 0x00000018, 0x80000012, 0x0000000b, 0x2fdf0002, 0x0000000c, 0x1f800002, - 0x00000000, 0x2c070000, 0x00000018, 0x8000ffe6, 0x00000008, 0x02000002, - 0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08, 0x00000008, 0x2c8000b0, - 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, - 0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000018, 0x80000004, - 0x0000000c, 0x1f800002, 0x00000000, 0x00000000, 0x00000018, 0x8000ffd9, - 0x0000000c, 0x29800002, 0x0000000c, 0x1f800002, 0x00000000, 0x2adf0000, - 0x00000008, 0x2a000005, 0x00000018, 0x8000ffd4, 0x00000008, 0x02240030, - 0x00000018, 0x00040000, 0x00000018, 0x80000015, 0x00000018, 0x80000017, - 0x00000018, 0x8000001b, 0x00000018, 0x8000004c, 0x00000018, 0x8000008c, - 0x00000018, 0x8000000f, 0x00000018, 0x8000000e, 0x00000018, 0x8000000d, - 0x00000018, 0x8000000c, 0x00000018, 0x800000c2, 0x00000018, 0x8000000a, - 0x00000018, 0x80000009, 0x00000018, 0x80000008, 0x00000018, 0x800000fd, - 0x00000018, 0x80000006, 0x00000018, 0x80000005, 0x00000018, 0x800000ff, - 0x00000018, 0x80000104, 0x00000018, 0x80000002, 0x00000018, 0x80000098, - 0x00000018, 0x80000000, 0x0000000c, 0x1f800001, 0x00000000, 0x00000000, - 0x00000018, 0x8000ffba, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001, - 0x0000000c, 0x1f800001, 0x00000008, 0x2a000002, 0x00000018, 0x8000ffb5, - 0x00000010, 0xb1a0b012, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000, - 0x00000008, 0x2c800000, 0x00000008, 0x2d000000, 0x00000010, 0x91d40000, - 0x00000008, 0x2d80011c, 0x00000000, 0x00000000, 0x00000010, 0x91de0000, - 0x0000000f, 0x47600008, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000, - 0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, - 0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000018, 0x80000013, - 0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002, 0x00000008, 0x2c800000, - 0x00000008, 0x2d000000, 0x00000010, 0x91d40000, 0x00000008, 0x2d80011c, - 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000, 0x00000000, 0x0f580000, - 0x00000010, 0x91de0000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, - 0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000000, 0x02620000, - 0x0000000b, 0x2fdf0002, 0x00000000, 0x309a0000, 0x00000000, 0x31040000, - 0x00000000, 0x0c961800, 0x00000009, 0x0c99ffff, 0x00000004, 0xcc993400, - 0x00000010, 0xb1963202, 0x00000008, 0x0f800000, 0x0000000c, 0x29800001, - 0x00000010, 0x00220002, 0x0000000c, 0x29520001, 0x0000000c, 0x29520000, - 0x00000008, 0x22000001, 0x0000000c, 0x1f800001, 0x00000000, 0x2adf0000, - 0x00000008, 0x2a000003, 0x00000018, 0x8000ff83, 0x00000010, 0xb1a0b01d, - 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0, - 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150, - 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000, - 0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000000, 0x00000000, - 0x00000010, 0x91de0000, 0x0000000f, 0x47600008, 0x00000000, 0x060e0000, - 0x00000010, 0x001f0000, 0x00000000, 0x0f580000, 0x00000010, 0x91de0000, - 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, 0x00000000, 0x0b670000, - 0x00000000, 0x0d620000, 0x00000000, 0x0ce71800, 0x00000009, 0x0c99ffff, - 0x00000004, 0xcc993400, 0x00000010, 0xb1963220, 0x00000008, 0x0f800000, - 0x00000018, 0x8000001e, 0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002, - 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, - 0x00000008, 0x2d80012c, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000, - 0x00000000, 0x0f580000, 0x00000010, 0x91de0000, 0x00000000, 0x0a640000, - 0x00000000, 0x0ae50000, 0x00000000, 0x0b670000, 0x00000000, 0x0d620000, - 0x00000000, 0x02630000, 0x0000000f, 0x47620010, 0x00000000, 0x0ce71800, - 0x0000000b, 0x2fdf0002, 0x00000000, 0x311a0000, 0x00000000, 0x31840000, - 0x0000000b, 0xc20000ff, 0x00000002, 0x42040000, 0x00000001, 0x31620800, - 0x0000000f, 0x020e0010, 0x00000002, 0x31620800, 0x00000009, 0x0c99ffff, - 0x00000004, 0xcc993400, 0x00000010, 0xb1963202, 0x00000008, 0x0f800000, - 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x0000000c, 0x61420006, - 0x00000008, 0x22000008, 0x00000000, 0x2adf0000, 0x00000008, 0x2a000004, - 0x00000018, 0x8000ff42, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, - 0x00000010, 0x91a0b008, 0x00000010, 0x91d40000, 0x0000000c, 0x31620018, - 0x00000008, 0x2d800001, 0x00000000, 0x00000000, 0x00000010, 0x91de0000, - 0x00000008, 0xac000001, 0x00000018, 0x8000000e, 0x00000000, 0x0380b000, - 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c004000, 0x00000010, 0x91d40000, - 0x00000008, 0x2d800101, 0x00000000, 0x00000000, 0x00000010, 0x91de0000, - 0x0000000c, 0x31620018, 0x00000008, 0x2d800001, 0x00000000, 0x00000000, - 0x00000010, 0x91de0000, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c000e00, - 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000008, 0x2a000007, - 0x00000018, 0x8000ff27, 0x00000010, 0xb1a0b016, 0x0000000b, 0x2fdf0002, - 0x00000000, 0x03d80000, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0, - 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150, - 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000, - 0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000008, 0x07000001, - 0x00000010, 0xb5de1c00, 0x00000010, 0x2c620002, 0x00000018, 0x8000000a, - 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c070000, 0x0000000c, 0x1f800001, - 0x00000010, 0x91de0000, 0x00000018, 0x8000ff11, 0x00000008, 0x2c8000b0, - 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, - 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000010, 0x91de0000, - 0x00000000, 0x2adf0000, 0x00000008, 0x2a00000a, 0x00000018, 0x8000ff07, - 0x00000000, 0x82265600, 0x0000000f, 0x47220008, 0x00000009, 0x070e000f, - 0x00000008, 0x070e0008, 0x00000008, 0x02800001, 0x00000007, 0x02851c00, - 0x00000008, 0x82850001, 0x00000000, 0x02840a00, 0x00000007, 0x42851c00, - 0x00000003, 0xc3aa5200, 0x00000000, 0x03b10e00, 0x00000010, 0x001f0000, - 0x0000000f, 0x0f280007, 0x00000007, 0x4b071c00, 0x00000000, 0x00000000, - 0x0000000f, 0x0a960003, 0x00000000, 0x0a955c00, 0x00000000, 0x4a005a00, - 0x00000000, 0x0c960a00, 0x00000009, 0x0c99ffff, 0x00000008, 0x0d00ffff, - 0x00000010, 0xb1963202, 0x00000008, 0x0f800005, 0x00000010, 0x00220020, - 0x00000000, 0x02a70000, 0x00000010, 0xb1850002, 0x00000008, 0x82850200, - 0x00000000, 0x02000000, 0x00000000, 0x03a60000, 0x00000018, 0x8000004e, - 0x00000000, 0x072b0000, 0x00000001, 0x878c1c00, 0x00000000, 0x870e1e00, - 0x00000000, 0x860c1e00, 0x00000000, 0x03061e00, 0x00000010, 0xb18e0003, - 0x00000018, 0x80000047, 0x00000018, 0x8000fffa, 0x00000010, 0x918c0003, - 0x00000010, 0xb1870002, 0x00000018, 0x80000043, 0x00000010, 0x91d40000, - 0x0000000c, 0x29800001, 0x00000000, 0x2a860000, 0x00000000, 0x230c0000, - 0x00000000, 0x2b070000, 0x00000010, 0xb187000e, 0x00000008, 0x2a000008, - 0x00000018, 0x8000003b, 0x00000010, 0x91d40000, 0x00000000, 0x28d18c00, - 0x00000000, 0x2a860000, 0x00000000, 0x230c0000, 0x00000000, 0x2b070000, - 0x00000018, 0x8000fff8, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001, - 0x00000000, 0x2aab0000, 0x00000000, 0xa3265600, 0x00000000, 0x2b000000, - 0x0000000c, 0x1f800001, 0x00000008, 0x2a000008, 0x00000018, 0x8000fec8, - 0x00000010, 0x91d40000, 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, - 0x00000008, 0x2a000009, 0x00000018, 0x8000fec3, 0x00000010, 0x91d40000, - 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000000, 0x29420000, - 0x00000008, 0x2a000002, 0x00000018, 0x8000febd, 0x00000018, 0x8000febc, - 0x00000010, 0xb1bcb016, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000, - 0x00000000, 0x2c3c0000, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, - 0x00000010, 0x91d40000, 0x00000008, 0x2d800150, 0x00000000, 0x00000000, - 0x00000010, 0x205f0000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000, - 0x00000008, 0x2d800108, 0x00000008, 0x07000001, 0x00000010, 0xb5de1c00, - 0x00000010, 0x2c620002, 0x00000018, 0x8000000a, 0x0000000b, 0x2fdf0002, - 0x00000000, 0x2c070000, 0x0000000c, 0x1f800000, 0x00000010, 0x91de0000, - 0x00000018, 0x8000fea6, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, - 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x0000000c, 0x29800000, - 0x0000000c, 0x1f800000, 0x00000010, 0x91de0000, 0x00000000, 0x2adf0000, - 0x00000008, 0x2a000006, 0x00000018, 0x8000fe9c, 0x00000008, 0x03050004, - 0x00000006, 0x83040c00, 0x00000008, 0x02850200, 0x00000000, 0x86050c00, - 0x00000001, 0x860c0e00, 0x00000008, 0x02040004, 0x00000000, 0x02041800, - 0x00000000, 0x83871800, 0x00000018, 0x00020000 }; +static u8 bnx2_rv2p_proc1[] = { + 0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x56, 0xcf, 0x6b, + 0x13, 0x51, 0x10, 0x9e, 0xec, 0x6e, 0xb2, 0xdb, 0x74, 0xbb, 0x1b, 0x2b, + 0xda, 0xa0, 0xb1, 0x8d, 0x51, 0x6a, 0x7f, 0xa4, 0xb4, 0x11, 0x0f, 0x82, + 0x42, 0x25, 0x3d, 0x04, 0x54, 0x44, 0x7a, 0x28, 0x22, 0x82, 0x36, 0x8a, + 0xfe, 0x1b, 0xa1, 0x3f, 0xd2, 0x4b, 0x10, 0x7a, 0xb0, 0x58, 0xf1, 0x50, + 0x10, 0x2a, 0x68, 0x0f, 0xc9, 0xa1, 0x20, 0x52, 0x11, 0xda, 0x8b, 0x07, + 0x2f, 0x42, 0x0f, 0x7a, 0x69, 0xbd, 0xa8, 0xff, 0x82, 0x08, 0x4d, 0x7c, + 0x6f, 0x66, 0x9e, 0xee, 0x6e, 0xb2, 0x4d, 0x15, 0xc1, 0x85, 0xf6, 0xe3, + 0xbd, 0x9d, 0x79, 0x33, 0xf3, 0xcd, 0x37, 0xfb, 0x62, 0x01, 0x40, 0x04, + 0x60, 0xcd, 0x46, 0x2c, 0x8d, 0x26, 0x04, 0x1a, 0x30, 0x7e, 0x52, 0x62, + 0x16, 0xde, 0xa6, 0x25, 0x4e, 0x44, 0xc6, 0xd3, 0x49, 0x81, 0x7b, 0x0d, + 0x28, 0xc9, 0x75, 0x4f, 0xf5, 0x55, 0xad, 0x53, 0xa0, 0x06, 0xbb, 0xa3, + 0x80, 0xcf, 0x47, 0x9d, 0xf0, 0x7c, 0xd6, 0x42, 0x2c, 0x31, 0xc2, 0x48, + 0x02, 0x61, 0x7b, 0x51, 0xae, 0xad, 0x48, 0x69, 0xc4, 0x42, 0x3f, 0xd0, + 0x68, 0x7f, 0x67, 0xd1, 0x15, 0xff, 0x53, 0xf0, 0x39, 0x2f, 0xd7, 0x56, + 0x7c, 0x0e, 0xed, 0xaa, 0xec, 0x2f, 0xfe, 0xd0, 0xfe, 0xba, 0xf0, 0x03, + 0x7e, 0x94, 0x5f, 0x02, 0xcf, 0x29, 0x66, 0x65, 0x5e, 0xdd, 0x22, 0xa0, + 0xca, 0xc7, 0x46, 0x2c, 0xf5, 0x91, 0xb5, 0x89, 0xef, 0xbf, 0x8a, 0xbc, + 0x55, 0xdc, 0x76, 0xf1, 0x82, 0xf9, 0x06, 0xe3, 0x26, 0x91, 0x1f, 0x28, + 0xf9, 0xe3, 0x00, 0xc8, 0xfd, 0x4f, 0x8d, 0x5f, 0xfb, 0x83, 0xfe, 0xf7, + 0xbb, 0x43, 0xf2, 0xbc, 0x28, 0xc0, 0x90, 0xb4, 0xdb, 0xe6, 0x7c, 0xc6, + 0xe0, 0xb4, 0x96, 0xc4, 0xf7, 0x06, 0xfa, 0x1f, 0x11, 0xe7, 0x4a, 0xec, + 0x61, 0x3c, 0xce, 0x78, 0x95, 0xb1, 0xc2, 0xe8, 0x32, 0x3a, 0x8c, 0x5d, + 0x8c, 0x36, 0xe3, 0x26, 0x63, 0x9c, 0xb1, 0x83, 0xd1, 0x62, 0xdc, 0x63, + 0x8c, 0x31, 0x46, 0x19, 0x1b, 0x8c, 0x46, 0x84, 0x50, 0xe3, 0xf5, 0x63, + 0x46, 0xe0, 0xba, 0x23, 0x81, 0xba, 0x5f, 0xb3, 0x2e, 0x24, 0x6f, 0xfc, + 0x7e, 0x50, 0xd9, 0x31, 0xef, 0x58, 0xf7, 0x3a, 0xdb, 0x75, 0x57, 0x57, + 0x02, 0xfa, 0x49, 0xef, 0xab, 0x9b, 0x54, 0x8b, 0x3e, 0xb8, 0x58, 0xcf, + 0x9d, 0x82, 0x8b, 0x71, 0x9c, 0x18, 0xed, 0xab, 0xb4, 0x6e, 0xb8, 0x84, + 0xf7, 0xe2, 0x84, 0x5f, 0x18, 0xef, 0x77, 0x12, 0x4e, 0x77, 0xc9, 0x7c, + 0x0e, 0x8b, 0x80, 0xea, 0x1c, 0x95, 0x4f, 0xbb, 0x3c, 0xc2, 0xe2, 0xa9, + 0xbc, 0xda, 0xc5, 0x25, 0x2c, 0x6a, 0xfe, 0xfa, 0x9f, 0x8c, 0x11, 0x1a, + 0x39, 0x22, 0x75, 0xc9, 0x16, 0x3d, 0x83, 0x46, 0x63, 0xd9, 0x36, 0xe4, + 0xfa, 0xdc, 0xf2, 0x7b, 0xd4, 0xfb, 0xd9, 0xa5, 0x1a, 0xe7, 0xe7, 0x2a, + 0x9e, 0x69, 0x0e, 0x32, 0x40, 0xeb, 0x49, 0xe4, 0x1d, 0x04, 0x5a, 0xb8, + 0x86, 0x8c, 0xbf, 0x5f, 0xa4, 0x43, 0x9d, 0xfb, 0x31, 0xcb, 0xfd, 0x38, + 0x11, 0xd2, 0x8f, 0xb0, 0xb9, 0x68, 0x9e, 0xc7, 0xdb, 0xe9, 0x20, 0x6f, + 0x61, 0xf3, 0xa3, 0xf8, 0xa6, 0xdd, 0x3f, 0xe5, 0xf1, 0x01, 0xf3, 0x58, + 0x24, 0x1e, 0x93, 0xdf, 0x5a, 0xf2, 0x94, 0xf6, 0xf0, 0x24, 0xeb, 0xec, + 0x0d, 0xe9, 0x73, 0x58, 0x7d, 0xd9, 0xbf, 0xee, 0x73, 0x20, 0x3f, 0xb8, + 0x8b, 0xdf, 0x9b, 0x04, 0x14, 0x0b, 0x2a, 0x5f, 0x3f, 0xcf, 0xc7, 0xa8, + 0xdf, 0x30, 0x97, 0x93, 0xfb, 0x62, 0xfe, 0x36, 0x35, 0x5c, 0x1b, 0xf9, + 0x88, 0x04, 0xab, 0x98, 0x23, 0x7f, 0x47, 0xd3, 0x78, 0x7d, 0x50, 0x5d, + 0xa8, 0xbe, 0x4b, 0x8c, 0x41, 0x7e, 0x9a, 0xeb, 0xcc, 0x50, 0x3c, 0xd2, + 0x81, 0xc1, 0x3a, 0xc8, 0xf3, 0xf7, 0x28, 0xc8, 0x87, 0x55, 0x5d, 0x59, + 0xf4, 0xce, 0x75, 0x12, 0x8a, 0x39, 0xd2, 0x55, 0x73, 0x5f, 0x59, 0x6f, + 0x6b, 0xea, 0xbb, 0x84, 0xdb, 0xd5, 0x92, 0xee, 0xab, 0xf7, 0x12, 0x64, + 0xbd, 0x3c, 0x47, 0x5a, 0xe8, 0xa3, 0x5d, 0x1c, 0xdf, 0x79, 0x0e, 0x64, + 0x5b, 0x7d, 0x6f, 0x4c, 0xae, 0xeb, 0x0c, 0xeb, 0xfb, 0x68, 0x93, 0xbe, + 0xd5, 0x7d, 0xf5, 0xef, 0x74, 0xce, 0xf5, 0x9b, 0x68, 0x97, 0xda, 0x59, + 0xf7, 0xde, 0x4f, 0x71, 0xcf, 0xfd, 0x44, 0x6e, 0xa6, 0xca, 0xbb, 0xcf, + 0x7b, 0xaf, 0x1c, 0x0a, 0xe9, 0x83, 0xf7, 0x3e, 0x0a, 0xd6, 0xeb, 0xd7, + 0x23, 0xf5, 0x35, 0xce, 0xf5, 0x9b, 0x0d, 0xee, 0xc3, 0x54, 0xff, 0x0c, + 0xe9, 0x3f, 0x53, 0x90, 0xfa, 0x71, 0xc1, 0x31, 0xe9, 0x7c, 0x42, 0x71, + 0x8e, 0x66, 0x62, 0xde, 0xf3, 0x1a, 0xad, 0xe7, 0x67, 0xd0, 0x2f, 0x3e, + 0xa7, 0xf6, 0xf3, 0x48, 0xd8, 0xe4, 0x8b, 0x2d, 0xe2, 0xbd, 0xa6, 0xab, + 0xb9, 0x70, 0x91, 0xef, 0x01, 0x97, 0xec, 0xcc, 0x2b, 0x8a, 0x2f, 0xb9, + 0xaf, 0xc3, 0x12, 0xcd, 0xc5, 0xad, 0x47, 0x84, 0x37, 0xe1, 0x32, 0x9d, + 0xfb, 0xfb, 0xfb, 0x66, 0x21, 0x42, 0x97, 0x57, 0xc7, 0x51, 0xa1, 0x63, + 0x9c, 0x63, 0x25, 0x57, 0x78, 0xae, 0x11, 0x9f, 0xf3, 0xa4, 0x73, 0x8d, + 0xf3, 0xc3, 0xab, 0x45, 0x3e, 0xab, 0xba, 0xac, 0xf7, 0x9a, 0xd2, 0x1d, + 0x0c, 0x9b, 0x38, 0x3f, 0xa9, 0xca, 0x02, 0x2e, 0x7b, 0x1d, 0x46, 0xbb, + 0x4c, 0x18, 0xc3, 0xfc, 0x75, 0x78, 0x58, 0x93, 0x7e, 0x05, 0xbe, 0xdf, + 0x7e, 0xb0, 0x5e, 0x74, 0xa8, 0xf0, 0xef, 0x8b, 0x05, 0x7c, 0x3f, 0x01, + 0xcd, 0xf7, 0x1b, 0xc5, 0x29, 0x0f, 0x11, 0xda, 0xa7, 0xb8, 0xaf, 0xc3, + 0xd2, 0xce, 0x11, 0x7e, 0xdc, 0x3f, 0xec, 0xc3, 0x05, 0x8f, 0x3f, 0x42, + 0xe5, 0xc3, 0x40, 0x98, 0xbf, 0xb4, 0xff, 0xde, 0xe2, 0x3e, 0xa5, 0xf7, + 0x2f, 0xc9, 0x7e, 0xaa, 0xff, 0x19, 0xd7, 0x3f, 0xec, 0xd5, 0xbd, 0x8a, + 0xf7, 0xae, 0xbe, 0xff, 0x7d, 0xdc, 0xc1, 0x76, 0x5b, 0xfb, 0xd8, 0xd1, + 0xf1, 0xf9, 0x41, 0xef, 0xfd, 0xfd, 0xa6, 0x4e, 0x3c, 0x6d, 0xd4, 0xd5, + 0x5c, 0x6d, 0x84, 0xcc, 0xd5, 0xc5, 0xff, 0x3a, 0x57, 0x10, 0x98, 0xab, + 0xd5, 0xfa, 0xc1, 0xe6, 0x0a, 0xb8, 0x7e, 0x08, 0x99, 0xab, 0x18, 0xf3, + 0xf0, 0x94, 0xcf, 0x33, 0x20, 0xaa, 0xc7, 0xb0, 0x7d, 0xc6, 0x2c, 0xeb, + 0x92, 0xf4, 0x68, 0x47, 0xcb, 0xa8, 0x3f, 0xc7, 0x2e, 0x93, 0x9d, 0x41, + 0xfb, 0x49, 0x85, 0x0b, 0xb3, 0xf4, 0x7b, 0x4a, 0x83, 0x9f, 0x94, 0x15, + 0x12, 0x3d, 0x80, 0x0b, 0x00, 0x00, 0x00 }; -static u32 bnx2_rv2p_proc2[] = { - 0x00000000, 0x2a000000, 0x00000010, 0xb1d40000, 0x00000008, 0x02540003, - 0x00000018, 0x00040000, 0x00000018, 0x8000000a, 0x00000018, 0x8000000a, - 0x00000018, 0x8000000e, 0x00000018, 0x80000056, 0x00000018, 0x800001b9, - 0x00000018, 0x800001e1, 0x00000018, 0x8000019b, 0x00000018, 0x800001f9, - 0x00000018, 0x8000019f, 0x00000018, 0x800001a6, 0x00000018, 0x80000000, - 0x0000000c, 0x29800001, 0x00000000, 0x2a000000, 0x0000000c, 0x29800000, - 0x00000010, 0x20530000, 0x00000018, 0x8000ffee, 0x0000000c, 0x29800001, - 0x00000010, 0x91de0000, 0x00000010, 0x001f0000, 0x00000000, 0x2f80aa00, - 0x00000000, 0x2a000000, 0x00000000, 0x0d610000, 0x00000000, 0x03620000, - 0x00000000, 0x2c400000, 0x00000000, 0x02638c00, 0x00000000, 0x26460000, - 0x00000010, 0x00420002, 0x00000008, 0x02040012, 0x00000010, 0xb9060836, - 0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, - 0x00000000, 0x0b660000, 0x00000000, 0x0c000000, 0x00000000, 0x0b800000, - 0x00000010, 0x00420009, 0x00000008, 0x0cc60012, 0x00000008, 0x0f800003, - 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000008, 0x27110012, - 0x00000000, 0x66900000, 0x00000008, 0xa31b0012, 0x00000018, 0x80000008, - 0x00000000, 0x0cc60000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000, - 0x00000010, 0x009f0000, 0x00000000, 0x27110000, 0x00000000, 0x66900000, - 0x00000000, 0x231b0000, 0x00000010, 0xb197320e, 0x00000000, 0x25960000, - 0x00000000, 0x021b0000, 0x00000010, 0x001f0000, 0x00000008, 0x0f800003, - 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000000, 0x22c50800, - 0x00000010, 0x009f0000, 0x00000000, 0x27002200, 0x00000000, 0x26802000, - 0x00000000, 0x231b0000, 0x0000000c, 0x69520001, 0x00000018, 0x8000fff3, - 0x00000010, 0x01130002, 0x00000010, 0xb1980003, 0x00000010, 0x001f0000, - 0x00000008, 0x0f800004, 0x00000008, 0x22000003, 0x00000008, 0x2c80000c, - 0x00000008, 0x2d00000c, 0x00000010, 0x009f0000, 0x00000000, 0x25960000, - 0x0000000c, 0x29800000, 0x00000000, 0x32140000, 0x00000000, 0x32950000, - 0x00000000, 0x33160000, 0x00000000, 0x31e32e00, 0x00000008, 0x2d800010, - 0x00000010, 0x20530000, 0x00000018, 0x8000ffac, 0x00000000, 0x23000000, - 0x00000000, 0x25e60000, 0x00000008, 0x2200000b, 0x0000000c, 0x69520000, - 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000018, 0x8000ffa5, - 0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000, - 0x00000010, 0x001f0000, 0x00000000, 0x02700000, 0x00000000, 0x0d620000, - 0x00000000, 0xbb630800, 0x00000000, 0x2a000000, 0x00000009, 0x076000ff, - 0x0000000f, 0x2c0e0007, 0x00000008, 0x2c800000, 0x00000008, 0x2d000064, - 0x00000008, 0x2d80011c, 0x00000009, 0x06420002, 0x0000000c, 0x61420001, - 0x00000000, 0x0f400000, 0x00000000, 0x02d08c00, 0x00000000, 0x23000000, - 0x00000004, 0x826da000, 0x00000000, 0x8304a000, 0x00000000, 0x22c50c00, - 0x00000000, 0x03760000, 0x00000004, 0x83860a00, 0x00000000, 0x83870c00, - 0x00000010, 0x91de0000, 0x00000000, 0x037c0000, 0x00000000, 0x837b0c00, - 0x00000001, 0x83060e00, 0x00000000, 0x83870c00, 0x00000000, 0x82850e00, - 0x00000010, 0xb1860016, 0x0000000f, 0x47610018, 0x00000000, 0x068e0000, - 0x0000000f, 0x47670010, 0x0000000f, 0x47e20010, 0x00000000, 0x870e1e00, - 0x00000010, 0xb70e1a10, 0x00000010, 0x0ce7000e, 0x00000008, 0x22000009, - 0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400, - 0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004, - 0x00000018, 0x8000023f, 0x00000000, 0x37ed0000, 0x0000000c, 0x73e7001a, - 0x00000010, 0x20530000, 0x00000008, 0x22000008, 0x0000000c, 0x61420004, - 0x00000000, 0x02f60000, 0x00000004, 0x82840a00, 0x00000010, 0xb1840a2b, - 0x00000010, 0x2d67000a, 0x00000010, 0xb96d0804, 0x00000004, 0xb6ed0a00, - 0x00000000, 0x37ed0000, 0x00000018, 0x80000029, 0x0000000c, 0x61420000, - 0x00000000, 0x37040000, 0x00000000, 0x37850000, 0x0000000c, 0x33e7001a, - 0x00000018, 0x80000024, 0x00000010, 0xb96d0809, 0x00000004, 0xb6ed0a00, - 0x00000000, 0x036d0000, 0x00000004, 0xb76e0c00, 0x00000010, 0x91ee0c1f, - 0x0000000c, 0x73e7001a, 0x00000004, 0xb6ef0c00, 0x00000000, 0x37ed0000, - 0x00000018, 0x8000001b, 0x0000000c, 0x61420000, 0x00000010, 0xb7ee0a05, - 0x00000010, 0xb96f0815, 0x00000003, 0xb76e0800, 0x00000004, 0xb7ef0a00, - 0x00000018, 0x80000015, 0x00000010, 0x0ce7000c, 0x00000008, 0x22000009, - 0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400, - 0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004, - 0x00000018, 0x80000215, 0x00000010, 0x20530000, 0x00000008, 0x22000008, - 0x0000000c, 0x61420004, 0x00000000, 0x37040000, 0x00000000, 0x37850000, - 0x00000000, 0x036d0000, 0x00000003, 0xb8f10c00, 0x00000018, 0x80000004, - 0x00000000, 0x02840000, 0x00000002, 0x21421800, 0x0000000c, 0x61420000, - 0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff, - 0x00000000, 0x23000000, 0x00000010, 0xb1840a3d, 0x00000010, 0x01420002, - 0x00000004, 0xb8f10a00, 0x00000003, 0x83760a00, 0x00000010, 0xb8040c39, - 0x00000010, 0xb7e6080a, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, - 0x00000009, 0x0c68ffff, 0x00000009, 0x0b67ffff, 0x00000000, 0x0be60000, - 0x00000000, 0x0c840000, 0x00000010, 0xb197320c, 0x00000008, 0x0f800002, - 0x00000018, 0x8000000a, 0x00000000, 0x0a6a0000, 0x00000000, 0x0aeb0000, - 0x00000000, 0x0c000000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0be90000, - 0x00000000, 0x0c840000, 0x00000010, 0xb1973203, 0x00000008, 0x0f800002, - 0x00000018, 0x80000001, 0x00000010, 0x001f0000, 0x00000000, 0x0c860000, - 0x00000000, 0x06980000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000, - 0x00000010, 0x009f0000, 0x00000010, 0xb1973210, 0x00000000, 0x231b0000, - 0x00000000, 0x02043600, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010, - 0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000, - 0x0000000c, 0x29000000, 0x00000018, 0x800001de, 0x00000000, 0x06980000, - 0x00000010, 0x20530000, 0x00000000, 0x22c58c00, 0x00000010, 0x001f0000, - 0x00000008, 0x0f800003, 0x00000018, 0x8000fff0, 0x00000000, 0x02043600, - 0x00000000, 0x231b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010, - 0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000, - 0x0000000c, 0x29000000, 0x00000010, 0x91840a02, 0x00000002, 0x21421800, - 0x00000000, 0x32140000, 0x00000000, 0x32950000, 0x00000005, 0x73e72c00, - 0x00000005, 0x74683000, 0x00000000, 0x33170000, 0x00000018, 0x80000138, - 0x00000010, 0x91c60004, 0x00000008, 0x07000004, 0x00000010, 0xb1c41c02, - 0x00000010, 0x91840a04, 0x00000018, 0x800001c3, 0x00000010, 0x20530000, - 0x00000000, 0x22c58c00, 0x00000010, 0xb1840a8e, 0x0000000c, 0x21420006, - 0x00000010, 0x0ce7001a, 0x0000000f, 0x43680010, 0x00000000, 0x03f30c00, - 0x00000010, 0x91870850, 0x0000000f, 0x46ec0010, 0x00000010, 0xb68d0c4e, - 0x00000000, 0x838d0c00, 0x00000000, 0xa3050800, 0x00000001, 0xa3460e00, - 0x00000000, 0x02048c00, 0x00000010, 0x91840a02, 0x00000002, 0x21421800, - 0x00000010, 0x001f0000, 0x00000008, 0x22000008, 0x00000003, 0x8384a000, - 0x0000000f, 0x65870010, 0x00000009, 0x2607ffff, 0x00000000, 0x27750c00, - 0x00000000, 0x66f40000, 0x0000000c, 0x29000000, 0x00000018, 0x800001aa, - 0x00000000, 0x03068c00, 0x00000003, 0xf4680c00, 0x00000010, 0x20530000, - 0x00000000, 0x22c58c00, 0x00000018, 0x8000ffe5, 0x00000000, 0x39760000, - 0x00000000, 0x39840000, 0x0000000c, 0x33e70019, 0x00000010, 0x001f0000, - 0x00000000, 0x031e0000, 0x00000000, 0x0760fe00, 0x0000000f, 0x0f0e0007, - 0x00000000, 0x83850800, 0x00000000, 0x0a7d0000, 0x00000000, 0x0afe0000, - 0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000, 0x00000000, 0x0c000000, - 0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003, - 0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff, - 0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010, - 0x00000002, 0x33e70e00, 0x00000000, 0x28f30000, 0x00000010, 0x009f0000, - 0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800, - 0x00000008, 0x22000006, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000, - 0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010, - 0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000, - 0x0000000c, 0x29000000, 0x00000018, 0x8000017e, 0x00000003, 0xf4683600, - 0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400, - 0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004, - 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000, - 0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000, - 0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000, - 0x00000000, 0x22c53600, 0x00000018, 0x8000ffac, 0x00000010, 0x001f0000, - 0x00000000, 0x031e0000, 0x00000000, 0x83850800, 0x00000009, 0x076000ff, - 0x0000000f, 0x0f0e0007, 0x00000000, 0x0c000000, 0x00000000, 0x0a7d0000, - 0x00000000, 0x0afe0000, 0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000, - 0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003, - 0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff, - 0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010, - 0x00000002, 0x33e70e00, 0x00000000, 0x39840000, 0x00000003, 0xb9720800, - 0x00000000, 0x28f30000, 0x0000000f, 0x65680010, 0x00000010, 0x009f0000, - 0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800, - 0x00000008, 0x22000007, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000, - 0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010, - 0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000, - 0x0000000c, 0x29000000, 0x00000018, 0x80000145, 0x00000003, 0xf4683600, - 0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400, - 0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004, - 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000, - 0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000, - 0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000, - 0x00000000, 0x22c53600, 0x00000018, 0x8000ff73, 0x00000010, 0x0ce70005, - 0x00000008, 0x2c80000c, 0x00000008, 0x2d000070, 0x00000008, 0x2d800010, - 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000018, 0x8000011d, - 0x00000000, 0x2c1e0000, 0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010, - 0x00000008, 0x2d800048, 0x00000000, 0x00000000, 0x00000010, 0x91de0000, - 0x00000018, 0x8000fe5d, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000, - 0x00000010, 0x001f0000, 0x00000000, 0x0f008000, 0x00000008, 0x0f800007, - 0x00000018, 0x80000006, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000, - 0x00000010, 0x001f0000, 0x0000000f, 0x0f470007, 0x00000008, 0x0f800008, - 0x00000018, 0x80000119, 0x00000010, 0x20530000, 0x00000018, 0x8000fe4f, - 0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000, - 0x00000000, 0x2a000000, 0x00000009, 0x0261ffff, 0x0000000d, 0x70e10001, - 0x00000018, 0x80000101, 0x00000000, 0x2c400000, 0x00000008, 0x2c8000c4, - 0x00000008, 0x2d00001c, 0x00000008, 0x2d800001, 0x00000005, 0x70e10800, - 0x00000010, 0x91de0000, 0x00000018, 0x8000fe41, 0x0000000c, 0x29800001, - 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000, 0x00000010, 0x001f0000, - 0x00000000, 0x02700000, 0x00000000, 0x0d620000, 0x00000000, 0xbb630800, - 0x00000000, 0x2a000000, 0x00000000, 0x0f400000, 0x00000000, 0x2c400000, - 0x0000000c, 0x73e7001b, 0x00000010, 0x0ce7000e, 0x00000000, 0x286d0000, - 0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff, 0x00000018, 0x80000069, - 0x00000008, 0x02000004, 0x00000010, 0x91c40803, 0x00000018, 0x800000f6, - 0x00000010, 0x20530000, 0x00000018, 0x800000e5, 0x00000008, 0x2c8000b8, - 0x00000008, 0x2d000010, 0x00000008, 0x2d800048, 0x00000018, 0x80000005, - 0x00000008, 0x2c8000c4, 0x00000008, 0x2d00001c, 0x00000008, 0x2d800001, - 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800048, - 0x00000008, 0x2d000068, 0x00000008, 0x2d800104, 0x00000000, 0x00000000, - 0x00000010, 0x91de0000, 0x00000000, 0x27f60000, 0x00000010, 0xb87a9e04, - 0x00000008, 0x2200000d, 0x00000018, 0x800000e2, 0x00000010, 0x20530000, - 0x00000018, 0x8000fe18, 0x0000000c, 0x29800001, 0x00000010, 0x91de0000, - 0x00000000, 0x2fd50000, 0x00000010, 0x001f0000, 0x00000000, 0x02700000, - 0x00000000, 0x0d620000, 0x00000000, 0xbb630800, 0x00000000, 0x2a000000, - 0x00000010, 0x0e670011, 0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010, - 0x00000009, 0x266dffff, 0x00000004, 0xb8f1a000, 0x00000000, 0x0f400000, - 0x0000000c, 0x73e7001c, 0x00000018, 0x80000040, 0x00000008, 0x02000004, - 0x00000010, 0x91c40802, 0x00000018, 0x800000cd, 0x00000000, 0x2c1e0000, - 0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010, 0x00000008, 0x2d800048, - 0x00000010, 0x20530000, 0x00000010, 0x91de0000, 0x00000018, 0x8000fdfe, - 0x0000000c, 0x29800001, 0x00000000, 0x03550000, 0x00000000, 0x06460000, - 0x00000000, 0x03d60000, 0x00000000, 0x2a000000, 0x0000000f, 0x0f480007, - 0x00000010, 0xb18c0027, 0x0000000f, 0x47420008, 0x00000009, 0x070e000f, - 0x00000008, 0x070e0008, 0x00000010, 0x001f0000, 0x00000008, 0x09000001, - 0x00000007, 0x09121c00, 0x00000003, 0xcbca9200, 0x00000000, 0x0b97a200, - 0x00000007, 0x4b171c00, 0x0000000f, 0x0a960003, 0x00000000, 0x0a959c00, - 0x00000000, 0x4a009a00, 0x00000008, 0x82120001, 0x00000001, 0x0c170800, - 0x00000000, 0x02180000, 0x00000000, 0x0c971800, 0x00000008, 0x0d00ffff, - 0x00000008, 0x0f800006, 0x0000000c, 0x29000000, 0x00000008, 0x22000001, - 0x00000000, 0x22c50c00, 0x00000010, 0x009f0000, 0x00000010, 0xb197320b, - 0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000, - 0x00000018, 0x800000a4, 0x00000000, 0x02180000, 0x00000010, 0x20530000, - 0x00000000, 0x22c53600, 0x00000010, 0x001f0000, 0x00000008, 0x0f800006, - 0x00000018, 0x8000fff5, 0x00000010, 0x91870002, 0x00000008, 0x2200000a, - 0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000, - 0x00000018, 0x80000098, 0x00000008, 0x0200000a, 0x00000010, 0x91c40804, - 0x00000010, 0x02c20003, 0x00000010, 0x001f0000, 0x00000008, 0x0f800008, - 0x00000010, 0x20530000, 0x00000018, 0x8000fdc9, 0x00000000, 0x06820000, - 0x00000010, 0x001f0000, 0x00000010, 0x0ce70028, 0x00000000, 0x03720000, - 0x00000000, 0xa8760c00, 0x00000000, 0x0cf60000, 0x00000010, 0xb8723224, - 0x00000000, 0x03440000, 0x00000008, 0x22000010, 0x00000000, 0x03ca0000, - 0x0000000f, 0x65680010, 0x00000000, 0x0bcf0000, 0x00000000, 0x27f20000, - 0x00000010, 0xb7ef3203, 0x0000000c, 0x21420004, 0x0000000c, 0x73e70019, - 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x8000007e, - 0x00000004, 0xb9723200, 0x00000010, 0x20530000, 0x00000000, 0x22060000, - 0x0000000c, 0x61420004, 0x00000000, 0x25070000, 0x00000000, 0x27970000, - 0x00000000, 0x290e0000, 0x00000010, 0x0ce70010, 0x00000010, 0xb873320f, - 0x0000000f, 0x436c0010, 0x00000000, 0x03f30c00, 0x00000000, 0x03f30000, - 0x00000000, 0x83990e00, 0x00000001, 0x83860e00, 0x00000000, 0x83060e00, - 0x00000003, 0xf66c0c00, 0x00000000, 0x39f30e00, 0x00000000, 0x3af50e00, - 0x00000000, 0x7a740000, 0x0000000f, 0x43680010, 0x00000001, 0x83860e00, - 0x00000000, 0x83060e00, 0x00000003, 0xf4680c00, 0x00000000, 0x286d0000, - 0x00000000, 0x03690000, 0x00000010, 0xb1f60c54, 0x00000000, 0x0a6a0000, - 0x00000000, 0x0aeb0000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0c000000, - 0x00000000, 0x0be90000, 0x00000003, 0x8cf6a000, 0x0000000c, 0x09800002, - 0x00000010, 0x009f0000, 0x00000010, 0xb8173209, 0x00000000, 0x35140000, - 0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34970000, - 0x00000004, 0xb8f12e00, 0x00000010, 0x001f0000, 0x00000008, 0x0f800004, - 0x00000018, 0x8000fff7, 0x00000000, 0x03e90000, 0x00000010, 0xb8f6a01a, - 0x00000010, 0x20130019, 0x00000010, 0xb1f10e18, 0x00000000, 0x83973200, - 0x00000000, 0x38700e00, 0x00000000, 0xbb760e00, 0x00000000, 0x37d00000, - 0x0000000c, 0x73e7001a, 0x00000003, 0xb8f1a000, 0x00000000, 0x32140000, - 0x00000000, 0x32950000, 0x00000005, 0x73e72c00, 0x00000000, 0x33190000, - 0x00000005, 0x74680000, 0x00000010, 0x0ce7000d, 0x00000008, 0x22000009, - 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x0000000c, 0x73e70019, - 0x0000000f, 0x65680010, 0x0000000c, 0x21420004, 0x00000018, 0x8000003c, - 0x00000010, 0x20530000, 0x0000000c, 0x61420004, 0x00000000, 0x290e0000, - 0x00000018, 0x80000002, 0x00000010, 0x91973206, 0x00000000, 0x35140000, - 0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34990000, - 0x00000004, 0xb8f13200, 0x00000000, 0x83690c00, 0x00000010, 0xb1860013, - 0x00000000, 0x28e90000, 0x00000008, 0x22000004, 0x00000000, 0x23ec0000, - 0x00000000, 0x03690000, 0x00000010, 0xb8660c07, 0x00000009, 0x036cffff, - 0x00000000, 0x326a0000, 0x00000000, 0x32eb0000, 0x00000005, 0x73e70c00, - 0x00000000, 0x33690000, 0x00000005, 0x74680000, 0x0000000c, 0x73e7001c, - 0x00000000, 0x03690000, 0x00000010, 0xb1f60c12, 0x00000010, 0xb1d00c11, - 0x0000000c, 0x21420005, 0x0000000c, 0x33e7001c, 0x00000018, 0x8000000e, - 0x00000010, 0x2e67000d, 0x00000000, 0x03690000, 0x00000010, 0xb1f60c0b, - 0x00000010, 0xb1d00c0a, 0x00000000, 0x03440000, 0x00000008, 0x2200000c, - 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x80000015, - 0x0000000c, 0x33e7001c, 0x00000010, 0x20530000, 0x00000000, 0x22060000, - 0x00000000, 0x290e0000, 0x00000018, 0x000d0000, 0x00000000, 0x06820000, - 0x00000010, 0x2de7000d, 0x00000010, 0x0ce7000c, 0x00000000, 0x27f20000, - 0x00000010, 0xb96d9e0a, 0x00000000, 0xa86d9e00, 0x00000009, 0x0361ffff, - 0x00000010, 0xb7500c07, 0x00000008, 0x2200000f, 0x0000000f, 0x65680010, - 0x00000000, 0x29000000, 0x00000018, 0x80000004, 0x0000000c, 0x33e7001b, - 0x00000010, 0x20530000, 0x00000018, 0x000d0000, 0x00000000, 0x2b820000, - 0x00000010, 0x20d2002f, 0x00000010, 0x0052002e, 0x00000009, 0x054e0007, - 0x00000010, 0xb18a002c, 0x00000000, 0x050a8c00, 0x00000008, 0x850a0008, - 0x00000010, 0x918a0029, 0x00000003, 0xc5008800, 0x00000008, 0xa3460001, - 0x00000010, 0xb1c60007, 0x00000008, 0x22000001, 0x0000000c, 0x29800000, - 0x00000010, 0x20530000, 0x00000000, 0x274e8c00, 0x00000000, 0x66cd0000, - 0x00000000, 0x22c58c00, 0x00000008, 0x22000014, 0x00000003, 0x22c58e00, - 0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00, - 0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000, - 0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x0000000c, 0x69520000, - 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000003, 0x22c58e00, - 0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00, - 0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000, - 0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x00000000, 0xa2c58c00, - 0x00000000, 0xa74e8c00, 0x00000000, 0xe6cd0000, 0x0000000f, 0x620a0010, - 0x00000008, 0x23460001, 0x0000000c, 0x29800000, 0x00000010, 0x20530000, - 0x0000000c, 0x29520000, 0x00000018, 0x80000002, 0x0000000c, 0x29800000, - 0x00000018, 0x00570000 }; +static u8 bnx2_rv2p_proc2[] = { + 0x1f, 0x8b, 0x08, 0x08, 0x7e, 0xd1, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xcd, 0x58, 0x5b, 0x6c, + 0x54, 0x55, 0x14, 0x3d, 0xf3, 0xe8, 0xcc, 0x9d, 0xe9, 0xed, 0x9d, 0xf2, + 0xb2, 0x03, 0xad, 0x08, 0xe5, 0xd1, 0x56, 0x29, 0xe8, 0x54, 0xab, 0x18, + 0x15, 0x2c, 0x5a, 0x8c, 0x26, 0x68, 0xf0, 0xf9, 0x63, 0x14, 0x04, 0xda, + 0x9a, 0x56, 0x9b, 0x16, 0xfb, 0x81, 0xaf, 0x09, 0x14, 0x6a, 0x4c, 0x25, + 0xd6, 0x08, 0xc5, 0x47, 0xa0, 0x11, 0x1f, 0x84, 0xf0, 0xd3, 0x1f, 0x3b, + 0x8d, 0x7f, 0x0a, 0x24, 0x6a, 0x88, 0xc4, 0xa8, 0x9f, 0x24, 0x68, 0xa0, + 0x21, 0x0a, 0x58, 0x8b, 0x63, 0x4c, 0xb4, 0xf5, 0xec, 0xbd, 0xf6, 0xb9, + 0x73, 0xef, 0x6d, 0x8b, 0x1a, 0xf9, 0x70, 0x3e, 0xba, 0x7b, 0xce, 0xd9, + 0x67, 0x3f, 0xd6, 0xde, 0x67, 0x9f, 0x7d, 0xae, 0x52, 0xfc, 0xbb, 0xb6, + 0x94, 0xc9, 0x37, 0x83, 0x96, 0xfe, 0x1b, 0x51, 0x0f, 0x85, 0xd3, 0x3c, + 0x8e, 0x2a, 0xa2, 0x49, 0xa5, 0xb2, 0x5e, 0xea, 0x08, 0x7d, 0x44, 0xe8, + 0x70, 0x08, 0xf4, 0xb4, 0xd0, 0x77, 0x84, 0xfe, 0x2e, 0xf4, 0x80, 0xd0, + 0x0f, 0x85, 0xea, 0x5f, 0xd6, 0xd6, 0x7f, 0xf4, 0xb0, 0x46, 0x89, 0x7e, + 0x1b, 0xd3, 0x35, 0xb0, 0xe3, 0xc1, 0x05, 0xc4, 0x77, 0x61, 0xa2, 0xc0, + 0x87, 0xf9, 0x53, 0x7d, 0xa0, 0xd7, 0x60, 0xd7, 0xe1, 0xec, 0x0a, 0xb3, + 0x1f, 0x64, 0x43, 0x09, 0xe8, 0xc6, 0x08, 0xe8, 0xea, 0x65, 0x4c, 0x7a, + 0x9f, 0x0a, 0x63, 0xdc, 0xb8, 0x94, 0xf6, 0x87, 0x55, 0x83, 0x22, 0x3f, + 0x67, 0xaa, 0x68, 0x98, 0xc6, 0xf5, 0x56, 0x6c, 0x18, 0xeb, 0x8f, 0xa5, + 0x40, 0x37, 0x25, 0x41, 0xcf, 0x08, 0xdd, 0x52, 0x2c, 0x7a, 0x6c, 0x31, + 0xbf, 0x98, 0xf6, 0x25, 0x5c, 0x39, 0xc7, 0x6d, 0xe0, 0x96, 0x95, 0xfd, + 0x4a, 0xc1, 0xce, 0x03, 0xb2, 0x3e, 0xa3, 0x0a, 0xb3, 0xaf, 0x6f, 0xc1, + 0xb8, 0xfc, 0x20, 0xf9, 0xa7, 0xff, 0xcf, 0x62, 0x7e, 0xfa, 0xfd, 0xf8, + 0x15, 0xf6, 0x83, 0x96, 0x2f, 0xa2, 0x75, 0x27, 0xd3, 0x3f, 0x88, 0xf1, + 0xde, 0x25, 0x32, 0x1f, 0x36, 0xf8, 0x18, 0x79, 0x41, 0x5c, 0x99, 0x58, + 0xc7, 0x2a, 0x7d, 0xf2, 0x2b, 0x15, 0xe4, 0x2f, 0xc8, 0x2e, 0x35, 0xf2, + 0x81, 0xfb, 0xfa, 0x16, 0xb2, 0x73, 0x4c, 0xc7, 0x01, 0xb8, 0xcd, 0x0a, + 0x95, 0xb2, 0xdc, 0x7d, 0x83, 0x5e, 0x3d, 0x51, 0xad, 0x07, 0xfa, 0x54, + 0xa5, 0xc5, 0x20, 0x65, 0x97, 0x81, 0xaa, 0x5a, 0xbf, 0x1f, 0x7b, 0x97, + 0x18, 0x7b, 0x30, 0x9e, 0x9d, 0x01, 0xdd, 0x23, 0xf4, 0xaa, 0x3a, 0x26, + 0xcb, 0x7f, 0xb8, 0xc1, 0x62, 0x0c, 0xb2, 0xb5, 0xde, 0x7c, 0x38, 0x32, + 0x61, 0xf0, 0x52, 0x8b, 0x40, 0xce, 0x2e, 0x21, 0x3e, 0x1d, 0x9c, 0x4a, + 0xc8, 0x5d, 0xdf, 0x32, 0x55, 0x1e, 0x7d, 0x30, 0x45, 0x1e, 0x61, 0xff, + 0xb7, 0x2b, 0x7c, 0xf9, 0xa4, 0xda, 0x25, 0x4f, 0x36, 0x22, 0x8f, 0xac, + 0xa7, 0x3e, 0x91, 0x85, 0x6b, 0x13, 0xfa, 0xcf, 0x84, 0x7a, 0x32, 0x4e, + 0x01, 0x8a, 0x2b, 0x87, 0xfd, 0x53, 0xe2, 0xe7, 0x26, 0xed, 0x27, 0xd1, + 0x8a, 0x50, 0xb6, 0x36, 0xc1, 0x38, 0x35, 0xc4, 0xa0, 0xaf, 0x61, 0x03, + 0xb6, 0xaf, 0x46, 0x5c, 0x7b, 0x4f, 0x86, 0x8d, 0xfd, 0x51, 0xfa, 0x3b, + 0xd0, 0xb6, 0x9d, 0x47, 0x03, 0xd1, 0x1d, 0x4c, 0xed, 0x63, 0x95, 0x58, + 0xee, 0x8a, 0xf0, 0x7a, 0x72, 0x97, 0xcc, 0xf7, 0xec, 0xf0, 0xdb, 0xfd, + 0x02, 0xf2, 0xdb, 0x7e, 0x7e, 0x47, 0x88, 0xa8, 0x13, 0x73, 0xf9, 0x98, + 0x3a, 0x3b, 0xb7, 0x13, 0xff, 0x55, 0x6a, 0xd7, 0x20, 0x29, 0x4e, 0xab, + 0x0d, 0x6b, 0xb1, 0x6f, 0x77, 0x2c, 0xc5, 0xb8, 0x36, 0xad, 0x05, 0xfd, + 0x1e, 0xf3, 0xf3, 0x9d, 0x1e, 0xe2, 0x2f, 0x9d, 0xe7, 0x0c, 0x71, 0x5e, + 0xa9, 0x11, 0xce, 0xc7, 0x04, 0x65, 0x06, 0xff, 0xda, 0xaa, 0xc1, 0xdf, + 0xbc, 0x99, 0x15, 0xbf, 0xd9, 0x9a, 0xe7, 0x3c, 0x18, 0xe8, 0x18, 0x26, + 0x3f, 0xe7, 0xaa, 0x91, 0x4e, 0xa2, 0x51, 0xd5, 0xb0, 0x90, 0xf0, 0x5e, + 0x15, 0x36, 0x71, 0x3a, 0x7f, 0x33, 0xcd, 0xcf, 0xd3, 0xeb, 0x26, 0x1e, + 0x24, 0xd7, 0x92, 0x78, 0x45, 0x5d, 0x7c, 0xf2, 0x61, 0xf8, 0xdb, 0xcd, + 0x76, 0x5f, 0x97, 0xec, 0xe6, 0xfc, 0x4a, 0xaa, 0x26, 0x8e, 0x7f, 0xd4, + 0x6a, 0x1b, 0xc6, 0xfa, 0xf9, 0x8f, 0x8d, 0x5c, 0xd2, 0x53, 0x23, 0x75, + 0x44, 0xb9, 0x72, 0xa2, 0x37, 0x83, 0xee, 0x34, 0x7a, 0xeb, 0x88, 0x6f, + 0xb1, 0x42, 0xfe, 0x26, 0x26, 0xc9, 0x69, 0x03, 0xce, 0xf6, 0x33, 0xec, + 0xf7, 0x35, 0xf6, 0x85, 0x3e, 0x63, 0x2f, 0xe6, 0x2f, 0xfa, 0xf4, 0x95, + 0x7b, 0xf4, 0x11, 0x7f, 0x51, 0xf2, 0x02, 0xef, 0x9b, 0x63, 0x3d, 0x3b, + 0xcc, 0xb8, 0x58, 0xcf, 0x0c, 0x41, 0xfe, 0xc5, 0x21, 0xe2, 0x9f, 0x23, + 0x7a, 0xed, 0xff, 0x88, 0xe7, 0x9c, 0x30, 0xe4, 0x4c, 0x8f, 0x5f, 0xc1, + 0x6f, 0xe3, 0x17, 0xcb, 0xb5, 0x47, 0x73, 0x69, 0xe6, 0x33, 0xf1, 0xe8, + 0x0e, 0x73, 0x02, 0xa6, 0x1b, 0x16, 0xfa, 0x71, 0x33, 0xf6, 0x9c, 0xdf, + 0xcc, 0x79, 0x3e, 0xd1, 0x26, 0x75, 0x40, 0x71, 0x9d, 0xb9, 0x5d, 0xe2, + 0xa1, 0xf3, 0x3a, 0x04, 0xff, 0x46, 0x73, 0x2c, 0x3f, 0xd9, 0xc5, 0x79, + 0xb9, 0xd2, 0x8e, 0xe6, 0x38, 0x5e, 0xd6, 0xd9, 0x21, 0x6c, 0x2b, 0xd4, + 0x4f, 0xc8, 0x6b, 0xb6, 0x41, 0x9b, 0xa4, 0x8e, 0x9e, 0x15, 0xda, 0x6d, + 0x33, 0x3e, 0xba, 0x8e, 0x59, 0x2c, 0x3f, 0x9b, 0x32, 0xf7, 0x0c, 0xd6, + 0x9f, 0x16, 0x39, 0x3f, 0x0a, 0x55, 0x22, 0xa7, 0x55, 0xf6, 0x9f, 0xf3, + 0xc9, 0x89, 0x04, 0xe4, 0x84, 0x94, 0xc1, 0xcd, 0x9c, 0xef, 0x5d, 0x52, + 0xbf, 0xf7, 0xc5, 0xa6, 0xab, 0xb7, 0x7c, 0x0e, 0xdc, 0xba, 0x5a, 0x8e, + 0x3a, 0x53, 0x1f, 0x0d, 0xb3, 0xbf, 0x03, 0xdd, 0x3b, 0x80, 0x53, 0x8f, + 0xe0, 0x14, 0x07, 0x4e, 0xf3, 0x0a, 0xf5, 0x59, 0x14, 0xd4, 0x90, 0xfe, + 0x53, 0x21, 0xe3, 0xc7, 0xbe, 0x98, 0xaf, 0xfe, 0xf6, 0x9a, 0xfa, 0x5b, + 0xa8, 0xd3, 0xc4, 0xff, 0xb3, 0xa9, 0x6f, 0x5a, 0x9f, 0xd1, 0xff, 0x6f, + 0xf5, 0x72, 0x9c, 0x92, 0xdd, 0x7d, 0x26, 0xce, 0x98, 0x2e, 0xd4, 0xd9, + 0x22, 0x22, 0xcb, 0x46, 0x3a, 0x99, 0x5e, 0xdf, 0xbc, 0x15, 0xf3, 0x65, + 0x7c, 0x4e, 0x6e, 0x09, 0x01, 0xaf, 0xa8, 0x3a, 0xde, 0x87, 0xba, 0xae, + 0xe2, 0x2c, 0xaf, 0xe2, 0x28, 0xc7, 0x3f, 0xaa, 0xe5, 0x12, 0xdf, 0x67, + 0xa1, 0x42, 0x3e, 0x7a, 0xfd, 0xd9, 0xad, 0xf3, 0x84, 0xec, 0x88, 0xe9, + 0xbc, 0xa5, 0xb1, 0x3e, 0x47, 0xb6, 0xe4, 0xf9, 0x1a, 0xe6, 0xb3, 0xc7, + 0x22, 0x34, 0xff, 0x80, 0xd5, 0xd3, 0x87, 0xf9, 0x9f, 0x1a, 0x69, 0xbc, + 0xce, 0x7e, 0x0d, 0xe7, 0xcc, 0x7e, 0x0d, 0xf5, 0xcb, 0x2a, 0x3a, 0x88, + 0xba, 0xd6, 0x78, 0x10, 0xf2, 0x71, 0x4f, 0x7b, 0xfd, 0xf2, 0xe2, 0x47, + 0xe7, 0xe1, 0xb2, 0x38, 0xd9, 0xcf, 0x09, 0x4e, 0x97, 0x7c, 0xf1, 0x39, + 0x6c, 0xe2, 0xd3, 0x1b, 0x93, 0xf3, 0xd2, 0x7c, 0x29, 0xe8, 0x17, 0xf1, + 0x9d, 0x71, 0xef, 0x9d, 0xae, 0x95, 0xa0, 0xdd, 0x2b, 0xe5, 0x9c, 0xd6, + 0xf9, 0xf3, 0x6b, 0x3e, 0xea, 0xf2, 0xb8, 0x7b, 0x4f, 0x20, 0xbf, 0xac, + 0x9d, 0xf0, 0x4b, 0xbd, 0x28, 0x79, 0x3c, 0x2e, 0xf4, 0x65, 0xc9, 0xdf, + 0x6d, 0xd2, 0xb7, 0x98, 0xfe, 0xe2, 0x0f, 0xcc, 0x3b, 0xfd, 0x6e, 0x5f, + 0x60, 0xea, 0x36, 0x8d, 0x43, 0xca, 0x89, 0x13, 0x83, 0x36, 0xeb, 0x33, + 0x24, 0x4a, 0xcf, 0x1a, 0xe0, 0x35, 0x52, 0x07, 0xbe, 0xdd, 0x91, 0xb0, + 0x8c, 0x21, 0x6f, 0xac, 0xda, 0x77, 0x0f, 0xd7, 0x4f, 0xc6, 0x93, 0xe4, + 0xc6, 0xdc, 0xfa, 0x24, 0x79, 0xaf, 0x26, 0x84, 0x96, 0x2f, 0xbe, 0x2c, + 0xbe, 0x85, 0xfe, 0x64, 0xa9, 0x17, 0xdf, 0x97, 0x34, 0xbe, 0xbc, 0xaf, + 0xbe, 0xf9, 0x12, 0xa6, 0x4b, 0x6f, 0x05, 0xed, 0xbb, 0x95, 0xe7, 0x17, + 0xa3, 0xee, 0x11, 0x7e, 0x9c, 0x5f, 0xf5, 0x6f, 0x0c, 0x9a, 0x7e, 0x42, + 0xf0, 0x08, 0xf4, 0x41, 0x65, 0x77, 0x80, 0xbe, 0x29, 0x74, 0xce, 0x2a, + 0xd0, 0xbd, 0xab, 0xfc, 0x71, 0x88, 0xa5, 0x7c, 0x71, 0xac, 0x47, 0x1c, + 0x8f, 0x4c, 0x04, 0xeb, 0x81, 0xc4, 0x4b, 0xc7, 0x27, 0x70, 0xbf, 0x1b, + 0xfd, 0xe2, 0xce, 0xdf, 0xc5, 0xed, 0x4a, 0xc7, 0xab, 0x7b, 0x25, 0xee, + 0x93, 0x0e, 0xe9, 0x4b, 0xc7, 0xdc, 0xfb, 0xe2, 0x9f, 0xc4, 0x31, 0x7e, + 0x85, 0xe3, 0x78, 0xf7, 0xff, 0x2c, 0x8e, 0x9d, 0x12, 0xc7, 0x22, 0xb9, + 0x57, 0x4d, 0xbf, 0xd9, 0x2e, 0x7d, 0x18, 0xf5, 0x8d, 0x7e, 0xbd, 0x4f, + 0x70, 0x1f, 0x78, 0xb5, 0x5b, 0x8f, 0xe7, 0x33, 0x7f, 0x4e, 0xf6, 0x95, + 0xca, 0xbe, 0x7b, 0x26, 0xed, 0x3b, 0xc5, 0xf5, 0xee, 0xf1, 0xf1, 0xc9, + 0xef, 0x15, 0x9f, 0x9d, 0x59, 0x95, 0x02, 0xee, 0xa8, 0xe3, 0xb1, 0x29, + 0xde, 0x37, 0x86, 0x1f, 0xf9, 0xb5, 0x36, 0x85, 0xba, 0x05, 0xfe, 0xb9, + 0x9e, 0x7a, 0x4a, 0xe3, 0xfb, 0xc7, 0xa7, 0xef, 0x57, 0x8d, 0x3c, 0xc4, + 0x6d, 0x43, 0xb8, 0x84, 0xf9, 0x4e, 0xb7, 0xf3, 0x7d, 0xe7, 0xfa, 0xb7, + 0x9a, 0xfd, 0x3a, 0x2a, 0xfe, 0x55, 0x88, 0x7f, 0x7a, 0xb9, 0x96, 0xeb, + 0xbe, 0x75, 0xba, 0xdd, 0xeb, 0xdf, 0x9d, 0x97, 0xd1, 0xf7, 0x4f, 0xfb, + 0x63, 0xd1, 0x9b, 0x32, 0xfa, 0x49, 0x5e, 0xb9, 0xf4, 0x7d, 0xd4, 0x4f, + 0x62, 0x7e, 0x72, 0x9f, 0x41, 0xfa, 0x5b, 0x34, 0x5e, 0x72, 0xdf, 0x70, + 0x3e, 0x47, 0xac, 0xa3, 0x6c, 0x57, 0x5e, 0xf9, 0x71, 0x39, 0x23, 0x7c, + 0x53, 0xc5, 0x8d, 0xd6, 0x8b, 0x64, 0x7d, 0x2a, 0xbf, 0xc5, 0x4e, 0x37, + 0x1f, 0x64, 0x1f, 0xf3, 0x35, 0x0b, 0x5f, 0x34, 0x34, 0x39, 0xfe, 0x18, + 0xe5, 0xab, 0x38, 0xaf, 0xf7, 0x6f, 0xcb, 0x11, 0x9f, 0x76, 0x9e, 0xf3, + 0xf0, 0xfb, 0x80, 0x7d, 0xe9, 0x2b, 0x80, 0x23, 0xf1, 0xcd, 0x50, 0x4d, + 0xce, 0x74, 0x78, 0xe1, 0xdd, 0x30, 0x9a, 0x33, 0x78, 0xdb, 0xec, 0xe7, + 0x48, 0x27, 0xe9, 0x5f, 0x1d, 0xc0, 0x31, 0x2c, 0x38, 0x9e, 0x50, 0x7f, + 0x9f, 0xf7, 0xc6, 0x0f, 0x6f, 0x5e, 0x8c, 0xff, 0x19, 0xcc, 0xe3, 0x87, + 0xe5, 0x5d, 0xdd, 0x18, 0x03, 0xfd, 0x2e, 0x62, 0xec, 0x46, 0x5e, 0xdf, + 0xc3, 0xe7, 0xb5, 0x4a, 0xf5, 0xf2, 0xbb, 0xc3, 0x52, 0x0d, 0x6b, 0xc9, + 0xee, 0x94, 0xae, 0x7f, 0xc8, 0x77, 0x27, 0xee, 0xbd, 0xb7, 0x75, 0x0d, + 0x4c, 0xc4, 0x69, 0x58, 0x31, 0x33, 0xc1, 0x82, 0xde, 0xf8, 0xe2, 0x4b, + 0x5e, 0x7e, 0xaf, 0xbf, 0x18, 0xf3, 0x65, 0xf7, 0x91, 0x9c, 0x88, 0xda, + 0x8b, 0xba, 0xfb, 0xee, 0x1e, 0xd0, 0xb7, 0xd5, 0xbd, 0xd8, 0x3f, 0x73, + 0x3b, 0xd7, 0x51, 0xab, 0x4c, 0xf2, 0x2b, 0x0d, 0x5c, 0xd3, 0xa8, 0xc3, + 0x13, 0x13, 0xaa, 0x04, 0xf7, 0x9a, 0x79, 0x07, 0xab, 0x1a, 0xd1, 0x8b, + 0xfa, 0x68, 0x17, 0xde, 0xc1, 0x44, 0x8b, 0x83, 0x7d, 0x9f, 0x55, 0xe8, + 0xaf, 0x08, 0x8f, 0xf7, 0x5d, 0x1c, 0xd3, 0xe1, 0x60, 0x5d, 0xf2, 0xfa, + 0x15, 0x93, 0x73, 0xfd, 0xab, 0xfb, 0x6e, 0xee, 0xe1, 0x7e, 0x2a, 0x19, + 0xac, 0xcb, 0x01, 0xf9, 0xfb, 0x24, 0x7e, 0x49, 0x89, 0x5f, 0x54, 0xc7, + 0x0f, 0xef, 0xed, 0x4f, 0x7d, 0xef, 0x7a, 0xaa, 0x1b, 0xde, 0xbc, 0xfb, + 0xfc, 0x4f, 0x63, 0xd7, 0xf6, 0x98, 0xb7, 0x0e, 0x57, 0xbb, 0xe7, 0xae, + 0x43, 0xde, 0x8b, 0x5d, 0x87, 0x30, 0xce, 0x73, 0xbf, 0xbc, 0x38, 0xd3, + 0x21, 0x79, 0x74, 0x57, 0x44, 0xf2, 0x41, 0xec, 0xfb, 0x22, 0x62, 0xee, + 0x1b, 0x8c, 0xbf, 0x92, 0xfb, 0xee, 0x97, 0x2a, 0xf4, 0xd9, 0x17, 0x87, + 0xcc, 0xfb, 0xc4, 0xbc, 0x57, 0xb0, 0xbe, 0x3e, 0xae, 0x04, 0x67, 0xbe, + 0xff, 0xb5, 0x3f, 0x9c, 0xaf, 0x99, 0x8e, 0x61, 0x1f, 0x5e, 0x2a, 0x16, + 0x78, 0xbf, 0xc4, 0xe5, 0xfb, 0x45, 0xbf, 0xe0, 0xe1, 0xf0, 0xf9, 0x29, + 0xd5, 0xf6, 0x13, 0x4d, 0x65, 0x3a, 0x73, 0xb0, 0xa7, 0xd5, 0xed, 0x23, + 0xc1, 0x27, 0xd4, 0x79, 0x4b, 0xde, 0xc1, 0xf2, 0x5e, 0xd6, 0xef, 0x61, + 0xf4, 0x73, 0xad, 0x79, 0x8c, 0xc7, 0xd0, 0xb7, 0x39, 0xbf, 0xca, 0xbd, + 0xb5, 0x75, 0x9b, 0xe9, 0x4b, 0xa7, 0xde, 0x67, 0xee, 0xb9, 0xb6, 0x6a, + 0xd0, 0x16, 0xee, 0x5b, 0x1f, 0xb2, 0xf3, 0x92, 0x1f, 0x85, 0x77, 0x89, + 0xff, 0x3d, 0x62, 0xfa, 0x85, 0x73, 0xc5, 0xb8, 0x67, 0xf3, 0xbd, 0x34, + 0xa1, 0xdf, 0x23, 0x09, 0x6f, 0x9e, 0x25, 0x32, 0x65, 0x82, 0xfb, 0xec, + 0x9b, 0x40, 0xf7, 0xdc, 0x84, 0xbe, 0xbc, 0xb5, 0x4b, 0x70, 0xb8, 0x91, + 0x71, 0x5b, 0x3e, 0x9a, 0x0b, 0x7e, 0x67, 0x21, 0x5c, 0x7f, 0x73, 0xfb, + 0xd1, 0x73, 0x6c, 0xd7, 0xbc, 0x81, 0x3c, 0xf3, 0xcd, 0x55, 0xb3, 0xf8, + 0xfc, 0xa6, 0x9d, 0x51, 0xd8, 0x99, 0xe9, 0x17, 0xbf, 0xda, 0x6f, 0x01, + 0xed, 0x92, 0x3a, 0x73, 0xd2, 0x7d, 0x97, 0xc3, 0x4e, 0x53, 0x4f, 0x26, + 0xbf, 0x13, 0x30, 0x9e, 0x5b, 0xc7, 0x63, 0xd5, 0xbc, 0x95, 0xe4, 0x97, + 0x4c, 0x7a, 0xcf, 0x16, 0xe2, 0x6e, 0xf2, 0xc1, 0xe4, 0x8f, 0xf7, 0x1d, + 0x7b, 0x9b, 0xa7, 0x5e, 0xfa, 0xe3, 0xef, 0x70, 0xbe, 0x84, 0x65, 0x3d, + 0x96, 0xe9, 0xef, 0xbb, 0x3c, 0x3e, 0x6f, 0x01, 0x9f, 0x8c, 0xd8, 0x6d, + 0xb7, 0xf0, 0x3b, 0x74, 0x96, 0xda, 0x25, 0xf1, 0x39, 0x57, 0x2d, 0x75, + 0x50, 0xec, 0xfb, 0x49, 0xfa, 0x1f, 0xc4, 0x31, 0x6e, 0x6f, 0xc9, 0x49, + 0xdc, 0x24, 0x8f, 0x9e, 0x16, 0xbf, 0x7f, 0x84, 0xdf, 0xb6, 0xf1, 0xbb, + 0xc5, 0xf5, 0xdb, 0xd4, 0x59, 0xaf, 0x9c, 0x99, 0x3a, 0x1f, 0xb8, 0x5e, + 0xdb, 0x27, 0xf9, 0xdd, 0x53, 0x24, 0xe7, 0xa1, 0x42, 0xbe, 0x3b, 0x38, + 0xe2, 0x4f, 0x89, 0x6a, 0x5a, 0xee, 0xdd, 0x57, 0x2c, 0xfb, 0x92, 0x7a, + 0x1f, 0xe6, 0x71, 0xfe, 0xec, 0x29, 0xf0, 0x34, 0xdf, 0x11, 0x8c, 0xdc, + 0xe0, 0x39, 0xf2, 0xe2, 0xc7, 0x37, 0x13, 0xff, 0x50, 0x07, 0x74, 0x9c, + 0x6a, 0xcd, 0xf7, 0x07, 0xcc, 0xe3, 0xfc, 0x26, 0xf7, 0xb7, 0xa1, 0xaf, + 0xdc, 0xdf, 0x76, 0x48, 0xfa, 0x08, 0xc1, 0xe5, 0x81, 0x21, 0xb2, 0x43, + 0xc7, 0xae, 0xd2, 0x7f, 0xfe, 0x61, 0x47, 0x54, 0xec, 0x28, 0xf7, 0xd8, + 0x11, 0xd0, 0x7b, 0x1d, 0xcd, 0xaf, 0x50, 0x5f, 0x73, 0x1e, 0x2e, 0x57, + 0xeb, 0x29, 0x47, 0xf4, 0xbd, 0xb0, 0xae, 0x88, 0xc6, 0xcb, 0xd4, 0xab, + 0xf0, 0xb7, 0x37, 0x59, 0x84, 0x3a, 0x96, 0xdc, 0x49, 0xf3, 0x35, 0xea, + 0xd5, 0x3e, 0x0e, 0xc4, 0x2b, 0xea, 0x18, 0xea, 0x73, 0xe3, 0x41, 0xb6, + 0x47, 0x1d, 0x1f, 0x34, 0xf5, 0x7a, 0xca, 0xef, 0x98, 0xbd, 0xeb, 0xa4, + 0x5e, 0x9c, 0xc0, 0x77, 0x51, 0xfd, 0x5e, 0x23, 0xfe, 0xd9, 0xe6, 0x3d, + 0xb8, 0xfb, 0x98, 0xa1, 0x8b, 0x7c, 0xe3, 0xfd, 0x27, 0x96, 0x0a, 0xad, + 0xf2, 0x8d, 0x07, 0xd6, 0x55, 0x09, 0xad, 0x36, 0xe3, 0xe9, 0xbe, 0x2b, + 0x5e, 0x29, 0xf9, 0x62, 0xf7, 0x7b, 0xe2, 0xcf, 0x47, 0xe2, 0xcf, 0x59, + 0xe0, 0x9f, 0xdc, 0x28, 0x78, 0x2c, 0x0a, 0xea, 0x17, 0xbb, 0xdc, 0x73, + 0x63, 0xd6, 0x11, 0x8f, 0x47, 0xd5, 0x5f, 0x3f, 0x97, 0x8f, 0x31, 0xd8, + 0x17, 0x00, 0x00, 0x00 }; static const int bnx2_TPAT_b06FwReleaseMajor = 0x1; static const int bnx2_TPAT_b06FwReleaseMinor = 0x0; @@ -2339,201 +1330,199 @@ static const u32 bnx2_TPAT_b06FwBssAddr static const int bnx2_TPAT_b06FwBssLen = 0x250; static const u32 bnx2_TPAT_b06FwSbssAddr = 0x08001a60; static const int bnx2_TPAT_b06FwSbssLen = 0x34; -static u32 bnx2_TPAT_b06FwText[(0x122c/4) + 1] = { - 0x0a000218, 0x00000000, 0x00000000, 0x0000000d, 0x74706174, 0x20322e35, - 0x2e313100, 0x02050b01, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, - 0x24421a60, 0x3c030800, 0x24631cf0, 0xac400000, 0x0043202b, 0x1480fffd, - 0x24420004, 0x3c1d0800, 0x37bd2ffc, 0x03a0f021, 0x3c100800, 0x26100860, - 0x3c1c0800, 0x279c1a60, 0x0e000546, 0x00000000, 0x0000000d, 0x8f820010, - 0x8c450008, 0x24030800, 0xaf430178, 0x97430104, 0x3c020008, 0xaf420140, - 0x8f820024, 0x30420001, 0x10400007, 0x3069ffff, 0x24020002, 0x2523fffe, - 0xa7420146, 0xa7430148, 0x0a000242, 0x3c020800, 0xa7400146, 0x3c020800, - 0x8c43083c, 0x1460000e, 0x24020f00, 0x8f820024, 0x30430020, 0x0003182b, - 0x00031823, 0x30650009, 0x30420c00, 0x24030400, 0x14430002, 0x34a40001, - 0x34a40005, 0xa744014a, 0x0a000264, 0x3c020800, 0x8f830014, 0x14620008, - 0x00000000, 0x8f820024, 0x30420020, 0x0002102b, 0x00021023, 0x3042000d, - 0x0a000262, 0x34420005, 0x8f820024, 0x30420020, 0x0002102b, 0x00021023, - 0x30420009, 0x34420001, 0xa742014a, 0x3c020800, 0x8c430820, 0x8f840024, - 0x3c020048, 0x00621825, 0x30840006, 0x24020002, 0x1082000d, 0x2c820003, - 0x50400005, 0x24020004, 0x10800012, 0x3c020001, 0x0a000284, 0x00000000, - 0x10820007, 0x24020006, 0x1482000f, 0x3c020111, 0x0a00027c, 0x00621025, - 0x0a00027b, 0x3c020101, 0x3c020011, 0x00621025, 0x24030001, 0xaf421000, - 0xaf830020, 0x0a000284, 0x00000000, 0x00621025, 0xaf421000, 0xaf800020, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8f830020, 0x1060003f, - 0x3c048000, 0x8f421000, 0x00441024, 0x1040fffd, 0x00000000, 0x10600039, - 0x00000000, 0x8f421000, 0x3c030020, 0x00431024, 0x10400034, 0x00000000, - 0x97421014, 0x14400031, 0x00000000, 0x97421008, 0x8f840010, 0x24420006, - 0x00024082, 0x00081880, 0x00643821, 0x8ce50000, 0x30430003, 0x30420001, - 0x10400004, 0x00000000, 0x0000000d, 0x0a0002c3, 0x00081080, 0x5460000f, - 0x30a5ffff, 0x3c06ffff, 0x00a62824, 0x0005182b, 0x00a61026, 0x0002102b, - 0x00621824, 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x240001fb, - 0x8ce20000, 0x0a0002c2, 0x00462825, 0x0005182b, 0x38a2ffff, 0x0002102b, - 0x00621824, 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x24000205, - 0x8ce20000, 0x3445ffff, 0x00081080, 0x00441021, 0x3c030800, 0xac450000, - 0x8c620830, 0x24420001, 0xac620830, 0x8f840018, 0x01202821, 0x24820008, - 0x30421fff, 0x24434000, 0x0343d821, 0x30a30007, 0xaf84000c, 0xaf820018, - 0xaf420084, 0x10600002, 0x24a20007, 0x3045fff8, 0x8f820030, 0x8f840000, - 0x00451821, 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, - 0xaf820030, 0x8f840030, 0x34028000, 0x00821021, 0x03421821, 0x3c021000, - 0xaf830010, 0xaf440080, 0x03e00008, 0xaf420178, 0x8f830024, 0x27bdffe0, - 0xafbf0018, 0xafb10014, 0x30620200, 0x14400004, 0xafb00010, 0x0000000d, - 0x00000000, 0x24000242, 0x00031a82, 0x30630003, 0x000310c0, 0x00431021, - 0x00021080, 0x00431021, 0x00021080, 0x3c030800, 0x24631aa0, 0x00438821, - 0x8e240000, 0x10800004, 0x00000000, 0x0000000d, 0x00000000, 0x2400024d, - 0x8f850010, 0x24020001, 0xae220000, 0x8ca70008, 0xa2200007, 0x8f620004, - 0x26300014, 0x02002021, 0x00021402, 0xa2220004, 0x304600ff, 0x24c60005, - 0x0e000673, 0x00063082, 0x8f620004, 0xa6220008, 0x8f430108, 0x3c021000, - 0x00621824, 0x10600008, 0x00000000, 0x97420104, 0x92230007, 0x2442ffec, - 0x3045ffff, 0x34630002, 0x0a000321, 0xa2230007, 0x97420104, 0x2442fff0, - 0x3045ffff, 0x8f620004, 0x3042ffff, 0x2c420013, 0x54400005, 0x92230007, - 0x92220007, 0x34420001, 0xa2220007, 0x92230007, 0x24020001, 0x10620009, - 0x28620002, 0x14400014, 0x24020002, 0x10620012, 0x24020003, 0x1062000a, - 0x00000000, 0x0a000342, 0x00000000, 0x8f820010, 0x8c43000c, 0x3c04ffff, - 0x00641824, 0x00651825, 0x0a000342, 0xac43000c, 0x8f820010, 0x8c430010, - 0x3c04ffff, 0x00641824, 0x00651825, 0xac430010, 0x8f620004, 0x3042ffff, - 0x24420002, 0x00021083, 0xa2220005, 0x304500ff, 0x8f820010, 0x3c04ffff, - 0x00052880, 0x00a22821, 0x8ca70000, 0x96220008, 0x97430104, 0x00e42024, - 0x24420002, 0x00621823, 0x00833825, 0xaca70000, 0x92240005, 0x00041080, - 0x02021021, 0x90430000, 0x3c05fff6, 0x34a5ffff, 0x3063000f, 0x00832021, - 0xa2240006, 0x308200ff, 0x24420003, 0x00021080, 0x02021021, 0x8c460000, - 0x308300ff, 0x8f820010, 0x3c04ff3f, 0x00031880, 0x00c53824, 0x00621821, - 0xae26000c, 0xac67000c, 0x8e22000c, 0x92230006, 0x3484ffff, 0x00441024, - 0x24630003, 0x00031880, 0x02031821, 0x00e42024, 0xae22000c, 0xac640000, - 0x92220006, 0x24420004, 0x00021080, 0x02021021, 0x94470002, 0xac470000, - 0x92230006, 0x8f820010, 0x00031880, 0x00621821, 0x24020010, 0xac670010, - 0x24030002, 0xa7420140, 0xa7400142, 0xa7400144, 0xa7430146, 0x97420104, - 0x24030001, 0x2442fffe, 0xa7420148, 0xa743014a, 0x8f820024, 0x24030002, - 0x30440006, 0x1083000d, 0x2c820003, 0x10400005, 0x24020004, 0x10800011, - 0x3c020009, 0x0a0003a5, 0x00000000, 0x10820007, 0x24020006, 0x1482000d, - 0x3c020119, 0x0a00039f, 0x24030001, 0x0a00039e, 0x3c020109, 0x3c020019, - 0x24030001, 0xaf421000, 0xaf830020, 0x0a0003a5, 0x00000000, 0xaf421000, - 0xaf800020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x92220004, - 0x24030008, 0x8f840020, 0x24420002, 0x30420007, 0x00621823, 0x30630007, - 0x10800006, 0xae230010, 0x3c038000, 0x8f421000, 0x00431024, 0x1040fffd, - 0x00000000, 0x8f820018, 0xaf82000c, 0x24420010, 0x30421fff, 0xaf820018, - 0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, 0x30620007, - 0x10400002, 0x24620007, 0x3043fff8, 0x8f820030, 0x8f840000, 0x00431821, - 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, 0xaf820030, - 0x8f840030, 0x34028000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x00821021, - 0x03421821, 0x3c021000, 0xaf830010, 0xaf440080, 0xaf420178, 0x03e00008, - 0x27bd0020, 0x8f830024, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0x30620200, - 0x14400004, 0xafb00010, 0x0000000d, 0x00000000, 0x240002e4, 0x00031a82, - 0x30630003, 0x000310c0, 0x00431021, 0x00021080, 0x00431021, 0x00021080, - 0x3c030800, 0x24631aa0, 0x00438021, 0x8e040000, 0x14800004, 0x00000000, - 0x0000000d, 0x00000000, 0x240002e9, 0x8f620004, 0x04410008, 0x26050014, - 0x92020006, 0x8e03000c, 0x24420003, 0x00021080, 0x00a21021, 0xac430000, - 0xae000000, 0x92020005, 0x24420001, 0x00021080, 0x00a21021, 0x8c430000, - 0x3c040001, 0x00641821, 0xac430000, 0x92060004, 0x27710008, 0x02202021, - 0x24c60005, 0x0e000673, 0x00063082, 0x92040006, 0x3c057fff, 0x8f620004, - 0x00042080, 0x00912021, 0x8c830004, 0x34a5ffff, 0x00451024, 0x00621821, - 0xac830004, 0x92050005, 0x3c07ffff, 0x92040004, 0x00052880, 0x00b12821, - 0x8ca30000, 0x97420104, 0x96060008, 0x00671824, 0x00441021, 0x00461023, - 0x3042ffff, 0x00621825, 0xaca30000, 0x92030007, 0x24020001, 0x1062000a, - 0x28620002, 0x1440001d, 0x2402000a, 0x24020002, 0x10620019, 0x24020003, - 0x1062000e, 0x2402000a, 0x0a000447, 0x00000000, 0x92020004, 0x97430104, - 0x8e24000c, 0x00621821, 0x2463fff2, 0x3063ffff, 0x00872024, 0x00832025, - 0xae24000c, 0x0a000447, 0x2402000a, 0x92020004, 0x97430104, 0x8e240010, - 0x00621821, 0x2463ffee, 0x3063ffff, 0x00872024, 0x00832025, 0xae240010, - 0x2402000a, 0xa7420140, 0x96030012, 0x8f840024, 0xa7430142, 0x92020004, - 0xa7420144, 0xa7400146, 0x97430104, 0x30840006, 0x24020001, 0xa7430148, - 0xa742014a, 0x24020002, 0x1082000d, 0x2c820003, 0x10400005, 0x24020004, - 0x10800011, 0x3c020041, 0x0a00046c, 0x00000000, 0x10820007, 0x24020006, - 0x1482000d, 0x3c020151, 0x0a000466, 0x24030001, 0x0a000465, 0x3c020141, - 0x3c020051, 0x24030001, 0xaf421000, 0xaf830020, 0x0a00046c, 0x00000000, - 0xaf421000, 0xaf800020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x8f820020, 0x8f840018, 0x10400006, 0x92030004, 0x3c058000, 0x8f421000, - 0x00451024, 0x1040fffd, 0x00000000, 0x2463000a, 0x30620007, 0x10400002, - 0x24620007, 0x304303f8, 0x00831021, 0x30421fff, 0xaf84000c, 0xaf820018, - 0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, 0x30620007, - 0x10400002, 0x24620007, 0x3043fff8, 0x8f820030, 0x8f840000, 0x00431821, - 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, 0xaf820030, - 0x8f840030, 0x34028000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x00821021, - 0x03421821, 0x3c021000, 0xaf830010, 0xaf440080, 0xaf420178, 0x03e00008, - 0x27bd0020, 0x8f620000, 0x97430104, 0x3c048000, 0x3045ffff, 0x3066ffff, - 0x8f420178, 0x00441024, 0x1440fffd, 0x2402000a, 0x30a30007, 0xa7420140, - 0x24020008, 0x00431023, 0x30420007, 0x24a3fffe, 0xa7420142, 0xa7430144, - 0xa7400146, 0xa7460148, 0x8f420108, 0x8f830024, 0x30420020, 0x0002102b, - 0x00021023, 0x30420009, 0x34420001, 0x30630006, 0xa742014a, 0x24020002, - 0x1062000d, 0x2c620003, 0x10400005, 0x24020004, 0x10600011, 0x3c020041, - 0x0a0004d6, 0x00000000, 0x10620007, 0x24020006, 0x1462000d, 0x3c020151, - 0x0a0004d0, 0x24030001, 0x0a0004cf, 0x3c020141, 0x3c020051, 0x24030001, - 0xaf421000, 0xaf830020, 0x0a0004d6, 0x00000000, 0xaf421000, 0xaf800020, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8f820020, 0x24a30008, - 0x8f850018, 0x10400006, 0x30c6ffff, 0x3c048000, 0x8f421000, 0x00441024, - 0x1040fffd, 0x00000000, 0x3063ffff, 0x30620007, 0x10400002, 0x24620007, - 0x3043fff8, 0x00a31021, 0x30421fff, 0x24434000, 0x0343d821, 0x00c02021, - 0x30830007, 0xaf85000c, 0xaf820018, 0xaf420084, 0x10600002, 0x24820007, - 0x3044fff8, 0x8f820030, 0x8f850000, 0x00441821, 0xaf82001c, 0x0065102b, - 0xaf830030, 0x14400002, 0x00651023, 0xaf820030, 0x8f840030, 0x34028000, - 0x3c030800, 0x8c650834, 0x00821021, 0x03421821, 0xaf830010, 0xaf440080, - 0x10a00006, 0x2402000e, 0x9383002f, 0x14620004, 0x3c021000, 0x2402043f, - 0xa7420148, 0x3c021000, 0x03e00008, 0xaf420178, 0x8f820024, 0x30424000, - 0x10400005, 0x24020800, 0x0000000d, 0x00000000, 0x2400040e, 0x24020800, - 0xaf420178, 0x97440104, 0x3c030008, 0xaf430140, 0x8f820024, 0x30420001, - 0x10400006, 0x3085ffff, 0x24020002, 0x24a3fffe, 0xa7420146, 0x0a000526, - 0xa7430148, 0xa7400146, 0x8f840018, 0x2402000d, 0xa742014a, 0x24830008, - 0x30631fff, 0x24624000, 0x0342d821, 0x30a20007, 0xaf84000c, 0xaf830018, - 0xaf430084, 0x10400002, 0x24a20007, 0x3045fff8, 0x8f820030, 0x8f840000, - 0x00451821, 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, - 0xaf820030, 0x8f840030, 0x34028000, 0x00821021, 0x03421821, 0x3c021000, - 0xaf830010, 0xaf440080, 0x03e00008, 0xaf420178, 0x27bdffe8, 0x3c046008, - 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x375b4000, - 0x00431024, 0x3442380c, 0xac825000, 0x8f430008, 0x3c100800, 0x37428000, - 0x34630001, 0xaf430008, 0xaf820010, 0x3c02601c, 0xaf800018, 0xaf400080, - 0xaf400084, 0x8c450008, 0x3c036000, 0x8c620808, 0x3c040800, 0x3c030080, - 0xac830820, 0x3042fff0, 0x38420010, 0x2c420001, 0xaf850000, 0xaf820004, - 0x0e000658, 0x00000000, 0x8f420000, 0x30420001, 0x1040fffb, 0x00000000, - 0x8f430108, 0x8f440100, 0x30622000, 0xaf830024, 0xaf840014, 0x10400004, - 0x8e02082c, 0x24420001, 0x0a0005c6, 0xae02082c, 0x30620200, 0x14400003, - 0x24020f00, 0x14820027, 0x24020d00, 0x97420104, 0x1040001c, 0x30624000, - 0x14400005, 0x00000000, 0x0e00022f, 0x00000000, 0x0a0005bb, 0x00000000, - 0x8f620008, 0x8f630000, 0x24020030, 0x00031e02, 0x306300f0, 0x10620007, - 0x28620031, 0x1440002f, 0x24020040, 0x10620007, 0x00000000, 0x0a0005bb, - 0x00000000, 0x0e0002e8, 0x00000000, 0x0a0005bb, 0x00000000, 0x0e0003db, - 0x00000000, 0x0a0005bb, 0x00000000, 0x30620040, 0x1440002b, 0x00000000, - 0x0000000d, 0x00000000, 0x240004b2, 0x0a0005c6, 0x00000000, 0x1482000f, - 0x30620006, 0x97420104, 0x10400005, 0x30620040, 0x0e000510, 0x00000000, - 0x0a0005bb, 0x00000000, 0x1440001b, 0x00000000, 0x0000000d, 0x00000000, - 0x240004c4, 0x0a0005c6, 0x00000000, 0x1040000e, 0x30621000, 0x10400005, - 0x00000000, 0x0e000688, 0x00000000, 0x0a0005bb, 0x00000000, 0x0e0004a1, - 0x00000000, 0x8f82002c, 0x24420001, 0xaf82002c, 0x0a0005c6, 0x00000000, - 0x30620040, 0x14400004, 0x00000000, 0x0000000d, 0x00000000, 0x240004db, - 0x8f420138, 0x3c034000, 0x00431025, 0xaf420138, 0x0a000566, 0x00000000, - 0x3c046008, 0x8c835000, 0x3c1a8000, 0x2402ff7f, 0x375b4000, 0x00621824, - 0x3463380c, 0xac835000, 0x8f420008, 0x3c056000, 0x3c03601c, 0x34420001, - 0xaf420008, 0x37428000, 0xaf800018, 0xaf820010, 0xaf400080, 0xaf400084, - 0x8c660008, 0x8ca20808, 0x3c040800, 0x3c030080, 0xac830820, 0x3042fff0, - 0x38420010, 0x2c420001, 0xaf860000, 0xaf820004, 0x03e00008, 0x00000000, - 0x3084ffff, 0x30820007, 0x10400002, 0x24820007, 0x3044fff8, 0x8f820018, - 0x00441821, 0x30631fff, 0x24644000, 0x0344d821, 0xaf82000c, 0xaf830018, - 0x03e00008, 0xaf430084, 0x3084ffff, 0x30820007, 0x10400002, 0x24820007, - 0x3044fff8, 0x8f820030, 0x8f830000, 0x00442021, 0xaf82001c, 0x0083102b, - 0xaf840030, 0x14400002, 0x00831023, 0xaf820030, 0x8f820030, 0x34038000, - 0x00431821, 0x03432021, 0xaf840010, 0x03e00008, 0xaf420080, 0x8f830024, - 0x24020002, 0x30630006, 0x1062000d, 0x2c620003, 0x50400005, 0x24020004, - 0x10600012, 0x3c020001, 0x0a00062a, 0x00000000, 0x10620007, 0x24020006, - 0x1462000f, 0x3c020111, 0x0a000622, 0x00821025, 0x0a000621, 0x3c020101, - 0x3c020011, 0x00821025, 0x24030001, 0xaf421000, 0xaf830020, 0x0a00062a, - 0x00000000, 0x00821025, 0xaf421000, 0xaf800020, 0x00000000, 0x00000000, - 0x00000000, 0x03e00008, 0x00000000, 0x8f820020, 0x10400005, 0x3c038000, - 0x8f421000, 0x00431024, 0x1040fffd, 0x00000000, 0x03e00008, 0x00000000, - 0x8f820024, 0x27bdffe8, 0x30424000, 0x14400005, 0xafbf0010, 0x0e00022f, - 0x00000000, 0x0a000656, 0x8fbf0010, 0x8f620008, 0x8f630000, 0x24020030, - 0x00031e02, 0x306300f0, 0x10620008, 0x28620031, 0x1440000d, 0x8fbf0010, - 0x24020040, 0x10620007, 0x00000000, 0x0a000656, 0x00000000, 0x0e0002e8, - 0x00000000, 0x0a000656, 0x8fbf0010, 0x0e0003db, 0x00000000, 0x8fbf0010, - 0x03e00008, 0x27bd0018, 0x8f840028, 0x1080000f, 0x3c026000, 0x8c430c3c, - 0x30630fff, 0xaf830008, 0x14600011, 0x3082000f, 0x10400005, 0x308200f0, - 0x10400003, 0x30820f00, 0x14400006, 0x00000000, 0x0000000d, 0x00000000, - 0x2400051a, 0x03e00008, 0x00000000, 0x0000000d, 0x00000000, 0x2400051f, - 0x03e00008, 0x00000000, 0xaf830028, 0x03e00008, 0x00000000, 0x10c00007, - 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb, - 0x24840004, 0x03e00008, 0x00000000, 0x0a000684, 0x00a01021, 0xac860000, - 0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa, 0x24a5ffff, - 0x03e00008, 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x00000000}; +static u8 bnx2_TPAT_b06FwText[] = { + 0x1f, 0x8b, 0x08, 0x08, 0x47, 0xd2, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x57, 0x4d, 0x68, + 0x1c, 0xe7, 0x19, 0x7e, 0xe7, 0x77, 0x47, 0x62, 0x25, 0x8d, 0x93, 0x3d, + 0xac, 0x5d, 0xa5, 0x99, 0x91, 0x46, 0x3f, 0x54, 0x26, 0x9e, 0x84, 0xa5, + 0x56, 0x61, 0x20, 0xe3, 0x99, 0x95, 0x2c, 0x0c, 0x05, 0x07, 0x42, 0x08, + 0xe4, 0xb2, 0x1d, 0x49, 0x36, 0x85, 0x1e, 0x5a, 0x9a, 0x43, 0xa0, 0x05, + 0x0f, 0x33, 0xeb, 0x34, 0x87, 0xc5, 0xdb, 0xaa, 0xc5, 0xbe, 0x94, 0xd6, + 0x95, 0xea, 0xe8, 0xb2, 0x68, 0xe2, 0x53, 0x0f, 0xc5, 0xd8, 0xb4, 0x54, + 0xd0, 0x53, 0x7b, 0x0a, 0x85, 0x5c, 0x4c, 0x69, 0x20, 0x85, 0x12, 0x44, + 0x0f, 0x21, 0xd4, 0xad, 0xa7, 0xcf, 0xfb, 0xcd, 0x8c, 0xbc, 0xbb, 0x95, + 0x5b, 0x1f, 0x02, 0x15, 0xac, 0x66, 0xe6, 0xfb, 0xde, 0xf7, 0xfb, 0x79, + 0x9f, 0xe7, 0x79, 0xbf, 0xf7, 0x6b, 0xca, 0x34, 0x49, 0xe5, 0xdf, 0x14, + 0x7e, 0x6f, 0x7f, 0xe3, 0xdb, 0x6f, 0x7f, 0xf5, 0xa5, 0x57, 0x2c, 0xa2, + 0x57, 0x5e, 0x92, 0x64, 0x5d, 0xa6, 0x2f, 0xe0, 0x4f, 0x21, 0x32, 0xab, + 0xf1, 0xf9, 0x47, 0x86, 0xec, 0x75, 0xce, 0x04, 0x0e, 0x19, 0x8a, 0x77, + 0x34, 0xbb, 0xe9, 0x10, 0xf9, 0x83, 0x15, 0x2b, 0xa4, 0x7f, 0xe5, 0x71, + 0x43, 0x25, 0x6e, 0x7f, 0xc1, 0xfb, 0xe7, 0xb9, 0x7b, 0xe7, 0xed, 0xa3, + 0xdb, 0x0a, 0x19, 0xa6, 0xd7, 0x31, 0xcc, 0x45, 0x32, 0x66, 0xe1, 0xf3, + 0xd3, 0xa5, 0x75, 0x8d, 0xa6, 0xab, 0xb1, 0x4c, 0x4a, 0xfa, 0x06, 0xad, + 0xf5, 0x30, 0x8e, 0xf3, 0x8e, 0x14, 0x66, 0xaa, 0x14, 0xde, 0x32, 0x48, + 0xf6, 0x7c, 0x29, 0xc8, 0x1c, 0xf4, 0x49, 0x14, 0xb8, 0x35, 0xf2, 0xcd, + 0x3c, 0xff, 0xa6, 0x2b, 0x93, 0xec, 0x3c, 0xce, 0xe7, 0x17, 0xd6, 0xa5, + 0x60, 0x7f, 0x43, 0x0a, 0xf7, 0x03, 0xde, 0x37, 0xd6, 0xb1, 0x2e, 0xf9, + 0xfb, 0xfc, 0xf4, 0x8c, 0xb0, 0x37, 0x4d, 0x9d, 0x06, 0xcd, 0xc8, 0x0e, + 0xfb, 0x5a, 0x14, 0xba, 0x2b, 0x4d, 0x85, 0xe6, 0xf1, 0x9b, 0xa0, 0x6d, + 0x97, 0xea, 0x81, 0x4b, 0xaa, 0xe2, 0xc8, 0x14, 0x36, 0x24, 0xfa, 0x65, + 0x4b, 0xc3, 0xef, 0x92, 0xd4, 0xde, 0xdf, 0x2a, 0xc7, 0x69, 0x50, 0x8a, + 0xb5, 0x44, 0x0d, 0x5e, 0x5b, 0xe1, 0x1f, 0xb8, 0x2b, 0xa6, 0x4c, 0xf3, + 0xf8, 0x4d, 0xe1, 0x3d, 0x82, 0x9d, 0x46, 0x41, 0x6b, 0xbc, 0x6f, 0x02, + 0xef, 0x58, 0x27, 0xc6, 0x0a, 0xc4, 0x3a, 0x2c, 0xac, 0xc3, 0xa1, 0x6e, + 0x7f, 0x03, 0xfb, 0x58, 0x68, 0x46, 0xa4, 0x53, 0x57, 0xac, 0x7d, 0x8a, + 0x12, 0x53, 0xa1, 0xe4, 0xac, 0x46, 0xfe, 0x65, 0x15, 0xdf, 0xcf, 0x51, + 0x6c, 0x4a, 0xb0, 0xe9, 0x96, 0xf8, 0xd5, 0xd0, 0xaf, 0xa3, 0x7d, 0x86, + 0x92, 0xc6, 0x29, 0x49, 0xf6, 0xbe, 0x8f, 0xf6, 0x05, 0x33, 0xa2, 0xef, + 0xe1, 0x29, 0xe1, 0xfb, 0x14, 0x8f, 0x87, 0x6f, 0x89, 0x14, 0x87, 0xcc, + 0x20, 0xb3, 0x28, 0xcd, 0x2a, 0x5f, 0x6e, 0x2f, 0xda, 0xe2, 0x6c, 0x1c, + 0x3b, 0xd8, 0xf5, 0x5f, 0xa5, 0x8e, 0x49, 0xb1, 0xea, 0xc1, 0xa6, 0xef, + 0x98, 0x6d, 0xe0, 0xe4, 0x0b, 0x3c, 0xbf, 0xc6, 0xed, 0xfc, 0x87, 0x76, + 0x8b, 0x14, 0xcf, 0x31, 0x43, 0x6a, 0x51, 0xd1, 0xd7, 0x30, 0x83, 0x5b, + 0x2f, 0x93, 0x2f, 0xe2, 0x61, 0xe0, 0xdd, 0xc4, 0x9e, 0x74, 0x60, 0x9b, + 0xf8, 0x32, 0xc5, 0x4d, 0x83, 0xec, 0xd5, 0x2d, 0xf4, 0x7c, 0xdc, 0x53, + 0x10, 0x67, 0xc6, 0x49, 0x2d, 0xfd, 0x18, 0xd7, 0xdf, 0x62, 0x5d, 0xb1, + 0x69, 0xd0, 0x0c, 0x75, 0x5e, 0xcf, 0xf3, 0x3b, 0x6e, 0x9e, 0xeb, 0x9e, + 0xb3, 0xfc, 0x3e, 0xad, 0x34, 0x35, 0x5a, 0x34, 0xf1, 0x44, 0xdc, 0x1c, + 0xc4, 0x46, 0x2d, 0xe7, 0x9f, 0x2a, 0xd7, 0xfa, 0x48, 0x42, 0xe8, 0xe9, + 0xcf, 0xbd, 0xdf, 0xf0, 0xde, 0x97, 0xd7, 0x85, 0x7d, 0x9e, 0xef, 0xae, + 0x3e, 0xcd, 0x5e, 0x93, 0x0b, 0xfb, 0x3c, 0x5f, 0x6b, 0xf1, 0x7c, 0x36, + 0xf6, 0xc6, 0x9c, 0x24, 0x5a, 0x1b, 0xb8, 0x46, 0xd4, 0xc3, 0xba, 0x1c, + 0x3c, 0x07, 0x4d, 0xac, 0xdd, 0x5e, 0xb6, 0x24, 0x83, 0x12, 0x27, 0x7f, + 0x11, 0x3c, 0xf0, 0x43, 0xc7, 0xfe, 0x53, 0xa8, 0xd4, 0x68, 0xcf, 0xad, + 0x53, 0x37, 0x6b, 0x52, 0x92, 0x75, 0x29, 0xc8, 0x64, 0x8c, 0x5f, 0xa3, + 0x5d, 0xe7, 0xf3, 0x7c, 0xcd, 0x75, 0x81, 0x33, 0xb1, 0x5f, 0x73, 0x8d, + 0x66, 0xd1, 0xbf, 0x62, 0x6e, 0x91, 0x8b, 0x98, 0xcb, 0x88, 0xc9, 0xbc, + 0x78, 0x4f, 0x32, 0x17, 0xfd, 0x14, 0xcb, 0x2d, 0xdb, 0x4c, 0xc8, 0x6e, + 0x06, 0x0a, 0x99, 0xb2, 0x67, 0xc2, 0x26, 0xa6, 0x76, 0x66, 0xd0, 0x43, + 0xe5, 0x1d, 0xc1, 0xe3, 0xb4, 0xff, 0x30, 0xbf, 0xb7, 0xd4, 0xa4, 0xfb, + 0x59, 0x83, 0xee, 0x66, 0x24, 0x47, 0x1c, 0xab, 0x86, 0x49, 0x1f, 0x64, + 0xd5, 0x3e, 0xc0, 0x65, 0x27, 0x39, 0xa3, 0x40, 0x67, 0x9b, 0xee, 0x03, + 0xb0, 0xc4, 0x06, 0x0e, 0x31, 0xf6, 0x5c, 0x3d, 0x79, 0x4f, 0xb7, 0xcf, + 0x6c, 0x3a, 0xf6, 0x7b, 0x21, 0xb3, 0xf3, 0x86, 0x8a, 0xd6, 0xe1, 0x38, + 0x7c, 0x1d, 0xfe, 0x26, 0x5d, 0x87, 0x5e, 0x64, 0xc4, 0x63, 0xee, 0xc0, + 0xa0, 0xfd, 0x5e, 0x8d, 0xac, 0x5d, 0x95, 0xa2, 0x7e, 0x83, 0xdc, 0x45, + 0xdb, 0x22, 0x59, 0x6e, 0xc8, 0x88, 0xdf, 0xdc, 0x6e, 0x4e, 0xeb, 0xae, + 0x46, 0x87, 0xce, 0x77, 0x75, 0x9a, 0x4e, 0x5c, 0x9d, 0xd8, 0xc6, 0xa0, + 0xb9, 0xf7, 0x0d, 0x29, 0xec, 0xf3, 0xfa, 0x39, 0xce, 0x46, 0x19, 0x67, + 0x55, 0x0a, 0x6e, 0xd5, 0x68, 0x7e, 0xe7, 0x6f, 0x79, 0xe0, 0x20, 0xc6, + 0xe0, 0xf1, 0x66, 0xcb, 0x56, 0x68, 0x12, 0x6d, 0xbb, 0xdc, 0x77, 0x54, + 0xb6, 0xf3, 0x18, 0x79, 0x1e, 0xb8, 0xcf, 0x53, 0xc0, 0xfc, 0x7e, 0x9d, + 0x7d, 0x6a, 0x34, 0xb7, 0xc3, 0xba, 0xc0, 0x73, 0x97, 0xbf, 0x79, 0x6d, + 0x13, 0x14, 0x61, 0x37, 0xd1, 0x72, 0x03, 0xfb, 0x97, 0x85, 0x06, 0x22, + 0xec, 0x56, 0x76, 0x26, 0xf1, 0x14, 0x71, 0x50, 0x0a, 0x3e, 0x73, 0x5e, + 0xa8, 0x53, 0x08, 0x5c, 0x55, 0xac, 0x67, 0x8b, 0x16, 0x9a, 0xdb, 0xa2, + 0x0f, 0x6d, 0x03, 0xee, 0x33, 0xc7, 0xfa, 0xf0, 0x3d, 0xa8, 0xd6, 0x20, + 0x03, 0xf3, 0x14, 0xb3, 0x68, 0x62, 0xaf, 0x6b, 0x2e, 0xdb, 0xb3, 0x6d, + 0xbc, 0xac, 0x91, 0xbd, 0xbc, 0x8b, 0xd1, 0xf7, 0x7b, 0xd8, 0xef, 0x4d, + 0xce, 0x35, 0x8e, 0xf5, 0x17, 0x62, 0xfb, 0x79, 0xec, 0x79, 0x61, 0x35, + 0xe5, 0xbe, 0x81, 0x46, 0xce, 0x4e, 0x6c, 0xaa, 0x88, 0xbd, 0x8c, 0xc0, + 0x87, 0x3f, 0xfc, 0x2c, 0xd7, 0x3c, 0x70, 0xb8, 0x35, 0x03, 0x6c, 0x6c, + 0x2b, 0x85, 0x9e, 0x1d, 0x8c, 0x9b, 0xb8, 0x0a, 0xfc, 0x0a, 0x8c, 0xd8, + 0x6e, 0xbd, 0x97, 0x53, 0x2a, 0xe6, 0xba, 0xc6, 0x73, 0x21, 0xe7, 0x38, + 0xab, 0xbf, 0x03, 0x27, 0x22, 0xaa, 0xd3, 0xe2, 0x41, 0x9d, 0xae, 0x0e, + 0xea, 0x34, 0x77, 0x43, 0x47, 0x1c, 0xf2, 0xbc, 0xdb, 0x62, 0x0d, 0x02, + 0x6b, 0x87, 0xed, 0xec, 0xa6, 0x22, 0xf3, 0x3a, 0xd0, 0x7f, 0x40, 0xb4, + 0x35, 0xd0, 0x11, 0x37, 0x75, 0x68, 0x6c, 0x99, 0x2e, 0xfe, 0x84, 0xe8, + 0xe2, 0x80, 0x7d, 0x79, 0xfc, 0xc2, 0x27, 0xc2, 0x9e, 0x65, 0x60, 0x7e, + 0x75, 0x20, 0x23, 0x1f, 0x20, 0x5f, 0xee, 0x07, 0xc8, 0x83, 0x6d, 0xfc, + 0xd6, 0x91, 0x1b, 0x19, 0x1b, 0xce, 0x13, 0x8f, 0x81, 0xcf, 0x06, 0xfa, + 0x2e, 0xa1, 0x8d, 0xf3, 0x16, 0xdb, 0xea, 0xd4, 0x76, 0xa7, 0x28, 0xad, + 0x72, 0x91, 0xc9, 0xb9, 0xe8, 0x14, 0xf8, 0x34, 0x81, 0xfc, 0x72, 0x47, + 0x19, 0xcd, 0x45, 0xc8, 0x59, 0x8d, 0xd3, 0xc8, 0x3d, 0x3f, 0x47, 0x3b, + 0x8f, 0xf7, 0x33, 0x3c, 0x27, 0xf0, 0x7d, 0x1a, 0xb6, 0xc3, 0x79, 0xa8, + 0xf2, 0x7b, 0x5a, 0x0e, 0x02, 0xef, 0x76, 0x0c, 0xd8, 0x5b, 0xd0, 0x0b, + 0xc7, 0xbb, 0x86, 0x7c, 0xc1, 0x31, 0xaf, 0x21, 0xa6, 0x3a, 0xe6, 0x36, + 0x69, 0xfe, 0x80, 0x62, 0xa5, 0xcc, 0x4f, 0xe1, 0x71, 0x7e, 0x6a, 0x0a, + 0x1e, 0x24, 0x99, 0x09, 0x1f, 0xd6, 0x6d, 0xa5, 0x53, 0xc6, 0x8e, 0xfc, + 0x00, 0x1a, 0x0e, 0x94, 0x3c, 0xdf, 0xc4, 0x19, 0x11, 0x01, 0x77, 0x1f, + 0xda, 0x8d, 0xa0, 0xdd, 0x70, 0x48, 0xbb, 0xe1, 0xff, 0xd4, 0x2e, 0x74, + 0x09, 0x8d, 0xdc, 0x05, 0xa7, 0x3e, 0xe8, 0x9f, 0xa4, 0x63, 0xd6, 0x30, + 0x6b, 0xd9, 0xa2, 0x7b, 0x4b, 0xcf, 0xa2, 0xe5, 0xbf, 0x3e, 0xab, 0x96, + 0x63, 0xd6, 0xb2, 0xca, 0x5a, 0x6e, 0x0c, 0x6b, 0xf9, 0x53, 0xf8, 0x17, + 0x9a, 0xbc, 0xa0, 0x36, 0x48, 0x5b, 0x04, 0x0e, 0x3b, 0x75, 0x52, 0x6e, + 0x3c, 0xe1, 0x1b, 0x73, 0x38, 0x1c, 0xe0, 0xdf, 0x81, 0x86, 0x3e, 0x69, + 0xb4, 0x1d, 0x39, 0x4f, 0xf5, 0xec, 0xe6, 0x96, 0xb0, 0x51, 0x49, 0x47, + 0xdc, 0xbf, 0xb3, 0x64, 0x5b, 0x96, 0x3c, 0xac, 0x79, 0xa8, 0x7e, 0x27, + 0xbf, 0xa6, 0x79, 0x3c, 0x4f, 0x6c, 0x81, 0xeb, 0xd6, 0x8f, 0x80, 0x51, + 0xda, 0x63, 0x9e, 0x3b, 0xe6, 0x9a, 0xe0, 0x17, 0xbe, 0xa1, 0x05, 0x0d, + 0x7c, 0xad, 0xc1, 0x4e, 0xdd, 0x29, 0xf4, 0x73, 0x17, 0xe3, 0xee, 0xf5, + 0x98, 0x5f, 0x06, 0xe9, 0x37, 0x9d, 0xe6, 0x55, 0x91, 0x73, 0xe7, 0xcd, + 0x75, 0x62, 0xed, 0xf1, 0x79, 0x87, 0xfe, 0x41, 0x8d, 0x14, 0xa1, 0xf7, + 0xc9, 0x52, 0xef, 0x2f, 0x20, 0x46, 0x93, 0xf8, 0x66, 0xcd, 0x9f, 0x2e, + 0x35, 0x3f, 0x8d, 0x27, 0xb7, 0x5d, 0x54, 0x0b, 0xee, 0x80, 0x87, 0x3b, + 0x8c, 0x6b, 0x1d, 0xf9, 0x8d, 0xe7, 0xff, 0x7b, 0xbe, 0xe9, 0x30, 0xb6, + 0x8e, 0xf5, 0x03, 0x5a, 0x80, 0xee, 0xd0, 0x7e, 0xc0, 0xb6, 0xec, 0x53, + 0xd9, 0x9a, 0xa5, 0xed, 0xa7, 0x63, 0xb6, 0x68, 0x3f, 0x60, 0x3b, 0xd6, + 0xc5, 0x73, 0xa4, 0xdc, 0xe4, 0xf3, 0x38, 0x60, 0x5d, 0xc0, 0xaf, 0x8d, + 0x36, 0xae, 0x19, 0xd8, 0x9f, 0xcf, 0x66, 0x5e, 0x27, 0xd7, 0x13, 0x7c, + 0x7e, 0x8f, 0x9d, 0xd3, 0xc7, 0xda, 0xb8, 0x00, 0xbe, 0x7f, 0x4b, 0xfd, + 0x4f, 0x6d, 0xbc, 0x06, 0x2d, 0x5c, 0x51, 0x0b, 0x6d, 0x6c, 0xe3, 0x79, + 0x01, 0xdf, 0xaf, 0x8d, 0x69, 0xa3, 0xf2, 0x7b, 0xfa, 0xf9, 0x9c, 0xf4, + 0x9b, 0xe2, 0x6c, 0xe5, 0xf9, 0x94, 0x1d, 0x8a, 0xb5, 0x52, 0x07, 0x6b, + 0xc7, 0x3a, 0x98, 0x44, 0xae, 0x18, 0xe1, 0xb8, 0x12, 0xba, 0xb6, 0x99, + 0x12, 0x6b, 0x62, 0xf8, 0xfc, 0xfa, 0x7f, 0xe9, 0x82, 0xc0, 0x23, 0x31, + 0x37, 0x6a, 0x0c, 0x3e, 0x0f, 0xf2, 0xfc, 0x8a, 0x8b, 0xfe, 0xaa, 0xd6, + 0x10, 0xd8, 0xf3, 0x59, 0xcb, 0x78, 0xa0, 0xbe, 0x73, 0xe6, 0xa1, 0x05, + 0xce, 0x01, 0x8f, 0xf3, 0x3d, 0x27, 0x40, 0x5b, 0x1b, 0xf1, 0x67, 0x4c, + 0x36, 0xa4, 0xf5, 0x7d, 0x83, 0xfd, 0xa0, 0xb3, 0x93, 0x6a, 0x2c, 0x1d, + 0x9a, 0x7a, 0x82, 0x13, 0xf3, 0x28, 0x1a, 0xc2, 0xa9, 0x23, 0x70, 0xfa, + 0xf0, 0x18, 0xa7, 0xa8, 0xc4, 0x29, 0x12, 0x38, 0xfd, 0xb1, 0xc4, 0xe9, + 0x0f, 0x4f, 0xc1, 0xe9, 0xc3, 0x67, 0xc0, 0xc9, 0xa0, 0x3d, 0xa7, 0x89, + 0x73, 0x56, 0x17, 0x35, 0xe9, 0xa1, 0x7b, 0x52, 0x4d, 0x75, 0x52, 0xdc, + 0x6d, 0x73, 0x8f, 0x86, 0xeb, 0x0e, 0xdb, 0x7a, 0x80, 0xf5, 0xa5, 0xc0, + 0xee, 0xfa, 0x58, 0xed, 0x91, 0xc0, 0xbe, 0x5d, 0xe2, 0x74, 0x1d, 0x38, + 0xb5, 0x4b, 0x9c, 0xb6, 0x87, 0x70, 0xda, 0x1e, 0xc1, 0x89, 0xf3, 0x49, + 0xcb, 0xd8, 0xee, 0x55, 0x18, 0x55, 0xf8, 0xe8, 0x74, 0xdb, 0x9c, 0xc6, + 0xfe, 0xcf, 0x51, 0xfa, 0x63, 0x95, 0xeb, 0x5a, 0x60, 0xf7, 0xaa, 0x2a, + 0x8b, 0xf3, 0x80, 0xdf, 0x9f, 0xd4, 0x27, 0x98, 0xcb, 0x0f, 0x5c, 0x8e, + 0x23, 0xea, 0x57, 0xa7, 0xca, 0x43, 0xcf, 0xab, 0xa8, 0xad, 0xf0, 0xcd, + 0x36, 0xaa, 0xd4, 0x86, 0xde, 0x15, 0xd4, 0xe5, 0xe1, 0x71, 0x5d, 0x5e, + 0xc4, 0xe0, 0x7a, 0x59, 0x97, 0xef, 0x39, 0x5c, 0x97, 0x2f, 0x6a, 0x34, + 0xb9, 0x51, 0x62, 0xc9, 0x9c, 0x9e, 0x42, 0xdf, 0x25, 0x81, 0x79, 0x8a, + 0xfc, 0xbd, 0x89, 0xfd, 0x47, 0x82, 0x9b, 0xa8, 0xb1, 0x4a, 0xde, 0xa2, + 0x86, 0xa5, 0x30, 0x2b, 0x62, 0xf5, 0xc5, 0xd6, 0x5d, 0x9f, 0x20, 0x4f, + 0x1b, 0x1d, 0x15, 0x75, 0xfd, 0xfd, 0x8c, 0xf3, 0x33, 0x5d, 0x4e, 0x7a, + 0x14, 0x9f, 0xf1, 0xae, 0xe5, 0xc0, 0xdc, 0x7f, 0xeb, 0x3c, 0x9f, 0x33, + 0xf5, 0xd5, 0xa0, 0x85, 0xf6, 0x81, 0x41, 0xa8, 0x7d, 0x70, 0x4f, 0xa1, + 0x38, 0x38, 0x2f, 0xa1, 0xc6, 0xc1, 0x37, 0x7c, 0x92, 0x6c, 0xb6, 0x23, + 0x7b, 0x4d, 0x70, 0x21, 0x26, 0x1f, 0xeb, 0xf4, 0x33, 0x71, 0x57, 0xe9, + 0x28, 0x9e, 0x81, 0xda, 0x92, 0x0c, 0x9c, 0xf3, 0x88, 0x89, 0x65, 0xa4, + 0x03, 0xd4, 0x41, 0x38, 0xfb, 0x83, 0x55, 0xc4, 0xe5, 0x2c, 0x70, 0xcb, + 0x54, 0xf8, 0xbe, 0xa9, 0x17, 0xf7, 0x1c, 0x54, 0x35, 0x22, 0x5e, 0x8f, + 0x4a, 0x7e, 0x88, 0x3a, 0x4b, 0x6a, 0xf7, 0xc9, 0x8a, 0x5c, 0xf0, 0x1c, + 0xe7, 0x48, 0x37, 0xe3, 0xda, 0xf9, 0xac, 0x21, 0xdf, 0xe0, 0x5c, 0x7e, + 0x88, 0x18, 0xe2, 0xfd, 0x80, 0xcf, 0x16, 0x85, 0xeb, 0x6f, 0xdc, 0x67, + 0x96, 0x90, 0x6b, 0x68, 0x0a, 0x79, 0x0f, 0x79, 0x77, 0x96, 0x71, 0xf2, + 0x23, 0xc6, 0x4b, 0x9c, 0x1b, 0xe7, 0xe4, 0x62, 0x9e, 0x5f, 0x6b, 0x05, + 0x7f, 0x71, 0x87, 0x41, 0xfc, 0x36, 0xfb, 0x2e, 0xe7, 0xdb, 0x2f, 0x2b, + 0x74, 0x44, 0x82, 0x8f, 0xe6, 0xcb, 0xc8, 0xc3, 0xe7, 0xe0, 0xe3, 0x0b, + 0x2d, 0x16, 0xf5, 0x56, 0xe5, 0xf3, 0xc9, 0xd8, 0x18, 0x1f, 0x29, 0xa3, + 0xdf, 0x3e, 0xf8, 0xbc, 0x52, 0xce, 0x57, 0xf1, 0xe3, 0x57, 0xe0, 0xc7, + 0x61, 0xd9, 0xcf, 0x77, 0x16, 0x1d, 0x36, 0xbc, 0x3e, 0xe6, 0x11, 0xdb, + 0x9b, 0xda, 0xe8, 0x18, 0x5f, 0x1a, 0xf3, 0xff, 0xfd, 0x90, 0xff, 0x34, + 0xef, 0xc9, 0x8c, 0x0a, 0x0e, 0xe2, 0xef, 0x3d, 0x7d, 0xd4, 0xf7, 0x17, + 0x6a, 0xf1, 0x7d, 0xb6, 0xe0, 0x9e, 0x83, 0x67, 0x76, 0x38, 0xb4, 0x36, + 0x75, 0x6c, 0xec, 0x87, 0x18, 0x7b, 0x15, 0x79, 0x84, 0x7c, 0x05, 0x77, + 0xa6, 0x90, 0xf0, 0x9e, 0x5d, 0xa9, 0xe2, 0x03, 0x4e, 0xd0, 0xe5, 0xb4, + 0xe4, 0x82, 0x5c, 0x70, 0x81, 0xeb, 0xb4, 0xd5, 0x4d, 0x70, 0x21, 0x05, + 0x17, 0xe0, 0xd7, 0xd1, 0xbc, 0x59, 0xe0, 0xcc, 0x39, 0x07, 0xdf, 0x19, + 0xf3, 0x82, 0x79, 0xc0, 0x9c, 0x78, 0xc2, 0x85, 0x2b, 0x3d, 0xc3, 0xd8, + 0xfd, 0x2f, 0x3c, 0x78, 0x57, 0xf0, 0x80, 0xf9, 0x58, 0xe4, 0x85, 0x2e, + 0x70, 0x48, 0xca, 0xbc, 0x50, 0xe8, 0x9c, 0xeb, 0x1b, 0xd6, 0x78, 0xa1, + 0x8d, 0x2d, 0x68, 0xa3, 0xad, 0x70, 0xbd, 0xc3, 0xba, 0x60, 0x3f, 0xd6, + 0xc6, 0x49, 0x7e, 0x85, 0x46, 0xd2, 0xbe, 0x6d, 0x55, 0xf9, 0x21, 0x85, + 0x2e, 0xba, 0xa5, 0x46, 0xd2, 0x52, 0x23, 0xb0, 0x89, 0x95, 0x16, 0xe7, + 0x7a, 0xdb, 0x0a, 0x91, 0x17, 0xba, 0x62, 0xcc, 0x98, 0x8a, 0x3b, 0x09, + 0xeb, 0x96, 0xf3, 0xe9, 0x50, 0x1e, 0x2d, 0xef, 0xa5, 0x1d, 0x71, 0x2f, + 0xfd, 0x8a, 0x3e, 0x9a, 0x47, 0x67, 0x90, 0x43, 0xf8, 0x5e, 0x3a, 0xa7, + 0xf3, 0xbd, 0x14, 0xba, 0xd3, 0x87, 0xef, 0xa5, 0xc9, 0xc8, 0xbd, 0xb4, + 0xf2, 0xe5, 0xf6, 0x93, 0xf2, 0x69, 0x15, 0x13, 0xce, 0xa9, 0x02, 0xf3, + 0x13, 0x6a, 0xbf, 0xca, 0x86, 0xf3, 0x0d, 0x6b, 0xb9, 0xcc, 0x51, 0xa8, + 0xb5, 0xee, 0x67, 0x15, 0xe7, 0xdf, 0xc0, 0x3c, 0xf8, 0xee, 0x9f, 0xc4, + 0x79, 0xa3, 0xe4, 0xfc, 0x54, 0xe1, 0xd3, 0x1f, 0xe6, 0xfd, 0x1b, 0xfa, + 0x28, 0xef, 0xab, 0x71, 0x2a, 0xde, 0x17, 0x63, 0x3e, 0x54, 0x9a, 0x38, + 0xdb, 0x96, 0x91, 0x6b, 0x66, 0xf8, 0xbe, 0x85, 0x5c, 0xe0, 0xd5, 0x71, + 0xef, 0x98, 0xe1, 0xb1, 0xd3, 0x0c, 0xe7, 0x4d, 0x03, 0xbc, 0x17, 0x9c, + 0x3d, 0x12, 0xf7, 0x01, 0xac, 0x7b, 0x86, 0xab, 0xab, 0x51, 0x2e, 0xbe, + 0x88, 0x0b, 0x45, 0xb5, 0x97, 0xaa, 0xcd, 0x19, 0x6a, 0x5b, 0x2e, 0xb1, + 0x2e, 0x62, 0xfd, 0xa0, 0xb8, 0x8f, 0xd3, 0x2e, 0x6a, 0xb1, 0x43, 0xd4, + 0x39, 0x77, 0x70, 0x9f, 0x4b, 0x06, 0x8f, 0xf2, 0x07, 0x0d, 0x95, 0xba, + 0xc7, 0x3e, 0x5d, 0xac, 0xd7, 0x36, 0x6f, 0xe3, 0xed, 0xdd, 0x41, 0x15, + 0x53, 0xee, 0xe7, 0xb6, 0x7f, 0xe0, 0xbc, 0x45, 0x1d, 0x37, 0x32, 0x67, + 0xf5, 0xce, 0x7f, 0xff, 0x06, 0x63, 0xe1, 0x4b, 0x7b, 0x30, 0x12, 0x00, + 0x00, 0x00 }; static u32 bnx2_TPAT_b06FwData[(0x0/4) + 1] = { 0x0 }; static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 }; @@ -2554,939 +1543,422 @@ static const u32 bnx2_TXP_b06FwBssAddr = static const int bnx2_TXP_b06FwBssLen = 0x1c4; static const u32 bnx2_TXP_b06FwSbssAddr = 0x08005760; static const int bnx2_TXP_b06FwSbssLen = 0x38; -static u32 bnx2_TXP_b06FwText[(0x5748/4) + 1] = { - 0x0a000d2c, 0x00000000, 0x00000000, 0x0000000d, 0x74787020, 0x322e352e, - 0x38000000, 0x02050800, 0x0000000a, 0x000003e8, 0x0000ea60, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, - 0x24425760, 0x3c030800, 0x24635964, 0xac400000, 0x0043202b, 0x1480fffd, - 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x261034b0, - 0x3c1c0800, 0x279c5760, 0x0e000f5b, 0x00000000, 0x0000000d, 0x8f840014, - 0x27bdffe8, 0xafb10014, 0xafb00010, 0x8f460104, 0x8f830008, 0x8c8500ac, - 0xaf430080, 0x948200a8, 0xa7420e10, 0x948300aa, 0xa7430e12, 0x8c8200ac, - 0xaf420e18, 0x97430e10, 0xa7430e14, 0x97420e12, 0x00008021, 0xa7420e16, - 0x8f430e18, 0x00006021, 0x00c53023, 0xaf430e1c, 0x10c001a2, 0x2d820001, - 0x3c0e1000, 0x2419fff8, 0x24110010, 0x240f0f00, 0x3c188100, 0x93620008, - 0x10400009, 0x00000000, 0x97620010, 0x00c2102b, 0x14400005, 0x00000000, - 0x97620010, 0x3042ffff, 0x0a000d6d, 0xaf420e00, 0xaf460e00, 0x8f420000, - 0x30420008, 0x1040fffd, 0x00000000, 0x97420e08, 0x8f450e04, 0x3044ffff, - 0x30820001, 0x14400005, 0x00000000, 0x14a00005, 0x3083a040, 0x0a000f34, - 0x00000000, 0x0000000d, 0x3083a040, 0x24020040, 0x1462004f, 0x3082a000, - 0x308a0036, 0x8f88000c, 0x30890008, 0x24020800, 0xaf420178, 0x01001821, - 0x9742008a, 0x00431023, 0x2442ffff, 0x30421fff, 0x2c420008, 0x1440fffa, - 0x00a06021, 0x8f820018, 0x00cc3023, 0x24070001, 0x8f830008, 0x304b00ff, - 0x24420001, 0xaf820018, 0x25024000, 0x106f0005, 0x03422021, 0x93820012, - 0x30420007, 0x00021240, 0x34470001, 0x000b1400, 0x3c030100, 0x00431025, - 0xac820000, 0x8f830018, 0x00ea3825, 0x1120000f, 0xac830004, 0x97430e0a, - 0x8f84000c, 0x00ee3825, 0x2402000e, 0x00781825, 0xaf430160, 0x25830006, - 0x24840008, 0x30841fff, 0xa742015a, 0xa7430158, 0xaf84000c, 0x0a000db7, - 0x00000000, 0x8f83000c, 0x25820002, 0xa7420158, 0x24630008, 0x30631fff, - 0xaf83000c, 0x54c0000f, 0x8f420e14, 0x8f820008, 0x504f0002, 0x24100001, - 0x34e70040, 0x97420e10, 0x97430e12, 0x8f850014, 0x00021400, 0x00621825, - 0xaca300a8, 0x8f840014, 0x8f420e18, 0xac8200ac, 0x8f420e14, 0x8f430e1c, - 0xaf420144, 0xaf430148, 0xa34b0152, 0xaf470154, 0x0a000efb, 0xaf4e0178, - 0x10400165, 0x00000000, 0x93620008, 0x50400008, 0xafa60008, 0x97620010, - 0x00a2102b, 0x10400003, 0x30820040, 0x1040015c, 0x00000000, 0xafa60008, - 0xa7840010, 0xaf850004, 0x93620008, 0x1440005f, 0x27ac0008, 0xaf60000c, - 0x97820010, 0x30424000, 0x10400002, 0x2403000e, 0x24030016, 0xa363000a, - 0x24034007, 0xaf630014, 0x93820012, 0x8f630014, 0x30420007, 0x00021240, - 0x00621825, 0xaf630014, 0x97820010, 0x8f630014, 0x30420010, 0x00621825, - 0xaf630014, 0x97820010, 0x30420008, 0x5040000e, 0x00002821, 0x8f620014, - 0x004e1025, 0xaf620014, 0x97430e0a, 0x2402000e, 0x00781825, 0xaf630004, - 0xa3620002, 0x9363000a, 0x3405fffc, 0x24630004, 0x0a000e06, 0xa363000a, - 0xaf600004, 0xa3600002, 0x97820010, 0x9363000a, 0x30421f00, 0x00021182, - 0x24420028, 0x00621821, 0xa3630009, 0x97420e0c, 0xa7620010, 0x93630009, - 0x24020008, 0x24630002, 0x30630007, 0x00431023, 0x30420007, 0xa362000b, - 0x93640009, 0x97620010, 0x8f890004, 0x97830010, 0x00441021, 0x00a21021, - 0x30630040, 0x10600007, 0x3045ffff, 0x00a9102b, 0x14400005, 0x0125102b, - 0x3c068000, 0x0a000e3a, 0x00005821, 0x0125102b, 0x544000c7, 0x00006021, - 0x97420e14, 0xa7420e10, 0x97430e16, 0xa7430e12, 0x8f420e1c, 0xaf420e18, - 0xaf450e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000, 0x97420e08, - 0x00a04821, 0xa7820010, 0x8f430e04, 0x00003021, 0x240b0001, 0xaf830004, - 0x97620010, 0x0a000e4c, 0x304dffff, 0x8f890004, 0x97820010, 0x30420040, - 0x10400004, 0x01206821, 0x3c068000, 0x0a000e4c, 0x00005821, 0x97630010, - 0x8f820004, 0x10430003, 0x00003021, 0x0a000eee, 0x00006021, 0x240b0001, - 0x8d820000, 0x00491023, 0x1440000d, 0xad820000, 0x8f620014, 0x34420040, - 0xaf620014, 0x97430e10, 0x97420e12, 0x8f840014, 0x00031c00, 0x00431025, - 0xac8200a8, 0x8f830014, 0x8f420e18, 0xac6200ac, 0x93620008, 0x1440003e, - 0x00000000, 0x25260002, 0x8f84000c, 0x9743008a, 0x3063ffff, 0xafa30000, - 0x8fa20000, 0x00441023, 0x2442ffff, 0x30421fff, 0x2c420010, 0x1440fff7, - 0x00000000, 0x8f82000c, 0x8f830018, 0x00021082, 0x00021080, 0x24424000, - 0x03422821, 0x00605021, 0x24630001, 0x314200ff, 0x00021400, 0xaf830018, - 0x3c033200, 0x00431025, 0xaca20000, 0x93630009, 0x9362000a, 0x00031c00, - 0x00431025, 0xaca20004, 0x8f830018, 0xaca30008, 0x97820010, 0x30420008, - 0x10400002, 0x00c04021, 0x25280006, 0x97430e14, 0x93640002, 0x8f450e1c, - 0x8f660004, 0x8f670014, 0x3063ffff, 0xa7430144, 0x97420e16, 0xa7420146, - 0xaf450148, 0xa34a0152, 0x8f82000c, 0x308400ff, 0xa744015a, 0xaf460160, - 0xa7480158, 0xaf470154, 0xaf4e0178, 0x00511021, 0x30421fff, 0xaf82000c, - 0x0a000ed9, 0x8d820000, 0x93620009, 0x9363000b, 0x8f85000c, 0x2463000a, - 0x00435021, 0x25440007, 0x00992024, 0x9743008a, 0x3063ffff, 0xafa30000, - 0x8fa20000, 0x00451023, 0x2442ffff, 0x30421fff, 0x0044102b, 0x1440fff7, - 0x00000000, 0x8f82000c, 0x8f840018, 0x00021082, 0x00021080, 0x24424000, - 0x03422821, 0x00804021, 0x24840001, 0xaf840018, 0x93630009, 0x310200ff, - 0x00022400, 0x3c024100, 0x24630002, 0x00621825, 0x00832025, 0xaca40000, - 0x8f62000c, 0x00461025, 0xaca20004, 0x97430e14, 0x93640002, 0x8f450e1c, - 0x8f660004, 0x8f670014, 0x3063ffff, 0xa7430144, 0x97420e16, 0x308400ff, - 0xa7420146, 0xaf450148, 0xa3480152, 0x8f83000c, 0x25420007, 0x00591024, - 0xa744015a, 0xaf460160, 0xa7490158, 0xaf470154, 0xaf4e0178, 0x00621821, - 0x30631fff, 0xaf83000c, 0x8d820000, 0x14400005, 0x00000000, 0x8f620014, - 0x2403ffbf, 0x00431024, 0xaf620014, 0x8f62000c, 0x004d1021, 0xaf62000c, - 0x93630008, 0x14600008, 0x00000000, 0x11600006, 0x00000000, 0x8f630014, - 0x3c02efff, 0x3442fffe, 0x00621824, 0xaf630014, 0xa36b0008, 0x01206021, - 0x1580000c, 0x8fa60008, 0x97420e14, 0x97430e16, 0x8f850014, 0x00021400, - 0x00621825, 0xaca300a8, 0x8f840014, 0x8f420e1c, 0xac8200ac, 0x0a000efd, - 0x2d820001, 0x14c0fe65, 0x2d820001, 0x00501025, 0x10400058, 0x24020f00, - 0x8f830008, 0x14620023, 0x3c048000, 0x11800009, 0x3c038000, 0x97420e08, - 0x30420040, 0x14400005, 0x00000000, 0x0000000d, 0x00000000, 0x2400032c, - 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x00000000, 0x97420e10, - 0x3c030500, 0x00431025, 0xaf42014c, 0x97430e14, 0xa7430144, 0x97420e16, - 0xa7420146, 0x8f430e1c, 0x24022000, 0xaf430148, 0x3c031000, 0xa3400152, - 0xa740015a, 0xaf400160, 0xa7400158, 0xaf420154, 0xaf430178, 0x8f830008, - 0x3c048000, 0x8f420178, 0x00441024, 0x1440fffd, 0x24020f00, 0x10620016, - 0x00000000, 0x97420e14, 0xa7420144, 0x97430e16, 0xa7430146, 0x8f420e1c, - 0x3c031000, 0xaf420148, 0x0a000f51, 0x24020240, 0x97420e14, 0x97430e16, - 0x8f840014, 0x00021400, 0x00621825, 0xac8300a8, 0x8f850014, 0x8f420e1c, - 0x00006021, 0xaca200ac, 0x0a000efd, 0x2d820001, 0xaf40014c, 0x11800007, - 0x00000000, 0x97420e10, 0xa7420144, 0x97430e12, 0xa7430146, 0x0a000f4e, - 0x8f420e18, 0x97420e14, 0xa7420144, 0x97430e16, 0xa7430146, 0x8f420e1c, - 0xaf420148, 0x24020040, 0x3c031000, 0xa3400152, 0xa740015a, 0xaf400160, - 0xa7400158, 0xaf420154, 0xaf430178, 0x8fb10014, 0x8fb00010, 0x03e00008, - 0x27bd0018, 0x27bdffd0, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, 0x3c020008, - 0x03421821, 0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c, - 0xafb20018, 0xafb10014, 0xafb00010, 0xaf830014, 0xaf440e00, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd, - 0x3c046004, 0xaf420e00, 0x8c835000, 0x24160800, 0x24150d00, 0x3c140800, - 0x24130f00, 0x3c120800, 0x3c114000, 0x2402ff7f, 0x00621824, 0x3463380c, - 0x24020009, 0xac835000, 0xaf420008, 0xaf800018, 0xaf80000c, 0x0e001559, - 0x00000000, 0x0e000ff0, 0x00000000, 0x3c020800, 0x245057c0, 0x8f420000, - 0x30420001, 0x1040fffd, 0x00000000, 0x8f440100, 0xaf840008, 0xaf440020, - 0xaf560178, 0x93430108, 0xa3830012, 0x93820012, 0x30420001, 0x10400008, - 0x00000000, 0x93820012, 0x30420006, 0x00021100, 0x0e000d43, 0x0050d821, - 0x0a000fac, 0x00000000, 0x14950005, 0x00000000, 0x0e000d43, 0x269b5840, - 0x0a000fac, 0x00000000, 0x14930005, 0x00000000, 0x0e000d43, 0x265b5860, - 0x0a000fac, 0x00000000, 0x0e0010ea, 0x00000000, 0xaf510138, 0x0a000f89, - 0x00000000, 0x27bdfff8, 0x3084ffff, 0x24820007, 0x3044fff8, 0x8f85000c, - 0x9743008a, 0x3063ffff, 0xafa30000, 0x8fa20000, 0x00451023, 0x2442ffff, - 0x30421fff, 0x0044102b, 0x1440fff7, 0x00000000, 0x8f82000c, 0x00021082, - 0x00021080, 0x24424000, 0x03421021, 0x03e00008, 0x27bd0008, 0x3084ffff, - 0x8f82000c, 0x24840007, 0x3084fff8, 0x00441021, 0x30421fff, 0xaf82000c, - 0x03e00008, 0x00000000, 0x27bdffe8, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, - 0x3c020008, 0x03421821, 0xafbf0010, 0xaf830014, 0xaf440e00, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd, - 0x3c046004, 0xaf420e00, 0x8c825000, 0x2403ff7f, 0x00431024, 0x3442380c, - 0x24030009, 0xac825000, 0xaf430008, 0xaf800018, 0xaf80000c, 0x0e001559, - 0x00000000, 0x0e000ff0, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, - 0x27bdffe8, 0x3c02000a, 0x03421821, 0x3c040800, 0x24845880, 0x24050019, - 0xafbf0010, 0xaf830024, 0x0e001565, 0x00003021, 0x3c050800, 0x3c020800, - 0x24425330, 0xaca258e8, 0x24a558e8, 0x3c020800, 0x244254f8, 0x3c030800, - 0x2463550c, 0x3c040800, 0xaca20004, 0x3c020800, 0x24425338, 0xaca30008, - 0xac825900, 0x24845900, 0x3c020800, 0x244253c4, 0x3c070800, 0x24e75404, - 0x3c060800, 0x24c65520, 0x3c050800, 0x24a55438, 0x3c030800, 0xac820004, - 0x3c020800, 0x24425528, 0xac870008, 0xac86000c, 0xac850010, 0xac625920, - 0x24635920, 0x8fbf0010, 0x3c020800, 0x24425540, 0xac620004, 0x3c020800, - 0xac670008, 0xac66000c, 0xac650010, 0xac400048, 0x03e00008, 0x27bd0018, - 0x974309da, 0x00804021, 0xad030000, 0x8f4209dc, 0xad020004, 0x8f4309e0, - 0xad030008, 0x934409d9, 0x24020001, 0x30840003, 0x1082001f, 0x30a900ff, - 0x28820002, 0x10400005, 0x24020002, 0x10800009, 0x3c0a0800, 0x0a001078, - 0x93420934, 0x1082000b, 0x24020003, 0x10820026, 0x3c0a0800, 0x0a001078, - 0x93420934, 0x974209e4, 0x00021400, 0x34420800, 0xad02000c, 0x0a001077, - 0x25080010, 0x974209e4, 0x00021400, 0x34428100, 0xad02000c, 0x974309e8, - 0x3c0a0800, 0x00031c00, 0x34630800, 0xad030010, 0x0a001077, 0x25080014, - 0x974409e4, 0x3c050800, 0x24a25880, 0x9443001c, 0x94460014, 0x94470010, - 0x00a05021, 0x24020800, 0xad000010, 0xad020014, 0x00042400, 0x00661821, - 0x00671823, 0x2463fff2, 0x00832025, 0xad04000c, 0x0a001077, 0x25080018, - 0x974209e4, 0x3c050800, 0x00021400, 0x34428100, 0xad02000c, 0x974409e8, - 0x24a25880, 0x9443001c, 0x94460014, 0x94470010, 0x00a05021, 0x24020800, - 0xad000014, 0xad020018, 0x00042400, 0x00661821, 0x00671823, 0x2463ffee, - 0x00832025, 0xad040010, 0x2508001c, 0x93420934, 0x93450921, 0x3c074000, - 0x25445880, 0x94830018, 0x94860014, 0x00021082, 0x00021600, 0x00052c00, - 0x00a72825, 0x00451025, 0x00661821, 0x00431025, 0xad020000, 0x9783002c, - 0x974209ea, 0x00621821, 0x00031c00, 0xad030004, 0x9782002c, 0x24420001, - 0x30427fff, 0xa782002c, 0x93430920, 0x3c020006, 0x00031e00, 0x00621825, - 0xad030008, 0x8f42092c, 0xad02000c, 0x8f430930, 0xad030010, 0x8f440938, - 0x25080014, 0xad040000, 0x8f820020, 0x11200004, 0xad020004, 0x8f420940, - 0x0a0010a1, 0x2442ffff, 0x8f420940, 0xad020008, 0x8f440948, 0x8f420940, - 0x93430936, 0x00823023, 0x00663006, 0x3402ffff, 0x0046102b, 0x54400001, - 0x3406ffff, 0x93420937, 0x25445880, 0x90830024, 0xad000010, 0x00021700, - 0x34630010, 0x00031c00, 0x00431025, 0x00461025, 0xad02000c, 0x8c830008, - 0x14600031, 0x25080014, 0x3c020800, 0x8c430048, 0x1060002d, 0x00000000, - 0x9342010b, 0xad020000, 0x8f830000, 0x8c6200b0, 0xad020004, 0x8f830000, - 0x8c6200b4, 0xad020008, 0x8f830000, 0x8c6200c0, 0xad02000c, 0x8f830000, - 0x8c6200c4, 0xad020010, 0x8f830000, 0x8c6200c8, 0xad020014, 0x8f830000, - 0x8c6200cc, 0xad020018, 0x8f830000, 0x8c6200e0, 0xad02001c, 0x8f830000, - 0x8c6200e8, 0xad020020, 0x8f830000, 0x8c6200f0, 0x3c04600e, 0xad020024, - 0x8c8200d0, 0xad020028, 0x8c8300d4, 0xad03002c, 0x8f820028, 0x3c046012, - 0xad020030, 0x8c8200a8, 0xad020034, 0x8c8300ac, 0x3c026000, 0xad030038, - 0x8c434448, 0xad03003c, 0x03e00008, 0x01001021, 0x27bdffa8, 0x3c020008, - 0x03423021, 0xafbf0054, 0xafbe0050, 0xafb7004c, 0xafb60048, 0xafb50044, - 0xafb40040, 0xafb3003c, 0xafb20038, 0xafb10034, 0xafb00030, 0xaf860000, - 0x24020040, 0xaf420814, 0xaf400810, 0x8f420944, 0x8f430950, 0x8f440954, - 0x8f45095c, 0xaf820034, 0xaf830020, 0xaf84001c, 0xaf850030, 0x90c20000, - 0x24030020, 0x304400ff, 0x10830005, 0x24020030, 0x10820022, 0x3c030800, - 0x0a001139, 0x8c62002c, 0x24020088, 0xaf420818, 0x3c020800, 0x244258e8, - 0xafa20020, 0x93430109, 0x3c020800, 0x10600009, 0x24575900, 0x3c026000, - 0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, - 0x24000376, 0x9342010a, 0x30420080, 0x14400021, 0x24020800, 0x3c026000, - 0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, - 0x2400037d, 0x0a001141, 0x24020800, 0x93430109, 0x3063007f, 0x00031140, - 0x000318c0, 0x00431021, 0x24430088, 0xaf430818, 0x0000000d, 0x3c020800, - 0x24425940, 0x3c030800, 0x24775950, 0x0a001140, 0xafa20020, 0x24420001, - 0xac62002c, 0x0000000d, 0x00000000, 0x24000395, 0x0a0014c1, 0x8fbf0054, - 0x24020800, 0xaf420178, 0x8f450104, 0x8f420988, 0x00a21023, 0x58400005, - 0x8f4309a0, 0x0000000d, 0x00000000, 0x240003b1, 0x8f4309a0, 0x3c100800, - 0xae0358b0, 0x8f4209a4, 0x8f830020, 0x260458b0, 0x2491ffd0, 0xae220034, - 0x00a21023, 0xae230028, 0xac82ffd0, 0x8fa30020, 0x8c620000, 0x0040f809, - 0x0200b021, 0x00409021, 0x32440010, 0x32420002, 0x10400007, 0xafa40024, - 0x8e220020, 0x32530040, 0x2403ffbf, 0x00431024, 0x0a001493, 0xae220020, - 0x32420020, 0x10400002, 0x3c020800, 0x24575920, 0x32420001, 0x14400007, - 0x00000000, 0x8f820008, 0xaf420080, 0x8ec358b0, 0xaf430e10, 0x8e220034, - 0xaf420e18, 0x9343010b, 0x93420905, 0x30420008, 0x1040003c, 0x307400ff, - 0x8f820000, 0x8c430074, 0x0460000a, 0x00000000, 0x3c026000, 0x24030100, - 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x240003ed, - 0x8f820000, 0x9044007b, 0x9343010a, 0x14830027, 0x32530040, 0x00003821, - 0x24052000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, - 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030100, - 0xaf420148, 0x24020047, 0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, - 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001, 0xad230030, - 0x9342010a, 0x3c030047, 0xafa50014, 0x00021600, 0x00431025, 0x00471025, - 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, - 0x3c070100, 0x3c050800, 0x24a25880, 0x0a001250, 0x8c430020, 0x32820002, - 0x10400050, 0x00000000, 0x0e0015b9, 0x32530040, 0x3c039000, 0x34630001, - 0x8f820008, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, 0x00441024, - 0x1440fffd, 0x00000000, 0x8f830000, 0x90620005, 0x34420008, 0xa0620005, - 0x8f840000, 0x8c820074, 0x3c038000, 0x00431025, 0xac820074, 0x90830000, - 0x24020020, 0x10620004, 0x00000000, 0x0000000d, 0x00000000, 0x2400040b, - 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x9084007b, - 0x9342010a, 0x14820028, 0x3c030800, 0x00003821, 0x24052000, 0x3c090800, - 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, 0x26c458b0, - 0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030100, 0xaf420148, 0x24020046, - 0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7470158, 0xaf450154, - 0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030046, - 0xafa50014, 0x00021600, 0x00431025, 0x00471025, 0xafa20010, 0x9343010b, - 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x3c070100, 0x3c030800, - 0x24625880, 0x0a001250, 0x8c430020, 0x93420108, 0x30420010, 0x50400056, - 0x9343093f, 0x8f860000, 0x90c2007f, 0x8cc30178, 0x304800ff, 0x15030004, - 0x00000000, 0x0000000d, 0x00000000, 0x24000425, 0x90c2007e, 0x90c40080, - 0x00081c00, 0x00021600, 0x00431025, 0x00042200, 0x90c3007a, 0x90c5000a, - 0x00441025, 0x11050028, 0x00623825, 0xa0c8000a, 0x00004021, 0x24056000, - 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, - 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, 0xaf420148, 0x24020052, - 0xaf47014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7480158, 0xaf450154, - 0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030052, - 0xafa50014, 0x00021600, 0x00431025, 0x00481025, 0xafa20010, 0x9343010b, - 0xafa30018, 0x8f440100, 0x0e00159b, 0x8f450104, 0x0a00124a, 0x00000000, - 0x3c026000, 0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, - 0x00000000, 0x2400043e, 0x16800009, 0x3c050800, 0x3c040800, 0x24825880, - 0x8c430020, 0x32530040, 0x2404ffbf, 0x00641824, 0x0a001493, 0xac430020, - 0x8ca25880, 0x10400005, 0x3c030800, 0x8c620034, 0xaca05880, 0x24420001, - 0xac620034, 0x9343093f, 0x24020012, 0x5462000e, 0x97420908, 0x32820038, - 0x14400009, 0x3c030800, 0x8f830000, 0x8c62004c, 0xac62005c, 0x3c020800, - 0x24445880, 0x8c820020, 0x0a001285, 0x32530040, 0xac605880, 0x97420908, - 0x5440001c, 0x97420908, 0x3c039000, 0x34630001, 0x8f820008, 0x32530040, - 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, 0x00441024, 0x1440fffd, - 0x3c028000, 0x8f840000, 0x8f850008, 0x8c830050, 0x34420001, 0x00a22825, - 0xaf830020, 0xac830070, 0xac83005c, 0xaf450020, 0x3c050800, 0x24a45880, - 0x8c820020, 0x2403ffbf, 0x00431024, 0x0a001493, 0xac820020, 0x000211c0, - 0xaf420024, 0x97420908, 0x3c030080, 0x34630003, 0x000211c0, 0xaf42080c, - 0xaf43081c, 0x974209ec, 0x8f4309a4, 0xa782002c, 0x3c020800, 0x24445880, - 0xac83002c, 0x93420937, 0x93430934, 0x00021080, 0x00621821, 0xa4830018, - 0x934209d8, 0x32850038, 0xafa50028, 0x00621821, 0xa483001a, 0x934209d8, - 0x93430934, 0x3c1e0800, 0x00809821, 0x00431021, 0x24420010, 0xa4820016, - 0x24020006, 0xae620020, 0x8fa20028, 0x10400003, 0x0000a821, 0x0a0012f0, - 0x24120008, 0x8f420958, 0x8f830020, 0x8f840030, 0x00431023, 0x00832023, - 0x04800003, 0xae620004, 0x04410003, 0x0082102b, 0x0a0012bc, 0xae600004, - 0x54400001, 0xae640004, 0x8ee20000, 0x0040f809, 0x00000000, 0x00409021, - 0x32420001, 0x5440001e, 0x8ee20004, 0x8e630008, 0x1060002b, 0x3c02c000, - 0x00621025, 0xaf420e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000, - 0x97420e08, 0xa7820010, 0x8f430e04, 0x8e620008, 0xaf830004, 0x8f840004, - 0x0044102b, 0x1040000b, 0x24150001, 0x24020100, 0x3c016000, 0xac22081c, - 0x3c020001, 0x3c016000, 0xac22081c, 0x0000000d, 0x00000000, 0x240004cd, - 0x24150001, 0x8ee20004, 0x0040f809, 0x00000000, 0x02429025, 0x32420002, - 0x5040001d, 0x8f470940, 0x12a00006, 0x8ec258b0, 0x8f830000, 0xac6200a8, - 0x8f840000, 0x8e620034, 0xac8200ac, 0x32420004, 0x50400013, 0x8f470940, - 0x3c020800, 0x3283007d, 0x10600110, 0x24575920, 0x32820001, 0x50400006, - 0x36520002, 0x8f830034, 0x8f420940, 0x10620109, 0x00000000, 0x36520002, - 0x24020008, 0xa6600010, 0xa6620012, 0xae600008, 0xa2600024, 0x8f470940, - 0x3c030800, 0x24685880, 0x8d02002c, 0x8d050008, 0x95040010, 0x9506000a, - 0x95030026, 0x00451021, 0x00862021, 0x00641821, 0xaf870034, 0xad02002c, - 0x32820030, 0x10400008, 0xa5030014, 0x91020024, 0x32910040, 0x34420004, - 0xa1020024, 0xaf400048, 0x0a001345, 0x3c040800, 0x93420923, 0x30420002, - 0x10400029, 0x32910040, 0x8f830000, 0x8f840020, 0x8c620084, 0x00441023, - 0x0442000a, 0x3c039000, 0x95020014, 0x8c630084, 0x00821021, 0x00621823, - 0x1c600004, 0x3c039000, 0x91020024, 0x34420001, 0xa1020024, 0x34630001, - 0x8f820008, 0x32910040, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, - 0x00441024, 0x1440fffd, 0x00000000, 0x8f840000, 0x9083003f, 0x2402000a, - 0x10620005, 0x2402000c, 0x9083003f, 0x24020008, 0x14620002, 0x24020014, - 0xa082003f, 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, - 0x3c040800, 0x24865880, 0x94c20010, 0x94c3001a, 0x8cc40008, 0x00432821, - 0x14800006, 0xa4c5001c, 0x3c020800, 0x8c430048, 0x10600002, 0x24a20040, - 0xa4c2001c, 0x27d05880, 0x9604001c, 0x96020012, 0x00822021, 0x24840002, - 0x0e000faf, 0x3084ffff, 0x8f850018, 0x00a01821, 0xa2030025, 0x8ee60008, - 0x00402021, 0x24a50001, 0xaf850018, 0x00c0f809, 0x00000000, 0x00402021, - 0x0e001026, 0x02202821, 0x8ee3000c, 0x0060f809, 0x00402021, 0x9604001c, - 0x96020012, 0x00822021, 0x24840002, 0x0e000fc5, 0x3084ffff, 0x8fc25880, - 0x8e030008, 0x00431023, 0x14400012, 0xafc25880, 0x54600006, 0x8e020020, - 0x3243004a, 0x24020002, 0x14620005, 0x00000000, 0x8e020020, 0x34420040, - 0x0a001382, 0xae020020, 0x52a00006, 0x36520002, 0x8e020030, 0xaf420e10, - 0x8e030034, 0xaf430e18, 0x36520002, 0x52a00008, 0x96670014, 0x8f830000, - 0x8f420e10, 0xac6200a8, 0x8f840000, 0x8f420e18, 0xac8200ac, 0x96670014, - 0x92680024, 0x24020040, 0xaf420814, 0x8f830020, 0x8f82001c, 0x00671821, - 0x00621023, 0xaf830020, 0x18400008, 0x00000000, 0x8f820000, 0xaf83001c, - 0xac430054, 0x54e00005, 0xaf400040, 0x0a0013a0, 0x8f42095c, 0x54e00001, - 0xaf400044, 0x8f42095c, 0x31030008, 0xaf820030, 0x1060001a, 0x00000000, - 0x8f840000, 0x90820120, 0x90830121, 0x304600ff, 0x00c31823, 0x30630007, - 0x24020007, 0x1062000e, 0x00000000, 0x90820122, 0x304200fe, 0xa0820122, - 0x8f850000, 0x00061880, 0x8f840020, 0x24a20100, 0x00431021, 0x24c30001, - 0x30630007, 0xac440000, 0x0a0013bd, 0xa0a30120, 0x90820122, 0x34420001, - 0xa0820122, 0x14e00003, 0x31020001, 0x10400031, 0x32510002, 0x8f820000, - 0x8c43000c, 0x30630001, 0x1060002c, 0x32510002, 0x3c029000, 0x8f830008, - 0x34420001, 0x3c048000, 0x00621825, 0xaf430020, 0x8f420020, 0x00441024, - 0x1440fffd, 0x00000000, 0x8f870000, 0x8ce2000c, 0x30420001, 0x10400018, - 0x00000000, 0x94e2006a, 0x00022880, 0x50a00001, 0x24050001, 0x94e30068, - 0x90e40081, 0x3c020800, 0x8c460024, 0x00652821, 0x00852804, 0x00c5102b, - 0x54400001, 0x00a03021, 0x3c020800, 0x8c440028, 0x00c4182b, 0x54600001, - 0x00c02021, 0x8f430074, 0x2402fffe, 0x00822824, 0x00a31821, 0xace3000c, - 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x8f820020, - 0x3c050800, 0x24b05880, 0xae020028, 0x8ee30010, 0x0060f809, 0x00000000, - 0x8f820028, 0x24420001, 0xaf820028, 0x12a00005, 0xaf40004c, 0x8f420e10, - 0xae020030, 0x8f430e18, 0xae030034, 0x1220fea7, 0x24020006, 0x8f870024, - 0x9786002c, 0x8f830000, 0x8f820034, 0x8f840020, 0x8f85001c, 0x32530040, - 0xa4e6002c, 0xac620044, 0x32420008, 0xac640050, 0xac650054, 0x1040007a, - 0x32820020, 0x10400027, 0x32910010, 0x00003821, 0x24052000, 0x3c090800, - 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, 0x26c458b0, - 0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030400, 0xaf420148, 0x24020041, - 0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7470158, 0xaf450154, - 0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030041, - 0xafa50014, 0x00021600, 0x00431025, 0x00471025, 0xafa20010, 0x9343010b, - 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x3c070400, 0x12200028, - 0x00003821, 0x24052000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, - 0x1440fffd, 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, - 0x3c030300, 0xaf420148, 0x2402004e, 0xaf43014c, 0xa3420152, 0x8d230030, - 0x3c021000, 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001, - 0xad230030, 0x9342010a, 0x3c03004e, 0xafa50014, 0x00021600, 0x00431025, - 0x00471025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104, - 0x0e00159b, 0x3c070300, 0x0a00148b, 0x8fa20024, 0x32820008, 0x10400026, - 0x24052000, 0x00003821, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, - 0x1440fffd, 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, - 0x3c030200, 0xaf420148, 0x2402004b, 0xaf43014c, 0xa3420152, 0x8d230030, - 0x3c021000, 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001, - 0xad230030, 0x9342010a, 0x3c03004b, 0xafa50014, 0x00021600, 0x00431025, - 0x00471025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104, - 0x0e00159b, 0x3c070200, 0x8fa20024, 0x14400004, 0x8fa30020, 0x32420010, - 0x10400004, 0x00000000, 0x8c620004, 0x0040f809, 0x00000000, 0x12600006, - 0x8fa40020, 0x8c820008, 0x0040f809, 0x00000000, 0x0a0014c1, 0x8fbf0054, - 0x3c030800, 0x8c6258a0, 0x30420040, 0x14400023, 0x8fbf0054, 0x00002821, - 0x24040040, 0x8f870020, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, - 0x8ec258b0, 0x26c358b0, 0x2463ffd0, 0xaf420144, 0x8c620034, 0xaf420148, - 0x24020049, 0xaf47014c, 0xa3420152, 0x3c021000, 0xa7450158, 0xaf440154, - 0xaf420178, 0x8c660034, 0x9342010a, 0x3c030049, 0xafa40014, 0x00021600, - 0x00431025, 0x00451025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, - 0x0e00159b, 0x8f450104, 0x8fbf0054, 0x8fbe0050, 0x8fb7004c, 0x8fb60048, - 0x8fb50044, 0x8fb40040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, - 0x03e00008, 0x27bd0058, 0x03e00008, 0x00001021, 0x3c020800, 0x24435880, - 0x8c650004, 0x8c445880, 0x0085182b, 0x10600002, 0x00403021, 0x00802821, - 0x9744093c, 0x00a4102b, 0x54400001, 0x00a02021, 0x93420923, 0x0004182b, - 0x00021042, 0x30420001, 0x00431024, 0x1040000d, 0x24c25880, 0x8f850000, - 0x8f830020, 0x8ca20084, 0x00431023, 0x04420007, 0x24c25880, 0x8ca20084, - 0x00641821, 0x00431023, 0x28420001, 0x00822023, 0x24c25880, 0xac440008, - 0xa4400026, 0x03e00008, 0x00001021, 0x8f850004, 0x97840010, 0x3c030800, - 0x24635880, 0x24020008, 0xa4620012, 0x8f820004, 0xa4600010, 0x000420c2, - 0x30840008, 0x2c420001, 0x00021023, 0x30420006, 0xac650008, 0x03e00008, - 0xa0640024, 0x3c020800, 0x24425880, 0x90450025, 0x9443001c, 0x3c021100, - 0xac800004, 0x00052c00, 0x24630002, 0x00621825, 0x00a32825, 0x24820008, - 0x03e00008, 0xac850000, 0x27bdffd8, 0x3c020800, 0x24425880, 0xafbf0020, - 0x90480025, 0x8c440008, 0x8c460020, 0x8f870020, 0x3c030800, 0x3c058000, - 0x8f420178, 0x00451024, 0x1440fffd, 0x8c6258b0, 0x246358b0, 0x2469ffd0, - 0xaf420144, 0x8d220034, 0x30c32000, 0xaf420148, 0x3c021000, 0xaf47014c, - 0xa3480152, 0xa7440158, 0xaf460154, 0xaf420178, 0x10600004, 0x3c030800, - 0x8c620030, 0x24420001, 0xac620030, 0x9342010a, 0x00081c00, 0x3084ffff, - 0xafa60014, 0x00021600, 0x00431025, 0x00441025, 0xafa20010, 0x9343010b, - 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x8d260034, 0x8fbf0020, - 0x03e00008, 0x27bd0028, 0x0000000d, 0x00000000, 0x2400019d, 0x03e00008, - 0x00000000, 0x0000000d, 0x00000000, 0x240001a9, 0x03e00008, 0x00000000, - 0x03e00008, 0x00000000, 0x3c020800, 0x24425880, 0xac400008, 0xa4400026, - 0x03e00008, 0x24020001, 0x3c020800, 0x24425880, 0x24030008, 0xac400008, - 0xa4400010, 0xa4430012, 0xa0400024, 0x03e00008, 0x24020004, 0x03e00008, - 0x00001021, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, - 0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00156c, - 0x00a01021, 0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021, - 0x1440fffa, 0x24a5ffff, 0x03e00008, 0x00000000, 0x3c0a0800, 0x8d490068, - 0x3c050800, 0x24a52098, 0x00093140, 0x00c51021, 0xac440000, 0x8f440e04, - 0x00a61021, 0xac440004, 0x97430e08, 0x97420e0c, 0x00a62021, 0x00031c00, - 0x00431025, 0xac820008, 0x8f430e10, 0x00801021, 0xac43000c, 0x8f440e14, - 0xac440010, 0x8f430e18, 0x3c0800ff, 0xac430014, 0x8f470e1c, 0x3508ffff, - 0x25290001, 0xac470018, 0x3c070800, 0x8ce3006c, 0x9344010a, 0x3c026000, - 0x24630001, 0xace3006c, 0x8c434448, 0x3129007f, 0x00a62821, 0xad490068, - 0x00042600, 0x00681824, 0x00832025, 0x03e00008, 0xaca4001c, 0x8fac0010, - 0x8fad0014, 0x8fae0018, 0x3c0b0800, 0x8d6a0060, 0x3c080800, 0x25080080, - 0x000a4940, 0x01281021, 0x01091821, 0xac440000, 0x00601021, 0xac650004, - 0xac460008, 0xac67000c, 0xac4c0010, 0xac6d0014, 0x3c036000, 0xac4e0018, - 0x8c654448, 0x3c040800, 0x8c820064, 0x254a0001, 0x314a00ff, 0x01094021, - 0xad6a0060, 0x24420001, 0xac820064, 0x03e00008, 0xad05001c, 0x3c030800, - 0x3c090800, 0x8d250070, 0x246330b0, 0x8f460100, 0x00053900, 0x00e31021, - 0xac460000, 0x8f440104, 0x00671021, 0xac440004, 0x8f460108, 0x8f840014, - 0x24a50001, 0xac460008, 0x8c880074, 0x3c060800, 0x8cc20074, 0x30a5003f, - 0x00671821, 0xad250070, 0x24420001, 0xacc20074, 0x03e00008, 0xac68000c, - 0x00000000 }; +static u8 bnx2_TXP_b06FwText[] = { + 0x1f, 0x8b, 0x08, 0x08, 0x21, 0xd3, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x6d, 0x6c, + 0x1b, 0xf7, 0x79, 0x7f, 0xee, 0x85, 0xd2, 0x51, 0x96, 0xe9, 0x93, 0xc2, + 0x78, 0x6c, 0xc0, 0xa6, 0x77, 0xd6, 0x51, 0x66, 0x20, 0xb5, 0xa0, 0x05, + 0x36, 0x55, 0x87, 0x43, 0x73, 0x3e, 0x52, 0x2f, 0x4e, 0x5c, 0x57, 0x71, + 0x94, 0x86, 0x6e, 0x0d, 0x8c, 0xa0, 0xec, 0xd8, 0xeb, 0x5a, 0x2c, 0x1f, + 0x8c, 0xd5, 0x68, 0xd1, 0x99, 0xa1, 0x68, 0xc7, 0xc9, 0x68, 0x51, 0xa9, + 0xe5, 0xa8, 0x43, 0x57, 0x80, 0x95, 0x64, 0xcb, 0x29, 0x4e, 0x3a, 0x65, + 0xcb, 0x16, 0x0c, 0x58, 0x16, 0xcd, 0x2f, 0x5d, 0x3f, 0x74, 0x80, 0x3f, + 0xec, 0x43, 0x3a, 0xec, 0x83, 0x91, 0x14, 0xad, 0x11, 0x6c, 0x59, 0xb0, + 0x2f, 0x33, 0xd6, 0x26, 0xb7, 0xdf, 0x73, 0x77, 0x94, 0x95, 0xc4, 0x4e, + 0xab, 0x7d, 0xbe, 0x07, 0x20, 0xee, 0x7f, 0xff, 0xd7, 0xe7, 0xfd, 0xe5, + 0x7f, 0x90, 0x06, 0xb7, 0x53, 0x17, 0x85, 0xb0, 0x1d, 0x3f, 0xed, 0x99, + 0x93, 0x27, 0x3e, 0xf7, 0xf9, 0xcf, 0x0d, 0xa1, 0x39, 0x4c, 0x4a, 0x4c, + 0xe4, 0xc1, 0x5b, 0x12, 0x51, 0xf9, 0x1d, 0x8a, 0x20, 0x82, 0x08, 0x22, + 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, + 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, + 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, + 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, + 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, + 0xf8, 0x9d, 0x20, 0x11, 0xa9, 0xfc, 0xdc, 0x1e, 0xfe, 0x48, 0x11, 0xcd, + 0xf2, 0x53, 0xb6, 0x41, 0x8a, 0x64, 0x1e, 0x39, 0x34, 0x65, 0x10, 0x59, + 0xce, 0x80, 0x56, 0xa0, 0xf7, 0xbd, 0x6a, 0x52, 0x26, 0xee, 0xff, 0xb4, + 0xf9, 0xdb, 0x53, 0xaf, 0x7f, 0x41, 0x7f, 0xaf, 0x25, 0x91, 0xa2, 0x9a, + 0x6b, 0x79, 0xb5, 0x9f, 0x94, 0x34, 0xd6, 0xfc, 0xd5, 0xee, 0xaf, 0xef, + 0xa0, 0x44, 0x7b, 0xaf, 0x24, 0xd5, 0x9b, 0xb7, 0xbc, 0xd7, 0x77, 0x27, + 0xe9, 0x15, 0x57, 0xa5, 0x35, 0x57, 0x16, 0x46, 0x9b, 0x0a, 0x4d, 0x37, + 0x1d, 0x3a, 0xdd, 0xa8, 0x52, 0xc1, 0xbd, 0x4c, 0xb5, 0x39, 0x35, 0x61, + 0x2f, 0xff, 0x84, 0xa6, 0xe7, 0x7a, 0x13, 0x85, 0x65, 0x87, 0x6a, 0x8d, + 0x54, 0xc2, 0x76, 0xd5, 0x44, 0x61, 0x3e, 0x89, 0xf7, 0xde, 0x84, 0x3d, + 0xaf, 0x57, 0x89, 0x76, 0x62, 0x4e, 0x2a, 0x51, 0x68, 0xea, 0x65, 0xa2, + 0xbe, 0xdc, 0x75, 0x4a, 0x27, 0x0a, 0xee, 0x82, 0xb0, 0xae, 0x0a, 0x54, + 0xfb, 0x2c, 0xa9, 0x09, 0xf3, 0xb6, 0xf7, 0x29, 0x43, 0xa5, 0x1e, 0x83, + 0x76, 0xec, 0x30, 0xe8, 0xd9, 0x94, 0xa9, 0x50, 0xe5, 0x7c, 0x9c, 0x2c, + 0x9f, 0x26, 0x95, 0x2a, 0xf3, 0x03, 0xea, 0x15, 0x8a, 0x91, 0x95, 0x6c, + 0xbf, 0x7b, 0x9e, 0x9d, 0xfb, 0x16, 0xff, 0x9d, 0x16, 0xce, 0xa2, 0xc4, + 0xa8, 0x4b, 0x64, 0x03, 0x2f, 0x3b, 0xf7, 0xbe, 0x17, 0xac, 0x51, 0x70, + 0xae, 0x9c, 0x18, 0x69, 0x7a, 0x5e, 0x31, 0x87, 0x33, 0x72, 0xed, 0xb5, + 0x31, 0x6a, 0x25, 0xad, 0xd6, 0x74, 0x2e, 0xbf, 0x23, 0xf8, 0x1b, 0x2f, + 0xa6, 0x91, 0xdf, 0x2d, 0x12, 0x8d, 0xaf, 0x50, 0x25, 0x49, 0xad, 0x5a, + 0xee, 0x61, 0x7a, 0x21, 0xd7, 0x4d, 0x67, 0xb1, 0xdf, 0xf3, 0x39, 0xf0, + 0xd1, 0x38, 0x29, 0xd8, 0xae, 0x9e, 0x22, 0xe1, 0x05, 0xb2, 0xe7, 0xfb, + 0xd4, 0x02, 0xe1, 0x6c, 0xc3, 0xfb, 0x8c, 0x9d, 0xc3, 0x79, 0x83, 0xff, + 0xeb, 0x59, 0x49, 0xbd, 0xdc, 0xa2, 0x14, 0xd5, 0x9a, 0x7d, 0xb9, 0x9f, + 0x93, 0x40, 0x9d, 0x06, 0xf3, 0xc7, 0xa3, 0xc7, 0x70, 0xae, 0x6d, 0xa0, + 0xdf, 0x25, 0x4b, 0xcc, 0xc4, 0xe8, 0x4f, 0x55, 0x5d, 0xb3, 0xa5, 0x5e, + 0xaa, 0x9d, 0xef, 0x04, 0x9e, 0x56, 0xaf, 0x88, 0xb9, 0x63, 0x79, 0x4a, + 0x6e, 0x23, 0x12, 0x24, 0x33, 0x83, 0x7d, 0x89, 0x6a, 0x4e, 0x0a, 0x6b, + 0x33, 0xc3, 0xef, 0xd0, 0x0e, 0xd2, 0x7a, 0x64, 0x9a, 0x76, 0xba, 0xc0, + 0xc7, 0x6e, 0xc8, 0x20, 0x33, 0xfc, 0x2e, 0x84, 0x22, 0x1a, 0x99, 0xd4, + 0x49, 0x2a, 0x0b, 0x05, 0xb7, 0x83, 0xa6, 0x33, 0x0a, 0xd5, 0x81, 0x47, + 0x3d, 0xf7, 0x35, 0xc1, 0x5e, 0x2e, 0x09, 0x85, 0x65, 0xcc, 0x73, 0x5f, + 0x0b, 0xff, 0x76, 0xad, 0x1b, 0xfb, 0x88, 0x54, 0xcb, 0x94, 0x30, 0xa6, + 0xd0, 0x14, 0xe6, 0x4d, 0x81, 0xa6, 0x69, 0x77, 0x07, 0xad, 0x4f, 0x26, + 0x13, 0xcc, 0xab, 0x1a, 0xc6, 0xbf, 0x32, 0x21, 0x90, 0x6a, 0x58, 0xf4, + 0xeb, 0x3c, 0x64, 0x38, 0xdf, 0xcb, 0x32, 0xa3, 0xd3, 0x4d, 0x4a, 0x8a, + 0x94, 0x49, 0x55, 0xe8, 0x32, 0x2d, 0x3a, 0x2c, 0x7f, 0xc8, 0x13, 0xf2, + 0xae, 0x39, 0xbc, 0x0e, 0x72, 0x6b, 0x16, 0xc1, 0x8f, 0x71, 0xe0, 0x70, + 0x50, 0x78, 0x6c, 0x71, 0x52, 0x18, 0x73, 0x7f, 0x93, 0xa0, 0xae, 0x93, + 0xc2, 0x01, 0xf7, 0xa8, 0x10, 0xf2, 0x1e, 0xb2, 0x53, 0xc8, 0x9a, 0x50, + 0xe8, 0x92, 0x1b, 0xc8, 0x6e, 0x01, 0xfa, 0x69, 0xa9, 0x16, 0xe4, 0x70, + 0x78, 0x63, 0x0e, 0x8f, 0xd5, 0x97, 0x65, 0x3a, 0xed, 0xf2, 0xfc, 0x3f, + 0x82, 0x7c, 0x14, 0x72, 0x76, 0x77, 0x53, 0x19, 0xfd, 0xb5, 0x79, 0xb2, + 0xec, 0x9c, 0x88, 0x35, 0x09, 0x92, 0x8c, 0x9d, 0xf8, 0x75, 0xd1, 0xd4, + 0x62, 0xa7, 0x25, 0x19, 0x49, 0x9a, 0x72, 0x99, 0x87, 0x78, 0x36, 0xdb, + 0x7c, 0x64, 0x5c, 0xb9, 0x9f, 0xd7, 0x71, 0xbf, 0x8a, 0xfe, 0xcd, 0x7d, + 0xac, 0x17, 0x09, 0xe0, 0xa3, 0x67, 0x59, 0x9f, 0x2b, 0xcd, 0x8c, 0x7a, + 0x80, 0x9f, 0x2e, 0xf3, 0xb6, 0xcd, 0x53, 0x19, 0x73, 0x45, 0xaa, 0x2c, + 0xe2, 0x9c, 0xf3, 0xbf, 0xf5, 0x62, 0x79, 0xbc, 0x1b, 0x1d, 0xa0, 0x8b, + 0xcf, 0x95, 0x81, 0x93, 0x48, 0xe5, 0x45, 0xde, 0x8b, 0xc7, 0x09, 0xb2, + 0xaf, 0xf5, 0x88, 0x94, 0x85, 0x7c, 0x75, 0x9c, 0x13, 0xc7, 0x9c, 0x6e, + 0xf0, 0x0f, 0xb4, 0x2e, 0xa3, 0x0d, 0xda, 0x45, 0x43, 0xc4, 0xfa, 0x4e, + 0x9a, 0xca, 0xb1, 0xbe, 0x30, 0x9e, 0xdb, 0xb0, 0x77, 0x9c, 0x8e, 0x9c, + 0x67, 0x7e, 0xc8, 0xf4, 0x3c, 0x70, 0x9c, 0x9e, 0xd7, 0xd5, 0x22, 0xe9, + 0xe0, 0x8d, 0x85, 0x79, 0x9d, 0x54, 0x56, 0x3d, 0x6f, 0x24, 0x37, 0xa0, + 0xbe, 0xec, 0xeb, 0xf9, 0x80, 0x9a, 0x11, 0xa8, 0xda, 0x61, 0xfe, 0x21, + 0x70, 0xd0, 0x4b, 0x44, 0xfc, 0xfe, 0xcf, 0x64, 0x4d, 0xb2, 0xfd, 0x24, + 0xf9, 0x2c, 0xd8, 0xd3, 0x4e, 0xe0, 0xcf, 0x36, 0x97, 0x86, 0x5c, 0x52, + 0xbe, 0x1d, 0x8c, 0xdc, 0xd5, 0x0e, 0xf4, 0xf1, 0x16, 0x6c, 0xa6, 0xb6, + 0x2c, 0xb3, 0xfd, 0xe5, 0xa0, 0x6e, 0xb4, 0xcd, 0x80, 0x6e, 0xf9, 0xb2, + 0xd9, 0x8f, 0xfd, 0x3d, 0xef, 0xcb, 0xb9, 0x00, 0xa7, 0xda, 0xbc, 0x85, + 0xb5, 0x32, 0xf8, 0xae, 0x1f, 0xd7, 0xfc, 0xf3, 0xf7, 0x87, 0xe7, 0xab, + 0x34, 0x05, 0xbc, 0x6b, 0x4d, 0x89, 0x0a, 0x2a, 0xef, 0xf1, 0x2e, 0xf7, + 0x97, 0x83, 0xbd, 0xa0, 0xb7, 0xe7, 0xfa, 0xd4, 0x7d, 0xb0, 0x25, 0xb6, + 0xb1, 0xda, 0x0a, 0xf3, 0x18, 0xfb, 0xe4, 0x99, 0xc7, 0xaa, 0x8f, 0xa3, + 0x3d, 0xcf, 0x7a, 0x44, 0x69, 0x89, 0x58, 0xcf, 0x2f, 0xb3, 0x2e, 0x41, + 0x3f, 0x03, 0xbd, 0xaa, 0x38, 0x2c, 0xff, 0x2f, 0x85, 0xf6, 0x29, 0x52, + 0x7f, 0x86, 0xf5, 0xfd, 0x05, 0x2a, 0xc0, 0xc6, 0xa7, 0x70, 0xd2, 0x22, + 0x68, 0x5a, 0x68, 0xf6, 0x81, 0x57, 0x6d, 0xbb, 0x83, 0x7c, 0x07, 0xff, + 0xc7, 0x0b, 0xe6, 0x77, 0x03, 0x27, 0xb6, 0x99, 0x9a, 0x2a, 0x52, 0x15, + 0x3f, 0xe8, 0x8d, 0xa1, 0x67, 0x6d, 0x49, 0x9f, 0x28, 0x03, 0x37, 0xe8, + 0x3d, 0xd9, 0x7b, 0x58, 0x9f, 0x31, 0xc7, 0xa5, 0xa1, 0xb6, 0x9d, 0x2d, + 0x38, 0x2c, 0xa7, 0x2e, 0x9c, 0xdb, 0xc6, 0x49, 0x46, 0x1f, 0xef, 0xa3, + 0x40, 0xe7, 0xdb, 0x3a, 0xc3, 0xfa, 0xa7, 0x5b, 0xeb, 0xd4, 0x41, 0xd9, + 0x0c, 0x7c, 0xd9, 0xbc, 0x08, 0xf9, 0xa5, 0xe1, 0x53, 0x64, 0x7a, 0xba, + 0x99, 0xa4, 0x63, 0x4d, 0xc6, 0xaf, 0x08, 0xbb, 0x83, 0x6f, 0x9b, 0x1f, + 0x85, 0x9d, 0x8d, 0x0b, 0x23, 0xb0, 0x89, 0x47, 0x17, 0x19, 0x27, 0x8f, + 0xd8, 0x2e, 0x8b, 0xcb, 0x65, 0x61, 0xd4, 0x2d, 0x09, 0xe3, 0xcb, 0x6c, + 0x27, 0x6c, 0x23, 0xba, 0xfa, 0x38, 0x31, 0x0d, 0x98, 0xe3, 0xfe, 0x22, + 0xc1, 0xb6, 0x5a, 0x3b, 0x17, 0x07, 0x1e, 0xdb, 0x80, 0x4f, 0x37, 0x6c, + 0x0f, 0xfa, 0x65, 0xe8, 0x13, 0xac, 0x33, 0xc5, 0x8c, 0xa1, 0xfd, 0x25, + 0x7d, 0x9c, 0x0f, 0x23, 0x1b, 0x7c, 0x18, 0x00, 0x4f, 0x3e, 0xcc, 0x87, + 0xfa, 0xc7, 0xf9, 0x60, 0x55, 0xc1, 0x87, 0x3a, 0xfc, 0x50, 0xdd, 0x65, + 0x9a, 0x3d, 0x12, 0xf7, 0x10, 0xb4, 0x93, 0xf6, 0x8a, 0x26, 0xeb, 0x28, + 0xdb, 0x49, 0x46, 0x9b, 0xc6, 0x0e, 0x4b, 0x4e, 0xb7, 0x6f, 0x1b, 0xa3, + 0x3e, 0x2f, 0x7e, 0x17, 0xbd, 0x4c, 0xdf, 0x1d, 0x9a, 0xc7, 0x17, 0xd9, + 0xdf, 0x40, 0xcf, 0x33, 0x86, 0x7a, 0x88, 0xee, 0xd0, 0xbd, 0xef, 0x0e, + 0xdd, 0x38, 0xa7, 0xed, 0x83, 0x98, 0xe6, 0xb6, 0x3f, 0x66, 0x5d, 0x79, + 0xc3, 0x93, 0x0c, 0x03, 0x32, 0x60, 0x7d, 0x61, 0x1c, 0x74, 0xf5, 0xcb, + 0xa0, 0xa7, 0x02, 0xbf, 0xc0, 0xb6, 0x54, 0xf6, 0xe7, 0x75, 0x50, 0xb9, + 0x27, 0x98, 0x3f, 0xd5, 0xf4, 0xfe, 0x4b, 0x34, 0x3f, 0xf0, 0xec, 0xbc, + 0x11, 0xda, 0xb8, 0x42, 0x7f, 0xb2, 0xa8, 0x97, 0x35, 0xa1, 0x9b, 0xaa, + 0xf7, 0xc3, 0xaf, 0x34, 0xd9, 0x3e, 0x76, 0xde, 0xc3, 0x97, 0xa5, 0x43, + 0x5f, 0xf6, 0x3e, 0x78, 0xcf, 0xb1, 0xe7, 0xe8, 0x07, 0xeb, 0x49, 0x7e, + 0x66, 0xd4, 0x09, 0x2a, 0x71, 0xbc, 0xd9, 0x21, 0xfa, 0xfe, 0xbb, 0x8f, + 0x63, 0x41, 0x55, 0x36, 0xe3, 0x54, 0xed, 0xa1, 0xaa, 0x64, 0xb2, 0x1d, + 0xb1, 0x6d, 0xb4, 0xf1, 0xde, 0x1e, 0xc6, 0xdd, 0x41, 0x89, 0x0c, 0x1e, + 0x47, 0x8c, 0x68, 0x32, 0x0d, 0xef, 0x87, 0xf2, 0x60, 0x7f, 0x4a, 0xb1, + 0x40, 0xdf, 0xf6, 0xc3, 0x5f, 0x32, 0x3f, 0x37, 0xeb, 0x0a, 0xfb, 0x51, + 0xd2, 0x44, 0x83, 0xfd, 0x28, 0xa9, 0x92, 0x79, 0x50, 0xb0, 0x16, 0xbf, + 0x26, 0x58, 0xe0, 0x9b, 0x05, 0xbe, 0x59, 0xe0, 0x9b, 0x0d, 0xbe, 0x15, + 0x5c, 0xc6, 0x85, 0xf1, 0x08, 0xf6, 0x2f, 0x06, 0xfb, 0x03, 0xc7, 0x9d, + 0x54, 0xf1, 0xed, 0x9b, 0x69, 0x85, 0x3f, 0xf6, 0x7d, 0xc1, 0xa8, 0x10, + 0xf8, 0x02, 0xde, 0x6f, 0x1c, 0xeb, 0x1f, 0x47, 0x8c, 0xb3, 0x44, 0xd1, + 0xb8, 0xc3, 0x8f, 0xfa, 0x26, 0x7e, 0x4c, 0x3b, 0xcc, 0x1f, 0x9e, 0xcf, + 0x76, 0xec, 0x40, 0xe6, 0x6d, 0x9e, 0xec, 0x07, 0x0e, 0x9d, 0x4c, 0x77, + 0x48, 0x07, 0xef, 0xdf, 0x1b, 0xee, 0x7f, 0x00, 0x7b, 0xb2, 0xdd, 0xde, + 0xed, 0x5c, 0x3e, 0x93, 0xe3, 0xe8, 0x27, 0xd1, 0x83, 0x3c, 0x02, 0x7e, + 0x66, 0x0d, 0x76, 0x76, 0x53, 0x4a, 0xd1, 0xeb, 0xbb, 0x6f, 0x20, 0xb7, + 0xa0, 0xea, 0x03, 0xa6, 0xa7, 0xc9, 0xe6, 0xfb, 0x5e, 0x3d, 0x0f, 0xdf, + 0x69, 0xea, 0x29, 0x5b, 0x1a, 0xa4, 0x37, 0xdc, 0x2c, 0xfd, 0x9d, 0x6b, + 0xd0, 0xdf, 0xba, 0x1a, 0xbd, 0xea, 0xa6, 0xe9, 0x6f, 0xdc, 0x14, 0xfd, + 0xb5, 0xdb, 0xce, 0x43, 0x92, 0xac, 0x47, 0x89, 0xa2, 0x7b, 0xb7, 0x5c, + 0x08, 0x3a, 0x8e, 0xbd, 0xec, 0xbc, 0x5c, 0x96, 0x4d, 0x3f, 0x3f, 0x98, + 0x98, 0x6e, 0x90, 0xb2, 0xd3, 0xa0, 0xed, 0xf7, 0x23, 0xef, 0x49, 0x9a, + 0xb4, 0xe3, 0x3e, 0x3c, 0x7b, 0x4d, 0xb2, 0x7a, 0xcc, 0x53, 0x9e, 0x68, + 0xb0, 0x1e, 0x75, 0x0f, 0x4f, 0xe5, 0xe3, 0x8c, 0xfb, 0xc4, 0x34, 0xfc, + 0x91, 0x8d, 0xb3, 0xaa, 0xd0, 0xc5, 0xaa, 0x7b, 0xe8, 0xfe, 0x20, 0x17, + 0x7a, 0x2f, 0xcc, 0x89, 0x38, 0xaf, 0x5a, 0x7f, 0x6a, 0xc2, 0x60, 0x3f, + 0x2b, 0x6c, 0xf2, 0xb3, 0x24, 0x14, 0x41, 0x53, 0x1d, 0xb8, 0x16, 0x41, + 0xe7, 0x57, 0x5d, 0x45, 0x28, 0x9c, 0xef, 0xa5, 0xe9, 0x45, 0x8e, 0x55, + 0x3c, 0x4f, 0x09, 0x73, 0x19, 0x7e, 0xef, 0xc0, 0x3b, 0x21, 0x7e, 0x14, + 0xb6, 0x53, 0x42, 0x7f, 0x73, 0x82, 0x9c, 0x30, 0x17, 0x89, 0xd1, 0x05, + 0x5f, 0x77, 0xb8, 0xdf, 0x2a, 0xfd, 0xb0, 0xff, 0x4e, 0xff, 0xf9, 0x8d, + 0xfe, 0x72, 0xe9, 0xeb, 0x1b, 0xfd, 0xef, 0xa8, 0x01, 0x4e, 0xc3, 0xc2, + 0xe3, 0xee, 0xf3, 0x61, 0xdf, 0x6d, 0xf0, 0xd3, 0xf3, 0xea, 0x88, 0x27, + 0x35, 0xe3, 0x36, 0x72, 0x1f, 0xf6, 0x29, 0x5b, 0xf1, 0x21, 0x1f, 0xf2, + 0x1f, 0xaa, 0x2d, 0xb1, 0x9c, 0x14, 0x0a, 0xf6, 0xe4, 0xf1, 0x4e, 0xf8, + 0x92, 0xdb, 0x68, 0x73, 0xec, 0x6a, 0xfb, 0x31, 0x9e, 0xc3, 0xeb, 0x6f, + 0xdd, 0x43, 0x96, 0x2a, 0x64, 0xb9, 0x35, 0x79, 0xd5, 0x1a, 0xa7, 0x42, + 0x9f, 0xd0, 0x3d, 0x6c, 0x43, 0x2e, 0x12, 0xe4, 0x52, 0x83, 0x5c, 0x0a, + 0xf7, 0x94, 0x0b, 0xce, 0xd8, 0xd0, 0x29, 0xc6, 0xa3, 0x2b, 0x3c, 0x9b, + 0x14, 0xd9, 0xac, 0x96, 0xea, 0xc6, 0xa7, 0x28, 0x66, 0x30, 0x1e, 0x06, + 0xf0, 0x38, 0x8a, 0xb5, 0x1c, 0xc3, 0x48, 0x89, 0x99, 0x2c, 0xcf, 0xdc, + 0x13, 0xb6, 0x71, 0xab, 0xb4, 0xe0, 0xdc, 0x2a, 0x5d, 0x34, 0xf8, 0xfd, + 0xf6, 0x64, 0x90, 0x37, 0x77, 0x3f, 0x89, 0xbc, 0x19, 0xeb, 0xd9, 0x1f, + 0x72, 0xff, 0x30, 0xe6, 0x71, 0x7c, 0xa0, 0x43, 0x35, 0xfc, 0xea, 0xfe, + 0xdc, 0x6b, 0x4f, 0xf0, 0xdc, 0x4e, 0x53, 0x9e, 0xfc, 0x35, 0x9e, 0x1d, + 0xa6, 0xf6, 0xe4, 0x4f, 0x0d, 0xde, 0x77, 0x78, 0xf2, 0xa2, 0xbf, 0x07, + 0x62, 0xa6, 0xbf, 0x36, 0xfb, 0x24, 0xaf, 0x7d, 0x0e, 0x3e, 0xf6, 0x0c, + 0xe2, 0xcb, 0x69, 0x47, 0x3b, 0x54, 0xc1, 0x6f, 0x8a, 0x71, 0x6a, 0xf2, + 0xb8, 0x85, 0x71, 0x19, 0xb1, 0x90, 0xdb, 0x0a, 0x1d, 0xc3, 0xbc, 0xa7, + 0x31, 0xef, 0xa8, 0x33, 0x8e, 0xbc, 0xbd, 0x4d, 0xd7, 0xbf, 0xc5, 0x0b, + 0xf3, 0xec, 0xcf, 0x91, 0xed, 0xaf, 0xfc, 0x7b, 0xdc, 0x86, 0x5f, 0x16, + 0x57, 0x6e, 0xc6, 0x0b, 0xa0, 0x5b, 0x5a, 0xf9, 0x45, 0xbc, 0x08, 0x3d, + 0x13, 0x0d, 0x09, 0x7e, 0xf9, 0x33, 0x54, 0x53, 0x3d, 0x7a, 0x19, 0xf1, + 0xab, 0x96, 0x85, 0xbf, 0x82, 0x34, 0x45, 0x03, 0x7e, 0x4c, 0x25, 0xa5, + 0xcb, 0x3c, 0xa9, 0x52, 0x57, 0x3e, 0x6e, 0x23, 0xde, 0xd4, 0x54, 0x09, + 0xfd, 0xfd, 0x78, 0x6e, 0xee, 0xff, 0x65, 0x1c, 0x7e, 0x0b, 0x3e, 0x82, + 0x14, 0x3b, 0xdf, 0x8d, 0xfd, 0xbf, 0x8d, 0x7e, 0x4c, 0xc8, 0x6c, 0xf4, + 0x3f, 0x1b, 0xf4, 0xdf, 0x02, 0x2e, 0xbc, 0x8e, 0xe3, 0x27, 0x29, 0x53, + 0x79, 0x15, 0x38, 0xf0, 0xdc, 0xa4, 0x3f, 0xb7, 0x38, 0xcf, 0x3c, 0xa8, + 0x96, 0x16, 0x8c, 0x34, 0x15, 0xe6, 0x92, 0x34, 0x3a, 0xa7, 0xd2, 0xd8, + 0x9c, 0x3e, 0xd1, 0x62, 0xfb, 0x01, 0xcd, 0x84, 0x1c, 0x41, 0x5c, 0x21, + 0x50, 0xac, 0xa7, 0x9e, 0xa6, 0xbe, 0xd4, 0x31, 0xfa, 0x6f, 0x0f, 0xb1, + 0x08, 0x71, 0xa8, 0x9b, 0x64, 0x7f, 0x9f, 0x54, 0xfb, 0x4c, 0x96, 0xd1, + 0x87, 0xce, 0x2d, 0xce, 0xdf, 0x6b, 0x5f, 0x28, 0xf1, 0x4a, 0xea, 0x23, + 0xfb, 0xbe, 0x1b, 0xee, 0xab, 0x62, 0xdf, 0x34, 0xf6, 0x64, 0x1a, 0xf5, + 0xf8, 0xc8, 0x79, 0xb2, 0x3a, 0x81, 0x5f, 0x31, 0x83, 0x98, 0x8f, 0x7d, + 0xce, 0xcc, 0xb1, 0xde, 0xd3, 0x4e, 0xfc, 0x06, 0x63, 0x94, 0xc9, 0x2e, + 0x23, 0x27, 0x18, 0xf1, 0xf7, 0x08, 0xf2, 0x05, 0x71, 0x65, 0x10, 0xf9, + 0xda, 0x3b, 0xc0, 0x87, 0xe3, 0x18, 0xd3, 0x2c, 0x83, 0xde, 0x41, 0xe4, + 0x09, 0x9c, 0xe3, 0x7b, 0xa7, 0xec, 0x1c, 0xda, 0xcb, 0x5a, 0xbc, 0x00, + 0xdb, 0x16, 0x4d, 0x7a, 0x50, 0xf2, 0x7d, 0x2c, 0xcb, 0x65, 0x10, 0x72, + 0x62, 0xbc, 0x73, 0x90, 0x13, 0xf3, 0x68, 0x38, 0x5e, 0x6c, 0x32, 0x8f, + 0x08, 0xf8, 0x68, 0xb0, 0x27, 0xd9, 0xcf, 0xf3, 0xc5, 0x15, 0x0b, 0xf3, + 0x7e, 0xac, 0x72, 0x2e, 0x66, 0x1b, 0xdc, 0x86, 0xed, 0xac, 0x8c, 0x63, + 0x2e, 0xb7, 0x1f, 0xc6, 0xbe, 0x7d, 0xb9, 0x1a, 0x75, 0xe4, 0x9e, 0x86, + 0xdd, 0x8a, 0xf9, 0x01, 0xc4, 0x68, 0x01, 0xb9, 0xa0, 0xe7, 0x75, 0xe4, + 0xbf, 0x00, 0x7a, 0x98, 0x0e, 0xe8, 0xf5, 0x2c, 0xf3, 0x95, 0xfe, 0x40, + 0xe4, 0x5c, 0x2d, 0xdf, 0xce, 0x6b, 0x38, 0x9e, 0xf3, 0xf9, 0x88, 0x23, + 0x8d, 0x3d, 0x88, 0xa5, 0xfe, 0xd9, 0xd0, 0xb1, 0x71, 0x2a, 0x34, 0x3e, + 0x8b, 0x9c, 0x93, 0x6d, 0x67, 0x9b, 0x60, 0x9f, 0x67, 0x1a, 0x09, 0xb1, + 0x66, 0x8d, 0x2a, 0x0d, 0x39, 0x6c, 0xbf, 0x8a, 0xb6, 0x12, 0xb6, 0xd7, + 0xd1, 0xee, 0x0e, 0xdb, 0xd7, 0xd0, 0x56, 0xc3, 0xf6, 0xcf, 0xd0, 0x4e, + 0x86, 0xed, 0x9f, 0xa3, 0x9d, 0x0a, 0xdb, 0x37, 0xd1, 0x4e, 0x87, 0xed, + 0x5b, 0x68, 0x6b, 0x61, 0xfb, 0x3d, 0xb4, 0x13, 0xb0, 0x73, 0x03, 0xef, + 0x37, 0x50, 0x2b, 0x66, 0xf1, 0xfc, 0x57, 0xe0, 0x36, 0x08, 0xde, 0x64, + 0xc1, 0x8f, 0x5e, 0x8c, 0xe5, 0xd0, 0x87, 0x1c, 0xb1, 0x91, 0xc7, 0xd3, + 0xc1, 0x18, 0x95, 0x61, 0x7b, 0x18, 0x1f, 0x2f, 0x16, 0x1a, 0x26, 0x9e, + 0x6c, 0x0f, 0xba, 0x4a, 0xc2, 0x65, 0xd8, 0xb9, 0xef, 0x63, 0x72, 0xb6, + 0x34, 0x09, 0xdb, 0x9e, 0xa0, 0x7f, 0x74, 0xf7, 0xd3, 0x6b, 0xee, 0x38, + 0xe2, 0x46, 0x11, 0x71, 0xc3, 0x42, 0xdc, 0x30, 0x11, 0x37, 0x86, 0x11, + 0x37, 0xf2, 0x88, 0x1b, 0x39, 0xc4, 0x0d, 0xa2, 0x33, 0x7e, 0x8c, 0x4a, + 0x2a, 0xa8, 0x51, 0x15, 0xcb, 0x2d, 0x82, 0xbf, 0x13, 0x90, 0xcd, 0x24, + 0x78, 0x7d, 0x38, 0x3e, 0xd2, 0xcc, 0xc3, 0x9f, 0x69, 0xf0, 0x11, 0x69, + 0xf8, 0xf2, 0x1c, 0x6a, 0x13, 0xa2, 0x2b, 0xb3, 0x1a, 0xfc, 0x8f, 0x47, + 0x45, 0xc4, 0xfe, 0x69, 0x15, 0xb8, 0x19, 0xbb, 0x7c, 0x9b, 0x91, 0xcc, + 0x2f, 0xf6, 0x50, 0xd7, 0x20, 0xe8, 0x39, 0x8b, 0xbe, 0x14, 0xf6, 0x63, + 0xbe, 0xde, 0x2a, 0xd9, 0x86, 0x46, 0x0b, 0x6e, 0x1c, 0xfe, 0x9f, 0xdf, + 0xe3, 0xcc, 0xe3, 0x43, 0x4f, 0x19, 0x4c, 0x03, 0xea, 0x3c, 0x23, 0xad, + 0x14, 0x1c, 0x81, 0x24, 0x93, 0x9f, 0xed, 0x1c, 0xe2, 0xcf, 0x90, 0x43, + 0x74, 0x41, 0x06, 0x55, 0xc4, 0x05, 0x9d, 0xf3, 0x0b, 0xe8, 0xf2, 0x27, + 0xcd, 0xff, 0x1e, 0xe6, 0xef, 0xc5, 0xd9, 0x3c, 0x8f, 0xcf, 0x39, 0x85, + 0xfa, 0xc1, 0xea, 0x91, 0x68, 0x3d, 0x25, 0xa1, 0x9e, 0x28, 0xd0, 0x59, + 0x2a, 0x00, 0x9f, 0x82, 0xdb, 0xbe, 0x07, 0xb0, 0x0e, 0x05, 0xfe, 0x6c, + 0xe2, 0xd0, 0xb7, 0x0d, 0x0b, 0xeb, 0x18, 0x3f, 0xd6, 0x5b, 0xe0, 0xbe, + 0xb1, 0xe7, 0x05, 0xec, 0xf9, 0x4f, 0x49, 0xea, 0x9a, 0x0c, 0xfc, 0x91, + 0x5f, 0xf3, 0xca, 0xc2, 0x48, 0xf3, 0x2c, 0xf8, 0xd3, 0x87, 0x1a, 0x05, + 0x7e, 0xa4, 0xd4, 0x02, 0x9f, 0xda, 0xf3, 0x5f, 0xc1, 0x7c, 0x7e, 0xf7, + 0xef, 0x0e, 0x4a, 0xd2, 0xea, 0x12, 0xe6, 0x69, 0xac, 0x3f, 0x25, 0xb9, + 0xff, 0x86, 0xf7, 0xa2, 0x91, 0xa7, 0x5d, 0xab, 0xbc, 0x2e, 0x4b, 0x7d, + 0xab, 0x37, 0xbc, 0x9a, 0xa3, 0xd1, 0x62, 0x93, 0xc0, 0xab, 0xf8, 0x6d, + 0x8b, 0xf4, 0x35, 0x12, 0xf5, 0x59, 0x0b, 0x7a, 0x5a, 0x1c, 0x12, 0xc9, + 0x1e, 0xea, 0x84, 0x8f, 0x32, 0x68, 0x09, 0x7c, 0xdf, 0x35, 0x63, 0xd1, + 0x13, 0x43, 0xed, 0x7c, 0x10, 0x51, 0x0f, 0xb8, 0xee, 0x5a, 0xd5, 0x30, + 0x87, 0x73, 0x71, 0xa6, 0x45, 0x03, 0x2f, 0x85, 0x60, 0x8d, 0x1f, 0xb3, + 0xb8, 0x8e, 0x05, 0xdf, 0xdc, 0xb5, 0xd2, 0xd5, 0x19, 0xd4, 0x1a, 0x90, + 0xf3, 0xae, 0x19, 0xae, 0x85, 0xb6, 0x81, 0x2f, 0x31, 0xd8, 0x06, 0xe7, + 0xf1, 0x08, 0xf4, 0xf0, 0x87, 0x27, 0xe0, 0xf1, 0x6b, 0xcd, 0x13, 0xd0, + 0xfb, 0x2e, 0x2a, 0xcb, 0x3e, 0x11, 0x9f, 0xc0, 0xe3, 0xff, 0xe4, 0xbc, + 0x0e, 0xf3, 0xbf, 0x4b, 0xc5, 0xd9, 0x2e, 0xec, 0xb5, 0x9b, 0xa6, 0x93, + 0x8c, 0x9b, 0x3e, 0x8c, 0x41, 0x2d, 0x06, 0x7e, 0xc6, 0xcd, 0x8f, 0xe6, + 0x7d, 0x6b, 0xa5, 0x2b, 0x33, 0x6b, 0xa5, 0x6b, 0xa0, 0xbf, 0x6e, 0x70, + 0x8d, 0x0c, 0x5d, 0x6a, 0x70, 0x6d, 0xcf, 0x79, 0xd1, 0x18, 0x74, 0x64, + 0xbf, 0x5f, 0x33, 0xdb, 0x8b, 0x39, 0xea, 0x3b, 0x47, 0xaa, 0x68, 0x96, + 0x84, 0x31, 0xe4, 0x45, 0x23, 0xee, 0x49, 0x7f, 0xee, 0x99, 0x06, 0xd7, + 0x2b, 0x18, 0x5b, 0x61, 0x5d, 0x18, 0x03, 0x3e, 0x49, 0xba, 0xe8, 0xb2, + 0x4f, 0x0a, 0xec, 0x78, 0x0c, 0xfc, 0x5a, 0xf0, 0xe9, 0x4a, 0x71, 0x1c, + 0x47, 0xbe, 0xc1, 0xf2, 0xf9, 0x21, 0xc7, 0x41, 0xa1, 0xd3, 0x6c, 0xfb, + 0xdb, 0x89, 0x5e, 0xe6, 0x59, 0xa1, 0x01, 0xdf, 0x3f, 0x34, 0x11, 0xe6, + 0x1c, 0x7f, 0x8f, 0x39, 0x8c, 0x3b, 0xcd, 0x4a, 0x26, 0xce, 0xc8, 0x33, + 0xcf, 0x38, 0xa7, 0xe4, 0x7d, 0xc1, 0x5b, 0xf0, 0x7d, 0x53, 0x6e, 0xe9, + 0xc3, 0x74, 0x33, 0x46, 0x95, 0x59, 0xf0, 0x2e, 0x8f, 0x27, 0x9c, 0x6b, + 0x1d, 0x7c, 0x03, 0x2d, 0xd5, 0x20, 0x9f, 0x3d, 0xc1, 0x31, 0x0d, 0xfe, + 0x06, 0x36, 0xcd, 0x31, 0x6b, 0xe3, 0xde, 0xc9, 0xf7, 0x25, 0x32, 0x19, + 0x41, 0xce, 0x2a, 0xe2, 0x2c, 0x3b, 0xcf, 0x7e, 0x10, 0xf8, 0xb8, 0xdf, + 0xa5, 0xfa, 0x2c, 0xd3, 0x05, 0x1b, 0x4f, 0xb2, 0x2e, 0xfe, 0x7f, 0xf9, + 0x38, 0xba, 0x45, 0x3e, 0x8e, 0x6e, 0x99, 0x8f, 0x12, 0xf8, 0x58, 0xd9, + 0xe0, 0xa3, 0x82, 0x3d, 0xf8, 0x3e, 0xe1, 0xab, 0x64, 0x4d, 0x3c, 0x02, + 0x3f, 0x0c, 0xff, 0xd1, 0x3c, 0x05, 0x9f, 0x70, 0x52, 0xb8, 0xda, 0xf0, + 0x68, 0x1c, 0xb5, 0xb2, 0x74, 0xff, 0x66, 0xfa, 0x33, 0xa0, 0xff, 0xcf, + 0x31, 0x5e, 0xa5, 0x6b, 0xb3, 0x94, 0x56, 0xa8, 0x7d, 0x2e, 0xed, 0x92, + 0xe9, 0x3b, 0x74, 0x75, 0xb6, 0x8b, 0xae, 0xcf, 0x66, 0xc0, 0xeb, 0x2c, + 0xc5, 0x7a, 0x32, 0xc3, 0x15, 0x18, 0xf1, 0xcf, 0x5a, 0xba, 0xc5, 0xba, + 0xf8, 0xfb, 0xf3, 0x82, 0xf9, 0x70, 0xd0, 0xe7, 0xc3, 0xd8, 0x47, 0xf8, + 0x30, 0x7e, 0x4f, 0x3e, 0x1c, 0xfc, 0x18, 0x1f, 0xc6, 0x3f, 0xc6, 0x07, + 0xe6, 0x01, 0xf3, 0xe2, 0xd1, 0xde, 0xf0, 0xff, 0x1f, 0x7d, 0x82, 0x7d, + 0x7c, 0x09, 0x74, 0x22, 0xa7, 0xd8, 0x19, 0xe4, 0x50, 0x9c, 0x63, 0xd5, + 0x0c, 0xe6, 0x57, 0x60, 0xbf, 0x32, 0x72, 0xea, 0x23, 0xa1, 0xfd, 0x16, + 0x1c, 0xe8, 0x65, 0x23, 0xe6, 0xdb, 0xaf, 0x64, 0xe6, 0xe1, 0x03, 0xaa, + 0xa5, 0x96, 0xc3, 0xfe, 0x07, 0x6d, 0x87, 0x79, 0xda, 0x0b, 0x5a, 0x12, + 0x54, 0x99, 0x54, 0x10, 0x5f, 0x87, 0xa1, 0xb7, 0x71, 0xdf, 0x07, 0x4a, + 0x26, 0xeb, 0xe1, 0x7e, 0xcc, 0x3f, 0x1c, 0xe6, 0x45, 0x88, 0x73, 0x38, + 0xa3, 0xd6, 0x38, 0x0d, 0xfc, 0xf8, 0x9c, 0x6a, 0xa9, 0xec, 0xf0, 0x9a, + 0x34, 0x62, 0x21, 0x3f, 0x37, 0xeb, 0xb7, 0xaf, 0xef, 0xf7, 0xd2, 0x71, + 0xe8, 0x26, 0xeb, 0xb4, 0x82, 0xdc, 0x78, 0x02, 0xf1, 0xc5, 0xd7, 0xd3, + 0xec, 0x02, 0xb1, 0xdf, 0x7f, 0x06, 0x75, 0xd1, 0x61, 0xfc, 0x34, 0x1a, + 0x71, 0x03, 0x9b, 0x5a, 0xf2, 0xcf, 0xfc, 0xb0, 0x4f, 0xaa, 0x39, 0xeb, + 0xc8, 0xdf, 0x0d, 0xec, 0xcb, 0xe7, 0x56, 0xc1, 0x1b, 0x09, 0xe7, 0x72, + 0x5f, 0x37, 0xe2, 0x00, 0xf8, 0xe4, 0xfe, 0x07, 0xfa, 0x97, 0xe0, 0x1f, + 0x39, 0x2f, 0x68, 0xe3, 0x8e, 0x1c, 0xc2, 0xe1, 0x78, 0x9d, 0x07, 0xcd, + 0x9c, 0x63, 0x73, 0x2e, 0x81, 0xfc, 0x63, 0xe9, 0x4d, 0xf4, 0x0d, 0xd3, + 0xe9, 0xa1, 0x2c, 0xe4, 0xc3, 0x7d, 0x0f, 0x84, 0x7d, 0x3c, 0x8f, 0x94, + 0x07, 0x4d, 0xfd, 0x07, 0x55, 0xdf, 0xaf, 0x43, 0x0f, 0x51, 0xf7, 0xd5, + 0x96, 0x90, 0x63, 0x00, 0xa7, 0xca, 0x6a, 0x16, 0xb9, 0x3c, 0xdf, 0xab, + 0xe9, 0x97, 0x91, 0x07, 0x83, 0x27, 0x0a, 0xf5, 0x1a, 0xa5, 0xd0, 0x0f, + 0xe7, 0x40, 0x1f, 0xdf, 0x3d, 0xf5, 0x21, 0xf7, 0x91, 0xc0, 0x08, 0xd8, + 0xe9, 0xaa, 0x44, 0x7b, 0xe5, 0x01, 0xb5, 0x46, 0xff, 0x80, 0xb9, 0x32, + 0x95, 0x57, 0x39, 0x87, 0x90, 0xe9, 0xc8, 0x2a, 0xd1, 0x5b, 0x33, 0xec, + 0x97, 0x19, 0xd8, 0x2f, 0xb3, 0x7f, 0x7d, 0xd0, 0x1f, 0x7b, 0x6b, 0x06, + 0x35, 0xf8, 0xcc, 0x00, 0xc7, 0xb0, 0x75, 0x11, 0xbc, 0x44, 0xee, 0xc3, + 0xf9, 0xf9, 0x5d, 0xee, 0x98, 0xda, 0xf7, 0x4b, 0x0a, 0x55, 0x66, 0xf8, + 0x6e, 0x49, 0xc6, 0xf9, 0x5c, 0x5b, 0x6c, 0x03, 0x7e, 0x02, 0xa1, 0xee, + 0x12, 0x38, 0xa6, 0x09, 0xd0, 0xa1, 0x5d, 0x90, 0x3d, 0xf8, 0x1f, 0xb6, + 0xdb, 0xfa, 0xf4, 0x2f, 0xd0, 0x27, 0x9e, 0x27, 0x6f, 0xc2, 0x25, 0x33, + 0x6b, 0x8b, 0x1c, 0x1f, 0x3e, 0x0d, 0xdb, 0xb3, 0xe2, 0x63, 0xcd, 0x0e, + 0x6a, 0xf5, 0xb2, 0x3d, 0xb0, 0x5e, 0x5c, 0x66, 0x9d, 0xc0, 0x19, 0xd0, + 0xa1, 0x19, 0xae, 0xe7, 0x65, 0xcc, 0xbb, 0x2f, 0x9c, 0xc7, 0xfc, 0xfe, + 0x1e, 0x4d, 0x0f, 0xa9, 0x42, 0x59, 0x0d, 0xe2, 0x45, 0x6d, 0xa8, 0x03, + 0x63, 0x22, 0x1d, 0x7c, 0x38, 0x8f, 0xb5, 0x9c, 0x53, 0xc5, 0x85, 0xc0, + 0x6f, 0x71, 0x1f, 0xdf, 0xd7, 0xa9, 0x54, 0xbe, 0xd4, 0x4b, 0x95, 0x4b, + 0x0a, 0xf8, 0x02, 0x44, 0x17, 0x82, 0x7d, 0xd8, 0x17, 0x1c, 0x87, 0xdc, + 0xc4, 0x73, 0x0a, 0xc5, 0xce, 0x21, 0x87, 0xbc, 0xd0, 0x45, 0x1d, 0x17, + 0xfa, 0x49, 0xba, 0xa0, 0x73, 0x7e, 0xa8, 0x9d, 0x81, 0x0c, 0x8f, 0x50, + 0x9e, 0x9e, 0x73, 0x07, 0x39, 0xc7, 0xc3, 0x39, 0x5c, 0xe7, 0x25, 0x49, + 0x42, 0xf2, 0x2f, 0xbe, 0x68, 0xd1, 0x8b, 0x43, 0xc0, 0x2b, 0x8f, 0xf6, + 0x8f, 0x91, 0xc7, 0xbb, 0x23, 0xf7, 0x71, 0xcc, 0x96, 0xcd, 0x3e, 0xc8, + 0x16, 0x74, 0xe5, 0x1e, 0xf2, 0xef, 0x44, 0x5f, 0x1c, 0x62, 0x7a, 0x34, + 0xd0, 0x52, 0x87, 0xae, 0xf3, 0x3d, 0x57, 0x17, 0xd9, 0x32, 0xeb, 0x32, + 0xf2, 0xaa, 0x0b, 0x75, 0x9a, 0x6a, 0xe8, 0x90, 0x59, 0x1f, 0xf4, 0x02, + 0x32, 0x4b, 0x73, 0x3f, 0xef, 0x2d, 0x84, 0xfb, 0xde, 0xd1, 0xf7, 0x17, + 0xef, 0xad, 0xef, 0x3e, 0xd4, 0x9b, 0x8f, 0xc0, 0x67, 0xa3, 0x2e, 0x32, + 0xe0, 0xd3, 0x55, 0xe4, 0x72, 0x06, 0xbf, 0x07, 0x77, 0x95, 0x15, 0xe4, + 0x85, 0xfc, 0x5e, 0x6b, 0xdd, 0xcd, 0x77, 0x07, 0xf6, 0x7d, 0x06, 0x3c, + 0xba, 0x32, 0xf7, 0x00, 0x5d, 0x9d, 0x53, 0xe8, 0x5a, 0x43, 0xcf, 0x16, + 0xa8, 0x83, 0xaa, 0xc9, 0x34, 0x5d, 0x5f, 0x6a, 0xe7, 0x93, 0x22, 0xf4, + 0xc4, 0x22, 0xce, 0xcd, 0xaf, 0x2c, 0x55, 0x4b, 0x37, 0x76, 0xa7, 0x49, + 0x7e, 0x09, 0xb6, 0xfd, 0x92, 0xae, 0xd5, 0xc0, 0xe7, 0xba, 0xe1, 0xa2, + 0x56, 0xe3, 0x3a, 0x32, 0x05, 0xbb, 0xd3, 0x53, 0x2d, 0xca, 0x90, 0xb4, + 0xa0, 0xd0, 0xaf, 0x66, 0x74, 0x8d, 0x75, 0xee, 0xa2, 0x81, 0x7e, 0x37, + 0x7e, 0x7b, 0x3d, 0xd0, 0x43, 0xf4, 0xf5, 0xa3, 0xbe, 0xd5, 0xb3, 0x9a, + 0xd8, 0x4d, 0x6f, 0x43, 0x27, 0xca, 0x7e, 0xdf, 0x47, 0xf7, 0xbc, 0x1e, + 0xee, 0x59, 0x2d, 0x5d, 0xe1, 0x3a, 0x68, 0x86, 0x75, 0xbe, 0x17, 0xfe, + 0x03, 0xef, 0x6e, 0x07, 0x95, 0x27, 0x11, 0xa3, 0x66, 0x1e, 0xa5, 0xc2, + 0x90, 0x18, 0xd0, 0xed, 0xf3, 0x82, 0xfb, 0xf8, 0x7e, 0xb2, 0x76, 0x1f, + 0xdb, 0xb2, 0xb8, 0x0a, 0xbd, 0x3a, 0xc8, 0x7a, 0x80, 0xdc, 0x0e, 0x39, + 0x04, 0xfb, 0x4e, 0x09, 0x39, 0x44, 0xc1, 0x0d, 0x74, 0xa3, 0x75, 0x30, + 0x49, 0xc7, 0x5e, 0x62, 0x19, 0x61, 0x6c, 0x43, 0xef, 0x36, 0xee, 0xc4, + 0x31, 0x66, 0xd0, 0xf1, 0xef, 0xb7, 0x73, 0x4a, 0xb6, 0xbd, 0x34, 0xe4, + 0xa1, 0xa3, 0xf6, 0xe8, 0x53, 0x2b, 0xbe, 0x4f, 0x81, 0x4e, 0xa4, 0x02, + 0x19, 0xd4, 0x30, 0x36, 0xed, 0x4e, 0xc2, 0x27, 0xc6, 0xe8, 0xe6, 0xa4, + 0x05, 0x9d, 0x68, 0x01, 0x87, 0xc3, 0x71, 0xbe, 0x4b, 0xb8, 0x39, 0x59, + 0xc4, 0xfb, 0x61, 0x3f, 0xf7, 0x97, 0xf6, 0x40, 0x97, 0xdc, 0x07, 0xc2, + 0xfc, 0x9c, 0xcf, 0xd3, 0x84, 0xda, 0xac, 0x2e, 0x4c, 0xcf, 0x7a, 0x34, + 0x9a, 0xeb, 0x4b, 0x5d, 0xa5, 0x4e, 0xff, 0xce, 0xd8, 0xf7, 0x9b, 0xfe, + 0x9c, 0x5d, 0x18, 0xff, 0x00, 0x3a, 0x85, 0x27, 0xe2, 0xf5, 0xe9, 0x66, + 0x35, 0xd5, 0x41, 0xac, 0x53, 0x24, 0x2c, 0x18, 0xec, 0x3b, 0x04, 0xba, + 0xea, 0xdf, 0x47, 0x13, 0x15, 0x9d, 0xd7, 0x99, 0x6e, 0x61, 0xb1, 0xc5, + 0x6b, 0x58, 0xce, 0xbc, 0x46, 0xa2, 0x9b, 0x49, 0xd8, 0xe5, 0x9e, 0x3d, + 0x7e, 0xbd, 0xf8, 0xf8, 0x10, 0xe3, 0xda, 0x0d, 0x99, 0x42, 0xbf, 0x50, + 0xdb, 0x94, 0x83, 0xbe, 0x59, 0xae, 0x4d, 0xa7, 0xf9, 0xde, 0x23, 0xef, + 0xeb, 0x5a, 0xa8, 0x1f, 0x1f, 0xd7, 0xb5, 0xe7, 0xb0, 0xf6, 0x2d, 0xf6, + 0xab, 0x90, 0x75, 0xe0, 0x23, 0xbe, 0x41, 0x6f, 0xcd, 0x55, 0xb3, 0xfc, + 0xcd, 0xa3, 0x35, 0x21, 0xa0, 0x16, 0x3f, 0x4e, 0x6f, 0xcf, 0x3d, 0x4b, + 0xbf, 0x9c, 0x65, 0xdd, 0x31, 0x68, 0x14, 0xfa, 0x74, 0x94, 0xe4, 0xec, + 0x69, 0x1a, 0x50, 0xaf, 0xfb, 0xb5, 0x8d, 0x9e, 0xf3, 0x6b, 0x3a, 0x33, + 0x4b, 0xc5, 0xc6, 0x40, 0xea, 0x1a, 0xfa, 0xca, 0x93, 0xba, 0xb6, 0x8e, + 0xdc, 0xa3, 0xd0, 0xfc, 0x80, 0xef, 0x6c, 0xb2, 0x35, 0xd8, 0xde, 0x22, + 0x6a, 0x9b, 0xb7, 0x9d, 0xbb, 0xe9, 0x2c, 0xd7, 0x56, 0x81, 0xff, 0x5e, + 0x33, 0x50, 0x63, 0xac, 0xaa, 0xa1, 0x0e, 0x31, 0x70, 0x9d, 0xc1, 0xf1, + 0x07, 0x4f, 0x37, 0x06, 0x9f, 0xb2, 0x1f, 0x7c, 0x67, 0xd9, 0x42, 0xfe, + 0xab, 0xfc, 0x8d, 0x0a, 0xf2, 0x5f, 0x5d, 0xfe, 0x40, 0xeb, 0x65, 0x3f, + 0x6b, 0x80, 0x96, 0x41, 0x3a, 0x33, 0xcf, 0xf2, 0x47, 0xec, 0xf5, 0xed, + 0x34, 0x0d, 0xfe, 0x72, 0x7c, 0x19, 0xa4, 0x5f, 0x2d, 0x15, 0xfd, 0xfb, + 0x6b, 0x1b, 0xb9, 0xd6, 0x11, 0x67, 0x12, 0xf5, 0xfa, 0x77, 0x40, 0x2f, + 0xce, 0x1e, 0xda, 0x8d, 0xa7, 0x0a, 0x9b, 0xdc, 0x72, 0x9e, 0x23, 0x07, + 0x79, 0xce, 0xde, 0x2d, 0xe6, 0x39, 0x7b, 0xb7, 0x92, 0xe7, 0xc8, 0x9d, + 0xe0, 0xab, 0xd6, 0xbb, 0x65, 0xdc, 0xa4, 0x00, 0xb7, 0x03, 0x5b, 0xc4, + 0xed, 0xc0, 0x56, 0x70, 0x93, 0x3a, 0xcd, 0xbf, 0x40, 0x8c, 0x35, 0x10, + 0xdb, 0xe0, 0xd7, 0x86, 0xfa, 0x59, 0x7f, 0x80, 0xa3, 0x8f, 0xeb, 0xef, + 0x8b, 0xa7, 0x18, 0xe0, 0xf9, 0xd8, 0x16, 0xf1, 0x7c, 0x6c, 0x2b, 0x78, + 0x8a, 0x9d, 0x26, 0xe3, 0x28, 0xc3, 0xd7, 0x70, 0x6d, 0x83, 0xd8, 0x3c, + 0x24, 0x87, 0xba, 0x2e, 0x87, 0x75, 0x0e, 0x03, 0x7c, 0x50, 0xaf, 0x46, + 0x4b, 0x4c, 0xcb, 0x46, 0xdf, 0x9d, 0x3a, 0x4b, 0x32, 0x5b, 0xa5, 0x4a, + 0x83, 0xef, 0x95, 0xfb, 0xb0, 0x0f, 0xf7, 0xf1, 0x37, 0x2a, 0x8b, 0x64, + 0xc4, 0xf7, 0xe7, 0x9a, 0x77, 0xa7, 0xf5, 0x2a, 0x68, 0x9d, 0x0a, 0x69, + 0xad, 0xf8, 0xb9, 0xe0, 0xbe, 0x4d, 0xb9, 0x60, 0x40, 0xe3, 0x08, 0x68, + 0x2c, 0x86, 0x34, 0x3e, 0xdd, 0x60, 0xda, 0xf6, 0xf9, 0xb4, 0x2d, 0x6d, + 0xa2, 0x6d, 0xe4, 0x9e, 0xf9, 0x1f, 0xe3, 0x81, 0x5a, 0x1a, 0xb9, 0xd7, + 0x6b, 0x4d, 0xd4, 0xd2, 0x4d, 0xd4, 0xd2, 0xd0, 0xf7, 0x57, 0x9b, 0xa8, + 0xa5, 0x9b, 0xa8, 0xa5, 0x61, 0x07, 0xaf, 0xc0, 0x56, 0x82, 0x3b, 0xdc, + 0x12, 0x71, 0x0d, 0xee, 0xd7, 0xe3, 0x14, 0xe4, 0x39, 0x05, 0xc4, 0xf0, + 0xa3, 0xc8, 0xf1, 0xd8, 0x6e, 0x4f, 0x13, 0xc7, 0x04, 0x3d, 0x87, 0x9a, + 0x2f, 0x5b, 0x25, 0x33, 0x5e, 0x9c, 0x1f, 0x50, 0x97, 0x02, 0xfb, 0xd6, + 0x5a, 0xc4, 0x71, 0x70, 0x20, 0x85, 0x08, 0xa9, 0xb2, 0x5f, 0xb0, 0x73, + 0x4c, 0xe7, 0x76, 0xf0, 0x10, 0xbe, 0xdb, 0x60, 0x1f, 0xc6, 0xbe, 0xb4, + 0x4e, 0x0b, 0x8d, 0xf0, 0x1b, 0x9a, 0xcc, 0xfd, 0xfc, 0xce, 0x31, 0xb7, + 0xcf, 0xf7, 0x69, 0x76, 0xb6, 0x0f, 0x71, 0x80, 0xfb, 0x15, 0xf8, 0x35, + 0xe8, 0xca, 0x52, 0x1b, 0x17, 0x19, 0xeb, 0x55, 0xaa, 0xcf, 0x07, 0x31, + 0x7c, 0xca, 0xe0, 0x38, 0x87, 0xf8, 0xbe, 0xc4, 0xdf, 0xb0, 0x10, 0xeb, + 0x97, 0xae, 0x68, 0x32, 0x6a, 0xc7, 0x3a, 0x7f, 0xa3, 0x1d, 0xec, 0xc3, + 0xf9, 0x1d, 0xfe, 0x1d, 0xed, 0x51, 0xff, 0xae, 0xcd, 0xa0, 0x23, 0xad, + 0x80, 0x16, 0xdb, 0xc8, 0xd0, 0xc8, 0x2c, 0xdf, 0x35, 0x51, 0x8f, 0x68, + 0xca, 0x54, 0x75, 0xf8, 0x7e, 0x68, 0xe3, 0xbb, 0x49, 0x76, 0x91, 0xeb, + 0x4f, 0x23, 0xb8, 0xff, 0x3c, 0xed, 0xbc, 0xc9, 0xf7, 0x9f, 0xe1, 0x3a, + 0x8d, 0xde, 0x70, 0x33, 0x34, 0x8e, 0xf8, 0x5a, 0x6c, 0x68, 0xf0, 0x6f, + 0xbe, 0x3c, 0x39, 0xa7, 0xad, 0xc6, 0x42, 0x99, 0x8e, 0x84, 0x32, 0xad, + 0x34, 0xd6, 0x80, 0xdf, 0x0d, 0xef, 0x8f, 0x43, 0x99, 0xee, 0x3a, 0x47, + 0xda, 0xd5, 0x1c, 0xcb, 0x95, 0x65, 0x19, 0xc8, 0x75, 0x7c, 0xb1, 0x24, + 0x14, 0x21, 0xd3, 0x51, 0x5f, 0xa6, 0x32, 0xc7, 0x05, 0xec, 0x95, 0x83, + 0xfc, 0xd9, 0x8f, 0xe1, 0xe9, 0xb0, 0x8c, 0xb9, 0xde, 0xe0, 0x58, 0x98, + 0xa4, 0x4b, 0x9b, 0xe4, 0x5c, 0xbc, 0xa7, 0x0e, 0xe7, 0xa9, 0xff, 0x9c, + 0x16, 0xde, 0x9b, 0x66, 0x21, 0xc7, 0x76, 0x2e, 0xf6, 0x23, 0x81, 0x8c, + 0xf6, 0x9d, 0x6e, 0xbb, 0xef, 0xe5, 0x4d, 0x7d, 0xed, 0x67, 0x9b, 0x56, + 0xc4, 0xb7, 0x0d, 0xde, 0xf3, 0x1d, 0xe4, 0x9d, 0x7e, 0xc9, 0x1f, 0x53, + 0x31, 0xd6, 0x4b, 0x85, 0x25, 0x83, 0xac, 0x16, 0xcf, 0x91, 0x49, 0x34, + 0xda, 0x72, 0xea, 0xa4, 0xf5, 0x30, 0xc6, 0x2d, 0x34, 0x3c, 0xef, 0xa7, + 0xd0, 0x9d, 0x8b, 0x5c, 0x77, 0x3b, 0xbf, 0xf1, 0xd6, 0x93, 0xc8, 0x21, + 0x37, 0xce, 0xfc, 0xe6, 0xfd, 0xd4, 0xa5, 0xab, 0x88, 0x09, 0x74, 0xc6, + 0x09, 0x51, 0x22, 0x1e, 0xe7, 0x3e, 0xfe, 0x06, 0xef, 0x79, 0x17, 0x8d, + 0x3b, 0x78, 0x75, 0x99, 0xc7, 0x69, 0xdf, 0x39, 0xf6, 0xff, 0x3f, 0xd0, + 0x2e, 0x1a, 0xd6, 0x9e, 0x38, 0xf2, 0xe7, 0xeb, 0xc4, 0xb1, 0x4f, 0x4e, + 0x14, 0x9b, 0xba, 0x7a, 0x09, 0x6b, 0x8b, 0x8e, 0xc2, 0xdf, 0xd6, 0xf9, + 0xfb, 0xa8, 0x76, 0x89, 0xda, 0xf7, 0x65, 0x90, 0xa7, 0xa3, 0xf2, 0x77, + 0x52, 0xb5, 0x8a, 0xd8, 0x52, 0x70, 0x92, 0x98, 0xaf, 0x62, 0x2e, 0xc7, + 0x05, 0x8f, 0x14, 0xd8, 0x50, 0xc1, 0x49, 0x27, 0xc6, 0x9a, 0x9e, 0xa7, + 0x7c, 0x5e, 0xa0, 0x87, 0x32, 0x29, 0x1a, 0x73, 0xf8, 0xfe, 0xf7, 0x9b, + 0xf4, 0x36, 0xec, 0xac, 0x78, 0x9e, 0x6b, 0x26, 0xf6, 0x29, 0x78, 0x77, + 0xf8, 0xbe, 0xea, 0x14, 0x3d, 0xb4, 0x47, 0xcf, 0x5e, 0x22, 0xe0, 0xb3, + 0x42, 0xfd, 0x48, 0x72, 0x53, 0xc7, 0xfd, 0xef, 0x6d, 0x8c, 0x6b, 0x9a, + 0x96, 0xc0, 0x1b, 0xa7, 0x99, 0xa4, 0x95, 0x66, 0x8a, 0x56, 0xa1, 0x1f, + 0xdb, 0xcc, 0x32, 0x7d, 0x03, 0x78, 0x2b, 0x66, 0x95, 0x94, 0x8c, 0xb5, + 0xaf, 0x0b, 0x78, 0x67, 0x05, 0x3d, 0x15, 0x17, 0x18, 0x77, 0x5d, 0x2d, + 0x03, 0x6f, 0xd6, 0xd1, 0x51, 0xa7, 0x9b, 0x8e, 0x61, 0xed, 0x7e, 0xe4, + 0x1f, 0xdf, 0x72, 0xa8, 0x2c, 0x99, 0x29, 0x3a, 0x80, 0xf3, 0x8e, 0x36, + 0x38, 0x57, 0x3b, 0x02, 0x5f, 0x23, 0xd0, 0xa3, 0x19, 0x8f, 0x1e, 0xdd, + 0xa3, 0x5b, 0x71, 0x01, 0x7b, 0xae, 0xb0, 0x9e, 0xa0, 0xdf, 0x09, 0xce, + 0x8d, 0xad, 0xf8, 0xba, 0x08, 0x7f, 0xfa, 0x0c, 0x65, 0xce, 0xad, 0xe5, + 0xa6, 0x90, 0x9f, 0x8f, 0x36, 0xe9, 0x8b, 0x31, 0x9c, 0xf7, 0x36, 0xf8, + 0x34, 0xea, 0xc8, 0x02, 0xf3, 0xe9, 0x58, 0xc0, 0x27, 0x8c, 0xf1, 0xb7, + 0x23, 0xce, 0xd1, 0xf8, 0xec, 0x13, 0x74, 0xb6, 0xc1, 0x77, 0xdd, 0x27, + 0xe8, 0x4a, 0xe3, 0x11, 0xba, 0x98, 0xe3, 0x5c, 0x07, 0xfb, 0xf8, 0x67, + 0xa0, 0xcf, 0x3f, 0xa3, 0x9b, 0x8e, 0xfb, 0x72, 0xfa, 0x3f, 0xc3, 0x06, + 0xd0, 0x70, 0x4c, 0x57, 0x00, 0x00, 0x00 }; static u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x0 }; static u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 }; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 55d2367..8171cae 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1199,8 +1199,7 @@ int bond_sethwaddr(struct net_device *bo } #define BOND_INTERSECT_FEATURES \ - (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\ - NETIF_F_TSO|NETIF_F_UFO) + (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO) /* * Compute the common dev->feature set available to all slaves. Some @@ -1218,9 +1217,7 @@ static int bond_compute_features(struct features &= (slave->dev->features & BOND_INTERSECT_FEATURES); if ((features & NETIF_F_SG) && - !(features & (NETIF_F_IP_CSUM | - NETIF_F_NO_CSUM | - NETIF_F_HW_CSUM))) + !(features & NETIF_F_ALL_CSUM)) features &= ~NETIF_F_SG; /* @@ -4191,7 +4188,7 @@ static int bond_init(struct net_device * */ bond_dev->features |= NETIF_F_VLAN_CHALLENGED; - /* don't acquire bond device's xmit_lock when + /* don't acquire bond device's netif_tx_lock when * transmitting */ bond_dev->features |= NETIF_F_LLTX; diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index ac48f75..565a54f 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2915,8 +2915,7 @@ static int cas_start_xmit(struct sk_buff */ static int ring; - skb = skb_padto(skb, cp->min_frame_size); - if (!skb) + if (skb_padto(skb, cp->min_frame_size)) return 0; /* XXX: we need some higher-level QoS hooks to steer packets to @@ -4877,7 +4876,7 @@ static int __devinit cas_init_one(struct const struct pci_device_id *ent) { static int cas_version_printed = 0; - unsigned long casreg_base, casreg_len; + unsigned long casreg_len; struct net_device *dev; struct cas *cp; int i, err, pci_using_dac; @@ -4972,7 +4971,6 @@ #endif pci_using_dac = 0; } - casreg_base = pci_resource_start(pdev, 0); casreg_len = pci_resource_len(pdev, 0); cp = netdev_priv(dev); @@ -5024,7 +5022,7 @@ #endif cp->timer_ticks = 0; /* give us access to cassini registers */ - cp->regs = ioremap(casreg_base, casreg_len); + cp->regs = pci_iomap(pdev, 0, casreg_len); if (cp->regs == 0UL) { printk(KERN_ERR PFX "Cannot map device registers, " "aborting.\n"); @@ -5123,7 +5121,7 @@ err_out_iounmap: cas_shutdown(cp); mutex_unlock(&cp->pm_mutex); - iounmap(cp->regs); + pci_iounmap(pdev, cp->regs); err_out_free_res: @@ -5171,7 +5169,7 @@ #if 1 #endif pci_free_consistent(pdev, sizeof(struct cas_init_block), cp->init_block, cp->block_dvma); - iounmap(cp->regs); + pci_iounmap(pdev, cp->regs); free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 4391bf4..53efff6 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -1418,7 +1418,7 @@ int t1_start_xmit(struct sk_buff *skb, s struct cpl_tx_pkt *cpl; #ifdef NETIF_F_TSO - if (skb_shinfo(skb)->tso_size) { + if (skb_shinfo(skb)->gso_size) { int eth_type; struct cpl_tx_pkt_lso *hdr; @@ -1433,7 +1433,7 @@ #ifdef NETIF_F_TSO hdr->ip_hdr_words = skb->nh.iph->ihl; hdr->tcp_hdr_words = skb->h.th->doff; hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type, - skb_shinfo(skb)->tso_size)); + skb_shinfo(skb)->gso_size)); hdr->len = htonl(skb->len - sizeof(*hdr)); cpl = (struct cpl_tx_pkt *)hdr; sge->stats.tx_lso_pkts++; diff --git a/drivers/net/declance.c b/drivers/net/declance.c index f130bda..d3d958e 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -885,8 +885,7 @@ static int lance_start_xmit(struct sk_bu len = skblen; if (len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; len = ETH_ZLEN; } diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 0941d40..e946c43 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -938,11 +938,8 @@ static int depca_start_xmit(struct sk_bu if (skb->len < 1) goto out; - if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - goto out; - } + if (skb_padto(skb, ETH_ZLEN)) + goto out; netif_stop_queue(dev); diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 31ac001..f37170c 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2780,6 +2780,80 @@ #endif DPRINTK(PROBE,ERR, "Error enabling wake\n"); } +/* ------------------ PCI Error Recovery infrastructure -------------- */ +/** + * e100_io_error_detected - called when PCI error is detected. + * @pdev: Pointer to PCI device + * @state: The current pci conneection state + */ +static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + + /* Similar to calling e100_down(), but avoids adpater I/O. */ + netdev->stop(netdev); + + /* Detach; put netif into state similar to hotplug unplug. */ + netif_poll_enable(netdev); + netif_device_detach(netdev); + + /* Request a slot reset. */ + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * e100_io_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch. + */ +static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct nic *nic = netdev_priv(netdev); + + if (pci_enable_device(pdev)) { + printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + pci_set_master(pdev); + + /* Only one device per card can do a reset */ + if (0 != PCI_FUNC(pdev->devfn)) + return PCI_ERS_RESULT_RECOVERED; + e100_hw_reset(nic); + e100_phy_init(nic); + + return PCI_ERS_RESULT_RECOVERED; +} + +/** + * e100_io_resume - resume normal operations + * @pdev: Pointer to PCI device + * + * Resume normal operations after an error recovery + * sequence has been completed. + */ +static void e100_io_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct nic *nic = netdev_priv(netdev); + + /* ack any pending wake events, disable PME */ + pci_enable_wake(pdev, 0, 0); + + netif_device_attach(netdev); + if (netif_running(netdev)) { + e100_open(netdev); + mod_timer(&nic->watchdog, jiffies); + } +} + +static struct pci_error_handlers e100_err_handler = { + .error_detected = e100_io_error_detected, + .slot_reset = e100_io_slot_reset, + .resume = e100_io_resume, +}; static struct pci_driver e100_driver = { .name = DRV_NAME, @@ -2791,6 +2865,7 @@ #ifdef CONFIG_PM .resume = e100_resume, #endif .shutdown = e100_shutdown, + .err_handler = &e100_err_handler, }; static int __init e100_init_module(void) diff --git a/drivers/net/e1000/Makefile b/drivers/net/e1000/Makefile index ca9f895..5dea2b7 100644 --- a/drivers/net/e1000/Makefile +++ b/drivers/net/e1000/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # -# Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. +# Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -22,6 +22,7 @@ # file called LICENSE. # # Contact Information: # Linux NICS +# e1000-devel Mailing List # Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 # ################################################################################ diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 281de41..2bc34fb 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -22,6 +22,7 @@ Contact Information: Linux NICS + e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ @@ -114,6 +115,8 @@ #define E1000_MAX_82544_RXD /* Supported Rx Buffer Sizes */ #define E1000_RXBUFFER_128 128 /* Used for packet split */ #define E1000_RXBUFFER_256 256 /* Used for packet split */ +#define E1000_RXBUFFER_512 512 +#define E1000_RXBUFFER_1024 1024 #define E1000_RXBUFFER_2048 2048 #define E1000_RXBUFFER_4096 4096 #define E1000_RXBUFFER_8192 8192 @@ -334,7 +337,6 @@ #ifdef CONFIG_PCI_MSI boolean_t have_msi; #endif /* to not mess up cache alignment, always add to the bottom */ - boolean_t txb2b; #ifdef NETIF_F_TSO boolean_t tso_force; #endif diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index d1c705b..6ed7f59 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -22,6 +22,7 @@ Contact Information: Linux NICS + e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ @@ -864,8 +865,8 @@ static int e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) { struct net_device *netdev = adapter->netdev; - uint32_t mask, i=0, shared_int = TRUE; - uint32_t irq = adapter->pdev->irq; + uint32_t mask, i=0, shared_int = TRUE; + uint32_t irq = adapter->pdev->irq; *data = 0; @@ -891,22 +892,22 @@ e1000_intr_test(struct e1000_adapter *ad /* Interrupt to test */ mask = 1 << i; - if (!shared_int) { - /* Disable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - E1000_WRITE_REG(&adapter->hw, IMC, mask); - E1000_WRITE_REG(&adapter->hw, ICS, mask); - msec_delay(10); - - if (adapter->test_icr & mask) { - *data = 3; - break; - } + if (!shared_int) { + /* Disable the interrupt to be reported in + * the cause register and then force the same + * interrupt and see if one gets posted. If + * an interrupt was posted to the bus, the + * test failed. + */ + adapter->test_icr = 0; + E1000_WRITE_REG(&adapter->hw, IMC, mask); + E1000_WRITE_REG(&adapter->hw, ICS, mask); + msec_delay(10); + + if (adapter->test_icr & mask) { + *data = 3; + break; + } } /* Enable the interrupt to be reported in @@ -925,7 +926,7 @@ e1000_intr_test(struct e1000_adapter *ad break; } - if (!shared_int) { + if (!shared_int) { /* Disable the other interrupts to be reported in * the cause register and then force the other * interrupts and see if any get posted. If diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 523c2c9..3959039 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -22,6 +22,7 @@ Contact Information: Linux NICS + e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ @@ -764,7 +765,7 @@ e1000_init_hw(struct e1000_hw *hw) } if (hw->mac_type == e1000_82573) { - e1000_enable_tx_pkt_filtering(hw); + e1000_enable_tx_pkt_filtering(hw); } switch (hw->mac_type) { @@ -860,7 +861,7 @@ e1000_adjust_serdes_amplitude(struct e10 if(eeprom_data != EEPROM_RESERVED_WORD) { /* Adjust SERDES output amplitude only. */ - eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; + eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data); if(ret_val) return ret_val; @@ -1227,7 +1228,7 @@ e1000_copper_link_igp_setup(struct e1000 if (hw->phy_reset_disable) return E1000_SUCCESS; - + ret_val = e1000_phy_reset(hw); if (ret_val) { DEBUGOUT("Error Resetting the PHY\n"); @@ -1369,7 +1370,7 @@ e1000_copper_link_ggp_setup(struct e1000 DEBUGFUNC("e1000_copper_link_ggp_setup"); if(!hw->phy_reset_disable) { - + /* Enable CRS on TX for half-duplex operation. */ ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); @@ -1518,7 +1519,7 @@ e1000_copper_link_mgp_setup(struct e1000 if(hw->phy_reset_disable) return E1000_SUCCESS; - + /* Enable CRS on TX. This must be set for half-duplex operation. */ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if(ret_val) @@ -1664,7 +1665,7 @@ e1000_copper_link_autoneg(struct e1000_h * collision distance in the Transmit Control Register. * 2) Set up flow control on the MAC to that established with * the link partner. -* 3) Config DSP to improve Gigabit link quality for some PHY revisions. +* 3) Config DSP to improve Gigabit link quality for some PHY revisions. * * hw - Struct containing variables accessed by shared code ******************************************************************************/ @@ -1673,7 +1674,7 @@ e1000_copper_link_postconfig(struct e100 { int32_t ret_val; DEBUGFUNC("e1000_copper_link_postconfig"); - + if(hw->mac_type >= e1000_82544) { e1000_config_collision_dist(hw); } else { @@ -1697,7 +1698,7 @@ e1000_copper_link_postconfig(struct e100 return ret_val; } } - + return E1000_SUCCESS; } @@ -1753,11 +1754,11 @@ e1000_setup_copper_link(struct e1000_hw } if(hw->autoneg) { - /* Setup autoneg and flow control advertisement - * and perform autonegotiation */ + /* Setup autoneg and flow control advertisement + * and perform autonegotiation */ ret_val = e1000_copper_link_autoneg(hw); if(ret_val) - return ret_val; + return ret_val; } else { /* PHY will be set to 10H, 10F, 100H,or 100F * depending on value from forced_speed_duplex. */ @@ -1785,7 +1786,7 @@ e1000_setup_copper_link(struct e1000_hw ret_val = e1000_copper_link_postconfig(hw); if(ret_val) return ret_val; - + DEBUGOUT("Valid link established!!!\n"); return E1000_SUCCESS; } @@ -1983,7 +1984,7 @@ e1000_phy_setup_autoneg(struct e1000_hw DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg); + ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg); if(ret_val) return ret_val; @@ -2272,7 +2273,7 @@ e1000_config_mac_to_phy(struct e1000_hw DEBUGFUNC("e1000_config_mac_to_phy"); - /* 82544 or newer MAC, Auto Speed Detection takes care of + /* 82544 or newer MAC, Auto Speed Detection takes care of * MAC speed/duplex configuration.*/ if (hw->mac_type >= e1000_82544) return E1000_SUCCESS; @@ -2291,9 +2292,9 @@ e1000_config_mac_to_phy(struct e1000_hw if(ret_val) return ret_val; - if(phy_data & M88E1000_PSSR_DPLX) + if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; - else + else ctrl &= ~E1000_CTRL_FD; e1000_config_collision_dist(hw); @@ -2492,10 +2493,10 @@ e1000_config_fc_after_link_up(struct e10 */ if(hw->original_fc == e1000_fc_full) { hw->fc = e1000_fc_full; - DEBUGOUT("Flow Control = FULL.\r\n"); + DEBUGOUT("Flow Control = FULL.\n"); } else { hw->fc = e1000_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } } /* For receiving PAUSE frames ONLY. @@ -2511,7 +2512,7 @@ e1000_config_fc_after_link_up(struct e10 (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc = e1000_fc_tx_pause; - DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n"); + DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); } /* For transmitting PAUSE frames ONLY. * @@ -2526,7 +2527,7 @@ e1000_config_fc_after_link_up(struct e10 !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc = e1000_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } /* Per the IEEE spec, at this point flow control should be * disabled. However, we want to consider that we could @@ -2552,10 +2553,10 @@ e1000_config_fc_after_link_up(struct e10 hw->original_fc == e1000_fc_tx_pause) || hw->fc_strict_ieee) { hw->fc = e1000_fc_none; - DEBUGOUT("Flow Control = NONE.\r\n"); + DEBUGOUT("Flow Control = NONE.\n"); } else { hw->fc = e1000_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } /* Now we need to do one last check... If we auto- @@ -2580,7 +2581,7 @@ e1000_config_fc_after_link_up(struct e10 return ret_val; } } else { - DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n"); + DEBUGOUT("Copper PHY and Auto Neg has not completed.\n"); } } return E1000_SUCCESS; @@ -2763,7 +2764,7 @@ e1000_check_for_link(struct e1000_hw *hw hw->autoneg_failed = 1; return 0; } - DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n"); + DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); /* Disable auto-negotiation in the TXCW register */ E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE)); @@ -2788,7 +2789,7 @@ e1000_check_for_link(struct e1000_hw *hw else if(((hw->media_type == e1000_media_type_fiber) || (hw->media_type == e1000_media_type_internal_serdes)) && (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n"); + DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); E1000_WRITE_REG(hw, TXCW, hw->txcw); E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU)); @@ -2851,13 +2852,13 @@ e1000_get_speed_and_duplex(struct e1000_ if(status & E1000_STATUS_FD) { *duplex = FULL_DUPLEX; - DEBUGOUT("Full Duplex\r\n"); + DEBUGOUT("Full Duplex\n"); } else { *duplex = HALF_DUPLEX; - DEBUGOUT(" Half Duplex\r\n"); + DEBUGOUT(" Half Duplex\n"); } } else { - DEBUGOUT("1000 Mbs, Full Duplex\r\n"); + DEBUGOUT("1000 Mbs, Full Duplex\n"); *speed = SPEED_1000; *duplex = FULL_DUPLEX; } @@ -2883,7 +2884,7 @@ e1000_get_speed_and_duplex(struct e1000_ } } - if ((hw->mac_type == e1000_80003es2lan) && + if ((hw->mac_type == e1000_80003es2lan) && (hw->media_type == e1000_media_type_copper)) { if (*speed == SPEED_1000) ret_val = e1000_configure_kmrn_for_1000(hw); @@ -3159,7 +3160,7 @@ e1000_read_phy_reg(struct e1000_hw *hw, if (e1000_swfw_sync_acquire(hw, swfw)) return -E1000_ERR_SWFW_SYNC; - if((hw->phy_type == e1000_phy_igp || + if((hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, @@ -3298,7 +3299,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, if (e1000_swfw_sync_acquire(hw, swfw)) return -E1000_ERR_SWFW_SYNC; - if((hw->phy_type == e1000_phy_igp || + if((hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, @@ -3496,22 +3497,22 @@ e1000_phy_hw_reset(struct e1000_hw *hw) } /* Read the device control register and assert the E1000_CTRL_PHY_RST * bit. Then, take it out of reset. - * For pre-e1000_82571 hardware, we delay for 10ms between the assert + * For pre-e1000_82571 hardware, we delay for 10ms between the assert * and deassert. For e1000_82571 hardware and later, we instead delay * for 50us between and 10ms after the deassertion. */ ctrl = E1000_READ_REG(hw, CTRL); E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST); E1000_WRITE_FLUSH(hw); - - if (hw->mac_type < e1000_82571) + + if (hw->mac_type < e1000_82571) msec_delay(10); else udelay(100); - + E1000_WRITE_REG(hw, CTRL, ctrl); E1000_WRITE_FLUSH(hw); - + if (hw->mac_type >= e1000_82571) msec_delay(10); e1000_swfw_sync_release(hw, swfw); @@ -3815,7 +3816,7 @@ e1000_phy_m88_get_info(struct e1000_hw * /* Check polarity status */ ret_val = e1000_check_polarity(hw, &polarity); if(ret_val) - return ret_val; + return ret_val; phy_info->cable_polarity = polarity; ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); @@ -4540,14 +4541,14 @@ e1000_read_eeprom_eerd(struct e1000_hw * E1000_WRITE_REG(hw, EERD, eerd); error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ); - + if(error) { break; } data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA); - + } - + return error; } @@ -4573,24 +4574,24 @@ e1000_write_eeprom_eewr(struct e1000_hw return -E1000_ERR_SWFW_SYNC; for (i = 0; i < words; i++) { - register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | - ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | + register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | + ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | E1000_EEPROM_RW_REG_START; error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE); if(error) { break; - } + } E1000_WRITE_REG(hw, EEWR, register_value); - + error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE); - + if(error) { break; - } + } } - + e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM); return error; } @@ -4610,7 +4611,7 @@ e1000_poll_eerd_eewr_done(struct e1000_h for(i = 0; i < attempts; i++) { if(eerd == E1000_EEPROM_POLL_READ) reg = E1000_READ_REG(hw, EERD); - else + else reg = E1000_READ_REG(hw, EEWR); if(reg & E1000_EEPROM_RW_REG_DONE) { @@ -5135,7 +5136,7 @@ e1000_mc_addr_list_update(struct e1000_h uint32_t i; uint32_t num_rar_entry; uint32_t num_mta_entry; - + DEBUGFUNC("e1000_mc_addr_list_update"); /* Set the new number of MC addresses that we are being requested to use. */ @@ -6240,7 +6241,7 @@ e1000_check_polarity(struct e1000_hw *hw * 1 - Downshift ocured. * * returns: - E1000_ERR_XXX - * E1000_SUCCESS + * E1000_SUCCESS * * For phy's older then IGP, this function reads the Downshift bit in the Phy * Specific Status register. For IGP phy's, it reads the Downgrade bit in the @@ -6255,7 +6256,7 @@ e1000_check_downshift(struct e1000_hw *h DEBUGFUNC("e1000_check_downshift"); - if(hw->phy_type == e1000_phy_igp || + if(hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2) { ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, &phy_data); @@ -6684,8 +6685,8 @@ e1000_set_d0_lplu_state(struct e1000_hw } else { - - phy_data |= IGP02E1000_PM_D0_LPLU; + + phy_data |= IGP02E1000_PM_D0_LPLU; ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); if (ret_val) return ret_val; @@ -6777,7 +6778,7 @@ int32_t e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer) { uint8_t i; - uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET; + uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET; uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH; length = (length >> 2); @@ -6796,7 +6797,7 @@ e1000_host_if_read_cookie(struct e1000_h * and also checks whether the previous command is completed. * It busy waits in case of previous command is not completed. * - * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or + * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or * timeout * - E1000_SUCCESS for success. ****************************************************************************/ @@ -6820,7 +6821,7 @@ e1000_mng_enable_host_if(struct e1000_hw msec_delay_irq(1); } - if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { + if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { DEBUGOUT("Previous command timeout failed .\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 150e45e..467c9ed 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -22,6 +22,7 @@ Contact Information: Linux NICS + e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ @@ -374,7 +375,7 @@ struct e1000_host_mng_dhcp_cookie{ }; #endif -int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer, +int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer, uint16_t length); boolean_t e1000_check_mng_mode(struct e1000_hw *hw); boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw); @@ -1801,7 +1802,7 @@ #define E1000_RCTL_FLXBUF_SHIFT 27 * value2 = [0..64512], default=4096 * value3 = [0..64512], default=0 */ - + #define E1000_PSRCTL_BSIZE0_MASK 0x0000007F #define E1000_PSRCTL_BSIZE1_MASK 0x00003F00 #define E1000_PSRCTL_BSIZE2_MASK 0x003F0000 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 97e71a4..32b7d44 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -22,51 +22,13 @@ Contact Information: Linux NICS + e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "e1000.h" -/* Change Log - * 7.0.33 3-Feb-2006 - * o Added another fix for the pass false carrier bit - * 7.0.32 24-Jan-2006 - * o Need to rebuild with noew version number for the pass false carrier - * fix in e1000_hw.c - * 7.0.30 18-Jan-2006 - * o fixup for tso workaround to disable it for pci-x - * o fix mem leak on 82542 - * o fixes for 10 Mb/s connections and incorrect stats - * 7.0.28 01/06/2006 - * o hardware workaround to only set "speed mode" bit for 1G link. - * 7.0.26 12/23/2005 - * o wake on lan support modified for device ID 10B5 - * o fix dhcp + vlan issue not making it to the iAMT firmware - * 7.0.24 12/9/2005 - * o New hardware support for the Gigabit NIC embedded in the south bridge - * o Fixes to the recycling logic (skb->tail) from IBM LTC - * 6.3.9 12/16/2005 - * o incorporate fix for recycled skbs from IBM LTC - * 6.3.7 11/18/2005 - * o Honor eeprom setting for enabling/disabling Wake On Lan - * 6.3.5 11/17/2005 - * o Fix memory leak in rx ring handling for PCI Express adapters - * 6.3.4 11/8/05 - * o Patch from Jesper Juhl to remove redundant NULL checks for kfree - * 6.3.2 9/20/05 - * o Render logic that sets/resets DRV_LOAD as inline functions to - * avoid code replication. If f/w is AMT then set DRV_LOAD only when - * network interface is open. - * o Handle DRV_LOAD set/reset in cases where AMT uses VLANs. - * o Adjust PBA partioning for Jumbo frames using MTU size and not - * rx_buffer_len - * 6.3.1 9/19/05 - * o Use adapter->tx_timeout_factor in Tx Hung Detect logic - * (e1000_clean_tx_irq) - * o Support for 8086:10B5 device (Quad Port) - */ - char e1000_driver_name[] = "e1000"; static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #ifndef CONFIG_E1000_NAPI @@ -74,9 +36,9 @@ #define DRIVERNAPI #else #define DRIVERNAPI "-NAPI" #endif -#define DRV_VERSION "7.0.33-k2"DRIVERNAPI +#define DRV_VERSION "7.0.38-k4"DRIVERNAPI char e1000_driver_version[] = DRV_VERSION; -static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; +static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table * @@ -208,8 +170,8 @@ static void e1000_leave_82542_rst(struct static void e1000_tx_timeout(struct net_device *dev); static void e1000_reset_task(struct net_device *dev); static void e1000_smartspeed(struct e1000_adapter *adapter); -static inline int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, - struct sk_buff *skb); +static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, + struct sk_buff *skb); static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); @@ -227,6 +189,16 @@ #ifdef CONFIG_NET_POLL_CONTROLLER static void e1000_netpoll (struct net_device *netdev); #endif +static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state); +static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev); +static void e1000_io_resume(struct pci_dev *pdev); + +static struct pci_error_handlers e1000_err_handler = { + .error_detected = e1000_io_error_detected, + .slot_reset = e1000_io_slot_reset, + .resume = e1000_io_resume, +}; static struct pci_driver e1000_driver = { .name = e1000_driver_name, @@ -238,7 +210,8 @@ #ifdef CONFIG_PM .suspend = e1000_suspend, .resume = e1000_resume, #endif - .shutdown = e1000_shutdown + .shutdown = e1000_shutdown, + .err_handler = &e1000_err_handler }; MODULE_AUTHOR("Intel Corporation, "); @@ -293,7 +266,7 @@ module_exit(e1000_exit_module); * @adapter: board private structure **/ -static inline void +static void e1000_irq_disable(struct e1000_adapter *adapter) { atomic_inc(&adapter->irq_sem); @@ -307,7 +280,7 @@ e1000_irq_disable(struct e1000_adapter * * @adapter: board private structure **/ -static inline void +static void e1000_irq_enable(struct e1000_adapter *adapter) { if (likely(atomic_dec_and_test(&adapter->irq_sem))) { @@ -348,10 +321,10 @@ e1000_update_mng_vlan(struct e1000_adapt * For ASF and Pass Through versions of f/w this means that the * driver is no longer loaded. For AMT version (only with 82573) i * of the f/w this means that the netowrk i/f is closed. - * + * **/ -static inline void +static void e1000_release_hw_control(struct e1000_adapter *adapter) { uint32_t ctrl_ext; @@ -361,6 +334,7 @@ e1000_release_hw_control(struct e1000_ad switch (adapter->hw.mac_type) { case e1000_82571: case e1000_82572: + case e1000_80003es2lan: ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); @@ -379,13 +353,13 @@ e1000_release_hw_control(struct e1000_ad * @adapter: address of board private structure * * e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit. - * For ASF and Pass Through versions of f/w this means that - * the driver is loaded. For AMT version (only with 82573) + * For ASF and Pass Through versions of f/w this means that + * the driver is loaded. For AMT version (only with 82573) * of the f/w this means that the netowrk i/f is open. - * + * **/ -static inline void +static void e1000_get_hw_control(struct e1000_adapter *adapter) { uint32_t ctrl_ext; @@ -394,6 +368,7 @@ e1000_get_hw_control(struct e1000_adapte switch (adapter->hw.mac_type) { case e1000_82571: case e1000_82572: + case e1000_80003es2lan: ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); @@ -421,7 +396,7 @@ e1000_up(struct e1000_adapter *adapter) uint16_t mii_reg; e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); if (mii_reg & MII_CR_POWER_DOWN) - e1000_phy_reset(&adapter->hw); + e1000_phy_hw_reset(&adapter->hw); } e1000_set_multi(netdev); @@ -711,8 +686,8 @@ #endif DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); /* if ksp3, indicate if it's port a being setup */ - if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 && - e1000_ksp3_port_a == 0) + if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 && + e1000_ksp3_port_a == 0) adapter->ksp3_port_a = 1; e1000_ksp3_port_a++; /* Reset for multiple KP3 adapters */ @@ -740,9 +715,9 @@ #endif if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; - /* hard_start_xmit is safe against parallel locking */ - netdev->features |= NETIF_F_LLTX; - + /* hard_start_xmit is safe against parallel locking */ + netdev->features |= NETIF_F_LLTX; + adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw); /* before reading the EEPROM, reset the controller to @@ -972,8 +947,8 @@ #endif pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); - adapter->rx_buffer_len = E1000_RXBUFFER_2048; - adapter->rx_ps_bsize0 = E1000_RXBUFFER_256; + adapter->rx_buffer_len = MAXIMUM_ETHERNET_FRAME_SIZE; + adapter->rx_ps_bsize0 = E1000_RXBUFFER_128; hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; @@ -1181,7 +1156,7 @@ e1000_close(struct net_device *netdev) * @start: address of beginning of memory * @len: length of memory **/ -static inline boolean_t +static boolean_t e1000_check_64k_bound(struct e1000_adapter *adapter, void *start, unsigned long len) { @@ -1599,14 +1574,21 @@ #endif rctl |= E1000_RCTL_LPE; /* Setup buffer sizes */ - if (adapter->hw.mac_type >= e1000_82571) { - /* We can now specify buffers in 1K increments. - * BSIZE and BSEX are ignored in this case. */ - rctl |= adapter->rx_buffer_len << 0x11; - } else { - rctl &= ~E1000_RCTL_SZ_4096; - rctl |= E1000_RCTL_BSEX; - switch (adapter->rx_buffer_len) { + rctl &= ~E1000_RCTL_SZ_4096; + rctl |= E1000_RCTL_BSEX; + switch (adapter->rx_buffer_len) { + case E1000_RXBUFFER_256: + rctl |= E1000_RCTL_SZ_256; + rctl &= ~E1000_RCTL_BSEX; + break; + case E1000_RXBUFFER_512: + rctl |= E1000_RCTL_SZ_512; + rctl &= ~E1000_RCTL_BSEX; + break; + case E1000_RXBUFFER_1024: + rctl |= E1000_RCTL_SZ_1024; + rctl &= ~E1000_RCTL_BSEX; + break; case E1000_RXBUFFER_2048: default: rctl |= E1000_RCTL_SZ_2048; @@ -1621,7 +1603,6 @@ #endif case E1000_RXBUFFER_16384: rctl |= E1000_RCTL_SZ_16384; break; - } } #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT @@ -1715,7 +1696,7 @@ e1000_configure_rx(struct e1000_adapter if (hw->mac_type >= e1000_82571) { ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); /* Reset delay timers after every interrupt */ - ctrl_ext |= E1000_CTRL_EXT_CANC; + ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR; #ifdef CONFIG_E1000_NAPI /* Auto-Mask interrupts upon ICR read. */ ctrl_ext |= E1000_CTRL_EXT_IAME; @@ -1807,7 +1788,7 @@ e1000_free_all_tx_resources(struct e1000 e1000_free_tx_resources(adapter, &adapter->tx_ring[i]); } -static inline void +static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info) { @@ -2247,6 +2228,7 @@ e1000_watchdog_task(struct e1000_adapter if (link) { if (!netif_carrier_ok(netdev)) { + boolean_t txb2b = 1; e1000_get_speed_and_duplex(&adapter->hw, &adapter->link_speed, &adapter->link_duplex); @@ -2260,23 +2242,22 @@ e1000_watchdog_task(struct e1000_adapter * and adjust the timeout factor */ netdev->tx_queue_len = adapter->tx_queue_len; adapter->tx_timeout_factor = 1; - adapter->txb2b = 1; switch (adapter->link_speed) { case SPEED_10: - adapter->txb2b = 0; + txb2b = 0; netdev->tx_queue_len = 10; adapter->tx_timeout_factor = 8; break; case SPEED_100: - adapter->txb2b = 0; + txb2b = 0; netdev->tx_queue_len = 100; /* maybe add some timeout factor ? */ break; } - if ((adapter->hw.mac_type == e1000_82571 || + if ((adapter->hw.mac_type == e1000_82571 || adapter->hw.mac_type == e1000_82572) && - adapter->txb2b == 0) { + txb2b == 0) { #define SPEED_MODE_BIT (1 << 21) uint32_t tarc0; tarc0 = E1000_READ_REG(&adapter->hw, TARC0); @@ -2400,7 +2381,7 @@ #define E1000_TX_FLAGS_IPV4 0x00000008 #define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 #define E1000_TX_FLAGS_VLAN_SHIFT 16 -static inline int +static int e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, struct sk_buff *skb) { @@ -2413,7 +2394,7 @@ #ifdef NETIF_F_TSO uint8_t ipcss, ipcso, tucss, tucso, hdr_len; int err; - if (skb_shinfo(skb)->tso_size) { + if (skb_shinfo(skb)->gso_size) { if (skb_header_cloned(skb)) { err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); if (err) @@ -2421,8 +2402,8 @@ #ifdef NETIF_F_TSO } hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); - mss = skb_shinfo(skb)->tso_size; - if (skb->protocol == ntohs(ETH_P_IP)) { + mss = skb_shinfo(skb)->gso_size; + if (skb->protocol == htons(ETH_P_IP)) { skb->nh.iph->tot_len = 0; skb->nh.iph->check = 0; skb->h.th->check = @@ -2480,7 +2461,7 @@ #endif return FALSE; } -static inline boolean_t +static boolean_t e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, struct sk_buff *skb) { @@ -2516,7 +2497,7 @@ e1000_tx_csum(struct e1000_adapter *adap #define E1000_MAX_TXD_PWR 12 #define E1000_MAX_DATA_PER_TXD (1<data_len && tx_ring->last_tx_tso && - !skb_shinfo(skb)->tso_size) { + !skb_shinfo(skb)->gso_size) { tx_ring->last_tx_tso = 0; size -= 4; } @@ -2625,7 +2606,7 @@ #endif return count; } -static inline void +static void e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, int tx_flags, int count) { @@ -2689,7 +2670,7 @@ e1000_tx_queue(struct e1000_adapter *ada #define E1000_FIFO_HDR 0x10 #define E1000_82547_PAD_LEN 0x3E0 -static inline int +static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb) { uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; @@ -2716,7 +2697,7 @@ no_fifo_stall_required: } #define MINIMUM_DHCP_PACKET_SIZE 282 -static inline int +static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb) { struct e1000_hw *hw = &adapter->hw; @@ -2764,7 +2745,7 @@ e1000_xmit_frame(struct sk_buff *skb, st unsigned int nr_frags = 0; unsigned int mss = 0; int count = 0; - int tso; + int tso; unsigned int f; len -= skb->data_len; @@ -2776,8 +2757,8 @@ e1000_xmit_frame(struct sk_buff *skb, st } #ifdef NETIF_F_TSO - mss = skb_shinfo(skb)->tso_size; - /* The controller does a simple calculation to + mss = skb_shinfo(skb)->gso_size; + /* The controller does a simple calculation to * make sure there is enough room in the FIFO before * initiating the DMA for each buffer. The calc is: * 4 = ceil(buffer len/mss). To make sure we don't @@ -2800,7 +2781,7 @@ #ifdef NETIF_F_TSO case e1000_82573: pull_size = min((unsigned int)4, skb->data_len); if (!__pskb_pull_tail(skb, pull_size)) { - printk(KERN_ERR + printk(KERN_ERR "__pskb_pull_tail failed.\n"); dev_kfree_skb_any(skb); return NETDEV_TX_OK; @@ -2826,7 +2807,7 @@ #endif #ifdef NETIF_F_TSO /* Controller Erratum workaround */ if (!skb->data_len && tx_ring->last_tx_tso && - !skb_shinfo(skb)->tso_size) + !skb_shinfo(skb)->gso_size) count++; #endif @@ -2901,7 +2882,7 @@ #endif /* Old method was to assume IPv4 packet by default if TSO was enabled. * 82571 hardware supports TSO capabilities for IPv6 as well... * no longer assume, we must. */ - if (likely(skb->protocol == ntohs(ETH_P_IP))) + if (likely(skb->protocol == htons(ETH_P_IP))) tx_flags |= E1000_TX_FLAGS_IPV4; e1000_tx_queue(adapter, tx_ring, tx_flags, @@ -2982,8 +2963,7 @@ e1000_change_mtu(struct net_device *netd /* Adapter-specific max frame size limits. */ switch (adapter->hw.mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: + case e1000_undefined ... e1000_82542_rev2_1: if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) { DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n"); return -EINVAL; @@ -3017,27 +2997,32 @@ #define MAX_STD_JUMBO_FRAME_SIZE 9234 break; } - - if (adapter->hw.mac_type > e1000_82547_rev_2) { - adapter->rx_buffer_len = max_frame; - E1000_ROUNDUP(adapter->rx_buffer_len, 1024); - } else { - if(unlikely((adapter->hw.mac_type < e1000_82543) && - (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) { - DPRINTK(PROBE, ERR, "Jumbo Frames not supported " - "on 82542\n"); - return -EINVAL; - } else { - if(max_frame <= E1000_RXBUFFER_2048) - adapter->rx_buffer_len = E1000_RXBUFFER_2048; - else if(max_frame <= E1000_RXBUFFER_4096) - adapter->rx_buffer_len = E1000_RXBUFFER_4096; - else if(max_frame <= E1000_RXBUFFER_8192) - adapter->rx_buffer_len = E1000_RXBUFFER_8192; - else if(max_frame <= E1000_RXBUFFER_16384) - adapter->rx_buffer_len = E1000_RXBUFFER_16384; - } - } + /* NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN + * means we reserve 2 more, this pushes us to allocate from the next + * larger slab size + * i.e. RXBUFFER_2048 --> size-4096 slab */ + + if (max_frame <= E1000_RXBUFFER_256) + adapter->rx_buffer_len = E1000_RXBUFFER_256; + else if (max_frame <= E1000_RXBUFFER_512) + adapter->rx_buffer_len = E1000_RXBUFFER_512; + else if (max_frame <= E1000_RXBUFFER_1024) + adapter->rx_buffer_len = E1000_RXBUFFER_1024; + else if (max_frame <= E1000_RXBUFFER_2048) + adapter->rx_buffer_len = E1000_RXBUFFER_2048; + else if (max_frame <= E1000_RXBUFFER_4096) + adapter->rx_buffer_len = E1000_RXBUFFER_4096; + else if (max_frame <= E1000_RXBUFFER_8192) + adapter->rx_buffer_len = E1000_RXBUFFER_8192; + else if (max_frame <= E1000_RXBUFFER_16384) + adapter->rx_buffer_len = E1000_RXBUFFER_16384; + + /* adjust allocation if LPE protects us, and we aren't using SBP */ +#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 + if (!adapter->hw.tbi_compatibility_on && + ((max_frame == MAXIMUM_ETHERNET_FRAME_SIZE) || + (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE))) + adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; netdev->mtu = new_mtu; @@ -3060,11 +3045,21 @@ void e1000_update_stats(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; + struct pci_dev *pdev = adapter->pdev; unsigned long flags; uint16_t phy_tmp; #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF + /* + * Prevent stats update while adapter is being reset, or if the pci + * connection is down. + */ + if (adapter->link_speed == 0) + return; + if (pdev->error_state && pdev->error_state != pci_channel_io_normal) + return; + spin_lock_irqsave(&adapter->stats_lock, flags); /* these counters are modified from e1000_adjust_tbi_stats, @@ -3165,7 +3160,6 @@ #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF adapter->stats.crcerrs + adapter->stats.algnerrc + adapter->stats.ruc + adapter->stats.roc + adapter->stats.cexterr; - adapter->net_stats.rx_dropped = 0; adapter->net_stats.rx_length_errors = adapter->stats.ruc + adapter->stats.roc; adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; @@ -3391,13 +3385,15 @@ #endif tx_ring->next_to_clean = i; - spin_lock(&tx_ring->tx_lock); - +#define TX_WAKE_THRESHOLD 32 if (unlikely(cleaned && netif_queue_stopped(netdev) && - netif_carrier_ok(netdev))) - netif_wake_queue(netdev); - - spin_unlock(&tx_ring->tx_lock); + netif_carrier_ok(netdev))) { + spin_lock(&tx_ring->tx_lock); + if (netif_queue_stopped(netdev) && + (E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) + netif_wake_queue(netdev); + spin_unlock(&tx_ring->tx_lock); + } if (adapter->detect_tx_hung) { /* Detect a transmit hang in hardware, this serializes the @@ -3445,7 +3441,7 @@ #endif * @sk_buff: socket buffer with received data **/ -static inline void +static void e1000_rx_checksum(struct e1000_adapter *adapter, uint32_t status_err, uint32_t csum, struct sk_buff *skb) @@ -3567,7 +3563,8 @@ #endif flags); length--; } else { - dev_kfree_skb_irq(skb); + /* recycle */ + buffer_info->skb = skb; goto next_desc; } } @@ -3675,6 +3672,7 @@ #endif i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC_PS(*rx_ring, i); staterr = le32_to_cpu(rx_desc->wb.middle.status_error); + buffer_info = &rx_ring->buffer_info[i]; while (staterr & E1000_RXD_STAT_DD) { buffer_info = &rx_ring->buffer_info[i]; @@ -3733,9 +3731,9 @@ #endif /* page alloc/put takes too long and effects small packet * throughput, so unsplit small packets and save the alloc/put*/ - if (l1 && ((length + l1) < E1000_CB_LENGTH)) { + if (l1 && ((length + l1) <= adapter->rx_ps_bsize0)) { u8 *vaddr; - /* there is no documentation about how to call + /* there is no documentation about how to call * kmap_atomic, so we can't hold the mapping * very long */ pci_dma_sync_single_for_cpu(pdev, @@ -4155,7 +4153,7 @@ e1000_mii_ioctl(struct net_device *netde spin_unlock_irqrestore(&adapter->stats_lock, flags); return -EIO; } - if (adapter->hw.phy_type == e1000_media_type_copper) { + if (adapter->hw.media_type == e1000_media_type_copper) { switch (data->reg_num) { case PHY_CTRL: if (mii_reg & MII_CR_POWER_DOWN) @@ -4514,21 +4512,13 @@ #endif E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN); E1000_WRITE_REG(&adapter->hw, WUFC, wufc); - retval = pci_enable_wake(pdev, PCI_D3hot, 1); - if (retval) - DPRINTK(PROBE, ERR, "Error enabling D3 wake\n"); - retval = pci_enable_wake(pdev, PCI_D3cold, 1); - if (retval) - DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n"); + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_enable_wake(pdev, PCI_D3cold, 1); } else { E1000_WRITE_REG(&adapter->hw, WUC, 0); E1000_WRITE_REG(&adapter->hw, WUFC, 0); - retval = pci_enable_wake(pdev, PCI_D3hot, 0); - if (retval) - DPRINTK(PROBE, ERR, "Error enabling D3 wake\n"); - retval = pci_enable_wake(pdev, PCI_D3cold, 0); - if (retval) - DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n"); + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); } if (adapter->hw.mac_type >= e1000_82540 && @@ -4537,13 +4527,8 @@ #endif if (manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; E1000_WRITE_REG(&adapter->hw, MANC, manc); - retval = pci_enable_wake(pdev, PCI_D3hot, 1); - if (retval) - DPRINTK(PROBE, ERR, "Error enabling D3 wake\n"); - retval = pci_enable_wake(pdev, PCI_D3cold, 1); - if (retval) - DPRINTK(PROBE, ERR, - "Error enabling D3 cold wake\n"); + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_enable_wake(pdev, PCI_D3cold, 1); } } @@ -4553,9 +4538,7 @@ #endif pci_disable_device(pdev); - retval = pci_set_power_state(pdev, pci_choose_state(pdev, state)); - if (retval) - DPRINTK(PROBE, ERR, "Error in setting power state\n"); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } @@ -4566,22 +4549,15 @@ e1000_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct e1000_adapter *adapter = netdev_priv(netdev); - int retval; uint32_t manc, ret_val; - retval = pci_set_power_state(pdev, PCI_D0); - if (retval) - DPRINTK(PROBE, ERR, "Error in setting power state\n"); + pci_set_power_state(pdev, PCI_D0); e1000_pci_restore_state(adapter); ret_val = pci_enable_device(pdev); pci_set_master(pdev); - retval = pci_enable_wake(pdev, PCI_D3hot, 0); - if (retval) - DPRINTK(PROBE, ERR, "Error enabling D3 wake\n"); - retval = pci_enable_wake(pdev, PCI_D3cold, 0); - if (retval) - DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n"); + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); e1000_reset(adapter); E1000_WRITE_REG(&adapter->hw, WUS, ~0); @@ -4635,4 +4611,101 @@ #endif } #endif +/** + * e1000_io_error_detected - called when PCI error is detected + * @pdev: Pointer to PCI device + * @state: The current pci conneection state + * + * This function is called after a PCI bus error affecting + * this device has been detected. + */ +static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev->priv; + + netif_device_detach(netdev); + + if (netif_running(netdev)) + e1000_down(adapter); + + /* Request a slot slot reset. */ + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * e1000_io_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. Implementation + * resembles the first-half of the e1000_resume routine. + */ +static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev->priv; + + if (pci_enable_device(pdev)) { + printk(KERN_ERR "e1000: Cannot re-enable PCI device after reset.\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + pci_set_master(pdev); + + pci_enable_wake(pdev, 3, 0); + pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */ + + /* Perform card reset only on one instance of the card */ + if (PCI_FUNC (pdev->devfn) != 0) + return PCI_ERS_RESULT_RECOVERED; + + e1000_reset(adapter); + E1000_WRITE_REG(&adapter->hw, WUS, ~0); + + return PCI_ERS_RESULT_RECOVERED; +} + +/** + * e1000_io_resume - called when traffic can start flowing again. + * @pdev: Pointer to PCI device + * + * This callback is called when the error recovery driver tells us that + * its OK to resume normal operation. Implementation resembles the + * second-half of the e1000_resume routine. + */ +static void e1000_io_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct e1000_adapter *adapter = netdev->priv; + uint32_t manc, swsm; + + if (netif_running(netdev)) { + if (e1000_up(adapter)) { + printk("e1000: can't bring device back up after reset\n"); + return; + } + } + + netif_device_attach(netdev); + + if (adapter->hw.mac_type >= e1000_82540 && + adapter->hw.media_type == e1000_media_type_copper) { + manc = E1000_READ_REG(&adapter->hw, MANC); + manc &= ~(E1000_MANC_ARP_EN); + E1000_WRITE_REG(&adapter->hw, MANC, manc); + } + + switch (adapter->hw.mac_type) { + case e1000_82573: + swsm = E1000_READ_REG(&adapter->hw, SWSM); + E1000_WRITE_REG(&adapter->hw, SWSM, + swsm | E1000_SWSM_DRV_LOAD); + break; + default: + break; + } + + if (netif_running(netdev)) + mod_timer(&adapter->watchdog_timer, jiffies); +} + /* e1000_main.c */ diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h index 9790db9..048d052 100644 --- a/drivers/net/e1000/e1000_osdep.h +++ b/drivers/net/e1000/e1000_osdep.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -22,6 +22,7 @@ Contact Information: Linux NICS + e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index e0a4d37..e55f896 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -22,6 +22,7 @@ Contact Information: Linux NICS + e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index a806dfe..e70f172 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -1154,8 +1154,7 @@ static int eepro_send_packet(struct sk_b printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name); if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index 82bd356..a74b207 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -677,8 +677,7 @@ #if NET_DEBUG > 6 #endif if (buf->len < ETH_ZLEN) { - buf = skb_padto(buf, ETH_ZLEN); - if (buf == NULL) + if (skb_padto(buf, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 2f7b868..724d7dc 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -21,15 +21,15 @@ http://www.scyld.com/network/epic100.html --------------------------------------------------------------------- - + Linux kernel-specific changes: - + LK1.1.2 (jgarzik): * Merge becker version 1.09 (4/08/2000) LK1.1.3: * Major bugfix to 1.09 driver (Francis Romieu) - + LK1.1.4 (jgarzik): * Merge becker test version 1.09 (5/29/2000) @@ -66,7 +66,7 @@ LK1.1.14 (Kryzsztof Halasa): * fix spurious bad initializations * pound phy a la SMSC's app note on the subject - + AC1.1.14ac * fix power up/down for ethtool that broke in 1.11 @@ -244,7 +244,7 @@ static struct pci_device_id epic_pci_tbl }; MODULE_DEVICE_TABLE (pci, epic_pci_tbl); - + #ifndef USE_IO_OPS #undef inb #undef inw @@ -370,7 +370,7 @@ static int epic_close(struct net_device static struct net_device_stats *epic_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); - + static int __devinit epic_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -392,9 +392,9 @@ #ifndef MODULE printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s", version, version2, version3); #endif - + card_idx++; - + ret = pci_enable_device(pdev); if (ret) goto out; @@ -405,7 +405,7 @@ #endif ret = -ENODEV; goto err_out_disable; } - + pci_set_master(pdev); ret = pci_request_regions(pdev, DRV_NAME); @@ -498,7 +498,7 @@ #endif ep->pci_dev = pdev; ep->chip_id = chip_idx; ep->chip_flags = pci_id_tbl[chip_idx].drv_flags; - ep->irq_mask = + ep->irq_mask = (ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) | CntFull | TxUnderrun | EpicNapiEvent; @@ -587,7 +587,7 @@ err_out_disable: pci_disable_device(pdev); goto out; } - + /* Serial EEPROM section. */ /* EEPROM_Ctrl bits. */ @@ -709,7 +709,7 @@ static void mdio_write(struct net_device outw(value, ioaddr + MIIData); outl((phy_id << 9) | (loc << 4) | MII_WRITEOP, ioaddr + MIICtrl); - for (i = 10000; i > 0; i--) { + for (i = 10000; i > 0; i--) { barrier(); if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0) break; @@ -717,7 +717,7 @@ static void mdio_write(struct net_device return; } - + static int epic_open(struct net_device *dev) { struct epic_private *ep = dev->priv; @@ -760,7 +760,7 @@ #else #endif udelay(20); /* Looks like EPII needs that if you want reliable RX init. FIXME: pci posting bug? */ - + for (i = 0; i < 3; i++) outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4); @@ -803,7 +803,7 @@ #endif /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) - | CntFull | TxUnderrun + | CntFull | TxUnderrun | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK); if (debug > 1) @@ -831,7 +831,7 @@ static void epic_pause(struct net_device struct epic_private *ep = dev->priv; netif_stop_queue (dev); - + /* Disable interrupts by clearing the interrupt mask. */ outl(0x00000000, ioaddr + INTMASK); /* Stop the chip's Tx and Rx DMA processes. */ @@ -987,7 +987,7 @@ static void epic_init_ring(struct net_de for (i = 0; i < RX_RING_SIZE; i++) { ep->rx_ring[i].rxstatus = 0; ep->rx_ring[i].buflength = cpu_to_le32(ep->rx_buf_sz); - ep->rx_ring[i].next = ep->rx_ring_dma + + ep->rx_ring[i].next = ep->rx_ring_dma + (i+1)*sizeof(struct epic_rx_desc); ep->rx_skbuff[i] = NULL; } @@ -1002,7 +1002,7 @@ static void epic_init_ring(struct net_de break; skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* 16 byte align the IP header. */ - ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev, + ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev, skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); ep->rx_ring[i].rxstatus = cpu_to_le32(DescOwn); } @@ -1013,7 +1013,7 @@ static void epic_init_ring(struct net_de for (i = 0; i < TX_RING_SIZE; i++) { ep->tx_skbuff[i] = NULL; ep->tx_ring[i].txstatus = 0x0000; - ep->tx_ring[i].next = ep->tx_ring_dma + + ep->tx_ring[i].next = ep->tx_ring_dma + (i+1)*sizeof(struct epic_tx_desc); } ep->tx_ring[i-1].next = ep->tx_ring_dma; @@ -1026,12 +1026,9 @@ static int epic_start_xmit(struct sk_buf int entry, free_count; u32 ctrl_word; unsigned long flags; - - if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; - } + + if (skb_padto(skb, ETH_ZLEN)) + return 0; /* Caution: the write order is important here, set the field with the "ownership" bit last. */ @@ -1042,7 +1039,7 @@ static int epic_start_xmit(struct sk_buf entry = ep->cur_tx % TX_RING_SIZE; ep->tx_skbuff[entry] = skb; - ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data, + ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); if (free_count < TX_QUEUE_LEN/2) {/* Typical path */ ctrl_word = cpu_to_le32(0x100000); /* No interrupt */ @@ -1126,7 +1123,7 @@ static void epic_tx(struct net_device *d /* Free the original skb. */ skb = ep->tx_skbuff[entry]; - pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, + pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq(skb); ep->tx_skbuff[entry] = NULL; @@ -1281,8 +1278,8 @@ static int epic_rx(struct net_device *de ep->rx_buf_sz, PCI_DMA_FROMDEVICE); } else { - pci_unmap_single(ep->pci_dev, - ep->rx_ring[entry].bufaddr, + pci_unmap_single(ep->pci_dev, + ep->rx_ring[entry].bufaddr, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); skb_put(skb = ep->rx_skbuff[entry], pkt_len); ep->rx_skbuff[entry] = NULL; @@ -1307,7 +1304,7 @@ static int epic_rx(struct net_device *de break; skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, + ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); work_done++; } @@ -1403,7 +1400,7 @@ static int epic_close(struct net_device ep->rx_ring[i].rxstatus = 0; /* Not owned by Epic chip. */ ep->rx_ring[i].buflength = 0; if (skb) { - pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr, + pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(skb); } @@ -1414,7 +1411,7 @@ static int epic_close(struct net_device ep->tx_skbuff[i] = NULL; if (!skb) continue; - pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr, + pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr, skb->len, PCI_DMA_TODEVICE); dev_kfree_skb(skb); } @@ -1607,7 +1604,7 @@ static void __devexit epic_remove_one (s { struct net_device *dev = pci_get_drvdata(pdev); struct epic_private *ep = dev->priv; - + pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma); pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma); unregister_netdev(dev); diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c index b67545b..4bf76f8 100644 --- a/drivers/net/eth16i.c +++ b/drivers/net/eth16i.c @@ -1064,8 +1064,7 @@ static int eth16i_tx(struct sk_buff *skb unsigned long flags; if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/fec.h b/drivers/net/fec.h index 965c5c4..1d42160 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h @@ -14,7 +14,7 @@ #define FEC_H /****************************************************************************/ #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) + defined(CONFIG_M520x) || defined(CONFIG_M532x) /* * Just figures, Motorola would have to change the offsets for * registers in the same peripheral device on different models diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index feb5b22..21be4fa 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -107,6 +107,8 @@ * 0.52: 20 Jan 2006: Add MSI/MSIX support. * 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset. * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup. + * 0.55: 22 Mar 2006: Add flow control (pause frame). + * 0.56: 22 Mar 2006: Additional ethtool config and moduleparam support. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -118,7 +120,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.54" +#define FORCEDETH_VERSION "0.56" #define DRV_NAME "forcedeth" #include @@ -163,6 +165,9 @@ #define DEV_HAS_VLAN 0x0020 #define DEV_HAS_MSI 0x0040 /* device supports MSI */ #define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ #define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */ +#define DEV_HAS_PAUSEFRAME_TX 0x0200 /* device supports tx pause frames */ +#define DEV_HAS_STATISTICS 0x0400 /* device supports hw statistics */ +#define DEV_HAS_TEST_EXTENDED 0x0800 /* device supports extended diagnostic test */ enum { NvRegIrqStatus = 0x000, @@ -203,6 +208,7 @@ #define NVREG_POLL_DEFAULT_CPU 13 NvRegMSIIrqMask = 0x030, #define NVREG_MSI_VECTOR_0_ENABLED 0x01 NvRegMisc1 = 0x080, +#define NVREG_MISC1_PAUSE_TX 0x01 #define NVREG_MISC1_HD 0x02 #define NVREG_MISC1_FORCE 0x3b0f3c @@ -214,9 +220,11 @@ #define NVREG_XMITCTL_START 0x01 #define NVREG_XMITSTAT_BUSY 0x01 NvRegPacketFilterFlags = 0x8c, -#define NVREG_PFF_ALWAYS 0x7F0008 +#define NVREG_PFF_PAUSE_RX 0x08 +#define NVREG_PFF_ALWAYS 0x7F0000 #define NVREG_PFF_PROMISC 0x80 #define NVREG_PFF_MYADDR 0x20 +#define NVREG_PFF_LOOPBACK 0x10 NvRegOffloadConfig = 0x90, #define NVREG_OFFLOAD_HOMEPHY 0x601 @@ -277,6 +285,9 @@ #define NVREG_TXRXCTL_VLANSTRIP 0x00040 #define NVREG_TXRXCTL_VLANINS 0x00080 NvRegTxRingPhysAddrHigh = 0x148, NvRegRxRingPhysAddrHigh = 0x14C, + NvRegTxPauseFrame = 0x170, +#define NVREG_TX_PAUSEFRAME_DISABLE 0x1ff0080 +#define NVREG_TX_PAUSEFRAME_ENABLE 0x0c00030 NvRegMIIStatus = 0x180, #define NVREG_MIISTAT_ERROR 0x0001 #define NVREG_MIISTAT_LINKCHANGE 0x0008 @@ -326,6 +337,33 @@ #define NVREG_POWERSTATE_D0 0x0000 #define NVREG_POWERSTATE_D1 0x0001 #define NVREG_POWERSTATE_D2 0x0002 #define NVREG_POWERSTATE_D3 0x0003 + NvRegTxCnt = 0x280, + NvRegTxZeroReXmt = 0x284, + NvRegTxOneReXmt = 0x288, + NvRegTxManyReXmt = 0x28c, + NvRegTxLateCol = 0x290, + NvRegTxUnderflow = 0x294, + NvRegTxLossCarrier = 0x298, + NvRegTxExcessDef = 0x29c, + NvRegTxRetryErr = 0x2a0, + NvRegRxFrameErr = 0x2a4, + NvRegRxExtraByte = 0x2a8, + NvRegRxLateCol = 0x2ac, + NvRegRxRunt = 0x2b0, + NvRegRxFrameTooLong = 0x2b4, + NvRegRxOverflow = 0x2b8, + NvRegRxFCSErr = 0x2bc, + NvRegRxFrameAlignErr = 0x2c0, + NvRegRxLenErr = 0x2c4, + NvRegRxUnicast = 0x2c8, + NvRegRxMulticast = 0x2cc, + NvRegRxBroadcast = 0x2d0, + NvRegTxDef = 0x2d4, + NvRegTxFrame = 0x2d8, + NvRegRxCnt = 0x2dc, + NvRegTxPause = 0x2e0, + NvRegRxPause = 0x2e4, + NvRegRxDropFrame = 0x2e8, NvRegVlanControl = 0x300, #define NVREG_VLANCONTROL_ENABLE 0x2000 NvRegMSIXMap0 = 0x3e0, @@ -449,16 +487,18 @@ #define NV_WAKEUPMASKENTRIES 4 /* General driver defaults */ #define NV_WATCHDOG_TIMEO (5*HZ) -#define RX_RING 128 -#define TX_RING 256 -/* - * If your nic mysteriously hangs then try to reduce the limits - * to 1/0: It might be required to set NV_TX_LASTPACKET in the - * last valid ring entry. But this would be impossible to - * implement - probably a disassembly error. +#define RX_RING_DEFAULT 128 +#define TX_RING_DEFAULT 256 +#define RX_RING_MIN 128 +#define TX_RING_MIN 64 +#define RING_MAX_DESC_VER_1 1024 +#define RING_MAX_DESC_VER_2_3 16384 +/* + * Difference between the get and put pointers for the tx ring. + * This is used to throttle the amount of data outstanding in the + * tx ring. */ -#define TX_LIMIT_STOP 255 -#define TX_LIMIT_START 254 +#define TX_LIMIT_DIFFERENCE 1 /* rx/tx mac addr + type + vlan + align + slack*/ #define NV_RX_HEADERS (64) @@ -472,8 +512,9 @@ #define NV_PKTLIMIT_2 9100 /* Actual lim #define OOM_REFILL (1+HZ/20) #define POLL_WAIT (1+HZ/100) #define LINK_TIMEOUT (3*HZ) +#define STATS_INTERVAL (10*HZ) -/* +/* * desc_ver values: * The nic supports three different descriptor types: * - DESC_VER_1: Original @@ -506,13 +547,13 @@ #define PHY_100 0x1 #define PHY_1000 0x2 #define PHY_HALF 0x100 -/* FIXME: MII defines that should be added to */ -#define MII_1000BT_CR 0x09 -#define MII_1000BT_SR 0x0a -#define ADVERTISE_1000FULL 0x0200 -#define ADVERTISE_1000HALF 0x0100 -#define LPA_1000FULL 0x0800 -#define LPA_1000HALF 0x0400 +#define NV_PAUSEFRAME_RX_CAPABLE 0x0001 +#define NV_PAUSEFRAME_TX_CAPABLE 0x0002 +#define NV_PAUSEFRAME_RX_ENABLE 0x0004 +#define NV_PAUSEFRAME_TX_ENABLE 0x0008 +#define NV_PAUSEFRAME_RX_REQ 0x0010 +#define NV_PAUSEFRAME_TX_REQ 0x0020 +#define NV_PAUSEFRAME_AUTONEG 0x0040 /* MSI/MSI-X defines */ #define NV_MSI_X_MAX_VECTORS 8 @@ -527,15 +568,110 @@ #define NV_MSI_X_VECTOR_RX 0x0 #define NV_MSI_X_VECTOR_TX 0x1 #define NV_MSI_X_VECTOR_OTHER 0x2 +/* statistics */ +struct nv_ethtool_str { + char name[ETH_GSTRING_LEN]; +}; + +static const struct nv_ethtool_str nv_estats_str[] = { + { "tx_bytes" }, + { "tx_zero_rexmt" }, + { "tx_one_rexmt" }, + { "tx_many_rexmt" }, + { "tx_late_collision" }, + { "tx_fifo_errors" }, + { "tx_carrier_errors" }, + { "tx_excess_deferral" }, + { "tx_retry_error" }, + { "tx_deferral" }, + { "tx_packets" }, + { "tx_pause" }, + { "rx_frame_error" }, + { "rx_extra_byte" }, + { "rx_late_collision" }, + { "rx_runt" }, + { "rx_frame_too_long" }, + { "rx_over_errors" }, + { "rx_crc_errors" }, + { "rx_frame_align_error" }, + { "rx_length_error" }, + { "rx_unicast" }, + { "rx_multicast" }, + { "rx_broadcast" }, + { "rx_bytes" }, + { "rx_pause" }, + { "rx_drop_frame" }, + { "rx_packets" }, + { "rx_errors_total" } +}; + +struct nv_ethtool_stats { + u64 tx_bytes; + u64 tx_zero_rexmt; + u64 tx_one_rexmt; + u64 tx_many_rexmt; + u64 tx_late_collision; + u64 tx_fifo_errors; + u64 tx_carrier_errors; + u64 tx_excess_deferral; + u64 tx_retry_error; + u64 tx_deferral; + u64 tx_packets; + u64 tx_pause; + u64 rx_frame_error; + u64 rx_extra_byte; + u64 rx_late_collision; + u64 rx_runt; + u64 rx_frame_too_long; + u64 rx_over_errors; + u64 rx_crc_errors; + u64 rx_frame_align_error; + u64 rx_length_error; + u64 rx_unicast; + u64 rx_multicast; + u64 rx_broadcast; + u64 rx_bytes; + u64 rx_pause; + u64 rx_drop_frame; + u64 rx_packets; + u64 rx_errors_total; +}; + +/* diagnostics */ +#define NV_TEST_COUNT_BASE 3 +#define NV_TEST_COUNT_EXTENDED 4 + +static const struct nv_ethtool_str nv_etests_str[] = { + { "link (online/offline)" }, + { "register (offline) " }, + { "interrupt (offline) " }, + { "loopback (offline) " } +}; + +struct register_test { + u32 reg; + u32 mask; +}; + +static const struct register_test nv_registers_test[] = { + { NvRegUnknownSetupReg6, 0x01 }, + { NvRegMisc1, 0x03c }, + { NvRegOffloadConfig, 0x03ff }, + { NvRegMulticastAddrA, 0xffffffff }, + { NvRegUnknownSetupReg3, 0x0ff }, + { NvRegWakeUpFlags, 0x07777 }, + { 0,0 } +}; + /* * SMP locking: * All hardware access under dev->priv->lock, except the performance * critical parts: * - rx is (pseudo-) lockless: it relies on the single-threading provided * by the arch code for interrupts. - * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission + * - tx setup is lockless: it relies on netif_tx_lock. Actual submission * needs dev->priv->lock :-( - * - set_multicast_list: preparation lockless, relies on dev->xmit_lock. + * - set_multicast_list: preparation lockless, relies on netif_tx_lock. */ /* in dev: base, irq */ @@ -545,6 +681,7 @@ struct fe_priv { /* General data: * Locking: spin_lock(&np->lock); */ struct net_device_stats stats; + struct nv_ethtool_stats estats; int in_shutdown; u32 linkspeed; int duplex; @@ -554,6 +691,7 @@ struct fe_priv { int wolenabled; unsigned int phy_oui; u16 gigabit; + int intr_test; /* General data: RO fields */ dma_addr_t ring_addr; @@ -573,13 +711,15 @@ struct fe_priv { */ ring_type rx_ring; unsigned int cur_rx, refill_rx; - struct sk_buff *rx_skbuff[RX_RING]; - dma_addr_t rx_dma[RX_RING]; + struct sk_buff **rx_skbuff; + dma_addr_t *rx_dma; unsigned int rx_buf_sz; unsigned int pkt_limit; struct timer_list oom_kick; struct timer_list nic_poll; + struct timer_list stats_poll; u32 nic_poll_irq; + int rx_ring_size; /* media detection workaround. * Locking: Within irq hander or disable_irq+spin_lock(&np->lock); @@ -591,10 +731,13 @@ struct fe_priv { */ ring_type tx_ring; unsigned int next_tx, nic_tx; - struct sk_buff *tx_skbuff[TX_RING]; - dma_addr_t tx_dma[TX_RING]; - unsigned int tx_dma_len[TX_RING]; + struct sk_buff **tx_skbuff; + dma_addr_t *tx_dma; + unsigned int *tx_dma_len; u32 tx_flags; + int tx_ring_size; + int tx_limit_start; + int tx_limit_stop; /* vlan fields */ struct vlan_group *vlangrp; @@ -602,6 +745,9 @@ struct fe_priv { /* msi/msi-x fields */ u32 msi_flags; struct msix_entry msi_x_entry[NV_MSI_X_MAX_VECTORS]; + + /* flow control */ + u32 pause_flags; }; /* @@ -612,12 +758,14 @@ static int max_interrupt_work = 5; /* * Optimization can be either throuput mode or cpu mode - * + * * Throughput Mode: Every tx and rx packet will generate an interrupt. * CPU Mode: Interrupts are controlled by a timer. */ -#define NV_OPTIMIZATION_MODE_THROUGHPUT 0 -#define NV_OPTIMIZATION_MODE_CPU 1 +enum { + NV_OPTIMIZATION_MODE_THROUGHPUT, + NV_OPTIMIZATION_MODE_CPU +}; static int optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT; /* @@ -630,14 +778,31 @@ static int optimization_mode = NV_OPTIMI static int poll_interval = -1; /* - * Disable MSI interrupts + * MSI interrupts + */ +enum { + NV_MSI_INT_DISABLED, + NV_MSI_INT_ENABLED +}; +static int msi = NV_MSI_INT_ENABLED; + +/* + * MSIX interrupts */ -static int disable_msi = 0; +enum { + NV_MSIX_INT_DISABLED, + NV_MSIX_INT_ENABLED +}; +static int msix = NV_MSIX_INT_ENABLED; /* - * Disable MSIX interrupts + * DMA 64bit */ -static int disable_msix = 0; +enum { + NV_DMA_64BIT_DISABLED, + NV_DMA_64BIT_ENABLED +}; +static int dma_64bit = NV_DMA_64BIT_ENABLED; static inline struct fe_priv *get_nvpriv(struct net_device *dev) { @@ -697,7 +862,7 @@ static void setup_hw_rings(struct net_de writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr); } if (rxtx_flags & NV_SETUP_TX_RING) { - writel((u32) cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr); + writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr); } } else { if (rxtx_flags & NV_SETUP_RX_RING) { @@ -705,12 +870,37 @@ static void setup_hw_rings(struct net_de writel((u32) (cpu_to_le64(np->ring_addr) >> 32), base + NvRegRxRingPhysAddrHigh); } if (rxtx_flags & NV_SETUP_TX_RING) { - writel((u32) cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr); - writel((u32) (cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)) >> 32), base + NvRegTxRingPhysAddrHigh); + writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr); + writel((u32) (cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)) >> 32), base + NvRegTxRingPhysAddrHigh); } } } +static void free_rings(struct net_device *dev) +{ + struct fe_priv *np = get_nvpriv(dev); + + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + if(np->rx_ring.orig) + pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size), + np->rx_ring.orig, np->ring_addr); + } else { + if (np->rx_ring.ex) + pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (np->rx_ring_size + np->tx_ring_size), + np->rx_ring.ex, np->ring_addr); + } + if (np->rx_skbuff) + kfree(np->rx_skbuff); + if (np->rx_dma) + kfree(np->rx_dma); + if (np->tx_skbuff) + kfree(np->tx_skbuff); + if (np->tx_dma) + kfree(np->tx_dma); + if (np->tx_dma_len) + kfree(np->tx_dma_len); +} + static int using_multi_irqs(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); @@ -860,7 +1050,7 @@ static int phy_init(struct net_device *d /* set advertise register */ reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); - reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|0x800|0x400); + reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|ADVERTISE_PAUSE_ASYM|ADVERTISE_PAUSE_CAP); if (mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg)) { printk(KERN_INFO "%s: phy write to advertise failed.\n", pci_name(np->pci_dev)); return PHY_ERROR; @@ -873,14 +1063,14 @@ static int phy_init(struct net_device *d mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ); if (mii_status & PHY_GIGABIT) { np->gigabit = PHY_GIGABIT; - mii_control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ); + mii_control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ); mii_control_1000 &= ~ADVERTISE_1000HALF; if (phyinterface & PHY_RGMII) mii_control_1000 |= ADVERTISE_1000FULL; else mii_control_1000 &= ~ADVERTISE_1000FULL; - if (mii_rw(dev, np->phyaddr, MII_1000BT_CR, mii_control_1000)) { + if (mii_rw(dev, np->phyaddr, MII_CTRL1000, mii_control_1000)) { printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); return PHY_ERROR; } @@ -918,6 +1108,8 @@ static int phy_init(struct net_device *d return PHY_ERROR; } } + /* some phys clear out pause advertisment on reset, set it back */ + mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg); /* restart auto negotiation */ mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); @@ -1047,7 +1239,7 @@ static int nv_alloc_rx(struct net_device while (np->cur_rx != refill_rx) { struct sk_buff *skb; - nr = refill_rx % RX_RING; + nr = refill_rx % np->rx_ring_size; if (np->rx_skbuff[nr] == NULL) { skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD); @@ -1076,7 +1268,7 @@ static int nv_alloc_rx(struct net_device refill_rx++; } np->refill_rx = refill_rx; - if (np->cur_rx - refill_rx == RX_RING) + if (np->cur_rx - refill_rx == np->rx_ring_size) return 1; return 0; } @@ -1110,14 +1302,14 @@ static void nv_do_rx_refill(unsigned lon } } -static void nv_init_rx(struct net_device *dev) +static void nv_init_rx(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); int i; - np->cur_rx = RX_RING; + np->cur_rx = np->rx_ring_size; np->refill_rx = 0; - for (i = 0; i < RX_RING; i++) + for (i = 0; i < np->rx_ring_size; i++) if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) np->rx_ring.orig[i].FlagLen = 0; else @@ -1130,7 +1322,7 @@ static void nv_init_tx(struct net_device int i; np->next_tx = np->nic_tx = 0; - for (i = 0; i < TX_RING; i++) { + for (i = 0; i < np->tx_ring_size; i++) { if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) np->tx_ring.orig[i].FlagLen = 0; else @@ -1174,8 +1366,8 @@ static void nv_drain_tx(struct net_devic { struct fe_priv *np = netdev_priv(dev); unsigned int i; - - for (i = 0; i < TX_RING; i++) { + + for (i = 0; i < np->tx_ring_size; i++) { if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) np->tx_ring.orig[i].FlagLen = 0; else @@ -1189,7 +1381,7 @@ static void nv_drain_rx(struct net_devic { struct fe_priv *np = netdev_priv(dev); int i; - for (i = 0; i < RX_RING; i++) { + for (i = 0; i < np->rx_ring_size; i++) { if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) np->rx_ring.orig[i].FlagLen = 0; else @@ -1213,7 +1405,7 @@ static void drain_ring(struct net_device /* * nv_start_xmit: dev->hard_start_xmit function - * Called with dev->xmit_lock held. + * Called with netif_tx_lock held. */ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -1221,8 +1413,8 @@ static int nv_start_xmit(struct sk_buff u32 tx_flags = 0; u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET); unsigned int fragments = skb_shinfo(skb)->nr_frags; - unsigned int nr = (np->next_tx - 1) % TX_RING; - unsigned int start_nr = np->next_tx % TX_RING; + unsigned int nr = (np->next_tx - 1) % np->tx_ring_size; + unsigned int start_nr = np->next_tx % np->tx_ring_size; unsigned int i; u32 offset = 0; u32 bcnt; @@ -1238,7 +1430,7 @@ static int nv_start_xmit(struct sk_buff spin_lock_irq(&np->lock); - if ((np->next_tx - np->nic_tx + entries - 1) > TX_LIMIT_STOP) { + if ((np->next_tx - np->nic_tx + entries - 1) > np->tx_limit_stop) { spin_unlock_irq(&np->lock); netif_stop_queue(dev); return NETDEV_TX_BUSY; @@ -1247,7 +1439,7 @@ static int nv_start_xmit(struct sk_buff /* setup the header buffer */ do { bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - nr = (nr + 1) % TX_RING; + nr = (nr + 1) % np->tx_ring_size; np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data + offset, bcnt, PCI_DMA_TODEVICE); @@ -1274,7 +1466,7 @@ static int nv_start_xmit(struct sk_buff do { bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - nr = (nr + 1) % TX_RING; + nr = (nr + 1) % np->tx_ring_size; np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt, PCI_DMA_TODEVICE); @@ -1303,8 +1495,8 @@ static int nv_start_xmit(struct sk_buff np->tx_skbuff[nr] = skb; #ifdef NETIF_F_TSO - if (skb_shinfo(skb)->tso_size) - tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT); + if (skb_shinfo(skb)->gso_size) + tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT); else #endif tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); @@ -1320,7 +1512,7 @@ #endif } else { np->tx_ring.ex[start_nr].TxVlan = cpu_to_le32(tx_flags_vlan); np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra); - } + } dprintk(KERN_DEBUG "%s: nv_start_xmit: packet %d (entries %d) queued for transmission. tx_flags_extra: %x\n", dev->name, np->next_tx, entries, tx_flags_extra); @@ -1356,7 +1548,7 @@ static void nv_tx_done(struct net_device struct sk_buff *skb; while (np->nic_tx != np->next_tx) { - i = np->nic_tx % TX_RING; + i = np->nic_tx % np->tx_ring_size; if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) Flags = le32_to_cpu(np->tx_ring.orig[i].FlagLen); @@ -1395,19 +1587,19 @@ static void nv_tx_done(struct net_device } else { np->stats.tx_packets++; np->stats.tx_bytes += skb->len; - } + } } } nv_release_txskb(dev, i); np->nic_tx++; } - if (np->next_tx - np->nic_tx < TX_LIMIT_START) + if (np->next_tx - np->nic_tx < np->tx_limit_start) netif_wake_queue(dev); } /* * nv_tx_timeout: dev->tx_timeout function - * Called with dev->xmit_lock held. + * Called with netif_tx_lock held. */ static void nv_tx_timeout(struct net_device *dev) { @@ -1438,10 +1630,10 @@ static void nv_tx_timeout(struct net_dev readl(base + i + 24), readl(base + i + 28)); } printk(KERN_INFO "%s: Dumping tx ring\n", dev->name); - for (i=0;itx_ring_size;i+= 4) { if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n", - i, + i, le32_to_cpu(np->tx_ring.orig[i].PacketBuffer), le32_to_cpu(np->tx_ring.orig[i].FlagLen), le32_to_cpu(np->tx_ring.orig[i+1].PacketBuffer), @@ -1452,7 +1644,7 @@ static void nv_tx_timeout(struct net_dev le32_to_cpu(np->tx_ring.orig[i+3].FlagLen)); } else { printk(KERN_INFO "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n", - i, + i, le32_to_cpu(np->tx_ring.ex[i].PacketBufferHigh), le32_to_cpu(np->tx_ring.ex[i].PacketBufferLow), le32_to_cpu(np->tx_ring.ex[i].FlagLen), @@ -1550,15 +1742,14 @@ static void nv_rx_process(struct net_dev u32 Flags; u32 vlanflags = 0; - for (;;) { struct sk_buff *skb; int len; int i; - if (np->cur_rx - np->refill_rx >= RX_RING) + if (np->cur_rx - np->refill_rx >= np->rx_ring_size) break; /* we scanned the whole ring - do not continue */ - i = np->cur_rx % RX_RING; + i = np->cur_rx % np->rx_ring_size; if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { Flags = le32_to_cpu(np->rx_ring.orig[i].FlagLen); len = nv_descr_getlength(&np->rx_ring.orig[i], np->desc_ver); @@ -1665,14 +1856,16 @@ static void nv_rx_process(struct net_dev } } } - Flags &= NV_RX2_CHECKSUMMASK; - if (Flags == NV_RX2_CHECKSUMOK1 || - Flags == NV_RX2_CHECKSUMOK2 || - Flags == NV_RX2_CHECKSUMOK3) { - dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name); - np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY; - } else { - dprintk(KERN_DEBUG "%s: hwchecksum miss!.\n", dev->name); + if (np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) { + Flags &= NV_RX2_CHECKSUMMASK; + if (Flags == NV_RX2_CHECKSUMOK1 || + Flags == NV_RX2_CHECKSUMOK2 || + Flags == NV_RX2_CHECKSUMOK3) { + dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name); + np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY; + } else { + dprintk(KERN_DEBUG "%s: hwchecksum miss!.\n", dev->name); + } } } /* got a valid packet - forward it to the network core */ @@ -1737,7 +1930,7 @@ static int nv_change_mtu(struct net_devi * Changing the MTU is a rare event, it shouldn't matter. */ nv_disable_irq(dev); - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); spin_lock(&np->lock); /* stop engines */ nv_stop_rx(dev); @@ -1747,18 +1940,15 @@ static int nv_change_mtu(struct net_devi nv_drain_rx(dev); nv_drain_tx(dev); /* reinit driver view of the rx queue */ - nv_init_rx(dev); - nv_init_tx(dev); - /* alloc new rx buffers */ set_bufsize(dev); - if (nv_alloc_rx(dev)) { + if (nv_init_ring(dev)) { if (!np->in_shutdown) mod_timer(&np->oom_kick, jiffies + OOM_REFILL); } /* reinit nic view of the rx queue */ writel(np->rx_buf_sz, base + NvRegOffloadConfig); setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); - writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT), + writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes); pci_push(base); writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); @@ -1768,7 +1958,7 @@ static int nv_change_mtu(struct net_devi nv_start_rx(dev); nv_start_tx(dev); spin_unlock(&np->lock); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); nv_enable_irq(dev); } return 0; @@ -1803,7 +1993,7 @@ static int nv_set_mac_address(struct net memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN); if (netif_running(dev)) { - spin_lock_bh(&dev->xmit_lock); + netif_tx_lock_bh(dev); spin_lock_irq(&np->lock); /* stop rx engine */ @@ -1815,7 +2005,7 @@ static int nv_set_mac_address(struct net /* restart rx engine */ nv_start_rx(dev); spin_unlock_irq(&np->lock); - spin_unlock_bh(&dev->xmit_lock); + netif_tx_unlock_bh(dev); } else { nv_copy_mac_to_hw(dev); } @@ -1824,7 +2014,7 @@ static int nv_set_mac_address(struct net /* * nv_set_multicast: dev->set_multicast function - * Called with dev->xmit_lock held. + * Called with netif_tx_lock held. */ static void nv_set_multicast(struct net_device *dev) { @@ -1832,16 +2022,16 @@ static void nv_set_multicast(struct net_ u8 __iomem *base = get_hwbase(dev); u32 addr[2]; u32 mask[2]; - u32 pff; + u32 pff = readl(base + NvRegPacketFilterFlags) & NVREG_PFF_PAUSE_RX; memset(addr, 0, sizeof(addr)); memset(mask, 0, sizeof(mask)); if (dev->flags & IFF_PROMISC) { printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); - pff = NVREG_PFF_PROMISC; + pff |= NVREG_PFF_PROMISC; } else { - pff = NVREG_PFF_MYADDR; + pff |= NVREG_PFF_MYADDR; if (dev->flags & IFF_ALLMULTI || dev->mc_list) { u32 alwaysOff[2]; @@ -1886,6 +2076,35 @@ static void nv_set_multicast(struct net_ spin_unlock_irq(&np->lock); } +static void nv_update_pause(struct net_device *dev, u32 pause_flags) +{ + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + + np->pause_flags &= ~(NV_PAUSEFRAME_TX_ENABLE | NV_PAUSEFRAME_RX_ENABLE); + + if (np->pause_flags & NV_PAUSEFRAME_RX_CAPABLE) { + u32 pff = readl(base + NvRegPacketFilterFlags) & ~NVREG_PFF_PAUSE_RX; + if (pause_flags & NV_PAUSEFRAME_RX_ENABLE) { + writel(pff|NVREG_PFF_PAUSE_RX, base + NvRegPacketFilterFlags); + np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE; + } else { + writel(pff, base + NvRegPacketFilterFlags); + } + } + if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE) { + u32 regmisc = readl(base + NvRegMisc1) & ~NVREG_MISC1_PAUSE_TX; + if (pause_flags & NV_PAUSEFRAME_TX_ENABLE) { + writel(NVREG_TX_PAUSEFRAME_ENABLE, base + NvRegTxPauseFrame); + writel(regmisc|NVREG_MISC1_PAUSE_TX, base + NvRegMisc1); + np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE; + } else { + writel(NVREG_TX_PAUSEFRAME_DISABLE, base + NvRegTxPauseFrame); + writel(regmisc, base + NvRegMisc1); + } + } +} + /** * nv_update_linkspeed: Setup the MAC according to the link partner * @dev: Network device to be configured @@ -1901,12 +2120,14 @@ static int nv_update_linkspeed(struct ne { struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - int adv, lpa; + int adv = 0; + int lpa = 0; + int adv_lpa, adv_pause, lpa_pause; int newls = np->linkspeed; int newdup = np->duplex; int mii_status; int retval = 0; - u32 control_1000, status_1000, phyreg; + u32 control_1000, status_1000, phyreg, pause_flags; /* BMSR_LSTATUS is latched, read it twice: * we want the current value. @@ -1952,10 +2173,15 @@ static int nv_update_linkspeed(struct ne goto set_speed; } + adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); + lpa = mii_rw(dev, np->phyaddr, MII_LPA, MII_READ); + dprintk(KERN_DEBUG "%s: nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n", + dev->name, adv, lpa); + retval = 1; if (np->gigabit == PHY_GIGABIT) { - control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ); - status_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_SR, MII_READ); + control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ); + status_1000 = mii_rw(dev, np->phyaddr, MII_STAT1000, MII_READ); if ((control_1000 & ADVERTISE_1000FULL) && (status_1000 & LPA_1000FULL)) { @@ -1967,27 +2193,22 @@ static int nv_update_linkspeed(struct ne } } - adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); - lpa = mii_rw(dev, np->phyaddr, MII_LPA, MII_READ); - dprintk(KERN_DEBUG "%s: nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n", - dev->name, adv, lpa); - /* FIXME: handle parallel detection properly */ - lpa = lpa & adv; - if (lpa & LPA_100FULL) { + adv_lpa = lpa & adv; + if (adv_lpa & LPA_100FULL) { newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100; newdup = 1; - } else if (lpa & LPA_100HALF) { + } else if (adv_lpa & LPA_100HALF) { newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100; newdup = 0; - } else if (lpa & LPA_10FULL) { + } else if (adv_lpa & LPA_10FULL) { newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; newdup = 1; - } else if (lpa & LPA_10HALF) { + } else if (adv_lpa & LPA_10HALF) { newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; newdup = 0; } else { - dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, lpa); + dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, adv_lpa); newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; newdup = 0; } @@ -2030,6 +2251,46 @@ set_speed: writel(np->linkspeed, base + NvRegLinkSpeed); pci_push(base); + pause_flags = 0; + /* setup pause frame */ + if (np->duplex != 0) { + if (np->autoneg && np->pause_flags & NV_PAUSEFRAME_AUTONEG) { + adv_pause = adv & (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM); + lpa_pause = lpa & (LPA_PAUSE_CAP| LPA_PAUSE_ASYM); + + switch (adv_pause) { + case (ADVERTISE_PAUSE_CAP): + if (lpa_pause & LPA_PAUSE_CAP) { + pause_flags |= NV_PAUSEFRAME_RX_ENABLE; + if (np->pause_flags & NV_PAUSEFRAME_TX_REQ) + pause_flags |= NV_PAUSEFRAME_TX_ENABLE; + } + break; + case (ADVERTISE_PAUSE_ASYM): + if (lpa_pause == (LPA_PAUSE_CAP| LPA_PAUSE_ASYM)) + { + pause_flags |= NV_PAUSEFRAME_TX_ENABLE; + } + break; + case (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM): + if (lpa_pause & LPA_PAUSE_CAP) + { + pause_flags |= NV_PAUSEFRAME_RX_ENABLE; + if (np->pause_flags & NV_PAUSEFRAME_TX_REQ) + pause_flags |= NV_PAUSEFRAME_TX_ENABLE; + } + if (lpa_pause == LPA_PAUSE_ASYM) + { + pause_flags |= NV_PAUSEFRAME_RX_ENABLE; + } + break; + } + } else { + pause_flags = np->pause_flags; + } + } + nv_update_pause(dev, pause_flags); + return retval; } @@ -2090,7 +2351,7 @@ static irqreturn_t nv_nic_irq(int foo, v spin_lock(&np->lock); nv_tx_done(dev); spin_unlock(&np->lock); - + nv_rx_process(dev); if (nv_alloc_rx(dev)) { spin_lock(&np->lock); @@ -2098,7 +2359,7 @@ static irqreturn_t nv_nic_irq(int foo, v mod_timer(&np->oom_kick, jiffies + OOM_REFILL); spin_unlock(&np->lock); } - + if (events & NVREG_IRQ_LINK) { spin_lock(&np->lock); nv_link_irq(dev); @@ -2163,7 +2424,7 @@ static irqreturn_t nv_nic_irq_tx(int foo spin_lock_irq(&np->lock); nv_tx_done(dev); spin_unlock_irq(&np->lock); - + if (events & (NVREG_IRQ_TX_ERR)) { dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", dev->name, events); @@ -2206,7 +2467,7 @@ static irqreturn_t nv_nic_irq_rx(int foo dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events); if (!(events & np->irqmask)) break; - + nv_rx_process(dev); if (nv_alloc_rx(dev)) { spin_lock_irq(&np->lock); @@ -2214,7 +2475,7 @@ static irqreturn_t nv_nic_irq_rx(int foo mod_timer(&np->oom_kick, jiffies + OOM_REFILL); spin_unlock_irq(&np->lock); } - + if (i > max_interrupt_work) { spin_lock_irq(&np->lock); /* disable interrupts on the nic */ @@ -2253,7 +2514,7 @@ static irqreturn_t nv_nic_irq_other(int dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); if (!(events & np->irqmask)) break; - + if (events & NVREG_IRQ_LINK) { spin_lock_irq(&np->lock); nv_link_irq(dev); @@ -2290,6 +2551,175 @@ static irqreturn_t nv_nic_irq_other(int return IRQ_RETVAL(i); } +static irqreturn_t nv_nic_irq_test(int foo, void *data, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) data; + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + u32 events; + + dprintk(KERN_DEBUG "%s: nv_nic_irq_test\n", dev->name); + + if (!(np->msi_flags & NV_MSI_X_ENABLED)) { + events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; + writel(NVREG_IRQ_TIMER, base + NvRegIrqStatus); + } else { + events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; + writel(NVREG_IRQ_TIMER, base + NvRegMSIXIrqStatus); + } + pci_push(base); + dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); + if (!(events & NVREG_IRQ_TIMER)) + return IRQ_RETVAL(0); + + spin_lock(&np->lock); + np->intr_test = 1; + spin_unlock(&np->lock); + + dprintk(KERN_DEBUG "%s: nv_nic_irq_test completed\n", dev->name); + + return IRQ_RETVAL(1); +} + +static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask) +{ + u8 __iomem *base = get_hwbase(dev); + int i; + u32 msixmap = 0; + + /* Each interrupt bit can be mapped to a MSIX vector (4 bits). + * MSIXMap0 represents the first 8 interrupts and MSIXMap1 represents + * the remaining 8 interrupts. + */ + for (i = 0; i < 8; i++) { + if ((irqmask >> i) & 0x1) { + msixmap |= vector << (i << 2); + } + } + writel(readl(base + NvRegMSIXMap0) | msixmap, base + NvRegMSIXMap0); + + msixmap = 0; + for (i = 0; i < 8; i++) { + if ((irqmask >> (i + 8)) & 0x1) { + msixmap |= vector << (i << 2); + } + } + writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1); +} + +static int nv_request_irq(struct net_device *dev, int intr_test) +{ + struct fe_priv *np = get_nvpriv(dev); + u8 __iomem *base = get_hwbase(dev); + int ret = 1; + int i; + + if (np->msi_flags & NV_MSI_X_CAPABLE) { + for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { + np->msi_x_entry[i].entry = i; + } + if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) { + np->msi_flags |= NV_MSI_X_ENABLED; + if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT && !intr_test) { + /* Request irq for rx handling */ + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_err; + } + /* Request irq for tx handling */ + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_free_rx; + } + /* Request irq for link and timer handling */ + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_free_tx; + } + /* map interrupts to their respective vector */ + writel(0, base + NvRegMSIXMap0); + writel(0, base + NvRegMSIXMap1); + set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL); + set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL); + set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER); + } else { + /* Request irq for all interrupts */ + if ((!intr_test && + request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) || + (intr_test && + request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq_test, SA_SHIRQ, dev->name, dev) != 0)) { + printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_err; + } + + /* map interrupts to vector 0 */ + writel(0, base + NvRegMSIXMap0); + writel(0, base + NvRegMSIXMap1); + } + } + } + if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { + if ((ret = pci_enable_msi(np->pci_dev)) == 0) { + np->msi_flags |= NV_MSI_ENABLED; + if ((!intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) || + (intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq_test, SA_SHIRQ, dev->name, dev) != 0)) { + printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); + pci_disable_msi(np->pci_dev); + np->msi_flags &= ~NV_MSI_ENABLED; + goto out_err; + } + + /* map interrupts to vector 0 */ + writel(0, base + NvRegMSIMap0); + writel(0, base + NvRegMSIMap1); + /* enable msi vector 0 */ + writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); + } + } + if (ret != 0) { + if ((!intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) || + (intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq_test, SA_SHIRQ, dev->name, dev) != 0)) + goto out_err; + + } + + return 0; +out_free_tx: + free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev); +out_free_rx: + free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev); +out_err: + return 1; +} + +static void nv_free_irq(struct net_device *dev) +{ + struct fe_priv *np = get_nvpriv(dev); + int i; + + if (np->msi_flags & NV_MSI_X_ENABLED) { + for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { + free_irq(np->msi_x_entry[i].vector, dev); + } + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + } else { + free_irq(np->pci_dev->irq, dev); + if (np->msi_flags & NV_MSI_ENABLED) { + pci_disable_msi(np->pci_dev); + np->msi_flags &= ~NV_MSI_ENABLED; + } + } +} + static void nv_do_nic_poll(unsigned long data) { struct net_device *dev = (struct net_device *) data; @@ -2326,7 +2756,7 @@ static void nv_do_nic_poll(unsigned long np->nic_poll_irq = 0; /* FIXME: Do we need synchronize_irq(dev->irq) here? */ - + writel(mask, base + NvRegIrqMask); pci_push(base); @@ -2359,6 +2789,56 @@ static void nv_poll_controller(struct ne } #endif +static void nv_do_stats_poll(unsigned long data) +{ + struct net_device *dev = (struct net_device *) data; + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + + np->estats.tx_bytes += readl(base + NvRegTxCnt); + np->estats.tx_zero_rexmt += readl(base + NvRegTxZeroReXmt); + np->estats.tx_one_rexmt += readl(base + NvRegTxOneReXmt); + np->estats.tx_many_rexmt += readl(base + NvRegTxManyReXmt); + np->estats.tx_late_collision += readl(base + NvRegTxLateCol); + np->estats.tx_fifo_errors += readl(base + NvRegTxUnderflow); + np->estats.tx_carrier_errors += readl(base + NvRegTxLossCarrier); + np->estats.tx_excess_deferral += readl(base + NvRegTxExcessDef); + np->estats.tx_retry_error += readl(base + NvRegTxRetryErr); + np->estats.tx_deferral += readl(base + NvRegTxDef); + np->estats.tx_packets += readl(base + NvRegTxFrame); + np->estats.tx_pause += readl(base + NvRegTxPause); + np->estats.rx_frame_error += readl(base + NvRegRxFrameErr); + np->estats.rx_extra_byte += readl(base + NvRegRxExtraByte); + np->estats.rx_late_collision += readl(base + NvRegRxLateCol); + np->estats.rx_runt += readl(base + NvRegRxRunt); + np->estats.rx_frame_too_long += readl(base + NvRegRxFrameTooLong); + np->estats.rx_over_errors += readl(base + NvRegRxOverflow); + np->estats.rx_crc_errors += readl(base + NvRegRxFCSErr); + np->estats.rx_frame_align_error += readl(base + NvRegRxFrameAlignErr); + np->estats.rx_length_error += readl(base + NvRegRxLenErr); + np->estats.rx_unicast += readl(base + NvRegRxUnicast); + np->estats.rx_multicast += readl(base + NvRegRxMulticast); + np->estats.rx_broadcast += readl(base + NvRegRxBroadcast); + np->estats.rx_bytes += readl(base + NvRegRxCnt); + np->estats.rx_pause += readl(base + NvRegRxPause); + np->estats.rx_drop_frame += readl(base + NvRegRxDropFrame); + np->estats.rx_packets = + np->estats.rx_unicast + + np->estats.rx_multicast + + np->estats.rx_broadcast; + np->estats.rx_errors_total = + np->estats.rx_crc_errors + + np->estats.rx_over_errors + + np->estats.rx_frame_error + + (np->estats.rx_frame_align_error - np->estats.rx_extra_byte) + + np->estats.rx_late_collision + + np->estats.rx_runt + + np->estats.rx_frame_too_long; + + if (!np->in_shutdown) + mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL); +} + static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct fe_priv *np = netdev_priv(dev); @@ -2382,17 +2862,19 @@ static int nv_set_wol(struct net_device { struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); + u32 flags = 0; - spin_lock_irq(&np->lock); if (wolinfo->wolopts == 0) { - writel(0, base + NvRegWakeUpFlags); np->wolenabled = 0; - } - if (wolinfo->wolopts & WAKE_MAGIC) { - writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags); + } else if (wolinfo->wolopts & WAKE_MAGIC) { np->wolenabled = 1; + flags = NVREG_WAKEUPFLAGS_ENABLE; + } + if (netif_running(dev)) { + spin_lock_irq(&np->lock); + writel(flags, base + NvRegWakeUpFlags); + spin_unlock_irq(&np->lock); } - spin_unlock_irq(&np->lock); return 0; } @@ -2406,9 +2888,17 @@ static int nv_get_settings(struct net_de if (!netif_running(dev)) { /* We do not track link speed / duplex setting if the * interface is disabled. Force a link check */ - nv_update_linkspeed(dev); + if (nv_update_linkspeed(dev)) { + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); + } else { + if (netif_carrier_ok(dev)) + netif_carrier_off(dev); + } } - switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) { + + if (netif_carrier_ok(dev)) { + switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) { case NVREG_LINKSPEED_10: ecmd->speed = SPEED_10; break; @@ -2418,10 +2908,14 @@ static int nv_get_settings(struct net_de case NVREG_LINKSPEED_1000: ecmd->speed = SPEED_1000; break; + } + ecmd->duplex = DUPLEX_HALF; + if (np->duplex) + ecmd->duplex = DUPLEX_FULL; + } else { + ecmd->speed = -1; + ecmd->duplex = -1; } - ecmd->duplex = DUPLEX_HALF; - if (np->duplex) - ecmd->duplex = DUPLEX_FULL; ecmd->autoneg = np->autoneg; @@ -2429,23 +2923,20 @@ static int nv_get_settings(struct net_de if (np->autoneg) { ecmd->advertising |= ADVERTISED_Autoneg; adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); - } else { - adv = np->fixed_mode; - } - if (adv & ADVERTISE_10HALF) - ecmd->advertising |= ADVERTISED_10baseT_Half; - if (adv & ADVERTISE_10FULL) - ecmd->advertising |= ADVERTISED_10baseT_Full; - if (adv & ADVERTISE_100HALF) - ecmd->advertising |= ADVERTISED_100baseT_Half; - if (adv & ADVERTISE_100FULL) - ecmd->advertising |= ADVERTISED_100baseT_Full; - if (np->autoneg && np->gigabit == PHY_GIGABIT) { - adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ); - if (adv & ADVERTISE_1000FULL) - ecmd->advertising |= ADVERTISED_1000baseT_Full; + if (adv & ADVERTISE_10HALF) + ecmd->advertising |= ADVERTISED_10baseT_Half; + if (adv & ADVERTISE_10FULL) + ecmd->advertising |= ADVERTISED_10baseT_Full; + if (adv & ADVERTISE_100HALF) + ecmd->advertising |= ADVERTISED_100baseT_Half; + if (adv & ADVERTISE_100FULL) + ecmd->advertising |= ADVERTISED_100baseT_Full; + if (np->gigabit == PHY_GIGABIT) { + adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ); + if (adv & ADVERTISE_1000FULL) + ecmd->advertising |= ADVERTISED_1000baseT_Full; + } } - ecmd->supported = (SUPPORTED_Autoneg | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | @@ -2497,7 +2988,18 @@ static int nv_set_settings(struct net_de return -EINVAL; } - spin_lock_irq(&np->lock); + netif_carrier_off(dev); + if (netif_running(dev)) { + nv_disable_irq(dev); + netif_tx_lock_bh(dev); + spin_lock(&np->lock); + /* stop engines */ + nv_stop_rx(dev); + nv_stop_tx(dev); + spin_unlock(&np->lock); + netif_tx_unlock_bh(dev); + } + if (ecmd->autoneg == AUTONEG_ENABLE) { int adv, bmcr; @@ -2505,7 +3007,7 @@ static int nv_set_settings(struct net_de /* advertise only what has been requested */ adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); - adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); + adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); if (ecmd->advertising & ADVERTISED_10baseT_Half) adv |= ADVERTISE_10HALF; if (ecmd->advertising & ADVERTISED_10baseT_Full) @@ -2514,16 +3016,22 @@ static int nv_set_settings(struct net_de adv |= ADVERTISE_100HALF; if (ecmd->advertising & ADVERTISED_100baseT_Full) adv |= ADVERTISE_100FULL; + if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) /* for rx we set both advertisments but disable tx pause */ + adv |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + if (np->pause_flags & NV_PAUSEFRAME_TX_REQ) + adv |= ADVERTISE_PAUSE_ASYM; mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv); if (np->gigabit == PHY_GIGABIT) { - adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ); + adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ); adv &= ~ADVERTISE_1000FULL; if (ecmd->advertising & ADVERTISED_1000baseT_Full) adv |= ADVERTISE_1000FULL; - mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv); + mii_rw(dev, np->phyaddr, MII_CTRL1000, adv); } + if (netif_running(dev)) + printk(KERN_INFO "%s: link down.\n", dev->name); bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); @@ -2534,7 +3042,7 @@ static int nv_set_settings(struct net_de np->autoneg = 0; adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); - adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); + adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF) adv |= ADVERTISE_10HALF; if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL) @@ -2543,30 +3051,49 @@ static int nv_set_settings(struct net_de adv |= ADVERTISE_100HALF; if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL) adv |= ADVERTISE_100FULL; + np->pause_flags &= ~(NV_PAUSEFRAME_AUTONEG|NV_PAUSEFRAME_RX_ENABLE|NV_PAUSEFRAME_TX_ENABLE); + if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) {/* for rx we set both advertisments but disable tx pause */ + adv |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE; + } + if (np->pause_flags & NV_PAUSEFRAME_TX_REQ) { + adv |= ADVERTISE_PAUSE_ASYM; + np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE; + } mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv); np->fixed_mode = adv; if (np->gigabit == PHY_GIGABIT) { - adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ); + adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ); adv &= ~ADVERTISE_1000FULL; - mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv); + mii_rw(dev, np->phyaddr, MII_CTRL1000, adv); } bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); - bmcr |= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_FULLDPLX); - if (adv & (ADVERTISE_10FULL|ADVERTISE_100FULL)) + bmcr &= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_SPEED1000|BMCR_FULLDPLX); + if (np->fixed_mode & (ADVERTISE_10FULL|ADVERTISE_100FULL)) bmcr |= BMCR_FULLDPLX; - if (adv & (ADVERTISE_100HALF|ADVERTISE_100FULL)) + if (np->fixed_mode & (ADVERTISE_100HALF|ADVERTISE_100FULL)) bmcr |= BMCR_SPEED100; mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); - - if (netif_running(dev)) { + if (np->phy_oui == PHY_OUI_MARVELL) { + /* reset the phy */ + if (phy_reset(dev)) { + printk(KERN_INFO "%s: phy reset failed\n", dev->name); + return -EINVAL; + } + } else if (netif_running(dev)) { /* Wait a bit and then reconfigure the nic. */ udelay(10); nv_linkchange(dev); } } - spin_unlock_irq(&np->lock); + + if (netif_running(dev)) { + nv_start_rx(dev); + nv_start_tx(dev); + nv_enable_irq(dev); + } return 0; } @@ -2598,24 +3125,39 @@ static int nv_nway_reset(struct net_devi struct fe_priv *np = netdev_priv(dev); int ret; - spin_lock_irq(&np->lock); if (np->autoneg) { int bmcr; + netif_carrier_off(dev); + if (netif_running(dev)) { + nv_disable_irq(dev); + netif_tx_lock_bh(dev); + spin_lock(&np->lock); + /* stop engines */ + nv_stop_rx(dev); + nv_stop_tx(dev); + spin_unlock(&np->lock); + netif_tx_unlock_bh(dev); + printk(KERN_INFO "%s: link down.\n", dev->name); + } + bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); + if (netif_running(dev)) { + nv_start_rx(dev); + nv_start_tx(dev); + nv_enable_irq(dev); + } ret = 0; } else { ret = -EINVAL; } - spin_unlock_irq(&np->lock); return ret; } -#ifdef NETIF_F_TSO static int nv_set_tso(struct net_device *dev, u32 value) { struct fe_priv *np = netdev_priv(dev); @@ -2623,187 +3165,702 @@ static int nv_set_tso(struct net_device if ((np->driver_data & DEV_HAS_CHECKSUM)) return ethtool_op_set_tso(dev, value); else - return value ? -EOPNOTSUPP : 0; + return -EOPNOTSUPP; } -#endif -static struct ethtool_ops ops = { - .get_drvinfo = nv_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_wol = nv_get_wol, - .set_wol = nv_set_wol, - .get_settings = nv_get_settings, - .set_settings = nv_set_settings, - .get_regs_len = nv_get_regs_len, - .get_regs = nv_get_regs, - .nway_reset = nv_nway_reset, - .get_perm_addr = ethtool_op_get_perm_addr, -#ifdef NETIF_F_TSO - .get_tso = ethtool_op_get_tso, - .set_tso = nv_set_tso -#endif -}; +static void nv_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring) +{ + struct fe_priv *np = netdev_priv(dev); -static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) + ring->rx_max_pending = (np->desc_ver == DESC_VER_1) ? RING_MAX_DESC_VER_1 : RING_MAX_DESC_VER_2_3; + ring->rx_mini_max_pending = 0; + ring->rx_jumbo_max_pending = 0; + ring->tx_max_pending = (np->desc_ver == DESC_VER_1) ? RING_MAX_DESC_VER_1 : RING_MAX_DESC_VER_2_3; + + ring->rx_pending = np->rx_ring_size; + ring->rx_mini_pending = 0; + ring->rx_jumbo_pending = 0; + ring->tx_pending = np->tx_ring_size; +} + +static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ring) { - struct fe_priv *np = get_nvpriv(dev); + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + u8 *rxtx_ring, *rx_skbuff, *tx_skbuff, *rx_dma, *tx_dma, *tx_dma_len; + dma_addr_t ring_addr; - spin_lock_irq(&np->lock); + if (ring->rx_pending < RX_RING_MIN || + ring->tx_pending < TX_RING_MIN || + ring->rx_mini_pending != 0 || + ring->rx_jumbo_pending != 0 || + (np->desc_ver == DESC_VER_1 && + (ring->rx_pending > RING_MAX_DESC_VER_1 || + ring->tx_pending > RING_MAX_DESC_VER_1)) || + (np->desc_ver != DESC_VER_1 && + (ring->rx_pending > RING_MAX_DESC_VER_2_3 || + ring->tx_pending > RING_MAX_DESC_VER_2_3))) { + return -EINVAL; + } - /* save vlan group */ - np->vlangrp = grp; + /* allocate new rings */ + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + rxtx_ring = pci_alloc_consistent(np->pci_dev, + sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending), + &ring_addr); + } else { + rxtx_ring = pci_alloc_consistent(np->pci_dev, + sizeof(struct ring_desc_ex) * (ring->rx_pending + ring->tx_pending), + &ring_addr); + } + rx_skbuff = kmalloc(sizeof(struct sk_buff*) * ring->rx_pending, GFP_KERNEL); + rx_dma = kmalloc(sizeof(dma_addr_t) * ring->rx_pending, GFP_KERNEL); + tx_skbuff = kmalloc(sizeof(struct sk_buff*) * ring->tx_pending, GFP_KERNEL); + tx_dma = kmalloc(sizeof(dma_addr_t) * ring->tx_pending, GFP_KERNEL); + tx_dma_len = kmalloc(sizeof(unsigned int) * ring->tx_pending, GFP_KERNEL); + if (!rxtx_ring || !rx_skbuff || !rx_dma || !tx_skbuff || !tx_dma || !tx_dma_len) { + /* fall back to old rings */ + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + if(rxtx_ring) + pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending), + rxtx_ring, ring_addr); + } else { + if (rxtx_ring) + pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (ring->rx_pending + ring->tx_pending), + rxtx_ring, ring_addr); + } + if (rx_skbuff) + kfree(rx_skbuff); + if (rx_dma) + kfree(rx_dma); + if (tx_skbuff) + kfree(tx_skbuff); + if (tx_dma) + kfree(tx_dma); + if (tx_dma_len) + kfree(tx_dma_len); + goto exit; + } - if (grp) { - /* enable vlan on MAC */ - np->txrxctl_bits |= NVREG_TXRXCTL_VLANSTRIP | NVREG_TXRXCTL_VLANINS; + if (netif_running(dev)) { + nv_disable_irq(dev); + netif_tx_lock_bh(dev); + spin_lock(&np->lock); + /* stop engines */ + nv_stop_rx(dev); + nv_stop_tx(dev); + nv_txrx_reset(dev); + /* drain queues */ + nv_drain_rx(dev); + nv_drain_tx(dev); + /* delete queues */ + free_rings(dev); + } + + /* set new values */ + np->rx_ring_size = ring->rx_pending; + np->tx_ring_size = ring->tx_pending; + np->tx_limit_stop = ring->tx_pending - TX_LIMIT_DIFFERENCE; + np->tx_limit_start = ring->tx_pending - TX_LIMIT_DIFFERENCE - 1; + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + np->rx_ring.orig = (struct ring_desc*)rxtx_ring; + np->tx_ring.orig = &np->rx_ring.orig[np->rx_ring_size]; } else { - /* disable vlan on MAC */ - np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANSTRIP; - np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANINS; + np->rx_ring.ex = (struct ring_desc_ex*)rxtx_ring; + np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size]; } + np->rx_skbuff = (struct sk_buff**)rx_skbuff; + np->rx_dma = (dma_addr_t*)rx_dma; + np->tx_skbuff = (struct sk_buff**)tx_skbuff; + np->tx_dma = (dma_addr_t*)tx_dma; + np->tx_dma_len = (unsigned int*)tx_dma_len; + np->ring_addr = ring_addr; + + memset(np->rx_skbuff, 0, sizeof(struct sk_buff*) * np->rx_ring_size); + memset(np->rx_dma, 0, sizeof(dma_addr_t) * np->rx_ring_size); + memset(np->tx_skbuff, 0, sizeof(struct sk_buff*) * np->tx_ring_size); + memset(np->tx_dma, 0, sizeof(dma_addr_t) * np->tx_ring_size); + memset(np->tx_dma_len, 0, sizeof(unsigned int) * np->tx_ring_size); - writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); + if (netif_running(dev)) { + /* reinit driver view of the queues */ + set_bufsize(dev); + if (nv_init_ring(dev)) { + if (!np->in_shutdown) + mod_timer(&np->oom_kick, jiffies + OOM_REFILL); + } - spin_unlock_irq(&np->lock); -}; + /* reinit nic view of the queues */ + writel(np->rx_buf_sz, base + NvRegOffloadConfig); + setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); + writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), + base + NvRegRingSizes); + pci_push(base); + writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); + pci_push(base); -static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) + /* restart engines */ + nv_start_rx(dev); + nv_start_tx(dev); + spin_unlock(&np->lock); + netif_tx_unlock_bh(dev); + nv_enable_irq(dev); + } + return 0; +exit: + return -ENOMEM; +} + +static void nv_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam* pause) { - /* nothing to do */ -}; + struct fe_priv *np = netdev_priv(dev); -static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask) + pause->autoneg = (np->pause_flags & NV_PAUSEFRAME_AUTONEG) != 0; + pause->rx_pause = (np->pause_flags & NV_PAUSEFRAME_RX_ENABLE) != 0; + pause->tx_pause = (np->pause_flags & NV_PAUSEFRAME_TX_ENABLE) != 0; +} + +static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam* pause) +{ + struct fe_priv *np = netdev_priv(dev); + int adv, bmcr; + + if ((!np->autoneg && np->duplex == 0) || + (np->autoneg && !pause->autoneg && np->duplex == 0)) { + printk(KERN_INFO "%s: can not set pause settings when forced link is in half duplex.\n", + dev->name); + return -EINVAL; + } + if (pause->tx_pause && !(np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE)) { + printk(KERN_INFO "%s: hardware does not support tx pause frames.\n", dev->name); + return -EINVAL; + } + + netif_carrier_off(dev); + if (netif_running(dev)) { + nv_disable_irq(dev); + netif_tx_lock_bh(dev); + spin_lock(&np->lock); + /* stop engines */ + nv_stop_rx(dev); + nv_stop_tx(dev); + spin_unlock(&np->lock); + netif_tx_unlock_bh(dev); + } + + np->pause_flags &= ~(NV_PAUSEFRAME_RX_REQ|NV_PAUSEFRAME_TX_REQ); + if (pause->rx_pause) + np->pause_flags |= NV_PAUSEFRAME_RX_REQ; + if (pause->tx_pause) + np->pause_flags |= NV_PAUSEFRAME_TX_REQ; + + if (np->autoneg && pause->autoneg) { + np->pause_flags |= NV_PAUSEFRAME_AUTONEG; + + adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); + adv &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) /* for rx we set both advertisments but disable tx pause */ + adv |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + if (np->pause_flags & NV_PAUSEFRAME_TX_REQ) + adv |= ADVERTISE_PAUSE_ASYM; + mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv); + + if (netif_running(dev)) + printk(KERN_INFO "%s: link down.\n", dev->name); + bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); + bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); + mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); + } else { + np->pause_flags &= ~(NV_PAUSEFRAME_AUTONEG|NV_PAUSEFRAME_RX_ENABLE|NV_PAUSEFRAME_TX_ENABLE); + if (pause->rx_pause) + np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE; + if (pause->tx_pause) + np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE; + + if (!netif_running(dev)) + nv_update_linkspeed(dev); + else + nv_update_pause(dev, np->pause_flags); + } + + if (netif_running(dev)) { + nv_start_rx(dev); + nv_start_tx(dev); + nv_enable_irq(dev); + } + return 0; +} + +static u32 nv_get_rx_csum(struct net_device *dev) +{ + struct fe_priv *np = netdev_priv(dev); + return (np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) != 0; +} + +static int nv_set_rx_csum(struct net_device *dev, u32 data) { + struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - int i; - u32 msixmap = 0; + int retcode = 0; - /* Each interrupt bit can be mapped to a MSIX vector (4 bits). - * MSIXMap0 represents the first 8 interrupts and MSIXMap1 represents - * the remaining 8 interrupts. - */ - for (i = 0; i < 8; i++) { - if ((irqmask >> i) & 0x1) { - msixmap |= vector << (i << 2); + if (np->driver_data & DEV_HAS_CHECKSUM) { + + if (((np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) && data) || + (!(np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) && !data)) { + /* already set or unset */ + return 0; } - } - writel(readl(base + NvRegMSIXMap0) | msixmap, base + NvRegMSIXMap0); - msixmap = 0; - for (i = 0; i < 8; i++) { - if ((irqmask >> (i + 8)) & 0x1) { - msixmap |= vector << (i << 2); + if (data) { + np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; + } else if (!(np->vlanctl_bits & NVREG_VLANCONTROL_ENABLE)) { + np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK; + } else { + printk(KERN_INFO "Can not disable rx checksum if vlan is enabled\n"); + return -EINVAL; } + + if (netif_running(dev)) { + spin_lock_irq(&np->lock); + writel(np->txrxctl_bits, base + NvRegTxRxControl); + spin_unlock_irq(&np->lock); + } + } else { + return -EINVAL; } - writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1); + + return retcode; } -static int nv_request_irq(struct net_device *dev) +static int nv_set_tx_csum(struct net_device *dev, u32 data) { - struct fe_priv *np = get_nvpriv(dev); + struct fe_priv *np = netdev_priv(dev); + + if (np->driver_data & DEV_HAS_CHECKSUM) + return ethtool_op_set_tx_hw_csum(dev, data); + else + return -EOPNOTSUPP; +} + +static int nv_set_sg(struct net_device *dev, u32 data) +{ + struct fe_priv *np = netdev_priv(dev); + + if (np->driver_data & DEV_HAS_CHECKSUM) + return ethtool_op_set_sg(dev, data); + else + return -EOPNOTSUPP; +} + +static int nv_get_stats_count(struct net_device *dev) +{ + struct fe_priv *np = netdev_priv(dev); + + if (np->driver_data & DEV_HAS_STATISTICS) + return (sizeof(struct nv_ethtool_stats)/sizeof(u64)); + else + return 0; +} + +static void nv_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *estats, u64 *buffer) +{ + struct fe_priv *np = netdev_priv(dev); + + /* update stats */ + nv_do_stats_poll((unsigned long)dev); + + memcpy(buffer, &np->estats, nv_get_stats_count(dev)*sizeof(u64)); +} + +static int nv_self_test_count(struct net_device *dev) +{ + struct fe_priv *np = netdev_priv(dev); + + if (np->driver_data & DEV_HAS_TEST_EXTENDED) + return NV_TEST_COUNT_EXTENDED; + else + return NV_TEST_COUNT_BASE; +} + +static int nv_link_test(struct net_device *dev) +{ + struct fe_priv *np = netdev_priv(dev); + int mii_status; + + mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ); + mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ); + + /* check phy link status */ + if (!(mii_status & BMSR_LSTATUS)) + return 0; + else + return 1; +} + +static int nv_register_test(struct net_device *dev) +{ + u8 __iomem *base = get_hwbase(dev); + int i = 0; + u32 orig_read, new_read; + + do { + orig_read = readl(base + nv_registers_test[i].reg); + + /* xor with mask to toggle bits */ + orig_read ^= nv_registers_test[i].mask; + + writel(orig_read, base + nv_registers_test[i].reg); + + new_read = readl(base + nv_registers_test[i].reg); + + if ((new_read & nv_registers_test[i].mask) != (orig_read & nv_registers_test[i].mask)) + return 0; + + /* restore original value */ + orig_read ^= nv_registers_test[i].mask; + writel(orig_read, base + nv_registers_test[i].reg); + + } while (nv_registers_test[++i].reg != 0); + + return 1; +} + +static int nv_interrupt_test(struct net_device *dev) +{ + struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); int ret = 1; - int i; + int testcnt; + u32 save_msi_flags, save_poll_interval = 0; - if (np->msi_flags & NV_MSI_X_CAPABLE) { - for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { - np->msi_x_entry[i].entry = i; + if (netif_running(dev)) { + /* free current irq */ + nv_free_irq(dev); + save_poll_interval = readl(base+NvRegPollingInterval); + } + + /* flag to test interrupt handler */ + np->intr_test = 0; + + /* setup test irq */ + save_msi_flags = np->msi_flags; + np->msi_flags &= ~NV_MSI_X_VECTORS_MASK; + np->msi_flags |= 0x001; /* setup 1 vector */ + if (nv_request_irq(dev, 1)) + return 0; + + /* setup timer interrupt */ + writel(NVREG_POLL_DEFAULT_CPU, base + NvRegPollingInterval); + writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6); + + nv_enable_hw_interrupts(dev, NVREG_IRQ_TIMER); + + /* wait for at least one interrupt */ + msleep(100); + + spin_lock_irq(&np->lock); + + /* flag should be set within ISR */ + testcnt = np->intr_test; + if (!testcnt) + ret = 2; + + nv_disable_hw_interrupts(dev, NVREG_IRQ_TIMER); + if (!(np->msi_flags & NV_MSI_X_ENABLED)) + writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); + else + writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); + + spin_unlock_irq(&np->lock); + + nv_free_irq(dev); + + np->msi_flags = save_msi_flags; + + if (netif_running(dev)) { + writel(save_poll_interval, base + NvRegPollingInterval); + writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6); + /* restore original irq */ + if (nv_request_irq(dev, 0)) + return 0; + } + + return ret; +} + +static int nv_loopback_test(struct net_device *dev) +{ + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + struct sk_buff *tx_skb, *rx_skb; + dma_addr_t test_dma_addr; + u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET); + u32 Flags; + int len, i, pkt_len; + u8 *pkt_data; + u32 filter_flags = 0; + u32 misc1_flags = 0; + int ret = 1; + + if (netif_running(dev)) { + nv_disable_irq(dev); + filter_flags = readl(base + NvRegPacketFilterFlags); + misc1_flags = readl(base + NvRegMisc1); + } else { + nv_txrx_reset(dev); + } + + /* reinit driver view of the rx queue */ + set_bufsize(dev); + nv_init_ring(dev); + + /* setup hardware for loopback */ + writel(NVREG_MISC1_FORCE, base + NvRegMisc1); + writel(NVREG_PFF_ALWAYS | NVREG_PFF_LOOPBACK, base + NvRegPacketFilterFlags); + + /* reinit nic view of the rx queue */ + writel(np->rx_buf_sz, base + NvRegOffloadConfig); + setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); + writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), + base + NvRegRingSizes); + pci_push(base); + + /* restart rx engine */ + nv_start_rx(dev); + nv_start_tx(dev); + + /* setup packet for tx */ + pkt_len = ETH_DATA_LEN; + tx_skb = dev_alloc_skb(pkt_len); + pkt_data = skb_put(tx_skb, pkt_len); + for (i = 0; i < pkt_len; i++) + pkt_data[i] = (u8)(i & 0xff); + test_dma_addr = pci_map_single(np->pci_dev, tx_skb->data, + tx_skb->end-tx_skb->data, PCI_DMA_FROMDEVICE); + + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + np->tx_ring.orig[0].PacketBuffer = cpu_to_le32(test_dma_addr); + np->tx_ring.orig[0].FlagLen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra); + } else { + np->tx_ring.ex[0].PacketBufferHigh = cpu_to_le64(test_dma_addr) >> 32; + np->tx_ring.ex[0].PacketBufferLow = cpu_to_le64(test_dma_addr) & 0x0FFFFFFFF; + np->tx_ring.ex[0].FlagLen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra); + } + writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); + pci_push(get_hwbase(dev)); + + msleep(500); + + /* check for rx of the packet */ + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + Flags = le32_to_cpu(np->rx_ring.orig[0].FlagLen); + len = nv_descr_getlength(&np->rx_ring.orig[0], np->desc_ver); + + } else { + Flags = le32_to_cpu(np->rx_ring.ex[0].FlagLen); + len = nv_descr_getlength_ex(&np->rx_ring.ex[0], np->desc_ver); + } + + if (Flags & NV_RX_AVAIL) { + ret = 0; + } else if (np->desc_ver == DESC_VER_1) { + if (Flags & NV_RX_ERROR) + ret = 0; + } else { + if (Flags & NV_RX2_ERROR) { + ret = 0; } - if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) { - np->msi_flags |= NV_MSI_X_ENABLED; - if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) { - /* Request irq for rx handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_err; - } - /* Request irq for tx handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_free_rx; - } - /* Request irq for link and timer handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_free_tx; - } - /* map interrupts to their respective vector */ - writel(0, base + NvRegMSIXMap0); - writel(0, base + NvRegMSIXMap1); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER); - } else { - /* Request irq for all interrupts */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_err; - } + } - /* map interrupts to vector 0 */ - writel(0, base + NvRegMSIXMap0); - writel(0, base + NvRegMSIXMap1); + if (ret) { + if (len != pkt_len) { + ret = 0; + dprintk(KERN_DEBUG "%s: loopback len mismatch %d vs %d\n", + dev->name, len, pkt_len); + } else { + rx_skb = np->rx_skbuff[0]; + for (i = 0; i < pkt_len; i++) { + if (rx_skb->data[i] != (u8)(i & 0xff)) { + ret = 0; + dprintk(KERN_DEBUG "%s: loopback pattern check failed on byte %d\n", + dev->name, i); + break; + } } } + } else { + dprintk(KERN_DEBUG "%s: loopback - did not receive test packet\n", dev->name); } - if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { - if ((ret = pci_enable_msi(np->pci_dev)) == 0) { - np->msi_flags |= NV_MSI_ENABLED; - if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); - pci_disable_msi(np->pci_dev); - np->msi_flags &= ~NV_MSI_ENABLED; - goto out_err; + + pci_unmap_page(np->pci_dev, test_dma_addr, + tx_skb->end-tx_skb->data, + PCI_DMA_TODEVICE); + dev_kfree_skb_any(tx_skb); + + /* stop engines */ + nv_stop_rx(dev); + nv_stop_tx(dev); + nv_txrx_reset(dev); + /* drain rx queue */ + nv_drain_rx(dev); + nv_drain_tx(dev); + + if (netif_running(dev)) { + writel(misc1_flags, base + NvRegMisc1); + writel(filter_flags, base + NvRegPacketFilterFlags); + nv_enable_irq(dev); + } + + return ret; +} + +static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 *buffer) +{ + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + int result; + memset(buffer, 0, nv_self_test_count(dev)*sizeof(u64)); + + if (!nv_link_test(dev)) { + test->flags |= ETH_TEST_FL_FAILED; + buffer[0] = 1; + } + + if (test->flags & ETH_TEST_FL_OFFLINE) { + if (netif_running(dev)) { + netif_stop_queue(dev); + netif_tx_lock_bh(dev); + spin_lock_irq(&np->lock); + nv_disable_hw_interrupts(dev, np->irqmask); + if (!(np->msi_flags & NV_MSI_X_ENABLED)) { + writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); + } else { + writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); } + /* stop engines */ + nv_stop_rx(dev); + nv_stop_tx(dev); + nv_txrx_reset(dev); + /* drain rx queue */ + nv_drain_rx(dev); + nv_drain_tx(dev); + spin_unlock_irq(&np->lock); + netif_tx_unlock_bh(dev); + } - /* map interrupts to vector 0 */ - writel(0, base + NvRegMSIMap0); - writel(0, base + NvRegMSIMap1); - /* enable msi vector 0 */ - writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); + if (!nv_register_test(dev)) { + test->flags |= ETH_TEST_FL_FAILED; + buffer[1] = 1; + } + + result = nv_interrupt_test(dev); + if (result != 1) { + test->flags |= ETH_TEST_FL_FAILED; + buffer[2] = 1; + } + if (result == 0) { + /* bail out */ + return; + } + + if (!nv_loopback_test(dev)) { + test->flags |= ETH_TEST_FL_FAILED; + buffer[3] = 1; + } + + if (netif_running(dev)) { + /* reinit driver view of the rx queue */ + set_bufsize(dev); + if (nv_init_ring(dev)) { + if (!np->in_shutdown) + mod_timer(&np->oom_kick, jiffies + OOM_REFILL); + } + /* reinit nic view of the rx queue */ + writel(np->rx_buf_sz, base + NvRegOffloadConfig); + setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); + writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), + base + NvRegRingSizes); + pci_push(base); + writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); + pci_push(base); + /* restart rx engine */ + nv_start_rx(dev); + nv_start_tx(dev); + netif_start_queue(dev); + nv_enable_hw_interrupts(dev, np->irqmask); } } - if (ret != 0) { - if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) - goto out_err; - } +} - return 0; -out_free_tx: - free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev); -out_free_rx: - free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev); -out_err: - return 1; +static void nv_get_strings(struct net_device *dev, u32 stringset, u8 *buffer) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(buffer, &nv_estats_str, nv_get_stats_count(dev)*sizeof(struct nv_ethtool_str)); + break; + case ETH_SS_TEST: + memcpy(buffer, &nv_etests_str, nv_self_test_count(dev)*sizeof(struct nv_ethtool_str)); + break; + } } -static void nv_free_irq(struct net_device *dev) +static struct ethtool_ops ops = { + .get_drvinfo = nv_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_wol = nv_get_wol, + .set_wol = nv_set_wol, + .get_settings = nv_get_settings, + .set_settings = nv_set_settings, + .get_regs_len = nv_get_regs_len, + .get_regs = nv_get_regs, + .nway_reset = nv_nway_reset, + .get_perm_addr = ethtool_op_get_perm_addr, + .get_tso = ethtool_op_get_tso, + .set_tso = nv_set_tso, + .get_ringparam = nv_get_ringparam, + .set_ringparam = nv_set_ringparam, + .get_pauseparam = nv_get_pauseparam, + .set_pauseparam = nv_set_pauseparam, + .get_rx_csum = nv_get_rx_csum, + .set_rx_csum = nv_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = nv_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = nv_set_sg, + .get_strings = nv_get_strings, + .get_stats_count = nv_get_stats_count, + .get_ethtool_stats = nv_get_ethtool_stats, + .self_test_count = nv_self_test_count, + .self_test = nv_self_test, +}; + +static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { struct fe_priv *np = get_nvpriv(dev); - int i; - if (np->msi_flags & NV_MSI_X_ENABLED) { - for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { - free_irq(np->msi_x_entry[i].vector, dev); - } - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; + spin_lock_irq(&np->lock); + + /* save vlan group */ + np->vlangrp = grp; + + if (grp) { + /* enable vlan on MAC */ + np->txrxctl_bits |= NVREG_TXRXCTL_VLANSTRIP | NVREG_TXRXCTL_VLANINS; } else { - free_irq(np->pci_dev->irq, dev); - if (np->msi_flags & NV_MSI_ENABLED) { - pci_disable_msi(np->pci_dev); - np->msi_flags &= ~NV_MSI_ENABLED; - } + /* disable vlan on MAC */ + np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANSTRIP; + np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANINS; } -} + + writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); + + spin_unlock_irq(&np->lock); +}; + +static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +{ + /* nothing to do */ +}; static int nv_open(struct net_device *dev) { @@ -2829,6 +3886,9 @@ static int nv_open(struct net_device *de writel(0, base + NvRegAdapterControl); + if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE) + writel(NVREG_TX_PAUSEFRAME_DISABLE, base + NvRegTxPauseFrame); + /* 2) initialize descriptor rings */ set_bufsize(dev); oom = nv_init_ring(dev); @@ -2845,7 +3905,7 @@ static int nv_open(struct net_device *de /* 4) give hw rings */ setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); - writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT), + writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes); /* 5) continue setup */ @@ -2887,7 +3947,8 @@ static int nv_open(struct net_device *de base + NvRegAdapterControl); writel(NVREG_MIISPEED_BIT8|NVREG_MIIDELAY, base + NvRegMIISpeed); writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4); - writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags); + if (np->wolenabled) + writel(NVREG_WAKEUPFLAGS_ENABLE , base + NvRegWakeUpFlags); i = readl(base + NvRegPowerState); if ( (i & NVREG_POWERSTATE_POWEREDUP) == 0) @@ -2903,7 +3964,7 @@ static int nv_open(struct net_device *de writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); pci_push(base); - if (nv_request_irq(dev)) { + if (nv_request_irq(dev, 0)) { goto out_drain; } @@ -2940,6 +4001,11 @@ static int nv_open(struct net_device *de } if (oom) mod_timer(&np->oom_kick, jiffies + OOM_REFILL); + + /* start statistics timer */ + if (np->driver_data & DEV_HAS_STATISTICS) + mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL); + spin_unlock_irq(&np->lock); return 0; @@ -2960,6 +4026,7 @@ static int nv_close(struct net_device *d del_timer_sync(&np->oom_kick); del_timer_sync(&np->nic_poll); + del_timer_sync(&np->stats_poll); netif_stop_queue(dev); spin_lock_irq(&np->lock); @@ -3019,6 +4086,9 @@ static int __devinit nv_probe(struct pci init_timer(&np->nic_poll); np->nic_poll.data = (unsigned long) dev; np->nic_poll.function = &nv_do_nic_poll; /* timer handler */ + init_timer(&np->stats_poll); + np->stats_poll.data = (unsigned long) dev; + np->stats_poll.function = &nv_do_stats_poll; /* timer handler */ err = pci_enable_device(pci_dev); if (err) { @@ -3033,7 +4103,7 @@ static int __devinit nv_probe(struct pci if (err < 0) goto out_disable; - if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL)) + if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS)) np->register_size = NV_PCI_REGSZ_VER2; else np->register_size = NV_PCI_REGSZ_VER1; @@ -3065,16 +4135,18 @@ static int __devinit nv_probe(struct pci /* packet format 3: supports 40-bit addressing */ np->desc_ver = DESC_VER_3; np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; - if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) { - printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", - pci_name(pci_dev)); - } else { - dev->features |= NETIF_F_HIGHDMA; - printk(KERN_INFO "forcedeth: using HIGHDMA\n"); - } - if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) { - printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n", - pci_name(pci_dev)); + if (dma_64bit) { + if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) { + printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", + pci_name(pci_dev)); + } else { + dev->features |= NETIF_F_HIGHDMA; + printk(KERN_INFO "forcedeth: using HIGHDMA\n"); + } + if (pci_set_consistent_dma_mask(pci_dev, DMA_39BIT_MASK)) { + printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed, using 32-bit ring buffers for device %s.\n", + pci_name(pci_dev)); + } } } else if (id->driver_data & DEV_HAS_LARGEDESC) { /* packet format 2: supports jumbo frames */ @@ -3107,13 +4179,19 @@ #endif } np->msi_flags = 0; - if ((id->driver_data & DEV_HAS_MSI) && !disable_msi) { + if ((id->driver_data & DEV_HAS_MSI) && msi) { np->msi_flags |= NV_MSI_CAPABLE; } - if ((id->driver_data & DEV_HAS_MSI_X) && !disable_msix) { + if ((id->driver_data & DEV_HAS_MSI_X) && msix) { np->msi_flags |= NV_MSI_X_CAPABLE; } + np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG; + if (id->driver_data & DEV_HAS_PAUSEFRAME_TX) { + np->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE | NV_PAUSEFRAME_TX_REQ; + } + + err = -ENOMEM; np->base = ioremap(addr, np->register_size); if (!np->base) @@ -3122,21 +4200,38 @@ #endif dev->irq = pci_dev->irq; + np->rx_ring_size = RX_RING_DEFAULT; + np->tx_ring_size = TX_RING_DEFAULT; + np->tx_limit_stop = np->tx_ring_size - TX_LIMIT_DIFFERENCE; + np->tx_limit_start = np->tx_ring_size - TX_LIMIT_DIFFERENCE - 1; + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { np->rx_ring.orig = pci_alloc_consistent(pci_dev, - sizeof(struct ring_desc) * (RX_RING + TX_RING), + sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size), &np->ring_addr); if (!np->rx_ring.orig) goto out_unmap; - np->tx_ring.orig = &np->rx_ring.orig[RX_RING]; + np->tx_ring.orig = &np->rx_ring.orig[np->rx_ring_size]; } else { np->rx_ring.ex = pci_alloc_consistent(pci_dev, - sizeof(struct ring_desc_ex) * (RX_RING + TX_RING), + sizeof(struct ring_desc_ex) * (np->rx_ring_size + np->tx_ring_size), &np->ring_addr); if (!np->rx_ring.ex) goto out_unmap; - np->tx_ring.ex = &np->rx_ring.ex[RX_RING]; + np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size]; } + np->rx_skbuff = kmalloc(sizeof(struct sk_buff*) * np->rx_ring_size, GFP_KERNEL); + np->rx_dma = kmalloc(sizeof(dma_addr_t) * np->rx_ring_size, GFP_KERNEL); + np->tx_skbuff = kmalloc(sizeof(struct sk_buff*) * np->tx_ring_size, GFP_KERNEL); + np->tx_dma = kmalloc(sizeof(dma_addr_t) * np->tx_ring_size, GFP_KERNEL); + np->tx_dma_len = kmalloc(sizeof(unsigned int) * np->tx_ring_size, GFP_KERNEL); + if (!np->rx_skbuff || !np->rx_dma || !np->tx_skbuff || !np->tx_dma || !np->tx_dma_len) + goto out_freering; + memset(np->rx_skbuff, 0, sizeof(struct sk_buff*) * np->rx_ring_size); + memset(np->rx_dma, 0, sizeof(dma_addr_t) * np->rx_ring_size); + memset(np->tx_skbuff, 0, sizeof(struct sk_buff*) * np->tx_ring_size); + memset(np->tx_dma, 0, sizeof(dma_addr_t) * np->tx_ring_size); + memset(np->tx_dma_len, 0, sizeof(unsigned int) * np->tx_ring_size); dev->open = nv_open; dev->stop = nv_close; @@ -3258,9 +4353,9 @@ #endif if (i == 33) { printk(KERN_INFO "%s: open: Could not find a valid PHY.\n", pci_name(pci_dev)); - goto out_freering; + goto out_error; } - + /* reset it */ phy_init(dev); @@ -3272,7 +4367,7 @@ #endif err = register_netdev(dev); if (err) { printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err); - goto out_freering; + goto out_error; } printk(KERN_INFO "%s: forcedeth.c: subsystem: %05x:%04x bound to %s\n", dev->name, pci_dev->subsystem_vendor, pci_dev->subsystem_device, @@ -3280,14 +4375,10 @@ #endif return 0; -out_freering: - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), - np->rx_ring.orig, np->ring_addr); - else - pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING), - np->rx_ring.ex, np->ring_addr); +out_error: pci_set_drvdata(pci_dev, NULL); +out_freering: + free_rings(dev); out_unmap: iounmap(get_hwbase(dev)); out_relreg: @@ -3303,15 +4394,11 @@ out: static void __devexit nv_remove(struct pci_dev *pci_dev) { struct net_device *dev = pci_get_drvdata(pci_dev); - struct fe_priv *np = netdev_priv(dev); unregister_netdev(dev); /* free all structures */ - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), np->rx_ring.orig, np->ring_addr); - else - pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING), np->rx_ring.ex, np->ring_addr); + free_rings(dev); iounmap(get_hwbase(dev)); pci_release_regions(pci_dev); pci_disable_device(pci_dev); @@ -3374,11 +4461,43 @@ static struct pci_device_id pci_tbl[] = }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + }, + { /* MCP61 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + }, + { /* MCP61 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + }, + { /* MCP61 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + }, + { /* MCP61 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + }, + { /* MCP65 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + }, + { /* MCP65 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + }, + { /* MCP65 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + }, + { /* MCP65 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, }, {0,}, }; @@ -3408,10 +4527,12 @@ module_param(optimization_mode, int, 0); MODULE_PARM_DESC(optimization_mode, "In throughput mode (0), every tx & rx packet will generate an interrupt. In CPU mode (1), interrupts are controlled by a timer."); module_param(poll_interval, int, 0); MODULE_PARM_DESC(poll_interval, "Interval determines how frequent timer interrupt is generated by [(time_in_micro_secs * 100) / (2^10)]. Min is 0 and Max is 65535."); -module_param(disable_msi, int, 0); -MODULE_PARM_DESC(disable_msi, "Disable MSI interrupts by setting to 1."); -module_param(disable_msix, int, 0); -MODULE_PARM_DESC(disable_msix, "Disable MSIX interrupts by setting to 1."); +module_param(msi, int, 0); +MODULE_PARM_DESC(msi, "MSI interrupts are enabled by setting to 1 and disabled by setting to 0."); +module_param(msix, int, 0); +MODULE_PARM_DESC(msix, "MSIX interrupts are enabled by setting to 1 and disabled by setting to 0."); +module_param(dma_64bit, int, 0); +MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0."); MODULE_AUTHOR("Manfred Spraul "); MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver"); diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 102c1f0..d12605f 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -308,9 +308,9 @@ static int sp_set_mac_address(struct net { struct sockaddr_ax25 *sa = addr; - spin_lock_irq(&dev->xmit_lock); + netif_tx_lock_bh(dev); memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + netif_tx_unlock_bh(dev); return 0; } @@ -767,9 +767,9 @@ static int sixpack_ioctl(struct tty_stru break; } - spin_lock_irq(&dev->xmit_lock); + netif_tx_lock_bh(dev); memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + netif_tx_unlock_bh(dev); err = 0; break; diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index d81a8e1..3ebbbe5 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -357,9 +357,9 @@ static int ax_set_mac_address(struct net { struct sockaddr_ax25 *sa = addr; - spin_lock_irq(&dev->xmit_lock); + netif_tx_lock_bh(dev); memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + netif_tx_unlock_bh(dev); return 0; } @@ -886,9 +886,9 @@ static int mkiss_ioctl(struct tty_struct break; } - spin_lock_irq(&dev->xmit_lock); + netif_tx_lock_bh(dev); memcpy(dev->dev_addr, addr, AX25_ADDR_LEN); - spin_unlock_irq(&dev->xmit_lock); + netif_tx_unlock_bh(dev); err = 0; break; diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index 0d7a625..e26a3e4 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c @@ -446,7 +446,7 @@ MODULE_LICENSE("GPL"); /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ -int +int __init init_module(void) { struct net_device *dev; diff --git a/drivers/net/hp.c b/drivers/net/hp.c index cf9fb36..551a71b 100644 --- a/drivers/net/hp.c +++ b/drivers/net/hp.c @@ -384,7 +384,7 @@ #endif } /* This function resets the ethercard if something screws up. */ -static void +static void __init hp_init_card(struct net_device *dev) { int irq = dev->irq; @@ -409,7 +409,7 @@ MODULE_LICENSE("GPL"); /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ -int +int __init init_module(void) { struct net_device *dev; diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 247c8ca..dd1dc32 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -1487,11 +1487,8 @@ #endif if (skb->len <= 0) return 0; - if (skb->len < ETH_ZLEN && lp->chip == HP100_CHIPID_SHASTA) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; - } + if (lp->chip == HP100_CHIPID_SHASTA && skb_padto(skb, ETH_ZLEN)) + return 0; /* Get Tx ring tail pointer */ if (lp->txrtail->next == lp->txrhead) { diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index 01ad904..51fd516 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -1,4 +1,4 @@ -/* +/* net-3-driver for the IBM LAN Adapter/A This is an extension to the Linux operating system, and is covered by the @@ -11,9 +11,9 @@ This driver is based both on the SK_MCA SK_G16 and 3C523 driver. paper sources: - 'PC Hardware: Aufbau, Funktionsweise, Programmierung' by + 'PC Hardware: Aufbau, Funktionsweise, Programmierung' by Hans-Peter Messmer for the basic Microchannel stuff - + 'Linux Geraetetreiber' by Allesandro Rubini, Kalle Dalheimer for help on Ethernet driver programming @@ -27,14 +27,14 @@ paper sources: special acknowledgements to: - Bob Eager for helping me out with documentation from IBM - - Jim Shorney for his endless patience with me while I was using + - Jim Shorney for his endless patience with me while I was using him as a beta tester to trace down the address filter bug ;-) Missing things: -> set debug level via ioctl instead of compile-time switches -> I didn't follow the development of the 2.1.x kernels, so my - assumptions about which things changed with which kernel version + assumptions about which things changed with which kernel version are probably nonsense History: @@ -275,7 +275,7 @@ static void InitDscrs(struct net_device priv->rrastart = raddr = priv->txbufstart + (TXBUFCNT * PKTSIZE); priv->rdastart = addr = priv->rrastart + (priv->rxbufcnt * sizeof(rra_t)); priv->rxbufstart = baddr = priv->rdastart + (priv->rxbufcnt * sizeof(rda_t)); - + for (z = 0; z < priv->rxbufcnt; z++) { rra.startlo = baddr; rra.starthi = 0; @@ -570,7 +570,7 @@ static void irqrx_handler(struct net_dev lrdaaddr = priv->rdastart + (priv->lastrxdescr * sizeof(rda_t)); memcpy_fromio(&rda, priv->base + rdaaddr, sizeof(rda_t)); - /* iron out upper word halves of fields we use - SONIC will duplicate + /* iron out upper word halves of fields we use - SONIC will duplicate bits 0..15 to 16..31 */ rda.status &= 0xffff; @@ -836,9 +836,9 @@ static int ibmlana_tx(struct sk_buff *sk baddr = priv->txbufstart + (priv->nexttxdescr * PKTSIZE); memcpy_toio(priv->base + baddr, skb->data, skb->len); - /* copy filler into RAM - in case we're filling up... + /* copy filler into RAM - in case we're filling up... we're filling a bit more than necessary, but that doesn't harm - since the buffer is far larger... + since the buffer is far larger... Sorry Linus for the filler string but I couldn't resist ;-) */ if (tmplen > skb->len) { @@ -952,7 +952,7 @@ static int ibmlana_probe(struct net_devi priv->realirq = irq; priv->medium = medium; spin_lock_init(&priv->lock); - + /* set base + irq for this device (irq not allocated so far) */ diff --git a/drivers/net/ibmlana.h b/drivers/net/ibmlana.h index 458ee22..6b58bab 100644 --- a/drivers/net/ibmlana.h +++ b/drivers/net/ibmlana.h @@ -17,7 +17,7 @@ #define IBM_LANA_ID 0xffe0 /* media enumeration - defined in a way that it fits onto the LAN/A's POS registers... */ -typedef enum { +typedef enum { Media_10BaseT, Media_10Base5, Media_Unknown, Media_10Base2, Media_Count } ibmlana_medium; @@ -27,7 +27,7 @@ typedef enum { typedef struct { unsigned int slot; /* MCA-Slot-# */ struct net_device_stats stat; /* packet statistics */ - int realirq; /* memorizes actual IRQ, even when + int realirq; /* memorizes actual IRQ, even when currently not allocated */ ibmlana_medium medium; /* physical cannector */ u32 tdastart, txbufstart, /* addresses */ @@ -41,7 +41,7 @@ typedef struct { spinlock_t lock; } ibmlana_priv; -/* this card uses quite a lot of I/O ports...luckily the MCA bus decodes +/* this card uses quite a lot of I/O ports...luckily the MCA bus decodes a full 64K I/O range... */ #define IBM_LANA_IORANGE 0xa0 diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 52d0102..4c2e727 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -24,7 +24,7 @@ /* for use with IBM i/pSeries LPAR Linux. It utilizes the logical LAN */ /* option of the RS/6000 Platform Architechture to interface with virtual */ /* ethernet NICs that are presented to the partition by the hypervisor. */ -/* */ +/* */ /**************************************************************************/ /* TODO: @@ -61,7 +61,7 @@ #include "ibmveth.h" #undef DEBUG #define ibmveth_printk(fmt, args...) \ - printk(KERN_INFO "%s: " fmt, __FILE__, ## args) + printk(KERN_DEBUG "%s: " fmt, __FILE__, ## args) #define ibmveth_error_printk(fmt, args...) \ printk(KERN_ERR "(%s:%3.3d ua:%x) ERROR: " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) @@ -79,7 +79,7 @@ #define ibmveth_assert(expr) \ #else #define ibmveth_debug_printk_no_adapter(fmt, args...) #define ibmveth_debug_printk(fmt, args...) -#define ibmveth_assert(expr) +#define ibmveth_assert(expr) #endif static int ibmveth_open(struct net_device *dev); @@ -96,6 +96,7 @@ static void ibmveth_proc_register_adapte static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter); static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter); +static struct kobj_type ktype_veth_pool; #ifdef CONFIG_PROC_FS #define IBMVETH_PROC_DIR "net/ibmveth" @@ -133,12 +134,13 @@ static inline int ibmveth_rxq_frame_leng } /* setup the initial settings for a buffer pool */ -static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size) +static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size, u32 pool_active) { pool->size = pool_size; pool->index = pool_index; pool->buff_size = buff_size; pool->threshold = pool_size / 2; + pool->active = pool_active; } /* allocate and setup an buffer pool - called during open */ @@ -146,13 +148,13 @@ static int ibmveth_alloc_buffer_pool(str { int i; - pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); + pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); if(!pool->free_map) { return -1; } - pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL); + pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL); if(!pool->dma_addr) { kfree(pool->free_map); pool->free_map = NULL; @@ -180,7 +182,6 @@ static int ibmveth_alloc_buffer_pool(str atomic_set(&pool->available, 0); pool->producer_index = 0; pool->consumer_index = 0; - pool->active = 0; return 0; } @@ -214,7 +215,7 @@ static void ibmveth_replenish_buffer_poo free_index = pool->consumer_index++ % pool->size; index = pool->free_map[free_index]; - + ibmveth_assert(index != IBM_VETH_INVALID_MAP); ibmveth_assert(pool->skbuff[index] == NULL); @@ -231,10 +232,10 @@ static void ibmveth_replenish_buffer_poo desc.desc = 0; desc.fields.valid = 1; desc.fields.length = pool->buff_size; - desc.fields.address = dma_addr; + desc.fields.address = dma_addr; lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); - + if(lpar_rc != H_SUCCESS) { pool->free_map[free_index] = index; pool->skbuff[index] = NULL; @@ -250,13 +251,13 @@ static void ibmveth_replenish_buffer_poo adapter->replenish_add_buff_success++; } } - + mb(); atomic_add(buffers_added, &(pool->available)); } /* replenish routine */ -static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) +static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) { int i; @@ -264,7 +265,7 @@ static void ibmveth_replenish_task(struc for(i = 0; i < IbmVethNumBufferPools; i++) if(adapter->rx_buff_pool[i].active) - ibmveth_replenish_buffer_pool(adapter, + ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[i]); adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8); @@ -301,7 +302,6 @@ static void ibmveth_free_buffer_pool(str kfree(pool->skbuff); pool->skbuff = NULL; } - pool->active = 0; } /* remove a buffer from a pool */ @@ -372,7 +372,7 @@ static void ibmveth_rxq_recycle_buffer(s desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index]; lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); - + if(lpar_rc != H_SUCCESS) { ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc); ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); @@ -407,7 +407,7 @@ static void ibmveth_cleanup(struct ibmve } free_page((unsigned long)adapter->buffer_list_addr); adapter->buffer_list_addr = NULL; - } + } if(adapter->filter_list_addr != NULL) { if(!dma_mapping_error(adapter->filter_list_dma)) { @@ -433,7 +433,9 @@ static void ibmveth_cleanup(struct ibmve } for(i = 0; irx_buff_pool[i]); + if (adapter->rx_buff_pool[i].active) + ibmveth_free_buffer_pool(adapter, + &adapter->rx_buff_pool[i]); } static int ibmveth_open(struct net_device *netdev) @@ -450,10 +452,10 @@ static int ibmveth_open(struct net_devic for(i = 0; irx_buff_pool[i].size; - + adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL); adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL); - + if(!adapter->buffer_list_addr || !adapter->filter_list_addr) { ibmveth_error_printk("unable to allocate filter or buffer list pages\n"); ibmveth_cleanup(adapter); @@ -489,9 +491,6 @@ static int ibmveth_open(struct net_devic adapter->rx_queue.num_slots = rxq_entries; adapter->rx_queue.toggle = 1; - /* call change_mtu to init the buffer pools based in initial mtu */ - ibmveth_change_mtu(netdev, netdev->mtu); - memcpy(&mac_address, netdev->dev_addr, netdev->addr_len); mac_address = mac_address >> 16; @@ -504,7 +503,7 @@ static int ibmveth_open(struct net_devic ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr); ibmveth_debug_printk("receive q @ 0x%p\n", adapter->rx_queue.queue_addr); - + lpar_rc = h_register_logical_lan(adapter->vdev->unit_address, adapter->buffer_list_dma, rxq_desc.desc, @@ -519,7 +518,18 @@ static int ibmveth_open(struct net_devic rxq_desc.desc, mac_address); ibmveth_cleanup(adapter); - return -ENONET; + return -ENONET; + } + + for(i = 0; irx_buff_pool[i].active) + continue; + if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[i])) { + ibmveth_error_printk("unable to alloc pool\n"); + adapter->rx_buff_pool[i].active = 0; + ibmveth_cleanup(adapter); + return -ENOMEM ; + } } ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq); @@ -547,10 +557,11 @@ static int ibmveth_close(struct net_devi { struct ibmveth_adapter *adapter = netdev->priv; long lpar_rc; - + ibmveth_debug_printk("close starting\n"); - netif_stop_queue(netdev); + if (!adapter->pool_config) + netif_stop_queue(netdev); free_irq(netdev->irq, netdev); @@ -694,7 +705,7 @@ static int ibmveth_start_xmit(struct sk_ desc[5].desc, correlator); } while ((lpar_rc == H_BUSY) && (retry_count--)); - + if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) { int i; ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc); @@ -780,7 +791,7 @@ static int ibmveth_poll(struct net_devic /* more work to do - return that we are not done yet */ netdev->quota -= frames_processed; *budget -= frames_processed; - return 1; + return 1; } /* we think we are done - reenable interrupts, then check once more to make sure we are done */ @@ -806,7 +817,7 @@ static int ibmveth_poll(struct net_devic } static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -{ +{ struct net_device *netdev = dev_instance; struct ibmveth_adapter *adapter = netdev->priv; unsigned long lpar_rc; @@ -862,7 +873,7 @@ static void ibmveth_set_multicast_list(s ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc); } } - + /* re-enable filtering */ lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, IbmVethMcastEnableFiltering, @@ -876,46 +887,22 @@ static void ibmveth_set_multicast_list(s static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) { struct ibmveth_adapter *adapter = dev->priv; + int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH; int i; - int prev_smaller = 1; - if ((new_mtu < 68) || - (new_mtu > (pool_size[IbmVethNumBufferPools-1]) - IBMVETH_BUFF_OH)) + if (new_mtu < IBMVETH_MAX_MTU) return -EINVAL; + /* Look for an active buffer pool that can hold the new MTU */ for(i = 0; i (pool_size[i] - IBMVETH_BUFF_OH)) { - activate = 1; - prev_smaller= 1; - } else { - if (prev_smaller) - activate = 1; - prev_smaller= 0; + if (!adapter->rx_buff_pool[i].active) + continue; + if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) { + dev->mtu = new_mtu; + return 0; } - - if (activate && !adapter->rx_buff_pool[i].active) { - struct ibmveth_buff_pool *pool = - &adapter->rx_buff_pool[i]; - if(ibmveth_alloc_buffer_pool(pool)) { - ibmveth_error_printk("unable to alloc pool\n"); - return -ENOMEM; - } - adapter->rx_buff_pool[i].active = 1; - } else if (!activate && adapter->rx_buff_pool[i].active) { - adapter->rx_buff_pool[i].active = 0; - h_free_logical_lan_buffer(adapter->vdev->unit_address, - (u64)pool_size[i]); - } - } - - /* kick the interrupt handler so that the new buffer pools get - replenished or deallocated */ - ibmveth_interrupt(dev->irq, dev, NULL); - - dev->mtu = new_mtu; - return 0; + return -EINVAL; } static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) @@ -928,7 +915,7 @@ static int __devinit ibmveth_probe(struc unsigned int *mcastFilterSize_p; - ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n", + ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n", dev->unit_address); mac_addr_p = (unsigned char *) vio_get_attribute(dev, VETH_MAC_ADDR, 0); @@ -937,7 +924,7 @@ static int __devinit ibmveth_probe(struc "attribute\n", __FILE__, __LINE__); return 0; } - + mcastFilterSize_p= (unsigned int *) vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, 0); if(!mcastFilterSize_p) { printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find " @@ -945,7 +932,7 @@ static int __devinit ibmveth_probe(struc __FILE__, __LINE__); return 0; } - + netdev = alloc_etherdev(sizeof(struct ibmveth_adapter)); if(!netdev) @@ -960,13 +947,14 @@ static int __devinit ibmveth_probe(struc adapter->vdev = dev; adapter->netdev = netdev; adapter->mcastFilterSize= *mcastFilterSize_p; - + adapter->pool_config = 0; + /* Some older boxes running PHYP non-natively have an OF that - returns a 8-byte local-mac-address field (and the first + returns a 8-byte local-mac-address field (and the first 2 bytes have to be ignored) while newer boxes' OF return - a 6-byte field. Note that IEEE 1275 specifies that + a 6-byte field. Note that IEEE 1275 specifies that local-mac-address must be a 6-byte field. - The RPA doc specifies that the first byte must be 10b, so + The RPA doc specifies that the first byte must be 10b, so we'll just look for it to solve this 8 vs. 6 byte field issue */ if ((*mac_addr_p & 0x3) != 0x02) @@ -976,7 +964,7 @@ static int __devinit ibmveth_probe(struc memcpy(&adapter->mac_addr, mac_addr_p, 6); adapter->liobn = dev->iommu_table->it_index; - + netdev->irq = dev->irq; netdev->open = ibmveth_open; netdev->poll = ibmveth_poll; @@ -989,14 +977,21 @@ static int __devinit ibmveth_probe(struc netdev->ethtool_ops = &netdev_ethtool_ops; netdev->change_mtu = ibmveth_change_mtu; SET_NETDEV_DEV(netdev, &dev->dev); - netdev->features |= NETIF_F_LLTX; + netdev->features |= NETIF_F_LLTX; spin_lock_init(&adapter->stats_lock); memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); - for(i = 0; irx_buff_pool[i], i, - pool_count[i], pool_size[i]); + for(i = 0; irx_buff_pool[i].kobj; + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i, + pool_count[i], pool_size[i], + pool_active[i]); + kobj->parent = &dev->dev.kobj; + sprintf(kobj->name, "pool%d", i); + kobj->ktype = &ktype_veth_pool; + kobject_register(kobj); + } ibmveth_debug_printk("adapter @ 0x%p\n", adapter); @@ -1025,6 +1020,10 @@ static int __devexit ibmveth_remove(stru { struct net_device *netdev = dev->dev.driver_data; struct ibmveth_adapter *adapter = netdev->priv; + int i; + + for(i = 0; irx_buff_pool[i].kobj); unregister_netdev(netdev); @@ -1048,7 +1047,7 @@ static void ibmveth_proc_unregister_driv remove_proc_entry(IBMVETH_PROC_DIR, NULL); } -static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) +static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) { if (*pos == 0) { return (void *)1; @@ -1063,18 +1062,18 @@ static void *ibmveth_seq_next(struct seq return NULL; } -static void ibmveth_seq_stop(struct seq_file *seq, void *v) +static void ibmveth_seq_stop(struct seq_file *seq, void *v) { } -static int ibmveth_seq_show(struct seq_file *seq, void *v) +static int ibmveth_seq_show(struct seq_file *seq, void *v) { struct ibmveth_adapter *adapter = seq->private; char *current_mac = ((char*) &adapter->netdev->dev_addr); char *firmware_mac = ((char*) &adapter->mac_addr) ; seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version); - + seq_printf(seq, "Unit Address: 0x%x\n", adapter->vdev->unit_address); seq_printf(seq, "LIOBN: 0x%lx\n", adapter->liobn); seq_printf(seq, "Current MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", @@ -1083,7 +1082,7 @@ static int ibmveth_seq_show(struct seq_f seq_printf(seq, "Firmware MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", firmware_mac[0], firmware_mac[1], firmware_mac[2], firmware_mac[3], firmware_mac[4], firmware_mac[5]); - + seq_printf(seq, "\nAdapter Statistics:\n"); seq_printf(seq, " TX: skbuffs linearized: %ld\n", adapter->tx_linearized); seq_printf(seq, " multi-descriptor sends: %ld\n", adapter->tx_multidesc_send); @@ -1095,7 +1094,7 @@ static int ibmveth_seq_show(struct seq_f seq_printf(seq, " add buffer failures: %ld\n", adapter->replenish_add_buff_failure); seq_printf(seq, " invalid buffers: %ld\n", adapter->rx_invalid_buffer); seq_printf(seq, " no buffers: %ld\n", adapter->rx_no_buffer); - + return 0; } static struct seq_operations ibmveth_seq_ops = { @@ -1153,11 +1152,11 @@ static void ibmveth_proc_unregister_adap } #else /* CONFIG_PROC_FS */ -static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) +static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) { } -static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) +static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) { } static void ibmveth_proc_register_driver(void) @@ -1169,6 +1168,132 @@ static void ibmveth_proc_unregister_driv } #endif /* CONFIG_PROC_FS */ +static struct attribute veth_active_attr; +static struct attribute veth_num_attr; +static struct attribute veth_size_attr; + +static ssize_t veth_pool_show(struct kobject * kobj, + struct attribute * attr, char * buf) +{ + struct ibmveth_buff_pool *pool = container_of(kobj, + struct ibmveth_buff_pool, + kobj); + + if (attr == &veth_active_attr) + return sprintf(buf, "%d\n", pool->active); + else if (attr == &veth_num_attr) + return sprintf(buf, "%d\n", pool->size); + else if (attr == &veth_size_attr) + return sprintf(buf, "%d\n", pool->buff_size); + return 0; +} + +static ssize_t veth_pool_store(struct kobject * kobj, struct attribute * attr, +const char * buf, size_t count) +{ + struct ibmveth_buff_pool *pool = container_of(kobj, + struct ibmveth_buff_pool, + kobj); + struct net_device *netdev = + container_of(kobj->parent, struct device, kobj)->driver_data; + struct ibmveth_adapter *adapter = netdev->priv; + long value = simple_strtol(buf, NULL, 10); + long rc; + + if (attr == &veth_active_attr) { + if (value && !pool->active) { + if(ibmveth_alloc_buffer_pool(pool)) { + ibmveth_error_printk("unable to alloc pool\n"); + return -ENOMEM; + } + pool->active = 1; + adapter->pool_config = 1; + ibmveth_close(netdev); + adapter->pool_config = 0; + if ((rc = ibmveth_open(netdev))) + return rc; + } else if (!value && pool->active) { + int mtu = netdev->mtu + IBMVETH_BUFF_OH; + int i; + /* Make sure there is a buffer pool with buffers that + can hold a packet of the size of the MTU */ + for(i = 0; irx_buff_pool[i]) + continue; + if (!adapter->rx_buff_pool[i].active) + continue; + if (mtu < adapter->rx_buff_pool[i].buff_size) { + pool->active = 0; + h_free_logical_lan_buffer(adapter-> + vdev-> + unit_address, + pool-> + buff_size); + } + } + if (pool->active) { + ibmveth_error_printk("no active pool >= MTU\n"); + return -EPERM; + } + } + } else if (attr == &veth_num_attr) { + if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT) + return -EINVAL; + else { + adapter->pool_config = 1; + ibmveth_close(netdev); + adapter->pool_config = 0; + pool->size = value; + if ((rc = ibmveth_open(netdev))) + return rc; + } + } else if (attr == &veth_size_attr) { + if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE) + return -EINVAL; + else { + adapter->pool_config = 1; + ibmveth_close(netdev); + adapter->pool_config = 0; + pool->buff_size = value; + if ((rc = ibmveth_open(netdev))) + return rc; + } + } + + /* kick the interrupt handler to allocate/deallocate pools */ + ibmveth_interrupt(netdev->irq, netdev, NULL); + return count; +} + + +#define ATTR(_name, _mode) \ + struct attribute veth_##_name##_attr = { \ + .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \ + }; + +static ATTR(active, 0644); +static ATTR(num, 0644); +static ATTR(size, 0644); + +static struct attribute * veth_pool_attrs[] = { + &veth_active_attr, + &veth_num_attr, + &veth_size_attr, + NULL, +}; + +static struct sysfs_ops veth_pool_ops = { + .show = veth_pool_show, + .store = veth_pool_store, +}; + +static struct kobj_type ktype_veth_pool = { + .release = NULL, + .sysfs_ops = &veth_pool_ops, + .default_attrs = veth_pool_attrs, +}; + + static struct vio_device_id ibmveth_device_table[] __devinitdata= { { "network", "IBM,l-lan"}, { "", "" } @@ -1198,7 +1323,7 @@ static void __exit ibmveth_module_exit(v { vio_unregister_driver(&ibmveth_driver); ibmveth_proc_unregister_driver(); -} +} module_init(ibmveth_module_init); module_exit(ibmveth_module_exit); diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h index 46919a8..8385bf8 100644 --- a/drivers/net/ibmveth.h +++ b/drivers/net/ibmveth.h @@ -75,10 +75,13 @@ #define h_free_logical_lan_buffer(ua, bu #define IbmVethNumBufferPools 5 #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */ +#define IBMVETH_MAX_MTU 68 +#define IBMVETH_MAX_POOL_COUNT 4096 +#define IBMVETH_MAX_BUF_SIZE (1024 * 128) -/* pool_size should be sorted */ static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 }; static int pool_count[] = { 256, 768, 256, 256, 256 }; +static int pool_active[] = { 1, 1, 0, 0, 0}; #define IBM_VETH_INVALID_MAP ((u16)0xffff) @@ -94,6 +97,7 @@ struct ibmveth_buff_pool { dma_addr_t *dma_addr; struct sk_buff **skbuff; int active; + struct kobject kobj; }; struct ibmveth_rx_q { @@ -118,6 +122,7 @@ struct ibmveth_adapter { dma_addr_t filter_list_dma; struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools]; struct ibmveth_rx_q rx_queue; + int pool_config; /* adapter specific stats */ u64 replenish_task_cycles; @@ -134,7 +139,7 @@ struct ibmveth_adapter { spinlock_t stats_lock; }; -struct ibmveth_buf_desc_fields { +struct ibmveth_buf_desc_fields { u32 valid : 1; u32 toggle : 1; u32 reserved : 6; @@ -143,7 +148,7 @@ struct ibmveth_buf_desc_fields { }; union ibmveth_buf_desc { - u64 desc; + u64 desc; struct ibmveth_buf_desc_fields fields; }; diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 31fb2d7..2e222ef 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -76,13 +76,13 @@ static void ri_tasklet(unsigned long dev dp->st_task_enter++; if ((skb = skb_peek(&dp->tq)) == NULL) { dp->st_txq_refl_try++; - if (spin_trylock(&_dev->xmit_lock)) { + if (netif_tx_trylock(_dev)) { dp->st_rxq_enter++; while ((skb = skb_dequeue(&dp->rq)) != NULL) { skb_queue_tail(&dp->tq, skb); dp->st_rx2tx_tran++; } - spin_unlock(&_dev->xmit_lock); + netif_tx_unlock(_dev); } else { /* reschedule */ dp->st_rxq_notenter++; @@ -110,7 +110,7 @@ static void ri_tasklet(unsigned long dev } } - if (spin_trylock(&_dev->xmit_lock)) { + if (netif_tx_trylock(_dev)) { dp->st_rxq_check++; if ((skb = skb_peek(&dp->rq)) == NULL) { dp->tasklet_pending = 0; @@ -118,10 +118,10 @@ static void ri_tasklet(unsigned long dev netif_wake_queue(_dev); } else { dp->st_rxq_rsch++; - spin_unlock(&_dev->xmit_lock); + netif_tx_unlock(_dev); goto resched; } - spin_unlock(&_dev->xmit_lock); + netif_tx_unlock(_dev); } else { resched: dp->tasklet_pending = 1; diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index ae71ed5..e76e6e7 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -145,7 +145,7 @@ static inline struct sk_buff * ioc3_allo static inline unsigned long ioc3_map(void *ptr, unsigned long vdev) { #ifdef CONFIG_SGI_IP27 - vdev <<= 58; /* Shift to PCI64_ATTR_VIRTUAL */ + vdev <<= 57; /* Shift to PCI64_ATTR_VIRTUAL */ return vdev | (0xaUL << PCI64_ATTR_TARG_SHFT) | PCI64_ATTR_PREF | ((unsigned long)ptr & TO_PHYS_MASK); diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index cff8598..d2ce489 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -417,5 +417,20 @@ config PXA_FICP available capabilities may vary from one PXA2xx target to another. +config MCS_FIR + tristate "MosChip MCS7780 IrDA-USB dongle" + depends on IRDA && USB && EXPERIMENTAL + help + Say Y or M here if you want to build support for the MosChip + MCS7780 IrDA-USB bridge device driver. + + USB bridge based on the MosChip MCS7780 don't conform to the + IrDA-USB device class specification, and therefore need their + own specific driver. Those dongles support SIR and FIR (4Mbps) + speeds. + + To compile it as a module, choose M here: the module will be called + mcs7780. + endmenu diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index c1ce239..5be09f1 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_ALI_FIR) += ali-ircc.o obj-$(CONFIG_VLSI_FIR) += vlsi_ir.o obj-$(CONFIG_VIA_FIR) += via-ircc.o obj-$(CONFIG_PXA_FICP) += pxaficp_ir.o +obj-$(CONFIG_MCS_FIR) += mcs7780.o # Old dongle drivers for old SIR drivers obj-$(CONFIG_ESI_DONGLE_OLD) += esi.o obj-$(CONFIG_TEKRAM_DONGLE_OLD) += tekram.o diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c index 2e7882e..bf1fca5 100644 --- a/drivers/net/irda/ali-ircc.c +++ b/drivers/net/irda/ali-ircc.c @@ -34,14 +34,12 @@ #include #include #include #include +#include #include #include #include -#include -#include - #include #include #include @@ -51,7 +49,19 @@ #include "ali-ircc.h" #define CHIP_IO_EXTENT 8 #define BROKEN_DONGLE_ID -static char *driver_name = "ali-ircc"; +#define ALI_IRCC_DRIVER_NAME "ali-ircc" + +/* Power Management */ +static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state); +static int ali_ircc_resume(struct platform_device *dev); + +static struct platform_driver ali_ircc_driver = { + .suspend = ali_ircc_suspend, + .resume = ali_ircc_resume, + .driver = { + .name = ALI_IRCC_DRIVER_NAME, + }, +}; /* Module parameters */ static int qos_mtt_bits = 0x07; /* 1 ms or more */ @@ -97,10 +107,7 @@ static int ali_ircc_is_receiving(struct static int ali_ircc_net_open(struct net_device *dev); static int ali_ircc_net_close(struct net_device *dev); static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static int ali_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data); static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud); -static void ali_ircc_suspend(struct ali_ircc_cb *self); -static void ali_ircc_wakeup(struct ali_ircc_cb *self); static struct net_device_stats *ali_ircc_net_get_stats(struct net_device *dev); /* SIR function */ @@ -145,6 +152,14 @@ static int __init ali_ircc_init(void) int i = 0; IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); + + ret = platform_driver_register(&ali_ircc_driver); + if (ret) { + IRDA_ERROR("%s, Can't register driver!\n", + ALI_IRCC_DRIVER_NAME); + return ret; + } + /* Probe for all the ALi chipsets we know about */ for (chip= chips; chip->name; chip++, i++) @@ -214,6 +229,10 @@ static int __init ali_ircc_init(void) } IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__); + + if (ret) + platform_driver_unregister(&ali_ircc_driver); + return ret; } @@ -228,14 +247,14 @@ static void __exit ali_ircc_cleanup(void int i; IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); - - pm_unregister_all(ali_ircc_pmproc); for (i=0; i < 4; i++) { if (dev_self[i]) ali_ircc_close(dev_self[i]); } + platform_driver_unregister(&ali_ircc_driver); + IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__); } @@ -249,7 +268,6 @@ static int ali_ircc_open(int i, chipio_t { struct net_device *dev; struct ali_ircc_cb *self; - struct pm_dev *pmdev; int dongle_id; int err; @@ -284,7 +302,8 @@ static int ali_ircc_open(int i, chipio_t self->io.fifo_size = 16; /* SIR: 16, FIR: 32 Benjamin 2000/11/1 */ /* Reserve the ioports that we need */ - if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) { + if (!request_region(self->io.fir_base, self->io.fir_ext, + ALI_IRCC_DRIVER_NAME)) { IRDA_WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__, self->io.fir_base); err = -ENODEV; @@ -354,13 +373,10 @@ static int ali_ircc_open(int i, chipio_t /* Check dongle id */ dongle_id = ali_ircc_read_dongle_id(i, info); - IRDA_MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__, driver_name, dongle_types[dongle_id]); + IRDA_MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__, + ALI_IRCC_DRIVER_NAME, dongle_types[dongle_id]); self->io.dongle_id = dongle_id; - - pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, ali_ircc_pmproc); - if (pmdev) - pmdev->data = self; IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__); @@ -548,12 +564,11 @@ static int ali_ircc_setup(chipio_t *info /* Should be 0x00 in the M1535/M1535D */ if(version != 0x00) { - IRDA_ERROR("%s, Wrong chip version %02x\n", driver_name, version); + IRDA_ERROR("%s, Wrong chip version %02x\n", + ALI_IRCC_DRIVER_NAME, version); return -1; } - // IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, info->cfg_base); - /* Set FIR FIFO Threshold Register */ switch_bank(iobase, BANK1); outb(RX_FIFO_Threshold, iobase+FIR_FIFO_TR); @@ -583,7 +598,8 @@ static int ali_ircc_setup(chipio_t *info /* Switch to SIR space */ FIR2SIR(iobase); - IRDA_MESSAGE("%s, driver loaded (Benjamin Kong)\n", driver_name); + IRDA_MESSAGE("%s, driver loaded (Benjamin Kong)\n", + ALI_IRCC_DRIVER_NAME); /* Enable receive interrupts */ // outb(UART_IER_RDI, iobase+UART_IER); //benjamin 2000/11/23 01:25PM @@ -647,7 +663,8 @@ static irqreturn_t ali_ircc_interrupt(in IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); if (!dev) { - IRDA_WARNING("%s: irq %d for unknown device.\n", driver_name, irq); + IRDA_WARNING("%s: irq %d for unknown device.\n", + ALI_IRCC_DRIVER_NAME, irq); return IRQ_NONE; } @@ -1328,7 +1345,8 @@ static int ali_ircc_net_open(struct net_ /* Request IRQ and install Interrupt Handler */ if (request_irq(self->io.irq, ali_ircc_interrupt, 0, dev->name, dev)) { - IRDA_WARNING("%s, unable to allocate irq=%d\n", driver_name, + IRDA_WARNING("%s, unable to allocate irq=%d\n", + ALI_IRCC_DRIVER_NAME, self->io.irq); return -EAGAIN; } @@ -1338,7 +1356,8 @@ static int ali_ircc_net_open(struct net_ * failure. */ if (request_dma(self->io.dma, dev->name)) { - IRDA_WARNING("%s, unable to allocate dma=%d\n", driver_name, + IRDA_WARNING("%s, unable to allocate dma=%d\n", + ALI_IRCC_DRIVER_NAME, self->io.dma); free_irq(self->io.irq, self); return -EAGAIN; @@ -2108,61 +2127,38 @@ static struct net_device_stats *ali_ircc return &self->stats; } -static void ali_ircc_suspend(struct ali_ircc_cb *self) +static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state) { - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ ); + struct ali_ircc_cb *self = platform_get_drvdata(dev); - IRDA_MESSAGE("%s, Suspending\n", driver_name); + IRDA_MESSAGE("%s, Suspending\n", ALI_IRCC_DRIVER_NAME); if (self->io.suspended) - return; + return 0; ali_ircc_net_close(self->netdev); self->io.suspended = 1; - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ ); + return 0; } -static void ali_ircc_wakeup(struct ali_ircc_cb *self) +static int ali_ircc_resume(struct platform_device *dev) { - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ ); + struct ali_ircc_cb *self = platform_get_drvdata(dev); if (!self->io.suspended) - return; + return 0; ali_ircc_net_open(self->netdev); - IRDA_MESSAGE("%s, Waking up\n", driver_name); + IRDA_MESSAGE("%s, Waking up\n", ALI_IRCC_DRIVER_NAME); self->io.suspended = 0; - - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ ); -} -static int ali_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) -{ - struct ali_ircc_cb *self = (struct ali_ircc_cb*) dev->data; - - IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ ); - - if (self) { - switch (rqst) { - case PM_SUSPEND: - ali_ircc_suspend(self); - break; - case PM_RESUME: - ali_ircc_wakeup(self); - break; - } - } - - IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ ); - return 0; } - /* ALi Chip Function */ static void SetCOMInterrupts(struct ali_ircc_cb *self , unsigned char enable) diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index cd87593..2a0d538 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -83,9 +83,9 @@ static struct usb_device_id dongles[] = /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */ { USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, /* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */ - { USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, - { USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, - { USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, + { USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR421X | IUC_SPEED_BUG }, + { USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR421X | IUC_SPEED_BUG }, + { USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR421X | IUC_SPEED_BUG }, { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS, .bInterfaceClass = USB_CLASS_APP_SPEC, @@ -154,7 +154,7 @@ static void irda_usb_build_header(struct * and if either speed or xbofs (or both) needs * to be changed. */ - if (self->capability & IUC_STIR_4210 && + if (self->capability & IUC_STIR421X && ((self->new_speed != -1) || (self->new_xbofs != -1))) { /* With STIR421x, speed and xBOFs must be set at the same @@ -318,7 +318,7 @@ static void irda_usb_change_speed_xbofs( /* Set the new speed and xbofs in this fake frame */ irda_usb_build_header(self, frame, 1); - if ( self->capability & IUC_STIR_4210 ) { + if (self->capability & IUC_STIR421X) { if (frame[0] == 0) return ; // do nothing if no change frame[1] = 0; // other parameters don't change here frame[2] = 0; @@ -455,7 +455,7 @@ static int irda_usb_hard_xmit(struct sk_ /* Change setting for next frame */ - if ( self->capability & IUC_STIR_4210 ) { + if (self->capability & IUC_STIR421X) { __u8 turnaround_time; __u8* frame; turnaround_time = get_turnaround_time( skb ); @@ -897,10 +897,13 @@ static void irda_usb_receive(struct urb docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD); /* Allocate a new skb */ - if ( self->capability & IUC_STIR_4210 ) - newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU + USB_IRDA_SIGMATEL_HEADER); + if (self->capability & IUC_STIR421X) + newskb = dev_alloc_skb(docopy ? urb->actual_length : + IRDA_SKB_MAX_MTU + + USB_IRDA_STIR421X_HEADER); else - newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU); + newskb = dev_alloc_skb(docopy ? urb->actual_length : + IRDA_SKB_MAX_MTU); if (!newskb) { self->stats.rx_dropped++; @@ -1022,188 +1025,140 @@ static int irda_usb_is_receiving(struct return 0; /* For now */ } - -#define STIR421X_PATCH_PRODUCT_VERSION_STR "Product Version: " -#define STIR421X_PATCH_COMPONENT_VERSION_STR "Component Version: " -#define STIR421X_PATCH_DATA_TAG_STR "STMP" -#define STIR421X_PATCH_FILE_VERSION_MAX_OFFSET 512 /* version info is before here */ -#define STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET 512 /* patch image starts before here */ -#define STIR421X_PATCH_FILE_END_OF_HEADER_TAG 0x1A /* marks end of patch file header (PC DOS text file EOF character) */ +#define STIR421X_PATCH_PRODUCT_VER "Product Version: " +#define STIR421X_PATCH_STMP_TAG "STMP" +#define STIR421X_PATCH_CODE_OFFSET 512 /* patch image starts before here */ +/* marks end of patch file header (PC DOS text file EOF character) */ +#define STIR421X_PATCH_END_OF_HDR_TAG 0x1A +#define STIR421X_PATCH_BLOCK_SIZE 1023 /* - * Known firmware patches for STIR421x dongles + * Function stir421x_fwupload (struct irda_usb_cb *self, + * unsigned char *patch, + * const unsigned int patch_len) + * + * Upload firmware code to SigmaTel 421X IRDA-USB dongle */ -static char * stir421x_patches[] = { - "42101001.sb", - "42101002.sb", -}; - -static int stir421x_get_patch_version(unsigned char * patch, const unsigned long patch_len) +static int stir421x_fw_upload(struct irda_usb_cb *self, + unsigned char *patch, + const unsigned int patch_len) { - unsigned int version_offset; - unsigned long version_major, version_minor, version_build; - unsigned char * version_start; - int version_found = 0; - - for (version_offset = 0; - version_offset < STIR421X_PATCH_FILE_END_OF_HEADER_TAG; - version_offset++) { - if (!memcmp(patch + version_offset, - STIR421X_PATCH_PRODUCT_VERSION_STR, - sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1)) { - version_found = 1; - version_start = patch + - version_offset + - sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1; - break; - } + int ret = -ENOMEM; + int actual_len = 0; + unsigned int i; + unsigned int block_size = 0; + unsigned char *patch_block; + + patch_block = kzalloc(STIR421X_PATCH_BLOCK_SIZE, GFP_KERNEL); + if (patch_block == NULL) + return -ENOMEM; + + /* break up patch into 1023-byte sections */ + for (i = 0; i < patch_len; i += block_size) { + block_size = patch_len - i; + + if (block_size > STIR421X_PATCH_BLOCK_SIZE) + block_size = STIR421X_PATCH_BLOCK_SIZE; + + /* upload the patch section */ + memcpy(patch_block, patch + i, block_size); + + ret = usb_bulk_msg(self->usbdev, + usb_sndbulkpipe(self->usbdev, + self->bulk_out_ep), + patch_block, block_size, + &actual_len, msecs_to_jiffies(500)); + IRDA_DEBUG(3,"%s(): Bulk send %u bytes, ret=%d\n", + __FUNCTION__, actual_len, ret); + + if (ret < 0) + break; } - /* We couldn't find a product version on this patch */ - if (!version_found) - return -EINVAL; - - /* Let's check if the product version is dotted */ - if (version_start[3] != '.' || - version_start[7] != '.') - return -EINVAL; - - version_major = simple_strtoul(version_start, NULL, 10); - version_minor = simple_strtoul(version_start + 4, NULL, 10); - version_build = simple_strtoul(version_start + 8, NULL, 10); - - IRDA_DEBUG(2, "%s(), Major: %ld Minor: %ld Build: %ld\n", - __FUNCTION__, - version_major, version_minor, version_build); - - return (((version_major) << 12) + - ((version_minor) << 8) + - ((version_build / 10) << 4) + - (version_build % 10)); - -} - - -static int stir421x_upload_patch (struct irda_usb_cb *self, - unsigned char * patch, - const unsigned int patch_len) -{ - int retval = 0; - int actual_len; - unsigned int i = 0, download_amount = 0; - unsigned char * patch_chunk; - - IRDA_DEBUG (2, "%s(), Uploading STIR421x Patch\n", __FUNCTION__); - - patch_chunk = kzalloc(STIR421X_MAX_PATCH_DOWNLOAD_SIZE, GFP_KERNEL); - if (patch_chunk == NULL) - return -ENOMEM; - - /* break up patch into 1023-byte sections */ - for (i = 0; retval >= 0 && i < patch_len; i += download_amount) { - download_amount = patch_len - i; - if (download_amount > STIR421X_MAX_PATCH_DOWNLOAD_SIZE) - download_amount = STIR421X_MAX_PATCH_DOWNLOAD_SIZE; - - /* download the patch section */ - memcpy(patch_chunk, patch + i, download_amount); - - retval = usb_bulk_msg (self->usbdev, - usb_sndbulkpipe (self->usbdev, - self->bulk_out_ep), - patch_chunk, download_amount, - &actual_len, msecs_to_jiffies (500)); - IRDA_DEBUG (2, "%s(), Sent %u bytes\n", __FUNCTION__, - actual_len); - if (retval == 0) - mdelay(10); - } - - kfree(patch_chunk); - - if (i != patch_len) { - IRDA_ERROR ("%s(), Pushed %d bytes (!= patch_len (%d))\n", - __FUNCTION__, i, patch_len); - retval = -EIO; - } - - if (retval < 0) - /* todo - mark device as not ready */ - IRDA_ERROR ("%s(), STIR421x patch upload failed (%d)\n", - __FUNCTION__, retval); - - return retval; -} + kfree(patch_block); + return ret; + } +/* + * Function stir421x_patch_device(struct irda_usb_cb *self) + * + * Get a firmware code from userspase using hotplug request_firmware() call + */ static int stir421x_patch_device(struct irda_usb_cb *self) { - unsigned int i, patch_found = 0, data_found = 0, data_offset; - int patch_version, ret = 0; - const struct firmware *fw_entry; - - for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) { - if(request_firmware(&fw_entry, stir421x_patches[i], &self->usbdev->dev) != 0) { - IRDA_ERROR( "%s(), Patch %s is not available\n", __FUNCTION__, stir421x_patches[i]); - continue; - } - - /* We found a patch from userspace */ - patch_version = stir421x_get_patch_version (fw_entry->data, fw_entry->size); - - if (patch_version < 0) { - /* Couldn't fetch a version, let's move on to the next file */ - IRDA_ERROR("%s(), version parsing failed\n", __FUNCTION__); - ret = patch_version; - release_firmware(fw_entry); - continue; - } - - if (patch_version != self->usbdev->descriptor.bcdDevice) { - /* Patch version and device don't match */ - IRDA_ERROR ("%s(), wrong patch version (%d <-> %d)\n", - __FUNCTION__, - patch_version, self->usbdev->descriptor.bcdDevice); - ret = -EINVAL; - release_firmware(fw_entry); - continue; - } - - /* If we're here, we've found a correct patch */ - patch_found = 1; - break; - - } - - /* We couldn't find a valid firmware, let's leave */ - if (!patch_found) - return ret; - - /* The actual image starts after the "STMP" keyword */ - for (data_offset = 0; data_offset < STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET; data_offset++) { - if (!memcmp(fw_entry->data + data_offset, - STIR421X_PATCH_DATA_TAG_STR, - sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))) { - IRDA_DEBUG(2, "%s(), found patch data for STIR421x at offset %d\n", - __FUNCTION__, data_offset); - data_found = 1; - break; - } - } - - /* We couldn't find "STMP" from the header */ - if (!data_found) - return -EINVAL; - - /* Let's upload the patch to the target */ - ret = stir421x_upload_patch(self, - &fw_entry->data[data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)], - fw_entry->size - (data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))); - - release_firmware(fw_entry); - - return ret; - + unsigned int i; + int ret; + char stir421x_fw_name[11]; + const struct firmware *fw; + unsigned char *fw_version_ptr; /* pointer to version string */ + unsigned long fw_version = 0; + + /* + * Known firmware patch file names for STIR421x dongles + * are "42101001.sb" or "42101002.sb" + */ + sprintf(stir421x_fw_name, "4210%4X.sb", + self->usbdev->descriptor.bcdDevice); + ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev); + if (ret < 0) + return ret; + + /* We get a patch from userspace */ + IRDA_MESSAGE("%s(): Received firmware %s (%zu bytes)\n", + __FUNCTION__, stir421x_fw_name, fw->size); + + ret = -EINVAL; + + /* Get the bcd product version */ + if (!memcmp(fw->data, STIR421X_PATCH_PRODUCT_VER, + sizeof(STIR421X_PATCH_PRODUCT_VER) - 1)) { + fw_version_ptr = fw->data + + sizeof(STIR421X_PATCH_PRODUCT_VER) - 1; + + /* Let's check if the product version is dotted */ + if (fw_version_ptr[3] == '.' && + fw_version_ptr[7] == '.') { + unsigned long major, minor, build; + major = simple_strtoul(fw_version_ptr, NULL, 10); + minor = simple_strtoul(fw_version_ptr + 4, NULL, 10); + build = simple_strtoul(fw_version_ptr + 8, NULL, 10); + + fw_version = (major << 12) + + (minor << 8) + + ((build / 10) << 4) + + (build % 10); + + IRDA_DEBUG(3, "%s(): Firmware Product version %ld\n", + __FUNCTION__, fw_version); + } + } + + if (self->usbdev->descriptor.bcdDevice == fw_version) { + /* + * If we're here, we've found a correct patch + * The actual image starts after the "STMP" keyword + * so forward to the firmware header tag + */ + for (i = 0; (fw->data[i] != STIR421X_PATCH_END_OF_HDR_TAG) + && (i < fw->size); i++) ; + /* here we check for the out of buffer case */ + if ((STIR421X_PATCH_END_OF_HDR_TAG == fw->data[i]) + && (i < STIR421X_PATCH_CODE_OFFSET)) { + if (!memcmp(fw->data + i + 1, STIR421X_PATCH_STMP_TAG, + sizeof(STIR421X_PATCH_STMP_TAG) - 1)) { + + /* We can upload the patch to the target */ + i += sizeof(STIR421X_PATCH_STMP_TAG); + ret = stir421x_fw_upload(self, &fw->data[i], + fw->size - i); + } + } + } + + release_firmware(fw); + + return ret; } @@ -1702,12 +1657,12 @@ static int irda_usb_probe(struct usb_int init_timer(&self->rx_defer_timer); self->capability = id->driver_info; - self->needspatch = ((self->capability & IUC_STIR_4210) != 0) ; + self->needspatch = ((self->capability & IUC_STIR421X) != 0); /* Create all of the needed urbs */ - if (self->capability & IUC_STIR_4210) { + if (self->capability & IUC_STIR421X) { self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS; - self->header_length = USB_IRDA_SIGMATEL_HEADER; + self->header_length = USB_IRDA_STIR421X_HEADER; } else { self->max_rx_urb = IU_MAX_RX_URBS; self->header_length = USB_IRDA_HEADER; @@ -1813,8 +1768,8 @@ static int irda_usb_probe(struct usb_int /* Now we fetch and upload the firmware patch */ ret = stir421x_patch_device(self); self->needspatch = (ret < 0); - if (ret < 0) { - printk("patch_device failed\n"); + if (self->needspatch) { + IRDA_ERROR("STIR421X: Couldn't upload patch\n"); goto err_out_5; } diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h index d833db5..6b2271f 100644 --- a/drivers/net/irda/irda-usb.h +++ b/drivers/net/irda/irda-usb.h @@ -34,9 +34,6 @@ #include #include #include /* struct irlap_cb */ -#define PATCH_FILE_SIZE_MAX 65536 -#define PATCH_FILE_SIZE_MIN 80 - #define RX_COPY_THRESHOLD 200 #define IRDA_USB_MAX_MTU 2051 #define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */ @@ -107,14 +104,15 @@ #define IUC_SIR_ONLY 0x08 /* Device does #define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */ #define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */ #define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */ -#define IUC_STIR_4210 0x80 /* SigmaTel 4210/4220/4116 VFIR */ +#define IUC_STIR421X 0x80 /* SigmaTel 4210/4220/4116 VFIR */ /* USB class definitions */ #define USB_IRDA_HEADER 0x01 #define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */ #define USB_DT_IRDA 0x21 -#define USB_IRDA_SIGMATEL_HEADER 0x03 -#define IU_SIGMATEL_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + USB_IRDA_SIGMATEL_HEADER) +#define USB_IRDA_STIR421X_HEADER 0x03 +#define IU_SIGMATEL_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + \ + USB_IRDA_STIR421X_HEADER) struct irda_class_desc { __u8 bLength; diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index 98fa531..44efd49 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -386,7 +386,7 @@ static int __irport_change_speed(struct /* Locking notes : this function may be called from irq context with * spinlock, via irport_write_wakeup(), or from non-interrupt without * spinlock (from the task timer). Yuck ! - * This is ugly, and unsafe is the spinlock is not already aquired. + * This is ugly, and unsafe is the spinlock is not already acquired. * This will be fixed when irda-task get rewritten. * Jean II */ if (!spin_is_locked(&self->lock)) { diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c new file mode 100644 index 0000000..754297f --- /dev/null +++ b/drivers/net/irda/mcs7780.c @@ -0,0 +1,1009 @@ +/***************************************************************************** +* +* Filename: mcs7780.c +* Version: 0.4-alpha +* Description: Irda MosChip USB Dongle Driver +* Authors: Lukasz Stelmach +* Brian Pugh +* Judy Fischbach +* +* Based on stir4200 driver, but some things done differently. +* Based on earlier driver by Paul Stewart +* +* Copyright (C) 2000, Roman Weissgaerber +* Copyright (C) 2001, Dag Brattli +* Copyright (C) 2001, Jean Tourrilhes +* Copyright (C) 2004, Stephen Hemminger +* Copyright (C) 2005, Lukasz Stelmach +* Copyright (C) 2005, Brian Pugh +* Copyright (C) 2005, Judy Fischbach +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****************************************************************************/ + +/* + * MCS7780 is a simple USB to IrDA bridge by MosChip. It is neither + * compatibile with irda-usb nor with stir4200. Although it is quite + * similar to the later as far as general idea of operation is concerned. + * That is it requires the software to do all the framing job at SIR speeds. + * The hardware does take care of the framing at MIR and FIR speeds. + * It supports all speeds from 2400 through 4Mbps + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "mcs7780.h" + +#define MCS_VENDOR_ID 0x9710 +#define MCS_PRODUCT_ID 0x7780 + +static struct usb_device_id mcs_table[] = { + /* MosChip Corp., MCS7780 FIR-USB Adapter */ + {USB_DEVICE(MCS_VENDOR_ID, MCS_PRODUCT_ID)}, + {}, +}; + +MODULE_AUTHOR("Brian Pugh "); +MODULE_DESCRIPTION("IrDA-USB Dongle Driver for MosChip MCS7780"); +MODULE_VERSION("0.3alpha"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(usb, mcs_table); + +static int qos_mtt_bits = 0x07 /* > 1ms */ ; +module_param(qos_mtt_bits, int, 0); +MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); + +static int receive_mode = 0x1; +module_param(receive_mode, int, 0); +MODULE_PARM_DESC(receive_mode, + "Receive mode of the device (1:fast, 0:slow, default:1)"); + +static int sir_tweak = 1; +module_param(sir_tweak, int, 0444); +MODULE_PARM_DESC(sir_tweak, + "Default pulse width (1:1.6us, 0:3/16 bit, default:1)."); + +static int transceiver_type = MCS_TSC_VISHAY; +module_param(transceiver_type, int, 0444); +MODULE_PARM_DESC(transceiver_type, "IR transceiver type, see mcs7780.h."); + +struct usb_driver mcs_driver = { + .name = "mcs7780", + .probe = mcs_probe, + .disconnect = mcs_disconnect, + .id_table = mcs_table, +}; + +/* speed flag selection by direct addressing. +addr = (speed >> 8) & 0x0f + +0x1 57600 0x2 115200 0x4 1152000 0x5 9600 +0x6 38400 0x9 2400 0xa 576000 0xb 19200 + +4Mbps (or 2400) must be checked separately. Since it also has +to be programmed in a different manner that is not a big problem. +*/ +static __u16 mcs_speed_set[16] = { 0, + MCS_SPEED_57600, + MCS_SPEED_115200, + 0, + MCS_SPEED_1152000, + MCS_SPEED_9600, + MCS_SPEED_38400, + 0, 0, + MCS_SPEED_2400, + MCS_SPEED_576000, + MCS_SPEED_19200, + 0, 0, 0, +}; + +/* Set given 16 bit register with a 16 bit value. Send control message + * to set dongle register. */ +static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val) +{ + struct usb_device *dev = mcs->usbdev; + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, + MCS_WR_RTYPE, val, reg, NULL, 0, + msecs_to_jiffies(MCS_CTRL_TIMEOUT)); +} + +/* Get 16 bit register value. Send contol message to read dongle register. */ +static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val) +{ + struct usb_device *dev = mcs->usbdev; + int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, + MCS_RD_RTYPE, 0, reg, val, 2, + msecs_to_jiffies(MCS_CTRL_TIMEOUT)); + + return ret; +} + +/* Setup a communication between mcs7780 and TFDU chips. It is described + * in more detail in the data sheet. The setup sequence puts the the + * vishay tranceiver into high speed mode. It will also receive SIR speed + * packets but at reduced sensitivity. + */ + +/* 0: OK 1:ERROR */ +static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs) +{ + int ret = 0; + __u16 rval; + + /* mcs_get_reg should read exactly two bytes from the dongle */ + ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval); + if (unlikely(ret != 2)) { + ret = -EIO; + goto error; + } + + /* The MCS_XCVR_CONF bit puts the transceiver into configuration + * mode. The MCS_MODE0 bit must start out high (1) and then + * transition to low and the MCS_STFIR and MCS_MODE1 bits must + * be low. + */ + rval |= (MCS_MODE0 | MCS_XCVR_CONF); + rval &= ~MCS_STFIR; + rval &= ~MCS_MODE1; + ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); + if (unlikely(ret)) + goto error; + + rval &= ~MCS_MODE0; + ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); + if (unlikely(ret)) + goto error; + + rval &= ~MCS_XCVR_CONF; + ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); + if (unlikely(ret)) + goto error; + + ret = 0; + error: + return ret; +} + +/* Setup a communication between mcs7780 and agilent chip. */ +static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs) +{ + IRDA_WARNING("This transceiver type is not supported yet."); + return 1; +} + +/* Setup a communication between mcs7780 and sharp chip. */ +static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs) +{ + IRDA_WARNING("This transceiver type is not supported yet."); + return 1; +} + +/* Common setup for all transceivers */ +static inline int mcs_setup_transceiver(struct mcs_cb *mcs) +{ + int ret = 0; + __u16 rval; + char *msg; + + msg = "Basic transceiver setup error."; + + /* read value of MODE Register, set the DRIVER and RESET bits + * and write value back out to MODE Register + */ + ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval); + if(unlikely(ret != 2)) + goto error; + rval |= MCS_DRIVER; /* put the mcs7780 into configuration mode. */ + ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); + if(unlikely(ret)) + goto error; + + rval = 0; /* set min pulse width to 0 initially. */ + ret = mcs_set_reg(mcs, MCS_MINRXPW_REG, rval); + if(unlikely(ret)) + goto error; + + ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval); + if(unlikely(ret != 2)) + goto error; + + rval &= ~MCS_FIR; /* turn off fir mode. */ + if(mcs->sir_tweak) + rval |= MCS_SIR16US; /* 1.6us pulse width */ + else + rval &= ~MCS_SIR16US; /* 3/16 bit time pulse width */ + + /* make sure ask mode and back to back packets are off. */ + rval &= ~(MCS_BBTG | MCS_ASK); + + rval &= ~MCS_SPEED_MASK; + rval |= MCS_SPEED_9600; /* make sure initial speed is 9600. */ + mcs->speed = 9600; + mcs->new_speed = 0; /* new_speed is set to 0 */ + rval &= ~MCS_PLLPWDN; /* disable power down. */ + + /* make sure device determines direction and that the auto send sip + * pulse are on. + */ + rval |= MCS_DTD | MCS_SIPEN; + + ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); + if(unlikely(ret)) + goto error; + + msg = "transceiver model specific setup error."; + switch (mcs->transceiver_type) { + case MCS_TSC_VISHAY: + ret = mcs_setup_transceiver_vishay(mcs); + break; + + case MCS_TSC_SHARP: + ret = mcs_setup_transceiver_sharp(mcs); + break; + + case MCS_TSC_AGILENT: + ret = mcs_setup_transceiver_agilent(mcs); + break; + + default: + IRDA_WARNING("Unknown transceiver type: %d", + mcs->transceiver_type); + ret = 1; + } + if (unlikely(ret)) + goto error; + + /* If transceiver is not SHARP, then if receive mode set + * on the RXFAST bit in the XCVR Register otherwise unset it + */ + if (mcs->transceiver_type != MCS_TSC_SHARP) { + + ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval); + if (unlikely(ret != 2)) + goto error; + if (mcs->receive_mode) + rval |= MCS_RXFAST; + else + rval &= ~MCS_RXFAST; + ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); + if (unlikely(ret)) + goto error; + } + + msg = "transceiver reset."; + + ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval); + if (unlikely(ret != 2)) + goto error; + + /* reset the mcs7780 so all changes take effect. */ + rval &= ~MCS_RESET; + ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); + if (unlikely(ret)) + goto error; + else + return ret; + +error: + IRDA_ERROR("%s", msg); + return ret; +} + +/* Wraps the data in format for SIR */ +static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf) +{ + int wraplen; + + /* 2: full frame length, including "the length" */ + wraplen = async_wrap_skb(skb, buf + 2, 4094); + + wraplen += 2; + buf[0] = wraplen & 0xff; + buf[1] = (wraplen >> 8) & 0xff; + + return wraplen; +} + +/* Wraps the data in format for FIR */ +static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf) +{ + unsigned int len = 0; + __u32 fcs = ~(crc32_le(~0, skb->data, skb->len)); + + /* add 2 bytes for length value and 4 bytes for fcs. */ + len = skb->len + 6; + + /* The mcs7780 requires that the first two bytes are the packet + * length in little endian order. Note: the length value includes + * the two bytes for the length value itself. + */ + buf[0] = len & 0xff; + buf[1] = (len >> 8) & 0xff; + /* copy the data into the tx buffer. */ + memcpy(buf+2, skb->data, skb->len); + /* put the fcs in the last four bytes in little endian order. */ + buf[len - 4] = fcs & 0xff; + buf[len - 3] = (fcs >> 8) & 0xff; + buf[len - 2] = (fcs >> 16) & 0xff; + buf[len - 1] = (fcs >> 24) & 0xff; + + return len; +} + +/* Wraps the data in format for MIR */ +static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf) +{ + __u16 fcs = 0; + int len = skb->len + 4; + + fcs = ~(irda_calc_crc16(~fcs, skb->data, skb->len)); + /* put the total packet length in first. Note: packet length + * value includes the two bytes that hold the packet length + * itself. + */ + buf[0] = len & 0xff; + buf[1] = (len >> 8) & 0xff; + /* copy the data */ + memcpy(buf+2, skb->data, skb->len); + /* put the fcs in last two bytes in little endian order. */ + buf[len - 2] = fcs & 0xff; + buf[len - 1] = (fcs >> 8) & 0xff; + + return len; +} + +/* Unwrap received packets at MIR speed. A 16 bit crc_ccitt checksum is + * used for the fcs. When performed over the entire packet the result + * should be GOOD_FCS = 0xf0b8. Hands the unwrapped data off to the IrDA + * layer via a sk_buff. + */ +static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len) +{ + __u16 fcs; + int new_len; + struct sk_buff *skb; + + /* Assume that the frames are going to fill a single packet + * rather than span multiple packets. + */ + + new_len = len - 2; + if(unlikely(new_len <= 0)) { + IRDA_ERROR("%s short frame length %d\n", + mcs->netdev->name, new_len); + ++mcs->stats.rx_errors; + ++mcs->stats.rx_length_errors; + return; + } + fcs = 0; + fcs = irda_calc_crc16(~fcs, buf, len); + + if(fcs != GOOD_FCS) { + IRDA_ERROR("crc error calc 0x%x len %d\n", + fcs, new_len); + mcs->stats.rx_errors++; + mcs->stats.rx_crc_errors++; + return; + } + + skb = dev_alloc_skb(new_len + 1); + if(unlikely(!skb)) { + ++mcs->stats.rx_dropped; + return; + } + + skb_reserve(skb, 1); + memcpy(skb->data, buf, new_len); + skb_put(skb, new_len); + skb->mac.raw = skb->data; + skb->protocol = htons(ETH_P_IRDA); + skb->dev = mcs->netdev; + + netif_rx(skb); + + mcs->stats.rx_packets++; + mcs->stats.rx_bytes += new_len; + + return; +} + +/* Unwrap received packets at FIR speed. A 32 bit crc_ccitt checksum is + * used for the fcs. Hands the unwrapped data off to the IrDA + * layer via a sk_buff. + */ +static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len) +{ + __u32 fcs; + int new_len; + struct sk_buff *skb; + + /* Assume that the frames are going to fill a single packet + * rather than span multiple packets. This is most likely a false + * assumption. + */ + + new_len = len - 4; + if(unlikely(new_len <= 0)) { + IRDA_ERROR("%s short frame length %d\n", + mcs->netdev->name, new_len); + ++mcs->stats.rx_errors; + ++mcs->stats.rx_length_errors; + return; + } + + fcs = ~(crc32_le(~0, buf, new_len)); + if(fcs != le32_to_cpu(get_unaligned((u32 *)(buf+new_len)))) { + IRDA_ERROR("crc error calc 0x%x len %d\n", fcs, new_len); + mcs->stats.rx_errors++; + mcs->stats.rx_crc_errors++; + return; + } + + skb = dev_alloc_skb(new_len + 1); + if(unlikely(!skb)) { + ++mcs->stats.rx_dropped; + return; + } + + skb_reserve(skb, 1); + memcpy(skb->data, buf, new_len); + skb_put(skb, new_len); + skb->mac.raw = skb->data; + skb->protocol = htons(ETH_P_IRDA); + skb->dev = mcs->netdev; + + netif_rx(skb); + + mcs->stats.rx_packets++; + mcs->stats.rx_bytes += new_len; + + return; +} + + +/* Allocates urbs for both receive and transmit. + * If alloc fails return error code 0 (fail) otherwise + * return error code 1 (success). + */ +static inline int mcs_setup_urbs(struct mcs_cb *mcs) +{ + mcs->rx_urb = NULL; + + mcs->tx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!mcs->tx_urb) + return 0; + + mcs->rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!mcs->rx_urb) + return 0; + + return 1; +} + +/* Sets up state to be initially outside frame, gets receive urb, + * sets status to successful and then submits the urb to start + * receiving the data. + */ +static inline int mcs_receive_start(struct mcs_cb *mcs) +{ + mcs->rx_buff.in_frame = FALSE; + mcs->rx_buff.state = OUTSIDE_FRAME; + + usb_fill_bulk_urb(mcs->rx_urb, mcs->usbdev, + usb_rcvbulkpipe(mcs->usbdev, mcs->ep_in), + mcs->in_buf, 4096, mcs_receive_irq, mcs); + + mcs->rx_urb->status = 0; + return usb_submit_urb(mcs->rx_urb, GFP_KERNEL); +} + +/* Finds the in and out endpoints for the mcs control block */ +static inline int mcs_find_endpoints(struct mcs_cb *mcs, + struct usb_host_endpoint *ep, int epnum) +{ + int i; + int ret = 0; + + /* If no place to store the endpoints just return */ + if (!ep) + return ret; + + /* cycle through all endpoints, find the first two that are DIR_IN */ + for (i = 0; i < epnum; i++) { + if (ep[i].desc.bEndpointAddress & USB_DIR_IN) + mcs->ep_in = ep[i].desc.bEndpointAddress; + else + mcs->ep_out = ep[i].desc.bEndpointAddress; + + /* MosChip says that the chip has only two bulk + * endpoints. Find one for each direction and move on. + */ + if ((mcs->ep_in != 0) && (mcs->ep_out != 0)) { + ret = 1; + break; + } + } + + return ret; +} + +static void mcs_speed_work(void *arg) +{ + struct mcs_cb *mcs = arg; + struct net_device *netdev = mcs->netdev; + + mcs_speed_change(mcs); + netif_wake_queue(netdev); +} + +/* Function to change the speed of the mcs7780. Fully supports SIR, + * MIR, and FIR speeds. + */ +static int mcs_speed_change(struct mcs_cb *mcs) +{ + int ret = 0; + int rst = 0; + int cnt = 0; + __u16 nspeed; + __u16 rval; + + nspeed = mcs_speed_set[(mcs->new_speed >> 8) & 0x0f]; + + do { + mcs_get_reg(mcs, MCS_RESV_REG, &rval); + } while(cnt++ < 100 && (rval & MCS_IRINTX)); + + if(cnt >= 100) { + IRDA_ERROR("unable to change speed"); + ret = -EIO; + goto error; + } + + mcs_get_reg(mcs, MCS_MODE_REG, &rval); + + /* MINRXPW values recomended by MosChip */ + if (mcs->new_speed <= 115200) { + rval &= ~MCS_FIR; + + if ((rst = (mcs->speed > 115200))) + mcs_set_reg(mcs, MCS_MINRXPW_REG, 0); + + } else if (mcs->new_speed <= 1152000) { + rval &= ~MCS_FIR; + + if ((rst = !(mcs->speed == 576000 || mcs->speed == 1152000))) + mcs_set_reg(mcs, MCS_MINRXPW_REG, 5); + + } else { + rval |= MCS_FIR; + + if ((rst = (mcs->speed != 4000000))) + mcs_set_reg(mcs, MCS_MINRXPW_REG, 5); + + } + + rval &= ~MCS_SPEED_MASK; + rval |= nspeed; + + ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); + if (unlikely(ret)) + goto error; + + if (rst) + switch (mcs->transceiver_type) { + case MCS_TSC_VISHAY: + ret = mcs_setup_transceiver_vishay(mcs); + break; + + case MCS_TSC_SHARP: + ret = mcs_setup_transceiver_sharp(mcs); + break; + + case MCS_TSC_AGILENT: + ret = mcs_setup_transceiver_agilent(mcs); + break; + + default: + ret = 1; + IRDA_WARNING("Unknown transceiver type: %d", + mcs->transceiver_type); + } + if (unlikely(ret)) + goto error; + + mcs_get_reg(mcs, MCS_MODE_REG, &rval); + rval &= ~MCS_RESET; + ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); + + mcs->speed = mcs->new_speed; + error: + mcs->new_speed = 0; + return ret; +} + +/* Ioctl calls not supported at this time. Can be an area of future work. */ +static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) +{ + /* struct if_irda_req *irq = (struct if_irda_req *)rq; */ + /* struct mcs_cb *mcs = netdev_priv(netdev); */ + int ret = 0; + + switch (cmd) { + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +/* Network device is taken down, done by "ifconfig irda0 down" */ +static int mcs_net_close(struct net_device *netdev) +{ + int ret = 0; + struct mcs_cb *mcs = netdev_priv(netdev); + + /* Stop transmit processing */ + netif_stop_queue(netdev); + + /* kill and free the receive and transmit URBs */ + usb_kill_urb(mcs->rx_urb); + usb_free_urb(mcs->rx_urb); + usb_kill_urb(mcs->tx_urb); + usb_free_urb(mcs->tx_urb); + + /* Stop and remove instance of IrLAP */ + if (mcs->irlap) + irlap_close(mcs->irlap); + + mcs->irlap = NULL; + return ret; +} + +/* Network device is taken up, done by "ifconfig irda0 up" */ +static int mcs_net_open(struct net_device *netdev) +{ + struct mcs_cb *mcs = netdev_priv(netdev); + char hwname[16]; + int ret = 0; + + ret = usb_clear_halt(mcs->usbdev, + usb_sndbulkpipe(mcs->usbdev, mcs->ep_in)); + if (ret) + goto error1; + ret = usb_clear_halt(mcs->usbdev, + usb_rcvbulkpipe(mcs->usbdev, mcs->ep_out)); + if (ret) + goto error1; + + ret = mcs_setup_transceiver(mcs); + if (ret) + goto error1; + + ret = -ENOMEM; + + /* Initialize for SIR/FIR to copy data directly into skb. */ + mcs->receiving = 0; + mcs->rx_buff.truesize = IRDA_SKB_MAX_MTU; + mcs->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); + if (!mcs->rx_buff.skb) + goto error1; + + skb_reserve(mcs->rx_buff.skb, 1); + mcs->rx_buff.head = mcs->rx_buff.skb->data; + do_gettimeofday(&mcs->rx_time); + + /* + * Now that everything should be initialized properly, + * Open new IrLAP layer instance to take care of us... + * Note : will send immediately a speed change... + */ + sprintf(hwname, "usb#%d", mcs->usbdev->devnum); + mcs->irlap = irlap_open(netdev, &mcs->qos, hwname); + if (!mcs->irlap) { + IRDA_ERROR("mcs7780: irlap_open failed"); + goto error2; + } + + if (!mcs_setup_urbs(mcs)) + goto error3; + + ret = mcs_receive_start(mcs); + if (ret) + goto error3; + + netif_start_queue(netdev); + return 0; + + error3: + irlap_close(mcs->irlap); + error2: + kfree_skb(mcs->rx_buff.skb); + error1: + return ret; +} + + +/* Get device stats for /proc/net/dev and ifconfig */ +static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev) +{ + struct mcs_cb *mcs = netdev_priv(netdev); + return &mcs->stats; +} + +/* Receive callback function. */ +static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs) +{ + __u8 *bytes; + struct mcs_cb *mcs = urb->context; + int i; + int ret; + + if (!netif_running(mcs->netdev)) + return; + + if (urb->status) + return; + + if (urb->actual_length > 0) { + bytes = urb->transfer_buffer; + + /* MCS returns frames without BOF and EOF + * I assume it returns whole frames. + */ + /* SIR speed */ + if(mcs->speed < 576000) { + async_unwrap_char(mcs->netdev, &mcs->stats, + &mcs->rx_buff, 0xc0); + + for (i = 0; i < urb->actual_length; i++) + async_unwrap_char(mcs->netdev, &mcs->stats, + &mcs->rx_buff, bytes[i]); + + async_unwrap_char(mcs->netdev, &mcs->stats, + &mcs->rx_buff, 0xc1); + } + /* MIR speed */ + else if(mcs->speed == 576000 || mcs->speed == 1152000) { + mcs_unwrap_mir(mcs, urb->transfer_buffer, + urb->actual_length); + } + /* FIR speed */ + else { + mcs_unwrap_fir(mcs, urb->transfer_buffer, + urb->actual_length); + } + mcs->netdev->last_rx = jiffies; + do_gettimeofday(&mcs->rx_time); + } + + ret = usb_submit_urb(urb, GFP_ATOMIC); +} + +/* Transmit callback funtion. */ +static void mcs_send_irq(struct urb *urb, struct pt_regs *regs) +{ + struct mcs_cb *mcs = urb->context; + struct net_device *ndev = mcs->netdev; + + if (unlikely(mcs->new_speed)) + schedule_work(&mcs->work); + else + netif_wake_queue(ndev); +} + +/* Transmit callback funtion. */ +static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + unsigned long flags; + struct mcs_cb *mcs; + int wraplen; + int ret = 0; + + + if (skb == NULL || ndev == NULL) + return -EINVAL; + + netif_stop_queue(ndev); + mcs = netdev_priv(ndev); + + spin_lock_irqsave(&mcs->lock, flags); + + mcs->new_speed = irda_get_next_speed(skb); + if (likely(mcs->new_speed == mcs->speed)) + mcs->new_speed = 0; + + /* SIR speed */ + if(mcs->speed < 576000) { + wraplen = mcs_wrap_sir_skb(skb, mcs->out_buf); + } + /* MIR speed */ + else if(mcs->speed == 576000 || mcs->speed == 1152000) { + wraplen = mcs_wrap_mir_skb(skb, mcs->out_buf); + } + /* FIR speed */ + else { + wraplen = mcs_wrap_fir_skb(skb, mcs->out_buf); + } + usb_fill_bulk_urb(mcs->tx_urb, mcs->usbdev, + usb_sndbulkpipe(mcs->usbdev, mcs->ep_out), + mcs->out_buf, wraplen, mcs_send_irq, mcs); + + if ((ret = usb_submit_urb(mcs->tx_urb, GFP_ATOMIC))) { + IRDA_ERROR("failed tx_urb: %d", ret); + switch (ret) { + case -ENODEV: + case -EPIPE: + break; + default: + mcs->stats.tx_errors++; + netif_start_queue(ndev); + } + } else { + mcs->stats.tx_packets++; + mcs->stats.tx_bytes += skb->len; + } + + dev_kfree_skb(skb); + spin_unlock_irqrestore(&mcs->lock, flags); + return ret; +} + +/* + * This function is called by the USB subsystem for each new device in the + * system. Need to verify the device and if it is, then start handling it. + */ +static int mcs_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct net_device *ndev = NULL; + struct mcs_cb *mcs; + int ret = -ENOMEM; + + ndev = alloc_irdadev(sizeof(*mcs)); + if (!ndev) + goto error1; + + IRDA_DEBUG(1, "MCS7780 USB-IrDA bridge found at %d.", udev->devnum); + + /* what is it realy for? */ + SET_MODULE_OWNER(ndev); + SET_NETDEV_DEV(ndev, &intf->dev); + + ret = usb_reset_configuration(udev); + if (ret != 0) { + IRDA_ERROR("mcs7780: usb reset configuration failed"); + goto error2; + } + + mcs = netdev_priv(ndev); + mcs->usbdev = udev; + mcs->netdev = ndev; + spin_lock_init(&mcs->lock); + + /* Initialize QoS for this device */ + irda_init_max_qos_capabilies(&mcs->qos); + + /* That's the Rx capability. */ + mcs->qos.baud_rate.bits &= + IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200 + | IR_576000 | IR_1152000 | (IR_4000000 << 8); + + + mcs->qos.min_turn_time.bits &= qos_mtt_bits; + irda_qos_bits_to_value(&mcs->qos); + + /* Speed change work initialisation*/ + INIT_WORK(&mcs->work, mcs_speed_work, mcs); + + /* Override the network functions we need to use */ + ndev->hard_start_xmit = mcs_hard_xmit; + ndev->open = mcs_net_open; + ndev->stop = mcs_net_close; + ndev->get_stats = mcs_net_get_stats; + ndev->do_ioctl = mcs_net_ioctl; + + if (!intf->cur_altsetting) + goto error2; + + ret = mcs_find_endpoints(mcs, intf->cur_altsetting->endpoint, + intf->cur_altsetting->desc.bNumEndpoints); + if (!ret) { + ret = -ENODEV; + goto error2; + } + + ret = register_netdev(ndev); + if (ret != 0) + goto error2; + + IRDA_DEBUG(1, "IrDA: Registered MosChip MCS7780 device as %s", + ndev->name); + + mcs->transceiver_type = transceiver_type; + mcs->sir_tweak = sir_tweak; + mcs->receive_mode = receive_mode; + + usb_set_intfdata(intf, mcs); + return 0; + + error2: + free_netdev(ndev); + + error1: + return ret; +} + +/* The current device is removed, the USB layer tells us to shut down. */ +static void mcs_disconnect(struct usb_interface *intf) +{ + struct mcs_cb *mcs = usb_get_intfdata(intf); + + if (!mcs) + return; + + flush_scheduled_work(); + + unregister_netdev(mcs->netdev); + free_netdev(mcs->netdev); + + usb_set_intfdata(intf, NULL); + IRDA_DEBUG(0, "MCS7780 now disconnected."); +} + +/* Module insertion */ +static int __init mcs_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&mcs_driver); + if (result) + IRDA_ERROR("usb_register failed. Error number %d", result); + + return result; +} +module_init(mcs_init); + +/* Module removal */ +static void __exit mcs_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&mcs_driver); +} +module_exit(mcs_exit); + diff --git a/drivers/net/irda/mcs7780.h b/drivers/net/irda/mcs7780.h new file mode 100644 index 0000000..1a723d7 --- /dev/null +++ b/drivers/net/irda/mcs7780.h @@ -0,0 +1,167 @@ +/***************************************************************************** +* +* Filename: mcs7780.h +* Version: 0.2-alpha +* Description: Irda MosChip USB Dongle +* Status: Experimental +* Authors: Lukasz Stelmach +* Brian Pugh +* +* Copyright (C) 2005, Lukasz Stelmach +* Copyright (C) 2005, Brian Pugh +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****************************************************************************/ +#ifndef _MCS7780_H +#define _MCS7780_H + +#define MCS_MODE_SIR 0 +#define MCS_MODE_MIR 1 +#define MCS_MODE_FIR 2 + +#define MCS_CTRL_TIMEOUT 500 +#define MCS_XMIT_TIMEOUT 500 +/* Possible transceiver types */ +#define MCS_TSC_VISHAY 0 /* Vishay TFD, default choice */ +#define MCS_TSC_AGILENT 1 /* Agilent 3602/3600 */ +#define MCS_TSC_SHARP 2 /* Sharp GP2W1000YP */ + +/* Requests */ +#define MCS_RD_RTYPE 0xC0 +#define MCS_WR_RTYPE 0x40 +#define MCS_RDREQ 0x0F +#define MCS_WRREQ 0x0E + +/* Register 0x00 */ +#define MCS_MODE_REG 0 +#define MCS_FIR ((__u16)0x0001) +#define MCS_SIR16US ((__u16)0x0002) +#define MCS_BBTG ((__u16)0x0004) +#define MCS_ASK ((__u16)0x0008) +#define MCS_PARITY ((__u16)0x0010) + +/* SIR/MIR speed constants */ +#define MCS_SPEED_SHIFT 5 +#define MCS_SPEED_MASK ((__u16)0x00E0) +#define MCS_SPEED(x) ((x & MCS_SPEED_MASK) >> MCS_SPEED_SHIFT) +#define MCS_SPEED_2400 ((0 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_9600 ((1 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_19200 ((2 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_38400 ((3 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_57600 ((4 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_115200 ((5 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_576000 ((6 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_1152000 ((7 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) + +#define MCS_PLLPWDN ((__u16)0x0100) +#define MCS_DRIVER ((__u16)0x0200) +#define MCS_DTD ((__u16)0x0400) +#define MCS_DIR ((__u16)0x0800) +#define MCS_SIPEN ((__u16)0x1000) +#define MCS_SENDSIP ((__u16)0x2000) +#define MCS_CHGDIR ((__u16)0x4000) +#define MCS_RESET ((__u16)0x8000) + +/* Register 0x02 */ +#define MCS_XCVR_REG 2 +#define MCS_MODE0 ((__u16)0x0001) +#define MCS_STFIR ((__u16)0x0002) +#define MCS_XCVR_CONF ((__u16)0x0004) +#define MCS_RXFAST ((__u16)0x0008) +/* TXCUR [6:4] */ +#define MCS_TXCUR_SHIFT 4 +#define MCS_TXCUR_MASK ((__u16)0x0070) +#define MCS_TXCUR(x) ((x & MCS_TXCUR_MASK) >> MCS_TXCUR_SHIFT) +#define MCS_SETTXCUR(x,y) \ + ((x & ~MCS_TXCUR_MASK) | (y << MCS_TXCUR_SHIFT) & MCS_TXCUR_MASK) + +#define MCS_MODE1 ((__u16)0x0080) +#define MCS_SMODE0 ((__u16)0x0100) +#define MCS_SMODE1 ((__u16)0x0200) +#define MCS_INVTX ((__u16)0x0400) +#define MCS_INVRX ((__u16)0x0800) + +#define MCS_MINRXPW_REG 4 + +#define MCS_RESV_REG 7 +#define MCS_IRINTX ((__u16)0x0001) +#define MCS_IRINRX ((__u16)0x0002) + +struct mcs_cb { + struct usb_device *usbdev; /* init: probe_irda */ + struct net_device *netdev; /* network layer */ + struct irlap_cb *irlap; /* The link layer we are binded to */ + struct net_device_stats stats; /* network statistics */ + struct qos_info qos; + unsigned int speed; /* Current speed */ + unsigned int new_speed; /* new speed */ + + struct work_struct work; /* Change speed work */ + + struct sk_buff *tx_pending; + char in_buf[4096]; /* transmit/receive buffer */ + char out_buf[4096]; /* transmit/receive buffer */ + __u8 *fifo_status; + + iobuff_t rx_buff; /* receive unwrap state machine */ + struct timeval rx_time; + spinlock_t lock; + int receiving; + + __u8 ep_in; + __u8 ep_out; + + struct urb *rx_urb; + struct urb *tx_urb; + + int transceiver_type; + int sir_tweak; + int receive_mode; +}; + +static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val); +static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val); + +static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs); +static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs); +static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs); +static inline int mcs_setup_transceiver(struct mcs_cb *mcs); +static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf); +static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf); +static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf); +static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len); +static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len); +static inline int mcs_setup_urbs(struct mcs_cb *mcs); +static inline int mcs_receive_start(struct mcs_cb *mcs); +static inline int mcs_find_endpoints(struct mcs_cb *mcs, + struct usb_host_endpoint *ep, int epnum); + +static int mcs_speed_change(struct mcs_cb *mcs); + +static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd); +static int mcs_net_close(struct net_device *netdev); +static int mcs_net_open(struct net_device *netdev); +static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev); + +static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs); +static void mcs_send_irq(struct urb *urb, struct pt_regs *regs); +static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *netdev); + +static int mcs_probe(struct usb_interface *intf, + const struct usb_device_id *id); +static void mcs_disconnect(struct usb_interface *intf); + +#endif /* _MCS7780_H */ diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index cc7ff8f..cb62f2a 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c @@ -115,8 +115,12 @@ static nsc_chip_t chips[] = { /* Contributed by Jan Frey - IBM A30/A31 */ { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, nsc_ircc_probe_39x, nsc_ircc_init_39x }, - { "IBM", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff, - nsc_ircc_probe_39x, nsc_ircc_init_39x }, + /* IBM ThinkPads using PC8738x (T60/X60/Z60) */ + { "IBM-PC8738x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff, + nsc_ircc_probe_39x, nsc_ircc_init_39x }, + /* IBM ThinkPads using PC8394T (T43/R52/?) */ + { "IBM-PC8394T", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf9, 0xff, + nsc_ircc_probe_39x, nsc_ircc_init_39x }, { NULL } }; diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c index 31867e4..d61b208 100644 --- a/drivers/net/irda/stir4200.c +++ b/drivers/net/irda/stir4200.c @@ -50,6 +50,7 @@ #include #include #include #include +#include #include #include #include @@ -173,9 +174,7 @@ struct stir_cb { struct qos_info qos; unsigned speed; /* Current speed */ - wait_queue_head_t thr_wait; /* transmit thread wakeup */ - struct completion thr_exited; - pid_t thr_pid; + struct task_struct *thread; /* transmit thread */ struct sk_buff *tx_pending; void *io_buf; /* transmit/receive buffer */ @@ -577,7 +576,7 @@ static int stir_hard_xmit(struct sk_buff SKB_LINEAR_ASSERT(skb); skb = xchg(&stir->tx_pending, skb); - wake_up(&stir->thr_wait); + wake_up_process(stir->thread); /* this should never happen unless stop/wakeup problem */ if (unlikely(skb)) { @@ -753,13 +752,7 @@ static int stir_transmit_thread(void *ar struct net_device *dev = stir->netdev; struct sk_buff *skb; - daemonize("%s", dev->name); - allow_signal(SIGTERM); - - while (netif_running(dev) - && netif_device_present(dev) - && !signal_pending(current)) - { + while (!kthread_should_stop()) { #ifdef CONFIG_PM /* if suspending, then power off and wait */ if (unlikely(freezing(current))) { @@ -813,10 +806,11 @@ #endif } /* sleep if nothing to send */ - wait_event_interruptible(stir->thr_wait, stir->tx_pending); - } + set_current_state(TASK_INTERRUPTIBLE); + schedule(); - complete_and_exit (&stir->thr_exited, 0); + } + return 0; } @@ -859,7 +853,7 @@ static void stir_rcv_irq(struct urb *urb warn("%s: usb receive submit error: %d", stir->netdev->name, err); stir->receiving = 0; - wake_up(&stir->thr_wait); + wake_up_process(stir->thread); } } @@ -928,10 +922,10 @@ static int stir_net_open(struct net_devi } /** Start kernel thread for transmit. */ - stir->thr_pid = kernel_thread(stir_transmit_thread, stir, - CLONE_FS|CLONE_FILES); - if (stir->thr_pid < 0) { - err = stir->thr_pid; + stir->thread = kthread_run(stir_transmit_thread, stir, + "%s", stir->netdev->name); + if (IS_ERR(stir->thread)) { + err = PTR_ERR(stir->thread); err("stir4200: unable to start kernel thread"); goto err_out6; } @@ -968,8 +962,7 @@ static int stir_net_close(struct net_dev netif_stop_queue(netdev); /* Kill transmit thread */ - kill_proc(stir->thr_pid, SIGTERM, 1); - wait_for_completion(&stir->thr_exited); + kthread_stop(stir->thread); kfree(stir->fifo_status); /* Mop up receive urb's */ @@ -1084,9 +1077,6 @@ static int stir_probe(struct usb_interfa stir->qos.min_turn_time.bits &= qos_mtt_bits; irda_qos_bits_to_value(&stir->qos); - init_completion (&stir->thr_exited); - init_waitqueue_head (&stir->thr_wait); - /* Override the network functions we need to use */ net->hard_start_xmit = stir_hard_xmit; net->open = stir_net_open; diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index 97a49e0..d70b9e8 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -959,7 +959,7 @@ static int vlsi_hard_start_xmit(struct s || (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec)) break; udelay(100); - /* must not sleep here - we are called under xmit_lock! */ + /* must not sleep here - called under netif_tx_lock! */ } } diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index f0f04be..93394d7 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -69,6 +69,7 @@ #include #include #include #include +#include #include #include @@ -1035,11 +1036,22 @@ static struct ethtool_ops ops = { .get_link = veth_get_link, }; -static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) +static struct net_device * __init veth_probe_one(int vlan, + struct vio_dev *vio_dev) { struct net_device *dev; struct veth_port *port; + struct device *vdev = &vio_dev->dev; int i, rc; + const unsigned char *mac_addr; + + mac_addr = vio_get_attribute(vio_dev, "local-mac-address", NULL); + if (mac_addr == NULL) + mac_addr = vio_get_attribute(vio_dev, "mac-address", NULL); + if (mac_addr == NULL) { + veth_error("Unable to fetch MAC address from device tree.\n"); + return NULL; + } dev = alloc_etherdev(sizeof (struct veth_port)); if (! dev) { @@ -1064,16 +1076,11 @@ static struct net_device * __init veth_p } port->dev = vdev; - dev->dev_addr[0] = 0x02; - dev->dev_addr[1] = 0x01; - dev->dev_addr[2] = 0xff; - dev->dev_addr[3] = vlan; - dev->dev_addr[4] = 0xff; - dev->dev_addr[5] = this_lp; + memcpy(dev->dev_addr, mac_addr, ETH_ALEN); dev->mtu = VETH_MAX_MTU; - memcpy(&port->mac_addr, dev->dev_addr, 6); + memcpy(&port->mac_addr, mac_addr, ETH_ALEN); dev->open = veth_open; dev->hard_start_xmit = veth_start_xmit; @@ -1608,7 +1615,7 @@ static int veth_probe(struct vio_dev *vd struct net_device *dev; struct veth_port *port; - dev = veth_probe_one(i, &vdev->dev); + dev = veth_probe_one(i, vdev); if (dev == NULL) { veth_remove(vdev); return 1; @@ -1641,7 +1648,7 @@ static int veth_probe(struct vio_dev *vd * support. */ static struct vio_device_id veth_device_table[] __devinitdata = { - { "vlan", "" }, + { "network", "IBM,iSeries-l-lan" }, { "", "" } }; MODULE_DEVICE_TABLE(vio, veth_device_table); diff --git a/drivers/net/ixgb/Makefile b/drivers/net/ixgb/Makefile index 7c7aff1..a8a2d3d 100644 --- a/drivers/net/ixgb/Makefile +++ b/drivers/net/ixgb/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # -# Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. +# Copyright(c) 1999 - 2006 Intel Corporation. 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 diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h index c83271b..a83ef28 100644 --- a/drivers/net/ixgb/ixgb.h +++ b/drivers/net/ixgb/ixgb.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -84,7 +84,12 @@ #else #define IXGB_DBG(args...) #endif -#define IXGB_ERR(args...) printk(KERN_ERR "ixgb: " args) +#define PFX "ixgb: " +#define DPRINTK(nlevel, klevel, fmt, args...) \ + (void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \ + printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \ + __FUNCTION__ , ## args)) + /* TX/RX descriptor defines */ #define DEFAULT_TXD 256 @@ -175,6 +180,7 @@ struct ixgb_adapter { uint64_t hw_csum_tx_good; uint64_t hw_csum_tx_error; uint32_t tx_int_delay; + uint32_t tx_timeout_count; boolean_t tx_int_delay_enable; boolean_t detect_tx_hung; @@ -192,7 +198,9 @@ struct ixgb_adapter { /* structs defined in ixgb_hw.h */ struct ixgb_hw hw; + u16 msg_enable; struct ixgb_hw_stats stats; + uint32_t alloc_rx_buff_failed; #ifdef CONFIG_PCI_MSI boolean_t have_msi; #endif diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c index 661a46b..8357c55 100644 --- a/drivers/net/ixgb/ixgb_ee.c +++ b/drivers/net/ixgb/ixgb_ee.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 diff --git a/drivers/net/ixgb/ixgb_ee.h b/drivers/net/ixgb/ixgb_ee.h index 5190aa8..bf6fa22 100644 --- a/drivers/net/ixgb/ixgb_ee.h +++ b/drivers/net/ixgb/ixgb_ee.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index d38ade5..cf19b89 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -44,6 +44,8 @@ extern void ixgb_free_rx_resources(struc extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter); extern void ixgb_update_stats(struct ixgb_adapter *adapter); +#define IXGB_ALL_RAR_ENTRIES 16 + struct ixgb_stats { char stat_string[ETH_GSTRING_LEN]; int sizeof_stat; @@ -76,6 +78,7 @@ static struct ixgb_stats ixgb_gstrings_s {"tx_heartbeat_errors", IXGB_STAT(net_stats.tx_heartbeat_errors)}, {"tx_window_errors", IXGB_STAT(net_stats.tx_window_errors)}, {"tx_deferred_ok", IXGB_STAT(stats.dc)}, + {"tx_timeout_count", IXGB_STAT(tx_timeout_count) }, {"rx_long_length_errors", IXGB_STAT(stats.roc)}, {"rx_short_length_errors", IXGB_STAT(stats.ruc)}, #ifdef NETIF_F_TSO @@ -117,6 +120,16 @@ ixgb_get_settings(struct net_device *net return 0; } +static void ixgb_set_speed_duplex(struct net_device *netdev) +{ + struct ixgb_adapter *adapter = netdev_priv(netdev); + /* be optimistic about our link, since we were up before */ + adapter->link_speed = 10000; + adapter->link_duplex = FULL_DUPLEX; + netif_carrier_on(netdev); + netif_wake_queue(netdev); +} + static int ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { @@ -130,12 +143,7 @@ ixgb_set_settings(struct net_device *net ixgb_down(adapter, TRUE); ixgb_reset(adapter); ixgb_up(adapter); - /* be optimistic about our link, since we were up before */ - adapter->link_speed = 10000; - adapter->link_duplex = FULL_DUPLEX; - netif_carrier_on(netdev); - netif_wake_queue(netdev); - + ixgb_set_speed_duplex(netdev); } else ixgb_reset(adapter); @@ -183,11 +191,7 @@ ixgb_set_pauseparam(struct net_device *n if(netif_running(adapter->netdev)) { ixgb_down(adapter, TRUE); ixgb_up(adapter); - /* be optimistic about our link, since we were up before */ - adapter->link_speed = 10000; - adapter->link_duplex = FULL_DUPLEX; - netif_carrier_on(netdev); - netif_wake_queue(netdev); + ixgb_set_speed_duplex(netdev); } else ixgb_reset(adapter); @@ -212,11 +216,7 @@ ixgb_set_rx_csum(struct net_device *netd if(netif_running(netdev)) { ixgb_down(adapter,TRUE); ixgb_up(adapter); - /* be optimistic about our link, since we were up before */ - adapter->link_speed = 10000; - adapter->link_duplex = FULL_DUPLEX; - netif_carrier_on(netdev); - netif_wake_queue(netdev); + ixgb_set_speed_duplex(netdev); } else ixgb_reset(adapter); return 0; @@ -251,6 +251,19 @@ ixgb_set_tso(struct net_device *netdev, } #endif /* NETIF_F_TSO */ +static uint32_t +ixgb_get_msglevel(struct net_device *netdev) +{ + struct ixgb_adapter *adapter = netdev_priv(netdev); + return adapter->msg_enable; +} + +static void +ixgb_set_msglevel(struct net_device *netdev, uint32_t data) +{ + struct ixgb_adapter *adapter = netdev_priv(netdev); + adapter->msg_enable = data; +} #define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_ static int @@ -303,7 +316,7 @@ ixgb_get_regs(struct net_device *netdev, *reg++ = IXGB_READ_REG(hw, RXCSUM); /* 20 */ /* there are 16 RAR entries in hardware, we only use 3 */ - for(i = 0; i < 16; i++) { + for(i = 0; i < IXGB_ALL_RAR_ENTRIES; i++) { *reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */ *reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */ } @@ -593,11 +606,7 @@ ixgb_set_ringparam(struct net_device *ne adapter->tx_ring = tx_new; if((err = ixgb_up(adapter))) return err; - /* be optimistic about our link, since we were up before */ - adapter->link_speed = 10000; - adapter->link_duplex = FULL_DUPLEX; - netif_carrier_on(netdev); - netif_wake_queue(netdev); + ixgb_set_speed_duplex(netdev); } return 0; @@ -714,6 +723,8 @@ static struct ethtool_ops ixgb_ethtool_o .set_tx_csum = ixgb_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, + .get_msglevel = ixgb_get_msglevel, + .set_msglevel = ixgb_set_msglevel, #ifdef NETIF_F_TSO .get_tso = ethtool_op_get_tso, .set_tso = ixgb_set_tso, diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c index 620cad4..f7fa10e 100644 --- a/drivers/net/ixgb/ixgb_hw.c +++ b/drivers/net/ixgb/ixgb_hw.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h index 382c630..cb45689 100644 --- a/drivers/net/ixgb/ixgb_hw.h +++ b/drivers/net/ixgb/ixgb_hw.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -57,6 +57,7 @@ typedef enum { typedef enum { ixgb_media_type_unknown = 0, ixgb_media_type_fiber = 1, + ixgb_media_type_copper = 2, ixgb_num_media_types } ixgb_media_type; diff --git a/drivers/net/ixgb/ixgb_ids.h b/drivers/net/ixgb/ixgb_ids.h index aee207e..40a085f 100644 --- a/drivers/net/ixgb/ixgb_ids.h +++ b/drivers/net/ixgb/ixgb_ids.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -43,6 +43,8 @@ #define IXGB_DEVICE_ID_82597EX_LR 0x1B #define IXGB_SUBDEVICE_ID_A11F 0xA11F #define IXGB_SUBDEVICE_ID_A01F 0xA01F -#endif /* #ifndef _IXGB_IDS_H_ */ +#define IXGB_DEVICE_ID_82597EX_CX4 0x109E +#define IXGB_SUBDEVICE_ID_A00C 0xA00C +#endif /* #ifndef _IXGB_IDS_H_ */ /* End of File */ diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index cfd67d8..8bb32f9 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -28,22 +28,6 @@ #include "ixgb.h" -/* Change Log - * 1.0.96 04/19/05 - * - Make needlessly global code static -- bunk@stusta.de - * - ethtool cleanup -- shemminger@osdl.org - * - Support for MODULE_VERSION -- linville@tuxdriver.com - * - add skb_header_cloned check to the tso path -- herbert@apana.org.au - * 1.0.88 01/05/05 - * - include fix to the condition that determines when to quit NAPI - Robert Olsson - * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down - * 1.0.84 10/26/04 - * - reset buffer_info->dma in Tx resource cleanup logic - * 1.0.83 10/12/04 - * - sparse cleanup - shemminger@osdl.org - * - fix tx resource cleanup logic - */ - char ixgb_driver_name[] = "ixgb"; static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver"; @@ -52,9 +36,9 @@ #define DRIVERNAPI #else #define DRIVERNAPI "-NAPI" #endif -#define DRV_VERSION "1.0.100-k2"DRIVERNAPI +#define DRV_VERSION "1.0.109-k2"DRIVERNAPI char ixgb_driver_version[] = DRV_VERSION; -static char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; +static char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; /* ixgb_pci_tbl - PCI Device ID Table * @@ -67,6 +51,8 @@ static char ixgb_copyright[] = "Copyrigh static struct pci_device_id ixgb_pci_tbl[] = { {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_CX4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_LR, @@ -148,6 +134,11 @@ MODULE_DESCRIPTION("Intel(R) PRO/10GbE N MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +#define DEFAULT_DEBUG_LEVEL_SHIFT 3 +static int debug = DEFAULT_DEBUG_LEVEL_SHIFT; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + /* some defines for controlling descriptor fetches in h/w */ #define RXDCTL_WTHRESH_DEFAULT 16 /* chip writes back at this many or RXT0 */ #define RXDCTL_PTHRESH_DEFAULT 0 /* chip considers prefech below @@ -196,7 +187,7 @@ module_exit(ixgb_exit_module); * @adapter: board private structure **/ -static inline void +static void ixgb_irq_disable(struct ixgb_adapter *adapter) { atomic_inc(&adapter->irq_sem); @@ -210,7 +201,7 @@ ixgb_irq_disable(struct ixgb_adapter *ad * @adapter: board private structure **/ -static inline void +static void ixgb_irq_enable(struct ixgb_adapter *adapter) { if(atomic_dec_and_test(&adapter->irq_sem)) { @@ -231,6 +222,7 @@ ixgb_up(struct ixgb_adapter *adapter) /* hardware has been reset, we need to reload some things */ + ixgb_rar_set(hw, netdev->dev_addr, 0); ixgb_set_multi(netdev); ixgb_restore_vlan(adapter); @@ -240,6 +232,9 @@ ixgb_up(struct ixgb_adapter *adapter) ixgb_configure_rx(adapter); ixgb_alloc_rx_buffers(adapter); + /* disable interrupts and get the hardware into a known state */ + IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff); + #ifdef CONFIG_PCI_MSI { boolean_t pcix = (IXGB_READ_REG(&adapter->hw, STATUS) & @@ -249,7 +244,7 @@ #ifdef CONFIG_PCI_MSI if (!pcix) adapter->have_msi = FALSE; else if((err = pci_enable_msi(adapter->pdev))) { - printk (KERN_ERR + DPRINTK(PROBE, ERR, "Unable to allocate MSI interrupt Error: %d\n", err); adapter->have_msi = FALSE; /* proceed to try to request regular interrupt */ @@ -259,11 +254,11 @@ #ifdef CONFIG_PCI_MSI #endif if((err = request_irq(adapter->pdev->irq, &ixgb_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, - netdev->name, netdev))) + netdev->name, netdev))) { + DPRINTK(PROBE, ERR, + "Unable to allocate interrupt Error: %d\n", err); return err; - - /* disable interrupts and get the hardware into a known state */ - IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff); + } if((hw->max_frame_size != max_frame) || (hw->max_frame_size != @@ -285,11 +280,12 @@ #endif } mod_timer(&adapter->watchdog_timer, jiffies); - ixgb_irq_enable(adapter); #ifdef CONFIG_IXGB_NAPI netif_poll_enable(netdev); #endif + ixgb_irq_enable(adapter); + return 0; } @@ -326,7 +322,7 @@ ixgb_reset(struct ixgb_adapter *adapter) ixgb_adapter_stop(&adapter->hw); if(!ixgb_init_hw(&adapter->hw)) - IXGB_DBG("ixgb_init_hw failed.\n"); + DPRINTK(PROBE, ERR, "ixgb_init_hw failed.\n"); } /** @@ -363,7 +359,8 @@ ixgb_probe(struct pci_dev *pdev, } else { if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) || (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) { - IXGB_ERR("No usable DMA configuration, aborting\n"); + printk(KERN_ERR + "ixgb: No usable DMA configuration, aborting\n"); goto err_dma_mask; } pci_using_dac = 0; @@ -388,6 +385,7 @@ ixgb_probe(struct pci_dev *pdev, adapter->netdev = netdev; adapter->pdev = pdev; adapter->hw.back = adapter; + adapter->msg_enable = netif_msg_init(debug, DEFAULT_DEBUG_LEVEL_SHIFT); mmio_start = pci_resource_start(pdev, BAR_0); mmio_len = pci_resource_len(pdev, BAR_0); @@ -416,7 +414,7 @@ ixgb_probe(struct pci_dev *pdev, netdev->change_mtu = &ixgb_change_mtu; ixgb_set_ethtool_ops(netdev); netdev->tx_timeout = &ixgb_tx_timeout; - netdev->watchdog_timeo = HZ; + netdev->watchdog_timeo = 5 * HZ; #ifdef CONFIG_IXGB_NAPI netdev->poll = &ixgb_clean; netdev->weight = 64; @@ -428,6 +426,7 @@ #ifdef CONFIG_NET_POLL_CONTROLLER netdev->poll_controller = ixgb_netpoll; #endif + strcpy(netdev->name, pci_name(pdev)); netdev->mem_start = mmio_start; netdev->mem_end = mmio_start + mmio_len; netdev->base_addr = adapter->hw.io_base; @@ -449,6 +448,9 @@ #endif #ifdef NETIF_F_TSO netdev->features |= NETIF_F_TSO; #endif +#ifdef NETIF_F_LLTX + netdev->features |= NETIF_F_LLTX; +#endif if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; @@ -456,7 +458,7 @@ #endif /* make sure the EEPROM is good */ if(!ixgb_validate_eeprom_checksum(&adapter->hw)) { - printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n"); + DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); err = -EIO; goto err_eeprom; } @@ -465,6 +467,7 @@ #endif memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len); if(!is_valid_ether_addr(netdev->perm_addr)) { + DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); err = -EIO; goto err_eeprom; } @@ -478,6 +481,7 @@ #endif INIT_WORK(&adapter->tx_timeout_task, (void (*)(void *))ixgb_tx_timeout_task, netdev); + strcpy(netdev->name, "eth%d"); if((err = register_netdev(netdev))) goto err_register; @@ -486,8 +490,7 @@ #endif netif_carrier_off(netdev); netif_stop_queue(netdev); - printk(KERN_INFO "%s: Intel(R) PRO/10GbE Network Connection\n", - netdev->name); + DPRINTK(PROBE, INFO, "Intel(R) PRO/10GbE Network Connection\n"); ixgb_check_options(adapter); /* reset the hardware with the new settings */ @@ -557,17 +560,17 @@ ixgb_sw_init(struct ixgb_adapter *adapte hw->subsystem_vendor_id = pdev->subsystem_vendor; hw->subsystem_id = pdev->subsystem_device; - adapter->rx_buffer_len = IXGB_RXBUFFER_2048; - hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH; + adapter->rx_buffer_len = hw->max_frame_size; if((hw->device_id == IXGB_DEVICE_ID_82597EX) - ||(hw->device_id == IXGB_DEVICE_ID_82597EX_LR) - ||(hw->device_id == IXGB_DEVICE_ID_82597EX_SR)) + || (hw->device_id == IXGB_DEVICE_ID_82597EX_CX4) + || (hw->device_id == IXGB_DEVICE_ID_82597EX_LR) + || (hw->device_id == IXGB_DEVICE_ID_82597EX_SR)) hw->mac_type = ixgb_82597; else { /* should never have loaded on this device */ - printk(KERN_ERR "ixgb: unsupported device id\n"); + DPRINTK(PROBE, ERR, "unsupported device id\n"); } /* enable flow control to be programmed */ @@ -665,6 +668,8 @@ ixgb_setup_tx_resources(struct ixgb_adap size = sizeof(struct ixgb_buffer) * txdr->count; txdr->buffer_info = vmalloc(size); if(!txdr->buffer_info) { + DPRINTK(PROBE, ERR, + "Unable to allocate transmit descriptor ring memory\n"); return -ENOMEM; } memset(txdr->buffer_info, 0, size); @@ -677,6 +682,8 @@ ixgb_setup_tx_resources(struct ixgb_adap txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); if(!txdr->desc) { vfree(txdr->buffer_info); + DPRINTK(PROBE, ERR, + "Unable to allocate transmit descriptor memory\n"); return -ENOMEM; } memset(txdr->desc, 0, txdr->size); @@ -750,6 +757,8 @@ ixgb_setup_rx_resources(struct ixgb_adap size = sizeof(struct ixgb_buffer) * rxdr->count; rxdr->buffer_info = vmalloc(size); if(!rxdr->buffer_info) { + DPRINTK(PROBE, ERR, + "Unable to allocate receive descriptor ring\n"); return -ENOMEM; } memset(rxdr->buffer_info, 0, size); @@ -763,6 +772,8 @@ ixgb_setup_rx_resources(struct ixgb_adap if(!rxdr->desc) { vfree(rxdr->buffer_info); + DPRINTK(PROBE, ERR, + "Unable to allocate receive descriptors\n"); return -ENOMEM; } memset(rxdr->desc, 0, rxdr->size); @@ -794,21 +805,14 @@ ixgb_setup_rctl(struct ixgb_adapter *ada rctl |= IXGB_RCTL_SECRC; - switch (adapter->rx_buffer_len) { - case IXGB_RXBUFFER_2048: - default: + if (adapter->rx_buffer_len <= IXGB_RXBUFFER_2048) rctl |= IXGB_RCTL_BSIZE_2048; - break; - case IXGB_RXBUFFER_4096: + else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_4096) rctl |= IXGB_RCTL_BSIZE_4096; - break; - case IXGB_RXBUFFER_8192: + else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_8192) rctl |= IXGB_RCTL_BSIZE_8192; - break; - case IXGB_RXBUFFER_16384: + else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_16384) rctl |= IXGB_RCTL_BSIZE_16384; - break; - } IXGB_WRITE_REG(&adapter->hw, RCTL, rctl); } @@ -898,22 +902,25 @@ ixgb_free_tx_resources(struct ixgb_adapt adapter->tx_ring.desc = NULL; } -static inline void +static void ixgb_unmap_and_free_tx_resource(struct ixgb_adapter *adapter, struct ixgb_buffer *buffer_info) { struct pci_dev *pdev = adapter->pdev; - if(buffer_info->dma) { - pci_unmap_page(pdev, - buffer_info->dma, - buffer_info->length, - PCI_DMA_TODEVICE); - buffer_info->dma = 0; - } - if(buffer_info->skb) { + + if (buffer_info->dma) + pci_unmap_page(pdev, buffer_info->dma, buffer_info->length, + PCI_DMA_TODEVICE); + + if (buffer_info->skb) dev_kfree_skb_any(buffer_info->skb); - buffer_info->skb = NULL; - } + + buffer_info->skb = NULL; + buffer_info->dma = 0; + buffer_info->time_stamp = 0; + /* these fields must always be initialized in tx + * buffer_info->length = 0; + * buffer_info->next_to_watch = 0; */ } /** @@ -1112,8 +1119,8 @@ ixgb_watchdog(unsigned long data) if(adapter->hw.link_up) { if(!netif_carrier_ok(netdev)) { - printk(KERN_INFO "ixgb: %s NIC Link is Up %d Mbps %s\n", - netdev->name, 10000, "Full Duplex"); + DPRINTK(LINK, INFO, + "NIC Link is Up 10000 Mbps Full Duplex\n"); adapter->link_speed = 10000; adapter->link_duplex = FULL_DUPLEX; netif_carrier_on(netdev); @@ -1123,9 +1130,7 @@ ixgb_watchdog(unsigned long data) if(netif_carrier_ok(netdev)) { adapter->link_speed = 0; adapter->link_duplex = 0; - printk(KERN_INFO - "ixgb: %s NIC Link is Down\n", - netdev->name); + DPRINTK(LINK, INFO, "NIC Link is Down\n"); netif_carrier_off(netdev); netif_stop_queue(netdev); @@ -1158,7 +1163,7 @@ #define IXGB_TX_FLAGS_CSUM 0x00000001 #define IXGB_TX_FLAGS_VLAN 0x00000002 #define IXGB_TX_FLAGS_TSO 0x00000004 -static inline int +static int ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb) { #ifdef NETIF_F_TSO @@ -1168,7 +1173,7 @@ #ifdef NETIF_F_TSO uint16_t ipcse, tucse, mss; int err; - if(likely(skb_shinfo(skb)->tso_size)) { + if(likely(skb_shinfo(skb)->gso_size)) { if (skb_header_cloned(skb)) { err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); if (err) @@ -1176,7 +1181,7 @@ #ifdef NETIF_F_TSO } hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; skb->nh.iph->tot_len = 0; skb->nh.iph->check = 0; skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr, @@ -1220,7 +1225,7 @@ #endif return 0; } -static inline boolean_t +static boolean_t ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb) { struct ixgb_context_desc *context_desc; @@ -1258,7 +1263,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapte #define IXGB_MAX_TXD_PWR 14 #define IXGB_MAX_DATA_PER_TXD (1<time_stamp = jiffies; + buffer_info->next_to_watch = 0; len -= size; offset += size; @@ -1309,6 +1315,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter size, PCI_DMA_TODEVICE); buffer_info->time_stamp = jiffies; + buffer_info->next_to_watch = 0; len -= size; offset += size; @@ -1323,7 +1330,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter return count; } -static inline void +static void ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags) { struct ixgb_desc_ring *tx_ring = &adapter->tx_ring; @@ -1395,13 +1402,26 @@ ixgb_xmit_frame(struct sk_buff *skb, str return 0; } +#ifdef NETIF_F_LLTX + local_irq_save(flags); + if (!spin_trylock(&adapter->tx_lock)) { + /* Collision - tell upper layer to requeue */ + local_irq_restore(flags); + return NETDEV_TX_LOCKED; + } +#else spin_lock_irqsave(&adapter->tx_lock, flags); +#endif + if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) { netif_stop_queue(netdev); spin_unlock_irqrestore(&adapter->tx_lock, flags); - return 1; + return NETDEV_TX_BUSY; } + +#ifndef NETIF_F_LLTX spin_unlock_irqrestore(&adapter->tx_lock, flags); +#endif if(adapter->vlgrp && vlan_tx_tag_present(skb)) { tx_flags |= IXGB_TX_FLAGS_VLAN; @@ -1413,10 +1433,13 @@ ixgb_xmit_frame(struct sk_buff *skb, str tso = ixgb_tso(adapter, skb); if (tso < 0) { dev_kfree_skb_any(skb); +#ifdef NETIF_F_LLTX + spin_unlock_irqrestore(&adapter->tx_lock, flags); +#endif return NETDEV_TX_OK; } - if (tso) + if (likely(tso)) tx_flags |= IXGB_TX_FLAGS_TSO; else if(ixgb_tx_csum(adapter, skb)) tx_flags |= IXGB_TX_FLAGS_CSUM; @@ -1426,7 +1449,15 @@ ixgb_xmit_frame(struct sk_buff *skb, str netdev->trans_start = jiffies; - return 0; +#ifdef NETIF_F_LLTX + /* Make sure there is space in the ring for the next send. */ + if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) + netif_stop_queue(netdev); + + spin_unlock_irqrestore(&adapter->tx_lock, flags); + +#endif + return NETDEV_TX_OK; } /** @@ -1448,6 +1479,7 @@ ixgb_tx_timeout_task(struct net_device * { struct ixgb_adapter *adapter = netdev_priv(netdev); + adapter->tx_timeout_count++; ixgb_down(adapter, TRUE); ixgb_up(adapter); } @@ -1486,28 +1518,15 @@ ixgb_change_mtu(struct net_device *netde if((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) { - IXGB_ERR("Invalid MTU setting\n"); + DPRINTK(PROBE, ERR, "Invalid MTU setting %d\n", new_mtu); return -EINVAL; } - if((max_frame <= IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) - || (max_frame <= IXGB_RXBUFFER_2048)) { - adapter->rx_buffer_len = IXGB_RXBUFFER_2048; - - } else if(max_frame <= IXGB_RXBUFFER_4096) { - adapter->rx_buffer_len = IXGB_RXBUFFER_4096; - - } else if(max_frame <= IXGB_RXBUFFER_8192) { - adapter->rx_buffer_len = IXGB_RXBUFFER_8192; - - } else { - adapter->rx_buffer_len = IXGB_RXBUFFER_16384; - } + adapter->rx_buffer_len = max_frame; netdev->mtu = new_mtu; - if(old_max_frame != max_frame && netif_running(netdev)) { - + if ((old_max_frame != max_frame) && netif_running(netdev)) { ixgb_down(adapter, TRUE); ixgb_up(adapter); } @@ -1765,23 +1784,43 @@ ixgb_clean_tx_irq(struct ixgb_adapter *a tx_ring->next_to_clean = i; - spin_lock(&adapter->tx_lock); - if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev) && - (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) { - - netif_wake_queue(netdev); + if (unlikely(netif_queue_stopped(netdev))) { + spin_lock(&adapter->tx_lock); + if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev) && + (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) + netif_wake_queue(netdev); + spin_unlock(&adapter->tx_lock); } - spin_unlock(&adapter->tx_lock); if(adapter->detect_tx_hung) { /* detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ adapter->detect_tx_hung = FALSE; - if(tx_ring->buffer_info[i].dma && - time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) + if (tx_ring->buffer_info[eop].dma && + time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + HZ) && !(IXGB_READ_REG(&adapter->hw, STATUS) & - IXGB_STATUS_TXOFF)) + IXGB_STATUS_TXOFF)) { + /* detected Tx unit hang */ + DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" + " TDH <%x>\n" + " TDT <%x>\n" + " next_to_use <%x>\n" + " next_to_clean <%x>\n" + "buffer_info[next_to_clean]\n" + " time_stamp <%lx>\n" + " next_to_watch <%x>\n" + " jiffies <%lx>\n" + " next_to_watch.status <%x>\n", + IXGB_READ_REG(&adapter->hw, TDH), + IXGB_READ_REG(&adapter->hw, TDT), + tx_ring->next_to_use, + tx_ring->next_to_clean, + tx_ring->buffer_info[eop].time_stamp, + eop, + jiffies, + eop_desc->status); netif_stop_queue(netdev); + } } return cleaned; @@ -1794,7 +1833,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *a * @sk_buff: socket buffer with received data **/ -static inline void +static void ixgb_rx_checksum(struct ixgb_adapter *adapter, struct ixgb_rx_desc *rx_desc, struct sk_buff *skb) @@ -1858,6 +1897,7 @@ #ifdef CONFIG_IXGB_NAPI #endif status = rx_desc->status; skb = buffer_info->skb; + buffer_info->skb = NULL; prefetch(skb->data); @@ -1902,6 +1942,26 @@ #endif goto rxdesc_done; } + /* code added for copybreak, this should improve + * performance for small packets with large amounts + * of reassembly being done in the stack */ +#define IXGB_CB_LENGTH 256 + if (length < IXGB_CB_LENGTH) { + struct sk_buff *new_skb = + dev_alloc_skb(length + NET_IP_ALIGN); + if (new_skb) { + skb_reserve(new_skb, NET_IP_ALIGN); + new_skb->dev = netdev; + memcpy(new_skb->data - NET_IP_ALIGN, + skb->data - NET_IP_ALIGN, + length + NET_IP_ALIGN); + /* save the skb in buffer_info as good */ + buffer_info->skb = skb; + skb = new_skb; + } + } + /* end copybreak code */ + /* Good Receive */ skb_put(skb, length); @@ -1931,7 +1991,6 @@ #endif /* CONFIG_IXGB_NAPI */ rxdesc_done: /* clean up descriptor, might be written over by hw */ rx_desc->status = 0; - buffer_info->skb = NULL; /* use prefetched values */ rx_desc = next_rxd; @@ -1971,12 +2030,18 @@ ixgb_alloc_rx_buffers(struct ixgb_adapte /* leave three descriptors unused */ while(--cleancount > 2) { - rx_desc = IXGB_RX_DESC(*rx_ring, i); - - skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN); + /* recycle! its good for you */ + if (!(skb = buffer_info->skb)) + skb = dev_alloc_skb(adapter->rx_buffer_len + + NET_IP_ALIGN); + else { + skb_trim(skb, 0); + goto map_skb; + } - if(unlikely(!skb)) { + if (unlikely(!skb)) { /* Better luck next round */ + adapter->alloc_rx_buff_failed++; break; } @@ -1990,33 +2055,36 @@ ixgb_alloc_rx_buffers(struct ixgb_adapte buffer_info->skb = skb; buffer_info->length = adapter->rx_buffer_len; - buffer_info->dma = - pci_map_single(pdev, - skb->data, - adapter->rx_buffer_len, - PCI_DMA_FROMDEVICE); +map_skb: + buffer_info->dma = pci_map_single(pdev, + skb->data, + adapter->rx_buffer_len, + PCI_DMA_FROMDEVICE); + rx_desc = IXGB_RX_DESC(*rx_ring, i); rx_desc->buff_addr = cpu_to_le64(buffer_info->dma); /* guarantee DD bit not set now before h/w gets descriptor * this is the rest of the workaround for h/w double * writeback. */ rx_desc->status = 0; - if((i & ~(num_group_tail_writes- 1)) == i) { - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). */ - wmb(); - - IXGB_WRITE_REG(&adapter->hw, RDT, i); - } if(++i == rx_ring->count) i = 0; buffer_info = &rx_ring->buffer_info[i]; } - rx_ring->next_to_use = i; + if (likely(rx_ring->next_to_use != i)) { + rx_ring->next_to_use = i; + if (unlikely(i-- == 0)) + i = (rx_ring->count - 1); + + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, such + * as IA-64). */ + wmb(); + IXGB_WRITE_REG(&adapter->hw, RDT, i); + } } /** diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h index dba2048..ee982fe 100644 --- a/drivers/net/ixgb/ixgb_osdep.h +++ b/drivers/net/ixgb/ixgb_osdep.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 diff --git a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ixgb/ixgb_param.c index 8a83dfd..39fbed2 100644 --- a/drivers/net/ixgb/ixgb_param.c +++ b/drivers/net/ixgb/ixgb_param.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2006 Intel Corporation. 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 @@ -76,7 +76,7 @@ IXGB_PARAM(RxDescriptors, "Number of rec * - 2 - Tx only, generate PAUSE frames but ignore them on receive * - 3 - Full Flow Control Support * - * Default Value: Read flow control settings from the EEPROM + * Default Value: 2 - Tx only (silicon bug avoidance) */ IXGB_PARAM(FlowControl, "Flow Control setting"); @@ -137,7 +137,7 @@ IXGB_PARAM(RxFCLowThresh, "Receive Flow * * Valid Range: 1 - 65535 * - * Default Value: 256 (0x100) + * Default Value: 65535 (0xffff) (we'll send an xon if we recover) */ IXGB_PARAM(FCReqTimeout, "Flow Control Request Timeout"); @@ -165,8 +165,6 @@ #define MIN_RDTR 0 #define XSUMRX_DEFAULT OPTION_ENABLED -#define FLOW_CONTROL_FULL ixgb_fc_full -#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL #define DEFAULT_FCRTL 0x28000 #define DEFAULT_FCRTH 0x30000 #define MIN_FCRTL 0 @@ -174,9 +172,9 @@ #define MAX_FCRTL 0x3FFE8 #define MIN_FCRTH 8 #define MAX_FCRTH 0x3FFF0 -#define DEFAULT_FCPAUSE 0x100 /* this may be too long */ #define MIN_FCPAUSE 1 #define MAX_FCPAUSE 0xffff +#define DEFAULT_FCPAUSE 0xFFFF /* this may be too long */ struct ixgb_option { enum { enable_option, range_option, list_option } type; @@ -336,7 +334,7 @@ ixgb_check_options(struct ixgb_adapter * .type = list_option, .name = "Flow Control", .err = "reading default settings from EEPROM", - .def = ixgb_fc_full, + .def = ixgb_fc_tx_pause, .arg = { .l = { .nr = LIST_LEN(fc_list), .p = fc_list }} }; @@ -365,8 +363,8 @@ ixgb_check_options(struct ixgb_adapter * } else { adapter->hw.fc.high_water = opt.def; } - if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) ) - printk (KERN_INFO + if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) ) + printk (KERN_INFO "Ignoring RxFCHighThresh when no RxFC\n"); } { /* Receive Flow Control Low Threshold */ @@ -385,8 +383,8 @@ ixgb_check_options(struct ixgb_adapter * } else { adapter->hw.fc.low_water = opt.def; } - if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) ) - printk (KERN_INFO + if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) ) + printk (KERN_INFO "Ignoring RxFCLowThresh when no RxFC\n"); } { /* Flow Control Pause Time Request*/ @@ -406,12 +404,12 @@ ixgb_check_options(struct ixgb_adapter * } else { adapter->hw.fc.pause_time = opt.def; } - if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) ) - printk (KERN_INFO + if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) ) + printk (KERN_INFO "Ignoring FCReqTimeout when no RxFC\n"); } /* high low and spacing check for rx flow control thresholds */ - if (adapter->hw.fc.type & ixgb_fc_rx_pause) { + if (adapter->hw.fc.type & ixgb_fc_tx_pause) { /* high must be greater than low */ if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) { /* set defaults */ diff --git a/drivers/net/lance.c b/drivers/net/lance.c index bb5ad47..c1c3452 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -968,8 +968,7 @@ static int lance_start_xmit(struct sk_bu /* The old LANCE chips doesn't automatically pad buffers to min. size. */ if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) { if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) goto out; lp->tx_ring[entry].length = -ETH_ZLEN; } diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index 957888d..1ab0944 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c @@ -1083,8 +1083,7 @@ static int i596_start_xmit(struct sk_buf skb->len, skb->data)); if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index b79d6e8..43fef7d 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -74,7 +74,7 @@ static void emulate_large_send_offload(s struct iphdr *iph = skb->nh.iph; struct tcphdr *th = (struct tcphdr*)(skb->nh.raw + (iph->ihl * 4)); unsigned int doffset = (iph->ihl + th->doff) * 4; - unsigned int mtu = skb_shinfo(skb)->tso_size + doffset; + unsigned int mtu = skb_shinfo(skb)->gso_size + doffset; unsigned int offset = 0; u32 seq = ntohl(th->seq); u16 id = ntohs(iph->id); @@ -139,7 +139,7 @@ #ifndef LOOPBACK_MUST_CHECKSUM #endif #ifdef LOOPBACK_TSO - if (skb_shinfo(skb)->tso_size) { + if (skb_shinfo(skb)->gso_size) { BUG_ON(skb->protocol != htons(ETH_P_IP)); BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP); diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index 94d5ea1..bf3f343 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -877,8 +877,7 @@ static int i596_start_xmit (struct sk_bu length = skb->len; if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 411f4d8..625ff61 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1200,7 +1200,7 @@ static int mv643xx_eth_start_xmit(struct } if (has_tiny_unaligned_frags(skb)) { - if ((skb_linearize(skb, GFP_ATOMIC) != 0)) { + if (__skb_linearize(skb)) { stats->tx_dropped++; printk(KERN_DEBUG "%s: failed to linearize tiny " "unaligned fragment\n", dev->name); diff --git a/drivers/net/myri10ge/Makefile b/drivers/net/myri10ge/Makefile new file mode 100644 index 0000000..5df8916 --- /dev/null +++ b/drivers/net/myri10ge/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the Myricom Myri-10G ethernet driver +# + +obj-$(CONFIG_MYRI10GE) += myri10ge.o diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c new file mode 100644 index 0000000..dbdf189 --- /dev/null +++ b/drivers/net/myri10ge/myri10ge.c @@ -0,0 +1,2860 @@ +/************************************************************************* + * myri10ge.c: Myricom Myri-10G Ethernet driver. + * + * Copyright (C) 2005, 2006 Myricom, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Myricom, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * If the eeprom on your board is not recent enough, you will need to get a + * newer firmware image at: + * http://www.myri.com/scs/download-Myri10GE.html + * + * Contact Information: + * + * Myricom, Inc., 325N Santa Anita Avenue, Arcadia, CA 91006 + *************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_MTRR +#include +#endif + +#include "myri10ge_mcp.h" +#include "myri10ge_mcp_gen_header.h" + +#define MYRI10GE_VERSION_STR "1.0.0" + +MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); +MODULE_AUTHOR("Maintainer: help@myri.com"); +MODULE_VERSION(MYRI10GE_VERSION_STR); +MODULE_LICENSE("Dual BSD/GPL"); + +#define MYRI10GE_MAX_ETHER_MTU 9014 + +#define MYRI10GE_ETH_STOPPED 0 +#define MYRI10GE_ETH_STOPPING 1 +#define MYRI10GE_ETH_STARTING 2 +#define MYRI10GE_ETH_RUNNING 3 +#define MYRI10GE_ETH_OPEN_FAILED 4 + +#define MYRI10GE_EEPROM_STRINGS_SIZE 256 +#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2) + +#define MYRI10GE_NO_CONFIRM_DATA 0xffffffff +#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff + +struct myri10ge_rx_buffer_state { + struct sk_buff *skb; + DECLARE_PCI_UNMAP_ADDR(bus) + DECLARE_PCI_UNMAP_LEN(len) +}; + +struct myri10ge_tx_buffer_state { + struct sk_buff *skb; + int last; + DECLARE_PCI_UNMAP_ADDR(bus) + DECLARE_PCI_UNMAP_LEN(len) +}; + +struct myri10ge_cmd { + u32 data0; + u32 data1; + u32 data2; +}; + +struct myri10ge_rx_buf { + struct mcp_kreq_ether_recv __iomem *lanai; /* lanai ptr for recv ring */ + u8 __iomem *wc_fifo; /* w/c rx dma addr fifo address */ + struct mcp_kreq_ether_recv *shadow; /* host shadow of recv ring */ + struct myri10ge_rx_buffer_state *info; + int cnt; + int alloc_fail; + int mask; /* number of rx slots -1 */ +}; + +struct myri10ge_tx_buf { + struct mcp_kreq_ether_send __iomem *lanai; /* lanai ptr for sendq */ + u8 __iomem *wc_fifo; /* w/c send fifo address */ + struct mcp_kreq_ether_send *req_list; /* host shadow of sendq */ + char *req_bytes; + struct myri10ge_tx_buffer_state *info; + int mask; /* number of transmit slots -1 */ + int boundary; /* boundary transmits cannot cross */ + int req ____cacheline_aligned; /* transmit slots submitted */ + int pkt_start; /* packets started */ + int done ____cacheline_aligned; /* transmit slots completed */ + int pkt_done; /* packets completed */ +}; + +struct myri10ge_rx_done { + struct mcp_slot *entry; + dma_addr_t bus; + int cnt; + int idx; +}; + +struct myri10ge_priv { + int running; /* running? */ + int csum_flag; /* rx_csums? */ + struct myri10ge_tx_buf tx; /* transmit ring */ + struct myri10ge_rx_buf rx_small; + struct myri10ge_rx_buf rx_big; + struct myri10ge_rx_done rx_done; + int small_bytes; + struct net_device *dev; + struct net_device_stats stats; + u8 __iomem *sram; + int sram_size; + unsigned long board_span; + unsigned long iomem_base; + u32 __iomem *irq_claim; + u32 __iomem *irq_deassert; + char *mac_addr_string; + struct mcp_cmd_response *cmd; + dma_addr_t cmd_bus; + struct mcp_irq_data *fw_stats; + dma_addr_t fw_stats_bus; + struct pci_dev *pdev; + int msi_enabled; + unsigned int link_state; + unsigned int rdma_tags_available; + int intr_coal_delay; + u32 __iomem *intr_coal_delay_ptr; + int mtrr; + int wake_queue; + int stop_queue; + int down_cnt; + wait_queue_head_t down_wq; + struct work_struct watchdog_work; + struct timer_list watchdog_timer; + int watchdog_tx_done; + int watchdog_resets; + int tx_linearized; + int pause; + char *fw_name; + char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; + char fw_version[128]; + u8 mac_addr[6]; /* eeprom mac address */ + unsigned long serial_number; + int vendor_specific_offset; + u32 devctl; + u16 msi_flags; + u32 pm_state[16]; + u32 read_dma; + u32 write_dma; + u32 read_write_dma; +}; + +static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat"; +static char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat"; + +static char *myri10ge_fw_name = NULL; +module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name\n"); + +static int myri10ge_ecrc_enable = 1; +module_param(myri10ge_ecrc_enable, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E\n"); + +static int myri10ge_max_intr_slots = 1024; +module_param(myri10ge_max_intr_slots, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_max_intr_slots, "Interrupt queue slots\n"); + +static int myri10ge_small_bytes = -1; /* -1 == auto */ +module_param(myri10ge_small_bytes, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(myri10ge_small_bytes, "Threshold of small packets\n"); + +static int myri10ge_msi = 1; /* enable msi by default */ +module_param(myri10ge_msi, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n"); + +static int myri10ge_intr_coal_delay = 25; +module_param(myri10ge_intr_coal_delay, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay\n"); + +static int myri10ge_flow_control = 1; +module_param(myri10ge_flow_control, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_flow_control, "Pause parameter\n"); + +static int myri10ge_deassert_wait = 1; +module_param(myri10ge_deassert_wait, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(myri10ge_deassert_wait, + "Wait when deasserting legacy interrupts\n"); + +static int myri10ge_force_firmware = 0; +module_param(myri10ge_force_firmware, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_force_firmware, + "Force firmware to assume aligned completions\n"); + +static int myri10ge_skb_cross_4k = 0; +module_param(myri10ge_skb_cross_4k, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(myri10ge_skb_cross_4k, + "Can a small skb cross a 4KB boundary?\n"); + +static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; +module_param(myri10ge_initial_mtu, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n"); + +static int myri10ge_napi_weight = 64; +module_param(myri10ge_napi_weight, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_napi_weight, "Set NAPI weight\n"); + +static int myri10ge_watchdog_timeout = 1; +module_param(myri10ge_watchdog_timeout, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_watchdog_timeout, "Set watchdog timeout\n"); + +static int myri10ge_max_irq_loops = 1048576; +module_param(myri10ge_max_irq_loops, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_max_irq_loops, + "Set stuck legacy IRQ detection threshold\n"); + +#define MYRI10GE_FW_OFFSET 1024*1024 +#define MYRI10GE_HIGHPART_TO_U32(X) \ +(sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0) +#define MYRI10GE_LOWPART_TO_U32(X) ((u32)(X)) + +#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) + +static int +myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, + struct myri10ge_cmd *data, int atomic) +{ + struct mcp_cmd *buf; + char buf_bytes[sizeof(*buf) + 8]; + struct mcp_cmd_response *response = mgp->cmd; + char __iomem *cmd_addr = mgp->sram + MXGEFW_CMD_OFFSET; + u32 dma_low, dma_high, result, value; + int sleep_total = 0; + + /* ensure buf is aligned to 8 bytes */ + buf = (struct mcp_cmd *)ALIGN((unsigned long)buf_bytes, 8); + + buf->data0 = htonl(data->data0); + buf->data1 = htonl(data->data1); + buf->data2 = htonl(data->data2); + buf->cmd = htonl(cmd); + dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus); + dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus); + + buf->response_addr.low = htonl(dma_low); + buf->response_addr.high = htonl(dma_high); + response->result = MYRI10GE_NO_RESPONSE_RESULT; + mb(); + myri10ge_pio_copy(cmd_addr, buf, sizeof(*buf)); + + /* wait up to 15ms. Longest command is the DMA benchmark, + * which is capped at 5ms, but runs from a timeout handler + * that runs every 7.8ms. So a 15ms timeout leaves us with + * a 2.2ms margin + */ + if (atomic) { + /* if atomic is set, do not sleep, + * and try to get the completion quickly + * (1ms will be enough for those commands) */ + for (sleep_total = 0; + sleep_total < 1000 + && response->result == MYRI10GE_NO_RESPONSE_RESULT; + sleep_total += 10) + udelay(10); + } else { + /* use msleep for most command */ + for (sleep_total = 0; + sleep_total < 15 + && response->result == MYRI10GE_NO_RESPONSE_RESULT; + sleep_total++) + msleep(1); + } + + result = ntohl(response->result); + value = ntohl(response->data); + if (result != MYRI10GE_NO_RESPONSE_RESULT) { + if (result == 0) { + data->data0 = value; + return 0; + } else { + dev_err(&mgp->pdev->dev, + "command %d failed, result = %d\n", + cmd, result); + return -ENXIO; + } + } + + dev_err(&mgp->pdev->dev, "command %d timed out, result = %d\n", + cmd, result); + return -EAGAIN; +} + +/* + * The eeprom strings on the lanaiX have the format + * SN=x\0 + * MAC=x:x:x:x:x:x\0 + * PT:ddd mmm xx xx:xx:xx xx\0 + * PV:ddd mmm xx xx:xx:xx xx\0 + */ +static int myri10ge_read_mac_addr(struct myri10ge_priv *mgp) +{ + char *ptr, *limit; + int i; + + ptr = mgp->eeprom_strings; + limit = mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE; + + while (*ptr != '\0' && ptr < limit) { + if (memcmp(ptr, "MAC=", 4) == 0) { + ptr += 4; + mgp->mac_addr_string = ptr; + for (i = 0; i < 6; i++) { + if ((ptr + 2) > limit) + goto abort; + mgp->mac_addr[i] = + simple_strtoul(ptr, &ptr, 16); + ptr += 1; + } + } + if (memcmp((const void *)ptr, "SN=", 3) == 0) { + ptr += 3; + mgp->serial_number = simple_strtoul(ptr, &ptr, 10); + } + while (ptr < limit && *ptr++) ; + } + + return 0; + +abort: + dev_err(&mgp->pdev->dev, "failed to parse eeprom_strings\n"); + return -ENXIO; +} + +/* + * Enable or disable periodic RDMAs from the host to make certain + * chipsets resend dropped PCIe messages + */ + +static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable) +{ + char __iomem *submit; + u32 buf[16]; + u32 dma_low, dma_high; + int i; + + /* clear confirmation addr */ + mgp->cmd->data = 0; + mb(); + + /* send a rdma command to the PCIe engine, and wait for the + * response in the confirmation address. The firmware should + * write a -1 there to indicate it is alive and well + */ + dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus); + dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus); + + buf[0] = htonl(dma_high); /* confirm addr MSW */ + buf[1] = htonl(dma_low); /* confirm addr LSW */ + buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA); /* confirm data */ + buf[3] = htonl(dma_high); /* dummy addr MSW */ + buf[4] = htonl(dma_low); /* dummy addr LSW */ + buf[5] = htonl(enable); /* enable? */ + + submit = mgp->sram + 0xfc01c0; + + myri10ge_pio_copy(submit, &buf, sizeof(buf)); + for (i = 0; mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20; i++) + msleep(1); + if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA) + dev_err(&mgp->pdev->dev, "dummy rdma %s failed\n", + (enable ? "enable" : "disable")); +} + +static int +myri10ge_validate_firmware(struct myri10ge_priv *mgp, + struct mcp_gen_header *hdr) +{ + struct device *dev = &mgp->pdev->dev; + int major, minor; + + /* check firmware type */ + if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) { + dev_err(dev, "Bad firmware type: 0x%x\n", ntohl(hdr->mcp_type)); + return -EINVAL; + } + + /* save firmware version for ethtool */ + strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version)); + + sscanf(mgp->fw_version, "%d.%d", &major, &minor); + + if (!(major == MXGEFW_VERSION_MAJOR && minor == MXGEFW_VERSION_MINOR)) { + dev_err(dev, "Found firmware version %s\n", mgp->fw_version); + dev_err(dev, "Driver needs %d.%d\n", MXGEFW_VERSION_MAJOR, + MXGEFW_VERSION_MINOR); + return -EINVAL; + } + return 0; +} + +static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size) +{ + unsigned crc, reread_crc; + const struct firmware *fw; + struct device *dev = &mgp->pdev->dev; + struct mcp_gen_header *hdr; + size_t hdr_offset; + int status; + + if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) { + dev_err(dev, "Unable to load %s firmware image via hotplug\n", + mgp->fw_name); + status = -EINVAL; + goto abort_with_nothing; + } + + /* check size */ + + if (fw->size >= mgp->sram_size - MYRI10GE_FW_OFFSET || + fw->size < MCP_HEADER_PTR_OFFSET + 4) { + dev_err(dev, "Firmware size invalid:%d\n", (int)fw->size); + status = -EINVAL; + goto abort_with_fw; + } + + /* check id */ + hdr_offset = ntohl(*(u32 *) (fw->data + MCP_HEADER_PTR_OFFSET)); + if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->size) { + dev_err(dev, "Bad firmware file\n"); + status = -EINVAL; + goto abort_with_fw; + } + hdr = (void *)(fw->data + hdr_offset); + + status = myri10ge_validate_firmware(mgp, hdr); + if (status != 0) + goto abort_with_fw; + + crc = crc32(~0, fw->data, fw->size); + if (mgp->tx.boundary == 2048) { + /* Avoid PCI burst on chipset with unaligned completions. */ + int i; + __iomem u32 *ptr = (__iomem u32 *) (mgp->sram + + MYRI10GE_FW_OFFSET); + for (i = 0; i < fw->size / 4; i++) { + __raw_writel(((u32 *) fw->data)[i], ptr + i); + wmb(); + } + } else { + myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET, fw->data, + fw->size); + } + /* corruption checking is good for parity recovery and buggy chipset */ + memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size); + reread_crc = crc32(~0, fw->data, fw->size); + if (crc != reread_crc) { + dev_err(dev, "CRC failed(fw-len=%u), got 0x%x (expect 0x%x)\n", + (unsigned)fw->size, reread_crc, crc); + status = -EIO; + goto abort_with_fw; + } + *size = (u32) fw->size; + +abort_with_fw: + release_firmware(fw); + +abort_with_nothing: + return status; +} + +static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp) +{ + struct mcp_gen_header *hdr; + struct device *dev = &mgp->pdev->dev; + const size_t bytes = sizeof(struct mcp_gen_header); + size_t hdr_offset; + int status; + + /* find running firmware header */ + hdr_offset = ntohl(__raw_readl(mgp->sram + MCP_HEADER_PTR_OFFSET)); + + if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > mgp->sram_size) { + dev_err(dev, "Running firmware has bad header offset (%d)\n", + (int)hdr_offset); + return -EIO; + } + + /* copy header of running firmware from SRAM to host memory to + * validate firmware */ + hdr = kmalloc(bytes, GFP_KERNEL); + if (hdr == NULL) { + dev_err(dev, "could not malloc firmware hdr\n"); + return -ENOMEM; + } + memcpy_fromio(hdr, mgp->sram + hdr_offset, bytes); + status = myri10ge_validate_firmware(mgp, hdr); + kfree(hdr); + return status; +} + +static int myri10ge_load_firmware(struct myri10ge_priv *mgp) +{ + char __iomem *submit; + u32 buf[16]; + u32 dma_low, dma_high, size; + int status, i; + + size = 0; + status = myri10ge_load_hotplug_firmware(mgp, &size); + if (status) { + dev_warn(&mgp->pdev->dev, "hotplug firmware loading failed\n"); + + /* Do not attempt to adopt firmware if there + * was a bad crc */ + if (status == -EIO) + return status; + + status = myri10ge_adopt_running_firmware(mgp); + if (status != 0) { + dev_err(&mgp->pdev->dev, + "failed to adopt running firmware\n"); + return status; + } + dev_info(&mgp->pdev->dev, + "Successfully adopted running firmware\n"); + if (mgp->tx.boundary == 4096) { + dev_warn(&mgp->pdev->dev, + "Using firmware currently running on NIC" + ". For optimal\n"); + dev_warn(&mgp->pdev->dev, + "performance consider loading optimized " + "firmware\n"); + dev_warn(&mgp->pdev->dev, "via hotplug\n"); + } + + mgp->fw_name = "adopted"; + mgp->tx.boundary = 2048; + return status; + } + + /* clear confirmation addr */ + mgp->cmd->data = 0; + mb(); + + /* send a reload command to the bootstrap MCP, and wait for the + * response in the confirmation address. The firmware should + * write a -1 there to indicate it is alive and well + */ + dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus); + dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus); + + buf[0] = htonl(dma_high); /* confirm addr MSW */ + buf[1] = htonl(dma_low); /* confirm addr LSW */ + buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA); /* confirm data */ + + /* FIX: All newest firmware should un-protect the bottom of + * the sram before handoff. However, the very first interfaces + * do not. Therefore the handoff copy must skip the first 8 bytes + */ + buf[3] = htonl(MYRI10GE_FW_OFFSET + 8); /* where the code starts */ + buf[4] = htonl(size - 8); /* length of code */ + buf[5] = htonl(8); /* where to copy to */ + buf[6] = htonl(0); /* where to jump to */ + + submit = mgp->sram + 0xfc0000; + + myri10ge_pio_copy(submit, &buf, sizeof(buf)); + mb(); + msleep(1); + mb(); + i = 0; + while (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20) { + msleep(1); + i++; + } + if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA) { + dev_err(&mgp->pdev->dev, "handoff failed\n"); + return -ENXIO; + } + dev_info(&mgp->pdev->dev, "handoff confirmed\n"); + myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096); + + return 0; +} + +static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, u8 * addr) +{ + struct myri10ge_cmd cmd; + int status; + + cmd.data0 = ((addr[0] << 24) | (addr[1] << 16) + | (addr[2] << 8) | addr[3]); + + cmd.data1 = ((addr[4] << 8) | (addr[5])); + + status = myri10ge_send_cmd(mgp, MXGEFW_SET_MAC_ADDRESS, &cmd, 0); + return status; +} + +static int myri10ge_change_pause(struct myri10ge_priv *mgp, int pause) +{ + struct myri10ge_cmd cmd; + int status, ctl; + + ctl = pause ? MXGEFW_ENABLE_FLOW_CONTROL : MXGEFW_DISABLE_FLOW_CONTROL; + status = myri10ge_send_cmd(mgp, ctl, &cmd, 0); + + if (status) { + printk(KERN_ERR + "myri10ge: %s: Failed to set flow control mode\n", + mgp->dev->name); + return status; + } + mgp->pause = pause; + return 0; +} + +static void +myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc, int atomic) +{ + struct myri10ge_cmd cmd; + int status, ctl; + + ctl = promisc ? MXGEFW_ENABLE_PROMISC : MXGEFW_DISABLE_PROMISC; + status = myri10ge_send_cmd(mgp, ctl, &cmd, atomic); + if (status) + printk(KERN_ERR "myri10ge: %s: Failed to set promisc mode\n", + mgp->dev->name); +} + +static int myri10ge_reset(struct myri10ge_priv *mgp) +{ + struct myri10ge_cmd cmd; + int status; + size_t bytes; + u32 len; + + /* try to send a reset command to the card to see if it + * is alive */ + memset(&cmd, 0, sizeof(cmd)); + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd, 0); + if (status != 0) { + dev_err(&mgp->pdev->dev, "failed reset\n"); + return -ENXIO; + } + + /* Now exchange information about interrupts */ + + bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); + memset(mgp->rx_done.entry, 0, bytes); + cmd.data0 = (u32) bytes; + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd, 0); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, &cmd, 0); + + status |= + myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0); + mgp->irq_claim = (__iomem u32 *) (mgp->sram + cmd.data0); + if (!mgp->msi_enabled) { + status |= myri10ge_send_cmd + (mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd, 0); + mgp->irq_deassert = (__iomem u32 *) (mgp->sram + cmd.data0); + + } + status |= myri10ge_send_cmd + (mgp, MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd, 0); + mgp->intr_coal_delay_ptr = (__iomem u32 *) (mgp->sram + cmd.data0); + if (status != 0) { + dev_err(&mgp->pdev->dev, "failed set interrupt parameters\n"); + return status; + } + __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); + + /* Run a small DMA test. + * The magic multipliers to the length tell the firmware + * to do DMA read, write, or read+write tests. The + * results are returned in cmd.data0. The upper 16 + * bits or the return is the number of transfers completed. + * The lower 16 bits is the time in 0.5us ticks that the + * transfers took to complete. + */ + + len = mgp->tx.boundary; + + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data2 = len * 0x10000; + status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); + if (status == 0) + mgp->read_dma = ((cmd.data0 >> 16) * len * 2) / + (cmd.data0 & 0xffff); + else + dev_warn(&mgp->pdev->dev, "DMA read benchmark failed: %d\n", + status); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data2 = len * 0x1; + status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); + if (status == 0) + mgp->write_dma = ((cmd.data0 >> 16) * len * 2) / + (cmd.data0 & 0xffff); + else + dev_warn(&mgp->pdev->dev, "DMA write benchmark failed: %d\n", + status); + + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data2 = len * 0x10001; + status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); + if (status == 0) + mgp->read_write_dma = ((cmd.data0 >> 16) * len * 2 * 2) / + (cmd.data0 & 0xffff); + else + dev_warn(&mgp->pdev->dev, + "DMA read/write benchmark failed: %d\n", status); + + memset(mgp->rx_done.entry, 0, bytes); + + /* reset mcp/driver shared state back to 0 */ + mgp->tx.req = 0; + mgp->tx.done = 0; + mgp->tx.pkt_start = 0; + mgp->tx.pkt_done = 0; + mgp->rx_big.cnt = 0; + mgp->rx_small.cnt = 0; + mgp->rx_done.idx = 0; + mgp->rx_done.cnt = 0; + status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr); + myri10ge_change_promisc(mgp, 0, 0); + myri10ge_change_pause(mgp, mgp->pause); + return status; +} + +static inline void +myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst, + struct mcp_kreq_ether_recv *src) +{ + u32 low; + + low = src->addr_low; + src->addr_low = DMA_32BIT_MASK; + myri10ge_pio_copy(dst, src, 8 * sizeof(*src)); + mb(); + src->addr_low = low; + __raw_writel(low, &dst->addr_low); + mb(); +} + +/* + * Set of routines to get a new receive buffer. Any buffer which + * crosses a 4KB boundary must start on a 4KB boundary due to PCIe + * wdma restrictions. We also try to align any smaller allocation to + * at least a 16 byte boundary for efficiency. We assume the linux + * memory allocator works by powers of 2, and will not return memory + * smaller than 2KB which crosses a 4KB boundary. If it does, we fall + * back to allocating 2x as much space as required. + * + * We intend to replace large (>4KB) skb allocations by using + * pages directly and building a fraglist in the near future. + */ + +static inline struct sk_buff *myri10ge_alloc_big(int bytes) +{ + struct sk_buff *skb; + unsigned long data, roundup; + + skb = dev_alloc_skb(bytes + 4096 + MXGEFW_PAD); + if (skb == NULL) + return NULL; + + /* Correct skb->truesize so that socket buffer + * accounting is not confused the rounding we must + * do to satisfy alignment constraints. + */ + skb->truesize -= 4096; + + data = (unsigned long)(skb->data); + roundup = (-data) & (4095); + skb_reserve(skb, roundup); + return skb; +} + +/* Allocate 2x as much space as required and use whichever portion + * does not cross a 4KB boundary */ +static inline struct sk_buff *myri10ge_alloc_small_safe(unsigned int bytes) +{ + struct sk_buff *skb; + unsigned long data, boundary; + + skb = dev_alloc_skb(2 * (bytes + MXGEFW_PAD) - 1); + if (unlikely(skb == NULL)) + return NULL; + + /* Correct skb->truesize so that socket buffer + * accounting is not confused the rounding we must + * do to satisfy alignment constraints. + */ + skb->truesize -= bytes + MXGEFW_PAD; + + data = (unsigned long)(skb->data); + boundary = (data + 4095UL) & ~4095UL; + if ((boundary - data) >= (bytes + MXGEFW_PAD)) + return skb; + + skb_reserve(skb, boundary - data); + return skb; +} + +/* Allocate just enough space, and verify that the allocated + * space does not cross a 4KB boundary */ +static inline struct sk_buff *myri10ge_alloc_small(int bytes) +{ + struct sk_buff *skb; + unsigned long roundup, data, end; + + skb = dev_alloc_skb(bytes + 16 + MXGEFW_PAD); + if (unlikely(skb == NULL)) + return NULL; + + /* Round allocated buffer to 16 byte boundary */ + data = (unsigned long)(skb->data); + roundup = (-data) & 15UL; + skb_reserve(skb, roundup); + /* Verify that the data buffer does not cross a page boundary */ + data = (unsigned long)(skb->data); + end = data + bytes + MXGEFW_PAD - 1; + if (unlikely(((end >> 12) != (data >> 12)) && (data & 4095UL))) { + printk(KERN_NOTICE + "myri10ge_alloc_small: small skb crossed 4KB boundary\n"); + myri10ge_skb_cross_4k = 1; + dev_kfree_skb_any(skb); + skb = myri10ge_alloc_small_safe(bytes); + } + return skb; +} + +static inline int +myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct pci_dev *pdev, int bytes, + int idx) +{ + struct sk_buff *skb; + dma_addr_t bus; + int len, retval = 0; + + bytes += VLAN_HLEN; /* account for 802.1q vlan tag */ + + if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ ) + skb = myri10ge_alloc_big(bytes); + else if (myri10ge_skb_cross_4k) + skb = myri10ge_alloc_small_safe(bytes); + else + skb = myri10ge_alloc_small(bytes); + + if (unlikely(skb == NULL)) { + rx->alloc_fail++; + retval = -ENOBUFS; + goto done; + } + + /* set len so that it only covers the area we + * need mapped for DMA */ + len = bytes + MXGEFW_PAD; + + bus = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE); + rx->info[idx].skb = skb; + pci_unmap_addr_set(&rx->info[idx], bus, bus); + pci_unmap_len_set(&rx->info[idx], len, len); + rx->shadow[idx].addr_low = htonl(MYRI10GE_LOWPART_TO_U32(bus)); + rx->shadow[idx].addr_high = htonl(MYRI10GE_HIGHPART_TO_U32(bus)); + +done: + /* copy 8 descriptors (64-bytes) to the mcp at a time */ + if ((idx & 7) == 7) { + if (rx->wc_fifo == NULL) + myri10ge_submit_8rx(&rx->lanai[idx - 7], + &rx->shadow[idx - 7]); + else { + mb(); + myri10ge_pio_copy(rx->wc_fifo, + &rx->shadow[idx - 7], 64); + } + } + return retval; +} + +static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum) +{ + struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data); + + if ((skb->protocol == ntohs(ETH_P_8021Q)) && + (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) || + vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) { + skb->csum = hw_csum; + skb->ip_summed = CHECKSUM_HW; + } +} + +static inline unsigned long +myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, + int bytes, int len, int csum) +{ + dma_addr_t bus; + struct sk_buff *skb; + int idx, unmap_len; + + idx = rx->cnt & rx->mask; + rx->cnt++; + + /* save a pointer to the received skb */ + skb = rx->info[idx].skb; + bus = pci_unmap_addr(&rx->info[idx], bus); + unmap_len = pci_unmap_len(&rx->info[idx], len); + + /* try to replace the received skb */ + if (myri10ge_getbuf(rx, mgp->pdev, bytes, idx)) { + /* drop the frame -- the old skbuf is re-cycled */ + mgp->stats.rx_dropped += 1; + return 0; + } + + /* unmap the recvd skb */ + pci_unmap_single(mgp->pdev, bus, unmap_len, PCI_DMA_FROMDEVICE); + + /* mcp implicitly skips 1st bytes so that packet is properly + * aligned */ + skb_reserve(skb, MXGEFW_PAD); + + /* set the length of the frame */ + skb_put(skb, len); + + skb->protocol = eth_type_trans(skb, mgp->dev); + skb->dev = mgp->dev; + if (mgp->csum_flag) { + if ((skb->protocol == ntohs(ETH_P_IP)) || + (skb->protocol == ntohs(ETH_P_IPV6))) { + skb->csum = ntohs((u16) csum); + skb->ip_summed = CHECKSUM_HW; + } else + myri10ge_vlan_ip_csum(skb, ntohs((u16) csum)); + } + + netif_receive_skb(skb); + mgp->dev->last_rx = jiffies; + return 1; +} + +static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) +{ + struct pci_dev *pdev = mgp->pdev; + struct myri10ge_tx_buf *tx = &mgp->tx; + struct sk_buff *skb; + int idx, len; + int limit = 0; + + while (tx->pkt_done != mcp_index) { + idx = tx->done & tx->mask; + skb = tx->info[idx].skb; + + /* Mark as free */ + tx->info[idx].skb = NULL; + if (tx->info[idx].last) { + tx->pkt_done++; + tx->info[idx].last = 0; + } + tx->done++; + len = pci_unmap_len(&tx->info[idx], len); + pci_unmap_len_set(&tx->info[idx], len, 0); + if (skb) { + mgp->stats.tx_bytes += skb->len; + mgp->stats.tx_packets++; + dev_kfree_skb_irq(skb); + if (len) + pci_unmap_single(pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + } else { + if (len) + pci_unmap_page(pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + } + + /* limit potential for livelock by only handling + * 2 full tx rings per call */ + if (unlikely(++limit > 2 * tx->mask)) + break; + } + /* start the queue if we've stopped it */ + if (netif_queue_stopped(mgp->dev) + && tx->req - tx->done < (tx->mask >> 1)) { + mgp->wake_queue++; + netif_wake_queue(mgp->dev); + } +} + +static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) +{ + struct myri10ge_rx_done *rx_done = &mgp->rx_done; + unsigned long rx_bytes = 0; + unsigned long rx_packets = 0; + unsigned long rx_ok; + + int idx = rx_done->idx; + int cnt = rx_done->cnt; + u16 length; + u16 checksum; + + while (rx_done->entry[idx].length != 0 && *limit != 0) { + length = ntohs(rx_done->entry[idx].length); + rx_done->entry[idx].length = 0; + checksum = ntohs(rx_done->entry[idx].checksum); + if (length <= mgp->small_bytes) + rx_ok = myri10ge_rx_done(mgp, &mgp->rx_small, + mgp->small_bytes, + length, checksum); + else + rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big, + mgp->dev->mtu + ETH_HLEN, + length, checksum); + rx_packets += rx_ok; + rx_bytes += rx_ok * (unsigned long)length; + cnt++; + idx = cnt & (myri10ge_max_intr_slots - 1); + + /* limit potential for livelock by only handling a + * limited number of frames. */ + (*limit)--; + } + rx_done->idx = idx; + rx_done->cnt = cnt; + mgp->stats.rx_packets += rx_packets; + mgp->stats.rx_bytes += rx_bytes; +} + +static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) +{ + struct mcp_irq_data *stats = mgp->fw_stats; + + if (unlikely(stats->stats_updated)) { + if (mgp->link_state != stats->link_up) { + mgp->link_state = stats->link_up; + if (mgp->link_state) { + printk(KERN_INFO "myri10ge: %s: link up\n", + mgp->dev->name); + netif_carrier_on(mgp->dev); + } else { + printk(KERN_INFO "myri10ge: %s: link down\n", + mgp->dev->name); + netif_carrier_off(mgp->dev); + } + } + if (mgp->rdma_tags_available != + ntohl(mgp->fw_stats->rdma_tags_available)) { + mgp->rdma_tags_available = + ntohl(mgp->fw_stats->rdma_tags_available); + printk(KERN_WARNING "myri10ge: %s: RDMA timed out! " + "%d tags left\n", mgp->dev->name, + mgp->rdma_tags_available); + } + mgp->down_cnt += stats->link_down; + if (stats->link_down) + wake_up(&mgp->down_wq); + } +} + +static int myri10ge_poll(struct net_device *netdev, int *budget) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + struct myri10ge_rx_done *rx_done = &mgp->rx_done; + int limit, orig_limit, work_done; + + /* process as many rx events as NAPI will allow */ + limit = min(*budget, netdev->quota); + orig_limit = limit; + myri10ge_clean_rx_done(mgp, &limit); + work_done = orig_limit - limit; + *budget -= work_done; + netdev->quota -= work_done; + + if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) { + netif_rx_complete(netdev); + __raw_writel(htonl(3), mgp->irq_claim); + return 0; + } + return 1; +} + +static irqreturn_t myri10ge_intr(int irq, void *arg, struct pt_regs *regs) +{ + struct myri10ge_priv *mgp = arg; + struct mcp_irq_data *stats = mgp->fw_stats; + struct myri10ge_tx_buf *tx = &mgp->tx; + u32 send_done_count; + int i; + + /* make sure it is our IRQ, and that the DMA has finished */ + if (unlikely(!stats->valid)) + return (IRQ_NONE); + + /* low bit indicates receives are present, so schedule + * napi poll handler */ + if (stats->valid & 1) + netif_rx_schedule(mgp->dev); + + if (!mgp->msi_enabled) { + __raw_writel(0, mgp->irq_deassert); + if (!myri10ge_deassert_wait) + stats->valid = 0; + mb(); + } else + stats->valid = 0; + + /* Wait for IRQ line to go low, if using INTx */ + i = 0; + while (1) { + i++; + /* check for transmit completes and receives */ + send_done_count = ntohl(stats->send_done_count); + if (send_done_count != tx->pkt_done) + myri10ge_tx_done(mgp, (int)send_done_count); + if (unlikely(i > myri10ge_max_irq_loops)) { + printk(KERN_WARNING "myri10ge: %s: irq stuck?\n", + mgp->dev->name); + stats->valid = 0; + schedule_work(&mgp->watchdog_work); + } + if (likely(stats->valid == 0)) + break; + cpu_relax(); + barrier(); + } + + myri10ge_check_statblock(mgp); + + __raw_writel(htonl(3), mgp->irq_claim + 1); + return (IRQ_HANDLED); +} + +static int +myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) +{ + cmd->autoneg = AUTONEG_DISABLE; + cmd->speed = SPEED_10000; + cmd->duplex = DUPLEX_FULL; + return 0; +} + +static void +myri10ge_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + + strlcpy(info->driver, "myri10ge", sizeof(info->driver)); + strlcpy(info->version, MYRI10GE_VERSION_STR, sizeof(info->version)); + strlcpy(info->fw_version, mgp->fw_version, sizeof(info->fw_version)); + strlcpy(info->bus_info, pci_name(mgp->pdev), sizeof(info->bus_info)); +} + +static int +myri10ge_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + coal->rx_coalesce_usecs = mgp->intr_coal_delay; + return 0; +} + +static int +myri10ge_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + + mgp->intr_coal_delay = coal->rx_coalesce_usecs; + __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); + return 0; +} + +static void +myri10ge_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + + pause->autoneg = 0; + pause->rx_pause = mgp->pause; + pause->tx_pause = mgp->pause; +} + +static int +myri10ge_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + + if (pause->tx_pause != mgp->pause) + return myri10ge_change_pause(mgp, pause->tx_pause); + if (pause->rx_pause != mgp->pause) + return myri10ge_change_pause(mgp, pause->tx_pause); + if (pause->autoneg != 0) + return -EINVAL; + return 0; +} + +static void +myri10ge_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + + ring->rx_mini_max_pending = mgp->rx_small.mask + 1; + ring->rx_max_pending = mgp->rx_big.mask + 1; + ring->rx_jumbo_max_pending = 0; + ring->tx_max_pending = mgp->rx_small.mask + 1; + ring->rx_mini_pending = ring->rx_mini_max_pending; + ring->rx_pending = ring->rx_max_pending; + ring->rx_jumbo_pending = ring->rx_jumbo_max_pending; + ring->tx_pending = ring->tx_max_pending; +} + +static u32 myri10ge_get_rx_csum(struct net_device *netdev) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + if (mgp->csum_flag) + return 1; + else + return 0; +} + +static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + if (csum_enabled) + mgp->csum_flag = MXGEFW_FLAGS_CKSUM; + else + mgp->csum_flag = 0; + return 0; +} + +static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { + "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", + "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", + "rx_length_errors", "rx_over_errors", "rx_crc_errors", + "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", + "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", + "tx_heartbeat_errors", "tx_window_errors", + /* device-specific stats */ + "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs", + "serial_number", "tx_pkt_start", "tx_pkt_done", + "tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt", + "wake_queue", "stop_queue", "watchdog_resets", "tx_linearized", + "link_up", "dropped_link_overflow", "dropped_link_error_or_filtered", + "dropped_runt", "dropped_overrun", "dropped_no_small_buffer", + "dropped_no_big_buffer" +}; + +#define MYRI10GE_NET_STATS_LEN 21 +#define MYRI10GE_STATS_LEN sizeof(myri10ge_gstrings_stats) / ETH_GSTRING_LEN + +static void +myri10ge_get_strings(struct net_device *netdev, u32 stringset, u8 * data) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(data, *myri10ge_gstrings_stats, + sizeof(myri10ge_gstrings_stats)); + break; + } +} + +static int myri10ge_get_stats_count(struct net_device *netdev) +{ + return MYRI10GE_STATS_LEN; +} + +static void +myri10ge_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 * data) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + int i; + + for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++) + data[i] = ((unsigned long *)&mgp->stats)[i]; + + data[i++] = (unsigned int)mgp->read_dma; + data[i++] = (unsigned int)mgp->write_dma; + data[i++] = (unsigned int)mgp->read_write_dma; + data[i++] = (unsigned int)mgp->serial_number; + data[i++] = (unsigned int)mgp->tx.pkt_start; + data[i++] = (unsigned int)mgp->tx.pkt_done; + data[i++] = (unsigned int)mgp->tx.req; + data[i++] = (unsigned int)mgp->tx.done; + data[i++] = (unsigned int)mgp->rx_small.cnt; + data[i++] = (unsigned int)mgp->rx_big.cnt; + data[i++] = (unsigned int)mgp->wake_queue; + data[i++] = (unsigned int)mgp->stop_queue; + data[i++] = (unsigned int)mgp->watchdog_resets; + data[i++] = (unsigned int)mgp->tx_linearized; + data[i++] = (unsigned int)ntohl(mgp->fw_stats->link_up); + data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow); + data[i++] = + (unsigned int)ntohl(mgp->fw_stats->dropped_link_error_or_filtered); + data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_runt); + data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun); + data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer); + data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer); +} + +static struct ethtool_ops myri10ge_ethtool_ops = { + .get_settings = myri10ge_get_settings, + .get_drvinfo = myri10ge_get_drvinfo, + .get_coalesce = myri10ge_get_coalesce, + .set_coalesce = myri10ge_set_coalesce, + .get_pauseparam = myri10ge_get_pauseparam, + .set_pauseparam = myri10ge_set_pauseparam, + .get_ringparam = myri10ge_get_ringparam, + .get_rx_csum = myri10ge_get_rx_csum, + .set_rx_csum = myri10ge_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_hw_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +#ifdef NETIF_F_TSO + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, +#endif + .get_strings = myri10ge_get_strings, + .get_stats_count = myri10ge_get_stats_count, + .get_ethtool_stats = myri10ge_get_ethtool_stats +}; + +static int myri10ge_allocate_rings(struct net_device *dev) +{ + struct myri10ge_priv *mgp; + struct myri10ge_cmd cmd; + int tx_ring_size, rx_ring_size; + int tx_ring_entries, rx_ring_entries; + int i, status; + size_t bytes; + + mgp = netdev_priv(dev); + + /* get ring sizes */ + + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0); + tx_ring_size = cmd.data0; + status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0); + rx_ring_size = cmd.data0; + + tx_ring_entries = tx_ring_size / sizeof(struct mcp_kreq_ether_send); + rx_ring_entries = rx_ring_size / sizeof(struct mcp_dma_addr); + mgp->tx.mask = tx_ring_entries - 1; + mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries - 1; + + /* allocate the host shadow rings */ + + bytes = 8 + (MYRI10GE_MAX_SEND_DESC_TSO + 4) + * sizeof(*mgp->tx.req_list); + mgp->tx.req_bytes = kzalloc(bytes, GFP_KERNEL); + if (mgp->tx.req_bytes == NULL) + goto abort_with_nothing; + + /* ensure req_list entries are aligned to 8 bytes */ + mgp->tx.req_list = (struct mcp_kreq_ether_send *) + ALIGN((unsigned long)mgp->tx.req_bytes, 8); + + bytes = rx_ring_entries * sizeof(*mgp->rx_small.shadow); + mgp->rx_small.shadow = kzalloc(bytes, GFP_KERNEL); + if (mgp->rx_small.shadow == NULL) + goto abort_with_tx_req_bytes; + + bytes = rx_ring_entries * sizeof(*mgp->rx_big.shadow); + mgp->rx_big.shadow = kzalloc(bytes, GFP_KERNEL); + if (mgp->rx_big.shadow == NULL) + goto abort_with_rx_small_shadow; + + /* allocate the host info rings */ + + bytes = tx_ring_entries * sizeof(*mgp->tx.info); + mgp->tx.info = kzalloc(bytes, GFP_KERNEL); + if (mgp->tx.info == NULL) + goto abort_with_rx_big_shadow; + + bytes = rx_ring_entries * sizeof(*mgp->rx_small.info); + mgp->rx_small.info = kzalloc(bytes, GFP_KERNEL); + if (mgp->rx_small.info == NULL) + goto abort_with_tx_info; + + bytes = rx_ring_entries * sizeof(*mgp->rx_big.info); + mgp->rx_big.info = kzalloc(bytes, GFP_KERNEL); + if (mgp->rx_big.info == NULL) + goto abort_with_rx_small_info; + + /* Fill the receive rings */ + + for (i = 0; i <= mgp->rx_small.mask; i++) { + status = myri10ge_getbuf(&mgp->rx_small, mgp->pdev, + mgp->small_bytes, i); + if (status) { + printk(KERN_ERR + "myri10ge: %s: alloced only %d small bufs\n", + dev->name, i); + goto abort_with_rx_small_ring; + } + } + + for (i = 0; i <= mgp->rx_big.mask; i++) { + status = + myri10ge_getbuf(&mgp->rx_big, mgp->pdev, + dev->mtu + ETH_HLEN, i); + if (status) { + printk(KERN_ERR + "myri10ge: %s: alloced only %d big bufs\n", + dev->name, i); + goto abort_with_rx_big_ring; + } + } + + return 0; + +abort_with_rx_big_ring: + for (i = 0; i <= mgp->rx_big.mask; i++) { + if (mgp->rx_big.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_big.info[i].skb); + if (pci_unmap_len(&mgp->rx_big.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_big.info[i], + bus), + pci_unmap_len(&mgp->rx_big.info[i], + len), + PCI_DMA_FROMDEVICE); + } + +abort_with_rx_small_ring: + for (i = 0; i <= mgp->rx_small.mask; i++) { + if (mgp->rx_small.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_small.info[i].skb); + if (pci_unmap_len(&mgp->rx_small.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_small.info[i], + bus), + pci_unmap_len(&mgp->rx_small.info[i], + len), + PCI_DMA_FROMDEVICE); + } + kfree(mgp->rx_big.info); + +abort_with_rx_small_info: + kfree(mgp->rx_small.info); + +abort_with_tx_info: + kfree(mgp->tx.info); + +abort_with_rx_big_shadow: + kfree(mgp->rx_big.shadow); + +abort_with_rx_small_shadow: + kfree(mgp->rx_small.shadow); + +abort_with_tx_req_bytes: + kfree(mgp->tx.req_bytes); + mgp->tx.req_bytes = NULL; + mgp->tx.req_list = NULL; + +abort_with_nothing: + return status; +} + +static void myri10ge_free_rings(struct net_device *dev) +{ + struct myri10ge_priv *mgp; + struct sk_buff *skb; + struct myri10ge_tx_buf *tx; + int i, len, idx; + + mgp = netdev_priv(dev); + + for (i = 0; i <= mgp->rx_big.mask; i++) { + if (mgp->rx_big.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_big.info[i].skb); + if (pci_unmap_len(&mgp->rx_big.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_big.info[i], + bus), + pci_unmap_len(&mgp->rx_big.info[i], + len), + PCI_DMA_FROMDEVICE); + } + + for (i = 0; i <= mgp->rx_small.mask; i++) { + if (mgp->rx_small.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_small.info[i].skb); + if (pci_unmap_len(&mgp->rx_small.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_small.info[i], + bus), + pci_unmap_len(&mgp->rx_small.info[i], + len), + PCI_DMA_FROMDEVICE); + } + + tx = &mgp->tx; + while (tx->done != tx->req) { + idx = tx->done & tx->mask; + skb = tx->info[idx].skb; + + /* Mark as free */ + tx->info[idx].skb = NULL; + tx->done++; + len = pci_unmap_len(&tx->info[idx], len); + pci_unmap_len_set(&tx->info[idx], len, 0); + if (skb) { + mgp->stats.tx_dropped++; + dev_kfree_skb_any(skb); + if (len) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + } else { + if (len) + pci_unmap_page(mgp->pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + } + } + kfree(mgp->rx_big.info); + + kfree(mgp->rx_small.info); + + kfree(mgp->tx.info); + + kfree(mgp->rx_big.shadow); + + kfree(mgp->rx_small.shadow); + + kfree(mgp->tx.req_bytes); + mgp->tx.req_bytes = NULL; + mgp->tx.req_list = NULL; +} + +static int myri10ge_open(struct net_device *dev) +{ + struct myri10ge_priv *mgp; + struct myri10ge_cmd cmd; + int status, big_pow2; + + mgp = netdev_priv(dev); + + if (mgp->running != MYRI10GE_ETH_STOPPED) + return -EBUSY; + + mgp->running = MYRI10GE_ETH_STARTING; + status = myri10ge_reset(mgp); + if (status != 0) { + printk(KERN_ERR "myri10ge: %s: failed reset\n", dev->name); + mgp->running = MYRI10GE_ETH_STOPPED; + return -ENXIO; + } + + /* decide what small buffer size to use. For good TCP rx + * performance, it is important to not receive 1514 byte + * frames into jumbo buffers, as it confuses the socket buffer + * accounting code, leading to drops and erratic performance. + */ + + if (dev->mtu <= ETH_DATA_LEN) + mgp->small_bytes = 128; /* enough for a TCP header */ + else + mgp->small_bytes = ETH_FRAME_LEN; /* enough for an ETH_DATA_LEN frame */ + + /* Override the small buffer size? */ + if (myri10ge_small_bytes > 0) + mgp->small_bytes = myri10ge_small_bytes; + + /* If the user sets an obscenely small MTU, adjust the small + * bytes down to nearly nothing */ + if (mgp->small_bytes >= (dev->mtu + ETH_HLEN)) + mgp->small_bytes = 64; + + /* get the lanai pointers to the send and receive rings */ + + status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0); + mgp->tx.lanai = + (struct mcp_kreq_ether_send __iomem *)(mgp->sram + cmd.data0); + + status |= + myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd, 0); + mgp->rx_small.lanai = + (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0); + + status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd, 0); + mgp->rx_big.lanai = + (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0); + + if (status != 0) { + printk(KERN_ERR + "myri10ge: %s: failed to get ring sizes or locations\n", + dev->name); + mgp->running = MYRI10GE_ETH_STOPPED; + return -ENXIO; + } + + if (mgp->mtrr >= 0) { + mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + 0x200000; + mgp->rx_small.wc_fifo = (u8 __iomem *) mgp->sram + 0x300000; + mgp->rx_big.wc_fifo = (u8 __iomem *) mgp->sram + 0x340000; + } else { + mgp->tx.wc_fifo = NULL; + mgp->rx_small.wc_fifo = NULL; + mgp->rx_big.wc_fifo = NULL; + } + + status = myri10ge_allocate_rings(dev); + if (status != 0) + goto abort_with_nothing; + + /* Firmware needs the big buff size as a power of 2. Lie and + * tell him the buffer is larger, because we only use 1 + * buffer/pkt, and the mtu will prevent overruns. + */ + big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD; + while ((big_pow2 & (big_pow2 - 1)) != 0) + big_pow2++; + + /* now give firmware buffers sizes, and MTU */ + cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN; + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_MTU, &cmd, 0); + cmd.data0 = mgp->small_bytes; + status |= + myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, &cmd, 0); + cmd.data0 = big_pow2; + status |= + myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_BIG_BUFFER_SIZE, &cmd, 0); + if (status) { + printk(KERN_ERR "myri10ge: %s: Couldn't set buffer sizes\n", + dev->name); + goto abort_with_rings; + } + + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->fw_stats_bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->fw_stats_bus); + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA, &cmd, 0); + if (status) { + printk(KERN_ERR "myri10ge: %s: Couldn't set stats DMA\n", + dev->name); + goto abort_with_rings; + } + + mgp->link_state = -1; + mgp->rdma_tags_available = 15; + + netif_poll_enable(mgp->dev); /* must happen prior to any irq */ + + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0); + if (status) { + printk(KERN_ERR "myri10ge: %s: Couldn't bring up link\n", + dev->name); + goto abort_with_rings; + } + + mgp->wake_queue = 0; + mgp->stop_queue = 0; + mgp->running = MYRI10GE_ETH_RUNNING; + mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ; + add_timer(&mgp->watchdog_timer); + netif_wake_queue(dev); + return 0; + +abort_with_rings: + myri10ge_free_rings(dev); + +abort_with_nothing: + mgp->running = MYRI10GE_ETH_STOPPED; + return -ENOMEM; +} + +static int myri10ge_close(struct net_device *dev) +{ + struct myri10ge_priv *mgp; + struct myri10ge_cmd cmd; + int status, old_down_cnt; + + mgp = netdev_priv(dev); + + if (mgp->running != MYRI10GE_ETH_RUNNING) + return 0; + + if (mgp->tx.req_bytes == NULL) + return 0; + + del_timer_sync(&mgp->watchdog_timer); + mgp->running = MYRI10GE_ETH_STOPPING; + netif_poll_disable(mgp->dev); + netif_carrier_off(dev); + netif_stop_queue(dev); + old_down_cnt = mgp->down_cnt; + mb(); + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0); + if (status) + printk(KERN_ERR "myri10ge: %s: Couldn't bring down link\n", + dev->name); + + wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt, HZ); + if (old_down_cnt == mgp->down_cnt) + printk(KERN_ERR "myri10ge: %s never got down irq\n", dev->name); + + netif_tx_disable(dev); + + myri10ge_free_rings(dev); + + mgp->running = MYRI10GE_ETH_STOPPED; + return 0; +} + +/* copy an array of struct mcp_kreq_ether_send's to the mcp. Copy + * backwards one at a time and handle ring wraps */ + +static inline void +myri10ge_submit_req_backwards(struct myri10ge_tx_buf *tx, + struct mcp_kreq_ether_send *src, int cnt) +{ + int idx, starting_slot; + starting_slot = tx->req; + while (cnt > 1) { + cnt--; + idx = (starting_slot + cnt) & tx->mask; + myri10ge_pio_copy(&tx->lanai[idx], &src[cnt], sizeof(*src)); + mb(); + } +} + +/* + * copy an array of struct mcp_kreq_ether_send's to the mcp. Copy + * at most 32 bytes at a time, so as to avoid involving the software + * pio handler in the nic. We re-write the first segment's flags + * to mark them valid only after writing the entire chain. + */ + +static inline void +myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src, + int cnt) +{ + int idx, i; + struct mcp_kreq_ether_send __iomem *dstp, *dst; + struct mcp_kreq_ether_send *srcp; + u8 last_flags; + + idx = tx->req & tx->mask; + + last_flags = src->flags; + src->flags = 0; + mb(); + dst = dstp = &tx->lanai[idx]; + srcp = src; + + if ((idx + cnt) < tx->mask) { + for (i = 0; i < (cnt - 1); i += 2) { + myri10ge_pio_copy(dstp, srcp, 2 * sizeof(*src)); + mb(); /* force write every 32 bytes */ + srcp += 2; + dstp += 2; + } + } else { + /* submit all but the first request, and ensure + * that it is submitted below */ + myri10ge_submit_req_backwards(tx, src, cnt); + i = 0; + } + if (i < cnt) { + /* submit the first request */ + myri10ge_pio_copy(dstp, srcp, sizeof(*src)); + mb(); /* barrier before setting valid flag */ + } + + /* re-write the last 32-bits with the valid flags */ + src->flags = last_flags; + __raw_writel(*((u32 *) src + 3), (u32 __iomem *) dst + 3); + tx->req += cnt; + mb(); +} + +static inline void +myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx, + struct mcp_kreq_ether_send *src, int cnt) +{ + tx->req += cnt; + mb(); + while (cnt >= 4) { + myri10ge_pio_copy(tx->wc_fifo, src, 64); + mb(); + src += 4; + cnt -= 4; + } + if (cnt > 0) { + /* pad it to 64 bytes. The src is 64 bytes bigger than it + * needs to be so that we don't overrun it */ + myri10ge_pio_copy(tx->wc_fifo + (cnt << 18), src, 64); + mb(); + } +} + +/* + * Transmit a packet. We need to split the packet so that a single + * segment does not cross myri10ge->tx.boundary, so this makes segment + * counting tricky. So rather than try to count segments up front, we + * just give up if there are too few segments to hold a reasonably + * fragmented packet currently available. If we run + * out of segments while preparing a packet for DMA, we just linearize + * it and try again. + */ + +static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct myri10ge_priv *mgp = netdev_priv(dev); + struct mcp_kreq_ether_send *req; + struct myri10ge_tx_buf *tx = &mgp->tx; + struct skb_frag_struct *frag; + dma_addr_t bus; + u32 low, high_swapped; + unsigned int len; + int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments; + u16 pseudo_hdr_offset, cksum_offset; + int cum_len, seglen, boundary, rdma_count; + u8 flags, odd_flag; + +again: + req = tx->req_list; + avail = tx->mask - 1 - (tx->req - tx->done); + + mss = 0; + max_segments = MXGEFW_MAX_SEND_DESC; + +#ifdef NETIF_F_TSO + if (skb->len > (dev->mtu + ETH_HLEN)) { + mss = skb_shinfo(skb)->gso_size; + if (mss != 0) + max_segments = MYRI10GE_MAX_SEND_DESC_TSO; + } +#endif /*NETIF_F_TSO */ + + if ((unlikely(avail < max_segments))) { + /* we are out of transmit resources */ + mgp->stop_queue++; + netif_stop_queue(dev); + return 1; + } + + /* Setup checksum offloading, if needed */ + cksum_offset = 0; + pseudo_hdr_offset = 0; + odd_flag = 0; + flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST); + if (likely(skb->ip_summed == CHECKSUM_HW)) { + cksum_offset = (skb->h.raw - skb->data); + pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data; + /* If the headers are excessively large, then we must + * fall back to a software checksum */ + if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) { + if (skb_checksum_help(skb, 0)) + goto drop; + cksum_offset = 0; + pseudo_hdr_offset = 0; + } else { + pseudo_hdr_offset = htons(pseudo_hdr_offset); + odd_flag = MXGEFW_FLAGS_ALIGN_ODD; + flags |= MXGEFW_FLAGS_CKSUM; + } + } + + cum_len = 0; + +#ifdef NETIF_F_TSO + if (mss) { /* TSO */ + /* this removes any CKSUM flag from before */ + flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST); + + /* negative cum_len signifies to the + * send loop that we are still in the + * header portion of the TSO packet. + * TSO header must be at most 134 bytes long */ + cum_len = -((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); + + /* for TSO, pseudo_hdr_offset holds mss. + * The firmware figures out where to put + * the checksum by parsing the header. */ + pseudo_hdr_offset = htons(mss); + } else +#endif /*NETIF_F_TSO */ + /* Mark small packets, and pad out tiny packets */ + if (skb->len <= MXGEFW_SEND_SMALL_SIZE) { + flags |= MXGEFW_FLAGS_SMALL; + + /* pad frames to at least ETH_ZLEN bytes */ + if (unlikely(skb->len < ETH_ZLEN)) { + if (skb_padto(skb, ETH_ZLEN)) { + /* The packet is gone, so we must + * return 0 */ + mgp->stats.tx_dropped += 1; + return 0; + } + /* adjust the len to account for the zero pad + * so that the nic can know how long it is */ + skb->len = ETH_ZLEN; + } + } + + /* map the skb for DMA */ + len = skb->len - skb->data_len; + idx = tx->req & tx->mask; + tx->info[idx].skb = skb; + bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE); + pci_unmap_addr_set(&tx->info[idx], bus, bus); + pci_unmap_len_set(&tx->info[idx], len, len); + + frag_cnt = skb_shinfo(skb)->nr_frags; + frag_idx = 0; + count = 0; + rdma_count = 0; + + /* "rdma_count" is the number of RDMAs belonging to the + * current packet BEFORE the current send request. For + * non-TSO packets, this is equal to "count". + * For TSO packets, rdma_count needs to be reset + * to 0 after a segment cut. + * + * The rdma_count field of the send request is + * the number of RDMAs of the packet starting at + * that request. For TSO send requests with one ore more cuts + * in the middle, this is the number of RDMAs starting + * after the last cut in the request. All previous + * segments before the last cut implicitly have 1 RDMA. + * + * Since the number of RDMAs is not known beforehand, + * it must be filled-in retroactively - after each + * segmentation cut or at the end of the entire packet. + */ + + while (1) { + /* Break the SKB or Fragment up into pieces which + * do not cross mgp->tx.boundary */ + low = MYRI10GE_LOWPART_TO_U32(bus); + high_swapped = htonl(MYRI10GE_HIGHPART_TO_U32(bus)); + while (len) { + u8 flags_next; + int cum_len_next; + + if (unlikely(count == max_segments)) + goto abort_linearize; + + boundary = (low + tx->boundary) & ~(tx->boundary - 1); + seglen = boundary - low; + if (seglen > len) + seglen = len; + flags_next = flags & ~MXGEFW_FLAGS_FIRST; + cum_len_next = cum_len + seglen; +#ifdef NETIF_F_TSO + if (mss) { /* TSO */ + (req - rdma_count)->rdma_count = rdma_count + 1; + + if (likely(cum_len >= 0)) { /* payload */ + int next_is_first, chop; + + chop = (cum_len_next > mss); + cum_len_next = cum_len_next % mss; + next_is_first = (cum_len_next == 0); + flags |= chop * MXGEFW_FLAGS_TSO_CHOP; + flags_next |= next_is_first * + MXGEFW_FLAGS_FIRST; + rdma_count |= -(chop | next_is_first); + rdma_count += chop & !next_is_first; + } else if (likely(cum_len_next >= 0)) { /* header ends */ + int small; + + rdma_count = -1; + cum_len_next = 0; + seglen = -cum_len; + small = (mss <= MXGEFW_SEND_SMALL_SIZE); + flags_next = MXGEFW_FLAGS_TSO_PLD | + MXGEFW_FLAGS_FIRST | + (small * MXGEFW_FLAGS_SMALL); + } + } +#endif /* NETIF_F_TSO */ + req->addr_high = high_swapped; + req->addr_low = htonl(low); + req->pseudo_hdr_offset = pseudo_hdr_offset; + req->pad = 0; /* complete solid 16-byte block; does this matter? */ + req->rdma_count = 1; + req->length = htons(seglen); + req->cksum_offset = cksum_offset; + req->flags = flags | ((cum_len & 1) * odd_flag); + + low += seglen; + len -= seglen; + cum_len = cum_len_next; + flags = flags_next; + req++; + count++; + rdma_count++; + if (unlikely(cksum_offset > seglen)) + cksum_offset -= seglen; + else + cksum_offset = 0; + } + if (frag_idx == frag_cnt) + break; + + /* map next fragment for DMA */ + idx = (count + tx->req) & tx->mask; + frag = &skb_shinfo(skb)->frags[frag_idx]; + frag_idx++; + len = frag->size; + bus = pci_map_page(mgp->pdev, frag->page, frag->page_offset, + len, PCI_DMA_TODEVICE); + pci_unmap_addr_set(&tx->info[idx], bus, bus); + pci_unmap_len_set(&tx->info[idx], len, len); + } + + (req - rdma_count)->rdma_count = rdma_count; +#ifdef NETIF_F_TSO + if (mss) + do { + req--; + req->flags |= MXGEFW_FLAGS_TSO_LAST; + } while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP | + MXGEFW_FLAGS_FIRST))); +#endif + idx = ((count - 1) + tx->req) & tx->mask; + tx->info[idx].last = 1; + if (tx->wc_fifo == NULL) + myri10ge_submit_req(tx, tx->req_list, count); + else + myri10ge_submit_req_wc(tx, tx->req_list, count); + tx->pkt_start++; + if ((avail - count) < MXGEFW_MAX_SEND_DESC) { + mgp->stop_queue++; + netif_stop_queue(dev); + } + dev->trans_start = jiffies; + return 0; + +abort_linearize: + /* Free any DMA resources we've alloced and clear out the skb + * slot so as to not trip up assertions, and to avoid a + * double-free if linearizing fails */ + + last_idx = (idx + 1) & tx->mask; + idx = tx->req & tx->mask; + tx->info[idx].skb = NULL; + do { + len = pci_unmap_len(&tx->info[idx], len); + if (len) { + if (tx->info[idx].skb != NULL) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + else + pci_unmap_page(mgp->pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + pci_unmap_len_set(&tx->info[idx], len, 0); + tx->info[idx].skb = NULL; + } + idx = (idx + 1) & tx->mask; + } while (idx != last_idx); + if (skb_shinfo(skb)->gso_size) { + printk(KERN_ERR + "myri10ge: %s: TSO but wanted to linearize?!?!?\n", + mgp->dev->name); + goto drop; + } + + if (skb_linearize(skb)) + goto drop; + + mgp->tx_linearized++; + goto again; + +drop: + dev_kfree_skb_any(skb); + mgp->stats.tx_dropped += 1; + return 0; + +} + +static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) +{ + struct myri10ge_priv *mgp = netdev_priv(dev); + return &mgp->stats; +} + +static void myri10ge_set_multicast_list(struct net_device *dev) +{ + /* can be called from atomic contexts, + * pass 1 to force atomicity in myri10ge_send_cmd() */ + myri10ge_change_promisc(netdev_priv(dev), dev->flags & IFF_PROMISC, 1); +} + +static int myri10ge_set_mac_address(struct net_device *dev, void *addr) +{ + struct sockaddr *sa = addr; + struct myri10ge_priv *mgp = netdev_priv(dev); + int status; + + if (!is_valid_ether_addr(sa->sa_data)) + return -EADDRNOTAVAIL; + + status = myri10ge_update_mac_address(mgp, sa->sa_data); + if (status != 0) { + printk(KERN_ERR + "myri10ge: %s: changing mac address failed with %d\n", + dev->name, status); + return status; + } + + /* change the dev structure */ + memcpy(dev->dev_addr, sa->sa_data, 6); + return 0; +} + +static int myri10ge_change_mtu(struct net_device *dev, int new_mtu) +{ + struct myri10ge_priv *mgp = netdev_priv(dev); + int error = 0; + + if ((new_mtu < 68) || (ETH_HLEN + new_mtu > MYRI10GE_MAX_ETHER_MTU)) { + printk(KERN_ERR "myri10ge: %s: new mtu (%d) is not valid\n", + dev->name, new_mtu); + return -EINVAL; + } + printk(KERN_INFO "%s: changing mtu from %d to %d\n", + dev->name, dev->mtu, new_mtu); + if (mgp->running) { + /* if we change the mtu on an active device, we must + * reset the device so the firmware sees the change */ + myri10ge_close(dev); + dev->mtu = new_mtu; + myri10ge_open(dev); + } else + dev->mtu = new_mtu; + + return error; +} + +/* + * Enable ECRC to align PCI-E Completion packets on an 8-byte boundary. + * Only do it if the bridge is a root port since we don't want to disturb + * any other device, except if forced with myri10ge_ecrc_enable > 1. + */ + +#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_PCIE 0x005d + +static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) +{ + struct pci_dev *bridge = mgp->pdev->bus->self; + struct device *dev = &mgp->pdev->dev; + unsigned cap; + unsigned err_cap; + u16 val; + u8 ext_type; + int ret; + + if (!myri10ge_ecrc_enable || !bridge) + return; + + /* check that the bridge is a root port */ + cap = pci_find_capability(bridge, PCI_CAP_ID_EXP); + pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val); + ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4; + if (ext_type != PCI_EXP_TYPE_ROOT_PORT) { + if (myri10ge_ecrc_enable > 1) { + struct pci_dev *old_bridge = bridge; + + /* Walk the hierarchy up to the root port + * where ECRC has to be enabled */ + do { + bridge = bridge->bus->self; + if (!bridge) { + dev_err(dev, + "Failed to find root port" + " to force ECRC\n"); + return; + } + cap = + pci_find_capability(bridge, PCI_CAP_ID_EXP); + pci_read_config_word(bridge, + cap + PCI_CAP_FLAGS, &val); + ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4; + } while (ext_type != PCI_EXP_TYPE_ROOT_PORT); + + dev_info(dev, + "Forcing ECRC on non-root port %s" + " (enabling on root port %s)\n", + pci_name(old_bridge), pci_name(bridge)); + } else { + dev_err(dev, + "Not enabling ECRC on non-root port %s\n", + pci_name(bridge)); + return; + } + } + + cap = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ERR); + if (!cap) + return; + + ret = pci_read_config_dword(bridge, cap + PCI_ERR_CAP, &err_cap); + if (ret) { + dev_err(dev, "failed reading ext-conf-space of %s\n", + pci_name(bridge)); + dev_err(dev, "\t pci=nommconf in use? " + "or buggy/incomplete/absent ACPI MCFG attr?\n"); + return; + } + if (!(err_cap & PCI_ERR_CAP_ECRC_GENC)) + return; + + err_cap |= PCI_ERR_CAP_ECRC_GENE; + pci_write_config_dword(bridge, cap + PCI_ERR_CAP, err_cap); + dev_info(dev, "Enabled ECRC on upstream bridge %s\n", pci_name(bridge)); + mgp->tx.boundary = 4096; + mgp->fw_name = myri10ge_fw_aligned; +} + +/* + * The Lanai Z8E PCI-E interface achieves higher Read-DMA throughput + * when the PCI-E Completion packets are aligned on an 8-byte + * boundary. Some PCI-E chip sets always align Completion packets; on + * the ones that do not, the alignment can be enforced by enabling + * ECRC generation (if supported). + * + * When PCI-E Completion packets are not aligned, it is actually more + * efficient to limit Read-DMA transactions to 2KB, rather than 4KB. + * + * If the driver can neither enable ECRC nor verify that it has + * already been enabled, then it must use a firmware image which works + * around unaligned completion packets (myri10ge_ethp_z8e.dat), and it + * should also ensure that it never gives the device a Read-DMA which is + * larger than 2KB by setting the tx.boundary to 2KB. If ECRC is + * enabled, then the driver should use the aligned (myri10ge_eth_z8e.dat) + * firmware image, and set tx.boundary to 4KB. + */ + +#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE 0x0132 + +static void myri10ge_select_firmware(struct myri10ge_priv *mgp) +{ + struct pci_dev *bridge = mgp->pdev->bus->self; + + mgp->tx.boundary = 2048; + mgp->fw_name = myri10ge_fw_unaligned; + + if (myri10ge_force_firmware == 0) { + myri10ge_enable_ecrc(mgp); + + /* Check to see if the upstream bridge is known to + * provide aligned completions */ + if (bridge + /* ServerWorks HT2000/HT1000 */ + && bridge->vendor == PCI_VENDOR_ID_SERVERWORKS + && bridge->device == + PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE) { + dev_info(&mgp->pdev->dev, + "Assuming aligned completions (0x%x:0x%x)\n", + bridge->vendor, bridge->device); + mgp->tx.boundary = 4096; + mgp->fw_name = myri10ge_fw_aligned; + } + } else { + if (myri10ge_force_firmware == 1) { + dev_info(&mgp->pdev->dev, + "Assuming aligned completions (forced)\n"); + mgp->tx.boundary = 4096; + mgp->fw_name = myri10ge_fw_aligned; + } else { + dev_info(&mgp->pdev->dev, + "Assuming unaligned completions (forced)\n"); + mgp->tx.boundary = 2048; + mgp->fw_name = myri10ge_fw_unaligned; + } + } + if (myri10ge_fw_name != NULL) { + dev_info(&mgp->pdev->dev, "overriding firmware to %s\n", + myri10ge_fw_name); + mgp->fw_name = myri10ge_fw_name; + } +} + +static void myri10ge_save_state(struct myri10ge_priv *mgp) +{ + struct pci_dev *pdev = mgp->pdev; + int cap; + + pci_save_state(pdev); + /* now save PCIe and MSI state that Linux will not + * save for us */ + cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); + pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, &mgp->devctl); + cap = pci_find_capability(pdev, PCI_CAP_ID_MSI); + pci_read_config_word(pdev, cap + PCI_MSI_FLAGS, &mgp->msi_flags); +} + +static void myri10ge_restore_state(struct myri10ge_priv *mgp) +{ + struct pci_dev *pdev = mgp->pdev; + int cap; + + /* restore PCIe and MSI state that linux will not */ + cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); + pci_write_config_dword(pdev, cap + PCI_CAP_ID_EXP, mgp->devctl); + cap = pci_find_capability(pdev, PCI_CAP_ID_MSI); + pci_write_config_word(pdev, cap + PCI_MSI_FLAGS, mgp->msi_flags); + + pci_restore_state(pdev); +} + +#ifdef CONFIG_PM + +static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct myri10ge_priv *mgp; + struct net_device *netdev; + + mgp = pci_get_drvdata(pdev); + if (mgp == NULL) + return -EINVAL; + netdev = mgp->dev; + + netif_device_detach(netdev); + if (netif_running(netdev)) { + printk(KERN_INFO "myri10ge: closing %s\n", netdev->name); + rtnl_lock(); + myri10ge_close(netdev); + rtnl_unlock(); + } + myri10ge_dummy_rdma(mgp, 0); + free_irq(pdev->irq, mgp); + myri10ge_save_state(mgp); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} + +static int myri10ge_resume(struct pci_dev *pdev) +{ + struct myri10ge_priv *mgp; + struct net_device *netdev; + int status; + u16 vendor; + + mgp = pci_get_drvdata(pdev); + if (mgp == NULL) + return -EINVAL; + netdev = mgp->dev; + pci_set_power_state(pdev, 0); /* zeros conf space as a side effect */ + msleep(5); /* give card time to respond */ + pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor); + if (vendor == 0xffff) { + printk(KERN_ERR "myri10ge: %s: device disappeared!\n", + mgp->dev->name); + return -EIO; + } + myri10ge_restore_state(mgp); + pci_enable_device(pdev); + pci_set_master(pdev); + + status = request_irq(pdev->irq, myri10ge_intr, SA_SHIRQ, + netdev->name, mgp); + if (status != 0) { + dev_err(&pdev->dev, "failed to allocate IRQ\n"); + goto abort_with_msi; + } + + myri10ge_reset(mgp); + myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096); + + /* Save configuration space to be restored if the + * nic resets due to a parity error */ + myri10ge_save_state(mgp); + + if (netif_running(netdev)) { + rtnl_lock(); + myri10ge_open(netdev); + rtnl_unlock(); + } + netif_device_attach(netdev); + + return 0; + +abort_with_msi: + return -EIO; + +} + +#endif /* CONFIG_PM */ + +static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) +{ + struct pci_dev *pdev = mgp->pdev; + int vs = mgp->vendor_specific_offset; + u32 reboot; + + /*enter read32 mode */ + pci_write_config_byte(pdev, vs + 0x10, 0x3); + + /*read REBOOT_STATUS (0xfffffff0) */ + pci_write_config_dword(pdev, vs + 0x18, 0xfffffff0); + pci_read_config_dword(pdev, vs + 0x14, &reboot); + return reboot; +} + +/* + * This watchdog is used to check whether the board has suffered + * from a parity error and needs to be recovered. + */ +static void myri10ge_watchdog(void *arg) +{ + struct myri10ge_priv *mgp = arg; + u32 reboot; + int status; + u16 cmd, vendor; + + mgp->watchdog_resets++; + pci_read_config_word(mgp->pdev, PCI_COMMAND, &cmd); + if ((cmd & PCI_COMMAND_MASTER) == 0) { + /* Bus master DMA disabled? Check to see + * if the card rebooted due to a parity error + * For now, just report it */ + reboot = myri10ge_read_reboot(mgp); + printk(KERN_ERR + "myri10ge: %s: NIC rebooted (0x%x), resetting\n", + mgp->dev->name, reboot); + /* + * A rebooted nic will come back with config space as + * it was after power was applied to PCIe bus. + * Attempt to restore config space which was saved + * when the driver was loaded, or the last time the + * nic was resumed from power saving mode. + */ + myri10ge_restore_state(mgp); + } else { + /* if we get back -1's from our slot, perhaps somebody + * powered off our card. Don't try to reset it in + * this case */ + if (cmd == 0xffff) { + pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor); + if (vendor == 0xffff) { + printk(KERN_ERR + "myri10ge: %s: device disappeared!\n", + mgp->dev->name); + return; + } + } + /* Perhaps it is a software error. Try to reset */ + + printk(KERN_ERR "myri10ge: %s: device timeout, resetting\n", + mgp->dev->name); + printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n", + mgp->dev->name, mgp->tx.req, mgp->tx.done, + mgp->tx.pkt_start, mgp->tx.pkt_done, + (int)ntohl(mgp->fw_stats->send_done_count)); + msleep(2000); + printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n", + mgp->dev->name, mgp->tx.req, mgp->tx.done, + mgp->tx.pkt_start, mgp->tx.pkt_done, + (int)ntohl(mgp->fw_stats->send_done_count)); + } + rtnl_lock(); + myri10ge_close(mgp->dev); + status = myri10ge_load_firmware(mgp); + if (status != 0) + printk(KERN_ERR "myri10ge: %s: failed to load firmware\n", + mgp->dev->name); + else + myri10ge_open(mgp->dev); + rtnl_unlock(); +} + +/* + * We use our own timer routine rather than relying upon + * netdev->tx_timeout because we have a very large hardware transmit + * queue. Due to the large queue, the netdev->tx_timeout function + * cannot detect a NIC with a parity error in a timely fashion if the + * NIC is lightly loaded. + */ +static void myri10ge_watchdog_timer(unsigned long arg) +{ + struct myri10ge_priv *mgp; + + mgp = (struct myri10ge_priv *)arg; + if (mgp->tx.req != mgp->tx.done && + mgp->tx.done == mgp->watchdog_tx_done) + /* nic seems like it might be stuck.. */ + schedule_work(&mgp->watchdog_work); + else + /* rearm timer */ + mod_timer(&mgp->watchdog_timer, + jiffies + myri10ge_watchdog_timeout * HZ); + + mgp->watchdog_tx_done = mgp->tx.done; +} + +static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct net_device *netdev; + struct myri10ge_priv *mgp; + struct device *dev = &pdev->dev; + size_t bytes; + int i; + int status = -ENXIO; + int cap; + int dac_enabled; + u16 val; + + netdev = alloc_etherdev(sizeof(*mgp)); + if (netdev == NULL) { + dev_err(dev, "Could not allocate ethernet device\n"); + return -ENOMEM; + } + + mgp = netdev_priv(netdev); + memset(mgp, 0, sizeof(*mgp)); + mgp->dev = netdev; + mgp->pdev = pdev; + mgp->csum_flag = MXGEFW_FLAGS_CKSUM; + mgp->pause = myri10ge_flow_control; + mgp->intr_coal_delay = myri10ge_intr_coal_delay; + init_waitqueue_head(&mgp->down_wq); + + if (pci_enable_device(pdev)) { + dev_err(&pdev->dev, "pci_enable_device call failed\n"); + status = -ENODEV; + goto abort_with_netdev; + } + myri10ge_select_firmware(mgp); + + /* Find the vendor-specific cap so we can check + * the reboot register later on */ + mgp->vendor_specific_offset + = pci_find_capability(pdev, PCI_CAP_ID_VNDR); + + /* Set our max read request to 4KB */ + cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); + if (cap < 64) { + dev_err(&pdev->dev, "Bad PCI_CAP_ID_EXP location %d\n", cap); + goto abort_with_netdev; + } + status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val); + if (status != 0) { + dev_err(&pdev->dev, "Error %d reading PCI_EXP_DEVCTL\n", + status); + goto abort_with_netdev; + } + val = (val & ~PCI_EXP_DEVCTL_READRQ) | (5 << 12); + status = pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, val); + if (status != 0) { + dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n", + status); + goto abort_with_netdev; + } + + pci_set_master(pdev); + dac_enabled = 1; + status = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + if (status != 0) { + dac_enabled = 0; + dev_err(&pdev->dev, + "64-bit pci address mask was refused, trying 32-bit"); + status = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + } + if (status != 0) { + dev_err(&pdev->dev, "Error %d setting DMA mask\n", status); + goto abort_with_netdev; + } + mgp->cmd = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->cmd), + &mgp->cmd_bus, GFP_KERNEL); + if (mgp->cmd == NULL) + goto abort_with_netdev; + + mgp->fw_stats = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->fw_stats), + &mgp->fw_stats_bus, GFP_KERNEL); + if (mgp->fw_stats == NULL) + goto abort_with_cmd; + + mgp->board_span = pci_resource_len(pdev, 0); + mgp->iomem_base = pci_resource_start(pdev, 0); + mgp->mtrr = -1; +#ifdef CONFIG_MTRR + mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span, + MTRR_TYPE_WRCOMB, 1); +#endif + /* Hack. need to get rid of these magic numbers */ + mgp->sram_size = + 2 * 1024 * 1024 - (2 * (48 * 1024) + (32 * 1024)) - 0x100; + if (mgp->sram_size > mgp->board_span) { + dev_err(&pdev->dev, "board span %ld bytes too small\n", + mgp->board_span); + goto abort_with_wc; + } + mgp->sram = ioremap(mgp->iomem_base, mgp->board_span); + if (mgp->sram == NULL) { + dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n", + mgp->board_span, mgp->iomem_base); + status = -ENXIO; + goto abort_with_wc; + } + memcpy_fromio(mgp->eeprom_strings, + mgp->sram + mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE, + MYRI10GE_EEPROM_STRINGS_SIZE); + memset(mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE - 2, 0, 2); + status = myri10ge_read_mac_addr(mgp); + if (status) + goto abort_with_ioremap; + + for (i = 0; i < ETH_ALEN; i++) + netdev->dev_addr[i] = mgp->mac_addr[i]; + + /* allocate rx done ring */ + bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); + mgp->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes, + &mgp->rx_done.bus, GFP_KERNEL); + if (mgp->rx_done.entry == NULL) + goto abort_with_ioremap; + memset(mgp->rx_done.entry, 0, bytes); + + status = myri10ge_load_firmware(mgp); + if (status != 0) { + dev_err(&pdev->dev, "failed to load firmware\n"); + goto abort_with_rx_done; + } + + status = myri10ge_reset(mgp); + if (status != 0) { + dev_err(&pdev->dev, "failed reset\n"); + goto abort_with_firmware; + } + + if (myri10ge_msi) { + status = pci_enable_msi(pdev); + if (status != 0) + dev_err(&pdev->dev, + "Error %d setting up MSI; falling back to xPIC\n", + status); + else + mgp->msi_enabled = 1; + } + + status = request_irq(pdev->irq, myri10ge_intr, SA_SHIRQ, + netdev->name, mgp); + if (status != 0) { + dev_err(&pdev->dev, "failed to allocate IRQ\n"); + goto abort_with_firmware; + } + + pci_set_drvdata(pdev, mgp); + if ((myri10ge_initial_mtu + ETH_HLEN) > MYRI10GE_MAX_ETHER_MTU) + myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; + if ((myri10ge_initial_mtu + ETH_HLEN) < 68) + myri10ge_initial_mtu = 68; + netdev->mtu = myri10ge_initial_mtu; + netdev->open = myri10ge_open; + netdev->stop = myri10ge_close; + netdev->hard_start_xmit = myri10ge_xmit; + netdev->get_stats = myri10ge_get_stats; + netdev->base_addr = mgp->iomem_base; + netdev->irq = pdev->irq; + netdev->change_mtu = myri10ge_change_mtu; + netdev->set_multicast_list = myri10ge_set_multicast_list; + netdev->set_mac_address = myri10ge_set_mac_address; + netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; + if (dac_enabled) + netdev->features |= NETIF_F_HIGHDMA; + netdev->poll = myri10ge_poll; + netdev->weight = myri10ge_napi_weight; + + /* Save configuration space to be restored if the + * nic resets due to a parity error */ + myri10ge_save_state(mgp); + + /* Setup the watchdog timer */ + setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer, + (unsigned long)mgp); + + SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops); + INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog, mgp); + status = register_netdev(netdev); + if (status != 0) { + dev_err(&pdev->dev, "register_netdev failed: %d\n", status); + goto abort_with_irq; + } + + printk(KERN_INFO "myri10ge: %s: %s IRQ %d, tx bndry %d, fw %s, WC %s\n", + netdev->name, (mgp->msi_enabled ? "MSI" : "xPIC"), + pdev->irq, mgp->tx.boundary, mgp->fw_name, + (mgp->mtrr >= 0 ? "Enabled" : "Disabled")); + + return 0; + +abort_with_irq: + free_irq(pdev->irq, mgp); + if (mgp->msi_enabled) + pci_disable_msi(pdev); + +abort_with_firmware: + myri10ge_dummy_rdma(mgp, 0); + +abort_with_rx_done: + bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); + dma_free_coherent(&pdev->dev, bytes, + mgp->rx_done.entry, mgp->rx_done.bus); + +abort_with_ioremap: + iounmap(mgp->sram); + +abort_with_wc: +#ifdef CONFIG_MTRR + if (mgp->mtrr >= 0) + mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span); +#endif + dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats), + mgp->fw_stats, mgp->fw_stats_bus); + +abort_with_cmd: + dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), + mgp->cmd, mgp->cmd_bus); + +abort_with_netdev: + + free_netdev(netdev); + return status; +} + +/* + * myri10ge_remove + * + * Does what is necessary to shutdown one Myrinet device. Called + * once for each Myrinet card by the kernel when a module is + * unloaded. + */ +static void myri10ge_remove(struct pci_dev *pdev) +{ + struct myri10ge_priv *mgp; + struct net_device *netdev; + size_t bytes; + + mgp = pci_get_drvdata(pdev); + if (mgp == NULL) + return; + + flush_scheduled_work(); + netdev = mgp->dev; + unregister_netdev(netdev); + free_irq(pdev->irq, mgp); + if (mgp->msi_enabled) + pci_disable_msi(pdev); + + myri10ge_dummy_rdma(mgp, 0); + + bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); + dma_free_coherent(&pdev->dev, bytes, + mgp->rx_done.entry, mgp->rx_done.bus); + + iounmap(mgp->sram); + +#ifdef CONFIG_MTRR + if (mgp->mtrr >= 0) + mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span); +#endif + dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats), + mgp->fw_stats, mgp->fw_stats_bus); + + dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), + mgp->cmd, mgp->cmd_bus); + + free_netdev(netdev); + pci_set_drvdata(pdev, NULL); +} + +#define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E 0x0008 + +static struct pci_device_id myri10ge_pci_tbl[] = { + {PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)}, + {0}, +}; + +static struct pci_driver myri10ge_driver = { + .name = "myri10ge", + .probe = myri10ge_probe, + .remove = myri10ge_remove, + .id_table = myri10ge_pci_tbl, +#ifdef CONFIG_PM + .suspend = myri10ge_suspend, + .resume = myri10ge_resume, +#endif +}; + +static __init int myri10ge_init_module(void) +{ + printk(KERN_INFO "%s: Version %s\n", myri10ge_driver.name, + MYRI10GE_VERSION_STR); + return pci_register_driver(&myri10ge_driver); +} + +module_init(myri10ge_init_module); + +static __exit void myri10ge_cleanup_module(void) +{ + pci_unregister_driver(&myri10ge_driver); +} + +module_exit(myri10ge_cleanup_module); diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h new file mode 100644 index 0000000..0a6cae6 --- /dev/null +++ b/drivers/net/myri10ge/myri10ge_mcp.h @@ -0,0 +1,205 @@ +#ifndef __MYRI10GE_MCP_H__ +#define __MYRI10GE_MCP_H__ + +#define MXGEFW_VERSION_MAJOR 1 +#define MXGEFW_VERSION_MINOR 4 + +/* 8 Bytes */ +struct mcp_dma_addr { + u32 high; + u32 low; +}; + +/* 4 Bytes */ +struct mcp_slot { + u16 checksum; + u16 length; +}; + +/* 64 Bytes */ +struct mcp_cmd { + u32 cmd; + u32 data0; /* will be low portion if data > 32 bits */ + /* 8 */ + u32 data1; /* will be high portion if data > 32 bits */ + u32 data2; /* currently unused.. */ + /* 16 */ + struct mcp_dma_addr response_addr; + /* 24 */ + u8 pad[40]; +}; + +/* 8 Bytes */ +struct mcp_cmd_response { + u32 data; + u32 result; +}; + +/* + * flags used in mcp_kreq_ether_send_t: + * + * The SMALL flag is only needed in the first segment. It is raised + * for packets that are total less or equal 512 bytes. + * + * The CKSUM flag must be set in all segments. + * + * The PADDED flags is set if the packet needs to be padded, and it + * must be set for all segments. + * + * The MXGEFW_FLAGS_ALIGN_ODD must be set if the cumulative + * length of all previous segments was odd. + */ + +#define MXGEFW_FLAGS_SMALL 0x1 +#define MXGEFW_FLAGS_TSO_HDR 0x1 +#define MXGEFW_FLAGS_FIRST 0x2 +#define MXGEFW_FLAGS_ALIGN_ODD 0x4 +#define MXGEFW_FLAGS_CKSUM 0x8 +#define MXGEFW_FLAGS_TSO_LAST 0x8 +#define MXGEFW_FLAGS_NO_TSO 0x10 +#define MXGEFW_FLAGS_TSO_CHOP 0x10 +#define MXGEFW_FLAGS_TSO_PLD 0x20 + +#define MXGEFW_SEND_SMALL_SIZE 1520 +#define MXGEFW_MAX_MTU 9400 + +union mcp_pso_or_cumlen { + u16 pseudo_hdr_offset; + u16 cum_len; +}; + +#define MXGEFW_MAX_SEND_DESC 12 +#define MXGEFW_PAD 2 + +/* 16 Bytes */ +struct mcp_kreq_ether_send { + u32 addr_high; + u32 addr_low; + u16 pseudo_hdr_offset; + u16 length; + u8 pad; + u8 rdma_count; + u8 cksum_offset; /* where to start computing cksum */ + u8 flags; /* as defined above */ +}; + +/* 8 Bytes */ +struct mcp_kreq_ether_recv { + u32 addr_high; + u32 addr_low; +}; + +/* Commands */ + +#define MXGEFW_CMD_OFFSET 0xf80000 + +enum myri10ge_mcp_cmd_type { + MXGEFW_CMD_NONE = 0, + /* Reset the mcp, it is left in a safe state, waiting + * for the driver to set all its parameters */ + MXGEFW_CMD_RESET, + + /* get the version number of the current firmware.. + * (may be available in the eeprom strings..? */ + MXGEFW_GET_MCP_VERSION, + + /* Parameters which must be set by the driver before it can + * issue MXGEFW_CMD_ETHERNET_UP. They persist until the next + * MXGEFW_CMD_RESET is issued */ + + MXGEFW_CMD_SET_INTRQ_DMA, + MXGEFW_CMD_SET_BIG_BUFFER_SIZE, /* in bytes, power of 2 */ + MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, /* in bytes */ + + /* Parameters which refer to lanai SRAM addresses where the + * driver must issue PIO writes for various things */ + + MXGEFW_CMD_GET_SEND_OFFSET, + MXGEFW_CMD_GET_SMALL_RX_OFFSET, + MXGEFW_CMD_GET_BIG_RX_OFFSET, + MXGEFW_CMD_GET_IRQ_ACK_OFFSET, + MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, + + /* Parameters which refer to rings stored on the MCP, + * and whose size is controlled by the mcp */ + + MXGEFW_CMD_GET_SEND_RING_SIZE, /* in bytes */ + MXGEFW_CMD_GET_RX_RING_SIZE, /* in bytes */ + + /* Parameters which refer to rings stored in the host, + * and whose size is controlled by the host. Note that + * all must be physically contiguous and must contain + * a power of 2 number of entries. */ + + MXGEFW_CMD_SET_INTRQ_SIZE, /* in bytes */ + + /* command to bring ethernet interface up. Above parameters + * (plus mtu & mac address) must have been exchanged prior + * to issuing this command */ + MXGEFW_CMD_ETHERNET_UP, + + /* command to bring ethernet interface down. No further sends + * or receives may be processed until an MXGEFW_CMD_ETHERNET_UP + * is issued, and all interrupt queues must be flushed prior + * to ack'ing this command */ + + MXGEFW_CMD_ETHERNET_DOWN, + + /* commands the driver may issue live, without resetting + * the nic. Note that increasing the mtu "live" should + * only be done if the driver has already supplied buffers + * sufficiently large to handle the new mtu. Decreasing + * the mtu live is safe */ + + MXGEFW_CMD_SET_MTU, + MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, /* in microseconds */ + MXGEFW_CMD_SET_STATS_INTERVAL, /* in microseconds */ + MXGEFW_CMD_SET_STATS_DMA, + + MXGEFW_ENABLE_PROMISC, + MXGEFW_DISABLE_PROMISC, + MXGEFW_SET_MAC_ADDRESS, + + MXGEFW_ENABLE_FLOW_CONTROL, + MXGEFW_DISABLE_FLOW_CONTROL, + + /* do a DMA test + * data0,data1 = DMA address + * data2 = RDMA length (MSH), WDMA length (LSH) + * command return data = repetitions (MSH), 0.5-ms ticks (LSH) + */ + MXGEFW_DMA_TEST +}; + +enum myri10ge_mcp_cmd_status { + MXGEFW_CMD_OK = 0, + MXGEFW_CMD_UNKNOWN, + MXGEFW_CMD_ERROR_RANGE, + MXGEFW_CMD_ERROR_BUSY, + MXGEFW_CMD_ERROR_EMPTY, + MXGEFW_CMD_ERROR_CLOSED, + MXGEFW_CMD_ERROR_HASH_ERROR, + MXGEFW_CMD_ERROR_BAD_PORT, + MXGEFW_CMD_ERROR_RESOURCES +}; + +/* 40 Bytes */ +struct mcp_irq_data { + u32 send_done_count; + + u32 link_up; + u32 dropped_link_overflow; + u32 dropped_link_error_or_filtered; + u32 dropped_runt; + u32 dropped_overrun; + u32 dropped_no_small_buffer; + u32 dropped_no_big_buffer; + u32 rdma_tags_available; + + u8 tx_stopped; + u8 link_down; + u8 stats_updated; + u8 valid; +}; + +#endif /* __MYRI10GE_MCP_H__ */ diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h new file mode 100644 index 0000000..487f779 --- /dev/null +++ b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h @@ -0,0 +1,58 @@ +#ifndef __MYRI10GE_MCP_GEN_HEADER_H__ +#define __MYRI10GE_MCP_GEN_HEADER_H__ + +/* this file define a standard header used as a first entry point to + * exchange information between firmware/driver and driver. The + * header structure can be anywhere in the mcp. It will usually be in + * the .data section, because some fields needs to be initialized at + * compile time. + * The 32bit word at offset MX_HEADER_PTR_OFFSET in the mcp must + * contains the location of the header. + * + * Typically a MCP will start with the following: + * .text + * .space 52 ! to help catch MEMORY_INT errors + * bt start ! jump to real code + * nop + * .long _gen_mcp_header + * + * The source will have a definition like: + * + * mcp_gen_header_t gen_mcp_header = { + * .header_length = sizeof(mcp_gen_header_t), + * .mcp_type = MCP_TYPE_XXX, + * .version = "something $Id: mcp_gen_header.h,v 1.2 2006/05/13 10:04:35 bgoglin Exp $", + * .mcp_globals = (unsigned)&Globals + * }; + */ + +#define MCP_HEADER_PTR_OFFSET 0x3c + +#define MCP_TYPE_MX 0x4d582020 /* "MX " */ +#define MCP_TYPE_PCIE 0x70636965 /* "PCIE" pcie-only MCP */ +#define MCP_TYPE_ETH 0x45544820 /* "ETH " */ +#define MCP_TYPE_MCP0 0x4d435030 /* "MCP0" */ + +struct mcp_gen_header { + /* the first 4 fields are filled at compile time */ + unsigned header_length; + unsigned mcp_type; + char version[128]; + unsigned mcp_globals; /* pointer to mcp-type specific structure */ + + /* filled by the MCP at run-time */ + unsigned sram_size; + unsigned string_specs; /* either the original STRING_SPECS or a superset */ + unsigned string_specs_len; + + /* Fields above this comment are guaranteed to be present. + * + * Fields below this comment are extensions added in later versions + * of this struct, drivers should compare the header_length against + * offsetof(field) to check wether a given MCP implements them. + * + * Never remove any field. Keep everything naturally align. + */ +}; + +#endif /* __MYRI10GE_MCP_GEN_HEADER_H__ */ diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 6c86dca..d9f616f 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -1,10 +1,10 @@ -/* myri_sbus.h: MyriCOM MyriNET SBUS card driver. +/* myri_sbus.c: MyriCOM MyriNET SBUS card driver. * - * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com) + * Copyright (C) 1996, 1999, 2006 David S. Miller (davem@davemloft.net) */ static char version[] = - "myri_sbus.c:v1.9 12/Sep/99 David S. Miller (davem@redhat.com)\n"; + "myri_sbus.c:v2.0 June 23, 2006 David S. Miller (davem@davemloft.net)\n"; #include #include @@ -81,10 +81,6 @@ #else #define DHDR(x) #endif -#ifdef MODULE -static struct myri_eth *root_myri_dev; -#endif - static void myri_reset_off(void __iomem *lp, void __iomem *cregs) { /* Clear IRQ mask. */ @@ -896,8 +892,9 @@ static void dump_eeprom(struct myri_eth } #endif -static int __init myri_ether_init(struct sbus_dev *sdev, int num) +static int __init myri_ether_init(struct sbus_dev *sdev) { + static int num; static unsigned version_printed; struct net_device *dev; struct myri_eth *mp; @@ -913,6 +910,9 @@ static int __init myri_ether_init(struct if (version_printed++ == 0) printk(version); + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &sdev->ofdev.dev); + mp = (struct myri_eth *) dev->priv; spin_lock_init(&mp->irq_lock); mp->myri_sdev = sdev; @@ -1092,10 +1092,9 @@ #endif goto err_free_irq; } -#ifdef MODULE - mp->next_module = root_myri_dev; - root_myri_dev = mp; -#endif + dev_set_drvdata(&sdev->ofdev.dev, mp); + + num++; printk("%s: MyriCOM MyriNET Ethernet ", dev->name); @@ -1114,61 +1113,68 @@ err: return -ENODEV; } -static int __init myri_sbus_match(struct sbus_dev *sdev) -{ - char *name = sdev->prom_name; - if (!strcmp(name, "MYRICOM,mlanai") || - !strcmp(name, "myri")) - return 1; +static int __devinit myri_sbus_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct sbus_dev *sdev = to_sbus_device(&dev->dev); - return 0; + return myri_ether_init(sdev); } -static int __init myri_sbus_probe(void) +static int __devexit myri_sbus_remove(struct of_device *dev) { - struct sbus_bus *bus; - struct sbus_dev *sdev = NULL; - static int called; - int cards = 0, v; + struct myri_eth *mp = dev_get_drvdata(&dev->dev); + struct net_device *net_dev = mp->dev; -#ifdef MODULE - root_myri_dev = NULL; -#endif + unregister_netdevice(net_dev); - if (called) - return -ENODEV; - called++; - - for_each_sbus(bus) { - for_each_sbusdev(sdev, bus) { - if (myri_sbus_match(sdev)) { - cards++; - DET(("Found myricom myrinet as %s\n", sdev->prom_name)); - if ((v = myri_ether_init(sdev, (cards - 1)))) - return v; - } - } + free_irq(net_dev->irq, net_dev); + + if (mp->eeprom.cpuvers < CPUVERS_4_0) { + sbus_iounmap(mp->regs, mp->reg_size); + } else { + sbus_iounmap(mp->cregs, PAGE_SIZE); + sbus_iounmap(mp->lregs, (256 * 1024)); + sbus_iounmap(mp->lanai, (512 * 1024)); } - if (!cards) - return -ENODEV; + + free_netdev(net_dev); + + dev_set_drvdata(&dev->dev, NULL); + return 0; } -static void __exit myri_sbus_cleanup(void) +static struct of_device_id myri_sbus_match[] = { + { + .name = "MYRICOM,mlanai", + }, + { + .name = "myri", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, myri_sbus_match); + +static struct of_platform_driver myri_sbus_driver = { + .name = "myri", + .match_table = myri_sbus_match, + .probe = myri_sbus_probe, + .remove = __devexit_p(myri_sbus_remove), +}; + +static int __init myri_sbus_init(void) +{ + return of_register_driver(&myri_sbus_driver, &sbus_bus_type); +} + +static void __exit myri_sbus_exit(void) { -#ifdef MODULE - while (root_myri_dev) { - struct myri_eth *next = root_myri_dev->next_module; - - unregister_netdev(root_myri_dev->dev); - /* this will also free the co-allocated 'root_myri_dev' */ - free_netdev(root_myri_dev->dev); - root_myri_dev = next; - } -#endif /* MODULE */ + of_unregister_driver(&myri_sbus_driver); } -module_init(myri_sbus_probe); -module_exit(myri_sbus_cleanup); +module_init(myri_sbus_init); +module_exit(myri_sbus_exit); + MODULE_LICENSE("GPL"); diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h index 47722f7..2f69ef7 100644 --- a/drivers/net/myri_sbus.h +++ b/drivers/net/myri_sbus.h @@ -290,7 +290,6 @@ struct myri_eth { unsigned int reg_size; /* Size of register space. */ unsigned int shmem_base; /* Offset to shared ram. */ struct sbus_dev *myri_sdev; /* Our SBUS device struct. */ - struct myri_eth *next_module; /* Next in adapter chain. */ }; /* We use this to acquire receive skb's that we can DMA directly into. */ diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 9062775..2e4eced 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -318,12 +318,12 @@ performance critical codepaths: The rx process only runs in the interrupt handler. Access from outside the interrupt handler is only permitted after disable_irq(). -The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap +The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap is set, then access is permitted under spin_lock_irq(&np->lock). Thus configuration functions that want to access everything must call disable_irq(dev->irq); - spin_lock_bh(dev->xmit_lock); + netif_tx_lock_bh(dev); spin_lock_irq(&np->lock); IV. Notes diff --git a/drivers/net/ne.c b/drivers/net/ne.c index b327652..963a11f 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -829,7 +829,7 @@ that the ne2k probe is the last 8390 bas is at boot) and so the probe will get confused by any other 8390 cards. ISA device autoprobes on a running machine are not recommended anyway. */ -int init_module(void) +int __init init_module(void) { int this_dev, found = 0; diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c index 2aa7b77..eebf5f0 100644 --- a/drivers/net/ne2.c +++ b/drivers/net/ne2.c @@ -780,7 +780,7 @@ MODULE_PARM_DESC(bad, "(ignored)"); /* Module code fixed by David Weinehall */ -int init_module(void) +int __init init_module(void) { struct net_device *dev; int this_dev, found = 0; diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c new file mode 100644 index 0000000..b92430c --- /dev/null +++ b/drivers/net/netx-eth.c @@ -0,0 +1,516 @@ +/* + * drivers/net/netx-eth.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* XC Fifo Offsets */ +#define EMPTY_PTR_FIFO(xcno) (0 + ((xcno) << 3)) /* Index of the empty pointer FIFO */ +#define IND_FIFO_PORT_HI(xcno) (1 + ((xcno) << 3)) /* Index of the FIFO where received */ + /* Data packages are indicated by XC */ +#define IND_FIFO_PORT_LO(xcno) (2 + ((xcno) << 3)) /* Index of the FIFO where received */ + /* Data packages are indicated by XC */ +#define REQ_FIFO_PORT_HI(xcno) (3 + ((xcno) << 3)) /* Index of the FIFO where Data packages */ + /* have to be indicated by ARM which */ + /* shall be sent */ +#define REQ_FIFO_PORT_LO(xcno) (4 + ((xcno) << 3)) /* Index of the FIFO where Data packages */ + /* have to be indicated by ARM which shall */ + /* be sent */ +#define CON_FIFO_PORT_HI(xcno) (5 + ((xcno) << 3)) /* Index of the FIFO where sent Data packages */ + /* are confirmed */ +#define CON_FIFO_PORT_LO(xcno) (6 + ((xcno) << 3)) /* Index of the FIFO where sent Data */ + /* packages are confirmed */ +#define PFIFO_MASK(xcno) (0x7f << (xcno*8)) + +#define FIFO_PTR_FRAMELEN_SHIFT 0 +#define FIFO_PTR_FRAMELEN_MASK (0x7ff << 0) +#define FIFO_PTR_FRAMELEN(len) (((len) << 0) & FIFO_PTR_FRAMELEN_MASK) +#define FIFO_PTR_TIMETRIG (1<<11) +#define FIFO_PTR_MULTI_REQ +#define FIFO_PTR_ORIGIN (1<<14) +#define FIFO_PTR_VLAN (1<<15) +#define FIFO_PTR_FRAMENO_SHIFT 16 +#define FIFO_PTR_FRAMENO_MASK (0x3f << 16) +#define FIFO_PTR_FRAMENO(no) (((no) << 16) & FIFO_PTR_FRAMENO_MASK) +#define FIFO_PTR_SEGMENT_SHIFT 22 +#define FIFO_PTR_SEGMENT_MASK (0xf << 22) +#define FIFO_PTR_SEGMENT(seg) (((seg) & 0xf) << 22) +#define FIFO_PTR_ERROR_SHIFT 28 +#define FIFO_PTR_ERROR_MASK (0xf << 28) + +#define ISR_LINK_STATUS_CHANGE (1<<4) +#define ISR_IND_LO (1<<3) +#define ISR_CON_LO (1<<2) +#define ISR_IND_HI (1<<1) +#define ISR_CON_HI (1<<0) + +#define ETH_MAC_LOCAL_CONFIG 0x1560 +#define ETH_MAC_4321 0x1564 +#define ETH_MAC_65 0x1568 + +#define MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT 16 +#define MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK (0xf<data; + unsigned int len = skb->len; + + spin_lock_irq(&priv->lock); + memcpy_toio(priv->sram_base + 1560, (void *)buf, len); + if (len < 60) { + memset_io(priv->sram_base + 1560 + len, 0, 60 - len); + len = 60; + } + + pfifo_push(REQ_FIFO_PORT_LO(priv->id), + FIFO_PTR_SEGMENT(priv->id) | + FIFO_PTR_FRAMENO(1) | + FIFO_PTR_FRAMELEN(len)); + + ndev->trans_start = jiffies; + priv->stats.tx_packets++; + priv->stats.tx_bytes += skb->len; + + netif_stop_queue(ndev); + spin_unlock_irq(&priv->lock); + dev_kfree_skb(skb); + + return 0; +} + +static void netx_eth_receive(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + unsigned int val, frameno, seg, len; + unsigned char *data; + struct sk_buff *skb; + + val = pfifo_pop(IND_FIFO_PORT_LO(priv->id)); + + frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT; + seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT; + len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT; + + skb = dev_alloc_skb(len); + if (unlikely(skb == NULL)) { + printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", + ndev->name); + priv->stats.rx_dropped++; + return; + } + + data = skb_put(skb, len); + + memcpy_fromio(data, priv->sram_base + frameno * 1560, len); + + pfifo_push(EMPTY_PTR_FIFO(priv->id), + FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno)); + + ndev->last_rx = jiffies; + skb->dev = ndev; + skb->protocol = eth_type_trans(skb, ndev); + netif_rx(skb); + priv->stats.rx_packets++; + priv->stats.rx_bytes += len; +} + +static irqreturn_t +netx_eth_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *ndev = dev_id; + struct netx_eth_priv *priv = netdev_priv(ndev); + int status; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + status = readl(NETX_PFIFO_XPEC_ISR(priv->id)); + while (status) { + int fill_level; + writel(status, NETX_PFIFO_XPEC_ISR(priv->id)); + + if ((status & ISR_CON_HI) || (status & ISR_IND_HI)) + printk("%s: unexpected status: 0x%08x\n", + __FUNCTION__, status); + + fill_level = + readl(NETX_PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(priv->id))); + while (fill_level--) + netx_eth_receive(ndev); + + if (status & ISR_CON_LO) + netif_wake_queue(ndev); + + if (status & ISR_LINK_STATUS_CHANGE) + mii_check_media(&priv->mii, netif_msg_link(priv), 1); + + status = readl(NETX_PFIFO_XPEC_ISR(priv->id)); + } + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; +} + +static struct net_device_stats *netx_eth_query_statistics(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + return &priv->stats; +} + +static int netx_eth_open(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + + if (request_irq + (ndev->irq, &netx_eth_interrupt, SA_SHIRQ, ndev->name, ndev)) + return -EAGAIN; + + writel(ndev->dev_addr[0] | + ndev->dev_addr[1]<<8 | + ndev->dev_addr[2]<<16 | + ndev->dev_addr[3]<<24, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321); + writel(ndev->dev_addr[4] | + ndev->dev_addr[5]<<8, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_65); + + writel(LOCAL_CONFIG_LINK_STATUS_IRQ_EN | + LOCAL_CONFIG_CON_LO_IRQ_EN | + LOCAL_CONFIG_CON_HI_IRQ_EN | + LOCAL_CONFIG_IND_LO_IRQ_EN | + LOCAL_CONFIG_IND_HI_IRQ_EN, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + + ETH_MAC_LOCAL_CONFIG); + + mii_check_media(&priv->mii, netif_msg_link(priv), 1); + netif_start_queue(ndev); + + return 0; +} + +static int netx_eth_close(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + + netif_stop_queue(ndev); + + writel(0, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_LOCAL_CONFIG); + + free_irq(ndev->irq, ndev); + + return 0; +} + +static void netx_eth_timeout(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + int i; + + printk(KERN_ERR "%s: transmit timed out, resetting\n", ndev->name); + + spin_lock_irq(&priv->lock); + + xc_reset(priv->xc); + xc_start(priv->xc); + + for (i=2; i<=18; i++) + pfifo_push(EMPTY_PTR_FIFO(priv->id), + FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id)); + + spin_unlock_irq(&priv->lock); + + netif_wake_queue(ndev); +} + +static int +netx_eth_phy_read(struct net_device *ndev, int phy_id, int reg) +{ + unsigned int val; + + val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) | + MIIMU_REGADDR(reg) | MIIMU_PHY_NRES; + + writel(val, NETX_MIIMU); + while (readl(NETX_MIIMU) & MIIMU_SNRDY); + + return readl(NETX_MIIMU) >> 16; + +} + +static void +netx_eth_phy_write(struct net_device *ndev, int phy_id, int reg, int value) +{ + unsigned int val; + + val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) | + MIIMU_REGADDR(reg) | MIIMU_PHY_NRES | MIIMU_OPMODE_WRITE | + MIIMU_DATA(value); + + writel(val, NETX_MIIMU); + while (readl(NETX_MIIMU) & MIIMU_SNRDY); +} + +static int netx_eth_enable(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + unsigned int mac4321, mac65; + int running, i; + + ether_setup(ndev); + + ndev->open = netx_eth_open; + ndev->stop = netx_eth_close; + ndev->hard_start_xmit = netx_eth_hard_start_xmit; + ndev->tx_timeout = netx_eth_timeout; + ndev->watchdog_timeo = msecs_to_jiffies(5000); + ndev->get_stats = netx_eth_query_statistics; + ndev->set_multicast_list = netx_eth_set_multicast_list; + + priv->msg_enable = NETIF_MSG_LINK; + priv->mii.phy_id_mask = 0x1f; + priv->mii.reg_num_mask = 0x1f; + priv->mii.force_media = 0; + priv->mii.full_duplex = 0; + priv->mii.dev = ndev; + priv->mii.mdio_read = netx_eth_phy_read; + priv->mii.mdio_write = netx_eth_phy_write; + priv->mii.phy_id = INTERNAL_PHY_ADR + priv->id; + + running = xc_running(priv->xc); + xc_stop(priv->xc); + + /* if the xc engine is already running, assume the bootloader has + * loaded the firmware for us + */ + if (running) { + /* get Node Address from hardware */ + mac4321 = readl(priv->xpec_base + + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321); + mac65 = readl(priv->xpec_base + + NETX_XPEC_RAM_START_OFS + ETH_MAC_65); + + ndev->dev_addr[0] = mac4321 & 0xff; + ndev->dev_addr[1] = (mac4321 >> 8) & 0xff; + ndev->dev_addr[2] = (mac4321 >> 16) & 0xff; + ndev->dev_addr[3] = (mac4321 >> 24) & 0xff; + ndev->dev_addr[4] = mac65 & 0xff; + ndev->dev_addr[5] = (mac65 >> 8) & 0xff; + } else { + if (xc_request_firmware(priv->xc)) { + printk(CARDNAME ": requesting firmware failed\n"); + return -ENODEV; + } + } + + xc_reset(priv->xc); + xc_start(priv->xc); + + if (!is_valid_ether_addr(ndev->dev_addr)) + printk("%s: Invalid ethernet MAC address. Please " + "set using ifconfig\n", ndev->name); + + for (i=2; i<=18; i++) + pfifo_push(EMPTY_PTR_FIFO(priv->id), + FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id)); + + return register_netdev(ndev); + +} + +static int netx_eth_drv_probe(struct platform_device *pdev) +{ + struct netx_eth_priv *priv; + struct net_device *ndev; + struct netxeth_platform_data *pdata; + int ret; + + ndev = alloc_etherdev(sizeof (struct netx_eth_priv)); + if (!ndev) { + printk("%s: could not allocate device.\n", CARDNAME); + ret = -ENOMEM; + goto exit; + } + SET_MODULE_OWNER(ndev); + SET_NETDEV_DEV(ndev, &pdev->dev); + + platform_set_drvdata(pdev, ndev); + + priv = netdev_priv(ndev); + + pdata = (struct netxeth_platform_data *)pdev->dev.platform_data; + priv->xc = request_xc(pdata->xcno, &pdev->dev); + if (!priv->xc) { + dev_err(&pdev->dev, "unable to request xc engine\n"); + ret = -ENODEV; + goto exit_free_netdev; + } + + ndev->irq = priv->xc->irq; + priv->id = pdev->id; + priv->xpec_base = priv->xc->xpec_base; + priv->xmac_base = priv->xc->xmac_base; + priv->sram_base = priv->xc->sram_base; + + ret = pfifo_request(PFIFO_MASK(priv->id)); + if (ret) { + printk("unable to request PFIFO\n"); + goto exit_free_xc; + } + + ret = netx_eth_enable(ndev); + if (ret) + goto exit_free_pfifo; + + return 0; +exit_free_pfifo: + pfifo_free(PFIFO_MASK(priv->id)); +exit_free_xc: + free_xc(priv->xc); +exit_free_netdev: + platform_set_drvdata(pdev, NULL); + free_netdev(ndev); +exit: + return ret; +} + +static int netx_eth_drv_remove(struct platform_device *pdev) +{ + struct net_device *ndev = dev_get_drvdata(&pdev->dev); + struct netx_eth_priv *priv = netdev_priv(ndev); + + platform_set_drvdata(pdev, NULL); + + unregister_netdev(ndev); + xc_stop(priv->xc); + free_xc(priv->xc); + free_netdev(ndev); + pfifo_free(PFIFO_MASK(priv->id)); + + return 0; +} + +static int netx_eth_drv_suspend(struct platform_device *pdev, pm_message_t state) +{ + dev_err(&pdev->dev, "suspend not implemented\n"); + return 0; +} + +static int netx_eth_drv_resume(struct platform_device *pdev) +{ + dev_err(&pdev->dev, "resume not implemented\n"); + return 0; +} + +static struct platform_driver netx_eth_driver = { + .probe = netx_eth_drv_probe, + .remove = netx_eth_drv_remove, + .suspend = netx_eth_drv_suspend, + .resume = netx_eth_drv_resume, + .driver = { + .name = CARDNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init netx_eth_init(void) +{ + unsigned int phy_control, val; + + printk("NetX Ethernet driver\n"); + + phy_control = PHY_CONTROL_PHY_ADDRESS(INTERNAL_PHY_ADR>>1) | + PHY_CONTROL_PHY1_MODE(PHY_MODE_ALL) | + PHY_CONTROL_PHY1_AUTOMDIX | + PHY_CONTROL_PHY1_EN | + PHY_CONTROL_PHY0_MODE(PHY_MODE_ALL) | + PHY_CONTROL_PHY0_AUTOMDIX | + PHY_CONTROL_PHY0_EN | + PHY_CONTROL_CLK_XLATIN; + + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(phy_control | PHY_CONTROL_RESET, NETX_SYSTEM_PHY_CONTROL); + udelay(100); + + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(phy_control, NETX_SYSTEM_PHY_CONTROL); + + return platform_driver_register(&netx_eth_driver); +} + +static void __exit netx_eth_cleanup(void) +{ + platform_driver_unregister(&netx_eth_driver); +} + +module_init(netx_eth_init); +module_exit(netx_eth_cleanup); + +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 09b1176..ea93b8f 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -831,8 +831,7 @@ static int fjn_start_xmit(struct sk_buff if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index d090df4..661bfe5 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -12,7 +12,7 @@ Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net pcnet_cs.c 1.153 2003/11/09 18:53:09 - + The network driver code is based on Donald Becker's NE2000 code: Written 1992,1993 by Donald Becker. @@ -146,7 +146,7 @@ #define MII_PHYID_REG1 0x02 #define MII_PHYID_REG2 0x03 static hw_info_t hw_info[] = { - { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT }, + { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT }, { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 }, { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 }, { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94, @@ -193,7 +193,7 @@ static hw_info_t hw_info[] = { { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 }, { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65, HAS_MISC_REG | HAS_IBM_MISC }, - { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45, + { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45, HAS_MISC_REG | HAS_IBM_MISC }, { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 }, { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 }, @@ -330,7 +330,7 @@ static hw_info_t *get_hwinfo(struct pcmc for (j = 0; j < 6; j++) dev->dev_addr[j] = readb(base + (j<<1)); } - + iounmap(virt); j = pcmcia_release_window(link->win); if (j != CS_SUCCESS) @@ -490,7 +490,7 @@ static int try_io_port(struct pcmcia_dev if (link->io.NumPorts2 > 0) { /* for master/slave multifunction cards */ link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - link->irq.Attributes = + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; } } else { @@ -543,19 +543,19 @@ static int pcnet_config(struct pcmcia_de manfid = le16_to_cpu(buf[0]); prodid = le16_to_cpu(buf[1]); } - + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (last_ret == CS_SUCCESS) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); cistpl_io_t *io = &(parse.cftable_entry.io); - + if (pcmcia_get_tuple_data(link, &tuple) != 0 || pcmcia_parse_tuple(link, &tuple, &parse) != 0 || cfg->index == 0 || cfg->io.nwin == 0) goto next_entry; - + link->conf.ConfigIndex = cfg->index; /* For multifunction cards, by convention, we configure the network function with window 0, and serial with window 1 */ @@ -584,7 +584,7 @@ static int pcnet_config(struct pcmcia_de } CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - + if (link->io.NumPorts2 == 8) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; @@ -592,7 +592,7 @@ static int pcnet_config(struct pcmcia_de if ((manfid == MANFID_IBM) && (prodid == PRODID_IBM_HOME_AND_AWAY)) link->conf.ConfigIndex |= 0x10; - + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; @@ -614,7 +614,7 @@ static int pcnet_config(struct pcmcia_de hw_info = get_ax88190(link); if (hw_info == NULL) hw_info = get_hwired(link); - + if (hw_info == NULL) { printk(KERN_NOTICE "pcnet_cs: unable to read hardware net" " address for io base %#3lx\n", dev->base_addr); @@ -631,7 +631,7 @@ static int pcnet_config(struct pcmcia_de info->flags &= ~USE_BIG_BUF; if (!use_big_buf) info->flags &= ~USE_BIG_BUF; - + if (info->flags & USE_BIG_BUF) { start_pg = SOCKET_START_PG; stop_pg = SOCKET_STOP_PG; @@ -929,7 +929,7 @@ static void set_misc_reg(struct net_devi kio_addr_t nic_base = dev->base_addr; pcnet_dev_t *info = PRIV(dev); u_char tmp; - + if (info->flags & HAS_MISC_REG) { tmp = inb_p(nic_base + PCNET_MISC) & ~3; if (dev->if_port == 2) @@ -1022,7 +1022,7 @@ static int pcnet_close(struct net_device ei_close(dev); free_irq(dev->irq, dev); - + link->open--; netif_stop_queue(dev); del_timer_sync(&info->watchdog); @@ -1054,12 +1054,12 @@ static void pcnet_reset_8390(struct net_ udelay(100); } outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */ - + if (i == 100) printk(KERN_ERR "%s: pcnet_reset_8390() did not complete.\n", dev->name); set_misc_reg(dev); - + } /* pcnet_reset_8390 */ /*====================================================================*/ @@ -1233,7 +1233,7 @@ static void dma_get_8390_hdr(struct net_ dev->name, ei_status.dmaing, ei_status.irqlock); return; } - + ei_status.dmaing |= 0x01; outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD); outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO); @@ -1458,7 +1458,7 @@ static void shmem_get_8390_hdr(struct ne void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8) + (ring_page << 8) - (ei_status.rx_start_page << 8); - + copyin(hdr, xfer_start, sizeof(struct e8390_pkt_hdr)); /* Fix for big endian systems */ hdr->count = le16_to_cpu(hdr->count); @@ -1473,7 +1473,7 @@ static void shmem_block_input(struct net unsigned long offset = (TX_PAGES<<8) + ring_offset - (ei_status.rx_start_page << 8); char *buf = skb->data; - + if (offset + count > ei_status.priv) { /* We must wrap the input move. */ int semi_count = ei_status.priv - offset; @@ -1541,7 +1541,7 @@ static int setup_shmem_window(struct pcm info->base = NULL; link->win = NULL; goto failed; } - + ei_status.mem = info->base + offset; ei_status.priv = req.Size; dev->mem_start = (u_long)ei_status.mem; @@ -1768,6 +1768,8 @@ static struct pcmcia_device_id pcnet_ids PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "NE2K.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"), + PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0", + 0xb4be14e3, 0x43ac239b, 0x0877b627), PCMCIA_DEVICE_NULL }; MODULE_DEVICE_TABLE(pcmcia, pcnet_ids); diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index e74bf50..a73d545 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1883,7 +1883,7 @@ static void smc_reset(struct net_device /* Set the Window 1 control, configuration and station addr registers. No point in writing the I/O base register ;-> */ SMC_SELECT_BANK(1); - /* Automatically release succesfully transmitted packets, + /* Automatically release successfully transmitted packets, Accept link errors, counter and Tx error interrupts. */ outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE, ioaddr + CONTROL); diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 71f4505..9bae77c 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1359,7 +1359,7 @@ do_start_xmit(struct sk_buff *skb, struc kio_addr_t ioaddr = dev->base_addr; int okay; unsigned freespace; - unsigned pktlen = skb? skb->len : 0; + unsigned pktlen = skb->len; DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n", skb, dev, pktlen); @@ -1374,8 +1374,7 @@ do_start_xmit(struct sk_buff *skb, struc */ if (pktlen < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; pktlen = ETH_ZLEN; } diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index fa39b94..2ba6d3a 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -44,6 +44,17 @@ config CICADA_PHY depends on PHYLIB ---help--- Currently supports the cis8204 +config VITESSE_PHY + tristate "Drivers for the Vitesse PHYs" + depends on PHYLIB + ---help--- + Currently supports the vsc8244 + +config SMSC_PHY + tristate "Drivers for SMSC PHYs" + depends on PHYLIB + ---help--- + Currently supports the LAN83C185 PHY endmenu diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index e4116a5..a00e619 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -8,3 +8,5 @@ obj-$(CONFIG_DAVICOM_PHY) += davicom.o obj-$(CONFIG_CICADA_PHY) += cicada.o obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o +obj-$(CONFIG_SMSC_PHY) += smsc.o +obj-$(CONFIG_VITESSE_PHY) += vitesse.o diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c new file mode 100644 index 0000000..25e31fb --- /dev/null +++ b/drivers/net/phy/smsc.c @@ -0,0 +1,101 @@ +/* + * drivers/net/phy/smsc.c + * + * Driver for SMSC PHYs + * + * Author: Herbert Valerio Riedel + * + * Copyright (c) 2006 Herbert Valerio Riedel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */ +#define MII_LAN83C185_IM 30 /* Interrupt Mask */ + +#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */ +#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */ +#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */ +#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */ +#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */ +#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */ +#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */ + +#define MII_LAN83C185_ISF_INT_ALL (0x0e) + +#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \ + (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4) + + +static int lan83c185_config_intr(struct phy_device *phydev) +{ + int rc = phy_write (phydev, MII_LAN83C185_IM, + ((PHY_INTERRUPT_ENABLED == phydev->interrupts) + ? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS + : 0)); + + return rc < 0 ? rc : 0; +} + +static int lan83c185_ack_interrupt(struct phy_device *phydev) +{ + int rc = phy_read (phydev, MII_LAN83C185_ISF); + + return rc < 0 ? rc : 0; +} + +static int lan83c185_config_init(struct phy_device *phydev) +{ + return lan83c185_ack_interrupt (phydev); +} + + +static struct phy_driver lan83c185_driver = { + .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ + .phy_id_mask = 0xfffffff0, + .name = "SMSC LAN83C185", + + .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause + | SUPPORTED_Asym_Pause), + .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, + + /* basic functions */ + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .config_init = lan83c185_config_init, + + /* IRQ related */ + .ack_interrupt = lan83c185_ack_interrupt, + .config_intr = lan83c185_config_intr, + + .driver = { .owner = THIS_MODULE, } +}; + +static int __init smsc_init(void) +{ + return phy_driver_register (&lan83c185_driver); +} + +static void __exit smsc_exit(void) +{ + phy_driver_unregister (&lan83c185_driver); +} + +MODULE_DESCRIPTION("SMSC PHY driver"); +MODULE_AUTHOR("Herbert Valerio Riedel"); +MODULE_LICENSE("GPL"); + +module_init(smsc_init); +module_exit(smsc_exit); diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c new file mode 100644 index 0000000..ffd215d --- /dev/null +++ b/drivers/net/phy/vitesse.c @@ -0,0 +1,112 @@ +/* + * Driver for Vitesse PHYs + * + * Author: Kriston Carson + * + * Copyright (c) 2005 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include + +/* Vitesse Extended Control Register 1 */ +#define MII_VSC8244_EXT_CON1 0x17 +#define MII_VSC8244_EXTCON1_INIT 0x0000 + +/* Vitesse Interrupt Mask Register */ +#define MII_VSC8244_IMASK 0x19 +#define MII_VSC8244_IMASK_IEN 0x8000 +#define MII_VSC8244_IMASK_SPEED 0x4000 +#define MII_VSC8244_IMASK_LINK 0x2000 +#define MII_VSC8244_IMASK_DUPLEX 0x1000 +#define MII_VSC8244_IMASK_MASK 0xf000 + +/* Vitesse Interrupt Status Register */ +#define MII_VSC8244_ISTAT 0x1a +#define MII_VSC8244_ISTAT_STATUS 0x8000 +#define MII_VSC8244_ISTAT_SPEED 0x4000 +#define MII_VSC8244_ISTAT_LINK 0x2000 +#define MII_VSC8244_ISTAT_DUPLEX 0x1000 + +/* Vitesse Auxiliary Control/Status Register */ +#define MII_VSC8244_AUX_CONSTAT 0x1c +#define MII_VSC8244_AUXCONSTAT_INIT 0x0004 +#define MII_VSC8244_AUXCONSTAT_DUPLEX 0x0020 +#define MII_VSC8244_AUXCONSTAT_SPEED 0x0018 +#define MII_VSC8244_AUXCONSTAT_GBIT 0x0010 +#define MII_VSC8244_AUXCONSTAT_100 0x0008 + +MODULE_DESCRIPTION("Vitesse PHY driver"); +MODULE_AUTHOR("Kriston Carson"); +MODULE_LICENSE("GPL"); + +static int vsc824x_config_init(struct phy_device *phydev) +{ + int err; + + err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, + MII_VSC8244_AUXCONSTAT_INIT); + if (err < 0) + return err; + + err = phy_write(phydev, MII_VSC8244_EXT_CON1, + MII_VSC8244_EXTCON1_INIT); + return err; +} + +static int vsc824x_ack_interrupt(struct phy_device *phydev) +{ + int err = phy_read(phydev, MII_VSC8244_ISTAT); + + return (err < 0) ? err : 0; +} + +static int vsc824x_config_intr(struct phy_device *phydev) +{ + int err; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + err = phy_write(phydev, MII_VSC8244_IMASK, + MII_VSC8244_IMASK_MASK); + else + err = phy_write(phydev, MII_VSC8244_IMASK, 0); + return err; +} + +/* Vitesse 824x */ +static struct phy_driver vsc8244_driver = { + .phy_id = 0x000fc6c2, + .name = "Vitesse VSC8244", + .phy_id_mask = 0x000fffc0, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &vsc824x_config_init, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &vsc824x_ack_interrupt, + .config_intr = &vsc824x_config_intr, + .driver = { .owner = THIS_MODULE,}, +}; + +static int __init vsc8244_init(void) +{ + return phy_driver_register(&vsc8244_driver); +} + +static void __exit vsc8244_exit(void) +{ + phy_driver_unregister(&vsc8244_driver); +} + +module_init(vsc8244_init); +module_exit(vsc8244_exit); diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index b2073fc..d643a09 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1609,8 +1609,6 @@ ppp_receive_nonmp_frame(struct ppp *ppp, kfree_skb(skb); skb = ns; } - else if (!pskb_may_pull(skb, skb->len)) - goto err; else skb->ip_summed = CHECKSUM_NONE; @@ -2580,8 +2578,7 @@ ppp_find_channel(int unit) list_for_each_entry(pch, &new_channels, list) { if (pch->file.index == unit) { - list_del(&pch->list); - list_add(&pch->list, &all_channels); + list_move(&pch->list, &all_channels); return pch; } } diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 0ad3310..12d1cb2 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -184,6 +184,7 @@ #undef _R static struct pci_device_id rtl8169_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), }, { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), }, { PCI_DEVICE(0x16ec, 0x0116), }, { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024, }, @@ -2171,7 +2172,7 @@ static int rtl8169_xmit_frags(struct rtl static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) { if (dev->features & NETIF_F_TSO) { - u32 mss = skb_shinfo(skb)->tso_size; + u32 mss = skb_shinfo(skb)->gso_size; if (mss) return LargeSend | ((mss & MSSMask) << MSSShift); @@ -2221,8 +2222,7 @@ static int rtl8169_start_xmit(struct sk_ len = skb->len; if (unlikely(len < ETH_ZLEN)) { - skb = skb_padto(skb, ETH_ZLEN); - if (!skb) + if (skb_padto(skb, ETH_ZLEN)) goto err_update_stats; len = ETH_ZLEN; } diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h index 00179bc..0ef5258 100644 --- a/drivers/net/s2io-regs.h +++ b/drivers/net/s2io-regs.h @@ -167,6 +167,7 @@ #define IIC_INT_REG_ACK_ERR u8 unused4[0x08]; u64 gpio_int_reg; +#define GPIO_INT_REG_DP_ERR_INT BIT(0) #define GPIO_INT_REG_LINK_DOWN BIT(1) #define GPIO_INT_REG_LINK_UP BIT(2) u64 gpio_int_mask; @@ -187,7 +188,7 @@ #define RX_TRAFFIC_INT_n(n) /* PIC Control registers */ u64 pic_control; #define PIC_CNTL_RX_ALARM_MAP_1 BIT(0) -#define PIC_CNTL_SHARED_SPLITS(n) vBIT(n,11,4) +#define PIC_CNTL_SHARED_SPLITS(n) vBIT(n,11,5) u64 swapper_ctrl; #define SWAPPER_CTRL_PIF_R_FE BIT(0) @@ -267,6 +268,21 @@ #define SET_UPDT_CLICKS(val) vBIT(va /* General Configuration */ u64 mdio_control; +#define MDIO_MMD_INDX_ADDR(val) vBIT(val, 0, 16) +#define MDIO_MMD_DEV_ADDR(val) vBIT(val, 19, 5) +#define MDIO_MMD_PMA_DEV_ADDR 0x1 +#define MDIO_MMD_PMD_DEV_ADDR 0x1 +#define MDIO_MMD_WIS_DEV_ADDR 0x2 +#define MDIO_MMD_PCS_DEV_ADDR 0x3 +#define MDIO_MMD_PHYXS_DEV_ADDR 0x4 +#define MDIO_MMS_PRT_ADDR(val) vBIT(val, 27, 5) +#define MDIO_CTRL_START_TRANS(val) vBIT(val, 56, 4) +#define MDIO_OP(val) vBIT(val, 60, 2) +#define MDIO_OP_ADDR_TRANS 0x0 +#define MDIO_OP_WRITE_TRANS 0x1 +#define MDIO_OP_READ_POST_INC_TRANS 0x2 +#define MDIO_OP_READ_TRANS 0x3 +#define MDIO_MDIO_DATA(val) vBIT(val, 32, 16) u64 dtx_control; @@ -284,9 +300,13 @@ #define I2C_CONTROL_SET_DATA(val) vBIT(v u64 gpio_control; #define GPIO_CTRL_GPIO_0 BIT(8) u64 misc_control; +#define EXT_REQ_EN BIT(1) #define MISC_LINK_STABILITY_PRD(val) vBIT(val,29,3) - u8 unused7_1[0x240 - 0x208]; + u8 unused7_1[0x230 - 0x208]; + + u64 pic_control2; + u64 ini_dperr_ctrl; u64 wreq_split_mask; #define WREQ_SPLIT_MASK_SET_MASK(val) vBIT(val, 52, 12) @@ -493,6 +513,7 @@ #define PRC_CTRL_NO_SNOOP #define PRC_CTRL_NO_SNOOP_DESC BIT(22) #define PRC_CTRL_NO_SNOOP_BUFF BIT(23) #define PRC_CTRL_BIMODAL_INTERRUPT BIT(37) +#define PRC_CTRL_GROUP_READS BIT(38) #define PRC_CTRL_RXD_BACKOFF_INTERVAL(val) vBIT(val,40,24) u64 prc_alarm_action; @@ -541,7 +562,12 @@ #define RX_PA_CFG_IGNORE_SNAP_OUI #define RX_PA_CFG_IGNORE_LLC_CTRL BIT(3) #define RX_PA_CFG_IGNORE_L2_ERR BIT(6) - u8 unused12[0x700 - 0x1D8]; + u64 unused_11_1; + + u64 ring_bump_counter1; + u64 ring_bump_counter2; + + u8 unused12[0x700 - 0x1F0]; u64 rxdma_debug_ctrl; diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 79208f4..3defe5d 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -26,15 +26,22 @@ * * The module loadable parameters that are supported by the driver and a brief * explaination of all the variables. + * * rx_ring_num : This can be used to program the number of receive rings used * in the driver. - * rx_ring_sz: This defines the number of descriptors each ring can have. This - * is also an array of size 8. + * rx_ring_sz: This defines the number of receive blocks each ring can have. + * This is also an array of size 8. * rx_ring_mode: This defines the operation mode of all 8 rings. The valid * values are 1, 2 and 3. * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver. * tx_fifo_len: This too is an array of 8. Each element defines the number of * Tx descriptors that can be associated with each corresponding FIFO. + * intr_type: This defines the type of interrupt. The values can be 0(INTA), + * 1(MSI), 2(MSI_X). Default value is '0(INTA)' + * lro: Specifies whether to enable Large Receive Offload (LRO) or not. + * Possible values '1' for enable '0' for disable. Default is '0' + * lro_max_pkts: This parameter defines maximum number of packets can be + * aggregated as a single large packet ************************************************************************/ #include @@ -70,7 +77,7 @@ #include #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.11.2" +#define DRV_VERSION "2.0.14.2" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; @@ -106,18 +113,14 @@ #define PANIC 1 #define LOW 2 static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring) { - int level = 0; mac_info_t *mac_control; mac_control = &sp->mac_control; - if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) { - level = LOW; - if (rxb_size <= rxd_count[sp->rxd_mode]) { - level = PANIC; - } - } - - return level; + if (rxb_size <= rxd_count[sp->rxd_mode]) + return PANIC; + else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) + return LOW; + return 0; } /* Ethtool related variables and Macros. */ @@ -136,7 +139,11 @@ static char ethtool_stats_keys[][ETH_GST {"tmac_mcst_frms"}, {"tmac_bcst_frms"}, {"tmac_pause_ctrl_frms"}, + {"tmac_ttl_octets"}, + {"tmac_ucst_frms"}, + {"tmac_nucst_frms"}, {"tmac_any_err_frms"}, + {"tmac_ttl_less_fb_octets"}, {"tmac_vld_ip_octets"}, {"tmac_vld_ip"}, {"tmac_drop_ip"}, @@ -151,13 +158,27 @@ static char ethtool_stats_keys[][ETH_GST {"rmac_vld_mcst_frms"}, {"rmac_vld_bcst_frms"}, {"rmac_in_rng_len_err_frms"}, + {"rmac_out_rng_len_err_frms"}, {"rmac_long_frms"}, {"rmac_pause_ctrl_frms"}, + {"rmac_unsup_ctrl_frms"}, + {"rmac_ttl_octets"}, + {"rmac_accepted_ucst_frms"}, + {"rmac_accepted_nucst_frms"}, {"rmac_discarded_frms"}, + {"rmac_drop_events"}, + {"rmac_ttl_less_fb_octets"}, + {"rmac_ttl_frms"}, {"rmac_usized_frms"}, {"rmac_osized_frms"}, {"rmac_frag_frms"}, {"rmac_jabber_frms"}, + {"rmac_ttl_64_frms"}, + {"rmac_ttl_65_127_frms"}, + {"rmac_ttl_128_255_frms"}, + {"rmac_ttl_256_511_frms"}, + {"rmac_ttl_512_1023_frms"}, + {"rmac_ttl_1024_1518_frms"}, {"rmac_ip"}, {"rmac_ip_octets"}, {"rmac_hdr_err_ip"}, @@ -166,12 +187,82 @@ static char ethtool_stats_keys[][ETH_GST {"rmac_tcp"}, {"rmac_udp"}, {"rmac_err_drp_udp"}, + {"rmac_xgmii_err_sym"}, + {"rmac_frms_q0"}, + {"rmac_frms_q1"}, + {"rmac_frms_q2"}, + {"rmac_frms_q3"}, + {"rmac_frms_q4"}, + {"rmac_frms_q5"}, + {"rmac_frms_q6"}, + {"rmac_frms_q7"}, + {"rmac_full_q0"}, + {"rmac_full_q1"}, + {"rmac_full_q2"}, + {"rmac_full_q3"}, + {"rmac_full_q4"}, + {"rmac_full_q5"}, + {"rmac_full_q6"}, + {"rmac_full_q7"}, {"rmac_pause_cnt"}, + {"rmac_xgmii_data_err_cnt"}, + {"rmac_xgmii_ctrl_err_cnt"}, {"rmac_accepted_ip"}, {"rmac_err_tcp"}, + {"rd_req_cnt"}, + {"new_rd_req_cnt"}, + {"new_rd_req_rtry_cnt"}, + {"rd_rtry_cnt"}, + {"wr_rtry_rd_ack_cnt"}, + {"wr_req_cnt"}, + {"new_wr_req_cnt"}, + {"new_wr_req_rtry_cnt"}, + {"wr_rtry_cnt"}, + {"wr_disc_cnt"}, + {"rd_rtry_wr_ack_cnt"}, + {"txp_wr_cnt"}, + {"txd_rd_cnt"}, + {"txd_wr_cnt"}, + {"rxd_rd_cnt"}, + {"rxd_wr_cnt"}, + {"txf_rd_cnt"}, + {"rxf_wr_cnt"}, + {"rmac_ttl_1519_4095_frms"}, + {"rmac_ttl_4096_8191_frms"}, + {"rmac_ttl_8192_max_frms"}, + {"rmac_ttl_gt_max_frms"}, + {"rmac_osized_alt_frms"}, + {"rmac_jabber_alt_frms"}, + {"rmac_gt_max_alt_frms"}, + {"rmac_vlan_frms"}, + {"rmac_len_discard"}, + {"rmac_fcs_discard"}, + {"rmac_pf_discard"}, + {"rmac_da_discard"}, + {"rmac_red_discard"}, + {"rmac_rts_discard"}, + {"rmac_ingm_full_discard"}, + {"link_fault_cnt"}, {"\n DRIVER STATISTICS"}, {"single_bit_ecc_errs"}, {"double_bit_ecc_errs"}, + {"parity_err_cnt"}, + {"serious_err_cnt"}, + {"soft_reset_cnt"}, + {"fifo_full_cnt"}, + {"ring_full_cnt"}, + ("alarm_transceiver_temp_high"), + ("alarm_transceiver_temp_low"), + ("alarm_laser_bias_current_high"), + ("alarm_laser_bias_current_low"), + ("alarm_laser_output_power_high"), + ("alarm_laser_output_power_low"), + ("warn_transceiver_temp_high"), + ("warn_transceiver_temp_low"), + ("warn_laser_bias_current_high"), + ("warn_laser_bias_current_low"), + ("warn_laser_output_power_high"), + ("warn_laser_output_power_low"), ("lro_aggregated_pkts"), ("lro_flush_both_count"), ("lro_out_of_sequence_pkts"), @@ -220,9 +311,7 @@ static void s2io_vlan_rx_kill_vid(struct * the XAUI. */ -#define SWITCH_SIGN 0xA5A5A5A5A5A5A5A5ULL #define END_SIGN 0x0 - static const u64 herc_act_dtx_cfg[] = { /* Set address */ 0x8000051536750000ULL, 0x80000515367500E0ULL, @@ -244,37 +333,19 @@ static const u64 herc_act_dtx_cfg[] = { END_SIGN }; -static const u64 xena_mdio_cfg[] = { - /* Reset PMA PLL */ - 0xC001010000000000ULL, 0xC0010100000000E0ULL, - 0xC0010100008000E4ULL, - /* Remove Reset from PMA PLL */ - 0xC001010000000000ULL, 0xC0010100000000E0ULL, - 0xC0010100000000E4ULL, - END_SIGN -}; - static const u64 xena_dtx_cfg[] = { + /* Set address */ 0x8000051500000000ULL, 0x80000515000000E0ULL, - 0x80000515D93500E4ULL, 0x8001051500000000ULL, - 0x80010515000000E0ULL, 0x80010515001E00E4ULL, - 0x8002051500000000ULL, 0x80020515000000E0ULL, - 0x80020515F21000E4ULL, - /* Set PADLOOPBACKN */ - 0x8002051500000000ULL, 0x80020515000000E0ULL, - 0x80020515B20000E4ULL, 0x8003051500000000ULL, - 0x80030515000000E0ULL, 0x80030515B20000E4ULL, - 0x8004051500000000ULL, 0x80040515000000E0ULL, - 0x80040515B20000E4ULL, 0x8005051500000000ULL, - 0x80050515000000E0ULL, 0x80050515B20000E4ULL, - SWITCH_SIGN, - /* Remove PADLOOPBACKN */ + /* Write data */ + 0x80000515D9350004ULL, 0x80000515D93500E4ULL, + /* Set address */ + 0x8001051500000000ULL, 0x80010515000000E0ULL, + /* Write data */ + 0x80010515001E0004ULL, 0x80010515001E00E4ULL, + /* Set address */ 0x8002051500000000ULL, 0x80020515000000E0ULL, - 0x80020515F20000E4ULL, 0x8003051500000000ULL, - 0x80030515000000E0ULL, 0x80030515F20000E4ULL, - 0x8004051500000000ULL, 0x80040515000000E0ULL, - 0x80040515F20000E4ULL, 0x8005051500000000ULL, - 0x80050515000000E0ULL, 0x80050515F20000E4ULL, + /* Write data */ + 0x80020515F2100004ULL, 0x80020515F21000E4ULL, END_SIGN }; @@ -303,15 +374,15 @@ static const u64 fix_mac[] = { /* Module Loadable parameters. */ static unsigned int tx_fifo_num = 1; static unsigned int tx_fifo_len[MAX_TX_FIFOS] = - {[0 ...(MAX_TX_FIFOS - 1)] = 0 }; + {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN}; static unsigned int rx_ring_num = 1; static unsigned int rx_ring_sz[MAX_RX_RINGS] = - {[0 ...(MAX_RX_RINGS - 1)] = 0 }; + {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT}; static unsigned int rts_frm_len[MAX_RX_RINGS] = {[0 ...(MAX_RX_RINGS - 1)] = 0 }; static unsigned int rx_ring_mode = 1; static unsigned int use_continuous_tx_intrs = 1; -static unsigned int rmac_pause_time = 65535; +static unsigned int rmac_pause_time = 0x100; static unsigned int mc_pause_threshold_q0q3 = 187; static unsigned int mc_pause_threshold_q4q7 = 187; static unsigned int shared_splits; @@ -549,11 +620,6 @@ static int init_shared_mem(struct s2io_n rx_blocks->block_dma_addr + (rxd_size[nic->rxd_mode] * l); } - - mac_control->rings[i].rx_blocks[j].block_virt_addr = - tmp_v_addr; - mac_control->rings[i].rx_blocks[j].block_dma_addr = - tmp_p_addr; } /* Interlinking all Rx Blocks */ for (j = 0; j < blk_cnt; j++) { @@ -772,7 +838,21 @@ static int s2io_verify_pci_mode(nic_t *n return mode; } +#define NEC_VENID 0x1033 +#define NEC_DEVID 0x0125 +static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev) +{ + struct pci_dev *tdev = NULL; + while ((tdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) { + if ((tdev->vendor == NEC_VENID) && (tdev->device == NEC_DEVID)){ + if (tdev->bus == s2io_pdev->bus->parent) + return 1; + } + } + return 0; +} +static int bus_speed[8] = {33, 133, 133, 200, 266, 133, 200, 266}; /** * s2io_print_pci_mode - */ @@ -789,6 +869,14 @@ static int s2io_print_pci_mode(nic_t *ni if ( val64 & PCI_MODE_UNKNOWN_MODE) return -1; /* Unknown PCI mode */ + config->bus_speed = bus_speed[mode]; + + if (s2io_on_nec_bridge(nic->pdev)) { + DBG_PRINT(ERR_DBG, "%s: Device is on PCI-E bus\n", + nic->dev->name); + return mode; + } + if (val64 & PCI_MODE_32_BITS) { DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name); } else { @@ -798,35 +886,27 @@ static int s2io_print_pci_mode(nic_t *ni switch(mode) { case PCI_MODE_PCI_33: DBG_PRINT(ERR_DBG, "33MHz PCI bus\n"); - config->bus_speed = 33; break; case PCI_MODE_PCI_66: DBG_PRINT(ERR_DBG, "66MHz PCI bus\n"); - config->bus_speed = 133; break; case PCI_MODE_PCIX_M1_66: DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n"); - config->bus_speed = 133; /* Herc doubles the clock rate */ break; case PCI_MODE_PCIX_M1_100: DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n"); - config->bus_speed = 200; break; case PCI_MODE_PCIX_M1_133: DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n"); - config->bus_speed = 266; break; case PCI_MODE_PCIX_M2_66: DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n"); - config->bus_speed = 133; break; case PCI_MODE_PCIX_M2_100: DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n"); - config->bus_speed = 200; break; case PCI_MODE_PCIX_M2_133: DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n"); - config->bus_speed = 266; break; default: return -1; /* Unsupported bus speed */ @@ -854,7 +934,7 @@ static int init_nic(struct s2io_nic *nic int i, j; mac_info_t *mac_control; struct config_param *config; - int mdio_cnt = 0, dtx_cnt = 0; + int dtx_cnt = 0; unsigned long long mem_share; int mem_size; @@ -901,20 +981,6 @@ static int init_nic(struct s2io_nic *nic val64 = dev->mtu; writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); - /* - * Configuring the XAUI Interface of Xena. - * *************************************** - * To Configure the Xena's XAUI, one has to write a series - * of 64 bit values into two registers in a particular - * sequence. Hence a macro 'SWITCH_SIGN' has been defined - * which will be defined in the array of configuration values - * (xena_dtx_cfg & xena_mdio_cfg) at appropriate places - * to switch writing from one regsiter to another. We continue - * writing these values until we encounter the 'END_SIGN' macro. - * For example, After making a series of 21 writes into - * dtx_control register the 'SWITCH_SIGN' appears and hence we - * start writing into mdio_control until we encounter END_SIGN. - */ if (nic->device_type & XFRAME_II_DEVICE) { while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) { SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt], @@ -924,35 +990,11 @@ static int init_nic(struct s2io_nic *nic dtx_cnt++; } } else { - while (1) { - dtx_cfg: - while (xena_dtx_cfg[dtx_cnt] != END_SIGN) { - if (xena_dtx_cfg[dtx_cnt] == SWITCH_SIGN) { - dtx_cnt++; - goto mdio_cfg; - } - SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt], - &bar0->dtx_control, UF); - val64 = readq(&bar0->dtx_control); - dtx_cnt++; - } - mdio_cfg: - while (xena_mdio_cfg[mdio_cnt] != END_SIGN) { - if (xena_mdio_cfg[mdio_cnt] == SWITCH_SIGN) { - mdio_cnt++; - goto dtx_cfg; - } - SPECIAL_REG_WRITE(xena_mdio_cfg[mdio_cnt], - &bar0->mdio_control, UF); - val64 = readq(&bar0->mdio_control); - mdio_cnt++; - } - if ((xena_dtx_cfg[dtx_cnt] == END_SIGN) && - (xena_mdio_cfg[mdio_cnt] == END_SIGN)) { - break; - } else { - goto dtx_cfg; - } + while (xena_dtx_cfg[dtx_cnt] != END_SIGN) { + SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt], + &bar0->dtx_control, UF); + val64 = readq(&bar0->dtx_control); + dtx_cnt++; } } @@ -994,11 +1036,6 @@ static int init_nic(struct s2io_nic *nic } } - /* Enable Tx FIFO partition 0. */ - val64 = readq(&bar0->tx_fifo_partition_0); - val64 |= BIT(0); /* To enable the FIFO partition. */ - writeq(val64, &bar0->tx_fifo_partition_0); - /* * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug * SXE-008 TRANSMIT DMA ARBITRATION ISSUE. @@ -1177,6 +1214,11 @@ static int init_nic(struct s2io_nic *nic break; } + /* Enable Tx FIFO partition 0. */ + val64 = readq(&bar0->tx_fifo_partition_0); + val64 |= (TX_FIFO_PARTITION_EN); + writeq(val64, &bar0->tx_fifo_partition_0); + /* Filling the Rx round robin registers as per the * number of Rings and steering based on QoS. */ @@ -1545,19 +1587,26 @@ static int init_nic(struct s2io_nic *nic val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits); writeq(val64, &bar0->pic_control); + if (nic->config.bus_speed == 266) { + writeq(TXREQTO_VAL(0x7f) | TXREQTO_EN, &bar0->txreqtimeout); + writeq(0x0, &bar0->read_retry_delay); + writeq(0x0, &bar0->write_retry_delay); + } + /* * Programming the Herc to split every write transaction * that does not start on an ADB to reduce disconnects. */ if (nic->device_type == XFRAME_II_DEVICE) { - val64 = WREQ_SPLIT_MASK_SET_MASK(255); - writeq(val64, &bar0->wreq_split_mask); - } - - /* Setting Link stability period to 64 ms */ - if (nic->device_type == XFRAME_II_DEVICE) { - val64 = MISC_LINK_STABILITY_PRD(3); + val64 = EXT_REQ_EN | MISC_LINK_STABILITY_PRD(3); writeq(val64, &bar0->misc_control); + val64 = readq(&bar0->pic_control2); + val64 &= ~(BIT(13)|BIT(14)|BIT(15)); + writeq(val64, &bar0->pic_control2); + } + if (strstr(nic->product_name, "CX4")) { + val64 = TMAC_AVG_IPG(0x17); + writeq(val64, &bar0->tmac_avg_ipg); } return SUCCESS; @@ -1948,6 +1997,10 @@ static int start_nic(struct s2io_nic *ni val64 |= PRC_CTRL_RC_ENABLED; else val64 |= PRC_CTRL_RC_ENABLED | PRC_CTRL_RING_MODE_3; + if (nic->device_type == XFRAME_II_DEVICE) + val64 |= PRC_CTRL_GROUP_READS; + val64 &= ~PRC_CTRL_RXD_BACKOFF_INTERVAL(0xFFFFFF); + val64 |= PRC_CTRL_RXD_BACKOFF_INTERVAL(0x1000); writeq(val64, &bar0->prc_ctrl_n[i]); } @@ -2018,6 +2071,13 @@ static int start_nic(struct s2io_nic *ni val64 |= ADAPTER_EOI_TX_ON; writeq(val64, &bar0->adapter_control); + if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) { + /* + * Dont see link state interrupts initally on some switches, + * so directly scheduling the link state task here. + */ + schedule_work(&nic->set_link_task); + } /* SXE-002: Initialize link and activity LED */ subid = nic->pdev->subsystem_device; if (((subid & 0xFF) >= 0x07) && @@ -2029,12 +2089,6 @@ static int start_nic(struct s2io_nic *ni writeq(val64, (void __iomem *)bar0 + 0x2700); } - /* - * Don't see link state interrupts on certain switches, so - * directly scheduling a link state task from here. - */ - schedule_work(&nic->set_link_task); - return SUCCESS; } /** @@ -2134,7 +2188,7 @@ static void stop_nic(struct s2io_nic *ni { XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0; - u16 interruptible, i; + u16 interruptible; mac_info_t *mac_control; struct config_param *config; @@ -2147,12 +2201,10 @@ static void stop_nic(struct s2io_nic *ni interruptible |= TX_MAC_INTR | RX_MAC_INTR; en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS); - /* Disable PRCs */ - for (i = 0; i < config->rx_ring_num; i++) { - val64 = readq(&bar0->prc_ctrl_n[i]); - val64 &= ~((u64) PRC_CTRL_RC_ENABLED); - writeq(val64, &bar0->prc_ctrl_n[i]); - } + /* Clearing Adapter_En bit of ADAPTER_CONTROL Register */ + val64 = readq(&bar0->adapter_control); + val64 &= ~(ADAPTER_CNTL_EN); + writeq(val64, &bar0->adapter_control); } static int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb) @@ -2231,13 +2283,12 @@ #endif alloc_cnt = mac_control->rings[ring_no].pkt_cnt - atomic_read(&nic->rx_bufs_left[ring_no]); + block_no1 = mac_control->rings[ring_no].rx_curr_get_info.block_index; + off1 = mac_control->rings[ring_no].rx_curr_get_info.offset; while (alloc_tab < alloc_cnt) { block_no = mac_control->rings[ring_no].rx_curr_put_info. block_index; - block_no1 = mac_control->rings[ring_no].rx_curr_get_info. - block_index; off = mac_control->rings[ring_no].rx_curr_put_info.offset; - off1 = mac_control->rings[ring_no].rx_curr_get_info.offset; rxdp = mac_control->rings[ring_no]. rx_blocks[block_no].rxds[off].virt_addr; @@ -2307,9 +2358,9 @@ #endif memset(rxdp, 0, sizeof(RxD1_t)); skb_reserve(skb, NET_IP_ALIGN); ((RxD1_t*)rxdp)->Buffer0_ptr = pci_map_single - (nic->pdev, skb->data, size, PCI_DMA_FROMDEVICE); - rxdp->Control_2 &= (~MASK_BUFFER0_SIZE_1); - rxdp->Control_2 |= SET_BUFFER0_SIZE_1(size); + (nic->pdev, skb->data, size - NET_IP_ALIGN, + PCI_DMA_FROMDEVICE); + rxdp->Control_2 = SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN); } else if (nic->rxd_mode >= RXD_MODE_3A) { /* @@ -2516,7 +2567,7 @@ static int s2io_poll(struct net_device * mac_info_t *mac_control; struct config_param *config; XENA_dev_config_t __iomem *bar0 = nic->bar0; - u64 val64; + u64 val64 = 0xFFFFFFFFFFFFFFFFULL; int i; atomic_inc(&nic->isr_cnt); @@ -2528,8 +2579,8 @@ static int s2io_poll(struct net_device * nic->pkts_to_process = dev->quota; org_pkts_to_process = nic->pkts_to_process; - val64 = readq(&bar0->rx_traffic_int); writeq(val64, &bar0->rx_traffic_int); + val64 = readl(&bar0->rx_traffic_int); for (i = 0; i < config->rx_ring_num; i++) { rx_intr_handler(&mac_control->rings[i]); @@ -2554,7 +2605,8 @@ static int s2io_poll(struct net_device * } } /* Re enable the Rx interrupts. */ - en_dis_able_nic_intrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS); + writeq(0x0, &bar0->rx_traffic_mask); + val64 = readl(&bar0->rx_traffic_mask); atomic_dec(&nic->isr_cnt); return 0; @@ -2575,6 +2627,50 @@ no_rx: #endif /** + * s2io_netpoll - Rx interrupt service handler for netpoll support + * @dev : pointer to the device structure. + * Description: + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void s2io_netpoll(struct net_device *dev) +{ + nic_t *nic = dev->priv; + mac_info_t *mac_control; + struct config_param *config; + XENA_dev_config_t __iomem *bar0 = nic->bar0; + u64 val64; + int i; + + disable_irq(dev->irq); + + atomic_inc(&nic->isr_cnt); + mac_control = &nic->mac_control; + config = &nic->config; + + val64 = readq(&bar0->rx_traffic_int); + writeq(val64, &bar0->rx_traffic_int); + + for (i = 0; i < config->rx_ring_num; i++) + rx_intr_handler(&mac_control->rings[i]); + + for (i = 0; i < config->rx_ring_num; i++) { + if (fill_rx_buffers(nic, i) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); + DBG_PRINT(ERR_DBG, " in Rx Netpoll!!\n"); + break; + } + } + atomic_dec(&nic->isr_cnt); + enable_irq(dev->irq); + return; +} +#endif + +/** * rx_intr_handler - Rx interrupt handler * @nic: device private variable. * Description: @@ -2666,6 +2762,7 @@ #endif ((RxD3_t*)rxdp)->Buffer2_ptr, dev->mtu, PCI_DMA_FROMDEVICE); } + prefetch(skb->data); rx_osm_handler(ring_data, rxdp); get_info.offset++; ring_data->rx_curr_get_info.offset = get_info.offset; @@ -2737,6 +2834,10 @@ static void tx_intr_handler(fifo_info_t if (txdlp->Control_1 & TXD_T_CODE) { unsigned long long err; err = txdlp->Control_1 & TXD_T_CODE; + if (err & 0x1) { + nic->mac_control.stats_info->sw_stat. + parity_err_cnt++; + } if ((err >> 48) == 0xA) { DBG_PRINT(TX_DBG, "TxD returned due \ to loss of link\n"); @@ -2760,7 +2861,8 @@ to loss of link\n"); dev_kfree_skb_irq(skb); get_info.offset++; - get_info.offset %= get_info.fifo_len + 1; + if (get_info.offset == get_info.fifo_len + 1) + get_info.offset = 0; txdlp = (TxD_t *) fifo_data->list_info [get_info.offset].list_virt_addr; fifo_data->tx_curr_get_info.offset = @@ -2774,6 +2876,256 @@ to loss of link\n"); } /** + * s2io_mdio_write - Function to write in to MDIO registers + * @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS) + * @addr : address value + * @value : data value + * @dev : pointer to net_device structure + * Description: + * This function is used to write values to the MDIO registers + * NONE + */ +static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device *dev) +{ + u64 val64 = 0x0; + nic_t *sp = dev->priv; + XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0; + + //address transaction + val64 = val64 | MDIO_MMD_INDX_ADDR(addr) + | MDIO_MMD_DEV_ADDR(mmd_type) + | MDIO_MMS_PRT_ADDR(0x0); + writeq(val64, &bar0->mdio_control); + val64 = val64 | MDIO_CTRL_START_TRANS(0xE); + writeq(val64, &bar0->mdio_control); + udelay(100); + + //Data transaction + val64 = 0x0; + val64 = val64 | MDIO_MMD_INDX_ADDR(addr) + | MDIO_MMD_DEV_ADDR(mmd_type) + | MDIO_MMS_PRT_ADDR(0x0) + | MDIO_MDIO_DATA(value) + | MDIO_OP(MDIO_OP_WRITE_TRANS); + writeq(val64, &bar0->mdio_control); + val64 = val64 | MDIO_CTRL_START_TRANS(0xE); + writeq(val64, &bar0->mdio_control); + udelay(100); + + val64 = 0x0; + val64 = val64 | MDIO_MMD_INDX_ADDR(addr) + | MDIO_MMD_DEV_ADDR(mmd_type) + | MDIO_MMS_PRT_ADDR(0x0) + | MDIO_OP(MDIO_OP_READ_TRANS); + writeq(val64, &bar0->mdio_control); + val64 = val64 | MDIO_CTRL_START_TRANS(0xE); + writeq(val64, &bar0->mdio_control); + udelay(100); + +} + +/** + * s2io_mdio_read - Function to write in to MDIO registers + * @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS) + * @addr : address value + * @dev : pointer to net_device structure + * Description: + * This function is used to read values to the MDIO registers + * NONE + */ +static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev) +{ + u64 val64 = 0x0; + u64 rval64 = 0x0; + nic_t *sp = dev->priv; + XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0; + + /* address transaction */ + val64 = val64 | MDIO_MMD_INDX_ADDR(addr) + | MDIO_MMD_DEV_ADDR(mmd_type) + | MDIO_MMS_PRT_ADDR(0x0); + writeq(val64, &bar0->mdio_control); + val64 = val64 | MDIO_CTRL_START_TRANS(0xE); + writeq(val64, &bar0->mdio_control); + udelay(100); + + /* Data transaction */ + val64 = 0x0; + val64 = val64 | MDIO_MMD_INDX_ADDR(addr) + | MDIO_MMD_DEV_ADDR(mmd_type) + | MDIO_MMS_PRT_ADDR(0x0) + | MDIO_OP(MDIO_OP_READ_TRANS); + writeq(val64, &bar0->mdio_control); + val64 = val64 | MDIO_CTRL_START_TRANS(0xE); + writeq(val64, &bar0->mdio_control); + udelay(100); + + /* Read the value from regs */ + rval64 = readq(&bar0->mdio_control); + rval64 = rval64 & 0xFFFF0000; + rval64 = rval64 >> 16; + return rval64; +} +/** + * s2io_chk_xpak_counter - Function to check the status of the xpak counters + * @counter : couter value to be updated + * @flag : flag to indicate the status + * @type : counter type + * Description: + * This function is to check the status of the xpak counters value + * NONE + */ + +static void s2io_chk_xpak_counter(u64 *counter, u64 * regs_stat, u32 index, u16 flag, u16 type) +{ + u64 mask = 0x3; + u64 val64; + int i; + for(i = 0; i 0) + { + *counter = *counter + 1; + val64 = *regs_stat & mask; + val64 = val64 >> (index * 0x2); + val64 = val64 + 1; + if(val64 == 3) + { + switch(type) + { + case 1: + DBG_PRINT(ERR_DBG, "Take Xframe NIC out of " + "service. Excessive temperatures may " + "result in premature transceiver " + "failure \n"); + break; + case 2: + DBG_PRINT(ERR_DBG, "Take Xframe NIC out of " + "service Excessive bias currents may " + "indicate imminent laser diode " + "failure \n"); + break; + case 3: + DBG_PRINT(ERR_DBG, "Take Xframe NIC out of " + "service Excessive laser output " + "power may saturate far-end " + "receiver\n"); + break; + default: + DBG_PRINT(ERR_DBG, "Incorrect XPAK Alarm " + "type \n"); + } + val64 = 0x0; + } + val64 = val64 << (index * 0x2); + *regs_stat = (*regs_stat & (~mask)) | (val64); + + } else { + *regs_stat = *regs_stat & (~mask); + } +} + +/** + * s2io_updt_xpak_counter - Function to update the xpak counters + * @dev : pointer to net_device struct + * Description: + * This function is to upate the status of the xpak counters value + * NONE + */ +static void s2io_updt_xpak_counter(struct net_device *dev) +{ + u16 flag = 0x0; + u16 type = 0x0; + u16 val16 = 0x0; + u64 val64 = 0x0; + u64 addr = 0x0; + + nic_t *sp = dev->priv; + StatInfo_t *stat_info = sp->mac_control.stats_info; + + /* Check the communication with the MDIO slave */ + addr = 0x0000; + val64 = 0x0; + val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + if((val64 == 0xFFFF) || (val64 == 0x0000)) + { + DBG_PRINT(ERR_DBG, "ERR: MDIO slave access failed - " + "Returned %llx\n", (unsigned long long)val64); + return; + } + + /* Check for the expecte value of 2040 at PMA address 0x0000 */ + if(val64 != 0x2040) + { + DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - "); + DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x2040\n", + (unsigned long long)val64); + return; + } + + /* Loading the DOM register to MDIO register */ + addr = 0xA100; + s2io_mdio_write(MDIO_MMD_PMA_DEV_ADDR, addr, val16, dev); + val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + + /* Reading the Alarm flags */ + addr = 0xA070; + val64 = 0x0; + val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + + flag = CHECKBIT(val64, 0x7); + type = 1; + s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_transceiver_temp_high, + &stat_info->xpak_stat.xpak_regs_stat, + 0x0, flag, type); + + if(CHECKBIT(val64, 0x6)) + stat_info->xpak_stat.alarm_transceiver_temp_low++; + + flag = CHECKBIT(val64, 0x3); + type = 2; + s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_bias_current_high, + &stat_info->xpak_stat.xpak_regs_stat, + 0x2, flag, type); + + if(CHECKBIT(val64, 0x2)) + stat_info->xpak_stat.alarm_laser_bias_current_low++; + + flag = CHECKBIT(val64, 0x1); + type = 3; + s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_output_power_high, + &stat_info->xpak_stat.xpak_regs_stat, + 0x4, flag, type); + + if(CHECKBIT(val64, 0x0)) + stat_info->xpak_stat.alarm_laser_output_power_low++; + + /* Reading the Warning flags */ + addr = 0xA074; + val64 = 0x0; + val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); + + if(CHECKBIT(val64, 0x7)) + stat_info->xpak_stat.warn_transceiver_temp_high++; + + if(CHECKBIT(val64, 0x6)) + stat_info->xpak_stat.warn_transceiver_temp_low++; + + if(CHECKBIT(val64, 0x3)) + stat_info->xpak_stat.warn_laser_bias_current_high++; + + if(CHECKBIT(val64, 0x2)) + stat_info->xpak_stat.warn_laser_bias_current_low++; + + if(CHECKBIT(val64, 0x1)) + stat_info->xpak_stat.warn_laser_output_power_high++; + + if(CHECKBIT(val64, 0x0)) + stat_info->xpak_stat.warn_laser_output_power_low++; +} + +/** * alarm_intr_handler - Alarm Interrrupt handler * @nic: device private variable * Description: If the interrupt was neither because of Rx packet or Tx @@ -2790,6 +3142,18 @@ static void alarm_intr_handler(struct s2 struct net_device *dev = (struct net_device *) nic->dev; XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0, err_reg = 0; + u64 cnt; + int i; + nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0; + /* Handling the XPAK counters update */ + if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) { + /* waiting for an hour */ + nic->mac_control.stats_info->xpak_stat.xpak_timer_count++; + } else { + s2io_updt_xpak_counter(dev); + /* reset the count to zero */ + nic->mac_control.stats_info->xpak_stat.xpak_timer_count = 0; + } /* Handling link status change error Intr */ if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) { @@ -2816,6 +3180,8 @@ static void alarm_intr_handler(struct s2 MC_ERR_REG_MIRI_ECC_DB_ERR_1)) { netif_stop_queue(dev); schedule_work(&nic->rst_timer_task); + nic->mac_control.stats_info->sw_stat. + soft_reset_cnt++; } } } else { @@ -2827,11 +3193,13 @@ static void alarm_intr_handler(struct s2 /* In case of a serious error, the device will be Reset. */ val64 = readq(&bar0->serr_source); if (val64 & SERR_SOURCE_ANY) { + nic->mac_control.stats_info->sw_stat.serious_err_cnt++; DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name); DBG_PRINT(ERR_DBG, "serious error %llx!!\n", (unsigned long long)val64); netif_stop_queue(dev); schedule_work(&nic->rst_timer_task); + nic->mac_control.stats_info->sw_stat.soft_reset_cnt++; } /* @@ -2849,6 +3217,35 @@ static void alarm_intr_handler(struct s2 ac = readq(&bar0->adapter_control); schedule_work(&nic->set_link_task); } + /* Check for data parity error */ + val64 = readq(&bar0->pic_int_status); + if (val64 & PIC_INT_GPIO) { + val64 = readq(&bar0->gpio_int_reg); + if (val64 & GPIO_INT_REG_DP_ERR_INT) { + nic->mac_control.stats_info->sw_stat.parity_err_cnt++; + schedule_work(&nic->rst_timer_task); + nic->mac_control.stats_info->sw_stat.soft_reset_cnt++; + } + } + + /* Check for ring full counter */ + if (nic->device_type & XFRAME_II_DEVICE) { + val64 = readq(&bar0->ring_bump_counter1); + for (i=0; i<4; i++) { + cnt = ( val64 & vBIT(0xFFFF,(i*16),16)); + cnt >>= 64 - ((i+1)*16); + nic->mac_control.stats_info->sw_stat.ring_full_cnt + += cnt; + } + + val64 = readq(&bar0->ring_bump_counter2); + for (i=0; i<4; i++) { + cnt = ( val64 & vBIT(0xFFFF,(i*16),16)); + cnt >>= 64 - ((i+1)*16); + nic->mac_control.stats_info->sw_stat.ring_full_cnt + += cnt; + } + } /* Other type of interrupts are not being handled now, TODO */ } @@ -2864,23 +3261,26 @@ static void alarm_intr_handler(struct s2 * SUCCESS on success and FAILURE on failure. */ -static int wait_for_cmd_complete(nic_t * sp) +static int wait_for_cmd_complete(void *addr, u64 busy_bit) { - XENA_dev_config_t __iomem *bar0 = sp->bar0; int ret = FAILURE, cnt = 0; u64 val64; while (TRUE) { - val64 = readq(&bar0->rmac_addr_cmd_mem); - if (!(val64 & RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) { + val64 = readq(addr); + if (!(val64 & busy_bit)) { ret = SUCCESS; break; } - msleep(50); + + if(in_interrupt()) + mdelay(50); + else + msleep(50); + if (cnt++ > 10) break; } - return ret; } @@ -2919,6 +3319,9 @@ static void s2io_reset(nic_t * sp) * PCI write to sw_reset register is done by this time. */ msleep(250); + if (strstr(sp->product_name, "CX4")) { + msleep(750); + } /* Restore the PCI state saved during initialization. */ pci_restore_state(sp->pdev); @@ -3137,7 +3540,7 @@ static void restore_xmsi_data(nic_t *nic u64 val64; int i; - for (i=0; i< MAX_REQUESTED_MSI_X; i++) { + for (i=0; i< nic->avail_msix_vectors; i++) { writeq(nic->msix_info[i].addr, &bar0->xmsi_address); writeq(nic->msix_info[i].data, &bar0->xmsi_data); val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6)); @@ -3156,7 +3559,7 @@ static void store_xmsi_data(nic_t *nic) int i; /* Store and display */ - for (i=0; i< MAX_REQUESTED_MSI_X; i++) { + for (i=0; i< nic->avail_msix_vectors; i++) { val64 = (BIT(15) | vBIT(i, 26, 6)); writeq(val64, &bar0->xmsi_access); if (wait_for_msix_trans(nic, i)) { @@ -3284,15 +3687,24 @@ static int s2io_enable_msi_x(nic_t *nic) writeq(tx_mat, &bar0->tx_mat0_n[7]); } + nic->avail_msix_vectors = 0; ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X); + /* We fail init if error or we get less vectors than min required */ + if (ret >= (nic->config.tx_fifo_num + nic->config.rx_ring_num + 1)) { + nic->avail_msix_vectors = ret; + ret = pci_enable_msix(nic->pdev, nic->entries, ret); + } if (ret) { DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name); kfree(nic->entries); kfree(nic->s2io_entries); nic->entries = NULL; nic->s2io_entries = NULL; + nic->avail_msix_vectors = 0; return -ENOMEM; } + if (!nic->avail_msix_vectors) + nic->avail_msix_vectors = MAX_REQUESTED_MSI_X; /* * To enable MSI-X, MSI also needs to be enabled, due to a bug @@ -3325,8 +3737,6 @@ static int s2io_open(struct net_device * { nic_t *sp = dev->priv; int err = 0; - int i; - u16 msi_control; /* Temp variable */ /* * Make sure you have link off by default every time @@ -3336,11 +3746,14 @@ static int s2io_open(struct net_device * sp->last_link_state = 0; /* Initialize H/W and enable interrupts */ - if (s2io_card_up(sp)) { + err = s2io_card_up(sp); + if (err) { DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n", dev->name); - err = -ENODEV; - goto hw_init_failed; + if (err == -ENODEV) + goto hw_init_failed; + else + goto hw_enable_failed; } /* Store the values of the MSIX table in the nic_t structure */ @@ -3357,6 +3770,8 @@ failed\n", dev->name); } } if (sp->intr_type == MSI_X) { + int i; + for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) { if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) { sprintf(sp->desc1, "%s:MSI-X-%d-TX", @@ -3409,24 +3824,26 @@ setting_mac_address_failed: isr_registration_failed: del_timer_sync(&sp->alarm_timer); if (sp->intr_type == MSI_X) { - if (sp->device_type == XFRAME_II_DEVICE) { - for (i=1; (sp->s2io_entries[i].in_use == - MSIX_REGISTERED_SUCCESS); i++) { - int vector = sp->entries[i].vector; - void *arg = sp->s2io_entries[i].arg; + int i; + u16 msi_control; /* Temp variable */ - free_irq(vector, arg); - } - pci_disable_msix(sp->pdev); + for (i=1; (sp->s2io_entries[i].in_use == + MSIX_REGISTERED_SUCCESS); i++) { + int vector = sp->entries[i].vector; + void *arg = sp->s2io_entries[i].arg; - /* Temp */ - pci_read_config_word(sp->pdev, 0x42, &msi_control); - msi_control &= 0xFFFE; /* Disable MSI */ - pci_write_config_word(sp->pdev, 0x42, msi_control); + free_irq(vector, arg); } + pci_disable_msix(sp->pdev); + + /* Temp */ + pci_read_config_word(sp->pdev, 0x42, &msi_control); + msi_control &= 0xFFFE; /* Disable MSI */ + pci_write_config_word(sp->pdev, 0x42, msi_control); } else if (sp->intr_type == MSI) pci_disable_msi(sp->pdev); +hw_enable_failed: s2io_reset(sp); hw_init_failed: if (sp->intr_type == MSI_X) { @@ -3454,35 +3871,12 @@ hw_init_failed: static int s2io_close(struct net_device *dev) { nic_t *sp = dev->priv; - int i; - u16 msi_control; flush_scheduled_work(); netif_stop_queue(dev); /* Reset card, kill tasklet and free Tx and Rx buffers. */ - s2io_card_down(sp); - - if (sp->intr_type == MSI_X) { - if (sp->device_type == XFRAME_II_DEVICE) { - for (i=1; (sp->s2io_entries[i].in_use == - MSIX_REGISTERED_SUCCESS); i++) { - int vector = sp->entries[i].vector; - void *arg = sp->s2io_entries[i].arg; - - free_irq(vector, arg); - } - pci_read_config_word(sp->pdev, 0x42, &msi_control); - msi_control &= 0xFFFE; /* Disable MSI */ - pci_write_config_word(sp->pdev, 0x42, msi_control); + s2io_card_down(sp, 1); - pci_disable_msix(sp->pdev); - } - } - else { - free_irq(sp->pdev->irq, dev); - if (sp->intr_type == MSI) - pci_disable_msi(sp->pdev); - } sp->device_close_flag = TRUE; /* Device is shut down. */ return 0; } @@ -3545,7 +3939,8 @@ #endif queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1; /* Avoid "put" pointer going beyond "get" pointer */ - if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) { + if (txdp->Host_Control || + ((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) { DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n"); netif_stop_queue(dev); dev_kfree_skb(skb); @@ -3564,8 +3959,8 @@ #endif txdp->Control_1 = 0; txdp->Control_2 = 0; #ifdef NETIF_F_TSO - mss = skb_shinfo(skb)->tso_size; - if (mss) { + mss = skb_shinfo(skb)->gso_size; + if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) { txdp->Control_1 |= TXD_TCP_LSO_EN; txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); } @@ -3585,10 +3980,10 @@ #endif } frg_len = skb->len - skb->data_len; - if (skb_shinfo(skb)->ufo_size) { + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) { int ufo_size; - ufo_size = skb_shinfo(skb)->ufo_size; + ufo_size = skb_shinfo(skb)->gso_size; ufo_size &= ~7; txdp->Control_1 |= TXD_UFO_EN; txdp->Control_1 |= TXD_UFO_MSS(ufo_size); @@ -3614,7 +4009,7 @@ #endif txdp->Host_Control = (unsigned long) skb; txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) txdp->Control_1 |= TXD_UFO_EN; frg_cnt = skb_shinfo(skb)->nr_frags; @@ -3629,12 +4024,12 @@ #endif (sp->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size); - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) txdp->Control_1 |= TXD_UFO_EN; } txdp->Control_1 |= TXD_GATHER_CODE_LAST; - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) frg_cnt++; /* as Txd0 was used for inband header */ tx_fifo = mac_control->tx_FIFO_start[queue]; @@ -3648,18 +4043,20 @@ #ifdef NETIF_F_TSO if (mss) val64 |= TX_FIFO_SPECIAL_FUNC; #endif - if (skb_shinfo(skb)->ufo_size) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) val64 |= TX_FIFO_SPECIAL_FUNC; writeq(val64, &tx_fifo->List_Control); mmiowb(); put_off++; - put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1; + if (put_off == mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1) + put_off = 0; mac_control->fifos[queue].tx_curr_put_info.offset = put_off; /* Avoid "put" pointer going beyond "get" pointer */ - if (((put_off + 1) % queue_len) == get_off) { + if (((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) { + sp->mac_control.stats_info->sw_stat.fifo_full_cnt++; DBG_PRINT(TX_DBG, "No free TxDs for xmit, Put: 0x%x Get:0x%x\n", put_off, get_off); @@ -3795,7 +4192,6 @@ s2io_msix_fifo_handle(int irq, void *dev atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; } - static void s2io_txpic_intr_handle(nic_t *sp) { XENA_dev_config_t __iomem *bar0 = sp->bar0; @@ -3806,41 +4202,56 @@ static void s2io_txpic_intr_handle(nic_t val64 = readq(&bar0->gpio_int_reg); if ((val64 & GPIO_INT_REG_LINK_DOWN) && (val64 & GPIO_INT_REG_LINK_UP)) { + /* + * This is unstable state so clear both up/down + * interrupt and adapter to re-evaluate the link state. + */ val64 |= GPIO_INT_REG_LINK_DOWN; val64 |= GPIO_INT_REG_LINK_UP; writeq(val64, &bar0->gpio_int_reg); - goto masking; - } - - if (((sp->last_link_state == LINK_UP) && - (val64 & GPIO_INT_REG_LINK_DOWN)) || - ((sp->last_link_state == LINK_DOWN) && - (val64 & GPIO_INT_REG_LINK_UP))) { val64 = readq(&bar0->gpio_int_mask); - val64 |= GPIO_INT_MASK_LINK_DOWN; - val64 |= GPIO_INT_MASK_LINK_UP; + val64 &= ~(GPIO_INT_MASK_LINK_UP | + GPIO_INT_MASK_LINK_DOWN); writeq(val64, &bar0->gpio_int_mask); - s2io_set_link((unsigned long)sp); } -masking: - if (sp->last_link_state == LINK_UP) { - /*enable down interrupt */ - val64 = readq(&bar0->gpio_int_mask); - /* unmasks link down intr */ - val64 &= ~GPIO_INT_MASK_LINK_DOWN; - /* masks link up intr */ - val64 |= GPIO_INT_MASK_LINK_UP; - writeq(val64, &bar0->gpio_int_mask); - } else { - /*enable UP Interrupt */ - val64 = readq(&bar0->gpio_int_mask); - /* unmasks link up interrupt */ - val64 &= ~GPIO_INT_MASK_LINK_UP; - /* masks link down interrupt */ - val64 |= GPIO_INT_MASK_LINK_DOWN; - writeq(val64, &bar0->gpio_int_mask); + else if (val64 & GPIO_INT_REG_LINK_UP) { + val64 = readq(&bar0->adapter_status); + if (verify_xena_quiescence(sp, val64, + sp->device_enabled_once)) { + /* Enable Adapter */ + val64 = readq(&bar0->adapter_control); + val64 |= ADAPTER_CNTL_EN; + writeq(val64, &bar0->adapter_control); + val64 |= ADAPTER_LED_ON; + writeq(val64, &bar0->adapter_control); + if (!sp->device_enabled_once) + sp->device_enabled_once = 1; + + s2io_link(sp, LINK_UP); + /* + * unmask link down interrupt and mask link-up + * intr + */ + val64 = readq(&bar0->gpio_int_mask); + val64 &= ~GPIO_INT_MASK_LINK_DOWN; + val64 |= GPIO_INT_MASK_LINK_UP; + writeq(val64, &bar0->gpio_int_mask); + + } + }else if (val64 & GPIO_INT_REG_LINK_DOWN) { + val64 = readq(&bar0->adapter_status); + if (verify_xena_quiescence(sp, val64, + sp->device_enabled_once)) { + s2io_link(sp, LINK_DOWN); + /* Link is down so unmaks link up interrupt */ + val64 = readq(&bar0->gpio_int_mask); + val64 &= ~GPIO_INT_MASK_LINK_UP; + val64 |= GPIO_INT_MASK_LINK_DOWN; + writeq(val64, &bar0->gpio_int_mask); + } } } + val64 = readq(&bar0->gpio_int_mask); } /** @@ -3863,7 +4274,7 @@ static irqreturn_t s2io_isr(int irq, voi nic_t *sp = dev->priv; XENA_dev_config_t __iomem *bar0 = sp->bar0; int i; - u64 reason = 0, val64; + u64 reason = 0, val64, org_mask; mac_info_t *mac_control; struct config_param *config; @@ -3887,43 +4298,41 @@ static irqreturn_t s2io_isr(int irq, voi return IRQ_NONE; } + val64 = 0xFFFFFFFFFFFFFFFFULL; + /* Store current mask before masking all interrupts */ + org_mask = readq(&bar0->general_int_mask); + writeq(val64, &bar0->general_int_mask); + #ifdef CONFIG_S2IO_NAPI if (reason & GEN_INTR_RXTRAFFIC) { if (netif_rx_schedule_prep(dev)) { - en_dis_able_nic_intrs(sp, RX_TRAFFIC_INTR, - DISABLE_INTRS); + writeq(val64, &bar0->rx_traffic_mask); __netif_rx_schedule(dev); } } #else - /* If Intr is because of Rx Traffic */ - if (reason & GEN_INTR_RXTRAFFIC) { - /* - * rx_traffic_int reg is an R1 register, writing all 1's - * will ensure that the actual interrupt causing bit get's - * cleared and hence a read can be avoided. - */ - val64 = 0xFFFFFFFFFFFFFFFFULL; - writeq(val64, &bar0->rx_traffic_int); - for (i = 0; i < config->rx_ring_num; i++) { - rx_intr_handler(&mac_control->rings[i]); - } + /* + * Rx handler is called by default, without checking for the + * cause of interrupt. + * rx_traffic_int reg is an R1 register, writing all 1's + * will ensure that the actual interrupt causing bit get's + * cleared and hence a read can be avoided. + */ + writeq(val64, &bar0->rx_traffic_int); + for (i = 0; i < config->rx_ring_num; i++) { + rx_intr_handler(&mac_control->rings[i]); } #endif - /* If Intr is because of Tx Traffic */ - if (reason & GEN_INTR_TXTRAFFIC) { - /* - * tx_traffic_int reg is an R1 register, writing all 1's - * will ensure that the actual interrupt causing bit get's - * cleared and hence a read can be avoided. - */ - val64 = 0xFFFFFFFFFFFFFFFFULL; - writeq(val64, &bar0->tx_traffic_int); + /* + * tx_traffic_int reg is an R1 register, writing all 1's + * will ensure that the actual interrupt causing bit get's + * cleared and hence a read can be avoided. + */ + writeq(val64, &bar0->tx_traffic_int); - for (i = 0; i < config->tx_fifo_num; i++) - tx_intr_handler(&mac_control->fifos[i]); - } + for (i = 0; i < config->tx_fifo_num; i++) + tx_intr_handler(&mac_control->fifos[i]); if (reason & GEN_INTR_TXPIC) s2io_txpic_intr_handle(sp); @@ -3949,6 +4358,7 @@ #ifndef CONFIG_S2IO_NAPI DBG_PRINT(ERR_DBG, " in ISR!!\n"); clear_bit(0, (&sp->tasklet_status)); atomic_dec(&sp->isr_cnt); + writeq(org_mask, &bar0->general_int_mask); return IRQ_HANDLED; } clear_bit(0, (&sp->tasklet_status)); @@ -3964,7 +4374,7 @@ #ifndef CONFIG_S2IO_NAPI } } #endif - + writeq(org_mask, &bar0->general_int_mask); atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; } @@ -4067,7 +4477,8 @@ static void s2io_set_multicast(struct ne RMAC_ADDR_CMD_MEM_OFFSET(MAC_MC_ALL_MC_ADDR_OFFSET); writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait till command completes */ - wait_for_cmd_complete(sp); + wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, + RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING); sp->m_cast_flg = 1; sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET; @@ -4082,7 +4493,8 @@ static void s2io_set_multicast(struct ne RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos); writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait till command completes */ - wait_for_cmd_complete(sp); + wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, + RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING); sp->m_cast_flg = 0; sp->all_multi_pos = 0; @@ -4147,7 +4559,8 @@ static void s2io_set_multicast(struct ne writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait for command completes */ - if (wait_for_cmd_complete(sp)) { + if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, + RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) { DBG_PRINT(ERR_DBG, "%s: Adding ", dev->name); DBG_PRINT(ERR_DBG, "Multicasts failed\n"); @@ -4177,7 +4590,8 @@ static void s2io_set_multicast(struct ne writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait for command completes */ - if (wait_for_cmd_complete(sp)) { + if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, + RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) { DBG_PRINT(ERR_DBG, "%s: Adding ", dev->name); DBG_PRINT(ERR_DBG, "Multicasts failed\n"); @@ -4222,7 +4636,8 @@ static int s2io_set_mac_addr(struct net_ RMAC_ADDR_CMD_MEM_OFFSET(0); writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait till command completes */ - if (wait_for_cmd_complete(sp)) { + if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, + RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) { DBG_PRINT(ERR_DBG, "%s: set_mac_addr failed\n", dev->name); return FAILURE; } @@ -4619,6 +5034,44 @@ static int write_eeprom(nic_t * sp, int } return ret; } +static void s2io_vpd_read(nic_t *nic) +{ + u8 vpd_data[256],data; + int i=0, cnt, fail = 0; + int vpd_addr = 0x80; + + if (nic->device_type == XFRAME_II_DEVICE) { + strcpy(nic->product_name, "Xframe II 10GbE network adapter"); + vpd_addr = 0x80; + } + else { + strcpy(nic->product_name, "Xframe I 10GbE network adapter"); + vpd_addr = 0x50; + } + + for (i = 0; i < 256; i +=4 ) { + pci_write_config_byte(nic->pdev, (vpd_addr + 2), i); + pci_read_config_byte(nic->pdev, (vpd_addr + 2), &data); + pci_write_config_byte(nic->pdev, (vpd_addr + 3), 0); + for (cnt = 0; cnt <5; cnt++) { + msleep(2); + pci_read_config_byte(nic->pdev, (vpd_addr + 3), &data); + if (data == 0x80) + break; + } + if (cnt >= 5) { + DBG_PRINT(ERR_DBG, "Read of VPD data failed\n"); + fail = 1; + break; + } + pci_read_config_dword(nic->pdev, (vpd_addr + 4), + (u32 *)&vpd_data[i]); + } + if ((!fail) && (vpd_data[1] < VPD_PRODUCT_NAME_LEN)) { + memset(nic->product_name, 0, vpd_data[1]); + memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); + } +} /** * s2io_ethtool_geeprom - reads the value stored in the Eeprom. @@ -4931,8 +5384,10 @@ static int s2io_link_test(nic_t * sp, ui u64 val64; val64 = readq(&bar0->adapter_status); - if (val64 & ADAPTER_STATUS_RMAC_LOCAL_FAULT) + if(!(LINK_IS_UP(val64))) *data = 1; + else + *data = 0; return 0; } @@ -5112,7 +5567,6 @@ static void s2io_get_ethtool_stats(struc int i = 0; nic_t *sp = dev->priv; StatInfo_t *stat_info = sp->mac_control.stats_info; - u64 tmp; s2io_updt_stats(sp); tmp_stats[i++] = @@ -5129,9 +5583,19 @@ static void s2io_get_ethtool_stats(struc (u64)le32_to_cpu(stat_info->tmac_bcst_frms_oflow) << 32 | le32_to_cpu(stat_info->tmac_bcst_frms); tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms); + tmp_stats[i++] = + (u64)le32_to_cpu(stat_info->tmac_ttl_octets_oflow) << 32 | + le32_to_cpu(stat_info->tmac_ttl_octets); + tmp_stats[i++] = + (u64)le32_to_cpu(stat_info->tmac_ucst_frms_oflow) << 32 | + le32_to_cpu(stat_info->tmac_ucst_frms); + tmp_stats[i++] = + (u64)le32_to_cpu(stat_info->tmac_nucst_frms_oflow) << 32 | + le32_to_cpu(stat_info->tmac_nucst_frms); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->tmac_any_err_frms_oflow) << 32 | le32_to_cpu(stat_info->tmac_any_err_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->tmac_ttl_less_fb_octets); tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->tmac_vld_ip_oflow) << 32 | @@ -5163,11 +5627,27 @@ static void s2io_get_ethtool_stats(struc (u64)le32_to_cpu(stat_info->rmac_vld_bcst_frms_oflow) << 32 | le32_to_cpu(stat_info->rmac_vld_bcst_frms); tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms); + tmp_stats[i++] = le32_to_cpu(stat_info->rmac_out_rng_len_err_frms); tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms); tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_unsup_ctrl_frms); + tmp_stats[i++] = + (u64)le32_to_cpu(stat_info->rmac_ttl_octets_oflow) << 32 | + le32_to_cpu(stat_info->rmac_ttl_octets); + tmp_stats[i++] = + (u64)le32_to_cpu(stat_info->rmac_accepted_ucst_frms_oflow) + << 32 | le32_to_cpu(stat_info->rmac_accepted_ucst_frms); + tmp_stats[i++] = + (u64)le32_to_cpu(stat_info->rmac_accepted_nucst_frms_oflow) + << 32 | le32_to_cpu(stat_info->rmac_accepted_nucst_frms); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_discarded_frms_oflow) << 32 | le32_to_cpu(stat_info->rmac_discarded_frms); + tmp_stats[i++] = + (u64)le32_to_cpu(stat_info->rmac_drop_events_oflow) + << 32 | le32_to_cpu(stat_info->rmac_drop_events); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_less_fb_octets); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_frms); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_usized_frms_oflow) << 32 | le32_to_cpu(stat_info->rmac_usized_frms); @@ -5180,40 +5660,129 @@ static void s2io_get_ethtool_stats(struc tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_jabber_frms_oflow) << 32 | le32_to_cpu(stat_info->rmac_jabber_frms); - tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 | + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_64_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_65_127_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_128_255_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_256_511_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_512_1023_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1024_1518_frms); + tmp_stats[i++] = + (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 | le32_to_cpu(stat_info->rmac_ip); tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets); tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip); - tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 | + tmp_stats[i++] = + (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 | le32_to_cpu(stat_info->rmac_drop_ip); - tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 | + tmp_stats[i++] = + (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 | le32_to_cpu(stat_info->rmac_icmp); tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp); - tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 | + tmp_stats[i++] = + (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 | le32_to_cpu(stat_info->rmac_udp); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_err_drp_udp_oflow) << 32 | le32_to_cpu(stat_info->rmac_err_drp_udp); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_err_sym); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q0); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q1); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q2); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q3); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q4); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q5); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q6); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q7); + tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q0); + tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q1); + tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q2); + tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q3); + tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q4); + tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q5); + tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q6); + tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q7); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_pause_cnt_oflow) << 32 | le32_to_cpu(stat_info->rmac_pause_cnt); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_data_err_cnt); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_ctrl_err_cnt); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_accepted_ip_oflow) << 32 | le32_to_cpu(stat_info->rmac_accepted_ip); tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp); + tmp_stats[i++] = le32_to_cpu(stat_info->rd_req_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_rtry_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_rd_ack_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->wr_req_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_rtry_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->wr_disc_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_wr_ack_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->txp_wr_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->txd_rd_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->txd_wr_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->rxd_rd_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->rxd_wr_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->txf_rd_cnt); + tmp_stats[i++] = le32_to_cpu(stat_info->rxf_wr_cnt); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1519_4095_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_4096_8191_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_8192_max_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_gt_max_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_osized_alt_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_jabber_alt_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_gt_max_alt_frms); + tmp_stats[i++] = le64_to_cpu(stat_info->rmac_vlan_frms); + tmp_stats[i++] = le32_to_cpu(stat_info->rmac_len_discard); + tmp_stats[i++] = le32_to_cpu(stat_info->rmac_fcs_discard); + tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pf_discard); + tmp_stats[i++] = le32_to_cpu(stat_info->rmac_da_discard); + tmp_stats[i++] = le32_to_cpu(stat_info->rmac_red_discard); + tmp_stats[i++] = le32_to_cpu(stat_info->rmac_rts_discard); + tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ingm_full_discard); + tmp_stats[i++] = le32_to_cpu(stat_info->link_fault_cnt); tmp_stats[i++] = 0; tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs; tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs; + tmp_stats[i++] = stat_info->sw_stat.parity_err_cnt; + tmp_stats[i++] = stat_info->sw_stat.serious_err_cnt; + tmp_stats[i++] = stat_info->sw_stat.soft_reset_cnt; + tmp_stats[i++] = stat_info->sw_stat.fifo_full_cnt; + tmp_stats[i++] = stat_info->sw_stat.ring_full_cnt; + tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_high; + tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_low; + tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_high; + tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_low; + tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_high; + tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_low; + tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_high; + tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_low; + tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_high; + tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_low; + tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_high; + tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_low; tmp_stats[i++] = stat_info->sw_stat.clubbed_frms_cnt; tmp_stats[i++] = stat_info->sw_stat.sending_both; tmp_stats[i++] = stat_info->sw_stat.outof_sequence_pkts; tmp_stats[i++] = stat_info->sw_stat.flush_max_pkts; - tmp = 0; if (stat_info->sw_stat.num_aggregations) { - tmp = stat_info->sw_stat.sum_avg_pkts_aggregated; - do_div(tmp, stat_info->sw_stat.num_aggregations); + u64 tmp = stat_info->sw_stat.sum_avg_pkts_aggregated; + int count = 0; + /* + * Since 64-bit divide does not work on all platforms, + * do repeated subtraction. + */ + while (tmp >= stat_info->sw_stat.num_aggregations) { + tmp -= stat_info->sw_stat.num_aggregations; + count++; + } + tmp_stats[i++] = count; } - tmp_stats[i++] = tmp; + else + tmp_stats[i++] = 0; } static int s2io_ethtool_get_regs_len(struct net_device *dev) @@ -5351,7 +5920,7 @@ static int s2io_change_mtu(struct net_de dev->mtu = new_mtu; if (netif_running(dev)) { - s2io_card_down(sp); + s2io_card_down(sp, 0); netif_stop_queue(dev); if (s2io_card_up(sp)) { DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", @@ -5489,12 +6058,172 @@ static void s2io_set_link(unsigned long clear_bit(0, &(nic->link_state)); } -static void s2io_card_down(nic_t * sp) +static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba, + struct sk_buff **skb, u64 *temp0, u64 *temp1, + u64 *temp2, int size) +{ + struct net_device *dev = sp->dev; + struct sk_buff *frag_list; + + if ((sp->rxd_mode == RXD_MODE_1) && (rxdp->Host_Control == 0)) { + /* allocate skb */ + if (*skb) { + DBG_PRINT(INFO_DBG, "SKB is not NULL\n"); + /* + * As Rx frame are not going to be processed, + * using same mapped address for the Rxd + * buffer pointer + */ + ((RxD1_t*)rxdp)->Buffer0_ptr = *temp0; + } else { + *skb = dev_alloc_skb(size); + if (!(*skb)) { + DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name); + DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n"); + return -ENOMEM ; + } + /* storing the mapped addr in a temp variable + * such it will be used for next rxd whose + * Host Control is NULL + */ + ((RxD1_t*)rxdp)->Buffer0_ptr = *temp0 = + pci_map_single( sp->pdev, (*skb)->data, + size - NET_IP_ALIGN, + PCI_DMA_FROMDEVICE); + rxdp->Host_Control = (unsigned long) (*skb); + } + } else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) { + /* Two buffer Mode */ + if (*skb) { + ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2; + ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0; + ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1; + } else { + *skb = dev_alloc_skb(size); + ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 = + pci_map_single(sp->pdev, (*skb)->data, + dev->mtu + 4, + PCI_DMA_FROMDEVICE); + ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 = + pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN, + PCI_DMA_FROMDEVICE); + rxdp->Host_Control = (unsigned long) (*skb); + + /* Buffer-1 will be dummy buffer not used */ + ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 = + pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN, + PCI_DMA_FROMDEVICE); + } + } else if ((rxdp->Host_Control == 0)) { + /* Three buffer mode */ + if (*skb) { + ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0; + ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1; + ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2; + } else { + *skb = dev_alloc_skb(size); + + ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 = + pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN, + PCI_DMA_FROMDEVICE); + /* Buffer-1 receives L3/L4 headers */ + ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 = + pci_map_single( sp->pdev, (*skb)->data, + l3l4hdr_size + 4, + PCI_DMA_FROMDEVICE); + /* + * skb_shinfo(skb)->frag_list will have L4 + * data payload + */ + skb_shinfo(*skb)->frag_list = dev_alloc_skb(dev->mtu + + ALIGN_SIZE); + if (skb_shinfo(*skb)->frag_list == NULL) { + DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb \ + failed\n ", dev->name); + return -ENOMEM ; + } + frag_list = skb_shinfo(*skb)->frag_list; + frag_list->next = NULL; + /* + * Buffer-2 receives L4 data payload + */ + ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 = + pci_map_single( sp->pdev, frag_list->data, + dev->mtu, PCI_DMA_FROMDEVICE); + } + } + return 0; +} +static void set_rxd_buffer_size(nic_t *sp, RxD_t *rxdp, int size) +{ + struct net_device *dev = sp->dev; + if (sp->rxd_mode == RXD_MODE_1) { + rxdp->Control_2 = SET_BUFFER0_SIZE_1( size - NET_IP_ALIGN); + } else if (sp->rxd_mode == RXD_MODE_3B) { + rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); + rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1); + rxdp->Control_2 |= SET_BUFFER2_SIZE_3( dev->mtu + 4); + } else { + rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); + rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4); + rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu); + } +} + +static int rxd_owner_bit_reset(nic_t *sp) +{ + int i, j, k, blk_cnt = 0, size; + mac_info_t * mac_control = &sp->mac_control; + struct config_param *config = &sp->config; + struct net_device *dev = sp->dev; + RxD_t *rxdp = NULL; + struct sk_buff *skb = NULL; + buffAdd_t *ba = NULL; + u64 temp0_64 = 0, temp1_64 = 0, temp2_64 = 0; + + /* Calculate the size based on ring mode */ + size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE + + HEADER_802_2_SIZE + HEADER_SNAP_SIZE; + if (sp->rxd_mode == RXD_MODE_1) + size += NET_IP_ALIGN; + else if (sp->rxd_mode == RXD_MODE_3B) + size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4; + else + size = l3l4hdr_size + ALIGN_SIZE + BUF0_LEN + 4; + + for (i = 0; i < config->rx_ring_num; i++) { + blk_cnt = config->rx_cfg[i].num_rxd / + (rxd_count[sp->rxd_mode] +1); + + for (j = 0; j < blk_cnt; j++) { + for (k = 0; k < rxd_count[sp->rxd_mode]; k++) { + rxdp = mac_control->rings[i]. + rx_blocks[j].rxds[k].virt_addr; + if(sp->rxd_mode >= RXD_MODE_3A) + ba = &mac_control->rings[i].ba[j][k]; + set_rxd_buffer_pointer(sp, rxdp, ba, + &skb,(u64 *)&temp0_64, + (u64 *)&temp1_64, + (u64 *)&temp2_64, size); + + set_rxd_buffer_size(sp, rxdp, size); + wmb(); + /* flip the Ownership bit to Hardware */ + rxdp->Control_1 |= RXD_OWN_XENA; + } + } + } + return 0; + +} + +static void s2io_card_down(nic_t * sp, int flag) { int cnt = 0; XENA_dev_config_t __iomem *bar0 = sp->bar0; unsigned long flags; register u64 val64 = 0; + struct net_device *dev = sp->dev; del_timer_sync(&sp->alarm_timer); /* If s2io_set_link task is executing, wait till it completes. */ @@ -5505,12 +6234,51 @@ static void s2io_card_down(nic_t * sp) /* disable Tx and Rx traffic on the NIC */ stop_nic(sp); + if (flag) { + if (sp->intr_type == MSI_X) { + int i; + u16 msi_control; + + for (i=1; (sp->s2io_entries[i].in_use == + MSIX_REGISTERED_SUCCESS); i++) { + int vector = sp->entries[i].vector; + void *arg = sp->s2io_entries[i].arg; + + free_irq(vector, arg); + } + pci_read_config_word(sp->pdev, 0x42, &msi_control); + msi_control &= 0xFFFE; /* Disable MSI */ + pci_write_config_word(sp->pdev, 0x42, msi_control); + pci_disable_msix(sp->pdev); + } else { + free_irq(sp->pdev->irq, dev); + if (sp->intr_type == MSI) + pci_disable_msi(sp->pdev); + } + } + /* Waiting till all Interrupt handlers are complete */ + cnt = 0; + do { + msleep(10); + if (!atomic_read(&sp->isr_cnt)) + break; + cnt++; + } while(cnt < 5); /* Kill tasklet. */ tasklet_kill(&sp->task); /* Check if the device is Quiescent and then Reset the NIC */ do { + /* As per the HW requirement we need to replenish the + * receive buffer to avoid the ring bump. Since there is + * no intention of processing the Rx frame at this pointwe are + * just settting the ownership bit of rxd in Each Rx + * ring to HW and set the appropriate buffer size + * based on the ring mode + */ + rxd_owner_bit_reset(sp); + val64 = readq(&bar0->adapter_status); if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) { break; @@ -5528,15 +6296,6 @@ static void s2io_card_down(nic_t * sp) } while (1); s2io_reset(sp); - /* Waiting till all Interrupt handlers are complete */ - cnt = 0; - do { - msleep(10); - if (!atomic_read(&sp->isr_cnt)) - break; - cnt++; - } while(cnt < 5); - spin_lock_irqsave(&sp->tx_lock, flags); /* Free all Tx buffers */ free_tx_buffers(sp); @@ -5637,7 +6396,7 @@ static void s2io_restart_nic(unsigned lo struct net_device *dev = (struct net_device *) data; nic_t *sp = dev->priv; - s2io_card_down(sp); + s2io_card_down(sp, 0); if (s2io_card_up(sp)) { DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", dev->name); @@ -5667,6 +6426,7 @@ static void s2io_tx_watchdog(struct net_ if (netif_carrier_ok(dev)) { schedule_work(&sp->rst_timer_task); + sp->mac_control.stats_info->sw_stat.soft_reset_cnt++; } } @@ -5695,18 +6455,33 @@ static int rx_osm_handler(ring_info_t *r ((unsigned long) rxdp->Host_Control); int ring_no = ring_data->ring_no; u16 l3_csum, l4_csum; + unsigned long long err = rxdp->Control_1 & RXD_T_CODE; lro_t *lro; skb->dev = dev; - if (rxdp->Control_1 & RXD_T_CODE) { - unsigned long long err = rxdp->Control_1 & RXD_T_CODE; - DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n", - dev->name, err); - dev_kfree_skb(skb); - sp->stats.rx_crc_errors++; - atomic_dec(&sp->rx_bufs_left[ring_no]); - rxdp->Host_Control = 0; - return 0; + + if (err) { + /* Check for parity error */ + if (err & 0x1) { + sp->mac_control.stats_info->sw_stat.parity_err_cnt++; + } + + /* + * Drop the packet if bad transfer code. Exception being + * 0x5, which could be due to unsupported IPv6 extension header. + * In this case, we let stack handle the packet. + * Note that in this case, since checksum will be incorrect, + * stack will validate the same. + */ + if (err && ((err >> 48) != 0x5)) { + DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n", + dev->name, err); + sp->stats.rx_crc_errors++; + dev_kfree_skb(skb); + atomic_dec(&sp->rx_bufs_left[ring_no]); + rxdp->Host_Control = 0; + return 0; + } } /* Updating statistics */ @@ -5792,6 +6567,9 @@ static int rx_osm_handler(ring_info_t *r clear_lro_session(lro); goto send_up; case 0: /* sessions exceeded */ + case -1: /* non-TCP or not + * L2 aggregatable + */ case 5: /* * First pkt in session not * L3/L4 aggregatable @@ -5918,13 +6696,6 @@ static void s2io_init_pci(nic_t * sp) pci_write_config_word(sp->pdev, PCI_COMMAND, (pci_cmd | PCI_COMMAND_PARITY)); pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); - - /* Forcibly disabling relaxed ordering capability of the card. */ - pcix_cmd &= 0xfffd; - pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, - pcix_cmd); - pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, - &(pcix_cmd)); } MODULE_AUTHOR("Raghavendra Koushik "); @@ -5954,6 +6725,55 @@ module_param(intr_type, int, 0); module_param(lro, int, 0); module_param(lro_max_pkts, int, 0); +static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) +{ + if ( tx_fifo_num > 8) { + DBG_PRINT(ERR_DBG, "s2io: Requested number of Tx fifos not " + "supported\n"); + DBG_PRINT(ERR_DBG, "s2io: Default to 8 Tx fifos\n"); + tx_fifo_num = 8; + } + if ( rx_ring_num > 8) { + DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not " + "supported\n"); + DBG_PRINT(ERR_DBG, "s2io: Default to 8 Rx rings\n"); + rx_ring_num = 8; + } +#ifdef CONFIG_S2IO_NAPI + if (*dev_intr_type != INTA) { + DBG_PRINT(ERR_DBG, "s2io: NAPI cannot be enabled when " + "MSI/MSI-X is enabled. Defaulting to INTA\n"); + *dev_intr_type = INTA; + } +#endif +#ifndef CONFIG_PCI_MSI + if (*dev_intr_type != INTA) { + DBG_PRINT(ERR_DBG, "s2io: This kernel does not support" + "MSI/MSI-X. Defaulting to INTA\n"); + *dev_intr_type = INTA; + } +#else + if (*dev_intr_type > MSI_X) { + DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. " + "Defaulting to INTA\n"); + *dev_intr_type = INTA; + } +#endif + if ((*dev_intr_type == MSI_X) && + ((pdev->device != PCI_DEVICE_ID_HERC_WIN) && + (pdev->device != PCI_DEVICE_ID_HERC_UNI))) { + DBG_PRINT(ERR_DBG, "s2io: Xframe I does not support MSI_X. " + "Defaulting to INTA\n"); + *dev_intr_type = INTA; + } + if (rx_ring_mode > 3) { + DBG_PRINT(ERR_DBG, "s2io: Requested ring mode not supported\n"); + DBG_PRINT(ERR_DBG, "s2io: Defaulting to 3-buffer mode\n"); + rx_ring_mode = 3; + } + return SUCCESS; +} + /** * s2io_init_nic - Initialization of the adapter . * @pdev : structure containing the PCI related information of the device. @@ -5984,15 +6804,8 @@ s2io_init_nic(struct pci_dev *pdev, cons int mode; u8 dev_intr_type = intr_type; -#ifdef CONFIG_S2IO_NAPI - if (dev_intr_type != INTA) { - DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \ -is enabled. Defaulting to INTA\n"); - dev_intr_type = INTA; - } - else - DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n"); -#endif + if ((ret = s2io_verify_parm(pdev, &dev_intr_type))) + return ret; if ((ret = pci_enable_device(pdev))) { DBG_PRINT(ERR_DBG, @@ -6017,14 +6830,6 @@ #endif pci_disable_device(pdev); return -ENOMEM; } - - if ((dev_intr_type == MSI_X) && - ((pdev->device != PCI_DEVICE_ID_HERC_WIN) && - (pdev->device != PCI_DEVICE_ID_HERC_UNI))) { - DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \ -Defaulting to INTA\n"); - dev_intr_type = INTA; - } if (dev_intr_type != MSI_X) { if (pci_request_regions(pdev, s2io_driver_name)) { DBG_PRINT(ERR_DBG, "Request Regions failed\n"), @@ -6100,8 +6905,6 @@ Defaulting to INTA\n"); config = &sp->config; /* Tx side parameters. */ - if (tx_fifo_len[0] == 0) - tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */ config->tx_fifo_num = tx_fifo_num; for (i = 0; i < MAX_TX_FIFOS; i++) { config->tx_cfg[i].fifo_len = tx_fifo_len[i]; @@ -6125,8 +6928,6 @@ Defaulting to INTA\n"); config->max_txds = MAX_SKB_FRAGS + 2; /* Rx side parameters. */ - if (rx_ring_sz[0] == 0) - rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */ config->rx_ring_num = rx_ring_num; for (i = 0; i < MAX_RX_RINGS; i++) { config->rx_cfg[i].num_rxd = rx_ring_sz[i] * @@ -6210,6 +7011,10 @@ #if defined(CONFIG_S2IO_NAPI) dev->weight = 32; #endif +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = s2io_netpoll; +#endif + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; if (sp->high_dma_flag == TRUE) dev->features |= NETIF_F_HIGHDMA; @@ -6267,8 +7072,8 @@ #endif val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET); writeq(val64, &bar0->rmac_addr_cmd_mem); - wait_for_cmd_complete(sp); - + wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, + RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING); tmp64 = readq(&bar0->rmac_addr_data0_mem); mac_down = (u32) tmp64; mac_up = (u32) (tmp64 >> 32); @@ -6322,82 +7127,63 @@ #endif ret = -ENODEV; goto register_failed; } - - if (sp->device_type & XFRAME_II_DEVICE) { - DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ", - dev->name); - DBG_PRINT(ERR_DBG, "(rev %d), Version %s", + s2io_vpd_read(sp); + DBG_PRINT(ERR_DBG, "%s: Neterion %s",dev->name, sp->product_name); + DBG_PRINT(ERR_DBG, "(rev %d), Driver version %s\n", get_xena_rev_id(sp->pdev), s2io_driver_version); - switch(sp->intr_type) { - case INTA: - DBG_PRINT(ERR_DBG, ", Intr type INTA"); - break; - case MSI: - DBG_PRINT(ERR_DBG, ", Intr type MSI"); - break; - case MSI_X: - DBG_PRINT(ERR_DBG, ", Intr type MSI-X"); - break; - } - - DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n"); - DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", + DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2005 Neterion Inc.\n"); + DBG_PRINT(ERR_DBG, "%s: MAC ADDR: " + "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, sp->def_mac_addr[0].mac_addr[0], sp->def_mac_addr[0].mac_addr[1], sp->def_mac_addr[0].mac_addr[2], sp->def_mac_addr[0].mac_addr[3], sp->def_mac_addr[0].mac_addr[4], sp->def_mac_addr[0].mac_addr[5]); + if (sp->device_type & XFRAME_II_DEVICE) { mode = s2io_print_pci_mode(sp); if (mode < 0) { - DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode "); + DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n"); ret = -EBADSLT; + unregister_netdev(dev); goto set_swap_failed; } - } else { - DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ", - dev->name); - DBG_PRINT(ERR_DBG, "(rev %d), Version %s", - get_xena_rev_id(sp->pdev), - s2io_driver_version); - switch(sp->intr_type) { - case INTA: - DBG_PRINT(ERR_DBG, ", Intr type INTA"); - break; - case MSI: - DBG_PRINT(ERR_DBG, ", Intr type MSI"); - break; - case MSI_X: - DBG_PRINT(ERR_DBG, ", Intr type MSI-X"); - break; - } - DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n"); - DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - sp->def_mac_addr[0].mac_addr[0], - sp->def_mac_addr[0].mac_addr[1], - sp->def_mac_addr[0].mac_addr[2], - sp->def_mac_addr[0].mac_addr[3], - sp->def_mac_addr[0].mac_addr[4], - sp->def_mac_addr[0].mac_addr[5]); } - if (sp->rxd_mode == RXD_MODE_3B) - DBG_PRINT(ERR_DBG, "%s: 2-Buffer mode support has been " - "enabled\n",dev->name); - if (sp->rxd_mode == RXD_MODE_3A) - DBG_PRINT(ERR_DBG, "%s: 3-Buffer mode support has been " - "enabled\n",dev->name); - + switch(sp->rxd_mode) { + case RXD_MODE_1: + DBG_PRINT(ERR_DBG, "%s: 1-Buffer receive mode enabled\n", + dev->name); + break; + case RXD_MODE_3B: + DBG_PRINT(ERR_DBG, "%s: 2-Buffer receive mode enabled\n", + dev->name); + break; + case RXD_MODE_3A: + DBG_PRINT(ERR_DBG, "%s: 3-Buffer receive mode enabled\n", + dev->name); + break; + } +#ifdef CONFIG_S2IO_NAPI + DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name); +#endif + switch(sp->intr_type) { + case INTA: + DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name); + break; + case MSI: + DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI\n", dev->name); + break; + case MSI_X: + DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name); + break; + } if (sp->lro) DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n", - dev->name); + dev->name); /* Initialize device name */ - strcpy(sp->name, dev->name); - if (sp->device_type & XFRAME_II_DEVICE) - strcat(sp->name, ": Neterion Xframe II 10GbE adapter"); - else - strcat(sp->name, ": Neterion Xframe I 10GbE adapter"); + sprintf(sp->name, "%s Neterion %s", dev->name, sp->product_name); /* Initialize bimodal Interrupts */ sp->config.bimodal = bimodal; diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 0a0b5b2..3203732 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -31,6 +31,8 @@ #undef SUCCESS #define SUCCESS 0 #define FAILURE -1 +#define CHECKBIT(value, nbit) (value & (1 << nbit)) + /* Maximum time to flicker LED when asked to identify NIC using ethtool */ #define MAX_FLICKER_TIME 60000 /* 60 Secs */ @@ -78,6 +80,11 @@ #define S2IO_JUMBO_SIZE 9600 typedef struct { unsigned long long single_ecc_errs; unsigned long long double_ecc_errs; + unsigned long long parity_err_cnt; + unsigned long long serious_err_cnt; + unsigned long long soft_reset_cnt; + unsigned long long fifo_full_cnt; + unsigned long long ring_full_cnt; /* LRO statistics */ unsigned long long clubbed_frms_cnt; unsigned long long sending_both; @@ -87,6 +94,25 @@ typedef struct { unsigned long long num_aggregations; } swStat_t; +/* Xpak releated alarm and warnings */ +typedef struct { + u64 alarm_transceiver_temp_high; + u64 alarm_transceiver_temp_low; + u64 alarm_laser_bias_current_high; + u64 alarm_laser_bias_current_low; + u64 alarm_laser_output_power_high; + u64 alarm_laser_output_power_low; + u64 warn_transceiver_temp_high; + u64 warn_transceiver_temp_low; + u64 warn_laser_bias_current_high; + u64 warn_laser_bias_current_low; + u64 warn_laser_output_power_high; + u64 warn_laser_output_power_low; + u64 xpak_regs_stat; + u32 xpak_timer_count; +} xpakStat_t; + + /* The statistics block of Xena */ typedef struct stat_block { /* Tx MAC statistics counters. */ @@ -263,7 +289,9 @@ typedef struct stat_block { u32 rmac_accepted_ip_oflow; u32 reserved_14; u32 link_fault_cnt; + u8 buffer[20]; swStat_t sw_stat; + xpakStat_t xpak_stat; } StatInfo_t; /* @@ -659,7 +687,8 @@ typedef struct { } usr_addr_t; /* Default Tunable parameters of the NIC. */ -#define DEFAULT_FIFO_LEN 4096 +#define DEFAULT_FIFO_0_LEN 4096 +#define DEFAULT_FIFO_1_7_LEN 512 #define SMALL_BLK_CNT 30 #define LARGE_BLK_CNT 100 @@ -732,7 +761,7 @@ #define MAX_SUPPORTED_MULTICASTS MAX_MAC int device_close_flag; int device_enabled_once; - char name[50]; + char name[60]; struct tasklet_struct task; volatile unsigned long tasklet_status; @@ -803,6 +832,8 @@ #define MSIX_FLG 0xA5 char desc1[35]; char desc2[35]; + int avail_msix_vectors; /* No. of MSI-X vectors granted by system */ + struct msix_info_st msix_info[0x3f]; #define XFRAME_I_DEVICE 1 @@ -824,6 +855,8 @@ #define MSI_X 2 spinlock_t rx_lock; atomic_t isr_cnt; u64 *ufo_in_band_v; +#define VPD_PRODUCT_NAME_LEN 50 + u8 product_name[VPD_PRODUCT_NAME_LEN]; }; #define RESET_ERROR 1; @@ -848,28 +881,32 @@ static inline void writeq(u64 val, void writel((u32) (val), addr); writel((u32) (val >> 32), (addr + 4)); } +#endif -/* In 32 bit modes, some registers have to be written in a - * particular order to expect correct hardware operation. The - * macro SPECIAL_REG_WRITE is used to perform such ordered - * writes. Defines UF (Upper First) and LF (Lower First) will - * be used to specify the required write order. +/* + * Some registers have to be written in a particular order to + * expect correct hardware operation. The macro SPECIAL_REG_WRITE + * is used to perform such ordered writes. Defines UF (Upper First) + * and LF (Lower First) will be used to specify the required write order. */ #define UF 1 #define LF 2 static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order) { + u32 ret; + if (order == LF) { writel((u32) (val), addr); + ret = readl(addr); writel((u32) (val >> 32), (addr + 4)); + ret = readl(addr + 4); } else { writel((u32) (val >> 32), (addr + 4)); + ret = readl(addr + 4); writel((u32) (val), addr); + ret = readl(addr); } } -#else -#define SPECIAL_REG_WRITE(val, addr, dummy) writeq(val, addr) -#endif /* Interrupt related values of Xena */ @@ -965,7 +1002,7 @@ static int verify_xena_quiescence(nic_t static struct ethtool_ops netdev_ethtool_ops; static void s2io_set_link(unsigned long data); static int s2io_set_swapper(nic_t * sp); -static void s2io_card_down(nic_t *nic); +static void s2io_card_down(nic_t *nic, int flag); static int s2io_card_up(nic_t *nic); static int get_xena_rev_id(struct pci_dev *pdev); static void restore_xmsi_data(nic_t *nic); diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index bcef03f..efd0f23 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -396,8 +396,7 @@ static int seeq8005_send_packet(struct s unsigned char *buf; if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 31dd3f0..df39f34 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -1156,8 +1156,7 @@ static int sis190_start_xmit(struct sk_b dma_addr_t mapping; if (unlikely(skb->len < ETH_ZLEN)) { - skb = skb_padto(skb, ETH_ZLEN); - if (!skb) { + if (skb_padto(skb, ETH_ZLEN)) { tp->stats.tx_dropped++; goto out; } diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index f5a3bf4..d058741 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -1,6 +1,6 @@ /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux. Copyright 1999 Silicon Integrated System Corporation - Revision: 1.08.09 Sep. 19 2005 + Revision: 1.08.10 Apr. 2 2006 Modified from the driver which is originally written by Donald Becker. @@ -17,9 +17,10 @@ SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution, preliminary Rev. 1.0 Jan. 18, 1998 + Rev 1.08.10 Apr. 2 2006 Daniele Venzano add vlan (jumbo packets) support Rev 1.08.09 Sep. 19 2005 Daniele Venzano add Wake on LAN support Rev 1.08.08 Jan. 22 2005 Daniele Venzano use netif_msg for debugging messages - Rev 1.08.07 Nov. 2 2003 Daniele Venzano add suspend/resume support + Rev 1.08.07 Nov. 2 2003 Daniele Venzano add suspend/resume support Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support Rev 1.08.05 Jun. 6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary Rev 1.08.04 Apr. 25 2002 Mufasa Yang added SiS962 support @@ -77,7 +78,7 @@ #include /* User space m #include "sis900.h" #define SIS900_MODULE_NAME "sis900" -#define SIS900_DRV_VERSION "v1.08.09 Sep. 19 2005" +#define SIS900_DRV_VERSION "v1.08.10 Apr. 2 2006" static char version[] __devinitdata = KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n"; @@ -1402,6 +1403,11 @@ static void sis900_set_mode (long ioaddr rx_flags |= RxATX; } +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + /* Can accept Jumbo packet */ + rx_flags |= RxAJAB; +#endif + outl (tx_flags, ioaddr + txcfg); outl (rx_flags, ioaddr + rxcfg); } @@ -1714,18 +1720,26 @@ static int sis900_rx(struct net_device * while (rx_status & OWN) { unsigned int rx_size; + unsigned int data_size; if (--rx_work_limit < 0) break; - rx_size = (rx_status & DSIZE) - CRC_SIZE; + data_size = rx_status & DSIZE; + rx_size = data_size - CRC_SIZE; + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) + /* ``TOOLONG'' flag means jumbo packet recived. */ + if ((rx_status & TOOLONG) && data_size <= MAX_FRAME_SIZE) + rx_status &= (~ ((unsigned int)TOOLONG)); +#endif if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) { /* corrupted packet received */ if (netif_msg_rx_err(sis_priv)) printk(KERN_DEBUG "%s: Corrupted packet " - "received, buffer status = 0x%8.8x.\n", - net_dev->name, rx_status); + "received, buffer status = 0x%8.8x/%d.\n", + net_dev->name, rx_status, data_size); sis_priv->stats.rx_errors++; if (rx_status & OVERRUN) sis_priv->stats.rx_over_errors++; diff --git a/drivers/net/sis900.h b/drivers/net/sis900.h index 5032394..4834e3a 100644 --- a/drivers/net/sis900.h +++ b/drivers/net/sis900.h @@ -310,8 +310,14 @@ #define HW_SPEED_DEFAULT (HW_SPE #define CRC_SIZE 4 #define MAC_HEADER_SIZE 14 -#define TX_BUF_SIZE 1536 -#define RX_BUF_SIZE 1536 +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#define MAX_FRAME_SIZE (1518 + 4) +#else +#define MAX_FRAME_SIZE 1518 +#endif /* CONFIG_VLAN_802_1Q */ + +#define TX_BUF_SIZE (MAX_FRAME_SIZE+18) +#define RX_BUF_SIZE (MAX_FRAME_SIZE+18) #define NUM_TX_DESC 16 /* Number of Tx descriptor registers. */ #define NUM_RX_DESC 16 /* Number of Rx descriptor registers. */ diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 38a26df..f3efbd1 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -1525,7 +1525,7 @@ #endif ** This is to resolve faulty padding by the HW with 0xaa bytes. */ if (BytesSend < C_LEN_ETHERNET_MINSIZE) { - if ((pMessage = skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) == NULL) { + if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) { spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); return 0; } diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 5ca5a1b..19a4a16 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -44,12 +44,13 @@ #include #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.5" +#define DRV_VERSION "1.6" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 #define DEFAULT_RX_RING_SIZE 512 #define MAX_TX_RING_SIZE 1024 +#define TX_LOW_WATER (MAX_SKB_FRAGS + 1) #define MAX_RX_RING_SIZE 4096 #define RX_COPY_THRESHOLD 128 #define RX_BUF_SIZE 1536 @@ -401,7 +402,7 @@ static int skge_set_ring_param(struct ne int err; if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE || - p->tx_pending < MAX_SKB_FRAGS+1 || p->tx_pending > MAX_TX_RING_SIZE) + p->tx_pending < TX_LOW_WATER || p->tx_pending > MAX_TX_RING_SIZE) return -EINVAL; skge->rx_ring.count = p->rx_pending; @@ -603,7 +604,7 @@ static void skge_led(struct skge_port *s struct skge_hw *hw = skge->hw; int port = skge->port; - spin_lock_bh(&hw->phy_lock); + mutex_lock(&hw->phy_mutex); if (hw->chip_id == CHIP_ID_GENESIS) { switch (mode) { case LED_MODE_OFF: @@ -663,7 +664,7 @@ static void skge_led(struct skge_port *s PHY_M_LED_MO_RX(MO_LED_ON)); } } - spin_unlock_bh(&hw->phy_lock); + mutex_unlock(&hw->phy_mutex); } /* blink LED's for finding board */ @@ -2038,7 +2039,7 @@ static void skge_phy_reset(struct skge_p netif_stop_queue(skge->netdev); netif_carrier_off(skge->netdev); - spin_lock_bh(&hw->phy_lock); + mutex_lock(&hw->phy_mutex); if (hw->chip_id == CHIP_ID_GENESIS) { genesis_reset(hw, port); genesis_mac_init(hw, port); @@ -2046,7 +2047,7 @@ static void skge_phy_reset(struct skge_p yukon_reset(hw, port); yukon_init(hw, port); } - spin_unlock_bh(&hw->phy_lock); + mutex_unlock(&hw->phy_mutex); } /* Basic MII support */ @@ -2067,12 +2068,12 @@ static int skge_ioctl(struct net_device /* fallthru */ case SIOCGMIIREG: { u16 val = 0; - spin_lock_bh(&hw->phy_lock); + mutex_lock(&hw->phy_mutex); if (hw->chip_id == CHIP_ID_GENESIS) err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); else err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); - spin_unlock_bh(&hw->phy_lock); + mutex_unlock(&hw->phy_mutex); data->val_out = val; break; } @@ -2081,14 +2082,14 @@ static int skge_ioctl(struct net_device if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_bh(&hw->phy_lock); + mutex_lock(&hw->phy_mutex); if (hw->chip_id == CHIP_ID_GENESIS) err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f, data->val_in); else err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f, data->val_in); - spin_unlock_bh(&hw->phy_lock); + mutex_unlock(&hw->phy_mutex); break; } return err; @@ -2191,12 +2192,12 @@ static int skge_up(struct net_device *de goto free_rx_ring; /* Initialize MAC */ - spin_lock_bh(&hw->phy_lock); + mutex_lock(&hw->phy_mutex); if (hw->chip_id == CHIP_ID_GENESIS) genesis_mac_init(hw, port); else yukon_mac_init(hw, port); - spin_unlock_bh(&hw->phy_lock); + mutex_unlock(&hw->phy_mutex); /* Configure RAMbuffers */ chunk = hw->ram_size / ((hw->ports + 1)*2); @@ -2302,21 +2303,19 @@ static int skge_xmit_frame(struct sk_buf { struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; - struct skge_ring *ring = &skge->tx_ring; struct skge_element *e; struct skge_tx_desc *td; int i; u32 control, len; u64 map; + unsigned long flags; - skb = skb_padto(skb, ETH_ZLEN); - if (!skb) + if (skb_padto(skb, ETH_ZLEN)) return NETDEV_TX_OK; - if (!spin_trylock(&skge->tx_lock)) { + if (!spin_trylock_irqsave(&skge->tx_lock, flags)) /* Collision - tell upper layer to requeue */ return NETDEV_TX_LOCKED; - } if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) { if (!netif_queue_stopped(dev)) { @@ -2325,12 +2324,13 @@ static int skge_xmit_frame(struct sk_buf printk(KERN_WARNING PFX "%s: ring full when queue awake!\n", dev->name); } - spin_unlock(&skge->tx_lock); + spin_unlock_irqrestore(&skge->tx_lock, flags); return NETDEV_TX_BUSY; } - e = ring->to_use; + e = skge->tx_ring.to_use; td = e->desc; + BUG_ON(td->control & BMU_OWN); e->skb = skb; len = skb_headlen(skb); map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); @@ -2371,8 +2371,10 @@ static int skge_xmit_frame(struct sk_buf frag->size, PCI_DMA_TODEVICE); e = e->next; - e->skb = NULL; + e->skb = skb; tf = e->desc; + BUG_ON(tf->control & BMU_OWN); + tf->dma_lo = map; tf->dma_hi = (u64) map >> 32; pci_unmap_addr_set(e, mapaddr, map); @@ -2389,56 +2391,68 @@ static int skge_xmit_frame(struct sk_buf skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START); - if (netif_msg_tx_queued(skge)) + if (unlikely(netif_msg_tx_queued(skge))) printk(KERN_DEBUG "%s: tx queued, slot %td, len %d\n", - dev->name, e - ring->start, skb->len); + dev->name, e - skge->tx_ring.start, skb->len); - ring->to_use = e->next; - if (skge_avail(&skge->tx_ring) <= MAX_SKB_FRAGS + 1) { + skge->tx_ring.to_use = e->next; + if (skge_avail(&skge->tx_ring) <= TX_LOW_WATER) { pr_debug("%s: transmit queue full\n", dev->name); netif_stop_queue(dev); } - mmiowb(); - spin_unlock(&skge->tx_lock); + spin_unlock_irqrestore(&skge->tx_lock, flags); dev->trans_start = jiffies; return NETDEV_TX_OK; } -static void skge_tx_complete(struct skge_port *skge, struct skge_element *last) + +/* Free resources associated with this reing element */ +static void skge_tx_free(struct skge_port *skge, struct skge_element *e, + u32 control) { struct pci_dev *pdev = skge->hw->pdev; - struct skge_element *e; - for (e = skge->tx_ring.to_clean; e != last; e = e->next) { - struct sk_buff *skb = e->skb; - int i; + BUG_ON(!e->skb); - e->skb = NULL; + /* skb header vs. fragment */ + if (control & BMU_STF) pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr), - skb_headlen(skb), PCI_DMA_TODEVICE); + pci_unmap_len(e, maplen), + PCI_DMA_TODEVICE); + else + pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr), + pci_unmap_len(e, maplen), + PCI_DMA_TODEVICE); - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - e = e->next; - pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr), - skb_shinfo(skb)->frags[i].size, - PCI_DMA_TODEVICE); - } + if (control & BMU_EOF) { + if (unlikely(netif_msg_tx_done(skge))) + printk(KERN_DEBUG PFX "%s: tx done slot %td\n", + skge->netdev->name, e - skge->tx_ring.start); - dev_kfree_skb(skb); + dev_kfree_skb_any(e->skb); } - skge->tx_ring.to_clean = e; + e->skb = NULL; } +/* Free all buffers in transmit ring */ static void skge_tx_clean(struct skge_port *skge) { + struct skge_element *e; + unsigned long flags; + + spin_lock_irqsave(&skge->tx_lock, flags); + for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { + struct skge_tx_desc *td = e->desc; + skge_tx_free(skge, e, td->control); + td->control = 0; + } - spin_lock_bh(&skge->tx_lock); - skge_tx_complete(skge, skge->tx_ring.to_use); + skge->tx_ring.to_clean = e; netif_wake_queue(skge->netdev); - spin_unlock_bh(&skge->tx_lock); + spin_unlock_irqrestore(&skge->tx_lock, flags); } static void skge_tx_timeout(struct net_device *dev) @@ -2664,32 +2678,28 @@ resubmit: return NULL; } -static void skge_tx_done(struct skge_port *skge) +/* Free all buffers in Tx ring which are no longer owned by device */ +static void skge_txirq(struct net_device *dev) { + struct skge_port *skge = netdev_priv(dev); struct skge_ring *ring = &skge->tx_ring; - struct skge_element *e, *last; + struct skge_element *e; + + rmb(); spin_lock(&skge->tx_lock); - last = ring->to_clean; for (e = ring->to_clean; e != ring->to_use; e = e->next) { struct skge_tx_desc *td = e->desc; if (td->control & BMU_OWN) break; - if (td->control & BMU_EOF) { - last = e->next; - if (unlikely(netif_msg_tx_done(skge))) - printk(KERN_DEBUG PFX "%s: tx done slot %td\n", - skge->netdev->name, e - ring->start); - } + skge_tx_free(skge, e, td->control); } + skge->tx_ring.to_clean = e; - skge_tx_complete(skge, last); - - skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); - - if (skge_avail(&skge->tx_ring) > MAX_SKB_FRAGS + 1) + if (netif_queue_stopped(skge->netdev) + && skge_avail(&skge->tx_ring) > TX_LOW_WATER) netif_wake_queue(skge->netdev); spin_unlock(&skge->tx_lock); @@ -2704,8 +2714,6 @@ static int skge_poll(struct net_device * int to_do = min(dev->quota, *budget); int work_done = 0; - skge_tx_done(skge); - for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) { struct skge_rx_desc *rd = e->desc; struct sk_buff *skb; @@ -2737,10 +2745,12 @@ static int skge_poll(struct net_device * return 1; /* not done */ netif_rx_complete(dev); - mmiowb(); - hw->intr_mask |= skge->port == 0 ? (IS_R1_F|IS_XA1_F) : (IS_R2_F|IS_XA2_F); + spin_lock_irq(&hw->hw_lock); + hw->intr_mask |= rxirqmask[skge->port]; skge_write32(hw, B0_IMSK, hw->intr_mask); + mmiowb(); + spin_unlock_irq(&hw->hw_lock); return 0; } @@ -2847,16 +2857,16 @@ static void skge_error_irq(struct skge_h } /* - * Interrupt from PHY are handled in tasklet (soft irq) + * Interrupt from PHY are handled in work queue * because accessing phy registers requires spin wait which might * cause excess interrupt latency. */ -static void skge_extirq(unsigned long data) +static void skge_extirq(void *arg) { - struct skge_hw *hw = (struct skge_hw *) data; + struct skge_hw *hw = arg; int port; - spin_lock(&hw->phy_lock); + mutex_lock(&hw->phy_mutex); for (port = 0; port < hw->ports; port++) { struct net_device *dev = hw->dev[port]; struct skge_port *skge = netdev_priv(dev); @@ -2868,10 +2878,12 @@ static void skge_extirq(unsigned long da bcom_phy_intr(skge); } } - spin_unlock(&hw->phy_lock); + mutex_unlock(&hw->phy_mutex); + spin_lock_irq(&hw->hw_lock); hw->intr_mask |= IS_EXT_REG; skge_write32(hw, B0_IMSK, hw->intr_mask); + spin_unlock_irq(&hw->hw_lock); } static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) @@ -2884,54 +2896,68 @@ static irqreturn_t skge_intr(int irq, vo if (status == 0) return IRQ_NONE; + spin_lock(&hw->hw_lock); + status &= hw->intr_mask; if (status & IS_EXT_REG) { hw->intr_mask &= ~IS_EXT_REG; - tasklet_schedule(&hw->ext_tasklet); + schedule_work(&hw->phy_work); } - if (status & (IS_R1_F|IS_XA1_F)) { - skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F); - hw->intr_mask &= ~(IS_R1_F|IS_XA1_F); - netif_rx_schedule(hw->dev[0]); + if (status & IS_XA1_F) { + skge_write8(hw, Q_ADDR(Q_XA1, Q_CSR), CSR_IRQ_CL_F); + skge_txirq(hw->dev[0]); } - if (status & (IS_R2_F|IS_XA2_F)) { - skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F); - hw->intr_mask &= ~(IS_R2_F|IS_XA2_F); - netif_rx_schedule(hw->dev[1]); + if (status & IS_R1_F) { + skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F); + hw->intr_mask &= ~IS_R1_F; + netif_rx_schedule(hw->dev[0]); } - if (likely((status & hw->intr_mask) == 0)) - return IRQ_HANDLED; + if (status & IS_PA_TO_TX1) + skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1); if (status & IS_PA_TO_RX1) { struct skge_port *skge = netdev_priv(hw->dev[0]); - ++skge->net_stats.rx_over_errors; - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1); - } - if (status & IS_PA_TO_RX2) { - struct skge_port *skge = netdev_priv(hw->dev[1]); ++skge->net_stats.rx_over_errors; - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2); + skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1); } - if (status & IS_PA_TO_TX1) - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1); - - if (status & IS_PA_TO_TX2) - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2); if (status & IS_MAC1) skge_mac_intr(hw, 0); - if (status & IS_MAC2) - skge_mac_intr(hw, 1); + if (hw->dev[1]) { + if (status & IS_XA2_F) { + skge_write8(hw, Q_ADDR(Q_XA2, Q_CSR), CSR_IRQ_CL_F); + skge_txirq(hw->dev[1]); + } + + if (status & IS_R2_F) { + skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F); + hw->intr_mask &= ~IS_R2_F; + netif_rx_schedule(hw->dev[1]); + } + + if (status & IS_PA_TO_RX2) { + struct skge_port *skge = netdev_priv(hw->dev[1]); + ++skge->net_stats.rx_over_errors; + skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2); + } + + if (status & IS_PA_TO_TX2) + skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2); + + if (status & IS_MAC2) + skge_mac_intr(hw, 1); + } if (status & IS_HW_ERR) skge_error_irq(hw); skge_write32(hw, B0_IMSK, hw->intr_mask); + spin_unlock(&hw->hw_lock); return IRQ_HANDLED; } @@ -2957,7 +2983,7 @@ static int skge_set_mac_address(struct n if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - spin_lock_bh(&hw->phy_lock); + mutex_lock(&hw->phy_mutex); memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); @@ -2970,7 +2996,7 @@ static int skge_set_mac_address(struct n gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); } - spin_unlock_bh(&hw->phy_lock); + mutex_unlock(&hw->phy_mutex); return 0; } @@ -3082,6 +3108,7 @@ static int skge_reset(struct skge_hw *hw else hw->ram_size = t8 * 4096; + spin_lock_init(&hw->hw_lock); hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1; if (hw->ports > 1) hw->intr_mask |= IS_PORT_2; @@ -3150,14 +3177,14 @@ static int skge_reset(struct skge_hw *hw skge_write32(hw, B0_IMSK, hw->intr_mask); - spin_lock_bh(&hw->phy_lock); + mutex_lock(&hw->phy_mutex); for (i = 0; i < hw->ports; i++) { if (hw->chip_id == CHIP_ID_GENESIS) genesis_reset(hw, i); else yukon_reset(hw, i); } - spin_unlock_bh(&hw->phy_lock); + mutex_unlock(&hw->phy_mutex); return 0; } @@ -3305,8 +3332,8 @@ #endif } hw->pdev = pdev; - spin_lock_init(&hw->phy_lock); - tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw); + mutex_init(&hw->phy_mutex); + INIT_WORK(&hw->phy_work, skge_extirq, hw); hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); if (!hw->regs) { @@ -3334,6 +3361,14 @@ #endif if ((dev = skge_devinit(hw, 0, using_dac)) == NULL) goto err_out_led_off; + if (!is_valid_ether_addr(dev->dev_addr)) { + printk(KERN_ERR PFX "%s: bad (zero?) ethernet address in rom\n", + pci_name(pdev)); + err = -EIO; + goto err_out_free_netdev; + } + + err = register_netdev(dev); if (err) { printk(KERN_ERR PFX "%s: cannot register net device\n", @@ -3388,11 +3423,15 @@ static void __devexit skge_remove(struct dev0 = hw->dev[0]; unregister_netdev(dev0); + spin_lock_irq(&hw->hw_lock); + hw->intr_mask = 0; skge_write32(hw, B0_IMSK, 0); + spin_unlock_irq(&hw->hw_lock); + skge_write16(hw, B0_LED, LED_STAT_OFF); skge_write8(hw, B0_CTST, CS_RST_SET); - tasklet_kill(&hw->ext_tasklet); + flush_scheduled_work(); free_irq(pdev->irq, hw); pci_release_regions(pdev); diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 1f1ce88..ed19ff4 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -2388,6 +2388,7 @@ struct skge_ring { struct skge_hw { void __iomem *regs; struct pci_dev *pdev; + spinlock_t hw_lock; u32 intr_mask; struct net_device *dev[2]; @@ -2399,9 +2400,8 @@ struct skge_hw { u32 ram_size; u32 ram_offset; u16 phy_addr; - - struct tasklet_struct ext_tasklet; - spinlock_t phy_lock; + struct work_struct phy_work; + struct mutex phy_mutex; }; enum { diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index fba1e4d..d357787 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1160,7 +1160,7 @@ static unsigned tx_le_req(const struct s count = sizeof(dma_addr_t) / sizeof(u32); count += skb_shinfo(skb)->nr_frags * count; - if (skb_shinfo(skb)->tso_size) + if (skb_shinfo(skb)->gso_size) ++count; if (skb->ip_summed == CHECKSUM_HW) @@ -1232,7 +1232,7 @@ static int sky2_xmit_frame(struct sk_buf } /* Check for TCP Segmentation Offload */ - mss = skb_shinfo(skb)->tso_size; + mss = skb_shinfo(skb)->gso_size; if (mss != 0) { /* just drop the packet if non-linear expansion fails */ if (skb_header_cloned(skb) && diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c index 3db30cd..5b4e852 100644 --- a/drivers/net/smc-ultra.c +++ b/drivers/net/smc-ultra.c @@ -553,7 +553,7 @@ MODULE_LICENSE("GPL"); /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ -int +int __init init_module(void) { struct net_device *dev; diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c index b3e397d..ff9bd97 100644 --- a/drivers/net/smc-ultra32.c +++ b/drivers/net/smc-ultra32.c @@ -421,7 +421,7 @@ static struct net_device *dev_ultra[MAX_ MODULE_DESCRIPTION("SMC Ultra32 EISA ethernet driver"); MODULE_LICENSE("GPL"); -int init_module(void) +int __init init_module(void) { int this_dev, found = 0; diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c new file mode 100644 index 0000000..bdd8702 --- /dev/null +++ b/drivers/net/smc911x.c @@ -0,0 +1,2307 @@ +/* + * smc911x.c + * This is a driver for SMSC's LAN911{5,6,7,8} single-chip Ethernet devices. + * + * Copyright (C) 2005 Sensoria Corp + * Derived from the unified SMC91x driver by Nicolas Pitre + * and the smsc911x.c reference driver by SMSC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Arguments: + * watchdog = TX watchdog timeout + * tx_fifo_kb = Size of TX FIFO in KB + * + * History: + * 04/16/05 Dustin McIntire Initial version + */ +static const char version[] = + "smc911x.c: v1.0 04-16-2005 by Dustin McIntire \n"; + +/* Debugging options */ +#define ENABLE_SMC_DEBUG_RX 0 +#define ENABLE_SMC_DEBUG_TX 0 +#define ENABLE_SMC_DEBUG_DMA 0 +#define ENABLE_SMC_DEBUG_PKTS 0 +#define ENABLE_SMC_DEBUG_MISC 0 +#define ENABLE_SMC_DEBUG_FUNC 0 + +#define SMC_DEBUG_RX ((ENABLE_SMC_DEBUG_RX ? 1 : 0) << 0) +#define SMC_DEBUG_TX ((ENABLE_SMC_DEBUG_TX ? 1 : 0) << 1) +#define SMC_DEBUG_DMA ((ENABLE_SMC_DEBUG_DMA ? 1 : 0) << 2) +#define SMC_DEBUG_PKTS ((ENABLE_SMC_DEBUG_PKTS ? 1 : 0) << 3) +#define SMC_DEBUG_MISC ((ENABLE_SMC_DEBUG_MISC ? 1 : 0) << 4) +#define SMC_DEBUG_FUNC ((ENABLE_SMC_DEBUG_FUNC ? 1 : 0) << 5) + +#ifndef SMC_DEBUG +#define SMC_DEBUG ( SMC_DEBUG_RX | \ + SMC_DEBUG_TX | \ + SMC_DEBUG_DMA | \ + SMC_DEBUG_PKTS | \ + SMC_DEBUG_MISC | \ + SMC_DEBUG_FUNC \ + ) +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "smc911x.h" + +/* + * Transmit timeout, default 5 seconds. + */ +static int watchdog = 5000; +module_param(watchdog, int, 0400); +MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); + +static int tx_fifo_kb=8; +module_param(tx_fifo_kb, int, 0400); +MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1 0 +#define DBG(n, args...) \ + do { \ + if (SMC_DEBUG & (n)) \ + printk(args); \ + } while (0) + +#define PRINTK(args...) printk(args) +#else +#define DBG(n, args...) do { } while (0) +#define PRINTK(args...) printk(KERN_DEBUG args) +#endif + +#if SMC_DEBUG_PKTS > 0 +static void PRINT_PKT(u_char *buf, int length) +{ + int i; + int remainder; + int lines; + + lines = length / 16; + remainder = length % 16; + + for (i = 0; i < lines ; i ++) { + int cur; + for (cur = 0; cur < 8; cur++) { + u_char a, b; + a = *buf++; + b = *buf++; + printk("%02x%02x ", a, b); + } + printk("\n"); + } + for (i = 0; i < remainder/2 ; i++) { + u_char a, b; + a = *buf++; + b = *buf++; + printk("%02x%02x ", a, b); + } + printk("\n"); +} +#else +#define PRINT_PKT(x...) do { } while (0) +#endif + + +/* this enables an interrupt in the interrupt mask register */ +#define SMC_ENABLE_INT(x) do { \ + unsigned int __mask; \ + unsigned long __flags; \ + spin_lock_irqsave(&lp->lock, __flags); \ + __mask = SMC_GET_INT_EN(); \ + __mask |= (x); \ + SMC_SET_INT_EN(__mask); \ + spin_unlock_irqrestore(&lp->lock, __flags); \ +} while (0) + +/* this disables an interrupt from the interrupt mask register */ +#define SMC_DISABLE_INT(x) do { \ + unsigned int __mask; \ + unsigned long __flags; \ + spin_lock_irqsave(&lp->lock, __flags); \ + __mask = SMC_GET_INT_EN(); \ + __mask &= ~(x); \ + SMC_SET_INT_EN(__mask); \ + spin_unlock_irqrestore(&lp->lock, __flags); \ +} while (0) + +/* + * this does a soft reset on the device + */ +static void smc911x_reset(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned int reg, timeout=0, resets=1; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + /* Take out of PM setting first */ + if ((SMC_GET_PMT_CTRL() & PMT_CTRL_READY_) == 0) { + /* Write to the bytetest will take out of powerdown */ + SMC_SET_BYTE_TEST(0); + timeout=10; + do { + udelay(10); + reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_; + } while ( timeout-- && !reg); + if (timeout == 0) { + PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name); + return; + } + } + + /* Disable all interrupts */ + spin_lock_irqsave(&lp->lock, flags); + SMC_SET_INT_EN(0); + spin_unlock_irqrestore(&lp->lock, flags); + + while (resets--) { + SMC_SET_HW_CFG(HW_CFG_SRST_); + timeout=10; + do { + udelay(10); + reg = SMC_GET_HW_CFG(); + /* If chip indicates reset timeout then try again */ + if (reg & HW_CFG_SRST_TO_) { + PRINTK("%s: chip reset timeout, retrying...\n", dev->name); + resets++; + break; + } + } while ( timeout-- && (reg & HW_CFG_SRST_)); + } + if (timeout == 0) { + PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name); + return; + } + + /* make sure EEPROM has finished loading before setting GPIO_CFG */ + timeout=1000; + while ( timeout-- && (SMC_GET_E2P_CMD() & E2P_CMD_EPC_BUSY_)) { + udelay(10); + } + if (timeout == 0){ + PRINTK("%s: smc911x_reset timeout waiting for EEPROM busy\n", dev->name); + return; + } + + /* Initialize interrupts */ + SMC_SET_INT_EN(0); + SMC_ACK_INT(-1); + + /* Reset the FIFO level and flow control settings */ + SMC_SET_HW_CFG((lp->tx_fifo_kb & 0xF) << 16); +//TODO: Figure out what appropriate pause time is + SMC_SET_FLOW(FLOW_FCPT_ | FLOW_FCEN_); + SMC_SET_AFC_CFG(lp->afc_cfg); + + + /* Set to LED outputs */ + SMC_SET_GPIO_CFG(0x70070000); + + /* + * Deassert IRQ for 1*10us for edge type interrupts + * and drive IRQ pin push-pull + */ + SMC_SET_IRQ_CFG( (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ ); + + /* clear anything saved */ + if (lp->pending_tx_skb != NULL) { + dev_kfree_skb (lp->pending_tx_skb); + lp->pending_tx_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + } +} + +/* + * Enable Interrupts, Receive, and Transmit + */ +static void smc911x_enable(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned mask, cfg, cr; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + SMC_SET_MAC_ADDR(dev->dev_addr); + + /* Enable TX */ + cfg = SMC_GET_HW_CFG(); + cfg &= HW_CFG_TX_FIF_SZ_ | 0xFFF; + cfg |= HW_CFG_SF_; + SMC_SET_HW_CFG(cfg); + SMC_SET_FIFO_TDA(0xFF); + /* Update TX stats on every 64 packets received or every 1 sec */ + SMC_SET_FIFO_TSL(64); + SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); + + spin_lock_irqsave(&lp->lock, flags); + SMC_GET_MAC_CR(cr); + cr |= MAC_CR_TXEN_ | MAC_CR_HBDIS_; + SMC_SET_MAC_CR(cr); + SMC_SET_TX_CFG(TX_CFG_TX_ON_); + spin_unlock_irqrestore(&lp->lock, flags); + + /* Add 2 byte padding to start of packets */ + SMC_SET_RX_CFG((2<<8) & RX_CFG_RXDOFF_); + + /* Turn on receiver and enable RX */ + if (cr & MAC_CR_RXEN_) + DBG(SMC_DEBUG_RX, "%s: Receiver already enabled\n", dev->name); + + spin_lock_irqsave(&lp->lock, flags); + SMC_SET_MAC_CR( cr | MAC_CR_RXEN_ ); + spin_unlock_irqrestore(&lp->lock, flags); + + /* Interrupt on every received packet */ + SMC_SET_FIFO_RSA(0x01); + SMC_SET_FIFO_RSL(0x00); + + /* now, enable interrupts */ + mask = INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_ | INT_EN_RSFL_EN_ | + INT_EN_GPT_INT_EN_ | INT_EN_RXDFH_INT_EN_ | INT_EN_RXE_EN_ | + INT_EN_PHY_INT_EN_; + if (IS_REV_A(lp->revision)) + mask|=INT_EN_RDFL_EN_; + else { + mask|=INT_EN_RDFO_EN_; + } + SMC_ENABLE_INT(mask); +} + +/* + * this puts the device in an inactive state + */ +static void smc911x_shutdown(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned cr; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __FUNCTION__); + + /* Disable IRQ's */ + SMC_SET_INT_EN(0); + + /* Turn of Rx and TX */ + spin_lock_irqsave(&lp->lock, flags); + SMC_GET_MAC_CR(cr); + cr &= ~(MAC_CR_TXEN_ | MAC_CR_RXEN_ | MAC_CR_HBDIS_); + SMC_SET_MAC_CR(cr); + SMC_SET_TX_CFG(TX_CFG_STOP_TX_); + spin_unlock_irqrestore(&lp->lock, flags); +} + +static inline void smc911x_drop_pkt(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int fifo_count, timeout, reg; + + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __FUNCTION__); + fifo_count = SMC_GET_RX_FIFO_INF() & 0xFFFF; + if (fifo_count <= 4) { + /* Manually dump the packet data */ + while (fifo_count--) + SMC_GET_RX_FIFO(); + } else { + /* Fast forward through the bad packet */ + SMC_SET_RX_DP_CTRL(RX_DP_CTRL_FFWD_BUSY_); + timeout=50; + do { + udelay(10); + reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_; + } while ( timeout-- && reg); + if (timeout == 0) { + PRINTK("%s: timeout waiting for RX fast forward\n", dev->name); + } + } +} + +/* + * This is the procedure to handle the receipt of a packet. + * It should be called after checking for packet presence in + * the RX status FIFO. It must be called with the spin lock + * already held. + */ +static inline void smc911x_rcv(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int pkt_len, status; + struct sk_buff *skb; + unsigned char *data; + + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", + dev->name, __FUNCTION__); + status = SMC_GET_RX_STS_FIFO(); + DBG(SMC_DEBUG_RX, "%s: Rx pkt len %d status 0x%08x \n", + dev->name, (status & 0x3fff0000) >> 16, status & 0xc000ffff); + pkt_len = (status & RX_STS_PKT_LEN_) >> 16; + if (status & RX_STS_ES_) { + /* Deal with a bad packet */ + lp->stats.rx_errors++; + if (status & RX_STS_CRC_ERR_) + lp->stats.rx_crc_errors++; + else { + if (status & RX_STS_LEN_ERR_) + lp->stats.rx_length_errors++; + if (status & RX_STS_MCAST_) + lp->stats.multicast++; + } + /* Remove the bad packet data from the RX FIFO */ + smc911x_drop_pkt(dev); + } else { + /* Receive a valid packet */ + /* Alloc a buffer with extra room for DMA alignment */ + skb=dev_alloc_skb(pkt_len+32); + if (unlikely(skb == NULL)) { + PRINTK( "%s: Low memory, rcvd packet dropped.\n", + dev->name); + lp->stats.rx_dropped++; + smc911x_drop_pkt(dev); + return; + } + /* Align IP header to 32 bits + * Note that the device is configured to add a 2 + * byte padding to the packet start, so we really + * want to write to the orignal data pointer */ + data = skb->data; + skb_reserve(skb, 2); + skb_put(skb,pkt_len-4); +#ifdef SMC_USE_DMA + { + unsigned int fifo; + /* Lower the FIFO threshold if possible */ + fifo = SMC_GET_FIFO_INT(); + if (fifo & 0xFF) fifo--; + DBG(SMC_DEBUG_RX, "%s: Setting RX stat FIFO threshold to %d\n", + dev->name, fifo & 0xff); + SMC_SET_FIFO_INT(fifo); + /* Setup RX DMA */ + SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN16_ | ((2<<8) & RX_CFG_RXDOFF_)); + lp->rxdma_active = 1; + lp->current_rx_skb = skb; + SMC_PULL_DATA(data, (pkt_len+2+15) & ~15); + /* Packet processing deferred to DMA RX interrupt */ + } +#else + SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_)); + SMC_PULL_DATA(data, pkt_len+2+3); + + DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name,); + PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64); + dev->last_rx = jiffies; + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + lp->stats.rx_packets++; + lp->stats.rx_bytes += pkt_len-4; +#endif + } +} + +/* + * This is called to actually send a packet to the chip. + */ +static void smc911x_hardware_send_pkt(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + struct sk_buff *skb; + unsigned int cmdA, cmdB, len; + unsigned char *buf; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __FUNCTION__); + BUG_ON(lp->pending_tx_skb == NULL); + + skb = lp->pending_tx_skb; + lp->pending_tx_skb = NULL; + + /* cmdA {25:24] data alignment [20:16] start offset [10:0] buffer length */ + /* cmdB {31:16] pkt tag [10:0] length */ +#ifdef SMC_USE_DMA + /* 16 byte buffer alignment mode */ + buf = (char*)((u32)(skb->data) & ~0xF); + len = (skb->len + 0xF + ((u32)skb->data & 0xF)) & ~0xF; + cmdA = (1<<24) | (((u32)skb->data & 0xF)<<16) | + TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ | + skb->len; +#else + buf = (char*)((u32)skb->data & ~0x3); + len = (skb->len + 3 + ((u32)skb->data & 3)) & ~0x3; + cmdA = (((u32)skb->data & 0x3) << 16) | + TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ | + skb->len; +#endif + /* tag is packet length so we can use this in stats update later */ + cmdB = (skb->len << 16) | (skb->len & 0x7FF); + + DBG(SMC_DEBUG_TX, "%s: TX PKT LENGTH 0x%04x (%d) BUF 0x%p CMDA 0x%08x CMDB 0x%08x\n", + dev->name, len, len, buf, cmdA, cmdB); + SMC_SET_TX_FIFO(cmdA); + SMC_SET_TX_FIFO(cmdB); + + DBG(SMC_DEBUG_PKTS, "%s: Transmitted packet\n", dev->name); + PRINT_PKT(buf, len <= 64 ? len : 64); + + /* Send pkt via PIO or DMA */ +#ifdef SMC_USE_DMA + lp->current_tx_skb = skb; + SMC_PUSH_DATA(buf, len); + /* DMA complete IRQ will free buffer and set jiffies */ +#else + SMC_PUSH_DATA(buf, len); + dev->trans_start = jiffies; + dev_kfree_skb(skb); +#endif + spin_lock_irqsave(&lp->lock, flags); + if (!lp->tx_throttle) { + netif_wake_queue(dev); + } + spin_unlock_irqrestore(&lp->lock, flags); + SMC_ENABLE_INT(INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_); +} + +/* + * Since I am not sure if I will have enough room in the chip's ram + * to store the packet, I call this routine which either sends it + * now, or set the card to generates an interrupt when ready + * for the packet. + */ +static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int free; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", + dev->name, __FUNCTION__); + + BUG_ON(lp->pending_tx_skb != NULL); + + free = SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TDFREE_; + DBG(SMC_DEBUG_TX, "%s: TX free space %d\n", dev->name, free); + + /* Turn off the flow when running out of space in FIFO */ + if (free <= SMC911X_TX_FIFO_LOW_THRESHOLD) { + DBG(SMC_DEBUG_TX, "%s: Disabling data flow due to low FIFO space (%d)\n", + dev->name, free); + spin_lock_irqsave(&lp->lock, flags); + /* Reenable when at least 1 packet of size MTU present */ + SMC_SET_FIFO_TDA((SMC911X_TX_FIFO_LOW_THRESHOLD)/64); + lp->tx_throttle = 1; + netif_stop_queue(dev); + spin_unlock_irqrestore(&lp->lock, flags); + } + + /* Drop packets when we run out of space in TX FIFO + * Account for overhead required for: + * + * Tx command words 8 bytes + * Start offset 15 bytes + * End padding 15 bytes + */ + if (unlikely(free < (skb->len + 8 + 15 + 15))) { + printk("%s: No Tx free space %d < %d\n", + dev->name, free, skb->len); + lp->pending_tx_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; + } + +#ifdef SMC_USE_DMA + { + /* If the DMA is already running then defer this packet Tx until + * the DMA IRQ starts it + */ + spin_lock_irqsave(&lp->lock, flags); + if (lp->txdma_active) { + DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Tx DMA running, deferring packet\n", dev->name); + lp->pending_tx_skb = skb; + netif_stop_queue(dev); + spin_unlock_irqrestore(&lp->lock, flags); + return 0; + } else { + DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Activating Tx DMA\n", dev->name); + lp->txdma_active = 1; + } + spin_unlock_irqrestore(&lp->lock, flags); + } +#endif + lp->pending_tx_skb = skb; + smc911x_hardware_send_pkt(dev); + + return 0; +} + +/* + * This handles a TX status interrupt, which is only called when: + * - a TX error occurred, or + * - TX of a packet completed. + */ +static void smc911x_tx(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned int tx_status; + + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", + dev->name, __FUNCTION__); + + /* Collect the TX status */ + while (((SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16) != 0) { + DBG(SMC_DEBUG_TX, "%s: Tx stat FIFO used 0x%04x\n", + dev->name, + (SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16); + tx_status = SMC_GET_TX_STS_FIFO(); + lp->stats.tx_packets++; + lp->stats.tx_bytes+=tx_status>>16; + DBG(SMC_DEBUG_TX, "%s: Tx FIFO tag 0x%04x status 0x%04x\n", + dev->name, (tx_status & 0xffff0000) >> 16, + tx_status & 0x0000ffff); + /* count Tx errors, but ignore lost carrier errors when in + * full-duplex mode */ + if ((tx_status & TX_STS_ES_) && !(lp->ctl_rfduplx && + !(tx_status & 0x00000306))) { + lp->stats.tx_errors++; + } + if (tx_status & TX_STS_MANY_COLL_) { + lp->stats.collisions+=16; + lp->stats.tx_aborted_errors++; + } else { + lp->stats.collisions+=(tx_status & TX_STS_COLL_CNT_) >> 3; + } + /* carrier error only has meaning for half-duplex communication */ + if ((tx_status & (TX_STS_LOC_ | TX_STS_NO_CARR_)) && + !lp->ctl_rfduplx) { + lp->stats.tx_carrier_errors++; + } + if (tx_status & TX_STS_LATE_COLL_) { + lp->stats.collisions++; + lp->stats.tx_aborted_errors++; + } + } +} + + +/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/ +/* + * Reads a register from the MII Management serial interface + */ + +static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int phydata; + + SMC_GET_MII(phyreg, phyaddr, phydata); + + DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%02x, phydata=0x%04x\n", + __FUNCTION__, phyaddr, phyreg, phydata); + return phydata; +} + + +/* + * Writes a register to the MII Management serial interface + */ +static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg, + int phydata) +{ + unsigned long ioaddr = dev->base_addr; + + DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", + __FUNCTION__, phyaddr, phyreg, phydata); + + SMC_SET_MII(phyreg, phyaddr, phydata); +} + +/* + * Finds and reports the PHY address (115 and 117 have external + * PHY interface 118 has internal only + */ +static void smc911x_phy_detect(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + int phyaddr; + unsigned int cfg, id1, id2; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + lp->phy_type = 0; + + /* + * Scan all 32 PHY addresses if necessary, starting at + * PHY#1 to PHY#31, and then PHY#0 last. + */ + switch(lp->version) { + case 0x115: + case 0x117: + cfg = SMC_GET_HW_CFG(); + if (cfg & HW_CFG_EXT_PHY_DET_) { + cfg &= ~HW_CFG_PHY_CLK_SEL_; + cfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_; + SMC_SET_HW_CFG(cfg); + udelay(10); /* Wait for clocks to stop */ + + cfg |= HW_CFG_EXT_PHY_EN_; + SMC_SET_HW_CFG(cfg); + udelay(10); /* Wait for clocks to stop */ + + cfg &= ~HW_CFG_PHY_CLK_SEL_; + cfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_; + SMC_SET_HW_CFG(cfg); + udelay(10); /* Wait for clocks to stop */ + + cfg |= HW_CFG_SMI_SEL_; + SMC_SET_HW_CFG(cfg); + + for (phyaddr = 1; phyaddr < 32; ++phyaddr) { + + /* Read the PHY identifiers */ + SMC_GET_PHY_ID1(phyaddr & 31, id1); + SMC_GET_PHY_ID2(phyaddr & 31, id2); + + /* Make sure it is a valid identifier */ + if (id1 != 0x0000 && id1 != 0xffff && + id1 != 0x8000 && id2 != 0x0000 && + id2 != 0xffff && id2 != 0x8000) { + /* Save the PHY's address */ + lp->mii.phy_id = phyaddr & 31; + lp->phy_type = id1 << 16 | id2; + break; + } + } + } + default: + /* Internal media only */ + SMC_GET_PHY_ID1(1, id1); + SMC_GET_PHY_ID2(1, id2); + /* Save the PHY's address */ + lp->mii.phy_id = 1; + lp->phy_type = id1 << 16 | id2; + } + + DBG(SMC_DEBUG_MISC, "%s: phy_id1=0x%x, phy_id2=0x%x phyaddr=0x%d\n", + dev->name, id1, id2, lp->mii.phy_id); +} + +/* + * Sets the PHY to a configuration as determined by the user. + * Called with spin_lock held. + */ +static int smc911x_phy_fixed(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + int bmcr; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + /* Enter Link Disable state */ + SMC_GET_PHY_BMCR(phyaddr, bmcr); + bmcr |= BMCR_PDOWN; + SMC_SET_PHY_BMCR(phyaddr, bmcr); + + /* + * Set our fixed capabilities + * Disable auto-negotiation + */ + bmcr &= ~BMCR_ANENABLE; + if (lp->ctl_rfduplx) + bmcr |= BMCR_FULLDPLX; + + if (lp->ctl_rspeed == 100) + bmcr |= BMCR_SPEED100; + + /* Write our capabilities to the phy control register */ + SMC_SET_PHY_BMCR(phyaddr, bmcr); + + /* Re-Configure the Receive/Phy Control register */ + bmcr &= ~BMCR_PDOWN; + SMC_SET_PHY_BMCR(phyaddr, bmcr); + + return 1; +} + +/* + * smc911x_phy_reset - reset the phy + * @dev: net device + * @phy: phy address + * + * Issue a software reset for the specified PHY and + * wait up to 100ms for the reset to complete. We should + * not access the PHY for 50ms after issuing the reset. + * + * The time to wait appears to be dependent on the PHY. + * + */ +static int smc911x_phy_reset(struct net_device *dev, int phy) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int timeout; + unsigned long flags; + unsigned int reg; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__); + + spin_lock_irqsave(&lp->lock, flags); + reg = SMC_GET_PMT_CTRL(); + reg &= ~0xfffff030; + reg |= PMT_CTRL_PHY_RST_; + SMC_SET_PMT_CTRL(reg); + spin_unlock_irqrestore(&lp->lock, flags); + for (timeout = 2; timeout; timeout--) { + msleep(50); + spin_lock_irqsave(&lp->lock, flags); + reg = SMC_GET_PMT_CTRL(); + spin_unlock_irqrestore(&lp->lock, flags); + if (!(reg & PMT_CTRL_PHY_RST_)) { + /* extra delay required because the phy may + * not be completed with its reset + * when PHY_BCR_RESET_ is cleared. 256us + * should suffice, but use 500us to be safe + */ + udelay(500); + break; + } + } + + return reg & PMT_CTRL_PHY_RST_; +} + +/* + * smc911x_phy_powerdown - powerdown phy + * @dev: net device + * @phy: phy address + * + * Power down the specified PHY + */ +static void smc911x_phy_powerdown(struct net_device *dev, int phy) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int bmcr; + + /* Enter Link Disable state */ + SMC_GET_PHY_BMCR(phy, bmcr); + bmcr |= BMCR_PDOWN; + SMC_SET_PHY_BMCR(phy, bmcr); +} + +/* + * smc911x_phy_check_media - check the media status and adjust BMCR + * @dev: net device + * @init: set true for initialisation + * + * Select duplex mode depending on negotiation state. This + * also updates our carrier state. + */ +static void smc911x_phy_check_media(struct net_device *dev, int init) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + unsigned int bmcr, cr; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) { + /* duplex state has changed */ + SMC_GET_PHY_BMCR(phyaddr, bmcr); + SMC_GET_MAC_CR(cr); + if (lp->mii.full_duplex) { + DBG(SMC_DEBUG_MISC, "%s: Configuring for full-duplex mode\n", dev->name); + bmcr |= BMCR_FULLDPLX; + cr |= MAC_CR_RCVOWN_; + } else { + DBG(SMC_DEBUG_MISC, "%s: Configuring for half-duplex mode\n", dev->name); + bmcr &= ~BMCR_FULLDPLX; + cr &= ~MAC_CR_RCVOWN_; + } + SMC_SET_PHY_BMCR(phyaddr, bmcr); + SMC_SET_MAC_CR(cr); + } +} + +/* + * Configures the specified PHY through the MII management interface + * using Autonegotiation. + * Calls smc911x_phy_fixed() if the user has requested a certain config. + * If RPC ANEG bit is set, the media selection is dependent purely on + * the selection by the MII (either in the MII BMCR reg or the result + * of autonegotiation.) If the RPC ANEG bit is cleared, the selection + * is controlled by the RPC SPEED and RPC DPLX bits. + */ +static void smc911x_phy_configure(void *data) +{ + struct net_device *dev = data; + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + int my_phy_caps; /* My PHY capabilities */ + int my_ad_caps; /* My Advertised capabilities */ + int status; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__); + + /* + * We should not be called if phy_type is zero. + */ + if (lp->phy_type == 0) + goto smc911x_phy_configure_exit; + + if (smc911x_phy_reset(dev, phyaddr)) { + printk("%s: PHY reset timed out\n", dev->name); + goto smc911x_phy_configure_exit; + } + spin_lock_irqsave(&lp->lock, flags); + + /* + * Enable PHY Interrupts (for register 18) + * Interrupts listed here are enabled + */ + SMC_SET_PHY_INT_MASK(phyaddr, PHY_INT_MASK_ENERGY_ON_ | + PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_REMOTE_FAULT_ | + PHY_INT_MASK_LINK_DOWN_); + + /* If the user requested no auto neg, then go set his request */ + if (lp->mii.force_media) { + smc911x_phy_fixed(dev); + goto smc911x_phy_configure_exit; + } + + /* Copy our capabilities from MII_BMSR to MII_ADVERTISE */ + SMC_GET_PHY_BMSR(phyaddr, my_phy_caps); + if (!(my_phy_caps & BMSR_ANEGCAPABLE)) { + printk(KERN_INFO "Auto negotiation NOT supported\n"); + smc911x_phy_fixed(dev); + goto smc911x_phy_configure_exit; + } + + /* CSMA capable w/ both pauses */ + my_ad_caps = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + + if (my_phy_caps & BMSR_100BASE4) + my_ad_caps |= ADVERTISE_100BASE4; + if (my_phy_caps & BMSR_100FULL) + my_ad_caps |= ADVERTISE_100FULL; + if (my_phy_caps & BMSR_100HALF) + my_ad_caps |= ADVERTISE_100HALF; + if (my_phy_caps & BMSR_10FULL) + my_ad_caps |= ADVERTISE_10FULL; + if (my_phy_caps & BMSR_10HALF) + my_ad_caps |= ADVERTISE_10HALF; + + /* Disable capabilities not selected by our user */ + if (lp->ctl_rspeed != 100) + my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF); + + if (!lp->ctl_rfduplx) + my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL); + + /* Update our Auto-Neg Advertisement Register */ + SMC_SET_PHY_MII_ADV(phyaddr, my_ad_caps); + lp->mii.advertising = my_ad_caps; + + /* + * Read the register back. Without this, it appears that when + * auto-negotiation is restarted, sometimes it isn't ready and + * the link does not come up. + */ + udelay(10); + SMC_GET_PHY_MII_ADV(phyaddr, status); + + DBG(SMC_DEBUG_MISC, "%s: phy caps=0x%04x\n", dev->name, my_phy_caps); + DBG(SMC_DEBUG_MISC, "%s: phy advertised caps=0x%04x\n", dev->name, my_ad_caps); + + /* Restart auto-negotiation process in order to advertise my caps */ + SMC_SET_PHY_BMCR(phyaddr, BMCR_ANENABLE | BMCR_ANRESTART); + + smc911x_phy_check_media(dev, 1); + +smc911x_phy_configure_exit: + spin_unlock_irqrestore(&lp->lock, flags); + lp->work_pending = 0; +} + +/* + * smc911x_phy_interrupt + * + * Purpose: Handle interrupts relating to PHY register 18. This is + * called from the "hard" interrupt handler under our private spinlock. + */ +static void smc911x_phy_interrupt(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + int status; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + if (lp->phy_type == 0) + return; + + smc911x_phy_check_media(dev, 0); + /* read to clear status bits */ + SMC_GET_PHY_INT_SRC(phyaddr,status); + DBG(SMC_DEBUG_MISC, "%s: PHY interrupt status 0x%04x\n", + dev->name, status & 0xffff); + DBG(SMC_DEBUG_MISC, "%s: AFC_CFG 0x%08x\n", + dev->name, SMC_GET_AFC_CFG()); +} + +/*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/ + +/* + * This is the main routine of the driver, to handle the device when + * it needs some attention. + */ +static irqreturn_t smc911x_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned int status, mask, timeout; + unsigned int rx_overrun=0, cr, pkts; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + spin_lock_irqsave(&lp->lock, flags); + + /* Spurious interrupt check */ + if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) != + (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) { + return IRQ_NONE; + } + + mask = SMC_GET_INT_EN(); + SMC_SET_INT_EN(0); + + /* set a timeout value, so I don't stay here forever */ + timeout = 8; + + + do { + status = SMC_GET_INT(); + + DBG(SMC_DEBUG_MISC, "%s: INT 0x%08x MASK 0x%08x OUTSIDE MASK 0x%08x\n", + dev->name, status, mask, status & ~mask); + + status &= mask; + if (!status) + break; + + /* Handle SW interrupt condition */ + if (status & INT_STS_SW_INT_) { + SMC_ACK_INT(INT_STS_SW_INT_); + mask &= ~INT_EN_SW_INT_EN_; + } + /* Handle various error conditions */ + if (status & INT_STS_RXE_) { + SMC_ACK_INT(INT_STS_RXE_); + lp->stats.rx_errors++; + } + if (status & INT_STS_RXDFH_INT_) { + SMC_ACK_INT(INT_STS_RXDFH_INT_); + lp->stats.rx_dropped+=SMC_GET_RX_DROP(); + } + /* Undocumented interrupt-what is the right thing to do here? */ + if (status & INT_STS_RXDF_INT_) { + SMC_ACK_INT(INT_STS_RXDF_INT_); + } + + /* Rx Data FIFO exceeds set level */ + if (status & INT_STS_RDFL_) { + if (IS_REV_A(lp->revision)) { + rx_overrun=1; + SMC_GET_MAC_CR(cr); + cr &= ~MAC_CR_RXEN_; + SMC_SET_MAC_CR(cr); + DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name); + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + } + SMC_ACK_INT(INT_STS_RDFL_); + } + if (status & INT_STS_RDFO_) { + if (!IS_REV_A(lp->revision)) { + SMC_GET_MAC_CR(cr); + cr &= ~MAC_CR_RXEN_; + SMC_SET_MAC_CR(cr); + rx_overrun=1; + DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name); + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + } + SMC_ACK_INT(INT_STS_RDFO_); + } + /* Handle receive condition */ + if ((status & INT_STS_RSFL_) || rx_overrun) { + unsigned int fifo; + DBG(SMC_DEBUG_RX, "%s: RX irq\n", dev->name); + fifo = SMC_GET_RX_FIFO_INF(); + pkts = (fifo & RX_FIFO_INF_RXSUSED_) >> 16; + DBG(SMC_DEBUG_RX, "%s: Rx FIFO pkts %d, bytes %d\n", + dev->name, pkts, fifo & 0xFFFF ); + if (pkts != 0) { +#ifdef SMC_USE_DMA + unsigned int fifo; + if (lp->rxdma_active){ + DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, + "%s: RX DMA active\n", dev->name); + /* The DMA is already running so up the IRQ threshold */ + fifo = SMC_GET_FIFO_INT() & ~0xFF; + fifo |= pkts & 0xFF; + DBG(SMC_DEBUG_RX, + "%s: Setting RX stat FIFO threshold to %d\n", + dev->name, fifo & 0xff); + SMC_SET_FIFO_INT(fifo); + } else +#endif + smc911x_rcv(dev); + } + SMC_ACK_INT(INT_STS_RSFL_); + } + /* Handle transmit FIFO available */ + if (status & INT_STS_TDFA_) { + DBG(SMC_DEBUG_TX, "%s: TX data FIFO space available irq\n", dev->name); + SMC_SET_FIFO_TDA(0xFF); + lp->tx_throttle = 0; +#ifdef SMC_USE_DMA + if (!lp->txdma_active) +#endif + netif_wake_queue(dev); + SMC_ACK_INT(INT_STS_TDFA_); + } + /* Handle transmit done condition */ +#if 1 + if (status & (INT_STS_TSFL_ | INT_STS_GPT_INT_)) { + DBG(SMC_DEBUG_TX | SMC_DEBUG_MISC, + "%s: Tx stat FIFO limit (%d) /GPT irq\n", + dev->name, (SMC_GET_FIFO_INT() & 0x00ff0000) >> 16); + smc911x_tx(dev); + SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); + SMC_ACK_INT(INT_STS_TSFL_); + SMC_ACK_INT(INT_STS_TSFL_ | INT_STS_GPT_INT_); + } +#else + if (status & INT_STS_TSFL_) { + DBG(SMC_DEBUG_TX, "%s: TX status FIFO limit (%d) irq \n", dev->name, ); + smc911x_tx(dev); + SMC_ACK_INT(INT_STS_TSFL_); + } + + if (status & INT_STS_GPT_INT_) { + DBG(SMC_DEBUG_RX, "%s: IRQ_CFG 0x%08x FIFO_INT 0x%08x RX_CFG 0x%08x\n", + dev->name, + SMC_GET_IRQ_CFG(), + SMC_GET_FIFO_INT(), + SMC_GET_RX_CFG()); + DBG(SMC_DEBUG_RX, "%s: Rx Stat FIFO Used 0x%02x " + "Data FIFO Used 0x%04x Stat FIFO 0x%08x\n", + dev->name, + (SMC_GET_RX_FIFO_INF() & 0x00ff0000) >> 16, + SMC_GET_RX_FIFO_INF() & 0xffff, + SMC_GET_RX_STS_FIFO_PEEK()); + SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); + SMC_ACK_INT(INT_STS_GPT_INT_); + } +#endif + + /* Handle PHY interupt condition */ + if (status & INT_STS_PHY_INT_) { + DBG(SMC_DEBUG_MISC, "%s: PHY irq\n", dev->name); + smc911x_phy_interrupt(dev); + SMC_ACK_INT(INT_STS_PHY_INT_); + } + } while (--timeout); + + /* restore mask state */ + SMC_SET_INT_EN(mask); + + DBG(SMC_DEBUG_MISC, "%s: Interrupt done (%d loops)\n", + dev->name, 8-timeout); + + spin_unlock_irqrestore(&lp->lock, flags); + + DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout); + + return IRQ_HANDLED; +} + +#ifdef SMC_USE_DMA +static void +smc911x_tx_dma_irq(int dma, void *data, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *)data; + struct smc911x_local *lp = netdev_priv(dev); + struct sk_buff *skb = lp->current_tx_skb; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: TX DMA irq handler\n", dev->name); + /* Clear the DMA interrupt sources */ + SMC_DMA_ACK_IRQ(dev, dma); + BUG_ON(skb == NULL); + dma_unmap_single(NULL, tx_dmabuf, tx_dmalen, DMA_TO_DEVICE); + dev->trans_start = jiffies; + dev_kfree_skb_irq(skb); + lp->current_tx_skb = NULL; + if (lp->pending_tx_skb != NULL) + smc911x_hardware_send_pkt(dev); + else { + DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, + "%s: No pending Tx packets. DMA disabled\n", dev->name); + spin_lock_irqsave(&lp->lock, flags); + lp->txdma_active = 0; + if (!lp->tx_throttle) { + netif_wake_queue(dev); + } + spin_unlock_irqrestore(&lp->lock, flags); + } + + DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, + "%s: TX DMA irq completed\n", dev->name); +} +static void +smc911x_rx_dma_irq(int dma, void *data, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *)data; + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + struct sk_buff *skb = lp->current_rx_skb; + unsigned long flags; + unsigned int pkts; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, "%s: RX DMA irq handler\n", dev->name); + /* Clear the DMA interrupt sources */ + SMC_DMA_ACK_IRQ(dev, dma); + dma_unmap_single(NULL, rx_dmabuf, rx_dmalen, DMA_FROM_DEVICE); + BUG_ON(skb == NULL); + lp->current_rx_skb = NULL; + PRINT_PKT(skb->data, skb->len); + dev->last_rx = jiffies; + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + lp->stats.rx_packets++; + lp->stats.rx_bytes += skb->len; + + spin_lock_irqsave(&lp->lock, flags); + pkts = (SMC_GET_RX_FIFO_INF() & RX_FIFO_INF_RXSUSED_) >> 16; + if (pkts != 0) { + smc911x_rcv(dev); + }else { + lp->rxdma_active = 0; + } + spin_unlock_irqrestore(&lp->lock, flags); + DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, + "%s: RX DMA irq completed. DMA RX FIFO PKTS %d\n", + dev->name, pkts); +} +#endif /* SMC_USE_DMA */ + +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling receive - used by netconsole and other diagnostic tools + * to allow network i/o with interrupts disabled. + */ +static void smc911x_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + smc911x_interrupt(dev->irq, dev, NULL); + enable_irq(dev->irq); +} +#endif + +/* Our watchdog timed out. Called by the networking layer */ +static void smc911x_timeout(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int status, mask; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + spin_lock_irqsave(&lp->lock, flags); + status = SMC_GET_INT(); + mask = SMC_GET_INT_EN(); + spin_unlock_irqrestore(&lp->lock, flags); + DBG(SMC_DEBUG_MISC, "%s: INT 0x%02x MASK 0x%02x \n", + dev->name, status, mask); + + /* Dump the current TX FIFO contents and restart */ + mask = SMC_GET_TX_CFG(); + SMC_SET_TX_CFG(mask | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_); + /* + * Reconfiguring the PHY doesn't seem like a bad idea here, but + * smc911x_phy_configure() calls msleep() which calls schedule_timeout() + * which calls schedule(). Hence we use a work queue. + */ + if (lp->phy_type != 0) { + if (schedule_work(&lp->phy_configure)) { + lp->work_pending = 1; + } + } + + /* We can accept TX packets again */ + dev->trans_start = jiffies; + netif_wake_queue(dev); +} + +/* + * This routine will, depending on the values passed to it, + * either make it accept multicast packets, go into + * promiscuous mode (for TCPDUMP and cousins) or accept + * a select set of multicast packets + */ +static void smc911x_set_multicast_list(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int multicast_table[2]; + unsigned int mcr, update_multicast = 0; + unsigned long flags; + /* table for flipping the order of 5 bits */ + static const unsigned char invert5[] = + {0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C, + 0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E, + 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0D, 0x1D, + 0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F}; + + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + spin_lock_irqsave(&lp->lock, flags); + SMC_GET_MAC_CR(mcr); + spin_unlock_irqrestore(&lp->lock, flags); + + if (dev->flags & IFF_PROMISC) { + + DBG(SMC_DEBUG_MISC, "%s: RCR_PRMS\n", dev->name); + mcr |= MAC_CR_PRMS_; + } + /* + * Here, I am setting this to accept all multicast packets. + * I don't need to zero the multicast table, because the flag is + * checked before the table is + */ + else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) { + DBG(SMC_DEBUG_MISC, "%s: RCR_ALMUL\n", dev->name); + mcr |= MAC_CR_MCPAS_; + } + + /* + * This sets the internal hardware table to filter out unwanted + * multicast packets before they take up memory. + * + * The SMC chip uses a hash table where the high 6 bits of the CRC of + * address are the offset into the table. If that bit is 1, then the + * multicast packet is accepted. Otherwise, it's dropped silently. + * + * To use the 6 bits as an offset into the table, the high 1 bit is + * the number of the 32 bit register, while the low 5 bits are the bit + * within that register. + */ + else if (dev->mc_count) { + int i; + struct dev_mc_list *cur_addr; + + /* Set the Hash perfec mode */ + mcr |= MAC_CR_HPFILT_; + + /* start with a table of all zeros: reject all */ + memset(multicast_table, 0, sizeof(multicast_table)); + + cur_addr = dev->mc_list; + for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) { + int position; + + /* do we have a pointer here? */ + if (!cur_addr) + break; + /* make sure this is a multicast address - + shouldn't this be a given if we have it here ? */ + if (!(*cur_addr->dmi_addr & 1)) + continue; + + /* only use the low order bits */ + position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f; + + /* do some messy swapping to put the bit in the right spot */ + multicast_table[invert5[position&0x1F]&0x1] |= + (1<>1)&0x1F]); + } + + /* be sure I get rid of flags I might have set */ + mcr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_); + + /* now, the table can be loaded into the chipset */ + update_multicast = 1; + } else { + DBG(SMC_DEBUG_MISC, "%s: ~(MAC_CR_PRMS_|MAC_CR_MCPAS_)\n", + dev->name); + mcr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_); + + /* + * since I'm disabling all multicast entirely, I need to + * clear the multicast list + */ + memset(multicast_table, 0, sizeof(multicast_table)); + update_multicast = 1; + } + + spin_lock_irqsave(&lp->lock, flags); + SMC_SET_MAC_CR(mcr); + if (update_multicast) { + DBG(SMC_DEBUG_MISC, + "%s: update mcast hash table 0x%08x 0x%08x\n", + dev->name, multicast_table[0], multicast_table[1]); + SMC_SET_HASHL(multicast_table[0]); + SMC_SET_HASHH(multicast_table[1]); + } + spin_unlock_irqrestore(&lp->lock, flags); +} + + +/* + * Open and Initialize the board + * + * Set up everything, reset the card, etc.. + */ +static int +smc911x_open(struct net_device *dev) +{ + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + /* + * Check that the address is valid. If its not, refuse + * to bring the device up. The user must specify an + * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx + */ + if (!is_valid_ether_addr(dev->dev_addr)) { + PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__); + return -EINVAL; + } + + /* reset the hardware */ + smc911x_reset(dev); + + /* Configure the PHY, initialize the link state */ + smc911x_phy_configure(dev); + + /* Turn on Tx + Rx */ + smc911x_enable(dev); + + netif_start_queue(dev); + + return 0; +} + +/* + * smc911x_close + * + * this makes the board clean up everything that it can + * and not talk to the outside world. Caused by + * an 'ifconfig ethX down' + */ +static int smc911x_close(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + netif_stop_queue(dev); + netif_carrier_off(dev); + + /* clear everything */ + smc911x_shutdown(dev); + + if (lp->phy_type != 0) { + /* We need to ensure that no calls to + * smc911x_phy_configure are pending. + + * flush_scheduled_work() cannot be called because we + * are running with the netlink semaphore held (from + * devinet_ioctl()) and the pending work queue + * contains linkwatch_event() (scheduled by + * netif_carrier_off() above). linkwatch_event() also + * wants the netlink semaphore. + */ + while (lp->work_pending) + schedule(); + smc911x_phy_powerdown(dev, lp->mii.phy_id); + } + + if (lp->pending_tx_skb) { + dev_kfree_skb(lp->pending_tx_skb); + lp->pending_tx_skb = NULL; + } + + return 0; +} + +/* + * Get the current statistics. + * This may be called with the card open or closed. + */ +static struct net_device_stats *smc911x_query_statistics(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + + return &lp->stats; +} + +/* + * Ethtool support + */ +static int +smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int ret, status; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + cmd->maxtxpkt = 1; + cmd->maxrxpkt = 1; + + if (lp->phy_type != 0) { + spin_lock_irqsave(&lp->lock, flags); + ret = mii_ethtool_gset(&lp->mii, cmd); + spin_unlock_irqrestore(&lp->lock, flags); + } else { + cmd->supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_TP | SUPPORTED_AUI; + + if (lp->ctl_rspeed == 10) + cmd->speed = SPEED_10; + else if (lp->ctl_rspeed == 100) + cmd->speed = SPEED_100; + + cmd->autoneg = AUTONEG_DISABLE; + if (lp->mii.phy_id==1) + cmd->transceiver = XCVR_INTERNAL; + else + cmd->transceiver = XCVR_EXTERNAL; + cmd->port = 0; + SMC_GET_PHY_SPECIAL(lp->mii.phy_id, status); + cmd->duplex = + (status & (PHY_SPECIAL_SPD_10FULL_ | PHY_SPECIAL_SPD_100FULL_)) ? + DUPLEX_FULL : DUPLEX_HALF; + ret = 0; + } + + return ret; +} + +static int +smc911x_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct smc911x_local *lp = netdev_priv(dev); + int ret; + unsigned long flags; + + if (lp->phy_type != 0) { + spin_lock_irqsave(&lp->lock, flags); + ret = mii_ethtool_sset(&lp->mii, cmd); + spin_unlock_irqrestore(&lp->lock, flags); + } else { + if (cmd->autoneg != AUTONEG_DISABLE || + cmd->speed != SPEED_10 || + (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) || + (cmd->port != PORT_TP && cmd->port != PORT_AUI)) + return -EINVAL; + + lp->ctl_rfduplx = cmd->duplex == DUPLEX_FULL; + + ret = 0; + } + + return ret; +} + +static void +smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strncpy(info->driver, CARDNAME, sizeof(info->driver)); + strncpy(info->version, version, sizeof(info->version)); + strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info)); +} + +static int smc911x_ethtool_nwayreset(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + int ret = -EINVAL; + unsigned long flags; + + if (lp->phy_type != 0) { + spin_lock_irqsave(&lp->lock, flags); + ret = mii_nway_restart(&lp->mii); + spin_unlock_irqrestore(&lp->lock, flags); + } + + return ret; +} + +static u32 smc911x_ethtool_getmsglevel(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + return lp->msg_enable; +} + +static void smc911x_ethtool_setmsglevel(struct net_device *dev, u32 level) +{ + struct smc911x_local *lp = netdev_priv(dev); + lp->msg_enable = level; +} + +static int smc911x_ethtool_getregslen(struct net_device *dev) +{ + /* System regs + MAC regs + PHY regs */ + return (((E2P_CMD - ID_REV)/4 + 1) + + (WUCSR - MAC_CR)+1 + 32) * sizeof(u32); +} + +static void smc911x_ethtool_getregs(struct net_device *dev, + struct ethtool_regs* regs, void *buf) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned long flags; + u32 reg,i,j=0; + u32 *data = (u32*)buf; + + regs->version = lp->version; + for(i=ID_REV;i<=E2P_CMD;i+=4) { + data[j++] = SMC_inl(ioaddr,i); + } + for(i=MAC_CR;i<=WUCSR;i++) { + spin_lock_irqsave(&lp->lock, flags); + SMC_GET_MAC_CSR(i, reg); + spin_unlock_irqrestore(&lp->lock, flags); + data[j++] = reg; + } + for(i=0;i<=31;i++) { + spin_lock_irqsave(&lp->lock, flags); + SMC_GET_MII(i, lp->mii.phy_id, reg); + spin_unlock_irqrestore(&lp->lock, flags); + data[j++] = reg & 0xFFFF; + } +} + +static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int timeout; + int e2p_cmd; + + e2p_cmd = SMC_GET_E2P_CMD(); + for(timeout=10;(e2p_cmd & E2P_CMD_EPC_BUSY_) && timeout; timeout--) { + if (e2p_cmd & E2P_CMD_EPC_TIMEOUT_) { + PRINTK("%s: %s timeout waiting for EEPROM to respond\n", + dev->name, __FUNCTION__); + return -EFAULT; + } + mdelay(1); + e2p_cmd = SMC_GET_E2P_CMD(); + } + if (timeout == 0) { + PRINTK("%s: %s timeout waiting for EEPROM CMD not busy\n", + dev->name, __FUNCTION__); + return -ETIMEDOUT; + } + return 0; +} + +static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev, + int cmd, int addr) +{ + unsigned long ioaddr = dev->base_addr; + int ret; + + if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) + return ret; + SMC_SET_E2P_CMD(E2P_CMD_EPC_BUSY_ | + ((cmd) & (0x7<<28)) | + ((addr) & 0xFF)); + return 0; +} + +static inline int smc911x_ethtool_read_eeprom_byte(struct net_device *dev, + u8 *data) +{ + unsigned long ioaddr = dev->base_addr; + int ret; + + if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) + return ret; + *data = SMC_GET_E2P_DATA(); + return 0; +} + +static inline int smc911x_ethtool_write_eeprom_byte(struct net_device *dev, + u8 data) +{ + unsigned long ioaddr = dev->base_addr; + int ret; + + if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) + return ret; + SMC_SET_E2P_DATA(data); + return 0; +} + +static int smc911x_ethtool_geteeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + u8 eebuf[SMC911X_EEPROM_LEN]; + int i, ret; + + for(i=0;ioffset, eeprom->len); + return 0; +} + +static int smc911x_ethtool_seteeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + int i, ret; + + /* Enable erase */ + if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWEN_, 0 ))!=0) + return ret; + for(i=eeprom->offset;i<(eeprom->offset+eeprom->len);i++) { + /* erase byte */ + if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_ERASE_, i ))!=0) + return ret; + /* write byte */ + if ((ret=smc911x_ethtool_write_eeprom_byte(dev, *data))!=0) + return ret; + if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_WRITE_, i ))!=0) + return ret; + } + return 0; +} + +static int smc911x_ethtool_geteeprom_len(struct net_device *dev) +{ + return SMC911X_EEPROM_LEN; +} + +static struct ethtool_ops smc911x_ethtool_ops = { + .get_settings = smc911x_ethtool_getsettings, + .set_settings = smc911x_ethtool_setsettings, + .get_drvinfo = smc911x_ethtool_getdrvinfo, + .get_msglevel = smc911x_ethtool_getmsglevel, + .set_msglevel = smc911x_ethtool_setmsglevel, + .nway_reset = smc911x_ethtool_nwayreset, + .get_link = ethtool_op_get_link, + .get_regs_len = smc911x_ethtool_getregslen, + .get_regs = smc911x_ethtool_getregs, + .get_eeprom_len = smc911x_ethtool_geteeprom_len, + .get_eeprom = smc911x_ethtool_geteeprom, + .set_eeprom = smc911x_ethtool_seteeprom, +}; + +/* + * smc911x_findirq + * + * This routine has a simple purpose -- make the SMC chip generate an + * interrupt, so an auto-detect routine can detect it, and find the IRQ, + */ +static int __init smc911x_findirq(unsigned long ioaddr) +{ + int timeout = 20; + unsigned long cookie; + + DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + + cookie = probe_irq_on(); + + /* + * Force a SW interrupt + */ + + SMC_SET_INT_EN(INT_EN_SW_INT_EN_); + + /* + * Wait until positive that the interrupt has been generated + */ + do { + int int_status; + udelay(10); + int_status = SMC_GET_INT_EN(); + if (int_status & INT_EN_SW_INT_EN_) + break; /* got the interrupt */ + } while (--timeout); + + /* + * there is really nothing that I can do here if timeout fails, + * as autoirq_report will return a 0 anyway, which is what I + * want in this case. Plus, the clean up is needed in both + * cases. + */ + + /* and disable all interrupts again */ + SMC_SET_INT_EN(0); + + /* and return what I found */ + return probe_irq_off(cookie); +} + +/* + * Function: smc911x_probe(unsigned long ioaddr) + * + * Purpose: + * Tests to see if a given ioaddr points to an SMC911x chip. + * Returns a 0 on success + * + * Algorithm: + * (1) see if the endian word is OK + * (1) see if I recognize the chip ID in the appropriate register + * + * Here I do typical initialization tasks. + * + * o Initialize the structure if needed + * o print out my vanity message if not done so already + * o print out what type of hardware is detected + * o print out the ethernet address + * o find the IRQ + * o set up my private data + * o configure the dev structure with my subroutines + * o actually GRAB the irq. + * o GRAB the region + */ +static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) +{ + struct smc911x_local *lp = netdev_priv(dev); + int i, retval; + unsigned int val, chip_id, revision; + const char *version_string; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + /* First, see if the endian word is recognized */ + val = SMC_GET_BYTE_TEST(); + DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val); + if (val != 0x87654321) { + printk(KERN_ERR "Invalid chip endian 0x08%x\n",val); + retval = -ENODEV; + goto err_out; + } + + /* + * check if the revision register is something that I + * recognize. These might need to be added to later, + * as future revisions could be added. + */ + chip_id = SMC_GET_PN(); + DBG(SMC_DEBUG_MISC, "%s: id probe returned 0x%04x\n", CARDNAME, chip_id); + for(i=0;chip_ids[i].id != 0; i++) { + if (chip_ids[i].id == chip_id) break; + } + if (!chip_ids[i].id) { + printk(KERN_ERR "Unknown chip ID %04x\n", chip_id); + retval = -ENODEV; + goto err_out; + } + version_string = chip_ids[i].name; + + revision = SMC_GET_REV(); + DBG(SMC_DEBUG_MISC, "%s: revision = 0x%04x\n", CARDNAME, revision); + + /* At this point I'll assume that the chip is an SMC911x. */ + DBG(SMC_DEBUG_MISC, "%s: Found a %s\n", CARDNAME, chip_ids[i].name); + + /* Validate the TX FIFO size requested */ + if ((tx_fifo_kb < 2) || (tx_fifo_kb > 14)) { + printk(KERN_ERR "Invalid TX FIFO size requested %d\n", tx_fifo_kb); + retval = -EINVAL; + goto err_out; + } + + /* fill in some of the fields */ + dev->base_addr = ioaddr; + lp->version = chip_ids[i].id; + lp->revision = revision; + lp->tx_fifo_kb = tx_fifo_kb; + /* Reverse calculate the RX FIFO size from the TX */ + lp->tx_fifo_size=(lp->tx_fifo_kb<<10) - 512; + lp->rx_fifo_size= ((0x4000 - 512 - lp->tx_fifo_size) / 16) * 15; + + /* Set the automatic flow control values */ + switch(lp->tx_fifo_kb) { + /* + * AFC_HI is about ((Rx Data Fifo Size)*2/3)/64 + * AFC_LO is AFC_HI/2 + * BACK_DUR is about 5uS*(AFC_LO) rounded down + */ + case 2:/* 13440 Rx Data Fifo Size */ + lp->afc_cfg=0x008C46AF;break; + case 3:/* 12480 Rx Data Fifo Size */ + lp->afc_cfg=0x0082419F;break; + case 4:/* 11520 Rx Data Fifo Size */ + lp->afc_cfg=0x00783C9F;break; + case 5:/* 10560 Rx Data Fifo Size */ + lp->afc_cfg=0x006E374F;break; + case 6:/* 9600 Rx Data Fifo Size */ + lp->afc_cfg=0x0064328F;break; + case 7:/* 8640 Rx Data Fifo Size */ + lp->afc_cfg=0x005A2D7F;break; + case 8:/* 7680 Rx Data Fifo Size */ + lp->afc_cfg=0x0050287F;break; + case 9:/* 6720 Rx Data Fifo Size */ + lp->afc_cfg=0x0046236F;break; + case 10:/* 5760 Rx Data Fifo Size */ + lp->afc_cfg=0x003C1E6F;break; + case 11:/* 4800 Rx Data Fifo Size */ + lp->afc_cfg=0x0032195F;break; + /* + * AFC_HI is ~1520 bytes less than RX Data Fifo Size + * AFC_LO is AFC_HI/2 + * BACK_DUR is about 5uS*(AFC_LO) rounded down + */ + case 12:/* 3840 Rx Data Fifo Size */ + lp->afc_cfg=0x0024124F;break; + case 13:/* 2880 Rx Data Fifo Size */ + lp->afc_cfg=0x0015073F;break; + case 14:/* 1920 Rx Data Fifo Size */ + lp->afc_cfg=0x0006032F;break; + default: + PRINTK("%s: ERROR -- no AFC_CFG setting found", + dev->name); + break; + } + + DBG(SMC_DEBUG_MISC | SMC_DEBUG_TX | SMC_DEBUG_RX, + "%s: tx_fifo %d rx_fifo %d afc_cfg 0x%08x\n", CARDNAME, + lp->tx_fifo_size, lp->rx_fifo_size, lp->afc_cfg); + + spin_lock_init(&lp->lock); + + /* Get the MAC address */ + SMC_GET_MAC_ADDR(dev->dev_addr); + + /* now, reset the chip, and put it into a known state */ + smc911x_reset(dev); + + /* + * If dev->irq is 0, then the device has to be banged on to see + * what the IRQ is. + * + * Specifying an IRQ is done with the assumption that the user knows + * what (s)he is doing. No checking is done!!!! + */ + if (dev->irq < 1) { + int trials; + + trials = 3; + while (trials--) { + dev->irq = smc911x_findirq(ioaddr); + if (dev->irq) + break; + /* kick the card and try again */ + smc911x_reset(dev); + } + } + if (dev->irq == 0) { + printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n", + dev->name); + retval = -ENODEV; + goto err_out; + } + dev->irq = irq_canonicalize(dev->irq); + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + + dev->open = smc911x_open; + dev->stop = smc911x_close; + dev->hard_start_xmit = smc911x_hard_start_xmit; + dev->tx_timeout = smc911x_timeout; + dev->watchdog_timeo = msecs_to_jiffies(watchdog); + dev->get_stats = smc911x_query_statistics; + dev->set_multicast_list = smc911x_set_multicast_list; + dev->ethtool_ops = &smc911x_ethtool_ops; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = smc911x_poll_controller; +#endif + + INIT_WORK(&lp->phy_configure, smc911x_phy_configure, dev); + lp->mii.phy_id_mask = 0x1f; + lp->mii.reg_num_mask = 0x1f; + lp->mii.force_media = 0; + lp->mii.full_duplex = 0; + lp->mii.dev = dev; + lp->mii.mdio_read = smc911x_phy_read; + lp->mii.mdio_write = smc911x_phy_write; + + /* + * Locate the phy, if any. + */ + smc911x_phy_detect(dev); + + /* Set default parameters */ + lp->msg_enable = NETIF_MSG_LINK; + lp->ctl_rfduplx = 1; + lp->ctl_rspeed = 100; + + /* Grab the IRQ */ + retval = request_irq(dev->irq, &smc911x_interrupt, SA_SHIRQ, dev->name, dev); + if (retval) + goto err_out; + + set_irq_type(dev->irq, IRQT_FALLING); + +#ifdef SMC_USE_DMA + lp->rxdma = SMC_DMA_REQUEST(dev, smc911x_rx_dma_irq); + lp->txdma = SMC_DMA_REQUEST(dev, smc911x_tx_dma_irq); + lp->rxdma_active = 0; + lp->txdma_active = 0; + dev->dma = lp->rxdma; +#endif + + retval = register_netdev(dev); + if (retval == 0) { + /* now, print out the card info, in a short format.. */ + printk("%s: %s (rev %d) at %#lx IRQ %d", + dev->name, version_string, lp->revision, + dev->base_addr, dev->irq); + +#ifdef SMC_USE_DMA + if (lp->rxdma != -1) + printk(" RXDMA %d ", lp->rxdma); + + if (lp->txdma != -1) + printk("TXDMA %d", lp->txdma); +#endif + printk("\n"); + if (!is_valid_ether_addr(dev->dev_addr)) { + printk("%s: Invalid ethernet MAC address. Please " + "set using ifconfig\n", dev->name); + } else { + /* Print the Ethernet address */ + printk("%s: Ethernet addr: ", dev->name); + for (i = 0; i < 5; i++) + printk("%2.2x:", dev->dev_addr[i]); + printk("%2.2x\n", dev->dev_addr[5]); + } + + if (lp->phy_type == 0) { + PRINTK("%s: No PHY found\n", dev->name); + } else if ((lp->phy_type & ~0xff) == LAN911X_INTERNAL_PHY_ID) { + PRINTK("%s: LAN911x Internal PHY\n", dev->name); + } else { + PRINTK("%s: External PHY 0x%08x\n", dev->name, lp->phy_type); + } + } + +err_out: +#ifdef SMC_USE_DMA + if (retval) { + if (lp->rxdma != -1) { + SMC_DMA_FREE(dev, lp->rxdma); + } + if (lp->txdma != -1) { + SMC_DMA_FREE(dev, lp->txdma); + } + } +#endif + return retval; +} + +/* + * smc911x_init(void) + * + * Output: + * 0 --> there is a device + * anything else, error + */ +static int smc911x_drv_probe(struct platform_device *pdev) +{ + struct net_device *ndev; + struct resource *res; + unsigned int *addr; + int ret; + + DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENODEV; + goto out; + } + + /* + * Request the regions. + */ + if (!request_mem_region(res->start, SMC911X_IO_EXTENT, CARDNAME)) { + ret = -EBUSY; + goto out; + } + + ndev = alloc_etherdev(sizeof(struct smc911x_local)); + if (!ndev) { + printk("%s: could not allocate device.\n", CARDNAME); + ret = -ENOMEM; + goto release_1; + } + SET_MODULE_OWNER(ndev); + SET_NETDEV_DEV(ndev, &pdev->dev); + + ndev->dma = (unsigned char)-1; + ndev->irq = platform_get_irq(pdev, 0); + + addr = ioremap(res->start, SMC911X_IO_EXTENT); + if (!addr) { + ret = -ENOMEM; + goto release_both; + } + + platform_set_drvdata(pdev, ndev); + ret = smc911x_probe(ndev, (unsigned long)addr); + if (ret != 0) { + platform_set_drvdata(pdev, NULL); + iounmap(addr); +release_both: + free_netdev(ndev); +release_1: + release_mem_region(res->start, SMC911X_IO_EXTENT); +out: + printk("%s: not found (%d).\n", CARDNAME, ret); + } +#ifdef SMC_USE_DMA + else { + struct smc911x_local *lp = netdev_priv(ndev); + lp->physaddr = res->start; + lp->dev = &pdev->dev; + } +#endif + + return ret; +} + +static int smc911x_drv_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct resource *res; + + DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + platform_set_drvdata(pdev, NULL); + + unregister_netdev(ndev); + + free_irq(ndev->irq, ndev); + +#ifdef SMC_USE_DMA + { + struct smc911x_local *lp = netdev_priv(ndev); + if (lp->rxdma != -1) { + SMC_DMA_FREE(dev, lp->rxdma); + } + if (lp->txdma != -1) { + SMC_DMA_FREE(dev, lp->txdma); + } + } +#endif + iounmap((void *)ndev->base_addr); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, SMC911X_IO_EXTENT); + + free_netdev(ndev); + return 0; +} + +static int smc911x_drv_suspend(struct platform_device *dev, pm_message_t state) +{ + struct net_device *ndev = platform_get_drvdata(dev); + unsigned long ioaddr = ndev->base_addr; + + DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + if (ndev) { + if (netif_running(ndev)) { + netif_device_detach(ndev); + smc911x_shutdown(ndev); +#if POWER_DOWN + /* Set D2 - Energy detect only setting */ + SMC_SET_PMT_CTRL(2<<12); +#endif + } + } + return 0; +} + +static int smc911x_drv_resume(struct platform_device *dev) +{ + struct net_device *ndev = platform_get_drvdata(dev); + + DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + if (ndev) { + struct smc911x_local *lp = netdev_priv(ndev); + + if (netif_running(ndev)) { + smc911x_reset(ndev); + smc911x_enable(ndev); + if (lp->phy_type != 0) + smc911x_phy_configure(ndev); + netif_device_attach(ndev); + } + } + return 0; +} + +static struct platform_driver smc911x_driver = { + .probe = smc911x_drv_probe, + .remove = smc911x_drv_remove, + .suspend = smc911x_drv_suspend, + .resume = smc911x_drv_resume, + .driver = { + .name = CARDNAME, + }, +}; + +static int __init smc911x_init(void) +{ + return platform_driver_register(&smc911x_driver); +} + +static void __exit smc911x_cleanup(void) +{ + platform_driver_unregister(&smc911x_driver); +} + +module_init(smc911x_init); +module_exit(smc911x_cleanup); diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h new file mode 100644 index 0000000..962a710 --- /dev/null +++ b/drivers/net/smc911x.h @@ -0,0 +1,835 @@ +/*------------------------------------------------------------------------ + . smc911x.h - macros for SMSC's LAN911{5,6,7,8} single-chip Ethernet device. + . + . Copyright (C) 2005 Sensoria Corp. + . Derived from the unified SMC91x driver by Nicolas Pitre + . + . This program is free software; you can redistribute it and/or modify + . it under the terms of the GNU General Public License as published by + . the Free Software Foundation; either version 2 of the License, or + . (at your option) any later version. + . + . This program is distributed in the hope that it will be useful, + . but WITHOUT ANY WARRANTY; without even the implied warranty of + . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + . GNU General Public License for more details. + . + . You should have received a copy of the GNU General Public License + . along with this program; if not, write to the Free Software + . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + . + . Information contained in this file was obtained from the LAN9118 + . manual from SMC. To get a copy, if you really want one, you can find + . information under www.smsc.com. + . + . Authors + . Dustin McIntire + . + ---------------------------------------------------------------------------*/ +#ifndef _SMC911X_H_ +#define _SMC911X_H_ + +/* + * Use the DMA feature on PXA chips + */ +#ifdef CONFIG_ARCH_PXA + #define SMC_USE_PXA_DMA 1 + #define SMC_USE_16BIT 0 + #define SMC_USE_32BIT 1 +#endif + + +/* + * Define the bus width specific IO macros + */ + +#if SMC_USE_16BIT +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw(a+2, r)<<16)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) \ + do{ \ + writel(v & 0xFFFF, (a) + (r)); \ + writel(v >> 16, (a) + (r) + 2); \ + } while (0) +#define SMC_insl(a, r, p, l) readsw((short*)((a) + (r)), p, l*2) +#define SMC_outsl(a, r, p, l) writesw((short*)((a) + (r)), p, l*2) + +#elif SMC_USE_32BIT +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((int*)((a) + (r)), p, l) +#define SMC_outsl(a, r, p, l) writesl((int*)((a) + (r)), p, l) + +#endif /* SMC_USE_16BIT */ + + + +#if SMC_USE_PXA_DMA +#define SMC_USE_DMA + +/* + * Define the request and free functions + * These are unfortunately architecture specific as no generic allocation + * mechanism exits + */ +#define SMC_DMA_REQUEST(dev, handler) \ + pxa_request_dma(dev->name, DMA_PRIO_LOW, handler, dev) + +#define SMC_DMA_FREE(dev, dma) \ + pxa_free_dma(dma) + +#define SMC_DMA_ACK_IRQ(dev, dma) \ +{ \ + if (DCSR(dma) & DCSR_BUSERR) { \ + printk("%s: DMA %d bus error!\n", dev->name, dma); \ + } \ + DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; \ +} + +/* + * Use a DMA for RX and TX packets. + */ +#include +#include +#include + +static dma_addr_t rx_dmabuf, tx_dmabuf; +static int rx_dmalen, tx_dmalen; + +#ifdef SMC_insl +#undef SMC_insl +#define SMC_insl(a, r, p, l) \ + smc_pxa_dma_insl(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l) + +static inline void +smc_pxa_dma_insl(struct device *dev, u_long ioaddr, u_long physaddr, + int reg, int dma, u_char *buf, int len) +{ + /* 64 bit alignment is required for memory to memory DMA */ + if ((long)buf & 4) { + *((u32 *)buf) = SMC_inl(ioaddr, reg); + buf += 4; + len--; + } + + len *= 4; + rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE); + rx_dmalen = len; + DCSR(dma) = DCSR_NODESC; + DTADR(dma) = rx_dmabuf; + DSADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | + DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; +} +#endif + +#ifdef SMC_insw +#undef SMC_insw +#define SMC_insw(a, r, p, l) \ + smc_pxa_dma_insw(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l) + +static inline void +smc_pxa_dma_insw(struct device *dev, u_long ioaddr, u_long physaddr, + int reg, int dma, u_char *buf, int len) +{ + /* 64 bit alignment is required for memory to memory DMA */ + while ((long)buf & 6) { + *((u16 *)buf) = SMC_inw(ioaddr, reg); + buf += 2; + len--; + } + + len *= 2; + rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE); + rx_dmalen = len; + DCSR(dma) = DCSR_NODESC; + DTADR(dma) = rx_dmabuf; + DSADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | + DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; +} +#endif + +#ifdef SMC_outsl +#undef SMC_outsl +#define SMC_outsl(a, r, p, l) \ + smc_pxa_dma_outsl(lp->dev, a, lp->physaddr, r, lp->txdma, p, l) + +static inline void +smc_pxa_dma_outsl(struct device *dev, u_long ioaddr, u_long physaddr, + int reg, int dma, u_char *buf, int len) +{ + /* 64 bit alignment is required for memory to memory DMA */ + if ((long)buf & 4) { + SMC_outl(*((u32 *)buf), ioaddr, reg); + buf += 4; + len--; + } + + len *= 4; + tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE); + tx_dmalen = len; + DCSR(dma) = DCSR_NODESC; + DSADR(dma) = tx_dmabuf; + DTADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 | + DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; +} +#endif + +#ifdef SMC_outsw +#undef SMC_outsw +#define SMC_outsw(a, r, p, l) \ + smc_pxa_dma_outsw(lp->dev, a, lp->physaddr, r, lp->txdma, p, l) + +static inline void +smc_pxa_dma_outsw(struct device *dev, u_long ioaddr, u_long physaddr, + int reg, int dma, u_char *buf, int len) +{ + /* 64 bit alignment is required for memory to memory DMA */ + while ((long)buf & 6) { + SMC_outw(*((u16 *)buf), ioaddr, reg); + buf += 2; + len--; + } + + len *= 2; + tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE); + tx_dmalen = len; + DCSR(dma) = DCSR_NODESC; + DSADR(dma) = tx_dmabuf; + DTADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 | + DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; +} +#endif + +#endif /* SMC_USE_PXA_DMA */ + + +/* Chip Parameters and Register Definitions */ + +#define SMC911X_TX_FIFO_LOW_THRESHOLD (1536*2) + +#define SMC911X_IO_EXTENT 0x100 + +#define SMC911X_EEPROM_LEN 7 + +/* Below are the register offsets and bit definitions + * of the Lan911x memory space + */ +#define RX_DATA_FIFO (0x00) + +#define TX_DATA_FIFO (0x20) +#define TX_CMD_A_INT_ON_COMP_ (0x80000000) +#define TX_CMD_A_INT_BUF_END_ALGN_ (0x03000000) +#define TX_CMD_A_INT_4_BYTE_ALGN_ (0x00000000) +#define TX_CMD_A_INT_16_BYTE_ALGN_ (0x01000000) +#define TX_CMD_A_INT_32_BYTE_ALGN_ (0x02000000) +#define TX_CMD_A_INT_DATA_OFFSET_ (0x001F0000) +#define TX_CMD_A_INT_FIRST_SEG_ (0x00002000) +#define TX_CMD_A_INT_LAST_SEG_ (0x00001000) +#define TX_CMD_A_BUF_SIZE_ (0x000007FF) +#define TX_CMD_B_PKT_TAG_ (0xFFFF0000) +#define TX_CMD_B_ADD_CRC_DISABLE_ (0x00002000) +#define TX_CMD_B_DISABLE_PADDING_ (0x00001000) +#define TX_CMD_B_PKT_BYTE_LENGTH_ (0x000007FF) + +#define RX_STATUS_FIFO (0x40) +#define RX_STS_PKT_LEN_ (0x3FFF0000) +#define RX_STS_ES_ (0x00008000) +#define RX_STS_BCST_ (0x00002000) +#define RX_STS_LEN_ERR_ (0x00001000) +#define RX_STS_RUNT_ERR_ (0x00000800) +#define RX_STS_MCAST_ (0x00000400) +#define RX_STS_TOO_LONG_ (0x00000080) +#define RX_STS_COLL_ (0x00000040) +#define RX_STS_ETH_TYPE_ (0x00000020) +#define RX_STS_WDOG_TMT_ (0x00000010) +#define RX_STS_MII_ERR_ (0x00000008) +#define RX_STS_DRIBBLING_ (0x00000004) +#define RX_STS_CRC_ERR_ (0x00000002) +#define RX_STATUS_FIFO_PEEK (0x44) +#define TX_STATUS_FIFO (0x48) +#define TX_STS_TAG_ (0xFFFF0000) +#define TX_STS_ES_ (0x00008000) +#define TX_STS_LOC_ (0x00000800) +#define TX_STS_NO_CARR_ (0x00000400) +#define TX_STS_LATE_COLL_ (0x00000200) +#define TX_STS_MANY_COLL_ (0x00000100) +#define TX_STS_COLL_CNT_ (0x00000078) +#define TX_STS_MANY_DEFER_ (0x00000004) +#define TX_STS_UNDERRUN_ (0x00000002) +#define TX_STS_DEFERRED_ (0x00000001) +#define TX_STATUS_FIFO_PEEK (0x4C) +#define ID_REV (0x50) +#define ID_REV_CHIP_ID_ (0xFFFF0000) /* RO */ +#define ID_REV_REV_ID_ (0x0000FFFF) /* RO */ + +#define INT_CFG (0x54) +#define INT_CFG_INT_DEAS_ (0xFF000000) /* R/W */ +#define INT_CFG_INT_DEAS_CLR_ (0x00004000) +#define INT_CFG_INT_DEAS_STS_ (0x00002000) +#define INT_CFG_IRQ_INT_ (0x00001000) /* RO */ +#define INT_CFG_IRQ_EN_ (0x00000100) /* R/W */ +#define INT_CFG_IRQ_POL_ (0x00000010) /* R/W Not Affected by SW Reset */ +#define INT_CFG_IRQ_TYPE_ (0x00000001) /* R/W Not Affected by SW Reset */ + +#define INT_STS (0x58) +#define INT_STS_SW_INT_ (0x80000000) /* R/WC */ +#define INT_STS_TXSTOP_INT_ (0x02000000) /* R/WC */ +#define INT_STS_RXSTOP_INT_ (0x01000000) /* R/WC */ +#define INT_STS_RXDFH_INT_ (0x00800000) /* R/WC */ +#define INT_STS_RXDF_INT_ (0x00400000) /* R/WC */ +#define INT_STS_TX_IOC_ (0x00200000) /* R/WC */ +#define INT_STS_RXD_INT_ (0x00100000) /* R/WC */ +#define INT_STS_GPT_INT_ (0x00080000) /* R/WC */ +#define INT_STS_PHY_INT_ (0x00040000) /* RO */ +#define INT_STS_PME_INT_ (0x00020000) /* R/WC */ +#define INT_STS_TXSO_ (0x00010000) /* R/WC */ +#define INT_STS_RWT_ (0x00008000) /* R/WC */ +#define INT_STS_RXE_ (0x00004000) /* R/WC */ +#define INT_STS_TXE_ (0x00002000) /* R/WC */ +//#define INT_STS_ERX_ (0x00001000) /* R/WC */ +#define INT_STS_TDFU_ (0x00000800) /* R/WC */ +#define INT_STS_TDFO_ (0x00000400) /* R/WC */ +#define INT_STS_TDFA_ (0x00000200) /* R/WC */ +#define INT_STS_TSFF_ (0x00000100) /* R/WC */ +#define INT_STS_TSFL_ (0x00000080) /* R/WC */ +//#define INT_STS_RXDF_ (0x00000040) /* R/WC */ +#define INT_STS_RDFO_ (0x00000040) /* R/WC */ +#define INT_STS_RDFL_ (0x00000020) /* R/WC */ +#define INT_STS_RSFF_ (0x00000010) /* R/WC */ +#define INT_STS_RSFL_ (0x00000008) /* R/WC */ +#define INT_STS_GPIO2_INT_ (0x00000004) /* R/WC */ +#define INT_STS_GPIO1_INT_ (0x00000002) /* R/WC */ +#define INT_STS_GPIO0_INT_ (0x00000001) /* R/WC */ + +#define INT_EN (0x5C) +#define INT_EN_SW_INT_EN_ (0x80000000) /* R/W */ +#define INT_EN_TXSTOP_INT_EN_ (0x02000000) /* R/W */ +#define INT_EN_RXSTOP_INT_EN_ (0x01000000) /* R/W */ +#define INT_EN_RXDFH_INT_EN_ (0x00800000) /* R/W */ +//#define INT_EN_RXDF_INT_EN_ (0x00400000) /* R/W */ +#define INT_EN_TIOC_INT_EN_ (0x00200000) /* R/W */ +#define INT_EN_RXD_INT_EN_ (0x00100000) /* R/W */ +#define INT_EN_GPT_INT_EN_ (0x00080000) /* R/W */ +#define INT_EN_PHY_INT_EN_ (0x00040000) /* R/W */ +#define INT_EN_PME_INT_EN_ (0x00020000) /* R/W */ +#define INT_EN_TXSO_EN_ (0x00010000) /* R/W */ +#define INT_EN_RWT_EN_ (0x00008000) /* R/W */ +#define INT_EN_RXE_EN_ (0x00004000) /* R/W */ +#define INT_EN_TXE_EN_ (0x00002000) /* R/W */ +//#define INT_EN_ERX_EN_ (0x00001000) /* R/W */ +#define INT_EN_TDFU_EN_ (0x00000800) /* R/W */ +#define INT_EN_TDFO_EN_ (0x00000400) /* R/W */ +#define INT_EN_TDFA_EN_ (0x00000200) /* R/W */ +#define INT_EN_TSFF_EN_ (0x00000100) /* R/W */ +#define INT_EN_TSFL_EN_ (0x00000080) /* R/W */ +//#define INT_EN_RXDF_EN_ (0x00000040) /* R/W */ +#define INT_EN_RDFO_EN_ (0x00000040) /* R/W */ +#define INT_EN_RDFL_EN_ (0x00000020) /* R/W */ +#define INT_EN_RSFF_EN_ (0x00000010) /* R/W */ +#define INT_EN_RSFL_EN_ (0x00000008) /* R/W */ +#define INT_EN_GPIO2_INT_ (0x00000004) /* R/W */ +#define INT_EN_GPIO1_INT_ (0x00000002) /* R/W */ +#define INT_EN_GPIO0_INT_ (0x00000001) /* R/W */ + +#define BYTE_TEST (0x64) +#define FIFO_INT (0x68) +#define FIFO_INT_TX_AVAIL_LEVEL_ (0xFF000000) /* R/W */ +#define FIFO_INT_TX_STS_LEVEL_ (0x00FF0000) /* R/W */ +#define FIFO_INT_RX_AVAIL_LEVEL_ (0x0000FF00) /* R/W */ +#define FIFO_INT_RX_STS_LEVEL_ (0x000000FF) /* R/W */ + +#define RX_CFG (0x6C) +#define RX_CFG_RX_END_ALGN_ (0xC0000000) /* R/W */ +#define RX_CFG_RX_END_ALGN4_ (0x00000000) /* R/W */ +#define RX_CFG_RX_END_ALGN16_ (0x40000000) /* R/W */ +#define RX_CFG_RX_END_ALGN32_ (0x80000000) /* R/W */ +#define RX_CFG_RX_DMA_CNT_ (0x0FFF0000) /* R/W */ +#define RX_CFG_RX_DUMP_ (0x00008000) /* R/W */ +#define RX_CFG_RXDOFF_ (0x00001F00) /* R/W */ +//#define RX_CFG_RXBAD_ (0x00000001) /* R/W */ + +#define TX_CFG (0x70) +//#define TX_CFG_TX_DMA_LVL_ (0xE0000000) /* R/W */ +//#define TX_CFG_TX_DMA_CNT_ (0x0FFF0000) /* R/W Self Clearing */ +#define TX_CFG_TXS_DUMP_ (0x00008000) /* Self Clearing */ +#define TX_CFG_TXD_DUMP_ (0x00004000) /* Self Clearing */ +#define TX_CFG_TXSAO_ (0x00000004) /* R/W */ +#define TX_CFG_TX_ON_ (0x00000002) /* R/W */ +#define TX_CFG_STOP_TX_ (0x00000001) /* Self Clearing */ + +#define HW_CFG (0x74) +#define HW_CFG_TTM_ (0x00200000) /* R/W */ +#define HW_CFG_SF_ (0x00100000) /* R/W */ +#define HW_CFG_TX_FIF_SZ_ (0x000F0000) /* R/W */ +#define HW_CFG_TR_ (0x00003000) /* R/W */ +#define HW_CFG_PHY_CLK_SEL_ (0x00000060) /* R/W */ +#define HW_CFG_PHY_CLK_SEL_INT_PHY_ (0x00000000) /* R/W */ +#define HW_CFG_PHY_CLK_SEL_EXT_PHY_ (0x00000020) /* R/W */ +#define HW_CFG_PHY_CLK_SEL_CLK_DIS_ (0x00000040) /* R/W */ +#define HW_CFG_SMI_SEL_ (0x00000010) /* R/W */ +#define HW_CFG_EXT_PHY_DET_ (0x00000008) /* RO */ +#define HW_CFG_EXT_PHY_EN_ (0x00000004) /* R/W */ +#define HW_CFG_32_16_BIT_MODE_ (0x00000004) /* RO */ +#define HW_CFG_SRST_TO_ (0x00000002) /* RO */ +#define HW_CFG_SRST_ (0x00000001) /* Self Clearing */ + +#define RX_DP_CTRL (0x78) +#define RX_DP_CTRL_RX_FFWD_ (0x80000000) /* R/W */ +#define RX_DP_CTRL_FFWD_BUSY_ (0x80000000) /* RO */ + +#define RX_FIFO_INF (0x7C) +#define RX_FIFO_INF_RXSUSED_ (0x00FF0000) /* RO */ +#define RX_FIFO_INF_RXDUSED_ (0x0000FFFF) /* RO */ + +#define TX_FIFO_INF (0x80) +#define TX_FIFO_INF_TSUSED_ (0x00FF0000) /* RO */ +#define TX_FIFO_INF_TDFREE_ (0x0000FFFF) /* RO */ + +#define PMT_CTRL (0x84) +#define PMT_CTRL_PM_MODE_ (0x00003000) /* Self Clearing */ +#define PMT_CTRL_PHY_RST_ (0x00000400) /* Self Clearing */ +#define PMT_CTRL_WOL_EN_ (0x00000200) /* R/W */ +#define PMT_CTRL_ED_EN_ (0x00000100) /* R/W */ +#define PMT_CTRL_PME_TYPE_ (0x00000040) /* R/W Not Affected by SW Reset */ +#define PMT_CTRL_WUPS_ (0x00000030) /* R/WC */ +#define PMT_CTRL_WUPS_NOWAKE_ (0x00000000) /* R/WC */ +#define PMT_CTRL_WUPS_ED_ (0x00000010) /* R/WC */ +#define PMT_CTRL_WUPS_WOL_ (0x00000020) /* R/WC */ +#define PMT_CTRL_WUPS_MULTI_ (0x00000030) /* R/WC */ +#define PMT_CTRL_PME_IND_ (0x00000008) /* R/W */ +#define PMT_CTRL_PME_POL_ (0x00000004) /* R/W */ +#define PMT_CTRL_PME_EN_ (0x00000002) /* R/W Not Affected by SW Reset */ +#define PMT_CTRL_READY_ (0x00000001) /* RO */ + +#define GPIO_CFG (0x88) +#define GPIO_CFG_LED3_EN_ (0x40000000) /* R/W */ +#define GPIO_CFG_LED2_EN_ (0x20000000) /* R/W */ +#define GPIO_CFG_LED1_EN_ (0x10000000) /* R/W */ +#define GPIO_CFG_GPIO2_INT_POL_ (0x04000000) /* R/W */ +#define GPIO_CFG_GPIO1_INT_POL_ (0x02000000) /* R/W */ +#define GPIO_CFG_GPIO0_INT_POL_ (0x01000000) /* R/W */ +#define GPIO_CFG_EEPR_EN_ (0x00700000) /* R/W */ +#define GPIO_CFG_GPIOBUF2_ (0x00040000) /* R/W */ +#define GPIO_CFG_GPIOBUF1_ (0x00020000) /* R/W */ +#define GPIO_CFG_GPIOBUF0_ (0x00010000) /* R/W */ +#define GPIO_CFG_GPIODIR2_ (0x00000400) /* R/W */ +#define GPIO_CFG_GPIODIR1_ (0x00000200) /* R/W */ +#define GPIO_CFG_GPIODIR0_ (0x00000100) /* R/W */ +#define GPIO_CFG_GPIOD4_ (0x00000010) /* R/W */ +#define GPIO_CFG_GPIOD3_ (0x00000008) /* R/W */ +#define GPIO_CFG_GPIOD2_ (0x00000004) /* R/W */ +#define GPIO_CFG_GPIOD1_ (0x00000002) /* R/W */ +#define GPIO_CFG_GPIOD0_ (0x00000001) /* R/W */ + +#define GPT_CFG (0x8C) +#define GPT_CFG_TIMER_EN_ (0x20000000) /* R/W */ +#define GPT_CFG_GPT_LOAD_ (0x0000FFFF) /* R/W */ + +#define GPT_CNT (0x90) +#define GPT_CNT_GPT_CNT_ (0x0000FFFF) /* RO */ + +#define ENDIAN (0x98) +#define FREE_RUN (0x9C) +#define RX_DROP (0xA0) +#define MAC_CSR_CMD (0xA4) +#define MAC_CSR_CMD_CSR_BUSY_ (0x80000000) /* Self Clearing */ +#define MAC_CSR_CMD_R_NOT_W_ (0x40000000) /* R/W */ +#define MAC_CSR_CMD_CSR_ADDR_ (0x000000FF) /* R/W */ + +#define MAC_CSR_DATA (0xA8) +#define AFC_CFG (0xAC) +#define AFC_CFG_AFC_HI_ (0x00FF0000) /* R/W */ +#define AFC_CFG_AFC_LO_ (0x0000FF00) /* R/W */ +#define AFC_CFG_BACK_DUR_ (0x000000F0) /* R/W */ +#define AFC_CFG_FCMULT_ (0x00000008) /* R/W */ +#define AFC_CFG_FCBRD_ (0x00000004) /* R/W */ +#define AFC_CFG_FCADD_ (0x00000002) /* R/W */ +#define AFC_CFG_FCANY_ (0x00000001) /* R/W */ + +#define E2P_CMD (0xB0) +#define E2P_CMD_EPC_BUSY_ (0x80000000) /* Self Clearing */ +#define E2P_CMD_EPC_CMD_ (0x70000000) /* R/W */ +#define E2P_CMD_EPC_CMD_READ_ (0x00000000) /* R/W */ +#define E2P_CMD_EPC_CMD_EWDS_ (0x10000000) /* R/W */ +#define E2P_CMD_EPC_CMD_EWEN_ (0x20000000) /* R/W */ +#define E2P_CMD_EPC_CMD_WRITE_ (0x30000000) /* R/W */ +#define E2P_CMD_EPC_CMD_WRAL_ (0x40000000) /* R/W */ +#define E2P_CMD_EPC_CMD_ERASE_ (0x50000000) /* R/W */ +#define E2P_CMD_EPC_CMD_ERAL_ (0x60000000) /* R/W */ +#define E2P_CMD_EPC_CMD_RELOAD_ (0x70000000) /* R/W */ +#define E2P_CMD_EPC_TIMEOUT_ (0x00000200) /* RO */ +#define E2P_CMD_MAC_ADDR_LOADED_ (0x00000100) /* RO */ +#define E2P_CMD_EPC_ADDR_ (0x000000FF) /* R/W */ + +#define E2P_DATA (0xB4) +#define E2P_DATA_EEPROM_DATA_ (0x000000FF) /* R/W */ +/* end of LAN register offsets and bit definitions */ + +/* + **************************************************************************** + **************************************************************************** + * MAC Control and Status Register (Indirect Address) + * Offset (through the MAC_CSR CMD and DATA port) + **************************************************************************** + **************************************************************************** + * + */ +#define MAC_CR (0x01) /* R/W */ + +/* MAC_CR - MAC Control Register */ +#define MAC_CR_RXALL_ (0x80000000) +// TODO: delete this bit? It is not described in the data sheet. +#define MAC_CR_HBDIS_ (0x10000000) +#define MAC_CR_RCVOWN_ (0x00800000) +#define MAC_CR_LOOPBK_ (0x00200000) +#define MAC_CR_FDPX_ (0x00100000) +#define MAC_CR_MCPAS_ (0x00080000) +#define MAC_CR_PRMS_ (0x00040000) +#define MAC_CR_INVFILT_ (0x00020000) +#define MAC_CR_PASSBAD_ (0x00010000) +#define MAC_CR_HFILT_ (0x00008000) +#define MAC_CR_HPFILT_ (0x00002000) +#define MAC_CR_LCOLL_ (0x00001000) +#define MAC_CR_BCAST_ (0x00000800) +#define MAC_CR_DISRTY_ (0x00000400) +#define MAC_CR_PADSTR_ (0x00000100) +#define MAC_CR_BOLMT_MASK_ (0x000000C0) +#define MAC_CR_DFCHK_ (0x00000020) +#define MAC_CR_TXEN_ (0x00000008) +#define MAC_CR_RXEN_ (0x00000004) + +#define ADDRH (0x02) /* R/W mask 0x0000FFFFUL */ +#define ADDRL (0x03) /* R/W mask 0xFFFFFFFFUL */ +#define HASHH (0x04) /* R/W */ +#define HASHL (0x05) /* R/W */ + +#define MII_ACC (0x06) /* R/W */ +#define MII_ACC_PHY_ADDR_ (0x0000F800) +#define MII_ACC_MIIRINDA_ (0x000007C0) +#define MII_ACC_MII_WRITE_ (0x00000002) +#define MII_ACC_MII_BUSY_ (0x00000001) + +#define MII_DATA (0x07) /* R/W mask 0x0000FFFFUL */ + +#define FLOW (0x08) /* R/W */ +#define FLOW_FCPT_ (0xFFFF0000) +#define FLOW_FCPASS_ (0x00000004) +#define FLOW_FCEN_ (0x00000002) +#define FLOW_FCBSY_ (0x00000001) + +#define VLAN1 (0x09) /* R/W mask 0x0000FFFFUL */ +#define VLAN1_VTI1_ (0x0000ffff) + +#define VLAN2 (0x0A) /* R/W mask 0x0000FFFFUL */ +#define VLAN2_VTI2_ (0x0000ffff) + +#define WUFF (0x0B) /* WO */ + +#define WUCSR (0x0C) /* R/W */ +#define WUCSR_GUE_ (0x00000200) +#define WUCSR_WUFR_ (0x00000040) +#define WUCSR_MPR_ (0x00000020) +#define WUCSR_WAKE_EN_ (0x00000004) +#define WUCSR_MPEN_ (0x00000002) + +/* + **************************************************************************** + * Chip Specific MII Defines + **************************************************************************** + * + * Phy register offsets and bit definitions + * + */ + +#define PHY_MODE_CTRL_STS ((u32)17) /* Mode Control/Status Register */ +//#define MODE_CTRL_STS_FASTRIP_ ((u16)0x4000) +#define MODE_CTRL_STS_EDPWRDOWN_ ((u16)0x2000) +//#define MODE_CTRL_STS_LOWSQEN_ ((u16)0x0800) +//#define MODE_CTRL_STS_MDPREBP_ ((u16)0x0400) +//#define MODE_CTRL_STS_FARLOOPBACK_ ((u16)0x0200) +//#define MODE_CTRL_STS_FASTEST_ ((u16)0x0100) +//#define MODE_CTRL_STS_REFCLKEN_ ((u16)0x0010) +//#define MODE_CTRL_STS_PHYADBP_ ((u16)0x0008) +//#define MODE_CTRL_STS_FORCE_G_LINK_ ((u16)0x0004) +#define MODE_CTRL_STS_ENERGYON_ ((u16)0x0002) + +#define PHY_INT_SRC ((u32)29) +#define PHY_INT_SRC_ENERGY_ON_ ((u16)0x0080) +#define PHY_INT_SRC_ANEG_COMP_ ((u16)0x0040) +#define PHY_INT_SRC_REMOTE_FAULT_ ((u16)0x0020) +#define PHY_INT_SRC_LINK_DOWN_ ((u16)0x0010) +#define PHY_INT_SRC_ANEG_LP_ACK_ ((u16)0x0008) +#define PHY_INT_SRC_PAR_DET_FAULT_ ((u16)0x0004) +#define PHY_INT_SRC_ANEG_PGRX_ ((u16)0x0002) + +#define PHY_INT_MASK ((u32)30) +#define PHY_INT_MASK_ENERGY_ON_ ((u16)0x0080) +#define PHY_INT_MASK_ANEG_COMP_ ((u16)0x0040) +#define PHY_INT_MASK_REMOTE_FAULT_ ((u16)0x0020) +#define PHY_INT_MASK_LINK_DOWN_ ((u16)0x0010) +#define PHY_INT_MASK_ANEG_LP_ACK_ ((u16)0x0008) +#define PHY_INT_MASK_PAR_DET_FAULT_ ((u16)0x0004) +#define PHY_INT_MASK_ANEG_PGRX_ ((u16)0x0002) + +#define PHY_SPECIAL ((u32)31) +#define PHY_SPECIAL_ANEG_DONE_ ((u16)0x1000) +#define PHY_SPECIAL_RES_ ((u16)0x0040) +#define PHY_SPECIAL_RES_MASK_ ((u16)0x0FE1) +#define PHY_SPECIAL_SPD_ ((u16)0x001C) +#define PHY_SPECIAL_SPD_10HALF_ ((u16)0x0004) +#define PHY_SPECIAL_SPD_10FULL_ ((u16)0x0014) +#define PHY_SPECIAL_SPD_100HALF_ ((u16)0x0008) +#define PHY_SPECIAL_SPD_100FULL_ ((u16)0x0018) + +#define LAN911X_INTERNAL_PHY_ID (0x0007C000) + +/* Chip ID values */ +#define CHIP_9115 0x115 +#define CHIP_9116 0x116 +#define CHIP_9117 0x117 +#define CHIP_9118 0x118 + +struct chip_id { + u16 id; + char *name; +}; + +static const struct chip_id chip_ids[] = { + { CHIP_9115, "LAN9115" }, + { CHIP_9116, "LAN9116" }, + { CHIP_9117, "LAN9117" }, + { CHIP_9118, "LAN9118" }, + { 0, NULL }, +}; + +#define IS_REV_A(x) ((x & 0xFFFF)==0) + +/* + * Macros to abstract register access according to the data bus + * capabilities. Please use those and not the in/out primitives. + */ +/* FIFO read/write macros */ +#define SMC_PUSH_DATA(p, l) SMC_outsl( ioaddr, TX_DATA_FIFO, p, (l) >> 2 ) +#define SMC_PULL_DATA(p, l) SMC_insl ( ioaddr, RX_DATA_FIFO, p, (l) >> 2 ) +#define SMC_SET_TX_FIFO(x) SMC_outl( x, ioaddr, TX_DATA_FIFO ) +#define SMC_GET_RX_FIFO() SMC_inl( ioaddr, RX_DATA_FIFO ) + + +/* I/O mapped register read/write macros */ +#define SMC_GET_TX_STS_FIFO() SMC_inl( ioaddr, TX_STATUS_FIFO ) +#define SMC_GET_RX_STS_FIFO() SMC_inl( ioaddr, RX_STATUS_FIFO ) +#define SMC_GET_RX_STS_FIFO_PEEK() SMC_inl( ioaddr, RX_STATUS_FIFO_PEEK ) +#define SMC_GET_PN() (SMC_inl( ioaddr, ID_REV ) >> 16) +#define SMC_GET_REV() (SMC_inl( ioaddr, ID_REV ) & 0xFFFF) +#define SMC_GET_IRQ_CFG() SMC_inl( ioaddr, INT_CFG ) +#define SMC_SET_IRQ_CFG(x) SMC_outl( x, ioaddr, INT_CFG ) +#define SMC_GET_INT() SMC_inl( ioaddr, INT_STS ) +#define SMC_ACK_INT(x) SMC_outl( x, ioaddr, INT_STS ) +#define SMC_GET_INT_EN() SMC_inl( ioaddr, INT_EN ) +#define SMC_SET_INT_EN(x) SMC_outl( x, ioaddr, INT_EN ) +#define SMC_GET_BYTE_TEST() SMC_inl( ioaddr, BYTE_TEST ) +#define SMC_SET_BYTE_TEST(x) SMC_outl( x, ioaddr, BYTE_TEST ) +#define SMC_GET_FIFO_INT() SMC_inl( ioaddr, FIFO_INT ) +#define SMC_SET_FIFO_INT(x) SMC_outl( x, ioaddr, FIFO_INT ) +#define SMC_SET_FIFO_TDA(x) \ + do { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_GET_FIFO_INT() & ~(0xFF<<24); \ + SMC_SET_FIFO_INT( __mask | (x)<<24 ); \ + local_irq_restore(__flags); \ + } while (0) +#define SMC_SET_FIFO_TSL(x) \ + do { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_GET_FIFO_INT() & ~(0xFF<<16); \ + SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<16)); \ + local_irq_restore(__flags); \ + } while (0) +#define SMC_SET_FIFO_RSA(x) \ + do { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_GET_FIFO_INT() & ~(0xFF<<8); \ + SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<8)); \ + local_irq_restore(__flags); \ + } while (0) +#define SMC_SET_FIFO_RSL(x) \ + do { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_GET_FIFO_INT() & ~0xFF; \ + SMC_SET_FIFO_INT( __mask | ((x) & 0xFF)); \ + local_irq_restore(__flags); \ + } while (0) +#define SMC_GET_RX_CFG() SMC_inl( ioaddr, RX_CFG ) +#define SMC_SET_RX_CFG(x) SMC_outl( x, ioaddr, RX_CFG ) +#define SMC_GET_TX_CFG() SMC_inl( ioaddr, TX_CFG ) +#define SMC_SET_TX_CFG(x) SMC_outl( x, ioaddr, TX_CFG ) +#define SMC_GET_HW_CFG() SMC_inl( ioaddr, HW_CFG ) +#define SMC_SET_HW_CFG(x) SMC_outl( x, ioaddr, HW_CFG ) +#define SMC_GET_RX_DP_CTRL() SMC_inl( ioaddr, RX_DP_CTRL ) +#define SMC_SET_RX_DP_CTRL(x) SMC_outl( x, ioaddr, RX_DP_CTRL ) +#define SMC_GET_PMT_CTRL() SMC_inl( ioaddr, PMT_CTRL ) +#define SMC_SET_PMT_CTRL(x) SMC_outl( x, ioaddr, PMT_CTRL ) +#define SMC_GET_GPIO_CFG() SMC_inl( ioaddr, GPIO_CFG ) +#define SMC_SET_GPIO_CFG(x) SMC_outl( x, ioaddr, GPIO_CFG ) +#define SMC_GET_RX_FIFO_INF() SMC_inl( ioaddr, RX_FIFO_INF ) +#define SMC_SET_RX_FIFO_INF(x) SMC_outl( x, ioaddr, RX_FIFO_INF ) +#define SMC_GET_TX_FIFO_INF() SMC_inl( ioaddr, TX_FIFO_INF ) +#define SMC_SET_TX_FIFO_INF(x) SMC_outl( x, ioaddr, TX_FIFO_INF ) +#define SMC_GET_GPT_CFG() SMC_inl( ioaddr, GPT_CFG ) +#define SMC_SET_GPT_CFG(x) SMC_outl( x, ioaddr, GPT_CFG ) +#define SMC_GET_RX_DROP() SMC_inl( ioaddr, RX_DROP ) +#define SMC_SET_RX_DROP(x) SMC_outl( x, ioaddr, RX_DROP ) +#define SMC_GET_MAC_CMD() SMC_inl( ioaddr, MAC_CSR_CMD ) +#define SMC_SET_MAC_CMD(x) SMC_outl( x, ioaddr, MAC_CSR_CMD ) +#define SMC_GET_MAC_DATA() SMC_inl( ioaddr, MAC_CSR_DATA ) +#define SMC_SET_MAC_DATA(x) SMC_outl( x, ioaddr, MAC_CSR_DATA ) +#define SMC_GET_AFC_CFG() SMC_inl( ioaddr, AFC_CFG ) +#define SMC_SET_AFC_CFG(x) SMC_outl( x, ioaddr, AFC_CFG ) +#define SMC_GET_E2P_CMD() SMC_inl( ioaddr, E2P_CMD ) +#define SMC_SET_E2P_CMD(x) SMC_outl( x, ioaddr, E2P_CMD ) +#define SMC_GET_E2P_DATA() SMC_inl( ioaddr, E2P_DATA ) +#define SMC_SET_E2P_DATA(x) SMC_outl( x, ioaddr, E2P_DATA ) + +/* MAC register read/write macros */ +#define SMC_GET_MAC_CSR(a,v) \ + do { \ + while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ | \ + MAC_CSR_CMD_R_NOT_W_ | (a) ); \ + while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + v = SMC_GET_MAC_DATA(); \ + } while (0) +#define SMC_SET_MAC_CSR(a,v) \ + do { \ + while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + SMC_SET_MAC_DATA(v); \ + SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ | (a) ); \ + while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + } while (0) +#define SMC_GET_MAC_CR(x) SMC_GET_MAC_CSR( MAC_CR, x ) +#define SMC_SET_MAC_CR(x) SMC_SET_MAC_CSR( MAC_CR, x ) +#define SMC_GET_ADDRH(x) SMC_GET_MAC_CSR( ADDRH, x ) +#define SMC_SET_ADDRH(x) SMC_SET_MAC_CSR( ADDRH, x ) +#define SMC_GET_ADDRL(x) SMC_GET_MAC_CSR( ADDRL, x ) +#define SMC_SET_ADDRL(x) SMC_SET_MAC_CSR( ADDRL, x ) +#define SMC_GET_HASHH(x) SMC_GET_MAC_CSR( HASHH, x ) +#define SMC_SET_HASHH(x) SMC_SET_MAC_CSR( HASHH, x ) +#define SMC_GET_HASHL(x) SMC_GET_MAC_CSR( HASHL, x ) +#define SMC_SET_HASHL(x) SMC_SET_MAC_CSR( HASHL, x ) +#define SMC_GET_MII_ACC(x) SMC_GET_MAC_CSR( MII_ACC, x ) +#define SMC_SET_MII_ACC(x) SMC_SET_MAC_CSR( MII_ACC, x ) +#define SMC_GET_MII_DATA(x) SMC_GET_MAC_CSR( MII_DATA, x ) +#define SMC_SET_MII_DATA(x) SMC_SET_MAC_CSR( MII_DATA, x ) +#define SMC_GET_FLOW(x) SMC_GET_MAC_CSR( FLOW, x ) +#define SMC_SET_FLOW(x) SMC_SET_MAC_CSR( FLOW, x ) +#define SMC_GET_VLAN1(x) SMC_GET_MAC_CSR( VLAN1, x ) +#define SMC_SET_VLAN1(x) SMC_SET_MAC_CSR( VLAN1, x ) +#define SMC_GET_VLAN2(x) SMC_GET_MAC_CSR( VLAN2, x ) +#define SMC_SET_VLAN2(x) SMC_SET_MAC_CSR( VLAN2, x ) +#define SMC_SET_WUFF(x) SMC_SET_MAC_CSR( WUFF, x ) +#define SMC_GET_WUCSR(x) SMC_GET_MAC_CSR( WUCSR, x ) +#define SMC_SET_WUCSR(x) SMC_SET_MAC_CSR( WUCSR, x ) + +/* PHY register read/write macros */ +#define SMC_GET_MII(a,phy,v) \ + do { \ + u32 __v; \ + do { \ + SMC_GET_MII_ACC(__v); \ + } while ( __v & MII_ACC_MII_BUSY_ ); \ + SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) | \ + MII_ACC_MII_BUSY_); \ + do { \ + SMC_GET_MII_ACC(__v); \ + } while ( __v & MII_ACC_MII_BUSY_ ); \ + SMC_GET_MII_DATA(v); \ + } while (0) +#define SMC_SET_MII(a,phy,v) \ + do { \ + u32 __v; \ + do { \ + SMC_GET_MII_ACC(__v); \ + } while ( __v & MII_ACC_MII_BUSY_ ); \ + SMC_SET_MII_DATA(v); \ + SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) | \ + MII_ACC_MII_BUSY_ | \ + MII_ACC_MII_WRITE_ ); \ + do { \ + SMC_GET_MII_ACC(__v); \ + } while ( __v & MII_ACC_MII_BUSY_ ); \ + } while (0) +#define SMC_GET_PHY_BMCR(phy,x) SMC_GET_MII( MII_BMCR, phy, x ) +#define SMC_SET_PHY_BMCR(phy,x) SMC_SET_MII( MII_BMCR, phy, x ) +#define SMC_GET_PHY_BMSR(phy,x) SMC_GET_MII( MII_BMSR, phy, x ) +#define SMC_GET_PHY_ID1(phy,x) SMC_GET_MII( MII_PHYSID1, phy, x ) +#define SMC_GET_PHY_ID2(phy,x) SMC_GET_MII( MII_PHYSID2, phy, x ) +#define SMC_GET_PHY_MII_ADV(phy,x) SMC_GET_MII( MII_ADVERTISE, phy, x ) +#define SMC_SET_PHY_MII_ADV(phy,x) SMC_SET_MII( MII_ADVERTISE, phy, x ) +#define SMC_GET_PHY_MII_LPA(phy,x) SMC_GET_MII( MII_LPA, phy, x ) +#define SMC_SET_PHY_MII_LPA(phy,x) SMC_SET_MII( MII_LPA, phy, x ) +#define SMC_GET_PHY_CTRL_STS(phy,x) SMC_GET_MII( PHY_MODE_CTRL_STS, phy, x ) +#define SMC_SET_PHY_CTRL_STS(phy,x) SMC_SET_MII( PHY_MODE_CTRL_STS, phy, x ) +#define SMC_GET_PHY_INT_SRC(phy,x) SMC_GET_MII( PHY_INT_SRC, phy, x ) +#define SMC_SET_PHY_INT_SRC(phy,x) SMC_SET_MII( PHY_INT_SRC, phy, x ) +#define SMC_GET_PHY_INT_MASK(phy,x) SMC_GET_MII( PHY_INT_MASK, phy, x ) +#define SMC_SET_PHY_INT_MASK(phy,x) SMC_SET_MII( PHY_INT_MASK, phy, x ) +#define SMC_GET_PHY_SPECIAL(phy,x) SMC_GET_MII( PHY_SPECIAL, phy, x ) + + + +/* Misc read/write macros */ + +#ifndef SMC_GET_MAC_ADDR +#define SMC_GET_MAC_ADDR(addr) \ + do { \ + unsigned int __v; \ + \ + SMC_GET_MAC_CSR(ADDRL, __v); \ + addr[0] = __v; addr[1] = __v >> 8; \ + addr[2] = __v >> 16; addr[3] = __v >> 24; \ + SMC_GET_MAC_CSR(ADDRH, __v); \ + addr[4] = __v; addr[5] = __v >> 8; \ + } while (0) +#endif + +#define SMC_SET_MAC_ADDR(addr) \ + do { \ + SMC_SET_MAC_CSR(ADDRL, \ + addr[0] | \ + (addr[1] << 8) | \ + (addr[2] << 16) | \ + (addr[3] << 24)); \ + SMC_SET_MAC_CSR(ADDRH, addr[4]|(addr[5] << 8));\ + } while (0) + + +#define SMC_WRITE_EEPROM_CMD(cmd, addr) \ + do { \ + while (SMC_GET_E2P_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + SMC_SET_MAC_CMD(MAC_CSR_CMD_R_NOT_W_ | a ); \ + while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + } while (0) + +#endif /* _SMC911X_H_ */ diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index f86697d..8b0321f 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -523,8 +523,7 @@ static int smc_wait_to_send_packet( stru length = skb->len; if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) { + if (skb_padto(skb, ETH_ZLEN)) { netif_wake_queue(dev); return 0; } @@ -732,12 +731,9 @@ static int ifport; struct net_device * __init smc_init(int unit) { struct net_device *dev = alloc_etherdev(sizeof(struct smc_local)); - static struct devlist *smcdev = smc_devlist; + struct devlist *smcdev = smc_devlist; int err = 0; -#ifndef NO_AUTOPROBE - smcdev = smc_devlist; -#endif if (!dev) return ERR_PTR(-ENODEV); @@ -1607,7 +1603,7 @@ MODULE_PARM_DESC(io, "SMC 99194 I/O base MODULE_PARM_DESC(irq, "SMC 99194 IRQ number"); MODULE_PARM_DESC(ifport, "SMC 99194 interface port (0-default, 1-TP, 2-AUI)"); -int init_module(void) +int __init init_module(void) { if (io == 0) printk(KERN_WARNING diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index e1be1af..bf77612 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -129,6 +129,24 @@ #define SMC_outb(v, a, r) writeb(v, (a) #define SMC_insb(a, r, p, l) readsb((a) + (r), p, (l)) #define SMC_outsb(a, r, p, l) writesb((a) + (r), p, (l)) +#elif defined(CONFIG_MACH_LOGICPD_PXA270) + +#define SMC_CAN_USE_8BIT 0 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_IO_SHIFT 0 +#define SMC_NOWAIT 1 +#define SMC_USE_PXA_DMA 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) + #elif defined(CONFIG_ARCH_INNOKOM) || \ defined(CONFIG_MACH_MAINSTONE) || \ defined(CONFIG_ARCH_PXA_IDP) || \ @@ -242,15 +260,17 @@ #define SMC_IRQ_FLAGS (0) #define RPC_LSA_DEFAULT RPC_LED_TX_RX #define RPC_LSB_DEFAULT RPC_LED_100_10 -#elif defined(CONFIG_MACH_LPD7A400) || defined(CONFIG_MACH_LPD7A404) +#elif defined(CONFIG_MACH_LPD79520) \ + || defined(CONFIG_MACH_LPD7A400) \ + || defined(CONFIG_MACH_LPD7A404) -/* The LPD7A40X_IOBARRIER is necessary to overcome a mismatch between - * the way that the CPU handles chip selects and the way that the SMC - * chip expects the chip select to operate. Refer to +/* The LPD7X_IOBARRIER is necessary to overcome a mismatch between the + * way that the CPU handles chip selects and the way that the SMC chip + * expects the chip select to operate. Refer to * Documentation/arm/Sharp-LH/IOBarrier for details. The read from - * IOBARRIER is a byte as a least-common denominator of possible - * regions to use as the barrier. It would be wasteful to read 32 - * bits from a byte oriented region. + * IOBARRIER is a byte, in order that we read the least-common + * denominator. It would be wasteful to read 32 bits from an 8-bit + * accessible region. * * There is no explicit protection against interrupts intervening * between the writew and the IOBARRIER. In SMC ISR there is a @@ -269,25 +289,35 @@ #define SMC_CAN_USE_8BIT 0 #define SMC_CAN_USE_16BIT 1 #define SMC_CAN_USE_32BIT 0 #define SMC_NOWAIT 0 -#define LPD7A40X_IOBARRIER readb (IOBARRIER_VIRT) +#define LPD7X_IOBARRIER readb (IOBARRIER_VIRT) -#define SMC_inw(a,r) readw ((void*) ((a) + (r))) -#define SMC_insw(a,r,p,l) readsw ((void*) ((a) + (r)), p, l) -#define SMC_outw(v,a,r) ({ writew ((v), (a) + (r)); LPD7A40X_IOBARRIER; }) +#define SMC_inw(a,r)\ + ({ unsigned short v = readw ((void*) ((a) + (r))); LPD7X_IOBARRIER; v; }) +#define SMC_outw(v,a,r) ({ writew ((v), (a) + (r)); LPD7X_IOBARRIER; }) -#define SMC_outsw LPD7A40X_SMC_outsw +#define SMC_insw LPD7_SMC_insw +static inline void LPD7_SMC_insw (unsigned char* a, int r, + unsigned char* p, int l) +{ + unsigned short* ps = (unsigned short*) p; + while (l-- > 0) { + *ps++ = readw (a + r); + LPD7X_IOBARRIER; + } +} -static inline void LPD7A40X_SMC_outsw(unsigned long a, int r, - unsigned char* p, int l) +#define SMC_outsw LPD7_SMC_outsw +static inline void LPD7_SMC_outsw (unsigned char* a, int r, + unsigned char* p, int l) { unsigned short* ps = (unsigned short*) p; while (l-- > 0) { writew (*ps++, a + r); - LPD7A40X_IOBARRIER; + LPD7X_IOBARRIER; } } -#define SMC_INTERRUPT_PREAMBLE LPD7A40X_IOBARRIER +#define SMC_INTERRUPT_PREAMBLE LPD7X_IOBARRIER #define RPC_LSA_DEFAULT RPC_LED_TX_RX #define RPC_LSB_DEFAULT RPC_LED_100_10 diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c index 90b818a..cab0dd9 100644 --- a/drivers/net/sonic.c +++ b/drivers/net/sonic.c @@ -231,8 +231,7 @@ static int sonic_send_packet(struct sk_b length = skb->len; if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 9b7805b..c158eed 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1349,8 +1349,7 @@ static int start_tx(struct sk_buff *skb, #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE) if (skb->ip_summed == CHECKSUM_HW) { - skb = skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK); - if (skb == NULL) + if (skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK)) return NETDEV_TX_OK; } #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */ diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index d4c0002..a2fad50 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -55,7 +55,7 @@ #endif /* sun3/60 addr/irq for the lance chip. If your sun is different, change this. */ #define LANCE_OBIO 0x120000 -#define LANCE_IRQ IRQ3 +#define LANCE_IRQ IRQ_AUTO_3 /* Debug level: * 0 = silent, print only serious errors diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index cfaf47c..7127f0f 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -72,8 +72,6 @@ #else #define DIRQ(x) #endif -static struct bigmac *root_bigmac_dev; - #define DEFAULT_JAMSIZE 4 /* Toe jam */ #define QEC_RESET_TRIES 200 @@ -491,7 +489,7 @@ static void bigmac_tcvr_init(struct bigm } } -static int bigmac_init(struct bigmac *, int); +static int bigmac_init_hw(struct bigmac *, int); static int try_next_permutation(struct bigmac *bp, void __iomem *tregs) { @@ -551,7 +549,7 @@ static void bigmac_timer(unsigned long d if (ret == -1) { printk(KERN_ERR "%s: Link down, cable problem?\n", bp->dev->name); - ret = bigmac_init(bp, 0); + ret = bigmac_init_hw(bp, 0); if (ret) { printk(KERN_ERR "%s: Error, cannot re-init the " "BigMAC.\n", bp->dev->name); @@ -621,7 +619,7 @@ static void bigmac_begin_auto_negotiatio add_timer(&bp->bigmac_timer); } -static int bigmac_init(struct bigmac *bp, int from_irq) +static int bigmac_init_hw(struct bigmac *bp, int from_irq) { void __iomem *gregs = bp->gregs; void __iomem *cregs = bp->creg; @@ -752,7 +750,7 @@ static void bigmac_is_medium_rare(struct } printk(" RESET\n"); - bigmac_init(bp, 1); + bigmac_init_hw(bp, 1); } /* BigMAC transmit complete service routines. */ @@ -926,7 +924,7 @@ static int bigmac_open(struct net_device return ret; } init_timer(&bp->bigmac_timer); - ret = bigmac_init(bp, 0); + ret = bigmac_init_hw(bp, 0); if (ret) free_irq(dev->irq, bp); return ret; @@ -950,7 +948,7 @@ static void bigmac_tx_timeout(struct net { struct bigmac *bp = (struct bigmac *) dev->priv; - bigmac_init(bp, 0); + bigmac_init_hw(bp, 0); netif_wake_queue(dev); } @@ -1104,6 +1102,8 @@ static int __init bigmac_ether_init(stru bp->qec_sdev = qec_sdev; bp->bigmac_sdev = qec_sdev->child; + SET_NETDEV_DEV(dev, &bp->bigmac_sdev->ofdev.dev); + spin_lock_init(&bp->lock); /* Verify the registers we expect, are actually there. */ @@ -1226,11 +1226,7 @@ static int __init bigmac_ether_init(stru goto fail_and_cleanup; } - /* Put us into the list of instances attached for later driver - * exit. - */ - bp->next_module = root_bigmac_dev; - root_bigmac_dev = bp; + dev_set_drvdata(&bp->bigmac_sdev->ofdev.dev, bp); printk(KERN_INFO "%s: BigMAC 100baseT Ethernet ", dev->name); for (i = 0; i < 6; i++) @@ -1266,69 +1262,68 @@ fail_and_cleanup: /* QEC can be the parent of either QuadEthernet or * a BigMAC. We want the latter. */ -static int __init bigmac_match(struct sbus_dev *sdev) +static int __devinit bigmac_sbus_probe(struct of_device *dev, const struct of_device_id *match) { - struct sbus_dev *child = sdev->child; + struct sbus_dev *sdev = to_sbus_device(&dev->dev); + struct device_node *dp = dev->node; - if (strcmp(sdev->prom_name, "qec") != 0) - return 0; + if (!strcmp(dp->name, "be")) + sdev = sdev->parent; - if (child == NULL) - return 0; - - if (strcmp(child->prom_name, "be") != 0) - return 0; - - return 1; + return bigmac_ether_init(sdev); } -static int __init bigmac_probe(void) +static int __devexit bigmac_sbus_remove(struct of_device *dev) { - struct sbus_bus *sbus; - struct sbus_dev *sdev = NULL; - static int called; - int cards = 0, v; - - root_bigmac_dev = NULL; - - if (called) - return -ENODEV; - called++; - - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if (bigmac_match(sdev)) { - cards++; - if ((v = bigmac_ether_init(sdev))) - return v; - } - } - } - if (!cards) - return -ENODEV; + struct bigmac *bp = dev_get_drvdata(&dev->dev); + struct net_device *net_dev = bp->dev; + + unregister_netdevice(net_dev); + + sbus_iounmap(bp->gregs, GLOB_REG_SIZE); + sbus_iounmap(bp->creg, CREG_REG_SIZE); + sbus_iounmap(bp->bregs, BMAC_REG_SIZE); + sbus_iounmap(bp->tregs, TCVR_REG_SIZE); + sbus_free_consistent(bp->bigmac_sdev, + PAGE_SIZE, + bp->bmac_block, + bp->bblock_dvma); + + free_netdev(net_dev); + + dev_set_drvdata(&dev->dev, NULL); + return 0; } -static void __exit bigmac_cleanup(void) -{ - while (root_bigmac_dev) { - struct bigmac *bp = root_bigmac_dev; - struct bigmac *bp_nxt = root_bigmac_dev->next_module; +static struct of_device_id bigmac_sbus_match[] = { + { + .name = "qec", + }, + { + .name = "be", + }, + {}, +}; - sbus_iounmap(bp->gregs, GLOB_REG_SIZE); - sbus_iounmap(bp->creg, CREG_REG_SIZE); - sbus_iounmap(bp->bregs, BMAC_REG_SIZE); - sbus_iounmap(bp->tregs, TCVR_REG_SIZE); - sbus_free_consistent(bp->bigmac_sdev, - PAGE_SIZE, - bp->bmac_block, - bp->bblock_dvma); +MODULE_DEVICE_TABLE(of, bigmac_sbus_match); - unregister_netdev(bp->dev); - free_netdev(bp->dev); - root_bigmac_dev = bp_nxt; - } +static struct of_platform_driver bigmac_sbus_driver = { + .name = "sunbmac", + .match_table = bigmac_sbus_match, + .probe = bigmac_sbus_probe, + .remove = __devexit_p(bigmac_sbus_remove), +}; + +static int __init bigmac_init(void) +{ + return of_register_driver(&bigmac_sbus_driver, &sbus_bus_type); +} + +static void __exit bigmac_exit(void) +{ + of_unregister_driver(&bigmac_sbus_driver); } -module_init(bigmac_probe); -module_exit(bigmac_cleanup); +module_init(bigmac_init); +module_exit(bigmac_exit); diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h index b0dbc51..b563d3c 100644 --- a/drivers/net/sunbmac.h +++ b/drivers/net/sunbmac.h @@ -332,7 +332,6 @@ struct bigmac { struct sbus_dev *qec_sdev; struct sbus_dev *bigmac_sdev; struct net_device *dev; - struct bigmac *next_module; }; /* We use this to acquire receive skb's that we can DMA directly into. */ diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 61eec46..f13b2a1 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -94,11 +94,13 @@ Version LK1.10 (Philippe De Muyter phdm@macqel.be): - Make 'unblock interface after Tx underrun' work + Version LK1.11 (Pedro Alejandro Lopez-Valencia palopezv at gmail.com): + - Add support for IC Plus Corporation IP100A chipset */ #define DRV_NAME "sundance" -#define DRV_VERSION "1.01+LK1.10" -#define DRV_RELDATE "28-Oct-2005" +#define DRV_VERSION "1.01+LK1.11" +#define DRV_RELDATE "14-Jun-2006" /* The user-configurable values. @@ -287,6 +289,7 @@ static struct pci_device_id sundance_pci {0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3}, {0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, {0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + {0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, {0,} }; MODULE_DEVICE_TABLE(pci, sundance_pci_tbl); @@ -305,6 +308,7 @@ static const struct pci_id_info pci_id_t {"D-Link DFE-530TXS FAST Ethernet Adapter"}, {"D-Link DL10050-based FAST Ethernet Adapter"}, {"Sundance Technology Alta"}, + {"IC Plus Corporation IP100A FAST Ethernet Adapter"}, {NULL,}, /* 0 terminated list. */ }; diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 38cd30c..5248670 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2880,17 +2880,20 @@ #endif #if defined(__sparc__) struct pci_dev *pdev = gp->pdev; struct pcidev_cookie *pcp = pdev->sysdata; - int node = -1; + int use_idprom = 1; if (pcp != NULL) { - node = pcp->prom_node; - if (prom_getproplen(node, "local-mac-address") == 6) - prom_getproperty(node, "local-mac-address", - dev->dev_addr, 6); - else - node = -1; + unsigned char *addr; + int len; + + addr = of_get_property(pcp->prom_node, "local-mac-address", + &len); + if (addr && len == 6) { + use_idprom = 0; + memcpy(dev->dev_addr, addr, 6); + } } - if (node == -1) + if (use_idprom) memcpy(dev->dev_addr, idprom->id_ethaddr, 6); #elif defined(CONFIG_PPC_PMAC) unsigned char *addr; diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c index b2ddd5e..9282b4b 100644 --- a/drivers/net/sungem_phy.c +++ b/drivers/net/sungem_phy.c @@ -345,9 +345,9 @@ static int bcm5421_enable_fiber(struct m static int bcm5461_enable_fiber(struct mii_phy* phy) { - phy_write(phy, MII_NCONFIG, 0xfc0c); - phy_write(phy, MII_BMCR, 0x4140); - phy_write(phy, MII_NCONFIG, 0xfc0b); + phy_write(phy, MII_NCONFIG, 0xfc0c); + phy_write(phy, MII_BMCR, 0x4140); + phy_write(phy, MII_NCONFIG, 0xfc0b); phy_write(phy, MII_BMCR, 0x0140); return 0; diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 9f046ca..c33ead3 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1,9 +1,9 @@ -/* $Id: sunhme.c,v 1.124 2002/01/15 06:25:51 davem Exp $ - * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, +/* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, * auto carrier detecting ethernet driver. Also known as the * "Happy Meal Ethernet" found on SunSwift SBUS cards. * - * Copyright (C) 1996, 1998, 1999, 2002, 2003 David S. Miller (davem@redhat.com) + * Copyright (C) 1996, 1998, 1999, 2002, 2003, + 2006 David S. Miller (davem@davemloft.net) * * Changes : * 2000/11/11 Willy Tarreau @@ -40,15 +40,13 @@ #include #include #include -#ifdef __sparc__ +#ifdef CONFIG_SPARC #include #include #include #include +#include #include -#ifndef __sparc_v9__ -#include -#endif #endif #include @@ -57,7 +55,7 @@ #include #ifdef CONFIG_PCI #include -#ifdef __sparc__ +#ifdef CONFIG_SPARC #include #endif #endif @@ -65,9 +63,9 @@ #endif #include "sunhme.h" #define DRV_NAME "sunhme" -#define DRV_VERSION "2.02" -#define DRV_RELDATE "8/24/03" -#define DRV_AUTHOR "David S. Miller (davem@redhat.com)" +#define DRV_VERSION "3.00" +#define DRV_RELDATE "June 23, 2006" +#define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" static char version[] = DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; @@ -83,8 +81,6 @@ static int macaddr[6]; module_param_array(macaddr, int, NULL, 0); MODULE_PARM_DESC(macaddr, "Happy Meal MAC address to set"); -static struct happy_meal *root_happy_dev; - #ifdef CONFIG_SBUS static struct quattro *qfe_sbus_list; #endif @@ -181,26 +177,6 @@ #define DEFAULT_IPG1 8 /* For all #define DEFAULT_IPG2 4 /* For all modes */ #define DEFAULT_JAMSIZE 4 /* Toe jam */ -#if defined(CONFIG_PCI) && defined(MODULE) -/* This happy_pci_ids is declared __initdata because it is only used - as an advisory to depmod. If this is ported to the new PCI interface - where it could be referenced at any time due to hot plugging, - the __initdata reference should be removed. */ - -static struct pci_device_id happymeal_pci_ids[] = { - { - .vendor = PCI_VENDOR_ID_SUN, - .device = PCI_DEVICE_ID_SUN_HAPPYMEAL, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); - -#endif - /* NOTE: In the descriptor writes one _must_ write the address * member _first_. The card must not be allowed to see * the updated descriptor flags until the address is @@ -1610,7 +1586,7 @@ static int happy_meal_init(struct happy_ HMD(("happy_meal_init: old[%08x] bursts<", hme_read32(hp, gregs + GREG_CFG))); -#ifndef __sparc__ +#ifndef CONFIG_SPARC /* It is always PCI and can handle 64byte bursts. */ hme_write32(hp, gregs + GREG_CFG, GREG_CFG_BURST64); #else @@ -1647,7 +1623,7 @@ #endif HMD(("XXX>")); hme_write32(hp, gregs + GREG_CFG, 0); } -#endif /* __sparc__ */ +#endif /* CONFIG_SPARC */ /* Turn off interrupts we do not want to hear. */ HMD((", enable global interrupts, ")); @@ -2221,13 +2197,8 @@ static int happy_meal_open(struct net_de if (request_irq(dev->irq, &happy_meal_interrupt, SA_SHIRQ, dev->name, (void *)dev)) { HMD(("EAGAIN\n")); -#ifdef __sparc__ - printk(KERN_ERR "happy_meal(SBUS): Can't order irq %s to go.\n", - __irq_itoa(dev->irq)); -#else printk(KERN_ERR "happy_meal(SBUS): Can't order irq %d to go.\n", dev->irq); -#endif return -EAGAIN; } @@ -2597,14 +2568,10 @@ static void __init quattro_apply_ranges( */ static struct quattro * __init quattro_sbus_find(struct sbus_dev *goal_sdev) { - struct sbus_bus *sbus; struct sbus_dev *sdev; struct quattro *qp; int i; - if (qfe_sbus_list == NULL) - goto found; - for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { for (i = 0, sdev = qp->quattro_dev; (sdev != NULL) && (i < 4); @@ -2613,17 +2580,7 @@ static struct quattro * __init quattro_s return qp; } } - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if (sdev == goal_sdev) - goto found; - } - } - /* Cannot find quattro parent, fail. */ - return NULL; - -found: qp = kmalloc(sizeof(struct quattro), GFP_KERNEL); if (qp != NULL) { int i; @@ -2660,6 +2617,17 @@ static void __init quattro_sbus_register } } } + +static void __devexit quattro_sbus_free_irqs(void) +{ + struct quattro *qp; + + for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { + struct sbus_dev *sdev = qp->quattro_dev; + + free_irq(sdev->irqs[0], qp); + } +} #endif /* CONFIG_SBUS */ #ifdef CONFIG_PCI @@ -2694,8 +2662,9 @@ static struct quattro * __init quattro_p #endif /* CONFIG_PCI */ #ifdef CONFIG_SBUS -static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) +static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) { + struct device_node *dp = sdev->ofdev.node; struct quattro *qp = NULL; struct happy_meal *hp; struct net_device *dev; @@ -2718,6 +2687,7 @@ static int __init happy_meal_sbus_init(s if (!dev) goto err_out; SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &sdev->ofdev.dev); if (hme_version_printed++ == 0) printk(KERN_INFO "%s", version); @@ -2733,13 +2703,16 @@ static int __init happy_meal_sbus_init(s for (i = 0; i < 6; i++) dev->dev_addr[i] = macaddr[i]; macaddr[5]++; - } else if (qfe_slot != -1 && - prom_getproplen(sdev->prom_node, - "local-mac-address") == 6) { - prom_getproperty(sdev->prom_node, "local-mac-address", - dev->dev_addr, 6); } else { - memcpy(dev->dev_addr, idprom->id_ethaddr, 6); + unsigned char *addr; + int len; + + addr = of_get_property(dp, "local-mac-address", &len); + + if (qfe_slot != -1 && addr && len == 6) + memcpy(dev->dev_addr, addr, 6); + else + memcpy(dev->dev_addr, idprom->id_ethaddr, 6); } hp = dev->priv; @@ -2750,9 +2723,8 @@ static int __init happy_meal_sbus_init(s err = -ENODEV; if (sdev->num_registers != 5) { - printk(KERN_ERR "happymeal: Device does not have 5 regs, it has %d.\n", + printk(KERN_ERR "happymeal: Device needs 5 regs, has %d.\n", sdev->num_registers); - printk(KERN_ERR "happymeal: Would you like that for here or to go?\n"); goto err_out_free_netdev; } @@ -2766,39 +2738,39 @@ static int __init happy_meal_sbus_init(s hp->gregs = sbus_ioremap(&sdev->resource[0], 0, GREG_REG_SIZE, "HME Global Regs"); if (!hp->gregs) { - printk(KERN_ERR "happymeal: Cannot map Happy Meal global registers.\n"); + printk(KERN_ERR "happymeal: Cannot map global registers.\n"); goto err_out_free_netdev; } hp->etxregs = sbus_ioremap(&sdev->resource[1], 0, ETX_REG_SIZE, "HME TX Regs"); if (!hp->etxregs) { - printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Transmit registers.\n"); + printk(KERN_ERR "happymeal: Cannot map MAC TX registers.\n"); goto err_out_iounmap; } hp->erxregs = sbus_ioremap(&sdev->resource[2], 0, ERX_REG_SIZE, "HME RX Regs"); if (!hp->erxregs) { - printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Receive registers.\n"); + printk(KERN_ERR "happymeal: Cannot map MAC RX registers.\n"); goto err_out_iounmap; } hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0, BMAC_REG_SIZE, "HME BIGMAC Regs"); if (!hp->bigmacregs) { - printk(KERN_ERR "happymeal: Cannot map Happy Meal BIGMAC registers.\n"); + printk(KERN_ERR "happymeal: Cannot map BIGMAC registers.\n"); goto err_out_iounmap; } hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0, TCVR_REG_SIZE, "HME Tranceiver Regs"); if (!hp->tcvregs) { - printk(KERN_ERR "happymeal: Cannot map Happy Meal Tranceiver registers.\n"); + printk(KERN_ERR "happymeal: Cannot map TCVR registers.\n"); goto err_out_iounmap; } - hp->hm_revision = prom_getintdefault(sdev->prom_node, "hm-rev", 0xff); + hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff); if (hp->hm_revision == 0xff) hp->hm_revision = 0xa0; @@ -2812,8 +2784,8 @@ static int __init happy_meal_sbus_init(s hp->happy_flags |= HFLAG_QUATTRO; /* Get the supported DVMA burst sizes from our Happy SBUS. */ - hp->happy_bursts = prom_getintdefault(sdev->bus->prom_node, - "burst-sizes", 0x00); + hp->happy_bursts = of_getintprop_default(sdev->bus->ofdev.node, + "burst-sizes", 0x00); hp->happy_block = sbus_alloc_consistent(hp->happy_dev, PAGE_SIZE, @@ -2876,6 +2848,8 @@ #endif goto err_out_free_consistent; } + dev_set_drvdata(&sdev->ofdev.dev, hp); + if (qfe_slot != -1) printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", dev->name, qfe_slot); @@ -2888,12 +2862,6 @@ #endif dev->dev_addr[i], i == 5 ? ' ' : ':'); printk("\n"); - /* We are home free at this point, link us in to the happy - * device list. - */ - hp->next_module = root_happy_dev; - root_happy_dev = hp; - return 0; err_out_free_consistent: @@ -2923,7 +2891,7 @@ err_out: #endif #ifdef CONFIG_PCI -#ifndef __sparc__ +#ifndef CONFIG_SPARC static int is_quattro_p(struct pci_dev *pdev) { struct pci_dev *busdev = pdev->bus->self; @@ -3011,14 +2979,14 @@ static void get_hme_mac_nonsparc(struct get_random_bytes(&dev_addr[3], 3); return; } -#endif /* !(__sparc__) */ +#endif /* !(CONFIG_SPARC) */ -static int __init happy_meal_pci_init(struct pci_dev *pdev) +static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct quattro *qp = NULL; -#ifdef __sparc__ +#ifdef CONFIG_SPARC struct pcidev_cookie *pcp; - int node; #endif struct happy_meal *hp; struct net_device *dev; @@ -3029,15 +2997,14 @@ #endif int err; /* Now make sure pci_dev cookie is there. */ -#ifdef __sparc__ +#ifdef CONFIG_SPARC pcp = pdev->sysdata; - if (pcp == NULL || pcp->prom_node == -1) { + if (pcp == NULL) { printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n"); return -ENODEV; } - node = pcp->prom_node; - prom_getstring(node, "name", prom_name, sizeof(prom_name)); + strcpy(prom_name, pcp->prom_node->name); #else if (is_quattro_p(pdev)) strcpy(prom_name, "SUNW,qfe"); @@ -3108,11 +3075,15 @@ #endif dev->dev_addr[i] = macaddr[i]; macaddr[5]++; } else { -#ifdef __sparc__ +#ifdef CONFIG_SPARC + unsigned char *addr; + int len; + if (qfe_slot != -1 && - prom_getproplen(node, "local-mac-address") == 6) { - prom_getproperty(node, "local-mac-address", - dev->dev_addr, 6); + (addr = of_get_property(pcp->prom_node, + "local-mac-address", &len)) != NULL + && len == 6) { + memcpy(dev->dev_addr, addr, 6); } else { memcpy(dev->dev_addr, idprom->id_ethaddr, 6); } @@ -3128,8 +3099,8 @@ #endif hp->bigmacregs = (hpreg_base + 0x6000UL); hp->tcvregs = (hpreg_base + 0x7000UL); -#ifdef __sparc__ - hp->hm_revision = prom_getintdefault(node, "hm-rev", 0xff); +#ifdef CONFIG_SPARC + hp->hm_revision = of_getintprop_default(pcp->prom_node, "hm-rev", 0xff); if (hp->hm_revision == 0xff) { unsigned char prev; @@ -3153,7 +3124,7 @@ #endif /* And of course, indicate this is PCI. */ hp->happy_flags |= HFLAG_PCI; -#ifdef __sparc__ +#ifdef CONFIG_SPARC /* Assume PCI happy meals can handle all burst sizes. */ hp->happy_bursts = DMA_BURSTBITS; #endif @@ -3216,6 +3187,8 @@ #endif goto err_out_iounmap; } + dev_set_drvdata(&pdev->dev, hp); + if (!qfe_slot) { struct pci_dev *qpdev = qp->quattro_dev; @@ -3245,12 +3218,6 @@ #endif printk("\n"); - /* We are home free at this point, link us in to the happy - * device list. - */ - hp->next_module = root_happy_dev; - root_happy_dev = hp; - return 0; err_out_iounmap: @@ -3268,136 +3235,146 @@ err_out_clear_quattro: err_out: return err; } -#endif -#ifdef CONFIG_SBUS -static int __init happy_meal_sbus_probe(void) +static void __devexit happy_meal_pci_remove(struct pci_dev *pdev) { - struct sbus_bus *sbus; - struct sbus_dev *sdev; - int cards = 0; - char model[128]; - - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - char *name = sdev->prom_name; - - if (!strcmp(name, "SUNW,hme")) { - cards++; - prom_getstring(sdev->prom_node, "model", - model, sizeof(model)); - if (!strcmp(model, "SUNW,sbus-qfe")) - happy_meal_sbus_init(sdev, 1); - else - happy_meal_sbus_init(sdev, 0); - } else if (!strcmp(name, "qfe") || - !strcmp(name, "SUNW,qfe")) { - cards++; - happy_meal_sbus_init(sdev, 1); - } - } - } - if (cards != 0) - quattro_sbus_register_irqs(); - return cards; + struct happy_meal *hp = dev_get_drvdata(&pdev->dev); + struct net_device *net_dev = hp->dev; + + unregister_netdev(net_dev); + + pci_free_consistent(hp->happy_dev, + PAGE_SIZE, + hp->happy_block, + hp->hblock_dvma); + iounmap(hp->gregs); + pci_release_regions(hp->happy_dev); + + free_netdev(net_dev); + + dev_set_drvdata(&pdev->dev, NULL); } -#endif -#ifdef CONFIG_PCI -static int __init happy_meal_pci_probe(void) +static struct pci_device_id happymeal_pci_ids[] = { + { + .vendor = PCI_VENDOR_ID_SUN, + .device = PCI_DEVICE_ID_SUN_HAPPYMEAL, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); + +static struct pci_driver hme_pci_driver = { + .name = "hme", + .id_table = happymeal_pci_ids, + .probe = happy_meal_pci_probe, + .remove = __devexit_p(happy_meal_pci_remove), +}; + +static int __init happy_meal_pci_init(void) { - struct pci_dev *pdev = NULL; - int cards = 0; + return pci_module_init(&hme_pci_driver); +} - while ((pdev = pci_find_device(PCI_VENDOR_ID_SUN, - PCI_DEVICE_ID_SUN_HAPPYMEAL, pdev)) != NULL) { - if (pci_enable_device(pdev)) - continue; - pci_set_master(pdev); - cards++; - happy_meal_pci_init(pdev); +static void happy_meal_pci_exit(void) +{ + pci_unregister_driver(&hme_pci_driver); + + while (qfe_pci_list) { + struct quattro *qfe = qfe_pci_list; + struct quattro *next = qfe->next; + + kfree(qfe); + + qfe_pci_list = next; } - return cards; } + #endif -static int __init happy_meal_probe(void) +#ifdef CONFIG_SBUS +static int __devinit hme_sbus_probe(struct of_device *dev, const struct of_device_id *match) { - static int called = 0; - int cards; + struct sbus_dev *sdev = to_sbus_device(&dev->dev); + struct device_node *dp = dev->node; + char *model = of_get_property(dp, "model", NULL); + int is_qfe = (match->data != NULL); - root_happy_dev = NULL; + if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe")) + is_qfe = 1; - if (called) - return -ENODEV; - called++; + return happy_meal_sbus_probe_one(sdev, is_qfe); +} + +static int __devexit hme_sbus_remove(struct of_device *dev) +{ + struct happy_meal *hp = dev_get_drvdata(&dev->dev); + struct net_device *net_dev = hp->dev; + + unregister_netdevice(net_dev); + + /* XXX qfe parent interrupt... */ + + sbus_iounmap(hp->gregs, GREG_REG_SIZE); + sbus_iounmap(hp->etxregs, ETX_REG_SIZE); + sbus_iounmap(hp->erxregs, ERX_REG_SIZE); + sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); + sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); + sbus_free_consistent(hp->happy_dev, + PAGE_SIZE, + hp->happy_block, + hp->hblock_dvma); + + free_netdev(net_dev); + + dev_set_drvdata(&dev->dev, NULL); - cards = 0; -#ifdef CONFIG_SBUS - cards += happy_meal_sbus_probe(); -#endif -#ifdef CONFIG_PCI - cards += happy_meal_pci_probe(); -#endif - if (!cards) - return -ENODEV; return 0; } +static struct of_device_id hme_sbus_match[] = { + { + .name = "SUNW,hme", + }, + { + .name = "SUNW,qfe", + .data = (void *) 1, + }, + { + .name = "qfe", + .data = (void *) 1, + }, + {}, +}; -static void __exit happy_meal_cleanup_module(void) -{ -#ifdef CONFIG_SBUS - struct quattro *last_seen_qfe = NULL; -#endif +MODULE_DEVICE_TABLE(of, hme_sbus_match); - while (root_happy_dev) { - struct happy_meal *hp = root_happy_dev; - struct happy_meal *next = root_happy_dev->next_module; - struct net_device *dev = hp->dev; +static struct of_platform_driver hme_sbus_driver = { + .name = "hme", + .match_table = hme_sbus_match, + .probe = hme_sbus_probe, + .remove = __devexit_p(hme_sbus_remove), +}; - /* Unregister netdev before unmapping registers as this - * call can end up trying to access those registers. - */ - unregister_netdev(dev); +static int __init happy_meal_sbus_init(void) +{ + int err; -#ifdef CONFIG_SBUS - if (!(hp->happy_flags & HFLAG_PCI)) { - if (hp->happy_flags & HFLAG_QUATTRO) { - if (hp->qfe_parent != last_seen_qfe) { - free_irq(dev->irq, hp->qfe_parent); - last_seen_qfe = hp->qfe_parent; - } - } + err = of_register_driver(&hme_sbus_driver, &sbus_bus_type); + if (!err) + quattro_sbus_register_irqs(); - sbus_iounmap(hp->gregs, GREG_REG_SIZE); - sbus_iounmap(hp->etxregs, ETX_REG_SIZE); - sbus_iounmap(hp->erxregs, ERX_REG_SIZE); - sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); - sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); - sbus_free_consistent(hp->happy_dev, - PAGE_SIZE, - hp->happy_block, - hp->hblock_dvma); - } -#endif -#ifdef CONFIG_PCI - if ((hp->happy_flags & HFLAG_PCI)) { - pci_free_consistent(hp->happy_dev, - PAGE_SIZE, - hp->happy_block, - hp->hblock_dvma); - iounmap(hp->gregs); - pci_release_regions(hp->happy_dev); - } -#endif - free_netdev(dev); + return err; +} - root_happy_dev = next; - } +static void happy_meal_sbus_exit(void) +{ + of_unregister_driver(&hme_sbus_driver); + quattro_sbus_free_irqs(); - /* Now cleanup the quattro lists. */ -#ifdef CONFIG_SBUS while (qfe_sbus_list) { struct quattro *qfe = qfe_sbus_list; struct quattro *next = qfe->next; @@ -3406,18 +3383,39 @@ #ifdef CONFIG_SBUS qfe_sbus_list = next; } +} #endif -#ifdef CONFIG_PCI - while (qfe_pci_list) { - struct quattro *qfe = qfe_pci_list; - struct quattro *next = qfe->next; - kfree(qfe); +static int __init happy_meal_probe(void) +{ + int err = 0; - qfe_pci_list = next; +#ifdef CONFIG_SBUS + err = happy_meal_sbus_init(); +#endif +#ifdef CONFIG_PCI + if (!err) { + err = happy_meal_pci_init(); +#ifdef CONFIG_SBUS + if (err) + happy_meal_sbus_exit(); +#endif } #endif + + return err; +} + + +static void __exit happy_meal_exit(void) +{ +#ifdef CONFIG_SBUS + happy_meal_sbus_exit(); +#endif +#ifdef CONFIG_PCI + happy_meal_pci_exit(); +#endif } module_init(happy_meal_probe); -module_exit(happy_meal_cleanup_module); +module_exit(happy_meal_exit); diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h index 34e9f95..9b7ccae 100644 --- a/drivers/net/sunhme.h +++ b/drivers/net/sunhme.h @@ -461,7 +461,6 @@ #endif struct net_device *dev; /* Backpointer */ struct quattro *qfe_parent; /* For Quattro cards */ int qfe_ent; /* Which instance on quattro */ - struct happy_meal *next_module; }; /* Here are the happy flags. */ diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index b7d87d4..2c239ab 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -266,7 +266,6 @@ struct lance_private { char *name; dma_addr_t init_block_dvma; struct net_device *dev; /* Backpointer */ - struct lance_private *next_module; struct sbus_dev *sdev; struct timer_list multicast_timer; }; @@ -298,8 +297,6 @@ int sparc_lance_debug = 2; #define LANCE_ADDR(x) ((long)(x) & ~0xff000000) -static struct lance_private *root_lance_dev; - /* Load the CSR registers */ static void load_csrs(struct lance_private *lp) { @@ -936,7 +933,7 @@ static int lance_open(struct net_device if (request_irq(dev->irq, &lance_interrupt, SA_SHIRQ, lancestr, (void *) dev)) { - printk(KERN_ERR "Lance: Can't get irq %s\n", __irq_itoa(dev->irq)); + printk(KERN_ERR "Lance: Can't get irq %d\n", dev->irq); return -EAGAIN; } @@ -1327,9 +1324,9 @@ static struct ethtool_ops sparc_lance_et .get_link = sparc_lance_get_link, }; -static int __init sparc_lance_init(struct sbus_dev *sdev, - struct sbus_dma *ledma, - struct sbus_dev *lebuffer) +static int __init sparc_lance_probe_one(struct sbus_dev *sdev, + struct sbus_dma *ledma, + struct sbus_dev *lebuffer) { static unsigned version_printed; struct net_device *dev; @@ -1473,6 +1470,7 @@ no_link_test: lp->dev = dev; SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &sdev->ofdev.dev); dev->open = &lance_open; dev->stop = &lance_close; dev->hard_start_xmit = &lance_start_xmit; @@ -1500,8 +1498,7 @@ no_link_test: goto fail; } - lp->next_module = root_lance_dev; - root_lance_dev = lp; + dev_set_drvdata(&sdev->ofdev.dev, lp); printk(KERN_INFO "%s: LANCE ", dev->name); @@ -1536,88 +1533,112 @@ #include #include /* Find all the lance cards on the system and initialize them */ -static int __init sparc_lance_probe(void) +static struct sbus_dev sun4_sdev; +static int __init sparc_lance_init(void) { - static struct sbus_dev sdev; - static int called; - - root_lance_dev = NULL; - - if (called) - return -ENODEV; - called++; - if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) || (idprom->id_machtype == (SM_SUN4|SM_4_470))) { - memset(&sdev, 0, sizeof(sdev)); - sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; - sdev.irqs[0] = 6; - return sparc_lance_init(&sdev, NULL, NULL); + memset(&sun4_sdev, 0, sizeof(sdev)); + sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; + sun4_sdev.irqs[0] = 6; + return sparc_lance_probe_one(&sun4_sdev, NULL, NULL); } return -ENODEV; } -#else /* !CONFIG_SUN4 */ - -/* Find all the lance cards on the system and initialize them */ -static int __init sparc_lance_probe(void) +static int __exit sunlance_sun4_remove(void) { - struct sbus_bus *bus; - struct sbus_dev *sdev = NULL; - struct sbus_dma *ledma = NULL; - static int called; - int cards = 0, v; - - root_lance_dev = NULL; - - if (called) - return -ENODEV; - called++; - - for_each_sbus (bus) { - for_each_sbusdev (sdev, bus) { - if (strcmp(sdev->prom_name, "le") == 0) { - cards++; - if ((v = sparc_lance_init(sdev, NULL, NULL))) - return v; - continue; - } - if (strcmp(sdev->prom_name, "ledma") == 0) { - cards++; - ledma = find_ledma(sdev); - if ((v = sparc_lance_init(sdev->child, - ledma, NULL))) - return v; - continue; - } - if (strcmp(sdev->prom_name, "lebuffer") == 0){ - cards++; - if ((v = sparc_lance_init(sdev->child, - NULL, sdev))) - return v; - continue; - } - } /* for each sbusdev */ - } /* for each sbus */ - if (!cards) - return -ENODEV; + struct lance_private *lp = dev_get_drvdata(&sun4_sdev->dev); + struct net_device *net_dev = lp->dev; + + unregister_netdevice(net_dev); + + lance_free_hwresources(root_lance_dev); + + free_netdev(net_dev); + + dev_set_drvdata(&sun4_sdev->dev, NULL); + return 0; } -#endif /* !CONFIG_SUN4 */ -static void __exit sparc_lance_cleanup(void) +#else /* !CONFIG_SUN4 */ + +static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match) { - struct lance_private *lp; + struct sbus_dev *sdev = to_sbus_device(&dev->dev); + struct device_node *dp = dev->node; + int err; + + if (!strcmp(dp->name, "le")) { + err = sparc_lance_probe_one(sdev, NULL, NULL); + } else if (!strcmp(dp->name, "ledma")) { + struct sbus_dma *ledma = find_ledma(sdev); - while (root_lance_dev) { - lp = root_lance_dev->next_module; + err = sparc_lance_probe_one(sdev->child, ledma, NULL); + } else { + BUG_ON(strcmp(dp->name, "lebuffer")); - unregister_netdev(root_lance_dev->dev); - lance_free_hwresources(root_lance_dev); - free_netdev(root_lance_dev->dev); - root_lance_dev = lp; + err = sparc_lance_probe_one(sdev->child, NULL, sdev); } + + return err; +} + +static int __devexit sunlance_sbus_remove(struct of_device *dev) +{ + struct lance_private *lp = dev_get_drvdata(&dev->dev); + struct net_device *net_dev = lp->dev; + + unregister_netdevice(net_dev); + + lance_free_hwresources(lp); + + free_netdev(net_dev); + + dev_set_drvdata(&dev->dev, NULL); + + return 0; +} + +static struct of_device_id sunlance_sbus_match[] = { + { + .name = "le", + }, + { + .name = "ledma", + }, + { + .name = "lebuffer", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, sunlance_sbus_match); + +static struct of_platform_driver sunlance_sbus_driver = { + .name = "sunlance", + .match_table = sunlance_sbus_match, + .probe = sunlance_sbus_probe, + .remove = __devexit_p(sunlance_sbus_remove), +}; + + +/* Find all the lance cards on the system and initialize them */ +static int __init sparc_lance_init(void) +{ + return of_register_driver(&sunlance_sbus_driver, &sbus_bus_type); +} +#endif /* !CONFIG_SUN4 */ + +static void __exit sparc_lance_exit(void) +{ +#ifdef CONFIG_SUN4 + sunlance_sun4_remove(); +#else + of_unregister_driver(&sunlance_sbus_driver); +#endif } -module_init(sparc_lance_probe); -module_exit(sparc_lance_cleanup); +module_init(sparc_lance_init); +module_exit(sparc_lance_exit); diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 1f2323b..9da6d5b 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -1,10 +1,9 @@ -/* $Id: sunqe.c,v 1.55 2002/01/15 06:48:55 davem Exp $ - * sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver. +/* sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver. * Once again I am out to prove that every ethernet * controller out there can be most efficiently programmed * if you make it look like a LANCE. * - * Copyright (C) 1996, 1999, 2003 David S. Miller (davem@redhat.com) + * Copyright (C) 1996, 1999, 2003, 2006 David S. Miller (davem@davemloft.net) */ #include @@ -41,9 +40,9 @@ #include #include "sunqe.h" #define DRV_NAME "sunqe" -#define DRV_VERSION "3.0" -#define DRV_RELDATE "8/24/03" -#define DRV_AUTHOR "David S. Miller (davem@redhat.com)" +#define DRV_VERSION "4.0" +#define DRV_RELDATE "June 23, 2006" +#define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" static char version[] = DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; @@ -755,298 +754,269 @@ static inline void qec_init_once(struct qecp->gregs + GLOB_RSIZE); } -/* Four QE's per QEC card. */ -static int __init qec_ether_init(struct net_device *dev, struct sbus_dev *sdev) +static u8 __init qec_get_burst(struct device_node *dp) { - static unsigned version_printed; - struct net_device *qe_devs[4]; - struct sunqe *qeps[4]; - struct sbus_dev *qesdevs[4]; - struct sbus_dev *child; - struct sunqec *qecp = NULL; u8 bsizes, bsizes_more; - int i, j, res = -ENOMEM; - for (i = 0; i < 4; i++) { - qe_devs[i] = alloc_etherdev(sizeof(struct sunqe)); - if (!qe_devs[i]) - goto out; - } + /* Find and set the burst sizes for the QEC, since it + * does the actual dma for all 4 channels. + */ + bsizes = of_getintprop_default(dp, "burst-sizes", 0xff); + bsizes &= 0xff; + bsizes_more = of_getintprop_default(dp->parent, "burst-sizes", 0xff); - if (version_printed++ == 0) - printk(KERN_INFO "%s", version); + if (bsizes_more != 0xff) + bsizes &= bsizes_more; + if (bsizes == 0xff || (bsizes & DMA_BURST16) == 0 || + (bsizes & DMA_BURST32)==0) + bsizes = (DMA_BURST32 - 1); - for (i = 0; i < 4; i++) { - qeps[i] = (struct sunqe *) qe_devs[i]->priv; - for (j = 0; j < 6; j++) - qe_devs[i]->dev_addr[j] = idprom->id_ethaddr[j]; - qeps[i]->channel = i; - spin_lock_init(&qeps[i]->lock); - } + return bsizes; +} - qecp = kmalloc(sizeof(struct sunqec), GFP_KERNEL); - if (qecp == NULL) - goto out1; - qecp->qec_sdev = sdev; +static struct sunqec * __init get_qec(struct sbus_dev *child_sdev) +{ + struct sbus_dev *qec_sdev = child_sdev->parent; + struct sunqec *qecp; - for (i = 0; i < 4; i++) { - qecp->qes[i] = qeps[i]; - qeps[i]->dev = qe_devs[i]; - qeps[i]->parent = qecp; + for (qecp = root_qec_dev; qecp; qecp = qecp->next_module) { + if (qecp->qec_sdev == qec_sdev) + break; } + if (!qecp) { + qecp = kzalloc(sizeof(struct sunqec), GFP_KERNEL); + if (qecp) { + u32 ctrl; + + qecp->qec_sdev = qec_sdev; + qecp->gregs = sbus_ioremap(&qec_sdev->resource[0], 0, + GLOB_REG_SIZE, + "QEC Global Registers"); + if (!qecp->gregs) + goto fail; + + /* Make sure the QEC is in MACE mode. */ + ctrl = sbus_readl(qecp->gregs + GLOB_CTRL); + ctrl &= 0xf0000000; + if (ctrl != GLOB_CTRL_MMODE) { + printk(KERN_ERR "qec: Not in MACE mode!\n"); + goto fail; + } - res = -ENODEV; + if (qec_global_reset(qecp->gregs)) + goto fail; - for (i = 0, child = sdev->child; i < 4; i++, child = child->next) { - /* Link in channel */ - j = prom_getintdefault(child->prom_node, "channel#", -1); - if (j == -1) - goto out2; - qesdevs[j] = child; - } + qecp->qec_bursts = qec_get_burst(qec_sdev->ofdev.node); - for (i = 0; i < 4; i++) - qeps[i]->qe_sdev = qesdevs[i]; + qec_init_once(qecp, qec_sdev); - /* Now map in the registers, QEC globals first. */ - qecp->gregs = sbus_ioremap(&sdev->resource[0], 0, - GLOB_REG_SIZE, "QEC Global Registers"); - if (!qecp->gregs) { - printk(KERN_ERR "QuadEther: Cannot map QEC global registers.\n"); - goto out2; - } + if (request_irq(qec_sdev->irqs[0], &qec_interrupt, + SA_SHIRQ, "qec", (void *) qecp)) { + printk(KERN_ERR "qec: Can't register irq.\n"); + goto fail; + } - /* Make sure the QEC is in MACE mode. */ - if ((sbus_readl(qecp->gregs + GLOB_CTRL) & 0xf0000000) != GLOB_CTRL_MMODE) { - printk(KERN_ERR "QuadEther: AIEEE, QEC is not in MACE mode!\n"); - goto out3; + qecp->next_module = root_qec_dev; + root_qec_dev = qecp; + } } - /* Reset the QEC. */ - if (qec_global_reset(qecp->gregs)) - goto out3; + return qecp; - /* Find and set the burst sizes for the QEC, since it does - * the actual dma for all 4 channels. - */ - bsizes = prom_getintdefault(sdev->prom_node, "burst-sizes", 0xff); - bsizes &= 0xff; - bsizes_more = prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff); +fail: + if (qecp->gregs) + sbus_iounmap(qecp->gregs, GLOB_REG_SIZE); + kfree(qecp); + return NULL; +} - if (bsizes_more != 0xff) - bsizes &= bsizes_more; - if (bsizes == 0xff || (bsizes & DMA_BURST16) == 0 || - (bsizes & DMA_BURST32)==0) - bsizes = (DMA_BURST32 - 1); +static int __init qec_ether_init(struct sbus_dev *sdev) +{ + static unsigned version_printed; + struct net_device *dev; + struct sunqe *qe; + struct sunqec *qecp; + int i, res; - qecp->qec_bursts = bsizes; + if (version_printed++ == 0) + printk(KERN_INFO "%s", version); - /* Perform one time QEC initialization, we never touch the QEC - * globals again after this. - */ - qec_init_once(qecp, sdev); - - for (i = 0; i < 4; i++) { - struct sunqe *qe = qeps[i]; - /* Map in QEC per-channel control registers. */ - qe->qcregs = sbus_ioremap(&qe->qe_sdev->resource[0], 0, - CREG_REG_SIZE, "QEC Channel Registers"); - if (!qe->qcregs) { - printk(KERN_ERR "QuadEther: Cannot map QE %d's channel registers.\n", i); - goto out4; - } + dev = alloc_etherdev(sizeof(struct sunqe)); + if (!dev) + return -ENOMEM; - /* Map in per-channel AMD MACE registers. */ - qe->mregs = sbus_ioremap(&qe->qe_sdev->resource[1], 0, - MREGS_REG_SIZE, "QE MACE Registers"); - if (!qe->mregs) { - printk(KERN_ERR "QuadEther: Cannot map QE %d's MACE registers.\n", i); - goto out4; - } + qe = netdev_priv(dev); - qe->qe_block = sbus_alloc_consistent(qe->qe_sdev, - PAGE_SIZE, - &qe->qblock_dvma); - qe->buffers = sbus_alloc_consistent(qe->qe_sdev, - sizeof(struct sunqe_buffers), - &qe->buffers_dvma); - if (qe->qe_block == NULL || qe->qblock_dvma == 0 || - qe->buffers == NULL || qe->buffers_dvma == 0) { - goto out4; + i = of_getintprop_default(sdev->ofdev.node, "channel#", -1); + if (i == -1) { + struct sbus_dev *td = sdev->parent->child; + i = 0; + while (td != sdev) { + td = td->next; + i++; } - - /* Stop this QE. */ - qe_stop(qe); } + qe->channel = i; + spin_lock_init(&qe->lock); + + res = -ENODEV; + qecp = get_qec(sdev); + if (!qecp) + goto fail; - for (i = 0; i < 4; i++) { - SET_MODULE_OWNER(qe_devs[i]); - qe_devs[i]->open = qe_open; - qe_devs[i]->stop = qe_close; - qe_devs[i]->hard_start_xmit = qe_start_xmit; - qe_devs[i]->get_stats = qe_get_stats; - qe_devs[i]->set_multicast_list = qe_set_multicast; - qe_devs[i]->tx_timeout = qe_tx_timeout; - qe_devs[i]->watchdog_timeo = 5*HZ; - qe_devs[i]->irq = sdev->irqs[0]; - qe_devs[i]->dma = 0; - qe_devs[i]->ethtool_ops = &qe_ethtool_ops; - } + qecp->qes[qe->channel] = qe; + qe->dev = dev; + qe->parent = qecp; + qe->qe_sdev = sdev; - /* QEC receives interrupts from each QE, then it sends the actual - * IRQ to the cpu itself. Since QEC is the single point of - * interrupt for all QE channels we register the IRQ handler - * for it now. - */ - if (request_irq(sdev->irqs[0], &qec_interrupt, - SA_SHIRQ, "QuadEther", (void *) qecp)) { - printk(KERN_ERR "QuadEther: Can't register QEC master irq handler.\n"); - res = -EAGAIN; - goto out4; + res = -ENOMEM; + qe->qcregs = sbus_ioremap(&qe->qe_sdev->resource[0], 0, + CREG_REG_SIZE, "QEC Channel Registers"); + if (!qe->qcregs) { + printk(KERN_ERR "qe: Cannot map channel registers.\n"); + goto fail; } - for (i = 0; i < 4; i++) { - if (register_netdev(qe_devs[i]) != 0) - goto out5; + qe->mregs = sbus_ioremap(&qe->qe_sdev->resource[1], 0, + MREGS_REG_SIZE, "QE MACE Registers"); + if (!qe->mregs) { + printk(KERN_ERR "qe: Cannot map MACE registers.\n"); + goto fail; } - /* Report the QE channels. */ - for (i = 0; i < 4; i++) { - printk(KERN_INFO "%s: QuadEthernet channel[%d] ", qe_devs[i]->name, i); - for (j = 0; j < 6; j++) - printk ("%2.2x%c", - qe_devs[i]->dev_addr[j], - j == 5 ? ' ': ':'); - printk("\n"); - } + qe->qe_block = sbus_alloc_consistent(qe->qe_sdev, + PAGE_SIZE, + &qe->qblock_dvma); + qe->buffers = sbus_alloc_consistent(qe->qe_sdev, + sizeof(struct sunqe_buffers), + &qe->buffers_dvma); + if (qe->qe_block == NULL || qe->qblock_dvma == 0 || + qe->buffers == NULL || qe->buffers_dvma == 0) + goto fail; + + /* Stop this QE. */ + qe_stop(qe); + + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &sdev->ofdev.dev); + + dev->open = qe_open; + dev->stop = qe_close; + dev->hard_start_xmit = qe_start_xmit; + dev->get_stats = qe_get_stats; + dev->set_multicast_list = qe_set_multicast; + dev->tx_timeout = qe_tx_timeout; + dev->watchdog_timeo = 5*HZ; + dev->irq = sdev->irqs[0]; + dev->dma = 0; + dev->ethtool_ops = &qe_ethtool_ops; + + res = register_netdev(dev); + if (res) + goto fail; + + dev_set_drvdata(&sdev->ofdev.dev, qe); + + printk(KERN_INFO "%s: qe channel[%d] ", dev->name, qe->channel); + for (i = 0; i < 6; i++) + printk ("%2.2x%c", + dev->dev_addr[i], + i == 5 ? ' ': ':'); + printk("\n"); - /* We are home free at this point, link the qe's into - * the master list for later driver exit. - */ - qecp->next_module = root_qec_dev; - root_qec_dev = qecp; return 0; -out5: - while (i--) - unregister_netdev(qe_devs[i]); - free_irq(sdev->irqs[0], (void *)qecp); -out4: - for (i = 0; i < 4; i++) { - struct sunqe *qe = (struct sunqe *)qe_devs[i]->priv; - - if (qe->qcregs) - sbus_iounmap(qe->qcregs, CREG_REG_SIZE); - if (qe->mregs) - sbus_iounmap(qe->mregs, MREGS_REG_SIZE); - if (qe->qe_block) - sbus_free_consistent(qe->qe_sdev, - PAGE_SIZE, - qe->qe_block, - qe->qblock_dvma); - if (qe->buffers) - sbus_free_consistent(qe->qe_sdev, - sizeof(struct sunqe_buffers), - qe->buffers, - qe->buffers_dvma); - } -out3: - sbus_iounmap(qecp->gregs, GLOB_REG_SIZE); -out2: - kfree(qecp); -out1: - i = 4; -out: - while (i--) - free_netdev(qe_devs[i]); +fail: + if (qe->qcregs) + sbus_iounmap(qe->qcregs, CREG_REG_SIZE); + if (qe->mregs) + sbus_iounmap(qe->mregs, MREGS_REG_SIZE); + if (qe->qe_block) + sbus_free_consistent(qe->qe_sdev, + PAGE_SIZE, + qe->qe_block, + qe->qblock_dvma); + if (qe->buffers) + sbus_free_consistent(qe->qe_sdev, + sizeof(struct sunqe_buffers), + qe->buffers, + qe->buffers_dvma); + + free_netdev(dev); + return res; } -static int __init qec_match(struct sbus_dev *sdev) +static int __devinit qec_sbus_probe(struct of_device *dev, const struct of_device_id *match) { - struct sbus_dev *sibling; - int i; - - if (strcmp(sdev->prom_name, "qec") != 0) - return 0; + struct sbus_dev *sdev = to_sbus_device(&dev->dev); - /* QEC can be parent of either QuadEthernet or BigMAC - * children. Do not confuse this with qfe/SUNW,qfe - * which is a quad-happymeal card and handled by - * a different driver. - */ - sibling = sdev->child; - for (i = 0; i < 4; i++) { - if (sibling == NULL) - return 0; - if (strcmp(sibling->prom_name, "qe") != 0) - return 0; - sibling = sibling->next; - } - return 1; + return qec_ether_init(sdev); } -static int __init qec_probe(void) +static int __devexit qec_sbus_remove(struct of_device *dev) { - struct net_device *dev = NULL; - struct sbus_bus *bus; - struct sbus_dev *sdev = NULL; - static int called; - int cards = 0, v; - - root_qec_dev = NULL; - - if (called) - return -ENODEV; - called++; - - for_each_sbus(bus) { - for_each_sbusdev(sdev, bus) { - if (cards) - dev = NULL; - - if (qec_match(sdev)) { - cards++; - if ((v = qec_ether_init(dev, sdev))) - return v; - } - } - } - if (!cards) - return -ENODEV; + struct sunqe *qp = dev_get_drvdata(&dev->dev); + struct net_device *net_dev = qp->dev; + + unregister_netdevice(net_dev); + + sbus_iounmap(qp->qcregs, CREG_REG_SIZE); + sbus_iounmap(qp->mregs, MREGS_REG_SIZE); + sbus_free_consistent(qp->qe_sdev, + PAGE_SIZE, + qp->qe_block, + qp->qblock_dvma); + sbus_free_consistent(qp->qe_sdev, + sizeof(struct sunqe_buffers), + qp->buffers, + qp->buffers_dvma); + + free_netdev(net_dev); + + dev_set_drvdata(&dev->dev, NULL); + return 0; } -static void __exit qec_cleanup(void) +static struct of_device_id qec_sbus_match[] = { + { + .name = "qe", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, qec_sbus_match); + +static struct of_platform_driver qec_sbus_driver = { + .name = "qec", + .match_table = qec_sbus_match, + .probe = qec_sbus_probe, + .remove = __devexit_p(qec_sbus_remove), +}; + +static int __init qec_init(void) +{ + return of_register_driver(&qec_sbus_driver, &sbus_bus_type); +} + +static void __exit qec_exit(void) { - struct sunqec *next_qec; - int i; + of_unregister_driver(&qec_sbus_driver); while (root_qec_dev) { - next_qec = root_qec_dev->next_module; - - /* Release all four QE channels, then the QEC itself. */ - for (i = 0; i < 4; i++) { - unregister_netdev(root_qec_dev->qes[i]->dev); - sbus_iounmap(root_qec_dev->qes[i]->qcregs, CREG_REG_SIZE); - sbus_iounmap(root_qec_dev->qes[i]->mregs, MREGS_REG_SIZE); - sbus_free_consistent(root_qec_dev->qes[i]->qe_sdev, - PAGE_SIZE, - root_qec_dev->qes[i]->qe_block, - root_qec_dev->qes[i]->qblock_dvma); - sbus_free_consistent(root_qec_dev->qes[i]->qe_sdev, - sizeof(struct sunqe_buffers), - root_qec_dev->qes[i]->buffers, - root_qec_dev->qes[i]->buffers_dvma); - free_netdev(root_qec_dev->qes[i]->dev); - } - free_irq(root_qec_dev->qec_sdev->irqs[0], (void *)root_qec_dev); + struct sunqec *next = root_qec_dev->next_module; + + free_irq(root_qec_dev->qec_sdev->irqs[0], + (void *) root_qec_dev); sbus_iounmap(root_qec_dev->gregs, GLOB_REG_SIZE); + kfree(root_qec_dev); - root_qec_dev = next_qec; + + root_qec_dev = next; } } -module_init(qec_probe); -module_exit(qec_cleanup); +module_init(qec_init); +module_exit(qec_exit); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 862c226..35f9316 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #include "tg3.h" #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.59" -#define DRV_MODULE_RELDATE "June 8, 2006" +#define DRV_MODULE_VERSION "3.60" +#define DRV_MODULE_RELDATE "June 17, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -229,6 +229,8 @@ static struct pci_device_id tg3_pci_tbl[ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M, @@ -2965,6 +2967,27 @@ static int tg3_setup_phy(struct tg3 *tp, return err; } +/* This is called whenever we suspect that the system chipset is re- + * ordering the sequence of MMIO to the tx send mailbox. The symptom + * is bogus tx completions. We try to recover by setting the + * TG3_FLAG_MBOX_WRITE_REORDER flag and resetting the chip later + * in the workqueue. + */ +static void tg3_tx_recover(struct tg3 *tp) +{ + BUG_ON((tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) || + tp->write32_tx_mbox == tg3_write_indirect_mbox); + + printk(KERN_WARNING PFX "%s: The system may be re-ordering memory-" + "mapped I/O cycles to the network device, attempting to " + "recover. Please report the problem to the driver maintainer " + "and include system chipset information.\n", tp->dev->name); + + spin_lock(&tp->lock); + tp->tg3_flags |= TG3_FLAG_TX_RECOVERY_PENDING; + spin_unlock(&tp->lock); +} + /* Tigon3 never reports partial packet sends. So we do not * need special logic to handle SKBs that have not had all * of their frags sent yet, like SunGEM does. @@ -2977,9 +3000,13 @@ static void tg3_tx(struct tg3 *tp) while (sw_idx != hw_idx) { struct tx_ring_info *ri = &tp->tx_buffers[sw_idx]; struct sk_buff *skb = ri->skb; - int i; + int i, tx_bug = 0; + + if (unlikely(skb == NULL)) { + tg3_tx_recover(tp); + return; + } - BUG_ON(skb == NULL); pci_unmap_single(tp->pdev, pci_unmap_addr(ri, mapping), skb_headlen(skb), @@ -2990,10 +3017,9 @@ static void tg3_tx(struct tg3 *tp) sw_idx = NEXT_TX(sw_idx); for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - BUG_ON(sw_idx == hw_idx); - ri = &tp->tx_buffers[sw_idx]; - BUG_ON(ri->skb != NULL); + if (unlikely(ri->skb != NULL || sw_idx == hw_idx)) + tx_bug = 1; pci_unmap_page(tp->pdev, pci_unmap_addr(ri, mapping), @@ -3004,6 +3030,11 @@ static void tg3_tx(struct tg3 *tp) } dev_kfree_skb(skb); + + if (unlikely(tx_bug)) { + tg3_tx_recover(tp); + return; + } } tp->tx_cons = sw_idx; @@ -3331,6 +3362,11 @@ static int tg3_poll(struct net_device *n /* run TX completion thread */ if (sblk->idx[0].tx_consumer != tp->tx_cons) { tg3_tx(tp); + if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) { + netif_rx_complete(netdev); + schedule_work(&tp->reset_task); + return 0; + } } /* run RX thread, within the bounds set by NAPI. @@ -3391,12 +3427,10 @@ static inline void tg3_full_lock(struct if (irq_sync) tg3_irq_quiesce(tp); spin_lock_bh(&tp->lock); - spin_lock(&tp->tx_lock); } static inline void tg3_full_unlock(struct tg3 *tp) { - spin_unlock(&tp->tx_lock); spin_unlock_bh(&tp->lock); } @@ -3579,6 +3613,13 @@ static void tg3_reset_task(void *_data) restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER; tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; + if (tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING) { + tp->write32_tx_mbox = tg3_write32_tx_mbox; + tp->write32_rx_mbox = tg3_write_flush_reg32; + tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER; + tp->tg3_flags &= ~TG3_FLAG_TX_RECOVERY_PENDING; + } + tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); tg3_init_hw(tp, 1); @@ -3718,14 +3759,11 @@ static int tg3_start_xmit(struct sk_buff len = skb_headlen(skb); - /* No BH disabling for tx_lock here. We are running in BH disabled - * context and TX reclaim runs via tp->poll inside of a software + /* We are running in BH disabled context with netif_tx_lock + * and TX reclaim runs via tp->poll inside of a software * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ - if (!spin_trylock(&tp->tx_lock)) - return NETDEV_TX_LOCKED; - if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -3734,7 +3772,6 @@ static int tg3_start_xmit(struct sk_buff printk(KERN_ERR PFX "%s: BUG! Tx Ring full when " "queue awake!\n", dev->name); } - spin_unlock(&tp->tx_lock); return NETDEV_TX_BUSY; } @@ -3743,7 +3780,7 @@ static int tg3_start_xmit(struct sk_buff #if TG3_TSO_SUPPORT != 0 mss = 0; if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->tso_size) != 0) { + (mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len; if (skb_header_cloned(skb) && @@ -3817,15 +3854,16 @@ #endif tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); tp->tx_prod = entry; - if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) { + if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) { + spin_lock(&tp->tx_lock); netif_stop_queue(dev); if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH) netif_wake_queue(tp->dev); + spin_unlock(&tp->tx_lock); } out_unlock: mmiowb(); - spin_unlock(&tp->tx_lock); dev->trans_start = jiffies; @@ -3844,14 +3882,11 @@ static int tg3_start_xmit_dma_bug(struct len = skb_headlen(skb); - /* No BH disabling for tx_lock here. We are running in BH disabled - * context and TX reclaim runs via tp->poll inside of a software + /* We are running in BH disabled context with netif_tx_lock + * and TX reclaim runs via tp->poll inside of a software * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ - if (!spin_trylock(&tp->tx_lock)) - return NETDEV_TX_LOCKED; - if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -3860,7 +3895,6 @@ static int tg3_start_xmit_dma_bug(struct printk(KERN_ERR PFX "%s: BUG! Tx Ring full when " "queue awake!\n", dev->name); } - spin_unlock(&tp->tx_lock); return NETDEV_TX_BUSY; } @@ -3871,7 +3905,7 @@ static int tg3_start_xmit_dma_bug(struct #if TG3_TSO_SUPPORT != 0 mss = 0; if (skb->len > (tp->dev->mtu + ETH_HLEN) && - (mss = skb_shinfo(skb)->tso_size) != 0) { + (mss = skb_shinfo(skb)->gso_size) != 0) { int tcp_opt_len, ip_tcp_len; if (skb_header_cloned(skb) && @@ -3998,15 +4032,16 @@ #endif tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); tp->tx_prod = entry; - if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) { + if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) { + spin_lock(&tp->tx_lock); netif_stop_queue(dev); if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH) netif_wake_queue(tp->dev); + spin_unlock(&tp->tx_lock); } out_unlock: mmiowb(); - spin_unlock(&tp->tx_lock); dev->trans_start = jiffies; @@ -10514,11 +10549,13 @@ static int __devinit tg3_get_macaddr_spa struct pcidev_cookie *pcp = pdev->sysdata; if (pcp != NULL) { - int node = pcp->prom_node; + unsigned char *addr; + int len; - if (prom_getproplen(node, "local-mac-address") == 6) { - prom_getproperty(node, "local-mac-address", - dev->dev_addr, 6); + addr = of_get_property(pcp->prom_node, "local-mac-address", + &len); + if (addr && len == 6) { + memcpy(dev->dev_addr, addr, 6); memcpy(dev->perm_addr, dev->dev_addr, 6); return 0; } @@ -11243,7 +11280,6 @@ static int __devinit tg3_init_one(struct SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - dev->features |= NETIF_F_LLTX; #if TG3_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->vlan_rx_register = tg3_vlan_rx_register; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index ff0faab..8209da5 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2074,12 +2074,22 @@ struct tg3 { /* SMP locking strategy: * - * lock: Held during all operations except TX packet - * processing. + * lock: Held during reset, PHY access, timer, and when + * updating tg3_flags and tg3_flags2. * - * tx_lock: Held during tg3_start_xmit and tg3_tx + * tx_lock: Held during tg3_start_xmit and tg3_tx only + * when calling netif_[start|stop]_queue. + * tg3_start_xmit is protected by netif_tx_lock. * * Both of these locks are to be held with BH safety. + * + * Because the IRQ handler, tg3_poll, and tg3_start_xmit + * are running lockless, it is necessary to completely + * quiesce the chip with tg3_netif_stop and tg3_full_lock + * before reconfiguring the device. + * + * indirect_lock: Held when accessing registers indirectly + * with IRQ disabling. */ spinlock_t lock; spinlock_t indirect_lock; @@ -2155,11 +2165,7 @@ #define TG3_FLAG_USE_MI_INTERRUPT 0x0000 #define TG3_FLAG_ENABLE_ASF 0x00000020 #define TG3_FLAG_5701_REG_WRITE_BUG 0x00000040 #define TG3_FLAG_POLL_SERDES 0x00000080 -#if defined(CONFIG_X86) #define TG3_FLAG_MBOX_WRITE_REORDER 0x00000100 -#else -#define TG3_FLAG_MBOX_WRITE_REORDER 0 /* disables code too */ -#endif #define TG3_FLAG_PCIX_TARGET_HWBUG 0x00000200 #define TG3_FLAG_WOL_SPEED_100MB 0x00000400 #define TG3_FLAG_WOL_ENABLE 0x00000800 @@ -2172,6 +2178,7 @@ #define TG3_FLAG_PCIX_MODE 0x00020000 #define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 #define TG3_FLAG_PCI_32BIT 0x00080000 #define TG3_FLAG_SRAM_USE_CONFIG 0x00100000 +#define TG3_FLAG_TX_RECOVERY_PENDING 0x00200000 #define TG3_FLAG_SERDES_WOL_CAP 0x00400000 #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 #define TG3_FLAG_10_100_ONLY 0x01000000 diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index 23032a7..c3cb8d2 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -217,7 +217,7 @@ static int __devinit olympic_probe(struc dev = alloc_trdev(sizeof(struct olympic_private)) ; if (!dev) { i = -ENOMEM; - goto op_free_dev; + goto op_release_dev; } olympic_priv = dev->priv ; @@ -282,8 +282,8 @@ op_free_iomap: if (olympic_priv->olympic_lap) iounmap(olympic_priv->olympic_lap); -op_free_dev: free_netdev(dev); +op_release_dev: pci_release_regions(pdev); op_disable_dev: diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index e3dd144..5f743b9 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -227,12 +227,12 @@ enum { SROMC0InfoLeaf = 27, MediaBlockMask = 0x3f, MediaCustomCSRs = (1 << 6), - + /* PCIPM bits */ PM_Sleep = (1 << 31), PM_Snooze = (1 << 30), PM_Mask = PM_Sleep | PM_Snooze, - + /* SIAStatus bits */ NWayState = (1 << 14) | (1 << 13) | (1 << 12), NWayRestart = (1 << 12), @@ -858,7 +858,7 @@ static void de_stop_rxtx (struct de_priv return; cpu_relax(); } - + printk(KERN_WARNING "%s: timeout expired stopping DMA\n", de->dev->name); } @@ -931,7 +931,7 @@ static void de_set_media (struct de_priv macmode |= FullDuplex; else macmode &= ~FullDuplex; - + if (netif_msg_link(de)) { printk(KERN_INFO "%s: set link %s\n" KERN_INFO "%s: mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n" @@ -966,9 +966,9 @@ static void de21040_media_timer (unsigne u32 status = dr32(SIAStatus); unsigned int carrier; unsigned long flags; - + carrier = (status & NetCxnErr) ? 0 : 1; - + if (carrier) { if (de->media_type != DE_MEDIA_AUI && (status & LinkFailStatus)) goto no_link_yet; @@ -985,7 +985,7 @@ static void de21040_media_timer (unsigne return; } - de_link_down(de); + de_link_down(de); if (de->media_lock) return; @@ -1039,7 +1039,7 @@ static unsigned int de_ok_to_advertise ( return 0; break; } - + return 1; } @@ -1050,9 +1050,9 @@ static void de21041_media_timer (unsigne u32 status = dr32(SIAStatus); unsigned int carrier; unsigned long flags; - + carrier = (status & NetCxnErr) ? 0 : 1; - + if (carrier) { if ((de->media_type == DE_MEDIA_TP_AUTO || de->media_type == DE_MEDIA_TP || @@ -1072,7 +1072,7 @@ static void de21041_media_timer (unsigne return; } - de_link_down(de); + de_link_down(de); /* if media type locked, don't switch media */ if (de->media_lock) @@ -1124,7 +1124,7 @@ static void de21041_media_timer (unsigne u32 next_states[] = { DE_MEDIA_AUI, DE_MEDIA_BNC, DE_MEDIA_TP_AUTO }; de_next_media(de, next_states, ARRAY_SIZE(next_states)); } - + set_media: spin_lock_irqsave(&de->lock, flags); de_stop_rxtx(de); @@ -1148,7 +1148,7 @@ static void de_media_interrupt (struct d mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK); return; } - + BUG_ON(!(status & LinkFail)); if (netif_carrier_ok(de->dev)) { @@ -1227,7 +1227,7 @@ static int de_init_hw (struct de_private int rc; de_adapter_wake(de); - + macmode = dr32(MacMode) & ~MacModeClear; rc = de_reset_mac(de); @@ -1413,7 +1413,7 @@ static int de_close (struct net_device * netif_stop_queue(dev); netif_carrier_off(dev); spin_unlock_irqrestore(&de->lock, flags); - + free_irq(dev->irq, dev); de_free_rings(de); @@ -1441,7 +1441,7 @@ static void de_tx_timeout (struct net_de spin_unlock_irq(&de->lock); enable_irq(dev->irq); - + /* Update the error counts. */ __de_get_stats(de); @@ -1451,7 +1451,7 @@ static void de_tx_timeout (struct net_de de_init_rings(de); de_init_hw(de); - + netif_wake_queue(dev); } @@ -1459,7 +1459,7 @@ static void __de_get_regs(struct de_priv { int i; u32 *rbuf = (u32 *)buf; - + /* read all CSRs */ for (i = 0; i < DE_NUM_REGS; i++) rbuf[i] = dr32(i * 8); @@ -1474,7 +1474,7 @@ static int __de_get_settings(struct de_p ecmd->transceiver = XCVR_INTERNAL; ecmd->phy_address = 0; ecmd->advertising = de->media_advertise; - + switch (de->media_type) { case DE_MEDIA_AUI: ecmd->port = PORT_AUI; @@ -1489,7 +1489,7 @@ static int __de_get_settings(struct de_p ecmd->speed = SPEED_10; break; } - + if (dr32(MacMode) & FullDuplex) ecmd->duplex = DUPLEX_FULL; else @@ -1529,7 +1529,7 @@ static int __de_set_settings(struct de_p if (ecmd->autoneg == AUTONEG_ENABLE && (!(ecmd->advertising & ADVERTISED_Autoneg))) return -EINVAL; - + switch (ecmd->port) { case PORT_AUI: new_media = DE_MEDIA_AUI; @@ -1554,22 +1554,22 @@ static int __de_set_settings(struct de_p return -EINVAL; break; } - + media_lock = (ecmd->autoneg == AUTONEG_ENABLE) ? 0 : 1; - + if ((new_media == de->media_type) && (media_lock == de->media_lock) && (ecmd->advertising == de->media_advertise)) return 0; /* nothing to change */ - + de_link_down(de); de_stop_rxtx(de); - + de->media_type = new_media; de->media_lock = media_lock; de->media_advertise = ecmd->advertising; de_set_media(de); - + return 0; } @@ -1817,7 +1817,7 @@ #endif case 0x0204: de->media_type = DE_MEDIA_TP_FD; break; default: de->media_type = DE_MEDIA_TP_AUTO; break; } - + if (netif_msg_probe(de)) printk(KERN_INFO "de%d: SROM leaf offset %u, default media %s\n", de->board_idx, ofs, @@ -1886,7 +1886,7 @@ #endif de->media[idx].csr13, de->media[idx].csr14, de->media[idx].csr15); - + } else if (netif_msg_probe(de)) printk("\n"); @@ -2118,7 +2118,7 @@ static int de_suspend (struct pci_dev *p spin_unlock_irq(&de->lock); enable_irq(dev->irq); - + /* Update the error counts. */ __de_get_stats(de); diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index f560941..da8bd0d 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -41,11 +41,11 @@ Digital Semiconductor SROM Specification. The driver currently recognises the following chips: - DC21040 (no SROM) - DC21041[A] - DC21140[A] - DC21142 - DC21143 + DC21040 (no SROM) + DC21041[A] + DC21140[A] + DC21142 + DC21143 So far the driver is known to work with the following cards: @@ -55,7 +55,7 @@ SMC8432 SMC9332 (w/new SROM) ZNYX31[45] - ZNYX346 10/100 4 port (can act as a 10/100 bridge!) + ZNYX346 10/100 4 port (can act as a 10/100 bridge!) The driver has been tested on a relatively busy network using the DE425, DE434, DE435 and DE500 cards and benchmarked with 'ttcp': it transferred @@ -106,7 +106,7 @@ loading by: insmod de4x5 io=0xghh where g = bus number - hh = device number + hh = device number NB: autoprobing for modules is now supported by default. You may just use: @@ -120,11 +120,11 @@ 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a kernel with the de4x5 configuration turned off and reboot. 5) insmod de4x5 [io=0xghh] - 6) run the net startup bits for your new eth?? interface(s) manually - (usually /etc/rc.inet[12] at boot time). + 6) run the net startup bits for your new eth?? interface(s) manually + (usually /etc/rc.inet[12] at boot time). 7) enjoy! - To unload a module, turn off the associated interface(s) + To unload a module, turn off the associated interface(s) 'ifconfig eth?? down' then 'rmmod de4x5'. Automedia detection is included so that in principal you can disconnect @@ -135,7 +135,7 @@ By default, the driver will now autodetect any DECchip based card. Should you have a need to restrict the driver to DIGITAL only cards, you can compile with a DEC_ONLY define, or if loading as a module, use the - 'dec_only=1' parameter. + 'dec_only=1' parameter. I've changed the timing routines to use the kernel timer and scheduling functions so that the hangs and other assorted problems that occurred @@ -204,7 +204,7 @@ following parameters are allowed: fdx for full duplex - autosense to set the media/speed; with the following + autosense to set the media/speed; with the following sub-parameters: TP, TP_NW, BNC, AUI, BNC_AUI, 100Mb, 10Mb, AUTO @@ -235,14 +235,14 @@ this automatically or include #define DE4X5_FORCE_EISA on or before line 1040 in the driver. - TO DO: + TO DO: ------ Revision History ---------------- Version Date Description - + 0.1 17-Nov-94 Initial writing. ALPHA code release. 0.2 13-Jan-95 Added PCI support for DE435's. 0.21 19-Jan-95 Added auto media detection. @@ -251,7 +251,7 @@ Add request/release_region code. Add loadable modules support for PCI. Clean up loadable modules support. - 0.23 28-Feb-95 Added DC21041 and DC21140 support. + 0.23 28-Feb-95 Added DC21041 and DC21140 support. Fix missed frame counter value and initialisation. Fixed EISA probe. 0.24 11-Apr-95 Change delay routine to use . @@ -280,7 +280,7 @@ Add kernel timer code (h/w is too flaky). Add MII based PHY autosense. Add new multicasting code. - Add new autosense algorithms for media/mode + Add new autosense algorithms for media/mode selection using kernel scheduling/timing. Re-formatted. Made changes suggested by : @@ -307,10 +307,10 @@ Add Accton to the list of broken cards. Fix TX under-run bug for non DC21140 chips. Fix boot command probe bug in alloc_device() as - reported by and + reported by and . Add cache locks to prevent a race condition as - reported by and + reported by and . Upgraded alloc_device() code. 0.431 28-Jun-96 Fix potential bug in queue_pkt() from discussion @@ -322,7 +322,7 @@ with a loopback packet. 0.442 9-Sep-96 Include AUI in dc21041 media printout. Bug reported by - 0.45 8-Dec-96 Include endian functions for PPC use, from work + 0.45 8-Dec-96 Include endian functions for PPC use, from work by and . 0.451 28-Dec-96 Added fix to allow autoprobe for modules after suggestion from . @@ -346,14 +346,14 @@ . 0.52 26-Apr-97 Some changes may not credit the right people - a disk crash meant I lost some mail. - Change RX interrupt routine to drop rather than - defer packets to avoid hang reported by + Change RX interrupt routine to drop rather than + defer packets to avoid hang reported by . Fix srom_exec() to return for COMPACT and type 1 infoblocks. Added DC21142 and DC21143 functions. Added byte counters from - Added SA_INTERRUPT temporary fix from + Added SA_INTERRUPT temporary fix from . 0.53 12-Nov-97 Fix the *_probe() to include 'eth??' name during module load: bug reported by @@ -363,10 +363,10 @@ Make above search independent of BIOS device scan direction. Completed DC2114[23] autosense functions. - 0.531 21-Dec-97 Fix DE500-XA 100Mb/s bug reported by + 0.531 21-Dec-97 Fix DE500-XA 100Mb/s bug reported by and . Added argument list to set up each board from either @@ -374,7 +374,7 @@ Added generic MII PHY functionality to deal with newer PHY chips. Fix the mess in 2.1.67. - 0.532 5-Jan-98 Fix bug in mii_get_phy() reported by + 0.532 5-Jan-98 Fix bug in mii_get_phy() reported by . Fix bug in pci_probe() for 64 bit systems reported by . @@ -398,7 +398,7 @@ version. I hope nothing is broken... Add TX done interrupt modification from suggestion by . - Fix is_anc_capable() bug reported by + Fix is_anc_capable() bug reported by . Fix type[13]_infoblock() bug: during MII search, PHY lp->rst not run because lp->ibn not initialised - @@ -413,7 +413,7 @@ Add an_exception() for old ZYNX346 and fix compile warning on PPC & SPARC, from . Fix lastPCI to correctly work with compiled in - kernels and modules from bug report by + kernels and modules from bug report by et al. 0.542 15-Sep-98 Fix dc2114x_autoconf() to stop multiple messages when media is unconnected. @@ -425,7 +425,7 @@ 0.544 8-May-99 Fix for buggy SROM in Motorola embedded boards using a 21143 by . Change PCI/EISA bus probing order. - 0.545 28-Nov-99 Further Moto SROM bug fix from + 0.545 28-Nov-99 Further Moto SROM bug fix from Remove double checking for DEBUG_RX in de4x5_dbg_rx() from report by @@ -434,8 +434,8 @@ variable 'pb', on a non de4x5 PCI device, in this case a PCI bridge (DEC chip 21152). The value of 'pb' is now only initialized if a de4x5 chip is - present. - + present. + 0.547 08-Nov-01 Use library crc32 functions by 0.548 30-Aug-03 Big 2.6 cleanup. Ported to PCI/EISA probing and generic DMA APIs. Fixed DE425 support on Alpha. @@ -584,7 +584,7 @@ #endif /* ** Allow per adapter set up. For modules this is simply a command line -** parameter, e.g.: +** parameter, e.g.: ** insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'. ** ** For a compiled in driver, place e.g. @@ -655,7 +655,7 @@ #define DE4X5_CLASS_CODE 0x00020000 ** Memory Alignment. Each descriptor is 4 longwords long. To force a ** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and ** DESC_ALIGN. ALIGN aligns the start address of the private memory area -** and hence the RX descriptor ring's first entry. +** and hence the RX descriptor ring's first entry. */ #define DE4X5_ALIGN4 ((u_long)4 - 1) /* 1 longword align */ #define DE4X5_ALIGN8 ((u_long)8 - 1) /* 2 longword align */ @@ -1081,8 +1081,8 @@ #define PHY_HARD_RESET {\ mdelay(2); /* Wait for 2ms */\ } - -static int __devinit + +static int __devinit de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) { char name[DE4X5_NAME_LENGTH + 1]; @@ -1102,12 +1102,12 @@ de4x5_hw_init(struct net_device *dev, u_ mdelay(10); RESET_DE4X5; - + if ((inl(DE4X5_STS) & (STS_TS | STS_RS)) != 0) { return -ENXIO; /* Hardware could not reset */ } - - /* + + /* ** Now find out what kind of DC21040/DC21041/DC21140 board we have. */ lp->useSROM = FALSE; @@ -1116,21 +1116,21 @@ de4x5_hw_init(struct net_device *dev, u_ } else { EISA_signature(name, gendev); } - + if (*name == '\0') { /* Not found a board signature */ return -ENXIO; } - + dev->base_addr = iobase; printk ("%s: %s at 0x%04lx", gendev->bus_id, name, iobase); - + printk(", h/w address "); status = get_hw_addr(dev); for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */ printk("%2.2x:", dev->dev_addr[i]); } printk("%2.2x,\n", dev->dev_addr[i]); - + if (status != 0) { printk(" which has an Ethernet PROM CRC error.\n"); return -ENXIO; @@ -1171,10 +1171,10 @@ #endif } lp->tx_ring = lp->rx_ring + NUM_RX_DESC; - + /* ** Set up the RX descriptor ring (Intels) - ** Allocate contiguous receive buffers, long word aligned (Alphas) + ** Allocate contiguous receive buffers, long word aligned (Alphas) */ #if !defined(__alpha__) && !defined(__powerpc__) && !defined(__sparc_v9__) && !defined(DE4X5_DO_MEMCPY) for (i=0; irxRingSize = NUM_RX_DESC; lp->txRingSize = NUM_TX_DESC; - + /* Write the end of list marker to the descriptor lists */ lp->rx_ring[lp->rxRingSize - 1].des1 |= cpu_to_le32(RD_RER); lp->tx_ring[lp->txRingSize - 1].des1 |= cpu_to_le32(TD_TER); @@ -1219,7 +1219,7 @@ #endif outl(lp->dma_rings, DE4X5_RRBA); outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc), DE4X5_TRBA); - + /* Initialise the IRQ mask and Enable/Disable */ lp->irq_mask = IMR_RIM | IMR_TIM | IMR_TUM | IMR_UNM; lp->irq_en = IMR_NIM | IMR_AIM; @@ -1252,7 +1252,7 @@ #endif if ((lp->chipset != DC21040) && (lp->chipset != DC21041)) { mii_get_phy(dev); } - + #ifndef __sparc_v9__ printk(" and requires IRQ%d (provided by %s).\n", dev->irq, #else @@ -1260,11 +1260,11 @@ #else #endif ((lp->bus == PCI) ? "PCI BIOS" : "EISA CNFG")); } - + if (de4x5_debug & DEBUG_VERSION) { printk(version); } - + /* The DE4X5-specific entries in the device structure. */ SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, gendev); @@ -1274,23 +1274,23 @@ #endif dev->get_stats = &de4x5_get_stats; dev->set_multicast_list = &set_multicast_list; dev->do_ioctl = &de4x5_ioctl; - + dev->mem_start = 0; - + /* Fill in the generic fields of the device structure. */ if ((status = register_netdev (dev))) { dma_free_coherent (gendev, lp->dma_size, lp->rx_ring, lp->dma_rings); return status; } - + /* Let the adapter sleep to save power */ yawn(dev, SLEEP); - + return status; } - + static int de4x5_open(struct net_device *dev) { @@ -1312,15 +1312,15 @@ de4x5_open(struct net_device *dev) */ yawn(dev, WAKEUP); - /* - ** Re-initialize the DE4X5... + /* + ** Re-initialize the DE4X5... */ status = de4x5_init(dev); spin_lock_init(&lp->lock); lp->state = OPEN; de4x5_dbg_open(dev); - - if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ, + + if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ, lp->adapter_name, dev)) { printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq); if (request_irq(dev->irq, de4x5_interrupt, SA_INTERRUPT | SA_SHIRQ, @@ -1340,11 +1340,11 @@ de4x5_open(struct net_device *dev) lp->interrupt = UNMASK_INTERRUPTS; dev->trans_start = jiffies; - + START_DE4X5; - + de4x5_setup_intr(dev); - + if (de4x5_debug & DEBUG_OPEN) { printk("\tsts: 0x%08x\n", inl(DE4X5_STS)); printk("\tbmr: 0x%08x\n", inl(DE4X5_BMR)); @@ -1355,7 +1355,7 @@ de4x5_open(struct net_device *dev) printk("\tstrr: 0x%08x\n", inl(DE4X5_STRR)); printk("\tsigr: 0x%08x\n", inl(DE4X5_SIGR)); } - + return status; } @@ -1369,15 +1369,15 @@ de4x5_open(struct net_device *dev) */ static int de4x5_init(struct net_device *dev) -{ +{ /* Lock out other processes whilst setting up the hardware */ netif_stop_queue(dev); - + de4x5_sw_reset(dev); - + /* Autoconfigure the connected port */ autoconf_media(dev); - + return 0; } @@ -1388,7 +1388,7 @@ de4x5_sw_reset(struct net_device *dev) u_long iobase = dev->base_addr; int i, j, status = 0; s32 bmr, omr; - + /* Select the MII or SRL port now and RESET the MAC */ if (!lp->useSROM) { if (lp->phy[lp->active].id != 0) { @@ -1399,7 +1399,7 @@ de4x5_sw_reset(struct net_device *dev) de4x5_switch_mac_port(dev); } - /* + /* ** Set the programmable burst length to 8 longwords for all the DC21140 ** Fasternet chips and 4 longwords for all others: DMA errors result ** without these values. Cache align 16 long. @@ -1416,23 +1416,23 @@ de4x5_sw_reset(struct net_device *dev) outl(lp->dma_rings, DE4X5_RRBA); outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc), DE4X5_TRBA); - + lp->rx_new = lp->rx_old = 0; lp->tx_new = lp->tx_old = 0; - + for (i = 0; i < lp->rxRingSize; i++) { lp->rx_ring[i].status = cpu_to_le32(R_OWN); } - + for (i = 0; i < lp->txRingSize; i++) { lp->tx_ring[i].status = cpu_to_le32(0); } - + barrier(); /* Build the setup frame depending on filtering mode */ SetMulticastFilter(dev); - + load_packet(dev, lp->setup_frame, PERFECT_F|TD_SET|SETUP_FRAME_LEN, (struct sk_buff *)1); outl(omr|OMR_ST, DE4X5_OMR); @@ -1445,18 +1445,18 @@ de4x5_sw_reset(struct net_device *dev) outl(omr, DE4X5_OMR); /* Stop everything! */ if (j == 0) { - printk("%s: Setup frame timed out, status %08x\n", dev->name, + printk("%s: Setup frame timed out, status %08x\n", dev->name, inl(DE4X5_STS)); status = -EIO; } - + lp->tx_new = (++lp->tx_new) % lp->txRingSize; lp->tx_old = lp->tx_new; return status; } -/* +/* ** Writes a socket buffer address to the next available transmit descriptor. */ static int @@ -1469,9 +1469,9 @@ de4x5_queue_pkt(struct sk_buff *skb, str netif_stop_queue(dev); if (lp->tx_enable == NO) { /* Cannot send for now */ - return -1; + return -1; } - + /* ** Clean out the TX ring asynchronously to interrupts - sometimes the ** interrupts are lost by delayed descriptor status updates relative to @@ -1482,7 +1482,7 @@ de4x5_queue_pkt(struct sk_buff *skb, str spin_unlock_irqrestore(&lp->lock, flags); /* Test if cache is already locked - requeue skb if so */ - if (test_and_set_bit(0, (void *)&lp->cache.lock) && !lp->interrupt) + if (test_and_set_bit(0, (void *)&lp->cache.lock) && !lp->interrupt) return -1; /* Transmit descriptor ring full or stale skb */ @@ -1509,10 +1509,10 @@ de4x5_queue_pkt(struct sk_buff *skb, str load_packet(dev, skb->data, TD_IC | TD_LS | TD_FS | skb->len, skb); lp->stats.tx_bytes += skb->len; outl(POLL_DEMAND, DE4X5_TPD);/* Start the TX */ - + lp->tx_new = (++lp->tx_new) % lp->txRingSize; dev->trans_start = jiffies; - + if (TX_BUFFS_AVAIL) { netif_start_queue(dev); /* Another pkt may be queued */ } @@ -1521,15 +1521,15 @@ de4x5_queue_pkt(struct sk_buff *skb, str } if (skb) de4x5_putb_cache(dev, skb); } - + lp->cache.lock = 0; return status; } /* -** The DE4X5 interrupt handler. -** +** The DE4X5 interrupt handler. +** ** I/O Read/Writes through intermediate PCI bridges are never 'posted', ** so that the asserted interrupt always has some real data to work with - ** if these I/O accesses are ever changed to memory accesses, ensure the @@ -1546,7 +1546,7 @@ de4x5_interrupt(int irq, void *dev_id, s s32 imr, omr, sts, limit; u_long iobase; unsigned int handled = 0; - + if (dev == NULL) { printk ("de4x5_interrupt(): irq %d for unknown device.\n", irq); return IRQ_NONE; @@ -1554,35 +1554,35 @@ de4x5_interrupt(int irq, void *dev_id, s lp = netdev_priv(dev); spin_lock(&lp->lock); iobase = dev->base_addr; - + DISABLE_IRQs; /* Ensure non re-entrancy */ if (test_and_set_bit(MASK_INTERRUPTS, (void*) &lp->interrupt)) printk("%s: Re-entering the interrupt handler.\n", dev->name); synchronize_irq(dev->irq); - + for (limit=0; limit<8; limit++) { sts = inl(DE4X5_STS); /* Read IRQ status */ outl(sts, DE4X5_STS); /* Reset the board interrupts */ - + if (!(sts & lp->irq_mask)) break;/* All done */ handled = 1; - + if (sts & (STS_RI | STS_RU)) /* Rx interrupt (packet[s] arrived) */ de4x5_rx(dev); - + if (sts & (STS_TI | STS_TU)) /* Tx interrupt (packet sent) */ - de4x5_tx(dev); - + de4x5_tx(dev); + if (sts & STS_LNF) { /* TP Link has failed */ lp->irq_mask &= ~IMR_LFM; } - + if (sts & STS_UNF) { /* Transmit underrun */ de4x5_txur(dev); } - + if (sts & STS_SE) { /* Bus Error */ STOP_DE4X5; printk("%s: Fatal bus error occurred, sts=%#8x, device stopped.\n", @@ -1603,7 +1603,7 @@ de4x5_interrupt(int irq, void *dev_id, s lp->interrupt = UNMASK_INTERRUPTS; ENABLE_IRQs; spin_unlock(&lp->lock); - + return IRQ_RETVAL(handled); } @@ -1614,11 +1614,11 @@ de4x5_rx(struct net_device *dev) u_long iobase = dev->base_addr; int entry; s32 status; - + for (entry=lp->rx_new; (s32)le32_to_cpu(lp->rx_ring[entry].status)>=0; entry=lp->rx_new) { status = (s32)le32_to_cpu(lp->rx_ring[entry].status); - + if (lp->rx_ovf) { if (inl(DE4X5_MFC) & MFC_FOCM) { de4x5_rx_ovfc(dev); @@ -1629,7 +1629,7 @@ de4x5_rx(struct net_device *dev) if (status & RD_FS) { /* Remember the start of frame */ lp->rx_old = entry; } - + if (status & RD_LS) { /* Valid frame status */ if (lp->tx_enable) lp->linkOK++; if (status & RD_ES) { /* There was an error. */ @@ -1646,9 +1646,9 @@ de4x5_rx(struct net_device *dev) struct sk_buff *skb; short pkt_len = (short)(le32_to_cpu(lp->rx_ring[entry].status) >> 16) - 4; - + if ((skb = de4x5_alloc_rx_buff(dev, entry, pkt_len)) == NULL) { - printk("%s: Insufficient memory; nuking packet.\n", + printk("%s: Insufficient memory; nuking packet.\n", dev->name); lp->stats.rx_dropped++; } else { @@ -1658,14 +1658,14 @@ de4x5_rx(struct net_device *dev) skb->protocol=eth_type_trans(skb,dev); de4x5_local_stats(dev, skb->data, pkt_len); netif_rx(skb); - + /* Update stats */ dev->last_rx = jiffies; lp->stats.rx_packets++; lp->stats.rx_bytes += pkt_len; } } - + /* Change buffer ownership for this frame, back to the adapter */ for (;lp->rx_old!=entry;lp->rx_old=(++lp->rx_old)%lp->rxRingSize) { lp->rx_ring[lp->rx_old].status = cpu_to_le32(R_OWN); @@ -1674,13 +1674,13 @@ de4x5_rx(struct net_device *dev) lp->rx_ring[entry].status = cpu_to_le32(R_OWN); barrier(); } - + /* ** Update entry information */ lp->rx_new = (++lp->rx_new) % lp->rxRingSize; } - + return 0; } @@ -1705,20 +1705,20 @@ de4x5_tx(struct net_device *dev) u_long iobase = dev->base_addr; int entry; s32 status; - + for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { status = (s32)le32_to_cpu(lp->tx_ring[entry].status); if (status < 0) { /* Buffer not sent yet */ break; } else if (status != 0x7fffffff) { /* Not setup frame */ if (status & TD_ES) { /* An error happened */ - lp->stats.tx_errors++; + lp->stats.tx_errors++; if (status & TD_NC) lp->stats.tx_carrier_errors++; if (status & TD_LC) lp->stats.tx_window_errors++; if (status & TD_UF) lp->stats.tx_fifo_errors++; if (status & TD_EC) lp->pktStats.excessive_collisions++; if (status & TD_DE) lp->stats.tx_aborted_errors++; - + if (TX_PKT_PENDING) { outl(POLL_DEMAND, DE4X5_TPD);/* Restart a stalled TX */ } @@ -1727,14 +1727,14 @@ de4x5_tx(struct net_device *dev) if (lp->tx_enable) lp->linkOK++; } /* Update the collision counter */ - lp->stats.collisions += ((status & TD_EC) ? 16 : + lp->stats.collisions += ((status & TD_EC) ? 16 : ((status & TD_CC) >> 3)); /* Free the buffer. */ if (lp->tx_skb[entry] != NULL) de4x5_free_tx_buff(lp, entry); } - + /* Update all the pointers */ lp->tx_old = (++lp->tx_old) % lp->txRingSize; } @@ -1746,7 +1746,7 @@ de4x5_tx(struct net_device *dev) else netif_start_queue(dev); } - + return 0; } @@ -1755,9 +1755,9 @@ de4x5_ast(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); int next_tick = DE4X5_AUTOSENSE_MS; - + disable_ast(dev); - + if (lp->useSROM) { next_tick = srom_autoconf(dev); } else if (lp->chipset == DC21140) { @@ -1769,7 +1769,7 @@ de4x5_ast(struct net_device *dev) } lp->linkOK = 0; enable_ast(dev, next_tick); - + return 0; } @@ -1792,11 +1792,11 @@ de4x5_txur(struct net_device *dev) } outl(omr | OMR_ST | OMR_SR, DE4X5_OMR); } - + return 0; } -static int +static int de4x5_rx_ovfc(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); @@ -1813,7 +1813,7 @@ de4x5_rx_ovfc(struct net_device *dev) } outl(omr, DE4X5_OMR); - + return 0; } @@ -1823,22 +1823,22 @@ de4x5_close(struct net_device *dev) struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; s32 imr, omr; - + disable_ast(dev); netif_stop_queue(dev); - + if (de4x5_debug & DEBUG_CLOSE) { printk("%s: Shutting down ethercard, status was %8.8x.\n", dev->name, inl(DE4X5_STS)); } - - /* + + /* ** We stop the DE4X5 here... mask interrupts and stop TX & RX */ DISABLE_IRQs; STOP_DE4X5; - + /* Free the associated irq */ free_irq(dev->irq, dev); lp->state = CLOSED; @@ -1846,10 +1846,10 @@ de4x5_close(struct net_device *dev) /* Free any socket buffers */ de4x5_free_rx_buffs(dev); de4x5_free_tx_buffs(dev); - + /* Put the adapter to sleep to save power */ yawn(dev, SLEEP); - + return 0; } @@ -1858,9 +1858,9 @@ de4x5_get_stats(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; - + lp->stats.rx_missed_errors = (int)(inl(DE4X5_MFC) & (MFC_OVFL | MFC_CNTR)); - + return &lp->stats; } @@ -1886,7 +1886,7 @@ de4x5_local_stats(struct net_device *dev (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) { lp->pktStats.unicast++; } - + lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ if (lp->pktStats.bins[0] == 0) { /* Reset counters */ memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats)); @@ -1937,11 +1937,11 @@ set_multicast_list(struct net_device *de omr = inl(DE4X5_OMR); omr |= OMR_PR; outl(omr, DE4X5_OMR); - } else { + } else { SetMulticastFilter(dev); - load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | + load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | SETUP_FRAME_LEN, (struct sk_buff *)1); - + lp->tx_new = (++lp->tx_new) % lp->txRingSize; outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */ dev->trans_start = jiffies; @@ -1969,20 +1969,20 @@ SetMulticastFilter(struct net_device *de omr = inl(DE4X5_OMR); omr &= ~(OMR_PR | OMR_PM); pa = build_setup_frame(dev, ALL); /* Build the basic frame */ - + if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 14)) { omr |= OMR_PM; /* Pass all multicasts */ } else if (lp->setup_f == HASH_PERF) { /* Hash Filtering */ for (i=0;imc_count;i++) { /* for each address in the list */ addrs=dmi->dmi_addr; dmi=dmi->next; - if ((*addrs & 0x01) == 1) { /* multicast address? */ + if ((*addrs & 0x01) == 1) { /* multicast address? */ crc = ether_crc_le(ETH_ALEN, addrs); hashcode = crc & HASH_BITS; /* hashcode is 9 LSb of CRC */ - + byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ bit = 1 << (hashcode & 0x07);/* bit[0-2] -> bit in byte */ - + byte <<= 1; /* calc offset into setup frame */ if (byte & 0x02) { byte -= 1; @@ -1994,14 +1994,14 @@ SetMulticastFilter(struct net_device *de for (j=0; jmc_count; j++) { addrs=dmi->dmi_addr; dmi=dmi->next; - for (i=0; icfrv = (u_short) inl(PCI_CFRV); device = (cfid >> 8) & 0x00ffff00; vendor = (u_short) cfid; - + /* Read the EISA Configuration Registers */ regval = inb(EISA_REG0) & (ER0_INTL | ER0_INTT); #ifdef CONFIG_ALPHA @@ -2050,7 +2050,7 @@ #ifdef CONFIG_ALPHA * care about the EISA configuration, and thus doesn't * configure the PLX bridge properly. Oh well... Simply mimic * the EISA config file to sort it out. */ - + /* EISA REG1: Assert DecChip 21040 HW Reset */ outb (ER1_IAM | 1, EISA_REG1); mdelay (1); @@ -2061,12 +2061,12 @@ #ifdef CONFIG_ALPHA /* EISA REG3: R/W Burst Transfer Enable */ outb (ER3_BWE | ER3_BRE, EISA_REG3); - + /* 32_bit slave/master, Preempt Time=23 bclks, Unlatched Interrupt */ outb (ER0_BSW | ER0_BMW | ER0_EPT | regval, EISA_REG0); #endif irq = de4x5_irq[(regval >> 1) & 0x03]; - + if (is_DC2114x) { device = ((lp->cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143); } @@ -2077,7 +2077,7 @@ #endif outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS); outl(0x00006000, PCI_CFLT); outl(iobase, PCI_CBIO); - + DevicePresent(dev, EISA_APROM); dev->irq = irq; @@ -2102,7 +2102,7 @@ static int __devexit de4x5_eisa_remove ( dev = device->driver_data; iobase = dev->base_addr; - + unregister_netdev (dev); free_netdev (dev); release_region (iobase + DE4X5_EISA_IO_PORTS, DE4X5_EISA_TOTAL_SIZE); @@ -2131,11 +2131,11 @@ #ifdef CONFIG_PCI /* ** This function searches the current bus (which is >0) for a DECchip with an -** SROM, so that in multiport cards that have one SROM shared between multiple +** SROM, so that in multiport cards that have one SROM shared between multiple ** DECchips, we can find the base SROM irrespective of the BIOS scan direction. ** For single port cards this is a time waster... */ -static void __devinit +static void __devinit srom_search(struct net_device *dev, struct pci_dev *pdev) { u_char pb; @@ -2163,7 +2163,7 @@ srom_search(struct net_device *dev, stru /* Set the device number information */ lp->device = PCI_SLOT(this_dev->devfn); lp->bus_num = pb; - + /* Set the chipset information */ if (is_DC2114x) { device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143); @@ -2176,7 +2176,7 @@ srom_search(struct net_device *dev, stru /* Fetch the IRQ to be used */ irq = this_dev->irq; if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; - + /* Check if I/O accesses are enabled */ pci_read_config_word(this_dev, PCI_COMMAND, &status); if (!(status & PCI_COMMAND_IO)) continue; @@ -2254,7 +2254,7 @@ static int __devinit de4x5_pci_probe (st lp = netdev_priv(dev); lp->bus = PCI; lp->bus_num = 0; - + /* Search for an SROM on this bus */ if (lp->bus_num != pb) { lp->bus_num = pb; @@ -2267,7 +2267,7 @@ static int __devinit de4x5_pci_probe (st /* Set the device number information */ lp->device = dev_num; lp->bus_num = pb; - + /* Set the chipset information */ if (is_DC2114x) { device = ((lp->cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143); @@ -2283,7 +2283,7 @@ static int __devinit de4x5_pci_probe (st error = -ENODEV; goto free_dev; } - + /* Check if I/O accesses and Bus Mastering are enabled */ pci_read_config_word(pdev, PCI_COMMAND, &status); #ifdef __powerpc__ @@ -2322,7 +2322,7 @@ #endif /* __powerpc__ */ } dev->irq = irq; - + if ((error = de4x5_hw_init(dev, iobase, &pdev->dev))) { goto release; } @@ -2377,7 +2377,7 @@ #endif ** Auto configure the media here rather than setting the port at compile ** time. This routine is called by de4x5_init() and when a loss of media is ** detected (excessive collisions, loss of carrier, no carrier or link fail -** [TP] or no recent receive activity) to check whether the user has been +** [TP] or no recent receive activity) to check whether the user has been ** sneaky and changed the port on us. */ static int @@ -2405,7 +2405,7 @@ autoconf_media(struct net_device *dev) } enable_ast(dev, next_tick); - + return (lp->media); } @@ -2428,7 +2428,7 @@ dc21040_autoconf(struct net_device *dev) u_long iobase = dev->base_addr; int next_tick = DE4X5_AUTOSENSE_MS; s32 imr; - + switch (lp->media) { case INIT: DISABLE_IRQs; @@ -2447,36 +2447,36 @@ dc21040_autoconf(struct net_device *dev) lp->local_state = 0; next_tick = dc21040_autoconf(dev); break; - + case TP: - next_tick = dc21040_state(dev, 0x8f01, 0xffff, 0x0000, 3000, BNC_AUI, + next_tick = dc21040_state(dev, 0x8f01, 0xffff, 0x0000, 3000, BNC_AUI, TP_SUSPECT, test_tp); break; - + case TP_SUSPECT: next_tick = de4x5_suspect_state(dev, 1000, TP, test_tp, dc21040_autoconf); break; - + case BNC: case AUI: case BNC_AUI: - next_tick = dc21040_state(dev, 0x8f09, 0x0705, 0x0006, 3000, EXT_SIA, + next_tick = dc21040_state(dev, 0x8f09, 0x0705, 0x0006, 3000, EXT_SIA, BNC_AUI_SUSPECT, ping_media); break; - + case BNC_AUI_SUSPECT: next_tick = de4x5_suspect_state(dev, 1000, BNC_AUI, ping_media, dc21040_autoconf); break; - + case EXT_SIA: - next_tick = dc21040_state(dev, 0x3041, 0x0000, 0x0006, 3000, + next_tick = dc21040_state(dev, 0x3041, 0x0000, 0x0006, 3000, NC, EXT_SIA_SUSPECT, ping_media); break; - + case EXT_SIA_SUSPECT: next_tick = de4x5_suspect_state(dev, 1000, EXT_SIA, ping_media, dc21040_autoconf); break; - + case NC: /* default to TP for all */ reset_init_sia(dev, 0x8f01, 0xffff, 0x0000); @@ -2488,13 +2488,13 @@ dc21040_autoconf(struct net_device *dev) lp->tx_enable = NO; break; } - + return next_tick; } static int dc21040_state(struct net_device *dev, int csr13, int csr14, int csr15, int timeout, - int next_state, int suspect_state, + int next_state, int suspect_state, int (*fn)(struct net_device *, int)) { struct de4x5_private *lp = netdev_priv(dev); @@ -2507,7 +2507,7 @@ dc21040_state(struct net_device *dev, in lp->local_state++; next_tick = 500; break; - + case 1: if (!lp->tx_enable) { linkBad = fn(dev, timeout); @@ -2527,7 +2527,7 @@ dc21040_state(struct net_device *dev, in } break; } - + return next_tick; } @@ -2582,7 +2582,7 @@ dc21041_autoconf(struct net_device *dev) u_long iobase = dev->base_addr; s32 sts, irqs, irq_mask, imr, omr; int next_tick = DE4X5_AUTOSENSE_MS; - + switch (lp->media) { case INIT: DISABLE_IRQs; @@ -2603,7 +2603,7 @@ dc21041_autoconf(struct net_device *dev) lp->local_state = 0; next_tick = dc21041_autoconf(dev); break; - + case TP_NW: if (lp->timeout < 0) { omr = inl(DE4X5_OMR);/* Set up full duplex for the autonegotiate */ @@ -2623,7 +2623,7 @@ dc21041_autoconf(struct net_device *dev) next_tick = dc21041_autoconf(dev); } break; - + case ANS: if (!lp->tx_enable) { irqs = STS_LNP; @@ -2645,11 +2645,11 @@ dc21041_autoconf(struct net_device *dev) next_tick = 3000; } break; - + case ANS_SUSPECT: next_tick = de4x5_suspect_state(dev, 1000, ANS, test_tp, dc21041_autoconf); break; - + case TP: if (!lp->tx_enable) { if (lp->timeout < 0) { @@ -2679,11 +2679,11 @@ dc21041_autoconf(struct net_device *dev) next_tick = 3000; } break; - + case TP_SUSPECT: next_tick = de4x5_suspect_state(dev, 1000, TP, test_tp, dc21041_autoconf); break; - + case AUI: if (!lp->tx_enable) { if (lp->timeout < 0) { @@ -2709,11 +2709,11 @@ dc21041_autoconf(struct net_device *dev) next_tick = 3000; } break; - + case AUI_SUSPECT: next_tick = de4x5_suspect_state(dev, 1000, AUI, ping_media, dc21041_autoconf); break; - + case BNC: switch (lp->local_state) { case 0: @@ -2731,7 +2731,7 @@ dc21041_autoconf(struct net_device *dev) next_tick = dc21041_autoconf(dev); } break; - + case 1: if (!lp->tx_enable) { if ((sts = ping_media(dev, 3000)) < 0) { @@ -2751,11 +2751,11 @@ dc21041_autoconf(struct net_device *dev) break; } break; - + case BNC_SUSPECT: next_tick = de4x5_suspect_state(dev, 1000, BNC, ping_media, dc21041_autoconf); break; - + case NC: omr = inl(DE4X5_OMR); /* Set up full duplex for the autonegotiate */ outl(omr | OMR_FDX, DE4X5_OMR); @@ -2768,7 +2768,7 @@ dc21041_autoconf(struct net_device *dev) lp->tx_enable = NO; break; } - + return next_tick; } @@ -2784,9 +2784,9 @@ dc21140m_autoconf(struct net_device *dev int ana, anlpa, cap, cr, slnk, sr; int next_tick = DE4X5_AUTOSENSE_MS; u_long imr, omr, iobase = dev->base_addr; - + switch(lp->media) { - case INIT: + case INIT: if (lp->timeout < 0) { DISABLE_IRQs; lp->tx_enable = FALSE; @@ -2813,7 +2813,7 @@ dc21140m_autoconf(struct net_device *dev lp->media = _100Mb; } else if (lp->autosense == _10Mb) { lp->media = _10Mb; - } else if ((lp->autosense == AUTO) && + } else if ((lp->autosense == AUTO) && ((sr=is_anc_capable(dev)) & MII_SR_ANC)) { ana = (((sr >> 6) & MII_ANA_TAF) | MII_ANA_CSMA); ana &= (lp->fdx ? ~0 : ~MII_ANA_FDAM); @@ -2831,7 +2831,7 @@ dc21140m_autoconf(struct net_device *dev next_tick = dc21140m_autoconf(dev); } break; - + case ANS: switch (lp->local_state) { case 0: @@ -2851,7 +2851,7 @@ dc21140m_autoconf(struct net_device *dev next_tick = dc21140m_autoconf(dev); } break; - + case 1: if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) { next_tick = sr & ~TIMER_CB; @@ -2862,7 +2862,7 @@ dc21140m_autoconf(struct net_device *dev lp->tmp = MII_SR_ASSC; anlpa = mii_rd(MII_ANLPA, lp->phy[lp->active].addr, DE4X5_MII); ana = mii_rd(MII_ANA, lp->phy[lp->active].addr, DE4X5_MII); - if (!(anlpa & MII_ANLPA_RF) && + if (!(anlpa & MII_ANLPA_RF) && (cap = anlpa & MII_ANLPA_TAF & ana)) { if (cap & MII_ANA_100M) { lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE); @@ -2879,10 +2879,10 @@ dc21140m_autoconf(struct net_device *dev break; } break; - + case SPD_DET: /* Choose 10Mb/s or 100Mb/s */ if (lp->timeout < 0) { - lp->tmp = (lp->phy[lp->active].id ? MII_SR_LKS : + lp->tmp = (lp->phy[lp->active].id ? MII_SR_LKS : (~gep_rd(dev) & GEP_LNP)); SET_100Mb_PDET; } @@ -2899,7 +2899,7 @@ dc21140m_autoconf(struct net_device *dev next_tick = dc21140m_autoconf(dev); } break; - + case _100Mb: /* Set 100Mb/s */ next_tick = 3000; if (!lp->tx_enable) { @@ -2933,7 +2933,7 @@ dc21140m_autoconf(struct net_device *dev } } break; - + case NC: if (lp->media != lp->c_media) { de4x5_dbg_media(dev); @@ -2943,7 +2943,7 @@ dc21140m_autoconf(struct net_device *dev lp->tx_enable = FALSE; break; } - + return next_tick; } @@ -3002,7 +3002,7 @@ dc2114x_autoconf(struct net_device *dev) lp->media = AUI; } else { lp->media = SPD_DET; - if ((lp->infoblock_media == ANS) && + if ((lp->infoblock_media == ANS) && ((sr=is_anc_capable(dev)) & MII_SR_ANC)) { ana = (((sr >> 6) & MII_ANA_TAF) | MII_ANA_CSMA); ana &= (lp->fdx ? ~0 : ~MII_ANA_FDAM); @@ -3014,7 +3014,7 @@ dc2114x_autoconf(struct net_device *dev) next_tick = dc2114x_autoconf(dev); } break; - + case ANS: switch (lp->local_state) { case 0: @@ -3034,7 +3034,7 @@ dc2114x_autoconf(struct net_device *dev) next_tick = dc2114x_autoconf(dev); } break; - + case 1: if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) { next_tick = sr & ~TIMER_CB; @@ -3045,7 +3045,7 @@ dc2114x_autoconf(struct net_device *dev) lp->tmp = MII_SR_ASSC; anlpa = mii_rd(MII_ANLPA, lp->phy[lp->active].addr, DE4X5_MII); ana = mii_rd(MII_ANA, lp->phy[lp->active].addr, DE4X5_MII); - if (!(anlpa & MII_ANLPA_RF) && + if (!(anlpa & MII_ANLPA_RF) && (cap = anlpa & MII_ANLPA_TAF & ana)) { if (cap & MII_ANA_100M) { lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE); @@ -3087,11 +3087,11 @@ dc2114x_autoconf(struct net_device *dev) next_tick = 3000; } break; - + case AUI_SUSPECT: next_tick = de4x5_suspect_state(dev, 1000, AUI, ping_media, dc2114x_autoconf); break; - + case BNC: switch (lp->local_state) { case 0: @@ -3109,7 +3109,7 @@ dc2114x_autoconf(struct net_device *dev) next_tick = dc2114x_autoconf(dev); } break; - + case 1: if (!lp->tx_enable) { if ((sts = ping_media(dev, 3000)) < 0) { @@ -3130,11 +3130,11 @@ dc2114x_autoconf(struct net_device *dev) break; } break; - + case BNC_SUSPECT: next_tick = de4x5_suspect_state(dev, 1000, BNC, ping_media, dc2114x_autoconf); break; - + case SPD_DET: /* Choose 10Mb/s or 100Mb/s */ if (srom_map_media(dev) < 0) { lp->tcount++; @@ -3161,7 +3161,7 @@ dc2114x_autoconf(struct net_device *dev) next_tick = dc2114x_autoconf(dev); } else if (((lp->media == _100Mb) && is_100_up(dev)) || (((lp->media == _10Mb) || (lp->media == TP) || - (lp->media == BNC) || (lp->media == AUI)) && + (lp->media == BNC) || (lp->media == AUI)) && is_10_up(dev))) { next_tick = dc2114x_autoconf(dev); } else { @@ -3169,7 +3169,7 @@ dc2114x_autoconf(struct net_device *dev) lp->media = INIT; } break; - + case _10Mb: next_tick = 3000; if (!lp->tx_enable) { @@ -3208,7 +3208,7 @@ printk("Huh?: media:%02x\n", lp->media); lp->media = INIT; break; } - + return next_tick; } @@ -3231,7 +3231,7 @@ srom_map_media(struct net_device *dev) struct de4x5_private *lp = netdev_priv(dev); lp->fdx = 0; - if (lp->infoblock_media == lp->media) + if (lp->infoblock_media == lp->media) return 0; switch(lp->infoblock_media) { @@ -3270,7 +3270,7 @@ srom_map_media(struct net_device *dev) case SROM_100BASEFF: if (!lp->params.fdx) return -1; lp->fdx = TRUE; - case SROM_100BASEF: + case SROM_100BASEF: if (lp->params.fdx && !lp->fdx) return -1; lp->media = _100Mb; break; @@ -3280,8 +3280,8 @@ srom_map_media(struct net_device *dev) lp->fdx = lp->params.fdx; break; - default: - printk("%s: Bad media code [%d] detected in SROM!\n", dev->name, + default: + printk("%s: Bad media code [%d] detected in SROM!\n", dev->name, lp->infoblock_media); return -1; break; @@ -3359,7 +3359,7 @@ test_media(struct net_device *dev, s32 i struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; s32 sts, csr12; - + if (lp->timeout < 0) { lp->timeout = msec/100; if (!lp->useSROM) { /* Already done if by SROM, else dc2104[01] */ @@ -3372,22 +3372,22 @@ test_media(struct net_device *dev, s32 i /* clear all pending interrupts */ sts = inl(DE4X5_STS); outl(sts, DE4X5_STS); - + /* clear csr12 NRA and SRA bits */ if ((lp->chipset == DC21041) || lp->useSROM) { csr12 = inl(DE4X5_SISR); outl(csr12, DE4X5_SISR); } } - + sts = inl(DE4X5_STS) & ~TIMER_CB; - + if (!(sts & irqs) && --lp->timeout) { sts = 100 | TIMER_CB; } else { lp->timeout = -1; } - + return sts; } @@ -3397,11 +3397,11 @@ test_tp(struct net_device *dev, s32 msec struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; int sisr; - + if (lp->timeout < 0) { lp->timeout = msec/100; } - + sisr = (inl(DE4X5_SISR) & ~TIMER_CB) & (SISR_LKF | SISR_NCR); if (sisr && --lp->timeout) { @@ -3409,7 +3409,7 @@ test_tp(struct net_device *dev, s32 msec } else { lp->timeout = -1; } - + return sisr; } @@ -3436,7 +3436,7 @@ test_for_100Mb(struct net_device *dev, i lp->timeout = msec/SAMPLE_INTERVAL; } } - + if (lp->phy[lp->active].id || lp->useSROM) { gep = is_100_up(dev) | is_spd_100(dev); } else { @@ -3447,7 +3447,7 @@ test_for_100Mb(struct net_device *dev, i } else { lp->timeout = -1; } - + return gep; } @@ -3459,13 +3459,13 @@ wait_for_link(struct net_device *dev) if (lp->timeout < 0) { lp->timeout = 1; } - + if (lp->timeout--) { return TIMER_CB; } else { lp->timeout = -1; } - + return 0; } @@ -3479,21 +3479,21 @@ test_mii_reg(struct net_device *dev, int struct de4x5_private *lp = netdev_priv(dev); int test; u_long iobase = dev->base_addr; - + if (lp->timeout < 0) { lp->timeout = msec/100; } - + if (pol) pol = ~0; reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask; test = (reg ^ pol) & mask; - + if (test && --lp->timeout) { reg = 100 | TIMER_CB; } else { lp->timeout = -1; } - + return reg; } @@ -3503,7 +3503,7 @@ is_spd_100(struct net_device *dev) struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; int spd; - + if (lp->useMII) { spd = mii_rd(lp->phy[lp->active].spd.reg, lp->phy[lp->active].addr, DE4X5_MII); spd = ~(spd ^ lp->phy[lp->active].spd.value); @@ -3517,7 +3517,7 @@ is_spd_100(struct net_device *dev) spd = (lp->asBitValid & (lp->asPolarity ^ (gep_rd(dev) & lp->asBit))) | (lp->linkOK & ~lp->asBitValid); } - + return spd; } @@ -3526,7 +3526,7 @@ is_100_up(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; - + if (lp->useMII) { /* Double read for sticky bits & temporary drops */ mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII); @@ -3547,7 +3547,7 @@ is_10_up(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; - + if (lp->useMII) { /* Double read for sticky bits & temporary drops */ mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII); @@ -3570,7 +3570,7 @@ is_anc_capable(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; - + if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) { return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII)); } else if ((lp->chipset & ~0x00ff) == DC2114x) { @@ -3590,24 +3590,24 @@ ping_media(struct net_device *dev, int m struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; int sisr; - + if (lp->timeout < 0) { lp->timeout = msec/100; - + lp->tmp = lp->tx_new; /* Remember the ring position */ load_packet(dev, lp->frame, TD_LS | TD_FS | sizeof(lp->frame), (struct sk_buff *)1); lp->tx_new = (++lp->tx_new) % lp->txRingSize; outl(POLL_DEMAND, DE4X5_TPD); } - + sisr = inl(DE4X5_SISR); - if ((!(sisr & SISR_NCR)) && - ((s32)le32_to_cpu(lp->tx_ring[lp->tmp].status) < 0) && + if ((!(sisr & SISR_NCR)) && + ((s32)le32_to_cpu(lp->tx_ring[lp->tmp].status) < 0) && (--lp->timeout)) { sisr = 100 | TIMER_CB; } else { - if ((!(sisr & SISR_NCR)) && + if ((!(sisr & SISR_NCR)) && !(le32_to_cpu(lp->tx_ring[lp->tmp].status) & (T_OWN | TD_ES)) && lp->timeout) { sisr = 0; @@ -3616,7 +3616,7 @@ ping_media(struct net_device *dev, int m } lp->timeout = -1; } - + return sisr; } @@ -3668,7 +3668,7 @@ #else } else { /* Linear buffer */ memcpy(skb_put(p,len),lp->rx_bufs + lp->rx_old * RX_BUFF_SZ,len); } - + return p; #endif } @@ -3751,23 +3751,23 @@ de4x5_rst_desc_ring(struct net_device *d outl(lp->dma_rings, DE4X5_RRBA); outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc), DE4X5_TRBA); - + lp->rx_new = lp->rx_old = 0; lp->tx_new = lp->tx_old = 0; - + for (i = 0; i < lp->rxRingSize; i++) { lp->rx_ring[i].status = cpu_to_le32(R_OWN); } - + for (i = 0; i < lp->txRingSize; i++) { lp->tx_ring[i].status = cpu_to_le32(0); } - + barrier(); lp->cache.save_cnt--; START_DE4X5; } - + return; } @@ -3792,7 +3792,7 @@ de4x5_cache_state(struct net_device *dev gep_wr(lp->cache.gepc, dev); gep_wr(lp->cache.gep, dev); } else { - reset_init_sia(dev, lp->cache.csr13, lp->cache.csr14, + reset_init_sia(dev, lp->cache.csr13, lp->cache.csr14, lp->cache.csr15); } break; @@ -3854,25 +3854,25 @@ test_ans(struct net_device *dev, s32 irq struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; s32 sts, ans; - + if (lp->timeout < 0) { lp->timeout = msec/100; outl(irq_mask, DE4X5_IMR); - + /* clear all pending interrupts */ sts = inl(DE4X5_STS); outl(sts, DE4X5_STS); } - + ans = inl(DE4X5_SISR) & SISR_ANS; sts = inl(DE4X5_STS) & ~TIMER_CB; - + if (!(sts & irqs) && (ans ^ ANS_NWOK) && --lp->timeout) { sts = 100 | TIMER_CB; } else { lp->timeout = -1; } - + return sts; } @@ -3882,7 +3882,7 @@ de4x5_setup_intr(struct net_device *dev) struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; s32 imr, sts; - + if (inl(DE4X5_OMR) & OMR_SR) { /* Only unmask if TX/RX is enabled */ imr = 0; UNMASK_IRQs; @@ -3890,7 +3890,7 @@ de4x5_setup_intr(struct net_device *dev) outl(sts, DE4X5_STS); ENABLE_IRQs; } - + return; } @@ -3936,17 +3936,17 @@ create_packet(struct net_device *dev, ch { int i; char *buf = frame; - + for (i=0; idev_addr[i]; } for (i=0; idev_addr[i]; } - + *buf++ = 0; /* Packet length (2 bytes) */ *buf++ = 1; - + return; } @@ -3978,7 +3978,7 @@ static int PCI_signature(char *name, struct de4x5_private *lp) { int i, status = 0, siglen = sizeof(de4x5_signatures)/sizeof(c_char *); - + if (lp->chipset == DC21040) { strcpy(name, "DE434/5"); return status; @@ -4007,7 +4007,7 @@ PCI_signature(char *name, struct de4x5_p } else if ((lp->chipset & ~0x00ff) == DC2114x) { lp->useSROM = TRUE; } - + return status; } @@ -4024,7 +4024,7 @@ DevicePresent(struct net_device *dev, u_ { int i, j=0; struct de4x5_private *lp = netdev_priv(dev); - + if (lp->chipset == DC21040) { if (lp->bus == EISA) { enet_addr_rst(aprom_addr); /* Reset Ethernet Address ROM Pointer */ @@ -4049,7 +4049,7 @@ DevicePresent(struct net_device *dev, u_ } de4x5_dbg_srom((struct de4x5_srom *)&lp->srom); } - + return; } @@ -4071,11 +4071,11 @@ enet_addr_rst(u_long aprom_addr) short sigLength=0; s8 data; int i, j; - + dev.llsig.a = ETH_PROM_SIG; dev.llsig.b = ETH_PROM_SIG; sigLength = sizeof(u32) << 1; - + for (i=0,j=0;j 0xffff) k-=0xffff; - + if (lp->bus == PCI) { if (lp->chipset == DC21040) { while ((tmp = inl(DE4X5_APROM)) < 0); @@ -4133,11 +4133,11 @@ get_hw_addr(struct net_device *dev) k += (u_short) ((tmp = inb(EISA_APROM)) << 8); dev->dev_addr[i++] = (u_char) tmp; } - + if (k > 0xffff) k-=0xffff; } if (k == 0xffff) k=0; - + if (lp->bus == PCI) { if (lp->chipset == DC21040) { while ((tmp = inl(DE4X5_APROM)) < 0); @@ -4156,7 +4156,7 @@ get_hw_addr(struct net_device *dev) srom_repair(dev, broken); #ifdef CONFIG_PPC_MULTIPLATFORM - /* + /* ** If the address starts with 00 a0, we have to bit-reverse ** each byte of the address. */ @@ -4245,7 +4245,7 @@ test_bad_enet(struct net_device *dev, in for (tmp=0,i=0; idev_addr[i]; if ((tmp == 0) || (tmp == 0x5fa)) { - if ((lp->chipset == last.chipset) && + if ((lp->chipset == last.chipset) && (lp->bus_num == last.bus) && (lp->bus_num > 0)) { for (i=0; idev_addr[i] = last.addr[i]; for (i=ETH_ALEN-1; i>2; --i) { @@ -4275,7 +4275,7 @@ test_bad_enet(struct net_device *dev, in static int an_exception(struct de4x5_private *lp) { - if ((*(u_short *)lp->srom.sub_vendor_id == 0x00c0) && + if ((*(u_short *)lp->srom.sub_vendor_id == 0x00c0) && (*(u_short *)lp->srom.sub_system_id == 0x95e0)) { return -1; } @@ -4290,11 +4290,11 @@ static short srom_rd(u_long addr, u_char offset) { sendto_srom(SROM_RD | SROM_SR, addr); - + srom_latch(SROM_RD | SROM_SR | DT_CS, addr); srom_command(SROM_RD | SROM_SR | DT_IN | DT_CS, addr); srom_address(SROM_RD | SROM_SR | DT_CS, addr, offset); - + return srom_data(SROM_RD | SROM_SR | DT_CS, addr); } @@ -4304,7 +4304,7 @@ srom_latch(u_int command, u_long addr) sendto_srom(command, addr); sendto_srom(command | DT_CLK, addr); sendto_srom(command, addr); - + return; } @@ -4314,7 +4314,7 @@ srom_command(u_int command, u_long addr) srom_latch(command, addr); srom_latch(command, addr); srom_latch((command & 0x0000ff00) | DT_CS, addr); - + return; } @@ -4322,15 +4322,15 @@ static void srom_address(u_int command, u_long addr, u_char offset) { int i, a; - + a = offset << 2; for (i=0; i<6; i++, a <<= 1) { srom_latch(command | ((a & 0x80) ? DT_IN : 0), addr); } udelay(1); - + i = (getfrom_srom(addr) >> 3) & 0x01; - + return; } @@ -4340,17 +4340,17 @@ srom_data(u_int command, u_long addr) int i; short word = 0; s32 tmp; - + for (i=0; i<16; i++) { sendto_srom(command | DT_CLK, addr); tmp = getfrom_srom(addr); sendto_srom(command, addr); - + word = (word << 1) | ((tmp >> 3) & 0x01); } - + sendto_srom(command & 0x0000ff00, addr); - + return word; } @@ -4359,13 +4359,13 @@ static void srom_busy(u_int command, u_long addr) { sendto_srom((command & 0x0000ff00) | DT_CS, addr); - + while (!((getfrom_srom(addr) >> 3) & 0x01)) { mdelay(1); } - + sendto_srom(command & 0x0000ff00, addr); - + return; } */ @@ -4375,7 +4375,7 @@ sendto_srom(u_int command, u_long addr) { outl(command, addr); udelay(1); - + return; } @@ -4383,10 +4383,10 @@ static int getfrom_srom(u_long addr) { s32 tmp; - + tmp = inl(addr); udelay(1); - + return tmp; } @@ -4403,7 +4403,7 @@ srom_infoleaf_info(struct net_device *de } if (i == INFOLEAF_SIZE) { lp->useSROM = FALSE; - printk("%s: Cannot find correct chipset for SROM decoding!\n", + printk("%s: Cannot find correct chipset for SROM decoding!\n", dev->name); return -ENXIO; } @@ -4420,7 +4420,7 @@ srom_infoleaf_info(struct net_device *de } if (i == 0) { lp->useSROM = FALSE; - printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n", + printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n", dev->name, lp->device); return -ENXIO; } @@ -4494,9 +4494,9 @@ srom_exec(struct net_device *dev, u_char if (((lp->ibn != 1) && (lp->ibn != 3) && (lp->ibn != 5)) || !count) return; if (lp->chipset != DC21140) RESET_SIA; - + while (count--) { - gep_wr(((lp->chipset==DC21140) && (lp->ibn!=5) ? + gep_wr(((lp->chipset==DC21140) && (lp->ibn!=5) ? *p++ : TWIDDLE(w++)), dev); mdelay(2); /* 2ms per action */ } @@ -4514,13 +4514,13 @@ srom_exec(struct net_device *dev, u_char ** unless I implement the DC21041 SROM functions. There's no need ** since the existing code will be satisfactory for all boards. */ -static int +static int dc21041_infoleaf(struct net_device *dev) { return DE4X5_AUTOSENSE_MS; } -static int +static int dc21140_infoleaf(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); @@ -4558,7 +4558,7 @@ dc21140_infoleaf(struct net_device *dev) return next_tick & ~TIMER_CB; } -static int +static int dc21142_infoleaf(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); @@ -4593,7 +4593,7 @@ dc21142_infoleaf(struct net_device *dev) return next_tick & ~TIMER_CB; } -static int +static int dc21143_infoleaf(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); @@ -4631,7 +4631,7 @@ dc21143_infoleaf(struct net_device *dev) ** The compact infoblock is only designed for DC21140[A] chips, so ** we'll reuse the dc21140m_autoconf function. Non MII media only. */ -static int +static int compact_infoblock(struct net_device *dev, u_char count, u_char *p) { struct de4x5_private *lp = netdev_priv(dev); @@ -4671,7 +4671,7 @@ compact_infoblock(struct net_device *dev /* ** This block describes non MII media for the DC21140[A] only. */ -static int +static int type0_infoblock(struct net_device *dev, u_char count, u_char *p) { struct de4x5_private *lp = netdev_priv(dev); @@ -4711,7 +4711,7 @@ type0_infoblock(struct net_device *dev, /* These functions are under construction! */ -static int +static int type1_infoblock(struct net_device *dev, u_char count, u_char *p) { struct de4x5_private *lp = netdev_priv(dev); @@ -4750,7 +4750,7 @@ type1_infoblock(struct net_device *dev, return dc21140m_autoconf(dev); } -static int +static int type2_infoblock(struct net_device *dev, u_char count, u_char *p) { struct de4x5_private *lp = netdev_priv(dev); @@ -4791,7 +4791,7 @@ type2_infoblock(struct net_device *dev, return dc2114x_autoconf(dev); } -static int +static int type3_infoblock(struct net_device *dev, u_char count, u_char *p) { struct de4x5_private *lp = netdev_priv(dev); @@ -4833,7 +4833,7 @@ type3_infoblock(struct net_device *dev, return dc2114x_autoconf(dev); } -static int +static int type4_infoblock(struct net_device *dev, u_char count, u_char *p) { struct de4x5_private *lp = netdev_priv(dev); @@ -4878,7 +4878,7 @@ type4_infoblock(struct net_device *dev, ** This block type provides information for resetting external devices ** (chips) through the General Purpose Register. */ -static int +static int type5_infoblock(struct net_device *dev, u_char count, u_char *p) { struct de4x5_private *lp = netdev_priv(dev); @@ -4916,7 +4916,7 @@ mii_rd(u_char phyreg, u_char phyaddr, u_ mii_address(phyaddr, ioaddr); /* PHY address to be accessed */ mii_address(phyreg, ioaddr); /* PHY Register to read */ mii_ta(MII_STRD, ioaddr); /* Turn around time - 2 MDC */ - + return mii_rdata(ioaddr); /* Read data */ } @@ -4931,7 +4931,7 @@ mii_wr(int data, u_char phyreg, u_char p mii_ta(MII_STWR, ioaddr); /* Turn around time - 2 MDC */ data = mii_swap(data, 16); /* Swap data bit ordering */ mii_wdata(data, 16, ioaddr); /* Write data */ - + return; } @@ -4940,12 +4940,12 @@ mii_rdata(u_long ioaddr) { int i; s32 tmp = 0; - + for (i=0; i<16; i++) { tmp <<= 1; tmp |= getfrom_mii(MII_MRD | MII_RD, ioaddr); } - + return tmp; } @@ -4953,12 +4953,12 @@ static void mii_wdata(int data, int len, u_long ioaddr) { int i; - + for (i=0; i>= 1; } - + return; } @@ -4966,13 +4966,13 @@ static void mii_address(u_char addr, u_long ioaddr) { int i; - + addr = mii_swap(addr, 5); for (i=0; i<5; i++) { sendto_mii(MII_MWR | MII_WR, addr, ioaddr); addr >>= 1; } - + return; } @@ -4980,12 +4980,12 @@ static void mii_ta(u_long rw, u_long ioaddr) { if (rw == MII_STWR) { - sendto_mii(MII_MWR | MII_WR, 1, ioaddr); - sendto_mii(MII_MWR | MII_WR, 0, ioaddr); + sendto_mii(MII_MWR | MII_WR, 1, ioaddr); + sendto_mii(MII_MWR | MII_WR, 0, ioaddr); } else { getfrom_mii(MII_MRD | MII_RD, ioaddr); /* Tri-state MDIO */ } - + return; } @@ -4993,13 +4993,13 @@ static int mii_swap(int data, int len) { int i, tmp = 0; - + for (i=0; i>= 1; } - + return tmp; } @@ -5007,13 +5007,13 @@ static void sendto_mii(u32 command, int data, u_long ioaddr) { u32 j; - + j = (data & 1) << 17; outl(command | j, ioaddr); udelay(1); outl(command | MII_MDC | j, ioaddr); udelay(1); - + return; } @@ -5024,7 +5024,7 @@ getfrom_mii(u32 command, u_long ioaddr) udelay(1); outl(command | MII_MDC, ioaddr); udelay(1); - + return ((inl(ioaddr) >> 19) & 1); } @@ -5085,7 +5085,7 @@ mii_get_phy(struct net_device *dev) u_long iobase = dev->base_addr; int i, j, k, n, limit=sizeof(phy_info)/sizeof(struct phy_table); int id; - + lp->active = 0; lp->useMII = TRUE; @@ -5094,7 +5094,7 @@ mii_get_phy(struct net_device *dev) lp->phy[lp->active].addr = i; if (i==0) n++; /* Count cycles */ while (de4x5_reset_phy(dev)<0) udelay(100);/* Wait for reset */ - id = mii_get_oui(i, DE4X5_MII); + id = mii_get_oui(i, DE4X5_MII); if ((id == 0) || (id == 65535)) continue; /* Valid ID? */ for (j=0; jphy[k].id && (k < DE4X5_MAX_PHY); k++) { /*For each PHY*/ mii_wr(MII_CR_RST, MII_CR, lp->phy[k].addr, DE4X5_MII); while (mii_rd(MII_CR, lp->phy[k].addr, DE4X5_MII) & MII_CR_RST); - + de4x5_dbg_mii(dev, k); } } @@ -5148,12 +5148,12 @@ build_setup_frame(struct net_device *dev struct de4x5_private *lp = netdev_priv(dev); int i; char *pa = lp->setup_frame; - + /* Initialise the setup frame */ if (mode == ALL) { memset(lp->setup_frame, 0, SETUP_FRAME_LEN); } - + if (lp->setup_f == HASH_PERF) { for (pa=lp->setup_frame+IMPERF_PA_OFFSET, i=0; idev_addr[i]; /* Host address */ @@ -5170,7 +5170,7 @@ build_setup_frame(struct net_device *dev if (i & 0x01) pa += 4; } } - + return pa; /* Points to the next entry */ } @@ -5178,7 +5178,7 @@ static void enable_ast(struct net_device *dev, u32 time_out) { timeout(dev, (void *)&de4x5_ast, (u_long)dev, time_out); - + return; } @@ -5186,9 +5186,9 @@ static void disable_ast(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); - + del_timer(&lp->timer); - + return; } @@ -5207,10 +5207,10 @@ de4x5_switch_mac_port(struct net_device omr |= lp->infoblock_csr6; if (omr & OMR_PS) omr |= OMR_HBD; outl(omr, DE4X5_OMR); - + /* Soft Reset */ RESET_DE4X5; - + /* Restore the GEP - especially for COMPACT and Type 0 Infoblocks */ if (lp->chipset == DC21140) { gep_wr(lp->cache.gepc, dev); @@ -5263,21 +5263,21 @@ timeout(struct net_device *dev, void (*f { struct de4x5_private *lp = netdev_priv(dev); int dt; - + /* First, cancel any pending timer events */ del_timer(&lp->timer); - + /* Convert msec to ticks */ dt = (msec * HZ) / 1000; if (dt==0) dt=1; - + /* Set up timer */ init_timer(&lp->timer); lp->timer.expires = jiffies + dt; lp->timer.function = fn; lp->timer.data = data; add_timer(&lp->timer); - + return; } @@ -5375,7 +5375,7 @@ de4x5_dbg_open(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); int i; - + if (de4x5_debug & DEBUG_OPEN) { printk("%s: de4x5 opening with irq %d\n",dev->name,dev->irq); printk("\tphysical address: "); @@ -5413,11 +5413,11 @@ de4x5_dbg_open(struct net_device *dev) } } printk("...0x%8.8x\n", le32_to_cpu(lp->tx_ring[i].buf)); - printk("Ring size: \nRX: %d\nTX: %d\n", - (short)lp->rxRingSize, - (short)lp->txRingSize); + printk("Ring size: \nRX: %d\nTX: %d\n", + (short)lp->rxRingSize, + (short)lp->txRingSize); } - + return; } @@ -5426,7 +5426,7 @@ de4x5_dbg_mii(struct net_device *dev, in { struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; - + if (de4x5_debug & DEBUG_MII) { printk("\nMII device address: %d\n", lp->phy[k].addr); printk("MII CR: %x\n",mii_rd(MII_CR,lp->phy[k].addr,DE4X5_MII)); @@ -5445,7 +5445,7 @@ de4x5_dbg_mii(struct net_device *dev, in printk("MII 20: %x\n",mii_rd(0x14,lp->phy[k].addr,DE4X5_MII)); } } - + return; } @@ -5453,17 +5453,17 @@ static void de4x5_dbg_media(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); - + if (lp->media != lp->c_media) { if (de4x5_debug & DEBUG_MEDIA) { printk("%s: media is %s%s\n", dev->name, (lp->media == NC ? "unconnected, link down or incompatible connection" : (lp->media == TP ? "TP" : (lp->media == ANS ? "TP/Nway" : - (lp->media == BNC ? "BNC" : - (lp->media == AUI ? "AUI" : - (lp->media == BNC_AUI ? "BNC/AUI" : - (lp->media == EXT_SIA ? "EXT SIA" : + (lp->media == BNC ? "BNC" : + (lp->media == AUI ? "AUI" : + (lp->media == BNC_AUI ? "BNC/AUI" : + (lp->media == EXT_SIA ? "EXT SIA" : (lp->media == _100Mb ? "100Mb/s" : (lp->media == _10Mb ? "10Mb/s" : "???" @@ -5471,7 +5471,7 @@ de4x5_dbg_media(struct net_device *dev) } lp->c_media = lp->media; } - + return; } @@ -5554,7 +5554,7 @@ de4x5_ioctl(struct net_device *dev, stru u32 lval[36]; } tmp; u_long flags = 0; - + switch(ioc->cmd) { case DE4X5_GET_HWADDR: /* Get the hardware address */ ioc->len = ETH_ALEN; @@ -5575,7 +5575,7 @@ de4x5_ioctl(struct net_device *dev, stru } build_setup_frame(dev, PHYS_ADDR_ONLY); /* Set up the descriptor and give ownership to the card */ - load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | + load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | SETUP_FRAME_LEN, (struct sk_buff *)1); lp->tx_new = (++lp->tx_new) % lp->txRingSize; outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */ @@ -5617,8 +5617,8 @@ de4x5_ioctl(struct net_device *dev, stru spin_lock_irqsave(&lp->lock, flags); memcpy(&statbuf, &lp->pktStats, ioc->len); spin_unlock_irqrestore(&lp->lock, flags); - if (copy_to_user(ioc->data, &statbuf, ioc->len)) - return -EFAULT; + if (copy_to_user(ioc->data, &statbuf, ioc->len)) + return -EFAULT; break; } case DE4X5_CLR_STATS: /* Zero out the driver statistics */ @@ -5652,9 +5652,9 @@ de4x5_ioctl(struct net_device *dev, stru ioc->len = j; if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; break; - + #define DE4X5_DUMP 0x0f /* Dump the DE4X5 Status */ -/* +/* case DE4X5_DUMP: j = 0; tmp.addr[j++] = dev->irq; @@ -5664,7 +5664,7 @@ #define DE4X5_DUMP 0x0f /* tmp.addr[j++] = lp->rxRingSize; tmp.lval[j>>2] = (long)lp->rx_ring; j+=4; tmp.lval[j>>2] = (long)lp->tx_ring; j+=4; - + for (i=0;irxRingSize-1;i++){ if (i < 3) { tmp.lval[j>>2] = (long)&lp->rx_ring[i].status; j+=4; @@ -5677,7 +5677,7 @@ #define DE4X5_DUMP 0x0f /* } } tmp.lval[j>>2] = (long)&lp->tx_ring[i].status; j+=4; - + for (i=0;irxRingSize-1;i++){ if (i < 3) { tmp.lval[j>>2] = (s32)le32_to_cpu(lp->rx_ring[i].buf); j+=4; @@ -5690,14 +5690,14 @@ #define DE4X5_DUMP 0x0f /* } } tmp.lval[j>>2] = (s32)le32_to_cpu(lp->tx_ring[i].buf); j+=4; - + for (i=0;irxRingSize;i++){ tmp.lval[j>>2] = le32_to_cpu(lp->rx_ring[i].status); j+=4; } for (i=0;itxRingSize;i++){ tmp.lval[j>>2] = le32_to_cpu(lp->tx_ring[i].status); j+=4; } - + tmp.lval[j>>2] = inl(DE4X5_BMR); j+=4; tmp.lval[j>>2] = inl(DE4X5_TPD); j+=4; tmp.lval[j>>2] = inl(DE4X5_RPD); j+=4; @@ -5706,18 +5706,18 @@ #define DE4X5_DUMP 0x0f /* tmp.lval[j>>2] = inl(DE4X5_STS); j+=4; tmp.lval[j>>2] = inl(DE4X5_OMR); j+=4; tmp.lval[j>>2] = inl(DE4X5_IMR); j+=4; - tmp.lval[j>>2] = lp->chipset; j+=4; + tmp.lval[j>>2] = lp->chipset; j+=4; if (lp->chipset == DC21140) { tmp.lval[j>>2] = gep_rd(dev); j+=4; } else { tmp.lval[j>>2] = inl(DE4X5_SISR); j+=4; tmp.lval[j>>2] = inl(DE4X5_SICR); j+=4; tmp.lval[j>>2] = inl(DE4X5_STRR); j+=4; - tmp.lval[j>>2] = inl(DE4X5_SIGR); j+=4; + tmp.lval[j>>2] = inl(DE4X5_SIGR); j+=4; } - tmp.lval[j>>2] = lp->phy[lp->active].id; j+=4; + tmp.lval[j>>2] = lp->phy[lp->active].id; j+=4; if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) { - tmp.lval[j>>2] = lp->active; j+=4; + tmp.lval[j>>2] = lp->active; j+=4; tmp.lval[j>>2]=mii_rd(MII_CR,lp->phy[lp->active].addr,DE4X5_MII); j+=4; tmp.lval[j>>2]=mii_rd(MII_SR,lp->phy[lp->active].addr,DE4X5_MII); j+=4; tmp.lval[j>>2]=mii_rd(MII_ID0,lp->phy[lp->active].addr,DE4X5_MII); j+=4; @@ -5734,10 +5734,10 @@ #define DE4X5_DUMP 0x0f /* tmp.lval[j>>2]=mii_rd(0x14,lp->phy[lp->active].addr,DE4X5_MII); j+=4; } } - + tmp.addr[j++] = lp->txRingSize; tmp.addr[j++] = netif_queue_stopped(dev); - + ioc->len = j; if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; break; @@ -5746,7 +5746,7 @@ #define DE4X5_DUMP 0x0f /* default: return -EOPNOTSUPP; } - + return status; } diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h index ad37a40..57226e5 100644 --- a/drivers/net/tulip/de4x5.h +++ b/drivers/net/tulip/de4x5.h @@ -38,11 +38,11 @@ #define DE4X5_SIGR iobase+(0x078 << lp /* ** EISA Register Address Map */ -#define EISA_ID iobase+0x0c80 /* EISA ID Registers */ -#define EISA_ID0 iobase+0x0c80 /* EISA ID Register 0 */ -#define EISA_ID1 iobase+0x0c81 /* EISA ID Register 1 */ -#define EISA_ID2 iobase+0x0c82 /* EISA ID Register 2 */ -#define EISA_ID3 iobase+0x0c83 /* EISA ID Register 3 */ +#define EISA_ID iobase+0x0c80 /* EISA ID Registers */ +#define EISA_ID0 iobase+0x0c80 /* EISA ID Register 0 */ +#define EISA_ID1 iobase+0x0c81 /* EISA ID Register 1 */ +#define EISA_ID2 iobase+0x0c82 /* EISA ID Register 2 */ +#define EISA_ID3 iobase+0x0c83 /* EISA ID Register 3 */ #define EISA_CR iobase+0x0c84 /* EISA Control Register */ #define EISA_REG0 iobase+0x0c88 /* EISA Configuration Register 0 */ #define EISA_REG1 iobase+0x0c89 /* EISA Configuration Register 1 */ @@ -1008,8 +1008,8 @@ struct de4x5_ioctl { unsigned char __user *data; /* Pointer to the data buffer */ }; -/* -** Recognised commands for the driver +/* +** Recognised commands for the driver */ #define DE4X5_GET_HWADDR 0x01 /* Get the hardware address */ #define DE4X5_SET_HWADDR 0x02 /* Set the hardware address */ diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 74e9075..ba5b112 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -50,7 +50,7 @@ forget to unmap PCI mapped skbs. Alan Cox - Added new PCI identifiers provided by Clear Zhang at ALi + Added new PCI identifiers provided by Clear Zhang at ALi for their 1563 ethernet device. TODO diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c index fbd9ab6..5ffbd5b 100644 --- a/drivers/net/tulip/eeprom.c +++ b/drivers/net/tulip/eeprom.c @@ -96,11 +96,11 @@ static const char *block_name[] __devini * tulip_build_fake_mediatable - Build a fake mediatable entry. * @tp: Ptr to the tulip private data. * - * Some cards like the 3x5 HSC cards (J3514A) do not have a standard + * Some cards like the 3x5 HSC cards (J3514A) do not have a standard * srom and can not be handled under the fixup routine. These cards - * still need a valid mediatable entry for correct csr12 setup and + * still need a valid mediatable entry for correct csr12 setup and * mii handling. - * + * * Since this is currently a parisc-linux specific function, the * #ifdef __hppa__ should completely optimize this function away for * non-parisc hardware. @@ -140,7 +140,7 @@ #ifdef CONFIG_GSC tp->flags |= HAS_PHY_IRQ; tp->csr12_shadow = -1; } -#endif +#endif } void __devinit tulip_parse_eeprom(struct net_device *dev) diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index bb35581..da4f759 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -139,22 +139,22 @@ #endif } /* Acknowledge current RX interrupt sources. */ iowrite32((RxIntr | RxNoBuf), tp->base_addr + CSR5); - - + + /* If we own the next entry, it is a new packet. Send it up. */ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { s32 status = le32_to_cpu(tp->rx_ring[entry].status); - - + + if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx) break; - + if (tulip_debug > 5) printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n", dev->name, entry, status); if (--rx_work_limit < 0) goto not_done; - + if ((status & 0x38008300) != 0x0300) { if ((status & 0x38000300) != 0x0300) { /* Ingore earlier buffers. */ @@ -180,7 +180,7 @@ #endif /* Omit the four octet CRC from the length. */ short pkt_len = ((status >> 16) & 0x7ff) - 4; struct sk_buff *skb; - + #ifndef final_version if (pkt_len > 1518) { printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n", @@ -213,7 +213,7 @@ #endif } else { /* Pass up the skb already on the Rx ring. */ char *temp = skb_put(skb = tp->rx_buffers[entry].skb, pkt_len); - + #ifndef final_version if (tp->rx_buffers[entry].mapping != le32_to_cpu(tp->rx_ring[entry].buffer1)) { @@ -225,17 +225,17 @@ #ifndef final_version skb->head, temp); } #endif - + pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); - + tp->rx_buffers[entry].skb = NULL; tp->rx_buffers[entry].mapping = 0; } skb->protocol = eth_type_trans(skb, dev); - + netif_receive_skb(skb); - + dev->last_rx = jiffies; tp->stats.rx_packets++; tp->stats.rx_bytes += pkt_len; @@ -245,12 +245,12 @@ #endif entry = (++tp->cur_rx) % RX_RING_SIZE; if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4) tulip_refill_rx(dev); - + } - + /* New ack strategy... irq does not ack Rx any longer hopefully this helps */ - + /* Really bad things can happen here... If new packet arrives * and an irq arrives (tx or just due to occasionally unset * mask), it will be acked by irq handler, but new thread @@ -259,28 +259,28 @@ #endif * tomorrow (night 011029). If it will not fail, we won * finally: amount of IO did not increase at all. */ } while ((ioread32(tp->base_addr + CSR5) & RxIntr)); - + done: - + #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION - + /* We use this simplistic scheme for IM. It's proven by real life installations. We can have IM enabled - continuesly but this would cause unnecessary latency. - Unfortunely we can't use all the NET_RX_* feedback here. - This would turn on IM for devices that is not contributing - to backlog congestion with unnecessary latency. - + continuesly but this would cause unnecessary latency. + Unfortunely we can't use all the NET_RX_* feedback here. + This would turn on IM for devices that is not contributing + to backlog congestion with unnecessary latency. + We monitor the the device RX-ring and have: - + HW Interrupt Mitigation either ON or OFF. - - ON: More then 1 pkt received (per intr.) OR we are dropping + + ON: More then 1 pkt received (per intr.) OR we are dropping OFF: Only 1 pkt received - + Note. We only use min and max (0, 15) settings from mit_table */ - - + + if( tp->flags & HAS_INTR_MITIGATION) { if( received > 1 ) { if( ! tp->mit_on ) { @@ -297,20 +297,20 @@ done: } #endif /* CONFIG_TULIP_NAPI_HW_MITIGATION */ - + dev->quota -= received; *budget -= received; - + tulip_refill_rx(dev); - + /* If RX ring is not full we are out of memory. */ if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom; - + /* Remove us from polling list and enable RX intr. */ - + netif_rx_complete(dev); iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7); - + /* The last op happens after poll completion. Which means the following: * 1. it can race with disabling irqs in irq handler * 2. it can race with dise/enabling irqs in other poll threads @@ -321,9 +321,9 @@ #endif /* CONFIG_TULIP_NAPI_HW_MITIGATIO * due to races in masking and due to too late acking of already * processed irqs. But it must not result in losing events. */ - + return 0; - + not_done: if (!received) { @@ -331,29 +331,29 @@ #endif /* CONFIG_TULIP_NAPI_HW_MITIGATIO } dev->quota -= received; *budget -= received; - + if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 || tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) tulip_refill_rx(dev); - + if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom; - + return 1; - - + + oom: /* Executed with RX ints disabled */ - - + + /* Start timer, stop polling, but do not enable rx interrupts. */ mod_timer(&tp->oom_timer, jiffies+1); - + /* Think: timer_pending() was an explicit signature of bug. * Timer can be pending now but fired and completed * before we did netif_rx_complete(). See? We would lose it. */ - + /* remove ourselves from the polling list */ netif_rx_complete(dev); - + return 0; } @@ -521,9 +521,9 @@ #endif /* Let's see whether the interrupt really is for us */ csr5 = ioread32(ioaddr + CSR5); - if (tp->flags & HAS_PHY_IRQ) + if (tp->flags & HAS_PHY_IRQ) handled = phy_interrupt (dev); - + if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) return IRQ_RETVAL(handled); @@ -538,17 +538,17 @@ #ifdef CONFIG_TULIP_NAPI /* Mask RX intrs and add the device to poll list. */ iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7); netif_rx_schedule(dev); - + if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass))) break; } - + /* Acknowledge the interrupt sources we handle here ASAP the poll function does Rx and RxNoBuf acking */ - + iowrite32(csr5 & 0x0001ff3f, ioaddr + CSR5); -#else +#else /* Acknowledge all of the current interrupt sources ASAP. */ iowrite32(csr5 & 0x0001ffff, ioaddr + CSR5); @@ -559,11 +559,11 @@ #else } #endif /* CONFIG_TULIP_NAPI */ - + if (tulip_debug > 4) printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", dev->name, csr5, ioread32(ioaddr + CSR5)); - + if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { unsigned int dirty_tx; @@ -737,17 +737,17 @@ #endif #ifdef CONFIG_TULIP_NAPI if (rxd) csr5 &= ~RxPollInt; - } while ((csr5 & (TxNoBuf | - TxDied | - TxIntr | + } while ((csr5 & (TxNoBuf | + TxDied | + TxIntr | TimerInt | /* Abnormal intr. */ - RxDied | - TxFIFOUnderflow | - TxJabber | - TPLnkFail | + RxDied | + TxFIFOUnderflow | + TxJabber | + TPLnkFail | SytemError )) != 0); -#else +#else } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0); tulip_refill_rx(dev); diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c index f53396f..e9bc2a9 100644 --- a/drivers/net/tulip/media.c +++ b/drivers/net/tulip/media.c @@ -140,7 +140,7 @@ void tulip_mdio_write(struct net_device spin_unlock_irqrestore(&tp->mii_lock, flags); return; } - + /* Establish sync by sending 32 logic ones. */ for (i = 32; i >= 0; i--) { iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index 05d2d96..d25020d 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h @@ -259,7 +259,7 @@ enum t21143_csr6_bits { There are no ill effects from too-large receive rings. */ #define TX_RING_SIZE 32 -#define RX_RING_SIZE 128 +#define RX_RING_SIZE 128 #define MEDIA_MASK 31 #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */ diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index c67c912..e0de667 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -1224,7 +1224,7 @@ #endif * Chips that have the MRM/reserved bit quirk and the burst quirk. That * is the DM910X and the on chip ULi devices */ - + static int tulip_uli_dm_quirk(struct pci_dev *pdev) { if (pdev->vendor == 0x1282 && pdev->device == 0x9102) @@ -1297,7 +1297,7 @@ #endif */ /* 1. Intel Saturn. Switch to 8 long words burst, 8 long word cache - aligned. Aries might need this too. The Saturn errata are not + aligned. Aries might need this too. The Saturn errata are not pretty reading but thankfully it's an old 486 chipset. 2. The dreaded SiS496 486 chipset. Same workaround as Intel @@ -1483,14 +1483,6 @@ #endif sa_offset = 2; /* Grrr, damn Matrox boards. */ multiport_cnt = 4; } -#ifdef CONFIG_DDB5476 - if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 6)) { - /* DDB5476 MAC address in first EEPROM locations. */ - sa_offset = 0; - /* No media table either */ - tp->flags &= ~HAS_MEDIA_TABLE; - } -#endif #ifdef CONFIG_DDB5477 if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 4)) { /* DDB5477 MAC address in first EEPROM locations. */ @@ -1500,7 +1492,7 @@ #ifdef CONFIG_DDB5477 } #endif #ifdef CONFIG_MIPS_COBALT - if ((pdev->bus->number == 0) && + if ((pdev->bus->number == 0) && ((PCI_SLOT(pdev->devfn) == 7) || (PCI_SLOT(pdev->devfn) == 12))) { /* Cobalt MAC address in first EEPROM locations. */ @@ -1558,10 +1550,14 @@ #endif dev->dev_addr[i] = last_phys_addr[i]; dev->dev_addr[i] = last_phys_addr[i] + 1; #if defined(__sparc__) - if ((pcp != NULL) && prom_getproplen(pcp->prom_node, - "local-mac-address") == 6) { - prom_getproperty(pcp->prom_node, "local-mac-address", - dev->dev_addr, 6); + if (pcp) { + unsigned char *addr; + int len; + + addr = of_get_property(pcp->prom_node, + "local-mac-address", &len); + if (addr && len == 6) + memcpy(dev->dev_addr, addr, 6); } #endif #if defined(__i386__) || defined(__x86_64__) /* Patch up x86 BIOS bug. */ diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 238e9c7..8b3a28f 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -9,7 +9,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + */ #define DRV_NAME "uli526x" @@ -185,7 +185,7 @@ struct uli526x_board_info { /* NIC SROM data */ unsigned char srom[128]; - u8 init; + u8 init; }; enum uli526x_offsets { @@ -258,7 +258,7 @@ static int __devinit uli526x_init_one (s struct uli526x_board_info *db; /* board information structure */ struct net_device *dev; int i, err; - + ULI526X_DBUG(0, "uli526x_init_one()", 0); if (!printed_version++) @@ -316,7 +316,7 @@ static int __devinit uli526x_init_one (s err = -ENOMEM; goto err_out_nomem; } - + db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr; db->first_tx_desc_dma = db->desc_pool_dma_ptr; db->buf_pool_start = db->buf_pool_ptr; @@ -324,14 +324,14 @@ static int __devinit uli526x_init_one (s db->chip_id = ent->driver_data; db->ioaddr = pci_resource_start(pdev, 0); - + db->pdev = pdev; db->init = 1; - + dev->base_addr = db->ioaddr; dev->irq = pdev->irq; pci_set_drvdata(pdev, dev); - + /* Register some necessary functions */ dev->open = &uli526x_open; dev->hard_start_xmit = &uli526x_start_xmit; @@ -341,7 +341,7 @@ static int __devinit uli526x_init_one (s dev->ethtool_ops = &netdev_ethtool_ops; spin_lock_init(&db->lock); - + /* read 64 word srom data */ for (i = 0; i < 64; i++) ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i)); @@ -374,7 +374,7 @@ static int __devinit uli526x_init_one (s goto err_out_res; printk(KERN_INFO "%s: ULi M%04lx at pci%s,",dev->name,ent->driver_data >> 16,pci_name(pdev)); - + for (i = 0; i < 6; i++) printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]); printk(", irq %d.\n", dev->irq); @@ -389,7 +389,7 @@ err_out_nomem: if(db->desc_pool_ptr) pci_free_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, db->desc_pool_ptr, db->desc_pool_dma_ptr); - + if(db->buf_pool_ptr != NULL) pci_free_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, db->buf_pool_ptr, db->buf_pool_dma_ptr); @@ -433,7 +433,7 @@ static int uli526x_open(struct net_devic { int ret; struct uli526x_board_info *db = netdev_priv(dev); - + ULI526X_DBUG(0, "uli526x_open", 0); ret = request_irq(dev->irq, &uli526x_interrupt, SA_SHIRQ, dev->name, dev); @@ -454,7 +454,7 @@ static int uli526x_open(struct net_devic /* CR6 operation mode decision */ db->cr6_data |= ULI526X_TXTH_256; db->cr0_data = CR0_DEFAULT; - + /* Initialize ULI526X board */ uli526x_init(dev); @@ -604,7 +604,7 @@ static int uli526x_start_xmit(struct sk_ /* Restore CR7 to enable interrupt */ spin_unlock_irqrestore(&db->lock, flags); outl(db->cr7_data, dev->base_addr + DCR7); - + /* free this SKB */ dev_kfree_skb(skb); @@ -782,7 +782,7 @@ static void uli526x_rx_packet(struct net struct sk_buff *skb; int rxlen; u32 rdes0; - + rxptr = db->rx_ready_ptr; while(db->rx_avail_cnt) { @@ -821,7 +821,7 @@ static void uli526x_rx_packet(struct net if ( !(rdes0 & 0x8000) || ((db->cr6_data & CR6_PM) && (rxlen>6)) ) { skb = rxptr->rx_skb_ptr; - + /* Good packet, send to upper layer */ /* Shorst packet used new SKB */ if ( (rxlen < RX_COPY_SIZE) && @@ -841,7 +841,7 @@ static void uli526x_rx_packet(struct net dev->last_rx = jiffies; db->stats.rx_packets++; db->stats.rx_bytes += rxlen; - + } else { /* Reuse SKB buffer when the packet is error */ ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0); @@ -911,7 +911,7 @@ ULi_ethtool_gset(struct uli526x_board_in SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII); - + ecmd->advertising = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | @@ -924,13 +924,13 @@ ULi_ethtool_gset(struct uli526x_board_in ecmd->phy_address = db->phy_addr; ecmd->transceiver = XCVR_EXTERNAL; - + ecmd->speed = 10; ecmd->duplex = DUPLEX_HALF; - + if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD) { - ecmd->speed = 100; + ecmd->speed = 100; } if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD) { @@ -939,11 +939,11 @@ ULi_ethtool_gset(struct uli526x_board_in if(db->link_failed) { ecmd->speed = -1; - ecmd->duplex = -1; + ecmd->duplex = -1; } - + if (db->media_mode & ULI526X_AUTO) - { + { ecmd->autoneg = AUTONEG_ENABLE; } } @@ -964,15 +964,15 @@ static void netdev_get_drvinfo(struct ne static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct uli526x_board_info *np = netdev_priv(dev); - + ULi_ethtool_gset(np, cmd); - + return 0; } static u32 netdev_get_link(struct net_device *dev) { struct uli526x_board_info *np = netdev_priv(dev); - + if(np->link_failed) return 0; else @@ -1005,11 +1005,11 @@ static void uli526x_timer(unsigned long struct uli526x_board_info *db = netdev_priv(dev); unsigned long flags; u8 TmpSpeed=10; - + //ULI526X_DBUG(0, "uli526x_timer()", 0); spin_lock_irqsave(&db->lock, flags); - + /* Dynamic reset ULI526X : system error or transmit time-out */ tmp_cr8 = inl(db->ioaddr + DCR8); if ( (db->interval_rx_cnt==0) && (tmp_cr8) ) { @@ -1021,9 +1021,9 @@ static void uli526x_timer(unsigned long /* TX polling kick monitor */ if ( db->tx_packet_cnt && time_after(jiffies, dev->trans_start + ULI526X_TX_KICK) ) { - outl(0x1, dev->base_addr + DCR1); // Tx polling again + outl(0x1, dev->base_addr + DCR1); // Tx polling again - // TX Timeout + // TX Timeout if ( time_after(jiffies, dev->trans_start + ULI526X_TX_TIMEOUT) ) { db->reset_TXtimeout++; db->wait_reset = 1; @@ -1073,7 +1073,7 @@ static void uli526x_timer(unsigned long uli526x_sense_speed(db) ) db->link_failed = 1; uli526x_process_mode(db); - + if(db->link_failed==0) { if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD) @@ -1404,7 +1404,7 @@ static u8 uli526x_sense_speed(struct uli phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id); if ( (phy_mode & 0x24) == 0x24 ) { - + phy_mode = ((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)<<7); if(phy_mode&0x8000) phy_mode = 0x8000; @@ -1414,7 +1414,7 @@ static u8 uli526x_sense_speed(struct uli phy_mode = 0x2000; else phy_mode = 0x1000; - + /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */ switch (phy_mode) { case 0x1000: db->op_mode = ULI526X_10MHF; break; @@ -1442,7 +1442,7 @@ static u8 uli526x_sense_speed(struct uli static void uli526x_set_phyxcer(struct uli526x_board_info *db) { u16 phy_reg; - + /* Phyxcer capability setting */ phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0; @@ -1457,7 +1457,7 @@ static void uli526x_set_phyxcer(struct u case ULI526X_100MHF: phy_reg |= 0x80; break; case ULI526X_100MFD: phy_reg |= 0x100; break; } - + } /* Write new capability to Phyxcer Reg4 */ @@ -1556,7 +1556,7 @@ static void phy_write(unsigned long ioba /* Write a word data to PHY controller */ for ( i = 0x8000; i > 0; i >>= 1) phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0, chip_id); - + } @@ -1574,7 +1574,7 @@ static u16 phy_read(unsigned long iobase return phy_readby_cr10(iobase, phy_addr, offset); /* M5261/M5263 Chip */ ioaddr = iobase + DCR9; - + /* Send 33 synchronization clock to Phy controller */ for (i = 0; i < 35; i++) phy_write_1bit(ioaddr, PHY_DATA_1, chip_id); @@ -1610,7 +1610,7 @@ static u16 phy_read(unsigned long iobase static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset) { unsigned long ioaddr,cr10_value; - + ioaddr = iobase + DCR10; cr10_value = phy_addr; cr10_value = (cr10_value<<5) + offset; @@ -1629,7 +1629,7 @@ static u16 phy_readby_cr10(unsigned long static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data) { unsigned long ioaddr,cr10_value; - + ioaddr = iobase + DCR10; cr10_value = phy_addr; cr10_value = (cr10_value<<5) + offset; @@ -1659,7 +1659,7 @@ static void phy_write_1bit(unsigned long static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id) { u16 phy_data; - + outl(0x50000 , ioaddr); udelay(1); phy_data = ( inl(ioaddr) >> 19 ) & 0x1; diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 136a70c..8fea2aa 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -38,12 +38,12 @@ Copyright (C) 2001 Manfred Spraul * ethtool support (jgarzik) * Replace some MII-related magic numbers with constants (jgarzik) - + TODO: * enable pci_power_off * Wake-On-LAN */ - + #define DRV_NAME "winbond-840" #define DRV_VERSION "1.01-d" #define DRV_RELDATE "Nov-17-2001" @@ -57,7 +57,7 @@ c-help-name: Winbond W89c840 PCI Etherne c-help-symbol: CONFIG_WINBOND_840 c-help: This driver is for the Winbond W89c840 chip. It also works with c-help: the TX9882 chip on the Compex RL100-ATX board. -c-help: More specific information and updates are available from +c-help: More specific information and updates are available from c-help: http://www.scyld.com/network/drivers.html */ @@ -207,7 +207,7 @@ Test with 'ping -s 10000' on a fast comp */ - + /* PCI probe table. @@ -374,7 +374,7 @@ static int netdev_ioctl(struct net_devic static struct ethtool_ops netdev_ethtool_ops; static int netdev_close(struct net_device *dev); - + static int __devinit w840_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -434,7 +434,7 @@ #endif np->mii_if.mdio_read = mdio_read; np->mii_if.mdio_write = mdio_write; np->base_addr = ioaddr; - + pci_set_drvdata(pdev, dev); if (dev->mem_start) @@ -510,7 +510,7 @@ err_out_netdev: return -ENODEV; } - + /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. These are often serial bit streams generated by the host processor. The example below is for the common 93c46 EEPROM, 64 16 bit words. */ @@ -660,7 +660,7 @@ static void mdio_write(struct net_device return; } - + static int netdev_open(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); @@ -731,7 +731,7 @@ static int update_link(struct net_device dev->name, np->phys[0]); netif_carrier_on(dev); } - + if ((np->mii & ~0xf) == MII_DAVICOM_DM9101) { /* If the link partner doesn't support autonegotiation * the MII detects it's abilities with the "parallel detection". @@ -761,7 +761,7 @@ static int update_link(struct net_device result |= 0x20000000; if (result != np->csr6 && debug) printk(KERN_INFO "%s: Setting %dMBit-%s-duplex based on MII#%d\n", - dev->name, fasteth ? 100 : 10, + dev->name, fasteth ? 100 : 10, duplex ? "full" : "half", np->phys[0]); return result; } @@ -947,7 +947,7 @@ #endif iowrite32(i, ioaddr + PCIBusCfg); np->csr6 = 0; - /* 128 byte Tx threshold; + /* 128 byte Tx threshold; Transmit on; Receive on; */ update_csr6(dev, 0x00022002 | update_link(dev) | __set_rx_mode(dev)); @@ -1584,7 +1584,7 @@ #endif /* __i386__ debugging only */ static void __devexit w840_remove1 (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - + if (dev) { struct netdev_private *np = netdev_priv(dev); unregister_netdev(dev); @@ -1605,11 +1605,11 @@ #ifdef CONFIG_PM * - get_stats: * spin_lock_irq(np->lock), doesn't touch hw if not present * - hard_start_xmit: - * netif_stop_queue + spin_unlock_wait(&dev->xmit_lock); + * synchronize_irq + netif_tx_disable; * - tx_timeout: - * netif_device_detach + spin_unlock_wait(&dev->xmit_lock); + * netif_device_detach + netif_tx_disable; * - set_multicast_list - * netif_device_detach + spin_unlock_wait(&dev->xmit_lock); + * netif_device_detach + netif_tx_disable; * - interrupt handler * doesn't touch hw if not present, synchronize_irq waits for * running instances of the interrupt handler. @@ -1635,11 +1635,10 @@ static int w840_suspend (struct pci_dev netif_device_detach(dev); update_csr6(dev, 0); iowrite32(0, ioaddr + IntrEnable); - netif_stop_queue(dev); spin_unlock_irq(&np->lock); - spin_unlock_wait(&dev->xmit_lock); synchronize_irq(dev->irq); + netif_tx_disable(dev); np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff; diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 5634410..63c2175 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -1,11 +1,11 @@ /* - * xircom_cb: A driver for the (tulip-like) Xircom Cardbus ethernet cards + * xircom_cb: A driver for the (tulip-like) Xircom Cardbus ethernet cards * * This software is (C) by the respective authors, and licensed under the GPL * License. * * Written by Arjan van de Ven for Red Hat, Inc. - * Based on work by Jeff Garzik, Doug Ledford and Donald Becker + * Based on work by Jeff Garzik, Doug Ledford and Donald Becker * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -93,7 +93,7 @@ struct xircom_private { unsigned long io_port; int open; - + /* transmit_used is the rotating counter that indicates which transmit descriptor has to be used next */ int transmit_used; @@ -153,10 +153,10 @@ static struct pci_device_id xircom_pci_t MODULE_DEVICE_TABLE(pci, xircom_pci_table); static struct pci_driver xircom_ops = { - .name = "xircom_cb", - .id_table = xircom_pci_table, - .probe = xircom_probe, - .remove = xircom_remove, + .name = "xircom_cb", + .id_table = xircom_pci_table, + .probe = xircom_probe, + .remove = xircom_remove, .suspend =NULL, .resume =NULL }; @@ -174,7 +174,7 @@ static void print_binary(unsigned int nu buffer[i2++]='1'; else buffer[i2++]='0'; - if ((i&3)==0) + if ((i&3)==0) buffer[i2++]=' '; } printk("%s\n",buffer); @@ -196,10 +196,10 @@ static struct ethtool_ops netdev_ethtool /* xircom_probe is the code that gets called on device insertion. it sets up the hardware and registers the device to the networklayer. - + TODO: Send 1 or 2 "dummy" packets here as the card seems to discard the first two packets that get send, and pump hates that. - + */ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -209,7 +209,7 @@ static int __devinit xircom_probe(struct unsigned long flags; unsigned short tmp16; enter("xircom_probe"); - + /* First do the PCI initialisation */ if (pci_enable_device(pdev)) @@ -217,24 +217,24 @@ static int __devinit xircom_probe(struct /* disable all powermanagement */ pci_write_config_dword(pdev, PCI_POWERMGMT, 0x0000); - + pci_set_master(pdev); /* Why isn't this done by pci_enable_device ?*/ - /* clear PCI status, if any */ - pci_read_config_word (pdev,PCI_STATUS, &tmp16); + /* clear PCI status, if any */ + pci_read_config_word (pdev,PCI_STATUS, &tmp16); pci_write_config_word (pdev, PCI_STATUS,tmp16); - + pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev); - + if (!request_region(pci_resource_start(pdev, 0), 128, "xircom_cb")) { printk(KERN_ERR "xircom_probe: failed to allocate io-region\n"); return -ENODEV; } - /* + /* Before changing the hardware, allocate the memory. This way, we can fail gracefully if not enough memory - is available. + is available. */ dev = alloc_etherdev(sizeof(struct xircom_private)); if (!dev) { @@ -242,13 +242,13 @@ static int __devinit xircom_probe(struct goto device_fail; } private = netdev_priv(dev); - + /* Allocate the send/receive buffers */ private->rx_buffer = pci_alloc_consistent(pdev,8192,&private->rx_dma_handle); if (private->rx_buffer == NULL) { printk(KERN_ERR "xircom_probe: no memory for rx buffer \n"); goto rx_buf_fail; - } + } private->tx_buffer = pci_alloc_consistent(pdev,8192,&private->tx_dma_handle); if (private->tx_buffer == NULL) { printk(KERN_ERR "xircom_probe: no memory for tx buffer \n"); @@ -265,11 +265,11 @@ static int __devinit xircom_probe(struct spin_lock_init(&private->lock); dev->irq = pdev->irq; dev->base_addr = private->io_port; - + initialize_card(private); read_mac_address(private); setup_descriptors(private); - + dev->open = &xircom_open; dev->hard_start_xmit = &xircom_start_xmit; dev->stop = &xircom_close; @@ -285,19 +285,19 @@ #endif printk(KERN_ERR "xircom_probe: netdevice registration failed.\n"); goto reg_fail; } - + printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq); /* start the transmitter to get a heartbeat */ /* TODO: send 2 dummy packets here */ transceiver_voodoo(private); - + spin_lock_irqsave(&private->lock,flags); activate_transmitter(private); activate_receiver(private); spin_unlock_irqrestore(&private->lock,flags); - + trigger_receive(private); - + leave("xircom_probe"); return 0; @@ -332,7 +332,7 @@ static void __devexit xircom_remove(stru free_netdev(dev); pci_set_drvdata(pdev, NULL); leave("xircom_remove"); -} +} static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { @@ -346,11 +346,11 @@ static irqreturn_t xircom_interrupt(int spin_lock(&card->lock); status = inl(card->io_port+CSR5); -#ifdef DEBUG +#ifdef DEBUG print_binary(status); printk("tx status 0x%08x 0x%08x \n",card->tx_buffer[0],card->tx_buffer[4]); printk("rx status 0x%08x 0x%08x \n",card->rx_buffer[0],card->rx_buffer[4]); -#endif +#endif /* Handle shared irq and hotplug */ if (status == 0 || status == 0xffffffff) { spin_unlock(&card->lock); @@ -366,21 +366,21 @@ #endif netif_carrier_on(dev); else netif_carrier_off(dev); - + } - /* Clear all remaining interrupts */ + /* Clear all remaining interrupts */ status |= 0xffffffff; /* FIXME: make this clear only the real existing bits */ outl(status,card->io_port+CSR5); - - for (i=0;ilock); leave("xircom_interrupt"); return IRQ_HANDLED; @@ -393,38 +393,38 @@ static int xircom_start_xmit(struct sk_b int nextdescriptor; int desc; enter("xircom_start_xmit"); - + card = netdev_priv(dev); spin_lock_irqsave(&card->lock,flags); - + /* First see if we can free some descriptors */ - for (desc=0;desctransmit_used +1) % (NUMDESCRIPTORS); desc = card->transmit_used; - + /* only send the packet if the descriptor is free */ if (card->tx_buffer[4*desc]==0) { /* Copy the packet data; zero the memory first as the card sometimes sends more than you ask it to. */ - + memset(&card->tx_buffer[bufferoffsets[desc]/4],0,1536); memcpy(&(card->tx_buffer[bufferoffsets[desc]/4]),skb->data,skb->len); - - + + /* FIXME: The specification tells us that the length we send HAS to be a multiple of 4 bytes. */ - + card->tx_buffer[4*desc+1] = skb->len; if (desc == NUMDESCRIPTORS-1) card->tx_buffer[4*desc+1] |= (1<<25); /* bit 25: last descriptor of the ring */ card->tx_buffer[4*desc+1] |= 0xF0000000; - /* 0xF0... means want interrupts*/ + /* 0xF0... means want interrupts*/ card->tx_skb[desc] = skb; - + wmb(); /* This gives the descriptor to the card */ card->tx_buffer[4*desc] = 0x80000000; @@ -433,18 +433,18 @@ static int xircom_start_xmit(struct sk_b netif_stop_queue(dev); } card->transmit_used = nextdescriptor; - leave("xircom-start_xmit - sent"); + leave("xircom-start_xmit - sent"); spin_unlock_irqrestore(&card->lock,flags); return 0; } - + /* Uh oh... no free descriptor... drop the packet */ netif_stop_queue(dev); spin_unlock_irqrestore(&card->lock,flags); trigger_transmit(card); - + return -EIO; } @@ -462,7 +462,7 @@ static int xircom_open(struct net_device leave("xircom_open - No IRQ"); return retval; } - + xircom_up(xp); xp->open = 1; leave("xircom_open"); @@ -473,31 +473,31 @@ static int xircom_close(struct net_devic { struct xircom_private *card; unsigned long flags; - + enter("xircom_close"); card = netdev_priv(dev); netif_stop_queue(dev); /* we don't want new packets */ - + spin_lock_irqsave(&card->lock,flags); - + disable_all_interrupts(card); -#if 0 +#if 0 /* We can enable this again once we send dummy packets on ifconfig ethX up */ deactivate_receiver(card); deactivate_transmitter(card); -#endif +#endif remove_descriptors(card); - + spin_unlock_irqrestore(&card->lock,flags); - + card->open = 0; free_irq(dev->irq,dev); - + leave("xircom_close"); - + return 0; - + } @@ -506,8 +506,8 @@ static struct net_device_stats *xircom_g { struct xircom_private *card = netdev_priv(dev); return &card->stats; -} - +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void xircom_poll_controller(struct net_device *dev) @@ -540,7 +540,7 @@ static void initialize_card(struct xirco outl(val, card->io_port + CSR0); - val = 0; /* Value 0x00 is a safe and conservative value + val = 0; /* Value 0x00 is a safe and conservative value for the PCI configuration settings */ outl(val, card->io_port + CSR0); @@ -617,23 +617,23 @@ static void setup_descriptors(struct xir /* Rx Descr2: address of the buffer we store the buffer at the 2nd half of the page */ - + address = (unsigned long) card->rx_dma_handle; card->rx_buffer[i*4 + 2] = cpu_to_le32(address + bufferoffsets[i]); /* Rx Desc3: address of 2nd buffer -> 0 */ card->rx_buffer[i*4 + 3] = 0; } - + wmb(); /* Write the receive descriptor ring address to the card */ address = (unsigned long) card->rx_dma_handle; - val = cpu_to_le32(address); + val = cpu_to_le32(address); outl(val, card->io_port + CSR3); /* Receive descr list address */ /* transmit descriptors */ memset(card->tx_buffer, 0, 128); /* clear the descriptors */ - + for (i=0;i 0x00000000 */ card->tx_buffer[i*4 + 0] = 0x00000000; @@ -641,7 +641,7 @@ static void setup_descriptors(struct xir card->tx_buffer[i*4 + 1] = 1536; if (i==NUMDESCRIPTORS-1) card->tx_buffer[i*4 + 1] |= (1 << 25); /* bit 25 is "last descriptor" */ - + /* Tx Descr2: address of the buffer we store the buffer at the 2nd half of the page */ address = (unsigned long) card->tx_dma_handle; @@ -748,7 +748,7 @@ static int receive_active(struct xircom_ activate_receiver enables the receiver on the card. Before being allowed to active the receiver, the receiver must be completely de-activated. To achieve this, -this code actually disables the receiver first; then it waits for the +this code actually disables the receiver first; then it waits for the receiver to become inactive, then it activates the receiver and then it waits for the receiver to be active. @@ -762,13 +762,13 @@ static void activate_receiver(struct xir val = inl(card->io_port + CSR6); /* Operation mode */ - + /* If the "active" bit is set and the receiver is already active, no need to do the expensive thing */ if ((val&2) && (receive_active(card))) return; - - + + val = val & ~2; /* disable the receiver */ outl(val, card->io_port + CSR6); @@ -805,7 +805,7 @@ static void activate_receiver(struct xir /* deactivate_receiver disables the receiver on the card. -To achieve this this code disables the receiver first; +To achieve this this code disables the receiver first; then it waits for the receiver to become inactive. must be called with the lock held and interrupts disabled. @@ -840,7 +840,7 @@ static void deactivate_receiver(struct x activate_transmitter enables the transmitter on the card. Before being allowed to active the transmitter, the transmitter must be completely de-activated. To achieve this, -this code actually disables the transmitter first; then it waits for the +this code actually disables the transmitter first; then it waits for the transmitter to become inactive, then it activates the transmitter and then it waits for the transmitter to be active again. @@ -856,7 +856,7 @@ static void activate_transmitter(struct val = inl(card->io_port + CSR6); /* Operation mode */ /* If the "active" bit is set and the receiver is already - active, no need to do the expensive thing */ + active, no need to do the expensive thing */ if ((val&(1<<13)) && (transmit_active(card))) return; @@ -896,7 +896,7 @@ static void activate_transmitter(struct /* deactivate_transmitter disables the transmitter on the card. -To achieve this this code disables the transmitter first; +To achieve this this code disables the transmitter first; then it waits for the transmitter to become inactive. must be called with the lock held and interrupts disabled. @@ -990,7 +990,7 @@ static void disable_all_interrupts(struc { unsigned int val; enter("enable_all_interrupts"); - + val = 0; /* disable all interrupts */ outl(val, card->io_port + CSR7); @@ -1031,8 +1031,8 @@ static int enable_promisc(struct xircom_ unsigned int val; enter("enable_promisc"); - val = inl(card->io_port + CSR6); - val = val | (1 << 6); + val = inl(card->io_port + CSR6); + val = val | (1 << 6); outl(val, card->io_port + CSR6); leave("enable_promisc"); @@ -1042,7 +1042,7 @@ static int enable_promisc(struct xircom_ -/* +/* link_status() checks the the links status and will return 0 for no link, 10 for 10mbit link and 100 for.. guess what. Must be called in locked state with interrupts disabled @@ -1051,15 +1051,15 @@ static int link_status(struct xircom_pri { unsigned int val; enter("link_status"); - + val = inb(card->io_port + CSR12); - + if (!(val&(1<<2))) /* bit 2 is 0 for 10mbit link, 1 for not an 10mbit link */ return 10; if (!(val&(1<<1))) /* bit 1 is 0 for 100mbit link, 1 for not an 100mbit link */ return 100; - - /* If we get here -> no link at all */ + + /* If we get here -> no link at all */ leave("link_status"); return 0; @@ -1071,7 +1071,7 @@ static int link_status(struct xircom_pri /* read_mac_address() reads the MAC address from the NIC and stores it in the "dev" structure. - + This function will take the spinlock itself and can, as a result, not be called with the lock helt. */ static void read_mac_address(struct xircom_private *card) @@ -1081,7 +1081,7 @@ static void read_mac_address(struct xirc int i; enter("read_mac_address"); - + spin_lock_irqsave(&card->lock, flags); outl(1 << 12, card->io_port + CSR9); /* enable boot rom access */ @@ -1095,7 +1095,7 @@ static void read_mac_address(struct xirc outl(i + 3, card->io_port + CSR10); data_count = inl(card->io_port + CSR9) & 0xff; if ((tuple == 0x22) && (data_id == 0x04) && (data_count == 0x06)) { - /* + /* * This is it. We have the data we want. */ for (j = 0; j < 6; j++) { @@ -1136,12 +1136,12 @@ static void transceiver_voodoo(struct xi spin_lock_irqsave(&card->lock, flags); outl(0x0008, card->io_port + CSR15); - udelay(25); + udelay(25); outl(0xa8050000, card->io_port + CSR15); udelay(25); outl(0xa00f0000, card->io_port + CSR15); udelay(25); - + spin_unlock_irqrestore(&card->lock, flags); netif_start_queue(card->dev); @@ -1163,15 +1163,15 @@ static void xircom_up(struct xircom_priv spin_lock_irqsave(&card->lock, flags); - + enable_link_interrupt(card); enable_transmit_interrupt(card); enable_receive_interrupt(card); enable_common_interrupts(card); enable_promisc(card); - + /* The card can have received packets already, read them away now */ - for (i=0;idev,card,i,bufferoffsets[i]); @@ -1185,15 +1185,15 @@ static void xircom_up(struct xircom_priv /* Bufferoffset is in BYTES */ static void investigate_read_descriptor(struct net_device *dev,struct xircom_private *card, int descnr, unsigned int bufferoffset) { - int status; - + int status; + enter("investigate_read_descriptor"); status = card->rx_buffer[4*descnr]; - + if ((status > 0)) { /* packet received */ - + /* TODO: discard error packets */ - + short pkt_len = ((status >> 16) & 0x7ff) - 4; /* minus 4, we don't want the CRC */ struct sk_buff *skb; @@ -1216,7 +1216,7 @@ static void investigate_read_descriptor( dev->last_rx = jiffies; card->stats.rx_packets++; card->stats.rx_bytes += pkt_len; - + out: /* give the buffer back to the card */ card->rx_buffer[4*descnr] = 0x80000000; @@ -1234,9 +1234,9 @@ static void investigate_write_descriptor int status; enter("investigate_write_descriptor"); - + status = card->tx_buffer[4*descnr]; -#if 0 +#if 0 if (status & 0x8000) { /* Major error */ printk(KERN_ERR "Major transmit error status %x \n", status); card->tx_buffer[4*descnr] = 0; @@ -1258,7 +1258,7 @@ #endif } leave("investigate_write_descriptor"); - + } @@ -1271,8 +1271,8 @@ static int __init xircom_init(void) static void __exit xircom_exit(void) { pci_unregister_driver(&xircom_ops); -} +} -module_init(xircom_init) +module_init(xircom_init) module_exit(xircom_exit) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index a1ed2d9..6c62d5c 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -490,6 +490,9 @@ static int tun_set_iff(struct file *file err = -EINVAL; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + /* Set dev type */ if (ifr->ifr_flags & IFF_TUN) { /* TUN device */ diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index d9258d4..e49e8b5 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -340,7 +340,7 @@ #define typhoon_synchronize_irq(x) synch #endif #if defined(NETIF_F_TSO) -#define skb_tso_size(x) (skb_shinfo(x)->tso_size) +#define skb_tso_size(x) (skb_shinfo(x)->gso_size) #define TSO_NUM_DESCRIPTORS 2 #define TSO_OFFLOAD_ON TYPHOON_OFFLOAD_TCP_SEGMENT #else diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index fdc2103..c80a4f1 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1284,11 +1284,8 @@ static int rhine_start_tx(struct sk_buff /* Calculate the next Tx descriptor entry. */ entry = rp->cur_tx % TX_RING_SIZE; - if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; - } + if (skb_padto(skb, ETH_ZLEN)) + return 0; rp->tx_skbuff[entry] = skb; diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index ed1f837..09e05fe 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -248,6 +248,7 @@ static void velocity_free_rd_ring(struct static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *); static int velocity_soft_reset(struct velocity_info *vptr); static void mii_init(struct velocity_info *vptr, u32 mii_status); +static u32 velocity_get_link(struct net_device *dev); static u32 velocity_get_opt_media_mode(struct velocity_info *vptr); static void velocity_print_link_status(struct velocity_info *vptr); static void safe_disable_mii_autopoll(struct mac_regs __iomem * regs); @@ -798,6 +799,9 @@ #endif if (ret < 0) goto err_iounmap; + if (velocity_get_link(dev)) + netif_carrier_off(dev); + velocity_print_info(vptr); pci_set_drvdata(pdev, dev); @@ -1653,8 +1657,10 @@ static void velocity_error(struct veloci if (linked) { vptr->mii_status &= ~VELOCITY_LINK_FAIL; + netif_carrier_on(vptr->dev); } else { vptr->mii_status |= VELOCITY_LINK_FAIL; + netif_carrier_off(vptr->dev); } velocity_print_link_status(vptr); @@ -1899,6 +1905,13 @@ static int velocity_xmit(struct sk_buff int pktlen = skb->len; +#ifdef VELOCITY_ZERO_COPY_SUPPORT + if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) { + kfree_skb(skb); + return 0; + } +#endif + spin_lock_irqsave(&vptr->lock, flags); index = vptr->td_curr[qnum]; @@ -1914,8 +1927,6 @@ static int velocity_xmit(struct sk_buff */ if (pktlen < ETH_ZLEN) { /* Cannot occur until ZC support */ - if(skb_linearize(skb, GFP_ATOMIC)) - return 0; pktlen = ETH_ZLEN; memcpy(tdinfo->buf, skb->data, skb->len); memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len); @@ -1933,7 +1944,6 @@ #ifdef VELOCITY_ZERO_COPY_SUPPORT int nfrags = skb_shinfo(skb)->nr_frags; tdinfo->skb = skb; if (nfrags > 6) { - skb_linearize(skb, GFP_ATOMIC); memcpy(tdinfo->buf, skb->data, skb->len); tdinfo->skb_dma[0] = tdinfo->buf_dma; td_ptr->tdesc0.pktsize = diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h index d9a774b..f1b2640 100644 --- a/drivers/net/via-velocity.h +++ b/drivers/net/via-velocity.h @@ -307,7 +307,7 @@ #define VCAM_SIZE 64 #define TX_QUEUE_NO 4 #define MAX_HW_MIB_COUNTER 32 -#define VELOCITY_MIN_MTU (1514-14) +#define VELOCITY_MIN_MTU (64) #define VELOCITY_MAX_MTU (9000) /* diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c index 43d854a..b60ef02 100644 --- a/drivers/net/wan/c101.c +++ b/drivers/net/wan/c101.c @@ -326,21 +326,21 @@ static int __init c101_run(unsigned long if (request_irq(irq, sca_intr, 0, devname, card)) { printk(KERN_ERR "c101: could not allocate IRQ\n"); c101_destroy_card(card); - return(-EBUSY); + return -EBUSY; } card->irq = irq; if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) { printk(KERN_ERR "c101: could not request RAM window\n"); c101_destroy_card(card); - return(-EBUSY); + return -EBUSY; } card->phy_winbase = winbase; card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE); if (!card->win0base) { printk(KERN_ERR "c101: could not map I/O address\n"); c101_destroy_card(card); - return -EBUSY; + return -EFAULT; } card->tx_ring_buffers = TX_RING_BUFFERS; diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c index 46cef8f..57f9538 100644 --- a/drivers/net/wan/hdlc_generic.c +++ b/drivers/net/wan/hdlc_generic.c @@ -259,7 +259,7 @@ int hdlc_ioctl(struct net_device *dev, s } } -static void hdlc_setup(struct net_device *dev) +void hdlc_setup(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); @@ -288,26 +288,6 @@ struct net_device *alloc_hdlcdev(void *p return dev; } -int register_hdlc_device(struct net_device *dev) -{ - int result = dev_alloc_name(dev, "hdlc%d"); - if (result < 0) - return result; - - result = register_netdev(dev); - if (result != 0) - return -EIO; - -#if 0 - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); /* no carrier until DCD goes up */ -#endif - - return 0; -} - - - void unregister_hdlc_device(struct net_device *dev) { rtnl_lock(); @@ -326,8 +306,8 @@ EXPORT_SYMBOL(hdlc_open); EXPORT_SYMBOL(hdlc_close); EXPORT_SYMBOL(hdlc_set_carrier); EXPORT_SYMBOL(hdlc_ioctl); +EXPORT_SYMBOL(hdlc_setup); EXPORT_SYMBOL(alloc_hdlcdev); -EXPORT_SYMBOL(register_hdlc_device); EXPORT_SYMBOL(unregister_hdlc_device); static struct packet_type hdlc_packet_type = { diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index cd32751..b7d88db 100644 --- a/drivers/net/wan/n2.c +++ b/drivers/net/wan/n2.c @@ -387,6 +387,11 @@ static int __init n2_run(unsigned long i } card->phy_winbase = winbase; card->winbase = ioremap(winbase, USE_WINDOWSIZE); + if (!card->winbase) { + printk(KERN_ERR "n2: ioremap() failed\n"); + n2_destroy_card(card); + return -EFAULT; + } outb(0, io + N2_PCR); outb(winbase >> 12, io + N2_BAR); diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index eba8e5c..670e8bd 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -50,10 +50,6 @@ #define MAX_TX_BUFFERS 10 static int pci_clock_freq = 33000000; #define CLOCK_BASE pci_clock_freq -#define PCI_VENDOR_ID_GORAMO 0x10B5 /* uses PLX:9050 ID - this card */ -#define PCI_DEVICE_ID_PCI200SYN 0x9050 /* doesn't have its own ID */ - - /* * PLX PCI9052 local configuration and shared runtime registers. * This structure can be used to access 9052 registers (memory mapped). @@ -262,7 +258,7 @@ static void pci200_pci_remove_one(struct int i; card_t *card = pci_get_drvdata(pdev); - for(i = 0; i < 2; i++) + for (i = 0; i < 2; i++) if (card->ports[i].card) { struct net_device *dev = port_to_dev(&card->ports[i]); unregister_hdlc_device(dev); @@ -358,6 +354,7 @@ #endif card->rambase == NULL) { printk(KERN_ERR "pci200syn: ioremap() failed\n"); pci200_pci_remove_one(pdev); + return -EFAULT; } /* Reset PLX */ @@ -385,6 +382,15 @@ #endif " %u RX packets rings\n", ramsize / 1024, ramphys, pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers); + if (pdev->subsystem_device == PCI_DEVICE_ID_PLX_9050) { + printk(KERN_ERR "Detected PCI200SYN card with old " + "configuration data.\n"); + printk(KERN_ERR "See for update.\n"); + printk(KERN_ERR "The card will stop working with" + " future versions of Linux if not updated.\n"); + } + if (card->tx_ring_buffers < 1) { printk(KERN_ERR "pci200syn: RAM test failed\n"); pci200_pci_remove_one(pdev); @@ -396,7 +402,7 @@ #endif writew(readw(p) | 0x0040, p); /* Allocate IRQ */ - if(request_irq(pdev->irq, sca_intr, SA_SHIRQ, devname, card)) { + if (request_irq(pdev->irq, sca_intr, SA_SHIRQ, devname, card)) { printk(KERN_WARNING "pci200syn: could not allocate IRQ%d.\n", pdev->irq); pci200_pci_remove_one(pdev); @@ -406,7 +412,7 @@ #endif sca_init(card, 0); - for(i = 0; i < 2; i++) { + for (i = 0; i < 2; i++) { port_t *port = &card->ports[i]; struct net_device *dev = port_to_dev(port); hdlc_device *hdlc = dev_to_hdlc(dev); @@ -425,7 +431,7 @@ #endif hdlc->xmit = sca_xmit; port->settings.clock_type = CLOCK_EXT; port->card = card; - if(register_hdlc_device(dev)) { + if (register_hdlc_device(dev)) { printk(KERN_ERR "pci200syn: unable to register hdlc " "device\n"); port->card = NULL; @@ -445,8 +451,10 @@ #endif static struct pci_device_id pci200_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_GORAMO, PCI_DEVICE_ID_PCI200SYN, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX, + PCI_DEVICE_ID_PLX_9050, 0, 0, 0 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX, + PCI_DEVICE_ID_PLX_PCI200SYN, 0, 0, 0 }, { 0, } }; diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 22e7940..7628c2d 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -60,9 +60,9 @@ #include static const char* version = "SDLA driver v0.30, 12 Sep 1996, mike.mclagan@linux.org"; -static unsigned int valid_port[] __initdata = { 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390}; +static unsigned int valid_port[] = { 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390}; -static unsigned int valid_mem[] __initdata = { +static unsigned int valid_mem[] = { 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000, 0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000, 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000, diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 29a756d..437e0e9 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -634,7 +634,13 @@ #endif /* set up PLX mapping */ plx_phy = pci_resource_start(pdev, 0); + card->plx = ioremap_nocache(plx_phy, 0x70); + if (!card->plx) { + printk(KERN_ERR "wanxl: ioremap() failed\n"); + wanxl_pci_remove_one(pdev); + return -EFAULT; + } #if RESET_WHILE_LOADING wanxl_reset(card); @@ -700,6 +706,12 @@ #endif } mem = ioremap_nocache(mem_phy, PDM_OFFSET + sizeof(firmware)); + if (!mem) { + printk(KERN_ERR "wanxl: ioremap() failed\n"); + wanxl_pci_remove_one(pdev); + return -EFAULT; + } + for (i = 0; i < sizeof(firmware); i += 4) writel(htonl(*(u32*)(firmware + i)), mem + PDM_OFFSET + i); diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index e0874cb..30ec235 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -235,7 +235,35 @@ config IPW2200_MONITOR promiscuous mode via the Wireless Tool's Monitor mode. While in this mode, no packets can be sent. -config IPW_QOS +config IPW2200_RADIOTAP + bool "Enable radiotap format 802.11 raw packet support" + depends on IPW2200_MONITOR + +config IPW2200_PROMISCUOUS + bool "Enable creation of a RF radiotap promiscuous interface" + depends on IPW2200_MONITOR + select IPW2200_RADIOTAP + ---help--- + Enables the creation of a second interface prefixed 'rtap'. + This second interface will provide every received in radiotap + format. + + This is useful for performing wireless network analysis while + maintaining an active association. + + Example usage: + + % modprobe ipw2200 rtap_iface=1 + % ifconfig rtap0 up + % tethereal -i rtap0 + + If you do not specify 'rtap_iface=1' as a module parameter then + the rtap interface will not be created and you will need to turn + it on via sysfs: + + % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface + +config IPW2200_QOS bool "Enable QoS support" depends on IPW2200 && EXPERIMENTAL @@ -503,6 +531,23 @@ config PRISM54 say M here and read . The module will be called prism54.ko. +config USB_ZD1201 + tristate "USB ZD1201 based Wireless device support" + depends on USB && NET_RADIO + select FW_LOADER + ---help--- + Say Y if you want to use wireless LAN adapters based on the ZyDAS + ZD1201 chip. + + This driver makes the adapter appear as a normal Ethernet interface, + typically on wlan0. + + The zd1201 device requires external firmware to be loaded. + This can be found at http://linux-lc100020.sourceforge.net/ + + To compile this driver as a module, choose M here: the + module will be called zd1201. + source "drivers/net/wireless/hostap/Kconfig" source "drivers/net/wireless/bcm43xx/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index c867798..512603d 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -40,3 +40,5 @@ obj-$(CONFIG_BCM43XX) += bcm43xx/ # 16-bit wireless PCMCIA client drivers obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o + +obj-$(CONFIG_USB_ZD1201) += zd1201.o diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 00764dd..4069b79 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -47,6 +47,7 @@ #include #include #include #include +#include #include "airo.h" @@ -467,6 +468,8 @@ #define RID_ECHOTEST_RID 0xFF70 #define RID_ECHOTEST_RESULTS 0xFF71 #define RID_BSSLISTFIRST 0xFF72 #define RID_BSSLISTNEXT 0xFF73 +#define RID_WPA_BSSLISTFIRST 0xFF74 +#define RID_WPA_BSSLISTNEXT 0xFF75 typedef struct { u16 cmd; @@ -739,6 +742,14 @@ typedef struct { u16 extSoftCap; } CapabilityRid; + +/* Only present on firmware >= 5.30.17 */ +typedef struct { + u16 unknown[4]; + u8 fixed[12]; /* WLAN management frame */ + u8 iep[624]; +} BSSListRidExtra; + typedef struct { u16 len; u16 index; /* First is 0 and 0xffff means end of list */ @@ -767,6 +778,9 @@ #define CAP_SHORTHDR (1<<5) } fh; u16 dsChannel; u16 atimWindow; + + /* Only present on firmware >= 5.30.17 */ + BSSListRidExtra extra; } BSSListRid; typedef struct { @@ -1140,8 +1154,6 @@ #define MPI_MAX_FIDS 1 char defindex; // Used with auto wep struct proc_dir_entry *proc_entry; spinlock_t aux_lock; - unsigned long flags; -#define FLAG_PROMISC 8 /* IFF_PROMISC 0x100 - include/linux/if.h */ #define FLAG_RADIO_OFF 0 /* User disabling of MAC */ #define FLAG_RADIO_DOWN 1 /* ifup/ifdown disabling of MAC */ #define FLAG_RADIO_MASK 0x03 @@ -1151,6 +1163,7 @@ #define FLAG_MIC_CAPABLE 4 #define FLAG_UPDATE_MULTI 5 #define FLAG_UPDATE_UNI 6 #define FLAG_802_11 7 +#define FLAG_PROMISC 8 /* IFF_PROMISC 0x100 - include/linux/if.h */ #define FLAG_PENDING_XMIT 9 #define FLAG_PENDING_XMIT11 10 #define FLAG_MPI 11 @@ -1158,17 +1171,19 @@ #define FLAG_REGISTERED 12 #define FLAG_COMMIT 13 #define FLAG_RESET 14 #define FLAG_FLASHING 15 -#define JOB_MASK 0x2ff0000 -#define JOB_DIE 16 -#define JOB_XMIT 17 -#define JOB_XMIT11 18 -#define JOB_STATS 19 -#define JOB_PROMISC 20 -#define JOB_MIC 21 -#define JOB_EVENT 22 -#define JOB_AUTOWEP 23 -#define JOB_WSTATS 24 -#define JOB_SCAN_RESULTS 25 +#define FLAG_WPA_CAPABLE 16 + unsigned long flags; +#define JOB_DIE 0 +#define JOB_XMIT 1 +#define JOB_XMIT11 2 +#define JOB_STATS 3 +#define JOB_PROMISC 4 +#define JOB_MIC 5 +#define JOB_EVENT 6 +#define JOB_AUTOWEP 7 +#define JOB_WSTATS 8 +#define JOB_SCAN_RESULTS 9 + unsigned long jobs; int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap); unsigned short *flash; @@ -1208,6 +1223,11 @@ #define JOB_SCAN_RESULTS 25 #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE char proc_name[IFNAMSIZ]; + /* WPA-related stuff */ + unsigned int bssListFirst; + unsigned int bssListNext; + unsigned int bssListRidLen; + struct list_head network_list; struct list_head network_free_list; BSSListElement *networks; @@ -1264,7 +1284,7 @@ static void micinit(struct airo_info *ai { MICRid mic_rid; - clear_bit(JOB_MIC, &ai->flags); + clear_bit(JOB_MIC, &ai->jobs); PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0); up(&ai->sem); @@ -1705,24 +1725,24 @@ static void emmh32_final(emmh32_context static int readBSSListRid(struct airo_info *ai, int first, BSSListRid *list) { int rc; - Cmd cmd; - Resp rsp; + Cmd cmd; + Resp rsp; if (first == 1) { - if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN; - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd=CMD_LISTBSS; - if (down_interruptible(&ai->sem)) - return -ERESTARTSYS; - issuecommand(ai, &cmd, &rsp); - up(&ai->sem); - /* Let the command take effect */ - ai->task = current; - ssleep(3); - ai->task = NULL; - } - rc = PC4500_readrid(ai, first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT, - list, sizeof(*list), 1); + if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN; + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd=CMD_LISTBSS; + if (down_interruptible(&ai->sem)) + return -ERESTARTSYS; + issuecommand(ai, &cmd, &rsp); + up(&ai->sem); + /* Let the command take effect */ + ai->task = current; + ssleep(3); + ai->task = NULL; + } + rc = PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext, + list, ai->bssListRidLen, 1); list->len = le16_to_cpu(list->len); list->index = le16_to_cpu(list->index); @@ -2112,7 +2132,7 @@ static void airo_end_xmit(struct net_dev int fid = priv->xmit.fid; u32 *fids = priv->fids; - clear_bit(JOB_XMIT, &priv->flags); + clear_bit(JOB_XMIT, &priv->jobs); clear_bit(FLAG_PENDING_XMIT, &priv->flags); status = transmit_802_3_packet (priv, fids[fid], skb->data); up(&priv->sem); @@ -2162,7 +2182,7 @@ static int airo_start_xmit(struct sk_buf if (down_trylock(&priv->sem) != 0) { set_bit(FLAG_PENDING_XMIT, &priv->flags); netif_stop_queue(dev); - set_bit(JOB_XMIT, &priv->flags); + set_bit(JOB_XMIT, &priv->jobs); wake_up_interruptible(&priv->thr_wait); } else airo_end_xmit(dev); @@ -2177,7 +2197,7 @@ static void airo_end_xmit11(struct net_d int fid = priv->xmit11.fid; u32 *fids = priv->fids; - clear_bit(JOB_XMIT11, &priv->flags); + clear_bit(JOB_XMIT11, &priv->jobs); clear_bit(FLAG_PENDING_XMIT11, &priv->flags); status = transmit_802_11_packet (priv, fids[fid], skb->data); up(&priv->sem); @@ -2233,7 +2253,7 @@ static int airo_start_xmit11(struct sk_b if (down_trylock(&priv->sem) != 0) { set_bit(FLAG_PENDING_XMIT11, &priv->flags); netif_stop_queue(dev); - set_bit(JOB_XMIT11, &priv->flags); + set_bit(JOB_XMIT11, &priv->jobs); wake_up_interruptible(&priv->thr_wait); } else airo_end_xmit11(dev); @@ -2244,7 +2264,7 @@ static void airo_read_stats(struct airo_ StatsRid stats_rid; u32 *vals = stats_rid.vals; - clear_bit(JOB_STATS, &ai->flags); + clear_bit(JOB_STATS, &ai->jobs); if (ai->power.event) { up(&ai->sem); return; @@ -2272,10 +2292,10 @@ static struct net_device_stats *airo_get { struct airo_info *local = dev->priv; - if (!test_bit(JOB_STATS, &local->flags)) { + if (!test_bit(JOB_STATS, &local->jobs)) { /* Get stats out of the card if available */ if (down_trylock(&local->sem) != 0) { - set_bit(JOB_STATS, &local->flags); + set_bit(JOB_STATS, &local->jobs); wake_up_interruptible(&local->thr_wait); } else airo_read_stats(local); @@ -2290,7 +2310,7 @@ static void airo_set_promisc(struct airo memset(&cmd, 0, sizeof(cmd)); cmd.cmd=CMD_SETMODE; - clear_bit(JOB_PROMISC, &ai->flags); + clear_bit(JOB_PROMISC, &ai->jobs); cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC; issuecommand(ai, &cmd, &rsp); up(&ai->sem); @@ -2302,7 +2322,7 @@ static void airo_set_multicast_list(stru if ((dev->flags ^ ai->flags) & IFF_PROMISC) { change_bit(FLAG_PROMISC, &ai->flags); if (down_trylock(&ai->sem) != 0) { - set_bit(JOB_PROMISC, &ai->flags); + set_bit(JOB_PROMISC, &ai->jobs); wake_up_interruptible(&ai->thr_wait); } else airo_set_promisc(ai); @@ -2380,7 +2400,7 @@ void stop_airo_card( struct net_device * } clear_bit(FLAG_REGISTERED, &ai->flags); } - set_bit(JOB_DIE, &ai->flags); + set_bit(JOB_DIE, &ai->jobs); kill_proc(ai->thr_pid, SIGTERM, 1); wait_for_completion(&ai->thr_exited); @@ -2701,14 +2721,14 @@ static int reset_card( struct net_device return 0; } -#define MAX_NETWORK_COUNT 64 +#define AIRO_MAX_NETWORK_COUNT 64 static int airo_networks_allocate(struct airo_info *ai) { if (ai->networks) return 0; ai->networks = - kzalloc(MAX_NETWORK_COUNT * sizeof(BSSListElement), + kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement), GFP_KERNEL); if (!ai->networks) { airo_print_warn(ai->dev->name, "Out of memory allocating beacons"); @@ -2732,11 +2752,33 @@ static void airo_networks_initialize(str INIT_LIST_HEAD(&ai->network_free_list); INIT_LIST_HEAD(&ai->network_list); - for (i = 0; i < MAX_NETWORK_COUNT; i++) + for (i = 0; i < AIRO_MAX_NETWORK_COUNT; i++) list_add_tail(&ai->networks[i].list, &ai->network_free_list); } +static int airo_test_wpa_capable(struct airo_info *ai) +{ + int status; + CapabilityRid cap_rid; + const char *name = ai->dev->name; + + status = readCapabilityRid(ai, &cap_rid, 1); + if (status != SUCCESS) return 0; + + /* Only firmware versions 5.30.17 or better can do WPA */ + if ((cap_rid.softVer > 0x530) + || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) { + airo_print_info(name, "WPA is supported."); + return 1; + } + + /* No WPA support */ + airo_print_info(name, "WPA unsupported (only firmware versions 5.30.17" + " and greater support WPA. Detected %s)", cap_rid.prodVer); + return 0; +} + static struct net_device *_init_airo_card( unsigned short irq, int port, int is_pcmcia, struct pci_dev *pci, struct device *dmdev ) @@ -2759,6 +2801,7 @@ static struct net_device *_init_airo_car ai = dev->priv; ai->wifidev = NULL; ai->flags = 0; + ai->jobs = 0; ai->dev = dev; if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) { airo_print_dbg(dev->name, "Found an MPI350 card"); @@ -2838,6 +2881,18 @@ static struct net_device *_init_airo_car set_bit(FLAG_FLASHING, &ai->flags); } + /* Test for WPA support */ + if (airo_test_wpa_capable(ai)) { + set_bit(FLAG_WPA_CAPABLE, &ai->flags); + ai->bssListFirst = RID_WPA_BSSLISTFIRST; + ai->bssListNext = RID_WPA_BSSLISTNEXT; + ai->bssListRidLen = sizeof(BSSListRid); + } else { + ai->bssListFirst = RID_BSSLISTFIRST; + ai->bssListNext = RID_BSSLISTNEXT; + ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); + } + rc = register_netdev(dev); if (rc) { airo_print_err(dev->name, "Couldn't register_netdev"); @@ -2875,7 +2930,7 @@ err_out_irq: err_out_unlink: del_airo_dev(dev); err_out_thr: - set_bit(JOB_DIE, &ai->flags); + set_bit(JOB_DIE, &ai->jobs); kill_proc(ai->thr_pid, SIGTERM, 1); wait_for_completion(&ai->thr_exited); err_out_free: @@ -2933,7 +2988,7 @@ static void airo_send_event(struct net_d union iwreq_data wrqu; StatusRid status_rid; - clear_bit(JOB_EVENT, &ai->flags); + clear_bit(JOB_EVENT, &ai->jobs); PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0); up(&ai->sem); wrqu.data.length = 0; @@ -2947,7 +3002,7 @@ static void airo_send_event(struct net_d static void airo_process_scan_results (struct airo_info *ai) { union iwreq_data wrqu; - BSSListRid BSSList; + BSSListRid bss; int rc; BSSListElement * loop_net; BSSListElement * tmp_net; @@ -2960,15 +3015,15 @@ static void airo_process_scan_results (s } /* Try to read the first entry of the scan result */ - rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 0); - if((rc) || (BSSList.index == 0xffff)) { + rc = PC4500_readrid(ai, ai->bssListFirst, &bss, ai->bssListRidLen, 0); + if((rc) || (bss.index == 0xffff)) { /* No scan results */ goto out; } /* Read and parse all entries */ tmp_net = NULL; - while((!rc) && (BSSList.index != 0xffff)) { + while((!rc) && (bss.index != 0xffff)) { /* Grab a network off the free list */ if (!list_empty(&ai->network_free_list)) { tmp_net = list_entry(ai->network_free_list.next, @@ -2977,19 +3032,19 @@ static void airo_process_scan_results (s } if (tmp_net != NULL) { - memcpy(tmp_net, &BSSList, sizeof(tmp_net->bss)); + memcpy(tmp_net, &bss, sizeof(tmp_net->bss)); list_add_tail(&tmp_net->list, &ai->network_list); tmp_net = NULL; } /* Read next entry */ - rc = PC4500_readrid(ai, RID_BSSLISTNEXT, - &BSSList, sizeof(BSSList), 0); + rc = PC4500_readrid(ai, ai->bssListNext, + &bss, ai->bssListRidLen, 0); } out: ai->scan_timeout = 0; - clear_bit(JOB_SCAN_RESULTS, &ai->flags); + clear_bit(JOB_SCAN_RESULTS, &ai->jobs); up(&ai->sem); /* Send an empty event to user space. @@ -3019,10 +3074,10 @@ static int airo_thread(void *data) { /* make swsusp happy with our thread */ try_to_freeze(); - if (test_bit(JOB_DIE, &ai->flags)) + if (test_bit(JOB_DIE, &ai->jobs)) break; - if (ai->flags & JOB_MASK) { + if (ai->jobs) { locked = down_interruptible(&ai->sem); } else { wait_queue_t wait; @@ -3031,16 +3086,16 @@ static int airo_thread(void *data) { add_wait_queue(&ai->thr_wait, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); - if (ai->flags & JOB_MASK) + if (ai->jobs) break; if (ai->expires || ai->scan_timeout) { if (ai->scan_timeout && time_after_eq(jiffies,ai->scan_timeout)){ - set_bit(JOB_SCAN_RESULTS,&ai->flags); + set_bit(JOB_SCAN_RESULTS, &ai->jobs); break; } else if (ai->expires && time_after_eq(jiffies,ai->expires)){ - set_bit(JOB_AUTOWEP,&ai->flags); + set_bit(JOB_AUTOWEP, &ai->jobs); break; } if (!signal_pending(current)) { @@ -3069,7 +3124,7 @@ static int airo_thread(void *data) { if (locked) continue; - if (test_bit(JOB_DIE, &ai->flags)) { + if (test_bit(JOB_DIE, &ai->jobs)) { up(&ai->sem); break; } @@ -3079,23 +3134,23 @@ static int airo_thread(void *data) { continue; } - if (test_bit(JOB_XMIT, &ai->flags)) + if (test_bit(JOB_XMIT, &ai->jobs)) airo_end_xmit(dev); - else if (test_bit(JOB_XMIT11, &ai->flags)) + else if (test_bit(JOB_XMIT11, &ai->jobs)) airo_end_xmit11(dev); - else if (test_bit(JOB_STATS, &ai->flags)) + else if (test_bit(JOB_STATS, &ai->jobs)) airo_read_stats(ai); - else if (test_bit(JOB_WSTATS, &ai->flags)) + else if (test_bit(JOB_WSTATS, &ai->jobs)) airo_read_wireless_stats(ai); - else if (test_bit(JOB_PROMISC, &ai->flags)) + else if (test_bit(JOB_PROMISC, &ai->jobs)) airo_set_promisc(ai); - else if (test_bit(JOB_MIC, &ai->flags)) + else if (test_bit(JOB_MIC, &ai->jobs)) micinit(ai); - else if (test_bit(JOB_EVENT, &ai->flags)) + else if (test_bit(JOB_EVENT, &ai->jobs)) airo_send_event(dev); - else if (test_bit(JOB_AUTOWEP, &ai->flags)) + else if (test_bit(JOB_AUTOWEP, &ai->jobs)) timer_func(dev); - else if (test_bit(JOB_SCAN_RESULTS, &ai->flags)) + else if (test_bit(JOB_SCAN_RESULTS, &ai->jobs)) airo_process_scan_results(ai); else /* Shouldn't get here, but we make sure to unlock */ up(&ai->sem); @@ -3133,7 +3188,7 @@ static irqreturn_t airo_interrupt ( int if ( status & EV_MIC ) { OUT4500( apriv, EVACK, EV_MIC ); if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) { - set_bit(JOB_MIC, &apriv->flags); + set_bit(JOB_MIC, &apriv->jobs); wake_up_interruptible(&apriv->thr_wait); } } @@ -3187,7 +3242,7 @@ #define RC_NOAUTH 9 /* Station requestin set_bit(FLAG_UPDATE_MULTI, &apriv->flags); if (down_trylock(&apriv->sem) != 0) { - set_bit(JOB_EVENT, &apriv->flags); + set_bit(JOB_EVENT, &apriv->jobs); wake_up_interruptible(&apriv->thr_wait); } else airo_send_event(dev); @@ -5485,7 +5540,7 @@ static void timer_func( struct net_devic up(&apriv->sem); /* Schedule check to see if the change worked */ - clear_bit(JOB_AUTOWEP, &apriv->flags); + clear_bit(JOB_AUTOWEP, &apriv->jobs); apriv->expires = RUN_AT(HZ*3); } @@ -6876,7 +6931,7 @@ static int airo_get_range(struct net_dev } range->num_txpower = i; range->txpower_capa = IW_TXPOW_MWATT; - range->we_version_source = 12; + range->we_version_source = 19; range->we_version_compiled = WIRELESS_EXT; range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; range->retry_flags = IW_RETRY_LIMIT; @@ -7152,6 +7207,7 @@ static inline char *airo_translate_scan( u16 capabilities; char * current_val; /* For rates */ int i; + char * buf; /* First entry *MUST* be the AP MAC address */ iwe.cmd = SIOCGIWAP; @@ -7238,8 +7294,69 @@ static inline char *airo_translate_scan( if((current_val - current_ev) > IW_EV_LCP_LEN) current_ev = current_val; - /* The other data in the scan result are not really - * interesting, so for now drop it - Jean II */ + /* Beacon interval */ + buf = kmalloc(30, GFP_KERNEL); + if (buf) { + iwe.cmd = IWEVCUSTOM; + sprintf(buf, "bcn_int=%d", bss->beaconInterval); + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); + kfree(buf); + } + + /* Put WPA/RSN Information Elements into the event stream */ + if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) { + unsigned int num_null_ies = 0; + u16 length = sizeof (bss->extra.iep); + struct ieee80211_info_element *info_element = + (struct ieee80211_info_element *) &bss->extra.iep; + + while ((length >= sizeof(*info_element)) && (num_null_ies < 2)) { + if (sizeof(*info_element) + info_element->len > length) { + /* Invalid element, don't continue parsing IE */ + break; + } + + switch (info_element->id) { + case MFIE_TYPE_SSID: + /* Two zero-length SSID elements + * mean we're done parsing elements */ + if (!info_element->len) + num_null_ies++; + break; + + case MFIE_TYPE_GENERIC: + if (info_element->len >= 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x50 && + info_element->data[2] == 0xf2 && + info_element->data[3] == 0x01) { + iwe.cmd = IWEVGENIE; + iwe.u.data.length = min(info_element->len + 2, + MAX_WPA_IE_LEN); + current_ev = iwe_stream_add_point(current_ev, end_buf, + &iwe, (char *) info_element); + } + break; + + case MFIE_TYPE_RSN: + iwe.cmd = IWEVGENIE; + iwe.u.data.length = min(info_element->len + 2, + MAX_WPA_IE_LEN); + current_ev = iwe_stream_add_point(current_ev, end_buf, + &iwe, (char *) info_element); + break; + + default: + break; + } + + length -= sizeof(*info_element) + info_element->len; + info_element = + (struct ieee80211_info_element *)&info_element-> + data[info_element->len]; + } + } return current_ev; } @@ -7521,7 +7638,7 @@ static void airo_read_wireless_stats(str u32 *vals = stats_rid.vals; /* Get stats out of the card */ - clear_bit(JOB_WSTATS, &local->flags); + clear_bit(JOB_WSTATS, &local->jobs); if (local->power.event) { up(&local->sem); return; @@ -7565,10 +7682,10 @@ static struct iw_statistics *airo_get_wi { struct airo_info *local = dev->priv; - if (!test_bit(JOB_WSTATS, &local->flags)) { + if (!test_bit(JOB_WSTATS, &local->jobs)) { /* Get stats out of the card if available */ if (down_trylock(&local->sem) != 0) { - set_bit(JOB_WSTATS, &local->flags); + set_bit(JOB_WSTATS, &local->jobs); wake_up_interruptible(&local->thr_wait); } else airo_read_wireless_stats(local); diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig index 25ea474..533993f 100644 --- a/drivers/net/wireless/bcm43xx/Kconfig +++ b/drivers/net/wireless/bcm43xx/Kconfig @@ -2,6 +2,7 @@ config BCM43XX tristate "Broadcom BCM43xx wireless support" depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL select FW_LOADER + select HW_RANDOM ---help--- This is an experimental driver for the Broadcom 43xx wireless chip, found in the Apple Airport Extreme and various other devices. diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 2e83083..17a5682 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -1,6 +1,7 @@ #ifndef BCM43xx_H_ #define BCM43xx_H_ +#include #include #include #include @@ -82,6 +83,7 @@ #define BCM43xx_MMIO_TSF_0 0x632 /* cor #define BCM43xx_MMIO_TSF_1 0x634 /* core rev < 3 only */ #define BCM43xx_MMIO_TSF_2 0x636 /* core rev < 3 only */ #define BCM43xx_MMIO_TSF_3 0x638 /* core rev < 3 only */ +#define BCM43xx_MMIO_RNG 0x65A #define BCM43xx_MMIO_POWERUP_DELAY 0x6A8 /* SPROM offsets. */ @@ -636,6 +638,17 @@ struct bcm43xx_key { u8 algorithm; }; +/* Driver initialization status. */ +enum { + BCM43xx_STAT_UNINIT, /* Uninitialized. */ + BCM43xx_STAT_INITIALIZING, /* init_board() in progress. */ + BCM43xx_STAT_INITIALIZED, /* Fully operational. */ + BCM43xx_STAT_SHUTTINGDOWN, /* free_board() in progress. */ + BCM43xx_STAT_RESTARTING, /* controller_restart() called. */ +}; +#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status) +#define bcm43xx_set_status(bcm, stat) atomic_set(&(bcm)->init_status, (stat)) + struct bcm43xx_private { struct ieee80211_device *ieee; struct ieee80211softmac_device *softmac; @@ -645,20 +658,18 @@ struct bcm43xx_private { unsigned int irq; void __iomem *mmio_addr; - unsigned int mmio_len; - /* Do not use the lock directly. Use the bcm43xx_lock* helper - * functions, to be MMIO-safe. */ - spinlock_t _lock; + /* Locking, see "theory of locking" text below. */ + spinlock_t irq_lock; + struct mutex mutex; + + /* Driver initialization status BCM43xx_STAT_*** */ + atomic_t init_status; - /* Driver status flags. */ - u32 initialized:1, /* init_board() succeed */ - was_initialized:1, /* for PCI suspend/resume. */ - shutting_down:1, /* free_board() in progress */ + u16 was_initialized:1, /* for PCI suspend/resume. */ __using_pio:1, /* Internal, use bcm43xx_using_pio(). */ bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */ reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */ - powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */ short_preamble:1, /* TRUE, if short preamble is enabled. */ firmware_norelease:1; /* Do not release the firmware. Used on suspend. */ @@ -722,7 +733,7 @@ #endif struct tasklet_struct isr_tasklet; /* Periodic tasks */ - struct timer_list periodic_tasks; + struct work_struct periodic_work; unsigned int periodic_state; struct work_struct restart_work; @@ -741,27 +752,65 @@ #endif const struct firmware *initvals0; const struct firmware *initvals1; + /* Random Number Generator. */ + struct hwrng rng; + char rng_name[20 + 1]; + /* Debugging stuff follows. */ #ifdef CONFIG_BCM43XX_DEBUG struct bcm43xx_dfsentry *dfsentry; #endif }; -/* bcm43xx_(un)lock() protect struct bcm43xx_private. - * Note that _NO_ MMIO writes are allowed. If you want to - * write to the device through MMIO in the critical section, use - * the *_mmio lock functions. - * MMIO read-access is allowed, though. - */ -#define bcm43xx_lock(bcm, flags) spin_lock_irqsave(&(bcm)->_lock, flags) -#define bcm43xx_unlock(bcm, flags) spin_unlock_irqrestore(&(bcm)->_lock, flags) -/* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO. - * MMIO write-access to the device is allowed. - * All MMIO writes are flushed on unlock, so it is guaranteed to not - * interfere with other threads writing MMIO registers. + +/* *** THEORY OF LOCKING *** + * + * We have two different locks in the bcm43xx driver. + * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private + * and the device registers. + * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. + * + * We have three types of helper function pairs to utilize these locks. + * (Always use the helper functions.) + * 1) bcm43xx_{un}lock_noirq(): + * Takes bcm->mutex. Does _not_ protect against IRQ concurrency, + * so it is almost always unsafe, if device IRQs are enabled. + * So only use this, if device IRQs are masked. + * Locking may sleep. + * You can sleep within the critical section. + * 2) bcm43xx_{un}lock_irqonly(): + * Takes bcm->irq_lock. Does _not_ protect against + * bcm43xx_lock_noirq() critical sections. + * Does only protect against the IRQ handler path and other + * irqonly() critical sections. + * Locking does not sleep. + * You must not sleep within the critical section. + * 3) bcm43xx_{un}lock_irqsafe(): + * This is the cummulative lock and takes both, mutex and irq_lock. + * Protects against noirq() and irqonly() critical sections (and + * the IRQ handler path). + * Locking may sleep. + * You must not sleep within the critical section. */ -#define bcm43xx_lock_mmio(bcm, flags) bcm43xx_lock(bcm, flags) -#define bcm43xx_unlock_mmio(bcm, flags) do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0) + +/* Lock type 1 */ +#define bcm43xx_lock_noirq(bcm) mutex_lock(&(bcm)->mutex) +#define bcm43xx_unlock_noirq(bcm) mutex_unlock(&(bcm)->mutex) +/* Lock type 2 */ +#define bcm43xx_lock_irqonly(bcm, flags) \ + spin_lock_irqsave(&(bcm)->irq_lock, flags) +#define bcm43xx_unlock_irqonly(bcm, flags) \ + spin_unlock_irqrestore(&(bcm)->irq_lock, flags) +/* Lock type 3 */ +#define bcm43xx_lock_irqsafe(bcm, flags) do { \ + bcm43xx_lock_noirq(bcm); \ + bcm43xx_lock_irqonly(bcm, flags); \ + } while (0) +#define bcm43xx_unlock_irqsafe(bcm, flags) do { \ + bcm43xx_unlock_irqonly(bcm, flags); \ + bcm43xx_unlock_noirq(bcm); \ + } while (0) + static inline struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) @@ -844,16 +893,6 @@ struct bcm43xx_radioinfo * bcm43xx_curre return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio); } -/* Are we running in init_board() context? */ -static inline -int bcm43xx_is_initializing(struct bcm43xx_private *bcm) -{ - if (bcm->initialized) - return 0; - if (bcm->shutting_down) - return 0; - return 1; -} static inline struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy, diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index 35a4fcb..ce2e40b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -77,8 +77,8 @@ static ssize_t devinfo_read_file(struct down(&big_buffer_sem); - bcm43xx_lock_mmio(bcm, flags); - if (!bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { fappend("Board not initialized.\n"); goto out; } @@ -92,7 +92,7 @@ static ssize_t devinfo_read_file(struct fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n", pci_dev->subsystem_vendor, pci_dev->subsystem_device); fappend("IRQ: %d\n", bcm->irq); - fappend("mmio_addr: 0x%p mmio_len: %u\n", bcm->mmio_addr, bcm->mmio_len); + fappend("mmio_addr: 0x%p\n", bcm->mmio_addr); fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev); if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16))) fappend("Radio disabled by hardware!\n"); @@ -121,7 +121,7 @@ #undef fappend_core fappend("\n"); out: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -159,8 +159,8 @@ static ssize_t spromdump_read_file(struc unsigned long flags; down(&big_buffer_sem); - bcm43xx_lock_mmio(bcm, flags); - if (!bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { fappend("Board not initialized.\n"); goto out; } @@ -169,7 +169,7 @@ static ssize_t spromdump_read_file(struc fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); out: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -188,8 +188,8 @@ static ssize_t tsf_read_file(struct file u64 tsf; down(&big_buffer_sem); - bcm43xx_lock_mmio(bcm, flags); - if (!bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { fappend("Board not initialized.\n"); goto out; } @@ -199,7 +199,7 @@ static ssize_t tsf_read_file(struct file (unsigned int)(tsf & 0xFFFFFFFFULL)); out: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -221,8 +221,8 @@ static ssize_t tsf_write_file(struct fil res = -EFAULT; goto out_up; } - bcm43xx_lock_mmio(bcm, flags); - if (!bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); res = -EFAULT; goto out_unlock; @@ -233,10 +233,11 @@ static ssize_t tsf_write_file(struct fil goto out_unlock; } bcm43xx_tsf_write(bcm, tsf); + mmiowb(); res = buf_size; out_unlock: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); out_up: up(&big_buffer_sem); return res; @@ -257,7 +258,7 @@ static ssize_t txstat_read_file(struct f int i, cnt, j = 0; down(&big_buffer_sem); - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", BCM43xx_NR_LOGGED_XMITSTATUS); @@ -293,14 +294,14 @@ static ssize_t txstat_read_file(struct f i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; } - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); if (*ppos == pos) { /* Done. Drop the copied data. */ e->xmitstatus_printing = 0; } - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); up(&big_buffer_sem); return res; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 4b2c02c..ec80692 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -51,12 +51,12 @@ static void bcm43xx_led_blink(unsigned l struct bcm43xx_private *bcm = led->bcm; unsigned long flags; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqonly(bcm, flags); if (led->blink_interval) { bcm43xx_led_changestate(led); mod_timer(&led->blink_timer, jiffies + led->blink_interval); } - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqonly(bcm, flags); } static void bcm43xx_led_blink_start(struct bcm43xx_led *led, diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 7ed18ca..27bcf47 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -128,13 +128,15 @@ #endif /* CONFIG_BCM43XX_DEBUG*/ static struct pci_device_id bcm43xx_pci_tbl[] = { /* Broadcom 4303 802.11b */ { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4307 802.11b */ + /* Broadcom 4307 802.11b */ { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4318 802.11b/g */ + /* Broadcom 4318 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + /* Broadcom 4319 802.11a/b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Broadcom 4306 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4306 802.11a */ + /* Broadcom 4306 802.11a */ // { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Broadcom 4309 802.11a/b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, @@ -496,20 +498,31 @@ static inline u32 bcm43xx_interrupt_disa return old_mask; } +/* Synchronize IRQ top- and bottom-half. + * IRQs must be masked before calling this. + * This must not be called with the irq_lock held. + */ +static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm) +{ + synchronize_irq(bcm->irq); + tasklet_disable(&bcm->isr_tasklet); +} + /* Make sure we don't receive more data from the device. */ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate) { - u32 old; unsigned long flags; + u32 old; - bcm43xx_lock_mmio(bcm, flags); - if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) { - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_lock_irqonly(bcm, flags); + if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { + bcm43xx_unlock_irqonly(bcm, flags); return -EBUSY; } old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - tasklet_disable(&bcm->isr_tasklet); - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqonly(bcm, flags); + bcm43xx_synchronize_irq(bcm); + if (oldstate) *oldstate = old; @@ -1387,7 +1400,7 @@ #ifndef CONFIG_BCM947XX bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); #endif } - if (bcm->shutting_down) { + if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) { bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002)); @@ -1707,7 +1720,7 @@ #else # define bcmirq_handled(irq) do { /* nothing */ } while (0) #endif /* CONFIG_BCM43XX_DEBUG*/ - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqonly(bcm, flags); reason = bcm->irq_reason; dma_reason[0] = bcm->dma_reason[0]; dma_reason[1] = bcm->dma_reason[1]; @@ -1732,7 +1745,8 @@ #endif /* CONFIG_BCM43XX_DEBUG*/ dma_reason[0], dma_reason[1], dma_reason[2], dma_reason[3]); bcm43xx_controller_restart(bcm, "DMA error"); - bcm43xx_unlock_mmio(bcm, flags); + mmiowb(); + bcm43xx_unlock_irqonly(bcm, flags); return; } if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) | @@ -1819,7 +1833,8 @@ #undef bcmirq_handled if (!modparam_noleds) bcm43xx_leds_update(bcm, activity); bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - bcm43xx_unlock_mmio(bcm, flags); + mmiowb(); + bcm43xx_unlock_irqonly(bcm, flags); } static void pio_irq_workaround(struct bcm43xx_private *bcm, @@ -1868,7 +1883,7 @@ static irqreturn_t bcm43xx_interrupt_han if (!bcm) return IRQ_NONE; - spin_lock(&bcm->_lock); + spin_lock(&bcm->irq_lock); reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); if (reason == 0xffffffff) { @@ -1897,7 +1912,7 @@ static irqreturn_t bcm43xx_interrupt_han * completely, but some careful work is needed to fix this. I think it * is best to stay with this cheap workaround for now... . */ - if (likely(bcm->initialized)) { + if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) { /* disable all IRQs. They are enabled again in the bottom half. */ bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); /* save the reason code and call our bottom half. */ @@ -1907,7 +1922,7 @@ static irqreturn_t bcm43xx_interrupt_han out: mmiowb(); - spin_unlock(&bcm->_lock); + spin_unlock(&bcm->irq_lock); return ret; } @@ -2131,6 +2146,13 @@ out: return err; } +#ifdef CONFIG_BCM947XX +static struct pci_device_id bcm43xx_47xx_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) }, + { 0 } +}; +#endif + static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) { int res; @@ -2140,11 +2162,15 @@ static int bcm43xx_initialize_irq(struct bcm->irq = bcm->pci_dev->irq; #ifdef CONFIG_BCM947XX if (bcm->pci_dev->bus->number == 0) { - struct pci_dev *d = NULL; - /* FIXME: we will probably need more device IDs here... */ - d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL); - if (d != NULL) { - bcm->irq = d->irq; + struct pci_dev *d; + struct pci_device_id *id; + for (id = bcm43xx_47xx_ids; id->vendor; id++) { + d = pci_get_device(id->vendor, id->device, NULL); + if (d != NULL) { + bcm->irq = d->irq; + pci_dev_put(d); + break; + } } } #endif @@ -3104,15 +3130,10 @@ static void bcm43xx_periodic_every15sec( //TODO for APHY (temperature?) } -static void bcm43xx_periodic_task_handler(unsigned long d) +static void do_periodic_work(struct bcm43xx_private *bcm) { - struct bcm43xx_private *bcm = (struct bcm43xx_private *)d; - unsigned long flags; unsigned int state; - bcm43xx_lock_mmio(bcm, flags); - - assert(bcm->initialized); state = bcm->periodic_state; if (state % 8 == 0) bcm43xx_periodic_every120sec(bcm); @@ -3120,29 +3141,93 @@ static void bcm43xx_periodic_task_handle bcm43xx_periodic_every60sec(bcm); if (state % 2 == 0) bcm43xx_periodic_every30sec(bcm); - bcm43xx_periodic_every15sec(bcm); + if (state % 1 == 0) + bcm43xx_periodic_every15sec(bcm); bcm->periodic_state = state + 1; - mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15)); + schedule_delayed_work(&bcm->periodic_work, HZ * 15); +} + +/* Estimate a "Badness" value based on the periodic work + * state-machine state. "Badness" is worse (bigger), if the + * periodic work will take longer. + */ +static int estimate_periodic_work_badness(unsigned int state) +{ + int badness = 0; - bcm43xx_unlock_mmio(bcm, flags); + if (state % 8 == 0) /* every 120 sec */ + badness += 10; + if (state % 4 == 0) /* every 60 sec */ + badness += 5; + if (state % 2 == 0) /* every 30 sec */ + badness += 1; + if (state % 1 == 0) /* every 15 sec */ + badness += 1; + +#define BADNESS_LIMIT 4 + return badness; +} + +static void bcm43xx_periodic_work_handler(void *d) +{ + struct bcm43xx_private *bcm = d; + unsigned long flags; + u32 savedirqs = 0; + int badness; + + badness = estimate_periodic_work_badness(bcm->periodic_state); + if (badness > BADNESS_LIMIT) { + /* Periodic work will take a long time, so we want it to + * be preemtible. + */ + bcm43xx_lock_irqonly(bcm, flags); + netif_stop_queue(bcm->net_dev); + if (bcm43xx_using_pio(bcm)) + bcm43xx_pio_freeze_txqueues(bcm); + savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + bcm43xx_unlock_irqonly(bcm, flags); + bcm43xx_lock_noirq(bcm); + bcm43xx_synchronize_irq(bcm); + } else { + /* Periodic work should take short time, so we want low + * locking overhead. + */ + bcm43xx_lock_irqsafe(bcm, flags); + } + + do_periodic_work(bcm); + + if (badness > BADNESS_LIMIT) { + bcm43xx_lock_irqonly(bcm, flags); + if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) { + tasklet_enable(&bcm->isr_tasklet); + bcm43xx_interrupt_enable(bcm, savedirqs); + if (bcm43xx_using_pio(bcm)) + bcm43xx_pio_thaw_txqueues(bcm); + } + netif_wake_queue(bcm->net_dev); + mmiowb(); + bcm43xx_unlock_irqonly(bcm, flags); + bcm43xx_unlock_noirq(bcm); + } else { + mmiowb(); + bcm43xx_unlock_irqsafe(bcm, flags); + } } static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) { - del_timer_sync(&bcm->periodic_tasks); + cancel_rearming_delayed_work(&bcm->periodic_work); } static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) { - struct timer_list *timer = &(bcm->periodic_tasks); + struct work_struct *work = &(bcm->periodic_work); - assert(bcm->initialized); - setup_timer(timer, - bcm43xx_periodic_task_handler, - (unsigned long)bcm); - timer->expires = jiffies; - add_timer(timer); + assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); + INIT_WORK(work, bcm43xx_periodic_work_handler, bcm); + schedule_work(work); } static void bcm43xx_security_init(struct bcm43xx_private *bcm) @@ -3152,21 +3237,51 @@ static void bcm43xx_security_init(struct bcm43xx_clear_keys(bcm); } +static int bcm43xx_rng_read(struct hwrng *rng, u32 *data) +{ + struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv; + unsigned long flags; + + bcm43xx_lock_irqonly(bcm, flags); + *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG); + bcm43xx_unlock_irqonly(bcm, flags); + + return (sizeof(u16)); +} + +static void bcm43xx_rng_exit(struct bcm43xx_private *bcm) +{ + hwrng_unregister(&bcm->rng); +} + +static int bcm43xx_rng_init(struct bcm43xx_private *bcm) +{ + int err; + + snprintf(bcm->rng_name, ARRAY_SIZE(bcm->rng_name), + "%s_%s", KBUILD_MODNAME, bcm->net_dev->name); + bcm->rng.name = bcm->rng_name; + bcm->rng.data_read = bcm43xx_rng_read; + bcm->rng.priv = (unsigned long)bcm; + err = hwrng_register(&bcm->rng); + if (err) + printk(KERN_ERR PFX "RNG init failed (%d)\n", err); + + return err; +} + /* This is the opposite of bcm43xx_init_board() */ static void bcm43xx_free_board(struct bcm43xx_private *bcm) { int i, err; - unsigned long flags; + bcm43xx_lock_noirq(bcm); bcm43xx_sysfs_unregister(bcm); - bcm43xx_periodic_tasks_delete(bcm); - bcm43xx_lock(bcm, flags); - bcm->initialized = 0; - bcm->shutting_down = 1; - bcm43xx_unlock(bcm, flags); + bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); + bcm43xx_rng_exit(bcm); for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { if (!bcm->core_80211[i].available) continue; @@ -3180,23 +3295,19 @@ static void bcm43xx_free_board(struct bc bcm43xx_pctl_set_crystal(bcm, 0); - bcm43xx_lock(bcm, flags); - bcm->shutting_down = 0; - bcm43xx_unlock(bcm, flags); + bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); + bcm43xx_unlock_noirq(bcm); } static int bcm43xx_init_board(struct bcm43xx_private *bcm) { int i, err; int connect_phy; - unsigned long flags; might_sleep(); - bcm43xx_lock(bcm, flags); - bcm->initialized = 0; - bcm->shutting_down = 0; - bcm43xx_unlock(bcm, flags); + bcm43xx_lock_noirq(bcm); + bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); err = bcm43xx_pctl_set_crystal(bcm, 1); if (err) @@ -3248,6 +3359,9 @@ static int bcm43xx_init_board(struct bcm bcm43xx_switch_core(bcm, &bcm->core_80211[0]); bcm43xx_mac_enable(bcm); } + err = bcm43xx_rng_init(bcm); + if (err) + goto err_80211_unwind; bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); dprintk(KERN_INFO PFX "80211 cores initialized\n"); @@ -3263,9 +3377,7 @@ static int bcm43xx_init_board(struct bcm } /* Initialization of the board is done. Flag it as such. */ - bcm43xx_lock(bcm, flags); - bcm->initialized = 1; - bcm43xx_unlock(bcm, flags); + bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); bcm43xx_periodic_tasks_setup(bcm); bcm43xx_sysfs_register(bcm); @@ -3276,6 +3388,8 @@ static int bcm43xx_init_board(struct bcm assert(err == 0); out: + bcm43xx_unlock_noirq(bcm); + return err; err_80211_unwind: @@ -3299,8 +3413,7 @@ static void bcm43xx_detach_board(struct bcm43xx_chipset_detach(bcm); /* Do _not_ access the chip, after it is detached. */ - iounmap(bcm->mmio_addr); - + pci_iounmap(pci_dev, bcm->mmio_addr); pci_release_regions(pci_dev); pci_disable_device(pci_dev); @@ -3390,40 +3503,26 @@ static int bcm43xx_attach_board(struct b struct net_device *net_dev = bcm->net_dev; int err; int i; - unsigned long mmio_start, mmio_flags, mmio_len; u32 coremask; err = pci_enable_device(pci_dev); if (err) { - printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err); + printk(KERN_ERR PFX "pci_enable_device() failed\n"); goto out; } - mmio_start = pci_resource_start(pci_dev, 0); - mmio_flags = pci_resource_flags(pci_dev, 0); - mmio_len = pci_resource_len(pci_dev, 0); - if (!(mmio_flags & IORESOURCE_MEM)) { - printk(KERN_ERR PFX - "%s, region #0 not an MMIO resource, aborting\n", - pci_name(pci_dev)); - err = -ENODEV; - goto err_pci_disable; - } err = pci_request_regions(pci_dev, KBUILD_MODNAME); if (err) { - printk(KERN_ERR PFX - "could not access PCI resources (%i)\n", err); + printk(KERN_ERR PFX "pci_request_regions() failed\n"); goto err_pci_disable; } /* enable PCI bus-mastering */ pci_set_master(pci_dev); - bcm->mmio_addr = ioremap(mmio_start, mmio_len); + bcm->mmio_addr = pci_iomap(pci_dev, 0, ~0UL); if (!bcm->mmio_addr) { - printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", - pci_name(pci_dev)); + printk(KERN_ERR PFX "pci_iomap() failed\n"); err = -EIO; goto err_pci_release; } - bcm->mmio_len = mmio_len; net_dev->base_addr = (unsigned long)bcm->mmio_addr; bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID, @@ -3517,7 +3616,7 @@ err_80211_unwind: err_chipset_detach: bcm43xx_chipset_detach(bcm); err_iounmap: - iounmap(bcm->mmio_addr); + pci_iounmap(pci_dev, bcm->mmio_addr); err_pci_release: pci_release_regions(pci_dev); err_pci_disable: @@ -3547,8 +3646,8 @@ static void bcm43xx_ieee80211_set_chan(s struct bcm43xx_radioinfo *radio; unsigned long flags; - bcm43xx_lock_mmio(bcm, flags); - if (bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { bcm43xx_mac_suspend(bcm); bcm43xx_radio_selectchannel(bcm, channel, 0); bcm43xx_mac_enable(bcm); @@ -3556,7 +3655,7 @@ static void bcm43xx_ieee80211_set_chan(s radio = bcm43xx_current_radio(bcm); radio->initial_channel = channel; } - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); } /* set_security() callback in struct ieee80211_device */ @@ -3568,9 +3667,9 @@ static void bcm43xx_ieee80211_set_securi unsigned long flags; int keyidx; - dprintk(KERN_INFO PFX "set security called\n"); + dprintk(KERN_INFO PFX "set security called"); - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); for (keyidx = 0; keyidxflags & (1<flags & SEC_ACTIVE_KEY) { secinfo->active_key = sec->active_key; - dprintk(KERN_INFO PFX " .active_key = %d\n", sec->active_key); + dprintk(", .active_key = %d", sec->active_key); } if (sec->flags & SEC_UNICAST_GROUP) { secinfo->unicast_uses_group = sec->unicast_uses_group; - dprintk(KERN_INFO PFX " .unicast_uses_group = %d\n", sec->unicast_uses_group); + dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group); } if (sec->flags & SEC_LEVEL) { secinfo->level = sec->level; - dprintk(KERN_INFO PFX " .level = %d\n", sec->level); + dprintk(", .level = %d", sec->level); } if (sec->flags & SEC_ENABLED) { secinfo->enabled = sec->enabled; - dprintk(KERN_INFO PFX " .enabled = %d\n", sec->enabled); + dprintk(", .enabled = %d", sec->enabled); } if (sec->flags & SEC_ENCRYPT) { secinfo->encrypt = sec->encrypt; - dprintk(KERN_INFO PFX " .encrypt = %d\n", sec->encrypt); + dprintk(", .encrypt = %d", sec->encrypt); } - if (bcm->initialized && !bcm->ieee->host_encrypt) { + dprintk("\n"); + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED && + !bcm->ieee->host_encrypt) { if (secinfo->enabled) { /* upload WEP keys to hardware */ char null_address[6] = { 0 }; @@ -3633,7 +3734,7 @@ static void bcm43xx_ieee80211_set_securi } else bcm43xx_clear_keys(bcm); } - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); } /* hard_start_xmit() callback in struct ieee80211_device */ @@ -3645,10 +3746,10 @@ static int bcm43xx_ieee80211_hard_start_ int err = -ENODEV; unsigned long flags; - bcm43xx_lock_mmio(bcm, flags); - if (likely(bcm->initialized)) + bcm43xx_lock_irqonly(bcm, flags); + if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) err = bcm43xx_tx(bcm, txb); - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqonly(bcm, flags); return err; } @@ -3663,9 +3764,9 @@ static void bcm43xx_net_tx_timeout(struc struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqonly(bcm, flags); bcm43xx_controller_restart(bcm, "TX timeout"); - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqonly(bcm, flags); } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -3690,9 +3791,11 @@ static int bcm43xx_net_open(struct net_d static int bcm43xx_net_stop(struct net_device *net_dev) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err; ieee80211softmac_stop(net_dev); - bcm43xx_disable_interrupts_sync(bcm, NULL); + err = bcm43xx_disable_interrupts_sync(bcm, NULL); + assert(!err); bcm43xx_free_board(bcm); return 0; @@ -3704,6 +3807,7 @@ static int bcm43xx_init_private(struct b { int err; + bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); bcm->ieee = netdev_priv(net_dev); bcm->softmac = ieee80211_priv(net_dev); bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; @@ -3712,7 +3816,8 @@ static int bcm43xx_init_private(struct b bcm->pci_dev = pci_dev; bcm->net_dev = net_dev; bcm->bad_frames_preempt = modparam_bad_frames_preempt; - spin_lock_init(&bcm->_lock); + spin_lock_init(&bcm->irq_lock); + mutex_init(&bcm->mutex); tasklet_init(&bcm->isr_tasklet, (void (*)(unsigned long))bcm43xx_interrupt_tasklet, (unsigned long)bcm); @@ -3843,7 +3948,7 @@ static void bcm43xx_chip_reset(void *_bc struct net_device *net_dev = bcm->net_dev; struct pci_dev *pci_dev = bcm->pci_dev; int err; - int was_initialized = bcm->initialized; + int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); netif_stop_queue(bcm->net_dev); tasklet_disable(&bcm->isr_tasklet); @@ -3878,6 +3983,7 @@ failure: */ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) { + bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING); bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); @@ -3896,11 +4002,11 @@ static int bcm43xx_suspend(struct pci_de dprintk(KERN_INFO PFX "Suspending...\n"); - bcm43xx_lock(bcm, flags); - bcm->was_initialized = bcm->initialized; - if (bcm->initialized) + bcm43xx_lock_irqsafe(bcm, flags); + bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); + if (bcm->was_initialized) try_to_shutdown = 1; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); netif_device_detach(net_dev); if (try_to_shutdown) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index b0abac5..f8200de 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -1410,7 +1410,10 @@ static inline u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + u16 ret; + unsigned long flags; + local_irq_save(flags); if (phy->connected) { bcm43xx_phy_write(bcm, 0x15, 0xE300); control <<= 8; @@ -1430,8 +1433,10 @@ u16 bcm43xx_phy_lo_g_deviation_subval(st bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0); udelay(8); } + ret = bcm43xx_phy_read(bcm, 0x002D); + local_irq_restore(flags); - return bcm43xx_phy_read(bcm, 0x002D); + return ret; } static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control) @@ -1648,7 +1653,7 @@ void bcm43xx_phy_set_baseband_attenuatio void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) { static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 }; - const int is_initializing = bcm43xx_is_initializing(bcm); + const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING); struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 h, i, oldi = 0, j; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 0aa1bd2..574085c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -262,8 +262,10 @@ static void tx_tasklet(unsigned long d) int err; u16 txctl; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqonly(bcm, flags); + if (queue->tx_frozen) + goto out_unlock; txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) goto out_unlock; @@ -298,7 +300,7 @@ static void tx_tasklet(unsigned long d) continue; } out_unlock: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqonly(bcm, flags); } static void setup_txqueues(struct bcm43xx_pioqueue *queue) @@ -374,7 +376,6 @@ static void cancel_transfers(struct bcm4 struct bcm43xx_pio_txpacket *packet, *tmp_packet; netif_tx_disable(queue->bcm->net_dev); - assert(queue->bcm->shutting_down); tasklet_disable(&queue->txtask); list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) @@ -634,5 +635,40 @@ void bcm43xx_pio_tx_resume(struct bcm43x bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) & ~BCM43xx_PIO_TXCTL_SUSPEND); bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1); - tasklet_schedule(&queue->txtask); + if (!list_empty(&queue->txqueue)) + tasklet_schedule(&queue->txtask); +} + +void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm) +{ + struct bcm43xx_pio *pio; + + assert(bcm43xx_using_pio(bcm)); + pio = bcm43xx_current_pio(bcm); + pio->queue0->tx_frozen = 1; + pio->queue1->tx_frozen = 1; + pio->queue2->tx_frozen = 1; + pio->queue3->tx_frozen = 1; } + +void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm) +{ + struct bcm43xx_pio *pio; + + assert(bcm43xx_using_pio(bcm)); + pio = bcm43xx_current_pio(bcm); + pio->queue0->tx_frozen = 0; + pio->queue1->tx_frozen = 0; + pio->queue2->tx_frozen = 0; + pio->queue3->tx_frozen = 0; + if (!list_empty(&pio->queue0->txqueue)) + tasklet_schedule(&pio->queue0->txtask); + if (!list_empty(&pio->queue1->txqueue)) + tasklet_schedule(&pio->queue1->txtask); + if (!list_empty(&pio->queue2->txqueue)) + tasklet_schedule(&pio->queue2->txtask); + if (!list_empty(&pio->queue3->txqueue)) + tasklet_schedule(&pio->queue3->txtask); +} + + diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h index dfc7820..bc78a3c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h @@ -54,6 +54,7 @@ struct bcm43xx_pioqueue { u16 mmio_base; u8 tx_suspended:1, + tx_frozen:1, need_workarounds:1; /* Workarounds needed for core.rev < 3 */ /* Adjusted size of the device internal TX buffer. */ @@ -108,8 +109,12 @@ void bcm43xx_pio_handle_xmitstatus(struc struct bcm43xx_xmitstatus *status); void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); +/* Suspend a TX queue on hardware level. */ void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue); void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue); +/* Suspend (freeze) the TX tasklet (software level). */ +void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm); +void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm); #else /* CONFIG_BCM43XX_PIO */ @@ -145,6 +150,14 @@ static inline void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) { } +static inline +void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm) +{ +} +static inline +void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm) +{ +} #endif /* CONFIG_BCM43XX_PIO */ #endif /* BCM43xx_PIO_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index b438f48..6a23bdc 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -120,12 +120,12 @@ static ssize_t bcm43xx_attr_sprom_show(s GFP_KERNEL); if (!sprom) return -ENOMEM; - bcm43xx_lock_mmio(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_irqsafe(bcm, flags); err = bcm43xx_sprom_read(bcm, sprom); if (!err) err = sprom2hex(sprom, buf, PAGE_SIZE); - bcm43xx_unlock_mmio(bcm, flags); + mmiowb(); + bcm43xx_unlock_irqsafe(bcm, flags); kfree(sprom); return err; @@ -150,10 +150,10 @@ static ssize_t bcm43xx_attr_sprom_store( err = hex2sprom(sprom, buf, count); if (err) goto out_kfree; - bcm43xx_lock_mmio(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_irqsafe(bcm, flags); err = bcm43xx_sprom_write(bcm, sprom); - bcm43xx_unlock_mmio(bcm, flags); + mmiowb(); + bcm43xx_unlock_irqsafe(bcm, flags); out_kfree: kfree(sprom); @@ -170,15 +170,13 @@ static ssize_t bcm43xx_attr_interfmode_s char *buf) { struct bcm43xx_private *bcm = dev_to_bcm(dev); - unsigned long flags; int err; ssize_t count = 0; if (!capable(CAP_NET_ADMIN)) return -EPERM; - bcm43xx_lock(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_noirq(bcm); switch (bcm43xx_current_radio(bcm)->interfmode) { case BCM43xx_RADIO_INTERFMODE_NONE: @@ -195,7 +193,7 @@ static ssize_t bcm43xx_attr_interfmode_s } err = 0; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_noirq(bcm); return err ? err : count; @@ -231,16 +229,15 @@ static ssize_t bcm43xx_attr_interfmode_s return -EINVAL; } - bcm43xx_lock_mmio(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_irqsafe(bcm, flags); err = bcm43xx_radio_set_interference_mitigation(bcm, mode); if (err) { printk(KERN_ERR PFX "Interference Mitigation not " "supported by device\n"); } - - bcm43xx_unlock_mmio(bcm, flags); + mmiowb(); + bcm43xx_unlock_irqsafe(bcm, flags); return err ? err : count; } @@ -254,15 +251,13 @@ static ssize_t bcm43xx_attr_preamble_sho char *buf) { struct bcm43xx_private *bcm = dev_to_bcm(dev); - unsigned long flags; int err; ssize_t count; if (!capable(CAP_NET_ADMIN)) return -EPERM; - bcm43xx_lock(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_noirq(bcm); if (bcm->short_preamble) count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); @@ -270,7 +265,7 @@ static ssize_t bcm43xx_attr_preamble_sho count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); err = 0; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_noirq(bcm); return err ? err : count; } @@ -290,13 +285,12 @@ static ssize_t bcm43xx_attr_preamble_sto value = get_boolean(buf, count); if (value < 0) return value; - bcm43xx_lock(bcm, flags); - assert(bcm->initialized); + bcm43xx_lock_irqsafe(bcm, flags); bcm->short_preamble = !!value; err = 0; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err ? err : count; } @@ -310,7 +304,7 @@ int bcm43xx_sysfs_register(struct bcm43x struct device *dev = &bcm->pci_dev->dev; int err; - assert(bcm->initialized); + assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); err = device_create_file(dev, &dev_attr_sprom); if (err) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index b450639..c35cb3a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -55,13 +55,13 @@ static int bcm43xx_wx_get_name(struct ne char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; int i; + unsigned long flags; struct bcm43xx_phyinfo *phy; char suffix[7] = { 0 }; int have_a = 0, have_b = 0, have_g = 0; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); for (i = 0; i < bcm->nr_80211_available; i++) { phy = &(bcm->core_80211_ext[i].phy); switch (phy->type) { @@ -77,7 +77,7 @@ static int bcm43xx_wx_get_name(struct ne assert(0); } } - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); i = 0; if (have_a) { @@ -111,7 +111,7 @@ static int bcm43xx_wx_set_channelfreq(st int freq; int err = -EINVAL; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { channel = data->freq.m; freq = bcm43xx_channel_to_freq(bcm, channel); @@ -121,7 +121,7 @@ static int bcm43xx_wx_set_channelfreq(st } if (!bcm43xx_is_valid_channel(bcm, channel)) goto out_unlock; - if (bcm->initialized) { + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { //ieee80211softmac_disassoc(softmac, $REASON); bcm43xx_mac_suspend(bcm); err = bcm43xx_radio_selectchannel(bcm, channel, 0); @@ -131,7 +131,7 @@ static int bcm43xx_wx_set_channelfreq(st err = 0; } out_unlock: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -147,11 +147,10 @@ static int bcm43xx_wx_get_channelfreq(st int err = -ENODEV; u16 channel; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); radio = bcm43xx_current_radio(bcm); channel = radio->channel; if (channel == 0xFF) { - assert(!bcm->initialized); channel = radio->initial_channel; if (channel == 0xFF) goto out_unlock; @@ -163,7 +162,7 @@ static int bcm43xx_wx_get_channelfreq(st err = 0; out_unlock: - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -181,13 +180,13 @@ static int bcm43xx_wx_set_mode(struct ne if (mode == IW_MODE_AUTO) mode = BCM43xx_INITIAL_IWMODE; - bcm43xx_lock_mmio(bcm, flags); - if (bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { if (bcm->ieee->iw_mode != mode) bcm43xx_set_iwmode(bcm, mode); } else bcm->ieee->iw_mode = mode; - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -200,9 +199,9 @@ static int bcm43xx_wx_get_mode(struct ne struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); data->mode = bcm->ieee->iw_mode; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -255,7 +254,7 @@ static int bcm43xx_wx_get_rangeparams(st IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); phy = bcm43xx_current_phy(bcm); range->num_bitrates = 0; @@ -302,7 +301,7 @@ static int bcm43xx_wx_get_rangeparams(st } range->num_frequency = j; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -313,14 +312,13 @@ static int bcm43xx_wx_set_nick(struct ne char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; size_t len; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_noirq(bcm); len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); memcpy(bcm->nick, extra, len); bcm->nick[len] = '\0'; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_noirq(bcm); return 0; } @@ -331,15 +329,14 @@ static int bcm43xx_wx_get_nick(struct ne char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; size_t len; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_noirq(bcm); len = strlen(bcm->nick) + 1; memcpy(extra, bcm->nick, len); data->data.length = (__u16)len; data->data.flags = 1; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_noirq(bcm); return 0; } @@ -353,7 +350,7 @@ static int bcm43xx_wx_set_rts(struct net unsigned long flags; int err = -EINVAL; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); if (data->rts.disabled) { bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; err = 0; @@ -364,7 +361,7 @@ static int bcm43xx_wx_set_rts(struct net err = 0; } } - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -377,11 +374,11 @@ static int bcm43xx_wx_get_rts(struct net struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); data->rts.value = bcm->rts_threshold; data->rts.fixed = 0; data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -395,7 +392,7 @@ static int bcm43xx_wx_set_frag(struct ne unsigned long flags; int err = -EINVAL; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); if (data->frag.disabled) { bcm->ieee->fts = MAX_FRAG_THRESHOLD; err = 0; @@ -406,7 +403,7 @@ static int bcm43xx_wx_set_frag(struct ne err = 0; } } - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -419,11 +416,11 @@ static int bcm43xx_wx_get_frag(struct ne struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); data->frag.value = bcm->ieee->fts; data->frag.fixed = 0; data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -445,8 +442,8 @@ static int bcm43xx_wx_set_xmitpower(stru return -EOPNOTSUPP; } - bcm43xx_lock_mmio(bcm, flags); - if (!bcm->initialized) + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) goto out_unlock; radio = bcm43xx_current_radio(bcm); phy = bcm43xx_current_phy(bcm); @@ -469,7 +466,7 @@ static int bcm43xx_wx_set_xmitpower(stru err = 0; out_unlock: - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -484,8 +481,8 @@ static int bcm43xx_wx_get_xmitpower(stru unsigned long flags; int err = -ENODEV; - bcm43xx_lock(bcm, flags); - if (!bcm->initialized) + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) goto out_unlock; radio = bcm43xx_current_radio(bcm); /* desired dBm value is in Q5.2 */ @@ -496,7 +493,7 @@ static int bcm43xx_wx_get_xmitpower(stru err = 0; out_unlock: - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -583,8 +580,8 @@ static int bcm43xx_wx_set_interfmode(str return -EINVAL; } - bcm43xx_lock_mmio(bcm, flags); - if (bcm->initialized) { + bcm43xx_lock_irqsafe(bcm, flags); + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { err = bcm43xx_radio_set_interference_mitigation(bcm, mode); if (err) { printk(KERN_ERR PFX "Interference Mitigation not " @@ -598,7 +595,7 @@ static int bcm43xx_wx_set_interfmode(str } else bcm43xx_current_radio(bcm)->interfmode = mode; } - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return err; } @@ -612,9 +609,9 @@ static int bcm43xx_wx_get_interfmode(str unsigned long flags; int mode; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); mode = bcm43xx_current_radio(bcm)->interfmode; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); switch (mode) { case BCM43xx_RADIO_INTERFMODE_NONE: @@ -644,9 +641,9 @@ static int bcm43xx_wx_set_shortpreamble( int on; on = *((int *)extra); - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); bcm->short_preamble = !!on; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -660,9 +657,9 @@ static int bcm43xx_wx_get_shortpreamble( unsigned long flags; int on; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); on = bcm->short_preamble; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); if (on) strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); @@ -684,11 +681,11 @@ static int bcm43xx_wx_set_swencryption(s on = *((int *)extra); - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); bcm->ieee->host_encrypt = !!on; bcm->ieee->host_decrypt = !!on; bcm->ieee->host_build_iv = !on; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); return 0; } @@ -702,9 +699,9 @@ static int bcm43xx_wx_get_swencryption(s unsigned long flags; int on; - bcm43xx_lock(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); on = bcm->ieee->host_encrypt; - bcm43xx_unlock(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); if (on) strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); @@ -767,11 +764,11 @@ static int bcm43xx_wx_sprom_read(struct if (!sprom) goto out; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); err = -ENODEV; - if (bcm->initialized) + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) err = bcm43xx_sprom_read(bcm, sprom); - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); if (!err) data->data.length = sprom2hex(sprom, extra); kfree(sprom); @@ -812,11 +809,11 @@ static int bcm43xx_wx_sprom_write(struct if (err) goto out_kfree; - bcm43xx_lock_mmio(bcm, flags); + bcm43xx_lock_irqsafe(bcm, flags); err = -ENODEV; - if (bcm->initialized) + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) err = bcm43xx_sprom_write(bcm, sprom); - bcm43xx_unlock_mmio(bcm, flags); + bcm43xx_unlock_irqsafe(bcm, flags); out_kfree: kfree(sprom); out: diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c index 346c6fe..2aa2f38 100644 --- a/drivers/net/wireless/hermes.c +++ b/drivers/net/wireless/hermes.c @@ -121,12 +121,6 @@ void hermes_struct_init(hermes_t *hw, vo hw->iobase = address; hw->reg_spacing = reg_spacing; hw->inten = 0x0; - -#ifdef HERMES_DEBUG_BUFFER - hw->dbufp = 0; - memset(&hw->dbuf, 0xff, sizeof(hw->dbuf)); - memset(&hw->profile, 0, sizeof(hw->profile)); -#endif } int hermes_init(hermes_t *hw) @@ -347,19 +341,6 @@ static int hermes_bap_seek(hermes_t *hw, reg = hermes_read_reg(hw, oreg); } -#ifdef HERMES_DEBUG_BUFFER - hw->profile[HERMES_BAP_BUSY_TIMEOUT - k]++; - - if (k < HERMES_BAP_BUSY_TIMEOUT) { - struct hermes_debug_entry *e = - &hw->dbuf[(hw->dbufp++) % HERMES_DEBUG_BUFSIZE]; - e->bap = bap; - e->id = id; - e->offset = offset; - e->cycles = HERMES_BAP_BUSY_TIMEOUT - k; - } -#endif - if (reg & HERMES_OFFSET_BUSY) return -ETIMEDOUT; @@ -419,8 +400,7 @@ int hermes_bap_pread(hermes_t *hw, int b } /* Write a block of data to the chip's buffer, via the - * BAP. Synchronization/serialization is the caller's problem. len - * must be even. + * BAP. Synchronization/serialization is the caller's problem. * * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware */ @@ -430,7 +410,7 @@ int hermes_bap_pwrite(hermes_t *hw, int int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; int err = 0; - if ( (len < 0) || (len % 2) ) + if (len < 0) return -EINVAL; err = hermes_bap_seek(hw, bap, id, offset); @@ -438,49 +418,12 @@ int hermes_bap_pwrite(hermes_t *hw, int goto out; /* Actually do the transfer */ - hermes_write_words(hw, dreg, buf, len/2); + hermes_write_bytes(hw, dreg, buf, len); out: return err; } -/* Write a block of data to the chip's buffer with padding if - * neccessary, via the BAP. Synchronization/serialization is the - * caller's problem. len must be even. - * - * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware - */ -int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, int len, - u16 id, u16 offset) -{ - int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; - int err = 0; - - if (len < 0 || len % 2 || data_len > len) - return -EINVAL; - - err = hermes_bap_seek(hw, bap, id, offset); - if (err) - goto out; - - /* Transfer all the complete words of data */ - hermes_write_words(hw, dreg, buf, data_len/2); - /* If there is an odd byte left over pad and transfer it */ - if (data_len & 1) { - u8 end[2]; - end[1] = 0; - end[0] = ((unsigned char *)buf)[data_len - 1]; - hermes_write_words(hw, dreg, end, 1); - data_len ++; - } - /* Now send zeros for the padding */ - if (data_len < len) - hermes_clear_words(hw, dreg, (len - data_len) / 2); - /* Complete */ - out: - return err; -} - /* Read a Length-Type-Value record from the card. * * If length is NULL, we ignore the length read from the card, and @@ -553,7 +496,7 @@ int hermes_write_ltv(hermes_t *hw, int b count = length - 1; - hermes_write_words(hw, dreg, value, count); + hermes_write_bytes(hw, dreg, value, count << 1); err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, rid, NULL); @@ -568,7 +511,6 @@ EXPORT_SYMBOL(hermes_allocate); EXPORT_SYMBOL(hermes_bap_pread); EXPORT_SYMBOL(hermes_bap_pwrite); -EXPORT_SYMBOL(hermes_bap_pwrite_pad); EXPORT_SYMBOL(hermes_read_ltv); EXPORT_SYMBOL(hermes_write_ltv); diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h index 7644f72..8e3f0e3 100644 --- a/drivers/net/wireless/hermes.h +++ b/drivers/net/wireless/hermes.h @@ -328,16 +328,6 @@ struct hermes_multicast { u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN]; } __attribute__ ((packed)); -// #define HERMES_DEBUG_BUFFER 1 -#define HERMES_DEBUG_BUFSIZE 4096 -struct hermes_debug_entry { - int bap; - u16 id, offset; - int cycles; -}; - -#ifdef __KERNEL__ - /* Timeouts */ #define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */ @@ -347,14 +337,7 @@ typedef struct hermes { int reg_spacing; #define HERMES_16BIT_REGSPACING 0 #define HERMES_32BIT_REGSPACING 1 - u16 inten; /* Which interrupts should be enabled? */ - -#ifdef HERMES_DEBUG_BUFFER - struct hermes_debug_entry dbuf[HERMES_DEBUG_BUFSIZE]; - unsigned long dbufp; - unsigned long profile[HERMES_BAP_BUSY_TIMEOUT+1]; -#endif } hermes_t; /* Register access convenience macros */ @@ -376,8 +359,6 @@ int hermes_bap_pread(hermes_t *hw, int b u16 id, u16 offset); int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, u16 id, u16 offset); -int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, - unsigned data_len, int len, u16 id, u16 offset); int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen, u16 *length, void *buf); int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, @@ -425,10 +406,13 @@ static inline void hermes_read_words(str ioread16_rep(hw->iobase + off, buf, count); } -static inline void hermes_write_words(struct hermes *hw, int off, const void *buf, unsigned count) +static inline void hermes_write_bytes(struct hermes *hw, int off, + const char *buf, unsigned count) { off = off << hw->reg_spacing; - iowrite16_rep(hw->iobase + off, buf, count); + iowrite16_rep(hw->iobase + off, buf, count >> 1); + if (unlikely(count & 1)) + iowrite8(buf[count - 1], hw->iobase + off); } static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count) @@ -462,21 +446,4 @@ static inline int hermes_write_wordrec(h return HERMES_WRITE_RECORD(hw, bap, rid, &rec); } -#else /* ! __KERNEL__ */ - -/* These are provided for the benefit of userspace drivers and testing programs - which use ioperm() or iopl() */ - -#define hermes_read_reg(base, off) (inw((base) + (off))) -#define hermes_write_reg(base, off, val) (outw((val), (base) + (off))) - -#define hermes_read_regn(base, name) (hermes_read_reg((base), HERMES_##name)) -#define hermes_write_regn(base, name, val) (hermes_write_reg((base), HERMES_##name, (val))) - -/* Note that for the next two, the count is in 16-bit words, not bytes */ -#define hermes_read_data(base, off, buf, count) (insw((base) + (off), (buf), (count))) -#define hermes_write_data(base, off, buf, count) (outsw((base) + (off), (buf), (count))) - -#endif /* ! __KERNEL__ */ - #endif /* _HERMES_H */ diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c index 06a5214..4a5be70 100644 --- a/drivers/net/wireless/hostap/hostap_80211_tx.c +++ b/drivers/net/wireless/hostap/hostap_80211_tx.c @@ -534,5 +534,4 @@ int hostap_master_start_xmit(struct sk_b } -EXPORT_SYMBOL(hostap_dump_tx_80211); EXPORT_SYMBOL(hostap_master_start_xmit); diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index 06c3fa3..ba13125 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -3276,17 +3276,6 @@ EXPORT_SYMBOL(hostap_init_data); EXPORT_SYMBOL(hostap_init_ap_proc); EXPORT_SYMBOL(hostap_free_data); EXPORT_SYMBOL(hostap_check_sta_fw_version); -EXPORT_SYMBOL(hostap_handle_sta_tx); -EXPORT_SYMBOL(hostap_handle_sta_release); EXPORT_SYMBOL(hostap_handle_sta_tx_exc); -EXPORT_SYMBOL(hostap_update_sta_ps); -EXPORT_SYMBOL(hostap_handle_sta_rx); -EXPORT_SYMBOL(hostap_is_sta_assoc); -EXPORT_SYMBOL(hostap_is_sta_authorized); -EXPORT_SYMBOL(hostap_add_sta); -EXPORT_SYMBOL(hostap_update_rates); -EXPORT_SYMBOL(hostap_add_wds_links); -EXPORT_SYMBOL(hostap_wds_link_oper); #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -EXPORT_SYMBOL(hostap_deauth_all_stas); #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 55bed92..db03dc2 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -881,6 +881,12 @@ static struct pcmcia_device_id hostap_cs PCMCIA_DEVICE_PROD_ID12( "ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), + PCMCIA_DEVICE_PROD_ID123( + "Pretec", "CompactWLAN Card 802.11b", "2.5", + 0x1cadd3e5, 0xe697636c, 0x7a5bfcf1), + PCMCIA_DEVICE_PROD_ID123( + "U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", + 0xc7b8df9d, 0x1700d087, 0x4b74baa0), PCMCIA_DEVICE_NULL }; MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index 8dd4c44..93786f4 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c @@ -1125,11 +1125,9 @@ EXPORT_SYMBOL(hostap_set_auth_algs); EXPORT_SYMBOL(hostap_dump_rx_header); EXPORT_SYMBOL(hostap_dump_tx_header); EXPORT_SYMBOL(hostap_80211_header_parse); -EXPORT_SYMBOL(hostap_80211_prism_header_parse); EXPORT_SYMBOL(hostap_80211_get_hdrlen); EXPORT_SYMBOL(hostap_get_stats); EXPORT_SYMBOL(hostap_setup_dev); -EXPORT_SYMBOL(hostap_proc); EXPORT_SYMBOL(hostap_set_multicast_list_queue); EXPORT_SYMBOL(hostap_set_hostapd); EXPORT_SYMBOL(hostap_set_hostapd_sta); diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 72335c8..94aeb23 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -1485,7 +1485,7 @@ #define HW_POWER_DOWN_DELAY (msecs_to_ji * * Sending the PREPARE_FOR_POWER_DOWN will restrict the * hardware from going into standby mode and will transition - * out of D0-standy if it is already in that state. + * out of D0-standby if it is already in that state. * * STATUS_PREPARE_POWER_DOWN_COMPLETE will be sent by the * driver upon completion. Once received, the driver can diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index bca89cf..081a899 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -33,7 +33,44 @@ #include "ipw2200.h" #include -#define IPW2200_VERSION "git-1.1.1" + +#ifndef KBUILD_EXTMOD +#define VK "k" +#else +#define VK +#endif + +#ifdef CONFIG_IPW2200_DEBUG +#define VD "d" +#else +#define VD +#endif + +#ifdef CONFIG_IPW2200_MONITOR +#define VM "m" +#else +#define VM +#endif + +#ifdef CONFIG_IPW2200_PROMISCUOUS +#define VP "p" +#else +#define VP +#endif + +#ifdef CONFIG_IPW2200_RADIOTAP +#define VR "r" +#else +#define VR +#endif + +#ifdef CONFIG_IPW2200_QOS +#define VQ "q" +#else +#define VQ +#endif + +#define IPW2200_VERSION "1.1.2" VK VD VM VP VR VQ #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" #define DRV_VERSION IPW2200_VERSION @@ -46,7 +83,9 @@ MODULE_AUTHOR(DRV_COPYRIGHT); MODULE_LICENSE("GPL"); static int cmdlog = 0; +#ifdef CONFIG_IPW2200_DEBUG static int debug = 0; +#endif static int channel = 0; static int mode = 0; @@ -61,8 +100,14 @@ static int roaming = 1; static const char ipw_modes[] = { 'a', 'b', 'g', '?' }; +static int antenna = CFG_SYS_ANTENNA_BOTH; + +#ifdef CONFIG_IPW2200_PROMISCUOUS +static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */ +#endif + -#ifdef CONFIG_IPW_QOS +#ifdef CONFIG_IPW2200_QOS static int qos_enable = 0; static int qos_burst_enable = 0; static int qos_no_ack_mask = 0; @@ -126,7 +171,7 @@ static int ipw_send_qos_params_command(s *qos_param); static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element *qos_param); -#endif /* CONFIG_IPW_QOS */ +#endif /* CONFIG_IPW2200_QOS */ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev); static void ipw_remove_current_network(struct ipw_priv *priv); @@ -488,7 +533,7 @@ static inline void ipw_clear_bit(struct ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask); } -static inline void ipw_enable_interrupts(struct ipw_priv *priv) +static inline void __ipw_enable_interrupts(struct ipw_priv *priv) { if (priv->status & STATUS_INT_ENABLED) return; @@ -496,7 +541,7 @@ static inline void ipw_enable_interrupts ipw_write32(priv, IPW_INTA_MASK_R, IPW_INTA_MASK_ALL); } -static inline void ipw_disable_interrupts(struct ipw_priv *priv) +static inline void __ipw_disable_interrupts(struct ipw_priv *priv) { if (!(priv->status & STATUS_INT_ENABLED)) return; @@ -504,6 +549,24 @@ static inline void ipw_disable_interrupt ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); } +static inline void ipw_enable_interrupts(struct ipw_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->irq_lock, flags); + __ipw_enable_interrupts(priv); + spin_unlock_irqrestore(&priv->irq_lock, flags); +} + +static inline void ipw_disable_interrupts(struct ipw_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->irq_lock, flags); + __ipw_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->irq_lock, flags); +} + #ifdef CONFIG_IPW2200_DEBUG static char *ipw_error_desc(u32 val) { @@ -1269,6 +1332,105 @@ static ssize_t show_cmd_log(struct devic static DEVICE_ATTR(cmd_log, S_IRUGO, show_cmd_log, NULL); +#ifdef CONFIG_IPW2200_PROMISCUOUS +static void ipw_prom_free(struct ipw_priv *priv); +static int ipw_prom_alloc(struct ipw_priv *priv); +static ssize_t store_rtap_iface(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + int rc = 0; + + if (count < 1) + return -EINVAL; + + switch (buf[0]) { + case '0': + if (!rtap_iface) + return count; + + if (netif_running(priv->prom_net_dev)) { + IPW_WARNING("Interface is up. Cannot unregister.\n"); + return count; + } + + ipw_prom_free(priv); + rtap_iface = 0; + break; + + case '1': + if (rtap_iface) + return count; + + rc = ipw_prom_alloc(priv); + if (!rc) + rtap_iface = 1; + break; + + default: + return -EINVAL; + } + + if (rc) { + IPW_ERROR("Failed to register promiscuous network " + "device (error %d).\n", rc); + } + + return count; +} + +static ssize_t show_rtap_iface(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + if (rtap_iface) + return sprintf(buf, "%s", priv->prom_net_dev->name); + else { + buf[0] = '-'; + buf[1] = '1'; + buf[2] = '\0'; + return 3; + } +} + +static DEVICE_ATTR(rtap_iface, S_IWUSR | S_IRUSR, show_rtap_iface, + store_rtap_iface); + +static ssize_t store_rtap_filter(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + + if (!priv->prom_priv) { + IPW_ERROR("Attempting to set filter without " + "rtap_iface enabled.\n"); + return -EPERM; + } + + priv->prom_priv->filter = simple_strtol(buf, NULL, 0); + + IPW_DEBUG_INFO("Setting rtap filter to " BIT_FMT16 "\n", + BIT_ARG16(priv->prom_priv->filter)); + + return count; +} + +static ssize_t show_rtap_filter(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct ipw_priv *priv = dev_get_drvdata(d); + return sprintf(buf, "0x%04X", + priv->prom_priv ? priv->prom_priv->filter : 0); +} + +static DEVICE_ATTR(rtap_filter, S_IWUSR | S_IRUSR, show_rtap_filter, + store_rtap_filter); +#endif + static ssize_t show_scan_age(struct device *d, struct device_attribute *attr, char *buf) { @@ -1712,7 +1874,7 @@ static void ipw_irq_tasklet(struct ipw_p unsigned long flags; int rc = 0; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->irq_lock, flags); inta = ipw_read32(priv, IPW_INTA_RW); inta_mask = ipw_read32(priv, IPW_INTA_MASK_R); @@ -1721,6 +1883,10 @@ static void ipw_irq_tasklet(struct ipw_p /* Add any cached INTA values that need to be handled */ inta |= priv->isr_inta; + spin_unlock_irqrestore(&priv->irq_lock, flags); + + spin_lock_irqsave(&priv->lock, flags); + /* handle all the justifications for the interrupt */ if (inta & IPW_INTA_BIT_RX_TRANSFER) { ipw_rx(priv); @@ -1849,10 +2015,10 @@ #endif IPW_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled); } + spin_unlock_irqrestore(&priv->lock, flags); + /* enable all interrupts */ ipw_enable_interrupts(priv); - - spin_unlock_irqrestore(&priv->lock, flags); } #define IPW_CMD(x) case IPW_CMD_ ## x : return #x @@ -2025,16 +2191,11 @@ static int ipw_send_host_complete(struct return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE); } -static int ipw_send_system_config(struct ipw_priv *priv, - struct ipw_sys_config *config) +static int ipw_send_system_config(struct ipw_priv *priv) { - if (!priv || !config) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, sizeof(*config), - config); + return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, + sizeof(priv->sys_config), + &priv->sys_config); } static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) @@ -3104,10 +3265,10 @@ static int ipw_reset_nic(struct ipw_priv struct ipw_fw { - u32 ver; - u32 boot_size; - u32 ucode_size; - u32 fw_size; + __le32 ver; + __le32 boot_size; + __le32 ucode_size; + __le32 fw_size; u8 data[0]; }; @@ -3131,8 +3292,8 @@ static int ipw_get_fw(struct ipw_priv *p fw = (void *)(*raw)->data; - if ((*raw)->size < sizeof(*fw) + - fw->boot_size + fw->ucode_size + fw->fw_size) { + if ((*raw)->size < sizeof(*fw) + le32_to_cpu(fw->boot_size) + + le32_to_cpu(fw->ucode_size) + le32_to_cpu(fw->fw_size)) { IPW_ERROR("%s is too small or corrupt (%zd)\n", name, (*raw)->size); return -EINVAL; @@ -3237,8 +3398,9 @@ #endif fw = (void *)raw->data; boot_img = &fw->data[0]; - ucode_img = &fw->data[fw->boot_size]; - fw_img = &fw->data[fw->boot_size + fw->ucode_size]; + ucode_img = &fw->data[le32_to_cpu(fw->boot_size)]; + fw_img = &fw->data[le32_to_cpu(fw->boot_size) + + le32_to_cpu(fw->ucode_size)]; if (rc < 0) goto error; @@ -3272,7 +3434,7 @@ #endif IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); /* DMA the initial boot firmware into the device */ - rc = ipw_load_firmware(priv, boot_img, fw->boot_size); + rc = ipw_load_firmware(priv, boot_img, le32_to_cpu(fw->boot_size)); if (rc < 0) { IPW_ERROR("Unable to load boot firmware: %d\n", rc); goto error; @@ -3294,7 +3456,7 @@ #endif ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); /* DMA the ucode into the device */ - rc = ipw_load_ucode(priv, ucode_img, fw->ucode_size); + rc = ipw_load_ucode(priv, ucode_img, le32_to_cpu(fw->ucode_size)); if (rc < 0) { IPW_ERROR("Unable to load ucode: %d\n", rc); goto error; @@ -3304,7 +3466,7 @@ #endif ipw_stop_nic(priv); /* DMA bss firmware into the device */ - rc = ipw_load_firmware(priv, fw_img, fw->fw_size); + rc = ipw_load_firmware(priv, fw_img, le32_to_cpu(fw->fw_size)); if (rc < 0) { IPW_ERROR("Unable to load firmware: %d\n", rc); goto error; @@ -3700,7 +3862,17 @@ static void ipw_bg_disassociate(void *da static void ipw_system_config(void *data) { struct ipw_priv *priv = data; - ipw_send_system_config(priv, &priv->sys_config); + +#ifdef CONFIG_IPW2200_PROMISCUOUS + if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) { + priv->sys_config.accept_all_data_frames = 1; + priv->sys_config.accept_non_directed_frames = 1; + priv->sys_config.accept_all_mgmt_bcpr = 1; + priv->sys_config.accept_all_mgmt_frames = 1; + } +#endif + + ipw_send_system_config(priv); } struct ipw_status_code { @@ -3771,6 +3943,13 @@ static void inline average_init(struct a memset(avg, 0, sizeof(*avg)); } +#define DEPTH_RSSI 8 +#define DEPTH_NOISE 16 +static s16 exponential_average(s16 prev_avg, s16 val, u8 depth) +{ + return ((depth-1)*prev_avg + val)/depth; +} + static void average_add(struct average *avg, s16 val) { avg->sum -= avg->entries[avg->pos]; @@ -3800,8 +3979,8 @@ static void ipw_reset_stats(struct ipw_p priv->quality = 0; average_init(&priv->average_missed_beacons); - average_init(&priv->average_rssi); - average_init(&priv->average_noise); + priv->exp_avg_rssi = -60; + priv->exp_avg_noise = -85 + 0x100; priv->last_rate = 0; priv->last_missed_beacons = 0; @@ -4008,7 +4187,7 @@ #define BEACON_THRESHOLD 5 IPW_DEBUG_STATS("Tx quality : %3d%% (%u errors, %u packets)\n", tx_quality, tx_failures_delta, tx_packets_delta); - rssi = average_value(&priv->average_rssi); + rssi = priv->exp_avg_rssi; signal_quality = (100 * (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) * @@ -4185,7 +4364,7 @@ static void ipw_rx_notification(struct i queue_work(priv->workqueue, &priv->system_config); -#ifdef CONFIG_IPW_QOS +#ifdef CONFIG_IPW2200_QOS #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \ le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_ctl)) if ((priv->status & STATUS_AUTH) && @@ -4482,6 +4661,24 @@ #endif /* CONFIG_IPW2200_MONITOR */ && priv->status & STATUS_ASSOCIATED) queue_delayed_work(priv->workqueue, &priv->request_scan, HZ); + + /* Send an empty event to user space. + * We don't send the received data on the event because + * it would require us to do complex transcoding, and + * we want to minimise the work done in the irq handler + * Use a request to extract the data. + * Also, we generate this even for any scan, regardless + * on how the scan was initiated. User space can just + * sync on periodic scan to get fresh data... + * Jean II */ + if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) { + union iwreq_data wrqu; + + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(priv->net_dev, SIOCGIWSCAN, + &wrqu, NULL); + } break; } @@ -4577,11 +4774,10 @@ #endif /* CONFIG_IPW2200_MONITOR */ case HOST_NOTIFICATION_NOISE_STATS:{ if (notif->size == sizeof(u32)) { - priv->last_noise = - (u8) (le32_to_cpu(notif->u.noise.value) & - 0xff); - average_add(&priv->average_noise, - priv->last_noise); + priv->exp_avg_noise = + exponential_average(priv->exp_avg_noise, + (u8) (le32_to_cpu(notif->u.noise.value) & 0xff), + DEPTH_NOISE); break; } @@ -6170,8 +6366,6 @@ static void ipw_wpa_assoc_frame(struct i { /* make sure WPA is enabled */ ipw_wpa_enable(priv, 1); - - ipw_disassociate(priv); } static int ipw_set_rsn_capa(struct ipw_priv *priv, @@ -6365,6 +6559,7 @@ static int ipw_wx_set_auth(struct net_de case IW_AUTH_WPA_ENABLED: ret = ipw_wpa_enable(priv, param->value); + ipw_disassociate(priv); break; case IW_AUTH_RX_UNENCRYPTED_EAPOL: @@ -6506,7 +6701,7 @@ static int ipw_wx_set_mlme(struct net_de return 0; } -#ifdef CONFIG_IPW_QOS +#ifdef CONFIG_IPW2200_QOS /* QoS */ /* @@ -6853,61 +7048,55 @@ static int ipw_get_tx_queue_number(struc return from_priority_to_tx_queue[priority] - 1; } -/* -* add QoS parameter to the TX command -*/ -static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, - u16 priority, - struct tfd_data *tfd, u8 unicast) +static int ipw_is_qos_active(struct net_device *dev, + struct sk_buff *skb) { - int ret = 0; - int tx_queue_id = 0; + struct ipw_priv *priv = ieee80211_priv(dev); struct ieee80211_qos_data *qos_data = NULL; int active, supported; - unsigned long flags; + u8 *daddr = skb->data + ETH_ALEN; + int unicast = !is_multicast_ether_addr(daddr); if (!(priv->status & STATUS_ASSOCIATED)) return 0; qos_data = &priv->assoc_network->qos_data; - spin_lock_irqsave(&priv->ieee->lock, flags); - if (priv->ieee->iw_mode == IW_MODE_ADHOC) { if (unicast == 0) qos_data->active = 0; else qos_data->active = qos_data->supported; } - active = qos_data->active; supported = qos_data->supported; - - spin_unlock_irqrestore(&priv->ieee->lock, flags); - IPW_DEBUG_QOS("QoS %d network is QoS active %d supported %d " "unicast %d\n", priv->qos_data.qos_enable, active, supported, unicast); - if (active && priv->qos_data.qos_enable) { - ret = from_priority_to_tx_queue[priority]; - tx_queue_id = ret - 1; - IPW_DEBUG_QOS("QoS packet priority is %d \n", priority); - if (priority <= 7) { - tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED; - tfd->tfd.tfd_26.mchdr.qos_ctrl = priority; - tfd->tfd.tfd_26.mchdr.frame_ctl |= - IEEE80211_STYPE_QOS_DATA; - - if (priv->qos_data.qos_no_ack_mask & - (1UL << tx_queue_id)) { - tfd->tx_flags &= ~DCT_FLAG_ACK_REQD; - tfd->tfd.tfd_26.mchdr.qos_ctrl |= - CTRL_QOS_NO_ACK; - } - } - } + if (active && priv->qos_data.qos_enable) + return 1; - return ret; + return 0; + +} +/* +* add QoS parameter to the TX command +*/ +static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, + u16 priority, + struct tfd_data *tfd) +{ + int tx_queue_id = 0; + + + tx_queue_id = from_priority_to_tx_queue[priority] - 1; + tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED; + + if (priv->qos_data.qos_no_ack_mask & (1UL << tx_queue_id)) { + tfd->tx_flags &= ~DCT_FLAG_ACK_REQD; + tfd->tfd.tfd_26.mchdr.qos_ctrl |= CTRL_QOS_NO_ACK; + } + return 0; } /* @@ -6977,7 +7166,7 @@ static int ipw_send_qos_info_command(str qos_param); } -#endif /* CONFIG_IPW_QOS */ +#endif /* CONFIG_IPW2200_QOS */ static int ipw_associate_network(struct ipw_priv *priv, struct ieee80211_network *network, @@ -7116,7 +7305,7 @@ static int ipw_associate_network(struct else priv->sys_config.answer_broadcast_ssid_probe = 0; - err = ipw_send_system_config(priv, &priv->sys_config); + err = ipw_send_system_config(priv); if (err) { IPW_DEBUG_HC("Attempt to send sys config command failed.\n"); return err; @@ -7141,7 +7330,7 @@ static int ipw_associate_network(struct priv->assoc_network = network; -#ifdef CONFIG_IPW_QOS +#ifdef CONFIG_IPW2200_QOS ipw_qos_association(priv, network); #endif @@ -7415,7 +7604,7 @@ static void ipw_handle_data_packet(struc } } -#ifdef CONFIG_IEEE80211_RADIOTAP +#ifdef CONFIG_IPW2200_RADIOTAP static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, struct ipw_rx_mem_buffer *rxb, struct ieee80211_rx_stats *stats) @@ -7432,15 +7621,7 @@ static void ipw_handle_data_packet_monit /* Magic struct that slots into the radiotap header -- no reason * to build this manually element by element, we can write it much * more efficiently than we can parse it. ORDER MATTERS HERE */ - struct ipw_rt_hdr { - struct ieee80211_radiotap_header rt_hdr; - u8 rt_flags; /* radiotap packet flags */ - u8 rt_rate; /* rate in 500kb/s */ - u16 rt_channel; /* channel in mhz */ - u16 rt_chbitmask; /* channel bitfield */ - s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ - u8 rt_antenna; /* antenna number */ - } *ipw_rt; + struct ipw_rt_hdr *ipw_rt; short len = le16_to_cpu(pkt->u.frame.length); @@ -7494,9 +7675,11 @@ static void ipw_handle_data_packet_monit /* Big bitfield of all the fields we provide in radiotap */ ipw_rt->rt_hdr.it_present = ((1 << IEEE80211_RADIOTAP_FLAGS) | + (1 << IEEE80211_RADIOTAP_TSFT) | (1 << IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_CHANNEL) | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | + (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | (1 << IEEE80211_RADIOTAP_ANTENNA)); /* Zero the flags, we'll add to them as we go */ @@ -7582,6 +7765,217 @@ static void ipw_handle_data_packet_monit } #endif +#ifdef CONFIG_IPW2200_PROMISCUOUS +#define ieee80211_is_probe_response(fc) \ + ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && \ + (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP ) + +#define ieee80211_is_management(fc) \ + ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) + +#define ieee80211_is_control(fc) \ + ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) + +#define ieee80211_is_data(fc) \ + ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) + +#define ieee80211_is_assoc_request(fc) \ + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ) + +#define ieee80211_is_reassoc_request(fc) \ + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ) + +static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, + struct ipw_rx_mem_buffer *rxb, + struct ieee80211_rx_stats *stats) +{ + struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; + struct ipw_rx_frame *frame = &pkt->u.frame; + struct ipw_rt_hdr *ipw_rt; + + /* First cache any information we need before we overwrite + * the information provided in the skb from the hardware */ + struct ieee80211_hdr *hdr; + u16 channel = frame->received_channel; + u8 phy_flags = frame->antennaAndPhy; + s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM; + s8 noise = frame->noise; + u8 rate = frame->rate; + short len = le16_to_cpu(pkt->u.frame.length); + u64 tsf = 0; + struct sk_buff *skb; + int hdr_only = 0; + u16 filter = priv->prom_priv->filter; + + /* If the filter is set to not include Rx frames then return */ + if (filter & IPW_PROM_NO_RX) + return; + + /* We received data from the HW, so stop the watchdog */ + priv->prom_net_dev->trans_start = jiffies; + + if (unlikely((len + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { + priv->prom_priv->ieee->stats.rx_errors++; + IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); + return; + } + + /* We only process data packets if the interface is open */ + if (unlikely(!netif_running(priv->prom_net_dev))) { + priv->prom_priv->ieee->stats.rx_dropped++; + IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); + return; + } + + /* Libpcap 0.9.3+ can handle variable length radiotap, so we'll use + * that now */ + if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) { + /* FIXME: Should alloc bigger skb instead */ + priv->prom_priv->ieee->stats.rx_dropped++; + IPW_DEBUG_DROP("Dropping too large packet in monitor\n"); + return; + } + + hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE; + if (ieee80211_is_management(hdr->frame_ctl)) { + if (filter & IPW_PROM_NO_MGMT) + return; + if (filter & IPW_PROM_MGMT_HEADER_ONLY) + hdr_only = 1; + } else if (ieee80211_is_control(hdr->frame_ctl)) { + if (filter & IPW_PROM_NO_CTL) + return; + if (filter & IPW_PROM_CTL_HEADER_ONLY) + hdr_only = 1; + } else if (ieee80211_is_data(hdr->frame_ctl)) { + if (filter & IPW_PROM_NO_DATA) + return; + if (filter & IPW_PROM_DATA_HEADER_ONLY) + hdr_only = 1; + } + + /* Copy the SKB since this is for the promiscuous side */ + skb = skb_copy(rxb->skb, GFP_ATOMIC); + if (skb == NULL) { + IPW_ERROR("skb_clone failed for promiscuous copy.\n"); + return; + } + + /* copy the frame data to write after where the radiotap header goes */ + ipw_rt = (void *)skb->data; + + if (hdr_only) + len = ieee80211_get_hdrlen(hdr->frame_ctl); + + memcpy(ipw_rt->payload, hdr, len); + + /* Zero the radiotap static buffer ... We only need to zero the bytes + * NOT part of our real header, saves a little time. + * + * No longer necessary since we fill in all our data. Purge before + * merging patch officially. + * memset(rxb->skb->data + sizeof(struct ipw_rt_hdr), 0, + * IEEE80211_RADIOTAP_HDRLEN - sizeof(struct ipw_rt_hdr)); + */ + + ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; + ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ + ipw_rt->rt_hdr.it_len = sizeof(*ipw_rt); /* total header+data */ + + /* Set the size of the skb to the size of the frame */ + skb_put(skb, ipw_rt->rt_hdr.it_len + len); + + /* Big bitfield of all the fields we provide in radiotap */ + ipw_rt->rt_hdr.it_present = + ((1 << IEEE80211_RADIOTAP_FLAGS) | + (1 << IEEE80211_RADIOTAP_TSFT) | + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_CHANNEL) | + (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | + (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | + (1 << IEEE80211_RADIOTAP_ANTENNA)); + + /* Zero the flags, we'll add to them as we go */ + ipw_rt->rt_flags = 0; + + ipw_rt->rt_tsf = tsf; + + /* Convert to DBM */ + ipw_rt->rt_dbmsignal = signal; + ipw_rt->rt_dbmnoise = noise; + + /* Convert the channel data and set the flags */ + ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(channel)); + if (channel > 14) { /* 802.11a */ + ipw_rt->rt_chbitmask = + cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); + } else if (phy_flags & (1 << 5)) { /* 802.11b */ + ipw_rt->rt_chbitmask = + cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ)); + } else { /* 802.11g */ + ipw_rt->rt_chbitmask = + (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); + } + + /* set the rate in multiples of 500k/s */ + switch (rate) { + case IPW_TX_RATE_1MB: + ipw_rt->rt_rate = 2; + break; + case IPW_TX_RATE_2MB: + ipw_rt->rt_rate = 4; + break; + case IPW_TX_RATE_5MB: + ipw_rt->rt_rate = 10; + break; + case IPW_TX_RATE_6MB: + ipw_rt->rt_rate = 12; + break; + case IPW_TX_RATE_9MB: + ipw_rt->rt_rate = 18; + break; + case IPW_TX_RATE_11MB: + ipw_rt->rt_rate = 22; + break; + case IPW_TX_RATE_12MB: + ipw_rt->rt_rate = 24; + break; + case IPW_TX_RATE_18MB: + ipw_rt->rt_rate = 36; + break; + case IPW_TX_RATE_24MB: + ipw_rt->rt_rate = 48; + break; + case IPW_TX_RATE_36MB: + ipw_rt->rt_rate = 72; + break; + case IPW_TX_RATE_48MB: + ipw_rt->rt_rate = 96; + break; + case IPW_TX_RATE_54MB: + ipw_rt->rt_rate = 108; + break; + default: + ipw_rt->rt_rate = 0; + break; + } + + /* antenna number */ + ipw_rt->rt_antenna = (phy_flags & 3); + + /* set the preamble flag if we have it */ + if (phy_flags & (1 << 6)) + ipw_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + + IPW_DEBUG_RX("Rx packet of %d bytes.\n", skb->len); + + if (!ieee80211_rx(priv->prom_priv->ieee, skb, stats)) { + priv->prom_priv->ieee->stats.rx_errors++; + dev_kfree_skb_any(skb); + } +} +#endif + static int is_network_packet(struct ipw_priv *priv, struct ieee80211_hdr_4addr *header) { @@ -7808,15 +8202,21 @@ static void ipw_rx(struct ipw_priv *priv priv->rx_packets++; +#ifdef CONFIG_IPW2200_PROMISCUOUS + if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) + ipw_handle_promiscuous_rx(priv, rxb, &stats); +#endif + #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { -#ifdef CONFIG_IEEE80211_RADIOTAP - ipw_handle_data_packet_monitor(priv, - rxb, - &stats); +#ifdef CONFIG_IPW2200_RADIOTAP + + ipw_handle_data_packet_monitor(priv, + rxb, + &stats); #else - ipw_handle_data_packet(priv, rxb, - &stats); + ipw_handle_data_packet(priv, rxb, + &stats); #endif break; } @@ -7837,9 +8237,9 @@ #endif if (network_packet && priv->assoc_network) { priv->assoc_network->stats.rssi = stats.rssi; - average_add(&priv->average_rssi, - stats.rssi); - priv->last_rx_rssi = stats.rssi; + priv->exp_avg_rssi = + exponential_average(priv->exp_avg_rssi, + stats.rssi, DEPTH_RSSI); } IPW_DEBUG_RX("Frame: len=%u\n", @@ -7982,10 +8382,10 @@ static int ipw_sw_reset(struct ipw_priv IPW_DEBUG_INFO("Bind to static channel %d\n", channel); /* TODO: Validate that provided channel is in range */ } -#ifdef CONFIG_IPW_QOS +#ifdef CONFIG_IPW2200_QOS ipw_qos_init(priv, qos_enable, qos_burst_enable, burst_duration_CCK, burst_duration_OFDM); -#endif /* CONFIG_IPW_QOS */ +#endif /* CONFIG_IPW2200_QOS */ switch (mode) { case 1: @@ -7996,7 +8396,7 @@ #endif /* CONFIG_IPW_QOS */ #ifdef CONFIG_IPW2200_MONITOR case 2: priv->ieee->iw_mode = IW_MODE_MONITOR; -#ifdef CONFIG_IEEE80211_RADIOTAP +#ifdef CONFIG_IPW2200_RADIOTAP priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; #else priv->net_dev->type = ARPHRD_IEEE80211; @@ -8251,7 +8651,7 @@ #ifdef CONFIG_IPW2200_MONITOR priv->net_dev->type = ARPHRD_ETHER; if (wrqu->mode == IW_MODE_MONITOR) -#ifdef CONFIG_IEEE80211_RADIOTAP +#ifdef CONFIG_IPW2200_RADIOTAP priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; #else priv->net_dev->type = ARPHRD_IEEE80211; @@ -8379,7 +8779,8 @@ static int ipw_wx_get_range(struct net_d /* Event capability (kernel + driver) */ range->event_capa[0] = (IW_EVENT_CAPA_K_0 | IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | - IW_EVENT_CAPA_MASK(SIOCGIWAP)); + IW_EVENT_CAPA_MASK(SIOCGIWAP) | + IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); range->event_capa[1] = IW_EVENT_CAPA_K_1; range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | @@ -8734,6 +9135,7 @@ static int ipw_wx_get_rate(struct net_de struct ipw_priv *priv = ieee80211_priv(dev); mutex_lock(&priv->mutex); wrqu->bitrate.value = priv->last_rate; + wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0; mutex_unlock(&priv->mutex); IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); return 0; @@ -9351,7 +9753,7 @@ static int ipw_wx_set_monitor(struct net IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); if (enable) { if (priv->ieee->iw_mode != IW_MODE_MONITOR) { -#ifdef CONFIG_IEEE80211_RADIOTAP +#ifdef CONFIG_IPW2200_RADIOTAP priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; #else priv->net_dev->type = ARPHRD_IEEE80211; @@ -9579,8 +9981,8 @@ static struct iw_statistics *ipw_get_wir } wstats->qual.qual = priv->quality; - wstats->qual.level = average_value(&priv->average_rssi); - wstats->qual.noise = average_value(&priv->average_noise); + wstats->qual.level = priv->exp_avg_rssi; + wstats->qual.noise = priv->exp_avg_noise; wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; @@ -9608,7 +10010,9 @@ static void init_sys_config(struct ipw_ sys_config->disable_unicast_decryption = 1; sys_config->exclude_multicast_unencrypted = 0; sys_config->disable_multicast_decryption = 1; - sys_config->antenna_diversity = CFG_SYS_ANTENNA_SLOW_DIV; + if (antenna < CFG_SYS_ANTENNA_BOTH || antenna > CFG_SYS_ANTENNA_B) + antenna = CFG_SYS_ANTENNA_BOTH; + sys_config->antenna_diversity = antenna; sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */ sys_config->dot11g_auto_detection = 0; sys_config->enable_cts_to_self = 0; @@ -9647,11 +10051,11 @@ we need to heavily modify the ieee80211_ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, int pri) { - struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) + struct ieee80211_hdr_3addrqos *hdr = (struct ieee80211_hdr_3addrqos *) txb->fragments[0]->data; int i = 0; struct tfd_frame *tfd; -#ifdef CONFIG_IPW_QOS +#ifdef CONFIG_IPW2200_QOS int tx_id = ipw_get_tx_queue_number(priv, pri); struct clx2_tx_queue *txq = &priv->txq[tx_id]; #else @@ -9662,9 +10066,9 @@ #endif u16 remaining_bytes; int fc; + hdr_len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); switch (priv->ieee->iw_mode) { case IW_MODE_ADHOC: - hdr_len = IEEE80211_3ADDR_LEN; unicast = !is_multicast_ether_addr(hdr->addr1); id = ipw_find_station(priv, hdr->addr1); if (id == IPW_INVALID_STATION) { @@ -9681,7 +10085,6 @@ #endif case IW_MODE_INFRA: default: unicast = !is_multicast_ether_addr(hdr->addr3); - hdr_len = IEEE80211_3ADDR_LEN; id = 0; break; } @@ -9759,9 +10162,10 @@ #endif /* No hardware encryption */ tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP; -#ifdef CONFIG_IPW_QOS - ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data), unicast); -#endif /* CONFIG_IPW_QOS */ +#ifdef CONFIG_IPW2200_QOS + if (fc & IEEE80211_STYPE_QOS_DATA) + ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data)); +#endif /* CONFIG_IPW2200_QOS */ /* payload */ tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2), @@ -9841,12 +10245,12 @@ #endif /* CONFIG_IPW_QOS */ static int ipw_net_is_queue_full(struct net_device *dev, int pri) { struct ipw_priv *priv = ieee80211_priv(dev); -#ifdef CONFIG_IPW_QOS +#ifdef CONFIG_IPW2200_QOS int tx_id = ipw_get_tx_queue_number(priv, pri); struct clx2_tx_queue *txq = &priv->txq[tx_id]; #else struct clx2_tx_queue *txq = &priv->txq[0]; -#endif /* CONFIG_IPW_QOS */ +#endif /* CONFIG_IPW2200_QOS */ if (ipw_queue_space(&txq->q) < txq->q.high_mark) return 1; @@ -9854,6 +10258,88 @@ #endif /* CONFIG_IPW_QOS */ return 0; } +#ifdef CONFIG_IPW2200_PROMISCUOUS +static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, + struct ieee80211_txb *txb) +{ + struct ieee80211_rx_stats dummystats; + struct ieee80211_hdr *hdr; + u8 n; + u16 filter = priv->prom_priv->filter; + int hdr_only = 0; + + if (filter & IPW_PROM_NO_TX) + return; + + memset(&dummystats, 0, sizeof(dummystats)); + + /* Filtering of fragment chains is done agains the first fragment */ + hdr = (void *)txb->fragments[0]->data; + if (ieee80211_is_management(hdr->frame_ctl)) { + if (filter & IPW_PROM_NO_MGMT) + return; + if (filter & IPW_PROM_MGMT_HEADER_ONLY) + hdr_only = 1; + } else if (ieee80211_is_control(hdr->frame_ctl)) { + if (filter & IPW_PROM_NO_CTL) + return; + if (filter & IPW_PROM_CTL_HEADER_ONLY) + hdr_only = 1; + } else if (ieee80211_is_data(hdr->frame_ctl)) { + if (filter & IPW_PROM_NO_DATA) + return; + if (filter & IPW_PROM_DATA_HEADER_ONLY) + hdr_only = 1; + } + + for(n=0; nnr_frags; ++n) { + struct sk_buff *src = txb->fragments[n]; + struct sk_buff *dst; + struct ieee80211_radiotap_header *rt_hdr; + int len; + + if (hdr_only) { + hdr = (void *)src->data; + len = ieee80211_get_hdrlen(hdr->frame_ctl); + } else + len = src->len; + + dst = alloc_skb( + len + IEEE80211_RADIOTAP_HDRLEN, GFP_ATOMIC); + if (!dst) continue; + + rt_hdr = (void *)skb_put(dst, sizeof(*rt_hdr)); + + rt_hdr->it_version = PKTHDR_RADIOTAP_VERSION; + rt_hdr->it_pad = 0; + rt_hdr->it_present = 0; /* after all, it's just an idea */ + rt_hdr->it_present |= (1 << IEEE80211_RADIOTAP_CHANNEL); + + *(u16*)skb_put(dst, sizeof(u16)) = cpu_to_le16( + ieee80211chan2mhz(priv->channel)); + if (priv->channel > 14) /* 802.11a */ + *(u16*)skb_put(dst, sizeof(u16)) = + cpu_to_le16(IEEE80211_CHAN_OFDM | + IEEE80211_CHAN_5GHZ); + else if (priv->ieee->mode == IEEE_B) /* 802.11b */ + *(u16*)skb_put(dst, sizeof(u16)) = + cpu_to_le16(IEEE80211_CHAN_CCK | + IEEE80211_CHAN_2GHZ); + else /* 802.11g */ + *(u16*)skb_put(dst, sizeof(u16)) = + cpu_to_le16(IEEE80211_CHAN_OFDM | + IEEE80211_CHAN_2GHZ); + + rt_hdr->it_len = dst->len; + + memcpy(skb_put(dst, len), src->data, len); + + if (!ieee80211_rx(priv->prom_priv->ieee, dst, &dummystats)) + dev_kfree_skb_any(dst); + } +} +#endif + static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, struct net_device *dev, int pri) { @@ -9871,6 +10357,11 @@ static int ipw_net_hard_start_xmit(struc goto fail_unlock; } +#ifdef CONFIG_IPW2200_PROMISCUOUS + if (rtap_iface && netif_running(priv->prom_net_dev)) + ipw_handle_promiscuous_tx(priv, txb); +#endif + ret = ipw_tx_skb(priv, txb, pri); if (ret == NETDEV_TX_OK) __ipw_led_activity_on(priv); @@ -9991,7 +10482,7 @@ static irqreturn_t ipw_isr(int irq, void if (!priv) return IRQ_NONE; - spin_lock(&priv->lock); + spin_lock(&priv->irq_lock); if (!(priv->status & STATUS_INT_ENABLED)) { /* Shared IRQ */ @@ -10013,7 +10504,7 @@ static irqreturn_t ipw_isr(int irq, void } /* tell the device to stop sending interrupts */ - ipw_disable_interrupts(priv); + __ipw_disable_interrupts(priv); /* ack current interrupts */ inta &= (IPW_INTA_MASK_ALL & inta_mask); @@ -10024,11 +10515,11 @@ static irqreturn_t ipw_isr(int irq, void tasklet_schedule(&priv->irq_tasklet); - spin_unlock(&priv->lock); + spin_unlock(&priv->irq_lock); return IRQ_HANDLED; none: - spin_unlock(&priv->lock); + spin_unlock(&priv->irq_lock); return IRQ_NONE; } @@ -10169,10 +10660,10 @@ static int ipw_setup_deferred_work(struc INIT_WORK(&priv->merge_networks, (void (*)(void *))ipw_merge_adhoc_network, priv); -#ifdef CONFIG_IPW_QOS +#ifdef CONFIG_IPW2200_QOS INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate, priv); -#endif /* CONFIG_IPW_QOS */ +#endif /* CONFIG_IPW2200_QOS */ tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) ipw_irq_tasklet, (unsigned long)priv); @@ -10318,12 +10809,21 @@ static int ipw_config(struct ipw_priv *p |= CFG_BT_COEXISTENCE_OOB; } +#ifdef CONFIG_IPW2200_PROMISCUOUS + if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) { + priv->sys_config.accept_all_data_frames = 1; + priv->sys_config.accept_non_directed_frames = 1; + priv->sys_config.accept_all_mgmt_bcpr = 1; + priv->sys_config.accept_all_mgmt_frames = 1; + } +#endif + if (priv->ieee->iw_mode == IW_MODE_ADHOC) priv->sys_config.answer_broadcast_ssid_probe = 1; else priv->sys_config.answer_broadcast_ssid_probe = 0; - if (ipw_send_system_config(priv, &priv->sys_config)) + if (ipw_send_system_config(priv)) goto error; init_supported_rates(priv, &priv->rates); @@ -10335,10 +10835,10 @@ static int ipw_config(struct ipw_priv *p if (ipw_send_rts_threshold(priv, priv->rts_threshold)) goto error; } -#ifdef CONFIG_IPW_QOS +#ifdef CONFIG_IPW2200_QOS IPW_DEBUG_QOS("QoS: call ipw_qos_activate\n"); ipw_qos_activate(priv, NULL); -#endif /* CONFIG_IPW_QOS */ +#endif /* CONFIG_IPW2200_QOS */ if (ipw_set_random_seed(priv)) goto error; @@ -10639,6 +11139,7 @@ static int ipw_up(struct ipw_priv *priv) if (priv->cmdlog == NULL) { IPW_ERROR("Error allocating %d command log entries.\n", cmdlog); + return -ENOMEM; } else { memset(priv->cmdlog, 0, sizeof(*priv->cmdlog) * cmdlog); priv->cmdlog_len = cmdlog; @@ -10860,6 +11361,10 @@ static struct attribute *ipw_sysfs_entri &dev_attr_led.attr, &dev_attr_speed_scan.attr, &dev_attr_net_stats.attr, +#ifdef CONFIG_IPW2200_PROMISCUOUS + &dev_attr_rtap_iface.attr, + &dev_attr_rtap_filter.attr, +#endif NULL }; @@ -10868,6 +11373,109 @@ static struct attribute_group ipw_attrib .attrs = ipw_sysfs_entries, }; +#ifdef CONFIG_IPW2200_PROMISCUOUS +static int ipw_prom_open(struct net_device *dev) +{ + struct ipw_prom_priv *prom_priv = ieee80211_priv(dev); + struct ipw_priv *priv = prom_priv->priv; + + IPW_DEBUG_INFO("prom dev->open\n"); + netif_carrier_off(dev); + netif_stop_queue(dev); + + if (priv->ieee->iw_mode != IW_MODE_MONITOR) { + priv->sys_config.accept_all_data_frames = 1; + priv->sys_config.accept_non_directed_frames = 1; + priv->sys_config.accept_all_mgmt_bcpr = 1; + priv->sys_config.accept_all_mgmt_frames = 1; + + ipw_send_system_config(priv); + } + + return 0; +} + +static int ipw_prom_stop(struct net_device *dev) +{ + struct ipw_prom_priv *prom_priv = ieee80211_priv(dev); + struct ipw_priv *priv = prom_priv->priv; + + IPW_DEBUG_INFO("prom dev->stop\n"); + + if (priv->ieee->iw_mode != IW_MODE_MONITOR) { + priv->sys_config.accept_all_data_frames = 0; + priv->sys_config.accept_non_directed_frames = 0; + priv->sys_config.accept_all_mgmt_bcpr = 0; + priv->sys_config.accept_all_mgmt_frames = 0; + + ipw_send_system_config(priv); + } + + return 0; +} + +static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + IPW_DEBUG_INFO("prom dev->xmit\n"); + netif_stop_queue(dev); + return -EOPNOTSUPP; +} + +static struct net_device_stats *ipw_prom_get_stats(struct net_device *dev) +{ + struct ipw_prom_priv *prom_priv = ieee80211_priv(dev); + return &prom_priv->ieee->stats; +} + +static int ipw_prom_alloc(struct ipw_priv *priv) +{ + int rc = 0; + + if (priv->prom_net_dev) + return -EPERM; + + priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv)); + if (priv->prom_net_dev == NULL) + return -ENOMEM; + + priv->prom_priv = ieee80211_priv(priv->prom_net_dev); + priv->prom_priv->ieee = netdev_priv(priv->prom_net_dev); + priv->prom_priv->priv = priv; + + strcpy(priv->prom_net_dev->name, "rtap%d"); + + priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP; + priv->prom_net_dev->open = ipw_prom_open; + priv->prom_net_dev->stop = ipw_prom_stop; + priv->prom_net_dev->get_stats = ipw_prom_get_stats; + priv->prom_net_dev->hard_start_xmit = ipw_prom_hard_start_xmit; + + priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR; + + rc = register_netdev(priv->prom_net_dev); + if (rc) { + free_ieee80211(priv->prom_net_dev); + priv->prom_net_dev = NULL; + return rc; + } + + return 0; +} + +static void ipw_prom_free(struct ipw_priv *priv) +{ + if (!priv->prom_net_dev) + return; + + unregister_netdev(priv->prom_net_dev); + free_ieee80211(priv->prom_net_dev); + + priv->prom_net_dev = NULL; +} + +#endif + + static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = 0; @@ -10891,6 +11499,7 @@ static int ipw_pci_probe(struct pci_dev #ifdef CONFIG_IPW2200_DEBUG ipw_debug_level = debug; #endif + spin_lock_init(&priv->irq_lock); spin_lock_init(&priv->lock); for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); @@ -10959,11 +11568,12 @@ #endif priv->ieee->set_security = shim__set_security; priv->ieee->is_queue_full = ipw_net_is_queue_full; -#ifdef CONFIG_IPW_QOS +#ifdef CONFIG_IPW2200_QOS + priv->ieee->is_qos_active = ipw_is_qos_active; priv->ieee->handle_probe_response = ipw_handle_beacon; priv->ieee->handle_beacon = ipw_handle_probe_response; priv->ieee->handle_assoc_response = ipw_handle_assoc_response; -#endif /* CONFIG_IPW_QOS */ +#endif /* CONFIG_IPW2200_QOS */ priv->ieee->perfect_rssi = -20; priv->ieee->worst_rssi = -85; @@ -10997,6 +11607,18 @@ #endif /* CONFIG_IPW_QOS */ goto out_remove_sysfs; } +#ifdef CONFIG_IPW2200_PROMISCUOUS + if (rtap_iface) { + err = ipw_prom_alloc(priv); + if (err) { + IPW_ERROR("Failed to register promiscuous network " + "device (error %d).\n", err); + unregister_netdev(priv->net_dev); + goto out_remove_sysfs; + } + } +#endif + printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg " "channels, %d 802.11a channels)\n", priv->ieee->geo.name, priv->ieee->geo.bg_channels, @@ -11076,6 +11698,10 @@ static void ipw_pci_remove(struct pci_de priv->error = NULL; } +#ifdef CONFIG_IPW2200_PROMISCUOUS + ipw_prom_free(priv); +#endif + free_irq(pdev->irq, priv); iounmap(priv->hw_base); pci_release_regions(pdev); @@ -11200,7 +11826,12 @@ #endif module_param(channel, int, 0444); MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); -#ifdef CONFIG_IPW_QOS +#ifdef CONFIG_IPW2200_PROMISCUOUS +module_param(rtap_iface, int, 0444); +MODULE_PARM_DESC(rtap_iface, "create the rtap interface (1 - create, default 0)"); +#endif + +#ifdef CONFIG_IPW2200_QOS module_param(qos_enable, int, 0444); MODULE_PARM_DESC(qos_enable, "enable all QoS functionalitis"); @@ -11215,7 +11846,7 @@ MODULE_PARM_DESC(burst_duration_CCK, "se module_param(burst_duration_OFDM, int, 0444); MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value"); -#endif /* CONFIG_IPW_QOS */ +#endif /* CONFIG_IPW2200_QOS */ #ifdef CONFIG_IPW2200_MONITOR module_param(mode, int, 0444); @@ -11238,5 +11869,8 @@ MODULE_PARM_DESC(cmdlog, module_param(roaming, int, 0444); MODULE_PARM_DESC(roaming, "enable roaming support (default on)"); +module_param(antenna, int, 0444); +MODULE_PARM_DESC(antenna, "select antenna 1=Main, 3=Aux, default 0 [both], 2=slow_diversity (choose the one with lower background noise)"); + module_exit(ipw_exit); module_init(ipw_init); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 4b98049..ea12ad6 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -789,7 +789,7 @@ struct ipw_sys_config { u8 bt_coexist_collision_thr; u8 silence_threshold; u8 accept_all_mgmt_bcpr; - u8 accept_all_mgtm_frames; + u8 accept_all_mgmt_frames; u8 pass_noise_stats_to_host; u8 reserved3; } __attribute__ ((packed)); @@ -1122,17 +1122,70 @@ struct ipw_fw_error { u8 payload[0]; } __attribute__ ((packed)); +#ifdef CONFIG_IPW2200_PROMISCUOUS + +enum ipw_prom_filter { + IPW_PROM_CTL_HEADER_ONLY = (1 << 0), + IPW_PROM_MGMT_HEADER_ONLY = (1 << 1), + IPW_PROM_DATA_HEADER_ONLY = (1 << 2), + IPW_PROM_ALL_HEADER_ONLY = 0xf, /* bits 0..3 */ + IPW_PROM_NO_TX = (1 << 4), + IPW_PROM_NO_RX = (1 << 5), + IPW_PROM_NO_CTL = (1 << 6), + IPW_PROM_NO_MGMT = (1 << 7), + IPW_PROM_NO_DATA = (1 << 8), +}; + +struct ipw_priv; +struct ipw_prom_priv { + struct ipw_priv *priv; + struct ieee80211_device *ieee; + enum ipw_prom_filter filter; + int tx_packets; + int rx_packets; +}; +#endif + +#if defined(CONFIG_IPW2200_RADIOTAP) || defined(CONFIG_IPW2200_PROMISCUOUS) +/* Magic struct that slots into the radiotap header -- no reason + * to build this manually element by element, we can write it much + * more efficiently than we can parse it. ORDER MATTERS HERE + * + * When sent to us via the simulated Rx interface in sysfs, the entire + * structure is provided regardless of any bits unset. + */ +struct ipw_rt_hdr { + struct ieee80211_radiotap_header rt_hdr; + u64 rt_tsf; /* TSF */ + u8 rt_flags; /* radiotap packet flags */ + u8 rt_rate; /* rate in 500kb/s */ + u16 rt_channel; /* channel in mhz */ + u16 rt_chbitmask; /* channel bitfield */ + s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ + s8 rt_dbmnoise; + u8 rt_antenna; /* antenna number */ + u8 payload[0]; /* payload... */ +} __attribute__ ((packed)); +#endif + struct ipw_priv { /* ieee device used by generic ieee processing code */ struct ieee80211_device *ieee; spinlock_t lock; + spinlock_t irq_lock; struct mutex mutex; /* basic pci-network driver stuff */ struct pci_dev *pci_dev; struct net_device *net_dev; +#ifdef CONFIG_IPW2200_PROMISCUOUS + /* Promiscuous mode */ + struct ipw_prom_priv *prom_priv; + struct net_device *prom_net_dev; +#endif + /* pci hardware address support */ void __iomem *hw_base; unsigned long hw_len; @@ -1153,11 +1206,9 @@ struct ipw_priv { u32 config; u32 capability; - u8 last_rx_rssi; - u8 last_noise; struct average average_missed_beacons; - struct average average_rssi; - struct average average_noise; + s16 exp_avg_rssi; + s16 exp_avg_noise; u32 port_type; int rx_bufs_min; /**< minimum number of bufs in Rx queue */ int rx_pend_max; /**< maximum pending buffers for one IRQ */ @@ -1308,6 +1359,29 @@ #endif /* debug macros */ +/* Debug and printf string expansion helpers for printing bitfields */ +#define BIT_FMT8 "%c%c%c%c-%c%c%c%c" +#define BIT_FMT16 BIT_FMT8 ":" BIT_FMT8 +#define BIT_FMT32 BIT_FMT16 " " BIT_FMT16 + +#define BITC(x,y) (((x>>y)&1)?'1':'0') +#define BIT_ARG8(x) \ +BITC(x,7),BITC(x,6),BITC(x,5),BITC(x,4),\ +BITC(x,3),BITC(x,2),BITC(x,1),BITC(x,0) + +#define BIT_ARG16(x) \ +BITC(x,15),BITC(x,14),BITC(x,13),BITC(x,12),\ +BITC(x,11),BITC(x,10),BITC(x,9),BITC(x,8),\ +BIT_ARG8(x) + +#define BIT_ARG32(x) \ +BITC(x,31),BITC(x,30),BITC(x,29),BITC(x,28),\ +BITC(x,27),BITC(x,26),BITC(x,25),BITC(x,24),\ +BITC(x,23),BITC(x,22),BITC(x,21),BITC(x,20),\ +BITC(x,19),BITC(x,18),BITC(x,17),BITC(x,16),\ +BIT_ARG16(x) + + #ifdef CONFIG_IPW2200_DEBUG #define IPW_DEBUG(level, fmt, args...) \ do { if (ipw_debug_level & (level)) \ diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index c2d0b09..8a31b59 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -201,41 +201,12 @@ #define BITRATE_TABLE_SIZE ARRAY_SIZE(bi /* Data types */ /********************************************************************/ -/* Used in Event handling. - * We avoid nested structures as they break on ARM -- Moustafa */ -struct hermes_tx_descriptor_802_11 { - /* hermes_tx_descriptor */ - __le16 status; - __le16 reserved1; - __le16 reserved2; - __le32 sw_support; - u8 retry_count; - u8 tx_rate; - __le16 tx_control; - - /* ieee80211_hdr */ +/* Beginning of the Tx descriptor, used in TxExc handling */ +struct hermes_txexc_data { + struct hermes_tx_descriptor desc; __le16 frame_ctl; __le16 duration_id; u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctl; - u8 addr4[ETH_ALEN]; - - __le16 data_len; - - /* ethhdr */ - u8 h_dest[ETH_ALEN]; /* destination eth addr */ - u8 h_source[ETH_ALEN]; /* source ether addr */ - __be16 h_proto; /* packet type ID field */ - - /* p8022_hdr */ - u8 dsap; - u8 ssap; - u8 ctrl; - u8 oui[3]; - - __be16 ethertype; } __attribute__ ((packed)); /* Rx frame header except compatibility 802.3 header */ @@ -450,53 +421,39 @@ static int orinoco_xmit(struct sk_buff * hermes_t *hw = &priv->hw; int err = 0; u16 txfid = priv->txfid; - char *p; struct ethhdr *eh; - int len, data_len, data_off; + int data_off; struct hermes_tx_descriptor desc; unsigned long flags; - TRACE_ENTER(dev->name); - if (! netif_running(dev)) { printk(KERN_ERR "%s: Tx on stopped device!\n", dev->name); - TRACE_EXIT(dev->name); - return 1; + return NETDEV_TX_BUSY; } if (netif_queue_stopped(dev)) { printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", dev->name); - TRACE_EXIT(dev->name); - return 1; + return NETDEV_TX_BUSY; } if (orinoco_lock(priv, &flags) != 0) { printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n", dev->name); - TRACE_EXIT(dev->name); - return 1; + return NETDEV_TX_BUSY; } if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) { /* Oops, the firmware hasn't established a connection, silently drop the packet (this seems to be the safest approach). */ - stats->tx_errors++; - orinoco_unlock(priv, &flags); - dev_kfree_skb(skb); - TRACE_EXIT(dev->name); - return 0; + goto drop; } - /* Length of the packet body */ - /* FIXME: what if the skb is smaller than this? */ - len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN); - skb = skb_padto(skb, len); - if (skb == NULL) - goto fail; - len -= ETH_HLEN; + /* Check packet length */ + if (skb->len < ETH_HLEN) + goto drop; eh = (struct ethhdr *)skb->data; @@ -507,8 +464,7 @@ static int orinoco_xmit(struct sk_buff * if (net_ratelimit()) printk(KERN_ERR "%s: Error %d writing Tx descriptor " "to BAP\n", dev->name, err); - stats->tx_errors++; - goto fail; + goto busy; } /* Clear the 802.11 header and data length fields - some @@ -519,50 +475,38 @@ static int orinoco_xmit(struct sk_buff * /* Encapsulate Ethernet-II frames */ if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ - struct header_struct hdr; - data_len = len; - data_off = HERMES_802_3_OFFSET + sizeof(hdr); - p = skb->data + ETH_HLEN; - - /* 802.3 header */ - memcpy(hdr.dest, eh->h_dest, ETH_ALEN); - memcpy(hdr.src, eh->h_source, ETH_ALEN); - hdr.len = htons(data_len + ENCAPS_OVERHEAD); - - /* 802.2 header */ - memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr)); - - hdr.ethertype = eh->h_proto; - err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), - txfid, HERMES_802_3_OFFSET); + struct header_struct { + struct ethhdr eth; /* 802.3 header */ + u8 encap[6]; /* 802.2 header */ + } __attribute__ ((packed)) hdr; + + /* Strip destination and source from the data */ + skb_pull(skb, 2 * ETH_ALEN); + data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr); + + /* And move them to a separate header */ + memcpy(&hdr.eth, eh, 2 * ETH_ALEN); + hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len); + memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); + + err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), + txfid, HERMES_802_3_OFFSET); if (err) { if (net_ratelimit()) printk(KERN_ERR "%s: Error %d writing packet " "header to BAP\n", dev->name, err); - stats->tx_errors++; - goto fail; + goto busy; } - /* Actual xfer length - allow for padding */ - len = ALIGN(data_len, 2); - if (len < ETH_ZLEN - ETH_HLEN) - len = ETH_ZLEN - ETH_HLEN; } else { /* IEEE 802.3 frame */ - data_len = len + ETH_HLEN; data_off = HERMES_802_3_OFFSET; - p = skb->data; - /* Actual xfer length - round up for odd length packets */ - len = ALIGN(data_len, 2); - if (len < ETH_ZLEN) - len = ETH_ZLEN; } - err = hermes_bap_pwrite_pad(hw, USER_BAP, p, data_len, len, + err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len, txfid, data_off); if (err) { printk(KERN_ERR "%s: Error %d writing packet to BAP\n", dev->name, err); - stats->tx_errors++; - goto fail; + goto busy; } /* Finally, we actually initiate the send */ @@ -575,25 +519,27 @@ static int orinoco_xmit(struct sk_buff * if (net_ratelimit()) printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err); - stats->tx_errors++; - goto fail; + goto busy; } dev->trans_start = jiffies; - stats->tx_bytes += data_off + data_len; + stats->tx_bytes += data_off + skb->len; + goto ok; - orinoco_unlock(priv, &flags); + drop: + stats->tx_errors++; + stats->tx_dropped++; + ok: + orinoco_unlock(priv, &flags); dev_kfree_skb(skb); + return NETDEV_TX_OK; - TRACE_EXIT(dev->name); - - return 0; - fail: - TRACE_EXIT(dev->name); - + busy: + if (err == -EIO) + schedule_work(&priv->reset_work); orinoco_unlock(priv, &flags); - return err; + return NETDEV_TX_BUSY; } static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw) @@ -629,7 +575,7 @@ static void __orinoco_ev_txexc(struct ne struct net_device_stats *stats = &priv->stats; u16 fid = hermes_read_regn(hw, TXCOMPLFID); u16 status; - struct hermes_tx_descriptor_802_11 hdr; + struct hermes_txexc_data hdr; int err = 0; if (fid == DUMMY_FID) @@ -637,8 +583,7 @@ static void __orinoco_ev_txexc(struct ne /* Read part of the frame header - we need status and addr1 */ err = hermes_bap_pread(hw, IRQ_BAP, &hdr, - offsetof(struct hermes_tx_descriptor_802_11, - addr2), + sizeof(struct hermes_txexc_data), fid, 0); hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); @@ -658,7 +603,7 @@ static void __orinoco_ev_txexc(struct ne * exceeded, because that's the only status that really mean * that this particular node went away. * Other errors means that *we* screwed up. - Jean II */ - status = le16_to_cpu(hdr.status); + status = le16_to_cpu(hdr.desc.status); if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { union iwreq_data wrqu; @@ -1398,16 +1343,12 @@ int __orinoco_down(struct net_device *de return 0; } -int orinoco_reinit_firmware(struct net_device *dev) +static int orinoco_allocate_fid(struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); struct hermes *hw = &priv->hw; int err; - err = hermes_init(hw); - if (err) - return err; - err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) { /* Try workaround for old Symbol firmware bug */ @@ -1426,6 +1367,19 @@ int orinoco_reinit_firmware(struct net_d return err; } +int orinoco_reinit_firmware(struct net_device *dev) +{ + struct orinoco_private *priv = netdev_priv(dev); + struct hermes *hw = &priv->hw; + int err; + + err = hermes_init(hw); + if (!err) + err = orinoco_allocate_fid(dev); + + return err; +} + static int __orinoco_hw_set_bitrate(struct orinoco_private *priv) { hermes_t *hw = &priv->hw; @@ -1833,7 +1787,9 @@ static int __orinoco_program_rids(struct /* Set promiscuity / multicast*/ priv->promiscuous = 0; priv->mc_count = 0; - __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */ + + /* FIXME: what about netif_tx_lock */ + __orinoco_set_multicast_list(dev); return 0; } @@ -2272,14 +2228,12 @@ static int orinoco_init(struct net_devic u16 reclen; int len; - TRACE_ENTER(dev->name); - /* No need to lock, the hw_unavailable flag is already set in * alloc_orinocodev() */ priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN; /* Initialize the firmware */ - err = orinoco_reinit_firmware(dev); + err = hermes_init(hw); if (err != 0) { printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n", dev->name, err); @@ -2337,6 +2291,13 @@ static int orinoco_init(struct net_devic printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick); + err = orinoco_allocate_fid(dev); + if (err) { + printk(KERN_ERR "%s: failed to allocate NIC buffer!\n", + dev->name); + goto out; + } + /* Get allowed channels */ err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST, &priv->channel_mask); @@ -2427,7 +2388,6 @@ static int orinoco_init(struct net_devic printk(KERN_DEBUG "%s: ready\n", dev->name); out: - TRACE_EXIT(dev->name); return err; } @@ -2795,8 +2755,6 @@ static int orinoco_ioctl_getiwrange(stru int numrates; int i, k; - TRACE_ENTER(dev->name); - rrq->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); @@ -2886,8 +2844,6 @@ static int orinoco_ioctl_getiwrange(stru IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); - TRACE_EXIT(dev->name); - return 0; } @@ -3069,8 +3025,6 @@ static int orinoco_ioctl_getessid(struct int err = 0; unsigned long flags; - TRACE_ENTER(dev->name); - if (netif_running(dev)) { err = orinoco_hw_get_essid(priv, &active, essidbuf); if (err) @@ -3085,8 +3039,6 @@ static int orinoco_ioctl_getessid(struct erq->flags = 1; erq->length = strlen(essidbuf) + 1; - TRACE_EXIT(dev->name); - return 0; } @@ -4347,69 +4299,6 @@ static struct ethtool_ops orinoco_ethtoo }; /********************************************************************/ -/* Debugging */ -/********************************************************************/ - -#if 0 -static void show_rx_frame(struct orinoco_rxframe_hdr *frame) -{ - printk(KERN_DEBUG "RX descriptor:\n"); - printk(KERN_DEBUG " status = 0x%04x\n", frame->desc.status); - printk(KERN_DEBUG " time = 0x%08x\n", frame->desc.time); - printk(KERN_DEBUG " silence = 0x%02x\n", frame->desc.silence); - printk(KERN_DEBUG " signal = 0x%02x\n", frame->desc.signal); - printk(KERN_DEBUG " rate = 0x%02x\n", frame->desc.rate); - printk(KERN_DEBUG " rxflow = 0x%02x\n", frame->desc.rxflow); - printk(KERN_DEBUG " reserved = 0x%08x\n", frame->desc.reserved); - - printk(KERN_DEBUG "IEEE 802.11 header:\n"); - printk(KERN_DEBUG " frame_ctl = 0x%04x\n", - frame->p80211.frame_ctl); - printk(KERN_DEBUG " duration_id = 0x%04x\n", - frame->p80211.duration_id); - printk(KERN_DEBUG " addr1 = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p80211.addr1[0], frame->p80211.addr1[1], - frame->p80211.addr1[2], frame->p80211.addr1[3], - frame->p80211.addr1[4], frame->p80211.addr1[5]); - printk(KERN_DEBUG " addr2 = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p80211.addr2[0], frame->p80211.addr2[1], - frame->p80211.addr2[2], frame->p80211.addr2[3], - frame->p80211.addr2[4], frame->p80211.addr2[5]); - printk(KERN_DEBUG " addr3 = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p80211.addr3[0], frame->p80211.addr3[1], - frame->p80211.addr3[2], frame->p80211.addr3[3], - frame->p80211.addr3[4], frame->p80211.addr3[5]); - printk(KERN_DEBUG " seq_ctl = 0x%04x\n", - frame->p80211.seq_ctl); - printk(KERN_DEBUG " addr4 = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p80211.addr4[0], frame->p80211.addr4[1], - frame->p80211.addr4[2], frame->p80211.addr4[3], - frame->p80211.addr4[4], frame->p80211.addr4[5]); - printk(KERN_DEBUG " data_len = 0x%04x\n", - frame->p80211.data_len); - - printk(KERN_DEBUG "IEEE 802.3 header:\n"); - printk(KERN_DEBUG " dest = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p8023.h_dest[0], frame->p8023.h_dest[1], - frame->p8023.h_dest[2], frame->p8023.h_dest[3], - frame->p8023.h_dest[4], frame->p8023.h_dest[5]); - printk(KERN_DEBUG " src = %02x:%02x:%02x:%02x:%02x:%02x\n", - frame->p8023.h_source[0], frame->p8023.h_source[1], - frame->p8023.h_source[2], frame->p8023.h_source[3], - frame->p8023.h_source[4], frame->p8023.h_source[5]); - printk(KERN_DEBUG " len = 0x%04x\n", frame->p8023.h_proto); - - printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n"); - printk(KERN_DEBUG " DSAP = 0x%02x\n", frame->p8022.dsap); - printk(KERN_DEBUG " SSAP = 0x%02x\n", frame->p8022.ssap); - printk(KERN_DEBUG " ctrl = 0x%02x\n", frame->p8022.ctrl); - printk(KERN_DEBUG " OUI = %02x:%02x:%02x\n", - frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]); - printk(KERN_DEBUG " ethertype = 0x%04x\n", frame->ethertype); -} -#endif /* 0 */ - -/********************************************************************/ /* Module initialization */ /********************************************************************/ diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h index f5d856d..16db3e1 100644 --- a/drivers/net/wireless/orinoco.h +++ b/drivers/net/wireless/orinoco.h @@ -7,7 +7,7 @@ #ifndef _ORINOCO_H #define _ORINOCO_H -#define DRIVER_VERSION "0.15rc3" +#define DRIVER_VERSION "0.15" #include #include @@ -30,20 +30,6 @@ struct orinoco_key { char data[ORINOCO_MAX_KEY_SIZE]; } __attribute__ ((packed)); -struct header_struct { - /* 802.3 */ - u8 dest[ETH_ALEN]; - u8 src[ETH_ALEN]; - __be16 len; - /* 802.2 */ - u8 dsap; - u8 ssap; - u8 ctrl; - /* SNAP */ - u8 oui[3]; - unsigned short ethertype; -} __attribute__ ((packed)); - typedef enum { FIRMWARE_TYPE_AGERE, FIRMWARE_TYPE_INTERSIL, @@ -132,9 +118,6 @@ #else #define DEBUG(n, args...) do { } while (0) #endif /* ORINOCO_DEBUG */ -#define TRACE_ENTER(devname) DEBUG(2, "%s: -> %s()\n", devname, __FUNCTION__); -#define TRACE_EXIT(devname) DEBUG(2, "%s: <- %s()\n", devname, __FUNCTION__); - /********************************************************************/ /* Exported prototypes */ /********************************************************************/ diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 434f7d7..b2aec4d 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -147,14 +147,11 @@ static void orinoco_cs_detach(struct pcm { struct net_device *dev = link->priv; + if (link->dev_node) + unregister_netdev(dev); + orinoco_cs_release(link); - DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); - if (link->dev_node) { - DEBUG(0, PFX "About to unregister net device %p\n", - dev); - unregister_netdev(dev); - } free_orinocodev(dev); } /* orinoco_cs_detach */ @@ -178,13 +175,10 @@ orinoco_cs_config(struct pcmcia_device * int last_fn, last_ret; u_char buf[64]; config_info_t conf; - cisinfo_t info; tuple_t tuple; cisparse_t parse; void __iomem *mem; - CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info)); - /* * This reads the card's CONFIG tuple to find its * configuration registers. @@ -234,12 +228,6 @@ orinoco_cs_config(struct pcmcia_device * goto next_entry; link->conf.ConfigIndex = cfg->index; - /* Does this card need audio output? */ - if (cfg->flags & CISTPL_CFTABLE_AUDIO) { - link->conf.Attributes |= CONF_ENABLE_SPKR; - link->conf.Status = CCSR_AUDIO_ENA; - } - /* Use power settings for Vcc and Vpp if present */ /* Note that the CIS values need to be rescaled */ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { @@ -355,19 +343,10 @@ orinoco_cs_config(struct pcmcia_device * net_device has been registered */ /* Finally, report what we've done */ - printk(KERN_DEBUG "%s: index 0x%02x: ", - dev->name, link->conf.ConfigIndex); - if (link->conf.Vpp) - printk(", Vpp %d.%d", link->conf.Vpp / 10, - link->conf.Vpp % 10); - printk(", irq %d", link->irq.AssignedIRQ); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1 + link->io.NumPorts1 - 1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2 + link->io.NumPorts2 - 1); - printk("\n"); + printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io " + "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id, + link->irq.AssignedIRQ, link->io.BasePort1, + link->io.BasePort1 + link->io.NumPorts1 - 1); return 0; @@ -436,7 +415,6 @@ static int orinoco_cs_resume(struct pcmc struct orinoco_private *priv = netdev_priv(dev); struct orinoco_pccard *card = priv->card; int err = 0; - unsigned long flags; if (! test_bit(0, &card->hard_reset_in_progress)) { err = orinoco_reinit_firmware(dev); @@ -446,7 +424,7 @@ static int orinoco_cs_resume(struct pcmc return -EIO; } - spin_lock_irqsave(&priv->lock, flags); + spin_lock(&priv->lock); netif_device_attach(dev); priv->hw_unavailable--; @@ -458,10 +436,10 @@ static int orinoco_cs_resume(struct pcmc dev->name, err); } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock(&priv->lock); } - return 0; + return err; } diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c index d1a670b..74b9d5b 100644 --- a/drivers/net/wireless/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco_nortel.c @@ -1,9 +1,8 @@ /* orinoco_nortel.c - * + * * Driver for Prism II devices which would usually be driven by orinoco_cs, * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in * Nortel emobility, Symbol LA-4113 and Symbol LA-4123. - * but are connected to the PCI bus by a Nortel PCI-PCMCIA-Adapter. * * Copyright (C) 2002 Tobias Hoffmann * (C) 2003 Christoph Jungegger @@ -50,67 +49,62 @@ #include #include #include "orinoco.h" +#include "orinoco_pci.h" #define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */ #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ -/* Nortel specific data */ -struct nortel_pci_card { - unsigned long iobase1; - unsigned long iobase2; -}; - /* - * Do a soft reset of the PCI card using the Configuration Option Register + * Do a soft reset of the card using the Configuration Option Register * We need this to get going... * This is the part of the code that is strongly inspired from wlan-ng * * Note bis : Don't try to access HERMES_CMD during the reset phase. * It just won't work ! */ -static int nortel_pci_cor_reset(struct orinoco_private *priv) +static int orinoco_nortel_cor_reset(struct orinoco_private *priv) { - struct nortel_pci_card *card = priv->card; + struct orinoco_pci_card *card = priv->card; - /* Assert the reset until the card notice */ - outw_p(8, card->iobase1 + 2); - inw(card->iobase2 + COR_OFFSET); - outw_p(0x80, card->iobase2 + COR_OFFSET); + /* Assert the reset until the card notices */ + iowrite16(8, card->bridge_io + 2); + ioread16(card->attr_io + COR_OFFSET); + iowrite16(0x80, card->attr_io + COR_OFFSET); mdelay(1); /* Give time for the card to recover from this hard effort */ - outw_p(0, card->iobase2 + COR_OFFSET); - outw_p(0, card->iobase2 + COR_OFFSET); + iowrite16(0, card->attr_io + COR_OFFSET); + iowrite16(0, card->attr_io + COR_OFFSET); mdelay(1); - /* set COR as usual */ - outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); - outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); + /* Set COR as usual */ + iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); + iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); mdelay(1); - outw_p(0x228, card->iobase1 + 2); + iowrite16(0x228, card->bridge_io + 2); return 0; } -static int nortel_pci_hw_init(struct nortel_pci_card *card) +static int orinoco_nortel_hw_init(struct orinoco_pci_card *card) { int i; u32 reg; - /* setup bridge */ - if (inw(card->iobase1) & 1) { + /* Setup bridge */ + if (ioread16(card->bridge_io) & 1) { printk(KERN_ERR PFX "brg1 answer1 wrong\n"); return -EBUSY; } - outw_p(0x118, card->iobase1 + 2); - outw_p(0x108, card->iobase1 + 2); + iowrite16(0x118, card->bridge_io + 2); + iowrite16(0x108, card->bridge_io + 2); mdelay(30); - outw_p(0x8, card->iobase1 + 2); + iowrite16(0x8, card->bridge_io + 2); for (i = 0; i < 30; i++) { mdelay(30); - if (inw(card->iobase1) & 0x10) { + if (ioread16(card->bridge_io) & 0x10) { break; } } @@ -118,42 +112,42 @@ static int nortel_pci_hw_init(struct nor printk(KERN_ERR PFX "brg1 timed out\n"); return -EBUSY; } - if (inw(card->iobase2 + 0xe0) & 1) { + if (ioread16(card->attr_io + COR_OFFSET) & 1) { printk(KERN_ERR PFX "brg2 answer1 wrong\n"); return -EBUSY; } - if (inw(card->iobase2 + 0xe2) & 1) { + if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) { printk(KERN_ERR PFX "brg2 answer2 wrong\n"); return -EBUSY; } - if (inw(card->iobase2 + 0xe4) & 1) { + if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) { printk(KERN_ERR PFX "brg2 answer3 wrong\n"); return -EBUSY; } - /* set the PCMCIA COR-Register */ - outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); + /* Set the PCMCIA COR register */ + iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); mdelay(1); - reg = inw(card->iobase2 + COR_OFFSET); + reg = ioread16(card->attr_io + COR_OFFSET); if (reg != COR_VALUE) { printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n", reg); return -EBUSY; } - /* set leds */ - outw_p(1, card->iobase1 + 10); + /* Set LEDs */ + iowrite16(1, card->bridge_io + 10); return 0; } -static int nortel_pci_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int orinoco_nortel_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { int err; struct orinoco_private *priv; - struct nortel_pci_card *card; + struct orinoco_pci_card *card; struct net_device *dev; - void __iomem *iomem; + void __iomem *hermes_io, *bridge_io, *attr_io; err = pci_enable_device(pdev); if (err) { @@ -162,19 +156,34 @@ static int nortel_pci_init_one(struct pc } err = pci_request_regions(pdev, DRIVER_NAME); - if (err != 0) { + if (err) { printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); goto fail_resources; } - iomem = pci_iomap(pdev, 2, 0); - if (!iomem) { - err = -ENOMEM; - goto fail_map_io; + bridge_io = pci_iomap(pdev, 0, 0); + if (!bridge_io) { + printk(KERN_ERR PFX "Cannot map bridge registers\n"); + err = -EIO; + goto fail_map_bridge; + } + + attr_io = pci_iomap(pdev, 1, 0); + if (!attr_io) { + printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n"); + err = -EIO; + goto fail_map_attr; + } + + hermes_io = pci_iomap(pdev, 2, 0); + if (!hermes_io) { + printk(KERN_ERR PFX "Cannot map chipset registers\n"); + err = -EIO; + goto fail_map_hermes; } /* Allocate network device */ - dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset); + dev = alloc_orinocodev(sizeof(*card), orinoco_nortel_cor_reset); if (!dev) { printk(KERN_ERR PFX "Cannot allocate network device\n"); err = -ENOMEM; @@ -183,16 +192,12 @@ static int nortel_pci_init_one(struct pc priv = netdev_priv(dev); card = priv->card; - card->iobase1 = pci_resource_start(pdev, 0); - card->iobase2 = pci_resource_start(pdev, 1); - dev->base_addr = pci_resource_start(pdev, 2); + card->bridge_io = bridge_io; + card->attr_io = attr_io; SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING); - - printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, " - "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr); + hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, dev); @@ -201,21 +206,19 @@ static int nortel_pci_init_one(struct pc err = -EBUSY; goto fail_irq; } - dev->irq = pdev->irq; - err = nortel_pci_hw_init(card); + err = orinoco_nortel_hw_init(card); if (err) { printk(KERN_ERR PFX "Hardware initialization failed\n"); goto fail; } - err = nortel_pci_cor_reset(priv); + err = orinoco_nortel_cor_reset(priv); if (err) { printk(KERN_ERR PFX "Initial reset failed\n"); goto fail; } - err = register_netdev(dev); if (err) { printk(KERN_ERR PFX "Cannot register network device\n"); @@ -223,6 +226,8 @@ static int nortel_pci_init_one(struct pc } pci_set_drvdata(pdev, dev); + printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name, + pci_name(pdev)); return 0; @@ -234,9 +239,15 @@ static int nortel_pci_init_one(struct pc free_orinocodev(dev); fail_alloc: - pci_iounmap(pdev, iomem); + pci_iounmap(pdev, hermes_io); - fail_map_io: + fail_map_hermes: + pci_iounmap(pdev, attr_io); + + fail_map_attr: + pci_iounmap(pdev, bridge_io); + + fail_map_bridge: pci_release_regions(pdev); fail_resources: @@ -245,26 +256,27 @@ static int nortel_pci_init_one(struct pc return err; } -static void __devexit nortel_pci_remove_one(struct pci_dev *pdev) +static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct orinoco_private *priv = netdev_priv(dev); - struct nortel_pci_card *card = priv->card; + struct orinoco_pci_card *card = priv->card; - /* clear leds */ - outw_p(0, card->iobase1 + 10); + /* Clear LEDs */ + iowrite16(0, card->bridge_io + 10); unregister_netdev(dev); - free_irq(dev->irq, dev); + free_irq(pdev->irq, dev); pci_set_drvdata(pdev, NULL); free_orinocodev(dev); pci_iounmap(pdev, priv->hw.iobase); + pci_iounmap(pdev, card->attr_io); + pci_iounmap(pdev, card->bridge_io); pci_release_regions(pdev); pci_disable_device(pdev); } - -static struct pci_device_id nortel_pci_id_table[] = { +static struct pci_device_id orinoco_nortel_id_table[] = { /* Nortel emobility PCI */ {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, /* Symbol LA-4123 PCI */ @@ -272,13 +284,15 @@ static struct pci_device_id nortel_pci_i {0,}, }; -MODULE_DEVICE_TABLE(pci, nortel_pci_id_table); +MODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table); -static struct pci_driver nortel_pci_driver = { - .name = DRIVER_NAME, - .id_table = nortel_pci_id_table, - .probe = nortel_pci_init_one, - .remove = __devexit_p(nortel_pci_remove_one), +static struct pci_driver orinoco_nortel_driver = { + .name = DRIVER_NAME, + .id_table = orinoco_nortel_id_table, + .probe = orinoco_nortel_init_one, + .remove = __devexit_p(orinoco_nortel_remove_one), + .suspend = orinoco_pci_suspend, + .resume = orinoco_pci_resume, }; static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION @@ -288,20 +302,19 @@ MODULE_DESCRIPTION ("Driver for wireless LAN cards using the Nortel PCI bridge"); MODULE_LICENSE("Dual MPL/GPL"); -static int __init nortel_pci_init(void) +static int __init orinoco_nortel_init(void) { printk(KERN_DEBUG "%s\n", version); - return pci_module_init(&nortel_pci_driver); + return pci_module_init(&orinoco_nortel_driver); } -static void __exit nortel_pci_exit(void) +static void __exit orinoco_nortel_exit(void) { - pci_unregister_driver(&nortel_pci_driver); - ssleep(1); + pci_unregister_driver(&orinoco_nortel_driver); } -module_init(nortel_pci_init); -module_exit(nortel_pci_exit); +module_init(orinoco_nortel_init); +module_exit(orinoco_nortel_exit); /* * Local variables: diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c index 5362c21..1c105f4 100644 --- a/drivers/net/wireless/orinoco_pci.c +++ b/drivers/net/wireless/orinoco_pci.c @@ -1,11 +1,11 @@ /* orinoco_pci.c * - * Driver for Prism II devices that have a direct PCI interface - * (i.e., not in a Pcmcia or PLX bridge) - * - * Specifically here we're talking about the Linksys WMP11 + * Driver for Prism 2.5/3 devices that have a direct PCI interface + * (i.e. these are not PCMCIA cards in a PCMCIA-to-PCI bridge). + * The card contains only one PCI region, which contains all the usual + * hermes registers, as well as the COR register. * - * Current maintainers (as of 29 September 2003) are: + * Current maintainers are: * Pavel Roskin * and David Gibson * @@ -41,54 +41,6 @@ * under either the MPL or the GPL. */ -/* - * Theory of operation... - * ------------------- - * Maybe you had a look in orinoco_plx. Well, this is totally different... - * - * The card contains only one PCI region, which contains all the usual - * hermes registers. - * - * The driver will memory map this region in normal memory. Because - * the hermes registers are mapped in normal memory and not in ISA I/O - * post space, we can't use the usual inw/outw macros and we need to - * use readw/writew. - * This slight difference force us to compile our own version of - * hermes.c with the register access macro changed. That's a bit - * hackish but works fine. - * - * Note that the PCI region is pretty big (4K). That's much more than - * the usual set of hermes register (0x0 -> 0x3E). I've got a strong - * suspicion that the whole memory space of the adapter is in fact in - * this region. Accessing directly the adapter memory instead of going - * through the usual register would speed up significantely the - * operations... - * - * Finally, the card looks like this : ------------------------ - Bus 0, device 14, function 0: - Network controller: PCI device 1260:3873 (Harris Semiconductor) (rev 1). - IRQ 11. - Master Capable. Latency=248. - Prefetchable 32 bit memory at 0xffbcc000 [0xffbccfff]. ------------------------ -00:0e.0 Network controller: Harris Semiconductor: Unknown device 3873 (rev 01) - Subsystem: Unknown device 1737:3874 - Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- - Status: Cap+ 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- SERR- #include #include "orinoco.h" +#include "orinoco_pci.h" -/* All the magic there is from wlan-ng */ -/* Magic offset of the reset register of the PCI card */ +/* Offset of the COR register of the PCI card */ #define HERMES_PCI_COR (0x26) -/* Magic bitmask to reset the card */ + +/* Bitmask to reset the card */ #define HERMES_PCI_COR_MASK (0x0080) + /* Magic timeouts for doing the reset. * Those times are straight from wlan-ng, and it is claimed that they * are necessary. Alan will kill me. Take your time and grab a coffee. */ @@ -113,13 +67,8 @@ #define HERMES_PCI_COR_ONT (250) /* ms #define HERMES_PCI_COR_OFFT (500) /* ms */ #define HERMES_PCI_COR_BUSYT (500) /* ms */ -/* Orinoco PCI specific data */ -struct orinoco_pci_card { - void __iomem *pci_ioaddr; -}; - /* - * Do a soft reset of the PCI card using the Configuration Option Register + * Do a soft reset of the card using the Configuration Option Register * We need this to get going... * This is the part of the code that is strongly inspired from wlan-ng * @@ -131,14 +80,13 @@ struct orinoco_pci_card { * Note bis : Don't try to access HERMES_CMD during the reset phase. * It just won't work ! */ -static int -orinoco_pci_cor_reset(struct orinoco_private *priv) +static int orinoco_pci_cor_reset(struct orinoco_private *priv) { hermes_t *hw = &priv->hw; - unsigned long timeout; - u16 reg; + unsigned long timeout; + u16 reg; - /* Assert the reset until the card notice */ + /* Assert the reset until the card notices */ hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK); mdelay(HERMES_PCI_COR_ONT); @@ -163,19 +111,14 @@ orinoco_pci_cor_reset(struct orinoco_pri return 0; } -/* - * Initialise a card. Mostly similar to PLX code. - */ static int orinoco_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - int err = 0; - unsigned long pci_iorange; - u16 __iomem *pci_ioaddr = NULL; - unsigned long pci_iolen; - struct orinoco_private *priv = NULL; + int err; + struct orinoco_private *priv; struct orinoco_pci_card *card; - struct net_device *dev = NULL; + struct net_device *dev; + void __iomem *hermes_io; err = pci_enable_device(pdev); if (err) { @@ -184,39 +127,32 @@ static int orinoco_pci_init_one(struct p } err = pci_request_regions(pdev, DRIVER_NAME); - if (err != 0) { + if (err) { printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); goto fail_resources; } - /* Resource 0 is mapped to the hermes registers */ - pci_iorange = pci_resource_start(pdev, 0); - pci_iolen = pci_resource_len(pdev, 0); - pci_ioaddr = ioremap(pci_iorange, pci_iolen); - if (!pci_iorange) { - printk(KERN_ERR PFX "Cannot remap hardware registers\n"); - goto fail_map; + hermes_io = pci_iomap(pdev, 0, 0); + if (!hermes_io) { + printk(KERN_ERR PFX "Cannot remap chipset registers\n"); + err = -EIO; + goto fail_map_hermes; } /* Allocate network device */ dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset); - if (! dev) { + if (!dev) { + printk(KERN_ERR PFX "Cannot allocate network device\n"); err = -ENOMEM; goto fail_alloc; } priv = netdev_priv(dev); card = priv->card; - card->pci_ioaddr = pci_ioaddr; - dev->mem_start = pci_iorange; - dev->mem_end = pci_iorange + pci_iolen - 1; SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - hermes_struct_init(&priv->hw, pci_ioaddr, HERMES_32BIT_REGSPACING); - - printk(KERN_DEBUG PFX "Detected device %s, mem:0x%lx-0x%lx, irq %d\n", - pci_name(pdev), dev->mem_start, dev->mem_end, pdev->irq); + hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING); err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, dev); @@ -225,9 +161,7 @@ static int orinoco_pci_init_one(struct p err = -EBUSY; goto fail_irq; } - dev->irq = pdev->irq; - /* Perform a COR reset to start the card */ err = orinoco_pci_cor_reset(priv); if (err) { printk(KERN_ERR PFX "Initial reset failed\n"); @@ -236,11 +170,13 @@ static int orinoco_pci_init_one(struct p err = register_netdev(dev); if (err) { - printk(KERN_ERR PFX "Failed to register net device\n"); + printk(KERN_ERR PFX "Cannot register network device\n"); goto fail; } pci_set_drvdata(pdev, dev); + printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name, + pci_name(pdev)); return 0; @@ -252,9 +188,9 @@ static int orinoco_pci_init_one(struct p free_orinocodev(dev); fail_alloc: - iounmap(pci_ioaddr); + pci_iounmap(pdev, hermes_io); - fail_map: + fail_map_hermes: pci_release_regions(pdev); fail_resources: @@ -267,87 +203,17 @@ static void __devexit orinoco_pci_remove { struct net_device *dev = pci_get_drvdata(pdev); struct orinoco_private *priv = netdev_priv(dev); - struct orinoco_pci_card *card = priv->card; unregister_netdev(dev); - free_irq(dev->irq, dev); + free_irq(pdev->irq, dev); pci_set_drvdata(pdev, NULL); free_orinocodev(dev); - iounmap(card->pci_ioaddr); + pci_iounmap(pdev, priv->hw.iobase); pci_release_regions(pdev); pci_disable_device(pdev); } -static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct orinoco_private *priv = netdev_priv(dev); - unsigned long flags; - int err; - - - err = orinoco_lock(priv, &flags); - if (err) { - printk(KERN_ERR "%s: hw_unavailable on orinoco_pci_suspend\n", - dev->name); - return err; - } - - err = __orinoco_down(dev); - if (err) - printk(KERN_WARNING "%s: orinoco_pci_suspend(): Error %d downing interface\n", - dev->name, err); - - netif_device_detach(dev); - - priv->hw_unavailable++; - - orinoco_unlock(priv, &flags); - - pci_save_state(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int orinoco_pci_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct orinoco_private *priv = netdev_priv(dev); - unsigned long flags; - int err; - - printk(KERN_DEBUG "%s: Orinoco-PCI waking up\n", dev->name); - - pci_set_power_state(pdev, 0); - pci_restore_state(pdev); - - err = orinoco_reinit_firmware(dev); - if (err) { - printk(KERN_ERR "%s: Error %d re-initializing firmware on orinoco_pci_resume()\n", - dev->name, err); - return err; - } - - spin_lock_irqsave(&priv->lock, flags); - - netif_device_attach(dev); - - priv->hw_unavailable--; - - if (priv->open && (! priv->hw_unavailable)) { - err = __orinoco_up(dev); - if (err) - printk(KERN_ERR "%s: Error %d restarting card on orinoco_pci_resume()\n", - dev->name, err); - } - - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -static struct pci_device_id orinoco_pci_pci_id_table[] = { +static struct pci_device_id orinoco_pci_id_table[] = { /* Intersil Prism 3 */ {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, /* Intersil Prism 2.5 */ @@ -357,11 +223,11 @@ static struct pci_device_id orinoco_pci_ {0,}, }; -MODULE_DEVICE_TABLE(pci, orinoco_pci_pci_id_table); +MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table); static struct pci_driver orinoco_pci_driver = { .name = DRIVER_NAME, - .id_table = orinoco_pci_pci_id_table, + .id_table = orinoco_pci_id_table, .probe = orinoco_pci_init_one, .remove = __devexit_p(orinoco_pci_remove_one), .suspend = orinoco_pci_suspend, diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco_pci.h new file mode 100644 index 0000000..7eb1e08 --- /dev/null +++ b/drivers/net/wireless/orinoco_pci.h @@ -0,0 +1,104 @@ +/* orinoco_pci.h + * + * Common code for all Orinoco drivers for PCI devices, including + * both native PCI and PCMCIA-to-PCI bridges. + * + * Copyright (C) 2005, Pavel Roskin. + * See orinoco.c for license. + */ + +#ifndef _ORINOCO_PCI_H +#define _ORINOCO_PCI_H + +#include + +/* Driver specific data */ +struct orinoco_pci_card { + void __iomem *bridge_io; + void __iomem *attr_io; +}; + +#ifdef CONFIG_PM +static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct orinoco_private *priv = netdev_priv(dev); + unsigned long flags; + int err; + + err = orinoco_lock(priv, &flags); + if (err) { + printk(KERN_ERR "%s: cannot lock hardware for suspend\n", + dev->name); + return err; + } + + err = __orinoco_down(dev); + if (err) + printk(KERN_WARNING "%s: error %d bringing interface down " + "for suspend\n", dev->name, err); + + netif_device_detach(dev); + + priv->hw_unavailable++; + + orinoco_unlock(priv, &flags); + + free_irq(pdev->irq, dev); + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +static int orinoco_pci_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct orinoco_private *priv = netdev_priv(dev); + unsigned long flags; + int err; + + pci_set_power_state(pdev, 0); + pci_enable_device(pdev); + pci_restore_state(pdev); + + err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, + dev->name, dev); + if (err) { + printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n", + dev->name); + pci_disable_device(pdev); + return -EBUSY; + } + + err = orinoco_reinit_firmware(dev); + if (err) { + printk(KERN_ERR "%s: error %d re-initializing firmware " + "on resume\n", dev->name, err); + return err; + } + + spin_lock_irqsave(&priv->lock, flags); + + netif_device_attach(dev); + + priv->hw_unavailable--; + + if (priv->open && (! priv->hw_unavailable)) { + err = __orinoco_up(dev); + if (err) + printk(KERN_ERR "%s: Error %d restarting card on resume\n", + dev->name, err); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} +#else +#define orinoco_pci_suspend NULL +#define orinoco_pci_resume NULL +#endif + +#endif /* _ORINOCO_PCI_H */ diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c index 210e737..84f696c 100644 --- a/drivers/net/wireless/orinoco_plx.c +++ b/drivers/net/wireless/orinoco_plx.c @@ -3,7 +3,7 @@ * Driver for Prism II devices which would usually be driven by orinoco_cs, * but are connected to the PCI bus by a PLX9052. * - * Current maintainers (as of 29 September 2003) are: + * Current maintainers are: * Pavel Roskin * and David Gibson * @@ -30,38 +30,18 @@ * other provisions required by the GPL. If you do not delete the * provisions above, a recipient may use your version of this file * under either the MPL or the GPL. - - * Caution: this is experimental and probably buggy. For success and - * failure reports for different cards and adaptors, see - * orinoco_plx_pci_id_table near the end of the file. If you have a - * card we don't have the PCI id for, and looks like it should work, - * drop me mail with the id and "it works"/"it doesn't work". - * - * Note: if everything gets detected fine but it doesn't actually send - * or receive packets, your first port of call should probably be to - * try newer firmware in the card. Especially if you're doing Ad-Hoc - * modes. - * - * The actual driving is done by orinoco.c, this is just resource - * allocation stuff. The explanation below is courtesy of Ryan Niemi - * on the linux-wlan-ng list at - * http://archives.neohapsis.com/archives/dev/linux-wlan/2001-q1/0026.html * - * The PLX9052-based cards (WL11000 and several others) are a - * different beast than the usual PCMCIA-based PRISM2 configuration - * expected by wlan-ng. Here's the general details on how the WL11000 - * PCI adapter works: + * Here's the general details on how the PLX9052 adapter works: * * - Two PCI I/O address spaces, one 0x80 long which contains the * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA * slot I/O address space. * - * - One PCI memory address space, mapped to the PCMCIA memory space + * - One PCI memory address space, mapped to the PCMCIA attribute space * (containing the CIS). * - * After identifying the I/O and memory space, you can read through - * the memory space to confirm the CIS's device ID or manufacturer ID - * to make sure it's the expected card. qKeep in mind that the PCMCIA + * Using the later, you can read through the CIS data to make sure the + * card is compatible with the driver. Keep in mind that the PCMCIA * spec specifies the CIS as the lower 8 bits of each word read from * the CIS, so to read the bytes of the CIS, read every other byte * (0,2,4,...). Passing that test, you need to enable the I/O address @@ -71,7 +51,7 @@ * within the PCI memory space. Write 0x41 to the COR register to * enable I/O mode and to select level triggered interrupts. To * confirm you actually succeeded, read the COR register back and make - * sure it actually got set to 0x41, incase you have an unexpected + * sure it actually got set to 0x41, in case you have an unexpected * card inserted. * * Following that, you can treat the second PCI I/O address space (the @@ -101,16 +81,6 @@ * that, I've hot-swapped a number of times during debugging and * driver development for various reasons (stuck WAIT# line after the * radio card's firmware locks up). - * - * Hope this is enough info for someone to add PLX9052 support to the - * wlan-ng card. In the case of the WL11000, the PCI ID's are - * 0x1639/0x0200, with matching subsystem ID's. Other PLX9052-based - * manufacturers other than Eumitcom (or on cards other than the - * WL11000) may have different PCI ID's. - * - * If anyone needs any more specific info, let me know. I haven't had - * time to implement support myself yet, and with the way things are - * going, might not have time for a while.. */ #define DRIVER_NAME "orinoco_plx" @@ -125,6 +95,7 @@ #include #include #include "orinoco.h" +#include "orinoco_pci.h" #define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */ #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ @@ -134,30 +105,20 @@ #define PLX_RESET_TIME (500) /* millisec #define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */ #define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ -static const u8 cis_magic[] = { - 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67 -}; - -/* Orinoco PLX specific data */ -struct orinoco_plx_card { - void __iomem *attr_mem; -}; - /* * Do a soft reset of the card using the Configuration Option Register */ static int orinoco_plx_cor_reset(struct orinoco_private *priv) { hermes_t *hw = &priv->hw; - struct orinoco_plx_card *card = priv->card; - u8 __iomem *attr_mem = card->attr_mem; + struct orinoco_pci_card *card = priv->card; unsigned long timeout; u16 reg; - writeb(COR_VALUE | COR_RESET, attr_mem + COR_OFFSET); + iowrite8(COR_VALUE | COR_RESET, card->attr_io + COR_OFFSET); mdelay(1); - writeb(COR_VALUE, attr_mem + COR_OFFSET); + iowrite8(COR_VALUE, card->attr_io + COR_OFFSET); mdelay(1); /* Just in case, wait more until the card is no longer busy */ @@ -168,7 +129,7 @@ static int orinoco_plx_cor_reset(struct reg = hermes_read_regn(hw, CMD); } - /* Did we timeout ? */ + /* Still busy? */ if (reg & HERMES_CMD_BUSY) { printk(KERN_ERR PFX "Busy timeout\n"); return -ETIMEDOUT; @@ -177,20 +138,55 @@ static int orinoco_plx_cor_reset(struct return 0; } +static int orinoco_plx_hw_init(struct orinoco_pci_card *card) +{ + int i; + u32 csr_reg; + static const u8 cis_magic[] = { + 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67 + }; + + printk(KERN_DEBUG PFX "CIS: "); + for (i = 0; i < 16; i++) { + printk("%02X:", ioread8(card->attr_io + (i << 1))); + } + printk("\n"); + + /* Verify whether a supported PC card is present */ + /* FIXME: we probably need to be smarted about this */ + for (i = 0; i < sizeof(cis_magic); i++) { + if (cis_magic[i] != ioread8(card->attr_io + (i << 1))) { + printk(KERN_ERR PFX "The CIS value of Prism2 PC " + "card is unexpected\n"); + return -ENODEV; + } + } + + /* bjoern: We need to tell the card to enable interrupts, in + case the serial eprom didn't do this already. See the + PLX9052 data book, p8-1 and 8-24 for reference. */ + csr_reg = ioread32(card->bridge_io + PLX_INTCSR); + if (!(csr_reg & PLX_INTCSR_INTEN)) { + csr_reg |= PLX_INTCSR_INTEN; + iowrite32(csr_reg, card->bridge_io + PLX_INTCSR); + csr_reg = ioread32(card->bridge_io + PLX_INTCSR); + if (!(csr_reg & PLX_INTCSR_INTEN)) { + printk(KERN_ERR PFX "Cannot enable interrupts\n"); + return -EIO; + } + } + + return 0; +} static int orinoco_plx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - int err = 0; - u8 __iomem *attr_mem = NULL; - u32 csr_reg, plx_addr; - struct orinoco_private *priv = NULL; - struct orinoco_plx_card *card; - unsigned long pccard_ioaddr = 0; - unsigned long pccard_iolen = 0; - struct net_device *dev = NULL; - void __iomem *mem; - int i; + int err; + struct orinoco_private *priv; + struct orinoco_pci_card *card; + struct net_device *dev; + void __iomem *hermes_io, *attr_io, *bridge_io; err = pci_enable_device(pdev); if (err) { @@ -199,30 +195,30 @@ static int orinoco_plx_init_one(struct p } err = pci_request_regions(pdev, DRIVER_NAME); - if (err != 0) { + if (err) { printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); goto fail_resources; } - /* Resource 1 is mapped to PLX-specific registers */ - plx_addr = pci_resource_start(pdev, 1); + bridge_io = pci_iomap(pdev, 1, 0); + if (!bridge_io) { + printk(KERN_ERR PFX "Cannot map bridge registers\n"); + err = -EIO; + goto fail_map_bridge; + } - /* Resource 2 is mapped to the PCMCIA attribute memory */ - attr_mem = ioremap(pci_resource_start(pdev, 2), - pci_resource_len(pdev, 2)); - if (!attr_mem) { - printk(KERN_ERR PFX "Cannot remap PCMCIA space\n"); + attr_io = pci_iomap(pdev, 2, 0); + if (!attr_io) { + printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n"); + err = -EIO; goto fail_map_attr; } - /* Resource 3 is mapped to the PCMCIA I/O address space */ - pccard_ioaddr = pci_resource_start(pdev, 3); - pccard_iolen = pci_resource_len(pdev, 3); - - mem = pci_iomap(pdev, 3, 0); - if (!mem) { - err = -ENOMEM; - goto fail_map_io; + hermes_io = pci_iomap(pdev, 3, 0); + if (!hermes_io) { + printk(KERN_ERR PFX "Cannot map chipset registers\n"); + err = -EIO; + goto fail_map_hermes; } /* Allocate network device */ @@ -235,16 +231,12 @@ static int orinoco_plx_init_one(struct p priv = netdev_priv(dev); card = priv->card; - card->attr_mem = attr_mem; - dev->base_addr = pccard_ioaddr; + card->bridge_io = bridge_io; + card->attr_io = attr_io; SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING); - - printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PLX device " - "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq, - pccard_ioaddr); + hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, dev); @@ -253,20 +245,11 @@ static int orinoco_plx_init_one(struct p err = -EBUSY; goto fail_irq; } - dev->irq = pdev->irq; - /* bjoern: We need to tell the card to enable interrupts, in - case the serial eprom didn't do this already. See the - PLX9052 data book, p8-1 and 8-24 for reference. */ - csr_reg = inl(plx_addr + PLX_INTCSR); - if (!(csr_reg & PLX_INTCSR_INTEN)) { - csr_reg |= PLX_INTCSR_INTEN; - outl(csr_reg, plx_addr + PLX_INTCSR); - csr_reg = inl(plx_addr + PLX_INTCSR); - if (!(csr_reg & PLX_INTCSR_INTEN)) { - printk(KERN_ERR PFX "Cannot enable interrupts\n"); - goto fail; - } + err = orinoco_plx_hw_init(card); + if (err) { + printk(KERN_ERR PFX "Hardware initialization failed\n"); + goto fail; } err = orinoco_plx_cor_reset(priv); @@ -275,23 +258,6 @@ static int orinoco_plx_init_one(struct p goto fail; } - printk(KERN_DEBUG PFX "CIS: "); - for (i = 0; i < 16; i++) { - printk("%02X:", readb(attr_mem + 2*i)); - } - printk("\n"); - - /* Verify whether a supported PC card is present */ - /* FIXME: we probably need to be smarted about this */ - for (i = 0; i < sizeof(cis_magic); i++) { - if (cis_magic[i] != readb(attr_mem +2*i)) { - printk(KERN_ERR PFX "The CIS value of Prism2 PC " - "card is unexpected\n"); - err = -EIO; - goto fail; - } - } - err = register_netdev(dev); if (err) { printk(KERN_ERR PFX "Cannot register network device\n"); @@ -299,6 +265,8 @@ static int orinoco_plx_init_one(struct p } pci_set_drvdata(pdev, dev); + printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name, + pci_name(pdev)); return 0; @@ -310,12 +278,15 @@ static int orinoco_plx_init_one(struct p free_orinocodev(dev); fail_alloc: - pci_iounmap(pdev, mem); + pci_iounmap(pdev, hermes_io); - fail_map_io: - iounmap(attr_mem); + fail_map_hermes: + pci_iounmap(pdev, attr_io); fail_map_attr: + pci_iounmap(pdev, bridge_io); + + fail_map_bridge: pci_release_regions(pdev); fail_resources: @@ -328,23 +299,20 @@ static void __devexit orinoco_plx_remove { struct net_device *dev = pci_get_drvdata(pdev); struct orinoco_private *priv = netdev_priv(dev); - struct orinoco_plx_card *card = priv->card; - u8 __iomem *attr_mem = card->attr_mem; - - BUG_ON(! dev); + struct orinoco_pci_card *card = priv->card; unregister_netdev(dev); - free_irq(dev->irq, dev); + free_irq(pdev->irq, dev); pci_set_drvdata(pdev, NULL); free_orinocodev(dev); pci_iounmap(pdev, priv->hw.iobase); - iounmap(attr_mem); + pci_iounmap(pdev, card->attr_io); + pci_iounmap(pdev, card->bridge_io); pci_release_regions(pdev); pci_disable_device(pdev); } - -static struct pci_device_id orinoco_plx_pci_id_table[] = { +static struct pci_device_id orinoco_plx_id_table[] = { {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */ {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */ {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ @@ -362,13 +330,15 @@ static struct pci_device_id orinoco_plx_ {0,}, }; -MODULE_DEVICE_TABLE(pci, orinoco_plx_pci_id_table); +MODULE_DEVICE_TABLE(pci, orinoco_plx_id_table); static struct pci_driver orinoco_plx_driver = { .name = DRIVER_NAME, - .id_table = orinoco_plx_pci_id_table, + .id_table = orinoco_plx_id_table, .probe = orinoco_plx_init_one, .remove = __devexit_p(orinoco_plx_remove_one), + .suspend = orinoco_pci_suspend, + .resume = orinoco_pci_resume, }; static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION @@ -388,7 +358,6 @@ static int __init orinoco_plx_init(void) static void __exit orinoco_plx_exit(void) { pci_unregister_driver(&orinoco_plx_driver); - ssleep(1); } module_init(orinoco_plx_init); diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c index 5e68b70..d2b4dec 100644 --- a/drivers/net/wireless/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco_tmd.c @@ -1,5 +1,5 @@ /* orinoco_tmd.c - * + * * Driver for Prism II devices which would usually be driven by orinoco_cs, * but are connected to the PCI bus by a TMD7160. * @@ -26,25 +26,13 @@ * other provisions required by the GPL. If you do not delete the * provisions above, a recipient may use your version of this file * under either the MPL or the GPL. - - * Caution: this is experimental and probably buggy. For success and - * failure reports for different cards and adaptors, see - * orinoco_tmd_pci_id_table near the end of the file. If you have a - * card we don't have the PCI id for, and looks like it should work, - * drop me mail with the id and "it works"/"it doesn't work". - * - * Note: if everything gets detected fine but it doesn't actually send - * or receive packets, your first port of call should probably be to - * try newer firmware in the card. Especially if you're doing Ad-Hoc - * modes * * The actual driving is done by orinoco.c, this is just resource * allocation stuff. * * This driver is modeled after the orinoco_plx driver. The main - * difference is that the TMD chip has only IO port ranges and no - * memory space, i.e. no access to the CIS. Compared to the PLX chip, - * the io range functionalities are exchanged. + * difference is that the TMD chip has only IO port ranges and doesn't + * provide access to the PCMCIA attribute space. * * Pheecom sells cards with the TMD chip as "ASIC version" */ @@ -61,32 +49,26 @@ #include #include #include "orinoco.h" +#include "orinoco_pci.h" #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ #define COR_RESET (0x80) /* reset bit in the COR register */ #define TMD_RESET_TIME (500) /* milliseconds */ -/* Orinoco TMD specific data */ -struct orinoco_tmd_card { - u32 tmd_io; -}; - - /* * Do a soft reset of the card using the Configuration Option Register */ static int orinoco_tmd_cor_reset(struct orinoco_private *priv) { hermes_t *hw = &priv->hw; - struct orinoco_tmd_card *card = priv->card; - u32 addr = card->tmd_io; + struct orinoco_pci_card *card = priv->card; unsigned long timeout; u16 reg; - outb(COR_VALUE | COR_RESET, addr); + iowrite8(COR_VALUE | COR_RESET, card->bridge_io); mdelay(1); - outb(COR_VALUE, addr); + iowrite8(COR_VALUE, card->bridge_io); mdelay(1); /* Just in case, wait more until the card is no longer busy */ @@ -97,7 +79,7 @@ static int orinoco_tmd_cor_reset(struct reg = hermes_read_regn(hw, CMD); } - /* Did we timeout ? */ + /* Still busy? */ if (reg & HERMES_CMD_BUSY) { printk(KERN_ERR PFX "Busy timeout\n"); return -ETIMEDOUT; @@ -110,11 +92,11 @@ static int orinoco_tmd_cor_reset(struct static int orinoco_tmd_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - int err = 0; - struct orinoco_private *priv = NULL; - struct orinoco_tmd_card *card; - struct net_device *dev = NULL; - void __iomem *mem; + int err; + struct orinoco_private *priv; + struct orinoco_pci_card *card; + struct net_device *dev; + void __iomem *hermes_io, *bridge_io; err = pci_enable_device(pdev); if (err) { @@ -123,20 +105,28 @@ static int orinoco_tmd_init_one(struct p } err = pci_request_regions(pdev, DRIVER_NAME); - if (err != 0) { + if (err) { printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); goto fail_resources; } - mem = pci_iomap(pdev, 2, 0); - if (! mem) { - err = -ENOMEM; - goto fail_iomap; + bridge_io = pci_iomap(pdev, 1, 0); + if (!bridge_io) { + printk(KERN_ERR PFX "Cannot map bridge registers\n"); + err = -EIO; + goto fail_map_bridge; + } + + hermes_io = pci_iomap(pdev, 2, 0); + if (!hermes_io) { + printk(KERN_ERR PFX "Cannot map chipset registers\n"); + err = -EIO; + goto fail_map_hermes; } /* Allocate network device */ dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset); - if (! dev) { + if (!dev) { printk(KERN_ERR PFX "Cannot allocate network device\n"); err = -ENOMEM; goto fail_alloc; @@ -144,16 +134,11 @@ static int orinoco_tmd_init_one(struct p priv = netdev_priv(dev); card = priv->card; - card->tmd_io = pci_resource_start(pdev, 1); - dev->base_addr = pci_resource_start(pdev, 2); + card->bridge_io = bridge_io; SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING); - - printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device " - "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq, - dev->base_addr); + hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, dev); @@ -162,7 +147,6 @@ static int orinoco_tmd_init_one(struct p err = -EBUSY; goto fail_irq; } - dev->irq = pdev->irq; err = orinoco_tmd_cor_reset(priv); if (err) { @@ -177,6 +161,8 @@ static int orinoco_tmd_init_one(struct p } pci_set_drvdata(pdev, dev); + printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name, + pci_name(pdev)); return 0; @@ -188,9 +174,12 @@ static int orinoco_tmd_init_one(struct p free_orinocodev(dev); fail_alloc: - pci_iounmap(pdev, mem); + pci_iounmap(pdev, hermes_io); + + fail_map_hermes: + pci_iounmap(pdev, bridge_io); - fail_iomap: + fail_map_bridge: pci_release_regions(pdev); fail_resources: @@ -203,31 +192,32 @@ static void __devexit orinoco_tmd_remove { struct net_device *dev = pci_get_drvdata(pdev); struct orinoco_private *priv = dev->priv; - - BUG_ON(! dev); + struct orinoco_pci_card *card = priv->card; unregister_netdev(dev); - free_irq(dev->irq, dev); + free_irq(pdev->irq, dev); pci_set_drvdata(pdev, NULL); free_orinocodev(dev); pci_iounmap(pdev, priv->hw.iobase); + pci_iounmap(pdev, card->bridge_io); pci_release_regions(pdev); pci_disable_device(pdev); } - -static struct pci_device_id orinoco_tmd_pci_id_table[] = { +static struct pci_device_id orinoco_tmd_id_table[] = { {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ {0,}, }; -MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table); +MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table); static struct pci_driver orinoco_tmd_driver = { .name = DRIVER_NAME, - .id_table = orinoco_tmd_pci_id_table, + .id_table = orinoco_tmd_id_table, .probe = orinoco_tmd_init_one, .remove = __devexit_p(orinoco_tmd_remove_one), + .suspend = orinoco_pci_suspend, + .resume = orinoco_pci_resume, }; static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION @@ -245,7 +235,6 @@ static int __init orinoco_tmd_init(void) static void __exit orinoco_tmd_exit(void) { pci_unregister_driver(&orinoco_tmd_driver); - ssleep(1); } module_init(orinoco_tmd_init); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 879eb42..a915fe6 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -924,8 +924,7 @@ static int ray_dev_start_xmit(struct sk_ if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index f7b77ce..7f9aa13 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -1,6 +1,6 @@ /* * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as - * Symbol Wireless Networker LA4100, CompactFlash cards by Socket + * Symbol Wireless Networker LA4137, CompactFlash cards by Socket * Communications and Intel PRO/Wireless 2011B. * * The driver implements Symbol firmware download. The rest is handled @@ -120,8 +120,8 @@ #define TEXT_END 0x1A /* End of text he * Each block has the following structure. */ struct dblock { - __le32 _addr; /* adapter address where to write the block */ - __le16 _len; /* length of the data only, in bytes */ + __le32 addr; /* adapter address where to write the block */ + __le16 len; /* length of the data only, in bytes */ char data[0]; /* data to be written */ } __attribute__ ((packed)); @@ -131,9 +131,9 @@ struct dblock { * items with matching ID should be written. */ struct pdr { - __le32 _id; /* record ID */ - __le32 _addr; /* adapter address where to write the data */ - __le32 _len; /* expected length of the data, in bytes */ + __le32 id; /* record ID */ + __le32 addr; /* adapter address where to write the data */ + __le32 len; /* expected length of the data, in bytes */ char next[0]; /* next PDR starts here */ } __attribute__ ((packed)); @@ -144,8 +144,8 @@ struct pdr { * be plugged into the secondary firmware. */ struct pdi { - __le16 _len; /* length of ID and data, in words */ - __le16 _id; /* record ID */ + __le16 len; /* length of ID and data, in words */ + __le16 id; /* record ID */ char data[0]; /* plug data */ } __attribute__ ((packed)); @@ -154,44 +154,44 @@ struct pdi { static inline u32 dblock_addr(const struct dblock *blk) { - return le32_to_cpu(blk->_addr); + return le32_to_cpu(blk->addr); } static inline u32 dblock_len(const struct dblock *blk) { - return le16_to_cpu(blk->_len); + return le16_to_cpu(blk->len); } static inline u32 pdr_id(const struct pdr *pdr) { - return le32_to_cpu(pdr->_id); + return le32_to_cpu(pdr->id); } static inline u32 pdr_addr(const struct pdr *pdr) { - return le32_to_cpu(pdr->_addr); + return le32_to_cpu(pdr->addr); } static inline u32 pdr_len(const struct pdr *pdr) { - return le32_to_cpu(pdr->_len); + return le32_to_cpu(pdr->len); } static inline u32 pdi_id(const struct pdi *pdi) { - return le16_to_cpu(pdi->_id); + return le16_to_cpu(pdi->id); } /* Return length of the data only, in bytes */ static inline u32 pdi_len(const struct pdi *pdi) { - return 2 * (le16_to_cpu(pdi->_len) - 1); + return 2 * (le16_to_cpu(pdi->len) - 1); } @@ -343,8 +343,7 @@ spectrum_plug_pdi(hermes_t *hw, struct p /* do the actual plugging */ spectrum_aux_setaddr(hw, pdr_addr(pdr)); - hermes_write_words(hw, HERMES_AUXDATA, pdi->data, - pdi_len(pdi) / 2); + hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi)); return 0; } @@ -424,8 +423,8 @@ spectrum_load_blocks(hermes_t *hw, const while (dblock_addr(blk) != BLOCK_END) { spectrum_aux_setaddr(hw, blkaddr); - hermes_write_words(hw, HERMES_AUXDATA, blk->data, - blklen / 2); + hermes_write_bytes(hw, HERMES_AUXDATA, blk->data, + blklen); blk = (struct dblock *) &blk->data[blklen]; blkaddr = dblock_addr(blk); @@ -626,14 +625,11 @@ static void spectrum_cs_detach(struct pc { struct net_device *dev = link->priv; + if (link->dev_node) + unregister_netdev(dev); + spectrum_cs_release(link); - DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); - if (link->dev_node) { - DEBUG(0, PFX "About to unregister net device %p\n", - dev); - unregister_netdev(dev); - } free_orinocodev(dev); } /* spectrum_cs_detach */ @@ -653,13 +649,10 @@ spectrum_cs_config(struct pcmcia_device int last_fn, last_ret; u_char buf[64]; config_info_t conf; - cisinfo_t info; tuple_t tuple; cisparse_t parse; void __iomem *mem; - CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info)); - /* * This reads the card's CONFIG tuple to find its * configuration registers. @@ -709,12 +702,6 @@ spectrum_cs_config(struct pcmcia_device goto next_entry; link->conf.ConfigIndex = cfg->index; - /* Does this card need audio output? */ - if (cfg->flags & CISTPL_CFTABLE_AUDIO) { - link->conf.Attributes |= CONF_ENABLE_SPKR; - link->conf.Status = CCSR_AUDIO_ENA; - } - /* Use power settings for Vcc and Vpp if present */ /* Note that the CIS values need to be rescaled */ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { @@ -835,19 +822,10 @@ spectrum_cs_config(struct pcmcia_device net_device has been registered */ /* Finally, report what we've done */ - printk(KERN_DEBUG "%s: index 0x%02x: ", - dev->name, link->conf.ConfigIndex); - if (link->conf.Vpp) - printk(", Vpp %d.%d", link->conf.Vpp / 10, - link->conf.Vpp % 10); - printk(", irq %d", link->irq.AssignedIRQ); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1 + link->io.NumPorts1 - 1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2 + link->io.NumPorts2 - 1); - printk("\n"); + printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io " + "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id, + link->irq.AssignedIRQ, link->io.BasePort1, + link->io.BasePort1 + link->io.NumPorts1 - 1); return 0; @@ -888,11 +866,10 @@ spectrum_cs_suspend(struct pcmcia_device { struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); - unsigned long flags; int err = 0; /* Mark the device as stopped, to block IO until later */ - spin_lock_irqsave(&priv->lock, flags); + spin_lock(&priv->lock); err = __orinoco_down(dev); if (err) @@ -902,9 +879,9 @@ spectrum_cs_suspend(struct pcmcia_device netif_device_detach(dev); priv->hw_unavailable++; - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock(&priv->lock); - return 0; + return err; } static int @@ -932,7 +909,7 @@ static char version[] __initdata = DRIVE " David Gibson , et al)"; static struct pcmcia_device_id spectrum_cs_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */ + PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */ PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */ PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */ PCMCIA_DEVICE_NULL, diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c index dade4b9..5b69bef 100644 --- a/drivers/net/wireless/wavelan.c +++ b/drivers/net/wireless/wavelan.c @@ -1695,8 +1695,8 @@ static int wv_frequency_list(unsigned lo /* Look in the table if the frequency is allowed */ if (table[9 - (freq / 16)] & (1 << (freq % 16))) { /* Compute approximate channel number */ - while ((((channel_bands[c] >> 1) - 24) < freq) && - (c < NELS(channel_bands))) + while ((c < NELS(channel_bands)) && + (((channel_bands[c] >> 1) - 24) < freq)) c++; list[i].i = c; /* Set the list index */ @@ -2903,6 +2903,7 @@ static int wavelan_packet_xmit(struct sk { net_local *lp = (net_local *) dev->priv; unsigned long flags; + char data[ETH_ZLEN]; #ifdef DEBUG_TX_TRACE printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name, @@ -2937,15 +2938,16 @@ #endif * able to detect collisions, therefore in theory we don't really * need to pad. Jean II */ if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; + memset(data, 0, ETH_ZLEN); + memcpy(data, skb->data, skb->len); + /* Write packet on the card */ + if(wv_packet_write(dev, data, ETH_ZLEN)) + return 1; /* We failed */ } - - /* Write packet on the card */ - if(wv_packet_write(dev, skb->data, skb->len)) + else if(wv_packet_write(dev, skb->data, skb->len)) return 1; /* We failed */ + dev_kfree_skb(skb); #ifdef DEBUG_TX_TRACE diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index f7724eb..561250f 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -3194,11 +3194,8 @@ #endif * and we don't have the Ethernet specific requirement of beeing * able to detect collisions, therefore in theory we don't really * need to pad. Jean II */ - if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; - } + if (skb_padto(skb, ETH_ZLEN)) + return 0; wv_packet_write(dev, skb->data, skb->len); diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c new file mode 100644 index 0000000..662ecc8 --- /dev/null +++ b/drivers/net/wireless/zd1201.c @@ -0,0 +1,1929 @@ +/* + * Driver for ZyDAS zd1201 based wireless USB devices. + * + * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * Parts of this driver have been derived from a wlan-ng version + * modified by ZyDAS. They also made documentation available, thanks! + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "zd1201.h" + +static struct usb_device_id zd1201_table[] = { + {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */ + {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ + {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ + {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ + {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */ + {} +}; + +static int ap; /* Are we an AP or a normal station? */ + +#define ZD1201_VERSION "0.15" + +MODULE_AUTHOR("Jeroen Vreeken "); +MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters"); +MODULE_VERSION(ZD1201_VERSION); +MODULE_LICENSE("GPL"); +module_param(ap, int, 0); +MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded"); +MODULE_DEVICE_TABLE(usb, zd1201_table); + + +static int zd1201_fw_upload(struct usb_device *dev, int apfw) +{ + const struct firmware *fw_entry; + char *data; + unsigned long len; + int err; + unsigned char ret; + char *buf; + char *fwfile; + + if (apfw) + fwfile = "zd1201-ap.fw"; + else + fwfile = "zd1201.fw"; + + err = request_firmware(&fw_entry, fwfile, &dev->dev); + if (err) { + dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile); + dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n"); + dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n"); + return err; + } + + data = fw_entry->data; + len = fw_entry->size; + + buf = kmalloc(1024, GFP_ATOMIC); + if (!buf) + goto exit; + + while (len > 0) { + int translen = (len > 1024) ? 1024 : len; + memcpy(buf, data, translen); + + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0, + USB_DIR_OUT | 0x40, 0, 0, buf, translen, + ZD1201_FW_TIMEOUT); + if (err < 0) + goto exit; + + len -= translen; + data += translen; + } + + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2, + USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT); + if (err < 0) + goto exit; + + err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4, + USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT); + if (err < 0) + goto exit; + + if (ret & 0x80) { + err = -EIO; + goto exit; + } + + err = 0; +exit: + kfree(buf); + release_firmware(fw_entry); + return err; +} + +static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs) +{ + struct zd1201 *zd = urb->context; + + switch(urb->status) { + case -EILSEQ: + case -ENODEV: + case -ETIMEDOUT: + case -ENOENT: + case -EPIPE: + case -EOVERFLOW: + case -ESHUTDOWN: + dev_warn(&zd->usb->dev, "%s: urb failed: %d\n", + zd->dev->name, urb->status); + } + + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return; +} + +/* cmdreq message: + u32 type + u16 cmd + u16 parm0 + u16 parm1 + u16 parm2 + u8 pad[4] + + total: 4 + 2 + 2 + 2 + 2 + 4 = 16 +*/ +static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0, + int parm1, int parm2) +{ + unsigned char *command; + int ret; + struct urb *urb; + + command = kmalloc(16, GFP_ATOMIC); + if (!command) + return -ENOMEM; + + *((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ); + *((__le16*)&command[4]) = cpu_to_le16(cmd); + *((__le16*)&command[6]) = cpu_to_le16(parm0); + *((__le16*)&command[8]) = cpu_to_le16(parm1); + *((__le16*)&command[10])= cpu_to_le16(parm2); + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + kfree(command); + return -ENOMEM; + } + usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), + command, 16, zd1201_usbfree, zd); + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) { + kfree(command); + usb_free_urb(urb); + } + + return ret; +} + +/* Callback after sending out a packet */ +static void zd1201_usbtx(struct urb *urb, struct pt_regs *regs) +{ + struct zd1201 *zd = urb->context; + netif_wake_queue(zd->dev); + return; +} + +/* Incoming data */ +static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs) +{ + struct zd1201 *zd = urb->context; + int free = 0; + unsigned char *data = urb->transfer_buffer; + struct sk_buff *skb; + unsigned char type; + + if (!zd) { + free = 1; + goto exit; + } + + switch(urb->status) { + case -EILSEQ: + case -ENODEV: + case -ETIMEDOUT: + case -ENOENT: + case -EPIPE: + case -EOVERFLOW: + case -ESHUTDOWN: + dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n", + zd->dev->name, urb->status); + free = 1; + goto exit; + } + + if (urb->status != 0 || urb->actual_length == 0) + goto resubmit; + + type = data[0]; + if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) { + memcpy(zd->rxdata, data, urb->actual_length); + zd->rxlen = urb->actual_length; + zd->rxdatas = 1; + wake_up(&zd->rxdataq); + } + /* Info frame */ + if (type == ZD1201_PACKET_INQUIRE) { + int i = 0; + unsigned short infotype, framelen, copylen; + framelen = le16_to_cpu(*(__le16*)&data[4]); + infotype = le16_to_cpu(*(__le16*)&data[6]); + + if (infotype == ZD1201_INF_LINKSTATUS) { + short linkstatus; + + linkstatus = le16_to_cpu(*(__le16*)&data[8]); + switch(linkstatus) { + case 1: + netif_carrier_on(zd->dev); + break; + case 2: + netif_carrier_off(zd->dev); + break; + case 3: + netif_carrier_off(zd->dev); + break; + case 4: + netif_carrier_on(zd->dev); + break; + default: + netif_carrier_off(zd->dev); + } + goto resubmit; + } + if (infotype == ZD1201_INF_ASSOCSTATUS) { + short status = le16_to_cpu(*(__le16*)(data+8)); + int event; + union iwreq_data wrqu; + + switch (status) { + case ZD1201_ASSOCSTATUS_STAASSOC: + case ZD1201_ASSOCSTATUS_REASSOC: + event = IWEVREGISTERED; + break; + case ZD1201_ASSOCSTATUS_DISASSOC: + case ZD1201_ASSOCSTATUS_ASSOCFAIL: + case ZD1201_ASSOCSTATUS_AUTHFAIL: + default: + event = IWEVEXPIRED; + } + memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN); + wrqu.addr.sa_family = ARPHRD_ETHER; + + /* Send event to user space */ + wireless_send_event(zd->dev, event, &wrqu, NULL); + + goto resubmit; + } + if (infotype == ZD1201_INF_AUTHREQ) { + union iwreq_data wrqu; + + memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN); + wrqu.addr.sa_family = ARPHRD_ETHER; + /* There isn't a event that trully fits this request. + We assume that userspace will be smart enough to + see a new station being expired and sends back a + authstation ioctl to authorize it. */ + wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL); + goto resubmit; + } + /* Other infotypes are handled outside this handler */ + zd->rxlen = 0; + while (i < urb->actual_length) { + copylen = le16_to_cpu(*(__le16*)&data[i+2]); + /* Sanity check, sometimes we get junk */ + if (copylen+zd->rxlen > sizeof(zd->rxdata)) + break; + memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen); + zd->rxlen += copylen; + i += 64; + } + if (i >= urb->actual_length) { + zd->rxdatas = 1; + wake_up(&zd->rxdataq); + } + goto resubmit; + } + /* Actual data */ + if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) { + int datalen = urb->actual_length-1; + unsigned short len, fc, seq; + struct hlist_node *node; + + len = ntohs(*(__be16 *)&data[datalen-2]); + if (len>datalen) + len=datalen; + fc = le16_to_cpu(*(__le16 *)&data[datalen-16]); + seq = le16_to_cpu(*(__le16 *)&data[datalen-24]); + + if (zd->monitor) { + if (datalen < 24) + goto resubmit; + if (!(skb = dev_alloc_skb(datalen+24))) + goto resubmit; + + memcpy(skb_put(skb, 2), &data[datalen-16], 2); + memcpy(skb_put(skb, 2), &data[datalen-2], 2); + memcpy(skb_put(skb, 6), &data[datalen-14], 6); + memcpy(skb_put(skb, 6), &data[datalen-22], 6); + memcpy(skb_put(skb, 6), &data[datalen-8], 6); + memcpy(skb_put(skb, 2), &data[datalen-24], 2); + memcpy(skb_put(skb, len), data, len); + skb->dev = zd->dev; + skb->dev->last_rx = jiffies; + skb->protocol = eth_type_trans(skb, zd->dev); + zd->stats.rx_packets++; + zd->stats.rx_bytes += skb->len; + netif_rx(skb); + goto resubmit; + } + + if ((seq & IEEE80211_SCTL_FRAG) || + (fc & IEEE80211_FCTL_MOREFRAGS)) { + struct zd1201_frag *frag = NULL; + char *ptr; + + if (datalen<14) + goto resubmit; + if ((seq & IEEE80211_SCTL_FRAG) == 0) { + frag = kmalloc(sizeof(*frag), GFP_ATOMIC); + if (!frag) + goto resubmit; + skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2); + if (!skb) { + kfree(frag); + goto resubmit; + } + frag->skb = skb; + frag->seq = seq & IEEE80211_SCTL_SEQ; + skb_reserve(skb, 2); + memcpy(skb_put(skb, 12), &data[datalen-14], 12); + memcpy(skb_put(skb, 2), &data[6], 2); + memcpy(skb_put(skb, len), data+8, len); + hlist_add_head(&frag->fnode, &zd->fraglist); + goto resubmit; + } + hlist_for_each_entry(frag, node, &zd->fraglist, fnode) + if (frag->seq == (seq&IEEE80211_SCTL_SEQ)) + break; + if (!frag) + goto resubmit; + skb = frag->skb; + ptr = skb_put(skb, len); + if (ptr) + memcpy(ptr, data+8, len); + if (fc & IEEE80211_FCTL_MOREFRAGS) + goto resubmit; + hlist_del_init(&frag->fnode); + kfree(frag); + } else { + if (datalen<14) + goto resubmit; + skb = dev_alloc_skb(len + 14 + 2); + if (!skb) + goto resubmit; + skb_reserve(skb, 2); + memcpy(skb_put(skb, 12), &data[datalen-14], 12); + memcpy(skb_put(skb, 2), &data[6], 2); + memcpy(skb_put(skb, len), data+8, len); + } + skb->dev = zd->dev; + skb->dev->last_rx = jiffies; + skb->protocol = eth_type_trans(skb, zd->dev); + zd->stats.rx_packets++; + zd->stats.rx_bytes += skb->len; + netif_rx(skb); + } +resubmit: + memset(data, 0, ZD1201_RXSIZE); + + urb->status = 0; + urb->dev = zd->usb; + if(usb_submit_urb(urb, GFP_ATOMIC)) + free = 1; + +exit: + if (free) { + zd->rxlen = 0; + zd->rxdatas = 1; + wake_up(&zd->rxdataq); + kfree(urb->transfer_buffer); + } + return; +} + +static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata, + unsigned int riddatalen) +{ + int err; + int i = 0; + int code; + int rid_fid; + int length; + unsigned char *pdata; + + zd->rxdatas = 0; + err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0); + if (err) + return err; + + wait_event_interruptible(zd->rxdataq, zd->rxdatas); + if (!zd->rxlen) + return -EIO; + + code = le16_to_cpu(*(__le16*)(&zd->rxdata[4])); + rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6])); + length = le16_to_cpu(*(__le16*)(&zd->rxdata[8])); + if (length > zd->rxlen) + length = zd->rxlen-6; + + /* If access bit is not on, then error */ + if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid ) + return -EINVAL; + + /* Not enough buffer for allocating data */ + if (riddatalen != (length - 4)) { + dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n", + riddatalen, zd->rxlen, length, rid, rid_fid); + return -ENODATA; + } + + zd->rxdatas = 0; + /* Issue SetRxRid commnd */ + err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length); + if (err) + return err; + + /* Receive RID record from resource packets */ + wait_event_interruptible(zd->rxdataq, zd->rxdatas); + if (!zd->rxlen) + return -EIO; + + if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) { + dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n", + zd->rxdata[zd->rxlen-1]); + return -EINVAL; + } + + /* Set the data pointer and received data length */ + pdata = zd->rxdata; + length = zd->rxlen; + + do { + int actual_length; + + actual_length = (length > 64) ? 64 : length; + + if (pdata[0] != 0x3) { + dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n", + pdata[0]); + return -EINVAL; + } + + if (actual_length != 64) { + /* Trim the last packet type byte */ + actual_length--; + } + + /* Skip the 4 bytes header (RID length and RID) */ + if (i == 0) { + pdata += 8; + actual_length -= 8; + } else { + pdata += 4; + actual_length -= 4; + } + + memcpy(riddata, pdata, actual_length); + riddata += actual_length; + pdata += actual_length; + length -= 64; + i++; + } while (length > 0); + + return 0; +} + +/* + * resreq: + * byte type + * byte sequence + * u16 reserved + * byte data[12] + * total: 16 + */ +static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait) +{ + int err; + unsigned char *request; + int reqlen; + char seq=0; + struct urb *urb; + gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC; + + len += 4; /* first 4 are for header */ + + zd->rxdatas = 0; + zd->rxlen = 0; + for (seq=0; len > 0; seq++) { + request = kmalloc(16, gfp_mask); + if (!request) + return -ENOMEM; + urb = usb_alloc_urb(0, gfp_mask); + if (!urb) { + kfree(request); + return -ENOMEM; + } + memset(request, 0, 16); + reqlen = len>12 ? 12 : len; + request[0] = ZD1201_USB_RESREQ; + request[1] = seq; + request[2] = 0; + request[3] = 0; + if (request[1] == 0) { + /* add header */ + *(__le16*)&request[4] = cpu_to_le16((len-2+1)/2); + *(__le16*)&request[6] = cpu_to_le16(rid); + memcpy(request+8, buf, reqlen-4); + buf += reqlen-4; + } else { + memcpy(request+4, buf, reqlen); + buf += reqlen; + } + + len -= reqlen; + + usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, + zd->endp_out2), request, 16, zd1201_usbfree, zd); + err = usb_submit_urb(urb, gfp_mask); + if (err) + goto err; + } + + request = kmalloc(16, gfp_mask); + if (!request) + return -ENOMEM; + urb = usb_alloc_urb(0, gfp_mask); + if (!urb) { + kfree(request); + return -ENOMEM; + } + *((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ); + *((__le16*)&request[4]) = + cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT); + *((__le16*)&request[6]) = cpu_to_le16(rid); + *((__le16*)&request[8]) = cpu_to_le16(0); + *((__le16*)&request[10]) = cpu_to_le16(0); + usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), + request, 16, zd1201_usbfree, zd); + err = usb_submit_urb(urb, gfp_mask); + if (err) + goto err; + + if (wait) { + wait_event_interruptible(zd->rxdataq, zd->rxdatas); + if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) { + dev_dbg(&zd->usb->dev, "wrong or no RID received\n"); + } + } + + return 0; +err: + kfree(request); + usb_free_urb(urb); + return err; +} + +static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val) +{ + int err; + __le16 zdval; + + err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16)); + if (err) + return err; + *val = le16_to_cpu(zdval); + return 0; +} + +static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val) +{ + __le16 zdval = cpu_to_le16(val); + return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1)); +} + +static int zd1201_drvr_start(struct zd1201 *zd) +{ + int err, i; + short max; + __le16 zdmax; + unsigned char *buffer; + + buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + usb_fill_bulk_urb(zd->rx_urb, zd->usb, + usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE, + zd1201_usbrx, zd); + + err = usb_submit_urb(zd->rx_urb, GFP_KERNEL); + if (err) + goto err_buffer; + + err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); + if (err) + goto err_urb; + + err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax, + sizeof(__le16)); + if (err) + goto err_urb; + + max = le16_to_cpu(zdmax); + for (i=0; irx_urb); + return err; +err_buffer: + kfree(buffer); + return err; +} + +/* Magic alert: The firmware doesn't seem to like the MAC state being + * toggled in promisc (aka monitor) mode. + * (It works a number of times, but will halt eventually) + * So we turn it of before disabling and on after enabling if needed. + */ +static int zd1201_enable(struct zd1201 *zd) +{ + int err; + + if (zd->mac_enabled) + return 0; + + err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0); + if (!err) + zd->mac_enabled = 1; + + if (zd->monitor) + err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1); + + return err; +} + +static int zd1201_disable(struct zd1201 *zd) +{ + int err; + + if (!zd->mac_enabled) + return 0; + if (zd->monitor) { + err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); + if (err) + return err; + } + + err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0); + if (!err) + zd->mac_enabled = 0; + return err; +} + +static int zd1201_mac_reset(struct zd1201 *zd) +{ + if (!zd->mac_enabled) + return 0; + zd1201_disable(zd); + return zd1201_enable(zd); +} + +static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen) +{ + int err, val; + char buf[IW_ESSID_MAX_SIZE+2]; + + err = zd1201_disable(zd); + if (err) + return err; + + val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; + val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val); + if (err) + return err; + + *(__le16 *)buf = cpu_to_le16(essidlen); + memcpy(buf+2, essid, essidlen); + if (!zd->ap) { /* Normal station */ + err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, + IW_ESSID_MAX_SIZE+2, 1); + if (err) + return err; + } else { /* AP */ + err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf, + IW_ESSID_MAX_SIZE+2, 1); + if (err) + return err; + } + + err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, + zd->dev->dev_addr, zd->dev->addr_len, 1); + if (err) + return err; + + err = zd1201_enable(zd); + if (err) + return err; + + msleep(100); + return 0; +} + +static int zd1201_net_open(struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + /* Start MAC with wildcard if no essid set */ + if (!zd->mac_enabled) + zd1201_join(zd, zd->essid, zd->essidlen); + netif_start_queue(dev); + + return 0; +} + +static int zd1201_net_stop(struct net_device *dev) +{ + netif_stop_queue(dev); + return 0; +} + +/* + RFC 1042 encapsulates Ethernet frames in 802.11 frames + by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0 + (0x00, 0x00, 0x00). Zd requires an additional padding, copy + of ethernet addresses, length of the standard RFC 1042 packet + and a command byte (which is nul for tx). + + tx frame (from Wlan NG): + RFC 1042: + llc 0xAA 0xAA 0x03 (802.2 LLC) + snap 0x00 0x00 0x00 (Ethernet encapsulated) + type 2 bytes, Ethernet type field + payload (minus eth header) + Zydas specific: + padding 1B if (skb->len+8+1)%64==0 + Eth MAC addr 12 bytes, Ethernet MAC addresses + length 2 bytes, RFC 1042 packet length + (llc+snap+type+payload) + zd 1 null byte, zd1201 packet type + */ +static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + unsigned char *txbuf = zd->txdata; + int txbuflen, pad = 0, err; + struct urb *urb = zd->tx_urb; + + if (!zd->mac_enabled || zd->monitor) { + zd->stats.tx_dropped++; + kfree_skb(skb); + return 0; + } + netif_stop_queue(dev); + + txbuflen = skb->len + 8 + 1; + if (txbuflen%64 == 0) { + pad = 1; + txbuflen++; + } + txbuf[0] = 0xAA; + txbuf[1] = 0xAA; + txbuf[2] = 0x03; + txbuf[3] = 0x00; /* rfc1042 */ + txbuf[4] = 0x00; + txbuf[5] = 0x00; + + memcpy(txbuf+6, skb->data+12, skb->len-12); + if (pad) + txbuf[skb->len-12+6]=0; + memcpy(txbuf+skb->len-12+6+pad, skb->data, 12); + *(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6); + txbuf[txbuflen-1] = 0; + + usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out), + txbuf, txbuflen, zd1201_usbtx, zd); + + err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC); + if (err) { + zd->stats.tx_errors++; + netif_start_queue(dev); + return err; + } + zd->stats.tx_packets++; + zd->stats.tx_bytes += skb->len; + dev->trans_start = jiffies; + kfree_skb(skb); + + return 0; +} + +static void zd1201_tx_timeout(struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + if (!zd) + return; + dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n", + dev->name); + usb_unlink_urb(zd->tx_urb); + zd->stats.tx_errors++; + /* Restart the timeout to quiet the watchdog: */ + dev->trans_start = jiffies; +} + +static int zd1201_set_mac_address(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + struct zd1201 *zd = (struct zd1201 *)dev->priv; + int err; + + if (!zd) + return -ENODEV; + + err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, + addr->sa_data, dev->addr_len, 1); + if (err) + return err; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + return zd1201_mac_reset(zd); +} + +static struct net_device_stats *zd1201_get_stats(struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + return &zd->stats; +} + +static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + return &zd->iwstats; +} + +static void zd1201_set_multicast(struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + struct dev_mc_list *mc = dev->mc_list; + unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; + int i; + + if (dev->mc_count > ZD1201_MAXMULTI) + return; + + for (i=0; imc_count; i++) { + memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN); + mc = mc->next; + } + zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, + dev->mc_count*ETH_ALEN, 0); + +} + +static int zd1201_config_commit(struct net_device *dev, + struct iw_request_info *info, struct iw_point *data, char *essid) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + return zd1201_mac_reset(zd); +} + +static int zd1201_get_name(struct net_device *dev, + struct iw_request_info *info, char *name, char *extra) +{ + strcpy(name, "IEEE 802.11b"); + return 0; +} + +static int zd1201_set_freq(struct net_device *dev, + struct iw_request_info *info, struct iw_freq *freq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short channel = 0; + int err; + + if (freq->e == 0) + channel = freq->m; + else { + if (freq->m >= 2482) + channel = 14; + if (freq->m >= 2407) + channel = (freq->m-2407)/5; + } + + err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel); + if (err) + return err; + + zd1201_mac_reset(zd); + + return 0; +} + +static int zd1201_get_freq(struct net_device *dev, + struct iw_request_info *info, struct iw_freq *freq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short channel; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel); + if (err) + return err; + freq->e = 0; + freq->m = channel; + + return 0; +} + +static int zd1201_set_mode(struct net_device *dev, + struct iw_request_info *info, __u32 *mode, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short porttype, monitor = 0; + unsigned char buffer[IW_ESSID_MAX_SIZE+2]; + int err; + + if (zd->ap) { + if (*mode != IW_MODE_MASTER) + return -EINVAL; + return 0; + } + + err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); + if (err) + return err; + zd->dev->type = ARPHRD_ETHER; + switch(*mode) { + case IW_MODE_MONITOR: + monitor = 1; + zd->dev->type = ARPHRD_IEEE80211; + /* Make sure we are no longer associated with by + setting an 'impossible' essid. + (otherwise we mess up firmware) + */ + zd1201_join(zd, "\0-*#\0", 5); + /* Put port in pIBSS */ + case 8: /* No pseudo-IBSS in wireless extensions (yet) */ + porttype = ZD1201_PORTTYPE_PSEUDOIBSS; + break; + case IW_MODE_ADHOC: + porttype = ZD1201_PORTTYPE_IBSS; + break; + case IW_MODE_INFRA: + porttype = ZD1201_PORTTYPE_BSS; + break; + default: + return -EINVAL; + } + + err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); + if (err) + return err; + if (zd->monitor && !monitor) { + zd1201_disable(zd); + *(__le16 *)buffer = cpu_to_le16(zd->essidlen); + memcpy(buffer+2, zd->essid, zd->essidlen); + err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, + buffer, IW_ESSID_MAX_SIZE+2, 1); + if (err) + return err; + } + zd->monitor = monitor; + /* If monitor mode is set we don't actually turn it on here since it + * is done during mac reset anyway (see zd1201_mac_enable). + */ + zd1201_mac_reset(zd); + + return 0; +} + +static int zd1201_get_mode(struct net_device *dev, + struct iw_request_info *info, __u32 *mode, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short porttype; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype); + if (err) + return err; + switch(porttype) { + case ZD1201_PORTTYPE_IBSS: + *mode = IW_MODE_ADHOC; + break; + case ZD1201_PORTTYPE_BSS: + *mode = IW_MODE_INFRA; + break; + case ZD1201_PORTTYPE_WDS: + *mode = IW_MODE_REPEAT; + break; + case ZD1201_PORTTYPE_PSEUDOIBSS: + *mode = 8;/* No Pseudo-IBSS... */ + break; + case ZD1201_PORTTYPE_AP: + *mode = IW_MODE_MASTER; + break; + default: + dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n", + porttype); + *mode = IW_MODE_AUTO; + } + if (zd->monitor) + *mode = IW_MODE_MONITOR; + + return 0; +} + +static int zd1201_get_range(struct net_device *dev, + struct iw_request_info *info, struct iw_point *wrq, char *extra) +{ + struct iw_range *range = (struct iw_range *)extra; + + wrq->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = WIRELESS_EXT; + + range->max_qual.qual = 128; + range->max_qual.level = 128; + range->max_qual.noise = 128; + range->max_qual.updated = 7; + + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + range->num_encoding_sizes = 2; + range->max_encoding_tokens = ZD1201_NUMKEYS; + + range->num_bitrates = 4; + range->bitrate[0] = 1000000; + range->bitrate[1] = 2000000; + range->bitrate[2] = 5500000; + range->bitrate[3] = 11000000; + + range->min_rts = 0; + range->min_frag = ZD1201_FRAGMIN; + range->max_rts = ZD1201_RTSMAX; + range->min_frag = ZD1201_FRAGMAX; + + return 0; +} + +/* Little bit of magic here: we only get the quality if we poll + * for it, and we never get an actual request to trigger such + * a poll. Therefore we 'assume' that the user will soon ask for + * the stats after asking the bssid. + */ +static int zd1201_get_wap(struct net_device *dev, + struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + unsigned char buffer[6]; + + if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) { + /* Unfortunately the quality and noise reported is useless. + they seem to be accumulators that increase until you + read them, unless we poll on a fixed interval we can't + use them + */ + /*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/ + zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]); + /*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/ + zd->iwstats.qual.updated = 2; + } + + return zd1201_getconfig(zd, ZD1201_RID_CURRENTBSSID, ap_addr->sa_data, 6); +} + +static int zd1201_set_scan(struct net_device *dev, + struct iw_request_info *info, struct iw_point *srq, char *extra) +{ + /* We do everything in get_scan */ + return 0; +} + +static int zd1201_get_scan(struct net_device *dev, + struct iw_request_info *info, struct iw_point *srq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + int err, i, j, enabled_save; + struct iw_event iwe; + char *cev = extra; + char *end_buf = extra + IW_SCAN_MAX_DATA; + + /* No scanning in AP mode */ + if (zd->ap) + return -EOPNOTSUPP; + + /* Scan doesn't seem to work if disabled */ + enabled_save = zd->mac_enabled; + zd1201_enable(zd); + + zd->rxdatas = 0; + err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, + ZD1201_INQ_SCANRESULTS, 0, 0); + if (err) + return err; + + wait_event_interruptible(zd->rxdataq, zd->rxdatas); + if (!zd->rxlen) + return -EIO; + + if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS) + return -EIO; + + for(i=8; irxlen; i+=62) { + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); + + iwe.cmd = SIOCGIWESSID; + iwe.u.data.length = zd->rxdata[i+16]; + iwe.u.data.flags = 1; + cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18); + + iwe.cmd = SIOCGIWMODE; + if (zd->rxdata[i+14]&0x01) + iwe.u.mode = IW_MODE_MASTER; + else + iwe.u.mode = IW_MODE_ADHOC; + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); + + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = zd->rxdata[i+0]; + iwe.u.freq.e = 0; + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); + + iwe.cmd = SIOCGIWRATE; + iwe.u.bitrate.fixed = 0; + iwe.u.bitrate.disabled = 0; + for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) { + iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000; + cev=iwe_stream_add_event(cev, end_buf, &iwe, + IW_EV_PARAM_LEN); + } + + iwe.cmd = SIOCGIWENCODE; + iwe.u.data.length = 0; + if (zd->rxdata[i+14]&0x10) + iwe.u.data.flags = IW_ENCODE_ENABLED; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); + + iwe.cmd = IWEVQUAL; + iwe.u.qual.qual = zd->rxdata[i+4]; + iwe.u.qual.noise= zd->rxdata[i+2]/10-100; + iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100; + iwe.u.qual.updated = 7; + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); + } + + if (!enabled_save) + zd1201_disable(zd); + + srq->length = cev - extra; + srq->flags = 0; + + return 0; +} + +static int zd1201_set_essid(struct net_device *dev, + struct iw_request_info *info, struct iw_point *data, char *essid) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + if (data->length > IW_ESSID_MAX_SIZE) + return -EINVAL; + if (data->length < 1) + data->length = 1; + zd->essidlen = data->length-1; + memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1); + memcpy(zd->essid, essid, data->length); + return zd1201_join(zd, zd->essid, zd->essidlen); +} + +static int zd1201_get_essid(struct net_device *dev, + struct iw_request_info *info, struct iw_point *data, char *essid) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + memcpy(essid, zd->essid, zd->essidlen); + data->flags = 1; + data->length = zd->essidlen; + + return 0; +} + +static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info, + struct iw_point *data, char *nick) +{ + strcpy(nick, "zd1201"); + data->flags = 1; + data->length = strlen(nick); + return 0; +} + +static int zd1201_set_rate(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short rate; + int err; + + switch (rrq->value) { + case 1000000: + rate = ZD1201_RATEB1; + break; + case 2000000: + rate = ZD1201_RATEB2; + break; + case 5500000: + rate = ZD1201_RATEB5; + break; + case 11000000: + default: + rate = ZD1201_RATEB11; + break; + } + if (!rrq->fixed) { /* Also enable all lower bitrates */ + rate |= rate-1; + } + + err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate); + if (err) + return err; + + return zd1201_mac_reset(zd); +} + +static int zd1201_get_rate(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short rate; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate); + if (err) + return err; + + switch(rate) { + case 1: + rrq->value = 1000000; + break; + case 2: + rrq->value = 2000000; + break; + case 5: + rrq->value = 5500000; + break; + case 11: + rrq->value = 11000000; + break; + default: + rrq->value = 0; + } + rrq->fixed = 0; + rrq->disabled = 0; + + return 0; +} + +static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + int err; + short val = rts->value; + + if (rts->disabled || !rts->fixed) + val = ZD1201_RTSMAX; + if (val > ZD1201_RTSMAX) + return -EINVAL; + if (val < 0) + return -EINVAL; + + err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val); + if (err) + return err; + return zd1201_mac_reset(zd); +} + +static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short rtst; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst); + if (err) + return err; + rts->value = rtst; + rts->disabled = (rts->value == ZD1201_RTSMAX); + rts->fixed = 1; + + return 0; +} + +static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + int err; + short val = frag->value; + + if (frag->disabled || !frag->fixed) + val = ZD1201_FRAGMAX; + if (val > ZD1201_FRAGMAX) + return -EINVAL; + if (val < ZD1201_FRAGMIN) + return -EINVAL; + if (val & 1) + return -EINVAL; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val); + if (err) + return err; + return zd1201_mac_reset(zd); +} + +static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short fragt; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt); + if (err) + return err; + frag->value = fragt; + frag->disabled = (frag->value == ZD1201_FRAGMAX); + frag->fixed = 1; + + return 0; +} + +static int zd1201_set_retry(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + return 0; +} + +static int zd1201_get_retry(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + return 0; +} + +static int zd1201_set_encode(struct net_device *dev, + struct iw_request_info *info, struct iw_point *erq, char *key) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short i; + int err, rid; + + if (erq->length > ZD1201_MAXKEYLEN) + return -EINVAL; + + i = (erq->flags & IW_ENCODE_INDEX)-1; + if (i == -1) { + err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i); + if (err) + return err; + } else { + err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i); + if (err) + return err; + } + + if (i < 0 || i >= ZD1201_NUMKEYS) + return -EINVAL; + + rid = ZD1201_RID_CNFDEFAULTKEY0 + i; + err = zd1201_setconfig(zd, rid, key, erq->length, 1); + if (err) + return err; + zd->encode_keylen[i] = erq->length; + memcpy(zd->encode_keys[i], key, erq->length); + + i=0; + if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) { + i |= 0x01; + zd->encode_enabled = 1; + } else + zd->encode_enabled = 0; + if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) { + i |= 0x02; + zd->encode_restricted = 1; + } else + zd->encode_restricted = 0; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i); + if (err) + return err; + + if (zd->encode_enabled) + i = ZD1201_CNFAUTHENTICATION_SHAREDKEY; + else + i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i); + if (err) + return err; + + return zd1201_mac_reset(zd); +} + +static int zd1201_get_encode(struct net_device *dev, + struct iw_request_info *info, struct iw_point *erq, char *key) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short i; + int err; + + if (zd->encode_enabled) + erq->flags = IW_ENCODE_ENABLED; + else + erq->flags = IW_ENCODE_DISABLED; + if (zd->encode_restricted) + erq->flags |= IW_ENCODE_RESTRICTED; + else + erq->flags |= IW_ENCODE_OPEN; + + i = (erq->flags & IW_ENCODE_INDEX) -1; + if (i == -1) { + err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i); + if (err) + return err; + } + if (i<0 || i>= ZD1201_NUMKEYS) + return -EINVAL; + + erq->flags |= i+1; + + erq->length = zd->encode_keylen[i]; + memcpy(key, zd->encode_keys[i], erq->length); + + return 0; +} + +static int zd1201_set_power(struct net_device *dev, + struct iw_request_info *info, struct iw_param *vwrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short enabled, duration, level; + int err; + + enabled = vwrq->disabled ? 0 : 1; + if (enabled) { + if (vwrq->flags & IW_POWER_PERIOD) { + duration = vwrq->value; + err = zd1201_setconfig16(zd, + ZD1201_RID_CNFMAXSLEEPDURATION, duration); + if (err) + return err; + goto out; + } + if (vwrq->flags & IW_POWER_TIMEOUT) { + err = zd1201_getconfig16(zd, + ZD1201_RID_CNFMAXSLEEPDURATION, &duration); + if (err) + return err; + level = vwrq->value * 4 / duration; + if (level > 4) + level = 4; + if (level < 0) + level = 0; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS, + level); + if (err) + return err; + goto out; + } + return -EINVAL; + } +out: + return zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled); +} + +static int zd1201_get_power(struct net_device *dev, + struct iw_request_info *info, struct iw_param *vwrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short enabled, level, duration; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled); + if (err) + return err; + err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level); + if (err) + return err; + err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration); + if (err) + return err; + vwrq->disabled = enabled ? 0 : 1; + if (vwrq->flags & IW_POWER_TYPE) { + if (vwrq->flags & IW_POWER_PERIOD) { + vwrq->value = duration; + vwrq->flags = IW_POWER_PERIOD; + } else { + vwrq->value = duration * level / 4; + vwrq->flags = IW_POWER_TIMEOUT; + } + } + if (vwrq->flags & IW_POWER_MODE) { + if (enabled && level) + vwrq->flags = IW_POWER_UNICAST_R; + else + vwrq->flags = IW_POWER_ALL_R; + } + + return 0; +} + + +static const iw_handler zd1201_iw_handler[] = +{ + (iw_handler) zd1201_config_commit, /* SIOCSIWCOMMIT */ + (iw_handler) zd1201_get_name, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) zd1201_set_freq, /* SIOCSIWFREQ */ + (iw_handler) zd1201_get_freq, /* SIOCGIWFREQ */ + (iw_handler) zd1201_set_mode, /* SIOCSIWMODE */ + (iw_handler) zd1201_get_mode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL, /* SIOCSIWRANGE */ + (iw_handler) zd1201_get_range, /* SIOCGIWRANGE */ + (iw_handler) NULL, /* SIOCSIWPRIV */ + (iw_handler) NULL, /* SIOCGIWPRIV */ + (iw_handler) NULL, /* SIOCSIWSTATS */ + (iw_handler) NULL, /* SIOCGIWSTATS */ + (iw_handler) NULL, /* SIOCSIWSPY */ + (iw_handler) NULL, /* SIOCGIWSPY */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL/*zd1201_set_wap*/, /* SIOCSIWAP */ + (iw_handler) zd1201_get_wap, /* SIOCGIWAP */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCGIWAPLIST */ + (iw_handler) zd1201_set_scan, /* SIOCSIWSCAN */ + (iw_handler) zd1201_get_scan, /* SIOCGIWSCAN */ + (iw_handler) zd1201_set_essid, /* SIOCSIWESSID */ + (iw_handler) zd1201_get_essid, /* SIOCGIWESSID */ + (iw_handler) NULL, /* SIOCSIWNICKN */ + (iw_handler) zd1201_get_nick, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) zd1201_set_rate, /* SIOCSIWRATE */ + (iw_handler) zd1201_get_rate, /* SIOCGIWRATE */ + (iw_handler) zd1201_set_rts, /* SIOCSIWRTS */ + (iw_handler) zd1201_get_rts, /* SIOCGIWRTS */ + (iw_handler) zd1201_set_frag, /* SIOCSIWFRAG */ + (iw_handler) zd1201_get_frag, /* SIOCGIWFRAG */ + (iw_handler) NULL, /* SIOCSIWTXPOW */ + (iw_handler) NULL, /* SIOCGIWTXPOW */ + (iw_handler) zd1201_set_retry, /* SIOCSIWRETRY */ + (iw_handler) zd1201_get_retry, /* SIOCGIWRETRY */ + (iw_handler) zd1201_set_encode, /* SIOCSIWENCODE */ + (iw_handler) zd1201_get_encode, /* SIOCGIWENCODE */ + (iw_handler) zd1201_set_power, /* SIOCSIWPOWER */ + (iw_handler) zd1201_get_power, /* SIOCGIWPOWER */ +}; + +static int zd1201_set_hostauth(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + if (!zd->ap) + return -EOPNOTSUPP; + + return zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value); +} + +static int zd1201_get_hostauth(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short hostauth; + int err; + + if (!zd->ap) + return -EOPNOTSUPP; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth); + if (err) + return err; + rrq->value = hostauth; + rrq->fixed = 1; + + return 0; +} + +static int zd1201_auth_sta(struct net_device *dev, + struct iw_request_info *info, struct sockaddr *sta, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + unsigned char buffer[10]; + + if (!zd->ap) + return -EOPNOTSUPP; + + memcpy(buffer, sta->sa_data, ETH_ALEN); + *(short*)(buffer+6) = 0; /* 0==success, 1==failure */ + *(short*)(buffer+8) = 0; + + return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1); +} + +static int zd1201_set_maxassoc(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + int err; + + if (!zd->ap) + return -EOPNOTSUPP; + + err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value); + if (err) + return err; + return 0; +} + +static int zd1201_get_maxassoc(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short maxassoc; + int err; + + if (!zd->ap) + return -EOPNOTSUPP; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc); + if (err) + return err; + rrq->value = maxassoc; + rrq->fixed = 1; + + return 0; +} + +static const iw_handler zd1201_private_handler[] = { + (iw_handler) zd1201_set_hostauth, /* ZD1201SIWHOSTAUTH */ + (iw_handler) zd1201_get_hostauth, /* ZD1201GIWHOSTAUTH */ + (iw_handler) zd1201_auth_sta, /* ZD1201SIWAUTHSTA */ + (iw_handler) NULL, /* nothing to get */ + (iw_handler) zd1201_set_maxassoc, /* ZD1201SIMAXASSOC */ + (iw_handler) zd1201_get_maxassoc, /* ZD1201GIMAXASSOC */ +}; + +static const struct iw_priv_args zd1201_private_args[] = { + { ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_NONE, "sethostauth" }, + { ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" }, + { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_NONE, "authstation" }, + { ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_NONE, "setmaxassoc" }, + { ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" }, +}; + +static const struct iw_handler_def zd1201_iw_handlers = { + .num_standard = ARRAY_SIZE(zd1201_iw_handler), + .num_private = ARRAY_SIZE(zd1201_private_handler), + .num_private_args = ARRAY_SIZE(zd1201_private_args), + .standard = (iw_handler *)zd1201_iw_handler, + .private = (iw_handler *)zd1201_private_handler, + .private_args = (struct iw_priv_args *) zd1201_private_args, + .get_wireless_stats = zd1201_get_wireless_stats, +}; + +static int zd1201_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct zd1201 *zd; + struct usb_device *usb; + int err; + short porttype; + char buf[IW_ESSID_MAX_SIZE+2]; + + usb = interface_to_usbdev(interface); + + zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL); + if (!zd) + return -ENOMEM; + zd->ap = ap; + zd->usb = usb; + zd->removed = 0; + init_waitqueue_head(&zd->rxdataq); + INIT_HLIST_HEAD(&zd->fraglist); + + err = zd1201_fw_upload(usb, zd->ap); + if (err) { + dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err); + goto err_zd; + } + + zd->endp_in = 1; + zd->endp_out = 1; + zd->endp_out2 = 2; + zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL); + zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!zd->rx_urb || !zd->tx_urb) + goto err_zd; + + mdelay(100); + err = zd1201_drvr_start(zd); + if (err) + goto err_zd; + + err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312); + if (err) + goto err_start; + + err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, + ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11); + if (err) + goto err_start; + + zd->dev = alloc_etherdev(0); + if (!zd->dev) + goto err_start; + + zd->dev->priv = zd; + zd->dev->open = zd1201_net_open; + zd->dev->stop = zd1201_net_stop; + zd->dev->get_stats = zd1201_get_stats; + zd->dev->wireless_handlers = + (struct iw_handler_def *)&zd1201_iw_handlers; + zd->dev->hard_start_xmit = zd1201_hard_start_xmit; + zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT; + zd->dev->tx_timeout = zd1201_tx_timeout; + zd->dev->set_multicast_list = zd1201_set_multicast; + zd->dev->set_mac_address = zd1201_set_mac_address; + strcpy(zd->dev->name, "wlan%d"); + + err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, + zd->dev->dev_addr, zd->dev->addr_len); + if (err) + goto err_net; + + /* Set wildcard essid to match zd->essid */ + *(__le16 *)buf = cpu_to_le16(0); + err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, + IW_ESSID_MAX_SIZE+2, 1); + if (err) + goto err_net; + + if (zd->ap) + porttype = ZD1201_PORTTYPE_AP; + else + porttype = ZD1201_PORTTYPE_BSS; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); + if (err) + goto err_net; + + SET_NETDEV_DEV(zd->dev, &usb->dev); + + err = register_netdev(zd->dev); + if (err) + goto err_net; + dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n", + zd->dev->name); + + usb_set_intfdata(interface, zd); + return 0; + +err_net: + free_netdev(zd->dev); +err_start: + /* Leave the device in reset state */ + zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); +err_zd: + if (zd->tx_urb) + usb_free_urb(zd->tx_urb); + if (zd->rx_urb) + usb_free_urb(zd->rx_urb); + kfree(zd); + return err; +} + +static void zd1201_disconnect(struct usb_interface *interface) +{ + struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface); + struct hlist_node *node, *node2; + struct zd1201_frag *frag; + + if (!zd) + return; + usb_set_intfdata(interface, NULL); + if (zd->dev) { + unregister_netdev(zd->dev); + free_netdev(zd->dev); + } + + hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) { + hlist_del_init(&frag->fnode); + kfree_skb(frag->skb); + kfree(frag); + } + + if (zd->tx_urb) { + usb_kill_urb(zd->tx_urb); + usb_free_urb(zd->tx_urb); + } + if (zd->rx_urb) { + usb_kill_urb(zd->rx_urb); + usb_free_urb(zd->rx_urb); + } + kfree(zd); +} + +#ifdef CONFIG_PM + +static int zd1201_suspend(struct usb_interface *interface, + pm_message_t message) +{ + struct zd1201 *zd = usb_get_intfdata(interface); + + netif_device_detach(zd->dev); + + zd->was_enabled = zd->mac_enabled; + + if (zd->was_enabled) + return zd1201_disable(zd); + else + return 0; +} + +static int zd1201_resume(struct usb_interface *interface) +{ + struct zd1201 *zd = usb_get_intfdata(interface); + + if (!zd || !zd->dev) + return -ENODEV; + + netif_device_attach(zd->dev); + + if (zd->was_enabled) + return zd1201_enable(zd); + else + return 0; +} + +#else + +#define zd1201_suspend NULL +#define zd1201_resume NULL + +#endif + +static struct usb_driver zd1201_usb = { + .name = "zd1201", + .probe = zd1201_probe, + .disconnect = zd1201_disconnect, + .id_table = zd1201_table, + .suspend = zd1201_suspend, + .resume = zd1201_resume, +}; + +static int __init zd1201_init(void) +{ + return usb_register(&zd1201_usb); +} + +static void __exit zd1201_cleanup(void) +{ + usb_deregister(&zd1201_usb); +} + +module_init(zd1201_init); +module_exit(zd1201_cleanup); diff --git a/drivers/net/wireless/zd1201.h b/drivers/net/wireless/zd1201.h new file mode 100644 index 0000000..235f0ee --- /dev/null +++ b/drivers/net/wireless/zd1201.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * Parts of this driver have been derived from a wlan-ng version + * modified by ZyDAS. + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + */ + +#ifndef _INCLUDE_ZD1201_H_ +#define _INCLUDE_ZD1201_H_ + +#define ZD1201_NUMKEYS 4 +#define ZD1201_MAXKEYLEN 13 +#define ZD1201_MAXMULTI 16 +#define ZD1201_FRAGMAX 2500 +#define ZD1201_FRAGMIN 256 +#define ZD1201_RTSMAX 2500 + +#define ZD1201_RXSIZE 3000 + +struct zd1201 { + struct usb_device *usb; + int removed; + struct net_device *dev; + struct net_device_stats stats; + struct iw_statistics iwstats; + + int endp_in; + int endp_out; + int endp_out2; + struct urb *rx_urb; + struct urb *tx_urb; + + unsigned char rxdata[ZD1201_RXSIZE]; + int rxlen; + wait_queue_head_t rxdataq; + int rxdatas; + struct hlist_head fraglist; + unsigned char txdata[ZD1201_RXSIZE]; + + int ap; + char essid[IW_ESSID_MAX_SIZE+1]; + int essidlen; + int mac_enabled; + int was_enabled; + int monitor; + int encode_enabled; + int encode_restricted; + unsigned char encode_keys[ZD1201_NUMKEYS][ZD1201_MAXKEYLEN]; + int encode_keylen[ZD1201_NUMKEYS]; +}; + +struct zd1201_frag { + struct hlist_node fnode; + int seq; + struct sk_buff *skb; +}; + +#define ZD1201SIWHOSTAUTH SIOCIWFIRSTPRIV +#define ZD1201GIWHOSTAUTH ZD1201SIWHOSTAUTH+1 +#define ZD1201SIWAUTHSTA SIOCIWFIRSTPRIV+2 +#define ZD1201SIWMAXASSOC SIOCIWFIRSTPRIV+4 +#define ZD1201GIWMAXASSOC ZD1201SIWMAXASSOC+1 + +#define ZD1201_FW_TIMEOUT (1000) + +#define ZD1201_TX_TIMEOUT (2000) + +#define ZD1201_USB_CMDREQ 0 +#define ZD1201_USB_RESREQ 1 + +#define ZD1201_CMDCODE_INIT 0x00 +#define ZD1201_CMDCODE_ENABLE 0x01 +#define ZD1201_CMDCODE_DISABLE 0x02 +#define ZD1201_CMDCODE_ALLOC 0x0a +#define ZD1201_CMDCODE_INQUIRE 0x11 +#define ZD1201_CMDCODE_SETRXRID 0x17 +#define ZD1201_CMDCODE_ACCESS 0x21 + +#define ZD1201_PACKET_EVENTSTAT 0x0 +#define ZD1201_PACKET_RXDATA 0x1 +#define ZD1201_PACKET_INQUIRE 0x2 +#define ZD1201_PACKET_RESOURCE 0x3 + +#define ZD1201_ACCESSBIT 0x0100 + +#define ZD1201_RID_CNFPORTTYPE 0xfc00 +#define ZD1201_RID_CNFOWNMACADDR 0xfc01 +#define ZD1201_RID_CNFDESIREDSSID 0xfc02 +#define ZD1201_RID_CNFOWNCHANNEL 0xfc03 +#define ZD1201_RID_CNFOWNSSID 0xfc04 +#define ZD1201_RID_CNFMAXDATALEN 0xfc07 +#define ZD1201_RID_CNFPMENABLED 0xfc09 +#define ZD1201_RID_CNFPMEPS 0xfc0a +#define ZD1201_RID_CNFMAXSLEEPDURATION 0xfc0c +#define ZD1201_RID_CNFDEFAULTKEYID 0xfc23 +#define ZD1201_RID_CNFDEFAULTKEY0 0xfc24 +#define ZD1201_RID_CNFDEFAULTKEY1 0xfc25 +#define ZD1201_RID_CNFDEFAULTKEY2 0xfc26 +#define ZD1201_RID_CNFDEFAULTKEY3 0xfc27 +#define ZD1201_RID_CNFWEBFLAGS 0xfc28 +#define ZD1201_RID_CNFAUTHENTICATION 0xfc2a +#define ZD1201_RID_CNFMAXASSOCSTATIONS 0xfc2b +#define ZD1201_RID_CNFHOSTAUTH 0xfc2e +#define ZD1201_RID_CNFGROUPADDRESS 0xfc80 +#define ZD1201_RID_CNFFRAGTHRESHOLD 0xfc82 +#define ZD1201_RID_CNFRTSTHRESHOLD 0xfc83 +#define ZD1201_RID_TXRATECNTL 0xfc84 +#define ZD1201_RID_PROMISCUOUSMODE 0xfc85 +#define ZD1201_RID_CNFBASICRATES 0xfcb3 +#define ZD1201_RID_AUTHENTICATESTA 0xfce3 +#define ZD1201_RID_CURRENTBSSID 0xfd42 +#define ZD1201_RID_COMMSQUALITY 0xfd43 +#define ZD1201_RID_CURRENTTXRATE 0xfd44 +#define ZD1201_RID_CNFMAXTXBUFFERNUMBER 0xfda0 +#define ZD1201_RID_CURRENTCHANNEL 0xfdc1 + +#define ZD1201_INQ_SCANRESULTS 0xf101 + +#define ZD1201_INF_LINKSTATUS 0xf200 +#define ZD1201_INF_ASSOCSTATUS 0xf201 +#define ZD1201_INF_AUTHREQ 0xf202 + +#define ZD1201_ASSOCSTATUS_STAASSOC 0x1 +#define ZD1201_ASSOCSTATUS_REASSOC 0x2 +#define ZD1201_ASSOCSTATUS_DISASSOC 0x3 +#define ZD1201_ASSOCSTATUS_ASSOCFAIL 0x4 +#define ZD1201_ASSOCSTATUS_AUTHFAIL 0x5 + +#define ZD1201_PORTTYPE_IBSS 0 +#define ZD1201_PORTTYPE_BSS 1 +#define ZD1201_PORTTYPE_WDS 2 +#define ZD1201_PORTTYPE_PSEUDOIBSS 3 +#define ZD1201_PORTTYPE_AP 6 + +#define ZD1201_RATEB1 1 +#define ZD1201_RATEB2 2 +#define ZD1201_RATEB5 4 /* 5.5 really, but 5 is shorter :) */ +#define ZD1201_RATEB11 8 + +#define ZD1201_CNFAUTHENTICATION_OPENSYSTEM 0x0001 +#define ZD1201_CNFAUTHENTICATION_SHAREDKEY 0x0002 + +#endif /* _INCLUDE_ZD1201_H_ */ diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index fd0f43b..ecec8e5 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -862,13 +862,11 @@ static int yellowfin_start_xmit(struct s /* Fix GX chipset errata. */ if (cacheline_end > 24 || cacheline_end == 0) { len = skb->len + 32 - cacheline_end + 1; - if (len != skb->len) - skb = skb_padto(skb, len); - } - if (skb == NULL) { - yp->tx_skbuff[entry] = NULL; - netif_wake_queue(dev); - return 0; + if (skb_padto(skb, len)) { + yp->tx_skbuff[entry] = NULL; + netif_wake_queue(dev); + return 0; + } } } yp->tx_skbuff[entry] = skb; diff --git a/drivers/net/znet.c b/drivers/net/znet.c index 3ac047b..a7c089d 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -544,8 +544,7 @@ static int znet_send_packet(struct sk_bu printk(KERN_DEBUG "%s: ZNet_send_packet.\n", dev->name); if (length < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) return 0; length = ETH_ZLEN; } diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index b2e8e49..43e521e 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -108,10 +108,10 @@ #ifdef CONFIG_MODULES return 0; /* FIXME: should we process all CPU buffers ? */ - down(&buffer_sem); + mutex_lock(&buffer_mutex); add_event_entry(ESCAPE_CODE); add_event_entry(MODULE_LOADED_CODE); - up(&buffer_sem); + mutex_unlock(&buffer_mutex); #endif return 0; } @@ -501,7 +501,7 @@ void sync_buffer(int cpu) sync_buffer_state state = sb_buffer_start; unsigned long available; - down(&buffer_sem); + mutex_lock(&buffer_mutex); add_cpu_switch(cpu); @@ -550,5 +550,5 @@ void sync_buffer(int cpu) mark_done(cpu); - up(&buffer_sem); + mutex_unlock(&buffer_mutex); } diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c index b80318f..04d6417 100644 --- a/drivers/oprofile/event_buffer.c +++ b/drivers/oprofile/event_buffer.c @@ -24,7 +24,7 @@ #include "oprof.h" #include "event_buffer.h" #include "oprofile_stats.h" -DECLARE_MUTEX(buffer_sem); +DEFINE_MUTEX(buffer_mutex); static unsigned long buffer_opened; static DECLARE_WAIT_QUEUE_HEAD(buffer_wait); @@ -32,7 +32,7 @@ static unsigned long * event_buffer; static unsigned long buffer_size; static unsigned long buffer_watershed; static size_t buffer_pos; -/* atomic_t because wait_event checks it outside of buffer_sem */ +/* atomic_t because wait_event checks it outside of buffer_mutex */ static atomic_t buffer_ready = ATOMIC_INIT(0); /* Add an entry to the event buffer. When we @@ -60,10 +60,10 @@ void add_event_entry(unsigned long value */ void wake_up_buffer_waiter(void) { - down(&buffer_sem); + mutex_lock(&buffer_mutex); atomic_set(&buffer_ready, 1); wake_up(&buffer_wait); - up(&buffer_sem); + mutex_unlock(&buffer_mutex); } @@ -162,7 +162,7 @@ static ssize_t event_buffer_read(struct if (!atomic_read(&buffer_ready)) return -EAGAIN; - down(&buffer_sem); + mutex_lock(&buffer_mutex); atomic_set(&buffer_ready, 0); @@ -177,7 +177,7 @@ static ssize_t event_buffer_read(struct buffer_pos = 0; out: - up(&buffer_sem); + mutex_unlock(&buffer_mutex); return retval; } diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h index 0180236..9241627 100644 --- a/drivers/oprofile/event_buffer.h +++ b/drivers/oprofile/event_buffer.h @@ -11,7 +11,7 @@ #ifndef EVENT_BUFFER_H #define EVENT_BUFFER_H #include -#include +#include int alloc_event_buffer(void); @@ -46,6 +46,6 @@ extern struct file_operations event_buff /* mutex between sync_cpu_buffers() and the * file reading code. */ -extern struct semaphore buffer_sem; +extern struct mutex buffer_mutex; #endif /* EVENT_BUFFER_H */ diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index b3f1cd6..e5162a6 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c @@ -12,7 +12,7 @@ #include #include #include #include -#include +#include #include "oprof.h" #include "event_buffer.h" @@ -25,7 +25,7 @@ struct oprofile_operations oprofile_ops; unsigned long oprofile_started; unsigned long backtrace_depth; static unsigned long is_setup; -static DECLARE_MUTEX(start_sem); +static DEFINE_MUTEX(start_mutex); /* timer 0 - use performance monitoring hardware if available @@ -37,7 +37,7 @@ int oprofile_setup(void) { int err; - down(&start_sem); + mutex_lock(&start_mutex); if ((err = alloc_cpu_buffers())) goto out; @@ -57,7 +57,7 @@ int oprofile_setup(void) goto out3; is_setup = 1; - up(&start_sem); + mutex_unlock(&start_mutex); return 0; out3: @@ -68,7 +68,7 @@ out2: out1: free_cpu_buffers(); out: - up(&start_sem); + mutex_unlock(&start_mutex); return err; } @@ -78,7 +78,7 @@ int oprofile_start(void) { int err = -EINVAL; - down(&start_sem); + mutex_lock(&start_mutex); if (!is_setup) goto out; @@ -95,7 +95,7 @@ int oprofile_start(void) oprofile_started = 1; out: - up(&start_sem); + mutex_unlock(&start_mutex); return err; } @@ -103,7 +103,7 @@ out: /* echo 0>/dev/oprofile/enable */ void oprofile_stop(void) { - down(&start_sem); + mutex_lock(&start_mutex); if (!oprofile_started) goto out; oprofile_ops.stop(); @@ -111,20 +111,20 @@ void oprofile_stop(void) /* wake up the daemon to read what remains */ wake_up_buffer_waiter(); out: - up(&start_sem); + mutex_unlock(&start_mutex); } void oprofile_shutdown(void) { - down(&start_sem); + mutex_lock(&start_mutex); sync_stop(); if (oprofile_ops.shutdown) oprofile_ops.shutdown(); is_setup = 0; free_event_buffer(); free_cpu_buffers(); - up(&start_sem); + mutex_unlock(&start_mutex); } @@ -132,7 +132,7 @@ int oprofile_set_backtrace(unsigned long { int err = 0; - down(&start_sem); + mutex_lock(&start_mutex); if (oprofile_started) { err = -EBUSY; @@ -147,7 +147,7 @@ int oprofile_set_backtrace(unsigned long backtrace_depth = val; out: - up(&start_sem); + mutex_unlock(&start_mutex); return err; } diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index b62da9b..71c2da2 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c @@ -272,10 +272,10 @@ static int oprofilefs_fill_super(struct } -static struct super_block *oprofilefs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int oprofilefs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, oprofilefs_fill_super); + return get_sb_single(fs_type, flags, data, oprofilefs_fill_super, mnt); } diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index f63c387..c7fa28a 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig @@ -48,7 +48,7 @@ config PARPORT_PC config PARPORT_SERIAL tristate "Multi-IO cards (parallel and serial)" - depends on SERIAL_8250 && PARPORT_PC && PCI + depends on SERIAL_8250_PCI && PARPORT_PC && PCI help This adds support for multi-IO PCI cards that have parallel and serial ports. You should say Y or M here. If you say M, the module @@ -85,11 +85,6 @@ config PARPORT_PC_PCMCIA config PARPORT_NOT_PC bool -config PARPORT_ARC - tristate "Archimedes hardware" - depends on ARM && PARPORT - select PARPORT_NOT_PC - config PARPORT_IP32 tristate "SGI IP32 builtin port (EXPERIMENTAL)" depends on SGI_IP32 && PARPORT && EXPERIMENTAL @@ -141,6 +136,18 @@ config PARPORT_SUNBPP found on many Sun machines. Note that many of the newer Ultras actually have pc style hardware instead. +config PARPORT_AX88796 + tristate "AX88796 Parallel Port" + depends on PARPORT + select PARPORT_NOT_PC + help + Say Y here if you need support for the parallel port hardware on + the AX88796 network controller chip. This code is also available + as a module (say M), called parport_ax88796. + + The driver is not dependant on the AX88796 network driver, and + should not interfere with the networking functions of the chip. + config PARPORT_1284 bool "IEEE 1284 transfer modes" depends on PARPORT diff --git a/drivers/parport/Makefile b/drivers/parport/Makefile index a19de35..696b8d4 100644 --- a/drivers/parport/Makefile +++ b/drivers/parport/Makefile @@ -17,4 +17,5 @@ obj-$(CONFIG_PARPORT_MFC3) += parport_mf obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o -obj-$(CONFIG_PARPORT_IP32) += parport_ip32.o +obj-$(CONFIG_PARPORT_AX88796) += parport_ax88796.o +obj-$(CONFIG_PARPORT_IP32) += parport_ip32.o \ No newline at end of file diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c index 9ee6732..fd41e28 100644 --- a/drivers/parport/daisy.c +++ b/drivers/parport/daisy.c @@ -283,7 +283,7 @@ void parport_close (struct pardevice *de * * This tries to locate a device on the given parallel port, * multiplexor port and daisy chain address, and returns its - * device number or -NXIO if no device with those coordinates + * device number or %-ENXIO if no device with those coordinates * exists. **/ diff --git a/drivers/parport/parport_arc.c b/drivers/parport/parport_arc.c deleted file mode 100644 index b35bb4f..0000000 --- a/drivers/parport/parport_arc.c +++ /dev/null @@ -1,139 +0,0 @@ -/* Low-level parallel port routines for Archimedes onboard hardware - * - * Author: Phil Blundell - */ - -/* This driver is for the parallel port hardware found on Acorn's old - * range of Archimedes machines. The A5000 and newer systems have PC-style - * I/O hardware and should use the parport_pc driver instead. - * - * The Acorn printer port hardware is very simple. There is a single 8-bit - * write-only latch for the data port and control/status bits are handled - * with various auxilliary input and output lines. The port is not - * bidirectional, does not support any modes other than SPP, and has only - * a subset of the standard printer control lines connected. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define DATA_ADDRESS 0x3350010 - -/* This is equivalent to the above and only used for request_region. */ -#define PORT_BASE 0x80000000 | ((DATA_ADDRESS - IO_BASE) >> 2) - -/* The hardware can't read from the data latch, so we must use a soft - copy. */ -static unsigned char data_copy; - -/* These are pretty simple. We know the irq is never shared and the - kernel does all the magic that's required. */ -static void arc_enable_irq(struct parport *p) -{ - enable_irq(p->irq); -} - -static void arc_disable_irq(struct parport *p) -{ - disable_irq(p->irq); -} - -static void arc_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - parport_generic_irq(irq, (struct parport *) dev_id, regs); -} - -static void arc_write_data(struct parport *p, unsigned char data) -{ - data_copy = data; - outb_t(data, DATA_LATCH); -} - -static unsigned char arc_read_data(struct parport *p) -{ - return data_copy; -} - -static struct parport_operations parport_arc_ops = -{ - .write_data = arc_write_data, - .read_data = arc_read_data, - - .write_control = arc_write_control, - .read_control = arc_read_control, - .frob_control = arc_frob_control, - - .read_status = arc_read_status, - - .enable_irq = arc_enable_irq, - .disable_irq = arc_disable_irq, - - .data_forward = arc_data_forward, - .data_reverse = arc_data_reverse, - - .init_state = arc_init_state, - .save_state = arc_save_state, - .restore_state = arc_restore_state, - - .epp_write_data = parport_ieee1284_epp_write_data, - .epp_read_data = parport_ieee1284_epp_read_data, - .epp_write_addr = parport_ieee1284_epp_write_addr, - .epp_read_addr = parport_ieee1284_epp_read_addr, - - .ecp_write_data = parport_ieee1284_ecp_write_data, - .ecp_read_data = parport_ieee1284_ecp_read_data, - .ecp_write_addr = parport_ieee1284_ecp_write_addr, - - .compat_write_data = parport_ieee1284_write_compat, - .nibble_read_data = parport_ieee1284_read_nibble, - .byte_read_data = parport_ieee1284_read_byte, - - .owner = THIS_MODULE, -}; - -/* --- Initialisation code -------------------------------- */ - -static int parport_arc_init(void) -{ - /* Archimedes hardware provides only one port, at a fixed address */ - struct parport *p; - struct resource res; - char *fake_name = "parport probe"); - - res = request_region(PORT_BASE, 1, fake_name); - if (res == NULL) - return 0; - - p = parport_register_port (PORT_BASE, IRQ_PRINTERACK, - PARPORT_DMA_NONE, &parport_arc_ops); - - if (!p) { - release_region(PORT_BASE, 1); - return 0; - } - - p->modes = PARPORT_MODE_ARCSPP; - p->size = 1; - rename_region(res, p->name); - - printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n", - p->irq); - - /* Tell the high-level drivers about the port. */ - parport_announce_port (p); - - return 1; -} - -module_init(parport_arc_init) diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c new file mode 100644 index 0000000..4baa719 --- /dev/null +++ b/drivers/parport/parport_ax88796.c @@ -0,0 +1,443 @@ +/* linux/drivers/parport/parport_ax88796.c + * + * (c) 2005,2006 Simtec Electronics + * Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define AX_SPR_BUSY (1<<7) +#define AX_SPR_ACK (1<<6) +#define AX_SPR_PE (1<<5) +#define AX_SPR_SLCT (1<<4) +#define AX_SPR_ERR (1<<3) + +#define AX_CPR_nDOE (1<<5) +#define AX_CPR_SLCTIN (1<<3) +#define AX_CPR_nINIT (1<<2) +#define AX_CPR_ATFD (1<<1) +#define AX_CPR_STRB (1<<0) + +struct ax_drvdata { + struct parport *parport; + struct parport_state suspend; + + struct device *dev; + struct resource *io; + + unsigned char irq_enabled; + + void __iomem *base; + void __iomem *spp_data; + void __iomem *spp_spr; + void __iomem *spp_cpr; +}; + +static inline struct ax_drvdata *pp_to_drv(struct parport *p) +{ + return p->private_data; +} + +static unsigned char +parport_ax88796_read_data(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + + return readb(dd->spp_data); +} + +static void +parport_ax88796_write_data(struct parport *p, unsigned char data) +{ + struct ax_drvdata *dd = pp_to_drv(p); + + writeb(data, dd->spp_data); +} + +static unsigned char +parport_ax88796_read_control(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned int cpr = readb(dd->spp_cpr); + unsigned int ret = 0; + + if (!(cpr & AX_CPR_STRB)) + ret |= PARPORT_CONTROL_STROBE; + + if (!(cpr & AX_CPR_ATFD)) + ret |= PARPORT_CONTROL_AUTOFD; + + if (cpr & AX_CPR_nINIT) + ret |= PARPORT_CONTROL_INIT; + + if (!(cpr & AX_CPR_SLCTIN)) + ret |= PARPORT_CONTROL_SELECT; + + return ret; +} + +static void +parport_ax88796_write_control(struct parport *p, unsigned char control) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned int cpr = readb(dd->spp_cpr); + + cpr &= AX_CPR_nDOE; + + if (!(control & PARPORT_CONTROL_STROBE)) + cpr |= AX_CPR_STRB; + + if (!(control & PARPORT_CONTROL_AUTOFD)) + cpr |= AX_CPR_ATFD; + + if (control & PARPORT_CONTROL_INIT) + cpr |= AX_CPR_nINIT; + + if (!(control & PARPORT_CONTROL_SELECT)) + cpr |= AX_CPR_SLCTIN; + + dev_dbg(dd->dev, "write_control: ctrl=%02x, cpr=%02x\n", control, cpr); + writeb(cpr, dd->spp_cpr); + + if (parport_ax88796_read_control(p) != control) { + dev_err(dd->dev, "write_control: read != set (%02x, %02x)\n", + parport_ax88796_read_control(p), control); + } +} + +static unsigned char +parport_ax88796_read_status(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned int status = readb(dd->spp_spr); + unsigned int ret = 0; + + if (status & AX_SPR_BUSY) + ret |= PARPORT_STATUS_BUSY; + + if (status & AX_SPR_ACK) + ret |= PARPORT_STATUS_ACK; + + if (status & AX_SPR_ERR) + ret |= PARPORT_STATUS_ERROR; + + if (status & AX_SPR_SLCT) + ret |= PARPORT_STATUS_SELECT; + + if (status & AX_SPR_PE) + ret |= PARPORT_STATUS_PAPEROUT; + + return ret; +} + +static unsigned char +parport_ax88796_frob_control(struct parport *p, unsigned char mask, + unsigned char val) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned char old = parport_ax88796_read_control(p); + + dev_dbg(dd->dev, "frob: mask=%02x, val=%02x, old=%02x\n", + mask, val, old); + + parport_ax88796_write_control(p, (old & ~mask) | val); + return old; +} + +static void +parport_ax88796_enable_irq(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned long flags; + + local_irq_save(flags); + if (!dd->irq_enabled) { + enable_irq(p->irq); + dd->irq_enabled = 1; + } + local_irq_restore(flags); +} + +static void +parport_ax88796_disable_irq(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned long flags; + + local_irq_save(flags); + if (dd->irq_enabled) { + disable_irq(p->irq); + dd->irq_enabled = 0; + } + local_irq_restore(flags); +} + +static void +parport_ax88796_data_forward(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + void __iomem *cpr = dd->spp_cpr; + + writeb((readb(cpr) & ~AX_CPR_nDOE), cpr); +} + +static void +parport_ax88796_data_reverse(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + void __iomem *cpr = dd->spp_cpr; + + writeb(readb(cpr) | AX_CPR_nDOE, cpr); +} + +static void +parport_ax88796_init_state(struct pardevice *d, struct parport_state *s) +{ + struct ax_drvdata *dd = pp_to_drv(d->port); + + memset(s, 0, sizeof(struct parport_state)); + + dev_dbg(dd->dev, "init_state: %p: state=%p\n", d, s); + s->u.ax88796.cpr = readb(dd->spp_cpr); +} + +static void +parport_ax88796_save_state(struct parport *p, struct parport_state *s) +{ + struct ax_drvdata *dd = pp_to_drv(p); + + dev_dbg(dd->dev, "save_state: %p: state=%p\n", p, s); + s->u.ax88796.cpr = readb(dd->spp_cpr); +} + +static void +parport_ax88796_restore_state(struct parport *p, struct parport_state *s) +{ + struct ax_drvdata *dd = pp_to_drv(p); + + dev_dbg(dd->dev, "restore_state: %p: state=%p\n", p, s); + writeb(s->u.ax88796.cpr, dd->spp_cpr); +} + +static irqreturn_t +parport_ax88796_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + parport_generic_irq(irq, dev_id, regs); + return IRQ_HANDLED; +} + + +static struct parport_operations parport_ax88796_ops = { + .write_data = parport_ax88796_write_data, + .read_data = parport_ax88796_read_data, + + .write_control = parport_ax88796_write_control, + .read_control = parport_ax88796_read_control, + .frob_control = parport_ax88796_frob_control, + + .read_status = parport_ax88796_read_status, + + .enable_irq = parport_ax88796_enable_irq, + .disable_irq = parport_ax88796_disable_irq, + + .data_forward = parport_ax88796_data_forward, + .data_reverse = parport_ax88796_data_reverse, + + .init_state = parport_ax88796_init_state, + .save_state = parport_ax88796_save_state, + .restore_state = parport_ax88796_restore_state, + + .epp_write_data = parport_ieee1284_epp_write_data, + .epp_read_data = parport_ieee1284_epp_read_data, + .epp_write_addr = parport_ieee1284_epp_write_addr, + .epp_read_addr = parport_ieee1284_epp_read_addr, + + .ecp_write_data = parport_ieee1284_ecp_write_data, + .ecp_read_data = parport_ieee1284_ecp_read_data, + .ecp_write_addr = parport_ieee1284_ecp_write_addr, + + .compat_write_data = parport_ieee1284_write_compat, + .nibble_read_data = parport_ieee1284_read_nibble, + .byte_read_data = parport_ieee1284_read_byte, + + .owner = THIS_MODULE, +}; + +static int parport_ax88796_probe(struct platform_device *pdev) +{ + struct device *_dev = &pdev->dev; + struct ax_drvdata *dd; + struct parport *pp = NULL; + struct resource *res; + unsigned long size; + int spacing; + int irq; + int ret; + + dd = kzalloc(sizeof(struct ax_drvdata), GFP_KERNEL); + if (dd == NULL) { + dev_err(_dev, "no memory for private data\n"); + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(_dev, "no MEM specified\n"); + ret = -ENXIO; + goto exit_mem; + } + + size = (res->end - res->start) + 1; + spacing = size / 3; + + dd->io = request_mem_region(res->start, size, pdev->name); + if (dd->io == NULL) { + dev_err(_dev, "cannot reserve memory\n"); + ret = -ENXIO; + goto exit_mem; + } + + dd->base = ioremap(res->start, size); + if (dd->base == NULL) { + dev_err(_dev, "cannot ioremap region\n"); + ret = -ENXIO; + goto exit_res; + } + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) + irq = PARPORT_IRQ_NONE; + + pp = parport_register_port((unsigned long)dd->base, irq, + PARPORT_DMA_NONE, + &parport_ax88796_ops); + + if (pp == NULL) { + dev_err(_dev, "failed to register parallel port\n"); + ret = -ENOMEM; + goto exit_unmap; + } + + pp->private_data = dd; + dd->parport = pp; + dd->dev = _dev; + + dd->spp_data = dd->base; + dd->spp_spr = dd->base + (spacing * 1); + dd->spp_cpr = dd->base + (spacing * 2); + + /* initialise the port controls */ + writeb(AX_CPR_STRB, dd->spp_cpr); + + if (irq >= 0) { + /* request irq */ + ret = request_irq(irq, parport_ax88796_interrupt, + SA_TRIGGER_FALLING, pdev->name, pp); + + if (ret < 0) + goto exit_port; + + dd->irq_enabled = 1; + } + + platform_set_drvdata(pdev, pp); + + dev_info(_dev, "attached parallel port driver\n"); + parport_announce_port(pp); + + return 0; + + exit_port: + parport_remove_port(pp); + exit_unmap: + iounmap(dd->base); + exit_res: + release_resource(dd->io); + kfree(dd->io); + exit_mem: + kfree(dd); + return ret; +} + +static int parport_ax88796_remove(struct platform_device *pdev) +{ + struct parport *p = platform_get_drvdata(pdev); + struct ax_drvdata *dd = pp_to_drv(p); + + free_irq(p->irq, p); + parport_remove_port(p); + iounmap(dd->base); + release_resource(dd->io); + kfree(dd->io); + kfree(dd); + + return 0; +} + +#ifdef CONFIG_PM + +static int parport_ax88796_suspend(struct platform_device *dev, + pm_message_t state) +{ + struct parport *p = platform_get_drvdata(dev); + struct ax_drvdata *dd = pp_to_drv(p); + + parport_ax88796_save_state(p, &dd->suspend); + writeb(AX_CPR_nDOE | AX_CPR_STRB, dd->spp_cpr); + return 0; +} + +static int parport_ax88796_resume(struct platform_device *dev) +{ + struct parport *p = platform_get_drvdata(dev); + struct ax_drvdata *dd = pp_to_drv(p); + + parport_ax88796_restore_state(p, &dd->suspend); + return 0; +} + +#else +#define parport_ax88796_suspend NULL +#define parport_ax88796_resume NULL +#endif + +static struct platform_driver axdrv = { + .driver = { + .name = "ax88796-pp", + .owner = THIS_MODULE, + }, + .probe = parport_ax88796_probe, + .remove = parport_ax88796_remove, + .suspend = parport_ax88796_suspend, + .resume = parport_ax88796_resume, +}; + +static int __init parport_ax88796_init(void) +{ + return platform_driver_register(&axdrv); +} + +static void __exit parport_ax88796_exit(void) +{ + platform_driver_unregister(&axdrv); +} + +module_init(parport_ax88796_init) +module_exit(parport_ax88796_exit) + +MODULE_AUTHOR("Ben Dooks "); +MODULE_DESCRIPTION("AX88796 Parport parallel port driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c index 1de52d9..7352104 100644 --- a/drivers/parport/parport_gsc.c +++ b/drivers/parport/parport_gsc.c @@ -15,7 +15,7 @@ * Phil Blundell * Tim Waugh * Jose Renau - * David Campbell + * David Campbell * Andrea Arcangeli */ diff --git a/drivers/parport/parport_gsc.h b/drivers/parport/parport_gsc.h index 662f6c1..fc9c37c 100644 --- a/drivers/parport/parport_gsc.h +++ b/drivers/parport/parport_gsc.h @@ -24,7 +24,7 @@ * Phil Blundell * Tim Waugh * Jose Renau - * David Campbell + * David Campbell * Andrea Arcangeli */ diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 48bbf32..7318e4a 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -3,7 +3,7 @@ * Authors: Phil Blundell * Tim Waugh * Jose Renau - * David Campbell + * David Campbell * Andrea Arcangeli * * based on work by Grant Guenther and Phil Blundell. diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 36a1556..7c43c53 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c @@ -1,5 +1,4 @@ -/* $Id: parport_sunbpp.c,v 1.12 2001/05/26 03:01:42 davem Exp $ - * Parallel-port routines for Sun architecture +/* parport_sunbpp.c: Parallel-port routines for SBUS * * Author: Derrick J. Brashear * @@ -14,6 +13,9 @@ * Gus Baldauf (gbaldauf@ix.netcom.com) * Peter Zaitcev * Tom Dyas + * + * Updated to new SBUS device framework: David S. Miller + * */ #include @@ -287,14 +289,7 @@ static struct parport_operations parport .owner = THIS_MODULE, }; -typedef struct { - struct list_head list; - struct parport *port; -} Node; -/* no locks, everything's serialized */ -static LIST_HEAD(port_list); - -static int __init init_one_port(struct sbus_dev *sdev) +static int __devinit init_one_port(struct sbus_dev *sdev) { struct parport *p; /* at least in theory there may be a "we don't dma" case */ @@ -303,109 +298,120 @@ static int __init init_one_port(struct s int irq, dma, err = 0, size; struct bpp_regs __iomem *regs; unsigned char value_tcr; - Node *node; - - dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev)); - node = kmalloc(sizeof(Node), GFP_KERNEL); - if (!node) - goto out0; irq = sdev->irqs[0]; base = sbus_ioremap(&sdev->resource[0], 0, sdev->reg_addrs[0].reg_size, "sunbpp"); if (!base) - goto out1; + return -ENODEV; size = sdev->reg_addrs[0].reg_size; dma = PARPORT_DMA_NONE; - dprintk(("alloc(ppops), ")); - ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); + ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); if (!ops) - goto out2; + goto out_unmap; memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); dprintk(("register_port\n")); if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) - goto out3; + goto out_free_ops; p->size = size; - dprintk((KERN_DEBUG "init_one_port: request_irq(%08x:%p:%x:%s:%p) ", - p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p)); if ((err = request_irq(p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p)) != 0) { - dprintk(("ERROR %d\n", err)); - goto out4; + goto out_put_port; } - dprintk(("OK\n")); + parport_sunbpp_enable_irq(p); regs = (struct bpp_regs __iomem *)p->base; - dprintk((KERN_DEBUG "forward\n")); + value_tcr = sbus_readb(®s->p_tcr); value_tcr &= ~P_TCR_DIR; sbus_writeb(value_tcr, ®s->p_tcr); printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); - node->port = p; - list_add(&node->list, &port_list); - parport_announce_port (p); - return 1; + dev_set_drvdata(&sdev->ofdev.dev, p); + + parport_announce_port(p); + + return 0; -out4: +out_put_port: parport_put_port(p); -out3: + +out_free_ops: kfree(ops); -out2: + +out_unmap: sbus_iounmap(base, size); -out1: - kfree(node); -out0: + return err; } -static int __init parport_sunbpp_init(void) +static int __devinit bpp_probe(struct of_device *dev, const struct of_device_id *match) { - struct sbus_bus *sbus; - struct sbus_dev *sdev; - int count = 0; - - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if (!strcmp(sdev->prom_name, "SUNW,bpp")) - count += init_one_port(sdev); - } + struct sbus_dev *sdev = to_sbus_device(&dev->dev); + + return init_one_port(sdev); +} + +static int __devexit bpp_remove(struct of_device *dev) +{ + struct parport *p = dev_get_drvdata(&dev->dev); + struct parport_operations *ops = p->ops; + + parport_remove_port(p); + + if (p->irq != PARPORT_IRQ_NONE) { + parport_sunbpp_disable_irq(p); + free_irq(p->irq, p); } - return count ? 0 : -ENODEV; + + sbus_iounmap((void __iomem *) p->base, p->size); + parport_put_port(p); + kfree(ops); + + dev_set_drvdata(&dev->dev, NULL); + + return 0; +} + +static struct of_device_id bpp_match[] = { + { + .name = "SUNW,bpp", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, bpp_match); + +static struct of_platform_driver bpp_sbus_driver = { + .name = "bpp", + .match_table = bpp_match, + .probe = bpp_probe, + .remove = __devexit_p(bpp_remove), +}; + +static int __init parport_sunbpp_init(void) +{ + return of_register_driver(&bpp_sbus_driver, &sbus_bus_type); } static void __exit parport_sunbpp_exit(void) { - while (!list_empty(&port_list)) { - Node *node = list_entry(port_list.next, Node, list); - struct parport *p = node->port; - struct parport_operations *ops = p->ops; - parport_remove_port(p); - - if (p->irq != PARPORT_IRQ_NONE) { - parport_sunbpp_disable_irq(p); - free_irq(p->irq, p); - } - sbus_iounmap((void __iomem *)p->base, p->size); - parport_put_port(p); - kfree (ops); - list_del(&node->list); - kfree (node); - } + of_unregister_driver(&bpp_sbus_driver); } MODULE_AUTHOR("Derrick J Brashear"); MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); +MODULE_VERSION("2.0"); MODULE_LICENSE("GPL"); module_init(parport_sunbpp_init) diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c index cbe1718..8610ae8 100644 --- a/drivers/parport/procfs.c +++ b/drivers/parport/procfs.c @@ -1,6 +1,6 @@ /* Sysctl interface for parport devices. * - * Authors: David Campbell + * Authors: David Campbell * Tim Waugh * Philip Blundell * Andrea Arcangeli diff --git a/drivers/parport/share.c b/drivers/parport/share.c index bbbfd79..2cb22c8 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -218,7 +218,7 @@ static void free_port (struct parport *p * parport_get_port - increment a port's reference count * @port: the port * - * This ensure's that a struct parport pointer remains valid + * This ensures that a struct parport pointer remains valid * until the matching parport_put_port() call. **/ diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 6707df9..f2d152b 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -26,7 +26,11 @@ obj-$(CONFIG_PPC32) += setup-irq.o obj-$(CONFIG_PPC64) += setup-bus.o obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o obj-$(CONFIG_X86_VISWS) += setup-irq.o -obj-$(CONFIG_PCI_MSI) += msi.o + +msiobj-y := msi.o msi-apic.o +msiobj-$(CONFIG_IA64_GENERIC) += msi-altix.o +msiobj-$(CONFIG_IA64_SGI_SN2) += msi-altix.o +obj-$(CONFIG_PCI_MSI) += $(msiobj-y) # # ACPI Related PCI FW Functions diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index eed67d9..7230926 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -81,9 +81,9 @@ void __devinit pci_bus_add_device(struct { device_add(&dev->dev); - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_add_tail(&dev->global_list, &pci_devices); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); pci_proc_attach_device(dev); pci_create_sysfs_dev_files(dev); @@ -125,10 +125,10 @@ void __devinit pci_bus_add_devices(struc */ if (dev->subordinate) { if (list_empty(&dev->subordinate->node)) { - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_add_tail(&dev->subordinate->node, &dev->bus->children); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); } pci_bus_add_devices(dev->subordinate); @@ -168,7 +168,7 @@ void pci_walk_bus(struct pci_bus *top, v struct list_head *next; bus = top; - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); next = top->devices.next; for (;;) { if (next == &bus->devices) { @@ -180,22 +180,19 @@ void pci_walk_bus(struct pci_bus *top, v continue; } dev = list_entry(next, struct pci_dev, bus_list); - pci_dev_get(dev); if (dev->subordinate) { /* this is a pci-pci bridge, do its devices next */ next = dev->subordinate->devices.next; bus = dev->subordinate; } else next = dev->bus_list.next; - spin_unlock(&pci_bus_lock); - /* Run device routines with the bus unlocked */ + /* Run device routines with the device locked */ + down(&dev->dev.sem); cb(dev, userdata); - - spin_lock(&pci_bus_lock); - pci_dev_put(dev); + up(&dev->dev.sem); } - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); } EXPORT_SYMBOL_GPL(pci_walk_bus); diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 39af9c3..51cb9f8 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -33,10 +34,184 @@ #include #include #include "pci_hotplug.h" +#define MY_NAME "acpi_pcihp" + +#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0) +#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) +#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) + #define METHOD_NAME__SUN "_SUN" #define METHOD_NAME__HPP "_HPP" #define METHOD_NAME_OSHP "OSHP" +static int debug_acpi; + +static acpi_status +decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx) +{ + int i; + union acpi_object *fields = record->package.elements; + u32 revision = fields[1].integer.value; + + switch (revision) { + case 1: + if (record->package.count != 6) + return AE_ERROR; + for (i = 2; i < 6; i++) + if (fields[i].type != ACPI_TYPE_INTEGER) + return AE_ERROR; + hpx->t0 = &hpx->type0_data; + hpx->t0->revision = revision; + hpx->t0->cache_line_size = fields[2].integer.value; + hpx->t0->latency_timer = fields[3].integer.value; + hpx->t0->enable_serr = fields[4].integer.value; + hpx->t0->enable_perr = fields[5].integer.value; + break; + default: + printk(KERN_WARNING + "%s: Type 0 Revision %d record not supported\n", + __FUNCTION__, revision); + return AE_ERROR; + } + return AE_OK; +} + +static acpi_status +decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx) +{ + int i; + union acpi_object *fields = record->package.elements; + u32 revision = fields[1].integer.value; + + switch (revision) { + case 1: + if (record->package.count != 5) + return AE_ERROR; + for (i = 2; i < 5; i++) + if (fields[i].type != ACPI_TYPE_INTEGER) + return AE_ERROR; + hpx->t1 = &hpx->type1_data; + hpx->t1->revision = revision; + hpx->t1->max_mem_read = fields[2].integer.value; + hpx->t1->avg_max_split = fields[3].integer.value; + hpx->t1->tot_max_split = fields[4].integer.value; + break; + default: + printk(KERN_WARNING + "%s: Type 1 Revision %d record not supported\n", + __FUNCTION__, revision); + return AE_ERROR; + } + return AE_OK; +} + +static acpi_status +decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx) +{ + int i; + union acpi_object *fields = record->package.elements; + u32 revision = fields[1].integer.value; + + switch (revision) { + case 1: + if (record->package.count != 18) + return AE_ERROR; + for (i = 2; i < 18; i++) + if (fields[i].type != ACPI_TYPE_INTEGER) + return AE_ERROR; + hpx->t2 = &hpx->type2_data; + hpx->t2->revision = revision; + hpx->t2->unc_err_mask_and = fields[2].integer.value; + hpx->t2->unc_err_mask_or = fields[3].integer.value; + hpx->t2->unc_err_sever_and = fields[4].integer.value; + hpx->t2->unc_err_sever_or = fields[5].integer.value; + hpx->t2->cor_err_mask_and = fields[6].integer.value; + hpx->t2->cor_err_mask_or = fields[7].integer.value; + hpx->t2->adv_err_cap_and = fields[8].integer.value; + hpx->t2->adv_err_cap_or = fields[9].integer.value; + hpx->t2->pci_exp_devctl_and = fields[10].integer.value; + hpx->t2->pci_exp_devctl_or = fields[11].integer.value; + hpx->t2->pci_exp_lnkctl_and = fields[12].integer.value; + hpx->t2->pci_exp_lnkctl_or = fields[13].integer.value; + hpx->t2->sec_unc_err_sever_and = fields[14].integer.value; + hpx->t2->sec_unc_err_sever_or = fields[15].integer.value; + hpx->t2->sec_unc_err_mask_and = fields[16].integer.value; + hpx->t2->sec_unc_err_mask_or = fields[17].integer.value; + break; + default: + printk(KERN_WARNING + "%s: Type 2 Revision %d record not supported\n", + __FUNCTION__, revision); + return AE_ERROR; + } + return AE_OK; +} + +static acpi_status +acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx) +{ + acpi_status status; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *package, *record, *fields; + u32 type; + int i; + + /* Clear the return buffer with zeros */ + memset(hpx, 0, sizeof(struct hotplug_params)); + + status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer); + if (ACPI_FAILURE(status)) + return status; + + package = (union acpi_object *)buffer.pointer; + if (package->type != ACPI_TYPE_PACKAGE) { + status = AE_ERROR; + goto exit; + } + + for (i = 0; i < package->package.count; i++) { + record = &package->package.elements[i]; + if (record->type != ACPI_TYPE_PACKAGE) { + status = AE_ERROR; + goto exit; + } + + fields = record->package.elements; + if (fields[0].type != ACPI_TYPE_INTEGER || + fields[1].type != ACPI_TYPE_INTEGER) { + status = AE_ERROR; + goto exit; + } + + type = fields[0].integer.value; + switch (type) { + case 0: + status = decode_type0_hpx_record(record, hpx); + if (ACPI_FAILURE(status)) + goto exit; + break; + case 1: + status = decode_type1_hpx_record(record, hpx); + if (ACPI_FAILURE(status)) + goto exit; + break; + case 2: + status = decode_type2_hpx_record(record, hpx); + if (ACPI_FAILURE(status)) + goto exit; + break; + default: + printk(KERN_ERR "%s: Type %d record not supported\n", + __FUNCTION__, type); + status = AE_ERROR; + goto exit; + } + } + exit: + kfree(buffer.pointer); + return status; +} static acpi_status acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) @@ -50,6 +225,9 @@ acpi_run_hpp(acpi_handle handle, struct acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + /* Clear the return buffer with zeros */ + memset(hpp, 0, sizeof(struct hotplug_params)); + /* get _hpp */ status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); switch (status) { @@ -58,7 +236,7 @@ acpi_run_hpp(acpi_handle handle, struct if (!ret_buf.pointer) { printk(KERN_ERR "%s:%s alloc for _HPP fail\n", __FUNCTION__, (char *)string.pointer); - acpi_os_free(string.pointer); + kfree(string.pointer); return AE_NO_MEMORY; } status = acpi_evaluate_object(handle, METHOD_NAME__HPP, @@ -69,7 +247,7 @@ acpi_run_hpp(acpi_handle handle, struct if (ACPI_FAILURE(status)) { pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__, (char *)string.pointer, status); - acpi_os_free(string.pointer); + kfree(string.pointer); return status; } } @@ -98,19 +276,20 @@ acpi_run_hpp(acpi_handle handle, struct } } - hpp->cache_line_size = nui[0]; - hpp->latency_timer = nui[1]; - hpp->enable_serr = nui[2]; - hpp->enable_perr = nui[3]; + hpp->t0 = &hpp->type0_data; + hpp->t0->cache_line_size = nui[0]; + hpp->t0->latency_timer = nui[1]; + hpp->t0->enable_serr = nui[2]; + hpp->t0->enable_perr = nui[3]; - pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size); - pr_debug(" _HPP: latency timer =0x%x\n", hpp->latency_timer); - pr_debug(" _HPP: enable SERR =0x%x\n", hpp->enable_serr); - pr_debug(" _HPP: enable PERR =0x%x\n", hpp->enable_perr); + pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size); + pr_debug(" _HPP: latency timer =0x%x\n", hpp->t0->latency_timer); + pr_debug(" _HPP: enable SERR =0x%x\n", hpp->t0->enable_serr); + pr_debug(" _HPP: enable PERR =0x%x\n", hpp->t0->enable_perr); free_and_return: - acpi_os_free(string.pointer); - acpi_os_free(ret_buf.pointer); + kfree(string.pointer); + kfree(ret_buf.pointer); return status; } @@ -130,13 +309,17 @@ acpi_status acpi_run_oshp(acpi_handle ha /* run OSHP */ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); if (ACPI_FAILURE(status)) - printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__, - (char *)string.pointer, status); + if (status != AE_NOT_FOUND) + printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", + __FUNCTION__, (char *)string.pointer, status); + else + dbg("%s:%s OSHP not found\n", + __FUNCTION__, (char *)string.pointer); else pr_debug("%s:%s OSHP passes\n", __FUNCTION__, (char *)string.pointer); - acpi_os_free(string.pointer); + kfree(string.pointer); return status; } EXPORT_SYMBOL_GPL(acpi_run_oshp); @@ -145,14 +328,27 @@ EXPORT_SYMBOL_GPL(acpi_run_oshp); /* acpi_get_hp_params_from_firmware * - * @dev - the pci_dev of the newly added device + * @bus - the pci_bus of the bus on which the device is newly added * @hpp - allocated by the caller */ -acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, +acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, struct hotplug_params *hpp) { acpi_status status = AE_NOT_FOUND; - struct pci_dev *pdev = dev; + acpi_handle handle, phandle; + struct pci_bus *pbus = bus; + struct pci_dev *pdev; + + do { + pdev = pbus->self; + if (!pdev) { + handle = acpi_get_pci_rootbridge_handle( + pci_domain_nr(pbus), pbus->number); + break; + } + handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); + pbus = pbus->parent; + } while (!handle); /* * _HPP settings apply to all child buses, until another _HPP is @@ -160,15 +356,19 @@ acpi_status acpi_get_hp_params_from_firm * look for it in the parent device scope since that would apply to * this pci dev. If we don't find any _HPP, use hardcoded defaults */ - while (pdev && (ACPI_FAILURE(status))) { - acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); - if (!handle) + while (handle) { + status = acpi_run_hpx(handle, hpp); + if (ACPI_SUCCESS(status)) break; status = acpi_run_hpp(handle, hpp); - if (!(pdev->bus->parent)) + if (ACPI_SUCCESS(status)) break; - /* Check if a parent object supports _HPP */ - pdev = pdev->bus->parent->self; + if (acpi_root_bridge(handle)) + break; + status = acpi_get_parent(handle, &phandle); + if (ACPI_FAILURE(status)) + break; + handle = phandle; } return status; } @@ -192,20 +392,23 @@ int acpi_root_bridge(acpi_handle handle) if ((info->valid & ACPI_VALID_HID) && !strcmp(PCI_ROOT_HID_STRING, info->hardware_id.value)) { - acpi_os_free(buffer.pointer); + kfree(buffer.pointer); return 1; } if (info->valid & ACPI_VALID_CID) { for (i=0; i < info->compatibility_id.count; i++) { if (!strcmp(PCI_ROOT_HID_STRING, info->compatibility_id.id[i].value)) { - acpi_os_free(buffer.pointer); + kfree(buffer.pointer); return 1; } } } - acpi_os_free(buffer.pointer); + kfree(buffer.pointer); } return 0; } EXPORT_SYMBOL_GPL(acpi_root_bridge); + +module_param(debug_acpi, bool, 0644); +MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not"); diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 467ac70..17a93f8 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -75,6 +75,10 @@ struct acpiphp_bridge { struct list_head list; acpi_handle handle; struct acpiphp_slot *slots; + + /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ + struct acpiphp_func *func; + int type; int nr_slots; @@ -122,6 +126,7 @@ struct acpiphp_slot { */ struct acpiphp_func { struct acpiphp_slot *slot; /* parent */ + struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */ struct list_head sibling; struct pci_dev *pci_dev; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 053ee84..d370f99 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -286,13 +286,19 @@ static void decode_hpp(struct acpiphp_br { acpi_status status; - status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp); - if (ACPI_FAILURE(status)) { + status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp); + if (ACPI_FAILURE(status) || + !bridge->hpp.t0 || (bridge->hpp.t0->revision > 1)) { /* use default numbers */ - bridge->hpp.cache_line_size = 0x10; - bridge->hpp.latency_timer = 0x40; - bridge->hpp.enable_serr = 0; - bridge->hpp.enable_perr = 0; + printk(KERN_WARNING + "%s: Could not get hotplug parameters. Use defaults\n", + __FUNCTION__); + bridge->hpp.t0 = &bridge->hpp.type0_data; + bridge->hpp.t0->revision = 0; + bridge->hpp.t0->cache_line_size = 0x10; + bridge->hpp.t0->latency_timer = 0x40; + bridge->hpp.t0->enable_serr = 0; + bridge->hpp.t0->enable_perr = 0; } } @@ -319,6 +325,13 @@ static void init_bridge_misc(struct acpi /* install notify handler */ if (bridge->type != BRIDGE_TYPE_HOST) { + if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { + status = acpi_remove_notify_handler(bridge->func->handle, + ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_func); + if (ACPI_FAILURE(status)) + err("failed to remove notify handler\n"); + } status = acpi_install_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_bridge, @@ -331,6 +344,66 @@ static void init_bridge_misc(struct acpi } +/* find acpiphp_func from acpiphp_bridge */ +static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle) +{ + struct list_head *node, *l; + struct acpiphp_bridge *bridge; + struct acpiphp_slot *slot; + struct acpiphp_func *func; + + list_for_each(node, &bridge_list) { + bridge = list_entry(node, struct acpiphp_bridge, list); + for (slot = bridge->slots; slot; slot = slot->next) { + list_for_each(l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, + sibling); + if (func->handle == handle) + return func; + } + } + } + + return NULL; +} + + +static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) +{ + acpi_handle dummy_handle; + + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_STA", &dummy_handle))) + bridge->flags |= BRIDGE_HAS_STA; + + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_EJ0", &dummy_handle))) + bridge->flags |= BRIDGE_HAS_EJ0; + + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_PS0", &dummy_handle))) + bridge->flags |= BRIDGE_HAS_PS0; + + if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_PS3", &dummy_handle))) + bridge->flags |= BRIDGE_HAS_PS3; + + /* is this ejectable p2p bridge? */ + if (bridge->flags & BRIDGE_HAS_EJ0) { + struct acpiphp_func *func; + + dbg("found ejectable p2p bridge\n"); + + /* make link between PCI bridge and PCI function */ + func = acpiphp_bridge_handle_to_function(bridge->handle); + if (!func) + return; + bridge->func = func; + func->bridge = bridge; + } +} + + /* allocate and initialize host bridge data structure */ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) { @@ -364,6 +437,7 @@ static void add_p2p_bridge(acpi_handle * bridge->type = BRIDGE_TYPE_P2P; bridge->handle = handle; + config_p2p_bridge_flags(bridge); bridge->pci_dev = pci_dev_get(pci_dev); bridge->pci_bus = pci_dev->subordinate; @@ -423,7 +497,7 @@ find_p2p_bridge(acpi_handle handle, u32 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, find_p2p_bridge, dev->subordinate, NULL); if (ACPI_FAILURE(status)) - warn("find_p2p_bridge faied (error code = 0x%x)\n", status); + warn("find_p2p_bridge failed (error code = 0x%x)\n", status); out: pci_dev_put(dev); @@ -478,7 +552,6 @@ static int add_bridge(acpi_handle handle if (detect_ejectable_slots(handle) > 0) { dbg("found PCI host-bus bridge with hot-pluggable slots\n"); add_host_bridge(handle, pci_bus); - return 0; } /* search P2P bridges under this host bridge */ @@ -486,7 +559,7 @@ static int add_bridge(acpi_handle handle find_p2p_bridge, pci_bus, NULL); if (ACPI_FAILURE(status)) - warn("find_p2p_bridge faied (error code = 0x%x)\n",status); + warn("find_p2p_bridge failed (error code = 0x%x)\n", status); return 0; } @@ -516,6 +589,16 @@ static void cleanup_bridge(struct acpiph if (ACPI_FAILURE(status)) err("failed to remove notify handler\n"); + if ((bridge->type != BRIDGE_TYPE_HOST) && + ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) { + status = acpi_install_notify_handler(bridge->func->handle, + ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_func, + bridge->func); + if (ACPI_FAILURE(status)) + err("failed to install interrupt notify handler\n"); + } + slot = bridge->slots; while (slot) { struct acpiphp_slot *next = slot->next; @@ -549,6 +632,11 @@ cleanup_p2p_bridge(acpi_handle handle, u { struct acpiphp_bridge *bridge; + /* cleanup p2p bridges under this P2P bridge + in a depth-first manner */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, + cleanup_p2p_bridge, NULL, NULL); + if (!(bridge = acpiphp_handle_to_bridge(handle))) return AE_OK; cleanup_bridge(bridge); @@ -559,15 +647,14 @@ static void remove_bridge(acpi_handle ha { struct acpiphp_bridge *bridge; + /* cleanup p2p bridges under this host bridge + in a depth-first manner */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, + (u32)1, cleanup_p2p_bridge, NULL, NULL); + bridge = acpiphp_handle_to_bridge(handle); - if (bridge) { + if (bridge) cleanup_bridge(bridge); - } else { - /* clean-up p2p bridges under this host bridge */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - ACPI_UINT32_MAX, cleanup_p2p_bridge, - NULL, NULL); - } } static struct pci_dev * get_apic_pci_info(acpi_handle handle) @@ -634,7 +721,7 @@ static int get_gsi_base(acpi_handle hand break; } out: - acpi_os_free(buffer.pointer); + kfree(buffer.pointer); return result; } @@ -797,36 +884,6 @@ static unsigned char acpiphp_max_busnr(s } - -/** - * get_func - get a pointer to acpiphp_func given a slot, device - * @slot: slot to search - * @dev: pci_dev struct to match. - * - * This function will increase the reference count of pci_dev, - * so callers should call pci_dev_put when complete. - * - */ -static struct acpiphp_func * -get_func(struct acpiphp_slot *slot, struct pci_dev *dev) -{ - struct acpiphp_func *func = NULL; - struct pci_bus *bus = slot->bridge->pci_bus; - struct pci_dev *pdev; - - list_for_each_entry(func, &slot->funcs, sibling) { - pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, - func->function)); - if (pdev) { - if (pdev == dev) - break; - pci_dev_put(pdev); - } - } - return func; -} - - /** * acpiphp_bus_add - add a new bus to acpi subsystem * @func: acpiphp_func of the bridge @@ -872,6 +929,28 @@ acpiphp_bus_add_out: } +/** + * acpiphp_bus_trim - trim a bus from acpi subsystem + * @handle: handle to acpi namespace + * + */ +int acpiphp_bus_trim(acpi_handle handle) +{ + struct acpi_device *device; + int retval; + + retval = acpi_bus_get_device(handle, &device); + if (retval) { + dbg("acpi_device not found\n"); + return retval; + } + + retval = acpi_bus_trim(device, 1); + if (retval) + err("cannot remove from acpi list\n"); + + return retval; +} /** * enable_device - enable, configure a slot @@ -889,6 +968,7 @@ static int enable_device(struct acpiphp_ struct acpiphp_func *func; int retval = 0; int num, max, pass; + acpi_status status; if (slot->flags & SLOT_ENABLED) goto err_exit; @@ -918,19 +998,17 @@ static int enable_device(struct acpiphp_ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { max = pci_scan_bridge(bus, dev, max, pass); - if (pass && dev->subordinate) { + if (pass && dev->subordinate) pci_bus_size_bridges(dev->subordinate); - func = get_func(slot, dev); - if (func) { - acpiphp_bus_add(func); - /* side effect of get_func */ - pci_dev_put(dev); - } - } } } } + list_for_each (l, &slot->funcs) { + func = list_entry(l, struct acpiphp_func, sibling); + acpiphp_bus_add(func); + } + pci_bus_assign_resources(bus); acpiphp_sanitize_bus(bus); pci_enable_bridges(bus); @@ -943,6 +1021,17 @@ static int enable_device(struct acpiphp_ func = list_entry(l, struct acpiphp_func, sibling); func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device, func->function)); + if (!func->pci_dev) + continue; + + if (func->pci_dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && + func->pci_dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) + continue; + + status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); + if (ACPI_FAILURE(status)) + warn("find_p2p_bridge failed (error code = 0x%x)\n", + status); } slot->flags |= SLOT_ENABLED; @@ -967,6 +1056,18 @@ static int disable_device(struct acpiphp list_for_each (l, &slot->funcs) { func = list_entry(l, struct acpiphp_func, sibling); + + if (func->bridge) { + /* cleanup p2p bridges under this P2P bridge */ + cleanup_p2p_bridge(func->bridge->handle, + (u32)1, NULL, NULL); + func->bridge = NULL; + } + + acpiphp_bus_trim(func->handle); + /* try to remove anyway. + * acpiphp_bus_add might have been failed */ + if (!func->pci_dev) continue; @@ -1111,16 +1212,17 @@ static void program_hpp(struct pci_dev * (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) return; + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, - bridge->hpp.cache_line_size); + bridge->hpp.t0->cache_line_size); pci_write_config_byte(dev, PCI_LATENCY_TIMER, - bridge->hpp.latency_timer); + bridge->hpp.t0->latency_timer); pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); - if (bridge->hpp.enable_serr) + if (bridge->hpp.t0->enable_serr) pci_cmd |= PCI_COMMAND_SERR; else pci_cmd &= ~PCI_COMMAND_SERR; - if (bridge->hpp.enable_perr) + if (bridge->hpp.t0->enable_perr) pci_cmd |= PCI_COMMAND_PARITY; else pci_cmd &= ~PCI_COMMAND_PARITY; @@ -1129,13 +1231,13 @@ static void program_hpp(struct pci_dev * /* Program bridge control value and child devices */ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, - bridge->hpp.latency_timer); + bridge->hpp.t0->latency_timer); pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); - if (bridge->hpp.enable_serr) + if (bridge->hpp.t0->enable_serr) pci_bctl |= PCI_BRIDGE_CTL_SERR; else pci_bctl &= ~PCI_BRIDGE_CTL_SERR; - if (bridge->hpp.enable_perr) + if (bridge->hpp.t0->enable_perr) pci_bctl |= PCI_BRIDGE_CTL_PARITY; else pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; @@ -1155,6 +1257,7 @@ static void acpiphp_set_hpp_values(acpi_ memset(&bridge, 0, sizeof(bridge)); bridge.handle = handle; + bridge.pci_bus = bus; bridge.pci_dev = bus->self; decode_hpp(&bridge); list_for_each_entry(dev, &bus->devices, bus_list) @@ -1297,6 +1400,13 @@ static void handle_hotplug_event_bridge( case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname); + if ((bridge->type != BRIDGE_TYPE_HOST) && + (bridge->flags & BRIDGE_HAS_EJ0)) { + struct acpiphp_slot *slot; + slot = bridge->func->slot; + if (!acpiphp_disable_slot(slot)) + acpiphp_eject_slot(slot); + } break; case ACPI_NOTIFY_FREQUENCY_MISMATCH: @@ -1490,9 +1600,15 @@ int acpiphp_enable_slot(struct acpiphp_s if (retval) goto err_exit; - if (get_slot_status(slot) == ACPI_STA_ALL) + if (get_slot_status(slot) == ACPI_STA_ALL) { /* configure all functions */ retval = enable_device(slot); + if (retval) + power_off_slot(slot); + } else { + dbg("%s: Slot status is not ACPI_STA_ALL\n", __FUNCTION__); + power_off_slot(slot); + } err_exit: mutex_unlock(&slot->crit_sect); diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index e13d5b8..5939294 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -285,7 +285,7 @@ static int get_attention_status(struct h (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); @@ -315,7 +315,7 @@ static int get_latch_status(struct hotpl debug("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); @@ -342,7 +342,7 @@ static int get_power_status(struct hotpl debug("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); @@ -369,7 +369,7 @@ static int get_adapter_present(struct ho debug("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value); ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { memcpy(&myslot, pslot, sizeof(struct slot)); @@ -401,7 +401,7 @@ static int get_max_bus_speed(struct hotp ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { rc = 0; @@ -441,7 +441,7 @@ static int get_cur_bus_speed(struct hotp ibmphp_lock_operations(); - if (hotplug_slot && value) { + if (hotplug_slot) { pslot = hotplug_slot->private; if (pslot) { rc = get_cur_bus_info(&pslot); diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index eb0d01d..e929b7c 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h @@ -176,11 +176,51 @@ extern int pci_hp_change_slot_info (stru struct hotplug_slot_info *info); extern struct subsystem pci_hotplug_slots_subsys; +/* PCI Setting Record (Type 0) */ +struct hpp_type0 { + u32 revision; + u8 cache_line_size; + u8 latency_timer; + u8 enable_serr; + u8 enable_perr; +}; + +/* PCI-X Setting Record (Type 1) */ +struct hpp_type1 { + u32 revision; + u8 max_mem_read; + u8 avg_max_split; + u16 tot_max_split; +}; + +/* PCI Express Setting Record (Type 2) */ +struct hpp_type2 { + u32 revision; + u32 unc_err_mask_and; + u32 unc_err_mask_or; + u32 unc_err_sever_and; + u32 unc_err_sever_or; + u32 cor_err_mask_and; + u32 cor_err_mask_or; + u32 adv_err_cap_and; + u32 adv_err_cap_or; + u16 pci_exp_devctl_and; + u16 pci_exp_devctl_or; + u16 pci_exp_lnkctl_and; + u16 pci_exp_lnkctl_or; + u32 sec_unc_err_sever_and; + u32 sec_unc_err_sever_or; + u32 sec_unc_err_mask_and; + u32 sec_unc_err_mask_or; +}; + struct hotplug_params { - u8 cache_line_size; - u8 latency_timer; - u8 enable_serr; - u8 enable_perr; + struct hpp_type0 *t0; /* Type0: NULL if not available */ + struct hpp_type1 *t1; /* Type1: NULL if not available */ + struct hpp_type2 *t2; /* Type2: NULL if not available */ + struct hpp_type0 type0_data; + struct hpp_type1 type1_data; + struct hpp_type2 type2_data; }; #ifdef CONFIG_ACPI @@ -188,7 +228,7 @@ #include #include #include extern acpi_status acpi_run_oshp(acpi_handle handle); -extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev, +extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, struct hotplug_params *hpp); int acpi_root_bridge(acpi_handle handle); #endif diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 92c1f0f..ce89f58 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -284,7 +284,7 @@ #define pciehp_get_hp_hw_control_from_fi static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) { - if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) + if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) return -ENODEV; return 0; } diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 601cf90..c67b7c3 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -69,6 +69,7 @@ static int get_power_status (struct hotp static int get_attention_status (struct hotplug_slot *slot, u8 *value); static int get_latch_status (struct hotplug_slot *slot, u8 *value); static int get_adapter_status (struct hotplug_slot *slot, u8 *value); +static int get_address (struct hotplug_slot *slot, u32 *value); static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); @@ -81,6 +82,7 @@ static struct hotplug_slot_ops pciehp_ho .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, + .get_address = get_address, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed, }; @@ -331,6 +333,18 @@ static int get_adapter_status(struct hot return 0; } +static int get_address(struct hotplug_slot *hotplug_slot, u32 *value) +{ + struct slot *slot = hotplug_slot->private; + struct pci_bus *bus = slot->ctrl->pci_dev->subordinate; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device; + + return 0; +} + static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) { struct slot *slot = hotplug_slot->private; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 6c14d9e..d77138e 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1288,7 +1288,7 @@ int pciehp_acpi_get_hp_hw_control_from_f if (ACPI_SUCCESS(status)) { dbg("Gained control for hotplug HW for pci %s (%s)\n", pci_name(dev), (char *)string.pointer); - acpi_os_free(string.pointer); + kfree(string.pointer); return 0; } if (acpi_root_bridge(handle)) @@ -1302,7 +1302,7 @@ int pciehp_acpi_get_hp_hw_control_from_f err("Cannot get control of hotplug hardware for pci %s\n", pci_name(dev)); - acpi_os_free(string.pointer); + kfree(string.pointer); return -1; } #endif @@ -1404,9 +1404,6 @@ int pcie_init(struct controller * ctrl, info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device); - if (pci_enable_device(pdev)) - goto abort_free_ctlr; - mutex_init(&ctrl->crit_sect); /* setup wait queue */ init_waitqueue_head(&ctrl->queue); @@ -1474,7 +1471,7 @@ int pcie_init(struct controller * ctrl, rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort_free_irq; } intr_enable = intr_enable | PRSN_DETECT_ENABLE; @@ -1500,19 +1497,19 @@ int pcie_init(struct controller * ctrl, rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort_free_irq; } rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort_disable_intr; } temp_word = 0x1F; /* Clear all events */ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); if (rc) { err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort_disable_intr; } if (pciehp_force) { @@ -1521,7 +1518,7 @@ int pcie_init(struct controller * ctrl, } else { rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev); if (rc) - goto abort_free_ctlr; + goto abort_disable_intr; } /* Add this HPC instance into the HPC list */ @@ -1548,6 +1545,21 @@ int pcie_init(struct controller * ctrl, return 0; /* We end up here for the many possible ways to fail this API. */ +abort_disable_intr: + rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); + if (!rc) { + temp_word &= ~(intr_enable | HP_INTR_ENABLE); + rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); + } + if (rc) + err("%s : disabling interrupts failed\n", __FUNCTION__); + +abort_free_irq: + if (pciehp_poll_mode) + del_timer_sync(&php_ctlr->int_poll_timer); + else + free_irq(php_ctlr->irq, ctrl); + abort_free_ctlr: pcie_cap_base = saved_cap_base; kfree(php_ctlr); diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 4017fb0..854aaea 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -34,6 +34,144 @@ #include #include "../pci.h" #include "pciehp.h" +static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) +{ + u16 pci_cmd, pci_bctl; + + if (hpp->revision > 1) { + printk(KERN_WARNING "%s: Rev.%d type0 record not supported\n", + __FUNCTION__, hpp->revision); + return; + } + + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer); + pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); + if (hpp->enable_serr) + pci_cmd |= PCI_COMMAND_SERR; + else + pci_cmd &= ~PCI_COMMAND_SERR; + if (hpp->enable_perr) + pci_cmd |= PCI_COMMAND_PARITY; + else + pci_cmd &= ~PCI_COMMAND_PARITY; + pci_write_config_word(dev, PCI_COMMAND, pci_cmd); + + /* Program bridge control value */ + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, + hpp->latency_timer); + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); + if (hpp->enable_serr) + pci_bctl |= PCI_BRIDGE_CTL_SERR; + else + pci_bctl &= ~PCI_BRIDGE_CTL_SERR; + if (hpp->enable_perr) + pci_bctl |= PCI_BRIDGE_CTL_PARITY; + else + pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); + } +} + +static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) +{ + int pos; + u16 reg16; + u32 reg32; + + if (hpp->revision > 1) { + printk(KERN_WARNING "%s: Rev.%d type2 record not supported\n", + __FUNCTION__, hpp->revision); + return; + } + + /* Find PCI Express capability */ + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!pos) + return; + + /* Initialize Device Control Register */ + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); + reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); + + /* Initialize Link Control Register */ + if (dev->subordinate) { + pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, ®16); + reg16 = (reg16 & hpp->pci_exp_lnkctl_and) + | hpp->pci_exp_lnkctl_or; + pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16); + } + + /* Find Advanced Error Reporting Enhanced Capability */ + pos = 256; + do { + pci_read_config_dword(dev, pos, ®32); + if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR) + break; + } while ((pos = PCI_EXT_CAP_NEXT(reg32))); + if (!pos) + return; + + /* Initialize Uncorrectable Error Mask Register */ + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, ®32); + reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or; + pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32); + + /* Initialize Uncorrectable Error Severity Register */ + pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, ®32); + reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or; + pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32); + + /* Initialize Correctable Error Mask Register */ + pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®32); + reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or; + pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32); + + /* Initialize Advanced Error Capabilities and Control Register */ + pci_read_config_dword(dev, pos + PCI_ERR_CAP, ®32); + reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or; + pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32); + + /* + * FIXME: The following two registers are not supported yet. + * + * o Secondary Uncorrectable Error Severity Register + * o Secondary Uncorrectable Error Mask Register + */ +} + +static void program_fw_provided_values(struct pci_dev *dev) +{ + struct pci_dev *cdev; + struct hotplug_params hpp; + + /* Program hpp values for this device */ + if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || + (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && + (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) + return; + + if (pciehp_get_hp_params_from_firmware(dev, &hpp)) { + printk(KERN_WARNING "%s: Could not get hotplug parameters\n", + __FUNCTION__); + return; + } + + if (hpp.t2) + program_hpp_type2(dev, hpp.t2); + if (hpp.t0) + program_hpp_type0(dev, hpp.t0); + + /* Program child devices */ + if (dev->subordinate) { + list_for_each_entry(cdev, &dev->subordinate->devices, + bus_list) + program_fw_provided_values(cdev); + } +} + static int pciehp_add_bridge(struct pci_dev *dev) { struct pci_bus *parent = dev->bus; @@ -66,10 +204,11 @@ int pciehp_configure_device(struct slot struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; int num, fn; - dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0)); + dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); if (dev) { err("Device %s already exists at %x:%x, cannot hot-add\n", pci_name(dev), p_slot->bus, p_slot->device); + pci_dev_put(dev); return -EINVAL; } @@ -86,14 +225,15 @@ int pciehp_configure_device(struct slot if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { err("Cannot hot-add display device %s\n", pci_name(dev)); + pci_dev_put(dev); continue; } if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { pciehp_add_bridge(dev); } - /* TBD: program firmware provided _HPP values */ - /* program_fw_provided_values(dev); */ + program_fw_provided_values(dev); + pci_dev_put(dev); } pci_bus_assign_resources(parent); @@ -106,18 +246,20 @@ int pciehp_unconfigure_device(struct slo int rc = 0; int j; u8 bctl = 0; + struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device); for (j=0; j<8 ; j++) { - struct pci_dev* temp = pci_find_slot(p_slot->bus, + struct pci_dev* temp = pci_get_slot(parent, (p_slot->device << 3) | j); if (!temp) continue; if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { err("Cannot remove display device %s\n", pci_name(temp)); + pci_dev_put(temp); continue; } if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { @@ -125,10 +267,12 @@ int pciehp_unconfigure_device(struct slo if (bctl & PCI_BRIDGE_CTL_VGA) { err("Cannot remove display device %s\n", pci_name(temp)); + pci_dev_put(temp); continue; } } pci_remove_bus_device(temp); + pci_dev_put(temp); } /* * Some PCI Express root ports require fixup after hot-plug operation. diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index 8cb9abd..f31d83c 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -18,11 +18,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -102,8 +104,7 @@ static struct hotplug_slot_attribute sn_ static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device) { struct pcibus_info *pcibus_info; - int bricktype; - int bus_num; + u16 busnum, segment, ioboard_type; pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); @@ -111,12 +112,14 @@ static int sn_pci_slot_valid(struct pci_ if (!(pcibus_info->pbi_valid_devices & (1 << device))) return -EPERM; - bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid); - bus_num = pcibus_info->pbi_buscommon.bs_persist_busnum & 0xf; + ioboard_type = sn_ioboard_to_pci_bus(pci_bus); + busnum = pcibus_info->pbi_buscommon.bs_persist_busnum; + segment = pci_domain_nr(pci_bus) & 0xf; /* Do not allow hotplug operations on base I/O cards */ - if ((bricktype == L1_BRICKTYPE_IX || bricktype == L1_BRICKTYPE_IA) && - (bus_num == 1 && device != 1)) + if ((ioboard_type == L1_BRICKTYPE_IX || + ioboard_type == L1_BRICKTYPE_IA) && + (segment == 1 && busnum == 0 && device != 1)) return -EPERM; return 1; @@ -125,23 +128,23 @@ static int sn_pci_slot_valid(struct pci_ static int sn_pci_bus_valid(struct pci_bus *pci_bus) { struct pcibus_info *pcibus_info; - int asic_type; - int bricktype; - - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); + u32 asic_type; + u16 ioboard_type; /* Don't register slots hanging off the TIOCA bus */ + pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); asic_type = pcibus_info->pbi_buscommon.bs_asic_type; if (asic_type == PCIIO_ASIC_TYPE_TIOCA) return -EPERM; /* Only register slots in I/O Bricks that support hotplug */ - bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid); - switch (bricktype) { + ioboard_type = sn_ioboard_to_pci_bus(pci_bus); + switch (ioboard_type) { case L1_BRICKTYPE_IX: case L1_BRICKTYPE_PX: case L1_BRICKTYPE_IA: case L1_BRICKTYPE_PA: + case L1_BOARDTYPE_PCIX3SLOT: return 1; break; default: @@ -175,14 +178,11 @@ static int sn_hp_slot_private_alloc(stru slot->pci_bus = pci_bus; sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x", pci_domain_nr(pci_bus), - ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf, + ((u16)pcibus_info->pbi_buscommon.bs_persist_busnum), device + 1); - sprintf(slot->physical_path, "module_%c%c%c%c%.2d", - '0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), - '0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), - '0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), - MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid), - MODULE_GET_BPOS(pcibus_info->pbi_moduleid)); + + sn_generate_path(pci_bus, slot->physical_path); + slot->hotplug_slot = bss_hotplug_slot; list_add(&slot->hp_list, &sn_hp_list); @@ -461,10 +461,12 @@ static inline int get_power_status(struc { struct slot *slot = bss_hotplug_slot->private; struct pcibus_info *pcibus_info; + u32 power; pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); mutex_lock(&sn_hotplug_mutex); - *value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num); + power = pcibus_info->pbi_enabled_devices & (1 << slot->device_num); + *value = power ? 1 : 0; mutex_unlock(&sn_hotplug_mutex); return 0; } @@ -553,8 +555,8 @@ static int sn_pci_hotplug_init(void) int rc; int registered = 0; - if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) { - printk(KERN_ERR "%s: PROM version must be greater than 4.30\n", + if (!sn_prom_feature_available(PRF_HOTPLUG_SUPPORT)) { + printk(KERN_ERR "%s: PROM version does not support hotplug.\n", __FUNCTION__); return -EPERM; } diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 5c70f43..7208b95 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -168,9 +168,9 @@ #define DISABLE_CARD 1 * error Messages */ #define msg_initialization_err "Initialization failure, error=%d\n" -#define msg_button_on "PCI slot #%d - powering on due to button press.\n" -#define msg_button_off "PCI slot #%d - powering off due to button press.\n" -#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" +#define msg_button_on "PCI slot #%s - powering on due to button press.\n" +#define msg_button_off "PCI slot #%s - powering off due to button press.\n" +#define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n" /* sysfs functions for the hotplug controller info */ extern void shpchp_create_ctrl_files (struct controller *ctrl); @@ -196,7 +196,7 @@ #ifdef CONFIG_ACPI static inline int get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) { - if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp))) + if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) return -ENODEV; return 0; } diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 3be4d49..a14e7de 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -491,16 +491,9 @@ #ifdef CONFIG_HOTPLUG_PCI_SHPC_POLL_EVEN shpchp_poll_mode = 1; #endif - shpchp_wq = create_singlethread_workqueue("shpchpd"); - if (!shpchp_wq) - return -ENOMEM; - retval = pci_register_driver(&shpc_driver); dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - if (retval) { - destroy_workqueue(shpchp_wq); - } return retval; } @@ -508,7 +501,6 @@ static void __exit shpcd_cleanup(void) { dbg("unload_shpchpd()\n"); pci_unregister_driver(&shpc_driver); - destroy_workqueue(shpchp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 4e63814..c39901d 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -72,7 +72,7 @@ u8 shpchp_handle_attention_button(u8 hp_ /* * Button pressed - See if need to TAKE ACTION!!! */ - info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Button pressed on Slot(%s)\n", p_slot->name); event_type = INT_BUTTON_PRESS; queue_interrupt_event(p_slot, event_type); @@ -101,7 +101,7 @@ u8 shpchp_handle_switch_change(u8 hp_slo /* * Switch opened */ - info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Latch open on Slot(%s)\n", p_slot->name); event_type = INT_SWITCH_OPEN; if (p_slot->pwr_save && p_slot->presence_save) { event_type = INT_POWER_FAULT; @@ -111,7 +111,7 @@ u8 shpchp_handle_switch_change(u8 hp_slo /* * Switch closed */ - info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Latch close on Slot(%s)\n", p_slot->name); event_type = INT_SWITCH_CLOSE; } @@ -139,13 +139,13 @@ u8 shpchp_handle_presence_change(u8 hp_s /* * Card Present */ - info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Card present on Slot(%s)\n", p_slot->name); event_type = INT_PRESENCE_ON; } else { /* * Not Present */ - info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Card not present on Slot(%s)\n", p_slot->name); event_type = INT_PRESENCE_OFF; } @@ -169,14 +169,14 @@ u8 shpchp_handle_power_fault(u8 hp_slot, /* * Power fault Cleared */ - info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Power fault cleared on Slot(%s)\n", p_slot->name); p_slot->status = 0x00; event_type = INT_POWER_FAULT_CLEAR; } else { /* * Power fault */ - info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Power fault on Slot(%s)\n", p_slot->name); event_type = INT_POWER_FAULT; /* set power fault status for this board */ p_slot->status = 0xFF; @@ -496,10 +496,10 @@ static void handle_button_press_event(st p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (getstatus) { p_slot->state = BLINKINGOFF_STATE; - info(msg_button_off, p_slot->number); + info(msg_button_off, p_slot->name); } else { p_slot->state = BLINKINGON_STATE; - info(msg_button_on, p_slot->number); + info(msg_button_on, p_slot->name); } /* blink green LED and turn off amber */ p_slot->hpc_ops->green_led_blink(p_slot); @@ -522,7 +522,7 @@ static void handle_button_press_event(st else p_slot->hpc_ops->green_led_off(p_slot); p_slot->hpc_ops->set_attention_status(p_slot, 0); - info(msg_button_cancel, p_slot->number); + info(msg_button_cancel, p_slot->name); p_slot->state = STATIC_STATE; break; case POWEROFF_STATE: @@ -575,17 +575,17 @@ static int shpchp_enable_slot (struct sl mutex_lock(&p_slot->ctrl->crit_sect); rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { - info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + info("No adapter on slot(%s)\n", p_slot->name); goto out; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { - info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + info("Latch open on slot(%s)\n", p_slot->name); goto out; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { - info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); + info("Already enabled on slot(%s)\n", p_slot->name); goto out; } @@ -634,17 +634,17 @@ static int shpchp_disable_slot (struct s rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { - info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + info("No adapter on slot(%s)\n", p_slot->name); goto out; } rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { - info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + info("Latch open on slot(%s)\n", p_slot->name); goto out; } rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || !getstatus) { - info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); + info("Already disabled slot(%s)\n", p_slot->name); goto out; } diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 66123cf..45facaa 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -90,77 +90,94 @@ #define UPDOWN 0x20000000 #define MRLSENSOR 0x40000000 #define ATTN_BUTTON 0x80000000 -/* Slot Status Field Definitions */ -/* Slot State */ -#define PWR_ONLY 0x0001 -#define ENABLED 0x0002 -#define DISABLED 0x0003 - -/* Power Indicator State */ -#define PWR_LED_ON 0x0004 -#define PWR_LED_BLINK 0x0008 -#define PWR_LED_OFF 0x000c - -/* Attention Indicator State */ -#define ATTEN_LED_ON 0x0010 -#define ATTEN_LED_BLINK 0x0020 -#define ATTEN_LED_OFF 0x0030 - -/* Power Fault */ -#define pwr_fault 0x0040 - -/* Attention Button */ -#define ATTEN_BUTTON 0x0080 - -/* MRL Sensor */ -#define MRL_SENSOR 0x0100 - -/* 66 MHz Capable */ -#define IS_66MHZ_CAP 0x0200 - -/* PRSNT1#/PRSNT2# */ -#define SLOT_EMP 0x0c00 - -/* PCI-X Capability */ -#define NON_PCIX 0x0000 -#define PCIX_66 0x1000 -#define PCIX_133 0x3000 -#define PCIX_266 0x4000 /* For PI = 2 only */ -#define PCIX_533 0x5000 /* For PI = 2 only */ - -/* SHPC 'write' operations/commands */ - -/* Slot operation - 0x00h to 0x3Fh */ - -#define NO_CHANGE 0x00 - -/* Slot state - Bits 0 & 1 of controller command register */ -#define SET_SLOT_PWR 0x01 -#define SET_SLOT_ENABLE 0x02 -#define SET_SLOT_DISABLE 0x03 +/* + * Interrupt Locator Register definitions + */ +#define CMD_INTR_PENDING (1 << 0) +#define SLOT_INTR_PENDING(i) (1 << (i + 1)) -/* Power indicator state - Bits 2 & 3 of controller command register*/ -#define SET_PWR_ON 0x04 -#define SET_PWR_BLINK 0x08 -#define SET_PWR_OFF 0x0C +/* + * Controller SERR-INT Register + */ +#define GLOBAL_INTR_MASK (1 << 0) +#define GLOBAL_SERR_MASK (1 << 1) +#define COMMAND_INTR_MASK (1 << 2) +#define ARBITER_SERR_MASK (1 << 3) +#define COMMAND_DETECTED (1 << 16) +#define ARBITER_DETECTED (1 << 17) +#define SERR_INTR_RSVDZ_MASK 0xfffc0000 -/* Attention indicator state - Bits 4 & 5 of controller command register*/ -#define SET_ATTN_ON 0x010 -#define SET_ATTN_BLINK 0x020 -#define SET_ATTN_OFF 0x030 +/* + * Logical Slot Register definitions + */ +#define SLOT_REG(i) (SLOT1 + (4 * i)) + +#define SLOT_STATE_SHIFT (0) +#define SLOT_STATE_MASK (3 << 0) +#define SLOT_STATE_PWRONLY (1) +#define SLOT_STATE_ENABLED (2) +#define SLOT_STATE_DISABLED (3) +#define PWR_LED_STATE_SHIFT (2) +#define PWR_LED_STATE_MASK (3 << 2) +#define ATN_LED_STATE_SHIFT (4) +#define ATN_LED_STATE_MASK (3 << 4) +#define ATN_LED_STATE_ON (1) +#define ATN_LED_STATE_BLINK (2) +#define ATN_LED_STATE_OFF (3) +#define POWER_FAULT (1 << 6) +#define ATN_BUTTON (1 << 7) +#define MRL_SENSOR (1 << 8) +#define MHZ66_CAP (1 << 9) +#define PRSNT_SHIFT (10) +#define PRSNT_MASK (3 << 10) +#define PCIX_CAP_SHIFT (12) +#define PCIX_CAP_MASK_PI1 (3 << 12) +#define PCIX_CAP_MASK_PI2 (7 << 12) +#define PRSNT_CHANGE_DETECTED (1 << 16) +#define ISO_PFAULT_DETECTED (1 << 17) +#define BUTTON_PRESS_DETECTED (1 << 18) +#define MRL_CHANGE_DETECTED (1 << 19) +#define CON_PFAULT_DETECTED (1 << 20) +#define PRSNT_CHANGE_INTR_MASK (1 << 24) +#define ISO_PFAULT_INTR_MASK (1 << 25) +#define BUTTON_PRESS_INTR_MASK (1 << 26) +#define MRL_CHANGE_INTR_MASK (1 << 27) +#define CON_PFAULT_INTR_MASK (1 << 28) +#define MRL_CHANGE_SERR_MASK (1 << 29) +#define CON_PFAULT_SERR_MASK (1 << 30) +#define SLOT_REG_RSVDZ_MASK (1 << 15) | (7 << 21) -/* Set bus speed/mode A - 0x40h to 0x47h */ -#define SETA_PCI_33MHZ 0x40 +/* + * SHPC Command Code definitnions + * + * Slot Operation 00h - 3Fh + * Set Bus Segment Speed/Mode A 40h - 47h + * Power-Only All Slots 48h + * Enable All Slots 49h + * Set Bus Segment Speed/Mode B (PI=2) 50h - 5Fh + * Reserved Command Codes 60h - BFh + * Vendor Specific Commands C0h - FFh + */ +#define SET_SLOT_PWR 0x01 /* Slot Operation */ +#define SET_SLOT_ENABLE 0x02 +#define SET_SLOT_DISABLE 0x03 +#define SET_PWR_ON 0x04 +#define SET_PWR_BLINK 0x08 +#define SET_PWR_OFF 0x0c +#define SET_ATTN_ON 0x10 +#define SET_ATTN_BLINK 0x20 +#define SET_ATTN_OFF 0x30 +#define SETA_PCI_33MHZ 0x40 /* Set Bus Segment Speed/Mode A */ #define SETA_PCI_66MHZ 0x41 #define SETA_PCIX_66MHZ 0x42 #define SETA_PCIX_100MHZ 0x43 #define SETA_PCIX_133MHZ 0x44 -#define RESERV_1 0x45 -#define RESERV_2 0x46 -#define RESERV_3 0x47 - -/* Set bus speed/mode B - 0x50h to 0x5fh */ -#define SETB_PCI_33MHZ 0x50 +#define SETA_RESERVED1 0x45 +#define SETA_RESERVED2 0x46 +#define SETA_RESERVED3 0x47 +#define SET_PWR_ONLY_ALL 0x48 /* Power-Only All Slots */ +#define SET_ENABLE_ALL 0x49 /* Enable All Slots */ +#define SETB_PCI_33MHZ 0x50 /* Set Bus Segment Speed/Mode B */ #define SETB_PCI_66MHZ 0x51 #define SETB_PCIX_66MHZ_PM 0x52 #define SETB_PCIX_100MHZ_PM 0x53 @@ -174,81 +191,115 @@ #define SETB_PCIX_133MHZ_266 0x5a #define SETB_PCIX_66MHZ_533 0x5b #define SETB_PCIX_100MHZ_533 0x5c #define SETB_PCIX_133MHZ_533 0x5d +#define SETB_RESERVED1 0x5e +#define SETB_RESERVED2 0x5f - -/* Power-on all slots - 0x48h */ -#define SET_PWR_ON_ALL 0x48 - -/* Enable all slots - 0x49h */ -#define SET_ENABLE_ALL 0x49 - -/* SHPC controller command error code */ +/* + * SHPC controller command error code + */ #define SWITCH_OPEN 0x1 #define INVALID_CMD 0x2 #define INVALID_SPEED_MODE 0x4 -/* For accessing SHPC Working Register Set */ +/* + * For accessing SHPC Working Register Set via PCI Configuration Space + */ #define DWORD_SELECT 0x2 #define DWORD_DATA 0x4 -#define BASE_OFFSET 0x0 /* Field Offset in Logical Slot Register - byte boundary */ #define SLOT_EVENT_LATCH 0x2 #define SLOT_SERR_INT_MASK 0x3 -static spinlock_t hpc_event_lock; - DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */ static int ctlr_seq_num = 0; /* Controller sequenc # */ static spinlock_t list_lock; -static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); +static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); -static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); +static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs); +static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec); static int hpc_check_cmd_status(struct controller *ctrl); -/* This is the interrupt polling timeout function. */ -static void int_poll_timeout(unsigned long lphp_ctlr) +static inline u8 shpc_readb(struct controller *ctrl, int reg) { - struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr; + return readb(ctrl->hpc_ctlr_handle->creg + reg); +} - DBG_ENTER_ROUTINE +static inline void shpc_writeb(struct controller *ctrl, int reg, u8 val) +{ + writeb(val, ctrl->hpc_ctlr_handle->creg + reg); +} - if ( !php_ctlr ) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return; - } +static inline u16 shpc_readw(struct controller *ctrl, int reg) +{ + return readw(ctrl->hpc_ctlr_handle->creg + reg); +} - /* Poll for interrupt events. regs == NULL => polling */ - shpc_isr( 0, (void *)php_ctlr, NULL ); +static inline void shpc_writew(struct controller *ctrl, int reg, u16 val) +{ + writew(val, ctrl->hpc_ctlr_handle->creg + reg); +} - init_timer(&php_ctlr->int_poll_timer); - if (!shpchp_poll_time) - shpchp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/ +static inline u32 shpc_readl(struct controller *ctrl, int reg) +{ + return readl(ctrl->hpc_ctlr_handle->creg + reg); +} - start_int_poll_timer(php_ctlr, shpchp_poll_time); - - return; +static inline void shpc_writel(struct controller *ctrl, int reg, u32 val) +{ + writel(val, ctrl->hpc_ctlr_handle->creg + reg); } -/* This function starts the interrupt polling timer. */ -static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds) +static inline int shpc_indirect_read(struct controller *ctrl, int index, + u32 *value) { - if (!php_ctlr) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return; - } + int rc; + u32 cap_offset = ctrl->cap_offset; + struct pci_dev *pdev = ctrl->pci_dev; + + rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index); + if (rc) + return rc; + return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value); +} + +/* + * This is the interrupt polling timeout function. + */ +static void int_poll_timeout(unsigned long lphp_ctlr) +{ + struct php_ctlr_state_s *php_ctlr = + (struct php_ctlr_state_s *)lphp_ctlr; + + DBG_ENTER_ROUTINE + + /* Poll for interrupt events. regs == NULL => polling */ + shpc_isr(0, php_ctlr->callback_instance_id, NULL); + + init_timer(&php_ctlr->int_poll_timer); + if (!shpchp_poll_time) + shpchp_poll_time = 2; /* default polling interval is 2 sec */ - if ( ( seconds <= 0 ) || ( seconds > 60 ) ) - seconds = 2; /* Clamp to sane value */ + start_int_poll_timer(php_ctlr, shpchp_poll_time); - php_ctlr->int_poll_timer.function = &int_poll_timeout; - php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; /* Instance data */ - php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ; - add_timer(&php_ctlr->int_poll_timer); + DBG_LEAVE_ROUTINE +} - return; +/* + * This function starts the interrupt polling timer. + */ +static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec) +{ + /* Clamp to sane value */ + if ((sec <= 0) || (sec > 60)) + sec = 2; + + php_ctlr->int_poll_timer.function = &int_poll_timeout; + php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; + php_ctlr->int_poll_timer.expires = jiffies + sec * HZ; + add_timer(&php_ctlr->int_poll_timer); } static inline int shpc_wait_cmd(struct controller *ctrl) @@ -272,7 +323,7 @@ static inline int shpc_wait_cmd(struct c static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u16 cmd_status; int retval = 0; u16 temp_word; @@ -282,14 +333,8 @@ static int shpc_write_cmd(struct slot *s mutex_lock(&slot->ctrl->cmd_lock); - if (!php_ctlr) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - retval = -EINVAL; - goto out; - } - for (i = 0; i < 10; i++) { - cmd_status = readw(php_ctlr->creg + CMD_STATUS); + cmd_status = shpc_readw(ctrl, CMD_STATUS); if (!(cmd_status & 0x1)) break; @@ -297,7 +342,7 @@ static int shpc_write_cmd(struct slot *s msleep(100); } - cmd_status = readw(php_ctlr->creg + CMD_STATUS); + cmd_status = shpc_readw(ctrl, CMD_STATUS); if (cmd_status & 0x1) { /* After 1 sec and and the controller is still busy */ @@ -314,7 +359,7 @@ static int shpc_write_cmd(struct slot *s * command. */ slot->ctrl->cmd_busy = 1; - writew(temp_word, php_ctlr->creg + CMD); + shpc_writew(ctrl, CMD, temp_word); /* * Wait for command completion. @@ -338,18 +383,12 @@ static int shpc_write_cmd(struct slot *s static int hpc_check_cmd_status(struct controller *ctrl) { - struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; u16 cmd_status; int retval = 0; DBG_ENTER_ROUTINE - - if (!ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - cmd_status = readw(php_ctlr->creg + CMD_STATUS) & 0x000F; + cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; switch (cmd_status >> 1) { case 0: @@ -378,37 +417,27 @@ static int hpc_check_cmd_status(struct c static int hpc_get_attention_status(struct slot *slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u32 slot_reg; - u16 slot_status; - u8 atten_led_state; + u8 state; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); - slot_status = (u16) slot_reg; - atten_led_state = (slot_status & 0x0030) >> 4; + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; - switch (atten_led_state) { - case 0: - *status = 0xFF; /* Reserved */ - break; - case 1: + switch (state) { + case ATN_LED_STATE_ON: *status = 1; /* On */ break; - case 2: + case ATN_LED_STATE_BLINK: *status = 2; /* Blink */ break; - case 3: + case ATN_LED_STATE_OFF: *status = 0; /* Off */ break; default: - *status = 0xFF; + *status = 0xFF; /* Reserved */ break; } @@ -418,64 +447,44 @@ static int hpc_get_attention_status(stru static int hpc_get_power_status(struct slot * slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u32 slot_reg; - u16 slot_status; - u8 slot_state; - int retval = 0; + u8 state; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); - slot_status = (u16) slot_reg; - slot_state = (slot_status & 0x0003); + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; - switch (slot_state) { - case 0: - *status = 0xFF; - break; - case 1: + switch (state) { + case SLOT_STATE_PWRONLY: *status = 2; /* Powered only */ break; - case 2: + case SLOT_STATE_ENABLED: *status = 1; /* Enabled */ break; - case 3: + case SLOT_STATE_DISABLED: *status = 0; /* Disabled */ break; default: - *status = 0xFF; + *status = 0xFF; /* Reserved */ break; } DBG_LEAVE_ROUTINE - return retval; + return 0; } static int hpc_get_latch_status(struct slot *slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u32 slot_reg; - u16 slot_status; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); - slot_status = (u16)slot_reg; - - *status = ((slot_status & 0x0100) == 0) ? 0 : 1; /* 0 -> close; 1 -> open */ - + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + *status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */ DBG_LEAVE_ROUTINE return 0; @@ -483,22 +492,15 @@ static int hpc_get_latch_status(struct s static int hpc_get_adapter_status(struct slot *slot, u8 *status) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u32 slot_reg; - u16 slot_status; - u8 card_state; + u8 state; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); - slot_status = (u16)slot_reg; - card_state = (u8)((slot_status & 0x0C00) >> 10); - *status = (card_state != 0x3) ? 1 : 0; + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; + *status = (state != 0x3) ? 1 : 0; DBG_LEAVE_ROUTINE return 0; @@ -506,16 +508,11 @@ static int hpc_get_adapter_status(struct static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; DBG_ENTER_ROUTINE - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - *prog_int = readb(php_ctlr->creg + PROG_INTERFACE); + *prog_int = shpc_readb(ctrl, PROG_INTERFACE); DBG_LEAVE_ROUTINE return 0; @@ -524,13 +521,27 @@ static int hpc_get_prog_int(struct slot static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) { int retval = 0; - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u32 slot_reg = readl(php_ctlr->creg + SLOT1 + 4 * slot->hp_slot); - u8 pcix_cap = (slot_reg >> 12) & 7; - u8 m66_cap = (slot_reg >> 9) & 1; + struct controller *ctrl = slot->ctrl; + u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + u8 m66_cap = !!(slot_reg & MHZ66_CAP); + u8 pi, pcix_cap; DBG_ENTER_ROUTINE + if ((retval = hpc_get_prog_int(slot, &pi))) + return retval; + + switch (pi) { + case 1: + pcix_cap = (slot_reg & PCIX_CAP_MASK_PI1) >> PCIX_CAP_SHIFT; + break; + case 2: + pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT; + break; + default: + return -ENODEV; + } + dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", __FUNCTION__, slot_reg, pcix_cap, m66_cap); @@ -564,20 +575,15 @@ static int hpc_get_adapter_speed(struct static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u16 sec_bus_status; u8 pi; int retval = 0; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - pi = readb(php_ctlr->creg + PROG_INTERFACE); - sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); + pi = shpc_readb(ctrl, PROG_INTERFACE); + sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); if (pi == 2) { *mode = (sec_bus_status & 0x0100) >> 8; @@ -593,128 +599,53 @@ static int hpc_get_mode1_ECC_cap(struct static int hpc_query_power_fault(struct slot * slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u32 slot_reg; - u16 slot_status; - u8 pwr_fault_state, status; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); - slot_status = (u16) slot_reg; - pwr_fault_state = (slot_status & 0x0040) >> 7; - status = (pwr_fault_state == 1) ? 0 : 1; + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); DBG_LEAVE_ROUTINE /* Note: Logic 0 => fault */ - return status; + return !(slot_reg & POWER_FAULT); } static int hpc_set_attention_status(struct slot *slot, u8 value) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u8 slot_cmd = 0; - int rc = 0; - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } switch (value) { case 0 : - slot_cmd = 0x30; /* OFF */ + slot_cmd = SET_ATTN_OFF; /* OFF */ break; case 1: - slot_cmd = 0x10; /* ON */ + slot_cmd = SET_ATTN_ON; /* ON */ break; case 2: - slot_cmd = 0x20; /* BLINK */ + slot_cmd = SET_ATTN_BLINK; /* BLINK */ break; default: return -1; } - shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - - return rc; + return shpc_write_cmd(slot, slot->hp_slot, slot_cmd); } static void hpc_set_green_led_on(struct slot *slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return ; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return ; - } - - slot_cmd = 0x04; - - shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - - return; + shpc_write_cmd(slot, slot->hp_slot, SET_PWR_ON); } static void hpc_set_green_led_off(struct slot *slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return ; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return ; - } - - slot_cmd = 0x0C; - - shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - - return; + shpc_write_cmd(slot, slot->hp_slot, SET_PWR_OFF); } static void hpc_set_green_led_blink(struct slot *slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return ; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return ; - } - - slot_cmd = 0x08; - - shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - - return; + shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK); } int shpc_get_ctlr_slot_config(struct controller *ctrl, @@ -724,21 +655,17 @@ int shpc_get_ctlr_slot_config(struct con int *updown, /* physical_slot_num increament: 1 or -1 */ int *flags) { - struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; + u32 slot_config; DBG_ENTER_ROUTINE - if (!ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - *first_device_num = php_ctlr->slot_device_offset; /* Obtained in shpc_init() */ - *num_ctlr_slots = php_ctlr->num_slots; /* Obtained in shpc_init() */ + slot_config = shpc_readl(ctrl, SLOT_CONFIG); + *first_device_num = (slot_config & FIRST_DEV_NUM) >> 8; + *num_ctlr_slots = slot_config & SLOT_NUM; + *physical_slot_num = (slot_config & PSN) >> 16; + *updown = ((slot_config & UPDOWN) >> 29) ? 1 : -1; - *physical_slot_num = (readl(php_ctlr->creg + SLOT_CONFIG) & PSN) >> 16; dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num); - *updown = ((readl(php_ctlr->creg + SLOT_CONFIG) & UPDOWN ) >> 29) ? 1 : -1; DBG_LEAVE_ROUTINE return 0; @@ -749,22 +676,34 @@ static void hpc_release_ctlr(struct cont struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; struct php_ctlr_state_s *p, *p_prev; int i; + u32 slot_reg, serr_int; DBG_ENTER_ROUTINE - if (!ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return ; - } - /* - * Mask all slot event interrupts + * Mask event interrupts and SERRs of all slots */ - for (i = 0; i < ctrl->num_slots; i++) - writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i)); + for (i = 0; i < ctrl->num_slots; i++) { + slot_reg = shpc_readl(ctrl, SLOT_REG(i)); + slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | + BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | + CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK | + CON_PFAULT_SERR_MASK); + slot_reg &= ~SLOT_REG_RSVDZ_MASK; + shpc_writel(ctrl, SLOT_REG(i), slot_reg); + } cleanup_slots(ctrl); + /* + * Mask SERR and System Interrut generation + */ + serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); + serr_int |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK | + COMMAND_INTR_MASK | ARBITER_SERR_MASK); + serr_int &= ~SERR_INTR_RSVDZ_MASK; + shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); + if (shpchp_poll_mode) { del_timer(&php_ctlr->int_poll_timer); } else { @@ -800,113 +739,79 @@ static void hpc_release_ctlr(struct cont kfree(php_ctlr); + /* + * If this is the last controller to be released, destroy the + * shpchpd work queue + */ + if (atomic_dec_and_test(&shpchp_num_controllers)) + destroy_workqueue(shpchp_wq); + DBG_LEAVE_ROUTINE } static int hpc_power_on_slot(struct slot * slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - int retval = 0; + int retval; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } - slot_cmd = 0x01; - - retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - + retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR); if (retval) { err("%s: Write command failed!\n", __FUNCTION__); - return -1; + return retval; } DBG_LEAVE_ROUTINE - return retval; + return 0; } static int hpc_slot_enable(struct slot * slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - int retval = 0; + int retval; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } - /* 3A => Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ - slot_cmd = 0x3A; - - retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - + /* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ + retval = shpc_write_cmd(slot, slot->hp_slot, + SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF); if (retval) { err("%s: Write command failed!\n", __FUNCTION__); - return -1; + return retval; } DBG_LEAVE_ROUTINE - return retval; + return 0; } static int hpc_slot_disable(struct slot * slot) { - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; - u8 slot_cmd; - int retval = 0; + int retval; DBG_ENTER_ROUTINE - if (!slot->ctrl->hpc_ctlr_handle) { - err("%s: Invalid HPC controller handle!\n", __FUNCTION__); - return -1; - } - - if (slot->hp_slot >= php_ctlr->num_slots) { - err("%s: Invalid HPC slot number!\n", __FUNCTION__); - return -1; - } - - /* 1F => Slot - Disable, Power Indicator - Off, Attention Indicator - On */ - slot_cmd = 0x1F; - - retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd); - + /* Slot - Disable, Power Indicator - Off, Attention Indicator - On */ + retval = shpc_write_cmd(slot, slot->hp_slot, + SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON); if (retval) { err("%s: Write command failed!\n", __FUNCTION__); - return -1; + return retval; } DBG_LEAVE_ROUTINE - return retval; + return 0; } static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) { int retval; - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; u8 pi, cmd; DBG_ENTER_ROUTINE - pi = readb(php_ctlr->creg + PROG_INTERFACE); + pi = shpc_readb(ctrl, PROG_INTERFACE); if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) return -EINVAL; @@ -965,100 +870,86 @@ static int hpc_set_bus_speed_mode(struct return retval; } -static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) +static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs) { - struct controller *ctrl = NULL; - struct php_ctlr_state_s *php_ctlr; - u8 schedule_flag = 0; - u8 temp_byte; - u32 temp_dword, intr_loc, intr_loc2; + struct controller *ctrl = (struct controller *)dev_id; + struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; + u32 serr_int, slot_reg, intr_loc, intr_loc2; int hp_slot; - if (!dev_id) - return IRQ_NONE; - - if (!shpchp_poll_mode) { - ctrl = (struct controller *)dev_id; - php_ctlr = ctrl->hpc_ctlr_handle; - } else { - php_ctlr = (struct php_ctlr_state_s *) dev_id; - ctrl = (struct controller *)php_ctlr->callback_instance_id; - } - - if (!ctrl) - return IRQ_NONE; - - if (!php_ctlr || !php_ctlr->creg) - return IRQ_NONE; - /* Check to see if it was our interrupt */ - intr_loc = readl(php_ctlr->creg + INTR_LOC); - + intr_loc = shpc_readl(ctrl, INTR_LOC); if (!intr_loc) return IRQ_NONE; + dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); if(!shpchp_poll_mode) { - /* Mask Global Interrupt Mask - see implementation note on p. 139 */ - /* of SHPC spec rev 1.0*/ - temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); - temp_dword |= 0x00000001; - writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + /* + * Mask Global Interrupt Mask - see implementation + * note on p. 139 of SHPC spec rev 1.0 + */ + serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); + serr_int |= GLOBAL_INTR_MASK; + serr_int &= ~SERR_INTR_RSVDZ_MASK; + shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); - intr_loc2 = readl(php_ctlr->creg + INTR_LOC); + intr_loc2 = shpc_readl(ctrl, INTR_LOC); dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); } - if (intr_loc & 0x0001) { + if (intr_loc & CMD_INTR_PENDING) { /* * Command Complete Interrupt Pending * RO only - clear by writing 1 to the Command Completion * Detect bit in Controller SERR-INT register */ - temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); - temp_dword &= 0xfffdffff; - writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); + serr_int &= ~SERR_INTR_RSVDZ_MASK; + shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); + ctrl->cmd_busy = 0; wake_up_interruptible(&ctrl->queue); } - if ((intr_loc = (intr_loc >> 1)) == 0) + if (!(intr_loc & ~CMD_INTR_PENDING)) goto out; for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { - /* To find out which slot has interrupt pending */ - if ((intr_loc >> hp_slot) & 0x01) { - temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot)); - dbg("%s: Slot %x with intr, slot register = %x\n", - __FUNCTION__, hp_slot, temp_dword); - temp_byte = (temp_dword >> 16) & 0xFF; - if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08)) - schedule_flag += php_ctlr->switch_change_callback( - hp_slot, php_ctlr->callback_instance_id); - if ((php_ctlr->attention_button_callback) && (temp_byte & 0x04)) - schedule_flag += php_ctlr->attention_button_callback( - hp_slot, php_ctlr->callback_instance_id); - if ((php_ctlr->presence_change_callback) && (temp_byte & 0x01)) - schedule_flag += php_ctlr->presence_change_callback( - hp_slot , php_ctlr->callback_instance_id); - if ((php_ctlr->power_fault_callback) && (temp_byte & 0x12)) - schedule_flag += php_ctlr->power_fault_callback( - hp_slot, php_ctlr->callback_instance_id); - - /* Clear all slot events */ - temp_dword = 0xe01f3fff; - writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot)); - - intr_loc2 = readl(php_ctlr->creg + INTR_LOC); - dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); - } + /* To find out which slot has interrupt pending */ + if (!(intr_loc & SLOT_INTR_PENDING(hp_slot))) + continue; + + slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); + dbg("%s: Slot %x with intr, slot register = %x\n", + __FUNCTION__, hp_slot, slot_reg); + + if (slot_reg & MRL_CHANGE_DETECTED) + php_ctlr->switch_change_callback( + hp_slot, php_ctlr->callback_instance_id); + + if (slot_reg & BUTTON_PRESS_DETECTED) + php_ctlr->attention_button_callback( + hp_slot, php_ctlr->callback_instance_id); + + if (slot_reg & PRSNT_CHANGE_DETECTED) + php_ctlr->presence_change_callback( + hp_slot , php_ctlr->callback_instance_id); + + if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED)) + php_ctlr->power_fault_callback( + hp_slot, php_ctlr->callback_instance_id); + + /* Clear all slot events */ + slot_reg &= ~SLOT_REG_RSVDZ_MASK; + shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); } out: if (!shpchp_poll_mode) { /* Unmask Global Interrupt Mask */ - temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); - temp_dword &= 0xfffffffe; - writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); + serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); + shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); } return IRQ_HANDLED; @@ -1067,11 +958,11 @@ static irqreturn_t shpc_isr(int IRQ, voi static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) { int retval = 0; - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; - u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); - u32 slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); - u32 slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); + u8 pi = shpc_readb(ctrl, PROG_INTERFACE); + u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); + u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2); DBG_ENTER_ROUTINE @@ -1114,10 +1005,10 @@ static int hpc_get_max_bus_speed (struct static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) { int retval = 0; - struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; + struct controller *ctrl = slot->ctrl; enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; - u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG); - u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); + u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG); + u8 pi = shpc_readb(ctrl, PROG_INTERFACE); u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); DBG_ENTER_ROUTINE @@ -1206,28 +1097,14 @@ static struct hpc_ops shpchp_hpc_ops = { .release_ctlr = hpc_release_ctlr, }; -inline static int shpc_indirect_creg_read(struct controller *ctrl, int index, - u32 *value) -{ - int rc; - u32 cap_offset = ctrl->cap_offset; - struct pci_dev *pdev = ctrl->pci_dev; - - rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index); - if (rc) - return rc; - return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value); -} - int shpc_init(struct controller * ctrl, struct pci_dev * pdev) { struct php_ctlr_state_s *php_ctlr, *p; void *instance_id = ctrl; int rc, num_slots = 0; u8 hp_slot; - static int first = 1; u32 shpc_base_offset; - u32 tempdword, slot_reg; + u32 tempdword, slot_reg, slot_config; u8 i; DBG_ENTER_ROUTINE @@ -1257,13 +1134,13 @@ int shpc_init(struct controller * ctrl, } dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset); - rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset); + rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset); if (rc) { err("%s: cannot read base_offset\n", __FUNCTION__); goto abort_free_ctlr; } - rc = shpc_indirect_creg_read(ctrl, 3, &tempdword); + rc = shpc_indirect_read(ctrl, 3, &tempdword); if (rc) { err("%s: cannot read slot config\n", __FUNCTION__); goto abort_free_ctlr; @@ -1272,7 +1149,7 @@ int shpc_init(struct controller * ctrl, dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots); for (i = 0; i < 9 + num_slots; i++) { - rc = shpc_indirect_creg_read(ctrl, i, &tempdword); + rc = shpc_indirect_read(ctrl, i, &tempdword); if (rc) { err("%s: cannot read creg (index = %d)\n", __FUNCTION__, i); @@ -1287,11 +1164,6 @@ int shpc_init(struct controller * ctrl, ctrl->mmio_size = 0x24 + 0x4 * num_slots; } - if (first) { - spin_lock_init(&hpc_event_lock); - first = 0; - } - info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device); @@ -1326,29 +1198,39 @@ int shpc_init(struct controller * ctrl, php_ctlr->power_fault_callback = shpchp_handle_power_fault; php_ctlr->callback_instance_id = instance_id; + ctrl->hpc_ctlr_handle = php_ctlr; + ctrl->hpc_ops = &shpchp_hpc_ops; + /* Return PCI Controller Info */ - php_ctlr->slot_device_offset = (readl(php_ctlr->creg + SLOT_CONFIG) & FIRST_DEV_NUM ) >> 8; - php_ctlr->num_slots = readl(php_ctlr->creg + SLOT_CONFIG) & SLOT_NUM; + slot_config = shpc_readl(ctrl, SLOT_CONFIG); + php_ctlr->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8; + php_ctlr->num_slots = slot_config & SLOT_NUM; dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset); dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots); /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ - tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); - tempdword = 0x0003000f; - writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE); - tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + tempdword |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK | + COMMAND_INTR_MASK | ARBITER_SERR_MASK); + tempdword &= ~SERR_INTR_RSVDZ_MASK; + shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); /* Mask the MRL sensor SERR Mask of individual slot in * Slot SERR-INT Mask & clear all the existing event if any */ for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); + slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); - tempdword = 0xffff3fff; - writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); + slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | + BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | + CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK | + CON_PFAULT_SERR_MASK); + slot_reg &= ~SLOT_REG_RSVDZ_MASK; + shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); } if (shpchp_poll_mode) {/* Install interrupt polling code */ @@ -1392,24 +1274,37 @@ int shpc_init(struct controller * ctrl, } spin_unlock(&list_lock); - ctlr_seq_num++; - ctrl->hpc_ctlr_handle = php_ctlr; - ctrl->hpc_ops = &shpchp_hpc_ops; + /* + * If this is the first controller to be initialized, + * initialize the shpchpd work queue + */ + if (atomic_add_return(1, &shpchp_num_controllers) == 1) { + shpchp_wq = create_singlethread_workqueue("shpchpd"); + if (!shpchp_wq) + return -ENOMEM; + } + + /* + * Unmask all event interrupts of all slots + */ for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { - slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); + slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); - tempdword = 0xe01f3fff; - writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); + slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | + BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | + CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK); + shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); } if (!shpchp_poll_mode) { /* Unmask all general input interrupts and SERR */ - tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); - tempdword = 0x0000000a; - writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE); - tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); + tempdword &= ~(GLOBAL_INTR_MASK | COMMAND_INTR_MASK | + SERR_INTR_RSVDZ_MASK); + shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); + tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); } diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 257adc2..0a6b25e 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -47,21 +47,28 @@ static void program_fw_provided_values(s return; /* use default values if we can't get them from firmware */ - if (get_hp_params_from_firmware(dev, &hpp)) { - hpp.cache_line_size = 8; - hpp.latency_timer = 0x40; - hpp.enable_serr = 0; - hpp.enable_perr = 0; + if (get_hp_params_from_firmware(dev, &hpp) || + !hpp.t0 || (hpp.t0->revision > 1)) { + printk(KERN_WARNING + "%s: Could not get hotplug parameters. Use defaults\n", + __FUNCTION__); + hpp.t0 = &hpp.type0_data; + hpp.t0->revision = 0; + hpp.t0->cache_line_size = 8; + hpp.t0->latency_timer = 0x40; + hpp.t0->enable_serr = 0; + hpp.t0->enable_perr = 0; } - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer); + pci_write_config_byte(dev, + PCI_CACHE_LINE_SIZE, hpp.t0->cache_line_size); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.t0->latency_timer); pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); - if (hpp.enable_serr) + if (hpp.t0->enable_serr) pci_cmd |= PCI_COMMAND_SERR; else pci_cmd &= ~PCI_COMMAND_SERR; - if (hpp.enable_perr) + if (hpp.t0->enable_perr) pci_cmd |= PCI_COMMAND_PARITY; else pci_cmd &= ~PCI_COMMAND_PARITY; @@ -70,13 +77,13 @@ static void program_fw_provided_values(s /* Program bridge control value and child devices */ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, - hpp.latency_timer); + hpp.t0->latency_timer); pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); - if (hpp.enable_serr) + if (hpp.t0->enable_serr) pci_bctl |= PCI_BRIDGE_CTL_SERR; else pci_bctl &= ~PCI_BRIDGE_CTL_SERR; - if (hpp.enable_perr) + if (hpp.t0->enable_perr) pci_bctl |= PCI_BRIDGE_CTL_PARITY; else pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; diff --git a/drivers/pci/msi-altix.c b/drivers/pci/msi-altix.c new file mode 100644 index 0000000..bed4183 --- /dev/null +++ b/drivers/pci/msi-altix.c @@ -0,0 +1,210 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "msi.h" + +struct sn_msi_info { + u64 pci_addr; + struct sn_irq_info *sn_irq_info; +}; + +static struct sn_msi_info *sn_msi_info; + +static void +sn_msi_teardown(unsigned int vector) +{ + nasid_t nasid; + int widget; + struct pci_dev *pdev; + struct pcidev_info *sn_pdev; + struct sn_irq_info *sn_irq_info; + struct pcibus_bussoft *bussoft; + struct sn_pcibus_provider *provider; + + sn_irq_info = sn_msi_info[vector].sn_irq_info; + if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0) + return; + + sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; + pdev = sn_pdev->pdi_linux_pcidev; + provider = SN_PCIDEV_BUSPROVIDER(pdev); + + (*provider->dma_unmap)(pdev, + sn_msi_info[vector].pci_addr, + PCI_DMA_FROMDEVICE); + sn_msi_info[vector].pci_addr = 0; + + bussoft = SN_PCIDEV_BUSSOFT(pdev); + nasid = NASID_GET(bussoft->bs_base); + widget = (nasid & 1) ? + TIO_SWIN_WIDGETNUM(bussoft->bs_base) : + SWIN_WIDGETNUM(bussoft->bs_base); + + sn_intr_free(nasid, widget, sn_irq_info); + sn_msi_info[vector].sn_irq_info = NULL; + + return; +} + +int +sn_msi_setup(struct pci_dev *pdev, unsigned int vector, + u32 *addr_hi, u32 *addr_lo, u32 *data) +{ + int widget; + int status; + nasid_t nasid; + u64 bus_addr; + struct sn_irq_info *sn_irq_info; + struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); + struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); + + if (bussoft == NULL) + return -EINVAL; + + if (provider == NULL || provider->dma_map_consistent == NULL) + return -EINVAL; + + /* + * Set up the vector plumbing. Let the prom (via sn_intr_alloc) + * decide which cpu to direct this msi at by default. + */ + + nasid = NASID_GET(bussoft->bs_base); + widget = (nasid & 1) ? + TIO_SWIN_WIDGETNUM(bussoft->bs_base) : + SWIN_WIDGETNUM(bussoft->bs_base); + + sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); + if (! sn_irq_info) + return -ENOMEM; + + status = sn_intr_alloc(nasid, widget, sn_irq_info, vector, -1, -1); + if (status) { + kfree(sn_irq_info); + return -ENOMEM; + } + + sn_irq_info->irq_int_bit = -1; /* mark this as an MSI irq */ + sn_irq_fixup(pdev, sn_irq_info); + + /* Prom probably should fill these in, but doesn't ... */ + sn_irq_info->irq_bridge_type = bussoft->bs_asic_type; + sn_irq_info->irq_bridge = (void *)bussoft->bs_base; + + /* + * Map the xio address into bus space + */ + bus_addr = (*provider->dma_map_consistent)(pdev, + sn_irq_info->irq_xtalkaddr, + sizeof(sn_irq_info->irq_xtalkaddr), + SN_DMA_MSI|SN_DMA_ADDR_XIO); + if (! bus_addr) { + sn_intr_free(nasid, widget, sn_irq_info); + kfree(sn_irq_info); + return -ENOMEM; + } + + sn_msi_info[vector].sn_irq_info = sn_irq_info; + sn_msi_info[vector].pci_addr = bus_addr; + + *addr_hi = (u32)(bus_addr >> 32); + *addr_lo = (u32)(bus_addr & 0x00000000ffffffff); + + /* + * In the SN platform, bit 16 is a "send vector" bit which + * must be present in order to move the vector through the system. + */ + *data = 0x100 + (unsigned int)vector; + +#ifdef CONFIG_SMP + set_irq_affinity_info((vector & 0xff), sn_irq_info->irq_cpuid, 0); +#endif + + return 0; +} + +static void +sn_msi_target(unsigned int vector, unsigned int cpu, + u32 *addr_hi, u32 *addr_lo) +{ + int slice; + nasid_t nasid; + u64 bus_addr; + struct pci_dev *pdev; + struct pcidev_info *sn_pdev; + struct sn_irq_info *sn_irq_info; + struct sn_irq_info *new_irq_info; + struct sn_pcibus_provider *provider; + + sn_irq_info = sn_msi_info[vector].sn_irq_info; + if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0) + return; + + /* + * Release XIO resources for the old MSI PCI address + */ + + sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; + pdev = sn_pdev->pdi_linux_pcidev; + provider = SN_PCIDEV_BUSPROVIDER(pdev); + + bus_addr = (u64)(*addr_hi) << 32 | (u64)(*addr_lo); + (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE); + sn_msi_info[vector].pci_addr = 0; + + nasid = cpuid_to_nasid(cpu); + slice = cpuid_to_slice(cpu); + + new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice); + sn_msi_info[vector].sn_irq_info = new_irq_info; + if (new_irq_info == NULL) + return; + + /* + * Map the xio address into bus space + */ + + bus_addr = (*provider->dma_map_consistent)(pdev, + new_irq_info->irq_xtalkaddr, + sizeof(new_irq_info->irq_xtalkaddr), + SN_DMA_MSI|SN_DMA_ADDR_XIO); + + sn_msi_info[vector].pci_addr = bus_addr; + *addr_hi = (u32)(bus_addr >> 32); + *addr_lo = (u32)(bus_addr & 0x00000000ffffffff); +} + +struct msi_ops sn_msi_ops = { + .setup = sn_msi_setup, + .teardown = sn_msi_teardown, +#ifdef CONFIG_SMP + .target = sn_msi_target, +#endif +}; + +int +sn_msi_init(void) +{ + sn_msi_info = + kzalloc(sizeof(struct sn_msi_info) * NR_VECTORS, GFP_KERNEL); + if (! sn_msi_info) + return -ENOMEM; + + msi_register(&sn_msi_ops); + return 0; +} diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c new file mode 100644 index 0000000..5ed798b --- /dev/null +++ b/drivers/pci/msi-apic.c @@ -0,0 +1,101 @@ +/* + * MSI hooks for standard x86 apic + */ + +#include +#include +#include + +#include "msi.h" + +/* + * Shifts for APIC-based data + */ + +#define MSI_DATA_VECTOR_SHIFT 0 +#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT) + +#define MSI_DATA_DELIVERY_SHIFT 8 +#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT) +#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT) + +#define MSI_DATA_LEVEL_SHIFT 14 +#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) +#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) + +#define MSI_DATA_TRIGGER_SHIFT 15 +#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) +#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) + +/* + * Shift/mask fields for APIC-based bus address + */ + +#define MSI_ADDR_HEADER 0xfee00000 + +#define MSI_ADDR_DESTID_MASK 0xfff0000f +#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT) + +#define MSI_ADDR_DESTMODE_SHIFT 2 +#define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT) +#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT) + +#define MSI_ADDR_REDIRECTION_SHIFT 3 +#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) +#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) + + +static void +msi_target_apic(unsigned int vector, + unsigned int dest_cpu, + u32 *address_hi, /* in/out */ + u32 *address_lo) /* in/out */ +{ + u32 addr = *address_lo; + + addr &= MSI_ADDR_DESTID_MASK; + addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(dest_cpu)); + + *address_lo = addr; +} + +static int +msi_setup_apic(struct pci_dev *pdev, /* unused in generic */ + unsigned int vector, + u32 *address_hi, + u32 *address_lo, + u32 *data) +{ + unsigned long dest_phys_id; + + dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); + + *address_hi = 0; + *address_lo = MSI_ADDR_HEADER | + MSI_ADDR_DESTMODE_PHYS | + MSI_ADDR_REDIRECTION_CPU | + MSI_ADDR_DESTID_CPU(dest_phys_id); + + *data = MSI_DATA_TRIGGER_EDGE | + MSI_DATA_LEVEL_ASSERT | + MSI_DATA_DELIVERY_FIXED | + MSI_DATA_VECTOR(vector); + + return 0; +} + +static void +msi_teardown_apic(unsigned int vector) +{ + return; /* no-op */ +} + +/* + * Generic ops used on most IA archs/platforms. Set with msi_register() + */ + +struct msi_ops msi_apic_ops = { + .setup = msi_setup_apic, + .teardown = msi_teardown_apic, + .target = msi_target_apic, +}; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9855c4c..7f84292 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -23,8 +23,6 @@ #include #include "pci.h" #include "msi.h" -#define MSI_TARGET_CPU first_cpu(cpu_online_map) - static DEFINE_SPINLOCK(msi_lock); static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; static kmem_cache_t* msi_cachep; @@ -37,9 +35,17 @@ static int nr_msix_devices; #ifndef CONFIG_X86_IO_APIC int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; -u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 }; #endif +static struct msi_ops *msi_ops; + +int +msi_register(struct msi_ops *ops) +{ + msi_ops = ops; + return 0; +} + static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags) { memset(p, 0, NR_IRQS * sizeof(struct msi_desc)); @@ -92,7 +98,7 @@ #ifdef CONFIG_SMP static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) { struct msi_desc *entry; - struct msg_address address; + u32 address_hi, address_lo; unsigned int irq = vector; unsigned int dest_cpu = first_cpu(cpu_mask); @@ -108,28 +114,36 @@ static void set_msi_affinity(unsigned in if (!pos) return; + pci_read_config_dword(entry->dev, msi_upper_address_reg(pos), + &address_hi); pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), - &address.lo_address.value); - address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; - address.lo_address.value |= (cpu_physical_id(dest_cpu) << - MSI_TARGET_CPU_SHIFT); - entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); + &address_lo); + + msi_ops->target(vector, dest_cpu, &address_hi, &address_lo); + + pci_write_config_dword(entry->dev, msi_upper_address_reg(pos), + address_hi); pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), - address.lo_address.value); + address_lo); set_native_irq_info(irq, cpu_mask); break; } case PCI_CAP_ID_MSIX: { - int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET; - - address.lo_address.value = readl(entry->mask_base + offset); - address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; - address.lo_address.value |= (cpu_physical_id(dest_cpu) << - MSI_TARGET_CPU_SHIFT); - entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); - writel(address.lo_address.value, entry->mask_base + offset); + int offset_hi = + entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET; + int offset_lo = + entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET; + + address_hi = readl(entry->mask_base + offset_hi); + address_lo = readl(entry->mask_base + offset_lo); + + msi_ops->target(vector, dest_cpu, &address_hi, &address_lo); + + writel(address_hi, entry->mask_base + offset_hi); + writel(address_lo, entry->mask_base + offset_lo); set_native_irq_info(irq, cpu_mask); break; } @@ -251,30 +265,6 @@ static struct hw_interrupt_type msi_irq_ .set_affinity = set_msi_affinity }; -static void msi_data_init(struct msg_data *msi_data, - unsigned int vector) -{ - memset(msi_data, 0, sizeof(struct msg_data)); - msi_data->vector = (u8)vector; - msi_data->delivery_mode = MSI_DELIVERY_MODE; - msi_data->level = MSI_LEVEL_MODE; - msi_data->trigger = MSI_TRIGGER_MODE; -} - -static void msi_address_init(struct msg_address *msi_address) -{ - unsigned int dest_id; - unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU); - - memset(msi_address, 0, sizeof(struct msg_address)); - msi_address->hi_address = (u32)0; - dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT); - msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE; - msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE; - msi_address->lo_address.u.dest_id = dest_id; - msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT); -} - static int msi_free_vector(struct pci_dev* dev, int vector, int reassign); static int assign_msi_vector(void) { @@ -369,13 +359,29 @@ static int msi_init(void) return status; } + status = msi_arch_init(); + if (status < 0) { + pci_msi_enable = 0; + printk(KERN_WARNING + "PCI: MSI arch init failed. MSI disabled.\n"); + return status; + } + + if (! msi_ops) { + printk(KERN_WARNING + "PCI: MSI ops not registered. MSI disabled.\n"); + status = -EINVAL; + return status; + } + + last_alloc_vector = assign_irq_vector(AUTO_ASSIGN); status = msi_cache_init(); if (status < 0) { pci_msi_enable = 0; printk(KERN_WARNING "PCI: MSI cache init failed\n"); return status; } - last_alloc_vector = assign_irq_vector(AUTO_ASSIGN); + if (last_alloc_vector < 0) { pci_msi_enable = 0; printk(KERN_WARNING "PCI: No interrupt vectors available for MSI\n"); @@ -442,9 +448,11 @@ static void enable_msi_mode(struct pci_d /* Set enabled bits to single MSI & enable MSI_enable bit */ msi_enable(control, 1); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msi_enabled = 1; } else { msix_enable(control); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msix_enabled = 1; } if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { /* PCI Express Endpoint device detected */ @@ -461,9 +469,11 @@ void disable_msi_mode(struct pci_dev *de /* Set enabled bits to single MSI & enable MSI_enable bit */ msi_disable(control); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msi_enabled = 0; } else { msix_disable(control); pci_write_config_word(dev, msi_control_reg(pos), control); + dev->msix_enabled = 0; } if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { /* PCI Express Endpoint device detected */ @@ -538,7 +548,6 @@ int pci_save_msi_state(struct pci_dev *d pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]); if (control & PCI_MSI_FLAGS_MASKBIT) pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]); - disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); save_state->cap_nr = PCI_CAP_ID_MSI; pci_add_saved_cap(dev, save_state); return 0; @@ -575,6 +584,8 @@ void pci_restore_msi_state(struct pci_de int pci_save_msix_state(struct pci_dev *dev) { int pos; + int temp; + int vector, head, tail = 0; u16 control; struct pci_cap_saved_state *save_state; @@ -582,6 +593,7 @@ int pci_save_msix_state(struct pci_dev * if (pos <= 0 || dev->no_msi) return 0; + /* save the capability */ pci_read_config_word(dev, msi_control_reg(pos), &control); if (!(control & PCI_MSIX_FLAGS_ENABLE)) return 0; @@ -593,7 +605,38 @@ int pci_save_msix_state(struct pci_dev * } *((u16 *)&save_state->data[0]) = control; - disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); + /* save the table */ + temp = dev->irq; + if (msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { + kfree(save_state); + return -EINVAL; + } + + vector = head = dev->irq; + while (head != tail) { + int j; + void __iomem *base; + struct msi_desc *entry; + + entry = msi_desc[vector]; + base = entry->mask_base; + j = entry->msi_attrib.entry_nr; + + entry->address_lo_save = + readl(base + j * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); + entry->address_hi_save = + readl(base + j * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); + entry->data_save = + readl(base + j * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_DATA_OFFSET); + + tail = msi_desc[vector]->link.tail; + vector = tail; + } + dev->irq = temp; + save_state->cap_nr = PCI_CAP_ID_MSIX; pci_add_saved_cap(dev, save_state); return 0; @@ -606,8 +649,6 @@ void pci_restore_msix_state(struct pci_d int vector, head, tail = 0; void __iomem *base; int j; - struct msg_address address; - struct msg_data data; struct msi_desc *entry; int temp; struct pci_cap_saved_state *save_state; @@ -633,20 +674,13 @@ void pci_restore_msix_state(struct pci_d base = entry->mask_base; j = entry->msi_attrib.entry_nr; - msi_address_init(&address); - msi_data_init(&data, vector); - - address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; - address.lo_address.value |= entry->msi_attrib.current_cpu << - MSI_TARGET_CPU_SHIFT; - - writel(address.lo_address.value, + writel(entry->address_lo_save, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); - writel(address.hi_address, + writel(entry->address_hi_save, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); - writel(*(u32*)&data, + writel(entry->data_save, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_DATA_OFFSET); @@ -660,30 +694,32 @@ void pci_restore_msix_state(struct pci_d } #endif -static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry) +static int msi_register_init(struct pci_dev *dev, struct msi_desc *entry) { - struct msg_address address; - struct msg_data data; + int status; + u32 address_hi; + u32 address_lo; + u32 data; int pos, vector = dev->irq; u16 control; pos = pci_find_capability(dev, PCI_CAP_ID_MSI); pci_read_config_word(dev, msi_control_reg(pos), &control); + /* Configure MSI capability structure */ - msi_address_init(&address); - msi_data_init(&data, vector); - entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >> - MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK); - pci_write_config_dword(dev, msi_lower_address_reg(pos), - address.lo_address.value); + status = msi_ops->setup(dev, vector, &address_hi, &address_lo, &data); + if (status < 0) + return status; + + pci_write_config_dword(dev, msi_lower_address_reg(pos), address_lo); if (is_64bit_address(control)) { pci_write_config_dword(dev, - msi_upper_address_reg(pos), address.hi_address); + msi_upper_address_reg(pos), address_hi); pci_write_config_word(dev, - msi_data_reg(pos, 1), *((u32*)&data)); + msi_data_reg(pos, 1), data); } else pci_write_config_word(dev, - msi_data_reg(pos, 0), *((u32*)&data)); + msi_data_reg(pos, 0), data); if (entry->msi_attrib.maskbit) { unsigned int maskbits, temp; /* All MSIs are unmasked by default, Mask them all */ @@ -697,6 +733,8 @@ static void msi_register_init(struct pci msi_mask_bits_reg(pos, is_64bit_address(control)), maskbits); } + + return 0; } /** @@ -710,6 +748,7 @@ static void msi_register_init(struct pci **/ static int msi_capability_init(struct pci_dev *dev) { + int status; struct msi_desc *entry; int pos, vector; u16 control; @@ -742,7 +781,12 @@ static int msi_capability_init(struct pc /* Replace with MSI handler */ irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit); /* Configure MSI capability structure */ - msi_register_init(dev, entry); + status = msi_register_init(dev, entry); + if (status != 0) { + dev->irq = entry->msi_attrib.default_vector; + kmem_cache_free(msi_cachep, entry); + return status; + } attach_msi_entry(entry, vector); /* Set MSI enabled bits */ @@ -765,8 +809,10 @@ static int msix_capability_init(struct p struct msix_entry *entries, int nvec) { struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; - struct msg_address address; - struct msg_data data; + u32 address_hi; + u32 address_lo; + u32 data; + int status; int vector, pos, i, j, nr_entries, temp = 0; unsigned long phys_addr; u32 table_offset; @@ -822,18 +868,20 @@ static int msix_capability_init(struct p /* Replace with MSI-X handler */ irq_handler_init(PCI_CAP_ID_MSIX, vector, 1); /* Configure MSI-X capability structure */ - msi_address_init(&address); - msi_data_init(&data, vector); - entry->msi_attrib.current_cpu = - ((address.lo_address.u.dest_id >> - MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK); - writel(address.lo_address.value, + status = msi_ops->setup(dev, vector, + &address_hi, + &address_lo, + &data); + if (status < 0) + break; + + writel(address_lo, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); - writel(address.hi_address, + writel(address_hi, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); - writel(*(u32*)&data, + writel(data, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_DATA_OFFSET); attach_msi_entry(entry, vector); @@ -865,6 +913,7 @@ static int msix_capability_init(struct p **/ int pci_enable_msi(struct pci_dev* dev) { + struct pci_bus *bus; int pos, temp, status = -EINVAL; u16 control; @@ -874,8 +923,9 @@ int pci_enable_msi(struct pci_dev* dev) if (dev->no_msi) return status; - if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) - return -EINVAL; + for (bus = dev->bus; bus; bus = bus->parent) + if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) + return -EINVAL; temp = dev->irq; @@ -887,23 +937,23 @@ int pci_enable_msi(struct pci_dev* dev) if (!pos) return -EINVAL; - pci_read_config_word(dev, msi_control_reg(pos), &control); - if (control & PCI_MSI_FLAGS_ENABLE) - return 0; /* Already in MSI mode */ - if (!msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { /* Lookup Sucess */ unsigned long flags; + pci_read_config_word(dev, msi_control_reg(pos), &control); + if (control & PCI_MSI_FLAGS_ENABLE) + return 0; /* Already in MSI mode */ spin_lock_irqsave(&msi_lock, flags); if (!vector_irq[dev->irq]) { msi_desc[dev->irq]->msi_attrib.state = 0; vector_irq[dev->irq] = -1; nr_released_vectors--; spin_unlock_irqrestore(&msi_lock, flags); - msi_register_init(dev, msi_desc[dev->irq]); - enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); - return 0; + status = msi_register_init(dev, msi_desc[dev->irq]); + if (status == 0) + enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); + return status; } spin_unlock_irqrestore(&msi_lock, flags); dev->irq = temp; @@ -980,6 +1030,8 @@ static int msi_free_vector(struct pci_de void __iomem *base; unsigned long flags; + msi_ops->teardown(vector); + spin_lock_irqsave(&msi_lock, flags); entry = msi_desc[vector]; if (!entry || entry->dev != dev) { @@ -1008,33 +1060,8 @@ static int msi_free_vector(struct pci_de entry_nr * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); - if (head == vector) { - /* - * Detect last MSI-X vector to be released. - * Release the MSI-X memory-mapped table. - */ -#if 0 - int pos, nr_entries; - unsigned long phys_addr; - u32 table_offset; - u16 control; - u8 bir; - - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - pci_read_config_word(dev, msi_control_reg(pos), - &control); - nr_entries = multi_msix_capable(control); - pci_read_config_dword(dev, msix_table_offset_reg(pos), - &table_offset); - bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; - phys_addr = pci_resource_start(dev, bir) + table_offset; -/* - * FIXME! and what did you want to do with phys_addr? - */ -#endif + if (head == vector) iounmap(base); - } } return 0; @@ -1108,6 +1135,7 @@ static int reroute_msix_table(int head, **/ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) { + struct pci_bus *bus; int status, pos, nr_entries, free_vectors; int i, j, temp; u16 control; @@ -1116,6 +1144,13 @@ int pci_enable_msix(struct pci_dev* dev, if (!pci_msi_enable || !dev || !entries) return -EINVAL; + if (dev->no_msi) + return -EINVAL; + + for (bus = dev->bus; bus; bus = bus->parent) + if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) + return -EINVAL; + status = msi_init(); if (status < 0) return status; @@ -1300,24 +1335,6 @@ void msi_remove_pci_irq_vectors(struct p } msi_free_vector(dev, vector, 0); if (warning) { - /* Force to release the MSI-X memory-mapped table */ -#if 0 - unsigned long phys_addr; - u32 table_offset; - u16 control; - u8 bir; - - pci_read_config_word(dev, msi_control_reg(pos), - &control); - pci_read_config_dword(dev, msix_table_offset_reg(pos), - &table_offset); - bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; - phys_addr = pci_resource_start(dev, bir) + table_offset; -/* - * FIXME! and what did you want to do with phys_addr? - */ -#endif iounmap(base); printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " "called without free_irq() on all MSI-X vectors\n", diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 4ac52d4..56951c3 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -6,6 +6,68 @@ #ifndef MSI_H #define MSI_H +/* + * MSI operation vector. Used by the msi core code (drivers/pci/msi.c) + * to abstract platform-specific tasks relating to MSI address generation + * and resource management. + */ +struct msi_ops { + /** + * setup - generate an MSI bus address and data for a given vector + * @pdev: PCI device context (in) + * @vector: vector allocated by the msi core (in) + * @addr_hi: upper 32 bits of PCI bus MSI address (out) + * @addr_lo: lower 32 bits of PCI bus MSI address (out) + * @data: MSI data payload (out) + * + * Description: The setup op is used to generate a PCI bus addres and + * data which the msi core will program into the card MSI capability + * registers. The setup routine is responsible for picking an initial + * cpu to target the MSI at. The setup routine is responsible for + * examining pdev to determine the MSI capabilities of the card and + * generating a suitable address/data. The setup routine is + * responsible for allocating and tracking any system resources it + * needs to route the MSI to the cpu it picks, and for associating + * those resources with the passed in vector. + * + * Returns 0 if the MSI address/data was successfully setup. + **/ + + int (*setup) (struct pci_dev *pdev, unsigned int vector, + u32 *addr_hi, u32 *addr_lo, u32 *data); + + /** + * teardown - release resources allocated by setup + * @vector: vector context for resources (in) + * + * Description: The teardown op is used to release any resources + * that were allocated in the setup routine associated with the passed + * in vector. + **/ + + void (*teardown) (unsigned int vector); + + /** + * target - retarget an MSI at a different cpu + * @vector: vector context for resources (in) + * @cpu: new cpu to direct vector at (in) + * @addr_hi: new value of PCI bus upper 32 bits (in/out) + * @addr_lo: new value of PCI bus lower 32 bits (in/out) + * + * Description: The target op is used to redirect an MSI vector + * at a different cpu. addr_hi/addr_lo coming in are the existing + * values that the MSI core has programmed into the card. The + * target code is responsible for freeing any resources (if any) + * associated with the old address, and generating a new PCI bus + * addr_hi/addr_lo that will redirect the vector at the indicated cpu. + **/ + + void (*target) (unsigned int vector, unsigned int cpu, + u32 *addr_hi, u32 *addr_lo); +}; + +extern int msi_register(struct msi_ops *ops); + #include /* @@ -63,67 +125,6 @@ #define msix_unmask(address) (address #define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK) #define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK) -/* - * MSI Defined Data Structures - */ -#define MSI_ADDRESS_HEADER 0xfee -#define MSI_ADDRESS_HEADER_SHIFT 12 -#define MSI_ADDRESS_HEADER_MASK 0xfff000 -#define MSI_ADDRESS_DEST_ID_MASK 0xfff0000f -#define MSI_TARGET_CPU_MASK 0xff -#define MSI_DELIVERY_MODE 0 -#define MSI_LEVEL_MODE 1 /* Edge always assert */ -#define MSI_TRIGGER_MODE 0 /* MSI is edge sensitive */ -#define MSI_PHYSICAL_MODE 0 -#define MSI_LOGICAL_MODE 1 -#define MSI_REDIRECTION_HINT_MODE 0 - -struct msg_data { -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u32 vector : 8; - __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ - __u32 reserved_1 : 3; - __u32 level : 1; /* 0: deassert | 1: assert */ - __u32 trigger : 1; /* 0: edge | 1: level */ - __u32 reserved_2 : 16; -#elif defined(__BIG_ENDIAN_BITFIELD) - __u32 reserved_2 : 16; - __u32 trigger : 1; /* 0: edge | 1: level */ - __u32 level : 1; /* 0: deassert | 1: assert */ - __u32 reserved_1 : 3; - __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ - __u32 vector : 8; -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif -} __attribute__ ((packed)); - -struct msg_address { - union { - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u32 reserved_1 : 2; - __u32 dest_mode : 1; /*0:physic | 1:logic */ - __u32 redirection_hint: 1; /*0: dedicated CPU - 1: lowest priority */ - __u32 reserved_2 : 4; - __u32 dest_id : 24; /* Destination ID */ -#elif defined(__BIG_ENDIAN_BITFIELD) - __u32 dest_id : 24; /* Destination ID */ - __u32 reserved_2 : 4; - __u32 redirection_hint: 1; /*0: dedicated CPU - 1: lowest priority */ - __u32 dest_mode : 1; /*0:physic | 1:logic */ - __u32 reserved_1 : 2; -#else -#error "Bitfield endianness not defined! Check your byteorder.h" -#endif - }u; - __u32 value; - }lo_address; - __u32 hi_address; -} __attribute__ ((packed)); - struct msi_desc { struct { __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ @@ -132,7 +133,7 @@ struct msi_desc { __u8 reserved: 1; /* reserved */ __u8 entry_nr; /* specific enabled entry */ __u8 default_vector; /* default pre-assigned vector */ - __u8 current_cpu; /* current destination cpu */ + __u8 unused; /* formerly unused destination cpu*/ }msi_attrib; struct { @@ -142,6 +143,14 @@ struct msi_desc { void __iomem *mask_base; struct pci_dev *dev; + +#ifdef CONFIG_PM + /* PM save area for MSIX address/data */ + + u32 address_hi_save; + u32 address_lo_save; + u32 data_save; +#endif }; #endif /* MSI_H */ diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index c2ecae5..bb7456c 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -267,7 +267,7 @@ static int acpi_pci_set_power_state(stru /* ACPI bus type */ -static int pci_acpi_find_device(struct device *dev, acpi_handle *handle) +static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) { struct pci_dev * pci_dev; acpi_integer addr; @@ -281,7 +281,7 @@ static int pci_acpi_find_device(struct d return 0; } -static int pci_acpi_find_root_bridge(struct device *dev, acpi_handle *handle) +static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle) { int num; unsigned int seg, bus; @@ -299,21 +299,21 @@ static int pci_acpi_find_root_bridge(str return 0; } -static struct acpi_bus_type pci_acpi_bus = { +static struct acpi_bus_type acpi_pci_bus = { .bus = &pci_bus_type, - .find_device = pci_acpi_find_device, - .find_bridge = pci_acpi_find_root_bridge, + .find_device = acpi_pci_find_device, + .find_bridge = acpi_pci_find_root_bridge, }; -static int __init pci_acpi_init(void) +static int __init acpi_pci_init(void) { int ret; - ret = register_acpi_bus_type(&pci_acpi_bus); + ret = register_acpi_bus_type(&acpi_pci_bus); if (ret) return 0; platform_pci_choose_state = acpi_pci_choose_state; platform_pci_set_power_state = acpi_pci_set_power_state; return 0; } -arch_initcall(pci_acpi_init); +arch_initcall(acpi_pci_init); diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 56ac2bc..bc405c0 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -43,6 +43,29 @@ pci_config_attr(subsystem_vendor, "0x%04 pci_config_attr(subsystem_device, "0x%04x\n"); pci_config_attr(class, "0x%06x\n"); pci_config_attr(irq, "%u\n"); +pci_config_attr(is_enabled, "%u\n"); + +static ssize_t broken_parity_status_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + return sprintf (buf, "%u\n", pdev->broken_parity_status); +} + +static ssize_t broken_parity_status_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pci_dev *pdev = to_pci_dev(dev); + ssize_t consumed = -EINVAL; + + if ((count > 0) && (*buf == '0' || *buf == '1')) { + pdev->broken_parity_status = *buf == '1' ? 1 : 0; + consumed = count; + } + return consumed; +} static ssize_t local_cpus_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -90,6 +113,25 @@ static ssize_t modalias_show(struct devi (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8), (u8)(pci_dev->class)); } +static ssize_t +is_enabled_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + /* this can crash the machine when done on the "wrong" device */ + if (!capable(CAP_SYS_ADMIN)) + return count; + + if (*buf == '0') + pci_disable_device(pdev); + + if (*buf == '1') + pci_enable_device(pdev); + + return count; +} + struct device_attribute pci_dev_attrs[] = { __ATTR_RO(resource), @@ -101,6 +143,9 @@ struct device_attribute pci_dev_attrs[] __ATTR_RO(irq), __ATTR_RO(local_cpus), __ATTR_RO(modalias), + __ATTR(enable, 0600, is_enabled_show, is_enabled_store), + __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), + broken_parity_status_show,broken_parity_status_store), __ATTR_NULL, }; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 1228627..23d3b17 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -164,7 +164,6 @@ int pci_bus_find_capability(struct pci_b return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap); } -#if 0 /** * pci_find_ext_capability - Find an extended capability * @dev: PCI device to query @@ -212,7 +211,7 @@ int pci_find_ext_capability(struct pci_d return 0; } -#endif /* 0 */ +EXPORT_SYMBOL_GPL(pci_find_ext_capability); /** * pci_find_parent_resource - return resource region of parent bus of given region @@ -370,7 +369,7 @@ pci_set_power_state(struct pci_dev *dev, /* * Give firmware a chance to be called, such as ACPI _PRx, _PSx - * Firmware method after natice method ? + * Firmware method after native method ? */ if (platform_pci_set_power_state) platform_pci_set_power_state(dev, state); @@ -518,7 +517,12 @@ pci_enable_device_bars(struct pci_dev *d int pci_enable_device(struct pci_dev *dev) { - int err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); + int err; + + if (dev->is_enabled) + return 0; + + err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); if (err) return err; pci_fixup_device(pci_fixup_enable, dev); @@ -547,7 +551,14 @@ void pci_disable_device(struct pci_dev *dev) { u16 pci_command; - + + if (dev->msi_enabled) + disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), + PCI_CAP_ID_MSI); + if (dev->msix_enabled) + disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), + PCI_CAP_ID_MSIX); + pci_read_config_word(dev, PCI_COMMAND, &pci_command); if (pci_command & PCI_COMMAND_MASTER) { pci_command &= ~PCI_COMMAND_MASTER; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 30630cb..29bdeca 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -40,7 +40,7 @@ extern int pci_bus_find_capability (stru extern void pci_remove_legacy_files(struct pci_bus *bus); /* Lock for read/write access to pci device and bus lists */ -extern spinlock_t pci_bus_lock; +extern struct rw_semaphore pci_bus_sem; #ifdef CONFIG_X86_IO_APIC extern int pci_msi_quirk; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a10ed9d..f89dbc3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -180,25 +180,31 @@ static void pci_read_bases(struct pci_de res->flags |= pci_calc_resource_flags(l); if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { - pci_read_config_dword(dev, reg+4, &l); + u32 szhi, lhi; + pci_read_config_dword(dev, reg+4, &lhi); + pci_write_config_dword(dev, reg+4, ~0); + pci_read_config_dword(dev, reg+4, &szhi); + pci_write_config_dword(dev, reg+4, lhi); + szhi = pci_size(lhi, szhi, 0xffffffff); next++; #if BITS_PER_LONG == 64 - res->start |= ((unsigned long) l) << 32; + res->start |= ((unsigned long) lhi) << 32; res->end = res->start + sz; - pci_write_config_dword(dev, reg+4, ~0); - pci_read_config_dword(dev, reg+4, &sz); - pci_write_config_dword(dev, reg+4, l); - sz = pci_size(l, sz, 0xffffffff); - if (sz) { + if (szhi) { /* This BAR needs > 4GB? Wow. */ - res->end |= (unsigned long)sz<<32; + res->end |= (unsigned long)szhi<<32; } #else - if (l) { - printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", pci_name(dev)); + if (szhi) { + printk(KERN_ERR "PCI: Unable to handle 64-bit BAR for device %s\n", pci_name(dev)); res->start = 0; res->flags = 0; - continue; + } else if (lhi) { + /* 64-bit wide address, treat as disabled */ + pci_write_config_dword(dev, reg, l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); + pci_write_config_dword(dev, reg+4, 0); + res->start = 0; + res->end = sz; } #endif } @@ -377,9 +383,9 @@ struct pci_bus * __devinit pci_add_new_b child = pci_alloc_child_bus(parent, dev, busnr); if (child) { - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_add_tail(&child->node, &parent->children); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); } return child; } @@ -838,9 +844,9 @@ void __devinit pci_device_add(struct pci * and the bus list for fixup functions, etc. */ INIT_LIST_HEAD(&dev->global_list); - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_add_tail(&dev->bus_list, &bus->devices); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); } struct pci_dev * __devinit @@ -975,9 +981,10 @@ struct pci_bus * __devinit pci_create_bu pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus); goto err_out; } - spin_lock(&pci_bus_lock); + + down_write(&pci_bus_sem); list_add_tail(&b->node, &pci_root_buses); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); memset(dev, 0, sizeof(*dev)); dev->parent = parent; @@ -1017,9 +1024,9 @@ class_dev_create_file_err: class_dev_reg_err: device_unregister(dev); dev_reg_err: - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_del(&b->node); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); err_out: kfree(dev); kfree(b); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d378478..4364d79 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -24,6 +24,17 @@ #include #include #include "pci.h" +/* The Mellanox Tavor device gives false positive parity errors + * Mark this device with a broken_parity_status, to allow + * PCI scanning code to "skip" this now blacklisted device. + */ +static void __devinit quirk_mellanox_tavor(struct pci_dev *dev) +{ + dev->broken_parity_status = 1; /* This device gives false positives */ +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR,quirk_mellanox_tavor); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE,quirk_mellanox_tavor); + /* Deal with broken BIOS'es that neglect to enable passive release, which can cause problems in combination with the 82441FX/PPro MTRRs */ static void __devinit quirk_passive_release(struct pci_dev *dev) @@ -878,27 +889,30 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I * when a PCI-Soundcard is added. The BIOS only gives Options * "Disabled" and "AUTO". This Quirk Sets the corresponding * Register-Value to enable the Soundcard. + * + * FIXME: Presently this quirk will run on anything that has an 8237 + * which isn't correct, we need to check DMI tables or something in + * order to make sure it only runs on the MSI-K8T-Neo2Fir. Because it + * runs everywhere at present we suppress the printk output in most + * irrelevant cases. */ static void __init k8t_sound_hostbridge(struct pci_dev *dev) { unsigned char val; - printk(KERN_INFO "PCI: Quirk-MSI-K8T Soundcard On\n"); pci_read_config_byte(dev, 0x50, &val); if (val == 0x88 || val == 0xc8) { + /* Assume it's probably a MSI-K8T-Neo2Fir */ + printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, attempting to turn soundcard ON\n"); pci_write_config_byte(dev, 0x50, val & (~0x40)); /* Verify the Change for Status output */ pci_read_config_byte(dev, 0x50, &val); if (val & 0x40) - printk(KERN_INFO "PCI: MSI-K8T soundcard still off\n"); + printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, soundcard still off\n"); else - printk(KERN_INFO "PCI: MSI-K8T soundcard on\n"); - } else { - printk(KERN_INFO "PCI: Unexpected Value in PCI-Register: " - "no Change!\n"); + printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, soundcard on\n"); } - } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge); @@ -1485,6 +1499,25 @@ static void __devinit quirk_p64h2_1k_io( } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); +/* Under some circumstances, AER is not linked with extended capabilities. + * Force it to be linked by setting the corresponding control bit in the + * config space. + */ +static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev) +{ + uint8_t b; + if (pci_read_config_byte(dev, 0xf41, &b) == 0) { + if (!(b & 0x20)) { + pci_write_config_byte(dev, 0xf41, b | 0x20); + printk(KERN_INFO + "PCI: Linking AER extended capability on %s\n", + pci_name(dev)); + } + } +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, + quirk_nvidia_ck804_pcie_aer_ext_cap); + EXPORT_SYMBOL(pcie_mch_quirk); #ifdef CONFIG_HOTPLUG EXPORT_SYMBOL(pci_fixup_device); diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 1a6bf9d..99ffbd4 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -22,18 +22,18 @@ static void pci_destroy_dev(struct pci_d pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); device_unregister(&dev->dev); - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_del(&dev->global_list); dev->global_list.next = dev->global_list.prev = NULL; - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); } /* Remove the device from the device lists, and prevent any further * list accesses from this device */ - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_del(&dev->bus_list); dev->bus_list.next = dev->bus_list.prev = NULL; - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); pci_free_resources(dev); pci_dev_put(dev); @@ -62,9 +62,9 @@ void pci_remove_bus(struct pci_bus *pci_ { pci_proc_detach_bus(pci_bus); - spin_lock(&pci_bus_lock); + down_write(&pci_bus_sem); list_del(&pci_bus->node); - spin_unlock(&pci_bus_lock); + up_write(&pci_bus_sem); pci_remove_legacy_files(pci_bus); class_device_remove_file(&pci_bus->class_dev, &class_device_attr_cpuaffinity); diff --git a/drivers/pci/search.c b/drivers/pci/search.c index ce7dd6e..622b3f8 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -13,7 +13,7 @@ #include #include #include "pci.h" -DEFINE_SPINLOCK(pci_bus_lock); +DECLARE_RWSEM(pci_bus_sem); static struct pci_bus * __devinit pci_do_find_bus(struct pci_bus* bus, unsigned char busnr) @@ -72,11 +72,11 @@ pci_find_next_bus(const struct pci_bus * struct pci_bus *b = NULL; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); n = from ? from->node.next : pci_root_buses.next; if (n != &pci_root_buses) b = pci_bus_b(n); - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); return b; } @@ -124,7 +124,7 @@ struct pci_dev * pci_get_slot(struct pci struct pci_dev *dev; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); list_for_each(tmp, &bus->devices) { dev = pci_dev_b(tmp); @@ -135,7 +135,7 @@ struct pci_dev * pci_get_slot(struct pci dev = NULL; out: pci_dev_get(dev); - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); return dev; } @@ -167,7 +167,7 @@ static struct pci_dev * pci_find_subsys( struct pci_dev *dev; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); n = from ? from->global_list.next : pci_devices.next; while (n && (n != &pci_devices)) { @@ -181,7 +181,7 @@ static struct pci_dev * pci_find_subsys( } dev = NULL; exit: - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); return dev; } @@ -232,7 +232,7 @@ pci_get_subsys(unsigned int vendor, unsi struct pci_dev *dev; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); n = from ? from->global_list.next : pci_devices.next; while (n && (n != &pci_devices)) { @@ -247,7 +247,7 @@ pci_get_subsys(unsigned int vendor, unsi dev = NULL; exit: dev = pci_dev_get(dev); - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); pci_dev_put(from); return dev; } @@ -292,7 +292,7 @@ pci_find_device_reverse(unsigned int ven struct pci_dev *dev; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); n = from ? from->global_list.prev : pci_devices.prev; while (n && (n != &pci_devices)) { @@ -304,7 +304,7 @@ pci_find_device_reverse(unsigned int ven } dev = NULL; exit: - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); return dev; } @@ -328,7 +328,7 @@ struct pci_dev *pci_get_class(unsigned i struct pci_dev *dev; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); n = from ? from->global_list.next : pci_devices.next; while (n && (n != &pci_devices)) { @@ -340,7 +340,7 @@ struct pci_dev *pci_get_class(unsigned i dev = NULL; exit: dev = pci_dev_get(dev); - spin_unlock(&pci_bus_lock); + up_read(&pci_bus_sem); pci_dev_put(from); return dev; } @@ -362,7 +362,7 @@ int pci_dev_present(const struct pci_dev int found = 0; WARN_ON(in_interrupt()); - spin_lock(&pci_bus_lock); + down_read(&pci_bus_sem); while (ids->vendor || ids->subvendor || ids->class_mask) { list_for_each_entry(dev, &pci_devices, global_list) { if (pci_match_one_device(ids, dev)) { @@ -372,8 +372,8 @@ int pci_dev_present(const struct pci_dev } ids++; } -exit: - spin_unlock(&pci_bus_lock); +exit: + up_read(&pci_bus_sem); return found; } EXPORT_SYMBOL(pci_dev_present); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 28ce3a7..35086e8 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -55,9 +55,10 @@ pbus_assign_resources_sorted(struct pci_ list_for_each_entry(dev, &bus->devices, bus_list) { u16 class = dev->class >> 8; - /* Don't touch classless devices and host bridges. */ + /* Don't touch classless devices or host bridges or ioapics. */ if (class == PCI_CLASS_NOT_DEFINED || - class == PCI_CLASS_BRIDGE_HOST) + class == PCI_CLASS_BRIDGE_HOST || + class == PCI_CLASS_SYSTEM_PIC) continue; pdev_sort_resources(dev, &head); diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index ea9277b..577f4b5 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -155,6 +155,46 @@ int pci_assign_resource(struct pci_dev * return ret; } +#ifdef CONFIG_EMBEDDED +int pci_assign_resource_fixed(struct pci_dev *dev, int resno) +{ + struct pci_bus *bus = dev->bus; + struct resource *res = dev->resource + resno; + unsigned int type_mask; + int i, ret = -EBUSY; + + type_mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; + + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { + struct resource *r = bus->resource[i]; + if (!r) + continue; + + /* type_mask must match */ + if ((res->flags ^ r->flags) & type_mask) + continue; + + ret = request_resource(r, res); + + if (ret == 0) + break; + } + + if (ret) { + printk(KERN_ERR "PCI: Failed to allocate %s resource " + "#%d:%llx@%llx for %s\n", + res->flags & IORESOURCE_IO ? "I/O" : "mem", + resno, (unsigned long long)(res->end - res->start + 1), + (unsigned long long)res->start, pci_name(dev)); + } else if (resno < PCI_BRIDGE_RESOURCES) { + pci_update_resource(dev, res, resno); + } + + return ret; +} +EXPORT_SYMBOL_GPL(pci_assign_resource_fixed); +#endif + /* Sort resources by alignment */ void __devinit pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c index c6b262b..19b1e12 100644 --- a/drivers/pcmcia/sa1100_badge4.c +++ b/drivers/pcmcia/sa1100_badge4.c @@ -128,8 +128,8 @@ badge4_pcmcia_configure_socket(struct so static struct pcmcia_low_level badge4_pcmcia_ops = { .owner = THIS_MODULE, - .init = sa1111_pcmcia_hw_init, - .shutdown = sa1111_pcmcia_hw_shutdown, + .hw_init = sa1111_pcmcia_hw_init, + .hw_shutdown = sa1111_pcmcia_hw_shutdown, .socket_state = sa1111_pcmcia_socket_state, .configure_socket = badge4_pcmcia_configure_socket, diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index bb19c64..0b4adcb 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -60,30 +60,34 @@ static void card_remove_first(struct pnp card_remove(dev); } -static int card_probe(struct pnp_card * card, struct pnp_card_driver * drv) +static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv) { - const struct pnp_card_device_id *id = match_card(drv,card); - if (id) { - struct pnp_card_link * clink = pnp_alloc(sizeof(struct pnp_card_link)); - if (!clink) - return 0; - clink->card = card; - clink->driver = drv; - clink->pm_state = PMSG_ON; - if (drv->probe) { - if (drv->probe(clink, id)>=0) - return 1; - else { - struct pnp_dev * dev; - card_for_each_dev(card, dev) { - if (dev->card_link == clink) - pnp_release_card_device(dev); - } - kfree(clink); - } - } else - return 1; + const struct pnp_card_device_id *id; + struct pnp_card_link *clink; + struct pnp_dev *dev; + + if (!drv->probe) + return 0; + id = match_card(drv,card); + if (!id) + return 0; + + clink = pnp_alloc(sizeof(*clink)); + if (!clink) + return 0; + clink->card = card; + clink->driver = drv; + clink->pm_state = PMSG_ON; + + if (drv->probe(clink, id) >= 0) + return 1; + + /* Recovery */ + card_for_each_dev(card, dev) { + if (dev->card_link == clink) + pnp_release_card_device(dev); } + kfree(clink); return 0; } diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 407b4ea..3a4a644 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -36,13 +36,13 @@ static int irq_flags(int triggering, int { int flag; if (triggering == ACPI_LEVEL_SENSITIVE) { - if(polarity == ACPI_ACTIVE_LOW) + if (polarity == ACPI_ACTIVE_LOW) flag = IORESOURCE_IRQ_LOWLEVEL; else flag = IORESOURCE_IRQ_HIGHLEVEL; } else { - if(polarity == ACPI_ACTIVE_LOW) + if (polarity == ACPI_ACTIVE_LOW) flag = IORESOURCE_IRQ_LOWEDGE; else flag = IORESOURCE_IRQ_HIGHEDGE; @@ -57,7 +57,7 @@ static void decode_irq_flags(int flag, i *triggering = ACPI_LEVEL_SENSITIVE; *polarity = ACPI_ACTIVE_LOW; break; - case IORESOURCE_IRQ_HIGHLEVEL: + case IORESOURCE_IRQ_HIGHLEVEL: *triggering = ACPI_LEVEL_SENSITIVE; *polarity = ACPI_ACTIVE_HIGH; break; @@ -73,7 +73,7 @@ static void decode_irq_flags(int flag, i } static void -pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi, +pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi, int triggering, int polarity) { int i = 0; @@ -101,7 +101,7 @@ pnpacpi_parse_allocated_irqresource(stru } static void -pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma) +pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma) { int i = 0; while (i < PNP_MAX_DMA && @@ -119,8 +119,8 @@ pnpacpi_parse_allocated_dmaresource(stru } static void -pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res, - u32 io, u32 len) +pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, + u64 io, u64 len) { int i = 0; while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && @@ -138,7 +138,7 @@ pnpacpi_parse_allocated_ioresource(struc } static void -pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res, +pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, u64 mem, u64 len) { int i = 0; @@ -156,11 +156,32 @@ pnpacpi_parse_allocated_memresource(stru } } +static void +pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, + struct acpi_resource *res) +{ + struct acpi_resource_address64 addr, *p = &addr; + acpi_status status; + + status = acpi_resource_to_address64(res, p); + if (!ACPI_SUCCESS(status)) { + pnp_warn("PnPACPI: failed to convert resource type %d", + res->type); + return; + } + + if (p->resource_type == ACPI_MEMORY_RANGE) + pnpacpi_parse_allocated_memresource(res_table, + p->minimum, p->address_length); + else if (p->resource_type == ACPI_IO_RANGE) + pnpacpi_parse_allocated_ioresource(res_table, + p->minimum, p->address_length); +} static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, void *data) { - struct pnp_resource_table * res_table = (struct pnp_resource_table *)data; + struct pnp_resource_table *res_table = (struct pnp_resource_table *)data; int i; switch (res->type) { @@ -221,19 +242,9 @@ static acpi_status pnpacpi_allocated_res res->data.fixed_memory32.address_length); break; case ACPI_RESOURCE_TYPE_ADDRESS16: - pnpacpi_parse_allocated_memresource(res_table, - res->data.address16.minimum, - res->data.address16.address_length); - break; case ACPI_RESOURCE_TYPE_ADDRESS32: - pnpacpi_parse_allocated_memresource(res_table, - res->data.address32.minimum, - res->data.address32.address_length); - break; case ACPI_RESOURCE_TYPE_ADDRESS64: - pnpacpi_parse_allocated_memresource(res_table, - res->data.address64.minimum, - res->data.address64.address_length); + pnpacpi_parse_allocated_address_space(res_table, res); break; case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: @@ -255,11 +266,11 @@ static acpi_status pnpacpi_allocated_res pnp_warn("PnPACPI: unknown resource type %d", res->type); return AE_ERROR; } - + return AE_OK; } -acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table * res) +acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table *res) { /* Blank the resource table values */ pnp_init_resource_table(res); @@ -317,17 +328,17 @@ static void pnpacpi_parse_dma_option(str pnp_err("Invalid DMA transfer type"); } - pnp_register_dma_resource(option,dma); + pnp_register_dma_resource(option, dma); return; } - + static void pnpacpi_parse_irq_option(struct pnp_option *option, struct acpi_resource_irq *p) { int i; - struct pnp_irq * irq; - + struct pnp_irq *irq; + if (p->interrupt_count == 0) return; irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); @@ -347,7 +358,7 @@ static void pnpacpi_parse_ext_irq_option struct acpi_resource_extended_irq *p) { int i; - struct pnp_irq * irq; + struct pnp_irq *irq; if (p->interrupt_count == 0) return; @@ -368,7 +379,7 @@ static void pnpacpi_parse_port_option(struct pnp_option *option, struct acpi_resource_io *io) { - struct pnp_port * port; + struct pnp_port *port; if (io->address_length == 0) return; @@ -381,7 +392,7 @@ pnpacpi_parse_port_option(struct pnp_opt port->size = io->address_length; port->flags = ACPI_DECODE_16 == io->io_decode ? PNP_PORT_FLAG_16BITADDR : 0; - pnp_register_port_resource(option,port); + pnp_register_port_resource(option, port); return; } @@ -389,7 +400,7 @@ static void pnpacpi_parse_fixed_port_option(struct pnp_option *option, struct acpi_resource_fixed_io *io) { - struct pnp_port * port; + struct pnp_port *port; if (io->address_length == 0) return; @@ -400,7 +411,7 @@ pnpacpi_parse_fixed_port_option(struct p port->size = io->address_length; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_register_port_resource(option,port); + pnp_register_port_resource(option, port); return; } @@ -408,7 +419,7 @@ static void pnpacpi_parse_mem24_option(struct pnp_option *option, struct acpi_resource_memory24 *p) { - struct pnp_mem * mem; + struct pnp_mem *mem; if (p->address_length == 0) return; @@ -423,7 +434,7 @@ pnpacpi_parse_mem24_option(struct pnp_op mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option,mem); + pnp_register_mem_resource(option, mem); return; } @@ -431,7 +442,7 @@ static void pnpacpi_parse_mem32_option(struct pnp_option *option, struct acpi_resource_memory32 *p) { - struct pnp_mem * mem; + struct pnp_mem *mem; if (p->address_length == 0) return; @@ -446,7 +457,7 @@ pnpacpi_parse_mem32_option(struct pnp_op mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option,mem); + pnp_register_mem_resource(option, mem); return; } @@ -454,7 +465,7 @@ static void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, struct acpi_resource_fixed_memory32 *p) { - struct pnp_mem * mem; + struct pnp_mem *mem; if (p->address_length == 0) return; @@ -468,7 +479,7 @@ pnpacpi_parse_fixed_mem32_option(struct mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option,mem); + pnp_register_mem_resource(option, mem); return; } @@ -477,8 +488,8 @@ pnpacpi_parse_address_option(struct pnp_ { struct acpi_resource_address64 addr, *p = &addr; acpi_status status; - struct pnp_mem * mem; - struct pnp_port * port; + struct pnp_mem *mem; + struct pnp_port *port; status = acpi_resource_to_address64(r, p); if (!ACPI_SUCCESS(status)) { @@ -498,7 +509,7 @@ pnpacpi_parse_address_option(struct pnp_ mem->align = 0; mem->flags = (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0; - pnp_register_mem_resource(option,mem); + pnp_register_mem_resource(option, mem); } else if (p->resource_type == ACPI_IO_RANGE) { port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); if (!port) @@ -507,7 +518,7 @@ pnpacpi_parse_address_option(struct pnp_ port->size = p->address_length; port->align = 0; port->flags = PNP_PORT_FLAG_FIXED; - pnp_register_port_resource(option,port); + pnp_register_port_resource(option, port); } } @@ -531,7 +542,7 @@ static acpi_status pnpacpi_option_resour break; case ACPI_RESOURCE_TYPE_DMA: - pnpacpi_parse_dma_option(option, &res->data.dma); + pnpacpi_parse_dma_option(option, &res->data.dma); break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -539,7 +550,7 @@ static acpi_status pnpacpi_option_resour case ACPI_GOOD_CONFIGURATION: priority = PNP_RES_PRIORITY_PREFERRED; break; - + case ACPI_ACCEPTABLE_CONFIGURATION: priority = PNP_RES_PRIORITY_ACCEPTABLE; break; @@ -555,7 +566,7 @@ static acpi_status pnpacpi_option_resour option = pnp_register_dependent_option(dev, priority); if (!option) return AE_ERROR; - parse_data->option = option; + parse_data->option = option; break; case ACPI_RESOURCE_TYPE_END_DEPENDENT: @@ -615,7 +626,7 @@ static acpi_status pnpacpi_option_resour pnp_warn("PnPACPI: unknown resource type %d", res->type); return AE_ERROR; } - + return AE_OK; } @@ -636,13 +647,8 @@ acpi_status pnpacpi_parse_resource_optio return status; } -/* - * Set resource - */ -static acpi_status pnpacpi_count_resources(struct acpi_resource *res, - void *data) +static int pnpacpi_supported_resource(struct acpi_resource *res) { - int *res_cnt = (int *)data; switch (res->type) { case ACPI_RESOURCE_TYPE_IRQ: case ACPI_RESOURCE_TYPE_DMA: @@ -655,43 +661,32 @@ static acpi_status pnpacpi_count_resourc case ACPI_RESOURCE_TYPE_ADDRESS32: case ACPI_RESOURCE_TYPE_ADDRESS64: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - (*res_cnt) ++; - case ACPI_RESOURCE_TYPE_START_DEPENDENT: - case ACPI_RESOURCE_TYPE_END_DEPENDENT: - case ACPI_RESOURCE_TYPE_VENDOR: - case ACPI_RESOURCE_TYPE_END_TAG: - case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: - default: - return AE_OK; + return 1; } - return AE_OK; + return 0; } -static acpi_status pnpacpi_type_resources(struct acpi_resource *res, +/* + * Set resource + */ +static acpi_status pnpacpi_count_resources(struct acpi_resource *res, void *data) { - struct acpi_resource **resource = (struct acpi_resource **)data; - switch (res->type) { - case ACPI_RESOURCE_TYPE_IRQ: - case ACPI_RESOURCE_TYPE_DMA: - case ACPI_RESOURCE_TYPE_IO: - case ACPI_RESOURCE_TYPE_FIXED_IO: - case ACPI_RESOURCE_TYPE_MEMORY24: - case ACPI_RESOURCE_TYPE_MEMORY32: - case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: - case ACPI_RESOURCE_TYPE_ADDRESS16: - case ACPI_RESOURCE_TYPE_ADDRESS32: - case ACPI_RESOURCE_TYPE_ADDRESS64: - case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + int *res_cnt = (int *)data; + + if (pnpacpi_supported_resource(res)) + (*res_cnt)++; + return AE_OK; +} + +static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) +{ + struct acpi_resource **resource = (struct acpi_resource **)data; + + if (pnpacpi_supported_resource(res)) { (*resource)->type = res->type; + (*resource)->length = sizeof(struct acpi_resource); (*resource)++; - case ACPI_RESOURCE_TYPE_START_DEPENDENT: - case ACPI_RESOURCE_TYPE_END_DEPENDENT: - case ACPI_RESOURCE_TYPE_VENDOR: - case ACPI_RESOURCE_TYPE_END_TAG: - case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: - default: - return AE_OK; } return AE_OK; @@ -735,11 +730,8 @@ static void pnpacpi_encode_irq(struct ac struct resource *p) { int triggering, polarity; - - decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, - &polarity); - resource->type = ACPI_RESOURCE_TYPE_IRQ; - resource->length = sizeof(struct acpi_resource); + + decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); resource->data.irq.triggering = triggering; resource->data.irq.polarity = polarity; if (triggering == ACPI_EDGE_SENSITIVE) @@ -754,11 +746,8 @@ static void pnpacpi_encode_ext_irq(struc struct resource *p) { int triggering, polarity; - - decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, - &polarity); - resource->type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ; - resource->length = sizeof(struct acpi_resource); + + decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); resource->data.extended_irq.producer_consumer = ACPI_CONSUMER; resource->data.extended_irq.triggering = triggering; resource->data.extended_irq.polarity = polarity; @@ -773,8 +762,6 @@ static void pnpacpi_encode_ext_irq(struc static void pnpacpi_encode_dma(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_DMA; - resource->length = sizeof(struct acpi_resource); /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ if (p->flags & IORESOURCE_DMA_COMPATIBLE) resource->data.dma.type = ACPI_COMPATIBILITY; @@ -798,8 +785,6 @@ static void pnpacpi_encode_dma(struct ac static void pnpacpi_encode_io(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_IO; - resource->length = sizeof(struct acpi_resource); /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)? ACPI_DECODE_16 : ACPI_DECODE_10; @@ -812,8 +797,6 @@ static void pnpacpi_encode_io(struct acp static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_FIXED_IO; - resource->length = sizeof(struct acpi_resource); resource->data.fixed_io.address = p->start; resource->data.fixed_io.address_length = p->end - p->start + 1; } @@ -821,8 +804,6 @@ static void pnpacpi_encode_fixed_io(stru static void pnpacpi_encode_mem24(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_MEMORY24; - resource->length = sizeof(struct acpi_resource); /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ resource->data.memory24.write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? @@ -836,8 +817,6 @@ static void pnpacpi_encode_mem24(struct static void pnpacpi_encode_mem32(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_MEMORY32; - resource->length = sizeof(struct acpi_resource); resource->data.memory32.write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; @@ -850,8 +829,6 @@ static void pnpacpi_encode_mem32(struct static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, struct resource *p) { - resource->type = ACPI_RESOURCE_TYPE_FIXED_MEMORY32; - resource->length = sizeof(struct acpi_resource); resource->data.fixed_memory32.write_protect = (p->flags & IORESOURCE_MEM_WRITEABLE) ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; @@ -882,37 +859,37 @@ int pnpacpi_encode_resources(struct pnp_ pnp_dbg("Encode dma"); pnpacpi_encode_dma(resource, &res_table->dma_resource[dma]); - dma ++; + dma++; break; case ACPI_RESOURCE_TYPE_IO: pnp_dbg("Encode io"); pnpacpi_encode_io(resource, &res_table->port_resource[port]); - port ++; + port++; break; case ACPI_RESOURCE_TYPE_FIXED_IO: pnp_dbg("Encode fixed io"); pnpacpi_encode_fixed_io(resource, &res_table->port_resource[port]); - port ++; + port++; break; case ACPI_RESOURCE_TYPE_MEMORY24: pnp_dbg("Encode mem24"); pnpacpi_encode_mem24(resource, &res_table->mem_resource[mem]); - mem ++; + mem++; break; case ACPI_RESOURCE_TYPE_MEMORY32: pnp_dbg("Encode mem32"); pnpacpi_encode_mem32(resource, &res_table->mem_resource[mem]); - mem ++; + mem++; break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: pnp_dbg("Encode fixed mem32"); pnpacpi_encode_fixed_mem32(resource, &res_table->mem_resource[mem]); - mem ++; + mem++; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: pnp_dbg("Encode ext irq"); @@ -933,8 +910,8 @@ int pnpacpi_encode_resources(struct pnp_ pnp_warn("unknown resource type %d", resource->type); return -EINVAL; } - resource ++; - i ++; + resource++; + i++; } return 0; } diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 65d090d..bccff40 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -73,6 +73,13 @@ config RTC_INTF_DEV This driver can also be built as a module. If so, the module will be called rtc-dev. +config RTC_INTF_DEV_UIE_EMUL + bool "RTC UIE emulation on dev interface" + depends on RTC_INTF_DEV + help + Provides an emulation for RTC_UIE if the underlaying rtc chip + driver did not provide RTC_UIE ioctls. + comment "RTC drivers" depends on RTC_CLASS @@ -86,6 +93,34 @@ config RTC_DRV_X1205 This driver can also be built as a module. If so, the module will be called rtc-x1205. +config RTC_DRV_DS1307 + tristate "Dallas/Maxim DS1307 and similar I2C RTC chips" + depends on RTC_CLASS && I2C + help + If you say yes here you get support for various compatible RTC + chips (often with battery backup) connected with I2C. This driver + should handle DS1307, DS1337, DS1338, DS1339, DS1340, ST M41T00, + and probably other chips. In some cases the RTC must already + have been initialized (by manufacturing or a bootloader). + + The first seven registers on these chips hold an RTC, and other + registers may add features such as NVRAM, a trickle charger for + the RTC/NVRAM backup power, and alarms. This driver may not + expose all those available chip features. + + This driver can also be built as a module. If so, the module + will be called rtc-ds1307. + +config RTC_DRV_DS1553 + tristate "Dallas DS1553" + depends on RTC_CLASS + help + If you say yes here you get support for the + Dallas DS1553 timekeeping chip. + + This driver can also be built as a module. If so, the module + will be called rtc-ds1553. + config RTC_DRV_DS1672 tristate "Dallas/Maxim DS1672" depends on RTC_CLASS && I2C @@ -96,6 +131,16 @@ config RTC_DRV_DS1672 This driver can also be built as a module. If so, the module will be called rtc-ds1672. +config RTC_DRV_DS1742 + tristate "Dallas DS1742" + depends on RTC_CLASS + help + If you say yes here you get support for the + Dallas DS1742 timekeeping chip. + + This driver can also be built as a module. If so, the module + will be called rtc-ds1742. + config RTC_DRV_PCF8563 tristate "Philips PCF8563/Epson RTC8564" depends on RTC_CLASS && I2C @@ -107,6 +152,16 @@ config RTC_DRV_PCF8563 This driver can also be built as a module. If so, the module will be called rtc-pcf8563. +config RTC_DRV_PCF8583 + tristate "Philips PCF8583" + depends on RTC_CLASS && I2C + help + If you say yes here you get support for the + Philips PCF8583 RTC chip. + + This driver can also be built as a module. If so, the module + will be called rtc-pcf8583. + config RTC_DRV_RS5C372 tristate "Ricoh RS5C372A/B" depends on RTC_CLASS && I2C @@ -157,6 +212,22 @@ config RTC_DRV_VR41XX To compile this driver as a module, choose M here: the module will be called rtc-vr41xx. +config RTC_DRV_PL031 + tristate "ARM AMBA PL031 RTC" + depends on RTC_CLASS && ARM_AMBA + help + If you say Y here you will get access to ARM AMBA + PrimeCell PL031 UART found on certain ARM SOCs. + + To compile this driver as a module, choose M here: the + module will be called rtc-pl031. + +config RTC_DRV_AT91 + tristate "AT91RM9200" + depends on RTC_CLASS && ARCH_AT91RM9200 + help + Driver for the Atmel AT91RM9200's internal RTC (Realtime Clock). + config RTC_DRV_TEST tristate "Test driver/device" depends on RTC_CLASS @@ -172,4 +243,24 @@ config RTC_DRV_TEST This driver can also be built as a module. If so, the module will be called rtc-test. +config RTC_DRV_MAX6902 + tristate "Maxim 6902" + depends on RTC_CLASS && SPI + help + If you say yes here you will get support for the + Maxim MAX6902 spi RTC chip. + + This driver can also be built as a module. If so, the module + will be called rtc-max6902. + +config RTC_DRV_V3020 + tristate "EM Microelectronic V3020" + depends on RTC_CLASS + help + If you say yes here you will get support for the + EM Microelectronic v3020 RTC chip. + + This driver can also be built as a module. If so, the module + will be called rtc-v3020. + endmenu diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index a9ca0f1..900d210 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -13,10 +13,18 @@ obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o +obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o +obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o +obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o +obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o +obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o +obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o +obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o +obj-$(CONFIG_RTC_DRV_AT91) += rtc-at91.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 413c7d5..5396bee 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -69,6 +69,7 @@ struct rtc_device *rtc_device_register(c rtc->id = id; rtc->ops = ops; rtc->owner = owner; + rtc->max_user_freq = 64; rtc->class_dev.dev = dev; rtc->class_dev.class = rtc_class; rtc->class_dev.release = rtc_device_release; diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 56e4907..579cd66 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -229,6 +229,9 @@ int rtc_irq_set_state(struct class_devic unsigned long flags; struct rtc_device *rtc = to_rtc_device(class_dev); + if (rtc->ops->irq_set_state == NULL) + return -ENXIO; + spin_lock_irqsave(&rtc->irq_task_lock, flags); if (rtc->irq_task != task) err = -ENXIO; @@ -243,25 +246,12 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_state); int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq) { - int err = 0, tmp = 0; + int err = 0; unsigned long flags; struct rtc_device *rtc = to_rtc_device(class_dev); - /* allowed range is 2-8192 */ - if (freq < 2 || freq > 8192) - return -EINVAL; -/* - FIXME: this does not belong here, will move where appropriate - at a later stage. It cannot hurt right now, trust me :) - if ((freq > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE))) - return -EACCES; -*/ - /* check if freq is a power of 2 */ - while (freq > (1 << tmp)) - tmp++; - - if (freq != (1 << tmp)) - return -EINVAL; + if (rtc->ops->irq_set_freq == NULL) + return -ENXIO; spin_lock_irqsave(&rtc->irq_task_lock, flags); if (rtc->irq_task != task) diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91.c new file mode 100644 index 0000000..b676f44 --- /dev/null +++ b/drivers/rtc/rtc-at91.c @@ -0,0 +1,407 @@ +/* + * Real Time Clock interface for Linux on Atmel AT91RM9200 + * + * Copyright (C) 2002 Rick Bronson + * + * Converted to RTC class model by Andrew Victor + * + * Ported to Linux 2.6 by Steven Scholz + * Based on s3c2410-rtc.c Simtec Electronics + * + * Based on sa1100-rtc.c by Nils Faerber + * Based on rtc.c by Paul Gortmaker + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +#define AT91_RTC_FREQ 1 +#define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ + +static DECLARE_COMPLETION(at91_rtc_updated); +static unsigned int at91_alarm_year = AT91_RTC_EPOCH; + +/* + * Decode time/date into rtc_time structure + */ +static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg, + struct rtc_time *tm) +{ + unsigned int time, date; + + /* must read twice in case it changes */ + do { + time = at91_sys_read(timereg); + date = at91_sys_read(calreg); + } while ((time != at91_sys_read(timereg)) || + (date != at91_sys_read(calreg))); + + tm->tm_sec = BCD2BIN((time & AT91_RTC_SEC) >> 0); + tm->tm_min = BCD2BIN((time & AT91_RTC_MIN) >> 8); + tm->tm_hour = BCD2BIN((time & AT91_RTC_HOUR) >> 16); + + /* + * The Calendar Alarm register does not have a field for + * the year - so these will return an invalid value. When an + * alarm is set, at91_alarm_year wille store the current year. + */ + tm->tm_year = BCD2BIN(date & AT91_RTC_CENT) * 100; /* century */ + tm->tm_year += BCD2BIN((date & AT91_RTC_YEAR) >> 8); /* year */ + + tm->tm_wday = BCD2BIN((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */ + tm->tm_mon = BCD2BIN((date & AT91_RTC_MONTH) >> 16) - 1; + tm->tm_mday = BCD2BIN((date & AT91_RTC_DATE) >> 24); +} + +/* + * Read current time and date in RTC + */ +static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm) +{ + at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, tm); + tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); + tm->tm_year = tm->tm_year - 1900; + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + return 0; +} + +/* + * Set current time and date in RTC + */ +static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) +{ + unsigned long cr; + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + /* Stop Time/Calendar from counting */ + cr = at91_sys_read(AT91_RTC_CR); + at91_sys_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); + + at91_sys_write(AT91_RTC_IER, AT91_RTC_ACKUPD); + wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */ + at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); + + at91_sys_write(AT91_RTC_TIMR, + BIN2BCD(tm->tm_sec) << 0 + | BIN2BCD(tm->tm_min) << 8 + | BIN2BCD(tm->tm_hour) << 16); + + at91_sys_write(AT91_RTC_CALR, + BIN2BCD((tm->tm_year + 1900) / 100) /* century */ + | BIN2BCD(tm->tm_year % 100) << 8 /* year */ + | BIN2BCD(tm->tm_mon + 1) << 16 /* tm_mon starts at zero */ + | BIN2BCD(tm->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */ + | BIN2BCD(tm->tm_mday) << 24); + + /* Restart Time/Calendar */ + cr = at91_sys_read(AT91_RTC_CR); + at91_sys_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM)); + + return 0; +} + +/* + * Read alarm time and date in RTC + */ +static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct rtc_time *tm = &alrm->time; + + at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm); + tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); + tm->tm_year = at91_alarm_year - 1900; + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + return 0; +} + +/* + * Set alarm time and date in RTC + */ +static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct rtc_time tm; + + at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm); + + at91_alarm_year = tm.tm_year; + + tm.tm_hour = alrm->time.tm_hour; + tm.tm_min = alrm->time.tm_min; + tm.tm_sec = alrm->time.tm_sec; + + at91_sys_write(AT91_RTC_TIMALR, + BIN2BCD(tm.tm_sec) << 0 + | BIN2BCD(tm.tm_min) << 8 + | BIN2BCD(tm.tm_hour) << 16 + | AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN); + at91_sys_write(AT91_RTC_CALALR, + BIN2BCD(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */ + | BIN2BCD(tm.tm_mday) << 24 + | AT91_RTC_DATEEN | AT91_RTC_MTHEN); + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, + tm.tm_min, tm.tm_sec); + + return 0; +} + +/* + * Handle commands from user-space + */ +static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, + unsigned long arg) +{ + int ret = 0; + + pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __FUNCTION__, cmd, arg); + + switch (cmd) { + case RTC_AIE_OFF: /* alarm off */ + at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); + break; + case RTC_AIE_ON: /* alarm on */ + at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); + break; + case RTC_UIE_OFF: /* update off */ + case RTC_PIE_OFF: /* periodic off */ + at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV); + break; + case RTC_UIE_ON: /* update on */ + case RTC_PIE_ON: /* periodic on */ + at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV); + break; + case RTC_IRQP_READ: /* read periodic alarm frequency */ + ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg); + break; + case RTC_IRQP_SET: /* set periodic alarm frequency */ + if (arg != AT91_RTC_FREQ) + ret = -EINVAL; + break; + default: + ret = -ENOIOCTLCMD; + break; + } + + return ret; +} + +/* + * Provide additional RTC information in /proc/driver/rtc + */ +static int at91_rtc_proc(struct device *dev, struct seq_file *seq) +{ + unsigned long imr = at91_sys_read(AT91_RTC_IMR); + + seq_printf(seq, "alarm_IRQ\t: %s\n", + (imr & AT91_RTC_ALARM) ? "yes" : "no"); + seq_printf(seq, "update_IRQ\t: %s\n", + (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); + seq_printf(seq, "periodic_IRQ\t: %s\n", + (imr & AT91_RTC_SECEV) ? "yes" : "no"); + seq_printf(seq, "periodic_freq\t: %ld\n", + (unsigned long) AT91_RTC_FREQ); + + return 0; +} + +/* + * IRQ handler for the RTC + */ +static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct platform_device *pdev = dev_id; + struct rtc_device *rtc = platform_get_drvdata(pdev); + unsigned int rtsr; + unsigned long events = 0; + + rtsr = at91_sys_read(AT91_RTC_SR) & at91_sys_read(AT91_RTC_IMR); + if (rtsr) { /* this interrupt is shared! Is it ours? */ + if (rtsr & AT91_RTC_ALARM) + events |= (RTC_AF | RTC_IRQF); + if (rtsr & AT91_RTC_SECEV) + events |= (RTC_UF | RTC_IRQF); + if (rtsr & AT91_RTC_ACKUPD) + complete(&at91_rtc_updated); + + at91_sys_write(AT91_RTC_SCCR, rtsr); /* clear status reg */ + + rtc_update_irq(&rtc->class_dev, 1, events); + + pr_debug("%s(): num=%ld, events=0x%02lx\n", __FUNCTION__, + events >> 8, events & 0x000000FF); + + return IRQ_HANDLED; + } + return IRQ_NONE; /* not handled */ +} + +static struct rtc_class_ops at91_rtc_ops = { + .ioctl = at91_rtc_ioctl, + .read_time = at91_rtc_readtime, + .set_time = at91_rtc_settime, + .read_alarm = at91_rtc_readalarm, + .set_alarm = at91_rtc_setalarm, + .proc = at91_rtc_proc, +}; + +/* + * Initialize and install RTC driver + */ +static int __init at91_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtc; + int ret; + + at91_sys_write(AT91_RTC_CR, 0); + at91_sys_write(AT91_RTC_MR, 0); /* 24 hour mode */ + + /* Disable all interrupts */ + at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | + AT91_RTC_SECEV | AT91_RTC_TIMEV | + AT91_RTC_CALEV); + + ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, + SA_SHIRQ, "at91_rtc", pdev); + if (ret) { + printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", + AT91_ID_SYS); + return ret; + } + + rtc = rtc_device_register(pdev->name, &pdev->dev, + &at91_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + free_irq(AT91_ID_SYS, pdev); + return PTR_ERR(rtc); + } + platform_set_drvdata(pdev, rtc); + + printk(KERN_INFO "AT91 Real Time Clock driver.\n"); + return 0; +} + +/* + * Disable and remove the RTC driver + */ +static int __devexit at91_rtc_remove(struct platform_device *pdev) +{ + struct rtc_device *rtc = platform_get_drvdata(pdev); + + /* Disable all interrupts */ + at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | + AT91_RTC_SECEV | AT91_RTC_TIMEV | + AT91_RTC_CALEV); + free_irq(AT91_ID_SYS, pdev); + + rtc_device_unregister(rtc); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +#ifdef CONFIG_PM + +/* AT91RM9200 RTC Power management control */ + +static struct timespec at91_rtc_delta; + +static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct rtc_time tm; + struct timespec time; + + time.tv_nsec = 0; + + /* calculate time delta for suspend */ + at91_rtc_readtime(&pdev->dev, &tm); + rtc_tm_to_time(&tm, &time.tv_sec); + save_time_delta(&at91_rtc_delta, &time); + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + 1900 + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + + return 0; +} + +static int at91_rtc_resume(struct platform_device *pdev) +{ + struct rtc_time tm; + struct timespec time; + + time.tv_nsec = 0; + + at91_rtc_readtime(&pdev->dev, &tm); + rtc_tm_to_time(&tm, &time.tv_sec); + restore_time_delta(&at91_rtc_delta, &time); + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + 1900 + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + + return 0; +} +#else +#define at91_rtc_suspend NULL +#define at91_rtc_resume NULL +#endif + +static struct platform_driver at91_rtc_driver = { + .probe = at91_rtc_probe, + .remove = at91_rtc_remove, + .suspend = at91_rtc_suspend, + .resume = at91_rtc_resume, + .driver = { + .name = "at91_rtc", + .owner = THIS_MODULE, + }, +}; + +static int __init at91_rtc_init(void) +{ + return platform_driver_register(&at91_rtc_driver); +} + +static void __exit at91_rtc_exit(void) +{ + platform_driver_unregister(&at91_rtc_driver); +} + +module_init(at91_rtc_init); +module_exit(at91_rtc_exit); + +MODULE_AUTHOR("Rick Bronson"); +MODULE_DESCRIPTION("RTC driver for Atmel AT91RM9200"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 2011567..61a5825 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -48,6 +48,93 @@ static int rtc_dev_open(struct inode *in return err; } +#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL +/* + * Routine to poll RTC seconds field for change as often as possible, + * after first RTC_UIE use timer to reduce polling + */ +static void rtc_uie_task(void *data) +{ + struct rtc_device *rtc = data; + struct rtc_time tm; + int num = 0; + int err; + + err = rtc_read_time(&rtc->class_dev, &tm); + spin_lock_irq(&rtc->irq_lock); + if (rtc->stop_uie_polling || err) { + rtc->uie_task_active = 0; + } else if (rtc->oldsecs != tm.tm_sec) { + num = (tm.tm_sec + 60 - rtc->oldsecs) % 60; + rtc->oldsecs = tm.tm_sec; + rtc->uie_timer.expires = jiffies + HZ - (HZ/10); + rtc->uie_timer_active = 1; + rtc->uie_task_active = 0; + add_timer(&rtc->uie_timer); + } else if (schedule_work(&rtc->uie_task) == 0) { + rtc->uie_task_active = 0; + } + spin_unlock_irq(&rtc->irq_lock); + if (num) + rtc_update_irq(&rtc->class_dev, num, RTC_UF | RTC_IRQF); +} + +static void rtc_uie_timer(unsigned long data) +{ + struct rtc_device *rtc = (struct rtc_device *)data; + unsigned long flags; + + spin_lock_irqsave(&rtc->irq_lock, flags); + rtc->uie_timer_active = 0; + rtc->uie_task_active = 1; + if ((schedule_work(&rtc->uie_task) == 0)) + rtc->uie_task_active = 0; + spin_unlock_irqrestore(&rtc->irq_lock, flags); +} + +static void clear_uie(struct rtc_device *rtc) +{ + spin_lock_irq(&rtc->irq_lock); + if (rtc->irq_active) { + rtc->stop_uie_polling = 1; + if (rtc->uie_timer_active) { + spin_unlock_irq(&rtc->irq_lock); + del_timer_sync(&rtc->uie_timer); + spin_lock_irq(&rtc->irq_lock); + rtc->uie_timer_active = 0; + } + if (rtc->uie_task_active) { + spin_unlock_irq(&rtc->irq_lock); + flush_scheduled_work(); + spin_lock_irq(&rtc->irq_lock); + } + rtc->irq_active = 0; + } + spin_unlock_irq(&rtc->irq_lock); +} + +static int set_uie(struct rtc_device *rtc) +{ + struct rtc_time tm; + int err; + + err = rtc_read_time(&rtc->class_dev, &tm); + if (err) + return err; + spin_lock_irq(&rtc->irq_lock); + if (!rtc->irq_active) { + rtc->irq_active = 1; + rtc->stop_uie_polling = 0; + rtc->oldsecs = tm.tm_sec; + rtc->uie_task_active = 1; + if (schedule_work(&rtc->uie_task) == 0) + rtc->uie_task_active = 0; + } + rtc->irq_data = 0; + spin_unlock_irq(&rtc->irq_lock); + return 0; +} +#endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */ static ssize_t rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) @@ -127,6 +214,28 @@ static int rtc_dev_ioctl(struct inode *i struct rtc_wkalrm alarm; void __user *uarg = (void __user *) arg; + /* check that the calles has appropriate permissions + * for certain ioctls. doing this check here is useful + * to avoid duplicate code in each driver. + */ + switch (cmd) { + case RTC_EPOCH_SET: + case RTC_SET_TIME: + if (!capable(CAP_SYS_TIME)) + return -EACCES; + break; + + case RTC_IRQP_SET: + if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE)) + return -EACCES; + break; + + case RTC_PIE_ON: + if (!capable(CAP_SYS_RESOURCE)) + return -EACCES; + break; + } + /* avoid conflicting IRQ users */ if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) { spin_lock(&rtc->irq_task_lock); @@ -185,9 +294,6 @@ static int rtc_dev_ioctl(struct inode *i break; case RTC_SET_TIME: - if (!capable(CAP_SYS_TIME)) - return -EACCES; - if (copy_from_user(&tm, uarg, sizeof(tm))) return -EFAULT; @@ -203,10 +309,6 @@ #ifndef rtc_epoch err = -EINVAL; break; } - if (!capable(CAP_SYS_TIME)) { - err = -EACCES; - break; - } rtc_epoch = arg; err = 0; #endif @@ -232,6 +334,14 @@ #endif return -EFAULT; break; +#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL + case RTC_UIE_OFF: + clear_uie(rtc); + return 0; + + case RTC_UIE_ON: + return set_uie(rtc); +#endif default: err = -ENOTTY; break; @@ -244,6 +354,9 @@ static int rtc_dev_release(struct inode { struct rtc_device *rtc = to_rtc_device(file->private_data); +#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL + clear_uie(rtc); +#endif if (rtc->ops->release) rtc->ops->release(rtc->class_dev.dev); @@ -284,6 +397,10 @@ static int rtc_dev_add_device(struct cla mutex_init(&rtc->char_lock); spin_lock_init(&rtc->irq_lock); init_waitqueue_head(&rtc->irq_queue); +#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL + INIT_WORK(&rtc->uie_task, rtc_uie_task, rtc); + setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc); +#endif cdev_init(&rtc->char_dev, &rtc_dev_fops); rtc->char_dev.owner = rtc->owner; diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c new file mode 100644 index 0000000..e8afb93 --- /dev/null +++ b/drivers/rtc/rtc-ds1307.c @@ -0,0 +1,388 @@ +/* + * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips. + * + * Copyright (C) 2005 James Chapman (ds1337 core) + * Copyright (C) 2006 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + + + +/* We can't determine type by probing, but if we expect pre-Linux code + * to have set the chip up as a clock (turning on the oscillator and + * setting the date and time), Linux can ignore the non-clock features. + * That's a natural job for a factory or repair bench. + * + * If the I2C "force" mechanism is used, we assume the chip is a ds1337. + * (Much better would be board-specific tables of I2C devices, along with + * the platform_data drivers would use to sort such issues out.) + */ +enum ds_type { + unknown = 0, + ds_1307, /* or ds1338, ... */ + ds_1337, /* or ds1339, ... */ + ds_1340, /* or st m41t00, ... */ + // rs5c372 too? different address... +}; + +static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + + + +/* RTC registers don't differ much, except for the century flag */ +#define DS1307_REG_SECS 0x00 /* 00-59 */ +# define DS1307_BIT_CH 0x80 +#define DS1307_REG_MIN 0x01 /* 00-59 */ +#define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */ +# define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */ +# define DS1340_BIT_CENTURY 0x40 /* in REG_HOUR */ +#define DS1307_REG_WDAY 0x03 /* 01-07 */ +#define DS1307_REG_MDAY 0x04 /* 01-31 */ +#define DS1307_REG_MONTH 0x05 /* 01-12 */ +# define DS1337_BIT_CENTURY 0x80 /* in REG_MONTH */ +#define DS1307_REG_YEAR 0x06 /* 00-99 */ + +/* Other registers (control, status, alarms, trickle charge, NVRAM, etc) + * start at 7, and they differ a lot. Only control and status matter for RTC; + * be careful using them. + */ +#define DS1307_REG_CONTROL 0x07 +# define DS1307_BIT_OUT 0x80 +# define DS1307_BIT_SQWE 0x10 +# define DS1307_BIT_RS1 0x02 +# define DS1307_BIT_RS0 0x01 +#define DS1337_REG_CONTROL 0x0e +# define DS1337_BIT_nEOSC 0x80 +# define DS1337_BIT_RS2 0x10 +# define DS1337_BIT_RS1 0x08 +# define DS1337_BIT_INTCN 0x04 +# define DS1337_BIT_A2IE 0x02 +# define DS1337_BIT_A1IE 0x01 +#define DS1337_REG_STATUS 0x0f +# define DS1337_BIT_OSF 0x80 +# define DS1337_BIT_A2I 0x02 +# define DS1337_BIT_A1I 0x01 +#define DS1339_REG_TRICKLE 0x10 + + + +struct ds1307 { + u8 reg_addr; + u8 regs[8]; + enum ds_type type; + struct i2c_msg msg[2]; + struct i2c_client client; + struct rtc_device *rtc; +}; + + +static int ds1307_get_time(struct device *dev, struct rtc_time *t) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + int tmp; + + /* read the RTC registers all at once */ + ds1307->msg[1].flags = I2C_M_RD; + ds1307->msg[1].len = 7; + + tmp = i2c_transfer(ds1307->client.adapter, ds1307->msg, 2); + if (tmp != 2) { + dev_err(dev, "%s error %d\n", "read", tmp); + return -EIO; + } + + dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n", + "read", + ds1307->regs[0], ds1307->regs[1], + ds1307->regs[2], ds1307->regs[3], + ds1307->regs[4], ds1307->regs[5], + ds1307->regs[6]); + + t->tm_sec = BCD2BIN(ds1307->regs[DS1307_REG_SECS] & 0x7f); + t->tm_min = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f); + tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f; + t->tm_hour = BCD2BIN(tmp); + t->tm_wday = BCD2BIN(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1; + t->tm_mday = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f); + tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f; + t->tm_mon = BCD2BIN(tmp) - 1; + + /* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */ + t->tm_year = BCD2BIN(ds1307->regs[DS1307_REG_YEAR]) + 100; + + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "read", t->tm_sec, t->tm_min, + t->tm_hour, t->tm_mday, + t->tm_mon, t->tm_year, t->tm_wday); + + return 0; +} + +static int ds1307_set_time(struct device *dev, struct rtc_time *t) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + int result; + int tmp; + u8 *buf = ds1307->regs; + + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "write", dt->tm_sec, dt->tm_min, + dt->tm_hour, dt->tm_mday, + dt->tm_mon, dt->tm_year, dt->tm_wday); + + *buf++ = 0; /* first register addr */ + buf[DS1307_REG_SECS] = BIN2BCD(t->tm_sec); + buf[DS1307_REG_MIN] = BIN2BCD(t->tm_min); + buf[DS1307_REG_HOUR] = BIN2BCD(t->tm_hour); + buf[DS1307_REG_WDAY] = BIN2BCD(t->tm_wday + 1); + buf[DS1307_REG_MDAY] = BIN2BCD(t->tm_mday); + buf[DS1307_REG_MONTH] = BIN2BCD(t->tm_mon + 1); + + /* assume 20YY not 19YY */ + tmp = t->tm_year - 100; + buf[DS1307_REG_YEAR] = BIN2BCD(tmp); + + if (ds1307->type == ds_1337) + buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY; + else if (ds1307->type == ds_1340) + buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN + | DS1340_BIT_CENTURY; + + ds1307->msg[1].flags = 0; + ds1307->msg[1].len = 8; + + dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n", + "write", buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6]); + + result = i2c_transfer(ds1307->client.adapter, &ds1307->msg[1], 1); + if (result != 1) { + dev_err(dev, "%s error %d\n", "write", tmp); + return -EIO; + } + return 0; +} + +static struct rtc_class_ops ds13xx_rtc_ops = { + .read_time = ds1307_get_time, + .set_time = ds1307_set_time, +}; + +static struct i2c_driver ds1307_driver; + +static int __devinit +ds1307_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct ds1307 *ds1307; + int err = -ENODEV; + struct i2c_client *client; + int tmp; + + if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &ds1307->client; + client->addr = address; + client->adapter = adapter; + client->driver = &ds1307_driver; + client->flags = 0; + + i2c_set_clientdata(client, ds1307); + + ds1307->msg[0].addr = client->addr; + ds1307->msg[0].flags = 0; + ds1307->msg[0].len = 1; + ds1307->msg[0].buf = &ds1307->reg_addr; + + ds1307->msg[1].addr = client->addr; + ds1307->msg[1].flags = I2C_M_RD; + ds1307->msg[1].len = sizeof(ds1307->regs); + ds1307->msg[1].buf = ds1307->regs; + + /* HACK: "force" implies "needs ds1337-style-oscillator setup" */ + if (kind >= 0) { + ds1307->type = ds_1337; + + ds1307->reg_addr = DS1337_REG_CONTROL; + ds1307->msg[1].len = 2; + + tmp = i2c_transfer(client->adapter, ds1307->msg, 2); + if (tmp != 2) { + pr_debug("read error %d\n", tmp); + err = -EIO; + goto exit_free; + } + + ds1307->reg_addr = 0; + ds1307->msg[1].len = sizeof(ds1307->regs); + + /* oscillator is off; need to turn it on */ + if ((ds1307->regs[0] & DS1337_BIT_nEOSC) + || (ds1307->regs[1] & DS1337_BIT_OSF)) { + printk(KERN_ERR "no ds1337 oscillator code\n"); + goto exit_free; + } + } else + ds1307->type = ds_1307; + +read_rtc: + /* read RTC registers */ + + tmp = i2c_transfer(client->adapter, ds1307->msg, 2); + if (tmp != 2) { + pr_debug("read error %d\n", tmp); + err = -EIO; + goto exit_free; + } + + /* minimal sanity checking; some chips (like DS1340) don't + * specify the extra bits as must-be-zero, but there are + * still a few values that are clearly out-of-range. + */ + tmp = ds1307->regs[DS1307_REG_SECS]; + if (tmp & DS1307_BIT_CH) { + if (ds1307->type && ds1307->type != ds_1307) { + pr_debug("not a ds1307?\n"); + goto exit_free; + } + ds1307->type = ds_1307; + + /* this partial initialization should work for ds1307, + * ds1338, ds1340, st m41t00, and more. + */ + dev_warn(&client->dev, "oscillator started; SET TIME!\n"); + i2c_smbus_write_byte_data(client, 0, 0); + goto read_rtc; + } + tmp = BCD2BIN(tmp & 0x7f); + if (tmp > 60) + goto exit_free; + tmp = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f); + if (tmp > 60) + goto exit_free; + + tmp = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f); + if (tmp == 0 || tmp > 31) + goto exit_free; + + tmp = BCD2BIN(ds1307->regs[DS1307_REG_MONTH] & 0x1f); + if (tmp == 0 || tmp > 12) + goto exit_free; + + /* force into in 24 hour mode (most chips) or + * disable century bit (ds1340) + */ + tmp = ds1307->regs[DS1307_REG_HOUR]; + if (tmp & (1 << 6)) { + if (tmp & (1 << 5)) + tmp = BCD2BIN(tmp & 0x1f) + 12; + else + tmp = BCD2BIN(tmp); + i2c_smbus_write_byte_data(client, + DS1307_REG_HOUR, + BIN2BCD(tmp)); + } + + /* FIXME chips like 1337 can generate alarm irqs too; those are + * worth exposing through the API (especially when the irq is + * wakeup-capable). + */ + + switch (ds1307->type) { + case unknown: + strlcpy(client->name, "unknown", I2C_NAME_SIZE); + break; + case ds_1307: + strlcpy(client->name, "ds1307", I2C_NAME_SIZE); + break; + case ds_1337: + strlcpy(client->name, "ds1337", I2C_NAME_SIZE); + break; + case ds_1340: + strlcpy(client->name, "ds1340", I2C_NAME_SIZE); + break; + } + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + + ds1307->rtc = rtc_device_register(client->name, &client->dev, + &ds13xx_rtc_ops, THIS_MODULE); + if (IS_ERR(ds1307->rtc)) { + err = PTR_ERR(ds1307->rtc); + dev_err(&client->dev, + "unable to register the class device\n"); + goto exit_detach; + } + + return 0; + +exit_detach: + i2c_detach_client(client); +exit_free: + kfree(ds1307); +exit: + return err; +} + +static int __devinit +ds1307_attach_adapter(struct i2c_adapter *adapter) +{ + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) + return 0; + return i2c_probe(adapter, &addr_data, ds1307_detect); +} + +static int __devexit ds1307_detach_client(struct i2c_client *client) +{ + int err; + struct ds1307 *ds1307 = i2c_get_clientdata(client); + + rtc_device_unregister(ds1307->rtc); + if ((err = i2c_detach_client(client))) + return err; + kfree(ds1307); + return 0; +} + +static struct i2c_driver ds1307_driver = { + .driver = { + .name = "ds1307", + .owner = THIS_MODULE, + }, + .attach_adapter = ds1307_attach_adapter, + .detach_client = __devexit_p(ds1307_detach_client), +}; + +static int __init ds1307_init(void) +{ + return i2c_add_driver(&ds1307_driver); +} +module_init(ds1307_init); + +static void __exit ds1307_exit(void) +{ + i2c_del_driver(&ds1307_driver); +} +module_exit(ds1307_exit); + +MODULE_DESCRIPTION("RTC driver for DS1307 and similar chips"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c new file mode 100644 index 0000000..ecafbad --- /dev/null +++ b/drivers/rtc/rtc-ds1553.c @@ -0,0 +1,414 @@ +/* + * An rtc driver for the Dallas DS1553 + * + * Copyright (C) 2006 Atsushi Nemoto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_VERSION "0.1" + +#define RTC_REG_SIZE 0x2000 +#define RTC_OFFSET 0x1ff0 + +#define RTC_FLAGS (RTC_OFFSET + 0) +#define RTC_SECONDS_ALARM (RTC_OFFSET + 2) +#define RTC_MINUTES_ALARM (RTC_OFFSET + 3) +#define RTC_HOURS_ALARM (RTC_OFFSET + 4) +#define RTC_DATE_ALARM (RTC_OFFSET + 5) +#define RTC_INTERRUPTS (RTC_OFFSET + 6) +#define RTC_WATCHDOG (RTC_OFFSET + 7) +#define RTC_CONTROL (RTC_OFFSET + 8) +#define RTC_CENTURY (RTC_OFFSET + 8) +#define RTC_SECONDS (RTC_OFFSET + 9) +#define RTC_MINUTES (RTC_OFFSET + 10) +#define RTC_HOURS (RTC_OFFSET + 11) +#define RTC_DAY (RTC_OFFSET + 12) +#define RTC_DATE (RTC_OFFSET + 13) +#define RTC_MONTH (RTC_OFFSET + 14) +#define RTC_YEAR (RTC_OFFSET + 15) + +#define RTC_CENTURY_MASK 0x3f +#define RTC_SECONDS_MASK 0x7f +#define RTC_DAY_MASK 0x07 + +/* Bits in the Control/Century register */ +#define RTC_WRITE 0x80 +#define RTC_READ 0x40 + +/* Bits in the Seconds register */ +#define RTC_STOP 0x80 + +/* Bits in the Flags register */ +#define RTC_FLAGS_AF 0x40 +#define RTC_FLAGS_BLF 0x10 + +/* Bits in the Interrupts register */ +#define RTC_INTS_AE 0x80 + +struct rtc_plat_data { + struct rtc_device *rtc; + void __iomem *ioaddr; + unsigned long baseaddr; + unsigned long last_jiffies; + int irq; + unsigned int irqen; + int alrm_sec; + int alrm_min; + int alrm_hour; + int alrm_mday; +}; + +static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + u8 century; + + century = BIN2BCD((tm->tm_year + 1900) / 100); + + writeb(RTC_WRITE, pdata->ioaddr + RTC_CONTROL); + + writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR); + writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH); + writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY); + writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE); + writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS); + writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES); + writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS); + + /* RTC_CENTURY and RTC_CONTROL share same register */ + writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY); + writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL); + return 0; +} + +static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + unsigned int year, month, day, hour, minute, second, week; + unsigned int century; + + /* give enough time to update RTC in case of continuous read */ + if (pdata->last_jiffies == jiffies) + msleep(1); + pdata->last_jiffies = jiffies; + writeb(RTC_READ, ioaddr + RTC_CONTROL); + second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK; + minute = readb(ioaddr + RTC_MINUTES); + hour = readb(ioaddr + RTC_HOURS); + day = readb(ioaddr + RTC_DATE); + week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK; + month = readb(ioaddr + RTC_MONTH); + year = readb(ioaddr + RTC_YEAR); + century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; + writeb(0, ioaddr + RTC_CONTROL); + tm->tm_sec = BCD2BIN(second); + tm->tm_min = BCD2BIN(minute); + tm->tm_hour = BCD2BIN(hour); + tm->tm_mday = BCD2BIN(day); + tm->tm_wday = BCD2BIN(week); + tm->tm_mon = BCD2BIN(month) - 1; + /* year is 1900 + tm->tm_year */ + tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900; + + if (rtc_valid_tm(tm) < 0) { + dev_err(dev, "retrieved date/time is not valid.\n"); + rtc_time_to_tm(0, tm); + } + return 0; +} + +static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata) +{ + void __iomem *ioaddr = pdata->ioaddr; + unsigned long flags; + + spin_lock_irqsave(&pdata->rtc->irq_lock, flags); + writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? + 0x80 : BIN2BCD(pdata->alrm_mday), + ioaddr + RTC_DATE_ALARM); + writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? + 0x80 : BIN2BCD(pdata->alrm_hour), + ioaddr + RTC_HOURS_ALARM); + writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? + 0x80 : BIN2BCD(pdata->alrm_min), + ioaddr + RTC_MINUTES_ALARM); + writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? + 0x80 : BIN2BCD(pdata->alrm_sec), + ioaddr + RTC_SECONDS_ALARM); + writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS); + readb(ioaddr + RTC_FLAGS); /* clear interrupts */ + spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); +} + +static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + if (pdata->irq < 0) + return -EINVAL; + pdata->alrm_mday = alrm->time.tm_mday; + pdata->alrm_hour = alrm->time.tm_hour; + pdata->alrm_min = alrm->time.tm_min; + pdata->alrm_sec = alrm->time.tm_sec; + if (alrm->enabled) + pdata->irqen |= RTC_AF; + ds1553_rtc_update_alarm(pdata); + return 0; +} + +static int ds1553_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + if (pdata->irq < 0) + return -EINVAL; + alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday; + alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour; + alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min; + alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec; + alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0; + return 0; +} + +static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct platform_device *pdev = dev_id; + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + unsigned long events = RTC_IRQF; + + /* read and clear interrupt */ + if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF)) + return IRQ_NONE; + if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) + events |= RTC_UF; + else + events |= RTC_AF; + rtc_update_irq(&pdata->rtc->class_dev, 1, events); + return IRQ_HANDLED; +} + +static void ds1553_rtc_release(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + if (pdata->irq >= 0) { + pdata->irqen = 0; + ds1553_rtc_update_alarm(pdata); + } +} + +static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, + unsigned long arg) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + if (pdata->irq < 0) + return -ENOIOCTLCMD; + switch (cmd) { + case RTC_AIE_OFF: + pdata->irqen &= ~RTC_AF; + ds1553_rtc_update_alarm(pdata); + break; + case RTC_AIE_ON: + pdata->irqen |= RTC_AF; + ds1553_rtc_update_alarm(pdata); + break; + case RTC_UIE_OFF: + pdata->irqen &= ~RTC_UF; + ds1553_rtc_update_alarm(pdata); + break; + case RTC_UIE_ON: + pdata->irqen |= RTC_UF; + ds1553_rtc_update_alarm(pdata); + break; + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static struct rtc_class_ops ds1553_rtc_ops = { + .read_time = ds1553_rtc_read_time, + .set_time = ds1553_rtc_set_time, + .read_alarm = ds1553_rtc_read_alarm, + .set_alarm = ds1553_rtc_set_alarm, + .release = ds1553_rtc_release, + .ioctl = ds1553_rtc_ioctl, +}; + +static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf, + loff_t pos, size_t size) +{ + struct platform_device *pdev = + to_platform_device(container_of(kobj, struct device, kobj)); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + ssize_t count; + + for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) + *buf++ = readb(ioaddr + pos++); + return count; +} + +static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf, + loff_t pos, size_t size) +{ + struct platform_device *pdev = + to_platform_device(container_of(kobj, struct device, kobj)); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + ssize_t count; + + for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) + writeb(*buf++, ioaddr + pos++); + return count; +} + +static struct bin_attribute ds1553_nvram_attr = { + .attr = { + .name = "nvram", + .mode = S_IRUGO | S_IWUGO, + .owner = THIS_MODULE, + }, + .size = RTC_OFFSET, + .read = ds1553_nvram_read, + .write = ds1553_nvram_write, +}; + +static int __init ds1553_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtc; + struct resource *res; + unsigned int cen, sec; + struct rtc_plat_data *pdata = NULL; + void __iomem *ioaddr = NULL; + int ret = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + pdata->irq = -1; + if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { + ret = -EBUSY; + goto out; + } + pdata->baseaddr = res->start; + ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); + if (!ioaddr) { + ret = -ENOMEM; + goto out; + } + pdata->ioaddr = ioaddr; + pdata->irq = platform_get_irq(pdev, 0); + + /* turn RTC on if it was not on */ + sec = readb(ioaddr + RTC_SECONDS); + if (sec & RTC_STOP) { + sec &= RTC_SECONDS_MASK; + cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; + writeb(RTC_WRITE, ioaddr + RTC_CONTROL); + writeb(sec, ioaddr + RTC_SECONDS); + writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL); + } + if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF) + dev_warn(&pdev->dev, "voltage-low detected.\n"); + + if (pdata->irq >= 0) { + writeb(0, ioaddr + RTC_INTERRUPTS); + if (request_irq(pdata->irq, ds1553_rtc_interrupt, SA_SHIRQ, + pdev->name, pdev) < 0) { + dev_warn(&pdev->dev, "interrupt not available.\n"); + pdata->irq = -1; + } + } + + rtc = rtc_device_register(pdev->name, &pdev->dev, + &ds1553_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + ret = PTR_ERR(rtc); + goto out; + } + pdata->rtc = rtc; + pdata->last_jiffies = jiffies; + platform_set_drvdata(pdev, pdata); + sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); + return 0; + out: + if (pdata->irq >= 0) + free_irq(pdata->irq, pdev); + if (ioaddr) + iounmap(ioaddr); + if (pdata->baseaddr) + release_mem_region(pdata->baseaddr, RTC_REG_SIZE); + kfree(pdata); + return ret; +} + +static int __devexit ds1553_rtc_remove(struct platform_device *pdev) +{ + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); + rtc_device_unregister(pdata->rtc); + if (pdata->irq >= 0) { + writeb(0, pdata->ioaddr + RTC_INTERRUPTS); + free_irq(pdata->irq, pdev); + } + iounmap(pdata->ioaddr); + release_mem_region(pdata->baseaddr, RTC_REG_SIZE); + kfree(pdata); + return 0; +} + +static struct platform_driver ds1553_rtc_driver = { + .probe = ds1553_rtc_probe, + .remove = __devexit_p(ds1553_rtc_remove), + .driver = { + .name = "ds1553", + .owner = THIS_MODULE, + }, +}; + +static __init int ds1553_init(void) +{ + return platform_driver_register(&ds1553_rtc_driver); +} + +static __exit void ds1553_exit(void) +{ + return platform_driver_unregister(&ds1553_rtc_driver); +} + +module_init(ds1553_init); +module_exit(ds1553_exit); + +MODULE_AUTHOR("Atsushi Nemoto "); +MODULE_DESCRIPTION("Dallas DS1553 RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c new file mode 100644 index 0000000..8e47e5a --- /dev/null +++ b/drivers/rtc/rtc-ds1742.c @@ -0,0 +1,259 @@ +/* + * An rtc driver for the Dallas DS1742 + * + * Copyright (C) 2006 Atsushi Nemoto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_VERSION "0.1" + +#define RTC_REG_SIZE 0x800 +#define RTC_OFFSET 0x7f8 + +#define RTC_CONTROL (RTC_OFFSET + 0) +#define RTC_CENTURY (RTC_OFFSET + 0) +#define RTC_SECONDS (RTC_OFFSET + 1) +#define RTC_MINUTES (RTC_OFFSET + 2) +#define RTC_HOURS (RTC_OFFSET + 3) +#define RTC_DAY (RTC_OFFSET + 4) +#define RTC_DATE (RTC_OFFSET + 5) +#define RTC_MONTH (RTC_OFFSET + 6) +#define RTC_YEAR (RTC_OFFSET + 7) + +#define RTC_CENTURY_MASK 0x3f +#define RTC_SECONDS_MASK 0x7f +#define RTC_DAY_MASK 0x07 + +/* Bits in the Control/Century register */ +#define RTC_WRITE 0x80 +#define RTC_READ 0x40 + +/* Bits in the Seconds register */ +#define RTC_STOP 0x80 + +/* Bits in the Day register */ +#define RTC_BATT_FLAG 0x80 + +struct rtc_plat_data { + struct rtc_device *rtc; + void __iomem *ioaddr; + unsigned long baseaddr; + unsigned long last_jiffies; +}; + +static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + u8 century; + + century = BIN2BCD((tm->tm_year + 1900) / 100); + + writeb(RTC_WRITE, ioaddr + RTC_CONTROL); + + writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR); + writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH); + writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY); + writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE); + writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS); + writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES); + writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS); + + /* RTC_CENTURY and RTC_CONTROL share same register */ + writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY); + writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL); + return 0; +} + +static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + unsigned int year, month, day, hour, minute, second, week; + unsigned int century; + + /* give enough time to update RTC in case of continuous read */ + if (pdata->last_jiffies == jiffies) + msleep(1); + pdata->last_jiffies = jiffies; + writeb(RTC_READ, ioaddr + RTC_CONTROL); + second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK; + minute = readb(ioaddr + RTC_MINUTES); + hour = readb(ioaddr + RTC_HOURS); + day = readb(ioaddr + RTC_DATE); + week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK; + month = readb(ioaddr + RTC_MONTH); + year = readb(ioaddr + RTC_YEAR); + century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; + writeb(0, ioaddr + RTC_CONTROL); + tm->tm_sec = BCD2BIN(second); + tm->tm_min = BCD2BIN(minute); + tm->tm_hour = BCD2BIN(hour); + tm->tm_mday = BCD2BIN(day); + tm->tm_wday = BCD2BIN(week); + tm->tm_mon = BCD2BIN(month) - 1; + /* year is 1900 + tm->tm_year */ + tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900; + + if (rtc_valid_tm(tm) < 0) { + dev_err(dev, "retrieved date/time is not valid.\n"); + rtc_time_to_tm(0, tm); + } + return 0; +} + +static struct rtc_class_ops ds1742_rtc_ops = { + .read_time = ds1742_rtc_read_time, + .set_time = ds1742_rtc_set_time, +}; + +static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf, + loff_t pos, size_t size) +{ + struct platform_device *pdev = + to_platform_device(container_of(kobj, struct device, kobj)); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + ssize_t count; + + for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) + *buf++ = readb(ioaddr + pos++); + return count; +} + +static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf, + loff_t pos, size_t size) +{ + struct platform_device *pdev = + to_platform_device(container_of(kobj, struct device, kobj)); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + ssize_t count; + + for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) + writeb(*buf++, ioaddr + pos++); + return count; +} + +static struct bin_attribute ds1742_nvram_attr = { + .attr = { + .name = "nvram", + .mode = S_IRUGO | S_IWUGO, + .owner = THIS_MODULE, + }, + .size = RTC_OFFSET, + .read = ds1742_nvram_read, + .write = ds1742_nvram_write, +}; + +static int __init ds1742_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtc; + struct resource *res; + unsigned int cen, sec; + struct rtc_plat_data *pdata = NULL; + void __iomem *ioaddr = NULL; + int ret = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { + ret = -EBUSY; + goto out; + } + pdata->baseaddr = res->start; + ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); + if (!ioaddr) { + ret = -ENOMEM; + goto out; + } + pdata->ioaddr = ioaddr; + + /* turn RTC on if it was not on */ + sec = readb(ioaddr + RTC_SECONDS); + if (sec & RTC_STOP) { + sec &= RTC_SECONDS_MASK; + cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; + writeb(RTC_WRITE, ioaddr + RTC_CONTROL); + writeb(sec, ioaddr + RTC_SECONDS); + writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL); + } + if (readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG) + dev_warn(&pdev->dev, "voltage-low detected.\n"); + + rtc = rtc_device_register(pdev->name, &pdev->dev, + &ds1742_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + ret = PTR_ERR(rtc); + goto out; + } + pdata->rtc = rtc; + pdata->last_jiffies = jiffies; + platform_set_drvdata(pdev, pdata); + sysfs_create_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr); + return 0; + out: + if (ioaddr) + iounmap(ioaddr); + if (pdata->baseaddr) + release_mem_region(pdata->baseaddr, RTC_REG_SIZE); + kfree(pdata); + return ret; +} + +static int __devexit ds1742_rtc_remove(struct platform_device *pdev) +{ + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + sysfs_remove_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr); + rtc_device_unregister(pdata->rtc); + iounmap(pdata->ioaddr); + release_mem_region(pdata->baseaddr, RTC_REG_SIZE); + kfree(pdata); + return 0; +} + +static struct platform_driver ds1742_rtc_driver = { + .probe = ds1742_rtc_probe, + .remove = __devexit_p(ds1742_rtc_remove), + .driver = { + .name = "ds1742", + .owner = THIS_MODULE, + }, +}; + +static __init int ds1742_init(void) +{ + return platform_driver_register(&ds1742_rtc_driver); +} + +static __exit void ds1742_exit(void) +{ + return platform_driver_unregister(&ds1742_rtc_driver); +} + +module_init(ds1742_init); +module_exit(ds1742_exit); + +MODULE_AUTHOR("Atsushi Nemoto "); +MODULE_DESCRIPTION("Dallas DS1742 RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index cfedc1d..9812120 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c @@ -18,9 +18,19 @@ static const unsigned char rtc_days_in_m 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static const unsigned short rtc_ydays[2][13] = { + /* Normal years */ + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + /* Leap years */ + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } +}; + #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) #define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400)) +/* + * The number of days in the month. + */ int rtc_month_days(unsigned int month, unsigned int year) { return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1); @@ -28,6 +38,15 @@ int rtc_month_days(unsigned int month, u EXPORT_SYMBOL(rtc_month_days); /* + * The number of days since January 1. (0 to 365) + */ +int rtc_year_days(unsigned int day, unsigned int month, unsigned int year) +{ + return rtc_ydays[LEAP_YEAR(year)][month] + day-1; +} +EXPORT_SYMBOL(rtc_year_days); + +/* * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. */ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c new file mode 100644 index 0000000..2c97395 --- /dev/null +++ b/drivers/rtc/rtc-max6902.c @@ -0,0 +1,286 @@ +/* drivers/char/max6902.c + * + * Copyright (C) 2006 8D Technologies inc. + * Copyright (C) 2004 Compulab Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for MAX6902 spi RTC + * + * Changelog: + * + * 24-May-2006: Raphael Assenat + * - Major rework + * Converted to rtc_device and uses the SPI layer. + * + * ??-???-2005: Someone at Compulab + * - Initial driver creation. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define MAX6902_REG_SECONDS 0x01 +#define MAX6902_REG_MINUTES 0x03 +#define MAX6902_REG_HOURS 0x05 +#define MAX6902_REG_DATE 0x07 +#define MAX6902_REG_MONTH 0x09 +#define MAX6902_REG_DAY 0x0B +#define MAX6902_REG_YEAR 0x0D +#define MAX6902_REG_CONTROL 0x0F +#define MAX6902_REG_CENTURY 0x13 + +#undef MAX6902_DEBUG + +struct max6902 { + struct rtc_device *rtc; + u8 buf[9]; /* Burst read cmd + 8 registers */ + u8 tx_buf[2]; + u8 rx_buf[2]; +}; + +static void max6902_set_reg(struct device *dev, unsigned char address, + unsigned char data) +{ + struct spi_device *spi = to_spi_device(dev); + unsigned char buf[2]; + + /* MSB must be '0' to write */ + buf[0] = address & 0x7f; + buf[1] = data; + + spi_write(spi, buf, 2); +} + +static int max6902_get_reg(struct device *dev, unsigned char address, + unsigned char *data) +{ + struct spi_device *spi = to_spi_device(dev); + struct max6902 *chip = dev_get_drvdata(dev); + struct spi_message message; + struct spi_transfer xfer; + int status; + + if (!data) + return -EINVAL; + + /* Build our spi message */ + spi_message_init(&message); + memset(&xfer, 0, sizeof(xfer)); + xfer.len = 2; + /* Can tx_buf and rx_buf be equal? The doc in spi.h is not sure... */ + xfer.tx_buf = chip->tx_buf; + xfer.rx_buf = chip->rx_buf; + + /* Set MSB to indicate read */ + chip->tx_buf[0] = address | 0x80; + + spi_message_add_tail(&xfer, &message); + + /* do the i/o */ + status = spi_sync(spi, &message); + if (status == 0) + status = message.status; + else + return status; + + *data = chip->rx_buf[1]; + + return status; +} + +static int max6902_get_datetime(struct device *dev, struct rtc_time *dt) +{ + unsigned char tmp; + int century; + int err; + struct spi_device *spi = to_spi_device(dev); + struct max6902 *chip = dev_get_drvdata(dev); + struct spi_message message; + struct spi_transfer xfer; + int status; + + err = max6902_get_reg(dev, MAX6902_REG_CENTURY, &tmp); + if (err) + return err; + + /* build the message */ + spi_message_init(&message); + memset(&xfer, 0, sizeof(xfer)); + xfer.len = 1 + 7; /* Burst read command + 7 registers */ + xfer.tx_buf = chip->buf; + xfer.rx_buf = chip->buf; + chip->buf[0] = 0xbf; /* Burst read */ + spi_message_add_tail(&xfer, &message); + + /* do the i/o */ + status = spi_sync(spi, &message); + if (status == 0) + status = message.status; + else + return status; + + /* The chip sends data in this order: + * Seconds, Minutes, Hours, Date, Month, Day, Year */ + dt->tm_sec = BCD2BIN(chip->buf[1]); + dt->tm_min = BCD2BIN(chip->buf[2]); + dt->tm_hour = BCD2BIN(chip->buf[3]); + dt->tm_mday = BCD2BIN(chip->buf[4]); + dt->tm_mon = BCD2BIN(chip->buf[5] - 1); + dt->tm_wday = BCD2BIN(chip->buf[6]); + dt->tm_year = BCD2BIN(chip->buf[7]); + + century = BCD2BIN(tmp) * 100; + + dt->tm_year += century; + dt->tm_year -= 1900; + +#ifdef MAX6902_DEBUG + printk("\n%s : Read RTC values\n",__FUNCTION__); + printk("tm_hour: %i\n",dt->tm_hour); + printk("tm_min : %i\n",dt->tm_min); + printk("tm_sec : %i\n",dt->tm_sec); + printk("tm_year: %i\n",dt->tm_year); + printk("tm_mon : %i\n",dt->tm_mon); + printk("tm_mday: %i\n",dt->tm_mday); + printk("tm_wday: %i\n",dt->tm_wday); +#endif + + return 0; +} + +static int max6902_set_datetime(struct device *dev, struct rtc_time *dt) +{ + dt->tm_year = dt->tm_year+1900; + +#ifdef MAX6902_DEBUG + printk("\n%s : Setting RTC values\n",__FUNCTION__); + printk("tm_sec : %i\n",dt->tm_sec); + printk("tm_min : %i\n",dt->tm_min); + printk("tm_hour: %i\n",dt->tm_hour); + printk("tm_mday: %i\n",dt->tm_mday); + printk("tm_wday: %i\n",dt->tm_wday); + printk("tm_year: %i\n",dt->tm_year); +#endif + + /* Remove write protection */ + max6902_set_reg(dev, 0xF, 0); + + max6902_set_reg(dev, 0x01, BIN2BCD(dt->tm_sec)); + max6902_set_reg(dev, 0x03, BIN2BCD(dt->tm_min)); + max6902_set_reg(dev, 0x05, BIN2BCD(dt->tm_hour)); + + max6902_set_reg(dev, 0x07, BIN2BCD(dt->tm_mday)); + max6902_set_reg(dev, 0x09, BIN2BCD(dt->tm_mon+1)); + max6902_set_reg(dev, 0x0B, BIN2BCD(dt->tm_wday)); + max6902_set_reg(dev, 0x0D, BIN2BCD(dt->tm_year%100)); + max6902_set_reg(dev, 0x13, BIN2BCD(dt->tm_year/100)); + + /* Compulab used a delay here. However, the datasheet + * does not mention a delay being required anywhere... */ + /* delay(2000); */ + + /* Write protect */ + max6902_set_reg(dev, 0xF, 0x80); + + return 0; +} + +static int max6902_read_time(struct device *dev, struct rtc_time *tm) +{ + return max6902_get_datetime(dev, tm); +} + +static int max6902_set_time(struct device *dev, struct rtc_time *tm) +{ + return max6902_set_datetime(dev, tm); +} + +static struct rtc_class_ops max6902_rtc_ops = { + .read_time = max6902_read_time, + .set_time = max6902_set_time, +}; + +static int __devinit max6902_probe(struct spi_device *spi) +{ + struct rtc_device *rtc; + unsigned char tmp; + struct max6902 *chip; + int res; + + rtc = rtc_device_register("max6902", + &spi->dev, &max6902_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + spi->mode = SPI_MODE_3; + spi->bits_per_word = 8; + spi_setup(spi); + + chip = kzalloc(sizeof *chip, GFP_KERNEL); + if (!chip) { + rtc_device_unregister(rtc); + return -ENOMEM; + } + chip->rtc = rtc; + dev_set_drvdata(&spi->dev, chip); + + res = max6902_get_reg(&spi->dev, MAX6902_REG_SECONDS, &tmp); + if (res) { + rtc_device_unregister(rtc); + return res; + } + + return 0; +} + +static int __devexit max6902_remove(struct spi_device *spi) +{ + struct max6902 *chip = platform_get_drvdata(spi); + struct rtc_device *rtc = chip->rtc; + + if (rtc) + rtc_device_unregister(rtc); + + kfree(chip); + + return 0; +} + +static struct spi_driver max6902_driver = { + .driver = { + .name = "max6902", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = max6902_probe, + .remove = __devexit_p(max6902_remove), +}; + +static __init int max6902_init(void) +{ + printk("max6902 spi driver\n"); + return spi_register_driver(&max6902_driver); +} +module_init(max6902_init); + +static __exit void max6902_exit(void) +{ + spi_unregister_driver(&max6902_driver); +} +module_exit(max6902_exit); + +MODULE_DESCRIPTION ("max6902 spi RTC driver"); +MODULE_AUTHOR ("Raphael Assenat"); +MODULE_LICENSE ("GPL"); diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c new file mode 100644 index 0000000..b235a30 --- /dev/null +++ b/drivers/rtc/rtc-pcf8583.c @@ -0,0 +1,394 @@ +/* + * drivers/rtc/rtc-pcf8583.c + * + * Copyright (C) 2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for PCF8583 RTC & RAM chip + * + * Converted to the generic RTC susbsystem by G. Liakhovetski (2006) + */ +#include +#include +#include +#include +#include +#include +#include +#include + +struct rtc_mem { + unsigned int loc; + unsigned int nr; + unsigned char *data; +}; + +struct pcf8583 { + struct i2c_client client; + struct rtc_device *rtc; + unsigned char ctrl; +}; + +#define CTRL_STOP 0x80 +#define CTRL_HOLD 0x40 +#define CTRL_32KHZ 0x00 +#define CTRL_MASK 0x08 +#define CTRL_ALARMEN 0x04 +#define CTRL_ALARM 0x02 +#define CTRL_TIMER 0x01 + +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Module parameters */ +I2C_CLIENT_INSMOD; + +static struct i2c_driver pcf8583_driver; + +#define get_ctrl(x) ((struct pcf8583 *)i2c_get_clientdata(x))->ctrl +#define set_ctrl(x, v) get_ctrl(x) = v + +#define CMOS_YEAR (64 + 128) +#define CMOS_CHECKSUM (63) + +static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt) +{ + unsigned char buf[8], addr[1] = { 1 }; + struct i2c_msg msgs[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 6, + .buf = buf, + } + }; + int ret; + + memset(buf, 0, sizeof(buf)); + + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret == 2) { + dt->tm_year = buf[4] >> 6; + dt->tm_wday = buf[5] >> 5; + + buf[4] &= 0x3f; + buf[5] &= 0x1f; + + dt->tm_sec = BCD_TO_BIN(buf[1]); + dt->tm_min = BCD_TO_BIN(buf[2]); + dt->tm_hour = BCD_TO_BIN(buf[3]); + dt->tm_mday = BCD_TO_BIN(buf[4]); + dt->tm_mon = BCD_TO_BIN(buf[5]); + } + + return ret == 2 ? 0 : -EIO; +} + +static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo) +{ + unsigned char buf[8]; + int ret, len = 6; + + buf[0] = 0; + buf[1] = get_ctrl(client) | 0x80; + buf[2] = 0; + buf[3] = BIN_TO_BCD(dt->tm_sec); + buf[4] = BIN_TO_BCD(dt->tm_min); + buf[5] = BIN_TO_BCD(dt->tm_hour); + + if (datetoo) { + len = 8; + buf[6] = BIN_TO_BCD(dt->tm_mday) | (dt->tm_year << 6); + buf[7] = BIN_TO_BCD(dt->tm_mon) | (dt->tm_wday << 5); + } + + ret = i2c_master_send(client, (char *)buf, len); + if (ret != len) + return -EIO; + + buf[1] = get_ctrl(client); + ret = i2c_master_send(client, (char *)buf, 2); + + return ret == 2 ? 0 : -EIO; +} + +static int pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl) +{ + *ctrl = get_ctrl(client); + return 0; +} + +static int pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl) +{ + unsigned char buf[2]; + + buf[0] = 0; + buf[1] = *ctrl; + set_ctrl(client, *ctrl); + + return i2c_master_send(client, (char *)buf, 2); +} + +static int pcf8583_read_mem(struct i2c_client *client, struct rtc_mem *mem) +{ + unsigned char addr[1]; + struct i2c_msg msgs[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = mem->nr, + .buf = mem->data, + } + }; + + if (mem->loc < 8) + return -EINVAL; + + addr[0] = mem->loc; + + return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; +} + +static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem) +{ + unsigned char addr[1]; + struct i2c_msg msgs[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_NOSTART, + .len = mem->nr, + .buf = mem->data, + } + }; + + if (mem->loc < 8) + return -EINVAL; + + addr[0] = mem->loc; + + return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; +} + +static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + unsigned char ctrl, year[2]; + struct rtc_mem mem = { CMOS_YEAR, sizeof(year), year }; + int real_year, year_offset, err; + + /* + * Ensure that the RTC is running. + */ + pcf8583_get_ctrl(client, &ctrl); + if (ctrl & (CTRL_STOP | CTRL_HOLD)) { + unsigned char new_ctrl = ctrl & ~(CTRL_STOP | CTRL_HOLD); + + printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n", + ctrl, new_ctrl); + + if ((err = pcf8583_set_ctrl(client, &new_ctrl)) < 0) + return err; + } + + if (pcf8583_get_datetime(client, tm) || + pcf8583_read_mem(client, &mem)) + return -EIO; + + real_year = year[0]; + + /* + * The RTC year holds the LSB two bits of the current + * year, which should reflect the LSB two bits of the + * CMOS copy of the year. Any difference indicates + * that we have to correct the CMOS version. + */ + year_offset = tm->tm_year - (real_year & 3); + if (year_offset < 0) + /* + * RTC year wrapped. Adjust it appropriately. + */ + year_offset += 4; + + tm->tm_year = real_year + year_offset + year[1] * 100; + + return 0; +} + +static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + unsigned char year[2], chk; + struct rtc_mem cmos_year = { CMOS_YEAR, sizeof(year), year }; + struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk }; + int ret; + + /* + * The RTC's own 2-bit year must reflect the least + * significant two bits of the CMOS year. + */ + + ret = pcf8583_set_datetime(client, tm, 1); + if (ret) + return ret; + + ret = pcf8583_read_mem(client, &cmos_check); + if (ret) + return ret; + + ret = pcf8583_read_mem(client, &cmos_year); + if (ret) + return ret; + + chk -= year[1] + year[0]; + + year[1] = tm->tm_year / 100; + year[0] = tm->tm_year % 100; + + chk += year[1] + year[0]; + + ret = pcf8583_write_mem(client, &cmos_year); + + if (ret) + return ret; + + ret = pcf8583_write_mem(client, &cmos_check); + + return ret; +} + +static struct rtc_class_ops pcf8583_rtc_ops = { + .read_time = pcf8583_rtc_read_time, + .set_time = pcf8583_rtc_set_time, +}; + +static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind); + +static int pcf8583_attach(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, pcf8583_probe); +} + +static int pcf8583_detach(struct i2c_client *client) +{ + int err; + struct pcf8583 *pcf = i2c_get_clientdata(client); + struct rtc_device *rtc = pcf->rtc; + + if (rtc) + rtc_device_unregister(rtc); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(pcf); + return 0; +} + +static struct i2c_driver pcf8583_driver = { + .driver = { + .name = "pcf8583", + }, + .id = I2C_DRIVERID_PCF8583, + .attach_adapter = pcf8583_attach, + .detach_client = pcf8583_detach, +}; + +static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind) +{ + struct pcf8583 *pcf; + struct i2c_client *client; + struct rtc_device *rtc; + unsigned char buf[1], ad[1] = { 0 }; + int err; + struct i2c_msg msgs[2] = { + { + .addr = addr, + .flags = 0, + .len = 1, + .buf = ad, + }, { + .addr = addr, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, + } + }; + + pcf = kzalloc(sizeof(*pcf), GFP_KERNEL); + if (!pcf) + return -ENOMEM; + + client = &pcf->client; + + client->addr = addr; + client->adapter = adap; + client->driver = &pcf8583_driver; + + strlcpy(client->name, pcf8583_driver.driver.name, I2C_NAME_SIZE); + + if (i2c_transfer(client->adapter, msgs, 2) != 2) { + err = -EIO; + goto exit_kfree; + } + + err = i2c_attach_client(client); + + if (err) + goto exit_kfree; + + rtc = rtc_device_register(pcf8583_driver.driver.name, &client->dev, + &pcf8583_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) { + err = PTR_ERR(rtc); + goto exit_detach; + } + + pcf->rtc = rtc; + i2c_set_clientdata(client, pcf); + set_ctrl(client, buf[0]); + + return 0; + +exit_detach: + i2c_detach_client(client); + +exit_kfree: + kfree(pcf); + + return err; +} + +static __init int pcf8583_init(void) +{ + return i2c_add_driver(&pcf8583_driver); +} + +static __exit void pcf8583_exit(void) +{ + i2c_del_driver(&pcf8583_driver); +} + +module_init(pcf8583_init); +module_exit(pcf8583_exit); + +MODULE_AUTHOR("Russell King"); +MODULE_DESCRIPTION("PCF8583 I2C RTC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c new file mode 100644 index 0000000..ee53863 --- /dev/null +++ b/drivers/rtc/rtc-pl031.c @@ -0,0 +1,233 @@ +/* + * drivers/rtc/rtc-pl031.c + * + * Real Time Clock interface for ARM AMBA PrimeCell 031 RTC + * + * Author: Deepak Saxena + * + * Copyright 2006 (c) MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +/* + * Register definitions + */ +#define RTC_DR 0x00 /* Data read register */ +#define RTC_MR 0x04 /* Match register */ +#define RTC_LR 0x08 /* Data load register */ +#define RTC_CR 0x0c /* Control register */ +#define RTC_IMSC 0x10 /* Interrupt mask and set register */ +#define RTC_RIS 0x14 /* Raw interrupt status register */ +#define RTC_MIS 0x18 /* Masked interrupt status register */ +#define RTC_ICR 0x1c /* Interrupt clear register */ + +struct pl031_local { + struct rtc_device *rtc; + void __iomem *base; +}; + +static irqreturn_t pl031_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct rtc_device *rtc = dev_id; + + rtc_update_irq(&rtc->class_dev, 1, RTC_AF); + + return IRQ_HANDLED; +} + +static int pl031_open(struct device *dev) +{ + /* + * We request IRQ in pl031_probe, so nothing to do here... + */ + return 0; +} + +static void pl031_release(struct device *dev) +{ +} + +static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) +{ + struct pl031_local *ldata = dev_get_drvdata(dev); + + switch (cmd) { + case RTC_AIE_OFF: + __raw_writel(1, ldata->base + RTC_MIS); + return 0; + case RTC_AIE_ON: + __raw_writel(0, ldata->base + RTC_MIS); + return 0; + } + + return -ENOIOCTLCMD; +} + +static int pl031_read_time(struct device *dev, struct rtc_time *tm) +{ + struct pl031_local *ldata = dev_get_drvdata(dev); + + rtc_time_to_tm(__raw_readl(ldata->base + RTC_DR), tm); + + return 0; +} + +static int pl031_set_time(struct device *dev, struct rtc_time *tm) +{ + unsigned long time; + struct pl031_local *ldata = dev_get_drvdata(dev); + + rtc_tm_to_time(tm, &time); + __raw_writel(time, ldata->base + RTC_LR); + + return 0; +} + +static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct pl031_local *ldata = dev_get_drvdata(dev); + + rtc_time_to_tm(__raw_readl(ldata->base + RTC_MR), &alarm->time); + alarm->pending = __raw_readl(ldata->base + RTC_RIS); + alarm->enabled = __raw_readl(ldata->base + RTC_IMSC); + + return 0; +} + +static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct pl031_local *ldata = dev_get_drvdata(dev); + unsigned long time; + + rtc_tm_to_time(&alarm->time, &time); + + __raw_writel(time, ldata->base + RTC_MR); + __raw_writel(!alarm->enabled, ldata->base + RTC_MIS); + + return 0; +} + +static struct rtc_class_ops pl031_ops = { + .open = pl031_open, + .release = pl031_release, + .ioctl = pl031_ioctl, + .read_time = pl031_read_time, + .set_time = pl031_set_time, + .read_alarm = pl031_read_alarm, + .set_alarm = pl031_set_alarm, +}; + +static int pl031_remove(struct amba_device *adev) +{ + struct pl031_local *ldata = dev_get_drvdata(&adev->dev); + + if (ldata) { + dev_set_drvdata(&adev->dev, NULL); + free_irq(adev->irq[0], ldata->rtc); + rtc_device_unregister(ldata->rtc); + iounmap(ldata->base); + kfree(ldata); + } + + return 0; +} + +static int pl031_probe(struct amba_device *adev, void *id) +{ + int ret; + struct pl031_local *ldata; + + + ldata = kmalloc(sizeof(struct pl031_local), GFP_KERNEL); + if (!ldata) { + ret = -ENOMEM; + goto out; + } + dev_set_drvdata(&adev->dev, ldata); + + ldata->base = ioremap(adev->res.start, + adev->res.end - adev->res.start + 1); + if (!ldata->base) { + ret = -ENOMEM; + goto out_no_remap; + } + + if (request_irq(adev->irq[0], pl031_interrupt, SA_INTERRUPT, + "rtc-pl031", ldata->rtc)) { + ret = -EIO; + goto out_no_irq; + } + + ldata->rtc = rtc_device_register("pl031", &adev->dev, &pl031_ops, + THIS_MODULE); + if (IS_ERR(ldata->rtc)) { + ret = PTR_ERR(ldata->rtc); + goto out_no_rtc; + } + + return 0; + +out_no_rtc: + free_irq(adev->irq[0], ldata->rtc); +out_no_irq: + iounmap(ldata->base); +out_no_remap: + dev_set_drvdata(&adev->dev, NULL); + kfree(ldata); +out: + return ret; +} + +static struct amba_id pl031_ids[] __initdata = { + { + .id = 0x00041031, + .mask = 0x000fffff, }, + {0, 0}, +}; + +static struct amba_driver pl031_driver = { + .drv = { + .name = "rtc-pl031", + }, + .id_table = pl031_ids, + .probe = pl031_probe, + .remove = pl031_remove, +}; + +static int __init pl031_init(void) +{ + return amba_driver_register(&pl031_driver); +} + +static void __exit pl031_exit(void) +{ + amba_driver_unregister(&pl031_driver); +} + +module_init(pl031_init); +module_exit(pl031_exit); + +MODULE_AUTHOR("Deepak Saxena 64) && !capable(CAP_SYS_RESOURCE)) - return -EACCES; spin_lock_irq(&sa1100_rtc_lock); OSMR1 = TIMER_FREQ/rtc_freq + OSCR; OIER |= OIER_E1; @@ -242,8 +240,6 @@ static int sa1100_rtc_ioctl(struct devic case RTC_IRQP_SET: if (arg < 1 || arg > TIMER_FREQ) return -EINVAL; - if ((arg > 64) && (!capable(CAP_SYS_RESOURCE))) - return -EACCES; rtc_freq = arg; return 0; } diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c new file mode 100644 index 0000000..a40f400 --- /dev/null +++ b/drivers/rtc/rtc-v3020.c @@ -0,0 +1,264 @@ +/* drivers/rtc/rtc-v3020.c + * + * Copyright (C) 2006 8D Technologies inc. + * Copyright (C) 2004 Compulab Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for the V3020 RTC + * + * Changelog: + * + * 10-May-2006: Raphael Assenat + * - Converted to platform driver + * - Use the generic rtc class + * + * ??-???-2004: Someone at Compulab + * - Initial driver creation. + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef DEBUG + +struct v3020 { + void __iomem *ioaddress; + int leftshift; + struct rtc_device *rtc; +}; + +static void v3020_set_reg(struct v3020 *chip, unsigned char address, + unsigned char data) +{ + int i; + unsigned char tmp; + + tmp = address; + for (i = 0; i < 4; i++) { + writel((tmp & 1) << chip->leftshift, chip->ioaddress); + tmp >>= 1; + } + + /* Commands dont have data */ + if (!V3020_IS_COMMAND(address)) { + for (i = 0; i < 8; i++) { + writel((data & 1) << chip->leftshift, chip->ioaddress); + data >>= 1; + } + } +} + +static unsigned char v3020_get_reg(struct v3020 *chip, unsigned char address) +{ + unsigned int data=0; + int i; + + for (i = 0; i < 4; i++) { + writel((address & 1) << chip->leftshift, chip->ioaddress); + address >>= 1; + } + + for (i = 0; i < 8; i++) { + data >>= 1; + if (readl(chip->ioaddress) & (1 << chip->leftshift)) + data |= 0x80; + } + + return data; +} + +static int v3020_read_time(struct device *dev, struct rtc_time *dt) +{ + struct v3020 *chip = dev_get_drvdata(dev); + int tmp; + + /* Copy the current time to ram... */ + v3020_set_reg(chip, V3020_CMD_CLOCK2RAM, 0); + + /* ...and then read constant values. */ + tmp = v3020_get_reg(chip, V3020_SECONDS); + dt->tm_sec = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_MINUTES); + dt->tm_min = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_HOURS); + dt->tm_hour = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_MONTH_DAY); + dt->tm_mday = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_MONTH); + dt->tm_mon = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_WEEK_DAY); + dt->tm_wday = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_YEAR); + dt->tm_year = BCD2BIN(tmp)+100; + +#ifdef DEBUG + printk("\n%s : Read RTC values\n",__FUNCTION__); + printk("tm_hour: %i\n",dt->tm_hour); + printk("tm_min : %i\n",dt->tm_min); + printk("tm_sec : %i\n",dt->tm_sec); + printk("tm_year: %i\n",dt->tm_year); + printk("tm_mon : %i\n",dt->tm_mon); + printk("tm_mday: %i\n",dt->tm_mday); + printk("tm_wday: %i\n",dt->tm_wday); +#endif + + return 0; +} + + +static int v3020_set_time(struct device *dev, struct rtc_time *dt) +{ + struct v3020 *chip = dev_get_drvdata(dev); + +#ifdef DEBUG + printk("\n%s : Setting RTC values\n",__FUNCTION__); + printk("tm_sec : %i\n",dt->tm_sec); + printk("tm_min : %i\n",dt->tm_min); + printk("tm_hour: %i\n",dt->tm_hour); + printk("tm_mday: %i\n",dt->tm_mday); + printk("tm_wday: %i\n",dt->tm_wday); + printk("tm_year: %i\n",dt->tm_year); +#endif + + /* Write all the values to ram... */ + v3020_set_reg(chip, V3020_SECONDS, BIN2BCD(dt->tm_sec)); + v3020_set_reg(chip, V3020_MINUTES, BIN2BCD(dt->tm_min)); + v3020_set_reg(chip, V3020_HOURS, BIN2BCD(dt->tm_hour)); + v3020_set_reg(chip, V3020_MONTH_DAY, BIN2BCD(dt->tm_mday)); + v3020_set_reg(chip, V3020_MONTH, BIN2BCD(dt->tm_mon)); + v3020_set_reg(chip, V3020_WEEK_DAY, BIN2BCD(dt->tm_wday)); + v3020_set_reg(chip, V3020_YEAR, BIN2BCD(dt->tm_year % 100)); + + /* ...and set the clock. */ + v3020_set_reg(chip, V3020_CMD_RAM2CLOCK, 0); + + /* Compulab used this delay here. I dont know why, + * the datasheet does not specify a delay. */ + /*mdelay(5);*/ + + return 0; +} + +static struct rtc_class_ops v3020_rtc_ops = { + .read_time = v3020_read_time, + .set_time = v3020_set_time, +}; + +static int rtc_probe(struct platform_device *pdev) +{ + struct v3020_platform_data *pdata = pdev->dev.platform_data; + struct v3020 *chip; + struct rtc_device *rtc; + int retval = -EBUSY; + int i; + int temp; + + if (pdev->num_resources != 1) + return -EBUSY; + + if (pdev->resource[0].flags != IORESOURCE_MEM) + return -EBUSY; + + if (pdev == NULL) + return -EBUSY; + + chip = kzalloc(sizeof *chip, GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->leftshift = pdata->leftshift; + chip->ioaddress = ioremap(pdev->resource[0].start, 1); + if (chip->ioaddress == NULL) + goto err_chip; + + /* Make sure the v3020 expects a communication cycle + * by reading 8 times */ + for (i = 0; i < 8; i++) + temp = readl(chip->ioaddress); + + /* Test chip by doing a write/read sequence + * to the chip ram */ + v3020_set_reg(chip, V3020_SECONDS, 0x33); + if(v3020_get_reg(chip, V3020_SECONDS) != 0x33) { + retval = -ENODEV; + goto err_io; + } + + /* Make sure frequency measurment mode, test modes, and lock + * are all disabled */ + v3020_set_reg(chip, V3020_STATUS_0, 0x0); + + dev_info(&pdev->dev, "Chip available at physical address 0x%p," + "data connected to D%d\n", + (void*)pdev->resource[0].start, + chip->leftshift); + + platform_set_drvdata(pdev, chip); + + rtc = rtc_device_register("v3020", + &pdev->dev, &v3020_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + retval = PTR_ERR(rtc); + goto err_io; + } + chip->rtc = rtc; + + return 0; + +err_io: + iounmap(chip->ioaddress); +err_chip: + kfree(chip); + + return retval; +} + +static int rtc_remove(struct platform_device *dev) +{ + struct v3020 *chip = platform_get_drvdata(dev); + struct rtc_device *rtc = chip->rtc; + + if (rtc) + rtc_device_unregister(rtc); + + iounmap(chip->ioaddress); + kfree(chip); + + return 0; +} + +static struct platform_driver rtc_device_driver = { + .probe = rtc_probe, + .remove = rtc_remove, + .driver = { + .name = "v3020", + .owner = THIS_MODULE, + }, +}; + +static __init int v3020_init(void) +{ + return platform_driver_register(&rtc_device_driver); +} + +static __exit void v3020_exit(void) +{ + platform_driver_unregister(&rtc_device_driver); +} + +module_init(v3020_init); +module_exit(v3020_exit); + +MODULE_DESCRIPTION("V3020 RTC"); +MODULE_AUTHOR("Raphael Assenat"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index 277596c..33e0292 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -81,7 +81,6 @@ #define RTCINTREG 0x1e #define RTC_FREQUENCY 32768 #define MAX_PERIODIC_RATE 6553 -#define MAX_USER_PERIODIC_RATE 64 static void __iomem *rtc1_base; static void __iomem *rtc2_base; @@ -240,9 +239,6 @@ static int vr41xx_rtc_ioctl(struct devic if (arg > MAX_PERIODIC_RATE) return -EINVAL; - if (arg > MAX_USER_PERIODIC_RATE && capable(CAP_SYS_RESOURCE) == 0) - return -EACCES; - periodic_frequency = arg; count = RTC_FREQUENCY; @@ -263,10 +259,6 @@ static int vr41xx_rtc_ioctl(struct devic /* Doesn't support before 1900 */ if (arg < 1900) return -EINVAL; - - if (capable(CAP_SYS_TIME) == 0) - return -EACCES; - epoch = arg; break; default: diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c index 56fa691..a4c53c1 100644 --- a/drivers/s390/char/sclp_quiesce.c +++ b/drivers/s390/char/sclp_quiesce.c @@ -13,6 +13,7 @@ #include #include #include #include +#include #include #include #include @@ -66,8 +67,6 @@ do_machine_quiesce(void) } #endif -extern void ctrl_alt_del(void); - /* Handler for quiesce event. Start shutdown procedure. */ static void sclp_quiesce_handler(struct evbuf_header *evbuf) diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h index 5e6b1f5..0ca1d12 100644 --- a/drivers/s390/crypto/z90crypt.h +++ b/drivers/s390/crypto/z90crypt.h @@ -1,7 +1,7 @@ /* * linux/drivers/s390/crypto/z90crypt.h * - * z90crypt 1.3.3 + * z90crypt 1.3.3 (kernel-private header) * * Copyright (C) 2001, 2005 IBM Corporation * Author(s): Robert Burroughs (burrough@us.ibm.com) @@ -27,188 +27,7 @@ #ifndef _Z90CRYPT_H_ #define _Z90CRYPT_H_ -#include - -#define z90crypt_VERSION 1 -#define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards -#define z90crypt_VARIANT 3 // 3 = CEX2A support - -/** - * struct ica_rsa_modexpo - * - * Requirements: - * - outputdatalength is at least as large as inputdatalength. - * - All key parts are right justified in their fields, padded on - * the left with zeroes. - * - length(b_key) = inputdatalength - * - length(n_modulus) = inputdatalength - */ -struct ica_rsa_modexpo { - char __user * inputdata; - unsigned int inputdatalength; - char __user * outputdata; - unsigned int outputdatalength; - char __user * b_key; - char __user * n_modulus; -}; - -/** - * struct ica_rsa_modexpo_crt - * - * Requirements: - * - inputdatalength is even. - * - outputdatalength is at least as large as inputdatalength. - * - All key parts are right justified in their fields, padded on - * the left with zeroes. - * - length(bp_key) = inputdatalength/2 + 8 - * - length(bq_key) = inputdatalength/2 - * - length(np_key) = inputdatalength/2 + 8 - * - length(nq_key) = inputdatalength/2 - * - length(u_mult_inv) = inputdatalength/2 + 8 - */ -struct ica_rsa_modexpo_crt { - char __user * inputdata; - unsigned int inputdatalength; - char __user * outputdata; - unsigned int outputdatalength; - char __user * bp_key; - char __user * bq_key; - char __user * np_prime; - char __user * nq_prime; - char __user * u_mult_inv; -}; - -#define Z90_IOCTL_MAGIC 'z' // NOTE: Need to allocate from linux folks - -/** - * Interface notes: - * - * The ioctl()s which are implemented (along with relevant details) - * are: - * - * ICARSAMODEXPO - * Perform an RSA operation using a Modulus-Exponent pair - * This takes an ica_rsa_modexpo struct as its arg. - * - * NOTE: please refer to the comments preceding this structure - * for the implementation details for the contents of the - * block - * - * ICARSACRT - * Perform an RSA operation using a Chinese-Remainder Theorem key - * This takes an ica_rsa_modexpo_crt struct as its arg. - * - * NOTE: please refer to the comments preceding this structure - * for the implementation details for the contents of the - * block - * - * Z90STAT_TOTALCOUNT - * Return an integer count of all device types together. - * - * Z90STAT_PCICACOUNT - * Return an integer count of all PCICAs. - * - * Z90STAT_PCICCCOUNT - * Return an integer count of all PCICCs. - * - * Z90STAT_PCIXCCMCL2COUNT - * Return an integer count of all MCL2 PCIXCCs. - * - * Z90STAT_PCIXCCMCL3COUNT - * Return an integer count of all MCL3 PCIXCCs. - * - * Z90STAT_CEX2CCOUNT - * Return an integer count of all CEX2Cs. - * - * Z90STAT_CEX2ACOUNT - * Return an integer count of all CEX2As. - * - * Z90STAT_REQUESTQ_COUNT - * Return an integer count of the number of entries waiting to be - * sent to a device. - * - * Z90STAT_PENDINGQ_COUNT - * Return an integer count of the number of entries sent to a - * device awaiting the reply. - * - * Z90STAT_TOTALOPEN_COUNT - * Return an integer count of the number of open file handles. - * - * Z90STAT_DOMAIN_INDEX - * Return the integer value of the Cryptographic Domain. - * - * Z90STAT_STATUS_MASK - * Return an 64 element array of unsigned chars for the status of - * all devices. - * 0x01: PCICA - * 0x02: PCICC - * 0x03: PCIXCC_MCL2 - * 0x04: PCIXCC_MCL3 - * 0x05: CEX2C - * 0x06: CEX2A - * 0x0d: device is disabled via the proc filesystem - * - * Z90STAT_QDEPTH_MASK - * Return an 64 element array of unsigned chars for the queue - * depth of all devices. - * - * Z90STAT_PERDEV_REQCNT - * Return an 64 element array of unsigned integers for the number - * of successfully completed requests per device since the device - * was detected and made available. - * - * ICAZ90STATUS (deprecated) - * Return some device driver status in a ica_z90_status struct - * This takes an ica_z90_status struct as its arg. - * - * NOTE: this ioctl() is deprecated, and has been replaced with - * single ioctl()s for each type of status being requested - * - * Z90STAT_PCIXCCCOUNT (deprecated) - * Return an integer count of all PCIXCCs (MCL2 + MCL3). - * This is DEPRECATED now that MCL3 PCIXCCs are treated differently from - * MCL2 PCIXCCs. - * - * Z90QUIESCE (not recommended) - * Quiesce the driver. This is intended to stop all new - * requests from being processed. Its use is NOT recommended, - * except in circumstances where there is no other way to stop - * callers from accessing the driver. Its original use was to - * allow the driver to be "drained" of work in preparation for - * a system shutdown. - * - * NOTE: once issued, this ban on new work cannot be undone - * except by unloading and reloading the driver. - */ - -/** - * Supported ioctl calls - */ -#define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0) -#define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0) - -/* DEPRECATED status calls (bound for removal at some point) */ -#define ICAZ90STATUS _IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status) -#define Z90STAT_PCIXCCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x43, int) - -/* unrelated to ICA callers */ -#define Z90QUIESCE _IO(Z90_IOCTL_MAGIC, 0x11) - -/* New status calls */ -#define Z90STAT_TOTALCOUNT _IOR(Z90_IOCTL_MAGIC, 0x40, int) -#define Z90STAT_PCICACOUNT _IOR(Z90_IOCTL_MAGIC, 0x41, int) -#define Z90STAT_PCICCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x42, int) -#define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int) -#define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int) -#define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int) -#define Z90STAT_CEX2ACOUNT _IOR(Z90_IOCTL_MAGIC, 0x4e, int) -#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int) -#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int) -#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int) -#define Z90STAT_DOMAIN_INDEX _IOR(Z90_IOCTL_MAGIC, 0x47, int) -#define Z90STAT_STATUS_MASK _IOR(Z90_IOCTL_MAGIC, 0x48, char[64]) -#define Z90STAT_QDEPTH_MASK _IOR(Z90_IOCTL_MAGIC, 0x49, char[64]) -#define Z90STAT_PERDEV_REQCNT _IOR(Z90_IOCTL_MAGIC, 0x4a, int[64]) +#include /** * local errno definitions diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile index 90d4d0e..6775a83 100644 --- a/drivers/s390/net/Makefile +++ b/drivers/s390/net/Makefile @@ -2,7 +2,7 @@ # # S/390 network devices # -ctc-objs := ctcmain.o ctctty.o ctcdbug.o +ctc-objs := ctcmain.o ctcdbug.o obj-$(CONFIG_IUCV) += iucv.o obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o @@ -10,6 +10,7 @@ obj-$(CONFIG_SMSGIUCV) += smsgiucv.o obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o obj-$(CONFIG_LCS) += lcs.o cu3088.o obj-$(CONFIG_CLAW) += claw.o cu3088.o +obj-$(CONFIG_MPC) += ctcmpc.o fsm.o cu3088.o qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth-$(CONFIG_PROC_FS) += qeth_proc.o obj-$(CONFIG_QETH) += qeth.o diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index fe986af..20c8eb1 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -6,7 +6,7 @@ * Fixes by : Jochen Röhrig (roehrig@de.ibm.com) * Arnaldo Carvalho de Melo Peter Tiedemann (ptiedem@de.ibm.com) - * Driver Model stuff by : Cornelia Huck + * Driver Model stuff by : Cornelia Huck * * Documentation used: * - Principles of Operation (IBM doc#: SA22-7201-06) @@ -65,7 +65,6 @@ #include #include -#include "ctctty.h" #include "fsm.h" #include "cu3088.h" @@ -479,10 +478,7 @@ #endif skb->dev = pskb->dev; skb->protocol = pskb->protocol; pskb->ip_summed = CHECKSUM_UNNECESSARY; - if (ch->protocol == CTC_PROTO_LINUX_TTY) - ctc_tty_netif_rx(skb); - else - netif_rx_ni(skb); + netif_rx_ni(skb); /** * Successful rx; reset logflags */ @@ -557,8 +553,7 @@ ccw_unit_check(struct channel *ch, unsig DBF_TEXT(trace, 5, __FUNCTION__); if (sense & SNS0_INTERVENTION_REQ) { if (sense & 0x01) { - if (ch->protocol != CTC_PROTO_LINUX_TTY) - ctc_pr_debug("%s: Interface disc. or Sel. reset " + ctc_pr_debug("%s: Interface disc. or Sel. reset " "(remote)\n", ch->id); fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch); } else { @@ -2034,7 +2029,6 @@ static void dev_action_chup(fsm_instance * fi, int event, void *arg) { struct net_device *dev = (struct net_device *) arg; - struct ctc_priv *privptr = dev->priv; DBF_TEXT(trace, 3, __FUNCTION__); switch (fsm_getstate(fi)) { @@ -2049,8 +2043,6 @@ dev_action_chup(fsm_instance * fi, int e fsm_newstate(fi, DEV_STATE_RUNNING); ctc_pr_info("%s: connected with remote side\n", dev->name); - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - ctc_tty_setcarrier(dev, 1); ctc_clear_busy(dev); } break; @@ -2059,8 +2051,6 @@ dev_action_chup(fsm_instance * fi, int e fsm_newstate(fi, DEV_STATE_RUNNING); ctc_pr_info("%s: connected with remote side\n", dev->name); - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - ctc_tty_setcarrier(dev, 1); ctc_clear_busy(dev); } break; @@ -2086,14 +2076,10 @@ dev_action_chup(fsm_instance * fi, int e static void dev_action_chdown(fsm_instance * fi, int event, void *arg) { - struct net_device *dev = (struct net_device *) arg; - struct ctc_priv *privptr = dev->priv; DBF_TEXT(trace, 3, __FUNCTION__); switch (fsm_getstate(fi)) { case DEV_STATE_RUNNING: - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - ctc_tty_setcarrier(dev, 0); if (event == DEV_EVENT_TXDOWN) fsm_newstate(fi, DEV_STATE_STARTWAIT_TX); else @@ -2397,8 +2383,6 @@ ctc_tx(struct sk_buff *skb, struct net_d */ if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) { fsm_event(privptr->fsm, DEV_EVENT_START, dev); - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - return -EBUSY; dev_kfree_skb(skb); privptr->stats.tx_dropped++; privptr->stats.tx_errors++; @@ -2608,20 +2592,13 @@ ctc_netdev_unregister(struct net_device if (!dev) return; privptr = (struct ctc_priv *) dev->priv; - if (privptr->protocol != CTC_PROTO_LINUX_TTY) - unregister_netdev(dev); - else - ctc_tty_unregister_netdev(dev); + unregister_netdev(dev); } static int ctc_netdev_register(struct net_device * dev) { - struct ctc_priv *privptr = (struct ctc_priv *) dev->priv; - if (privptr->protocol != CTC_PROTO_LINUX_TTY) - return register_netdev(dev); - else - return ctc_tty_register_netdev(dev); + return register_netdev(dev); } static void @@ -2667,7 +2644,9 @@ ctc_proto_store(struct device *dev, stru if (!priv) return -ENODEV; sscanf(buf, "%u", &value); - if ((value < 0) || (value > CTC_PROTO_MAX)) + if (!((value == CTC_PROTO_S390) || + (value == CTC_PROTO_LINUX) || + (value == CTC_PROTO_OS390))) return -EINVAL; priv->protocol = value; @@ -2897,10 +2876,7 @@ ctc_new_device(struct ccwgroup_device *c goto out; } - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - strlcpy(dev->name, "ctctty%d", IFNAMSIZ); - else - strlcpy(dev->name, "ctc%d", IFNAMSIZ); + strlcpy(dev->name, "ctc%d", IFNAMSIZ); for (direction = READ; direction <= WRITE; direction++) { privptr->channel[direction] = @@ -3046,7 +3022,6 @@ ctc_exit(void) { DBF_TEXT(setup, 3, __FUNCTION__); unregister_cu3088_discipline(&ctc_group_driver); - ctc_tty_cleanup(); ctc_unregister_dbf_views(); ctc_pr_info("CTC driver unloaded\n"); } @@ -3073,10 +3048,8 @@ ctc_init(void) ctc_pr_crit("ctc_init failed with ctc_register_dbf_views rc = %d\n", ret); return ret; } - ctc_tty_init(); ret = register_cu3088_discipline(&ctc_group_driver); if (ret) { - ctc_tty_cleanup(); ctc_unregister_dbf_views(); } return ret; diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h index d2e835c..7f305d1 100644 --- a/drivers/s390/net/ctcmain.h +++ b/drivers/s390/net/ctcmain.h @@ -35,7 +35,9 @@ #define _CTCMAIN_H_ #include #include -#include "ctctty.h" +#include +#include + #include "fsm.h" #include "cu3088.h" @@ -50,9 +52,7 @@ #define CCW_CMD_PREPARE 0xe3 #define CTC_PROTO_S390 0 #define CTC_PROTO_LINUX 1 -#define CTC_PROTO_LINUX_TTY 2 #define CTC_PROTO_OS390 3 -#define CTC_PROTO_MAX 3 #define CTC_BUFSIZE_LIMIT 65535 #define CTC_BUFSIZE_DEFAULT 32768 @@ -257,15 +257,13 @@ static __inline__ void ctc_clear_busy(struct net_device * dev) { clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy)); - if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) - netif_wake_queue(dev); + netif_wake_queue(dev); } static __inline__ int ctc_test_and_set_busy(struct net_device * dev) { - if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) - netif_stop_queue(dev); + netif_stop_queue(dev); return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy); } diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c deleted file mode 100644 index af54d1d..0000000 --- a/drivers/s390/net/ctctty.c +++ /dev/null @@ -1,1259 +0,0 @@ -/* - * CTC / ESCON network driver, tty interface. - * - * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ctctty.h" -#include "ctcdbug.h" - -#define CTC_TTY_MAJOR 43 -#define CTC_TTY_MAX_DEVICES 64 - -#define CTC_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */ -#define CTC_ASYNC_INITIALIZED 0x80000000 /* port was initialized */ -#define CTC_ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device active */ -#define CTC_ASYNC_CLOSING 0x08000000 /* Serial port is closing */ -#define CTC_ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */ -#define CTC_ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */ -#define CTC_ASYNC_HUP_NOTIFY 0x0001 /* Notify tty on hangups/closes */ -#define CTC_ASYNC_NETDEV_OPEN 0x0002 /* Underlying netdev is open */ -#define CTC_ASYNC_TX_LINESTAT 0x0004 /* Must send line status */ -#define CTC_ASYNC_SPLIT_TERMIOS 0x0008 /* Sep. termios for dialin/out */ -#define CTC_TTY_XMIT_SIZE 1024 /* Default bufsize for write */ -#define CTC_SERIAL_XMIT_MAX 4000 /* Maximum bufsize for write */ - -/* Private data (similar to async_struct in ) */ -typedef struct { - int magic; - int flags; /* defined in tty.h */ - int mcr; /* Modem control register */ - int msr; /* Modem status register */ - int lsr; /* Line status register */ - int line; - int count; /* # of fd on device */ - int blocked_open; /* # of blocked opens */ - struct net_device *netdev; - struct sk_buff_head tx_queue; /* transmit queue */ - struct sk_buff_head rx_queue; /* receive queue */ - struct tty_struct *tty; /* Pointer to corresponding tty */ - wait_queue_head_t open_wait; - wait_queue_head_t close_wait; - struct semaphore write_sem; - struct tasklet_struct tasklet; - struct timer_list stoptimer; -} ctc_tty_info; - -/* Description of one CTC-tty */ -typedef struct { - struct tty_driver *ctc_tty_device; /* tty-device */ - ctc_tty_info info[CTC_TTY_MAX_DEVICES]; /* Private data */ -} ctc_tty_driver; - -static ctc_tty_driver *driver; - -/* Leave this unchanged unless you know what you do! */ -#define MODEM_PARANOIA_CHECK -#define MODEM_DO_RESTART - -#define CTC_TTY_NAME "ctctty" - -static __u32 ctc_tty_magic = CTC_ASYNC_MAGIC; -static int ctc_tty_shuttingdown = 0; - -static spinlock_t ctc_tty_lock; - -/* ctc_tty_try_read() is called from within ctc_tty_rcv_skb() - * to stuff incoming data directly into a tty's flip-buffer. If the - * flip buffer is full, the packet gets queued up. - * - * Return: - * 1 = Success - * 0 = Failure, data has to be buffered and later processed by - * ctc_tty_readmodem(). - */ -static int -ctc_tty_try_read(ctc_tty_info * info, struct sk_buff *skb) -{ - int len; - struct tty_struct *tty; - - DBF_TEXT(trace, 5, __FUNCTION__); - if ((tty = info->tty)) { - if (info->mcr & UART_MCR_RTS) { - len = skb->len; - tty_insert_flip_string(tty, skb->data, len); - tty_flip_buffer_push(tty); - kfree_skb(skb); - return 1; - } - } - return 0; -} - -/* ctc_tty_readmodem() is called periodically from within timer-interrupt. - * It tries getting received data from the receive queue an stuff it into - * the tty's flip-buffer. - */ -static int -ctc_tty_readmodem(ctc_tty_info *info) -{ - int ret = 1; - struct tty_struct *tty; - - DBF_TEXT(trace, 5, __FUNCTION__); - if ((tty = info->tty)) { - if (info->mcr & UART_MCR_RTS) { - struct sk_buff *skb; - - if ((skb = skb_dequeue(&info->rx_queue))) { - int len = skb->len; - tty_insert_flip_string(tty, skb->data, len); - skb_pull(skb, len); - tty_flip_buffer_push(tty); - if (skb->len > 0) - skb_queue_head(&info->rx_queue, skb); - else { - kfree_skb(skb); - ret = !skb_queue_empty(&info->rx_queue); - } - } - } - } - return ret; -} - -void -ctc_tty_setcarrier(struct net_device *netdev, int on) -{ - int i; - - DBF_TEXT(trace, 4, __FUNCTION__); - if ((!driver) || ctc_tty_shuttingdown) - return; - for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) - if (driver->info[i].netdev == netdev) { - ctc_tty_info *info = &driver->info[i]; - if (on) - info->msr |= UART_MSR_DCD; - else - info->msr &= ~UART_MSR_DCD; - if ((info->flags & CTC_ASYNC_CHECK_CD) && (!on)) - tty_hangup(info->tty); - } -} - -void -ctc_tty_netif_rx(struct sk_buff *skb) -{ - int i; - ctc_tty_info *info = NULL; - - DBF_TEXT(trace, 5, __FUNCTION__); - if (!skb) - return; - if ((!skb->dev) || (!driver) || ctc_tty_shuttingdown) { - dev_kfree_skb(skb); - return; - } - for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) - if (driver->info[i].netdev == skb->dev) { - info = &driver->info[i]; - break; - } - if (!info) { - dev_kfree_skb(skb); - return; - } - if (skb->len < 6) { - dev_kfree_skb(skb); - return; - } - if (memcmp(skb->data, &ctc_tty_magic, sizeof(__u32))) { - dev_kfree_skb(skb); - return; - } - skb_pull(skb, sizeof(__u32)); - - i = *((int *)skb->data); - skb_pull(skb, sizeof(info->mcr)); - if (i & UART_MCR_RTS) { - info->msr |= UART_MSR_CTS; - if (info->flags & CTC_ASYNC_CTS_FLOW) - info->tty->hw_stopped = 0; - } else { - info->msr &= ~UART_MSR_CTS; - if (info->flags & CTC_ASYNC_CTS_FLOW) - info->tty->hw_stopped = 1; - } - if (i & UART_MCR_DTR) - info->msr |= UART_MSR_DSR; - else - info->msr &= ~UART_MSR_DSR; - if (skb->len <= 0) { - kfree_skb(skb); - return; - } - /* Try to deliver directly via tty-flip-buf if queue is empty */ - if (skb_queue_empty(&info->rx_queue)) - if (ctc_tty_try_read(info, skb)) - return; - /* Direct deliver failed or queue wasn't empty. - * Queue up for later dequeueing via timer-irq. - */ - skb_queue_tail(&info->rx_queue, skb); - /* Schedule dequeuing */ - tasklet_schedule(&info->tasklet); -} - -static int -ctc_tty_tint(ctc_tty_info * info) -{ - struct sk_buff *skb = skb_dequeue(&info->tx_queue); - int stopped = (info->tty->hw_stopped || info->tty->stopped); - int wake = 1; - int rc; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (!info->netdev) { - if (skb) - kfree_skb(skb); - return 0; - } - if (info->flags & CTC_ASYNC_TX_LINESTAT) { - int skb_res = info->netdev->hard_header_len + - sizeof(info->mcr) + sizeof(__u32); - /* If we must update line status, - * create an empty dummy skb and insert it. - */ - if (skb) - skb_queue_head(&info->tx_queue, skb); - - skb = dev_alloc_skb(skb_res); - if (!skb) { - printk(KERN_WARNING - "ctc_tty: Out of memory in %s%d tint\n", - CTC_TTY_NAME, info->line); - return 1; - } - skb_reserve(skb, skb_res); - stopped = 0; - wake = 0; - } - if (!skb) - return 0; - if (stopped) { - skb_queue_head(&info->tx_queue, skb); - return 1; - } -#if 0 - if (skb->len > 0) - printk(KERN_DEBUG "tint: %d %02x\n", skb->len, *(skb->data)); - else - printk(KERN_DEBUG "tint: %d STAT\n", skb->len); -#endif - memcpy(skb_push(skb, sizeof(info->mcr)), &info->mcr, sizeof(info->mcr)); - memcpy(skb_push(skb, sizeof(__u32)), &ctc_tty_magic, sizeof(__u32)); - rc = info->netdev->hard_start_xmit(skb, info->netdev); - if (rc) { - skb_pull(skb, sizeof(info->mcr) + sizeof(__u32)); - if (skb->len > 0) - skb_queue_head(&info->tx_queue, skb); - else - kfree_skb(skb); - } else { - struct tty_struct *tty = info->tty; - - info->flags &= ~CTC_ASYNC_TX_LINESTAT; - if (tty) { - tty_wakeup(tty); - } - } - return (skb_queue_empty(&info->tx_queue) ? 0 : 1); -} - -/************************************************************ - * - * Modem-functions - * - * mostly "stolen" from original Linux-serial.c and friends. - * - ************************************************************/ - -static inline int -ctc_tty_paranoia_check(ctc_tty_info * info, char *name, const char *routine) -{ -#ifdef MODEM_PARANOIA_CHECK - if (!info) { - printk(KERN_WARNING "ctc_tty: null info_struct for %s in %s\n", - name, routine); - return 1; - } - if (info->magic != CTC_ASYNC_MAGIC) { - printk(KERN_WARNING "ctc_tty: bad magic for info struct %s in %s\n", - name, routine); - return 1; - } -#endif - return 0; -} - -static void -ctc_tty_inject(ctc_tty_info *info, char c) -{ - int skb_res; - struct sk_buff *skb; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (ctc_tty_shuttingdown) - return; - skb_res = info->netdev->hard_header_len + sizeof(info->mcr) + - sizeof(__u32) + 1; - skb = dev_alloc_skb(skb_res); - if (!skb) { - printk(KERN_WARNING - "ctc_tty: Out of memory in %s%d tx_inject\n", - CTC_TTY_NAME, info->line); - return; - } - skb_reserve(skb, skb_res); - *(skb_put(skb, 1)) = c; - skb_queue_head(&info->tx_queue, skb); - tasklet_schedule(&info->tasklet); -} - -static void -ctc_tty_transmit_status(ctc_tty_info *info) -{ - DBF_TEXT(trace, 5, __FUNCTION__); - if (ctc_tty_shuttingdown) - return; - info->flags |= CTC_ASYNC_TX_LINESTAT; - tasklet_schedule(&info->tasklet); -} - -static void -ctc_tty_change_speed(ctc_tty_info * info) -{ - unsigned int cflag; - unsigned int quot; - int i; - - DBF_TEXT(trace, 3, __FUNCTION__); - if (!info->tty || !info->tty->termios) - return; - cflag = info->tty->termios->c_cflag; - - quot = i = cflag & CBAUD; - if (i & CBAUDEX) { - i &= ~CBAUDEX; - if (i < 1 || i > 2) - info->tty->termios->c_cflag &= ~CBAUDEX; - else - i += 15; - } - if (quot) { - info->mcr |= UART_MCR_DTR; - info->mcr |= UART_MCR_RTS; - ctc_tty_transmit_status(info); - } else { - info->mcr &= ~UART_MCR_DTR; - info->mcr &= ~UART_MCR_RTS; - ctc_tty_transmit_status(info); - return; - } - - /* CTS flow control flag and modem status interrupts */ - if (cflag & CRTSCTS) { - info->flags |= CTC_ASYNC_CTS_FLOW; - } else - info->flags &= ~CTC_ASYNC_CTS_FLOW; - if (cflag & CLOCAL) - info->flags &= ~CTC_ASYNC_CHECK_CD; - else { - info->flags |= CTC_ASYNC_CHECK_CD; - } -} - -static int -ctc_tty_startup(ctc_tty_info * info) -{ - DBF_TEXT(trace, 3, __FUNCTION__); - if (info->flags & CTC_ASYNC_INITIALIZED) - return 0; -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "starting up %s%d ...\n", CTC_TTY_NAME, info->line); -#endif - /* - * Now, initialize the UART - */ - info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - /* - * and set the speed of the serial port - */ - ctc_tty_change_speed(info); - - info->flags |= CTC_ASYNC_INITIALIZED; - if (!(info->flags & CTC_ASYNC_NETDEV_OPEN)) - info->netdev->open(info->netdev); - info->flags |= CTC_ASYNC_NETDEV_OPEN; - return 0; -} - -static void -ctc_tty_stopdev(unsigned long data) -{ - ctc_tty_info *info = (ctc_tty_info *)data; - - if ((!info) || (!info->netdev) || - (info->flags & CTC_ASYNC_INITIALIZED)) - return; - info->netdev->stop(info->netdev); - info->flags &= ~CTC_ASYNC_NETDEV_OPEN; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void -ctc_tty_shutdown(ctc_tty_info * info) -{ - DBF_TEXT(trace, 3, __FUNCTION__); - if (!(info->flags & CTC_ASYNC_INITIALIZED)) - return; -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "Shutting down %s%d ....\n", CTC_TTY_NAME, info->line); -#endif - info->msr &= ~UART_MSR_RI; - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) - info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS); - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - mod_timer(&info->stoptimer, jiffies + (10 * HZ)); - skb_queue_purge(&info->tx_queue); - skb_queue_purge(&info->rx_queue); - info->flags &= ~CTC_ASYNC_INITIALIZED; -} - -/* ctc_tty_write() is the main send-routine. It is called from the upper - * levels within the kernel to perform sending data. Depending on the - * online-flag it either directs output to the at-command-interpreter or - * to the lower level. Additional tasks done here: - * - If online, check for escape-sequence (+++) - * - If sending audio-data, call ctc_tty_DLEdown() to parse DLE-codes. - * - If receiving audio-data, call ctc_tty_end_vrx() to abort if needed. - * - If dialing, abort dial. - */ -static int -ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count) -{ - int c; - int total = 0; - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - DBF_TEXT(trace, 5, __FUNCTION__); - if (ctc_tty_shuttingdown) - goto ex; - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write")) - goto ex; - if (!tty) - goto ex; - if (!info->netdev) { - total = -ENODEV; - goto ex; - } - while (1) { - struct sk_buff *skb; - int skb_res; - - c = (count < CTC_TTY_XMIT_SIZE) ? count : CTC_TTY_XMIT_SIZE; - if (c <= 0) - break; - - skb_res = info->netdev->hard_header_len + sizeof(info->mcr) + - + sizeof(__u32); - skb = dev_alloc_skb(skb_res + c); - if (!skb) { - printk(KERN_WARNING - "ctc_tty: Out of memory in %s%d write\n", - CTC_TTY_NAME, info->line); - break; - } - skb_reserve(skb, skb_res); - memcpy(skb_put(skb, c), buf, c); - skb_queue_tail(&info->tx_queue, skb); - buf += c; - total += c; - count -= c; - } - if (!skb_queue_empty(&info->tx_queue)) { - info->lsr &= ~UART_LSR_TEMT; - tasklet_schedule(&info->tasklet); - } -ex: - DBF_TEXT(trace, 6, __FUNCTION__); - return total; -} - -static int -ctc_tty_write_room(struct tty_struct *tty) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write_room")) - return 0; - return CTC_TTY_XMIT_SIZE; -} - -static int -ctc_tty_chars_in_buffer(struct tty_struct *tty) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_chars_in_buffer")) - return 0; - return 0; -} - -static void -ctc_tty_flush_buffer(struct tty_struct *tty) -{ - ctc_tty_info *info; - unsigned long flags; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (!tty) - goto ex; - spin_lock_irqsave(&ctc_tty_lock, flags); - info = (ctc_tty_info *) tty->driver_data; - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_buffer")) { - spin_unlock_irqrestore(&ctc_tty_lock, flags); - goto ex; - } - skb_queue_purge(&info->tx_queue); - info->lsr |= UART_LSR_TEMT; - spin_unlock_irqrestore(&ctc_tty_lock, flags); - wake_up_interruptible(&tty->write_wait); - tty_wakeup(tty); -ex: - DBF_TEXT_(trace, 2, "ex: %s ", __FUNCTION__); - return; -} - -static void -ctc_tty_flush_chars(struct tty_struct *tty) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (ctc_tty_shuttingdown) - return; - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_chars")) - return; - if (tty->stopped || tty->hw_stopped || skb_queue_empty(&info->tx_queue)) - return; - tasklet_schedule(&info->tasklet); -} - -/* - * ------------------------------------------------------------ - * ctc_tty_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void -ctc_tty_throttle(struct tty_struct *tty) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_throttle")) - return; - info->mcr &= ~UART_MCR_RTS; - if (I_IXOFF(tty)) - ctc_tty_inject(info, STOP_CHAR(tty)); - ctc_tty_transmit_status(info); -} - -static void -ctc_tty_unthrottle(struct tty_struct *tty) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_unthrottle")) - return; - info->mcr |= UART_MCR_RTS; - if (I_IXOFF(tty)) - ctc_tty_inject(info, START_CHAR(tty)); - ctc_tty_transmit_status(info); -} - -/* - * ------------------------------------------------------------ - * ctc_tty_ioctl() and friends - * ------------------------------------------------------------ - */ - -/* - * ctc_tty_get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows RS485 driver to be written in user space. - */ -static int -ctc_tty_get_lsr_info(ctc_tty_info * info, uint __user *value) -{ - u_char status; - uint result; - ulong flags; - - DBF_TEXT(trace, 4, __FUNCTION__); - spin_lock_irqsave(&ctc_tty_lock, flags); - status = info->lsr; - spin_unlock_irqrestore(&ctc_tty_lock, flags); - result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); - put_user(result, value); - return 0; -} - - -static int ctc_tty_tiocmget(struct tty_struct *tty, struct file *file) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - u_char control, - status; - uint result; - ulong flags; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl")) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - control = info->mcr; - spin_lock_irqsave(&ctc_tty_lock, flags); - status = info->msr; - spin_unlock_irqrestore(&ctc_tty_lock, flags); - result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) - | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) - | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) - | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) - | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) - | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); - return result; -} - -static int -ctc_tty_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl")) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - if (set & TIOCM_RTS) - info->mcr |= UART_MCR_RTS; - if (set & TIOCM_DTR) - info->mcr |= UART_MCR_DTR; - - if (clear & TIOCM_RTS) - info->mcr &= ~UART_MCR_RTS; - if (clear & TIOCM_DTR) - info->mcr &= ~UART_MCR_DTR; - - if ((set | clear) & (TIOCM_RTS|TIOCM_DTR)) - ctc_tty_transmit_status(info); - return 0; -} - -static int -ctc_tty_ioctl(struct tty_struct *tty, struct file *file, - uint cmd, ulong arg) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - int error; - int retval; - - DBF_TEXT(trace, 4, __FUNCTION__); - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl")) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ -#ifdef CTC_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "%s%d ioctl TCSBRK\n", CTC_TTY_NAME, info->line); -#endif - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ -#ifdef CTC_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "%s%d ioctl TCSBRKP\n", CTC_TTY_NAME, info->line); -#endif - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - return 0; - case TIOCGSOFTCAR: -#ifdef CTC_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "%s%d ioctl TIOCGSOFTCAR\n", CTC_TTY_NAME, - info->line); -#endif - error = put_user(C_CLOCAL(tty) ? 1 : 0, (ulong __user *) arg); - return error; - case TIOCSSOFTCAR: -#ifdef CTC_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "%s%d ioctl TIOCSSOFTCAR\n", CTC_TTY_NAME, - info->line); -#endif - error = get_user(arg, (ulong __user *) arg); - if (error) - return error; - tty->termios->c_cflag = - ((tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); - return 0; - case TIOCSERGETLSR: /* Get line status register */ -#ifdef CTC_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME, - info->line); -#endif - if (access_ok(VERIFY_WRITE, (void __user *) arg, sizeof(uint))) - return ctc_tty_get_lsr_info(info, (uint __user *) arg); - else - return -EFAULT; - default: -#ifdef CTC_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on %s%d\n", cmd, - CTC_TTY_NAME, info->line); -#endif - return -ENOIOCTLCMD; - } - return 0; -} - -static void -ctc_tty_set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - unsigned int cflag = tty->termios->c_cflag; - - DBF_TEXT(trace, 4, __FUNCTION__); - ctc_tty_change_speed(info); - - /* Handle transition to B0 */ - if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) { - info->mcr &= ~(UART_MCR_DTR|UART_MCR_RTS); - ctc_tty_transmit_status(info); - } - - /* Handle transition from B0 to other */ - if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { - info->mcr |= UART_MCR_DTR; - if (!(tty->termios->c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { - info->mcr |= UART_MCR_RTS; - } - ctc_tty_transmit_status(info); - } - - /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) - tty->hw_stopped = 0; -} - -/* - * ------------------------------------------------------------ - * ctc_tty_open() and friends - * ------------------------------------------------------------ - */ -static int -ctc_tty_block_til_ready(struct tty_struct *tty, struct file *filp, ctc_tty_info *info) -{ - DECLARE_WAITQUEUE(wait, NULL); - int do_clocal = 0; - unsigned long flags; - int retval; - - DBF_TEXT(trace, 4, __FUNCTION__); - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || - (info->flags & CTC_ASYNC_CLOSING)) { - if (info->flags & CTC_ASYNC_CLOSING) - wait_event(info->close_wait, - !(info->flags & CTC_ASYNC_CLOSING)); -#ifdef MODEM_DO_RESTART - if (info->flags & CTC_ASYNC_HUP_NOTIFY) - return -EAGAIN; - else - return -ERESTARTSYS; -#else - return -EAGAIN; -#endif - } - /* - * If non-blocking mode is set, then make the check up front - * and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= CTC_ASYNC_NORMAL_ACTIVE; - return 0; - } - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that - * ctc_tty_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "ctc_tty_block_til_ready before block: %s%d, count = %d\n", - CTC_TTY_NAME, info->line, info->count); -#endif - spin_lock_irqsave(&ctc_tty_lock, flags); - if (!(tty_hung_up_p(filp))) - info->count--; - spin_unlock_irqrestore(&ctc_tty_lock, flags); - info->blocked_open++; - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(info->flags & CTC_ASYNC_INITIALIZED)) { -#ifdef MODEM_DO_RESTART - if (info->flags & CTC_ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif - break; - } - if (!(info->flags & CTC_ASYNC_CLOSING) && - (do_clocal || (info->msr & UART_MSR_DCD))) { - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "ctc_tty_block_til_ready blocking: %s%d, count = %d\n", - CTC_TTY_NAME, info->line, info->count); -#endif - schedule(); - } - current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); - if (!tty_hung_up_p(filp)) - info->count++; - info->blocked_open--; -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "ctc_tty_block_til_ready after blocking: %s%d, count = %d\n", - CTC_TTY_NAME, info->line, info->count); -#endif - if (retval) - return retval; - info->flags |= CTC_ASYNC_NORMAL_ACTIVE; - return 0; -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port, linking in its async structure into - * the IRQ chain. It also performs the serial-specific - * initialization for the tty structure. - */ -static int -ctc_tty_open(struct tty_struct *tty, struct file *filp) -{ - ctc_tty_info *info; - unsigned long saveflags; - int retval, - line; - - DBF_TEXT(trace, 3, __FUNCTION__); - line = tty->index; - if (line < 0 || line > CTC_TTY_MAX_DEVICES) - return -ENODEV; - info = &driver->info[line]; - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_open")) - return -ENODEV; - if (!info->netdev) - return -ENODEV; -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "ctc_tty_open %s, count = %d\n", tty->name, - info->count); -#endif - spin_lock_irqsave(&ctc_tty_lock, saveflags); - info->count++; - tty->driver_data = info; - info->tty = tty; - spin_unlock_irqrestore(&ctc_tty_lock, saveflags); - /* - * Start up serial port - */ - retval = ctc_tty_startup(info); - if (retval) { -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "ctc_tty_open return after startup\n"); -#endif - return retval; - } - retval = ctc_tty_block_til_ready(tty, filp, info); - if (retval) { -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "ctc_tty_open return after ctc_tty_block_til_ready \n"); -#endif - return retval; - } -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "ctc_tty_open %s successful...\n", tty->name); -#endif - return 0; -} - -static void -ctc_tty_close(struct tty_struct *tty, struct file *filp) -{ - ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - ulong flags; - ulong timeout; - DBF_TEXT(trace, 3, __FUNCTION__); - if (!info || ctc_tty_paranoia_check(info, tty->name, "ctc_tty_close")) - return; - spin_lock_irqsave(&ctc_tty_lock, flags); - if (tty_hung_up_p(filp)) { - spin_unlock_irqrestore(&ctc_tty_lock, flags); -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "ctc_tty_close return after tty_hung_up_p\n"); -#endif - return; - } - if ((tty->count == 1) && (info->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk(KERN_ERR "ctc_tty_close: bad port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; - } - if (--info->count < 0) { - printk(KERN_ERR "ctc_tty_close: bad port count for %s%d: %d\n", - CTC_TTY_NAME, info->line, info->count); - info->count = 0; - } - if (info->count) { - local_irq_restore(flags); -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "ctc_tty_close after info->count != 0\n"); -#endif - return; - } - info->flags |= CTC_ASYNC_CLOSING; - tty->closing = 1; - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - if (info->flags & CTC_ASYNC_INITIALIZED) { - tty_wait_until_sent(tty, 30*HZ); /* 30 seconds timeout */ - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - timeout = jiffies + HZ; - while (!(info->lsr & UART_LSR_TEMT)) { - spin_unlock_irqrestore(&ctc_tty_lock, flags); - msleep(500); - spin_lock_irqsave(&ctc_tty_lock, flags); - if (time_after(jiffies,timeout)) - break; - } - } - ctc_tty_shutdown(info); - if (tty->driver->flush_buffer) { - skb_queue_purge(&info->tx_queue); - info->lsr |= UART_LSR_TEMT; - } - tty_ldisc_flush(tty); - info->tty = 0; - tty->closing = 0; - if (info->blocked_open) { - msleep_interruptible(500); - wake_up_interruptible(&info->open_wait); - } - info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); - spin_unlock_irqrestore(&ctc_tty_lock, flags); -#ifdef CTC_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "ctc_tty_close normal exit\n"); -#endif -} - -/* - * ctc_tty_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -static void -ctc_tty_hangup(struct tty_struct *tty) -{ - ctc_tty_info *info = (ctc_tty_info *)tty->driver_data; - unsigned long saveflags; - DBF_TEXT(trace, 3, __FUNCTION__); - if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_hangup")) - return; - ctc_tty_shutdown(info); - info->count = 0; - info->flags &= ~CTC_ASYNC_NORMAL_ACTIVE; - spin_lock_irqsave(&ctc_tty_lock, saveflags); - info->tty = 0; - spin_unlock_irqrestore(&ctc_tty_lock, saveflags); - wake_up_interruptible(&info->open_wait); -} - - -/* - * For all online tty's, try sending data to - * the lower levels. - */ -static void -ctc_tty_task(unsigned long arg) -{ - ctc_tty_info *info = (void *)arg; - unsigned long saveflags; - int again; - - DBF_TEXT(trace, 3, __FUNCTION__); - spin_lock_irqsave(&ctc_tty_lock, saveflags); - if ((!ctc_tty_shuttingdown) && info) { - again = ctc_tty_tint(info); - if (!again) - info->lsr |= UART_LSR_TEMT; - again |= ctc_tty_readmodem(info); - if (again) { - tasklet_schedule(&info->tasklet); - } - } - spin_unlock_irqrestore(&ctc_tty_lock, saveflags); -} - -static struct tty_operations ctc_ops = { - .open = ctc_tty_open, - .close = ctc_tty_close, - .write = ctc_tty_write, - .flush_chars = ctc_tty_flush_chars, - .write_room = ctc_tty_write_room, - .chars_in_buffer = ctc_tty_chars_in_buffer, - .flush_buffer = ctc_tty_flush_buffer, - .ioctl = ctc_tty_ioctl, - .throttle = ctc_tty_throttle, - .unthrottle = ctc_tty_unthrottle, - .set_termios = ctc_tty_set_termios, - .hangup = ctc_tty_hangup, - .tiocmget = ctc_tty_tiocmget, - .tiocmset = ctc_tty_tiocmset, -}; - -int -ctc_tty_init(void) -{ - int i; - ctc_tty_info *info; - struct tty_driver *device; - - DBF_TEXT(trace, 2, __FUNCTION__); - driver = kmalloc(sizeof(ctc_tty_driver), GFP_KERNEL); - if (driver == NULL) { - printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n"); - return -ENOMEM; - } - memset(driver, 0, sizeof(ctc_tty_driver)); - device = alloc_tty_driver(CTC_TTY_MAX_DEVICES); - if (!device) { - kfree(driver); - printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n"); - return -ENOMEM; - } - - device->devfs_name = "ctc/" CTC_TTY_NAME; - device->name = CTC_TTY_NAME; - device->major = CTC_TTY_MAJOR; - device->minor_start = 0; - device->type = TTY_DRIVER_TYPE_SERIAL; - device->subtype = SERIAL_TYPE_NORMAL; - device->init_termios = tty_std_termios; - device->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - device->flags = TTY_DRIVER_REAL_RAW; - device->driver_name = "ctc_tty", - tty_set_operations(device, &ctc_ops); - if (tty_register_driver(device)) { - printk(KERN_WARNING "ctc_tty: Couldn't register serial-device\n"); - put_tty_driver(device); - kfree(driver); - return -1; - } - driver->ctc_tty_device = device; - for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) { - info = &driver->info[i]; - init_MUTEX(&info->write_sem); - tasklet_init(&info->tasklet, ctc_tty_task, - (unsigned long) info); - info->magic = CTC_ASYNC_MAGIC; - info->line = i; - info->tty = 0; - info->count = 0; - info->blocked_open = 0; - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - skb_queue_head_init(&info->tx_queue); - skb_queue_head_init(&info->rx_queue); - init_timer(&info->stoptimer); - info->stoptimer.function = ctc_tty_stopdev; - info->stoptimer.data = (unsigned long)info; - info->mcr = UART_MCR_RTS; - } - return 0; -} - -int -ctc_tty_register_netdev(struct net_device *dev) { - int ttynum; - char *err; - char *p; - - DBF_TEXT(trace, 2, __FUNCTION__); - if ((!dev) || (!dev->name)) { - printk(KERN_WARNING - "ctc_tty_register_netdev called " - "with NULL dev or NULL dev-name\n"); - return -1; - } - - /* - * If the name is a format string the caller wants us to - * do a name allocation : format string must end with %d - */ - if (strchr(dev->name, '%')) - { - int err = dev_alloc_name(dev, dev->name); // dev->name is changed by this - if (err < 0) { - printk(KERN_DEBUG "dev_alloc returned error %d\n", err); - return err; - } - - } - - for (p = dev->name; p && ((*p < '0') || (*p > '9')); p++); - ttynum = simple_strtoul(p, &err, 0); - if ((ttynum < 0) || (ttynum >= CTC_TTY_MAX_DEVICES) || - (err && *err)) { - printk(KERN_WARNING - "ctc_tty_register_netdev called " - "with number in name '%s'\n", dev->name); - return -1; - } - if (driver->info[ttynum].netdev) { - printk(KERN_WARNING - "ctc_tty_register_netdev called " - "for already registered device '%s'\n", - dev->name); - return -1; - } - driver->info[ttynum].netdev = dev; - return 0; -} - -void -ctc_tty_unregister_netdev(struct net_device *dev) { - int i; - unsigned long saveflags; - ctc_tty_info *info = NULL; - - DBF_TEXT(trace, 2, __FUNCTION__); - spin_lock_irqsave(&ctc_tty_lock, saveflags); - for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) - if (driver->info[i].netdev == dev) { - info = &driver->info[i]; - break; - } - if (info) { - info->netdev = NULL; - skb_queue_purge(&info->tx_queue); - skb_queue_purge(&info->rx_queue); - } - spin_unlock_irqrestore(&ctc_tty_lock, saveflags); -} - -void -ctc_tty_cleanup(void) { - unsigned long saveflags; - - DBF_TEXT(trace, 2, __FUNCTION__); - spin_lock_irqsave(&ctc_tty_lock, saveflags); - ctc_tty_shuttingdown = 1; - spin_unlock_irqrestore(&ctc_tty_lock, saveflags); - tty_unregister_driver(driver->ctc_tty_device); - put_tty_driver(driver->ctc_tty_device); - kfree(driver); - driver = NULL; -} diff --git a/drivers/s390/net/ctctty.h b/drivers/s390/net/ctctty.h deleted file mode 100644 index 7254dc0..0000000 --- a/drivers/s390/net/ctctty.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * CTC / ESCON network driver, tty interface. - * - * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _CTCTTY_H_ -#define _CTCTTY_H_ - -#include -#include - -extern int ctc_tty_register_netdev(struct net_device *); -extern void ctc_tty_unregister_netdev(struct net_device *); -extern void ctc_tty_netif_rx(struct sk_buff *); -extern int ctc_tty_init(void); -extern void ctc_tty_cleanup(void); -extern void ctc_tty_setcarrier(struct net_device *, int); - -#endif diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index f94419b..2eded55 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -1140,10 +1140,9 @@ list_modified: } } /* re-insert all entries from the failed_list into ipm_list */ - list_for_each_entry_safe(ipm, tmp, &failed_list, list) { - list_del_init(&ipm->list); - list_add_tail(&ipm->list, &card->ipm_list); - } + list_for_each_entry_safe(ipm, tmp, &failed_list, list) + list_move_tail(&ipm->list, &card->ipm_list); + spin_unlock_irqrestore(&card->ipm_lock, flags); } diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 0bab60a..38aad83 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -420,7 +420,7 @@ #endif /* CONFIG_QETH_VLAN */ } tcph = eddp->skb->h.th; while (eddp->skb_offset < eddp->skb->len) { - data_len = min((int)skb_shinfo(eddp->skb)->tso_size, + data_len = min((int)skb_shinfo(eddp->skb)->gso_size, (int)(eddp->skb->len - eddp->skb_offset)); /* prepare qdio hdr */ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){ @@ -515,20 +515,20 @@ qeth_eddp_calc_num_pages(struct qeth_edd QETH_DBF_TEXT(trace, 5, "eddpcanp"); /* can we put multiple skbs in one page? */ - skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len); + skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len); if (skbs_per_page > 1){ - ctx->num_pages = (skb_shinfo(skb)->tso_segs + 1) / + ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) / skbs_per_page + 1; ctx->elements_per_skb = 1; } else { /* no -> how many elements per skb? */ - ctx->elements_per_skb = (skb_shinfo(skb)->tso_size + hdr_len + + ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len + PAGE_SIZE) >> PAGE_SHIFT; ctx->num_pages = ctx->elements_per_skb * - (skb_shinfo(skb)->tso_segs + 1); + (skb_shinfo(skb)->gso_segs + 1); } ctx->num_elements = ctx->elements_per_skb * - (skb_shinfo(skb)->tso_segs + 1); + (skb_shinfo(skb)->gso_segs + 1); } static inline struct qeth_eddp_context * diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 9e671a4..56009d7 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -4417,7 +4417,7 @@ qeth_send_packet(struct qeth_card *card, struct qeth_eddp_context *ctx = NULL; int tx_bytes = skb->len; unsigned short nr_frags = skb_shinfo(skb)->nr_frags; - unsigned short tso_size = skb_shinfo(skb)->tso_size; + unsigned short tso_size = skb_shinfo(skb)->gso_size; int rc; QETH_DBF_TEXT(trace, 6, "sendpkt"); @@ -4453,7 +4453,7 @@ qeth_send_packet(struct qeth_card *card, queue = card->qdio.out_qs [qeth_get_priority_queue(card, skb, ipv, cast_type)]; - if (skb_shinfo(skb)->tso_size) + if (skb_shinfo(skb)->gso_size) large_send = card->options.large_send; /*are we able to do TSO ? If so ,prepare and send it from here */ diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h index 24ef40c..593f298 100644 --- a/drivers/s390/net/qeth_tso.h +++ b/drivers/s390/net/qeth_tso.h @@ -51,7 +51,7 @@ qeth_tso_fill_header(struct qeth_card *c hdr->ext.hdr_version = 1; hdr->ext.hdr_len = 28; /*insert non-fix values */ - hdr->ext.mss = skb_shinfo(skb)->tso_size; + hdr->ext.mss = skb_shinfo(skb)->gso_size; hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4); hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - sizeof(struct qeth_hdr_tso)); diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 395cfc6..9cd789b 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -1,18 +1,8 @@ /* + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * linux/drivers/s390/scsi/zfcp_aux.c - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 - * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +19,20 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + * Driver authors: + * Martin Peschke (originator of the driver) + * Raimund Schroeder + * Aron Zeh + * Wolfgang Taphorn + * Stefan Bader + * Heiko Carstens (kernel 2.6 port of the driver) + * Andreas Herrmann + * Maxim Shchetynin + * Volker Sameske + * Ralph Wuerthner + */ + #include "zfcp_ext.h" /* accumulated log level (module parameter) */ @@ -75,15 +79,9 @@ static struct miscdevice zfcp_cfdc_misc /* declare driver module init/cleanup functions */ module_init(zfcp_module_init); -MODULE_AUTHOR("Heiko Carstens , " - "Andreas Herrman , " - "Martin Peschke , " - "Raimund Schroeder , " - "Wolfgang Taphorn , " - "Aron Zeh , " - "IBM Deutschland Entwicklung GmbH"); +MODULE_AUTHOR("IBM Deutschland Entwicklung GmbH - linux390@de.ibm.com"); MODULE_DESCRIPTION - ("FCP (SCSI over Fibre Channel) HBA driver for IBM eServer zSeries"); + ("FCP (SCSI over Fibre Channel) HBA driver for IBM System z9 and zSeries"); MODULE_LICENSE("GPL"); module_param(device, charp, 0400); @@ -291,12 +289,11 @@ zfcp_cfdc_dev_ioctl(struct file *file, u goto out; } - sg_list = kmalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL); + sg_list = kzalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL); if (sg_list == NULL) { retval = -ENOMEM; goto out; } - memset(sg_list, 0, sizeof(*sg_list)); if (command != ZFCP_CFDC_IOC) { ZFCP_LOG_INFO("IOC request code 0x%x invalid\n", command); @@ -478,14 +475,13 @@ zfcp_sg_list_alloc(struct zfcp_sg_list * sg_list->count = size >> PAGE_SHIFT; if (size & ~PAGE_MASK) sg_list->count++; - sg_list->sg = kmalloc(sg_list->count * sizeof(struct scatterlist), + sg_list->sg = kcalloc(sg_list->count, sizeof(struct scatterlist), GFP_KERNEL); if (sg_list->sg == NULL) { sg_list->count = 0; retval = -ENOMEM; goto out; } - memset(sg_list->sg, 0, sg_list->count * sizeof(struct scatterlist)); for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) { sg->length = min(size, PAGE_SIZE); @@ -744,7 +740,7 @@ struct zfcp_unit * zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun) { struct zfcp_unit *unit, *tmp_unit; - scsi_lun_t scsi_lun; + unsigned int scsi_lun; int found; /* @@ -758,10 +754,9 @@ zfcp_unit_enqueue(struct zfcp_port *port if (unit) return NULL; - unit = kmalloc(sizeof (struct zfcp_unit), GFP_KERNEL); + unit = kzalloc(sizeof (struct zfcp_unit), GFP_KERNEL); if (!unit) return NULL; - memset(unit, 0, sizeof (struct zfcp_unit)); /* initialise reference count stuff */ atomic_set(&unit->refcount, 0); @@ -929,13 +924,12 @@ zfcp_adapter_enqueue(struct ccw_device * */ /* try to allocate new adapter data structure (zeroed) */ - adapter = kmalloc(sizeof (struct zfcp_adapter), GFP_KERNEL); + adapter = kzalloc(sizeof (struct zfcp_adapter), GFP_KERNEL); if (!adapter) { ZFCP_LOG_INFO("error: allocation of base adapter " "structure failed\n"); goto out; } - memset(adapter, 0, sizeof (struct zfcp_adapter)); ccw_device->handler = NULL; @@ -997,12 +991,6 @@ zfcp_adapter_enqueue(struct ccw_device * /* intitialise SCSI ER timer */ init_timer(&adapter->scsi_er_timer); - /* set FC service class used per default */ - adapter->fc_service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT; - - sprintf(adapter->name, "%s", zfcp_get_busid_by_adapter(adapter)); - ASCEBC(adapter->name, strlen(adapter->name)); - /* mark adapter unusable as long as sysfs registration is not complete */ atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); @@ -1139,10 +1127,9 @@ zfcp_port_enqueue(struct zfcp_adapter *a return NULL; } - port = kmalloc(sizeof (struct zfcp_port), GFP_KERNEL); + port = kzalloc(sizeof (struct zfcp_port), GFP_KERNEL); if (!port) return NULL; - memset(port, 0, sizeof (struct zfcp_port)); /* initialise reference count stuff */ atomic_set(&port->refcount, 0); @@ -1354,18 +1341,19 @@ static void zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter, struct fsf_status_read_buffer *status_buffer) { - logi *els_logi = (logi *) status_buffer->payload; + struct fsf_plogi *els_plogi; struct zfcp_port *port; unsigned long flags; + els_plogi = (struct fsf_plogi *) status_buffer->payload; read_lock_irqsave(&zfcp_data.config_lock, flags); list_for_each_entry(port, &adapter->port_list_head, list) { - if (port->wwpn == (*(wwn_t *) & els_logi->nport_wwn)) + if (port->wwpn == (*(wwn_t *) &els_plogi->serv_param.wwpn)) break; } read_unlock_irqrestore(&zfcp_data.config_lock, flags); - if (!port || (port->wwpn != (*(wwn_t *) & els_logi->nport_wwn))) { + if (!port || (port->wwpn != (*(wwn_t *) &els_plogi->serv_param.wwpn))) { ZFCP_LOG_DEBUG("ignored incoming PLOGI for nonexisting port " "with d_id 0x%08x on adapter %s\n", status_buffer->d_id, @@ -1760,4 +1748,25 @@ zfcp_handle_els_rjt(u32 sq, struct zfcp_ return ret; } +/** + * zfcp_plogi_evaluate - evaluate PLOGI playload and copy important fields + * into zfcp_port structure + * @port: zfcp_port structure + * @plogi: plogi payload + */ +void +zfcp_plogi_evaluate(struct zfcp_port *port, struct fsf_plogi *plogi) +{ + port->maxframe_size = plogi->serv_param.common_serv_param[7] | + ((plogi->serv_param.common_serv_param[6] & 0x0F) << 8); + if (plogi->serv_param.class1_serv_param[0] & 0x80) + port->supported_classes |= FC_COS_CLASS1; + if (plogi->serv_param.class2_serv_param[0] & 0x80) + port->supported_classes |= FC_COS_CLASS2; + if (plogi->serv_param.class3_serv_param[0] & 0x80) + port->supported_classes |= FC_COS_CLASS3; + if (plogi->serv_param.class4_serv_param[0] & 0x80) + port->supported_classes |= FC_COS_CLASS4; +} + #undef ZFCP_LOG_AREA diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 241136d..57d8e4b 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -1,16 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_ccw.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * CCW driver related routines - * - * (C) Copyright IBM Corp. 2003, 2004 - * - * Authors: - * Martin Peschke - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index a5f2ba9..c033145 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -1,12 +1,8 @@ /* + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * linux/drivers/s390/scsi/zfcp_dbf.c - * - * FCP adapter driver for IBM eServer zSeries - * - * Debugging facilities - * - * (C) Copyright IBM Corp. 2005 + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 6eba56c..2df512a 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -1,19 +1,8 @@ /* - * - * linux/drivers/s390/scsi/zfcp_def.h - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann - * Volker Sameske + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -50,7 +39,6 @@ #include #include #include #include -#include "../../fc4/fc.h" #include "zfcp_fsf.h" #include #include @@ -64,7 +52,7 @@ #include /********************* GENERAL DEFINES *********************************/ /* zfcp version number, it consists of major, minor, and patch-level number */ -#define ZFCP_VERSION "4.5.0" +#define ZFCP_VERSION "4.7.0" /** * zfcp_sg_to_address - determine kernel address from struct scatterlist @@ -89,13 +77,9 @@ zfcp_address_to_sg(void *address, struct list->offset = ((unsigned long) address) & (PAGE_SIZE - 1); } -/********************* SCSI SPECIFIC DEFINES *********************************/ +#define REQUEST_LIST_SIZE 128 -/* 32 bit for SCSI ID and LUN as long as the SCSI stack uses this type */ -typedef u32 scsi_id_t; -typedef u32 scsi_lun_t; - -#define ZFCP_ERP_SCSI_LOW_MEM_TIMEOUT (100*HZ) +/********************* SCSI SPECIFIC DEFINES *********************************/ #define ZFCP_SCSI_ER_TIMEOUT (100*HZ) /********************* CIO/QDIO SPECIFIC DEFINES *****************************/ @@ -233,8 +217,9 @@ #define RSP_CODE_TASKMAN_UNSUPP 4 #define RSP_CODE_TASKMAN_FAILED 5 /* see fc-fs */ -#define LS_FAN 0x60000000 -#define LS_RSCN 0x61040000 +#define LS_RSCN 0x61040000 +#define LS_LOGO 0x05000000 +#define LS_PLOGI 0x03000000 struct fcp_rscn_head { u8 command; @@ -263,13 +248,6 @@ #define ZFCP_NO_PORTS_PER_AREA 0x100 #define ZFCP_NO_PORTS_PER_DOMAIN 0x10000 #define ZFCP_NO_PORTS_PER_FABRIC 0x1000000 -struct fcp_fan { - u32 command; - u32 fport_did; - wwn_t fport_wwpn; - wwn_t fport_wwname; -} __attribute__((packed)); - /* see fc-ph */ struct fcp_logo { u32 command; @@ -507,9 +485,6 @@ #define ZFCP_CT_TIMEOUT (3 * R_A_TOV) #define ZFCP_NAME "zfcp" -/* read-only LUN sharing switch initial value */ -#define ZFCP_RO_LUN_SHARING_DEFAULTS 0 - /* independent log areas */ #define ZFCP_LOG_AREA_OTHER 0 #define ZFCP_LOG_AREA_SCSI 1 @@ -608,7 +583,6 @@ #endif * and unit */ #define ZFCP_COMMON_FLAGS 0xfff00000 -#define ZFCP_SPECIFIC_FLAGS 0x000fffff /* common status bits */ #define ZFCP_STATUS_COMMON_REMOVE 0x80000000 @@ -633,11 +607,6 @@ #define ZFCP_STATUS_ADAPTER_ERP_PENDING #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 #define ZFCP_STATUS_ADAPTER_XPORT_OK 0x00000800 -#define ZFCP_STATUS_ADAPTER_SCSI_UP \ - (ZFCP_STATUS_COMMON_UNBLOCKED | \ - ZFCP_STATUS_ADAPTER_REGISTERED) - - /* FC-PH/FC-GS well-known address identifiers for generic services */ #define ZFCP_DID_MANAGEMENT_SERVICE 0xFFFFFA #define ZFCP_DID_TIME_SERVICE 0xFFFFFB @@ -652,7 +621,6 @@ #define ZFCP_STATUS_PORT_PHYS_CLOSING 0 #define ZFCP_STATUS_PORT_NO_WWPN 0x00000008 #define ZFCP_STATUS_PORT_NO_SCSI_ID 0x00000010 #define ZFCP_STATUS_PORT_INVALID_WWPN 0x00000020 -#define ZFCP_STATUS_PORT_ACCESS_DENIED 0x00000040 /* for ports with well known addresses */ #define ZFCP_STATUS_PORT_WKA \ @@ -908,15 +876,12 @@ struct zfcp_adapter { wwn_t peer_wwpn; /* P2P peer WWPN */ u32 peer_d_id; /* P2P peer D_ID */ struct ccw_device *ccw_device; /* S/390 ccw device */ - u8 fc_service_class; u32 hydra_version; /* Hydra version */ u32 fsf_lic_version; u32 adapter_features; /* FCP channel features */ u32 connection_features; /* host connection features */ u32 hardware_version; /* of FCP channel */ struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ - unsigned short scsi_host_no; /* Assigned host number */ - unsigned char name[9]; struct list_head port_list_head; /* remote port list */ struct list_head port_remove_lh; /* head of ports to be removed */ @@ -994,6 +959,8 @@ struct zfcp_port { u32 handle; /* handle assigned by FSF */ struct zfcp_erp_action erp_action; /* pending error recovery */ atomic_t erp_counter; + u32 maxframe_size; + u32 supported_classes; }; /* the struct device sysfs_device must be at the beginning of this structure. @@ -1008,7 +975,7 @@ struct zfcp_unit { refcount drop to zero */ struct zfcp_port *port; /* remote port of unit */ atomic_t status; /* status of this logical unit */ - scsi_lun_t scsi_lun; /* own SCSI LUN */ + unsigned int scsi_lun; /* own SCSI LUN */ fcp_lun_t fcp_lun; /* own FCP_LUN */ u32 handle; /* handle assigned by FSF */ struct scsi_device *device; /* scsi device struct pointer */ @@ -1052,11 +1019,6 @@ struct zfcp_data { struct list_head adapter_list_head; /* head of adapter list */ struct list_head adapter_remove_lh; /* head of adapters to be removed */ - rwlock_t status_read_lock; /* for status read thread */ - struct list_head status_read_receive_head; - struct list_head status_read_send_head; - struct semaphore status_read_sema; - wait_queue_head_t status_read_thread_wqh; u32 adapters; /* # of adapters in list */ rwlock_t config_lock; /* serialises changes to adapter/port/unit @@ -1095,9 +1057,6 @@ struct zfcp_fsf_req_pool_element { /********************** ZFCP SPECIFIC DEFINES ********************************/ -#define ZFCP_FSFREQ_CLEANUP_TIMEOUT HZ/10 - -#define ZFCP_KNOWN 0x00000001 #define ZFCP_REQ_AUTO_CLEANUP 0x00000002 #define ZFCP_WAIT_FOR_SBAL 0x00000004 #define ZFCP_REQ_NO_QTCB 0x00000008 @@ -1105,9 +1064,6 @@ #define ZFCP_REQ_NO_QTCB 0x00000008 #define ZFCP_SET 0x00000100 #define ZFCP_CLEAR 0x00000200 -#define ZFCP_INTERRUPTIBLE 1 -#define ZFCP_UNINTERRUPTIBLE 0 - #ifndef atomic_test_mask #define atomic_test_mask(mask, target) \ ((atomic_read(target) & mask) == mask) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 57cb628..909731b 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -1,18 +1,8 @@ /* - * - * linux/drivers/s390/scsi/zfcp_erp.c - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 - * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. + * + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -177,7 +167,7 @@ zfcp_fsf_scsi_er_timeout_handler(unsigne * initiates adapter recovery which is done * asynchronously * - * returns: 0 - initiated action succesfully + * returns: 0 - initiated action successfully * <0 - failed to initiate action */ int @@ -213,7 +203,7 @@ zfcp_erp_adapter_reopen_internal(struct * purpose: Wrappper for zfcp_erp_adapter_reopen_internal * used to ensure the correct locking * - * returns: 0 - initiated action succesfully + * returns: 0 - initiated action successfully * <0 - failed to initiate action */ int @@ -231,13 +221,6 @@ zfcp_erp_adapter_reopen(struct zfcp_adap return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ int zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask) { @@ -251,13 +234,6 @@ zfcp_erp_adapter_shutdown(struct zfcp_ad return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ int zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask) { @@ -271,13 +247,6 @@ zfcp_erp_port_shutdown(struct zfcp_port return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ int zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask) { @@ -306,20 +275,17 @@ zfcp_erp_adisc(struct zfcp_port *port) int retval = 0; struct timer_list *timer; - send_els = kmalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC); + send_els = kzalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC); if (send_els == NULL) goto nomem; - memset(send_els, 0, sizeof(*send_els)); - send_els->req = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC); + send_els->req = kzalloc(sizeof(struct scatterlist), GFP_ATOMIC); if (send_els->req == NULL) goto nomem; - memset(send_els->req, 0, sizeof(*send_els->req)); - send_els->resp = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC); + send_els->resp = kzalloc(sizeof(struct scatterlist), GFP_ATOMIC); if (send_els->resp == NULL) goto nomem; - memset(send_els->resp, 0, sizeof(*send_els->resp)); address = (void *) get_zeroed_page(GFP_ATOMIC); if (address == NULL) @@ -503,7 +469,7 @@ zfcp_test_link(struct zfcp_port *port) * initiates Forced Reopen recovery which is done * asynchronously * - * returns: 0 - initiated action succesfully + * returns: 0 - initiated action successfully * <0 - failed to initiate action */ static int @@ -543,7 +509,7 @@ zfcp_erp_port_forced_reopen_internal(str * purpose: Wrappper for zfcp_erp_port_forced_reopen_internal * used to ensure the correct locking * - * returns: 0 - initiated action succesfully + * returns: 0 - initiated action successfully * <0 - failed to initiate action */ int @@ -570,7 +536,7 @@ zfcp_erp_port_forced_reopen(struct zfcp_ * initiates Reopen recovery which is done * asynchronously * - * returns: 0 - initiated action succesfully + * returns: 0 - initiated action successfully * <0 - failed to initiate action */ static int @@ -639,7 +605,7 @@ zfcp_erp_port_reopen(struct zfcp_port *p * initiates Reopen recovery which is done * asynchronously * - * returns: 0 - initiated action succesfully + * returns: 0 - initiated action successfully * <0 - failed to initiate action */ static int @@ -812,13 +778,6 @@ zfcp_erp_unit_unblock(struct zfcp_unit * atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status); } -/* - * function: - * - * purpose: - * - * returns: - */ static void zfcp_erp_action_ready(struct zfcp_erp_action *erp_action) { @@ -1356,13 +1315,6 @@ zfcp_erp_strategy_check_action(struct zf return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) { @@ -1538,13 +1490,6 @@ zfcp_erp_strategy_check_target(struct zf return result; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_statechange(int action, u32 status, @@ -1586,13 +1531,6 @@ zfcp_erp_strategy_statechange(int action return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static inline int zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) { @@ -1605,13 +1543,6 @@ zfcp_erp_strategy_statechange_detected(a !(ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status)); } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result) { @@ -1642,13 +1573,6 @@ zfcp_erp_strategy_check_unit(struct zfcp return result; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result) { @@ -1678,13 +1602,6 @@ zfcp_erp_strategy_check_port(struct zfcp return result; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result) { @@ -1764,13 +1681,6 @@ zfcp_erp_strategy_followup_actions(int a return 0; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter) { @@ -1809,12 +1719,6 @@ zfcp_erp_wait(struct zfcp_adapter *adapt return retval; } -/* - * function: zfcp_erp_modify_adapter_status - * - * purpose: - * - */ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, u32 mask, int set_or_clear) @@ -1901,7 +1805,7 @@ zfcp_erp_modify_unit_status(struct zfcp_ * purpose: Wrappper for zfcp_erp_port_reopen_all_internal * used to ensure the correct locking * - * returns: 0 - initiated action succesfully + * returns: 0 - initiated action successfully * <0 - failed to initiate action */ int @@ -1919,13 +1823,6 @@ zfcp_erp_port_reopen_all(struct zfcp_ada return retval; } -/* - * function: - * - * purpose: - * - * returns: FIXME - */ static int zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask) { @@ -2370,13 +2267,6 @@ zfcp_erp_adapter_strategy_open_fsf_xport return ret; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action *erp_action) @@ -2545,13 +2435,6 @@ zfcp_erp_port_strategy(struct zfcp_erp_a return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action) { @@ -2566,15 +2449,6 @@ zfcp_erp_port_strategy_open(struct zfcp_ return retval; } -/* - * function: - * - * purpose: - * - * returns: - * - * FIXME(design): currently only prepared for fabric (nameserver!) - */ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action) { @@ -2690,13 +2564,6 @@ zfcp_erp_port_strategy_open_common(struc return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action) { @@ -2813,13 +2680,6 @@ zfcp_erp_port_forced_strategy_close(stru return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) { @@ -3022,13 +2882,6 @@ zfcp_erp_unit_strategy(struct zfcp_erp_a return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) { @@ -3129,13 +2982,6 @@ zfcp_erp_unit_strategy_open(struct zfcp_ return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static inline void zfcp_erp_timeout_init(struct zfcp_erp_action *erp_action) { @@ -3331,13 +3177,6 @@ zfcp_erp_action_enqueue(int action, return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ static int zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) { @@ -3402,9 +3241,13 @@ zfcp_erp_action_cleanup(int action, stru break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: case ZFCP_ERP_ACTION_REOPEN_PORT: + if (atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, + &port->status)) { + zfcp_port_put(port); + break; + } + if ((result == ZFCP_ERP_SUCCEEDED) - && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, - &port->status) && !port->rport) { struct fc_rport_identifiers ids; ids.node_name = port->wwnn; @@ -3418,12 +3261,30 @@ zfcp_erp_action_cleanup(int action, stru "(adapter %s, wwpn=0x%016Lx)\n", zfcp_get_busid_by_port(port), port->wwpn); - else + else { scsi_flush_work(adapter->scsi_host); + port->rport->maxframe_size = port->maxframe_size; + port->rport->supported_classes = + port->supported_classes; + } + } + if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) { + fc_remote_port_delete(port->rport); + port->rport = NULL; } zfcp_port_put(port); break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: + if (result != ZFCP_ERP_SUCCEEDED) { + struct zfcp_port *port; + list_for_each_entry(port, &adapter->port_list_head, list) + if (port->rport && + !atomic_test_mask(ZFCP_STATUS_PORT_WKA, + &port->status)) { + fc_remote_port_delete(port->rport); + port->rport = NULL; + } + } zfcp_adapter_put(adapter); break; default: @@ -3432,13 +3293,6 @@ zfcp_erp_action_cleanup(int action, stru } -/* - * function: - * - * purpose: - * - * returns: FIXME - */ static int zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) { @@ -3455,13 +3309,6 @@ zfcp_erp_action_dismiss_adapter(struct z return retval; } -/* - * function: - * - * purpose: - * - * returns: FIXME - */ static int zfcp_erp_action_dismiss_port(struct zfcp_port *port) { @@ -3480,13 +3327,6 @@ zfcp_erp_action_dismiss_port(struct zfcp return retval; } -/* - * function: - * - * purpose: - * - * returns: FIXME - */ static int zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) { @@ -3501,13 +3341,6 @@ zfcp_erp_action_dismiss_unit(struct zfcp return retval; } -/* - * function: - * - * purpose: moves erp_action to 'erp running list' - * - * returns: - */ static inline void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) { @@ -3518,13 +3351,6 @@ zfcp_erp_action_to_running(struct zfcp_e list_move(&erp_action->list, &erp_action->adapter->erp_running_head); } -/* - * function: - * - * purpose: moves erp_action to 'erp ready list' - * - * returns: - */ static inline void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) { @@ -3535,11 +3361,6 @@ zfcp_erp_action_to_ready(struct zfcp_erp list_move(&erp_action->list, &erp_action->adapter->erp_ready_head); } -/* - * function: zfcp_erp_port_boxed - * - * purpose: - */ void zfcp_erp_port_boxed(struct zfcp_port *port) { @@ -3556,11 +3377,6 @@ zfcp_erp_port_boxed(struct zfcp_port *po zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED); } -/* - * function: zfcp_erp_unit_boxed - * - * purpose: - */ void zfcp_erp_unit_boxed(struct zfcp_unit *unit) { @@ -3574,11 +3390,6 @@ zfcp_erp_unit_boxed(struct zfcp_unit *un zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED); } -/* - * function: zfcp_erp_port_access_denied - * - * purpose: - */ void zfcp_erp_port_access_denied(struct zfcp_port *port) { @@ -3595,11 +3406,6 @@ zfcp_erp_port_access_denied(struct zfcp_ read_unlock_irqrestore(&zfcp_data.config_lock, flags); } -/* - * function: zfcp_erp_unit_access_denied - * - * purpose: - */ void zfcp_erp_unit_access_denied(struct zfcp_unit *unit) { @@ -3613,11 +3419,6 @@ zfcp_erp_unit_access_denied(struct zfcp_ ZFCP_SET); } -/* - * function: zfcp_erp_adapter_access_changed - * - * purpose: - */ void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter) { @@ -3628,7 +3429,7 @@ zfcp_erp_adapter_access_changed(struct z return; debug_text_event(adapter->erp_dbf, 3, "a_access_recover"); - debug_event(adapter->erp_dbf, 3, &adapter->name, 8); + debug_event(adapter->erp_dbf, 3, zfcp_get_busid_by_adapter(adapter), 8); read_lock_irqsave(&zfcp_data.config_lock, flags); if (adapter->nameserver_port) @@ -3639,11 +3440,6 @@ zfcp_erp_adapter_access_changed(struct z read_unlock_irqrestore(&zfcp_data.config_lock, flags); } -/* - * function: zfcp_erp_port_access_changed - * - * purpose: - */ void zfcp_erp_port_access_changed(struct zfcp_port *port) { @@ -3672,11 +3468,6 @@ zfcp_erp_port_access_changed(struct zfcp zfcp_get_busid_by_adapter(adapter), port->wwpn); } -/* - * function: zfcp_erp_unit_access_changed - * - * purpose: - */ void zfcp_erp_unit_access_changed(struct zfcp_unit *unit) { diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 700f540..d023660 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -1,18 +1,8 @@ /* - * - * linux/drivers/s390/scsi/zfcp_ext.h - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -125,6 +115,7 @@ extern int zfcp_nameserver_enqueue(stru extern int zfcp_ns_gid_pn_request(struct zfcp_erp_action *); extern int zfcp_check_ct_response(struct ct_hdr *); extern int zfcp_handle_els_rjt(u32, struct zfcp_ls_rjt_par *); +extern void zfcp_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); /******************************* SCSI ****************************************/ extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); @@ -141,8 +132,6 @@ extern int zfcp_scsi_command_async(struc struct scsi_cmnd *, struct timer_list *); extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, struct timer_list *); -extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *); -extern void zfcp_set_fc_rport_attrs(struct zfcp_port *); extern struct scsi_transport_template *zfcp_transport_template; extern struct fc_function_template zfcp_transport_functions; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 662ec57..6335f92 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1,19 +1,8 @@ /* + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * linux/drivers/s390/scsi/zfcp_fsf.c - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 - * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann - * Volker Sameske + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -877,6 +866,7 @@ zfcp_fsf_status_read_handler(struct zfcp struct zfcp_adapter *adapter = fsf_req->adapter; struct fsf_status_read_buffer *status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; + struct fsf_bit_error_payload *fsf_bit_error; if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { zfcp_hba_dbf_event_fsf_unsol("dism", adapter, status_buffer); @@ -903,10 +893,37 @@ zfcp_fsf_status_read_handler(struct zfcp break; case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: - ZFCP_LOG_NORMAL("Bit error threshold data received:\n"); - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, - (char *) status_buffer, - sizeof (struct fsf_status_read_buffer)); + fsf_bit_error = (struct fsf_bit_error_payload *) + status_buffer->payload; + ZFCP_LOG_NORMAL("Warning: bit error threshold data " + "received (adapter %s, " + "link failures = %i, loss of sync errors = %i, " + "loss of signal errors = %i, " + "primitive sequence errors = %i, " + "invalid transmission word errors = %i, " + "CRC errors = %i)\n", + zfcp_get_busid_by_adapter(adapter), + fsf_bit_error->link_failure_error_count, + fsf_bit_error->loss_of_sync_error_count, + fsf_bit_error->loss_of_signal_error_count, + fsf_bit_error->primitive_sequence_error_count, + fsf_bit_error->invalid_transmission_word_error_count, + fsf_bit_error->crc_error_count); + ZFCP_LOG_INFO("Additional bit error threshold data " + "(adapter %s, " + "primitive sequence event time-outs = %i, " + "elastic buffer overrun errors = %i, " + "advertised receive buffer-to-buffer credit = %i, " + "current receice buffer-to-buffer credit = %i, " + "advertised transmit buffer-to-buffer credit = %i, " + "current transmit buffer-to-buffer credit = %i)\n", + zfcp_get_busid_by_adapter(adapter), + fsf_bit_error->primitive_sequence_event_timeout_count, + fsf_bit_error->elastic_buffer_overrun_error_count, + fsf_bit_error->advertised_receive_b2b_credit, + fsf_bit_error->current_receive_b2b_credit, + fsf_bit_error->advertised_transmit_b2b_credit, + fsf_bit_error->current_transmit_b2b_credit); break; case FSF_STATUS_READ_LINK_DOWN: @@ -1427,7 +1444,8 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct /* settings in QTCB */ fsf_req->qtcb->header.port_handle = port->handle; - fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; + fsf_req->qtcb->bottom.support.service_class = + ZFCP_FC_SERVICE_CLASS_DEFAULT; fsf_req->qtcb->bottom.support.timeout = ct->timeout; fsf_req->data = (unsigned long) ct; @@ -1496,18 +1514,10 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: - if (adapter->fc_service_class <= 3) { - ZFCP_LOG_INFO("error: adapter %s does not support fc " - "class %d.\n", - zfcp_get_busid_by_port(port), - adapter->fc_service_class); - } else { - ZFCP_LOG_INFO("bug: The fibre channel class at the " - "adapter %s is invalid. " - "(debug info %d)\n", - zfcp_get_busid_by_port(port), - adapter->fc_service_class); - } + ZFCP_LOG_INFO("error: adapter %s does not support fc " + "class %d.\n", + zfcp_get_busid_by_port(port), + ZFCP_FC_SERVICE_CLASS_DEFAULT); /* stop operation for this adapter */ debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); zfcp_erp_adapter_shutdown(adapter, 0); @@ -1730,7 +1740,8 @@ zfcp_fsf_send_els(struct zfcp_send_els * /* settings in QTCB */ fsf_req->qtcb->bottom.support.d_id = d_id; - fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; + fsf_req->qtcb->bottom.support.service_class = + ZFCP_FC_SERVICE_CLASS_DEFAULT; fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; fsf_req->data = (unsigned long) els; @@ -1800,18 +1811,10 @@ static int zfcp_fsf_send_els_handler(str break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: - if (adapter->fc_service_class <= 3) { - ZFCP_LOG_INFO("error: adapter %s does " - "not support fibrechannel class %d.\n", - zfcp_get_busid_by_adapter(adapter), - adapter->fc_service_class); - } else { - ZFCP_LOG_INFO("bug: The fibrechannel class at " - "adapter %s is invalid. " - "(debug info %d)\n", - zfcp_get_busid_by_adapter(adapter), - adapter->fc_service_class); - } + ZFCP_LOG_INFO("error: adapter %s does not support fc " + "class %d.\n", + zfcp_get_busid_by_adapter(adapter), + ZFCP_FC_SERVICE_CLASS_DEFAULT); /* stop operation for this adapter */ debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); zfcp_erp_adapter_shutdown(adapter, 0); @@ -1940,14 +1943,6 @@ skip_fsfstatus: return retval; } -/* - * function: - * - * purpose: - * - * returns: address of initiated FSF request - * NULL - request could not be initiated - */ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) { @@ -2565,8 +2560,7 @@ zfcp_fsf_open_port_handler(struct zfcp_f if (!atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, &port->status)) { if (fsf_req->qtcb->bottom.support.els1_length < - ((((unsigned long) &plogi->serv_param.wwpn) - - ((unsigned long) plogi)) + sizeof (u64))) { + sizeof (struct fsf_plogi)) { ZFCP_LOG_INFO( "warning: insufficient length of " "PLOGI payload (%i)\n", @@ -2585,8 +2579,10 @@ zfcp_fsf_open_port_handler(struct zfcp_f atomic_clear_mask( ZFCP_STATUS_PORT_DID_DID, &port->status); - } else + } else { port->wwnn = plogi->serv_param.wwnn; + zfcp_plogi_evaluate(port, plogi); + } } } break; @@ -2993,8 +2989,8 @@ zfcp_fsf_open_unit(struct zfcp_erp_actio erp_action->fsf_req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun; if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE)) - erp_action->fsf_req->qtcb->bottom.support.option = - FSF_OPEN_LUN_SUPPRESS_BOXING; + erp_action->fsf_req->qtcb->bottom.support.option = + FSF_OPEN_LUN_SUPPRESS_BOXING; atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); erp_action->fsf_req->data = (unsigned long) erp_action->unit; erp_action->fsf_req->erp_action = erp_action; @@ -3569,7 +3565,7 @@ zfcp_fsf_send_fcp_command_task(struct zf } /* set FC service class in QTCB (3 per default) */ - fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class; + fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT; /* set FCP_LUN in FCP_CMND IU in QTCB */ fcp_cmnd_iu->fcp_lun = unit->fcp_lun; @@ -3667,18 +3663,6 @@ zfcp_fsf_send_fcp_command_task(struct zf return retval; } -/* - * function: zfcp_fsf_send_fcp_command_task_management - * - * purpose: - * - * returns: - * - * FIXME(design): should be watched by a timeout!!! - * FIXME(design) shouldn't this be modified to return an int - * also...don't know how though - * - */ struct zfcp_fsf_req * zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter, struct zfcp_unit *unit, @@ -3720,7 +3704,7 @@ zfcp_fsf_send_fcp_command_task_managemen fsf_req->qtcb->header.lun_handle = unit->handle; fsf_req->qtcb->header.port_handle = unit->port->handle; fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; - fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class; + fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT; fsf_req->qtcb->bottom.io.fcp_cmnd_length = sizeof (struct fcp_cmnd_iu) + sizeof (fcp_dl_t); @@ -3843,18 +3827,10 @@ zfcp_fsf_send_fcp_command_handler(struct break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: - if (fsf_req->adapter->fc_service_class <= 3) { - ZFCP_LOG_NORMAL("error: The adapter %s does " - "not support fibrechannel class %d.\n", - zfcp_get_busid_by_unit(unit), - fsf_req->adapter->fc_service_class); - } else { - ZFCP_LOG_NORMAL("bug: The fibrechannel class at " - "adapter %s is invalid. " - "(debug info %d)\n", - zfcp_get_busid_by_unit(unit), - fsf_req->adapter->fc_service_class); - } + ZFCP_LOG_INFO("error: adapter %s does not support fc " + "class %d.\n", + zfcp_get_busid_by_unit(unit), + ZFCP_FC_SERVICE_CLASS_DEFAULT); /* stop operation for this adapter */ debug_text_exception(fsf_req->adapter->erp_dbf, 0, "fsf_s_class_nsup"); diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index e734415..7118661 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -1,19 +1,8 @@ /* - * - * linux/drivers/s390/scsi/zfcp_fsf.h - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann - * Volker Sameske + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,8 +22,7 @@ #ifndef FSF_H #define FSF_H -#define FSF_QTCB_VERSION1 0x00000001 -#define FSF_QTCB_CURRENT_VERSION FSF_QTCB_VERSION1 +#define FSF_QTCB_CURRENT_VERSION 0x00000001 /* FSF commands */ #define FSF_QTCB_FCP_CMND 0x00000001 @@ -64,7 +52,7 @@ #define FSF_CFDC_OPTION_FORCE 0x000000 #define FSF_CFDC_OPTION_FULL_ACCESS 0x00000002 #define FSF_CFDC_OPTION_RESTRICTED_ACCESS 0x00000004 -/* FSF protocol stati */ +/* FSF protocol states */ #define FSF_PROT_GOOD 0x00000001 #define FSF_PROT_QTCB_VERSION_ERROR 0x00000010 #define FSF_PROT_SEQ_NUMB_ERROR 0x00000020 @@ -76,7 +64,7 @@ #define FSF_PROT_LINK_DOWN #define FSF_PROT_REEST_QUEUE 0x00000800 #define FSF_PROT_ERROR_STATE 0x01000000 -/* FSF stati */ +/* FSF states */ #define FSF_GOOD 0x00000000 #define FSF_PORT_ALREADY_OPEN 0x00000001 #define FSF_LUN_ALREADY_OPEN 0x00000002 @@ -269,20 +257,6 @@ #define FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED #define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000 #define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000 -struct fsf_queue_designator; -struct fsf_status_read_buffer; -struct fsf_port_closed_payload; -struct fsf_bit_error_payload; -union fsf_prot_status_qual; -struct fsf_qual_version_error; -struct fsf_qual_sequence_error; -struct fsf_qtcb_prefix; -struct fsf_qtcb_header; -struct fsf_qtcb_bottom_config; -struct fsf_qtcb_bottom_support; -struct fsf_qtcb_bottom_io; -union fsf_qtcb_bottom; - struct fsf_queue_designator { u8 cssid; u8 chpid; diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 1c32751..345a191 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -1,18 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_qdio.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * QDIO related routines - * - * (C) Copyright IBM Corp. 2002, 2004 - * - * Authors: - * Martin Peschke - * Raimund Schroeder - * Wolfgang Taphorn - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -178,7 +168,8 @@ zfcp_qdio_allocate(struct zfcp_adapter * init_data->cdev = adapter->ccw_device; init_data->q_format = QDIO_SCSI_QFMT; - memcpy(init_data->adapter_name, &adapter->name, 8); + memcpy(init_data->adapter_name, zfcp_get_busid_by_adapter(adapter), 8); + ASCEBC(init_data->adapter_name, 8); init_data->qib_param_field_format = 0; init_data->qib_param_field = NULL; init_data->input_slib_elements = NULL; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 9e6d07d..46e14f2 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -1,18 +1,8 @@ /* - * - * linux/drivers/s390/scsi/zfcp_scsi.c - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,8 +35,8 @@ static int zfcp_scsi_eh_host_reset_handl static int zfcp_task_management_function(struct zfcp_unit *, u8, struct scsi_cmnd *); -static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, - scsi_lun_t); +static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, + unsigned int, unsigned int); static struct device_attribute *zfcp_sysfs_sdev_attrs[]; @@ -161,14 +151,6 @@ set_driver_byte(u32 * result, char statu set_byte(result, status, 3); } -/* - * function: zfcp_scsi_slave_alloc - * - * purpose: - * - * returns: - */ - static int zfcp_scsi_slave_alloc(struct scsi_device *sdp) { @@ -195,14 +177,6 @@ zfcp_scsi_slave_alloc(struct scsi_device return retval; } -/* - * function: zfcp_scsi_slave_destroy - * - * purpose: - * - * returns: - */ - static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) { @@ -374,18 +348,9 @@ zfcp_scsi_queuecommand(struct scsi_cmnd return zfcp_scsi_command_async(adapter, unit, scpnt, NULL); } -/* - * function: zfcp_unit_lookup - * - * purpose: - * - * returns: - * - * context: - */ static struct zfcp_unit * -zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id, - scsi_lun_t lun) +zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id, + unsigned int lun) { struct zfcp_port *port; struct zfcp_unit *unit, *retval = NULL; @@ -491,13 +456,6 @@ zfcp_scsi_eh_abort_handler(struct scsi_c return retval; } -/* - * function: zfcp_scsi_eh_device_reset_handler - * - * purpose: - * - * returns: - */ int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) { @@ -625,13 +583,6 @@ zfcp_scsi_eh_host_reset_handler(struct s return SUCCESS; } -/* - * function: - * - * purpose: - * - * returns: - */ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) { @@ -657,10 +608,6 @@ zfcp_adapter_scsi_register(struct zfcp_a adapter->scsi_host->unique_id = unique_id++; /* FIXME */ adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH; adapter->scsi_host->transportt = zfcp_transport_template; - /* - * Reverse mapping of the host number to avoid race condition - */ - adapter->scsi_host_no = adapter->scsi_host->host_no; /* * save a pointer to our own adapter data structure within @@ -678,13 +625,6 @@ zfcp_adapter_scsi_register(struct zfcp_a return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) { @@ -703,7 +643,6 @@ zfcp_adapter_scsi_unregister(struct zfcp scsi_remove_host(shost); scsi_host_put(shost); adapter->scsi_host = NULL; - adapter->scsi_host_no = 0; atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status); return; @@ -817,10 +756,9 @@ zfcp_get_fc_host_stats(struct Scsi_Host if (!fc_stats) return NULL; - data = kmalloc(sizeof(*data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return NULL; - memset(data, 0, sizeof(*data)); ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); if (ret) { @@ -848,10 +786,9 @@ zfcp_reset_fc_host_stats(struct Scsi_Hos int ret; adapter = (struct zfcp_adapter *)shost->hostdata[0]; - data = kmalloc(sizeof(*data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return; - memset(data, 0, sizeof(*data)); ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); if (ret == 0) { @@ -863,11 +800,18 @@ zfcp_reset_fc_host_stats(struct Scsi_Hos } } +static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout) +{ + rport->dev_loss_tmo = timeout; +} + struct fc_function_template zfcp_transport_functions = { .show_starget_port_id = 1, .show_starget_port_name = 1, .show_starget_node_name = 1, .show_rport_supported_classes = 1, + .show_rport_maxframe_size = 1, + .show_rport_dev_loss_tmo = 1, .show_host_node_name = 1, .show_host_port_name = 1, .show_host_permanent_port_name = 1, @@ -877,6 +821,7 @@ struct fc_function_template zfcp_transpo .show_host_serial_number = 1, .get_fc_host_stats = zfcp_get_fc_host_stats, .reset_fc_host_stats = zfcp_reset_fc_host_stats, + .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo, /* no functions registered for following dynamic attributes but directly set by LLDD */ .show_host_port_type = 1, diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index b29ac25..705c6d4 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c @@ -1,16 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_sysfs_adapter.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * sysfs adapter related routines - * - * (C) Copyright IBM Corp. 2003, 2004 - * - * Authors: - * Martin Peschke - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c index 6622d55..005e62f 100644 --- a/drivers/s390/scsi/zfcp_sysfs_driver.c +++ b/drivers/s390/scsi/zfcp_sysfs_driver.c @@ -1,16 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_sysfs_driver.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * sysfs driver related routines - * - * (C) Copyright IBM Corp. 2003, 2004 - * - * Authors: - * Martin Peschke - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c index f401d42..1320c05 100644 --- a/drivers/s390/scsi/zfcp_sysfs_port.c +++ b/drivers/s390/scsi/zfcp_sysfs_port.c @@ -1,17 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_sysfs_port.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * sysfs port related routines - * - * (C) Copyright IBM Corp. 2003, 2004 - * - * Authors: - * Martin Peschke - * Heiko Carstens - * Andreas Herrmann - * Volker Sameske + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c index ad5dfb8..81a4841 100644 --- a/drivers/s390/scsi/zfcp_sysfs_unit.c +++ b/drivers/s390/scsi/zfcp_sysfs_unit.c @@ -1,17 +1,8 @@ /* - * linux/drivers/s390/scsi/zfcp_sysfs_unit.c + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * FCP adapter driver for IBM eServer zSeries - * - * sysfs unit related routines - * - * (C) Copyright IBM Corp. 2003, 2004 - * - * Authors: - * Martin Peschke - * Heiko Carstens - * Andreas Herrmann - * Volker Sameske + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index d89f83f..1cc706e 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c @@ -575,9 +575,9 @@ int bbc_envctrl_init(void) int devidx = 0; while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { - if (!strcmp(echild->prom_name, "temperature")) + if (!strcmp(echild->prom_node->name, "temperature")) attach_one_temp(echild, temp_index++); - if (!strcmp(echild->prom_name, "fan-control")) + if (!strcmp(echild->prom_node->name, "fan-control")) attach_one_fan(echild, fan_index++); } if (temp_index != 0 && fan_index != 0) { diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 3e156e0..7363437 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -423,7 +423,7 @@ static int __init bbc_present(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "bbc")) + if (!strcmp(edev->prom_node->name, "bbc")) return 1; } } @@ -446,7 +446,7 @@ static int __init bbc_i2c_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "i2c")) { + if (!strcmp(edev->prom_node->name, "i2c")) { if (!attach_one_i2c(edev, index)) index++; } diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c index fd2cc77..21737b7 100644 --- a/drivers/sbus/char/cpwatchdog.c +++ b/drivers/sbus/char/cpwatchdog.c @@ -304,8 +304,8 @@ static int wd_open(struct inode *inode, SA_SHIRQ, WD_OBPNAME, (void *)wd_dev.regs)) { - printk("%s: Cannot register IRQ %s\n", - WD_OBPNAME, __irq_itoa(wd_dev.irq)); + printk("%s: Cannot register IRQ %d\n", + WD_OBPNAME, wd_dev.irq); return(-EBUSY); } wd_dev.initialized = 1; @@ -755,7 +755,7 @@ static int __init wd_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, WD_OBPNAME)) + if (!strcmp(edev->ofdev.node->name, WD_OBPNAME)) goto ebus_done; } } diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index c3a51d1..d92bc88 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -184,7 +184,7 @@ static int __init d7s_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, D7S_OBPNAME)) + if (!strcmp(edev->prom_node->name, D7S_OBPNAME)) goto ebus_done; } } diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 19e8edd..cf97e9e 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -768,16 +768,14 @@ static void envctrl_set_mon(struct i2c_c * decoding tables, monitor type, optional properties. * Return: None. */ -static void envctrl_init_adc(struct i2c_child_t *pchild, int node) +static void envctrl_init_adc(struct i2c_child_t *pchild, struct device_node *dp) { - char chnls_desc[CHANNEL_DESC_SZ]; int i = 0, len; - char *pos = chnls_desc; + char *pos; + unsigned int *pval; /* Firmware describe channels into a stream separated by a '\0'. */ - len = prom_getproperty(node, "channels-description", chnls_desc, - CHANNEL_DESC_SZ); - chnls_desc[CHANNEL_DESC_SZ - 1] = '\0'; + pos = of_get_property(dp, "channels-description", &len); while (len > 0) { int l = strlen(pos) + 1; @@ -787,10 +785,13 @@ static void envctrl_init_adc(struct i2c_ } /* Get optional properties. */ - len = prom_getproperty(node, "warning-temp", (char *)&warning_temperature, - sizeof(warning_temperature)); - len = prom_getproperty(node, "shutdown-temp", (char *)&shutdown_temperature, - sizeof(shutdown_temperature)); + pval = of_get_property(dp, "warning-temp", NULL); + if (pval) + warning_temperature = *pval; + + pval = of_get_property(dp, "shutdown-temp", NULL); + if (pval) + shutdown_temperature = *pval; } /* Function Description: Initialize child device monitoring fan status. @@ -864,21 +865,18 @@ static void envctrl_init_voltage_status( static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, struct i2c_child_t *pchild) { - int node, len, i, tbls_size = 0; - - node = edev_child->prom_node; + int len, i, tbls_size = 0; + struct device_node *dp = edev_child->prom_node; + void *pval; /* Get device address. */ - len = prom_getproperty(node, "reg", - (char *) &(pchild->addr), - sizeof(pchild->addr)); + pval = of_get_property(dp, "reg", &len); + memcpy(&pchild->addr, pval, len); /* Get tables property. Read firmware temperature tables. */ - len = prom_getproperty(node, "translation", - (char *) pchild->tblprop_array, - (PCF8584_MAX_CHANNELS * - sizeof(struct pcf8584_tblprop))); - if (len > 0) { + pval = of_get_property(dp, "translation", &len); + if (pval && len > 0) { + memcpy(pchild->tblprop_array, pval, len); pchild->total_tbls = len / sizeof(struct pcf8584_tblprop); for (i = 0; i < pchild->total_tbls; i++) { if ((pchild->tblprop_array[i].size + pchild->tblprop_array[i].offset) > tbls_size) { @@ -891,12 +889,12 @@ static void envctrl_init_i2c_child(struc printk("envctrl: Failed to allocate table.\n"); return; } - len = prom_getproperty(node, "tables", - (char *) pchild->tables, tbls_size); - if (len <= 0) { + pval = of_get_property(dp, "tables", &len); + if (!pval || len <= 0) { printk("envctrl: Failed to get table.\n"); return; } + memcpy(pchild->tables, pval, len); } /* SPARCengine ASM Reference Manual (ref. SMI doc 805-7581-04) @@ -907,12 +905,11 @@ static void envctrl_init_i2c_child(struc * 'NULL' monitor type. */ if (ENVCTRL_CPCI_IGNORED_NODE == pchild->addr) { + struct device_node *root_node; int len; - char prop[56]; - len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop)); - if (0 < len && (0 == strncmp(prop, "SUNW,UltraSPARC-IIi-cEngine", len))) - { + root_node = of_find_node_by_path("/"); + if (!strcmp(root_node->name, "SUNW,UltraSPARC-IIi-cEngine")) { for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) { pchild->mon_type[len] = ENVCTRL_NOMON; } @@ -921,16 +918,14 @@ static void envctrl_init_i2c_child(struc } /* Get the monitor channels. */ - len = prom_getproperty(node, "channels-in-use", - (char *) pchild->chnl_array, - (PCF8584_MAX_CHANNELS * - sizeof(struct pcf8584_channel))); + pval = of_get_property(dp, "channels-in-use", &len); + memcpy(pchild->chnl_array, pval, len); pchild->total_chnls = len / sizeof(struct pcf8584_channel); for (i = 0; i < pchild->total_chnls; i++) { switch (pchild->chnl_array[i].type) { case PCF8584_TEMP_TYPE: - envctrl_init_adc(pchild, node); + envctrl_init_adc(pchild, dp); break; case PCF8584_GLOBALADDR_TYPE: @@ -945,7 +940,7 @@ static void envctrl_init_i2c_child(struc case PCF8584_VOLTAGE_TYPE: if (pchild->i2ctype == I2C_ADC) { - envctrl_init_adc(pchild,node); + envctrl_init_adc(pchild,dp); } else { envctrl_init_voltage_status(pchild); } @@ -1046,7 +1041,7 @@ static int __init envctrl_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "bbc")) { + if (!strcmp(edev->prom_node->name, "bbc")) { /* If we find a boot-bus controller node, * then this envctrl driver is not for us. */ @@ -1060,14 +1055,14 @@ static int __init envctrl_init(void) */ for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "i2c")) { + if (!strcmp(edev->prom_node->name, "i2c")) { i2c = ioremap(edev->resource[0].start, 0x2); for_each_edevchild(edev, edev_child) { - if (!strcmp("gpio", edev_child->prom_name)) { + if (!strcmp("gpio", edev_child->prom_node->name)) { i2c_childlist[i].i2ctype = I2C_GPIO; envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); } - if (!strcmp("adc", edev_child->prom_name)) { + if (!strcmp("adc", edev_child->prom_node->name)) { i2c_childlist[i].i2ctype = I2C_ADC; envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); } diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 2beb3dd..31b8a5f 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -71,7 +71,6 @@ flash_mmap(struct file *file, struct vm_ if (vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)) > size) size = vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)); - vma->vm_flags |= (VM_SHM | VM_LOCKED); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); if (io_remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot)) @@ -192,9 +191,11 @@ #endif } if (!sdev) { #ifdef CONFIG_PCI + struct linux_prom_registers *ebus_regs; + for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "flashprom")) + if (!strcmp(edev->prom_node->name, "flashprom")) goto ebus_done; } } @@ -202,23 +203,23 @@ #ifdef CONFIG_PCI if (!edev) return -ENODEV; - len = prom_getproperty(edev->prom_node, "reg", (void *)regs, sizeof(regs)); - if ((len % sizeof(regs[0])) != 0) { + ebus_regs = of_get_property(edev->prom_node, "reg", &len); + if (!ebus_regs || (len % sizeof(regs[0])) != 0) { printk("flash: Strange reg property size %d\n", len); return -ENODEV; } - nregs = len / sizeof(regs[0]); + nregs = len / sizeof(ebus_regs[0]); flash.read_base = edev->resource[0].start; - flash.read_size = regs[0].reg_size; + flash.read_size = ebus_regs[0].reg_size; if (nregs == 1) { flash.write_base = edev->resource[0].start; - flash.write_size = regs[0].reg_size; + flash.write_size = ebus_regs[0].reg_size; } else if (nregs == 2) { flash.write_base = edev->resource[1].start; - flash.write_size = regs[1].reg_size; + flash.write_size = ebus_regs[1].reg_size; } else { printk("flash: Strange number of regs %d\n", nregs); return -ENODEV; diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 239e108..d7e4bb4 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -29,8 +29,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define PROMLIB_INTERNAL - #include #include #include @@ -39,10 +37,10 @@ #include #include #include #include -#include #include #include #include +#include #include #include #include @@ -51,15 +49,20 @@ #include #include #endif +MODULE_AUTHOR("Thomas K. Dyas (tdyas@noc.rutgers.edu) and Eddie C. Dost (ecd@skynet.be)"); +MODULE_DESCRIPTION("OPENPROM Configuration Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.0"); + /* Private data kept by the driver for each descriptor. */ typedef struct openprom_private_data { - int current_node; /* Current node for SunOS ioctls. */ - int lastnode; /* Last valid node used by BSD ioctls. */ + struct device_node *current_node; /* Current node for SunOS ioctls. */ + struct device_node *lastnode; /* Last valid node used by BSD ioctls. */ } DATA; /* ID of the PROM node containing all of the EEPROM options. */ -static int options_node = 0; +static struct device_node *options_node; /* * Copy an openpromio structure into kernel space from user space. @@ -87,9 +90,8 @@ static int copyin(struct openpromio __us if (bufsize > OPROMMAXPARAM) bufsize = OPROMMAXPARAM; - if (!(*opp_p = kmalloc(sizeof(int) + bufsize + 1, GFP_KERNEL))) + if (!(*opp_p = kzalloc(sizeof(int) + bufsize + 1, GFP_KERNEL))) return -ENOMEM; - memset(*opp_p, 0, sizeof(int) + bufsize + 1); if (copy_from_user(&(*opp_p)->oprom_array, &info->oprom_array, bufsize)) { @@ -107,10 +109,9 @@ static int getstrings(struct openpromio if (!info || !opp_p) return -EFAULT; - if (!(*opp_p = kmalloc(sizeof(int) + OPROMMAXPARAM + 1, GFP_KERNEL))) + if (!(*opp_p = kzalloc(sizeof(int) + OPROMMAXPARAM + 1, GFP_KERNEL))) return -ENOMEM; - memset(*opp_p, 0, sizeof(int) + OPROMMAXPARAM + 1); (*opp_p)->oprom_size = 0; n = bufsize = 0; @@ -140,16 +141,164 @@ static int copyout(void __user *info, st return 0; } +static int opromgetprop(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize) +{ + void *pval; + int len; + + pval = of_get_property(dp, op->oprom_array, &len); + if (!pval || len <= 0 || len > bufsize) + return copyout(argp, op, sizeof(int)); + + memcpy(op->oprom_array, pval, len); + op->oprom_array[len] = '\0'; + op->oprom_size = len; + + return copyout(argp, op, sizeof(int) + bufsize); +} + +static int opromnxtprop(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize) +{ + struct property *prop; + int len; + + if (op->oprom_array[0] == '\0') { + prop = dp->properties; + if (!prop) + return copyout(argp, op, sizeof(int)); + len = strlen(prop->name); + } else { + prop = of_find_property(dp, op->oprom_array, NULL); + + if (!prop || + !prop->next || + (len = strlen(prop->next->name)) + 1 > bufsize) + return copyout(argp, op, sizeof(int)); + + prop = prop->next; + } + + memcpy(op->oprom_array, prop->name, len); + op->oprom_array[len] = '\0'; + op->oprom_size = ++len; + + return copyout(argp, op, sizeof(int) + bufsize); +} + +static int opromsetopt(struct device_node *dp, struct openpromio *op, int bufsize) +{ + char *buf = op->oprom_array + strlen(op->oprom_array) + 1; + int len = op->oprom_array + bufsize - buf; + + return of_set_property(options_node, op->oprom_array, buf, len); +} + +static int opromnext(void __user *argp, unsigned int cmd, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data) +{ + phandle ph; + + BUILD_BUG_ON(sizeof(phandle) != sizeof(int)); + + if (bufsize < sizeof(phandle)) + return -EINVAL; + + ph = *((int *) op->oprom_array); + if (ph) { + dp = of_find_node_by_phandle(ph); + if (!dp) + return -EINVAL; + + switch (cmd) { + case OPROMNEXT: + dp = dp->sibling; + break; + + case OPROMCHILD: + dp = dp->child; + break; + + case OPROMSETCUR: + default: + break; + }; + } else { + /* Sibling of node zero is the root node. */ + if (cmd != OPROMNEXT) + return -EINVAL; + + dp = of_find_node_by_path("/"); + } + + ph = 0; + if (dp) + ph = dp->node; + + data->current_node = dp; + *((int *) op->oprom_array) = ph; + op->oprom_size = sizeof(phandle); + + return copyout(argp, op, bufsize + sizeof(int)); +} + +static int oprompci2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data) +{ + int err = -EINVAL; + + if (bufsize >= 2*sizeof(int)) { +#ifdef CONFIG_PCI + struct pci_dev *pdev; + struct pcidev_cookie *pcp; + pdev = pci_find_slot (((int *) op->oprom_array)[0], + ((int *) op->oprom_array)[1]); + + pcp = pdev->sysdata; + if (pcp != NULL) { + dp = pcp->prom_node; + data->current_node = dp; + *((int *)op->oprom_array) = dp->node; + op->oprom_size = sizeof(int); + err = copyout(argp, op, bufsize + sizeof(int)); + } +#endif + } + + return err; +} + +static int oprompath2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data) +{ + dp = of_find_node_by_path(op->oprom_array); + data->current_node = dp; + *((int *)op->oprom_array) = dp->node; + op->oprom_size = sizeof(int); + + return copyout(argp, op, bufsize + sizeof(int)); +} + +static int opromgetbootargs(void __user *argp, struct openpromio *op, int bufsize) +{ + char *buf = saved_command_line; + int len = strlen(buf); + + if (len > bufsize) + return -EINVAL; + + strcpy(op->oprom_array, buf); + op->oprom_size = len; + + return copyout(argp, op, bufsize + sizeof(int)); +} + /* * SunOS and Solaris /dev/openprom ioctl calls. */ static int openprom_sunos_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg, int node) + unsigned int cmd, unsigned long arg, + struct device_node *dp) { - DATA *data = (DATA *) file->private_data; - char buffer[OPROMMAXPARAM+1], *buf; + DATA *data = file->private_data; struct openpromio *opp; - int bufsize, len, error = 0; + int bufsize, error = 0; static int cnt; void __user *argp = (void __user *)arg; @@ -164,119 +313,35 @@ static int openprom_sunos_ioctl(struct i switch (cmd) { case OPROMGETOPT: case OPROMGETPROP: - len = prom_getproplen(node, opp->oprom_array); - - if (len <= 0 || len > bufsize) { - error = copyout(argp, opp, sizeof(int)); - break; - } - - len = prom_getproperty(node, opp->oprom_array, buffer, bufsize); - - memcpy(opp->oprom_array, buffer, len); - opp->oprom_array[len] = '\0'; - opp->oprom_size = len; - - error = copyout(argp, opp, sizeof(int) + bufsize); + error = opromgetprop(argp, dp, opp, bufsize); break; case OPROMNXTOPT: case OPROMNXTPROP: - buf = prom_nextprop(node, opp->oprom_array, buffer); - - len = strlen(buf); - if (len == 0 || len + 1 > bufsize) { - error = copyout(argp, opp, sizeof(int)); - break; - } - - memcpy(opp->oprom_array, buf, len); - opp->oprom_array[len] = '\0'; - opp->oprom_size = ++len; - - error = copyout(argp, opp, sizeof(int) + bufsize); + error = opromnxtprop(argp, dp, opp, bufsize); break; case OPROMSETOPT: case OPROMSETOPT2: - buf = opp->oprom_array + strlen(opp->oprom_array) + 1; - len = opp->oprom_array + bufsize - buf; - - error = prom_setprop(options_node, opp->oprom_array, - buf, len); - - if (error < 0) - error = -EINVAL; + error = opromsetopt(dp, opp, bufsize); break; case OPROMNEXT: case OPROMCHILD: case OPROMSETCUR: - if (bufsize < sizeof(int)) { - error = -EINVAL; - break; - } - - node = *((int *) opp->oprom_array); - - switch (cmd) { - case OPROMNEXT: node = __prom_getsibling(node); break; - case OPROMCHILD: node = __prom_getchild(node); break; - case OPROMSETCUR: break; - } - - data->current_node = node; - *((int *)opp->oprom_array) = node; - opp->oprom_size = sizeof(int); - - error = copyout(argp, opp, bufsize + sizeof(int)); + error = opromnext(argp, cmd, dp, opp, bufsize, data); break; case OPROMPCI2NODE: - error = -EINVAL; - - if (bufsize >= 2*sizeof(int)) { -#ifdef CONFIG_PCI - struct pci_dev *pdev; - struct pcidev_cookie *pcp; - pdev = pci_find_slot (((int *) opp->oprom_array)[0], - ((int *) opp->oprom_array)[1]); - - pcp = pdev->sysdata; - if (pcp != NULL && pcp->prom_node != -1 && pcp->prom_node) { - node = pcp->prom_node; - data->current_node = node; - *((int *)opp->oprom_array) = node; - opp->oprom_size = sizeof(int); - error = copyout(argp, opp, bufsize + sizeof(int)); - } -#endif - } + error = oprompci2node(argp, dp, opp, bufsize, data); break; case OPROMPATH2NODE: - node = prom_finddevice(opp->oprom_array); - data->current_node = node; - *((int *)opp->oprom_array) = node; - opp->oprom_size = sizeof(int); - - error = copyout(argp, opp, bufsize + sizeof(int)); + error = oprompath2node(argp, dp, opp, bufsize, data); break; case OPROMGETBOOTARGS: - buf = saved_command_line; - - len = strlen(buf); - - if (len > bufsize) { - error = -EINVAL; - break; - } - - strcpy(opp->oprom_array, buf); - opp->oprom_size = len; - - error = copyout(argp, opp, bufsize + sizeof(int)); + error = opromgetbootargs(argp, opp, bufsize); break; case OPROMU2P: @@ -297,25 +362,14 @@ #endif return error; } - -/* Return nonzero if a specific node is in the PROM device tree. */ -static int intree(int root, int node) +static struct device_node *get_node(phandle n, DATA *data) { - for (; root != 0; root = prom_getsibling(root)) - if (root == node || intree(prom_getchild(root),node)) - return 1; - return 0; -} + struct device_node *dp = of_find_node_by_phandle(n); -/* Return nonzero if a specific node is "valid". */ -static int goodnode(int n, DATA *data) -{ - if (n == data->lastnode || n == prom_root_node || n == options_node) - return 1; - if (n == 0 || n == -1 || !intree(prom_root_node,n)) - return 0; - data->lastnode = n; - return 1; + if (dp) + data->lastnode = dp; + + return dp; } /* Copy in a whole string from userspace into kernelspace. */ @@ -330,7 +384,7 @@ static int copyin_string(char __user *us if (!tmp) return -ENOMEM; - if(copy_from_user(tmp, user, len)) { + if (copy_from_user(tmp, user, len)) { kfree(tmp); return -EFAULT; } @@ -345,162 +399,187 @@ static int copyin_string(char __user *us /* * NetBSD /dev/openprom ioctl calls. */ -static int openprom_bsd_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) +static int opiocget(void __user *argp, DATA *data) { - DATA *data = (DATA *) file->private_data; - void __user *argp = (void __user *)arg; struct opiocdesc op; - int error, node, len; - char *str, *tmp; - char buffer[64]; - static int cnt; - - switch (cmd) { - case OPIOCGET: - if (copy_from_user(&op, argp, sizeof(op))) - return -EFAULT; - - if (!goodnode(op.op_nodeid,data)) - return -EINVAL; + struct device_node *dp; + char *str; + void *pval; + int err, len; - error = copyin_string(op.op_name, op.op_namelen, &str); - if (error) - return error; + if (copy_from_user(&op, argp, sizeof(op))) + return -EFAULT; - len = prom_getproplen(op.op_nodeid,str); + dp = get_node(op.op_nodeid, data); - if (len > op.op_buflen) { - kfree(str); - return -ENOMEM; - } + err = copyin_string(op.op_name, op.op_namelen, &str); + if (err) + return err; + pval = of_get_property(dp, str, &len); + err = 0; + if (!pval || len > op.op_buflen) { + err = -EINVAL; + } else { op.op_buflen = len; + if (copy_to_user(argp, &op, sizeof(op)) || + copy_to_user(op.op_buf, pval, len)) + err = -EFAULT; + } + kfree(str); - if (len <= 0) { - kfree(str); - /* Verified by the above copy_from_user */ - if (__copy_to_user(argp, &op, - sizeof(op))) - return -EFAULT; - return 0; - } + return err; +} - tmp = kmalloc(len + 1, GFP_KERNEL); - if (!tmp) { - kfree(str); - return -ENOMEM; - } +static int opiocnextprop(void __user *argp, DATA *data) +{ + struct opiocdesc op; + struct device_node *dp; + struct property *prop; + char *str; + int err, len; - cnt = prom_getproperty(op.op_nodeid, str, tmp, len); - if (cnt <= 0) { - error = -EINVAL; - } else { - tmp[len] = '\0'; + if (copy_from_user(&op, argp, sizeof(op))) + return -EFAULT; - if (__copy_to_user(argp, &op, sizeof(op)) != 0 || - copy_to_user(op.op_buf, tmp, len) != 0) - error = -EFAULT; - } + dp = get_node(op.op_nodeid, data); + if (!dp) + return -EINVAL; - kfree(tmp); - kfree(str); + err = copyin_string(op.op_name, op.op_namelen, &str); + if (err) + return err; - return error; + if (str[0] == '\0') { + prop = dp->properties; + } else { + prop = of_find_property(dp, str, NULL); + if (prop) + prop = prop->next; + } + kfree(str); - case OPIOCNEXTPROP: - if (copy_from_user(&op, argp, sizeof(op))) - return -EFAULT; + if (!prop) + len = 0; + else + len = prop->length; - if (!goodnode(op.op_nodeid,data)) - return -EINVAL; + if (len > op.op_buflen) + len = op.op_buflen; - error = copyin_string(op.op_name, op.op_namelen, &str); - if (error) - return error; + if (copy_to_user(argp, &op, sizeof(op))) + return -EFAULT; - tmp = prom_nextprop(op.op_nodeid,str,buffer); + if (len && + copy_to_user(op.op_buf, prop->value, len)) + return -EFAULT; - if (tmp) { - len = strlen(tmp); - if (len > op.op_buflen) - len = op.op_buflen; - else - op.op_buflen = len; - } else { - len = op.op_buflen = 0; - } + return 0; +} - if (!access_ok(VERIFY_WRITE, argp, sizeof(op))) { - kfree(str); - return -EFAULT; - } +static int opiocset(void __user *argp, DATA *data) +{ + struct opiocdesc op; + struct device_node *dp; + char *str, *tmp; + int err; - if (!access_ok(VERIFY_WRITE, op.op_buf, len)) { - kfree(str); - return -EFAULT; - } + if (copy_from_user(&op, argp, sizeof(op))) + return -EFAULT; + + dp = get_node(op.op_nodeid, data); + if (!dp) + return -EINVAL; - error = __copy_to_user(argp, &op, sizeof(op)); - if (!error) error = __copy_to_user(op.op_buf, tmp, len); + err = copyin_string(op.op_name, op.op_namelen, &str); + if (err) + return err; + err = copyin_string(op.op_buf, op.op_buflen, &tmp); + if (err) { kfree(str); + return err; + } - return error; + err = of_set_property(dp, str, tmp, op.op_buflen); - case OPIOCSET: - if (copy_from_user(&op, argp, sizeof(op))) - return -EFAULT; + kfree(str); + kfree(tmp); - if (!goodnode(op.op_nodeid,data)) - return -EINVAL; + return err; +} - error = copyin_string(op.op_name, op.op_namelen, &str); - if (error) - return error; +static int opiocgetnext(unsigned int cmd, void __user *argp) +{ + struct device_node *dp; + phandle nd; - error = copyin_string(op.op_buf, op.op_buflen, &tmp); - if (error) { - kfree(str); - return error; - } + BUILD_BUG_ON(sizeof(phandle) != sizeof(int)); - len = prom_setprop(op.op_nodeid,str,tmp,op.op_buflen+1); + if (copy_from_user(&nd, argp, sizeof(phandle))) + return -EFAULT; - if (len != op.op_buflen) + if (nd == 0) { + if (cmd != OPIOCGETNEXT) return -EINVAL; + dp = of_find_node_by_path("/"); + } else { + dp = of_find_node_by_phandle(nd); + nd = 0; + if (dp) { + if (cmd == OPIOCGETNEXT) + dp = dp->sibling; + else + dp = dp->child; + } + } + if (dp) + nd = dp->node; + if (copy_to_user(argp, &nd, sizeof(phandle))) + return -EFAULT; - kfree(str); - kfree(tmp); + return 0; +} - return 0; +static int openprom_bsd_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + DATA *data = (DATA *) file->private_data; + void __user *argp = (void __user *)arg; + int err; - case OPIOCGETOPTNODE: - if (copy_to_user(argp, &options_node, sizeof(int))) - return -EFAULT; - return 0; + switch (cmd) { + case OPIOCGET: + err = opiocget(argp, data); + break; - case OPIOCGETNEXT: - case OPIOCGETCHILD: - if (copy_from_user(&node, argp, sizeof(int))) - return -EFAULT; + case OPIOCNEXTPROP: + err = opiocnextprop(argp, data); + break; - if (cmd == OPIOCGETNEXT) - node = __prom_getsibling(node); - else - node = __prom_getchild(node); + case OPIOCSET: + err = opiocset(argp, data); + break; + + case OPIOCGETOPTNODE: + BUILD_BUG_ON(sizeof(phandle) != sizeof(int)); - if (__copy_to_user(argp, &node, sizeof(int))) + if (copy_to_user(argp, &options_node->node, sizeof(phandle))) return -EFAULT; return 0; + case OPIOCGETNEXT: + case OPIOCGETCHILD: + err = opiocgetnext(cmd, argp); + break; + default: - if (cnt++ < 10) - printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd); return -EINVAL; - } + }; + + return err; } @@ -511,7 +590,6 @@ static int openprom_ioctl(struct inode * unsigned int cmd, unsigned long arg) { DATA *data = (DATA *) file->private_data; - static int cnt; switch (cmd) { case OPROMGETOPT: @@ -563,10 +641,8 @@ static int openprom_ioctl(struct inode * return openprom_bsd_ioctl(inode,file,cmd,arg); default: - if (cnt++ < 10) - printk("openprom_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg); return -EINVAL; - } + }; } static long openprom_compat_ioctl(struct file *file, unsigned int cmd, @@ -594,9 +670,7 @@ static long openprom_compat_ioctl(struct case OPROMSETCUR: case OPROMPCI2NODE: case OPROMPATH2NODE: - lock_kernel(); rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg); - lock_kernel(); break; } @@ -607,13 +681,13 @@ static int openprom_open(struct inode * { DATA *data; - data = (DATA *) kmalloc(sizeof(DATA), GFP_KERNEL); + data = kmalloc(sizeof(DATA), GFP_KERNEL); if (!data) return -ENOMEM; - data->current_node = prom_root_node; - data->lastnode = prom_root_node; - file->private_data = (void *)data; + data->current_node = of_find_node_by_path("/"); + data->lastnode = data->current_node; + file->private_data = (void *) data; return 0; } @@ -634,24 +708,30 @@ static struct file_operations openprom_f }; static struct miscdevice openprom_dev = { - SUN_OPENPROM_MINOR, "openprom", &openprom_fops + .minor = SUN_OPENPROM_MINOR, + .name = "openprom", + .fops = &openprom_fops, }; static int __init openprom_init(void) { - int error; + struct device_node *dp; + int err; - error = misc_register(&openprom_dev); - if (error) { - printk(KERN_ERR "openprom: unable to get misc minor\n"); - return error; - } + err = misc_register(&openprom_dev); + if (err) + return err; - options_node = prom_getchild(prom_root_node); - options_node = prom_searchsiblings(options_node,"options"); + dp = of_find_node_by_path("/"); + dp = dp->child; + while (dp) { + if (!strcmp(dp->name, "options")) + break; + dp = dp->sibling; + } + options_node = dp; - if (options_node == 0 || options_node == -1) { - printk(KERN_ERR "openprom: unable to find options node\n"); + if (!options_node) { misc_deregister(&openprom_dev); return -EIO; } @@ -666,4 +746,3 @@ static void __exit openprom_cleanup(void module_init(openprom_init); module_exit(openprom_cleanup); -MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/sbus/char/riowatchdog.c index d1babff..2a9cc82 100644 --- a/drivers/sbus/char/riowatchdog.c +++ b/drivers/sbus/char/riowatchdog.c @@ -211,7 +211,7 @@ static int __init riowd_bbc_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "bbc")) + if (!strcmp(edev->ofdev.node->name, "bbc")) goto found_bbc; } } @@ -238,7 +238,7 @@ static int __init riowd_init(void) for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, RIOWD_NAME)) + if (!strcmp(edev->ofdev.node->name, RIOWD_NAME)) goto ebus_done; } } diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index e2d9a7c..575b1f7 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c @@ -400,7 +400,7 @@ static int __init ts102_uctrl_init(void) } driver->regs->uctrl_intr = UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK; - printk("uctrl: 0x%x (irq %s)\n", driver->regs, __irq_itoa(driver->irq)); + printk("uctrl: 0x%x (irq %d)\n", driver->regs, driver->irq); uctrl_get_event_status(); uctrl_get_external_status(); return 0; diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index dfdd6be..ddcd330 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c @@ -623,7 +623,7 @@ static int vfc_mmap(struct file *file, s map_size = sizeof(struct vfc_regs); vma->vm_flags |= - (VM_SHM | VM_LOCKED | VM_IO | VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE); + (VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE); map_offset = (unsigned int) (long)dev->phys_regs; ret = io_remap_pfn_range(vma, vma->vm_start, MK_IOSPACE_PFN(dev->which_io, diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index 5d30a3e..387a6aa 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c @@ -1,7 +1,6 @@ -/* $Id: sbus.c,v 1.100 2002/01/24 15:36:24 davem Exp $ - * sbus.c: SBus support routines. +/* sbus.c: SBus support routines. * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net) */ #include @@ -14,237 +13,76 @@ #include #include #include #include +#include +#include #include #include -struct sbus_bus *sbus_root = NULL; +struct sbus_bus *sbus_root; -static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } }; -#ifdef CONFIG_SPARC32 -static int interrupts[PROMINTR_MAX] __initdata = { 0 }; -#endif - -#ifdef CONFIG_PCI -extern int pcic_present(void); -#endif - -/* Perhaps when I figure out more about the iommu we'll put a - * device registration routine here that probe_sbus() calls to - * setup the iommu for each Sbus. - */ - -/* We call this for each SBus device, and fill the structure based - * upon the prom device tree. We return the start of memory after - * the things we have allocated. - */ - -/* #define DEBUG_FILL */ - -static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev) +static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev) { - unsigned long address, base; + unsigned long base; + void *pval; int len; - sdev->prom_node = prom_node; - prom_getstring(prom_node, "name", - sdev->prom_name, sizeof(sdev->prom_name)); - address = prom_getint(prom_node, "address"); - len = prom_getproperty(prom_node, "reg", - (char *) sdev->reg_addrs, - sizeof(sdev->reg_addrs)); - if (len == -1) { - sdev->num_registers = 0; - goto no_regs; - } + sdev->prom_node = dp->node; + strcpy(sdev->prom_name, dp->name); - if (len % sizeof(struct linux_prom_registers)) { - prom_printf("fill_sbus_device: proplen for regs of %s " - " was %d, need multiple of %d\n", - sdev->prom_name, len, - (int) sizeof(struct linux_prom_registers)); - prom_halt(); - } - if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) { - prom_printf("fill_sbus_device: Too many register properties " - "for device %s, len=%d\n", - sdev->prom_name, len); - prom_halt(); - } - sdev->num_registers = len / sizeof(struct linux_prom_registers); - sdev->ranges_applied = 0; + pval = of_get_property(dp, "reg", &len); + sdev->num_registers = 0; + if (pval) { + memcpy(sdev->reg_addrs, pval, len); - base = (unsigned long) sdev->reg_addrs[0].phys_addr; + sdev->num_registers = + len / sizeof(struct linux_prom_registers); - /* Compute the slot number. */ - if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) { - sdev->slot = sbus_dev_slot(base); - } else { - sdev->slot = sdev->reg_addrs[0].which_io; - } + base = (unsigned long) sdev->reg_addrs[0].phys_addr; -no_regs: - len = prom_getproperty(prom_node, "ranges", - (char *)sdev->device_ranges, - sizeof(sdev->device_ranges)); - if (len == -1) { - sdev->num_device_ranges = 0; - goto no_ranges; - } - if (len % sizeof(struct linux_prom_ranges)) { - prom_printf("fill_sbus_device: proplen for ranges of %s " - " was %d, need multiple of %d\n", - sdev->prom_name, len, - (int) sizeof(struct linux_prom_ranges)); - prom_halt(); - } - if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) { - prom_printf("fill_sbus_device: Too many range properties " - "for device %s, len=%d\n", - sdev->prom_name, len); - prom_halt(); + /* Compute the slot number. */ + if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) + sdev->slot = sbus_dev_slot(base); + else + sdev->slot = sdev->reg_addrs[0].which_io; } - sdev->num_device_ranges = - len / sizeof(struct linux_prom_ranges); - -no_ranges: - /* XXX Unfortunately, IRQ issues are very arch specific. - * XXX Pull this crud out into an arch specific area - * XXX at some point. -DaveM - */ -#ifdef CONFIG_SPARC64 - len = prom_getproperty(prom_node, "interrupts", - (char *) irqs, sizeof(irqs)); - if (len == -1 || len == 0) { - sdev->irqs[0] = 0; - sdev->num_irqs = 0; - } else { - unsigned int pri = irqs[0].pri; - - sdev->num_irqs = 1; - if (pri < 0x20) - pri += sdev->slot * 8; - - sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); + + pval = of_get_property(dp, "ranges", &len); + sdev->num_device_ranges = 0; + if (pval) { + memcpy(sdev->device_ranges, pval, len); + sdev->num_device_ranges = + len / sizeof(struct linux_prom_ranges); } -#endif /* CONFIG_SPARC64 */ - -#ifdef CONFIG_SPARC32 - len = prom_getproperty(prom_node, "intr", - (char *)irqs, sizeof(irqs)); - if (len != -1) { - sdev->num_irqs = len / 8; - if (sdev->num_irqs == 0) { - sdev->irqs[0] = 0; - } else if (sparc_cpu_model == sun4d) { - extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); - - for (len = 0; len < sdev->num_irqs; len++) - sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri); - } else { - for (len = 0; len < sdev->num_irqs; len++) - sdev->irqs[len] = irqs[len].pri; - } - } else { - /* No "intr" node found-- check for "interrupts" node. - * This node contains SBus interrupt levels, not IPLs - * as in "intr", and no vector values. We convert - * SBus interrupt levels to PILs (platform specific). - */ - len = prom_getproperty(prom_node, "interrupts", - (char *)interrupts, sizeof(interrupts)); - if (len == -1) { - sdev->irqs[0] = 0; - sdev->num_irqs = 0; - } else { - sdev->num_irqs = len / sizeof(int); - for (len = 0; len < sdev->num_irqs; len++) { - sdev->irqs[len] = sbint_to_irq(sdev, interrupts[len]); - } - } - } -#endif /* CONFIG_SPARC32 */ -} -/* This routine gets called from whoever needs the sbus first, to scan - * the SBus device tree. Currently it just prints out the devices - * found on the bus and builds trees of SBUS structs and attached - * devices. - */ + sbus_fill_device_irq(sdev); -extern void iommu_init(int iommu_node, struct sbus_bus *sbus); -extern void iounit_init(int sbi_node, int iounit_node, struct sbus_bus *sbus); -void sun4_init(void); -#ifdef CONFIG_SUN_AUXIO -extern void auxio_probe(void); -#endif - -static void __init sbus_do_child_siblings(int start_node, - struct sbus_dev *child, - struct sbus_dev *parent, - struct sbus_bus *sbus) -{ - struct sbus_dev *this_dev = child; - int this_node = start_node; - - /* Child already filled in, just need to traverse siblings. */ - child->child = NULL; - child->parent = parent; - while((this_node = prom_getsibling(this_node)) != 0) { - this_dev->next = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); - this_dev = this_dev->next; - this_dev->next = NULL; - this_dev->parent = parent; - - this_dev->bus = sbus; - fill_sbus_device(this_node, this_dev); - - if(prom_getchild(this_node)) { - this_dev->child = kmalloc(sizeof(struct sbus_dev), - GFP_ATOMIC); - this_dev->child->bus = sbus; - this_dev->child->next = NULL; - fill_sbus_device(prom_getchild(this_node), this_dev->child); - sbus_do_child_siblings(prom_getchild(this_node), - this_dev->child, this_dev, sbus); - } else { - this_dev->child = NULL; - } - } -} + sdev->ofdev.node = dp; + if (sdev->parent) + sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev; + else + sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev; + sdev->ofdev.dev.bus = &sbus_bus_type; + strcpy(sdev->ofdev.dev.bus_id, dp->path_component_name); -/* - * XXX This functions appears to be a distorted version of - * prom_sbus_ranges_init(), with all sun4d stuff cut away. - * Ask DaveM what is going on here, how is sun4d supposed to work... XXX - */ -/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */ + if (of_device_register(&sdev->ofdev) != 0) + printk(KERN_DEBUG "sbus: device registration error for %s!\n", + sdev->ofdev.dev.bus_id); +} -static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus) +static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus) { + void *pval; int len; - len = prom_getproperty(sbus->prom_node, "ranges", - (char *) sbus->sbus_ranges, - sizeof(sbus->sbus_ranges)); - if (len == -1 || len == 0) { - sbus->num_sbus_ranges = 0; - return; - } - sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges); -#ifdef CONFIG_SPARC32 - if (sparc_cpu_model == sun4d) { - struct linux_prom_ranges iounit_ranges[PROMREG_MAX]; - int num_iounit_ranges; - - len = prom_getproperty(parent_node, "ranges", - (char *) iounit_ranges, - sizeof (iounit_ranges)); - if (len != -1) { - num_iounit_ranges = (len/sizeof(struct linux_prom_ranges)); - prom_adjust_ranges (sbus->sbus_ranges, sbus->num_sbus_ranges, iounit_ranges, num_iounit_ranges); - } + pval = of_get_property(dp, "ranges", &len); + sbus->num_sbus_ranges = 0; + if (pval) { + memcpy(sbus->sbus_ranges, pval, len); + sbus->num_sbus_ranges = + len / sizeof(struct linux_prom_ranges); + + sbus_arch_bus_ranges_init(dp->parent, sbus); } -#endif } static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges, @@ -322,241 +160,127 @@ static void __init sbus_fixup_all_regs(s } } -extern void register_proc_sparc_ioport(void); -extern void firetruck_init(void); +/* We preserve the "probe order" of these bus and device lists to give + * the same ordering as the old code. + */ +static void __init sbus_insert(struct sbus_bus *sbus, struct sbus_bus **root) +{ + while (*root) + root = &(*root)->next; + *root = sbus; + sbus->next = NULL; +} -#ifdef CONFIG_SUN4 -extern void sun4_dvma_init(void); -#endif +static void __init sdev_insert(struct sbus_dev *sdev, struct sbus_dev **root) +{ + while (*root) + root = &(*root)->next; + *root = sdev; + sdev->next = NULL; +} -static int __init sbus_init(void) +static void __init walk_children(struct device_node *dp, struct sbus_dev *parent, struct sbus_bus *sbus) { - int nd, this_sbus, sbus_devs, topnd, iommund; - unsigned int sbus_clock; - struct sbus_bus *sbus; - struct sbus_dev *this_dev; - int num_sbus = 0; /* How many did we find? */ + dp = dp->child; + while (dp) { + struct sbus_dev *sdev; -#ifdef CONFIG_SPARC32 - register_proc_sparc_ioport(); -#endif + sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); + if (sdev) { + sdev_insert(sdev, &parent->child); -#ifdef CONFIG_SUN4 - sun4_dvma_init(); - return 0; -#endif - - topnd = prom_getchild(prom_root_node); - - /* Finding the first sbus is a special case... */ - iommund = 0; - if(sparc_cpu_model == sun4u) { - nd = prom_searchsiblings(topnd, "sbus"); - if(nd == 0) { -#ifdef CONFIG_PCI - if (!pcic_present()) { - prom_printf("Neither SBUS nor PCI found.\n"); - prom_halt(); - } else { -#ifdef CONFIG_SPARC64 - firetruck_init(); -#endif - } - return 0; -#else - prom_printf("YEEE, UltraSparc sbus not found\n"); - prom_halt(); -#endif - } - } else if(sparc_cpu_model == sun4d) { - if((iommund = prom_searchsiblings(topnd, "io-unit")) == 0 || - (nd = prom_getchild(iommund)) == 0 || - (nd = prom_searchsiblings(nd, "sbi")) == 0) { - panic("sbi not found"); - } - } else if((nd = prom_searchsiblings(topnd, "sbus")) == 0) { - if((iommund = prom_searchsiblings(topnd, "iommu")) == 0 || - (nd = prom_getchild(iommund)) == 0 || - (nd = prom_searchsiblings(nd, "sbus")) == 0) { -#ifdef CONFIG_PCI - if (!pcic_present()) { - prom_printf("Neither SBUS nor PCI found.\n"); - prom_halt(); - } - return 0; -#else - /* No reason to run further - the data access trap will occur. */ - panic("sbus not found"); -#endif + sdev->bus = sbus; + sdev->parent = parent; + + fill_sbus_device(dp, sdev); + + walk_children(dp, sdev, sbus); } + dp = dp->sibling; } +} - /* Ok, we've found the first one, allocate first SBus struct - * and place in chain. - */ - sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC); - sbus->next = NULL; - sbus->prom_node = nd; - this_sbus = nd; +static void __init build_one_sbus(struct device_node *dp, int num_sbus) +{ + struct sbus_bus *sbus; + unsigned int sbus_clock; + struct device_node *dev_dp; - if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d) - iommu_init(iommund, sbus); + sbus = kzalloc(sizeof(struct sbus_bus), GFP_ATOMIC); + if (!sbus) + return; - /* Loop until we find no more SBUS's */ - while(this_sbus) { -#ifdef CONFIG_SPARC64 - /* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */ - if(sparc_cpu_model == sun4u) { - extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus); + sbus_insert(sbus, &sbus_root); + sbus->prom_node = dp->node; - sbus_iommu_init(this_sbus, sbus); - } -#endif /* CONFIG_SPARC64 */ - -#ifdef CONFIG_SPARC32 - if (sparc_cpu_model == sun4d) - iounit_init(this_sbus, iommund, sbus); -#endif /* CONFIG_SPARC32 */ - printk("sbus%d: ", num_sbus); - sbus_clock = prom_getint(this_sbus, "clock-frequency"); - if(sbus_clock == -1) - sbus_clock = (25*1000*1000); - printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), - (int) (((sbus_clock/1000)%1000 != 0) ? - (((sbus_clock/1000)%1000) + 1000) : 0)); - - prom_getstring(this_sbus, "name", - sbus->prom_name, sizeof(sbus->prom_name)); - sbus->clock_freq = sbus_clock; -#ifdef CONFIG_SPARC32 - if (sparc_cpu_model == sun4d) { - sbus->devid = prom_getint(iommund, "device-id"); - sbus->board = prom_getint(iommund, "board#"); - } -#endif - - sbus_bus_ranges_init(iommund, sbus); - - sbus_devs = prom_getchild(this_sbus); - if (!sbus_devs) { - sbus->devices = NULL; - goto next_bus; - } + sbus_setup_iommu(sbus, dp); - sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); - - this_dev = sbus->devices; - this_dev->next = NULL; - - this_dev->bus = sbus; - this_dev->parent = NULL; - fill_sbus_device(sbus_devs, this_dev); - - /* Should we traverse for children? */ - if(prom_getchild(sbus_devs)) { - /* Allocate device node */ - this_dev->child = kmalloc(sizeof(struct sbus_dev), - GFP_ATOMIC); - /* Fill it */ - this_dev->child->bus = sbus; - this_dev->child->next = NULL; - fill_sbus_device(prom_getchild(sbus_devs), - this_dev->child); - sbus_do_child_siblings(prom_getchild(sbus_devs), - this_dev->child, - this_dev, - sbus); - } else { - this_dev->child = NULL; - } + printk("sbus%d: ", num_sbus); - while((sbus_devs = prom_getsibling(sbus_devs)) != 0) { - /* Allocate device node */ - this_dev->next = kmalloc(sizeof(struct sbus_dev), - GFP_ATOMIC); - this_dev = this_dev->next; - this_dev->next = NULL; - - /* Fill it */ - this_dev->bus = sbus; - this_dev->parent = NULL; - fill_sbus_device(sbus_devs, this_dev); - - /* Is there a child node hanging off of us? */ - if(prom_getchild(sbus_devs)) { - /* Get new device struct */ - this_dev->child = kmalloc(sizeof(struct sbus_dev), - GFP_ATOMIC); - /* Fill it */ - this_dev->child->bus = sbus; - this_dev->child->next = NULL; - fill_sbus_device(prom_getchild(sbus_devs), - this_dev->child); - sbus_do_child_siblings(prom_getchild(sbus_devs), - this_dev->child, - this_dev, - sbus); - } else { - this_dev->child = NULL; - } + sbus_clock = of_getintprop_default(dp, "clock-frequency", + (25*1000*1000)); + sbus->clock_freq = sbus_clock; + + printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), + (int) (((sbus_clock/1000)%1000 != 0) ? + (((sbus_clock/1000)%1000) + 1000) : 0)); + + strcpy(sbus->prom_name, dp->name); + + sbus_setup_arch_props(sbus, dp); + + sbus_bus_ranges_init(dp, sbus); + + sbus->ofdev.node = dp; + sbus->ofdev.dev.parent = NULL; + sbus->ofdev.dev.bus = &sbus_bus_type; + strcpy(sbus->ofdev.dev.bus_id, dp->path_component_name); + + if (of_device_register(&sbus->ofdev) != 0) + printk(KERN_DEBUG "sbus: device registration error for %s!\n", + sbus->ofdev.dev.bus_id); + + dev_dp = dp->child; + while (dev_dp) { + struct sbus_dev *sdev; + + sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); + if (sdev) { + sdev_insert(sdev, &sbus->devices); + + sdev->bus = sbus; + sdev->parent = NULL; + fill_sbus_device(dev_dp, sdev); + + walk_children(dev_dp, sdev, sbus); } + dev_dp = dev_dp->sibling; + } - /* Walk all devices and apply parent ranges. */ - sbus_fixup_all_regs(sbus->devices); + sbus_fixup_all_regs(sbus->devices); - dvma_init(sbus); - next_bus: + dvma_init(sbus); +} + +static int __init sbus_init(void) +{ + struct device_node *dp; + const char *sbus_name = "sbus"; + int num_sbus = 0; + + if (sbus_arch_preinit()) + return 0; + + if (sparc_cpu_model == sun4d) + sbus_name = "sbi"; + + for_each_node_by_name(dp, sbus_name) { + build_one_sbus(dp, num_sbus); num_sbus++; - if(sparc_cpu_model == sun4u) { - this_sbus = prom_getsibling(this_sbus); - if(!this_sbus) - break; - this_sbus = prom_searchsiblings(this_sbus, "sbus"); - } else if(sparc_cpu_model == sun4d) { - iommund = prom_getsibling(iommund); - if(!iommund) - break; - iommund = prom_searchsiblings(iommund, "io-unit"); - if(!iommund) - break; - this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi"); - } else { - this_sbus = prom_getsibling(this_sbus); - if(!this_sbus) - break; - this_sbus = prom_searchsiblings(this_sbus, "sbus"); - } - if(this_sbus) { - sbus->next = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC); - sbus = sbus->next; - sbus->next = NULL; - sbus->prom_node = this_sbus; - } else { - break; - } - } /* while(this_sbus) */ - if (sparc_cpu_model == sun4d) { - extern void sun4d_init_sbi_irq(void); - sun4d_init_sbi_irq(); - } - -#ifdef CONFIG_SPARC64 - if (sparc_cpu_model == sun4u) { - firetruck_init(); } -#endif -#ifdef CONFIG_SUN_AUXIO - if (sparc_cpu_model == sun4u) - auxio_probe (); -#endif -#ifdef CONFIG_SPARC64 - if (sparc_cpu_model == sun4u) { - extern void clock_probe(void); - - clock_probe(); - } -#endif + + sbus_arch_postinit(); return 0; } diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index caeb6d2..b003baf 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -1388,7 +1388,7 @@ static int twa_map_scsi_sg_data(TW_Devic if (cmd->use_sg == 0) goto out; - use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, DMA_BIDIRECTIONAL); + use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); if (use_sg == 0) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list"); diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index e8e41e6..17dbd4a 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -405,7 +405,7 @@ static int tw_decode_sense(TW_Device_Ext /* Attempt to return intelligent sense information */ if (fill_sense) { if ((command->status == 0xc7) || (command->status == 0xcb)) { - for (i=0;i<(sizeof(tw_sense_table)/sizeof(tw_sense_table[0]));i++) { + for (i = 0; i < ARRAY_SIZE(tw_sense_table); i++) { if (command->flags == tw_sense_table[i][0]) { /* Valid bit and 'current errors' */ @@ -625,7 +625,7 @@ static int tw_aen_complete(TW_Device_Ext if (aen == 0x0ff) { printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no); } else { - table_max = sizeof(tw_aen_string)/sizeof(char *); + table_max = ARRAY_SIZE(tw_aen_string); if ((aen & 0x0ff) < table_max) { if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') { printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8); @@ -786,7 +786,7 @@ static int tw_aen_drain_queue(TW_Device_ if (aen == 0x0ff) { printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n"); } else { - table_max = sizeof(tw_aen_string)/sizeof(char *); + table_max = ARRAY_SIZE(tw_aen_string); if ((aen & 0x0ff) < table_max) { if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') { printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8); @@ -1286,7 +1286,7 @@ static int tw_map_scsi_sg_data(struct pc if (cmd->use_sg == 0) return 0; - use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, DMA_BIDIRECTIONAL); + use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); if (use_sg == 0) { printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n"); diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 6a0f950..3c683dc 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -183,6 +183,10 @@ STATIC struct device_attribute *NCR_700_ STATIC struct scsi_transport_template *NCR_700_transport_template = NULL; +struct NCR_700_sense { + unsigned char cmnd[MAX_COMMAND_SIZE]; +}; + static char *NCR_700_phase[] = { "", "after selection", @@ -316,7 +320,7 @@ NCR_700_detect(struct scsi_host_template BUG_ON(!dma_is_consistent(pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); hostdata->dev = dev; - + pSlots = pScript + SLOTS_OFFSET; /* Fill in the missing routines from the host template */ @@ -332,19 +336,18 @@ NCR_700_detect(struct scsi_host_template tpnt->slave_destroy = NCR_700_slave_destroy; tpnt->change_queue_depth = NCR_700_change_queue_depth; tpnt->change_queue_type = NCR_700_change_queue_type; - + if(tpnt->name == NULL) tpnt->name = "53c700"; if(tpnt->proc_name == NULL) tpnt->proc_name = "53c700"; - host = scsi_host_alloc(tpnt, 4); if (!host) return NULL; memset(hostdata->slots, 0, sizeof(struct NCR_700_command_slot) * NCR_700_COMMAND_SLOTS_PER_HOST); - for(j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) { + for (j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) { dma_addr_t offset = (dma_addr_t)((unsigned long)&hostdata->slots[j].SG[0] - (unsigned long)&hostdata->slots[0].SG[0]); hostdata->slots[j].pSG = (struct NCR_700_SG_List *)((unsigned long)(pSlots + offset)); @@ -355,14 +358,12 @@ NCR_700_detect(struct scsi_host_template hostdata->slots[j].state = NCR_700_SLOT_FREE; } - for(j = 0; j < sizeof(SCRIPT)/sizeof(SCRIPT[0]); j++) { + for (j = 0; j < ARRAY_SIZE(SCRIPT); j++) script[j] = bS_to_host(SCRIPT[j]); - } /* adjust all labels to be bus physical */ - for(j = 0; j < PATCHES; j++) { + for (j = 0; j < PATCHES; j++) script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]); - } /* now patch up fixed addresses. */ script_patch_32(script, MessageLocation, pScript + MSGOUT_OFFSET); @@ -376,7 +377,7 @@ NCR_700_detect(struct scsi_host_template dma_sync_single_for_device(hostdata->dev, pScript, sizeof(SCRIPT), DMA_TO_DEVICE); hostdata->state = NCR_700_HOST_FREE; hostdata->cmd = NULL; - host->max_id = 7; + host->max_id = 8; host->max_lun = NCR_700_MAX_LUNS; BUG_ON(NCR_700_transport_template == NULL); host->transportt = NCR_700_transport_template; @@ -385,17 +386,17 @@ NCR_700_detect(struct scsi_host_template host->hostdata[0] = (unsigned long)hostdata; /* kick the chip */ NCR_700_writeb(0xff, host, CTEST9_REG); - if(hostdata->chip710) + if (hostdata->chip710) hostdata->rev = (NCR_700_readb(host, CTEST8_REG)>>4) & 0x0f; else hostdata->rev = (NCR_700_readb(host, CTEST7_REG)>>4) & 0x0f; hostdata->fast = (NCR_700_readb(host, CTEST9_REG) == 0); - if(banner == 0) { + if (banner == 0) { printk(KERN_NOTICE "53c700: Version " NCR_700_VERSION " By James.Bottomley@HansenPartnership.com\n"); banner = 1; } printk(KERN_NOTICE "scsi%d: %s rev %d %s\n", host->host_no, - hostdata->chip710 ? "53c710" : + hostdata->chip710 ? "53c710" : (hostdata->fast ? "53c700-66" : "53c700"), hostdata->rev, hostdata->differential ? "(Differential)" : ""); @@ -540,6 +541,7 @@ find_empty_slot(struct NCR_700_Host_Para * finish routine. If we cannot queue the command when it * is properly build, we then change to NCR_700_SLOT_QUEUED */ slot->state = NCR_700_SLOT_BUSY; + slot->flags = 0; hostdata->command_slot_count++; return slot; @@ -589,7 +591,7 @@ NCR_700_unmap(struct NCR_700_Host_Parame if(SCp->sc_data_direction != DMA_NONE && SCp->sc_data_direction != DMA_BIDIRECTIONAL) { if(SCp->use_sg) { - dma_unmap_sg(hostdata->dev, SCp->buffer, + dma_unmap_sg(hostdata->dev, SCp->request_buffer, SCp->use_sg, SCp->sc_data_direction); } else { dma_unmap_single(hostdata->dev, slot->dma_handle, @@ -611,30 +613,23 @@ NCR_700_scsi_done(struct NCR_700_Host_Pa (struct NCR_700_command_slot *)SCp->host_scribble; NCR_700_unmap(hostdata, SCp, slot); - dma_unmap_single(hostdata->dev, slot->pCmd, - sizeof(SCp->cmnd), DMA_TO_DEVICE); - if(SCp->cmnd[0] == REQUEST_SENSE && SCp->cmnd[6] == NCR_700_INTERNAL_SENSE_MAGIC) { + if (slot->flags == NCR_700_FLAG_AUTOSENSE) { + struct NCR_700_sense *sense = SCp->device->hostdata; #ifdef NCR_700_DEBUG printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n", SCp, SCp->cmnd[7], result); scsi_print_sense("53c700", SCp); #endif + dma_unmap_single(hostdata->dev, slot->dma_handle, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); /* restore the old result if the request sense was * successful */ if(result == 0) - result = SCp->cmnd[7]; - /* now restore the original command */ - memcpy((void *) SCp->cmnd, (void *) SCp->data_cmnd, - sizeof(SCp->data_cmnd)); - SCp->request_buffer = SCp->buffer; - SCp->request_bufflen = SCp->bufflen; - SCp->use_sg = SCp->old_use_sg; - SCp->cmd_len = SCp->old_cmd_len; - SCp->sc_data_direction = SCp->sc_old_data_direction; - SCp->underflow = SCp->old_underflow; - - } + result = sense->cmnd[7]; + } else + dma_unmap_single(hostdata->dev, slot->pCmd, + sizeof(SCp->cmnd), DMA_TO_DEVICE); + free_slot(slot, hostdata); #ifdef NCR_700_DEBUG if(NCR_700_get_depth(SCp->device) == 0 || @@ -982,6 +977,7 @@ process_script_interrupt(__u32 dsps, __u "broken device is looping in contingent allegiance: ignoring\n"); NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]); } else { + struct NCR_700_sense *sense = SCp->device->hostdata; #ifdef NCR_DEBUG scsi_print_command(SCp); printk(" cmd %p has status %d, requesting sense\n", @@ -995,27 +991,25 @@ #endif * data associated with the command * here */ NCR_700_unmap(hostdata, SCp, slot); - - SCp->cmnd[0] = REQUEST_SENSE; - SCp->cmnd[1] = (SCp->device->lun & 0x7) << 5; - SCp->cmnd[2] = 0; - SCp->cmnd[3] = 0; - SCp->cmnd[4] = sizeof(SCp->sense_buffer); - SCp->cmnd[5] = 0; - SCp->cmd_len = 6; + dma_unmap_single(hostdata->dev, slot->pCmd, + sizeof(SCp->cmnd), + DMA_TO_DEVICE); + + sense->cmnd[0] = REQUEST_SENSE; + sense->cmnd[1] = (SCp->device->lun & 0x7) << 5; + sense->cmnd[2] = 0; + sense->cmnd[3] = 0; + sense->cmnd[4] = sizeof(SCp->sense_buffer); + sense->cmnd[5] = 0; /* Here's a quiet hack: the * REQUEST_SENSE command is six bytes, * so store a flag indicating that * this was an internal sense request * and the original status at the end * of the command */ - SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; - SCp->cmnd[7] = hostdata->status[0]; - SCp->use_sg = 0; - SCp->sc_data_direction = DMA_FROM_DEVICE; - dma_sync_single_for_device(hostdata->dev, slot->pCmd, - SCp->cmd_len, DMA_TO_DEVICE); - SCp->request_bufflen = sizeof(SCp->sense_buffer); + sense->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; + sense->cmnd[7] = hostdata->status[0]; + slot->pCmd = dma_map_single(hostdata->dev, sense->cmnd, sizeof(sense->cmnd), DMA_TO_DEVICE); slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); slot->SG[0].pAddr = bS_to_host(slot->dma_handle); @@ -1027,6 +1021,7 @@ #endif /* queue the command for reissue */ slot->state = NCR_700_SLOT_QUEUED; + slot->flags = NCR_700_FLAG_AUTOSENSE; hostdata->state = NCR_700_HOST_FREE; hostdata->cmd = NULL; } @@ -1247,7 +1242,7 @@ #endif if(SCp->use_sg) { for(i = 0; i < SCp->use_sg + 1; i++) { - printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr); + printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->request_buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr); } } } @@ -1406,12 +1401,14 @@ NCR_700_start_command(struct scsi_cmnd * /* keep interrupts disabled until we have the command correctly * set up so we cannot take a selection interrupt */ - hostdata->msgout[0] = NCR_700_identify(SCp->cmnd[0] != REQUEST_SENSE, + hostdata->msgout[0] = NCR_700_identify((SCp->cmnd[0] != REQUEST_SENSE && + slot->flags != NCR_700_FLAG_AUTOSENSE), SCp->device->lun); /* for INQUIRY or REQUEST_SENSE commands, we cannot be sure * if the negotiated transfer parameters still hold, so * always renegotiate them */ - if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE) { + if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE || + slot->flags == NCR_700_FLAG_AUTOSENSE) { NCR_700_clear_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); } @@ -1420,7 +1417,8 @@ NCR_700_start_command(struct scsi_cmnd * * will refuse all tags, so send the request sense as untagged * */ if((hostdata->tag_negotiated & (1<tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE)) { + && (slot->tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE && + slot->flags != NCR_700_FLAG_AUTOSENSE)) { count += scsi_populate_tag_msg(SCp, &hostdata->msgout[count]); } @@ -1866,8 +1864,9 @@ #endif __u32 count = 0; if(SCp->use_sg) { - sg_count = dma_map_sg(hostdata->dev, SCp->buffer, - SCp->use_sg, direction); + sg_count = dma_map_sg(hostdata->dev, + SCp->request_buffer, SCp->use_sg, + direction); } else { vPtr = dma_map_single(hostdata->dev, SCp->request_buffer, @@ -1882,7 +1881,7 @@ #endif for(i = 0; i < sg_count; i++) { if(SCp->use_sg) { - struct scatterlist *sg = SCp->buffer; + struct scatterlist *sg = SCp->request_buffer; vPtr = sg_dma_address(&sg[i]); count = sg_dma_len(&sg[i]); @@ -2045,6 +2044,11 @@ NCR_700_slave_configure(struct scsi_devi struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + SDp->hostdata = kmalloc(GFP_KERNEL, sizeof(struct NCR_700_sense)); + + if (!SDp->hostdata) + return -ENOMEM; + /* to do here: allocate memory; build a queue_full list */ if(SDp->tagged_supported) { scsi_set_tag_type(SDp, MSG_ORDERED_TAG); @@ -2068,7 +2072,8 @@ NCR_700_slave_configure(struct scsi_devi STATIC void NCR_700_slave_destroy(struct scsi_device *SDp) { - /* to do here: deallocate memory */ + kfree(SDp->hostdata); + SDp->hostdata = NULL; } static int diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h index a8c83bb..7f22a06 100644 --- a/drivers/scsi/53c700.h +++ b/drivers/scsi/53c700.h @@ -163,6 +163,8 @@ struct NCR_700_command_slot { #define NCR_700_SLOT_BUSY (1|NCR_700_SLOT_MAGIC) /* slot has command active on HA */ #define NCR_700_SLOT_QUEUED (2|NCR_700_SLOT_MAGIC) /* slot has command to be made active on HA */ __u8 state; + #define NCR_700_FLAG_AUTOSENSE 0x01 + __u8 flags; int tag; __u32 resume_offset; struct scsi_cmnd *cmnd; @@ -472,8 +474,7 @@ NCR_700_readl(struct Scsi_Host *host, __ ioread32(hostdata->base + reg); #if 1 /* sanity check the register */ - if((reg & 0x3) != 0) - BUG(); + BUG_ON((reg & 0x3) != 0); #endif return value; @@ -496,8 +497,7 @@ NCR_700_writel(__u32 value, struct Scsi_ #if 1 /* sanity check the register */ - if((reg & 0x3) != 0) - BUG(); + BUG_ON((reg & 0x3) != 0); #endif bEBus ? iowrite32be(value, hostdata->base + reg): diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c index 7894b8e..765769a 100644 --- a/drivers/scsi/53c7xx.c +++ b/drivers/scsi/53c7xx.c @@ -361,7 +361,7 @@ #endif static char *setup_strings[] = {"","","","","","","",""}; -#define MAX_SETUP_STRINGS (sizeof(setup_strings) / sizeof(char *)) +#define MAX_SETUP_STRINGS ARRAY_SIZE(setup_strings) #define SETUP_BUFFER_SIZE 200 static char setup_buffer[SETUP_BUFFER_SIZE]; static char setup_used[MAX_SETUP_STRINGS]; @@ -709,7 +709,7 @@ request_synchronous (int host, int targe printk (KERN_ALERT "target %d is host ID\n", target); return -1; } - else if (target > h->max_id) { + else if (target >= h->max_id) { printk (KERN_ALERT "target %d exceeds maximum of %d\n", target, h->max_id); return -1; @@ -2190,15 +2190,15 @@ static const struct { */ -static void +static void synchronous (struct Scsi_Host *host, int target, char *msg) { struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; int desire, divisor, i, limit; unsigned char scntl3, sxfer; /* The diagnostic message fits on one line, even with max. width integers */ - char buf[80]; - + char buf[80]; + /* Desired transfer clock in Hz */ desire = 1000000000L / (msg[3] * 4); /* Scale the available SCSI clock by 10 so we get tenths */ @@ -2209,14 +2209,14 @@ synchronous (struct Scsi_Host *host, int msg[4] = 8; if (hostdata->options & OPTION_DEBUG_SDTR) - printk("scsi%d : optimal synchronous divisor of %d.%01d\n", + printk("scsi%d : optimal synchronous divisor of %d.%01d\n", host->host_no, divisor / 10, divisor % 10); - limit = (sizeof(syncs) / sizeof(syncs[0]) -1); + limit = ARRAY_SIZE(syncs) - 1; for (i = 0; (i < limit) && (divisor > syncs[i].div); ++i); if (hostdata->options & OPTION_DEBUG_SDTR) - printk("scsi%d : selected synchronous divisor of %d.%01d\n", + printk("scsi%d : selected synchronous divisor of %d.%01d\n", host->host_no, syncs[i].div / 10, syncs[i].div % 10); msg[3] = ((1000000000L / hostdata->scsi_clock) * syncs[i].div / 10 / 4); @@ -3622,7 +3622,7 @@ #endif #ifdef LINUX_1_2 || cmd->device->id > 7 #else - || cmd->device->id > host->max_id + || cmd->device->id >= host->max_id #endif || cmd->device->id == host->this_id || hostdata->state == STATE_DISABLED) { diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index a480a37..c84b02a 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -532,6 +532,16 @@ config SCSI_PDC_ADMA If unsure, say N. +config SCSI_HPTIOP + tristate "HighPoint RocketRAID 3xxx Controller support" + depends on SCSI && PCI + help + This option enables support for HighPoint RocketRAID 3xxx + controllers. + + To compile this driver as a module, choose M here; the module + will be called hptiop. If unsure, say N. + config SCSI_SATA_QSTOR tristate "Pacific Digital SATA QStor support" depends on SCSI_SATA && PCI @@ -1159,7 +1169,7 @@ config SCSI_NCR_Q720 you do not have this SCSI card, so say N. config SCSI_NCR53C8XX_DEFAULT_TAGS - int " default tagged command queue depth" + int "default tagged command queue depth" depends on SCSI_ZALON || SCSI_NCR_Q720 default "8" ---help--- @@ -1185,7 +1195,7 @@ config SCSI_NCR53C8XX_DEFAULT_TAGS There is no safe option other than using good SCSI devices. config SCSI_NCR53C8XX_MAX_TAGS - int " maximum number of queued commands" + int "maximum number of queued commands" depends on SCSI_ZALON || SCSI_NCR_Q720 default "32" ---help--- @@ -1202,7 +1212,7 @@ config SCSI_NCR53C8XX_MAX_TAGS There is no safe option and the default answer is recommended. config SCSI_NCR53C8XX_SYNC - int " synchronous transfers frequency in MHz" + int "synchronous transfers frequency in MHz" depends on SCSI_ZALON || SCSI_NCR_Q720 default "20" ---help--- @@ -1236,7 +1246,7 @@ config SCSI_NCR53C8XX_SYNC terminations and SCSI conformant devices. config SCSI_NCR53C8XX_PROFILE - bool " enable profiling" + bool "enable profiling" depends on SCSI_ZALON || SCSI_NCR_Q720 help This option allows you to enable profiling information gathering. @@ -1247,7 +1257,7 @@ config SCSI_NCR53C8XX_PROFILE The normal answer therefore is N. config SCSI_NCR53C8XX_NO_DISCONNECT - bool " not allow targets to disconnect" + bool "not allow targets to disconnect" depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0 help This option is only provided for safety if you suspect some SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 81803a1..ebd0cf0 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -33,7 +33,8 @@ obj-$(CONFIG_SCSI_FC_ATTRS) += scsi_tra obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o -obj-$(CONFIG_ISCSI_TCP) += iscsi_tcp.o +obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o +obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o obj-$(CONFIG_SCSI_AMIGA7XX) += amiga7xx.o 53c7xx.o obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o @@ -136,6 +137,7 @@ obj-$(CONFIG_SCSI_SATA_NV) += libata.o s obj-$(CONFIG_SCSI_SATA_ULI) += libata.o sata_uli.o obj-$(CONFIG_SCSI_SATA_MV) += libata.o sata_mv.o obj-$(CONFIG_SCSI_PDC_ADMA) += libata.o pdc_adma.o +obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o obj-$(CONFIG_ARM) += arm/ @@ -164,7 +166,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m) zalon7xx-objs := zalon.o ncr53c8xx.o NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o -libata-objs := libata-core.o libata-scsi.o libata-bmdma.o +libata-objs := libata-core.o libata-scsi.o libata-bmdma.o libata-eh.o oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o # Files generated that shall be removed upon make clean diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 9f0ddbe..75f2f7a 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -296,7 +296,7 @@ static __inline__ void initialize_SCp(Sc */ if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *) cmd->buffer; + cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+ cmd->SCp.buffer->offset; @@ -500,7 +500,7 @@ #endif /* * Function : int should_disconnect (unsigned char cmd) * - * Purpose : decide weather a command would normally disconnect or + * Purpose : decide whether a command would normally disconnect or * not, since if it won't disconnect we should go to sleep. * * Input : cmd - opcode of SCSI command diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index ae37d3a..8472c53 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -213,16 +213,16 @@ static void *addresses[] = { (void *) 0xd8000, (void *) 0xc8000 }; -#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) +#define ADDRESS_COUNT ARRAY_SIZE(addresses) #endif /* USE_BIOS */ /* possible i/o port addresses */ static unsigned short ports[] = { 0x230, 0x330, 0x280, 0x290, 0x330, 0x340, 0x300, 0x310, 0x348, 0x350 }; -#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short )) +#define PORT_COUNT ARRAY_SIZE(ports) /* possible interrupt channels */ static unsigned short intrs[] = { 10, 11, 12, 15 }; -#define INTR_COUNT (sizeof( intrs ) / sizeof( unsigned short )) +#define INTR_COUNT ARRAY_SIZE(intrs) /* signatures for NCR 53c406a based controllers */ #if USE_BIOS @@ -236,7 +236,7 @@ struct signature { { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82},}; -#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) +#define SIGNATURE_COUNT ARRAY_SIZE(signatures) #endif /* USE_BIOS */ /* ============================================================ */ diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 642a3b4..83b5c7d 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -148,6 +148,8 @@ static int nondasd = -1; static int dacmode = -1; static int commit = -1; +int startup_timeout = 180; +int aif_timeout = 120; module_param(nondasd, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); @@ -155,6 +157,10 @@ module_param(dacmode, int, S_IRUGO|S_IWU MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on"); module_param(commit, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on"); +module_param(startup_timeout, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for adapter to have it's kernel up and\nrunning. This is typically adjusted for large systems that do not have a BIOS."); +module_param(aif_timeout, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(aif_timeout, "The duration of time in seconds to wait for applications to pick up AIFs before\nderegistering them. This is typically adjusted for heavily burdened systems."); int numacb = -1; module_param(numacb, int, S_IRUGO|S_IWUSR); @@ -390,8 +396,7 @@ static void get_container_name_callback( scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); - if (fibptr == NULL) - BUG(); + BUG_ON(fibptr == NULL); get_name_reply = (struct aac_get_name_resp *) fib_data(fibptr); /* Failure is irrelevant, using default value instead */ @@ -635,13 +640,13 @@ static void setinqstr(struct aac_dev *de cp[sizeof(str->pid)] = c; } else { struct aac_driver_ident *mp = aac_get_driver_ident(dev->cardtype); - - inqstrcpy (mp->vname, str->vid); + + inqstrcpy (mp->vname, str->vid); /* last six chars reserved for vol type */ inqstrcpy (mp->model, str->pid); } - if (tindex < (sizeof(container_types)/sizeof(char *))){ + if (tindex < ARRAY_SIZE(container_types)){ char *findit = str->pid; for ( ; *findit != ' '; findit++); /* walk till we find a space */ @@ -950,12 +955,11 @@ static void io_callback(void *context, s smp_processor_id(), (unsigned long long)lba, jiffies); } - if (fibptr == NULL) - BUG(); + BUG_ON(fibptr == NULL); if(scsicmd->use_sg) pci_unmap_sg(dev->pdev, - (struct scatterlist *)scsicmd->buffer, + (struct scatterlist *)scsicmd->request_buffer, scsicmd->use_sg, scsicmd->sc_data_direction); else if(scsicmd->request_bufflen) @@ -1086,8 +1090,7 @@ static int aac_read(struct scsi_cmnd * s aac_build_sgraw(scsicmd, &readcmd->sg); fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw)); - if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) - BUG(); + BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))); /* * Now send the Fib to the adapter */ @@ -1255,8 +1258,7 @@ static int aac_write(struct scsi_cmnd * aac_build_sgraw(scsicmd, &writecmd->sg); fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw)); - if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) - BUG(); + BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))); /* * Now send the Fib to the adapter */ @@ -1570,7 +1572,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsi * see: .c i.e. aac.c */ if (scmd_id(scsicmd) == host->this_id) { - setinqstr(dev, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *))); + setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types)); inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */ aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; @@ -1898,8 +1900,7 @@ static void aac_srb_callback(void *conte scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; dev = (struct aac_dev *)scsicmd->device->host->hostdata; - if (fibptr == NULL) - BUG(); + BUG_ON(fibptr == NULL); srbreply = (struct aac_srb_reply *) fib_data(fibptr); @@ -1913,7 +1914,7 @@ static void aac_srb_callback(void *conte if(scsicmd->use_sg) pci_unmap_sg(dev->pdev, - (struct scatterlist *)scsicmd->buffer, + (struct scatterlist *)scsicmd->request_buffer, scsicmd->use_sg, scsicmd->sc_data_direction); else if(scsicmd->request_bufflen) @@ -2218,15 +2219,15 @@ static unsigned long aac_build_sg(struct } } else if(scsicmd->request_bufflen) { - dma_addr_t addr; - addr = pci_map_single(dev->pdev, + u32 addr; + scsicmd->SCp.dma_handle = pci_map_single(dev->pdev, scsicmd->request_buffer, scsicmd->request_bufflen, scsicmd->sc_data_direction); + addr = scsicmd->SCp.dma_handle; psg->count = cpu_to_le32(1); psg->sg[0].addr = cpu_to_le32(addr); psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); - scsicmd->SCp.dma_handle = addr; byte_count = scsicmd->request_bufflen; } return byte_count; @@ -2375,7 +2376,7 @@ static struct aac_srb_status_info srb_st { SRB_STATUS_SUCCESS, "Success"}, { SRB_STATUS_ABORTED, "Aborted Command"}, { SRB_STATUS_ABORT_FAILED, "Abort Failed"}, - { SRB_STATUS_ERROR, "Error Event"}, + { SRB_STATUS_ERROR, "Error Event"}, { SRB_STATUS_BUSY, "Device Busy"}, { SRB_STATUS_INVALID_REQUEST, "Invalid Request"}, { SRB_STATUS_INVALID_PATH_ID, "Invalid Path ID"}, @@ -2394,7 +2395,7 @@ static struct aac_srb_status_info srb_st { SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"}, { SRB_STATUS_REQUEST_FLUSHED, "Request Flushed"}, { SRB_STATUS_DELAYED_RETRY, "Delayed Retry"}, - { SRB_STATUS_INVALID_LUN, "Invalid LUN"}, + { SRB_STATUS_INVALID_LUN, "Invalid LUN"}, { SRB_STATUS_INVALID_TARGET_ID, "Invalid TARGET ID"}, { SRB_STATUS_BAD_FUNCTION, "Bad Function"}, { SRB_STATUS_ERROR_RECOVERY, "Error Recovery"}, @@ -2409,11 +2410,9 @@ char *aac_get_status_string(u32 status) { int i; - for(i=0; i < (sizeof(srb_status_info)/sizeof(struct aac_srb_status_info)); i++ ){ - if(srb_status_info[i].status == status){ + for (i = 0; i < ARRAY_SIZE(srb_status_info); i++) + if (srb_status_info[i].status == status) return srb_status_info[i].str; - } - } return "Bad Status Code"; } diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index f773b0d..d0eecd4 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -12,7 +12,7 @@ #define nblank(x) _nblank(x)[0] #ifndef AAC_DRIVER_BUILD # define AAC_DRIVER_BUILD 2409 -# define AAC_DRIVER_BRANCH "-mh1" +# define AAC_DRIVER_BRANCH "-mh2" #endif #define MAXIMUM_NUM_CONTAINERS 32 @@ -563,7 +563,6 @@ struct aac_queue { spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ /* only valid for command queues which receive entries from the adapter. */ - struct list_head pendingq; /* A queue of outstanding fib's to the adapter. */ u32 numpending; /* Number of entries on outstanding queue. */ struct aac_dev * dev; /* Back pointer to adapter structure */ }; @@ -823,11 +822,6 @@ struct fib { void *callback_data; u32 flags; // u32 dmb was ulong /* - * The following is used to put this fib context onto the - * Outstanding I/O queue. - */ - struct list_head queue; - /* * And for the internal issue/reply queues (we may be able * to merge these two) */ @@ -1815,3 +1809,5 @@ int aac_probe_container(struct aac_dev * extern int numacb; extern int acbsize; extern char aac_driver_version[]; +extern int startup_timeout; +extern int aif_timeout; diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 9f75144..255421d 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -535,7 +535,7 @@ static int aac_send_raw_srb(struct aac_d default: data_dir = DMA_NONE; } - if (user_srbcmd->sg.count > (sizeof(sg_list)/sizeof(sg_list[0]))) { + if (user_srbcmd->sg.count > ARRAY_SIZE(sg_list)) { dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n", le32_to_cpu(srbcmd->sg.count))); rcode = -EINVAL; diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 1939745..7cea514 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -103,9 +103,12 @@ static int aac_alloc_comm(struct aac_dev * This assumes the memory is mapped zero->n, which isnt * always true on real computers. It also has some slight problems * with the GART on x86-64. I've btw never tried DMA from PCI space - * on this platform but don't be suprised if its problematic. + * on this platform but don't be surprised if its problematic. + * [AK: something is very very wrong when a driver tests this symbol. + * Someone should figure out what the comment writer really meant here and fix + * the code. Or just remove that bad code. ] */ -#ifndef CONFIG_GART_IOMMU +#ifndef CONFIG_IOMMU if ((num_physpages << (PAGE_SHIFT - 12)) <= AAC_MAX_HOSTPHYSMEMPAGES) { init->HostPhysMemPages = cpu_to_le32(num_physpages << (PAGE_SHIFT-12)); @@ -159,7 +162,6 @@ static void aac_queue_init(struct aac_de { q->numpending = 0; q->dev = dev; - INIT_LIST_HEAD(&q->pendingq); init_waitqueue_head(&q->cmdready); INIT_LIST_HEAD(&q->cmdq); init_waitqueue_head(&q->qfull); diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 9f9f4aa..3f27419 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -229,8 +229,7 @@ void aac_fib_init(struct fib *fibptr) static void fib_dealloc(struct fib * fibptr) { struct hw_fib *hw_fib = fibptr->hw_fib; - if(hw_fib->header.StructType != FIB_MAGIC) - BUG(); + BUG_ON(hw_fib->header.StructType != FIB_MAGIC); hw_fib->header.XferState = 0; } @@ -472,7 +471,6 @@ int aac_fib_send(u16 command, struct fib spin_lock_irqsave(q->lock, qflags); if (dev->new_comm_interface) { unsigned long count = 10000000L; /* 50 seconds */ - list_add_tail(&fibptr->queue, &q->pendingq); q->numpending++; spin_unlock_irqrestore(q->lock, qflags); while (aac_adapter_send(fibptr) != 0) { @@ -481,7 +479,6 @@ int aac_fib_send(u16 command, struct fib spin_unlock_irqrestore(&fibptr->event_lock, flags); spin_lock_irqsave(q->lock, qflags); q->numpending--; - list_del(&fibptr->queue); spin_unlock_irqrestore(q->lock, qflags); return -ETIMEDOUT; } @@ -492,7 +489,6 @@ int aac_fib_send(u16 command, struct fib unsigned long nointr = 0; aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr); - list_add_tail(&fibptr->queue, &q->pendingq); q->numpending++; *(q->headers.producer) = cpu_to_le32(index + 1); spin_unlock_irqrestore(q->lock, qflags); @@ -520,7 +516,6 @@ int aac_fib_send(u16 command, struct fib if (--count == 0) { spin_lock_irqsave(q->lock, qflags); q->numpending--; - list_del(&fibptr->queue); spin_unlock_irqrestore(q->lock, qflags); if (wait == -1) { printk(KERN_ERR "aacraid: aac_fib_send: first asynchronous command timed out.\n" @@ -534,8 +529,7 @@ int aac_fib_send(u16 command, struct fib } } else down(&fibptr->event_wait); - if(fibptr->done == 0) - BUG(); + BUG_ON(fibptr->done == 0); if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){ return -ETIMEDOUT; @@ -1214,7 +1208,7 @@ int aac_command_thread(void *data) * since the last read off * the queue? */ - if ((time_now - time_last) > 120) { + if ((time_now - time_last) > aif_timeout) { entry = entry->next; aac_close_fib_context(dev, fibctx); continue; diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index f6bcb94..b2a5c72 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -85,10 +85,9 @@ unsigned int aac_response_normal(struct * continue. The caller has already been notified that * the fib timed out. */ - if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { - list_del(&fib->queue); + if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) dev->queues->queue[AdapNormCmdQueue].numpending--; - } else { + else { printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags); printk(KERN_DEBUG"aacraid: hwfib=%p fib index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib); continue; @@ -284,7 +283,6 @@ unsigned int aac_intr_normal(struct aac_ return 0; } - list_del(&fib->queue); dev->queues->queue[AdapNormCmdQueue].numpending--; if (fast) { diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 6ef89c9..e42a479 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -119,7 +119,7 @@ static struct pci_device_id aac_pci_tbl[ { 0x9005, 0x0286, 0x9005, 0x029f, 0, 0, 26 }, /* ICP9014R0 (Lancer) */ { 0x9005, 0x0286, 0x9005, 0x02a0, 0, 0, 27 }, /* ICP9047MA (Lancer) */ { 0x9005, 0x0286, 0x9005, 0x02a1, 0, 0, 28 }, /* ICP9087MA (Lancer) */ - { 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5085AU (Hurricane) */ + { 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5445AU (Hurricane44) */ { 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */ { 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */ { 0x9005, 0x0286, 0x9005, 0x02a6, 0, 0, 32 }, /* ICP9067MA (Intruder-6) */ @@ -143,7 +143,7 @@ static struct pci_device_id aac_pci_tbl[ { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000SAS (BlackBird) */ { 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */ { 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */ - { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-4810SAS (Hurricane */ + { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-3800SAS (Hurricane44) */ { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/ { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/ @@ -195,7 +195,7 @@ static struct aac_driver_ident aac_drive { aac_rkt_init, "aacraid", "ICP ", "ICP9014R0 ", 1 }, /* ICP9014R0 (Lancer) */ { aac_rkt_init, "aacraid", "ICP ", "ICP9047MA ", 1 }, /* ICP9047MA (Lancer) */ { aac_rkt_init, "aacraid", "ICP ", "ICP9087MA ", 1 }, /* ICP9087MA (Lancer) */ - { aac_rkt_init, "aacraid", "ICP ", "ICP5085AU ", 1 }, /* ICP5085AU (Hurricane) */ + { aac_rkt_init, "aacraid", "ICP ", "ICP5445AU ", 1 }, /* ICP5445AU (Hurricane44) */ { aac_rx_init, "aacraid", "ICP ", "ICP9085LI ", 1 }, /* ICP9085LI (Marauder-X) */ { aac_rx_init, "aacraid", "ICP ", "ICP5085BR ", 1 }, /* ICP5085BR (Marauder-E) */ { aac_rkt_init, "aacraid", "ICP ", "ICP9067MA ", 1 }, /* ICP9067MA (Intruder-6) */ @@ -217,7 +217,7 @@ static struct aac_driver_ident aac_drive { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4000SAS ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4800SAS ", 1 }, /* ASR-4800SAS (Marauder-X) */ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-4805SAS ", 1 }, /* ASR-4805SAS (Marauder-E) */ - { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-4810SAS ", 1 }, /* ASR-4810SAS (Hurricane) */ + { aac_rkt_init, "aacraid", "ADAPTEC ", "ASR-3800SAS ", 1 }, /* ASR-3800SAS (Hurricane44) */ { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/ { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/ @@ -453,15 +453,10 @@ static int aac_eh_reset(struct scsi_cmnd printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", AAC_DRIVERNAME); - - - spin_lock_irq(host->host_lock); - aac = (struct aac_dev *)host->hostdata; if (aac_adapter_check_health(aac)) { printk(KERN_ERR "%s: Host adapter appears dead\n", AAC_DRIVERNAME); - spin_unlock_irq(host->host_lock); return -ENODEV; } /* @@ -487,13 +482,10 @@ static int aac_eh_reset(struct scsi_cmnd /* * We can exit If all the commands are complete */ - spin_unlock_irq(host->host_lock); if (active == 0) return SUCCESS; ssleep(1); - spin_lock_irq(host->host_lock); } - spin_unlock_irq(host->host_lock); printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); return -ETIMEDOUT; } @@ -572,7 +564,7 @@ static long aac_compat_do_ioctl(struct a f = compat_alloc_user_space(sizeof(*f)); ret = 0; - if (clear_user(f, sizeof(*f)) != sizeof(*f)) + if (clear_user(f, sizeof(*f))) ret = -EFAULT; if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32))) ret = -EFAULT; diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 7a23e02..5b52966 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -444,14 +444,14 @@ int aac_rkt_init(struct aac_dev *dev) */ while (!(rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_UP_AND_RUNNING)) { - if(time_after(jiffies, start+180*HZ)) + if(time_after(jiffies, start+startup_timeout*HZ)) { status = rkt_readl(dev, MUnit.OMRx[0]); printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", dev->name, instance, status); goto error_iounmap; } - schedule_timeout_uninterruptible(1); + msleep(1); } if (request_irq(dev->scsi_host_ptr->irq, aac_rkt_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) { diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 729b9eb..9dadfb2 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -444,14 +444,14 @@ int aac_rx_init(struct aac_dev *dev) while ((!(rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) || (!(rx_readl(dev, MUnit.OMRx[0]) & KERNEL_UP_AND_RUNNING))) { - if(time_after(jiffies, start+180*HZ)) + if(time_after(jiffies, start+startup_timeout*HZ)) { status = rx_readl(dev, IndexRegs.Mailbox[7]); printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", dev->name, instance, status); goto error_iounmap; } - schedule_timeout_uninterruptible(1); + msleep(1); } if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) { diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index a534549..88d400f 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c @@ -66,11 +66,11 @@ static irqreturn_t aac_sa_intr(int irq, sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */ sa_writew(dev, DoorbellReg_s, PrintfDone); } else if (intstat & DOORBELL_1) { // dev -> Host Normal Command Ready - aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); sa_writew(dev, DoorbellClrReg_p, DOORBELL_1); + aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); } else if (intstat & DOORBELL_2) { // dev -> Host Normal Response Ready - aac_response_normal(&dev->queues->queue[HostNormRespQueue]); sa_writew(dev, DoorbellClrReg_p, DOORBELL_2); + aac_response_normal(&dev->queues->queue[HostNormRespQueue]); } else if (intstat & DOORBELL_3) { // dev -> Host Normal Command Not Full sa_writew(dev, DoorbellClrReg_p, DOORBELL_3); } else if (intstat & DOORBELL_4) { // dev -> Host Normal Response Not Full @@ -318,13 +318,13 @@ int aac_sa_init(struct aac_dev *dev) * Wait for the adapter to be up and running. Wait up to 3 minutes. */ while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) { - if (time_after(jiffies, start+180*HZ)) { + if (time_after(jiffies, start+startup_timeout*HZ)) { status = sa_readl(dev, Mailbox7); printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %lx.\n", name, instance, status); goto error_iounmap; } - schedule_timeout_uninterruptible(1); + msleep(1); } if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) { diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 2a41963..dd9fb3d 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -12374,7 +12374,7 @@ AscInitFromEEP(ASC_DVC_VAR *asc_dvc) ASC_PRINT1( "AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n", i); } else { - ASC_PRINT("AscInitFromEEP: Succesfully re-wrote EEPROM."); + ASC_PRINT("AscInitFromEEP: Successfully re-wrote EEPROM.\n"); } } return (warn_code); @@ -17316,7 +17316,7 @@ AdvWaitEEPCmd(AdvPortAddr iop_base) /* * Write the EEPROM from 'cfg_buf'. */ -void +void __init AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) { ushort *wbuf; @@ -17383,7 +17383,7 @@ AdvSet3550EEPConfig(AdvPortAddr iop_base /* * Write the EEPROM from 'cfg_buf'. */ -void +void __init AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) { @@ -17451,7 +17451,7 @@ AdvSet38C0800EEPConfig(AdvPortAddr iop_b /* * Write the EEPROM from 'cfg_buf'. */ -void +void __init AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) { diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 51bad7a..86c6bd2 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -1011,7 +1011,7 @@ static int __init do_setup(char *str) int count=setup_idx; - get_options(str, sizeof(ints)/sizeof(int), ints); + get_options(str, ARRAY_SIZE(ints), ints); aha1542_setup(str,ints); return count #include #define DRV_NAME "ahci" -#define DRV_VERSION "1.2" +#define DRV_VERSION "1.3" enum { @@ -56,12 +56,15 @@ enum { AHCI_MAX_SG = 168, /* hardware max is 64K */ AHCI_DMA_BOUNDARY = 0xffffffff, AHCI_USE_CLUSTERING = 0, - AHCI_CMD_SLOT_SZ = 32 * 32, + AHCI_MAX_CMDS = 32, + AHCI_CMD_SZ = 32, + AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ, AHCI_RX_FIS_SZ = 256, - AHCI_CMD_TBL_HDR = 0x80, AHCI_CMD_TBL_CDB = 0x40, - AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16), - AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ + + AHCI_CMD_TBL_HDR_SZ = 0x80, + AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16), + AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS, + AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + AHCI_RX_FIS_SZ, AHCI_IRQ_ON_SG = (1 << 31), AHCI_CMD_ATAPI = (1 << 5), @@ -71,8 +74,10 @@ enum { AHCI_CMD_CLR_BUSY = (1 << 10), RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ + RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ board_ahci = 0, + board_ahci_vt8251 = 1, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -87,8 +92,9 @@ enum { HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ /* HOST_CAP bits */ - HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */ + HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ + HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ /* registers for each SATA port */ PORT_LST_ADDR = 0x00, /* command list DMA addr */ @@ -127,15 +133,17 @@ enum { PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */ PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */ - PORT_IRQ_FATAL = PORT_IRQ_TF_ERR | - PORT_IRQ_HBUS_ERR | - PORT_IRQ_HBUS_DATA_ERR | - PORT_IRQ_IF_ERR, - DEF_PORT_IRQ = PORT_IRQ_FATAL | PORT_IRQ_PHYRDY | - PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE | - PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS | - PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS | - PORT_IRQ_D2H_REG_FIS, + PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR | + PORT_IRQ_IF_ERR | + PORT_IRQ_CONNECT | + PORT_IRQ_PHYRDY | + PORT_IRQ_UNK_FIS, + PORT_IRQ_ERROR = PORT_IRQ_FREEZE | + PORT_IRQ_TF_ERR | + PORT_IRQ_HBUS_DATA_ERR, + DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | + PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | + PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS, /* PORT_CMD bits */ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ @@ -153,6 +161,10 @@ enum { /* hpriv->flags bits */ AHCI_FLAG_MSI = (1 << 0), + + /* ap->flags bits */ + AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24), + AHCI_FLAG_NO_NCQ = (1 << 25), }; struct ahci_cmd_hdr { @@ -181,7 +193,6 @@ struct ahci_port_priv { dma_addr_t cmd_slot_dma; void *cmd_tbl; dma_addr_t cmd_tbl_dma; - struct ahci_sg *cmd_tbl_sg; void *rx_fis; dma_addr_t rx_fis_dma; }; @@ -191,15 +202,16 @@ static void ahci_scr_write (struct ata_p static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs); -static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes); static void ahci_irq_clear(struct ata_port *ap); -static void ahci_eng_timeout(struct ata_port *ap); static int ahci_port_start(struct ata_port *ap); static void ahci_port_stop(struct ata_port *ap); static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static void ahci_qc_prep(struct ata_queued_cmd *qc); static u8 ahci_check_status(struct ata_port *ap); -static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); +static void ahci_freeze(struct ata_port *ap); +static void ahci_thaw(struct ata_port *ap); +static void ahci_error_handler(struct ata_port *ap); +static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); static void ahci_remove_one (struct pci_dev *pdev); static struct scsi_host_template ahci_sht = { @@ -207,7 +219,8 @@ static struct scsi_host_template ahci_sh .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, + .change_queue_depth = ata_scsi_change_queue_depth, + .can_queue = AHCI_MAX_CMDS - 1, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = AHCI_MAX_SG, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, @@ -216,6 +229,7 @@ static struct scsi_host_template ahci_sh .proc_name = DRV_NAME, .dma_boundary = AHCI_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -228,19 +242,21 @@ static const struct ata_port_operations .tf_read = ahci_tf_read, - .probe_reset = ahci_probe_reset, - .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, - .eng_timeout = ahci_eng_timeout, - .irq_handler = ahci_interrupt, .irq_clear = ahci_irq_clear, .scr_read = ahci_scr_read, .scr_write = ahci_scr_write, + .freeze = ahci_freeze, + .thaw = ahci_thaw, + + .error_handler = ahci_error_handler, + .post_internal_cmd = ahci_post_internal_cmd, + .port_start = ahci_port_start, .port_stop = ahci_port_stop, }; @@ -250,7 +266,19 @@ static const struct ata_port_info ahci_p { .sht = &ahci_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + ATA_FLAG_SKIP_D2H_BSY, + .pio_mask = 0x1f, /* pio0-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &ahci_ops, + }, + /* board_ahci_vt8251 */ + { + .sht = &ahci_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + ATA_FLAG_SKIP_D2H_BSY | + AHCI_FLAG_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, @@ -258,6 +286,7 @@ static const struct ata_port_info ahci_p }; static const struct pci_device_id ahci_pci_tbl[] = { + /* Intel */ { PCI_VENDOR_ID_INTEL, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ICH6 */ { PCI_VENDOR_ID_INTEL, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, @@ -288,14 +317,39 @@ static const struct pci_device_id ahci_p board_ahci }, /* ICH8M */ { PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ICH8M */ + + /* JMicron */ { 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB360 */ + { 0x197b, 0x2361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* JMicron JMB361 */ { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB363 */ + { 0x197b, 0x2365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* JMicron JMB365 */ + { 0x197b, 0x2366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* JMicron JMB366 */ + + /* ATI */ { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ATI SB600 non-raid */ { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* ATI SB600 raid */ + + /* VIA */ + { PCI_VENDOR_ID_VIA, 0x3349, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci_vt8251 }, /* VIA VT8251 */ + + /* NVIDIA */ + { PCI_VENDOR_ID_NVIDIA, 0x044c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { PCI_VENDOR_ID_NVIDIA, 0x044d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { PCI_VENDOR_ID_NVIDIA, 0x044e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { PCI_VENDOR_ID_NVIDIA, 0x044f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* MCP65 */ + { } /* terminate list */ }; @@ -374,8 +428,6 @@ static int ahci_port_start(struct ata_po pp->cmd_tbl = mem; pp->cmd_tbl_dma = mem_dma; - pp->cmd_tbl_sg = mem + AHCI_CMD_TBL_HDR; - ap->private_data = pp; if (hpriv->cap & HOST_CAP_64) @@ -508,46 +560,71 @@ static unsigned int ahci_dev_classify(st return ata_dev_classify(&tf); } -static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) +static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, + u32 opts) { - pp->cmd_slot[0].opts = cpu_to_le32(opts); - pp->cmd_slot[0].status = 0; - pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff); - pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); + dma_addr_t cmd_tbl_dma; + + cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ; + + pp->cmd_slot[tag].opts = cpu_to_le32(opts); + pp->cmd_slot[tag].status = 0; + pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff); + pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16); } -static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val, - unsigned long interval_msec, - unsigned long timeout_msec) +static int ahci_clo(struct ata_port *ap) { - unsigned long timeout; + void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; + struct ahci_host_priv *hpriv = ap->host_set->private_data; u32 tmp; - timeout = jiffies + (timeout_msec * HZ) / 1000; - do { - tmp = readl(reg); - if ((tmp & mask) == val) - return 0; - msleep(interval_msec); - } while (time_before(jiffies, timeout)); + if (!(hpriv->cap & HOST_CAP_CLO)) + return -EOPNOTSUPP; - return -1; + tmp = readl(port_mmio + PORT_CMD); + tmp |= PORT_CMD_CLO; + writel(tmp, port_mmio + PORT_CMD); + + tmp = ata_wait_register(port_mmio + PORT_CMD, + PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); + if (tmp & PORT_CMD_CLO) + return -EIO; + + return 0; } -static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) +static int ahci_prereset(struct ata_port *ap) +{ + if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) && + (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) { + /* ATA_BUSY hasn't cleared, so send a CLO */ + ahci_clo(ap); + } + + return ata_std_prereset(ap); +} + +static int ahci_softreset(struct ata_port *ap, unsigned int *class) { - struct ahci_host_priv *hpriv = ap->host_set->private_data; struct ahci_port_priv *pp = ap->private_data; void __iomem *mmio = ap->host_set->mmio_base; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); const u32 cmd_fis_len = 5; /* five dwords */ const char *reason = NULL; struct ata_taskfile tf; + u32 tmp; u8 *fis; int rc; DPRINTK("ENTER\n"); + if (ata_port_offline(ap)) { + DPRINTK("PHY reports no device\n"); + *class = ATA_DEV_NONE; + return 0; + } + /* prepare for SRST (AHCI-1.1 10.4.1) */ rc = ahci_stop_engine(ap); if (rc) { @@ -558,23 +635,13 @@ static int ahci_softreset(struct ata_por /* check BUSY/DRQ, perform Command List Override if necessary */ ahci_tf_read(ap, &tf); if (tf.command & (ATA_BUSY | ATA_DRQ)) { - u32 tmp; + rc = ahci_clo(ap); - if (!(hpriv->cap & HOST_CAP_CLO)) { - rc = -EIO; - reason = "port busy but no CLO"; + if (rc == -EOPNOTSUPP) { + reason = "port busy but CLO unavailable"; goto fail_restart; - } - - tmp = readl(port_mmio + PORT_CMD); - tmp |= PORT_CMD_CLO; - writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ - - if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0, - 1, 500)) { - rc = -EIO; - reason = "CLO failed"; + } else if (rc) { + reason = "port busy but CLO failed"; goto fail_restart; } } @@ -582,20 +649,21 @@ static int ahci_softreset(struct ata_por /* restart engine */ ahci_start_engine(ap); - ata_tf_init(ap, &tf, 0); + ata_tf_init(ap->device, &tf); fis = pp->cmd_tbl; /* issue the first D2H Register FIS */ - ahci_fill_cmd_slot(pp, cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY); + ahci_fill_cmd_slot(pp, 0, + cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY); tf.ctl |= ATA_SRST; ata_tf_to_fis(&tf, fis, 0); fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ writel(1, port_mmio + PORT_CMD_ISSUE); - readl(port_mmio + PORT_CMD_ISSUE); /* flush */ - if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) { + tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500); + if (tmp & 0x1) { rc = -EIO; reason = "1st FIS failed"; goto fail; @@ -605,7 +673,7 @@ static int ahci_softreset(struct ata_por msleep(1); /* issue the second D2H Register FIS */ - ahci_fill_cmd_slot(pp, cmd_fis_len); + ahci_fill_cmd_slot(pp, 0, cmd_fis_len); tf.ctl &= ~ATA_SRST; ata_tf_to_fis(&tf, fis, 0); @@ -625,7 +693,7 @@ static int ahci_softreset(struct ata_por msleep(150); *class = ATA_DEV_NONE; - if (sata_dev_present(ap)) { + if (ata_port_online(ap)) { if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { rc = -EIO; reason = "device not ready"; @@ -640,25 +708,31 @@ static int ahci_softreset(struct ata_por fail_restart: ahci_start_engine(ap); fail: - if (verbose) - printk(KERN_ERR "ata%u: softreset failed (%s)\n", - ap->id, reason); - else - DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason); + ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); return rc; } -static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) +static int ahci_hardreset(struct ata_port *ap, unsigned int *class) { + struct ahci_port_priv *pp = ap->private_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + struct ata_taskfile tf; int rc; DPRINTK("ENTER\n"); ahci_stop_engine(ap); - rc = sata_std_hardreset(ap, verbose, class); + + /* clear D2H reception area to properly wait for D2H FIS */ + ata_tf_init(ap->device, &tf); + tf.command = 0xff; + ata_tf_to_fis(&tf, d2h_fis, 0); + + rc = sata_std_hardreset(ap, class); + ahci_start_engine(ap); - if (rc == 0) + if (rc == 0 && ata_port_online(ap)) *class = ahci_dev_classify(ap); if (*class == ATA_DEV_UNKNOWN) *class = ATA_DEV_NONE; @@ -686,13 +760,6 @@ static void ahci_postreset(struct ata_po } } -static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes) -{ - return ata_drive_probe_reset(ap, ata_std_probeinit, - ahci_softreset, ahci_hardreset, - ahci_postreset, classes); -} - static u8 ahci_check_status(struct ata_port *ap) { void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; @@ -708,9 +775,8 @@ static void ahci_tf_read(struct ata_port ata_tf_from_fis(d2h_fis, tf); } -static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc) +static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl) { - struct ahci_port_priv *pp = qc->ap->private_data; struct scatterlist *sg; struct ahci_sg *ahci_sg; unsigned int n_sg = 0; @@ -720,7 +786,7 @@ static unsigned int ahci_fill_sg(struct /* * Next, the S/G list. */ - ahci_sg = pp->cmd_tbl_sg; + ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ; ata_for_each_sg(sg, qc) { dma_addr_t addr = sg_dma_address(sg); u32 sg_len = sg_dma_len(sg); @@ -741,6 +807,7 @@ static void ahci_qc_prep(struct ata_queu struct ata_port *ap = qc->ap; struct ahci_port_priv *pp = ap->private_data; int is_atapi = is_atapi_taskfile(&qc->tf); + void *cmd_tbl; u32 opts; const u32 cmd_fis_len = 5; /* five dwords */ unsigned int n_elem; @@ -749,16 +816,17 @@ static void ahci_qc_prep(struct ata_queu * Fill in command table information. First, the header, * a SATA Register - Host to Device command FIS. */ - ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0); + cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ; + + ata_tf_to_fis(&qc->tf, cmd_tbl, 0); if (is_atapi) { - memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); - memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, - qc->dev->cdb_len); + memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); + memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len); } n_elem = 0; if (qc->flags & ATA_QCFLAG_DMAMAP) - n_elem = ahci_fill_sg(qc); + n_elem = ahci_fill_sg(qc, cmd_tbl); /* * Fill in command slot information. @@ -769,112 +837,122 @@ static void ahci_qc_prep(struct ata_queu if (is_atapi) opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH; - ahci_fill_cmd_slot(pp, opts); + ahci_fill_cmd_slot(pp, qc->tag, opts); } -static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) +static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) { - void __iomem *mmio = ap->host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - u32 tmp; + struct ahci_port_priv *pp = ap->private_data; + struct ata_eh_info *ehi = &ap->eh_info; + unsigned int err_mask = 0, action = 0; + struct ata_queued_cmd *qc; + u32 serror; - if ((ap->device[0].class != ATA_DEV_ATAPI) || - ((irq_stat & PORT_IRQ_TF_ERR) == 0)) - printk(KERN_WARNING "ata%u: port reset, " - "p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n", - ap->id, - irq_stat, - readl(mmio + HOST_IRQ_STAT), - readl(port_mmio + PORT_IRQ_STAT), - readl(port_mmio + PORT_CMD), - readl(port_mmio + PORT_TFDATA), - readl(port_mmio + PORT_SCR_STAT), - readl(port_mmio + PORT_SCR_ERR)); - - /* stop DMA */ - ahci_stop_engine(ap); + ata_ehi_clear_desc(ehi); - /* clear SATA phy error, if any */ - tmp = readl(port_mmio + PORT_SCR_ERR); - writel(tmp, port_mmio + PORT_SCR_ERR); + /* AHCI needs SError cleared; otherwise, it might lock up */ + serror = ahci_scr_read(ap, SCR_ERROR); + ahci_scr_write(ap, SCR_ERROR, serror); - /* if DRQ/BSY is set, device needs to be reset. - * if so, issue COMRESET - */ - tmp = readl(port_mmio + PORT_TFDATA); - if (tmp & (ATA_BUSY | ATA_DRQ)) { - writel(0x301, port_mmio + PORT_SCR_CTL); - readl(port_mmio + PORT_SCR_CTL); /* flush */ - udelay(10); - writel(0x300, port_mmio + PORT_SCR_CTL); - readl(port_mmio + PORT_SCR_CTL); /* flush */ + /* analyze @irq_stat */ + ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); + + if (irq_stat & PORT_IRQ_TF_ERR) + err_mask |= AC_ERR_DEV; + + if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) { + err_mask |= AC_ERR_HOST_BUS; + action |= ATA_EH_SOFTRESET; } - /* re-start DMA */ - ahci_start_engine(ap); -} + if (irq_stat & PORT_IRQ_IF_ERR) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi, ", interface fatal error"); + } -static void ahci_eng_timeout(struct ata_port *ap) -{ - struct ata_host_set *host_set = ap->host_set; - void __iomem *mmio = host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - struct ata_queued_cmd *qc; - unsigned long flags; + if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) { + ata_ehi_hotplugged(ehi); + ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ? + "connection status changed" : "PHY RDY changed"); + } + + if (irq_stat & PORT_IRQ_UNK_FIS) { + u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK); - printk(KERN_WARNING "ata%u: handling error/timeout\n", ap->id); + err_mask |= AC_ERR_HSM; + action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi, ", unknown FIS %08x %08x %08x %08x", + unk[0], unk[1], unk[2], unk[3]); + } - spin_lock_irqsave(&host_set->lock, flags); + /* okay, let's hand over to EH */ + ehi->serror |= serror; + ehi->action |= action; - ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT)); qc = ata_qc_from_tag(ap, ap->active_tag); - qc->err_mask |= AC_ERR_TIMEOUT; - - spin_unlock_irqrestore(&host_set->lock, flags); + if (qc) + qc->err_mask |= err_mask; + else + ehi->err_mask |= err_mask; - ata_eh_qc_complete(qc); + if (irq_stat & PORT_IRQ_FREEZE) + ata_port_freeze(ap); + else + ata_port_abort(ap); } -static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) +static void ahci_host_intr(struct ata_port *ap) { void __iomem *mmio = ap->host_set->mmio_base; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - u32 status, serr, ci; - - serr = readl(port_mmio + PORT_SCR_ERR); - writel(serr, port_mmio + PORT_SCR_ERR); + struct ata_eh_info *ehi = &ap->eh_info; + u32 status, qc_active; + int rc; status = readl(port_mmio + PORT_IRQ_STAT); writel(status, port_mmio + PORT_IRQ_STAT); - ci = readl(port_mmio + PORT_CMD_ISSUE); - if (likely((ci & 0x1) == 0)) { - if (qc) { - WARN_ON(qc->err_mask); - ata_qc_complete(qc); - qc = NULL; - } + if (unlikely(status & PORT_IRQ_ERROR)) { + ahci_error_intr(ap, status); + return; } - if (status & PORT_IRQ_FATAL) { - unsigned int err_mask; - if (status & PORT_IRQ_TF_ERR) - err_mask = AC_ERR_DEV; - else if (status & PORT_IRQ_IF_ERR) - err_mask = AC_ERR_ATA_BUS; - else - err_mask = AC_ERR_HOST_BUS; - - /* command processing has stopped due to error; restart */ - ahci_restart_port(ap, status); - - if (qc) { - qc->err_mask |= err_mask; - ata_qc_complete(qc); - } + if (ap->sactive) + qc_active = readl(port_mmio + PORT_SCR_ACT); + else + qc_active = readl(port_mmio + PORT_CMD_ISSUE); + + rc = ata_qc_complete_multiple(ap, qc_active, NULL); + if (rc > 0) + return; + if (rc < 0) { + ehi->err_mask |= AC_ERR_HSM; + ehi->action |= ATA_EH_SOFTRESET; + ata_port_freeze(ap); + return; + } + + /* hmmm... a spurious interupt */ + + /* some devices send D2H reg with I bit set during NCQ command phase */ + if (ap->sactive && status & PORT_IRQ_D2H_REG_FIS) + return; + + /* ignore interim PIO setup fis interrupts */ + if (ata_tag_valid(ap->active_tag)) { + struct ata_queued_cmd *qc = + ata_qc_from_tag(ap, ap->active_tag); + + if (qc && qc->tf.protocol == ATA_PROT_PIO && + (status & PORT_IRQ_PIOS_FIS)) + return; } - return 1; + if (ata_ratelimit()) + ata_port_printk(ap, KERN_INFO, "spurious interrupt " + "(irq_stat 0x%x active_tag %d sactive 0x%x)\n", + status, ap->active_tag, ap->sactive); } static void ahci_irq_clear(struct ata_port *ap) @@ -882,7 +960,7 @@ static void ahci_irq_clear(struct ata_po /* TODO */ } -static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; struct ahci_host_priv *hpriv; @@ -911,14 +989,7 @@ static irqreturn_t ahci_interrupt (int i ap = host_set->ports[i]; if (ap) { - struct ata_queued_cmd *qc; - qc = ata_qc_from_tag(ap, ap->active_tag); - if (!ahci_host_intr(ap, qc)) - if (ata_ratelimit()) - dev_printk(KERN_WARNING, host_set->dev, - "unhandled interrupt on port %u\n", - i); - + ahci_host_intr(ap); VPRINTK("port %u\n", i); } else { VPRINTK("port %u (no irq)\n", i); @@ -935,7 +1006,7 @@ static irqreturn_t ahci_interrupt (int i handled = 1; } - spin_unlock(&host_set->lock); + spin_unlock(&host_set->lock); VPRINTK("EXIT\n"); @@ -947,12 +1018,65 @@ static unsigned int ahci_qc_issue(struct struct ata_port *ap = qc->ap; void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; - writel(1, port_mmio + PORT_CMD_ISSUE); + if (qc->tf.protocol == ATA_PROT_NCQ) + writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); + writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE); readl(port_mmio + PORT_CMD_ISSUE); /* flush */ return 0; } +static void ahci_freeze(struct ata_port *ap) +{ + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + + /* turn IRQ off */ + writel(0, port_mmio + PORT_IRQ_MASK); +} + +static void ahci_thaw(struct ata_port *ap) +{ + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + u32 tmp; + + /* clear IRQ */ + tmp = readl(port_mmio + PORT_IRQ_STAT); + writel(tmp, port_mmio + PORT_IRQ_STAT); + writel(1 << ap->id, mmio + HOST_IRQ_STAT); + + /* turn IRQ back on */ + writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); +} + +static void ahci_error_handler(struct ata_port *ap) +{ + if (!(ap->flags & ATA_FLAG_FROZEN)) { + /* restart engine */ + ahci_stop_engine(ap); + ahci_start_engine(ap); + } + + /* perform recovery */ + ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset, + ahci_postreset); +} + +static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + if (qc->flags & ATA_QCFLAG_FAILED) + qc->err_mask |= AC_ERR_OTHER; + + if (qc->err_mask) { + /* make DMA engine forget about the failed command */ + ahci_stop_engine(ap); + ahci_start_engine(ap); + } +} + static void ahci_setup_port(struct ata_ioports *port, unsigned long base, unsigned int port_idx) { @@ -1097,9 +1221,6 @@ #endif writel(tmp, port_mmio + PORT_IRQ_STAT); writel(1 << i, mmio + HOST_IRQ_STAT); - - /* set irq mask (enables interrupts) */ - writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); } tmp = readl(mmio + HOST_CTL); @@ -1197,6 +1318,8 @@ static int ahci_init_one (struct pci_dev VPRINTK("ENTER\n"); + WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS); + if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); @@ -1264,6 +1387,10 @@ static int ahci_init_one (struct pci_dev if (rc) goto err_out_hpriv; + if (!(probe_ent->host_flags & AHCI_FLAG_NO_NCQ) && + (hpriv->cap & HOST_CAP_NCQ)) + probe_ent->host_flags |= ATA_FLAG_NCQ; + ahci_print_info(probe_ent); /* FIXME: check ata_device_add return value */ @@ -1295,21 +1422,17 @@ static void ahci_remove_one (struct pci_ struct device *dev = pci_dev_to_dev(pdev); struct ata_host_set *host_set = dev_get_drvdata(dev); struct ahci_host_priv *hpriv = host_set->private_data; - struct ata_port *ap; unsigned int i; int have_msi; - for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; - - scsi_remove_host(ap->host); - } + for (i = 0; i < host_set->n_ports; i++) + ata_port_detach(host_set->ports[i]); have_msi = hpriv->flags & AHCI_FLAG_MSI; free_irq(host_set->irq, host_set); for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; + struct ata_port *ap = host_set->ports[i]; ata_scsi_release(ap->host); scsi_host_put(ap->host); diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c index 527efd3..c4d1723 100644 --- a/drivers/scsi/aic7xxx/aic7770.c +++ b/drivers/scsi/aic7xxx/aic7770.c @@ -107,7 +107,7 @@ struct aic7770_identity aic7770_ident_ta ahc_aic7770_EISA_setup } }; -const int ahc_num_aic7770_devs = NUM_ELEMENTS(aic7770_ident_table); +const int ahc_num_aic7770_devs = ARRAY_SIZE(aic7770_ident_table); struct aic7770_identity * aic7770_find_device(uint32_t id) diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index bb5166d..eb77456 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -68,8 +68,6 @@ #ifndef FALSE #define FALSE 0 #endif -#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array)) - #define ALL_CHANNELS '\0' #define ALL_TARGETS_MASK 0xFFFF #define INITIATOR_WILDCARD (~0) diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 08771f6..801fc81 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -59,7 +59,7 @@ char *ahd_chip_names[] = "aic7902", "aic7901A" }; -static const u_int num_chip_names = NUM_ELEMENTS(ahd_chip_names); +static const u_int num_chip_names = ARRAY_SIZE(ahd_chip_names); /* * Hardware error codes. @@ -77,7 +77,7 @@ static struct ahd_hard_error_entry ahd_h { MPARERR, "Scratch or SCB Memory Parity Error" }, { CIOPARERR, "CIOBUS Parity Error" }, }; -static const u_int num_errors = NUM_ELEMENTS(ahd_hard_errors); +static const u_int num_errors = ARRAY_SIZE(ahd_hard_errors); static struct ahd_phase_table_entry ahd_phase_table[] = { @@ -97,7 +97,7 @@ static struct ahd_phase_table_entry ahd_ * In most cases we only wish to itterate over real phases, so * exclude the last element from the count. */ -static const u_int num_phases = NUM_ELEMENTS(ahd_phase_table) - 1; +static const u_int num_phases = ARRAY_SIZE(ahd_phase_table) - 1; /* Our Sequencer Program */ #include "aic79xx_seq.h" @@ -7259,7 +7259,7 @@ ahd_qinfifo_count(struct ahd_softc *ahd) return (wrap_qinfifonext - wrap_qinpos); else return (wrap_qinfifonext - + NUM_ELEMENTS(ahd->qinfifo) - wrap_qinpos); + + ARRAY_SIZE(ahd->qinfifo) - wrap_qinpos); } void @@ -8619,7 +8619,7 @@ ahd_check_patch(struct ahd_softc *ahd, s struct patch *last_patch; u_int num_patches; - num_patches = sizeof(patches)/sizeof(struct patch); + num_patches = ARRAY_SIZE(patches); last_patch = &patches[num_patches]; cur_patch = *start_patch; @@ -9396,8 +9396,8 @@ ahd_find_tmode_devs(struct ahd_softc *ah } else { u_int max_id; - max_id = (ahd->features & AHD_WIDE) ? 15 : 7; - if (ccb->ccb_h.target_id > max_id) + max_id = (ahd->features & AHD_WIDE) ? 16 : 8; + if (ccb->ccb_h.target_id >= max_id) return (CAM_TID_INVALID); if (ccb->ccb_h.target_lun >= AHD_NUM_LUNS) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 66e4a47..e0ccdf3 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -916,7 +916,7 @@ ahd_linux_setup_iocell_info(u_long index { if ((instance >= 0) - && (instance < NUM_ELEMENTS(aic79xx_iocell_info))) { + && (instance < ARRAY_SIZE(aic79xx_iocell_info))) { uint8_t *iocell_info; iocell_info = (uint8_t*)&aic79xx_iocell_info[instance]; @@ -934,7 +934,7 @@ ahd_linux_setup_tag_info_global(char *p) tags = simple_strtoul(p + 1, NULL, 0) & 0xff; printf("Setting Global Tags= %d\n", tags); - for (i = 0; i < NUM_ELEMENTS(aic79xx_tag_info); i++) { + for (i = 0; i < ARRAY_SIZE(aic79xx_tag_info); i++) { for (j = 0; j < AHD_NUM_TARGETS; j++) { aic79xx_tag_info[i].tag_commands[j] = tags; } @@ -946,7 +946,7 @@ ahd_linux_setup_tag_info(u_long arg, int { if ((instance >= 0) && (targ >= 0) - && (instance < NUM_ELEMENTS(aic79xx_tag_info)) + && (instance < ARRAY_SIZE(aic79xx_tag_info)) && (targ < AHD_NUM_TARGETS)) { aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF; if (bootverbose) @@ -1072,21 +1072,21 @@ #endif end = strchr(s, '\0'); /* - * XXX ia64 gcc isn't smart enough to know that NUM_ELEMENTS + * XXX ia64 gcc isn't smart enough to know that ARRAY_SIZE * will never be 0 in this case. - */ - n = 0; + */ + n = 0; while ((p = strsep(&s, ",.")) != NULL) { if (*p == '\0') continue; - for (i = 0; i < NUM_ELEMENTS(options); i++) { + for (i = 0; i < ARRAY_SIZE(options); i++) { n = strlen(options[i].name); if (strncmp(options[i].name, p, n) == 0) break; } - if (i == NUM_ELEMENTS(options)) + if (i == ARRAY_SIZE(options)) continue; if (strncmp(p, "global_tag_depth", n) == 0) { @@ -1294,7 +1294,7 @@ ahd_platform_init(struct ahd_softc *ahd) /* * Lookup and commit any modified IO Cell options. */ - if (ahd->unit < NUM_ELEMENTS(aic79xx_iocell_info)) { + if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) { struct ahd_linux_iocell_opts *iocell_opts; iocell_opts = &aic79xx_iocell_info[ahd->unit]; @@ -1426,7 +1426,7 @@ ahd_linux_user_tagdepth(struct ahd_softc tags = 0; if ((ahd->user_discenable & devinfo->target_mask) != 0) { - if (ahd->unit >= NUM_ELEMENTS(aic79xx_tag_info)) { + if (ahd->unit >= ARRAY_SIZE(aic79xx_tag_info)) { if (warned_user == 0) { printf(KERN_WARNING diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 757242e..14850f3 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -201,7 +201,7 @@ struct ahd_pci_identity ahd_pci_ident_ta } }; -const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table); +const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table); #define DEVCONFIG 0x40 #define PCIXINITPAT 0x0000E000ul diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c index 39a2784..24fd59a 100644 --- a/drivers/scsi/aic7xxx/aic79xx_proc.c +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c @@ -76,11 +76,9 @@ static u_int ahd_calc_syncsrate(u_int period_factor) { int i; - int num_syncrates; - num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); /* See if the period is in the "exception" table */ - for (i = 0; i < num_syncrates; i++) { + for (i = 0; i < ARRAY_SIZE(scsi_syncrates); i++) { if (period_factor == scsi_syncrates[i].period_factor) { /* Period in kHz */ diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index 91d294c..62ff8c3 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -69,8 +69,6 @@ #ifndef FALSE #define FALSE 0 #endif -#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array)) - #define ALL_CHANNELS '\0' #define ALL_TARGETS_MASK 0xFFFF #define INITIATOR_WILDCARD (~0) @@ -233,6 +231,7 @@ typedef enum { AHC_TARGETMODE = 0x20000, /* Has tested target mode support */ AHC_MULTIROLE = 0x40000, /* Space for two roles at a time */ AHC_REMOVABLE = 0x80000, /* Hot-Swap supported */ + AHC_HVD = 0x100000, /* HVD rather than SE */ AHC_AIC7770_FE = AHC_FENONE, /* * The real 7850 does not support Ultra modes, but there are diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index d375669..93e4e40 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -68,7 +68,7 @@ char *ahc_chip_names[] = "aic7892", "aic7899" }; -static const u_int num_chip_names = NUM_ELEMENTS(ahc_chip_names); +static const u_int num_chip_names = ARRAY_SIZE(ahc_chip_names); /* * Hardware error codes. @@ -88,7 +88,7 @@ static struct ahc_hard_error_entry ahc_h { PCIERRSTAT, "PCI Error detected" }, { CIOPARERR, "CIOBUS Parity Error" }, }; -static const u_int num_errors = NUM_ELEMENTS(ahc_hard_errors); +static const u_int num_errors = ARRAY_SIZE(ahc_hard_errors); static struct ahc_phase_table_entry ahc_phase_table[] = { @@ -108,7 +108,7 @@ static struct ahc_phase_table_entry ahc_ * In most cases we only wish to itterate over real phases, so * exclude the last element from the count. */ -static const u_int num_phases = NUM_ELEMENTS(ahc_phase_table) - 1; +static const u_int num_phases = ARRAY_SIZE(ahc_phase_table) - 1; /* * Valid SCSIRATE values. (p. 3-17) @@ -6367,7 +6367,7 @@ ahc_check_patch(struct ahc_softc *ahc, s struct patch *last_patch; u_int num_patches; - num_patches = sizeof(patches)/sizeof(struct patch); + num_patches = ARRAY_SIZE(patches); last_patch = &patches[num_patches]; cur_patch = *start_patch; @@ -6774,8 +6774,8 @@ ahc_find_tmode_devs(struct ahc_softc *ah } else { u_int max_id; - max_id = (ahc->features & AHC_WIDE) ? 15 : 7; - if (ccb->ccb_h.target_id > max_id) + max_id = (ahc->features & AHC_WIDE) ? 16 : 8; + if (ccb->ccb_h.target_id >= max_id) return (CAM_TID_INVALID); if (ccb->ccb_h.target_lun >= AHC_NUM_LUNS) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 2c80167..debf3e2 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -886,7 +886,7 @@ ahc_linux_setup_tag_info_global(char *p) tags = simple_strtoul(p + 1, NULL, 0) & 0xff; printf("Setting Global Tags= %d\n", tags); - for (i = 0; i < NUM_ELEMENTS(aic7xxx_tag_info); i++) { + for (i = 0; i < ARRAY_SIZE(aic7xxx_tag_info); i++) { for (j = 0; j < AHC_NUM_TARGETS; j++) { aic7xxx_tag_info[i].tag_commands[j] = tags; } @@ -898,7 +898,7 @@ ahc_linux_setup_tag_info(u_long arg, int { if ((instance >= 0) && (targ >= 0) - && (instance < NUM_ELEMENTS(aic7xxx_tag_info)) + && (instance < ARRAY_SIZE(aic7xxx_tag_info)) && (targ < AHC_NUM_TARGETS)) { aic7xxx_tag_info[instance].tag_commands[targ] = value & 0xff; if (bootverbose) @@ -1020,7 +1020,7 @@ #endif end = strchr(s, '\0'); /* - * XXX ia64 gcc isn't smart enough to know that NUM_ELEMENTS + * XXX ia64 gcc isn't smart enough to know that ARRAY_SIZE * will never be 0 in this case. */ n = 0; @@ -1028,13 +1028,13 @@ #endif while ((p = strsep(&s, ",.")) != NULL) { if (*p == '\0') continue; - for (i = 0; i < NUM_ELEMENTS(options); i++) { + for (i = 0; i < ARRAY_SIZE(options); i++) { n = strlen(options[i].name); if (strncmp(options[i].name, p, n) == 0) break; } - if (i == NUM_ELEMENTS(options)) + if (i == ARRAY_SIZE(options)) continue; if (strncmp(p, "global_tag_depth", n) == 0) { @@ -1360,7 +1360,7 @@ ahc_linux_user_tagdepth(struct ahc_softc tags = 0; if ((ahc->user_discenable & devinfo->target_mask) != 0) { - if (ahc->unit >= NUM_ELEMENTS(aic7xxx_tag_info)) { + if (ahc->unit >= ARRAY_SIZE(aic7xxx_tag_info)) { if (warned_user == 0) { printf(KERN_WARNING @@ -2537,6 +2537,22 @@ static void ahc_linux_set_iu(struct scsi } #endif +static void ahc_linux_get_signalling(struct Scsi_Host *shost) +{ + struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata; + u8 mode = ahc_inb(ahc, SBLKCTL); + + if (mode & ENAB40) + spi_signalling(shost) = SPI_SIGNAL_LVD; + else if (mode & ENAB20) + spi_signalling(shost) = + ahc->features & AHC_HVD ? + SPI_SIGNAL_HVD : + SPI_SIGNAL_SE; + else + spi_signalling(shost) = SPI_SIGNAL_UNKNOWN; +} + static struct spi_function_template ahc_linux_transport_functions = { .set_offset = ahc_linux_set_offset, .show_offset = 1, @@ -2552,6 +2568,7 @@ #if 0 .set_qas = ahc_linux_set_qas, .show_qas = 1, #endif + .get_signalling = ahc_linux_get_signalling, }; diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 3adecef..63cab2d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -144,16 +144,22 @@ static ahc_device_setup_t ahc_aic785X_se static ahc_device_setup_t ahc_aic7860_setup; static ahc_device_setup_t ahc_apa1480_setup; static ahc_device_setup_t ahc_aic7870_setup; +static ahc_device_setup_t ahc_aic7870h_setup; static ahc_device_setup_t ahc_aha394X_setup; +static ahc_device_setup_t ahc_aha394Xh_setup; static ahc_device_setup_t ahc_aha494X_setup; +static ahc_device_setup_t ahc_aha494Xh_setup; static ahc_device_setup_t ahc_aha398X_setup; static ahc_device_setup_t ahc_aic7880_setup; +static ahc_device_setup_t ahc_aic7880h_setup; static ahc_device_setup_t ahc_aha2940Pro_setup; static ahc_device_setup_t ahc_aha394XU_setup; +static ahc_device_setup_t ahc_aha394XUh_setup; static ahc_device_setup_t ahc_aha398XU_setup; static ahc_device_setup_t ahc_aic7890_setup; static ahc_device_setup_t ahc_aic7892_setup; static ahc_device_setup_t ahc_aic7895_setup; +static ahc_device_setup_t ahc_aic7895h_setup; static ahc_device_setup_t ahc_aic7896_setup; static ahc_device_setup_t ahc_aic7899_setup; static ahc_device_setup_t ahc_aha29160C_setup; @@ -225,19 +231,19 @@ struct ahc_pci_identity ahc_pci_ident_ta ID_AHA_2944, ID_ALL_MASK, "Adaptec 2944 SCSI adapter", - ahc_aic7870_setup + ahc_aic7870h_setup }, { ID_AHA_3944, ID_ALL_MASK, "Adaptec 3944 SCSI adapter", - ahc_aha394X_setup + ahc_aha394Xh_setup }, { ID_AHA_4944, ID_ALL_MASK, "Adaptec 4944 SCSI adapter", - ahc_aha494X_setup + ahc_aha494Xh_setup }, /* aic7880 based controllers */ { @@ -256,13 +262,13 @@ struct ahc_pci_identity ahc_pci_ident_ta ID_AHA_2944U & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec 2944 Ultra SCSI adapter", - ahc_aic7880_setup + ahc_aic7880h_setup }, { ID_AHA_3944U & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec 3944 Ultra SCSI adapter", - ahc_aha394XU_setup + ahc_aha394XUh_setup }, { ID_AHA_398XU & ID_DEV_VENDOR_MASK, @@ -278,7 +284,7 @@ struct ahc_pci_identity ahc_pci_ident_ta ID_AHA_4944U & ID_DEV_VENDOR_MASK, ID_DEV_VENDOR_MASK, "Adaptec 4944 Ultra SCSI adapter", - ahc_aic7880_setup + ahc_aic7880h_setup }, { ID_AHA_2930U & ID_DEV_VENDOR_MASK, @@ -414,7 +420,7 @@ struct ahc_pci_identity ahc_pci_ident_ta ID_AHA_3944AU, ID_ALL_MASK, "Adaptec 3944A Ultra SCSI adapter", - ahc_aic7895_setup + ahc_aic7895h_setup }, { ID_AIC7895_ARO, @@ -553,7 +559,7 @@ struct ahc_pci_identity ahc_pci_ident_ta } }; -const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table); +const u_int ahc_num_pci_devs = ARRAY_SIZE(ahc_pci_ident_table); #define AHC_394X_SLOT_CHANNEL_A 4 #define AHC_394X_SLOT_CHANNEL_B 5 @@ -2121,6 +2127,16 @@ ahc_aic7870_setup(struct ahc_softc *ahc) } static int +ahc_aic7870h_setup(struct ahc_softc *ahc) +{ + int error = ahc_aic7870_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + +static int ahc_aha394X_setup(struct ahc_softc *ahc) { int error; @@ -2132,6 +2148,16 @@ ahc_aha394X_setup(struct ahc_softc *ahc) } static int +ahc_aha394Xh_setup(struct ahc_softc *ahc) +{ + int error = ahc_aha394X_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + +static int ahc_aha398X_setup(struct ahc_softc *ahc) { int error; @@ -2154,6 +2180,16 @@ ahc_aha494X_setup(struct ahc_softc *ahc) } static int +ahc_aha494Xh_setup(struct ahc_softc *ahc) +{ + int error = ahc_aha494X_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + +static int ahc_aic7880_setup(struct ahc_softc *ahc) { ahc_dev_softc_t pci; @@ -2175,6 +2211,17 @@ ahc_aic7880_setup(struct ahc_softc *ahc) } static int +ahc_aic7880h_setup(struct ahc_softc *ahc) +{ + int error = ahc_aic7880_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + + +static int ahc_aha2940Pro_setup(struct ahc_softc *ahc) { @@ -2194,6 +2241,16 @@ ahc_aha394XU_setup(struct ahc_softc *ahc } static int +ahc_aha394XUh_setup(struct ahc_softc *ahc) +{ + int error = ahc_aha394XU_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + +static int ahc_aha398XU_setup(struct ahc_softc *ahc) { int error; @@ -2292,6 +2349,16 @@ #endif } static int +ahc_aic7895h_setup(struct ahc_softc *ahc) +{ + int error = ahc_aic7895_setup(ahc); + + ahc->features |= AHC_HVD; + + return error; +} + +static int ahc_aic7896_setup(struct ahc_softc *ahc) { ahc_dev_softc_t pci; diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c index 04a3506..5914b4a 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c @@ -77,11 +77,9 @@ static u_int ahc_calc_syncsrate(u_int period_factor) { int i; - int num_syncrates; - num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); /* See if the period is in the "exception" table */ - for (i = 0; i < num_syncrates; i++) { + for (i = 0; i < ARRAY_SIZE(scsi_syncrates); i++) { if (period_factor == scsi_syncrates[i].period_factor) { /* Period in kHz */ diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 770f164..5dba1c6 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c @@ -1565,7 +1565,7 @@ aic7xxx_check_patch(struct aic7xxx_host struct sequencer_patch *last_patch; int num_patches; - num_patches = sizeof(sequencer_patches)/sizeof(struct sequencer_patch); + num_patches = ARRAY_SIZE(sequencer_patches); last_patch = &sequencer_patches[num_patches]; cur_patch = *start_patch; diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c index b10750b..8caa590 100644 --- a/drivers/scsi/arm/queue.c +++ b/drivers/scsi/arm/queue.c @@ -118,8 +118,7 @@ int __queue_add(Queue_t *queue, Scsi_Cmn list_del(l); q = list_entry(l, QE_t, list); - if (BAD_MAGIC(q, QUEUE_MAGIC_FREE)) - BUG(); + BUG_ON(BAD_MAGIC(q, QUEUE_MAGIC_FREE)); SET_MAGIC(q, QUEUE_MAGIC_USED); q->SCpnt = SCpnt; @@ -144,8 +143,7 @@ static Scsi_Cmnd *__queue_remove(Queue_t */ list_del(ent); q = list_entry(ent, QE_t, list); - if (BAD_MAGIC(q, QUEUE_MAGIC_USED)) - BUG(); + BUG_ON(BAD_MAGIC(q, QUEUE_MAGIC_USED)); SET_MAGIC(q, QUEUE_MAGIC_FREE); list_add(ent, &queue->free); diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 6dc8814..521b718 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -93,7 +93,7 @@ #include #include #define DRV_NAME "ata_piix" -#define DRV_VERSION "1.05" +#define DRV_VERSION "1.10" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ @@ -146,11 +146,10 @@ struct piix_map_db { static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); - -static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes); -static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes); static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev); static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev); +static void piix_pata_error_handler(struct ata_port *ap); +static void piix_sata_error_handler(struct ata_port *ap); static unsigned int in_module_init = 1; @@ -159,6 +158,7 @@ #ifdef ATA_ENABLE_PATA { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, + { 0x8086, 0x27df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, #endif /* NOTE: The following PCI ids must be kept in sync with the @@ -218,6 +218,7 @@ static struct scsi_host_template piix_sh .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend, @@ -227,6 +228,7 @@ static const struct ata_port_operations .port_disable = ata_port_disable, .set_piomode = piix_set_piomode, .set_dmamode = piix_set_dmamode, + .mode_filter = ata_pci_default_filter, .tf_load = ata_tf_load, .tf_read = ata_tf_read, @@ -234,16 +236,18 @@ static const struct ata_port_operations .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .probe_reset = piix_pata_probe_reset, - .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = piix_pata_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -262,16 +266,18 @@ static const struct ata_port_operations .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .probe_reset = piix_sata_probe_reset, - .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = piix_sata_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -455,59 +461,51 @@ cbl40: } /** - * piix_pata_probeinit - probeinit for PATA host controller + * piix_pata_prereset - prereset for PATA host controller * @ap: Target port * - * Probeinit including cable detection. - * - * LOCKING: - * None (inherited from caller). - */ -static void piix_pata_probeinit(struct ata_port *ap) -{ - piix_pata_cbl_detect(ap); - ata_std_probeinit(ap); -} - -/** - * piix_pata_probe_reset - Perform reset on PATA port and classify - * @ap: Port to reset - * @classes: Resulting classes of attached devices - * - * Reset PATA phy and classify attached devices. + * Prereset including cable detection. * * LOCKING: * None (inherited from caller). */ -static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes) +static int piix_pata_prereset(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) { - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); + ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n"); + ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; return 0; } - return ata_drive_probe_reset(ap, piix_pata_probeinit, - ata_std_softreset, NULL, - ata_std_postreset, classes); + piix_pata_cbl_detect(ap); + + return ata_std_prereset(ap); +} + +static void piix_pata_error_handler(struct ata_port *ap) +{ + ata_bmdma_drive_eh(ap, piix_pata_prereset, ata_std_softreset, NULL, + ata_std_postreset); } /** - * piix_sata_probe - Probe PCI device for present SATA devices - * @ap: Port associated with the PCI device we wish to probe + * piix_sata_prereset - prereset for SATA host controller + * @ap: Target port * * Reads and configures SATA PCI device's PCI config register * Port Configuration and Status (PCS) to determine port and - * device availability. + * device availability. Return -ENODEV to skip reset if no + * device is present. * * LOCKING: * None (inherited from caller). * * RETURNS: - * Mask of avaliable devices on the port. + * 0 if device is present, -ENODEV otherwise. */ -static unsigned int piix_sata_probe (struct ata_port *ap) +static int piix_sata_prereset(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); const unsigned int *map = ap->host_set->private_data; @@ -549,29 +547,19 @@ static unsigned int piix_sata_probe (str DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", ap->id, pcs, present_mask); - return present_mask; -} - -/** - * piix_sata_probe_reset - Perform reset on SATA port and classify - * @ap: Port to reset - * @classes: Resulting classes of attached devices - * - * Reset SATA phy and classify attached devices. - * - * LOCKING: - * None (inherited from caller). - */ -static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes) -{ - if (!piix_sata_probe(ap)) { - printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id); + if (!present_mask) { + ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n"); + ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; return 0; } - return ata_drive_probe_reset(ap, ata_std_probeinit, - ata_std_softreset, NULL, - ata_std_postreset, classes); + return ata_std_prereset(ap); +} + +static void piix_sata_error_handler(struct ata_port *ap) +{ + ata_bmdma_drive_eh(ap, piix_sata_prereset, ata_std_softreset, NULL, + ata_std_postreset); } /** @@ -760,15 +748,15 @@ static int __devinit piix_check_450nx_er pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); pci_read_config_word(pdev, 0x41, &cfg); /* Only on the original revision: IDE DMA can hang */ - if(rev == 0x00) + if (rev == 0x00) no_piix_dma = 1; /* On all revisions below 5 PXB bus lock must be disabled for IDE */ - else if(cfg & (1<<14) && rev < 5) + else if (cfg & (1<<14) && rev < 5) no_piix_dma = 2; } - if(no_piix_dma) + if (no_piix_dma) dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n"); - if(no_piix_dma == 2) + if (no_piix_dma == 2) dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n"); return no_piix_dma; } diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index a198d86..3ee4d4d 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -473,7 +473,7 @@ go_42: */ if (workreq->use_sg) { pci_unmap_sg(dev->pdev, - (struct scatterlist *)workreq->buffer, + (struct scatterlist *)workreq->request_buffer, workreq->use_sg, workreq->sc_data_direction); } else if (workreq->request_bufflen && @@ -3047,7 +3047,7 @@ #endif if (atp_dev.chip_ver == 4) shpnt->max_id = 16; else - shpnt->max_id = 7; + shpnt->max_id = 8; shpnt->this_id = host_id; shpnt->unique_id = base_io; shpnt->io_port = base_io; diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 30a3353..d92d504 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -13,9 +13,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -114,8 +114,7 @@ static const struct value_name_pair main {0xd, "Report supported task management functions"}, {0xe, "Report priority"}, }; -#define MAINT_IN_SZ \ - (int)(sizeof(maint_in_arr) / sizeof(maint_in_arr[0])) +#define MAINT_IN_SZ ARRAY_SIZE(maint_in_arr) static const struct value_name_pair maint_out_arr[] = { {0x6, "Set device identifier"}, @@ -123,34 +122,29 @@ static const struct value_name_pair main {0xb, "Change aliases"}, {0xe, "Set priority"}, }; -#define MAINT_OUT_SZ \ - (int)(sizeof(maint_out_arr) / sizeof(maint_out_arr[0])) +#define MAINT_OUT_SZ ARRAY_SIZE(maint_out_arr) static const struct value_name_pair serv_in12_arr[] = { {0x1, "Read media serial number"}, }; -#define SERV_IN12_SZ \ - (int)(sizeof(serv_in12_arr) / sizeof(serv_in12_arr[0])) +#define SERV_IN12_SZ ARRAY_SIZE(serv_in12_arr) static const struct value_name_pair serv_out12_arr[] = { {-1, "dummy entry"}, }; -#define SERV_OUT12_SZ \ - (int)(sizeof(serv_out12_arr) / sizeof(serv_in12_arr[0])) +#define SERV_OUT12_SZ ARRAY_SIZE(serv_out12_arr) static const struct value_name_pair serv_in16_arr[] = { {0x10, "Read capacity(16)"}, {0x11, "Read long(16)"}, }; -#define SERV_IN16_SZ \ - (int)(sizeof(serv_in16_arr) / sizeof(serv_in16_arr[0])) +#define SERV_IN16_SZ ARRAY_SIZE(serv_in16_arr) static const struct value_name_pair serv_out16_arr[] = { {0x11, "Write long(16)"}, {0x1f, "Notify data transfer device(16)"}, }; -#define SERV_OUT16_SZ \ - (int)(sizeof(serv_out16_arr) / sizeof(serv_in16_arr[0])) +#define SERV_OUT16_SZ ARRAY_SIZE(serv_out16_arr) static const struct value_name_pair variable_length_arr[] = { {0x1, "Rebuild(32)"}, @@ -190,8 +184,7 @@ static const struct value_name_pair vari {0x8f7e, "Perform SCSI command (osd)"}, {0x8f7f, "Perform task management function (osd)"}, }; -#define VARIABLE_LENGTH_SZ \ - (int)(sizeof(variable_length_arr) / sizeof(variable_length_arr[0])) +#define VARIABLE_LENGTH_SZ ARRAY_SIZE(variable_length_arr) static const char * get_sa_name(const struct value_name_pair * arr, int arr_sz, int service_action) @@ -1268,16 +1261,6 @@ void scsi_print_sense(const char *devcla } EXPORT_SYMBOL(scsi_print_sense); -void scsi_print_req_sense(const char *devclass, struct scsi_request *sreq) -{ - const char *name = devclass; - - if (sreq->sr_request->rq_disk) - name = sreq->sr_request->rq_disk->disk_name; - __scsi_print_sense(name, sreq->sr_sense_buffer, SCSI_SENSE_BUFFERSIZE); -} -EXPORT_SYMBOL(scsi_print_req_sense); - void scsi_print_command(struct scsi_cmnd *cmd) { /* Assume appended output (i.e. not at start of line) */ @@ -1290,10 +1273,10 @@ EXPORT_SYMBOL(scsi_print_command); #ifdef CONFIG_SCSI_CONSTANTS static const char * const hostbyte_table[]={ -"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", +"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR", "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY"}; -#define NUM_HOSTBYTE_STRS (sizeof(hostbyte_table) / sizeof(const char *)) +#define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table) void scsi_print_hostbyte(int scsiresult) { @@ -1303,7 +1286,7 @@ void scsi_print_hostbyte(int scsiresult) if (hb < NUM_HOSTBYTE_STRS) printk("(%s) ", hostbyte_table[hb]); else - printk("is invalid "); + printk("is invalid "); } #else void scsi_print_hostbyte(int scsiresult) @@ -1315,14 +1298,14 @@ #endif #ifdef CONFIG_SCSI_CONSTANTS static const char * const driverbyte_table[]={ -"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR", +"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR", "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"}; -#define NUM_DRIVERBYTE_STRS (sizeof(driverbyte_table) / sizeof(const char *)) +#define NUM_DRIVERBYTE_STRS ARRAY_SIZE(driverbyte_table) static const char * const driversuggest_table[]={"SUGGEST_OK", "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE", "SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"}; -#define NUM_SUGGEST_STRS (sizeof(driversuggest_table) / sizeof(const char *)) +#define NUM_SUGGEST_STRS ARRAY_SIZE(driversuggest_table) void scsi_print_driverbyte(int scsiresult) { diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index cbf8252..58b0748 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -230,13 +230,12 @@ struct ScsiReqBlk { struct scsi_cmnd *cmd; struct SGentry *segment_x; /* Linear array of hw sg entries (up to 64 entries) */ - u32 sg_bus_addr; /* Bus address of sg list (ie, of segment_x) */ + dma_addr_t sg_bus_addr; /* Bus address of sg list (ie, of segment_x) */ u8 sg_count; /* No of HW sg entries for this request */ u8 sg_index; /* Index of HW sg entry for this request */ - u32 total_xfer_length; /* Total number of bytes remaining to be transfered */ - unsigned char *virt_addr; /* Virtual address of current transfer position */ - + size_t total_xfer_length; /* Total number of bytes remaining to be transfered */ + size_t request_length; /* Total number of bytes in this request */ /* * The sense buffer handling function, request_sense, uses * the first hw sg entry (segment_x[0]) and the transfer @@ -246,8 +245,7 @@ struct ScsiReqBlk { * total_xfer_length in xferred. These values are restored in * pci_unmap_srb_sense. This is the only place xferred is used. */ - unsigned char *virt_addr_req; /* Saved virtual address of the request buffer */ - u32 xferred; /* Saved copy of total_xfer_length */ + size_t xferred; /* Saved copy of total_xfer_length */ u16 state; @@ -977,17 +975,6 @@ static void send_srb(struct AdapterCtlBl } } -static inline void pio_trigger(void) -{ - static int feedback_requested; - - if (!feedback_requested) { - feedback_requested = 1; - printk(KERN_WARNING "%s: Please, contact " - "to help improve support for your system.\n", __FILE__); - } -} - /* Prepare SRB for being sent to Device DCB w/ command *cmd */ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) @@ -1001,7 +988,6 @@ static void build_srb(struct scsi_cmnd * srb->sg_count = 0; srb->total_xfer_length = 0; srb->sg_bus_addr = 0; - srb->virt_addr = NULL; srb->sg_index = 0; srb->adapter_status = 0; srb->target_status = 0; @@ -1032,7 +1018,6 @@ static void build_srb(struct scsi_cmnd * reqlen, cmd->request_buffer, cmd->use_sg, srb->sg_count); - srb->virt_addr = page_address(sl->page); for (i = 0; i < srb->sg_count; i++) { u32 busaddr = (u32)sg_dma_address(&sl[i]); u32 seglen = (u32)sl[i].length; @@ -1077,12 +1062,14 @@ static void build_srb(struct scsi_cmnd * srb->total_xfer_length++; srb->segment_x[0].length = srb->total_xfer_length; - srb->virt_addr = cmd->request_buffer; + dprintkdbg(DBG_0, "build_srb: [1] len=%d buf=%p use_sg=%d map=%08x\n", srb->total_xfer_length, cmd->request_buffer, cmd->use_sg, srb->segment_x[0].address); } + + srb->request_length = srb->total_xfer_length; } @@ -1414,10 +1401,10 @@ static int dc395x_eh_abort(struct scsi_c } srb = find_cmd(cmd, &dcb->srb_going_list); if (srb) { - dprintkl(KERN_DEBUG, "eh_abort: Command in progress"); + dprintkl(KERN_DEBUG, "eh_abort: Command in progress\n"); /* XXX: Should abort the command here */ } else { - dprintkl(KERN_DEBUG, "eh_abort: Command not found"); + dprintkl(KERN_DEBUG, "eh_abort: Command not found\n"); } return FAILED; } @@ -1976,14 +1963,11 @@ static void sg_verify_length(struct Scsi /* * Compute the next Scatter Gather list index and adjust its length - * and address if necessary; also compute virt_addr + * and address if necessary */ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) { u8 idx; - struct scatterlist *sg; - struct scsi_cmnd *cmd = srb->cmd; - int segment = cmd->use_sg; u32 xferred = srb->total_xfer_length - left; /* bytes transfered */ struct SGentry *psge = srb->segment_x + srb->sg_index; @@ -2016,29 +2000,6 @@ static void sg_update_list(struct ScsiRe psge++; } sg_verify_length(srb); - - /* we need the corresponding virtual address */ - if (!segment || (srb->flag & AUTO_REQSENSE)) { - srb->virt_addr += xferred; - return; - } - - /* We have to walk the scatterlist to find it */ - sg = (struct scatterlist *)cmd->request_buffer; - while (segment--) { - unsigned long mask = - ~((unsigned long)sg->length - 1) & PAGE_MASK; - if ((sg_dma_address(sg) & mask) == (psge->address & mask)) { - srb->virt_addr = (page_address(sg->page) - + psge->address - - (psge->address & PAGE_MASK)); - return; - } - ++sg; - } - - dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n"); - srb->virt_addr = NULL; } @@ -2050,15 +2011,7 @@ static void sg_update_list(struct ScsiRe */ static void sg_subtract_one(struct ScsiReqBlk *srb) { - srb->total_xfer_length--; - srb->segment_x[srb->sg_index].length--; - if (srb->total_xfer_length && - !srb->segment_x[srb->sg_index].length) { - if (debug_enabled(DBG_PIO)) - printk(" (next segment)"); - srb->sg_index++; - sg_update_list(srb, srb->total_xfer_length); - } + sg_update_list(srb, srb->total_xfer_length - 1); } @@ -2118,7 +2071,7 @@ static void data_out_phase0(struct Adapt * If we need more data, the DMA SG list will be freshly set up, anyway */ dprintkdbg(DBG_PIO, "data_out_phase0: " - "DMA{fifcnt=0x%02x fifostat=0x%02x} " + "DMA{fifocnt=0x%02x fifostat=0x%02x} " "SCSI{fifocnt=0x%02x cnt=0x%06x status=0x%04x} total=0x%06x\n", DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), @@ -2239,12 +2192,11 @@ static void data_out_phase1(struct Adapt data_io_transfer(acb, srb, XFERDATAOUT); } - static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { u16 scsi_status = *pscsi_status; - u32 d_left_counter = 0; + dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n", srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); @@ -2262,6 +2214,9 @@ static void data_in_phase0(struct Adapte * seem to be a bad idea, actually. */ if (!(srb->state & SRB_XFERPAD)) { + u32 d_left_counter; + unsigned int sc, fc; + if (scsi_status & PARITYERROR) { dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) " "Parity Error\n", srb->cmd->pid); @@ -2298,18 +2253,19 @@ #endif DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT)); } /* Now: Check remainig data: The SCSI counters should tell us ... */ - d_left_counter = DC395x_read32(acb, TRM_S1040_SCSI_COUNTER) - + ((DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f) + sc = DC395x_read32(acb, TRM_S1040_SCSI_COUNTER); + fc = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT); + d_left_counter = sc + ((fc & 0x1f) << ((srb->dcb->sync_period & WIDE_SYNC) ? 1 : 0)); dprintkdbg(DBG_KG, "data_in_phase0: " "SCSI{fifocnt=0x%02x%s ctr=0x%08x} " "DMA{fifocnt=0x%02x fifostat=0x%02x ctr=0x%08x} " "Remain{totxfer=%i scsi_fifo+ctr=%i}\n", - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT), + fc, (srb->dcb->sync_period & WIDE_SYNC) ? "words" : "bytes", - DC395x_read32(acb, TRM_S1040_SCSI_COUNTER), - DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT), + sc, + fc, DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT), DC395x_read32(acb, TRM_S1040_DMA_CXCNT), srb->total_xfer_length, d_left_counter); @@ -2317,40 +2273,79 @@ #if DC395x_LASTPIO /* KG: Less than or equal to 4 bytes can not be transfered via DMA, it seems. */ if (d_left_counter && srb->total_xfer_length <= DC395x_LASTPIO) { + size_t left_io = srb->total_xfer_length; + /*u32 addr = (srb->segment_x[srb->sg_index].address); */ /*sg_update_list (srb, d_left_counter); */ - dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) to " - "%p for remaining %i bytes:", - DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f, + dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) " + "for remaining %i bytes:", + fc & 0x1f, (srb->dcb->sync_period & WIDE_SYNC) ? "words" : "bytes", - srb->virt_addr, srb->total_xfer_length); if (srb->dcb->sync_period & WIDE_SYNC) DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, CFG2_WIDEFIFO); - while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != 0x40) { - u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); - pio_trigger(); - *(srb->virt_addr)++ = byte; - if (debug_enabled(DBG_PIO)) - printk(" %02x", byte); - d_left_counter--; - sg_subtract_one(srb); - } - if (srb->dcb->sync_period & WIDE_SYNC) { -#if 1 - /* Read the last byte ... */ - if (srb->total_xfer_length > 0) { - u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); - pio_trigger(); - *(srb->virt_addr)++ = byte; - srb->total_xfer_length--; + while (left_io) { + unsigned char *virt, *base = NULL; + unsigned long flags = 0; + size_t len = left_io; + + if (srb->cmd->use_sg) { + size_t offset = srb->request_length - left_io; + local_irq_save(flags); + /* Assumption: it's inside one page as it's at most 4 bytes and + I just assume it's on a 4-byte boundary */ + base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer, + srb->sg_count, &offset, &len); + virt = base + offset; + } else { + virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io; + len = left_io; + } + left_io -= len; + + while (len) { + u8 byte; + byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + *virt++ = byte; + if (debug_enabled(DBG_PIO)) printk(" %02x", byte); + + d_left_counter--; + sg_subtract_one(srb); + + len--; + + fc = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT); + + if (fc == 0x40) { + left_io = 0; + break; + } + } + + WARN_ON((fc != 0x40) == !d_left_counter); + + if (fc == 0x40 && (srb->dcb->sync_period & WIDE_SYNC)) { + /* Read the last byte ... */ + if (srb->total_xfer_length > 0) { + u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + + *virt++ = byte; + srb->total_xfer_length--; + if (debug_enabled(DBG_PIO)) + printk(" %02x", byte); + } + + DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0); + } + + if (srb->cmd->use_sg) { + scsi_kunmap_atomic_sg(base); + local_irq_restore(flags); } -#endif - DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0); } /*printk(" %08x", *(u32*)(bus_to_virt (addr))); */ /*srb->total_xfer_length = 0; */ @@ -2509,22 +2504,43 @@ #if DC395x_LASTPIO SCMD_FIFO_IN); } else { /* write */ int ln = srb->total_xfer_length; + size_t left_io = srb->total_xfer_length; + if (srb->dcb->sync_period & WIDE_SYNC) DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, CFG2_WIDEFIFO); - dprintkdbg(DBG_PIO, - "data_io_transfer: PIO %i bytes from %p:", - srb->total_xfer_length, srb->virt_addr); - while (srb->total_xfer_length) { - if (debug_enabled(DBG_PIO)) - printk(" %02x", (unsigned char) *(srb->virt_addr)); + while (left_io) { + unsigned char *virt, *base = NULL; + unsigned long flags = 0; + size_t len = left_io; + + if (srb->cmd->use_sg) { + size_t offset = srb->request_length - left_io; + local_irq_save(flags); + /* Again, max 4 bytes */ + base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer, + srb->sg_count, &offset, &len); + virt = base + offset; + } else { + virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io; + len = left_io; + } + left_io -= len; + + while (len--) { + if (debug_enabled(DBG_PIO)) + printk(" %02x", *virt); + + DC395x_write8(acb, TRM_S1040_SCSI_FIFO, *virt++); - pio_trigger(); - DC395x_write8(acb, TRM_S1040_SCSI_FIFO, - *(srb->virt_addr)++); + sg_subtract_one(srb); + } - sg_subtract_one(srb); + if (srb->cmd->use_sg) { + scsi_kunmap_atomic_sg(base); + local_irq_restore(flags); + } } if (srb->dcb->sync_period & WIDE_SYNC) { if (ln % 2) { @@ -3319,7 +3335,6 @@ static void pci_unmap_srb_sense(struct A srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].address; srb->segment_x[0].length = srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].length; - srb->virt_addr = srb->virt_addr_req; } @@ -3332,21 +3347,14 @@ static void srb_done(struct AdapterCtlBl { u8 tempcnt, status; struct scsi_cmnd *cmd = srb->cmd; - struct ScsiInqData *ptr; enum dma_data_direction dir = cmd->sc_data_direction; - - if (cmd->use_sg) { - struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; - ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset); - } else { - ptr = (struct ScsiInqData *)(cmd->request_buffer); - } + int ckc_only = 1; dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); - dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p addr=%p\n", + dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n", srb, cmd->use_sg, srb->sg_index, srb->sg_count, - cmd->request_buffer, ptr); + cmd->request_buffer); status = srb->target_status; if (srb->flag & AUTO_REQSENSE) { dprintkdbg(DBG_0, "srb_done: AUTO_REQSENSE1\n"); @@ -3485,29 +3493,47 @@ static void srb_done(struct AdapterCtlBl srb->segment_x[0].address, cmd->request_bufflen, dir); } - - if ((cmd->result & RES_DID) == 0 && cmd->cmnd[0] == INQUIRY - && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8 - && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2) - dcb->inquiry7 = ptr->Flags; + ckc_only = 0; /* Check Error Conditions */ ckc_e: + if (cmd->cmnd[0] == INQUIRY) { + unsigned char *base = NULL; + struct ScsiInqData *ptr; + unsigned long flags = 0; + + if (cmd->use_sg) { + struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; + size_t offset = 0, len = sizeof(struct ScsiInqData); + + local_irq_save(flags); + base = scsi_kmap_atomic_sg(sg, cmd->use_sg, &offset, &len); + ptr = (struct ScsiInqData *)(base + offset); + } else + ptr = (struct ScsiInqData *)(cmd->request_buffer); + + if (!ckc_only && (cmd->result & RES_DID) == 0 + && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8 + && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2) + dcb->inquiry7 = ptr->Flags; + /*if( srb->cmd->cmnd[0] == INQUIRY && */ /* (host_byte(cmd->result) == DID_OK || status_byte(cmd->result) & CHECK_CONDITION) ) */ - if (cmd->cmnd[0] == INQUIRY && (cmd->result == (DID_OK << 16) - || status_byte(cmd-> - result) & - CHECK_CONDITION)) { - - if (!dcb->init_tcq_flag) { - add_dev(acb, dcb, ptr); - dcb->init_tcq_flag = 1; + if ((cmd->result == (DID_OK << 16) + || status_byte(cmd->result) & + CHECK_CONDITION)) { + if (!dcb->init_tcq_flag) { + add_dev(acb, dcb, ptr); + dcb->init_tcq_flag = 1; + } } + if (cmd->use_sg) { + scsi_kunmap_atomic_sg(base); + local_irq_restore(flags); + } } - /* Here is the info for Doug Gilbert's sg3 ... */ cmd->resid = srb->total_xfer_length; /* This may be interpreted by sb. or not ... */ @@ -3713,8 +3739,6 @@ static void request_sense(struct Adapter srb->xferred = srb->total_xfer_length; /* srb->segment_x : a one entry of S/G list table */ srb->total_xfer_length = sizeof(cmd->sense_buffer); - srb->virt_addr_req = srb->virt_addr; - srb->virt_addr = cmd->sense_buffer; srb->segment_x[0].length = sizeof(cmd->sense_buffer); /* Map sense buffer */ srb->segment_x[0].address = @@ -3747,7 +3771,7 @@ static void request_sense(struct Adapter * @target: The target for the new device. * @lun: The lun for the new device. * - * Return the new device if succesfull or NULL on failure. + * Return the new device if successful or NULL on failure. **/ static struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb, u8 target, u8 lun) diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 310d2f4..c5108c8 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -145,35 +145,35 @@ #else 0, IRQ_AUTO}}; #endif -#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) +#define NO_OVERRIDES ARRAY_SIZE(overrides) static struct base { unsigned long address; int noauto; -} bases[] __initdata = { - { 0xcc000, 0 }, - { 0xc8000, 0 }, - { 0xdc000, 0 }, +} bases[] __initdata = { + { 0xcc000, 0 }, + { 0xc8000, 0 }, + { 0xdc000, 0 }, { 0xd8000, 0 } }; -#define NO_BASES (sizeof (bases) / sizeof (struct base)) +#define NO_BASES ARRAY_SIZE(bases) static const struct signature { const char *string; int offset; -} signatures[] = { +} signatures[] = { {"DATA TECHNOLOGY CORPORATION BIOS", 0x25}, }; -#define NO_SIGNATURES (sizeof (signatures) / sizeof (struct signature)) +#define NO_SIGNATURES ARRAY_SIZE(signatures) #ifndef MODULE /* * Function : dtc_setup(char *str, int *ints) * * Purpose : LILO command line initialization of the overrides array, - * + * * Inputs : str - unused, ints - array of integer parameters with ints[0] * equal to the number of ints. * diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c index 87a8c3d..ddb5124 100644 --- a/drivers/scsi/esp.c +++ b/drivers/scsi/esp.c @@ -1,7 +1,6 @@ -/* $Id: esp.c,v 1.101 2002/01/15 06:48:55 davem Exp $ - * esp.c: EnhancedScsiProcessor Sun SCSI driver code. +/* esp.c: ESP Sun SCSI driver. * - * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1995, 1998, 2006 David S. Miller (davem@davemloft.net) */ /* TODO: @@ -185,11 +184,6 @@ enum { /*5*/ do_intr_end }; -/* The master ring of all esp hosts we are managing in this driver. */ -static struct esp *espchain; -static DEFINE_SPINLOCK(espchain_lock); -static int esps_running = 0; - /* Forward declarations. */ static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs); @@ -694,36 +688,6 @@ static void __init esp_bootup_reset(stru sbus_readb(esp->eregs + ESP_INTRPT); } -static void esp_chain_add(struct esp *esp) -{ - spin_lock_irq(&espchain_lock); - if (espchain) { - struct esp *elink = espchain; - while (elink->next) - elink = elink->next; - elink->next = esp; - } else { - espchain = esp; - } - esp->next = NULL; - spin_unlock_irq(&espchain_lock); -} - -static void esp_chain_del(struct esp *esp) -{ - spin_lock_irq(&espchain_lock); - if (espchain == esp) { - espchain = esp->next; - } else { - struct esp *elink = espchain; - while (elink->next != esp) - elink = elink->next; - elink->next = esp->next; - } - esp->next = NULL; - spin_unlock_irq(&espchain_lock); -} - static int __init esp_find_dvma(struct esp *esp, struct sbus_dev *dma_sdev) { struct sbus_dev *sdev = esp->sdev; @@ -821,8 +785,8 @@ static int __init esp_register_irq(struc return -1; } - printk("esp%d: IRQ %s ", esp->esp_id, - __irq_itoa(esp->ehost->irq)); + printk("esp%d: IRQ %d ", esp->esp_id, + esp->ehost->irq); return 0; } @@ -830,19 +794,20 @@ static int __init esp_register_irq(struc static void __init esp_get_scsi_id(struct esp *esp) { struct sbus_dev *sdev = esp->sdev; + struct device_node *dp = sdev->ofdev.node; - esp->scsi_id = prom_getintdefault(esp->prom_node, - "initiator-id", - -1); + esp->scsi_id = of_getintprop_default(dp, + "initiator-id", + -1); if (esp->scsi_id == -1) - esp->scsi_id = prom_getintdefault(esp->prom_node, - "scsi-initiator-id", - -1); + esp->scsi_id = of_getintprop_default(dp, + "scsi-initiator-id", + -1); if (esp->scsi_id == -1) esp->scsi_id = (sdev->bus == NULL) ? 7 : - prom_getintdefault(sdev->bus->prom_node, - "scsi-initiator-id", - 7); + of_getintprop_default(sdev->bus->ofdev.node, + "scsi-initiator-id", + 7); esp->ehost->this_id = esp->scsi_id; esp->scsi_id_mask = (1 << esp->scsi_id); @@ -1067,28 +1032,30 @@ static void __init esp_init_swstate(stru esp->prev_hme_dmacsr = 0xffffffff; } -static int __init detect_one_esp(struct scsi_host_template *tpnt, struct sbus_dev *esp_dev, - struct sbus_dev *espdma, struct sbus_bus *sbus, - int id, int hme) +static int __init detect_one_esp(struct scsi_host_template *tpnt, + struct device *dev, + struct sbus_dev *esp_dev, + struct sbus_dev *espdma, + struct sbus_bus *sbus, + int hme) { - struct Scsi_Host *esp_host = scsi_register(tpnt, sizeof(struct esp)); + static int instance; + struct Scsi_Host *esp_host = scsi_host_alloc(tpnt, sizeof(struct esp)); struct esp *esp; - if (!esp_host) { - printk("ESP: Cannot register SCSI host\n"); - return -1; - } + if (!esp_host) + return -ENOMEM; + if (hme) esp_host->max_id = 16; esp = (struct esp *) esp_host->hostdata; esp->ehost = esp_host; esp->sdev = esp_dev; - esp->esp_id = id; + esp->esp_id = instance; esp->prom_node = esp_dev->prom_node; prom_getstring(esp->prom_node, "name", esp->prom_name, sizeof(esp->prom_name)); - esp_chain_add(esp); if (esp_find_dvma(esp, espdma) < 0) goto fail_unlink; if (esp_map_regs(esp, hme) < 0) { @@ -1115,8 +1082,19 @@ static int __init detect_one_esp(struct esp_bootup_reset(esp); + if (scsi_add_host(esp_host, dev)) + goto fail_free_irq; + + dev_set_drvdata(&esp_dev->ofdev.dev, esp); + + scsi_scan_host(esp_host); + instance++; + return 0; +fail_free_irq: + free_irq(esp->ehost->irq, esp); + fail_unmap_cmdarea: sbus_free_consistent(esp->sdev, 16, (void *) esp->esp_command, @@ -1129,119 +1107,98 @@ fail_dvma_release: esp->dma->allocated = 0; fail_unlink: - esp_chain_del(esp); - scsi_unregister(esp_host); + scsi_host_put(esp_host); return -1; } /* Detecting ESP chips on the machine. This is the simple and easy * version. */ +static int __devexit esp_remove_common(struct esp *esp) +{ + unsigned int irq = esp->ehost->irq; + + scsi_remove_host(esp->ehost); + + ESP_INTSOFF(esp->dregs); +#if 0 + esp_reset_dma(esp); + esp_reset_esp(esp); +#endif + + free_irq(irq, esp); + sbus_free_consistent(esp->sdev, 16, + (void *) esp->esp_command, esp->esp_command_dvma); + sbus_iounmap(esp->eregs, ESP_REG_SIZE); + esp->dma->allocated = 0; + + scsi_host_put(esp->ehost); + + return 0; +} + #ifdef CONFIG_SUN4 #include -static int __init esp_detect(struct scsi_host_template *tpnt) -{ - static struct sbus_dev esp_dev; - int esps_in_use = 0; - - espchain = NULL; +static struct sbus_dev sun4_esp_dev; +static int __init esp_sun4_probe(struct scsi_host_template *tpnt) +{ if (sun4_esp_physaddr) { - memset (&esp_dev, 0, sizeof(esp_dev)); - esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr; - esp_dev.irqs[0] = 4; - esp_dev.resource[0].start = sun4_esp_physaddr; - esp_dev.resource[0].end = sun4_esp_physaddr + ESP_REG_SIZE - 1; - esp_dev.resource[0].flags = IORESOURCE_IO; - - if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0)) - esps_in_use++; - printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use); - esps_running = esps_in_use; + memset(&sun4_esp_dev, 0, sizeof(esp_dev)); + sun4_esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr; + sun4_esp_dev.irqs[0] = 4; + sun4_esp_dev.resource[0].start = sun4_esp_physaddr; + sun4_esp_dev.resource[0].end = + sun4_esp_physaddr + ESP_REG_SIZE - 1; + sun4_esp_dev.resource[0].flags = IORESOURCE_IO; + + return detect_one_esp(tpnt, NULL, + &sun4_esp_dev, NULL, NULL, 0); } - return esps_in_use; + return 0; } -#else /* !CONFIG_SUN4 */ - -static int __init esp_detect(struct scsi_host_template *tpnt) +static int __devexit esp_sun4_remove(void) { - struct sbus_bus *sbus; - struct sbus_dev *esp_dev, *sbdev_iter; - int nesps = 0, esps_in_use = 0; + struct esp *esp = dev_get_drvdata(&dev->dev); - espchain = 0; - if (!sbus_root) { -#ifdef CONFIG_PCI - return 0; -#else - panic("No SBUS in esp_detect()"); -#endif - } - for_each_sbus(sbus) { - for_each_sbusdev(sbdev_iter, sbus) { - struct sbus_dev *espdma = NULL; - int hme = 0; - - /* Is it an esp sbus device? */ - esp_dev = sbdev_iter; - if (strcmp(esp_dev->prom_name, "esp") && - strcmp(esp_dev->prom_name, "SUNW,esp")) { - if (!strcmp(esp_dev->prom_name, "SUNW,fas")) { - hme = 1; - espdma = esp_dev; - } else { - if (!esp_dev->child || - (strcmp(esp_dev->prom_name, "espdma") && - strcmp(esp_dev->prom_name, "dma"))) - continue; /* nope... */ - espdma = esp_dev; - esp_dev = esp_dev->child; - if (strcmp(esp_dev->prom_name, "esp") && - strcmp(esp_dev->prom_name, "SUNW,esp")) - continue; /* how can this happen? */ - } - } - - if (detect_one_esp(tpnt, esp_dev, espdma, sbus, nesps++, hme) < 0) - continue; - - esps_in_use++; - } /* for each sbusdev */ - } /* for each sbus */ - printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, - esps_in_use); - esps_running = esps_in_use; - return esps_in_use; + return esp_remove_common(esp); } -#endif /* !CONFIG_SUN4 */ +#else /* !CONFIG_SUN4 */ -/* - */ -static int esp_release(struct Scsi_Host *host) +static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match) { - struct esp *esp = (struct esp *) host->hostdata; + struct sbus_dev *sdev = to_sbus_device(&dev->dev); + struct device_node *dp = dev->node; + struct sbus_dev *dma_sdev = NULL; + int hme = 0; + + if (dp->parent && + (!strcmp(dp->parent->name, "espdma") || + !strcmp(dp->parent->name, "dma"))) + dma_sdev = sdev->parent; + else if (!strcmp(dp->name, "SUNW,fas")) { + dma_sdev = sdev; + hme = 1; + } - ESP_INTSOFF(esp->dregs); -#if 0 - esp_reset_dma(esp); - esp_reset_esp(esp); -#endif + return detect_one_esp(match->data, &dev->dev, + sdev, dma_sdev, sdev->bus, hme); +} - free_irq(esp->ehost->irq, esp); - sbus_free_consistent(esp->sdev, 16, - (void *) esp->esp_command, esp->esp_command_dvma); - sbus_iounmap(esp->eregs, ESP_REG_SIZE); - esp->dma->allocated = 0; - esp_chain_del(esp); +static int __devexit esp_sbus_remove(struct of_device *dev) +{ + struct esp *esp = dev_get_drvdata(&dev->dev); - return 0; + return esp_remove_common(esp); } +#endif /* !CONFIG_SUN4 */ + /* The info function will return whatever useful * information the developer sees fit. If not provided, then * the name field will be used instead. @@ -1415,18 +1372,11 @@ static int esp_host_info(struct esp *esp static int esp_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout) { - struct esp *esp; + struct esp *esp = (struct esp *) host->hostdata; if (inout) return -EINVAL; /* not yet */ - for_each_esp(esp) { - if (esp->ehost == host) - break; - } - if (!esp) - return -EINVAL; - if (start) *start = buffer; @@ -4377,15 +4327,12 @@ static void esp_slave_destroy(struct scs SDptr->hostdata = NULL; } -static struct scsi_host_template driver_template = { - .proc_name = "esp", - .proc_info = esp_proc_info, - .name = "Sun ESP 100/100a/200", - .detect = esp_detect, +static struct scsi_host_template esp_template = { + .module = THIS_MODULE, + .name = "esp", + .info = esp_info, .slave_alloc = esp_slave_alloc, .slave_destroy = esp_slave_destroy, - .release = esp_release, - .info = esp_info, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, .eh_bus_reset_handler = esp_reset, @@ -4394,12 +4341,58 @@ static struct scsi_host_template driver_ .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, + .proc_name = "esp", + .proc_info = esp_proc_info, +}; + +#ifndef CONFIG_SUN4 +static struct of_device_id esp_match[] = { + { + .name = "SUNW,esp", + .data = &esp_template, + }, + { + .name = "SUNW,fas", + .data = &esp_template, + }, + { + .name = "esp", + .data = &esp_template, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, esp_match); + +static struct of_platform_driver esp_sbus_driver = { + .name = "esp", + .match_table = esp_match, + .probe = esp_sbus_probe, + .remove = __devexit_p(esp_sbus_remove), }; +#endif + +static int __init esp_init(void) +{ +#ifdef CONFIG_SUN4 + return esp_sun4_probe(&esp_template); +#else + return of_register_driver(&esp_sbus_driver, &sbus_bus_type); +#endif +} -#include "scsi_module.c" +static void __exit esp_exit(void) +{ +#ifdef CONFIG_SUN4 + esp_sun4_remove(); +#else + of_unregister_driver(&esp_sbus_driver); +#endif +} -MODULE_DESCRIPTION("EnhancedScsiProcessor Sun SCSI driver"); -MODULE_AUTHOR("David S. Miller (davem@redhat.com)"); +MODULE_DESCRIPTION("ESP Sun SCSI driver"); +MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +module_init(esp_init); +module_exit(esp_exit); diff --git a/drivers/scsi/esp.h b/drivers/scsi/esp.h index 73f7d69..a98cda9 100644 --- a/drivers/scsi/esp.h +++ b/drivers/scsi/esp.h @@ -403,8 +403,4 @@ #define ESP_NEG_DEFP(mhz, cfact) \ #define ESP_MHZ_TO_CYCLE(mhertz) ((1000000000) / ((mhertz) / 1000)) #define ESP_TICK(ccf, cycle) ((7682 * (ccf) * (cycle) / 1000)) -/* For our interrupt engine. */ -#define for_each_esp(esp) \ - for((esp) = espchain; (esp); (esp) = (esp)->next) - #endif /* !(_SPARC_ESP_H) */ diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c index cca485a..70a1606 100644 --- a/drivers/scsi/fd_mcs.c +++ b/drivers/scsi/fd_mcs.c @@ -279,7 +279,7 @@ static struct fd_mcs_adapters_struct fd_ 2}, }; -#define FD_BRDS sizeof(fd_mcs_adapters)/sizeof(struct fd_mcs_adapters_struct) +#define FD_BRDS ARRAY_SIZE(fd_mcs_adapters) static irqreturn_t fd_mcs_intr(int irq, void *dev_id, struct pt_regs *regs); diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 7334244..e16013f 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -420,10 +420,10 @@ static unsigned long addresses[] = { 0xd0000, 0xe0000, }; -#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) - +#define ADDRESS_COUNT ARRAY_SIZE(addresses) + static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; -#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short )) +#define PORT_COUNT ARRAY_SIZE(ports) static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; @@ -502,7 +502,7 @@ static struct signature { geometry location are verified). */ }; -#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) +#define SIGNATURE_COUNT ARRAY_SIZE(signatures) static void print_banner( struct Scsi_Host *shpnt ) { @@ -519,7 +519,7 @@ static void print_banner( struct Scsi_Ho if (bios_minor >= 0) printk("%d", bios_minor); else printk("?."); - + printk( " at 0x%lx using scsi id %d\n", bios_base, shpnt->this_id ); } diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index e6bcfe9..5f313c9 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -138,10 +138,9 @@ #else [1] __initdata = { { 0,},}; #endif +#define NO_OVERRIDES ARRAY_SIZE(overrides) -#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) - -#ifndef MODULE +#ifndef MODULE /** * internal_setup - handle lilo command string override @@ -210,7 +209,7 @@ static int __init do_NCR5380_setup(char { int ints[10]; - get_options(str, sizeof(ints) / sizeof(int), ints); + get_options(str, ARRAY_SIZE(ints), ints); internal_setup(BOARD_NCR5380, str, ints); return 1; } @@ -218,7 +217,7 @@ static int __init do_NCR5380_setup(char /** * do_NCR53C400_setup - set up entry point * @str: unused - * @ints: integer parameters from kernel setup code + * @ints: integer parameters from kernel setup code * * Setup function invoked at boot to parse the ncr53c400= command * line. @@ -228,7 +227,7 @@ static int __init do_NCR53C400_setup(cha { int ints[10]; - get_options(str, sizeof(ints) / sizeof(int), ints); + get_options(str, ARRAY_SIZE(ints), ints); internal_setup(BOARD_NCR53C400, str, ints); return 1; } @@ -236,7 +235,7 @@ static int __init do_NCR53C400_setup(cha /** * do_NCR53C400A_setup - set up entry point * @str: unused - * @ints: integer parameters from kernel setup code + * @ints: integer parameters from kernel setup code * * Setup function invoked at boot to parse the ncr53c400a= command * line. @@ -246,7 +245,7 @@ static int __init do_NCR53C400A_setup(ch { int ints[10]; - get_options(str, sizeof(ints) / sizeof(int), ints); + get_options(str, ARRAY_SIZE(ints), ints); internal_setup(BOARD_NCR53C400A, str, ints); return 1; } @@ -254,7 +253,7 @@ static int __init do_NCR53C400A_setup(ch /** * do_DTC3181E_setup - set up entry point * @str: unused - * @ints: integer parameters from kernel setup code + * @ints: integer parameters from kernel setup code * * Setup function invoked at boot to parse the dtc3181e= command * line. @@ -264,7 +263,7 @@ static int __init do_DTC3181E_setup(char { int ints[10]; - get_options(str, sizeof(ints) / sizeof(int), ints); + get_options(str, ARRAY_SIZE(ints), ints); internal_setup(BOARD_DTC3181E, str, ints); return 1; } diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index d5740bb..76071a1 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4,9 +4,9 @@ * Intel Corporation: Storage RAID Controllers * * * * gdth.c * - * Copyright (C) 1995-04 ICP vortex GmbH, Achim Leubner * + * Copyright (C) 1995-06 ICP vortex GmbH, Achim Leubner * * Copyright (C) 2002-04 Intel Corporation * - * Copyright (C) 2003-04 Adaptec Inc. * + * Copyright (C) 2003-06 Adaptec Inc. * * * * * * Additions/Fixes: * @@ -27,9 +27,14 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Linux kernel 2.2.x, 2.4.x, 2.6.x supported * + * Linux kernel 2.4.x, 2.6.x supported * * * * $Log: gdth.c,v $ + * Revision 1.74 2006/04/10 13:44:47 achim + * Community changes for 2.6.x + * Kernel 2.2.x no longer supported + * scsi_request interface removed, thanks to Christoph Hellwig + * * Revision 1.73 2004/03/31 13:33:03 achim * Special command 0xfd implemented to detect 64-bit DMA support * @@ -94,7 +99,7 @@ * Bugfix free_irq() * * Revision 1.56 2001/08/09 11:19:39 achim - * struct scsi_host_template changes + * Scsi_Host_Template changes * * Revision 1.55 2001/08/09 10:11:28 achim * Command HOST_UNFREEZE_IO before cache service init. @@ -388,7 +393,13 @@ #include #include #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6) #include +#else +#define DMA_32BIT_MASK 0x00000000ffffffffULL +#define DMA_64BIT_MASK 0xffffffffffffffffULL +#endif + #ifdef GDTH_RTC #include #endif @@ -408,8 +419,8 @@ #endif #include "scsi.h" #include -#include "gdth.h" #include "gdth_kcompat.h" +#include "gdth.h" static void gdth_delay(int milliseconds); static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs); @@ -464,6 +475,8 @@ static int gdth_ioctl(struct inode *inod static void gdth_flush(int hanum); static int gdth_halt(struct notifier_block *nb, ulong event, void *buf); +static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)); +static void gdth_scsi_done(struct scsi_cmnd *scp); #ifdef DEBUG_GDTH static unchar DebugState = DEBUG_GDTH; @@ -556,8 +569,8 @@ static struct timer_list gdth_timer; #endif #define PTR2USHORT(a) (ushort)(ulong)(a) -#define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b) -#define INDEX_OK(i,t) ((i)b) +#define INDEX_OK(i,t) ((i)hostdata)) #define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext) @@ -643,6 +656,7 @@ static int probe_eisa_isa = 0; static int force_dma32 = 0; /* parameters for modprobe/insmod */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) module_param_array(irq, int, NULL, 0); module_param(disable, int, 0); module_param(reserve_mode, int, 0); @@ -655,6 +669,20 @@ module_param(virt_ctr, int, 0); module_param(shared_access, int, 0); module_param(probe_eisa_isa, int, 0); module_param(force_dma32, int, 0); +#else +MODULE_PARM(irq, "i"); +MODULE_PARM(disable, "i"); +MODULE_PARM(reserve_mode, "i"); +MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i"); +MODULE_PARM(reverse_scan, "i"); +MODULE_PARM(hdr_channel, "i"); +MODULE_PARM(max_ids, "i"); +MODULE_PARM(rescan, "i"); +MODULE_PARM(virt_ctr, "i"); +MODULE_PARM(shared_access, "i"); +MODULE_PARM(probe_eisa_isa, "i"); +MODULE_PARM(force_dma32, "i"); +#endif MODULE_AUTHOR("Achim Leubner"); MODULE_LICENSE("GPL"); @@ -683,6 +711,91 @@ static void gdth_delay(int milliseconds) } } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +static void gdth_scsi_done(struct scsi_cmnd *scp) +{ + TRACE2(("gdth_scsi_done()\n")); + + if (scp->request) + complete((struct completion *)scp->request); +} + +int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, + int timeout, u32 *info) +{ + Scsi_Cmnd *scp; + DECLARE_COMPLETION(wait); + int rval; + + scp = kmalloc(sizeof(*scp), GFP_KERNEL); + if (!scp) + return -ENOMEM; + memset(scp, 0, sizeof(*scp)); + scp->device = sdev; + /* use request field to save the ptr. to completion struct. */ + scp->request = (struct request *)&wait; + scp->timeout_per_command = timeout*HZ; + scp->request_buffer = gdtcmd; + scp->cmd_len = 12; + memcpy(scp->cmnd, cmnd, 12); + scp->SCp.this_residual = IOCTL_PRI; /* priority */ + scp->done = gdth_scsi_done; /* some fn. test this */ + gdth_queuecommand(scp, gdth_scsi_done); + wait_for_completion(&wait); + + rval = scp->SCp.Status; + if (info) + *info = scp->SCp.Message; + kfree(scp); + return rval; +} +#else +static void gdth_scsi_done(Scsi_Cmnd *scp) +{ + TRACE2(("gdth_scsi_done()\n")); + + scp->request.rq_status = RQ_SCSI_DONE; + if (scp->request.waiting) + complete(scp->request.waiting); +} + +int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, + int timeout, u32 *info) +{ + Scsi_Cmnd *scp = scsi_allocate_device(sdev, 1, FALSE); + unsigned bufflen = gdtcmd ? sizeof(gdth_cmd_str) : 0; + DECLARE_COMPLETION(wait); + int rval; + + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; + scp->SCp.this_residual = IOCTL_PRI; /* priority */ + scp->request.rq_status = RQ_SCSI_BUSY; + scp->request.waiting = &wait; + scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); + wait_for_completion(&wait); + + rval = scp->SCp.Status; + if (info) + *info = scp->SCp.Message; + + scsi_release_command(scp); + return rval; +} +#endif + +int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd, + int timeout, u32 *info) +{ + struct scsi_device *sdev = scsi_get_host_dev(shost); + int rval = __gdth_execute(sdev, gdtcmd, cmnd, timeout, info); + + scsi_free_host_dev(sdev); + return rval; +} + static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs) { *cyls = size /HEADS/SECS; @@ -773,7 +886,7 @@ static struct pci_device_id gdthtable[] MODULE_DEVICE_TABLE(pci,gdthtable); static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, - ushort vendor, ushort device) + ushort vendor, ushort device) { ulong base0, base1, base2; struct pci_dev *pdev; @@ -2248,14 +2361,16 @@ static void gdth_putq(int hanum,Scsi_Cmn ha = HADATA(gdth_ctr_tab[hanum]); spin_lock_irqsave(&ha->smp_lock, flags); - scp->SCp.this_residual = (int)priority; - b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; - t = scp->device->id; - if (priority >= DEFAULT_PRI) { - if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || - (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) { - TRACE2(("gdth_putq(): locked IO -> update_timeout()\n")); - scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + if (scp->done != gdth_scsi_done) { + scp->SCp.this_residual = (int)priority; + b = virt_ctr ? NUMDATA(scp->device->host)->busnum:scp->device->channel; + t = scp->device->id; + if (priority >= DEFAULT_PRI) { + if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || + (b==ha->virt_bus && thdr[t].lock)) { + TRACE2(("gdth_putq(): locked IO ->update_timeout()\n")); + scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + } } } @@ -2309,14 +2424,18 @@ static void gdth_next(int hanum) for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) { if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr) pscp = (Scsi_Cmnd *)pscp->SCp.ptr; - b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel; - t = nscp->device->id; - l = nscp->device->lun; - if (nscp->SCp.this_residual >= DEFAULT_PRI) { - if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || - (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) - continue; - } + if (nscp->done != gdth_scsi_done) { + b = virt_ctr ? + NUMDATA(nscp->device->host)->busnum : nscp->device->channel; + t = nscp->device->id; + l = nscp->device->lun; + if (nscp->SCp.this_residual >= DEFAULT_PRI) { + if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || + (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) + continue; + } + } else + b = t = l = 0; if (firsttime) { if (gdth_test_busy(hanum)) { /* controller busy ? */ @@ -2331,7 +2450,7 @@ static void gdth_next(int hanum) firsttime = FALSE; } - if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) { + if (nscp->done != gdth_scsi_done) { if (nscp->SCp.phase == -1) { nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */ if (nscp->cmnd[0] == TEST_UNIT_READY) { @@ -2394,7 +2513,7 @@ static void gdth_next(int hanum) else nscp->scsi_done(nscp); } - } else if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) { + } else if (nscp->done == gdth_scsi_done) { if (!(cmd_index=gdth_special_cmd(hanum,nscp))) this_cmd = FALSE; next_cmd = FALSE; @@ -2542,13 +2661,13 @@ static void gdth_copy_internal_data(int gdth_ha_str *ha; char *address; - cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen; + cpcount = count<=(ushort)scp->request_bufflen ? count:(ushort)scp->request_bufflen; ha = HADATA(gdth_ctr_tab[hanum]); if (scp->use_sg) { sl = (struct scatterlist *)scp->request_buffer; for (i=0,cpsum=0; iuse_sg; ++i,++sl) { - unsigned long flags; + unsigned long flags; cpnow = (ushort)sl->length; TRACE(("copy_internal() now %d sum %d count %d %d\n", cpnow,cpsum,cpcount,(ushort)scp->bufflen)); @@ -2560,12 +2679,19 @@ static void gdth_copy_internal_data(int hanum); return; } - local_irq_save(flags); - address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset; + local_irq_save(flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset; + memcpy(address,buffer,cpnow); + flush_dcache_page(sl->page); + kunmap_atomic(address, KM_BIO_SRC_IRQ); +#else + address = kmap_atomic(sl->page, KM_BH_IRQ) + sl->offset; memcpy(address,buffer,cpnow); - flush_dcache_page(sl->page); - kunmap_atomic(address, KM_BIO_SRC_IRQ); - local_irq_restore(flags); + flush_dcache_page(sl->page); + kunmap_atomic(address, KM_BH_IRQ); +#endif + local_irq_restore(flags); if (cpsum == cpcount) break; buffer += cpnow; @@ -2946,9 +3072,9 @@ static int gdth_fill_raw_cmd(int hanum,S offset = (ulong)scp->sense_buffer & ~PAGE_MASK; sense_paddr = pci_map_page(ha->pdev,page,offset, 16,PCI_DMA_FROMDEVICE); - scp->SCp.buffer = (struct scatterlist *)((ulong32)sense_paddr); + *(ulong32 *)&scp->SCp.buffer = (ulong32)sense_paddr; /* high part, if 64bit */ - scp->host_scribble = (char *)(ulong32)((ulong64)sense_paddr >> 32); + *(ulong32 *)&scp->host_scribble = (ulong32)((ulong64)sense_paddr >> 32); cmdp->OpCode = GDT_WRITE; /* always */ cmdp->BoardNode = LOCALBOARD; if (mode64) { @@ -3022,7 +3148,7 @@ #ifdef GDTH_STATISTICS } #endif - } else { + } else if (scp->request_bufflen) { scp->SCp.Status = GDTH_MAP_SINGLE; scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; page = virt_to_page(scp->request_buffer); @@ -3309,7 +3435,7 @@ #endif } if (!gdth_polling) - spin_lock_irqsave(&ha2->smp_lock, flags); + spin_lock_irqsave(&ha2->smp_lock, flags); wait_index = 0; /* search controller */ @@ -3642,9 +3768,10 @@ static int gdth_sync_event(int hanum,int scp->request_bufflen,scp->SCp.Message); if (scp->SCp.buffer) { dma_addr_t addr; - addr = (dma_addr_t)(ulong32)scp->SCp.buffer; + addr = (dma_addr_t)*(ulong32 *)&scp->SCp.buffer; if (scp->host_scribble) - addr += (dma_addr_t)((ulong64)(ulong32)scp->host_scribble << 32); + addr += (dma_addr_t) + ((ulong64)(*(ulong32 *)&scp->host_scribble) << 32); pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE); } @@ -4154,7 +4281,11 @@ int __init option_setup(char *str) return 1; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static int __init gdth_detect(struct scsi_host_template *shtp) +#else +static int __init gdth_detect(Scsi_Host_Template *shtp) +#endif { struct Scsi_Host *shp; gdth_pci_str pcistr[MAXHA]; @@ -4188,7 +4319,7 @@ #endif return 0; } - printk("GDT-HA: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR); + printk("GDT-HA: Storage RAID Controller Driver. Version: %s\n",GDTH_VERSION_STR); /* initializations */ gdth_polling = TRUE; b = 0; gdth_clear_events(); @@ -4751,7 +4882,7 @@ static int gdth_eh_bus_reset(Scsi_Cmnd * gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS, BUS_L2P(ha,b), 0, 0); gdth_polling = FALSE; - spin_unlock_irqrestore(&ha->smp_lock, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); } return SUCCESS; } @@ -4819,7 +4950,9 @@ #endif priority = DEFAULT_PRI; if (scp->done == gdth_scsi_done) priority = scp->SCp.this_residual; - gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6); + else + gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6); + gdth_putq( hanum, scp, priority ); gdth_next( hanum ); return 0; @@ -4922,11 +5055,7 @@ static int ioc_resetdrv(void __user *arg gdth_cmd_str cmd; int hanum; gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; -#else - Scsi_Cmnd *scp; -#endif + int rval; if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) || res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES) @@ -4943,25 +5072,11 @@ #endif cmd.u.cache64.DeviceNo = res.number; else cmd.u.cache.DeviceNo = res.number; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &cmd, cmnd, 30); - res.status = (ushort)srp->sr_command->SCp.Status; - scsi_release_request(srp); -#else - scp = scsi_allocate_device(ha->sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &cmd, cmnd, 30); - res.status = (ushort)scp->SCp.Status; - scsi_release_command(scp); -#endif + + rval = __gdth_execute(ha->sdev, &cmd, cmnd, 30, NULL); + if (rval < 0) + return rval; + res.status = rval; if (copy_to_user(arg, &res, sizeof(gdth_ioctl_reset))) return -EFAULT; @@ -4974,12 +5089,8 @@ static int ioc_general(void __user *arg, char *buf = NULL; ulong64 paddr; int hanum; - gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; -#else - Scsi_Cmnd *scp; -#endif + gdth_ha_str *ha; + int rval; if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)) || gen.ionode >= gdth_ctr_count) @@ -5071,27 +5182,10 @@ #endif } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &gen.command, cmnd, gen.timeout); - gen.status = srp->sr_command->SCp.Status; - gen.info = srp->sr_command->SCp.Message; - scsi_release_request(srp); -#else - scp = scsi_allocate_device(ha->sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout); - gen.status = scp->SCp.Status; - gen.info = scp->SCp.Message; - scsi_release_command(scp); -#endif + rval = __gdth_execute(ha->sdev, &gen.command, cmnd, gen.timeout, &gen.info); + if (rval < 0) + return rval; + gen.status = rval; if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf, gen.data_len + gen.sense_len)) { @@ -5114,40 +5208,22 @@ static int ioc_hdrlist(void __user *arg, gdth_ha_str *ha; unchar i; int hanum, rc = -ENOMEM; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; -#else - Scsi_Cmnd *scp; -#endif - + u32 cluster_type = 0; + rsc = kmalloc(sizeof(*rsc), GFP_KERNEL); cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); if (!rsc || !cmd) - goto free_fail; + goto free_fail; if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) || rsc->ionode >= gdth_ctr_count) { rc = -EFAULT; - goto free_fail; + goto free_fail; } hanum = rsc->ionode; ha = HADATA(gdth_ctr_tab[hanum]); memset(cmd, 0, sizeof(gdth_cmd_str)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); - if (!srp) - goto free_fail; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#else - scp = scsi_allocate_device(ha->sdev, 1, FALSE); - if (!scp) - goto free_fail; - scp->cmd_len = 12; - scp->use_sg = 0; -#endif - for (i = 0; i < MAX_HDRIVES; ++i) { if (!ha->hdr[i].present) { rsc->hdr_list[i].bus = 0xff; @@ -5164,27 +5240,15 @@ #endif cmd->u.cache64.DeviceNo = i; else cmd->u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - if (srp->sr_command->SCp.Status == S_OK) - rsc->hdr_list[i].cluster_type = srp->sr_command->SCp.Message; -#else - gdth_do_cmd(scp, cmd, cmnd, 30); - if (scp->SCp.Status == S_OK) - rsc->hdr_list[i].cluster_type = scp->SCp.Message; -#endif + if (__gdth_execute(ha->sdev, cmd, cmnd, 30, &cluster_type) == S_OK) + rsc->hdr_list[i].cluster_type = cluster_type; } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scsi_release_request(srp); -#else - scsi_release_command(scp); -#endif - + if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan))) rc = -EFAULT; else - rc = 0; + rc = 0; free_fail: kfree(rsc); @@ -5202,40 +5266,21 @@ static int ioc_rescan(void __user *arg, int rc = -ENOMEM; ulong flags; gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; -#else - Scsi_Cmnd *scp; -#endif rsc = kmalloc(sizeof(*rsc), GFP_KERNEL); cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd || !rsc) - goto free_fail; + goto free_fail; if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) || rsc->ionode >= gdth_ctr_count) { - rc = -EFAULT; - goto free_fail; + rc = -EFAULT; + goto free_fail; } hanum = rsc->ionode; ha = HADATA(gdth_ctr_tab[hanum]); memset(cmd, 0, sizeof(gdth_cmd_str)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); - if (!srp) - goto free_fail; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#else - scp = scsi_allocate_device(ha->sdev, 1, FALSE); - if (!scp) - goto free_fail; - scp->cmd_len = 12; - scp->use_sg = 0; -#endif - if (rsc->flag == 0) { /* old method: re-init. cache service */ cmd->Service = CACHESERVICE; @@ -5246,19 +5291,8 @@ #endif cmd->OpCode = GDT_INIT; cmd->u.cache.DeviceNo = LINUX_OS; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - gdth_do_cmd(scp, cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); i = 0; hdr_cnt = (status == S_OK ? (ushort)info : 0); } else { @@ -5273,15 +5307,9 @@ #endif cmd->u.cache64.DeviceNo = i; else cmd->u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#else - gdth_do_cmd(scp, cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#endif + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + spin_lock_irqsave(&ha->smp_lock, flags); rsc->hdr_list[i].bus = ha->virt_bus; rsc->hdr_list[i].target = i; @@ -5313,15 +5341,9 @@ #endif cmd->u.cache64.DeviceNo = i; else cmd->u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#else - gdth_do_cmd(scp, cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#endif + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + spin_lock_irqsave(&ha->smp_lock, flags); ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0); spin_unlock_irqrestore(&ha->smp_lock, flags); @@ -5332,15 +5354,9 @@ #endif cmd->u.cache64.DeviceNo = i; else cmd->u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#else - gdth_do_cmd(scp, cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#endif + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + spin_lock_irqsave(&ha->smp_lock, flags); ha->hdr[i].cluster_type = ((status == S_OK && !shared_access) ? (ushort)info : 0); @@ -5353,29 +5369,18 @@ #endif cmd->u.cache64.DeviceNo = i; else cmd->u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#else - gdth_do_cmd(scp, cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#endif + + status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info); + spin_lock_irqsave(&ha->smp_lock, flags); ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0); spin_unlock_irqrestore(&ha->smp_lock, flags); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scsi_release_request(srp); -#else - scsi_release_command(scp); -#endif if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan))) rc = -EFAULT; else - rc = 0; + rc = 0; free_fail: kfree(rsc); @@ -5515,17 +5520,18 @@ static int gdth_ioctl(struct inode *inod hanum = res.ionode; ha = HADATA(gdth_ctr_tab[hanum]); - /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.6.x */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scp = scsi_get_command(ha->sdev, GFP_KERNEL); + scp = kmalloc(sizeof(*scp), GFP_KERNEL); if (!scp) return -ENOMEM; + memset(scp, 0, sizeof(*scp)); + scp->device = ha->sdev; scp->cmd_len = 12; scp->use_sg = 0; scp->device->channel = virt_ctr ? 0 : res.number; rval = gdth_eh_bus_reset(scp); res.status = (rval == SUCCESS ? S_OK : S_GENERR); - scsi_put_command(scp); + kfree(scp); #else scp = scsi_allocate_device(ha->sdev, 1, FALSE); if (!scp) @@ -5558,34 +5564,12 @@ static void gdth_flush(int hanum) int i; gdth_ha_str *ha; gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; -#else - Scsi_Cmnd *scp; -#endif - struct scsi_device *sdev; char cmnd[MAX_COMMAND_SIZE]; memset(cmnd, 0xff, MAX_COMMAND_SIZE); TRACE2(("gdth_flush() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#else - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return; - scp->cmd_len = 12; - scp->use_sg = 0; -#endif - for (i = 0; i < MAX_HDRIVES; ++i) { if (ha->hdr[i].present) { gdtcmd.BoardNode = LOCALBOARD; @@ -5601,20 +5585,10 @@ #endif gdtcmd.u.cache.sg_canz = 0; } TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(srp, &gdtcmd, cmnd, 30); -#else - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); -#endif + + gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 30, NULL); } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#else - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#endif } /* shutdown routine */ @@ -5623,18 +5597,11 @@ static int gdth_halt(struct notifier_blo int hanum; #ifndef __alpha__ gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *srp; - struct scsi_device *sdev; -#else - Scsi_Cmnd *scp; - struct scsi_device *sdev; -#endif char cmnd[MAX_COMMAND_SIZE]; #endif if (notifier_disabled) - return NOTIFY_OK; + return NOTIFY_OK; TRACE2(("gdth_halt() event %d\n",(int)event)); if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) @@ -5652,31 +5619,7 @@ #ifndef __alpha__ gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_RESET; TRACE2(("gdth_halt(): reset controller %d\n", hanum)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) { - unregister_reboot_notifier(&gdth_notifier); - return NOTIFY_OK; - } - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &gdtcmd, cmnd, 10); - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#else - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) { - unregister_reboot_notifier(&gdth_notifier); - return NOTIFY_OK; - } - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &gdtcmd, cmnd, 10); - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#endif + gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 10, NULL); #endif } printk("Done.\n"); @@ -5687,7 +5630,22 @@ #endif return NOTIFY_OK; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +/* configure lun */ +static int gdth_slave_configure(struct scsi_device *sdev) +{ + scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); + sdev->skip_ms_page_3f = 1; + sdev->skip_ms_page_8 = 1; + return 0; +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static struct scsi_host_template driver_template = { +#else +static Scsi_Host_Template driver_template = { +#endif .proc_name = "gdth", .proc_info = gdth_proc_info, .name = "GDT SCSI Disk Array Controller", @@ -5698,6 +5656,9 @@ static struct scsi_host_template driver_ .eh_bus_reset_handler = gdth_eh_bus_reset, .bios_param = gdth_bios_param, .can_queue = GDTH_MAXCMDS, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + .slave_configure = gdth_slave_configure, +#endif .this_id = -1, .sg_tablesize = GDTH_MAXSG, .cmd_per_lun = GDTH_MAXC_P_L, diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index cc4882f..47eae02 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -4,13 +4,13 @@ #define _GDTH_H /* * Header file for the GDT Disk Array/Storage RAID controllers driver for Linux * - * gdth.h Copyright (C) 1995-03 ICP vortex, Achim Leubner + * gdth.h Copyright (C) 1995-06 ICP vortex, Achim Leubner * See gdth.c for further informations and * below for supported controller types * * * - * $Id: gdth.h,v 1.57 2004/03/31 11:52:09 achim Exp $ + * $Id: gdth.h,v 1.58 2006/01/11 16:14:09 achim Exp $ */ #include @@ -26,9 +26,9 @@ #endif /* defines, macros */ /* driver version */ -#define GDTH_VERSION_STR "3.04" +#define GDTH_VERSION_STR "3.05" #define GDTH_VERSION 3 -#define GDTH_SUBVERSION 4 +#define GDTH_SUBVERSION 5 /* protocol version */ #define PROTOCOL_VERSION 1 diff --git a/drivers/scsi/gdth_kcompat.h b/drivers/scsi/gdth_kcompat.h index e6cf0ed..2a302ee 100644 --- a/drivers/scsi/gdth_kcompat.h +++ b/drivers/scsi/gdth_kcompat.h @@ -1,5 +1,3 @@ - - #ifndef IRQ_HANDLED typedef void irqreturn_t; #define IRQ_NONE @@ -10,6 +8,18 @@ #ifndef MODULE_LICENSE #define MODULE_LICENSE(x) #endif +#ifndef __iomem +#define __iomem +#endif + +#ifndef __attribute_used__ +#define __attribute_used__ __devinitdata +#endif + +#ifndef __user +#define __user +#endif + #ifndef SERVICE_ACTION_IN #define SERVICE_ACTION_IN 0x9e #endif diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c index 5e8657f..32982eb 100644 --- a/drivers/scsi/gdth_proc.c +++ b/drivers/scsi/gdth_proc.c @@ -1,5 +1,5 @@ /* gdth_proc.c - * $Id: gdth_proc.c,v 1.42 2004/03/05 15:50:20 achim Exp $ + * $Id: gdth_proc.c,v 1.43 2006/01/11 16:15:00 achim Exp $ */ #include @@ -51,57 +51,26 @@ #endif static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, int hanum,int busnum) { - int ret_val = -EINVAL; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *scp; - struct scsi_device *sdev; -#else - Scsi_Cmnd *scp; - struct scsi_device *sdev; -#endif - TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); + int ret_val = -EINVAL; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - sdev = scsi_get_host_dev(host); - scp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!scp) - return -ENOMEM; - scp->sr_cmd_len = 12; - scp->sr_use_sg = 0; -#else - sdev = scsi_get_host_dev(host); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; -#endif + TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); if (length >= 4) { if (strncmp(buffer,"gdth",4) == 0) { buffer += 5; length -= 5; - ret_val = gdth_set_asc_info( buffer, length, hanum, scp ); + ret_val = gdth_set_asc_info(host, buffer, length, hanum); } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scsi_release_request(scp); - scsi_free_host_dev(sdev); -#else - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#endif + return ret_val; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp) -#else -static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp) -#endif +static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, + int length,int hanum) { - int orig_length, drive, wb_mode; - int i, found; + int orig_length, drive, wb_mode; + int i, found; gdth_ha_str *ha; gdth_cmd_str gdtcmd; gdth_cpar_str *pcpar; @@ -146,11 +115,8 @@ #endif gdtcmd.u.cache.DeviceNo = i; gdtcmd.u.cache.BlockNo = 1; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, &gdtcmd, cmnd, 30); -#else - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); -#endif + + gdth_execute(host, &gdtcmd, cmnd, 30, NULL); } } if (!found) @@ -202,11 +168,9 @@ #endif gdtcmd.u.ioctl.subfunc = CACHE_CONFIG; gdtcmd.u.ioctl.channel = INVALID_CHANNEL; pcpar->write_back = wb_mode==1 ? 0:1; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, &gdtcmd, cmnd, 30); -#else - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); -#endif + + gdth_execute(host, &gdtcmd, cmnd, 30, NULL); + gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr); printk("Done.\n"); return(orig_length); @@ -230,13 +194,6 @@ static int gdth_get_info(char *buffer,ch gdth_cmd_str *gdtcmd; gdth_evt_str *estr; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - Scsi_Request *scp; - struct scsi_device *sdev; -#else - Scsi_Cmnd *scp; - struct scsi_device *sdev; -#endif char hrec[161]; struct timeval tv; @@ -252,7 +209,7 @@ #endif gdtcmd = kmalloc(sizeof(*gdtcmd), GFP_KERNEL); estr = kmalloc(sizeof(*estr), GFP_KERNEL); if (!gdtcmd || !estr) - goto free_fail; + goto free_fail; memset(cmnd, 0xff, 12); memset(gdtcmd, 0, sizeof(gdth_cmd_str)); @@ -260,28 +217,6 @@ #endif TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum)); ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - sdev = scsi_get_host_dev(host); - scp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!scp) - goto free_fail; - scp->sr_cmd_len = 12; - scp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - sdev = scsi_get_host_dev(host); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - goto free_fail; - scp->cmd_len = 12; - scp->use_sg = 0; -#else - memset(&sdev,0,sizeof(struct scsi_device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = host; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; -#endif - /* request is i.e. "cat /proc/scsi/gdth/0" */ /* format: %-15s\t%-10s\t%-15s\t%s */ @@ -386,16 +321,9 @@ #endif sizeof(pds->list[0]); if (pds->entries > cnt) pds->entries = cnt; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status != S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status != S_OK) -#endif - { + + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK) pds->count = 0; - } /* other IOCTLs must fit into area GDTH_SCRATCH/4 */ for (j = 0; j < ha->raw[i].pdev_cnt; ++j) { @@ -410,14 +338,8 @@ #endif gdtcmd->u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN; gdtcmd->u.ioctl.channel = ha->raw[i].address | ha->raw[i].id_list[j]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status == S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status == S_OK) -#endif - { + + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { strncpy(hrec,pdi->vendor,8); strncpy(hrec+8,pdi->product,16); strncpy(hrec+24,pdi->revision,4); @@ -466,14 +388,8 @@ #endif gdtcmd->u.ioctl.channel = ha->raw[i].address | ha->raw[i].id_list[j]; pdef->sddc_type = 0x08; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status == S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status == S_OK) -#endif - { + + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { size = sprintf(buffer+len, " Grown Defects:\t%d\n", pdef->sddc_cnt); @@ -519,16 +435,8 @@ #endif gdtcmd->u.ioctl.param_size = sizeof(gdth_cdrinfo_str); gdtcmd->u.ioctl.subfunc = CACHE_DRV_INFO; gdtcmd->u.ioctl.channel = drv_no; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status != S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status != S_OK) -#endif - { + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK) break; - } pcdi->ld_dtype >>= 16; j++; if (pcdi->ld_dtype > 2) { @@ -629,14 +537,7 @@ #endif gdtcmd->u.ioctl.param_size = sizeof(gdth_arrayinf_str); gdtcmd->u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN; gdtcmd->u.ioctl.channel = i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status == S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status == S_OK) -#endif - { + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { if (pai->ai_state == 0) strcpy(hrec, "idle"); else if (pai->ai_state == 2) @@ -710,14 +611,7 @@ #endif gdtcmd->u.ioctl.channel = i; phg->entries = MAX_HDRIVES; phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - gdth_do_req(scp, gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status != S_OK) -#else - gdth_do_cmd(scp, gdtcmd, cmnd, 30); - if (scp->SCp.Status != S_OK) -#endif - { + if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) { ha->hdr[i].ldr_no = i; ha->hdr[i].rw_attribs = 0; ha->hdr[i].start_sec = 0; @@ -791,13 +685,6 @@ #endif } stop_output: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scsi_release_request(scp); - scsi_free_host_dev(sdev); -#else - scsi_release_command(scp); - scsi_free_host_dev(sdev); -#endif *start = buffer +(offset-begin); len -= (offset-begin); if (len > length) @@ -812,64 +699,6 @@ free_fail: return rc; } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static void gdth_do_req(Scsi_Request *scp, gdth_cmd_str *gdtcmd, - char *cmnd, int timeout) -{ - unsigned bufflen; - DECLARE_COMPLETION(wait); - - TRACE2(("gdth_do_req()\n")); - if (gdtcmd != NULL) { - bufflen = sizeof(gdth_cmd_str); - } else { - bufflen = 0; - } - scp->sr_request->rq_status = RQ_SCSI_BUSY; - scp->sr_request->waiting = &wait; - scsi_do_req(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); - wait_for_completion(&wait); -} - -#else -static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd, - char *cmnd, int timeout) -{ - unsigned bufflen; - DECLARE_COMPLETION(wait); - - TRACE2(("gdth_do_cmd()\n")); - if (gdtcmd != NULL) { - scp->SCp.this_residual = IOCTL_PRI; - bufflen = sizeof(gdth_cmd_str); - } else { - scp->SCp.this_residual = DEFAULT_PRI; - bufflen = 0; - } - - scp->request.rq_status = RQ_SCSI_BUSY; - scp->request.waiting = &wait; - scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); - wait_for_completion(&wait); -} -#endif - -void gdth_scsi_done(Scsi_Cmnd *scp) -{ - TRACE2(("gdth_scsi_done()\n")); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scp->request->rq_status = RQ_SCSI_DONE; - if (scp->request->waiting != NULL) - complete(scp->request->waiting); -#else - scp->request.rq_status = RQ_SCSI_DONE; - if (scp->request.waiting != NULL) - complete(scp->request.waiting); -#endif -} - static char *gdth_ioctl_alloc(int hanum, int size, int scratch, ulong64 *paddr) { @@ -976,11 +805,14 @@ static void gdth_stop_timeout(int hanum, spin_lock_irqsave(&ha->smp_lock, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; - t = scp->device->id; - if (t == (unchar)id && b == (unchar)busnum) { - TRACE2(("gdth_stop_timeout(): update_timeout()\n")); - scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + if (scp->done != gdth_scsi_done) { + b = virt_ctr ? + NUMDATA(scp->device->host)->busnum : scp->device->channel; + t = scp->device->id; + if (t == (unchar)id && b == (unchar)busnum) { + TRACE2(("gdth_stop_timeout(): update_timeout()\n")); + scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + } } } spin_unlock_irqrestore(&ha->smp_lock, flags); @@ -997,11 +829,14 @@ static void gdth_start_timeout(int hanum spin_lock_irqsave(&ha->smp_lock, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; - t = scp->device->id; - if (t == (unchar)id && b == (unchar)busnum) { - TRACE2(("gdth_start_timeout(): update_timeout()\n")); - gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual); + if (scp->done != gdth_scsi_done) { + b = virt_ctr ? + NUMDATA(scp->device->host)->busnum : scp->device->channel; + t = scp->device->id; + if (t == (unchar)id && b == (unchar)busnum) { + TRACE2(("gdth_start_timeout(): update_timeout()\n")); + gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual); + } } } spin_unlock_irqrestore(&ha->smp_lock, flags); diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h index 295e825..a679eeb 100644 --- a/drivers/scsi/gdth_proc.h +++ b/drivers/scsi/gdth_proc.h @@ -5,20 +5,16 @@ #define _GDTH_PROC_H * $Id: gdth_proc.h,v 1.16 2004/01/14 13:09:01 achim Exp $ */ +int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd, + int timeout, u32 *info); + static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, int hanum,int busnum); static int gdth_get_info(char *buffer,char **start,off_t offset,int length, struct Scsi_Host *host,int hanum,int busnum); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static void gdth_do_req(Scsi_Request *srp, gdth_cmd_str *cmd, - char *cmnd, int timeout); -static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp); -#else -static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, - char *cmnd, int timeout); -static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp); -#endif +static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, + int length, int hanum); static char *gdth_ioctl_alloc(int hanum, int size, int scratch, ulong64 *paddr); @@ -28,7 +24,5 @@ static void gdth_stop_timeout(int hanum, static void gdth_start_timeout(int hanum, int busnum, int id); static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout); -void gdth_scsi_done(Scsi_Cmnd *scp); - #endif diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c new file mode 100644 index 0000000..f778083 --- /dev/null +++ b/drivers/scsi/hptiop.c @@ -0,0 +1,1493 @@ +/* + * HighPoint RR3xxx controller driver for Linux + * Copyright (C) 2006 HighPoint Technologies, Inc. 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Please report bugs/comments/suggestions to linux@highpoint-tech.com + * + * For more information, visit http://www.highpoint-tech.com + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hptiop.h" + +MODULE_AUTHOR("HighPoint Technologies, Inc."); +MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx SATA Controller Driver"); + +static char driver_name[] = "hptiop"; +static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver"; +static const char driver_ver[] = "v1.0 (060426)"; + +static DEFINE_SPINLOCK(hptiop_hba_list_lock); +static LIST_HEAD(hptiop_hba_list); +static int hptiop_cdev_major = -1; + +static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag); +static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag); +static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg); + +static inline void hptiop_pci_posting_flush(struct hpt_iopmu __iomem *iop) +{ + readl(&iop->outbound_intstatus); +} + +static int iop_wait_ready(struct hpt_iopmu __iomem *iop, u32 millisec) +{ + u32 req = 0; + int i; + + for (i = 0; i < millisec; i++) { + req = readl(&iop->inbound_queue); + if (req != IOPMU_QUEUE_EMPTY) + break; + msleep(1); + } + + if (req != IOPMU_QUEUE_EMPTY) { + writel(req, &iop->outbound_queue); + hptiop_pci_posting_flush(iop); + return 0; + } + + return -1; +} + +static void hptiop_request_callback(struct hptiop_hba *hba, u32 tag) +{ + if ((tag & IOPMU_QUEUE_MASK_HOST_BITS) == IOPMU_QUEUE_ADDR_HOST_BIT) + return hptiop_host_request_callback(hba, + tag & ~IOPMU_QUEUE_ADDR_HOST_BIT); + else + return hptiop_iop_request_callback(hba, tag); +} + +static inline void hptiop_drain_outbound_queue(struct hptiop_hba *hba) +{ + u32 req; + + while ((req = readl(&hba->iop->outbound_queue)) != IOPMU_QUEUE_EMPTY) { + + if (req & IOPMU_QUEUE_MASK_HOST_BITS) + hptiop_request_callback(hba, req); + else { + struct hpt_iop_request_header __iomem * p; + + p = (struct hpt_iop_request_header __iomem *) + ((char __iomem *)hba->iop + req); + + if (readl(&p->flags) & IOP_REQUEST_FLAG_SYNC_REQUEST) { + if (readl(&p->context)) + hptiop_request_callback(hba, req); + else + writel(1, &p->context); + } + else + hptiop_request_callback(hba, req); + } + } +} + +static int __iop_intr(struct hptiop_hba *hba) +{ + struct hpt_iopmu __iomem *iop = hba->iop; + u32 status; + int ret = 0; + + status = readl(&iop->outbound_intstatus); + + if (status & IOPMU_OUTBOUND_INT_MSG0) { + u32 msg = readl(&iop->outbound_msgaddr0); + dprintk("received outbound msg %x\n", msg); + writel(IOPMU_OUTBOUND_INT_MSG0, &iop->outbound_intstatus); + hptiop_message_callback(hba, msg); + ret = 1; + } + + if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) { + hptiop_drain_outbound_queue(hba); + ret = 1; + } + + return ret; +} + +static int iop_send_sync_request(struct hptiop_hba *hba, + void __iomem *_req, u32 millisec) +{ + struct hpt_iop_request_header __iomem *req = _req; + u32 i; + + writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST, + &req->flags); + + writel(0, &req->context); + + writel((unsigned long)req - (unsigned long)hba->iop, + &hba->iop->inbound_queue); + + hptiop_pci_posting_flush(hba->iop); + + for (i = 0; i < millisec; i++) { + __iop_intr(hba); + if (readl(&req->context)) + return 0; + msleep(1); + } + + return -1; +} + +static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec) +{ + u32 i; + + hba->msg_done = 0; + + writel(msg, &hba->iop->inbound_msgaddr0); + + hptiop_pci_posting_flush(hba->iop); + + for (i = 0; i < millisec; i++) { + spin_lock_irq(hba->host->host_lock); + __iop_intr(hba); + spin_unlock_irq(hba->host->host_lock); + if (hba->msg_done) + break; + msleep(1); + } + + return hba->msg_done? 0 : -1; +} + +static int iop_get_config(struct hptiop_hba *hba, + struct hpt_iop_request_get_config *config) +{ + u32 req32; + struct hpt_iop_request_get_config __iomem *req; + + req32 = readl(&hba->iop->inbound_queue); + if (req32 == IOPMU_QUEUE_EMPTY) + return -1; + + req = (struct hpt_iop_request_get_config __iomem *) + ((unsigned long)hba->iop + req32); + + writel(0, &req->header.flags); + writel(IOP_REQUEST_TYPE_GET_CONFIG, &req->header.type); + writel(sizeof(struct hpt_iop_request_get_config), &req->header.size); + writel(IOP_RESULT_PENDING, &req->header.result); + + if (iop_send_sync_request(hba, req, 20000)) { + dprintk("Get config send cmd failed\n"); + return -1; + } + + memcpy_fromio(config, req, sizeof(*config)); + writel(req32, &hba->iop->outbound_queue); + return 0; +} + +static int iop_set_config(struct hptiop_hba *hba, + struct hpt_iop_request_set_config *config) +{ + u32 req32; + struct hpt_iop_request_set_config __iomem *req; + + req32 = readl(&hba->iop->inbound_queue); + if (req32 == IOPMU_QUEUE_EMPTY) + return -1; + + req = (struct hpt_iop_request_set_config __iomem *) + ((unsigned long)hba->iop + req32); + + memcpy_toio((u8 __iomem *)req + sizeof(struct hpt_iop_request_header), + (u8 *)config + sizeof(struct hpt_iop_request_header), + sizeof(struct hpt_iop_request_set_config) - + sizeof(struct hpt_iop_request_header)); + + writel(0, &req->header.flags); + writel(IOP_REQUEST_TYPE_SET_CONFIG, &req->header.type); + writel(sizeof(struct hpt_iop_request_set_config), &req->header.size); + writel(IOP_RESULT_PENDING, &req->header.result); + + if (iop_send_sync_request(hba, req, 20000)) { + dprintk("Set config send cmd failed\n"); + return -1; + } + + writel(req32, &hba->iop->outbound_queue); + return 0; +} + +static int hptiop_initialize_iop(struct hptiop_hba *hba) +{ + struct hpt_iopmu __iomem *iop = hba->iop; + + /* enable interrupts */ + writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0), + &iop->outbound_intmask); + + hba->initialized = 1; + + /* start background tasks */ + if (iop_send_sync_msg(hba, + IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) { + printk(KERN_ERR "scsi%d: fail to start background task\n", + hba->host->host_no); + return -1; + } + return 0; +} + +static int hptiop_map_pci_bar(struct hptiop_hba *hba) +{ + u32 mem_base_phy, length; + void __iomem *mem_base_virt; + struct pci_dev *pcidev = hba->pcidev; + + if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) { + printk(KERN_ERR "scsi%d: pci resource invalid\n", + hba->host->host_no); + return -1; + } + + mem_base_phy = pci_resource_start(pcidev, 0); + length = pci_resource_len(pcidev, 0); + mem_base_virt = ioremap(mem_base_phy, length); + + if (!mem_base_virt) { + printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n", + hba->host->host_no); + return -1; + } + + hba->iop = mem_base_virt; + dprintk("hptiop_map_pci_bar: iop=%p\n", hba->iop); + return 0; +} + +static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg) +{ + dprintk("iop message 0x%x\n", msg); + + if (!hba->initialized) + return; + + if (msg == IOPMU_INBOUND_MSG0_RESET) { + atomic_set(&hba->resetting, 0); + wake_up(&hba->reset_wq); + } + else if (msg <= IOPMU_INBOUND_MSG0_MAX) + hba->msg_done = 1; +} + +static inline struct hptiop_request *get_req(struct hptiop_hba *hba) +{ + struct hptiop_request *ret; + + dprintk("get_req : req=%p\n", hba->req_list); + + ret = hba->req_list; + if (ret) + hba->req_list = ret->next; + + return ret; +} + +static inline void free_req(struct hptiop_hba *hba, struct hptiop_request *req) +{ + dprintk("free_req(%d, %p)\n", req->index, req); + req->next = hba->req_list; + hba->req_list = req; +} + +static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag) +{ + struct hpt_iop_request_scsi_command *req; + struct scsi_cmnd *scp; + + req = (struct hpt_iop_request_scsi_command *)hba->reqs[tag].req_virt; + dprintk("hptiop_host_request_callback: req=%p, type=%d, " + "result=%d, context=0x%x tag=%d\n", + req, req->header.type, req->header.result, + req->header.context, tag); + + BUG_ON(!req->header.result); + BUG_ON(req->header.type != cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND)); + + scp = hba->reqs[tag].scp; + + if (HPT_SCP(scp)->mapped) { + if (scp->use_sg) + pci_unmap_sg(hba->pcidev, + (struct scatterlist *)scp->request_buffer, + scp->use_sg, + scp->sc_data_direction + ); + else + pci_unmap_single(hba->pcidev, + HPT_SCP(scp)->dma_handle, + scp->request_bufflen, + scp->sc_data_direction + ); + } + + switch (le32_to_cpu(req->header.result)) { + case IOP_RESULT_SUCCESS: + scp->result = (DID_OK<<16); + break; + case IOP_RESULT_BAD_TARGET: + scp->result = (DID_BAD_TARGET<<16); + break; + case IOP_RESULT_BUSY: + scp->result = (DID_BUS_BUSY<<16); + break; + case IOP_RESULT_RESET: + scp->result = (DID_RESET<<16); + break; + case IOP_RESULT_FAIL: + scp->result = (DID_ERROR<<16); + break; + case IOP_RESULT_INVALID_REQUEST: + scp->result = (DID_ABORT<<16); + break; + case IOP_RESULT_MODE_SENSE_CHECK_CONDITION: + scp->result = SAM_STAT_CHECK_CONDITION; + memset(&scp->sense_buffer, + 0, sizeof(scp->sense_buffer)); + memcpy(&scp->sense_buffer, + &req->sg_list, le32_to_cpu(req->dataxfer_length)); + break; + + default: + scp->result = ((DRIVER_INVALID|SUGGEST_ABORT)<<24) | + (DID_ABORT<<16); + break; + } + + dprintk("scsi_done(%p)\n", scp); + scp->scsi_done(scp); + free_req(hba, &hba->reqs[tag]); +} + +void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag) +{ + struct hpt_iop_request_header __iomem *req; + struct hpt_iop_request_ioctl_command __iomem *p; + struct hpt_ioctl_k *arg; + + req = (struct hpt_iop_request_header __iomem *) + ((unsigned long)hba->iop + tag); + dprintk("hptiop_iop_request_callback: req=%p, type=%d, " + "result=%d, context=0x%x tag=%d\n", + req, readl(&req->type), readl(&req->result), + readl(&req->context), tag); + + BUG_ON(!readl(&req->result)); + BUG_ON(readl(&req->type) != IOP_REQUEST_TYPE_IOCTL_COMMAND); + + p = (struct hpt_iop_request_ioctl_command __iomem *)req; + arg = (struct hpt_ioctl_k *)(unsigned long) + (readl(&req->context) | + ((u64)readl(&req->context_hi32)<<32)); + + if (readl(&req->result) == IOP_RESULT_SUCCESS) { + arg->result = HPT_IOCTL_RESULT_OK; + + if (arg->outbuf_size) + memcpy_fromio(arg->outbuf, + &p->buf[(readl(&p->inbuf_size) + 3)& ~3], + arg->outbuf_size); + + if (arg->bytes_returned) + *arg->bytes_returned = arg->outbuf_size; + } + else + arg->result = HPT_IOCTL_RESULT_FAILED; + + arg->done(arg); + writel(tag, &hba->iop->outbound_queue); +} + +static irqreturn_t hptiop_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct hptiop_hba *hba = dev_id; + int handled; + unsigned long flags; + + spin_lock_irqsave(hba->host->host_lock, flags); + handled = __iop_intr(hba); + spin_unlock_irqrestore(hba->host->host_lock, flags); + + return handled; +} + +static int hptiop_buildsgl(struct scsi_cmnd *scp, struct hpt_iopsg *psg) +{ + struct Scsi_Host *host = scp->device->host; + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + struct scatterlist *sglist = (struct scatterlist *)scp->request_buffer; + + /* + * though we'll not get non-use_sg fields anymore, + * keep use_sg checking anyway + */ + if (scp->use_sg) { + int idx; + + HPT_SCP(scp)->sgcnt = pci_map_sg(hba->pcidev, + sglist, scp->use_sg, + scp->sc_data_direction); + HPT_SCP(scp)->mapped = 1; + BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors); + + for (idx = 0; idx < HPT_SCP(scp)->sgcnt; idx++) { + psg[idx].pci_address = + cpu_to_le64(sg_dma_address(&sglist[idx])); + psg[idx].size = cpu_to_le32(sg_dma_len(&sglist[idx])); + psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ? + cpu_to_le32(1) : 0; + } + + return HPT_SCP(scp)->sgcnt; + } else { + HPT_SCP(scp)->dma_handle = pci_map_single( + hba->pcidev, + scp->request_buffer, + scp->request_bufflen, + scp->sc_data_direction + ); + HPT_SCP(scp)->mapped = 1; + psg->pci_address = cpu_to_le64(HPT_SCP(scp)->dma_handle); + psg->size = cpu_to_le32(scp->request_bufflen); + psg->eot = cpu_to_le32(1); + return 1; + } +} + +static int hptiop_queuecommand(struct scsi_cmnd *scp, + void (*done)(struct scsi_cmnd *)) +{ + struct Scsi_Host *host = scp->device->host; + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + struct hpt_iop_request_scsi_command *req; + int sg_count = 0; + struct hptiop_request *_req; + + BUG_ON(!done); + scp->scsi_done = done; + + _req = get_req(hba); + if (_req == NULL) { + dprintk("hptiop_queuecmd : no free req\n"); + return SCSI_MLQUEUE_HOST_BUSY; + } + + _req->scp = scp; + + dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%x-%x-%x) " + "req_index=%d, req=%p\n", + scp, + host->host_no, scp->device->channel, + scp->device->id, scp->device->lun, + *((u32 *)&scp->cmnd), + *((u32 *)&scp->cmnd + 1), + *((u32 *)&scp->cmnd + 2), + _req->index, _req->req_virt); + + scp->result = 0; + + if (scp->device->channel || scp->device->lun || + scp->device->id > hba->max_devices) { + scp->result = DID_BAD_TARGET << 16; + free_req(hba, _req); + goto cmd_done; + } + + req = (struct hpt_iop_request_scsi_command *)_req->req_virt; + + /* build S/G table */ + if (scp->request_bufflen) + sg_count = hptiop_buildsgl(scp, req->sg_list); + else + HPT_SCP(scp)->mapped = 0; + + req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT); + req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND); + req->header.result = cpu_to_le32(IOP_RESULT_PENDING); + req->header.context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT | + (u32)_req->index); + req->header.context_hi32 = 0; + req->dataxfer_length = cpu_to_le32(scp->request_bufflen); + req->channel = scp->device->channel; + req->target = scp->device->id; + req->lun = scp->device->lun; + req->header.size = cpu_to_le32( + sizeof(struct hpt_iop_request_scsi_command) + - sizeof(struct hpt_iopsg) + + sg_count * sizeof(struct hpt_iopsg)); + + memcpy(req->cdb, scp->cmnd, sizeof(req->cdb)); + + writel(IOPMU_QUEUE_ADDR_HOST_BIT | _req->req_shifted_phy, + &hba->iop->inbound_queue); + + return 0; + +cmd_done: + dprintk("scsi_done(scp=%p)\n", scp); + scp->scsi_done(scp); + return 0; +} + +static const char *hptiop_info(struct Scsi_Host *host) +{ + return driver_name_long; +} + +static int hptiop_reset_hba(struct hptiop_hba *hba) +{ + if (atomic_xchg(&hba->resetting, 1) == 0) { + atomic_inc(&hba->reset_count); + writel(IOPMU_INBOUND_MSG0_RESET, + &hba->iop->outbound_msgaddr0); + hptiop_pci_posting_flush(hba->iop); + } + + wait_event_timeout(hba->reset_wq, + atomic_read(&hba->resetting) == 0, 60 * HZ); + + if (atomic_read(&hba->resetting)) { + /* IOP is in unkown state, abort reset */ + printk(KERN_ERR "scsi%d: reset failed\n", hba->host->host_no); + return -1; + } + + if (iop_send_sync_msg(hba, + IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) { + dprintk("scsi%d: fail to start background task\n", + hba->host->host_no); + } + + return 0; +} + +static int hptiop_reset(struct scsi_cmnd *scp) +{ + struct Scsi_Host * host = scp->device->host; + struct hptiop_hba * hba = (struct hptiop_hba *)host->hostdata; + + printk(KERN_WARNING "hptiop_reset(%d/%d/%d) scp=%p\n", + scp->device->host->host_no, scp->device->channel, + scp->device->id, scp); + + return hptiop_reset_hba(hba)? FAILED : SUCCESS; +} + +static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev, + int queue_depth) +{ + if(queue_depth > 256) + queue_depth = 256; + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); + return queue_depth; +} + +struct hptiop_getinfo { + char __user *buffer; + loff_t buflength; + loff_t bufoffset; + loff_t buffillen; + loff_t filpos; +}; + +static void hptiop_copy_mem_info(struct hptiop_getinfo *pinfo, + char *data, int datalen) +{ + if (pinfo->filpos < pinfo->bufoffset) { + if (pinfo->filpos + datalen <= pinfo->bufoffset) { + pinfo->filpos += datalen; + return; + } else { + data += (pinfo->bufoffset - pinfo->filpos); + datalen -= (pinfo->bufoffset - pinfo->filpos); + pinfo->filpos = pinfo->bufoffset; + } + } + + pinfo->filpos += datalen; + if (pinfo->buffillen == pinfo->buflength) + return; + + if (pinfo->buflength - pinfo->buffillen < datalen) + datalen = pinfo->buflength - pinfo->buffillen; + + if (copy_to_user(pinfo->buffer + pinfo->buffillen, data, datalen)) + return; + + pinfo->buffillen += datalen; +} + +static int hptiop_copy_info(struct hptiop_getinfo *pinfo, char *fmt, ...) +{ + va_list args; + char buf[128]; + int len; + + va_start(args, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + hptiop_copy_mem_info(pinfo, buf, len); + return len; +} + +static void hptiop_ioctl_done(struct hpt_ioctl_k *arg) +{ + arg->done = NULL; + wake_up(&arg->hba->ioctl_wq); +} + +static void hptiop_do_ioctl(struct hpt_ioctl_k *arg) +{ + struct hptiop_hba *hba = arg->hba; + u32 val; + struct hpt_iop_request_ioctl_command __iomem *req; + int ioctl_retry = 0; + + dprintk("scsi%d: hptiop_do_ioctl\n", hba->host->host_no); + + /* + * check (in + out) buff size from application. + * outbuf must be dword aligned. + */ + if (((arg->inbuf_size + 3) & ~3) + arg->outbuf_size > + hba->max_request_size + - sizeof(struct hpt_iop_request_header) + - 4 * sizeof(u32)) { + dprintk("scsi%d: ioctl buf size (%d/%d) is too large\n", + hba->host->host_no, + arg->inbuf_size, arg->outbuf_size); + arg->result = HPT_IOCTL_RESULT_FAILED; + return; + } + +retry: + spin_lock_irq(hba->host->host_lock); + + val = readl(&hba->iop->inbound_queue); + if (val == IOPMU_QUEUE_EMPTY) { + spin_unlock_irq(hba->host->host_lock); + dprintk("scsi%d: no free req for ioctl\n", hba->host->host_no); + arg->result = -1; + return; + } + + req = (struct hpt_iop_request_ioctl_command __iomem *) + ((unsigned long)hba->iop + val); + + writel(HPT_CTL_CODE_LINUX_TO_IOP(arg->ioctl_code), + &req->ioctl_code); + writel(arg->inbuf_size, &req->inbuf_size); + writel(arg->outbuf_size, &req->outbuf_size); + + /* + * use the buffer on the IOP local memory first, then copy it + * back to host. + * the caller's request buffer shoudl be little-endian. + */ + if (arg->inbuf_size) + memcpy_toio(req->buf, arg->inbuf, arg->inbuf_size); + + /* correct the controller ID for IOP */ + if ((arg->ioctl_code == HPT_IOCTL_GET_CHANNEL_INFO || + arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO_V2 || + arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO) + && arg->inbuf_size >= sizeof(u32)) + writel(0, req->buf); + + writel(IOP_REQUEST_TYPE_IOCTL_COMMAND, &req->header.type); + writel(0, &req->header.flags); + writel(offsetof(struct hpt_iop_request_ioctl_command, buf) + + arg->inbuf_size, &req->header.size); + writel((u32)(unsigned long)arg, &req->header.context); + writel(BITS_PER_LONG > 32 ? (u32)((unsigned long)arg>>32) : 0, + &req->header.context_hi32); + writel(IOP_RESULT_PENDING, &req->header.result); + + arg->result = HPT_IOCTL_RESULT_FAILED; + arg->done = hptiop_ioctl_done; + + writel(val, &hba->iop->inbound_queue); + hptiop_pci_posting_flush(hba->iop); + + spin_unlock_irq(hba->host->host_lock); + + wait_event_timeout(hba->ioctl_wq, arg->done == NULL, 60 * HZ); + + if (arg->done != NULL) { + hptiop_reset_hba(hba); + if (ioctl_retry++ < 3) + goto retry; + } + + dprintk("hpt_iop_ioctl %x result %d\n", + arg->ioctl_code, arg->result); +} + +static int __hpt_do_ioctl(struct hptiop_hba *hba, u32 code, void *inbuf, + u32 insize, void *outbuf, u32 outsize) +{ + struct hpt_ioctl_k arg; + arg.hba = hba; + arg.ioctl_code = code; + arg.inbuf = inbuf; + arg.outbuf = outbuf; + arg.inbuf_size = insize; + arg.outbuf_size = outsize; + arg.bytes_returned = NULL; + hptiop_do_ioctl(&arg); + return arg.result; +} + +static inline int hpt_id_valid(__le32 id) +{ + return id != 0 && id != cpu_to_le32(0xffffffff); +} + +static int hptiop_get_controller_info(struct hptiop_hba *hba, + struct hpt_controller_info *pinfo) +{ + int id = 0; + + return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CONTROLLER_INFO, + &id, sizeof(int), pinfo, sizeof(*pinfo)); +} + + +static int hptiop_get_channel_info(struct hptiop_hba *hba, int bus, + struct hpt_channel_info *pinfo) +{ + u32 ids[2]; + + ids[0] = 0; + ids[1] = bus; + return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CHANNEL_INFO, + ids, sizeof(ids), pinfo, sizeof(*pinfo)); + +} + +static int hptiop_get_logical_devices(struct hptiop_hba *hba, + __le32 *pids, int maxcount) +{ + int i; + u32 count = maxcount - 1; + + if (__hpt_do_ioctl(hba, HPT_IOCTL_GET_LOGICAL_DEVICES, + &count, sizeof(u32), + pids, sizeof(u32) * maxcount)) + return -1; + + maxcount = le32_to_cpu(pids[0]); + for (i = 0; i < maxcount; i++) + pids[i] = pids[i+1]; + + return maxcount; +} + +static int hptiop_get_device_info_v3(struct hptiop_hba *hba, __le32 id, + struct hpt_logical_device_info_v3 *pinfo) +{ + return __hpt_do_ioctl(hba, HPT_IOCTL_GET_DEVICE_INFO_V3, + &id, sizeof(u32), + pinfo, sizeof(*pinfo)); +} + +static const char *get_array_status(struct hpt_logical_device_info_v3 *devinfo) +{ + static char s[64]; + u32 flags = le32_to_cpu(devinfo->u.array.flags); + u32 trans_prog = le32_to_cpu(devinfo->u.array.transforming_progress); + u32 reb_prog = le32_to_cpu(devinfo->u.array.rebuilding_progress); + + if (flags & ARRAY_FLAG_DISABLED) + return "Disabled"; + else if (flags & ARRAY_FLAG_TRANSFORMING) + sprintf(s, "Expanding/Migrating %d.%d%%%s%s", + trans_prog / 100, + trans_prog % 100, + (flags & (ARRAY_FLAG_NEEDBUILDING|ARRAY_FLAG_BROKEN))? + ", Critical" : "", + ((flags & ARRAY_FLAG_NEEDINITIALIZING) && + !(flags & ARRAY_FLAG_REBUILDING) && + !(flags & ARRAY_FLAG_INITIALIZING))? + ", Unintialized" : ""); + else if ((flags & ARRAY_FLAG_BROKEN) && + devinfo->u.array.array_type != AT_RAID6) + return "Critical"; + else if (flags & ARRAY_FLAG_REBUILDING) + sprintf(s, + (flags & ARRAY_FLAG_NEEDINITIALIZING)? + "%sBackground initializing %d.%d%%" : + "%sRebuilding %d.%d%%", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + reb_prog / 100, + reb_prog % 100); + else if (flags & ARRAY_FLAG_VERIFYING) + sprintf(s, "%sVerifying %d.%d%%", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + reb_prog / 100, + reb_prog % 100); + else if (flags & ARRAY_FLAG_INITIALIZING) + sprintf(s, "%sForground initializing %d.%d%%", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + reb_prog / 100, + reb_prog % 100); + else if (flags & ARRAY_FLAG_NEEDTRANSFORM) + sprintf(s,"%s%s%s", "Need Expanding/Migrating", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + ((flags & ARRAY_FLAG_NEEDINITIALIZING) && + !(flags & ARRAY_FLAG_REBUILDING) && + !(flags & ARRAY_FLAG_INITIALIZING))? + ", Unintialized" : ""); + else if (flags & ARRAY_FLAG_NEEDINITIALIZING && + !(flags & ARRAY_FLAG_REBUILDING) && + !(flags & ARRAY_FLAG_INITIALIZING)) + sprintf(s,"%sUninitialized", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : ""); + else if ((flags & ARRAY_FLAG_NEEDBUILDING) || + (flags & ARRAY_FLAG_BROKEN)) + return "Critical"; + else + return "Normal"; + return s; +} + +static void hptiop_dump_devinfo(struct hptiop_hba *hba, + struct hptiop_getinfo *pinfo, __le32 id, int indent) +{ + struct hpt_logical_device_info_v3 devinfo; + int i; + u64 capacity; + + for (i = 0; i < indent; i++) + hptiop_copy_info(pinfo, "\t"); + + if (hptiop_get_device_info_v3(hba, id, &devinfo)) { + hptiop_copy_info(pinfo, "unknown\n"); + return; + } + + switch (devinfo.type) { + + case LDT_DEVICE: { + struct hd_driveid *driveid; + u32 flags = le32_to_cpu(devinfo.u.device.flags); + + driveid = (struct hd_driveid *)devinfo.u.device.ident; + /* model[] is 40 chars long, but we just want 20 chars here */ + driveid->model[20] = 0; + + if (indent) + if (flags & DEVICE_FLAG_DISABLED) + hptiop_copy_info(pinfo,"Missing\n"); + else + hptiop_copy_info(pinfo, "CH%d %s\n", + devinfo.u.device.path_id + 1, + driveid->model); + else { + capacity = le64_to_cpu(devinfo.capacity) * 512; + do_div(capacity, 1000000); + hptiop_copy_info(pinfo, + "CH%d %s, %lluMB, %s %s%s%s%s\n", + devinfo.u.device.path_id + 1, + driveid->model, + capacity, + (flags & DEVICE_FLAG_DISABLED)? + "Disabled" : "Normal", + devinfo.u.device.read_ahead_enabled? + "[RA]" : "", + devinfo.u.device.write_cache_enabled? + "[WC]" : "", + devinfo.u.device.TCQ_enabled? + "[TCQ]" : "", + devinfo.u.device.NCQ_enabled? + "[NCQ]" : "" + ); + } + break; + } + + case LDT_ARRAY: + if (devinfo.target_id != INVALID_TARGET_ID) + hptiop_copy_info(pinfo, "[DISK %d_%d] ", + devinfo.vbus_id, devinfo.target_id); + + capacity = le64_to_cpu(devinfo.capacity) * 512; + do_div(capacity, 1000000); + hptiop_copy_info(pinfo, "%s (%s), %lluMB, %s\n", + devinfo.u.array.name, + devinfo.u.array.array_type==AT_RAID0? "RAID0" : + devinfo.u.array.array_type==AT_RAID1? "RAID1" : + devinfo.u.array.array_type==AT_RAID5? "RAID5" : + devinfo.u.array.array_type==AT_RAID6? "RAID6" : + devinfo.u.array.array_type==AT_JBOD? "JBOD" : + "unknown", + capacity, + get_array_status(&devinfo)); + for (i = 0; i < devinfo.u.array.ndisk; i++) { + if (hpt_id_valid(devinfo.u.array.members[i])) { + if (cpu_to_le16(1<private_data; + struct hptiop_getinfo info; + int i, j, ndev; + struct hpt_controller_info con_info; + struct hpt_channel_info chan_info; + __le32 ids[32]; + + info.buffer = buf; + info.buflength = count; + info.bufoffset = ppos ? *ppos : 0; + info.filpos = 0; + info.buffillen = 0; + + if (hptiop_get_controller_info(hba, &con_info)) + return -EIO; + + for (i = 0; i < con_info.num_buses; i++) { + if (hptiop_get_channel_info(hba, i, &chan_info) == 0) { + if (hpt_id_valid(chan_info.devices[0])) + hptiop_dump_devinfo(hba, &info, + chan_info.devices[0], 0); + if (hpt_id_valid(chan_info.devices[1])) + hptiop_dump_devinfo(hba, &info, + chan_info.devices[1], 0); + } + } + + ndev = hptiop_get_logical_devices(hba, ids, + sizeof(ids) / sizeof(ids[0])); + + /* + * if hptiop_get_logical_devices fails, ndev==-1 and it just + * output nothing here + */ + for (j = 0; j < ndev; j++) + hptiop_dump_devinfo(hba, &info, ids[j], 0); + + if (ppos) + *ppos += info.buffillen; + + return info.buffillen; +} + +static int hptiop_cdev_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct hptiop_hba *hba = file->private_data; + struct hpt_ioctl_u ioctl_u; + struct hpt_ioctl_k ioctl_k; + u32 bytes_returned; + int err = -EINVAL; + + if (copy_from_user(&ioctl_u, + (void __user *)arg, sizeof(struct hpt_ioctl_u))) + return -EINVAL; + + if (ioctl_u.magic != HPT_IOCTL_MAGIC) + return -EINVAL; + + ioctl_k.ioctl_code = ioctl_u.ioctl_code; + ioctl_k.inbuf = NULL; + ioctl_k.inbuf_size = ioctl_u.inbuf_size; + ioctl_k.outbuf = NULL; + ioctl_k.outbuf_size = ioctl_u.outbuf_size; + ioctl_k.hba = hba; + ioctl_k.bytes_returned = &bytes_returned; + + /* verify user buffer */ + if ((ioctl_k.inbuf_size && !access_ok(VERIFY_READ, + ioctl_u.inbuf, ioctl_k.inbuf_size)) || + (ioctl_k.outbuf_size && !access_ok(VERIFY_WRITE, + ioctl_u.outbuf, ioctl_k.outbuf_size)) || + (ioctl_u.bytes_returned && !access_ok(VERIFY_WRITE, + ioctl_u.bytes_returned, sizeof(u32))) || + ioctl_k.inbuf_size + ioctl_k.outbuf_size > 0x10000) { + + dprintk("scsi%d: got bad user address\n", hba->host->host_no); + return -EINVAL; + } + + /* map buffer to kernel. */ + if (ioctl_k.inbuf_size) { + ioctl_k.inbuf = kmalloc(ioctl_k.inbuf_size, GFP_KERNEL); + if (!ioctl_k.inbuf) { + dprintk("scsi%d: fail to alloc inbuf\n", + hba->host->host_no); + err = -ENOMEM; + goto err_exit; + } + + if (copy_from_user(ioctl_k.inbuf, + ioctl_u.inbuf, ioctl_k.inbuf_size)) { + goto err_exit; + } + } + + if (ioctl_k.outbuf_size) { + ioctl_k.outbuf = kmalloc(ioctl_k.outbuf_size, GFP_KERNEL); + if (!ioctl_k.outbuf) { + dprintk("scsi%d: fail to alloc outbuf\n", + hba->host->host_no); + err = -ENOMEM; + goto err_exit; + } + } + + hptiop_do_ioctl(&ioctl_k); + + if (ioctl_k.result == HPT_IOCTL_RESULT_OK) { + if (ioctl_k.outbuf_size && + copy_to_user(ioctl_u.outbuf, + ioctl_k.outbuf, ioctl_k.outbuf_size)) + goto err_exit; + + if (ioctl_u.bytes_returned && + copy_to_user(ioctl_u.bytes_returned, + &bytes_returned, sizeof(u32))) + goto err_exit; + + err = 0; + } + +err_exit: + kfree(ioctl_k.inbuf); + kfree(ioctl_k.outbuf); + + return err; +} + +static int hptiop_cdev_open(struct inode *inode, struct file *file) +{ + struct hptiop_hba *hba; + unsigned i = 0, minor = iminor(inode); + int ret = -ENODEV; + + spin_lock(&hptiop_hba_list_lock); + list_for_each_entry(hba, &hptiop_hba_list, link) { + if (i == minor) { + file->private_data = hba; + ret = 0; + goto out; + } + i++; + } + +out: + spin_unlock(&hptiop_hba_list_lock); + return ret; +} + +static struct file_operations hptiop_cdev_fops = { + .owner = THIS_MODULE, + .read = hptiop_cdev_read, + .ioctl = hptiop_cdev_ioctl, + .open = hptiop_cdev_open, +}; + +static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(class_dev); + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + + return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n", + hba->firmware_version >> 24, + (hba->firmware_version >> 16) & 0xff, + (hba->firmware_version >> 8) & 0xff, + hba->firmware_version & 0xff); +} + +static struct class_device_attribute hptiop_attr_version = { + .attr = { + .name = "driver-version", + .mode = S_IRUGO, + }, + .show = hptiop_show_version, +}; + +static struct class_device_attribute hptiop_attr_fw_version = { + .attr = { + .name = "firmware-version", + .mode = S_IRUGO, + }, + .show = hptiop_show_fw_version, +}; + +static struct class_device_attribute *hptiop_attrs[] = { + &hptiop_attr_version, + &hptiop_attr_fw_version, + NULL +}; + +static struct scsi_host_template driver_template = { + .module = THIS_MODULE, + .name = driver_name, + .queuecommand = hptiop_queuecommand, + .eh_device_reset_handler = hptiop_reset, + .eh_bus_reset_handler = hptiop_reset, + .info = hptiop_info, + .unchecked_isa_dma = 0, + .emulated = 0, + .use_clustering = ENABLE_CLUSTERING, + .proc_name = driver_name, + .shost_attrs = hptiop_attrs, + .this_id = -1, + .change_queue_depth = hptiop_adjust_disk_queue_depth, +}; + +static int __devinit hptiop_probe(struct pci_dev *pcidev, + const struct pci_device_id *id) +{ + struct Scsi_Host *host = NULL; + struct hptiop_hba *hba; + struct hpt_iop_request_get_config iop_config; + struct hpt_iop_request_set_config set_config; + dma_addr_t start_phy; + void *start_virt; + u32 offset, i, req_size; + + dprintk("hptiop_probe(%p)\n", pcidev); + + if (pci_enable_device(pcidev)) { + printk(KERN_ERR "hptiop: fail to enable pci device\n"); + return -ENODEV; + } + + printk(KERN_INFO "adapter at PCI %d:%d:%d, IRQ %d\n", + pcidev->bus->number, pcidev->devfn >> 3, pcidev->devfn & 7, + pcidev->irq); + + pci_set_master(pcidev); + + /* Enable 64bit DMA if possible */ + if (pci_set_dma_mask(pcidev, DMA_64BIT_MASK)) { + if (pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) { + printk(KERN_ERR "hptiop: fail to set dma_mask\n"); + goto disable_pci_device; + } + } + + if (pci_request_regions(pcidev, driver_name)) { + printk(KERN_ERR "hptiop: pci_request_regions failed\n"); + goto disable_pci_device; + } + + host = scsi_host_alloc(&driver_template, sizeof(struct hptiop_hba)); + if (!host) { + printk(KERN_ERR "hptiop: fail to alloc scsi host\n"); + goto free_pci_regions; + } + + hba = (struct hptiop_hba *)host->hostdata; + + hba->pcidev = pcidev; + hba->host = host; + hba->initialized = 0; + + atomic_set(&hba->resetting, 0); + atomic_set(&hba->reset_count, 0); + + init_waitqueue_head(&hba->reset_wq); + init_waitqueue_head(&hba->ioctl_wq); + + host->max_lun = 1; + host->max_channel = 0; + host->io_port = 0; + host->n_io_port = 0; + host->irq = pcidev->irq; + + if (hptiop_map_pci_bar(hba)) + goto free_scsi_host; + + if (iop_wait_ready(hba->iop, 20000)) { + printk(KERN_ERR "scsi%d: firmware not ready\n", + hba->host->host_no); + goto unmap_pci_bar; + } + + if (iop_get_config(hba, &iop_config)) { + printk(KERN_ERR "scsi%d: get config failed\n", + hba->host->host_no); + goto unmap_pci_bar; + } + + hba->max_requests = min(le32_to_cpu(iop_config.max_requests), + HPTIOP_MAX_REQUESTS); + hba->max_devices = le32_to_cpu(iop_config.max_devices); + hba->max_request_size = le32_to_cpu(iop_config.request_size); + hba->max_sg_descriptors = le32_to_cpu(iop_config.max_sg_count); + hba->firmware_version = le32_to_cpu(iop_config.firmware_version); + hba->sdram_size = le32_to_cpu(iop_config.sdram_size); + + host->max_sectors = le32_to_cpu(iop_config.data_transfer_length) >> 9; + host->max_id = le32_to_cpu(iop_config.max_devices); + host->sg_tablesize = le32_to_cpu(iop_config.max_sg_count); + host->can_queue = le32_to_cpu(iop_config.max_requests); + host->cmd_per_lun = le32_to_cpu(iop_config.max_requests); + host->max_cmd_len = 16; + + set_config.vbus_id = cpu_to_le32(host->host_no); + set_config.iop_id = cpu_to_le32(host->host_no); + + if (iop_set_config(hba, &set_config)) { + printk(KERN_ERR "scsi%d: set config failed\n", + hba->host->host_no); + goto unmap_pci_bar; + } + + if (scsi_add_host(host, &pcidev->dev)) { + printk(KERN_ERR "scsi%d: scsi_add_host failed\n", + hba->host->host_no); + goto unmap_pci_bar; + } + + pci_set_drvdata(pcidev, host); + + if (request_irq(pcidev->irq, hptiop_intr, SA_SHIRQ, + driver_name, hba)) { + printk(KERN_ERR "scsi%d: request irq %d failed\n", + hba->host->host_no, pcidev->irq); + goto remove_scsi_host; + } + + /* Allocate request mem */ + req_size = sizeof(struct hpt_iop_request_scsi_command) + + sizeof(struct hpt_iopsg) * (hba->max_sg_descriptors - 1); + if ((req_size& 0x1f) != 0) + req_size = (req_size + 0x1f) & ~0x1f; + + dprintk("req_size=%d, max_requests=%d\n", req_size, hba->max_requests); + + hba->req_size = req_size; + start_virt = dma_alloc_coherent(&pcidev->dev, + hba->req_size*hba->max_requests + 0x20, + &start_phy, GFP_KERNEL); + + if (!start_virt) { + printk(KERN_ERR "scsi%d: fail to alloc request mem\n", + hba->host->host_no); + goto free_request_irq; + } + + hba->dma_coherent = start_virt; + hba->dma_coherent_handle = start_phy; + + if ((start_phy & 0x1f) != 0) + { + offset = ((start_phy + 0x1f) & ~0x1f) - start_phy; + start_phy += offset; + start_virt += offset; + } + + hba->req_list = start_virt; + for (i = 0; i < hba->max_requests; i++) { + hba->reqs[i].next = NULL; + hba->reqs[i].req_virt = start_virt; + hba->reqs[i].req_shifted_phy = start_phy >> 5; + hba->reqs[i].index = i; + free_req(hba, &hba->reqs[i]); + start_virt = (char *)start_virt + hba->req_size; + start_phy = start_phy + hba->req_size; + } + + /* Enable Interrupt and start background task */ + if (hptiop_initialize_iop(hba)) + goto free_request_mem; + + spin_lock(&hptiop_hba_list_lock); + list_add_tail(&hba->link, &hptiop_hba_list); + spin_unlock(&hptiop_hba_list_lock); + + scsi_scan_host(host); + + dprintk("scsi%d: hptiop_probe successfully\n", hba->host->host_no); + return 0; + +free_request_mem: + dma_free_coherent(&hba->pcidev->dev, + hba->req_size*hba->max_requests + 0x20, + hba->dma_coherent, hba->dma_coherent_handle); + +free_request_irq: + free_irq(hba->pcidev->irq, hba); + +remove_scsi_host: + scsi_remove_host(host); + +unmap_pci_bar: + iounmap(hba->iop); + +free_pci_regions: + pci_release_regions(pcidev) ; + +free_scsi_host: + scsi_host_put(host); + +disable_pci_device: + pci_disable_device(pcidev); + + dprintk("scsi%d: hptiop_probe fail\n", host->host_no); + return -ENODEV; +} + +static void hptiop_shutdown(struct pci_dev *pcidev) +{ + struct Scsi_Host *host = pci_get_drvdata(pcidev); + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + struct hpt_iopmu __iomem *iop = hba->iop; + u32 int_mask; + + dprintk("hptiop_shutdown(%p)\n", hba); + + /* stop the iop */ + if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000)) + printk(KERN_ERR "scsi%d: shutdown the iop timeout\n", + hba->host->host_no); + + /* disable all outbound interrupts */ + int_mask = readl(&iop->outbound_intmask); + writel(int_mask | + IOPMU_OUTBOUND_INT_MSG0 | IOPMU_OUTBOUND_INT_POSTQUEUE, + &iop->outbound_intmask); + hptiop_pci_posting_flush(iop); +} + +static void hptiop_remove(struct pci_dev *pcidev) +{ + struct Scsi_Host *host = pci_get_drvdata(pcidev); + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + + dprintk("scsi%d: hptiop_remove\n", hba->host->host_no); + + scsi_remove_host(host); + + spin_lock(&hptiop_hba_list_lock); + list_del_init(&hba->link); + spin_unlock(&hptiop_hba_list_lock); + + hptiop_shutdown(pcidev); + + free_irq(hba->pcidev->irq, hba); + + dma_free_coherent(&hba->pcidev->dev, + hba->req_size * hba->max_requests + 0x20, + hba->dma_coherent, + hba->dma_coherent_handle); + + iounmap(hba->iop); + + pci_release_regions(hba->pcidev); + pci_set_drvdata(hba->pcidev, NULL); + pci_disable_device(hba->pcidev); + + scsi_host_put(host); +} + +static struct pci_device_id hptiop_id_table[] = { + { PCI_DEVICE(0x1103, 0x3220) }, + { PCI_DEVICE(0x1103, 0x3320) }, + {}, +}; + +MODULE_DEVICE_TABLE(pci, hptiop_id_table); + +static struct pci_driver hptiop_pci_driver = { + .name = driver_name, + .id_table = hptiop_id_table, + .probe = hptiop_probe, + .remove = hptiop_remove, + .shutdown = hptiop_shutdown, +}; + +static int __init hptiop_module_init(void) +{ + int error; + + printk(KERN_INFO "%s %s\n", driver_name_long, driver_ver); + + error = pci_register_driver(&hptiop_pci_driver); + if (error < 0) + return error; + + hptiop_cdev_major = register_chrdev(0, "hptiop", &hptiop_cdev_fops); + if (hptiop_cdev_major < 0) { + printk(KERN_WARNING "unable to register hptiop device.\n"); + return hptiop_cdev_major; + } + + return 0; +} + +static void __exit hptiop_module_exit(void) +{ + dprintk("hptiop_module_exit\n"); + unregister_chrdev(hptiop_cdev_major, "hptiop"); + pci_unregister_driver(&hptiop_pci_driver); +} + + +module_init(hptiop_module_init); +module_exit(hptiop_module_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/hptiop.h b/drivers/scsi/hptiop.h new file mode 100644 index 0000000..f04f7e8 --- /dev/null +++ b/drivers/scsi/hptiop.h @@ -0,0 +1,465 @@ +/* + * HighPoint RR3xxx controller driver for Linux + * Copyright (C) 2006 HighPoint Technologies, Inc. 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Please report bugs/comments/suggestions to linux@highpoint-tech.com + * + * For more information, visit http://www.highpoint-tech.com + */ +#ifndef _HPTIOP_H_ +#define _HPTIOP_H_ + +/* + * logical device type. + * Identify array (logical device) and physical device. + */ +#define LDT_ARRAY 1 +#define LDT_DEVICE 2 + +/* + * Array types + */ +#define AT_UNKNOWN 0 +#define AT_RAID0 1 +#define AT_RAID1 2 +#define AT_RAID5 3 +#define AT_RAID6 4 +#define AT_JBOD 7 + +#define MAX_NAME_LENGTH 36 +#define MAX_ARRAYNAME_LEN 16 + +#define MAX_ARRAY_MEMBERS_V1 8 +#define MAX_ARRAY_MEMBERS_V2 16 + +/* keep definition for source code compatiblity */ +#define MAX_ARRAY_MEMBERS MAX_ARRAY_MEMBERS_V1 + +/* + * array flags + */ +#define ARRAY_FLAG_DISABLED 0x00000001 /* The array is disabled */ +#define ARRAY_FLAG_NEEDBUILDING 0x00000002 /* need to be rebuilt */ +#define ARRAY_FLAG_REBUILDING 0x00000004 /* in rebuilding process */ +#define ARRAY_FLAG_BROKEN 0x00000008 /* broken but still working */ +#define ARRAY_FLAG_BOOTDISK 0x00000010 /* has a active partition */ +#define ARRAY_FLAG_BOOTMARK 0x00000040 /* array has boot mark set */ +#define ARRAY_FLAG_NEED_AUTOREBUILD 0x00000080 /* auto-rebuild should start */ +#define ARRAY_FLAG_VERIFYING 0x00000100 /* is being verified */ +#define ARRAY_FLAG_INITIALIZING 0x00000200 /* is being initialized */ +#define ARRAY_FLAG_TRANSFORMING 0x00000400 /* tranform in progress */ +#define ARRAY_FLAG_NEEDTRANSFORM 0x00000800 /* array need tranform */ +#define ARRAY_FLAG_NEEDINITIALIZING 0x00001000 /* initialization not done */ +#define ARRAY_FLAG_BROKEN_REDUNDANT 0x00002000 /* broken but redundant */ + +/* + * device flags + */ +#define DEVICE_FLAG_DISABLED 0x00000001 /* device is disabled */ +#define DEVICE_FLAG_UNINITIALIZED 0x00010000 /* device is not initialized */ +#define DEVICE_FLAG_LEGACY 0x00020000 /* lagacy drive */ +#define DEVICE_FLAG_IS_SPARE 0x80000000 /* is a spare disk */ + +/* + * ioctl codes + */ +#define HPT_CTL_CODE(x) (x+0xFF00) +#define HPT_CTL_CODE_LINUX_TO_IOP(x) ((x)-0xff00) + +#define HPT_IOCTL_GET_CONTROLLER_INFO HPT_CTL_CODE(2) +#define HPT_IOCTL_GET_CHANNEL_INFO HPT_CTL_CODE(3) +#define HPT_IOCTL_GET_LOGICAL_DEVICES HPT_CTL_CODE(4) +#define HPT_IOCTL_GET_DRIVER_CAPABILITIES HPT_CTL_CODE(19) +#define HPT_IOCTL_GET_DEVICE_INFO_V3 HPT_CTL_CODE(46) +#define HPT_IOCTL_GET_CONTROLLER_INFO_V2 HPT_CTL_CODE(47) + +/* + * Controller information. + */ +struct hpt_controller_info { + u8 chip_type; /* chip type */ + u8 interrupt_level; /* IRQ level */ + u8 num_buses; /* bus count */ + u8 chip_flags; + + u8 product_id[MAX_NAME_LENGTH];/* product name */ + u8 vendor_id[MAX_NAME_LENGTH]; /* vendor name */ +} +__attribute__((packed)); + +/* + * Channel information. + */ +struct hpt_channel_info { + __le32 io_port; /* IDE Base Port Address */ + __le32 control_port; /* IDE Control Port Address */ + __le32 devices[2]; /* device connected to this channel */ +} +__attribute__((packed)); + +/* + * Array information. + */ +struct hpt_array_info_v3 { + u8 name[MAX_ARRAYNAME_LEN]; /* array name */ + u8 description[64]; /* array description */ + u8 create_manager[16]; /* who created it */ + __le32 create_time; /* when created it */ + + u8 array_type; /* array type */ + u8 block_size_shift; /* stripe size */ + u8 ndisk; /* Number of ID in Members[] */ + u8 reserved; + + __le32 flags; /* working flags, see ARRAY_FLAG_XXX */ + __le32 members[MAX_ARRAY_MEMBERS_V2]; /* member array/disks */ + + __le32 rebuilding_progress; + __le64 rebuilt_sectors; /* rebuilding point (LBA) for single member */ + + __le32 transform_source; + __le32 transform_target; /* destination device ID */ + __le32 transforming_progress; + __le32 signature; /* persistent identification*/ + __le16 critical_members; /* bit mask of critical members */ + __le16 reserve2; + __le32 reserve; +} +__attribute__((packed)); + +/* + * physical device information. + */ +#define MAX_PARENTS_PER_DISK 8 + +struct hpt_device_info_v2 { + u8 ctlr_id; /* controller id */ + u8 path_id; /* bus */ + u8 target_id; /* id */ + u8 device_mode_setting; /* Current Data Transfer mode: 0-4 PIO0-4 */ + /* 5-7 MW DMA0-2, 8-13 UDMA0-5 */ + u8 device_type; /* device type */ + u8 usable_mode; /* highest usable mode */ + +#ifdef __BIG_ENDIAN_BITFIELD + u8 NCQ_enabled: 1; + u8 NCQ_supported: 1; + u8 TCQ_enabled: 1; + u8 TCQ_supported: 1; + u8 write_cache_enabled: 1; + u8 write_cache_supported: 1; + u8 read_ahead_enabled: 1; + u8 read_ahead_supported: 1; + u8 reserved6: 6; + u8 spin_up_mode: 2; +#else + u8 read_ahead_supported: 1; + u8 read_ahead_enabled: 1; + u8 write_cache_supported: 1; + u8 write_cache_enabled: 1; + u8 TCQ_supported: 1; + u8 TCQ_enabled: 1; + u8 NCQ_supported: 1; + u8 NCQ_enabled: 1; + u8 spin_up_mode: 2; + u8 reserved6: 6; +#endif + + __le32 flags; /* working flags, see DEVICE_FLAG_XXX */ + u8 ident[150]; /* (partitial) Identify Data of this device */ + + __le64 total_free; + __le64 max_free; + __le64 bad_sectors; + __le32 parent_arrays[MAX_PARENTS_PER_DISK]; +} +__attribute__((packed)); + +/* + * Logical device information. + */ +#define INVALID_TARGET_ID 0xFF +#define INVALID_BUS_ID 0xFF + +struct hpt_logical_device_info_v3 { + u8 type; /* LDT_ARRAY or LDT_DEVICE */ + u8 cache_policy; /* refer to CACHE_POLICY_xxx */ + u8 vbus_id; /* vbus sequence in vbus_list */ + u8 target_id; /* OS target id. 0xFF is invalid */ + /* OS name: DISK $VBusId_$TargetId */ + __le64 capacity; /* array capacity */ + __le32 parent_array; /* don't use this field for physical + device. use ParentArrays field in + hpt_device_info_v2 */ + /* reserved statistic fields */ + __le32 stat1; + __le32 stat2; + __le32 stat3; + __le32 stat4; + + union { + struct hpt_array_info_v3 array; + struct hpt_device_info_v2 device; + } __attribute__((packed)) u; + +} +__attribute__((packed)); + +/* + * ioctl structure + */ +#define HPT_IOCTL_MAGIC 0xA1B2C3D4 + +struct hpt_ioctl_u { + u32 magic; /* used to check if it's a valid ioctl packet */ + u32 ioctl_code; /* operation control code */ + void __user *inbuf; /* input data buffer */ + u32 inbuf_size; /* size of input data buffer */ + void __user *outbuf; /* output data buffer */ + u32 outbuf_size; /* size of output data buffer */ + void __user *bytes_returned; /* count of bytes returned */ +} +__attribute__((packed)); + + +struct hpt_iopmu +{ + __le32 resrved0[4]; + __le32 inbound_msgaddr0; + __le32 inbound_msgaddr1; + __le32 outbound_msgaddr0; + __le32 outbound_msgaddr1; + __le32 inbound_doorbell; + __le32 inbound_intstatus; + __le32 inbound_intmask; + __le32 outbound_doorbell; + __le32 outbound_intstatus; + __le32 outbound_intmask; + __le32 reserved1[2]; + __le32 inbound_queue; + __le32 outbound_queue; +}; + +#define IOPMU_QUEUE_EMPTY 0xffffffff +#define IOPMU_QUEUE_MASK_HOST_BITS 0xf0000000 +#define IOPMU_QUEUE_ADDR_HOST_BIT 0x80000000 + +#define IOPMU_OUTBOUND_INT_MSG0 1 +#define IOPMU_OUTBOUND_INT_MSG1 2 +#define IOPMU_OUTBOUND_INT_DOORBELL 4 +#define IOPMU_OUTBOUND_INT_POSTQUEUE 8 +#define IOPMU_OUTBOUND_INT_PCI 0x10 + +#define IOPMU_INBOUND_INT_MSG0 1 +#define IOPMU_INBOUND_INT_MSG1 2 +#define IOPMU_INBOUND_INT_DOORBELL 4 +#define IOPMU_INBOUND_INT_ERROR 8 +#define IOPMU_INBOUND_INT_POSTQUEUE 0x10 + +enum hpt_iopmu_message { + /* host-to-iop messages */ + IOPMU_INBOUND_MSG0_NOP = 0, + IOPMU_INBOUND_MSG0_RESET, + IOPMU_INBOUND_MSG0_FLUSH, + IOPMU_INBOUND_MSG0_SHUTDOWN, + IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, + IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, + IOPMU_INBOUND_MSG0_MAX = 0xff, + /* iop-to-host messages */ + IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100, + IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_MAX = 0x1ff, + IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_0 = 0x200, + IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_MAX = 0x2ff, + IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_0 = 0x300, + IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff, +}; + +struct hpt_iop_request_header +{ + __le32 size; + __le32 type; + __le32 flags; + __le32 result; + __le32 context; /* host context */ + __le32 context_hi32; +}; + +#define IOP_REQUEST_FLAG_SYNC_REQUEST 1 +#define IOP_REQUEST_FLAG_BIST_REQUEST 2 +#define IOP_REQUEST_FLAG_REMAPPED 4 +#define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8 + +enum hpt_iop_request_type { + IOP_REQUEST_TYPE_GET_CONFIG = 0, + IOP_REQUEST_TYPE_SET_CONFIG, + IOP_REQUEST_TYPE_BLOCK_COMMAND, + IOP_REQUEST_TYPE_SCSI_COMMAND, + IOP_REQUEST_TYPE_IOCTL_COMMAND, + IOP_REQUEST_TYPE_MAX +}; + +enum hpt_iop_result_type { + IOP_RESULT_PENDING = 0, + IOP_RESULT_SUCCESS, + IOP_RESULT_FAIL, + IOP_RESULT_BUSY, + IOP_RESULT_RESET, + IOP_RESULT_INVALID_REQUEST, + IOP_RESULT_BAD_TARGET, + IOP_RESULT_MODE_SENSE_CHECK_CONDITION, +}; + +struct hpt_iop_request_get_config +{ + struct hpt_iop_request_header header; + __le32 interface_version; + __le32 firmware_version; + __le32 max_requests; + __le32 request_size; + __le32 max_sg_count; + __le32 data_transfer_length; + __le32 alignment_mask; + __le32 max_devices; + __le32 sdram_size; +}; + +struct hpt_iop_request_set_config +{ + struct hpt_iop_request_header header; + __le32 iop_id; + __le32 vbus_id; + __le32 reserve[6]; +}; + +struct hpt_iopsg +{ + __le32 size; + __le32 eot; /* non-zero: end of table */ + __le64 pci_address; +}; + +struct hpt_iop_request_block_command +{ + struct hpt_iop_request_header header; + u8 channel; + u8 target; + u8 lun; + u8 pad1; + __le16 command; /* IOP_BLOCK_COMMAND_{READ,WRITE} */ + __le16 sectors; + __le64 lba; + struct hpt_iopsg sg_list[1]; +}; + +#define IOP_BLOCK_COMMAND_READ 1 +#define IOP_BLOCK_COMMAND_WRITE 2 +#define IOP_BLOCK_COMMAND_VERIFY 3 +#define IOP_BLOCK_COMMAND_FLUSH 4 +#define IOP_BLOCK_COMMAND_SHUTDOWN 5 + +struct hpt_iop_request_scsi_command +{ + struct hpt_iop_request_header header; + u8 channel; + u8 target; + u8 lun; + u8 pad1; + u8 cdb[16]; + __le32 dataxfer_length; + struct hpt_iopsg sg_list[1]; +}; + +struct hpt_iop_request_ioctl_command +{ + struct hpt_iop_request_header header; + __le32 ioctl_code; + __le32 inbuf_size; + __le32 outbuf_size; + __le32 bytes_returned; + u8 buf[1]; + /* out data should be put at buf[(inbuf_size+3)&~3] */ +}; + +#define HPTIOP_MAX_REQUESTS 256u + +struct hptiop_request { + struct hptiop_request * next; + void * req_virt; + u32 req_shifted_phy; + struct scsi_cmnd * scp; + int index; +}; + +struct hpt_scsi_pointer { + int mapped; + int sgcnt; + dma_addr_t dma_handle; +}; + +#define HPT_SCP(scp) ((struct hpt_scsi_pointer *)&(scp)->SCp) + +struct hptiop_hba { + struct hpt_iopmu __iomem * iop; + struct Scsi_Host * host; + struct pci_dev * pcidev; + + struct list_head link; + + /* IOP config info */ + u32 firmware_version; + u32 sdram_size; + u32 max_devices; + u32 max_requests; + u32 max_request_size; + u32 max_sg_descriptors; + + u32 req_size; /* host-allocated request buffer size */ + int initialized; + int msg_done; + + struct hptiop_request * req_list; + struct hptiop_request reqs[HPTIOP_MAX_REQUESTS]; + + /* used to free allocated dma area */ + void * dma_coherent; + dma_addr_t dma_coherent_handle; + + atomic_t reset_count; + atomic_t resetting; + + wait_queue_head_t reset_wq; + wait_queue_head_t ioctl_wq; +}; + +struct hpt_ioctl_k +{ + struct hptiop_hba * hba; + u32 ioctl_code; + u32 inbuf_size; + u32 outbuf_size; + void * inbuf; + void * outbuf; + u32 * bytes_returned; + void (*done)(struct hpt_ioctl_k *); + int result; /* HPT_IOCTL_RESULT_ */ +}; + +#define HPT_IOCTL_RESULT_OK 0 +#define HPT_IOCTL_RESULT_FAILED (-1) + +#if 0 +#define dprintk(fmt, args...) do { printk(fmt, ##args); } while(0) +#else +#define dprintk(fmt, args...) +#endif + +#endif diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 24eb59e..497f664 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -760,7 +760,7 @@ static int device_inquiry(int host_index while (!got_interrupt(host_index)) barrier(); - /*if command succesful, break */ + /*if command successful, break */ if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) return 1; } @@ -885,7 +885,7 @@ static int immediate_assign(int host_ind while (!got_interrupt(host_index)) barrier(); - /*if command succesful, break */ + /*if command successful, break */ if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) return 1; } @@ -921,7 +921,7 @@ static int immediate_feature(int host_in return 2; } else global_command_error_excuse = 0; - /*if command succesful, break */ + /*if command successful, break */ if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) return 1; } @@ -959,7 +959,7 @@ static int immediate_reset(int host_inde /* did not work, finish */ return 1; } - /*if command succesful, break */ + /*if command successful, break */ if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) return 1; } @@ -1441,7 +1441,7 @@ static int ibmmca_getinfo(char *buf, int struct Scsi_Host *dev = dev_id; spin_lock_irqsave(dev->host_lock, flags); - + shpnt = dev; /* assign host-structure to local pointer */ len = 0; /* set filled text-buffer index to 0 */ /* get the _special contents of the hostdata structure */ @@ -1456,7 +1456,7 @@ static int ibmmca_getinfo(char *buf, int /* if the integrated subsystem has been found automatically: */ len += sprintf(buf + len, "Adapter category: integrated\n" "Chip revision level: %d\n" "Chip status: %s\n" "8 kByte NVRAM status: %s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 1) ? "enabled" : "disabled", (pos[2] & 2) ? "locked" : "accessible"); - } else if ((speciale >= 0) && (speciale < (sizeof(subsys_list) / sizeof(struct subsys_list_struct)))) { + } else if ((speciale >= 0) && (speciale < ARRAY_SIZE(subsys_list))) { /* if the subsystem is a slot adapter */ len += sprintf(buf + len, "Adapter category: slot-card\n" "ROM Segment Address: "); if ((pos[2] & 0xf0) == 0xf0) @@ -1477,16 +1477,16 @@ static int ibmmca_getinfo(char *buf, int while (len % sizeof(int) != (sizeof(int) - 1)) len += sprintf(buf + len, " "); len += sprintf(buf + len, "\n"); - + spin_unlock_irqrestore(shpnt->host_lock, flags); - + return len; } int ibmmca_detect(struct scsi_host_template * scsi_template) { struct Scsi_Host *shpnt; - int port, id, i, j, k, list_size, slot; + int port, id, i, j, k, slot; int devices_on_irq_11 = 0; int devices_on_irq_14 = 0; int IRQ14_registered = 0; @@ -1603,8 +1603,7 @@ #endif /* now look for other adapters in MCA slots, */ /* determine the number of known IBM-SCSI-subsystem types */ /* see the pos[2] dependence to get the adapter port-offset. */ - list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); - for (i = 0; i < list_size; i++) { + for (i = 0; i < ARRAY_SIZE(subsys_list); i++) { /* scan each slot for a fitting adapter id */ slot = 0; /* start at slot 0 */ while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot)) @@ -1669,8 +1668,7 @@ #endif /* now check for SCSI-adapters, mapped to the integrated SCSI * area. E.g. a W/Cache in MCA-slot 9(!). Do the check correct here, * as this is a known effect on some models 95xx. */ - list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); - for (i = 0; i < list_size; i++) { + for (i = 0; i < ARRAY_SIZE(subsys_list); i++) { /* scan each slot for a fitting adapter id */ slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI); if (slot != MCA_NOTFOUND) { /* scan through all slots */ @@ -2243,8 +2241,7 @@ static int __ibmmca_host_reset(Scsi_Cmnd int host_index; unsigned long imm_command; - if (cmd == NULL) - BUG(); + BUG_ON(cmd == NULL); ticks = IM_RESET_DELAY * HZ; shpnt = cmd->device->host; diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 2e9be83..944fc12 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -121,10 +121,9 @@ static int initialize_event_pool(struct pool->size = size; pool->next = 0; - pool->events = kmalloc(pool->size * sizeof(*pool->events), GFP_KERNEL); + pool->events = kcalloc(pool->size, sizeof(*pool->events), GFP_KERNEL); if (!pool->events) return -ENOMEM; - memset(pool->events, 0x00, pool->size * sizeof(*pool->events)); pool->iu_storage = dma_alloc_coherent(hostdata->dev, diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 39b760a..988e6f7 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -600,8 +600,7 @@ static ide_startstop_t idescsi_transfer_ "issuing a packet command\n"); return ide_do_reset (drive); } - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); /* Set the interrupt routine */ ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry); /* Send the actual packet */ @@ -691,8 +690,7 @@ static ide_startstop_t idescsi_issue_pc set_bit(PC_DMA_OK, &pc->flags); if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { - if (HWGROUP(drive)->handler != NULL) - BUG(); + BUG_ON(HWGROUP(drive)->handler != NULL); ide_set_handler(drive, &idescsi_transfer_pc, get_timeout(pc), idescsi_expiry); /* Issue the packet command */ diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index fc0f30a..681bd18 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -3,9 +3,6 @@ * * (The IMM is the embedded controller in the ZIP Plus drive.) * - * Current Maintainer: David Campbell (Perth, Western Australia) - * campbell@torque.net - * * My unoffical company acronym list is 21 pages long: * FLA: Four letter acronym with built in facility for * future expansion to five letters. @@ -1119,6 +1116,10 @@ static int device_check(imm_struct *dev) return -ENODEV; } +/* + * imm cannot deal with highmem, so this causes all IO pages for this host + * to reside in low memory (hence mapped) + */ static int imm_adjust_queue(struct scsi_device *device) { blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH); @@ -1141,10 +1142,6 @@ static struct scsi_host_template imm_tem .use_clustering = ENABLE_CLUSTERING, .can_queue = 1, .slave_alloc = imm_adjust_queue, - .unchecked_isa_dma = 1, /* imm cannot deal with highmem, so - * this is an easy trick to ensure - * all io pages for this host reside - * in low memory */ }; /*************************************************************************** diff --git a/drivers/scsi/imm.h b/drivers/scsi/imm.h index dc3aebf..ece936a 100644 --- a/drivers/scsi/imm.h +++ b/drivers/scsi/imm.h @@ -2,7 +2,7 @@ /* Driver for the Iomega MatchMaker parallel port SCSI HBA embedded in * the Iomega ZIP Plus drive * - * (c) 1998 David Campbell campbell@torque.net + * (c) 1998 David Campbell * * Please note that I live in Perth, Western Australia. GMT+0800 */ diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index 9c51987..883bc92 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c @@ -370,7 +370,7 @@ static int in2000_queuecommand(Scsi_Cmnd */ if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *) cmd->buffer; + cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; cmd->SCp.ptr = (char *) page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset; cmd->SCp.this_residual = cmd->SCp.buffer->length; @@ -1809,7 +1809,7 @@ static int in2000_abort(Scsi_Cmnd * cmd) #define MAX_IN2000_HOSTS 3 -#define MAX_SETUP_ARGS (sizeof(setup_args) / sizeof(char *)) +#define MAX_SETUP_ARGS ARRAY_SIZE(setup_args) #define SETUP_BUFFER_SIZE 200 static char setup_buffer[SETUP_BUFFER_SIZE]; static char setup_used[MAX_SETUP_ARGS]; diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 0cc7f65..913ba95 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -154,7 +154,6 @@ #ifdef DEBUG_i91u static unsigned int i91u_debug = DEBUG_DEFAULT; #endif -#define TULSZ(sz) (sizeof(sz) / sizeof(sz[0])) #define TUL_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) )) typedef struct PCI_ID_Struc { @@ -2771,7 +2770,7 @@ static int tul_NewReturnNumberOfAdapters init_i91uAdapter_table(); - for (i = 0; i < TULSZ(i91u_pci_devices); i++) + for (i = 0; i < ARRAY_SIZE(i91u_pci_devices); i++) { while ((pDev = pci_find_device(i91u_pci_devices[i].vendor_id, i91u_pci_devices[i].device_id, pDev)) != NULL) { if (pci_enable_device(pDev)) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 8b80e59..96b65b3 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -79,7 +79,6 @@ #include #include #include #include -#include #include "ipr.h" /* diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index a4c0b04..78f2ff7 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -556,7 +556,7 @@ ips_setup(char *ips_str) * We now have key/value pairs. * Update the variables */ - for (i = 0; i < (sizeof (options) / sizeof (options[0])); i++) { + for (i = 0; i < ARRAY_SIZE(options); i++) { if (strnicmp (key, options[i].option_name, strlen(options[i].option_name)) == 0) { @@ -4364,7 +4364,7 @@ ips_rdcap(ips_ha_t * ha, ips_scb_t * scb METHOD_TRACE("ips_rdcap", 1); - if (scb->scsi_cmd->bufflen < 8) + if (scb->scsi_cmd->request_bufflen < 8) return (0); cap.lba = @@ -6438,7 +6438,7 @@ ips_erase_bios(ips_ha_t * ha) /* VPP failure */ return (1); - /* check for succesful flash */ + /* check for successful flash */ if (status & 0x30) /* sequence error */ return (1); @@ -6550,7 +6550,7 @@ ips_erase_bios_memio(ips_ha_t * ha) /* VPP failure */ return (1); - /* check for succesful flash */ + /* check for successful flash */ if (status & 0x30) /* sequence error */ return (1); diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 2068b66..b4743a9 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -3,7 +3,8 @@ * * Copyright (C) 2004 Dmitry Yusupov * Copyright (C) 2004 Alex Aizman - * Copyright (C) 2005 Mike Christie + * Copyright (C) 2005 - 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify @@ -36,37 +37,28 @@ #include #include #include #include -#include -#include -#include -#include #include #include #include #include "iscsi_tcp.h" +#define ISCSI_TCP_VERSION "1.0-595" + MODULE_AUTHOR("Dmitry Yusupov , " "Alex Aizman "); MODULE_DESCRIPTION("iSCSI/TCP data-path"); MODULE_LICENSE("GPL"); -MODULE_VERSION("0:4.445"); +MODULE_VERSION(ISCSI_TCP_VERSION); /* #define DEBUG_TCP */ -/* #define DEBUG_SCSI */ #define DEBUG_ASSERT #ifdef DEBUG_TCP -#define debug_tcp(fmt...) printk(KERN_DEBUG "tcp: " fmt) +#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt) #else #define debug_tcp(fmt...) #endif -#ifdef DEBUG_SCSI -#define debug_scsi(fmt...) printk(KERN_DEBUG "scsi: " fmt) -#else -#define debug_scsi(fmt...) -#endif - #ifndef DEBUG_ASSERT #ifdef BUG_ON #undef BUG_ON @@ -74,22 +66,9 @@ #endif #define BUG_ON(expr) #endif -#define INVALID_SN_DELTA 0xffff - static unsigned int iscsi_max_lun = 512; module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); -/* global data */ -static kmem_cache_t *taskcache; - -static inline void -iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size) -{ - sg_init_one(&ibuf->sg, (u8 *)vbuf, size); - ibuf->sent = 0; - ibuf->use_sendmsg = 0; -} - static inline void iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) { @@ -130,68 +109,39 @@ static inline void iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf, u8* crc) { - crypto_digest_digest(conn->tx_tfm, &buf->sg, 1, crc); - buf->sg.length += sizeof(uint32_t); -} + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; -static void -iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) -{ - struct iscsi_session *session = conn->session; - unsigned long flags; - - spin_lock_irqsave(&session->lock, flags); - if (session->conn_cnt == 1 || session->leadconn == conn) - session->state = ISCSI_STATE_FAILED; - spin_unlock_irqrestore(&session->lock, flags); - set_bit(SUSPEND_BIT, &conn->suspend_tx); - set_bit(SUSPEND_BIT, &conn->suspend_rx); - iscsi_conn_error(conn->cls_conn, err); + crypto_digest_digest(tcp_conn->tx_tfm, &buf->sg, 1, crc); + buf->sg.length += sizeof(uint32_t); } static inline int -iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) +iscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn) { - uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn); - uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn); - - if (max_cmdsn < exp_cmdsn -1 && - max_cmdsn > exp_cmdsn - INVALID_SN_DELTA) - return ISCSI_ERR_MAX_CMDSN; - if (max_cmdsn > session->max_cmdsn || - max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA) - session->max_cmdsn = max_cmdsn; - if (exp_cmdsn > session->exp_cmdsn || - exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA) - session->exp_cmdsn = exp_cmdsn; + struct sk_buff *skb = tcp_conn->in.skb; - return 0; -} + tcp_conn->in.zero_copy_hdr = 0; -static inline int -iscsi_hdr_extract(struct iscsi_conn *conn) -{ - struct sk_buff *skb = conn->in.skb; - - if (conn->in.copy >= conn->hdr_size && - conn->in_progress == IN_PROGRESS_WAIT_HEADER) { + if (tcp_conn->in.copy >= tcp_conn->hdr_size && + tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER) { /* * Zero-copy PDU Header: using connection context * to store header pointer. */ if (skb_shinfo(skb)->frag_list == NULL && - !skb_shinfo(skb)->nr_frags) - conn->in.hdr = (struct iscsi_hdr *) - ((char*)skb->data + conn->in.offset); - else { + !skb_shinfo(skb)->nr_frags) { + tcp_conn->in.hdr = (struct iscsi_hdr *) + ((char*)skb->data + tcp_conn->in.offset); + tcp_conn->in.zero_copy_hdr = 1; + } else { /* ignoring return code since we checked * in.copy before */ - skb_copy_bits(skb, conn->in.offset, - &conn->hdr, conn->hdr_size); - conn->in.hdr = &conn->hdr; + skb_copy_bits(skb, tcp_conn->in.offset, + &tcp_conn->hdr, tcp_conn->hdr_size); + tcp_conn->in.hdr = &tcp_conn->hdr; } - conn->in.offset += conn->hdr_size; - conn->in.copy -= conn->hdr_size; + tcp_conn->in.offset += tcp_conn->hdr_size; + tcp_conn->in.copy -= tcp_conn->hdr_size; } else { int hdr_remains; int copylen; @@ -201,118 +151,51 @@ iscsi_hdr_extract(struct iscsi_conn *con * copying it... This'll happen quite rarely. */ - if (conn->in_progress == IN_PROGRESS_WAIT_HEADER) - conn->in.hdr_offset = 0; + if (tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER) + tcp_conn->in.hdr_offset = 0; - hdr_remains = conn->hdr_size - conn->in.hdr_offset; + hdr_remains = tcp_conn->hdr_size - tcp_conn->in.hdr_offset; BUG_ON(hdr_remains <= 0); - copylen = min(conn->in.copy, hdr_remains); - skb_copy_bits(skb, conn->in.offset, - (char*)&conn->hdr + conn->in.hdr_offset, copylen); + copylen = min(tcp_conn->in.copy, hdr_remains); + skb_copy_bits(skb, tcp_conn->in.offset, + (char*)&tcp_conn->hdr + tcp_conn->in.hdr_offset, + copylen); debug_tcp("PDU gather offset %d bytes %d in.offset %d " - "in.copy %d\n", conn->in.hdr_offset, copylen, - conn->in.offset, conn->in.copy); + "in.copy %d\n", tcp_conn->in.hdr_offset, copylen, + tcp_conn->in.offset, tcp_conn->in.copy); - conn->in.offset += copylen; - conn->in.copy -= copylen; + tcp_conn->in.offset += copylen; + tcp_conn->in.copy -= copylen; if (copylen < hdr_remains) { - conn->in_progress = IN_PROGRESS_HEADER_GATHER; - conn->in.hdr_offset += copylen; + tcp_conn->in_progress = IN_PROGRESS_HEADER_GATHER; + tcp_conn->in.hdr_offset += copylen; return -EAGAIN; } - conn->in.hdr = &conn->hdr; - conn->discontiguous_hdr_cnt++; - conn->in_progress = IN_PROGRESS_WAIT_HEADER; + tcp_conn->in.hdr = &tcp_conn->hdr; + tcp_conn->discontiguous_hdr_cnt++; + tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; } return 0; } -static inline void -iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +/* + * must be called with session lock + */ +static void +__iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct scsi_cmnd *sc = ctask->sc; - struct iscsi_session *session = conn->session; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct scsi_cmnd *sc; - spin_lock(&session->lock); - if (unlikely(!sc)) { - spin_unlock(&session->lock); + sc = ctask->sc; + if (unlikely(!sc)) return; - } - if (sc->sc_data_direction == DMA_TO_DEVICE) { - struct iscsi_data_task *dtask, *n; - /* WRITE: cleanup Data-Out's if any */ - list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) { - list_del(&dtask->item); - mempool_free(dtask, ctask->datapool); - } - } - ctask->xmstate = XMSTATE_IDLE; - ctask->r2t = NULL; - ctask->sc = NULL; - __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); - spin_unlock(&session->lock); -} - -/** - * iscsi_cmd_rsp - SCSI Command Response processing - * @conn: iscsi connection - * @ctask: scsi command task - **/ -static int -iscsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) -{ - int rc; - struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)conn->in.hdr; - struct iscsi_session *session = conn->session; - struct scsi_cmnd *sc = ctask->sc; - - rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); - if (rc) { - sc->result = (DID_ERROR << 16); - goto out; - } - conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; - - sc->result = (DID_OK << 16) | rhdr->cmd_status; - - if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) { - sc->result = (DID_ERROR << 16); - goto out; - } - - if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION && conn->senselen) { - int sensecopy = min(conn->senselen, SCSI_SENSE_BUFFERSIZE); - - memcpy(sc->sense_buffer, conn->data + 2, sensecopy); - debug_scsi("copied %d bytes of sense\n", sensecopy); - } - - if (sc->sc_data_direction == DMA_TO_DEVICE) - goto out; - - if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { - int res_count = be32_to_cpu(rhdr->residual_count); - - if (res_count > 0 && res_count <= sc->request_bufflen) - sc->resid = res_count; - else - sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; - } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW) - sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; - else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) - sc->resid = be32_to_cpu(rhdr->residual_count); - -out: - debug_scsi("done [sc %lx res %d itt 0x%x]\n", - (long)sc, sc->result, ctask->itt); - conn->scsirsp_pdus_cnt++; - iscsi_ctask_cleanup(conn, ctask); - sc->scsi_done(sc); - return rc; + tcp_ctask->xmstate = XMSTATE_IDLE; + tcp_ctask->r2t = NULL; } /** @@ -324,7 +207,9 @@ static int iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { int rc; - struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)conn->in.hdr; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr; struct iscsi_session *session = conn->session; int datasn = be32_to_cpu(rhdr->datasn); @@ -334,9 +219,9 @@ iscsi_data_rsp(struct iscsi_conn *conn, /* * setup Data-In byte counter (gets decremented..) */ - ctask->data_count = conn->in.datalen; + ctask->data_count = tcp_conn->in.datalen; - if (conn->in.datalen == 0) + if (tcp_conn->in.datalen == 0) return 0; if (ctask->datasn != datasn) @@ -344,8 +229,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, ctask->datasn++; - ctask->data_offset = be32_to_cpu(rhdr->offset); - if (ctask->data_offset + conn->in.datalen > ctask->total_length) + tcp_ctask->data_offset = be32_to_cpu(rhdr->offset); + if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length) return ISCSI_ERR_DATA_OFFSET; if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) { @@ -390,19 +275,17 @@ iscsi_solicit_data_init(struct iscsi_con struct iscsi_r2t_info *r2t) { struct iscsi_data *hdr; - struct iscsi_data_task *dtask; struct scsi_cmnd *sc = ctask->sc; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); - BUG_ON(!dtask); - hdr = &dtask->hdr; + hdr = &r2t->dtask.hdr; memset(hdr, 0, sizeof(struct iscsi_data)); hdr->ttt = r2t->ttt; hdr->datasn = cpu_to_be32(r2t->solicit_datasn); r2t->solicit_datasn++; hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; - memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); - hdr->itt = ctask->hdr.itt; + memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); + hdr->itt = ctask->hdr->itt; hdr->exp_statsn = r2t->exp_statsn; hdr->offset = cpu_to_be32(r2t->data_offset); if (r2t->data_length > conn->max_xmit_dlength) { @@ -418,11 +301,9 @@ iscsi_solicit_data_init(struct iscsi_con r2t->sent = 0; - iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr, + iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr, sizeof(struct iscsi_hdr)); - r2t->dtask = dtask; - if (sc->use_sg) { int i, sg_count = 0; struct scatterlist *sg = sc->request_buffer; @@ -451,11 +332,9 @@ iscsi_solicit_data_init(struct iscsi_con } BUG_ON(r2t->sg == NULL); } else - iscsi_buf_init_iov(&ctask->sendbuf, + iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)sc->request_buffer + r2t->data_offset, r2t->data_count); - - list_add(&dtask->item, &ctask->dataqueue); } /** @@ -468,17 +347,16 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, s { struct iscsi_r2t_info *r2t; struct iscsi_session *session = conn->session; - struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)conn->in.hdr; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr; int r2tsn = be32_to_cpu(rhdr->r2tsn); int rc; - if (conn->in.ahslen) - return ISCSI_ERR_AHSLEN; - - if (conn->in.datalen) + if (tcp_conn->in.datalen) return ISCSI_ERR_DATALEN; - if (ctask->exp_r2tsn && ctask->exp_r2tsn != r2tsn) + if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn) return ISCSI_ERR_R2TSN; rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); @@ -496,7 +374,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, s spin_unlock(&session->lock); return 0; } - rc = __kfifo_get(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); + rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); BUG_ON(!rc); r2t->exp_statsn = rhdr->statsn; @@ -518,10 +396,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, s iscsi_solicit_data_init(conn, ctask, r2t); - ctask->exp_r2tsn = r2tsn + 1; - ctask->xmstate |= XMSTATE_SOL_HDR; - __kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*)); - __kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*)); + tcp_ctask->exp_r2tsn = r2tsn + 1; + tcp_ctask->xmstate |= XMSTATE_SOL_HDR; + __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); + __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); scsi_queue_work(session->host, &conn->xmitwork); conn->r2t_pdus_cnt++; @@ -531,258 +409,136 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, s } static int -iscsi_hdr_recv(struct iscsi_conn *conn) +iscsi_tcp_hdr_recv(struct iscsi_conn *conn) { - int rc = 0; + int rc = 0, opcode, ahslen; struct iscsi_hdr *hdr; - struct iscsi_cmd_task *ctask; struct iscsi_session *session = conn->session; - uint32_t cdgst, rdgst = 0; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + uint32_t cdgst, rdgst = 0, itt; - hdr = conn->in.hdr; + hdr = tcp_conn->in.hdr; /* verify PDU length */ - conn->in.datalen = ntoh24(hdr->dlength); - if (conn->in.datalen > conn->max_recv_dlength) { + tcp_conn->in.datalen = ntoh24(hdr->dlength); + if (tcp_conn->in.datalen > conn->max_recv_dlength) { printk(KERN_ERR "iscsi_tcp: datalen %d > %d\n", - conn->in.datalen, conn->max_recv_dlength); + tcp_conn->in.datalen, conn->max_recv_dlength); return ISCSI_ERR_DATALEN; } - conn->data_copied = 0; + tcp_conn->data_copied = 0; /* read AHS */ - conn->in.ahslen = hdr->hlength * 4; - conn->in.offset += conn->in.ahslen; - conn->in.copy -= conn->in.ahslen; - if (conn->in.copy < 0) { + ahslen = hdr->hlength << 2; + tcp_conn->in.offset += ahslen; + tcp_conn->in.copy -= ahslen; + if (tcp_conn->in.copy < 0) { printk(KERN_ERR "iscsi_tcp: can't handle AHS with length " - "%d bytes\n", conn->in.ahslen); + "%d bytes\n", ahslen); return ISCSI_ERR_AHSLEN; } /* calculate read padding */ - conn->in.padding = conn->in.datalen & (ISCSI_PAD_LEN-1); - if (conn->in.padding) { - conn->in.padding = ISCSI_PAD_LEN - conn->in.padding; - debug_scsi("read padding %d bytes\n", conn->in.padding); + tcp_conn->in.padding = tcp_conn->in.datalen & (ISCSI_PAD_LEN-1); + if (tcp_conn->in.padding) { + tcp_conn->in.padding = ISCSI_PAD_LEN - tcp_conn->in.padding; + debug_scsi("read padding %d bytes\n", tcp_conn->in.padding); } if (conn->hdrdgst_en) { struct scatterlist sg; sg_init_one(&sg, (u8 *)hdr, - sizeof(struct iscsi_hdr) + conn->in.ahslen); - crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst); + sizeof(struct iscsi_hdr) + ahslen); + crypto_digest_digest(tcp_conn->rx_tfm, &sg, 1, (u8 *)&cdgst); rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) + - conn->in.ahslen); + ahslen); if (cdgst != rdgst) { - printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error " - "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst, - cdgst); + printk(KERN_ERR "iscsi_tcp: hdrdgst error " + "recv 0x%x calc 0x%x\n", rdgst, cdgst); return ISCSI_ERR_HDR_DGST; } } - /* save opcode for later */ - conn->in.opcode = hdr->opcode & ISCSI_OPCODE_MASK; - + opcode = hdr->opcode & ISCSI_OPCODE_MASK; /* verify itt (itt encoding: age+cid+itt) */ - if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { - if ((hdr->itt & AGE_MASK) != - (session->age << AGE_SHIFT)) { - printk(KERN_ERR "iscsi_tcp: received itt %x expected " - "session age (%x)\n", hdr->itt, - session->age & AGE_MASK); - return ISCSI_ERR_BAD_ITT; - } - - if ((hdr->itt & CID_MASK) != (conn->id << CID_SHIFT)) { - printk(KERN_ERR "iscsi_tcp: received itt %x, expected " - "CID (%x)\n", hdr->itt, conn->id); - return ISCSI_ERR_BAD_ITT; - } - conn->in.itt = hdr->itt & ITT_MASK; - } else - conn->in.itt = hdr->itt; + rc = iscsi_verify_itt(conn, hdr, &itt); + if (rc == ISCSI_ERR_NO_SCSI_CMD) { + tcp_conn->in.datalen = 0; /* force drop */ + return 0; + } else if (rc) + return rc; debug_tcp("opcode 0x%x offset %d copy %d ahslen %d datalen %d\n", - hdr->opcode, conn->in.offset, conn->in.copy, - conn->in.ahslen, conn->in.datalen); - - if (conn->in.itt < session->cmds_max) { - ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt]; - - if (!ctask->sc) { - printk(KERN_INFO "iscsi_tcp: dropping ctask with " - "itt 0x%x\n", ctask->itt); - conn->in.datalen = 0; /* force drop */ - return 0; - } - - if (ctask->sc->SCp.phase != session->age) { - printk(KERN_ERR "iscsi_tcp: ctask's session age %d, " - "expected %d\n", ctask->sc->SCp.phase, - session->age); - return ISCSI_ERR_SESSION_FAILED; - } - - conn->in.ctask = ctask; - - debug_scsi("rsp [op 0x%x cid %d sc %lx itt 0x%x len %d]\n", - hdr->opcode, conn->id, (long)ctask->sc, - ctask->itt, conn->in.datalen); - - switch(conn->in.opcode) { - case ISCSI_OP_SCSI_CMD_RSP: - BUG_ON((void*)ctask != ctask->sc->SCp.ptr); - if (!conn->in.datalen) - rc = iscsi_cmd_rsp(conn, ctask); - else - /* - * got sense or response data; copying PDU - * Header to the connection's header - * placeholder - */ - memcpy(&conn->hdr, hdr, - sizeof(struct iscsi_hdr)); - break; - case ISCSI_OP_SCSI_DATA_IN: - BUG_ON((void*)ctask != ctask->sc->SCp.ptr); - /* save flags for non-exceptional status */ - conn->in.flags = hdr->flags; - /* save cmd_status for sense data */ - conn->in.cmd_status = - ((struct iscsi_data_rsp*)hdr)->cmd_status; - rc = iscsi_data_rsp(conn, ctask); - break; - case ISCSI_OP_R2T: - BUG_ON((void*)ctask != ctask->sc->SCp.ptr); - if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) - rc = iscsi_r2t_rsp(conn, ctask); - else - rc = ISCSI_ERR_PROTO; - break; - default: - rc = ISCSI_ERR_BAD_OPCODE; - break; - } - } else if (conn->in.itt >= ISCSI_MGMT_ITT_OFFSET && - conn->in.itt < ISCSI_MGMT_ITT_OFFSET + - session->mgmtpool_max) { - struct iscsi_mgmt_task *mtask = (struct iscsi_mgmt_task *) - session->mgmt_cmds[conn->in.itt - - ISCSI_MGMT_ITT_OFFSET]; - - debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n", - conn->in.opcode, conn->id, mtask->itt, - conn->in.datalen); - - switch(conn->in.opcode) { - case ISCSI_OP_LOGIN_RSP: - case ISCSI_OP_TEXT_RSP: - case ISCSI_OP_LOGOUT_RSP: - rc = iscsi_check_assign_cmdsn(session, - (struct iscsi_nopin*)hdr); - if (rc) - break; - - if (!conn->in.datalen) { - rc = iscsi_recv_pdu(conn->cls_conn, hdr, - NULL, 0); - if (conn->login_mtask != mtask) { - spin_lock(&session->lock); - __kfifo_put(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*)); - spin_unlock(&session->lock); - } - } - break; - case ISCSI_OP_SCSI_TMFUNC_RSP: - rc = iscsi_check_assign_cmdsn(session, - (struct iscsi_nopin*)hdr); - if (rc) - break; + opcode, tcp_conn->in.offset, tcp_conn->in.copy, + ahslen, tcp_conn->in.datalen); - if (conn->in.datalen || conn->in.ahslen) { - rc = ISCSI_ERR_PROTO; - break; - } - conn->tmfrsp_pdus_cnt++; - spin_lock(&session->lock); - if (conn->tmabort_state == TMABORT_INITIAL) { - __kfifo_put(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*)); - conn->tmabort_state = - ((struct iscsi_tm_rsp *)hdr)-> - response == ISCSI_TMF_RSP_COMPLETE ? - TMABORT_SUCCESS:TMABORT_FAILED; - /* unblock eh_abort() */ - wake_up(&conn->ehwait); - } - spin_unlock(&session->lock); - break; - case ISCSI_OP_NOOP_IN: - if (hdr->ttt != ISCSI_RESERVED_TAG) { - rc = ISCSI_ERR_PROTO; - break; - } - rc = iscsi_check_assign_cmdsn(session, - (struct iscsi_nopin*)hdr); - if (rc) - break; - conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; - - if (!conn->in.datalen) { - struct iscsi_mgmt_task *mtask; - - rc = iscsi_recv_pdu(conn->cls_conn, hdr, - NULL, 0); - mtask = (struct iscsi_mgmt_task *) - session->mgmt_cmds[conn->in.itt - - ISCSI_MGMT_ITT_OFFSET]; - if (conn->login_mtask != mtask) { - spin_lock(&session->lock); - __kfifo_put(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*)); - spin_unlock(&session->lock); - } - } - break; - default: - rc = ISCSI_ERR_BAD_OPCODE; - break; - } - } else if (conn->in.itt == ISCSI_RESERVED_TAG) { - switch(conn->in.opcode) { - case ISCSI_OP_NOOP_IN: - if (!conn->in.datalen) { - rc = iscsi_check_assign_cmdsn(session, - (struct iscsi_nopin*)hdr); - if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) - rc = iscsi_recv_pdu(conn->cls_conn, - hdr, NULL, 0); - } else - rc = ISCSI_ERR_PROTO; - break; - case ISCSI_OP_REJECT: - /* we need sth like iscsi_reject_rsp()*/ - case ISCSI_OP_ASYNC_EVENT: - /* we need sth like iscsi_async_event_rsp() */ - rc = ISCSI_ERR_BAD_OPCODE; - break; - default: - rc = ISCSI_ERR_BAD_OPCODE; - break; - } - } else - rc = ISCSI_ERR_BAD_ITT; + switch(opcode) { + case ISCSI_OP_SCSI_DATA_IN: + tcp_conn->in.ctask = session->cmds[itt]; + rc = iscsi_data_rsp(conn, tcp_conn->in.ctask); + /* fall through */ + case ISCSI_OP_SCSI_CMD_RSP: + tcp_conn->in.ctask = session->cmds[itt]; + if (tcp_conn->in.datalen) + goto copy_hdr; + + spin_lock(&session->lock); + __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); + rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); + spin_unlock(&session->lock); + break; + case ISCSI_OP_R2T: + tcp_conn->in.ctask = session->cmds[itt]; + if (ahslen) + rc = ISCSI_ERR_AHSLEN; + else if (tcp_conn->in.ctask->sc->sc_data_direction == + DMA_TO_DEVICE) + rc = iscsi_r2t_rsp(conn, tcp_conn->in.ctask); + else + rc = ISCSI_ERR_PROTO; + break; + case ISCSI_OP_LOGIN_RSP: + case ISCSI_OP_TEXT_RSP: + case ISCSI_OP_LOGOUT_RSP: + case ISCSI_OP_NOOP_IN: + case ISCSI_OP_REJECT: + case ISCSI_OP_ASYNC_EVENT: + if (tcp_conn->in.datalen) + goto copy_hdr; + /* fall through */ + case ISCSI_OP_SCSI_TMFUNC_RSP: + rc = iscsi_complete_pdu(conn, hdr, NULL, 0); + break; + default: + rc = ISCSI_ERR_BAD_OPCODE; + break; + } return rc; + +copy_hdr: + /* + * if we did zero copy for the header but we will need multiple + * skbs to complete the command then we have to copy the header + * for later use + */ + if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy < + (tcp_conn->in.datalen + tcp_conn->in.padding + + (conn->datadgst_en ? 4 : 0))) { + debug_tcp("Copying header for later use. in.copy %d in.datalen" + " %d\n", tcp_conn->in.copy, tcp_conn->in.datalen); + memcpy(&tcp_conn->hdr, tcp_conn->in.hdr, + sizeof(struct iscsi_hdr)); + tcp_conn->in.hdr = &tcp_conn->hdr; + tcp_conn->in.zero_copy_hdr = 0; + } + return 0; } /** * iscsi_ctask_copy - copy skb bits to the destanation cmd task - * @conn: iscsi connection + * @conn: iscsi tcp connection * @ctask: scsi command task * @buf: buffer to copy to * @buf_size: size of buffer @@ -804,110 +560,113 @@ iscsi_hdr_recv(struct iscsi_conn *conn) * buf_left left to copy from in progress buffer **/ static inline int -iscsi_ctask_copy(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, +iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask, void *buf, int buf_size, int offset) { - int buf_left = buf_size - (conn->data_copied + offset); - int size = min(conn->in.copy, buf_left); + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + int buf_left = buf_size - (tcp_conn->data_copied + offset); + int size = min(tcp_conn->in.copy, buf_left); int rc; size = min(size, ctask->data_count); debug_tcp("ctask_copy %d bytes at offset %d copied %d\n", - size, conn->in.offset, conn->in.copied); + size, tcp_conn->in.offset, tcp_conn->in.copied); BUG_ON(size <= 0); - BUG_ON(ctask->sent + size > ctask->total_length); + BUG_ON(tcp_ctask->sent + size > ctask->total_length); - rc = skb_copy_bits(conn->in.skb, conn->in.offset, - (char*)buf + (offset + conn->data_copied), size); + rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, + (char*)buf + (offset + tcp_conn->data_copied), size); /* must fit into skb->len */ BUG_ON(rc); - conn->in.offset += size; - conn->in.copy -= size; - conn->in.copied += size; - conn->data_copied += size; - ctask->sent += size; + tcp_conn->in.offset += size; + tcp_conn->in.copy -= size; + tcp_conn->in.copied += size; + tcp_conn->data_copied += size; + tcp_ctask->sent += size; ctask->data_count -= size; - BUG_ON(conn->in.copy < 0); + BUG_ON(tcp_conn->in.copy < 0); BUG_ON(ctask->data_count < 0); - if (buf_size != (conn->data_copied + offset)) { + if (buf_size != (tcp_conn->data_copied + offset)) { if (!ctask->data_count) { - BUG_ON(buf_size - conn->data_copied < 0); + BUG_ON(buf_size - tcp_conn->data_copied < 0); /* done with this PDU */ - return buf_size - conn->data_copied; + return buf_size - tcp_conn->data_copied; } return -EAGAIN; } /* done with this buffer or with both - PDU and buffer */ - conn->data_copied = 0; + tcp_conn->data_copied = 0; return 0; } /** * iscsi_tcp_copy - copy skb bits to the destanation buffer - * @conn: iscsi connection - * @buf: buffer to copy to - * @buf_size: number of bytes to copy + * @conn: iscsi tcp connection * * Notes: * The function calls skb_copy_bits() and updates per-connection * byte counters. **/ static inline int -iscsi_tcp_copy(struct iscsi_conn *conn, void *buf, int buf_size) +iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn) { - int buf_left = buf_size - conn->data_copied; - int size = min(conn->in.copy, buf_left); + void *buf = tcp_conn->data; + int buf_size = tcp_conn->in.datalen; + int buf_left = buf_size - tcp_conn->data_copied; + int size = min(tcp_conn->in.copy, buf_left); int rc; debug_tcp("tcp_copy %d bytes at offset %d copied %d\n", - size, conn->in.offset, conn->data_copied); + size, tcp_conn->in.offset, tcp_conn->data_copied); BUG_ON(size <= 0); - rc = skb_copy_bits(conn->in.skb, conn->in.offset, - (char*)buf + conn->data_copied, size); + rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, + (char*)buf + tcp_conn->data_copied, size); BUG_ON(rc); - conn->in.offset += size; - conn->in.copy -= size; - conn->in.copied += size; - conn->data_copied += size; + tcp_conn->in.offset += size; + tcp_conn->in.copy -= size; + tcp_conn->in.copied += size; + tcp_conn->data_copied += size; - if (buf_size != conn->data_copied) + if (buf_size != tcp_conn->data_copied) return -EAGAIN; return 0; } static inline void -partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg, - int offset, int length) +partial_sg_digest_update(struct iscsi_tcp_conn *tcp_conn, + struct scatterlist *sg, int offset, int length) { struct scatterlist temp; memcpy(&temp, sg, sizeof(struct scatterlist)); temp.offset = offset; temp.length = length; - crypto_digest_update(conn->data_rx_tfm, &temp, 1); + crypto_digest_update(tcp_conn->data_rx_tfm, &temp, 1); } static void -iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len) +iscsi_recv_digest_update(struct iscsi_tcp_conn *tcp_conn, char* buf, int len) { struct scatterlist tmp; sg_init_one(&tmp, buf, len); - crypto_digest_update(conn->data_rx_tfm, &tmp, 1); + crypto_digest_update(tcp_conn->data_rx_tfm, &tmp, 1); } static int iscsi_scsi_data_in(struct iscsi_conn *conn) { - struct iscsi_cmd_task *ctask = conn->in.ctask; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_cmd_task *ctask = tcp_conn->in.ctask; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct scsi_cmnd *sc = ctask->sc; struct scatterlist *sg; int i, offset, rc = 0; @@ -919,31 +678,33 @@ static int iscsi_scsi_data_in(struct isc */ if (!sc->use_sg) { i = ctask->data_count; - rc = iscsi_ctask_copy(conn, ctask, sc->request_buffer, - sc->request_bufflen, ctask->data_offset); + rc = iscsi_ctask_copy(tcp_conn, ctask, sc->request_buffer, + sc->request_bufflen, + tcp_ctask->data_offset); if (rc == -EAGAIN) return rc; if (conn->datadgst_en) - iscsi_recv_digest_update(conn, sc->request_buffer, i); + iscsi_recv_digest_update(tcp_conn, sc->request_buffer, + i); rc = 0; goto done; } - offset = ctask->data_offset; + offset = tcp_ctask->data_offset; sg = sc->request_buffer; - if (ctask->data_offset) - for (i = 0; i < ctask->sg_count; i++) + if (tcp_ctask->data_offset) + for (i = 0; i < tcp_ctask->sg_count; i++) offset -= sg[i].length; /* we've passed through partial sg*/ if (offset < 0) offset = 0; - for (i = ctask->sg_count; i < sc->use_sg; i++) { + for (i = tcp_ctask->sg_count; i < sc->use_sg; i++) { char *dest; dest = kmap_atomic(sg[i].page, KM_SOFTIRQ0); - rc = iscsi_ctask_copy(conn, ctask, dest + sg[i].offset, + rc = iscsi_ctask_copy(tcp_conn, ctask, dest + sg[i].offset, sg[i].length, offset); kunmap_atomic(dest, KM_SOFTIRQ0); if (rc == -EAGAIN) @@ -952,15 +713,17 @@ static int iscsi_scsi_data_in(struct isc if (!rc) { if (conn->datadgst_en) { if (!offset) - crypto_digest_update(conn->data_rx_tfm, - &sg[i], 1); + crypto_digest_update( + tcp_conn->data_rx_tfm, + &sg[i], 1); else - partial_sg_digest_update(conn, &sg[i], + partial_sg_digest_update(tcp_conn, + &sg[i], sg[i].offset + offset, sg[i].length - offset); } offset = 0; - ctask->sg_count++; + tcp_ctask->sg_count++; } if (!ctask->data_count) { @@ -968,25 +731,26 @@ static int iscsi_scsi_data_in(struct isc /* * data-in is complete, but buffer not... */ - partial_sg_digest_update(conn, &sg[i], + partial_sg_digest_update(tcp_conn, &sg[i], sg[i].offset, sg[i].length-rc); rc = 0; break; } - if (!conn->in.copy) + if (!tcp_conn->in.copy) return -EAGAIN; } BUG_ON(ctask->data_count); done: /* check for non-exceptional status */ - if (conn->in.flags & ISCSI_FLAG_DATA_STATUS) { + if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) { debug_scsi("done [sc %lx res %d itt 0x%x]\n", (long)sc, sc->result, ctask->itt); - conn->scsirsp_pdus_cnt++; - iscsi_ctask_cleanup(conn, ctask); - sc->scsi_done(sc); + spin_lock(&conn->session->lock); + __iscsi_ctask_cleanup(conn, ctask); + __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0); + spin_unlock(&conn->session->lock); } return rc; @@ -995,71 +759,38 @@ done: static int iscsi_data_recv(struct iscsi_conn *conn) { - struct iscsi_session *session = conn->session; - int rc = 0; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + int rc = 0, opcode; - switch(conn->in.opcode) { + opcode = tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK; + switch (opcode) { case ISCSI_OP_SCSI_DATA_IN: rc = iscsi_scsi_data_in(conn); break; - case ISCSI_OP_SCSI_CMD_RSP: { - /* - * SCSI Sense Data: - * copying the entire Data Segment. - */ - if (iscsi_tcp_copy(conn, conn->data, conn->in.datalen)) { - rc = -EAGAIN; - goto exit; - } - - /* - * check for sense - */ - conn->in.hdr = &conn->hdr; - conn->senselen = (conn->data[0] << 8) | conn->data[1]; - rc = iscsi_cmd_rsp(conn, conn->in.ctask); - if (!rc && conn->datadgst_en) - iscsi_recv_digest_update(conn, conn->data, - conn->in.datalen); - } - break; + case ISCSI_OP_SCSI_CMD_RSP: + spin_lock(&conn->session->lock); + __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); + spin_unlock(&conn->session->lock); case ISCSI_OP_TEXT_RSP: case ISCSI_OP_LOGIN_RSP: - case ISCSI_OP_NOOP_IN: { - struct iscsi_mgmt_task *mtask = NULL; - - if (conn->in.itt != ISCSI_RESERVED_TAG) - mtask = (struct iscsi_mgmt_task *) - session->mgmt_cmds[conn->in.itt - - ISCSI_MGMT_ITT_OFFSET]; - + case ISCSI_OP_NOOP_IN: + case ISCSI_OP_ASYNC_EVENT: + case ISCSI_OP_REJECT: /* * Collect data segment to the connection's data * placeholder */ - if (iscsi_tcp_copy(conn, conn->data, conn->in.datalen)) { + if (iscsi_tcp_copy(tcp_conn)) { rc = -EAGAIN; goto exit; } - rc = iscsi_recv_pdu(conn->cls_conn, conn->in.hdr, - conn->data, conn->in.datalen); - - if (!rc && conn->datadgst_en && - conn->in.opcode != ISCSI_OP_LOGIN_RSP) - iscsi_recv_digest_update(conn, conn->data, - conn->in.datalen); - - if (mtask && conn->login_mtask != mtask) { - spin_lock(&session->lock); - __kfifo_put(session->mgmtpool.queue, (void*)&mtask, - sizeof(void*)); - spin_unlock(&session->lock); - } - } - break; - case ISCSI_OP_ASYNC_EVENT: - case ISCSI_OP_REJECT: + rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, tcp_conn->data, + tcp_conn->in.datalen); + if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP) + iscsi_recv_digest_update(tcp_conn, tcp_conn->data, + tcp_conn->in.datalen); + break; default: BUG_ON(1); } @@ -1080,6 +811,7 @@ iscsi_tcp_data_recv(read_descriptor_t *r { int rc; struct iscsi_conn *conn = rd_desc->arg.data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; int processed; char pad[ISCSI_PAD_LEN]; struct scatterlist sg; @@ -1088,15 +820,15 @@ iscsi_tcp_data_recv(read_descriptor_t *r * Save current SKB and its offset in the corresponding * connection context. */ - conn->in.copy = skb->len - offset; - conn->in.offset = offset; - conn->in.skb = skb; - conn->in.len = conn->in.copy; - BUG_ON(conn->in.copy <= 0); - debug_tcp("in %d bytes\n", conn->in.copy); + tcp_conn->in.copy = skb->len - offset; + tcp_conn->in.offset = offset; + tcp_conn->in.skb = skb; + tcp_conn->in.len = tcp_conn->in.copy; + BUG_ON(tcp_conn->in.copy <= 0); + debug_tcp("in %d bytes\n", tcp_conn->in.copy); more: - conn->in.copied = 0; + tcp_conn->in.copied = 0; rc = 0; if (unlikely(conn->suspend_rx)) { @@ -1104,9 +836,9 @@ more: return 0; } - if (conn->in_progress == IN_PROGRESS_WAIT_HEADER || - conn->in_progress == IN_PROGRESS_HEADER_GATHER) { - rc = iscsi_hdr_extract(conn); + if (tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER || + tcp_conn->in_progress == IN_PROGRESS_HEADER_GATHER) { + rc = iscsi_hdr_extract(tcp_conn); if (rc) { if (rc == -EAGAIN) goto nomore; @@ -1119,90 +851,91 @@ more: /* * Verify and process incoming PDU header. */ - rc = iscsi_hdr_recv(conn); - if (!rc && conn->in.datalen) { + rc = iscsi_tcp_hdr_recv(conn); + if (!rc && tcp_conn->in.datalen) { if (conn->datadgst_en) { - BUG_ON(!conn->data_rx_tfm); - crypto_digest_init(conn->data_rx_tfm); + BUG_ON(!tcp_conn->data_rx_tfm); + crypto_digest_init(tcp_conn->data_rx_tfm); } - conn->in_progress = IN_PROGRESS_DATA_RECV; + tcp_conn->in_progress = IN_PROGRESS_DATA_RECV; } else if (rc) { iscsi_conn_failure(conn, rc); return 0; } } - if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { + if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { uint32_t recv_digest; + debug_tcp("extra data_recv offset %d copy %d\n", - conn->in.offset, conn->in.copy); - skb_copy_bits(conn->in.skb, conn->in.offset, + tcp_conn->in.offset, tcp_conn->in.copy); + skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, &recv_digest, 4); - conn->in.offset += 4; - conn->in.copy -= 4; - if (recv_digest != conn->in.datadgst) { + tcp_conn->in.offset += 4; + tcp_conn->in.copy -= 4; + if (recv_digest != tcp_conn->in.datadgst) { debug_tcp("iscsi_tcp: data digest error!" "0x%x != 0x%x\n", recv_digest, - conn->in.datadgst); + tcp_conn->in.datadgst); iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST); return 0; } else { debug_tcp("iscsi_tcp: data digest match!" "0x%x == 0x%x\n", recv_digest, - conn->in.datadgst); - conn->in_progress = IN_PROGRESS_WAIT_HEADER; + tcp_conn->in.datadgst); + tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; } } - if (conn->in_progress == IN_PROGRESS_DATA_RECV && conn->in.copy) { + if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV && + tcp_conn->in.copy) { debug_tcp("data_recv offset %d copy %d\n", - conn->in.offset, conn->in.copy); + tcp_conn->in.offset, tcp_conn->in.copy); rc = iscsi_data_recv(conn); if (rc) { - if (rc == -EAGAIN) { - rd_desc->count = conn->in.datalen - - conn->in.ctask->data_count; + if (rc == -EAGAIN) goto again; - } iscsi_conn_failure(conn, rc); return 0; } - conn->in.copy -= conn->in.padding; - conn->in.offset += conn->in.padding; + tcp_conn->in.copy -= tcp_conn->in.padding; + tcp_conn->in.offset += tcp_conn->in.padding; if (conn->datadgst_en) { - if (conn->in.padding) { - debug_tcp("padding -> %d\n", conn->in.padding); - memset(pad, 0, conn->in.padding); - sg_init_one(&sg, pad, conn->in.padding); - crypto_digest_update(conn->data_rx_tfm, &sg, 1); + if (tcp_conn->in.padding) { + debug_tcp("padding -> %d\n", + tcp_conn->in.padding); + memset(pad, 0, tcp_conn->in.padding); + sg_init_one(&sg, pad, tcp_conn->in.padding); + crypto_digest_update(tcp_conn->data_rx_tfm, + &sg, 1); } - crypto_digest_final(conn->data_rx_tfm, - (u8 *) & conn->in.datadgst); - debug_tcp("rx digest 0x%x\n", conn->in.datadgst); - conn->in_progress = IN_PROGRESS_DDIGEST_RECV; + crypto_digest_final(tcp_conn->data_rx_tfm, + (u8 *) & tcp_conn->in.datadgst); + debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst); + tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV; } else - conn->in_progress = IN_PROGRESS_WAIT_HEADER; + tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; } debug_tcp("f, processed %d from out of %d padding %d\n", - conn->in.offset - offset, (int)len, conn->in.padding); - BUG_ON(conn->in.offset - offset > len); + tcp_conn->in.offset - offset, (int)len, tcp_conn->in.padding); + BUG_ON(tcp_conn->in.offset - offset > len); - if (conn->in.offset - offset != len) { + if (tcp_conn->in.offset - offset != len) { debug_tcp("continue to process %d bytes\n", - (int)len - (conn->in.offset - offset)); + (int)len - (tcp_conn->in.offset - offset)); goto more; } nomore: - processed = conn->in.offset - offset; + processed = tcp_conn->in.offset - offset; BUG_ON(processed == 0); return processed; again: - processed = conn->in.offset - offset; + processed = tcp_conn->in.offset - offset; debug_tcp("c, processed %d from out of %d rd_desc_cnt %d\n", processed, (int)len, (int)rd_desc->count); BUG_ON(processed == 0); @@ -1220,9 +953,14 @@ iscsi_tcp_data_ready(struct sock *sk, in read_lock(&sk->sk_callback_lock); - /* use rd_desc to pass 'conn' to iscsi_tcp_data_recv */ + /* + * Use rd_desc to pass 'conn' to iscsi_tcp_data_recv. + * We set count to 1 because we want the network layer to + * hand us all the skbs that are available. iscsi_tcp_data_recv + * handled pdus that cross buffers or pdus that still need data. + */ rd_desc.arg.data = conn; - rd_desc.count = 0; + rd_desc.count = 1; tcp_read_sock(sk, &rd_desc, iscsi_tcp_data_recv); read_unlock(&sk->sk_callback_lock); @@ -1231,6 +969,7 @@ iscsi_tcp_data_ready(struct sock *sk, in static void iscsi_tcp_state_change(struct sock *sk) { + struct iscsi_tcp_conn *tcp_conn; struct iscsi_conn *conn; struct iscsi_session *session; void (*old_state_change)(struct sock *); @@ -1247,7 +986,8 @@ iscsi_tcp_state_change(struct sock *sk) iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); } - old_state_change = conn->old_state_change; + tcp_conn = conn->dd_data; + old_state_change = tcp_conn->old_state_change; read_unlock(&sk->sk_callback_lock); @@ -1262,23 +1002,25 @@ static void iscsi_write_space(struct sock *sk) { struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data; - conn->old_write_space(sk); + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + + tcp_conn->old_write_space(sk); debug_tcp("iscsi_write_space: cid %d\n", conn->id); - clear_bit(SUSPEND_BIT, &conn->suspend_tx); scsi_queue_work(conn->session->host, &conn->xmitwork); } static void iscsi_conn_set_callbacks(struct iscsi_conn *conn) { - struct sock *sk = conn->sock->sk; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct sock *sk = tcp_conn->sock->sk; /* assign new callbacks */ write_lock_bh(&sk->sk_callback_lock); sk->sk_user_data = conn; - conn->old_data_ready = sk->sk_data_ready; - conn->old_state_change = sk->sk_state_change; - conn->old_write_space = sk->sk_write_space; + tcp_conn->old_data_ready = sk->sk_data_ready; + tcp_conn->old_state_change = sk->sk_state_change; + tcp_conn->old_write_space = sk->sk_write_space; sk->sk_data_ready = iscsi_tcp_data_ready; sk->sk_state_change = iscsi_tcp_state_change; sk->sk_write_space = iscsi_write_space; @@ -1288,14 +1030,15 @@ iscsi_conn_set_callbacks(struct iscsi_co static void iscsi_conn_restore_callbacks(struct iscsi_conn *conn) { - struct sock *sk = conn->sock->sk; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct sock *sk = tcp_conn->sock->sk; /* restore socket callbacks, see also: iscsi_conn_set_callbacks() */ write_lock_bh(&sk->sk_callback_lock); sk->sk_user_data = NULL; - sk->sk_data_ready = conn->old_data_ready; - sk->sk_state_change = conn->old_state_change; - sk->sk_write_space = conn->old_write_space; + sk->sk_data_ready = tcp_conn->old_data_ready; + sk->sk_state_change = tcp_conn->old_state_change; + sk->sk_write_space = tcp_conn->old_write_space; sk->sk_no_check = 0; write_unlock_bh(&sk->sk_callback_lock); } @@ -1310,8 +1053,9 @@ iscsi_conn_restore_callbacks(struct iscs static inline int iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) { - struct socket *sk = conn->sock; - int offset = buf->sg.offset + buf->sent; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct socket *sk = tcp_conn->sock; + int offset = buf->sg.offset + buf->sent, res; /* * if we got use_sg=0 or are sending something we kmallocd @@ -1322,9 +1066,22 @@ iscsi_send(struct iscsi_conn *conn, stru * slab case. */ if (buf->use_sendmsg) - return sock_no_sendpage(sk, buf->sg.page, offset, size, flags); + res = sock_no_sendpage(sk, buf->sg.page, offset, size, flags); + else + res = tcp_conn->sendpage(sk, buf->sg.page, offset, size, flags); + + if (res >= 0) { + conn->txdata_octets += res; + buf->sent += res; + return res; + } + + tcp_conn->sendpage_failures_cnt++; + if (res == -EAGAIN) + res = -ENOBUFS; else - return conn->sendpage(sk, buf->sg.page, offset, size, flags); + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + return res; } /** @@ -1350,16 +1107,10 @@ iscsi_sendhdr(struct iscsi_conn *conn, s res = iscsi_send(conn, buf, size, flags); debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); if (res >= 0) { - conn->txdata_octets += res; - buf->sent += res; if (size != res) return -EAGAIN; return 0; - } else if (res == -EAGAIN) { - conn->sendpage_failures_cnt++; - set_bit(SUSPEND_BIT, &conn->suspend_tx); - } else if (res == -EPIPE) - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + } return res; } @@ -1392,47 +1143,46 @@ iscsi_sendpage(struct iscsi_conn *conn, debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", size, buf->sent, *count, *sent, res); if (res >= 0) { - conn->txdata_octets += res; - buf->sent += res; *count -= res; *sent += res; if (size != res) return -EAGAIN; return 0; - } else if (res == -EAGAIN) { - conn->sendpage_failures_cnt++; - set_bit(SUSPEND_BIT, &conn->suspend_tx); - } else if (res == -EPIPE) - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + } return res; } static inline void -iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn, + struct iscsi_cmd_task *ctask) { - BUG_ON(!conn->data_tx_tfm); - crypto_digest_init(conn->data_tx_tfm); - ctask->digest_count = 4; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + + BUG_ON(!tcp_conn->data_tx_tfm); + crypto_digest_init(tcp_conn->data_tx_tfm); + tcp_ctask->digest_count = 4; } static int iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_buf *buf, uint32_t *digest, int final) { + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; int rc = 0; int sent = 0; if (final) - crypto_digest_final(conn->data_tx_tfm, (u8*)digest); + crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest); - iscsi_buf_init_virt(buf, (char*)digest, 4); - rc = iscsi_sendpage(conn, buf, &ctask->digest_count, &sent); + iscsi_buf_init_iov(buf, (char*)digest, 4); + rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); if (rc) { - ctask->datadigest = *digest; - ctask->xmstate |= XMSTATE_DATA_DIGEST; + tcp_ctask->datadigest = *digest; + tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST; } else - ctask->digest_count = 4; + tcp_ctask->digest_count = 4; return rc; } @@ -1453,21 +1203,19 @@ static void iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, struct iscsi_r2t_info *r2t, int left) { + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data *hdr; - struct iscsi_data_task *dtask; struct scsi_cmnd *sc = ctask->sc; int new_offset; - dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); - BUG_ON(!dtask); - hdr = &dtask->hdr; + hdr = &r2t->dtask.hdr; memset(hdr, 0, sizeof(struct iscsi_data)); hdr->ttt = r2t->ttt; hdr->datasn = cpu_to_be32(r2t->solicit_datasn); r2t->solicit_datasn++; hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; - memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); - hdr->itt = ctask->hdr.itt; + memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); + hdr->itt = ctask->hdr->itt; hdr->exp_statsn = r2t->exp_statsn; new_offset = r2t->data_offset + r2t->sent; hdr->offset = cpu_to_be32(new_offset); @@ -1481,181 +1229,98 @@ iscsi_solicit_data_cont(struct iscsi_con } conn->dataout_pdus_cnt++; - iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr, + iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr, sizeof(struct iscsi_hdr)); - r2t->dtask = dtask; - if (sc->use_sg && !iscsi_buf_left(&r2t->sendbuf)) { - BUG_ON(ctask->bad_sg == r2t->sg); + BUG_ON(tcp_ctask->bad_sg == r2t->sg); iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg); r2t->sg += 1; } else - iscsi_buf_init_iov(&ctask->sendbuf, + iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)sc->request_buffer + new_offset, r2t->data_count); - - list_add(&dtask->item, &ctask->dataqueue); } static void iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_data *hdr; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data_task *dtask; - dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC); - BUG_ON(!dtask); - hdr = &dtask->hdr; - memset(hdr, 0, sizeof(struct iscsi_data)); - hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); - hdr->datasn = cpu_to_be32(ctask->unsol_datasn); - ctask->unsol_datasn++; - hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; - memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); - hdr->itt = ctask->hdr.itt; - hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); - hdr->offset = cpu_to_be32(ctask->total_length - - ctask->r2t_data_count - - ctask->unsol_count); - if (ctask->unsol_count > conn->max_xmit_dlength) { - hton24(hdr->dlength, conn->max_xmit_dlength); - ctask->data_count = conn->max_xmit_dlength; - hdr->flags = 0; - } else { - hton24(hdr->dlength, ctask->unsol_count); - ctask->data_count = ctask->unsol_count; - hdr->flags = ISCSI_FLAG_CMD_FINAL; - } - - iscsi_buf_init_virt(&ctask->headbuf, (char*)hdr, + dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask; + iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr, + tcp_ctask->r2t_data_count); + iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr, sizeof(struct iscsi_hdr)); - - list_add(&dtask->item, &ctask->dataqueue); - - ctask->dtask = dtask; } /** - * iscsi_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands + * iscsi_tcp_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands * @conn: iscsi connection * @ctask: scsi command task * @sc: scsi command **/ static void -iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, - struct scsi_cmnd *sc) +iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) { - struct iscsi_session *session = conn->session; - - BUG_ON(__kfifo_len(ctask->r2tqueue)); - - ctask->sc = sc; - ctask->conn = conn; - ctask->hdr.opcode = ISCSI_OP_SCSI_CMD; - ctask->hdr.flags = ISCSI_ATTR_SIMPLE; - int_to_scsilun(sc->device->lun, (struct scsi_lun *)ctask->hdr.lun); - ctask->hdr.itt = ctask->itt | (conn->id << CID_SHIFT) | - (session->age << AGE_SHIFT); - ctask->hdr.data_length = cpu_to_be32(sc->request_bufflen); - ctask->hdr.cmdsn = cpu_to_be32(session->cmdsn); session->cmdsn++; - ctask->hdr.exp_statsn = cpu_to_be32(conn->exp_statsn); - memcpy(ctask->hdr.cdb, sc->cmnd, sc->cmd_len); - memset(&ctask->hdr.cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len); + struct scsi_cmnd *sc = ctask->sc; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - ctask->mtask = NULL; - ctask->sent = 0; - ctask->sg_count = 0; + BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); - ctask->total_length = sc->request_bufflen; + tcp_ctask->sent = 0; + tcp_ctask->sg_count = 0; if (sc->sc_data_direction == DMA_TO_DEVICE) { - ctask->exp_r2tsn = 0; - ctask->hdr.flags |= ISCSI_FLAG_CMD_WRITE; + tcp_ctask->xmstate = XMSTATE_W_HDR; + tcp_ctask->exp_r2tsn = 0; BUG_ON(ctask->total_length == 0); + if (sc->use_sg) { struct scatterlist *sg = sc->request_buffer; - iscsi_buf_init_sg(&ctask->sendbuf, - &sg[ctask->sg_count++]); - ctask->sg = sg; - ctask->bad_sg = sg + sc->use_sg; - } else { - iscsi_buf_init_iov(&ctask->sendbuf, sc->request_buffer, - sc->request_bufflen); - } + iscsi_buf_init_sg(&tcp_ctask->sendbuf, + &sg[tcp_ctask->sg_count++]); + tcp_ctask->sg = sg; + tcp_ctask->bad_sg = sg + sc->use_sg; + } else + iscsi_buf_init_iov(&tcp_ctask->sendbuf, + sc->request_buffer, + sc->request_bufflen); - /* - * Write counters: - * - * imm_count bytes to be sent right after - * SCSI PDU Header - * - * unsol_count bytes(as Data-Out) to be sent - * without R2T ack right after - * immediate data - * - * r2t_data_count bytes to be sent via R2T ack's - * - * pad_count bytes to be sent as zero-padding - */ - ctask->imm_count = 0; - ctask->unsol_count = 0; - ctask->unsol_datasn = 0; - ctask->xmstate = XMSTATE_W_HDR; - /* calculate write padding */ - ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1); - if (ctask->pad_count) { - ctask->pad_count = ISCSI_PAD_LEN - ctask->pad_count; + if (ctask->imm_count) + tcp_ctask->xmstate |= XMSTATE_IMM_DATA; + + tcp_ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1); + if (tcp_ctask->pad_count) { + tcp_ctask->pad_count = ISCSI_PAD_LEN - + tcp_ctask->pad_count; debug_scsi("write padding %d bytes\n", - ctask->pad_count); - ctask->xmstate |= XMSTATE_W_PAD; + tcp_ctask->pad_count); + tcp_ctask->xmstate |= XMSTATE_W_PAD; } - if (session->imm_data_en) { - if (ctask->total_length >= session->first_burst) - ctask->imm_count = min(session->first_burst, - conn->max_xmit_dlength); - else - ctask->imm_count = min(ctask->total_length, - conn->max_xmit_dlength); - hton24(ctask->hdr.dlength, ctask->imm_count); - ctask->xmstate |= XMSTATE_IMM_DATA; - } else - zero_data(ctask->hdr.dlength); - - if (!session->initial_r2t_en) - ctask->unsol_count = min(session->first_burst, - ctask->total_length) - ctask->imm_count; - if (!ctask->unsol_count) - /* No unsolicit Data-Out's */ - ctask->hdr.flags |= ISCSI_FLAG_CMD_FINAL; - else - ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; - ctask->r2t_data_count = ctask->total_length - + if (ctask->unsol_count) + tcp_ctask->xmstate |= XMSTATE_UNS_HDR | + XMSTATE_UNS_INIT; + tcp_ctask->r2t_data_count = ctask->total_length - ctask->imm_count - ctask->unsol_count; debug_scsi("cmd [itt %x total %d imm %d imm_data %d " "r2t_data %d]\n", ctask->itt, ctask->total_length, ctask->imm_count, - ctask->unsol_count, ctask->r2t_data_count); - } else { - ctask->hdr.flags |= ISCSI_FLAG_CMD_FINAL; - if (sc->sc_data_direction == DMA_FROM_DEVICE) - ctask->hdr.flags |= ISCSI_FLAG_CMD_READ; - ctask->datasn = 0; - ctask->xmstate = XMSTATE_R_HDR; - zero_data(ctask->hdr.dlength); - } + ctask->unsol_count, tcp_ctask->r2t_data_count); + } else + tcp_ctask->xmstate = XMSTATE_R_HDR; - iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, + iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr, sizeof(struct iscsi_hdr)); - conn->scsicmd_pdus_cnt++; } /** - * iscsi_mtask_xmit - xmit management(immediate) task + * iscsi_tcp_mtask_xmit - xmit management(immediate) task * @conn: iscsi connection * @mtask: task management task * @@ -1669,132 +1334,167 @@ iscsi_cmd_init(struct iscsi_conn *conn, * IN_PROGRESS_IMM_DATA - PDU Data xmit in progress **/ static int -iscsi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) +iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) { + struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; + int rc; debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", - conn->id, mtask->xmstate, mtask->itt); + conn->id, tcp_mtask->xmstate, mtask->itt); - if (mtask->xmstate & XMSTATE_IMM_HDR) { - mtask->xmstate &= ~XMSTATE_IMM_HDR; + if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) { + tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR; if (mtask->data_count) - mtask->xmstate |= XMSTATE_IMM_DATA; + tcp_mtask->xmstate |= XMSTATE_IMM_DATA; if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE && - conn->stop_stage != STOP_CONN_RECOVER && + conn->stop_stage != STOP_CONN_RECOVER && conn->hdrdgst_en) - iscsi_hdr_digest(conn, &mtask->headbuf, - (u8*)mtask->hdrext); - if (iscsi_sendhdr(conn, &mtask->headbuf, mtask->data_count)) { - mtask->xmstate |= XMSTATE_IMM_HDR; + iscsi_hdr_digest(conn, &tcp_mtask->headbuf, + (u8*)tcp_mtask->hdrext); + rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, + mtask->data_count); + if (rc) { + tcp_mtask->xmstate |= XMSTATE_IMM_HDR; if (mtask->data_count) - mtask->xmstate &= ~XMSTATE_IMM_DATA; - return -EAGAIN; + tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; + return rc; } } - if (mtask->xmstate & XMSTATE_IMM_DATA) { + if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) { BUG_ON(!mtask->data_count); - mtask->xmstate &= ~XMSTATE_IMM_DATA; + tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; /* FIXME: implement. * Virtual buffer could be spreaded across multiple pages... */ do { - if (iscsi_sendpage(conn, &mtask->sendbuf, - &mtask->data_count, &mtask->sent)) { - mtask->xmstate |= XMSTATE_IMM_DATA; - return -EAGAIN; + int rc; + + rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf, + &mtask->data_count, &tcp_mtask->sent); + if (rc) { + tcp_mtask->xmstate |= XMSTATE_IMM_DATA; + return rc; } } while (mtask->data_count); } - BUG_ON(mtask->xmstate != XMSTATE_IDLE); + BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE); + if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) { + struct iscsi_session *session = conn->session; + + spin_lock_bh(&session->lock); + list_del(&conn->mtask->running); + __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask, + sizeof(void*)); + spin_unlock_bh(&session->lock); + } return 0; } static inline int -handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +handle_xmstate_r_hdr(struct iscsi_conn *conn, + struct iscsi_tcp_cmd_task *tcp_ctask) { - ctask->xmstate &= ~XMSTATE_R_HDR; + int rc; + + tcp_ctask->xmstate &= ~XMSTATE_R_HDR; if (conn->hdrdgst_en) - iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); - if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) { - BUG_ON(ctask->xmstate != XMSTATE_IDLE); + iscsi_hdr_digest(conn, &tcp_ctask->headbuf, + (u8*)tcp_ctask->hdrext); + rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0); + if (!rc) { + BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE); return 0; /* wait for Data-In */ } - ctask->xmstate |= XMSTATE_R_HDR; - return -EAGAIN; + tcp_ctask->xmstate |= XMSTATE_R_HDR; + return rc; } static inline int -handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +handle_xmstate_w_hdr(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask) { - ctask->xmstate &= ~XMSTATE_W_HDR; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + int rc; + + tcp_ctask->xmstate &= ~XMSTATE_W_HDR; if (conn->hdrdgst_en) - iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); - if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) { - ctask->xmstate |= XMSTATE_W_HDR; - return -EAGAIN; - } - return 0; + iscsi_hdr_digest(conn, &tcp_ctask->headbuf, + (u8*)tcp_ctask->hdrext); + rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); + if (rc) + tcp_ctask->xmstate |= XMSTATE_W_HDR; + return rc; } static inline int handle_xmstate_data_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - ctask->xmstate &= ~XMSTATE_DATA_DIGEST; - debug_tcp("resent data digest 0x%x\n", ctask->datadigest); - if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, - &ctask->datadigest, 0)) { - ctask->xmstate |= XMSTATE_DATA_DIGEST; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + int rc; + + tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST; + debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest); + rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, + &tcp_ctask->datadigest, 0); + if (rc) { + tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST; debug_tcp("resent data digest 0x%x fail!\n", - ctask->datadigest); - return -EAGAIN; + tcp_ctask->datadigest); } - return 0; + + return rc; } static inline int handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + int rc; + BUG_ON(!ctask->imm_count); - ctask->xmstate &= ~XMSTATE_IMM_DATA; + tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; if (conn->datadgst_en) { - iscsi_data_digest_init(conn, ctask); - ctask->immdigest = 0; + iscsi_data_digest_init(tcp_conn, ctask); + tcp_ctask->immdigest = 0; } for (;;) { - if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->imm_count, - &ctask->sent)) { - ctask->xmstate |= XMSTATE_IMM_DATA; + rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, + &ctask->imm_count, &tcp_ctask->sent); + if (rc) { + tcp_ctask->xmstate |= XMSTATE_IMM_DATA; if (conn->datadgst_en) { - crypto_digest_final(conn->data_tx_tfm, - (u8*)&ctask->immdigest); + crypto_digest_final(tcp_conn->data_tx_tfm, + (u8*)&tcp_ctask->immdigest); debug_tcp("tx imm sendpage fail 0x%x\n", - ctask->datadigest); + tcp_ctask->datadigest); } - return -EAGAIN; + return rc; } if (conn->datadgst_en) - crypto_digest_update(conn->data_tx_tfm, - &ctask->sendbuf.sg, 1); + crypto_digest_update(tcp_conn->data_tx_tfm, + &tcp_ctask->sendbuf.sg, 1); if (!ctask->imm_count) break; - iscsi_buf_init_sg(&ctask->sendbuf, - &ctask->sg[ctask->sg_count++]); + iscsi_buf_init_sg(&tcp_ctask->sendbuf, + &tcp_ctask->sg[tcp_ctask->sg_count++]); } - if (conn->datadgst_en && !(ctask->xmstate & XMSTATE_W_PAD)) { - if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, - &ctask->immdigest, 1)) { + if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { + rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, + &tcp_ctask->immdigest, 1); + if (rc) { debug_tcp("sending imm digest 0x%x fail!\n", - ctask->immdigest); - return -EAGAIN; + tcp_ctask->immdigest); + return rc; } - debug_tcp("sending imm digest 0x%x\n", ctask->immdigest); + debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest); } return 0; @@ -1803,74 +1503,81 @@ handle_xmstate_imm_data(struct iscsi_con static inline int handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_data_task *dtask; + int rc; - ctask->xmstate |= XMSTATE_UNS_DATA; - if (ctask->xmstate & XMSTATE_UNS_INIT) { + tcp_ctask->xmstate |= XMSTATE_UNS_DATA; + if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { iscsi_unsolicit_data_init(conn, ctask); - BUG_ON(!ctask->dtask); - dtask = ctask->dtask; + dtask = tcp_ctask->dtask; if (conn->hdrdgst_en) - iscsi_hdr_digest(conn, &ctask->headbuf, + iscsi_hdr_digest(conn, &tcp_ctask->headbuf, (u8*)dtask->hdrext); - ctask->xmstate &= ~XMSTATE_UNS_INIT; + tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; } - if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->data_count)) { - ctask->xmstate &= ~XMSTATE_UNS_DATA; - ctask->xmstate |= XMSTATE_UNS_HDR; - return -EAGAIN; + + rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); + if (rc) { + tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; + tcp_ctask->xmstate |= XMSTATE_UNS_HDR; + return rc; } debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n", - ctask->itt, ctask->unsol_count, ctask->sent); + ctask->itt, ctask->unsol_count, tcp_ctask->sent); return 0; } static inline int handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_data_task *dtask = ctask->dtask; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_data_task *dtask = tcp_ctask->dtask; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + int rc; BUG_ON(!ctask->data_count); - ctask->xmstate &= ~XMSTATE_UNS_DATA; + tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; if (conn->datadgst_en) { - iscsi_data_digest_init(conn, ctask); + iscsi_data_digest_init(tcp_conn, ctask); dtask->digest = 0; } for (;;) { - int start = ctask->sent; + int start = tcp_ctask->sent; - if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->data_count, - &ctask->sent)) { - ctask->unsol_count -= ctask->sent - start; - ctask->xmstate |= XMSTATE_UNS_DATA; + rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, + &ctask->data_count, &tcp_ctask->sent); + if (rc) { + ctask->unsol_count -= tcp_ctask->sent - start; + tcp_ctask->xmstate |= XMSTATE_UNS_DATA; /* will continue with this ctask later.. */ if (conn->datadgst_en) { - crypto_digest_final(conn->data_tx_tfm, + crypto_digest_final(tcp_conn->data_tx_tfm, (u8 *)&dtask->digest); debug_tcp("tx uns data fail 0x%x\n", dtask->digest); } - return -EAGAIN; + return rc; } - BUG_ON(ctask->sent > ctask->total_length); - ctask->unsol_count -= ctask->sent - start; + BUG_ON(tcp_ctask->sent > ctask->total_length); + ctask->unsol_count -= tcp_ctask->sent - start; /* * XXX:we may run here with un-initial sendbuf. * so pass it */ - if (conn->datadgst_en && ctask->sent - start > 0) - crypto_digest_update(conn->data_tx_tfm, - &ctask->sendbuf.sg, 1); + if (conn->datadgst_en && tcp_ctask->sent - start > 0) + crypto_digest_update(tcp_conn->data_tx_tfm, + &tcp_ctask->sendbuf.sg, 1); if (!ctask->data_count) break; - iscsi_buf_init_sg(&ctask->sendbuf, - &ctask->sg[ctask->sg_count++]); + iscsi_buf_init_sg(&tcp_ctask->sendbuf, + &tcp_ctask->sg[tcp_ctask->sg_count++]); } BUG_ON(ctask->unsol_count < 0); @@ -1880,27 +1587,29 @@ handle_xmstate_uns_data(struct iscsi_con */ if (ctask->unsol_count) { if (conn->datadgst_en) { - if (iscsi_digest_final_send(conn, ctask, + rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1)) { + &dtask->digest, 1); + if (rc) { debug_tcp("send uns digest 0x%x fail\n", dtask->digest); - return -EAGAIN; + return rc; } debug_tcp("sending uns digest 0x%x, more uns\n", dtask->digest); } - ctask->xmstate |= XMSTATE_UNS_INIT; + tcp_ctask->xmstate |= XMSTATE_UNS_INIT; return 1; } - if (conn->datadgst_en && !(ctask->xmstate & XMSTATE_W_PAD)) { - if (iscsi_digest_final_send(conn, ctask, + if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { + rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1)) { + &dtask->digest, 1); + if (rc) { debug_tcp("send last uns digest 0x%x fail\n", dtask->digest); - return -EAGAIN; + return rc; } debug_tcp("sending uns digest 0x%x\n",dtask->digest); } @@ -1912,15 +1621,17 @@ static inline int handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { struct iscsi_session *session = conn->session; - struct iscsi_r2t_info *r2t = ctask->r2t; - struct iscsi_data_task *dtask = r2t->dtask; - int left; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_r2t_info *r2t = tcp_ctask->r2t; + struct iscsi_data_task *dtask = &r2t->dtask; + int left, rc; - ctask->xmstate &= ~XMSTATE_SOL_DATA; - ctask->dtask = dtask; + tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; + tcp_ctask->dtask = dtask; if (conn->datadgst_en) { - iscsi_data_digest_init(conn, ctask); + iscsi_data_digest_init(tcp_conn, ctask); dtask->digest = 0; } solicit_again: @@ -1930,25 +1641,27 @@ solicit_again: if (!r2t->data_count) goto data_out_done; - if (iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent)) { - ctask->xmstate |= XMSTATE_SOL_DATA; + rc = iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent); + if (rc) { + tcp_ctask->xmstate |= XMSTATE_SOL_DATA; /* will continue with this ctask later.. */ if (conn->datadgst_en) { - crypto_digest_final(conn->data_tx_tfm, + crypto_digest_final(tcp_conn->data_tx_tfm, (u8 *)&dtask->digest); debug_tcp("r2t data send fail 0x%x\n", dtask->digest); } - return -EAGAIN; + return rc; } BUG_ON(r2t->data_count < 0); if (conn->datadgst_en) - crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1); + crypto_digest_update(tcp_conn->data_tx_tfm, &r2t->sendbuf.sg, + 1); if (r2t->data_count) { BUG_ON(ctask->sc->use_sg == 0); if (!iscsi_buf_left(&r2t->sendbuf)) { - BUG_ON(ctask->bad_sg == r2t->sg); + BUG_ON(tcp_ctask->bad_sg == r2t->sg); iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg); r2t->sg += 1; } @@ -1964,19 +1677,20 @@ data_out_done: left = r2t->data_length - r2t->sent; if (left) { if (conn->datadgst_en) { - if (iscsi_digest_final_send(conn, ctask, + rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1)) { + &dtask->digest, 1); + if (rc) { debug_tcp("send r2t data digest 0x%x" "fail\n", dtask->digest); - return -EAGAIN; + return rc; } debug_tcp("r2t data send digest 0x%x\n", dtask->digest); } iscsi_solicit_data_cont(conn, ctask, r2t, left); - ctask->xmstate |= XMSTATE_SOL_DATA; - ctask->xmstate &= ~XMSTATE_SOL_HDR; + tcp_ctask->xmstate |= XMSTATE_SOL_DATA; + tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; return 1; } @@ -1984,26 +1698,27 @@ data_out_done: * Done with this R2T. Check if there are more * outstanding R2Ts ready to be processed. */ - BUG_ON(ctask->r2t_data_count - r2t->data_length < 0); + BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0); if (conn->datadgst_en) { - if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1)) { + rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, + &dtask->digest, 1); + if (rc) { debug_tcp("send last r2t data digest 0x%x" "fail\n", dtask->digest); - return -EAGAIN; + return rc; } debug_tcp("r2t done dout digest 0x%x\n", dtask->digest); } - ctask->r2t_data_count -= r2t->data_length; - ctask->r2t = NULL; + tcp_ctask->r2t_data_count -= r2t->data_length; + tcp_ctask->r2t = NULL; spin_lock_bh(&session->lock); - __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); + __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); spin_unlock_bh(&session->lock); - if (__kfifo_get(ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { - ctask->r2t = r2t; - ctask->xmstate |= XMSTATE_SOL_DATA; - ctask->xmstate &= ~XMSTATE_SOL_HDR; + if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { + tcp_ctask->r2t = r2t; + tcp_ctask->xmstate |= XMSTATE_SOL_DATA; + tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; return 1; } @@ -2013,36 +1728,44 @@ data_out_done: static inline int handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_data_task *dtask = ctask->dtask; - int sent; - - ctask->xmstate &= ~XMSTATE_W_PAD; - iscsi_buf_init_virt(&ctask->sendbuf, (char*)&ctask->pad, - ctask->pad_count); - if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->pad_count, &sent)) { - ctask->xmstate |= XMSTATE_W_PAD; - return -EAGAIN; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_data_task *dtask = tcp_ctask->dtask; + int sent, rc; + + tcp_ctask->xmstate &= ~XMSTATE_W_PAD; + iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, + tcp_ctask->pad_count); + rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, + &sent); + if (rc) { + tcp_ctask->xmstate |= XMSTATE_W_PAD; + return rc; } if (conn->datadgst_en) { - crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1); + crypto_digest_update(tcp_conn->data_tx_tfm, + &tcp_ctask->sendbuf.sg, 1); /* imm data? */ if (!dtask) { - if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, - &ctask->immdigest, 1)) { + rc = iscsi_digest_final_send(conn, ctask, + &tcp_ctask->immbuf, + &tcp_ctask->immdigest, 1); + if (rc) { debug_tcp("send padding digest 0x%x" - "fail!\n", ctask->immdigest); - return -EAGAIN; + "fail!\n", tcp_ctask->immdigest); + return rc; } debug_tcp("done with padding, digest 0x%x\n", - ctask->datadigest); + tcp_ctask->datadigest); } else { - if (iscsi_digest_final_send(conn, ctask, + rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, - &dtask->digest, 1)) { + &dtask->digest, 1); + if (rc) { debug_tcp("send padding digest 0x%x" "fail\n", dtask->digest); - return -EAGAIN; + return rc; } debug_tcp("done with padding, digest 0x%x\n", dtask->digest); @@ -2053,12 +1776,13 @@ handle_xmstate_w_pad(struct iscsi_conn * } static int -iscsi_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; int rc = 0; debug_scsi("ctask deq [cid %d xmstate %x itt 0x%x]\n", - conn->id, ctask->xmstate, ctask->itt); + conn->id, tcp_ctask->xmstate, ctask->itt); /* * serialize with TMF AbortTask @@ -2066,40 +1790,38 @@ iscsi_ctask_xmit(struct iscsi_conn *conn if (ctask->mtask) return rc; - if (ctask->xmstate & XMSTATE_R_HDR) { - rc = handle_xmstate_r_hdr(conn, ctask); - return rc; - } + if (tcp_ctask->xmstate & XMSTATE_R_HDR) + return handle_xmstate_r_hdr(conn, tcp_ctask); - if (ctask->xmstate & XMSTATE_W_HDR) { + if (tcp_ctask->xmstate & XMSTATE_W_HDR) { rc = handle_xmstate_w_hdr(conn, ctask); if (rc) return rc; } /* XXX: for data digest xmit recover */ - if (ctask->xmstate & XMSTATE_DATA_DIGEST) { + if (tcp_ctask->xmstate & XMSTATE_DATA_DIGEST) { rc = handle_xmstate_data_digest(conn, ctask); if (rc) return rc; } - if (ctask->xmstate & XMSTATE_IMM_DATA) { + if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { rc = handle_xmstate_imm_data(conn, ctask); if (rc) return rc; } - if (ctask->xmstate & XMSTATE_UNS_HDR) { + if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) { BUG_ON(!ctask->unsol_count); - ctask->xmstate &= ~XMSTATE_UNS_HDR; + tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; unsolicit_head_again: rc = handle_xmstate_uns_hdr(conn, ctask); if (rc) return rc; } - if (ctask->xmstate & XMSTATE_UNS_DATA) { + if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) { rc = handle_xmstate_uns_data(conn, ctask); if (rc == 1) goto unsolicit_head_again; @@ -2108,23 +1830,24 @@ unsolicit_head_again: goto done; } - if (ctask->xmstate & XMSTATE_SOL_HDR) { + if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { struct iscsi_r2t_info *r2t; - ctask->xmstate &= ~XMSTATE_SOL_HDR; - ctask->xmstate |= XMSTATE_SOL_DATA; - if (!ctask->r2t) - __kfifo_get(ctask->r2tqueue, (void*)&ctask->r2t, + tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; + tcp_ctask->xmstate |= XMSTATE_SOL_DATA; + if (!tcp_ctask->r2t) + __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, sizeof(void*)); solicit_head_again: - r2t = ctask->r2t; + r2t = tcp_ctask->r2t; if (conn->hdrdgst_en) iscsi_hdr_digest(conn, &r2t->headbuf, - (u8*)r2t->dtask->hdrext); - if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { - ctask->xmstate &= ~XMSTATE_SOL_DATA; - ctask->xmstate |= XMSTATE_SOL_HDR; - return -EAGAIN; + (u8*)r2t->dtask.hdrext); + rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); + if (rc) { + tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; + tcp_ctask->xmstate |= XMSTATE_SOL_HDR; + return rc; } debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n", @@ -2132,7 +1855,7 @@ solicit_head_again: r2t->sent); } - if (ctask->xmstate & XMSTATE_SOL_DATA) { + if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) { rc = handle_xmstate_sol_data(conn, ctask); if (rc == 1) goto solicit_head_again; @@ -2145,1022 +1868,199 @@ done: * Last thing to check is whether we need to send write * padding. Note that we check for xmstate equality, not just the bit. */ - if (ctask->xmstate == XMSTATE_W_PAD) + if (tcp_ctask->xmstate == XMSTATE_W_PAD) rc = handle_xmstate_w_pad(conn, ctask); return rc; } -/** - * iscsi_data_xmit - xmit any command into the scheduled connection - * @conn: iscsi connection - * - * Notes: - * The function can return -EAGAIN in which case the caller must - * re-schedule it again later or recover. '0' return code means - * successful xmit. - **/ -static int -iscsi_data_xmit(struct iscsi_conn *conn) -{ - if (unlikely(conn->suspend_tx)) { - debug_tcp("conn %d Tx suspended!\n", conn->id); - return 0; - } - - /* - * Transmit in the following order: - * - * 1) un-finished xmit (ctask or mtask) - * 2) immediate control PDUs - * 3) write data - * 4) SCSI commands - * 5) non-immediate control PDUs - * - * No need to lock around __kfifo_get as long as - * there's one producer and one consumer. - */ - - BUG_ON(conn->ctask && conn->mtask); - - if (conn->ctask) { - if (iscsi_ctask_xmit(conn, conn->ctask)) - goto again; - /* done with this in-progress ctask */ - conn->ctask = NULL; - } - if (conn->mtask) { - if (iscsi_mtask_xmit(conn, conn->mtask)) - goto again; - /* done with this in-progress mtask */ - conn->mtask = NULL; - } - - /* process immediate first */ - if (unlikely(__kfifo_len(conn->immqueue))) { - struct iscsi_session *session = conn->session; - while (__kfifo_get(conn->immqueue, (void*)&conn->mtask, - sizeof(void*))) { - if (iscsi_mtask_xmit(conn, conn->mtask)) - goto again; - - if (conn->mtask->hdr.itt == - cpu_to_be32(ISCSI_RESERVED_TAG)) { - spin_lock_bh(&session->lock); - __kfifo_put(session->mgmtpool.queue, - (void*)&conn->mtask, sizeof(void*)); - spin_unlock_bh(&session->lock); - } - } - /* done with this mtask */ - conn->mtask = NULL; - } - - /* process write queue */ - while (__kfifo_get(conn->writequeue, (void*)&conn->ctask, - sizeof(void*))) { - if (iscsi_ctask_xmit(conn, conn->ctask)) - goto again; - } - - /* process command queue */ - while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask, - sizeof(void*))) { - if (iscsi_ctask_xmit(conn, conn->ctask)) - goto again; - } - /* done with this ctask */ - conn->ctask = NULL; - - /* process the rest control plane PDUs, if any */ - if (unlikely(__kfifo_len(conn->mgmtqueue))) { - struct iscsi_session *session = conn->session; - - while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask, - sizeof(void*))) { - if (iscsi_mtask_xmit(conn, conn->mtask)) - goto again; - - if (conn->mtask->hdr.itt == - cpu_to_be32(ISCSI_RESERVED_TAG)) { - spin_lock_bh(&session->lock); - __kfifo_put(session->mgmtpool.queue, - (void*)&conn->mtask, - sizeof(void*)); - spin_unlock_bh(&session->lock); - } - } - /* done with this mtask */ - conn->mtask = NULL; - } - - return 0; - -again: - if (unlikely(conn->suspend_tx)) - return 0; - - return -EAGAIN; -} - -static void -iscsi_xmitworker(void *data) -{ - struct iscsi_conn *conn = data; - - /* - * serialize Xmit worker on a per-connection basis. - */ - mutex_lock(&conn->xmitmutex); - if (iscsi_data_xmit(conn)) - scsi_queue_work(conn->session->host, &conn->xmitwork); - mutex_unlock(&conn->xmitmutex); -} - -#define FAILURE_BAD_HOST 1 -#define FAILURE_SESSION_FAILED 2 -#define FAILURE_SESSION_FREED 3 -#define FAILURE_WINDOW_CLOSED 4 -#define FAILURE_SESSION_TERMINATE 5 - -static int -iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) -{ - struct Scsi_Host *host; - int reason = 0; - struct iscsi_session *session; - struct iscsi_conn *conn = NULL; - struct iscsi_cmd_task *ctask = NULL; - - sc->scsi_done = done; - sc->result = 0; - - host = sc->device->host; - session = iscsi_hostdata(host->hostdata); - BUG_ON(host != session->host); - - spin_lock(&session->lock); - - if (session->state != ISCSI_STATE_LOGGED_IN) { - if (session->state == ISCSI_STATE_FAILED) { - reason = FAILURE_SESSION_FAILED; - goto reject; - } else if (session->state == ISCSI_STATE_TERMINATE) { - reason = FAILURE_SESSION_TERMINATE; - goto fault; - } - reason = FAILURE_SESSION_FREED; - goto fault; - } - - /* - * Check for iSCSI window and take care of CmdSN wrap-around - */ - if ((int)(session->max_cmdsn - session->cmdsn) < 0) { - reason = FAILURE_WINDOW_CLOSED; - goto reject; - } - - conn = session->leadconn; - - __kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); - BUG_ON(ctask->sc); - - sc->SCp.phase = session->age; - sc->SCp.ptr = (char*)ctask; - iscsi_cmd_init(conn, ctask, sc); - - __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); - debug_scsi( - "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", - sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", - conn->id, (long)sc, ctask->itt, sc->request_bufflen, - session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); - spin_unlock(&session->lock); - - scsi_queue_work(host, &conn->xmitwork); - return 0; - -reject: - spin_unlock(&session->lock); - debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason); - return SCSI_MLQUEUE_HOST_BUSY; - -fault: - spin_unlock(&session->lock); - printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n", - sc->cmnd[0], reason); - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = NOT_READY; - sc->sense_buffer[7] = 0x6; - sc->sense_buffer[12] = 0x08; - sc->sense_buffer[13] = 0x00; - sc->result = (DID_NO_CONNECT << 16); - sc->resid = sc->request_bufflen; - sc->scsi_done(sc); - return 0; -} - -static int -iscsi_change_queue_depth(struct scsi_device *sdev, int depth) -{ - if (depth > ISCSI_MAX_CMD_PER_LUN) - depth = ISCSI_MAX_CMD_PER_LUN; - scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); - return sdev->queue_depth; -} - -static int -iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) -{ - int i; - - *items = kmalloc(max * sizeof(void*), GFP_KERNEL); - if (*items == NULL) - return -ENOMEM; - - q->max = max; - q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL); - if (q->pool == NULL) { - kfree(*items); - return -ENOMEM; - } - - q->queue = kfifo_init((void*)q->pool, max * sizeof(void*), - GFP_KERNEL, NULL); - if (q->queue == ERR_PTR(-ENOMEM)) { - kfree(q->pool); - kfree(*items); - return -ENOMEM; - } - - for (i = 0; i < max; i++) { - q->pool[i] = kmalloc(item_size, GFP_KERNEL); - if (q->pool[i] == NULL) { - int j; - - for (j = 0; j < i; j++) - kfree(q->pool[j]); - - kfifo_free(q->queue); - kfree(q->pool); - kfree(*items); - return -ENOMEM; - } - memset(q->pool[i], 0, item_size); - (*items)[i] = q->pool[i]; - __kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*)); - } - return 0; -} - -static void -iscsi_pool_free(struct iscsi_queue *q, void **items) -{ - int i; - - for (i = 0; i < q->max; i++) - kfree(items[i]); - kfree(q->pool); - kfree(items); -} - static struct iscsi_cls_conn * -iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) +iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) { - struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); - struct iscsi_session *session = iscsi_hostdata(shost->hostdata); struct iscsi_conn *conn; struct iscsi_cls_conn *cls_conn; + struct iscsi_tcp_conn *tcp_conn; - cls_conn = iscsi_create_conn(cls_session, conn_idx); + cls_conn = iscsi_conn_setup(cls_session, conn_idx); if (!cls_conn) return NULL; conn = cls_conn->dd_data; - memset(conn, 0, sizeof(*conn)); - - conn->cls_conn = cls_conn; - conn->c_stage = ISCSI_CONN_INITIAL_STAGE; - conn->in_progress = IN_PROGRESS_WAIT_HEADER; - conn->id = conn_idx; - conn->exp_statsn = 0; - conn->tmabort_state = TMABORT_INITIAL; - - /* initial operational parameters */ - conn->hdr_size = sizeof(struct iscsi_hdr); - conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; + /* + * due to strange issues with iser these are not set + * in iscsi_conn_setup + */ conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; - /* initialize general xmit PDU commands queue */ - conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*), - GFP_KERNEL, NULL); - if (conn->xmitqueue == ERR_PTR(-ENOMEM)) - goto xmitqueue_alloc_fail; - - /* initialize write response PDU commands queue */ - conn->writequeue = kfifo_alloc(session->cmds_max * sizeof(void*), - GFP_KERNEL, NULL); - if (conn->writequeue == ERR_PTR(-ENOMEM)) - goto writequeue_alloc_fail; - - /* initialize general immediate & non-immediate PDU commands queue */ - conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), - GFP_KERNEL, NULL); - if (conn->immqueue == ERR_PTR(-ENOMEM)) - goto immqueue_alloc_fail; + tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL); + if (!tcp_conn) + goto tcp_conn_alloc_fail; - conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), - GFP_KERNEL, NULL); - if (conn->mgmtqueue == ERR_PTR(-ENOMEM)) - goto mgmtqueue_alloc_fail; - - INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn); - - /* allocate login_mtask used for the login/text sequences */ - spin_lock_bh(&session->lock); - if (!__kfifo_get(session->mgmtpool.queue, - (void*)&conn->login_mtask, - sizeof(void*))) { - spin_unlock_bh(&session->lock); - goto login_mtask_alloc_fail; - } - spin_unlock_bh(&session->lock); + conn->dd_data = tcp_conn; + tcp_conn->iscsi_conn = conn; + tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; + /* initial operational parameters */ + tcp_conn->hdr_size = sizeof(struct iscsi_hdr); + tcp_conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; /* allocate initial PDU receive place holder */ - if (conn->data_size <= PAGE_SIZE) - conn->data = kmalloc(conn->data_size, GFP_KERNEL); + if (tcp_conn->data_size <= PAGE_SIZE) + tcp_conn->data = kmalloc(tcp_conn->data_size, GFP_KERNEL); else - conn->data = (void*)__get_free_pages(GFP_KERNEL, - get_order(conn->data_size)); - if (!conn->data) + tcp_conn->data = (void*)__get_free_pages(GFP_KERNEL, + get_order(tcp_conn->data_size)); + if (!tcp_conn->data) goto max_recv_dlenght_alloc_fail; - init_timer(&conn->tmabort_timer); - mutex_init(&conn->xmitmutex); - init_waitqueue_head(&conn->ehwait); - return cls_conn; max_recv_dlenght_alloc_fail: - spin_lock_bh(&session->lock); - __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, - sizeof(void*)); - spin_unlock_bh(&session->lock); -login_mtask_alloc_fail: - kfifo_free(conn->mgmtqueue); -mgmtqueue_alloc_fail: - kfifo_free(conn->immqueue); -immqueue_alloc_fail: - kfifo_free(conn->writequeue); -writequeue_alloc_fail: - kfifo_free(conn->xmitqueue); -xmitqueue_alloc_fail: - iscsi_destroy_conn(cls_conn); + kfree(tcp_conn); +tcp_conn_alloc_fail: + iscsi_conn_teardown(cls_conn); return NULL; } static void -iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn) +iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) { struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_session *session = conn->session; - unsigned long flags; - - mutex_lock(&conn->xmitmutex); - set_bit(SUSPEND_BIT, &conn->suspend_tx); - if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) { - struct sock *sk = conn->sock->sk; - - /* - * conn_start() has never been called! - * need to cleanup the socket. - */ - write_lock_bh(&sk->sk_callback_lock); - set_bit(SUSPEND_BIT, &conn->suspend_rx); - write_unlock_bh(&sk->sk_callback_lock); - - sock_hold(conn->sock->sk); - iscsi_conn_restore_callbacks(conn); - sock_put(conn->sock->sk); - sock_release(conn->sock); - conn->sock = NULL; - } + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + int digest = 0; - spin_lock_bh(&session->lock); - conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; - if (session->leadconn == conn) { - /* - * leading connection? then give up on recovery. - */ - session->state = ISCSI_STATE_TERMINATE; - wake_up(&conn->ehwait); - } - spin_unlock_bh(&session->lock); + if (conn->hdrdgst_en || conn->datadgst_en) + digest = 1; - mutex_unlock(&conn->xmitmutex); - - /* - * Block until all in-progress commands for this connection - * time out or fail. - */ - for (;;) { - spin_lock_irqsave(session->host->host_lock, flags); - if (!session->host->host_busy) { /* OK for ERL == 0 */ - spin_unlock_irqrestore(session->host->host_lock, flags); - break; - } - spin_unlock_irqrestore(session->host->host_lock, flags); - msleep_interruptible(500); - printk("conn_destroy(): host_busy %d host_failed %d\n", - session->host->host_busy, session->host->host_failed); - /* - * force eh_abort() to unblock - */ - wake_up(&conn->ehwait); - } + iscsi_conn_teardown(cls_conn); - /* now free crypto */ - if (conn->hdrdgst_en || conn->datadgst_en) { - if (conn->tx_tfm) - crypto_free_tfm(conn->tx_tfm); - if (conn->rx_tfm) - crypto_free_tfm(conn->rx_tfm); - if (conn->data_tx_tfm) - crypto_free_tfm(conn->data_tx_tfm); - if (conn->data_rx_tfm) - crypto_free_tfm(conn->data_rx_tfm); + /* now free tcp_conn */ + if (digest) { + if (tcp_conn->tx_tfm) + crypto_free_tfm(tcp_conn->tx_tfm); + if (tcp_conn->rx_tfm) + crypto_free_tfm(tcp_conn->rx_tfm); + if (tcp_conn->data_tx_tfm) + crypto_free_tfm(tcp_conn->data_tx_tfm); + if (tcp_conn->data_rx_tfm) + crypto_free_tfm(tcp_conn->data_rx_tfm); } /* free conn->data, size = MaxRecvDataSegmentLength */ - if (conn->data_size <= PAGE_SIZE) - kfree(conn->data); + if (tcp_conn->data_size <= PAGE_SIZE) + kfree(tcp_conn->data); else - free_pages((unsigned long)conn->data, - get_order(conn->data_size)); - - spin_lock_bh(&session->lock); - __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, - sizeof(void*)); - list_del(&conn->item); - if (list_empty(&session->connections)) - session->leadconn = NULL; - if (session->leadconn && session->leadconn == conn) - session->leadconn = container_of(session->connections.next, - struct iscsi_conn, item); - - if (session->leadconn == NULL) - /* none connections exits.. reset sequencing */ - session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; - spin_unlock_bh(&session->lock); - - kfifo_free(conn->xmitqueue); - kfifo_free(conn->writequeue); - kfifo_free(conn->immqueue); - kfifo_free(conn->mgmtqueue); - - iscsi_destroy_conn(cls_conn); + free_pages((unsigned long)tcp_conn->data, + get_order(tcp_conn->data_size)); + kfree(tcp_conn); } static int -iscsi_conn_bind(struct iscsi_cls_session *cls_session, - struct iscsi_cls_conn *cls_conn, uint32_t transport_fd, - int is_leading) +iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, + struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, + int is_leading) { - struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); - struct iscsi_session *session = iscsi_hostdata(shost->hostdata); - struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data; + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct sock *sk; struct socket *sock; int err; /* lookup for existing socket */ - sock = sockfd_lookup(transport_fd, &err); + sock = sockfd_lookup((int)transport_eph, &err); if (!sock) { printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err); return -EEXIST; } - /* lookup for existing connection */ - spin_lock_bh(&session->lock); - list_for_each_entry(tmp, &session->connections, item) { - if (tmp == conn) { - if (conn->c_stage != ISCSI_CONN_STOPPED || - conn->stop_stage == STOP_CONN_TERM) { - printk(KERN_ERR "iscsi_tcp: can't bind " - "non-stopped connection (%d:%d)\n", - conn->c_stage, conn->stop_stage); - spin_unlock_bh(&session->lock); - return -EIO; - } - break; - } - } - if (tmp != conn) { - /* bind new iSCSI connection to session */ - conn->session = session; + err = iscsi_conn_bind(cls_session, cls_conn, is_leading); + if (err) + return err; - list_add(&conn->item, &session->connections); - } - spin_unlock_bh(&session->lock); - - if (conn->stop_stage != STOP_CONN_SUSPEND) { - /* bind iSCSI connection and socket */ - conn->sock = sock; - - /* setup Socket parameters */ - sk = sock->sk; - sk->sk_reuse = 1; - sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */ - sk->sk_allocation = GFP_ATOMIC; + /* bind iSCSI connection and socket */ + tcp_conn->sock = sock; - /* FIXME: disable Nagle's algorithm */ + /* setup Socket parameters */ + sk = sock->sk; + sk->sk_reuse = 1; + sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */ + sk->sk_allocation = GFP_ATOMIC; - /* - * Intercept TCP callbacks for sendfile like receive - * processing. - */ - iscsi_conn_set_callbacks(conn); - - conn->sendpage = conn->sock->ops->sendpage; - - /* - * set receive state machine into initial state - */ - conn->in_progress = IN_PROGRESS_WAIT_HEADER; - } - - if (is_leading) - session->leadconn = conn; + /* FIXME: disable Nagle's algorithm */ /* - * Unblock xmitworker(), Login Phase will pass through. + * Intercept TCP callbacks for sendfile like receive + * processing. */ - clear_bit(SUSPEND_BIT, &conn->suspend_rx); - clear_bit(SUSPEND_BIT, &conn->suspend_tx); + conn->recv_lock = &sk->sk_callback_lock; + iscsi_conn_set_callbacks(conn); + tcp_conn->sendpage = tcp_conn->sock->ops->sendpage; + /* + * set receive state machine into initial state + */ + tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; return 0; } -static int -iscsi_conn_start(struct iscsi_cls_conn *cls_conn) +static void +iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { - struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_session *session = conn->session; - struct sock *sk; - - /* FF phase warming up... */ - - if (session == NULL) { - printk(KERN_ERR "iscsi_tcp: can't start unbound connection\n"); - return -EPERM; - } - - sk = conn->sock->sk; - - write_lock_bh(&sk->sk_callback_lock); - spin_lock_bh(&session->lock); - conn->c_stage = ISCSI_CONN_STARTED; - session->state = ISCSI_STATE_LOGGED_IN; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_r2t_info *r2t; - switch(conn->stop_stage) { - case STOP_CONN_RECOVER: - /* - * unblock eh_abort() if it is blocked. re-try all - * commands after successful recovery - */ - session->conn_cnt++; - conn->stop_stage = 0; - conn->tmabort_state = TMABORT_INITIAL; - session->age++; - wake_up(&conn->ehwait); - break; - case STOP_CONN_TERM: - session->conn_cnt++; - conn->stop_stage = 0; - break; - case STOP_CONN_SUSPEND: - conn->stop_stage = 0; - clear_bit(SUSPEND_BIT, &conn->suspend_rx); - clear_bit(SUSPEND_BIT, &conn->suspend_tx); - break; - default: - break; - } - spin_unlock_bh(&session->lock); - write_unlock_bh(&sk->sk_callback_lock); + /* flush ctask's r2t queues */ + while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) + __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, + sizeof(void*)); - return 0; + __iscsi_ctask_cleanup(conn, ctask); } static void -iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) +iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn) { - struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_session *session = conn->session; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct sock *sk; - unsigned long flags; - BUG_ON(!conn->sock); - sk = conn->sock->sk; + if (!tcp_conn->sock) + return; + + sk = tcp_conn->sock->sk; write_lock_bh(&sk->sk_callback_lock); - set_bit(SUSPEND_BIT, &conn->suspend_rx); + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); write_unlock_bh(&sk->sk_callback_lock); - - mutex_lock(&conn->xmitmutex); - - spin_lock_irqsave(session->host->host_lock, flags); - spin_lock(&session->lock); - conn->stop_stage = flag; - conn->c_stage = ISCSI_CONN_STOPPED; - set_bit(SUSPEND_BIT, &conn->suspend_tx); - - if (flag != STOP_CONN_SUSPEND) - session->conn_cnt--; - - if (session->conn_cnt == 0 || session->leadconn == conn) - session->state = ISCSI_STATE_FAILED; - - spin_unlock(&session->lock); - spin_unlock_irqrestore(session->host->host_lock, flags); - - if (flag == STOP_CONN_TERM || flag == STOP_CONN_RECOVER) { - struct iscsi_cmd_task *ctask; - struct iscsi_mgmt_task *mtask; - - /* - * Socket must go now. - */ - sock_hold(conn->sock->sk); - iscsi_conn_restore_callbacks(conn); - sock_put(conn->sock->sk); - - /* - * flush xmit queues. - */ - spin_lock_bh(&session->lock); - while (__kfifo_get(conn->writequeue, (void*)&ctask, - sizeof(void*)) || - __kfifo_get(conn->xmitqueue, (void*)&ctask, - sizeof(void*))) { - struct iscsi_r2t_info *r2t; - - /* - * flush ctask's r2t queues - */ - while (__kfifo_get(ctask->r2tqueue, (void*)&r2t, - sizeof(void*))) - __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, - sizeof(void*)); - - spin_unlock_bh(&session->lock); - local_bh_disable(); - iscsi_ctask_cleanup(conn, ctask); - local_bh_enable(); - spin_lock_bh(&session->lock); - } - conn->ctask = NULL; - while (__kfifo_get(conn->immqueue, (void*)&mtask, - sizeof(void*)) || - __kfifo_get(conn->mgmtqueue, (void*)&mtask, - sizeof(void*))) { - __kfifo_put(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*)); - } - conn->mtask = NULL; - spin_unlock_bh(&session->lock); - - /* - * release socket only after we stopped data_xmit() - * activity and flushed all outstandings - */ - sock_release(conn->sock); - conn->sock = NULL; - - /* - * for connection level recovery we should not calculate - * header digest. conn->hdr_size used for optimization - * in hdr_extract() and will be re-negotiated at - * set_param() time. - */ - if (flag == STOP_CONN_RECOVER) { - conn->hdr_size = sizeof(struct iscsi_hdr); - conn->hdrdgst_en = 0; - conn->datadgst_en = 0; - } - } - mutex_unlock(&conn->xmitmutex); -} - -static int -iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, - char *data, uint32_t data_size) -{ - struct iscsi_session *session = conn->session; - struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; - struct iscsi_mgmt_task *mtask; - - spin_lock_bh(&session->lock); - if (session->state == ISCSI_STATE_TERMINATE) { - spin_unlock_bh(&session->lock); - return -EPERM; - } - if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) || - hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) - /* - * Login and Text are sent serially, in - * request-followed-by-response sequence. - * Same mtask can be used. Same ITT must be used. - * Note that login_mtask is preallocated at conn_create(). - */ - mtask = conn->login_mtask; - else { - BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); - BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); - - if (!__kfifo_get(session->mgmtpool.queue, - (void*)&mtask, sizeof(void*))) { - spin_unlock_bh(&session->lock); - return -ENOSPC; - } - } - - /* - * pre-format CmdSN and ExpStatSN for outgoing PDU. - */ - if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { - hdr->itt = mtask->itt | (conn->id << CID_SHIFT) | - (session->age << AGE_SHIFT); - nop->cmdsn = cpu_to_be32(session->cmdsn); - if (conn->c_stage == ISCSI_CONN_STARTED && - !(hdr->opcode & ISCSI_OP_IMMEDIATE)) - session->cmdsn++; - } else - /* do not advance CmdSN */ - nop->cmdsn = cpu_to_be32(session->cmdsn); - - nop->exp_statsn = cpu_to_be32(conn->exp_statsn); - - memcpy(&mtask->hdr, hdr, sizeof(struct iscsi_hdr)); - - iscsi_buf_init_virt(&mtask->headbuf, (char*)&mtask->hdr, - sizeof(struct iscsi_hdr)); - - spin_unlock_bh(&session->lock); - - if (data_size) { - memcpy(mtask->data, data, data_size); - mtask->data_count = data_size; - } else - mtask->data_count = 0; - - mtask->xmstate = XMSTATE_IMM_HDR; - - if (mtask->data_count) { - iscsi_buf_init_iov(&mtask->sendbuf, (char*)mtask->data, - mtask->data_count); - } - - debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", - hdr->opcode, hdr->itt, data_size); - - /* - * since send_pdu() could be called at least from two contexts, - * we need to serialize __kfifo_put, so we don't have to take - * additional lock on fast data-path - */ - if (hdr->opcode & ISCSI_OP_IMMEDIATE) - __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*)); - else - __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); - - scsi_queue_work(session->host, &conn->xmitwork); - return 0; } -static int -iscsi_eh_host_reset(struct scsi_cmnd *sc) +static void +iscsi_tcp_terminate_conn(struct iscsi_conn *conn) { - struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; - struct iscsi_conn *conn = ctask->conn; - struct iscsi_session *session = conn->session; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - spin_lock_bh(&session->lock); - if (session->state == ISCSI_STATE_TERMINATE) { - debug_scsi("failing host reset: session terminated " - "[CID %d age %d]", conn->id, session->age); - spin_unlock_bh(&session->lock); - return FAILED; - } - spin_unlock_bh(&session->lock); + if (!tcp_conn->sock) + return; - debug_scsi("failing connection CID %d due to SCSI host reset " - "[itt 0x%x age %d]", conn->id, ctask->itt, - session->age); - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + sock_hold(tcp_conn->sock->sk); + iscsi_conn_restore_callbacks(conn); + sock_put(tcp_conn->sock->sk); - return SUCCESS; + sock_release(tcp_conn->sock); + tcp_conn->sock = NULL; + conn->recv_lock = NULL; } +/* called with host lock */ static void -iscsi_tmabort_timedout(unsigned long data) -{ - struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data; - struct iscsi_conn *conn = ctask->conn; - struct iscsi_session *session = conn->session; - - spin_lock(&session->lock); - if (conn->tmabort_state == TMABORT_INITIAL) { - __kfifo_put(session->mgmtpool.queue, - (void*)&ctask->mtask, sizeof(void*)); - conn->tmabort_state = TMABORT_TIMEDOUT; - debug_scsi("tmabort timedout [sc %lx itt 0x%x]\n", - (long)ctask->sc, ctask->itt); - /* unblock eh_abort() */ - wake_up(&conn->ehwait); - } - spin_unlock(&session->lock); -} - -static int -iscsi_eh_abort(struct scsi_cmnd *sc) +iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, + char *data, uint32_t data_size) { - int rc; - struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; - struct iscsi_conn *conn = ctask->conn; - struct iscsi_session *session = conn->session; - - conn->eh_abort_cnt++; - debug_scsi("aborting [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); - - /* - * two cases for ERL=0 here: - * - * 1) connection-level failure; - * 2) recovery due protocol error; - */ - mutex_lock(&conn->xmitmutex); - spin_lock_bh(&session->lock); - if (session->state != ISCSI_STATE_LOGGED_IN) { - if (session->state == ISCSI_STATE_TERMINATE) { - spin_unlock_bh(&session->lock); - mutex_unlock(&conn->xmitmutex); - goto failed; - } - spin_unlock_bh(&session->lock); - } else { - struct iscsi_tm *hdr = &conn->tmhdr; - - /* - * Still LOGGED_IN... - */ - - if (!ctask->sc || sc->SCp.phase != session->age) { - /* - * 1) ctask completed before time out. But session - * is still ok => Happy Retry. - * 2) session was re-open during time out of ctask. - */ - spin_unlock_bh(&session->lock); - mutex_unlock(&conn->xmitmutex); - goto success; - } - conn->tmabort_state = TMABORT_INITIAL; - spin_unlock_bh(&session->lock); - - /* - * ctask timed out but session is OK - * ERL=0 requires task mgmt abort to be issued on each - * failed command. requests must be serialized. - */ - memset(hdr, 0, sizeof(struct iscsi_tm)); - hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; - hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; - hdr->flags |= ISCSI_FLAG_CMD_FINAL; - memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun)); - hdr->rtt = ctask->hdr.itt; - hdr->refcmdsn = ctask->hdr.cmdsn; - - rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr, - NULL, 0); - if (rc) { - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - debug_scsi("abort sent failure [itt 0x%x]", ctask->itt); - } else { - struct iscsi_r2t_info *r2t; - - /* - * TMF abort vs. TMF response race logic - */ - spin_lock_bh(&session->lock); - ctask->mtask = (struct iscsi_mgmt_task *) - session->mgmt_cmds[(hdr->itt & ITT_MASK) - - ISCSI_MGMT_ITT_OFFSET]; - /* - * have to flush r2tqueue to avoid r2t leaks - */ - while (__kfifo_get(ctask->r2tqueue, (void*)&r2t, - sizeof(void*))) { - __kfifo_put(ctask->r2tpool.queue, (void*)&r2t, - sizeof(void*)); - } - if (conn->tmabort_state == TMABORT_INITIAL) { - conn->tmfcmd_pdus_cnt++; - conn->tmabort_timer.expires = 3*HZ + jiffies; - conn->tmabort_timer.function = - iscsi_tmabort_timedout; - conn->tmabort_timer.data = (unsigned long)ctask; - add_timer(&conn->tmabort_timer); - debug_scsi("abort sent [itt 0x%x]", ctask->itt); - } else { - if (!ctask->sc || - conn->tmabort_state == TMABORT_SUCCESS) { - conn->tmabort_state = TMABORT_INITIAL; - spin_unlock_bh(&session->lock); - mutex_unlock(&conn->xmitmutex); - goto success; - } - conn->tmabort_state = TMABORT_INITIAL; - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - } - spin_unlock_bh(&session->lock); - } - } - mutex_unlock(&conn->xmitmutex); - - - /* - * block eh thread until: - * - * 1) abort response; - * 2) abort timeout; - * 3) session re-opened; - * 4) session terminated; - */ - for (;;) { - int p_state = session->state; - - rc = wait_event_interruptible(conn->ehwait, - (p_state == ISCSI_STATE_LOGGED_IN ? - (session->state == ISCSI_STATE_TERMINATE || - conn->tmabort_state != TMABORT_INITIAL) : - (session->state == ISCSI_STATE_TERMINATE || - session->state == ISCSI_STATE_LOGGED_IN))); - if (rc) { - /* shutdown.. */ - session->state = ISCSI_STATE_TERMINATE; - goto failed; - } - - if (signal_pending(current)) - flush_signals(current); - - if (session->state == ISCSI_STATE_TERMINATE) - goto failed; - - spin_lock_bh(&session->lock); - if (sc->SCp.phase == session->age && - (conn->tmabort_state == TMABORT_TIMEDOUT || - conn->tmabort_state == TMABORT_FAILED)) { - conn->tmabort_state = TMABORT_INITIAL; - if (!ctask->sc) { - /* - * ctask completed before tmf abort response or - * time out. - * But session is still ok => Happy Retry. - */ - spin_unlock_bh(&session->lock); - break; - } - spin_unlock_bh(&session->lock); - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - continue; - } - spin_unlock_bh(&session->lock); - break; - } - -success: - debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); - rc = SUCCESS; - goto exit; - -failed: - debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); - rc = FAILED; + struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; -exit: - del_timer_sync(&conn->tmabort_timer); - - mutex_lock(&conn->xmitmutex); - if (conn->sock) { - struct sock *sk = conn->sock->sk; + iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, + sizeof(struct iscsi_hdr)); + tcp_mtask->xmstate = XMSTATE_IMM_HDR; - write_lock_bh(&sk->sk_callback_lock); - iscsi_ctask_cleanup(conn, ctask); - write_unlock_bh(&sk->sk_callback_lock); - } - mutex_unlock(&conn->xmitmutex); - return rc; + if (mtask->data_count) + iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data, + mtask->data_count); } static int @@ -3174,6 +2074,7 @@ iscsi_r2tpool_alloc(struct iscsi_session */ for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; /* * pre-allocated x4 as much r2ts to handle race when @@ -3182,42 +2083,32 @@ iscsi_r2tpool_alloc(struct iscsi_session */ /* R2T pool */ - if (iscsi_pool_init(&ctask->r2tpool, session->max_r2t * 4, - (void***)&ctask->r2ts, sizeof(struct iscsi_r2t_info))) { + if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4, + (void***)&tcp_ctask->r2ts, + sizeof(struct iscsi_r2t_info))) { goto r2t_alloc_fail; } /* R2T xmit queue */ - ctask->r2tqueue = kfifo_alloc( + tcp_ctask->r2tqueue = kfifo_alloc( session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL); - if (ctask->r2tqueue == ERR_PTR(-ENOMEM)) { - iscsi_pool_free(&ctask->r2tpool, (void**)ctask->r2ts); + if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) { + iscsi_pool_free(&tcp_ctask->r2tpool, + (void**)tcp_ctask->r2ts); goto r2t_alloc_fail; } - - /* - * number of - * Data-Out PDU's within R2T-sequence can be quite big; - * using mempool - */ - ctask->datapool = mempool_create_slab_pool(ISCSI_DTASK_DEFAULT_MAX, - taskcache); - if (ctask->datapool == NULL) { - kfifo_free(ctask->r2tqueue); - iscsi_pool_free(&ctask->r2tpool, (void**)ctask->r2ts); - goto r2t_alloc_fail; - } - INIT_LIST_HEAD(&ctask->dataqueue); } return 0; r2t_alloc_fail: for (i = 0; i < cmd_i; i++) { - mempool_destroy(session->cmds[i]->datapool); - kfifo_free(session->cmds[i]->r2tqueue); - iscsi_pool_free(&session->cmds[i]->r2tpool, - (void**)session->cmds[i]->r2ts); + struct iscsi_cmd_task *ctask = session->cmds[i]; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + + kfifo_free(tcp_ctask->r2tqueue); + iscsi_pool_free(&tcp_ctask->r2tpool, + (void**)tcp_ctask->r2ts); } return -ENOMEM; } @@ -3228,127 +2119,13 @@ iscsi_r2tpool_free(struct iscsi_session int i; for (i = 0; i < session->cmds_max; i++) { - mempool_destroy(session->cmds[i]->datapool); - kfifo_free(session->cmds[i]->r2tqueue); - iscsi_pool_free(&session->cmds[i]->r2tpool, - (void**)session->cmds[i]->r2ts); - } -} + struct iscsi_cmd_task *ctask = session->cmds[i]; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; -static struct scsi_host_template iscsi_sht = { - .name = "iSCSI Initiator over TCP/IP, v." - ISCSI_VERSION_STR, - .queuecommand = iscsi_queuecommand, - .change_queue_depth = iscsi_change_queue_depth, - .can_queue = ISCSI_XMIT_CMDS_MAX - 1, - .sg_tablesize = ISCSI_SG_TABLESIZE, - .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, - .eh_abort_handler = iscsi_eh_abort, - .eh_host_reset_handler = iscsi_eh_host_reset, - .use_clustering = DISABLE_CLUSTERING, - .proc_name = "iscsi_tcp", - .this_id = -1, -}; - -static struct iscsi_transport iscsi_tcp_transport; - -static struct iscsi_cls_session * -iscsi_session_create(struct scsi_transport_template *scsit, - uint32_t initial_cmdsn, uint32_t *sid) -{ - struct Scsi_Host *shost; - struct iscsi_session *session; - int cmd_i; - - shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport); - if (!shost) - return NULL; - - session = iscsi_hostdata(shost->hostdata); - memset(session, 0, sizeof(struct iscsi_session)); - session->host = shost; - session->state = ISCSI_STATE_FREE; - session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; - session->cmds_max = ISCSI_XMIT_CMDS_MAX; - session->cmdsn = initial_cmdsn; - session->exp_cmdsn = initial_cmdsn + 1; - session->max_cmdsn = initial_cmdsn + 1; - session->max_r2t = 1; - *sid = shost->host_no; - - /* initialize SCSI PDU commands pool */ - if (iscsi_pool_init(&session->cmdpool, session->cmds_max, - (void***)&session->cmds, sizeof(struct iscsi_cmd_task))) - goto cmdpool_alloc_fail; - - /* pre-format cmds pool with ITT */ - for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) - session->cmds[cmd_i]->itt = cmd_i; - - spin_lock_init(&session->lock); - INIT_LIST_HEAD(&session->connections); - - /* initialize immediate command pool */ - if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, - (void***)&session->mgmt_cmds, sizeof(struct iscsi_mgmt_task))) - goto mgmtpool_alloc_fail; - - - /* pre-format immediate cmds pool with ITT */ - for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { - session->mgmt_cmds[cmd_i]->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; - session->mgmt_cmds[cmd_i]->data = kmalloc( - DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); - if (!session->mgmt_cmds[cmd_i]->data) { - int j; - - for (j = 0; j < cmd_i; j++) - kfree(session->mgmt_cmds[j]->data); - goto immdata_alloc_fail; - } + kfifo_free(tcp_ctask->r2tqueue); + iscsi_pool_free(&tcp_ctask->r2tpool, + (void**)tcp_ctask->r2ts); } - - if (iscsi_r2tpool_alloc(session)) - goto r2tpool_alloc_fail; - - return hostdata_session(shost->hostdata); - -r2tpool_alloc_fail: - for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) - kfree(session->mgmt_cmds[cmd_i]->data); -immdata_alloc_fail: - iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); -mgmtpool_alloc_fail: - iscsi_pool_free(&session->cmdpool, (void**)session->cmds); -cmdpool_alloc_fail: - iscsi_transport_destroy_session(shost); - return NULL; -} - -static void -iscsi_session_destroy(struct iscsi_cls_session *cls_session) -{ - struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); - struct iscsi_session *session = iscsi_hostdata(shost->hostdata); - int cmd_i; - struct iscsi_data_task *dtask, *n; - - for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { - struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; - list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) { - list_del(&dtask->item); - mempool_free(dtask, ctask->datapool); - } - } - - for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) - kfree(session->mgmt_cmds[cmd_i]->data); - - iscsi_r2tpool_free(session); - iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); - iscsi_pool_free(&session->cmdpool, (void**)session->cmds); - - iscsi_transport_destroy_session(shost); } static int @@ -3357,23 +2134,14 @@ iscsi_conn_set_param(struct iscsi_cls_co { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session = conn->session; - - spin_lock_bh(&session->lock); - if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE && - conn->stop_stage != STOP_CONN_RECOVER) { - printk(KERN_ERR "iscsi_tcp: can not change parameter [%d]\n", - param); - spin_unlock_bh(&session->lock); - return 0; - } - spin_unlock_bh(&session->lock); + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; switch(param) { case ISCSI_PARAM_MAX_RECV_DLENGTH: { - char *saveptr = conn->data; + char *saveptr = tcp_conn->data; gfp_t flags = GFP_KERNEL; - if (conn->data_size >= value) { + if (tcp_conn->data_size >= value) { conn->max_recv_dlength = value; break; } @@ -3384,21 +2152,21 @@ iscsi_conn_set_param(struct iscsi_cls_co spin_unlock_bh(&session->lock); if (value <= PAGE_SIZE) - conn->data = kmalloc(value, flags); + tcp_conn->data = kmalloc(value, flags); else - conn->data = (void*)__get_free_pages(flags, + tcp_conn->data = (void*)__get_free_pages(flags, get_order(value)); - if (conn->data == NULL) { - conn->data = saveptr; + if (tcp_conn->data == NULL) { + tcp_conn->data = saveptr; return -ENOMEM; } - if (conn->data_size <= PAGE_SIZE) + if (tcp_conn->data_size <= PAGE_SIZE) kfree(saveptr); else free_pages((unsigned long)saveptr, - get_order(conn->data_size)); + get_order(tcp_conn->data_size)); conn->max_recv_dlength = value; - conn->data_size = value; + tcp_conn->data_size = value; } break; case ISCSI_PARAM_MAX_XMIT_DLENGTH: @@ -3406,49 +2174,51 @@ iscsi_conn_set_param(struct iscsi_cls_co break; case ISCSI_PARAM_HDRDGST_EN: conn->hdrdgst_en = value; - conn->hdr_size = sizeof(struct iscsi_hdr); + tcp_conn->hdr_size = sizeof(struct iscsi_hdr); if (conn->hdrdgst_en) { - conn->hdr_size += sizeof(__u32); - if (!conn->tx_tfm) - conn->tx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!conn->tx_tfm) + tcp_conn->hdr_size += sizeof(__u32); + if (!tcp_conn->tx_tfm) + tcp_conn->tx_tfm = crypto_alloc_tfm("crc32c", + 0); + if (!tcp_conn->tx_tfm) return -ENOMEM; - if (!conn->rx_tfm) - conn->rx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!conn->rx_tfm) { - crypto_free_tfm(conn->tx_tfm); + if (!tcp_conn->rx_tfm) + tcp_conn->rx_tfm = crypto_alloc_tfm("crc32c", + 0); + if (!tcp_conn->rx_tfm) { + crypto_free_tfm(tcp_conn->tx_tfm); return -ENOMEM; } } else { - if (conn->tx_tfm) - crypto_free_tfm(conn->tx_tfm); - if (conn->rx_tfm) - crypto_free_tfm(conn->rx_tfm); + if (tcp_conn->tx_tfm) + crypto_free_tfm(tcp_conn->tx_tfm); + if (tcp_conn->rx_tfm) + crypto_free_tfm(tcp_conn->rx_tfm); } break; case ISCSI_PARAM_DATADGST_EN: conn->datadgst_en = value; if (conn->datadgst_en) { - if (!conn->data_tx_tfm) - conn->data_tx_tfm = + if (!tcp_conn->data_tx_tfm) + tcp_conn->data_tx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!conn->data_tx_tfm) + if (!tcp_conn->data_tx_tfm) return -ENOMEM; - if (!conn->data_rx_tfm) - conn->data_rx_tfm = + if (!tcp_conn->data_rx_tfm) + tcp_conn->data_rx_tfm = crypto_alloc_tfm("crc32c", 0); - if (!conn->data_rx_tfm) { - crypto_free_tfm(conn->data_tx_tfm); + if (!tcp_conn->data_rx_tfm) { + crypto_free_tfm(tcp_conn->data_tx_tfm); return -ENOMEM; } } else { - if (conn->data_tx_tfm) - crypto_free_tfm(conn->data_tx_tfm); - if (conn->data_rx_tfm) - crypto_free_tfm(conn->data_rx_tfm); + if (tcp_conn->data_tx_tfm) + crypto_free_tfm(tcp_conn->data_tx_tfm); + if (tcp_conn->data_rx_tfm) + crypto_free_tfm(tcp_conn->data_rx_tfm); } - conn->sendpage = conn->datadgst_en ? - sock_no_sendpage : conn->sock->ops->sendpage; + tcp_conn->sendpage = conn->datadgst_en ? + sock_no_sendpage : tcp_conn->sock->ops->sendpage; break; case ISCSI_PARAM_INITIAL_R2T_EN: session->initial_r2t_en = value; @@ -3489,6 +2259,9 @@ iscsi_conn_set_param(struct iscsi_cls_co BUG_ON(value); session->ofmarker_en = value; break; + case ISCSI_PARAM_EXP_STATSN: + conn->exp_statsn = value; + break; default: break; } @@ -3535,7 +2308,7 @@ iscsi_session_get_param(struct iscsi_cls *value = session->ofmarker_en; break; default: - return ISCSI_ERR_PARAM_NOT_FOUND; + return -EINVAL; } return 0; @@ -3546,6 +2319,8 @@ iscsi_conn_get_param(struct iscsi_cls_co enum iscsi_param param, uint32_t *value) { struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct inet_sock *inet; switch(param) { case ISCSI_PARAM_MAX_RECV_DLENGTH: @@ -3560,17 +2335,70 @@ iscsi_conn_get_param(struct iscsi_cls_co case ISCSI_PARAM_DATADGST_EN: *value = conn->datadgst_en; break; + case ISCSI_PARAM_CONN_PORT: + mutex_lock(&conn->xmitmutex); + if (!tcp_conn->sock) { + mutex_unlock(&conn->xmitmutex); + return -EINVAL; + } + + inet = inet_sk(tcp_conn->sock->sk); + *value = be16_to_cpu(inet->dport); + mutex_unlock(&conn->xmitmutex); + case ISCSI_PARAM_EXP_STATSN: + *value = conn->exp_statsn; + break; default: - return ISCSI_ERR_PARAM_NOT_FOUND; + return -EINVAL; } return 0; } +static int +iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn, + enum iscsi_param param, char *buf) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct sock *sk; + struct inet_sock *inet; + struct ipv6_pinfo *np; + int len = 0; + + switch (param) { + case ISCSI_PARAM_CONN_ADDRESS: + mutex_lock(&conn->xmitmutex); + if (!tcp_conn->sock) { + mutex_unlock(&conn->xmitmutex); + return -EINVAL; + } + + sk = tcp_conn->sock->sk; + if (sk->sk_family == PF_INET) { + inet = inet_sk(sk); + len = sprintf(buf, "%u.%u.%u.%u\n", + NIPQUAD(inet->daddr)); + } else { + np = inet6_sk(sk); + len = sprintf(buf, + "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + NIP6(np->daddr)); + } + mutex_unlock(&conn->xmitmutex); + break; + default: + return -EINVAL; + } + + return len; +} + static void iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) { struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; stats->txdata_octets = conn->txdata_octets; stats->rxdata_octets = conn->rxdata_octets; @@ -3583,68 +2411,141 @@ iscsi_conn_get_stats(struct iscsi_cls_co stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; stats->custom_length = 3; strcpy(stats->custom[0].desc, "tx_sendpage_failures"); - stats->custom[0].value = conn->sendpage_failures_cnt; + stats->custom[0].value = tcp_conn->sendpage_failures_cnt; strcpy(stats->custom[1].desc, "rx_discontiguous_hdr"); - stats->custom[1].value = conn->discontiguous_hdr_cnt; + stats->custom[1].value = tcp_conn->discontiguous_hdr_cnt; strcpy(stats->custom[2].desc, "eh_abort_cnt"); stats->custom[2].value = conn->eh_abort_cnt; } -static int -iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, - char *data, uint32_t data_size) +static struct iscsi_cls_session * +iscsi_tcp_session_create(struct iscsi_transport *iscsit, + struct scsi_transport_template *scsit, + uint32_t initial_cmdsn, uint32_t *hostno) { - struct iscsi_conn *conn = cls_conn->dd_data; - int rc; + struct iscsi_cls_session *cls_session; + struct iscsi_session *session; + uint32_t hn; + int cmd_i; - mutex_lock(&conn->xmitmutex); - rc = iscsi_conn_send_generic(conn, hdr, data, data_size); - mutex_unlock(&conn->xmitmutex); + cls_session = iscsi_session_setup(iscsit, scsit, + sizeof(struct iscsi_tcp_cmd_task), + sizeof(struct iscsi_tcp_mgmt_task), + initial_cmdsn, &hn); + if (!cls_session) + return NULL; + *hostno = hn; - return rc; + session = class_to_transport_session(cls_session); + for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { + struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + + ctask->hdr = &tcp_ctask->hdr; + } + + for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { + struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i]; + struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; + + mtask->hdr = &tcp_mtask->hdr; + } + + if (iscsi_r2tpool_alloc(class_to_transport_session(cls_session))) + goto r2tpool_alloc_fail; + + return cls_session; + +r2tpool_alloc_fail: + iscsi_session_teardown(cls_session); + return NULL; } +static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) +{ + iscsi_r2tpool_free(class_to_transport_session(cls_session)); + iscsi_session_teardown(cls_session); +} + +static struct scsi_host_template iscsi_sht = { + .name = "iSCSI Initiator over TCP/IP, v" + ISCSI_TCP_VERSION, + .queuecommand = iscsi_queuecommand, + .change_queue_depth = iscsi_change_queue_depth, + .can_queue = ISCSI_XMIT_CMDS_MAX - 1, + .sg_tablesize = ISCSI_SG_TABLESIZE, + .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, + .eh_abort_handler = iscsi_eh_abort, + .eh_host_reset_handler = iscsi_eh_host_reset, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "iscsi_tcp", + .this_id = -1, +}; + static struct iscsi_transport iscsi_tcp_transport = { .owner = THIS_MODULE, .name = "tcp", .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST | CAP_DATADGST, + .param_mask = ISCSI_MAX_RECV_DLENGTH | + ISCSI_MAX_XMIT_DLENGTH | + ISCSI_HDRDGST_EN | + ISCSI_DATADGST_EN | + ISCSI_INITIAL_R2T_EN | + ISCSI_MAX_R2T | + ISCSI_IMM_DATA_EN | + ISCSI_FIRST_BURST | + ISCSI_MAX_BURST | + ISCSI_PDU_INORDER_EN | + ISCSI_DATASEQ_INORDER_EN | + ISCSI_ERL | + ISCSI_CONN_PORT | + ISCSI_CONN_ADDRESS | + ISCSI_EXP_STATSN, .host_template = &iscsi_sht, - .hostdata_size = sizeof(struct iscsi_session), .conndata_size = sizeof(struct iscsi_conn), .max_conn = 1, .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, - .create_session = iscsi_session_create, - .destroy_session = iscsi_session_destroy, - .create_conn = iscsi_conn_create, - .bind_conn = iscsi_conn_bind, - .destroy_conn = iscsi_conn_destroy, + /* session management */ + .create_session = iscsi_tcp_session_create, + .destroy_session = iscsi_tcp_session_destroy, + /* connection management */ + .create_conn = iscsi_tcp_conn_create, + .bind_conn = iscsi_tcp_conn_bind, + .destroy_conn = iscsi_tcp_conn_destroy, .set_param = iscsi_conn_set_param, .get_conn_param = iscsi_conn_get_param, + .get_conn_str_param = iscsi_conn_get_str_param, .get_session_param = iscsi_session_get_param, .start_conn = iscsi_conn_start, .stop_conn = iscsi_conn_stop, + /* these are called as part of conn recovery */ + .suspend_conn_recv = iscsi_tcp_suspend_conn_rx, + .terminate_conn = iscsi_tcp_terminate_conn, + /* IO */ .send_pdu = iscsi_conn_send_pdu, .get_stats = iscsi_conn_get_stats, + .init_cmd_task = iscsi_tcp_cmd_init, + .init_mgmt_task = iscsi_tcp_mgmt_init, + .xmit_cmd_task = iscsi_tcp_ctask_xmit, + .xmit_mgmt_task = iscsi_tcp_mtask_xmit, + .cleanup_cmd_task = iscsi_tcp_cleanup_ctask, + /* recovery */ + .session_recovery_timedout = iscsi_session_recovery_timedout, }; static int __init iscsi_tcp_init(void) { if (iscsi_max_lun < 1) { - printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); + printk(KERN_ERR "iscsi_tcp: Invalid max_lun value of %u\n", + iscsi_max_lun); return -EINVAL; } iscsi_tcp_transport.max_lun = iscsi_max_lun; - taskcache = kmem_cache_create("iscsi_taskcache", - sizeof(struct iscsi_data_task), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - if (!taskcache) - return -ENOMEM; - if (!iscsi_register_transport(&iscsi_tcp_transport)) - kmem_cache_destroy(taskcache); + return -ENODEV; return 0; } @@ -3653,7 +2554,6 @@ static void __exit iscsi_tcp_exit(void) { iscsi_unregister_transport(&iscsi_tcp_transport); - kmem_cache_destroy(taskcache); } module_init(iscsi_tcp_init); diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index ba26741..8083028 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -2,7 +2,8 @@ * iSCSI Initiator TCP Transport * Copyright (C) 2004 Dmitry Yusupov * Copyright (C) 2004 Alex Aizman - * Copyright (C) 2005 Mike Christie + * Copyright (C) 2005 - 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify @@ -21,20 +22,7 @@ #ifndef ISCSI_TCP_H #define ISCSI_TCP_H -/* Session's states */ -#define ISCSI_STATE_FREE 1 -#define ISCSI_STATE_LOGGED_IN 2 -#define ISCSI_STATE_FAILED 3 -#define ISCSI_STATE_TERMINATE 4 - -/* Connection's states */ -#define ISCSI_CONN_INITIAL_STAGE 0 -#define ISCSI_CONN_STARTED 1 -#define ISCSI_CONN_STOPPED 2 -#define ISCSI_CONN_CLEANUP_WAIT 3 - -/* Connection suspend "bit" */ -#define SUSPEND_BIT 1 +#include /* Socket's Receive state machine */ #define IN_PROGRESS_WAIT_HEADER 0x0 @@ -42,12 +30,6 @@ #define IN_PROGRESS_HEADER_GATHER 0x1 #define IN_PROGRESS_DATA_RECV 0x2 #define IN_PROGRESS_DDIGEST_RECV 0x3 -/* Task Mgmt states */ -#define TMABORT_INITIAL 0x0 -#define TMABORT_SUCCESS 0x1 -#define TMABORT_FAILED 0x2 -#define TMABORT_TIMEDOUT 0x3 - /* xmit state machine */ #define XMSTATE_IDLE 0x0 #define XMSTATE_R_HDR 0x1 @@ -62,34 +44,14 @@ #define XMSTATE_SOL_DATA 0x100 #define XMSTATE_W_PAD 0x200 #define XMSTATE_DATA_DIGEST 0x400 -#define ISCSI_CONN_MAX 1 #define ISCSI_CONN_RCVBUF_MIN 262144 #define ISCSI_CONN_SNDBUF_MIN 262144 #define ISCSI_PAD_LEN 4 #define ISCSI_R2T_MAX 16 -#define ISCSI_XMIT_CMDS_MAX 128 /* must be power of 2 */ -#define ISCSI_MGMT_CMDS_MAX 32 /* must be power of 2 */ -#define ISCSI_MGMT_ITT_OFFSET 0xa00 #define ISCSI_SG_TABLESIZE SG_ALL -#define ISCSI_DEF_CMD_PER_LUN 32 -#define ISCSI_MAX_CMD_PER_LUN 128 #define ISCSI_TCP_MAX_CMD_LEN 16 -#define ITT_MASK (0xfff) -#define CID_SHIFT 12 -#define CID_MASK (0xffff<ioaddr; + + ap->ctl |= ATA_NIEN; + ap->last_ctl = ap->ctl; + + if (ap->flags & ATA_FLAG_MMIO) + writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr); + else + outb(ap->ctl, ioaddr->ctl_addr); +} + +/** + * ata_bmdma_thaw - Thaw BMDMA controller port + * @ap: port to thaw + * + * Thaw BMDMA controller port. + * + * LOCKING: + * Inherited from caller. + */ +void ata_bmdma_thaw(struct ata_port *ap) +{ + /* clear & re-enable interrupts */ + ata_chk_status(ap); + ap->ops->irq_clear(ap); + if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ + ata_irq_on(ap); +} + +/** + * ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller + * @ap: port to handle error for + * @prereset: prereset method (can be NULL) + * @softreset: softreset method (can be NULL) + * @hardreset: hardreset method (can be NULL) + * @postreset: postreset method (can be NULL) + * + * Handle error for ATA BMDMA controller. It can handle both + * PATA and SATA controllers. Many controllers should be able to + * use this EH as-is or with some added handling before and + * after. + * + * This function is intended to be used for constructing + * ->error_handler callback by low level drivers. + * + * LOCKING: + * Kernel thread context (may sleep) + */ +void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset) +{ + struct ata_eh_context *ehc = &ap->eh_context; + struct ata_queued_cmd *qc; + unsigned long flags; + int thaw = 0; + + qc = __ata_qc_from_tag(ap, ap->active_tag); + if (qc && !(qc->flags & ATA_QCFLAG_FAILED)) + qc = NULL; + + /* reset PIO HSM and stop DMA engine */ + spin_lock_irqsave(ap->lock, flags); + + ap->hsm_task_state = HSM_ST_IDLE; + + if (qc && (qc->tf.protocol == ATA_PROT_DMA || + qc->tf.protocol == ATA_PROT_ATAPI_DMA)) { + u8 host_stat; + + host_stat = ata_bmdma_status(ap); + + ata_ehi_push_desc(&ehc->i, "BMDMA stat 0x%x", host_stat); + + /* BMDMA controllers indicate host bus error by + * setting DMA_ERR bit and timing out. As it wasn't + * really a timeout event, adjust error mask and + * cancel frozen state. + */ + if (qc->err_mask == AC_ERR_TIMEOUT && host_stat & ATA_DMA_ERR) { + qc->err_mask = AC_ERR_HOST_BUS; + thaw = 1; + } + + ap->ops->bmdma_stop(qc); + } + + ata_altstatus(ap); + ata_chk_status(ap); + ap->ops->irq_clear(ap); + + spin_unlock_irqrestore(ap->lock, flags); + + if (thaw) + ata_eh_thaw_port(ap); + + /* PIO and DMA engines have been stopped, perform recovery */ + ata_do_eh(ap, prereset, softreset, hardreset, postreset); +} + +/** + * ata_bmdma_error_handler - Stock error handler for BMDMA controller + * @ap: port to handle error for + * + * Stock error handler for BMDMA controller. + * + * LOCKING: + * Kernel thread context (may sleep) + */ +void ata_bmdma_error_handler(struct ata_port *ap) +{ + ata_reset_fn_t hardreset; + + hardreset = NULL; + if (sata_scr_valid(ap)) + hardreset = sata_std_hardreset; + + ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset, + ata_std_postreset); +} + +/** + * ata_bmdma_post_internal_cmd - Stock post_internal_cmd for + * BMDMA controller + * @qc: internal command to clean up + * + * LOCKING: + * Kernel thread context (may sleep) + */ +void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc) +{ + ata_bmdma_stop(qc); +} + #ifdef CONFIG_PCI static struct ata_probe_ent * ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) @@ -930,10 +1075,21 @@ int ata_pci_init_one (struct pci_dev *pd /* FIXME: check ata_device_add return */ if (legacy_mode) { - if (legacy_mode & (1 << 0)) + struct device *dev = &pdev->dev; + struct ata_host_set *host_set = NULL; + + if (legacy_mode & (1 << 0)) { ata_device_add(probe_ent); - if (legacy_mode & (1 << 1)) + host_set = dev_get_drvdata(dev); + } + + if (legacy_mode & (1 << 1)) { ata_device_add(probe_ent2); + if (host_set) { + host_set->next = dev_get_drvdata(dev); + dev_set_drvdata(dev, host_set); + } + } } else ata_device_add(probe_ent); diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b046ffa..6c66877 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -61,22 +61,29 @@ #include #include "libata.h" -static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev, - u16 heads, - u16 sectors); -static void ata_set_mode(struct ata_port *ap); -static unsigned int ata_dev_set_xfermode(struct ata_port *ap, - struct ata_device *dev); -static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev); +/* debounce timing parameters in msecs { interval, duration, timeout } */ +const unsigned long sata_deb_timing_boot[] = { 5, 100, 2000 }; +const unsigned long sata_deb_timing_eh[] = { 25, 500, 2000 }; +const unsigned long sata_deb_timing_before_fsrst[] = { 100, 2000, 5000 }; + +static unsigned int ata_dev_init_params(struct ata_device *dev, + u16 heads, u16 sectors); +static unsigned int ata_dev_set_xfermode(struct ata_device *dev); +static void ata_dev_xfermask(struct ata_device *dev); static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; +struct workqueue_struct *ata_aux_wq; + int atapi_enabled = 1; module_param(atapi_enabled, int, 0444); MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)"); +int atapi_dmadir = 0; +module_param(atapi_dmadir, int, 0444); +MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off, 1=on)"); + int libata_fua = 0; module_param_named(fua, libata_fua, int, 0444); MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)"); @@ -397,11 +404,22 @@ static const char *ata_mode_string(unsig return ""; } -static void ata_dev_disable(struct ata_port *ap, struct ata_device *dev) +static const char *sata_spd_string(unsigned int spd) { - if (ata_dev_present(dev)) { - printk(KERN_WARNING "ata%u: dev %u disabled\n", - ap->id, dev->devno); + static const char * const spd_str[] = { + "1.5 Gbps", + "3.0 Gbps", + }; + + if (spd == 0 || (spd - 1) >= ARRAY_SIZE(spd_str)) + return ""; + return spd_str[spd - 1]; +} + +void ata_dev_disable(struct ata_device *dev) +{ + if (ata_dev_enabled(dev) && ata_msg_drv(dev->ap)) { + ata_dev_printk(dev, KERN_WARNING, "disabled\n"); dev->class++; } } @@ -759,8 +777,11 @@ void ata_std_dev_select (struct ata_port void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep) { - VPRINTK("ENTER, ata%u: device %u, wait %u\n", - ap->id, device, wait); + if (ata_msg_probe(ap)) { + ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, ata%u: " + "device %u, wait %u\n", + ap->id, device, wait); + } if (wait) ata_wait_idle(ap); @@ -915,9 +936,9 @@ void ata_port_flush_task(struct ata_port DPRINTK("ENTER\n"); - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ap->flags |= ATA_FLAG_FLUSH_PORT_TASK; - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); DPRINTK("flush #1\n"); flush_workqueue(ata_wq); @@ -928,30 +949,31 @@ void ata_port_flush_task(struct ata_port * Cancel and flush. */ if (!cancel_delayed_work(&ap->port_task)) { - DPRINTK("flush #2\n"); + if (ata_msg_ctl(ap)) + ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n", __FUNCTION__); flush_workqueue(ata_wq); } - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->lock, flags); ap->flags &= ~ATA_FLAG_FLUSH_PORT_TASK; - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); - DPRINTK("EXIT\n"); + if (ata_msg_ctl(ap)) + ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__); } void ata_qc_complete_internal(struct ata_queued_cmd *qc) { struct completion *waiting = qc->private_data; - qc->ap->ops->tf_read(qc->ap, &qc->tf); complete(waiting); } /** * ata_exec_internal - execute libata internal command - * @ap: Port to which the command is sent * @dev: Device to which the command is sent * @tf: Taskfile registers for the command and the result + * @cdb: CDB for packet command * @dma_dir: Data tranfer direction of the command * @buf: Data buffer of the command * @buflen: Length of data buffer @@ -964,25 +986,66 @@ void ata_qc_complete_internal(struct ata * * LOCKING: * None. Should be called with kernel context, might sleep. + * + * RETURNS: + * Zero on success, AC_ERR_* mask on failure */ - -static unsigned -ata_exec_internal(struct ata_port *ap, struct ata_device *dev, - struct ata_taskfile *tf, - int dma_dir, void *buf, unsigned int buflen) +unsigned ata_exec_internal(struct ata_device *dev, + struct ata_taskfile *tf, const u8 *cdb, + int dma_dir, void *buf, unsigned int buflen) { + struct ata_port *ap = dev->ap; u8 command = tf->command; struct ata_queued_cmd *qc; + unsigned int tag, preempted_tag; + u32 preempted_sactive, preempted_qc_active; DECLARE_COMPLETION(wait); unsigned long flags; unsigned int err_mask; + int rc; + + spin_lock_irqsave(ap->lock, flags); + + /* no internal command while frozen */ + if (ap->flags & ATA_FLAG_FROZEN) { + spin_unlock_irqrestore(ap->lock, flags); + return AC_ERR_SYSTEM; + } - spin_lock_irqsave(&ap->host_set->lock, flags); + /* initialize internal qc */ - qc = ata_qc_new_init(ap, dev); - BUG_ON(qc == NULL); + /* XXX: Tag 0 is used for drivers with legacy EH as some + * drivers choke if any other tag is given. This breaks + * ata_tag_internal() test for those drivers. Don't use new + * EH stuff without converting to it. + */ + if (ap->ops->error_handler) + tag = ATA_TAG_INTERNAL; + else + tag = 0; + + if (test_and_set_bit(tag, &ap->qc_allocated)) + BUG(); + qc = __ata_qc_from_tag(ap, tag); + qc->tag = tag; + qc->scsicmd = NULL; + qc->ap = ap; + qc->dev = dev; + ata_qc_reinit(qc); + + preempted_tag = ap->active_tag; + preempted_sactive = ap->sactive; + preempted_qc_active = ap->qc_active; + ap->active_tag = ATA_TAG_POISON; + ap->sactive = 0; + ap->qc_active = 0; + + /* prepare & issue qc */ qc->tf = *tf; + if (cdb) + memcpy(qc->cdb, cdb, ATAPI_CDB_LEN); + qc->flags |= ATA_QCFLAG_RESULT_TF; qc->dma_dir = dma_dir; if (dma_dir != DMA_NONE) { ata_sg_init_one(qc, buf, buflen); @@ -994,33 +1057,58 @@ ata_exec_internal(struct ata_port *ap, s ata_qc_issue(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); + + rc = wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL); - if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) { - ata_port_flush_task(ap); + ata_port_flush_task(ap); - spin_lock_irqsave(&ap->host_set->lock, flags); + if (!rc) { + spin_lock_irqsave(ap->lock, flags); /* We're racing with irq here. If we lose, the * following test prevents us from completing the qc - * again. If completion irq occurs after here but - * before the caller cleans up, it will result in a - * spurious interrupt. We can live with that. + * twice. If we win, the port is frozen and will be + * cleaned up by ->post_internal_cmd(). */ if (qc->flags & ATA_QCFLAG_ACTIVE) { - qc->err_mask = AC_ERR_TIMEOUT; - ata_qc_complete(qc); - printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n", - ap->id, command); + qc->err_mask |= AC_ERR_TIMEOUT; + + if (ap->ops->error_handler) + ata_port_freeze(ap); + else + ata_qc_complete(qc); + + if (ata_msg_warn(ap)) + ata_dev_printk(dev, KERN_WARNING, + "qc timeout (cmd 0x%x)\n", command); } - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->lock, flags); } - *tf = qc->tf; + /* do post_internal_cmd */ + if (ap->ops->post_internal_cmd) + ap->ops->post_internal_cmd(qc); + + if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) { + if (ata_msg_warn(ap)) + ata_dev_printk(dev, KERN_WARNING, + "zero err_mask for failed " + "internal command, assuming AC_ERR_OTHER\n"); + qc->err_mask |= AC_ERR_OTHER; + } + + /* finish up */ + spin_lock_irqsave(ap->lock, flags); + + *tf = qc->result_tf; err_mask = qc->err_mask; ata_qc_free(qc); + ap->active_tag = preempted_tag; + ap->sactive = preempted_sactive; + ap->qc_active = preempted_qc_active; /* XXX - Some LLDDs (sata_mv) disable port on command failure. * Until those drivers are fixed, we detect the condition @@ -1033,11 +1121,13 @@ ata_exec_internal(struct ata_port *ap, s * * Kill the following code as soon as those drivers are fixed. */ - if (ap->flags & ATA_FLAG_PORT_DISABLED) { + if (ap->flags & ATA_FLAG_DISABLED) { err_mask |= AC_ERR_SYSTEM; ata_port_probe(ap); } + spin_unlock_irqrestore(ap->lock, flags); + return err_mask; } @@ -1076,11 +1166,10 @@ unsigned int ata_pio_need_iordy(const st /** * ata_dev_read_id - Read ID data from the specified device - * @ap: port on which target device resides * @dev: target device * @p_class: pointer to class of the target device (may be changed) * @post_reset: is this read ID post-reset? - * @p_id: read IDENTIFY page (newly allocated) + * @id: buffer to read IDENTIFY data into * * Read ID data from the specified device. ATA_CMD_ID_ATA is * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI @@ -1093,29 +1182,24 @@ unsigned int ata_pio_need_iordy(const st * RETURNS: * 0 on success, -errno otherwise. */ -static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, - unsigned int *p_class, int post_reset, u16 **p_id) +int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, + int post_reset, u16 *id) { + struct ata_port *ap = dev->ap; unsigned int class = *p_class; struct ata_taskfile tf; unsigned int err_mask = 0; - u16 *id; const char *reason; int rc; - DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); + if (ata_msg_ctl(ap)) + ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n", + __FUNCTION__, ap->id, dev->devno); ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ - id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL); - if (id == NULL) { - rc = -ENOMEM; - reason = "out of memory"; - goto err_out; - } - retry: - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); switch (class) { case ATA_DEV_ATA: @@ -1132,7 +1216,7 @@ static int ata_dev_read_id(struct ata_po tf.protocol = ATA_PROT_PIO; - err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE, + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, id, sizeof(id[0]) * ATA_ID_WORDS); if (err_mask) { rc = -EIO; @@ -1159,7 +1243,7 @@ static int ata_dev_read_id(struct ata_po * Some drives were very specific about that exact sequence. */ if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) { - err_mask = ata_dev_init_params(ap, dev, id[3], id[6]); + err_mask = ata_dev_init_params(dev, id[3], id[6]); if (err_mask) { rc = -EIO; reason = "INIT_DEV_PARAMS failed"; @@ -1175,25 +1259,45 @@ static int ata_dev_read_id(struct ata_po } *p_class = class; - *p_id = id; + return 0; err_out: - printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n", - ap->id, dev->devno, reason); - kfree(id); + if (ata_msg_warn(ap)) + ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY " + "(%s, err_mask=0x%x)\n", reason, err_mask); return rc; } -static inline u8 ata_dev_knobble(const struct ata_port *ap, - struct ata_device *dev) +static inline u8 ata_dev_knobble(struct ata_device *dev) { - return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); + return ((dev->ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); +} + +static void ata_dev_config_ncq(struct ata_device *dev, + char *desc, size_t desc_sz) +{ + struct ata_port *ap = dev->ap; + int hdepth = 0, ddepth = ata_id_queue_depth(dev->id); + + if (!ata_id_has_ncq(dev->id)) { + desc[0] = '\0'; + return; + } + + if (ap->flags & ATA_FLAG_NCQ) { + hdepth = min(ap->host->can_queue, ATA_MAX_QUEUE - 1); + dev->flags |= ATA_DFLAG_NCQ; + } + + if (hdepth >= ddepth) + snprintf(desc, desc_sz, "NCQ (depth %d)", ddepth); + else + snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth); } /** * ata_dev_configure - Configure the specified ATA/ATAPI device - * @ap: Port on which target device resides * @dev: Target device to configure * @print_info: Enable device info printout * @@ -1206,30 +1310,33 @@ static inline u8 ata_dev_knobble(const s * RETURNS: * 0 on success, -errno otherwise */ -static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, - int print_info) +int ata_dev_configure(struct ata_device *dev, int print_info) { + struct ata_port *ap = dev->ap; const u16 *id = dev->id; unsigned int xfer_mask; int i, rc; - if (!ata_dev_present(dev)) { - DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", - ap->id, dev->devno); + if (!ata_dev_enabled(dev) && ata_msg_info(ap)) { + ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT (host %u, dev %u) -- nodev\n", + __FUNCTION__, ap->id, dev->devno); return 0; } - DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n", + __FUNCTION__, ap->id, dev->devno); /* print device capabilities */ - if (print_info) - printk(KERN_DEBUG "ata%u: dev %u cfg 49:%04x 82:%04x 83:%04x " - "84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n", - ap->id, dev->devno, id[49], id[82], id[83], - id[84], id[85], id[86], id[87], id[88]); + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, "%s: cfg 49:%04x 82:%04x 83:%04x " + "84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n", + __FUNCTION__, + id[49], id[82], id[83], id[84], + id[85], id[86], id[87], id[88]); /* initialize to-be-configured parameters */ - dev->flags = 0; + dev->flags &= ~ATA_DFLAG_CFG_MASK; dev->max_sectors = 0; dev->cdb_len = 0; dev->n_sectors = 0; @@ -1244,7 +1351,8 @@ static int ata_dev_configure(struct ata_ /* find max transfer mode; for printk only */ xfer_mask = ata_id_xfermask(id); - ata_dump_id(id); + if (ata_msg_probe(ap)) + ata_dump_id(id); /* ATA-specific feature tests */ if (dev->class == ATA_DEV_ATA) { @@ -1252,6 +1360,7 @@ static int ata_dev_configure(struct ata_ if (ata_id_has_lba(id)) { const char *lba_desc; + char ncq_desc[20]; lba_desc = "LBA"; dev->flags |= ATA_DFLAG_LBA; @@ -1260,15 +1369,17 @@ static int ata_dev_configure(struct ata_ lba_desc = "LBA48"; } + /* config NCQ */ + ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc)); + /* print device info to dmesg */ - if (print_info) - printk(KERN_INFO "ata%u: dev %u ATA-%d, " - "max %s, %Lu sectors: %s\n", - ap->id, dev->devno, - ata_id_major_version(id), - ata_mode_string(xfer_mask), - (unsigned long long)dev->n_sectors, - lba_desc); + if (ata_msg_info(ap)) + ata_dev_printk(dev, KERN_INFO, "ATA-%d, " + "max %s, %Lu sectors: %s %s\n", + ata_id_major_version(id), + ata_mode_string(xfer_mask), + (unsigned long long)dev->n_sectors, + lba_desc, ncq_desc); } else { /* CHS */ @@ -1285,14 +1396,20 @@ static int ata_dev_configure(struct ata_ } /* print device info to dmesg */ - if (print_info) - printk(KERN_INFO "ata%u: dev %u ATA-%d, " - "max %s, %Lu sectors: CHS %u/%u/%u\n", - ap->id, dev->devno, - ata_id_major_version(id), - ata_mode_string(xfer_mask), - (unsigned long long)dev->n_sectors, - dev->cylinders, dev->heads, dev->sectors); + if (ata_msg_info(ap)) + ata_dev_printk(dev, KERN_INFO, "ATA-%d, " + "max %s, %Lu sectors: CHS %u/%u/%u\n", + ata_id_major_version(id), + ata_mode_string(xfer_mask), + (unsigned long long)dev->n_sectors, + dev->cylinders, dev->heads, dev->sectors); + } + + if (dev->id[59] & 0x100) { + dev->multi_count = dev->id[59] & 0xff; + if (ata_msg_info(ap)) + ata_dev_printk(dev, KERN_INFO, "ata%u: dev %u multi count %u\n", + ap->id, dev->devno, dev->multi_count); } dev->cdb_len = 16; @@ -1300,18 +1417,28 @@ static int ata_dev_configure(struct ata_ /* ATAPI-specific feature tests */ else if (dev->class == ATA_DEV_ATAPI) { + char *cdb_intr_string = ""; + rc = atapi_cdb_len(id); if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { - printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); + if (ata_msg_warn(ap)) + ata_dev_printk(dev, KERN_WARNING, + "unsupported CDB len\n"); rc = -EINVAL; goto err_out_nosup; } dev->cdb_len = (unsigned int) rc; + if (ata_id_cdb_intr(dev->id)) { + dev->flags |= ATA_DFLAG_CDB_INTR; + cdb_intr_string = ", CDB intr"; + } + /* print device info to dmesg */ - if (print_info) - printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", - ap->id, dev->devno, ata_mode_string(xfer_mask)); + if (ata_msg_info(ap)) + ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n", + ata_mode_string(xfer_mask), + cdb_intr_string); } ap->host->max_cmd_len = 0; @@ -1321,10 +1448,10 @@ static int ata_dev_configure(struct ata_ ap->device[i].cdb_len); /* limit bridge transfers to udma5, 200 sectors */ - if (ata_dev_knobble(ap, dev)) { - if (print_info) - printk(KERN_INFO "ata%u(%u): applying bridge limits\n", - ap->id, dev->devno); + if (ata_dev_knobble(dev)) { + if (ata_msg_info(ap)) + ata_dev_printk(dev, KERN_INFO, + "applying bridge limits\n"); dev->udma_mask &= ATA_UDMA5; dev->max_sectors = ATA_MAX_SECTORS; } @@ -1332,11 +1459,15 @@ static int ata_dev_configure(struct ata_ if (ap->ops->dev_config) ap->ops->dev_config(ap, dev); - DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n", + __FUNCTION__, ata_chk_status(ap)); return 0; err_out_nosup: - DPRINTK("EXIT, err\n"); + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s: EXIT, err\n", __FUNCTION__); return rc; } @@ -1352,79 +1483,104 @@ err_out_nosup: * PCI/etc. bus probe sem. * * RETURNS: - * Zero on success, non-zero on error. + * Zero on success, negative errno otherwise. */ static int ata_bus_probe(struct ata_port *ap) { unsigned int classes[ATA_MAX_DEVICES]; - unsigned int i, rc, found = 0; + int tries[ATA_MAX_DEVICES]; + int i, rc, down_xfermask; + struct ata_device *dev; ata_port_probe(ap); - /* reset and determine device classes */ for (i = 0; i < ATA_MAX_DEVICES; i++) - classes[i] = ATA_DEV_UNKNOWN; + tries[i] = ATA_PROBE_MAX_TRIES; - if (ap->ops->probe_reset) { - rc = ap->ops->probe_reset(ap, classes); - if (rc) { - printk("ata%u: reset failed (errno=%d)\n", ap->id, rc); - return rc; - } - } else { - ap->ops->phy_reset(ap); + retry: + down_xfermask = 0; - if (!(ap->flags & ATA_FLAG_PORT_DISABLED)) - for (i = 0; i < ATA_MAX_DEVICES; i++) - classes[i] = ap->device[i].class; + /* reset and determine device classes */ + ap->ops->phy_reset(ap); - ata_port_probe(ap); + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + + if (!(ap->flags & ATA_FLAG_DISABLED) && + dev->class != ATA_DEV_UNKNOWN) + classes[dev->devno] = dev->class; + else + classes[dev->devno] = ATA_DEV_NONE; + + dev->class = ATA_DEV_UNKNOWN; } + ata_port_probe(ap); + + /* after the reset the device state is PIO 0 and the controller + state is undefined. Record the mode */ + for (i = 0; i < ATA_MAX_DEVICES; i++) - if (classes[i] == ATA_DEV_UNKNOWN) - classes[i] = ATA_DEV_NONE; + ap->device[i].pio_mode = XFER_PIO_0; /* read IDENTIFY page and configure devices */ for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; + dev = &ap->device[i]; - dev->class = classes[i]; + if (tries[i]) + dev->class = classes[i]; - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) continue; - WARN_ON(dev->id != NULL); - if (ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id)) { - dev->class = ATA_DEV_NONE; - continue; - } + rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); + if (rc) + goto fail; - if (ata_dev_configure(ap, dev, 1)) { - ata_dev_disable(ap, dev); - continue; - } + rc = ata_dev_configure(dev, 1); + if (rc) + goto fail; + } - found = 1; + /* configure transfer mode */ + rc = ata_set_mode(ap, &dev); + if (rc) { + down_xfermask = 1; + goto fail; } - if (!found) - goto err_out_disable; + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ata_dev_enabled(&ap->device[i])) + return 0; - if (ap->ops->set_mode) - ap->ops->set_mode(ap); - else - ata_set_mode(ap); + /* no device present, disable port */ + ata_port_disable(ap); + ap->ops->port_disable(ap); + return -ENODEV; - if (ap->flags & ATA_FLAG_PORT_DISABLED) - goto err_out_disable; + fail: + switch (rc) { + case -EINVAL: + case -ENODEV: + tries[dev->devno] = 0; + break; + case -EIO: + sata_down_spd_limit(ap); + /* fall through */ + default: + tries[dev->devno]--; + if (down_xfermask && + ata_down_xfermask_limit(dev, tries[dev->devno] == 1)) + tries[dev->devno] = 0; + } - return 0; + if (!tries[dev->devno]) { + ata_down_xfermask_limit(dev, 1); + ata_dev_disable(dev); + } -err_out_disable: - ap->ops->port_disable(ap); - return -1; + goto retry; } /** @@ -1440,7 +1596,7 @@ err_out_disable: void ata_port_probe(struct ata_port *ap) { - ap->flags &= ~ATA_FLAG_PORT_DISABLED; + ap->flags &= ~ATA_FLAG_DISABLED; } /** @@ -1454,27 +1610,21 @@ void ata_port_probe(struct ata_port *ap) */ static void sata_print_link_status(struct ata_port *ap) { - u32 sstatus, tmp; - const char *speed; + u32 sstatus, scontrol, tmp; - if (!ap->ops->scr_read) + if (sata_scr_read(ap, SCR_STATUS, &sstatus)) return; + sata_scr_read(ap, SCR_CONTROL, &scontrol); - sstatus = scr_read(ap, SCR_STATUS); - - if (sata_dev_present(ap)) { + if (ata_port_online(ap)) { tmp = (sstatus >> 4) & 0xf; - if (tmp & (1 << 0)) - speed = "1.5"; - else if (tmp & (1 << 1)) - speed = "3.0"; - else - speed = ""; - printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n", - ap->id, speed, sstatus); + ata_port_printk(ap, KERN_INFO, + "SATA link up %s (SStatus %X SControl %X)\n", + sata_spd_string(tmp), sstatus, scontrol); } else { - printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n", - ap->id, sstatus); + ata_port_printk(ap, KERN_INFO, + "SATA link down (SStatus %X SControl %X)\n", + sstatus, scontrol); } } @@ -1497,17 +1647,18 @@ void __sata_phy_reset(struct ata_port *a if (ap->flags & ATA_FLAG_SATA_RESET) { /* issue phy wake/reset */ - scr_write_flush(ap, SCR_CONTROL, 0x301); + sata_scr_write_flush(ap, SCR_CONTROL, 0x301); /* Couldn't find anything in SATA I/II specs, but * AHCI-1.1 10.4.2 says at least 1 ms. */ mdelay(1); } - scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */ + /* phy wake/clear reset */ + sata_scr_write_flush(ap, SCR_CONTROL, 0x300); /* wait for phy to become ready, if necessary */ do { msleep(200); - sstatus = scr_read(ap, SCR_STATUS); + sata_scr_read(ap, SCR_STATUS, &sstatus); if ((sstatus & 0xf) != 1) break; } while (time_before(jiffies, timeout)); @@ -1516,12 +1667,12 @@ void __sata_phy_reset(struct ata_port *a sata_print_link_status(ap); /* TODO: phy layer with polling, timeouts, etc. */ - if (sata_dev_present(ap)) + if (!ata_port_offline(ap)) ata_port_probe(ap); else ata_port_disable(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) + if (ap->flags & ATA_FLAG_DISABLED) return; if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { @@ -1546,24 +1697,24 @@ void __sata_phy_reset(struct ata_port *a void sata_phy_reset(struct ata_port *ap) { __sata_phy_reset(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) + if (ap->flags & ATA_FLAG_DISABLED) return; ata_bus_reset(ap); } /** * ata_dev_pair - return other device on cable - * @ap: port * @adev: device * * Obtain the other device on the same cable, or if none is * present NULL is returned */ -struct ata_device *ata_dev_pair(struct ata_port *ap, struct ata_device *adev) +struct ata_device *ata_dev_pair(struct ata_device *adev) { + struct ata_port *ap = adev->ap; struct ata_device *pair = &ap->device[1 - adev->devno]; - if (!ata_dev_present(pair)) + if (!ata_dev_enabled(pair)) return NULL; return pair; } @@ -1585,7 +1736,122 @@ void ata_port_disable(struct ata_port *a { ap->device[0].class = ATA_DEV_NONE; ap->device[1].class = ATA_DEV_NONE; - ap->flags |= ATA_FLAG_PORT_DISABLED; + ap->flags |= ATA_FLAG_DISABLED; +} + +/** + * sata_down_spd_limit - adjust SATA spd limit downward + * @ap: Port to adjust SATA spd limit for + * + * Adjust SATA spd limit of @ap downward. Note that this + * function only adjusts the limit. The change must be applied + * using sata_set_spd(). + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 0 on success, negative errno on failure + */ +int sata_down_spd_limit(struct ata_port *ap) +{ + u32 sstatus, spd, mask; + int rc, highbit; + + rc = sata_scr_read(ap, SCR_STATUS, &sstatus); + if (rc) + return rc; + + mask = ap->sata_spd_limit; + if (mask <= 1) + return -EINVAL; + highbit = fls(mask) - 1; + mask &= ~(1 << highbit); + + spd = (sstatus >> 4) & 0xf; + if (spd <= 1) + return -EINVAL; + spd--; + mask &= (1 << spd) - 1; + if (!mask) + return -EINVAL; + + ap->sata_spd_limit = mask; + + ata_port_printk(ap, KERN_WARNING, "limiting SATA link speed to %s\n", + sata_spd_string(fls(mask))); + + return 0; +} + +static int __sata_set_spd_needed(struct ata_port *ap, u32 *scontrol) +{ + u32 spd, limit; + + if (ap->sata_spd_limit == UINT_MAX) + limit = 0; + else + limit = fls(ap->sata_spd_limit); + + spd = (*scontrol >> 4) & 0xf; + *scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4); + + return spd != limit; +} + +/** + * sata_set_spd_needed - is SATA spd configuration needed + * @ap: Port in question + * + * Test whether the spd limit in SControl matches + * @ap->sata_spd_limit. This function is used to determine + * whether hardreset is necessary to apply SATA spd + * configuration. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 1 if SATA spd configuration is needed, 0 otherwise. + */ +int sata_set_spd_needed(struct ata_port *ap) +{ + u32 scontrol; + + if (sata_scr_read(ap, SCR_CONTROL, &scontrol)) + return 0; + + return __sata_set_spd_needed(ap, &scontrol); +} + +/** + * sata_set_spd - set SATA spd according to spd limit + * @ap: Port to set SATA spd for + * + * Set SATA spd of @ap according to sata_spd_limit. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 0 if spd doesn't need to be changed, 1 if spd has been + * changed. Negative errno if SCR registers are inaccessible. + */ +int sata_set_spd(struct ata_port *ap) +{ + u32 scontrol; + int rc; + + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; + + if (!__sata_set_spd_needed(ap, &scontrol)) + return 0; + + if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) + return rc; + + return 1; } /* @@ -1736,151 +2002,196 @@ int ata_timing_compute(struct ata_device return 0; } -static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) +/** + * ata_down_xfermask_limit - adjust dev xfer masks downward + * @dev: Device to adjust xfer masks + * @force_pio0: Force PIO0 + * + * Adjust xfer masks of @dev downward. Note that this function + * does not apply the change. Invoking ata_set_mode() afterwards + * will apply the limit. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 0 on success, negative errno on failure + */ +int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0) +{ + unsigned long xfer_mask; + int highbit; + + xfer_mask = ata_pack_xfermask(dev->pio_mask, dev->mwdma_mask, + dev->udma_mask); + + if (!xfer_mask) + goto fail; + /* don't gear down to MWDMA from UDMA, go directly to PIO */ + if (xfer_mask & ATA_MASK_UDMA) + xfer_mask &= ~ATA_MASK_MWDMA; + + highbit = fls(xfer_mask) - 1; + xfer_mask &= ~(1 << highbit); + if (force_pio0) + xfer_mask &= 1 << ATA_SHIFT_PIO; + if (!xfer_mask) + goto fail; + + ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, + &dev->udma_mask); + + ata_dev_printk(dev, KERN_WARNING, "limiting speed to %s\n", + ata_mode_string(xfer_mask)); + + return 0; + + fail: + return -EINVAL; +} + +static int ata_dev_set_mode(struct ata_device *dev) { unsigned int err_mask; int rc; + dev->flags &= ~ATA_DFLAG_PIO; if (dev->xfer_shift == ATA_SHIFT_PIO) dev->flags |= ATA_DFLAG_PIO; - err_mask = ata_dev_set_xfermode(ap, dev); + err_mask = ata_dev_set_xfermode(dev); if (err_mask) { - printk(KERN_ERR - "ata%u: failed to set xfermode (err_mask=0x%x)\n", - ap->id, err_mask); + ata_dev_printk(dev, KERN_ERR, "failed to set xfermode " + "(err_mask=0x%x)\n", err_mask); return -EIO; } - rc = ata_dev_revalidate(ap, dev, 0); - if (rc) { - printk(KERN_ERR - "ata%u: failed to revalidate after set xfermode\n", - ap->id); + rc = ata_dev_revalidate(dev, 0); + if (rc) return rc; - } DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n", dev->xfer_shift, (int)dev->xfer_mode); - printk(KERN_INFO "ata%u: dev %u configured for %s\n", - ap->id, dev->devno, - ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode))); + ata_dev_printk(dev, KERN_INFO, "configured for %s\n", + ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode))); return 0; } -static int ata_host_set_pio(struct ata_port *ap) -{ - int i; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - - if (!ata_dev_present(dev)) - continue; - - if (!dev->pio_mode) { - printk(KERN_WARNING "ata%u: no PIO support for device %d.\n", ap->id, i); - return -1; - } - - dev->xfer_mode = dev->pio_mode; - dev->xfer_shift = ATA_SHIFT_PIO; - if (ap->ops->set_piomode) - ap->ops->set_piomode(ap, dev); - } - - return 0; -} - -static void ata_host_set_dma(struct ata_port *ap) -{ - int i; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - - if (!ata_dev_present(dev) || !dev->dma_mode) - continue; - - dev->xfer_mode = dev->dma_mode; - dev->xfer_shift = ata_xfer_mode2shift(dev->dma_mode); - if (ap->ops->set_dmamode) - ap->ops->set_dmamode(ap, dev); - } -} - /** * ata_set_mode - Program timings and issue SET FEATURES - XFER * @ap: port on which timings will be programmed + * @r_failed_dev: out paramter for failed device * - * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). + * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If + * ata_set_mode() fails, pointer to the failing device is + * returned in @r_failed_dev. * * LOCKING: * PCI/etc. bus probe sem. + * + * RETURNS: + * 0 on success, negative errno otherwise */ -static void ata_set_mode(struct ata_port *ap) +int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) { - int i, rc, used_dma = 0; + struct ata_device *dev; + int i, rc = 0, used_dma = 0, found = 0; + + /* has private set_mode? */ + if (ap->ops->set_mode) { + /* FIXME: make ->set_mode handle no device case and + * return error code and failing device on failure. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + if (ata_dev_enabled(&ap->device[i])) { + ap->ops->set_mode(ap); + break; + } + } + return 0; + } /* step 1: calculate xfer_mask */ for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; unsigned int pio_mask, dma_mask; - if (!ata_dev_present(dev)) - continue; + dev = &ap->device[i]; - ata_dev_xfermask(ap, dev); + if (!ata_dev_enabled(dev)) + continue; - /* TODO: let LLDD filter dev->*_mask here */ + ata_dev_xfermask(dev); pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0); dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); dev->pio_mode = ata_xfer_mask2mode(pio_mask); dev->dma_mode = ata_xfer_mask2mode(dma_mask); + found = 1; if (dev->dma_mode) used_dma = 1; } + if (!found) + goto out; /* step 2: always set host PIO timings */ - rc = ata_host_set_pio(ap); - if (rc) - goto err_out; + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + if (!ata_dev_enabled(dev)) + continue; + + if (!dev->pio_mode) { + ata_dev_printk(dev, KERN_WARNING, "no PIO support\n"); + rc = -EINVAL; + goto out; + } + + dev->xfer_mode = dev->pio_mode; + dev->xfer_shift = ATA_SHIFT_PIO; + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, dev); + } /* step 3: set host DMA timings */ - ata_host_set_dma(ap); + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + + if (!ata_dev_enabled(dev) || !dev->dma_mode) + continue; + + dev->xfer_mode = dev->dma_mode; + dev->xfer_shift = ata_xfer_mode2shift(dev->dma_mode); + if (ap->ops->set_dmamode) + ap->ops->set_dmamode(ap, dev); + } /* step 4: update devices' xfer mode */ for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; + dev = &ap->device[i]; - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) continue; - if (ata_dev_set_mode(ap, dev)) - goto err_out; + rc = ata_dev_set_mode(dev); + if (rc) + goto out; } - /* - * Record simplex status. If we selected DMA then the other - * host channels are not permitted to do so. + /* Record simplex status. If we selected DMA then the other + * host channels are not permitted to do so. */ - if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX)) ap->host_set->simplex_claimed = 1; - /* - * Chip specific finalisation - */ + /* step5: chip specific finalisation */ if (ap->ops->post_set_mode) ap->ops->post_set_mode(ap); - return; - -err_out: - ata_port_disable(ap); + out: + if (rc) + *r_failed_dev = dev; + return rc; } /** @@ -1930,8 +2241,8 @@ unsigned int ata_busy_sleep (struct ata_ } if (status & ATA_BUSY) - printk(KERN_WARNING "ata%u is slow to respond, " - "please be patient\n", ap->id); + ata_port_printk(ap, KERN_WARNING, + "port is slow to respond, please be patient\n"); timeout = timer_start + tmout; while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) { @@ -1940,8 +2251,8 @@ unsigned int ata_busy_sleep (struct ata_ } if (status & ATA_BUSY) { - printk(KERN_ERR "ata%u failed to respond (%lu secs)\n", - ap->id, tmout / HZ); + ata_port_printk(ap, KERN_ERR, "port failed to respond " + "(%lu secs)\n", tmout / HZ); return 1; } @@ -2033,8 +2344,10 @@ static unsigned int ata_bus_softreset(st * the bus shows 0xFF because the odd clown forgets the D7 * pulldown resistor. */ - if (ata_check_status(ap) == 0xFF) + if (ata_check_status(ap) == 0xFF) { + ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n"); return AC_ERR_OTHER; + } ata_bus_post_reset(ap, devmask); @@ -2058,7 +2371,7 @@ static unsigned int ata_bus_softreset(st * Obtains host_set lock. * * SIDE EFFECTS: - * Sets ATA_FLAG_PORT_DISABLED if bus reset fails. + * Sets ATA_FLAG_DISABLED if bus reset fails. */ void ata_bus_reset(struct ata_port *ap) @@ -2126,60 +2439,195 @@ void ata_bus_reset(struct ata_port *ap) return; err_out: - printk(KERN_ERR "ata%u: disabling port\n", ap->id); + ata_port_printk(ap, KERN_ERR, "disabling port\n"); ap->ops->port_disable(ap); DPRINTK("EXIT\n"); } -static int sata_phy_resume(struct ata_port *ap) +/** + * sata_phy_debounce - debounce SATA phy status + * @ap: ATA port to debounce SATA phy status for + * @params: timing parameters { interval, duratinon, timeout } in msec + * + * Make sure SStatus of @ap reaches stable state, determined by + * holding the same value where DET is not 1 for @duration polled + * every @interval, before @timeout. Timeout constraints the + * beginning of the stable state. Because, after hot unplugging, + * DET gets stuck at 1 on some controllers, this functions waits + * until timeout then returns 0 if DET is stable at 1. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno on failure. + */ +int sata_phy_debounce(struct ata_port *ap, const unsigned long *params) { - unsigned long timeout = jiffies + (HZ * 5); - u32 sstatus; + unsigned long interval_msec = params[0]; + unsigned long duration = params[1] * HZ / 1000; + unsigned long timeout = jiffies + params[2] * HZ / 1000; + unsigned long last_jiffies; + u32 last, cur; + int rc; - scr_write_flush(ap, SCR_CONTROL, 0x300); + if ((rc = sata_scr_read(ap, SCR_STATUS, &cur))) + return rc; + cur &= 0xf; - /* Wait for phy to become ready, if necessary. */ - do { - msleep(200); - sstatus = scr_read(ap, SCR_STATUS); - if ((sstatus & 0xf) != 1) - return 0; - } while (time_before(jiffies, timeout)); + last = cur; + last_jiffies = jiffies; - return -1; + while (1) { + msleep(interval_msec); + if ((rc = sata_scr_read(ap, SCR_STATUS, &cur))) + return rc; + cur &= 0xf; + + /* DET stable? */ + if (cur == last) { + if (cur == 1 && time_before(jiffies, timeout)) + continue; + if (time_after(jiffies, last_jiffies + duration)) + return 0; + continue; + } + + /* unstable, start over */ + last = cur; + last_jiffies = jiffies; + + /* check timeout */ + if (time_after(jiffies, timeout)) + return -EBUSY; + } } /** - * ata_std_probeinit - initialize probing - * @ap: port to be probed + * sata_phy_resume - resume SATA phy + * @ap: ATA port to resume SATA phy for + * @params: timing parameters { interval, duratinon, timeout } in msec * - * @ap is about to be probed. Initialize it. This function is - * to be used as standard callback for ata_drive_probe_reset(). + * Resume SATA phy of @ap and debounce it. * - * NOTE!!! Do not use this function as probeinit if a low level - * driver implements only hardreset. Just pass NULL as probeinit - * in that case. Using this function is probably okay but doing - * so makes reset sequence different from the original - * ->phy_reset implementation and Jeff nervous. :-P + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno on failure. */ -void ata_std_probeinit(struct ata_port *ap) +int sata_phy_resume(struct ata_port *ap, const unsigned long *params) { - if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { - sata_phy_resume(ap); - if (sata_dev_present(ap)) - ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + u32 scontrol; + int rc; + + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; + + scontrol = (scontrol & 0x0f0) | 0x300; + + if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) + return rc; + + /* Some PHYs react badly if SStatus is pounded immediately + * after resuming. Delay 200ms before debouncing. + */ + msleep(200); + + return sata_phy_debounce(ap, params); +} + +static void ata_wait_spinup(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + unsigned long end, secs; + int rc; + + /* first, debounce phy if SATA */ + if (ap->cbl == ATA_CBL_SATA) { + rc = sata_phy_debounce(ap, sata_deb_timing_eh); + + /* if debounced successfully and offline, no need to wait */ + if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap)) + return; } + + /* okay, let's give the drive time to spin up */ + end = ehc->i.hotplug_timestamp + ATA_SPINUP_WAIT * HZ / 1000; + secs = ((end - jiffies) + HZ - 1) / HZ; + + if (time_after(jiffies, end)) + return; + + if (secs > 5) + ata_port_printk(ap, KERN_INFO, "waiting for device to spin up " + "(%lu secs)\n", secs); + + schedule_timeout_uninterruptible(end - jiffies); +} + +/** + * ata_std_prereset - prepare for reset + * @ap: ATA port to be reset + * + * @ap is about to be reset. Initialize it. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int ata_std_prereset(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + const unsigned long *timing; + int rc; + + /* hotplug? */ + if (ehc->i.flags & ATA_EHI_HOTPLUGGED) { + if (ap->flags & ATA_FLAG_HRST_TO_RESUME) + ehc->i.action |= ATA_EH_HARDRESET; + if (ap->flags & ATA_FLAG_SKIP_D2H_BSY) + ata_wait_spinup(ap); + } + + /* if we're about to do hardreset, nothing more to do */ + if (ehc->i.action & ATA_EH_HARDRESET) + return 0; + + /* if SATA, resume phy */ + if (ap->cbl == ATA_CBL_SATA) { + if (ap->flags & ATA_FLAG_LOADING) + timing = sata_deb_timing_boot; + else + timing = sata_deb_timing_eh; + + rc = sata_phy_resume(ap, timing); + if (rc && rc != -EOPNOTSUPP) { + /* phy resume failed */ + ata_port_printk(ap, KERN_WARNING, "failed to resume " + "link for reset (errno=%d)\n", rc); + return rc; + } + } + + /* Wait for !BSY if the controller can wait for the first D2H + * Reg FIS and we don't know that no device is attached. + */ + if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap)) + ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); + + return 0; } /** * ata_std_softreset - reset host port via ATA SRST * @ap: port to reset - * @verbose: fail verbosely * @classes: resulting classes of attached devices * - * Reset host port using ATA SRST. This function is to be used - * as standard callback for ata_drive_*_reset() functions. + * Reset host port using ATA SRST. * * LOCKING: * Kernel thread context (may sleep) @@ -2187,7 +2635,7 @@ void ata_std_probeinit(struct ata_port * * RETURNS: * 0 on success, -errno otherwise. */ -int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) +int ata_std_softreset(struct ata_port *ap, unsigned int *classes) { unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; unsigned int devmask = 0, err_mask; @@ -2195,7 +2643,7 @@ int ata_std_softreset(struct ata_port *a DPRINTK("ENTER\n"); - if (ap->ops->scr_read && !sata_dev_present(ap)) { + if (ata_port_offline(ap)) { classes[0] = ATA_DEV_NONE; goto out; } @@ -2213,11 +2661,7 @@ int ata_std_softreset(struct ata_port *a DPRINTK("about to softreset, devmask=%x\n", devmask); err_mask = ata_bus_softreset(ap, devmask); if (err_mask) { - if (verbose) - printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n", - ap->id, err_mask); - else - DPRINTK("EXIT, softreset failed (err_mask=0x%x)\n", + ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n", err_mask); return -EIO; } @@ -2235,12 +2679,9 @@ int ata_std_softreset(struct ata_port *a /** * sata_std_hardreset - reset host port via SATA phy reset * @ap: port to reset - * @verbose: fail verbosely * @class: resulting class of attached device * * SATA phy-reset host port using DET bits of SControl register. - * This function is to be used as standard callback for - * ata_drive_*_reset(). * * LOCKING: * Kernel thread context (may sleep) @@ -2248,35 +2689,57 @@ int ata_std_softreset(struct ata_port *a * RETURNS: * 0 on success, -errno otherwise. */ -int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) +int sata_std_hardreset(struct ata_port *ap, unsigned int *class) { + u32 scontrol; + int rc; + DPRINTK("ENTER\n"); - /* Issue phy wake/reset */ - scr_write_flush(ap, SCR_CONTROL, 0x301); + if (sata_set_spd_needed(ap)) { + /* SATA spec says nothing about how to reconfigure + * spd. To be on the safe side, turn off phy during + * reconfiguration. This works for at least ICH7 AHCI + * and Sil3124. + */ + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; + + scontrol = (scontrol & 0x0f0) | 0x302; - /* - * Couldn't find anything in SATA I/II specs, but AHCI-1.1 + if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) + return rc; + + sata_set_spd(ap); + } + + /* issue phy wake/reset */ + if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) + return rc; + + scontrol = (scontrol & 0x0f0) | 0x301; + + if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol))) + return rc; + + /* Couldn't find anything in SATA I/II specs, but AHCI-1.1 * 10.4.2 says at least 1 ms. */ msleep(1); - /* Bring phy back */ - sata_phy_resume(ap); + /* bring phy back */ + sata_phy_resume(ap, sata_deb_timing_eh); /* TODO: phy layer with polling, timeouts, etc. */ - if (!sata_dev_present(ap)) { + if (ata_port_offline(ap)) { *class = ATA_DEV_NONE; DPRINTK("EXIT, link offline\n"); return 0; } if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - if (verbose) - printk(KERN_ERR "ata%u: COMRESET failed " - "(device not ready)\n", ap->id); - else - DPRINTK("EXIT, device not ready\n"); + ata_port_printk(ap, KERN_ERR, + "COMRESET failed (device not ready)\n"); return -EIO; } @@ -2297,27 +2760,28 @@ int sata_std_hardreset(struct ata_port * * the device might have been reset more than once using * different reset methods before postreset is invoked. * - * This function is to be used as standard callback for - * ata_drive_*_reset(). - * * LOCKING: * Kernel thread context (may sleep) */ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) { - DPRINTK("ENTER\n"); + u32 serror; - /* set cable type if it isn't already set */ - if (ap->cbl == ATA_CBL_NONE && ap->flags & ATA_FLAG_SATA) - ap->cbl = ATA_CBL_SATA; + DPRINTK("ENTER\n"); /* print link status */ - if (ap->cbl == ATA_CBL_SATA) - sata_print_link_status(ap); + sata_print_link_status(ap); + + /* clear SError */ + if (sata_scr_read(ap, SCR_ERROR, &serror) == 0) + sata_scr_write(ap, SCR_ERROR, serror); /* re-enable interrupts */ - if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ - ata_irq_on(ap); + if (!ap->ops->error_handler) { + /* FIXME: hack. create a hook instead */ + if (ap->ioaddr.ctl_addr) + ata_irq_on(ap); + } /* is double-select really necessary? */ if (classes[0] != ATA_DEV_NONE) @@ -2343,126 +2807,7 @@ void ata_std_postreset(struct ata_port * } /** - * ata_std_probe_reset - standard probe reset method - * @ap: prot to perform probe-reset - * @classes: resulting classes of attached devices - * - * The stock off-the-shelf ->probe_reset method. - * - * LOCKING: - * Kernel thread context (may sleep) - * - * RETURNS: - * 0 on success, -errno otherwise. - */ -int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) -{ - ata_reset_fn_t hardreset; - - hardreset = NULL; - if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) - hardreset = sata_std_hardreset; - - return ata_drive_probe_reset(ap, ata_std_probeinit, - ata_std_softreset, hardreset, - ata_std_postreset, classes); -} - -static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset, - ata_postreset_fn_t postreset, - unsigned int *classes) -{ - int i, rc; - - for (i = 0; i < ATA_MAX_DEVICES; i++) - classes[i] = ATA_DEV_UNKNOWN; - - rc = reset(ap, 0, classes); - if (rc) - return rc; - - /* If any class isn't ATA_DEV_UNKNOWN, consider classification - * is complete and convert all ATA_DEV_UNKNOWN to - * ATA_DEV_NONE. - */ - for (i = 0; i < ATA_MAX_DEVICES; i++) - if (classes[i] != ATA_DEV_UNKNOWN) - break; - - if (i < ATA_MAX_DEVICES) - for (i = 0; i < ATA_MAX_DEVICES; i++) - if (classes[i] == ATA_DEV_UNKNOWN) - classes[i] = ATA_DEV_NONE; - - if (postreset) - postreset(ap, classes); - - return classes[0] != ATA_DEV_UNKNOWN ? 0 : -ENODEV; -} - -/** - * ata_drive_probe_reset - Perform probe reset with given methods - * @ap: port to reset - * @probeinit: probeinit method (can be NULL) - * @softreset: softreset method (can be NULL) - * @hardreset: hardreset method (can be NULL) - * @postreset: postreset method (can be NULL) - * @classes: resulting classes of attached devices - * - * Reset the specified port and classify attached devices using - * given methods. This function prefers softreset but tries all - * possible reset sequences to reset and classify devices. This - * function is intended to be used for constructing ->probe_reset - * callback by low level drivers. - * - * Reset methods should follow the following rules. - * - * - Return 0 on sucess, -errno on failure. - * - If classification is supported, fill classes[] with - * recognized class codes. - * - If classification is not supported, leave classes[] alone. - * - If verbose is non-zero, print error message on failure; - * otherwise, shut up. - * - * LOCKING: - * Kernel thread context (may sleep) - * - * RETURNS: - * 0 on success, -EINVAL if no reset method is avaliable, -ENODEV - * if classification fails, and any error code from reset - * methods. - */ -int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, - ata_reset_fn_t softreset, ata_reset_fn_t hardreset, - ata_postreset_fn_t postreset, unsigned int *classes) -{ - int rc = -EINVAL; - - if (probeinit) - probeinit(ap); - - if (softreset) { - rc = do_probe_reset(ap, softreset, postreset, classes); - if (rc == 0) - return 0; - } - - if (!hardreset) - return rc; - - rc = do_probe_reset(ap, hardreset, postreset, classes); - if (rc == 0 || rc != -ENODEV) - return rc; - - if (softreset) - rc = do_probe_reset(ap, softreset, postreset, classes); - - return rc; -} - -/** * ata_dev_same_device - Determine whether new ID matches configured device - * @ap: port on which the device to compare against resides * @dev: device to compare against * @new_class: class of the new device * @new_id: IDENTIFY page of the new device @@ -2477,17 +2822,16 @@ int ata_drive_probe_reset(struct ata_por * RETURNS: * 1 if @dev matches @new_class and @new_id, 0 otherwise. */ -static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev, - unsigned int new_class, const u16 *new_id) +static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class, + const u16 *new_id) { const u16 *old_id = dev->id; unsigned char model[2][41], serial[2][21]; u64 new_n_sectors; if (dev->class != new_class) { - printk(KERN_INFO - "ata%u: dev %u class mismatch %d != %d\n", - ap->id, dev->devno, dev->class, new_class); + ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n", + dev->class, new_class); return 0; } @@ -2498,24 +2842,22 @@ static int ata_dev_same_device(struct at new_n_sectors = ata_id_n_sectors(new_id); if (strcmp(model[0], model[1])) { - printk(KERN_INFO - "ata%u: dev %u model number mismatch '%s' != '%s'\n", - ap->id, dev->devno, model[0], model[1]); + ata_dev_printk(dev, KERN_INFO, "model number mismatch " + "'%s' != '%s'\n", model[0], model[1]); return 0; } if (strcmp(serial[0], serial[1])) { - printk(KERN_INFO - "ata%u: dev %u serial number mismatch '%s' != '%s'\n", - ap->id, dev->devno, serial[0], serial[1]); + ata_dev_printk(dev, KERN_INFO, "serial number mismatch " + "'%s' != '%s'\n", serial[0], serial[1]); return 0; } if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) { - printk(KERN_INFO - "ata%u: dev %u n_sectors mismatch %llu != %llu\n", - ap->id, dev->devno, (unsigned long long)dev->n_sectors, - (unsigned long long)new_n_sectors); + ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch " + "%llu != %llu\n", + (unsigned long long)dev->n_sectors, + (unsigned long long)new_n_sectors); return 0; } @@ -2524,7 +2866,6 @@ static int ata_dev_same_device(struct at /** * ata_dev_revalidate - Revalidate ATA device - * @ap: port on which the device to revalidate resides * @dev: device to revalidate * @post_reset: is this revalidation after reset? * @@ -2537,40 +2878,37 @@ static int ata_dev_same_device(struct at * RETURNS: * 0 on success, negative errno otherwise */ -int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, - int post_reset) +int ata_dev_revalidate(struct ata_device *dev, int post_reset) { - unsigned int class; - u16 *id; + unsigned int class = dev->class; + u16 *id = (void *)dev->ap->sector_buf; int rc; - if (!ata_dev_present(dev)) - return -ENODEV; - - class = dev->class; - id = NULL; + if (!ata_dev_enabled(dev)) { + rc = -ENODEV; + goto fail; + } - /* allocate & read ID data */ - rc = ata_dev_read_id(ap, dev, &class, post_reset, &id); + /* read ID data */ + rc = ata_dev_read_id(dev, &class, post_reset, id); if (rc) goto fail; /* is the device still there? */ - if (!ata_dev_same_device(ap, dev, class, id)) { + if (!ata_dev_same_device(dev, class, id)) { rc = -ENODEV; goto fail; } - kfree(dev->id); - dev->id = id; + memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS); /* configure device according to the new ID */ - return ata_dev_configure(ap, dev, 0); + rc = ata_dev_configure(dev, 0); + if (rc == 0) + return 0; fail: - printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", - ap->id, dev->devno, rc); - kfree(id); + ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc); return rc; } @@ -2626,6 +2964,14 @@ static int ata_dma_blacklisted(const str unsigned int nlen, rlen; int i; + /* We don't support polling DMA. + * DMA blacklist those ATAPI devices with CDB-intr (and use PIO) + * if the LLDD handles only interrupts in the HSM_ST_LAST state. + */ + if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) && + (dev->flags & ATA_DFLAG_CDB_INTR)) + return 1; + ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); ata_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS, @@ -2646,7 +2992,6 @@ static int ata_dma_blacklisted(const str /** * ata_dev_xfermask - Compute supported xfermask of the given device - * @ap: Port on which the device to compute xfermask for resides * @dev: Device to compute xfermask for * * Compute supported xfermask of @dev and store it in @@ -2661,49 +3006,61 @@ static int ata_dma_blacklisted(const str * LOCKING: * None. */ -static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) +static void ata_dev_xfermask(struct ata_device *dev) { + struct ata_port *ap = dev->ap; struct ata_host_set *hs = ap->host_set; unsigned long xfer_mask; int i; - xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, - ap->udma_mask); + xfer_mask = ata_pack_xfermask(ap->pio_mask, + ap->mwdma_mask, ap->udma_mask); + + /* Apply cable rule here. Don't apply it early because when + * we handle hot plug the cable type can itself change. + */ + if (ap->cbl == ATA_CBL_PATA40) + xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); /* FIXME: Use port-wide xfermask for now */ for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *d = &ap->device[i]; - if (!ata_dev_present(d)) + + if (ata_dev_absent(d)) + continue; + + if (ata_dev_disabled(d)) { + /* to avoid violating device selection timing */ + xfer_mask &= ata_pack_xfermask(d->pio_mask, + UINT_MAX, UINT_MAX); continue; - xfer_mask &= ata_pack_xfermask(d->pio_mask, d->mwdma_mask, - d->udma_mask); + } + + xfer_mask &= ata_pack_xfermask(d->pio_mask, + d->mwdma_mask, d->udma_mask); xfer_mask &= ata_id_xfermask(d->id); if (ata_dma_blacklisted(d)) xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); - /* Apply cable rule here. Don't apply it early because when - we handle hot plug the cable type can itself change */ - if (ap->cbl == ATA_CBL_PATA40) - xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); } if (ata_dma_blacklisted(dev)) - printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " - "disabling DMA\n", ap->id, dev->devno); + ata_dev_printk(dev, KERN_WARNING, + "device is on DMA blacklist, disabling DMA\n"); if (hs->flags & ATA_HOST_SIMPLEX) { if (hs->simplex_claimed) xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); } + if (ap->ops->mode_filter) xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask); - ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, - &dev->udma_mask); + ata_unpack_xfermask(xfer_mask, &dev->pio_mask, + &dev->mwdma_mask, &dev->udma_mask); } /** * ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command - * @ap: Port associated with device @dev * @dev: Device to which command will be sent * * Issue SET FEATURES - XFER MODE command to device @dev @@ -2716,8 +3073,7 @@ static void ata_dev_xfermask(struct ata_ * 0 on success, AC_ERR_* mask otherwise. */ -static unsigned int ata_dev_set_xfermode(struct ata_port *ap, - struct ata_device *dev) +static unsigned int ata_dev_set_xfermode(struct ata_device *dev) { struct ata_taskfile tf; unsigned int err_mask; @@ -2725,14 +3081,14 @@ static unsigned int ata_dev_set_xfermode /* set up set-features taskfile */ DPRINTK("set features - xfer mode\n"); - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); tf.command = ATA_CMD_SET_FEATURES; tf.feature = SETFEATURES_XFER; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; tf.nsect = dev->xfer_mode; - err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; @@ -2740,7 +3096,6 @@ static unsigned int ata_dev_set_xfermode /** * ata_dev_init_params - Issue INIT DEV PARAMS command - * @ap: Port associated with device @dev * @dev: Device to which command will be sent * @heads: Number of heads (taskfile parameter) * @sectors: Number of sectors (taskfile parameter) @@ -2751,11 +3106,8 @@ static unsigned int ata_dev_set_xfermode * RETURNS: * 0 on success, AC_ERR_* mask otherwise. */ - -static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev, - u16 heads, - u16 sectors) +static unsigned int ata_dev_init_params(struct ata_device *dev, + u16 heads, u16 sectors) { struct ata_taskfile tf; unsigned int err_mask; @@ -2767,14 +3119,14 @@ static unsigned int ata_dev_init_params( /* set up init dev params taskfile */ DPRINTK("init dev params \n"); - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); tf.command = ATA_CMD_INIT_DEV_PARAMS; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; tf.nsect = sectors; tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */ - err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; @@ -2957,6 +3309,7 @@ void ata_sg_init_one(struct ata_queued_c qc->n_elem = 1; qc->orig_n_elem = 1; qc->buf_virt = buf; + qc->nbytes = buflen; sg = qc->__sg; sg_init_one(sg, buf, buflen); @@ -3140,134 +3493,6 @@ skip_map: } /** - * ata_poll_qc_complete - turn irq back on and finish qc - * @qc: Command to complete - * @err_mask: ATA status register content - * - * LOCKING: - * None. (grabs host lock) - */ - -void ata_poll_qc_complete(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - unsigned long flags; - - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_NOINTR; - ata_irq_on(ap); - ata_qc_complete(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); -} - -/** - * ata_pio_poll - poll using PIO, depending on current state - * @ap: the target ata_port - * - * LOCKING: - * None. (executing in kernel thread context) - * - * RETURNS: - * timeout value to use - */ - -static unsigned long ata_pio_poll(struct ata_port *ap) -{ - struct ata_queued_cmd *qc; - u8 status; - unsigned int poll_state = HSM_ST_UNKNOWN; - unsigned int reg_state = HSM_ST_UNKNOWN; - - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - - switch (ap->hsm_task_state) { - case HSM_ST: - case HSM_ST_POLL: - poll_state = HSM_ST_POLL; - reg_state = HSM_ST; - break; - case HSM_ST_LAST: - case HSM_ST_LAST_POLL: - poll_state = HSM_ST_LAST_POLL; - reg_state = HSM_ST_LAST; - break; - default: - BUG(); - break; - } - - status = ata_chk_status(ap); - if (status & ATA_BUSY) { - if (time_after(jiffies, ap->pio_task_timeout)) { - qc->err_mask |= AC_ERR_TIMEOUT; - ap->hsm_task_state = HSM_ST_TMOUT; - return 0; - } - ap->hsm_task_state = poll_state; - return ATA_SHORT_PAUSE; - } - - ap->hsm_task_state = reg_state; - return 0; -} - -/** - * ata_pio_complete - check if drive is busy or idle - * @ap: the target ata_port - * - * LOCKING: - * None. (executing in kernel thread context) - * - * RETURNS: - * Non-zero if qc completed, zero otherwise. - */ - -static int ata_pio_complete (struct ata_port *ap) -{ - struct ata_queued_cmd *qc; - u8 drv_stat; - - /* - * This is purely heuristic. This is a fast path. Sometimes when - * we enter, BSY will be cleared in a chk-status or two. If not, - * the drive is probably seeking or something. Snooze for a couple - * msecs, then chk-status again. If still busy, fall back to - * HSM_ST_POLL state. - */ - drv_stat = ata_busy_wait(ap, ATA_BUSY, 10); - if (drv_stat & ATA_BUSY) { - msleep(2); - drv_stat = ata_busy_wait(ap, ATA_BUSY, 10); - if (drv_stat & ATA_BUSY) { - ap->hsm_task_state = HSM_ST_LAST_POLL; - ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; - return 0; - } - } - - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - - drv_stat = ata_wait_idle(ap); - if (!ata_ok(drv_stat)) { - qc->err_mask |= __ac_err_mask(drv_stat); - ap->hsm_task_state = HSM_ST_ERR; - return 0; - } - - ap->hsm_task_state = HSM_ST_IDLE; - - WARN_ON(qc->err_mask); - ata_poll_qc_complete(qc); - - /* another command may start at this point */ - - return 1; -} - - -/** * swap_buf_le16 - swap halves of 16-bit words in place * @buf: Buffer to swap * @buf_words: Number of 16-bit words in buffer. @@ -3291,7 +3516,7 @@ #endif /* __BIG_ENDIAN */ /** * ata_mmio_data_xfer - Transfer data by MMIO - * @ap: port to read/write + * @adev: device for this I/O * @buf: data buffer * @buflen: buffer length * @write_data: read/write @@ -3302,9 +3527,10 @@ #endif /* __BIG_ENDIAN */ * Inherited from caller. */ -static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, - unsigned int buflen, int write_data) +void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data) { + struct ata_port *ap = adev->ap; unsigned int i; unsigned int words = buflen >> 1; u16 *buf16 = (u16 *) buf; @@ -3336,7 +3562,7 @@ static void ata_mmio_data_xfer(struct at /** * ata_pio_data_xfer - Transfer data by PIO - * @ap: port to read/write + * @adev: device to target * @buf: data buffer * @buflen: buffer length * @write_data: read/write @@ -3347,9 +3573,10 @@ static void ata_mmio_data_xfer(struct at * Inherited from caller. */ -static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, - unsigned int buflen, int write_data) +void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data) { + struct ata_port *ap = adev->ap; unsigned int words = buflen >> 1; /* Transfer multiple of 2 bytes */ @@ -3374,38 +3601,29 @@ static void ata_pio_data_xfer(struct ata } /** - * ata_data_xfer - Transfer data from/to the data register. - * @ap: port to read/write + * ata_pio_data_xfer_noirq - Transfer data by PIO + * @adev: device to target * @buf: data buffer * @buflen: buffer length - * @do_write: read/write + * @write_data: read/write * - * Transfer data from/to the device data register. + * Transfer data from/to the device data register by PIO. Do the + * transfer with interrupts disabled. * * LOCKING: * Inherited from caller. */ -static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, - unsigned int buflen, int do_write) +void ata_pio_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, + unsigned int buflen, int write_data) { - /* Make the crap hardware pay the costs not the good stuff */ - if (unlikely(ap->flags & ATA_FLAG_IRQ_MASK)) { - unsigned long flags; - local_irq_save(flags); - if (ap->flags & ATA_FLAG_MMIO) - ata_mmio_data_xfer(ap, buf, buflen, do_write); - else - ata_pio_data_xfer(ap, buf, buflen, do_write); - local_irq_restore(flags); - } else { - if (ap->flags & ATA_FLAG_MMIO) - ata_mmio_data_xfer(ap, buf, buflen, do_write); - else - ata_pio_data_xfer(ap, buf, buflen, do_write); - } + unsigned long flags; + local_irq_save(flags); + ata_pio_data_xfer(adev, buf, buflen, write_data); + local_irq_restore(flags); } + /** * ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data. * @qc: Command on going @@ -3435,7 +3653,24 @@ static void ata_pio_sector(struct ata_qu page = nth_page(page, (offset >> PAGE_SHIFT)); offset %= PAGE_SIZE; - buf = kmap(page) + offset; + DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); + + if (PageHighMem(page)) { + unsigned long flags; + + /* FIXME: use a bounce buffer */ + local_irq_save(flags); + buf = kmap_atomic(page, KM_IRQ0); + + /* do the actual data transfer */ + ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write); + + kunmap_atomic(buf, KM_IRQ0); + local_irq_restore(flags); + } else { + buf = page_address(page); + ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write); + } qc->cursect++; qc->cursg_ofs++; @@ -3444,14 +3679,68 @@ static void ata_pio_sector(struct ata_qu qc->cursg++; qc->cursg_ofs = 0; } +} - DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); +/** + * ata_pio_sectors - Transfer one or many 512-byte sectors. + * @qc: Command on going + * + * Transfer one or many ATA_SECT_SIZE of data from/to the + * ATA device for the DRQ request. + * + * LOCKING: + * Inherited from caller. + */ + +static void ata_pio_sectors(struct ata_queued_cmd *qc) +{ + if (is_multi_taskfile(&qc->tf)) { + /* READ/WRITE MULTIPLE */ + unsigned int nsect; - /* do the actual data transfer */ - do_write = (qc->tf.flags & ATA_TFLAG_WRITE); - ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write); + WARN_ON(qc->dev->multi_count == 0); - kunmap(page); + nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count); + while (nsect--) + ata_pio_sector(qc); + } else + ata_pio_sector(qc); +} + +/** + * atapi_send_cdb - Write CDB bytes to hardware + * @ap: Port to which ATAPI device is attached. + * @qc: Taskfile currently active + * + * When device has indicated its readiness to accept + * a CDB, this function is called. Send the CDB. + * + * LOCKING: + * caller. + */ + +static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) +{ + /* send SCSI cdb */ + DPRINTK("send cdb\n"); + WARN_ON(qc->dev->cdb_len < 12); + + ap->ops->data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1); + ata_altstatus(ap); /* flush */ + + switch (qc->tf.protocol) { + case ATA_PROT_ATAPI: + ap->hsm_task_state = HSM_ST; + break; + case ATA_PROT_ATAPI_NODATA: + ap->hsm_task_state = HSM_ST_LAST; + break; + case ATA_PROT_ATAPI_DMA: + ap->hsm_task_state = HSM_ST_LAST; + /* initiate bmdma */ + ap->ops->bmdma_start(qc); + break; + } } /** @@ -3492,11 +3781,11 @@ next_sg: unsigned int i; if (words) /* warning if bytes > 1 */ - printk(KERN_WARNING "ata%u: %u bytes trailing data\n", - ap->id, bytes); + ata_dev_printk(qc->dev, KERN_WARNING, + "%u bytes trailing data\n", bytes); for (i = 0; i < words; i++) - ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write); + ap->ops->data_xfer(qc->dev, (unsigned char*)pad_buf, 2, do_write); ap->hsm_task_state = HSM_ST_LAST; return; @@ -3517,7 +3806,24 @@ next_sg: /* don't cross page boundaries */ count = min(count, (unsigned int)PAGE_SIZE - offset); - buf = kmap(page) + offset; + DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); + + if (PageHighMem(page)) { + unsigned long flags; + + /* FIXME: use bounce buffer */ + local_irq_save(flags); + buf = kmap_atomic(page, KM_IRQ0); + + /* do the actual data transfer */ + ap->ops->data_xfer(qc->dev, buf + offset, count, do_write); + + kunmap_atomic(buf, KM_IRQ0); + local_irq_restore(flags); + } else { + buf = page_address(page); + ap->ops->data_xfer(qc->dev, buf + offset, count, do_write); + } bytes -= count; qc->curbytes += count; @@ -3528,13 +3834,6 @@ next_sg: qc->cursg_ofs = 0; } - DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); - - /* do the actual data transfer */ - ata_data_xfer(ap, buf, count, do_write); - - kunmap(page); - if (bytes) goto next_sg; } @@ -3556,10 +3855,16 @@ static void atapi_pio_bytes(struct ata_q unsigned int ireason, bc_lo, bc_hi, bytes; int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0; - ap->ops->tf_read(ap, &qc->tf); - ireason = qc->tf.nsect; - bc_lo = qc->tf.lbam; - bc_hi = qc->tf.lbah; + /* Abuse qc->result_tf for temp storage of intermediate TF + * here to save some kernel stack usage. + * For normal completion, qc->result_tf is not relevant. For + * error, qc->result_tf is later overwritten by ata_qc_complete(). + * So, the correctness of qc->result_tf is not affected. + */ + ap->ops->tf_read(ap, &qc->result_tf); + ireason = qc->result_tf.nsect; + bc_lo = qc->result_tf.lbam; + bc_hi = qc->result_tf.lbah; bytes = (bc_hi << 8) | bc_lo; /* shall be cleared to zero, indicating xfer of data */ @@ -3571,307 +3876,365 @@ static void atapi_pio_bytes(struct ata_q if (do_write != i_write) goto err_out; + VPRINTK("ata%u: xfering %d bytes\n", ap->id, bytes); + __atapi_pio_bytes(qc, bytes); return; err_out: - printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n", - ap->id, dev->devno); + ata_dev_printk(dev, KERN_INFO, "ATAPI check failed\n"); qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; } /** - * ata_pio_block - start PIO on a block + * ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue. * @ap: the target ata_port + * @qc: qc on going * - * LOCKING: - * None. (executing in kernel thread context) + * RETURNS: + * 1 if ok in workqueue, 0 otherwise. */ -static void ata_pio_block(struct ata_port *ap) +static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc) { - struct ata_queued_cmd *qc; - u8 status; + if (qc->tf.flags & ATA_TFLAG_POLLING) + return 1; - /* - * This is purely heuristic. This is a fast path. - * Sometimes when we enter, BSY will be cleared in - * a chk-status or two. If not, the drive is probably seeking - * or something. Snooze for a couple msecs, then - * chk-status again. If still busy, fall back to - * HSM_ST_POLL state. - */ - status = ata_busy_wait(ap, ATA_BUSY, 5); - if (status & ATA_BUSY) { - msleep(2); - status = ata_busy_wait(ap, ATA_BUSY, 10); - if (status & ATA_BUSY) { - ap->hsm_task_state = HSM_ST_POLL; - ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; - return; - } + if (ap->hsm_task_state == HSM_ST_FIRST) { + if (qc->tf.protocol == ATA_PROT_PIO && + (qc->tf.flags & ATA_TFLAG_WRITE)) + return 1; + + if (is_atapi_taskfile(&qc->tf) && + !(qc->dev->flags & ATA_DFLAG_CDB_INTR)) + return 1; } - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); + return 0; +} - /* check error */ - if (status & (ATA_ERR | ATA_DF)) { - qc->err_mask |= AC_ERR_DEV; - ap->hsm_task_state = HSM_ST_ERR; - return; - } +/** + * ata_hsm_qc_complete - finish a qc running on standard HSM + * @qc: Command to complete + * @in_wq: 1 if called from workqueue, 0 otherwise + * + * Finish @qc which is running on standard HSM. + * + * LOCKING: + * If @in_wq is zero, spin_lock_irqsave(host_set lock). + * Otherwise, none on entry and grabs host lock. + */ +static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) +{ + struct ata_port *ap = qc->ap; + unsigned long flags; - /* transfer data if any */ - if (is_atapi_taskfile(&qc->tf)) { - /* DRQ=0 means no more data to transfer */ - if ((status & ATA_DRQ) == 0) { - ap->hsm_task_state = HSM_ST_LAST; - return; - } + if (ap->ops->error_handler) { + if (in_wq) { + spin_lock_irqsave(ap->lock, flags); - atapi_pio_bytes(qc); - } else { - /* handle BSY=0, DRQ=0 as error */ - if ((status & ATA_DRQ) == 0) { - qc->err_mask |= AC_ERR_HSM; - ap->hsm_task_state = HSM_ST_ERR; - return; - } + /* EH might have kicked in while host_set lock + * is released. + */ + qc = ata_qc_from_tag(ap, qc->tag); + if (qc) { + if (likely(!(qc->err_mask & AC_ERR_HSM))) { + ata_irq_on(ap); + ata_qc_complete(qc); + } else + ata_port_freeze(ap); + } - ata_pio_sector(qc); + spin_unlock_irqrestore(ap->lock, flags); + } else { + if (likely(!(qc->err_mask & AC_ERR_HSM))) + ata_qc_complete(qc); + else + ata_port_freeze(ap); + } + } else { + if (in_wq) { + spin_lock_irqsave(ap->lock, flags); + ata_irq_on(ap); + ata_qc_complete(qc); + spin_unlock_irqrestore(ap->lock, flags); + } else + ata_qc_complete(qc); } ata_altstatus(ap); /* flush */ } -static void ata_pio_error(struct ata_port *ap) +/** + * ata_hsm_move - move the HSM to the next state. + * @ap: the target ata_port + * @qc: qc on going + * @status: current device status + * @in_wq: 1 if called from workqueue, 0 otherwise + * + * RETURNS: + * 1 when poll next status needed, 0 otherwise. + */ +int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, + u8 status, int in_wq) { - struct ata_queued_cmd *qc; + unsigned long flags = 0; + int poll_next; - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); + WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0); - if (qc->tf.command != ATA_CMD_PACKET) - printk(KERN_WARNING "ata%u: PIO error\n", ap->id); - - /* make sure qc->err_mask is available to - * know what's wrong and recover + /* Make sure ata_qc_issue_prot() does not throw things + * like DMA polling into the workqueue. Notice that + * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING). */ - WARN_ON(qc->err_mask == 0); - - ap->hsm_task_state = HSM_ST_IDLE; - - ata_poll_qc_complete(qc); -} - -static void ata_pio_task(void *_data) -{ - struct ata_port *ap = _data; - unsigned long timeout; - int qc_completed; + WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc)); fsm_start: - timeout = 0; - qc_completed = 0; + DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n", + ap->id, qc->tf.protocol, ap->hsm_task_state, status); switch (ap->hsm_task_state) { - case HSM_ST_IDLE: - return; - - case HSM_ST: - ata_pio_block(ap); - break; - - case HSM_ST_LAST: - qc_completed = ata_pio_complete(ap); - break; + case HSM_ST_FIRST: + /* Send first data block or PACKET CDB */ - case HSM_ST_POLL: - case HSM_ST_LAST_POLL: - timeout = ata_pio_poll(ap); - break; - - case HSM_ST_TMOUT: - case HSM_ST_ERR: - ata_pio_error(ap); - return; - } - - if (timeout) - ata_port_queue_task(ap, ata_pio_task, ap, timeout); - else if (!qc_completed) - goto fsm_start; -} - -/** - * atapi_packet_task - Write CDB bytes to hardware - * @_data: Port to which ATAPI device is attached. - * - * When device has indicated its readiness to accept - * a CDB, this function is called. Send the CDB. - * If DMA is to be performed, exit immediately. - * Otherwise, we are in polling mode, so poll - * status under operation succeeds or fails. - * - * LOCKING: - * Kernel thread context (may sleep) - */ - -static void atapi_packet_task(void *_data) -{ - struct ata_port *ap = _data; - struct ata_queued_cmd *qc; - u8 status; - - qc = ata_qc_from_tag(ap, ap->active_tag); - WARN_ON(qc == NULL); - WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); + /* If polling, we will stay in the work queue after + * sending the data. Otherwise, interrupt handler + * takes over after sending the data. + */ + poll_next = (qc->tf.flags & ATA_TFLAG_POLLING); + + /* check device status */ + if (unlikely((status & ATA_DRQ) == 0)) { + /* handle BSY=0, DRQ=0 as error */ + if (likely(status & (ATA_ERR | ATA_DF))) + /* device stops HSM for abort/error */ + qc->err_mask |= AC_ERR_DEV; + else + /* HSM violation. Let EH handle this */ + qc->err_mask |= AC_ERR_HSM; - /* sleep-wait for BSY to clear */ - DPRINTK("busy wait\n"); - if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) { - qc->err_mask |= AC_ERR_TIMEOUT; - goto err_out; - } + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } - /* make sure DRQ is set */ - status = ata_chk_status(ap); - if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) { - qc->err_mask |= AC_ERR_HSM; - goto err_out; - } + /* Device should not ask for data transfer (DRQ=1) + * when it finds something wrong. + * We ignore DRQ here and stop the HSM by + * changing hsm_task_state to HSM_ST_ERR and + * let the EH abort the command or reset the device. + */ + if (unlikely(status & (ATA_ERR | ATA_DF))) { + printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", + ap->id, status); + qc->err_mask |= AC_ERR_HSM; + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } - /* send SCSI cdb */ - DPRINTK("send cdb\n"); - WARN_ON(qc->dev->cdb_len < 12); + /* Send the CDB (atapi) or the first data block (ata pio out). + * During the state transition, interrupt handler shouldn't + * be invoked before the data transfer is complete and + * hsm_task_state is changed. Hence, the following locking. + */ + if (in_wq) + spin_lock_irqsave(ap->lock, flags); - if (qc->tf.protocol == ATA_PROT_ATAPI_DMA || - qc->tf.protocol == ATA_PROT_ATAPI_NODATA) { - unsigned long flags; + if (qc->tf.protocol == ATA_PROT_PIO) { + /* PIO data out protocol. + * send first data block. + */ - /* Once we're done issuing command and kicking bmdma, - * irq handler takes over. To not lose irq, we need - * to clear NOINTR flag before sending cdb, but - * interrupt handler shouldn't be invoked before we're - * finished. Hence, the following locking. + /* ata_pio_sectors() might change the state + * to HSM_ST_LAST. so, the state is changed here + * before ata_pio_sectors(). + */ + ap->hsm_task_state = HSM_ST; + ata_pio_sectors(qc); + ata_altstatus(ap); /* flush */ + } else + /* send CDB */ + atapi_send_cdb(ap, qc); + + if (in_wq) + spin_unlock_irqrestore(ap->lock, flags); + + /* if polling, ata_pio_task() handles the rest. + * otherwise, interrupt handler takes over from here. */ - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_NOINTR; - ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); - ata_altstatus(ap); /* flush */ + break; - if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) - ap->ops->bmdma_start(qc); /* initiate bmdma */ - spin_unlock_irqrestore(&ap->host_set->lock, flags); - } else { - ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); - ata_altstatus(ap); /* flush */ + case HSM_ST: + /* complete command or read/write the data register */ + if (qc->tf.protocol == ATA_PROT_ATAPI) { + /* ATAPI PIO protocol */ + if ((status & ATA_DRQ) == 0) { + /* No more data to transfer or device error. + * Device error will be tagged in HSM_ST_LAST. + */ + ap->hsm_task_state = HSM_ST_LAST; + goto fsm_start; + } - /* PIO commands are handled by polling */ - ap->hsm_task_state = HSM_ST; - ata_port_queue_task(ap, ata_pio_task, ap, 0); - } + /* Device should not ask for data transfer (DRQ=1) + * when it finds something wrong. + * We ignore DRQ here and stop the HSM by + * changing hsm_task_state to HSM_ST_ERR and + * let the EH abort the command or reset the device. + */ + if (unlikely(status & (ATA_ERR | ATA_DF))) { + printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n", + ap->id, status); + qc->err_mask |= AC_ERR_HSM; + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } - return; + atapi_pio_bytes(qc); -err_out: - ata_poll_qc_complete(qc); -} + if (unlikely(ap->hsm_task_state == HSM_ST_ERR)) + /* bad ireason reported by device */ + goto fsm_start; -/** - * ata_qc_timeout - Handle timeout of queued command - * @qc: Command that timed out - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ + } else { + /* ATA PIO protocol */ + if (unlikely((status & ATA_DRQ) == 0)) { + /* handle BSY=0, DRQ=0 as error */ + if (likely(status & (ATA_ERR | ATA_DF))) + /* device stops HSM for abort/error */ + qc->err_mask |= AC_ERR_DEV; + else + /* HSM violation. Let EH handle this */ + qc->err_mask |= AC_ERR_HSM; + + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } -static void ata_qc_timeout(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct ata_host_set *host_set = ap->host_set; - u8 host_stat = 0, drv_stat; - unsigned long flags; + /* For PIO reads, some devices may ask for + * data transfer (DRQ=1) alone with ERR=1. + * We respect DRQ here and transfer one + * block of junk data before changing the + * hsm_task_state to HSM_ST_ERR. + * + * For PIO writes, ERR=1 DRQ=1 doesn't make + * sense since the data block has been + * transferred to the device. + */ + if (unlikely(status & (ATA_ERR | ATA_DF))) { + /* data might be corrputed */ + qc->err_mask |= AC_ERR_DEV; + + if (!(qc->tf.flags & ATA_TFLAG_WRITE)) { + ata_pio_sectors(qc); + ata_altstatus(ap); + status = ata_wait_idle(ap); + } + + if (status & (ATA_BUSY | ATA_DRQ)) + qc->err_mask |= AC_ERR_HSM; + + /* ata_pio_sectors() might change the + * state to HSM_ST_LAST. so, the state + * is changed after ata_pio_sectors(). + */ + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } - DPRINTK("ENTER\n"); + ata_pio_sectors(qc); - ap->hsm_task_state = HSM_ST_IDLE; + if (ap->hsm_task_state == HSM_ST_LAST && + (!(qc->tf.flags & ATA_TFLAG_WRITE))) { + /* all data read */ + ata_altstatus(ap); + status = ata_wait_idle(ap); + goto fsm_start; + } + } - spin_lock_irqsave(&host_set->lock, flags); + ata_altstatus(ap); /* flush */ + poll_next = 1; + break; - switch (qc->tf.protocol) { + case HSM_ST_LAST: + if (unlikely(!ata_ok(status))) { + qc->err_mask |= __ac_err_mask(status); + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } - case ATA_PROT_DMA: - case ATA_PROT_ATAPI_DMA: - host_stat = ap->ops->bmdma_status(ap); + /* no more data to transfer */ + DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n", + ap->id, qc->dev->devno, status); - /* before we do anything else, clear DMA-Start bit */ - ap->ops->bmdma_stop(qc); + WARN_ON(qc->err_mask); - /* fall through */ + ap->hsm_task_state = HSM_ST_IDLE; - default: - ata_altstatus(ap); - drv_stat = ata_chk_status(ap); + /* complete taskfile transaction */ + ata_hsm_qc_complete(qc, in_wq); - /* ack bmdma irq events */ - ap->ops->irq_clear(ap); + poll_next = 0; + break; + + case HSM_ST_ERR: + /* make sure qc->err_mask is available to + * know what's wrong and recover + */ + WARN_ON(qc->err_mask == 0); - printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", - ap->id, qc->tf.command, drv_stat, host_stat); + ap->hsm_task_state = HSM_ST_IDLE; /* complete taskfile transaction */ - qc->err_mask |= ac_err_mask(drv_stat); + ata_hsm_qc_complete(qc, in_wq); + + poll_next = 0; break; + default: + poll_next = 0; + BUG(); } - spin_unlock_irqrestore(&host_set->lock, flags); - - ata_eh_qc_complete(qc); - - DPRINTK("EXIT\n"); + return poll_next; } -/** - * ata_eng_timeout - Handle timeout of queued command - * @ap: Port on which timed-out command is active - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ - -void ata_eng_timeout(struct ata_port *ap) +static void ata_pio_task(void *_data) { - DPRINTK("ENTER\n"); + struct ata_queued_cmd *qc = _data; + struct ata_port *ap = qc->ap; + u8 status; + int poll_next; - ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag)); +fsm_start: + WARN_ON(ap->hsm_task_state == HSM_ST_IDLE); - DPRINTK("EXIT\n"); + /* + * This is purely heuristic. This is a fast path. + * Sometimes when we enter, BSY will be cleared in + * a chk-status or two. If not, the drive is probably seeking + * or something. Snooze for a couple msecs, then + * chk-status again. If still busy, queue delayed work. + */ + status = ata_busy_wait(ap, ATA_BUSY, 5); + if (status & ATA_BUSY) { + msleep(2); + status = ata_busy_wait(ap, ATA_BUSY, 10); + if (status & ATA_BUSY) { + ata_port_queue_task(ap, ata_pio_task, qc, ATA_SHORT_PAUSE); + return; + } + } + + /* move the HSM */ + poll_next = ata_hsm_move(ap, qc, status, 1); + + /* another command or interrupt handler + * may be running at this point. + */ + if (poll_next) + goto fsm_start; } /** @@ -3888,9 +4251,14 @@ static struct ata_queued_cmd *ata_qc_new struct ata_queued_cmd *qc = NULL; unsigned int i; - for (i = 0; i < ATA_MAX_QUEUE; i++) - if (!test_and_set_bit(i, &ap->qactive)) { - qc = ata_qc_from_tag(ap, i); + /* no command while frozen */ + if (unlikely(ap->flags & ATA_FLAG_FROZEN)) + return NULL; + + /* the last tag is reserved for internal command. */ + for (i = 0; i < ATA_MAX_QUEUE - 1; i++) + if (!test_and_set_bit(i, &ap->qc_allocated)) { + qc = __ata_qc_from_tag(ap, i); break; } @@ -3902,16 +4270,15 @@ static struct ata_queued_cmd *ata_qc_new /** * ata_qc_new_init - Request an available ATA command, and initialize it - * @ap: Port associated with device @dev * @dev: Device from whom we request an available command structure * * LOCKING: * None. */ -struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, - struct ata_device *dev) +struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev) { + struct ata_port *ap = dev->ap; struct ata_queued_cmd *qc; qc = ata_qc_new(ap); @@ -3946,36 +4313,153 @@ void ata_qc_free(struct ata_queued_cmd * qc->flags = 0; tag = qc->tag; if (likely(ata_tag_valid(tag))) { - if (tag == ap->active_tag) - ap->active_tag = ATA_TAG_POISON; qc->tag = ATA_TAG_POISON; - clear_bit(tag, &ap->qactive); + clear_bit(tag, &ap->qc_allocated); } } void __ata_qc_complete(struct ata_queued_cmd *qc) { + struct ata_port *ap = qc->ap; + WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); if (likely(qc->flags & ATA_QCFLAG_DMAMAP)) ata_sg_clean(qc); + /* command should be marked inactive atomically with qc completion */ + if (qc->tf.protocol == ATA_PROT_NCQ) + ap->sactive &= ~(1 << qc->tag); + else + ap->active_tag = ATA_TAG_POISON; + /* atapi: mark qc as inactive to prevent the interrupt handler * from completing the command twice later, before the error handler * is called. (when rc != 0 and atapi request sense is needed) */ qc->flags &= ~ATA_QCFLAG_ACTIVE; + ap->qc_active &= ~(1 << qc->tag); /* call completion callback */ qc->complete_fn(qc); } +/** + * ata_qc_complete - Complete an active ATA command + * @qc: Command to complete + * @err_mask: ATA Status register contents + * + * Indicate to the mid and upper layers that an ATA + * command has completed, with either an ok or not-ok status. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_qc_complete(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + /* XXX: New EH and old EH use different mechanisms to + * synchronize EH with regular execution path. + * + * In new EH, a failed qc is marked with ATA_QCFLAG_FAILED. + * Normal execution path is responsible for not accessing a + * failed qc. libata core enforces the rule by returning NULL + * from ata_qc_from_tag() for failed qcs. + * + * Old EH depends on ata_qc_complete() nullifying completion + * requests if ATA_QCFLAG_EH_SCHEDULED is set. Old EH does + * not synchronize with interrupt handler. Only PIO task is + * taken care of. + */ + if (ap->ops->error_handler) { + WARN_ON(ap->flags & ATA_FLAG_FROZEN); + + if (unlikely(qc->err_mask)) + qc->flags |= ATA_QCFLAG_FAILED; + + if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { + if (!ata_tag_internal(qc->tag)) { + /* always fill result TF for failed qc */ + ap->ops->tf_read(ap, &qc->result_tf); + ata_qc_schedule_eh(qc); + return; + } + } + + /* read result TF if requested */ + if (qc->flags & ATA_QCFLAG_RESULT_TF) + ap->ops->tf_read(ap, &qc->result_tf); + + __ata_qc_complete(qc); + } else { + if (qc->flags & ATA_QCFLAG_EH_SCHEDULED) + return; + + /* read result TF if failed or requested */ + if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF) + ap->ops->tf_read(ap, &qc->result_tf); + + __ata_qc_complete(qc); + } +} + +/** + * ata_qc_complete_multiple - Complete multiple qcs successfully + * @ap: port in question + * @qc_active: new qc_active mask + * @finish_qc: LLDD callback invoked before completing a qc + * + * Complete in-flight commands. This functions is meant to be + * called from low-level driver's interrupt routine to complete + * requests normally. ap->qc_active and @qc_active is compared + * and commands are completed accordingly. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Number of completed commands on success, -errno otherwise. + */ +int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active, + void (*finish_qc)(struct ata_queued_cmd *)) +{ + int nr_done = 0; + u32 done_mask; + int i; + + done_mask = ap->qc_active ^ qc_active; + + if (unlikely(done_mask & qc_active)) { + ata_port_printk(ap, KERN_ERR, "illegal qc_active transition " + "(%08x->%08x)\n", ap->qc_active, qc_active); + return -EINVAL; + } + + for (i = 0; i < ATA_MAX_QUEUE; i++) { + struct ata_queued_cmd *qc; + + if (!(done_mask & (1 << i))) + continue; + + if ((qc = ata_qc_from_tag(ap, i))) { + if (finish_qc) + finish_qc(qc); + ata_qc_complete(qc); + nr_done++; + } + } + + return nr_done; +} + static inline int ata_should_dma_map(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; switch (qc->tf.protocol) { + case ATA_PROT_NCQ: case ATA_PROT_DMA: case ATA_PROT_ATAPI_DMA: return 1; @@ -4010,8 +4494,22 @@ void ata_qc_issue(struct ata_queued_cmd { struct ata_port *ap = qc->ap; - qc->ap->active_tag = qc->tag; + /* Make sure only one non-NCQ command is outstanding. The + * check is skipped for old EH because it reuses active qc to + * request ATAPI sense. + */ + WARN_ON(ap->ops->error_handler && ata_tag_valid(ap->active_tag)); + + if (qc->tf.protocol == ATA_PROT_NCQ) { + WARN_ON(ap->sactive & (1 << qc->tag)); + ap->sactive |= 1 << qc->tag; + } else { + WARN_ON(ap->sactive); + ap->active_tag = qc->tag; + } + qc->flags |= ATA_QCFLAG_ACTIVE; + ap->qc_active |= 1 << qc->tag; if (ata_should_dma_map(qc)) { if (qc->flags & ATA_QCFLAG_SG) { @@ -4061,43 +4559,105 @@ unsigned int ata_qc_issue_prot(struct at { struct ata_port *ap = qc->ap; + /* Use polling pio if the LLD doesn't handle + * interrupt driven pio and atapi CDB interrupt. + */ + if (ap->flags & ATA_FLAG_PIO_POLLING) { + switch (qc->tf.protocol) { + case ATA_PROT_PIO: + case ATA_PROT_ATAPI: + case ATA_PROT_ATAPI_NODATA: + qc->tf.flags |= ATA_TFLAG_POLLING; + break; + case ATA_PROT_ATAPI_DMA: + if (qc->dev->flags & ATA_DFLAG_CDB_INTR) + /* see ata_dma_blacklisted() */ + BUG(); + break; + default: + break; + } + } + + /* select the device */ ata_dev_select(ap, qc->dev->devno, 1, 0); + /* start the command */ switch (qc->tf.protocol) { case ATA_PROT_NODATA: + if (qc->tf.flags & ATA_TFLAG_POLLING) + ata_qc_set_polling(qc); + ata_tf_to_host(ap, &qc->tf); + ap->hsm_task_state = HSM_ST_LAST; + + if (qc->tf.flags & ATA_TFLAG_POLLING) + ata_port_queue_task(ap, ata_pio_task, qc, 0); + break; case ATA_PROT_DMA: + WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING); + ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ ap->ops->bmdma_setup(qc); /* set up bmdma */ ap->ops->bmdma_start(qc); /* initiate bmdma */ + ap->hsm_task_state = HSM_ST_LAST; break; - case ATA_PROT_PIO: /* load tf registers, initiate polling pio */ - ata_qc_set_polling(qc); - ata_tf_to_host(ap, &qc->tf); - ap->hsm_task_state = HSM_ST; - ata_port_queue_task(ap, ata_pio_task, ap, 0); - break; + case ATA_PROT_PIO: + if (qc->tf.flags & ATA_TFLAG_POLLING) + ata_qc_set_polling(qc); - case ATA_PROT_ATAPI: - ata_qc_set_polling(qc); ata_tf_to_host(ap, &qc->tf); - ata_port_queue_task(ap, atapi_packet_task, ap, 0); + + if (qc->tf.flags & ATA_TFLAG_WRITE) { + /* PIO data out protocol */ + ap->hsm_task_state = HSM_ST_FIRST; + ata_port_queue_task(ap, ata_pio_task, qc, 0); + + /* always send first data block using + * the ata_pio_task() codepath. + */ + } else { + /* PIO data in protocol */ + ap->hsm_task_state = HSM_ST; + + if (qc->tf.flags & ATA_TFLAG_POLLING) + ata_port_queue_task(ap, ata_pio_task, qc, 0); + + /* if polling, ata_pio_task() handles the rest. + * otherwise, interrupt handler takes over from here. + */ + } + break; + case ATA_PROT_ATAPI: case ATA_PROT_ATAPI_NODATA: - ap->flags |= ATA_FLAG_NOINTR; + if (qc->tf.flags & ATA_TFLAG_POLLING) + ata_qc_set_polling(qc); + ata_tf_to_host(ap, &qc->tf); - ata_port_queue_task(ap, atapi_packet_task, ap, 0); + + ap->hsm_task_state = HSM_ST_FIRST; + + /* send cdb by polling if no cdb interrupt */ + if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || + (qc->tf.flags & ATA_TFLAG_POLLING)) + ata_port_queue_task(ap, ata_pio_task, qc, 0); break; case ATA_PROT_ATAPI_DMA: - ap->flags |= ATA_FLAG_NOINTR; + WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING); + ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ ap->ops->bmdma_setup(qc); /* set up bmdma */ - ata_port_queue_task(ap, atapi_packet_task, ap, 0); + ap->hsm_task_state = HSM_ST_FIRST; + + /* send cdb by polling if no cdb interrupt */ + if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) + ata_port_queue_task(ap, ata_pio_task, qc, 0); break; default: @@ -4127,52 +4687,66 @@ unsigned int ata_qc_issue_prot(struct at inline unsigned int ata_host_intr (struct ata_port *ap, struct ata_queued_cmd *qc) { - u8 status, host_stat; + u8 status, host_stat = 0; - switch (qc->tf.protocol) { + VPRINTK("ata%u: protocol %d task_state %d\n", + ap->id, qc->tf.protocol, ap->hsm_task_state); - case ATA_PROT_DMA: - case ATA_PROT_ATAPI_DMA: - case ATA_PROT_ATAPI: - /* check status of DMA engine */ - host_stat = ap->ops->bmdma_status(ap); - VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat); - - /* if it's not our irq... */ - if (!(host_stat & ATA_DMA_INTR)) - goto idle_irq; - - /* before we do anything else, clear DMA-Start bit */ - ap->ops->bmdma_stop(qc); - - /* fall through */ - - case ATA_PROT_ATAPI_NODATA: - case ATA_PROT_NODATA: - /* check altstatus */ - status = ata_altstatus(ap); - if (status & ATA_BUSY) - goto idle_irq; + /* Check whether we are expecting interrupt in this state */ + switch (ap->hsm_task_state) { + case HSM_ST_FIRST: + /* Some pre-ATAPI-4 devices assert INTRQ + * at this state when ready to receive CDB. + */ - /* check main status, clearing INTRQ */ - status = ata_chk_status(ap); - if (unlikely(status & ATA_BUSY)) + /* Check the ATA_DFLAG_CDB_INTR flag is enough here. + * The flag was turned on only for atapi devices. + * No need to check is_atapi_taskfile(&qc->tf) again. + */ + if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) goto idle_irq; - DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n", - ap->id, qc->tf.protocol, status); - - /* ack bmdma irq events */ - ap->ops->irq_clear(ap); - - /* complete taskfile transaction */ - qc->err_mask |= ac_err_mask(status); - ata_qc_complete(qc); break; - + case HSM_ST_LAST: + if (qc->tf.protocol == ATA_PROT_DMA || + qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + /* check status of DMA engine */ + host_stat = ap->ops->bmdma_status(ap); + VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat); + + /* if it's not our irq... */ + if (!(host_stat & ATA_DMA_INTR)) + goto idle_irq; + + /* before we do anything else, clear DMA-Start bit */ + ap->ops->bmdma_stop(qc); + + if (unlikely(host_stat & ATA_DMA_ERR)) { + /* error when transfering data to/from memory */ + qc->err_mask |= AC_ERR_HOST_BUS; + ap->hsm_task_state = HSM_ST_ERR; + } + } + break; + case HSM_ST: + break; default: goto idle_irq; } + /* check altstatus */ + status = ata_altstatus(ap); + if (status & ATA_BUSY) + goto idle_irq; + + /* check main status, clearing INTRQ */ + status = ata_chk_status(ap); + if (unlikely(status & ATA_BUSY)) + goto idle_irq; + + /* ack bmdma irq events */ + ap->ops->irq_clear(ap); + + ata_hsm_move(ap, qc, status, 0); return 1; /* irq handled */ idle_irq: @@ -4181,7 +4755,7 @@ idle_irq: #ifdef ATA_IRQ_TRAP if ((ap->stats.idle_irq % 1000) == 0) { ata_irq_ack(ap, 0); /* debug trap */ - printk(KERN_WARNING "ata%d: irq trap\n", ap->id); + ata_port_printk(ap, KERN_WARNING, "irq trap\n"); return 1; } #endif @@ -4219,11 +4793,11 @@ irqreturn_t ata_interrupt (int irq, void ap = host_set->ports[i]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN)) && + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) && (qc->flags & ATA_QCFLAG_ACTIVE)) handled |= ata_host_intr(ap, qc); } @@ -4234,32 +4808,168 @@ irqreturn_t ata_interrupt (int irq, void return IRQ_RETVAL(handled); } +/** + * sata_scr_valid - test whether SCRs are accessible + * @ap: ATA port to test SCR accessibility for + * + * Test whether SCRs are accessible for @ap. + * + * LOCKING: + * None. + * + * RETURNS: + * 1 if SCRs are accessible, 0 otherwise. + */ +int sata_scr_valid(struct ata_port *ap) +{ + return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read; +} + +/** + * sata_scr_read - read SCR register of the specified port + * @ap: ATA port to read SCR for + * @reg: SCR to read + * @val: Place to store read value + * + * Read SCR register @reg of @ap into *@val. This function is + * guaranteed to succeed if the cable type of the port is SATA + * and the port implements ->scr_read. + * + * LOCKING: + * None. + * + * RETURNS: + * 0 on success, negative errno on failure. + */ +int sata_scr_read(struct ata_port *ap, int reg, u32 *val) +{ + if (sata_scr_valid(ap)) { + *val = ap->ops->scr_read(ap, reg); + return 0; + } + return -EOPNOTSUPP; +} + +/** + * sata_scr_write - write SCR register of the specified port + * @ap: ATA port to write SCR for + * @reg: SCR to write + * @val: value to write + * + * Write @val to SCR register @reg of @ap. This function is + * guaranteed to succeed if the cable type of the port is SATA + * and the port implements ->scr_read. + * + * LOCKING: + * None. + * + * RETURNS: + * 0 on success, negative errno on failure. + */ +int sata_scr_write(struct ata_port *ap, int reg, u32 val) +{ + if (sata_scr_valid(ap)) { + ap->ops->scr_write(ap, reg, val); + return 0; + } + return -EOPNOTSUPP; +} + +/** + * sata_scr_write_flush - write SCR register of the specified port and flush + * @ap: ATA port to write SCR for + * @reg: SCR to write + * @val: value to write + * + * This function is identical to sata_scr_write() except that this + * function performs flush after writing to the register. + * + * LOCKING: + * None. + * + * RETURNS: + * 0 on success, negative errno on failure. + */ +int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val) +{ + if (sata_scr_valid(ap)) { + ap->ops->scr_write(ap, reg, val); + ap->ops->scr_read(ap, reg); + return 0; + } + return -EOPNOTSUPP; +} + +/** + * ata_port_online - test whether the given port is online + * @ap: ATA port to test + * + * Test whether @ap is online. Note that this function returns 0 + * if online status of @ap cannot be obtained, so + * ata_port_online(ap) != !ata_port_offline(ap). + * + * LOCKING: + * None. + * + * RETURNS: + * 1 if the port online status is available and online. + */ +int ata_port_online(struct ata_port *ap) +{ + u32 sstatus; + + if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) == 0x3) + return 1; + return 0; +} + +/** + * ata_port_offline - test whether the given port is offline + * @ap: ATA port to test + * + * Test whether @ap is offline. Note that this function returns + * 0 if offline status of @ap cannot be obtained, so + * ata_port_online(ap) != !ata_port_offline(ap). + * + * LOCKING: + * None. + * + * RETURNS: + * 1 if the port offline status is available and offline. + */ +int ata_port_offline(struct ata_port *ap) +{ + u32 sstatus; + + if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) != 0x3) + return 1; + return 0; +} /* * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, * without filling any other registers */ -static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev, - u8 cmd) +static int ata_do_simple_cmd(struct ata_device *dev, u8 cmd) { struct ata_taskfile tf; int err; - ata_tf_init(ap, &tf, dev->devno); + ata_tf_init(dev, &tf); tf.command = cmd; tf.flags |= ATA_TFLAG_DEVICE; tf.protocol = ATA_PROT_NODATA; - err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); + err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); if (err) - printk(KERN_ERR "%s: ata command failed: %d\n", - __FUNCTION__, err); + ata_dev_printk(dev, KERN_ERR, "%s: ata command failed: %d\n", + __FUNCTION__, err); return err; } -static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev) +static int ata_flush_cache(struct ata_device *dev) { u8 cmd; @@ -4271,22 +4981,21 @@ static int ata_flush_cache(struct ata_po else cmd = ATA_CMD_FLUSH; - return ata_do_simple_cmd(ap, dev, cmd); + return ata_do_simple_cmd(dev, cmd); } -static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev) +static int ata_standby_drive(struct ata_device *dev) { - return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1); + return ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1); } -static int ata_start_drive(struct ata_port *ap, struct ata_device *dev) +static int ata_start_drive(struct ata_device *dev) { - return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE); + return ata_do_simple_cmd(dev, ATA_CMD_IDLEIMMEDIATE); } /** * ata_device_resume - wakeup a previously suspended devices - * @ap: port the device is connected to * @dev: the device to resume * * Kick the drive back into action, by sending it an idle immediate @@ -4294,39 +5003,47 @@ static int ata_start_drive(struct ata_po * and host. * */ -int ata_device_resume(struct ata_port *ap, struct ata_device *dev) +int ata_device_resume(struct ata_device *dev) { + struct ata_port *ap = dev->ap; + if (ap->flags & ATA_FLAG_SUSPENDED) { + struct ata_device *failed_dev; + + ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 200000); + ap->flags &= ~ATA_FLAG_SUSPENDED; - ata_set_mode(ap); + while (ata_set_mode(ap, &failed_dev)) + ata_dev_disable(failed_dev); } - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) return 0; if (dev->class == ATA_DEV_ATA) - ata_start_drive(ap, dev); + ata_start_drive(dev); return 0; } /** * ata_device_suspend - prepare a device for suspend - * @ap: port the device is connected to * @dev: the device to suspend * @state: target power management state * * Flush the cache on the drive, if appropriate, then issue a * standbynow command. */ -int ata_device_suspend(struct ata_port *ap, struct ata_device *dev, pm_message_t state) +int ata_device_suspend(struct ata_device *dev, pm_message_t state) { - if (!ata_dev_present(dev)) + struct ata_port *ap = dev->ap; + + if (!ata_dev_enabled(dev)) return 0; if (dev->class == ATA_DEV_ATA) - ata_flush_cache(ap, dev); + ata_flush_cache(dev); if (state.event != PM_EVENT_FREEZE) - ata_standby_drive(ap, dev); + ata_standby_drive(dev); ap->flags |= ATA_FLAG_SUSPENDED; return 0; } @@ -4414,6 +5131,38 @@ static void ata_host_remove(struct ata_p } /** + * ata_dev_init - Initialize an ata_device structure + * @dev: Device structure to initialize + * + * Initialize @dev in preparation for probing. + * + * LOCKING: + * Inherited from caller. + */ +void ata_dev_init(struct ata_device *dev) +{ + struct ata_port *ap = dev->ap; + unsigned long flags; + + /* SATA spd limit is bound to the first device */ + ap->sata_spd_limit = ap->hw_sata_spd_limit; + + /* High bits of dev->flags are used to record warm plug + * requests which occur asynchronously. Synchronize using + * host_set lock. + */ + spin_lock_irqsave(ap->lock, flags); + dev->flags &= ~ATA_DFLAG_INIT_MASK; + spin_unlock_irqrestore(ap->lock, flags); + + memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0, + sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET); + dev->pio_mask = UINT_MAX; + dev->mwdma_mask = UINT_MAX; + dev->udma_mask = UINT_MAX; +} + +/** * ata_host_init - Initialize an ata_port structure * @ap: Structure to initialize * @host: associated SCSI mid-layer structure @@ -4427,7 +5176,6 @@ static void ata_host_remove(struct ata_p * LOCKING: * Inherited from caller. */ - static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, struct ata_host_set *host_set, const struct ata_probe_ent *ent, unsigned int port_no) @@ -4440,7 +5188,8 @@ static void ata_host_init(struct ata_por host->unique_id = ata_unique_id++; host->max_cmd_len = 12; - ap->flags = ATA_FLAG_PORT_DISABLED; + ap->lock = &host_set->lock; + ap->flags = ATA_FLAG_DISABLED; ap->id = host->unique_id; ap->host = host; ap->ctl = ATA_DEVCTL_OBS; @@ -4454,19 +5203,35 @@ static void ata_host_init(struct ata_por ap->udma_mask = ent->udma_mask; ap->flags |= ent->host_flags; ap->ops = ent->port_ops; - ap->cbl = ATA_CBL_NONE; + ap->hw_sata_spd_limit = UINT_MAX; ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; +#if defined(ATA_VERBOSE_DEBUG) + /* turn on all debugging levels */ + ap->msg_enable = 0x00FF; +#elif defined(ATA_DEBUG) + ap->msg_enable = ATA_MSG_DRV | ATA_MSG_INFO | ATA_MSG_CTL | ATA_MSG_WARN | ATA_MSG_ERR; +#else + ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN; +#endif + INIT_WORK(&ap->port_task, NULL, NULL); + INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); + INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap); INIT_LIST_HEAD(&ap->eh_done_q); + init_waitqueue_head(&ap->eh_wait_q); + + /* set cable type */ + ap->cbl = ATA_CBL_NONE; + if (ap->flags & ATA_FLAG_SATA) + ap->cbl = ATA_CBL_SATA; for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; + dev->ap = ap; dev->devno = i; - dev->pio_mask = UINT_MAX; - dev->mwdma_mask = UINT_MAX; - dev->udma_mask = UINT_MAX; + ata_dev_init(dev); } #ifdef ATA_IRQ_TRAP @@ -4502,7 +5267,7 @@ static struct ata_port * ata_host_add(co DPRINTK("ENTER\n"); - if (!ent->port_ops->probe_reset && + if (!ent->port_ops->error_handler && !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) { printk(KERN_ERR "ata%u: no reset mechanism available\n", port_no); @@ -4515,7 +5280,7 @@ static struct ata_port * ata_host_add(co host->transportt = &ata_scsi_transport_template; - ap = (struct ata_port *) &host->hostdata[0]; + ap = ata_shost_to_port(host); ata_host_init(ap, host, host_set, ent, port_no); @@ -4548,12 +5313,12 @@ err_out: * RETURNS: * Number of ports registered. Zero on error (no ports registered). */ - int ata_device_add(const struct ata_probe_ent *ent) { unsigned int count = 0, i; struct device *dev = ent->dev; struct ata_host_set *host_set; + int rc; DPRINTK("ENTER\n"); /* alloc a container for our list of ATA ports (buses) */ @@ -4586,18 +5351,18 @@ int ata_device_add(const struct ata_prob (ap->pio_mask << ATA_SHIFT_PIO); /* print per-port info to dmesg */ - printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX " - "bmdma 0x%lX irq %lu\n", - ap->id, - ap->flags & ATA_FLAG_SATA ? 'S' : 'P', - ata_mode_string(xfer_mode_mask), - ap->ioaddr.cmd_addr, - ap->ioaddr.ctl_addr, - ap->ioaddr.bmdma_addr, - ent->irq); + ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX " + "ctl 0x%lX bmdma 0x%lX irq %lu\n", + ap->flags & ATA_FLAG_SATA ? 'S' : 'P', + ata_mode_string(xfer_mode_mask), + ap->ioaddr.cmd_addr, + ap->ioaddr.ctl_addr, + ap->ioaddr.bmdma_addr, + ent->irq); ata_chk_status(ap); host_set->ops->irq_clear(ap); + ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */ count++; } @@ -4605,41 +5370,72 @@ int ata_device_add(const struct ata_prob goto err_free_ret; /* obtain irq, that is shared between channels */ - if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags, - DRV_NAME, host_set)) + rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags, + DRV_NAME, host_set); + if (rc) { + dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n", + ent->irq, rc); goto err_out; + } /* perform each probe synchronously */ DPRINTK("probe begin\n"); for (i = 0; i < count; i++) { struct ata_port *ap; + u32 scontrol; int rc; ap = host_set->ports[i]; - DPRINTK("ata%u: bus probe begin\n", ap->id); - rc = ata_bus_probe(ap); - DPRINTK("ata%u: bus probe end\n", ap->id); - - if (rc) { - /* FIXME: do something useful here? - * Current libata behavior will - * tear down everything when - * the module is removed - * or the h/w is unplugged. - */ + /* init sata_spd_limit to the current value */ + if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) { + int spd = (scontrol >> 4) & 0xf; + ap->hw_sata_spd_limit &= (1 << spd) - 1; } + ap->sata_spd_limit = ap->hw_sata_spd_limit; rc = scsi_add_host(ap->host, dev); if (rc) { - printk(KERN_ERR "ata%u: scsi_add_host failed\n", - ap->id); + ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n"); /* FIXME: do something useful here */ /* FIXME: handle unconditional calls to * scsi_scan_host and ata_host_remove, below, * at the very least */ } + + if (ap->ops->error_handler) { + unsigned long flags; + + ata_port_probe(ap); + + /* kick EH for boot probing */ + spin_lock_irqsave(ap->lock, flags); + + ap->eh_info.probe_mask = (1 << ATA_MAX_DEVICES) - 1; + ap->eh_info.action |= ATA_EH_SOFTRESET; + + ap->flags |= ATA_FLAG_LOADING; + ata_port_schedule_eh(ap); + + spin_unlock_irqrestore(ap->lock, flags); + + /* wait for EH to finish */ + ata_port_wait_eh(ap); + } else { + DPRINTK("ata%u: bus probe begin\n", ap->id); + rc = ata_bus_probe(ap); + DPRINTK("ata%u: bus probe end\n", ap->id); + + if (rc) { + /* FIXME: do something useful here? + * Current libata behavior will + * tear down everything when + * the module is removed + * or the h/w is unplugged. + */ + } + } } /* probes are done, now scan each port's disk(s) */ @@ -4667,6 +5463,63 @@ err_free_ret: } /** + * ata_port_detach - Detach ATA port in prepration of device removal + * @ap: ATA port to be detached + * + * Detach all ATA devices and the associated SCSI devices of @ap; + * then, remove the associated SCSI host. @ap is guaranteed to + * be quiescent on return from this function. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_port_detach(struct ata_port *ap) +{ + unsigned long flags; + int i; + + if (!ap->ops->error_handler) + return; + + /* tell EH we're leaving & flush EH */ + spin_lock_irqsave(ap->lock, flags); + ap->flags |= ATA_FLAG_UNLOADING; + spin_unlock_irqrestore(ap->lock, flags); + + ata_port_wait_eh(ap); + + /* EH is now guaranteed to see UNLOADING, so no new device + * will be attached. Disable all existing devices. + */ + spin_lock_irqsave(ap->lock, flags); + + for (i = 0; i < ATA_MAX_DEVICES; i++) + ata_dev_disable(&ap->device[i]); + + spin_unlock_irqrestore(ap->lock, flags); + + /* Final freeze & EH. All in-flight commands are aborted. EH + * will be skipped and retrials will be terminated with bad + * target. + */ + spin_lock_irqsave(ap->lock, flags); + ata_port_freeze(ap); /* won't be thawed */ + spin_unlock_irqrestore(ap->lock, flags); + + ata_port_wait_eh(ap); + + /* Flush hotplug task. The sequence is similar to + * ata_port_flush_task(). + */ + flush_workqueue(ata_aux_wq); + cancel_delayed_work(&ap->hotplug_task); + flush_workqueue(ata_aux_wq); + + /* remove the associated SCSI host */ + scsi_remove_host(ap->host); +} + +/** * ata_host_set_remove - PCI layer callback for device removal * @host_set: ATA host set that was removed * @@ -4679,18 +5532,15 @@ err_free_ret: void ata_host_set_remove(struct ata_host_set *host_set) { - struct ata_port *ap; unsigned int i; - for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; - scsi_remove_host(ap->host); - } + for (i = 0; i < host_set->n_ports; i++) + ata_port_detach(host_set->ports[i]); free_irq(host_set->irq, host_set); for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; + struct ata_port *ap = host_set->ports[i]; ata_scsi_release(ap->host); @@ -4728,15 +5578,12 @@ void ata_host_set_remove(struct ata_host int ata_scsi_release(struct Scsi_Host *host) { - struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; - int i; + struct ata_port *ap = ata_shost_to_port(host); DPRINTK("ENTER\n"); ap->ops->port_disable(ap); ata_host_remove(ap, 0); - for (i = 0; i < ATA_MAX_DEVICES; i++) - kfree(ap->device[i].id); DPRINTK("EXIT\n"); return 1; @@ -4796,8 +5643,12 @@ void ata_pci_remove_one (struct pci_dev { struct device *dev = pci_dev_to_dev(pdev); struct ata_host_set *host_set = dev_get_drvdata(dev); + struct ata_host_set *host_set2 = host_set->next; ata_host_set_remove(host_set); + if (host_set2) + ata_host_set_remove(host_set2); + pci_release_regions(pdev); pci_disable_device(pdev); dev_set_drvdata(dev, NULL); @@ -4862,6 +5713,12 @@ static int __init ata_init(void) if (!ata_wq) return -ENOMEM; + ata_aux_wq = create_singlethread_workqueue("ata_aux"); + if (!ata_aux_wq) { + destroy_workqueue(ata_wq); + return -ENOMEM; + } + printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n"); return 0; } @@ -4869,6 +5726,7 @@ static int __init ata_init(void) static void __exit ata_exit(void) { destroy_workqueue(ata_wq); + destroy_workqueue(ata_aux_wq); } module_init(ata_init); @@ -4895,6 +5753,52 @@ int ata_ratelimit(void) return rc; } +/** + * ata_wait_register - wait until register value changes + * @reg: IO-mapped register + * @mask: Mask to apply to read register value + * @val: Wait condition + * @interval_msec: polling interval in milliseconds + * @timeout_msec: timeout in milliseconds + * + * Waiting for some bits of register to change is a common + * operation for ATA controllers. This function reads 32bit LE + * IO-mapped register @reg and tests for the following condition. + * + * (*@reg & mask) != val + * + * If the condition is met, it returns; otherwise, the process is + * repeated after @interval_msec until timeout. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * The final register value. + */ +u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, + unsigned long interval_msec, + unsigned long timeout_msec) +{ + unsigned long timeout; + u32 tmp; + + tmp = ioread32(reg); + + /* Calculate timeout _after_ the first read to make sure + * preceding writes reach the controller before starting to + * eat away the timeout. + */ + timeout = jiffies + (timeout_msec * HZ) / 1000; + + while ((tmp & mask) == val && time_before(jiffies, timeout)) { + msleep(interval_msec); + tmp = ioread32(reg); + } + + return tmp; +} + /* * libata is essentially a library of internal helper functions for * low-level ATA host controller drivers. As such, the API/ABI is @@ -4902,15 +5806,20 @@ int ata_ratelimit(void) * Do not depend on ABI/API stability. */ +EXPORT_SYMBOL_GPL(sata_deb_timing_boot); +EXPORT_SYMBOL_GPL(sata_deb_timing_eh); +EXPORT_SYMBOL_GPL(sata_deb_timing_before_fsrst); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_std_ports); EXPORT_SYMBOL_GPL(ata_device_add); +EXPORT_SYMBOL_GPL(ata_port_detach); EXPORT_SYMBOL_GPL(ata_host_set_remove); EXPORT_SYMBOL_GPL(ata_sg_init); EXPORT_SYMBOL_GPL(ata_sg_init_one); -EXPORT_SYMBOL_GPL(__ata_qc_complete); +EXPORT_SYMBOL_GPL(ata_hsm_move); +EXPORT_SYMBOL_GPL(ata_qc_complete); +EXPORT_SYMBOL_GPL(ata_qc_complete_multiple); EXPORT_SYMBOL_GPL(ata_qc_issue_prot); -EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_tf_load); EXPORT_SYMBOL_GPL(ata_tf_read); EXPORT_SYMBOL_GPL(ata_noop_dev_select); @@ -4924,6 +5833,9 @@ EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_stop); EXPORT_SYMBOL_GPL(ata_host_stop); EXPORT_SYMBOL_GPL(ata_interrupt); +EXPORT_SYMBOL_GPL(ata_mmio_data_xfer); +EXPORT_SYMBOL_GPL(ata_pio_data_xfer); +EXPORT_SYMBOL_GPL(ata_pio_data_xfer_noirq); EXPORT_SYMBOL_GPL(ata_qc_prep); EXPORT_SYMBOL_GPL(ata_noop_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup); @@ -4931,33 +5843,46 @@ EXPORT_SYMBOL_GPL(ata_bmdma_start); EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); EXPORT_SYMBOL_GPL(ata_bmdma_status); EXPORT_SYMBOL_GPL(ata_bmdma_stop); +EXPORT_SYMBOL_GPL(ata_bmdma_freeze); +EXPORT_SYMBOL_GPL(ata_bmdma_thaw); +EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh); +EXPORT_SYMBOL_GPL(ata_bmdma_error_handler); +EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd); EXPORT_SYMBOL_GPL(ata_port_probe); +EXPORT_SYMBOL_GPL(sata_set_spd); +EXPORT_SYMBOL_GPL(sata_phy_debounce); +EXPORT_SYMBOL_GPL(sata_phy_resume); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); -EXPORT_SYMBOL_GPL(ata_std_probeinit); +EXPORT_SYMBOL_GPL(ata_std_prereset); EXPORT_SYMBOL_GPL(ata_std_softreset); EXPORT_SYMBOL_GPL(sata_std_hardreset); EXPORT_SYMBOL_GPL(ata_std_postreset); -EXPORT_SYMBOL_GPL(ata_std_probe_reset); -EXPORT_SYMBOL_GPL(ata_drive_probe_reset); EXPORT_SYMBOL_GPL(ata_dev_revalidate); EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_pair); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); +EXPORT_SYMBOL_GPL(ata_wait_register); EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); +EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy); +EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); +EXPORT_SYMBOL_GPL(sata_scr_valid); +EXPORT_SYMBOL_GPL(sata_scr_read); +EXPORT_SYMBOL_GPL(sata_scr_write); +EXPORT_SYMBOL_GPL(sata_scr_write_flush); +EXPORT_SYMBOL_GPL(ata_port_online); +EXPORT_SYMBOL_GPL(ata_port_offline); EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_c_string); EXPORT_SYMBOL_GPL(ata_scsi_simulate); -EXPORT_SYMBOL_GPL(ata_eh_qc_complete); -EXPORT_SYMBOL_GPL(ata_eh_qc_retry); EXPORT_SYMBOL_GPL(ata_pio_need_iordy); EXPORT_SYMBOL_GPL(ata_timing_compute); @@ -4979,3 +5904,13 @@ EXPORT_SYMBOL_GPL(ata_device_suspend); EXPORT_SYMBOL_GPL(ata_device_resume); EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); EXPORT_SYMBOL_GPL(ata_scsi_device_resume); + +EXPORT_SYMBOL_GPL(ata_eng_timeout); +EXPORT_SYMBOL_GPL(ata_port_schedule_eh); +EXPORT_SYMBOL_GPL(ata_port_abort); +EXPORT_SYMBOL_GPL(ata_port_freeze); +EXPORT_SYMBOL_GPL(ata_eh_freeze_port); +EXPORT_SYMBOL_GPL(ata_eh_thaw_port); +EXPORT_SYMBOL_GPL(ata_eh_qc_complete); +EXPORT_SYMBOL_GPL(ata_eh_qc_retry); +EXPORT_SYMBOL_GPL(ata_do_eh); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c new file mode 100644 index 0000000..8233859 --- /dev/null +++ b/drivers/scsi/libata-eh.c @@ -0,0 +1,1907 @@ +/* + * libata-eh.c - libata error handling + * + * Maintained by: Jeff Garzik + * Please ALWAYS copy linux-ide@vger.kernel.org + * on emails. + * + * Copyright 2006 Tejun Heo + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, + * USA. + * + * + * libata documentation is available via 'make {ps|pdf}docs', + * as Documentation/DocBook/libata.* + * + * Hardware documentation available from http://www.t13.org/ and + * http://www.sata-io.org/ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "scsi_transport_api.h" + +#include + +#include "libata.h" + +static void __ata_port_freeze(struct ata_port *ap); +static void ata_eh_finish(struct ata_port *ap); + +static void ata_ering_record(struct ata_ering *ering, int is_io, + unsigned int err_mask) +{ + struct ata_ering_entry *ent; + + WARN_ON(!err_mask); + + ering->cursor++; + ering->cursor %= ATA_ERING_SIZE; + + ent = &ering->ring[ering->cursor]; + ent->is_io = is_io; + ent->err_mask = err_mask; + ent->timestamp = get_jiffies_64(); +} + +static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering) +{ + struct ata_ering_entry *ent = &ering->ring[ering->cursor]; + if (!ent->err_mask) + return NULL; + return ent; +} + +static int ata_ering_map(struct ata_ering *ering, + int (*map_fn)(struct ata_ering_entry *, void *), + void *arg) +{ + int idx, rc = 0; + struct ata_ering_entry *ent; + + idx = ering->cursor; + do { + ent = &ering->ring[idx]; + if (!ent->err_mask) + break; + rc = map_fn(ent, arg); + if (rc) + break; + idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE; + } while (idx != ering->cursor); + + return rc; +} + +/** + * ata_scsi_timed_out - SCSI layer time out callback + * @cmd: timed out SCSI command + * + * Handles SCSI layer timeout. We race with normal completion of + * the qc for @cmd. If the qc is already gone, we lose and let + * the scsi command finish (EH_HANDLED). Otherwise, the qc has + * timed out and EH should be invoked. Prevent ata_qc_complete() + * from finishing it by setting EH_SCHEDULED and return + * EH_NOT_HANDLED. + * + * TODO: kill this function once old EH is gone. + * + * LOCKING: + * Called from timer context + * + * RETURNS: + * EH_HANDLED or EH_NOT_HANDLED + */ +enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *host = cmd->device->host; + struct ata_port *ap = ata_shost_to_port(host); + unsigned long flags; + struct ata_queued_cmd *qc; + enum scsi_eh_timer_return ret; + + DPRINTK("ENTER\n"); + + if (ap->ops->error_handler) { + ret = EH_NOT_HANDLED; + goto out; + } + + ret = EH_HANDLED; + spin_lock_irqsave(ap->lock, flags); + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc) { + WARN_ON(qc->scsicmd != cmd); + qc->flags |= ATA_QCFLAG_EH_SCHEDULED; + qc->err_mask |= AC_ERR_TIMEOUT; + ret = EH_NOT_HANDLED; + } + spin_unlock_irqrestore(ap->lock, flags); + + out: + DPRINTK("EXIT, ret=%d\n", ret); + return ret; +} + +/** + * ata_scsi_error - SCSI layer error handler callback + * @host: SCSI host on which error occurred + * + * Handles SCSI-layer-thrown error events. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + * + * RETURNS: + * Zero. + */ +void ata_scsi_error(struct Scsi_Host *host) +{ + struct ata_port *ap = ata_shost_to_port(host); + spinlock_t *ap_lock = ap->lock; + int i, repeat_cnt = ATA_EH_MAX_REPEAT; + unsigned long flags; + + DPRINTK("ENTER\n"); + + /* synchronize with port task */ + ata_port_flush_task(ap); + + /* synchronize with host_set lock and sort out timeouts */ + + /* For new EH, all qcs are finished in one of three ways - + * normal completion, error completion, and SCSI timeout. + * Both cmpletions can race against SCSI timeout. When normal + * completion wins, the qc never reaches EH. When error + * completion wins, the qc has ATA_QCFLAG_FAILED set. + * + * When SCSI timeout wins, things are a bit more complex. + * Normal or error completion can occur after the timeout but + * before this point. In such cases, both types of + * completions are honored. A scmd is determined to have + * timed out iff its associated qc is active and not failed. + */ + if (ap->ops->error_handler) { + struct scsi_cmnd *scmd, *tmp; + int nr_timedout = 0; + + spin_lock_irqsave(ap_lock, flags); + + list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) { + struct ata_queued_cmd *qc; + + for (i = 0; i < ATA_MAX_QUEUE; i++) { + qc = __ata_qc_from_tag(ap, i); + if (qc->flags & ATA_QCFLAG_ACTIVE && + qc->scsicmd == scmd) + break; + } + + if (i < ATA_MAX_QUEUE) { + /* the scmd has an associated qc */ + if (!(qc->flags & ATA_QCFLAG_FAILED)) { + /* which hasn't failed yet, timeout */ + qc->err_mask |= AC_ERR_TIMEOUT; + qc->flags |= ATA_QCFLAG_FAILED; + nr_timedout++; + } + } else { + /* Normal completion occurred after + * SCSI timeout but before this point. + * Successfully complete it. + */ + scmd->retries = scmd->allowed; + scsi_eh_finish_cmd(scmd, &ap->eh_done_q); + } + } + + /* If we have timed out qcs. They belong to EH from + * this point but the state of the controller is + * unknown. Freeze the port to make sure the IRQ + * handler doesn't diddle with those qcs. This must + * be done atomically w.r.t. setting QCFLAG_FAILED. + */ + if (nr_timedout) + __ata_port_freeze(ap); + + spin_unlock_irqrestore(ap_lock, flags); + } else + spin_unlock_wait(ap_lock); + + repeat: + /* invoke error handler */ + if (ap->ops->error_handler) { + /* fetch & clear EH info */ + spin_lock_irqsave(ap_lock, flags); + + memset(&ap->eh_context, 0, sizeof(ap->eh_context)); + ap->eh_context.i = ap->eh_info; + memset(&ap->eh_info, 0, sizeof(ap->eh_info)); + + ap->flags |= ATA_FLAG_EH_IN_PROGRESS; + ap->flags &= ~ATA_FLAG_EH_PENDING; + + spin_unlock_irqrestore(ap_lock, flags); + + /* invoke EH. if unloading, just finish failed qcs */ + if (!(ap->flags & ATA_FLAG_UNLOADING)) + ap->ops->error_handler(ap); + else + ata_eh_finish(ap); + + /* Exception might have happend after ->error_handler + * recovered the port but before this point. Repeat + * EH in such case. + */ + spin_lock_irqsave(ap_lock, flags); + + if (ap->flags & ATA_FLAG_EH_PENDING) { + if (--repeat_cnt) { + ata_port_printk(ap, KERN_INFO, + "EH pending after completion, " + "repeating EH (cnt=%d)\n", repeat_cnt); + spin_unlock_irqrestore(ap_lock, flags); + goto repeat; + } + ata_port_printk(ap, KERN_ERR, "EH pending after %d " + "tries, giving up\n", ATA_EH_MAX_REPEAT); + } + + /* this run is complete, make sure EH info is clear */ + memset(&ap->eh_info, 0, sizeof(ap->eh_info)); + + /* Clear host_eh_scheduled while holding ap_lock such + * that if exception occurs after this point but + * before EH completion, SCSI midlayer will + * re-initiate EH. + */ + host->host_eh_scheduled = 0; + + spin_unlock_irqrestore(ap_lock, flags); + } else { + WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); + ap->ops->eng_timeout(ap); + } + + /* finish or retry handled scmd's and clean up */ + WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); + + scsi_eh_flush_done_q(&ap->eh_done_q); + + /* clean up */ + spin_lock_irqsave(ap_lock, flags); + + if (ap->flags & ATA_FLAG_LOADING) { + ap->flags &= ~ATA_FLAG_LOADING; + } else { + if (ap->flags & ATA_FLAG_SCSI_HOTPLUG) + queue_work(ata_aux_wq, &ap->hotplug_task); + if (ap->flags & ATA_FLAG_RECOVERED) + ata_port_printk(ap, KERN_INFO, "EH complete\n"); + } + + ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG | ATA_FLAG_RECOVERED); + + /* tell wait_eh that we're done */ + ap->flags &= ~ATA_FLAG_EH_IN_PROGRESS; + wake_up_all(&ap->eh_wait_q); + + spin_unlock_irqrestore(ap_lock, flags); + + DPRINTK("EXIT\n"); +} + +/** + * ata_port_wait_eh - Wait for the currently pending EH to complete + * @ap: Port to wait EH for + * + * Wait until the currently pending EH is complete. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_port_wait_eh(struct ata_port *ap) +{ + unsigned long flags; + DEFINE_WAIT(wait); + + retry: + spin_lock_irqsave(ap->lock, flags); + + while (ap->flags & (ATA_FLAG_EH_PENDING | ATA_FLAG_EH_IN_PROGRESS)) { + prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE); + spin_unlock_irqrestore(ap->lock, flags); + schedule(); + spin_lock_irqsave(ap->lock, flags); + } + finish_wait(&ap->eh_wait_q, &wait); + + spin_unlock_irqrestore(ap->lock, flags); + + /* make sure SCSI EH is complete */ + if (scsi_host_in_recovery(ap->host)) { + msleep(10); + goto retry; + } +} + +/** + * ata_qc_timeout - Handle timeout of queued command + * @qc: Command that timed out + * + * Some part of the kernel (currently, only the SCSI layer) + * has noticed that the active command on port @ap has not + * completed after a specified length of time. Handle this + * condition by disabling DMA (if necessary) and completing + * transactions, with error if necessary. + * + * This also handles the case of the "lost interrupt", where + * for some reason (possibly hardware bug, possibly driver bug) + * an interrupt was not delivered to the driver, even though the + * transaction completed successfully. + * + * TODO: kill this function once old EH is gone. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + */ +static void ata_qc_timeout(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + u8 host_stat = 0, drv_stat; + unsigned long flags; + + DPRINTK("ENTER\n"); + + ap->hsm_task_state = HSM_ST_IDLE; + + spin_lock_irqsave(ap->lock, flags); + + switch (qc->tf.protocol) { + + case ATA_PROT_DMA: + case ATA_PROT_ATAPI_DMA: + host_stat = ap->ops->bmdma_status(ap); + + /* before we do anything else, clear DMA-Start bit */ + ap->ops->bmdma_stop(qc); + + /* fall through */ + + default: + ata_altstatus(ap); + drv_stat = ata_chk_status(ap); + + /* ack bmdma irq events */ + ap->ops->irq_clear(ap); + + ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, " + "stat 0x%x host_stat 0x%x\n", + qc->tf.command, drv_stat, host_stat); + + /* complete taskfile transaction */ + qc->err_mask |= AC_ERR_TIMEOUT; + break; + } + + spin_unlock_irqrestore(ap->lock, flags); + + ata_eh_qc_complete(qc); + + DPRINTK("EXIT\n"); +} + +/** + * ata_eng_timeout - Handle timeout of queued command + * @ap: Port on which timed-out command is active + * + * Some part of the kernel (currently, only the SCSI layer) + * has noticed that the active command on port @ap has not + * completed after a specified length of time. Handle this + * condition by disabling DMA (if necessary) and completing + * transactions, with error if necessary. + * + * This also handles the case of the "lost interrupt", where + * for some reason (possibly hardware bug, possibly driver bug) + * an interrupt was not delivered to the driver, even though the + * transaction completed successfully. + * + * TODO: kill this function once old EH is gone. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + */ +void ata_eng_timeout(struct ata_port *ap) +{ + DPRINTK("ENTER\n"); + + ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag)); + + DPRINTK("EXIT\n"); +} + +/** + * ata_qc_schedule_eh - schedule qc for error handling + * @qc: command to schedule error handling for + * + * Schedule error handling for @qc. EH will kick in as soon as + * other commands are drained. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_qc_schedule_eh(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + WARN_ON(!ap->ops->error_handler); + + qc->flags |= ATA_QCFLAG_FAILED; + qc->ap->flags |= ATA_FLAG_EH_PENDING; + + /* The following will fail if timeout has already expired. + * ata_scsi_error() takes care of such scmds on EH entry. + * Note that ATA_QCFLAG_FAILED is unconditionally set after + * this function completes. + */ + scsi_req_abort_cmd(qc->scsicmd); +} + +/** + * ata_port_schedule_eh - schedule error handling without a qc + * @ap: ATA port to schedule EH for + * + * Schedule error handling for @ap. EH will kick in as soon as + * all commands are drained. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_port_schedule_eh(struct ata_port *ap) +{ + WARN_ON(!ap->ops->error_handler); + + ap->flags |= ATA_FLAG_EH_PENDING; + scsi_schedule_eh(ap->host); + + DPRINTK("port EH scheduled\n"); +} + +/** + * ata_port_abort - abort all qc's on the port + * @ap: ATA port to abort qc's for + * + * Abort all active qc's of @ap and schedule EH. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Number of aborted qc's. + */ +int ata_port_abort(struct ata_port *ap) +{ + int tag, nr_aborted = 0; + + WARN_ON(!ap->ops->error_handler); + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag); + + if (qc) { + qc->flags |= ATA_QCFLAG_FAILED; + ata_qc_complete(qc); + nr_aborted++; + } + } + + if (!nr_aborted) + ata_port_schedule_eh(ap); + + return nr_aborted; +} + +/** + * __ata_port_freeze - freeze port + * @ap: ATA port to freeze + * + * This function is called when HSM violation or some other + * condition disrupts normal operation of the port. Frozen port + * is not allowed to perform any operation until the port is + * thawed, which usually follows a successful reset. + * + * ap->ops->freeze() callback can be used for freezing the port + * hardware-wise (e.g. mask interrupt and stop DMA engine). If a + * port cannot be frozen hardware-wise, the interrupt handler + * must ack and clear interrupts unconditionally while the port + * is frozen. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +static void __ata_port_freeze(struct ata_port *ap) +{ + WARN_ON(!ap->ops->error_handler); + + if (ap->ops->freeze) + ap->ops->freeze(ap); + + ap->flags |= ATA_FLAG_FROZEN; + + DPRINTK("ata%u port frozen\n", ap->id); +} + +/** + * ata_port_freeze - abort & freeze port + * @ap: ATA port to freeze + * + * Abort and freeze @ap. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Number of aborted commands. + */ +int ata_port_freeze(struct ata_port *ap) +{ + int nr_aborted; + + WARN_ON(!ap->ops->error_handler); + + nr_aborted = ata_port_abort(ap); + __ata_port_freeze(ap); + + return nr_aborted; +} + +/** + * ata_eh_freeze_port - EH helper to freeze port + * @ap: ATA port to freeze + * + * Freeze @ap. + * + * LOCKING: + * None. + */ +void ata_eh_freeze_port(struct ata_port *ap) +{ + unsigned long flags; + + if (!ap->ops->error_handler) + return; + + spin_lock_irqsave(ap->lock, flags); + __ata_port_freeze(ap); + spin_unlock_irqrestore(ap->lock, flags); +} + +/** + * ata_port_thaw_port - EH helper to thaw port + * @ap: ATA port to thaw + * + * Thaw frozen port @ap. + * + * LOCKING: + * None. + */ +void ata_eh_thaw_port(struct ata_port *ap) +{ + unsigned long flags; + + if (!ap->ops->error_handler) + return; + + spin_lock_irqsave(ap->lock, flags); + + ap->flags &= ~ATA_FLAG_FROZEN; + + if (ap->ops->thaw) + ap->ops->thaw(ap); + + spin_unlock_irqrestore(ap->lock, flags); + + DPRINTK("ata%u port thawed\n", ap->id); +} + +static void ata_eh_scsidone(struct scsi_cmnd *scmd) +{ + /* nada */ +} + +static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scsi_cmnd *scmd = qc->scsicmd; + unsigned long flags; + + spin_lock_irqsave(ap->lock, flags); + qc->scsidone = ata_eh_scsidone; + __ata_qc_complete(qc); + WARN_ON(ata_tag_valid(qc->tag)); + spin_unlock_irqrestore(ap->lock, flags); + + scsi_eh_finish_cmd(scmd, &ap->eh_done_q); +} + +/** + * ata_eh_qc_complete - Complete an active ATA command from EH + * @qc: Command to complete + * + * Indicate to the mid and upper layers that an ATA command has + * completed. To be used from EH. + */ +void ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + scmd->retries = scmd->allowed; + __ata_eh_qc_complete(qc); +} + +/** + * ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH + * @qc: Command to retry + * + * Indicate to the mid and upper layers that an ATA command + * should be retried. To be used from EH. + * + * SCSI midlayer limits the number of retries to scmd->allowed. + * scmd->retries is decremented for commands which get retried + * due to unrelated failures (qc->err_mask is zero). + */ +void ata_eh_qc_retry(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + if (!qc->err_mask && scmd->retries) + scmd->retries--; + __ata_eh_qc_complete(qc); +} + +/** + * ata_eh_detach_dev - detach ATA device + * @dev: ATA device to detach + * + * Detach @dev. + * + * LOCKING: + * None. + */ +static void ata_eh_detach_dev(struct ata_device *dev) +{ + struct ata_port *ap = dev->ap; + unsigned long flags; + + ata_dev_disable(dev); + + spin_lock_irqsave(ap->lock, flags); + + dev->flags &= ~ATA_DFLAG_DETACH; + + if (ata_scsi_offline_dev(dev)) { + dev->flags |= ATA_DFLAG_DETACHED; + ap->flags |= ATA_FLAG_SCSI_HOTPLUG; + } + + spin_unlock_irqrestore(ap->lock, flags); +} + +static void ata_eh_clear_action(struct ata_device *dev, + struct ata_eh_info *ehi, unsigned int action) +{ + int i; + + if (!dev) { + ehi->action &= ~action; + for (i = 0; i < ATA_MAX_DEVICES; i++) + ehi->dev_action[i] &= ~action; + } else { + /* doesn't make sense for port-wide EH actions */ + WARN_ON(!(action & ATA_EH_PERDEV_MASK)); + + /* break ehi->action into ehi->dev_action */ + if (ehi->action & action) { + for (i = 0; i < ATA_MAX_DEVICES; i++) + ehi->dev_action[i] |= ehi->action & action; + ehi->action &= ~action; + } + + /* turn off the specified per-dev action */ + ehi->dev_action[dev->devno] &= ~action; + } +} + +/** + * ata_eh_about_to_do - about to perform eh_action + * @ap: target ATA port + * @dev: target ATA dev for per-dev action (can be NULL) + * @action: action about to be performed + * + * Called just before performing EH actions to clear related bits + * in @ap->eh_info such that eh actions are not unnecessarily + * repeated. + * + * LOCKING: + * None. + */ +static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev, + unsigned int action) +{ + unsigned long flags; + + spin_lock_irqsave(ap->lock, flags); + ata_eh_clear_action(dev, &ap->eh_info, action); + ap->flags |= ATA_FLAG_RECOVERED; + spin_unlock_irqrestore(ap->lock, flags); +} + +/** + * ata_eh_done - EH action complete + * @ap: target ATA port + * @dev: target ATA dev for per-dev action (can be NULL) + * @action: action just completed + * + * Called right after performing EH actions to clear related bits + * in @ap->eh_context. + * + * LOCKING: + * None. + */ +static void ata_eh_done(struct ata_port *ap, struct ata_device *dev, + unsigned int action) +{ + ata_eh_clear_action(dev, &ap->eh_context.i, action); +} + +/** + * ata_err_string - convert err_mask to descriptive string + * @err_mask: error mask to convert to string + * + * Convert @err_mask to descriptive string. Errors are + * prioritized according to severity and only the most severe + * error is reported. + * + * LOCKING: + * None. + * + * RETURNS: + * Descriptive string for @err_mask + */ +static const char * ata_err_string(unsigned int err_mask) +{ + if (err_mask & AC_ERR_HOST_BUS) + return "host bus error"; + if (err_mask & AC_ERR_ATA_BUS) + return "ATA bus error"; + if (err_mask & AC_ERR_TIMEOUT) + return "timeout"; + if (err_mask & AC_ERR_HSM) + return "HSM violation"; + if (err_mask & AC_ERR_SYSTEM) + return "internal error"; + if (err_mask & AC_ERR_MEDIA) + return "media error"; + if (err_mask & AC_ERR_INVALID) + return "invalid argument"; + if (err_mask & AC_ERR_DEV) + return "device error"; + return "unknown error"; +} + +/** + * ata_read_log_page - read a specific log page + * @dev: target device + * @page: page to read + * @buf: buffer to store read page + * @sectors: number of sectors to read + * + * Read log page using READ_LOG_EXT command. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, AC_ERR_* mask otherwise. + */ +static unsigned int ata_read_log_page(struct ata_device *dev, + u8 page, void *buf, unsigned int sectors) +{ + struct ata_taskfile tf; + unsigned int err_mask; + + DPRINTK("read log page - page %d\n", page); + + ata_tf_init(dev, &tf); + tf.command = ATA_CMD_READ_LOG_EXT; + tf.lbal = page; + tf.nsect = sectors; + tf.hob_nsect = sectors >> 8; + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE; + tf.protocol = ATA_PROT_PIO; + + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, + buf, sectors * ATA_SECT_SIZE); + + DPRINTK("EXIT, err_mask=%x\n", err_mask); + return err_mask; +} + +/** + * ata_eh_read_log_10h - Read log page 10h for NCQ error details + * @dev: Device to read log page 10h from + * @tag: Resulting tag of the failed command + * @tf: Resulting taskfile registers of the failed command + * + * Read log page 10h to obtain NCQ error details and clear error + * condition. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +static int ata_eh_read_log_10h(struct ata_device *dev, + int *tag, struct ata_taskfile *tf) +{ + u8 *buf = dev->ap->sector_buf; + unsigned int err_mask; + u8 csum; + int i; + + err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1); + if (err_mask) + return -EIO; + + csum = 0; + for (i = 0; i < ATA_SECT_SIZE; i++) + csum += buf[i]; + if (csum) + ata_dev_printk(dev, KERN_WARNING, + "invalid checksum 0x%x on log page 10h\n", csum); + + if (buf[0] & 0x80) + return -ENOENT; + + *tag = buf[0] & 0x1f; + + tf->command = buf[2]; + tf->feature = buf[3]; + tf->lbal = buf[4]; + tf->lbam = buf[5]; + tf->lbah = buf[6]; + tf->device = buf[7]; + tf->hob_lbal = buf[8]; + tf->hob_lbam = buf[9]; + tf->hob_lbah = buf[10]; + tf->nsect = buf[12]; + tf->hob_nsect = buf[13]; + + return 0; +} + +/** + * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE + * @dev: device to perform REQUEST_SENSE to + * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) + * + * Perform ATAPI REQUEST_SENSE after the device reported CHECK + * SENSE. This function is EH helper. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, AC_ERR_* mask on failure + */ +static unsigned int atapi_eh_request_sense(struct ata_device *dev, + unsigned char *sense_buf) +{ + struct ata_port *ap = dev->ap; + struct ata_taskfile tf; + u8 cdb[ATAPI_CDB_LEN]; + + DPRINTK("ATAPI request sense\n"); + + ata_tf_init(dev, &tf); + + /* FIXME: is this needed? */ + memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE); + + /* XXX: why tf_read here? */ + ap->ops->tf_read(ap, &tf); + + /* fill these in, for the case where they are -not- overwritten */ + sense_buf[0] = 0x70; + sense_buf[2] = tf.feature >> 4; + + memset(cdb, 0, ATAPI_CDB_LEN); + cdb[0] = REQUEST_SENSE; + cdb[4] = SCSI_SENSE_BUFFERSIZE; + + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf.command = ATA_CMD_PACKET; + + /* is it pointless to prefer PIO for "safety reasons"? */ + if (ap->flags & ATA_FLAG_PIO_DMA) { + tf.protocol = ATA_PROT_ATAPI_DMA; + tf.feature |= ATAPI_PKT_DMA; + } else { + tf.protocol = ATA_PROT_ATAPI; + tf.lbam = (8 * 1024) & 0xff; + tf.lbah = (8 * 1024) >> 8; + } + + return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE, + sense_buf, SCSI_SENSE_BUFFERSIZE); +} + +/** + * ata_eh_analyze_serror - analyze SError for a failed port + * @ap: ATA port to analyze SError for + * + * Analyze SError if available and further determine cause of + * failure. + * + * LOCKING: + * None. + */ +static void ata_eh_analyze_serror(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + u32 serror = ehc->i.serror; + unsigned int err_mask = 0, action = 0; + + if (serror & SERR_PERSISTENT) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_HARDRESET; + } + if (serror & + (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_SOFTRESET; + } + if (serror & SERR_PROTOCOL) { + err_mask |= AC_ERR_HSM; + action |= ATA_EH_SOFTRESET; + } + if (serror & SERR_INTERNAL) { + err_mask |= AC_ERR_SYSTEM; + action |= ATA_EH_SOFTRESET; + } + if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) + ata_ehi_hotplugged(&ehc->i); + + ehc->i.err_mask |= err_mask; + ehc->i.action |= action; +} + +/** + * ata_eh_analyze_ncq_error - analyze NCQ error + * @ap: ATA port to analyze NCQ error for + * + * Read log page 10h, determine the offending qc and acquire + * error status TF. For NCQ device errors, all LLDDs have to do + * is setting AC_ERR_DEV in ehi->err_mask. This function takes + * care of the rest. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_eh_analyze_ncq_error(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + struct ata_device *dev = ap->device; + struct ata_queued_cmd *qc; + struct ata_taskfile tf; + int tag, rc; + + /* if frozen, we can't do much */ + if (ap->flags & ATA_FLAG_FROZEN) + return; + + /* is it NCQ device error? */ + if (!ap->sactive || !(ehc->i.err_mask & AC_ERR_DEV)) + return; + + /* has LLDD analyzed already? */ + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + + if (qc->err_mask) + return; + } + + /* okay, this error is ours */ + rc = ata_eh_read_log_10h(dev, &tag, &tf); + if (rc) { + ata_port_printk(ap, KERN_ERR, "failed to read log page 10h " + "(errno=%d)\n", rc); + return; + } + + if (!(ap->sactive & (1 << tag))) { + ata_port_printk(ap, KERN_ERR, "log page 10h reported " + "inactive tag %d\n", tag); + return; + } + + /* we've got the perpetrator, condemn it */ + qc = __ata_qc_from_tag(ap, tag); + memcpy(&qc->result_tf, &tf, sizeof(tf)); + qc->err_mask |= AC_ERR_DEV; + ehc->i.err_mask &= ~AC_ERR_DEV; +} + +/** + * ata_eh_analyze_tf - analyze taskfile of a failed qc + * @qc: qc to analyze + * @tf: Taskfile registers to analyze + * + * Analyze taskfile of @qc and further determine cause of + * failure. This function also requests ATAPI sense data if + * avaliable. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * Determined recovery action + */ +static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, + const struct ata_taskfile *tf) +{ + unsigned int tmp, action = 0; + u8 stat = tf->command, err = tf->feature; + + if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) { + qc->err_mask |= AC_ERR_HSM; + return ATA_EH_SOFTRESET; + } + + if (!(qc->err_mask & AC_ERR_DEV)) + return 0; + + switch (qc->dev->class) { + case ATA_DEV_ATA: + if (err & ATA_ICRC) + qc->err_mask |= AC_ERR_ATA_BUS; + if (err & ATA_UNC) + qc->err_mask |= AC_ERR_MEDIA; + if (err & ATA_IDNF) + qc->err_mask |= AC_ERR_INVALID; + break; + + case ATA_DEV_ATAPI: + tmp = atapi_eh_request_sense(qc->dev, + qc->scsicmd->sense_buffer); + if (!tmp) { + /* ATA_QCFLAG_SENSE_VALID is used to tell + * atapi_qc_complete() that sense data is + * already valid. + * + * TODO: interpret sense data and set + * appropriate err_mask. + */ + qc->flags |= ATA_QCFLAG_SENSE_VALID; + } else + qc->err_mask |= tmp; + } + + if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS)) + action |= ATA_EH_SOFTRESET; + + return action; +} + +static int ata_eh_categorize_ering_entry(struct ata_ering_entry *ent) +{ + if (ent->err_mask & (AC_ERR_ATA_BUS | AC_ERR_TIMEOUT)) + return 1; + + if (ent->is_io) { + if (ent->err_mask & AC_ERR_HSM) + return 1; + if ((ent->err_mask & + (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV) + return 2; + } + + return 0; +} + +struct speed_down_needed_arg { + u64 since; + int nr_errors[3]; +}; + +static int speed_down_needed_cb(struct ata_ering_entry *ent, void *void_arg) +{ + struct speed_down_needed_arg *arg = void_arg; + + if (ent->timestamp < arg->since) + return -1; + + arg->nr_errors[ata_eh_categorize_ering_entry(ent)]++; + return 0; +} + +/** + * ata_eh_speed_down_needed - Determine wheter speed down is necessary + * @dev: Device of interest + * + * This function examines error ring of @dev and determines + * whether speed down is necessary. Speed down is necessary if + * there have been more than 3 of Cat-1 errors or 10 of Cat-2 + * errors during last 15 minutes. + * + * Cat-1 errors are ATA_BUS, TIMEOUT for any command and HSM + * violation for known supported commands. + * + * Cat-2 errors are unclassified DEV error for known supported + * command. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 1 if speed down is necessary, 0 otherwise + */ +static int ata_eh_speed_down_needed(struct ata_device *dev) +{ + const u64 interval = 15LLU * 60 * HZ; + static const int err_limits[3] = { -1, 3, 10 }; + struct speed_down_needed_arg arg; + struct ata_ering_entry *ent; + int err_cat; + u64 j64; + + ent = ata_ering_top(&dev->ering); + if (!ent) + return 0; + + err_cat = ata_eh_categorize_ering_entry(ent); + if (err_cat == 0) + return 0; + + memset(&arg, 0, sizeof(arg)); + + j64 = get_jiffies_64(); + if (j64 >= interval) + arg.since = j64 - interval; + else + arg.since = 0; + + ata_ering_map(&dev->ering, speed_down_needed_cb, &arg); + + return arg.nr_errors[err_cat] > err_limits[err_cat]; +} + +/** + * ata_eh_speed_down - record error and speed down if necessary + * @dev: Failed device + * @is_io: Did the device fail during normal IO? + * @err_mask: err_mask of the error + * + * Record error and examine error history to determine whether + * adjusting transmission speed is necessary. It also sets + * transmission limits appropriately if such adjustment is + * necessary. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise + */ +static int ata_eh_speed_down(struct ata_device *dev, int is_io, + unsigned int err_mask) +{ + if (!err_mask) + return 0; + + /* record error and determine whether speed down is necessary */ + ata_ering_record(&dev->ering, is_io, err_mask); + + if (!ata_eh_speed_down_needed(dev)) + return 0; + + /* speed down SATA link speed if possible */ + if (sata_down_spd_limit(dev->ap) == 0) + return ATA_EH_HARDRESET; + + /* lower transfer mode */ + if (ata_down_xfermask_limit(dev, 0) == 0) + return ATA_EH_SOFTRESET; + + ata_dev_printk(dev, KERN_ERR, + "speed down requested but no transfer mode left\n"); + return 0; +} + +/** + * ata_eh_autopsy - analyze error and determine recovery action + * @ap: ATA port to perform autopsy on + * + * Analyze why @ap failed and determine which recovery action is + * needed. This function also sets more detailed AC_ERR_* values + * and fills sense data for ATAPI CHECK SENSE. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_eh_autopsy(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + unsigned int action = ehc->i.action; + struct ata_device *failed_dev = NULL; + unsigned int all_err_mask = 0; + int tag, is_io = 0; + u32 serror; + int rc; + + DPRINTK("ENTER\n"); + + /* obtain and analyze SError */ + rc = sata_scr_read(ap, SCR_ERROR, &serror); + if (rc == 0) { + ehc->i.serror |= serror; + ata_eh_analyze_serror(ap); + } else if (rc != -EOPNOTSUPP) + action |= ATA_EH_HARDRESET; + + /* analyze NCQ failure */ + ata_eh_analyze_ncq_error(ap); + + /* any real error trumps AC_ERR_OTHER */ + if (ehc->i.err_mask & ~AC_ERR_OTHER) + ehc->i.err_mask &= ~AC_ERR_OTHER; + + all_err_mask |= ehc->i.err_mask; + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + + /* inherit upper level err_mask */ + qc->err_mask |= ehc->i.err_mask; + + /* analyze TF */ + action |= ata_eh_analyze_tf(qc, &qc->result_tf); + + /* DEV errors are probably spurious in case of ATA_BUS error */ + if (qc->err_mask & AC_ERR_ATA_BUS) + qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_MEDIA | + AC_ERR_INVALID); + + /* any real error trumps unknown error */ + if (qc->err_mask & ~AC_ERR_OTHER) + qc->err_mask &= ~AC_ERR_OTHER; + + /* SENSE_VALID trumps dev/unknown error and revalidation */ + if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); + action &= ~ATA_EH_REVALIDATE; + } + + /* accumulate error info */ + failed_dev = qc->dev; + all_err_mask |= qc->err_mask; + if (qc->flags & ATA_QCFLAG_IO) + is_io = 1; + } + + /* enforce default EH actions */ + if (ap->flags & ATA_FLAG_FROZEN || + all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) + action |= ATA_EH_SOFTRESET; + else if (all_err_mask) + action |= ATA_EH_REVALIDATE; + + /* if we have offending qcs and the associated failed device */ + if (failed_dev) { + /* speed down */ + action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask); + + /* perform per-dev EH action only on the offending device */ + ehc->i.dev_action[failed_dev->devno] |= + action & ATA_EH_PERDEV_MASK; + action &= ~ATA_EH_PERDEV_MASK; + } + + /* record autopsy result */ + ehc->i.dev = failed_dev; + ehc->i.action = action; + + DPRINTK("EXIT\n"); +} + +/** + * ata_eh_report - report error handling to user + * @ap: ATA port EH is going on + * + * Report EH to user. + * + * LOCKING: + * None. + */ +static void ata_eh_report(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + const char *frozen, *desc; + int tag, nr_failed = 0; + + desc = NULL; + if (ehc->i.desc[0] != '\0') + desc = ehc->i.desc; + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask) + continue; + + nr_failed++; + } + + if (!nr_failed && !ehc->i.err_mask) + return; + + frozen = ""; + if (ap->flags & ATA_FLAG_FROZEN) + frozen = " frozen"; + + if (ehc->i.dev) { + ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x " + "SAct 0x%x SErr 0x%x action 0x%x%s\n", + ehc->i.err_mask, ap->sactive, ehc->i.serror, + ehc->i.action, frozen); + if (desc) + ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc); + } else { + ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x " + "SAct 0x%x SErr 0x%x action 0x%x%s\n", + ehc->i.err_mask, ap->sactive, ehc->i.serror, + ehc->i.action, frozen); + if (desc) + ata_port_printk(ap, KERN_ERR, "(%s)\n", desc); + } + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask) + continue; + + ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x " + "Emask 0x%x stat 0x%x err 0x%x (%s)\n", + qc->tag, qc->tf.command, qc->err_mask, + qc->result_tf.command, qc->result_tf.feature, + ata_err_string(qc->err_mask)); + } +} + +static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, + unsigned int *classes) +{ + int i, rc; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_UNKNOWN; + + rc = reset(ap, classes); + if (rc) + return rc; + + /* If any class isn't ATA_DEV_UNKNOWN, consider classification + * is complete and convert all ATA_DEV_UNKNOWN to + * ATA_DEV_NONE. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (classes[i] != ATA_DEV_UNKNOWN) + break; + + if (i < ATA_MAX_DEVICES) + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (classes[i] == ATA_DEV_UNKNOWN) + classes[i] = ATA_DEV_NONE; + + return 0; +} + +static int ata_eh_followup_srst_needed(int rc, int classify, + const unsigned int *classes) +{ + if (rc == -EAGAIN) + return 1; + if (rc != 0) + return 0; + if (classify && classes[0] == ATA_DEV_UNKNOWN) + return 1; + return 0; +} + +static int ata_eh_reset(struct ata_port *ap, int classify, + ata_prereset_fn_t prereset, ata_reset_fn_t softreset, + ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) +{ + struct ata_eh_context *ehc = &ap->eh_context; + unsigned int *classes = ehc->classes; + int tries = ATA_EH_RESET_TRIES; + int verbose = !(ap->flags & ATA_FLAG_LOADING); + unsigned int action; + ata_reset_fn_t reset; + int i, did_followup_srst, rc; + + /* Determine which reset to use and record in ehc->i.action. + * prereset() may examine and modify it. + */ + action = ehc->i.action; + ehc->i.action &= ~ATA_EH_RESET_MASK; + if (softreset && (!hardreset || (!sata_set_spd_needed(ap) && + !(action & ATA_EH_HARDRESET)))) + ehc->i.action |= ATA_EH_SOFTRESET; + else + ehc->i.action |= ATA_EH_HARDRESET; + + if (prereset) { + rc = prereset(ap); + if (rc) { + ata_port_printk(ap, KERN_ERR, + "prereset failed (errno=%d)\n", rc); + return rc; + } + } + + /* prereset() might have modified ehc->i.action */ + if (ehc->i.action & ATA_EH_HARDRESET) + reset = hardreset; + else if (ehc->i.action & ATA_EH_SOFTRESET) + reset = softreset; + else { + /* prereset told us not to reset, bang classes and return */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_NONE; + return 0; + } + + /* did prereset() screw up? if so, fix up to avoid oopsing */ + if (!reset) { + ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested " + "invalid reset type\n"); + if (softreset) + reset = softreset; + else + reset = hardreset; + } + + retry: + /* shut up during boot probing */ + if (verbose) + ata_port_printk(ap, KERN_INFO, "%s resetting port\n", + reset == softreset ? "soft" : "hard"); + + /* reset */ + ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK); + ehc->i.flags |= ATA_EHI_DID_RESET; + + rc = ata_do_reset(ap, reset, classes); + + did_followup_srst = 0; + if (reset == hardreset && + ata_eh_followup_srst_needed(rc, classify, classes)) { + /* okay, let's do follow-up softreset */ + did_followup_srst = 1; + reset = softreset; + + if (!reset) { + ata_port_printk(ap, KERN_ERR, + "follow-up softreset required " + "but no softreset avaliable\n"); + return -EINVAL; + } + + ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK); + rc = ata_do_reset(ap, reset, classes); + + if (rc == 0 && classify && + classes[0] == ATA_DEV_UNKNOWN) { + ata_port_printk(ap, KERN_ERR, + "classification failed\n"); + return -EINVAL; + } + } + + if (rc && --tries) { + const char *type; + + if (reset == softreset) { + if (did_followup_srst) + type = "follow-up soft"; + else + type = "soft"; + } else + type = "hard"; + + ata_port_printk(ap, KERN_WARNING, + "%sreset failed, retrying in 5 secs\n", type); + ssleep(5); + + if (reset == hardreset) + sata_down_spd_limit(ap); + if (hardreset) + reset = hardreset; + goto retry; + } + + if (rc == 0) { + /* After the reset, the device state is PIO 0 and the + * controller state is undefined. Record the mode. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + ap->device[i].pio_mode = XFER_PIO_0; + + if (postreset) + postreset(ap, classes); + + /* reset successful, schedule revalidation */ + ata_eh_done(ap, NULL, ATA_EH_RESET_MASK); + ehc->i.action |= ATA_EH_REVALIDATE; + } + + return rc; +} + +static int ata_eh_revalidate_and_attach(struct ata_port *ap, + struct ata_device **r_failed_dev) +{ + struct ata_eh_context *ehc = &ap->eh_context; + struct ata_device *dev; + unsigned long flags; + int i, rc = 0; + + DPRINTK("ENTER\n"); + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + unsigned int action; + + dev = &ap->device[i]; + action = ehc->i.action | ehc->i.dev_action[dev->devno]; + + if (action & ATA_EH_REVALIDATE && ata_dev_enabled(dev)) { + if (ata_port_offline(ap)) { + rc = -EIO; + break; + } + + ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE); + rc = ata_dev_revalidate(dev, + ehc->i.flags & ATA_EHI_DID_RESET); + if (rc) + break; + + ata_eh_done(ap, dev, ATA_EH_REVALIDATE); + + /* schedule the scsi_rescan_device() here */ + queue_work(ata_aux_wq, &(ap->scsi_rescan_task)); + } else if (dev->class == ATA_DEV_UNKNOWN && + ehc->tries[dev->devno] && + ata_class_enabled(ehc->classes[dev->devno])) { + dev->class = ehc->classes[dev->devno]; + + rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); + if (rc == 0) + rc = ata_dev_configure(dev, 1); + + if (rc) { + dev->class = ATA_DEV_UNKNOWN; + break; + } + + spin_lock_irqsave(ap->lock, flags); + ap->flags |= ATA_FLAG_SCSI_HOTPLUG; + spin_unlock_irqrestore(ap->lock, flags); + } + } + + if (rc) + *r_failed_dev = dev; + + DPRINTK("EXIT\n"); + return rc; +} + +static int ata_port_nr_enabled(struct ata_port *ap) +{ + int i, cnt = 0; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ata_dev_enabled(&ap->device[i])) + cnt++; + return cnt; +} + +static int ata_port_nr_vacant(struct ata_port *ap) +{ + int i, cnt = 0; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ap->device[i].class == ATA_DEV_UNKNOWN) + cnt++; + return cnt; +} + +static int ata_eh_skip_recovery(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + int i; + + if (ap->flags & ATA_FLAG_FROZEN || ata_port_nr_enabled(ap)) + return 0; + + /* skip if class codes for all vacant slots are ATA_DEV_NONE */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + + if (dev->class == ATA_DEV_UNKNOWN && + ehc->classes[dev->devno] != ATA_DEV_NONE) + return 0; + } + + return 1; +} + +/** + * ata_eh_recover - recover host port after error + * @ap: host port to recover + * @prereset: prereset method (can be NULL) + * @softreset: softreset method (can be NULL) + * @hardreset: hardreset method (can be NULL) + * @postreset: postreset method (can be NULL) + * + * This is the alpha and omega, eum and yang, heart and soul of + * libata exception handling. On entry, actions required to + * recover the port and hotplug requests are recorded in + * eh_context. This function executes all the operations with + * appropriate retrials and fallbacks to resurrect failed + * devices, detach goners and greet newcomers. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno on failure. + */ +static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset) +{ + struct ata_eh_context *ehc = &ap->eh_context; + struct ata_device *dev; + int down_xfermask, i, rc; + + DPRINTK("ENTER\n"); + + /* prep for recovery */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + + ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; + + /* process hotplug request */ + if (dev->flags & ATA_DFLAG_DETACH) + ata_eh_detach_dev(dev); + + if (!ata_dev_enabled(dev) && + ((ehc->i.probe_mask & (1 << dev->devno)) && + !(ehc->did_probe_mask & (1 << dev->devno)))) { + ata_eh_detach_dev(dev); + ata_dev_init(dev); + ehc->did_probe_mask |= (1 << dev->devno); + ehc->i.action |= ATA_EH_SOFTRESET; + } + } + + retry: + down_xfermask = 0; + rc = 0; + + /* if UNLOADING, finish immediately */ + if (ap->flags & ATA_FLAG_UNLOADING) + goto out; + + /* skip EH if possible. */ + if (ata_eh_skip_recovery(ap)) + ehc->i.action = 0; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + ehc->classes[i] = ATA_DEV_UNKNOWN; + + /* reset */ + if (ehc->i.action & ATA_EH_RESET_MASK) { + ata_eh_freeze_port(ap); + + rc = ata_eh_reset(ap, ata_port_nr_vacant(ap), prereset, + softreset, hardreset, postreset); + if (rc) { + ata_port_printk(ap, KERN_ERR, + "reset failed, giving up\n"); + goto out; + } + + ata_eh_thaw_port(ap); + } + + /* revalidate existing devices and attach new ones */ + rc = ata_eh_revalidate_and_attach(ap, &dev); + if (rc) + goto dev_fail; + + /* configure transfer mode if the port has been reset */ + if (ehc->i.flags & ATA_EHI_DID_RESET) { + rc = ata_set_mode(ap, &dev); + if (rc) { + down_xfermask = 1; + goto dev_fail; + } + } + + goto out; + + dev_fail: + switch (rc) { + case -ENODEV: + /* device missing, schedule probing */ + ehc->i.probe_mask |= (1 << dev->devno); + case -EINVAL: + ehc->tries[dev->devno] = 0; + break; + case -EIO: + sata_down_spd_limit(ap); + default: + ehc->tries[dev->devno]--; + if (down_xfermask && + ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1)) + ehc->tries[dev->devno] = 0; + } + + if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) { + /* disable device if it has used up all its chances */ + ata_dev_disable(dev); + + /* detach if offline */ + if (ata_port_offline(ap)) + ata_eh_detach_dev(dev); + + /* probe if requested */ + if ((ehc->i.probe_mask & (1 << dev->devno)) && + !(ehc->did_probe_mask & (1 << dev->devno))) { + ata_eh_detach_dev(dev); + ata_dev_init(dev); + + ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; + ehc->did_probe_mask |= (1 << dev->devno); + ehc->i.action |= ATA_EH_SOFTRESET; + } + } else { + /* soft didn't work? be haaaaard */ + if (ehc->i.flags & ATA_EHI_DID_RESET) + ehc->i.action |= ATA_EH_HARDRESET; + else + ehc->i.action |= ATA_EH_SOFTRESET; + } + + if (ata_port_nr_enabled(ap)) { + ata_port_printk(ap, KERN_WARNING, "failed to recover some " + "devices, retrying in 5 secs\n"); + ssleep(5); + } else { + /* no device left, repeat fast */ + msleep(500); + } + + goto retry; + + out: + if (rc) { + for (i = 0; i < ATA_MAX_DEVICES; i++) + ata_dev_disable(&ap->device[i]); + } + + DPRINTK("EXIT, rc=%d\n", rc); + return rc; +} + +/** + * ata_eh_finish - finish up EH + * @ap: host port to finish EH for + * + * Recovery is complete. Clean up EH states and retry or finish + * failed qcs. + * + * LOCKING: + * None. + */ +static void ata_eh_finish(struct ata_port *ap) +{ + int tag; + + /* retry or finish qcs */ + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + + if (qc->err_mask) { + /* FIXME: Once EH migration is complete, + * generate sense data in this function, + * considering both err_mask and tf. + */ + if (qc->err_mask & AC_ERR_INVALID) + ata_eh_qc_complete(qc); + else + ata_eh_qc_retry(qc); + } else { + if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + ata_eh_qc_complete(qc); + } else { + /* feed zero TF to sense generation */ + memset(&qc->result_tf, 0, sizeof(qc->result_tf)); + ata_eh_qc_retry(qc); + } + } + } +} + +/** + * ata_do_eh - do standard error handling + * @ap: host port to handle error for + * @prereset: prereset method (can be NULL) + * @softreset: softreset method (can be NULL) + * @hardreset: hardreset method (can be NULL) + * @postreset: postreset method (can be NULL) + * + * Perform standard error handling sequence. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset) +{ + if (!(ap->flags & ATA_FLAG_LOADING)) { + ata_eh_autopsy(ap); + ata_eh_report(ap); + } + + ata_eh_recover(ap, prereset, softreset, hardreset, postreset); + ata_eh_finish(ap); +} diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index a0289ec..93d18a7 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -38,9 +38,10 @@ #include #include #include #include +#include #include #include -#include +#include #include #include #include @@ -51,10 +52,14 @@ #include "libata.h" #define SECTOR_SIZE 512 typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); -static struct ata_device * -ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); -static void ata_scsi_error(struct Scsi_Host *host); -enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); + +static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap, + const struct scsi_device *scsidev); +static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, + const struct scsi_device *scsidev); +static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, + unsigned int id, unsigned int lun); + #define RW_RECOVERY_MPAGE 0x1 #define RW_RECOVERY_MPAGE_LEN 12 @@ -102,6 +107,7 @@ static const u8 def_control_mpage[CONTRO struct scsi_transport_template ata_scsi_transport_template = { .eh_strategy_handler = ata_scsi_error, .eh_timed_out = ata_scsi_timed_out, + .user_scan = ata_scsi_user_scan, }; @@ -304,7 +310,6 @@ int ata_scsi_ioctl(struct scsi_device *s /** * ata_scsi_qc_new - acquire new ata_queued_cmd reference - * @ap: ATA port to which the new command is attached * @dev: ATA device to which the new command is attached * @cmd: SCSI command that originated this ATA command * @done: SCSI command completion function @@ -323,14 +328,13 @@ int ata_scsi_ioctl(struct scsi_device *s * RETURNS: * Command allocated, or %NULL if none available. */ -struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, - struct ata_device *dev, +struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ata_queued_cmd *qc; - qc = ata_qc_new_init(ap, dev); + qc = ata_qc_new_init(dev); if (qc) { qc->scsicmd = cmd; qc->scsidone = done; @@ -397,18 +401,18 @@ void ata_dump_status(unsigned id, struct int ata_scsi_device_resume(struct scsi_device *sdev) { - struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; - struct ata_device *dev = &ap->device[sdev->id]; + struct ata_port *ap = ata_shost_to_port(sdev->host); + struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); - return ata_device_resume(ap, dev); + return ata_device_resume(dev); } int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) { - struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; - struct ata_device *dev = &ap->device[sdev->id]; + struct ata_port *ap = ata_shost_to_port(sdev->host); + struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); - return ata_device_suspend(ap, dev, state); + return ata_device_suspend(dev, state); } /** @@ -419,6 +423,7 @@ int ata_scsi_device_suspend(struct scsi_ * @sk: the sense key we'll fill out * @asc: the additional sense code we'll fill out * @ascq: the additional sense code qualifier we'll fill out + * @verbose: be verbose * * Converts an ATA error into a SCSI error. Fill out pointers to * SK, ASC, and ASCQ bytes for later use in fixed or descriptor @@ -428,7 +433,7 @@ int ata_scsi_device_suspend(struct scsi_ * spin_lock_irqsave(host_set lock) */ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, - u8 *ascq) + u8 *ascq, int verbose) { int i; @@ -493,8 +498,9 @@ void ata_to_sense_error(unsigned id, u8 } } /* No immediate match */ - printk(KERN_WARNING "ata%u: no sense translation for " - "error 0x%02x\n", id, drv_err); + if (verbose) + printk(KERN_WARNING "ata%u: no sense translation for " + "error 0x%02x\n", id, drv_err); } /* Fall back to interpreting status bits */ @@ -507,8 +513,9 @@ void ata_to_sense_error(unsigned id, u8 } } /* No error? Undecoded? */ - printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", - id, drv_stat); + if (verbose) + printk(KERN_WARNING "ata%u: no sense translation for " + "status: 0x%02x\n", id, drv_stat); /* We need a sensible error return here, which is tricky, and one that won't cause people to do things like return a disk wrongly */ @@ -517,9 +524,10 @@ void ata_to_sense_error(unsigned id, u8 *ascq = 0x00; translate_done: - printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to " - "SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err, - *sk, *asc, *ascq); + if (verbose) + printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x " + "to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", + id, drv_stat, drv_err, *sk, *asc, *ascq); return; } @@ -539,27 +547,23 @@ void ata_to_sense_error(unsigned id, u8 void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; - struct ata_taskfile *tf = &qc->tf; + struct ata_taskfile *tf = &qc->result_tf; unsigned char *sb = cmd->sense_buffer; unsigned char *desc = sb + 8; + int verbose = qc->ap->ops->error_handler == NULL; memset(sb, 0, SCSI_SENSE_BUFFERSIZE); cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; /* - * Read the controller registers. - */ - WARN_ON(qc->ap->ops->tf_read == NULL); - qc->ap->ops->tf_read(qc->ap, tf); - - /* * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. */ - if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { + if (qc->err_mask || + tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->id, tf->command, tf->feature, - &sb[1], &sb[2], &sb[3]); + &sb[1], &sb[2], &sb[3], verbose); sb[1] &= 0x0f; } @@ -615,26 +619,22 @@ void ata_gen_ata_desc_sense(struct ata_q void ata_gen_fixed_sense(struct ata_queued_cmd *qc) { struct scsi_cmnd *cmd = qc->scsicmd; - struct ata_taskfile *tf = &qc->tf; + struct ata_taskfile *tf = &qc->result_tf; unsigned char *sb = cmd->sense_buffer; + int verbose = qc->ap->ops->error_handler == NULL; memset(sb, 0, SCSI_SENSE_BUFFERSIZE); cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; /* - * Read the controller registers. - */ - WARN_ON(qc->ap->ops->tf_read == NULL); - qc->ap->ops->tf_read(qc->ap, tf); - - /* * Use ata_to_sense_error() to map status register bits * onto sense key, asc & ascq. */ - if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { + if (qc->err_mask || + tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ata_to_sense_error(qc->ap->id, tf->command, tf->feature, - &sb[2], &sb[12], &sb[13]); + &sb[2], &sb[12], &sb[13], verbose); sb[2] &= 0x0f; } @@ -677,7 +677,7 @@ static void ata_scsi_dev_config(struct s */ max_sectors = ATA_MAX_SECTORS; if (dev->flags & ATA_DFLAG_LBA48) - max_sectors = 2048; + max_sectors = ATA_MAX_SECTORS_LBA48; if (dev->max_sectors) max_sectors = dev->max_sectors; @@ -692,6 +692,14 @@ static void ata_scsi_dev_config(struct s request_queue_t *q = sdev->request_queue; blk_queue_max_hw_segments(q, q->max_hw_segments - 1); } + + if (dev->flags & ATA_DFLAG_NCQ) { + int depth; + + depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); + depth = min(ATA_MAX_QUEUE - 1, depth); + scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); + } } /** @@ -708,152 +716,88 @@ static void ata_scsi_dev_config(struct s int ata_scsi_slave_config(struct scsi_device *sdev) { + struct ata_port *ap = ata_shost_to_port(sdev->host); + struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); + ata_scsi_sdev_config(sdev); blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); - if (sdev->id < ATA_MAX_DEVICES) { - struct ata_port *ap; - struct ata_device *dev; - - ap = (struct ata_port *) &sdev->host->hostdata[0]; - dev = &ap->device[sdev->id]; - + if (dev) ata_scsi_dev_config(sdev, dev); - } return 0; /* scsi layer doesn't check return value, sigh */ } /** - * ata_scsi_timed_out - SCSI layer time out callback - * @cmd: timed out SCSI command + * ata_scsi_slave_destroy - SCSI device is about to be destroyed + * @sdev: SCSI device to be destroyed * - * Handles SCSI layer timeout. We race with normal completion of - * the qc for @cmd. If the qc is already gone, we lose and let - * the scsi command finish (EH_HANDLED). Otherwise, the qc has - * timed out and EH should be invoked. Prevent ata_qc_complete() - * from finishing it by setting EH_SCHEDULED and return - * EH_NOT_HANDLED. + * @sdev is about to be destroyed for hot/warm unplugging. If + * this unplugging was initiated by libata as indicated by NULL + * dev->sdev, this function doesn't have to do anything. + * Otherwise, SCSI layer initiated warm-unplug is in progress. + * Clear dev->sdev, schedule the device for ATA detach and invoke + * EH. * * LOCKING: - * Called from timer context - * - * RETURNS: - * EH_HANDLED or EH_NOT_HANDLED + * Defined by SCSI layer. We don't really care. */ -enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) +void ata_scsi_slave_destroy(struct scsi_device *sdev) { - struct Scsi_Host *host = cmd->device->host; - struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + struct ata_port *ap = ata_shost_to_port(sdev->host); unsigned long flags; - struct ata_queued_cmd *qc; - enum scsi_eh_timer_return ret = EH_HANDLED; + struct ata_device *dev; - DPRINTK("ENTER\n"); + if (!ap->ops->error_handler) + return; - spin_lock_irqsave(&ap->host_set->lock, flags); - qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc) { - WARN_ON(qc->scsicmd != cmd); - qc->flags |= ATA_QCFLAG_EH_SCHEDULED; - qc->err_mask |= AC_ERR_TIMEOUT; - ret = EH_NOT_HANDLED; + spin_lock_irqsave(ap->lock, flags); + dev = __ata_scsi_find_dev(ap, sdev); + if (dev && dev->sdev) { + /* SCSI device already in CANCEL state, no need to offline it */ + dev->sdev = NULL; + dev->flags |= ATA_DFLAG_DETACH; + ata_port_schedule_eh(ap); } - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - DPRINTK("EXIT, ret=%d\n", ret); - return ret; + spin_unlock_irqrestore(ap->lock, flags); } /** - * ata_scsi_error - SCSI layer error handler callback - * @host: SCSI host on which error occurred + * ata_scsi_change_queue_depth - SCSI callback for queue depth config + * @sdev: SCSI device to configure queue depth for + * @queue_depth: new queue depth * - * Handles SCSI-layer-thrown error events. + * This is libata standard hostt->change_queue_depth callback. + * SCSI will call into this callback when user tries to set queue + * depth via sysfs. * * LOCKING: - * Inherited from SCSI layer (none, can sleep) + * SCSI layer (we don't care) + * + * RETURNS: + * Newly configured queue depth. */ - -static void ata_scsi_error(struct Scsi_Host *host) +int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth) { - struct ata_port *ap; - unsigned long flags; - - DPRINTK("ENTER\n"); - - ap = (struct ata_port *) &host->hostdata[0]; - - spin_lock_irqsave(&ap->host_set->lock, flags); - WARN_ON(ap->flags & ATA_FLAG_IN_EH); - ap->flags |= ATA_FLAG_IN_EH; - WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - ata_port_flush_task(ap); - - ap->ops->eng_timeout(ap); - - WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); - - scsi_eh_flush_done_q(&ap->eh_done_q); - - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_IN_EH; - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - DPRINTK("EXIT\n"); -} - -static void ata_eh_scsidone(struct scsi_cmnd *scmd) -{ - /* nada */ -} - -static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct scsi_cmnd *scmd = qc->scsicmd; - unsigned long flags; + struct ata_port *ap = ata_shost_to_port(sdev->host); + struct ata_device *dev; + int max_depth; - spin_lock_irqsave(&ap->host_set->lock, flags); - qc->scsidone = ata_eh_scsidone; - __ata_qc_complete(qc); - WARN_ON(ata_tag_valid(qc->tag)); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + if (queue_depth < 1) + return sdev->queue_depth; - scsi_eh_finish_cmd(scmd, &ap->eh_done_q); -} + dev = ata_scsi_find_dev(ap, sdev); + if (!dev || !ata_dev_enabled(dev)) + return sdev->queue_depth; -/** - * ata_eh_qc_complete - Complete an active ATA command from EH - * @qc: Command to complete - * - * Indicate to the mid and upper layers that an ATA command has - * completed. To be used from EH. - */ -void ata_eh_qc_complete(struct ata_queued_cmd *qc) -{ - struct scsi_cmnd *scmd = qc->scsicmd; - scmd->retries = scmd->allowed; - __ata_eh_qc_complete(qc); -} + max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); + max_depth = min(ATA_MAX_QUEUE - 1, max_depth); + if (queue_depth > max_depth) + queue_depth = max_depth; -/** - * ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH - * @qc: Command to retry - * - * Indicate to the mid and upper layers that an ATA command - * should be retried. To be used from EH. - * - * SCSI midlayer limits the number of retries to scmd->allowed. - * This function might need to adjust scmd->retries for commands - * which get retried due to unrelated NCQ failures. - */ -void ata_eh_qc_retry(struct ata_queued_cmd *qc) -{ - __ata_eh_qc_complete(qc); + scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth); + return queue_depth; } /** @@ -891,7 +835,7 @@ static unsigned int ata_scsi_start_stop_ tf->nsect = 1; /* 1 sector, lba=0 */ if (qc->dev->flags & ATA_DFLAG_LBA) { - qc->tf.flags |= ATA_TFLAG_LBA; + tf->flags |= ATA_TFLAG_LBA; tf->lbah = 0x0; tf->lbam = 0x0; @@ -1195,6 +1139,7 @@ static unsigned int ata_scsi_rw_xlat(str u64 block; u32 n_block; + qc->flags |= ATA_QCFLAG_IO; tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 || @@ -1241,7 +1186,36 @@ static unsigned int ata_scsi_rw_xlat(str */ goto nothing_to_do; - if (dev->flags & ATA_DFLAG_LBA) { + if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) { + /* yay, NCQ */ + if (!lba_48_ok(block, n_block)) + goto out_of_range; + + tf->protocol = ATA_PROT_NCQ; + tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48; + + if (tf->flags & ATA_TFLAG_WRITE) + tf->command = ATA_CMD_FPDMA_WRITE; + else + tf->command = ATA_CMD_FPDMA_READ; + + qc->nsect = n_block; + + tf->nsect = qc->tag << 3; + tf->hob_feature = (n_block >> 8) & 0xff; + tf->feature = n_block & 0xff; + + tf->hob_lbah = (block >> 40) & 0xff; + tf->hob_lbam = (block >> 32) & 0xff; + tf->hob_lbal = (block >> 24) & 0xff; + tf->lbah = (block >> 16) & 0xff; + tf->lbam = (block >> 8) & 0xff; + tf->lbal = block & 0xff; + + tf->device = 1 << 6; + if (tf->flags & ATA_TFLAG_FUA) + tf->device |= 1 << 7; + } else if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; if (lba_28_ok(block, n_block)) { @@ -1332,6 +1306,17 @@ static void ata_scsi_qc_complete(struct u8 *cdb = cmd->cmnd; int need_sense = (qc->err_mask != 0); + /* We snoop the SET_FEATURES - Write Cache ON/OFF command, and + * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE + * cache + */ + if (!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) && + ((qc->tf.feature == SETFEATURES_WC_ON) || + (qc->tf.feature == SETFEATURES_WC_OFF))) { + qc->ap->eh_info.action |= ATA_EH_REVALIDATE; + ata_port_schedule_eh(qc->ap); + } + /* For ATA pass thru (SAT) commands, generate a sense block if * user mandated it or if there's an error. Note that if we * generate because the user forced us to, a check condition @@ -1356,10 +1341,8 @@ static void ata_scsi_qc_complete(struct } } - if (need_sense) { - /* The ata_gen_..._sense routines fill in tf */ - ata_dump_status(qc->ap->id, &qc->tf); - } + if (need_sense && !qc->ap->ops->error_handler) + ata_dump_status(qc->ap->id, &qc->result_tf); qc->scsidone(cmd); @@ -1367,8 +1350,40 @@ static void ata_scsi_qc_complete(struct } /** + * ata_scmd_need_defer - Check whether we need to defer scmd + * @dev: ATA device to which the command is addressed + * @is_io: Is the command IO (and thus possibly NCQ)? + * + * NCQ and non-NCQ commands cannot run together. As upper layer + * only knows the queue depth, we are responsible for maintaining + * exclusion. This function checks whether a new command can be + * issued to @dev. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * 1 if deferring is needed, 0 otherwise. + */ +static int ata_scmd_need_defer(struct ata_device *dev, int is_io) +{ + struct ata_port *ap = dev->ap; + + if (!(dev->flags & ATA_DFLAG_NCQ)) + return 0; + + if (is_io) { + if (!ata_tag_valid(ap->active_tag)) + return 0; + } else { + if (!ata_tag_valid(ap->active_tag) && !ap->sactive) + return 0; + } + return 1; +} + +/** * ata_scsi_translate - Translate then issue SCSI command to ATA device - * @ap: ATA port to which the command is addressed * @dev: ATA device to which the command is addressed * @cmd: SCSI command to execute * @done: SCSI command completion function @@ -1389,19 +1404,25 @@ static void ata_scsi_qc_complete(struct * * LOCKING: * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command + * needs to be deferred. */ - -static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, +static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), ata_xlat_func_t xlat_func) { struct ata_queued_cmd *qc; u8 *scsicmd = cmd->cmnd; + int is_io = xlat_func == ata_scsi_rw_xlat; VPRINTK("ENTER\n"); - qc = ata_scsi_qc_new(ap, dev, cmd, done); + if (unlikely(ata_scmd_need_defer(dev, is_io))) + goto defer; + + qc = ata_scsi_qc_new(dev, cmd, done); if (!qc) goto err_mem; @@ -1409,8 +1430,8 @@ static void ata_scsi_translate(struct at if (cmd->sc_data_direction == DMA_FROM_DEVICE || cmd->sc_data_direction == DMA_TO_DEVICE) { if (unlikely(cmd->request_bufflen < 1)) { - printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n", - ap->id, dev->devno); + ata_dev_printk(dev, KERN_WARNING, + "WARNING: zero len r/w req\n"); goto err_did; } @@ -1432,13 +1453,13 @@ static void ata_scsi_translate(struct at ata_qc_issue(qc); VPRINTK("EXIT\n"); - return; + return 0; early_finish: ata_qc_free(qc); done(cmd); DPRINTK("EXIT - early finish (good or error)\n"); - return; + return 0; err_did: ata_qc_free(qc); @@ -1446,7 +1467,11 @@ err_mem: cmd->result = (DID_ERROR << 16); done(cmd); DPRINTK("EXIT - internal\n"); - return; + return 0; + +defer: + DPRINTK("EXIT - defer\n"); + return SCSI_MLQUEUE_DEVICE_BUSY; } /** @@ -1944,7 +1969,7 @@ unsigned int ata_scsiop_mode_sense(struc return 0; dpofua = 0; - if (ata_dev_supports_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && + if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) && (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) dpofua = 1 << 4; @@ -2137,13 +2162,14 @@ void ata_scsi_badcmd(struct scsi_cmnd *c static void atapi_sense_complete(struct ata_queued_cmd *qc) { - if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) + if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) { /* FIXME: not quite right; we don't want the * translation of taskfile registers into * a sense descriptors, since that's only * correct for ATA, not ATAPI */ ata_gen_ata_desc_sense(qc); + } qc->scsidone(qc->scsicmd); ata_qc_free(qc); @@ -2207,21 +2233,38 @@ static void atapi_qc_complete(struct ata VPRINTK("ENTER, err_mask 0x%X\n", err_mask); + /* handle completion from new EH */ + if (unlikely(qc->ap->ops->error_handler && + (err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID))) { + + if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) { + /* FIXME: not quite right; we don't want the + * translation of taskfile registers into a + * sense descriptors, since that's only + * correct for ATA, not ATAPI + */ + ata_gen_ata_desc_sense(qc); + } + + qc->scsicmd->result = SAM_STAT_CHECK_CONDITION; + qc->scsidone(cmd); + ata_qc_free(qc); + return; + } + + /* successful completion or old EH failure path */ if (unlikely(err_mask & AC_ERR_DEV)) { cmd->result = SAM_STAT_CHECK_CONDITION; atapi_request_sense(qc); return; - } - - else if (unlikely(err_mask)) + } else if (unlikely(err_mask)) { /* FIXME: not quite right; we don't want the * translation of taskfile registers into * a sense descriptors, since that's only * correct for ATA, not ATAPI */ ata_gen_ata_desc_sense(qc); - - else { + } else { u8 *scsicmd = cmd->cmnd; if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) { @@ -2303,18 +2346,63 @@ static unsigned int atapi_xlat(struct at qc->tf.protocol = ATA_PROT_ATAPI_DMA; qc->tf.feature |= ATAPI_PKT_DMA; -#ifdef ATAPI_ENABLE_DMADIR - /* some SATA bridges need us to indicate data xfer direction */ - if (cmd->sc_data_direction != DMA_TO_DEVICE) + if (atapi_dmadir && (cmd->sc_data_direction != DMA_TO_DEVICE)) + /* some SATA bridges need us to indicate data xfer direction */ qc->tf.feature |= ATAPI_DMADIR; -#endif } - qc->nbytes = cmd->bufflen; + qc->nbytes = cmd->request_bufflen; return 0; } +static struct ata_device * ata_find_dev(struct ata_port *ap, int id) +{ + if (likely(id < ATA_MAX_DEVICES)) + return &ap->device[id]; + return NULL; +} + +static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap, + const struct scsi_device *scsidev) +{ + /* skip commands not addressed to targets we simulate */ + if (unlikely(scsidev->channel || scsidev->lun)) + return NULL; + + return ata_find_dev(ap, scsidev->id); +} + +/** + * ata_scsi_dev_enabled - determine if device is enabled + * @dev: ATA device + * + * Determine if commands should be sent to the specified device. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * 0 if commands are not allowed / 1 if commands are allowed + */ + +static int ata_scsi_dev_enabled(struct ata_device *dev) +{ + if (unlikely(!ata_dev_enabled(dev))) + return 0; + + if (!atapi_enabled || (dev->ap->flags & ATA_FLAG_NO_ATAPI)) { + if (unlikely(dev->class == ATA_DEV_ATAPI)) { + ata_dev_printk(dev, KERN_WARNING, + "WARNING: ATAPI is %s, device ignored.\n", + atapi_enabled ? "not supported with this driver" : "disabled"); + return 0; + } + } + + return 1; +} + /** * ata_scsi_find_dev - lookup ata_device from scsi_cmnd * @ap: ATA port to which the device is attached @@ -2331,33 +2419,14 @@ #endif * RETURNS: * Associated ATA device, or %NULL if not found. */ - static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) { - struct ata_device *dev; + struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev); - /* skip commands not addressed to targets we simulate */ - if (likely(scsidev->id < ATA_MAX_DEVICES)) - dev = &ap->device[scsidev->id]; - else + if (unlikely(!dev || !ata_scsi_dev_enabled(dev))) return NULL; - if (unlikely((scsidev->channel != 0) || - (scsidev->lun != 0))) - return NULL; - - if (unlikely(!ata_dev_present(dev))) - return NULL; - - if (!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) { - if (unlikely(dev->class == ATA_DEV_ATAPI)) { - printk(KERN_WARNING "ata%u(%u): WARNING: ATAPI is %s, device ignored.\n", - ap->id, dev->devno, atapi_enabled ? "not supported with this driver" : "disabled"); - return NULL; - } - } - return dev; } @@ -2414,10 +2483,15 @@ ata_scsi_pass_thru(struct ata_queued_cmd { struct ata_taskfile *tf = &(qc->tf); struct scsi_cmnd *cmd = qc->scsicmd; + struct ata_device *dev = qc->dev; if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) goto invalid_fld; + /* We may not issue DMA commands if no DMA mode is set */ + if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) + goto invalid_fld; + if (scsicmd[1] & 0xe0) /* PIO multi not supported yet */ goto invalid_fld; @@ -2500,7 +2574,10 @@ ata_scsi_pass_thru(struct ata_queued_cmd * TODO: find out if we need to do more here to * cover scatter/gather case. */ - qc->nsect = cmd->bufflen / ATA_SECT_SIZE; + qc->nsect = cmd->request_bufflen / ATA_SECT_SIZE; + + /* request result TF */ + qc->flags |= ATA_QCFLAG_RESULT_TF; return 0; @@ -2578,19 +2655,24 @@ #ifdef ATA_DEBUG #endif } -static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), - struct ata_port *ap, struct ata_device *dev) +static inline int __ata_scsi_queuecmd(struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *), + struct ata_device *dev) { + int rc = 0; + if (dev->class == ATA_DEV_ATA) { ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, cmd->cmnd[0]); if (xlat_func) - ata_scsi_translate(ap, dev, cmd, done, xlat_func); + rc = ata_scsi_translate(dev, cmd, done, xlat_func); else - ata_scsi_simulate(ap, dev, cmd, done); + ata_scsi_simulate(dev, cmd, done); } else - ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); + rc = ata_scsi_translate(dev, cmd, done, atapi_xlat); + + return rc; } /** @@ -2609,39 +2691,39 @@ static inline void __ata_scsi_queuecmd(s * Releases scsi-layer-held lock, and obtains host_set lock. * * RETURNS: - * Zero. + * Return value from __ata_scsi_queuecmd() if @cmd can be queued, + * 0 otherwise. */ - int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ata_port *ap; struct ata_device *dev; struct scsi_device *scsidev = cmd->device; struct Scsi_Host *shost = scsidev->host; + int rc = 0; - ap = (struct ata_port *) &shost->hostdata[0]; + ap = ata_shost_to_port(shost); spin_unlock(shost->host_lock); - spin_lock(&ap->host_set->lock); + spin_lock(ap->lock); ata_scsi_dump_cdb(ap, cmd); dev = ata_scsi_find_dev(ap, scsidev); if (likely(dev)) - __ata_scsi_queuecmd(cmd, done, ap, dev); + rc = __ata_scsi_queuecmd(cmd, done, dev); else { cmd->result = (DID_BAD_TARGET << 16); done(cmd); } - spin_unlock(&ap->host_set->lock); + spin_unlock(ap->lock); spin_lock(shost->host_lock); - return 0; + return rc; } /** * ata_scsi_simulate - simulate SCSI command on ATA device - * @ap: port the device is connected to * @dev: the target device * @cmd: SCSI command being sent to device. * @done: SCSI command completion function. @@ -2653,14 +2735,12 @@ int ata_scsi_queuecmd(struct scsi_cmnd * * spin_lock_irqsave(host_set lock) */ -void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, +void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ata_scsi_args args; const u8 *scsicmd = cmd->cmnd; - args.ap = ap; args.dev = dev; args.id = dev->id; args.cmd = cmd; @@ -2732,17 +2812,241 @@ void ata_scsi_simulate(struct ata_port * void ata_scsi_scan_host(struct ata_port *ap) { - struct ata_device *dev; unsigned int i; - if (ap->flags & ATA_FLAG_PORT_DISABLED) + if (ap->flags & ATA_FLAG_DISABLED) return; for (i = 0; i < ATA_MAX_DEVICES; i++) { - dev = &ap->device[i]; + struct ata_device *dev = &ap->device[i]; + struct scsi_device *sdev; - if (ata_dev_present(dev)) - scsi_scan_target(&ap->host->shost_gendev, 0, i, 0, 0); + if (!ata_dev_enabled(dev) || dev->sdev) + continue; + + sdev = __scsi_add_device(ap->host, 0, i, 0, NULL); + if (!IS_ERR(sdev)) { + dev->sdev = sdev; + scsi_device_put(sdev); + } + } +} + +/** + * ata_scsi_offline_dev - offline attached SCSI device + * @dev: ATA device to offline attached SCSI device for + * + * This function is called from ata_eh_hotplug() and responsible + * for taking the SCSI device attached to @dev offline. This + * function is called with host_set lock which protects dev->sdev + * against clearing. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * 1 if attached SCSI device exists, 0 otherwise. + */ +int ata_scsi_offline_dev(struct ata_device *dev) +{ + if (dev->sdev) { + scsi_device_set_state(dev->sdev, SDEV_OFFLINE); + return 1; } + return 0; } +/** + * ata_scsi_remove_dev - remove attached SCSI device + * @dev: ATA device to remove attached SCSI device for + * + * This function is called from ata_eh_scsi_hotplug() and + * responsible for removing the SCSI device attached to @dev. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_scsi_remove_dev(struct ata_device *dev) +{ + struct ata_port *ap = dev->ap; + struct scsi_device *sdev; + unsigned long flags; + + /* Alas, we need to grab scan_mutex to ensure SCSI device + * state doesn't change underneath us and thus + * scsi_device_get() always succeeds. The mutex locking can + * be removed if there is __scsi_device_get() interface which + * increments reference counts regardless of device state. + */ + mutex_lock(&ap->host->scan_mutex); + spin_lock_irqsave(ap->lock, flags); + + /* clearing dev->sdev is protected by host_set lock */ + sdev = dev->sdev; + dev->sdev = NULL; + + if (sdev) { + /* If user initiated unplug races with us, sdev can go + * away underneath us after the host_set lock and + * scan_mutex are released. Hold onto it. + */ + if (scsi_device_get(sdev) == 0) { + /* The following ensures the attached sdev is + * offline on return from ata_scsi_offline_dev() + * regardless it wins or loses the race + * against this function. + */ + scsi_device_set_state(sdev, SDEV_OFFLINE); + } else { + WARN_ON(1); + sdev = NULL; + } + } + + spin_unlock_irqrestore(ap->lock, flags); + mutex_unlock(&ap->host->scan_mutex); + + if (sdev) { + ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n", + sdev->sdev_gendev.bus_id); + + scsi_remove_device(sdev); + scsi_device_put(sdev); + } +} + +/** + * ata_scsi_hotplug - SCSI part of hotplug + * @data: Pointer to ATA port to perform SCSI hotplug on + * + * Perform SCSI part of hotplug. It's executed from a separate + * workqueue after EH completes. This is necessary because SCSI + * hot plugging requires working EH and hot unplugging is + * synchronized with hot plugging with a mutex. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_scsi_hotplug(void *data) +{ + struct ata_port *ap = data; + int i; + + if (ap->flags & ATA_FLAG_UNLOADING) { + DPRINTK("ENTER/EXIT - unloading\n"); + return; + } + + DPRINTK("ENTER\n"); + + /* unplug detached devices */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + unsigned long flags; + + if (!(dev->flags & ATA_DFLAG_DETACHED)) + continue; + + spin_lock_irqsave(ap->lock, flags); + dev->flags &= ~ATA_DFLAG_DETACHED; + spin_unlock_irqrestore(ap->lock, flags); + + ata_scsi_remove_dev(dev); + } + + /* scan for new ones */ + ata_scsi_scan_host(ap); + + /* If we scanned while EH was in progress, scan would have + * failed silently. Requeue if there are enabled but + * unattached devices. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + if (ata_dev_enabled(dev) && !dev->sdev) { + queue_delayed_work(ata_aux_wq, &ap->hotplug_task, HZ); + break; + } + } + + DPRINTK("EXIT\n"); +} + +/** + * ata_scsi_user_scan - indication for user-initiated bus scan + * @shost: SCSI host to scan + * @channel: Channel to scan + * @id: ID to scan + * @lun: LUN to scan + * + * This function is called when user explicitly requests bus + * scan. Set probe pending flag and invoke EH. + * + * LOCKING: + * SCSI layer (we don't care) + * + * RETURNS: + * Zero. + */ +static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, + unsigned int id, unsigned int lun) +{ + struct ata_port *ap = ata_shost_to_port(shost); + unsigned long flags; + int rc = 0; + + if (!ap->ops->error_handler) + return -EOPNOTSUPP; + + if ((channel != SCAN_WILD_CARD && channel != 0) || + (lun != SCAN_WILD_CARD && lun != 0)) + return -EINVAL; + + spin_lock_irqsave(ap->lock, flags); + + if (id == SCAN_WILD_CARD) { + ap->eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1; + ap->eh_info.action |= ATA_EH_SOFTRESET; + } else { + struct ata_device *dev = ata_find_dev(ap, id); + + if (dev) { + ap->eh_info.probe_mask |= 1 << dev->devno; + ap->eh_info.action |= ATA_EH_SOFTRESET; + } else + rc = -EINVAL; + } + + if (rc == 0) + ata_port_schedule_eh(ap); + + spin_unlock_irqrestore(ap->lock, flags); + + return rc; +} + +/** + * ata_scsi_dev_rescan - initiate scsi_rescan_device() + * @data: Pointer to ATA port to perform scsi_rescan_device() + * + * After ATA pass thru (SAT) commands are executed successfully, + * libata need to propagate the changes to SCSI layer. This + * function must be executed from ata_aux_wq such that sdev + * attach/detach don't race with rescan. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_scsi_dev_rescan(void *data) +{ + struct ata_port *ap = data; + struct ata_device *dev; + unsigned int i; + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + + if (ata_dev_enabled(dev) && dev->sdev) + scsi_rescan_device(&(dev->sdev->sdev_gendev)); + } +} diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index bac8cba..bdd4888 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -29,10 +29,9 @@ #ifndef __LIBATA_H__ #define __LIBATA_H__ #define DRV_NAME "libata" -#define DRV_VERSION "1.20" /* must be exactly four chars */ +#define DRV_VERSION "1.30" /* must be exactly four chars */ struct ata_scsi_args { - struct ata_port *ap; struct ata_device *dev; u16 *id; struct scsi_cmnd *cmd; @@ -40,18 +39,32 @@ struct ata_scsi_args { }; /* libata-core.c */ +extern struct workqueue_struct *ata_aux_wq; extern int atapi_enabled; +extern int atapi_dmadir; extern int libata_fua; -extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, - struct ata_device *dev); +extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); +extern void ata_dev_disable(struct ata_device *dev); extern void ata_port_flush_task(struct ata_port *ap); +extern unsigned ata_exec_internal(struct ata_device *dev, + struct ata_taskfile *tf, const u8 *cdb, + int dma_dir, void *buf, unsigned int buflen); +extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, + int post_reset, u16 *id); +extern int ata_dev_configure(struct ata_device *dev, int print_info); +extern int sata_down_spd_limit(struct ata_port *ap); +extern int sata_set_spd_needed(struct ata_port *ap); +extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0); +extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); +extern void __ata_qc_complete(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); extern void swap_buf_le16(u16 *buf, unsigned int buf_words); +extern void ata_dev_init(struct ata_device *dev); extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); @@ -60,6 +73,8 @@ extern int ata_cmd_ioctl(struct scsi_dev extern struct scsi_transport_template ata_scsi_transport_template; extern void ata_scsi_scan_host(struct ata_port *ap); +extern int ata_scsi_offline_dev(struct ata_device *dev); +extern void ata_scsi_hotplug(void *data); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); @@ -88,5 +103,13 @@ extern void ata_scsi_set_sense(struct sc extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen)); +extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); +extern void ata_scsi_dev_rescan(void *data); + +/* libata-eh.c */ +extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); +extern void ata_scsi_error(struct Scsi_Host *host); +extern void ata_port_wait_eh(struct ata_port *ap); +extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); #endif /* __LIBATA_H__ */ diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c new file mode 100644 index 0000000..2673a11 --- /dev/null +++ b/drivers/scsi/libiscsi.c @@ -0,0 +1,1702 @@ +/* + * iSCSI lib functions + * + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004 - 2006 Mike Christie + * Copyright (C) 2004 - 2005 Dmitry Yusupov + * Copyright (C) 2004 - 2005 Alex Aizman + * maintained by open-iscsi@googlegroups.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct iscsi_session * +class_to_transport_session(struct iscsi_cls_session *cls_session) +{ + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + return iscsi_hostdata(shost->hostdata); +} +EXPORT_SYMBOL_GPL(class_to_transport_session); + +#define INVALID_SN_DELTA 0xffff + +int +iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) +{ + uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn); + uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn); + + if (max_cmdsn < exp_cmdsn -1 && + max_cmdsn > exp_cmdsn - INVALID_SN_DELTA) + return ISCSI_ERR_MAX_CMDSN; + if (max_cmdsn > session->max_cmdsn || + max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA) + session->max_cmdsn = max_cmdsn; + if (exp_cmdsn > session->exp_cmdsn || + exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA) + session->exp_cmdsn = exp_cmdsn; + + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn); + +void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask, + struct iscsi_data *hdr, + int transport_data_cnt) +{ + struct iscsi_conn *conn = ctask->conn; + + memset(hdr, 0, sizeof(struct iscsi_data)); + hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); + hdr->datasn = cpu_to_be32(ctask->unsol_datasn); + ctask->unsol_datasn++; + hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; + memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); + + hdr->itt = ctask->hdr->itt; + hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); + + hdr->offset = cpu_to_be32(ctask->total_length - + transport_data_cnt - + ctask->unsol_count); + + if (ctask->unsol_count > conn->max_xmit_dlength) { + hton24(hdr->dlength, conn->max_xmit_dlength); + ctask->data_count = conn->max_xmit_dlength; + hdr->flags = 0; + } else { + hton24(hdr->dlength, ctask->unsol_count); + ctask->data_count = ctask->unsol_count; + hdr->flags = ISCSI_FLAG_CMD_FINAL; + } +} +EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu); + +/** + * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu + * @ctask: iscsi cmd task + * + * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set + * fields like dlength or final based on how much data it sends + */ +static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) +{ + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + struct iscsi_cmd *hdr = ctask->hdr; + struct scsi_cmnd *sc = ctask->sc; + + hdr->opcode = ISCSI_OP_SCSI_CMD; + hdr->flags = ISCSI_ATTR_SIMPLE; + int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); + hdr->itt = ctask->itt | (conn->id << ISCSI_CID_SHIFT) | + (session->age << ISCSI_AGE_SHIFT); + hdr->data_length = cpu_to_be32(sc->request_bufflen); + hdr->cmdsn = cpu_to_be32(session->cmdsn); + session->cmdsn++; + hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); + memcpy(hdr->cdb, sc->cmnd, sc->cmd_len); + memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len); + + if (sc->sc_data_direction == DMA_TO_DEVICE) { + hdr->flags |= ISCSI_FLAG_CMD_WRITE; + /* + * Write counters: + * + * imm_count bytes to be sent right after + * SCSI PDU Header + * + * unsol_count bytes(as Data-Out) to be sent + * without R2T ack right after + * immediate data + * + * r2t_data_count bytes to be sent via R2T ack's + * + * pad_count bytes to be sent as zero-padding + */ + ctask->imm_count = 0; + ctask->unsol_count = 0; + ctask->unsol_datasn = 0; + + if (session->imm_data_en) { + if (ctask->total_length >= session->first_burst) + ctask->imm_count = min(session->first_burst, + conn->max_xmit_dlength); + else + ctask->imm_count = min(ctask->total_length, + conn->max_xmit_dlength); + hton24(ctask->hdr->dlength, ctask->imm_count); + } else + zero_data(ctask->hdr->dlength); + + if (!session->initial_r2t_en) + ctask->unsol_count = min(session->first_burst, + ctask->total_length) - ctask->imm_count; + if (!ctask->unsol_count) + /* No unsolicit Data-Out's */ + ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL; + } else { + ctask->datasn = 0; + hdr->flags |= ISCSI_FLAG_CMD_FINAL; + zero_data(hdr->dlength); + + if (sc->sc_data_direction == DMA_FROM_DEVICE) + hdr->flags |= ISCSI_FLAG_CMD_READ; + } + + conn->scsicmd_pdus_cnt++; +} +EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu); + +/** + * iscsi_complete_command - return command back to scsi-ml + * @session: iscsi session + * @ctask: iscsi cmd task + * + * Must be called with session lock. + * This function returns the scsi command to scsi-ml and returns + * the cmd task to the pool of available cmd tasks. + */ +static void iscsi_complete_command(struct iscsi_session *session, + struct iscsi_cmd_task *ctask) +{ + struct scsi_cmnd *sc = ctask->sc; + + ctask->sc = NULL; + list_del_init(&ctask->running); + __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); + sc->scsi_done(sc); +} + +/** + * iscsi_cmd_rsp - SCSI Command Response processing + * @conn: iscsi connection + * @hdr: iscsi header + * @ctask: scsi command task + * @data: cmd data buffer + * @datalen: len of buffer + * + * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and + * then completes the command and task. + **/ +static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + struct iscsi_cmd_task *ctask, char *data, + int datalen) +{ + int rc; + struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr; + struct iscsi_session *session = conn->session; + struct scsi_cmnd *sc = ctask->sc; + + rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); + if (rc) { + sc->result = DID_ERROR << 16; + goto out; + } + + conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; + + sc->result = (DID_OK << 16) | rhdr->cmd_status; + + if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) { + sc->result = DID_ERROR << 16; + goto out; + } + + if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION) { + int senselen; + + if (datalen < 2) { +invalid_datalen: + printk(KERN_ERR "iscsi: Got CHECK_CONDITION but " + "invalid data buffer size of %d\n", datalen); + sc->result = DID_BAD_TARGET << 16; + goto out; + } + + senselen = (data[0] << 8) | data[1]; + if (datalen < senselen) + goto invalid_datalen; + + memcpy(sc->sense_buffer, data + 2, + min(senselen, SCSI_SENSE_BUFFERSIZE)); + debug_scsi("copied %d bytes of sense\n", + min(senselen, SCSI_SENSE_BUFFERSIZE)); + } + + if (sc->sc_data_direction == DMA_TO_DEVICE) + goto out; + + if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { + int res_count = be32_to_cpu(rhdr->residual_count); + + if (res_count > 0 && res_count <= sc->request_bufflen) + sc->resid = res_count; + else + sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; + } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW) + sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; + else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) + sc->resid = be32_to_cpu(rhdr->residual_count); + +out: + debug_scsi("done [sc %lx res %d itt 0x%x]\n", + (long)sc, sc->result, ctask->itt); + conn->scsirsp_pdus_cnt++; + + iscsi_complete_command(conn->session, ctask); + return rc; +} + +/** + * __iscsi_complete_pdu - complete pdu + * @conn: iscsi conn + * @hdr: iscsi header + * @data: data buffer + * @datalen: len of data buffer + * + * Completes pdu processing by freeing any resources allocated at + * queuecommand or send generic. session lock must be held and verify + * itt must have been called. + */ +int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + char *data, int datalen) +{ + struct iscsi_session *session = conn->session; + int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0; + struct iscsi_cmd_task *ctask; + struct iscsi_mgmt_task *mtask; + uint32_t itt; + + if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) + itt = hdr->itt & ISCSI_ITT_MASK; + else + itt = hdr->itt; + + if (itt < session->cmds_max) { + ctask = session->cmds[itt]; + + debug_scsi("cmdrsp [op 0x%x cid %d itt 0x%x len %d]\n", + opcode, conn->id, ctask->itt, datalen); + + switch(opcode) { + case ISCSI_OP_SCSI_CMD_RSP: + BUG_ON((void*)ctask != ctask->sc->SCp.ptr); + rc = iscsi_scsi_cmd_rsp(conn, hdr, ctask, data, + datalen); + break; + case ISCSI_OP_SCSI_DATA_IN: + BUG_ON((void*)ctask != ctask->sc->SCp.ptr); + if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { + conn->scsirsp_pdus_cnt++; + iscsi_complete_command(session, ctask); + } + break; + case ISCSI_OP_R2T: + /* LLD handles this for now */ + break; + default: + rc = ISCSI_ERR_BAD_OPCODE; + break; + } + } else if (itt >= ISCSI_MGMT_ITT_OFFSET && + itt < ISCSI_MGMT_ITT_OFFSET + session->mgmtpool_max) { + mtask = session->mgmt_cmds[itt - ISCSI_MGMT_ITT_OFFSET]; + + debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n", + opcode, conn->id, mtask->itt, datalen); + + rc = iscsi_check_assign_cmdsn(session, + (struct iscsi_nopin*)hdr); + if (rc) + goto done; + + switch(opcode) { + case ISCSI_OP_LOGOUT_RSP: + conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; + /* fall through */ + case ISCSI_OP_LOGIN_RSP: + case ISCSI_OP_TEXT_RSP: + /* + * login related PDU's exp_statsn is handled in + * userspace + */ + rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen); + list_del(&mtask->running); + if (conn->login_mtask != mtask) + __kfifo_put(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*)); + break; + case ISCSI_OP_SCSI_TMFUNC_RSP: + if (datalen) { + rc = ISCSI_ERR_PROTO; + break; + } + + conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; + conn->tmfrsp_pdus_cnt++; + if (conn->tmabort_state == TMABORT_INITIAL) { + conn->tmabort_state = + ((struct iscsi_tm_rsp *)hdr)-> + response == ISCSI_TMF_RSP_COMPLETE ? + TMABORT_SUCCESS:TMABORT_FAILED; + /* unblock eh_abort() */ + wake_up(&conn->ehwait); + } + break; + case ISCSI_OP_NOOP_IN: + if (hdr->ttt != ISCSI_RESERVED_TAG) { + rc = ISCSI_ERR_PROTO; + break; + } + conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; + + rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen); + list_del(&mtask->running); + if (conn->login_mtask != mtask) + __kfifo_put(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*)); + break; + default: + rc = ISCSI_ERR_BAD_OPCODE; + break; + } + } else if (itt == ISCSI_RESERVED_TAG) { + switch(opcode) { + case ISCSI_OP_NOOP_IN: + if (!datalen) { + rc = iscsi_check_assign_cmdsn(session, + (struct iscsi_nopin*)hdr); + if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) + rc = iscsi_recv_pdu(conn->cls_conn, + hdr, NULL, 0); + } else + rc = ISCSI_ERR_PROTO; + break; + case ISCSI_OP_REJECT: + /* we need sth like iscsi_reject_rsp()*/ + case ISCSI_OP_ASYNC_EVENT: + conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; + /* we need sth like iscsi_async_event_rsp() */ + rc = ISCSI_ERR_BAD_OPCODE; + break; + default: + rc = ISCSI_ERR_BAD_OPCODE; + break; + } + } else + rc = ISCSI_ERR_BAD_ITT; + +done: + return rc; +} +EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); + +int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + char *data, int datalen) +{ + int rc; + + spin_lock(&conn->session->lock); + rc = __iscsi_complete_pdu(conn, hdr, data, datalen); + spin_unlock(&conn->session->lock); + return rc; +} +EXPORT_SYMBOL_GPL(iscsi_complete_pdu); + +/* verify itt (itt encoding: age+cid+itt) */ +int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + uint32_t *ret_itt) +{ + struct iscsi_session *session = conn->session; + struct iscsi_cmd_task *ctask; + uint32_t itt; + + if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { + if ((hdr->itt & ISCSI_AGE_MASK) != + (session->age << ISCSI_AGE_SHIFT)) { + printk(KERN_ERR "iscsi: received itt %x expected " + "session age (%x)\n", hdr->itt, + session->age & ISCSI_AGE_MASK); + return ISCSI_ERR_BAD_ITT; + } + + if ((hdr->itt & ISCSI_CID_MASK) != + (conn->id << ISCSI_CID_SHIFT)) { + printk(KERN_ERR "iscsi: received itt %x, expected " + "CID (%x)\n", hdr->itt, conn->id); + return ISCSI_ERR_BAD_ITT; + } + itt = hdr->itt & ISCSI_ITT_MASK; + } else + itt = hdr->itt; + + if (itt < session->cmds_max) { + ctask = session->cmds[itt]; + + if (!ctask->sc) { + printk(KERN_INFO "iscsi: dropping ctask with " + "itt 0x%x\n", ctask->itt); + /* force drop */ + return ISCSI_ERR_NO_SCSI_CMD; + } + + if (ctask->sc->SCp.phase != session->age) { + printk(KERN_ERR "iscsi: ctask's session age %d, " + "expected %d\n", ctask->sc->SCp.phase, + session->age); + return ISCSI_ERR_SESSION_FAILED; + } + } + + *ret_itt = itt; + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_verify_itt); + +void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) +{ + struct iscsi_session *session = conn->session; + unsigned long flags; + + spin_lock_irqsave(&session->lock, flags); + if (session->state == ISCSI_STATE_FAILED) { + spin_unlock_irqrestore(&session->lock, flags); + return; + } + + if (conn->stop_stage == 0) + session->state = ISCSI_STATE_FAILED; + spin_unlock_irqrestore(&session->lock, flags); + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); + iscsi_conn_error(conn->cls_conn, err); +} +EXPORT_SYMBOL_GPL(iscsi_conn_failure); + +/** + * iscsi_data_xmit - xmit any command into the scheduled connection + * @conn: iscsi connection + * + * Notes: + * The function can return -EAGAIN in which case the caller must + * re-schedule it again later or recover. '0' return code means + * successful xmit. + **/ +static int iscsi_data_xmit(struct iscsi_conn *conn) +{ + struct iscsi_transport *tt; + int rc = 0; + + if (unlikely(conn->suspend_tx)) { + debug_scsi("conn %d Tx suspended!\n", conn->id); + return -ENODATA; + } + tt = conn->session->tt; + + /* + * Transmit in the following order: + * + * 1) un-finished xmit (ctask or mtask) + * 2) immediate control PDUs + * 3) write data + * 4) SCSI commands + * 5) non-immediate control PDUs + * + * No need to lock around __kfifo_get as long as + * there's one producer and one consumer. + */ + + BUG_ON(conn->ctask && conn->mtask); + + if (conn->ctask) { + rc = tt->xmit_cmd_task(conn, conn->ctask); + if (rc) + goto again; + /* done with this in-progress ctask */ + conn->ctask = NULL; + } + if (conn->mtask) { + rc = tt->xmit_mgmt_task(conn, conn->mtask); + if (rc) + goto again; + /* done with this in-progress mtask */ + conn->mtask = NULL; + } + + /* process immediate first */ + if (unlikely(__kfifo_len(conn->immqueue))) { + while (__kfifo_get(conn->immqueue, (void*)&conn->mtask, + sizeof(void*))) { + spin_lock_bh(&conn->session->lock); + list_add_tail(&conn->mtask->running, + &conn->mgmt_run_list); + spin_unlock_bh(&conn->session->lock); + rc = tt->xmit_mgmt_task(conn, conn->mtask); + if (rc) + goto again; + } + /* done with this mtask */ + conn->mtask = NULL; + } + + /* process command queue */ + while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask, + sizeof(void*))) { + /* + * iscsi tcp may readd the task to the xmitqueue to send + * write data + */ + spin_lock_bh(&conn->session->lock); + if (list_empty(&conn->ctask->running)) + list_add_tail(&conn->ctask->running, &conn->run_list); + spin_unlock_bh(&conn->session->lock); + rc = tt->xmit_cmd_task(conn, conn->ctask); + if (rc) + goto again; + } + /* done with this ctask */ + conn->ctask = NULL; + + /* process the rest control plane PDUs, if any */ + if (unlikely(__kfifo_len(conn->mgmtqueue))) { + while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask, + sizeof(void*))) { + spin_lock_bh(&conn->session->lock); + list_add_tail(&conn->mtask->running, + &conn->mgmt_run_list); + spin_unlock_bh(&conn->session->lock); + rc = tt->xmit_mgmt_task(conn, conn->mtask); + if (rc) + goto again; + } + /* done with this mtask */ + conn->mtask = NULL; + } + + return -ENODATA; + +again: + if (unlikely(conn->suspend_tx)) + return -ENODATA; + + return rc; +} + +static void iscsi_xmitworker(void *data) +{ + struct iscsi_conn *conn = data; + int rc; + /* + * serialize Xmit worker on a per-connection basis. + */ + mutex_lock(&conn->xmitmutex); + do { + rc = iscsi_data_xmit(conn); + } while (rc >= 0 || rc == -EAGAIN); + mutex_unlock(&conn->xmitmutex); +} + +enum { + FAILURE_BAD_HOST = 1, + FAILURE_SESSION_FAILED, + FAILURE_SESSION_FREED, + FAILURE_WINDOW_CLOSED, + FAILURE_SESSION_TERMINATE, + FAILURE_SESSION_IN_RECOVERY, + FAILURE_SESSION_RECOVERY_TIMEOUT, +}; + +int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) +{ + struct Scsi_Host *host; + int reason = 0; + struct iscsi_session *session; + struct iscsi_conn *conn; + struct iscsi_cmd_task *ctask = NULL; + + sc->scsi_done = done; + sc->result = 0; + + host = sc->device->host; + session = iscsi_hostdata(host->hostdata); + + spin_lock(&session->lock); + + /* + * ISCSI_STATE_FAILED is a temp. state. The recovery + * code will decide what is best to do with command queued + * during this time + */ + if (session->state != ISCSI_STATE_LOGGED_IN && + session->state != ISCSI_STATE_FAILED) { + /* + * to handle the race between when we set the recovery state + * and block the session we requeue here (commands could + * be entering our queuecommand while a block is starting + * up because the block code is not locked) + */ + if (session->state == ISCSI_STATE_IN_RECOVERY) { + reason = FAILURE_SESSION_IN_RECOVERY; + goto reject; + } + + if (session->state == ISCSI_STATE_RECOVERY_FAILED) + reason = FAILURE_SESSION_RECOVERY_TIMEOUT; + else if (session->state == ISCSI_STATE_TERMINATE) + reason = FAILURE_SESSION_TERMINATE; + else + reason = FAILURE_SESSION_FREED; + goto fault; + } + + /* + * Check for iSCSI window and take care of CmdSN wrap-around + */ + if ((int)(session->max_cmdsn - session->cmdsn) < 0) { + reason = FAILURE_WINDOW_CLOSED; + goto reject; + } + + conn = session->leadconn; + + __kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); + sc->SCp.phase = session->age; + sc->SCp.ptr = (char *)ctask; + + ctask->mtask = NULL; + ctask->conn = conn; + ctask->sc = sc; + INIT_LIST_HEAD(&ctask->running); + ctask->total_length = sc->request_bufflen; + iscsi_prep_scsi_cmd_pdu(ctask); + + session->tt->init_cmd_task(ctask); + + __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); + debug_scsi( + "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", + sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", + conn->id, (long)sc, ctask->itt, sc->request_bufflen, + session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); + spin_unlock(&session->lock); + + scsi_queue_work(host, &conn->xmitwork); + return 0; + +reject: + spin_unlock(&session->lock); + debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason); + return SCSI_MLQUEUE_HOST_BUSY; + +fault: + spin_unlock(&session->lock); + printk(KERN_ERR "iscsi: cmd 0x%x is not queued (%d)\n", + sc->cmnd[0], reason); + sc->result = (DID_NO_CONNECT << 16); + sc->resid = sc->request_bufflen; + sc->scsi_done(sc); + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_queuecommand); + +int iscsi_change_queue_depth(struct scsi_device *sdev, int depth) +{ + if (depth > ISCSI_MAX_CMD_PER_LUN) + depth = ISCSI_MAX_CMD_PER_LUN; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); + return sdev->queue_depth; +} +EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); + +static int +iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + char *data, uint32_t data_size) +{ + struct iscsi_session *session = conn->session; + struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; + struct iscsi_mgmt_task *mtask; + + spin_lock_bh(&session->lock); + if (session->state == ISCSI_STATE_TERMINATE) { + spin_unlock_bh(&session->lock); + return -EPERM; + } + if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) || + hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) + /* + * Login and Text are sent serially, in + * request-followed-by-response sequence. + * Same mtask can be used. Same ITT must be used. + * Note that login_mtask is preallocated at conn_create(). + */ + mtask = conn->login_mtask; + else { + BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); + BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); + + nop->exp_statsn = cpu_to_be32(conn->exp_statsn); + if (!__kfifo_get(session->mgmtpool.queue, + (void*)&mtask, sizeof(void*))) { + spin_unlock_bh(&session->lock); + return -ENOSPC; + } + } + + /* + * pre-format CmdSN for outgoing PDU. + */ + if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { + hdr->itt = mtask->itt | (conn->id << ISCSI_CID_SHIFT) | + (session->age << ISCSI_AGE_SHIFT); + nop->cmdsn = cpu_to_be32(session->cmdsn); + if (conn->c_stage == ISCSI_CONN_STARTED && + !(hdr->opcode & ISCSI_OP_IMMEDIATE)) + session->cmdsn++; + } else + /* do not advance CmdSN */ + nop->cmdsn = cpu_to_be32(session->cmdsn); + + if (data_size) { + memcpy(mtask->data, data, data_size); + mtask->data_count = data_size; + } else + mtask->data_count = 0; + + INIT_LIST_HEAD(&mtask->running); + memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); + if (session->tt->init_mgmt_task) + session->tt->init_mgmt_task(conn, mtask, data, data_size); + spin_unlock_bh(&session->lock); + + debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", + hdr->opcode, hdr->itt, data_size); + + /* + * since send_pdu() could be called at least from two contexts, + * we need to serialize __kfifo_put, so we don't have to take + * additional lock on fast data-path + */ + if (hdr->opcode & ISCSI_OP_IMMEDIATE) + __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*)); + else + __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); + + scsi_queue_work(session->host, &conn->xmitwork); + return 0; +} + +int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, + char *data, uint32_t data_size) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + int rc; + + mutex_lock(&conn->xmitmutex); + rc = iscsi_conn_send_generic(conn, hdr, data, data_size); + mutex_unlock(&conn->xmitmutex); + + return rc; +} +EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); + +void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) +{ + struct iscsi_session *session = class_to_transport_session(cls_session); + struct iscsi_conn *conn = session->leadconn; + + spin_lock_bh(&session->lock); + if (session->state != ISCSI_STATE_LOGGED_IN) { + session->state = ISCSI_STATE_RECOVERY_FAILED; + if (conn) + wake_up(&conn->ehwait); + } + spin_unlock_bh(&session->lock); +} +EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout); + +int iscsi_eh_host_reset(struct scsi_cmnd *sc) +{ + struct Scsi_Host *host = sc->device->host; + struct iscsi_session *session = iscsi_hostdata(host->hostdata); + struct iscsi_conn *conn = session->leadconn; + int fail_session = 0; + + spin_lock_bh(&session->lock); + if (session->state == ISCSI_STATE_TERMINATE) { +failed: + debug_scsi("failing host reset: session terminated " + "[CID %d age %d]", conn->id, session->age); + spin_unlock_bh(&session->lock); + return FAILED; + } + + if (sc->SCp.phase == session->age) { + debug_scsi("failing connection CID %d due to SCSI host reset", + conn->id); + fail_session = 1; + } + spin_unlock_bh(&session->lock); + + /* + * we drop the lock here but the leadconn cannot be destoyed while + * we are in the scsi eh + */ + if (fail_session) + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + + debug_scsi("iscsi_eh_host_reset wait for relogin\n"); + wait_event_interruptible(conn->ehwait, + session->state == ISCSI_STATE_TERMINATE || + session->state == ISCSI_STATE_LOGGED_IN || + session->state == ISCSI_STATE_RECOVERY_FAILED); + if (signal_pending(current)) + flush_signals(current); + + spin_lock_bh(&session->lock); + if (session->state == ISCSI_STATE_LOGGED_IN) + printk(KERN_INFO "iscsi: host reset succeeded\n"); + else + goto failed; + spin_unlock_bh(&session->lock); + + return SUCCESS; +} +EXPORT_SYMBOL_GPL(iscsi_eh_host_reset); + +static void iscsi_tmabort_timedout(unsigned long data) +{ + struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data; + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + + spin_lock(&session->lock); + if (conn->tmabort_state == TMABORT_INITIAL) { + conn->tmabort_state = TMABORT_TIMEDOUT; + debug_scsi("tmabort timedout [sc %p itt 0x%x]\n", + ctask->sc, ctask->itt); + /* unblock eh_abort() */ + wake_up(&conn->ehwait); + } + spin_unlock(&session->lock); +} + +/* must be called with the mutex lock */ +static int iscsi_exec_abort_task(struct scsi_cmnd *sc, + struct iscsi_cmd_task *ctask) +{ + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + struct iscsi_tm *hdr = &conn->tmhdr; + int rc; + + /* + * ctask timed out but session is OK requests must be serialized. + */ + memset(hdr, 0, sizeof(struct iscsi_tm)); + hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; + hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; + hdr->flags |= ISCSI_FLAG_CMD_FINAL; + memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); + hdr->rtt = ctask->hdr->itt; + hdr->refcmdsn = ctask->hdr->cmdsn; + + rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr, + NULL, 0); + if (rc) { + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc); + return rc; + } + + debug_scsi("abort sent [itt 0x%x]\n", ctask->itt); + + spin_lock_bh(&session->lock); + ctask->mtask = (struct iscsi_mgmt_task *) + session->mgmt_cmds[(hdr->itt & ISCSI_ITT_MASK) - + ISCSI_MGMT_ITT_OFFSET]; + + if (conn->tmabort_state == TMABORT_INITIAL) { + conn->tmfcmd_pdus_cnt++; + conn->tmabort_timer.expires = 10*HZ + jiffies; + conn->tmabort_timer.function = iscsi_tmabort_timedout; + conn->tmabort_timer.data = (unsigned long)ctask; + add_timer(&conn->tmabort_timer); + debug_scsi("abort set timeout [itt 0x%x]", ctask->itt); + } + spin_unlock_bh(&session->lock); + mutex_unlock(&conn->xmitmutex); + + /* + * block eh thread until: + * + * 1) abort response + * 2) abort timeout + * 3) session is terminated or restarted or userspace has + * given up on recovery + */ + wait_event_interruptible(conn->ehwait, + sc->SCp.phase != session->age || + session->state != ISCSI_STATE_LOGGED_IN || + conn->tmabort_state != TMABORT_INITIAL); + if (signal_pending(current)) + flush_signals(current); + del_timer_sync(&conn->tmabort_timer); + + mutex_lock(&conn->xmitmutex); + return 0; +} + +/* + * xmit mutex and session lock must be held + */ +#define iscsi_remove_task(tasktype) \ +static struct iscsi_##tasktype * \ +iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt) \ +{ \ + int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); \ + struct iscsi_##tasktype *task; \ + \ + debug_scsi("searching %d tasks\n", nr_tasks); \ + \ + for (i = 0; i < nr_tasks; i++) { \ + __kfifo_get(fifo, (void*)&task, sizeof(void*)); \ + debug_scsi("check task %u\n", task->itt); \ + \ + if (task->itt == itt) { \ + debug_scsi("matched task\n"); \ + return task; \ + } \ + \ + __kfifo_put(fifo, (void*)&task, sizeof(void*)); \ + } \ + return NULL; \ +} + +iscsi_remove_task(mgmt_task); +iscsi_remove_task(cmd_task); + +static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) +{ + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + + if (!ctask->mtask) + return -EINVAL; + + if (!iscsi_remove_mgmt_task(conn->immqueue, ctask->mtask->itt)) + list_del(&ctask->mtask->running); + __kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask, + sizeof(void*)); + ctask->mtask = NULL; + return 0; +} + +/* + * session lock and xmitmutex must be held + */ +static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, + int err) +{ + struct scsi_cmnd *sc; + + conn->session->tt->cleanup_cmd_task(conn, ctask); + iscsi_ctask_mtask_cleanup(ctask); + + sc = ctask->sc; + if (!sc) + return; + sc->result = err; + sc->resid = sc->request_bufflen; + iscsi_complete_command(conn->session, ctask); +} + +int iscsi_eh_abort(struct scsi_cmnd *sc) +{ + struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; + struct iscsi_conn *conn = ctask->conn; + struct iscsi_session *session = conn->session; + struct iscsi_cmd_task *pending_ctask; + int rc; + + conn->eh_abort_cnt++; + debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); + + mutex_lock(&conn->xmitmutex); + spin_lock_bh(&session->lock); + + /* + * If we are not logged in or we have started a new session + * then let the host reset code handle this + */ + if (session->state != ISCSI_STATE_LOGGED_IN || + sc->SCp.phase != session->age) + goto failed; + + /* ctask completed before time out */ + if (!ctask->sc) + goto success; + + /* what should we do here ? */ + if (conn->ctask == ctask) { + printk(KERN_INFO "iscsi: sc %p itt 0x%x partially sent. " + "Failing abort\n", sc, ctask->itt); + goto failed; + } + + /* check for the easy pending cmd abort */ + pending_ctask = iscsi_remove_cmd_task(conn->xmitqueue, ctask->itt); + if (pending_ctask) { + /* iscsi_tcp queues write transfers on the xmitqueue */ + if (list_empty(&pending_ctask->running)) { + debug_scsi("found pending task\n"); + goto success; + } else + __kfifo_put(conn->xmitqueue, (void*)&pending_ctask, + sizeof(void*)); + } + + conn->tmabort_state = TMABORT_INITIAL; + + spin_unlock_bh(&session->lock); + rc = iscsi_exec_abort_task(sc, ctask); + spin_lock_bh(&session->lock); + + iscsi_ctask_mtask_cleanup(ctask); + if (rc || sc->SCp.phase != session->age || + session->state != ISCSI_STATE_LOGGED_IN) + goto failed; + + /* ctask completed before tmf abort response */ + if (!ctask->sc) { + debug_scsi("sc completed while abort in progress\n"); + goto success; + } + + if (conn->tmabort_state != TMABORT_SUCCESS) { + spin_unlock_bh(&session->lock); + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + spin_lock_bh(&session->lock); + goto failed; + } + +success: + debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + spin_unlock_bh(&session->lock); + + /* + * clean up task if aborted. we have the xmitmutex so grab + * the recv lock as a writer + */ + write_lock_bh(conn->recv_lock); + spin_lock(&session->lock); + fail_command(conn, ctask, DID_ABORT << 16); + spin_unlock(&session->lock); + write_unlock_bh(conn->recv_lock); + + mutex_unlock(&conn->xmitmutex); + return SUCCESS; + +failed: + spin_unlock_bh(&session->lock); + mutex_unlock(&conn->xmitmutex); + + debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + return FAILED; +} +EXPORT_SYMBOL_GPL(iscsi_eh_abort); + +int +iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) +{ + int i; + + *items = kmalloc(max * sizeof(void*), GFP_KERNEL); + if (*items == NULL) + return -ENOMEM; + + q->max = max; + q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL); + if (q->pool == NULL) { + kfree(*items); + return -ENOMEM; + } + + q->queue = kfifo_init((void*)q->pool, max * sizeof(void*), + GFP_KERNEL, NULL); + if (q->queue == ERR_PTR(-ENOMEM)) { + kfree(q->pool); + kfree(*items); + return -ENOMEM; + } + + for (i = 0; i < max; i++) { + q->pool[i] = kmalloc(item_size, GFP_KERNEL); + if (q->pool[i] == NULL) { + int j; + + for (j = 0; j < i; j++) + kfree(q->pool[j]); + + kfifo_free(q->queue); + kfree(q->pool); + kfree(*items); + return -ENOMEM; + } + memset(q->pool[i], 0, item_size); + (*items)[i] = q->pool[i]; + __kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*)); + } + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_pool_init); + +void iscsi_pool_free(struct iscsi_queue *q, void **items) +{ + int i; + + for (i = 0; i < q->max; i++) + kfree(items[i]); + kfree(q->pool); + kfree(items); +} +EXPORT_SYMBOL_GPL(iscsi_pool_free); + +/* + * iSCSI Session's hostdata organization: + * + * *------------------* <== hostdata_session(host->hostdata) + * | ptr to class sess| + * |------------------| <== iscsi_hostdata(host->hostdata) + * | iscsi_session | + * *------------------* + */ + +#define hostdata_privsize(_sz) (sizeof(unsigned long) + _sz + \ + _sz % sizeof(unsigned long)) + +#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata)) + +/** + * iscsi_session_setup - create iscsi cls session and host and session + * @scsit: scsi transport template + * @iscsit: iscsi transport template + * @initial_cmdsn: initial CmdSN + * @hostno: host no allocated + * + * This can be used by software iscsi_transports that allocate + * a session per scsi host. + **/ +struct iscsi_cls_session * +iscsi_session_setup(struct iscsi_transport *iscsit, + struct scsi_transport_template *scsit, + int cmd_task_size, int mgmt_task_size, + uint32_t initial_cmdsn, uint32_t *hostno) +{ + struct Scsi_Host *shost; + struct iscsi_session *session; + struct iscsi_cls_session *cls_session; + int cmd_i; + + shost = scsi_host_alloc(iscsit->host_template, + hostdata_privsize(sizeof(*session))); + if (!shost) + return NULL; + + shost->max_id = 1; + shost->max_channel = 0; + shost->max_lun = iscsit->max_lun; + shost->max_cmd_len = iscsit->max_cmd_len; + shost->transportt = scsit; + shost->transportt->create_work_queue = 1; + *hostno = shost->host_no; + + session = iscsi_hostdata(shost->hostdata); + memset(session, 0, sizeof(struct iscsi_session)); + session->host = shost; + session->state = ISCSI_STATE_FREE; + session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; + session->cmds_max = ISCSI_XMIT_CMDS_MAX; + session->cmdsn = initial_cmdsn; + session->exp_cmdsn = initial_cmdsn + 1; + session->max_cmdsn = initial_cmdsn + 1; + session->max_r2t = 1; + session->tt = iscsit; + + /* initialize SCSI PDU commands pool */ + if (iscsi_pool_init(&session->cmdpool, session->cmds_max, + (void***)&session->cmds, + cmd_task_size + sizeof(struct iscsi_cmd_task))) + goto cmdpool_alloc_fail; + + /* pre-format cmds pool with ITT */ + for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { + struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; + + if (cmd_task_size) + ctask->dd_data = &ctask[1]; + ctask->itt = cmd_i; + } + + spin_lock_init(&session->lock); + INIT_LIST_HEAD(&session->connections); + + /* initialize immediate command pool */ + if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, + (void***)&session->mgmt_cmds, + mgmt_task_size + sizeof(struct iscsi_mgmt_task))) + goto mgmtpool_alloc_fail; + + + /* pre-format immediate cmds pool with ITT */ + for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { + struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i]; + + if (mgmt_task_size) + mtask->dd_data = &mtask[1]; + mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; + } + + if (scsi_add_host(shost, NULL)) + goto add_host_fail; + + cls_session = iscsi_create_session(shost, iscsit, 0); + if (!cls_session) + goto cls_session_fail; + *(unsigned long*)shost->hostdata = (unsigned long)cls_session; + + return cls_session; + +cls_session_fail: + scsi_remove_host(shost); +add_host_fail: + iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); +mgmtpool_alloc_fail: + iscsi_pool_free(&session->cmdpool, (void**)session->cmds); +cmdpool_alloc_fail: + scsi_host_put(shost); + return NULL; +} +EXPORT_SYMBOL_GPL(iscsi_session_setup); + +/** + * iscsi_session_teardown - destroy session, host, and cls_session + * shost: scsi host + * + * This can be used by software iscsi_transports that allocate + * a session per scsi host. + **/ +void iscsi_session_teardown(struct iscsi_cls_session *cls_session) +{ + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + struct iscsi_session *session = iscsi_hostdata(shost->hostdata); + + scsi_remove_host(shost); + + iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); + iscsi_pool_free(&session->cmdpool, (void**)session->cmds); + + iscsi_destroy_session(cls_session); + scsi_host_put(shost); +} +EXPORT_SYMBOL_GPL(iscsi_session_teardown); + +/** + * iscsi_conn_setup - create iscsi_cls_conn and iscsi_conn + * @cls_session: iscsi_cls_session + * @conn_idx: cid + **/ +struct iscsi_cls_conn * +iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) +{ + struct iscsi_session *session = class_to_transport_session(cls_session); + struct iscsi_conn *conn; + struct iscsi_cls_conn *cls_conn; + char *data; + + cls_conn = iscsi_create_conn(cls_session, conn_idx); + if (!cls_conn) + return NULL; + conn = cls_conn->dd_data; + memset(conn, 0, sizeof(*conn)); + + conn->session = session; + conn->cls_conn = cls_conn; + conn->c_stage = ISCSI_CONN_INITIAL_STAGE; + conn->id = conn_idx; + conn->exp_statsn = 0; + conn->tmabort_state = TMABORT_INITIAL; + INIT_LIST_HEAD(&conn->run_list); + INIT_LIST_HEAD(&conn->mgmt_run_list); + + /* initialize general xmit PDU commands queue */ + conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*), + GFP_KERNEL, NULL); + if (conn->xmitqueue == ERR_PTR(-ENOMEM)) + goto xmitqueue_alloc_fail; + + /* initialize general immediate & non-immediate PDU commands queue */ + conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), + GFP_KERNEL, NULL); + if (conn->immqueue == ERR_PTR(-ENOMEM)) + goto immqueue_alloc_fail; + + conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), + GFP_KERNEL, NULL); + if (conn->mgmtqueue == ERR_PTR(-ENOMEM)) + goto mgmtqueue_alloc_fail; + + INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn); + + /* allocate login_mtask used for the login/text sequences */ + spin_lock_bh(&session->lock); + if (!__kfifo_get(session->mgmtpool.queue, + (void*)&conn->login_mtask, + sizeof(void*))) { + spin_unlock_bh(&session->lock); + goto login_mtask_alloc_fail; + } + spin_unlock_bh(&session->lock); + + data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); + if (!data) + goto login_mtask_data_alloc_fail; + conn->login_mtask->data = data; + + init_timer(&conn->tmabort_timer); + mutex_init(&conn->xmitmutex); + init_waitqueue_head(&conn->ehwait); + + return cls_conn; + +login_mtask_data_alloc_fail: + __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, + sizeof(void*)); +login_mtask_alloc_fail: + kfifo_free(conn->mgmtqueue); +mgmtqueue_alloc_fail: + kfifo_free(conn->immqueue); +immqueue_alloc_fail: + kfifo_free(conn->xmitqueue); +xmitqueue_alloc_fail: + iscsi_destroy_conn(cls_conn); + return NULL; +} +EXPORT_SYMBOL_GPL(iscsi_conn_setup); + +/** + * iscsi_conn_teardown - teardown iscsi connection + * cls_conn: iscsi class connection + * + * TODO: we may need to make this into a two step process + * like scsi-mls remove + put host + */ +void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; + unsigned long flags; + + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + mutex_lock(&conn->xmitmutex); + if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) { + if (session->tt->suspend_conn_recv) + session->tt->suspend_conn_recv(conn); + + session->tt->terminate_conn(conn); + } + + spin_lock_bh(&session->lock); + conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; + if (session->leadconn == conn) { + /* + * leading connection? then give up on recovery. + */ + session->state = ISCSI_STATE_TERMINATE; + wake_up(&conn->ehwait); + } + spin_unlock_bh(&session->lock); + + mutex_unlock(&conn->xmitmutex); + + /* + * Block until all in-progress commands for this connection + * time out or fail. + */ + for (;;) { + spin_lock_irqsave(session->host->host_lock, flags); + if (!session->host->host_busy) { /* OK for ERL == 0 */ + spin_unlock_irqrestore(session->host->host_lock, flags); + break; + } + spin_unlock_irqrestore(session->host->host_lock, flags); + msleep_interruptible(500); + printk(KERN_INFO "iscsi: scsi conn_destroy(): host_busy %d " + "host_failed %d\n", session->host->host_busy, + session->host->host_failed); + /* + * force eh_abort() to unblock + */ + wake_up(&conn->ehwait); + } + + spin_lock_bh(&session->lock); + kfree(conn->login_mtask->data); + __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, + sizeof(void*)); + list_del(&conn->item); + if (list_empty(&session->connections)) + session->leadconn = NULL; + if (session->leadconn && session->leadconn == conn) + session->leadconn = container_of(session->connections.next, + struct iscsi_conn, item); + + if (session->leadconn == NULL) + /* no connections exits.. reset sequencing */ + session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; + spin_unlock_bh(&session->lock); + + kfifo_free(conn->xmitqueue); + kfifo_free(conn->immqueue); + kfifo_free(conn->mgmtqueue); + + iscsi_destroy_conn(cls_conn); +} +EXPORT_SYMBOL_GPL(iscsi_conn_teardown); + +int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; + + if (session == NULL) { + printk(KERN_ERR "iscsi: can't start unbound connection\n"); + return -EPERM; + } + + spin_lock_bh(&session->lock); + conn->c_stage = ISCSI_CONN_STARTED; + session->state = ISCSI_STATE_LOGGED_IN; + + switch(conn->stop_stage) { + case STOP_CONN_RECOVER: + /* + * unblock eh_abort() if it is blocked. re-try all + * commands after successful recovery + */ + conn->stop_stage = 0; + conn->tmabort_state = TMABORT_INITIAL; + session->age++; + spin_unlock_bh(&session->lock); + + iscsi_unblock_session(session_to_cls(session)); + wake_up(&conn->ehwait); + return 0; + case STOP_CONN_TERM: + conn->stop_stage = 0; + break; + default: + break; + } + spin_unlock_bh(&session->lock); + + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_conn_start); + +static void +flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) +{ + struct iscsi_mgmt_task *mtask, *tmp; + + /* handle pending */ + while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) || + __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) { + if (mtask == conn->login_mtask) + continue; + debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt); + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + sizeof(void*)); + } + + /* handle running */ + list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) { + debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt); + list_del(&mtask->running); + + if (mtask == conn->login_mtask) + continue; + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + sizeof(void*)); + } + + conn->mtask = NULL; +} + +/* Fail commands. Mutex and session lock held and recv side suspended */ +static void fail_all_commands(struct iscsi_conn *conn) +{ + struct iscsi_cmd_task *ctask, *tmp; + + /* flush pending */ + while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) { + debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, + ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + + /* fail all other running */ + list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { + debug_scsi("failing in progress sc %p itt 0x%x\n", + ctask->sc, ctask->itt); + fail_command(conn, ctask, DID_BUS_BUSY << 16); + } + + conn->ctask = NULL; +} + +static void iscsi_start_session_recovery(struct iscsi_session *session, + struct iscsi_conn *conn, int flag) +{ + int old_stop_stage; + + spin_lock_bh(&session->lock); + if (conn->stop_stage == STOP_CONN_TERM) { + spin_unlock_bh(&session->lock); + return; + } + + /* + * When this is called for the in_login state, we only want to clean + * up the login task and connection. We do not need to block and set + * the recovery state again + */ + if (flag == STOP_CONN_TERM) + session->state = ISCSI_STATE_TERMINATE; + else if (conn->stop_stage != STOP_CONN_RECOVER) + session->state = ISCSI_STATE_IN_RECOVERY; + + old_stop_stage = conn->stop_stage; + conn->stop_stage = flag; + conn->c_stage = ISCSI_CONN_STOPPED; + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + spin_unlock_bh(&session->lock); + + if (session->tt->suspend_conn_recv) + session->tt->suspend_conn_recv(conn); + + mutex_lock(&conn->xmitmutex); + /* + * for connection level recovery we should not calculate + * header digest. conn->hdr_size used for optimization + * in hdr_extract() and will be re-negotiated at + * set_param() time. + */ + if (flag == STOP_CONN_RECOVER) { + conn->hdrdgst_en = 0; + conn->datadgst_en = 0; + if (session->state == ISCSI_STATE_IN_RECOVERY && + old_stop_stage != STOP_CONN_RECOVER) { + debug_scsi("blocking session\n"); + iscsi_block_session(session_to_cls(session)); + } + } + + session->tt->terminate_conn(conn); + /* + * flush queues. + */ + spin_lock_bh(&session->lock); + fail_all_commands(conn); + flush_control_queues(session, conn); + spin_unlock_bh(&session->lock); + + mutex_unlock(&conn->xmitmutex); +} + +void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; + + switch (flag) { + case STOP_CONN_RECOVER: + case STOP_CONN_TERM: + iscsi_start_session_recovery(session, conn, flag); + break; + default: + printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag); + } +} +EXPORT_SYMBOL_GPL(iscsi_conn_stop); + +int iscsi_conn_bind(struct iscsi_cls_session *cls_session, + struct iscsi_cls_conn *cls_conn, int is_leading) +{ + struct iscsi_session *session = class_to_transport_session(cls_session); + struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data; + + /* lookup for existing connection */ + spin_lock_bh(&session->lock); + list_for_each_entry(tmp, &session->connections, item) { + if (tmp == conn) { + if (conn->c_stage != ISCSI_CONN_STOPPED || + conn->stop_stage == STOP_CONN_TERM) { + printk(KERN_ERR "iscsi: can't bind " + "non-stopped connection (%d:%d)\n", + conn->c_stage, conn->stop_stage); + spin_unlock_bh(&session->lock); + return -EIO; + } + break; + } + } + if (tmp != conn) { + /* bind new iSCSI connection to session */ + conn->session = session; + list_add(&conn->item, &session->connections); + } + spin_unlock_bh(&session->lock); + + if (is_leading) + session->leadconn = conn; + + /* + * Unblock xmitworker(), Login Phase will pass through. + */ + clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); + clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_conn_bind); + +MODULE_AUTHOR("Mike Christie"); +MODULE_DESCRIPTION("iSCSI library functions"); +MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index e31fadd..118206d 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c @@ -43,9 +43,6 @@ #include /* #define DEBUG_MAC_ESP */ -#define mac_turnon_irq(x) mac_enable_irq(x) -#define mac_turnoff_irq(x) mac_disable_irq(x) - extern void esp_handle(struct NCR_ESP *esp); extern void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs); @@ -639,13 +636,13 @@ static void dma_init_write(struct NCR_ES static void dma_ints_off(struct NCR_ESP * esp) { - mac_turnoff_irq(esp->irq); + disable_irq(esp->irq); } static void dma_ints_on(struct NCR_ESP * esp) { - mac_turnon_irq(esp->irq); + enable_irq(esp->irq); } /* diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 777f9bc..a942a21 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -65,9 +65,6 @@ #endif #define RESET_BOOT #define DRIVER_SETUP -#define ENABLE_IRQ() mac_enable_irq( IRQ_MAC_SCSI ); -#define DISABLE_IRQ() mac_disable_irq( IRQ_MAC_SCSI ); - extern void via_scsi_clear(void); #ifdef RESET_BOOT @@ -351,7 +348,7 @@ static void mac_scsi_reset_boot(struct S printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." ); /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */ - mac_disable_irq(IRQ_MAC_SCSI); + disable_irq(IRQ_MAC_SCSI); /* get in phase */ NCR5380_write( TARGET_COMMAND_REG, @@ -369,7 +366,7 @@ static void mac_scsi_reset_boot(struct S barrier(); /* switch on SCSI IRQ again */ - mac_enable_irq(IRQ_MAC_SCSI); + enable_irq(IRQ_MAC_SCSI); printk(KERN_INFO " done\n" ); } diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index de35ffe..5d2cefb 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -524,7 +524,7 @@ mega_build_cmd(adapter_t *adapter, Scsi_ * filter the internal and ioctl commands */ if((cmd->cmnd[0] == MEGA_INTERNAL_CMD)) { - return cmd->buffer; + return cmd->request_buffer; } @@ -1828,7 +1828,7 @@ mega_build_sglist(adapter_t *adapter, sc scb->dma_type = MEGA_SGLIST; - if( sgcnt > adapter->sglen ) BUG(); + BUG_ON(sgcnt > adapter->sglen); *len = 0; @@ -4492,7 +4492,7 @@ mega_internal_command(adapter_t *adapter scmd->device = sdev; scmd->device->host = adapter->host; - scmd->buffer = (void *)scb; + scmd->request_buffer = (void *)scb; scmd->cmnd[0] = MEGA_INTERNAL_CMD; scb->state |= SCB_ACTIVE; diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index bec1424..b7caf60 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -714,7 +714,7 @@ megaraid_io_detach(adapter_t *adapter) * . Allocate memory required for all the commands * . Use internal library of FW routines, build up complete soft state */ -static int __init +static int __devinit megaraid_init_mbox(adapter_t *adapter) { struct pci_dev *pdev; diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 3972946..0c9516f 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -741,7 +741,6 @@ static int megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) { u32 frame_count; - unsigned long flags; struct megasas_cmd *cmd; struct megasas_instance *instance; @@ -776,9 +775,7 @@ megasas_queue_command(struct scsi_cmnd * /* * Issue the command to the FW */ - spin_lock_irqsave(&instance->instance_lock, flags); - instance->fw_outstanding++; - spin_unlock_irqrestore(&instance->instance_lock, flags); + atomic_inc(&instance->fw_outstanding); instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set); @@ -826,19 +823,20 @@ static int megasas_wait_for_outstanding( for (i = 0; i < wait_time; i++) { - if (!instance->fw_outstanding) + int outstanding = atomic_read(&instance->fw_outstanding); + + if (!outstanding) break; if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { printk(KERN_NOTICE "megasas: [%2d]waiting for %d " - "commands to complete\n", i, - instance->fw_outstanding); + "commands to complete\n",i,outstanding); } msleep(1000); } - if (instance->fw_outstanding) { + if (atomic_read(&instance->fw_outstanding)) { instance->hw_crit_error = 1; return FAILED; } @@ -1050,7 +1048,6 @@ megasas_complete_cmd(struct megasas_inst { int exception = 0; struct megasas_header *hdr = &cmd->frame->hdr; - unsigned long flags; if (cmd->scmd) { cmd->scmd->SCp.ptr = (char *)0; @@ -1082,9 +1079,7 @@ megasas_complete_cmd(struct megasas_inst if (exception) { - spin_lock_irqsave(&instance->instance_lock, flags); - instance->fw_outstanding--; - spin_unlock_irqrestore(&instance->instance_lock, flags); + atomic_dec(&instance->fw_outstanding); megasas_unmap_sgbuf(instance, cmd); cmd->scmd->scsi_done(cmd->scmd); @@ -1132,9 +1127,7 @@ megasas_complete_cmd(struct megasas_inst break; } - spin_lock_irqsave(&instance->instance_lock, flags); - instance->fw_outstanding--; - spin_unlock_irqrestore(&instance->instance_lock, flags); + atomic_dec(&instance->fw_outstanding); megasas_unmap_sgbuf(instance, cmd); cmd->scmd->scsi_done(cmd->scmd); @@ -2171,11 +2164,12 @@ megasas_probe_one(struct pci_dev *pdev, */ INIT_LIST_HEAD(&instance->cmd_pool); + atomic_set(&instance->fw_outstanding,0); + init_waitqueue_head(&instance->int_cmd_wait_q); init_waitqueue_head(&instance->abort_cmd_wait_q); spin_lock_init(&instance->cmd_pool_lock); - spin_lock_init(&instance->instance_lock); sema_init(&instance->aen_mutex, 1); sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 89639f0..927d6ff 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1077,9 +1077,8 @@ struct megasas_instance { struct pci_dev *pdev; u32 unique_id; - u32 fw_outstanding; + atomic_t fw_outstanding; u32 hw_crit_error; - spinlock_t instance_lock; struct megasas_instance_template *instancet; }; diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 22f9131..b28712d 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -529,7 +529,7 @@ static void __unmap_scsi_data(struct dev { switch(cmd->__data_mapped) { case 2: - dma_unmap_sg(dev, cmd->buffer, cmd->use_sg, + dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg, cmd->sc_data_direction); break; case 1: @@ -564,7 +564,7 @@ static int __map_scsi_sg_data(struct dev if (cmd->use_sg == 0) return 0; - use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg, + use_sg = dma_map_sg(dev, cmd->request_buffer, cmd->use_sg, cmd->sc_data_direction); cmd->__data_mapped = 2; cmd->__data_mapping = use_sg; @@ -5118,8 +5118,7 @@ static void ncr_ccb_skipped(struct ncb * cp->host_status &= ~HS_SKIPMASK; cp->start.schedule.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, select)); - list_del(&cp->link_ccbq); - list_add_tail(&cp->link_ccbq, &lp->skip_ccbq); + list_move_tail(&cp->link_ccbq, &lp->skip_ccbq); if (cp->queued) { --lp->queuedccbs; } @@ -7697,7 +7696,7 @@ static int ncr_scatter(struct ncb *np, s if (!use_sg) segment = ncr_scatter_no_sglist(np, cp, cmd); else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) { - struct scatterlist *scatter = (struct scatterlist *)cmd->buffer; + struct scatterlist *scatter = (struct scatterlist *)cmd->request_buffer; struct scr_tblmove *data; if (use_sg > MAX_SCATTER) { diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index 30ee0ef..5c55e15 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -1636,7 +1636,7 @@ static void nsp32_scsi_done(struct scsi_ if (SCpnt->use_sg) { pci_unmap_sg(data->Pci, - (struct scatterlist *)SCpnt->buffer, + (struct scatterlist *)SCpnt->request_buffer, SCpnt->use_sg, SCpnt->sc_data_direction); } else { pci_unmap_single(data->Pci, diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index e3bd4bc..4a2fed3 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -4724,7 +4724,7 @@ err_out: /* Flush the tape buffer before close */ -static int os_scsi_tape_flush(struct file * filp) +static int os_scsi_tape_flush(struct file * filp, fl_owner_t id) { int result = 0, result2; struct osst_tape * STp = filp->private_data; @@ -5492,7 +5492,7 @@ static int __init osst_setup (char *str) char *stp; stp = get_options(str, ARRAY_SIZE(ints), ints); - + if (ints[0] > 0) { for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++) *parms[i].val = ints[i + 1]; @@ -5507,7 +5507,7 @@ static int __init osst_setup (char *str) break; } } - if (i >= sizeof(parms) / sizeof(struct osst_dev_parm)) + if (i >= ARRAY_SIZE(parms)) printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n", stp); stp = strchr(stp, ','); diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index f09e94a..1bf96ed 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -156,7 +156,7 @@ static int default_irqs[] __initdata = static struct override { unsigned short io_port; int irq; -} overrides +} overrides #ifdef PAS16_OVERRIDE [] __initdata = PAS16_OVERRIDE; #else @@ -164,19 +164,19 @@ #else {0,IRQ_AUTO}}; #endif -#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) +#define NO_OVERRIDES ARRAY_SIZE(overrides) static struct base { unsigned short io_port; int noauto; -} bases[] __initdata = +} bases[] __initdata = { {PAS16_DEFAULT_BASE_1, 0}, {PAS16_DEFAULT_BASE_2, 0}, {PAS16_DEFAULT_BASE_3, 0}, {PAS16_DEFAULT_BASE_4, 0} }; -#define NO_BASES (sizeof (bases) / sizeof (struct base)) +#define NO_BASES ARRAY_SIZE(bases) static const unsigned short pas16_offset[ 8 ] = { diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 5cda16c..7ebe8e0 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -46,7 +46,7 @@ #include #include #define DRV_NAME "pdc_adma" -#define DRV_VERSION "0.03" +#define DRV_VERSION "0.04" /* macro to calculate base address for ATA regs */ #define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40)) @@ -152,6 +152,7 @@ static struct scsi_host_template adma_at .proc_name = DRV_NAME, .dma_boundary = ADMA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -167,6 +168,7 @@ static const struct ata_port_operations .qc_prep = adma_qc_prep, .qc_issue = adma_qc_issue, .eng_timeout = adma_eng_timeout, + .data_xfer = ata_mmio_data_xfer, .irq_handler = adma_intr, .irq_clear = adma_irq_clear, .port_start = adma_port_start, @@ -455,13 +457,13 @@ static inline unsigned int adma_intr_pkt continue; handled = 1; adma_enter_reg_mode(ap); - if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) + if (ap->flags & ATA_FLAG_DISABLED) continue; pp = ap->private_data; if (!pp || pp->state != adma_state_pkt) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { if ((status & (aPERR | aPSD | aUIRQ))) qc->err_mask |= AC_ERR_OTHER; else if (pp->pkt[0] != cDONE) @@ -480,13 +482,13 @@ static inline unsigned int adma_intr_mmi for (port_no = 0; port_no < host_set->n_ports; ++port_no) { struct ata_port *ap; ap = host_set->ports[port_no]; - if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) { + if (ap && (!(ap->flags & ATA_FLAG_DISABLED))) { struct ata_queued_cmd *qc; struct adma_port_priv *pp = ap->private_data; if (!pp || pp->state != adma_state_mmio) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { /* check main status, clearing INTRQ */ u8 status = ata_check_status(ap); diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c index 46624ab..83a6717 100644 --- a/drivers/scsi/pluto.c +++ b/drivers/scsi/pluto.c @@ -27,6 +27,9 @@ #include "pluto.h" #include +#define RQ_SCSI_BUSY 0xffff +#define RQ_SCSI_DONE 0xfffe + /* #define PLUTO_DEBUG */ #define pluto_printk printk ("PLUTO %s: ", fc->name); printk diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 108910f..d58ac5a 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -6,8 +6,6 @@ * (c) 1995,1996 Grant R. Guenther, grant@torque.net, * under the terms of the GNU General Public License. * - * Current Maintainer: David Campbell (Perth, Western Australia, GMT+0800) - * campbell@torque.net */ #include diff --git a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h index f6e1a15..7511df3 100644 --- a/drivers/scsi/ppa.h +++ b/drivers/scsi/ppa.h @@ -2,7 +2,7 @@ * the Iomega ZIP drive * * (c) 1996 Grant R. Guenther grant@torque.net - * David Campbell campbell@torque.net + * David Campbell * * All comments to David. */ diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 5a48e55..680f606 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -397,30 +397,6 @@ #include "ql12160_fw.h" /* ISP RISC cod #include "ql1280_fw.h" #include "ql1040_fw.h" - -/* - * Missing PCI ID's - */ -#ifndef PCI_DEVICE_ID_QLOGIC_ISP1080 -#define PCI_DEVICE_ID_QLOGIC_ISP1080 0x1080 -#endif -#ifndef PCI_DEVICE_ID_QLOGIC_ISP1240 -#define PCI_DEVICE_ID_QLOGIC_ISP1240 0x1240 -#endif -#ifndef PCI_DEVICE_ID_QLOGIC_ISP1280 -#define PCI_DEVICE_ID_QLOGIC_ISP1280 0x1280 -#endif -#ifndef PCI_DEVICE_ID_QLOGIC_ISP10160 -#define PCI_DEVICE_ID_QLOGIC_ISP10160 0x1016 -#endif -#ifndef PCI_DEVICE_ID_QLOGIC_ISP12160 -#define PCI_DEVICE_ID_QLOGIC_ISP12160 0x1216 -#endif - -#ifndef PCI_VENDOR_ID_AMI -#define PCI_VENDOR_ID_AMI 0x101e -#endif - #ifndef BITS_PER_LONG #error "BITS_PER_LONG not defined!" #endif @@ -4239,15 +4215,12 @@ qla1280_get_token(char *str) { char *sep; long ret = -1; - int i, len; - - len = sizeof(setup_token)/sizeof(struct setup_tokens); + int i; sep = strchr(str, ':'); if (sep) { - for (i = 0; i < len; i++){ - + for (i = 0; i < ARRAY_SIZE(setup_token); i++) { if (!strncmp(setup_token[i].token, str, (sep - str))) { ret = setup_token[i].val; break; diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index ff40906..8c865b9 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig @@ -24,48 +24,3 @@ config SCSI_QLA_FC Firmware images can be retrieved from: ftp://ftp.qlogic.com/outgoing/linux/firmware/ - - NOTE: The original method of building firmware-loader - modules has been deprecated as the firmware-images will - be removed from the kernel sources. - -config SCSI_QLA2XXX_EMBEDDED_FIRMWARE - bool " Use firmware-loader modules (DEPRECATED)" - depends on SCSI_QLA_FC - help - This option offers you the deprecated firmware-loader - modules that have been obsoleted by the usage of the - Firmware Loader interface in the qla2xxx driver. - -config SCSI_QLA21XX - tristate " Build QLogic ISP2100 firmware-module" - depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE - ---help--- - This driver supports the QLogic 21xx (ISP2100) host adapter family. - -config SCSI_QLA22XX - tristate " Build QLogic ISP2200 firmware-module" - depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE - ---help--- - This driver supports the QLogic 22xx (ISP2200) host adapter family. - -config SCSI_QLA2300 - tristate " Build QLogic ISP2300/ISP6312 firmware-module" - depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE - ---help--- - This driver supports the QLogic 2300 (ISP2300, ISP2312 and - ISP6312) host adapter family. - -config SCSI_QLA2322 - tristate " Build QLogic ISP2322/ISP6322 firmware-module" - depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE - ---help--- - This driver supports the QLogic 2322 (ISP2322 and ISP6322) host - adapter family. - -config SCSI_QLA24XX - tristate " Build QLogic ISP24xx firmware-module" - depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE - ---help--- - This driver supports the QLogic 24xx (ISP2422 and ISP2432) host - adapter family. diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index c8f670e..411663a 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile @@ -1,18 +1,4 @@ -EXTRA_CFLAGS += -DUNIQUE_FW_NAME - qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ - qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o + qla_dbg.o qla_sup.o qla_attr.o obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o - -qla2100-y := ql2100.o ql2100_fw.o -qla2200-y := ql2200.o ql2200_fw.o -qla2300-y := ql2300.o ql2300_fw.o -qla2322-y := ql2322.o ql2322_fw.o -qla2400-y := ql2400.o ql2400_fw.o - -obj-$(CONFIG_SCSI_QLA21XX) += qla2xxx.o qla2100.o -obj-$(CONFIG_SCSI_QLA22XX) += qla2xxx.o qla2200.o -obj-$(CONFIG_SCSI_QLA2300) += qla2xxx.o qla2300.o -obj-$(CONFIG_SCSI_QLA2322) += qla2xxx.o qla2322.o -obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o qla2400.o diff --git a/drivers/scsi/qla2xxx/ql2100.c b/drivers/scsi/qla2xxx/ql2100.c deleted file mode 100644 index f5db223..0000000 --- a/drivers/scsi/qla2xxx/ql2100.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (C) 2003 Christoph Hellwig. - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include -#include -#include - -#include "qla_def.h" - -static char qla_driver_name[] = "qla2100"; - -extern unsigned char fw2100tp_version[]; -extern unsigned char fw2100tp_version_str[]; -extern unsigned short fw2100tp_addr01; -extern unsigned short fw2100tp_code01[]; -extern unsigned short fw2100tp_length01; - -static struct qla_fw_info qla_fw_tbl[] = { - { - .addressing = FW_INFO_ADDR_NORMAL, - .fwcode = &fw2100tp_code01[0], - .fwlen = &fw2100tp_length01, - .fwstart = &fw2100tp_addr01, - }, - - { FW_INFO_ADDR_NOMORE, }, -}; - -static struct qla_board_info qla_board_tbl = { - .drv_name = qla_driver_name, - - .isp_name = "ISP2100", - .fw_info = qla_fw_tbl, -}; - -static struct pci_device_id qla2100_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2100, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl, - }, - - {0, 0}, -}; -MODULE_DEVICE_TABLE(pci, qla2100_pci_tbl); - -static int __devinit -qla2100_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - return qla2x00_probe_one(pdev, - (struct qla_board_info *)id->driver_data); -} - -static void __devexit -qla2100_remove_one(struct pci_dev *pdev) -{ - qla2x00_remove_one(pdev); -} - -static struct pci_driver qla2100_pci_driver = { - .name = "qla2100", - .id_table = qla2100_pci_tbl, - .probe = qla2100_probe_one, - .remove = __devexit_p(qla2100_remove_one), -}; - -static int __init -qla2100_init(void) -{ - return pci_module_init(&qla2100_pci_driver); -} - -static void __exit -qla2100_exit(void) -{ - pci_unregister_driver(&qla2100_pci_driver); -} - -module_init(qla2100_init); -module_exit(qla2100_exit); - -MODULE_AUTHOR("QLogic Corporation"); -MODULE_DESCRIPTION("QLogic ISP21xx FC-SCSI Host Bus Adapter driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2100_fw.c b/drivers/scsi/qla2xxx/ql2100_fw.c deleted file mode 100644 index 5600616..0000000 --- a/drivers/scsi/qla2xxx/ql2100_fw.c +++ /dev/null @@ -1,4848 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ - -/* - * Firmware Version 1.19.25 (13:12 Dec 10, 2003) - */ - -#ifdef UNIQUE_FW_NAME -unsigned short fw2100tp_version = 1*1024+19; -#else -unsigned short risc_code_version = 1*1024+19; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned char fw2100tp_version_str[] = {1,19,25}; -#else -unsigned char firmware_version[] = {1,19,25}; -#endif - -#ifdef UNIQUE_FW_NAME -#define fw2100tp_VERSION_STRING "1.19.25" -#else -#define FW_VERSION_STRING "1.19.25" -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2100tp_addr01 = 0x1000 ; -#else -unsigned short risc_code_addr01 = 0x1000 ; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2100tp_code01[] = { -#else -unsigned short risc_code01[] = { -#endif - 0x0078, 0x102d, 0x0000, 0x9601, 0x0000, 0x0001, 0x0013, 0x0019, - 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, - 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, - 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3231, 0x3030, 0x2046, 0x6972, - 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x312e, 0x3139, 0x2020, 0x2020, 0x2400, 0x2091, 0x2000, 0x20c1, - 0x0021, 0x2039, 0xffff, 0x2019, 0xaaaa, 0x2760, 0x2069, 0x7fff, - 0x20c1, 0x0020, 0x2c2c, 0x2d34, 0x2762, 0x236a, 0x2c24, 0x2d04, - 0x266a, 0x2562, 0xa406, 0x00c0, 0x1052, 0x20c1, 0x0021, 0x2c2c, - 0x2362, 0x2c04, 0x2562, 0xa306, 0x0040, 0x1052, 0x20c1, 0x0020, - 0x2039, 0x8fff, 0x20a1, 0xae00, 0x2708, 0x810d, 0x810d, 0x810d, - 0x810d, 0xa18c, 0x000f, 0x2001, 0x000a, 0xa112, 0xa00e, 0x21a8, - 0x41a4, 0x3400, 0x8211, 0x00c0, 0x105f, 0x2708, 0x3400, 0xa102, - 0x0040, 0x106f, 0x0048, 0x106f, 0x20a8, 0xa00e, 0x41a4, 0x20a1, - 0xa601, 0x2009, 0x0000, 0x20a9, 0x07ff, 0x41a4, 0x3400, 0x20c9, - 0xabff, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x25c7, - 0x2051, 0xa700, 0x2a70, 0x7762, 0xa786, 0x8fff, 0x0040, 0x1092, - 0x705f, 0xce00, 0x705b, 0xcdf1, 0x7067, 0x0200, 0x706b, 0x0200, - 0x0078, 0x109a, 0x705b, 0xbe01, 0x7067, 0x0100, 0x706b, 0x0100, - 0x705f, 0xbe00, 0x1078, 0x12df, 0x1078, 0x13ca, 0x1078, 0x1577, - 0x1078, 0x1ce9, 0x1078, 0x42ec, 0x1078, 0x76bf, 0x1078, 0x1355, - 0x1078, 0x2ac0, 0x1078, 0x4e93, 0x1078, 0x49a3, 0x1078, 0x594a, - 0x1078, 0x2263, 0x1078, 0x5c43, 0x1078, 0x5485, 0x1078, 0x2162, - 0x1078, 0x2240, 0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x10cf, - 0x7820, 0xa086, 0x0002, 0x00c0, 0x10cf, 0x7823, 0x4000, 0x0068, - 0x10c7, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, - 0x7003, 0x0000, 0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000, - 0xa08e, 0x0003, 0x00c0, 0x10ef, 0x1078, 0x365e, 0x1078, 0x2ae8, - 0x1078, 0x4ee3, 0x1078, 0x4b66, 0x2009, 0x0100, 0x2104, 0xa082, - 0x0002, 0x0048, 0x10f3, 0x1078, 0x5966, 0x0078, 0x10d6, 0x1079, - 0x10f7, 0x0078, 0x10dc, 0x1078, 0x7197, 0x0078, 0x10eb, 0x1101, - 0x1102, 0x11be, 0x10ff, 0x1246, 0x12dc, 0x12dd, 0x12de, 0x1078, - 0x1332, 0x007c, 0x127e, 0x0f7e, 0x2091, 0x8000, 0x7000, 0xa086, - 0x0001, 0x00c0, 0x1198, 0x1078, 0x3aec, 0x2079, 0x0100, 0x7844, - 0xa005, 0x00c0, 0x1198, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x1078, - 0x1adf, 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, - 0x8010, 0x73c4, 0x1078, 0x361b, 0x2001, 0xffff, 0x1078, 0x5ae6, - 0x723c, 0xc284, 0x723e, 0x2001, 0xa70c, 0x2014, 0xc2ac, 0x2202, - 0x1078, 0x6f9f, 0x2011, 0x0004, 0x1078, 0x8d2b, 0x1078, 0x489e, - 0x1078, 0x42d4, 0x0040, 0x1144, 0x7087, 0x0001, 0x70bf, 0x0000, - 0x1078, 0x3c9e, 0x0078, 0x1198, 0x1078, 0x4967, 0x0040, 0x114d, - 0x7a0c, 0xc2b4, 0x7a0e, 0x0078, 0x1159, 0x1078, 0x90b6, 0x70cc, - 0xd09c, 0x00c0, 0x1159, 0x7098, 0xa005, 0x0040, 0x1159, 0x1078, - 0x42b8, 0x70d7, 0x0000, 0x70d3, 0x0000, 0x72cc, 0x2079, 0xa752, - 0x7804, 0xd0ac, 0x0040, 0x1165, 0xc295, 0x72ce, 0xa296, 0x0004, - 0x0040, 0x1186, 0x2011, 0x0001, 0x1078, 0x8d2b, 0x7093, 0x0000, - 0x7097, 0xffff, 0x7003, 0x0002, 0x0f7f, 0x1078, 0x2677, 0x2011, - 0x0005, 0x1078, 0x70e0, 0x1078, 0x62d1, 0x0c7e, 0x2061, 0x0100, - 0x60e3, 0x0008, 0x0c7f, 0x127f, 0x0078, 0x119a, 0x7093, 0x0000, - 0x7097, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005, 0x1078, 0x70e0, - 0x1078, 0x62d1, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, - 0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082, 0x2009, 0x007e, - 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, 0x0029, 0x1078, - 0x73d0, 0x027f, 0x1078, 0xa501, 0x037f, 0x027f, 0x017f, 0x1078, - 0x298e, 0x8108, 0x00f0, 0x11a0, 0x0c7f, 0x706f, 0x0000, 0x7070, - 0xa084, 0x00ff, 0x7072, 0x709b, 0x0000, 0x007c, 0x127e, 0x2091, - 0x8000, 0x7000, 0xa086, 0x0002, 0x00c0, 0x1244, 0x7094, 0xa086, - 0xffff, 0x0040, 0x11d1, 0x1078, 0x2677, 0x1078, 0x62d1, 0x0078, - 0x1244, 0x70cc, 0xd09c, 0x0040, 0x11fd, 0xd084, 0x0040, 0x11fd, - 0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c, - 0x0040, 0x11fd, 0x70d0, 0xa086, 0xffff, 0x0040, 0x11f9, 0x1078, - 0x27f7, 0x1078, 0x62d1, 0x70cc, 0xd094, 0x00c0, 0x1244, 0x2011, - 0x0001, 0x2019, 0x0000, 0x1078, 0x282f, 0x1078, 0x62d1, 0x0078, - 0x1244, 0x70d4, 0xa005, 0x00c0, 0x1244, 0x7090, 0xa005, 0x00c0, - 0x1244, 0x1078, 0x4967, 0x00c0, 0x1244, 0x2001, 0xa753, 0x2004, - 0xd0ac, 0x0040, 0x1227, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009, - 0x0000, 0x017e, 0x1078, 0x45c4, 0x00c0, 0x121a, 0x6000, 0xd0ec, - 0x00c0, 0x1222, 0x017f, 0x8108, 0x00f0, 0x1211, 0x0c7f, 0x157f, - 0x0078, 0x1227, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x1244, 0x7003, - 0x0003, 0x7097, 0xffff, 0x2001, 0x0000, 0x1078, 0x24e8, 0x1078, - 0x3699, 0x2001, 0xa9b2, 0x2004, 0xa086, 0x0005, 0x00c0, 0x123c, - 0x2011, 0x0000, 0x1078, 0x70e0, 0x2011, 0x0000, 0x1078, 0x70ea, - 0x1078, 0x62d1, 0x1078, 0x639b, 0x127f, 0x007c, 0x017e, 0x0f7e, - 0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7, 0x1078, - 0x42a1, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0040, - 0x125b, 0x7827, 0x0040, 0xd19c, 0x0040, 0x1260, 0x7827, 0x0008, - 0x007e, 0x037e, 0x157e, 0xa006, 0x1078, 0x5ae6, 0x7900, 0xa18a, - 0x0003, 0x0050, 0x1289, 0x7954, 0xd1ac, 0x00c0, 0x1289, 0x2009, - 0x00f8, 0x1078, 0x42a1, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, - 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x1281, 0x7824, 0xd0ac, 0x00c0, - 0x12ca, 0x00f0, 0x1279, 0x2001, 0x0001, 0x1078, 0x24e8, 0x0078, - 0x12d5, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0050, 0x00e0, - 0x128f, 0x2091, 0x6000, 0x00f0, 0x128f, 0x7853, 0x0400, 0x782f, - 0x0000, 0x2009, 0x00f8, 0x1078, 0x42a1, 0x20a9, 0x000e, 0x0005, - 0x00f0, 0x129f, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, 0x0010, - 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040, 0x12b4, - 0x7824, 0xd0ac, 0x00c0, 0x12ca, 0x8319, 0x00c0, 0x12aa, 0x2009, - 0xa732, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0040, 0x12c4, - 0x200b, 0x0000, 0x1078, 0x2588, 0x2001, 0x0001, 0x1078, 0x24e8, - 0x0078, 0x12d3, 0x2001, 0xa732, 0x2003, 0x0000, 0x7828, 0xc09d, - 0x782a, 0x7827, 0x0048, 0x7853, 0x0400, 0x157f, 0x037f, 0x007f, - 0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c, 0x007c, 0x2a70, - 0x2061, 0xa9ad, 0x2063, 0x0001, 0x6007, 0x0013, 0x600b, 0x0019, - 0x600f, 0x0017, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, - 0x12f5, 0x7053, 0xffff, 0x0078, 0x12f7, 0x7053, 0x0000, 0x7057, - 0xffff, 0x706f, 0x0000, 0x7073, 0x0000, 0x1078, 0x90b6, 0x2061, - 0xa98d, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, - 0x0200, 0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, - 0x07d0, 0x2061, 0xa995, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, - 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, - 0x0001, 0x601f, 0x0000, 0x2061, 0xa9a5, 0x6003, 0x514c, 0x6007, - 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0xa726, 0x2003, - 0x0000, 0x007c, 0x2091, 0x8000, 0x0068, 0x1334, 0x007e, 0x017e, - 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x133a, 0x017f, 0x792e, - 0x007f, 0x782a, 0x007f, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, - 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2079, 0xa700, - 0x7803, 0x0005, 0x0078, 0x1352, 0x007c, 0x2071, 0xa700, 0x715c, - 0x712e, 0x2021, 0x0001, 0xa190, 0x002d, 0xa298, 0x002d, 0x0048, - 0x136b, 0x7060, 0xa302, 0x00c8, 0x136b, 0x220a, 0x2208, 0x2310, - 0x8420, 0x0078, 0x135d, 0x200b, 0x0000, 0x74aa, 0x74ae, 0x007c, - 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa700, 0x70ac, 0xa0ea, - 0x0010, 0x00c8, 0x137e, 0xa06e, 0x0078, 0x1388, 0x8001, 0x70ae, - 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, - 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa700, 0x127e, 0x2091, - 0x8000, 0x70ac, 0x8001, 0x00c8, 0x1398, 0xa06e, 0x0078, 0x13a1, - 0x70ae, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, - 0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, - 0x2071, 0xa700, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, - 0x70ae, 0x127f, 0x0e7f, 0x007c, 0x8dff, 0x0040, 0x13c0, 0x6804, - 0x6807, 0x0000, 0x007e, 0x1078, 0x13a4, 0x0d7f, 0x0078, 0x13b4, - 0x007c, 0x0e7e, 0x2071, 0xa700, 0x70ac, 0xa08a, 0x0010, 0xa00d, - 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa9d6, 0x7007, 0x0000, 0x701b, - 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, - 0x7012, 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x0e7e, 0x2270, - 0x700b, 0x0000, 0x2071, 0xa9d6, 0x7018, 0xa088, 0xa9df, 0x220a, - 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x00c0, 0x13f6, - 0x0f7e, 0x2079, 0x0010, 0x1078, 0x1408, 0x0f7f, 0x0e7f, 0x127f, - 0x007c, 0x0e7e, 0x2071, 0xa9d6, 0x7004, 0xa005, 0x00c0, 0x1406, - 0x0f7e, 0x2079, 0x0010, 0x1078, 0x1408, 0x0f7f, 0x0e7f, 0x007c, - 0x7000, 0x0079, 0x140b, 0x140f, 0x1479, 0x1496, 0x1496, 0x7018, - 0x711c, 0xa106, 0x00c0, 0x1417, 0x7007, 0x0000, 0x007c, 0x0d7e, - 0xa180, 0xa9df, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, - 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, - 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, - 0x0d7f, 0xd084, 0x0040, 0x1439, 0x7007, 0x0001, 0x1078, 0x143e, - 0x007c, 0x7007, 0x0002, 0x1078, 0x1454, 0x007c, 0x017e, 0x027e, - 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1449, 0x2110, - 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803, - 0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e, 0x137e, 0x147e, - 0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c, - 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1468, 0x2110, 0xa006, - 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x3300, - 0x7016, 0x7803, 0x0001, 0x157f, 0x147f, 0x137f, 0x027f, 0x017f, - 0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0xa7fa, 0x20a1, 0x0018, - 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000, - 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, - 0xa7f5, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x137e, 0x147e, - 0x157e, 0x2001, 0xa829, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, - 0x2001, 0xa82a, 0x20ac, 0x53a6, 0x2099, 0xa82b, 0x20a1, 0x0018, - 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000, - 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, - 0xa826, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x017e, 0x0e7e, - 0x2071, 0xa9d6, 0x0f7e, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, - 0xd1fc, 0x0040, 0x14d0, 0xa18c, 0x0700, 0x7004, 0x1079, 0x14d4, - 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x1408, 0x14dc, 0x1509, 0x1531, - 0x1564, 0x14da, 0x0078, 0x14da, 0xa18c, 0x0700, 0x00c0, 0x1502, - 0x137e, 0x147e, 0x157e, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, - 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x157f, 0x147f, - 0x137f, 0x700c, 0xa005, 0x0040, 0x151e, 0x1078, 0x143e, 0x007c, - 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, - 0x1408, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x0078, - 0x14fd, 0xa18c, 0x0700, 0x00c0, 0x1514, 0x700c, 0xa005, 0x0040, - 0x151e, 0x1078, 0x1454, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, - 0x0200, 0x7007, 0x0000, 0x1078, 0x1408, 0x007c, 0x0d7e, 0x7008, - 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, - 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x1408, - 0x007c, 0xa18c, 0x0700, 0x00c0, 0x155e, 0x137e, 0x147e, 0x157e, - 0x2001, 0xa7f8, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014, - 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xa7fa, 0x2004, - 0xd0bc, 0x0040, 0x1554, 0x2001, 0xa803, 0x2004, 0xa080, 0x000d, - 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x157f, 0x147f, 0x137f, 0x7007, - 0x0000, 0x1078, 0x4f8c, 0x1078, 0x1408, 0x007c, 0x2011, 0x8003, - 0x1078, 0x361b, 0x0078, 0x1562, 0xa18c, 0x0700, 0x00c0, 0x1571, - 0x2001, 0xa828, 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x1408, - 0x007c, 0x2011, 0x8004, 0x1078, 0x361b, 0x0078, 0x1575, 0x127e, - 0x2091, 0x2100, 0x2079, 0x0030, 0x2071, 0xa9e7, 0x7803, 0x0004, - 0x7003, 0x0000, 0x700f, 0xa9ed, 0x7013, 0xa9ed, 0x780f, 0x0076, - 0x7803, 0x0004, 0x127f, 0x007c, 0x6934, 0xa184, 0x0007, 0x0079, - 0x1591, 0x1599, 0x15df, 0x1599, 0x1599, 0x1599, 0x15c4, 0x15a8, - 0x159d, 0xa085, 0x0001, 0x0078, 0x15f9, 0x684c, 0xd0bc, 0x0040, - 0x1599, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x15e7, - 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1599, 0x684c, 0xd0bc, - 0x0040, 0x1599, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, - 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, - 0x6832, 0x6858, 0x0078, 0x15ef, 0xa18c, 0x00ff, 0xa186, 0x0015, - 0x00c0, 0x1599, 0x684c, 0xd0ac, 0x0040, 0x1599, 0x6804, 0x681a, - 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, - 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, 0x15ef, 0x684c, - 0xd0ac, 0x0040, 0x1599, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, - 0x000f, 0xa188, 0x206a, 0x210c, 0x6932, 0x2d08, 0x691a, 0x6826, - 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, - 0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, - 0x2004, 0x82ff, 0x0040, 0x161c, 0xa280, 0x0004, 0x0d7e, 0x206c, - 0x684c, 0xd0dc, 0x00c0, 0x1618, 0x1078, 0x158c, 0x0040, 0x1618, - 0x0d7f, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0078, 0x161c, - 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, 0x037e, 0x027e, - 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, 0xa005, 0x00c0, - 0x1630, 0x7206, 0x2001, 0x1651, 0x007e, 0x2260, 0x0078, 0x17e0, - 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, - 0xaa08, 0x0048, 0x163d, 0x2009, 0xa9ed, 0x710e, 0x7010, 0xa102, - 0xa082, 0x0009, 0x0040, 0x1648, 0xa080, 0x001b, 0x00c0, 0x164b, - 0x2009, 0x0138, 0x200a, 0x7000, 0xa005, 0x00c0, 0x1651, 0x1078, - 0x17c1, 0x127f, 0x007c, 0x127e, 0x027e, 0x037e, 0x0c7e, 0x007e, - 0x2091, 0x2100, 0x007f, 0x047f, 0x037f, 0x027f, 0x0d7e, 0x0c7e, - 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, 0xa005, 0x0040, 0x16dd, - 0x6808, 0xa005, 0x0040, 0x174a, 0x7000, 0xa005, 0x00c0, 0x1672, - 0x0078, 0x16d2, 0x700c, 0x7110, 0xa106, 0x00c0, 0x1753, 0x7004, - 0xa406, 0x00c0, 0x16d2, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, - 0x168f, 0x047e, 0x1078, 0x1913, 0x047f, 0x2460, 0x6010, 0xa080, - 0x0002, 0x2004, 0xa005, 0x0040, 0x174a, 0x0078, 0x166c, 0x2001, - 0x0207, 0x2004, 0xd09c, 0x00c0, 0x167b, 0x7804, 0xa084, 0x6000, - 0x0040, 0x16a0, 0xa086, 0x6000, 0x0040, 0x16a0, 0x0078, 0x167b, - 0x7100, 0xa186, 0x0002, 0x00c0, 0x16c0, 0x0e7e, 0x2b68, 0x6818, - 0x2060, 0x1078, 0x203f, 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, - 0x16b5, 0x7108, 0x720c, 0x0078, 0x16b7, 0x7110, 0x7214, 0x6810, - 0xa100, 0x6812, 0x6814, 0xa201, 0x6816, 0x0e7f, 0x0078, 0x16c4, - 0xa186, 0x0001, 0x00c0, 0x16cc, 0x7820, 0x6910, 0xa100, 0x6812, - 0x7824, 0x6914, 0xa101, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, - 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x1753, 0x2009, - 0x0048, 0x1078, 0x775c, 0x0078, 0x1753, 0x6808, 0xa005, 0x0040, - 0x174a, 0x7000, 0xa005, 0x00c0, 0x16e7, 0x0078, 0x174a, 0x700c, - 0x7110, 0xa106, 0x00c0, 0x16f0, 0x7004, 0xa406, 0x00c0, 0x174a, - 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, 0x1704, 0x047e, 0x1078, - 0x1913, 0x047f, 0x2460, 0x6010, 0xa080, 0x0002, 0x2004, 0xa005, - 0x0040, 0x174a, 0x0078, 0x16e1, 0x2001, 0x0207, 0x2004, 0xd09c, - 0x00c0, 0x16f0, 0x2001, 0x0005, 0x2004, 0xd08c, 0x00c0, 0x16f6, - 0x7804, 0xa084, 0x6000, 0x0040, 0x171b, 0xa086, 0x6000, 0x0040, - 0x171b, 0x0078, 0x16f0, 0x7007, 0x0000, 0xa016, 0x2218, 0x7000, - 0xa08e, 0x0001, 0x0040, 0x173c, 0xa08e, 0x0002, 0x00c0, 0x174a, - 0x0c7e, 0x0e7e, 0x6818, 0x2060, 0x1078, 0x203f, 0x2804, 0xac70, - 0x6034, 0xd09c, 0x00c0, 0x1738, 0x7308, 0x720c, 0x0078, 0x173a, - 0x7310, 0x7214, 0x0e7f, 0x0c7f, 0x7820, 0xa318, 0x7824, 0xa211, - 0x6810, 0xa300, 0x6812, 0x6814, 0xa201, 0x6816, 0x7803, 0x0004, - 0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x1753, 0x2009, - 0x0048, 0x1078, 0x775c, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e, - 0x0e7e, 0x027e, 0x037e, 0x047e, 0x057e, 0x2071, 0xa9e7, 0x7000, - 0xa086, 0x0000, 0x0040, 0x17ba, 0x7004, 0xac06, 0x00c0, 0x17ab, - 0x2079, 0x0030, 0x7000, 0xa086, 0x0003, 0x0040, 0x17ab, 0x7804, - 0xd0fc, 0x00c0, 0x17a7, 0x20e1, 0x6000, 0x2011, 0x0032, 0x2001, - 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x00c0, 0x176f, - 0x8211, 0x00c0, 0x1777, 0x7804, 0xd0fc, 0x00c0, 0x17a7, 0x1078, - 0x1b22, 0x027e, 0x057e, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, - 0x178d, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, - 0x0000, 0x057f, 0x027f, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, - 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0078, 0x17ab, 0x1078, - 0x1913, 0x0078, 0x175f, 0x157e, 0x20a9, 0x0009, 0x2009, 0xa9ed, - 0x2104, 0xac06, 0x00c0, 0x17b5, 0x200a, 0xa188, 0x0003, 0x00f0, - 0x17b0, 0x157f, 0x057f, 0x047f, 0x037f, 0x027f, 0x0e7f, 0x0f7f, - 0x007c, 0x700c, 0x7110, 0xa106, 0x00c0, 0x17c9, 0x7003, 0x0000, - 0x007c, 0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, - 0x8108, 0xa182, 0xaa08, 0x0048, 0x17d7, 0x2009, 0xa9ed, 0x7112, - 0x700c, 0xa106, 0x00c0, 0x17e0, 0x2001, 0x0138, 0x2003, 0x0008, - 0x8cff, 0x00c0, 0x17e7, 0x1078, 0x1b4d, 0x0078, 0x1854, 0x6010, - 0x2068, 0x2d58, 0x6828, 0xa406, 0x00c0, 0x17f2, 0x682c, 0xa306, - 0x0040, 0x182f, 0x601c, 0xa086, 0x0008, 0x0040, 0x182f, 0x6024, - 0xd0f4, 0x00c0, 0x181c, 0xd0d4, 0x0040, 0x1818, 0x6038, 0xa402, - 0x6034, 0xa303, 0x0040, 0x1806, 0x00c8, 0x1818, 0x643a, 0x6336, - 0x6c2a, 0x6b2e, 0x047e, 0x037e, 0x2400, 0x6c7c, 0xa402, 0x6812, - 0x2300, 0x6b80, 0xa303, 0x6816, 0x037f, 0x047f, 0x0078, 0x181c, - 0x1078, 0x9063, 0x0040, 0x17e3, 0x2001, 0xa774, 0x2004, 0xd0b4, - 0x00c0, 0x182b, 0x6018, 0x2004, 0xd0bc, 0x00c0, 0x182b, 0x6817, - 0x7fff, 0x6813, 0xffff, 0x1078, 0x208a, 0x00c0, 0x17e3, 0x0c7e, - 0x7004, 0x2060, 0x6024, 0xc0d4, 0x6026, 0x0c7f, 0x684c, 0xd0f4, - 0x0040, 0x1840, 0x6817, 0xffff, 0x6813, 0xffff, 0x0078, 0x17e3, - 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, - 0x000f, 0x2009, 0x0011, 0x1078, 0x1855, 0x0040, 0x1853, 0x2009, - 0x0001, 0x1078, 0x1855, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x18ec, - 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1877, 0xd0f4, 0x00c0, - 0x1887, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1867, 0x18ce, - 0x188e, 0x188e, 0x18ce, 0x18ce, 0x18c6, 0x18ce, 0x188e, 0x18ce, - 0x1894, 0x1894, 0x18ce, 0x18ce, 0x18ce, 0x18bd, 0x1894, 0xc0fc, - 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x0d7e, 0xd99c, 0x0040, - 0x18d1, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x18d1, 0xc0f4, - 0x6852, 0x6b6c, 0x6a70, 0x0d7e, 0x0078, 0x18d8, 0x6b08, 0x6a0c, - 0x6d00, 0x6c04, 0x0078, 0x18d1, 0x7b0c, 0xd3bc, 0x0040, 0x18b5, - 0x7004, 0x0e7e, 0x2070, 0x701c, 0x0e7f, 0xa086, 0x0008, 0x00c0, - 0x18b5, 0x7b08, 0xa39c, 0x0fff, 0x2d20, 0x0d7f, 0x0d7e, 0x6a14, - 0x82ff, 0x00c0, 0x18b0, 0x6810, 0xa302, 0x0048, 0x18b0, 0x6b10, - 0x2011, 0x0000, 0x2468, 0x0078, 0x18b7, 0x6b10, 0x6a14, 0x6d00, - 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x18d1, 0x0d7f, 0x0d7e, 0x6834, - 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x18ce, 0x0d7f, 0x1078, - 0x2026, 0x00c0, 0x1855, 0xa00e, 0x0078, 0x18ec, 0x0d7f, 0x1078, - 0x1332, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, - 0x7000, 0x8000, 0x7002, 0x0d7f, 0x6828, 0xa300, 0x682a, 0x682c, - 0xa201, 0x682e, 0x2300, 0x6b10, 0xa302, 0x6812, 0x2200, 0x6a14, - 0xa203, 0x6816, 0x1078, 0x2026, 0x007c, 0x1078, 0x1332, 0x1078, - 0x1c97, 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x7003, 0x0000, - 0x1078, 0x1af4, 0x1078, 0x8d16, 0x0040, 0x190c, 0x6808, 0x8001, - 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, - 0xffff, 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8a11, 0x0078, - 0x1adb, 0x1078, 0x1332, 0x127e, 0x2091, 0x2100, 0x007e, 0x017e, - 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, - 0x00c0, 0x18ef, 0xa184, 0x0003, 0xa086, 0x0003, 0x0040, 0x1911, - 0x7000, 0x0079, 0x192b, 0x1933, 0x1935, 0x1a34, 0x1ab2, 0x1ac9, - 0x1933, 0x1933, 0x1933, 0x1078, 0x1332, 0x8001, 0x7002, 0xa184, - 0x0880, 0x00c0, 0x194a, 0x8aff, 0x0040, 0x19d4, 0x2009, 0x0001, - 0x1078, 0x1855, 0x0040, 0x1adb, 0x2009, 0x0001, 0x1078, 0x1855, - 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x00c0, - 0x19b2, 0x027e, 0x037e, 0x017e, 0x7808, 0xd0ec, 0x00c0, 0x1962, - 0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7803, 0x0009, 0x7003, 0x0004, - 0x0078, 0x1964, 0x1078, 0x1bd7, 0x017f, 0xd194, 0x0040, 0x196b, - 0x8aff, 0x0040, 0x19a1, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, - 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x0c7e, 0x7004, 0x2060, - 0x6024, 0xd0f4, 0x00c0, 0x197e, 0x633a, 0x6236, 0x0c7f, 0x2400, - 0x6910, 0xa100, 0x6812, 0x2500, 0x6914, 0xa101, 0x6816, 0x037f, - 0x027f, 0x2600, 0x681e, 0x2700, 0x6822, 0x1078, 0x203f, 0x2a00, - 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, - 0x6808, 0x8001, 0x680a, 0x00c0, 0x19a7, 0x684c, 0xd0e4, 0x0040, - 0x19a7, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x7000, - 0xa086, 0x0004, 0x0040, 0x1adb, 0x7003, 0x0000, 0x1078, 0x17c1, - 0x0078, 0x1adb, 0x057e, 0x7d0c, 0xd5bc, 0x00c0, 0x19b9, 0x1078, - 0xa58e, 0x057f, 0x1078, 0x1af4, 0x0f7e, 0x7004, 0x2078, 0x1078, - 0x4963, 0x0040, 0x19c6, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, - 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, - 0x6980, 0x6916, 0x0078, 0x1adb, 0x7004, 0x0c7e, 0x2060, 0x6024, - 0x0c7f, 0xd0f4, 0x0040, 0x19e1, 0x6808, 0x8001, 0x680a, 0x0078, - 0x19f5, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x19f9, - 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x00c0, 0x19f5, 0x7004, - 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x1078, 0x17c1, 0x0078, - 0x1adb, 0x7814, 0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, - 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa192, 0x0841, 0x00c8, - 0x18ef, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, - 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x1078, 0x1b5e, - 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, - 0x0040, 0x1a1e, 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x0076, - 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, - 0x1078, 0x1b92, 0x0040, 0x19f5, 0x8001, 0x7002, 0xd194, 0x0040, - 0x1a46, 0x7804, 0xd0fc, 0x00c0, 0x191b, 0x8aff, 0x0040, 0x1adb, - 0x2009, 0x0001, 0x1078, 0x1855, 0x0078, 0x1adb, 0xa184, 0x0880, - 0x00c0, 0x1a53, 0x8aff, 0x0040, 0x1adb, 0x2009, 0x0001, 0x1078, - 0x1855, 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, - 0x00c0, 0x1a93, 0x027e, 0x037e, 0x7808, 0xd0ec, 0x00c0, 0x1a66, - 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1a68, 0x1078, 0x1bd7, - 0x6b28, 0x6a2c, 0x1078, 0x203f, 0x0d7e, 0x0f7e, 0x2d78, 0x2804, - 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1a83, 0x6808, 0x2008, 0xa31a, - 0x680c, 0xa213, 0x7810, 0xa100, 0x7812, 0x690c, 0x7814, 0xa101, - 0x7816, 0x0078, 0x1a8f, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213, - 0x7810, 0xa100, 0x7812, 0x6914, 0x7814, 0xa101, 0x7816, 0x0f7f, - 0x0d7f, 0x0078, 0x196d, 0x057e, 0x7d0c, 0x1078, 0xa58e, 0x057f, - 0x1078, 0x1af4, 0x0f7e, 0x7004, 0x2078, 0x1078, 0x4963, 0x0040, - 0x1aa4, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, 0xffff, 0x682f, - 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, - 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, - 0x0040, 0x1ac5, 0x6808, 0x8001, 0x680a, 0x00c0, 0x1ac5, 0x7004, - 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x1078, 0x17c1, 0x0078, - 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6010, - 0xa005, 0x0040, 0x1ac5, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, - 0x6b2c, 0x1078, 0x17e0, 0x017f, 0x007f, 0x127f, 0x007c, 0x127e, - 0x2091, 0x2100, 0x7000, 0xa086, 0x0003, 0x00c0, 0x1af2, 0x700c, - 0x7110, 0xa106, 0x0040, 0x1af2, 0x20e1, 0x9028, 0x700f, 0xa9ed, - 0x7013, 0xa9ed, 0x127f, 0x007c, 0x0c7e, 0x1078, 0x1b22, 0x20e1, - 0x9028, 0x700c, 0x7110, 0xa106, 0x0040, 0x1b19, 0x2104, 0xa005, - 0x0040, 0x1b08, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, - 0xa188, 0x0003, 0xa182, 0xaa08, 0x0048, 0x1b10, 0x2009, 0xa9ed, - 0x7112, 0x700c, 0xa106, 0x00c0, 0x1af9, 0x2011, 0x0008, 0x0078, - 0x1af9, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, 0x0138, 0x2202, - 0x0c7f, 0x007c, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2021, - 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x00c0, 0x1b3f, 0x2001, - 0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0, 0x1b3f, 0x2001, 0x0111, - 0x201c, 0x83ff, 0x00c0, 0x1b3f, 0x8421, 0x00c0, 0x1b29, 0x007c, - 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x00c0, 0x1b4c, - 0x8109, 0x00c0, 0x1b44, 0x007c, 0x007c, 0x1078, 0x1b40, 0x0040, - 0x1b55, 0x780c, 0xd0a4, 0x0040, 0x1b5b, 0x1078, 0x1af4, 0xa085, - 0x0001, 0x0078, 0x1b5d, 0x1078, 0x1b92, 0x007c, 0x0e7e, 0x2071, - 0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1b22, 0x2019, - 0x5000, 0x8319, 0x0040, 0x1b7c, 0x2001, 0xaa08, 0x2004, 0xa086, - 0x0000, 0x0040, 0x1b7c, 0x2001, 0x0021, 0xd0fc, 0x0040, 0x1b69, - 0x1078, 0x1eaa, 0x0078, 0x1b67, 0x20e1, 0x7000, 0x7324, 0x7420, - 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, - 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, - 0x0e7f, 0x007c, 0x027e, 0x2001, 0x015d, 0x2001, 0x0000, 0x7908, - 0xa18c, 0x0fff, 0xa182, 0x0ffd, 0x0048, 0x1ba0, 0x2009, 0x0000, - 0xa190, 0x0007, 0xa294, 0x1ff8, 0x8214, 0x8214, 0x8214, 0x2001, - 0x020a, 0x82ff, 0x0040, 0x1bb5, 0x20e1, 0x6000, 0x200c, 0x200c, - 0x200c, 0x200c, 0x8211, 0x00c0, 0x1bae, 0x20e1, 0x7000, 0x200c, - 0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, 0x2001, 0x0208, 0x200c, - 0x2001, 0x0209, 0x2004, 0xa106, 0x0040, 0x1bd4, 0x1078, 0x1b40, - 0x0040, 0x1bd2, 0x7908, 0xd1ec, 0x00c0, 0x1bd4, 0x790c, 0xd1a4, - 0x0040, 0x1b97, 0x1078, 0x1af4, 0xa006, 0x027f, 0x007c, 0x7c20, - 0x7d24, 0x7e30, 0x7f34, 0x700c, 0x7110, 0xa106, 0x0040, 0x1c69, - 0x7004, 0x017e, 0x210c, 0xa106, 0x017f, 0x0040, 0x1c69, 0x0d7e, - 0x0c7e, 0x216c, 0x2d00, 0xa005, 0x0040, 0x1c67, 0x681c, 0xa086, - 0x0008, 0x0040, 0x1c67, 0x6824, 0xd0d4, 0x00c0, 0x1c67, 0x6810, - 0x2068, 0x6850, 0xd0fc, 0x0040, 0x1c29, 0x8108, 0x2104, 0x6b2c, - 0xa306, 0x00c0, 0x1c67, 0x8108, 0x2104, 0x6a28, 0xa206, 0x00c0, - 0x1c67, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x6870, - 0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060, 0x6034, - 0xd09c, 0x0040, 0x1c24, 0x6830, 0x2004, 0xac68, 0x6808, 0x783a, - 0x680c, 0x783e, 0x0078, 0x1c65, 0xa006, 0x783a, 0x783e, 0x0078, - 0x1c65, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c67, 0x6b2c, 0xa306, - 0x00c0, 0x1c67, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c67, 0x6a28, - 0xa206, 0x00c0, 0x1c67, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2004, - 0x6918, 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, 0x00c0, 0x1c57, - 0x6008, 0x7822, 0x686e, 0x600c, 0x7826, 0x6872, 0x6000, 0x7832, - 0x6004, 0x7836, 0xa006, 0x783a, 0x783e, 0x0078, 0x1c65, 0x6010, - 0x7822, 0x686e, 0x6014, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004, - 0x7836, 0x6008, 0x783a, 0x600c, 0x783e, 0x7803, 0x0011, 0x0c7f, - 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0x027e, 0x2071, 0xa9e7, - 0x2079, 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x0040, - 0x1c92, 0x8211, 0x0040, 0x1c90, 0x2001, 0x0005, 0x2004, 0xd08c, - 0x0040, 0x1c79, 0x7904, 0xa18c, 0x0780, 0x017e, 0x1078, 0x1913, - 0x017f, 0x81ff, 0x00c0, 0x1c90, 0x2011, 0x0050, 0x0078, 0x1c74, - 0xa085, 0x0001, 0x027f, 0x017f, 0x0e7f, 0x0f7f, 0x007c, 0x7803, - 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac, 0x0040, 0x1ce8, 0x8109, - 0x00c0, 0x1c9b, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0003, 0x1048, - 0x1332, 0x1078, 0x1fca, 0x0e7e, 0x0f7e, 0x2071, 0xa9d6, 0x2079, - 0x0010, 0x7004, 0xa086, 0x0000, 0x0040, 0x1ce0, 0x7800, 0x007e, - 0x7820, 0x007e, 0x7830, 0x007e, 0x7834, 0x007e, 0x7838, 0x007e, - 0x783c, 0x007e, 0x7803, 0x0004, 0x7823, 0x0000, 0x0005, 0x0005, - 0x2079, 0x0030, 0x7804, 0xd0ac, 0x10c0, 0x1332, 0x2079, 0x0010, - 0x007f, 0x783e, 0x007f, 0x783a, 0x007f, 0x7836, 0x007f, 0x7832, - 0x007f, 0x7822, 0x007f, 0x7802, 0x0f7f, 0x0e7f, 0x0078, 0x1ce6, - 0x0f7f, 0x0e7f, 0x7804, 0xd0ac, 0x10c0, 0x1332, 0x1078, 0x639b, - 0x007c, 0x0e7e, 0x2071, 0xaa08, 0x7003, 0x0000, 0x0e7f, 0x007c, - 0x0d7e, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1d6b, - 0x6934, 0xa184, 0x0007, 0x0079, 0x1cfd, 0x1d05, 0x1d56, 0x1d05, - 0x1d05, 0x1d05, 0x1d3b, 0x1d18, 0x1d07, 0x1078, 0x1332, 0x684c, - 0xd0b4, 0x0040, 0x1e79, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, - 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1d5e, - 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1d05, 0x684c, - 0xd0b4, 0x0040, 0x1e79, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, - 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, - 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, - 0x6958, 0x0078, 0x1d67, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, - 0x1d6b, 0x684c, 0xd0b4, 0x0040, 0x1e79, 0x6804, 0x681a, 0xa080, - 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, - 0x6958, 0xa006, 0x682e, 0x682a, 0x0078, 0x1d67, 0x684c, 0xd0b4, - 0x0040, 0x18ed, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, - 0x6834, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, 0x6926, - 0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c, 0x0f7e, 0x2079, 0x0020, - 0x7804, 0xd0fc, 0x10c0, 0x1eaa, 0x0e7e, 0x0d7e, 0x2071, 0xaa08, - 0x7000, 0xa005, 0x00c0, 0x1df0, 0x0c7e, 0x7206, 0xa280, 0x0004, - 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x0d7e, 0x2068, - 0x686c, 0x7812, 0x6890, 0x0f7e, 0x20e1, 0x9040, 0x2079, 0x0200, - 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x0f7f, 0x0d7f, 0x2b68, - 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, - 0x000f, 0x6908, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0007, 0x0040, - 0x1db2, 0xa184, 0x0007, 0x0040, 0x1db2, 0x017e, 0x2009, 0x0008, - 0xa102, 0x017f, 0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081, - 0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, - 0x6814, 0xa106, 0x00c0, 0x1dc9, 0x6928, 0x6810, 0xa106, 0x0040, - 0x1dd6, 0x037e, 0x047e, 0x6b14, 0x6c10, 0x1078, 0x208a, 0x047f, - 0x037f, 0x0040, 0x1dd6, 0x0c7f, 0x0078, 0x1df0, 0x8aff, 0x00c0, - 0x1dde, 0x0c7f, 0xa085, 0x0001, 0x0078, 0x1df0, 0x127e, 0x2091, - 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x1078, 0x1df4, 0x0040, - 0x1ded, 0x2009, 0x0001, 0x1078, 0x1df4, 0x127f, 0x0c7f, 0xa006, - 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e, - 0x037e, 0x027e, 0x8aff, 0x0040, 0x1e72, 0x700c, 0x7214, 0xa23a, - 0x7010, 0x7218, 0xa203, 0x0048, 0x1e71, 0xa705, 0x0040, 0x1e71, - 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1e24, 0x0d7e, 0x2804, - 0xac68, 0x2900, 0x0079, 0x1e14, 0x1e53, 0x1e34, 0x1e34, 0x1e53, - 0x1e53, 0x1e4b, 0x1e53, 0x1e34, 0x1e53, 0x1e3a, 0x1e3a, 0x1e53, - 0x1e53, 0x1e53, 0x1e42, 0x1e3a, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, - 0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1e57, 0x0d7e, 0x2804, 0xac68, - 0x6f08, 0x6e0c, 0x0078, 0x1e56, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, - 0x0078, 0x1e56, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, - 0x0078, 0x1e56, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x001e, 0x00c0, 0x1e53, 0x0d7f, 0x1078, 0x2026, 0x00c0, 0x1dfa, - 0xa00e, 0x0078, 0x1e72, 0x0d7f, 0x1078, 0x1332, 0x0d7f, 0x7b22, - 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, - 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, - 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x1078, 0x2026, 0x0078, - 0x1e72, 0xa006, 0x027f, 0x037f, 0x047f, 0x057f, 0x067f, 0x077f, - 0x007c, 0x1078, 0x1332, 0x027e, 0x2001, 0x0105, 0x2003, 0x0010, - 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, - 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x1e92, 0x6850, - 0xc0bd, 0x6852, 0x0d7f, 0x0c7e, 0x1078, 0x8a11, 0x0c7f, 0x2001, - 0xa9c0, 0x2004, 0xac06, 0x00c0, 0x1ea7, 0x20e1, 0x9040, 0x1078, - 0x738a, 0x2011, 0x0000, 0x1078, 0x70ea, 0x1078, 0x639b, 0x027f, - 0x0078, 0x1f76, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e, - 0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020, 0x2071, 0xaa08, 0x2b68, - 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0, - 0x1e7b, 0x7000, 0x0079, 0x1ec4, 0x1f76, 0x1ec8, 0x1f43, 0x1f74, - 0x8001, 0x7002, 0xd19c, 0x00c0, 0x1edc, 0x8aff, 0x0040, 0x1efb, - 0x2009, 0x0001, 0x1078, 0x1df4, 0x0040, 0x1f76, 0x2009, 0x0001, - 0x1078, 0x1df4, 0x0078, 0x1f76, 0x7803, 0x0004, 0xd194, 0x0040, - 0x1eec, 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1ef1, 0x684c, - 0xc0f5, 0x684e, 0x0078, 0x1ef1, 0x1078, 0x203f, 0x6850, 0xc0fd, - 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, - 0x0000, 0x0078, 0x1f76, 0x711c, 0x81ff, 0x0040, 0x1f11, 0x7918, - 0x7922, 0x7827, 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002, - 0x700c, 0xa100, 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078, - 0x1f76, 0x0f7e, 0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079, - 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x037e, - 0x2019, 0x1000, 0x8319, 0x1040, 0x1332, 0x7820, 0xd0bc, 0x00c0, - 0x1f22, 0x037f, 0x79c8, 0x007f, 0xa102, 0x017f, 0x007e, 0x017e, - 0x79c4, 0x007f, 0xa103, 0x78c6, 0x007f, 0x78ca, 0xa284, 0x0004, - 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f, 0x7803, 0x0008, 0x7003, - 0x0000, 0x0078, 0x1f76, 0x8001, 0x7002, 0xd194, 0x0040, 0x1f58, - 0x7804, 0xd0fc, 0x00c0, 0x1eba, 0xd19c, 0x00c0, 0x1f72, 0x8aff, - 0x0040, 0x1f76, 0x2009, 0x0001, 0x1078, 0x1df4, 0x0078, 0x1f76, - 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078, 0x203f, 0x0d7e, 0x2804, - 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1f6b, 0x6808, 0xa31a, 0x680c, - 0xa213, 0x0078, 0x1f6f, 0x6810, 0xa31a, 0x6814, 0xa213, 0x0d7f, - 0x0078, 0x1eec, 0x0078, 0x1eec, 0x1078, 0x1332, 0x0c7f, 0x0d7f, - 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f, 0x007c, 0x0f7e, 0x0e7e, - 0x2071, 0xaa08, 0x7000, 0xa086, 0x0000, 0x0040, 0x1fc7, 0x2079, - 0x0020, 0x017e, 0x2009, 0x0207, 0x210c, 0xd194, 0x0040, 0x1fa4, - 0x2009, 0x020c, 0x210c, 0xa184, 0x0003, 0x0040, 0x1fa4, 0x1078, - 0xa5e2, 0x2001, 0x0133, 0x2004, 0xa005, 0x1040, 0x1332, 0x20e1, - 0x9040, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, - 0x0203, 0x210c, 0xa106, 0x00c0, 0x1faf, 0x20e1, 0x9040, 0x7804, - 0xd0fc, 0x0040, 0x1f8a, 0x1078, 0x1eaa, 0x7000, 0xa086, 0x0000, - 0x00c0, 0x1f8a, 0x017f, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, - 0x1fbd, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f, - 0x0f7f, 0x007c, 0x027e, 0x0c7e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, - 0xaa08, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0040, 0x2003, - 0x7004, 0x2060, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x1fed, - 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x00c0, 0x1fed, - 0x6808, 0x7a18, 0xa206, 0x0040, 0x2009, 0x2001, 0x0105, 0x2003, - 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, - 0x2060, 0x1078, 0x8a11, 0x20e1, 0x9040, 0x1078, 0x738a, 0x2011, - 0x0000, 0x1078, 0x70ea, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x027f, - 0x007c, 0x6810, 0x6a14, 0xa205, 0x00c0, 0x1fed, 0x684c, 0xc0dc, - 0x684e, 0x2c10, 0x1078, 0x1cf0, 0x2001, 0x0105, 0x2003, 0x0010, - 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x2069, 0xa9b1, - 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x2003, 0x8840, 0x2804, - 0xa005, 0x00c0, 0x203a, 0x6004, 0xa005, 0x0040, 0x203c, 0x681a, - 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x206a, 0x2044, 0x88ff, - 0x1040, 0x1332, 0x8a51, 0x007c, 0x2051, 0x0000, 0x007c, 0x8a50, - 0x8841, 0x2804, 0xa005, 0x00c0, 0x2059, 0x2c00, 0xad06, 0x0040, - 0x204e, 0x6000, 0xa005, 0x00c0, 0x204e, 0x2d00, 0x2060, 0x681a, - 0x6034, 0xa084, 0x000f, 0xa080, 0x207a, 0x2044, 0x88ff, 0x1040, - 0x1332, 0x007c, 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, - 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, - 0x0000, 0x0000, 0x0000, 0x205f, 0x205b, 0x0000, 0x0000, 0x2069, - 0x0000, 0x205f, 0x0000, 0x2066, 0x2063, 0x0000, 0x0000, 0x0000, - 0x2069, 0x2066, 0x0000, 0x2061, 0x2061, 0x0000, 0x0000, 0x2069, - 0x0000, 0x2061, 0x0000, 0x2067, 0x2067, 0x0000, 0x0000, 0x0000, - 0x2069, 0x2067, 0x0a7e, 0x097e, 0x087e, 0x6b2e, 0x6c2a, 0x6858, - 0xa055, 0x0040, 0x212d, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0, - 0x206a, 0xa986, 0x0007, 0x0040, 0x20a5, 0xa986, 0x000e, 0x0040, - 0x20a5, 0xa986, 0x000f, 0x00c0, 0x20a9, 0x605c, 0xa422, 0x6060, - 0xa31b, 0x2804, 0xa045, 0x00c0, 0x20b7, 0x0050, 0x20b1, 0x0078, - 0x212d, 0x6004, 0xa065, 0x0040, 0x212d, 0x0078, 0x2094, 0x2804, - 0xa005, 0x0040, 0x20d5, 0xac68, 0xd99c, 0x00c0, 0x20c5, 0x6808, - 0xa422, 0x680c, 0xa31b, 0x0078, 0x20c9, 0x6810, 0xa422, 0x6814, - 0xa31b, 0x0048, 0x20f4, 0x2300, 0xa405, 0x0040, 0x20db, 0x8a51, - 0x0040, 0x212d, 0x8840, 0x0078, 0x20b7, 0x6004, 0xa065, 0x0040, - 0x212d, 0x0078, 0x2094, 0x8a51, 0x0040, 0x212d, 0x8840, 0x2804, - 0xa005, 0x00c0, 0x20ee, 0x6004, 0xa065, 0x0040, 0x212d, 0x6034, - 0xa0cc, 0x000f, 0xa9c0, 0x206a, 0x2804, 0x2040, 0x2b68, 0x6850, - 0xc0fc, 0x6852, 0x0078, 0x2121, 0x8422, 0x8420, 0x831a, 0xa399, - 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f, 0xd99c, 0x00c0, - 0x210f, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x1048, - 0x1332, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078, 0x211b, 0x6910, - 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048, 0x1332, 0x6800, - 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd, - 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, 0x007f, - 0x007f, 0x007f, 0xa006, 0x0078, 0x2132, 0x087f, 0x097f, 0x0a7f, - 0xa085, 0x0001, 0x007c, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007, - 0x0079, 0x213a, 0x2142, 0x2143, 0x2146, 0x2149, 0x214e, 0x2151, - 0x2156, 0x215b, 0x007c, 0x1078, 0x1eaa, 0x007c, 0x1078, 0x1913, - 0x007c, 0x1078, 0x1913, 0x1078, 0x1eaa, 0x007c, 0x1078, 0x14be, - 0x007c, 0x1078, 0x1eaa, 0x1078, 0x14be, 0x007c, 0x1078, 0x1913, - 0x1078, 0x14be, 0x007c, 0x1078, 0x1913, 0x1078, 0x1eaa, 0x1078, - 0x14be, 0x007c, 0x127e, 0x2091, 0x2300, 0x2079, 0x0200, 0x2071, - 0xac80, 0x2069, 0xa700, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, - 0x1078, 0x251f, 0x781b, 0x0002, 0x20e1, 0x8700, 0x127f, 0x007c, - 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007, 0x0079, 0x2180, - 0x21a4, 0x2188, 0x218c, 0x2190, 0x2196, 0x219a, 0x219e, 0x21a2, - 0x1078, 0x548e, 0x0078, 0x21a4, 0x1078, 0x54da, 0x0078, 0x21a4, - 0x1078, 0x548e, 0x1078, 0x54da, 0x0078, 0x21a4, 0x1078, 0x21a6, - 0x0078, 0x21a4, 0x1078, 0x21a6, 0x0078, 0x21a4, 0x1078, 0x21a6, - 0x0078, 0x21a4, 0x1078, 0x21a6, 0x127f, 0x007c, 0x007e, 0x017e, - 0x027e, 0x1078, 0xa5e2, 0x7930, 0xa184, 0x0003, 0x0040, 0x21c9, - 0x2001, 0xa9c0, 0x2004, 0xa005, 0x0040, 0x21c5, 0x2001, 0x0133, - 0x2004, 0xa005, 0x1040, 0x1332, 0x0c7e, 0x2001, 0xa9c0, 0x2064, - 0x1078, 0x8a11, 0x0c7f, 0x0078, 0x21f2, 0x20e1, 0x9040, 0x0078, - 0x21f2, 0xa184, 0x0030, 0x0040, 0x21da, 0x6a00, 0xa286, 0x0003, - 0x00c0, 0x21d4, 0x0078, 0x21d6, 0x1078, 0x4224, 0x20e1, 0x9010, - 0x0078, 0x21f2, 0xa184, 0x00c0, 0x0040, 0x21ec, 0x0e7e, 0x037e, - 0x047e, 0x057e, 0x2071, 0xa9e7, 0x1078, 0x1af4, 0x057f, 0x047f, - 0x037f, 0x0e7f, 0x0078, 0x21f2, 0xa184, 0x0300, 0x0040, 0x21f2, - 0x20e1, 0x9020, 0x7932, 0x027f, 0x017f, 0x007f, 0x007c, 0x017e, - 0x0e7e, 0x0f7e, 0x2071, 0xa700, 0x7128, 0x2001, 0xa990, 0x2102, - 0x2001, 0xa998, 0x2102, 0xa182, 0x0211, 0x00c8, 0x220b, 0x2009, - 0x0008, 0x0078, 0x2235, 0xa182, 0x0259, 0x00c8, 0x2213, 0x2009, - 0x0007, 0x0078, 0x2235, 0xa182, 0x02c1, 0x00c8, 0x221b, 0x2009, - 0x0006, 0x0078, 0x2235, 0xa182, 0x0349, 0x00c8, 0x2223, 0x2009, - 0x0005, 0x0078, 0x2235, 0xa182, 0x0421, 0x00c8, 0x222b, 0x2009, - 0x0004, 0x0078, 0x2235, 0xa182, 0x0581, 0x00c8, 0x2233, 0x2009, - 0x0003, 0x0078, 0x2235, 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, - 0x7817, 0x0004, 0x1078, 0x251f, 0x0f7f, 0x0e7f, 0x017f, 0x007c, - 0x127e, 0x2091, 0x2200, 0x2061, 0x0100, 0x2071, 0xa700, 0x6024, - 0x6026, 0x6053, 0x0030, 0x6033, 0x00ef, 0x60e7, 0x0000, 0x60eb, - 0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, - 0x0080, 0x602f, 0x0000, 0x6007, 0x0eaf, 0x600f, 0x00ff, 0x602b, - 0x002f, 0x127f, 0x007c, 0x2001, 0xa730, 0x2003, 0x0000, 0x2001, - 0xa72f, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x007e, - 0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0, 0x227b, 0xa184, - 0x0007, 0x0079, 0x2281, 0xa195, 0x0004, 0xa284, 0x0007, 0x0079, - 0x2281, 0x22ad, 0x2289, 0x228d, 0x2291, 0x2297, 0x229b, 0x22a1, - 0x22a7, 0x1078, 0x5c56, 0x0078, 0x22ad, 0x1078, 0x5d45, 0x0078, - 0x22ad, 0x1078, 0x5d45, 0x1078, 0x5c56, 0x0078, 0x22ad, 0x1078, - 0x22b2, 0x0078, 0x22ad, 0x1078, 0x5c56, 0x1078, 0x22b2, 0x0078, - 0x22ad, 0x1078, 0x5d45, 0x1078, 0x22b2, 0x0078, 0x22ad, 0x1078, - 0x5d45, 0x1078, 0x5c56, 0x1078, 0x22b2, 0x027f, 0x017f, 0x007f, - 0x127f, 0x007c, 0x6124, 0xd1ac, 0x0040, 0x23ac, 0x017e, 0x047e, - 0x0c7e, 0x644c, 0xa486, 0xf0f0, 0x00c0, 0x22c5, 0x2061, 0x0100, - 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74c6, 0xa48c, 0xff00, - 0x7034, 0xd084, 0x0040, 0x22dd, 0xa186, 0xf800, 0x00c0, 0x22dd, - 0x703c, 0xd084, 0x00c0, 0x22dd, 0xc085, 0x703e, 0x037e, 0x2418, - 0x2011, 0x8016, 0x1078, 0x361b, 0x037f, 0xa196, 0xff00, 0x0040, - 0x231f, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040, 0x231f, - 0x7130, 0xd184, 0x00c0, 0x231f, 0x2011, 0xa753, 0x2214, 0xd2ec, - 0x0040, 0x22fa, 0xc18d, 0x7132, 0x2011, 0xa753, 0x2214, 0xd2ac, - 0x00c0, 0x231f, 0x6240, 0xa294, 0x0010, 0x0040, 0x2306, 0x6248, - 0xa294, 0xff00, 0xa296, 0xff00, 0x0040, 0x231f, 0x7030, 0xd08c, - 0x0040, 0x2371, 0x7034, 0xd08c, 0x00c0, 0x2316, 0x2001, 0xa70c, - 0x200c, 0xd1ac, 0x00c0, 0x2371, 0xc1ad, 0x2102, 0x037e, 0x73c4, - 0x2011, 0x8013, 0x1078, 0x361b, 0x037f, 0x0078, 0x2371, 0x7034, - 0xd08c, 0x00c0, 0x232b, 0x2001, 0xa70c, 0x200c, 0xd1ac, 0x00c0, - 0x2371, 0xc1ad, 0x2102, 0x037e, 0x73c4, 0x2011, 0x8013, 0x1078, - 0x361b, 0x037f, 0x7130, 0xc185, 0x7132, 0x2011, 0xa753, 0x220c, - 0xd1a4, 0x0040, 0x2355, 0x017e, 0x2009, 0x0001, 0x2011, 0x0100, - 0x1078, 0x5bf1, 0x2019, 0x000e, 0x1078, 0xa1a5, 0xa484, 0x00ff, - 0xa080, 0x29c0, 0x200c, 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, - 0x2009, 0x000e, 0x1078, 0xa22d, 0x017f, 0xd1ac, 0x00c0, 0x2362, - 0x017e, 0x2009, 0x0000, 0x2019, 0x0004, 0x1078, 0x284f, 0x017f, - 0x0078, 0x2371, 0x157e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x1078, - 0x45c4, 0x00c0, 0x236d, 0x1078, 0x42f8, 0x8108, 0x00f0, 0x2367, - 0x157f, 0x0c7f, 0x047f, 0x0f7e, 0x2079, 0xa9c4, 0x783c, 0xa086, - 0x0000, 0x0040, 0x2383, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, - 0x0140, 0x7803, 0x0000, 0x0f7f, 0x2011, 0x0003, 0x1078, 0x70e0, - 0x2011, 0x0002, 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, 0x2019, - 0x0000, 0x1078, 0x7058, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001, - 0xa700, 0x2014, 0xa296, 0x0004, 0x00c0, 0x23a4, 0xd19c, 0x00c0, - 0x23ac, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xa722, - 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0040, 0x2490, 0x0f7e, - 0x2079, 0xa9c4, 0x783c, 0xa086, 0x0001, 0x00c0, 0x23d0, 0x017e, - 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x1000, - 0x7803, 0x0000, 0x2079, 0xa9b1, 0x7807, 0x0000, 0x7833, 0x0000, - 0x1078, 0x62d1, 0x1078, 0x639b, 0x017f, 0x0f7f, 0x0078, 0x2490, - 0x0f7f, 0x017e, 0x3900, 0xa082, 0xaae3, 0x00c8, 0x23db, 0x017e, - 0x1078, 0x747a, 0x017f, 0x6220, 0xd2b4, 0x0040, 0x2446, 0x1078, - 0x5acb, 0x1078, 0x6e0f, 0x6027, 0x0004, 0x0f7e, 0x2019, 0xa9ba, - 0x2304, 0xa07d, 0x0040, 0x241c, 0x7804, 0xa086, 0x0032, 0x00c0, - 0x241c, 0x0d7e, 0x0c7e, 0x0e7e, 0x2069, 0x0140, 0x618c, 0x6288, - 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, - 0x8001, 0x00c0, 0x2400, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, - 0x0000, 0x618e, 0x628a, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x7810, - 0x2070, 0x7037, 0x0103, 0x2f60, 0x1078, 0x772d, 0x0e7f, 0x0c7f, - 0x0d7f, 0x0f7f, 0x017f, 0x007c, 0x0f7f, 0x0d7e, 0x2069, 0x0140, - 0x6804, 0xa084, 0x4000, 0x0040, 0x2429, 0x6803, 0x1000, 0x6803, - 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa9b1, 0x6028, 0xa09a, 0x00c8, - 0x00c8, 0x2439, 0x8000, 0x602a, 0x0c7f, 0x1078, 0x6e01, 0x0078, - 0x248f, 0x2019, 0xa9ba, 0x2304, 0xa065, 0x0040, 0x2443, 0x2009, - 0x0027, 0x1078, 0x775c, 0x0c7f, 0x0078, 0x248f, 0xd2bc, 0x0040, - 0x248f, 0x1078, 0x5ad8, 0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e, - 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x245b, 0x6803, - 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa9b1, 0x6044, - 0xa09a, 0x00c8, 0x00c8, 0x247e, 0x8000, 0x6046, 0x603c, 0x0c7f, - 0xa005, 0x0040, 0x248f, 0x2009, 0x07d0, 0x1078, 0x5ad0, 0xa080, - 0x0007, 0x2004, 0xa086, 0x0006, 0x00c0, 0x247a, 0x6017, 0x0012, - 0x0078, 0x248f, 0x6017, 0x0016, 0x0078, 0x248f, 0x037e, 0x2019, - 0x0001, 0x1078, 0x7058, 0x037f, 0x2019, 0xa9c0, 0x2304, 0xa065, - 0x0040, 0x248e, 0x2009, 0x004f, 0x1078, 0x775c, 0x0c7f, 0x017f, - 0xd19c, 0x0040, 0x24e4, 0x7034, 0xd0ac, 0x00c0, 0x24c1, 0x017e, - 0x157e, 0x6027, 0x0008, 0x602f, 0x0020, 0x20a9, 0x000a, 0x00f0, - 0x249f, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, - 0x0320, 0x00e0, 0x24a9, 0x2091, 0x6000, 0x6020, 0xd09c, 0x00c0, - 0x24b8, 0x157f, 0x6152, 0x017f, 0x6027, 0x0008, 0x0078, 0x24e4, - 0x1078, 0x2577, 0x00f0, 0x24a9, 0x157f, 0x6152, 0x017f, 0x6027, - 0x0008, 0x017e, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x1078, - 0x70e0, 0x2011, 0x0002, 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, - 0x2019, 0x0000, 0x1078, 0x7058, 0x037f, 0x60e3, 0x0000, 0x1078, - 0xa5bd, 0x1078, 0xa5db, 0x2001, 0xa700, 0x2003, 0x0004, 0x6027, - 0x0008, 0x1078, 0x1246, 0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c, - 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000, - 0x2071, 0xa700, 0x71bc, 0x70be, 0xa116, 0x0040, 0x2518, 0x81ff, - 0x0040, 0x2500, 0x2011, 0x8011, 0x1078, 0x361b, 0x0078, 0x2518, - 0x2011, 0x8012, 0x1078, 0x361b, 0x2001, 0xa772, 0x2004, 0xd0fc, - 0x00c0, 0x2518, 0x037e, 0x0c7e, 0x1078, 0x6f9f, 0x2061, 0x0100, - 0x2019, 0x0028, 0x2009, 0x0000, 0x1078, 0x284f, 0x0c7f, 0x037f, - 0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, 0x0c7e, - 0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100, 0xa190, 0x253b, 0x2204, - 0x60f2, 0x2011, 0x2548, 0x6000, 0xa082, 0x0003, 0x00c8, 0x2534, - 0x2001, 0x00ff, 0x0078, 0x2535, 0x2204, 0x60ee, 0x027f, 0x007f, - 0x0f7f, 0x0c7f, 0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, - 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, - 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, - 0x2130, 0xa094, 0xff00, 0x00c0, 0x2558, 0x81ff, 0x0040, 0x255c, - 0x1078, 0x5761, 0x0078, 0x2563, 0xa080, 0x29c0, 0x200c, 0xa18c, - 0xff00, 0x810f, 0xa006, 0x007c, 0xa080, 0x29c0, 0x200c, 0xa18c, - 0x00ff, 0x007c, 0x0c7e, 0x2061, 0xa700, 0x6030, 0x0040, 0x2573, - 0xc09d, 0x0078, 0x2574, 0xc09c, 0x6032, 0x0c7f, 0x007c, 0x007e, - 0x157e, 0x0f7e, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, - 0x00c0, 0x2584, 0x00f0, 0x257e, 0x0f7f, 0x157f, 0x007f, 0x007c, - 0x0c7e, 0x007e, 0x2061, 0x0100, 0x6030, 0x007e, 0x6048, 0x007e, - 0x60e4, 0x007e, 0x60e8, 0x007e, 0x6050, 0x007e, 0x60f0, 0x007e, - 0x60ec, 0x007e, 0x600c, 0x007e, 0x6004, 0x007e, 0x6028, 0x007e, - 0x60e0, 0x007e, 0x602f, 0x0100, 0x602f, 0x0000, 0x0005, 0x0005, - 0x0005, 0x0005, 0x602f, 0x0040, 0x602f, 0x0000, 0x007f, 0x60e2, - 0x007f, 0x602a, 0x007f, 0x6006, 0x007f, 0x600e, 0x007f, 0x60ee, - 0x007f, 0x60f2, 0x007f, 0x6052, 0x007f, 0x60ea, 0x007f, 0x60e6, - 0x007f, 0x604a, 0x007f, 0x6032, 0x007f, 0x0c7f, 0x007c, 0x25e7, - 0x25eb, 0x25ef, 0x25f5, 0x25fb, 0x2601, 0x2607, 0x260f, 0x2617, - 0x261d, 0x2623, 0x262b, 0x2633, 0x263b, 0x2643, 0x264d, 0x2657, - 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, - 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x107e, - 0x007e, 0x0078, 0x2670, 0x107e, 0x007e, 0x0078, 0x2670, 0x107e, - 0x007e, 0x1078, 0x226c, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, - 0x226c, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x0078, - 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, - 0x007e, 0x1078, 0x226c, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, - 0x007e, 0x1078, 0x226c, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e, - 0x007e, 0x1078, 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, - 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, - 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, - 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x1078, - 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x1078, - 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078, - 0x2133, 0x1078, 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, - 0x226c, 0x1078, 0x2133, 0x1078, 0x2178, 0x0078, 0x2670, 0x0005, - 0x0078, 0x2657, 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x2660, - 0x2670, 0x25ed, 0x25f1, 0x25f7, 0x25fd, 0x2603, 0x2609, 0x2611, - 0x2619, 0x261f, 0x2625, 0x262d, 0x2635, 0x263d, 0x2645, 0x264f, - 0x0008, 0x265a, 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e, - 0x027e, 0x047e, 0x2021, 0x0000, 0x1078, 0x4967, 0x00c0, 0x2772, - 0x70cc, 0xd09c, 0x0040, 0x268e, 0xd084, 0x00c0, 0x268e, 0xd0bc, - 0x00c0, 0x2772, 0x1078, 0x2776, 0x0078, 0x2772, 0xd0cc, 0x00c0, - 0x2772, 0xd094, 0x0040, 0x2698, 0x7097, 0xffff, 0x0078, 0x2772, - 0x2001, 0x010c, 0x203c, 0x7284, 0xd284, 0x0040, 0x2701, 0xd28c, - 0x00c0, 0x2701, 0x037e, 0x7394, 0xa38e, 0xffff, 0x0040, 0x26ab, - 0x83ff, 0x00c0, 0x26ad, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xadc0, - 0x2c04, 0xa38c, 0x0001, 0x0040, 0x26ba, 0xa084, 0xff00, 0x8007, - 0x0078, 0x26bc, 0xa084, 0x00ff, 0xa70e, 0x0040, 0x26f6, 0xa08e, - 0x0000, 0x0040, 0x26f6, 0xa08e, 0x00ff, 0x00c0, 0x26d3, 0x7230, - 0xd284, 0x00c0, 0x26fc, 0x7284, 0xc28d, 0x7286, 0x7097, 0xffff, - 0x037f, 0x0078, 0x2701, 0x2009, 0x0000, 0x1078, 0x254d, 0x1078, - 0x455c, 0x00c0, 0x26f9, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, - 0x00c0, 0x26f0, 0x7030, 0xd08c, 0x0040, 0x26ea, 0x6000, 0xd0bc, - 0x0040, 0x26f0, 0x1078, 0x278c, 0x0040, 0x26f9, 0x0078, 0x26f6, - 0x1078, 0x28c4, 0x1078, 0x27b9, 0x0040, 0x26f9, 0x8318, 0x0078, - 0x26ad, 0x7396, 0x0078, 0x26fe, 0x7097, 0xffff, 0x037f, 0x0078, - 0x2772, 0xa780, 0x29c0, 0x203c, 0xa7bc, 0xff00, 0x873f, 0x2041, - 0x007e, 0x7094, 0xa096, 0xffff, 0x00c0, 0x2713, 0x2009, 0x0000, - 0x28a8, 0x0078, 0x271f, 0xa812, 0x0048, 0x271b, 0x2008, 0xa802, - 0x20a8, 0x0078, 0x271f, 0x7097, 0xffff, 0x0078, 0x2772, 0x2700, - 0x157e, 0x017e, 0xa106, 0x0040, 0x2766, 0xc484, 0x1078, 0x45c4, - 0x0040, 0x2730, 0x1078, 0x455c, 0x00c0, 0x276f, 0x0078, 0x2731, - 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2740, - 0x7030, 0xd08c, 0x0040, 0x275e, 0x6000, 0xd0bc, 0x00c0, 0x275e, - 0x7284, 0xd28c, 0x0040, 0x2756, 0x6004, 0xa084, 0x00ff, 0xa082, - 0x0006, 0x0048, 0x2766, 0xd484, 0x00c0, 0x2752, 0x1078, 0x457f, - 0x0078, 0x2754, 0x1078, 0x298e, 0x0078, 0x2766, 0x1078, 0x28c4, - 0x1078, 0x27b9, 0x0040, 0x276f, 0x0078, 0x2766, 0x1078, 0x2959, - 0x0040, 0x2766, 0x1078, 0x278c, 0x0040, 0x276f, 0x017f, 0x8108, - 0x157f, 0x00f0, 0x271f, 0x7097, 0xffff, 0x0078, 0x2772, 0x017f, - 0x157f, 0x7196, 0x047f, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x017e, - 0x7097, 0x0001, 0x2009, 0x007e, 0x1078, 0x455c, 0x00c0, 0x2789, - 0x1078, 0x28c4, 0x1078, 0x27b9, 0x0040, 0x2789, 0x70cc, 0xc0bd, - 0x70ce, 0x017f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, - 0x2c68, 0x2001, 0xa757, 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078, - 0x76c7, 0x0040, 0x27b4, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, - 0x0000, 0x1078, 0x44ee, 0x2001, 0x0000, 0x1078, 0x4502, 0x127e, - 0x2091, 0x8000, 0x7090, 0x8000, 0x7092, 0x127f, 0x2009, 0x0004, - 0x1078, 0x775c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, - 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x2001, 0xa757, - 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078, 0x9197, 0x0040, 0x27f2, - 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, - 0x0040, 0x27db, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, - 0x27db, 0x1078, 0x2880, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, - 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x127e, 0x2091, 0x8000, - 0x7090, 0x8000, 0x7092, 0x127f, 0x2009, 0x0002, 0x1078, 0x775c, - 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, - 0x027e, 0x2009, 0x0080, 0x1078, 0x455c, 0x00c0, 0x2805, 0x1078, - 0x2808, 0x0040, 0x2805, 0x70d3, 0xffff, 0x027f, 0x0c7f, 0x007c, - 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x76c7, 0x0040, - 0x282a, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, - 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x127e, 0x2091, 0x8000, - 0x70d4, 0x8000, 0x70d6, 0x127f, 0x2009, 0x0002, 0x1078, 0x775c, - 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, - 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2009, 0x007f, 0x1078, 0x455c, - 0x00c0, 0x284b, 0x2c68, 0x1078, 0x76c7, 0x0040, 0x284b, 0x2d00, - 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, 0x2009, 0x0022, 0x1078, - 0x775c, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x0c7f, 0x007c, 0x0e7e, - 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078, 0x5f0e, 0x1078, 0x5eae, - 0x1078, 0x8068, 0x2130, 0x81ff, 0x0040, 0x2864, 0x20a9, 0x007e, - 0x2009, 0x0000, 0x0078, 0x2868, 0x20a9, 0x007f, 0x2009, 0x0000, - 0x017e, 0x1078, 0x45c4, 0x00c0, 0x2871, 0x1078, 0x47e9, 0x1078, - 0x42f8, 0x017f, 0x8108, 0x00f0, 0x2868, 0x86ff, 0x00c0, 0x287a, - 0x1078, 0x119b, 0x027f, 0x037f, 0x067f, 0x0c7f, 0x0e7f, 0x007c, - 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, - 0x027e, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, - 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f9b, 0x077f, 0x017f, 0x2e60, - 0x1078, 0x47e9, 0x6210, 0x6314, 0x1078, 0x42f8, 0x6212, 0x6316, - 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x007e, - 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x28ba, 0x2071, - 0xa700, 0x7090, 0xa005, 0x0040, 0x28b7, 0x8001, 0x7092, 0x007f, - 0x0e7f, 0x007c, 0x2071, 0xa700, 0x70d4, 0xa005, 0x0040, 0x28b7, - 0x8001, 0x70d6, 0x0078, 0x28b7, 0x6000, 0xc08c, 0x6002, 0x007c, - 0x0f7e, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x2178, - 0x81ff, 0x00c0, 0x28d7, 0x20a9, 0x0001, 0x0078, 0x28f2, 0x2001, - 0xa753, 0x2004, 0xd0c4, 0x0040, 0x28ee, 0xd0a4, 0x0040, 0x28ee, - 0x047e, 0x6018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, - 0xa006, 0x2009, 0x002d, 0x1078, 0xa22d, 0x047f, 0x20a9, 0x00ff, - 0x2011, 0x0000, 0x027e, 0xa28e, 0x007e, 0x0040, 0x2936, 0xa28e, - 0x007f, 0x0040, 0x2936, 0xa28e, 0x0080, 0x0040, 0x2936, 0xa288, - 0xa835, 0x210c, 0x81ff, 0x0040, 0x2936, 0x8fff, 0x1040, 0x2942, - 0x0c7e, 0x2160, 0x2001, 0x0001, 0x1078, 0x4972, 0x0c7f, 0x2019, - 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, - 0x0c7e, 0x027e, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, - 0x00c0, 0x2926, 0x6007, 0x0404, 0x0078, 0x292b, 0x2001, 0x0004, - 0x8007, 0xa215, 0x6206, 0x027f, 0x0c7f, 0x017e, 0x2c08, 0x1078, - 0x9f9b, 0x017f, 0x077f, 0x2160, 0x1078, 0x47e9, 0x027f, 0x8210, - 0x00f0, 0x28f2, 0x157f, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, - 0x0f7f, 0x007c, 0x047e, 0x027e, 0x017e, 0x2001, 0xa753, 0x2004, - 0xd0c4, 0x0040, 0x2955, 0xd0a4, 0x0040, 0x2955, 0xa006, 0x2220, - 0x8427, 0x2009, 0x0029, 0x1078, 0xa22d, 0x017f, 0x027f, 0x047f, - 0x007c, 0x017e, 0x027e, 0x037e, 0x0c7e, 0x7284, 0x82ff, 0x0040, - 0x2987, 0xa290, 0xa753, 0x2214, 0xd2ac, 0x00c0, 0x2987, 0x2100, - 0x1078, 0x2564, 0x81ff, 0x0040, 0x2989, 0x2019, 0x0001, 0x8314, - 0xa2e0, 0xadc0, 0x2c04, 0xd384, 0x0040, 0x297b, 0xa084, 0xff00, - 0x8007, 0x0078, 0x297d, 0xa084, 0x00ff, 0xa116, 0x0040, 0x2989, - 0xa096, 0x00ff, 0x0040, 0x2987, 0x8318, 0x0078, 0x296f, 0xa085, - 0x0001, 0x0c7f, 0x037f, 0x027f, 0x017f, 0x007c, 0x017e, 0x0c7e, - 0x127e, 0x2091, 0x8000, 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, - 0x2019, 0x0029, 0x1078, 0x73d0, 0x027f, 0x1078, 0xa501, 0x037f, - 0x027f, 0x017f, 0xa180, 0xa835, 0x2004, 0xa065, 0x0040, 0x29b7, - 0x017e, 0x0c7e, 0x1078, 0x9197, 0x017f, 0x1040, 0x1332, 0x611a, - 0x1078, 0x2880, 0x1078, 0x772d, 0x017f, 0x1078, 0x457f, 0x127f, - 0x0c7f, 0x017f, 0x007c, 0x2001, 0xa733, 0x2004, 0xd0cc, 0x007c, - 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, - 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, - 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, - 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, - 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, - 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, - 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, - 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, - 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, - 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, - 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, - 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, - 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, - 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, - 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, - 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, - 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, - 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, - 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, - 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, - 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, - 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, - 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, - 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, - 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, - 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, - 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, - 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, - 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x2071, 0xa782, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, - 0x703e, 0x7033, 0xa792, 0x7037, 0xa792, 0x7007, 0x0001, 0x2061, - 0xa7d2, 0x6003, 0x0002, 0x007c, 0x0090, 0x2ae7, 0x0068, 0x2ae7, - 0x2071, 0xa782, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2ae7, 0x2a60, - 0x7820, 0xa08e, 0x0069, 0x00c0, 0x2bd7, 0x0079, 0x2b6b, 0x007c, - 0x2071, 0xa782, 0x7004, 0x0079, 0x2aed, 0x2af1, 0x2af2, 0x2afc, - 0x2b0e, 0x007c, 0x0090, 0x2afb, 0x0068, 0x2afb, 0x2b78, 0x7818, - 0xd084, 0x0040, 0x2b1a, 0x007c, 0x2b78, 0x2061, 0xa7d2, 0x6008, - 0xa08e, 0x0100, 0x0040, 0x2b09, 0xa086, 0x0200, 0x0040, 0x2bcf, - 0x007c, 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068, - 0x6834, 0xa086, 0x0103, 0x0040, 0x2b16, 0x007c, 0x2a60, 0x2b78, - 0x7018, 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2b23, - 0x61bc, 0x0079, 0x2b2b, 0x2100, 0xa08a, 0x003f, 0x00c8, 0x2bcb, - 0x61bc, 0x0079, 0x2b6b, 0x2bad, 0x2bdf, 0x2be7, 0x2beb, 0x2bf3, - 0x2bf9, 0x2bfd, 0x2c09, 0x2c0d, 0x2c17, 0x2c1b, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2c1f, 0x2bcb, 0x2c2f, 0x2c46, 0x2c5d, 0x2cdd, 0x2ce2, - 0x2d0f, 0x2d69, 0x2d7a, 0x2d98, 0x2dd9, 0x2de3, 0x2df0, 0x2e03, - 0x2e22, 0x2e2b, 0x2e68, 0x2e6e, 0x2bcb, 0x2e8a, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x2e91, 0x2e9b, 0x2bcb, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2ea3, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x2eb5, 0x2ece, 0x2bcb, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x2ee0, 0x2f37, 0x2f95, 0x2fa9, 0x2bcb, - 0x2bcb, 0x2bcb, 0x398e, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x2c17, 0x2c1b, 0x2fc0, 0x2bcb, 0x2fcd, - 0x3a26, 0x3a83, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, - 0x2bcb, 0x2bcb, 0x2bcb, 0x301a, 0x314f, 0x316b, 0x3177, 0x31da, - 0x3233, 0x323e, 0x327d, 0x328c, 0x329b, 0x329e, 0x2fd1, 0x32c2, - 0x331e, 0x332b, 0x343c, 0x356f, 0x3599, 0x36a6, 0x2bcb, 0x36b6, - 0x36f0, 0x37bf, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x3827, 0x3843, - 0x38bd, 0x3977, 0x713c, 0x0078, 0x2bad, 0x2021, 0x4000, 0x1078, - 0x35f5, 0x127e, 0x2091, 0x8000, 0x0068, 0x2bba, 0x7818, 0xd084, - 0x0040, 0x2bbd, 0x127f, 0x0078, 0x2bb1, 0x7c22, 0x7926, 0x7a2a, - 0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, - 0x5000, 0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x2baf, 0x2021, - 0x4002, 0x0078, 0x2baf, 0x2021, 0x4003, 0x0078, 0x2baf, 0x2021, - 0x4005, 0x0078, 0x2baf, 0x2021, 0x4006, 0x0078, 0x2baf, 0xa02e, - 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x3604, 0x7823, - 0x0004, 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, - 0x7930, 0x0078, 0x3608, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, - 0x2bad, 0x7924, 0x2114, 0x0078, 0x2bad, 0x2099, 0x0009, 0x20a1, - 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0078, - 0x2bad, 0x7824, 0x2060, 0x0078, 0x2c21, 0x2009, 0x0001, 0x2011, - 0x0013, 0x2019, 0x0019, 0x783b, 0x0017, 0x0078, 0x2bad, 0x7d38, - 0x7c3c, 0x0078, 0x2be1, 0x7d38, 0x7c3c, 0x0078, 0x2bed, 0x2061, - 0x1000, 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0, - 0x2c23, 0x2010, 0xa005, 0x0040, 0x2bad, 0x0078, 0x2bd3, 0x2069, - 0xa752, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2bdb, 0x8019, 0x0040, - 0x2bdb, 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, - 0x685a, 0x685e, 0x1078, 0x4eae, 0x0078, 0x2bad, 0x2069, 0xa752, - 0x7824, 0x7934, 0xa11a, 0x00c8, 0x2bdb, 0x8019, 0x0040, 0x2bdb, - 0x684e, 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, - 0x686e, 0x1078, 0x4a3e, 0x0078, 0x2bad, 0xa02e, 0x2520, 0x81ff, - 0x00c0, 0x2bd7, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, - 0xa789, 0x41a1, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x2009, 0x0020, - 0x1078, 0x3604, 0x701b, 0x2c75, 0x007c, 0x6834, 0x2008, 0xa084, - 0x00ff, 0xa096, 0x0011, 0x0040, 0x2c85, 0xa096, 0x0019, 0x0040, - 0x2c85, 0xa096, 0x0015, 0x00c0, 0x2bd7, 0x810f, 0xa18c, 0x00ff, - 0x0040, 0x2bd7, 0x710e, 0x700c, 0x8001, 0x0040, 0x2cb6, 0x700e, - 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x2009, 0x0020, 0x2061, 0xa7d2, - 0x6224, 0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, - 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x1078, 0x3604, 0x701b, 0x2ca9, - 0x007c, 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0040, 0x2cb4, - 0xa096, 0x000a, 0x00c0, 0x2bd7, 0x0078, 0x2c8b, 0x7010, 0x2068, - 0x6838, 0xc0fd, 0x683a, 0x1078, 0x4431, 0x00c0, 0x2cc4, 0x7007, - 0x0003, 0x701b, 0x2cc6, 0x007c, 0x1078, 0x4b51, 0x127e, 0x2091, - 0x8000, 0x20a9, 0x0005, 0x2099, 0xa789, 0x530a, 0x2100, 0xa210, - 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, - 0x2009, 0x0020, 0x127f, 0x0078, 0x3608, 0x61a4, 0x7824, 0x60a6, - 0x0078, 0x2bad, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, - 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, - 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, - 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, - 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, - 0x00f0, 0xa08a, 0x0003, 0x00c8, 0x0427, 0x0078, 0x0423, 0x81ff, - 0x00c0, 0x2bd7, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x45c4, - 0x00c0, 0x2bdb, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, - 0x2d23, 0x0078, 0x2bdb, 0x7c28, 0x7d2c, 0x1078, 0x47a4, 0xd28c, - 0x00c0, 0x2d2e, 0x1078, 0x4736, 0x0078, 0x2d30, 0x1078, 0x4772, - 0x00c0, 0x2d5a, 0x2061, 0xae00, 0x127e, 0x2091, 0x8000, 0x6000, - 0xa086, 0x0000, 0x0040, 0x2d48, 0x6010, 0xa06d, 0x0040, 0x2d48, - 0x683c, 0xa406, 0x00c0, 0x2d48, 0x6840, 0xa506, 0x0040, 0x2d53, - 0x127f, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, 0xac02, 0x00c8, - 0x2bd7, 0x0078, 0x2d34, 0x1078, 0x8a11, 0x127f, 0x0040, 0x2bd7, - 0x0078, 0x2bad, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4b51, 0x127e, - 0x2091, 0x8000, 0x1078, 0x8f95, 0x1078, 0x4a73, 0x127f, 0x0078, - 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, 0x0040, 0x2bdb, - 0x1078, 0x4673, 0x0040, 0x2bd7, 0x1078, 0x47b2, 0x0040, 0x2bd7, - 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, - 0x2bdb, 0x1078, 0x482f, 0x0040, 0x2bd7, 0x2019, 0x0005, 0x1078, - 0x47d3, 0x0040, 0x2bd7, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, - 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x5a52, 0x0078, 0x2bad, - 0x127e, 0x2091, 0x8000, 0x81ff, 0x0040, 0x2da2, 0x2009, 0x0001, - 0x0078, 0x2dd3, 0x2029, 0x00ff, 0x6450, 0x2400, 0xa506, 0x0040, - 0x2dcd, 0x2508, 0x1078, 0x45c4, 0x00c0, 0x2dcd, 0x1078, 0x482f, - 0x00c0, 0x2db8, 0x2009, 0x0002, 0x62ac, 0x2518, 0x0078, 0x2dd3, - 0x2019, 0x0004, 0x1078, 0x47d3, 0x00c0, 0x2dc2, 0x2009, 0x0006, - 0x0078, 0x2dd3, 0x7824, 0xa08a, 0x1000, 0x00c8, 0x2dd6, 0x8003, - 0x800b, 0x810b, 0xa108, 0x1078, 0x5a52, 0x8529, 0x00c8, 0x2da5, - 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, 0x2bd7, 0x127f, 0x0078, - 0x2bdb, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x46e7, 0x1078, - 0x47a4, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, - 0x0040, 0x2bdb, 0x1078, 0x46d6, 0x1078, 0x47a4, 0x0078, 0x2bad, - 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, - 0x4775, 0x0040, 0x2bd7, 0x1078, 0x4484, 0x1078, 0x472f, 0x1078, - 0x47a4, 0x0078, 0x2bad, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, - 0x4673, 0x0040, 0x2bd7, 0x62a0, 0x2019, 0x0005, 0x0c7e, 0x1078, - 0x47e9, 0x0c7f, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, - 0x5e0a, 0x2009, 0x0000, 0x1078, 0x9f9b, 0x077f, 0x1078, 0x47a4, - 0x0078, 0x2bad, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x47a4, - 0x2208, 0x0078, 0x2bad, 0x157e, 0x0d7e, 0x0e7e, 0x2069, 0xa814, - 0x6810, 0x6914, 0xa10a, 0x00c8, 0x2e37, 0x2009, 0x0000, 0x6816, - 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x00ff, 0x2069, 0xa835, - 0x2d04, 0xa075, 0x0040, 0x2e4c, 0x704c, 0x1078, 0x2e56, 0xa210, - 0x7080, 0x1078, 0x2e56, 0xa318, 0x8d68, 0x00f0, 0x2e40, 0x2300, - 0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078, 0x2bad, 0x0f7e, 0x017e, - 0xa07d, 0x0040, 0x2e65, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, - 0x0040, 0x2e65, 0x2178, 0x0078, 0x2e5d, 0x017f, 0x0f7f, 0x007c, - 0x2069, 0xa814, 0x6910, 0x62a8, 0x0078, 0x2bad, 0x81ff, 0x00c0, - 0x2bd7, 0x6150, 0xa190, 0x29c0, 0x2214, 0xa294, 0x00ff, 0x6070, - 0xa084, 0xff00, 0xa215, 0x636c, 0x67cc, 0xd79c, 0x0040, 0x2e84, - 0x2031, 0x0001, 0x0078, 0x2e86, 0x2031, 0x0000, 0x7e3a, 0x7f3e, - 0x0078, 0x2bad, 0x6140, 0x6244, 0x2019, 0xa9a2, 0x231c, 0x0078, - 0x2bad, 0x127e, 0x2091, 0x8000, 0x6134, 0x6338, 0xa006, 0x2010, - 0x127f, 0x0078, 0x2bad, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x6244, - 0x6338, 0x0078, 0x2bad, 0x6140, 0x6244, 0x7824, 0x6042, 0x7b28, - 0x6346, 0x2069, 0xa752, 0x831f, 0xa305, 0x6816, 0x782c, 0x2069, - 0xa9a2, 0x2d1c, 0x206a, 0x0078, 0x2bad, 0x017e, 0x127e, 0x2091, - 0x8000, 0x7824, 0x6036, 0xd094, 0x0040, 0x2ec8, 0x7828, 0xa085, - 0x0001, 0x2009, 0xa9ab, 0x200a, 0x2001, 0xffff, 0x1078, 0x5ae6, - 0x782c, 0x603a, 0x127f, 0x017f, 0x0078, 0x2bad, 0x1078, 0x35e4, - 0x0040, 0x2bdb, 0x7828, 0xa00d, 0x0040, 0x2bdb, 0x782c, 0xa005, - 0x0040, 0x2bdb, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078, 0x2bad, - 0x2001, 0xa700, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x0c7e, - 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, - 0x00c0, 0x2ef7, 0x6030, 0xa085, 0xff00, 0x0078, 0x2f06, 0xa182, - 0x007f, 0x00c8, 0x2f30, 0xa188, 0x29c0, 0x210c, 0xa18c, 0x00ff, - 0x6030, 0xa116, 0x0040, 0x2f30, 0x810f, 0xa105, 0x127e, 0x2091, - 0x8000, 0x007e, 0x1078, 0x76c7, 0x007f, 0x0040, 0x2f2c, 0x601a, - 0x600b, 0xbc09, 0x601f, 0x0001, 0x1078, 0x35ba, 0x0040, 0x2f33, - 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, - 0x683a, 0x701b, 0x2f8e, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, - 0x775c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2bd7, - 0x0c7f, 0x0078, 0x2bdb, 0x1078, 0x772d, 0x0078, 0x2f2c, 0x2001, - 0xa700, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x0c7e, 0x2061, - 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x00c0, - 0x2f4e, 0x6030, 0xa085, 0xff00, 0x0078, 0x2f5d, 0xa182, 0x007f, - 0x00c8, 0x2f87, 0xa188, 0x29c0, 0x210c, 0xa18c, 0x00ff, 0x6030, - 0xa116, 0x0040, 0x2f87, 0x810f, 0xa105, 0x127e, 0x2091, 0x8000, - 0x007e, 0x1078, 0x76c7, 0x007f, 0x0040, 0x2f83, 0x601a, 0x600b, - 0xbc05, 0x601f, 0x0001, 0x1078, 0x35ba, 0x0040, 0x2f8a, 0x6837, - 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x701b, 0x2f8e, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, 0x775c, - 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2bd7, 0x0c7f, - 0x0078, 0x2bdb, 0x1078, 0x772d, 0x0078, 0x2f83, 0x6830, 0xa086, - 0x0100, 0x0040, 0x2bd7, 0x0078, 0x2bad, 0x2061, 0xaa33, 0x127e, - 0x2091, 0x8000, 0x6000, 0xd084, 0x0040, 0x2fa6, 0x6104, 0x6208, - 0x2019, 0xa712, 0x231c, 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, - 0x2bdb, 0x81ff, 0x00c0, 0x2bd7, 0x127e, 0x2091, 0x8000, 0x6248, - 0x6064, 0xa202, 0x0048, 0x2fbd, 0xa085, 0x0001, 0x1078, 0x256a, - 0x1078, 0x3c9e, 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, 0x2bdb, - 0x127e, 0x2091, 0x8000, 0x20a9, 0x0012, 0x2001, 0xa740, 0x20a0, - 0xa006, 0x40a4, 0x127f, 0x0078, 0x2bad, 0x7d38, 0x7c3c, 0x0078, - 0x2c5f, 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x2bd7, - 0x6250, 0xa084, 0xff00, 0x8007, 0xa206, 0x00c0, 0x2fe9, 0x2001, - 0xa740, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, - 0x3608, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2bd7, 0x0c7e, - 0x1078, 0x35ba, 0x0c7f, 0x0040, 0x2bd7, 0x6837, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x1078, 0x8e5a, 0x0040, 0x2bd7, 0x7007, 0x0003, - 0x701b, 0x300b, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, - 0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, - 0x0078, 0x3608, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x1078, 0x42dd, - 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, - 0x701b, 0x302b, 0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, - 0x2bdb, 0x6804, 0xd0ac, 0x0040, 0x3038, 0xd0a4, 0x0040, 0x2bdb, - 0xd094, 0x0040, 0x3043, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, - 0xffdf, 0x6106, 0x0c7f, 0xd08c, 0x0040, 0x304e, 0x0c7e, 0x2061, - 0x0100, 0x6104, 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, - 0x210c, 0xa18a, 0x0002, 0x0048, 0x3063, 0xd084, 0x0040, 0x3063, - 0x6a28, 0xa28a, 0x007f, 0x00c8, 0x2bdb, 0xa288, 0x29c0, 0x210c, - 0xa18c, 0x00ff, 0x6156, 0xd0dc, 0x0040, 0x306c, 0x6828, 0xa08a, - 0x007f, 0x00c8, 0x2bdb, 0x6052, 0x6808, 0xa08a, 0x0100, 0x0048, - 0x2bdb, 0xa08a, 0x0841, 0x00c8, 0x2bdb, 0xa084, 0x0007, 0x00c0, - 0x2bdb, 0x680c, 0xa005, 0x0040, 0x2bdb, 0x6810, 0xa005, 0x0040, - 0x2bdb, 0x6848, 0x6940, 0xa10a, 0x00c8, 0x2bdb, 0x8001, 0x0040, - 0x2bdb, 0x684c, 0x6944, 0xa10a, 0x00c8, 0x2bdb, 0x8001, 0x0040, - 0x2bdb, 0x6804, 0xd0fc, 0x0040, 0x30c2, 0x1078, 0x35ba, 0x0040, - 0x2bd7, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, - 0x0038, 0xa399, 0x0000, 0x1078, 0x3604, 0x701b, 0x30a8, 0x007c, - 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0xa76e, 0x2da0, - 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xa772, 0x200c, 0xd1e4, - 0x0040, 0x30c2, 0x0c7e, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, - 0x6006, 0x0c7f, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xa752, 0x2da0, - 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x6142, 0x8007, 0xa084, 0x00ff, - 0x6046, 0x1078, 0x4eae, 0x1078, 0x49ce, 0x1078, 0x4a3e, 0x6000, - 0xa086, 0x0000, 0x00c0, 0x314d, 0x6808, 0x602a, 0x1078, 0x21f7, - 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, - 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0040, 0x30fa, - 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, - 0x0078, 0x30fc, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, - 0x1078, 0x5b19, 0x6904, 0xd1fc, 0x0040, 0x312f, 0x0c7e, 0x2009, - 0x0000, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0040, 0x312c, 0x0078, - 0x3116, 0x839d, 0x00c8, 0x312c, 0x3508, 0x8109, 0x1078, 0x5480, - 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, - 0xa184, 0x00ff, 0x6006, 0x8108, 0x00c0, 0x312a, 0x6003, 0x0003, - 0x0078, 0x312c, 0x6003, 0x0001, 0x00f0, 0x3111, 0x0c7f, 0x0c7e, - 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x0c7f, 0x1078, - 0x3819, 0x0040, 0x313d, 0x1078, 0x256a, 0x60c0, 0xa005, 0x0040, - 0x3149, 0x6003, 0x0001, 0x2091, 0x301d, 0x1078, 0x4224, 0x0078, - 0x314d, 0x6003, 0x0004, 0x2091, 0x301d, 0x0078, 0x2bad, 0x6000, - 0xa086, 0x0000, 0x0040, 0x2bd7, 0x2069, 0xa752, 0x7830, 0x6842, - 0x7834, 0x6846, 0x6804, 0xd0fc, 0x0040, 0x3162, 0x2009, 0x0030, - 0x0078, 0x3164, 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, - 0x7d38, 0x0078, 0x3608, 0xa006, 0x1078, 0x256a, 0x81ff, 0x00c0, - 0x2bd7, 0x1078, 0x42dd, 0x1078, 0x4224, 0x0078, 0x2bad, 0x81ff, - 0x00c0, 0x2bd7, 0x6184, 0x81ff, 0x0040, 0x3191, 0x703f, 0x0000, - 0x2001, 0xadc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, - 0x127e, 0x2091, 0x8000, 0x1078, 0x3608, 0x701b, 0x2baa, 0x127f, - 0x007c, 0x703f, 0x0001, 0x0d7e, 0x2069, 0xadc0, 0x20a9, 0x0040, - 0x20a1, 0xadc0, 0x2019, 0xffff, 0x43a4, 0x6550, 0xa588, 0x29c0, - 0x210c, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, - 0xa506, 0x0040, 0x31c3, 0x1078, 0x45c4, 0x00c0, 0x31c3, 0x6014, - 0x821c, 0x0048, 0x31bb, 0xa398, 0xadc0, 0xa085, 0xff00, 0x8007, - 0x201a, 0x0078, 0x31c2, 0xa398, 0xadc0, 0x2324, 0xa4a4, 0xff00, - 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x00c8, 0x31ca, - 0x0078, 0x31a7, 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x0d7f, - 0x20a9, 0x0040, 0x20a1, 0xadc0, 0x2099, 0xadc0, 0x1078, 0x4281, - 0x0078, 0x3180, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x0c7e, 0x1078, - 0x35ba, 0x0c7f, 0x00c0, 0x31e8, 0x2009, 0x0002, 0x0078, 0x2bd7, - 0x2001, 0xa753, 0x2004, 0xd0b4, 0x0040, 0x320f, 0x6000, 0xd08c, - 0x00c0, 0x320f, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, - 0x320f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8eae, - 0x00c0, 0x3206, 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, - 0x701b, 0x320b, 0x007c, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x20a9, - 0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, - 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, 0x20a0, 0x1078, 0x4281, - 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, - 0x1078, 0x4281, 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, - 0x7d38, 0x0078, 0x3608, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, - 0x0040, 0x2bdb, 0x1078, 0x47bd, 0x0078, 0x2bad, 0x81ff, 0x00c0, - 0x2bd7, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, 0x1078, 0x35e4, - 0x0040, 0x2bdb, 0x1078, 0x482f, 0x0040, 0x2bd7, 0x2019, 0x0004, - 0x1078, 0x47d3, 0x7924, 0x810f, 0x7a28, 0x1078, 0x3259, 0x0078, - 0x2bad, 0xa186, 0x00ff, 0x0040, 0x3261, 0x1078, 0x3271, 0x0078, - 0x3270, 0x2029, 0x007e, 0x2061, 0xa700, 0x6450, 0x2400, 0xa506, - 0x0040, 0x326d, 0x2508, 0x1078, 0x3271, 0x8529, 0x00c8, 0x3266, - 0x007c, 0x1078, 0x45c4, 0x00c0, 0x327c, 0x2200, 0x8003, 0x800b, - 0x810b, 0xa108, 0x1078, 0x5a52, 0x007c, 0x81ff, 0x00c0, 0x2bd7, - 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, - 0x1078, 0x47c8, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, - 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, 0x1078, - 0x47b2, 0x0078, 0x2bad, 0x6100, 0x0078, 0x2bad, 0x1078, 0x35e4, - 0x0040, 0x2bdb, 0x2001, 0xa700, 0x2004, 0xa086, 0x0003, 0x00c0, - 0x2bd7, 0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x32b2, - 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, - 0x6b04, 0x831f, 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, - 0x0078, 0x2bad, 0xa006, 0x1078, 0x256a, 0x7824, 0xa084, 0x00ff, - 0xa086, 0x00ff, 0x0040, 0x32cf, 0x81ff, 0x00c0, 0x2bd7, 0x1078, - 0x42dd, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, 0x7924, 0xa18c, - 0xff00, 0x810f, 0xa186, 0x00ff, 0x0040, 0x32e5, 0xa182, 0x007f, - 0x00c8, 0x2bdb, 0x2100, 0x1078, 0x2564, 0x027e, 0x0c7e, 0x127e, - 0x2091, 0x8000, 0x2061, 0xa9c4, 0x601b, 0x0000, 0x601f, 0x0000, - 0x2011, 0x0003, 0x1078, 0x70e0, 0x2011, 0x0002, 0x1078, 0x70ea, - 0x1078, 0x6fc4, 0x037e, 0x2019, 0x0000, 0x1078, 0x7058, 0x037f, - 0x2061, 0x0100, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, - 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4259, - 0x1078, 0x5add, 0x7924, 0xa18c, 0xff00, 0x810f, 0x7a28, 0x1078, - 0x3259, 0x127f, 0x0c7f, 0x027f, 0x0078, 0x2bad, 0x7924, 0xa18c, - 0xff00, 0x810f, 0x0c7e, 0x1078, 0x455c, 0x2c08, 0x0c7f, 0x00c0, - 0x2bdb, 0x0078, 0x2bad, 0x81ff, 0x0040, 0x3332, 0x2009, 0x0001, - 0x0078, 0x2bd7, 0x60cc, 0xd09c, 0x00c0, 0x333a, 0x2009, 0x0005, - 0x0078, 0x2bd7, 0x1078, 0x35ba, 0x00c0, 0x3342, 0x2009, 0x0002, - 0x0078, 0x2bd7, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, - 0x3604, 0x701b, 0x334c, 0x007c, 0x2009, 0x0080, 0x1078, 0x45c4, - 0x00c0, 0x3359, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, - 0x335d, 0x2021, 0x400a, 0x0078, 0x2baf, 0x0d7e, 0xade8, 0x000d, - 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, - 0x0100, 0x0040, 0x33d0, 0xa0be, 0x0112, 0x0040, 0x33d0, 0xa0be, - 0x0113, 0x0040, 0x33d0, 0xa0be, 0x0114, 0x0040, 0x33d0, 0xa0be, - 0x0117, 0x0040, 0x33d0, 0xa0be, 0x011a, 0x0040, 0x33d0, 0xa0be, - 0x0121, 0x0040, 0x33c6, 0xa0be, 0x0131, 0x0040, 0x33c6, 0xa0be, - 0x0171, 0x0040, 0x33d0, 0xa0be, 0x0173, 0x0040, 0x33d0, 0xa0be, - 0x01a1, 0x00c0, 0x3398, 0x6830, 0x8007, 0x6832, 0x0078, 0x33d6, - 0xa0be, 0x0212, 0x0040, 0x33cc, 0xa0be, 0x0213, 0x0040, 0x33cc, - 0xa0be, 0x0214, 0x0040, 0x33be, 0xa0be, 0x0217, 0x0040, 0x33b8, - 0xa0be, 0x021a, 0x00c0, 0x33b1, 0x6838, 0x8007, 0x683a, 0x0078, - 0x33d0, 0xa0be, 0x0300, 0x0040, 0x33d0, 0x0d7f, 0x0078, 0x2bdb, - 0xad80, 0x0010, 0x20a9, 0x0007, 0x1078, 0x3418, 0xad80, 0x000e, - 0x20a9, 0x0001, 0x1078, 0x3418, 0x0078, 0x33d0, 0xad80, 0x000c, - 0x1078, 0x3426, 0x0078, 0x33d6, 0xad80, 0x000e, 0x1078, 0x3426, - 0xad80, 0x000c, 0x20a9, 0x0001, 0x1078, 0x3418, 0x0c7e, 0x1078, - 0x35ba, 0x0040, 0x3409, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, - 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, - 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, - 0x0000, 0x0c7f, 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x6823, 0x0000, 0x6804, 0x2068, 0x1078, 0x8e76, 0x00c0, 0x3404, - 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x340f, - 0x007c, 0x0c7f, 0x0d7f, 0x2009, 0x0002, 0x0078, 0x2bd7, 0x6820, - 0xa086, 0x8001, 0x00c0, 0x2bad, 0x2009, 0x0004, 0x0078, 0x2bd7, - 0x017e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, - 0x280a, 0x8108, 0x00f0, 0x341a, 0x017f, 0x007c, 0x017e, 0x0a7e, - 0x0b7e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, - 0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, - 0x0b7f, 0x0a7f, 0x017f, 0x007c, 0x81ff, 0x0040, 0x3443, 0x2009, - 0x0001, 0x0078, 0x2bd7, 0x60cc, 0xd09c, 0x00c0, 0x344b, 0x2009, - 0x0005, 0x0078, 0x2bd7, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, - 0xa182, 0x0080, 0x0048, 0x2bdb, 0xa182, 0x00ff, 0x00c8, 0x2bdb, - 0x7a2c, 0x7b28, 0x606c, 0xa306, 0x00c0, 0x3466, 0x6070, 0xa24e, - 0x0040, 0x2bdb, 0xa9cc, 0xff00, 0x0040, 0x2bdb, 0x0c7e, 0x1078, - 0x350f, 0x2c68, 0x0c7f, 0x0040, 0x349e, 0xa0c6, 0x4000, 0x00c0, - 0x3484, 0x0c7e, 0x007e, 0x2d60, 0x2009, 0x0000, 0x1078, 0x489b, - 0x00c0, 0x347b, 0xc185, 0x6000, 0xd0bc, 0x0040, 0x3480, 0xc18d, - 0x007f, 0x0c7f, 0x0078, 0x349b, 0xa0c6, 0x4007, 0x00c0, 0x348b, - 0x2408, 0x0078, 0x349b, 0xa0c6, 0x4008, 0x00c0, 0x3493, 0x2708, - 0x2610, 0x0078, 0x349b, 0xa0c6, 0x4009, 0x00c0, 0x3499, 0x0078, - 0x349b, 0x2001, 0x4006, 0x2020, 0x0078, 0x2baf, 0x2d00, 0x7022, - 0x017e, 0x0b7e, 0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x76c7, 0x0040, - 0x34e4, 0x2d00, 0x601a, 0x2001, 0xa757, 0x2004, 0xa084, 0x00ff, - 0x6842, 0x2e58, 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, - 0x2b70, 0x00c0, 0x34c5, 0x1078, 0x772d, 0x0e7f, 0x0c7f, 0x0b7f, - 0x017f, 0x2009, 0x0002, 0x0078, 0x2bd7, 0x6837, 0x0000, 0x2d00, - 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, - 0x8000, 0x1078, 0x2880, 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, - 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x2009, 0x0002, - 0x1078, 0x775c, 0xa085, 0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, - 0x00c0, 0x34ee, 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, - 0x701b, 0x34f3, 0x007c, 0x6830, 0xa086, 0x0100, 0x7020, 0x2060, - 0x00c0, 0x3501, 0x2009, 0x0004, 0x6204, 0xa294, 0x00ff, 0x0078, - 0x2bd7, 0x2009, 0x0000, 0x1078, 0x489b, 0x00c0, 0x3508, 0xc185, - 0x6000, 0xd0bc, 0x0040, 0x350d, 0xc18d, 0x0078, 0x2bad, 0x0e7e, - 0x0d7e, 0x2029, 0x0000, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, - 0xa8b5, 0x2e04, 0xa005, 0x00c0, 0x3524, 0x2100, 0xa406, 0x00c0, - 0x3555, 0x2428, 0x0078, 0x3555, 0x2068, 0x6f10, 0x2700, 0xa306, - 0x00c0, 0x3546, 0x6e14, 0x2600, 0xa206, 0x00c0, 0x3546, 0x2400, - 0xa106, 0x00c0, 0x3542, 0x2d60, 0xd884, 0x0040, 0x356a, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x356a, 0x2001, 0x4000, - 0x0078, 0x356b, 0x2001, 0x4007, 0x0078, 0x356b, 0x2400, 0xa106, - 0x00c0, 0x3555, 0x6e14, 0x87ff, 0x00c0, 0x3551, 0x86ff, 0x0040, - 0x3521, 0x2001, 0x4008, 0x0078, 0x356b, 0x8420, 0x8e70, 0x00f0, - 0x3519, 0x85ff, 0x00c0, 0x3564, 0x2001, 0x4009, 0x0078, 0x356b, - 0x2001, 0x0001, 0x0078, 0x356b, 0x1078, 0x455c, 0x00c0, 0x3560, - 0x6312, 0x6216, 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, - 0x00c0, 0x2bd7, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x6837, 0x0000, - 0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005, 0x0040, 0x2bdb, 0xa096, - 0x00ff, 0x0040, 0x3587, 0xa092, 0x0004, 0x00c8, 0x2bdb, 0x2010, - 0x2d18, 0x1078, 0x282f, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, - 0x3592, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, 0x0078, - 0x2bad, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, - 0x2bdb, 0xa182, 0x00ff, 0x00c8, 0x2bdb, 0x127e, 0x2091, 0x8000, - 0x1078, 0x8d5b, 0x00c0, 0x35b7, 0xa190, 0xa835, 0x2204, 0xa065, - 0x0040, 0x35b7, 0x1078, 0x42f8, 0x127f, 0x0078, 0x2bad, 0x127f, - 0x0078, 0x2bd7, 0x1078, 0x138b, 0x0040, 0x35d1, 0xa006, 0x6802, - 0x7010, 0xa005, 0x00c0, 0x35c9, 0x2d00, 0x7012, 0x7016, 0x0078, - 0x35cf, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, - 0x000d, 0x007c, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x45c4, - 0x00c0, 0x35e1, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, - 0x35e2, 0xa066, 0x8cff, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, - 0x1078, 0x45c4, 0x00c0, 0x35f2, 0xa6b4, 0x00ff, 0xa682, 0x4000, - 0x0048, 0x35f3, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, - 0x0040, 0x3600, 0x2168, 0x6904, 0x1078, 0x13a4, 0x0078, 0x35f7, - 0x7112, 0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x360a, - 0x2031, 0x0000, 0x2061, 0xa7d2, 0x6606, 0x6112, 0x600e, 0x6226, - 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, - 0x701b, 0x2bad, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, - 0x0000, 0x2001, 0xa790, 0x2004, 0xa005, 0x00c0, 0x3636, 0x0068, - 0x3636, 0x7818, 0xd084, 0x00c0, 0x3636, 0x7a22, 0x7b26, 0x7c2a, - 0x781b, 0x0001, 0x2091, 0x4080, 0x0078, 0x365b, 0x017e, 0x0c7e, - 0x0e7e, 0x2071, 0xa782, 0x7138, 0xa182, 0x0008, 0x0048, 0x3644, - 0x7030, 0x2060, 0x0078, 0x3655, 0x7030, 0xa0e0, 0x0008, 0xac82, - 0xa7d2, 0x0048, 0x364d, 0x2061, 0xa792, 0x2c00, 0x7032, 0x81ff, - 0x00c0, 0x3653, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, - 0x0e7f, 0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, - 0xa782, 0x7038, 0xa005, 0x0040, 0x3697, 0x127e, 0x2091, 0x8000, - 0x0068, 0x3696, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, - 0x3695, 0x0c7e, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, - 0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, - 0x703a, 0xa005, 0x00c0, 0x368b, 0x7033, 0xa792, 0x7037, 0xa792, - 0x0c7f, 0x0078, 0x3695, 0xac80, 0x0008, 0xa0fa, 0xa7d2, 0x0048, - 0x3693, 0x2001, 0xa792, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, - 0x007c, 0x027e, 0x2001, 0xa753, 0x2004, 0xd0c4, 0x0040, 0x36a4, - 0x2011, 0x8014, 0x1078, 0x361b, 0x027f, 0x007c, 0x81ff, 0x00c0, - 0x2bd7, 0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, - 0x6032, 0x1078, 0x4224, 0x127f, 0x0078, 0x2bad, 0x81ff, 0x00c0, - 0x2bd7, 0x6000, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x2001, 0xa753, - 0x2004, 0xd0ac, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x36d3, 0x7828, - 0xa005, 0x0040, 0x2bad, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, 0x0040, - 0x2bd7, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x1078, 0x8f22, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x36e9, - 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, 0x0078, 0x2bad, - 0x2001, 0xa700, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x7f24, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x35ba, 0x0040, 0x2bd7, - 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, - 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078, 0x45c4, 0x00c0, 0x376d, - 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0040, 0x371d, 0xa0c4, - 0xff00, 0xa8c6, 0x0600, 0x00c0, 0x376d, 0x2001, 0xa753, 0x2004, - 0xd0ac, 0x00c0, 0x372a, 0x1078, 0x489b, 0x00c0, 0x372a, 0xd79c, - 0x0040, 0x376d, 0xd794, 0x00c0, 0x3730, 0xd784, 0x0040, 0x373c, - 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078, - 0x3426, 0xd794, 0x0040, 0x3745, 0xac80, 0x000a, 0x2098, 0x3400, - 0x20a9, 0x0004, 0x53a3, 0x1078, 0x3426, 0x21a2, 0xd794, 0x0040, - 0x3765, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3, - 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400, - 0x20a9, 0x0002, 0x53a3, 0x1078, 0x3418, 0xac80, 0x0026, 0x2098, - 0x20a9, 0x0002, 0x53a3, 0x0078, 0x3766, 0x94a0, 0xd794, 0x0040, - 0x376b, 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0xd78c, 0x0040, - 0x3777, 0xa186, 0x0100, 0x0040, 0x3788, 0x0078, 0x377b, 0xa186, - 0x007e, 0x0040, 0x3788, 0xd794, 0x0040, 0x3782, 0xa686, 0x0020, - 0x0078, 0x3784, 0xa686, 0x0028, 0x0040, 0x3791, 0x0078, 0x370c, - 0x86ff, 0x00c0, 0x378f, 0x7120, 0x810b, 0x0078, 0x2bad, 0x702f, - 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xa7d2, - 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, - 0x6532, 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, 0x701b, 0x37a9, - 0x007c, 0x702c, 0xa005, 0x00c0, 0x37bb, 0x711c, 0x7024, 0x20a0, - 0x7728, 0x2031, 0x0000, 0x2061, 0xa7d2, 0x6224, 0x6328, 0x642c, - 0x6530, 0x0078, 0x370c, 0x7120, 0x810b, 0x0078, 0x2bad, 0x2029, - 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, - 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa184, - 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, - 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, - 0x0048, 0x2bdb, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, - 0xa502, 0x0048, 0x2bdb, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, - 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa384, 0x00ff, 0xa0e2, - 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa484, 0xff00, - 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, - 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, - 0x2bdb, 0x2061, 0xa9a5, 0x6102, 0x6206, 0x630a, 0x640e, 0x0078, - 0x2bad, 0x007e, 0x2001, 0xa753, 0x2004, 0xd0cc, 0x007f, 0x007c, - 0x007e, 0x2001, 0xa772, 0x2004, 0xd0bc, 0x007f, 0x007c, 0x6164, - 0x7a24, 0x6300, 0x82ff, 0x00c0, 0x3830, 0x7926, 0x0078, 0x2bad, - 0x83ff, 0x00c0, 0x2bdb, 0x2001, 0xfff0, 0xa200, 0x00c8, 0x2bdb, - 0x2019, 0xffff, 0x6068, 0xa302, 0xa200, 0x0048, 0x2bdb, 0x7926, - 0x6266, 0x0078, 0x2bad, 0x2001, 0xa700, 0x2004, 0xa086, 0x0003, - 0x00c0, 0x2bd7, 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x1078, 0x35ba, - 0x0040, 0x2bd7, 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, - 0x702f, 0x0000, 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xa835, - 0x2c64, 0x8cff, 0x0040, 0x387d, 0x6004, 0xa084, 0x00ff, 0xa086, - 0x0006, 0x0040, 0x3872, 0x6004, 0xa084, 0xff00, 0xa086, 0x0600, - 0x00c0, 0x387d, 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007, 0xa105, - 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182, 0x00ff, - 0x0040, 0x3888, 0xa386, 0x002a, 0x0040, 0x3891, 0x0078, 0x385e, - 0x83ff, 0x00c0, 0x388f, 0x7120, 0x810c, 0x0078, 0x2bad, 0x702f, - 0x0001, 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0xa7d2, 0x6007, - 0x0000, 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, - 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, 0x701b, 0x38a8, 0x007c, - 0x702c, 0xa005, 0x00c0, 0x38b9, 0x711c, 0x7024, 0x20a0, 0x2019, - 0x0000, 0x2061, 0xa7d2, 0x6424, 0x6528, 0x662c, 0x6730, 0x0078, - 0x385e, 0x7120, 0x810c, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, - 0x60cc, 0xd09c, 0x0040, 0x2bd7, 0x1078, 0x35ba, 0x0040, 0x2bd7, - 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, 0x701b, - 0x38d2, 0x007c, 0x0d7e, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, - 0x0040, 0x38e5, 0xa0be, 0x7100, 0x0040, 0x38e5, 0xa0be, 0x7200, - 0x0040, 0x38e5, 0x0d7f, 0x0078, 0x2bdb, 0x6820, 0x6924, 0x1078, - 0x254d, 0x00c0, 0x3910, 0x1078, 0x455c, 0x00c0, 0x3910, 0x7122, - 0x6612, 0x6516, 0x6e18, 0x0c7e, 0x1078, 0x35ba, 0x0040, 0x3910, - 0x1078, 0x35ba, 0x0040, 0x3910, 0x0c7f, 0x0d7f, 0x6837, 0x0000, - 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x1078, - 0x8e92, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x3913, 0x007c, - 0x0d7f, 0x0078, 0x2bd7, 0x7120, 0x1078, 0x298e, 0x6820, 0xa086, - 0x8001, 0x0040, 0x2bd7, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, - 0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x1078, 0x4281, 0x007f, - 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xa7d2, - 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x00c0, 0x393a, - 0x0078, 0x393e, 0xa7c6, 0x7100, 0x00c0, 0x3946, 0xa6c2, 0x0004, - 0x0048, 0x2bdb, 0x2009, 0x0004, 0x0078, 0x3608, 0xa7c6, 0x7200, - 0x00c0, 0x2bdb, 0xa6c2, 0x0054, 0x0048, 0x2bdb, 0x600e, 0x6013, - 0x002a, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13db, - 0x7007, 0x0002, 0x701b, 0x395d, 0x007c, 0x701c, 0x2068, 0x6804, - 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x007e, 0x20a9, 0x002a, - 0x2098, 0x20a0, 0x1078, 0x4281, 0x007f, 0x2009, 0x002a, 0x2061, - 0xa7d2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x3608, 0x81ff, - 0x00c0, 0x2bd7, 0x792c, 0x2001, 0xa99d, 0x2102, 0x1078, 0x35d2, - 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, 0x127e, 0x2091, - 0x8000, 0x1078, 0x47de, 0x127f, 0x0078, 0x2bad, 0x7824, 0xd08c, - 0x00c0, 0x3995, 0xd084, 0x0040, 0x31da, 0x1078, 0x35e4, 0x0040, - 0x2bdb, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, 0x00c0, 0x39a3, 0x2009, - 0x0002, 0x0078, 0x2bd7, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, - 0x0040, 0x39b0, 0xa08e, 0x0004, 0x0040, 0x39b0, 0xa08e, 0x0005, - 0x00c0, 0x39dd, 0x7824, 0xd08c, 0x0040, 0x39bb, 0x6000, 0xc08c, - 0x6002, 0x0078, 0x39c5, 0x2001, 0xa753, 0x2004, 0xd0b4, 0x0040, - 0x320f, 0x6000, 0xd08c, 0x00c0, 0x320f, 0x6837, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x1078, 0x8eae, 0x00c0, 0x39d2, 0x2009, 0x0003, - 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x39d7, 0x007c, 0x1078, - 0x35e4, 0x0040, 0x2bdb, 0x0078, 0x320f, 0x2009, 0xa72f, 0x210c, - 0x81ff, 0x0040, 0x39e7, 0x2009, 0x0001, 0x0078, 0x2bd7, 0x2001, - 0xa700, 0x2004, 0xa086, 0x0003, 0x0040, 0x39f2, 0x2009, 0x0007, - 0x0078, 0x2bd7, 0x2001, 0xa753, 0x2004, 0xd0ac, 0x0040, 0x39fc, - 0x2009, 0x0008, 0x0078, 0x2bd7, 0x609c, 0xd0a4, 0x00c0, 0x3a03, - 0xd0ac, 0x00c0, 0x320f, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x1078, 0x8f22, 0x00c0, 0x3a12, 0x2009, 0x0003, - 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x3a17, 0x007c, 0x6830, - 0xa086, 0x0100, 0x00c0, 0x3a20, 0x2009, 0x0004, 0x0078, 0x2bd7, - 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x0078, 0x39b2, 0x81ff, 0x2009, - 0x0001, 0x00c0, 0x2bd7, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, - 0x00c0, 0x2bd7, 0x2001, 0xa753, 0x2004, 0xd0ac, 0x2009, 0x0008, - 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x00c0, 0x2bd7, 0x0c7e, - 0x1078, 0x35ba, 0x0c7f, 0x2009, 0x0002, 0x0040, 0x2bd7, 0x6837, - 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, - 0xff00, 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x00c0, 0x3a65, 0xc0ed, - 0x6952, 0x792c, 0x6956, 0x0078, 0x3a6e, 0xa28e, 0x0100, 0x00c0, - 0x2bdb, 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, 0x683e, 0x1078, - 0x90cd, 0x2009, 0x0003, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, - 0x3a7a, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040, - 0x2bd7, 0x0078, 0x2bad, 0x81ff, 0x2009, 0x0001, 0x00c0, 0x2bd7, - 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0, 0x2bd7, 0x1078, - 0x35e4, 0x0040, 0x2bdb, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, - 0x2009, 0x0009, 0x00c0, 0x2bd7, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, - 0x2009, 0x0002, 0x0040, 0x2bd7, 0xad80, 0x000f, 0x2009, 0x0008, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, 0x701b, 0x3ab1, - 0x007c, 0x0d7e, 0xade8, 0x000f, 0x6800, 0xa086, 0x0500, 0x00c0, - 0x3ac4, 0x6804, 0xa005, 0x00c0, 0x3ac4, 0x6808, 0xa084, 0xff00, - 0x00c0, 0x3ac4, 0x0078, 0x3ac7, 0x0d7f, 0x00c0, 0x2bdb, 0x0d7f, - 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x0c7e, - 0x1078, 0x35e4, 0x00c0, 0x3ad7, 0x0c7f, 0x0078, 0x2bdb, 0x1078, - 0x9129, 0x2009, 0x0003, 0x0c7f, 0x0040, 0x2bd7, 0x7007, 0x0003, - 0x701b, 0x3ae3, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, - 0x0040, 0x2bd7, 0x0078, 0x2bad, 0x127e, 0x0c7e, 0x0e7e, 0x2061, - 0x0100, 0x2071, 0xa700, 0x6044, 0xd0a4, 0x00c0, 0x3b15, 0xd084, - 0x0040, 0x3afe, 0x1078, 0x3c75, 0x0078, 0x3b11, 0xd08c, 0x0040, - 0x3b05, 0x1078, 0x3b8c, 0x0078, 0x3b11, 0xd094, 0x0040, 0x3b0c, - 0x1078, 0x3b60, 0x0078, 0x3b11, 0xd09c, 0x0040, 0x3b11, 0x1078, - 0x3b1f, 0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, - 0x00c0, 0x3b1c, 0xc19d, 0x612a, 0x017f, 0x0078, 0x3b11, 0x624c, - 0xa286, 0xf0f0, 0x00c0, 0x3b30, 0x6048, 0xa086, 0xf0f0, 0x0040, - 0x3b30, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x3b5f, - 0xa294, 0xff00, 0xa296, 0xf700, 0x0040, 0x3b45, 0x7134, 0xd1a4, - 0x00c0, 0x3b45, 0x6240, 0xa294, 0x0010, 0x0040, 0x3b45, 0x2009, - 0x00f7, 0x1078, 0x42a1, 0x0078, 0x3b5f, 0x6043, 0x0040, 0x6043, - 0x0000, 0x7077, 0x0000, 0x708f, 0x0001, 0x70b3, 0x0000, 0x70cf, - 0x0000, 0x2009, 0xadc0, 0x200b, 0x0000, 0x7087, 0x0000, 0x707b, - 0x000f, 0x2009, 0x000f, 0x2011, 0x41d5, 0x1078, 0x5add, 0x007c, - 0x157e, 0x7078, 0xa005, 0x00c0, 0x3b8a, 0x2011, 0x41d5, 0x1078, - 0x5a45, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, - 0x00c8, 0x6044, 0xd08c, 0x00c0, 0x3b83, 0x00f0, 0x3b71, 0x6242, - 0x708b, 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, - 0x6242, 0x0078, 0x3b8a, 0x6242, 0x708b, 0x0000, 0x707f, 0x0000, - 0x0078, 0x3b8a, 0x157f, 0x007c, 0x707c, 0xa08a, 0x0003, 0x00c8, - 0x3b95, 0x1079, 0x3b98, 0x0078, 0x3b97, 0x1078, 0x1332, 0x007c, - 0x3b9b, 0x3bea, 0x3c74, 0x0f7e, 0x707f, 0x0001, 0x20e1, 0xa000, - 0x20e1, 0x8700, 0x1078, 0x21f7, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x2079, 0xac00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, - 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, - 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, - 0x782f, 0x0000, 0x2079, 0xac0c, 0x207b, 0x1101, 0x7807, 0x0000, - 0x2099, 0xa705, 0x20a1, 0xac0e, 0x20a9, 0x0004, 0x53a3, 0x2079, - 0xac12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xac00, 0x20a1, - 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, - 0x1078, 0x420b, 0x0f7f, 0x7083, 0x0000, 0x6043, 0x0008, 0x6043, - 0x0000, 0x007c, 0x0d7e, 0x7080, 0x7083, 0x0000, 0xa025, 0x0040, - 0x3c5e, 0x6020, 0xd0b4, 0x00c0, 0x3c5c, 0x718c, 0x81ff, 0x0040, - 0x3c4b, 0xa486, 0x000c, 0x00c0, 0x3c56, 0xa480, 0x0018, 0x8004, - 0x20a8, 0x2011, 0xac80, 0x2019, 0xac00, 0x220c, 0x2304, 0xa106, - 0x00c0, 0x3c22, 0x8210, 0x8318, 0x00f0, 0x3c05, 0x6043, 0x0004, - 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707f, 0x0002, - 0x708b, 0x0002, 0x2009, 0x07d0, 0x2011, 0x41dc, 0x1078, 0x5add, - 0x0078, 0x3c5c, 0x2069, 0xac80, 0x6930, 0xa18e, 0x1101, 0x00c0, - 0x3c56, 0x6834, 0xa005, 0x00c0, 0x3c56, 0x6900, 0xa18c, 0x00ff, - 0x00c0, 0x3c36, 0x6804, 0xa005, 0x0040, 0x3c4b, 0x2011, 0xac8e, - 0x2019, 0xa705, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0048, - 0x3c49, 0x00c0, 0x3c56, 0x8210, 0x8318, 0x00f0, 0x3c3c, 0x0078, - 0x3c56, 0x708f, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, - 0xac80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, - 0x6043, 0x0000, 0x0078, 0x3c5e, 0x0d7f, 0x007c, 0x6020, 0xd0b4, - 0x00c0, 0x3c5c, 0x60c3, 0x000c, 0x2011, 0xa9bb, 0x2013, 0x0000, - 0x7083, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, - 0x1078, 0x6e06, 0x0078, 0x3c5c, 0x007c, 0x7088, 0xa08a, 0x001d, - 0x00c8, 0x3c7e, 0x1079, 0x3c81, 0x0078, 0x3c80, 0x1078, 0x1332, - 0x007c, 0x3cab, 0x3cba, 0x3ce9, 0x3d02, 0x3d2e, 0x3d5a, 0x3d86, - 0x3dbc, 0x3de8, 0x3e10, 0x3e53, 0x3e7d, 0x3e9f, 0x3eb5, 0x3edb, - 0x3eee, 0x3ef7, 0x3f2b, 0x3f57, 0x3f83, 0x3faf, 0x3fe5, 0x4030, - 0x405f, 0x4081, 0x40c3, 0x40e9, 0x4102, 0x4103, 0x0c7e, 0x2061, - 0xa700, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, - 0x6006, 0x0c7f, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, - 0x0002, 0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x41dc, 0x1078, - 0x5add, 0x007c, 0x0f7e, 0x7080, 0xa086, 0x0014, 0x00c0, 0x3ce7, - 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3ce7, 0x2079, 0xac80, - 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3ce5, 0x7834, 0xa005, 0x00c0, - 0x3ce5, 0x7a38, 0xd2fc, 0x0040, 0x3cdb, 0x70b0, 0xa005, 0x00c0, - 0x3cdb, 0x70b3, 0x0001, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x708b, - 0x0010, 0x1078, 0x3ef7, 0x0078, 0x3ce7, 0x1078, 0x4224, 0x0f7f, - 0x007c, 0x708b, 0x0003, 0x6043, 0x0004, 0x2011, 0x41dc, 0x1078, - 0x5a45, 0x1078, 0x4289, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, - 0x000a, 0x20a3, 0x0000, 0x00f0, 0x3cf9, 0x60c3, 0x0014, 0x1078, - 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3d2c, 0x2011, - 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3d2a, 0x2079, - 0xac80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3d2a, 0x7834, 0xa005, - 0x00c0, 0x3d2a, 0x7a38, 0xd2fc, 0x0040, 0x3d24, 0x70b0, 0xa005, - 0x00c0, 0x3d24, 0x70b3, 0x0001, 0x708b, 0x0004, 0x1078, 0x3d2e, - 0x0078, 0x3d2c, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, 0x0005, - 0x1078, 0x4289, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, - 0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3d4c, 0x7074, 0xa005, 0x00c0, - 0x3d4c, 0x7150, 0xa186, 0xffff, 0x0040, 0x3d4c, 0x1078, 0x419d, - 0x0040, 0x3d4c, 0x1078, 0x42b8, 0x20a9, 0x0008, 0x2298, 0x26a0, - 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, - 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3d84, 0x2011, - 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3d82, 0x2079, - 0xac80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3d82, 0x7834, 0xa005, - 0x00c0, 0x3d82, 0x7a38, 0xd2fc, 0x0040, 0x3d7c, 0x70b0, 0xa005, - 0x00c0, 0x3d7c, 0x70b3, 0x0001, 0x708b, 0x0006, 0x1078, 0x3d86, - 0x0078, 0x3d84, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, 0x0007, - 0x1078, 0x4289, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, - 0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3dae, 0x7074, 0xa005, 0x00c0, - 0x3dae, 0x7154, 0xa186, 0xffff, 0x0040, 0x3dae, 0xa180, 0x29c0, - 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x419d, 0x0040, 0x3dae, - 0x1078, 0x3820, 0x0040, 0x3dae, 0x1078, 0x256a, 0x20a9, 0x0008, - 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, - 0x3de6, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, - 0x3de4, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3de4, - 0x7834, 0xa005, 0x00c0, 0x3de4, 0x7a38, 0xd2fc, 0x0040, 0x3dde, - 0x70b0, 0xa005, 0x00c0, 0x3dde, 0x70b3, 0x0001, 0x708b, 0x0008, - 0x1078, 0x3de8, 0x0078, 0x3de6, 0x1078, 0x4224, 0x0f7f, 0x007c, - 0x708b, 0x0009, 0x1078, 0x4289, 0x20a3, 0x1105, 0x20a3, 0x0100, - 0x3430, 0x1078, 0x42d4, 0x00c0, 0x3e01, 0x7074, 0xa005, 0x00c0, - 0x3e01, 0x1078, 0x4104, 0x00c0, 0x3e0b, 0xa085, 0x0001, 0x1078, - 0x256a, 0x20a9, 0x0008, 0x2099, 0xac8e, 0x26a0, 0x53a6, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, - 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3e51, 0x2011, 0x41dc, 0x1078, - 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3e4f, 0x2079, 0xac80, 0x7a30, - 0xa296, 0x1105, 0x00c0, 0x3e4f, 0x7834, 0x2011, 0x0100, 0xa21e, - 0x00c0, 0x3e3a, 0x7a38, 0xd2fc, 0x0040, 0x3e34, 0x70b0, 0xa005, - 0x00c0, 0x3e34, 0x70b3, 0x0001, 0x708b, 0x000a, 0x1078, 0x3e53, - 0x0078, 0x3e51, 0xa005, 0x00c0, 0x3e4f, 0x7a38, 0xd2fc, 0x0040, - 0x3e47, 0x70b0, 0xa005, 0x00c0, 0x3e47, 0x70b3, 0x0001, 0x7087, - 0x0000, 0x708b, 0x000e, 0x1078, 0x3edb, 0x0078, 0x3e51, 0x1078, - 0x4224, 0x0f7f, 0x007c, 0x708b, 0x000b, 0x2011, 0xac0e, 0x22a0, - 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, - 0x0000, 0x41a4, 0x1078, 0x4289, 0x20a3, 0x1106, 0x20a3, 0x0000, - 0x1078, 0x42d4, 0x0040, 0x3e70, 0x2013, 0x0000, 0x0078, 0x3e74, - 0x6030, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, - 0x60c3, 0x0084, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, - 0x0040, 0x3e9d, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, - 0x00c0, 0x3e9b, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1106, 0x00c0, - 0x3e9b, 0x7834, 0xa005, 0x00c0, 0x3e9b, 0x708b, 0x000c, 0x1078, - 0x3e9f, 0x0078, 0x3e9d, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, - 0x000d, 0x1078, 0x4289, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, - 0xac8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0084, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, - 0x0040, 0x3ed9, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, - 0x00c0, 0x3ed7, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1107, 0x00c0, - 0x3ed7, 0x7834, 0xa005, 0x00c0, 0x3ed7, 0x7087, 0x0001, 0x1078, - 0x427b, 0x708b, 0x000e, 0x1078, 0x3edb, 0x0078, 0x3ed9, 0x1078, - 0x4224, 0x0f7f, 0x007c, 0x708b, 0x000f, 0x7083, 0x0000, 0x608b, - 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, - 0x07d0, 0x2011, 0x41dc, 0x1078, 0x5a38, 0x007c, 0x7080, 0xa005, - 0x0040, 0x3ef6, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x007c, 0x708b, - 0x0011, 0x1078, 0x42d4, 0x00c0, 0x3f14, 0x716c, 0x81ff, 0x0040, - 0x3f14, 0x2009, 0x0000, 0x7070, 0xa084, 0x00ff, 0x1078, 0x254d, - 0xa186, 0x007e, 0x0040, 0x3f14, 0xa186, 0x0080, 0x0040, 0x3f14, - 0x2011, 0xac8e, 0x1078, 0x419d, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x2099, 0xac80, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, - 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, - 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3f55, - 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3f53, - 0x2079, 0xac80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3f53, 0x7834, - 0xa005, 0x00c0, 0x3f53, 0x7a38, 0xd2fc, 0x0040, 0x3f4d, 0x70b0, - 0xa005, 0x00c0, 0x3f4d, 0x70b3, 0x0001, 0x708b, 0x0012, 0x1078, - 0x3f57, 0x0078, 0x3f55, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, - 0x0013, 0x1078, 0x4295, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, - 0x2011, 0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3f75, 0x7074, 0xa005, - 0x00c0, 0x3f75, 0x7150, 0xa186, 0xffff, 0x0040, 0x3f75, 0x1078, - 0x419d, 0x0040, 0x3f75, 0x1078, 0x42b8, 0x20a9, 0x0008, 0x2298, - 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, - 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3fad, - 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3fab, - 0x2079, 0xac80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3fab, 0x7834, - 0xa005, 0x00c0, 0x3fab, 0x7a38, 0xd2fc, 0x0040, 0x3fa5, 0x70b0, - 0xa005, 0x00c0, 0x3fa5, 0x70b3, 0x0001, 0x708b, 0x0014, 0x1078, - 0x3faf, 0x0078, 0x3fad, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, - 0x0015, 0x1078, 0x4295, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, - 0x2011, 0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3fd7, 0x7074, 0xa005, - 0x00c0, 0x3fd7, 0x7154, 0xa186, 0xffff, 0x0040, 0x3fd7, 0xa180, - 0x29c0, 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x419d, 0x0040, - 0x3fd7, 0x1078, 0x3820, 0x0040, 0x3fd7, 0x1078, 0x256a, 0x20a9, - 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, - 0x0040, 0x402e, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, - 0x00c0, 0x402c, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1105, 0x00c0, - 0x402c, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x400b, 0x7a38, - 0xd2fc, 0x0040, 0x4009, 0x70b0, 0xa005, 0x00c0, 0x4009, 0x70b3, - 0x0001, 0x0078, 0x401a, 0xa005, 0x00c0, 0x402c, 0x7a38, 0xd2fc, - 0x0040, 0x4018, 0x70b0, 0xa005, 0x00c0, 0x4018, 0x70b3, 0x0001, - 0x7087, 0x0000, 0x7a38, 0xd2f4, 0x0040, 0x4026, 0x2001, 0xa774, - 0x2004, 0xd0a4, 0x00c0, 0x4026, 0x70cf, 0x0008, 0x708b, 0x0016, - 0x1078, 0x4030, 0x0078, 0x402e, 0x1078, 0x4224, 0x0f7f, 0x007c, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xac80, 0x20a1, 0x020b, - 0x20a9, 0x000e, 0x53a6, 0x3430, 0x2011, 0xac8e, 0x708b, 0x0017, - 0x1078, 0x42d4, 0x00c0, 0x4050, 0x7074, 0xa005, 0x00c0, 0x4050, - 0x1078, 0x4104, 0x00c0, 0x405a, 0xa085, 0x0001, 0x1078, 0x256a, - 0x20a9, 0x0008, 0x2099, 0xac8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, - 0x7080, 0xa005, 0x0040, 0x407f, 0x2011, 0x41dc, 0x1078, 0x5a45, - 0xa086, 0x0084, 0x00c0, 0x407d, 0x2079, 0xac80, 0x7a30, 0xa296, - 0x1106, 0x00c0, 0x407d, 0x7834, 0xa005, 0x00c0, 0x407d, 0x708b, - 0x0018, 0x1078, 0x4081, 0x0078, 0x407f, 0x1078, 0x4224, 0x0f7f, - 0x007c, 0x708b, 0x0019, 0x1078, 0x4295, 0x20a3, 0x1106, 0x20a3, - 0x0000, 0x3430, 0x2099, 0xac8e, 0x2039, 0xac0e, 0x27a0, 0x20a9, - 0x0040, 0x53a3, 0x1078, 0x42d4, 0x00c0, 0x40b5, 0x2728, 0x2514, - 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, - 0xa205, 0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0, 0xac0e, 0x2414, - 0xa38c, 0x0001, 0x0040, 0x40b0, 0xa294, 0xff00, 0x0078, 0x40b3, - 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, - 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, - 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x40e7, - 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, 0x00c0, 0x40e5, - 0x2079, 0xac80, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x40e5, 0x7834, - 0xa005, 0x00c0, 0x40e5, 0x7087, 0x0001, 0x1078, 0x427b, 0x708b, - 0x001a, 0x1078, 0x40e9, 0x0078, 0x40e7, 0x1078, 0x4224, 0x0f7f, - 0x007c, 0x708b, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, - 0xac80, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, - 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078, - 0x420b, 0x007c, 0x007c, 0x007c, 0x087e, 0x097e, 0x2029, 0xa753, - 0x252c, 0x20a9, 0x0008, 0x2041, 0xac0e, 0x28a0, 0x2099, 0xac8e, - 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0040, 0x411a, - 0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0, - 0x412c, 0xd5d4, 0x0040, 0x4127, 0x8210, 0x0078, 0x4128, 0x8211, - 0x00f0, 0x411a, 0x0078, 0x4194, 0x82ff, 0x00c0, 0x413e, 0xd5d4, - 0x0040, 0x4138, 0xa1a6, 0x3fff, 0x0040, 0x4124, 0x0078, 0x413c, - 0xa1a6, 0x3fff, 0x0040, 0x4194, 0xa18d, 0xc000, 0x20a9, 0x0010, - 0x2019, 0x0001, 0xd5d4, 0x0040, 0x4147, 0x2019, 0x0010, 0x2120, - 0xd5d4, 0x0040, 0x414e, 0x8423, 0x0078, 0x414f, 0x8424, 0x00c8, - 0x415c, 0xd5d4, 0x0040, 0x4157, 0x8319, 0x0078, 0x4158, 0x8318, - 0x00f0, 0x4148, 0x0078, 0x4194, 0x23a8, 0x2021, 0x0001, 0x8426, - 0x8425, 0x00f0, 0x4160, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0040, - 0x4174, 0x007e, 0x2039, 0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8, - 0xa5a8, 0x0010, 0x00f0, 0x4170, 0x7552, 0xa5c8, 0x29c0, 0x292c, - 0xa5ac, 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0000, - 0x7572, 0x2018, 0x2304, 0xa405, 0x201a, 0x7077, 0x0001, 0x26a0, - 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0xa085, 0x0001, 0x0078, 0x419a, 0xa006, 0x0078, 0x419a, 0xa006, - 0x1078, 0x1332, 0x097f, 0x087f, 0x007c, 0x2118, 0x2021, 0x0000, - 0x2001, 0x0007, 0xa39a, 0x0010, 0x0048, 0x41aa, 0x8420, 0x8001, - 0x0078, 0x41a2, 0x2118, 0x84ff, 0x0040, 0x41b3, 0xa39a, 0x0010, - 0x8421, 0x00c0, 0x41ae, 0x2021, 0x0001, 0x83ff, 0x0040, 0x41bc, - 0x8423, 0x8319, 0x00c0, 0x41b8, 0xa238, 0x2704, 0xa42c, 0x00c0, - 0x41d4, 0xa405, 0x203a, 0x7152, 0xa1a0, 0x29c0, 0x242c, 0xa5ac, - 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0000, 0x7572, - 0x7077, 0x0001, 0xa084, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa700, - 0x707b, 0x0000, 0x0e7f, 0x007c, 0x0e7e, 0x0f7e, 0x2001, 0x0002, - 0x1078, 0x5ae6, 0x2079, 0x0100, 0x2071, 0x0140, 0x1078, 0x6e0f, - 0x7004, 0xa084, 0x4000, 0x0040, 0x41f1, 0x7003, 0x1000, 0x7003, - 0x0000, 0x127e, 0x2091, 0x8000, 0x2071, 0xa722, 0x2073, 0x0000, - 0x7840, 0x027e, 0x017e, 0x2009, 0x00f7, 0x1078, 0x42a1, 0x017f, - 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x027f, 0x127f, - 0x0f7f, 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x2011, 0xa9bb, - 0x2013, 0x0000, 0x7083, 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, - 0x0056, 0x60a7, 0x9575, 0x1078, 0x6e06, 0x2009, 0x07d0, 0x2011, - 0x41dc, 0x1078, 0x5add, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, - 0x2091, 0x8000, 0x2011, 0x0003, 0x1078, 0x70e0, 0x2011, 0x0002, - 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, 0x2019, 0x0000, 0x1078, - 0x7058, 0x037f, 0x2009, 0x00f7, 0x1078, 0x42a1, 0x2061, 0xa9c4, - 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0xa700, 0x6003, 0x0001, - 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, - 0x2011, 0x4259, 0x1078, 0x5a38, 0x127f, 0x0c7f, 0x027f, 0x017f, - 0x007c, 0x0e7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2001, 0x0001, - 0x1078, 0x5ae6, 0x2071, 0x0100, 0x1078, 0x6e0f, 0x2071, 0x0140, - 0x7004, 0xa084, 0x4000, 0x0040, 0x4271, 0x7003, 0x1000, 0x7003, - 0x0000, 0x2001, 0x0001, 0x1078, 0x24e8, 0x1078, 0x4224, 0x127f, - 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040, 0x20a1, 0xadc0, 0x2099, - 0xac8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x00f0, 0x4281, - 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xac00, 0x20a1, - 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x2099, 0xac80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, - 0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100, 0x810f, 0x2001, 0xa72f, - 0x2004, 0xa005, 0x00c0, 0x42b2, 0x6030, 0xa084, 0x00ff, 0xa105, - 0x0078, 0x42b4, 0xa185, 0x00f7, 0x604a, 0x007f, 0x0c7f, 0x007c, - 0x017e, 0x047e, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x42cb, - 0xa006, 0x2020, 0x2009, 0x002a, 0x1078, 0xa22d, 0x2001, 0xa70c, - 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x1078, - 0x284f, 0x047f, 0x017f, 0x007c, 0x007e, 0x2001, 0xa70c, 0x2004, - 0xd09c, 0x0040, 0x42db, 0x007f, 0x007c, 0x007e, 0x017e, 0x127e, - 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, - 0x127f, 0x017f, 0x007f, 0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009, - 0xa835, 0xa006, 0x200a, 0x8108, 0x00f0, 0x42f2, 0x157f, 0x007c, - 0x0d7e, 0x037e, 0x157e, 0x137e, 0x147e, 0x2069, 0xa752, 0xa006, - 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x29c0, - 0x231c, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, - 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, - 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, - 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, - 0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, - 0x61a2, 0x0d7e, 0x60a4, 0xa06d, 0x0040, 0x4338, 0x1078, 0x13a4, - 0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0040, 0x4340, 0x1078, 0x13a4, - 0x60ab, 0x0000, 0x0d7f, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c, - 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, - 0x037f, 0x0d7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x6944, 0x6e48, - 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, 0x4424, 0xa18c, 0xff00, - 0x810f, 0xa182, 0x00ff, 0x00c8, 0x442a, 0x2001, 0xa70c, 0x2004, - 0xa084, 0x0003, 0x0040, 0x4385, 0x2001, 0xa70c, 0x2004, 0xd084, - 0x00c0, 0x4405, 0xa188, 0xa835, 0x2104, 0xa065, 0x0040, 0x4405, - 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x4405, 0x6000, - 0xd0c4, 0x0040, 0x4405, 0x0078, 0x4392, 0xa188, 0xa835, 0x2104, - 0xa065, 0x0040, 0x43e9, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, - 0x00c0, 0x43ef, 0x60a4, 0xa00d, 0x0040, 0x439a, 0x1078, 0x4817, - 0x0040, 0x43e3, 0x60a8, 0xa00d, 0x0040, 0x43b4, 0x1078, 0x486a, - 0x00c0, 0x43b4, 0x694c, 0xd1fc, 0x00c0, 0x43aa, 0x1078, 0x44df, - 0x0078, 0x43de, 0x1078, 0x4484, 0x694c, 0xd1ec, 0x00c0, 0x43de, - 0x1078, 0x46d6, 0x0078, 0x43de, 0x694c, 0xa184, 0xa000, 0x0040, - 0x43ce, 0xd1ec, 0x0040, 0x43c7, 0xd1fc, 0x0040, 0x43c3, 0x1078, - 0x46e7, 0x0078, 0x43ca, 0x1078, 0x46e7, 0x0078, 0x43ce, 0xd1fc, - 0x0040, 0x43ce, 0x1078, 0x4484, 0x0078, 0x43de, 0x6050, 0xa00d, - 0x0040, 0x43d9, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0078, - 0x43de, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x1078, 0x5da9, - 0xa006, 0x127f, 0x007c, 0x2001, 0x0005, 0x2009, 0x0000, 0x0078, - 0x442e, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078, 0x442e, 0xa082, - 0x0006, 0x00c8, 0x4405, 0x60a0, 0xd0bc, 0x00c0, 0x4401, 0x6100, - 0xd1fc, 0x0040, 0x4392, 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, - 0x442e, 0x2001, 0x0028, 0x0078, 0x4420, 0x2009, 0xa70c, 0x210c, - 0xd18c, 0x0040, 0x440f, 0x2001, 0x0004, 0x0078, 0x4420, 0xd184, - 0x0040, 0x4416, 0x2001, 0x0004, 0x0078, 0x4420, 0x2001, 0x0029, - 0x6100, 0xd1fc, 0x0040, 0x4420, 0x2009, 0x1000, 0x0078, 0x442e, - 0x2009, 0x0000, 0x0078, 0x442e, 0x2001, 0x0029, 0x2009, 0x0000, - 0x0078, 0x442e, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x127f, - 0x007c, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, - 0x447e, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, 0x4464, - 0xa188, 0xa835, 0x2104, 0xa065, 0x0040, 0x4464, 0x6004, 0xa084, - 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x446a, 0x684c, 0xd0ec, 0x0040, - 0x4457, 0x1078, 0x46e7, 0x1078, 0x4484, 0x0078, 0x445f, 0x1078, - 0x4484, 0x684c, 0xd0fc, 0x0040, 0x445f, 0x1078, 0x46d6, 0x1078, - 0x472f, 0xa006, 0x0078, 0x4482, 0x2001, 0x0028, 0x2009, 0x0000, - 0x0078, 0x4482, 0xa082, 0x0006, 0x00c8, 0x4478, 0x6100, 0xd1fc, - 0x0040, 0x444d, 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, 0x4482, - 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x4482, 0x2001, 0x0029, - 0x2009, 0x0000, 0xa005, 0x007c, 0x127e, 0x2091, 0x8000, 0x6050, - 0xa00d, 0x0040, 0x4492, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, - 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, - 0x4490, 0x127e, 0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x44af, - 0x0e7e, 0x2071, 0xa9b1, 0x7004, 0xa086, 0x0002, 0x0040, 0x44b6, - 0x0e7f, 0x604c, 0x6802, 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, - 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x44ad, 0x701c, 0xac06, - 0x00c0, 0x44a8, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, - 0x0e7f, 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, - 0x0040, 0x44d1, 0x6800, 0xa005, 0x00c0, 0x44cf, 0x6052, 0x604e, - 0xad05, 0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x44de, 0x6800, - 0xa005, 0x00c0, 0x44dc, 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, - 0x0000, 0x6084, 0xa00d, 0x0040, 0x44e9, 0x2d00, 0x200a, 0x6086, - 0x007c, 0x2d00, 0x6086, 0x6082, 0x0078, 0x44e8, 0x127e, 0x0c7e, - 0x027e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, - 0x44fc, 0xc285, 0x0078, 0x44fd, 0xc284, 0x6202, 0x027f, 0x0c7f, - 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, - 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, 0x4521, 0x609c, 0xd0ac, - 0x0040, 0x4521, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x4521, - 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x00c0, 0x4521, 0x2011, - 0x0600, 0x007f, 0xa294, 0xff00, 0xa215, 0x6206, 0x007e, 0xa086, - 0x0006, 0x00c0, 0x4531, 0x6290, 0x82ff, 0x00c0, 0x4531, 0x1078, - 0x1332, 0x007f, 0x0c7f, 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, - 0x8000, 0x6218, 0x2260, 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, - 0x4553, 0x609c, 0xd0a4, 0x0040, 0x4553, 0x2001, 0xa753, 0x2004, - 0xd0ac, 0x00c0, 0x4553, 0xa284, 0x00ff, 0xa086, 0x0007, 0x00c0, - 0x4553, 0x2011, 0x0006, 0x007f, 0xa294, 0x00ff, 0x8007, 0xa215, - 0x6206, 0x0c7f, 0x127f, 0x007c, 0x027e, 0xa182, 0x00ff, 0x0048, - 0x4565, 0xa085, 0x0001, 0x0078, 0x457d, 0xa190, 0xa835, 0x2204, - 0xa065, 0x00c0, 0x457c, 0x017e, 0x0d7e, 0x1078, 0x1370, 0x2d60, - 0x0d7f, 0x017f, 0x0040, 0x4561, 0x2c00, 0x2012, 0x60a7, 0x0000, - 0x60ab, 0x0000, 0x1078, 0x42f8, 0xa006, 0x027f, 0x007c, 0x127e, - 0x2091, 0x8000, 0x027e, 0xa182, 0x00ff, 0x0048, 0x458b, 0xa085, - 0x0001, 0x0078, 0x45c1, 0x0d7e, 0xa190, 0xa835, 0x2204, 0xa06d, - 0x0040, 0x45bf, 0x2013, 0x0000, 0x0d7e, 0x0c7e, 0x2d60, 0x60a4, - 0xa06d, 0x0040, 0x459d, 0x1078, 0x13a4, 0x60a8, 0xa06d, 0x0040, - 0x45a3, 0x1078, 0x13a4, 0x0c7f, 0x0d7f, 0x0d7e, 0x0c7e, 0x68ac, - 0x2060, 0x8cff, 0x0040, 0x45bb, 0x600c, 0x007e, 0x6010, 0x2068, - 0x1078, 0x8d16, 0x0040, 0x45b6, 0x1078, 0x13b4, 0x1078, 0x772d, - 0x0c7f, 0x0078, 0x45a9, 0x0c7f, 0x0d7f, 0x1078, 0x13a4, 0x0d7f, - 0xa006, 0x027f, 0x127f, 0x007c, 0x017e, 0xa182, 0x00ff, 0x0048, - 0x45cd, 0xa085, 0x0001, 0x0078, 0x45d4, 0xa188, 0xa835, 0x2104, - 0xa065, 0x0040, 0x45c9, 0xa006, 0x017f, 0x007c, 0x0d7e, 0x157e, - 0x137e, 0x147e, 0x600b, 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, - 0x6002, 0x2069, 0xac8e, 0x6808, 0x605e, 0x6810, 0x6062, 0x6138, - 0xa10a, 0x0048, 0x45ec, 0x603a, 0x6814, 0x6066, 0x2099, 0xac96, - 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xac9a, - 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xacae, - 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, - 0x60a0, 0xa086, 0x007e, 0x00c0, 0x4611, 0x2069, 0xac8e, 0x690c, - 0x616e, 0xa182, 0x0211, 0x00c8, 0x4619, 0x2009, 0x0008, 0x0078, - 0x4643, 0xa182, 0x0259, 0x00c8, 0x4621, 0x2009, 0x0007, 0x0078, - 0x4643, 0xa182, 0x02c1, 0x00c8, 0x4629, 0x2009, 0x0006, 0x0078, - 0x4643, 0xa182, 0x0349, 0x00c8, 0x4631, 0x2009, 0x0005, 0x0078, - 0x4643, 0xa182, 0x0421, 0x00c8, 0x4639, 0x2009, 0x0004, 0x0078, - 0x4643, 0xa182, 0x0581, 0x00c8, 0x4641, 0x2009, 0x0003, 0x0078, - 0x4643, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, 0x0d7f, - 0x007c, 0x017e, 0x027e, 0x0e7e, 0x2071, 0xac8d, 0x2e04, 0x6896, - 0x2071, 0xac8e, 0x7004, 0x689a, 0x701c, 0x689e, 0x6a00, 0x2009, - 0xa772, 0x210c, 0xd0bc, 0x0040, 0x4663, 0xd1ec, 0x0040, 0x4663, - 0xc2ad, 0x0078, 0x4664, 0xc2ac, 0xd0c4, 0x0040, 0x466d, 0xd1e4, - 0x0040, 0x466d, 0xc2bd, 0x0078, 0x466e, 0xc2bc, 0x6a02, 0x0e7f, - 0x027f, 0x017f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, - 0xa06d, 0x0040, 0x4697, 0x6900, 0x81ff, 0x00c0, 0x46ab, 0x6a04, - 0xa282, 0x0010, 0x00c8, 0x46b0, 0xad88, 0x0004, 0x20a9, 0x0010, - 0x2104, 0xa086, 0xffff, 0x0040, 0x4692, 0x8108, 0x00f0, 0x4688, - 0x1078, 0x1332, 0x260a, 0x8210, 0x6a06, 0x0078, 0x46ab, 0x1078, - 0x138b, 0x0040, 0x46b0, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, - 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x00f0, 0x46a3, - 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, - 0xa006, 0x0078, 0x46ad, 0x127e, 0x2091, 0x8000, 0x0d7e, 0x60a4, - 0xa00d, 0x0040, 0x46d3, 0x2168, 0x6800, 0xa005, 0x00c0, 0x46cf, - 0x1078, 0x4817, 0x00c0, 0x46d3, 0x200b, 0xffff, 0x6804, 0xa08a, - 0x0002, 0x0048, 0x46cf, 0x8001, 0x6806, 0x0078, 0x46d3, 0x1078, - 0x13a4, 0x60a7, 0x0000, 0x0d7f, 0x127f, 0x007c, 0x127e, 0x2091, - 0x8000, 0x1078, 0x487f, 0x0078, 0x46df, 0x1078, 0x4484, 0x1078, - 0x4775, 0x00c0, 0x46dd, 0x1078, 0x472f, 0x127f, 0x007c, 0x0d7e, - 0x127e, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x0040, 0x470b, 0x6950, - 0x81ff, 0x00c0, 0x471f, 0x6a54, 0xa282, 0x0010, 0x00c8, 0x472c, - 0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0040, - 0x4706, 0x8108, 0x00f0, 0x46fc, 0x1078, 0x1332, 0x260a, 0x8210, - 0x6a56, 0x0078, 0x471f, 0x1078, 0x138b, 0x0040, 0x472c, 0x2d00, - 0x60aa, 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, - 0xffff, 0x8108, 0x00f0, 0x4717, 0x6857, 0x0001, 0x6e62, 0x0078, - 0x4723, 0x1078, 0x44df, 0x1078, 0x4739, 0x00c0, 0x4721, 0xa085, - 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x4729, 0x127e, - 0x2091, 0x8000, 0x1078, 0x5da9, 0x127f, 0x007c, 0xa01e, 0x0078, - 0x473b, 0x2019, 0x0001, 0xa00e, 0x127e, 0x2091, 0x8000, 0x604c, - 0x2068, 0x6000, 0xd0dc, 0x00c0, 0x4759, 0x8dff, 0x0040, 0x4770, - 0x83ff, 0x0040, 0x4751, 0x6848, 0xa606, 0x0040, 0x475e, 0x0078, - 0x4759, 0x683c, 0xa406, 0x00c0, 0x4759, 0x6840, 0xa506, 0x0040, - 0x475e, 0x2d08, 0x6800, 0x2068, 0x0078, 0x4745, 0x1078, 0x7233, - 0x6a00, 0x604c, 0xad06, 0x00c0, 0x4768, 0x624e, 0x0078, 0x476b, - 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x4770, 0x6152, 0x8dff, - 0x127f, 0x007c, 0xa01e, 0x0078, 0x4777, 0x2019, 0x0001, 0xa00e, - 0x6080, 0x2068, 0x8dff, 0x0040, 0x47a3, 0x83ff, 0x0040, 0x4786, - 0x6848, 0xa606, 0x0040, 0x4793, 0x0078, 0x478e, 0x683c, 0xa406, - 0x00c0, 0x478e, 0x6840, 0xa506, 0x0040, 0x4793, 0x2d08, 0x6800, - 0x2068, 0x0078, 0x477a, 0x6a00, 0x6080, 0xad06, 0x00c0, 0x479b, - 0x6282, 0x0078, 0x479e, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, - 0x47a3, 0x6186, 0x8dff, 0x007c, 0xa016, 0x1078, 0x4810, 0x00c0, - 0x47ab, 0x2011, 0x0001, 0x1078, 0x4863, 0x00c0, 0x47b1, 0xa295, - 0x0002, 0x007c, 0x1078, 0x489b, 0x0040, 0x47ba, 0x1078, 0x8dda, - 0x0078, 0x47bc, 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, 0x0040, - 0x47c5, 0x1078, 0x8d72, 0x0078, 0x47c7, 0xa085, 0x0001, 0x007c, - 0x1078, 0x489b, 0x0040, 0x47d0, 0x1078, 0x8dbc, 0x0078, 0x47d2, - 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, 0x0040, 0x47db, 0x1078, - 0x8d8e, 0x0078, 0x47dd, 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, - 0x0040, 0x47e6, 0x1078, 0x8df8, 0x0078, 0x47e8, 0xa085, 0x0001, - 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, - 0x0040, 0x4808, 0x6800, 0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x1078, 0x8f8d, 0x007e, 0x6000, 0xd0fc, 0x0040, 0x4802, - 0x1078, 0xa4fd, 0x007f, 0x1078, 0x4a73, 0x007f, 0x0078, 0x47ef, - 0x6083, 0x0000, 0x6087, 0x0000, 0x0d7f, 0x007f, 0x127f, 0x007c, - 0x60a4, 0xa00d, 0x00c0, 0x4817, 0xa085, 0x0001, 0x007c, 0x0e7e, - 0x2170, 0x7000, 0xa005, 0x00c0, 0x482c, 0x20a9, 0x0010, 0xae88, - 0x0004, 0x2104, 0xa606, 0x0040, 0x482c, 0x8108, 0x00f0, 0x4821, - 0xa085, 0x0001, 0x0078, 0x482d, 0xa006, 0x0e7f, 0x007c, 0x0d7e, - 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x00c0, 0x483d, 0x1078, - 0x138b, 0x0040, 0x484f, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807, - 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, - 0x00f0, 0x4845, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, - 0x0078, 0x484c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, - 0x0040, 0x4860, 0x60a7, 0x0000, 0x1078, 0x13a4, 0xa085, 0x0001, - 0x127f, 0x0d7f, 0x007c, 0x60a8, 0xa00d, 0x00c0, 0x486a, 0xa085, - 0x0001, 0x007c, 0x0e7e, 0x2170, 0x7050, 0xa005, 0x00c0, 0x487d, - 0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0040, 0x487d, - 0x8108, 0x00f0, 0x4874, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x127e, - 0x2091, 0x8000, 0x1078, 0x4863, 0x00c0, 0x4899, 0x200b, 0xffff, - 0x0d7e, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, 0x0048, 0x4894, - 0x8001, 0x6856, 0x0078, 0x4898, 0x1078, 0x13a4, 0x60ab, 0x0000, - 0x0d7f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e, 0x71b0, - 0x81ff, 0x00c0, 0x48b9, 0x71cc, 0xd19c, 0x0040, 0x48b9, 0x2001, - 0x007e, 0xa080, 0xa835, 0x2004, 0xa07d, 0x0040, 0x48b9, 0x7804, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x48b9, 0x7800, 0xc0ed, - 0x7802, 0x2079, 0xa752, 0x7804, 0xd0a4, 0x0040, 0x48df, 0x157e, - 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x45c4, - 0x00c0, 0x48d9, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, - 0x0040, 0x48d6, 0xa086, 0x0006, 0x00c0, 0x48d9, 0x6000, 0xc0ed, - 0x6002, 0x017f, 0x8108, 0x00f0, 0x48c5, 0x0c7f, 0x157f, 0x1078, - 0x4967, 0x0040, 0x48e8, 0x2001, 0xa9a1, 0x200c, 0x0078, 0x48f0, - 0x2079, 0xa752, 0x7804, 0xd0a4, 0x0040, 0x48f4, 0x2009, 0x07d0, - 0x2011, 0x48f6, 0x1078, 0x5add, 0x0f7f, 0x007c, 0x2011, 0x48f6, - 0x1078, 0x5a45, 0x1078, 0x4967, 0x0040, 0x491e, 0x2001, 0xa8b3, - 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xa753, - 0x2004, 0xd0a4, 0x0040, 0x4912, 0x2009, 0x07d0, 0x2011, 0x48f6, - 0x1078, 0x5add, 0x0e7e, 0x2071, 0xa700, 0x706f, 0x0000, 0x7073, - 0x0000, 0x1078, 0x2677, 0x0e7f, 0x0078, 0x4956, 0x157e, 0x0c7e, - 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x45c4, 0x00c0, - 0x4950, 0x6000, 0xd0ec, 0x0040, 0x4950, 0x047e, 0x62a0, 0xa294, - 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0xa22d, 0x6000, - 0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, - 0x6006, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, - 0x1078, 0x5e0a, 0x2009, 0x0000, 0x1078, 0x9f9b, 0x077f, 0x047f, - 0x017f, 0x8108, 0x00f0, 0x4924, 0x0c7f, 0x157f, 0x007c, 0x0c7e, - 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x7818, - 0x2004, 0xd0ac, 0x007c, 0x7818, 0x2004, 0xd0bc, 0x007c, 0x0f7e, - 0x2001, 0xa8b3, 0x2004, 0xa07d, 0x0040, 0x4970, 0x7800, 0xd0ec, - 0x0f7f, 0x007c, 0x127e, 0x027e, 0x2091, 0x8000, 0x007e, 0x62a0, - 0xa290, 0xa835, 0x2204, 0xac06, 0x10c0, 0x1332, 0x007f, 0x6200, - 0xa005, 0x0040, 0x4986, 0xc2fd, 0x0078, 0x4987, 0xc2fc, 0x6202, - 0x027f, 0x127f, 0x007c, 0x2011, 0xa733, 0x2204, 0xd0cc, 0x0040, - 0x4998, 0x2001, 0xa99f, 0x200c, 0x2011, 0x4999, 0x1078, 0x5add, - 0x007c, 0x2011, 0x4999, 0x1078, 0x5a45, 0x2011, 0xa733, 0x2204, - 0xc0cc, 0x2012, 0x007c, 0x2071, 0xa814, 0x7003, 0x0001, 0x7007, - 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, - 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, - 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xa97d, 0x7003, - 0xa814, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xa95d, 0x7013, - 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x007c, 0x017e, 0x0e7e, - 0x2071, 0xa935, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, - 0xa753, 0x2004, 0xd0fc, 0x00c0, 0x49e8, 0x2001, 0xa753, 0x2004, - 0xa00e, 0xd09c, 0x0040, 0x49e5, 0x8108, 0x7102, 0x0078, 0x4a3b, - 0x2001, 0xa772, 0x200c, 0xa184, 0x000f, 0x2009, 0xa773, 0x210c, - 0x0079, 0x49f2, 0x49dd, 0x4a13, 0x4a1b, 0x4a26, 0x4a2c, 0x49dd, - 0x49dd, 0x49dd, 0x4a02, 0x49dd, 0x49dd, 0x49dd, 0x49dd, 0x49dd, - 0x49dd, 0x49dd, 0x7003, 0x0004, 0x137e, 0x147e, 0x157e, 0x2099, - 0xa776, 0x20a1, 0xa986, 0x20a9, 0x0004, 0x53a3, 0x157f, 0x147f, - 0x137f, 0x0078, 0x4a3b, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, - 0x0002, 0x0078, 0x4a21, 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, - 0x0003, 0x7002, 0x7097, 0x0001, 0x0078, 0x4a38, 0x7007, 0x0122, - 0x2001, 0x0002, 0x0078, 0x4a30, 0x7007, 0x0121, 0x2001, 0x0003, - 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a, - 0xa184, 0x00ff, 0x7092, 0x0e7f, 0x017f, 0x007c, 0x0e7e, 0x2071, - 0xa814, 0x684c, 0xa005, 0x00c0, 0x4a4c, 0x7028, 0xc085, 0x702a, - 0xa085, 0x0001, 0x0078, 0x4a71, 0x6a60, 0x7236, 0x6b64, 0x733a, - 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, - 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, - 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, - 0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, - 0xa006, 0x0e7f, 0x007c, 0x0e7e, 0x027e, 0x6838, 0xd0fc, 0x00c0, - 0x4ac9, 0x6804, 0xa00d, 0x0040, 0x4a8f, 0x0d7e, 0x2071, 0xa700, - 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, - 0x00c0, 0x4a82, 0x702e, 0x70ac, 0xa200, 0x70ae, 0x0d7f, 0x2071, - 0xa814, 0x701c, 0xa005, 0x00c0, 0x4adb, 0x0068, 0x4ad9, 0x2071, - 0xa935, 0x7200, 0x82ff, 0x0040, 0x4ad9, 0x6934, 0xa186, 0x0103, - 0x00c0, 0x4aec, 0x6948, 0x6844, 0xa105, 0x00c0, 0x4acc, 0x2009, - 0x8020, 0x2200, 0x0079, 0x4aac, 0x4ad9, 0x4ab1, 0x4b09, 0x4b17, - 0x4ad9, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4ad9, 0x7122, - 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, - 0x2071, 0xa700, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, - 0x70ae, 0x027f, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, 0x00c0, - 0x4ad9, 0x6868, 0xa005, 0x00c0, 0x4ad9, 0x2009, 0x8020, 0x0078, - 0x4aa9, 0x2071, 0xa814, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, - 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x4ae9, 0x6902, 0x0078, - 0x4aea, 0x711e, 0x0078, 0x4ac9, 0xa18c, 0x00ff, 0xa186, 0x0017, - 0x0040, 0x4afa, 0xa186, 0x001e, 0x0040, 0x4afa, 0xa18e, 0x001f, - 0x00c0, 0x4ad9, 0x684c, 0xd0cc, 0x0040, 0x4ad9, 0x6850, 0xa084, - 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4ad9, 0x2009, 0x8021, 0x0078, - 0x4aa9, 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4ad9, 0x7186, - 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x4b27, 0x7084, - 0x8008, 0xa092, 0x000f, 0x00c8, 0x4ad9, 0x7186, 0xae90, 0x0003, - 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, - 0xa10a, 0x0048, 0x4ac0, 0x718c, 0x7084, 0xa10a, 0x0048, 0x4ac0, - 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4ac0, 0x2071, 0xa935, - 0x7000, 0xa086, 0x0002, 0x00c0, 0x4b47, 0x1078, 0x4dc3, 0x2071, - 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4ac0, 0x1078, - 0x4dee, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, - 0x4ac0, 0x007e, 0x684c, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, - 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0xa084, - 0x00ff, 0x684e, 0x007f, 0x684a, 0x6952, 0x007c, 0x2071, 0xa814, - 0x7004, 0x0079, 0x4b6b, 0x4b75, 0x4b86, 0x4d94, 0x4d95, 0x4dbc, - 0x4dc2, 0x4b76, 0x4d82, 0x4d23, 0x4da5, 0x007c, 0x127e, 0x2091, - 0x8000, 0x0068, 0x4b85, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, - 0x4080, 0x7007, 0x0001, 0x700b, 0x0000, 0x127f, 0x2069, 0xa9c4, - 0x6844, 0xa005, 0x0050, 0x4bae, 0x00c0, 0x4bae, 0x127e, 0x2091, - 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xa820, 0x2004, 0xa10a, - 0x0040, 0x4ba9, 0x0068, 0x4bad, 0x2069, 0x0000, 0x6818, 0xd084, - 0x00c0, 0x4bad, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, - 0x4080, 0x2069, 0xa9c4, 0x6847, 0xffff, 0x127f, 0x2069, 0xa700, - 0x6848, 0x6964, 0xa102, 0x2069, 0xa935, 0x688a, 0x6984, 0x701c, - 0xa06d, 0x0040, 0x4bc0, 0x81ff, 0x0040, 0x4c08, 0x0078, 0x4bd6, - 0x81ff, 0x0040, 0x4cda, 0x2071, 0xa935, 0x7184, 0x7088, 0xa10a, - 0x00c8, 0x4bd6, 0x7190, 0x2071, 0xa9c4, 0x7040, 0xa005, 0x0040, - 0x4bd6, 0x00d0, 0x4cda, 0x7142, 0x0078, 0x4cda, 0x2071, 0xa935, - 0x718c, 0x127e, 0x2091, 0x8000, 0x7084, 0xa10a, 0x0048, 0x4cf7, - 0x0068, 0x4c8c, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4c8c, - 0x2001, 0xffff, 0x2071, 0xa9c4, 0x7042, 0x2071, 0xa935, 0x7000, - 0xa086, 0x0002, 0x00c0, 0x4bfe, 0x1078, 0x4dc3, 0x2071, 0x0000, - 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4c8c, 0x1078, 0x4dee, - 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4c8c, - 0x2071, 0xa935, 0x7000, 0xa005, 0x0040, 0x4cb9, 0x6934, 0xa186, - 0x0103, 0x00c0, 0x4c8f, 0x684c, 0xd0bc, 0x00c0, 0x4cb9, 0x6948, - 0x6844, 0xa105, 0x00c0, 0x4cac, 0x2009, 0x8020, 0x2071, 0xa935, - 0x7000, 0x0079, 0x4c23, 0x4cb9, 0x4c71, 0x4c49, 0x4c5b, 0x4c28, - 0x137e, 0x147e, 0x157e, 0x2099, 0xa776, 0x20a1, 0xa986, 0x20a9, - 0x0004, 0x53a3, 0x157f, 0x147f, 0x137f, 0x2071, 0xa97d, 0xad80, - 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, - 0x2e10, 0x1078, 0x13db, 0x2071, 0xa814, 0x7007, 0x0009, 0x0078, - 0x4cda, 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4cda, 0xae90, - 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xa814, 0x1078, - 0x4e4c, 0x0078, 0x4cda, 0x7084, 0x8008, 0xa092, 0x000f, 0x00c8, - 0x4cda, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, - 0x6840, 0x2012, 0x7186, 0x2071, 0xa814, 0x1078, 0x4e4c, 0x0078, - 0x4cda, 0x127e, 0x2091, 0x8000, 0x0068, 0x4c8c, 0x2071, 0x0000, - 0x7018, 0xd084, 0x00c0, 0x4c8c, 0x7122, 0x683c, 0x7026, 0x6840, - 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x127f, 0x2071, 0xa814, - 0x1078, 0x4e4c, 0x0078, 0x4cda, 0x127f, 0x0078, 0x4cda, 0xa18c, - 0x00ff, 0xa186, 0x0017, 0x0040, 0x4c9d, 0xa186, 0x001e, 0x0040, - 0x4c9d, 0xa18e, 0x001f, 0x00c0, 0x4cb9, 0x684c, 0xd0cc, 0x0040, - 0x4cb9, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4cb9, - 0x2009, 0x8021, 0x0078, 0x4c1e, 0x6844, 0xa086, 0x0100, 0x00c0, - 0x4cb9, 0x6868, 0xa005, 0x00c0, 0x4cb9, 0x2009, 0x8020, 0x0078, - 0x4c1e, 0x2071, 0xa814, 0x1078, 0x4e60, 0x0040, 0x4cda, 0x2071, - 0xa814, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, - 0x00c0, 0x4cd1, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x4cd1, - 0x710e, 0x7007, 0x0003, 0x1078, 0x4e80, 0x7050, 0xa086, 0x0100, - 0x0040, 0x4d95, 0x127e, 0x2091, 0x8000, 0x2071, 0xa814, 0x7008, - 0xa086, 0x0001, 0x00c0, 0x4cf5, 0x0068, 0x4cf5, 0x2009, 0x000d, - 0x7030, 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, - 0x0006, 0x00c0, 0x4cf5, 0x7007, 0x0001, 0x127f, 0x007c, 0x2071, - 0xa814, 0x1078, 0x4e60, 0x0040, 0x4d20, 0x2071, 0xa935, 0x7084, - 0x700a, 0x20a9, 0x0020, 0x2099, 0xa936, 0x20a1, 0xa95d, 0x53a3, - 0x7087, 0x0000, 0x2071, 0xa814, 0x2069, 0xa97d, 0x706c, 0x6826, - 0x7070, 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x1078, - 0x13db, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0xa9c4, 0x7042, - 0x127f, 0x0078, 0x4cda, 0x2069, 0xa97d, 0x6808, 0xa08e, 0x0000, - 0x0040, 0x4d81, 0xa08e, 0x0200, 0x0040, 0x4d7f, 0xa08e, 0x0100, - 0x00c0, 0x4d81, 0x127e, 0x2091, 0x8000, 0x0068, 0x4d7c, 0x2069, - 0x0000, 0x6818, 0xd084, 0x00c0, 0x4d7c, 0x702c, 0x7130, 0x8108, - 0xa102, 0x0048, 0x4d4a, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, - 0x0078, 0x4d54, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4d54, - 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, - 0x2001, 0xa95a, 0x2004, 0xa005, 0x00c0, 0x4d73, 0x6934, 0x2069, - 0xa935, 0x689c, 0x699e, 0x2069, 0xa9c4, 0xa102, 0x00c0, 0x4d6c, - 0x6844, 0xa005, 0x00d0, 0x4d7a, 0x2001, 0xa95b, 0x200c, 0x810d, - 0x6946, 0x0078, 0x4d7a, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, - 0x2091, 0x4080, 0x7007, 0x0001, 0x127f, 0x0078, 0x4d81, 0x7007, - 0x0005, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4d93, 0x1078, 0x4e60, - 0x0040, 0x4d93, 0x7007, 0x0003, 0x1078, 0x4e80, 0x7050, 0xa086, - 0x0100, 0x0040, 0x4d95, 0x007c, 0x007c, 0x7050, 0xa09e, 0x0100, - 0x00c0, 0x4d9e, 0x7007, 0x0004, 0x0078, 0x4dbc, 0xa086, 0x0200, - 0x00c0, 0x4da4, 0x7007, 0x0005, 0x007c, 0x2001, 0xa97f, 0x2004, - 0xa08e, 0x0100, 0x00c0, 0x4db1, 0x7007, 0x0001, 0x1078, 0x4e4c, - 0x007c, 0xa08e, 0x0000, 0x0040, 0x4db0, 0xa08e, 0x0200, 0x00c0, - 0x4db0, 0x7007, 0x0005, 0x007c, 0x1078, 0x4e16, 0x7006, 0x1078, - 0x4e4c, 0x007c, 0x007c, 0x0e7e, 0x157e, 0x2071, 0xa935, 0x7184, - 0x81ff, 0x0040, 0x4deb, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, - 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0070, 0x4de8, 0x2014, - 0x722a, 0x8000, 0x0070, 0x4de8, 0x2014, 0x722e, 0x8000, 0x0070, - 0x4de8, 0x2014, 0x723a, 0x8000, 0x0070, 0x4de8, 0x2014, 0x723e, - 0xa180, 0x8030, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x0e7e, 0x157e, - 0x2071, 0xa935, 0x7184, 0x81ff, 0x0040, 0x4e13, 0xa006, 0x7086, - 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, - 0x2014, 0x722a, 0x8000, 0x0070, 0x4e0c, 0x2014, 0x723a, 0x8000, - 0x2014, 0x723e, 0x0078, 0x4e10, 0x2001, 0x8020, 0x0078, 0x4e12, - 0x2001, 0x8042, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x702c, 0x7130, - 0x8108, 0xa102, 0x0048, 0x4e23, 0xa00e, 0x7034, 0x706e, 0x7038, - 0x7072, 0x0078, 0x4e2d, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, - 0x4e2d, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, - 0x700e, 0x00c0, 0x4e43, 0x127e, 0x2091, 0x8000, 0x0068, 0x4e46, - 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, - 0x0000, 0x127f, 0x007c, 0x2001, 0x0007, 0x007c, 0x2001, 0x0006, - 0x700b, 0x0001, 0x127f, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4e5f, - 0x127e, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, - 0xa005, 0x00c0, 0x4e5c, 0x701a, 0x127f, 0x1078, 0x13a4, 0x007c, - 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0040, 0x4e6f, 0x2304, - 0x230c, 0xa10e, 0x0040, 0x4e6f, 0xa006, 0x0078, 0x4e7f, 0x732c, - 0x8319, 0x7130, 0xa102, 0x00c0, 0x4e79, 0x2300, 0xa005, 0x0078, - 0x4e7f, 0x0048, 0x4e7e, 0xa302, 0x0078, 0x4e7f, 0x8002, 0x007c, - 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x127e, - 0x2091, 0x8000, 0x2009, 0xa9d6, 0x2104, 0xc08d, 0x200a, 0x127f, - 0x1078, 0x13f9, 0x007c, 0x2071, 0xa7e2, 0x7003, 0x0000, 0x7007, - 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, - 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, - 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x007c, 0x0e7e, 0x2071, - 0xa7e2, 0x6848, 0xa005, 0x00c0, 0x4ebc, 0x7028, 0xc085, 0x702a, - 0xa085, 0x0001, 0x0078, 0x4ee1, 0x6a50, 0x7236, 0x6b54, 0x733a, - 0x6858, 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, - 0x6840, 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, - 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, - 0x7376, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, - 0xa006, 0x0e7f, 0x007c, 0x2b78, 0x2071, 0xa7e2, 0x7004, 0x1079, - 0x4f41, 0x700c, 0x0079, 0x4eec, 0x4ef1, 0x4ee6, 0x4ee6, 0x4ee6, - 0x4ee6, 0x007c, 0x700c, 0x0079, 0x4ef5, 0x4efa, 0x4f3f, 0x4f3f, - 0x4f40, 0x4f40, 0x7830, 0x7930, 0xa106, 0x0040, 0x4f04, 0x7830, - 0x7930, 0xa106, 0x00c0, 0x4f2a, 0x7030, 0xa10a, 0x0040, 0x4f2a, - 0x00c8, 0x4f0c, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x00c8, 0x4f2b, - 0x1078, 0x1370, 0x0040, 0x4f2a, 0x2d00, 0x705a, 0x7063, 0x0040, - 0x2001, 0x0003, 0x7057, 0x0000, 0x127e, 0x007e, 0x2091, 0x8000, - 0x2009, 0xa9d6, 0x2104, 0xc085, 0x200a, 0x007f, 0x700e, 0x127f, - 0x1078, 0x13f9, 0x007c, 0x1078, 0x1370, 0x0040, 0x4f2a, 0x2d00, - 0x705a, 0x1078, 0x1370, 0x00c0, 0x4f37, 0x0078, 0x4f16, 0x2d00, - 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x0078, 0x4f1a, 0x007c, - 0x007c, 0x4f52, 0x4f53, 0x4f8a, 0x4f8b, 0x4f3f, 0x4fc1, 0x4fc6, - 0x4ffd, 0x4ffe, 0x5019, 0x501a, 0x501b, 0x501c, 0x501d, 0x501e, - 0x509e, 0x50c8, 0x007c, 0x700c, 0x0079, 0x4f56, 0x4f5b, 0x4f5e, - 0x4f6e, 0x4f89, 0x4f89, 0x1078, 0x4ef2, 0x007c, 0x127e, 0x8001, - 0x700e, 0x7058, 0x007e, 0x1078, 0x5464, 0x0040, 0x4f6b, 0x2091, - 0x8000, 0x1078, 0x4ef2, 0x0d7f, 0x0078, 0x4f77, 0x127e, 0x8001, - 0x700e, 0x1078, 0x5464, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, - 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, - 0x00c8, 0x4f86, 0x1079, 0x4fa1, 0x127f, 0x007c, 0x127f, 0x1078, - 0x501f, 0x007c, 0x007c, 0x007c, 0x0e7e, 0x2071, 0xa7e2, 0x700c, - 0x0079, 0x4f92, 0x4f97, 0x4f97, 0x4f97, 0x4f99, 0x4f9d, 0x0e7f, - 0x007c, 0x700f, 0x0001, 0x0078, 0x4f9f, 0x700f, 0x0002, 0x0e7f, - 0x007c, 0x501f, 0x501f, 0x503b, 0x501f, 0x5171, 0x501f, 0x501f, - 0x501f, 0x501f, 0x501f, 0x503b, 0x51bb, 0x5208, 0x5261, 0x5277, - 0x501f, 0x501f, 0x5057, 0x503b, 0x501f, 0x501f, 0x5078, 0x5338, - 0x5356, 0x501f, 0x5057, 0x501f, 0x501f, 0x501f, 0x501f, 0x506d, - 0x5356, 0x7020, 0x2068, 0x1078, 0x13a4, 0x007c, 0x700c, 0x0079, - 0x4fc9, 0x4fce, 0x4fd1, 0x4fe1, 0x4ffc, 0x4ffc, 0x1078, 0x4ef2, - 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x5464, - 0x0040, 0x4fde, 0x2091, 0x8000, 0x1078, 0x4ef2, 0x0d7f, 0x0078, - 0x4fea, 0x127e, 0x8001, 0x700e, 0x1078, 0x5464, 0x7058, 0x2068, - 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, - 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x4ff9, 0x1079, 0x4fff, 0x127f, - 0x007c, 0x127f, 0x1078, 0x501f, 0x007c, 0x007c, 0x007c, 0x501f, - 0x503b, 0x515b, 0x501f, 0x503b, 0x501f, 0x503b, 0x503b, 0x501f, - 0x503b, 0x515b, 0x503b, 0x503b, 0x503b, 0x503b, 0x503b, 0x501f, - 0x503b, 0x515b, 0x501f, 0x501f, 0x503b, 0x501f, 0x501f, 0x501f, - 0x503b, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x7007, - 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x127e, 0x2091, - 0x8000, 0x1078, 0x4a73, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, - 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, - 0x4a73, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, - 0xc0ed, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4a73, 0x127f, - 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, - 0x127e, 0x2091, 0x8000, 0x1078, 0x4a73, 0x127f, 0x007c, 0x6834, - 0x8007, 0xa084, 0x00ff, 0x0040, 0x502d, 0x8001, 0x00c0, 0x5064, - 0x7007, 0x0001, 0x0078, 0x513a, 0x7007, 0x0006, 0x7012, 0x2d00, - 0x7016, 0x701a, 0x704b, 0x513a, 0x007c, 0x684c, 0xa084, 0x00c0, - 0xa086, 0x00c0, 0x00c0, 0x5078, 0x7007, 0x0001, 0x0078, 0x5373, - 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, - 0x20a1, 0xa80d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8, - 0x5049, 0x6884, 0xa08a, 0x0002, 0x00c8, 0x5049, 0x82ff, 0x00c0, - 0x509a, 0x6888, 0x698c, 0xa105, 0x0040, 0x509a, 0x2001, 0x510a, - 0x0078, 0x509d, 0xa280, 0x5100, 0x2004, 0x70c6, 0x7010, 0xa015, - 0x0040, 0x50e8, 0x1078, 0x1370, 0x00c0, 0x50a9, 0x7007, 0x000f, - 0x007c, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x6000, 0x6836, 0x6004, - 0xad00, 0x7096, 0x6008, 0xa20a, 0x00c8, 0x50b8, 0xa00e, 0x2200, - 0x7112, 0x620c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0040, 0x50c1, - 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x1078, 0x13db, - 0x7090, 0xa08e, 0x0100, 0x0040, 0x50dc, 0xa086, 0x0200, 0x0040, - 0x50d4, 0x7007, 0x0010, 0x007c, 0x7020, 0x2068, 0x1078, 0x13a4, - 0x7014, 0x2068, 0x0078, 0x5049, 0x7020, 0x2068, 0x7018, 0x6802, - 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0078, 0x509e, - 0x7014, 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x00c0, 0x50f7, - 0x6888, 0x698c, 0xa105, 0x0040, 0x50f7, 0x1078, 0x510e, 0x6834, - 0xa084, 0x00ff, 0xa086, 0x001e, 0x0040, 0x5373, 0x0078, 0x513a, - 0x5102, 0x5106, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, - 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x0f7e, 0x0e7e, - 0x0c7e, 0x077e, 0x067e, 0x6f88, 0x6e8c, 0x6804, 0x2060, 0xacf0, - 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, - 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, - 0x0040, 0x5130, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0078, 0x511d, - 0x6004, 0xa065, 0x00c0, 0x5117, 0x067f, 0x077f, 0x0c7f, 0x0e7f, - 0x0f7f, 0x007c, 0x2009, 0xa72f, 0x210c, 0x81ff, 0x00c0, 0x5155, - 0x6838, 0xa084, 0x00ff, 0x683a, 0x1078, 0x4353, 0x00c0, 0x5149, - 0x007c, 0x1078, 0x4b51, 0x127e, 0x2091, 0x8000, 0x1078, 0x8f8d, - 0x1078, 0x4a73, 0x127f, 0x0078, 0x5148, 0x2001, 0x0028, 0x2009, - 0x0000, 0x0078, 0x5149, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, - 0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x516a, 0x7007, 0x0006, - 0x0078, 0x5170, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, - 0x007c, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, - 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x519a, - 0x2009, 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0040, 0x519a, - 0xa005, 0x00c0, 0x51ad, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, - 0x45c4, 0x00c0, 0x51ad, 0x067e, 0x6e50, 0x1078, 0x46b3, 0x067f, - 0x0078, 0x51ad, 0x047e, 0x2011, 0xa70c, 0x2224, 0xc484, 0xc48c, - 0x2412, 0x047f, 0x0c7e, 0x1078, 0x45c4, 0x00c0, 0x51a9, 0x1078, - 0x4852, 0x8108, 0x00f0, 0x51a3, 0x0c7f, 0x684c, 0xd084, 0x00c0, - 0x51b4, 0x1078, 0x13a4, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, - 0x4a73, 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, - 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x51ff, 0x2061, 0xaa33, - 0x6100, 0xd184, 0x0040, 0x51df, 0x6858, 0xa084, 0x00ff, 0x00c0, - 0x5202, 0x6000, 0xd084, 0x0040, 0x51ff, 0x6004, 0xa005, 0x00c0, - 0x5205, 0x6003, 0x0000, 0x600b, 0x0000, 0x0078, 0x51fc, 0x2011, - 0x0001, 0x6860, 0xa005, 0x00c0, 0x51e7, 0x2001, 0x001e, 0x8000, - 0x6016, 0x6858, 0xa084, 0x00ff, 0x0040, 0x51ff, 0x6006, 0x6858, - 0x8007, 0xa084, 0x00ff, 0x0040, 0x51ff, 0x600a, 0x6858, 0x8000, - 0x00c0, 0x51fb, 0xc28d, 0x6202, 0x127f, 0x0078, 0x5453, 0x127f, - 0x0078, 0x544b, 0x127f, 0x0078, 0x5443, 0x127f, 0x0078, 0x5447, - 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xa753, 0x2004, - 0xd0a4, 0x0040, 0x525e, 0x2061, 0xaa33, 0x6000, 0xd084, 0x0040, - 0x525e, 0x6204, 0x6308, 0xd08c, 0x00c0, 0x5250, 0x6c48, 0xa484, - 0x0003, 0x0040, 0x5236, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, - 0x522f, 0x2100, 0xa210, 0x0048, 0x525b, 0x0078, 0x5236, 0x8001, - 0x00c0, 0x525b, 0x2100, 0xa212, 0x0048, 0x525b, 0xa484, 0x000c, - 0x0040, 0x5250, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, - 0x00c0, 0x5248, 0x2100, 0xa318, 0x0048, 0x525b, 0x0078, 0x5250, - 0xa082, 0x0004, 0x00c0, 0x525b, 0x2100, 0xa31a, 0x0048, 0x525b, - 0x6860, 0xa005, 0x0040, 0x5256, 0x8000, 0x6016, 0x6206, 0x630a, - 0x127f, 0x0078, 0x5453, 0x127f, 0x0078, 0x544f, 0x127f, 0x0078, - 0x544b, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xaa33, - 0x6300, 0xd38c, 0x00c0, 0x5271, 0x6308, 0x8318, 0x0048, 0x5274, - 0x630a, 0x127f, 0x0078, 0x5461, 0x127f, 0x0078, 0x544f, 0x127e, - 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0040, - 0x528b, 0x0c7e, 0x2061, 0xaa33, 0x6000, 0xa084, 0xfcff, 0x6002, - 0x0c7f, 0x0078, 0x52ba, 0x6858, 0xa005, 0x0040, 0x52d1, 0x685c, - 0xa065, 0x0040, 0x52cd, 0x2001, 0xa72f, 0x2004, 0xa005, 0x0040, - 0x529d, 0x1078, 0x8ed6, 0x0078, 0x52ab, 0x6013, 0x0400, 0x6037, - 0x0000, 0x694c, 0xd1a4, 0x0040, 0x52a7, 0x6950, 0x6136, 0x2009, - 0x0041, 0x1078, 0x775c, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, - 0x00c0, 0x52ba, 0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078, - 0x5bf1, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x52c9, 0x2061, 0xaa33, - 0x6000, 0xd08c, 0x00c0, 0x52c9, 0x6008, 0x8000, 0x0048, 0x52cd, - 0x600a, 0x0c7f, 0x127f, 0x0078, 0x5453, 0x0c7f, 0x127f, 0x0078, - 0x544b, 0x6954, 0xa186, 0x0045, 0x0040, 0x5306, 0xa186, 0x002a, - 0x00c0, 0x52e1, 0x2001, 0xa70c, 0x200c, 0xc194, 0x2102, 0x0078, - 0x52ba, 0xa186, 0x0020, 0x0040, 0x52fa, 0xa186, 0x0029, 0x0040, - 0x52ed, 0xa186, 0x002d, 0x00c0, 0x52cd, 0x6944, 0xa18c, 0xff00, - 0x810f, 0x1078, 0x45c4, 0x00c0, 0x52ba, 0x6000, 0xc0e4, 0x6002, - 0x0078, 0x52ba, 0x685c, 0xa065, 0x0040, 0x52cd, 0x6007, 0x0024, - 0x2001, 0xa9a3, 0x2004, 0x6016, 0x0078, 0x52ba, 0x685c, 0xa065, - 0x0040, 0x52cd, 0x0e7e, 0x6860, 0xa075, 0x2001, 0xa72f, 0x2004, - 0xa005, 0x0040, 0x531e, 0x1078, 0x8ed6, 0x8eff, 0x0040, 0x531b, - 0x2e60, 0x1078, 0x8ed6, 0x0e7f, 0x0078, 0x52ba, 0x6024, 0xc0dc, - 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0040, - 0x532f, 0x6007, 0x003b, 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, - 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0e7f, 0x0078, 0x52ba, - 0x2061, 0xaa33, 0x6000, 0xd084, 0x0040, 0x5352, 0xd08c, 0x00c0, - 0x5461, 0x2091, 0x8000, 0x6204, 0x8210, 0x0048, 0x534c, 0x6206, - 0x2091, 0x8001, 0x0078, 0x5461, 0x2091, 0x8001, 0x6853, 0x0016, - 0x0078, 0x545a, 0x6853, 0x0007, 0x0078, 0x545a, 0x6834, 0x8007, - 0xa084, 0x00ff, 0x00c0, 0x5360, 0x1078, 0x502d, 0x0078, 0x5372, - 0x2030, 0x8001, 0x00c0, 0x536a, 0x7007, 0x0001, 0x1078, 0x5373, - 0x0078, 0x5372, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, - 0x704b, 0x5373, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, 0xa03e, - 0x2009, 0xa72f, 0x210c, 0x81ff, 0x00c0, 0x53ff, 0x2009, 0xa70c, - 0x210c, 0xd194, 0x00c0, 0x5431, 0x6848, 0x2070, 0xae82, 0xae00, - 0x0048, 0x53ef, 0x2001, 0xa716, 0x2004, 0xae02, 0x00c8, 0x53ef, - 0x2061, 0xaa33, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, 0x00c0, - 0x53d2, 0x711c, 0xa186, 0x0006, 0x00c0, 0x53da, 0x7018, 0xa005, - 0x0040, 0x53ff, 0x2004, 0xd0e4, 0x00c0, 0x542b, 0x7024, 0xd0dc, - 0x00c0, 0x5435, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7010, - 0xa005, 0x00c0, 0x53be, 0x7112, 0x684c, 0xd0f4, 0x00c0, 0x5439, - 0x2e60, 0x1078, 0x5b27, 0x127f, 0x0e7f, 0x007c, 0x2068, 0x6800, - 0xa005, 0x00c0, 0x53be, 0x6902, 0x2168, 0x684c, 0xd0f4, 0x00c0, - 0x5439, 0x127f, 0x0e7f, 0x007c, 0x127f, 0x0e7f, 0x6853, 0x0006, - 0x0078, 0x545a, 0xd184, 0x0040, 0x53cc, 0xd1c4, 0x00c0, 0x53f3, - 0x0078, 0x53f7, 0x6944, 0xa18c, 0xff00, 0x810f, 0x1078, 0x45c4, - 0x00c0, 0x542b, 0x6000, 0xd0e4, 0x00c0, 0x542b, 0x711c, 0xa186, - 0x0007, 0x00c0, 0x53ef, 0x6853, 0x0002, 0x0078, 0x542d, 0x6853, - 0x0008, 0x0078, 0x542d, 0x6853, 0x000e, 0x0078, 0x542d, 0x6853, - 0x0017, 0x0078, 0x542d, 0x6853, 0x0035, 0x0078, 0x542d, 0x2001, - 0xa772, 0x2004, 0xd0fc, 0x0040, 0x5427, 0x6848, 0x2070, 0xae82, - 0xae00, 0x0048, 0x5427, 0x6058, 0xae02, 0x00c8, 0x5427, 0x711c, - 0xa186, 0x0006, 0x00c0, 0x5427, 0x7018, 0xa005, 0x0040, 0x5427, - 0x2004, 0xd0bc, 0x0040, 0x5427, 0x2039, 0x0001, 0x7000, 0xa086, - 0x0007, 0x00c0, 0x537e, 0x7003, 0x0002, 0x0078, 0x537e, 0x6853, - 0x0028, 0x0078, 0x542d, 0x6853, 0x0029, 0x127f, 0x0e7f, 0x0078, - 0x545a, 0x6853, 0x002a, 0x0078, 0x542d, 0x6853, 0x0045, 0x0078, - 0x542d, 0x2e60, 0x2019, 0x0002, 0x6017, 0x0014, 0x1078, 0x9dd7, - 0x127f, 0x0e7f, 0x007c, 0x2009, 0x003e, 0x0078, 0x5455, 0x2009, - 0x0004, 0x0078, 0x5455, 0x2009, 0x0006, 0x0078, 0x5455, 0x2009, - 0x0016, 0x0078, 0x5455, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, - 0xa105, 0x6856, 0x2091, 0x8000, 0x1078, 0x4a73, 0x2091, 0x8001, - 0x007c, 0x1078, 0x13a4, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, - 0x0048, 0x5471, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078, - 0x547d, 0x7070, 0xa080, 0x0040, 0x7072, 0x00c8, 0x547d, 0x7074, - 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x007c, - 0x0d7e, 0x1078, 0x5b1e, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004, - 0x2204, 0xa085, 0x8002, 0x2012, 0x0d7f, 0x007c, 0x20e1, 0x0002, - 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x549c, - 0xa086, 0x1000, 0x00c0, 0x54d3, 0x20e1, 0x0000, 0x3d00, 0xa094, - 0xff00, 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x00c0, 0x54b7, - 0xa184, 0xff00, 0x8007, 0xa086, 0x0008, 0x00c0, 0x54d3, 0x1078, - 0x29bb, 0x00c0, 0x54d3, 0x1078, 0x56b2, 0x0078, 0x54ce, 0x20e1, - 0x0004, 0x3d60, 0xd1bc, 0x00c0, 0x54be, 0x3e60, 0xac84, 0x000f, - 0x00c0, 0x54d3, 0xac82, 0xae00, 0x0048, 0x54d3, 0x6858, 0xac02, - 0x00c8, 0x54d3, 0x2009, 0x0047, 0x1078, 0x775c, 0x7a1c, 0xd284, - 0x00c0, 0x548e, 0x007c, 0xa016, 0x1078, 0x15fa, 0x0078, 0x54ce, - 0x0078, 0x54d3, 0x781c, 0xd08c, 0x0040, 0x5502, 0x157e, 0x137e, - 0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076, 0x00c0, - 0x5518, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, 0x5507, 0x1078, - 0x554e, 0x0040, 0x5518, 0x20e1, 0x3000, 0x7828, 0x7828, 0x1078, - 0x556c, 0x147f, 0x137f, 0x157f, 0x2009, 0xa9b9, 0x2104, 0xa005, - 0x00c0, 0x5503, 0x007c, 0x1078, 0x62d1, 0x0078, 0x5502, 0xa484, - 0x7000, 0x00c0, 0x5518, 0x1078, 0x554e, 0x0040, 0x552c, 0x7000, - 0xa084, 0xff00, 0xa086, 0x8100, 0x0040, 0x54f3, 0x0078, 0x552c, - 0x1078, 0xa55f, 0xd5a4, 0x0040, 0x5528, 0x047e, 0x1078, 0x1b22, - 0x047f, 0x20e1, 0x9010, 0x2001, 0x0138, 0x2202, 0x0078, 0x5530, - 0x1078, 0x554e, 0x6883, 0x0000, 0x20e1, 0x3000, 0x7828, 0x7828, - 0x1078, 0x5537, 0x147f, 0x137f, 0x157f, 0x0078, 0x5502, 0x2001, - 0xa70e, 0x2004, 0xd08c, 0x0040, 0x554d, 0x2001, 0xa700, 0x2004, - 0xa086, 0x0003, 0x00c0, 0x554d, 0x027e, 0x037e, 0x2011, 0x8048, - 0x2518, 0x1078, 0x361b, 0x037f, 0x027f, 0x007c, 0xa484, 0x01ff, - 0x6882, 0xa005, 0x0040, 0x5560, 0xa080, 0x001f, 0xa084, 0x03f8, - 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c, - 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, - 0xa085, 0x0001, 0x0078, 0x555f, 0x7000, 0xa084, 0xff00, 0xa08c, - 0xf000, 0x8007, 0xa196, 0x0000, 0x00c0, 0x5579, 0x0078, 0x57ba, - 0x007c, 0xa196, 0x2000, 0x00c0, 0x558a, 0x6900, 0xa18e, 0x0001, - 0x00c0, 0x5586, 0x1078, 0x3aec, 0x0078, 0x5578, 0x1078, 0x5592, - 0x0078, 0x5578, 0xa196, 0x8000, 0x00c0, 0x5578, 0x1078, 0x5871, - 0x0078, 0x5578, 0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, - 0x0001, 0x0040, 0x559f, 0xa196, 0x0023, 0x00c0, 0x56aa, 0xa08e, - 0x0023, 0x00c0, 0x55d4, 0x1078, 0x591d, 0x0040, 0x56aa, 0x7124, - 0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x55b8, 0x7034, 0xa005, - 0x00c0, 0x56aa, 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x56aa, - 0xa08e, 0x0214, 0x0040, 0x55c0, 0xa08e, 0x0210, 0x00c0, 0x55c6, - 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x56aa, 0xa08e, 0x0100, - 0x00c0, 0x56aa, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x0016, - 0x1078, 0x775c, 0x0078, 0x56aa, 0xa08e, 0x0022, 0x00c0, 0x56aa, - 0x7030, 0xa08e, 0x0300, 0x00c0, 0x55e5, 0x7034, 0xa005, 0x00c0, - 0x56aa, 0x2009, 0x0017, 0x0078, 0x5676, 0xa08e, 0x0500, 0x00c0, - 0x55f1, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x0018, 0x0078, - 0x5676, 0xa08e, 0x2010, 0x00c0, 0x55f9, 0x2009, 0x0019, 0x0078, - 0x5676, 0xa08e, 0x2110, 0x00c0, 0x5601, 0x2009, 0x001a, 0x0078, - 0x5676, 0xa08e, 0x5200, 0x00c0, 0x560d, 0x7034, 0xa005, 0x00c0, - 0x56aa, 0x2009, 0x001b, 0x0078, 0x5676, 0xa08e, 0x5000, 0x00c0, - 0x5619, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x001c, 0x0078, - 0x5676, 0xa08e, 0x1300, 0x00c0, 0x5621, 0x2009, 0x0034, 0x0078, - 0x5676, 0xa08e, 0x1200, 0x00c0, 0x562d, 0x7034, 0xa005, 0x00c0, - 0x56aa, 0x2009, 0x0024, 0x0078, 0x5676, 0xa08c, 0xff00, 0xa18e, - 0x2400, 0x00c0, 0x5637, 0x2009, 0x002d, 0x0078, 0x5676, 0xa08c, - 0xff00, 0xa18e, 0x5300, 0x00c0, 0x5641, 0x2009, 0x002a, 0x0078, - 0x5676, 0xa08e, 0x0f00, 0x00c0, 0x5649, 0x2009, 0x0020, 0x0078, - 0x5676, 0xa08e, 0x5300, 0x00c0, 0x564f, 0x0078, 0x566c, 0xa08e, - 0x6104, 0x00c0, 0x566c, 0x2011, 0xac8d, 0x8208, 0x2204, 0xa082, - 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, - 0x047e, 0x2124, 0x1078, 0x361b, 0x047f, 0x8108, 0x00f0, 0x565c, - 0x2009, 0x0023, 0x0078, 0x5676, 0xa08e, 0x6000, 0x00c0, 0x5674, - 0x2009, 0x003f, 0x0078, 0x5676, 0x2009, 0x001d, 0x017e, 0x2011, - 0xac83, 0x2204, 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x56ac, - 0x1078, 0x455c, 0x00c0, 0x56ac, 0x6612, 0x6516, 0x86ff, 0x0040, - 0x569c, 0x017f, 0x017e, 0xa186, 0x0017, 0x00c0, 0x569c, 0x686c, - 0xa606, 0x00c0, 0x569c, 0x6870, 0xa506, 0xa084, 0xff00, 0x00c0, - 0x569c, 0x6000, 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x76c7, 0x0040, - 0x56af, 0x017f, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, - 0x1078, 0x775c, 0x0c7f, 0x007c, 0x017f, 0x0078, 0x56aa, 0x0c7f, - 0x0078, 0x56ac, 0x0c7e, 0x1078, 0x570f, 0x00c0, 0x570d, 0xa28e, - 0x0033, 0x00c0, 0x56de, 0x1078, 0x591d, 0x0040, 0x570d, 0x7124, - 0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x56d0, 0x7034, 0xa005, - 0x00c0, 0x570d, 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x570d, - 0xa08e, 0x0100, 0x00c0, 0x570d, 0x7034, 0xa005, 0x00c0, 0x570d, - 0x2009, 0x0016, 0x1078, 0x775c, 0x0078, 0x570d, 0xa28e, 0x0032, - 0x00c0, 0x570d, 0x7030, 0xa08e, 0x1400, 0x00c0, 0x570d, 0x2009, - 0x0038, 0x017e, 0x2011, 0xac83, 0x2204, 0x8211, 0x220c, 0x1078, - 0x254d, 0x00c0, 0x570c, 0x1078, 0x455c, 0x00c0, 0x570c, 0x6612, - 0x6516, 0x0c7e, 0x1078, 0x76c7, 0x0040, 0x570b, 0x017f, 0x611a, - 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x775c, 0x1078, - 0x62d1, 0x0078, 0x570d, 0x0c7f, 0x017f, 0x0c7f, 0x007c, 0x0f7e, - 0x0d7e, 0x027e, 0x017e, 0x137e, 0x147e, 0x157e, 0x3c00, 0x007e, - 0x2079, 0x0030, 0x2069, 0x0200, 0x1078, 0x1c6a, 0x00c0, 0x5750, - 0x1078, 0x1b40, 0x0040, 0x575d, 0x7908, 0xa18c, 0x1fff, 0xa182, - 0x0011, 0x00c8, 0x575a, 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, - 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, - 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0xa08a, 0x0140, - 0x10c8, 0x1332, 0x80ac, 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, - 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, 0x0004, 0xa294, 0x0070, - 0x007f, 0x20e0, 0x157f, 0x147f, 0x137f, 0x017f, 0x027f, 0x0d7f, - 0x0f7f, 0x007c, 0xa016, 0x1078, 0x15fa, 0xa085, 0x0001, 0x0078, - 0x5750, 0x047e, 0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, - 0x00c0, 0x5782, 0xa596, 0xfffd, 0x00c0, 0x5772, 0x2009, 0x007f, - 0x0078, 0x57b5, 0xa596, 0xfffe, 0x00c0, 0x577a, 0x2009, 0x007e, - 0x0078, 0x57b5, 0xa596, 0xfffc, 0x00c0, 0x5782, 0x2009, 0x0080, - 0x0078, 0x57b5, 0x2011, 0x0000, 0x2021, 0x0081, 0x20a9, 0x007e, - 0x2071, 0xa8b6, 0x2e1c, 0x83ff, 0x00c0, 0x5794, 0x82ff, 0x00c0, - 0x57a9, 0x2410, 0x0078, 0x57a9, 0x2368, 0x6f10, 0x007e, 0x2100, - 0xa706, 0x007f, 0x6b14, 0x00c0, 0x57a3, 0xa346, 0x00c0, 0x57a3, - 0x2408, 0x0078, 0x57b5, 0x87ff, 0x00c0, 0x57a9, 0x83ff, 0x0040, - 0x578e, 0x8420, 0x8e70, 0x00f0, 0x578a, 0x82ff, 0x00c0, 0x57b4, - 0xa085, 0x0001, 0x0078, 0x57b6, 0x2208, 0xa006, 0x0d7f, 0x0e7f, - 0x047f, 0x007c, 0xa084, 0x0007, 0x0079, 0x57bf, 0x007c, 0x57c7, - 0x57c7, 0x57c7, 0x5933, 0x57c7, 0x57c8, 0x57e1, 0x5858, 0x007c, - 0x7110, 0xd1bc, 0x0040, 0x57e0, 0x7120, 0x2160, 0xac8c, 0x000f, - 0x00c0, 0x57e0, 0xac8a, 0xae00, 0x0048, 0x57e0, 0x6858, 0xac02, - 0x00c8, 0x57e0, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x775c, - 0x007c, 0x0c7e, 0xa484, 0x01ff, 0x0040, 0x5833, 0x7110, 0xd1bc, - 0x00c0, 0x5833, 0x2011, 0xac83, 0x2204, 0x8211, 0x220c, 0x1078, - 0x254d, 0x00c0, 0x5833, 0x1078, 0x455c, 0x00c0, 0x5833, 0x6612, - 0x6516, 0x6000, 0xd0ec, 0x00c0, 0x5833, 0x6204, 0xa294, 0xff00, - 0x8217, 0xa286, 0x0006, 0x00c0, 0x5818, 0x0c7e, 0x1078, 0x76c7, - 0x017f, 0x0040, 0x5835, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, - 0x7130, 0x6122, 0x2009, 0x0044, 0x1078, 0x775c, 0x0078, 0x5833, - 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x5833, 0x611a, 0x601f, - 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x582b, 0x6007, - 0x0005, 0x0078, 0x582d, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, - 0x5dd7, 0x1078, 0x62d1, 0x0c7f, 0x007c, 0x2001, 0xa70d, 0x2004, - 0xd0ec, 0x0040, 0x583f, 0x2011, 0x8049, 0x1078, 0x361b, 0x0c7e, - 0x1078, 0x9197, 0x017f, 0x0040, 0x5833, 0x611a, 0x601f, 0x0006, - 0x7120, 0x610a, 0x7130, 0x6122, 0x6013, 0x0300, 0x6003, 0x0001, - 0x6007, 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x5833, - 0x7110, 0xd1bc, 0x0040, 0x5870, 0x7020, 0x2060, 0xac84, 0x000f, - 0x00c0, 0x5870, 0xac82, 0xae00, 0x0048, 0x5870, 0x6858, 0xac02, - 0x00c8, 0x5870, 0x7124, 0x610a, 0x2009, 0x0045, 0x1078, 0x775c, - 0x007c, 0x007e, 0x1078, 0x29bb, 0x007f, 0x00c0, 0x5887, 0x7110, - 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x5887, 0xa084, - 0x000f, 0xa08a, 0x0006, 0x00c8, 0x5887, 0x1079, 0x5888, 0x007c, - 0x588e, 0x588f, 0x588e, 0x588e, 0x58ff, 0x590e, 0x007c, 0x7110, - 0xd1bc, 0x0040, 0x5897, 0x702c, 0xd084, 0x0040, 0x58fe, 0x700c, - 0x7108, 0x1078, 0x254d, 0x00c0, 0x58fe, 0x1078, 0x455c, 0x00c0, - 0x58fe, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x0040, 0x58c9, - 0xa28c, 0x00ff, 0xa186, 0x0004, 0x0040, 0x58b2, 0xa186, 0x0006, - 0x00c0, 0x58ef, 0x0c7e, 0x1078, 0x591d, 0x0c7f, 0x0040, 0x58fe, - 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, - 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x1078, 0x775c, 0x0078, - 0x58fe, 0xa28c, 0x00ff, 0xa186, 0x0006, 0x0040, 0x58de, 0xa186, - 0x0004, 0x0040, 0x58de, 0xa294, 0xff00, 0x8217, 0xa286, 0x0004, - 0x0040, 0x58de, 0xa286, 0x0006, 0x00c0, 0x58ef, 0x0c7e, 0x1078, - 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, 0x0005, 0x7120, - 0x610a, 0x2009, 0x0088, 0x1078, 0x775c, 0x0078, 0x58fe, 0x0c7e, - 0x1078, 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, 0x0004, - 0x7120, 0x610a, 0x2009, 0x0001, 0x1078, 0x775c, 0x007c, 0x7110, - 0xd1bc, 0x0040, 0x590d, 0x1078, 0x591d, 0x0040, 0x590d, 0x7124, - 0x610a, 0x2009, 0x0089, 0x1078, 0x775c, 0x007c, 0x7110, 0xd1bc, - 0x0040, 0x591c, 0x1078, 0x591d, 0x0040, 0x591c, 0x7124, 0x610a, - 0x2009, 0x008a, 0x1078, 0x775c, 0x007c, 0x7020, 0x2060, 0xac84, - 0x000f, 0x00c0, 0x5930, 0xac82, 0xae00, 0x0048, 0x5930, 0x2001, - 0xa716, 0x2004, 0xac02, 0x00c8, 0x5930, 0xa085, 0x0001, 0x007c, - 0xa006, 0x0078, 0x592f, 0x7110, 0xd1bc, 0x00c0, 0x5949, 0x7024, - 0x2060, 0xac84, 0x000f, 0x00c0, 0x5949, 0xac82, 0xae00, 0x0048, - 0x5949, 0x6858, 0xac02, 0x00c8, 0x5949, 0x2009, 0x0051, 0x1078, - 0x775c, 0x007c, 0x2071, 0xa9c4, 0x7003, 0x0003, 0x700f, 0x0361, - 0xa006, 0x701a, 0x7012, 0x7017, 0xae00, 0x7007, 0x0000, 0x7026, - 0x702b, 0x6e1c, 0x7032, 0x7037, 0x6e70, 0x703b, 0x0002, 0x703f, - 0x0000, 0x7043, 0xffff, 0x7047, 0xffff, 0x007c, 0x2071, 0xa9c4, - 0x00e0, 0x5a32, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, - 0x59de, 0x700f, 0x0361, 0x7007, 0x0001, 0x127e, 0x2091, 0x8000, - 0x7138, 0x8109, 0x713a, 0x00c0, 0x59dc, 0x703b, 0x0002, 0x2009, - 0x0100, 0x2104, 0xa082, 0x0003, 0x00c8, 0x59dc, 0x703c, 0xa086, - 0x0001, 0x00c0, 0x59b9, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, - 0x4000, 0x0040, 0x5997, 0x6803, 0x1000, 0x0078, 0x599e, 0x6804, - 0xa084, 0x1000, 0x0040, 0x599e, 0x6803, 0x0100, 0x6803, 0x0000, - 0x703f, 0x0000, 0x2069, 0xa9b1, 0x6804, 0xa082, 0x0006, 0x00c0, - 0x59ab, 0x6807, 0x0000, 0x6830, 0xa082, 0x0003, 0x00c0, 0x59b2, - 0x6833, 0x0000, 0x1078, 0x62d1, 0x1078, 0x639b, 0x0d7f, 0x0078, - 0x59dc, 0x0d7e, 0x2069, 0xa700, 0x6948, 0x6864, 0xa102, 0x00c8, - 0x59db, 0x2069, 0xa9b1, 0x6804, 0xa086, 0x0000, 0x00c0, 0x59db, - 0x6830, 0xa086, 0x0000, 0x00c0, 0x59db, 0x703f, 0x0001, 0x6807, - 0x0006, 0x6833, 0x0003, 0x2069, 0x0100, 0x6830, 0x689e, 0x2069, - 0x0140, 0x6803, 0x0600, 0x0d7f, 0x0078, 0x59e1, 0x127e, 0x2091, - 0x8000, 0x7024, 0xa00d, 0x0040, 0x59f9, 0x7020, 0x8001, 0x7022, - 0x00c0, 0x59f9, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, - 0x00c0, 0x59f4, 0x7028, 0x107a, 0x81ff, 0x00c0, 0x59f9, 0x7028, - 0x107a, 0x7030, 0xa00d, 0x0040, 0x5a10, 0x702c, 0x8001, 0x702e, - 0x00c0, 0x5a10, 0x702f, 0x0009, 0x8109, 0x7132, 0x0040, 0x5a0e, - 0xa184, 0x007f, 0x1040, 0x6ea2, 0x0078, 0x5a10, 0x7034, 0x107a, - 0x7040, 0xa005, 0x0040, 0x5a18, 0x0050, 0x5a18, 0x8001, 0x7042, - 0x7044, 0xa005, 0x0040, 0x5a20, 0x0050, 0x5a20, 0x8001, 0x7046, - 0x7018, 0xa00d, 0x0040, 0x5a31, 0x7008, 0x8001, 0x700a, 0x00c0, - 0x5a31, 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x5a31, 0x701c, - 0x107a, 0x127f, 0x7004, 0x0079, 0x5a35, 0x5a5c, 0x5a5d, 0x5a79, - 0x0e7e, 0x2071, 0xa9c4, 0x7018, 0xa005, 0x00c0, 0x5a43, 0x711a, - 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x2071, - 0xa9c4, 0x701c, 0xa206, 0x00c0, 0x5a4f, 0x701a, 0x701e, 0x007f, - 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa9c4, 0x6088, 0xa102, 0x0048, - 0x5a5a, 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078, 0x45c4, - 0x00c0, 0x5a6f, 0x6088, 0x8001, 0x0048, 0x5a6f, 0x608a, 0x00c0, - 0x5a6f, 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x8108, - 0xa182, 0x00ff, 0x0048, 0x5a77, 0xa00e, 0x7007, 0x0002, 0x7112, - 0x007c, 0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x603c, 0xa005, - 0x0040, 0x5a88, 0x8001, 0x603e, 0x00c0, 0x5a88, 0x1078, 0x8fac, - 0x6014, 0xa005, 0x0040, 0x5ab2, 0x8001, 0x6016, 0x00c0, 0x5ab2, - 0x611c, 0xa186, 0x0003, 0x0040, 0x5a99, 0xa186, 0x0006, 0x00c0, - 0x5ab0, 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x5ab0, - 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x5aa9, 0x2001, - 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x5ab2, - 0x1078, 0x8ace, 0x127f, 0xac88, 0x0010, 0x7116, 0x2001, 0xce00, - 0xa102, 0x0048, 0x5abf, 0x7017, 0xae00, 0x7007, 0x0000, 0x007c, - 0x0e7e, 0x2071, 0xa9c4, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b, - 0x0002, 0x0e7f, 0x007c, 0x2001, 0xa9cd, 0x2003, 0x0000, 0x007c, - 0x0e7e, 0x2071, 0xa9c4, 0x7132, 0x702f, 0x0009, 0x0e7f, 0x007c, - 0x2011, 0xa9d0, 0x2013, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa9c4, - 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x027e, 0x0e7e, - 0x0f7e, 0x2079, 0xa700, 0x7a34, 0xd294, 0x0040, 0x5b15, 0x2071, - 0xa9ac, 0x2e14, 0xa0fe, 0x0000, 0x0040, 0x5b02, 0xa0fe, 0x0001, - 0x0040, 0x5b06, 0xa0fe, 0x0002, 0x00c0, 0x5b11, 0xa292, 0x0085, - 0x0078, 0x5b08, 0xa292, 0x0005, 0x0078, 0x5b08, 0xa292, 0x0002, - 0x2272, 0x0040, 0x5b0d, 0x00c8, 0x5b15, 0x2011, 0x8037, 0x1078, - 0x361b, 0x2011, 0xa9ab, 0x2204, 0x2072, 0x0f7f, 0x0e7f, 0x027f, - 0x007c, 0x0c7e, 0x2061, 0xaa33, 0x0c7f, 0x007c, 0xa184, 0x000f, - 0x8003, 0x8003, 0x8003, 0xa080, 0xaa33, 0x2060, 0x007c, 0x6854, - 0xa08a, 0x199a, 0x0048, 0x5b2e, 0x2001, 0x1999, 0xa005, 0x00c0, - 0x5b3d, 0x0c7e, 0x2061, 0xaa33, 0x6014, 0x0c7f, 0xa005, 0x00c0, - 0x5b42, 0x2001, 0x001e, 0x0078, 0x5b42, 0xa08e, 0xffff, 0x00c0, - 0x5b42, 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, - 0xa08c, 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x5b9e, 0xd0b4, 0x00c0, - 0x5b59, 0xd0bc, 0x00c0, 0x5b8b, 0x2009, 0x0006, 0x1078, 0x5bc3, - 0x007c, 0xd0fc, 0x0040, 0x5b64, 0xa084, 0x0003, 0x0040, 0x5b64, - 0xa086, 0x0003, 0x00c0, 0x5bbc, 0x6024, 0xd0d4, 0x0040, 0x5b6e, - 0xc0d4, 0x6026, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xa774, - 0x2104, 0xd084, 0x0040, 0x5b83, 0x6118, 0xa188, 0x0027, 0x2104, - 0xd08c, 0x00c0, 0x5b83, 0x87ff, 0x00c0, 0x5b82, 0x2009, 0x0042, - 0x1078, 0x775c, 0x007c, 0x87ff, 0x00c0, 0x5b8a, 0x2009, 0x0043, - 0x1078, 0x775c, 0x007c, 0xd0fc, 0x0040, 0x5b96, 0xa084, 0x0003, - 0x0040, 0x5b96, 0xa086, 0x0003, 0x00c0, 0x5bbc, 0x87ff, 0x00c0, - 0x5b9d, 0x2009, 0x0042, 0x1078, 0x775c, 0x007c, 0xd0fc, 0x0040, - 0x5baf, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0040, 0x5bb3, 0x87ff, - 0x00c0, 0x5bae, 0x2009, 0x0041, 0x1078, 0x775c, 0x007c, 0x1078, - 0x5bc1, 0x0078, 0x5bae, 0x87ff, 0x00c0, 0x5bae, 0x2009, 0x0043, - 0x1078, 0x775c, 0x0078, 0x5bae, 0x2009, 0x0004, 0x1078, 0x5bc3, - 0x007c, 0x2009, 0x0001, 0x0d7e, 0x6010, 0xa0ec, 0xf000, 0x0040, - 0x5bef, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x00c0, - 0x5be5, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x00c0, 0x5be5, - 0x0c7e, 0x2061, 0xaa33, 0x6200, 0xd28c, 0x00c0, 0x5be4, 0x6204, - 0x8210, 0x0048, 0x5be4, 0x6206, 0x0c7f, 0x1078, 0x4a73, 0x6010, - 0xa06d, 0x077e, 0x2039, 0x0000, 0x10c0, 0x5b27, 0x077f, 0x0d7f, - 0x007c, 0x157e, 0x0c7e, 0x2061, 0xaa33, 0x6000, 0x81ff, 0x0040, - 0x5bfc, 0xa205, 0x0078, 0x5bfd, 0xa204, 0x6002, 0x0c7f, 0x157f, - 0x007c, 0x6800, 0xd08c, 0x00c0, 0x5c0d, 0x6808, 0xa005, 0x0040, - 0x5c0d, 0x8001, 0x680a, 0xa085, 0x0001, 0x007c, 0x20a9, 0x0010, - 0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x5c17, 0xa200, 0x00f0, - 0x5c12, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, - 0x0040, 0x5c3d, 0xa11a, 0x00c8, 0x5c3d, 0x8213, 0x818d, 0x0048, - 0x5c30, 0xa11a, 0x00c8, 0x5c31, 0x00f0, 0x5c25, 0x0078, 0x5c35, - 0xa11a, 0x2308, 0x8210, 0x00f0, 0x5c25, 0x007e, 0x3200, 0xa084, - 0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, - 0x0800, 0x0078, 0x5c39, 0x127e, 0x2091, 0x2200, 0x2079, 0xa9b1, - 0x127f, 0x0d7e, 0x2069, 0xa9b1, 0x6803, 0x0005, 0x2069, 0x0004, - 0x2d04, 0xa085, 0x8001, 0x206a, 0x0d7f, 0x007c, 0x0c7e, 0x6027, - 0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x5c5e, 0x5c68, 0x5c8d, - 0x5ce8, 0x5c6e, 0x5c8d, 0x5c68, 0x5c66, 0x5c66, 0x1078, 0x1332, - 0x1078, 0x5acb, 0x1078, 0x62d1, 0x0c7f, 0x007c, 0x62c0, 0x82ff, - 0x00c0, 0x5c74, 0x0c7f, 0x007c, 0x2011, 0x41dc, 0x1078, 0x5a45, - 0x7828, 0xa092, 0x00c8, 0x00c8, 0x5c83, 0x8000, 0x782a, 0x1078, - 0x421b, 0x0078, 0x5c72, 0x1078, 0x41dc, 0x7807, 0x0003, 0x7827, - 0x0000, 0x782b, 0x0000, 0x0078, 0x5c72, 0x1078, 0x5acb, 0x3c00, - 0x007e, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x007f, 0x20e0, - 0x82ff, 0x0040, 0x5cab, 0x62c0, 0x82ff, 0x00c0, 0x5cab, 0x782b, - 0x0000, 0x7824, 0xa065, 0x1040, 0x1332, 0x2009, 0x0013, 0x1078, - 0x775c, 0x0c7f, 0x007c, 0x3900, 0xa082, 0xaae3, 0x00c8, 0x5cb2, - 0x1078, 0x747a, 0x0c7e, 0x7824, 0xa065, 0x1040, 0x1332, 0x7804, - 0xa086, 0x0004, 0x0040, 0x5d2d, 0x7828, 0xa092, 0x2710, 0x00c8, - 0x5cc8, 0x8000, 0x782a, 0x0c7f, 0x1078, 0x6e01, 0x0078, 0x5ca9, - 0x6104, 0xa186, 0x0003, 0x00c0, 0x5cdf, 0x0e7e, 0x2071, 0xa700, - 0x70d8, 0x0e7f, 0xd08c, 0x0040, 0x5cdf, 0x0c7e, 0x0e7e, 0x2061, - 0x0100, 0x2071, 0xa700, 0x1078, 0x4224, 0x0e7f, 0x0c7f, 0x1078, - 0xa5d4, 0x2009, 0x0014, 0x1078, 0x775c, 0x0c7f, 0x0078, 0x5ca9, - 0x2001, 0xa9cd, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x5cfc, - 0x782b, 0x0000, 0x7824, 0xa065, 0x1040, 0x1332, 0x2009, 0x0013, - 0x1078, 0x77b3, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x3900, 0xa082, - 0xaae3, 0x00c8, 0x5d05, 0x1078, 0x747a, 0x7824, 0xa005, 0x1040, - 0x1332, 0x781c, 0xa06d, 0x1040, 0x1332, 0x6800, 0xc0dc, 0x6802, - 0x7924, 0x2160, 0x1078, 0x772d, 0x693c, 0x81ff, 0x1040, 0x1332, - 0x8109, 0x693e, 0x6854, 0xa015, 0x0040, 0x5d21, 0x7a1e, 0x0078, - 0x5d23, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f, - 0x0c7f, 0x1078, 0x62d1, 0x0078, 0x5cfa, 0x6104, 0xa186, 0x0002, - 0x0040, 0x5d38, 0xa186, 0x0004, 0x0040, 0x5d38, 0x0078, 0x5cbc, - 0x7808, 0xac06, 0x0040, 0x5cbc, 0x1078, 0x61cd, 0x1078, 0x5dd7, - 0x0c7f, 0x1078, 0x62d1, 0x0078, 0x5ca9, 0x0c7e, 0x6027, 0x0002, - 0x62c8, 0x82ff, 0x00c0, 0x5d61, 0x62c4, 0x82ff, 0x00c0, 0x5d61, - 0x793c, 0xa1e5, 0x0000, 0x0040, 0x5d5b, 0x2009, 0x0049, 0x1078, - 0x775c, 0x0c7f, 0x007c, 0x2011, 0xa9d0, 0x2013, 0x0000, 0x0078, - 0x5d59, 0x3908, 0xa192, 0xaae3, 0x00c8, 0x5d68, 0x1078, 0x747a, - 0x6017, 0x0010, 0x793c, 0x81ff, 0x0040, 0x5d5b, 0x7944, 0xa192, - 0x7530, 0x00c8, 0x5d85, 0x8108, 0x7946, 0x793c, 0xa188, 0x0007, - 0x210c, 0xa18e, 0x0006, 0x00c0, 0x5d81, 0x6017, 0x0012, 0x0078, - 0x5d59, 0x6017, 0x0016, 0x0078, 0x5d59, 0x7848, 0xc085, 0x784a, - 0x0078, 0x5d59, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, - 0x600f, 0x0000, 0x2c08, 0x2061, 0xa9b1, 0x6020, 0x8000, 0x6022, - 0x6010, 0xa005, 0x0040, 0x5da5, 0xa080, 0x0003, 0x2102, 0x6112, - 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c, 0x6116, 0x6112, 0x0078, - 0x5da0, 0x0d7e, 0x2069, 0xa9b1, 0x6000, 0xd0d4, 0x0040, 0x5dbe, - 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x00c0, 0x5db9, 0x2c00, - 0x681e, 0x6804, 0xa084, 0x0007, 0x0079, 0x62d9, 0xc0d5, 0x6002, - 0x6818, 0xa005, 0x0040, 0x5dd0, 0x6056, 0x605b, 0x0000, 0x007e, - 0x2c00, 0x681a, 0x0d7f, 0x685a, 0x2069, 0xa9b1, 0x0078, 0x5db0, - 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x0078, 0x5db0, 0x007e, - 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, - 0x2061, 0xa9b1, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, - 0x5df2, 0xa080, 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, - 0x007f, 0x007c, 0x610e, 0x610a, 0x0078, 0x5ded, 0x0c7e, 0x600f, - 0x0000, 0x2c08, 0x2061, 0xa9b1, 0x6034, 0xa005, 0x0040, 0x5e06, - 0xa080, 0x0003, 0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136, - 0x0078, 0x5e04, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, - 0x037e, 0x027e, 0x017e, 0x007e, 0x127e, 0xa02e, 0x2071, 0xa9b1, - 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x5e8c, - 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x5e87, 0x87ff, - 0x0040, 0x5e2e, 0x6020, 0xa106, 0x00c0, 0x5e87, 0x703c, 0xac06, - 0x00c0, 0x5e44, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x7033, - 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, - 0x0000, 0x037f, 0x2029, 0x0001, 0x7038, 0xac36, 0x00c0, 0x5e4a, - 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5e58, 0x2c00, 0xaf36, - 0x0040, 0x5e56, 0x2f00, 0x7036, 0x0078, 0x5e58, 0x7037, 0x0000, - 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5e61, 0x7e0e, 0x0078, - 0x5e62, 0x2678, 0x600f, 0x0000, 0x1078, 0x8d16, 0x0040, 0x5e82, - 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5e9d, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x017e, 0x037e, 0x077e, 0x1078, - 0x8f8d, 0x1078, 0xa4f2, 0x1078, 0x4a73, 0x077f, 0x037f, 0x017f, - 0x1078, 0x8ec9, 0x1078, 0x8ed6, 0x0c7f, 0x0078, 0x5e1d, 0x2c78, - 0x600c, 0x2060, 0x0078, 0x5e1d, 0x85ff, 0x0040, 0x5e91, 0x1078, - 0x639b, 0x127f, 0x007f, 0x017f, 0x027f, 0x037f, 0x057f, 0x067f, - 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, - 0x00c0, 0x5e6f, 0x017e, 0x037e, 0x077e, 0x1078, 0xa4f2, 0x1078, - 0xa1da, 0x077f, 0x037f, 0x017f, 0x0078, 0x5e82, 0x007e, 0x067e, - 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000, 0x127e, 0x2091, 0x8000, - 0x2079, 0xa9b1, 0x7838, 0xa065, 0x0040, 0x5eef, 0x600c, 0x007e, - 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0, 0x5ed6, 0x037e, 0x2019, - 0x0001, 0x1078, 0x7058, 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, - 0x0000, 0x7847, 0x0000, 0x784b, 0x0000, 0x037f, 0x1078, 0x8d16, - 0x0040, 0x5eea, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, - 0x5ef8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, - 0x1078, 0x8ec9, 0x1078, 0x8ed6, 0x007f, 0x0078, 0x5ebb, 0x7e3a, - 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, - 0x601c, 0xa086, 0x0006, 0x00c0, 0x5ee1, 0x1078, 0xa1da, 0x0078, - 0x5eea, 0x017e, 0x027e, 0x087e, 0x2041, 0x0000, 0x1078, 0x5f1b, - 0x1078, 0x5fdb, 0x087f, 0x027f, 0x017f, 0x007c, 0x0f7e, 0x127e, - 0x2079, 0xa9b1, 0x2091, 0x8000, 0x1078, 0x6076, 0x1078, 0x60ec, - 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, - 0x017e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x7614, - 0x2660, 0x2678, 0x8cff, 0x0040, 0x5fb5, 0x6018, 0xa080, 0x0028, - 0x2004, 0xa206, 0x00c0, 0x5fb0, 0x88ff, 0x0040, 0x5f3b, 0x6020, - 0xa106, 0x00c0, 0x5fb0, 0x7024, 0xac06, 0x00c0, 0x5f6b, 0x2069, - 0x0100, 0x68c0, 0xa005, 0x0040, 0x5f66, 0x1078, 0x5acb, 0x1078, - 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, - 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5f5b, 0x6803, - 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, - 0x5f63, 0x6827, 0x0001, 0x037f, 0x0078, 0x5f6b, 0x6003, 0x0009, - 0x630a, 0x0078, 0x5fb0, 0x7014, 0xac36, 0x00c0, 0x5f71, 0x660c, - 0x7616, 0x7010, 0xac36, 0x00c0, 0x5f7f, 0x2c00, 0xaf36, 0x0040, - 0x5f7d, 0x2f00, 0x7012, 0x0078, 0x5f7f, 0x7013, 0x0000, 0x660c, - 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5f88, 0x7e0e, 0x0078, 0x5f89, - 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, - 0x5fa9, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5fbe, 0x6837, 0x0103, - 0x6b4a, 0x6847, 0x0000, 0x017e, 0x037e, 0x087e, 0x1078, 0x8f8d, - 0x1078, 0xa4f2, 0x1078, 0x4a73, 0x087f, 0x037f, 0x017f, 0x1078, - 0x8ec9, 0x1078, 0x8ed6, 0x1078, 0x7233, 0x0c7f, 0x0078, 0x5f2a, - 0x2c78, 0x600c, 0x2060, 0x0078, 0x5f2a, 0x127f, 0x007f, 0x017f, - 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, - 0x0006, 0x00c0, 0x5fcf, 0x017e, 0x037e, 0x087e, 0x1078, 0xa4f2, - 0x1078, 0xa1da, 0x087f, 0x037f, 0x017f, 0x0078, 0x5fa9, 0x601c, - 0xa086, 0x0002, 0x00c0, 0x5fa9, 0x6004, 0xa086, 0x0085, 0x0040, - 0x5f96, 0x0078, 0x5fa9, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, - 0xa280, 0xa835, 0x2004, 0xa065, 0x0040, 0x6072, 0x0f7e, 0x0e7e, - 0x0d7e, 0x067e, 0x2071, 0xa9b1, 0x6654, 0x7018, 0xac06, 0x00c0, - 0x5ff2, 0x761a, 0x701c, 0xac06, 0x00c0, 0x5ffe, 0x86ff, 0x00c0, - 0x5ffd, 0x7018, 0x701e, 0x0078, 0x5ffe, 0x761e, 0x6058, 0xa07d, - 0x0040, 0x6003, 0x7e56, 0xa6ed, 0x0000, 0x0040, 0x6009, 0x2f00, - 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, - 0x6002, 0x1078, 0x44d3, 0x0040, 0x606e, 0x7624, 0x86ff, 0x0040, - 0x605c, 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, 0x605c, 0x0d7e, - 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x6053, 0x1078, 0x5acb, - 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7027, 0x0000, - 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x603c, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0040, 0x6044, 0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, - 0xa005, 0x0040, 0x604d, 0x8001, 0x603e, 0x2660, 0x1078, 0x8ed6, - 0x0c7f, 0x0078, 0x605c, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, - 0x630a, 0x0c7f, 0x0078, 0x6011, 0x8dff, 0x0040, 0x606a, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8f8d, 0x1078, 0xa4f2, - 0x1078, 0x4a73, 0x1078, 0x7233, 0x0078, 0x6011, 0x067f, 0x0d7f, - 0x0e7f, 0x0f7f, 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e, - 0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x60d0, - 0x600c, 0x007e, 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x60b5, - 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x60af, 0x1078, 0x5acb, - 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7827, 0x0000, - 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x60a4, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0040, 0x60ac, 0x6827, 0x0001, 0x037f, 0x0078, 0x60b5, 0x6003, - 0x0009, 0x630a, 0x2c30, 0x0078, 0x60cd, 0x6010, 0x2068, 0x1078, - 0x8d16, 0x0040, 0x60c9, 0x601c, 0xa086, 0x0003, 0x00c0, 0x60d7, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078, - 0x8ec9, 0x1078, 0x8ed6, 0x1078, 0x7233, 0x007f, 0x0078, 0x607d, - 0x7e16, 0x7e12, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, - 0xa086, 0x0006, 0x00c0, 0x60e0, 0x1078, 0xa1da, 0x0078, 0x60c9, - 0x601c, 0xa086, 0x0002, 0x00c0, 0x60c9, 0x6004, 0xa086, 0x0085, - 0x0040, 0x60c0, 0x0078, 0x60c9, 0x007e, 0x067e, 0x0c7e, 0x0d7e, - 0x7818, 0xa065, 0x0040, 0x615a, 0x6054, 0x007e, 0x6057, 0x0000, - 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x44d3, - 0x0040, 0x6157, 0x7e24, 0x86ff, 0x0040, 0x6149, 0xa680, 0x0004, - 0x2004, 0xad06, 0x00c0, 0x6149, 0x0d7e, 0x2069, 0x0100, 0x68c0, - 0xa005, 0x0040, 0x6140, 0x1078, 0x5acb, 0x1078, 0x6e0f, 0x68c3, - 0x0000, 0x1078, 0x7378, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140, - 0x6b04, 0xa384, 0x1000, 0x0040, 0x6129, 0x6803, 0x0100, 0x6803, - 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x6131, 0x6827, - 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x613a, - 0x8001, 0x603e, 0x2660, 0x1078, 0x8ed6, 0x0c7f, 0x0078, 0x6149, - 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, - 0x60fe, 0x8dff, 0x0040, 0x6153, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x1078, 0x4a73, 0x1078, 0x7233, 0x0078, 0x60fe, 0x007f, - 0x0078, 0x60f1, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, - 0x007c, 0x0e7e, 0x0d7e, 0x067e, 0x6000, 0xd0dc, 0x0040, 0x6181, - 0x604c, 0xa06d, 0x0040, 0x6181, 0x6848, 0xa606, 0x00c0, 0x6181, - 0x2071, 0xa9b1, 0x7024, 0xa035, 0x0040, 0x6181, 0xa080, 0x0004, - 0x2004, 0xad06, 0x00c0, 0x6181, 0x6000, 0xc0dc, 0x6002, 0x1078, - 0x6185, 0x067f, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x2079, 0x0100, - 0x78c0, 0xa005, 0x00c0, 0x6194, 0x0c7e, 0x2660, 0x6003, 0x0009, - 0x630a, 0x0c7f, 0x0078, 0x61cb, 0x1078, 0x6e0f, 0x78c3, 0x0000, - 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, 0x2079, 0x0140, 0x7b04, - 0xa384, 0x1000, 0x0040, 0x61a8, 0x7803, 0x0100, 0x7803, 0x0000, - 0x2079, 0x0100, 0x7824, 0xd084, 0x0040, 0x61b0, 0x7827, 0x0001, - 0x1078, 0x7378, 0x037f, 0x1078, 0x44d3, 0x0c7e, 0x603c, 0xa005, - 0x0040, 0x61bc, 0x8001, 0x603e, 0x2660, 0x1078, 0x772d, 0x0c7f, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8f8d, 0x1078, - 0x4a73, 0x1078, 0x7233, 0x0f7f, 0x007c, 0x0e7e, 0x0c7e, 0x2071, - 0xa9b1, 0x7004, 0xa084, 0x0007, 0x0079, 0x61d6, 0x61e0, 0x61e3, - 0x61fc, 0x6218, 0x6262, 0x61e0, 0x61e0, 0x61de, 0x1078, 0x1332, - 0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040, 0x61f1, 0x7020, - 0x8001, 0x7022, 0x600c, 0xa015, 0x0040, 0x61f8, 0x7216, 0x600f, - 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, - 0x7216, 0x7212, 0x0078, 0x61f1, 0x6018, 0x2060, 0x1078, 0x44d3, - 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0040, 0x620d, - 0x6054, 0xa015, 0x0040, 0x6214, 0x721e, 0x7007, 0x0000, 0x7027, - 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7218, 0x721e, 0x0078, 0x620d, - 0x7024, 0xa065, 0x0040, 0x625f, 0x700c, 0xac06, 0x00c0, 0x622f, - 0x1078, 0x7233, 0x600c, 0xa015, 0x0040, 0x622b, 0x720e, 0x600f, - 0x0000, 0x0078, 0x625d, 0x720e, 0x720a, 0x0078, 0x625d, 0x7014, - 0xac06, 0x00c0, 0x6242, 0x1078, 0x7233, 0x600c, 0xa015, 0x0040, - 0x623e, 0x7216, 0x600f, 0x0000, 0x0078, 0x625d, 0x7216, 0x7212, - 0x0078, 0x625d, 0x601c, 0xa086, 0x0003, 0x00c0, 0x625d, 0x6018, - 0x2060, 0x1078, 0x44d3, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x7233, - 0x701c, 0xa065, 0x0040, 0x625d, 0x6054, 0xa015, 0x0040, 0x625b, - 0x721e, 0x0078, 0x625d, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, - 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040, 0x626f, 0x1078, 0x7233, - 0x600c, 0xa015, 0x0040, 0x6276, 0x720e, 0x600f, 0x0000, 0x1078, - 0x7378, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, - 0x0078, 0x626f, 0x0d7e, 0x2069, 0xa9b1, 0x6830, 0xa084, 0x0003, - 0x0079, 0x6282, 0x6288, 0x628a, 0x62b4, 0x6288, 0x1078, 0x1332, - 0x0d7f, 0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x62aa, - 0x683c, 0xa065, 0x0040, 0x629b, 0x600c, 0xa015, 0x0040, 0x62a6, - 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, - 0xa9d0, 0x2013, 0x0000, 0x0c7f, 0x0d7f, 0x007c, 0x683a, 0x6836, - 0x0078, 0x629b, 0x6843, 0x0000, 0x6838, 0xa065, 0x0040, 0x629b, - 0x6003, 0x0003, 0x0078, 0x629b, 0x0c7e, 0x6843, 0x0000, 0x6847, - 0x0000, 0x684b, 0x0000, 0x683c, 0xa065, 0x0040, 0x62ce, 0x600c, - 0xa015, 0x0040, 0x62ca, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, - 0x0078, 0x62ce, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f, - 0x007c, 0x0d7e, 0x2069, 0xa9b1, 0x6804, 0xa084, 0x0007, 0x0079, - 0x62d9, 0x62e3, 0x638a, 0x638a, 0x638a, 0x638a, 0x638c, 0x638a, - 0x62e1, 0x1078, 0x1332, 0x6820, 0xa005, 0x00c0, 0x62e9, 0x0d7f, - 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x62f8, 0x6807, 0x0004, - 0x6826, 0x682b, 0x0000, 0x1078, 0x63d4, 0x0c7f, 0x0d7f, 0x007c, - 0x6814, 0xa065, 0x0040, 0x6306, 0x6807, 0x0001, 0x6826, 0x682b, - 0x0000, 0x1078, 0x63d4, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, 0x037e, - 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x6385, 0x704c, 0xa00d, 0x0040, - 0x6315, 0x7088, 0xa005, 0x0040, 0x632d, 0x7054, 0xa075, 0x0040, - 0x631e, 0xa20e, 0x0040, 0x6385, 0x0078, 0x6323, 0x6818, 0xa20e, - 0x0040, 0x6385, 0x2070, 0x704c, 0xa00d, 0x0040, 0x6315, 0x7088, - 0xa005, 0x00c0, 0x6315, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, - 0x00c8, 0x6315, 0x1078, 0x76fc, 0x0040, 0x6385, 0x8318, 0x733e, - 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff, - 0x6032, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004, - 0xa08a, 0x199a, 0x0048, 0x634e, 0x2001, 0x1999, 0x8003, 0x801b, - 0x831b, 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc, - 0x0040, 0x6367, 0x7100, 0xd1f4, 0x0040, 0x6363, 0x7114, 0xa18c, - 0x00ff, 0x0078, 0x636c, 0x2009, 0x0000, 0x0078, 0x636c, 0xa1e0, - 0x29c0, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, - 0x6965, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, - 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, - 0x0f7f, 0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f, - 0x0078, 0x6383, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, - 0x6398, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x63d4, - 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0xa9b1, 0x6830, - 0xa086, 0x0000, 0x00c0, 0x63bb, 0x6838, 0xa07d, 0x0040, 0x63bb, - 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x127e, - 0x0f7e, 0x2091, 0x2200, 0x027f, 0x1078, 0x1d6d, 0x00c0, 0x63be, - 0x127f, 0x1078, 0x6cb3, 0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843, - 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0040, 0x63d0, 0x6a3a, - 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x63bb, - 0x683a, 0x6836, 0x0078, 0x63ca, 0x601c, 0xa084, 0x000f, 0x1079, - 0x63da, 0x007c, 0x63e3, 0x63e8, 0x6809, 0x6922, 0x63e8, 0x6809, - 0x6922, 0x63e3, 0x63e8, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x007c, - 0x157e, 0x137e, 0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0044, - 0x10c8, 0x1332, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x6405, - 0x7900, 0xd1f4, 0x0040, 0x6401, 0x7914, 0xa18c, 0x00ff, 0x0078, - 0x640a, 0x2009, 0x0000, 0x0078, 0x640a, 0xa1f8, 0x29c0, 0x2f0c, - 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, - 0x00c8, 0x645c, 0x1079, 0x641a, 0x0f7f, 0x0c7f, 0x147f, 0x137f, - 0x157f, 0x007c, 0x64c2, 0x650a, 0x6532, 0x65cd, 0x65fd, 0x6605, - 0x662c, 0x663d, 0x664e, 0x6656, 0x666e, 0x6656, 0x66d9, 0x663d, - 0x66fa, 0x6702, 0x664e, 0x6702, 0x6713, 0x645a, 0x645a, 0x645a, - 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, - 0x6eef, 0x6f14, 0x6f29, 0x6f4c, 0x6f6d, 0x662c, 0x645a, 0x662c, - 0x6656, 0x645a, 0x6532, 0x65cd, 0x645a, 0x749c, 0x6656, 0x645a, - 0x74bc, 0x6656, 0x645a, 0x645a, 0x64bd, 0x646b, 0x645a, 0x74e1, - 0x7558, 0x7640, 0x645a, 0x7651, 0x6626, 0x766d, 0x645a, 0x6f82, - 0x645a, 0x645a, 0x1078, 0x1332, 0x2100, 0x1079, 0x6465, 0x0f7f, - 0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c, 0x6469, 0x6469, 0x6469, - 0x649f, 0x1078, 0x1332, 0x0d7e, 0x20a1, 0x020b, 0x1078, 0x6731, - 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, - 0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6dfb, 0x0d7f, 0x007c, - 0x0d7e, 0x7818, 0x2068, 0x68a0, 0xa082, 0x007e, 0x0048, 0x649c, - 0xa085, 0x0001, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x649a, 0x0d7e, - 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x0500, 0x20a3, 0x0000, - 0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, - 0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, - 0x0010, 0x1078, 0x6dfb, 0x0d7f, 0x007c, 0x6030, 0x609a, 0x1078, - 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x5200, - 0x20a3, 0x0000, 0x0d7e, 0x2069, 0xa752, 0x6804, 0xd084, 0x0040, - 0x64dc, 0x6828, 0x20a3, 0x0000, 0x017e, 0x1078, 0x2564, 0x21a2, - 0x017f, 0x0d7f, 0x0078, 0x64e1, 0x0d7f, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a9, 0x0004, 0x2099, 0xa705, 0x53a6, 0x20a9, 0x0004, - 0x2099, 0xa701, 0x53a6, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, - 0x007f, 0x0048, 0x64fb, 0x2001, 0xa71b, 0x20a6, 0x2001, 0xa71c, - 0x20a6, 0x0078, 0x6501, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, - 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, - 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x0500, - 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, - 0x0048, 0x6522, 0x2001, 0xa71b, 0x20a6, 0x2001, 0xa71c, 0x20a6, - 0x0078, 0x6528, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, - 0x20a9, 0x0004, 0x2099, 0xa705, 0x53a6, 0x60c3, 0x0010, 0x1078, - 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x0c7e, 0x7818, - 0x2060, 0x2001, 0x0000, 0x1078, 0x4972, 0x0c7f, 0x7818, 0xa080, - 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x654d, 0x20a3, 0x0400, - 0x620c, 0xc2b4, 0x620e, 0x0078, 0x654f, 0x20a3, 0x0300, 0x20a3, - 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, - 0x659c, 0x2099, 0xa98d, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, - 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, - 0xa705, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa701, 0x53a6, 0x20a9, - 0x0010, 0x20a3, 0x0000, 0x00f0, 0x6579, 0x2099, 0xa995, 0x3304, - 0xc0dd, 0x20a2, 0x2001, 0xa772, 0x2004, 0xd0e4, 0x0040, 0x6594, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, - 0x20a9, 0x0004, 0x0078, 0x6596, 0x20a9, 0x0007, 0x20a3, 0x0000, - 0x00f0, 0x6596, 0x0078, 0x65bc, 0x2099, 0xa98d, 0x20a9, 0x0008, - 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa705, 0x53a6, 0x20a9, 0x0004, - 0x2099, 0xa701, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, - 0x65ad, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x65b3, 0x2099, - 0xa995, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, - 0x00f0, 0x65be, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x65c4, - 0x60c3, 0x0074, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, - 0x6731, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, - 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, - 0x2079, 0xa752, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x65e9, 0xa085, - 0x0020, 0xd1a4, 0x0040, 0x65ee, 0xa085, 0x0010, 0xa085, 0x0002, - 0x0d7e, 0x0078, 0x66b7, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, - 0x6731, 0x20a3, 0x5000, 0x0078, 0x654f, 0x20a1, 0x020b, 0x1078, - 0x6731, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, - 0x1078, 0x67b9, 0x0078, 0x6630, 0x20a1, 0x020b, 0x1078, 0x67c2, - 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0004, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, - 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, - 0x2a00, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, - 0x1078, 0x67c2, 0x20a3, 0x0200, 0x0078, 0x654f, 0x20a1, 0x020b, - 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, - 0x0040, 0x6665, 0x20a2, 0x0078, 0x6667, 0x20a3, 0x0003, 0x7810, - 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x0d7e, 0x20a1, - 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, - 0x0800, 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x6694, - 0x6998, 0xa184, 0xc000, 0x00c0, 0x6690, 0xd1ec, 0x0040, 0x668c, - 0x20a3, 0x2100, 0x0078, 0x6696, 0x20a3, 0x0100, 0x0078, 0x6696, - 0x20a3, 0x0400, 0x0078, 0x6696, 0x20a3, 0x0700, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa752, 0x7904, - 0x0f7f, 0xd1ac, 0x00c0, 0x66a6, 0xa085, 0x0020, 0xd1a4, 0x0040, - 0x66ab, 0xa085, 0x0010, 0x2009, 0xa774, 0x210c, 0xd184, 0x0040, - 0x66b5, 0x699c, 0xd18c, 0x0040, 0x66b7, 0xa085, 0x0002, 0x027e, - 0x2009, 0xa772, 0x210c, 0xd1e4, 0x0040, 0x66c5, 0xc0c5, 0xa094, - 0x0030, 0xa296, 0x0010, 0x0040, 0x66cf, 0xd1ec, 0x0040, 0x66cf, - 0xa094, 0x0030, 0xa296, 0x0010, 0x0040, 0x66cf, 0xc0bd, 0x027f, - 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x0d7f, - 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0210, 0x20a3, - 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, - 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0200, - 0x0078, 0x64c8, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, - 0x1078, 0x6dfb, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, - 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, - 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, - 0x027e, 0x037e, 0x047e, 0x2019, 0x3200, 0x2021, 0x0800, 0x0078, - 0x6738, 0x027e, 0x037e, 0x047e, 0x2019, 0x2200, 0x2021, 0x0100, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, - 0xa286, 0x007e, 0x00c0, 0x674b, 0xa385, 0x00ff, 0x20a2, 0x20a3, - 0xfffe, 0x0078, 0x6780, 0xa286, 0x007f, 0x00c0, 0x6757, 0x0d7e, - 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x0078, 0x676e, 0xd2bc, - 0x0040, 0x6776, 0xa286, 0x0080, 0x0d7e, 0x00c0, 0x6766, 0xa385, - 0x00ff, 0x20a2, 0x20a3, 0xfffc, 0x0078, 0x676e, 0xa2e8, 0xa835, - 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6784, 0x0d7e, 0xa2e8, - 0xa835, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, - 0x20a3, 0x0000, 0x6230, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x047f, - 0x037f, 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, - 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, - 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, - 0x2011, 0xfffc, 0x22a2, 0x0d7e, 0x2069, 0xa71b, 0x2da6, 0x8d68, - 0x2da6, 0x0d7f, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, 0x678b, - 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, - 0x007c, 0x027e, 0x037e, 0x047e, 0x2019, 0x3300, 0x2021, 0x0800, - 0x0078, 0x67c9, 0x027e, 0x037e, 0x047e, 0x2019, 0x2300, 0x2021, - 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0xa092, 0x007e, 0x0048, 0x67e6, 0x0d7e, 0xa0e8, 0xa835, - 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x67f4, 0x0d7e, 0xa0e8, - 0xa835, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, - 0x20a3, 0x0000, 0x6230, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, - 0x0000, 0x047f, 0x037f, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, - 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, - 0x007c, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1332, - 0xa08a, 0x008c, 0x10c8, 0x1332, 0x6118, 0x2178, 0x79a0, 0xd1bc, - 0x0040, 0x6827, 0x7900, 0xd1f4, 0x0040, 0x6823, 0x7914, 0xa18c, - 0x00ff, 0x0078, 0x682c, 0x2009, 0x0000, 0x0078, 0x682c, 0xa1f8, - 0x29c0, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, - 0xa082, 0x0085, 0x1079, 0x6837, 0x0f7f, 0x0c7f, 0x007c, 0x6840, - 0x684b, 0x6866, 0x683e, 0x683e, 0x683e, 0x6840, 0x1078, 0x1332, - 0x147e, 0x20a1, 0x020b, 0x1078, 0x6879, 0x60c3, 0x0000, 0x1078, - 0x6dfb, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, 0x68ad, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, - 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x147f, 0x007c, 0x147e, 0x20a1, - 0x020b, 0x1078, 0x68ee, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x1078, 0x6dfb, 0x147f, - 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, - 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x6898, 0x0d7e, 0xa0e8, - 0xa835, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, - 0x2069, 0xa71b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x68a7, - 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, - 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, - 0x0009, 0x20a3, 0x0000, 0x0078, 0x678b, 0x027e, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, - 0x0048, 0x68cc, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, - 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, 0x2da6, 0x8d68, - 0x2da6, 0x0d7f, 0x0078, 0x68db, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, - 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, - 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x1078, - 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7a10, 0x22a2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e, 0x20e1, - 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, - 0x007e, 0x0048, 0x690d, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, - 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, 0x2da6, - 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x691c, 0x0d7e, 0xa0e8, 0xa835, - 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, - 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, - 0x0078, 0x68df, 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040, - 0x1048, 0x1332, 0xa08a, 0x0053, 0x10c8, 0x1332, 0x7918, 0x2160, - 0x61a0, 0xd1bc, 0x0040, 0x6941, 0x6100, 0xd1f4, 0x0040, 0x693d, - 0x6114, 0xa18c, 0x00ff, 0x0078, 0x6946, 0x2009, 0x0000, 0x0078, - 0x6946, 0xa1e0, 0x29c0, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, - 0x619a, 0xa082, 0x0040, 0x1079, 0x6950, 0x0f7f, 0x0c7f, 0x007c, - 0x6965, 0x6a73, 0x6a14, 0x6c27, 0x6963, 0x6963, 0x6963, 0x6963, - 0x6963, 0x6963, 0x6963, 0x714c, 0x715d, 0x716e, 0x717f, 0x6963, - 0x767e, 0x6963, 0x713b, 0x1078, 0x1332, 0x0d7e, 0x157e, 0x147e, - 0x780b, 0xffff, 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7910, 0x2168, - 0x6948, 0x7922, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, - 0xa184, 0x000f, 0x00c0, 0x6980, 0x2001, 0x0005, 0x0078, 0x698a, - 0xd184, 0x0040, 0x6987, 0x2001, 0x0004, 0x0078, 0x698a, 0xa084, - 0x0006, 0x8004, 0x017e, 0x2008, 0x7830, 0xa084, 0x00ff, 0x8007, - 0xa105, 0x017f, 0x20a2, 0xd1ac, 0x0040, 0x699a, 0x20a3, 0x0002, - 0x0078, 0x69a6, 0xd1b4, 0x0040, 0x69a1, 0x20a3, 0x0001, 0x0078, - 0x69a6, 0x20a3, 0x0000, 0x2230, 0x0078, 0x69a8, 0x6a80, 0x6e7c, - 0x20a9, 0x0008, 0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, - 0x00f0, 0x69ac, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, - 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xa9cd, - 0x2003, 0x07d0, 0x2001, 0xa9cc, 0x2003, 0x0009, 0x2001, 0xa9d2, - 0x2003, 0x0002, 0x1078, 0x158c, 0x147f, 0x157f, 0x0d7f, 0x007c, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, - 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, - 0x2004, 0xd0bc, 0x0040, 0x69f6, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, - 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6a05, 0x0d7e, 0xa0e8, - 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, - 0x0d7f, 0x20a3, 0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3, - 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, - 0x20a1, 0x020b, 0x1078, 0x6a34, 0x7810, 0x2068, 0x6860, 0x20a2, - 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x147f, - 0x137f, 0x157f, 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6a52, - 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xa71b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, - 0x0078, 0x6a61, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, - 0x0500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, - 0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, - 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x7810, - 0xa0ec, 0xf000, 0x0040, 0x6a8b, 0xa06d, 0x1078, 0x495f, 0x0040, - 0x6a8b, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6a8b, - 0x7824, 0xc0cd, 0x7826, 0x20a1, 0x020b, 0x1078, 0x6be0, 0xa016, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, - 0x00c0, 0x6aa2, 0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x6aaa, - 0x0078, 0x6aa5, 0xa006, 0x1079, 0x6aaa, 0x147f, 0x137f, 0x157f, - 0x0d7f, 0x007c, 0x6ab4, 0x6b4c, 0x6b57, 0x6b81, 0x6b95, 0x6bb1, - 0x6bbc, 0x6ab2, 0x1078, 0x1332, 0x017e, 0x037e, 0x694c, 0xa18c, - 0x0003, 0x0040, 0x6abf, 0xa186, 0x0003, 0x00c0, 0x6ace, 0x6b78, - 0x7824, 0xd0cc, 0x0040, 0x6ac5, 0xc3e5, 0x23a2, 0x6868, 0x20a2, - 0x6864, 0x20a2, 0x037f, 0x017f, 0x0078, 0x6b8c, 0xa186, 0x0001, - 0x10c0, 0x1332, 0x6b78, 0x7824, 0xd0cc, 0x0040, 0x6ad8, 0xc3e5, - 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, - 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, 0x0040, - 0x6b46, 0xd3c4, 0x0040, 0x6aee, 0x687c, 0xa108, 0xd3cc, 0x0040, - 0x6af3, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80, 0x0020, - 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x6af8, 0x157f, 0x22a2, - 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x6b46, 0x20a1, 0x020b, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x007e, 0x7818, 0xa080, 0x0028, - 0x2004, 0xd0bc, 0x0040, 0x6b26, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, - 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6b35, 0x0d7e, 0xa0e8, - 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, - 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x007f, 0x7b24, 0xd3cc, - 0x0040, 0x6b3e, 0x20a3, 0x0889, 0x0078, 0x6b40, 0x20a3, 0x0898, - 0x20a2, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f, - 0x017f, 0x1078, 0x6dfb, 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, - 0x0040, 0x6b53, 0xc2e5, 0x22a2, 0xa016, 0x0078, 0x6b8a, 0x2011, - 0x0302, 0x7824, 0xd0cc, 0x0040, 0x6b5e, 0xc2e5, 0x22a2, 0xa016, - 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, - 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x1078, 0x6dfb, - 0x007c, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x0040, 0x6b88, 0xc2e5, - 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, - 0x60c3, 0x0018, 0x1078, 0x6dfb, 0x007c, 0x2011, 0x0100, 0x7824, - 0xd0cc, 0x0040, 0x6b9c, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, - 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7834, 0xa084, - 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x6dfb, - 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0040, 0x6bb8, 0xc2e5, - 0x22a2, 0xa016, 0x0078, 0x6b8a, 0x037e, 0x7b10, 0xa384, 0xff00, - 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x6bcf, 0x7824, 0xd0cc, - 0x0040, 0x6bcb, 0xc2e5, 0x22a2, 0x037f, 0x0078, 0x6b8a, 0x047e, - 0x2021, 0x0800, 0x007e, 0x7824, 0xd0cc, 0x007f, 0x0040, 0x6bd9, - 0xc4e5, 0x24a2, 0x047f, 0x22a2, 0x20a2, 0x037f, 0x0078, 0x6b8c, - 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0xd0bc, 0x0040, 0x6bfe, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, - 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6c0d, 0x0d7e, 0xa0e8, - 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, - 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x7824, 0xd0cc, 0x0040, - 0x6c15, 0x20a3, 0x0889, 0x0078, 0x6c17, 0x20a3, 0x0898, 0x20a3, - 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, - 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0d7e, - 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810, 0xa084, 0x0700, - 0x8007, 0x1079, 0x6c3a, 0x037f, 0x017f, 0x147f, 0x137f, 0x157f, - 0x0d7f, 0x007c, 0x6c42, 0x6c42, 0x6c44, 0x6c42, 0x6c42, 0x6c42, - 0x6c69, 0x6c42, 0x1078, 0x1332, 0x7910, 0xa18c, 0xf8ff, 0xa18d, - 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x6c73, - 0x0d7e, 0x2069, 0xa752, 0x6804, 0xd0bc, 0x0040, 0x6c5e, 0x682c, - 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x6c60, 0x20a3, 0x3f00, - 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x1078, 0x6dfb, - 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x6c73, 0x20a3, - 0x7f00, 0x0078, 0x6c61, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6c91, 0x0d7e, - 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, - 0x20a2, 0x2069, 0xa71b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, - 0x6ca0, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0100, - 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, - 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078, 0x6dea, 0x22a2, - 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x057e, 0x047e, - 0x037e, 0x2061, 0x0100, 0x2071, 0xa700, 0x6130, 0x7818, 0x2068, - 0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x6cca, 0x6910, 0x6a14, 0x6430, - 0x0078, 0x6cce, 0x6910, 0x6a14, 0x736c, 0x7470, 0x781c, 0xa086, - 0x0006, 0x0040, 0x6d2d, 0xd5bc, 0x0040, 0x6cde, 0xa185, 0x0100, - 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6ce5, 0xa185, 0x0100, - 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073, 0x0809, 0x6077, - 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, - 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810, 0x2070, - 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, - 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0xa582, 0x0080, 0x0048, 0x6d17, 0x6a00, 0xd2f4, 0x0040, 0x6d15, - 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6d17, 0x2011, 0x0000, 0x629e, - 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, - 0x0040, 0x6d24, 0x2009, 0x1b58, 0x1078, 0x5ad0, 0x037f, 0x047f, - 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810, 0x2070, 0x704c, - 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x6d85, 0xd5bc, 0x0040, - 0x6d41, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, - 0x6d48, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, - 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, - 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, - 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, 0x707c, - 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, 0xa109, - 0x792a, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, - 0x0000, 0xa582, 0x0080, 0x0048, 0x6d80, 0x6a00, 0xd2f4, 0x0040, - 0x6d7e, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6d80, 0x2011, 0x0000, - 0x629e, 0x6017, 0x0012, 0x0078, 0x6d1a, 0xd5bc, 0x0040, 0x6d90, - 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6d97, - 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x1078, - 0x495f, 0x0040, 0x6dad, 0x0d7e, 0x7810, 0xa06d, 0x684c, 0x0d7f, - 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6dad, 0x7824, 0xc0cd, - 0x7826, 0x6073, 0x0889, 0x0078, 0x6daf, 0x6073, 0x0898, 0x6077, - 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, - 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7014, 0x608a, - 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, - 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, - 0x0048, 0x6ddd, 0x6a00, 0xd2f4, 0x0040, 0x6ddb, 0x6a14, 0xa294, - 0x00ff, 0x0078, 0x6ddd, 0x2011, 0x0000, 0x629e, 0x7824, 0xd0cc, - 0x0040, 0x6de6, 0x6017, 0x0016, 0x0078, 0x6d1a, 0x6017, 0x0012, - 0x0078, 0x6d1a, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, - 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e, 0x2069, 0xa9b1, 0x6843, - 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x1078, 0x6e06, 0x1078, 0x5ac0, 0x007c, 0x007e, 0x6014, - 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x007f, 0x007c, 0x007e, - 0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, - 0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e, 0x0d7e, 0x017e, 0x027e, - 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, - 0x6e59, 0x1078, 0x6e0f, 0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e, - 0x2061, 0xa9b1, 0x6128, 0xa192, 0x00c8, 0x00c8, 0x6e44, 0x8108, - 0x612a, 0x6124, 0x0c7f, 0x81ff, 0x0040, 0x6e54, 0x1078, 0x5ac0, - 0x1078, 0x6e06, 0x0078, 0x6e54, 0x6124, 0xa1e5, 0x0000, 0x0040, - 0x6e51, 0x1078, 0xa5d4, 0x1078, 0x5acb, 0x2009, 0x0014, 0x1078, - 0x775c, 0x0c7f, 0x0078, 0x6e54, 0x027f, 0x017f, 0x0d7f, 0x0c7f, - 0x007c, 0x2001, 0xa9cd, 0x2004, 0xa005, 0x00c0, 0x6e54, 0x0c7e, - 0x2061, 0xa9b1, 0x6128, 0xa192, 0x0003, 0x00c8, 0x6e44, 0x8108, - 0x612a, 0x0c7f, 0x1078, 0x5ac0, 0x1078, 0x4224, 0x0078, 0x6e54, - 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x5ad8, 0x2071, - 0xa9b1, 0x713c, 0x81ff, 0x0040, 0x6e9a, 0x2061, 0x0100, 0x2069, - 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x6ea0, 0x6803, 0x1000, - 0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x037f, - 0x713c, 0x2160, 0x1078, 0xa5d4, 0x2009, 0x004a, 0x1078, 0x775c, - 0x0078, 0x6e9a, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, - 0x0078, 0x6e8a, 0x0e7e, 0x2071, 0xa9b1, 0x7048, 0xd084, 0x0040, - 0x6ebc, 0x713c, 0x81ff, 0x0040, 0x6ebc, 0x2071, 0x0100, 0xa188, - 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, 0x6eba, 0x7017, 0x0012, - 0x0078, 0x6ebc, 0x7017, 0x0016, 0x0e7f, 0x007c, 0x0e7e, 0x0d7e, - 0x0c7e, 0x067e, 0x057e, 0x047e, 0x007e, 0x127e, 0x2091, 0x8000, - 0x6018, 0x2068, 0x6ca0, 0x2071, 0xa9b1, 0x7018, 0x2068, 0x8dff, - 0x0040, 0x6ee6, 0x68a0, 0xa406, 0x0040, 0x6eda, 0x6854, 0x2068, - 0x0078, 0x6ecf, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60, - 0x1078, 0x4736, 0x0040, 0x6ee6, 0xa085, 0x0001, 0x127f, 0x007f, - 0x047f, 0x057f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x20a1, - 0x020b, 0x1078, 0x6731, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x781c, 0xa086, 0x0004, 0x00c0, 0x6f01, 0x6098, 0x0078, - 0x6f02, 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, - 0x0010, 0xa006, 0x20a2, 0x00f0, 0x6f0a, 0x20a2, 0x20a2, 0x60c3, - 0x002c, 0x1078, 0x6dfb, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, - 0x1078, 0x6731, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x147f, 0x157f, - 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, - 0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0xa740, 0x2019, - 0xa741, 0x23a6, 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x00f0, - 0x6f39, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, - 0x6dfb, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, - 0x20a1, 0x020b, 0x1078, 0x6799, 0x1078, 0x67b0, 0x7810, 0xa080, - 0x0000, 0x2004, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, - 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, 0x1078, 0x6dfb, - 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, - 0x020b, 0x1078, 0x6731, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x147f, - 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, - 0x1078, 0x6731, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, - 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, - 0x1078, 0x6dfb, 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x0e7e, - 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x700c, - 0x2060, 0x8cff, 0x0040, 0x6fbb, 0x1078, 0x8f10, 0x00c0, 0x6fb2, - 0x1078, 0x7c83, 0x600c, 0x007e, 0x1078, 0x772d, 0x1078, 0x7233, - 0x0c7f, 0x0078, 0x6fa9, 0x700f, 0x0000, 0x700b, 0x0000, 0x127f, - 0x007f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e, - 0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069, - 0x0100, 0x2079, 0x0140, 0x2071, 0xa9b1, 0x7024, 0x2060, 0x8cff, - 0x0040, 0x7014, 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x5acb, - 0x2009, 0x0013, 0x1078, 0x775c, 0x20a9, 0x01f4, 0x6824, 0xd094, - 0x0040, 0x6ff7, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, - 0x7009, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x7009, 0xd084, - 0x0040, 0x6ffe, 0x6827, 0x0001, 0x0078, 0x7000, 0x00f0, 0x6fe6, - 0x7804, 0xa084, 0x1000, 0x0040, 0x7009, 0x7803, 0x0100, 0x7803, - 0x0000, 0x6824, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, - 0x0f7f, 0x157f, 0x127f, 0x007c, 0x2001, 0xa700, 0x2004, 0xa096, - 0x0001, 0x0040, 0x704e, 0xa096, 0x0004, 0x0040, 0x704e, 0x1078, - 0x5acb, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x41dc, 0x1078, - 0x5a45, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x703c, 0x6827, - 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x704e, 0x7803, 0x1000, - 0x7803, 0x0000, 0x0078, 0x704e, 0xd084, 0x0040, 0x7043, 0x6827, - 0x0001, 0x0078, 0x7045, 0x00f0, 0x702b, 0x7804, 0xa084, 0x1000, - 0x0040, 0x704e, 0x7803, 0x0100, 0x7803, 0x0000, 0x007f, 0x017f, - 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, - 0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e, - 0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0xa9b1, 0x703c, 0x2060, 0x8cff, 0x0040, 0x70d6, 0x68af, 0x95f5, - 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x00c0, 0x7074, 0x68c7, - 0x0000, 0x68cb, 0x0008, 0x1078, 0x5ad8, 0x1078, 0x1f7e, 0x047e, - 0x057e, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5, 0x2021, 0x0169, - 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x70a5, 0x68c7, - 0x0000, 0x68cb, 0x0008, 0x0e7e, 0x0f7e, 0x2079, 0x0020, 0x2071, - 0xaa08, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012, 0x6816, 0x7803, - 0x0008, 0x7003, 0x0000, 0x0f7f, 0x0e7f, 0x250a, 0x057f, 0x047f, - 0xa39d, 0x0000, 0x00c0, 0x70b0, 0x2009, 0x0049, 0x1078, 0x775c, - 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x70c3, 0x6827, 0x0004, - 0x7804, 0xa084, 0x4000, 0x0040, 0x70d5, 0x7803, 0x1000, 0x7803, - 0x0000, 0x0078, 0x70d5, 0xd08c, 0x0040, 0x70ca, 0x6827, 0x0002, - 0x0078, 0x70cc, 0x00f0, 0x70b2, 0x7804, 0xa084, 0x1000, 0x0040, - 0x70d5, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f, - 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, - 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa9b1, 0x6a06, 0x127f, - 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa9b1, - 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, - 0x007e, 0x127e, 0x2071, 0xa9b1, 0x7614, 0x2660, 0x2678, 0x2091, - 0x8000, 0x8cff, 0x0040, 0x7134, 0x601c, 0xa206, 0x00c0, 0x712f, - 0x7014, 0xac36, 0x00c0, 0x710e, 0x660c, 0x7616, 0x7010, 0xac36, - 0x00c0, 0x711c, 0x2c00, 0xaf36, 0x0040, 0x711a, 0x2f00, 0x7012, - 0x0078, 0x711c, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, - 0x0040, 0x7125, 0x7e0e, 0x0078, 0x7126, 0x2678, 0x600f, 0x0000, - 0x1078, 0x8ed6, 0x1078, 0x7233, 0x0c7f, 0x0078, 0x7101, 0x2c78, - 0x600c, 0x2060, 0x0078, 0x7101, 0x127f, 0x007f, 0x067f, 0x0c7f, - 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, - 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, - 0x20a3, 0x1000, 0x0078, 0x718e, 0x157e, 0x147e, 0x20a1, 0x020b, - 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, - 0x20a2, 0x20a3, 0x4000, 0x0078, 0x718e, 0x157e, 0x147e, 0x20a1, - 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, - 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x0078, 0x718e, 0x157e, 0x147e, - 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x718e, 0x157e, - 0x147e, 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, - 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x723e, - 0x60c3, 0x0020, 0x1078, 0x6dfb, 0x147f, 0x157f, 0x007c, 0x127e, - 0x0c7e, 0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0, - 0x71a6, 0xd1bc, 0x00c0, 0x71f0, 0x0078, 0x7230, 0x2009, 0x017f, - 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9, - 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x71e7, - 0x6020, 0xd0b4, 0x0040, 0x71e7, 0x6024, 0xd094, 0x00c0, 0x71e7, - 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x71e7, 0x00f0, - 0x71b3, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, - 0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, 0xbc91, 0x6043, - 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0, - 0x71e6, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x71dd, 0x027f, 0x0d7f, - 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x7230, - 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, - 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, - 0x0040, 0x7229, 0x6020, 0xd0bc, 0x0040, 0x7229, 0x2104, 0xa084, - 0x000f, 0xa086, 0x0004, 0x00c0, 0x7229, 0x00f0, 0x71fd, 0x027e, - 0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d, - 0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, 0x0001, 0x6043, - 0x0000, 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x7223, - 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, - 0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0xa9b1, 0x7020, 0xa005, - 0x0040, 0x723c, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008, - 0x20a2, 0x00f0, 0x7240, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e, - 0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, - 0x2071, 0xa9b1, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, - 0x0040, 0x72e2, 0x8cff, 0x0040, 0x72e2, 0x601c, 0xa086, 0x0006, - 0x00c0, 0x72dd, 0x88ff, 0x0040, 0x726d, 0x2800, 0xac06, 0x00c0, - 0x72dd, 0x2039, 0x0000, 0x0078, 0x7278, 0x6018, 0xa206, 0x00c0, - 0x72dd, 0x85ff, 0x0040, 0x7278, 0x6020, 0xa106, 0x00c0, 0x72dd, - 0x7024, 0xac06, 0x00c0, 0x72a8, 0x2069, 0x0100, 0x68c0, 0xa005, - 0x0040, 0x72a3, 0x1078, 0x5acb, 0x6817, 0x0008, 0x68c3, 0x0000, - 0x1078, 0x7378, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, - 0xa384, 0x1000, 0x0040, 0x7298, 0x6803, 0x0100, 0x6803, 0x0000, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x72a0, 0x6827, 0x0001, - 0x037f, 0x0078, 0x72a8, 0x6003, 0x0009, 0x630a, 0x0078, 0x72dd, - 0x7014, 0xac36, 0x00c0, 0x72ae, 0x660c, 0x7616, 0x7010, 0xac36, - 0x00c0, 0x72bc, 0x2c00, 0xaf36, 0x0040, 0x72ba, 0x2f00, 0x7012, - 0x0078, 0x72bc, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, - 0x0040, 0x72c5, 0x7e0e, 0x0078, 0x72c6, 0x2678, 0x89ff, 0x00c0, - 0x72d5, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, - 0x72d3, 0x1078, 0xa1da, 0x1078, 0x8ed6, 0x1078, 0x7233, 0x88ff, - 0x00c0, 0x72ec, 0x0c7f, 0x0078, 0x7257, 0x2c78, 0x600c, 0x2060, - 0x0078, 0x7257, 0xa006, 0x127f, 0x007f, 0x067f, 0x077f, 0x0c7f, - 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5, - 0x0001, 0x0078, 0x72e3, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, - 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x7638, - 0x2660, 0x2678, 0x8cff, 0x0040, 0x7367, 0x601c, 0xa086, 0x0006, - 0x00c0, 0x7362, 0x87ff, 0x0040, 0x7313, 0x2700, 0xac06, 0x00c0, - 0x7362, 0x0078, 0x731e, 0x6018, 0xa206, 0x00c0, 0x7362, 0x85ff, - 0x0040, 0x731e, 0x6020, 0xa106, 0x00c0, 0x7362, 0x703c, 0xac06, - 0x00c0, 0x7332, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x7033, - 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, - 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x7338, 0x660c, 0x763a, - 0x7034, 0xac36, 0x00c0, 0x7346, 0x2c00, 0xaf36, 0x0040, 0x7344, - 0x2f00, 0x7036, 0x0078, 0x7346, 0x7037, 0x0000, 0x660c, 0x067e, - 0x2c00, 0xaf06, 0x0040, 0x734f, 0x7e0e, 0x0078, 0x7350, 0x2678, - 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x735a, - 0x1078, 0xa1da, 0x1078, 0x8ed6, 0x87ff, 0x00c0, 0x7371, 0x0c7f, - 0x0078, 0x7302, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7302, 0xa006, - 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, - 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa7bd, 0x0001, 0x0078, 0x7368, - 0x0e7e, 0x2071, 0xa9b1, 0x2001, 0xa700, 0x2004, 0xa086, 0x0002, - 0x00c0, 0x7386, 0x7007, 0x0005, 0x0078, 0x7388, 0x7007, 0x0000, - 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x027e, 0x007e, - 0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x2c10, 0x7638, 0x2660, - 0x2678, 0x8cff, 0x0040, 0x73c8, 0x2200, 0xac06, 0x00c0, 0x73c3, - 0x7038, 0xac36, 0x00c0, 0x73a6, 0x660c, 0x763a, 0x7034, 0xac36, - 0x00c0, 0x73b4, 0x2c00, 0xaf36, 0x0040, 0x73b2, 0x2f00, 0x7036, - 0x0078, 0x73b4, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0040, - 0x73bc, 0x7e0e, 0x0078, 0x73bd, 0x2678, 0x600f, 0x0000, 0xa085, - 0x0001, 0x0078, 0x73c8, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7399, - 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, - 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091, - 0x8000, 0x2071, 0xa9b1, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0040, - 0x7469, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x7464, - 0x7024, 0xac06, 0x00c0, 0x740f, 0x2069, 0x0100, 0x68c0, 0xa005, - 0x0040, 0x743d, 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, - 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, - 0x0040, 0x7406, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0040, 0x740e, 0x6827, 0x0001, 0x037f, 0x700c, - 0xac36, 0x00c0, 0x7415, 0x660c, 0x760e, 0x7008, 0xac36, 0x00c0, - 0x7423, 0x2c00, 0xaf36, 0x0040, 0x7421, 0x2f00, 0x700a, 0x0078, - 0x7423, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, - 0x742c, 0x7e0e, 0x0078, 0x742d, 0x2678, 0x600f, 0x0000, 0x1078, - 0x8efc, 0x00c0, 0x7441, 0x1078, 0x28a6, 0x1078, 0x8f10, 0x00c0, - 0x745d, 0x1078, 0x7c83, 0x0078, 0x745d, 0x1078, 0x7378, 0x0078, - 0x740f, 0x1078, 0x8f10, 0x00c0, 0x7449, 0x1078, 0x7c83, 0x0078, - 0x745d, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x745d, 0x601c, - 0xa086, 0x0003, 0x00c0, 0x7471, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x1078, 0x8ed6, 0x1078, - 0x7233, 0x0c7f, 0x0078, 0x73de, 0x2c78, 0x600c, 0x2060, 0x0078, - 0x73de, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, - 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x745d, 0x1078, 0xa1da, - 0x0078, 0x745d, 0x037e, 0x157e, 0x137e, 0x147e, 0x3908, 0xa006, - 0xa190, 0x0020, 0x221c, 0xa39e, 0x2676, 0x00c0, 0x748b, 0x8210, - 0x8000, 0x0078, 0x7482, 0xa005, 0x0040, 0x7497, 0x20a9, 0x0020, - 0x2198, 0x8211, 0xa282, 0x0020, 0x20c8, 0x20a0, 0x53a3, 0x147f, - 0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078, - 0x67c2, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x2099, 0xa9a5, 0x20a9, 0x0004, 0x53a6, - 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x1078, 0x6dfb, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, - 0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, - 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6dfb, - 0x007c, 0x0d7e, 0x017e, 0x2f68, 0x2009, 0x0035, 0x1078, 0x91cc, - 0x00c0, 0x7551, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x1300, - 0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0040, - 0x752d, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0, - 0x7507, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0078, 0x7542, 0xa286, - 0x007f, 0x00c0, 0x7511, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0078, - 0x7542, 0xd2bc, 0x0040, 0x7527, 0xa286, 0x0080, 0x00c0, 0x751e, - 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0078, 0x7542, 0xa2e8, 0xa835, - 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x0078, 0x7542, 0x20a3, - 0x0000, 0x6098, 0x20a2, 0x0078, 0x7542, 0x7818, 0xa080, 0x0028, - 0x2004, 0xa082, 0x007e, 0x0048, 0x753e, 0x0d7e, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x7542, 0x20a3, 0x0000, - 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x017f, 0x0d7f, - 0x007c, 0x7817, 0x0001, 0x7803, 0x0006, 0x017f, 0x0d7f, 0x007c, - 0x0d7e, 0x027e, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x0040, - 0x757a, 0xa186, 0x0003, 0x0040, 0x75d5, 0xa186, 0x0005, 0x0040, - 0x75b8, 0xa186, 0x0004, 0x0040, 0x75a8, 0xa186, 0x0008, 0x0040, - 0x75c2, 0x7807, 0x0037, 0x7813, 0x1700, 0x1078, 0x7640, 0x027f, - 0x0d7f, 0x007c, 0x1078, 0x75fd, 0x2009, 0x4000, 0x6800, 0x0079, - 0x7581, 0x7594, 0x75a2, 0x7596, 0x75a2, 0x759d, 0x7594, 0x7594, - 0x75a2, 0x75a2, 0x75a2, 0x75a2, 0x7594, 0x7594, 0x7594, 0x7594, - 0x7594, 0x75a2, 0x7594, 0x75a2, 0x1078, 0x1332, 0x6824, 0xd0e4, - 0x0040, 0x759d, 0xd0cc, 0x0040, 0x75a0, 0xa00e, 0x0078, 0x75a2, - 0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0078, 0x75f3, - 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, - 0x6a00, 0xa286, 0x0002, 0x00c0, 0x75b6, 0xa00e, 0x0078, 0x75f3, - 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, - 0x0078, 0x75f3, 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x2009, 0x4000, 0xa286, 0x0005, 0x0040, 0x75d2, 0xa286, 0x0002, - 0x00c0, 0x75d3, 0xa00e, 0x0078, 0x75f3, 0x1078, 0x75fd, 0x6810, - 0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, - 0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002, 0x0040, - 0x75f1, 0xa08e, 0x0004, 0x0040, 0x75f1, 0x2009, 0x4000, 0x0078, - 0x75f3, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018, - 0x1078, 0x6dfb, 0x027f, 0x0d7f, 0x007c, 0x037e, 0x047e, 0x057e, - 0x067e, 0x20a1, 0x020b, 0x1078, 0x67c2, 0xa006, 0x20a3, 0x0200, - 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028, - 0x2004, 0xa092, 0x007e, 0x0048, 0x7623, 0x0d7e, 0x2069, 0xa71b, - 0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xa835, 0x2d6c, 0x6b10, 0x6c14, - 0x0d7f, 0x0078, 0x7629, 0x2019, 0x0000, 0x6498, 0x2029, 0x0000, - 0x6630, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003, 0x00c0, - 0x7637, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0078, 0x763b, 0x23a2, - 0x24a2, 0x25a2, 0x26a2, 0x067f, 0x057f, 0x047f, 0x037f, 0x007c, - 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, - 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, - 0x007c, 0x20a1, 0x020b, 0x1078, 0x6728, 0x20a3, 0x1400, 0x20a3, - 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c, - 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000, - 0x60c3, 0x0010, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, - 0x67b9, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810, - 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x147e, 0x20a1, - 0x020b, 0x1078, 0x7689, 0x60c3, 0x0000, 0x1078, 0x6dfb, 0x147f, - 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0xd0bc, 0x0040, 0x76a6, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, - 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, - 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x76ae, 0x20a3, 0x0300, - 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0819, - 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x2fa2, - 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x007c, 0x2061, - 0xae00, 0x2a70, 0x7064, 0x704a, 0x704f, 0xae00, 0x007c, 0x0e7e, - 0x127e, 0x2071, 0xa700, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010, - 0x0048, 0x76f9, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, - 0x76e5, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, 0x76e1, 0x0078, - 0x76d4, 0x2061, 0xae00, 0x0078, 0x76d4, 0x6003, 0x0008, 0x8529, - 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, 0x76f5, 0x754e, - 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704f, 0xae00, 0x0078, - 0x76f0, 0xa006, 0x0078, 0x76f2, 0x0e7e, 0x2071, 0xa700, 0x7548, - 0xa582, 0x0010, 0x0048, 0x772a, 0x704c, 0x2060, 0x6000, 0xa086, - 0x0000, 0x0040, 0x7717, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, - 0x7713, 0x0078, 0x7706, 0x2061, 0xae00, 0x0078, 0x7706, 0x6003, - 0x0008, 0x8529, 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, - 0x7726, 0x754e, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x704f, 0xae00, - 0x0078, 0x7722, 0xa006, 0x0078, 0x7724, 0xac82, 0xae00, 0x1048, - 0x1332, 0x2001, 0xa716, 0x2004, 0xac02, 0x10c8, 0x1332, 0xa006, - 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, - 0x6003, 0x0000, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, - 0x603a, 0x603e, 0x2061, 0xa700, 0x6048, 0x8000, 0x604a, 0xa086, - 0x0001, 0x0040, 0x7754, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, - 0x62d1, 0x127f, 0x0078, 0x7753, 0x601c, 0xa084, 0x000f, 0x0079, - 0x7761, 0x776a, 0x777b, 0x7797, 0x77b3, 0x921e, 0x923a, 0x9256, - 0x776a, 0x777b, 0xa186, 0x0013, 0x00c0, 0x7773, 0x1078, 0x61cd, - 0x1078, 0x62d1, 0x007c, 0xa18e, 0x0047, 0x00c0, 0x777a, 0xa016, - 0x1078, 0x15fa, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, - 0x1332, 0x1079, 0x7785, 0x067f, 0x007c, 0x7795, 0x7b00, 0x7cb2, - 0x7795, 0x7d36, 0x77cf, 0x7795, 0x7795, 0x7a92, 0x80f6, 0x7795, - 0x7795, 0x7795, 0x7795, 0x7795, 0x7795, 0x1078, 0x1332, 0x067e, - 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x77a1, 0x067f, - 0x007c, 0x77b1, 0x87d3, 0x77b1, 0x77b1, 0x77b1, 0x77b1, 0x77b1, - 0x77b1, 0x8776, 0x8961, 0x77b1, 0x8803, 0x8889, 0x8803, 0x8889, - 0x77b1, 0x1078, 0x1332, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, - 0x1332, 0x1079, 0x77bd, 0x067f, 0x007c, 0x77cd, 0x813d, 0x820e, - 0x8372, 0x84f1, 0x77cd, 0x77cd, 0x77cd, 0x8116, 0x871e, 0x8722, - 0x77cd, 0x77cd, 0x77cd, 0x77cd, 0x8752, 0x1078, 0x1332, 0xa1b6, - 0x0015, 0x00c0, 0x77d7, 0x1078, 0x772d, 0x0078, 0x77dd, 0xa1b6, - 0x0016, 0x10c0, 0x1332, 0x1078, 0x772d, 0x007c, 0x20a9, 0x000e, - 0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, - 0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, - 0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x77ec, - 0x0e7e, 0x1078, 0x8d16, 0x0040, 0x7803, 0x6010, 0x2070, 0x7007, - 0x0000, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x772d, 0x007c, 0x0d7e, - 0x037e, 0x7330, 0xa386, 0x0200, 0x00c0, 0x7814, 0x6018, 0x2068, - 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0040, 0x781e, - 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x1078, 0x772d, - 0x037f, 0x0d7f, 0x007c, 0x017e, 0x20a9, 0x002a, 0xae80, 0x000c, - 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, - 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, - 0x0e7e, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, - 0x772d, 0x017f, 0x007c, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2c68, - 0x017e, 0x2009, 0x0035, 0x1078, 0x91cc, 0x017f, 0x00c0, 0x785f, - 0x027e, 0x6228, 0x2268, 0x027f, 0x2071, 0xac8c, 0x6b1c, 0xa386, - 0x0003, 0x0040, 0x7863, 0xa386, 0x0006, 0x0040, 0x7867, 0x1078, - 0x772d, 0x0078, 0x7869, 0x1078, 0x786c, 0x0078, 0x7869, 0x1078, - 0x7938, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x6810, 0x2078, 0xa186, - 0x0015, 0x0040, 0x791d, 0xa18e, 0x0016, 0x00c0, 0x7936, 0x700c, - 0xa08c, 0xff00, 0xa186, 0x1700, 0x0040, 0x7882, 0xa186, 0x0300, - 0x00c0, 0x78f8, 0x8fff, 0x00c0, 0x788c, 0x6800, 0xa086, 0x000f, - 0x0040, 0x78db, 0x0078, 0x7934, 0x6808, 0xa086, 0xffff, 0x00c0, - 0x7921, 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x00c0, 0x78a2, - 0x797c, 0x7810, 0xa106, 0x00c0, 0x7921, 0x7980, 0x7814, 0xa106, - 0x00c0, 0x7921, 0x1078, 0x8ec9, 0x6830, 0x7852, 0x784c, 0xc0dc, - 0xc0f4, 0xc0d4, 0x784e, 0x027e, 0xa00e, 0x6a14, 0x2001, 0x000a, - 0x1078, 0x5c1c, 0x7854, 0xa20a, 0x0048, 0x78b7, 0x8011, 0x7a56, - 0x82ff, 0x027f, 0x00c0, 0x78c3, 0x0c7e, 0x2d60, 0x1078, 0x8af0, - 0x0c7f, 0x0078, 0x7934, 0x0c7e, 0x0d7e, 0x2f68, 0x6838, 0xd0fc, - 0x00c0, 0x78ce, 0x1078, 0x4353, 0x0078, 0x78d0, 0x1078, 0x4431, - 0x0d7f, 0x0c7f, 0x00c0, 0x7921, 0x0c7e, 0x2d60, 0x1078, 0x772d, - 0x0c7f, 0x0078, 0x7934, 0x0c7e, 0x1078, 0x9197, 0x0040, 0x78f1, - 0x6013, 0x0000, 0x6818, 0x601a, 0x601f, 0x0003, 0x6904, 0x0c7e, - 0x2d60, 0x1078, 0x772d, 0x0c7f, 0x1078, 0x775c, 0x0c7f, 0x0078, - 0x7934, 0x2001, 0xa9a4, 0x2004, 0x683e, 0x0c7f, 0x0078, 0x7934, - 0x7008, 0xa086, 0x000b, 0x00c0, 0x7912, 0x6018, 0x200c, 0xc1bc, - 0x2102, 0x0c7e, 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, 0x6003, - 0x000b, 0x601f, 0x0002, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, - 0x0078, 0x7934, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x7921, 0x2001, - 0xa9a4, 0x2004, 0x683e, 0x0078, 0x7934, 0x1078, 0x7953, 0x0078, - 0x7936, 0x8fff, 0x1040, 0x1332, 0x0c7e, 0x0d7e, 0x2d60, 0x2f68, - 0x6837, 0x0103, 0x684b, 0x0003, 0x1078, 0x89df, 0x1078, 0x8ec9, - 0x1078, 0x8ed6, 0x0d7f, 0x0c7f, 0x1078, 0x772d, 0x0f7f, 0x007c, - 0xa186, 0x0015, 0x00c0, 0x7942, 0x2001, 0xa9a4, 0x2004, 0x683e, - 0x0078, 0x7950, 0xa18e, 0x0016, 0x00c0, 0x7952, 0x0c7e, 0x2d00, - 0x2060, 0x1078, 0xa4a5, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x0c7f, - 0x1078, 0x772d, 0x007c, 0x027e, 0x037e, 0x047e, 0x7228, 0x7c80, - 0x7b7c, 0xd2f4, 0x0040, 0x7962, 0x2001, 0xa9a4, 0x2004, 0x683e, - 0x0078, 0x79c6, 0x0c7e, 0x2d60, 0x1078, 0x8a03, 0x0c7f, 0x6804, - 0xa086, 0x0050, 0x00c0, 0x797a, 0x0c7e, 0x2d00, 0x2060, 0x6003, - 0x0001, 0x6007, 0x0050, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, - 0x0078, 0x79c6, 0x6800, 0xa086, 0x000f, 0x0040, 0x799c, 0x8fff, - 0x1040, 0x1332, 0x6824, 0xd0dc, 0x00c0, 0x799c, 0x6800, 0xa086, - 0x0004, 0x00c0, 0x79a1, 0x784c, 0xd0ac, 0x0040, 0x79a1, 0x784c, - 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, - 0x0001, 0x682e, 0x0078, 0x79c0, 0x2001, 0x0007, 0x682e, 0x0078, - 0x79c0, 0x784c, 0xd0b4, 0x00c0, 0x79ae, 0xd0ac, 0x0040, 0x799c, - 0x784c, 0xd0f4, 0x00c0, 0x799c, 0x0078, 0x798f, 0xd2ec, 0x00c0, - 0x799c, 0x7024, 0xa306, 0x00c0, 0x79b9, 0x7020, 0xa406, 0x0040, - 0x799c, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, - 0x1078, 0x9000, 0x1078, 0x62d1, 0x0078, 0x79c8, 0x1078, 0x772d, - 0x047f, 0x037f, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x027e, 0x6034, - 0x2068, 0x6a1c, 0xa286, 0x0007, 0x0040, 0x7a35, 0xa286, 0x0002, - 0x0040, 0x7a35, 0xa286, 0x0000, 0x0040, 0x7a35, 0x6808, 0x6338, - 0xa306, 0x00c0, 0x7a35, 0x2071, 0xac8c, 0xa186, 0x0015, 0x0040, - 0x7a2f, 0xa18e, 0x0016, 0x00c0, 0x7a02, 0x6030, 0xa084, 0x00ff, - 0xa086, 0x0001, 0x00c0, 0x7a02, 0x700c, 0xa086, 0x2a00, 0x00c0, - 0x7a02, 0x6034, 0xa080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, 0x2102, - 0x0078, 0x7a2f, 0x0c7e, 0x6034, 0x2060, 0x6104, 0xa186, 0x004b, - 0x0040, 0x7a22, 0xa186, 0x004c, 0x0040, 0x7a22, 0xa186, 0x004d, - 0x0040, 0x7a22, 0xa186, 0x004e, 0x0040, 0x7a22, 0xa186, 0x0052, - 0x0040, 0x7a22, 0x6010, 0x2068, 0x1078, 0x8d16, 0x1040, 0x1332, - 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, - 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, 0x0078, 0x7a35, 0x6034, - 0x2068, 0x2001, 0xa9a4, 0x2004, 0x683e, 0x1078, 0x772d, 0x027f, - 0x0d7f, 0x0e7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98, 0x6010, - 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x00c0, 0x7a73, 0x6018, 0x2068, - 0x157e, 0x037e, 0x027e, 0xae90, 0x000c, 0xa290, 0x0004, 0x20a9, - 0x0004, 0xad98, 0x000a, 0x1078, 0x80de, 0x027f, 0x037f, 0x157f, - 0x00c0, 0x7a76, 0x157e, 0x037e, 0x027e, 0xae90, 0x000c, 0xa290, - 0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, 0x1078, 0x80de, 0x027f, - 0x037f, 0x157f, 0x00c0, 0x7a76, 0x7038, 0x680a, 0x703c, 0x680e, - 0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x77f8, 0x1078, 0x2880, - 0x0c7e, 0x1078, 0x76c7, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f, - 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x1078, - 0x4502, 0x1078, 0x4535, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0c7f, - 0x0078, 0x7a73, 0x2100, 0xa1b2, 0x0044, 0x10c8, 0x1332, 0xa1b2, - 0x0040, 0x00c8, 0x7af7, 0x0079, 0x7a9d, 0x7aeb, 0x7adf, 0x7aeb, - 0x7aeb, 0x7aeb, 0x7aeb, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, - 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, - 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, - 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7aeb, 0x7aeb, - 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7add, - 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, - 0x7aeb, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, - 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7add, 0x1078, 0x1332, 0x6003, - 0x0001, 0x6106, 0x1078, 0x5dd7, 0x127e, 0x2091, 0x8000, 0x1078, - 0x62d1, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5dd7, - 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x2600, - 0x0079, 0x7afa, 0x7afe, 0x7afe, 0x7afe, 0x7aeb, 0x1078, 0x1332, - 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1332, 0xa1b6, 0x0013, 0x00c0, - 0x7b10, 0xa0b2, 0x0040, 0x00c8, 0x7c79, 0x2008, 0x0079, 0x7bbf, - 0xa1b6, 0x0027, 0x00c0, 0x7b7c, 0x1078, 0x61cd, 0x6004, 0x1078, - 0x8efc, 0x0040, 0x7b2d, 0x1078, 0x8f10, 0x0040, 0x7b74, 0xa08e, - 0x0021, 0x0040, 0x7b78, 0xa08e, 0x0022, 0x0040, 0x7b74, 0xa08e, - 0x003d, 0x0040, 0x7b78, 0x0078, 0x7b6f, 0x1078, 0x28a6, 0x2001, - 0x0007, 0x1078, 0x4502, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, - 0x7c83, 0xa186, 0x007e, 0x00c0, 0x7b42, 0x2001, 0xa733, 0x2014, - 0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, - 0x0028, 0x1078, 0x73d0, 0x027f, 0x1078, 0xa501, 0x037f, 0x027f, - 0x017f, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, 0x0028, 0x1078, - 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x0c7e, 0x6018, - 0xa065, 0x0040, 0x7b65, 0x1078, 0x47e9, 0x0c7f, 0x2c08, 0x1078, - 0x9f9b, 0x077f, 0x037f, 0x027f, 0x017f, 0x1078, 0x457f, 0x1078, - 0x772d, 0x1078, 0x62d1, 0x007c, 0x1078, 0x7c83, 0x0078, 0x7b6f, - 0x1078, 0x7ca6, 0x0078, 0x7b6f, 0xa186, 0x0014, 0x00c0, 0x7b73, - 0x1078, 0x61cd, 0x1078, 0x2880, 0x1078, 0x8efc, 0x00c0, 0x7b9b, - 0x1078, 0x28a6, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, 0x7c83, - 0xa186, 0x007e, 0x00c0, 0x7b99, 0x2001, 0xa733, 0x200c, 0xc185, - 0x2102, 0x0078, 0x7b6f, 0x1078, 0x8f10, 0x00c0, 0x7ba3, 0x1078, - 0x7c83, 0x0078, 0x7b6f, 0x6004, 0xa08e, 0x0032, 0x00c0, 0x7bb4, - 0x0e7e, 0x0f7e, 0x2071, 0xa782, 0x2079, 0x0000, 0x1078, 0x2bd7, - 0x0f7f, 0x0e7f, 0x0078, 0x7b6f, 0x6004, 0xa08e, 0x0021, 0x0040, - 0x7b9f, 0xa08e, 0x0022, 0x1040, 0x7c83, 0x0078, 0x7b6f, 0x7c01, - 0x7c03, 0x7c07, 0x7c0b, 0x7c0f, 0x7c13, 0x7bff, 0x7bff, 0x7bff, - 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, - 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, - 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7c17, 0x7c29, 0x7bff, - 0x7c2b, 0x7c29, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7c29, - 0x7c29, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, - 0x7bff, 0x7c5c, 0x7c29, 0x7bff, 0x7c23, 0x7bff, 0x7bff, 0x7bff, - 0x7c25, 0x7bff, 0x7bff, 0x7bff, 0x7c29, 0x7bff, 0x7bff, 0x1078, - 0x1332, 0x0078, 0x7c29, 0x2001, 0x000b, 0x0078, 0x7c36, 0x2001, - 0x0003, 0x0078, 0x7c36, 0x2001, 0x0005, 0x0078, 0x7c36, 0x2001, - 0x0001, 0x0078, 0x7c36, 0x2001, 0x0009, 0x0078, 0x7c36, 0x1078, - 0x61cd, 0x6003, 0x0005, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x1078, - 0x62d1, 0x0078, 0x7c35, 0x0078, 0x7c29, 0x0078, 0x7c29, 0x1078, - 0x4502, 0x0078, 0x7c6e, 0x1078, 0x61cd, 0x6003, 0x0004, 0x2001, - 0xa9a2, 0x2004, 0x6016, 0x1078, 0x62d1, 0x007c, 0x1078, 0x4502, - 0x1078, 0x61cd, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x6003, 0x0002, - 0x037e, 0x2019, 0xa75d, 0x2304, 0xa084, 0xff00, 0x00c0, 0x7c4d, - 0x2019, 0xa9a2, 0x231c, 0x0078, 0x7c56, 0x8007, 0xa09a, 0x0004, - 0x0048, 0x7c48, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x037f, - 0x1078, 0x62d1, 0x0078, 0x7c35, 0x0e7e, 0x0f7e, 0x2071, 0xa782, - 0x2079, 0x0000, 0x1078, 0x2bd7, 0x0f7f, 0x0e7f, 0x1078, 0x61cd, - 0x1078, 0x772d, 0x1078, 0x62d1, 0x0078, 0x7c35, 0x1078, 0x61cd, - 0x6003, 0x0002, 0x2001, 0xa9a2, 0x2004, 0x6016, 0x1078, 0x62d1, - 0x007c, 0x2600, 0x2008, 0x0079, 0x7c7d, 0x7c81, 0x7c81, 0x7c81, - 0x7c6e, 0x1078, 0x1332, 0x0e7e, 0x1078, 0x8d16, 0x0040, 0x7c9f, - 0x6010, 0x2070, 0x7038, 0xd0fc, 0x0040, 0x7c9f, 0x7007, 0x0000, - 0x017e, 0x6004, 0xa08e, 0x0021, 0x0040, 0x7ca1, 0xa08e, 0x003d, - 0x0040, 0x7ca1, 0x017f, 0x7037, 0x0103, 0x7033, 0x0100, 0x0e7f, - 0x007c, 0x017f, 0x1078, 0x7ca6, 0x0078, 0x7c9f, 0x0e7e, 0xacf0, - 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x7023, 0x8001, - 0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, - 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1332, 0x6604, 0xa6b6, 0x0043, - 0x00c0, 0x7cc6, 0x1078, 0x9144, 0x0078, 0x7d25, 0x6604, 0xa6b6, - 0x0033, 0x00c0, 0x7ccf, 0x1078, 0x90e8, 0x0078, 0x7d25, 0x6604, - 0xa6b6, 0x0028, 0x00c0, 0x7cd8, 0x1078, 0x8f3f, 0x0078, 0x7d25, - 0x6604, 0xa6b6, 0x0029, 0x00c0, 0x7ce1, 0x1078, 0x8f59, 0x0078, - 0x7d25, 0x6604, 0xa6b6, 0x001f, 0x00c0, 0x7cea, 0x1078, 0x77de, - 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0000, 0x00c0, 0x7cf3, 0x1078, - 0x7a3b, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0022, 0x00c0, 0x7cfc, - 0x1078, 0x7807, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0035, 0x00c0, - 0x7d05, 0x1078, 0x7843, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0039, - 0x00c0, 0x7d0e, 0x1078, 0x79cc, 0x0078, 0x7d25, 0x6604, 0xa6b6, - 0x003d, 0x00c0, 0x7d17, 0x1078, 0x7823, 0x0078, 0x7d25, 0xa1b6, - 0x0015, 0x00c0, 0x7d1f, 0x1079, 0x7d2a, 0x0078, 0x7d25, 0xa1b6, - 0x0016, 0x00c0, 0x7d26, 0x1079, 0x7e7f, 0x007c, 0x1078, 0x7773, - 0x0078, 0x7d25, 0x7d4e, 0x7d51, 0x7d4e, 0x7d9c, 0x7d4e, 0x7e13, - 0x7e8b, 0x7d4e, 0x7d4e, 0x7e57, 0x7d4e, 0x7e6d, 0xa1b6, 0x0048, - 0x0040, 0x7d42, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, - 0x15fa, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, - 0x7037, 0x0103, 0x0e7f, 0x1078, 0x772d, 0x007c, 0x0005, 0x0005, - 0x007c, 0x0e7e, 0x2071, 0xa700, 0x7080, 0xa086, 0x0074, 0x00c0, - 0x7d85, 0x1078, 0x9f6f, 0x00c0, 0x7d77, 0x0d7e, 0x6018, 0x2068, - 0x7030, 0xd08c, 0x0040, 0x7d6a, 0x6800, 0xd0bc, 0x0040, 0x7d6a, - 0xc0c5, 0x6802, 0x1078, 0x7d89, 0x0d7f, 0x2001, 0x0006, 0x1078, - 0x4502, 0x1078, 0x28a6, 0x1078, 0x772d, 0x0078, 0x7d87, 0x2001, - 0x000a, 0x1078, 0x4502, 0x1078, 0x28a6, 0x6003, 0x0001, 0x6007, - 0x0001, 0x1078, 0x5dd7, 0x0078, 0x7d87, 0x1078, 0x7dff, 0x0e7f, - 0x007c, 0x6800, 0xd084, 0x0040, 0x7d9b, 0x2001, 0x0000, 0x1078, - 0x44ee, 0x2069, 0xa752, 0x6804, 0xd0a4, 0x0040, 0x7d9b, 0x2001, - 0x0006, 0x1078, 0x4535, 0x007c, 0x0d7e, 0x2011, 0xa720, 0x2204, - 0xa086, 0x0074, 0x00c0, 0x7dfb, 0x6018, 0x2068, 0x6aa0, 0xa286, - 0x007e, 0x00c0, 0x7daf, 0x1078, 0x7f9b, 0x0078, 0x7dfd, 0x1078, - 0x7f91, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, 0x0080, - 0x00c0, 0x7dd3, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, - 0x0040, 0x7dc9, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, - 0x0200, 0x2001, 0x0006, 0x1078, 0x4502, 0x1078, 0x28a6, 0x1078, - 0x772d, 0x0078, 0x7dfd, 0x0e7e, 0x2071, 0xa733, 0x2e04, 0xd09c, - 0x0040, 0x7dee, 0x2071, 0xac80, 0x7108, 0x720c, 0xa18c, 0x00ff, - 0x00c0, 0x7de6, 0xa284, 0xff00, 0x0040, 0x7dee, 0x6018, 0x2070, - 0x70a0, 0xd0bc, 0x00c0, 0x7dee, 0x7112, 0x7216, 0x0e7f, 0x2001, - 0x0004, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, - 0x5dd7, 0x0078, 0x7dfd, 0x1078, 0x7dff, 0x0d7f, 0x007c, 0x2001, - 0x0007, 0x1078, 0x4502, 0x2001, 0xa700, 0x2004, 0xa086, 0x0003, - 0x00c0, 0x7e0e, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, 0x28a6, - 0x1078, 0x772d, 0x007c, 0x0e7e, 0x2071, 0xa700, 0x7080, 0xa086, - 0x0014, 0x00c0, 0x7e51, 0x7000, 0xa086, 0x0003, 0x00c0, 0x7e26, - 0x6010, 0xa005, 0x00c0, 0x7e26, 0x1078, 0x3699, 0x0d7e, 0x6018, - 0x2068, 0x1078, 0x4649, 0x1078, 0x7d89, 0x0d7f, 0x1078, 0x8043, - 0x00c0, 0x7e51, 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, - 0x0040, 0x7e51, 0x2001, 0x0006, 0x1078, 0x4502, 0x0e7e, 0x6010, - 0xa005, 0x0040, 0x7e4a, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, - 0x7033, 0x0200, 0x0e7f, 0x1078, 0x28a6, 0x1078, 0x772d, 0x0078, - 0x7e55, 0x1078, 0x7c83, 0x1078, 0x7dff, 0x0e7f, 0x007c, 0x2011, - 0xa720, 0x2204, 0xa086, 0x0014, 0x00c0, 0x7e6a, 0x2001, 0x0002, - 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5dd7, - 0x0078, 0x7e6c, 0x1078, 0x7dff, 0x007c, 0x2011, 0xa720, 0x2204, - 0xa086, 0x0004, 0x00c0, 0x7e7c, 0x2001, 0x0007, 0x1078, 0x4502, - 0x1078, 0x772d, 0x0078, 0x7e7e, 0x1078, 0x7dff, 0x007c, 0x7d4e, - 0x7e97, 0x7d4e, 0x7ed2, 0x7d4e, 0x7f44, 0x7e8b, 0x7d4e, 0x7d4e, - 0x7f59, 0x7d4e, 0x7f6c, 0x6604, 0xa686, 0x0003, 0x0040, 0x7e13, - 0xa6b6, 0x001e, 0x00c0, 0x7e96, 0x1078, 0x772d, 0x007c, 0x0d7e, - 0x0c7e, 0x1078, 0x7f7f, 0x00c0, 0x7ead, 0x2001, 0x0000, 0x1078, - 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, - 0x0002, 0x1078, 0x5dd7, 0x0078, 0x7ecf, 0x2009, 0xac8e, 0x2104, - 0xa086, 0x0009, 0x00c0, 0x7ec2, 0x6018, 0x2068, 0x6840, 0xa084, - 0x00ff, 0xa005, 0x0040, 0x7ecd, 0x8001, 0x6842, 0x6017, 0x000a, - 0x0078, 0x7ecf, 0x2009, 0xac8f, 0x2104, 0xa084, 0xff00, 0xa086, - 0x1900, 0x00c0, 0x7ecd, 0x0078, 0x7ea1, 0x1078, 0x7dff, 0x0c7f, - 0x0d7f, 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7ee6, 0x2001, 0x0000, - 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, 0x0001, - 0x6007, 0x0002, 0x1078, 0x5dd7, 0x0078, 0x7f12, 0x1078, 0x7c83, - 0x2009, 0xac8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0040, - 0x7f13, 0xa686, 0x000b, 0x0040, 0x7f10, 0x2009, 0xac8f, 0x2104, - 0xa084, 0xff00, 0x00c0, 0x7f00, 0xa686, 0x0009, 0x0040, 0x7f13, - 0xa086, 0x1900, 0x00c0, 0x7f10, 0xa686, 0x0009, 0x0040, 0x7f13, - 0x2001, 0x0004, 0x1078, 0x4502, 0x1078, 0x772d, 0x0078, 0x7f12, - 0x1078, 0x7dff, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16, - 0x0040, 0x7f21, 0x6838, 0xd0fc, 0x0040, 0x7f21, 0x0d7f, 0x0078, - 0x7f10, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, - 0x7f32, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f, - 0x0078, 0x7f12, 0x68a0, 0xa086, 0x007e, 0x00c0, 0x7f3f, 0x0e7e, - 0x2071, 0xa700, 0x1078, 0x42b8, 0x0e7f, 0x0078, 0x7f41, 0x1078, - 0x2880, 0x0d7f, 0x0078, 0x7f10, 0x1078, 0x7f8e, 0x00c0, 0x7f54, - 0x2001, 0x0004, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0003, - 0x1078, 0x5dd7, 0x0078, 0x7f58, 0x1078, 0x7c83, 0x1078, 0x7dff, - 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7f69, 0x2001, 0x0008, 0x1078, - 0x4502, 0x6003, 0x0001, 0x6007, 0x0005, 0x1078, 0x5dd7, 0x0078, - 0x7f6b, 0x1078, 0x7dff, 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7f7c, - 0x2001, 0x000a, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0001, - 0x1078, 0x5dd7, 0x0078, 0x7f7e, 0x1078, 0x7dff, 0x007c, 0x2009, - 0xac8e, 0x2104, 0xa086, 0x0003, 0x00c0, 0x7f8d, 0x2009, 0xac8f, - 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x007c, 0xa085, 0x0001, - 0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006, 0x2164, 0x1078, 0x45d6, - 0x017f, 0x0c7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x037e, 0x017e, - 0x6018, 0x2068, 0x2071, 0xa733, 0x2e04, 0xa085, 0x0003, 0x2072, - 0x1078, 0x8014, 0x0040, 0x7fd9, 0x2009, 0xa733, 0x2104, 0xc0cd, - 0x200a, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x7fc2, 0xa006, - 0x2020, 0x2009, 0x002a, 0x1078, 0xa22d, 0x2001, 0xa70c, 0x200c, - 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x1078, 0x284f, - 0x2071, 0xa700, 0x1078, 0x2677, 0x0c7e, 0x157e, 0x20a9, 0x0081, - 0x2009, 0x007f, 0x1078, 0x298e, 0x8108, 0x00f0, 0x7fd2, 0x157f, - 0x0c7f, 0x1078, 0x7f91, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, - 0xac80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xa71b, - 0x206a, 0x78e6, 0x007e, 0x8e70, 0x2e04, 0x2069, 0xa71c, 0x206a, - 0x78ea, 0xa084, 0xff00, 0x017f, 0xa105, 0x2009, 0xa726, 0x200a, - 0x2069, 0xac8e, 0x2071, 0xa99e, 0x6810, 0x2072, 0x6814, 0x7006, - 0x6818, 0x700a, 0x681c, 0x700e, 0x1078, 0x907e, 0x2001, 0x0006, - 0x1078, 0x4502, 0x1078, 0x28a6, 0x1078, 0x772d, 0x017f, 0x037f, - 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x037e, 0x0e7e, 0x157e, - 0x2019, 0xa726, 0x231c, 0x83ff, 0x0040, 0x803e, 0x2071, 0xac80, - 0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, - 0x00c0, 0x803e, 0x2011, 0xac96, 0xad98, 0x000a, 0x20a9, 0x0004, - 0x1078, 0x80de, 0x00c0, 0x803e, 0x2011, 0xac9a, 0xad98, 0x0006, - 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x803e, 0x157f, 0x0e7f, - 0x037f, 0x027f, 0x007c, 0x0e7e, 0x2071, 0xac8c, 0x7004, 0xa086, - 0x0014, 0x00c0, 0x8066, 0x7008, 0xa086, 0x0800, 0x00c0, 0x8066, - 0x700c, 0xd0ec, 0x0040, 0x8064, 0xa084, 0x0f00, 0xa086, 0x0100, - 0x00c0, 0x8064, 0x7024, 0xd0a4, 0x00c0, 0x8061, 0xd0ac, 0x0040, - 0x8064, 0xa006, 0x0078, 0x8066, 0xa085, 0x0001, 0x0e7f, 0x007c, - 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, 0x007e, - 0x127e, 0x2091, 0x8000, 0x2029, 0xa9ba, 0x252c, 0x2021, 0xa9c0, - 0x2424, 0x2061, 0xae00, 0x2071, 0xa700, 0x7248, 0x7064, 0xa202, - 0x00c8, 0x80cc, 0x1078, 0xa252, 0x0040, 0x80c4, 0x671c, 0xa786, - 0x0001, 0x0040, 0x80c4, 0xa786, 0x0007, 0x0040, 0x80c4, 0x2500, - 0xac06, 0x0040, 0x80c4, 0x2400, 0xac06, 0x0040, 0x80c4, 0x0c7e, - 0x6000, 0xa086, 0x0004, 0x00c0, 0x809f, 0x1078, 0x1757, 0xa786, - 0x0008, 0x00c0, 0x80ae, 0x1078, 0x8f10, 0x00c0, 0x80ae, 0x0c7f, - 0x1078, 0x7c83, 0x1078, 0x8ed6, 0x0078, 0x80c4, 0x6010, 0x2068, - 0x1078, 0x8d16, 0x0040, 0x80c1, 0xa786, 0x0003, 0x00c0, 0x80d6, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078, - 0x8ec9, 0x1078, 0x8ed6, 0x0c7f, 0xace0, 0x0010, 0x7058, 0xac02, - 0x00c8, 0x80cc, 0x0078, 0x807d, 0x127f, 0x007f, 0x027f, 0x047f, - 0x057f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006, - 0x00c0, 0x80b8, 0x1078, 0xa1da, 0x0078, 0x80c1, 0x220c, 0x2304, - 0xa106, 0x00c0, 0x80e9, 0x8210, 0x8318, 0x00f0, 0x80de, 0xa006, - 0x007c, 0x2304, 0xa102, 0x0048, 0x80f1, 0x2001, 0x0001, 0x0078, - 0x80f3, 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a, - 0x0044, 0x10c8, 0x1332, 0x1078, 0x8efc, 0x0040, 0x8105, 0x1078, - 0x8f10, 0x0040, 0x8112, 0x0078, 0x810b, 0x1078, 0x28a6, 0x1078, - 0x8f10, 0x0040, 0x8112, 0x1078, 0x61cd, 0x1078, 0x772d, 0x1078, - 0x62d1, 0x007c, 0x1078, 0x7c83, 0x0078, 0x810b, 0xa182, 0x0040, - 0x0079, 0x811a, 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, - 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, 0x812f, 0x812f, 0x812f, - 0x812f, 0x812d, 0x812d, 0x812d, 0x812f, 0x1078, 0x1332, 0x600b, - 0xffff, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, - 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, - 0x8146, 0x6004, 0xa082, 0x0040, 0x0079, 0x81d1, 0xa186, 0x0027, - 0x00c0, 0x8168, 0x1078, 0x61cd, 0x1078, 0x2880, 0x0d7e, 0x6110, - 0x2168, 0x1078, 0x8d16, 0x0040, 0x8162, 0x6837, 0x0103, 0x684b, - 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x1078, 0x4a73, - 0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, - 0xa186, 0x0014, 0x00c0, 0x8171, 0x6004, 0xa082, 0x0040, 0x0079, - 0x8199, 0xa186, 0x0046, 0x0040, 0x817d, 0xa186, 0x0045, 0x0040, - 0x817d, 0xa186, 0x0047, 0x10c0, 0x1332, 0x2001, 0x0109, 0x2004, - 0xd084, 0x0040, 0x8196, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, - 0x027e, 0x1078, 0x5c56, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, - 0xa086, 0x0002, 0x00c0, 0x8196, 0x0078, 0x820e, 0x1078, 0x7773, - 0x007c, 0x81ae, 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ac, - 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ca, 0x81ca, 0x81ca, 0x81ca, - 0x81ac, 0x81ca, 0x81ac, 0x81ca, 0x1078, 0x1332, 0x1078, 0x61cd, - 0x0d7e, 0x6110, 0x2168, 0x1078, 0x8d16, 0x0040, 0x81c4, 0x6837, - 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, - 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d, 0x1078, - 0x62d1, 0x007c, 0x1078, 0x61cd, 0x1078, 0x772d, 0x1078, 0x62d1, - 0x007c, 0x81e6, 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81e4, - 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81f8, 0x81f8, 0x81f8, 0x81f8, - 0x81e4, 0x8207, 0x81e4, 0x81f8, 0x1078, 0x1332, 0x1078, 0x61cd, - 0x2001, 0xa9a4, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x62d1, - 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, - 0x1078, 0x61cd, 0x2001, 0xa9a2, 0x2004, 0x6016, 0x2001, 0xa9a4, - 0x2004, 0x603e, 0x6003, 0x000f, 0x1078, 0x62d1, 0x007c, 0x1078, - 0x61cd, 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, 0xa182, 0x0040, - 0x0079, 0x8212, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x8227, - 0x8331, 0x8363, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, - 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x1078, 0x1332, 0x0e7e, - 0x0d7e, 0x603f, 0x0000, 0x2071, 0xac80, 0x7124, 0x610a, 0x2071, - 0xac8c, 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, - 0x82f0, 0xa68c, 0x0c00, 0x0040, 0x8265, 0x0f7e, 0x2c78, 0x1078, - 0x4963, 0x0f7f, 0x0040, 0x8261, 0x684c, 0xd0ac, 0x0040, 0x8261, - 0x6024, 0xd0dc, 0x00c0, 0x8261, 0x6850, 0xd0bc, 0x00c0, 0x8261, - 0x7318, 0x6814, 0xa306, 0x00c0, 0x8308, 0x731c, 0x6810, 0xa31e, - 0x0040, 0x8261, 0xd6d4, 0x0040, 0x8308, 0x6b14, 0xa305, 0x00c0, - 0x8308, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, - 0x0002, 0x0040, 0x8298, 0xa186, 0x0028, 0x00c0, 0x8275, 0x1078, - 0x8eea, 0x684b, 0x001c, 0x0078, 0x829a, 0xd6dc, 0x0040, 0x8291, - 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0040, 0x828f, 0x6914, 0x6a10, - 0x2100, 0xa205, 0x0040, 0x828f, 0x7018, 0xa106, 0x00c0, 0x828c, - 0x701c, 0xa206, 0x0040, 0x828f, 0x6962, 0x6a5e, 0xc6dc, 0x0078, - 0x829a, 0xd6d4, 0x0040, 0x8298, 0x684b, 0x0007, 0x0078, 0x829a, - 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x0040, - 0x82c3, 0xa686, 0x0100, 0x00c0, 0x82ae, 0x2001, 0xac99, 0x2004, - 0xa005, 0x00c0, 0x82ae, 0xc6c4, 0x0078, 0x8236, 0x7328, 0x732c, - 0x6b56, 0x83ff, 0x0040, 0x82c3, 0xa38a, 0x0009, 0x0048, 0x82ba, - 0x2019, 0x0008, 0x037e, 0x2308, 0x2019, 0xac98, 0xad90, 0x0019, - 0x1078, 0x89f2, 0x037f, 0xd6cc, 0x0040, 0x831e, 0x7124, 0x695a, - 0x81ff, 0x0040, 0x831e, 0xa192, 0x0021, 0x00c8, 0x82dc, 0x2071, - 0xac98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x89f2, - 0x1078, 0x9204, 0x0078, 0x831e, 0x6838, 0xd0fc, 0x0040, 0x82e5, - 0x2009, 0x0020, 0x695a, 0x0078, 0x82cf, 0x0f7e, 0x2d78, 0x1078, - 0x898a, 0x0f7f, 0x1078, 0x9204, 0x1078, 0x89df, 0x0078, 0x8320, - 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x830e, 0x684c, - 0xd0ac, 0x0040, 0x830e, 0x6024, 0xd0dc, 0x00c0, 0x830e, 0x6850, - 0xd0bc, 0x00c0, 0x830e, 0x6810, 0x6914, 0xa105, 0x0040, 0x830e, - 0x1078, 0x8fcf, 0x0d7f, 0x0e7f, 0x0078, 0x8330, 0x684b, 0x0000, - 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x831e, 0x6810, - 0x6914, 0xa115, 0x0040, 0x831e, 0x1078, 0x84e2, 0x1078, 0x4a73, - 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, 0x8328, 0x8211, 0x6a3e, - 0x1078, 0x8f99, 0x0d7f, 0x0e7f, 0x00c0, 0x8330, 0x1078, 0x772d, - 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0xac8c, 0x7c04, 0x7b00, - 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0040, 0x8348, - 0x6003, 0x0002, 0x0f7f, 0x007c, 0x2130, 0x2228, 0x0078, 0x8354, - 0x2400, 0x797c, 0xa10a, 0x2300, 0x7a80, 0xa213, 0x2600, 0xa102, - 0x2500, 0xa203, 0x0048, 0x8344, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, - 0x0f7f, 0x603f, 0x0000, 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x5df6, - 0x1078, 0x639b, 0x007c, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x6003, - 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, - 0x15fa, 0x007c, 0xa182, 0x0040, 0x0079, 0x8376, 0x8389, 0x8389, - 0x8389, 0x8389, 0x8389, 0x838b, 0x8431, 0x8389, 0x8389, 0x8447, - 0x84b8, 0x8389, 0x8389, 0x8389, 0x8389, 0x84c7, 0x8389, 0x8389, - 0x8389, 0x1078, 0x1332, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, - 0xac8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, - 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, 0x83a2, - 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x842c, 0xa694, 0xff00, 0xa284, - 0x0c00, 0x0040, 0x83af, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, - 0x0300, 0x0040, 0x842c, 0x1078, 0x138b, 0x1040, 0x1332, 0x2d00, - 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, - 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0040, - 0x83cd, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, - 0x0002, 0x0040, 0x83e9, 0xa186, 0x0028, 0x00c0, 0x83db, 0x684b, - 0x001c, 0x0078, 0x83eb, 0xd6dc, 0x0040, 0x83e2, 0x684b, 0x0015, - 0x0078, 0x83eb, 0xd6d4, 0x0040, 0x83e9, 0x684b, 0x0007, 0x0078, - 0x83eb, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, - 0xa01e, 0xd6c4, 0x0040, 0x8409, 0x7328, 0x732c, 0x6b56, 0x83ff, - 0x0040, 0x8409, 0xa38a, 0x0009, 0x0048, 0x8400, 0x2019, 0x0008, - 0x037e, 0x2308, 0x2019, 0xac98, 0xad90, 0x0019, 0x1078, 0x89f2, - 0x037f, 0xd6cc, 0x0040, 0x842c, 0x7124, 0x695a, 0x81ff, 0x0040, - 0x842c, 0xa192, 0x0021, 0x00c8, 0x8420, 0x2071, 0xac98, 0x831c, - 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x89f2, 0x0078, 0x842c, - 0x7838, 0xd0fc, 0x0040, 0x8429, 0x2009, 0x0020, 0x695a, 0x0078, - 0x8415, 0x2d78, 0x1078, 0x898a, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, - 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0xac8c, 0x7c04, 0x7b00, - 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, - 0x0f7f, 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x6df4, 0x007c, 0x0d7e, - 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x8453, 0x2001, - 0xa9a4, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x627a, 0x1078, - 0x639b, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x84b6, 0xd1cc, - 0x0040, 0x848d, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x8485, 0x017e, - 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198, 0x000d, - 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, - 0x00f0, 0x8474, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e, 0x017f, - 0x2168, 0x1078, 0x13b4, 0x0078, 0x84b0, 0x017e, 0x1078, 0x13b4, - 0x0d7f, 0x1078, 0x89df, 0x0078, 0x84b0, 0x6837, 0x0103, 0x6944, - 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, 0x84ac, 0xa086, 0x0028, - 0x00c0, 0x849e, 0x684b, 0x001c, 0x0078, 0x84ae, 0xd1dc, 0x0040, - 0x84a5, 0x684b, 0x0015, 0x0078, 0x84ae, 0xd1d4, 0x0040, 0x84ac, - 0x684b, 0x0007, 0x0078, 0x84ae, 0x684b, 0x0000, 0x1078, 0x4a73, - 0x1078, 0x8f99, 0x00c0, 0x84b6, 0x1078, 0x772d, 0x0d7f, 0x007c, - 0x2019, 0x0001, 0x1078, 0x7058, 0x6003, 0x0002, 0x2001, 0xa9a4, - 0x2004, 0x603e, 0x1078, 0x627a, 0x1078, 0x639b, 0x007c, 0x1078, - 0x627a, 0x1078, 0x2880, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x8d16, - 0x0040, 0x84dc, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, - 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d, 0x1078, - 0x639b, 0x007c, 0x684b, 0x0015, 0xd1fc, 0x0040, 0x84ee, 0x684b, - 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962, 0x685e, - 0x007c, 0xa182, 0x0040, 0x0079, 0x84f5, 0x8508, 0x8508, 0x8508, - 0x8508, 0x8508, 0x850a, 0x8508, 0x85e0, 0x85ec, 0x8508, 0x8508, - 0x8508, 0x8508, 0x8508, 0x8508, 0x8508, 0x8508, 0x8508, 0x8508, - 0x1078, 0x1332, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0xac8c, - 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x0f7e, 0x2c78, 0x1078, - 0x4963, 0x0f7f, 0x0040, 0x8528, 0xa684, 0x00ff, 0x00c0, 0x8528, - 0x6024, 0xd0f4, 0x0040, 0x8528, 0x1078, 0x8fcf, 0x0078, 0x85db, - 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, - 0x0040, 0x8534, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x85d0, 0xa694, - 0xff00, 0xa284, 0x0c00, 0x0040, 0x8541, 0x7018, 0x7862, 0x701c, - 0x785e, 0xa284, 0x0300, 0x0040, 0x85cd, 0xa686, 0x0100, 0x00c0, - 0x8553, 0x2001, 0xac99, 0x2004, 0xa005, 0x00c0, 0x8553, 0xc6c4, - 0x7e46, 0x0078, 0x8534, 0x1078, 0x138b, 0x1040, 0x1332, 0x2d00, - 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, - 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, - 0x0040, 0x856e, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, - 0xa186, 0x0002, 0x0040, 0x858a, 0xa186, 0x0028, 0x00c0, 0x857c, - 0x684b, 0x001c, 0x0078, 0x858c, 0xd6dc, 0x0040, 0x8583, 0x684b, - 0x0015, 0x0078, 0x858c, 0xd6d4, 0x0040, 0x858a, 0x684b, 0x0007, - 0x0078, 0x858c, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, - 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x85aa, 0x7328, 0x732c, 0x6b56, - 0x83ff, 0x0040, 0x85aa, 0xa38a, 0x0009, 0x0048, 0x85a1, 0x2019, - 0x0008, 0x037e, 0x2308, 0x2019, 0xac98, 0xad90, 0x0019, 0x1078, - 0x89f2, 0x037f, 0xd6cc, 0x0040, 0x85cd, 0x7124, 0x695a, 0x81ff, - 0x0040, 0x85cd, 0xa192, 0x0021, 0x00c8, 0x85c1, 0x2071, 0xac98, - 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x89f2, 0x0078, - 0x85cd, 0x7838, 0xd0fc, 0x0040, 0x85ca, 0x2009, 0x0020, 0x695a, - 0x0078, 0x85b6, 0x2d78, 0x1078, 0x898a, 0xd6dc, 0x00c0, 0x85d3, - 0xa006, 0x0078, 0x85d9, 0x2001, 0x0001, 0x2071, 0xac8c, 0x7218, - 0x731c, 0x1078, 0x1653, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, - 0x2001, 0xa9a4, 0x2004, 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20, - 0x2c10, 0x1078, 0x15fa, 0x007c, 0x2001, 0xa9a4, 0x2004, 0x603e, - 0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, - 0x871c, 0x603f, 0x0000, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, - 0x0040, 0x8632, 0x6814, 0x6910, 0xa115, 0x0040, 0x8632, 0x6a60, - 0xa206, 0x00c0, 0x860f, 0x685c, 0xa106, 0x0040, 0x8632, 0x684c, - 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, - 0x6024, 0xd0f4, 0x00c0, 0x8627, 0x697c, 0x6810, 0xa102, 0x603a, - 0x6980, 0x6814, 0xa103, 0x6036, 0x6024, 0xc0f5, 0x6026, 0x0d7e, - 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, 0x0d7f, 0x1078, 0x8fcf, - 0x0078, 0x871c, 0x694c, 0xd1cc, 0x0040, 0x86e1, 0x6948, 0x6838, - 0xd0fc, 0x0040, 0x8699, 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, - 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, - 0x866c, 0xa086, 0x0028, 0x00c0, 0x8653, 0x684b, 0x001c, 0x784b, - 0x001c, 0x0078, 0x8677, 0xd1dc, 0x0040, 0x8663, 0x684b, 0x0015, - 0x784b, 0x0015, 0x1078, 0x917c, 0x0040, 0x8661, 0x7944, 0xc1dc, - 0x7946, 0x0078, 0x8677, 0xd1d4, 0x0040, 0x866c, 0x684b, 0x0007, - 0x784b, 0x0007, 0x0078, 0x8677, 0x684c, 0xd0ac, 0x0040, 0x8677, - 0x6810, 0x6914, 0xa115, 0x0040, 0x8677, 0x1078, 0x84e2, 0x6848, - 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, 0xaf98, - 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, - 0x8210, 0x00f0, 0x8685, 0x157f, 0x0f7f, 0x007f, 0x6852, 0x007f, - 0x684e, 0x1078, 0x9204, 0x017f, 0x2168, 0x1078, 0x13b4, 0x0078, - 0x8716, 0x017e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, - 0x0002, 0x0040, 0x86c6, 0xa086, 0x0028, 0x00c0, 0x86ad, 0x684b, - 0x001c, 0x784b, 0x001c, 0x0078, 0x86d1, 0xd1dc, 0x0040, 0x86bd, - 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x917c, 0x0040, 0x86bb, - 0x7944, 0xc1dc, 0x7946, 0x0078, 0x86d1, 0xd1d4, 0x0040, 0x86c6, - 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x86d1, 0x684c, 0xd0ac, - 0x0040, 0x86d1, 0x6810, 0x6914, 0xa115, 0x0040, 0x86d1, 0x1078, - 0x84e2, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e, 0x0f7f, - 0x1078, 0x13b4, 0x0d7f, 0x1078, 0x9204, 0x1078, 0x89df, 0x0078, - 0x8716, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, - 0x0040, 0x8707, 0xa086, 0x0028, 0x00c0, 0x86f2, 0x684b, 0x001c, - 0x0078, 0x8714, 0xd1dc, 0x0040, 0x8700, 0x684b, 0x0015, 0x1078, - 0x917c, 0x0040, 0x86fe, 0x6944, 0xc1dc, 0x6946, 0x0078, 0x8714, - 0xd1d4, 0x0040, 0x8707, 0x684b, 0x0007, 0x0078, 0x8714, 0x684b, - 0x0000, 0x684c, 0xd0ac, 0x0040, 0x8714, 0x6810, 0x6914, 0xa115, - 0x0040, 0x8714, 0x1078, 0x84e2, 0x1078, 0x4a73, 0x1078, 0x8f99, - 0x00c0, 0x871c, 0x1078, 0x772d, 0x0d7f, 0x007c, 0x1078, 0x61cd, - 0x0078, 0x8724, 0x1078, 0x627a, 0x1078, 0x8d16, 0x0040, 0x8743, - 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xa70c, 0x210c, - 0xd18c, 0x00c0, 0x874e, 0xd184, 0x00c0, 0x874a, 0x6108, 0x694a, - 0xa18e, 0x0029, 0x00c0, 0x873e, 0x1078, 0xa4f2, 0x6847, 0x0000, - 0x1078, 0x4a73, 0x0d7f, 0x1078, 0x772d, 0x1078, 0x62d1, 0x1078, - 0x639b, 0x007c, 0x684b, 0x0004, 0x0078, 0x873e, 0x684b, 0x0004, - 0x0078, 0x873e, 0xa182, 0x0040, 0x0079, 0x8756, 0x8769, 0x8769, - 0x8769, 0x8769, 0x8769, 0x876b, 0x8769, 0x876e, 0x8769, 0x8769, - 0x8769, 0x8769, 0x8769, 0x8769, 0x8769, 0x8769, 0x8769, 0x8769, - 0x8769, 0x1078, 0x1332, 0x1078, 0x772d, 0x007c, 0x007e, 0x027e, - 0xa016, 0x1078, 0x15fa, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085, - 0x0079, 0x877a, 0x8783, 0x8781, 0x8781, 0x878f, 0x8781, 0x8781, - 0x8781, 0x1078, 0x1332, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, - 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x027e, - 0x057e, 0x0d7e, 0x0e7e, 0x2071, 0xac80, 0x7224, 0x6212, 0x7220, - 0x1078, 0x8d02, 0x0040, 0x87b4, 0x2268, 0x6800, 0xa086, 0x0000, - 0x0040, 0x87b4, 0x6018, 0x6d18, 0xa52e, 0x00c0, 0x87b4, 0x0c7e, - 0x2d60, 0x1078, 0x8a03, 0x0c7f, 0x0040, 0x87b4, 0x6803, 0x0002, - 0x6007, 0x0086, 0x0078, 0x87b6, 0x6007, 0x0087, 0x6003, 0x0001, - 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0f7e, 0x2278, 0x1078, 0x4963, - 0x0f7f, 0x0040, 0x87ce, 0x6824, 0xd0ec, 0x0040, 0x87ce, 0x0c7e, - 0x2260, 0x603f, 0x0000, 0x1078, 0x8fcf, 0x0c7f, 0x0e7f, 0x0d7f, - 0x057f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x87e4, 0x6004, - 0xa08a, 0x0085, 0x1048, 0x1332, 0xa08a, 0x008c, 0x10c8, 0x1332, - 0xa082, 0x0085, 0x0079, 0x87f3, 0xa186, 0x0027, 0x0040, 0x87ec, - 0xa186, 0x0014, 0x10c0, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6, - 0x1078, 0x62d1, 0x007c, 0x87fa, 0x87fc, 0x87fc, 0x87fa, 0x87fa, - 0x87fa, 0x87fa, 0x1078, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6, - 0x1078, 0x62d1, 0x007c, 0xa186, 0x0013, 0x00c0, 0x880d, 0x6004, - 0xa082, 0x0085, 0x2008, 0x0078, 0x8848, 0xa186, 0x0027, 0x00c0, - 0x8830, 0x1078, 0x61cd, 0x1078, 0x2880, 0x0d7e, 0x6010, 0x2068, - 0x1078, 0x8d16, 0x0040, 0x8826, 0x6837, 0x0103, 0x6847, 0x0000, - 0x684b, 0x0029, 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078, - 0x772d, 0x1078, 0x62d1, 0x007c, 0x1078, 0x7773, 0x0078, 0x882b, - 0xa186, 0x0014, 0x00c0, 0x882c, 0x1078, 0x61cd, 0x0d7e, 0x6010, - 0x2068, 0x1078, 0x8d16, 0x0040, 0x8826, 0x6837, 0x0103, 0x6847, - 0x0000, 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x0078, 0x8822, - 0x0079, 0x884a, 0x8853, 0x8851, 0x8851, 0x8851, 0x8851, 0x8851, - 0x886e, 0x1078, 0x1332, 0x1078, 0x61cd, 0x6030, 0xa08c, 0xff00, - 0x810f, 0xa186, 0x0039, 0x0040, 0x8861, 0xa186, 0x0035, 0x00c0, - 0x8865, 0x2001, 0xa9a2, 0x0078, 0x8867, 0x2001, 0xa9a3, 0x2004, - 0x6016, 0x6003, 0x000c, 0x1078, 0x62d1, 0x007c, 0x1078, 0x61cd, - 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x887c, - 0xa186, 0x0035, 0x00c0, 0x8880, 0x2001, 0xa9a2, 0x0078, 0x8882, - 0x2001, 0xa9a3, 0x2004, 0x6016, 0x6003, 0x000e, 0x1078, 0x62d1, - 0x007c, 0xa182, 0x008c, 0x00c8, 0x8893, 0xa182, 0x0085, 0x0048, - 0x8893, 0x0079, 0x8896, 0x1078, 0x7773, 0x007c, 0x889d, 0x889d, - 0x889d, 0x889d, 0x889f, 0x88fc, 0x889d, 0x1078, 0x1332, 0x0f7e, - 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x88b2, 0x6030, 0xa08c, - 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x8913, 0xa186, 0x0035, - 0x0040, 0x8913, 0x0d7e, 0x1078, 0x8d16, 0x00c0, 0x88bb, 0x1078, - 0x8ec9, 0x0078, 0x88de, 0x6010, 0x2068, 0x684c, 0xd0e4, 0x00c0, - 0x88c3, 0x1078, 0x8ec9, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, - 0x88cf, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0078, 0x88da, 0xd0bc, - 0x0040, 0x88d6, 0x684b, 0x0002, 0x0078, 0x88da, 0x684b, 0x0005, - 0x1078, 0x8f95, 0x6847, 0x0000, 0x1078, 0x4a73, 0x2c68, 0x1078, - 0x76c7, 0x0040, 0x88f7, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, - 0xac8e, 0x210c, 0x6136, 0x2009, 0xac8f, 0x210c, 0x613a, 0x6918, - 0x611a, 0x6920, 0x6122, 0x601f, 0x0001, 0x1078, 0x5d8a, 0x2d60, - 0x1078, 0x772d, 0x0d7f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4963, - 0x0f7f, 0x0040, 0x8939, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, - 0x0035, 0x0040, 0x8913, 0xa186, 0x001e, 0x0040, 0x8913, 0xa186, - 0x0039, 0x00c0, 0x8939, 0x0d7e, 0x2c68, 0x1078, 0x91cc, 0x00c0, - 0x895d, 0x1078, 0x76c7, 0x0040, 0x8936, 0x6106, 0x6003, 0x0001, - 0x601f, 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, - 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, - 0x6920, 0x6122, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x2d60, 0x0078, - 0x895d, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x895d, - 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x894c, 0xc0ec, 0x6852, - 0x684b, 0x0006, 0x0078, 0x8957, 0xd0bc, 0x0040, 0x8953, 0x684b, - 0x0002, 0x0078, 0x8957, 0x684b, 0x0005, 0x1078, 0x8f95, 0x6847, - 0x0000, 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d, - 0x007c, 0x017e, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, - 0x8971, 0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x1078, - 0x4a73, 0x0d7f, 0x017f, 0xa186, 0x0013, 0x0040, 0x8983, 0xa186, - 0x0014, 0x0040, 0x8983, 0xa186, 0x0027, 0x0040, 0x8983, 0x1078, - 0x7773, 0x0078, 0x8989, 0x1078, 0x61cd, 0x1078, 0x8ed6, 0x1078, - 0x62d1, 0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, - 0xa182, 0x0101, 0x00c8, 0x8996, 0x0078, 0x8998, 0x2009, 0x0100, - 0x2130, 0x2069, 0xac98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, - 0xaf90, 0x001d, 0x1078, 0x89f2, 0xa6b2, 0x0020, 0x7804, 0xa06d, - 0x0040, 0x89ac, 0x1078, 0x13b4, 0x1078, 0x138b, 0x0040, 0x89d6, - 0x8528, 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, - 0x003d, 0x00c8, 0x89c2, 0x2608, 0xad90, 0x000f, 0x1078, 0x89f2, - 0x0078, 0x89d6, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, - 0x000f, 0x1078, 0x89f2, 0x0078, 0x89ac, 0x0f7f, 0x852f, 0xa5ad, - 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0078, 0x89db, 0x0f7f, 0x852f, - 0xa5ad, 0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, - 0x8dff, 0x0040, 0x89f0, 0x6804, 0xa07d, 0x0040, 0x89ee, 0x6807, - 0x0000, 0x1078, 0x4a73, 0x2f68, 0x0078, 0x89e3, 0x1078, 0x4a73, - 0x0f7f, 0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x89f8, 0x8108, - 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, - 0x89fa, 0x157f, 0x007c, 0x067e, 0x127e, 0x2091, 0x8000, 0x2031, - 0x0001, 0x601c, 0xa084, 0x000f, 0x1079, 0x8a1f, 0x127f, 0x067f, - 0x007c, 0x127e, 0x2091, 0x8000, 0x067e, 0x2031, 0x0000, 0x601c, - 0xa084, 0x000f, 0x1079, 0x8a1f, 0x067f, 0x127f, 0x007c, 0x8a39, - 0x8a27, 0x8a34, 0x8a55, 0x8a27, 0x8a34, 0x8a55, 0x8a34, 0x1078, - 0x1332, 0x037e, 0x2019, 0x0010, 0x1078, 0x9dd7, 0x601f, 0x0006, - 0x6003, 0x0007, 0x037f, 0x007c, 0xa006, 0x007c, 0xa085, 0x0001, - 0x007c, 0x0d7e, 0x86ff, 0x00c0, 0x8a50, 0x6010, 0x2068, 0x1078, - 0x8d16, 0x0040, 0x8a52, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4b51, - 0x1078, 0x8f95, 0x1078, 0x4a73, 0x1078, 0x772d, 0xa085, 0x0001, - 0x0d7f, 0x007c, 0xa006, 0x0078, 0x8a50, 0x6000, 0xa08a, 0x0010, - 0x10c8, 0x1332, 0x1079, 0x8a5d, 0x007c, 0x8a6d, 0x8a92, 0x8a6f, - 0x8ab5, 0x8a8e, 0x8a6d, 0x8a34, 0x8a39, 0x8a39, 0x8a34, 0x8a34, - 0x8a34, 0x8a34, 0x8a34, 0x8a34, 0x8a34, 0x1078, 0x1332, 0x86ff, - 0x00c0, 0x8a8b, 0x601c, 0xa086, 0x0006, 0x0040, 0x8a8b, 0x0d7e, - 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x8a80, 0x1078, 0x8f95, - 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, - 0x5d8a, 0x1078, 0x62d1, 0xa085, 0x0001, 0x007c, 0x1078, 0x1757, - 0x0078, 0x8a6f, 0x0e7e, 0x2071, 0xa9b1, 0x7024, 0xac06, 0x00c0, - 0x8a9b, 0x1078, 0x6fc4, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, - 0x00c0, 0x8aad, 0x087e, 0x097e, 0x2049, 0x0001, 0x2c40, 0x1078, - 0x7246, 0x097f, 0x087f, 0x0078, 0x8aaf, 0x1078, 0x6ebe, 0x0e7f, - 0x00c0, 0x8a6f, 0x1078, 0x8a34, 0x007c, 0x037e, 0x0e7e, 0x2071, - 0xa9b1, 0x703c, 0xac06, 0x00c0, 0x8ac5, 0x2019, 0x0000, 0x1078, - 0x7058, 0x0e7f, 0x037f, 0x0078, 0x8a6f, 0x1078, 0x738a, 0x0e7f, - 0x037f, 0x00c0, 0x8a6f, 0x1078, 0x8a34, 0x007c, 0x0c7e, 0x601c, - 0xa084, 0x000f, 0x1079, 0x8ad6, 0x0c7f, 0x007c, 0x8ae5, 0x8b57, - 0x8c8f, 0x8af0, 0x8ed6, 0x8ae5, 0x9dc8, 0x772d, 0x8b57, 0x1078, - 0x8f10, 0x00c0, 0x8ae5, 0x1078, 0x7c83, 0x007c, 0x1078, 0x61cd, - 0x1078, 0x62d1, 0x1078, 0x772d, 0x007c, 0x6017, 0x0001, 0x007c, - 0x1078, 0x8d16, 0x0040, 0x8af8, 0x6010, 0xa080, 0x0019, 0x2c02, - 0x6000, 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8b00, 0x007c, - 0x8b10, 0x8b12, 0x8b34, 0x8b46, 0x8b53, 0x8b10, 0x8ae5, 0x8ae5, - 0x8ae5, 0x8b46, 0x8b46, 0x8b10, 0x8b10, 0x8b10, 0x8b10, 0x8b50, - 0x1078, 0x1332, 0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, - 0x2071, 0xa9b1, 0x7024, 0xac06, 0x0040, 0x8b30, 0x1078, 0x6ebe, - 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xa9a3, - 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0e7f, 0x007c, - 0x6017, 0x0001, 0x0078, 0x8b2e, 0x0d7e, 0x6010, 0x2068, 0x6850, - 0xc0b5, 0x6852, 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, - 0x0002, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x007c, 0x0d7e, 0x6017, - 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x007c, - 0x1078, 0x772d, 0x007c, 0x1078, 0x1757, 0x0078, 0x8b34, 0x6000, - 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8b5f, 0x007c, 0x8b6f, - 0x8aed, 0x8b71, 0x8b6f, 0x8b71, 0x8b71, 0x8ae6, 0x8b6f, 0x8adf, - 0x8adf, 0x8b6f, 0x8b6f, 0x8b6f, 0x8b6f, 0x8b6f, 0x8b6f, 0x1078, - 0x1332, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, - 0xa08a, 0x000c, 0x10c8, 0x1332, 0x1079, 0x8b7f, 0x007c, 0x8b8b, - 0x8c33, 0x8b8d, 0x8bcd, 0x8b8d, 0x8bcd, 0x8b8d, 0x8b9a, 0x8b8b, - 0x8bcd, 0x8b8b, 0x8bb7, 0x1078, 0x1332, 0x6004, 0xa08e, 0x0016, - 0x0040, 0x8bc8, 0xa08e, 0x0004, 0x0040, 0x8bc8, 0xa08e, 0x0002, - 0x0040, 0x8bc8, 0x6004, 0x1078, 0x8f10, 0x0040, 0x8c4e, 0xa08e, - 0x0021, 0x0040, 0x8c52, 0xa08e, 0x0022, 0x0040, 0x8c4e, 0xa08e, - 0x003d, 0x0040, 0x8c52, 0xa08e, 0x0039, 0x0040, 0x8c56, 0xa08e, - 0x0035, 0x0040, 0x8c56, 0xa08e, 0x001e, 0x0040, 0x8bca, 0xa08e, - 0x0001, 0x00c0, 0x8bc6, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, - 0x00ff, 0x0d7f, 0xa086, 0x0006, 0x0040, 0x8bc8, 0x1078, 0x2880, - 0x1078, 0x7c83, 0x1078, 0x8ed6, 0x007c, 0x0c7e, 0x0d7e, 0x6104, - 0xa186, 0x0016, 0x0040, 0x8c23, 0xa186, 0x0002, 0x00c0, 0x8bf6, - 0x6018, 0x2068, 0x68a0, 0xd0bc, 0x00c0, 0x8c7a, 0x6840, 0xa084, - 0x00ff, 0xa005, 0x0040, 0x8bf6, 0x8001, 0x6842, 0x6013, 0x0000, - 0x601f, 0x0007, 0x6017, 0x0398, 0x1078, 0x76c7, 0x0040, 0x8bf6, - 0x2d00, 0x601a, 0x601f, 0x0001, 0x0078, 0x8c23, 0x0d7f, 0x0c7f, - 0x6004, 0xa08e, 0x0002, 0x00c0, 0x8c14, 0x6018, 0xa080, 0x0028, - 0x2004, 0xa086, 0x007e, 0x00c0, 0x8c14, 0x2009, 0xa733, 0x2104, - 0xc085, 0x200a, 0x0e7e, 0x2071, 0xa700, 0x1078, 0x42b8, 0x0e7f, - 0x1078, 0x7c83, 0x0078, 0x8c18, 0x1078, 0x7c83, 0x1078, 0x2880, - 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x28a6, 0x127f, 0x0e7f, - 0x1078, 0x8ed6, 0x007c, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, - 0x0001, 0x6007, 0x0002, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0d7f, - 0x0c7f, 0x0078, 0x8c22, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, - 0x0040, 0x8c23, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, - 0x0040, 0x8bf6, 0x8001, 0x6842, 0x6003, 0x0001, 0x1078, 0x5dd7, - 0x1078, 0x62d1, 0x0d7f, 0x0c7f, 0x0078, 0x8c22, 0x1078, 0x7c83, - 0x0078, 0x8bca, 0x1078, 0x7ca6, 0x0078, 0x8bca, 0x0d7e, 0x2c68, - 0x6104, 0x1078, 0x91cc, 0x0d7f, 0x0040, 0x8c62, 0x1078, 0x772d, - 0x0078, 0x8c79, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, - 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, - 0x600a, 0x2001, 0xa9a3, 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, - 0x62d1, 0x007c, 0x0d7f, 0x0c7f, 0x1078, 0x7c83, 0x1078, 0x2880, - 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x28a6, 0x6013, 0x0000, - 0x601f, 0x0007, 0x6017, 0x0398, 0x127f, 0x0e7f, 0x007c, 0x6000, - 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8c97, 0x007c, 0x8ca7, - 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, - 0x8ae5, 0x8ca7, 0x8aed, 0x8ca9, 0x8aed, 0x8cb7, 0x8ca7, 0x1078, - 0x1332, 0x6004, 0xa086, 0x008b, 0x0040, 0x8cb7, 0x6007, 0x008b, - 0x6003, 0x000d, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x007c, 0x1078, - 0x8ec9, 0x1078, 0x8d16, 0x0040, 0x8cef, 0x1078, 0x2880, 0x0d7e, - 0x1078, 0x8d16, 0x0040, 0x8cd1, 0x6010, 0x2068, 0x6837, 0x0103, - 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x1078, - 0x4a73, 0x2c68, 0x1078, 0x76c7, 0x0040, 0x8cdf, 0x6818, 0x601a, - 0x0c7e, 0x2d60, 0x1078, 0x8ed6, 0x0c7f, 0x0078, 0x8ce0, 0x2d60, - 0x0d7f, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, - 0x0001, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0078, 0x8d01, 0x6030, - 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x8cfb, 0xa186, - 0x0035, 0x00c0, 0x8cff, 0x1078, 0x2880, 0x0078, 0x8cd1, 0x1078, - 0x8ed6, 0x007c, 0xa284, 0x000f, 0x00c0, 0x8d13, 0xa282, 0xae00, - 0x0048, 0x8d13, 0x2001, 0xa716, 0x2004, 0xa202, 0x00c8, 0x8d13, - 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x8d12, 0x027e, 0x0e7e, - 0x2071, 0xa700, 0x6210, 0x705c, 0xa202, 0x0048, 0x8d28, 0x7060, - 0xa202, 0x00c8, 0x8d28, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c, - 0xa006, 0x0078, 0x8d25, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e, - 0x2091, 0x8000, 0x2061, 0xae00, 0x2071, 0xa700, 0x7348, 0x7064, - 0xa302, 0x00c8, 0x8d55, 0x601c, 0xa206, 0x00c0, 0x8d4d, 0x1078, - 0x903b, 0x0040, 0x8d4d, 0x1078, 0x8f10, 0x00c0, 0x8d49, 0x1078, - 0x7c83, 0x0c7e, 0x1078, 0x772d, 0x0c7f, 0xace0, 0x0010, 0x7058, - 0xac02, 0x00c8, 0x8d55, 0x0078, 0x8d36, 0x127f, 0x007f, 0x037f, - 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0xa835, - 0x210c, 0x81ff, 0x0040, 0x8d69, 0x2061, 0xaab3, 0x611a, 0x1078, - 0x2880, 0xa006, 0x0078, 0x8d6e, 0xa085, 0x0001, 0x017f, 0x0c7f, - 0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e, - 0x1078, 0x76c7, 0x057f, 0x0040, 0x8d8b, 0x6612, 0x651a, 0x601f, - 0x0003, 0x2009, 0x004b, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, - 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8d87, 0x0c7e, 0x057e, - 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x76c7, 0x057f, - 0x0040, 0x8db9, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e, - 0x2560, 0x1078, 0x47e9, 0x0c7f, 0x1078, 0x5f01, 0x077e, 0x2039, - 0x0000, 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f9b, 0x077f, 0x2009, - 0x004c, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, - 0x007c, 0xa006, 0x0078, 0x8db5, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, - 0x1078, 0x76c7, 0x2c78, 0x0c7f, 0x0040, 0x8dd6, 0x7e12, 0x2c00, - 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x1078, 0x8e21, 0x2f60, - 0x2009, 0x004d, 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, - 0x0f7f, 0x007c, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x76c7, - 0x2c78, 0x0c7f, 0x0040, 0x8df4, 0x7e12, 0x2c00, 0x781a, 0x781f, - 0x0003, 0x2021, 0x0005, 0x1078, 0x8e21, 0x2f60, 0x2009, 0x004e, - 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c, - 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x76c7, 0x2c78, 0x0c7f, - 0x0040, 0x8e1d, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, - 0x0004, 0x1078, 0x8e21, 0x2001, 0xa99d, 0x2004, 0xd0fc, 0x0040, - 0x8e16, 0x2f60, 0x1078, 0x772d, 0x0078, 0x8e1b, 0x2f60, 0x2009, - 0x0052, 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, - 0x007c, 0x097e, 0x077e, 0x127e, 0x2091, 0x8000, 0x1078, 0x4775, - 0x0040, 0x8e2e, 0x2001, 0x8e26, 0x0078, 0x8e34, 0x1078, 0x4739, - 0x0040, 0x8e3d, 0x2001, 0x8e2e, 0x007e, 0xa00e, 0x2400, 0x1078, - 0x4b51, 0x1078, 0x4a73, 0x007f, 0x007a, 0x2418, 0x1078, 0x6161, - 0x62a0, 0x087e, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x1078, - 0x5f1b, 0x087f, 0x1078, 0x5e0a, 0x2f08, 0x2648, 0x1078, 0x9f9b, - 0x613c, 0x81ff, 0x1040, 0x5fdb, 0x1078, 0x62d1, 0x127f, 0x077f, - 0x097f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, - 0x76c7, 0x017f, 0x0040, 0x8e73, 0x660a, 0x611a, 0x601f, 0x0001, - 0x2d00, 0x6012, 0x2009, 0x001f, 0x1078, 0x775c, 0xa085, 0x0001, - 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8e70, 0x0c7e, 0x127e, - 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x8e8f, - 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, - 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, - 0x0078, 0x8e8c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, - 0x76c7, 0x017f, 0x0040, 0x8eab, 0x660a, 0x611a, 0x601f, 0x0001, - 0x2d00, 0x6012, 0x2009, 0x003d, 0x1078, 0x775c, 0xa085, 0x0001, - 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8ea8, 0x0c7e, 0x127e, - 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x8ec6, - 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x1078, - 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, - 0x8ec3, 0x027e, 0x0d7e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, - 0x8ed3, 0x8211, 0x6a3e, 0x0d7f, 0x027f, 0x007c, 0x007e, 0x6000, - 0xa086, 0x0000, 0x0040, 0x8ee8, 0x6013, 0x0000, 0x601f, 0x0007, - 0x2001, 0xa9a3, 0x2004, 0x6016, 0x1078, 0xa4a5, 0x603f, 0x0000, - 0x007f, 0x007c, 0x067e, 0x0c7e, 0x0d7e, 0x2031, 0xa753, 0x2634, - 0xd6e4, 0x0040, 0x8ef8, 0x6618, 0x2660, 0x6e48, 0x1078, 0x46e7, - 0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, - 0x0002, 0x0040, 0x8f0d, 0xa08e, 0x0003, 0x0040, 0x8f0d, 0xa08e, - 0x0004, 0x0040, 0x8f0d, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, - 0x007e, 0x0d7e, 0x6010, 0xa06d, 0x0040, 0x8f1d, 0x6838, 0xd0fc, - 0x0040, 0x8f1d, 0xa006, 0x0078, 0x8f1f, 0xa085, 0x0001, 0x0d7f, - 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, - 0x76c7, 0x017f, 0x0040, 0x8f3c, 0x611a, 0x601f, 0x0001, 0x2d00, - 0x6012, 0x1078, 0x2880, 0x2009, 0x0028, 0x1078, 0x775c, 0xa085, - 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8f39, 0xa186, - 0x0015, 0x00c0, 0x8f54, 0x2011, 0xa720, 0x2204, 0xa086, 0x0074, - 0x00c0, 0x8f54, 0x1078, 0x7f91, 0x6003, 0x0001, 0x6007, 0x0029, - 0x1078, 0x5dd7, 0x0078, 0x8f58, 0x1078, 0x7c83, 0x1078, 0x772d, - 0x007c, 0xa186, 0x0016, 0x00c0, 0x8f63, 0x2001, 0x0004, 0x1078, - 0x4502, 0x0078, 0x8f84, 0xa186, 0x0015, 0x00c0, 0x8f88, 0x2011, - 0xa720, 0x2204, 0xa086, 0x0014, 0x00c0, 0x8f88, 0x0d7e, 0x6018, - 0x2068, 0x1078, 0x4649, 0x0d7f, 0x1078, 0x8043, 0x00c0, 0x8f88, - 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, 0x0040, 0x8f88, - 0x2001, 0x0006, 0x1078, 0x4502, 0x1078, 0x77f8, 0x0078, 0x8f8c, - 0x1078, 0x7c83, 0x1078, 0x772d, 0x007c, 0x6848, 0xa086, 0x0005, - 0x00c0, 0x8f94, 0x1078, 0x8f95, 0x007c, 0x6850, 0xc0ad, 0x6852, - 0x007c, 0x0e7e, 0x2071, 0xac8c, 0x7014, 0xd0e4, 0x0040, 0x8faa, - 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x1078, 0x5d8a, - 0x1078, 0x62d1, 0x0e7f, 0x007c, 0x0c7e, 0x0f7e, 0x2c78, 0x1078, - 0x4963, 0x0f7f, 0x0040, 0x8fb9, 0x601c, 0xa084, 0x000f, 0x1079, - 0x8fbb, 0x0c7f, 0x007c, 0x8ae5, 0x8fc6, 0x8fc9, 0x8fcc, 0xa26d, - 0xa289, 0xa28c, 0x8ae5, 0x8ae5, 0x1078, 0x1332, 0x0005, 0x0005, - 0x007c, 0x0005, 0x0005, 0x007c, 0x1078, 0x8fcf, 0x007c, 0x0f7e, - 0x2c78, 0x1078, 0x4963, 0x0040, 0x8ffe, 0x1078, 0x76c7, 0x00c0, - 0x8fdf, 0x2001, 0xa9a4, 0x2004, 0x783e, 0x0078, 0x8ffe, 0x7818, - 0x601a, 0x781c, 0xa086, 0x0003, 0x0040, 0x8fec, 0x7808, 0x6036, - 0x2f00, 0x603a, 0x0078, 0x8ff0, 0x7808, 0x603a, 0x2f00, 0x6036, - 0x602a, 0x601f, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x7920, - 0x6122, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x2f60, 0x0f7f, 0x007c, - 0x017e, 0x0f7e, 0x682c, 0x6032, 0xa08e, 0x0001, 0x0040, 0x9011, - 0xa086, 0x0005, 0x0040, 0x9015, 0xa006, 0x602a, 0x602e, 0x0078, - 0x9026, 0x6824, 0xc0f4, 0xc0d5, 0x6826, 0x6810, 0x2078, 0x787c, - 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x00c8, 0x900c, 0x6834, - 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036, - 0x6808, 0x603a, 0x6918, 0x611a, 0x6920, 0x6122, 0x601f, 0x0001, - 0x6007, 0x0039, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x6803, 0x0002, - 0x0f7f, 0x017f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0034, - 0x0040, 0x9060, 0xa08e, 0x0035, 0x0040, 0x9060, 0xa08e, 0x0036, - 0x0040, 0x9060, 0xa08e, 0x0037, 0x0040, 0x9060, 0xa08e, 0x0038, - 0x0040, 0x9060, 0xa08e, 0x0039, 0x0040, 0x9060, 0xa08e, 0x003a, - 0x0040, 0x9060, 0xa08e, 0x003b, 0x0040, 0x9060, 0xa085, 0x0001, - 0x017f, 0x007f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x00c0, - 0x906d, 0xa085, 0x0001, 0x0078, 0x907c, 0x6024, 0xd0f4, 0x00c0, - 0x907b, 0xc0f5, 0x6026, 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, - 0x6036, 0x1078, 0x1757, 0xa006, 0x0f7f, 0x007c, 0x007e, 0x017e, - 0x027e, 0x037e, 0x0e7e, 0x2001, 0xa99e, 0x200c, 0x8000, 0x2014, - 0x2001, 0x0032, 0x1078, 0x5c1c, 0x2001, 0xa9a2, 0x82ff, 0x00c0, - 0x9093, 0x2011, 0x0014, 0x2202, 0x2001, 0xa9a0, 0x200c, 0x8000, - 0x2014, 0x2071, 0xa98d, 0x711a, 0x721e, 0x2001, 0x0064, 0x1078, - 0x5c1c, 0x2001, 0xa9a3, 0x82ff, 0x00c0, 0x90a8, 0x2011, 0x0014, - 0x2202, 0x2009, 0xa9a4, 0xa280, 0x000a, 0x200a, 0x1078, 0x498b, - 0x0e7f, 0x037f, 0x027f, 0x017f, 0x007f, 0x007c, 0x007e, 0x0e7e, - 0x2001, 0xa9a2, 0x2003, 0x0028, 0x2001, 0xa9a3, 0x2003, 0x0014, - 0x2071, 0xa98d, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0xa9a4, - 0x2003, 0x001e, 0x0e7f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, - 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x90e5, 0x611a, - 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x1078, 0x775c, - 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x90e2, - 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, 0xa700, 0xa186, 0x0015, 0x00c0, - 0x9117, 0x7080, 0xa086, 0x0018, 0x00c0, 0x9117, 0x6010, 0x2068, - 0x6a3c, 0xd2e4, 0x00c0, 0x910b, 0x2c78, 0x1078, 0x6490, 0x0040, - 0x911f, 0x706c, 0x6a50, 0xa206, 0x00c0, 0x9113, 0x7070, 0x6a54, - 0xa206, 0x00c0, 0x9113, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, - 0x0000, 0x1078, 0x28c8, 0x1078, 0x77f8, 0x0078, 0x911b, 0x1078, - 0x7c83, 0x1078, 0x772d, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x7050, - 0xa080, 0x29c0, 0x2004, 0x6a54, 0xa206, 0x0040, 0x910b, 0x0078, - 0x9113, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, - 0x017f, 0x0040, 0x9141, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, - 0x2009, 0x0043, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, - 0x007c, 0xa006, 0x0078, 0x913e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, - 0xa700, 0xa186, 0x0015, 0x00c0, 0x916a, 0x7080, 0xa086, 0x0004, - 0x00c0, 0x916a, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x1078, 0x6490, - 0x0040, 0x9172, 0x706c, 0x6a08, 0xa206, 0x00c0, 0x9166, 0x7070, - 0x6a0c, 0xa206, 0x00c0, 0x9166, 0x1078, 0x2880, 0x1078, 0x77f8, - 0x0078, 0x916e, 0x1078, 0x7c83, 0x1078, 0x772d, 0x0f7f, 0x0e7f, - 0x0d7f, 0x007c, 0x7050, 0xa080, 0x29c0, 0x2004, 0x6a0c, 0xa206, - 0x0040, 0x9164, 0x0078, 0x9166, 0x017e, 0x027e, 0x684c, 0xd0ac, - 0x0040, 0x9194, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040, 0x9194, - 0x6860, 0xa106, 0x00c0, 0x9190, 0x685c, 0xa206, 0x0040, 0x9194, - 0x6962, 0x6a5e, 0xa085, 0x0001, 0x027f, 0x017f, 0x007c, 0x0e7e, - 0x127e, 0x2071, 0xa700, 0x2091, 0x8000, 0x7548, 0xa582, 0x0001, - 0x0048, 0x91c9, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, - 0x91b5, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, 0x91b1, 0x0078, - 0x91a4, 0x2061, 0xae00, 0x0078, 0x91a4, 0x6003, 0x0008, 0x8529, - 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, 0x91c5, 0x754e, - 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704f, 0xae00, 0x0078, - 0x91c0, 0xa006, 0x0078, 0x91c2, 0x0c7e, 0x027e, 0x017e, 0xa186, - 0x0035, 0x0040, 0x91d6, 0x6a34, 0x0078, 0x91d7, 0x6a28, 0x1078, - 0x8d02, 0x0040, 0x9200, 0x2260, 0x611c, 0xa186, 0x0003, 0x0040, - 0x91e5, 0xa186, 0x0006, 0x00c0, 0x91fc, 0x6834, 0xa206, 0x0040, - 0x91f4, 0x6838, 0xa206, 0x00c0, 0x91fc, 0x6108, 0x6834, 0xa106, - 0x00c0, 0x91fc, 0x0078, 0x91f9, 0x6008, 0x6938, 0xa106, 0x00c0, - 0x91fc, 0x6018, 0x6918, 0xa106, 0x017f, 0x027f, 0x0c7f, 0x007c, - 0xa085, 0x0001, 0x0078, 0x91fc, 0x6944, 0xd1cc, 0x0040, 0x921d, - 0xa18c, 0x00ff, 0xa18e, 0x0002, 0x00c0, 0x921d, 0xad88, 0x001e, - 0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, 0x0001, 0x00c0, 0x921d, - 0x6810, 0x6914, 0xa115, 0x10c0, 0x84e2, 0x007c, 0x067e, 0x6000, - 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x9228, 0x067f, 0x007c, - 0x9238, 0x96ef, 0x980b, 0x9238, 0x9238, 0x9238, 0x9238, 0x9238, - 0x9272, 0x989e, 0x9238, 0x9238, 0x9238, 0x9238, 0x9238, 0x9238, - 0x1078, 0x1332, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1332, - 0x1079, 0x9244, 0x067f, 0x007c, 0x9254, 0x9d63, 0x9254, 0x9254, - 0x9254, 0x9254, 0x9254, 0x9254, 0x9d21, 0x9db1, 0x9254, 0xa3c0, - 0xa3f4, 0xa3c0, 0xa3f4, 0x9254, 0x1078, 0x1332, 0x067e, 0x6000, - 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x9260, 0x067f, 0x007c, - 0x9270, 0x99fb, 0x9ad7, 0x9b05, 0x9b80, 0x9270, 0x9c86, 0x9c2e, - 0x98aa, 0x9cf5, 0x9d0b, 0x9270, 0x9270, 0x9270, 0x9270, 0x9270, - 0x1078, 0x1332, 0xa1b2, 0x0044, 0x10c8, 0x1332, 0x2100, 0x0079, - 0x9279, 0x92b9, 0x94a8, 0x92b9, 0x92b9, 0x92b9, 0x94b0, 0x92b9, - 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, - 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, - 0x92bb, 0x9321, 0x9330, 0x9387, 0x93a6, 0x9425, 0x9495, 0x92b9, - 0x92b9, 0x94b4, 0x92b9, 0x92b9, 0x94c7, 0x94d2, 0x92b9, 0x92b9, - 0x92b9, 0x92b9, 0x92b9, 0x950a, 0x92b9, 0x92b9, 0x9519, 0x92b9, - 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x9532, 0x92b9, 0x92b9, - 0x92b9, 0x95bf, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, - 0x9639, 0x1078, 0x1332, 0x1078, 0x4967, 0x00c0, 0x92cb, 0x2001, - 0xa733, 0x2004, 0xd0cc, 0x00c0, 0x92cb, 0xa084, 0x0009, 0xa086, - 0x0008, 0x00c0, 0x92d3, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, - 0x0000, 0x0078, 0x94a3, 0x1078, 0x4957, 0x0e7e, 0x0c7e, 0x037e, - 0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, - 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x2c08, - 0x1078, 0x9f9b, 0x077f, 0x017f, 0x2e60, 0x1078, 0x47e9, 0x017f, - 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x6618, 0x0c7e, 0x2660, 0x1078, - 0x45d6, 0x0c7f, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, - 0x0006, 0x0048, 0x9313, 0x1078, 0x9ecf, 0x00c0, 0x9381, 0x1078, - 0x9e60, 0x00c0, 0x930f, 0x6007, 0x0008, 0x0078, 0x94a3, 0x6007, - 0x0009, 0x0078, 0x94a3, 0x1078, 0xa0af, 0x0040, 0x931d, 0x1078, - 0x9ecf, 0x0040, 0x9307, 0x0078, 0x9381, 0x6013, 0x1900, 0x0078, - 0x930f, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x6106, 0x1078, 0x9e15, - 0x6007, 0x0006, 0x0078, 0x94a3, 0x6007, 0x0007, 0x0078, 0x94a3, - 0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb, 0x00c0, 0x9674, - 0x0d7e, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006, - 0x00c8, 0x9346, 0x2001, 0x0001, 0x1078, 0x44ee, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0006, 0x0040, 0x9363, 0xa686, 0x0004, 0x0040, - 0x9363, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0040, 0x9363, - 0xa686, 0x0004, 0x0040, 0x9363, 0xa686, 0x0005, 0x0040, 0x9363, - 0x0d7f, 0x0078, 0x9381, 0x1078, 0x9f35, 0x00c0, 0x937c, 0xa686, - 0x0006, 0x00c0, 0x9375, 0x027e, 0x6218, 0xa290, 0x0028, 0x2214, - 0x2009, 0x0000, 0x1078, 0x28c8, 0x027f, 0x1078, 0x4649, 0x6007, - 0x000a, 0x0d7f, 0x0078, 0x94a3, 0x6007, 0x000b, 0x0d7f, 0x0078, - 0x94a3, 0x1078, 0x2880, 0x6007, 0x0001, 0x0078, 0x94a3, 0x1078, - 0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x6618, - 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa686, 0x0707, 0x0040, 0x9381, - 0x027e, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, - 0x28c8, 0x027f, 0x6007, 0x000c, 0x0078, 0x94a3, 0x1078, 0x4967, - 0x00c0, 0x93b3, 0x2001, 0xa733, 0x2004, 0xa084, 0x0009, 0xa086, - 0x0008, 0x00c0, 0x93bb, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, - 0x0000, 0x0078, 0x94a3, 0x1078, 0x4957, 0x6618, 0xa6b0, 0x0001, - 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x93ff, 0xa6b4, - 0xff00, 0x8637, 0xa686, 0x0004, 0x0040, 0x93d2, 0xa686, 0x0006, - 0x00c0, 0x9381, 0x1078, 0x9f44, 0x00c0, 0x93da, 0x6007, 0x000e, - 0x0078, 0x94a3, 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, - 0x00ff, 0x8427, 0x047e, 0x1078, 0x2880, 0x047f, 0x017e, 0xa006, - 0x2009, 0xa753, 0x210c, 0xd1a4, 0x0040, 0x93f9, 0x2009, 0x0029, - 0x1078, 0xa22d, 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5, 0x6802, - 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, 0x0078, 0x94a3, 0x2001, - 0x0001, 0x1078, 0x44ee, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, - 0x0004, 0x2019, 0xa705, 0x2011, 0xac90, 0x1078, 0x80de, 0x037f, - 0x027f, 0x017f, 0x157f, 0xa005, 0x0040, 0x941f, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0006, 0x0040, 0x93d2, 0x0078, 0x9381, 0x6013, - 0x1900, 0x6007, 0x0009, 0x0078, 0x94a3, 0x1078, 0x4967, 0x00c0, - 0x9432, 0x2001, 0xa733, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, - 0x00c0, 0x943a, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, - 0x0078, 0x94a3, 0x1078, 0x4957, 0x6618, 0xa6b0, 0x0001, 0x2634, - 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x9482, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0004, 0x0040, 0x9451, 0xa686, 0x0006, 0x00c0, - 0x9381, 0x1078, 0x9f6f, 0x00c0, 0x945d, 0x1078, 0x9e60, 0x00c0, - 0x945d, 0x6007, 0x0010, 0x0078, 0x94a3, 0x047e, 0x6418, 0xa4a0, - 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x047e, 0x1078, 0x2880, - 0x047f, 0x017e, 0xa006, 0x2009, 0xa753, 0x210c, 0xd1a4, 0x0040, - 0x947c, 0x2009, 0x0029, 0x1078, 0xa22d, 0x6018, 0x0d7e, 0x2068, - 0x6800, 0xc0e5, 0x6802, 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, - 0x0078, 0x94a3, 0x1078, 0xa0af, 0x0040, 0x948f, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0006, 0x0040, 0x9451, 0x0078, 0x9381, 0x6013, - 0x1900, 0x6007, 0x0009, 0x0078, 0x94a3, 0x1078, 0x29bb, 0x00c0, - 0x9674, 0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x9677, 0x00c0, - 0x9381, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x007c, - 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x0078, 0x94a7, - 0x6007, 0x0005, 0x0078, 0x94aa, 0x1078, 0xa42c, 0x00c0, 0x9674, - 0x1078, 0x29bb, 0x00c0, 0x9674, 0x1078, 0x9677, 0x00c0, 0x9381, - 0x6007, 0x0020, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x007c, 0x1078, - 0x29bb, 0x00c0, 0x9674, 0x6007, 0x0023, 0x6003, 0x0001, 0x1078, - 0x5dd7, 0x007c, 0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb, - 0x00c0, 0x9674, 0x1078, 0x9677, 0x00c0, 0x9381, 0x017e, 0x027e, - 0x2011, 0xac90, 0x2214, 0x2c08, 0xa006, 0x1078, 0xa1f6, 0x00c0, - 0x94f9, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xac89, - 0x2214, 0xa296, 0xffff, 0x00c0, 0x9503, 0x6007, 0x0025, 0x0078, - 0x9503, 0x6004, 0xa086, 0x0024, 0x00c0, 0x9500, 0x1078, 0x772d, - 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x027f, - 0x017f, 0x007c, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x6106, 0x1078, - 0x9697, 0x6007, 0x002b, 0x0078, 0x94a3, 0x6007, 0x002c, 0x0078, - 0x94a3, 0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb, 0x00c0, - 0x9674, 0x1078, 0x9677, 0x00c0, 0x9381, 0x6106, 0x1078, 0x969c, - 0x00c0, 0x952e, 0x6007, 0x002e, 0x0078, 0x94a3, 0x6007, 0x002f, - 0x0078, 0x94a3, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x0e7e, 0x0d7e, - 0x0c7e, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086, - 0x0006, 0x0040, 0x954f, 0xa184, 0xff00, 0x8007, 0xa086, 0x0006, - 0x0040, 0x954f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0078, 0x94a8, 0x2001, - 0xa772, 0x2004, 0xd0e4, 0x0040, 0x95bb, 0x2071, 0xac8c, 0x7010, - 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xa753, 0x2004, - 0xd0a4, 0x0040, 0x956d, 0x6018, 0x2068, 0x6810, 0xa106, 0x00c0, - 0x956d, 0x6814, 0xa206, 0x0040, 0x9591, 0x2001, 0xa753, 0x2004, - 0xd0ac, 0x00c0, 0x95af, 0x2069, 0xa700, 0x6870, 0xa206, 0x00c0, - 0x95af, 0x686c, 0xa106, 0x00c0, 0x95af, 0x7210, 0x1078, 0x8d02, - 0x0040, 0x95b5, 0x1078, 0xa29e, 0x0040, 0x95b5, 0x622a, 0x6007, - 0x0036, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x0c7f, 0x0d7f, 0x0e7f, - 0x007c, 0x7214, 0xa286, 0xffff, 0x0040, 0x95a3, 0x1078, 0x8d02, - 0x0040, 0x95b5, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x00c0, - 0x95b5, 0x0078, 0x957e, 0x7210, 0x2c08, 0xa085, 0x0001, 0x1078, - 0xa1f6, 0x2c10, 0x2160, 0x0040, 0x95b5, 0x0078, 0x957e, 0x6007, - 0x0037, 0x6013, 0x1500, 0x0078, 0x9589, 0x6007, 0x0037, 0x6013, - 0x1700, 0x0078, 0x9589, 0x6007, 0x0012, 0x0078, 0x9589, 0x1078, - 0x29bb, 0x00c0, 0x9674, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, - 0xff00, 0x8007, 0xa086, 0x0006, 0x00c0, 0x94a8, 0x0e7e, 0x0d7e, - 0x0c7e, 0x2001, 0xa772, 0x2004, 0xd0e4, 0x0040, 0x9631, 0x2069, - 0xa700, 0x2071, 0xac8c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, - 0xffff, 0x00c0, 0x95ee, 0x7208, 0x0c7e, 0x2c08, 0xa085, 0x0001, - 0x1078, 0xa1f6, 0x2c10, 0x0c7f, 0x0040, 0x9625, 0x1078, 0x8d02, - 0x0040, 0x9625, 0x0c7e, 0x027e, 0x2260, 0x1078, 0x8a03, 0x027f, - 0x0c7f, 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186, 0x0001, 0x0040, - 0x960f, 0xa186, 0x0005, 0x0040, 0x9609, 0xa186, 0x0007, 0x00c0, - 0x9619, 0xa280, 0x0004, 0x2004, 0xa005, 0x0040, 0x9619, 0x057e, - 0x7510, 0x7614, 0x1078, 0xa2b3, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, - 0x007c, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, - 0x0001, 0x1078, 0x5d8a, 0x0078, 0x9615, 0x6007, 0x003b, 0x602b, - 0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x0078, - 0x9615, 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0078, - 0x9589, 0x0e7e, 0x027e, 0x1078, 0x4967, 0x0040, 0x966e, 0x1078, - 0x4957, 0x1078, 0xa4b9, 0x00c0, 0x966c, 0x2071, 0xa700, 0x70cc, - 0xc085, 0x70ce, 0x0f7e, 0x2079, 0x0100, 0x7298, 0xa284, 0x00ff, - 0x706e, 0x78e6, 0xa284, 0xff00, 0x7270, 0xa205, 0x7072, 0x78ea, - 0x0f7f, 0x70d7, 0x0000, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, - 0x9665, 0x2011, 0xa9ca, 0x2013, 0x07d0, 0xd0ac, 0x00c0, 0x966e, - 0x1078, 0x2677, 0x0078, 0x966e, 0x1078, 0xa4e9, 0x027f, 0x0e7f, - 0x1078, 0x772d, 0x0078, 0x94a7, 0x1078, 0x772d, 0x007c, 0x0d7e, - 0x067e, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, - 0x0006, 0x0040, 0x9694, 0xa686, 0x0004, 0x0040, 0x9694, 0x6e04, - 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0040, 0x9694, 0xa686, 0x0004, - 0x0040, 0x9694, 0xa085, 0x0001, 0x067f, 0x0d7f, 0x007c, 0x0d7e, - 0x1078, 0x96cb, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x96da, 0x00c0, - 0x96c4, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, 0x00ff, 0xa115, - 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0040, 0x96b2, 0x2009, 0x0001, - 0x0078, 0x96c0, 0xd1ec, 0x0040, 0x96c4, 0x6920, 0xa18c, 0x00ff, - 0x6824, 0x1078, 0x254d, 0x00c0, 0x96c4, 0x2110, 0x2009, 0x0000, - 0x1078, 0x28c8, 0x0078, 0x96c8, 0xa085, 0x0001, 0x0078, 0x96c9, - 0xa006, 0x0d7f, 0x007c, 0x2069, 0xac8d, 0x6800, 0xa082, 0x0010, - 0x00c8, 0x96d8, 0x6013, 0x0000, 0xa085, 0x0001, 0x0078, 0x96d9, - 0xa006, 0x007c, 0x6013, 0x0000, 0x2069, 0xac8c, 0x6808, 0xa084, - 0xff00, 0xa086, 0x0800, 0x00c0, 0x96ee, 0x6800, 0xa084, 0x00ff, - 0xa08e, 0x0014, 0x0040, 0x96ee, 0xa08e, 0x0010, 0x007c, 0x6004, - 0xa0b2, 0x0044, 0x10c8, 0x1332, 0xa1b6, 0x0013, 0x00c0, 0x96fb, - 0x2008, 0x0079, 0x970e, 0xa1b6, 0x0027, 0x0040, 0x9703, 0xa1b6, - 0x0014, 0x10c0, 0x1332, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, - 0x61cd, 0x1078, 0x8ed6, 0x1078, 0x62d1, 0x007c, 0x974e, 0x9750, - 0x974e, 0x974e, 0x974e, 0x9750, 0x975c, 0x97e6, 0x97a9, 0x97e6, - 0x97bd, 0x97e6, 0x975c, 0x97e6, 0x97de, 0x97e6, 0x97de, 0x97e6, - 0x97e6, 0x974e, 0x974e, 0x974e, 0x974e, 0x974e, 0x974e, 0x974e, - 0x974e, 0x974e, 0x974e, 0x974e, 0x9750, 0x974e, 0x97e6, 0x974e, - 0x974e, 0x97e6, 0x974e, 0x97e6, 0x97e6, 0x974e, 0x974e, 0x974e, - 0x974e, 0x97e6, 0x97e6, 0x974e, 0x97e6, 0x97e6, 0x974e, 0x974e, - 0x974e, 0x974e, 0x974e, 0x9750, 0x97e6, 0x97e6, 0x974e, 0x974e, - 0x97e6, 0x97e6, 0x974e, 0x974e, 0x974e, 0x974e, 0x1078, 0x1332, - 0x1078, 0x61cd, 0x2001, 0xa9a2, 0x2004, 0x6016, 0x6003, 0x0002, - 0x1078, 0x62d1, 0x0078, 0x97ec, 0x0f7e, 0x2079, 0xa752, 0x7804, - 0x0f7f, 0xd0ac, 0x00c0, 0x97e6, 0x2001, 0x0000, 0x1078, 0x44ee, - 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0040, 0x97e6, - 0x0c7e, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x00c0, 0x9780, 0x6010, - 0xa005, 0x0040, 0x9780, 0x0c7f, 0x1078, 0x3699, 0x0078, 0x97e6, - 0x0c7f, 0x2001, 0xa700, 0x2004, 0xa086, 0x0002, 0x00c0, 0x978f, - 0x0f7e, 0x2079, 0xa700, 0x7890, 0x8000, 0x7892, 0x0f7f, 0x2001, - 0x0002, 0x1078, 0x4502, 0x1078, 0x61cd, 0x601f, 0x0001, 0x6003, - 0x0001, 0x6007, 0x0002, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0c7e, - 0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x5a52, 0x0c7f, 0x0078, - 0x97ec, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0006, 0x0040, 0x97e6, 0xa686, 0x0004, 0x0040, - 0x97e6, 0x2001, 0x0004, 0x0078, 0x97e4, 0x2001, 0xa700, 0x2004, - 0xa086, 0x0003, 0x00c0, 0x97c6, 0x1078, 0x3699, 0x2001, 0x0006, - 0x1078, 0x97ed, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, - 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x97e6, 0x2001, 0x0006, - 0x0078, 0x97e4, 0x2001, 0x0004, 0x0078, 0x97e4, 0x2001, 0x0006, - 0x1078, 0x97ed, 0x0078, 0x97e6, 0x1078, 0x4535, 0x1078, 0x61cd, - 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, 0x017e, 0x0d7e, 0x6118, - 0x2168, 0x6900, 0xd184, 0x0040, 0x9808, 0x6104, 0xa18e, 0x000a, - 0x00c0, 0x9800, 0x699c, 0xd1a4, 0x00c0, 0x9800, 0x2001, 0x0007, - 0x1078, 0x4502, 0x2001, 0x0000, 0x1078, 0x44ee, 0x1078, 0x28a6, - 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, - 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1332, 0xa1b6, - 0x0015, 0x00c0, 0x981f, 0x1079, 0x9826, 0x0078, 0x9825, 0xa1b6, - 0x0016, 0x10c0, 0x1332, 0x1079, 0x9832, 0x007c, 0x7d4e, 0x7d4e, - 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x9887, 0x983e, 0x7d4e, 0x7d4e, - 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, - 0x9887, 0x988f, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x0f7e, 0x2079, - 0xa752, 0x7804, 0xd0ac, 0x00c0, 0x9865, 0x6018, 0xa07d, 0x0040, - 0x9865, 0x7800, 0xd0f4, 0x00c0, 0x9851, 0x7810, 0xa005, 0x00c0, - 0x9865, 0x2001, 0x0000, 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, - 0x4502, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, - 0x5dd7, 0x1078, 0x62d1, 0x0078, 0x9885, 0x2011, 0xac83, 0x2204, - 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x9885, 0x0c7e, 0x1078, - 0x45c4, 0x0040, 0x9878, 0x0c7f, 0x1078, 0x772d, 0x0078, 0x9885, - 0x6010, 0x007e, 0x6014, 0x007e, 0x1078, 0x42f8, 0x007f, 0x6016, - 0x007f, 0x6012, 0x0c7f, 0x1078, 0x772d, 0x0f7f, 0x007c, 0x6604, - 0xa6b6, 0x001e, 0x00c0, 0x988e, 0x1078, 0x772d, 0x007c, 0x1078, - 0x7f8e, 0x00c0, 0x989b, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, - 0x5dd7, 0x0078, 0x989d, 0x1078, 0x772d, 0x007c, 0x6004, 0xa08a, - 0x0044, 0x10c8, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6, 0x1078, - 0x62d1, 0x007c, 0xa182, 0x0040, 0x0079, 0x98ae, 0x98c1, 0x98c1, - 0x98c1, 0x98c1, 0x98c3, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, - 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, - 0x98c1, 0x1078, 0x1332, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e, - 0x027e, 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, 0x0040, 0x98d4, - 0x2021, 0x0000, 0x1078, 0xa482, 0x6106, 0x2071, 0xac80, 0x7444, - 0xa4a4, 0xff00, 0x0040, 0x992b, 0xa486, 0x2000, 0x00c0, 0x98e6, - 0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x5bf1, 0x1078, 0x138b, - 0x1040, 0x1332, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, - 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2, - 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x017e, 0xa084, - 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x4a73, - 0x017f, 0xa486, 0x2000, 0x00c0, 0x9913, 0x2019, 0x0017, 0x1078, - 0xa1a5, 0x0078, 0x998d, 0xa486, 0x0400, 0x00c0, 0x991d, 0x2019, - 0x0002, 0x1078, 0xa156, 0x0078, 0x998d, 0xa486, 0x0200, 0x00c0, - 0x9923, 0x1078, 0xa13b, 0xa486, 0x1000, 0x00c0, 0x9929, 0x1078, - 0xa18a, 0x0078, 0x998d, 0x2069, 0xaa33, 0x6a00, 0xd284, 0x0040, - 0x99f7, 0xa284, 0x0300, 0x00c0, 0x99ef, 0x6804, 0xa005, 0x0040, - 0x99d5, 0x2d78, 0x6003, 0x0007, 0x1078, 0x1370, 0x0040, 0x9994, - 0x7800, 0xd08c, 0x00c0, 0x9947, 0x7804, 0x8001, 0x7806, 0x6013, - 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, - 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, - 0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, - 0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, - 0x0002, 0x00c0, 0x996f, 0x684f, 0x0040, 0x0078, 0x9979, 0xa286, - 0x0001, 0x00c0, 0x9977, 0x684f, 0x0080, 0x0078, 0x9979, 0x684f, - 0x0000, 0x20a9, 0x000a, 0x2001, 0xac90, 0xad90, 0x0015, 0x200c, - 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x997f, 0x200c, 0x6982, - 0x8000, 0x200c, 0x697e, 0x1078, 0x4a73, 0x027f, 0x047f, 0x157f, - 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x2001, 0xa70e, 0x2004, 0xd084, - 0x0040, 0x999e, 0x1078, 0x138b, 0x00c0, 0x9940, 0x6013, 0x0100, - 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, - 0x0078, 0x998d, 0x2069, 0xac92, 0x2d04, 0xa084, 0xff00, 0xa086, - 0x1200, 0x00c0, 0x99c9, 0x2069, 0xac80, 0x686c, 0xa084, 0x00ff, - 0x017e, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, - 0x0001, 0x6007, 0x0043, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, - 0x998d, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, - 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x998d, 0x2001, 0xa70d, 0x2004, - 0xd0ec, 0x0040, 0x99df, 0x2011, 0x8049, 0x1078, 0x361b, 0x6013, - 0x0300, 0x0078, 0x99e5, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, - 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x998d, 0x6013, - 0x0500, 0x0078, 0x99e5, 0x6013, 0x0600, 0x0078, 0x99aa, 0x6013, - 0x0200, 0x0078, 0x99aa, 0xa186, 0x0013, 0x00c0, 0x9a0d, 0x6004, - 0xa08a, 0x0040, 0x1048, 0x1332, 0xa08a, 0x0053, 0x10c8, 0x1332, - 0xa082, 0x0040, 0x2008, 0x0079, 0x9a92, 0xa186, 0x0051, 0x0040, - 0x9a1a, 0xa186, 0x0047, 0x00c0, 0x9a33, 0x6004, 0xa086, 0x0041, - 0x0040, 0x9a41, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040, 0x9a41, - 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078, 0x5c56, - 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002, 0x00c0, - 0x9a41, 0x0078, 0x9ad7, 0xa186, 0x0027, 0x0040, 0x9a3b, 0xa186, - 0x0014, 0x10c0, 0x1332, 0x6004, 0xa082, 0x0040, 0x2008, 0x0079, - 0x9a44, 0x1078, 0x7773, 0x007c, 0x9a57, 0x9a59, 0x9a59, 0x9a81, - 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, - 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x1078, - 0x1332, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x037e, 0x0d7e, 0x6010, - 0xa06d, 0x0040, 0x9a7e, 0xad84, 0xf000, 0x0040, 0x9a7e, 0x6003, - 0x0002, 0x6018, 0x2004, 0xd0bc, 0x00c0, 0x9a7e, 0x2019, 0x0004, - 0x1078, 0xa1da, 0x6013, 0x0000, 0x6014, 0xa005, 0x00c0, 0x9a7c, - 0x2001, 0xa9a3, 0x2004, 0x6016, 0x6003, 0x0007, 0x0d7f, 0x037f, - 0x007c, 0x0d7e, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x1078, 0x8d16, - 0x0040, 0x9a8e, 0x6010, 0x2068, 0x1078, 0x13a4, 0x1078, 0x8ed6, - 0x0d7f, 0x007c, 0x9aa5, 0x9ac4, 0x9aae, 0x9ad1, 0x9aa5, 0x9aa5, - 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, - 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x1078, 0x1332, 0x6010, - 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x1078, 0x61cd, - 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0040, 0x9abf, 0x6003, - 0x0007, 0x2009, 0x0043, 0x1078, 0x775c, 0x0078, 0x9ac1, 0x6003, - 0x0002, 0x1078, 0x62d1, 0x007c, 0x1078, 0x61cd, 0x1078, 0xa433, - 0x00c0, 0x9ace, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x1078, 0x62d1, - 0x007c, 0x1078, 0x61cd, 0x2009, 0x0041, 0x0078, 0x9c2e, 0xa182, - 0x0040, 0x0079, 0x9adb, 0x9aee, 0x9af0, 0x9aee, 0x9aee, 0x9aee, - 0x9aee, 0x9aee, 0x9af1, 0x9aee, 0x9aee, 0x9aee, 0x9aee, 0x9aee, - 0x9aee, 0x9aee, 0x9aee, 0x9aee, 0x9afc, 0x9aee, 0x1078, 0x1332, - 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, - 0x2c10, 0x1078, 0x15fa, 0x007c, 0x0d7e, 0x1078, 0x5bc1, 0x0d7f, - 0x1078, 0xa4a5, 0x1078, 0x772d, 0x007c, 0xa182, 0x0040, 0x0079, - 0x9b09, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, - 0x9b1e, 0x9b1c, 0x9b21, 0x9b4c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, - 0x9b4c, 0x9b1c, 0x9b1c, 0x9b1c, 0x1078, 0x1332, 0x1078, 0x7773, - 0x007c, 0x1078, 0x627a, 0x1078, 0x639b, 0x6010, 0x0d7e, 0x2068, - 0x684c, 0xd0fc, 0x0040, 0x9b37, 0xa08c, 0x0003, 0xa18e, 0x0002, - 0x0040, 0x9b3f, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x9c2e, 0x6003, - 0x0007, 0x6017, 0x0000, 0x1078, 0x5bc1, 0x0d7f, 0x007c, 0x1078, - 0xa433, 0x0040, 0x9b45, 0x0d7f, 0x007c, 0x1078, 0x5bc1, 0x1078, - 0x772d, 0x0d7f, 0x0078, 0x9b3e, 0x037e, 0x1078, 0x627a, 0x1078, - 0x639b, 0x6010, 0x0d7e, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0040, - 0x9b6c, 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x9b68, - 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a, - 0x6003, 0x0002, 0x0078, 0x9b7d, 0x2019, 0x0004, 0x1078, 0xa1da, - 0x6014, 0xa005, 0x00c0, 0x9b79, 0x2001, 0xa9a3, 0x2004, 0x8003, - 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, 0x0d7f, 0x037f, 0x007c, - 0xa186, 0x0013, 0x00c0, 0x9b8e, 0x6004, 0xa086, 0x0042, 0x10c0, - 0x1332, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x007c, 0xa186, 0x0027, - 0x0040, 0x9b96, 0xa186, 0x0014, 0x00c0, 0x9ba6, 0x6004, 0xa086, - 0x0042, 0x10c0, 0x1332, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, - 0x61cd, 0x1078, 0x8ed6, 0x1078, 0x62d1, 0x007c, 0xa182, 0x0040, - 0x0079, 0x9baa, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, - 0x9bbd, 0x9bbf, 0x9bcb, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, - 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x1078, 0x1332, 0x037e, - 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15fa, - 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e, 0x2068, 0x6810, 0x6a14, - 0x6118, 0x210c, 0xd1bc, 0x0040, 0x9bea, 0x6124, 0xd1f4, 0x00c0, - 0x9bea, 0x007e, 0x047e, 0x057e, 0x6c7c, 0xa422, 0x6d80, 0x2200, - 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, 0x652a, 0x057f, - 0x047f, 0x007f, 0xa20d, 0x00c0, 0x9bfe, 0x684c, 0xd0fc, 0x0040, - 0x9bf6, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x9c2e, 0x6003, 0x0007, - 0x6017, 0x0000, 0x1078, 0x5bc1, 0x0d7f, 0x007c, 0x007e, 0x0f7e, - 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x007f, 0x0040, 0x9c0b, 0x6003, - 0x0002, 0x0d7f, 0x007c, 0x2009, 0xa70d, 0x210c, 0xd19c, 0x0040, - 0x9c15, 0x6003, 0x0007, 0x0078, 0x9c17, 0x6003, 0x0006, 0x1078, - 0x9c1d, 0x1078, 0x5bc3, 0x0d7f, 0x007c, 0xd2fc, 0x0040, 0x9c29, - 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0078, - 0x9c2b, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x007c, 0xa182, 0x0040, - 0x0048, 0x9c34, 0x0079, 0x9c41, 0xa186, 0x0013, 0x0040, 0x9c3c, - 0xa186, 0x0014, 0x10c0, 0x1332, 0x6024, 0xd0dc, 0x1040, 0x1332, - 0x007c, 0x9c54, 0x9c5b, 0x9c67, 0x9c73, 0x9c54, 0x9c54, 0x9c54, - 0x9c82, 0x9c54, 0x9c56, 0x9c56, 0x9c54, 0x9c54, 0x9c54, 0x9c54, - 0x9c54, 0x9c54, 0x9c54, 0x9c54, 0x1078, 0x1332, 0x6024, 0xd0dc, - 0x1040, 0x1332, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, - 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x6003, - 0x0001, 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, 0x8000, 0x1078, - 0x62d1, 0x127f, 0x007c, 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, - 0x1cf0, 0x127e, 0x2091, 0x8000, 0x1078, 0x5df6, 0x1078, 0x639b, - 0x127f, 0x007c, 0xa016, 0x1078, 0x15fa, 0x007c, 0x127e, 0x2091, - 0x8000, 0x037e, 0x0d7e, 0xa182, 0x0040, 0x1079, 0x9c93, 0x0d7f, - 0x037f, 0x127f, 0x007c, 0x9ca3, 0x9ca5, 0x9cba, 0x9cd9, 0x9ca3, - 0x9ca3, 0x9ca3, 0x9cf1, 0x9ca3, 0x9ca3, 0x9ca3, 0x9ca3, 0x9ca3, - 0x9ca3, 0x9ca3, 0x9ca3, 0x1078, 0x1332, 0x6010, 0x2068, 0x684c, - 0xd0fc, 0x0040, 0x9ccf, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, - 0x9ccf, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, 0x1078, 0x62d1, - 0x0078, 0x9cf4, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9ccf, - 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, 0x9ccf, 0x6003, 0x0001, - 0x6106, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x9cf4, 0x6013, - 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, 0x1078, 0xa1da, 0x0078, - 0x9cf4, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9ccf, 0xa09c, - 0x0003, 0xa39e, 0x0003, 0x0040, 0x9ccf, 0x6003, 0x0003, 0x6106, - 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x5df6, 0x1078, 0x639b, 0x0078, - 0x9cf4, 0xa016, 0x1078, 0x15fa, 0x007c, 0x1078, 0x61cd, 0x6110, - 0x81ff, 0x0040, 0x9d06, 0x0d7e, 0x2168, 0x1078, 0xa4f2, 0x037e, - 0x2019, 0x0029, 0x1078, 0xa1da, 0x037f, 0x0d7f, 0x1078, 0x8ed6, - 0x1078, 0x62d1, 0x007c, 0x1078, 0x627a, 0x6110, 0x81ff, 0x0040, - 0x9d1c, 0x0d7e, 0x2168, 0x1078, 0xa4f2, 0x037e, 0x2019, 0x0029, - 0x1078, 0xa1da, 0x037f, 0x0d7f, 0x1078, 0x8ed6, 0x1078, 0x639b, - 0x007c, 0xa182, 0x0085, 0x0079, 0x9d25, 0x9d2e, 0x9d2c, 0x9d2c, - 0x9d3a, 0x9d2c, 0x9d2c, 0x9d2c, 0x1078, 0x1332, 0x6003, 0x000b, - 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, - 0x127f, 0x007c, 0x027e, 0x0e7e, 0x1078, 0xa42c, 0x0040, 0x9d44, - 0x1078, 0x772d, 0x0078, 0x9d60, 0x2071, 0xac80, 0x7224, 0x6212, - 0x7220, 0x1078, 0xa079, 0x0040, 0x9d51, 0x6007, 0x0086, 0x0078, - 0x9d5a, 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x00c0, 0x9d5a, - 0x6007, 0x0086, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, - 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x9d74, 0x6004, - 0xa08a, 0x0085, 0x1048, 0x1332, 0xa08a, 0x008c, 0x10c8, 0x1332, - 0xa082, 0x0085, 0x0079, 0x9d8b, 0xa186, 0x0027, 0x0040, 0x9d80, - 0xa186, 0x0014, 0x0040, 0x9d80, 0x1078, 0x7773, 0x0078, 0x9d8a, - 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, 0x61cd, 0x1078, 0x8ed6, - 0x1078, 0x62d1, 0x007c, 0x9d92, 0x9d94, 0x9d94, 0x9d92, 0x9d92, - 0x9d92, 0x9d92, 0x1078, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6, - 0x1078, 0x62d1, 0x007c, 0xa182, 0x0085, 0x1048, 0x1332, 0xa182, - 0x008c, 0x10c8, 0x1332, 0xa182, 0x0085, 0x0079, 0x9da7, 0x9dae, - 0x9dae, 0x9dae, 0x9db0, 0x9dae, 0x9dae, 0x9dae, 0x1078, 0x1332, - 0x007c, 0xa186, 0x0013, 0x0040, 0x9dc1, 0xa186, 0x0014, 0x0040, - 0x9dc1, 0xa186, 0x0027, 0x0040, 0x9dc1, 0x1078, 0x7773, 0x0078, - 0x9dc7, 0x1078, 0x61cd, 0x1078, 0x8ed6, 0x1078, 0x62d1, 0x007c, - 0x037e, 0x1078, 0xa4a5, 0x603f, 0x0000, 0x2019, 0x000b, 0x1078, - 0x9dd7, 0x601f, 0x0006, 0x6003, 0x0007, 0x037f, 0x007c, 0x127e, - 0x037e, 0x2091, 0x8000, 0x087e, 0x2c40, 0x097e, 0x2049, 0x0000, - 0x1078, 0x7246, 0x097f, 0x087f, 0x00c0, 0x9e12, 0x077e, 0x2c38, - 0x1078, 0x72f3, 0x077f, 0x00c0, 0x9e12, 0x6000, 0xa086, 0x0000, - 0x0040, 0x9e12, 0x601c, 0xa086, 0x0007, 0x0040, 0x9e12, 0x0d7e, - 0x6000, 0xa086, 0x0004, 0x00c0, 0x9e03, 0x1078, 0xa4a5, 0x601f, - 0x0007, 0x1078, 0x1757, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, - 0x9e0b, 0x1078, 0xa1da, 0x0d7f, 0x6013, 0x0000, 0x1078, 0xa4a5, - 0x601f, 0x0007, 0x037f, 0x127f, 0x007c, 0x0f7e, 0x0c7e, 0x037e, - 0x157e, 0x2079, 0xac80, 0x7938, 0x783c, 0x1078, 0x254d, 0x00c0, - 0x9e59, 0x017e, 0x0c7e, 0x1078, 0x45c4, 0x00c0, 0x9e59, 0x017f, - 0x027f, 0x027e, 0x017e, 0x2019, 0x0029, 0x1078, 0x73d0, 0x1078, - 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x077f, 0x017f, - 0x077e, 0x2039, 0x0000, 0x1078, 0x9f9b, 0x077f, 0x1078, 0x47e9, - 0x027e, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, - 0x9e4d, 0xa286, 0x0004, 0x00c0, 0x9e50, 0x62a0, 0x1078, 0x2942, - 0x027f, 0x017f, 0x1078, 0x42f8, 0x6612, 0x6516, 0xa006, 0x0078, - 0x9e5b, 0x0c7f, 0x017f, 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, - 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x2009, 0xa720, 0x2104, 0xa086, - 0x0074, 0x00c0, 0x9ec3, 0x2069, 0xac8e, 0x690c, 0xa182, 0x0100, - 0x0048, 0x9eb3, 0x6908, 0xa184, 0x8000, 0x0040, 0x9ebf, 0x6018, - 0x2070, 0x7010, 0xa084, 0x00ff, 0x0040, 0x9e82, 0x7000, 0xd0f4, - 0x0040, 0x9e86, 0xa184, 0x0800, 0x0040, 0x9ebf, 0x6910, 0xa18a, - 0x0001, 0x0048, 0x9eb7, 0x6914, 0x2069, 0xacae, 0x6904, 0x81ff, - 0x00c0, 0x9eab, 0x690c, 0xa182, 0x0100, 0x0048, 0x9eb3, 0x6908, - 0x81ff, 0x00c0, 0x9eaf, 0x6910, 0xa18a, 0x0001, 0x0048, 0x9eb7, - 0x6918, 0xa18a, 0x0001, 0x0048, 0x9ebf, 0x0078, 0x9ec9, 0x6013, - 0x0100, 0x0078, 0x9ec5, 0x6013, 0x0300, 0x0078, 0x9ec5, 0x6013, - 0x0500, 0x0078, 0x9ec5, 0x6013, 0x0700, 0x0078, 0x9ec5, 0x6013, - 0x0900, 0x0078, 0x9ec5, 0x6013, 0x0b00, 0x0078, 0x9ec5, 0x6013, - 0x0f00, 0x0078, 0x9ec5, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, - 0x9eca, 0xa006, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, - 0x0d7e, 0x027e, 0x037e, 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, - 0x00ff, 0xa286, 0x0006, 0x0040, 0x9ef3, 0xa286, 0x0004, 0x0040, - 0x9ef3, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x9ef3, - 0xa286, 0x0004, 0x0040, 0x9ef3, 0x0c7e, 0x2d60, 0x1078, 0x45d6, - 0x0c7f, 0x0078, 0x9f2e, 0x2011, 0xac96, 0xad98, 0x000a, 0x20a9, - 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f2f, 0x2011, 0xac9a, 0xad98, - 0x0006, 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f2f, 0x047e, - 0x017e, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xa753, - 0x210c, 0xd1a4, 0x0040, 0x9f1b, 0x2009, 0x0029, 0x1078, 0xa22d, - 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, - 0x2039, 0x0000, 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f9b, 0x077f, - 0x2001, 0x0007, 0x1078, 0x4535, 0x017f, 0x047f, 0xa006, 0x157f, - 0x037f, 0x027f, 0x0d7f, 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0xac8e, - 0x6800, 0xa086, 0x0800, 0x0040, 0x9f41, 0x6013, 0x0000, 0x0078, - 0x9f42, 0xa006, 0x0d7f, 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, - 0x037e, 0x157e, 0x2079, 0xac8c, 0x7930, 0x7834, 0x1078, 0x254d, - 0x00c0, 0x9f68, 0x1078, 0x45c4, 0x00c0, 0x9f68, 0x2011, 0xac90, - 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f68, - 0x2011, 0xac94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x80de, - 0x157f, 0x037f, 0x027f, 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, - 0x007e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2011, 0xac83, 0x2204, - 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x9f94, 0x1078, 0x45c4, - 0x00c0, 0x9f94, 0x2011, 0xac96, 0xac98, 0x000a, 0x20a9, 0x0004, - 0x1078, 0x80de, 0x00c0, 0x9f94, 0x2011, 0xac9a, 0xac98, 0x0006, - 0x20a9, 0x0004, 0x1078, 0x80de, 0x157f, 0x037f, 0x027f, 0x017f, - 0x007f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x087e, 0x077e, 0x067e, - 0x057e, 0x047e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, 0x2029, - 0xa9ba, 0x252c, 0x2021, 0xa9c0, 0x2424, 0x2061, 0xae00, 0x2071, - 0xa700, 0x7648, 0x7064, 0x81ff, 0x0040, 0x9fc2, 0x007e, 0xa186, - 0xaab3, 0x007f, 0x0040, 0x9fc2, 0x8001, 0xa602, 0x00c8, 0xa02c, - 0x0078, 0x9fc5, 0xa606, 0x0040, 0xa02c, 0x2100, 0xac06, 0x0040, - 0xa022, 0x1078, 0xa252, 0x0040, 0xa022, 0x671c, 0xa786, 0x0001, - 0x0040, 0xa047, 0xa786, 0x0004, 0x0040, 0xa047, 0xa786, 0x0007, - 0x0040, 0xa022, 0x2500, 0xac06, 0x0040, 0xa022, 0x2400, 0xac06, - 0x0040, 0xa022, 0x1078, 0xa266, 0x00c0, 0xa022, 0x88ff, 0x0040, - 0x9fed, 0x6020, 0xa906, 0x00c0, 0xa022, 0x0d7e, 0x6000, 0xa086, - 0x0004, 0x00c0, 0x9ff7, 0x017e, 0x1078, 0x1757, 0x017f, 0xa786, - 0x0008, 0x00c0, 0xa006, 0x1078, 0x8f10, 0x00c0, 0xa006, 0x1078, - 0x7c83, 0x0d7f, 0x1078, 0x8ed6, 0x0078, 0xa022, 0x6010, 0x2068, - 0x1078, 0x8d16, 0x0040, 0xa01f, 0xa786, 0x0003, 0x00c0, 0xa036, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0xa4f2, 0x017e, - 0x1078, 0x8f8d, 0x1078, 0x4a73, 0x017f, 0x1078, 0x8ec9, 0x0d7f, - 0x1078, 0x8ed6, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, 0xac02, - 0x00c8, 0xa02c, 0x0078, 0x9faf, 0x127f, 0x027f, 0x047f, 0x057f, - 0x067f, 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006, - 0x00c0, 0xa010, 0xa386, 0x0005, 0x0040, 0xa044, 0x1078, 0xa4f2, - 0x1078, 0xa1da, 0x0078, 0xa01f, 0x0d7f, 0x0078, 0xa022, 0x1078, - 0xa266, 0x00c0, 0xa022, 0x81ff, 0x0040, 0xa022, 0xa180, 0x0001, - 0x2004, 0xa086, 0x0018, 0x0040, 0xa05c, 0xa180, 0x0001, 0x2004, - 0xa086, 0x002d, 0x00c0, 0xa022, 0x6000, 0xa086, 0x0002, 0x00c0, - 0xa022, 0x1078, 0x8efc, 0x0040, 0xa06d, 0x1078, 0x8f10, 0x00c0, - 0xa022, 0x1078, 0x7c83, 0x0078, 0xa075, 0x1078, 0x28a6, 0x1078, - 0x8f10, 0x00c0, 0xa075, 0x1078, 0x7c83, 0x1078, 0x8ed6, 0x0078, - 0xa022, 0x0c7e, 0x0e7e, 0x017e, 0x2c08, 0x2170, 0xa006, 0x1078, - 0xa1f6, 0x017f, 0x0040, 0xa089, 0x601c, 0xa084, 0x000f, 0x1079, - 0xa08c, 0x0e7f, 0x0c7f, 0x007c, 0xa094, 0xa094, 0xa094, 0xa094, - 0xa094, 0xa094, 0xa096, 0xa094, 0xa006, 0x007c, 0x047e, 0x017e, - 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, - 0x2009, 0x0020, 0x1078, 0xa22d, 0x017f, 0x047f, 0x037e, 0x2019, - 0x0002, 0x1078, 0x9dd7, 0x037f, 0xa085, 0x0001, 0x007c, 0x2001, - 0x0001, 0x1078, 0x44ee, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, - 0x0004, 0x2019, 0xa705, 0x2011, 0xac96, 0x1078, 0x80de, 0x037f, - 0x027f, 0x017f, 0x157f, 0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, - 0x087e, 0x077e, 0x067e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, - 0x2061, 0xae00, 0x2079, 0x0001, 0x8fff, 0x0040, 0xa12d, 0x2071, - 0xa700, 0x7648, 0x7064, 0x8001, 0xa602, 0x00c8, 0xa12d, 0x88ff, - 0x0040, 0xa0e8, 0x2800, 0xac06, 0x00c0, 0xa123, 0x2079, 0x0000, - 0x1078, 0xa252, 0x0040, 0xa123, 0x2400, 0xac06, 0x0040, 0xa123, - 0x671c, 0xa786, 0x0006, 0x00c0, 0xa123, 0xa786, 0x0007, 0x0040, - 0xa123, 0x88ff, 0x00c0, 0xa107, 0x6018, 0xa206, 0x00c0, 0xa123, - 0x85ff, 0x0040, 0xa107, 0x6020, 0xa106, 0x00c0, 0xa123, 0x0d7e, - 0x6000, 0xa086, 0x0004, 0x00c0, 0xa113, 0x1078, 0xa4a5, 0x601f, - 0x0007, 0x1078, 0x1757, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, - 0xa11d, 0x047e, 0x1078, 0xa1da, 0x047f, 0x0d7f, 0x1078, 0x8ed6, - 0x88ff, 0x00c0, 0xa137, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, - 0xac02, 0x00c8, 0xa12d, 0x0078, 0xa0d4, 0xa006, 0x127f, 0x027f, - 0x067f, 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, - 0x0001, 0x0078, 0xa12e, 0x077e, 0x057e, 0x087e, 0x2041, 0x0000, - 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, 0x6218, 0x097e, 0x2049, - 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, - 0x72f3, 0x1078, 0xa0c5, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, - 0x057e, 0x077e, 0x0c7e, 0x157e, 0x2c20, 0x2128, 0x20a9, 0x007f, - 0x2009, 0x0000, 0x017e, 0x037e, 0x1078, 0x45c4, 0x00c0, 0xa17e, - 0x2c10, 0x057e, 0x087e, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, - 0x097e, 0x2049, 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, 0x2039, - 0x0000, 0x1078, 0x72f3, 0x1078, 0xa0c5, 0x057f, 0x037f, 0x017f, - 0x8108, 0x00f0, 0xa162, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, - 0x027f, 0x007c, 0x077e, 0x057e, 0x6218, 0x087e, 0x2041, 0x0000, - 0x2029, 0x0001, 0x2019, 0x0048, 0x097e, 0x2049, 0x0000, 0x1078, - 0x7246, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, 0x72f3, 0x2c20, - 0x1078, 0xa0c5, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, - 0x077e, 0x0c7e, 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, - 0x017e, 0x037e, 0x1078, 0x45c4, 0x00c0, 0xa1ce, 0x2c10, 0x087e, - 0x2041, 0x0000, 0x2828, 0x047e, 0x2021, 0x0001, 0x1078, 0xa482, - 0x047f, 0x097e, 0x2049, 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, - 0x2039, 0x0000, 0x1078, 0x72f3, 0x1078, 0xa0c5, 0x037f, 0x017f, - 0x8108, 0x00f0, 0xa1b0, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, - 0x027f, 0x007c, 0x017e, 0x0f7e, 0xad82, 0xce00, 0x0048, 0xa1f3, - 0xad82, 0xffff, 0x00c8, 0xa1f3, 0x6800, 0xa07d, 0x0040, 0xa1f0, - 0x6803, 0x0000, 0x6b52, 0x1078, 0x4a73, 0x2f68, 0x0078, 0xa1e4, - 0x6b52, 0x1078, 0x4a73, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, - 0x037e, 0x2061, 0xae00, 0xa005, 0x00c0, 0xa206, 0x2071, 0xa700, - 0x7448, 0x7064, 0x8001, 0xa402, 0x00c8, 0xa228, 0x2100, 0xac06, - 0x0040, 0xa21a, 0x6000, 0xa086, 0x0000, 0x0040, 0xa21a, 0x6008, - 0xa206, 0x00c0, 0xa21a, 0x6018, 0xa1a0, 0x0006, 0x2424, 0xa406, - 0x0040, 0xa224, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, 0xac02, - 0x00c8, 0xa228, 0x0078, 0xa206, 0xa085, 0x0001, 0x0078, 0xa229, - 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c, 0x0d7e, 0x007e, 0x1078, - 0x138b, 0x007f, 0x1040, 0x1332, 0x6837, 0x010d, 0x685e, 0x027e, - 0x2010, 0x1078, 0x8d02, 0x2001, 0x0000, 0x0040, 0xa243, 0x2200, - 0xa080, 0x0008, 0x2004, 0x027f, 0x684a, 0x6956, 0x6c46, 0x684f, - 0x0000, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x1078, 0x4a73, - 0x0d7f, 0x007c, 0x6700, 0xa786, 0x0000, 0x0040, 0xa265, 0xa786, - 0x0001, 0x0040, 0xa265, 0xa786, 0x000a, 0x0040, 0xa265, 0xa786, - 0x0009, 0x0040, 0xa265, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x6018, - 0x2070, 0x70a0, 0xa206, 0x0e7f, 0x007c, 0x017e, 0x6004, 0xa08e, - 0x001e, 0x00c0, 0xa287, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, - 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0005, 0x2001, - 0xa9a3, 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x017f, - 0x007c, 0x0005, 0x0005, 0x007c, 0x6024, 0xd0e4, 0x0040, 0xa29d, - 0xd0cc, 0x0040, 0xa297, 0x1078, 0x8fcf, 0x0078, 0xa29d, 0x1078, - 0xa4a5, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x007c, 0xa280, 0x0007, - 0x2004, 0xa084, 0x000f, 0x0079, 0xa2a5, 0xa2ae, 0xa2ae, 0xa2ae, - 0xa2b0, 0xa2ae, 0xa2b0, 0xa2b0, 0xa2ae, 0xa2b0, 0xa006, 0x007c, - 0xa085, 0x0001, 0x007c, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, - 0x0079, 0xa2ba, 0xa2c3, 0xa2c3, 0xa2c3, 0xa2c3, 0xa2c3, 0xa2c3, - 0xa2ce, 0xa2c3, 0xa2c3, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, - 0x2a00, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x007c, 0x0c7e, 0x2260, - 0x1078, 0xa4a5, 0x603f, 0x0000, 0x6024, 0xc0f4, 0xc0cc, 0x6026, - 0x0c7f, 0x0d7e, 0x2268, 0xa186, 0x0007, 0x00c0, 0xa32f, 0x6810, - 0xa005, 0x0040, 0xa2ec, 0xa080, 0x0013, 0x2004, 0xd0fc, 0x00c0, - 0xa2ec, 0x0d7f, 0x0078, 0xa2c3, 0x6007, 0x003a, 0x6003, 0x0001, - 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7e, 0x2d60, 0x6100, 0xa186, - 0x0002, 0x00c0, 0xa3bd, 0x6010, 0xa005, 0x00c0, 0xa306, 0x6000, - 0xa086, 0x0007, 0x10c0, 0x1332, 0x0078, 0xa3bd, 0xa08c, 0xf000, - 0x00c0, 0xa312, 0x0078, 0xa312, 0x2068, 0x6800, 0xa005, 0x00c0, - 0xa30c, 0x2d00, 0xa080, 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, - 0x0002, 0x00c0, 0xa32b, 0x6010, 0x2068, 0x684c, 0xc0dc, 0xc0f4, - 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, 0x2009, 0x0043, 0x1078, - 0x9c2e, 0x0078, 0xa3bd, 0x2009, 0x0041, 0x0078, 0xa3b7, 0xa186, - 0x0005, 0x00c0, 0xa376, 0x6810, 0xa080, 0x0013, 0x2004, 0xd0bc, - 0x00c0, 0xa33d, 0x0d7f, 0x0078, 0xa2c3, 0xd0b4, 0x0040, 0xa345, - 0xd0fc, 0x1040, 0x1332, 0x0078, 0xa2df, 0x6007, 0x003a, 0x6003, - 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7e, 0x2d60, 0x6100, - 0xa186, 0x0002, 0x0040, 0xa358, 0xa186, 0x0004, 0x00c0, 0xa3bd, - 0x2071, 0xa9e7, 0x7000, 0xa086, 0x0003, 0x00c0, 0xa365, 0x7004, - 0xac06, 0x00c0, 0xa365, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, - 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, - 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0078, 0xa3b7, 0x037e, 0x0d7e, - 0x0d7e, 0x1078, 0x138b, 0x037f, 0x1040, 0x1332, 0x6837, 0x010d, - 0x6803, 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, - 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872, 0x2360, 0x6024, 0xc0dd, - 0x6026, 0x6018, 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, - 0x6320, 0x6b4a, 0x6846, 0x684f, 0x0000, 0x6d6a, 0x6e66, 0x686f, - 0x0001, 0x1078, 0x4a73, 0x2019, 0x0045, 0x6008, 0x2068, 0x1078, - 0x9dd7, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, 0x6017, - 0x0000, 0x603f, 0x0000, 0x0d7f, 0x037f, 0x0078, 0xa3be, 0x603f, - 0x0000, 0x6003, 0x0007, 0x1078, 0x9c2e, 0x0c7f, 0x0d7f, 0x007c, - 0xa186, 0x0013, 0x00c0, 0xa3ca, 0x6004, 0xa082, 0x0085, 0x2008, - 0x0079, 0xa3e4, 0xa186, 0x0027, 0x00c0, 0xa3dd, 0x1078, 0x61cd, - 0x037e, 0x0d7e, 0x6010, 0x2068, 0x2019, 0x0004, 0x1078, 0xa1da, - 0x0d7f, 0x037f, 0x1078, 0x62d1, 0x007c, 0xa186, 0x0014, 0x0040, - 0xa3ce, 0x1078, 0x7773, 0x007c, 0xa3ed, 0xa3eb, 0xa3eb, 0xa3eb, - 0xa3eb, 0xa3eb, 0xa3ed, 0x1078, 0x1332, 0x1078, 0x61cd, 0x6003, - 0x000c, 0x1078, 0x62d1, 0x007c, 0xa182, 0x008c, 0x00c8, 0xa3fe, - 0xa182, 0x0085, 0x0048, 0xa3fe, 0x0079, 0xa401, 0x1078, 0x7773, - 0x007c, 0xa408, 0xa408, 0xa408, 0xa408, 0xa40a, 0xa429, 0xa408, - 0x1078, 0x1332, 0x0d7e, 0x2c68, 0x1078, 0x76c7, 0x0040, 0xa424, - 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xac8e, 0x210c, 0x6136, - 0x2009, 0xac8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, - 0x601f, 0x0004, 0x1078, 0x5d8a, 0x2d60, 0x1078, 0x772d, 0x0d7f, - 0x007c, 0x1078, 0x772d, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, - 0xd0ec, 0x0e7f, 0x007c, 0x6010, 0xa08c, 0xf000, 0x0040, 0xa481, - 0xa080, 0x0013, 0x200c, 0xd1ec, 0x0040, 0xa481, 0x2001, 0xa772, - 0x2004, 0xd0ec, 0x0040, 0xa481, 0x6003, 0x0002, 0x6024, 0xc0e5, - 0x6026, 0xd1ac, 0x0040, 0xa45f, 0x0f7e, 0x2c78, 0x1078, 0x495f, - 0x0f7f, 0x0040, 0xa45f, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x2009, - 0xa772, 0x210c, 0xd1f4, 0x00c0, 0xa47f, 0x0078, 0xa471, 0x2009, - 0xa772, 0x210c, 0xd1f4, 0x0040, 0xa46b, 0x6024, 0xc0e4, 0x6026, - 0xa006, 0x0078, 0xa481, 0x2001, 0xa9a4, 0x200c, 0x8103, 0xa100, - 0x603e, 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0040, 0xa47c, - 0xa088, 0x0003, 0x0078, 0xa474, 0x2c0a, 0x600f, 0x0000, 0xa085, - 0x0001, 0x007c, 0x017e, 0x0c7e, 0x0e7e, 0x6120, 0xa2f0, 0x002b, - 0x2e04, 0x2060, 0x8cff, 0x0040, 0xa4a1, 0x84ff, 0x00c0, 0xa494, - 0x6020, 0xa106, 0x00c0, 0xa49c, 0x600c, 0x2072, 0x1078, 0x5bc1, - 0x1078, 0x772d, 0x0078, 0xa49e, 0xacf0, 0x0003, 0x2e64, 0x0078, - 0xa48a, 0x0e7f, 0x0c7f, 0x017f, 0x007c, 0x0d7e, 0x6018, 0xa0e8, - 0x002b, 0x2d04, 0xa005, 0x0040, 0xa4b7, 0xac06, 0x0040, 0xa4b5, - 0x2d04, 0xa0e8, 0x0003, 0x0078, 0xa4a9, 0x600c, 0x206a, 0x0d7f, - 0x007c, 0x027e, 0x037e, 0x157e, 0x2011, 0xa726, 0x2204, 0xa084, - 0x00ff, 0x2019, 0xac8e, 0x2334, 0xa636, 0x00c0, 0xa4e5, 0x8318, - 0x2334, 0x2204, 0xa084, 0xff00, 0xa636, 0x00c0, 0xa4e5, 0x2011, - 0xac90, 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, 0x1078, 0x80de, - 0x00c0, 0xa4e5, 0x2011, 0xac94, 0x6018, 0xa098, 0x0006, 0x20a9, - 0x0004, 0x1078, 0x80de, 0x00c0, 0xa4e5, 0x157f, 0x037f, 0x027f, - 0x007c, 0x0e7e, 0x2071, 0xa700, 0x1078, 0x42b8, 0x1078, 0x2677, - 0x0e7f, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0040, - 0xa4fb, 0x1078, 0xa4fd, 0x0e7f, 0x007c, 0x6850, 0xc0e5, 0x6852, - 0x007c, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, - 0x017e, 0x127e, 0x2091, 0x8000, 0x2029, 0xa9ba, 0x252c, 0x2021, - 0xa9c0, 0x2424, 0x2061, 0xae00, 0x2071, 0xa700, 0x7648, 0x7064, - 0xa606, 0x0040, 0xa555, 0x671c, 0xa786, 0x0001, 0x0040, 0xa524, - 0xa786, 0x0008, 0x00c0, 0xa54b, 0x2500, 0xac06, 0x0040, 0xa54b, - 0x2400, 0xac06, 0x0040, 0xa54b, 0x1078, 0xa252, 0x0040, 0xa54b, - 0x1078, 0xa266, 0x00c0, 0xa54b, 0x6000, 0xa086, 0x0004, 0x00c0, - 0xa53d, 0x017e, 0x1078, 0x1757, 0x017f, 0x1078, 0x8efc, 0x00c0, - 0xa543, 0x1078, 0x28a6, 0x1078, 0x8f10, 0x00c0, 0xa549, 0x1078, - 0x7c83, 0x1078, 0x8ed6, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, - 0xac02, 0x00c8, 0xa555, 0x0078, 0xa514, 0x127f, 0x017f, 0x027f, - 0x047f, 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, - 0x007e, 0x0e7e, 0x017e, 0x2091, 0x8000, 0x2071, 0xa740, 0xd5a4, - 0x0040, 0xa56d, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa573, - 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0xa589, 0x2500, 0xa084, - 0x0007, 0xa08e, 0x0003, 0x0040, 0xa589, 0xa08e, 0x0004, 0x0040, - 0xa589, 0xa08e, 0x0005, 0x0040, 0xa589, 0x2071, 0xa74a, 0x1078, - 0xa5ca, 0x017f, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, - 0x0e7e, 0x017e, 0x2091, 0x8000, 0x2071, 0xa740, 0xd5a4, 0x0040, - 0xa59c, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa5a2, 0x7030, - 0x8000, 0x7032, 0xd5ac, 0x0040, 0xa5b8, 0x2500, 0xa084, 0x0007, - 0xa08e, 0x0003, 0x0040, 0xa5b8, 0xa08e, 0x0004, 0x0040, 0xa5b8, - 0xa08e, 0x0005, 0x0040, 0xa5b8, 0x2071, 0xa74a, 0x1078, 0xa5ca, - 0x017f, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, - 0x2091, 0x8000, 0x2071, 0xa742, 0x1078, 0xa5ca, 0x0e7f, 0x007f, - 0x127f, 0x007c, 0x2e04, 0x8000, 0x2072, 0x00c8, 0xa5d3, 0x8e70, - 0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e, 0x2071, 0xa740, 0x1078, - 0xa5ca, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa744, 0x1078, 0xa5ca, - 0x0e7f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, - 0xa740, 0x7044, 0x8000, 0x7046, 0x0e7f, 0x007f, 0x127f, 0x007c, - 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, - 0x4811 -}; -#ifdef UNIQUE_FW_NAME -unsigned short fw2100tp_length01 = 0x9601; -#else -unsigned short risc_code_length01 = 0x9601; -#endif - diff --git a/drivers/scsi/qla2xxx/ql2200.c b/drivers/scsi/qla2xxx/ql2200.c deleted file mode 100644 index 0eef72d..0000000 --- a/drivers/scsi/qla2xxx/ql2200.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (C) 2003 Christoph Hellwig. - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include -#include -#include - -#include "qla_def.h" - -static char qla_driver_name[] = "qla2200"; - -extern unsigned char fw2200tp_version[]; -extern unsigned char fw2200tp_version_str[]; -extern unsigned short fw2200tp_addr01; -extern unsigned short fw2200tp_code01[]; -extern unsigned short fw2200tp_length01; - -static struct qla_fw_info qla_fw_tbl[] = { - { - .addressing = FW_INFO_ADDR_NORMAL, - .fwcode = &fw2200tp_code01[0], - .fwlen = &fw2200tp_length01, - .fwstart = &fw2200tp_addr01, - }, - - { FW_INFO_ADDR_NOMORE, }, -}; - -static struct qla_board_info qla_board_tbl = { - .drv_name = qla_driver_name, - - .isp_name = "ISP2200", - .fw_info = qla_fw_tbl, -}; - -static struct pci_device_id qla2200_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2200, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl, - }, - - {0, 0}, -}; -MODULE_DEVICE_TABLE(pci, qla2200_pci_tbl); - -static int __devinit -qla2200_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - return qla2x00_probe_one(pdev, - (struct qla_board_info *)id->driver_data); -} - -static void __devexit -qla2200_remove_one(struct pci_dev *pdev) -{ - qla2x00_remove_one(pdev); -} - -static struct pci_driver qla2200_pci_driver = { - .name = "qla2200", - .id_table = qla2200_pci_tbl, - .probe = qla2200_probe_one, - .remove = __devexit_p(qla2200_remove_one), -}; - -static int __init -qla2200_init(void) -{ - return pci_module_init(&qla2200_pci_driver); -} - -static void __exit -qla2200_exit(void) -{ - pci_unregister_driver(&qla2200_pci_driver); -} - -module_init(qla2200_init); -module_exit(qla2200_exit); - -MODULE_AUTHOR("QLogic Corporation"); -MODULE_DESCRIPTION("QLogic ISP22xx FC-SCSI Host Bus Adapter driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2200_fw.c b/drivers/scsi/qla2xxx/ql2200_fw.c deleted file mode 100644 index ac07e18..0000000 --- a/drivers/scsi/qla2xxx/ql2200_fw.c +++ /dev/null @@ -1,5333 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ - -/* - * Firmware Version 2.02.08 (17:06 Mar 22, 2005) - */ - -#ifdef UNIQUE_FW_NAME -unsigned short fw2200tp_version = 2*1024+2; -#else -unsigned short risc_code_version = 2*1024+2; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned char fw2200tp_version_str[] = {2,2,8}; -#else -unsigned char firmware_version[] = {2,2,8}; -#endif - -#ifdef UNIQUE_FW_NAME -#define fw2200tp_VERSION_STRING "2.02.08" -#else -#define FW_VERSION_STRING "2.02.08" -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2200tp_addr01 = 0x1000 ; -#else -unsigned short risc_code_addr01 = 0x1000 ; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2200tp_code01[] = { -#else -unsigned short risc_code01[] = { -#endif - 0x0470, 0x0000, 0x0000, 0xa52b, 0x0000, 0x0002, 0x0002, 0x0008, - 0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, - 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, - 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972, - 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x322e, 0x3032, 0x2e30, 0x3820, 0x2020, 0x2020, 0x2400, 0x20c1, - 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xbbff, 0x2091, - 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x299f, - 0x2051, 0xb600, 0x2a70, 0x2029, 0xee00, 0x2031, 0xffff, 0x2039, - 0xede9, 0x2021, 0x0200, 0x0804, 0x146d, 0x20a1, 0xb52b, 0xa00e, - 0x20a9, 0x08d5, 0x41a4, 0x3400, 0x7562, 0x7666, 0x775e, 0x746a, - 0x746e, 0x20a1, 0xbe00, 0x7164, 0x810d, 0x810d, 0x810d, 0x810d, - 0xa18c, 0x000f, 0x2001, 0x000b, 0xa112, 0xa00e, 0x21a8, 0x41a4, - 0x3400, 0x8211, 0x1dd8, 0x7164, 0x3400, 0xa102, 0x0120, 0x0218, - 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xb600, - 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001, - 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0, - 0x2009, 0xb600, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e, - 0x41a4, 0x080c, 0x1416, 0x080c, 0x1637, 0x080c, 0x17d4, 0x080c, - 0x1fbe, 0x080c, 0x4c72, 0x080c, 0x8646, 0x080c, 0x15c0, 0x080c, - 0x2ef9, 0x080c, 0x5dfc, 0x080c, 0x53b3, 0x080c, 0x6940, 0x080c, - 0x2545, 0x080c, 0x6bd3, 0x080c, 0x642d, 0x080c, 0x23ff, 0x080c, - 0x2513, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820, - 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bd, 0x781b, - 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000, - 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3f4f, 0x080c, - 0x2f20, 0x080c, 0x5e4a, 0x080c, 0x5562, 0x080c, 0x696b, 0x0c80, - 0x000b, 0x0c98, 0x10e4, 0x10e5, 0x1215, 0x10e2, 0x12e2, 0x1413, - 0x1414, 0x1415, 0x080c, 0x151a, 0x0005, 0x0126, 0x00f6, 0x2091, - 0x8000, 0x7000, 0xa086, 0x0001, 0x1904, 0x11f2, 0x080c, 0x158d, - 0x080c, 0x5b41, 0x0150, 0x080c, 0x5b67, 0x15c0, 0x2079, 0x0100, - 0x7828, 0xa085, 0x1800, 0x782a, 0x0488, 0x080c, 0x5a79, 0x7000, - 0xa086, 0x0001, 0x1904, 0x11f2, 0x708c, 0xa086, 0x0028, 0x1904, - 0x11f2, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827, - 0xffff, 0x7a28, 0xa295, 0x1e2f, 0x7a2a, 0x2011, 0x5a14, 0x080c, - 0x6a0e, 0x2011, 0x5a07, 0x080c, 0x6ace, 0x2011, 0x5a56, 0x080c, - 0x6a0e, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x2011, 0x8030, 0x2019, - 0x0000, 0x708b, 0x0000, 0x080c, 0x1e05, 0x00e8, 0x080c, 0x44d6, - 0x2079, 0x0100, 0x7844, 0xa005, 0x1904, 0x11f2, 0x2011, 0x4b23, - 0x080c, 0x6a0e, 0x2011, 0x5a56, 0x080c, 0x6a0e, 0x080c, 0x1e05, - 0x2001, 0xb88d, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842, - 0x2011, 0x8010, 0x73cc, 0x080c, 0x3f13, 0x723c, 0xc284, 0x723e, - 0x2001, 0xb60c, 0x200c, 0xc1ac, 0x2102, 0x080c, 0x7fbc, 0x2011, - 0x0004, 0x080c, 0x9d1c, 0x080c, 0x52bf, 0x080c, 0x5b41, 0x0158, - 0x080c, 0x4c4a, 0x0140, 0x708b, 0x0001, 0x70c7, 0x0000, 0x080c, - 0x4673, 0x0804, 0x11f2, 0x080c, 0x537b, 0x0120, 0x7a0c, 0xc2b4, - 0x7a0e, 0x0060, 0x7073, 0x0000, 0x080c, 0xa0c4, 0x70d4, 0xd09c, - 0x1128, 0x70a0, 0xa005, 0x0110, 0x080c, 0x4c28, 0x70df, 0x0000, - 0x70db, 0x0000, 0x72d4, 0x080c, 0x5b41, 0x1180, 0x2011, 0x0000, - 0x0016, 0x080c, 0x2920, 0x2019, 0xb88f, 0x211a, 0x001e, 0x7053, - 0xffff, 0x7057, 0x00ef, 0x7077, 0x0000, 0x0020, 0x2019, 0xb88f, - 0x201b, 0x0000, 0x2079, 0xb652, 0x7804, 0xd0ac, 0x0108, 0xc295, - 0x72d6, 0x080c, 0x5b41, 0x0118, 0xa296, 0x0004, 0x0548, 0x2011, - 0x0001, 0x080c, 0x9d1c, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, - 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, 0x0003, - 0x782a, 0x00fe, 0x080c, 0x2aed, 0x2011, 0x0005, 0x080c, 0x80fc, - 0x080c, 0x71e5, 0x080c, 0x5b41, 0x0148, 0x00c6, 0x2061, 0x0100, - 0x0016, 0x080c, 0x2920, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420, - 0x709b, 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, 0x00f6, 0x2079, - 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, 0x0003, 0x782a, 0x00fe, - 0x2011, 0x0005, 0x080c, 0x80fc, 0x080c, 0x71e5, 0x080c, 0x5b41, - 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2920, 0x61e2, - 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5b41, - 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x5b41, - 0x1118, 0x2009, 0x0000, 0x0010, 0x2009, 0x007e, 0x080c, 0x2dcc, - 0x8108, 0x1f04, 0x1206, 0x00ce, 0x7073, 0x0000, 0x7074, 0xa084, - 0x00ff, 0x7076, 0x70a3, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, - 0x7000, 0xa086, 0x0002, 0x1904, 0x12e0, 0x709c, 0xa086, 0xffff, - 0x0130, 0x080c, 0x2aed, 0x080c, 0x71e5, 0x0804, 0x12e0, 0x70d4, - 0xd0ac, 0x1110, 0xd09c, 0x0540, 0xd084, 0x0530, 0x0006, 0x0016, - 0x2001, 0x0103, 0x2009, 0xb88d, 0x210c, 0x2102, 0x001e, 0x000e, - 0xd08c, 0x01d0, 0x70d8, 0xa086, 0xffff, 0x0190, 0x080c, 0x2c4c, - 0x080c, 0x71e5, 0x70d4, 0xd094, 0x1904, 0x12e0, 0x2011, 0x0001, - 0x2019, 0x0000, 0x080c, 0x2c84, 0x080c, 0x71e5, 0x0804, 0x12e0, - 0x70dc, 0xa005, 0x1904, 0x12e0, 0x7098, 0xa005, 0x1904, 0x12e0, - 0x70d4, 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x12e0, 0x080c, 0x537b, - 0x1904, 0x12e0, 0x2001, 0xb653, 0x2004, 0xd0ac, 0x01c8, 0x0156, - 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x501b, - 0x1118, 0x6000, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x126d, - 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x12e0, - 0x0006, 0x0016, 0x2001, 0x0103, 0x2009, 0xb88d, 0x210c, 0x2102, - 0x001e, 0x000e, 0x71a8, 0x81ff, 0x11b0, 0xa006, 0x2009, 0x0200, - 0x20a9, 0x0002, 0x20a1, 0xb8df, 0x40a1, 0x2009, 0x0700, 0x20a9, - 0x0002, 0x20a1, 0xb8cf, 0x40a1, 0x7070, 0x8007, 0x7174, 0x810f, - 0x20a9, 0x0002, 0x40a1, 0x20a1, 0xb8d3, 0x2009, 0x0000, 0x080c, - 0x1500, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x40a1, 0x7030, - 0xc08c, 0x7032, 0x7003, 0x0003, 0x709f, 0xffff, 0x080c, 0x1586, - 0xa006, 0x080c, 0x27f8, 0x080c, 0x3f85, 0x00f6, 0x2079, 0x0100, - 0x080c, 0x5b67, 0x0150, 0x080c, 0x5b41, 0x7828, 0x0118, 0xa084, - 0xe1ff, 0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0xb8e2, - 0x2004, 0xa086, 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0x80fc, - 0x2011, 0x0000, 0x080c, 0x8106, 0x080c, 0x71e5, 0x080c, 0x72a2, - 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, - 0x2079, 0x0100, 0x2009, 0xb634, 0x2104, 0xa005, 0x1110, 0x080c, - 0x294c, 0x2009, 0x00f7, 0x080c, 0x4c11, 0x7940, 0xa18c, 0x0010, - 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, - 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, - 0x1350, 0x080c, 0x5b53, 0x0158, 0x080c, 0x5b67, 0x1128, 0x2001, - 0xb89e, 0x2003, 0x0000, 0x0070, 0x080c, 0x5b49, 0x0dc0, 0x2001, - 0xb89e, 0x2003, 0xaaaa, 0x2001, 0xb89f, 0x2003, 0x0001, 0x080c, - 0x5a79, 0x0058, 0x080c, 0x5b41, 0x0140, 0x2009, 0x00f8, 0x080c, - 0x4c11, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, - 0xd09c, 0x1138, 0x080c, 0x5b41, 0x0138, 0x7824, 0xd0ac, 0x1904, - 0x13fa, 0x1f04, 0x132f, 0x0070, 0x7824, 0x080c, 0x5b5d, 0x0118, - 0xd0ac, 0x1904, 0x13fa, 0xa084, 0x1800, 0x0d98, 0x7003, 0x0001, - 0x0804, 0x13fa, 0x2001, 0x0001, 0x080c, 0x27f8, 0x0804, 0x1409, - 0x7850, 0xa084, 0x0180, 0x7852, 0x782f, 0x0020, 0x20a9, 0x0046, - 0x1d04, 0x1358, 0x080c, 0x6ab6, 0x1f04, 0x1358, 0x7850, 0xa084, - 0x0180, 0xa085, 0x0400, 0x7852, 0x782f, 0x0000, 0x080c, 0x5b53, - 0x0158, 0x080c, 0x5b67, 0x1128, 0x2001, 0xb89e, 0x2003, 0x0000, - 0x0070, 0x080c, 0x5b49, 0x0dc0, 0x2001, 0xb89e, 0x2003, 0xaaaa, - 0x2001, 0xb89f, 0x2003, 0x0001, 0x080c, 0x5a79, 0x0020, 0x2009, - 0x00f8, 0x080c, 0x4c11, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x1385, - 0x7850, 0xa084, 0x0180, 0xa085, 0x1400, 0x7852, 0x080c, 0x5b41, - 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, - 0xea60, 0x7820, 0xd09c, 0x1558, 0x080c, 0x5b41, 0x05d8, 0x7824, - 0xd0ac, 0x1904, 0x13fa, 0x080c, 0x5b67, 0x1508, 0x0046, 0x2021, - 0x0190, 0x8421, 0x1df0, 0x004e, 0x8421, 0x11c8, 0x7827, 0x0048, - 0x20a9, 0x01f4, 0x1d04, 0x13b2, 0x080c, 0x6ab6, 0x1f04, 0x13b2, - 0x7824, 0xa084, 0x0068, 0x15c8, 0x2001, 0xb89e, 0x2003, 0xaaaa, - 0x2001, 0xb89f, 0x2003, 0x0001, 0x7003, 0x0001, 0x0498, 0x1d04, - 0x13cb, 0x080c, 0x6ab6, 0x8319, 0x1960, 0x2009, 0xb634, 0x2104, - 0x8000, 0x200a, 0xa084, 0xfff0, 0x0120, 0x200b, 0x0000, 0x080c, - 0x294c, 0x00d8, 0x080c, 0x5b53, 0x1140, 0xa4a2, 0x0064, 0x1128, - 0x080c, 0x5b18, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0xe000, - 0xe000, 0x7824, 0x080c, 0x5b5d, 0x0110, 0xd0ac, 0x1158, 0xa084, - 0x1800, 0x09a8, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, - 0x27f8, 0x0048, 0x2001, 0xb634, 0x2003, 0x0000, 0x7827, 0x0048, - 0x7828, 0xc09d, 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, - 0x7852, 0x015e, 0x003e, 0x000e, 0x080c, 0x155d, 0x012e, 0x00fe, - 0x004e, 0x001e, 0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2061, - 0xb8c2, 0x2063, 0x0002, 0x6007, 0x0002, 0x600b, 0x0008, 0x600f, - 0x0017, 0x2001, 0xb89e, 0x2003, 0x0000, 0x708b, 0x0000, 0x2009, - 0x0100, 0x2104, 0xa082, 0x0002, 0x0218, 0x7053, 0xffff, 0x0010, - 0x7053, 0x0000, 0x705b, 0xffff, 0x7073, 0x0000, 0x7077, 0x0000, - 0x080c, 0xa0c4, 0x2061, 0xb88e, 0x6003, 0x0909, 0x6007, 0x0000, - 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x000f, - 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, 0xb896, 0x6003, 0x8000, - 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, - 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, 0x0000, 0x2061, 0xb8b9, - 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, - 0x2001, 0xb628, 0x2003, 0x0000, 0x0005, 0x04a0, 0x2011, 0x0000, - 0x81ff, 0x0570, 0xa186, 0x0001, 0x1148, 0x2031, 0x8fff, 0x2039, - 0xd601, 0x2021, 0x0100, 0x2029, 0xd600, 0x00e8, 0xa186, 0x0002, - 0x1118, 0x2011, 0x0000, 0x00b8, 0xa186, 0x0005, 0x1118, 0x2011, - 0x0001, 0x0088, 0xa186, 0x0009, 0x1118, 0x2011, 0x0002, 0x0058, - 0xa186, 0x000a, 0x1118, 0x2011, 0x0002, 0x0028, 0xa186, 0x0055, - 0x1110, 0x2011, 0x0003, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, - 0x0804, 0x104d, 0xa00e, 0x2011, 0x0003, 0x2019, 0x14a9, 0x0804, - 0x14fa, 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, - 0xe000, 0x2c04, 0xa306, 0x2262, 0x1110, 0xc1b5, 0xc1a5, 0x2011, - 0x0000, 0x2019, 0x14bc, 0x04f0, 0x2019, 0xaaaa, 0x2061, 0xffff, - 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0xe000, - 0xe000, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x0110, 0xc18d, - 0x0008, 0xc185, 0x2011, 0x0002, 0x2019, 0x14d7, 0x0418, 0x2061, - 0xffff, 0x2019, 0xaaaa, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, - 0x2262, 0xa306, 0x1180, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, - 0x2061, 0x7fff, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x1110, - 0xc195, 0x0008, 0xc19d, 0x2011, 0x0001, 0x2019, 0x14f8, 0x0010, - 0x0804, 0x146e, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0837, - 0x2011, 0x0000, 0x080c, 0x501b, 0x1178, 0x6004, 0xa0c4, 0x00ff, - 0xa8c6, 0x0006, 0x0128, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x1120, - 0xa186, 0x0080, 0x0108, 0x8210, 0x8108, 0xa186, 0x0100, 0x1d50, - 0x2208, 0x0005, 0x2091, 0x8000, 0x0e04, 0x151c, 0x0006, 0x0016, - 0x2079, 0x0000, 0x7818, 0xd084, 0x1de8, 0x001e, 0x792e, 0x000e, - 0x782a, 0x000e, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, - 0x0001, 0x2091, 0x5000, 0x0126, 0x0156, 0x0146, 0x20a9, 0x0010, - 0x20a1, 0xba0d, 0x2091, 0x2000, 0x40a1, 0x20a9, 0x0010, 0x2091, - 0x2200, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2400, 0x40a1, 0x20a9, - 0x0010, 0x2091, 0x2600, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2800, - 0x40a1, 0x014e, 0x015e, 0x012e, 0x2079, 0xb600, 0x7803, 0x0005, - 0x2091, 0x4080, 0x04c9, 0x0cf8, 0x0005, 0x0006, 0x080c, 0x15a8, - 0x1518, 0x00f6, 0x2079, 0xb624, 0x2f04, 0x8000, 0x207a, 0xa082, - 0x000f, 0x0258, 0xa006, 0x207a, 0x2079, 0xb626, 0x2f04, 0xa084, - 0x0001, 0xa086, 0x0001, 0x207a, 0x0070, 0x2079, 0xb626, 0x2f7c, - 0x8fff, 0x1128, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0020, 0x2001, - 0x0c03, 0x2003, 0x00c0, 0x00fe, 0x000e, 0x0005, 0x0409, 0x1120, - 0x2001, 0x0c03, 0x2003, 0x0080, 0x0005, 0x00d1, 0x1120, 0x2001, - 0x0c03, 0x2003, 0x0040, 0x0005, 0x0006, 0x0091, 0x1178, 0x2001, - 0x0c03, 0x2003, 0x0040, 0x2009, 0x0fff, 0x00a1, 0x2001, 0x0c03, - 0x2003, 0x0080, 0x2009, 0x0fff, 0x0069, 0x0c88, 0x000e, 0x0005, - 0x00c6, 0x2061, 0x0c00, 0x2c04, 0xa084, 0x00ff, 0xa086, 0x00aa, - 0x00ce, 0x0005, 0x0156, 0x0126, 0xa18c, 0x0fff, 0x21a8, 0x1d04, - 0x15b7, 0x2091, 0x6000, 0x1f04, 0x15b7, 0x012e, 0x015e, 0x0005, - 0x2071, 0xb600, 0x7160, 0x712e, 0x2021, 0x0001, 0xa190, 0x0030, - 0xa298, 0x0030, 0x0240, 0x7064, 0xa302, 0x1228, 0x220a, 0x2208, - 0x2310, 0x8420, 0x0ca8, 0x3800, 0xd08c, 0x0148, 0x7064, 0xa086, - 0xb600, 0x0128, 0x7067, 0xb600, 0x2011, 0x1000, 0x0c48, 0x200b, - 0x0000, 0x74b2, 0x74b6, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0xb600, 0x70b4, 0xa0ea, 0x0010, 0x0268, 0x8001, 0x70b6, - 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, - 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x2071, 0xb600, - 0x0126, 0x2091, 0x8000, 0x70b4, 0x8001, 0x0260, 0x70b6, 0x702c, - 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, - 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0xb600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, 0x8000, - 0x70b6, 0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, - 0x0000, 0x0006, 0x0c49, 0x00de, 0x0cb8, 0x0005, 0x00e6, 0x2071, - 0xb600, 0x70b4, 0xa08a, 0x0010, 0xa00d, 0x00ee, 0x0005, 0x00e6, - 0x2071, 0xb913, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, - 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x00ee, 0x0005, - 0x0126, 0x2091, 0x8000, 0x00e6, 0x2270, 0x700b, 0x0000, 0x2071, - 0xb913, 0x7018, 0xa088, 0xb91c, 0x220a, 0x8000, 0xa084, 0x0007, - 0x701a, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0089, - 0x00fe, 0x00ee, 0x012e, 0x0005, 0x00e6, 0x2071, 0xb913, 0x7004, - 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0019, 0x00fe, 0x00ee, - 0x0005, 0x7000, 0x0002, 0x1677, 0x16db, 0x16f8, 0x16f8, 0x7018, - 0x711c, 0xa106, 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, 0xa180, - 0xb91c, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, 0x711e, - 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, 0x783a, - 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, 0x00de, - 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002, - 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, - 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, - 0x7803, 0x0020, 0x7803, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016, - 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x2098, 0x20a1, 0x0014, - 0x7803, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x1210, - 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, - 0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x015e, 0x014e, 0x013e, - 0x002e, 0x001e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2099, 0xb6fa, - 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, - 0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, - 0x7002, 0x700b, 0xb6f5, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, - 0x0136, 0x0146, 0x0156, 0x2001, 0xb729, 0x209c, 0x20a1, 0x0014, - 0x7803, 0x0026, 0x2001, 0xb72a, 0x20ac, 0x53a6, 0x2099, 0xb72b, - 0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, - 0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, - 0x7002, 0x700b, 0xb726, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, - 0x0016, 0x00e6, 0x2071, 0xb913, 0x00f6, 0x2079, 0x0010, 0x7904, - 0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, 0x0700, 0x7004, 0x0023, - 0x00fe, 0x00ee, 0x001e, 0x0005, 0x1671, 0x173b, 0x1769, 0x1793, - 0x17c3, 0x173a, 0x0cf8, 0xa18c, 0x0700, 0x1528, 0x0136, 0x0146, - 0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, - 0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, 0x013e, 0x700c, - 0xa005, 0x0570, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x16a2, - 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, - 0x080c, 0x1671, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, - 0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, 0xa005, 0x0188, 0x7830, - 0x7832, 0x7834, 0x7836, 0x080c, 0x16b7, 0x0005, 0x7008, 0xa080, - 0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x080c, 0x1671, 0x0005, - 0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, - 0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x00de, 0x7007, 0x0000, - 0x080c, 0x1671, 0x0005, 0xa18c, 0x0700, 0x1540, 0x0136, 0x0146, - 0x0156, 0x2001, 0xb6f8, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, - 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xb6fa, - 0x2004, 0xd0bc, 0x0148, 0x2001, 0xb703, 0x2004, 0xa080, 0x000d, - 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, 0x014e, 0x013e, 0x7007, - 0x0000, 0x080c, 0x5ee1, 0x080c, 0x1671, 0x0005, 0x2011, 0x8003, - 0x080c, 0x3f13, 0x0cf8, 0xa18c, 0x0700, 0x1148, 0x2001, 0xb728, - 0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x1671, 0x0005, 0x2011, - 0x8004, 0x080c, 0x3f13, 0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079, - 0x0030, 0x2071, 0xb924, 0x7003, 0x0000, 0x700f, 0xb930, 0x7013, - 0xb930, 0x780f, 0x00f6, 0x7803, 0x0004, 0x012e, 0x0005, 0x6934, - 0xa184, 0x0007, 0x0002, 0x17f3, 0x1831, 0x17f3, 0x17f3, 0x17f3, - 0x1819, 0x1800, 0x17f7, 0xa085, 0x0001, 0x0804, 0x184b, 0x684c, - 0xd0bc, 0x0dc8, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x04c8, - 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d70, 0x684c, 0xd0bc, 0x0d58, - 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, 0xa080, 0x000d, - 0x2004, 0xa084, 0x000f, 0xa080, 0x2308, 0x2005, 0x6832, 0x6858, - 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x19a8, 0x684c, 0xd0ac, - 0x0990, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, - 0xa080, 0x2308, 0x2005, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, - 0x0080, 0x684c, 0xd0ac, 0x0904, 0x17f3, 0xa006, 0x682e, 0x682a, - 0x6858, 0xa18c, 0x000f, 0xa188, 0x2308, 0x210d, 0x6932, 0x2d08, - 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, - 0x6912, 0x6980, 0x6916, 0x0005, 0x684c, 0xd0ac, 0x090c, 0x151a, - 0x6833, 0x2305, 0x2d08, 0x691a, 0x6858, 0x8001, 0x6826, 0x684c, - 0xc0dd, 0x684e, 0xa006, 0x680a, 0x682e, 0x682a, 0x697c, 0x6912, - 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, - 0x020a, 0x2004, 0x82ff, 0x01e8, 0xa280, 0x0004, 0x00d6, 0x206c, - 0x684c, 0xd0dc, 0x1190, 0xa280, 0x0007, 0x2004, 0xa086, 0x000a, - 0x1110, 0x0891, 0x0010, 0x080c, 0x17e7, 0x0138, 0x00de, 0xa280, - 0x0000, 0x2003, 0x0002, 0xa016, 0x0020, 0x6808, 0x8000, 0x680a, - 0x00de, 0x0126, 0x0046, 0x0036, 0x0026, 0x2091, 0x2200, 0x002e, - 0x003e, 0x004e, 0x7000, 0xa005, 0x01d0, 0x710c, 0x220a, 0x8108, - 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, 0xb94b, 0x0210, 0x2009, - 0xb930, 0x710e, 0x7010, 0xa102, 0xa082, 0x0009, 0x0118, 0xa080, - 0x001b, 0x1118, 0x2009, 0x0138, 0x200a, 0x012e, 0x0005, 0x7206, - 0x2001, 0x18ad, 0x0006, 0x2260, 0x0804, 0x19da, 0x0126, 0x0026, - 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, 0x004e, 0x003e, - 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, - 0xa005, 0x0904, 0x190f, 0x6808, 0xa005, 0x0904, 0x1946, 0x7000, - 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, 0xa106, 0x1904, 0x194e, - 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0168, - 0x0046, 0x080c, 0x1b22, 0x004e, 0x2460, 0x6010, 0xa080, 0x0002, - 0x2004, 0xa005, 0x0904, 0x1946, 0x0c10, 0x2001, 0x0207, 0x2004, - 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, 0x0120, 0xa086, 0x6000, - 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, 0x0004, - 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x1904, - 0x194e, 0x2009, 0x0048, 0x080c, 0x86d3, 0x0804, 0x194e, 0x6808, - 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, 0x7110, 0xa106, - 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, 0x2004, 0xd08c, - 0x0160, 0x0046, 0x080c, 0x1b22, 0x004e, 0x2460, 0x6010, 0xa080, - 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, 0x0207, 0x2004, - 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, 0x1d50, 0x7804, - 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, 0x7818, 0x6812, - 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x6100, 0xa18e, - 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x86d3, 0x00ce, 0x00de, - 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046, 0x0056, - 0x2071, 0xb924, 0x7000, 0xa086, 0x0000, 0x0904, 0x19b8, 0x7004, - 0xac06, 0x1904, 0x19aa, 0x2079, 0x0030, 0x7000, 0xa086, 0x0003, - 0x0904, 0x19aa, 0x7804, 0xd0fc, 0x15c8, 0x20e1, 0x6000, 0x2011, - 0x0032, 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, - 0x1d88, 0x8211, 0x1db0, 0x7804, 0xd0fc, 0x1540, 0x080c, 0x1e8a, - 0x0026, 0x0056, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x1de8, 0x7803, - 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, 0x0000, 0x005e, - 0x002e, 0x2001, 0x015d, 0x2003, 0x0000, 0x080c, 0x5b41, 0x1138, - 0x0066, 0x2031, 0x0001, 0x080c, 0x5bc3, 0x006e, 0x0058, 0x2001, - 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0020, 0x080c, 0x1b22, - 0x0804, 0x195a, 0x0156, 0x20a9, 0x0009, 0x2009, 0xb930, 0x2104, - 0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x19af, 0x015e, - 0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, 0x700c, - 0x7110, 0xa106, 0x0904, 0x1a4e, 0x2104, 0x7006, 0x2060, 0x8108, - 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xb94b, 0x0210, 0x2009, - 0xb930, 0x7112, 0x700c, 0xa106, 0x1128, 0x080c, 0x2920, 0x2001, - 0x0138, 0x2102, 0x8cff, 0x0598, 0x6010, 0x2068, 0x2d58, 0x6828, - 0xa406, 0x1590, 0x682c, 0xa306, 0x1578, 0x7004, 0x2060, 0x6020, - 0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, 0x6817, 0xffff, 0x6813, - 0xffff, 0x00e8, 0x6850, 0xd0f4, 0x1130, 0x7803, 0x0004, 0x6810, - 0x781a, 0x6814, 0x781e, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, - 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, 0x0011, 0x080c, 0x1a51, - 0x0120, 0x2009, 0x0001, 0x080c, 0x1a51, 0x2d58, 0x0005, 0x080c, - 0x1df9, 0x0904, 0x19bf, 0x0cd0, 0x6020, 0xd0f4, 0x11e0, 0xd0d4, - 0x01b8, 0x6038, 0xa402, 0x6034, 0xa303, 0x0108, 0x1288, 0x643a, - 0x6336, 0x6c2a, 0x6b2e, 0x0046, 0x0036, 0x2400, 0x6c7c, 0xa402, - 0x6812, 0x2300, 0x6b80, 0xa303, 0x6816, 0x003e, 0x004e, 0x0018, - 0x080c, 0xa056, 0x09e0, 0x601c, 0xa08e, 0x0008, 0x0904, 0x19e5, - 0xa08e, 0x000a, 0x0904, 0x19e5, 0x2001, 0xb674, 0x2004, 0xd0b4, - 0x1140, 0x6018, 0x2004, 0xd0bc, 0x1120, 0x6817, 0x7fff, 0x6813, - 0xffff, 0x080c, 0x2328, 0x1918, 0x0804, 0x19e5, 0x7003, 0x0000, - 0x0005, 0x8aff, 0x0904, 0x1afc, 0xa03e, 0x2730, 0xc9fc, 0x6850, - 0xd0fc, 0x11b8, 0xd0f4, 0x1588, 0x00d6, 0x2805, 0xac68, 0x2900, - 0x0002, 0x1aba, 0x1a93, 0x1a93, 0x1aba, 0x1aba, 0x1ab2, 0x1aba, - 0x1a93, 0x1aba, 0x1a9b, 0x1a9b, 0x1aba, 0x1aba, 0x1aba, 0x1aaa, - 0x1a9b, 0x7803, 0x0004, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, - 0x6c20, 0x00d6, 0xd99c, 0x0140, 0x2805, 0xac68, 0x6f08, 0x6e0c, - 0x080c, 0x23ed, 0x0120, 0x04d0, 0x080c, 0x23ed, 0x15b0, 0x6850, - 0xc0fd, 0x6852, 0x00de, 0xa006, 0x0005, 0xc0f4, 0x6852, 0x6b6c, - 0x6a70, 0x00d6, 0x04c0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x080c, - 0x23ed, 0x0d80, 0x0410, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, - 0x6e0c, 0x080c, 0x23ed, 0x0d30, 0x00c8, 0x6d00, 0x6c04, 0x6f08, - 0x6e0c, 0x00a0, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x001e, 0x1140, 0x00de, 0x080c, 0x22ca, 0x1904, 0x1a51, 0xa00e, - 0x0804, 0x1afc, 0x00de, 0x080c, 0x151a, 0xc9fd, 0x7b22, 0x7a26, - 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7316, 0x721a, 0x751e, 0x7422, - 0x7726, 0x762a, 0x7902, 0x7100, 0x8108, 0x7102, 0x00de, 0x6828, - 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x8109, 0x2d08, 0x1500, - 0xd9fc, 0x0160, 0xc9fc, 0x080c, 0x22ca, 0x01e8, 0x2805, 0xac68, - 0x6800, 0xa506, 0x11c0, 0x6804, 0xa406, 0x00a8, 0xc9fc, 0x080c, - 0x22ca, 0x0188, 0x2805, 0xac68, 0x6800, 0xa506, 0x1160, 0x6804, - 0xa406, 0x1148, 0x6808, 0xa706, 0x1130, 0x680c, 0xa606, 0x0018, - 0xc9fc, 0x080c, 0x22ca, 0x2168, 0x0005, 0x080c, 0x151a, 0x080c, - 0x1f71, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x7003, 0x0000, - 0x080c, 0x1e1a, 0x080c, 0x9d16, 0x0170, 0x6808, 0x8001, 0x680a, - 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, 0xffff, - 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x99e6, 0x0804, 0x1d47, - 0x080c, 0x151a, 0x0126, 0x2091, 0x2200, 0x0006, 0x0016, 0x2b68, - 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x1978, - 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000, 0x0002, 0x1b3f, - 0x1b45, 0x1c56, 0x1d22, 0x1d36, 0x1b3f, 0x1b3f, 0x1b3f, 0x7804, - 0xd09c, 0x1904, 0x1d47, 0x080c, 0x151a, 0x8001, 0x7002, 0xd1bc, - 0x11a0, 0xd19c, 0x1904, 0x1bda, 0xd1dc, 0x1178, 0x8aff, 0x0904, - 0x1bda, 0x2009, 0x0001, 0x080c, 0x1a51, 0x0904, 0x1d47, 0x2009, - 0x0001, 0x080c, 0x1a51, 0x0804, 0x1d47, 0x7803, 0x0004, 0x7003, - 0x0000, 0xd1bc, 0x1904, 0x1bba, 0x0026, 0x0036, 0x7c20, 0x7d24, - 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, - 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, - 0x7003, 0x0004, 0x0010, 0x080c, 0x1d4b, 0x6b28, 0x6a2c, 0x2400, - 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x00c6, - 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, 0x633a, 0x6236, 0x00ce, - 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x2500, 0xa405, 0x0128, 0x080c, - 0x22e0, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, - 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x1148, 0x684c, 0xd0e4, - 0x0130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x86d3, 0x7000, - 0xa086, 0x0004, 0x0904, 0x1d47, 0x7003, 0x0000, 0x080c, 0x19bf, - 0x0804, 0x1d47, 0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, 0xb4c3, - 0x005e, 0x080c, 0x1e1a, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5377, - 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, - 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, - 0x0804, 0x1d47, 0x7004, 0x00c6, 0x2060, 0x6020, 0x00ce, 0xd0f4, - 0x0120, 0x6808, 0x8001, 0x680a, 0x04c0, 0x7818, 0x6812, 0x7a1c, - 0x6a16, 0xd19c, 0x0160, 0xa205, 0x0150, 0x7004, 0xa080, 0x0007, - 0x2004, 0xa084, 0xfffd, 0xa086, 0x0008, 0x1904, 0x1b5d, 0x684c, - 0xc0f5, 0x684e, 0x7814, 0xa005, 0x1520, 0x7003, 0x0000, 0x6808, - 0x8001, 0x680a, 0x01a0, 0x7004, 0x2060, 0x601c, 0xa086, 0x000a, - 0x11a0, 0x0156, 0x20a9, 0x0009, 0x2009, 0xb930, 0x2104, 0xac06, - 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x1c0e, 0x015e, 0x7004, - 0x2060, 0x2009, 0x0048, 0x080c, 0x86d3, 0x080c, 0x19bf, 0x0804, - 0x1d47, 0x7818, 0x6812, 0x781c, 0x6816, 0x7814, 0x7908, 0xa18c, - 0x0fff, 0xa192, 0x0841, 0x1a04, 0x1aff, 0xa188, 0x0007, 0x8114, - 0x8214, 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, - 0x810b, 0x810b, 0x080c, 0x1eb5, 0x7803, 0x0004, 0x780f, 0xffff, - 0x7803, 0x0001, 0x7804, 0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803, - 0x0004, 0x780f, 0x00f6, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, - 0x0048, 0x080c, 0x86d3, 0x080c, 0x1f0b, 0x0838, 0x8001, 0x7002, - 0xd194, 0x01b0, 0x7804, 0xd0fc, 0x1904, 0x1cf2, 0xd09c, 0x0138, - 0x7804, 0xd0fc, 0x1904, 0x1cf2, 0xd09c, 0x1904, 0x1cf6, 0x8aff, - 0x0904, 0x1d47, 0x2009, 0x0001, 0x080c, 0x1a51, 0x0804, 0x1d47, - 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904, 0x1d47, 0x2009, 0x0001, - 0x080c, 0x1a51, 0x0804, 0x1d47, 0x7818, 0x6812, 0x7a1c, 0x6a16, - 0xa205, 0x0904, 0x1bf7, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, - 0x1904, 0x1cd4, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0029, 0x1118, - 0xd19c, 0x1904, 0x1bf7, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, - 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, - 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, - 0x0004, 0x0020, 0x0016, 0x080c, 0x1d4b, 0x001e, 0x6b28, 0x6a2c, - 0x080c, 0x22e0, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, - 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, - 0xa213, 0x00de, 0xd194, 0x0904, 0x1b7f, 0x2a00, 0x6826, 0x2c00, - 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x6b2a, 0x6a2e, - 0x003e, 0x002e, 0x0804, 0x1c1d, 0x0056, 0x7d0c, 0x080c, 0xb4c3, - 0x005e, 0x080c, 0x1e1a, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5377, - 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, - 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, - 0x0804, 0x1d47, 0x7804, 0xd09c, 0x0904, 0x1b2a, 0x7c20, 0x7824, - 0xa405, 0x1904, 0x1b2a, 0x7818, 0x6812, 0x7c1c, 0x6c16, 0xa405, - 0x1120, 0x7803, 0x0002, 0x0804, 0x1bf7, 0x751c, 0x7420, 0x7724, - 0x7628, 0x7014, 0xa528, 0x7018, 0xa421, 0xa7b9, 0x0000, 0xa6b1, - 0x0000, 0x7830, 0xa506, 0x1150, 0x7834, 0xa406, 0x1138, 0x7838, - 0xa706, 0x1120, 0x783c, 0xa606, 0x0904, 0x1b2a, 0x7803, 0x0002, - 0x0804, 0x1c83, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, - 0x0150, 0x6808, 0x8001, 0x680a, 0x1130, 0x7004, 0x2060, 0x2009, - 0x0048, 0x080c, 0x86d3, 0x080c, 0x19bf, 0x0088, 0x7803, 0x0004, - 0x7003, 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068, - 0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x080c, 0x19da, 0x001e, - 0x000e, 0x012e, 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1ded, - 0x7004, 0x0016, 0x210c, 0xa106, 0x001e, 0x0904, 0x1ded, 0x00d6, - 0x00c6, 0x216c, 0x2d00, 0xa005, 0x0904, 0x1deb, 0x681c, 0xa086, - 0x0008, 0x0904, 0x1deb, 0x6820, 0xd0d4, 0x1904, 0x1deb, 0x6810, - 0x2068, 0x6850, 0xd0fc, 0x05a8, 0x8108, 0x2104, 0x6b2c, 0xa306, - 0x1904, 0x1deb, 0x8108, 0x2104, 0x6a28, 0xa206, 0x1904, 0x1deb, - 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x7016, 0x6870, - 0x7826, 0x701a, 0x681c, 0x7832, 0x701e, 0x6820, 0x7836, 0x7022, - 0x6818, 0x2060, 0x6034, 0xd09c, 0x0168, 0x6830, 0x2005, 0x00d6, - 0xac68, 0x6808, 0x783a, 0x7026, 0x680c, 0x783e, 0x702a, 0x00de, - 0x0804, 0x1de5, 0xa006, 0x783a, 0x783e, 0x7026, 0x702a, 0x0804, - 0x1de5, 0x8108, 0x2104, 0xa005, 0x1904, 0x1deb, 0x6b2c, 0xa306, - 0x1904, 0x1deb, 0x8108, 0x2104, 0xa005, 0x15e8, 0x6a28, 0xa206, - 0x15d0, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, 0xa160, - 0xa180, 0x000d, 0x2004, 0xd09c, 0x11a0, 0x6008, 0x7822, 0x7016, - 0x686e, 0x600c, 0x7826, 0x701a, 0x6872, 0x6000, 0x7832, 0x701e, - 0x6004, 0x7836, 0x7022, 0xa006, 0x783a, 0x783e, 0x7026, 0x702a, - 0x00a0, 0x6010, 0x7822, 0x7016, 0x686e, 0x6014, 0x7826, 0x701a, - 0x6872, 0x6000, 0x7832, 0x701e, 0x6004, 0x7836, 0x7022, 0x6008, - 0x783a, 0x7026, 0x600c, 0x783e, 0x702a, 0x6810, 0x781a, 0x6814, - 0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, 0x0005, 0x2011, 0x0201, - 0x2009, 0x003c, 0x2204, 0xa005, 0x1118, 0x8109, 0x1dd8, 0x0005, - 0x0005, 0x0ca1, 0x0118, 0x780c, 0xd0a4, 0x0120, 0x00d9, 0xa085, - 0x0001, 0x0010, 0x080c, 0x1f0b, 0x0005, 0x0126, 0x2091, 0x2200, - 0x7000, 0xa086, 0x0003, 0x1160, 0x700c, 0x7110, 0xa106, 0x0140, - 0x080c, 0x2991, 0x20e1, 0x9028, 0x700f, 0xb930, 0x7013, 0xb930, - 0x012e, 0x0005, 0x00c6, 0x080c, 0x5b41, 0x11b8, 0x2001, 0x0160, - 0x2003, 0x0000, 0x2001, 0x0138, 0x2003, 0x0000, 0x2011, 0x00c8, - 0xe000, 0xe000, 0x8211, 0x1de0, 0x04b1, 0x0066, 0x2031, 0x0000, - 0x080c, 0x5bc3, 0x006e, 0x00ce, 0x0005, 0x080c, 0x1e8a, 0x080c, - 0x2991, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x01c0, 0x2104, - 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, - 0xa188, 0x0003, 0xa182, 0xb94b, 0x0210, 0x2009, 0xb930, 0x7112, - 0x700c, 0xa106, 0x1d40, 0x080c, 0x2920, 0x2110, 0x0c20, 0x2001, - 0x015d, 0x2003, 0x0000, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, - 0x2202, 0x00ce, 0x0005, 0x080c, 0x2991, 0x20e1, 0x9028, 0x2001, - 0x015d, 0x2003, 0x0000, 0x00e6, 0x00c6, 0x0016, 0x2071, 0xb924, - 0x700c, 0x7110, 0xa106, 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, - 0x6010, 0x2060, 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, - 0xb94b, 0x0210, 0x2009, 0xb930, 0x7112, 0x0c50, 0x001e, 0x00ce, - 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, - 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x5b41, 0x1148, 0x2021, - 0x0002, 0x1d04, 0x1e99, 0x2091, 0x6000, 0x8421, 0x1dd0, 0x0005, - 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, - 0x0109, 0x201c, 0xa39c, 0x0048, 0x1138, 0x2001, 0x0111, 0x201c, - 0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005, 0x00e6, 0x2071, 0x0200, - 0x7808, 0xa084, 0xf000, 0xa10d, 0x0869, 0x2001, 0x0105, 0x2004, - 0xa084, 0x0003, 0x1130, 0x2001, 0xb94b, 0x2004, 0xa086, 0x0000, - 0x0548, 0xa026, 0x2019, 0xf000, 0x8319, 0x1148, 0x2001, 0x012b, - 0x2003, 0x95f5, 0x2001, 0x0129, 0x2003, 0x95f5, 0x00d8, 0x2001, - 0x0105, 0x2004, 0xa084, 0x0003, 0x1130, 0x2001, 0xb94b, 0x2004, - 0xa086, 0x0000, 0x0178, 0x2001, 0x0132, 0x2004, 0xa436, 0x0110, - 0x2020, 0x0c00, 0x2001, 0x0021, 0x2004, 0xd0fc, 0x09e8, 0x080c, - 0x216d, 0x08c0, 0x20e1, 0x7000, 0x7324, 0x7420, 0x7028, 0x7028, - 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, 0x0100, 0x7037, - 0x0008, 0x7326, 0x7422, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, - 0x2202, 0x00ee, 0x0005, 0x0026, 0x2001, 0x015d, 0x2003, 0x0000, - 0x7908, 0xa18c, 0x0fff, 0xa182, 0x0ffd, 0x0210, 0x2009, 0x0000, - 0xa190, 0x0007, 0xa294, 0x1ff8, 0x8214, 0x8214, 0x8214, 0x2001, - 0x020a, 0x82ff, 0x0140, 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, - 0x200c, 0x8211, 0x1dd0, 0x20e1, 0x7000, 0x200c, 0x200c, 0x7003, - 0x0000, 0x20e1, 0x6000, 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, - 0x2004, 0xa106, 0x0158, 0x080c, 0x1dee, 0x0130, 0x7908, 0xd1ec, - 0x1128, 0x790c, 0xd1a4, 0x0960, 0x080c, 0x1e1a, 0xa006, 0x002e, - 0x0005, 0x00f6, 0x00e6, 0x0016, 0x0026, 0x2071, 0xb924, 0x2079, - 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x01a8, 0x8211, - 0x0188, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0dc8, 0x7904, 0xa18c, - 0x0780, 0x0016, 0x080c, 0x1b22, 0x001e, 0x81ff, 0x1118, 0x2011, - 0x0050, 0x0c48, 0xa085, 0x0001, 0x002e, 0x001e, 0x00ee, 0x00fe, - 0x0005, 0x7803, 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac, 0x0904, - 0x1fbd, 0x8109, 0x1dd0, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0003, - 0x0a0c, 0x151a, 0x080c, 0x2274, 0x00e6, 0x00f6, 0x2071, 0xb913, - 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, 0x0538, 0x7800, 0x0006, - 0x7820, 0x0006, 0x7830, 0x0006, 0x7834, 0x0006, 0x7838, 0x0006, - 0x783c, 0x0006, 0x7803, 0x0004, 0xe000, 0xe000, 0x2079, 0x0030, - 0x7804, 0xd0ac, 0x190c, 0x151a, 0x2079, 0x0010, 0x000e, 0x783e, - 0x000e, 0x783a, 0x000e, 0x7836, 0x000e, 0x7832, 0x000e, 0x7822, - 0x000e, 0x7802, 0x00fe, 0x00ee, 0x0030, 0x00fe, 0x00ee, 0x7804, - 0xd0ac, 0x190c, 0x151a, 0x080c, 0x72a2, 0x0005, 0x00e6, 0x2071, - 0xb94b, 0x7003, 0x0000, 0x00ee, 0x0005, 0x00d6, 0xa280, 0x0004, - 0x206c, 0x694c, 0xd1dc, 0x1904, 0x203b, 0x6934, 0xa184, 0x0007, - 0x0002, 0x1fd9, 0x2026, 0x1fd9, 0x1fd9, 0x1fd9, 0x200d, 0x1fec, - 0x1fdb, 0x080c, 0x151a, 0x684c, 0xd0b4, 0x0904, 0x212a, 0x6860, - 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, - 0x680e, 0x6958, 0x0804, 0x202e, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x001e, 0x1d38, 0x684c, 0xd0b4, 0x0904, 0x212a, 0x6860, 0x682e, - 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, - 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, - 0x2308, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c, 0x00ff, 0xa186, - 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x212a, 0x6804, 0x681a, - 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x2308, 0x2005, - 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088, 0x684c, 0xd0b4, - 0x0904, 0x1afd, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, - 0x6834, 0xa084, 0x000f, 0xa080, 0x2308, 0x2005, 0x6832, 0x6926, - 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6, 0x2079, 0x0020, - 0x7804, 0xd0fc, 0x190c, 0x216d, 0x00e6, 0x00d6, 0x2071, 0xb94b, - 0x7000, 0xa005, 0x1904, 0x20aa, 0x00c6, 0x7206, 0xa280, 0x0004, - 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x00d6, 0x2068, - 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, 0x9040, 0x2079, 0x0200, - 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0x00de, 0x2b68, - 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, - 0x000f, 0x6908, 0x791a, 0x7116, 0x680c, 0x781e, 0x701a, 0xa006, - 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x1120, 0x6928, - 0x6810, 0xa106, 0x0190, 0x2001, 0xb674, 0x2004, 0xd0cc, 0x0110, - 0x00ce, 0x0400, 0x0036, 0x0046, 0x6b14, 0x6c10, 0x080c, 0x2328, - 0x004e, 0x003e, 0x0110, 0x00ce, 0x00a8, 0x8aff, 0x1120, 0x00ce, - 0xa085, 0x0001, 0x0078, 0x0126, 0x2091, 0x8000, 0x2079, 0x0020, - 0x2009, 0x0001, 0x0059, 0x0118, 0x2009, 0x0001, 0x0039, 0x012e, - 0x00ce, 0xa006, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0076, 0x0066, - 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x2123, 0x700c, - 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0a04, 0x2122, 0xa705, - 0x0904, 0x2122, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11a8, 0x00d6, - 0x2805, 0xac68, 0x2900, 0x0002, 0x2105, 0x20ea, 0x20ea, 0x2105, - 0x2105, 0x20fe, 0x2105, 0x20ea, 0x2105, 0x20ef, 0x20ef, 0x2105, - 0x2105, 0x2105, 0x20f6, 0x20ef, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, - 0x6d1c, 0x6c20, 0xd99c, 0x0528, 0x00d6, 0x2805, 0xac68, 0x6f08, - 0x6e0c, 0x00f0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10, - 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6, - 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1138, 0x00de, 0x080c, - 0x22ca, 0x1904, 0x20b4, 0xa00e, 0x00f0, 0x00de, 0x080c, 0x151a, - 0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, - 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, - 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x080c, - 0x22ca, 0x0008, 0xa006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e, - 0x007e, 0x0005, 0x080c, 0x151a, 0x0026, 0x2001, 0x0105, 0x2003, - 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, - 0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0118, 0x6850, - 0xc0bd, 0x6852, 0x601c, 0xa086, 0x0006, 0x1180, 0x2061, 0x0100, - 0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0xa206, 0x1dc0, - 0x60c4, 0x686a, 0x60c8, 0x6866, 0x7004, 0x2060, 0x00de, 0x00c6, - 0x080c, 0x99e6, 0x00ce, 0x2001, 0xb8f0, 0x2004, 0xac06, 0x1150, - 0x20e1, 0x9040, 0x080c, 0x82e4, 0x2011, 0x0000, 0x080c, 0x8106, - 0x080c, 0x72a2, 0x002e, 0x0804, 0x2227, 0x0126, 0x2091, 0x2400, - 0x0006, 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, - 0x2071, 0xb94b, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, - 0xa184, 0x0700, 0x1904, 0x212c, 0x7000, 0x0002, 0x2227, 0x218a, - 0x21fa, 0x2225, 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, - 0x2009, 0x0001, 0x080c, 0x20ae, 0x0904, 0x2227, 0x2009, 0x0001, - 0x080c, 0x20ae, 0x0804, 0x2227, 0x7803, 0x0004, 0xd194, 0x0148, - 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, - 0x00b8, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, - 0x7824, 0x6872, 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, - 0x6a2e, 0x003e, 0x002e, 0x080c, 0x22e0, 0x6850, 0xc0fd, 0x6852, - 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, - 0x0804, 0x2227, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, - 0x2079, 0x0100, 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, - 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x151a, 0x7820, 0xd0bc, - 0x1dd0, 0x003e, 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, - 0x79c4, 0x000e, 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, - 0xa085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, - 0x0000, 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, - 0x1904, 0x217d, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, - 0x080c, 0x20ae, 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, - 0x22e0, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, - 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, - 0x00de, 0x0804, 0x21ad, 0x0804, 0x21a9, 0x080c, 0x151a, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, - 0x00e6, 0x2071, 0xb94b, 0x7000, 0xa086, 0x0000, 0x05d0, 0x2079, - 0x0020, 0x0016, 0x2009, 0x0207, 0x210c, 0xd194, 0x0198, 0x2009, - 0x020c, 0x210c, 0xa184, 0x0003, 0x0168, 0x080c, 0xb50c, 0x2001, - 0x0133, 0x2004, 0xa005, 0x090c, 0x151a, 0x20e1, 0x9040, 0x2001, - 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, - 0xa106, 0x1110, 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x09d8, 0x080c, - 0x216d, 0x7000, 0xa086, 0x0000, 0x19a8, 0x001e, 0x7803, 0x0004, - 0x7804, 0xd0ac, 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, - 0x0000, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x2071, 0xb94b, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, - 0x0540, 0x7004, 0x2060, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0158, - 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, - 0x7a18, 0xa206, 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, - 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, - 0x99e6, 0x20e1, 0x9040, 0x080c, 0x82e4, 0x2011, 0x0000, 0x080c, - 0x8106, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, - 0x6a14, 0xa205, 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, - 0x1fc5, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, - 0x0004, 0x7003, 0x0000, 0x2069, 0xb8e1, 0x6833, 0x0000, 0x683f, - 0x0000, 0x08f8, 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, - 0x0168, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x2308, - 0x2045, 0x88ff, 0x090c, 0x151a, 0x8a51, 0x0005, 0x2050, 0x0005, - 0x8a50, 0x8841, 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, - 0x6000, 0xa005, 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, - 0x000f, 0xa080, 0x2318, 0x2045, 0x88ff, 0x090c, 0x151a, 0x0005, - 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, - 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, - 0x0000, 0x22fd, 0x22f9, 0x0000, 0x0000, 0x2307, 0x0000, 0x22fd, - 0x0000, 0x2304, 0x2301, 0x0000, 0x0000, 0x0000, 0x2307, 0x2304, - 0x0000, 0x22ff, 0x22ff, 0x0000, 0x0000, 0x2307, 0x0000, 0x22ff, - 0x0000, 0x2305, 0x2305, 0x0000, 0x0000, 0x0000, 0x2307, 0x2305, - 0x00a6, 0x0096, 0x0086, 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0904, - 0x23b9, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2308, 0xa986, - 0x0007, 0x0130, 0xa986, 0x000e, 0x0118, 0xa986, 0x000f, 0x1120, - 0x605c, 0xa422, 0x6060, 0xa31b, 0x2805, 0xa045, 0x1140, 0x0310, - 0x0804, 0x23b9, 0x6004, 0xa065, 0x0904, 0x23b9, 0x0c18, 0x2805, - 0xa005, 0x01a8, 0xac68, 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, - 0xa31b, 0x0020, 0x6810, 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, - 0xa405, 0x0150, 0x8a51, 0x0904, 0x23b9, 0x8840, 0x0c40, 0x6004, - 0xa065, 0x0904, 0x23b9, 0x0830, 0x8a51, 0x0904, 0x23b9, 0x8840, - 0x2805, 0xa005, 0x1158, 0x6004, 0xa065, 0x0904, 0x23b9, 0x6034, - 0xa0cc, 0x000f, 0xa9c0, 0x2308, 0x2805, 0x2040, 0x2b68, 0x6850, - 0xc0fc, 0x6852, 0x0458, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, - 0x00d6, 0x2b68, 0x6c6e, 0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, - 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x0a0c, 0x151a, 0x6800, - 0xa420, 0x6804, 0xa319, 0x0060, 0x6910, 0x2400, 0xa122, 0x6914, - 0x2300, 0xa11b, 0x0a0c, 0x151a, 0x6800, 0xa420, 0x6804, 0xa319, - 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, - 0x2800, 0x6832, 0x2a00, 0x6826, 0x000e, 0x000e, 0x000e, 0xa006, - 0x0028, 0x008e, 0x009e, 0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, - 0x0005, 0x2004, 0xa084, 0x0007, 0x0002, 0x23cd, 0x23ce, 0x23d1, - 0x23d4, 0x23d9, 0x23dc, 0x23e1, 0x23e6, 0x0005, 0x080c, 0x216d, - 0x0005, 0x080c, 0x1b22, 0x0005, 0x080c, 0x1b22, 0x080c, 0x216d, - 0x0005, 0x080c, 0x1720, 0x0005, 0x080c, 0x216d, 0x080c, 0x1720, - 0x0005, 0x080c, 0x1b22, 0x080c, 0x1720, 0x0005, 0x080c, 0x1b22, - 0x080c, 0x216d, 0x080c, 0x1720, 0x0005, 0x0006, 0x7000, 0xa086, - 0x0001, 0x1158, 0x701c, 0xa506, 0x1140, 0x7020, 0xa406, 0x1128, - 0x7024, 0xa706, 0x1110, 0x7028, 0xa606, 0x000e, 0x0005, 0x0126, - 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0xbc80, 0x2069, 0xb600, - 0x080c, 0x24f5, 0x080c, 0x24e5, 0x2009, 0x0004, 0x7912, 0x7817, - 0x0004, 0x080c, 0x282d, 0x781b, 0x0002, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x20a9, 0x0080, 0x782f, 0x0000, 0x1f04, 0x241b, 0x20e1, - 0x9080, 0x783b, 0x001f, 0x20e1, 0x8700, 0x012e, 0x0005, 0x0126, - 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, 0x24e2, 0xa084, 0x0007, - 0x0002, 0x244b, 0x2439, 0x243c, 0x243f, 0x2444, 0x2446, 0x2448, - 0x244a, 0x080c, 0x6436, 0x0078, 0x080c, 0x6475, 0x0060, 0x080c, - 0x6436, 0x080c, 0x6475, 0x0038, 0x0041, 0x0028, 0x0031, 0x0018, - 0x0021, 0x0008, 0x0011, 0x012e, 0x0005, 0x0006, 0x0016, 0x0026, - 0x080c, 0xb50c, 0x7930, 0xa184, 0x0003, 0x01b0, 0x2001, 0xb8f0, - 0x2004, 0xa005, 0x0170, 0x2001, 0x0133, 0x2004, 0xa005, 0x090c, - 0x151a, 0x00c6, 0x2001, 0xb8f0, 0x2064, 0x080c, 0x99e6, 0x00ce, - 0x04b8, 0x20e1, 0x9040, 0x04a0, 0xa184, 0x0030, 0x01e0, 0x6a00, - 0xa286, 0x0003, 0x1108, 0x00a0, 0x080c, 0x5b41, 0x1178, 0x2001, - 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, - 0x0001, 0x080c, 0x5b85, 0x080c, 0x5a79, 0x0010, 0x080c, 0x4b7b, - 0x080c, 0x24e5, 0x00a8, 0xa184, 0x00c0, 0x0168, 0x00e6, 0x0036, - 0x0046, 0x0056, 0x2071, 0xb924, 0x080c, 0x1e1a, 0x005e, 0x004e, - 0x003e, 0x00ee, 0x0028, 0xa184, 0x0300, 0x0110, 0x20e1, 0x9020, - 0x7932, 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, 0x00e6, 0x00f6, - 0x2071, 0xb600, 0x7128, 0x2001, 0xb891, 0x2102, 0x2001, 0xb899, - 0x2102, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, - 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, - 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, - 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, - 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x2079, - 0x0200, 0x7912, 0x7817, 0x0004, 0x080c, 0x282d, 0x00fe, 0x00ee, - 0x001e, 0x0005, 0x7938, 0x080c, 0x151a, 0x00e6, 0x0026, 0x2071, - 0x0200, 0x20e1, 0x1000, 0x7220, 0x7028, 0x7020, 0xa206, 0x0de0, - 0x20e1, 0x9010, 0x002e, 0x00ee, 0x0005, 0x20e1, 0xa000, 0x7837, - 0x0001, 0x782f, 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, 0x782f, - 0x0000, 0x7837, 0x0005, 0x20a9, 0x0210, 0x7830, 0xd0bc, 0x1110, - 0x1f04, 0x2505, 0x7837, 0x0001, 0x7837, 0x0000, 0xe000, 0xe000, - 0x20e1, 0xa000, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, - 0x2071, 0xb600, 0x6024, 0x6026, 0x6053, 0x0030, 0x080c, 0x286c, - 0x6050, 0xa084, 0xfe7f, 0x6052, 0x2009, 0x00ef, 0x6132, 0x6136, - 0x080c, 0x287c, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, - 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, - 0x0e9f, 0x601b, 0x001e, 0x600f, 0x00ff, 0x2001, 0xb88d, 0x2003, - 0x00ff, 0x602b, 0x002f, 0x012e, 0x0005, 0x2001, 0xb632, 0x2003, - 0x0000, 0x2001, 0xb631, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091, - 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0xa184, 0x1e2c, 0x1118, - 0xa184, 0x0007, 0x002a, 0xa195, 0x0004, 0xa284, 0x0007, 0x0002, - 0x2582, 0x2568, 0x256b, 0x256e, 0x2573, 0x2575, 0x2579, 0x257d, - 0x080c, 0x6be6, 0x00b8, 0x080c, 0x6cc1, 0x00a0, 0x080c, 0x6cc1, - 0x080c, 0x6be6, 0x0078, 0x0099, 0x0068, 0x080c, 0x6be6, 0x0079, - 0x0048, 0x080c, 0x6cc1, 0x0059, 0x0028, 0x080c, 0x6cc1, 0x080c, - 0x6be6, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x6124, - 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, 0x279b, 0x080c, 0x5b41, - 0x0578, 0x7000, 0xa086, 0x0003, 0x0198, 0x6024, 0xa084, 0x1800, - 0x0178, 0x080c, 0x5b67, 0x0118, 0x080c, 0x5b53, 0x1148, 0x6027, - 0x0020, 0x6043, 0x0000, 0x2001, 0xb89e, 0x2003, 0xaaaa, 0x0458, - 0x080c, 0x5b67, 0x15d0, 0x6024, 0xa084, 0x1800, 0x1108, 0x04a8, - 0x2001, 0xb89e, 0x2003, 0xaaaa, 0x2001, 0xb89f, 0x2003, 0x0001, - 0x2001, 0xb600, 0x2003, 0x0001, 0x080c, 0x5a79, 0x0804, 0x279b, - 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1188, 0xd0d4, - 0x11a0, 0xd0cc, 0x0130, 0x708c, 0xa086, 0x0028, 0x1110, 0x080c, - 0x5cd0, 0x0804, 0x279b, 0x2001, 0xb89f, 0x2003, 0x0000, 0x0048, - 0x2001, 0xb89f, 0x2003, 0x0002, 0x0020, 0x080c, 0x5c43, 0x0804, - 0x279b, 0x080c, 0x5d75, 0x0804, 0x279b, 0xd1ac, 0x0904, 0x26e3, - 0x080c, 0x5b41, 0x11d8, 0x6027, 0x0020, 0x0006, 0x0026, 0x0036, - 0x080c, 0x5b5d, 0x1170, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, - 0xb600, 0x2003, 0x0001, 0x080c, 0x5a79, 0x003e, 0x002e, 0x000e, - 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x5b18, 0x0016, 0x0046, - 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, - 0x6043, 0x0090, 0x6043, 0x0010, 0x74ce, 0xa48c, 0xff00, 0x7034, - 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x703c, 0xd084, 0x1148, - 0xc085, 0x703e, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x3f13, - 0x003e, 0xa196, 0xff00, 0x05b8, 0x7054, 0xa084, 0x00ff, 0x810f, - 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, 0x2011, 0xb653, 0x2214, - 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xb653, 0x2214, 0xd2ac, - 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, 0x6248, 0xa294, 0xff00, - 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, 0x26b0, 0x7034, - 0xd08c, 0x1140, 0x2001, 0xb60c, 0x200c, 0xd1ac, 0x1904, 0x26b0, - 0xc1ad, 0x2102, 0x0036, 0x73cc, 0x2011, 0x8013, 0x080c, 0x3f13, - 0x003e, 0x0804, 0x26b0, 0x7034, 0xd08c, 0x1140, 0x2001, 0xb60c, - 0x200c, 0xd1ac, 0x1904, 0x26b0, 0xc1ad, 0x2102, 0x0036, 0x73cc, - 0x2011, 0x8013, 0x080c, 0x3f13, 0x003e, 0x7130, 0xc185, 0x7132, - 0x2011, 0xb653, 0x220c, 0xd1a4, 0x01d0, 0x0016, 0x2009, 0x0001, - 0x2011, 0x0100, 0x080c, 0x6b8c, 0x2019, 0x000e, 0x080c, 0xb121, - 0xa484, 0x00ff, 0xa080, 0x2df9, 0x200d, 0xa18c, 0xff00, 0x810f, - 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0xb1a4, 0x001e, 0xd1ac, - 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, 0x2ca4, - 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0x080c, - 0x501b, 0x1110, 0x080c, 0x4c7e, 0x8108, 0x1f04, 0x26a7, 0x015e, - 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, - 0x080c, 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c, - 0x806b, 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0xb600, 0x2014, - 0xa296, 0x0004, 0x1128, 0xd19c, 0x11b0, 0x6228, 0xc29d, 0x622a, - 0x2003, 0x0001, 0x2001, 0xb623, 0x2003, 0x0000, 0x6027, 0x0020, - 0x080c, 0x5b67, 0x1140, 0x0016, 0x2009, 0x07d0, 0x2011, 0x5a56, - 0x080c, 0x6a94, 0x001e, 0xd194, 0x0904, 0x279b, 0x0016, 0x6220, - 0xd2b4, 0x0904, 0x274c, 0x080c, 0x6a82, 0x080c, 0x7df3, 0x6027, - 0x0004, 0x00f6, 0x2019, 0xb8ea, 0x2304, 0xa07d, 0x0570, 0x7804, - 0xa086, 0x0032, 0x1550, 0x00d6, 0x00c6, 0x00e6, 0x2069, 0x0140, - 0x618c, 0x6288, 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, 0x0002, - 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x6803, 0x1000, - 0x6803, 0x0000, 0x618e, 0x628a, 0x080c, 0x7102, 0x080c, 0x71e5, - 0x7810, 0x2070, 0x7037, 0x0103, 0x2f60, 0x080c, 0x86a4, 0x00ee, - 0x00ce, 0x00de, 0x00fe, 0x001e, 0x0005, 0x00fe, 0x00d6, 0x2069, - 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, 0x6803, - 0x0000, 0x00de, 0x00c6, 0x2061, 0xb8e1, 0x6028, 0xa09a, 0x00c8, - 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x7de6, 0x0804, 0x279a, - 0x2019, 0xb8ea, 0x2304, 0xa065, 0x0120, 0x2009, 0x0027, 0x080c, - 0x86d3, 0x00ce, 0x0804, 0x279a, 0xd2bc, 0x0904, 0x279a, 0x080c, - 0x6a8f, 0x6014, 0xa084, 0x0184, 0xa085, 0x0010, 0x6016, 0x6027, - 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, - 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0xb8e1, - 0x6044, 0xa09a, 0x00c8, 0x12f0, 0x8000, 0x6046, 0x603c, 0x00ce, - 0xa005, 0x0540, 0x2009, 0x07d0, 0x080c, 0x6a87, 0xa080, 0x0007, - 0x2004, 0xa086, 0x0006, 0x1138, 0x6114, 0xa18c, 0x0184, 0xa18d, - 0x0012, 0x6116, 0x00b8, 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0016, - 0x6116, 0x0080, 0x0036, 0x2019, 0x0001, 0x080c, 0x806b, 0x003e, - 0x2019, 0xb8f0, 0x2304, 0xa065, 0x0120, 0x2009, 0x004f, 0x080c, - 0x86d3, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x27f4, 0x7034, 0xd0ac, - 0x1560, 0x0016, 0x0156, 0x6027, 0x0008, 0x602f, 0x0020, 0x20a9, - 0x0006, 0x1d04, 0x27a9, 0x2091, 0x6000, 0x1f04, 0x27a9, 0x602f, - 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, 0x0366, 0x1d04, - 0x27b7, 0x2091, 0x6000, 0x6020, 0xd09c, 0x1130, 0x015e, 0x6152, - 0x001e, 0x6027, 0x0008, 0x0480, 0x080c, 0x293c, 0x1f04, 0x27b7, - 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, 0xc09c, - 0x602a, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, - 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c, 0x806b, - 0x003e, 0x60e3, 0x0000, 0x080c, 0xb4eb, 0x080c, 0xb506, 0xa085, - 0x0001, 0x080c, 0x5b85, 0x2001, 0xb600, 0x2003, 0x0004, 0x6027, - 0x0008, 0x080c, 0x12e2, 0x001e, 0xa18c, 0xffd0, 0x6126, 0x0005, - 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, - 0x2071, 0xb600, 0x71c4, 0x70c6, 0xa116, 0x0500, 0x81ff, 0x0128, - 0x2011, 0x8011, 0x080c, 0x3f13, 0x00c8, 0x2011, 0x8012, 0x080c, - 0x3f13, 0x2001, 0xb672, 0x2004, 0xd0fc, 0x1180, 0x0036, 0x00c6, - 0x080c, 0x28c7, 0x080c, 0x7fbc, 0x2061, 0x0100, 0x2019, 0x0028, - 0x2009, 0x0000, 0x080c, 0x2ca4, 0x00ce, 0x003e, 0x012e, 0x00fe, - 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x00c6, 0x00f6, 0x0006, - 0x0026, 0x2061, 0x0100, 0xa190, 0x2840, 0x2205, 0x60f2, 0x2011, - 0x284d, 0x2205, 0x60ee, 0x002e, 0x000e, 0x00fe, 0x00ce, 0x0005, - 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0, 0x0258, - 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8, 0x00d0, - 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094, 0xff00, - 0x1110, 0x81ff, 0x0118, 0x080c, 0x6723, 0x0038, 0xa080, 0x2df9, - 0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, 0x0005, 0xa080, 0x2df9, - 0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, - 0xb615, 0x2003, 0x00ef, 0x20a9, 0x0010, 0xa006, 0x6852, 0x6856, - 0x1f04, 0x2877, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, - 0x0140, 0x2001, 0xb615, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, - 0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, 0x82ff, 0x1128, 0xa184, - 0x000f, 0xa080, 0xb51a, 0x2005, 0x6856, 0x8211, 0x1f04, 0x288c, - 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0xb600, 0x6030, - 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, - 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0xa116, - 0x0180, 0xa112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, - 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x28bc, 0x680f, - 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x2001, - 0xb653, 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, - 0x2020, 0x2009, 0x002e, 0x080c, 0xb1a4, 0x004e, 0x0005, 0x00f6, - 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0548, 0xa084, - 0x0700, 0xa08e, 0x0300, 0x1520, 0x2011, 0x0000, 0x2009, 0x0002, - 0x2300, 0xa080, 0x0020, 0x2018, 0x2300, 0x080c, 0x6bb2, 0x2011, - 0x0030, 0x2200, 0x8007, 0xa085, 0x004c, 0x78c2, 0x2009, 0x0204, - 0x210c, 0x2200, 0xa100, 0x2009, 0x0138, 0x200a, 0x080c, 0x5b41, - 0x1118, 0x2009, 0xb88f, 0x200a, 0x002e, 0x001e, 0x00fe, 0x0005, - 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, - 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0xa184, 0x0003, - 0x0110, 0x0804, 0x1b20, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, - 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, 0x0268, - 0x2001, 0x0170, 0x200c, 0xa18c, 0x00ff, 0xa18e, 0x004c, 0x1128, - 0x200c, 0xa18c, 0xff00, 0x810f, 0x0010, 0x2009, 0x0000, 0x2001, - 0x0204, 0x2004, 0xa108, 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, - 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2943, - 0x00fe, 0x015e, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, - 0x0100, 0x6030, 0x0006, 0x6048, 0x0006, 0x60e4, 0x0006, 0x60e8, - 0x0006, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, - 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x60e0, 0x0006, 0x602f, - 0x0100, 0x602f, 0x0000, 0xe000, 0xe000, 0xe000, 0xe000, 0x602f, - 0x0040, 0x602f, 0x0000, 0x000e, 0x60e2, 0x000e, 0x602a, 0x000e, - 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x000e, - 0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, 0x000e, 0x604a, 0x000e, - 0x6032, 0x6036, 0x2008, 0x080c, 0x287c, 0x000e, 0x00ce, 0x001e, - 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170, - 0x2104, 0x200b, 0x0080, 0xe000, 0xe000, 0x200a, 0x0005, 0x2a2f, - 0x2a33, 0x2a37, 0x2a3d, 0x2a43, 0x2a49, 0x2a4f, 0x2a57, 0x2a5f, - 0x2a65, 0x2a6b, 0x2a73, 0x2a7b, 0x2a83, 0x2a8b, 0x2a95, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2aa1, - 0x2aa1, 0x2aa7, 0x2aa7, 0x2aae, 0x2aae, 0x2ab5, 0x2ab5, 0x2abe, - 0x2abe, 0x2ac5, 0x2ac5, 0x2ace, 0x2ace, 0x2ad7, 0x2ad7, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, - 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, - 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x0106, - 0x0006, 0x0804, 0x2aea, 0x0106, 0x0006, 0x0804, 0x2aea, 0x0106, - 0x0006, 0x080c, 0x254e, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, - 0x254e, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x0804, - 0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x0804, 0x2aea, 0x0106, - 0x0006, 0x080c, 0x254e, 0x080c, 0x23bf, 0x0804, 0x2aea, 0x0106, - 0x0006, 0x080c, 0x254e, 0x080c, 0x23bf, 0x0804, 0x2aea, 0x0106, - 0x0006, 0x080c, 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, - 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x254e, 0x080c, - 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x254e, 0x080c, - 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x080c, - 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x080c, - 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x254e, 0x080c, - 0x23bf, 0x080c, 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, - 0x254e, 0x080c, 0x23bf, 0x080c, 0x2427, 0x0804, 0x2aea, 0xe000, - 0x0cf0, 0x0106, 0x0006, 0x080c, 0x290b, 0x0804, 0x2aea, 0x0106, - 0x0006, 0x080c, 0x290b, 0x080c, 0x254e, 0x04e0, 0x0106, 0x0006, - 0x080c, 0x290b, 0x080c, 0x23bf, 0x04a8, 0x0106, 0x0006, 0x080c, - 0x290b, 0x080c, 0x254e, 0x080c, 0x23bf, 0x0460, 0x0106, 0x0006, - 0x080c, 0x290b, 0x080c, 0x2427, 0x0428, 0x0106, 0x0006, 0x080c, - 0x290b, 0x080c, 0x254e, 0x080c, 0x2427, 0x00e0, 0x0106, 0x0006, - 0x080c, 0x290b, 0x080c, 0x23bf, 0x080c, 0x2427, 0x0098, 0x0106, - 0x0006, 0x080c, 0x290b, 0x080c, 0x254e, 0x080c, 0x23bf, 0x080c, - 0x2427, 0x0040, 0x20d1, 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, - 0x080c, 0x151a, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, 0x0046, - 0x2021, 0x0000, 0x080c, 0x537b, 0x1904, 0x2bca, 0x72d4, 0x2001, - 0xb89e, 0x2004, 0xa005, 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, - 0xd2bc, 0x1904, 0x2bca, 0x080c, 0x2bce, 0x0804, 0x2bca, 0xd2cc, - 0x1904, 0x2bca, 0x080c, 0x5b41, 0x1120, 0x709f, 0xffff, 0x0804, - 0x2bca, 0xd294, 0x0120, 0x709f, 0xffff, 0x0804, 0x2bca, 0x2001, - 0xb615, 0x203c, 0x7288, 0xd284, 0x0904, 0x2b6c, 0xd28c, 0x1904, - 0x2b6c, 0x0036, 0x739c, 0xa38e, 0xffff, 0x1110, 0x2019, 0x0001, - 0x8314, 0xa2e0, 0xbdc0, 0x2c04, 0xa38c, 0x0001, 0x0120, 0xa084, - 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa70e, 0x0560, 0xa08e, - 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, 0x7230, 0xd284, 0x1538, - 0x7288, 0xc28d, 0x728a, 0x709f, 0xffff, 0x003e, 0x0428, 0x2009, - 0x0000, 0x080c, 0x2852, 0x080c, 0x4fbf, 0x11b8, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, 0xd08c, 0x0118, 0x6000, - 0xd0bc, 0x0120, 0x080c, 0x2be1, 0x0140, 0x0028, 0x080c, 0x2d12, - 0x080c, 0x2c0f, 0x0110, 0x8318, 0x0818, 0x739e, 0x0010, 0x709f, - 0xffff, 0x003e, 0x0804, 0x2bca, 0xa780, 0x2df9, 0x203d, 0xa7bc, - 0xff00, 0x873f, 0x2041, 0x007e, 0x709c, 0xa096, 0xffff, 0x1120, - 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, 0x0220, 0x2008, 0xa802, - 0x20a8, 0x0020, 0x709f, 0xffff, 0x0804, 0x2bca, 0x2700, 0x0156, - 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, 0x501b, 0x0120, 0x080c, - 0x4fbf, 0x15a8, 0x0008, 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086, - 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, 0x6000, 0xd0bc, 0x11d0, - 0x7288, 0xd28c, 0x0188, 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, - 0x02b0, 0xd484, 0x1118, 0x080c, 0x4fde, 0x0028, 0x080c, 0x2d9f, - 0x0170, 0x080c, 0x2dcc, 0x0058, 0x080c, 0x2d12, 0x080c, 0x2c0f, - 0x0170, 0x0028, 0x080c, 0x2d9f, 0x0110, 0x0419, 0x0140, 0x001e, - 0x8108, 0x015e, 0x1f04, 0x2b86, 0x709f, 0xffff, 0x0018, 0x001e, - 0x015e, 0x719e, 0x004e, 0x002e, 0x00ce, 0x0005, 0x00c6, 0x0016, - 0x709f, 0x0001, 0x2009, 0x007e, 0x080c, 0x4fbf, 0x1138, 0x080c, - 0x2d12, 0x04a9, 0x0118, 0x70d4, 0xc0bd, 0x70d6, 0x001e, 0x00ce, - 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xb657, - 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9f92, 0x01d8, 0x2d00, - 0x601a, 0x080c, 0xa0e3, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, - 0x4f5d, 0x2001, 0x0000, 0x080c, 0x4f6f, 0x0126, 0x2091, 0x8000, - 0x7098, 0x8000, 0x709a, 0x012e, 0x2009, 0x0004, 0x080c, 0x86d3, - 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, - 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xb657, 0x2004, 0xa084, - 0x00ff, 0x6842, 0x080c, 0x9f92, 0x0550, 0x2d00, 0x601a, 0x6800, - 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, 0x0140, 0x6804, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, 0x2cd1, 0x080c, 0xa0e3, - 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002, - 0x080c, 0x4f6f, 0x0126, 0x2091, 0x8000, 0x7098, 0x8000, 0x709a, - 0x012e, 0x2009, 0x0002, 0x080c, 0x86d3, 0xa085, 0x0001, 0x00ce, - 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, 0x0080, - 0x080c, 0x4fbf, 0x1120, 0x0031, 0x0110, 0x70db, 0xffff, 0x002e, - 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, - 0x864e, 0x01e8, 0x2d00, 0x601a, 0x080c, 0xa0e3, 0x601f, 0x0001, - 0x2001, 0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, - 0x0126, 0x2091, 0x8000, 0x080c, 0x2cd1, 0x70dc, 0x8000, 0x70de, - 0x012e, 0x2009, 0x0002, 0x080c, 0x86d3, 0xa085, 0x0001, 0x00ce, - 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091, - 0x8000, 0x2009, 0x007f, 0x080c, 0x4fbf, 0x1190, 0x2c68, 0x080c, - 0x864e, 0x0170, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, - 0x080c, 0xa0e3, 0x2009, 0x0022, 0x080c, 0x86d3, 0xa085, 0x0001, - 0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, - 0x0026, 0x080c, 0x6e73, 0x080c, 0x6e16, 0x080c, 0x90fb, 0x2130, - 0x81ff, 0x0128, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0020, 0x20a9, - 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x501b, 0x1120, 0x080c, - 0x521c, 0x080c, 0x4c7e, 0x001e, 0x8108, 0x1f04, 0x2cbb, 0x86ff, - 0x1110, 0x080c, 0x11f5, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, - 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, 0x2270, - 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x6e67, 0x0076, 0x2039, - 0x0000, 0x080c, 0x6d74, 0x2c08, 0x080c, 0xaf3e, 0x007e, 0x001e, - 0x2e60, 0x080c, 0x521c, 0x6210, 0x6314, 0x080c, 0x4c7e, 0x6212, - 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, - 0x0006, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x0080, 0x0150, - 0x2071, 0xb600, 0x7098, 0xa005, 0x0110, 0x8001, 0x709a, 0x000e, - 0x00ee, 0x0005, 0x2071, 0xb600, 0x70dc, 0xa005, 0x0dc0, 0x8001, - 0x70de, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6, - 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, - 0x20a9, 0x0001, 0x0098, 0x2001, 0xb653, 0x2004, 0xd0c4, 0x0150, - 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002d, 0x080c, - 0xb1a4, 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x0026, 0xa28e, - 0x007e, 0x0904, 0x2d7e, 0xa28e, 0x007f, 0x0904, 0x2d7e, 0xa28e, - 0x0080, 0x05e0, 0xa288, 0xb735, 0x210c, 0x81ff, 0x05b8, 0x8fff, - 0x1148, 0x2001, 0xb8be, 0x0006, 0x2003, 0x0001, 0x04d9, 0x000e, - 0x2003, 0x0000, 0x00c6, 0x2160, 0x2001, 0x0001, 0x080c, 0x5385, - 0x00ce, 0x2019, 0x0029, 0x080c, 0x6e67, 0x0076, 0x2039, 0x0000, - 0x080c, 0x6d74, 0x00c6, 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, - 0xa286, 0x0006, 0x1118, 0x6007, 0x0404, 0x0028, 0x2001, 0x0004, - 0x8007, 0xa215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, - 0xaf3e, 0x001e, 0x007e, 0x2160, 0x080c, 0x521c, 0x002e, 0x8210, - 0x1f04, 0x2d36, 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, - 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x2001, 0xb653, 0x2004, - 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0xa006, 0x2220, 0x8427, 0x2009, - 0x0029, 0x080c, 0xb1a4, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016, - 0x0026, 0x0036, 0x00c6, 0x7288, 0x82ff, 0x01f8, 0x2011, 0xb653, - 0x2214, 0xd2ac, 0x11d0, 0x2100, 0x080c, 0x2866, 0x81ff, 0x01b8, - 0x2019, 0x0001, 0x8314, 0xa2e0, 0xbdc0, 0x2c04, 0xd384, 0x0120, - 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa116, 0x0138, - 0xa096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0xa085, 0x0001, 0x00ce, - 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, 0x0029, - 0x080c, 0x8320, 0x002e, 0x080c, 0xb449, 0x003e, 0x002e, 0x001e, - 0xa180, 0xb735, 0x2004, 0xa065, 0x0158, 0x0016, 0x00c6, 0x2061, - 0xb9f5, 0x001e, 0x611a, 0x080c, 0x2cd1, 0x001e, 0x080c, 0x4fde, - 0x012e, 0x00ce, 0x001e, 0x0005, 0x2001, 0xb635, 0x2004, 0xd0cc, - 0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, - 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, - 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, - 0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, - 0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, - 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, - 0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, - 0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, - 0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, - 0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, - 0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, - 0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, - 0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, - 0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, - 0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, - 0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, - 0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, - 0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, - 0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, - 0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, - 0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, - 0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, - 0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, - 0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, - 0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, - 0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, - 0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x2071, 0xb682, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, - 0x703a, 0x703e, 0x7033, 0xb692, 0x7037, 0xb692, 0x7007, 0x0001, - 0x2061, 0xb6d2, 0x6003, 0x0002, 0x0005, 0x1004, 0x2f1f, 0x0e04, - 0x2f1f, 0x2071, 0xb682, 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60, - 0x7820, 0xa08e, 0x0069, 0x1904, 0x3004, 0x0804, 0x2f9d, 0x0005, - 0x2071, 0xb682, 0x7004, 0x0002, 0x2f28, 0x2f29, 0x2f32, 0x2f43, - 0x0005, 0x1004, 0x2f31, 0x0e04, 0x2f31, 0x2b78, 0x7818, 0xd084, - 0x01e8, 0x0005, 0x2b78, 0x2061, 0xb6d2, 0x6008, 0xa08e, 0x0100, - 0x0128, 0xa086, 0x0200, 0x0904, 0x2ffe, 0x0005, 0x7014, 0x2068, - 0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, 0x6834, 0xa086, 0x0103, - 0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820, - 0xa08a, 0x0040, 0x1210, 0x61c4, 0x0042, 0x2100, 0xa08a, 0x003f, - 0x1a04, 0x2ffb, 0x61c4, 0x0804, 0x2f9d, 0x2fdf, 0x300a, 0x3012, - 0x3016, 0x301e, 0x3024, 0x3028, 0x3034, 0x3037, 0x3041, 0x3044, - 0x2ffb, 0x2ffb, 0x2ffb, 0x3047, 0x2ffb, 0x3056, 0x306d, 0x3084, - 0x30fe, 0x3103, 0x312c, 0x317d, 0x318e, 0x31ad, 0x31e5, 0x31ef, - 0x31fc, 0x320f, 0x3230, 0x3239, 0x326f, 0x3275, 0x2ffb, 0x329e, - 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x32a5, 0x32af, 0x2ffb, - 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x32b7, - 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x32c9, 0x32d3, 0x2ffb, - 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x0002, 0x32fd, 0x3351, - 0x33ac, 0x33c6, 0x2ffb, 0x33f7, 0x382a, 0x427a, 0x2ffb, 0x2ffb, - 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x3041, 0x3044, - 0x382c, 0x2ffb, 0x3839, 0x4313, 0x436e, 0x43d2, 0x2ffb, 0x4435, - 0x445f, 0x447e, 0x44b0, 0x2ffb, 0x2ffb, 0x2ffb, 0x383d, 0x39e2, - 0x39fc, 0x3a26, 0x3a87, 0x3ae7, 0x3af2, 0x3b2a, 0x3b39, 0x3b48, - 0x3b4b, 0x3b6e, 0x3bba, 0x3c34, 0x3c41, 0x3d42, 0x3e6a, 0x3e93, - 0x3f91, 0x3fb3, 0x3fbf, 0x3ff8, 0x40bc, 0x2ffb, 0x2ffb, 0x2ffb, - 0x2ffb, 0x4124, 0x413f, 0x41b1, 0x4263, 0x713c, 0x0000, 0x2021, - 0x4000, 0x080c, 0x3ef0, 0x0126, 0x2091, 0x8000, 0x0e04, 0x2feb, - 0x7818, 0xd084, 0x0110, 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a, - 0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, - 0x5000, 0x012e, 0x0005, 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002, - 0x0c00, 0x2021, 0x4003, 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021, - 0x4006, 0x08b8, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, - 0x0804, 0x3efd, 0x7823, 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520, - 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3f00, 0x7924, 0x7828, - 0x2114, 0x200a, 0x0804, 0x2fdf, 0x7924, 0x2114, 0x0804, 0x2fdf, - 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, - 0x7a28, 0x7b2c, 0x0804, 0x2fdf, 0x7824, 0x2060, 0x0090, 0x2009, - 0x0002, 0x2011, 0x0002, 0x2019, 0x0008, 0x783b, 0x0017, 0x0804, - 0x2fdf, 0x7d38, 0x7c3c, 0x0840, 0x7d38, 0x7c3c, 0x0888, 0x2061, - 0x1000, 0xe10c, 0xa006, 0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, - 0x2010, 0xa005, 0x0904, 0x2fdf, 0x0804, 0x3001, 0x2069, 0xb652, - 0x7824, 0x7930, 0xa11a, 0x1a04, 0x3007, 0x8019, 0x0904, 0x3007, - 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, - 0x685e, 0x080c, 0x5e17, 0x0804, 0x2fdf, 0x2069, 0xb652, 0x7824, - 0x7934, 0xa11a, 0x1a04, 0x3007, 0x8019, 0x0904, 0x3007, 0x684e, - 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, - 0x080c, 0x5447, 0x0804, 0x2fdf, 0xa02e, 0x2520, 0x81ff, 0x1904, - 0x3004, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xb689, - 0x41a1, 0x080c, 0x3ebc, 0x0904, 0x3004, 0x2009, 0x0020, 0x080c, - 0x3efd, 0x701b, 0x309c, 0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, - 0xa096, 0x0011, 0x0138, 0xa096, 0x0019, 0x0120, 0xa096, 0x0015, - 0x1904, 0x3004, 0x810f, 0xa18c, 0x00ff, 0x0904, 0x3004, 0x710e, - 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3ebc, 0x0904, 0x3004, - 0x2009, 0x0020, 0x2061, 0xb6d2, 0x6224, 0x6328, 0x642c, 0x6530, - 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, - 0x080c, 0x3efd, 0x701b, 0x30cd, 0x0005, 0x6834, 0xa084, 0x00ff, - 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904, 0x3004, 0x08c0, - 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x4ebb, 0x1128, - 0x7007, 0x0003, 0x701b, 0x30e7, 0x0005, 0x080c, 0x554d, 0x0126, - 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xb689, 0x530a, 0x2100, - 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, - 0x000d, 0x2009, 0x0020, 0x012e, 0x0804, 0x3f00, 0x61ac, 0x7824, - 0x60ae, 0x0804, 0x2fdf, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, - 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, - 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, - 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, - 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, - 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904, 0x3004, 0x7924, - 0x810f, 0xa18c, 0x00ff, 0x080c, 0x501b, 0x1904, 0x3007, 0x7e38, - 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804, 0x3007, 0x7c28, - 0x7d2c, 0x080c, 0x51e3, 0xd28c, 0x1118, 0x080c, 0x518c, 0x0010, - 0x080c, 0x51bc, 0x1518, 0x2061, 0xbe00, 0x0126, 0x2091, 0x8000, - 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d, 0x0130, 0x683c, - 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e, 0xace0, 0x0018, - 0x2001, 0xb617, 0x2004, 0xac02, 0x1a04, 0x3004, 0x0c30, 0x080c, - 0x99e6, 0x012e, 0x0904, 0x3004, 0x0804, 0x2fdf, 0xa00e, 0x2001, - 0x0005, 0x080c, 0x554d, 0x0126, 0x2091, 0x8000, 0x080c, 0x9f8e, - 0x080c, 0x547a, 0x012e, 0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004, - 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x50e1, 0x0904, 0x3004, - 0x080c, 0x51ef, 0x0904, 0x3004, 0x0804, 0x2fdf, 0x81ff, 0x1904, - 0x3004, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x080c, 0x525b, 0x0904, - 0x3004, 0x2019, 0x0005, 0x7924, 0x080c, 0x520a, 0x0904, 0x3004, - 0x7828, 0xa08a, 0x1000, 0x1a04, 0x3007, 0x8003, 0x800b, 0x810b, - 0xa108, 0x080c, 0x6a1a, 0x0804, 0x2fdf, 0x0126, 0x2091, 0x8000, - 0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x00ff, 0x6450, - 0x2400, 0xa506, 0x01f8, 0x2508, 0x080c, 0x501b, 0x11d8, 0x080c, - 0x525b, 0x1128, 0x2009, 0x0002, 0x62b4, 0x2518, 0x00c0, 0x2019, - 0x0004, 0xa00e, 0x080c, 0x520a, 0x1118, 0x2009, 0x0006, 0x0078, - 0x7824, 0xa08a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0xa108, - 0x080c, 0x6a1a, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x2fdf, 0x012e, - 0x0804, 0x3004, 0x012e, 0x0804, 0x3007, 0x080c, 0x3ed1, 0x0904, - 0x3007, 0x080c, 0x5147, 0x080c, 0x51e3, 0x0804, 0x2fdf, 0x81ff, - 0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x5138, - 0x080c, 0x51e3, 0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004, 0x080c, - 0x3ed1, 0x0904, 0x3007, 0x080c, 0x51be, 0x0904, 0x3004, 0x080c, - 0x4eff, 0x080c, 0x5185, 0x080c, 0x51e3, 0x0804, 0x2fdf, 0x080c, - 0x3ed1, 0x0904, 0x3007, 0x080c, 0x50e1, 0x0904, 0x3004, 0x62a0, - 0x2019, 0x0005, 0x00c6, 0x080c, 0x521c, 0x2061, 0x0000, 0x080c, - 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2009, 0x0000, - 0x080c, 0xaf3e, 0x007e, 0x00ce, 0x080c, 0x51e3, 0x0804, 0x2fdf, - 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x51e3, 0x2208, 0x0804, - 0x2fdf, 0x0156, 0x00d6, 0x00e6, 0x2069, 0xb714, 0x6810, 0x6914, - 0xa10a, 0x1210, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, - 0x0000, 0x20a9, 0x007e, 0x2069, 0xb735, 0x2d04, 0xa075, 0x0130, - 0x704c, 0x0071, 0xa210, 0x7080, 0x0059, 0xa318, 0x8d68, 0x1f04, - 0x324d, 0x2300, 0xa218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x2fdf, - 0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001, 0x0000, 0x8000, 0x2f0c, - 0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, - 0xb714, 0x6910, 0x62b0, 0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004, - 0x6150, 0xa190, 0x2df9, 0x2215, 0xa294, 0x00ff, 0x6370, 0x83ff, - 0x0108, 0x6274, 0x67d4, 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090, - 0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031, - 0x0002, 0x0040, 0x080c, 0x5b41, 0x1118, 0x2031, 0x0004, 0x0010, - 0x2031, 0x0000, 0x7e3a, 0x7f3e, 0x0804, 0x2fdf, 0x6140, 0x6244, - 0x2019, 0xb8b6, 0x231c, 0x0804, 0x2fdf, 0x0126, 0x2091, 0x8000, - 0x6134, 0xa006, 0x2010, 0x6338, 0x012e, 0x0804, 0x2fdf, 0x080c, - 0x3ee1, 0x0904, 0x3007, 0x6244, 0x6338, 0x0804, 0x2fdf, 0x6140, - 0x6244, 0x7824, 0x6042, 0x7b28, 0x6346, 0x2069, 0xb652, 0x831f, - 0xa305, 0x6816, 0x782c, 0x2069, 0xb8b6, 0x2d1c, 0x206a, 0x0804, - 0x2fdf, 0x0126, 0x2091, 0x8000, 0x7824, 0x6036, 0x782c, 0x603a, - 0x012e, 0x0804, 0x2fdf, 0x7838, 0xa005, 0x01a8, 0x7828, 0xa025, - 0x0904, 0x3007, 0x782c, 0xa02d, 0x0904, 0x3007, 0xa00e, 0x080c, - 0x501b, 0x1120, 0x6244, 0x6338, 0x6446, 0x653a, 0xa186, 0x00ff, - 0x0190, 0x8108, 0x0ca0, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x7828, - 0xa00d, 0x0904, 0x3007, 0x782c, 0xa005, 0x0904, 0x3007, 0x6244, - 0x6146, 0x6338, 0x603a, 0x0804, 0x2fdf, 0x2001, 0xb600, 0x2004, - 0xa086, 0x0003, 0x1904, 0x3004, 0x00c6, 0x2061, 0x0100, 0x7924, - 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xb615, - 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, - 0x2df9, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xb615, 0x2004, 0xa116, - 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, - 0x864e, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, - 0x080c, 0x3ebc, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, - 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x33a5, 0x2d00, 0x6012, - 0x2009, 0x0032, 0x080c, 0x86d3, 0x012e, 0x00ce, 0x0005, 0x012e, - 0x00ce, 0x0804, 0x3004, 0x00ce, 0x0804, 0x3007, 0x080c, 0x86a4, - 0x0cb0, 0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004, - 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, - 0x00ff, 0x1130, 0x2001, 0xb615, 0x2004, 0xa085, 0xff00, 0x0078, - 0xa182, 0x007f, 0x16a0, 0xa188, 0x2df9, 0x210d, 0xa18c, 0x00ff, - 0x2001, 0xb615, 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, - 0x2091, 0x8000, 0x0006, 0x080c, 0x864e, 0x000e, 0x01e0, 0x601a, - 0x600b, 0xbc05, 0x601f, 0x0001, 0x080c, 0x3ebc, 0x01d8, 0x6837, - 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x701b, 0x33a5, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x86d3, - 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x3004, 0x00ce, - 0x0804, 0x3007, 0x080c, 0x86a4, 0x0cb0, 0x6830, 0xa086, 0x0100, - 0x0904, 0x3004, 0x0804, 0x2fdf, 0x2061, 0xb975, 0x0126, 0x2091, - 0x8000, 0x6000, 0xd084, 0x0178, 0x6104, 0x6208, 0x2a60, 0x6068, - 0x783a, 0x60b4, 0x783e, 0x60b0, 0x2019, 0x0072, 0x201a, 0x6348, - 0x012e, 0x0804, 0x2fdf, 0xa00e, 0x2110, 0x0c80, 0x81ff, 0x1904, - 0x3004, 0x080c, 0x5b41, 0x0904, 0x3004, 0x0126, 0x2091, 0x8000, - 0x6248, 0x6068, 0xa202, 0x0248, 0xa085, 0x0001, 0x080c, 0x289c, - 0x080c, 0x4673, 0x012e, 0x0804, 0x2fdf, 0x012e, 0x0804, 0x3007, - 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0xb8c0, 0x2070, 0x2061, - 0xb652, 0x6008, 0x2072, 0x2009, 0x0000, 0x2011, 0x1000, 0x080c, - 0x6bb2, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x7824, 0xa084, 0x0007, 0x0002, 0x3409, 0x3412, - 0x3419, 0x3406, 0x3406, 0x3406, 0x3406, 0x3406, 0x012e, 0x0804, - 0x3007, 0x2009, 0x0114, 0x2104, 0xa085, 0x0800, 0x200a, 0x080c, - 0x3584, 0x0070, 0x2009, 0x010b, 0x200b, 0x0010, 0x080c, 0x3584, - 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x2fe1, - 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x080c, 0x33e0, 0x2009, 0x0101, 0x210c, 0x0016, 0x2001, 0x0138, - 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, 0x007a, 0x2034, 0x2001, - 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, 0x2058, 0x080c, 0x37cf, - 0x080c, 0x3733, 0xa03e, 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60, - 0x2071, 0xb94b, 0x2079, 0x0020, 0x00d6, 0x2069, 0x0000, 0x6824, - 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004, 0x783e, 0x2001, 0x007c, - 0x2004, 0x783a, 0x00de, 0x2011, 0x0001, 0x080c, 0x36df, 0x080c, - 0x36df, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x362a, 0x080c, 0x3707, - 0x080c, 0x3684, 0x080c, 0x35e9, 0x080c, 0x361a, 0x00f6, 0x2079, - 0x0100, 0x7824, 0xd094, 0x0530, 0x7814, 0xa084, 0x0184, 0xa085, - 0x0010, 0x7816, 0x2079, 0x0140, 0x080c, 0x3562, 0x1110, 0x00fe, - 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079, 0x0100, 0x7827, 0x0086, - 0x7814, 0xa084, 0x0184, 0xa085, 0x0032, 0x7816, 0x080c, 0x3562, - 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc, 0x0dc0, 0x7827, 0x0080, - 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x356c, - 0x00fe, 0x0804, 0x352c, 0x00fe, 0x080c, 0x3562, 0x1150, 0x8948, - 0x2001, 0x007a, 0x2602, 0x2001, 0x007b, 0x2502, 0x080c, 0x356c, - 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201, 0x2004, 0xa005, 0x1904, - 0x3466, 0x8739, 0x0038, 0x2001, 0xb924, 0x2004, 0xa086, 0x0000, - 0x1904, 0x3466, 0x2001, 0x0033, 0x2003, 0x00f6, 0x8631, 0x1208, - 0x8529, 0x2500, 0xa605, 0x0904, 0x352c, 0x7824, 0xd0bc, 0x0128, - 0x2900, 0xaa05, 0xab05, 0x1904, 0x352c, 0x6033, 0x000d, 0x2001, - 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, 0x1148, 0x2001, 0xb924, - 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, 0x0040, 0x6027, - 0x0001, 0x2001, 0x0075, 0x2004, 0xa005, 0x0108, 0x6026, 0x2c00, - 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a, 0x6833, 0x000d, 0x7824, - 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061, - 0x0020, 0x6003, 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x3501, - 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001, 0x0074, 0x2004, 0xa005, - 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, 0x0020, - 0x7827, 0x0002, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x601a, - 0x0006, 0x2001, 0x0073, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, - 0x00ce, 0x00fe, 0x0804, 0x3444, 0x2061, 0x0100, 0x6027, 0x0002, - 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824, 0xa084, 0x0003, 0xa086, - 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050, 0xa084, 0xf7ef, 0x6052, - 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e, 0x604b, 0xf7f7, 0x6043, - 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10, 0x2b18, 0x2b00, 0xaa05, - 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, - 0x008e, 0x1118, 0x012e, 0x0804, 0x2fdf, 0x012e, 0x2021, 0x400c, - 0x0804, 0x2fe1, 0xa085, 0x0001, 0x1d04, 0x356b, 0x2091, 0x6000, - 0x8420, 0xa486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, - 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, 0x0020, 0x2003, 0x0004, - 0x2001, 0xb924, 0x2003, 0x0000, 0x2001, 0xb94b, 0x2003, 0x0000, - 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, - 0xb615, 0x200c, 0x7932, 0x7936, 0x080c, 0x287c, 0x7850, 0xa084, - 0x0980, 0xa085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, - 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad, 0x782e, 0x20a9, 0x0046, - 0x1d04, 0x35a0, 0x2091, 0x6000, 0x1f04, 0x35a0, 0x7850, 0xa085, - 0x0400, 0x7852, 0x2001, 0x0009, 0x2004, 0xa084, 0x0003, 0xa086, - 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e, 0x784b, 0xf7f7, 0x7843, - 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x35bd, - 0x7850, 0xa085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, 0xe000, - 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850, - 0xa085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, 0xe000, - 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, 0x2003, 0x0100, 0x7827, - 0x0020, 0x7843, 0x0000, 0x2003, 0x0000, 0x7827, 0x0048, 0x00fe, - 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0xb924, - 0x2079, 0x0030, 0x2001, 0x0201, 0x2004, 0xa005, 0x0160, 0x7000, - 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, - 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x780c, 0xa08c, - 0x0070, 0x0178, 0x2009, 0x007a, 0x260a, 0x2009, 0x007b, 0x250a, - 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, 0x8948, 0xd0a4, 0x0108, - 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0140, - 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x0ca8, - 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, 0xb8c1, 0x2004, - 0x70e2, 0x2009, 0xb615, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, - 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, - 0xa080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, - 0xa006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, - 0x95d5, 0x7027, 0x0080, 0x7014, 0xa084, 0x0184, 0xa085, 0x0032, - 0x7016, 0x080c, 0x3707, 0x080c, 0x3562, 0x1110, 0x8421, 0x0028, - 0x7024, 0xd0bc, 0x0db0, 0x7027, 0x0080, 0x00f6, 0x00e6, 0x2071, - 0xb924, 0x2079, 0x0030, 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, - 0x0120, 0x683c, 0x783e, 0x6838, 0x783a, 0x00de, 0x2011, 0x0011, - 0x080c, 0x36df, 0x2011, 0x0001, 0x080c, 0x36df, 0x00ee, 0x00fe, - 0x7017, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0xb924, - 0x2079, 0x0030, 0x7904, 0xd1fc, 0x0904, 0x36dc, 0x7803, 0x0002, - 0xa026, 0xd19c, 0x1904, 0x36d8, 0x7000, 0x0002, 0x36dc, 0x369a, - 0x36be, 0x36d8, 0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, - 0x2011, 0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, - 0x7820, 0x7924, 0x7803, 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, - 0x200c, 0x81ff, 0x0de8, 0x080c, 0x3606, 0x2009, 0x0001, 0x7808, - 0xd0ec, 0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, - 0xa184, 0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, - 0x00b1, 0x0090, 0x6030, 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, - 0x6000, 0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, - 0x7803, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, - 0xa005, 0x0520, 0x8001, 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, - 0x7832, 0x8840, 0x2804, 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, - 0x2804, 0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, - 0xa802, 0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, - 0x601a, 0x2001, 0x000d, 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, - 0x00e6, 0x00c6, 0x2071, 0xb94b, 0x2079, 0x0020, 0x7904, 0xd1fc, - 0x01f0, 0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x372f, - 0x371a, 0x3726, 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, - 0x080c, 0x36df, 0x0160, 0x080c, 0x36df, 0x0048, 0x8001, 0x7002, - 0x7804, 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, 0x36df, 0x00ce, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, - 0x2001, 0xb8c1, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0xb8c0, - 0x2004, 0x60ce, 0x6004, 0xc0ac, 0xa085, 0x0200, 0x6006, 0x2001, - 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, 0x2001, 0x0076, 0x2024, - 0x2001, 0x0077, 0x201c, 0x080c, 0x3ebc, 0x6833, 0x000d, 0x6f26, - 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, - 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, 0x04b1, 0x1d90, - 0x2d00, 0x681a, 0x0088, 0x080c, 0x3ebc, 0x6833, 0x000d, 0x2070, - 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, 0x0076, 0x2004, 0x2072, - 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, 0x0020, 0x2079, 0x0100, - 0x2001, 0xb8c0, 0x2004, 0x6012, 0x20e1, 0x9040, 0x2001, 0x0072, - 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001, 0x0073, - 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0xa006, 0x603a, - 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0010, - 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, 0x7336, 0xa006, - 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7122, 0x7003, - 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, 0x7003, 0x0040, - 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60, - 0x00c6, 0x080c, 0x3ebc, 0x00ce, 0x6018, 0x2070, 0x2d00, 0x7006, - 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, - 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, 0x2001, 0x0078, - 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3ebc, 0x2d60, 0x6833, - 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, - 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, - 0x080c, 0x379d, 0x1d88, 0x2d00, 0x681a, 0x00e0, 0x080c, 0x3ebc, - 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001, 0x2c00, 0x601a, - 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079, 0x2004, 0x7006, - 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x2001, 0x0073, - 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, - 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, 0x6027, 0x0000, - 0x2001, 0xb924, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, - 0x00ee, 0x0005, 0x0804, 0x2fdf, 0x0126, 0x2091, 0x8000, 0x20a9, - 0x0012, 0x2001, 0xb640, 0x20a0, 0xa006, 0x40a4, 0x012e, 0x0804, - 0x2fdf, 0x7d38, 0x7c3c, 0x0804, 0x3086, 0x080c, 0x3ebc, 0x0904, - 0x3004, 0x080c, 0x5b41, 0x0110, 0x080c, 0x4c52, 0x2009, 0x001c, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x3851, - 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, 0x3007, 0x6804, - 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x3007, 0xd094, 0x00c6, 0x2061, - 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, 0x0218, 0xa18c, - 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, - 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, 0x0010, 0xa18c, - 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, - 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, 0x1a04, 0x3007, - 0xa288, 0x2df9, 0x210d, 0xa18c, 0x00ff, 0x615a, 0xd0dc, 0x0130, - 0x6828, 0xa08a, 0x007f, 0x1a04, 0x3007, 0x6052, 0x6808, 0xa08a, - 0x0100, 0x0a04, 0x3007, 0xa08a, 0x0841, 0x1a04, 0x3007, 0xa084, - 0x0007, 0x1904, 0x3007, 0x680c, 0xa005, 0x0904, 0x3007, 0x6810, - 0xa005, 0x0904, 0x3007, 0x6848, 0x6940, 0xa10a, 0x1a04, 0x3007, - 0x8001, 0x0904, 0x3007, 0x684c, 0x6944, 0xa10a, 0x1a04, 0x3007, - 0x8001, 0x0904, 0x3007, 0x6804, 0xd0fc, 0x0560, 0x080c, 0x3ebc, - 0x0904, 0x3004, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, - 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x3efd, 0x701b, 0x38d1, - 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0xb66e, - 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xb672, 0x200c, - 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, - 0x6006, 0x00ce, 0x2009, 0xb8b1, 0x200b, 0x0000, 0x2001, 0xb674, - 0x2004, 0xd0ac, 0x0158, 0x7824, 0x200a, 0x2009, 0x017f, 0x200a, - 0x3200, 0xa084, 0x003f, 0xa085, 0x3020, 0x2090, 0x20a9, 0x001c, - 0x2d98, 0x2069, 0xb652, 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, - 0x6142, 0x8007, 0xa084, 0x00ff, 0x6046, 0x080c, 0x5e17, 0x080c, - 0x53de, 0x080c, 0x5447, 0x6000, 0xa086, 0x0000, 0x1904, 0x39cc, - 0x6808, 0x602a, 0x080c, 0x24a5, 0x0006, 0x2001, 0x0100, 0x2004, - 0xa082, 0x0005, 0x000e, 0x0268, 0x2009, 0x0170, 0x200b, 0x0080, - 0xe000, 0xe000, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x28d7, - 0x003e, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, - 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, - 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, - 0x0010, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, - 0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0xb8c7, 0x40a1, - 0x080c, 0x6ada, 0x6904, 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, - 0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, - 0x3508, 0x8109, 0x080c, 0x63ce, 0x6878, 0x6016, 0x6874, 0x2008, - 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, - 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x3966, - 0x00ce, 0x2069, 0xb652, 0x2001, 0xb89e, 0x6a80, 0xa294, 0x0030, - 0xa28e, 0x0000, 0x0170, 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, - 0x0140, 0x2003, 0xaaaa, 0x080c, 0x2920, 0x2001, 0xb88f, 0x2102, - 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, - 0x0000, 0x00ce, 0x080c, 0x5b41, 0x0128, 0x080c, 0x4116, 0x0110, - 0x080c, 0x289c, 0x60c8, 0xa005, 0x01d0, 0x6003, 0x0001, 0x2009, - 0x39b2, 0x00e0, 0x080c, 0x5b41, 0x1178, 0x2011, 0x5a14, 0x080c, - 0x6a0e, 0x2011, 0x5a07, 0x080c, 0x6ace, 0x2001, 0xb89f, 0x2003, - 0x0000, 0x080c, 0x5a79, 0x0040, 0x080c, 0x4b7b, 0x0028, 0x6003, - 0x0004, 0x2009, 0x39cc, 0x0010, 0x0804, 0x2fdf, 0x2001, 0x0100, - 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, 0x0170, 0x2004, 0xa084, - 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, 0x309d, 0x0817, 0x2091, - 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, 0x0904, 0x3004, 0x2069, - 0xb652, 0x7830, 0x6842, 0x7834, 0x6846, 0x6804, 0xd0fc, 0x0118, - 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, - 0x7c3c, 0x7d38, 0x0804, 0x3f00, 0xa006, 0x080c, 0x289c, 0x81ff, - 0x1904, 0x3004, 0x080c, 0x5b41, 0x1178, 0x2001, 0xb89f, 0x2003, - 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, - 0x5b85, 0x080c, 0x5a79, 0x0080, 0x0016, 0x2009, 0xffff, 0x8109, - 0x0130, 0x2001, 0xb8e2, 0x2004, 0xa086, 0x0000, 0x1dc0, 0x001e, - 0x080c, 0x4c52, 0x080c, 0x4b7b, 0x0804, 0x2fdf, 0x81ff, 0x1904, - 0x3004, 0x080c, 0x5b41, 0x1110, 0x0804, 0x3004, 0x6188, 0x81ff, - 0x0198, 0x703f, 0x0000, 0x2001, 0xbdc0, 0x2009, 0x0040, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, 0x3f00, - 0x701b, 0x2fdd, 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, - 0xbdc0, 0x20a9, 0x0040, 0x20a1, 0xbdc0, 0x2019, 0xffff, 0x43a4, - 0x6550, 0xa588, 0x2df9, 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, - 0x2011, 0x0002, 0x2100, 0xa506, 0x01a8, 0x080c, 0x501b, 0x1190, - 0x6014, 0x821c, 0x0238, 0xa398, 0xbdc0, 0xa085, 0xff00, 0x8007, - 0x201a, 0x0038, 0xa398, 0xbdc0, 0x2324, 0xa4a4, 0xff00, 0xa405, - 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, - 0x8007, 0x2d0c, 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, - 0xbdc0, 0x2099, 0xbdc0, 0x080c, 0x4bf1, 0x0804, 0x3a33, 0x080c, - 0x3ee1, 0x0904, 0x3007, 0x00c6, 0x080c, 0x3ebc, 0x00ce, 0x1120, - 0x2009, 0x0002, 0x0804, 0x3004, 0x2001, 0xb653, 0x2004, 0xd0b4, - 0x0550, 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0520, 0xa08e, - 0x7f00, 0x0508, 0xa08e, 0x8000, 0x01f0, 0x6000, 0xd08c, 0x11d8, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837, 0x0000, - 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9e96, 0x1120, 0x2009, 0x0003, - 0x0804, 0x3004, 0x7007, 0x0003, 0x701b, 0x3abf, 0x0005, 0x080c, - 0x3ee1, 0x0904, 0x3007, 0x20a9, 0x002b, 0x2c98, 0xade8, 0x0002, - 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, - 0x0006, 0x20a0, 0x080c, 0x4bf1, 0x20a9, 0x0004, 0xac80, 0x000a, - 0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x4bf1, 0x2d00, 0x2009, - 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3f00, 0x81ff, - 0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x51f8, - 0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004, 0x7828, 0xa08a, 0x1000, - 0x1a04, 0x3007, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x080c, 0x525b, - 0x0904, 0x3004, 0x2019, 0x0004, 0xa00e, 0x080c, 0x520a, 0x7924, - 0x810f, 0x7a28, 0x0011, 0x0804, 0x2fdf, 0xa186, 0x00ff, 0x0110, - 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0xb600, 0x6450, 0x2400, - 0xa506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, - 0x501b, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, - 0x6a1a, 0x0005, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904, - 0x3007, 0x080c, 0x50e1, 0x0904, 0x3004, 0x080c, 0x5201, 0x0804, - 0x2fdf, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904, 0x3007, - 0x080c, 0x50e1, 0x0904, 0x3004, 0x080c, 0x51ef, 0x0804, 0x2fdf, - 0x6100, 0x0804, 0x2fdf, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x2001, - 0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004, 0x00d6, 0xace8, - 0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007, - 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217, - 0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x2fdf, 0x7824, 0xa09c, - 0x0003, 0xd0b4, 0x1160, 0xa39a, 0x0003, 0x1a04, 0x3004, 0x6250, - 0xa294, 0x00ff, 0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, - 0xb640, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, - 0x3f00, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ee1, 0x0904, 0x3007, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1904, 0x3004, 0x00c6, - 0x080c, 0x3ebc, 0x00ce, 0x0904, 0x3004, 0x6837, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x080c, 0x9e42, 0x0904, 0x3004, 0x7007, 0x0003, - 0x701b, 0x3bab, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x3004, - 0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, - 0x0804, 0x3f00, 0xa006, 0x080c, 0x289c, 0x7824, 0xa084, 0x00ff, - 0xa086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x3004, 0x080c, 0x5b41, - 0x0110, 0x080c, 0x4c52, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x3007, - 0x7924, 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, - 0x007f, 0x1a04, 0x3007, 0x2100, 0x080c, 0x2866, 0x0026, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x2061, 0xb8f4, 0x601b, 0x0000, 0x601f, - 0x0000, 0x080c, 0x5b41, 0x1178, 0x2001, 0xb89f, 0x2003, 0x0001, - 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5b85, - 0x080c, 0x5a79, 0x0440, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, - 0x0002, 0x080c, 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, - 0x080c, 0x806b, 0x003e, 0x2061, 0x0100, 0x2001, 0xb615, 0x2004, - 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, - 0x0010, 0x2009, 0xb8bf, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, - 0x4bb4, 0x080c, 0x6a94, 0x7924, 0xa18c, 0xff00, 0x810f, 0x080c, - 0x5b41, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c, 0x3b0d, 0x012e, - 0x00ce, 0x002e, 0x0804, 0x2fdf, 0x7924, 0xa18c, 0xff00, 0x810f, - 0x00c6, 0x080c, 0x4fbf, 0x2c08, 0x00ce, 0x1904, 0x3007, 0x0804, - 0x2fdf, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3004, 0x60d4, - 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x3004, - 0x080c, 0x3ebc, 0x1120, 0x2009, 0x0002, 0x0804, 0x3004, 0x7924, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x3c61, - 0x0005, 0x2009, 0x0080, 0x080c, 0x501b, 0x1130, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a, 0x0804, 0x2fe1, - 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, - 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x3cd8, 0xa0be, 0x0112, - 0x0904, 0x3cd8, 0xa0be, 0x0113, 0x0904, 0x3cd8, 0xa0be, 0x0114, - 0x0904, 0x3cd8, 0xa0be, 0x0117, 0x0904, 0x3cd8, 0xa0be, 0x011a, - 0x0904, 0x3cd8, 0xa0be, 0x011c, 0x0904, 0x3cd8, 0xa0be, 0x0121, - 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8, 0xa0be, - 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007, 0x6832, - 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528, 0xa0be, - 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a, 0x1120, - 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8, 0x00de, - 0x0804, 0x3007, 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c, 0x3d1e, - 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x3d1e, 0x0048, 0xad80, - 0x000c, 0x080c, 0x3d2c, 0x0050, 0xad80, 0x000e, 0x080c, 0x3d2c, - 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, 0x3d1e, 0x00c6, 0x080c, - 0x3ebc, 0x0568, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853, - 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, - 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, - 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, - 0x0000, 0x6804, 0x2068, 0x080c, 0x9e5e, 0x1120, 0x2009, 0x0003, - 0x0804, 0x3004, 0x7007, 0x0003, 0x701b, 0x3d15, 0x0005, 0x00ce, - 0x00de, 0x2009, 0x0002, 0x0804, 0x3004, 0x6820, 0xa086, 0x8001, - 0x1904, 0x2fdf, 0x2009, 0x0004, 0x0804, 0x3004, 0x0016, 0x2008, - 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, - 0x1f04, 0x3d20, 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, - 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, - 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, - 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3004, - 0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, - 0x3004, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d4, 0xd0ac, - 0x1120, 0xa182, 0x0080, 0x0a04, 0x3007, 0xa182, 0x00ff, 0x1a04, - 0x3007, 0x7a2c, 0x7b28, 0x6070, 0xa306, 0x1140, 0x6074, 0xa24e, - 0x0904, 0x3007, 0xa9cc, 0xff00, 0x0904, 0x3007, 0x0126, 0x2091, - 0x8000, 0x00c6, 0x080c, 0x3e0c, 0x2c68, 0x00ce, 0x0538, 0xa0c6, - 0x4000, 0x1178, 0x00c6, 0x0006, 0x2d60, 0xa00e, 0x080c, 0x52bc, - 0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, - 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, - 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, - 0x2001, 0x4006, 0x2020, 0x012e, 0x0804, 0x2fe1, 0x2d00, 0x7022, - 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x864e, 0x05c0, - 0x2d00, 0x601a, 0x080c, 0xa0e3, 0x2e58, 0x00ee, 0x00e6, 0x00c6, - 0x080c, 0x3ebc, 0x00ce, 0x2b70, 0x1158, 0x080c, 0x86a4, 0x00ee, - 0x00ce, 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, 0x0804, 0x3004, - 0x6837, 0x0000, 0x683b, 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, - 0x6838, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0x683a, 0x080c, 0x2cd1, - 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002, - 0x080c, 0x4f6f, 0x2009, 0x0002, 0x080c, 0x86d3, 0xa085, 0x0001, - 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, 0x0003, - 0x0804, 0x3004, 0x7007, 0x0003, 0x701b, 0x3def, 0x0005, 0x6830, - 0xa086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204, - 0xa294, 0x00ff, 0x0804, 0x3004, 0x2009, 0x0000, 0x6838, 0xd0f4, - 0x1904, 0x2fdf, 0x080c, 0x52bc, 0x1108, 0xc185, 0x6000, 0xd0bc, - 0x0108, 0xc18d, 0x0804, 0x2fdf, 0x00e6, 0x00d6, 0xa02e, 0x2001, - 0xb635, 0x2004, 0xd0ac, 0x0130, 0xa026, 0x20a9, 0x00ff, 0x2071, - 0xb735, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xb7b5, - 0x2e04, 0xa005, 0x1130, 0x2100, 0xa406, 0x1570, 0x2428, 0xc5fd, - 0x0458, 0x2068, 0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14, 0x2600, - 0xa206, 0x1190, 0x2400, 0xa106, 0x1160, 0x2d60, 0xd884, 0x0568, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1538, 0x2001, 0x4000, - 0x0428, 0x2001, 0x4007, 0x0410, 0x2400, 0xa106, 0x1168, 0x6e14, - 0x87ff, 0x1138, 0x86ff, 0x09d0, 0x2001, 0xb635, 0x2004, 0xd0ac, - 0x19a8, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x3e20, - 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, - 0x080c, 0x4fbf, 0x1dd0, 0x6312, 0x6216, 0xa006, 0xa005, 0x00de, - 0x00ee, 0x0005, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ebc, 0x0904, - 0x3004, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005, - 0x0904, 0x3007, 0xa096, 0x00ff, 0x0120, 0xa092, 0x0004, 0x1a04, - 0x3007, 0x2010, 0x2d18, 0x080c, 0x2c84, 0x0904, 0x3004, 0x7007, - 0x0003, 0x701b, 0x3e8c, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, - 0x3004, 0x0804, 0x2fdf, 0x7924, 0xa18c, 0xff00, 0x810f, 0x60d4, - 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x3007, 0xa182, 0x00ff, - 0x1a04, 0x3007, 0x0126, 0x2091, 0x8000, 0x080c, 0x9d46, 0x1188, - 0xa190, 0xb735, 0x2204, 0xa065, 0x0160, 0x080c, 0x4c7e, 0x2001, - 0xb635, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e, 0x0804, - 0x2fdf, 0x012e, 0x0804, 0x3004, 0x080c, 0x15fd, 0x0188, 0xa006, - 0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016, 0x0030, - 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, - 0x0005, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x501b, 0x1130, - 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, 0xa066, 0x8cff, - 0x0005, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, 0x501b, 0x1128, - 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, - 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, 0x1614, - 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, - 0x2031, 0x0000, 0x2061, 0xb6d2, 0x6606, 0x6112, 0x600e, 0x6226, - 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1648, 0x7007, 0x0002, - 0x701b, 0x2fdf, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, - 0x0000, 0x2001, 0xb690, 0x2004, 0xa005, 0x1168, 0x0e04, 0x3f2b, - 0x7818, 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001, - 0x2091, 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, 0x2071, 0xb682, - 0x7138, 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, 0x0078, 0x7030, - 0xa0e0, 0x0004, 0xac82, 0xb6d2, 0x0210, 0x2061, 0xb692, 0x2c00, - 0x7032, 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, - 0x640a, 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005, 0x00e6, - 0x2071, 0xb682, 0x7038, 0xa005, 0x0570, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x3f82, 0x00f6, 0x2079, 0x0000, 0x7818, 0xd084, 0x1508, - 0x00c6, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, - 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, - 0xa005, 0x1130, 0x7033, 0xb692, 0x7037, 0xb692, 0x00ce, 0x0048, - 0xac80, 0x0004, 0xa0fa, 0xb6d2, 0x0210, 0x2001, 0xb692, 0x7036, - 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001, 0xb653, - 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x3f13, 0x002e, - 0x0005, 0x81ff, 0x1904, 0x3004, 0x0126, 0x2091, 0x8000, 0x6030, - 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x5b41, 0x1178, 0x2001, - 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, - 0x0001, 0x080c, 0x5b85, 0x080c, 0x5a79, 0x0010, 0x080c, 0x4b7b, - 0x012e, 0x0804, 0x2fdf, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x1128, - 0x61e0, 0xa10d, 0x61e2, 0x0804, 0x2fdf, 0x0804, 0x3007, 0x81ff, - 0x1904, 0x3004, 0x6000, 0xa086, 0x0003, 0x1904, 0x3004, 0x2001, - 0xb653, 0x2004, 0xd0ac, 0x1904, 0x3004, 0x080c, 0x3ee1, 0x0904, - 0x3007, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, 0x7828, - 0xa005, 0x0904, 0x2fdf, 0x00c6, 0x080c, 0x3ebc, 0x00ce, 0x0904, - 0x3004, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, - 0x080c, 0x9f27, 0x0904, 0x3004, 0x7007, 0x0003, 0x701b, 0x3ff1, - 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x3004, 0x0804, 0x2fdf, - 0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004, 0x7f24, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3ebc, 0x0904, 0x3004, - 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, - 0xad80, 0x0005, 0x7026, 0x20a0, 0x080c, 0x501b, 0x1904, 0x406b, - 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0130, 0xa0c4, 0xff00, - 0xa8c6, 0x0600, 0x1904, 0x406b, 0x2001, 0xb653, 0x2004, 0xd0ac, - 0x1128, 0x080c, 0x52bc, 0x1110, 0xd79c, 0x05e8, 0xd794, 0x1110, - 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, - 0x53a3, 0x080c, 0x3d2c, 0xd794, 0x0148, 0xac80, 0x000a, 0x2098, - 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3d2c, 0x21a2, 0xd794, - 0x01d8, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3, - 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400, - 0x20a9, 0x0002, 0x53a3, 0x080c, 0x3d1e, 0xac80, 0x0026, 0x2098, - 0x20a9, 0x0002, 0x53a3, 0x0008, 0x94a0, 0xd794, 0x0110, 0xa6b0, - 0x000b, 0xa6b0, 0x0005, 0x8108, 0x2001, 0xb635, 0x2004, 0xd0ac, - 0x0118, 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, 0x0100, - 0x0170, 0x0018, 0xa186, 0x007e, 0x0150, 0xd794, 0x0118, 0xa686, - 0x0020, 0x0010, 0xa686, 0x0028, 0x0150, 0x0804, 0x4014, 0x86ff, - 0x1120, 0x7120, 0x810b, 0x0804, 0x2fdf, 0x702f, 0x0001, 0x711e, - 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xb6d2, 0x6007, 0x0000, - 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, - 0x080c, 0x1648, 0x7007, 0x0002, 0x701b, 0x40a7, 0x0005, 0x702c, - 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, - 0x2061, 0xb6d2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804, 0x4014, - 0x7120, 0x810b, 0x0804, 0x2fdf, 0x2029, 0x007e, 0x7924, 0x7a28, - 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, - 0x3007, 0xa502, 0x0a04, 0x3007, 0xa184, 0x00ff, 0xa0e2, 0x0020, - 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0xa284, 0xff00, 0x8007, - 0xa0e2, 0x0020, 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0xa284, - 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, - 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x3007, 0xa502, - 0x0a04, 0x3007, 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3007, - 0xa502, 0x0a04, 0x3007, 0xa484, 0xff00, 0x8007, 0xa0e2, 0x0020, - 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0xa484, 0x00ff, 0xa0e2, - 0x0020, 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0x2061, 0xb8b9, - 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2fdf, 0x0006, 0x2001, - 0xb653, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001, 0xb672, - 0x2004, 0xd0bc, 0x000e, 0x0005, 0x6168, 0x7a24, 0x6300, 0x82ff, - 0x1118, 0x7926, 0x0804, 0x2fdf, 0x83ff, 0x1904, 0x3007, 0x2001, - 0xfff0, 0xa200, 0x1a04, 0x3007, 0x2019, 0xffff, 0x606c, 0xa302, - 0xa200, 0x0a04, 0x3007, 0x7926, 0x626a, 0x0804, 0x2fdf, 0x2001, - 0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004, 0x7c28, 0x7d24, - 0x7e38, 0x7f2c, 0x080c, 0x3ebc, 0x0904, 0x3004, 0x2009, 0x0000, - 0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, 0x0003, - 0x7026, 0x20a0, 0xa1e0, 0xb735, 0x2c64, 0x8cff, 0x01b8, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, 0xa084, 0xff00, - 0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007, - 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182, - 0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, 0x83ff, 0x1120, - 0x7120, 0x810c, 0x0804, 0x2fdf, 0x702f, 0x0001, 0x711e, 0x7020, - 0xa300, 0x7022, 0x2061, 0xb6d2, 0x6007, 0x0000, 0x6312, 0x7024, - 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, 0x080c, 0x1648, - 0x7007, 0x0002, 0x701b, 0x419d, 0x0005, 0x702c, 0xa005, 0x1168, - 0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xb6d2, 0x6424, - 0x6528, 0x662c, 0x6730, 0x0804, 0x415a, 0x7120, 0x810c, 0x0804, - 0x2fdf, 0x81ff, 0x1904, 0x3004, 0x60d4, 0xd0ac, 0x1118, 0xd09c, - 0x0904, 0x3004, 0x080c, 0x3ebc, 0x0904, 0x3004, 0x7924, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x41c8, 0x0005, - 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, 0x0148, 0xa0be, - 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, 0x0804, 0x3007, - 0x6820, 0x6924, 0x080c, 0x2852, 0x1510, 0x080c, 0x4fbf, 0x11f8, - 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, 0x3ebc, 0x01b8, - 0x080c, 0x3ebc, 0x01a0, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0x9e7a, - 0x0904, 0x3004, 0x7007, 0x0003, 0x701b, 0x4202, 0x0005, 0x00de, - 0x0804, 0x3004, 0x7120, 0x080c, 0x2dcc, 0x6820, 0xa086, 0x8001, - 0x0904, 0x3004, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, 0x0006, - 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4bf1, 0x000e, 0xade8, - 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xb6d2, 0x6007, - 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018, 0xa7c6, - 0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x3007, 0x2009, 0x0004, - 0x0804, 0x3f00, 0xa7c6, 0x7200, 0x1904, 0x3007, 0xa6c2, 0x0054, - 0x0a04, 0x3007, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e, - 0x6532, 0x2c10, 0x080c, 0x1648, 0x7007, 0x0002, 0x701b, 0x4249, - 0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080, - 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4bf1, - 0x000e, 0x2009, 0x002a, 0x2061, 0xb6d2, 0x6224, 0x6328, 0x642c, - 0x6530, 0x0804, 0x3f00, 0x81ff, 0x1904, 0x3004, 0x792c, 0x2001, - 0xb8a0, 0x2102, 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x50e1, - 0x0904, 0x3004, 0x0126, 0x2091, 0x8000, 0x080c, 0x5213, 0x012e, - 0x0804, 0x2fdf, 0x7824, 0xd08c, 0x1118, 0xd084, 0x0904, 0x3a87, - 0x080c, 0x3ee1, 0x0904, 0x3007, 0x00c6, 0x080c, 0x3ebc, 0x00ce, - 0x1120, 0x2009, 0x0002, 0x0804, 0x3004, 0x6004, 0xa084, 0x00ff, - 0xa086, 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa08e, 0x0005, - 0x15b8, 0x7824, 0xd08c, 0x0120, 0x6000, 0xc08c, 0x6002, 0x0030, - 0x2001, 0xb653, 0x2004, 0xd0b4, 0x0904, 0x3ac3, 0x7824, 0xa084, - 0xff00, 0xa08e, 0x7e00, 0x0904, 0x3ac3, 0xa08e, 0x7f00, 0x0904, - 0x3ac3, 0xa08e, 0x8000, 0x0904, 0x3ac3, 0x6000, 0xd08c, 0x1904, - 0x3ac3, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9e96, - 0x1120, 0x2009, 0x0003, 0x0804, 0x3004, 0x7007, 0x0003, 0x701b, - 0x42ca, 0x0005, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x0804, 0x3ac3, - 0x2009, 0xb631, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x3004, 0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x0120, 0x2009, - 0x0007, 0x0804, 0x3004, 0x2001, 0xb653, 0x2004, 0xd0ac, 0x0120, - 0x2009, 0x0008, 0x0804, 0x3004, 0x609c, 0xd0a4, 0x1118, 0xd0ac, - 0x1904, 0x3ac3, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, - 0x683a, 0x080c, 0x9f27, 0x1120, 0x2009, 0x0003, 0x0804, 0x3004, - 0x7007, 0x0003, 0x701b, 0x4305, 0x0005, 0x6830, 0xa086, 0x0100, - 0x1120, 0x2009, 0x0004, 0x0804, 0x3004, 0x080c, 0x3ee1, 0x0904, - 0x3007, 0x0804, 0x4299, 0x81ff, 0x2009, 0x0001, 0x1904, 0x3004, - 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, 0x3004, 0x2001, - 0xb653, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, 0x3004, 0x080c, - 0x3ee1, 0x0904, 0x3007, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, - 0x2009, 0x0009, 0x1904, 0x3004, 0x00c6, 0x080c, 0x3ebc, 0x00ce, - 0x2009, 0x0002, 0x0904, 0x3004, 0x6837, 0x0000, 0x6833, 0x0000, - 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, 0xa18c, 0x00ff, - 0xa006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, 0x6956, 0x0048, - 0xa28e, 0x0100, 0x1904, 0x3007, 0xc0e5, 0x6853, 0x0000, 0x6857, - 0x0000, 0x683e, 0x080c, 0xa0e4, 0x2009, 0x0003, 0x0904, 0x3004, - 0x7007, 0x0003, 0x701b, 0x4365, 0x0005, 0x6830, 0xa086, 0x0100, - 0x2009, 0x0004, 0x0904, 0x3004, 0x0804, 0x2fdf, 0x81ff, 0x2009, - 0x0001, 0x1904, 0x3004, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, - 0x1904, 0x3004, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x6004, 0xa084, - 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x3004, 0x00c6, - 0x080c, 0x3ebc, 0x00ce, 0x2009, 0x0002, 0x0904, 0x3004, 0xad80, - 0x000f, 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, - 0x3efd, 0x701b, 0x439c, 0x0005, 0x00d6, 0xade8, 0x000f, 0x6800, - 0xa086, 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, 0x6808, 0xa084, - 0xff00, 0x1108, 0x0018, 0x00de, 0x1904, 0x3007, 0x00de, 0x6837, - 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x00c6, 0x080c, - 0x3ee1, 0x1118, 0x00ce, 0x0804, 0x3007, 0x080c, 0xa133, 0x2009, - 0x0003, 0x00ce, 0x0904, 0x3004, 0x7007, 0x0003, 0x701b, 0x43c9, - 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, 0x3004, - 0x0804, 0x2fdf, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3004, - 0x6000, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804, 0x3004, - 0x7e24, 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, 0x080c, 0x501b, - 0x1904, 0x3007, 0xa186, 0x007f, 0x0150, 0x6004, 0xa084, 0x00ff, - 0xa086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, 0x3004, 0x00c6, - 0x080c, 0x3ebc, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x3004, - 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x2001, 0x0100, 0x8007, - 0x680a, 0x080c, 0x9eb1, 0x1120, 0x2009, 0x0003, 0x0804, 0x3004, - 0x7007, 0x0003, 0x701b, 0x4415, 0x0005, 0x6808, 0x8007, 0xa086, - 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x3004, 0x68b0, 0x6836, - 0x6810, 0x8007, 0xa084, 0x00ff, 0x800c, 0x6814, 0x8007, 0xa084, - 0x00ff, 0x8004, 0xa080, 0x0002, 0xa108, 0xad80, 0x0004, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3f00, 0x080c, 0x3ebc, 0x1120, - 0x2009, 0x0002, 0x0804, 0x3004, 0x7924, 0xa194, 0xff00, 0xa18c, - 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x3007, 0x2009, 0x001a, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x4451, - 0x0005, 0x2001, 0xb62a, 0x2003, 0x0001, 0xad80, 0x000d, 0x2098, - 0x20a9, 0x001a, 0x20a1, 0xb8c7, 0x53a3, 0x0804, 0x2fdf, 0x080c, - 0x3ebc, 0x1120, 0x2009, 0x0002, 0x0804, 0x3004, 0x7924, 0xa194, - 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x3007, - 0x2099, 0xb8c7, 0x20a0, 0x20a9, 0x001a, 0x53a3, 0x2009, 0x001a, - 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3f00, 0x7824, 0xa08a, - 0x1000, 0x1a04, 0x3007, 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, - 0x810b, 0xa108, 0x00c6, 0x2061, 0xb8f4, 0x6142, 0x00ce, 0x012e, - 0x0804, 0x2fdf, 0x00c6, 0x080c, 0x5b41, 0x1188, 0x2001, 0xb89f, - 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, - 0x080c, 0x5b85, 0x080c, 0x5a79, 0x080c, 0x151a, 0x0038, 0x2061, - 0xb600, 0x6030, 0xc09d, 0x6032, 0x080c, 0x4b7b, 0x00ce, 0x0005, - 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0xb8f4, 0x7924, 0x6152, - 0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7838, 0x606a, 0x783c, - 0x6066, 0x7828, 0x6062, 0x782c, 0x605e, 0x2061, 0xb8a1, 0x2001, - 0xb909, 0x600e, 0x6013, 0x0001, 0x6017, 0x0002, 0x6007, 0x0000, - 0x6037, 0x0000, 0x00ce, 0x012e, 0x0804, 0x2fdf, 0x0126, 0x00c6, - 0x00e6, 0x2061, 0x0100, 0x2071, 0xb600, 0x6044, 0xd0a4, 0x11b0, - 0xd084, 0x0118, 0x080c, 0x464d, 0x0068, 0xd08c, 0x0118, 0x080c, - 0x456e, 0x0040, 0xd094, 0x0118, 0x080c, 0x453f, 0x0018, 0xd09c, - 0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e, 0x0005, 0x0016, 0x6128, - 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0ca0, 0x624c, 0xa286, - 0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0, 0x0130, 0x624a, 0x6043, - 0x0090, 0x6043, 0x0010, 0x0490, 0xa294, 0xff00, 0xa296, 0xf700, - 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240, 0xa295, 0x0100, 0x6242, - 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x4c11, 0x00f0, - 0x6040, 0xa084, 0x0010, 0xa085, 0x0140, 0x6042, 0x6043, 0x0000, - 0x707b, 0x0000, 0x7097, 0x0001, 0x70bb, 0x0000, 0x70d7, 0x0000, - 0x2009, 0xbdc0, 0x200b, 0x0000, 0x708b, 0x0000, 0x707f, 0x000a, - 0x2009, 0x000a, 0x2011, 0x4b1c, 0x080c, 0x6a94, 0x0005, 0x0156, - 0x2001, 0xb674, 0x2004, 0xd08c, 0x0110, 0x7053, 0xffff, 0x707c, - 0xa005, 0x1510, 0x2011, 0x4b1c, 0x080c, 0x6a0e, 0x6040, 0xa094, - 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, - 0x1168, 0x1f04, 0x4556, 0x6242, 0x708f, 0x0000, 0x6040, 0xa094, - 0x0010, 0xa285, 0x0080, 0x6042, 0x6242, 0x0030, 0x6242, 0x708f, - 0x0000, 0x7083, 0x0000, 0x0000, 0x015e, 0x0005, 0x7080, 0xa08a, - 0x0003, 0x1210, 0x0023, 0x0010, 0x080c, 0x151a, 0x0005, 0x457a, - 0x45ca, 0x464c, 0x00f6, 0x7083, 0x0001, 0x20e1, 0xa000, 0xe000, - 0x20e1, 0x8700, 0x080c, 0x24a5, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x2079, 0xbc00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, - 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, - 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, - 0x782f, 0x0000, 0x2079, 0xbc0c, 0x207b, 0x1101, 0x7807, 0x0000, - 0x2099, 0xb605, 0x20a1, 0xbc0e, 0x20a9, 0x0004, 0x53a3, 0x2079, - 0xbc12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xbc00, 0x20a1, - 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, - 0x080c, 0x4b55, 0x00fe, 0x7087, 0x0000, 0x6043, 0x0008, 0x6043, - 0x0000, 0x0005, 0x00d6, 0x7084, 0x7087, 0x0000, 0xa025, 0x0904, - 0x4634, 0x6020, 0xd0b4, 0x1904, 0x4632, 0x7194, 0x81ff, 0x0904, - 0x4622, 0xa486, 0x000c, 0x1904, 0x462d, 0xa480, 0x0018, 0x8004, - 0x20a8, 0x2011, 0xbc80, 0x2019, 0xbc00, 0x220c, 0x2304, 0xa106, - 0x11b8, 0x8210, 0x8318, 0x1f04, 0x45e5, 0x6043, 0x0004, 0x608b, - 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x7083, 0x0002, 0x708f, - 0x0002, 0x2009, 0x07d0, 0x2011, 0x4b23, 0x080c, 0x6a94, 0x0490, - 0x2069, 0xbc80, 0x6930, 0xa18e, 0x1101, 0x1538, 0x6834, 0xa005, - 0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118, 0x6804, 0xa005, 0x0190, - 0x2011, 0xbc8e, 0x2019, 0xb605, 0x20a9, 0x0004, 0x220c, 0x2304, - 0xa102, 0x0230, 0x1190, 0x8210, 0x8318, 0x1f04, 0x4616, 0x0068, - 0x7097, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbc80, - 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043, - 0x0000, 0x0010, 0x00de, 0x0005, 0x6040, 0xa085, 0x0100, 0x6042, - 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c, 0x2011, 0xb8eb, 0x2013, - 0x0000, 0x7087, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x080c, 0x7dea, 0x0c30, 0x0005, 0x708c, 0xa08a, 0x001d, - 0x1210, 0x0023, 0x0010, 0x080c, 0x151a, 0x0005, 0x4680, 0x468f, - 0x46b7, 0x46d0, 0x46f4, 0x471c, 0x4740, 0x4771, 0x4795, 0x47bd, - 0x47f4, 0x481c, 0x4838, 0x484e, 0x486e, 0x4881, 0x4889, 0x48b9, - 0x48dd, 0x4905, 0x4929, 0x495a, 0x4997, 0x49c6, 0x49e2, 0x4a21, - 0x4a41, 0x4a5a, 0x4a5b, 0x00c6, 0x2061, 0xb600, 0x6003, 0x0007, - 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006, 0x00ce, 0x0005, - 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002, 0x708f, 0x0001, - 0x2009, 0x07d0, 0x2011, 0x4b23, 0x080c, 0x6a94, 0x0005, 0x00f6, - 0x7084, 0xa086, 0x0014, 0x1508, 0x6043, 0x0000, 0x6020, 0xd0b4, - 0x11e0, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1102, 0x11a0, 0x7834, - 0xa005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, - 0x70bb, 0x0001, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x708f, 0x0010, - 0x080c, 0x4889, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, - 0x0003, 0x6043, 0x0004, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x080c, - 0x4bf9, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a, 0x20a3, - 0x0000, 0x1f04, 0x46c7, 0x60c3, 0x0014, 0x080c, 0x4b55, 0x0005, - 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4b23, 0x080c, 0x6a0e, - 0xa086, 0x0014, 0x11a8, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1102, - 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, - 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0004, 0x0029, 0x0010, - 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x0005, 0x080c, 0x4bf9, - 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xbc8e, 0x080c, - 0x4c4a, 0x1160, 0x7078, 0xa005, 0x1148, 0x7150, 0xa186, 0xffff, - 0x0128, 0x080c, 0x4ae7, 0x0110, 0x080c, 0x4c28, 0x20a9, 0x0008, - 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x0014, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, - 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0014, 0x11a8, 0x2079, - 0xbc80, 0x7a30, 0xa296, 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, - 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, - 0x708f, 0x0006, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, - 0x708f, 0x0007, 0x080c, 0x4bf9, 0x20a3, 0x1104, 0x20a3, 0x0000, - 0x3430, 0x2011, 0xbc8e, 0x080c, 0x4c4a, 0x11a8, 0x7078, 0xa005, - 0x1190, 0x7158, 0xa186, 0xffff, 0x0170, 0xa180, 0x2df9, 0x200d, - 0xa18c, 0xff00, 0x810f, 0x080c, 0x4ae7, 0x0128, 0x080c, 0x411d, - 0x0110, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4b55, - 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4b23, 0x080c, - 0x6a0e, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbc80, 0x7a30, 0xa296, - 0x1104, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, - 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0008, 0x0029, - 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x0009, 0x080c, - 0x4bf9, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430, 0x080c, 0x4c4a, - 0x1150, 0x7078, 0xa005, 0x1138, 0x080c, 0x4a5c, 0x1170, 0xa085, - 0x0001, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2099, 0xbc8e, 0x26a0, - 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, - 0x4b55, 0x0010, 0x080c, 0x4673, 0x0005, 0x00f6, 0x7084, 0xa005, - 0x0588, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0014, 0x1540, - 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1105, 0x1510, 0x7834, 0x2011, - 0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, - 0x1110, 0x70bb, 0x0001, 0x708f, 0x000a, 0x00b1, 0x0098, 0xa005, - 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, - 0x0001, 0x708b, 0x0000, 0x708f, 0x000e, 0x080c, 0x486e, 0x0010, - 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x000b, 0x2011, 0xbc0e, - 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, - 0x2009, 0x0000, 0x41a4, 0x080c, 0x4bf9, 0x20a3, 0x1106, 0x20a3, - 0x0000, 0x080c, 0x4c4a, 0x0118, 0x2013, 0x0000, 0x0020, 0x7054, - 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3, - 0x0084, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0, - 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0084, 0x1168, 0x2079, - 0xbc80, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, - 0x708f, 0x000c, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, - 0x708f, 0x000d, 0x080c, 0x4bf9, 0x20a3, 0x1107, 0x20a3, 0x0000, - 0x2099, 0xbc8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x60c3, 0x0084, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084, - 0xa005, 0x01d0, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0084, - 0x1188, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834, - 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, 0x4beb, 0x708f, 0x000e, - 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x000f, - 0x7087, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, - 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x4b23, 0x080c, 0x6a02, - 0x0005, 0x7084, 0xa005, 0x0120, 0x2011, 0x4b23, 0x080c, 0x6a0e, - 0x0005, 0x708f, 0x0011, 0x080c, 0x4c4a, 0x11a0, 0x7170, 0x81ff, - 0x0188, 0x2009, 0x0000, 0x7074, 0xa084, 0x00ff, 0x080c, 0x2852, - 0xa186, 0x007e, 0x0138, 0xa186, 0x0080, 0x0120, 0x2011, 0xbc8e, - 0x080c, 0x4ae7, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbc80, - 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, - 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x080c, 0x4b55, - 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4b23, 0x080c, - 0x6a0e, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbc80, 0x7a30, 0xa296, - 0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, - 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0012, 0x0029, - 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x0013, 0x080c, - 0x4c05, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xbc8e, - 0x080c, 0x4c4a, 0x1160, 0x7078, 0xa005, 0x1148, 0x7150, 0xa186, - 0xffff, 0x0128, 0x080c, 0x4ae7, 0x0110, 0x080c, 0x4c28, 0x20a9, - 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005, - 0x01f0, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0014, 0x11a8, - 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, - 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, - 0x0001, 0x708f, 0x0014, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, - 0x0005, 0x708f, 0x0015, 0x080c, 0x4c05, 0x20a3, 0x1104, 0x20a3, - 0x0000, 0x3430, 0x2011, 0xbc8e, 0x080c, 0x4c4a, 0x11a8, 0x7078, - 0xa005, 0x1190, 0x7158, 0xa186, 0xffff, 0x0170, 0xa180, 0x2df9, - 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4ae7, 0x0128, 0x080c, - 0x411d, 0x0110, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2298, 0x26a0, - 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, - 0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005, 0x05b8, 0x2011, 0x4b23, - 0x080c, 0x6a0e, 0xa086, 0x0014, 0x1570, 0x2079, 0xbc80, 0x7a30, - 0xa296, 0x1105, 0x1540, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1148, - 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, - 0x0060, 0xa005, 0x11c0, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, - 0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, 0x7a38, 0xd2f4, 0x0138, - 0x2001, 0xb674, 0x2004, 0xd0a4, 0x1110, 0x70d7, 0x0008, 0x708f, - 0x0016, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x20e1, - 0x9080, 0x20e1, 0x4000, 0x2099, 0xbc80, 0x20a1, 0x020b, 0x20a9, - 0x000e, 0x53a6, 0x3430, 0x2011, 0xbc8e, 0x708f, 0x0017, 0x080c, - 0x4c4a, 0x1150, 0x7078, 0xa005, 0x1138, 0x080c, 0x4a5c, 0x1170, - 0xa085, 0x0001, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2099, 0xbc8e, - 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, - 0x080c, 0x4b55, 0x0010, 0x080c, 0x4673, 0x0005, 0x00f6, 0x7084, - 0xa005, 0x01b0, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0084, - 0x1168, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, - 0xa005, 0x1120, 0x708f, 0x0018, 0x0029, 0x0010, 0x080c, 0x4b7b, - 0x00fe, 0x0005, 0x708f, 0x0019, 0x080c, 0x4c05, 0x20a3, 0x1106, - 0x20a3, 0x0000, 0x3430, 0x2099, 0xbc8e, 0x2039, 0xbc0e, 0x27a0, - 0x20a9, 0x0040, 0x53a3, 0x080c, 0x4c4a, 0x11e8, 0x2728, 0x2514, - 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, - 0xa205, 0x202a, 0x7054, 0x2310, 0x8214, 0xa2a0, 0xbc0e, 0x2414, - 0xa38c, 0x0001, 0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff, - 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4b55, - 0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, 0x2011, 0x4b23, 0x080c, - 0x6a0e, 0xa086, 0x0084, 0x1188, 0x2079, 0xbc80, 0x7a30, 0xa296, - 0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x708b, 0x0001, 0x080c, - 0x4beb, 0x708f, 0x001a, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, - 0x0005, 0x708f, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, - 0xbc80, 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, 0x0007, - 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c, - 0x4b55, 0x0005, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0xb653, - 0x252c, 0x20a9, 0x0008, 0x2041, 0xbc0e, 0x28a0, 0x2099, 0xbc8e, - 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011, - 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4, - 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x4a71, 0x0804, 0x4adf, - 0x82ff, 0x1160, 0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020, - 0xa1a6, 0x3fff, 0x0904, 0x4adf, 0xa18d, 0xc000, 0x20a9, 0x0010, - 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, - 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, - 0x0008, 0x8318, 0x1f04, 0x4a97, 0x04d0, 0x23a8, 0x2021, 0x0001, - 0x8426, 0x8425, 0x1f04, 0x4aa9, 0x2328, 0x8529, 0xa2be, 0x0007, - 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8, - 0xa5a8, 0x0010, 0x1f04, 0x4ab8, 0x7552, 0xa5c8, 0x2df9, 0x292d, - 0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, - 0x287c, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, - 0x201a, 0x707b, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0028, 0xa006, - 0x0018, 0xa006, 0x080c, 0x151a, 0x009e, 0x008e, 0x0005, 0x2118, - 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0218, 0x8420, - 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421, - 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, - 0xa238, 0x2704, 0xa42c, 0x11b8, 0xa405, 0x203a, 0x7152, 0xa1a0, - 0x2df9, 0x242d, 0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016, - 0x2508, 0x080c, 0x287c, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x707b, - 0x0001, 0xa084, 0x0000, 0x0005, 0x00e6, 0x2071, 0xb600, 0x707f, - 0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, - 0x0140, 0x080c, 0x4c61, 0x080c, 0x7df3, 0x7004, 0xa084, 0x4000, - 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x0126, 0x2091, 0x8000, - 0x2071, 0xb623, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, - 0x00f7, 0x080c, 0x4c11, 0x001e, 0xa094, 0x0010, 0xa285, 0x0080, - 0x7842, 0x7a42, 0x2009, 0x1388, 0x2011, 0x5a14, 0x080c, 0x6a94, - 0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, - 0x2011, 0xb8eb, 0x2013, 0x0000, 0x7087, 0x0000, 0x012e, 0x20e1, - 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x7dea, 0x6144, - 0xd184, 0x0120, 0x718c, 0xa18d, 0x2000, 0x0018, 0x7180, 0xa18d, - 0x1000, 0x2011, 0xb8bf, 0x2112, 0x2009, 0x07d0, 0x2011, 0x4b23, - 0x080c, 0x6a94, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, - 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c, 0x806b, - 0x003e, 0x2009, 0x00f7, 0x080c, 0x4c11, 0x2061, 0xb8f4, 0x601b, - 0x0000, 0x601f, 0x0000, 0x2061, 0xb600, 0x6003, 0x0001, 0x2061, - 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0xb8bf, 0x200b, - 0x0000, 0x2009, 0x002d, 0x2011, 0x4bb4, 0x080c, 0x6a02, 0x012e, - 0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, - 0x8000, 0x080c, 0x4c61, 0x2071, 0x0100, 0x080c, 0x7df3, 0x2071, - 0x0140, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, - 0x0000, 0x080c, 0x5b49, 0x01a8, 0x080c, 0x5b67, 0x1190, 0x2001, - 0xb89e, 0x2003, 0xaaaa, 0x0016, 0x080c, 0x2920, 0x2001, 0xb88f, - 0x2102, 0x001e, 0x2001, 0xb89f, 0x2003, 0x0000, 0x080c, 0x5a79, - 0x0030, 0x2001, 0x0001, 0x080c, 0x27f8, 0x080c, 0x4b7b, 0x012e, - 0x000e, 0x00ee, 0x0005, 0x20a9, 0x0040, 0x20a1, 0xbdc0, 0x2099, - 0xbc8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x1f04, 0x4bf1, - 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbc00, 0x20a1, - 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x2099, 0xbc80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, - 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0xb631, - 0x2004, 0xa005, 0x1138, 0x2001, 0xb615, 0x2004, 0xa084, 0x00ff, - 0xa105, 0x0010, 0xa185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, - 0x0016, 0x0046, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x0158, 0xa006, - 0x2020, 0x2009, 0x002a, 0x080c, 0xb1a4, 0x2001, 0xb60c, 0x200c, - 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x080c, 0x2ca4, - 0x004e, 0x001e, 0x0005, 0x080c, 0x4b7b, 0x708f, 0x0000, 0x7087, - 0x0000, 0x0005, 0x0006, 0x2001, 0xb60c, 0x2004, 0xd09c, 0x0100, - 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, - 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, - 0x0005, 0x2001, 0xb60d, 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036, - 0x2011, 0x8017, 0x2001, 0xb8bf, 0x201c, 0x080c, 0x3f13, 0x003e, - 0x002e, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, 0xb735, 0xa006, - 0x200a, 0x8108, 0x1f04, 0x4c78, 0x015e, 0x0005, 0x00d6, 0x0036, - 0x0156, 0x0136, 0x0146, 0x2069, 0xb652, 0xa006, 0x6002, 0x6007, - 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2df9, 0x231d, 0xa39c, - 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4, - 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042, - 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, - 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a, - 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, 0x61a2, 0x00d6, - 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1614, 0x60a7, 0x0000, 0x60a8, - 0xa06d, 0x0110, 0x080c, 0x1614, 0x60ab, 0x0000, 0x00de, 0xa006, - 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084, 0x00ff, - 0x6042, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, - 0x2091, 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, - 0x1a04, 0x4d8c, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, - 0x4d91, 0x2001, 0xb60c, 0x2004, 0xa084, 0x0003, 0x01c0, 0x2001, - 0xb60c, 0x2004, 0xd084, 0x1904, 0x4d74, 0xa188, 0xb735, 0x2104, - 0xa065, 0x0904, 0x4d74, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, - 0x1904, 0x4d74, 0x6000, 0xd0c4, 0x0904, 0x4d74, 0x0068, 0xa188, - 0xb735, 0x2104, 0xa065, 0x0904, 0x4d59, 0x6004, 0xa084, 0x00ff, - 0xa08e, 0x0006, 0x1904, 0x4d5e, 0x60a4, 0xa00d, 0x0118, 0x080c, - 0x5246, 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x5291, 0x1170, - 0x694c, 0xd1fc, 0x1118, 0x080c, 0x4f50, 0x0448, 0x080c, 0x4eff, - 0x694c, 0xd1ec, 0x1520, 0x080c, 0x5138, 0x0408, 0x694c, 0xa184, - 0xa000, 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x5147, - 0x0028, 0x080c, 0x5147, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x4eff, - 0x0070, 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000, - 0x6052, 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c, - 0x6d1c, 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000, - 0x04e0, 0x2001, 0x0028, 0x2009, 0x0000, 0x04b8, 0xa082, 0x0006, - 0x1298, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, - 0x1140, 0x6100, 0xd1fc, 0x0128, 0x2001, 0x0029, 0x2009, 0x1000, - 0x0420, 0x2001, 0x0028, 0x00a8, 0x2009, 0xb60c, 0x210c, 0xd18c, - 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, - 0x0040, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, - 0x0060, 0x2009, 0x0000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, - 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x012e, 0x0005, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, 0x8007, 0xa084, 0x00ff, - 0x2008, 0xa182, 0x00ff, 0x1a04, 0x4deb, 0xa188, 0xb735, 0x2104, - 0xa065, 0x01c0, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11a8, - 0x2c70, 0x080c, 0x864e, 0x05e8, 0x2e00, 0x601a, 0x2d00, 0x6012, - 0x600b, 0xffff, 0x601f, 0x000a, 0x2009, 0x0003, 0x080c, 0x86d3, - 0xa006, 0x0460, 0x2001, 0x0028, 0x0440, 0xa082, 0x0006, 0x1298, - 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, - 0x6100, 0xd1fc, 0x09e8, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, - 0x2001, 0x0028, 0x0090, 0x2009, 0xb60c, 0x210c, 0xd18c, 0x0118, - 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, - 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, - 0x0005, 0x2001, 0x002c, 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x2011, 0x0000, 0x2079, 0xb600, 0x6944, 0xa18c, 0xff00, - 0x810f, 0xa182, 0x00ff, 0x1a04, 0x4eb6, 0x080c, 0x501b, 0x11a0, - 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, 0x1270, 0x6864, 0xa0c6, - 0x006f, 0x0150, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1904, 0x4e9f, - 0x60a0, 0xd0bc, 0x1904, 0x4e9f, 0x6864, 0xa0c6, 0x006f, 0x0118, - 0x2008, 0x0804, 0x4e68, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f, - 0x78d4, 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, 0xa182, 0x00ff, - 0x16b8, 0x6a70, 0x6b6c, 0x7870, 0xa306, 0x1160, 0x7874, 0xa24e, - 0x1118, 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, 0x1118, 0x2208, - 0x2310, 0x0430, 0x080c, 0x3e0c, 0x2c70, 0x0550, 0x2009, 0x0000, - 0x2011, 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, 0x2e60, 0x080c, - 0x52bc, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x000e, - 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, - 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, - 0x2001, 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, 0x0030, 0x0450, - 0x080c, 0x864e, 0x1138, 0x2001, 0x4005, 0x2009, 0x0003, 0x2011, - 0x0000, 0x0c80, 0x2e00, 0x601a, 0x080c, 0xa0e3, 0x2d00, 0x6012, - 0x601f, 0x0001, 0x6838, 0xd88c, 0x0108, 0xc0f5, 0x683a, 0x0126, - 0x2091, 0x8000, 0x080c, 0x2cd1, 0x012e, 0x2001, 0x0000, 0x080c, - 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x2009, 0x0002, 0x080c, - 0x86d3, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x2001, - 0x0028, 0x2009, 0x0000, 0x0cb0, 0x2009, 0xb60c, 0x210c, 0xd18c, - 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, - 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, 0x2001, 0x0029, - 0x2009, 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, - 0x4000, 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x12e0, - 0xa188, 0xb735, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084, 0x00ff, - 0xa08e, 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, 0x080c, 0x5147, - 0x0431, 0x0030, 0x0421, 0x684c, 0xd0fc, 0x0110, 0x080c, 0x5138, - 0x080c, 0x5185, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009, 0x0000, - 0x00a0, 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d20, 0x2001, - 0x0029, 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000, - 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x0005, 0x0126, - 0x2091, 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, 0x200a, 0x6803, - 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, - 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0xa005, 0x0170, - 0x00e6, 0x2071, 0xb8e1, 0x7004, 0xa086, 0x0002, 0x0168, 0x00ee, - 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00, 0x6052, - 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, 0x1d80, 0x604c, - 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130, 0x6800, 0xa005, - 0x1108, 0x6052, 0x604e, 0xad05, 0x012e, 0x0005, 0x604c, 0xa06d, - 0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x0005, - 0x6803, 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00, 0x200a, 0x6086, - 0x0005, 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126, 0x00c6, 0x0026, - 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0110, 0xc285, - 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, 0x0005, 0x0126, - 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, - 0x0006, 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, 0xb653, 0x2004, - 0xd0a4, 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x1110, - 0x2011, 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, 0x6206, 0x0006, - 0xa086, 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, 0x080c, 0x151a, - 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, - 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, 0x1178, 0x609c, - 0xd0a4, 0x0160, 0x2001, 0xb653, 0x2004, 0xd0ac, 0x1138, 0xa284, - 0x00ff, 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0xa294, - 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0026, - 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190, 0xb735, - 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x15e4, 0x2d60, - 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab, - 0x0000, 0x080c, 0x4c7e, 0xa006, 0x002e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x0480, - 0x00d6, 0xa190, 0xb735, 0x2204, 0xa06d, 0x0540, 0x2013, 0x0000, - 0x00d6, 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1614, - 0x60a8, 0xa06d, 0x0110, 0x080c, 0x1614, 0x00ce, 0x00de, 0x00d6, - 0x00c6, 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6010, - 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0x1624, 0x080c, 0x86a4, - 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x1614, 0x00de, 0xa006, - 0x002e, 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218, 0xa085, - 0x0001, 0x0030, 0xa188, 0xb735, 0x2104, 0xa065, 0x0dc0, 0xa006, - 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b, 0x0000, - 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x5b41, 0x1558, - 0x60a0, 0xa086, 0x007e, 0x2069, 0xbc90, 0x0130, 0x2001, 0xb635, - 0x2004, 0xd0ac, 0x1500, 0x0098, 0x2d04, 0xd0e4, 0x01e0, 0x00d6, - 0x2069, 0xbc8e, 0x00c6, 0x2061, 0xb8b2, 0x6810, 0x2062, 0x6814, - 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de, 0x8d69, - 0x2d04, 0x2069, 0x0140, 0xa005, 0x1110, 0x2001, 0x0001, 0x6886, - 0x2069, 0xb600, 0x68a6, 0x2069, 0xbc8e, 0x6808, 0x605e, 0x6810, - 0x6062, 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814, 0x6066, 0x2099, - 0xbc96, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, - 0xbc9a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, - 0xbcae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, - 0x6076, 0x60a0, 0xa086, 0x007e, 0x1120, 0x2069, 0xbc8e, 0x690c, - 0x616e, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182, - 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, - 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005, - 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182, - 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x6192, - 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, - 0x2071, 0xbc8d, 0x2e04, 0x6896, 0x2071, 0xbc8e, 0x7004, 0x689a, - 0x701c, 0x689e, 0x6a00, 0x2009, 0xb672, 0x210c, 0xd0bc, 0x0120, - 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0120, 0xd1e4, - 0x0110, 0xc2bd, 0x0008, 0xc2bc, 0x6a02, 0x00ee, 0x002e, 0x001e, - 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x01c0, - 0x6900, 0x81ff, 0x1540, 0x6a04, 0xa282, 0x0010, 0x1648, 0xad88, - 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, - 0x1f04, 0x50f3, 0x080c, 0x151a, 0x260a, 0x8210, 0x6a06, 0x0098, - 0x080c, 0x15fd, 0x01a8, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, - 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x510b, - 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, - 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x00d6, 0x60a4, 0xa00d, - 0x01a0, 0x2168, 0x6800, 0xa005, 0x1160, 0x080c, 0x5246, 0x1168, - 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6806, - 0x0020, 0x080c, 0x1614, 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x080c, 0x52a4, 0x0010, 0x080c, 0x4eff, - 0x080c, 0x51be, 0x1dd8, 0x080c, 0x5185, 0x012e, 0x0005, 0x00d6, - 0x0126, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x01c0, 0x6950, 0x81ff, - 0x1540, 0x6a54, 0xa282, 0x0010, 0x1670, 0xad88, 0x0018, 0x20a9, - 0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x5159, - 0x080c, 0x151a, 0x260a, 0x8210, 0x6a56, 0x0098, 0x080c, 0x15fd, - 0x01d0, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, - 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5171, 0x6857, 0x0001, - 0x6e62, 0x0010, 0x080c, 0x4f50, 0x0089, 0x1de0, 0xa085, 0x0001, - 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6d1c, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, - 0xa00e, 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, - 0x1170, 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, - 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, - 0x6800, 0x2068, 0x0c70, 0x080c, 0x81a5, 0x6a00, 0x604c, 0xad06, - 0x1110, 0x624e, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110, - 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, - 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff, 0x0120, 0x6848, - 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, - 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, 0x6080, 0xad06, - 0x1110, 0x6282, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110, - 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c, 0x5240, 0x1110, 0x2011, - 0x0001, 0x080c, 0x528b, 0x1110, 0xa295, 0x0002, 0x0005, 0x080c, - 0x52bc, 0x0118, 0x080c, 0x9dcb, 0x0010, 0xa085, 0x0001, 0x0005, - 0x080c, 0x52bc, 0x0118, 0x080c, 0x9d5b, 0x0010, 0xa085, 0x0001, - 0x0005, 0x080c, 0x52bc, 0x0118, 0x080c, 0x9dae, 0x0010, 0xa085, - 0x0001, 0x0005, 0x080c, 0x52bc, 0x0118, 0x080c, 0x9d77, 0x0010, - 0xa085, 0x0001, 0x0005, 0x080c, 0x52bc, 0x0118, 0x080c, 0x9de7, - 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, 0x00d6, 0x2091, - 0x8000, 0x6080, 0xa06d, 0x01a0, 0x6800, 0x0006, 0x6837, 0x0103, - 0x6b4a, 0x6847, 0x0000, 0x080c, 0x9f88, 0x0006, 0x6000, 0xd0fc, - 0x0110, 0x080c, 0xb445, 0x000e, 0x080c, 0x547a, 0x000e, 0x0c50, - 0x6083, 0x0000, 0x6087, 0x0000, 0x00de, 0x000e, 0x012e, 0x0005, - 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, - 0x7000, 0xa005, 0x1168, 0x20a9, 0x0010, 0xae88, 0x0004, 0x2104, - 0xa606, 0x0130, 0x8108, 0x1f04, 0x524f, 0xa085, 0x0001, 0x0008, - 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, - 0xa06d, 0x1128, 0x080c, 0x15fd, 0x01a0, 0x2d00, 0x60a6, 0x6803, - 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, - 0xffff, 0x8108, 0x1f04, 0x526f, 0xa085, 0x0001, 0x012e, 0x00de, - 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, - 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x1614, 0xa085, 0x0001, - 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, 0xa085, 0x0001, - 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, 0x20a9, 0x0010, - 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x529a, - 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x0c19, - 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, 0x6854, 0xa08a, - 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, 0x1614, 0x60ab, - 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, 0x0005, 0x00f6, - 0x080c, 0x5b41, 0x01b0, 0x71b8, 0x81ff, 0x1198, 0x71d4, 0xd19c, - 0x0180, 0x2001, 0x007e, 0xa080, 0xb735, 0x2004, 0xa07d, 0x0148, - 0x7804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118, 0x7800, 0xc0ed, - 0x7802, 0x2079, 0xb652, 0x7804, 0xd0a4, 0x01e8, 0x0156, 0x00c6, - 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x501b, 0x1168, - 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0118, 0xa086, - 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04, - 0x52e4, 0x00ce, 0x015e, 0x080c, 0x537b, 0x0120, 0x2001, 0xb8b5, - 0x200c, 0x0038, 0x2079, 0xb652, 0x7804, 0xd0a4, 0x0130, 0x2009, - 0x07d0, 0x2011, 0x530f, 0x080c, 0x6a94, 0x00fe, 0x0005, 0x2011, - 0x530f, 0x080c, 0x6a0e, 0x080c, 0x537b, 0x01f0, 0x2001, 0xb7b3, - 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xb653, - 0x2004, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, 0x530f, 0x080c, - 0x6a94, 0x00e6, 0x2071, 0xb600, 0x7073, 0x0000, 0x7077, 0x0000, - 0x080c, 0x2aed, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, 0x007f, - 0x2009, 0x0000, 0x0016, 0x080c, 0x501b, 0x1530, 0x6000, 0xd0ec, - 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, - 0x0029, 0x080c, 0xb1a4, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004, - 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c, - 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2009, 0x0000, - 0x080c, 0xaf3e, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x533a, - 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060, 0x6000, 0xc0ec, - 0x6002, 0x00ce, 0x0005, 0x7818, 0x2004, 0xd0ac, 0x0005, 0x7818, - 0x2004, 0xd0bc, 0x0005, 0x00f6, 0x2001, 0xb7b3, 0x2004, 0xa07d, - 0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091, - 0x8000, 0x0006, 0x62a0, 0xa290, 0xb735, 0x2204, 0xac06, 0x190c, - 0x151a, 0x000e, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, - 0x6202, 0x002e, 0x012e, 0x0005, 0x2011, 0xb635, 0x2204, 0xd0cc, - 0x0138, 0x2001, 0xb8b3, 0x200c, 0x2011, 0x53a9, 0x080c, 0x6a94, - 0x0005, 0x2011, 0x53a9, 0x080c, 0x6a0e, 0x2011, 0xb635, 0x2204, - 0xc0cc, 0x2012, 0x0005, 0x2071, 0xb714, 0x7003, 0x0001, 0x7007, - 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, - 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, - 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xb87d, 0x7003, - 0xb714, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xb85d, 0x7013, - 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005, 0x0016, 0x00e6, - 0x2071, 0xb835, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, - 0xb653, 0x2004, 0xd0fc, 0x1150, 0x2001, 0xb653, 0x2004, 0xa00e, - 0xd09c, 0x0108, 0x8108, 0x7102, 0x0804, 0x5444, 0x2001, 0xb672, - 0x200c, 0xa184, 0x000f, 0x2009, 0xb673, 0x210c, 0x0002, 0x53ec, - 0x541f, 0x5426, 0x5430, 0x5435, 0x53ec, 0x53ec, 0x53ec, 0x540f, - 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x7003, - 0x0004, 0x0136, 0x0146, 0x0156, 0x2099, 0xb676, 0x20a1, 0xb886, - 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x0428, 0x708f, - 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, 0x708f, 0x0002, - 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097, 0x0001, 0x0088, - 0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007, 0x0121, 0x2001, - 0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, - 0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e, 0x0005, 0x00e6, - 0x2071, 0xb714, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, - 0xa085, 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868, - 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844, - 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006, - 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, - 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, - 0x00ee, 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, - 0x54d3, 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0xb600, 0xa016, - 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, - 0x702e, 0x70b4, 0xa200, 0x70b6, 0x00de, 0x2071, 0xb714, 0x701c, - 0xa005, 0x1904, 0x54e3, 0x20a9, 0x0032, 0x0f04, 0x54e1, 0x0e04, - 0x549d, 0x2071, 0xb835, 0x7200, 0x82ff, 0x05d8, 0x6934, 0xa186, - 0x0103, 0x1904, 0x54f1, 0x6948, 0x6844, 0xa105, 0x1540, 0x2009, - 0x8020, 0x2200, 0x0002, 0x54e1, 0x54b8, 0x5509, 0x5515, 0x54e1, - 0x2071, 0x0000, 0x20a9, 0x0032, 0x0f04, 0x54e1, 0x7018, 0xd084, - 0x1dd8, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, - 0x2091, 0x4080, 0x2071, 0xb600, 0x702c, 0x206a, 0x2d00, 0x702e, - 0x70b4, 0x8000, 0x70b6, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844, - 0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020, - 0x0880, 0x2071, 0xb714, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, - 0x7012, 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, - 0x0c10, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, - 0x0118, 0xa18e, 0x001f, 0x1d28, 0x684c, 0xd0cc, 0x0d10, 0x6850, - 0xa084, 0x00ff, 0xa086, 0x0001, 0x19e0, 0x2009, 0x8021, 0x0804, - 0x54b1, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a98, 0x7186, 0xae90, - 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x7084, 0x8008, 0xa092, - 0x000f, 0x1a38, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, - 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, 0x54ca, - 0x718c, 0x7084, 0xa10a, 0x0a04, 0x54ca, 0x2071, 0x0000, 0x7018, - 0xd084, 0x1904, 0x54ca, 0x2071, 0xb835, 0x7000, 0xa086, 0x0002, - 0x1150, 0x080c, 0x5794, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, - 0x4080, 0x0804, 0x54ca, 0x080c, 0x57be, 0x2071, 0x0000, 0x701b, - 0x0001, 0x2091, 0x4080, 0x0804, 0x54ca, 0x0006, 0x684c, 0x0006, - 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, - 0x0000, 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e, 0x000e, 0x684a, - 0x6952, 0x0005, 0x2071, 0xb714, 0x7004, 0x0002, 0x5570, 0x5581, - 0x577f, 0x5780, 0x578d, 0x5793, 0x5571, 0x5770, 0x5706, 0x575c, - 0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5580, 0x2009, 0x000d, - 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x700b, 0x0000, - 0x012e, 0x2069, 0xb8f4, 0x683c, 0xa005, 0x03f8, 0x11f0, 0x0126, - 0x2091, 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xb720, 0x2004, - 0xa10a, 0x0170, 0x0e04, 0x55a4, 0x2069, 0x0000, 0x6818, 0xd084, - 0x1158, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, - 0x2069, 0xb8f4, 0x683f, 0xffff, 0x012e, 0x2069, 0xb600, 0x6848, - 0x6968, 0xa102, 0x2069, 0xb835, 0x688a, 0x6984, 0x701c, 0xa06d, - 0x0120, 0x81ff, 0x0904, 0x55fa, 0x00a0, 0x81ff, 0x0904, 0x56c0, - 0x2071, 0xb835, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, 0x2071, - 0xb8f4, 0x7038, 0xa005, 0x0128, 0x1b04, 0x56c0, 0x713a, 0x0804, - 0x56c0, 0x2071, 0xb835, 0x718c, 0x0126, 0x2091, 0x8000, 0x7084, - 0xa10a, 0x0a04, 0x56db, 0x0e04, 0x567c, 0x2071, 0x0000, 0x7018, - 0xd084, 0x1904, 0x567c, 0x2001, 0xffff, 0x2071, 0xb8f4, 0x703a, - 0x2071, 0xb835, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x5794, - 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x567c, - 0x080c, 0x57be, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, - 0x0804, 0x567c, 0x2071, 0xb835, 0x7000, 0xa005, 0x0904, 0x56a2, - 0x6934, 0xa186, 0x0103, 0x1904, 0x567f, 0x684c, 0xd0bc, 0x1904, - 0x56a2, 0x6948, 0x6844, 0xa105, 0x1904, 0x5697, 0x2009, 0x8020, - 0x2071, 0xb835, 0x7000, 0x0002, 0x56a2, 0x5662, 0x563a, 0x564c, - 0x5619, 0x0136, 0x0146, 0x0156, 0x2099, 0xb676, 0x20a1, 0xb886, - 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x2071, 0xb87d, - 0xad80, 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, - 0x0000, 0x2e10, 0x080c, 0x1648, 0x2071, 0xb714, 0x7007, 0x0009, - 0x0804, 0x56c0, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x56c0, - 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xb714, - 0x080c, 0x5815, 0x0804, 0x56c0, 0x7084, 0x8008, 0xa092, 0x000f, - 0x1a04, 0x56c0, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, - 0x8210, 0x6840, 0x2012, 0x7186, 0x2071, 0xb714, 0x080c, 0x5815, - 0x0804, 0x56c0, 0x0126, 0x2091, 0x8000, 0x0e04, 0x567c, 0x2071, - 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026, 0x6840, - 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071, 0xb714, - 0x080c, 0x5815, 0x0804, 0x56c0, 0x012e, 0x0804, 0x56c0, 0xa18c, - 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, 0xa18e, - 0x001f, 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850, 0xa084, 0x00ff, - 0xa086, 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, 0x5610, 0x6844, - 0xa086, 0x0100, 0x1138, 0x6868, 0xa005, 0x1120, 0x2009, 0x8020, - 0x0804, 0x5610, 0x2071, 0xb714, 0x080c, 0x5827, 0x01c8, 0x2071, - 0xb714, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, - 0x1130, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x7007, - 0x0003, 0x080c, 0x5840, 0x7050, 0xa086, 0x0100, 0x0904, 0x5780, - 0x0126, 0x2091, 0x8000, 0x2071, 0xb714, 0x7008, 0xa086, 0x0001, - 0x1180, 0x0e04, 0x56d9, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, - 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006, 0x1110, 0x7007, - 0x0001, 0x012e, 0x0005, 0x2071, 0xb714, 0x080c, 0x5827, 0x0518, - 0x2071, 0xb835, 0x7084, 0x700a, 0x20a9, 0x0020, 0x2099, 0xb836, - 0x20a1, 0xb85d, 0x53a3, 0x7087, 0x0000, 0x2071, 0xb714, 0x2069, - 0xb87d, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074, 0x682e, 0x7078, - 0x6832, 0x2d10, 0x080c, 0x1648, 0x7007, 0x0008, 0x2001, 0xffff, - 0x2071, 0xb8f4, 0x703a, 0x012e, 0x0804, 0x56c0, 0x2069, 0xb87d, - 0x6808, 0xa08e, 0x0000, 0x0904, 0x575b, 0xa08e, 0x0200, 0x0904, - 0x5759, 0xa08e, 0x0100, 0x1904, 0x575b, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x5757, 0x2069, 0x0000, 0x6818, 0xd084, 0x15c0, 0x702c, - 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, - 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, - 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, 0x2001, - 0xb85a, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069, 0xb835, 0x689c, - 0x699e, 0x2069, 0xb8f4, 0xa102, 0x1118, 0x683c, 0xa005, 0x1368, - 0x2001, 0xb85b, 0x200c, 0x810d, 0x693e, 0x0038, 0x2009, 0x8040, - 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x012e, - 0x0010, 0x7007, 0x0005, 0x0005, 0x2001, 0xb87f, 0x2004, 0xa08e, - 0x0100, 0x1128, 0x7007, 0x0001, 0x080c, 0x5815, 0x0005, 0xa08e, - 0x0000, 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007, 0x0005, 0x0005, - 0x701c, 0xa06d, 0x0158, 0x080c, 0x5827, 0x0140, 0x7007, 0x0003, - 0x080c, 0x5840, 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, 0x0005, - 0x7050, 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004, 0x0030, 0xa086, - 0x0200, 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, 0x57e3, 0x7006, - 0x080c, 0x5815, 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, 0xb835, - 0x7184, 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, - 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, 0x57b8, 0x2014, - 0x722a, 0x8000, 0x0f04, 0x57b8, 0x2014, 0x722e, 0x8000, 0x0f04, - 0x57b8, 0x2014, 0x723a, 0x8000, 0x0f04, 0x57b8, 0x2014, 0x723e, - 0xa180, 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, 0x0156, - 0x2071, 0xb835, 0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, 0xae80, - 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014, - 0x722a, 0x8000, 0x0f04, 0x57da, 0x2014, 0x723a, 0x8000, 0x2014, - 0x723e, 0x0018, 0x2001, 0x8020, 0x0010, 0x2001, 0x8042, 0x7022, - 0x015e, 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, - 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, - 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, - 0x700c, 0x8001, 0x700e, 0x1180, 0x0126, 0x2091, 0x8000, 0x0e04, - 0x580f, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, - 0x700b, 0x0000, 0x012e, 0x0005, 0x2001, 0x0007, 0x0005, 0x2001, - 0x0006, 0x700b, 0x0001, 0x012e, 0x0005, 0x701c, 0xa06d, 0x0170, - 0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, - 0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1614, 0x0005, 0x2019, - 0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, 0x230c, 0xa10e, - 0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, 0xa102, 0x1118, - 0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, 0x8002, 0x0005, - 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x0126, - 0x2091, 0x8000, 0x2009, 0xb913, 0x2104, 0xc08d, 0x200a, 0x012e, - 0x080c, 0x1664, 0x0005, 0x708c, 0xa08a, 0x0029, 0x1220, 0xa082, - 0x001d, 0x0033, 0x0010, 0x080c, 0x151a, 0x6027, 0x1e00, 0x0005, - 0x594e, 0x58c9, 0x58e1, 0x591e, 0x593f, 0x5979, 0x598b, 0x58e1, - 0x5965, 0x586d, 0x589b, 0x586c, 0x0005, 0x00d6, 0x2069, 0x0200, - 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, - 0x2069, 0xb8c6, 0x2d04, 0x7002, 0x080c, 0x5c43, 0x6028, 0xa085, - 0x0600, 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xb8c6, 0x2d04, - 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, - 0x0056, 0x2071, 0xb924, 0x080c, 0x1e1a, 0x005e, 0x004e, 0x003e, - 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0xa005, - 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, 0xb8c6, - 0x2d04, 0x7002, 0x080c, 0x5cd0, 0x6028, 0xa085, 0x0600, 0x602a, - 0x00b0, 0x708f, 0x0028, 0x2069, 0xb8c6, 0x2d04, 0x7002, 0x6028, - 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, - 0xb924, 0x080c, 0x1e1a, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, - 0x0005, 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x59f6, - 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x708f, 0x0020, - 0x080c, 0x59f6, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, - 0x0005, 0x6803, 0x0088, 0x6124, 0xd1cc, 0x1590, 0xd1dc, 0x1568, - 0xd1e4, 0x1540, 0xa184, 0x1e00, 0x1580, 0x60e3, 0x0001, 0x600c, - 0xc0b4, 0x600e, 0x080c, 0x5b71, 0x080c, 0x24e5, 0x0156, 0x6803, - 0x0100, 0x20a9, 0x0014, 0x6804, 0xd0dc, 0x1118, 0x1f04, 0x58fb, - 0x0048, 0x20a9, 0x0014, 0x6803, 0x0080, 0x6804, 0xd0d4, 0x1130, - 0x1f04, 0x5905, 0x080c, 0x5b92, 0x015e, 0x0078, 0x015e, 0x708f, - 0x0028, 0x0058, 0x708f, 0x001e, 0x0040, 0x708f, 0x001d, 0x0028, - 0x708f, 0x0020, 0x0010, 0x708f, 0x001f, 0x0005, 0x60e3, 0x0001, - 0x600c, 0xc0b4, 0x600e, 0x080c, 0x5b71, 0x080c, 0x24e5, 0x6803, - 0x0080, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, - 0xa184, 0x1e00, 0x1158, 0x708f, 0x0028, 0x0040, 0x708f, 0x001e, - 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, 0x6803, - 0x00a0, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1e63, - 0x708f, 0x001e, 0x0010, 0x708f, 0x001d, 0x0005, 0x080c, 0x5a68, - 0x6124, 0xd1dc, 0x1188, 0x080c, 0x59f6, 0x0016, 0x080c, 0x1e63, - 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x708f, 0x001e, 0x0020, - 0x708f, 0x001f, 0x080c, 0x59f6, 0x0005, 0x6803, 0x00a0, 0x6124, - 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, - 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x0021, - 0x0005, 0x080c, 0x5a68, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, - 0xd1e4, 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, - 0x708f, 0x001f, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1d4, 0x1178, - 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x708f, 0x001e, - 0x0040, 0x708f, 0x001d, 0x0028, 0x708f, 0x0020, 0x0010, 0x708f, - 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, - 0x0100, 0x2069, 0x0140, 0x2071, 0xb600, 0x2091, 0x8000, 0x080c, - 0x5b41, 0x11e8, 0x2001, 0xb60c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4, - 0x2102, 0x6027, 0x0200, 0xe000, 0xe000, 0x6024, 0xd0cc, 0x0158, - 0x6803, 0x00a0, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, - 0x2003, 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, - 0x5b5d, 0x0150, 0x080c, 0x5b53, 0x1138, 0x2001, 0x0001, 0x080c, - 0x27f8, 0x080c, 0x5b18, 0x00a0, 0x080c, 0x5a65, 0x0178, 0x2001, - 0x0001, 0x080c, 0x27f8, 0x708c, 0xa086, 0x001e, 0x0120, 0x708c, - 0xa086, 0x0022, 0x1118, 0x708f, 0x0025, 0x0010, 0x708f, 0x0021, - 0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, - 0x5a07, 0x080c, 0x6ace, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, - 0x2011, 0x5a07, 0x080c, 0x6ac5, 0x002e, 0x001e, 0x0005, 0x00e6, - 0x00f6, 0x0016, 0x080c, 0x7df3, 0x2071, 0xb600, 0x080c, 0x59a2, - 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x7df3, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0xb600, 0x2091, 0x8000, 0x6028, 0xc09c, - 0x602a, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, - 0x8106, 0x080c, 0x7fe0, 0x080c, 0x6a82, 0x0036, 0x2019, 0x0000, - 0x080c, 0x806b, 0x003e, 0x60e3, 0x0000, 0x080c, 0xb4eb, 0x080c, - 0xb506, 0x2001, 0xb600, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c, - 0x12e2, 0x2001, 0x0001, 0x080c, 0x27f8, 0x012e, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x2001, 0xb600, - 0x2004, 0xa086, 0x0004, 0x0140, 0x2001, 0xb89e, 0x2003, 0xaaaa, - 0x2001, 0xb89f, 0x2003, 0x0000, 0x0005, 0x6020, 0xd09c, 0x0005, - 0x6800, 0xa086, 0x00c0, 0x0160, 0x6803, 0x00c0, 0x0156, 0x20a9, - 0x002d, 0x1d04, 0x5a71, 0x2091, 0x6000, 0x1f04, 0x5a71, 0x015e, - 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, - 0x2071, 0xb600, 0x2001, 0xb89f, 0x200c, 0xa186, 0x0000, 0x0158, - 0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, 0x0003, - 0x0158, 0x0804, 0x5b06, 0x708f, 0x0022, 0x0040, 0x708f, 0x0021, - 0x0028, 0x708f, 0x0023, 0x0020, 0x708f, 0x0024, 0x6043, 0x0000, - 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28a7, - 0x0026, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, - 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c, 0x806b, - 0x003e, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, 0x0028, - 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, - 0x0005, 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, 0x5b14, - 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, 0x1130, - 0x6803, 0x0100, 0x1f04, 0x5ac9, 0x080c, 0x5b92, 0x012e, 0x015e, - 0x080c, 0x5b53, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006, - 0xa085, 0x0020, 0x6052, 0x080c, 0x5b92, 0xa006, 0x8001, 0x1df0, - 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x5b92, - 0x0016, 0x0026, 0x2009, 0x00c8, 0x2011, 0x5a14, 0x080c, 0x6a94, - 0x002e, 0x001e, 0x2001, 0xb89f, 0x2003, 0x0004, 0x080c, 0x5853, - 0x080c, 0x5b53, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, - 0x2001, 0xb89f, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, - 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, - 0xb600, 0x2001, 0xb89e, 0x2003, 0x0000, 0x2001, 0xb88f, 0x2003, - 0x0000, 0x708f, 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, - 0x0000, 0x080c, 0x28a7, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043, - 0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, - 0x0005, 0x0006, 0x2001, 0xb89e, 0x2004, 0xa086, 0xaaaa, 0x000e, - 0x0005, 0x0006, 0x2001, 0xb672, 0x2004, 0xa084, 0x0030, 0xa086, - 0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0xb672, 0x2004, 0xa084, - 0x0030, 0xa086, 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, 0xb672, - 0x2004, 0xa084, 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, 0x0006, - 0x2001, 0xb672, 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e, - 0x0005, 0x2001, 0xb60c, 0x2004, 0xd0a4, 0x0170, 0x080c, 0x28c7, - 0x0036, 0x0016, 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, 0x2ca4, - 0x001e, 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xb60c, - 0x2e04, 0x0118, 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072, - 0x00ee, 0x0005, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, - 0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100, - 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, - 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, - 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28a7, - 0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, 0x000e, - 0x6052, 0x6050, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xb600, - 0x6020, 0xa084, 0x0080, 0x0138, 0x2001, 0xb60c, 0x200c, 0xc1bd, - 0x2102, 0x0804, 0x5c3b, 0x2001, 0xb60c, 0x200c, 0xc1bc, 0x2102, - 0x6028, 0xa084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, 0x0090, - 0x20a9, 0x0384, 0x6024, 0xd0cc, 0x1508, 0x1d04, 0x5bea, 0x2091, - 0x6000, 0x1f04, 0x5bea, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, - 0x0002, 0x080c, 0x8106, 0x080c, 0x7fe0, 0x2019, 0x0000, 0x080c, - 0x806b, 0x6803, 0x00a0, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, - 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x0468, 0x86ff, 0x1120, - 0x080c, 0x1e63, 0x080c, 0x24e5, 0x60e3, 0x0000, 0x2001, 0xb88f, - 0x2004, 0x080c, 0x28a7, 0x60e2, 0x6803, 0x0080, 0x20a9, 0x0384, - 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0138, - 0x1d04, 0x5c20, 0x2091, 0x6000, 0x1f04, 0x5c20, 0x0820, 0x6028, - 0xa085, 0x1e00, 0x602a, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, - 0x0008, 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, - 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, - 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb600, 0x2069, 0x0140, - 0x6020, 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005, 0x1904, 0x5c97, - 0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, - 0x080c, 0x28a7, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, 0x6808, - 0xa005, 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a, 0x6027, 0x0400, - 0x2069, 0xb8c6, 0x7000, 0x206a, 0x708f, 0x0026, 0x7003, 0x0001, - 0x20a9, 0x0002, 0x1d04, 0x5c7a, 0x2091, 0x6000, 0x1f04, 0x5c7a, - 0x0804, 0x5cc8, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00, - 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0520, 0xa084, 0x1a00, - 0x1508, 0x1d04, 0x5c86, 0x2091, 0x6000, 0x1f04, 0x5c86, 0x2011, - 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, 0x8106, 0x080c, - 0x7fe0, 0x2019, 0x0000, 0x080c, 0x806b, 0x6803, 0x00a0, 0x2001, - 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, - 0x0001, 0x00b0, 0x080c, 0x24e5, 0x6803, 0x0080, 0x2069, 0x0140, - 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, - 0x6886, 0x2001, 0xb88f, 0x2004, 0x080c, 0x28a7, 0x60e2, 0xa006, - 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, - 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2071, 0xb600, 0x6020, 0xa084, 0x00c0, 0x01e0, 0x2011, - 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, 0x8106, 0x080c, - 0x7fe0, 0x2019, 0x0000, 0x080c, 0x806b, 0x2069, 0x0140, 0x6803, - 0x00a0, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, - 0x0001, 0x0804, 0x5d6d, 0x2001, 0xb60c, 0x200c, 0xd1b4, 0x1160, - 0xc1b5, 0x2102, 0x080c, 0x59fc, 0x2069, 0x0140, 0x080c, 0x24e5, - 0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0xa005, - 0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfdff, 0x602a, - 0x6027, 0x0200, 0x2069, 0xb8c6, 0x7000, 0x206a, 0x708f, 0x0027, - 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x5d24, 0x2091, 0x6000, - 0x1f04, 0x5d24, 0x0804, 0x5d6d, 0x6027, 0x1e00, 0x2009, 0x1e00, - 0xe000, 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0, 0x1d04, - 0x5d2c, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x696b, - 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0xb8f4, - 0x7018, 0x00ee, 0xa005, 0x1d00, 0x0500, 0x0026, 0x2011, 0x5a14, - 0x080c, 0x6a0e, 0x2011, 0x5a07, 0x080c, 0x6ace, 0x002e, 0x2069, - 0x0140, 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, - 0x0008, 0x6886, 0x2001, 0xb88f, 0x2004, 0x080c, 0x28a7, 0x60e2, - 0x2001, 0xb60c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, - 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, - 0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb600, - 0x7130, 0xd184, 0x1180, 0x2011, 0xb653, 0x2214, 0xd2ec, 0x0138, - 0xc18d, 0x7132, 0x2011, 0xb653, 0x2214, 0xd2ac, 0x1120, 0x7030, - 0xd08c, 0x0904, 0x5dda, 0x7130, 0xc185, 0x7132, 0x2011, 0xb653, - 0x220c, 0xd1a4, 0x0530, 0x0016, 0x2019, 0x000e, 0x080c, 0xb121, - 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0xa186, 0x007e, 0x01a0, - 0xa186, 0x0080, 0x0188, 0x080c, 0x501b, 0x1170, 0x8127, 0xa006, - 0x0016, 0x2009, 0x000e, 0x080c, 0xb1a4, 0x2009, 0x0001, 0x2011, - 0x0100, 0x080c, 0x6b8c, 0x001e, 0x8108, 0x1f04, 0x5da5, 0x015e, - 0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, - 0x080c, 0x2ca4, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, - 0x0000, 0x080c, 0x501b, 0x1110, 0x080c, 0x4c7e, 0x8108, 0x1f04, - 0x5dd1, 0x015e, 0x080c, 0x1e63, 0x2011, 0x0003, 0x080c, 0x80fc, - 0x2011, 0x0002, 0x080c, 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, - 0x0000, 0x080c, 0x806b, 0x003e, 0x60e3, 0x0000, 0x2001, 0xb600, - 0x2003, 0x0001, 0x080c, 0x5a79, 0x00ee, 0x00ce, 0x004e, 0x003e, - 0x002e, 0x001e, 0x015e, 0x0005, 0x2071, 0xb6e2, 0x7003, 0x0000, - 0x7007, 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, - 0x7053, 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, - 0x708b, 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6, - 0x2071, 0xb6e2, 0x6848, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, - 0xa085, 0x0001, 0x0428, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, - 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, - 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, - 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, - 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, - 0x00ee, 0x0005, 0x2b78, 0x2071, 0xb6e2, 0x7004, 0x0043, 0x700c, - 0x0002, 0x5e56, 0x5e4d, 0x5e4d, 0x5e4d, 0x5e4d, 0x0005, 0x5eac, - 0x5ead, 0x5edf, 0x5ee0, 0x5eaa, 0x5f2e, 0x5f33, 0x5f64, 0x5f65, - 0x5f80, 0x5f81, 0x5f82, 0x5f83, 0x5f84, 0x5f85, 0x603b, 0x6062, - 0x700c, 0x0002, 0x5e6f, 0x5eaa, 0x5eaa, 0x5eab, 0x5eab, 0x7830, - 0x7930, 0xa106, 0x0120, 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, - 0xa10a, 0x01f8, 0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, - 0x080c, 0x15e4, 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, - 0x0003, 0x7057, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, - 0xb913, 0x2104, 0xc085, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, - 0x1664, 0x0005, 0x080c, 0x15e4, 0x0de0, 0x2d00, 0x705a, 0x080c, - 0x15e4, 0x1108, 0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, - 0x0004, 0x08f8, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x5eb4, - 0x5eb7, 0x5ec5, 0x5ede, 0x5ede, 0x080c, 0x5e68, 0x0005, 0x0126, - 0x8001, 0x700e, 0x7058, 0x0006, 0x080c, 0x63b5, 0x0120, 0x2091, - 0x8000, 0x080c, 0x5e68, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, - 0x080c, 0x63b5, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, - 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x003a, 0x1218, - 0x00db, 0x012e, 0x0005, 0x012e, 0x080c, 0x5f86, 0x0005, 0x0005, - 0x0005, 0x00e6, 0x2071, 0xb6e2, 0x700c, 0x0002, 0x5eeb, 0x5eeb, - 0x5eeb, 0x5eed, 0x5ef0, 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, - 0x700f, 0x0002, 0x00ee, 0x0005, 0x5f86, 0x5f86, 0x5fa2, 0x5f86, - 0x611f, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5fa2, 0x6161, - 0x61a4, 0x61ed, 0x6201, 0x5f86, 0x5f86, 0x5fbe, 0x5fa2, 0x5f86, - 0x5f86, 0x6018, 0x62ad, 0x62c8, 0x5f86, 0x5fbe, 0x5f86, 0x5f86, - 0x5f86, 0x5f86, 0x600e, 0x62c8, 0x5f86, 0x5f86, 0x5f86, 0x5f86, - 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5fd2, 0x5f86, 0x5f86, - 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x63d3, - 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5fe7, 0x7020, 0x2068, - 0x080c, 0x1614, 0x0005, 0x700c, 0x0002, 0x5f3a, 0x5f3d, 0x5f4b, - 0x5f63, 0x5f63, 0x080c, 0x5e68, 0x0005, 0x0126, 0x8001, 0x700e, - 0x7058, 0x0006, 0x080c, 0x63b5, 0x0120, 0x2091, 0x8000, 0x080c, - 0x5e68, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x63b5, - 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, - 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x1218, 0x003b, 0x012e, - 0x0005, 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x5f86, 0x5fa2, - 0x610b, 0x5f86, 0x5fa2, 0x5f86, 0x5fa2, 0x5fa2, 0x5f86, 0x5fa2, - 0x610b, 0x5fa2, 0x5fa2, 0x5fa2, 0x5fa2, 0x5fa2, 0x5f86, 0x5fa2, - 0x610b, 0x5f86, 0x5f86, 0x5fa2, 0x5f86, 0x5f86, 0x5f86, 0x5fa2, - 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x7007, 0x0001, - 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x0126, 0x2091, 0x8000, - 0x080c, 0x547a, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, - 0x00ff, 0xc0e5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, - 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, - 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, 0x012e, 0x0005, - 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x0126, - 0x2091, 0x8000, 0x080c, 0x547a, 0x012e, 0x0005, 0x6834, 0x8007, - 0xa084, 0x00ff, 0x0988, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, - 0x60cb, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, - 0x60cb, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, 0x5f94, - 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x60e8, 0x7007, 0x0006, - 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x60e8, 0x0005, 0x6834, - 0x8007, 0xa084, 0x00ff, 0xa086, 0x0001, 0x1904, 0x5f94, 0x7007, - 0x0001, 0x2009, 0xb631, 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, - 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x4df4, 0x1108, 0x0005, - 0x0126, 0x2091, 0x8000, 0x6837, 0x0139, 0x684a, 0x6952, 0x080c, - 0x547a, 0x012e, 0x0ca0, 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, - 0x00c0, 0xa086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x62e0, - 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, - 0x20a1, 0xb70d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, - 0x5fb0, 0x6a84, 0xa28a, 0x0002, 0x1a04, 0x5fb0, 0x82ff, 0x1138, - 0x6888, 0x698c, 0xa105, 0x0118, 0x2001, 0x609e, 0x0018, 0xa280, - 0x6094, 0x2005, 0x70c6, 0x7010, 0xa015, 0x0904, 0x6080, 0x080c, - 0x15e4, 0x1118, 0x7007, 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, - 0x2060, 0x2c05, 0x6836, 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, - 0x1210, 0xa00e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, - 0x0004, 0x0108, 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, - 0x080c, 0x1648, 0x7090, 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, - 0x0118, 0x7007, 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x1614, - 0x7014, 0x2068, 0x0804, 0x5fb0, 0x7020, 0x2068, 0x7018, 0x6802, - 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x603b, - 0x7014, 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x1128, 0x6888, - 0x698c, 0xa105, 0x0108, 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, - 0x001e, 0x0904, 0x62e0, 0x04b8, 0x6096, 0x609a, 0x0002, 0x0011, - 0x0007, 0x0004, 0x000a, 0x000f, 0x0005, 0x0006, 0x000a, 0x0011, - 0x0005, 0x0004, 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, - 0x6e8c, 0x6804, 0x2060, 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, - 0x0005, 0x700c, 0x7816, 0x7008, 0x7812, 0x7004, 0x7806, 0x7000, - 0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, - 0x0006, 0x0c78, 0x6004, 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, - 0x00ee, 0x00fe, 0x0005, 0x2009, 0xb631, 0x210c, 0x81ff, 0x1198, - 0x6838, 0xa084, 0x00ff, 0x683a, 0x080c, 0x4cd7, 0x1108, 0x0005, - 0x080c, 0x554d, 0x0126, 0x2091, 0x8000, 0x080c, 0x9f88, 0x080c, - 0x547a, 0x012e, 0x0ca0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, - 0x2009, 0xb631, 0x210c, 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01c0, - 0x6838, 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x4d98, - 0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0x684a, 0x6952, 0x080c, - 0x547a, 0x012e, 0x0cb0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c90, - 0x2001, 0x0000, 0x0c78, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, - 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0006, 0x0030, - 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x7007, - 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff, - 0x20a9, 0x0001, 0xa096, 0x0001, 0x01b0, 0x2009, 0x0000, 0x20a9, - 0x00ff, 0xa096, 0x0002, 0x0178, 0xa005, 0x11f0, 0x6944, 0x810f, - 0xa18c, 0x00ff, 0x080c, 0x501b, 0x11b8, 0x0066, 0x6e50, 0x080c, - 0x511a, 0x006e, 0x0088, 0x0046, 0x2011, 0xb60c, 0x2224, 0xc484, - 0x2412, 0x004e, 0x00c6, 0x080c, 0x501b, 0x1110, 0x080c, 0x527b, - 0x8108, 0x1f04, 0x614b, 0x00ce, 0x684c, 0xd084, 0x1118, 0x080c, - 0x1614, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, 0x012e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xb653, - 0x2004, 0xd0a4, 0x0580, 0x2061, 0xb975, 0x6100, 0xd184, 0x0178, - 0x6858, 0xa084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, - 0xa005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, - 0x0001, 0x6860, 0xa005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, - 0x6858, 0xa084, 0x00ff, 0x0178, 0x6006, 0x6858, 0x8007, 0xa084, - 0x00ff, 0x0148, 0x600a, 0x6858, 0x8000, 0x1108, 0xc28d, 0x6202, - 0x012e, 0x0804, 0x63a4, 0x012e, 0x0804, 0x639e, 0x012e, 0x0804, - 0x6398, 0x012e, 0x0804, 0x639b, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0xb975, - 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48, - 0xa484, 0x0003, 0x0170, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120, - 0x2100, 0xa210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0xa212, - 0x02f0, 0xa484, 0x000c, 0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff, - 0xa082, 0x0004, 0x1120, 0x2100, 0xa318, 0x0288, 0x0030, 0xa082, - 0x0004, 0x1168, 0x2100, 0xa31a, 0x0250, 0x6860, 0xa005, 0x0110, - 0x8000, 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x63a4, 0x012e, - 0x0804, 0x63a1, 0x012e, 0x0804, 0x639e, 0x0126, 0x2091, 0x8000, - 0x7007, 0x0001, 0x2061, 0xb975, 0x6300, 0xd38c, 0x1120, 0x6308, - 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x63b2, 0x012e, 0x0804, - 0x63a1, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, - 0xd0ac, 0x0148, 0x00c6, 0x2061, 0xb975, 0x6000, 0xa084, 0xfcff, - 0x6002, 0x00ce, 0x0448, 0x6858, 0xa005, 0x05d0, 0x685c, 0xa065, - 0x0598, 0x2001, 0xb631, 0x2004, 0xa005, 0x0118, 0x080c, 0x9ed9, - 0x0068, 0x6013, 0x0400, 0x6057, 0x0000, 0x694c, 0xd1a4, 0x0110, - 0x6950, 0x6156, 0x2009, 0x0041, 0x080c, 0x86d3, 0x6958, 0xa18c, - 0xff00, 0xa186, 0x2000, 0x1140, 0x0026, 0x2009, 0x0000, 0x2011, - 0xfdff, 0x080c, 0x6b8c, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061, - 0xb975, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, - 0x00ce, 0x012e, 0x0804, 0x63a4, 0x00ce, 0x012e, 0x0804, 0x639e, - 0x6954, 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d, 0x0d28, 0xa186, - 0x0045, 0x0528, 0xa186, 0x002a, 0x1130, 0x2001, 0xb60c, 0x200c, - 0xc194, 0x2102, 0x08c8, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029, - 0x1d18, 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x501b, 0x1960, - 0x6000, 0xc0e4, 0x6002, 0x0840, 0x685c, 0xa065, 0x09a8, 0x6007, - 0x0024, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x0804, 0x623c, 0x685c, - 0xa065, 0x0950, 0x00e6, 0x6860, 0xa075, 0x2001, 0xb631, 0x2004, - 0xa005, 0x0150, 0x080c, 0x9ed9, 0x8eff, 0x0118, 0x2e60, 0x080c, - 0x9ed9, 0x00ee, 0x0804, 0x623c, 0x6020, 0xc0dc, 0xc0d5, 0x6022, - 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b, - 0x6874, 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x6cff, - 0x080c, 0x71e5, 0x00ee, 0x0804, 0x623c, 0x2061, 0xb975, 0x6000, - 0xd084, 0x0190, 0xd08c, 0x1904, 0x63b2, 0x0126, 0x2091, 0x8000, - 0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x63b2, 0x012e, - 0x6853, 0x0016, 0x0804, 0x63ab, 0x6853, 0x0007, 0x0804, 0x63ab, - 0x6834, 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x5f94, 0x0078, - 0x2030, 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, - 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x62e0, 0x0005, - 0x00e6, 0x0126, 0x2091, 0x8000, 0xa03e, 0x2009, 0xb631, 0x210c, - 0x81ff, 0x1904, 0x635e, 0x2009, 0xb60c, 0x210c, 0xd194, 0x1904, - 0x6388, 0x6848, 0x2070, 0xae82, 0xbe00, 0x0a04, 0x6352, 0x2001, - 0xb617, 0x2004, 0xae02, 0x1a04, 0x6352, 0x711c, 0xa186, 0x0006, - 0x1904, 0x6341, 0x7018, 0xa005, 0x0904, 0x635e, 0x2004, 0xd0e4, - 0x1904, 0x6383, 0x2061, 0xb975, 0x6100, 0xa184, 0x0301, 0xa086, - 0x0001, 0x1550, 0x7020, 0xd0dc, 0x1904, 0x638b, 0x6853, 0x0000, - 0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, - 0xd0f4, 0x1904, 0x638e, 0x2e60, 0x080c, 0x6ae8, 0x012e, 0x00ee, - 0x0005, 0x2068, 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, - 0xd0f4, 0x1904, 0x638e, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, - 0x6853, 0x0006, 0x0804, 0x63ab, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, - 0x00b8, 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x501b, 0x15d8, - 0x6000, 0xd0e4, 0x15c0, 0x711c, 0xa186, 0x0007, 0x1118, 0x6853, - 0x0002, 0x0498, 0x6853, 0x0008, 0x0480, 0x6853, 0x000e, 0x0468, - 0x6853, 0x0017, 0x0450, 0x6853, 0x0035, 0x0438, 0x2001, 0xb672, - 0x2004, 0xd0fc, 0x01e8, 0x6848, 0x2070, 0xae82, 0xbe00, 0x02c0, - 0x605c, 0xae02, 0x12a8, 0x711c, 0xa186, 0x0006, 0x1188, 0x7018, - 0xa005, 0x0170, 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, - 0xa086, 0x0007, 0x1904, 0x62eb, 0x7003, 0x0002, 0x0804, 0x62eb, - 0x6853, 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee, 0x0418, - 0x6853, 0x002a, 0x0cd0, 0x6853, 0x0045, 0x0cb8, 0x2e60, 0x2019, - 0x0002, 0x6017, 0x0014, 0x080c, 0xad9c, 0x012e, 0x00ee, 0x0005, - 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006, - 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0x6854, 0xa084, - 0xff00, 0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, - 0x012e, 0x0005, 0x080c, 0x1614, 0x0005, 0x702c, 0x7130, 0x8108, - 0xa102, 0x0230, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0058, - 0x7070, 0xa080, 0x0040, 0x7072, 0x1230, 0x7074, 0xa081, 0x0000, - 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c, - 0x6adf, 0x00de, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, - 0x7007, 0x0001, 0x6a44, 0xa282, 0x0004, 0x1a04, 0x641e, 0xd284, - 0x0170, 0x6a4c, 0xa290, 0xb735, 0x2204, 0xa065, 0x6004, 0x05e0, - 0x8007, 0xa084, 0x00ff, 0xa084, 0x0006, 0x1108, 0x04a8, 0x2c10, - 0x080c, 0x864e, 0x1118, 0x080c, 0x9f92, 0x05a0, 0x621a, 0x6844, - 0x0002, 0x63fd, 0x6402, 0x6405, 0x640b, 0x2019, 0x0002, 0x080c, - 0xb121, 0x0060, 0x080c, 0xb0b8, 0x0048, 0x2019, 0x0002, 0x6950, - 0x080c, 0xb0d3, 0x0018, 0x6950, 0x080c, 0xb0b8, 0x080c, 0x86a4, - 0x6857, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, 0x012e, - 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0x6857, 0x0006, - 0x0c88, 0x6857, 0x0002, 0x0c70, 0x6857, 0x0005, 0x0c58, 0x6857, - 0x0004, 0x0c40, 0x6857, 0x0007, 0x0c28, 0x00d6, 0x2011, 0x0004, - 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, 0x0005, 0x20e1, 0x0002, - 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0118, 0xa086, - 0x1000, 0x1570, 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, 0x8217, - 0xa084, 0xf000, 0xa086, 0x3000, 0x1160, 0xa184, 0xff00, 0x8007, - 0xa086, 0x0008, 0x11e8, 0x080c, 0x2df4, 0x11d0, 0x080c, 0x6675, - 0x0098, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x1108, 0x3e60, 0xac84, - 0x0007, 0x1170, 0xac82, 0xbe00, 0x0258, 0x685c, 0xac02, 0x1240, - 0x2009, 0x0047, 0x080c, 0x86d3, 0x7a1c, 0xd284, 0x1938, 0x0005, - 0xa016, 0x080c, 0x1863, 0x0cc0, 0x0cd8, 0x781c, 0xd08c, 0x0500, - 0x0156, 0x0136, 0x0146, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, - 0x0076, 0x1538, 0xa484, 0x7000, 0xa086, 0x1000, 0x11a8, 0x080c, - 0x64f0, 0x01f8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x080c, 0x650c, - 0x014e, 0x013e, 0x015e, 0x2009, 0xb8e9, 0x2104, 0xa005, 0x1108, - 0x0005, 0x080c, 0x71e5, 0x0ce0, 0xa484, 0x7000, 0x1548, 0x080c, - 0x64f0, 0x01d8, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x0d10, - 0x00a0, 0xd5a4, 0x0178, 0x0056, 0x0046, 0x080c, 0x1e8a, 0x080c, - 0x24e5, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x004e, - 0x005e, 0x0048, 0x04a9, 0x6887, 0x0000, 0x080c, 0xb49b, 0x20e1, - 0x3000, 0x7828, 0x7828, 0x00b9, 0x014e, 0x013e, 0x015e, 0x0880, - 0x0439, 0x1130, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x1d68, - 0x080c, 0xb49b, 0x20e1, 0x3000, 0x7828, 0x7828, 0x0056, 0x080c, - 0x68e6, 0x005e, 0x0c40, 0x2001, 0xb60e, 0x2004, 0xd08c, 0x0178, - 0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x1148, 0x0026, 0x0036, - 0x2011, 0x8048, 0x2518, 0x080c, 0x3f13, 0x003e, 0x002e, 0x0005, - 0xa484, 0x01ff, 0x6886, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084, - 0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, - 0x0005, 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, - 0x53a5, 0xa085, 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c, - 0xf000, 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x677a, 0x0005, - 0xa196, 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, - 0x44d6, 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, - 0x6826, 0x0c68, 0x00c6, 0x6a84, 0x82ff, 0x0904, 0x666f, 0x7110, - 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023, - 0x1904, 0x666f, 0xa08e, 0x0023, 0x1570, 0x080c, 0x68c1, 0x0904, - 0x666f, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034, - 0xa005, 0x1904, 0x666f, 0x2009, 0x0015, 0x080c, 0x86d3, 0x0804, - 0x666f, 0xa08e, 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, 0x2009, - 0x0015, 0x080c, 0x86d3, 0x0804, 0x666f, 0xa08e, 0x0100, 0x1904, - 0x666f, 0x7034, 0xa005, 0x1904, 0x666f, 0x2009, 0x0016, 0x080c, - 0x86d3, 0x0804, 0x666f, 0xa08e, 0x0022, 0x1904, 0x666f, 0x7030, - 0xa08e, 0x0300, 0x1580, 0x68d4, 0xd0a4, 0x0528, 0xc0b5, 0x68d6, - 0x7100, 0xa18c, 0x00ff, 0x6972, 0x7004, 0x6876, 0x00f6, 0x2079, - 0x0100, 0x79e6, 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, - 0x080c, 0x287c, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, - 0x2852, 0x6952, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, - 0xb600, 0x70a6, 0x00ee, 0x7034, 0xa005, 0x1904, 0x666f, 0x2009, - 0x0017, 0x0804, 0x6635, 0xa08e, 0x0400, 0x1158, 0x7034, 0xa005, - 0x1904, 0x666f, 0x68d4, 0xc0a5, 0x68d6, 0x2009, 0x0030, 0x0804, - 0x6635, 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, 0x666f, - 0x2009, 0x0018, 0x0804, 0x6635, 0xa08e, 0x2010, 0x1120, 0x2009, - 0x0019, 0x0804, 0x6635, 0xa08e, 0x2110, 0x1120, 0x2009, 0x001a, - 0x0804, 0x6635, 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, 0x1904, - 0x666f, 0x2009, 0x001b, 0x0804, 0x6635, 0xa08e, 0x5000, 0x1140, - 0x7034, 0xa005, 0x1904, 0x666f, 0x2009, 0x001c, 0x0804, 0x6635, - 0xa08e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x6635, 0xa08e, - 0x1200, 0x1140, 0x7034, 0xa005, 0x1904, 0x666f, 0x2009, 0x0024, - 0x0804, 0x6635, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1118, 0x2009, - 0x002d, 0x04d8, 0xa08c, 0xff00, 0xa18e, 0x5300, 0x1118, 0x2009, - 0x002a, 0x0498, 0xa08e, 0x0f00, 0x1118, 0x2009, 0x0020, 0x0468, - 0xa08e, 0x5300, 0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011, - 0xbc8d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, - 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3f13, - 0x004e, 0x8108, 0x1f04, 0x6618, 0x2009, 0x0023, 0x0070, 0xa08e, - 0x6000, 0x1118, 0x2009, 0x003f, 0x0040, 0xa08e, 0x7800, 0x1118, - 0x2009, 0x0045, 0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xbc83, - 0x2204, 0x8211, 0x220c, 0x080c, 0x2852, 0x1598, 0x080c, 0x4fbf, - 0x1580, 0x6612, 0x6516, 0x86ff, 0x01e8, 0x001e, 0x0016, 0xa186, - 0x0017, 0x1158, 0x6870, 0xa606, 0x11a8, 0x6874, 0xa506, 0xa084, - 0xff00, 0x1180, 0x6000, 0xc0f5, 0x6002, 0xa186, 0x0046, 0x1150, - 0x6870, 0xa606, 0x1138, 0x6874, 0xa506, 0xa084, 0xff00, 0x1110, - 0x001e, 0x0068, 0x00c6, 0x080c, 0x864e, 0x0168, 0x001e, 0x611a, - 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x86d3, 0x00ce, - 0x0005, 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00c6, 0x0046, 0x080c, - 0x66c9, 0x1904, 0x66c6, 0xa28e, 0x0033, 0x11e8, 0x080c, 0x68c1, - 0x0904, 0x66c6, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140, - 0x7034, 0xa005, 0x15d8, 0x2009, 0x0015, 0x080c, 0x86d3, 0x04b0, - 0xa08e, 0x0100, 0x1598, 0x7034, 0xa005, 0x1580, 0x2009, 0x0016, - 0x080c, 0x86d3, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e, - 0x1400, 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xbc83, 0x2204, - 0x8211, 0x220c, 0x080c, 0x2852, 0x11c0, 0x080c, 0x4fbf, 0x11a8, - 0x6612, 0x6516, 0x00c6, 0x080c, 0x864e, 0x0170, 0x001e, 0x611a, - 0x080c, 0xa0e3, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, - 0x86d3, 0x080c, 0x71e5, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, - 0x0005, 0x00f6, 0x00d6, 0x0026, 0x0016, 0x0136, 0x0146, 0x0156, - 0x3c00, 0x0006, 0x2079, 0x0030, 0x2069, 0x0200, 0x080c, 0x1f49, - 0x1590, 0x080c, 0x1dee, 0x05e0, 0x04f1, 0x1130, 0x7908, 0xa18c, - 0x1fff, 0xa182, 0x0011, 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000, - 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, - 0x2004, 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0419, - 0x1120, 0xa08a, 0x0140, 0x1a0c, 0x151a, 0x80ac, 0x20e1, 0x6000, - 0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, - 0x0004, 0xa294, 0x0070, 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e, - 0x001e, 0x002e, 0x00de, 0x00fe, 0x0005, 0xa016, 0x080c, 0x1863, - 0xa085, 0x0001, 0x0c80, 0x0006, 0x2001, 0x0111, 0x2004, 0xa084, - 0x0003, 0x000e, 0x0005, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, - 0xa696, 0x00ff, 0x1198, 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, - 0x0804, 0x6775, 0xa596, 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, - 0xa596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, - 0x2019, 0xb635, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, - 0x00ff, 0x2071, 0xb735, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, - 0x2071, 0xb7b6, 0x2e1c, 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, - 0xc2fd, 0x0080, 0x2368, 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, - 0x6b14, 0x1120, 0xa346, 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, - 0x83ff, 0x0d58, 0x8420, 0x8e70, 0x1f04, 0x6752, 0x82ff, 0x1118, - 0xa085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, - 0x004e, 0x0005, 0xa084, 0x0007, 0x000a, 0x0005, 0x6786, 0x6786, - 0x6786, 0x68d3, 0x6786, 0x6787, 0x679c, 0x6811, 0x0005, 0x7110, - 0xd1bc, 0x0188, 0x7120, 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, - 0xbe00, 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, - 0x0046, 0x080c, 0x86d3, 0x0005, 0x00c6, 0xa484, 0x01ff, 0x0904, - 0x67ef, 0x7110, 0xd1bc, 0x1904, 0x67ef, 0x2011, 0xbc83, 0x2204, - 0x8211, 0x220c, 0x080c, 0x2852, 0x1904, 0x67ef, 0x080c, 0x4fbf, - 0x15f0, 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15c8, 0x6204, 0xa294, - 0xff00, 0x8217, 0xa286, 0x0006, 0x0148, 0x6204, 0xa294, 0x00ff, - 0xa286, 0x0006, 0x11a0, 0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, - 0x864e, 0x001e, 0x0530, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, - 0x7130, 0x6152, 0x2009, 0x0044, 0x080c, 0x86d3, 0x00c0, 0x00c6, - 0x080c, 0x864e, 0x001e, 0x0198, 0x611a, 0x601f, 0x0004, 0x7120, - 0x610a, 0xa286, 0x0004, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, - 0x0001, 0x6003, 0x0001, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00ce, - 0x0005, 0x2001, 0xb60d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, - 0x080c, 0x3f13, 0x00c6, 0x080c, 0x9f92, 0x001e, 0x0d80, 0x611a, - 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x6013, 0x0300, - 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6cff, 0x080c, 0x71e5, - 0x08f0, 0x7110, 0xd1bc, 0x0188, 0x7020, 0x2060, 0xac84, 0x0007, - 0x1160, 0xac82, 0xbe00, 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, - 0x610a, 0x2009, 0x0045, 0x080c, 0x86d3, 0x0005, 0x0006, 0x080c, - 0x2df4, 0x000e, 0x1168, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, - 0x0000, 0x1130, 0xa084, 0x000f, 0xa08a, 0x0006, 0x1208, 0x000b, - 0x0005, 0x683f, 0x6840, 0x683f, 0x683f, 0x68a9, 0x68b5, 0x0005, - 0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x68a8, 0x700c, - 0x7108, 0x080c, 0x2852, 0x1904, 0x68a8, 0x080c, 0x4fbf, 0x1904, - 0x68a8, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x01f8, 0xa28c, - 0x00ff, 0xa186, 0x0004, 0x0118, 0xa186, 0x0006, 0x15c8, 0x00c6, - 0x080c, 0x68c1, 0x00ce, 0x0904, 0x68a8, 0x00c6, 0x080c, 0x864e, - 0x001e, 0x05f0, 0x611a, 0x080c, 0xa0e3, 0x601f, 0x0002, 0x7120, - 0x610a, 0x2009, 0x0088, 0x080c, 0x86d3, 0x0490, 0xa28c, 0x00ff, - 0xa186, 0x0006, 0x0160, 0xa186, 0x0004, 0x0148, 0xa294, 0xff00, - 0x8217, 0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1188, 0x00c6, - 0x080c, 0x864e, 0x001e, 0x01e0, 0x611a, 0x080c, 0xa0e3, 0x601f, - 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x86d3, 0x0080, - 0x00c6, 0x080c, 0x864e, 0x001e, 0x0158, 0x611a, 0x080c, 0xa0e3, - 0x601f, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x86d3, - 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, 0x7124, 0x610a, - 0x2009, 0x0089, 0x080c, 0x86d3, 0x0005, 0x7110, 0xd1bc, 0x0140, - 0x0041, 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x86d3, - 0x0005, 0x7020, 0x2060, 0xac84, 0x0007, 0x1158, 0xac82, 0xbe00, - 0x0240, 0x2001, 0xb617, 0x2004, 0xac02, 0x1218, 0xa085, 0x0001, - 0x0005, 0xa006, 0x0ce8, 0x7110, 0xd1bc, 0x1178, 0x7024, 0x2060, - 0xac84, 0x0007, 0x1150, 0xac82, 0xbe00, 0x0238, 0x685c, 0xac02, - 0x1220, 0x2009, 0x0051, 0x080c, 0x86d3, 0x0005, 0x2031, 0x0105, - 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, - 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, - 0x00f6, 0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x05b0, 0x080c, - 0x864e, 0x0598, 0x0066, 0x00c6, 0x0046, 0x2011, 0xbc83, 0x2204, - 0x8211, 0x220c, 0x080c, 0x2852, 0x1580, 0x080c, 0x4fbf, 0x1568, - 0x6612, 0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, 0xa0e3, - 0x080c, 0x15fd, 0x01f0, 0x2d00, 0x6056, 0x6803, 0x0000, 0x6837, - 0x0000, 0x6c3a, 0xadf8, 0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98, - 0x53a3, 0x006e, 0x6612, 0x6007, 0x003e, 0x601f, 0x0001, 0x6003, - 0x0001, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00fe, 0x00de, 0x00ce, - 0x0005, 0x080c, 0x86a4, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, - 0x2071, 0xb8f4, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, - 0x7076, 0x7012, 0x7017, 0xbe00, 0x7007, 0x0000, 0x7026, 0x702b, - 0x7e0a, 0x7032, 0x7037, 0x7e6a, 0x703b, 0xffff, 0x703f, 0xffff, - 0x7042, 0x7047, 0x4492, 0x704a, 0x705b, 0x6a9d, 0x2001, 0xb8a1, - 0x2003, 0x0003, 0x2001, 0xb8a3, 0x2003, 0x0100, 0x3a00, 0xa084, - 0x0005, 0x706e, 0x0005, 0x2071, 0xb8f4, 0x1d04, 0x69fd, 0x2091, - 0x6000, 0x700c, 0x8001, 0x700e, 0x1518, 0x700f, 0x0361, 0x7007, - 0x0001, 0x0126, 0x2091, 0x8000, 0x7040, 0xa00d, 0x0128, 0x8109, - 0x7142, 0x1110, 0x7044, 0x080f, 0x00c6, 0x2061, 0xb600, 0x6034, - 0x00ce, 0xd0cc, 0x0180, 0x3a00, 0xa084, 0x0005, 0x726c, 0xa216, - 0x0150, 0x706e, 0x2011, 0x8043, 0x2018, 0x080c, 0x3f13, 0x0018, - 0x0126, 0x2091, 0x8000, 0x7024, 0xa00d, 0x0188, 0x7020, 0x8001, - 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, - 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, - 0xa00d, 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009, - 0x8109, 0x7132, 0x0128, 0xa184, 0x007f, 0x090c, 0x7eaf, 0x0010, - 0x7034, 0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a, - 0x703c, 0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0xa00d, - 0x0168, 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109, - 0x714e, 0x1120, 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0xa00d, - 0x01d8, 0x0016, 0x7074, 0xa00d, 0x0158, 0x7070, 0x8001, 0x7072, - 0x1138, 0x7073, 0x0009, 0x8109, 0x7176, 0x1110, 0x7078, 0x080f, - 0x001e, 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, - 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x6a23, - 0x6a24, 0x6a3c, 0x00e6, 0x2071, 0xb8f4, 0x7018, 0xa005, 0x1120, - 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, - 0x2071, 0xb8f4, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e, - 0x00ee, 0x0005, 0x00e6, 0x2071, 0xb8f4, 0x6088, 0xa102, 0x0208, - 0x618a, 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x501b, 0x1158, - 0x6088, 0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, - 0x080c, 0x71e5, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e, - 0x7007, 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, - 0x8000, 0x603c, 0xa005, 0x0128, 0x8001, 0x603e, 0x1110, 0x080c, - 0x9fd1, 0x6014, 0xa005, 0x0500, 0x8001, 0x6016, 0x11e8, 0x611c, - 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x11a0, 0x6010, 0x2068, - 0x6854, 0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, - 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, - 0x6116, 0x0010, 0x080c, 0x9aa1, 0x012e, 0xac88, 0x0018, 0x7116, - 0x2001, 0xee00, 0xa102, 0x0220, 0x7017, 0xbe00, 0x7007, 0x0000, - 0x0005, 0x00e6, 0x2071, 0xb8f4, 0x7027, 0x07d0, 0x7023, 0x0009, - 0x00ee, 0x0005, 0x2001, 0xb8fd, 0x2003, 0x0000, 0x0005, 0x00e6, - 0x2071, 0xb8f4, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, - 0xb900, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0xb8f4, 0x711a, - 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x0026, 0x7054, - 0x8000, 0x7056, 0x2061, 0xb8a1, 0x6008, 0xa086, 0x0000, 0x0158, - 0x7068, 0x6032, 0x7064, 0x602e, 0x7060, 0x602a, 0x705c, 0x6026, - 0x2c10, 0x080c, 0x1648, 0x002e, 0x00ce, 0x0005, 0x0006, 0x0016, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x696b, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0xb8f4, - 0x7176, 0x727a, 0x7073, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, - 0x2071, 0xb8f4, 0x7078, 0xa206, 0x1110, 0x7076, 0x707a, 0x000e, - 0x00ee, 0x0005, 0x00c6, 0x2061, 0xb975, 0x00ce, 0x0005, 0xa184, - 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0xb975, 0x2060, 0x0005, - 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0xa005, 0x1150, - 0x00c6, 0x2061, 0xb975, 0x6014, 0x00ce, 0xa005, 0x1138, 0x2001, - 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006, 0x8003, 0x800b, - 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0, 0xa18e, 0x00c0, - 0x05e8, 0xd0b4, 0x1138, 0xd0bc, 0x1550, 0x2009, 0x0006, 0x080c, - 0x6b63, 0x0005, 0xd0fc, 0x0138, 0xa084, 0x0003, 0x0120, 0xa086, - 0x0003, 0x1904, 0x6b5d, 0x6020, 0xd0d4, 0x0130, 0xc0d4, 0x6022, - 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xb674, 0x2104, 0xd084, - 0x0138, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x86d3, 0x0005, - 0x87ff, 0x1120, 0x2009, 0x0043, 0x080c, 0x86d3, 0x0005, 0xd0fc, - 0x0130, 0xa084, 0x0003, 0x0118, 0xa086, 0x0003, 0x11f0, 0x87ff, - 0x1120, 0x2009, 0x0042, 0x080c, 0x86d3, 0x0005, 0xd0fc, 0x0160, - 0xa084, 0x0003, 0xa08e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, - 0x0041, 0x080c, 0x86d3, 0x0005, 0x0061, 0x0ce8, 0x87ff, 0x1dd8, - 0x2009, 0x0043, 0x080c, 0x86d3, 0x0cb0, 0x2009, 0x0004, 0x0019, - 0x0005, 0x2009, 0x0001, 0x00d6, 0x6010, 0xa0ec, 0xf000, 0x0510, - 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x1188, 0x694c, - 0xa18c, 0x8100, 0xa18e, 0x8100, 0x1158, 0x00c6, 0x2061, 0xb975, - 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, - 0x080c, 0x547a, 0x6010, 0xa06d, 0x0076, 0x2039, 0x0000, 0x190c, - 0x6ae8, 0x007e, 0x00de, 0x0005, 0x0156, 0x00c6, 0x2061, 0xb975, - 0x6000, 0x81ff, 0x0110, 0xa205, 0x0008, 0xa204, 0x6002, 0x00ce, - 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0xa005, 0x0120, - 0x8001, 0x680a, 0xa085, 0x0001, 0x0005, 0x20a9, 0x0010, 0xa006, - 0x8004, 0x8086, 0x818e, 0x1208, 0xa200, 0x1f04, 0x6ba9, 0x8086, - 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, - 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, 0x6bb9, - 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, 0x6bb9, 0x0006, 0x3200, - 0xa084, 0xefff, 0x2080, 0x000e, 0x015e, 0x0005, 0x0006, 0x3200, - 0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091, 0x2800, 0x2079, 0xb8e1, - 0x012e, 0x00d6, 0x2069, 0xb8e1, 0x6803, 0x0005, 0x2069, 0x0004, - 0x2d04, 0xa085, 0x8001, 0x206a, 0x00de, 0x0005, 0x00c6, 0x6027, - 0x0001, 0x7804, 0xa084, 0x0007, 0x0002, 0x6bf7, 0x6c18, 0x6c6b, - 0x6bfd, 0x6c18, 0x6bf7, 0x6bf5, 0x6bf5, 0x080c, 0x151a, 0x080c, - 0x6a82, 0x080c, 0x71e5, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, - 0x00ce, 0x0005, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x7828, 0xa092, - 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, 0x4b65, 0x0c88, 0x080c, - 0x4b23, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c40, - 0x080c, 0x6a82, 0x3c00, 0x0006, 0x2011, 0x0209, 0x20e1, 0x4000, - 0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178, 0x62c0, 0x82ff, 0x1160, - 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x151a, 0x2009, 0x0013, - 0x080c, 0x86d3, 0x00ce, 0x0005, 0x3900, 0xa082, 0xba2d, 0x1210, - 0x080c, 0x83b9, 0x00c6, 0x7824, 0xa065, 0x090c, 0x151a, 0x7804, - 0xa086, 0x0004, 0x0904, 0x6cab, 0x7828, 0xa092, 0x2710, 0x1230, - 0x8000, 0x782a, 0x00ce, 0x080c, 0x7de6, 0x0c20, 0x6104, 0xa186, - 0x0003, 0x1188, 0x00e6, 0x2071, 0xb600, 0x70e0, 0x00ee, 0xd08c, - 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb600, 0x080c, - 0x4b7b, 0x00ee, 0x00ce, 0x080c, 0xb500, 0x2009, 0x0014, 0x080c, - 0x86d3, 0x00ce, 0x0838, 0x2001, 0xb8fd, 0x2003, 0x0000, 0x62c0, - 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x151a, - 0x2009, 0x0013, 0x080c, 0x872c, 0x00ce, 0x0005, 0x00c6, 0x00d6, - 0x3900, 0xa082, 0xba2d, 0x1210, 0x080c, 0x83b9, 0x7824, 0xa005, - 0x090c, 0x151a, 0x781c, 0xa06d, 0x090c, 0x151a, 0x6800, 0xc0dc, - 0x6802, 0x7924, 0x2160, 0x080c, 0x86a4, 0x693c, 0x81ff, 0x090c, - 0x151a, 0x8109, 0x693e, 0x6854, 0xa015, 0x0110, 0x7a1e, 0x0010, - 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, - 0x080c, 0x71e5, 0x0888, 0x6104, 0xa186, 0x0002, 0x0128, 0xa186, - 0x0004, 0x0110, 0x0804, 0x6c44, 0x7808, 0xac06, 0x0904, 0x6c44, - 0x080c, 0x7102, 0x080c, 0x6d45, 0x00ce, 0x080c, 0x71e5, 0x0804, - 0x6c32, 0x00c6, 0x6027, 0x0002, 0x62c8, 0x60c4, 0xa205, 0x1178, - 0x793c, 0xa1e5, 0x0000, 0x0130, 0x2009, 0x0049, 0x080c, 0x86d3, - 0x00ce, 0x0005, 0x2011, 0xb900, 0x2013, 0x0000, 0x0cc8, 0x3908, - 0xa192, 0xba2d, 0x1210, 0x080c, 0x83b9, 0x793c, 0x81ff, 0x0d90, - 0x7944, 0xa192, 0x7530, 0x12b8, 0x8108, 0x7946, 0x793c, 0xa188, - 0x0007, 0x210c, 0xa18e, 0x0006, 0x1138, 0x6014, 0xa084, 0x0184, - 0xa085, 0x0012, 0x6016, 0x08e0, 0x6014, 0xa084, 0x0184, 0xa085, - 0x0016, 0x6016, 0x08a8, 0x7848, 0xc085, 0x784a, 0x0888, 0x0006, - 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, - 0x2061, 0xb8e1, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0148, - 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, - 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0xb8e1, 0x6000, - 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x1110, - 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x71eb, 0xc0d5, - 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000, 0x0006, - 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0xb8e1, 0x0c18, 0x6056, - 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xb8e1, - 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080, 0x0003, - 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x610e, - 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, 0xb8e1, - 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136, 0x00ce, - 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, - 0xa02e, 0x2071, 0xb8e1, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, - 0x8cff, 0x0904, 0x6ded, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, - 0x1904, 0x6de8, 0x87ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6de8, - 0x703c, 0xac06, 0x1190, 0x0036, 0x2019, 0x0001, 0x080c, 0x806b, - 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, - 0x704b, 0x0000, 0x003e, 0x2029, 0x0001, 0x7038, 0xac36, 0x1110, - 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, - 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, - 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, - 0x9d16, 0x01c8, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x1580, - 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x0016, 0x0036, 0x0076, - 0x080c, 0x9f88, 0x080c, 0xb43c, 0x080c, 0x547a, 0x007e, 0x003e, - 0x001e, 0x080c, 0x9ecd, 0x080c, 0x9ed9, 0x00ce, 0x0804, 0x6d88, - 0x2c78, 0x600c, 0x2060, 0x0804, 0x6d88, 0x85ff, 0x0120, 0x0036, - 0x080c, 0x72a2, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, - 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x601c, 0xa086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, - 0xb43c, 0x080c, 0xb155, 0x007e, 0x003e, 0x001e, 0x08a0, 0x601c, - 0xa086, 0x000a, 0x0904, 0x6dd2, 0x0804, 0x6dd0, 0x0006, 0x0066, - 0x00c6, 0x00d6, 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, - 0x2079, 0xb8e1, 0x7838, 0xa065, 0x0568, 0x600c, 0x0006, 0x600f, - 0x0000, 0x783c, 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c, - 0x806b, 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, - 0x0000, 0x784b, 0x0000, 0x003e, 0x080c, 0x9d16, 0x0178, 0x6010, - 0x2068, 0x601c, 0xa086, 0x0003, 0x11b0, 0x6837, 0x0103, 0x6b4a, - 0x6847, 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x080c, 0x9ed9, - 0x000e, 0x0888, 0x7e3a, 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, - 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c, - 0xb155, 0x0c60, 0x601c, 0xa086, 0x000a, 0x0d08, 0x08f0, 0x0016, - 0x0026, 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x6f35, 0x008e, - 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0xb8e1, 0x2091, - 0x8000, 0x080c, 0x6fc2, 0x080c, 0x7034, 0x012e, 0x00fe, 0x0005, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0xb8e1, 0x7614, 0x2660, 0x2678, 0x8cff, - 0x0904, 0x6f0b, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, - 0x6f06, 0x88ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6f06, 0x7024, - 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, - 0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a, - 0x04e8, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36, - 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013, - 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, - 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9d16, 0x01b8, - 0x601c, 0xa086, 0x0003, 0x1540, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0x9f88, 0x080c, 0xb43c, - 0x080c, 0x547a, 0x008e, 0x003e, 0x001e, 0x080c, 0x9ecd, 0x080c, - 0x9ed9, 0x080c, 0x81a5, 0x00ce, 0x0804, 0x6e8f, 0x2c78, 0x600c, - 0x2060, 0x0804, 0x6e8f, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x1158, - 0x0016, 0x0036, 0x0086, 0x080c, 0xb43c, 0x080c, 0xb155, 0x008e, - 0x003e, 0x001e, 0x08e0, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, - 0xa086, 0x0085, 0x0908, 0x0898, 0x601c, 0xa086, 0x0005, 0x1978, - 0x6004, 0xa086, 0x0085, 0x0d20, 0x0850, 0x00c6, 0x0006, 0x0126, - 0x2091, 0x8000, 0xa280, 0xb735, 0x2004, 0xa065, 0x0904, 0x6fbe, - 0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, 0xb8e1, 0x6654, 0x7018, - 0xac06, 0x1108, 0x761a, 0x701c, 0xac06, 0x1130, 0x86ff, 0x1118, - 0x7018, 0x701e, 0x0008, 0x761e, 0x6058, 0xa07d, 0x0108, 0x7e56, - 0xa6ed, 0x0000, 0x0110, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, - 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x4f46, 0x0904, - 0x6fba, 0x7624, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, - 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, - 0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, - 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x9ed9, 0x00ce, 0x0048, - 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, - 0x6f65, 0x8dff, 0x0158, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, - 0x080c, 0x9f88, 0x080c, 0xb43c, 0x080c, 0x547a, 0x080c, 0x81a5, - 0x0804, 0x6f65, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e, - 0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x2031, 0x0000, - 0x7814, 0xa065, 0x0904, 0x7014, 0x600c, 0x0006, 0x600f, 0x0000, - 0x7824, 0xac06, 0x1540, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, - 0x080c, 0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, - 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, - 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009, - 0x630a, 0x2c30, 0x00b0, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0168, - 0x601c, 0xa086, 0x0003, 0x11b8, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x080c, 0x9ed9, 0x080c, - 0x81a5, 0x000e, 0x0804, 0x6fc9, 0x7e16, 0x7e12, 0x00de, 0x00ce, - 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c, - 0xb155, 0x0c58, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, 0xa086, - 0x0085, 0x09d0, 0x0c10, 0x601c, 0xa086, 0x0005, 0x19f0, 0x6004, - 0xa086, 0x0085, 0x0d60, 0x08c8, 0x0006, 0x0066, 0x00c6, 0x00d6, - 0x7818, 0xa065, 0x0904, 0x709a, 0x6054, 0x0006, 0x6057, 0x0000, - 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x4f46, - 0x0904, 0x7097, 0x7e24, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, - 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, - 0x080c, 0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, - 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, - 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, - 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x9ed9, 0x00ce, - 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, - 0x0804, 0x7046, 0x8dff, 0x0138, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x080c, 0x547a, 0x080c, 0x81a5, 0x0804, 0x7046, 0x000e, - 0x0804, 0x7039, 0x781e, 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e, - 0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, 0x01a0, 0x604c, - 0xa06d, 0x0188, 0x6848, 0xa606, 0x1170, 0x2071, 0xb8e1, 0x7024, - 0xa035, 0x0148, 0xa080, 0x0004, 0x2004, 0xad06, 0x1120, 0x6000, - 0xc0dc, 0x6002, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, - 0x2079, 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660, 0x6003, - 0x0009, 0x630a, 0x00ce, 0x04a0, 0x080c, 0x7df3, 0x78c3, 0x0000, - 0x080c, 0x82d4, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, - 0xa384, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x2079, - 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x82d4, - 0x003e, 0x080c, 0x4f46, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, - 0x603e, 0x2660, 0x080c, 0x86a4, 0x00ce, 0x6837, 0x0103, 0x6b4a, - 0x6847, 0x0000, 0x080c, 0x9f88, 0x080c, 0x547a, 0x080c, 0x81a5, - 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2071, 0xb8e1, 0x7004, 0xa084, - 0x0007, 0x0002, 0x7114, 0x7117, 0x712d, 0x7146, 0x7183, 0x7114, - 0x7112, 0x7112, 0x080c, 0x151a, 0x00ce, 0x00ee, 0x0005, 0x7024, - 0xa065, 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0150, - 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, - 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060, 0x080c, - 0x4f46, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0120, - 0x6054, 0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027, 0x0000, - 0x00ce, 0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024, 0xa065, - 0x05b8, 0x700c, 0xac06, 0x1160, 0x080c, 0x81a5, 0x600c, 0xa015, - 0x0120, 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, - 0x7014, 0xac06, 0x1160, 0x080c, 0x81a5, 0x600c, 0xa015, 0x0120, - 0x7216, 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x601c, - 0xa086, 0x0003, 0x1198, 0x6018, 0x2060, 0x080c, 0x4f46, 0x6000, - 0xc0dc, 0x6002, 0x080c, 0x81a5, 0x701c, 0xa065, 0x0138, 0x6054, - 0xa015, 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, - 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c, 0x81a5, - 0x600c, 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x82d4, - 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, - 0x00d6, 0x2069, 0xb8e1, 0x6830, 0xa084, 0x0003, 0x0002, 0x71a5, - 0x71a7, 0x71cb, 0x71a3, 0x080c, 0x151a, 0x00de, 0x0005, 0x00c6, - 0x6840, 0xa086, 0x0001, 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, - 0xa015, 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, - 0x0000, 0x2011, 0xb900, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, - 0x683a, 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0xa065, 0x0d68, - 0x6003, 0x0003, 0x0c50, 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, - 0x684b, 0x0000, 0x683c, 0xa065, 0x0168, 0x600c, 0xa015, 0x0130, - 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, 0x0020, 0x683f, 0x0000, - 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005, 0x00d6, 0x2069, 0xb8e1, - 0x6804, 0xa084, 0x0007, 0x0002, 0x71f6, 0x7292, 0x7292, 0x7292, - 0x7292, 0x7294, 0x71f4, 0x71f4, 0x080c, 0x151a, 0x6820, 0xa005, - 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0150, 0x6807, - 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x72e4, 0x00ce, 0x00de, - 0x0005, 0x6814, 0xa065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b, - 0x0000, 0x080c, 0x72e4, 0x00ce, 0x00de, 0x0005, 0x00e6, 0x0036, - 0x6a1c, 0xa2f5, 0x0000, 0x0904, 0x728e, 0x704c, 0xa00d, 0x0118, - 0x7088, 0xa005, 0x01a0, 0x7054, 0xa075, 0x0120, 0xa20e, 0x0904, - 0x728e, 0x0028, 0x6818, 0xa20e, 0x0904, 0x728e, 0x2070, 0x704c, - 0xa00d, 0x0d88, 0x7088, 0xa005, 0x1d70, 0x2e00, 0x681e, 0x733c, - 0x7038, 0xa302, 0x1e40, 0x080c, 0x867b, 0x0904, 0x728e, 0x8318, - 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, - 0x00ff, 0x605a, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, - 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x801b, - 0x831b, 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78, 0x71a0, 0x2001, - 0xb635, 0x2004, 0xd0ac, 0x1110, 0xd1bc, 0x0150, 0x7100, 0xd1f4, - 0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, - 0xa1e0, 0x2df9, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, - 0x080c, 0x7914, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, - 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, - 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x003e, 0x00ee, - 0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0138, - 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x72e4, 0x00ce, - 0x00de, 0x0005, 0x00f6, 0x00d6, 0x2069, 0xb8e1, 0x6830, 0xa086, - 0x0000, 0x11d0, 0x2001, 0xb60c, 0x200c, 0xd1bc, 0x1560, 0x6838, - 0xa07d, 0x0190, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, - 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x203d, - 0x1130, 0x012e, 0x080c, 0x7c5d, 0x00de, 0x00fe, 0x0005, 0x012e, - 0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0140, - 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c60, - 0x683a, 0x6836, 0x0cc0, 0xc1bc, 0x2102, 0x0066, 0x2031, 0x0001, - 0x080c, 0x5bc3, 0x006e, 0x0858, 0x601c, 0xa084, 0x000f, 0x000b, - 0x0005, 0x72f2, 0x72f7, 0x77b5, 0x78d1, 0x72f7, 0x77b5, 0x78d1, - 0x72f2, 0x72f7, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0005, 0x0156, - 0x0136, 0x0146, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0080, 0x1a0c, - 0x151a, 0x6118, 0x2178, 0x79a0, 0x2011, 0xb635, 0x2214, 0xd2ac, - 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, - 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2df9, 0x2f0d, - 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, - 0x1a04, 0x736b, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, - 0x0005, 0x741a, 0x7465, 0x7492, 0x755f, 0x758d, 0x7595, 0x75bb, - 0x75cc, 0x75dd, 0x75e5, 0x75fb, 0x75e5, 0x765c, 0x75cc, 0x767d, - 0x7685, 0x75dd, 0x7685, 0x7696, 0x7369, 0x7369, 0x7369, 0x7369, - 0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7efe, - 0x7f23, 0x7f46, 0x7f69, 0x7f8a, 0x75bb, 0x7369, 0x75bb, 0x75e5, - 0x7369, 0x7492, 0x755f, 0x7369, 0x83d6, 0x75e5, 0x7369, 0x83f6, - 0x75e5, 0x7369, 0x75dd, 0x7413, 0x737e, 0x7369, 0x841b, 0x8490, - 0x8567, 0x7369, 0x8578, 0x75b6, 0x8594, 0x7369, 0x7f9f, 0x85ef, - 0x7369, 0x080c, 0x151a, 0x2100, 0x0033, 0x00fe, 0x00ce, 0x014e, - 0x013e, 0x015e, 0x0005, 0x737c, 0x737c, 0x737c, 0x73b2, 0x73d0, - 0x73e6, 0x737c, 0x737c, 0x737c, 0x080c, 0x151a, 0x00d6, 0x20a1, - 0x020b, 0x080c, 0x76b3, 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, - 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854, - 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, - 0x7de0, 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068, 0x68a0, 0x2069, - 0xb600, 0x6ad4, 0xd2ac, 0x1110, 0xd0bc, 0x0110, 0xa085, 0x0001, - 0x00de, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x20a3, - 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2, - 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2, - 0x681c, 0x20a2, 0x60c3, 0x0010, 0x080c, 0x7de0, 0x00de, 0x0005, - 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x20a3, 0x7800, - 0x20a3, 0x0000, 0x7808, 0x8007, 0x20a2, 0x20a3, 0x0000, 0x60c3, - 0x0008, 0x080c, 0x7de0, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3, 0x0200, 0x20a3, 0x0000, - 0x20a3, 0xdf10, 0x20a3, 0x0034, 0x2099, 0xb605, 0x20a9, 0x0004, - 0x53a6, 0x2099, 0xb601, 0x20a9, 0x0004, 0x53a6, 0x2099, 0xb8c7, - 0x20a9, 0x001a, 0x3304, 0x8007, 0x20a2, 0x9398, 0x1f04, 0x7402, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x7de0, - 0x014e, 0x015e, 0x0005, 0x2001, 0xb615, 0x2004, 0x609a, 0x080c, - 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x20a3, 0x5200, - 0x20a3, 0x0000, 0x00d6, 0x2069, 0xb652, 0x6804, 0xd084, 0x0150, - 0x6828, 0x20a3, 0x0000, 0x0016, 0x080c, 0x2866, 0x21a2, 0x001e, - 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, - 0x0004, 0x2099, 0xb605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb601, - 0x53a6, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, - 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, 0xb61c, 0x20a6, - 0x2001, 0xb61d, 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xb615, - 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x001c, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, - 0x76b3, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0xb635, 0x2004, - 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, - 0x0238, 0x2001, 0xb61c, 0x20a6, 0x2001, 0xb61d, 0x20a6, 0x0040, - 0x20a3, 0x0000, 0x2001, 0xb615, 0x2004, 0xa084, 0x00ff, 0x20a2, - 0x20a9, 0x0004, 0x2099, 0xb605, 0x53a6, 0x60c3, 0x0010, 0x080c, - 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x00c6, 0x7818, - 0x2060, 0x2001, 0x0000, 0x080c, 0x5385, 0x00ce, 0x7818, 0xa080, - 0x0028, 0x2004, 0xa086, 0x007e, 0x1130, 0x20a3, 0x0400, 0x620c, - 0xc2b4, 0x620e, 0x0010, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, - 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1904, 0x7521, 0x2001, - 0xb635, 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xb88e, 0x33a6, 0x9398, - 0x20a3, 0x0000, 0x9398, 0x3304, 0xa084, 0x2000, 0x20a2, 0x9398, - 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x2001, 0x2710, 0x20a2, - 0x9398, 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099, 0xb88e, 0x33a6, - 0x9398, 0x33a6, 0x9398, 0x3304, 0x080c, 0x5b41, 0x1118, 0xa084, - 0x37ff, 0x0010, 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, - 0x0004, 0x2099, 0xb605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb601, - 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x74fb, 0x20a9, - 0x0008, 0x20a3, 0x0000, 0x1f04, 0x7501, 0x2099, 0xb896, 0x3304, - 0xc0dd, 0x20a2, 0x2001, 0xb672, 0x2004, 0xd0e4, 0x0158, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, 0x20a9, - 0x0004, 0x0010, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x1f04, 0x751c, - 0x0468, 0x2001, 0xb635, 0x2004, 0xd0a4, 0x0140, 0x2001, 0xb88f, - 0x2004, 0x60e3, 0x0000, 0x080c, 0x28a7, 0x60e2, 0x2099, 0xb88e, - 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb605, 0x53a6, - 0x20a9, 0x0004, 0x2099, 0xb601, 0x53a6, 0x20a9, 0x0008, 0x20a3, - 0x0000, 0x1f04, 0x753f, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, - 0x7545, 0x2099, 0xb896, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, - 0x20a3, 0x0000, 0x1f04, 0x7550, 0x20a9, 0x000a, 0x20a3, 0x0000, - 0x1f04, 0x7556, 0x60c3, 0x0074, 0x080c, 0x7de0, 0x0005, 0x20a1, - 0x020b, 0x080c, 0x76b3, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, - 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, - 0x20a2, 0x00f6, 0x2079, 0xb652, 0x7904, 0x00fe, 0xd1ac, 0x1110, - 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0xa085, 0x0002, - 0x00d6, 0x0804, 0x763e, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, - 0x76b3, 0x20a3, 0x5000, 0x0804, 0x74ad, 0x20a1, 0x020b, 0x080c, - 0x76b3, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x60c3, 0x0014, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, - 0x080c, 0x7747, 0x0020, 0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3, - 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x0004, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x774f, - 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, - 0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, - 0x774f, 0x20a3, 0x0200, 0x0804, 0x74ad, 0x20a1, 0x020b, 0x080c, - 0x774f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, 0x0110, - 0x20a2, 0x0010, 0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008, - 0x080c, 0x7de0, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x774f, - 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818, 0x2068, - 0x6894, 0xa086, 0x0014, 0x1198, 0x699c, 0xa184, 0x0030, 0x0190, - 0x6998, 0xa184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x20a3, 0x2100, - 0x0058, 0x20a3, 0x0100, 0x0040, 0x20a3, 0x0400, 0x0028, 0x20a3, - 0x0700, 0x0010, 0x700f, 0x0800, 0xa006, 0x20a2, 0x20a2, 0x20a2, - 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xb652, 0x7904, 0x00fe, 0xd1ac, - 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, - 0xb674, 0x210c, 0xd184, 0x1110, 0xa085, 0x0002, 0x0026, 0x2009, - 0xb672, 0x210c, 0xd1e4, 0x0130, 0xc0c5, 0xa094, 0x0030, 0xa296, - 0x0010, 0x0140, 0xd1ec, 0x0130, 0xa094, 0x0030, 0xa296, 0x0010, - 0x0108, 0xc0bd, 0x002e, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, - 0x080c, 0x7de0, 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x774f, - 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, - 0x774f, 0x20a3, 0x0200, 0x0804, 0x7420, 0x20a1, 0x020b, 0x080c, - 0x774f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, - 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, - 0x080c, 0x7de0, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3200, - 0x2021, 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2200, - 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, - 0x0028, 0x2014, 0xa286, 0x007e, 0x11a0, 0xa385, 0x00ff, 0x20a2, - 0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x2001, - 0xb89e, 0x2004, 0xa005, 0x0118, 0x2011, 0xb61d, 0x2214, 0x22a2, - 0x04d0, 0xa286, 0x007f, 0x1138, 0x00d6, 0xa385, 0x00ff, 0x20a2, - 0x20a3, 0xfffd, 0x00c8, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1110, - 0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6, 0x1130, 0xa385, 0x00ff, - 0x20a2, 0x20a3, 0xfffc, 0x0040, 0xa2e8, 0xb735, 0x2d6c, 0x6810, - 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, - 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa2e8, 0xb735, 0x2d6c, 0x6810, - 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, - 0xb615, 0x2214, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x004e, 0x003e, - 0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x2fa2, - 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, - 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, - 0xfffc, 0x22a2, 0x00d6, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, - 0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x08e0, 0x20a3, 0x0100, - 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x0005, 0x0026, - 0x0036, 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0038, 0x0026, - 0x0036, 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635, - 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x02d8, 0x00d6, 0xa0e8, - 0xb735, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x6810, - 0xa005, 0x1140, 0x6814, 0xa005, 0x1128, 0x20a3, 0x00ff, 0x20a3, - 0xfffe, 0x0028, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0080, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa305, 0x20a2, - 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, - 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, 0x0000, 0x004e, 0x003e, - 0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x080c, 0x7dcf, - 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7810, 0x20a2, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00c6, 0x00f6, 0x6004, - 0xa08a, 0x0085, 0x0a0c, 0x151a, 0xa08a, 0x008c, 0x1a0c, 0x151a, - 0x6118, 0x2178, 0x79a0, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, - 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, - 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2df9, 0x2f0d, 0xa18c, - 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x001b, - 0x00fe, 0x00ce, 0x0005, 0x77ec, 0x77f6, 0x7811, 0x77ea, 0x77ea, - 0x77ea, 0x77ec, 0x080c, 0x151a, 0x0146, 0x20a1, 0x020b, 0x04a1, - 0x60c3, 0x0000, 0x080c, 0x7de0, 0x014e, 0x0005, 0x0146, 0x20a1, - 0x020b, 0x080c, 0x785d, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, - 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, 0x7de0, 0x014e, - 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7897, 0x20a3, 0x0003, - 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, - 0x080c, 0x7de0, 0x014e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635, 0x2214, - 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xb735, - 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, - 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, - 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, - 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x22a2, 0x20a3, - 0x0009, 0x20a3, 0x0000, 0x0804, 0x771a, 0x0026, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635, - 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, - 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, - 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, - 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, - 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x22a2, - 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, 0x77a6, 0x0026, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, - 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, - 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8500, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, - 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, - 0x77a6, 0x00c6, 0x00f6, 0x2c78, 0x7804, 0xa08a, 0x0040, 0x0a0c, - 0x151a, 0xa08a, 0x0053, 0x1a0c, 0x151a, 0x7918, 0x2160, 0x61a0, - 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x6100, - 0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, - 0x0028, 0xa1e0, 0x2df9, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, - 0x619a, 0xa082, 0x0040, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x7914, - 0x7a20, 0x79bd, 0x7bd2, 0x7912, 0x7912, 0x7912, 0x7912, 0x7912, - 0x7912, 0x7912, 0x815e, 0x816e, 0x817e, 0x818e, 0x7912, 0x85a5, - 0x7912, 0x814d, 0x080c, 0x151a, 0x00d6, 0x0156, 0x0146, 0x780b, - 0xffff, 0x20a1, 0x020b, 0x080c, 0x7974, 0x7910, 0x2168, 0x6948, - 0x7952, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, - 0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, - 0x0004, 0x0018, 0xa084, 0x0006, 0x8004, 0x0016, 0x2008, 0x7858, - 0xa084, 0x00ff, 0x8007, 0xa105, 0x001e, 0x20a2, 0xd1ac, 0x0118, - 0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118, 0x20a3, 0x0001, 0x0020, - 0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80, 0x6e7c, 0x20a9, 0x0008, - 0x0136, 0xad88, 0x0017, 0x2198, 0x20a1, 0x021b, 0x53a6, 0x013e, - 0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, - 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xb8fd, - 0x2003, 0x07d0, 0x2001, 0xb8fc, 0x2003, 0x0009, 0x080c, 0x17e7, - 0x014e, 0x015e, 0x00de, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, - 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0x2019, 0xb635, 0x231c, - 0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, - 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb61c, - 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb735, - 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x00de, - 0x20a3, 0x0000, 0x2009, 0xb615, 0x210c, 0x21a2, 0x20a3, 0x0829, - 0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005, 0x00d6, 0x0156, 0x0136, - 0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810, 0x2068, 0x6860, 0x20a2, - 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x080c, 0x7de0, 0x014e, - 0x013e, 0x015e, 0x00de, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, - 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635, 0x2214, - 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, - 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb61c, - 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb735, - 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x00de, - 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x22a2, 0x20a3, 0x0889, - 0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x7a08, - 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, - 0x00d6, 0x0156, 0x0136, 0x0146, 0x7810, 0xa0ec, 0xf000, 0x0168, - 0xa06d, 0x080c, 0x5373, 0x0148, 0x684c, 0xa084, 0x2020, 0xa086, - 0x2020, 0x1118, 0x7820, 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c, - 0x7b88, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, - 0xa084, 0xf000, 0x1130, 0x7810, 0xa084, 0x0700, 0x8007, 0x0043, - 0x0010, 0xa006, 0x002b, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, - 0x7a5a, 0x7aef, 0x7aff, 0x7b31, 0x7b44, 0x7b5f, 0x7b68, 0x7a58, - 0x080c, 0x151a, 0x0016, 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118, - 0xa186, 0x0003, 0x1170, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5, - 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, - 0x7b3b, 0xa186, 0x0001, 0x190c, 0x151a, 0x6b78, 0x7820, 0xd0cc, - 0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, - 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, - 0x0300, 0x0904, 0x7ae9, 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc, - 0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020, - 0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x7a98, 0x015e, 0x22a2, - 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0904, 0x7ae9, 0x20a1, 0x020b, - 0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, 0x0028, - 0x2004, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, - 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, - 0x2214, 0x22a2, 0x000e, 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889, - 0x0010, 0x20a3, 0x0898, 0x20a2, 0x080c, 0x7dcf, 0x22a2, 0x20a3, - 0x0000, 0x61c2, 0x003e, 0x001e, 0x080c, 0x7de0, 0x0005, 0x2011, - 0x0008, 0x2001, 0xb60d, 0x2004, 0xd0f4, 0x0110, 0x2011, 0x0028, - 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x04d0, 0x2011, - 0x0302, 0x0016, 0x0036, 0x7828, 0x792c, 0xa11d, 0x0108, 0xc2dd, - 0x7b20, 0xd3cc, 0x0108, 0xc2e5, 0x22a2, 0x20a2, 0x21a2, 0x003e, - 0x001e, 0xa016, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500, - 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x080c, 0x7de0, - 0x0005, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, - 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, - 0x0018, 0x080c, 0x7de0, 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc, - 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, - 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2, - 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x080c, 0x7de0, 0x0005, 0x2011, - 0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888, - 0x0036, 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, - 0x1138, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808, - 0x0046, 0x2021, 0x0800, 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108, - 0xc4e5, 0x24a2, 0x004e, 0x22a2, 0x20a2, 0x003e, 0x0804, 0x7b3b, - 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, - 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, - 0x2214, 0x22a2, 0x7820, 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010, - 0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3, - 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x0016, 0x0036, - 0x7810, 0xa084, 0x0700, 0x8007, 0x003b, 0x003e, 0x001e, 0x014e, - 0x013e, 0x015e, 0x00de, 0x0005, 0x7bec, 0x7bec, 0x7bee, 0x7bec, - 0x7bec, 0x7bec, 0x7c10, 0x7bec, 0x080c, 0x151a, 0x7910, 0xa18c, - 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, - 0x00f9, 0x00d6, 0x2069, 0xb652, 0x6804, 0xd0bc, 0x0130, 0x682c, - 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de, - 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x080c, 0x7de0, 0x0005, - 0x20a1, 0x020b, 0x2009, 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80, - 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, - 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, - 0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, - 0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0100, - 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, - 0x2214, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c, - 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6, - 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xb600, 0x7154, - 0x7818, 0x2068, 0x68a0, 0x2028, 0x76d4, 0xd6ac, 0x1130, 0xd0bc, - 0x1120, 0x6910, 0x6a14, 0x7454, 0x0020, 0x6910, 0x6a14, 0x7370, - 0x7474, 0x781c, 0xa0be, 0x0006, 0x0904, 0x7d1a, 0xa0be, 0x000a, - 0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073, - 0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, - 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, - 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, - 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0x609f, 0x0000, 0x080c, 0x8640, 0x2009, 0x07d0, 0x60c4, 0xa084, - 0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x6a87, 0x003e, - 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d4, 0xd0ac, - 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, - 0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, - 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, - 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, - 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, - 0x700c, 0x60c6, 0x7008, 0x60ca, 0x792c, 0xa108, 0x792e, 0x700c, - 0x7928, 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, - 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, - 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x8640, - 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110, 0x2009, - 0x1b58, 0x080c, 0x6a87, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, - 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003, 0xa086, - 0x0002, 0x0904, 0x7d70, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1110, - 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, - 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, - 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, - 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, 0x6086, 0x7808, - 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, 0x707c, - 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, 0xa109, - 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, - 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, - 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x863d, 0x0804, 0x7d08, - 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, - 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, 0x0700, - 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, 0x5373, 0x0180, - 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, 0x2020, 0xa086, - 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, 0x0889, 0x0010, - 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, - 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, - 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, - 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, - 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, - 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, 0x0120, 0x080c, - 0x8640, 0x0804, 0x7d08, 0x080c, 0x863d, 0x0804, 0x7d08, 0x7a18, - 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, - 0x0005, 0x00d6, 0x2069, 0xb8e1, 0x6843, 0x0001, 0x00de, 0x0005, - 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x0019, 0x080c, - 0x6a79, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, - 0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, - 0x61a4, 0x60a7, 0x95f5, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, - 0x6016, 0x000e, 0xe000, 0xe000, 0xe000, 0xe000, 0x61a6, 0x00ce, - 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, - 0x2069, 0x0140, 0x080c, 0x5b41, 0x1198, 0x2001, 0xb8fd, 0x2004, - 0xa005, 0x15b8, 0x0066, 0x2031, 0x0001, 0x080c, 0x5bc3, 0x006e, - 0x1118, 0x080c, 0x6a79, 0x0468, 0x00c6, 0x2061, 0xb8e1, 0x00d8, - 0x6904, 0xa194, 0x4000, 0x0550, 0x0831, 0x6803, 0x1000, 0x6803, - 0x0000, 0x00c6, 0x2061, 0xb8e1, 0x6128, 0xa192, 0x00c8, 0x1258, - 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x6a79, - 0x080c, 0x7dea, 0x0070, 0x6124, 0xa1e5, 0x0000, 0x0140, 0x080c, - 0xb500, 0x080c, 0x6a82, 0x2009, 0x0014, 0x080c, 0x86d3, 0x00ce, - 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0xb8fd, - 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, 0xb8e1, 0x6128, 0xa192, - 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x6a79, 0x080c, - 0x4b7b, 0x0c38, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, - 0x6a8f, 0x2071, 0xb8e1, 0x713c, 0x81ff, 0x0590, 0x2061, 0x0100, - 0x2069, 0x0140, 0x080c, 0x5b41, 0x11a8, 0x0036, 0x2019, 0x0002, - 0x080c, 0x806b, 0x003e, 0x713c, 0x2160, 0x080c, 0xb500, 0x2009, - 0x004a, 0x080c, 0x86d3, 0x0066, 0x2031, 0x0001, 0x080c, 0x5bc3, - 0x006e, 0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, 0x1000, - 0x6803, 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x806b, 0x003e, - 0x713c, 0x2160, 0x080c, 0xb500, 0x2009, 0x004a, 0x080c, 0x86d3, - 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, 0x0026, - 0x00e6, 0x2071, 0xb8e1, 0x7048, 0xd084, 0x01c0, 0x713c, 0x81ff, - 0x01a8, 0x2071, 0x0100, 0xa188, 0x0007, 0x2114, 0xa28e, 0x0006, - 0x1138, 0x7014, 0xa084, 0x0184, 0xa085, 0x0012, 0x7016, 0x0030, - 0x7014, 0xa084, 0x0184, 0xa085, 0x0016, 0x7016, 0x00ee, 0x002e, - 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, - 0x0126, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071, 0xb8e1, - 0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, 0xa406, 0x0118, 0x6854, - 0x2068, 0x0cc0, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60, - 0x080c, 0x518c, 0x0110, 0xa085, 0x0001, 0x012e, 0x000e, 0x004e, - 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x20a1, 0x020b, - 0x080c, 0x76b3, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x781c, 0xa086, 0x0004, 0x1110, 0x6098, 0x0018, 0x2001, 0xb615, - 0x2004, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, - 0xa006, 0x20a2, 0x1f04, 0x7f19, 0x20a2, 0x20a2, 0x60c3, 0x002c, - 0x080c, 0x7de0, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, - 0x76b3, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x7808, 0xd09c, 0x1150, - 0x20a3, 0x0000, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7de0, 0x014e, - 0x015e, 0x0005, 0x00d6, 0x7818, 0xa06d, 0x090c, 0x151a, 0x6810, - 0xa084, 0x00ff, 0x20a2, 0x6814, 0x00de, 0x0c60, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3, 0x0200, 0x20a3, 0x0000, - 0x20a9, 0x0006, 0x2011, 0xb640, 0x2019, 0xb641, 0x23a6, 0x22a6, - 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x7f56, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7de0, 0x014e, 0x015e, - 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, - 0x7728, 0x080c, 0x773e, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, - 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, - 0x0004, 0x8003, 0x60c2, 0x080c, 0x7de0, 0x002e, 0x001e, 0x014e, - 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x76b3, - 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, - 0x60c3, 0x0008, 0x080c, 0x7de0, 0x014e, 0x015e, 0x0005, 0x0156, - 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x7810, - 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808, 0xa088, - 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x080c, 0x7de0, 0x002e, - 0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0xb8e1, 0x700c, 0x2060, 0x8cff, 0x0178, - 0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x600c, 0x0006, 0x080c, - 0xa0db, 0x080c, 0x86a4, 0x080c, 0x81a5, 0x00ce, 0x0c78, 0x700f, - 0x0000, 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, - 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, - 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0xb8e1, 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c, 0x7df3, 0x68c3, - 0x0000, 0x080c, 0x6a82, 0x2009, 0x0013, 0x080c, 0x86d3, 0x20a9, - 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, - 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, - 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x8001, 0x7804, 0xa084, - 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, - 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, - 0x0005, 0x2001, 0xb600, 0x2004, 0xa096, 0x0001, 0x0590, 0xa096, - 0x0004, 0x0578, 0x080c, 0x6a82, 0x6814, 0xa084, 0x0001, 0x0110, - 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x4b23, - 0x080c, 0x6a0e, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, - 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, - 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, - 0x8044, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, - 0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, - 0x2079, 0x0140, 0x2071, 0xb8e1, 0x703c, 0x2060, 0x8cff, 0x0904, - 0x80f2, 0xa386, 0x0002, 0x1128, 0x6814, 0xa084, 0x0002, 0x0904, - 0x80f2, 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, - 0x1df0, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x080c, 0x6a8f, 0x080c, - 0x222f, 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, - 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x1500, 0x68af, 0x95f5, - 0x68c7, 0x0000, 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, - 0x2071, 0xb94b, 0x6814, 0xa084, 0x0184, 0xa085, 0x0012, 0x6816, - 0x7803, 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, 0xa386, 0x0002, - 0x1128, 0x7884, 0xa005, 0x1110, 0x7887, 0x0001, 0x2001, 0xb8b1, - 0x2004, 0x200a, 0x004e, 0xa39d, 0x0000, 0x1120, 0x2009, 0x0049, - 0x080c, 0x86d3, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0158, 0x6827, - 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, - 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, - 0x80d4, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, - 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, - 0x2069, 0xb8e1, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, - 0x2091, 0x8000, 0x2069, 0xb8e1, 0x6a32, 0x012e, 0x00de, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, 0x0126, 0x2071, 0xb8e1, - 0x7614, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0538, 0x601c, - 0xa206, 0x1500, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, - 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, - 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, - 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x9ed9, 0x080c, 0x81a5, - 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, 0x08b8, 0x012e, 0x000e, - 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0156, 0x0146, 0x20a1, - 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, - 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, 0x819d, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0478, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x00f8, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x0156, 0x0146, - 0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x0089, 0x60c3, 0x0020, - 0x080c, 0x7de0, 0x014e, 0x015e, 0x0005, 0x00e6, 0x2071, 0xb8e1, - 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, 0x00ee, 0x0005, 0x20a9, - 0x0008, 0x20a2, 0x1f04, 0x81b1, 0x20a2, 0x20a2, 0x0005, 0x00f6, - 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0xb8e1, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, - 0x87ff, 0x0904, 0x824d, 0x8cff, 0x0904, 0x824d, 0x601c, 0xa086, - 0x0006, 0x1904, 0x8248, 0x88ff, 0x0138, 0x2800, 0xac06, 0x1904, - 0x8248, 0x2039, 0x0000, 0x0050, 0x6018, 0xa206, 0x1904, 0x8248, - 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x8248, 0x7024, 0xac06, - 0x1598, 0x2069, 0x0100, 0x68c0, 0xa005, 0x1160, 0x6824, 0xd084, - 0x0148, 0x6827, 0x0001, 0x080c, 0x6a82, 0x080c, 0x82d4, 0x7027, - 0x0000, 0x0410, 0x080c, 0x6a82, 0x6820, 0xd0b4, 0x0110, 0x68a7, - 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x7014, 0xac36, 0x1110, 0x660c, - 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, - 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1158, 0x600f, 0x0000, - 0x6010, 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0xb155, 0x080c, - 0x9ed9, 0x080c, 0x81a5, 0x88ff, 0x1190, 0x00ce, 0x0804, 0x81c8, - 0x2c78, 0x600c, 0x2060, 0x0804, 0x81c8, 0xa006, 0x012e, 0x000e, - 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, - 0x0000, 0x00ce, 0xa8c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0xb8e1, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, 0x82c4, 0x601c, - 0xa086, 0x0006, 0x1904, 0x82bf, 0x87ff, 0x0128, 0x2700, 0xac06, - 0x1904, 0x82bf, 0x0048, 0x6018, 0xa206, 0x1904, 0x82bf, 0x85ff, - 0x0118, 0x6050, 0xa106, 0x15d8, 0x703c, 0xac06, 0x1180, 0x0036, - 0x2019, 0x0001, 0x080c, 0x806b, 0x7033, 0x0000, 0x703f, 0x0000, - 0x7043, 0x0000, 0x7047, 0x0000, 0x704b, 0x0000, 0x003e, 0x7038, - 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, - 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, - 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, - 0x0000, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0xb155, - 0x080c, 0x9ed9, 0x87ff, 0x1190, 0x00ce, 0x0804, 0x826c, 0x2c78, - 0x600c, 0x2060, 0x0804, 0x826c, 0xa006, 0x012e, 0x000e, 0x002e, - 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000, - 0x00ce, 0xa7bd, 0x0001, 0x0c88, 0x00e6, 0x2071, 0xb8e1, 0x2001, - 0xb600, 0x2004, 0xa086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, - 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, - 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb8e1, 0x2c10, - 0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, 0x2200, 0xac06, 0x11e0, - 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, - 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, - 0x660c, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, - 0x0000, 0xa085, 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08d8, - 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0xb8e1, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, - 0x83aa, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x83a5, - 0x7024, 0xac06, 0x1508, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0904, - 0x8381, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, - 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0xac36, 0x1110, 0x660c, - 0x760e, 0x7008, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, - 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x9f03, - 0x1158, 0x080c, 0x2cf7, 0x080c, 0x9f14, 0x11f0, 0x080c, 0x8ca5, - 0x00d8, 0x080c, 0x82d4, 0x08c0, 0x080c, 0x9f14, 0x1118, 0x080c, - 0x8ca5, 0x0090, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0168, 0x601c, - 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, - 0x080c, 0x547a, 0x080c, 0x9ecd, 0x080c, 0xa0db, 0x080c, 0x9ed9, - 0x080c, 0x81a5, 0x00ce, 0x0804, 0x832e, 0x2c78, 0x600c, 0x2060, - 0x0804, 0x832e, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x1d30, 0x080c, 0xb155, - 0x0c18, 0x0036, 0x0156, 0x0136, 0x0146, 0x3908, 0xa006, 0xa190, - 0x0020, 0x221c, 0xa39e, 0x2aec, 0x1118, 0x8210, 0x8000, 0x0cc8, - 0xa005, 0x0138, 0x20a9, 0x0020, 0x2198, 0xa110, 0x22a0, 0x22c8, - 0x53a3, 0x014e, 0x013e, 0x015e, 0x003e, 0x0005, 0x00d6, 0x20a1, - 0x020b, 0x080c, 0x774f, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, - 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2099, 0xb8b9, 0x20a9, - 0x0004, 0x53a6, 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x080c, 0x7de0, 0x00de, 0x0005, 0x20a1, 0x020b, - 0x080c, 0x774f, 0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800, - 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, - 0x7828, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, - 0x080c, 0x7de0, 0x0005, 0x00d6, 0x0016, 0x2f68, 0x2009, 0x0035, - 0x080c, 0xa1c6, 0x1904, 0x8489, 0x20a1, 0x020b, 0x080c, 0x76b3, - 0x20a3, 0x1300, 0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086, - 0x0003, 0x0580, 0x7818, 0xa080, 0x0028, 0x2014, 0x2001, 0xb635, - 0x2004, 0xd0ac, 0x11d0, 0xa286, 0x007e, 0x1128, 0x20a3, 0x00ff, - 0x20a3, 0xfffe, 0x04b8, 0xa286, 0x007f, 0x1128, 0x20a3, 0x00ff, - 0x20a3, 0xfffd, 0x0478, 0xd2bc, 0x0180, 0xa286, 0x0080, 0x1128, - 0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0428, 0xa2e8, 0xb735, 0x2d6c, - 0x6810, 0x20a2, 0x6814, 0x20a2, 0x00e8, 0x20a3, 0x0000, 0x6098, - 0x20a2, 0x00c0, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1138, 0x7818, - 0xa080, 0x0028, 0x2004, 0xa082, 0x007e, 0x0240, 0x00d6, 0x2069, - 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0020, 0x20a3, 0x0000, - 0x6034, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, 0x7de0, 0x001e, 0x00de, - 0x0005, 0x7817, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x0005, - 0x00d6, 0x0026, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x01c0, - 0xa186, 0x0003, 0x0904, 0x84ff, 0xa186, 0x0005, 0x0904, 0x84e8, - 0xa186, 0x0004, 0x05b8, 0xa186, 0x0008, 0x0904, 0x84f0, 0x7807, - 0x0037, 0x7813, 0x1700, 0x080c, 0x8567, 0x002e, 0x00de, 0x0005, - 0x080c, 0x8523, 0x2009, 0x4000, 0x6800, 0x0002, 0x84c9, 0x84d4, - 0x84cb, 0x84d4, 0x84d0, 0x84c9, 0x84c9, 0x84d4, 0x84d4, 0x84d4, - 0x84d4, 0x84c9, 0x84c9, 0x84c9, 0x84c9, 0x84c9, 0x84d4, 0x84c9, - 0x84d4, 0x080c, 0x151a, 0x6820, 0xd0e4, 0x0110, 0xd0cc, 0x0110, - 0xa00e, 0x0010, 0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2, - 0x0804, 0x8519, 0x080c, 0x8523, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x2009, 0x4000, 0x6a00, 0xa286, 0x0002, 0x1108, 0xa00e, 0x0488, - 0x04d1, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x0448, - 0x0491, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0xa286, - 0x0005, 0x0118, 0xa286, 0x0002, 0x1108, 0xa00e, 0x00d0, 0x0419, - 0x6810, 0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103, - 0x20a2, 0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002, - 0x0130, 0xa08e, 0x0004, 0x0118, 0x2009, 0x4000, 0x0010, 0x2009, - 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7de0, - 0x002e, 0x00de, 0x0005, 0x0036, 0x0046, 0x0056, 0x0066, 0x20a1, - 0x020b, 0x080c, 0x774f, 0xa006, 0x20a3, 0x0200, 0x20a2, 0x7934, - 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, - 0xb635, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0268, 0x00d6, - 0x2069, 0xb61c, 0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xb735, 0x2d6c, - 0x6b10, 0x6c14, 0x00de, 0x0030, 0x2019, 0x0000, 0x6498, 0x2029, - 0x0000, 0x6634, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003, - 0x1128, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0020, 0x23a2, 0x24a2, - 0x25a2, 0x26a2, 0x006e, 0x005e, 0x004e, 0x003e, 0x0005, 0x20a1, - 0x020b, 0x080c, 0x774f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, - 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005, - 0x20a1, 0x020b, 0x080c, 0x76ab, 0x20a3, 0x1400, 0x20a3, 0x0000, - 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c, 0x20a2, - 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000, 0x60c3, - 0x0010, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7747, - 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810, 0x20a2, - 0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005, 0x0146, 0x20a1, 0x020b, - 0x0031, 0x60c3, 0x0000, 0x080c, 0x7de0, 0x014e, 0x0005, 0x20e1, - 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, - 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, - 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, - 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0078, 0x00d6, - 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, - 0x20a2, 0x00de, 0x20a3, 0x0000, 0x6234, 0x22a2, 0x20a3, 0x0819, - 0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x2fa2, - 0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005, 0x20a1, - 0x020b, 0x0079, 0x7910, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0000, - 0x20e1, 0x9080, 0x60a7, 0x9575, 0x080c, 0x7dea, 0x080c, 0x6a79, - 0x0005, 0x0156, 0x0136, 0x0036, 0x00d6, 0x00e6, 0x20e1, 0x9080, - 0x20e1, 0x4000, 0x7854, 0x2068, 0xadf0, 0x000f, 0x7210, 0xa296, - 0x00c0, 0xa294, 0xfffd, 0x7212, 0x7214, 0xa294, 0x0300, 0x7216, - 0x7100, 0xa194, 0x00ff, 0x7308, 0xa384, 0x00ff, 0xa08d, 0xc200, - 0x7102, 0xa384, 0xff00, 0xa215, 0x720a, 0x7004, 0x720c, 0x700e, - 0x7206, 0x20a9, 0x000a, 0x2e98, 0x53a6, 0x60a3, 0x0035, 0x6a38, - 0xa294, 0x7000, 0xa286, 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee, - 0x00de, 0x003e, 0x013e, 0x015e, 0x0005, 0x2009, 0x0092, 0x0010, - 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, 0x0005, 0x2061, 0xbe00, - 0x2a70, 0x7068, 0x704a, 0x704f, 0xbe00, 0x0005, 0x00e6, 0x0126, - 0x2071, 0xb600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010, 0x0608, - 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, - 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xbe00, 0x0c98, 0x6003, - 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, 0x1230, - 0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, 0xbe00, - 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xb600, 0x7548, 0xa582, - 0x0010, 0x0600, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, - 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xbe00, - 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, - 0xa502, 0x1228, 0x754e, 0xa085, 0x0001, 0x00ee, 0x0005, 0x704f, - 0xbe00, 0x0cc8, 0xa006, 0x0cc8, 0xac82, 0xbe00, 0x0a0c, 0x151a, - 0x2001, 0xb617, 0x2004, 0xac02, 0x1a0c, 0x151a, 0xa006, 0x6006, - 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, - 0x0000, 0x6052, 0x6056, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, - 0x6036, 0x603a, 0x603e, 0x2061, 0xb600, 0x6048, 0x8000, 0x604a, - 0xa086, 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, - 0x71e5, 0x012e, 0x0cc0, 0x601c, 0xa084, 0x000f, 0x0002, 0x86e7, - 0x86f6, 0x8711, 0x872c, 0xa20e, 0xa229, 0xa244, 0x86e7, 0x86f6, - 0x86e7, 0x8747, 0x86e7, 0x86e7, 0x86e7, 0x86e7, 0x86e7, 0xa186, - 0x0013, 0x1128, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0005, 0xa18e, - 0x0047, 0x1118, 0xa016, 0x080c, 0x1863, 0x0005, 0x0066, 0x6000, - 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0x870f, - 0x8b27, 0x8cdf, 0x870f, 0x8d54, 0x8805, 0x870f, 0x870f, 0x8ab9, - 0x917b, 0x870f, 0x870f, 0x870f, 0x870f, 0x870f, 0x870f, 0x080c, - 0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, - 0x006e, 0x0005, 0x872a, 0x97de, 0x872a, 0x872a, 0x872a, 0x872a, - 0x872a, 0x872a, 0x9789, 0x994a, 0x872a, 0x980b, 0x9882, 0x980b, - 0x9882, 0x872a, 0x080c, 0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010, - 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0x8745, 0x91bc, 0x9286, - 0x93c4, 0x954d, 0x8745, 0x8745, 0x8745, 0x9196, 0x9739, 0x973c, - 0x8745, 0x8745, 0x8745, 0x8745, 0x9766, 0x080c, 0x151a, 0x0066, - 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, - 0x8760, 0x8760, 0x8760, 0x878e, 0x87db, 0x8760, 0x8760, 0x8760, - 0x8762, 0x8760, 0x8760, 0x8760, 0x8760, 0x8760, 0x8760, 0x8760, - 0x080c, 0x151a, 0xa186, 0x0003, 0x190c, 0x151a, 0x00d6, 0x6003, - 0x0003, 0x6106, 0x6010, 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, - 0x6880, 0x680e, 0x6813, 0x0000, 0x6817, 0x0000, 0x6854, 0xa092, - 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0xa210, - 0x6216, 0x00de, 0x2c10, 0x080c, 0x1fc5, 0x080c, 0x6d62, 0x0126, - 0x2091, 0x8000, 0x080c, 0x72a2, 0x012e, 0x0005, 0xa182, 0x0047, - 0x0002, 0x879a, 0x879a, 0x879c, 0x87b5, 0x879a, 0x879a, 0x879a, - 0x879a, 0x87c7, 0x080c, 0x151a, 0x00d6, 0x0016, 0x080c, 0x7198, - 0x080c, 0x72a2, 0x6003, 0x0004, 0x6110, 0x2168, 0x684f, 0x0020, - 0x685c, 0x685a, 0x6874, 0x687e, 0x6878, 0x6882, 0x6897, 0x0000, - 0x689b, 0x0000, 0x001e, 0x00de, 0x0005, 0x080c, 0x7198, 0x00d6, - 0x6110, 0x2168, 0x080c, 0x9d16, 0x0120, 0x684b, 0x0006, 0x080c, - 0x547a, 0x00de, 0x080c, 0x86a4, 0x080c, 0x72a2, 0x0005, 0x080c, - 0x7198, 0x080c, 0x2cd1, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9d16, - 0x0120, 0x684b, 0x0029, 0x080c, 0x547a, 0x00de, 0x080c, 0x86a4, - 0x080c, 0x72a2, 0x0005, 0xa182, 0x0047, 0x0002, 0x87e9, 0x87f8, - 0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x080c, - 0x151a, 0x00d6, 0x6010, 0x2068, 0x684c, 0xc0f4, 0x684e, 0x00de, - 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1863, 0x0005, - 0x00d6, 0x6110, 0x2168, 0x684b, 0x0000, 0x6853, 0x0000, 0x080c, - 0x547a, 0x00de, 0x080c, 0x86a4, 0x0005, 0xa1b6, 0x0015, 0x1118, - 0x080c, 0x86a4, 0x0030, 0xa1b6, 0x0016, 0x190c, 0x151a, 0x080c, - 0x86a4, 0x0005, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, - 0x20a9, 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0, 0x3318, 0x3428, - 0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002, 0xa398, 0x0002, - 0xa4a0, 0x0002, 0x1f04, 0x8820, 0x00e6, 0x080c, 0x9d16, 0x0130, - 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, 0x00ee, 0x080c, - 0x86a4, 0x0005, 0x00d6, 0x0036, 0x7330, 0xa386, 0x0200, 0x1130, - 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, - 0x0130, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x080c, - 0x86a4, 0x003e, 0x00de, 0x0005, 0x0016, 0x20a9, 0x002a, 0xae80, - 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, - 0x002a, 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, - 0x53a3, 0x00e6, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x00ee, - 0x080c, 0x86a4, 0x001e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030, - 0xa086, 0x0100, 0x0140, 0x7038, 0xa084, 0x00ff, 0x800c, 0x703c, - 0xa084, 0x00ff, 0x8004, 0xa080, 0x0004, 0xa108, 0x21a8, 0xae80, - 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x080c, 0x4bf1, - 0x00e6, 0x080c, 0x9d16, 0x0140, 0x6010, 0x2070, 0x7007, 0x0000, - 0x7034, 0x70b2, 0x7037, 0x0103, 0x00ee, 0x080c, 0x86a4, 0x001e, - 0x0005, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2c68, 0x0016, 0x2009, - 0x0035, 0x080c, 0xa1c6, 0x001e, 0x1168, 0x0026, 0x6228, 0x2268, - 0x002e, 0x2071, 0xbc8c, 0x6b1c, 0xa386, 0x0003, 0x0130, 0xa386, - 0x0006, 0x0128, 0x080c, 0x86a4, 0x0020, 0x0031, 0x0010, 0x080c, - 0x8982, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6810, 0x2078, 0xa186, - 0x0015, 0x0904, 0x8969, 0xa18e, 0x0016, 0x1904, 0x8980, 0x700c, - 0xa08c, 0xff00, 0xa186, 0x1700, 0x0120, 0xa186, 0x0300, 0x1904, - 0x8948, 0x8fff, 0x1138, 0x6800, 0xa086, 0x000f, 0x0904, 0x892c, - 0x0804, 0x897e, 0x6808, 0xa086, 0xffff, 0x1904, 0x896b, 0x784c, - 0xa084, 0x0060, 0xa086, 0x0020, 0x1150, 0x797c, 0x7810, 0xa106, - 0x1904, 0x896b, 0x7980, 0x7814, 0xa106, 0x1904, 0x896b, 0x080c, - 0x9ecd, 0x6858, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, 0x784e, - 0x0026, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x080c, 0x6bb2, 0x7854, - 0xa20a, 0x0208, 0x8011, 0x7a56, 0x82ff, 0x002e, 0x1138, 0x00c6, - 0x2d60, 0x080c, 0x9ac5, 0x00ce, 0x0804, 0x897e, 0x00c6, 0x00d6, - 0x2f68, 0x6838, 0xd0fc, 0x1118, 0x080c, 0x4cd7, 0x0010, 0x080c, - 0x4ebb, 0x00de, 0x00ce, 0x1904, 0x896b, 0x00c6, 0x2d60, 0x080c, - 0x86a4, 0x00ce, 0x0804, 0x897e, 0x00c6, 0x080c, 0x9f92, 0x0190, - 0x6013, 0x0000, 0x6818, 0x601a, 0x080c, 0xa0e3, 0x601f, 0x0003, - 0x6904, 0x00c6, 0x2d60, 0x080c, 0x86a4, 0x00ce, 0x080c, 0x86d3, - 0x00ce, 0x04e0, 0x2001, 0xb8b8, 0x2004, 0x683e, 0x00ce, 0x04b0, - 0x7008, 0xa086, 0x000b, 0x11a0, 0x6018, 0x200c, 0xc1bc, 0x2102, - 0x00c6, 0x2d60, 0x784b, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, - 0x601f, 0x0002, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00ce, 0x00f0, - 0x700c, 0xa086, 0x2a00, 0x1138, 0x2001, 0xb8b8, 0x2004, 0x683e, - 0x00a8, 0x0481, 0x00a8, 0x8fff, 0x090c, 0x151a, 0x00c6, 0x00d6, - 0x2d60, 0x2f68, 0x6837, 0x0103, 0x684b, 0x0003, 0x080c, 0x99b9, - 0x080c, 0x9ecd, 0x080c, 0x9ed9, 0x00de, 0x00ce, 0x080c, 0x86a4, - 0x00fe, 0x0005, 0xa186, 0x0015, 0x1128, 0x2001, 0xb8b8, 0x2004, - 0x683e, 0x0068, 0xa18e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, - 0x080c, 0xb3f6, 0x080c, 0x6b61, 0x080c, 0x86a4, 0x00ce, 0x080c, - 0x86a4, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0x7c80, 0x7b7c, - 0xd2f4, 0x0130, 0x2001, 0xb8b8, 0x2004, 0x683e, 0x0804, 0x89fc, - 0x00c6, 0x2d60, 0x080c, 0x99d9, 0x00ce, 0x6804, 0xa086, 0x0050, - 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, - 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00ce, 0x04f0, 0x6800, 0xa086, - 0x000f, 0x01c8, 0x8fff, 0x090c, 0x151a, 0x6820, 0xd0dc, 0x1198, - 0x6800, 0xa086, 0x0004, 0x1198, 0x784c, 0xd0ac, 0x0180, 0x784c, - 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, - 0x0001, 0x682e, 0x00e0, 0x2001, 0x0007, 0x682e, 0x00c0, 0x784c, - 0xd0b4, 0x1130, 0xd0ac, 0x0db8, 0x784c, 0xd0f4, 0x1da0, 0x0c38, - 0xd2ec, 0x1d88, 0x7024, 0xa306, 0x1118, 0x7020, 0xa406, 0x0d58, - 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, 0x080c, - 0xa01f, 0x080c, 0x71e5, 0x0010, 0x080c, 0x86a4, 0x004e, 0x003e, - 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x6034, 0x2068, 0x6a1c, - 0xa286, 0x0007, 0x0904, 0x8a60, 0xa286, 0x0002, 0x0904, 0x8a60, - 0xa286, 0x0000, 0x0904, 0x8a60, 0x6808, 0x6338, 0xa306, 0x1904, - 0x8a60, 0x2071, 0xbc8c, 0xa186, 0x0015, 0x05e0, 0xa18e, 0x0016, - 0x1190, 0x6030, 0xa084, 0x00ff, 0xa086, 0x0001, 0x1160, 0x700c, - 0xa086, 0x2a00, 0x1140, 0x6034, 0xa080, 0x0008, 0x200c, 0xc1dd, - 0xc1f5, 0x2102, 0x0438, 0x00c6, 0x6034, 0x2060, 0x6104, 0xa186, - 0x004b, 0x01a0, 0xa186, 0x004c, 0x0188, 0xa186, 0x004d, 0x0170, - 0xa186, 0x004e, 0x0158, 0xa186, 0x0052, 0x0140, 0x6010, 0x2068, - 0x080c, 0x9d16, 0x090c, 0x151a, 0x684b, 0x0003, 0x6007, 0x0085, - 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x6cff, 0x080c, 0x71e5, - 0x00ce, 0x0030, 0x6034, 0x2070, 0x2001, 0xb8b8, 0x2004, 0x703e, - 0x080c, 0x86a4, 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x20a9, - 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x1558, - 0x6018, 0x2068, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, 0xa290, - 0x0004, 0x20a9, 0x0004, 0xad98, 0x000a, 0x080c, 0x9166, 0x002e, - 0x003e, 0x015e, 0x11d8, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, - 0xa290, 0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, 0x080c, 0x9166, - 0x002e, 0x003e, 0x015e, 0x1150, 0x7038, 0x680a, 0x703c, 0x680e, - 0x6800, 0xc08d, 0x6802, 0x00de, 0x0804, 0x882c, 0x080c, 0x2cd1, - 0x00c6, 0x080c, 0x864e, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f, - 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, - 0x4f6f, 0x080c, 0x4f9c, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00ce, - 0x0c10, 0x2100, 0xa1b2, 0x0080, 0x1a0c, 0x151a, 0xa1b2, 0x0040, - 0x1a04, 0x8b1d, 0x0002, 0x8b11, 0x8b05, 0x8b11, 0x8b11, 0x8b11, - 0x8b11, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, - 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, - 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, - 0x8b03, 0x8b03, 0x8b11, 0x8b03, 0x8b11, 0x8b11, 0x8b03, 0x8b03, - 0x8b03, 0x8b03, 0x8b03, 0x8b11, 0x8b03, 0x8b03, 0x8b03, 0x8b03, - 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b11, 0x8b11, 0x8b03, - 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, - 0x8b11, 0x8b03, 0x8b03, 0x080c, 0x151a, 0x6003, 0x0001, 0x6106, - 0x080c, 0x6d45, 0x0126, 0x2091, 0x8000, 0x080c, 0x71e5, 0x012e, - 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x6d45, 0x0126, 0x2091, - 0x8000, 0x080c, 0x71e5, 0x012e, 0x0005, 0x2600, 0x0002, 0x8b11, - 0x8b11, 0x8b25, 0x8b11, 0x8b11, 0x8b25, 0x080c, 0x151a, 0x6004, - 0xa0b2, 0x0080, 0x1a0c, 0x151a, 0xa1b6, 0x0013, 0x0904, 0x8bd7, - 0xa1b6, 0x0027, 0x1904, 0x8b9d, 0x080c, 0x7102, 0x6004, 0x080c, - 0x9f03, 0x0190, 0x080c, 0x9f14, 0x0904, 0x8b97, 0xa08e, 0x0021, - 0x0904, 0x8b9a, 0xa08e, 0x0022, 0x0904, 0x8b97, 0xa08e, 0x003d, - 0x0904, 0x8b9a, 0x0804, 0x8b90, 0x080c, 0x2cf7, 0x2001, 0x0007, - 0x080c, 0x4f6f, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8ca5, - 0xa186, 0x007e, 0x1148, 0x2001, 0xb635, 0x2014, 0xc285, 0x080c, - 0x5b41, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110, - 0x0026, 0x2019, 0x0028, 0x080c, 0x8320, 0x002e, 0x080c, 0xb449, - 0x003e, 0x002e, 0x001e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, - 0x0028, 0x080c, 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, - 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, 0x521c, 0x00ce, 0x2c08, - 0x080c, 0xaf3e, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0x4fde, - 0x080c, 0xa0db, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, 0x080c, - 0x8ca5, 0x0cb0, 0x080c, 0x8cd3, 0x0c98, 0xa186, 0x0014, 0x1db0, - 0x080c, 0x7102, 0x080c, 0x2cd1, 0x080c, 0x9f03, 0x1188, 0x080c, - 0x2cf7, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8ca5, 0xa186, - 0x007e, 0x1128, 0x2001, 0xb635, 0x200c, 0xc185, 0x2102, 0x08c0, - 0x080c, 0x9f14, 0x1118, 0x080c, 0x8ca5, 0x0890, 0x6004, 0xa08e, - 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0xb682, 0x2079, 0x0000, - 0x080c, 0x3004, 0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e, 0x0021, - 0x0d50, 0xa08e, 0x0022, 0x090c, 0x8ca5, 0x0804, 0x8b90, 0xa0b2, - 0x0040, 0x1a04, 0x8c9a, 0x2008, 0x0002, 0x8c1f, 0x8c20, 0x8c23, - 0x8c26, 0x8c29, 0x8c2c, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, - 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, - 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, - 0x8c1d, 0x8c1d, 0x8c1d, 0x8c2f, 0x8c3e, 0x8c1d, 0x8c40, 0x8c3e, - 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c3e, 0x8c3e, 0x8c1d, - 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c7a, - 0x8c3e, 0x8c1d, 0x8c3a, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c3b, 0x8c1d, - 0x8c1d, 0x8c1d, 0x8c3e, 0x8c71, 0x8c1d, 0x080c, 0x151a, 0x00f0, - 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, 0x2001, 0x0005, - 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, 0x0400, 0x080c, - 0x7102, 0x6003, 0x0005, 0x2001, 0xb8b8, 0x2004, 0x603e, 0x080c, - 0x71e5, 0x00a0, 0x0018, 0x0010, 0x080c, 0x4f6f, 0x0804, 0x8c8b, - 0x080c, 0x7102, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x2001, 0xb8b8, - 0x2004, 0x603e, 0x6003, 0x0004, 0x080c, 0x71e5, 0x0005, 0x080c, - 0x4f6f, 0x080c, 0x7102, 0x6003, 0x0002, 0x2001, 0xb8b8, 0x2004, - 0x603e, 0x0036, 0x2019, 0xb65d, 0x2304, 0xa084, 0xff00, 0x1120, - 0x2001, 0xb8b6, 0x201c, 0x0040, 0x8007, 0xa09a, 0x0004, 0x0ec0, - 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x080c, 0x71e5, - 0x08e8, 0x080c, 0x7102, 0x080c, 0xa0db, 0x080c, 0x86a4, 0x080c, - 0x71e5, 0x08a0, 0x00e6, 0x00f6, 0x2071, 0xb682, 0x2079, 0x0000, - 0x080c, 0x3004, 0x00fe, 0x00ee, 0x080c, 0x7102, 0x080c, 0x86a4, - 0x080c, 0x71e5, 0x0818, 0x080c, 0x7102, 0x2001, 0xb8b8, 0x2004, - 0x603e, 0x6003, 0x0002, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x080c, - 0x71e5, 0x0005, 0x2600, 0x2008, 0x0002, 0x8ca3, 0x8ca3, 0x8ca3, - 0x8c8b, 0x8c8b, 0x8ca3, 0x080c, 0x151a, 0x00e6, 0x0026, 0x0016, - 0x080c, 0x9d16, 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, - 0x1148, 0x2001, 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, - 0xa192, 0x0090, 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, - 0x6004, 0xa08e, 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, - 0x7037, 0x0103, 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, - 0x001e, 0x0009, 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, - 0x2070, 0x7037, 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, - 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, - 0x1a0c, 0x151a, 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0xa14e, - 0x0804, 0x8d44, 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0xa0fe, - 0x0804, 0x8d44, 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0x9f44, - 0x0804, 0x8d44, 0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x9f5b, - 0x04d8, 0x6604, 0xa6b6, 0x001f, 0x1118, 0x080c, 0x8812, 0x04a0, - 0x6604, 0xa6b6, 0x0000, 0x1118, 0x080c, 0x8a66, 0x0468, 0x6604, - 0xa6b6, 0x0022, 0x1118, 0x080c, 0x883a, 0x0430, 0x6604, 0xa6b6, - 0x0035, 0x1118, 0x080c, 0x88a1, 0x00f8, 0x6604, 0xa6b6, 0x0039, - 0x1118, 0x080c, 0x8a02, 0x00c0, 0x6604, 0xa6b6, 0x003d, 0x1118, - 0x080c, 0x8854, 0x0088, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, - 0x8874, 0x0050, 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, - 0x0016, 0x1118, 0x0804, 0x8f08, 0x0005, 0x080c, 0x86ef, 0x0ce0, - 0x8d6b, 0x8d6e, 0x8d6b, 0x8db0, 0x8d6b, 0x8e95, 0x8f16, 0x8d6b, - 0x8d6b, 0x8ee4, 0x8d6b, 0x8ef8, 0xa1b6, 0x0048, 0x0140, 0x20e1, - 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1863, 0x0005, 0x00e6, - 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, - 0x080c, 0x86a4, 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, - 0xb600, 0x7084, 0xa086, 0x0074, 0x1530, 0x080c, 0xaf15, 0x11b0, - 0x00d6, 0x6018, 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, - 0x0110, 0xc0c5, 0x6802, 0x00d9, 0x00de, 0x2001, 0x0006, 0x080c, - 0x4f6f, 0x080c, 0x2cf7, 0x080c, 0x86a4, 0x0078, 0x2001, 0x000a, - 0x080c, 0x4f6f, 0x080c, 0x2cf7, 0x6003, 0x0001, 0x6007, 0x0001, - 0x080c, 0x6d45, 0x0010, 0x080c, 0x8e82, 0x00ee, 0x0005, 0x6800, - 0xd084, 0x0168, 0x2001, 0x0000, 0x080c, 0x4f5d, 0x2069, 0xb652, - 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x4f9c, 0x0005, - 0x00d6, 0x2011, 0xb621, 0x2204, 0xa086, 0x0074, 0x1904, 0x8e7f, - 0x6018, 0x2068, 0x6aa0, 0xa286, 0x007e, 0x1120, 0x080c, 0x902e, - 0x0804, 0x8e1e, 0x080c, 0x9024, 0x6018, 0x2068, 0xa080, 0x0028, - 0x2014, 0xa286, 0x0080, 0x11c0, 0x6813, 0x00ff, 0x6817, 0xfffc, - 0x6010, 0xa005, 0x0138, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, - 0x6833, 0x0200, 0x2001, 0x0006, 0x080c, 0x4f6f, 0x080c, 0x2cf7, - 0x080c, 0x86a4, 0x0804, 0x8e80, 0x00e6, 0x2071, 0xb635, 0x2e04, - 0xd09c, 0x0188, 0x2071, 0xbc80, 0x7108, 0x720c, 0xa18c, 0x00ff, - 0x1118, 0xa284, 0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc, - 0x1110, 0x7112, 0x7216, 0x00ee, 0x6010, 0xa005, 0x0198, 0x2068, - 0x6838, 0xd0f4, 0x0178, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0039, - 0x1958, 0x2001, 0x0000, 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, - 0xa192, 0x0840, 0x2001, 0x0004, 0x080c, 0x4f6f, 0x6003, 0x0001, - 0x6007, 0x0003, 0x080c, 0x6d45, 0x0804, 0x8e80, 0x685c, 0xd0e4, - 0x01d8, 0x080c, 0xa08e, 0x080c, 0x5b41, 0x0118, 0xd0dc, 0x1904, - 0x8dda, 0x2011, 0xb635, 0x2204, 0xc0ad, 0x2012, 0x2001, 0xb88f, - 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x28a7, - 0x78e2, 0x00fe, 0x0804, 0x8dda, 0x080c, 0xa0c4, 0x2011, 0xb635, - 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xb037, 0x000e, 0x1904, - 0x8dda, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x4f6f, 0x2001, - 0x0000, 0x080c, 0x4f5d, 0x00c6, 0x2009, 0x00ef, 0x00f6, 0x2079, - 0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe, 0x080c, 0x287c, 0x00f6, - 0x2079, 0xb600, 0x7976, 0x2100, 0x2009, 0x0000, 0x080c, 0x2852, - 0x7952, 0x00fe, 0x8108, 0x080c, 0x4fbf, 0x2c00, 0x00ce, 0x1904, - 0x8dda, 0x601a, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x601f, 0x0001, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6d45, 0x0008, 0x0011, - 0x00de, 0x0005, 0x2001, 0x0007, 0x080c, 0x4f6f, 0x2001, 0xb600, - 0x2004, 0xa086, 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, 0x4f9c, - 0x080c, 0x2cf7, 0x080c, 0x86a4, 0x0005, 0x00e6, 0x0026, 0x0016, - 0x2071, 0xb600, 0x7084, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, - 0x0003, 0x1128, 0x6010, 0xa005, 0x1110, 0x080c, 0x3f85, 0x00d6, - 0x6018, 0x2068, 0x080c, 0x50bd, 0x080c, 0x8d9f, 0x00de, 0x080c, - 0x90dd, 0x1550, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, - 0x0518, 0x2001, 0x0006, 0x080c, 0x4f6f, 0x00e6, 0x6010, 0xa075, - 0x01a8, 0x7034, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, - 0x0000, 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0xa192, 0x0030, - 0x7007, 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, - 0x2cf7, 0x080c, 0x86a4, 0x0020, 0x080c, 0x8ca5, 0x080c, 0x8e82, - 0x001e, 0x002e, 0x00ee, 0x0005, 0x2011, 0xb621, 0x2204, 0xa086, - 0x0014, 0x1158, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x6d45, 0x0010, 0x080c, 0x8e82, 0x0005, - 0x2011, 0xb621, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007, - 0x080c, 0x4f6f, 0x080c, 0x86a4, 0x0010, 0x080c, 0x8e82, 0x0005, - 0x000b, 0x0005, 0x8d6b, 0x8f21, 0x8d6b, 0x8f55, 0x8d6b, 0x8fe0, - 0x8f16, 0x8d6b, 0x8d6b, 0x8ff3, 0x8d6b, 0x9003, 0x6604, 0xa686, - 0x0003, 0x0904, 0x8e95, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x86a4, - 0x0005, 0x00d6, 0x00c6, 0x080c, 0x9013, 0x1178, 0x2001, 0x0000, - 0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003, 0x0001, - 0x6007, 0x0002, 0x080c, 0x6d45, 0x00e8, 0x2009, 0xbc8e, 0x2104, - 0xa086, 0x0009, 0x1160, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, - 0xa005, 0x0170, 0x8001, 0x6842, 0x6017, 0x000a, 0x0058, 0x2009, - 0xbc8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900, 0x1108, 0x08d0, - 0x080c, 0x8e82, 0x00ce, 0x00de, 0x0005, 0x0026, 0x2011, 0x0000, - 0x080c, 0x9021, 0x00d6, 0x2069, 0xb89e, 0x2d04, 0xa005, 0x0168, - 0x6018, 0x2068, 0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0xb61d, - 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, - 0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x6d45, 0x0480, 0x00d6, 0x6010, - 0x2068, 0x080c, 0x9d16, 0x00de, 0x0108, 0x6a34, 0x080c, 0x8ca5, - 0x2009, 0xbc8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0500, - 0xa686, 0x000b, 0x01c8, 0x2009, 0xbc8f, 0x2104, 0xa084, 0xff00, - 0x1118, 0xa686, 0x0009, 0x01a0, 0xa086, 0x1900, 0x1168, 0xa686, - 0x0009, 0x0170, 0x2001, 0x0004, 0x080c, 0x4f6f, 0x2001, 0x0028, - 0x6016, 0x6007, 0x004b, 0x0010, 0x080c, 0x8e82, 0x002e, 0x0005, - 0x00d6, 0xa286, 0x0139, 0x0160, 0x6010, 0x2068, 0x080c, 0x9d16, - 0x0148, 0x6834, 0xa086, 0x0139, 0x0118, 0x6838, 0xd0fc, 0x0110, - 0x00de, 0x0c50, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, - 0x0140, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, - 0x08e8, 0x68a0, 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xb600, - 0x080c, 0x4c28, 0x00ee, 0x0010, 0x080c, 0x2cd1, 0x00de, 0x0860, - 0x080c, 0x9021, 0x1158, 0x2001, 0x0004, 0x080c, 0x4f6f, 0x6003, - 0x0001, 0x6007, 0x0003, 0x080c, 0x6d45, 0x0020, 0x080c, 0x8ca5, - 0x080c, 0x8e82, 0x0005, 0x0469, 0x1158, 0x2001, 0x0008, 0x080c, - 0x4f6f, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x6d45, 0x0010, - 0x080c, 0x8e82, 0x0005, 0x00e9, 0x1158, 0x2001, 0x000a, 0x080c, - 0x4f6f, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x6d45, 0x0010, - 0x080c, 0x8e82, 0x0005, 0x2009, 0xbc8e, 0x2104, 0xa086, 0x0003, - 0x1138, 0x2009, 0xbc8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, - 0x0005, 0xa085, 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006, - 0x2164, 0x080c, 0x502a, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, - 0x00d6, 0x0036, 0x0016, 0x6018, 0x2068, 0x2071, 0xb635, 0x2e04, - 0xa085, 0x0003, 0x2072, 0x080c, 0x90b2, 0x0560, 0x2009, 0xb635, - 0x2104, 0xc0cd, 0x200a, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x0158, - 0xa006, 0x2020, 0x2009, 0x002a, 0x080c, 0xb1a4, 0x2001, 0xb60c, - 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x080c, - 0x2ca4, 0x2071, 0xb600, 0x080c, 0x2aed, 0x00c6, 0x0156, 0x20a9, - 0x0081, 0x2009, 0x007f, 0x080c, 0x2dcc, 0x8108, 0x1f04, 0x9063, - 0x015e, 0x00ce, 0x080c, 0x9024, 0x6813, 0x00ff, 0x6817, 0xfffe, - 0x2071, 0xbc80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, - 0xb61c, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0xb61d, - 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0xa084, 0xff00, 0x001e, - 0xa105, 0x2009, 0xb628, 0x200a, 0x2200, 0xa084, 0x00ff, 0x2008, - 0x080c, 0x287c, 0x080c, 0x5b41, 0x0170, 0x2069, 0xbc8e, 0x2071, - 0xb8b2, 0x6810, 0x2072, 0x6814, 0x7006, 0x6818, 0x700a, 0x681c, - 0x700e, 0x080c, 0xa08e, 0x0040, 0x2001, 0x0006, 0x080c, 0x4f6f, - 0x080c, 0x2cf7, 0x080c, 0x86a4, 0x001e, 0x003e, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0xb628, - 0x231c, 0x83ff, 0x01e8, 0x2071, 0xbc80, 0x2e14, 0xa294, 0x00ff, - 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, 0x1190, 0x2011, 0xbc96, - 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1148, 0x2011, - 0xbc9a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1100, - 0x015e, 0x00ee, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xbc8c, - 0x7004, 0xa086, 0x0014, 0x11a8, 0x7008, 0xa086, 0x0800, 0x1188, - 0x700c, 0xd0ec, 0x0160, 0xa084, 0x0f00, 0xa086, 0x0100, 0x1138, - 0x7024, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0xa006, 0x0010, 0xa085, - 0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0056, - 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0xb8ea, - 0x252c, 0x2021, 0xb8f0, 0x2424, 0x2061, 0xbe00, 0x2071, 0xb600, - 0x7248, 0x7068, 0xa202, 0x16f0, 0x080c, 0xb1cc, 0x05a0, 0x671c, - 0xa786, 0x0001, 0x0580, 0xa786, 0x0007, 0x0568, 0x2500, 0xac06, - 0x0550, 0x2400, 0xac06, 0x0538, 0x00c6, 0x6000, 0xa086, 0x0004, - 0x1110, 0x080c, 0x1952, 0xa786, 0x0008, 0x1148, 0x080c, 0x9f14, - 0x1130, 0x00ce, 0x080c, 0x8ca5, 0x080c, 0x9ed9, 0x00a0, 0x6010, - 0x2068, 0x080c, 0x9d16, 0x0160, 0xa786, 0x0003, 0x11e8, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, - 0x080c, 0x9ed9, 0x00ce, 0xace0, 0x0018, 0x705c, 0xac02, 0x1210, - 0x0804, 0x9110, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e, - 0x00ce, 0x00de, 0x00ee, 0x0005, 0xa786, 0x0006, 0x1118, 0x080c, - 0xb155, 0x0c30, 0xa786, 0x000a, 0x09e0, 0x08c8, 0x220c, 0x2304, - 0xa106, 0x1130, 0x8210, 0x8318, 0x1f04, 0x9166, 0xa006, 0x0005, - 0x2304, 0xa102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, - 0xa18d, 0x0001, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x151a, - 0x080c, 0x9f03, 0x0120, 0x080c, 0x9f14, 0x0168, 0x0028, 0x080c, - 0x2cf7, 0x080c, 0x9f14, 0x0138, 0x080c, 0x7102, 0x080c, 0x86a4, - 0x080c, 0x71e5, 0x0005, 0x080c, 0x8ca5, 0x0cb0, 0xa182, 0x0040, - 0x0002, 0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ac, - 0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ae, 0x91ae, 0x91ae, 0x91ae, - 0x91ac, 0x91ac, 0x91ac, 0x91ae, 0x080c, 0x151a, 0x600b, 0xffff, - 0x6003, 0x0001, 0x6106, 0x080c, 0x6cff, 0x0126, 0x2091, 0x8000, - 0x080c, 0x71e5, 0x012e, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, - 0xa082, 0x0040, 0x0804, 0x9248, 0xa186, 0x0027, 0x11e8, 0x080c, - 0x7102, 0x080c, 0x2cd1, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9d16, - 0x0168, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, 0x694c, - 0xc1c5, 0x694e, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c, - 0x86a4, 0x080c, 0x71e5, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004, - 0xa082, 0x0040, 0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045, - 0x0120, 0xa186, 0x0047, 0x190c, 0x151a, 0x2001, 0x0109, 0x2004, - 0xd084, 0x0198, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, - 0x080c, 0x6be6, 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000, - 0xa086, 0x0002, 0x1110, 0x0804, 0x9286, 0x080c, 0x86ef, 0x0005, - 0x0002, 0x9226, 0x9224, 0x9224, 0x9224, 0x9224, 0x9224, 0x9224, - 0x9224, 0x9224, 0x9224, 0x9224, 0x9241, 0x9241, 0x9241, 0x9241, - 0x9224, 0x9241, 0x9224, 0x9241, 0x080c, 0x151a, 0x080c, 0x7102, - 0x00d6, 0x6110, 0x2168, 0x080c, 0x9d16, 0x0168, 0x6837, 0x0103, - 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x080c, - 0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c, 0x86a4, 0x080c, 0x71e5, - 0x0005, 0x080c, 0x7102, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, - 0x0002, 0x925e, 0x925c, 0x925c, 0x925c, 0x925c, 0x925c, 0x925c, - 0x925c, 0x925c, 0x925c, 0x925c, 0x9270, 0x9270, 0x9270, 0x9270, - 0x925c, 0x927f, 0x925c, 0x9270, 0x080c, 0x151a, 0x080c, 0x7102, - 0x2001, 0xb8b8, 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x71e5, - 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x0005, - 0x080c, 0x7102, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x2001, 0xb8b8, - 0x2004, 0x603e, 0x6003, 0x000f, 0x080c, 0x71e5, 0x0005, 0x080c, - 0x7102, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, 0xa182, 0x0040, - 0x0002, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c, 0x929e, 0x9386, - 0x93b5, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c, - 0x929c, 0x929c, 0x929c, 0x929c, 0x080c, 0x151a, 0x00e6, 0x00d6, - 0x603f, 0x0000, 0x2071, 0xbc80, 0x7124, 0x610a, 0x2071, 0xbc8c, - 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0904, 0x934c, - 0xa68c, 0x0c00, 0x0518, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, - 0x01c8, 0x684c, 0xd0ac, 0x01b0, 0x6020, 0xd0dc, 0x1198, 0x6850, - 0xd0bc, 0x1180, 0x7318, 0x6814, 0xa306, 0x1904, 0x935f, 0x731c, - 0x6810, 0xa31e, 0x0138, 0xd6d4, 0x0904, 0x935f, 0x6b14, 0xa305, - 0x1904, 0x935f, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, - 0xa186, 0x0002, 0x0518, 0xa186, 0x0028, 0x1128, 0x080c, 0x9ef2, - 0x684b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0x684b, 0x0015, 0x684c, - 0xd0ac, 0x0170, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0148, 0x7018, - 0xa106, 0x1118, 0x701c, 0xa206, 0x0118, 0x6962, 0x6a5e, 0xc6dc, - 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, - 0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x01f0, 0xa686, 0x0100, - 0x1140, 0x2001, 0xbc99, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x0804, - 0x92ad, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, 0x0009, - 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xbc98, 0xad90, - 0x0019, 0x080c, 0x99c9, 0x003e, 0xd6cc, 0x0904, 0x9375, 0x7124, - 0x695a, 0x81ff, 0x0904, 0x9375, 0xa192, 0x0021, 0x1260, 0x2071, - 0xbc98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x99c9, - 0x080c, 0xa1f3, 0x04d0, 0x6838, 0xd0fc, 0x0120, 0x2009, 0x0020, - 0x695a, 0x0c68, 0x00f6, 0x2d78, 0x080c, 0x996e, 0x00fe, 0x080c, - 0xa1f3, 0x080c, 0x99b9, 0x0458, 0x00f6, 0x2c78, 0x080c, 0x5377, - 0x00fe, 0x0190, 0x684c, 0xd0ac, 0x0178, 0x6020, 0xd0dc, 0x1160, - 0x6850, 0xd0bc, 0x1148, 0x6810, 0x6914, 0xa105, 0x0128, 0x080c, - 0x9ff1, 0x00de, 0x00ee, 0x0408, 0x684b, 0x0000, 0x6837, 0x0103, - 0x6e46, 0x080c, 0x9523, 0x1148, 0x684c, 0xd0ac, 0x0130, 0x6810, - 0x6914, 0xa115, 0x0110, 0x080c, 0x953f, 0x080c, 0x547a, 0x6218, - 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x080c, 0x9fbf, - 0x00de, 0x00ee, 0x1110, 0x080c, 0x86a4, 0x0005, 0x00f6, 0x6003, - 0x0003, 0x2079, 0xbc8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, - 0x2078, 0x784c, 0xd0ac, 0x0138, 0x6003, 0x0002, 0x00fe, 0x0005, - 0x2130, 0x2228, 0x0058, 0x2400, 0x797c, 0xa10a, 0x2300, 0x7a80, - 0xa213, 0x2600, 0xa102, 0x2500, 0xa203, 0x0e90, 0x7c12, 0x7b16, - 0x7e0a, 0x7d0e, 0x00fe, 0x603f, 0x0000, 0x2c10, 0x080c, 0x1fc5, - 0x080c, 0x6d62, 0x080c, 0x72a2, 0x0005, 0x2001, 0xb8b8, 0x2004, - 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, - 0x2c10, 0x080c, 0x1863, 0x0005, 0xa182, 0x0040, 0x0002, 0x93da, - 0x93da, 0x93da, 0x93da, 0x93da, 0x93dc, 0x946f, 0x93da, 0x93da, - 0x9485, 0x94eb, 0x93da, 0x93da, 0x93da, 0x93da, 0x9509, 0x93da, - 0x93da, 0x93da, 0x080c, 0x151a, 0x0076, 0x00f6, 0x00e6, 0x00d6, - 0x2071, 0xbc8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, - 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, - 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x946a, 0xa694, 0xff00, 0xa284, - 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, - 0x0904, 0x946a, 0x080c, 0x15fd, 0x090c, 0x151a, 0x2d00, 0x784a, - 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, - 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, - 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, - 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, - 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, - 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, - 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, - 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xbc98, - 0xad90, 0x0019, 0x080c, 0x99c9, 0x003e, 0xd6cc, 0x01d8, 0x7124, - 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, 0xbc98, - 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x99c9, 0x0050, - 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, - 0x080c, 0x996e, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x00f6, - 0x6003, 0x0003, 0x2079, 0xbc8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, - 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x2c10, - 0x080c, 0x1fc5, 0x080c, 0x7dd9, 0x0005, 0x00d6, 0x00f6, 0x2c78, - 0x080c, 0x5377, 0x00fe, 0x0120, 0x2001, 0xb8b8, 0x2004, 0x603e, - 0x6003, 0x0002, 0x080c, 0x7198, 0x080c, 0x72a2, 0x6110, 0x2168, - 0x694c, 0xd1e4, 0x0904, 0x94e9, 0xd1cc, 0x0540, 0x6948, 0x6838, - 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, 0xad90, - 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, - 0x2012, 0x8318, 0x8210, 0x1f04, 0x94af, 0x015e, 0x000e, 0x6852, - 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1624, 0x0428, 0x0016, - 0x080c, 0x1624, 0x00de, 0x080c, 0x99b9, 0x00f0, 0x6837, 0x0103, - 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086, 0x0028, - 0x1118, 0x684b, 0x001c, 0x0070, 0xd1dc, 0x0118, 0x684b, 0x0015, - 0x0048, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0020, 0x684b, 0x0000, - 0x080c, 0x9523, 0x080c, 0x547a, 0x080c, 0x9fbf, 0x1110, 0x080c, - 0x86a4, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x806b, 0x6003, - 0x0002, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0140, 0x6808, - 0x612c, 0xa10a, 0x612e, 0x680c, 0x6128, 0xa10b, 0x612a, 0x00de, - 0x2001, 0xb8b8, 0x2004, 0x603e, 0x080c, 0x7198, 0x080c, 0x72a2, - 0x0005, 0x080c, 0x7198, 0x080c, 0x2cd1, 0x00d6, 0x6110, 0x2168, - 0x080c, 0x9d16, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, - 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c, 0x86a4, - 0x080c, 0x72a2, 0x0005, 0x684c, 0xd0b4, 0x01c0, 0x602c, 0x697c, - 0xa112, 0x6028, 0x6980, 0xa10b, 0x2100, 0xa205, 0x0168, 0x684b, - 0x0015, 0xd1fc, 0x0138, 0x684b, 0x0007, 0x8212, 0x8210, 0x810a, - 0xa189, 0x0000, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x0005, 0x684b, - 0x0015, 0xd1fc, 0x0138, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, - 0xa189, 0x0000, 0x6962, 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, - 0x9563, 0x9563, 0x9563, 0x9563, 0x9563, 0x9565, 0x9563, 0x9620, - 0x962c, 0x9563, 0x9563, 0x9563, 0x9563, 0x9563, 0x9563, 0x9563, - 0x9563, 0x9563, 0x9563, 0x080c, 0x151a, 0x0076, 0x00f6, 0x00e6, - 0x00d6, 0x2071, 0xbc8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, - 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, 0x0150, 0xa684, 0x00ff, - 0x1138, 0x6020, 0xd0f4, 0x0120, 0x080c, 0x9ff1, 0x0804, 0x961b, - 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, - 0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x9611, 0xa694, 0xff00, - 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, - 0x0300, 0x0904, 0x960f, 0xa686, 0x0100, 0x1140, 0x2001, 0xbc99, - 0x2004, 0xa005, 0x1118, 0xc6c4, 0x7e46, 0x0c28, 0x080c, 0x15fd, - 0x090c, 0x151a, 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, - 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, - 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, - 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, 0xa186, 0x0028, 0x1118, - 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, - 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, - 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, - 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, - 0x0008, 0x0036, 0x2308, 0x2019, 0xbc98, 0xad90, 0x0019, 0x080c, - 0x99c9, 0x003e, 0xd6cc, 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, - 0xa192, 0x0021, 0x1250, 0x2071, 0xbc98, 0x831c, 0x2300, 0xae18, - 0xad90, 0x001d, 0x080c, 0x99c9, 0x0050, 0x7838, 0xd0fc, 0x0120, - 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, 0x080c, 0x996e, 0xd6dc, - 0x1110, 0xa006, 0x0030, 0x2001, 0x0001, 0x2071, 0xbc8c, 0x7218, - 0x731c, 0x080c, 0x18b6, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, - 0x2001, 0xb8b8, 0x2004, 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20, - 0x2c10, 0x080c, 0x1863, 0x0005, 0x2001, 0xb8b8, 0x2004, 0x603e, - 0x00d6, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, - 0x9737, 0x603f, 0x0000, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, - 0x0560, 0x6814, 0x6910, 0xa115, 0x0540, 0x6a60, 0xa206, 0x1118, - 0x685c, 0xa106, 0x0510, 0x684c, 0xc0e4, 0x684e, 0x6847, 0x0000, - 0x6863, 0x0000, 0x685f, 0x0000, 0x6020, 0xd0f4, 0x1158, 0x697c, - 0x6810, 0xa102, 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6020, - 0xc0f5, 0x6022, 0x00d6, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e, - 0x00de, 0x080c, 0x9ff1, 0x0804, 0x9737, 0x694c, 0xd1cc, 0x0904, - 0x9707, 0x6948, 0x6838, 0xd0fc, 0x0904, 0x96ca, 0x0016, 0x684c, - 0x0006, 0x6850, 0x0006, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, - 0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, - 0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, - 0x0015, 0x080c, 0xa17b, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, - 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, - 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x953f, - 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, - 0xaf98, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012, - 0x8318, 0x8210, 0x1f04, 0x96b6, 0x015e, 0x00fe, 0x000e, 0x6852, - 0x000e, 0x684e, 0x080c, 0xa1f3, 0x001e, 0x2168, 0x080c, 0x1624, - 0x0804, 0x9732, 0x0016, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, - 0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, - 0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, - 0x0015, 0x080c, 0xa17b, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, - 0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, - 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x953f, - 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e, 0x00fe, 0x080c, - 0x1624, 0x00de, 0x080c, 0xa1f3, 0x080c, 0x99b9, 0x0458, 0x6837, - 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01b0, 0xa086, - 0x0028, 0x1118, 0x684b, 0x001c, 0x00d8, 0xd1dc, 0x0148, 0x684b, - 0x0015, 0x080c, 0xa17b, 0x0118, 0x6944, 0xc1dc, 0x6946, 0x0080, - 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0058, 0x684b, 0x0000, 0x684c, - 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x953f, - 0x080c, 0x547a, 0x080c, 0x9fbf, 0x1110, 0x080c, 0x86a4, 0x00de, - 0x0005, 0x080c, 0x7102, 0x0010, 0x080c, 0x7198, 0x080c, 0x9d16, - 0x01c0, 0x00d6, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xb60c, - 0x210c, 0xd18c, 0x11c0, 0xd184, 0x1198, 0x6108, 0x694a, 0xa18e, - 0x0029, 0x1110, 0x080c, 0xb43c, 0x6847, 0x0000, 0x080c, 0x547a, - 0x00de, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x080c, 0x72a2, 0x0005, - 0x684b, 0x0004, 0x0c88, 0x684b, 0x0004, 0x0c70, 0xa182, 0x0040, - 0x0002, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c, 0x977e, 0x977c, - 0x9781, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c, - 0x977c, 0x977c, 0x977c, 0x977c, 0x080c, 0x151a, 0x080c, 0x86a4, - 0x0005, 0x0006, 0x0026, 0xa016, 0x080c, 0x1863, 0x002e, 0x000e, - 0x0005, 0xa182, 0x0085, 0x0002, 0x9795, 0x9793, 0x9793, 0x97a1, - 0x9793, 0x9793, 0x9793, 0x080c, 0x151a, 0x6003, 0x0001, 0x6106, - 0x080c, 0x6cff, 0x0126, 0x2091, 0x8000, 0x080c, 0x71e5, 0x012e, - 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0xbc80, 0x7224, - 0x6212, 0x7220, 0x080c, 0x9d06, 0x01a0, 0x2268, 0x6800, 0xa086, - 0x0000, 0x0178, 0x6018, 0x6d18, 0xa52e, 0x1158, 0x00c6, 0x2d60, - 0x080c, 0x99d9, 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086, - 0x0010, 0x6007, 0x0087, 0x6003, 0x0001, 0x080c, 0x6cff, 0x080c, - 0x71e5, 0x00f6, 0x2278, 0x080c, 0x5377, 0x00fe, 0x0150, 0x6820, - 0xd0ec, 0x0138, 0x00c6, 0x2260, 0x603f, 0x0000, 0x080c, 0x9ff1, - 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0xa186, 0x0013, - 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x151a, 0xa08a, 0x008c, - 0x1a0c, 0x151a, 0xa082, 0x0085, 0x0072, 0xa186, 0x0027, 0x0120, - 0xa186, 0x0014, 0x190c, 0x151a, 0x080c, 0x7102, 0x080c, 0x9ed9, - 0x080c, 0x71e5, 0x0005, 0x9802, 0x9804, 0x9804, 0x9802, 0x9802, - 0x9802, 0x9802, 0x080c, 0x151a, 0x080c, 0x7102, 0x080c, 0x9ed9, - 0x080c, 0x71e5, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, - 0x0085, 0x2008, 0x04a8, 0xa186, 0x0027, 0x11e8, 0x080c, 0x7102, - 0x080c, 0x2cd1, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0150, - 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0029, 0x080c, 0x547a, - 0x080c, 0x9ecd, 0x00de, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, - 0x080c, 0x86ef, 0x0ce0, 0xa186, 0x0014, 0x1dd0, 0x080c, 0x7102, - 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0d60, 0x6837, 0x0103, - 0x6847, 0x0000, 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x08f0, - 0x0002, 0x9852, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x986a, - 0x080c, 0x151a, 0x080c, 0x7102, 0x6030, 0xa08c, 0xff00, 0x810f, - 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x2001, 0xb8b6, - 0x0010, 0x2001, 0xb8b7, 0x2004, 0x6016, 0x6003, 0x000c, 0x080c, - 0x71e5, 0x0005, 0x080c, 0x7102, 0x6030, 0xa08c, 0xff00, 0x810f, - 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x2001, 0xb8b6, - 0x0010, 0x2001, 0xb8b7, 0x2004, 0x6016, 0x6003, 0x000e, 0x080c, - 0x71e5, 0x0005, 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, - 0x001a, 0x080c, 0x86ef, 0x0005, 0x9893, 0x9893, 0x9893, 0x9893, - 0x9895, 0x98ee, 0x9893, 0x080c, 0x151a, 0x00d6, 0x00f6, 0x2c78, - 0x080c, 0x5377, 0x00fe, 0x0168, 0x6030, 0xa08c, 0xff00, 0x810f, - 0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x00de, 0x0804, - 0x9901, 0x080c, 0x9d16, 0x1118, 0x080c, 0x9ecd, 0x00f0, 0x6010, - 0x2068, 0x684c, 0xd0e4, 0x1110, 0x080c, 0x9ecd, 0x6837, 0x0103, - 0x6850, 0xd0b4, 0x0128, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0048, - 0xd0bc, 0x0118, 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, - 0x9f8e, 0x6847, 0x0000, 0x080c, 0x547a, 0x2c68, 0x080c, 0x864e, - 0x01c0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, - 0xbc8e, 0x210c, 0x6136, 0x2009, 0xbc8f, 0x210c, 0x613a, 0x6918, - 0x611a, 0x080c, 0xa0e3, 0x6950, 0x6152, 0x601f, 0x0001, 0x080c, - 0x6cff, 0x2d60, 0x080c, 0x86a4, 0x00de, 0x0005, 0x00f6, 0x2c78, - 0x080c, 0x5377, 0x00fe, 0x0598, 0x6030, 0xa08c, 0xff00, 0x810f, - 0xa186, 0x0035, 0x0130, 0xa186, 0x001e, 0x0118, 0xa186, 0x0039, - 0x1530, 0x00d6, 0x2c68, 0x080c, 0xa1c6, 0x1904, 0x9946, 0x080c, - 0x864e, 0x01d8, 0x6106, 0x6003, 0x0001, 0x601f, 0x0001, 0x6918, - 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, 0x6930, 0xa18c, 0x00ff, - 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, 0x6950, 0x6152, 0x080c, - 0xa0e3, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x2d60, 0x00f8, 0x00d6, - 0x6010, 0x2068, 0x080c, 0x9d16, 0x01c8, 0x6837, 0x0103, 0x6850, - 0xd0b4, 0x0128, 0xc0ec, 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc, - 0x0118, 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9f8e, - 0x6847, 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c, - 0x86a4, 0x0005, 0x0016, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, - 0x0140, 0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x080c, - 0x547a, 0x00de, 0x001e, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, - 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x86ef, 0x0030, 0x080c, - 0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0x0056, 0x0066, - 0x00d6, 0x00f6, 0x2029, 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, - 0x2009, 0x0100, 0x2130, 0x2069, 0xbc98, 0x831c, 0x2300, 0xad18, - 0x2009, 0x0020, 0xaf90, 0x001d, 0x080c, 0x99c9, 0xa6b2, 0x0020, - 0x7804, 0xa06d, 0x0110, 0x080c, 0x1624, 0x080c, 0x15fd, 0x0500, - 0x8528, 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, - 0x003d, 0x1228, 0x2608, 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, - 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, - 0x00fe, 0x852f, 0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, - 0x00fe, 0x852f, 0xa5ad, 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, - 0x0005, 0x00f6, 0x8dff, 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, - 0x0000, 0x080c, 0x547a, 0x2f68, 0x0cb8, 0x080c, 0x547a, 0x00fe, - 0x0005, 0x0156, 0xa184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, - 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x1f04, 0x99d0, 0x015e, - 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x601c, - 0xa084, 0x000f, 0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x0066, 0x2031, 0x0000, 0x601c, 0xa084, 0x000f, 0x001b, - 0x006e, 0x012e, 0x0005, 0x9a10, 0x9a10, 0x9a0b, 0x9a32, 0x99fe, - 0x9a0b, 0x9a32, 0x9a0b, 0x9a0b, 0x99fe, 0x9a0b, 0x080c, 0x151a, - 0x0036, 0x2019, 0x0010, 0x080c, 0xad9c, 0x601f, 0x0006, 0x6003, - 0x0007, 0x003e, 0x0005, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, - 0x00d6, 0x86ff, 0x11d8, 0x6010, 0x2068, 0x080c, 0x9d16, 0x01c0, - 0x6834, 0xa086, 0x0139, 0x1128, 0x684b, 0x0005, 0x6853, 0x0000, - 0x0028, 0xa00e, 0x2001, 0x0005, 0x080c, 0x554d, 0x080c, 0x9f8e, - 0x080c, 0x547a, 0x080c, 0x86a4, 0xa085, 0x0001, 0x00de, 0x0005, - 0xa006, 0x0ce0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x151a, 0x000b, - 0x0005, 0x9a49, 0x9a6a, 0x9a4b, 0x9a89, 0x9a67, 0x9a49, 0x9a0b, - 0x9a10, 0x9a10, 0x9a0b, 0x9a0b, 0x9a0b, 0x9a0b, 0x9a0b, 0x9a0b, - 0x9a0b, 0x080c, 0x151a, 0x86ff, 0x11b8, 0x601c, 0xa086, 0x0006, - 0x0198, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, - 0x9f8e, 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, - 0x080c, 0x6cff, 0x080c, 0x71e5, 0xa085, 0x0001, 0x0005, 0x080c, - 0x1952, 0x0c08, 0x00e6, 0x2071, 0xb8e1, 0x7024, 0xac06, 0x1110, - 0x080c, 0x7fe0, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, 0x1150, - 0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x81b7, 0x009e, - 0x008e, 0x0010, 0x080c, 0x7ed1, 0x00ee, 0x1928, 0x080c, 0x9a0b, - 0x0005, 0x0036, 0x00e6, 0x2071, 0xb8e1, 0x703c, 0xac06, 0x1140, - 0x2019, 0x0000, 0x080c, 0x806b, 0x00ee, 0x003e, 0x0804, 0x9a4b, - 0x080c, 0x82e4, 0x00ee, 0x003e, 0x1904, 0x9a4b, 0x080c, 0x9a0b, - 0x0005, 0x00c6, 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, - 0x9aba, 0x9b27, 0x9c75, 0x9ac5, 0x9ed9, 0x9aba, 0xad8e, 0xa20a, - 0x9b27, 0x9ab3, 0x9ce0, 0x080c, 0x151a, 0x080c, 0x9f14, 0x1110, - 0x080c, 0x8ca5, 0x0005, 0x080c, 0x7102, 0x080c, 0x71e5, 0x080c, - 0x86a4, 0x0005, 0x6017, 0x0001, 0x0005, 0x080c, 0x9d16, 0x0120, - 0x6010, 0xa080, 0x0019, 0x2c02, 0x6000, 0xa08a, 0x0010, 0x1a0c, - 0x151a, 0x000b, 0x0005, 0x9ae3, 0x9ae5, 0x9b05, 0x9b17, 0x9b24, - 0x9ae3, 0x9aba, 0x9aba, 0x9aba, 0x9b17, 0x9b17, 0x9ae3, 0x9ae3, - 0x9ae3, 0x9ae3, 0x9b21, 0x080c, 0x151a, 0x00e6, 0x6010, 0x2070, - 0x7050, 0xc0b5, 0x7052, 0x2071, 0xb8e1, 0x7024, 0xac06, 0x0190, - 0x080c, 0x7ed1, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, - 0x2001, 0xb8b7, 0x2004, 0x6016, 0x080c, 0x6cff, 0x080c, 0x71e5, - 0x00ee, 0x0005, 0x6017, 0x0001, 0x0cd8, 0x00d6, 0x6010, 0x2068, - 0x6850, 0xc0b5, 0x6852, 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, - 0x601f, 0x0002, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0005, 0x00d6, - 0x6017, 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, - 0x0005, 0x080c, 0x86a4, 0x0005, 0x080c, 0x1952, 0x08f0, 0x6000, - 0xa08a, 0x0010, 0x1a0c, 0x151a, 0x000b, 0x0005, 0x9b3e, 0x9ac2, - 0x9b40, 0x9b3e, 0x9b40, 0x9b40, 0x9abb, 0x9b3e, 0x9ab5, 0x9ab5, - 0x9b3e, 0x9b3e, 0x9b3e, 0x9b3e, 0x9b3e, 0x9b3e, 0x080c, 0x151a, - 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa08a, - 0x000c, 0x1a0c, 0x151a, 0x000b, 0x0005, 0x9b59, 0x9c1b, 0x9b5b, - 0x9b99, 0x9b5b, 0x9b99, 0x9b5b, 0x9b69, 0x9b59, 0x9b99, 0x9b59, - 0x9b85, 0x080c, 0x151a, 0x6004, 0xa08e, 0x0016, 0x05a8, 0xa08e, - 0x0004, 0x0590, 0xa08e, 0x0002, 0x0578, 0xa08e, 0x004b, 0x0904, - 0x9c17, 0x6004, 0x080c, 0x9f14, 0x0904, 0x9c34, 0xa08e, 0x0021, - 0x0904, 0x9c38, 0xa08e, 0x0022, 0x0904, 0x9c34, 0xa08e, 0x003d, - 0x0904, 0x9c38, 0xa08e, 0x0039, 0x0904, 0x9c3c, 0xa08e, 0x0035, - 0x0904, 0x9c3c, 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, 0x1150, - 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa086, - 0x0006, 0x0110, 0x080c, 0x2cd1, 0x080c, 0x8ca5, 0x080c, 0x9ed9, - 0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, 0x9c08, - 0xa186, 0x0002, 0x15d8, 0x2001, 0xb635, 0x2004, 0xd08c, 0x1198, - 0x080c, 0x5b41, 0x1180, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, - 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5b85, 0x080c, - 0x5a79, 0x0804, 0x9c5e, 0x6018, 0x2068, 0x2001, 0xb635, 0x2004, - 0xd0ac, 0x1904, 0x9c5e, 0x68a0, 0xd0bc, 0x1904, 0x9c5e, 0x6840, - 0xa084, 0x00ff, 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, 0x0000, - 0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, 0x864e, - 0x0128, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, 0x00ce, - 0x6004, 0xa08e, 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, 0x2004, - 0xa086, 0x007e, 0x1170, 0x2009, 0xb635, 0x2104, 0xc085, 0x200a, - 0x00e6, 0x2071, 0xb600, 0x080c, 0x4c28, 0x00ee, 0x080c, 0x8ca5, - 0x0020, 0x080c, 0x8ca5, 0x080c, 0x2cd1, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x080c, 0x2cf7, 0x012e, 0x00ee, 0x080c, 0x9ed9, 0x0005, - 0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003, 0x0001, 0x6007, 0x0002, - 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00de, 0x00ce, 0x0c80, 0x080c, - 0x2cf7, 0x0804, 0x9b94, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, - 0x0d38, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0904, - 0x9bde, 0x8001, 0x6842, 0x6003, 0x0001, 0x080c, 0x6d45, 0x080c, - 0x71e5, 0x00de, 0x00ce, 0x0898, 0x080c, 0x8ca5, 0x0804, 0x9b96, - 0x080c, 0x8cd3, 0x0804, 0x9b96, 0x00d6, 0x2c68, 0x6104, 0x080c, - 0xa1c6, 0x00de, 0x0118, 0x080c, 0x86a4, 0x00b8, 0x6004, 0x8007, - 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, - 0x000b, 0x601f, 0x0002, 0x6038, 0x600a, 0x2001, 0xb8b7, 0x2004, - 0x6016, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0005, 0x00de, 0x00ce, - 0x080c, 0x8ca5, 0x080c, 0x2cd1, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x080c, 0x2cf7, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, - 0x603f, 0x0000, 0x012e, 0x00ee, 0x0005, 0x6000, 0xa08a, 0x0010, - 0x1a0c, 0x151a, 0x000b, 0x0005, 0x9c8c, 0x9c8c, 0x9c8c, 0x9c8c, - 0x9c8c, 0x9c8c, 0x9c8c, 0x9c8c, 0x9c8c, 0x9aba, 0x9c8c, 0x9ac2, - 0x9c8e, 0x9ac2, 0x9c9b, 0x9c8c, 0x080c, 0x151a, 0x6004, 0xa086, - 0x008b, 0x0148, 0x6007, 0x008b, 0x6003, 0x000d, 0x080c, 0x6cff, - 0x080c, 0x71e5, 0x0005, 0x080c, 0x9ecd, 0x080c, 0x9d16, 0x0580, - 0x080c, 0x2cd1, 0x00d6, 0x080c, 0x9d16, 0x0168, 0x6010, 0x2068, - 0x6837, 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, - 0x6852, 0x080c, 0x547a, 0x2c68, 0x080c, 0x864e, 0x0150, 0x6818, - 0x601a, 0x080c, 0xa0e3, 0x00c6, 0x2d60, 0x080c, 0x9ed9, 0x00ce, - 0x0008, 0x2d60, 0x00de, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, - 0x0001, 0x6003, 0x0001, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x0078, - 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186, - 0x0035, 0x1118, 0x080c, 0x2cd1, 0x08b0, 0x080c, 0x9ed9, 0x0005, - 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x151a, 0x000b, 0x0005, 0x9cf7, - 0x9cf7, 0x9cf7, 0x9cf9, 0x9cf9, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, - 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x080c, - 0x151a, 0x080c, 0x82e4, 0x190c, 0x151a, 0x6110, 0x2168, 0x684b, - 0x0006, 0x080c, 0x547a, 0x080c, 0x86a4, 0x0005, 0xa284, 0x0007, - 0x1158, 0xa282, 0xbe00, 0x0240, 0x2001, 0xb617, 0x2004, 0xa202, - 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210, - 0xa294, 0xf000, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, - 0x0126, 0x2091, 0x8000, 0x2061, 0xbe00, 0x2071, 0xb600, 0x7348, - 0x7068, 0xa302, 0x12a8, 0x601c, 0xa206, 0x1160, 0x080c, 0xa06e, - 0x0148, 0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x00c6, 0x080c, - 0x86a4, 0x00ce, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0c38, - 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, - 0x0016, 0xa188, 0xb735, 0x210c, 0x81ff, 0x0128, 0x2061, 0xb9f5, - 0x611a, 0x080c, 0x2cd1, 0xa006, 0x0010, 0xa085, 0x0001, 0x001e, - 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, - 0x00c6, 0x080c, 0x864e, 0x005e, 0x0180, 0x6612, 0x651a, 0x080c, - 0xa0e3, 0x601f, 0x0003, 0x2009, 0x004b, 0x080c, 0x86d3, 0xa085, - 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6, - 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, 0x9f92, - 0x005e, 0x0550, 0x6013, 0x0000, 0x651a, 0x080c, 0xa0e3, 0x601f, - 0x0003, 0x0016, 0x00c6, 0x2560, 0x080c, 0x521c, 0x00ce, 0x080c, - 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2c08, 0x080c, - 0xaf3e, 0x007e, 0x001e, 0xd184, 0x0128, 0x080c, 0x86a4, 0xa085, - 0x0001, 0x0030, 0x2009, 0x004c, 0x080c, 0x86d3, 0xa085, 0x0001, - 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00f6, 0x00c6, - 0x0046, 0x00c6, 0x080c, 0x864e, 0x2c78, 0x00ce, 0x0180, 0x7e12, - 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x080c, 0x9e0c, - 0x2f60, 0x2009, 0x004d, 0x080c, 0x86d3, 0xa085, 0x0001, 0x004e, - 0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c, - 0x864e, 0x2c78, 0x00ce, 0x0178, 0x7e12, 0x2c00, 0x781a, 0x781f, - 0x0003, 0x2021, 0x0005, 0x0481, 0x2f60, 0x2009, 0x004e, 0x080c, - 0x86d3, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, - 0x00c6, 0x0046, 0x00c6, 0x080c, 0x864e, 0x2c78, 0x00ce, 0x01c0, - 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0004, 0x00a1, - 0x2001, 0xb8a0, 0x2004, 0xd0fc, 0x0120, 0x2f60, 0x080c, 0x86a4, - 0x0028, 0x2f60, 0x2009, 0x0052, 0x080c, 0x86d3, 0xa085, 0x0001, - 0x004e, 0x00ce, 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, - 0x8000, 0x080c, 0x51be, 0x0118, 0x2001, 0x9e11, 0x0028, 0x080c, - 0x518e, 0x0158, 0x2001, 0x9e17, 0x0006, 0xa00e, 0x2400, 0x080c, - 0x554d, 0x080c, 0x547a, 0x000e, 0x0807, 0x2418, 0x080c, 0x70a1, - 0x62a0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, - 0x6e80, 0x008e, 0x080c, 0x6d74, 0x2f08, 0x2648, 0x080c, 0xaf3e, - 0x613c, 0x81ff, 0x090c, 0x6f35, 0x080c, 0x71e5, 0x012e, 0x007e, - 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, - 0x864e, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xa0e3, 0x601f, - 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, 0x080c, 0x86d3, 0xa085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x080c, 0x864e, 0x001e, 0x0188, 0x660a, - 0x611a, 0x080c, 0xa0e3, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, - 0x0021, 0x080c, 0x86d3, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, - 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, - 0x864e, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xa0e3, 0x601f, - 0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x080c, 0x86d3, 0xa085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x00c6, 0x080c, 0x9f92, 0x001e, 0x0180, 0x611a, - 0x080c, 0xa0e3, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, - 0x080c, 0x86d3, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, - 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x864e, - 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xa0e3, 0x601f, 0x0001, - 0x2d00, 0x6012, 0x2009, 0x0044, 0x080c, 0x86d3, 0xa085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x0026, 0x00d6, 0x6218, - 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, - 0x0005, 0x0006, 0x6000, 0xa086, 0x0000, 0x0190, 0x6013, 0x0000, - 0x601f, 0x0007, 0x2001, 0xb8b6, 0x2004, 0x0006, 0xa082, 0x0051, - 0x000e, 0x0208, 0x8004, 0x6016, 0x080c, 0xb3f6, 0x603f, 0x0000, - 0x000e, 0x0005, 0x0066, 0x00c6, 0x00d6, 0x2031, 0xb653, 0x2634, - 0xd6e4, 0x0128, 0x6618, 0x2660, 0x6e48, 0x080c, 0x5147, 0x00de, - 0x00ce, 0x006e, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0002, - 0x0140, 0xa08e, 0x0003, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa085, - 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d, - 0x0148, 0x6834, 0xa086, 0x0139, 0x0138, 0x6838, 0xd0fc, 0x0110, - 0xa006, 0x0010, 0xa085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x864e, 0x001e, 0x0190, - 0x611a, 0x080c, 0xa0e3, 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, - 0x2cd1, 0x2009, 0x0028, 0x080c, 0x86d3, 0xa085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0xa006, 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, - 0xb621, 0x2204, 0xa086, 0x0074, 0x1148, 0x080c, 0x9024, 0x6003, - 0x0001, 0x6007, 0x0029, 0x080c, 0x6d45, 0x0020, 0x080c, 0x8ca5, - 0x080c, 0x86a4, 0x0005, 0xa186, 0x0016, 0x1128, 0x2001, 0x0004, - 0x080c, 0x4f6f, 0x00e8, 0xa186, 0x0015, 0x11e8, 0x2011, 0xb621, - 0x2204, 0xa086, 0x0014, 0x11b8, 0x00d6, 0x6018, 0x2068, 0x080c, - 0x50bd, 0x00de, 0x080c, 0x90dd, 0x1170, 0x00d6, 0x6018, 0x2068, - 0x6890, 0x00de, 0xa005, 0x0138, 0x2001, 0x0006, 0x080c, 0x4f6f, - 0x080c, 0x882c, 0x0020, 0x080c, 0x8ca5, 0x080c, 0x86a4, 0x0005, - 0x6848, 0xa086, 0x0005, 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, - 0x6852, 0x0005, 0x00e6, 0x0126, 0x2071, 0xb600, 0x2091, 0x8000, - 0x7548, 0xa582, 0x0001, 0x0608, 0x704c, 0x2060, 0x6000, 0xa086, - 0x0000, 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, - 0x2061, 0xbe00, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, - 0x0018, 0x705c, 0xa502, 0x1230, 0x754e, 0xa085, 0x0001, 0x012e, - 0x00ee, 0x0005, 0x704f, 0xbe00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, - 0x2071, 0xbc8c, 0x7014, 0xd0e4, 0x0150, 0x6013, 0x0000, 0x6003, - 0x0001, 0x6007, 0x0050, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00ee, - 0x0005, 0x00c6, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, 0x0120, - 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, 0x9aba, 0x9fe9, - 0x9fec, 0x9fef, 0xb1e3, 0xb1fe, 0xb201, 0x9aba, 0x9aba, 0x080c, - 0x151a, 0xe000, 0xe000, 0x0005, 0xe000, 0xe000, 0x0005, 0x0009, - 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x0538, 0x080c, 0x864e, - 0x1128, 0x2001, 0xb8b8, 0x2004, 0x783e, 0x00f8, 0x7818, 0x601a, - 0x080c, 0xa0e3, 0x781c, 0xa086, 0x0003, 0x0128, 0x7808, 0x6036, - 0x2f00, 0x603a, 0x0020, 0x7808, 0x603a, 0x2f00, 0x6036, 0x602a, - 0x601f, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x7950, 0x6152, - 0x080c, 0x6cff, 0x080c, 0x71e5, 0x2f60, 0x00fe, 0x0005, 0x0016, - 0x00f6, 0x682c, 0x6032, 0xa08e, 0x0001, 0x0138, 0xa086, 0x0005, - 0x0140, 0xa006, 0x602a, 0x602e, 0x00a0, 0x6820, 0xc0f4, 0xc0d5, - 0x6822, 0x6810, 0x2078, 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, - 0xa103, 0x1e78, 0x6834, 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, - 0x602e, 0x2d00, 0x6036, 0x6808, 0x603a, 0x6918, 0x611a, 0x6950, - 0x6152, 0x601f, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x080c, - 0x6cff, 0x6803, 0x0002, 0x00fe, 0x001e, 0x0005, 0x00f6, 0x2c78, - 0x080c, 0x5377, 0x1118, 0xa085, 0x0001, 0x0070, 0x6020, 0xd0f4, - 0x1150, 0xc0f5, 0x6022, 0x6010, 0x2078, 0x7828, 0x603a, 0x782c, - 0x6036, 0x080c, 0x1952, 0xa006, 0x00fe, 0x0005, 0x0006, 0x0016, - 0x6004, 0xa08e, 0x0034, 0x01b8, 0xa08e, 0x0035, 0x01a0, 0xa08e, - 0x0036, 0x0188, 0xa08e, 0x0037, 0x0170, 0xa08e, 0x0038, 0x0158, - 0xa08e, 0x0039, 0x0140, 0xa08e, 0x003a, 0x0128, 0xa08e, 0x003b, - 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00e6, 0x2001, 0xb8b2, 0x200c, 0x8000, 0x2014, - 0x2001, 0x0032, 0x080c, 0x6bb2, 0x2001, 0xb8b6, 0x82ff, 0x1110, - 0x2011, 0x0014, 0x2202, 0x2001, 0xb8b4, 0x200c, 0x8000, 0x2014, - 0x2071, 0xb88e, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x6bb2, - 0x2001, 0xb8b7, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2009, - 0xb8b8, 0xa280, 0x000a, 0x200a, 0x080c, 0x539c, 0x00ee, 0x003e, - 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x00e6, 0x2001, 0xb8b6, - 0x2003, 0x0028, 0x2001, 0xb8b7, 0x2003, 0x0014, 0x2071, 0xb88e, - 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0xb8b8, 0x2003, 0x001e, - 0x00ee, 0x000e, 0x0005, 0x00d6, 0x6054, 0xa06d, 0x0110, 0x080c, - 0x1614, 0x00de, 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x00c6, 0x080c, 0x864e, 0x001e, 0x0178, 0x611a, 0x0ca1, 0x601f, - 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x080c, 0x86d3, 0xa085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, - 0x00f6, 0x2071, 0xb600, 0xa186, 0x0015, 0x1500, 0x7084, 0xa086, - 0x0018, 0x11e0, 0x6010, 0x2068, 0x6a3c, 0xd2e4, 0x1160, 0x2c78, - 0x080c, 0x73a3, 0x01d8, 0x7070, 0x6a50, 0xa206, 0x1160, 0x7074, - 0x6a54, 0xa206, 0x1140, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, - 0x0000, 0x080c, 0x2d16, 0x080c, 0x882c, 0x0020, 0x080c, 0x8ca5, - 0x080c, 0x86a4, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a54, - 0xa206, 0x0d48, 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, - 0x080c, 0x864e, 0x001e, 0x0180, 0x611a, 0x080c, 0xa0e3, 0x601f, - 0x0001, 0x2d00, 0x6012, 0x2009, 0x0043, 0x080c, 0x86d3, 0xa085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6, - 0x00f6, 0x2071, 0xb600, 0xa186, 0x0015, 0x11c0, 0x7084, 0xa086, - 0x0004, 0x11a0, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x080c, 0x73a3, - 0x01a8, 0x7070, 0x6a08, 0xa206, 0x1130, 0x7074, 0x6a0c, 0xa206, - 0x1110, 0x080c, 0x2cd1, 0x080c, 0x882c, 0x0020, 0x080c, 0x8ca5, - 0x080c, 0x86a4, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a0c, - 0xa206, 0x0d78, 0x0c80, 0x0016, 0x0026, 0x684c, 0xd0ac, 0x0178, - 0x6914, 0x6a10, 0x2100, 0xa205, 0x0150, 0x6860, 0xa106, 0x1118, - 0x685c, 0xa206, 0x0120, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x002e, - 0x001e, 0x0005, 0x00d6, 0x0036, 0x6310, 0x2368, 0x684a, 0x6952, - 0xa29e, 0x4000, 0x11a0, 0x00c6, 0x6318, 0x2360, 0x2009, 0x0000, - 0x6838, 0xd0f4, 0x1140, 0x080c, 0x52bc, 0x1108, 0xc185, 0x6000, - 0xd0bc, 0x0108, 0xc18d, 0x6a66, 0x696a, 0x00ce, 0x0080, 0x6a66, - 0x3918, 0xa398, 0x0006, 0x231c, 0x686b, 0x0004, 0x6b72, 0x00c6, - 0x6318, 0x2360, 0x6004, 0xa084, 0x00ff, 0x686e, 0x00ce, 0x080c, - 0x547a, 0x6013, 0x0000, 0x003e, 0x00de, 0x0005, 0x00c6, 0x0026, - 0x0016, 0xa186, 0x0035, 0x0110, 0x6a34, 0x0008, 0x6a28, 0x080c, - 0x9d06, 0x01f0, 0x2260, 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, - 0x0006, 0x1190, 0x6834, 0xa206, 0x0140, 0x6838, 0xa206, 0x1160, - 0x6108, 0x6834, 0xa106, 0x1140, 0x0020, 0x6008, 0x6938, 0xa106, - 0x1118, 0x6018, 0x6918, 0xa106, 0x001e, 0x002e, 0x00ce, 0x0005, - 0xa085, 0x0001, 0x0cc8, 0x6944, 0xd1cc, 0x0198, 0xa18c, 0x00ff, - 0xa18e, 0x0002, 0x1170, 0xad88, 0x001e, 0x210c, 0xa18c, 0x0f00, - 0x810f, 0xa18e, 0x0001, 0x1128, 0x6810, 0x6914, 0xa115, 0x190c, - 0x953f, 0x0005, 0x080c, 0x86a4, 0x0804, 0x71e5, 0x0066, 0x6000, - 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0xa227, - 0xa702, 0xa828, 0xa227, 0xa227, 0xa227, 0xa227, 0xa227, 0xa25f, - 0xa8ac, 0xa227, 0xa227, 0xa227, 0xa227, 0xa227, 0xa227, 0x080c, - 0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, - 0x006e, 0x0005, 0xa242, 0xad33, 0xa242, 0xa242, 0xa242, 0xa242, - 0xa242, 0xa242, 0xacf5, 0xad7b, 0xa242, 0xb328, 0xb358, 0xb328, - 0xb358, 0xa242, 0x080c, 0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010, - 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0xa25d, 0xa9fc, 0xaac9, - 0xaaf6, 0xab7a, 0xa25d, 0xac67, 0xac12, 0xa8b8, 0xaccb, 0xace0, - 0xa25d, 0xa25d, 0xa25d, 0xa25d, 0xa25d, 0x080c, 0x151a, 0xa1b2, - 0x0080, 0x1a0c, 0x151a, 0x2100, 0xa1b2, 0x0040, 0x1a04, 0xa676, - 0x0002, 0xa2a9, 0xa474, 0xa2a9, 0xa2a9, 0xa2a9, 0xa47b, 0xa2a9, - 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, - 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, - 0xa2ab, 0xa309, 0xa318, 0xa366, 0xa384, 0xa402, 0xa461, 0xa2a9, - 0xa2a9, 0xa47e, 0xa2a9, 0xa2a9, 0xa491, 0xa49c, 0xa2a9, 0xa2a9, - 0xa2a9, 0xa2a9, 0xa2a9, 0xa527, 0xa2a9, 0xa2a9, 0xa53a, 0xa2a9, - 0xa2a9, 0xa4f2, 0xa2a9, 0xa2a9, 0xa2a9, 0xa552, 0xa2a9, 0xa2a9, - 0xa2a9, 0xa5cc, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, - 0xa63d, 0x080c, 0x151a, 0x080c, 0x537b, 0x1150, 0x2001, 0xb635, - 0x2004, 0xd0cc, 0x1128, 0xa084, 0x0009, 0xa086, 0x0008, 0x1140, - 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804, 0xa46f, - 0x080c, 0x536b, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, - 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x6e67, 0x0076, - 0x2039, 0x0000, 0x080c, 0x6d74, 0x2c08, 0x080c, 0xaf3e, 0x007e, - 0x001e, 0x2e60, 0x080c, 0x521c, 0x001e, 0x002e, 0x003e, 0x00ce, - 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x502a, 0x00ce, 0xa6b0, - 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278, 0x080c, - 0xae82, 0x1904, 0xa360, 0x080c, 0xae22, 0x1120, 0x6007, 0x0008, - 0x0804, 0xa46f, 0x6007, 0x0009, 0x0804, 0xa46f, 0x080c, 0xb037, - 0x0128, 0x080c, 0xae82, 0x0d78, 0x0804, 0xa360, 0x6013, 0x1900, - 0x0c88, 0x080c, 0x2df4, 0x1904, 0xa673, 0x6106, 0x080c, 0xaddc, - 0x6007, 0x0006, 0x0804, 0xa46f, 0x6007, 0x0007, 0x0804, 0xa46f, - 0x080c, 0xb38c, 0x1904, 0xa673, 0x080c, 0x2df4, 0x1904, 0xa673, - 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006, - 0x1220, 0x2001, 0x0001, 0x080c, 0x4f5d, 0xa6b4, 0xff00, 0x8637, - 0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, 0xa6b4, - 0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, 0xa686, - 0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xaee0, 0x11a0, 0xa686, - 0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, - 0x0000, 0x080c, 0x2d16, 0x002e, 0x080c, 0x50bd, 0x6007, 0x000a, - 0x00de, 0x0804, 0xa46f, 0x6007, 0x000b, 0x00de, 0x0804, 0xa46f, - 0x080c, 0x2cd1, 0x6007, 0x0001, 0x0804, 0xa46f, 0x080c, 0xb38c, - 0x1904, 0xa673, 0x080c, 0x2df4, 0x1904, 0xa673, 0x6618, 0x00d6, - 0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d50, 0x0026, 0x6218, - 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2d16, 0x002e, - 0x6007, 0x000c, 0x0804, 0xa46f, 0x080c, 0x537b, 0x1140, 0x2001, - 0xb635, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, - 0xa2b8, 0x080c, 0x536b, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, - 0x00ff, 0xa082, 0x0006, 0x06e8, 0x1138, 0x0026, 0x2001, 0x0006, - 0x080c, 0x4f9c, 0x002e, 0x0050, 0xa6b4, 0xff00, 0x8637, 0xa686, - 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0xa360, 0x080c, 0xaeed, - 0x1120, 0x6007, 0x000e, 0x0804, 0xa46f, 0x0046, 0x6418, 0xa4a0, - 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x2cd1, - 0x004e, 0x0016, 0xa006, 0x2009, 0xb653, 0x210c, 0xd1a4, 0x0158, - 0x2009, 0x0029, 0x080c, 0xb1a4, 0x6018, 0x00d6, 0x2068, 0x6800, - 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804, - 0xa46f, 0x2001, 0x0001, 0x080c, 0x4f5d, 0x0156, 0x0016, 0x0026, - 0x0036, 0x20a9, 0x0004, 0x2019, 0xb605, 0x2011, 0xbc90, 0x080c, - 0x9166, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0168, 0xa6b4, - 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0xa360, 0xa682, 0x0007, - 0x0a04, 0xa3ae, 0x0804, 0xa360, 0x6013, 0x1900, 0x6007, 0x0009, - 0x0804, 0xa46f, 0x080c, 0x537b, 0x1140, 0x2001, 0xb635, 0x2004, - 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, 0xa2b8, 0x080c, - 0x536b, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, - 0x0006, 0x06b8, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0120, - 0xa686, 0x0006, 0x1904, 0xa360, 0x080c, 0xaf15, 0x1138, 0x080c, - 0xae22, 0x1120, 0x6007, 0x0010, 0x0804, 0xa46f, 0x0046, 0x6418, - 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, - 0x2cd1, 0x004e, 0x0016, 0xa006, 0x2009, 0xb653, 0x210c, 0xd1a4, - 0x0158, 0x2009, 0x0029, 0x080c, 0xb1a4, 0x6018, 0x00d6, 0x2068, - 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, - 0x00f0, 0x080c, 0xb037, 0x0140, 0xa6b4, 0xff00, 0x8637, 0xa686, - 0x0006, 0x0950, 0x0804, 0xa360, 0x6013, 0x1900, 0x6007, 0x0009, - 0x0070, 0x080c, 0x2df4, 0x1904, 0xa673, 0x080c, 0xb38c, 0x1904, - 0xa673, 0x080c, 0xa69b, 0x1904, 0xa360, 0x6007, 0x0012, 0x6003, - 0x0001, 0x080c, 0x6d45, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x6d45, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, 0xb38c, - 0x1904, 0xa673, 0x080c, 0x2df4, 0x1904, 0xa673, 0x080c, 0xa69b, - 0x1904, 0xa360, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x6d45, - 0x0005, 0x080c, 0x2df4, 0x1904, 0xa673, 0x6007, 0x0023, 0x6003, - 0x0001, 0x080c, 0x6d45, 0x0005, 0x080c, 0xb38c, 0x1904, 0xa673, - 0x080c, 0x2df4, 0x1904, 0xa673, 0x080c, 0xa69b, 0x1904, 0xa360, - 0x0016, 0x0026, 0x2011, 0xbc91, 0x2214, 0xa286, 0xffff, 0x0190, - 0x2c08, 0x080c, 0x9d06, 0x01e0, 0x2260, 0x2011, 0xbc90, 0x2214, - 0x6008, 0xa206, 0x11a8, 0x6018, 0xa190, 0x0006, 0x2214, 0xa206, - 0x01e8, 0x0070, 0x2011, 0xbc90, 0x2214, 0x2c08, 0xa006, 0x080c, - 0xb176, 0x11a0, 0x2011, 0xbc91, 0x2214, 0xa286, 0xffff, 0x01c0, - 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xbc89, 0x2214, - 0xa296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x601c, 0xa086, - 0x0007, 0x1d70, 0x6004, 0xa086, 0x0024, 0x1110, 0x080c, 0x86a4, - 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x6d45, 0x002e, - 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x4f5d, 0x0156, 0x0016, - 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xb605, 0x2011, 0xbc96, - 0x080c, 0x9166, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, - 0x0031, 0x0804, 0xa46f, 0x080c, 0x8e82, 0x080c, 0x5b41, 0x11b0, - 0x0006, 0x0026, 0x0036, 0x080c, 0x5b5d, 0x1158, 0x2001, 0xb89f, - 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0x080c, 0x5a79, - 0x0010, 0x080c, 0x5b18, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, - 0x2df4, 0x1904, 0xa673, 0x080c, 0xa69b, 0x1904, 0xa360, 0x6106, - 0x080c, 0xa6b7, 0x6007, 0x002b, 0x0804, 0xa46f, 0x6007, 0x002c, - 0x0804, 0xa46f, 0x080c, 0xb38c, 0x1904, 0xa673, 0x080c, 0x2df4, - 0x1904, 0xa673, 0x080c, 0xa69b, 0x1904, 0xa360, 0x6106, 0x080c, - 0xa6bb, 0x1120, 0x6007, 0x002e, 0x0804, 0xa46f, 0x6007, 0x002f, - 0x0804, 0xa46f, 0x080c, 0x2df4, 0x1904, 0xa673, 0x00e6, 0x00d6, - 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086, - 0x0006, 0x0158, 0xa184, 0xff00, 0x8007, 0xa086, 0x0006, 0x0128, - 0x00ce, 0x00de, 0x00ee, 0x0804, 0xa474, 0x2001, 0xb672, 0x2004, - 0xd0e4, 0x0904, 0xa5c9, 0x2071, 0xbc8c, 0x7010, 0x6036, 0x7014, - 0x603a, 0x7108, 0x720c, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x0140, - 0x6018, 0x2068, 0x6810, 0xa106, 0x1118, 0x6814, 0xa206, 0x01f8, - 0x2001, 0xb653, 0x2004, 0xd0ac, 0x1590, 0x2069, 0xb600, 0x6874, - 0xa206, 0x1568, 0x6870, 0xa106, 0x1550, 0x7210, 0x080c, 0x9d06, - 0x0558, 0x080c, 0xb210, 0x0540, 0x622a, 0x6007, 0x0036, 0x6003, - 0x0001, 0x080c, 0x6cff, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, - 0xa286, 0xffff, 0x0150, 0x080c, 0x9d06, 0x01b0, 0xa280, 0x0002, - 0x2004, 0x7110, 0xa106, 0x1180, 0x0c08, 0x7210, 0x2c08, 0xa085, - 0x0001, 0x080c, 0xb176, 0x2c10, 0x2160, 0x0130, 0x08b8, 0x6007, - 0x0037, 0x6013, 0x1500, 0x08d8, 0x6007, 0x0037, 0x6013, 0x1700, - 0x08b0, 0x6007, 0x0012, 0x0898, 0x080c, 0x2df4, 0x1904, 0xa673, - 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, 0xff00, 0x8007, 0xa086, - 0x0006, 0x1904, 0xa474, 0x00e6, 0x00d6, 0x00c6, 0x2001, 0xb672, - 0x2004, 0xd0e4, 0x0904, 0xa635, 0x2069, 0xb600, 0x2071, 0xbc8c, - 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, 0xffff, 0x1150, 0x7208, - 0x00c6, 0x2c08, 0xa085, 0x0001, 0x080c, 0xb176, 0x2c10, 0x00ce, - 0x0588, 0x080c, 0x9d06, 0x0570, 0x00c6, 0x0026, 0x2260, 0x080c, - 0x99d9, 0x002e, 0x00ce, 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186, - 0x0001, 0x0158, 0xa186, 0x0005, 0x0118, 0xa186, 0x0007, 0x1178, - 0xa280, 0x0004, 0x2004, 0xa005, 0x0150, 0x0056, 0x7510, 0x7614, - 0x080c, 0xb227, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, - 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, - 0x6cff, 0x0c88, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x1700, - 0x6003, 0x0001, 0x080c, 0x6cff, 0x0c30, 0x6007, 0x003b, 0x602b, - 0x000b, 0x6013, 0x0000, 0x0804, 0xa59f, 0x00e6, 0x0026, 0x080c, - 0x537b, 0x0558, 0x080c, 0x536b, 0x080c, 0xb407, 0x1520, 0x2071, - 0xb600, 0x70d4, 0xc085, 0x70d6, 0x00f6, 0x2079, 0x0100, 0x72a0, - 0xa284, 0x00ff, 0x7072, 0x78e6, 0xa284, 0xff00, 0x7274, 0xa205, - 0x7076, 0x78ea, 0x00fe, 0x70df, 0x0000, 0x2001, 0xb653, 0x2004, - 0xd0a4, 0x0120, 0x2011, 0xb8fa, 0x2013, 0x07d0, 0xd0ac, 0x1128, - 0x080c, 0x2aed, 0x0010, 0x080c, 0xb433, 0x002e, 0x00ee, 0x080c, - 0x86a4, 0x0804, 0xa473, 0x080c, 0x86a4, 0x0005, 0x2600, 0x0002, - 0xa681, 0xa681, 0xa681, 0xa681, 0xa681, 0xa683, 0xa681, 0xa681, - 0xa681, 0x080c, 0x151a, 0x080c, 0xb38c, 0x1d68, 0x080c, 0x2df4, - 0x1d50, 0x0089, 0x1138, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, - 0x6d45, 0x0005, 0x080c, 0x2cd1, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x6d45, 0x0005, 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, - 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0xa686, 0x0004, - 0x0158, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0128, 0xa686, - 0x0004, 0x0110, 0xa085, 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, - 0x0449, 0x00de, 0x0005, 0x00d6, 0x0491, 0x11f0, 0x680c, 0xa08c, - 0xff00, 0x6820, 0xa084, 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, - 0xd1e4, 0x0118, 0x2009, 0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920, - 0xa18c, 0x00ff, 0x6824, 0x080c, 0x2852, 0x1130, 0x2110, 0x2009, - 0x0000, 0x080c, 0x2d16, 0x0018, 0xa085, 0x0001, 0x0008, 0xa006, - 0x00de, 0x0005, 0x2069, 0xbc8d, 0x6800, 0xa082, 0x0010, 0x1228, - 0x6013, 0x0000, 0xa085, 0x0001, 0x0008, 0xa006, 0x0005, 0x6013, - 0x0000, 0x2069, 0xbc8c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, - 0x1140, 0x6800, 0xa084, 0x00ff, 0xa08e, 0x0014, 0x0110, 0xa08e, - 0x0010, 0x0005, 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x151a, 0xa1b6, - 0x0013, 0x1130, 0x2008, 0xa1b2, 0x0040, 0x1a04, 0xa802, 0x0092, - 0xa1b6, 0x0027, 0x0120, 0xa1b6, 0x0014, 0x190c, 0x151a, 0x2001, - 0x0007, 0x080c, 0x4f9c, 0x080c, 0x7102, 0x080c, 0x9ed9, 0x080c, - 0x71e5, 0x0005, 0xa762, 0xa764, 0xa762, 0xa762, 0xa762, 0xa764, - 0xa776, 0xa7fb, 0xa7c6, 0xa7fb, 0xa7d7, 0xa7fb, 0xa776, 0xa7fb, - 0xa7f3, 0xa7fb, 0xa7f3, 0xa7fb, 0xa7fb, 0xa762, 0xa762, 0xa762, - 0xa762, 0xa762, 0xa762, 0xa762, 0xa762, 0xa762, 0xa762, 0xa762, - 0xa764, 0xa762, 0xa7fb, 0xa762, 0xa762, 0xa7fb, 0xa762, 0xa7f8, - 0xa7fb, 0xa762, 0xa762, 0xa762, 0xa762, 0xa7fb, 0xa7fb, 0xa762, - 0xa7fb, 0xa7fb, 0xa762, 0xa770, 0xa762, 0xa762, 0xa762, 0xa762, - 0xa7f7, 0xa7fb, 0xa762, 0xa762, 0xa7fb, 0xa7fb, 0xa762, 0xa762, - 0xa762, 0xa762, 0x080c, 0x151a, 0x080c, 0x7102, 0x2001, 0xb8b6, - 0x2004, 0x6016, 0x6003, 0x0002, 0x080c, 0x71e5, 0x0804, 0xa801, - 0x2001, 0x0000, 0x080c, 0x4f5d, 0x0804, 0xa7fb, 0x00f6, 0x2079, - 0xb652, 0x7804, 0x00fe, 0xd0ac, 0x1904, 0xa7fb, 0x2001, 0x0000, - 0x080c, 0x4f5d, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, - 0x1140, 0x00f6, 0x2079, 0xb600, 0x7898, 0x8000, 0x789a, 0x00fe, - 0x00e0, 0x00c6, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x1140, 0x6010, - 0xa005, 0x0128, 0x00ce, 0x080c, 0x3f85, 0x0804, 0xa7fb, 0x00ce, - 0x2001, 0xb600, 0x2004, 0xa086, 0x0002, 0x1138, 0x00f6, 0x2079, - 0xb600, 0x7898, 0x8000, 0x789a, 0x00fe, 0x2001, 0x0002, 0x080c, - 0x4f6f, 0x080c, 0x7102, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00c6, 0x6118, 0x2160, - 0x2009, 0x0001, 0x080c, 0x6a1a, 0x00ce, 0x04d8, 0x6618, 0x00d6, - 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, - 0x0550, 0xa686, 0x0004, 0x0538, 0x2001, 0x0004, 0x0410, 0x2001, - 0xb600, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, 0x3f85, 0x2001, - 0x0006, 0x04a1, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, - 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, 0x0006, 0x0048, - 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0401, 0x0020, 0x0018, - 0x0010, 0x080c, 0x4f9c, 0x080c, 0x7102, 0x080c, 0x86a4, 0x080c, - 0x71e5, 0x0005, 0x2600, 0x0002, 0xa80d, 0xa80d, 0xa80d, 0xa80d, - 0xa80d, 0xa80f, 0xa80d, 0xa80d, 0xa80d, 0x080c, 0x151a, 0x080c, - 0x7102, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, 0x0016, 0x00d6, - 0x6118, 0x2168, 0x6900, 0xd184, 0x0140, 0x080c, 0x4f6f, 0x2001, - 0x0000, 0x080c, 0x4f5d, 0x080c, 0x2cf7, 0x00de, 0x001e, 0x0005, - 0x00d6, 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, - 0xa0b2, 0x000c, 0x1a0c, 0x151a, 0xa1b6, 0x0015, 0x1110, 0x003b, - 0x0028, 0xa1b6, 0x0016, 0x190c, 0x151a, 0x006b, 0x0005, 0x8d6b, - 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0xa898, 0xa857, 0x8d6b, - 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, - 0x8d6b, 0xa898, 0xa89f, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x00f6, - 0x2079, 0xb652, 0x7804, 0xd0ac, 0x11e0, 0x6018, 0xa07d, 0x01c8, - 0x7800, 0xd0f4, 0x1118, 0x7810, 0xa005, 0x1198, 0x2001, 0x0000, - 0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x601f, 0x0001, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6d45, 0x080c, 0x71e5, - 0x00e8, 0x2011, 0xbc83, 0x2204, 0x8211, 0x220c, 0x080c, 0x2852, - 0x11a8, 0x00c6, 0x080c, 0x501b, 0x0120, 0x00ce, 0x080c, 0x86a4, - 0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, 0x4c7e, 0x000e, - 0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0x86a4, 0x00fe, 0x0005, - 0x6604, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x86a4, 0x0005, 0x080c, - 0x9021, 0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x6d45, - 0x0010, 0x080c, 0x86a4, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, - 0x151a, 0x080c, 0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, - 0xa182, 0x0040, 0x0002, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8d0, - 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, - 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0x080c, 0x151a, - 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6218, 0xa280, - 0x002b, 0x2004, 0xa005, 0x0120, 0x2021, 0x0000, 0x080c, 0xb3d8, - 0x6106, 0x2071, 0xbc80, 0x7444, 0xa4a4, 0xff00, 0x0904, 0xa934, - 0xa486, 0x2000, 0x1130, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, - 0x6b8c, 0x080c, 0x15fd, 0x090c, 0x151a, 0x6003, 0x0007, 0x2d00, - 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, - 0x685e, 0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, - 0x694a, 0x0016, 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, 0x6853, - 0x0000, 0x6857, 0x0036, 0x080c, 0x547a, 0x001e, 0xa486, 0x2000, - 0x1130, 0x2019, 0x0017, 0x080c, 0xb121, 0x0804, 0xa991, 0xa486, - 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xb0d3, 0x0804, 0xa991, - 0xa486, 0x0200, 0x1110, 0x080c, 0xb0b8, 0xa486, 0x1000, 0x1110, - 0x080c, 0xb106, 0x0804, 0xa991, 0x2069, 0xb975, 0x6a00, 0xd284, - 0x0904, 0xa9f8, 0xa284, 0x0300, 0x1904, 0xa9f1, 0x6804, 0xa005, - 0x0904, 0xa9d9, 0x2d78, 0x6003, 0x0007, 0x080c, 0x15e4, 0x0904, - 0xa998, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6013, - 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, - 0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, - 0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, 0x6992, - 0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, - 0x0002, 0x1118, 0x684f, 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, - 0x684f, 0x0080, 0x0010, 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, - 0xbc90, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, - 0x1f04, 0xa983, 0x200c, 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, - 0x547a, 0x002e, 0x004e, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, - 0x2001, 0xb60e, 0x2004, 0xd084, 0x0120, 0x080c, 0x15fd, 0x1904, - 0xa949, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, - 0x6cff, 0x080c, 0x71e5, 0x0c28, 0x2069, 0xbc92, 0x2d04, 0xa084, - 0xff00, 0xa086, 0x1200, 0x11a8, 0x2069, 0xbc80, 0x686c, 0xa084, - 0x00ff, 0x0016, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x001e, - 0x6003, 0x0001, 0x6007, 0x0043, 0x080c, 0x6cff, 0x080c, 0x71e5, - 0x0840, 0x6868, 0x602a, 0x686c, 0x602e, 0x6013, 0x0200, 0x6003, - 0x0001, 0x6007, 0x0041, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0804, - 0xa991, 0x2001, 0xb60d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, - 0x080c, 0x3f13, 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, - 0x0001, 0x6007, 0x0041, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0804, - 0xa991, 0x6013, 0x0500, 0x0c98, 0x6013, 0x0600, 0x0804, 0xa9ac, - 0x6013, 0x0200, 0x0804, 0xa9ac, 0xa186, 0x0013, 0x1170, 0x6004, - 0xa08a, 0x0040, 0x0a0c, 0x151a, 0xa08a, 0x0053, 0x1a0c, 0x151a, - 0xa082, 0x0040, 0x2008, 0x0804, 0xaa86, 0xa186, 0x0051, 0x0138, - 0xa186, 0x0047, 0x11d8, 0x6004, 0xa086, 0x0041, 0x0518, 0x2001, - 0x0109, 0x2004, 0xd084, 0x01f0, 0x0126, 0x2091, 0x2800, 0x0006, - 0x0016, 0x0026, 0x080c, 0x6be6, 0x002e, 0x001e, 0x000e, 0x012e, - 0x6000, 0xa086, 0x0002, 0x1170, 0x0804, 0xaac9, 0xa186, 0x0027, - 0x0120, 0xa186, 0x0014, 0x190c, 0x151a, 0x6004, 0xa082, 0x0040, - 0x2008, 0x001a, 0x080c, 0x86ef, 0x0005, 0xaa50, 0xaa52, 0xaa52, - 0xaa76, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, - 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, - 0x080c, 0x151a, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0036, 0x00d6, - 0x6010, 0xa06d, 0x01c0, 0xad84, 0xf000, 0x01a8, 0x6003, 0x0002, - 0x6018, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xb155, - 0x6013, 0x0000, 0x6014, 0xa005, 0x1120, 0x2001, 0xb8b7, 0x2004, - 0x6016, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, 0x080c, - 0x7102, 0x080c, 0x71e5, 0x080c, 0x9d16, 0x0120, 0x6010, 0x2068, - 0x080c, 0x1614, 0x080c, 0x9ed9, 0x00de, 0x0005, 0x0002, 0xaa9a, - 0xaab7, 0xaaa3, 0xaac3, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, - 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, - 0xaa9a, 0xaa9a, 0x080c, 0x151a, 0x6010, 0xa088, 0x0013, 0x2104, - 0xa085, 0x0400, 0x200a, 0x080c, 0x7102, 0x6010, 0xa080, 0x0013, - 0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, - 0x86d3, 0x0010, 0x6003, 0x0002, 0x080c, 0x71e5, 0x0005, 0x080c, - 0x7102, 0x080c, 0xb393, 0x1120, 0x080c, 0x6b61, 0x080c, 0x86a4, - 0x080c, 0x71e5, 0x0005, 0x080c, 0x7102, 0x2009, 0x0041, 0x0804, - 0xac12, 0xa182, 0x0040, 0x0002, 0xaadf, 0xaae1, 0xaadf, 0xaadf, - 0xaadf, 0xaadf, 0xaadf, 0xaae2, 0xaadf, 0xaadf, 0xaadf, 0xaadf, - 0xaadf, 0xaadf, 0xaadf, 0xaadf, 0xaadf, 0xaaed, 0xaadf, 0x080c, - 0x151a, 0x0005, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, - 0x3e20, 0x2c10, 0x080c, 0x1863, 0x0005, 0x00d6, 0x080c, 0x6b61, - 0x00de, 0x080c, 0xb3f6, 0x080c, 0x86a4, 0x0005, 0xa182, 0x0040, - 0x0002, 0xab0c, 0xab0c, 0xab0c, 0xab0c, 0xab0c, 0xab0c, 0xab0c, - 0xab0e, 0xab0c, 0xab11, 0xab4a, 0xab0c, 0xab0c, 0xab0c, 0xab0c, - 0xab4a, 0xab0c, 0xab0c, 0xab0c, 0x080c, 0x151a, 0x080c, 0x86ef, - 0x0005, 0x2001, 0xb672, 0x2004, 0xd0e4, 0x0158, 0x2001, 0x0100, - 0x2004, 0xa082, 0x0005, 0x0228, 0x2001, 0x011f, 0x2004, 0x6036, - 0x0010, 0x6037, 0x0000, 0x080c, 0x7198, 0x080c, 0x72a2, 0x6010, - 0x00d6, 0x2068, 0x684c, 0xd0fc, 0x0150, 0xa08c, 0x0003, 0xa18e, - 0x0002, 0x0168, 0x2009, 0x0041, 0x00de, 0x0804, 0xac12, 0x6003, - 0x0007, 0x6017, 0x0000, 0x080c, 0x6b61, 0x00de, 0x0005, 0x080c, - 0xb393, 0x0110, 0x00de, 0x0005, 0x080c, 0x6b61, 0x080c, 0x86a4, - 0x00de, 0x0ca0, 0x0036, 0x080c, 0x7198, 0x080c, 0x72a2, 0x6010, - 0x00d6, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0188, 0x684c, 0xa084, - 0x0003, 0xa086, 0x0002, 0x0140, 0x687c, 0x632c, 0xa31a, 0x632e, - 0x6880, 0x6328, 0xa31b, 0x632a, 0x6003, 0x0002, 0x0080, 0x2019, - 0x0004, 0x080c, 0xb155, 0x6014, 0xa005, 0x1128, 0x2001, 0xb8b7, - 0x2004, 0x8003, 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, 0x00de, - 0x003e, 0x0005, 0xa186, 0x0013, 0x1150, 0x6004, 0xa086, 0x0042, - 0x190c, 0x151a, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0005, 0xa186, - 0x0027, 0x0118, 0xa186, 0x0014, 0x1180, 0x6004, 0xa086, 0x0042, - 0x190c, 0x151a, 0x2001, 0x0007, 0x080c, 0x4f9c, 0x080c, 0x7102, - 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0xa182, 0x0040, 0x0002, - 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb5, - 0xabc1, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, - 0xabb3, 0xabb3, 0xabb3, 0x080c, 0x151a, 0x0036, 0x0046, 0x20e1, - 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1863, 0x004e, 0x003e, - 0x0005, 0x6010, 0x00d6, 0x2068, 0x6810, 0x6a14, 0x0006, 0x0046, - 0x0056, 0x6c7c, 0xa422, 0x6d80, 0x2200, 0xa52b, 0x602c, 0xa420, - 0x642e, 0x6028, 0xa529, 0x652a, 0x005e, 0x004e, 0x000e, 0xa20d, - 0x1178, 0x684c, 0xd0fc, 0x0120, 0x2009, 0x0041, 0x00de, 0x0490, - 0x6003, 0x0007, 0x6017, 0x0000, 0x080c, 0x6b61, 0x00de, 0x0005, - 0x0006, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, 0x000e, 0x0120, - 0x6003, 0x0002, 0x00de, 0x0005, 0x2009, 0xb60d, 0x210c, 0xd19c, - 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, 0x0021, 0x080c, - 0x6b63, 0x00de, 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212, - 0xa291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, 0x6a6a, - 0x6866, 0x0005, 0xa182, 0x0040, 0x0208, 0x0062, 0xa186, 0x0013, - 0x0120, 0xa186, 0x0014, 0x190c, 0x151a, 0x6020, 0xd0dc, 0x090c, - 0x151a, 0x0005, 0xac35, 0xac3c, 0xac48, 0xac54, 0xac35, 0xac35, - 0xac35, 0xac63, 0xac35, 0xac37, 0xac37, 0xac35, 0xac35, 0xac35, - 0xac35, 0xac37, 0xac35, 0xac37, 0xac35, 0x080c, 0x151a, 0x6020, - 0xd0dc, 0x090c, 0x151a, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, - 0x6cff, 0x0126, 0x2091, 0x8000, 0x080c, 0x71e5, 0x012e, 0x0005, - 0x6003, 0x0001, 0x6106, 0x080c, 0x6cff, 0x0126, 0x2091, 0x8000, - 0x080c, 0x71e5, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, - 0x080c, 0x1fc5, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d62, 0x080c, - 0x72a2, 0x012e, 0x0005, 0xa016, 0x080c, 0x1863, 0x0005, 0x0126, - 0x2091, 0x8000, 0x0036, 0x00d6, 0xa182, 0x0040, 0x0023, 0x00de, - 0x003e, 0x012e, 0x0005, 0xac83, 0xac85, 0xac97, 0xacb2, 0xac83, - 0xac83, 0xac83, 0xacc7, 0xac83, 0xac83, 0xac83, 0xac83, 0xac83, - 0xac83, 0xac83, 0xac83, 0x080c, 0x151a, 0x6010, 0x2068, 0x684c, - 0xd0fc, 0x01f8, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x01d0, 0x6003, - 0x0001, 0x6106, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0498, 0x6010, - 0x2068, 0x684c, 0xd0fc, 0x0168, 0xa09c, 0x0003, 0xa39e, 0x0003, - 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x6cff, 0x080c, 0x71e5, - 0x0408, 0x6013, 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, 0x080c, - 0xb155, 0x00c0, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0d90, 0xa09c, - 0x0003, 0xa39e, 0x0003, 0x0d68, 0x6003, 0x0003, 0x6106, 0x2c10, - 0x080c, 0x1fc5, 0x080c, 0x6d62, 0x080c, 0x72a2, 0x0018, 0xa016, - 0x080c, 0x1863, 0x0005, 0x080c, 0x7102, 0x6110, 0x81ff, 0x0158, - 0x00d6, 0x2168, 0x080c, 0xb43c, 0x0036, 0x2019, 0x0029, 0x080c, - 0xb155, 0x003e, 0x00de, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, - 0x080c, 0x7198, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, - 0xb43c, 0x0036, 0x2019, 0x0029, 0x080c, 0xb155, 0x003e, 0x00de, - 0x080c, 0x9ed9, 0x080c, 0x72a2, 0x0005, 0xa182, 0x0085, 0x0002, - 0xad01, 0xacff, 0xacff, 0xad0d, 0xacff, 0xacff, 0xacff, 0x080c, - 0x151a, 0x6003, 0x000b, 0x6106, 0x080c, 0x6cff, 0x0126, 0x2091, - 0x8000, 0x080c, 0x71e5, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, - 0xb38c, 0x0118, 0x080c, 0x86a4, 0x00d8, 0x2071, 0xbc80, 0x7224, - 0x6212, 0x7220, 0x080c, 0xb003, 0x0118, 0x6007, 0x0086, 0x0040, - 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x1110, 0x6007, 0x0086, - 0x6003, 0x0001, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x080c, 0x72a2, - 0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, - 0x0085, 0x0a0c, 0x151a, 0xa08a, 0x008c, 0x1a0c, 0x151a, 0xa082, - 0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186, 0x0014, 0x0118, - 0x080c, 0x86ef, 0x0050, 0x2001, 0x0007, 0x080c, 0x4f9c, 0x080c, - 0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0xad5d, 0xad5f, - 0xad5f, 0xad5d, 0xad5d, 0xad5d, 0xad5d, 0x080c, 0x151a, 0x080c, - 0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0xa182, 0x0085, - 0x0a0c, 0x151a, 0xa182, 0x008c, 0x1a0c, 0x151a, 0xa182, 0x0085, - 0x0002, 0xad78, 0xad78, 0xad78, 0xad7a, 0xad78, 0xad78, 0xad78, - 0x080c, 0x151a, 0x0005, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, - 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x86ef, 0x0030, 0x080c, - 0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0x0036, 0x080c, - 0xb3f6, 0x603f, 0x0000, 0x2019, 0x000b, 0x0031, 0x601f, 0x0006, - 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000, - 0x0086, 0x2c40, 0x0096, 0x2049, 0x0000, 0x080c, 0x81b7, 0x009e, - 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, 0x825d, 0x007e, 0x1548, - 0x6000, 0xa086, 0x0000, 0x0528, 0x601c, 0xa086, 0x0007, 0x0508, - 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, 0x080c, 0xb3f6, 0x601f, - 0x0007, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x080c, 0x1952, 0x6010, - 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0xb155, 0x00de, 0x6013, - 0x0000, 0x080c, 0xb3f6, 0x601f, 0x0007, 0x2001, 0xb8b6, 0x2004, - 0x6016, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156, - 0x2079, 0xbc80, 0x7938, 0x783c, 0x080c, 0x2852, 0x15b0, 0x0016, - 0x00c6, 0x080c, 0x501b, 0x1578, 0x001e, 0x002e, 0x0026, 0x0016, - 0x2019, 0x0029, 0x080c, 0x8320, 0x080c, 0x6e67, 0x0076, 0x2039, - 0x0000, 0x080c, 0x6d74, 0x007e, 0x001e, 0x0076, 0x2039, 0x0000, - 0x080c, 0xaf3e, 0x007e, 0x080c, 0x521c, 0x0026, 0x6204, 0xa294, - 0xff00, 0x8217, 0xa286, 0x0006, 0x0118, 0xa286, 0x0004, 0x1118, - 0x62a0, 0x080c, 0x2d8a, 0x002e, 0x001e, 0x080c, 0x4c7e, 0x6612, - 0x6516, 0xa006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce, - 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0xb621, - 0x2104, 0xa086, 0x0074, 0x1904, 0xae77, 0x2069, 0xbc8e, 0x690c, - 0xa182, 0x0100, 0x06c0, 0x6908, 0xa184, 0x8000, 0x05e8, 0x2001, - 0xb89e, 0x2004, 0xa005, 0x1160, 0x6018, 0x2070, 0x7010, 0xa084, - 0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, 0xa184, 0x0800, 0x0560, - 0x6910, 0xa18a, 0x0001, 0x0610, 0x6914, 0x2069, 0xbcae, 0x6904, - 0x81ff, 0x1198, 0x690c, 0xa182, 0x0100, 0x02a8, 0x6908, 0x81ff, - 0x1178, 0x6910, 0xa18a, 0x0001, 0x0288, 0x6918, 0xa18a, 0x0001, - 0x0298, 0x00d0, 0x6013, 0x0100, 0x00a0, 0x6013, 0x0300, 0x0088, - 0x6013, 0x0500, 0x0070, 0x6013, 0x0700, 0x0058, 0x6013, 0x0900, - 0x0040, 0x6013, 0x0b00, 0x0028, 0x6013, 0x0f00, 0x0010, 0x6013, - 0x2d00, 0xa085, 0x0001, 0x0008, 0xa006, 0x001e, 0x00ee, 0x00de, - 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, 0x6218, - 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, 0x0190, 0xa286, - 0x0004, 0x0178, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0148, - 0xa286, 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, 0x502a, 0x00ce, - 0x04c0, 0x2011, 0xbc96, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, - 0x9166, 0x1580, 0x2011, 0xbc9a, 0xad98, 0x0006, 0x20a9, 0x0004, - 0x080c, 0x9166, 0x1538, 0x0046, 0x0016, 0x6aa0, 0xa294, 0x00ff, - 0x8227, 0xa006, 0x2009, 0xb653, 0x210c, 0xd1a4, 0x0138, 0x2009, - 0x0029, 0x080c, 0xb1a4, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, - 0x080c, 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2c08, - 0x080c, 0xaf3e, 0x007e, 0x2001, 0x0007, 0x080c, 0x4f9c, 0x001e, - 0x004e, 0xa006, 0x015e, 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005, - 0x00d6, 0x2069, 0xbc8e, 0x6800, 0xa086, 0x0800, 0x0118, 0x6013, - 0x0000, 0x0008, 0xa006, 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016, - 0x0026, 0x0036, 0x0156, 0x2079, 0xbc8c, 0x7930, 0x7834, 0x080c, - 0x2852, 0x11a0, 0x080c, 0x501b, 0x1188, 0x2011, 0xbc90, 0xac98, - 0x000a, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1140, 0x2011, 0xbc94, - 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x015e, 0x003e, - 0x002e, 0x001e, 0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016, - 0x0026, 0x0036, 0x0156, 0x2011, 0xbc83, 0x2204, 0x8211, 0x220c, - 0x080c, 0x2852, 0x11a0, 0x080c, 0x501b, 0x1188, 0x2011, 0xbc96, - 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1140, 0x2011, - 0xbc9a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x015e, - 0x003e, 0x002e, 0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6, - 0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, - 0x8000, 0x2740, 0x2029, 0xb8ea, 0x252c, 0x2021, 0xb8f0, 0x2424, - 0x2061, 0xbe00, 0x2071, 0xb600, 0x7648, 0x7068, 0x81ff, 0x0150, - 0x0006, 0xa186, 0xb9f5, 0x000e, 0x0128, 0x8001, 0xa602, 0x1a04, - 0xafbf, 0x0018, 0xa606, 0x0904, 0xafbf, 0x2100, 0xac06, 0x0904, - 0xafb6, 0x080c, 0xb1cc, 0x0904, 0xafb6, 0x671c, 0xa786, 0x0001, - 0x0904, 0xafda, 0xa786, 0x0004, 0x0904, 0xafda, 0xa786, 0x0007, - 0x05e8, 0x2500, 0xac06, 0x05d0, 0x2400, 0xac06, 0x05b8, 0x080c, - 0xb1dc, 0x15a0, 0x88ff, 0x0118, 0x6050, 0xa906, 0x1578, 0x00d6, - 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1952, 0x001e, - 0xa786, 0x0008, 0x1148, 0x080c, 0x9f14, 0x1130, 0x080c, 0x8ca5, - 0x00de, 0x080c, 0x9ed9, 0x00d0, 0x6010, 0x2068, 0x080c, 0x9d16, - 0x0190, 0xa786, 0x0003, 0x1528, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x080c, 0xb43c, 0x0016, 0x080c, 0x9f88, 0x080c, 0x547a, - 0x001e, 0x080c, 0x9ecd, 0x00de, 0x080c, 0x9ed9, 0xace0, 0x0018, - 0x2001, 0xb617, 0x2004, 0xac02, 0x1210, 0x0804, 0xaf52, 0x012e, - 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, - 0x0005, 0xa786, 0x0006, 0x1150, 0xa386, 0x0005, 0x0128, 0x080c, - 0xb43c, 0x080c, 0xb155, 0x08f8, 0x00de, 0x0c00, 0xa786, 0x000a, - 0x0968, 0x0850, 0x080c, 0xb1dc, 0x19c8, 0x81ff, 0x09b8, 0xa180, - 0x0001, 0x2004, 0xa086, 0x0018, 0x0130, 0xa180, 0x0001, 0x2004, - 0xa086, 0x002d, 0x1958, 0x6000, 0xa086, 0x0002, 0x1938, 0x080c, - 0x9f03, 0x0130, 0x080c, 0x9f14, 0x1908, 0x080c, 0x8ca5, 0x0038, - 0x080c, 0x2cf7, 0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x080c, - 0x9ed9, 0x0804, 0xafb6, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, - 0xa006, 0x080c, 0xb176, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f, - 0x001b, 0x00ee, 0x00ce, 0x0005, 0xb01c, 0xb01c, 0xb01c, 0xb01c, - 0xb01c, 0xb01c, 0xb01e, 0xb01c, 0xa006, 0x0005, 0x0046, 0x0016, - 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, - 0x2009, 0x0020, 0x080c, 0xb1a4, 0x001e, 0x004e, 0x0036, 0x2019, - 0x0002, 0x080c, 0xad9c, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001, - 0x0001, 0x080c, 0x4f5d, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, - 0x0004, 0x2019, 0xb605, 0x2011, 0xbc96, 0x080c, 0x9166, 0x003e, - 0x002e, 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, - 0x2061, 0xbe00, 0x2079, 0x0001, 0x8fff, 0x0904, 0xb0ab, 0x2071, - 0xb600, 0x7648, 0x7068, 0x8001, 0xa602, 0x1a04, 0xb0ab, 0x88ff, - 0x0128, 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000, 0x080c, 0xb1cc, - 0x0588, 0x2400, 0xac06, 0x0570, 0x671c, 0xa786, 0x0006, 0x1550, - 0xa786, 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1510, - 0x85ff, 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6, 0x6000, 0xa086, - 0x0004, 0x1150, 0x080c, 0xb3f6, 0x601f, 0x0007, 0x2001, 0xb8b6, - 0x2004, 0x6016, 0x080c, 0x1952, 0x6010, 0x2068, 0x080c, 0x9d16, - 0x0120, 0x0046, 0x080c, 0xb155, 0x004e, 0x00de, 0x080c, 0x9ed9, - 0x88ff, 0x1198, 0xace0, 0x0018, 0x2001, 0xb617, 0x2004, 0xac02, - 0x1210, 0x0804, 0xb05c, 0xa006, 0x012e, 0x002e, 0x006e, 0x007e, - 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca0, - 0x0076, 0x0056, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, - 0x2019, 0x0002, 0x6218, 0x0096, 0x2049, 0x0000, 0x080c, 0x81b7, - 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x825d, 0x080c, 0xb04d, - 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, - 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, - 0x0036, 0x080c, 0x501b, 0x11b0, 0x2c10, 0x0056, 0x0086, 0x2041, - 0x0000, 0x2508, 0x2029, 0x0001, 0x0096, 0x2049, 0x0000, 0x080c, - 0x81b7, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x825d, 0x080c, - 0xb04d, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xb0df, 0x015e, - 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056, - 0x6218, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, - 0x0096, 0x2049, 0x0000, 0x080c, 0x81b7, 0x009e, 0x008e, 0x2039, - 0x0000, 0x080c, 0x825d, 0x2c20, 0x080c, 0xb04d, 0x005e, 0x007e, - 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, - 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x501b, - 0x11c0, 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828, 0x0046, 0x2021, - 0x0001, 0x080c, 0xb3d8, 0x004e, 0x0096, 0x2049, 0x0000, 0x080c, - 0x81b7, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x825d, 0x080c, - 0xb04d, 0x003e, 0x001e, 0x8108, 0x1f04, 0xb12c, 0x015e, 0x00ce, - 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x3800, - 0xd08c, 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82, 0xb600, 0x0230, - 0xad82, 0xee00, 0x0280, 0xad82, 0xffff, 0x1268, 0x6800, 0xa07d, - 0x0138, 0x6803, 0x0000, 0x6b52, 0x080c, 0x547a, 0x2f68, 0x0cb0, - 0x6b52, 0x080c, 0x547a, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, - 0x0036, 0x2061, 0xbe00, 0xa005, 0x1138, 0x2071, 0xb600, 0x7448, - 0x7068, 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000, - 0xa086, 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0, - 0x0006, 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xb617, - 0x2004, 0xac02, 0x1220, 0x0c40, 0xa085, 0x0001, 0x0008, 0xa006, - 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15fd, - 0x000e, 0x090c, 0x151a, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010, - 0x080c, 0x9d06, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014, - 0x2004, 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0x2001, - 0xb8be, 0x2004, 0x6852, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, - 0x080c, 0x547a, 0x00de, 0x0005, 0x6700, 0xa786, 0x0000, 0x0158, - 0xa786, 0x0001, 0x0140, 0xa786, 0x000a, 0x0128, 0xa786, 0x0009, - 0x0110, 0xa085, 0x0001, 0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0, - 0xa206, 0x00ee, 0x0005, 0x0016, 0x6004, 0xa08e, 0x001e, 0x11a0, - 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, - 0x6003, 0x000b, 0x601f, 0x0005, 0x2001, 0xb8b7, 0x2004, 0x6016, - 0x080c, 0x6cff, 0x080c, 0x71e5, 0x001e, 0x0005, 0xe000, 0xe000, - 0x0005, 0x6020, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0x9ff1, - 0x0030, 0x080c, 0xb3f6, 0x080c, 0x6b61, 0x080c, 0x86a4, 0x0005, - 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb21f, 0xb21f, - 0xb21f, 0xb224, 0xb21f, 0xb221, 0xb221, 0xb21f, 0xb221, 0xa006, - 0x0005, 0x00c6, 0x2260, 0x00ce, 0xa085, 0x0001, 0x0005, 0xa280, - 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb236, 0xb236, 0xb236, - 0xb236, 0xb236, 0xb236, 0xb241, 0xb236, 0xb236, 0x6007, 0x003b, - 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x6cff, - 0x0005, 0x00c6, 0x2260, 0x080c, 0xb3f6, 0x603f, 0x0000, 0x6020, - 0xc0f4, 0xc0cc, 0x6022, 0x6037, 0x0000, 0x00ce, 0x00d6, 0x2268, - 0xa186, 0x0007, 0x1904, 0xb29c, 0x6810, 0xa005, 0x0138, 0xa080, - 0x0013, 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08c0, 0x6007, 0x003a, - 0x6003, 0x0001, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00c6, 0x2d60, - 0x6100, 0xa186, 0x0002, 0x1904, 0xb325, 0x6010, 0xa005, 0x1138, - 0x6000, 0xa086, 0x0007, 0x190c, 0x151a, 0x0804, 0xb325, 0xa08c, - 0xf000, 0x1130, 0x0028, 0x2068, 0x6800, 0xa005, 0x1de0, 0x2d00, - 0xa080, 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, 0x0002, 0x1180, - 0x6010, 0x2068, 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, - 0xc0fc, 0x6852, 0x2009, 0x0043, 0x080c, 0xac12, 0x0804, 0xb325, - 0x2009, 0x0041, 0x0804, 0xb31f, 0xa186, 0x0005, 0x15f0, 0x6810, - 0xa080, 0x0013, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xb236, - 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x151a, 0x0804, 0xb254, 0x6007, - 0x003a, 0x6003, 0x0001, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00c6, - 0x2d60, 0x6100, 0xa186, 0x0002, 0x0120, 0xa186, 0x0004, 0x1904, - 0xb325, 0x2071, 0xb924, 0x7000, 0xa086, 0x0003, 0x1128, 0x7004, - 0xac06, 0x1110, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, 0x200c, - 0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc, - 0x2102, 0x2009, 0x0042, 0x0804, 0xb31f, 0x0036, 0x00d6, 0x00d6, - 0x080c, 0x15fd, 0x003e, 0x090c, 0x151a, 0x6837, 0x010d, 0x6803, - 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, 0x0045, - 0x2c00, 0x6862, 0x6034, 0x6872, 0x2360, 0x6020, 0xc0dd, 0x6022, - 0x6018, 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, 0x6350, - 0x6b4a, 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6d6a, 0x6e66, - 0x686f, 0x0001, 0x080c, 0x547a, 0x2019, 0x0045, 0x6008, 0x2068, - 0x080c, 0xad9c, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, - 0x6017, 0x0000, 0x603f, 0x0000, 0x00de, 0x003e, 0x0038, 0x603f, - 0x0000, 0x6003, 0x0007, 0x080c, 0xac12, 0x00ce, 0x00de, 0x0005, - 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, - 0xa186, 0x0027, 0x1178, 0x080c, 0x7102, 0x0036, 0x00d6, 0x6010, - 0x2068, 0x2019, 0x0004, 0x080c, 0xb155, 0x00de, 0x003e, 0x080c, - 0x71e5, 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c, 0x86ef, 0x0005, - 0xb351, 0xb34f, 0xb34f, 0xb34f, 0xb34f, 0xb34f, 0xb351, 0x080c, - 0x151a, 0x080c, 0x7102, 0x6003, 0x000c, 0x080c, 0x71e5, 0x0005, - 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, - 0x86ef, 0x0005, 0xb369, 0xb369, 0xb369, 0xb369, 0xb36b, 0xb389, - 0xb369, 0x080c, 0x151a, 0x00d6, 0x2c68, 0x080c, 0x864e, 0x01a0, - 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xbc8e, 0x210c, 0x6136, - 0x2009, 0xbc8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a, - 0x601f, 0x0004, 0x080c, 0x6cff, 0x2d60, 0x080c, 0x86a4, 0x00de, - 0x0005, 0x080c, 0x86a4, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, - 0xd0ec, 0x00ee, 0x0005, 0x6010, 0xa08c, 0xf000, 0x0904, 0xb3d7, - 0xa080, 0x0013, 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xb672, 0x2004, - 0xd0ec, 0x05a8, 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, - 0x0180, 0x00f6, 0x2c78, 0x080c, 0x5373, 0x00fe, 0x0150, 0x2001, - 0xb8b8, 0x2004, 0x603e, 0x2009, 0xb672, 0x210c, 0xd1f4, 0x11e8, - 0x0080, 0x2009, 0xb672, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, - 0x6022, 0xa006, 0x00a0, 0x2001, 0xb8b8, 0x200c, 0x8103, 0xa100, - 0x603e, 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0118, 0xa088, - 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, - 0x0016, 0x00c6, 0x00e6, 0x6150, 0xa2f0, 0x002b, 0x2e04, 0x2060, - 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, - 0x2072, 0x080c, 0x6b61, 0x080c, 0x86a4, 0x0010, 0xacf0, 0x0003, - 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, - 0xa0e8, 0x002b, 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, - 0xa0e8, 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, - 0x0036, 0x0156, 0x2011, 0xb628, 0x2204, 0xa084, 0x00ff, 0x2019, - 0xbc8e, 0x2334, 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, - 0xff00, 0xa636, 0x11a0, 0x2011, 0xbc90, 0x6018, 0xa098, 0x000a, - 0x20a9, 0x0004, 0x080c, 0x9166, 0x1150, 0x2011, 0xbc94, 0x6018, - 0xa098, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1100, 0x015e, - 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xb600, 0x080c, 0x4c28, - 0x080c, 0x2aed, 0x00ee, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, - 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, - 0x0005, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, - 0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0xb8ea, 0x252c, 0x2021, - 0xb8f0, 0x2424, 0x2061, 0xbe00, 0x2071, 0xb600, 0x7648, 0x7068, - 0xa606, 0x0578, 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, - 0x1500, 0x2500, 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, - 0xb1cc, 0x01b8, 0x080c, 0xb1dc, 0x11a0, 0x6000, 0xa086, 0x0004, - 0x1120, 0x0016, 0x080c, 0x1952, 0x001e, 0x080c, 0x9f03, 0x1110, - 0x080c, 0x2cf7, 0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x080c, - 0x9ed9, 0xace0, 0x0018, 0x2001, 0xb617, 0x2004, 0xac02, 0x1208, - 0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, - 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, - 0x8000, 0x2071, 0xb640, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, - 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, - 0xa084, 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, - 0xa08e, 0x0005, 0x0118, 0x2071, 0xb64a, 0x04c9, 0x001e, 0x00ee, - 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, - 0x8000, 0x2071, 0xb640, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, - 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500, - 0xa084, 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130, - 0xa08e, 0x0005, 0x0118, 0x2071, 0xb64a, 0x0089, 0x001e, 0x00ee, - 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, - 0x2071, 0xb642, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, - 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, - 0x00e6, 0x2071, 0xb640, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, - 0xb644, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, - 0x8000, 0x2071, 0xb640, 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e, - 0x012e, 0x0005, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, - 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, - 0x4000, 0x8000, 0xdb06 -}; -#ifdef UNIQUE_FW_NAME -unsigned short fw2200tp_length01 = 0xa52b; -#else -unsigned short risc_code_length01 = 0xa52b; -#endif - diff --git a/drivers/scsi/qla2xxx/ql2300.c b/drivers/scsi/qla2xxx/ql2300.c deleted file mode 100644 index e7a93dd..0000000 --- a/drivers/scsi/qla2xxx/ql2300.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (C) 2003 Christoph Hellwig. - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include -#include -#include - -#include "qla_def.h" - -static char qla_driver_name[] = "qla2300"; - -extern unsigned char fw2300ipx_version[]; -extern unsigned char fw2300ipx_version_str[]; -extern unsigned short fw2300ipx_addr01; -extern unsigned short fw2300ipx_code01[]; -extern unsigned short fw2300ipx_length01; - -static struct qla_fw_info qla_fw_tbl[] = { - { - .addressing = FW_INFO_ADDR_NORMAL, - .fwcode = &fw2300ipx_code01[0], - .fwlen = &fw2300ipx_length01, - .fwstart = &fw2300ipx_addr01, - }, - { FW_INFO_ADDR_NOMORE, }, -}; - -static struct qla_board_info qla_board_tbl[] = { - { - .drv_name = qla_driver_name, - .isp_name = "ISP2300", - .fw_info = qla_fw_tbl, - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP2312", - .fw_info = qla_fw_tbl, - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP6312", - .fw_info = qla_fw_tbl, - }, -}; - -static struct pci_device_id qla2300_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2300, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[0], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2312, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[1], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP6312, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[2], - }, - {0, 0}, -}; -MODULE_DEVICE_TABLE(pci, qla2300_pci_tbl); - -static int __devinit -qla2300_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - return qla2x00_probe_one(pdev, - (struct qla_board_info *)id->driver_data); -} - -static void __devexit -qla2300_remove_one(struct pci_dev *pdev) -{ - qla2x00_remove_one(pdev); -} - -static struct pci_driver qla2300_pci_driver = { - .name = "qla2300", - .id_table = qla2300_pci_tbl, - .probe = qla2300_probe_one, - .remove = __devexit_p(qla2300_remove_one), -}; - -static int __init -qla2300_init(void) -{ - return pci_module_init(&qla2300_pci_driver); -} - -static void __exit -qla2300_exit(void) -{ - pci_unregister_driver(&qla2300_pci_driver); -} - -module_init(qla2300_init); -module_exit(qla2300_exit); - -MODULE_AUTHOR("QLogic Corporation"); -MODULE_DESCRIPTION("QLogic ISP23xx FC-SCSI Host Bus Adapter driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2300_fw.c b/drivers/scsi/qla2xxx/ql2300_fw.c deleted file mode 100644 index b8ce7fe..0000000 --- a/drivers/scsi/qla2xxx/ql2300_fw.c +++ /dev/null @@ -1,7746 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ - -/* - * Firmware Version 3.03.20 (15:39 Feb 01, 2006) - */ - -#ifdef UNIQUE_FW_NAME -unsigned short fw2300ipx_version = 3*1024+3; -#else -unsigned short risc_code_version = 3*1024+3; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned char fw2300ipx_version_str[] = {3, 3,20}; -#else -unsigned char firmware_version[] = {3, 3,20}; -#endif - -#ifdef UNIQUE_FW_NAME -#define fw2300ipx_VERSION_STRING "3.03.20" -#else -#define FW_VERSION_STRING "3.03.20" -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2300ipx_addr01 = 0x0800 ; -#else -unsigned short risc_code_addr01 = 0x0800 ; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2300ipx_code01[] = { -#else -unsigned short risc_code01[] = { -#endif - 0x0470, 0x0000, 0x0000, 0xf091, 0x0000, 0x0003, 0x0003, 0x0014, - 0x0137, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, - 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, - 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, - 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x332e, 0x3033, 0x2e32, 0x3020, 0x2020, 0x2020, 0x2400, 0x20a9, - 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, - 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, - 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, - 0x400f, 0x2091, 0x2800, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, - 0x2091, 0x2a00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, - 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, - 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, - 0x0000, 0x20c1, 0x0004, 0x20c9, 0x1bff, 0x2059, 0x0000, 0x2b78, - 0x7883, 0x0004, 0x2089, 0x2d93, 0x2051, 0x1800, 0x2a70, 0x20e1, - 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e52, 0x2029, - 0x4d00, 0x2031, 0xffff, 0x2039, 0x4cd0, 0x2021, 0x0200, 0x20e9, - 0x0001, 0x20a1, 0x0000, 0x20a9, 0x0800, 0x900e, 0x4104, 0x20e9, - 0x0001, 0x20a1, 0x1000, 0x900e, 0x2001, 0x0cc0, 0x9084, 0x0fff, - 0x20a8, 0x4104, 0x2001, 0x0000, 0x9086, 0x0000, 0x0120, 0x21a8, - 0x4104, 0x8001, 0x1de0, 0x756e, 0x7672, 0x776a, 0x7476, 0x747a, - 0x00e6, 0x2071, 0x1ad1, 0x2472, 0x00ee, 0x20a1, 0x1cd0, 0x7170, - 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x000f, 0x2001, 0x0001, - 0x9112, 0x900e, 0x21a8, 0x4104, 0x8211, 0x1de0, 0x7170, 0x3400, - 0x8001, 0x9102, 0x0120, 0x0218, 0x20a8, 0x900e, 0x4104, 0x2009, - 0x1800, 0x810d, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x001f, - 0x2001, 0x0001, 0x9112, 0x20e9, 0x0001, 0x20a1, 0x0800, 0x900e, - 0x20a9, 0x0800, 0x4104, 0x8211, 0x1dd8, 0x080c, 0x0f26, 0x080c, - 0x613c, 0x080c, 0xb269, 0x080c, 0x10dd, 0x080c, 0x12fc, 0x080c, - 0x1bd7, 0x080c, 0x0d57, 0x080c, 0x1062, 0x080c, 0x34b6, 0x080c, - 0x7946, 0x080c, 0x6b7c, 0x080c, 0x8a69, 0x080c, 0x874a, 0x080c, - 0x24b7, 0x080c, 0x93a5, 0x080c, 0x8066, 0x080c, 0x22e8, 0x080c, - 0x241c, 0x080c, 0x24ac, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004, - 0x091f, 0x7880, 0x9086, 0x0002, 0x1190, 0x7883, 0x4000, 0x7837, - 0x4000, 0x7833, 0x0010, 0x0e04, 0x0913, 0x2091, 0x5000, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x2071, - 0x1800, 0x7003, 0x0000, 0x2071, 0x1800, 0x7000, 0x908e, 0x0003, - 0x1178, 0x080c, 0x4d09, 0x080c, 0x34dd, 0x080c, 0x79b7, 0x080c, - 0x7122, 0x080c, 0x8b50, 0x080c, 0x8776, 0x080c, 0x2cdd, 0x0c58, - 0x000b, 0x0c78, 0x0944, 0x0945, 0x0ae0, 0x0942, 0x0ba0, 0x0d56, - 0x0d56, 0x0d56, 0x080c, 0x0dc5, 0x0005, 0x0126, 0x00f6, 0x2091, - 0x8000, 0x7000, 0x9086, 0x0001, 0x1904, 0x0ab3, 0x080c, 0x0e94, - 0x080c, 0x7637, 0x0150, 0x080c, 0x765a, 0x15a0, 0x2079, 0x0100, - 0x7828, 0x9085, 0x1800, 0x782a, 0x0468, 0x080c, 0x7563, 0x7000, - 0x9086, 0x0001, 0x1904, 0x0ab3, 0x7098, 0x9086, 0x0029, 0x1904, - 0x0ab3, 0x080c, 0x8733, 0x080c, 0x8725, 0x2001, 0x0161, 0x2003, - 0x0001, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0x9295, 0x5e2f, - 0x7a2a, 0x2011, 0x74b2, 0x080c, 0x883d, 0x2011, 0x74a5, 0x080c, - 0x8917, 0x2011, 0x5f97, 0x080c, 0x883d, 0x2011, 0x8030, 0x901e, - 0x7396, 0x04d0, 0x080c, 0x583f, 0x2079, 0x0100, 0x7844, 0x9005, - 0x1904, 0x0ab3, 0x2011, 0x5f97, 0x080c, 0x883d, 0x2011, 0x74b2, - 0x080c, 0x883d, 0x2011, 0x74a5, 0x080c, 0x8917, 0x2001, 0x0265, - 0x2001, 0x0205, 0x2003, 0x0000, 0x7840, 0x9084, 0xfffb, 0x7842, - 0x2001, 0x19a7, 0x2004, 0x9005, 0x1140, 0x00c6, 0x2061, 0x0100, - 0x080c, 0x60e4, 0x00ce, 0x0804, 0x0ab3, 0x780f, 0x006b, 0x7a28, - 0x080c, 0x763f, 0x0118, 0x9295, 0x5e2f, 0x0010, 0x9295, 0x402f, - 0x7a2a, 0x2011, 0x8010, 0x73d8, 0x2001, 0x19a8, 0x2003, 0x0001, - 0x080c, 0x2b82, 0x080c, 0x4c44, 0x7248, 0xc284, 0x724a, 0x2001, - 0x180c, 0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x080c, 0xa9b0, 0x2011, - 0x0004, 0x080c, 0xd0e8, 0x080c, 0x6947, 0x080c, 0x7637, 0x1120, - 0x080c, 0x2bc6, 0x02e0, 0x0400, 0x080c, 0x60eb, 0x0140, 0x7097, - 0x0001, 0x70d3, 0x0000, 0x080c, 0x5a11, 0x0804, 0x0ab3, 0x080c, - 0x57d5, 0xd094, 0x0188, 0x2011, 0x180c, 0x2204, 0xc0cd, 0x2012, - 0x080c, 0x57d9, 0xd0d4, 0x1118, 0x080c, 0x2bc6, 0x1270, 0x2011, - 0x180c, 0x2204, 0xc0bc, 0x00a8, 0x080c, 0x57d9, 0xd0d4, 0x1db8, - 0x2011, 0x180c, 0x2204, 0xc0bd, 0x0060, 0x2011, 0x180c, 0x2204, - 0xc0bd, 0x2012, 0x080c, 0x6a9b, 0x1128, 0xd0a4, 0x0118, 0x2204, - 0xc0fd, 0x2012, 0x080c, 0x6a61, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e, - 0x00a8, 0x707f, 0x0000, 0x080c, 0x7637, 0x1130, 0x70b0, 0x9005, - 0x1168, 0x080c, 0xd52b, 0x0050, 0x080c, 0xd52b, 0x70dc, 0xd09c, - 0x1128, 0x70b0, 0x9005, 0x0110, 0x080c, 0x60c1, 0x70e7, 0x0000, - 0x70e3, 0x0000, 0x70a7, 0x0000, 0x080c, 0x2bce, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c4, 0x2012, 0x72dc, 0x080c, 0x7637, 0x1178, - 0x9016, 0x0016, 0x080c, 0x298b, 0x2019, 0x196d, 0x211a, 0x001e, - 0x705f, 0xffff, 0x7063, 0x00ef, 0x7083, 0x0000, 0x0020, 0x2019, - 0x196d, 0x201b, 0x0000, 0x2079, 0x1847, 0x7804, 0xd0ac, 0x0108, - 0xc295, 0x72de, 0x080c, 0x7637, 0x0118, 0x9296, 0x0004, 0x0548, - 0x2011, 0x0001, 0x080c, 0xd0e8, 0x70ab, 0x0000, 0x70af, 0xffff, - 0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, - 0x0003, 0x782a, 0x00fe, 0x080c, 0x3000, 0x2011, 0x0005, 0x080c, - 0xaabf, 0x080c, 0x9ab1, 0x080c, 0x7637, 0x0148, 0x00c6, 0x2061, - 0x0100, 0x0016, 0x080c, 0x298b, 0x61e2, 0x001e, 0x00ce, 0x012e, - 0x0420, 0x70ab, 0x0000, 0x70af, 0xffff, 0x7003, 0x0002, 0x00f6, - 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, 0x782a, - 0x00fe, 0x2011, 0x0005, 0x080c, 0xaabf, 0x080c, 0x9ab1, 0x080c, - 0x7637, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x298b, - 0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x00b6, - 0x080c, 0x7637, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, - 0x080c, 0x7637, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, - 0x0138, 0x9180, 0x1000, 0x2004, 0x905d, 0x0110, 0xb800, 0xd0bc, - 0x090c, 0x334c, 0x8108, 0x1f04, 0x0ac7, 0x707f, 0x0000, 0x7080, - 0x9084, 0x00ff, 0x7082, 0x70b3, 0x0000, 0x00be, 0x00ce, 0x0005, - 0x00b6, 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, 0x1904, - 0x0b9d, 0x70ac, 0x9086, 0xffff, 0x0130, 0x080c, 0x3000, 0x080c, - 0x9ab1, 0x0804, 0x0b9d, 0x70dc, 0xd0ac, 0x1110, 0xd09c, 0x0558, - 0xd084, 0x0548, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, - 0xd08c, 0x0508, 0x080c, 0x33af, 0x11d0, 0x70e0, 0x9086, 0xffff, - 0x01b0, 0x080c, 0x31bc, 0x080c, 0x9ab1, 0x70dc, 0xd094, 0x1904, - 0x0b9d, 0x2011, 0x0001, 0x080c, 0xd7e3, 0x0110, 0x2011, 0x0003, - 0x901e, 0x080c, 0x31f6, 0x080c, 0x9ab1, 0x0804, 0x0b9d, 0x70e4, - 0x9005, 0x1904, 0x0b9d, 0x70a8, 0x9005, 0x1904, 0x0b9d, 0x70dc, - 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x0b9d, 0x080c, 0x6a61, 0x1904, - 0x0b9d, 0x080c, 0x6ab4, 0x1904, 0x0b9d, 0x080c, 0x6a9b, 0x01c0, - 0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6724, - 0x1118, 0xb800, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b3d, - 0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x0b9d, - 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0x2011, 0x19b4, - 0x080c, 0x0f96, 0x2011, 0x19ce, 0x080c, 0x0f96, 0x7030, 0xc08c, - 0x7032, 0x7003, 0x0003, 0x70af, 0xffff, 0x080c, 0x0e76, 0x9006, - 0x080c, 0x281c, 0x080c, 0x33af, 0x0118, 0x080c, 0x4de1, 0x0050, - 0x0036, 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4dfb, - 0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x765a, 0x0150, - 0x080c, 0x7637, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, - 0xffdf, 0x782a, 0x00fe, 0x2001, 0x19e9, 0x2004, 0x9086, 0x0005, - 0x1120, 0x2011, 0x0000, 0x080c, 0xaabf, 0x2011, 0x0000, 0x080c, - 0xaac9, 0x080c, 0x9ab1, 0x080c, 0x9bd3, 0x012e, 0x00be, 0x0005, - 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, - 0x7904, 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x60aa, - 0x7940, 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, - 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, - 0x7954, 0xd1ac, 0x1904, 0x0c2d, 0x2001, 0x19a8, 0x2004, 0x9005, - 0x1518, 0x080c, 0x2c49, 0x1148, 0x2001, 0x0001, 0x080c, 0x2bb1, - 0x2001, 0x0001, 0x080c, 0x2b94, 0x00b8, 0x080c, 0x2c51, 0x1138, - 0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94, 0x0068, 0x080c, - 0x2c59, 0x1d50, 0x2001, 0x1998, 0x2004, 0xd0fc, 0x0108, 0x0020, - 0x080c, 0x29bf, 0x0804, 0x0d0d, 0x080c, 0x7648, 0x0148, 0x080c, - 0x765a, 0x1118, 0x080c, 0x7941, 0x0050, 0x080c, 0x763f, 0x0dd0, - 0x080c, 0x793c, 0x080c, 0x7932, 0x080c, 0x7563, 0x0058, 0x080c, - 0x7637, 0x0140, 0x2009, 0x00f8, 0x080c, 0x60aa, 0x7843, 0x0090, - 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, - 0x7637, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x0d12, 0x1f04, 0x0c0c, - 0x0070, 0x7824, 0x080c, 0x7651, 0x0118, 0xd0ac, 0x1904, 0x0d12, - 0x9084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, 0x0d12, 0x2001, - 0x0001, 0x080c, 0x281c, 0x0804, 0x0d25, 0x2001, 0x19a8, 0x2004, - 0x9005, 0x1518, 0x080c, 0x2c49, 0x1148, 0x2001, 0x0001, 0x080c, - 0x2bb1, 0x2001, 0x0001, 0x080c, 0x2b94, 0x00b8, 0x080c, 0x2c51, - 0x1138, 0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94, 0x0068, - 0x080c, 0x2c59, 0x1d50, 0x2001, 0x1998, 0x2004, 0xd0fc, 0x0108, - 0x0020, 0x080c, 0x29bf, 0x0804, 0x0d0d, 0x7850, 0x9085, 0x0040, - 0x7852, 0x7938, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2c61, - 0x9085, 0x2000, 0x7852, 0x793a, 0x20a9, 0x0046, 0x1d04, 0x0c66, - 0x080c, 0x88f7, 0x1f04, 0x0c66, 0x7850, 0x9085, 0x0400, 0x9084, - 0xdfbf, 0x7852, 0x793a, 0x080c, 0x7648, 0x0148, 0x080c, 0x765a, - 0x1118, 0x080c, 0x7941, 0x0050, 0x080c, 0x763f, 0x0dd0, 0x080c, - 0x793c, 0x080c, 0x7932, 0x080c, 0x7563, 0x0020, 0x2009, 0x00f8, - 0x080c, 0x60aa, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x0c8c, 0x7850, - 0x9085, 0x1400, 0x7852, 0x080c, 0x7637, 0x0120, 0x7843, 0x0090, - 0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, 0x0d0c, 0x88f7, - 0x7820, 0xd09c, 0x1588, 0x080c, 0x7637, 0x0904, 0x0cf2, 0x7824, - 0xd0ac, 0x1904, 0x0d12, 0x080c, 0x765a, 0x1530, 0x0046, 0x2021, - 0x0320, 0x8421, 0x1df0, 0x004e, 0x7827, 0x1800, 0x080c, 0x2c61, - 0x7824, 0x9084, 0x1800, 0x1168, 0x9484, 0x0fff, 0x1140, 0x2001, - 0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, 0x0d33, 0x8421, - 0x1158, 0x1d04, 0x0ccd, 0x080c, 0x88f7, 0x080c, 0x793c, 0x080c, - 0x7932, 0x7003, 0x0001, 0x04f0, 0x8319, 0x1940, 0x1d04, 0x0cda, - 0x080c, 0x88f7, 0x2009, 0x199b, 0x2104, 0x9005, 0x0118, 0x8001, - 0x200a, 0x1178, 0x200b, 0x000a, 0x7827, 0x0048, 0x20a9, 0x0002, - 0x080c, 0x2c42, 0x7924, 0x080c, 0x2c61, 0xd19c, 0x0110, 0x080c, - 0x2b82, 0x00d8, 0x080c, 0x7648, 0x1140, 0x94a2, 0x03e8, 0x1128, - 0x080c, 0x760f, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0x080c, - 0x2c61, 0x7824, 0x080c, 0x7651, 0x0110, 0xd0ac, 0x1158, 0x9084, - 0x1800, 0x0950, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, - 0x281c, 0x0078, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904, - 0x918d, 0x0002, 0x7906, 0x7827, 0x0048, 0x7828, 0x9085, 0x0028, - 0x782a, 0x7850, 0x9085, 0x0400, 0x7852, 0x2001, 0x19a8, 0x2003, - 0x0000, 0x9006, 0x78f2, 0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, - 0x004e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0036, 0x0046, 0x00b6, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0069, 0x0d0c, 0x88f7, - 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, - 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x189e, 0x7004, 0x9086, - 0x0001, 0x1110, 0x080c, 0x34dd, 0x00ee, 0x0005, 0x0005, 0x2a70, - 0x2061, 0x19ac, 0x2063, 0x0003, 0x6007, 0x0003, 0x600b, 0x0014, - 0x600f, 0x0137, 0x2001, 0x197c, 0x900e, 0x2102, 0x7196, 0x2001, - 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x705f, 0xffff, 0x0008, - 0x715e, 0x7067, 0xffff, 0x717e, 0x7182, 0x080c, 0xd52b, 0x70eb, - 0x00c0, 0x2061, 0x196c, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, - 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x001f, 0x611a, 0x601f, - 0x07d0, 0x2061, 0x1974, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, - 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, - 0x1989, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, - 0x2020, 0x2001, 0x182c, 0x2102, 0x0005, 0x9016, 0x080c, 0x6724, - 0x1178, 0xb804, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4, - 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210, - 0x8108, 0x9186, 0x0800, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, - 0x2079, 0x0000, 0x000e, 0x00f6, 0x0010, 0x2091, 0x8000, 0x0e04, - 0x0dc7, 0x0006, 0x0016, 0x2001, 0x8002, 0x0006, 0x2079, 0x0000, - 0x000e, 0x7882, 0x7836, 0x001e, 0x798e, 0x000e, 0x788a, 0x000e, - 0x7886, 0x3900, 0x789a, 0x00d6, 0x2069, 0x0300, 0x6818, 0x78ae, - 0x681c, 0x78b2, 0x2001, 0x1a09, 0x2004, 0x78b6, 0x2001, 0x1a86, - 0x2004, 0x78ba, 0x6808, 0x78be, 0x00de, 0x7833, 0x0012, 0x2091, - 0x5000, 0x0156, 0x00d6, 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, - 0x1aa9, 0x7a08, 0x226a, 0x2069, 0x1aaa, 0x7a18, 0x226a, 0x8d68, - 0x7a1c, 0x226a, 0x782c, 0x2019, 0x1ab7, 0x201a, 0x2019, 0x1aba, - 0x9016, 0x7808, 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, 0x8318, - 0x9386, 0x1acf, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, - 0xdead, 0x2019, 0x1ab8, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, - 0x0000, 0x2069, 0x1a89, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, - 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0e26, 0x002e, 0x003e, 0x00de, - 0x015e, 0x2079, 0x1800, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a1c, 0x2004, 0x9005, - 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, - 0x2003, 0x0002, 0x2003, 0x1001, 0x080c, 0x57e4, 0x1108, 0x0099, - 0x0cd8, 0x0005, 0x918c, 0x03ff, 0x2001, 0x0003, 0x2004, 0x9084, - 0x0600, 0x1118, 0x918d, 0x2800, 0x0010, 0x918d, 0x2000, 0x2001, - 0x017f, 0x2102, 0x0005, 0x0026, 0x0126, 0x2011, 0x0080, 0x080c, - 0x0eee, 0x20a9, 0x0900, 0x080c, 0x0f0f, 0x2011, 0x0040, 0x080c, - 0x0eee, 0x20a9, 0x0900, 0x080c, 0x0f0f, 0x0c78, 0x0026, 0x080c, - 0x0efb, 0x1118, 0x2011, 0x0040, 0x0098, 0x2011, 0x010e, 0x2214, - 0x9294, 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0xa880, 0x0010, - 0x2011, 0x6840, 0xd0e4, 0x70ef, 0x0000, 0x1120, 0x70ef, 0x0fa0, - 0x080c, 0x0f00, 0x002e, 0x0005, 0x0026, 0x080c, 0x0efb, 0x0128, - 0xd0a4, 0x1138, 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, 0x080c, - 0x0f00, 0x002e, 0x0005, 0x0026, 0x70ef, 0x0000, 0x080c, 0x0efb, - 0x1148, 0x080c, 0x2c59, 0x1118, 0x2011, 0x8484, 0x0058, 0x2011, - 0x8282, 0x0040, 0x080c, 0x2c59, 0x1118, 0x2011, 0xcdc5, 0x0010, - 0x2011, 0xcac2, 0x080c, 0x0f00, 0x002e, 0x0005, 0x00e6, 0x0006, - 0x2071, 0x1800, 0xd0b4, 0x70e8, 0x1110, 0xc0e4, 0x0048, 0x0006, - 0x3b00, 0x9084, 0xff3f, 0x20d8, 0x000e, 0x70ef, 0x0000, 0xc0e5, - 0x0079, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0xd0e4, - 0x70e8, 0x1110, 0xc0dc, 0x0008, 0xc0dd, 0x0011, 0x00ee, 0x0005, - 0x70ea, 0x7000, 0x9084, 0x0007, 0x000b, 0x0005, 0x0ebd, 0x0e94, - 0x0e94, 0x0e76, 0x0ea3, 0x0e94, 0x0e94, 0x0ea3, 0x0016, 0x3b08, - 0x3a00, 0x9104, 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205, - 0x20d0, 0x001e, 0x0005, 0x2001, 0x183a, 0x2004, 0xd0dc, 0x0005, - 0x9e86, 0x1800, 0x190c, 0x0dc5, 0x70e8, 0xd0e4, 0x0108, 0xc2e5, - 0x72ea, 0xd0e4, 0x1118, 0x9294, 0x00c0, 0x0c01, 0x0005, 0x1d04, - 0x0f0f, 0x2091, 0x6000, 0x1f04, 0x0f0f, 0x0005, 0x890e, 0x810e, - 0x810f, 0x9194, 0x003f, 0x918c, 0xffc0, 0x0005, 0x0006, 0x2200, - 0x914d, 0x894f, 0x894d, 0x894d, 0x000e, 0x0005, 0x01d6, 0x0146, - 0x0036, 0x0096, 0x2061, 0x188d, 0x600b, 0x0000, 0x600f, 0x0000, - 0x6003, 0x0000, 0x6007, 0x0000, 0x2009, 0xffc0, 0x2105, 0x0006, - 0x2001, 0xaaaa, 0x200f, 0x2019, 0x5555, 0x9016, 0x2049, 0x0bff, - 0xab02, 0xa001, 0xa001, 0xa800, 0x9306, 0x1138, 0x2105, 0x9306, - 0x0120, 0x8210, 0x99c8, 0x0400, 0x0c98, 0x000e, 0x200f, 0x2001, - 0x189d, 0x928a, 0x000e, 0x1638, 0x928a, 0x0006, 0x2011, 0x0006, - 0x1210, 0x2011, 0x0000, 0x2202, 0x9006, 0x2008, 0x82ff, 0x01b0, - 0x8200, 0x600a, 0x600f, 0xffff, 0x6003, 0x0002, 0x6007, 0x0000, - 0x0026, 0x2019, 0x0010, 0x9280, 0x0001, 0x20e8, 0x21a0, 0x21a8, - 0x4104, 0x8319, 0x1de0, 0x8211, 0x1da0, 0x002e, 0x009e, 0x003e, - 0x014e, 0x01de, 0x0005, 0x2011, 0x000e, 0x08e8, 0x0016, 0x0026, - 0x0096, 0x3348, 0x080c, 0x0f16, 0x2100, 0x9300, 0x2098, 0x22e0, - 0x009e, 0x002e, 0x001e, 0x0036, 0x3518, 0x20a9, 0x0001, 0x4002, - 0x8007, 0x4004, 0x8319, 0x1dd8, 0x003e, 0x0005, 0x20e9, 0x0001, - 0x71b8, 0x81ff, 0x11c0, 0x9006, 0x2009, 0x0200, 0x20a9, 0x0002, - 0x9298, 0x0018, 0x23a0, 0x4001, 0x2009, 0x0700, 0x20a9, 0x0002, - 0x9298, 0x0008, 0x23a0, 0x4001, 0x707c, 0x8007, 0x7180, 0x810f, - 0x20a9, 0x0002, 0x4001, 0x9298, 0x000c, 0x23a0, 0x900e, 0x080c, - 0x0da5, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x4001, 0x0005, - 0x89ff, 0x0140, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, 0x1040, - 0x009e, 0x0cb0, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, 0x10b9, - 0x090c, 0x0dc5, 0x00ee, 0x0005, 0x0086, 0x00e6, 0x0006, 0x0026, - 0x0036, 0x0126, 0x2091, 0x8000, 0x00c9, 0x2071, 0x1800, 0x73c0, - 0x702c, 0x9016, 0x9045, 0x0158, 0x8210, 0x9906, 0x090c, 0x0dc5, - 0x2300, 0x9202, 0x0120, 0x1a0c, 0x0dc5, 0xa000, 0x0c98, 0x012e, - 0x003e, 0x002e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x0086, 0x00e6, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1910, 0x7010, 0x9005, - 0x0140, 0x7018, 0x9045, 0x0128, 0x9906, 0x090c, 0x0dc5, 0xa000, - 0x0cc8, 0x012e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x00e6, 0x2071, - 0x1800, 0x0126, 0x2091, 0x8000, 0x70c0, 0x8001, 0x0270, 0x70c2, - 0x702c, 0x2048, 0x9085, 0x0001, 0xa800, 0x702e, 0xa803, 0x0000, - 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x904e, 0x0cd8, 0x00e6, - 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x70c0, 0x90ca, 0x0020, - 0x0268, 0x8001, 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e, 0xa803, - 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x904e, 0x0cd8, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x0016, 0x890e, 0x810e, 0x810f, - 0x9184, 0x003f, 0xa862, 0x9184, 0xffc0, 0xa85e, 0x001e, 0x0020, - 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x012e, - 0x00ee, 0x0005, 0x2071, 0x1800, 0x9026, 0x2009, 0x0000, 0x2049, - 0x0400, 0x2900, 0x702e, 0x8940, 0x2800, 0xa802, 0xa95e, 0xa863, - 0x0001, 0x8420, 0x9886, 0x0440, 0x0120, 0x2848, 0x9188, 0x0040, - 0x0c90, 0x2071, 0x188d, 0x7000, 0x9005, 0x11a0, 0x2001, 0x0534, - 0xa802, 0x2048, 0x2009, 0x4d00, 0x8940, 0x2800, 0xa802, 0xa95e, - 0xa863, 0x0001, 0x8420, 0x9886, 0x0800, 0x0120, 0x2848, 0x9188, - 0x0040, 0x0c90, 0x2071, 0x188d, 0x7104, 0x7200, 0x82ff, 0x01d0, - 0x7308, 0x8318, 0x831f, 0x831b, 0x831b, 0x7312, 0x8319, 0x2001, - 0x0800, 0xa802, 0x2048, 0x8900, 0xa802, 0x2040, 0xa95e, 0xaa62, - 0x8420, 0x2300, 0x9906, 0x0130, 0x2848, 0x9188, 0x0040, 0x9291, - 0x0000, 0x0c88, 0xa803, 0x0000, 0x2071, 0x1800, 0x74be, 0x74c2, - 0x0005, 0x00e6, 0x0016, 0x9984, 0xfc00, 0x01e8, 0x908c, 0xf800, - 0x1168, 0x9982, 0x0400, 0x02b8, 0x9982, 0x0440, 0x0278, 0x9982, - 0x0534, 0x0288, 0x9982, 0x0800, 0x1270, 0x0040, 0x9982, 0x0800, - 0x0250, 0x2071, 0x188d, 0x7010, 0x9902, 0x1228, 0x9085, 0x0001, - 0x001e, 0x00ee, 0x0005, 0x9006, 0x0cd8, 0x00e6, 0x2071, 0x1a1b, - 0x7007, 0x0000, 0x9006, 0x701e, 0x7022, 0x7002, 0x2071, 0x0000, - 0x7010, 0x9085, 0x8044, 0x7012, 0x2071, 0x0080, 0x9006, 0x20a9, - 0x0040, 0x7022, 0x1f04, 0x10f1, 0x702b, 0x0020, 0x00ee, 0x0005, - 0x0126, 0x2091, 0x8000, 0x00e6, 0xa06f, 0x0000, 0x2071, 0x1a1b, - 0x701c, 0x9088, 0x1a25, 0x280a, 0x8000, 0x9084, 0x003f, 0x701e, - 0x7120, 0x9106, 0x090c, 0x0dc5, 0x7004, 0x9005, 0x1128, 0x00f6, - 0x2079, 0x0080, 0x00a9, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x00e6, 0x2071, 0x1a1b, 0x7004, 0x9005, 0x1128, - 0x00f6, 0x2079, 0x0080, 0x0021, 0x00fe, 0x00ee, 0x012e, 0x0005, - 0x7004, 0x9086, 0x0000, 0x1110, 0x7007, 0x0006, 0x7000, 0x0002, - 0x113a, 0x12bd, 0x1138, 0x1138, 0x12b1, 0x12b1, 0x12b1, 0x12b1, - 0x080c, 0x0dc5, 0x701c, 0x7120, 0x9106, 0x1148, 0x792c, 0x9184, - 0x0001, 0x1120, 0xd1fc, 0x1110, 0x7007, 0x0000, 0x0005, 0x0096, - 0x9180, 0x1a25, 0x2004, 0x700a, 0x2048, 0x8108, 0x918c, 0x003f, - 0x7122, 0x782b, 0x0026, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, - 0x780a, 0xa898, 0x780e, 0xa878, 0x700e, 0xa870, 0x7016, 0xa874, - 0x701a, 0xa868, 0x009e, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, - 0x0005, 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, - 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, - 0x7212, 0x8203, 0x7812, 0x782b, 0x0020, 0x782b, 0x0041, 0x002e, - 0x001e, 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, - 0x20e0, 0x7018, 0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, 0x782b, - 0x0026, 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, - 0x9006, 0x700e, 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, 0x0020, - 0x3300, 0x701a, 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, - 0x001e, 0x0005, 0x2009, 0x1a1b, 0x2104, 0xc095, 0x200a, 0x080c, - 0x1117, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1a1b, 0x00f6, 0x2079, - 0x0080, 0x792c, 0xd1bc, 0x190c, 0x0dbe, 0x782b, 0x0002, 0xd1fc, - 0x0120, 0x918c, 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, - 0x0005, 0x1128, 0x11d0, 0x1204, 0x12dc, 0x0dc5, 0x12f7, 0x0dc5, - 0x918c, 0x0700, 0x1550, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8, - 0x7018, 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, - 0x7010, 0x20a8, 0x4005, 0x3400, 0x701a, 0x015e, 0x014e, 0x013e, - 0x700c, 0x9005, 0x0578, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, - 0x116d, 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0100, 0x009e, - 0x7007, 0x0000, 0x080c, 0x1128, 0x0005, 0x7008, 0x0096, 0x2048, - 0xa86f, 0x0200, 0x009e, 0x0ca0, 0x918c, 0x0700, 0x1150, 0x700c, - 0x9005, 0x0180, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x1182, - 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x7007, - 0x0000, 0x0080, 0x0096, 0x7008, 0x2048, 0x7800, 0xa88e, 0x7804, - 0xa892, 0x7808, 0xa896, 0x780c, 0xa89a, 0xa86f, 0x0100, 0x009e, - 0x7007, 0x0000, 0x0096, 0x00d6, 0x7008, 0x2048, 0x2001, 0x18b9, - 0x2004, 0x9906, 0x1128, 0xa89c, 0x080f, 0x00de, 0x009e, 0x00a0, - 0x00de, 0x009e, 0x0096, 0x00d6, 0x7008, 0x2048, 0x0081, 0x0150, - 0xa89c, 0x0086, 0x2940, 0x080f, 0x008e, 0x00de, 0x009e, 0x080c, - 0x1117, 0x0005, 0x00de, 0x009e, 0x080c, 0x1117, 0x0005, 0xa8a8, - 0xd08c, 0x0005, 0x0096, 0xa0a0, 0x904d, 0x090c, 0x0dc5, 0xa06c, - 0x908e, 0x0100, 0x0130, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, - 0x4002, 0x080c, 0x6e92, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x2848, - 0x080c, 0x1040, 0x009e, 0x0005, 0x00a6, 0xa0a0, 0x904d, 0x090c, - 0x0dc5, 0xa06c, 0x908e, 0x0100, 0x0128, 0xa87b, 0x0001, 0xa883, - 0x0000, 0x00c0, 0xa80c, 0x2050, 0xb004, 0x9005, 0x0198, 0xa80e, - 0x2050, 0x8006, 0x8006, 0x8007, 0x908c, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x0002, 0xa076, 0xa172, 0xb000, 0xa07a, 0x2810, 0x080c, - 0x10f8, 0x00e8, 0xa97c, 0xa894, 0x0016, 0x0006, 0x080c, 0x6e92, - 0x000e, 0x001e, 0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060, - 0x080c, 0xb2d3, 0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, 0xa8a3, - 0x0000, 0x080c, 0x1040, 0x7007, 0x0000, 0x080c, 0x1117, 0x00ae, - 0x0005, 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, - 0x7000, 0xc094, 0x7002, 0x012e, 0x0005, 0x0096, 0x2001, 0x192f, - 0x204c, 0xa87c, 0x7812, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, - 0x780a, 0xa898, 0x780e, 0x782b, 0x0020, 0x0126, 0x2091, 0x8000, - 0x782b, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x2900, - 0x700a, 0x012e, 0x009e, 0x0005, 0x20e1, 0x0000, 0x2099, 0x0088, - 0x782b, 0x0040, 0x0096, 0x2001, 0x192f, 0x204c, 0xaa7c, 0x009e, - 0x080c, 0x8d91, 0x2009, 0x188c, 0x2104, 0x9084, 0xfffc, 0x200a, - 0x080c, 0x8bf3, 0x7007, 0x0000, 0x080c, 0x1128, 0x0005, 0x7007, - 0x0000, 0x080c, 0x1128, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, - 0x0300, 0x2071, 0x1a65, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x781b, - 0x4800, 0x00c1, 0x7803, 0x0003, 0x780f, 0x0000, 0x20a9, 0x03ea, - 0x2061, 0xf0ae, 0x2c0d, 0x7912, 0xe104, 0x9ce0, 0x0002, 0x7916, - 0x1f04, 0x1312, 0x7807, 0x0007, 0x7803, 0x0000, 0x7803, 0x0001, - 0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, 0x7808, 0xd09c, 0x0120, - 0x7820, 0x080c, 0x1376, 0x0cc8, 0x2001, 0x1a66, 0x2003, 0x0000, - 0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807, - 0x0007, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, 0x782b, - 0x1a89, 0x781f, 0xff00, 0x781b, 0xb700, 0x2001, 0x0200, 0x2004, - 0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x1a89, 0x602f, 0x1cd0, - 0x2001, 0x181a, 0x2004, 0x9082, 0x1cd0, 0x6032, 0x603b, 0x20c7, - 0x2001, 0x33b6, 0xd0fc, 0x190c, 0x0dc5, 0x2001, 0x1810, 0x2004, - 0xd0c4, 0x1128, 0x2001, 0x0003, 0x2004, 0xd0d4, 0x1118, 0x783f, - 0x33b6, 0x0020, 0x9084, 0xc000, 0x783f, 0xb3b6, 0x604f, 0x193d, - 0x2001, 0x1928, 0x2004, 0x6042, 0x00ce, 0x0005, 0x9086, 0x000d, - 0x11d0, 0x7808, 0xd09c, 0x01b8, 0x7820, 0x0026, 0x2010, 0x080c, - 0xd0c6, 0x0180, 0x2260, 0x6000, 0x9086, 0x0004, 0x1158, 0x0016, - 0x6120, 0x9186, 0x0009, 0x0108, 0x0020, 0x2009, 0x004c, 0x080c, - 0xb352, 0x001e, 0x002e, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908, - 0x9184, 0x0070, 0x190c, 0x0dbe, 0xd19c, 0x0158, 0x7820, 0x908c, - 0xf000, 0x15e8, 0x908a, 0x0024, 0x1a0c, 0x0dc5, 0x0023, 0x012e, - 0x0005, 0x012e, 0x0005, 0x13cf, 0x13cf, 0x13e6, 0x13eb, 0x13ef, - 0x13f4, 0x141c, 0x1420, 0x142e, 0x1432, 0x13cf, 0x14ff, 0x1503, - 0x1575, 0x157c, 0x13cf, 0x157d, 0x157e, 0x1589, 0x1590, 0x13cf, - 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13f6, 0x13cf, - 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13d3, 0x13d1, 0x080c, - 0x0dc5, 0x080c, 0x0dbe, 0x080c, 0x159b, 0x2009, 0x1a7e, 0x2104, - 0x8000, 0x200a, 0x080c, 0x813a, 0x080c, 0x1ad9, 0x0005, 0x2009, - 0x0048, 0x2060, 0x080c, 0xb352, 0x012e, 0x0005, 0x7004, 0xc085, - 0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, 0x080c, - 0x159b, 0x080c, 0x16fb, 0x0005, 0x080c, 0x0dc5, 0x080c, 0x159b, - 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009, - 0x0048, 0x080c, 0xb352, 0x2001, 0x015d, 0x2003, 0x0000, 0x2009, - 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, - 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, 0x15a0, 0x2001, - 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, 0x0005, - 0x080c, 0x159b, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, - 0x009e, 0x2009, 0x0048, 0x080c, 0xb352, 0x0005, 0x080c, 0x159b, - 0x080c, 0x0dc5, 0x080c, 0x159b, 0x080c, 0x14ea, 0x7827, 0x0018, - 0x79ac, 0xd1dc, 0x0904, 0x149b, 0x7827, 0x0015, 0x7828, 0x782b, - 0x0000, 0x9065, 0x0140, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x0804, 0x14a1, 0x7004, 0x9005, 0x01c8, 0x1188, 0x78ab, - 0x0004, 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0dc5, - 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0804, 0x14cf, - 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x1503, 0x0005, 0x7827, - 0x0018, 0xa001, 0x7828, 0x7827, 0x0011, 0xa001, 0x7928, 0x9106, - 0x0110, 0x79ac, 0x08e0, 0x00e6, 0x2071, 0x0200, 0x702c, 0xd0c4, - 0x0140, 0x00ee, 0x080c, 0x1ad9, 0x080c, 0x1322, 0x7803, 0x0001, - 0x0005, 0x7037, 0x0001, 0xa001, 0x7150, 0x00ee, 0x918c, 0xff00, - 0x9186, 0x0500, 0x0110, 0x79ac, 0x0810, 0x7004, 0xc09d, 0x7006, - 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x1503, 0x2001, 0x020d, - 0x2003, 0x0020, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, 0x090c, - 0x0dc5, 0x6014, 0x2048, 0x78ab, 0x0004, 0x918c, 0x0700, 0x01a8, - 0x080c, 0x813a, 0x080c, 0x1ad9, 0x080c, 0xd0d8, 0x0158, 0xa9ac, - 0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, 0xa880, - 0xc0bd, 0xa882, 0x080c, 0xccf3, 0x0005, 0x6020, 0x9086, 0x0009, - 0x1128, 0x2009, 0x004c, 0x080c, 0xb352, 0x0048, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xd4c4, 0x2029, - 0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, - 0x7dbc, 0x080c, 0xf057, 0xd5a4, 0x1118, 0x080c, 0x15a0, 0x0005, - 0x080c, 0x813a, 0x080c, 0x1ad9, 0x0005, 0x781f, 0x0300, 0x7803, - 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, - 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, - 0x080c, 0x1611, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, 0x7004, - 0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, 0x190c, 0x0dc5, - 0xd184, 0x11b1, 0xd19c, 0x0180, 0xc19c, 0x7106, 0x0016, 0x080c, - 0x16de, 0x001e, 0x0148, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x080c, 0x15a0, 0x0005, 0x81ff, 0x190c, 0x0dc5, 0x0005, - 0x2100, 0xc184, 0xc1b4, 0x7106, 0xd0b4, 0x0016, 0x00e6, 0x1904, - 0x156a, 0x2071, 0x0200, 0x080c, 0x16cb, 0x05e0, 0x080c, 0x16de, - 0x05b0, 0x6014, 0x9005, 0x05b0, 0x0096, 0x2048, 0xa864, 0x009e, - 0x9084, 0x00ff, 0x908e, 0x0029, 0x0160, 0x908e, 0x0048, 0x1550, - 0x601c, 0xd084, 0x11e0, 0x00f6, 0x2c78, 0x080c, 0x1768, 0x00fe, - 0x00b0, 0x00f6, 0x2c78, 0x080c, 0x18fd, 0x00fe, 0x2009, 0x01f4, - 0x8109, 0x0168, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, - 0x0218, 0x2004, 0xd0ec, 0x1118, 0x080c, 0x15a0, 0x0040, 0x2001, - 0x020d, 0x2003, 0x0020, 0x080c, 0x1322, 0x7803, 0x0001, 0x00ee, - 0x001e, 0x0005, 0x080c, 0x16de, 0x0dd0, 0x2001, 0x020d, 0x2003, - 0x0050, 0x2003, 0x0020, 0x0461, 0x0c90, 0x0429, 0x2060, 0x2009, - 0x0053, 0x080c, 0xb352, 0x0005, 0x0005, 0x0005, 0x00e1, 0x2008, - 0x00d1, 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, 0x080c, 0x90de, - 0x0005, 0x0089, 0x9005, 0x0118, 0x080c, 0x8ce2, 0x0cd0, 0x0005, - 0x2001, 0x0036, 0x2009, 0x1820, 0x210c, 0x2011, 0x181f, 0x2214, - 0x080c, 0x1611, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, - 0x080c, 0x14ea, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109, - 0x0510, 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000, - 0x79bc, 0xd1a4, 0x1528, 0x79b8, 0x918c, 0x0fff, 0x0180, 0x9182, - 0x0841, 0x1268, 0x9188, 0x0007, 0x918c, 0x0ff8, 0x810c, 0x810c, - 0x810c, 0x080c, 0x1603, 0x6827, 0x0001, 0x8109, 0x1dd0, 0x04d9, - 0x6827, 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, - 0x1500, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1130, 0x08c0, - 0x080c, 0x813a, 0x080c, 0x1ad9, 0x0090, 0x7827, 0x0015, 0x782b, - 0x0000, 0x7827, 0x0018, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, - 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, - 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d30, 0x7827, - 0x0015, 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, 0x9085, 0x1800, - 0x6802, 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005, - 0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, 0x9086, 0x0041, - 0x0005, 0x00f6, 0x2079, 0x0300, 0x0006, 0x7808, 0xd09c, 0x0140, - 0x0016, 0x0026, 0x00c6, 0x080c, 0x1394, 0x00ce, 0x002e, 0x001e, - 0x000e, 0x0006, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x0059, - 0x1118, 0x000e, 0x00fe, 0x0005, 0x000e, 0x792c, 0x3900, 0x8000, - 0x2004, 0x080c, 0x0dc5, 0x2009, 0x180c, 0x2104, 0xc0f4, 0x200a, - 0x2009, 0xff00, 0x8109, 0x0904, 0x168f, 0x7a18, 0x9284, 0x0030, - 0x0904, 0x168a, 0x9284, 0x0048, 0x9086, 0x0008, 0x1904, 0x168a, - 0x2001, 0x0109, 0x2004, 0xd08c, 0x01f0, 0x0006, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x0126, 0x2091, 0x2800, 0x00f6, 0x0026, - 0x0016, 0x2009, 0x1a81, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, - 0x94b1, 0x001e, 0x002e, 0x00fe, 0x012e, 0x015e, 0x014e, 0x013e, - 0x01de, 0x01ce, 0x000e, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x01d0, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x00f6, - 0x0016, 0x2009, 0x1a82, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, - 0x1eeb, 0x001e, 0x00fe, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce, - 0x012e, 0x000e, 0x7818, 0xd0bc, 0x1904, 0x163a, 0x0005, 0x2001, - 0x180c, 0x2004, 0xd0f4, 0x1528, 0x7a18, 0x9284, 0x0030, 0x0508, - 0x9284, 0x0048, 0x9086, 0x0008, 0x11e0, 0x2001, 0x19f7, 0x2004, - 0x9005, 0x01b8, 0x2001, 0x1a69, 0x2004, 0x9086, 0x0000, 0x0188, - 0x2009, 0x1a80, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, 0xa767, - 0x2009, 0x180c, 0x2104, 0xc0f5, 0x200a, 0x2009, 0xff00, 0x0804, - 0x163a, 0x9085, 0x0001, 0x0005, 0x7832, 0x7936, 0x7a3a, 0x781b, - 0x8080, 0x080c, 0x1633, 0x1108, 0x0005, 0x792c, 0x3900, 0x8000, - 0x2004, 0x080c, 0x0dc5, 0x7037, 0x0001, 0x7150, 0x7037, 0x0002, - 0x7050, 0x2060, 0xd1bc, 0x1110, 0x7054, 0x2060, 0x918c, 0xff00, - 0x9186, 0x0500, 0x0110, 0x9085, 0x0001, 0x0005, 0x0006, 0x0046, - 0x00e6, 0x2071, 0x0200, 0x7037, 0x0002, 0x7058, 0x9084, 0xff00, - 0x8007, 0x9086, 0x00bc, 0x1158, 0x2021, 0x1a7f, 0x2404, 0x8000, - 0x0208, 0x2022, 0x080c, 0x813a, 0x080c, 0x1ad9, 0x9006, 0x00ee, - 0x004e, 0x000e, 0x0005, 0x0c11, 0x1108, 0x0005, 0x00e6, 0x0016, - 0x2071, 0x0200, 0x0841, 0x6124, 0xd1dc, 0x01f8, 0x701c, 0xd08c, - 0x0904, 0x175d, 0x7017, 0x0000, 0x2001, 0x0264, 0x2004, 0xd0bc, - 0x0904, 0x175d, 0x2001, 0x0268, 0x00c6, 0x2064, 0x6104, 0x6038, - 0x00ce, 0x918e, 0x0039, 0x1904, 0x175d, 0x9c06, 0x15f0, 0x0126, - 0x2091, 0x2600, 0x080c, 0x8081, 0x012e, 0x7358, 0x745c, 0x6014, - 0x905d, 0x0598, 0x2b48, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x190c, 0xd49f, 0xab42, 0xac3e, 0x2001, 0x1869, 0x2004, - 0xd0b4, 0x1170, 0x601c, 0xd0e4, 0x1158, 0x6010, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0bc, 0x1120, 0xa83b, 0x7fff, 0xa837, 0xffff, - 0x080c, 0x20e7, 0x1190, 0x080c, 0x195a, 0x2a00, 0xa816, 0x0130, - 0x2800, 0xa80e, 0x2c05, 0xa80a, 0x2c00, 0xa812, 0x7037, 0x0020, - 0x781f, 0x0300, 0x001e, 0x00ee, 0x0005, 0x7037, 0x0050, 0x7037, - 0x0020, 0x001e, 0x00ee, 0x080c, 0x15a0, 0x0005, 0x080c, 0x0dc5, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x190c, 0x6b5e, 0x2ff0, 0x0126, - 0x2091, 0x2200, 0x0016, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, - 0x903e, 0x2730, 0xa864, 0x2068, 0xa81a, 0x9d84, 0x000f, 0x9088, - 0x20c7, 0x2165, 0x0002, 0x179a, 0x1808, 0x179a, 0x179a, 0x179e, - 0x17e9, 0x179a, 0x17be, 0x1793, 0x17ff, 0x179a, 0x179a, 0x17a3, - 0x18f5, 0x17d2, 0x17c8, 0xa964, 0x918c, 0x00ff, 0x918e, 0x0048, - 0x0904, 0x17ff, 0x9085, 0x0001, 0x0804, 0x18eb, 0xa87c, 0xd0ac, - 0x0dc8, 0x0804, 0x180f, 0xa87c, 0xd0ac, 0x0da0, 0x0804, 0x187a, - 0xa898, 0x901d, 0x1108, 0xab9c, 0x9016, 0xaab2, 0xaa3e, 0xaa42, - 0x3e00, 0x9080, 0x0008, 0x2004, 0x9080, 0x933d, 0x2005, 0x9005, - 0x090c, 0x0dc5, 0x2004, 0xa8ae, 0x0804, 0x18d3, 0xa87c, 0xd0bc, - 0x09c8, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x180f, - 0xa87c, 0xd0bc, 0x0978, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, - 0x0804, 0x187a, 0xa87c, 0xd0bc, 0x0928, 0xa890, 0xa842, 0xa88c, - 0xa83e, 0xa804, 0x9045, 0x090c, 0x0dc5, 0xa164, 0xa91a, 0x91ec, - 0x000f, 0x9d80, 0x20c7, 0x2065, 0xa888, 0xd19c, 0x1904, 0x187a, - 0x0430, 0xa87c, 0xd0ac, 0x0904, 0x179a, 0xa804, 0x9045, 0x090c, - 0x0dc5, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x20c7, 0x2065, - 0x9006, 0xa842, 0xa83e, 0xd19c, 0x1904, 0x187a, 0x0080, 0xa87c, - 0xd0ac, 0x0904, 0x179a, 0x9006, 0xa842, 0xa83e, 0x0804, 0x187a, - 0xa87c, 0xd0ac, 0x0904, 0x179a, 0x9006, 0xa842, 0xa83e, 0x2c05, - 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002, 0x1832, - 0x1832, 0x1834, 0x1832, 0x1832, 0x1832, 0x183e, 0x1832, 0x1832, - 0x1832, 0x1848, 0x1832, 0x1832, 0x1832, 0x1852, 0x1832, 0x1832, - 0x1832, 0x185c, 0x1832, 0x1832, 0x1832, 0x1866, 0x1832, 0x1832, - 0x1832, 0x1870, 0x080c, 0x0dc5, 0xa574, 0xa478, 0x9d86, 0x0024, - 0x0904, 0x17a8, 0xa37c, 0xa280, 0x0804, 0x18d3, 0xa584, 0xa488, - 0x9d86, 0x0024, 0x0904, 0x17a8, 0xa38c, 0xa290, 0x0804, 0x18d3, - 0xa594, 0xa498, 0x9d86, 0x0024, 0x0904, 0x17a8, 0xa39c, 0xa2a0, - 0x0804, 0x18d3, 0xa5a4, 0xa4a8, 0x9d86, 0x0024, 0x0904, 0x17a8, - 0xa3ac, 0xa2b0, 0x0804, 0x18d3, 0xa5b4, 0xa4b8, 0x9d86, 0x0024, - 0x0904, 0x17a8, 0xa3bc, 0xa2c0, 0x0804, 0x18d3, 0xa5c4, 0xa4c8, - 0x9d86, 0x0024, 0x0904, 0x17a8, 0xa3cc, 0xa2d0, 0x0804, 0x18d3, - 0xa5d4, 0xa4d8, 0x9d86, 0x0024, 0x0904, 0x17a8, 0xa3dc, 0xa2e0, - 0x0804, 0x18d3, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x189d, 0x189b, 0x189b, 0x189b, 0x189b, 0x189b, - 0x18a8, 0x189b, 0x189b, 0x189b, 0x189b, 0x189b, 0x18b3, 0x189b, - 0x189b, 0x189b, 0x189b, 0x189b, 0x18be, 0x189b, 0x189b, 0x189b, - 0x189b, 0x189b, 0x18c9, 0x080c, 0x0dc5, 0xa56c, 0xa470, 0xa774, - 0xa678, 0x9d86, 0x002c, 0x0904, 0x17a8, 0xa37c, 0xa280, 0x0458, - 0xa584, 0xa488, 0xa78c, 0xa690, 0x9d86, 0x002c, 0x0904, 0x17a8, - 0xa394, 0xa298, 0x0400, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86, - 0x002c, 0x0904, 0x17a8, 0xa3ac, 0xa2b0, 0x00a8, 0xa5b4, 0xa4b8, - 0xa7bc, 0xa6c0, 0x9d86, 0x002c, 0x0904, 0x17a8, 0xa3c4, 0xa2c8, - 0x0050, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0x9d86, 0x002c, 0x0904, - 0x17a8, 0xa3dc, 0xa2e0, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, - 0xae2a, 0xa988, 0x8c60, 0x2c1d, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, - 0x8109, 0xa916, 0x1160, 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, - 0xc0dd, 0xa87e, 0x9006, 0x00ce, 0x001e, 0x012e, 0x0005, 0x2800, - 0xa80e, 0xab0a, 0x2c00, 0xa812, 0x0c70, 0x0804, 0x179a, 0x2001, - 0x180d, 0x2004, 0xd08c, 0x190c, 0x6b5e, 0x2ff0, 0x0126, 0x2091, - 0x2200, 0x0016, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0xa80e, - 0x2061, 0x20c2, 0xa813, 0x20c2, 0x2c05, 0xa80a, 0xa964, 0xa91a, - 0xa87c, 0xd0ac, 0x090c, 0x0dc5, 0x9006, 0xa842, 0xa83e, 0x2c05, - 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0xadcc, 0xacd0, 0xafd4, 0xaed8, - 0xabdc, 0xaae0, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, - 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0xa988, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0008, 0x1120, 0x8109, 0xa916, 0x0128, 0x0080, 0x918a, - 0x0002, 0xa916, 0x1160, 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, - 0xc0dd, 0xa87e, 0x9006, 0x00ce, 0x001e, 0x012e, 0x0005, 0xa804, - 0x9045, 0x090c, 0x0dc5, 0xa80e, 0xa064, 0xa81a, 0x9084, 0x000f, - 0x9080, 0x20c7, 0x2015, 0x82ff, 0x090c, 0x0dc5, 0xaa12, 0x2205, - 0xa80a, 0x0c08, 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, - 0x0002, 0x1a4f, 0x19b1, 0x19b1, 0x1a4f, 0x1a4f, 0x1a49, 0x1a4f, - 0x19b1, 0x1a00, 0x1a00, 0x1a00, 0x1a4f, 0x1a4f, 0x1a4f, 0x1a46, - 0x1a00, 0xc0fc, 0xa882, 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, - 0x0904, 0x1a51, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x199d, 0x199b, 0x199b, 0x199b, 0x199b, 0x199b, - 0x19a1, 0x199b, 0x199b, 0x199b, 0x199b, 0x199b, 0x19a5, 0x199b, - 0x199b, 0x199b, 0x199b, 0x199b, 0x19a9, 0x199b, 0x199b, 0x199b, - 0x199b, 0x199b, 0x19ad, 0x080c, 0x0dc5, 0xa774, 0xa678, 0x0804, - 0x1a51, 0xa78c, 0xa690, 0x0804, 0x1a51, 0xa7a4, 0xa6a8, 0x0804, - 0x1a51, 0xa7bc, 0xa6c0, 0x0804, 0x1a51, 0xa7d4, 0xa6d8, 0x0804, - 0x1a51, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, - 0x0002, 0x19d4, 0x19d4, 0x19d6, 0x19d4, 0x19d4, 0x19d4, 0x19dc, - 0x19d4, 0x19d4, 0x19d4, 0x19e2, 0x19d4, 0x19d4, 0x19d4, 0x19e8, - 0x19d4, 0x19d4, 0x19d4, 0x19ee, 0x19d4, 0x19d4, 0x19d4, 0x19f4, - 0x19d4, 0x19d4, 0x19d4, 0x19fa, 0x080c, 0x0dc5, 0xa574, 0xa478, - 0xa37c, 0xa280, 0x0804, 0x1a51, 0xa584, 0xa488, 0xa38c, 0xa290, - 0x0804, 0x1a51, 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x1a51, - 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, 0x1a51, 0xa5b4, 0xa4b8, - 0xa3bc, 0xa2c0, 0x0804, 0x1a51, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, - 0x0804, 0x1a51, 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x1a51, - 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002, - 0x1a23, 0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a2a, 0x1a21, - 0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a31, 0x1a21, 0x1a21, 0x1a21, - 0x1a21, 0x1a21, 0x1a38, 0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a21, - 0x1a3f, 0x080c, 0x0dc5, 0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c, - 0xa280, 0x0438, 0xa584, 0xa488, 0xa78c, 0xa690, 0xa394, 0xa298, - 0x0400, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x00c8, - 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, 0xa2c8, 0x0090, 0xa5cc, - 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0, 0x0058, 0x9d86, 0x000e, - 0x1130, 0x080c, 0x207f, 0x1904, 0x195a, 0x900e, 0x0050, 0x080c, - 0x0dc5, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0x080c, - 0x207f, 0x0005, 0x6014, 0x2048, 0x6118, 0x81ff, 0x0148, 0x810c, - 0x810c, 0x810c, 0x81ff, 0x1118, 0xa887, 0x0001, 0x0008, 0xa986, - 0x601b, 0x0002, 0xa874, 0x9084, 0x00ff, 0x9084, 0x0008, 0x0150, - 0x00e9, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, - 0xb352, 0x0005, 0xa974, 0xd1dc, 0x1108, 0x0005, 0xa934, 0xa88c, - 0x9106, 0x1158, 0xa938, 0xa890, 0x9106, 0x1138, 0x601c, 0xc084, - 0x601e, 0x2009, 0x0048, 0x0804, 0xb352, 0x0005, 0x0126, 0x00c6, - 0x2091, 0x2200, 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, - 0x05b0, 0x9186, 0x0003, 0x0598, 0x6020, 0x6023, 0x0000, 0x0006, - 0x2031, 0x0008, 0x00c6, 0x781f, 0x0808, 0x7808, 0xd09c, 0x0120, - 0x080c, 0x1394, 0x8631, 0x1db8, 0x00ce, 0x781f, 0x0800, 0x2031, - 0x0168, 0x00c6, 0x7808, 0xd09c, 0x190c, 0x1394, 0x00ce, 0x2001, - 0x0038, 0x080c, 0x1b69, 0x7930, 0x9186, 0x0040, 0x0160, 0x9186, - 0x0042, 0x190c, 0x0dc5, 0x2001, 0x001e, 0x8001, 0x1df0, 0x8631, - 0x1d40, 0x080c, 0x1b78, 0x000e, 0x6022, 0x012e, 0x0005, 0x080c, - 0x1b65, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db8, 0x782b, 0x0000, - 0x0ca0, 0x00f6, 0x2079, 0x0300, 0x7803, 0x0000, 0x78ab, 0x0004, - 0x2001, 0xf000, 0x8001, 0x090c, 0x0dc5, 0x7aac, 0xd2ac, 0x1dd0, - 0x00fe, 0x080c, 0x7637, 0x1188, 0x2001, 0x0138, 0x2003, 0x0000, - 0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, 0xa001, 0xa001, - 0x8211, 0x1de0, 0x0059, 0x0804, 0x76e4, 0x0479, 0x0039, 0x2001, - 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, - 0x0200, 0x080c, 0x2c6d, 0x2009, 0x003c, 0x080c, 0x2409, 0x2001, - 0x015d, 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, - 0x8725, 0x70a0, 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, - 0x020d, 0x2003, 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x1322, - 0x7803, 0x0001, 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, - 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, - 0x7637, 0x1108, 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, - 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, - 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, - 0x015d, 0x2003, 0x0000, 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, - 0x0048, 0xa001, 0xa001, 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, - 0x1db0, 0x004e, 0x0c60, 0x004e, 0x0c40, 0x601c, 0xc084, 0x601e, - 0x0005, 0x2c08, 0x621c, 0x080c, 0x1611, 0x7930, 0x0005, 0x2c08, - 0x621c, 0x080c, 0x16bc, 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, - 0x2031, 0x0064, 0x781c, 0x9084, 0x0007, 0x0170, 0x2001, 0x0038, - 0x0c41, 0x9186, 0x0040, 0x0904, 0x1bd6, 0x2001, 0x001e, 0x0c69, - 0x8631, 0x1d80, 0x080c, 0x0dc5, 0x781f, 0x0202, 0x2001, 0x015d, - 0x2003, 0x0000, 0x2001, 0x0dac, 0x0c01, 0x781c, 0xd084, 0x0110, - 0x0861, 0x04e0, 0x2001, 0x0030, 0x0891, 0x9186, 0x0040, 0x0568, - 0x781c, 0xd084, 0x1da8, 0x781f, 0x0101, 0x2001, 0x0014, 0x0869, - 0x2001, 0x0037, 0x0821, 0x9186, 0x0040, 0x0140, 0x2001, 0x0030, - 0x080c, 0x1b6f, 0x9186, 0x0040, 0x190c, 0x0dc5, 0x00d6, 0x2069, - 0x0200, 0x692c, 0xd1f4, 0x1170, 0xd1c4, 0x0160, 0xd19c, 0x0130, - 0x6800, 0x9085, 0x1800, 0x6802, 0x00de, 0x0080, 0x6908, 0x9184, - 0x0007, 0x1db0, 0x00de, 0x781f, 0x0100, 0x791c, 0x9184, 0x0007, - 0x090c, 0x0dc5, 0xa001, 0xa001, 0x781f, 0x0200, 0x0005, 0x0126, - 0x2091, 0x2400, 0x2071, 0x1a69, 0x2079, 0x0090, 0x012e, 0x0005, - 0x9280, 0x0005, 0x2004, 0x2048, 0xa97c, 0xd1dc, 0x1904, 0x1c78, - 0xa964, 0x9184, 0x0007, 0x0002, 0x1bf4, 0x1c63, 0x1c0b, 0x1c0d, - 0x1c0b, 0x1c4b, 0x1c2b, 0x1c1a, 0x918c, 0x00ff, 0x9186, 0x0008, - 0x1170, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0x9006, 0xa842, 0xa83e, - 0xa988, 0x2900, 0xa85a, 0xa813, 0x20c2, 0x0804, 0x1c74, 0x9186, - 0x0048, 0x0904, 0x1c63, 0x080c, 0x0dc5, 0x9184, 0x00ff, 0x9086, - 0x0013, 0x0904, 0x1c63, 0x9184, 0x00ff, 0x9086, 0x001b, 0x0904, - 0x1c63, 0x0c88, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa890, 0xa842, - 0xa83a, 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, - 0xa988, 0x0804, 0x1c6b, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, - 0x19d0, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa890, 0xa842, 0xa83a, - 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0xa804, - 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x20c7, 0x2005, - 0xa812, 0xa988, 0x0448, 0x918c, 0x00ff, 0x9186, 0x0015, 0x1540, - 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa804, 0xa85a, 0x2040, 0xa064, - 0x9084, 0x000f, 0x9080, 0x20c7, 0x2005, 0xa812, 0xa988, 0x9006, - 0xa842, 0xa83e, 0x0088, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa988, - 0x9006, 0xa842, 0xa83e, 0x2900, 0xa85a, 0xa864, 0x9084, 0x000f, - 0x9080, 0x20c7, 0x2005, 0xa812, 0xa916, 0xa87c, 0xc0dd, 0xa87e, - 0x0005, 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, 0x1eeb, - 0x00e6, 0x2071, 0x1a69, 0x7000, 0x9005, 0x1904, 0x1cdf, 0x7206, - 0x9280, 0x0005, 0x204c, 0x9280, 0x0004, 0x2004, 0x782b, 0x0004, - 0x00f6, 0x2079, 0x0200, 0x7803, 0x0040, 0x00fe, 0x00b6, 0x2058, - 0xb86c, 0x7836, 0xb890, 0x00be, 0x00f6, 0x2079, 0x0200, 0x7803, - 0x0040, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x781a, - 0x78d7, 0x0000, 0x00fe, 0xa814, 0x2050, 0xa858, 0x2040, 0xa810, - 0x2060, 0xa064, 0x90ec, 0x000f, 0xa944, 0x791a, 0x7116, 0xa848, - 0x781e, 0x701a, 0x9006, 0x700e, 0x7012, 0x7004, 0xa940, 0xa838, - 0x9106, 0x1500, 0xa93c, 0xa834, 0x9106, 0x11e0, 0x0006, 0x0016, - 0xa938, 0xa834, 0x9105, 0x0118, 0x001e, 0x000e, 0x0098, 0x001e, - 0x000e, 0x8aff, 0x01c8, 0x0126, 0x2091, 0x8000, 0x2009, 0x0306, - 0x200b, 0x0808, 0x00d9, 0x0108, 0x00c9, 0x012e, 0x9006, 0x00ee, - 0x00fe, 0x0005, 0x0036, 0x0046, 0xab38, 0xac34, 0x080c, 0x20e7, - 0x004e, 0x003e, 0x0d30, 0x0c98, 0x9085, 0x0001, 0x0c80, 0x2009, - 0x0306, 0x200b, 0x4800, 0x7027, 0x0000, 0x0005, 0x0076, 0x0066, - 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x1e9e, 0x700c, - 0x7214, 0x923a, 0x7010, 0x7218, 0x9203, 0x0a04, 0x1e9d, 0x9705, - 0x0904, 0x1e9d, 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, - 0x0002, 0x1e22, 0x1d61, 0x1d61, 0x1e22, 0x1e22, 0x1dff, 0x1e22, - 0x1d61, 0x1e06, 0x1db0, 0x1db0, 0x1e22, 0x1e22, 0x1e22, 0x1df9, - 0x1db0, 0xc0fc, 0xa882, 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, - 0x0904, 0x1e2f, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x1d4d, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, - 0x1d51, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d55, 0x1d4b, - 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d59, 0x1d4b, 0x1d4b, 0x1d4b, - 0x1d4b, 0x1d4b, 0x1d5d, 0x080c, 0x0dc5, 0xa774, 0xa678, 0x0804, - 0x1e2f, 0xa78c, 0xa690, 0x0804, 0x1e2f, 0xa7a4, 0xa6a8, 0x0804, - 0x1e2f, 0xa7bc, 0xa6c0, 0x0804, 0x1e2f, 0xa7d4, 0xa6d8, 0x0804, - 0x1e2f, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, - 0x0002, 0x1d84, 0x1d84, 0x1d86, 0x1d84, 0x1d84, 0x1d84, 0x1d8c, - 0x1d84, 0x1d84, 0x1d84, 0x1d92, 0x1d84, 0x1d84, 0x1d84, 0x1d98, - 0x1d84, 0x1d84, 0x1d84, 0x1d9e, 0x1d84, 0x1d84, 0x1d84, 0x1da4, - 0x1d84, 0x1d84, 0x1d84, 0x1daa, 0x080c, 0x0dc5, 0xa574, 0xa478, - 0xa37c, 0xa280, 0x0804, 0x1e2f, 0xa584, 0xa488, 0xa38c, 0xa290, - 0x0804, 0x1e2f, 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x1e2f, - 0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, 0x1e2f, 0xa5b4, 0xa4b8, - 0xa3bc, 0xa2c0, 0x0804, 0x1e2f, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, - 0x0804, 0x1e2f, 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x1e2f, - 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002, - 0x1dd3, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1ddb, 0x1dd1, - 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1de3, 0x1dd1, 0x1dd1, 0x1dd1, - 0x1dd1, 0x1dd1, 0x1deb, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, - 0x1df2, 0x080c, 0x0dc5, 0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c, - 0xa280, 0x0804, 0x1e2f, 0xa584, 0xa488, 0xa78c, 0xa690, 0xa394, - 0xa298, 0x0804, 0x1e2f, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac, - 0xa2b0, 0x0804, 0x1e2f, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, - 0xa2c8, 0x04e8, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0, - 0x04b0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x1518, 0x080c, - 0x207f, 0x1904, 0x1cfc, 0x900e, 0x0804, 0x1e9e, 0xab64, 0x939c, - 0x00ff, 0x9386, 0x0048, 0x1180, 0x00c6, 0x7004, 0x2060, 0x6004, - 0x9086, 0x0043, 0x00ce, 0x0904, 0x1db0, 0xab9c, 0x9016, 0xad8c, - 0xac90, 0xaf94, 0xae98, 0x0098, 0x9386, 0x0008, 0x0904, 0x1db0, - 0x080c, 0x0dc5, 0xa964, 0x918c, 0x00ff, 0x9186, 0x0013, 0x0904, - 0x1d61, 0x9186, 0x001b, 0x0904, 0x1db0, 0x080c, 0x0dc5, 0x2009, - 0x030f, 0x2104, 0xd0fc, 0x0538, 0x0066, 0x2009, 0x0306, 0x2134, - 0x200b, 0x4000, 0x2104, 0x9084, 0x0030, 0x15b8, 0x2031, 0x1000, - 0x2600, 0x9302, 0x928b, 0x0000, 0xa82e, 0xa932, 0x0278, 0x9105, - 0x0168, 0x2011, 0x0000, 0x2618, 0x2600, 0x9500, 0xa81e, 0x9481, - 0x0000, 0xa822, 0xa880, 0xc0fd, 0xa882, 0x0020, 0xa82f, 0x0000, - 0xa833, 0x0000, 0x006e, 0x7b12, 0x7a16, 0x7d02, 0x7c06, 0x7f0a, - 0x7e0e, 0x782b, 0x0001, 0x7000, 0x8000, 0x7002, 0xa83c, 0x9300, - 0xa83e, 0xa840, 0x9201, 0xa842, 0x700c, 0x9300, 0x700e, 0x7010, - 0x9201, 0x7012, 0x080c, 0x207f, 0x0448, 0xd6b4, 0x0110, 0x200b, - 0x4040, 0x2031, 0x0080, 0x9584, 0x007f, 0x0108, 0x9632, 0x7124, - 0x7000, 0x9086, 0x0000, 0x1198, 0xc185, 0x7126, 0x2009, 0x0306, - 0x2104, 0xd0b4, 0x1904, 0x1e40, 0x200b, 0x4040, 0x2009, 0x1a83, - 0x2104, 0x8000, 0x0a04, 0x1e40, 0x200a, 0x0804, 0x1e40, 0xc18d, - 0x7126, 0xd184, 0x1d58, 0x0804, 0x1e40, 0x9006, 0x002e, 0x003e, - 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x0dc5, 0x0026, - 0x2001, 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7003, 0x0000, - 0x7004, 0x2060, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0118, 0xa880, - 0xc0bd, 0xa882, 0x782c, 0xd0ac, 0x1de8, 0x080c, 0x1cef, 0x6020, - 0x9086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, - 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0xa89a, 0x60c8, - 0xa896, 0x7004, 0x2060, 0x00c6, 0x080c, 0xccf3, 0x00ce, 0x2001, - 0x19f7, 0x2004, 0x9c06, 0x1160, 0x2009, 0x0040, 0x080c, 0x2409, - 0x080c, 0xac2b, 0x2011, 0x0000, 0x080c, 0xaac9, 0x080c, 0x9bd3, - 0x002e, 0x0804, 0x202f, 0x0126, 0x2091, 0x2400, 0xa858, 0x2040, - 0x792c, 0x782b, 0x0002, 0x9184, 0x0700, 0x1904, 0x1ea7, 0x7000, - 0x0002, 0x202f, 0x1efd, 0x1f7d, 0x202d, 0x8001, 0x7002, 0x7027, - 0x0000, 0xd19c, 0x1158, 0x8aff, 0x0904, 0x1f4a, 0x080c, 0x1cf6, - 0x0904, 0x202f, 0x080c, 0x1cf6, 0x0804, 0x202f, 0x782b, 0x0004, - 0xd194, 0x0148, 0xa880, 0xc0fc, 0xa882, 0x8aff, 0x1518, 0xa87c, - 0xc0f5, 0xa87e, 0x00f8, 0x0026, 0x0036, 0xab3c, 0xaa40, 0x0016, - 0x7910, 0xa82c, 0x9100, 0xa82e, 0x7914, 0xa830, 0x9101, 0xa832, - 0x001e, 0x7810, 0x931a, 0x7814, 0x9213, 0x7800, 0xa81e, 0x7804, - 0xa822, 0xab3e, 0xaa42, 0x003e, 0x002e, 0x080c, 0x209a, 0xa880, - 0xc0fd, 0xa882, 0x2a00, 0xa816, 0x2800, 0xa85a, 0x2c00, 0xa812, - 0x7003, 0x0000, 0x2009, 0x0306, 0x200b, 0x4800, 0x7027, 0x0000, - 0x0804, 0x202f, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, - 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816, - 0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x0dc5, 0x7820, 0xd0bc, - 0x1dd0, 0x003e, 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006, 0x0016, - 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, 0x1984, - 0x9085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x782b, 0x0008, 0x7003, - 0x0000, 0x080c, 0x1cef, 0x0804, 0x202f, 0x8001, 0x7002, 0x7024, - 0x8004, 0x7026, 0xd194, 0x0170, 0x782c, 0xd0fc, 0x1904, 0x1ef0, - 0xd19c, 0x1904, 0x202b, 0x8aff, 0x0904, 0x202f, 0x080c, 0x1cf6, - 0x0804, 0x202f, 0x0026, 0x0036, 0xab3c, 0xaa40, 0x080c, 0x209a, - 0xdd9c, 0x1904, 0x1fea, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5, - 0x9082, 0x001b, 0x0002, 0x1fbe, 0x1fbe, 0x1fc0, 0x1fbe, 0x1fbe, - 0x1fbe, 0x1fc6, 0x1fbe, 0x1fbe, 0x1fbe, 0x1fcc, 0x1fbe, 0x1fbe, - 0x1fbe, 0x1fd2, 0x1fbe, 0x1fbe, 0x1fbe, 0x1fd8, 0x1fbe, 0x1fbe, - 0x1fbe, 0x1fde, 0x1fbe, 0x1fbe, 0x1fbe, 0x1fe4, 0x080c, 0x0dc5, - 0xa07c, 0x931a, 0xa080, 0x9213, 0x0804, 0x1f1f, 0xa08c, 0x931a, - 0xa090, 0x9213, 0x0804, 0x1f1f, 0xa09c, 0x931a, 0xa0a0, 0x9213, - 0x0804, 0x1f1f, 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1f1f, - 0xa0bc, 0x931a, 0xa0c0, 0x9213, 0x0804, 0x1f1f, 0xa0cc, 0x931a, - 0xa0d0, 0x9213, 0x0804, 0x1f1f, 0xa0dc, 0x931a, 0xa0e0, 0x9213, - 0x0804, 0x1f1f, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x200d, 0x200b, 0x200b, 0x200b, 0x200b, 0x200b, - 0x2013, 0x200b, 0x200b, 0x200b, 0x200b, 0x200b, 0x2019, 0x200b, - 0x200b, 0x200b, 0x200b, 0x200b, 0x201f, 0x200b, 0x200b, 0x200b, - 0x200b, 0x200b, 0x2025, 0x080c, 0x0dc5, 0xa07c, 0x931a, 0xa080, - 0x9213, 0x0804, 0x1f1f, 0xa094, 0x931a, 0xa098, 0x9213, 0x0804, - 0x1f1f, 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1f1f, 0xa0c4, - 0x931a, 0xa0c8, 0x9213, 0x0804, 0x1f1f, 0xa0dc, 0x931a, 0xa0e0, - 0x9213, 0x0804, 0x1f1f, 0x0804, 0x1f1b, 0x080c, 0x0dc5, 0x012e, - 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a69, 0x7000, 0x9086, 0x0000, - 0x0904, 0x207a, 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, 0xd194, - 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, 0x080c, - 0xf0a0, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0dc5, 0x0016, - 0x2009, 0x0040, 0x080c, 0x2409, 0x001e, 0x2001, 0x020c, 0x2102, - 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, - 0x2009, 0x0040, 0x080c, 0x2409, 0x782c, 0xd0fc, 0x09a8, 0x080c, - 0x1eeb, 0x7000, 0x9086, 0x0000, 0x1978, 0x782b, 0x0004, 0x782c, - 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2409, 0x782b, 0x0002, - 0x7003, 0x0000, 0x080c, 0x1cef, 0x00ee, 0x00fe, 0x0005, 0xa880, - 0xd0fc, 0x11a8, 0x8c60, 0x2c05, 0x9005, 0x0110, 0x8a51, 0x0005, - 0xa004, 0x9005, 0x0168, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, - 0x9080, 0x20c7, 0x2065, 0x8cff, 0x090c, 0x0dc5, 0x8a51, 0x0005, - 0x2050, 0x0005, 0xa880, 0xd0fc, 0x11b8, 0x8a50, 0x8c61, 0x2c05, - 0x9005, 0x1190, 0x2800, 0x9906, 0x0120, 0xa000, 0x9005, 0x1108, - 0x2900, 0x2040, 0xa85a, 0xa064, 0x9084, 0x000f, 0x9080, 0x20d7, - 0x2065, 0x8cff, 0x090c, 0x0dc5, 0x0005, 0x0000, 0x001d, 0x0021, - 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, 0x0021, - 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, 0x0023, 0x0000, 0x0000, - 0x20ba, 0x20b6, 0x20ba, 0x20ba, 0x20c4, 0x0000, 0x20ba, 0x20c1, - 0x20c1, 0x20be, 0x20c1, 0x20c1, 0x0000, 0x20c4, 0x20c1, 0x0000, - 0x20bc, 0x20bc, 0x0000, 0x20bc, 0x20c4, 0x0000, 0x20bc, 0x20c2, - 0x20c2, 0x20c2, 0x0000, 0x20c2, 0x0000, 0x20c4, 0x20c2, 0x00c6, - 0x00d6, 0x0086, 0xab42, 0xac3e, 0xa888, 0x9055, 0x0904, 0x22c6, - 0x2940, 0xa064, 0x90ec, 0x000f, 0x9084, 0x00ff, 0x9086, 0x0008, - 0x1118, 0x2061, 0x20c2, 0x00d0, 0x9de0, 0x20c7, 0x9d86, 0x0007, - 0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f, 0x1120, 0xa08c, - 0x9422, 0xa090, 0x931b, 0x2c05, 0x9065, 0x1140, 0x0310, 0x0804, - 0x22c6, 0xa004, 0x9045, 0x0904, 0x22c6, 0x08d8, 0x2c05, 0x9005, - 0x0904, 0x21ae, 0xdd9c, 0x1904, 0x216a, 0x908a, 0x0036, 0x1a0c, - 0x0dc5, 0x9082, 0x001b, 0x0002, 0x213f, 0x213f, 0x2141, 0x213f, - 0x213f, 0x213f, 0x2147, 0x213f, 0x213f, 0x213f, 0x214d, 0x213f, - 0x213f, 0x213f, 0x2153, 0x213f, 0x213f, 0x213f, 0x2159, 0x213f, - 0x213f, 0x213f, 0x215f, 0x213f, 0x213f, 0x213f, 0x2165, 0x080c, - 0x0dc5, 0xa07c, 0x9422, 0xa080, 0x931b, 0x0804, 0x21a4, 0xa08c, - 0x9422, 0xa090, 0x931b, 0x0804, 0x21a4, 0xa09c, 0x9422, 0xa0a0, - 0x931b, 0x0804, 0x21a4, 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0804, - 0x21a4, 0xa0bc, 0x9422, 0xa0c0, 0x931b, 0x0804, 0x21a4, 0xa0cc, - 0x9422, 0xa0d0, 0x931b, 0x0804, 0x21a4, 0xa0dc, 0x9422, 0xa0e0, - 0x931b, 0x04d0, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, 0x001b, - 0x0002, 0x218c, 0x218a, 0x218a, 0x218a, 0x218a, 0x218a, 0x2191, - 0x218a, 0x218a, 0x218a, 0x218a, 0x218a, 0x2196, 0x218a, 0x218a, - 0x218a, 0x218a, 0x218a, 0x219b, 0x218a, 0x218a, 0x218a, 0x218a, - 0x218a, 0x21a0, 0x080c, 0x0dc5, 0xa07c, 0x9422, 0xa080, 0x931b, - 0x0098, 0xa094, 0x9422, 0xa098, 0x931b, 0x0070, 0xa0ac, 0x9422, - 0xa0b0, 0x931b, 0x0048, 0xa0c4, 0x9422, 0xa0c8, 0x931b, 0x0020, - 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x0630, 0x2300, 0x9405, 0x0160, - 0x8a51, 0x0904, 0x22c6, 0x8c60, 0x0804, 0x2116, 0xa004, 0x9045, - 0x0904, 0x22c6, 0x0804, 0x20f1, 0x8a51, 0x0904, 0x22c6, 0x8c60, - 0x2c05, 0x9005, 0x1158, 0xa004, 0x9045, 0x0904, 0x22c6, 0xa064, - 0x90ec, 0x000f, 0x9de0, 0x20c7, 0x2c05, 0x2060, 0xa880, 0xc0fc, - 0xa882, 0x0804, 0x22bb, 0x2c05, 0x8422, 0x8420, 0x831a, 0x9399, - 0x0000, 0xac2e, 0xab32, 0xdd9c, 0x1904, 0x2258, 0x9082, 0x001b, - 0x0002, 0x21f4, 0x21f4, 0x21f6, 0x21f4, 0x21f4, 0x21f4, 0x2204, - 0x21f4, 0x21f4, 0x21f4, 0x2212, 0x21f4, 0x21f4, 0x21f4, 0x2220, - 0x21f4, 0x21f4, 0x21f4, 0x222e, 0x21f4, 0x21f4, 0x21f4, 0x223c, - 0x21f4, 0x21f4, 0x21f4, 0x224a, 0x080c, 0x0dc5, 0xa17c, 0x2400, - 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa074, 0x9420, - 0xa078, 0x9319, 0x0804, 0x22b6, 0xa18c, 0x2400, 0x9122, 0xa190, - 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa084, 0x9420, 0xa088, 0x9319, - 0x0804, 0x22b6, 0xa19c, 0x2400, 0x9122, 0xa1a0, 0x2300, 0x911b, - 0x0a0c, 0x0dc5, 0xa094, 0x9420, 0xa098, 0x9319, 0x0804, 0x22b6, - 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0dc5, - 0xa0a4, 0x9420, 0xa0a8, 0x9319, 0x0804, 0x22b6, 0xa1bc, 0x2400, - 0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa0b4, 0x9420, - 0xa0b8, 0x9319, 0x0804, 0x22b6, 0xa1cc, 0x2400, 0x9122, 0xa1d0, - 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa0c4, 0x9420, 0xa0c8, 0x9319, - 0x0804, 0x22b6, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, - 0x0a0c, 0x0dc5, 0xa0d4, 0x9420, 0xa0d8, 0x9319, 0x0804, 0x22b6, - 0x9082, 0x001b, 0x0002, 0x2276, 0x2274, 0x2274, 0x2274, 0x2274, - 0x2274, 0x2283, 0x2274, 0x2274, 0x2274, 0x2274, 0x2274, 0x2290, - 0x2274, 0x2274, 0x2274, 0x2274, 0x2274, 0x229d, 0x2274, 0x2274, - 0x2274, 0x2274, 0x2274, 0x22aa, 0x080c, 0x0dc5, 0xa17c, 0x2400, - 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa06c, 0x9420, - 0xa070, 0x9319, 0x0498, 0xa194, 0x2400, 0x9122, 0xa198, 0x2300, - 0x911b, 0x0a0c, 0x0dc5, 0xa084, 0x9420, 0xa088, 0x9319, 0x0430, - 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0dc5, - 0xa09c, 0x9420, 0xa0a0, 0x9319, 0x00c8, 0xa1c4, 0x2400, 0x9122, - 0xa1c8, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa0b4, 0x9420, 0xa0b8, - 0x9319, 0x0060, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b, - 0x0a0c, 0x0dc5, 0xa0cc, 0x9420, 0xa0d0, 0x9319, 0xac1e, 0xab22, - 0xa880, 0xc0fd, 0xa882, 0x2800, 0xa85a, 0x2c00, 0xa812, 0x2a00, - 0xa816, 0x000e, 0x000e, 0x000e, 0x9006, 0x0028, 0x008e, 0x00de, - 0x00ce, 0x9085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xd0bc, - 0x190c, 0x0dbe, 0x9084, 0x0007, 0x0002, 0x22e7, 0x1eeb, 0x22e7, - 0x22dd, 0x22e0, 0x22e3, 0x22e0, 0x22e3, 0x080c, 0x1eeb, 0x0005, - 0x080c, 0x11b2, 0x0005, 0x080c, 0x1eeb, 0x080c, 0x11b2, 0x0005, - 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x0260, 0x2069, - 0x1800, 0x7817, 0x0000, 0x789b, 0x0814, 0x78a3, 0x0406, 0x789f, - 0x0410, 0x2009, 0x013b, 0x200b, 0x0400, 0x781b, 0x0002, 0x783b, - 0x001f, 0x7837, 0x0020, 0x7803, 0x1600, 0x012e, 0x0005, 0x2091, - 0x2600, 0x781c, 0xd0a4, 0x190c, 0x2406, 0x7900, 0xd1dc, 0x1118, - 0x9084, 0x0006, 0x001a, 0x9084, 0x000e, 0x0002, 0x232e, 0x2326, - 0x8081, 0x2326, 0x2328, 0x2328, 0x2328, 0x2328, 0x8067, 0x2326, - 0x232a, 0x2326, 0x2328, 0x2326, 0x2328, 0x2326, 0x080c, 0x0dc5, - 0x0031, 0x0020, 0x080c, 0x8067, 0x080c, 0x8081, 0x0005, 0x0006, - 0x0016, 0x0026, 0x080c, 0xf0a0, 0x7930, 0x9184, 0x0003, 0x01c0, - 0x2001, 0x19f7, 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, 0x2004, - 0x9005, 0x090c, 0x0dc5, 0x00c6, 0x2001, 0x19f7, 0x2064, 0x080c, - 0xccf3, 0x00ce, 0x00f8, 0x2009, 0x0040, 0x080c, 0x2409, 0x00d0, - 0x9184, 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, 0x080c, - 0x7637, 0x1138, 0x080c, 0x7932, 0x080c, 0x612e, 0x080c, 0x7563, - 0x0010, 0x080c, 0x5fed, 0x080c, 0x8130, 0x0041, 0x0018, 0x9184, - 0x9540, 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x0036, - 0x0046, 0x0056, 0x2071, 0x1a65, 0x080c, 0x1ad9, 0x005e, 0x004e, - 0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, 0x1800, - 0x7128, 0x2001, 0x196f, 0x2102, 0x2001, 0x1977, 0x2102, 0x2001, - 0x013b, 0x2102, 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, 0x78a3, - 0x0200, 0x9198, 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, 0x0005, - 0x2320, 0x9182, 0x0204, 0x1230, 0x2011, 0x0008, 0x8423, 0x8423, - 0x8423, 0x0488, 0x9182, 0x024c, 0x1240, 0x2011, 0x0007, 0x8403, - 0x8003, 0x9400, 0x9400, 0x9420, 0x0430, 0x9182, 0x02bc, 0x1238, - 0x2011, 0x0006, 0x8403, 0x8003, 0x9400, 0x9420, 0x00e0, 0x9182, - 0x034c, 0x1230, 0x2011, 0x0005, 0x8403, 0x8003, 0x9420, 0x0098, - 0x9182, 0x042c, 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, 0x0058, - 0x9182, 0x059c, 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, 0x0018, - 0x2011, 0x0002, 0x8423, 0x9482, 0x0228, 0x8002, 0x8020, 0x8301, - 0x9402, 0x0110, 0x0208, 0x8321, 0x8217, 0x8203, 0x9405, 0x789a, - 0x012e, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6814, 0x9084, - 0xffc0, 0x910d, 0x6916, 0x00de, 0x000e, 0x0005, 0x00d6, 0x2069, - 0x0200, 0x9005, 0x6810, 0x0110, 0xc0a5, 0x0008, 0xc0a4, 0x6812, - 0x00de, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6810, 0x9084, - 0xfff8, 0x910d, 0x6912, 0x00de, 0x000e, 0x0005, 0x7938, 0x080c, - 0x0dbe, 0x00f6, 0x2079, 0x0200, 0x7902, 0xa001, 0xa001, 0xa001, - 0xa001, 0xa001, 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, - 0xa001, 0xa001, 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, - 0x0100, 0x2071, 0x1800, 0x2009, 0x0000, 0x080c, 0x2c67, 0x080c, - 0x2b82, 0x6054, 0x8004, 0x8004, 0x8004, 0x8004, 0x9084, 0x000c, - 0x6150, 0x918c, 0xfff3, 0x9105, 0x6052, 0x6050, 0x9084, 0xb17f, - 0x9085, 0x2000, 0x6052, 0x2009, 0x199d, 0x2011, 0x199e, 0x6358, - 0x939c, 0x38f0, 0x2320, 0x080c, 0x2bc6, 0x1238, 0x939d, 0x4003, - 0x94a5, 0x8603, 0x230a, 0x2412, 0x0030, 0x939d, 0x0203, 0x94a5, - 0x8603, 0x230a, 0x2412, 0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c, - 0x2b94, 0x20a9, 0x0012, 0x1d04, 0x245b, 0x2091, 0x6000, 0x1f04, - 0x245b, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, - 0x9084, 0xdfff, 0x6052, 0x6024, 0x6026, 0x080c, 0x28ac, 0x2009, - 0x00ef, 0x6132, 0x6136, 0x080c, 0x28bc, 0x60e7, 0x0000, 0x61ea, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1110, 0x2001, - 0x0008, 0x60e2, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, - 0x602f, 0x0000, 0x6007, 0x349f, 0x60bb, 0x0000, 0x20a9, 0x0018, - 0x60bf, 0x0000, 0x1f04, 0x2490, 0x60bb, 0x0000, 0x60bf, 0x0108, - 0x60bf, 0x0012, 0x60bf, 0x0405, 0x60bf, 0x0014, 0x60bf, 0x0320, - 0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, - 0x602b, 0x402f, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, - 0x0080, 0x78c3, 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001, - 0x1835, 0x2003, 0x0000, 0x2001, 0x1834, 0x2003, 0x0001, 0x0005, - 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x0066, - 0x2031, 0x1837, 0x2634, 0x96b4, 0x0028, 0x006e, 0x1138, 0x6020, - 0xd1bc, 0x0120, 0xd0bc, 0x1168, 0xd0b4, 0x1198, 0x9184, 0x5e2c, - 0x1118, 0x9184, 0x0007, 0x00aa, 0x9195, 0x0004, 0x9284, 0x0007, - 0x0082, 0x0016, 0x2001, 0x188b, 0x200c, 0xd184, 0x001e, 0x0d70, - 0x0c98, 0x0016, 0x2001, 0x188b, 0x200c, 0xd194, 0x001e, 0x0d30, - 0x0c58, 0x2513, 0x24f9, 0x24fc, 0x24ff, 0x2504, 0x2506, 0x250a, - 0x250e, 0x080c, 0x93e2, 0x00b8, 0x080c, 0x94b1, 0x00a0, 0x080c, - 0x94b1, 0x080c, 0x93e2, 0x0078, 0x0099, 0x0068, 0x080c, 0x93e2, - 0x0079, 0x0048, 0x080c, 0x94b1, 0x0059, 0x0028, 0x080c, 0x94b1, - 0x080c, 0x93e2, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, - 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, 0x2784, - 0xd1f4, 0x190c, 0x0dbe, 0x080c, 0x7637, 0x0904, 0x256e, 0x080c, - 0xd7e3, 0x1120, 0x7000, 0x9086, 0x0003, 0x0570, 0x6024, 0x9084, - 0x1800, 0x0550, 0x080c, 0x765a, 0x0118, 0x080c, 0x7648, 0x1520, - 0x6027, 0x0020, 0x6043, 0x0000, 0x080c, 0xd7e3, 0x0168, 0x080c, - 0x765a, 0x1150, 0x2001, 0x19a8, 0x2003, 0x0001, 0x6027, 0x1800, - 0x080c, 0x74b2, 0x0804, 0x2787, 0x70a4, 0x9005, 0x1150, 0x70a7, - 0x0001, 0x00d6, 0x2069, 0x0140, 0x080c, 0x768b, 0x00de, 0x1904, - 0x2787, 0x080c, 0x793c, 0x0428, 0x080c, 0x765a, 0x1590, 0x6024, - 0x9084, 0x1800, 0x1108, 0x0468, 0x080c, 0x793c, 0x080c, 0x7932, - 0x080c, 0x612e, 0x080c, 0x7563, 0x0804, 0x2784, 0xd1ac, 0x1508, - 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc, - 0x0130, 0x7098, 0x9086, 0x0029, 0x1110, 0x080c, 0x7818, 0x0804, - 0x2784, 0x080c, 0x7937, 0x0048, 0x2001, 0x197d, 0x2003, 0x0002, - 0x0020, 0x080c, 0x7774, 0x0804, 0x2784, 0x080c, 0x78ba, 0x0804, - 0x2784, 0x6220, 0xd1bc, 0x0138, 0xd2bc, 0x1904, 0x27e1, 0xd2b4, - 0x1904, 0x27f4, 0x0000, 0xd1ac, 0x0904, 0x2699, 0x0036, 0x6328, - 0xc3bc, 0x632a, 0x003e, 0x080c, 0x7637, 0x11c0, 0x6027, 0x0020, - 0x0006, 0x0026, 0x0036, 0x080c, 0x7651, 0x1158, 0x080c, 0x7932, - 0x080c, 0x612e, 0x080c, 0x7563, 0x003e, 0x002e, 0x000e, 0x00ae, - 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x760f, 0x0016, 0x0046, - 0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, - 0x6043, 0x0090, 0x6043, 0x0010, 0x74da, 0x948c, 0xff00, 0x7038, - 0xd084, 0x0190, 0x080c, 0xd7e3, 0x1118, 0x9186, 0xf800, 0x1160, - 0x7048, 0xd084, 0x1148, 0xc085, 0x704a, 0x0036, 0x2418, 0x2011, - 0x8016, 0x080c, 0x4c44, 0x003e, 0x080c, 0xd7dc, 0x1904, 0x2676, - 0x9196, 0xff00, 0x05a8, 0x7060, 0x9084, 0x00ff, 0x810f, 0x81ff, - 0x0110, 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, 0x33aa, - 0x0128, 0xc18d, 0x7132, 0x080c, 0x6a9b, 0x1510, 0x6240, 0x9294, - 0x0010, 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, - 0x7030, 0xd08c, 0x0904, 0x2676, 0x7038, 0xd08c, 0x1140, 0x2001, - 0x180c, 0x200c, 0xd1ac, 0x1904, 0x2676, 0xc1ad, 0x2102, 0x0036, - 0x73d8, 0x2011, 0x8013, 0x080c, 0x4c44, 0x003e, 0x0804, 0x2676, - 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, - 0x2676, 0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c, - 0x4c44, 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1848, 0x220c, - 0xd1a4, 0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, - 0x8a50, 0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, 0xeba1, - 0x00ce, 0x9484, 0x00ff, 0x9080, 0x33b6, 0x200d, 0x918c, 0xff00, - 0x810f, 0x2120, 0x9006, 0x2009, 0x000e, 0x080c, 0xec31, 0x001e, - 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x321b, 0x001e, - 0x00a8, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x6724, - 0x1140, 0x7030, 0xd084, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, - 0x6148, 0x8108, 0x1f04, 0x2666, 0x00be, 0x015e, 0x00ce, 0x004e, - 0x080c, 0xb244, 0x60e3, 0x0000, 0x001e, 0x2001, 0x1800, 0x2014, - 0x9296, 0x0004, 0x1170, 0xd19c, 0x11a0, 0x2011, 0x180c, 0x2214, - 0xd29c, 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, - 0x622a, 0x2003, 0x0001, 0x2001, 0x1826, 0x2003, 0x0000, 0x6027, - 0x0020, 0xd194, 0x0904, 0x2784, 0x0016, 0x6220, 0xd2b4, 0x0904, - 0x2721, 0x080c, 0x88c3, 0x080c, 0xa6e9, 0x6027, 0x0004, 0x00f6, - 0x2019, 0x19f1, 0x2304, 0x907d, 0x0904, 0x26f0, 0x7804, 0x9086, - 0x0032, 0x15f0, 0x00d6, 0x00c6, 0x00e6, 0x0096, 0x2069, 0x0140, - 0x782c, 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, 0x2001, 0x0003, - 0x8001, 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, 0x8001, 0x1df0, - 0x080c, 0x2d49, 0x2001, 0x001e, 0x8001, 0x0240, 0x20a9, 0x0009, - 0x080c, 0x2c42, 0x6904, 0xd1dc, 0x1140, 0x0cb0, 0x2001, 0x0100, - 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x080c, 0x99a5, 0x080c, - 0x9ab1, 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, 0x080c, 0xb2d3, - 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x00ae, 0x0005, - 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, - 0x080c, 0x2d49, 0x00de, 0x00c6, 0x2061, 0x19e8, 0x6028, 0x080c, - 0xd7e3, 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, 0x909a, 0x00c8, - 0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0xa6c5, 0x0804, 0x2783, - 0x2061, 0x0100, 0x62c0, 0x080c, 0xb0ca, 0x2019, 0x19f1, 0x2304, - 0x9065, 0x0120, 0x2009, 0x0027, 0x080c, 0xb352, 0x00ce, 0x0804, - 0x2783, 0xd2bc, 0x0904, 0x276a, 0x080c, 0x88d0, 0x6014, 0x9084, - 0x1984, 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, - 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2d49, 0x00de, - 0x00c6, 0x2061, 0x19e8, 0x6044, 0x080c, 0xd7e3, 0x0120, 0x909a, - 0x0003, 0x1658, 0x0018, 0x909a, 0x00c8, 0x1638, 0x8000, 0x6046, - 0x603c, 0x00ce, 0x9005, 0x05b8, 0x2009, 0x07d0, 0x080c, 0x88c8, - 0x9080, 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x6114, 0x918c, - 0x1984, 0x918d, 0x0012, 0x6116, 0x0430, 0x9080, 0x0008, 0x2004, - 0x9086, 0x0009, 0x0d98, 0x6114, 0x918c, 0x1984, 0x918d, 0x0016, - 0x6116, 0x00c8, 0x6027, 0x0004, 0x00b0, 0x0036, 0x2019, 0x0001, - 0x080c, 0xaa49, 0x003e, 0x2019, 0x19f7, 0x2304, 0x9065, 0x0150, - 0x2009, 0x004f, 0x6020, 0x9086, 0x0009, 0x1110, 0x2009, 0x004f, - 0x080c, 0xb352, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x27dc, 0x7038, - 0xd0ac, 0x1538, 0x0016, 0x0156, 0x6027, 0x0008, 0x080c, 0x2d73, - 0x20a9, 0x0028, 0xa001, 0x1f04, 0x2792, 0x6150, 0x9185, 0x1400, - 0x6052, 0x20a9, 0x0366, 0x1d04, 0x279b, 0x080c, 0x88f7, 0x6020, - 0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x04a0, - 0x080c, 0x2c29, 0x1f04, 0x279b, 0x015e, 0x6152, 0x001e, 0x6027, - 0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x080c, 0xb244, 0x60e3, - 0x0000, 0x080c, 0xf07f, 0x080c, 0xf09a, 0x080c, 0x57d9, 0xd0fc, - 0x1138, 0x080c, 0xd7dc, 0x1120, 0x9085, 0x0001, 0x080c, 0x767b, - 0x9006, 0x080c, 0x2d39, 0x2009, 0x0002, 0x080c, 0x2c67, 0x00e6, - 0x2071, 0x1800, 0x7003, 0x0004, 0x080c, 0x0ea3, 0x00ee, 0x6027, - 0x0008, 0x080c, 0x0ba0, 0x001e, 0x918c, 0xffd0, 0x6126, 0x00ae, - 0x0005, 0x0016, 0x2001, 0x188b, 0x200c, 0xd184, 0x001e, 0x0904, - 0x259b, 0x0016, 0x2009, 0x27ed, 0x00d0, 0x2001, 0x188b, 0x200c, - 0xc184, 0x2102, 0x001e, 0x0c40, 0x0016, 0x2001, 0x188b, 0x200c, - 0xd194, 0x001e, 0x0904, 0x259b, 0x0016, 0x2009, 0x2800, 0x0038, - 0x2001, 0x188b, 0x200c, 0xc194, 0x2102, 0x001e, 0x08a8, 0x6028, - 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, 0xbc91, 0x8000, 0x2003, - 0xffff, 0x6043, 0x0001, 0x080c, 0x2c61, 0x6027, 0x0080, 0x6017, - 0x0000, 0x6043, 0x0000, 0x0817, 0x0006, 0x0016, 0x0026, 0x0036, - 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x71d0, - 0x70d2, 0x9116, 0x0904, 0x286b, 0x81ff, 0x01a0, 0x2009, 0x0000, - 0x080c, 0x2c67, 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, 0x939e, - 0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, 0x080c, - 0x4c44, 0x0448, 0x2001, 0x19a9, 0x200c, 0x81ff, 0x1140, 0x2001, - 0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, 0x2118, - 0x2011, 0x8012, 0x080c, 0x4c44, 0x080c, 0x0ea3, 0x080c, 0x57d9, - 0xd0fc, 0x1188, 0x080c, 0xd7dc, 0x1170, 0x00c6, 0x080c, 0x2907, - 0x080c, 0xa9b0, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0002, - 0x080c, 0x321b, 0x00ce, 0x012e, 0x00fe, 0x00ee, 0x003e, 0x002e, - 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, - 0xff00, 0x11f0, 0x2011, 0x1837, 0x2214, 0xd2ac, 0x11c8, 0x81ff, - 0x01e8, 0x2011, 0x181f, 0x2204, 0x9106, 0x1190, 0x2011, 0x1820, - 0x2214, 0x9294, 0xff00, 0x9584, 0xff00, 0x9206, 0x1148, 0x2011, - 0x1820, 0x2214, 0x9294, 0x00ff, 0x9584, 0x00ff, 0x9206, 0x1120, - 0x2500, 0x080c, 0x83a5, 0x0048, 0x9584, 0x00ff, 0x9080, 0x33b6, - 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, 0x33b6, - 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001, - 0x1818, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856, - 0x1f04, 0x28b7, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069, - 0x0140, 0x2001, 0x1818, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214, - 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184, - 0x000f, 0x9080, 0xf880, 0x2005, 0x6856, 0x8211, 0x1f04, 0x28cc, - 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x1800, 0x6030, - 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156, - 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0x9116, - 0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402, - 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x28fc, 0x680f, - 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x080c, - 0x57d5, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020, - 0x2009, 0x002e, 0x080c, 0xec31, 0x004e, 0x0005, 0x00f6, 0x0016, - 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x2973, 0x080c, - 0x2bc6, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, 0x1120, 0x2011, - 0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, 0x2011, 0x8000, - 0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, 0x2009, 0x0001, - 0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0, - 0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, 0x0078, 0x908e, - 0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, 0x9084, 0x0700, - 0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, 0x2300, 0x9080, - 0x0020, 0x2018, 0x080c, 0x9375, 0x928c, 0xff00, 0x0110, 0x2011, - 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138, - 0x220a, 0x080c, 0x7637, 0x1118, 0x2009, 0x196d, 0x220a, 0x002e, - 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, - 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000, - 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0dbe, 0x002e, 0x001e, - 0x000e, 0x012e, 0x0005, 0x2001, 0x180d, 0x2004, 0xd08c, 0x0118, - 0x2009, 0x0002, 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168, - 0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128, - 0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, 0x2001, 0x0227, - 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226, - 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018, - 0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, 0x1800, 0x0156, - 0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x1990, 0x2004, 0x908a, - 0x0007, 0x1a0c, 0x0dc5, 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e, - 0x015e, 0x0005, 0x29d9, 0x29f7, 0x2a1b, 0x2a1d, 0x2a46, 0x2a48, - 0x2a4a, 0x2001, 0x0001, 0x080c, 0x281c, 0x080c, 0x2c24, 0x2001, - 0x1992, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006, - 0x20a9, 0x0009, 0x080c, 0x2be2, 0x2001, 0x1990, 0x2003, 0x0006, - 0x2009, 0x001e, 0x2011, 0x2a4b, 0x080c, 0x88d5, 0x0005, 0x2009, - 0x1995, 0x200b, 0x0000, 0x2001, 0x199a, 0x2003, 0x0036, 0x2001, - 0x1999, 0x2003, 0x002a, 0x2001, 0x1992, 0x2003, 0x0001, 0x9006, - 0x080c, 0x2b94, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x2be2, - 0x2001, 0x1990, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2a4b, - 0x080c, 0x88d5, 0x0005, 0x080c, 0x0dc5, 0x2001, 0x199a, 0x2003, - 0x0036, 0x2001, 0x1992, 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005, - 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, - 0x2b94, 0x2001, 0x1996, 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9, - 0x0009, 0x080c, 0x2be2, 0x2001, 0x1990, 0x2003, 0x0006, 0x2009, - 0x001e, 0x2011, 0x2a4b, 0x080c, 0x88d5, 0x0005, 0x080c, 0x0dc5, - 0x080c, 0x0dc5, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, - 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, 0x1992, - 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0dc5, 0x0043, 0x012e, 0x015e, - 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x2a6d, 0x2a89, - 0x2ac5, 0x2af1, 0x2b11, 0x2b1d, 0x2b1f, 0x080c, 0x2bd6, 0x1190, - 0x2009, 0x1998, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004, - 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x1990, 0x2003, - 0x0001, 0x0030, 0x080c, 0x2b43, 0x2001, 0xffff, 0x080c, 0x29e8, - 0x0005, 0x080c, 0x2b21, 0x05c0, 0x2009, 0x1999, 0x2104, 0x8001, - 0x200a, 0x080c, 0x2bd6, 0x1158, 0x7a38, 0x9294, 0x0005, 0x9296, - 0x0005, 0x0518, 0x2009, 0x1998, 0x2104, 0xc085, 0x200a, 0x2009, - 0x1995, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, 0x080c, - 0x2b29, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296, - 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2bb1, - 0x2001, 0x1992, 0x2003, 0x0002, 0x0028, 0x2001, 0x1990, 0x2003, - 0x0003, 0x0010, 0x080c, 0x2a0a, 0x0005, 0x080c, 0x2b21, 0x0540, - 0x2009, 0x1999, 0x2104, 0x8001, 0x200a, 0x080c, 0x2bd6, 0x1148, - 0x2001, 0x1990, 0x2003, 0x0003, 0x2001, 0x1991, 0x2003, 0x0000, - 0x00b8, 0x2009, 0x1999, 0x2104, 0x9005, 0x1118, 0x080c, 0x2b66, - 0x0010, 0x080c, 0x2b36, 0x080c, 0x2b29, 0x2009, 0x1995, 0x200b, - 0x0000, 0x2001, 0x1992, 0x2003, 0x0001, 0x080c, 0x2a0a, 0x0000, - 0x0005, 0x0479, 0x01e8, 0x080c, 0x2bd6, 0x1198, 0x2009, 0x1996, - 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, 0x2001, - 0x199b, 0x2003, 0x000a, 0x2009, 0x1998, 0x2104, 0xc0fd, 0x200a, - 0x0038, 0x00f9, 0x2001, 0x1992, 0x2003, 0x0004, 0x080c, 0x2a35, - 0x0005, 0x0079, 0x0148, 0x080c, 0x2bd6, 0x1118, 0x080c, 0x2a21, - 0x0018, 0x0079, 0x080c, 0x2a35, 0x0005, 0x080c, 0x0dc5, 0x080c, - 0x0dc5, 0x2009, 0x199a, 0x2104, 0x8001, 0x200a, 0x090c, 0x2b82, - 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, - 0x0010, 0x2001, 0x0001, 0x080c, 0x2bb1, 0x0005, 0x7a38, 0x9294, - 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x080c, 0x2b94, 0x0005, 0x2009, 0x1995, 0x2104, 0x8000, 0x200a, - 0x9086, 0x0005, 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38, 0x9294, - 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006, - 0x0010, 0x2001, 0x0001, 0x080c, 0x2bb1, 0x0005, 0x0086, 0x2001, - 0x1998, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0dc5, 0x2009, 0x1997, - 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, 0xd084, - 0x1120, 0x080c, 0x0dc5, 0x9006, 0x0010, 0x2001, 0x0001, 0x00a1, - 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x1990, 0x20a9, 0x0009, - 0x2003, 0x0000, 0x8000, 0x1f04, 0x2b88, 0x2001, 0x1997, 0x2003, - 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, - 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, 0x783a, - 0x2009, 0x199d, 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, 0xfffb, - 0x9085, 0x0006, 0x783a, 0x2009, 0x199e, 0x210c, 0x795a, 0x00fe, - 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0138, 0x7838, - 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x0030, 0x7838, 0x9084, - 0xfffb, 0x9085, 0x0005, 0x783a, 0x00fe, 0x0005, 0x0006, 0x2001, - 0x0100, 0x2004, 0x9082, 0x0007, 0x000e, 0x0005, 0x0006, 0x2001, - 0x0100, 0x2004, 0x9082, 0x0009, 0x000e, 0x0005, 0x0156, 0x20a9, - 0x0064, 0x7820, 0x080c, 0x2c61, 0xd09c, 0x1110, 0x1f04, 0x2bd9, - 0x015e, 0x0005, 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, 0x7850, - 0x9085, 0x0040, 0x7852, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, - 0x2c61, 0x9085, 0x2000, 0x7852, 0x000e, 0x2008, 0x9186, 0x0000, - 0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, 0x783b, - 0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, 0x0030, - 0x9186, 0x0003, 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, 0x1d04, - 0x2c0f, 0x080c, 0x88f7, 0x1f04, 0x2c0f, 0x7850, 0x9085, 0x0400, - 0x9084, 0xdfbf, 0x7852, 0x080c, 0x2c61, 0x9085, 0x1000, 0x7852, - 0x000e, 0x001e, 0x012e, 0x0005, 0x7850, 0x9084, 0xffcf, 0x7852, - 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, - 0x7854, 0xd0ac, 0x1130, 0x7820, 0xd0e4, 0x1140, 0x1f04, 0x2c33, - 0x0028, 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2c39, 0x00fe, 0x015e, - 0x000e, 0x0005, 0x1d04, 0x2c42, 0x080c, 0x88f7, 0x1f04, 0x2c42, - 0x0005, 0x0006, 0x2001, 0x199c, 0x2004, 0x9086, 0x0000, 0x000e, - 0x0005, 0x0006, 0x2001, 0x199c, 0x2004, 0x9086, 0x0001, 0x000e, - 0x0005, 0x0006, 0x2001, 0x199c, 0x2004, 0x9086, 0x0002, 0x000e, - 0x0005, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006, - 0x2001, 0x19a9, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104, - 0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xa001, - 0xa001, 0x200a, 0x0005, 0x0036, 0x0046, 0x2001, 0x0141, 0x200c, - 0x918c, 0xff00, 0x9186, 0x2100, 0x0140, 0x9186, 0x2000, 0x0170, - 0x9186, 0x0100, 0x1904, 0x2cda, 0x0048, 0x0016, 0x2009, 0x1a87, - 0x2104, 0x8000, 0x0208, 0x200a, 0x001e, 0x04f0, 0x2009, 0x00a2, - 0x080c, 0x0e52, 0x2019, 0x0160, 0x2324, 0x2011, 0x0003, 0x2009, - 0x0169, 0x2104, 0x9084, 0x0007, 0x210c, 0x918c, 0x0007, 0x910e, - 0x1db0, 0x9086, 0x0003, 0x1548, 0x2304, 0x0066, 0x0076, 0x2031, - 0x0002, 0x233c, 0x973e, 0x0148, 0x8631, 0x1dd8, 0x2031, 0x1a88, - 0x263c, 0x8738, 0x0208, 0x2732, 0x2304, 0x007e, 0x006e, 0x9402, - 0x02a0, 0x19d0, 0x8211, 0x19d8, 0x84ff, 0x0170, 0x2001, 0x0141, - 0x200c, 0x918c, 0xff00, 0x9186, 0x0100, 0x0130, 0x2009, 0x180c, - 0x2104, 0xc0dd, 0x200a, 0x0008, 0x0421, 0x2001, 0x1981, 0x200c, - 0x080c, 0x0e52, 0x004e, 0x003e, 0x0005, 0x2001, 0x180c, 0x2004, - 0xd0dc, 0x01b0, 0x2001, 0x0160, 0x2004, 0x9005, 0x0140, 0x2001, - 0x0141, 0x2004, 0x9084, 0xff00, 0x9086, 0x0100, 0x1148, 0x0126, - 0x2091, 0x8000, 0x0016, 0x0026, 0x0021, 0x002e, 0x001e, 0x012e, - 0x0005, 0x00c6, 0x2061, 0x0100, 0x6014, 0x0006, 0x2001, 0x0161, - 0x2003, 0x0000, 0x6017, 0x0018, 0xa001, 0xa001, 0x602f, 0x0008, - 0x6104, 0x918e, 0x0010, 0x6106, 0x918e, 0x0010, 0x6106, 0x6017, - 0x0040, 0x04b9, 0x001e, 0x9184, 0x0003, 0x01e0, 0x0036, 0x0016, - 0x2019, 0x0141, 0x6124, 0x918c, 0x0028, 0x1120, 0x2304, 0x9084, - 0x2800, 0x0dc0, 0x001e, 0x919c, 0xffe4, 0x9184, 0x0001, 0x0118, - 0x9385, 0x0009, 0x6016, 0x9184, 0x0002, 0x0118, 0x9385, 0x0012, - 0x6016, 0x003e, 0x2001, 0x180c, 0x200c, 0xc1dc, 0x2102, 0x00ce, - 0x0005, 0x0016, 0x0026, 0x080c, 0x7651, 0x0108, 0xc0bc, 0x2009, - 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, - 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, - 0x9285, 0x1000, 0x200a, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, - 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, - 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, - 0x1128, 0x080c, 0x7651, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, - 0x001e, 0x000e, 0x0005, 0x0006, 0x0156, 0x6050, 0x9085, 0x0040, - 0x6052, 0x6050, 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2c61, 0x9085, - 0x2000, 0x6052, 0x20a9, 0x0012, 0x1d04, 0x2d84, 0x080c, 0x88f7, - 0x1f04, 0x2d84, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, - 0x015e, 0x000e, 0x0005, 0x2fff, 0x2fff, 0x2e23, 0x2e23, 0x2e2f, - 0x2e2f, 0x2e3b, 0x2e3b, 0x2e49, 0x2e49, 0x2e55, 0x2e55, 0x2e63, - 0x2e63, 0x2e71, 0x2e71, 0x2e83, 0x2e83, 0x2e8f, 0x2e8f, 0x2e9d, - 0x2e9d, 0x2ebb, 0x2ebb, 0x2edb, 0x2edb, 0x2eab, 0x2eab, 0x2ecb, - 0x2ecb, 0x2ee9, 0x2ee9, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2efb, 0x2efb, 0x2f07, 0x2f07, 0x2f15, - 0x2f15, 0x2f23, 0x2f23, 0x2f33, 0x2f33, 0x2f41, 0x2f41, 0x2f51, - 0x2f51, 0x2f61, 0x2f61, 0x2f73, 0x2f73, 0x2f81, 0x2f81, 0x2f91, - 0x2f91, 0x2fb3, 0x2fb3, 0x2fd5, 0x2fd5, 0x2fa1, 0x2fa1, 0x2fc4, - 0x2fc4, 0x2fe4, 0x2fe4, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, - 0x2e81, 0x2e81, 0x2e81, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x24c0, 0x0804, 0x2ff7, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x22cc, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x24c0, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x1394, 0x0804, 0x2ff7, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x24c0, 0x080c, 0x1394, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, - 0x1394, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x24c0, 0x080c, 0x1394, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c, - 0x1394, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x1394, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x1394, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c, 0x1394, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x0804, 0x2ff7, 0x0106, - 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, - 0x2976, 0x080c, 0x24c0, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, - 0x22cc, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, - 0x24c0, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x24c0, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, 0x2307, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x1394, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x24c0, 0x080c, 0x1394, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, 0x1394, 0x0804, - 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x2976, 0x080c, 0x24c0, 0x080c, 0x1394, 0x080c, - 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, - 0x24c0, 0x080c, 0x1394, 0x0498, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, - 0x080c, 0x1394, 0x080c, 0x2307, 0x0410, 0x0106, 0x0006, 0x0126, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, - 0x1394, 0x080c, 0x2307, 0x0098, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, - 0x080c, 0x24c0, 0x080c, 0x1394, 0x080c, 0x2307, 0x0000, 0x015e, - 0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, - 0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6a61, 0x1904, - 0x3137, 0x72dc, 0x2001, 0x197c, 0x2004, 0x9005, 0x1110, 0xd29c, - 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x3137, 0x080c, 0x313c, - 0x0804, 0x3137, 0xd2cc, 0x1904, 0x3137, 0x080c, 0x7637, 0x1120, - 0x70af, 0xffff, 0x0804, 0x3137, 0xd294, 0x0120, 0x70af, 0xffff, - 0x0804, 0x3137, 0x080c, 0x33a5, 0x0160, 0x080c, 0xd7e3, 0x0128, - 0x2001, 0x1818, 0x203c, 0x0804, 0x30b0, 0x70af, 0xffff, 0x0804, - 0x3137, 0x2001, 0x1818, 0x203c, 0x7294, 0xd284, 0x0904, 0x30b0, - 0xd28c, 0x1904, 0x30b0, 0x0036, 0x73ac, 0x938e, 0xffff, 0x1110, - 0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, 0x2c04, 0x938c, 0x0001, - 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, - 0x0904, 0x30a6, 0x908e, 0x0000, 0x0904, 0x30a6, 0x908e, 0x00ff, - 0x1160, 0x7230, 0xd284, 0x1904, 0x30ab, 0x7294, 0xc28d, 0x7296, - 0x70af, 0xffff, 0x003e, 0x0804, 0x30b0, 0x2009, 0x180d, 0x210c, - 0xd18c, 0x0150, 0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e, - 0x0118, 0x70af, 0xffff, 0x0488, 0x900e, 0x080c, 0x2873, 0x080c, - 0x66b9, 0x1538, 0x9006, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, - 0x00c6, 0x2060, 0x080c, 0x8cf7, 0x00ce, 0x090c, 0x9096, 0xb8af, - 0x0000, 0x080c, 0x6aa3, 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, - 0xd0bc, 0x0138, 0x080c, 0x6944, 0x0120, 0x080c, 0x3155, 0x0148, - 0x0028, 0x080c, 0x3295, 0x080c, 0x3181, 0x0118, 0x8318, 0x0804, - 0x304a, 0x73ae, 0x0010, 0x70af, 0xffff, 0x003e, 0x0804, 0x3137, - 0x9780, 0x33b6, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, - 0x70ac, 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, - 0x0220, 0x2008, 0x9802, 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804, - 0x3137, 0x2700, 0x0156, 0x0016, 0x9106, 0x0904, 0x312c, 0x2001, - 0x180d, 0x2004, 0xd08c, 0x0158, 0x0026, 0x2011, 0x0010, 0x080c, - 0x6ac7, 0x002e, 0x0120, 0x2009, 0xffff, 0x0804, 0x3134, 0xc484, - 0x080c, 0x6724, 0x0168, 0x080c, 0xd7e3, 0x1904, 0x312c, 0x080c, - 0x33a5, 0x1904, 0x312c, 0x080c, 0x66b9, 0x1904, 0x3134, 0x0008, - 0xc485, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, 0x2060, - 0x080c, 0x8cf7, 0x00ce, 0x090c, 0x9096, 0xb8af, 0x0000, 0x080c, - 0x6aa3, 0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0, - 0x7294, 0xd28c, 0x0180, 0x080c, 0x6aa3, 0x9082, 0x0006, 0x02e0, - 0xd484, 0x1118, 0x080c, 0x66de, 0x0028, 0x080c, 0x3321, 0x01a0, - 0x080c, 0x334c, 0x0088, 0x080c, 0x3295, 0x080c, 0xd7e3, 0x1160, - 0x080c, 0x3181, 0x0188, 0x0040, 0x080c, 0xd7e3, 0x1118, 0x080c, - 0x3321, 0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, - 0x30c9, 0x70af, 0xffff, 0x0018, 0x001e, 0x015e, 0x71ae, 0x004e, - 0x002e, 0x00ce, 0x00be, 0x0005, 0x00c6, 0x0016, 0x70af, 0x0001, - 0x2009, 0x007e, 0x080c, 0x66b9, 0x1168, 0xb813, 0x00ff, 0xb817, - 0xfffe, 0x080c, 0x3295, 0x04a9, 0x0128, 0x70dc, 0xc0bd, 0x70de, - 0x080c, 0xd52b, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, - 0x00c6, 0x2001, 0x184c, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, - 0xb325, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xd554, 0x6023, 0x0001, - 0x9006, 0x080c, 0x6656, 0x2001, 0x0000, 0x080c, 0x666a, 0x0126, - 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, 0x0004, - 0x080c, 0xb352, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, - 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, 0x2004, - 0x9084, 0x00ff, 0xb842, 0x080c, 0xb325, 0x0548, 0x2b00, 0x6012, - 0xb800, 0xc0c4, 0xb802, 0xb8a0, 0x9086, 0x007e, 0x0140, 0xb804, - 0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x3250, 0x080c, - 0xd554, 0x6023, 0x0001, 0x9006, 0x080c, 0x6656, 0x2001, 0x0002, - 0x080c, 0x666a, 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, - 0x012e, 0x2009, 0x0002, 0x080c, 0xb352, 0x9085, 0x0001, 0x00ce, - 0x00de, 0x007e, 0x001e, 0x0005, 0x00b6, 0x00c6, 0x0026, 0x2009, - 0x0080, 0x080c, 0x66b9, 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, - 0x0039, 0x0110, 0x70e3, 0xffff, 0x002e, 0x00ce, 0x00be, 0x0005, - 0x0016, 0x0076, 0x00d6, 0x00c6, 0x080c, 0xb27d, 0x01d0, 0x2b00, - 0x6012, 0x080c, 0xd554, 0x6023, 0x0001, 0x9006, 0x080c, 0x6656, - 0x2001, 0x0002, 0x080c, 0x666a, 0x0126, 0x2091, 0x8000, 0x70e4, - 0x8000, 0x70e6, 0x012e, 0x2009, 0x0002, 0x080c, 0xb352, 0x9085, - 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, - 0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x66b9, 0x11b8, - 0xb813, 0x00ff, 0xb817, 0xfffd, 0xb8cf, 0x0004, 0x080c, 0xb27d, - 0x0170, 0x2b00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, - 0xd554, 0x2009, 0x0022, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, - 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, - 0x00b6, 0x21f0, 0x080c, 0x96af, 0x080c, 0x962f, 0x080c, 0xb111, - 0x080c, 0xc2d3, 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, - 0x900e, 0x0018, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6724, - 0x1140, 0x9686, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, - 0x6148, 0x001e, 0x8108, 0x1f04, 0x3235, 0x9686, 0x0001, 0x190c, - 0x3379, 0x00be, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, - 0x00e6, 0x00c6, 0x0046, 0x0036, 0x0026, 0x0016, 0x00b6, 0x6210, - 0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0x96a4, 0x0076, - 0x2039, 0x0000, 0x080c, 0x9577, 0x2c08, 0x080c, 0xe91c, 0x007e, - 0x001e, 0xba10, 0xbb14, 0xbcc0, 0x080c, 0x6148, 0xba12, 0xbb16, - 0xbcc2, 0x00be, 0x001e, 0x002e, 0x003e, 0x004e, 0x00ce, 0x00ee, - 0x0005, 0x00e6, 0x0006, 0x00b6, 0x6010, 0x2058, 0xb8a0, 0x00be, - 0x9086, 0x0080, 0x0150, 0x2071, 0x1800, 0x70a8, 0x9005, 0x0110, - 0x8001, 0x70aa, 0x000e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x70e4, - 0x9005, 0x0dc0, 0x8001, 0x70e6, 0x0ca8, 0xb800, 0xc08c, 0xb802, - 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x0036, 0x0026, - 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0078, - 0x080c, 0x57d5, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2020, - 0x2009, 0x002d, 0x080c, 0xec31, 0x20a9, 0x0800, 0x9016, 0x0026, - 0x928e, 0x007e, 0x0904, 0x3300, 0x928e, 0x007f, 0x0904, 0x3300, - 0x928e, 0x0080, 0x05e8, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05c0, - 0x8fff, 0x1148, 0x2001, 0x198e, 0x0006, 0x2003, 0x0001, 0x04f1, - 0x000e, 0x2003, 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, 0x0001, - 0x080c, 0x6a6d, 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, 0x96a4, - 0x0076, 0x2039, 0x0000, 0x080c, 0x9577, 0x00b6, 0x00c6, 0x0026, - 0x2158, 0xba04, 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, 0xb807, - 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0x9215, 0xba06, 0x002e, - 0x00ce, 0x00be, 0x0016, 0x2c08, 0x080c, 0xe91c, 0x001e, 0x007e, - 0x002e, 0x8210, 0x1f04, 0x32b7, 0x015e, 0x001e, 0x002e, 0x003e, - 0x004e, 0x00be, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, - 0x0016, 0x080c, 0x57d5, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, - 0x2220, 0x2009, 0x0029, 0x080c, 0xec31, 0x001e, 0x002e, 0x004e, - 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x7294, 0x82ff, 0x01e8, - 0x080c, 0x6a9b, 0x11d0, 0x2100, 0x080c, 0x28a6, 0x81ff, 0x01b8, - 0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, 0x2c04, 0xd384, 0x0120, - 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x9116, 0x0138, - 0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0x9085, 0x0001, 0x00ce, - 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x0036, 0x2019, 0x0029, 0x00a9, 0x003e, 0x9180, 0x1000, - 0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, 0x2061, 0x1ab7, 0x001e, - 0x6112, 0x080c, 0x3250, 0x001e, 0x080c, 0x66de, 0x012e, 0x00ce, - 0x001e, 0x0005, 0x0016, 0x0026, 0x2110, 0x080c, 0xac6c, 0x080c, - 0xef94, 0x002e, 0x001e, 0x0005, 0x2001, 0x1837, 0x2004, 0xd0cc, - 0x0005, 0x00c6, 0x00b6, 0x080c, 0x7637, 0x1118, 0x20a9, 0x0800, - 0x0010, 0x20a9, 0x0782, 0x080c, 0x7637, 0x1110, 0x900e, 0x0010, - 0x2009, 0x007e, 0x9180, 0x1000, 0x2004, 0x905d, 0x0130, 0x86ff, - 0x0110, 0xb800, 0xd0bc, 0x090c, 0x66de, 0x8108, 0x1f04, 0x338a, - 0x2061, 0x1800, 0x607f, 0x0000, 0x6080, 0x9084, 0x00ff, 0x6082, - 0x60b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x2001, 0x1869, 0x2004, - 0xd0bc, 0x0005, 0x2011, 0x1848, 0x2214, 0xd2ec, 0x0005, 0x0026, - 0x2011, 0x1867, 0x2214, 0xd2dc, 0x002e, 0x0005, 0x7eef, 0x7de8, - 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, - 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, - 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, - 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, - 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, - 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, - 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, - 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, - 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, - 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, - 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, - 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, - 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, - 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, - 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, - 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, - 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, - 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, - 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, - 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, - 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, - 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, - 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, - 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, - 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, - 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0x189e, - 0x7003, 0x0002, 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, 0x700e, - 0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, 0x7007, 0x0001, - 0x080c, 0x1027, 0x090c, 0x0dc5, 0x2900, 0x706a, 0xa867, 0x0002, - 0xa8ab, 0xdcb0, 0x080c, 0x1027, 0x090c, 0x0dc5, 0x2900, 0x706e, - 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x189e, 0x7004, - 0x0002, 0x34e5, 0x34e6, 0x34f9, 0x350d, 0x0005, 0x1004, 0x34f6, - 0x0e04, 0x34f6, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, 0x700c, - 0x9005, 0x1128, 0x700f, 0x0001, 0x012e, 0x0468, 0x0005, 0x012e, - 0x0ce8, 0x2079, 0x0000, 0x2061, 0x18b8, 0x2c4c, 0xa86c, 0x908e, - 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x35e1, 0x0005, 0x7018, - 0x2048, 0x2061, 0x1800, 0x701c, 0x0807, 0x7014, 0x2048, 0xa864, - 0x9094, 0x00ff, 0x9296, 0x0029, 0x1120, 0xaa78, 0xd2fc, 0x0128, - 0x0005, 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, 0x2061, - 0x1800, 0x701c, 0x0807, 0x2061, 0x1800, 0x7880, 0x908a, 0x0040, - 0x1210, 0x61d0, 0x0042, 0x2100, 0x908a, 0x003f, 0x1a04, 0x35de, - 0x61d0, 0x0804, 0x3573, 0x35b5, 0x35ed, 0x35de, 0x35f9, 0x3603, - 0x3609, 0x360d, 0x361d, 0x3621, 0x3637, 0x363d, 0x3643, 0x364e, - 0x3659, 0x3668, 0x3677, 0x3685, 0x369c, 0x36b7, 0x35de, 0x3762, - 0x37a0, 0x3846, 0x3857, 0x387a, 0x35de, 0x35de, 0x35de, 0x38b2, - 0x38ce, 0x38d7, 0x3906, 0x390c, 0x35de, 0x3952, 0x35de, 0x35de, - 0x35de, 0x35de, 0x35de, 0x395d, 0x3966, 0x396e, 0x3970, 0x35de, - 0x35de, 0x35de, 0x35de, 0x35de, 0x35de, 0x399c, 0x35de, 0x35de, - 0x35de, 0x35de, 0x35de, 0x39b9, 0x3a40, 0x35de, 0x35de, 0x35de, - 0x35de, 0x35de, 0x35de, 0x0002, 0x3a6a, 0x3a6d, 0x3acc, 0x3ae5, - 0x3b15, 0x3db7, 0x35de, 0x5398, 0x35de, 0x35de, 0x35de, 0x35de, - 0x35de, 0x35de, 0x35de, 0x35de, 0x3637, 0x363d, 0x42ec, 0x57f9, - 0x430a, 0x5427, 0x5479, 0x5584, 0x35de, 0x55e6, 0x5622, 0x5653, - 0x575b, 0x5680, 0x56db, 0x35de, 0x430e, 0x44e1, 0x44f7, 0x451c, - 0x4581, 0x45f5, 0x4615, 0x468c, 0x46e8, 0x4744, 0x4747, 0x476c, - 0x4823, 0x4889, 0x4891, 0x49c6, 0x4b6e, 0x4ba2, 0x4e06, 0x35de, - 0x4e24, 0x4eeb, 0x4fd4, 0x502e, 0x35de, 0x50c1, 0x35de, 0x50d7, - 0x50f2, 0x4891, 0x5338, 0x714c, 0x0000, 0x2021, 0x4000, 0x080c, - 0x4c20, 0x0126, 0x2091, 0x8000, 0x0e04, 0x35bf, 0x0010, 0x012e, - 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, - 0x7833, 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x7007, 0x0001, - 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, 0x4001, - 0x08b0, 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, 0x2021, - 0x4005, 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, 0x902e, - 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x81ff, 0x0d98, 0x0804, - 0x4c2d, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, - 0x7990, 0x0804, 0x4c30, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, - 0x35b5, 0x7984, 0x2114, 0x0804, 0x35b5, 0x20e1, 0x0000, 0x2099, - 0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, - 0x7984, 0x7a88, 0x7b8c, 0x0804, 0x35b5, 0x7884, 0x2060, 0x0804, - 0x366a, 0x2009, 0x0003, 0x2011, 0x0003, 0x2019, 0x0014, 0x789b, - 0x0137, 0x7893, 0xffff, 0x2001, 0x188f, 0x2004, 0x9005, 0x0118, - 0x7896, 0x0804, 0x35b5, 0x7897, 0x0001, 0x0804, 0x35b5, 0x2039, - 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x35f1, 0x2039, 0x0001, 0x7d98, - 0x7c9c, 0x0804, 0x35fd, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, - 0x35ea, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x35f1, 0x79a0, 0x9182, - 0x0040, 0x0210, 0x0804, 0x35ea, 0x2138, 0x7d98, 0x7c9c, 0x0804, - 0x35fd, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x35ea, 0x21e8, - 0x7984, 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x35b5, - 0x2061, 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, - 0x1dd8, 0x2010, 0x9005, 0x0904, 0x35b5, 0x0804, 0x35e4, 0x79a0, - 0x9182, 0x0040, 0x0210, 0x0804, 0x35ea, 0x21e0, 0x20a9, 0x0001, - 0x7984, 0x2198, 0x4012, 0x0804, 0x35b5, 0x2069, 0x1847, 0x7884, - 0x7990, 0x911a, 0x1a04, 0x35ea, 0x8019, 0x0904, 0x35ea, 0x684a, - 0x6942, 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, - 0x080c, 0x7963, 0x0804, 0x35b5, 0x2069, 0x1847, 0x7884, 0x7994, - 0x911a, 0x1a04, 0x35ea, 0x8019, 0x0904, 0x35ea, 0x684e, 0x6946, - 0x788c, 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6bf8, 0x012e, 0x0804, 0x35b5, 0x902e, - 0x2520, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35e7, 0x7984, - 0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a6, - 0x4101, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, - 0x2009, 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c2d, - 0x701f, 0x36db, 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, - 0x0011, 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, - 0x9096, 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x35e7, 0x810f, - 0x918c, 0x00ff, 0x0904, 0x35e7, 0x7112, 0x7010, 0x8001, 0x0560, - 0x7012, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, - 0x2009, 0x0020, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, - 0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, - 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c2d, 0x701f, 0x3719, - 0x0005, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, - 0x000a, 0x1904, 0x35e7, 0x0888, 0x0126, 0x2091, 0x8000, 0x7014, - 0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, 0x00ff, 0x9096, - 0x0029, 0x1148, 0xc2fd, 0xaa7a, 0x080c, 0x629f, 0x0138, 0xa87a, - 0xa982, 0x012e, 0x0060, 0x080c, 0x65cf, 0x1130, 0x7007, 0x0003, - 0x701f, 0x3747, 0x012e, 0x0005, 0x080c, 0x710b, 0x012e, 0x0126, - 0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x18a6, - 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, - 0x0000, 0xa85c, 0x9080, 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60, - 0x0804, 0x4c30, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010, - 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020, - 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100, - 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0x9205, 0x789a, 0x2009, - 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a1c, 0x2004, 0x9005, - 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, - 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, 0x0080, 0x0804, 0x0427, - 0x81ff, 0x1904, 0x35e7, 0x7984, 0x080c, 0x6724, 0x1904, 0x35ea, - 0x7e98, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x35ea, 0x7c88, - 0x7d8c, 0x080c, 0x6887, 0x080c, 0x6856, 0x0000, 0x1518, 0x2061, - 0x1cd0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, - 0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, - 0x0150, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, - 0x1a04, 0x35e7, 0x0c30, 0x080c, 0xccf3, 0x012e, 0x0904, 0x35e7, - 0x0804, 0x35b5, 0x900e, 0x2001, 0x0005, 0x080c, 0x710b, 0x0126, - 0x2091, 0x8000, 0x080c, 0xd3d4, 0x080c, 0x6e9f, 0x012e, 0x0804, - 0x35b5, 0x00a6, 0x2950, 0xb198, 0x080c, 0x6724, 0x1904, 0x3833, - 0xb6a4, 0x9684, 0x3fff, 0x9082, 0x4000, 0x16e8, 0xb49c, 0xb5a0, - 0x080c, 0x6887, 0x080c, 0x6856, 0x1520, 0x2061, 0x1cd0, 0x0126, - 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, - 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0158, 0x012e, - 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x2009, 0x000d, - 0x12b0, 0x0c28, 0x080c, 0xccf3, 0x012e, 0x2009, 0x0003, 0x0178, - 0x00e0, 0x900e, 0x2001, 0x0005, 0x080c, 0x710b, 0x0126, 0x2091, - 0x8000, 0x080c, 0xd3d4, 0x080c, 0x6e92, 0x012e, 0x0070, 0xb097, - 0x4005, 0xb19a, 0x0010, 0xb097, 0x4006, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0030, 0x2a48, 0x00ae, 0x0005, 0xb097, 0x4000, 0x9006, - 0x918d, 0x0001, 0x2008, 0x2a48, 0x00ae, 0x0005, 0x81ff, 0x1904, - 0x35e7, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x67eb, 0x0904, - 0x35e7, 0x080c, 0x688d, 0x0904, 0x35e7, 0x0804, 0x460c, 0x81ff, - 0x1904, 0x35e7, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x691b, - 0x0904, 0x35e7, 0x2019, 0x0005, 0x79a8, 0x080c, 0x68a8, 0x0904, - 0x35e7, 0x7888, 0x908a, 0x1000, 0x1a04, 0x35ea, 0x8003, 0x800b, - 0x810b, 0x9108, 0x080c, 0x884b, 0x79a8, 0xd184, 0x1904, 0x35b5, - 0x0804, 0x460c, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, - 0x0001, 0x0450, 0x2029, 0x07ff, 0x645c, 0x2400, 0x9506, 0x01f8, - 0x2508, 0x080c, 0x6724, 0x11d8, 0x080c, 0x691b, 0x1128, 0x2009, - 0x0002, 0x62c0, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, - 0x68a8, 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, - 0x1270, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x884b, 0x8529, - 0x1ae0, 0x012e, 0x0804, 0x35b5, 0x012e, 0x0804, 0x35e7, 0x012e, - 0x0804, 0x35ea, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x67eb, - 0x0904, 0x35e7, 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c, - 0x96a4, 0x0076, 0x903e, 0x080c, 0x9577, 0x900e, 0x080c, 0xe91c, - 0x007e, 0x00ce, 0x080c, 0x6887, 0x0804, 0x35b5, 0x080c, 0x4bfb, - 0x0904, 0x35ea, 0x080c, 0x6887, 0x2208, 0x0804, 0x35b5, 0x0156, - 0x00d6, 0x00e6, 0x2069, 0x1910, 0x6810, 0x6914, 0x910a, 0x1208, - 0x900e, 0x6816, 0x9016, 0x901e, 0x20a9, 0x007e, 0x2069, 0x1000, - 0x2d04, 0x905d, 0x0118, 0xb84c, 0x0059, 0x9210, 0x8d68, 0x1f04, - 0x38e8, 0x2300, 0x9218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x35b5, - 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff, - 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0x1910, - 0x6910, 0x62bc, 0x0804, 0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x35e7, 0x0126, 0x2091, 0x8000, 0x080c, 0x57e9, 0x0128, - 0x2009, 0x0007, 0x012e, 0x0804, 0x35e7, 0x012e, 0x615c, 0x9190, - 0x33b6, 0x2215, 0x9294, 0x00ff, 0x637c, 0x83ff, 0x0108, 0x6280, - 0x67dc, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001, - 0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003, - 0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002, - 0x0068, 0x080c, 0x7637, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c, - 0x0120, 0x2009, 0x0005, 0x0804, 0x35e7, 0x9036, 0x7e9a, 0x7f9e, - 0x0804, 0x35b5, 0x614c, 0x6250, 0x2019, 0x1986, 0x231c, 0x2001, - 0x1987, 0x2004, 0x789a, 0x0804, 0x35b5, 0x0126, 0x2091, 0x8000, - 0x6138, 0x623c, 0x6340, 0x012e, 0x0804, 0x35b5, 0x080c, 0x4c17, - 0x0904, 0x35ea, 0xba44, 0xbb38, 0x0804, 0x35b5, 0x080c, 0x0dc5, - 0x080c, 0x4c17, 0x2110, 0x0904, 0x35ea, 0xb804, 0x908c, 0x00ff, - 0x918e, 0x0006, 0x0140, 0x9084, 0xff00, 0x9086, 0x0600, 0x2009, - 0x0009, 0x1904, 0x35e7, 0x0126, 0x2091, 0x8000, 0x2019, 0x0005, - 0x00c6, 0x9066, 0x080c, 0xac6c, 0x080c, 0x96a4, 0x0076, 0x903e, - 0x080c, 0x9577, 0x900e, 0x080c, 0xe91c, 0x007e, 0x00ce, 0xb807, - 0x0407, 0x012e, 0x0804, 0x35b5, 0x614c, 0x6250, 0x7884, 0x604e, - 0x7b88, 0x6352, 0x2069, 0x1847, 0x831f, 0x9305, 0x6816, 0x788c, - 0x2069, 0x1986, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, 0x1210, - 0x2031, 0x07d0, 0x2069, 0x1987, 0x2d04, 0x266a, 0x789a, 0x0804, - 0x35b5, 0x0126, 0x2091, 0x8000, 0x6138, 0x7884, 0x603a, 0x910e, - 0xd1b4, 0x190c, 0x0ebe, 0xd094, 0x0148, 0x00e6, 0x2071, 0x19fb, - 0x79b4, 0x9192, 0x07d0, 0x1208, 0x713e, 0x00ee, 0xd0c4, 0x01a8, - 0x00d6, 0x78a8, 0x2009, 0x199d, 0x200a, 0x78ac, 0x2011, 0x199e, - 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, 0x2214, - 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7888, 0xd0ec, 0x0178, - 0x6034, 0xc08d, 0x6036, 0x2001, 0x0050, 0x6076, 0x607a, 0x6056, - 0x606b, 0x2450, 0x00c6, 0x2061, 0x1ad1, 0x2062, 0x00ce, 0x2011, - 0x0114, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0080, 0x0010, - 0x918c, 0xff7f, 0x2112, 0x603c, 0x7988, 0x613e, 0x6140, 0x910d, - 0x788c, 0x6042, 0x7a88, 0x9294, 0x1000, 0x9205, 0x910e, 0xd1e4, - 0x190c, 0x0ed4, 0x9084, 0x0020, 0x0130, 0x78b4, 0x6046, 0x9084, - 0x0001, 0x090c, 0x42ec, 0x6040, 0xd0cc, 0x0120, 0x78b0, 0x2011, - 0x0114, 0x2012, 0x012e, 0x0804, 0x35b5, 0x00f6, 0x2079, 0x1800, - 0x7a38, 0xa898, 0x9084, 0xfebf, 0x9215, 0xa89c, 0x9084, 0xfebf, - 0x8002, 0x9214, 0x7838, 0x9084, 0x0140, 0x9215, 0x7a3a, 0xa897, - 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, 0x0005, - 0x7898, 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x35ea, 0x788c, - 0x902d, 0x0904, 0x35ea, 0x900e, 0x080c, 0x6724, 0x1120, 0xba44, - 0xbb38, 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, 0x8108, 0x0ca0, - 0x080c, 0x4c17, 0x0904, 0x35ea, 0x7888, 0x900d, 0x0904, 0x35ea, - 0x788c, 0x9005, 0x0904, 0x35ea, 0xba44, 0xb946, 0xbb38, 0xb83a, - 0x0804, 0x35b5, 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c, - 0x57e9, 0x1904, 0x35e7, 0x00c6, 0x2061, 0x0100, 0x7984, 0x9186, - 0x00ff, 0x1130, 0x2001, 0x1818, 0x2004, 0x9085, 0xff00, 0x0088, - 0x9182, 0x007f, 0x16e0, 0x9188, 0x33b6, 0x210d, 0x918c, 0x00ff, - 0x2001, 0x1818, 0x2004, 0x0026, 0x9116, 0x002e, 0x0580, 0x810f, - 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0xb27d, 0x000e, - 0x0510, 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, 0x66bf, 0x2b08, - 0x00be, 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, 0x4be4, 0x01d0, - 0x9006, 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, 0xc0fd, 0xa86a, - 0x701f, 0x3ac5, 0x2900, 0x6016, 0x2009, 0x0032, 0x080c, 0xb352, - 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x35e7, 0x00ce, - 0x0804, 0x35ea, 0x080c, 0xb2d3, 0x0cb0, 0xa830, 0x9086, 0x0100, - 0x0904, 0x35e7, 0x0804, 0x35b5, 0x2061, 0x1a74, 0x0126, 0x2091, - 0x8000, 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, 0x2061, 0x1800, - 0x6354, 0x6074, 0x789a, 0x60c0, 0x789e, 0x60bc, 0x78aa, 0x012e, - 0x0804, 0x35b5, 0x900e, 0x2110, 0x0c88, 0x81ff, 0x1904, 0x35e7, - 0x080c, 0x7637, 0x0904, 0x35e7, 0x0126, 0x2091, 0x8000, 0x6254, - 0x6074, 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x28dc, 0x080c, - 0x5a11, 0x012e, 0x0804, 0x35b5, 0x012e, 0x0804, 0x35ea, 0x0006, - 0x0016, 0x00c6, 0x00e6, 0x2001, 0x19aa, 0x2070, 0x2061, 0x1847, - 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x9375, 0x7206, - 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x35b7, 0x7884, - 0xd0fc, 0x0158, 0x2001, 0x002a, 0x2004, 0x9005, 0x0180, 0x9082, - 0x00e1, 0x0298, 0x012e, 0x0804, 0x35ea, 0x2001, 0x002a, 0x2004, - 0x9005, 0x0128, 0x2069, 0x1847, 0x6908, 0x9102, 0x1230, 0x012e, - 0x0804, 0x35ea, 0x012e, 0x0804, 0x35e7, 0x080c, 0xb23d, 0x0dd0, - 0x7884, 0xd0fc, 0x0904, 0x3b94, 0x00c6, 0x080c, 0x4be4, 0x00ce, - 0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, 0x7898, 0xa80e, 0x789c, - 0xa812, 0x2001, 0x002e, 0x2004, 0xa81a, 0x2001, 0x002f, 0x2004, - 0xa81e, 0x2001, 0x0030, 0x2004, 0xa822, 0x2001, 0x0031, 0x2004, - 0xa826, 0x2001, 0x0034, 0x2004, 0xa82a, 0x2001, 0x0035, 0x2004, - 0xa82e, 0x2001, 0x002a, 0x2004, 0x9080, 0x0003, 0x9084, 0x00fc, - 0x8004, 0xa816, 0x080c, 0x3d1a, 0x0928, 0x7014, 0x2048, 0xad2c, - 0xac28, 0xab1c, 0xaa18, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, - 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, - 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x4c2d, 0x701f, 0x3c57, - 0x7023, 0x0001, 0x012e, 0x0005, 0x0046, 0x0086, 0x0096, 0x00a6, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3aff, 0x2001, - 0x19a0, 0x2003, 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104, - 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c, - 0x3d89, 0x080c, 0x3d48, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, - 0x1a69, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, - 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004, - 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x4130, 0x008e, 0x00ee, - 0x00fe, 0x080c, 0x4052, 0x080c, 0x3f57, 0x05b8, 0x2001, 0x020b, - 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, 0x41a4, 0x00f6, 0x2079, - 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x1560, 0x2071, 0x0200, - 0x7037, 0x0000, 0x7050, 0x9084, 0xff00, 0x9086, 0x3200, 0x1510, - 0x7037, 0x0001, 0x7050, 0x9084, 0xff00, 0x9086, 0xe100, 0x11d0, - 0x7037, 0x0000, 0x7054, 0x7037, 0x0000, 0x715c, 0x9106, 0x1190, - 0x2001, 0x1820, 0x2004, 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100, - 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, 0x080c, 0x3f61, 0x080c, - 0x3d43, 0x0058, 0x080c, 0x3d43, 0x080c, 0x40c8, 0x080c, 0x4048, - 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, 0x2001, 0x032a, 0x2003, - 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x001e, 0x6106, 0x2011, - 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf, - 0x0012, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c, - 0x12fc, 0x2009, 0x0028, 0x080c, 0x2409, 0x2001, 0x0227, 0x200c, - 0x2102, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, - 0x008e, 0x004e, 0x2001, 0x19a0, 0x2004, 0x9005, 0x1118, 0x012e, - 0x0804, 0x35b5, 0x012e, 0x2021, 0x400c, 0x0804, 0x35b7, 0x0016, - 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, - 0x0156, 0x7014, 0x2048, 0x7020, 0x20a8, 0x8000, 0x7022, 0xa804, - 0x9005, 0x0904, 0x3cb3, 0x2048, 0x1f04, 0x3c67, 0x7068, 0x2040, - 0xa28c, 0xa390, 0xa494, 0xa598, 0xa930, 0xa808, 0xd0b4, 0x1120, - 0x2029, 0x0000, 0x2021, 0x0000, 0x0096, 0x7014, 0x2048, 0xa864, - 0x009e, 0x9086, 0x0103, 0x0170, 0x8906, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x4c2d, 0x701f, - 0x3c57, 0x00b0, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, - 0x0006, 0x080c, 0x0f8b, 0x000e, 0x080c, 0x4c30, 0x701f, 0x3c57, - 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, - 0x002e, 0x001e, 0x0005, 0x7014, 0x2048, 0xa864, 0x9086, 0x0103, - 0x1118, 0x701f, 0x3d18, 0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd, - 0xa86a, 0x2009, 0x007f, 0x080c, 0x66b9, 0x0110, 0x9006, 0x0030, - 0xb813, 0x00ff, 0xb817, 0xfffd, 0x080c, 0xd5a7, 0x015e, 0x00de, - 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, - 0x0904, 0x35e7, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, - 0x0086, 0x0096, 0x00d6, 0x0156, 0x701f, 0x3cea, 0x7007, 0x0003, - 0x0804, 0x3ca8, 0xa830, 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, - 0x35b7, 0x0076, 0xad10, 0xac0c, 0xab24, 0xaa20, 0xa930, 0xa808, - 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, - 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0f8b, 0x000e, - 0x080c, 0x4c30, 0x007e, 0x701f, 0x3c57, 0x7023, 0x0001, 0x0005, - 0x0804, 0x35b5, 0x0156, 0x00c6, 0xa814, 0x908a, 0x001e, 0x0218, - 0xa833, 0x001e, 0x0010, 0xa832, 0x0078, 0x81ff, 0x0168, 0x0016, - 0x080c, 0x4be4, 0x001e, 0x0130, 0xa800, 0x2040, 0xa008, 0xa80a, - 0x2100, 0x0c58, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, - 0x0005, 0x0006, 0x00f6, 0x2079, 0x0000, 0x7880, 0x9086, 0x0044, - 0x00fe, 0x000e, 0x0005, 0x2001, 0x19a0, 0x2003, 0x0001, 0x0005, - 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, 0x19ab, 0x2004, - 0x601a, 0x2061, 0x0100, 0x2001, 0x19aa, 0x2004, 0x60ce, 0x6104, - 0xc1ac, 0x6106, 0x080c, 0x4be4, 0xa813, 0x0019, 0xa817, 0x0001, - 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, - 0x2004, 0xa86a, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x19aa, - 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x2409, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0xa86e, 0x601a, 0xa873, 0x0000, 0x601f, - 0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, - 0x0005, 0x00e6, 0x080c, 0x4be4, 0x2940, 0xa013, 0x0019, 0xa017, - 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa866, 0x2001, - 0x0031, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0xa86e, 0xa873, 0x0000, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, - 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, - 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x8000, 0x81ff, 0x0148, 0x080c, 0x2c59, 0x1130, 0x9006, - 0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94, 0x2001, 0x199f, 0x2003, - 0x0000, 0x7884, 0x9084, 0x0007, 0x0002, 0x3dd8, 0x3de1, 0x3dea, - 0x3dd5, 0x3dd5, 0x3dd5, 0x3dd5, 0x3dd5, 0x012e, 0x0804, 0x35ea, - 0x2009, 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, 0x080c, 0x3fab, - 0x00c0, 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, 0x200a, 0x080c, - 0x3fab, 0x0078, 0x080c, 0x7637, 0x1128, 0x012e, 0x2009, 0x0016, - 0x0804, 0x35e7, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, - 0x35b7, 0x2001, 0x0141, 0x2004, 0xd0dc, 0x0db0, 0x0086, 0x0096, - 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3aff, - 0x2009, 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, 0x9006, 0x2068, - 0x2060, 0x2058, 0x080c, 0x427f, 0x080c, 0x41cf, 0x903e, 0x2720, - 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, 0x1a69, 0x2079, 0x0090, - 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x68d4, 0x780e, - 0x68d0, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x4130, 0x080c, - 0x2c61, 0x080c, 0x2c61, 0x080c, 0x2c61, 0x080c, 0x2c61, 0x080c, - 0x4130, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x4052, 0x2009, 0x9c40, - 0x8109, 0x11b0, 0x080c, 0x3f61, 0x2001, 0x0004, 0x200c, 0x918c, - 0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, - 0x00ae, 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, 0x35e7, 0x0cf8, - 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, 0x00f6, 0x2079, - 0x0000, 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, - 0x81ff, 0x0150, 0x080c, 0x4030, 0x2d00, 0x9c05, 0x9b05, 0x0120, - 0x080c, 0x3f61, 0x0804, 0x3f0e, 0x080c, 0x41a4, 0x080c, 0x40c8, - 0x080c, 0x4013, 0x080c, 0x4048, 0x00f6, 0x2079, 0x0100, 0x7824, - 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x3f61, 0x00fe, 0x0804, 0x3f0e, - 0x00fe, 0x080c, 0x3f57, 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602, - 0x2001, 0x0033, 0x2502, 0x080c, 0x3f61, 0x0080, 0x87ff, 0x0138, - 0x2001, 0x0201, 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, - 0x1a65, 0x2004, 0x9086, 0x0000, 0x1904, 0x3e5e, 0x2001, 0x032f, - 0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, - 0x3f0e, 0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904, - 0x3f0e, 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, - 0xd0ac, 0x1148, 0x2001, 0x1a65, 0x2003, 0x0003, 0x2001, 0x032a, - 0x2003, 0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, 0x9005, 0x0108, - 0xa016, 0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, 0x2409, 0x2900, - 0xa85a, 0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0xa817, 0x0000, - 0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, - 0x0203, 0x2004, 0x1f04, 0x3ee5, 0x00ce, 0x0030, 0xa817, 0x0001, - 0x78b0, 0x9005, 0x0108, 0xa816, 0x00f6, 0x00c6, 0x2079, 0x0100, - 0x2061, 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, 0x2004, 0x9084, - 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, - 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3e18, 0x001e, 0x00c6, - 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, - 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, 0x200c, - 0x918c, 0xfffd, 0x2102, 0x080c, 0x12fc, 0x7884, 0x9084, 0x0003, - 0x9086, 0x0002, 0x01a0, 0x2009, 0x0028, 0x080c, 0x2409, 0x2001, - 0x0227, 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ef, 0x6052, 0x602f, - 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x00ce, - 0x2d08, 0x2c10, 0x2b18, 0x2b00, 0x9c05, 0x9d05, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, - 0x0804, 0x35b5, 0x012e, 0x2021, 0x400c, 0x0804, 0x35b7, 0x9085, - 0x0001, 0x1d04, 0x3f60, 0x2091, 0x6000, 0x8420, 0x9486, 0x0064, - 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, 0x2003, - 0x0004, 0x2001, 0x1a65, 0x2003, 0x0000, 0x0071, 0x2009, 0x0048, - 0x080c, 0x2409, 0x2001, 0x0227, 0x2024, 0x2402, 0x2001, 0x0109, - 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a69, - 0x7000, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, 0x2009, 0x0206, - 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, - 0x080c, 0x2409, 0x782c, 0xd0fc, 0x0d88, 0x080c, 0x41a4, 0x7000, - 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8, - 0x2009, 0x0040, 0x080c, 0x2409, 0x782b, 0x0002, 0x7003, 0x0000, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, 0x1818, - 0x200c, 0x7932, 0x7936, 0x080c, 0x28bc, 0x7850, 0x9084, 0xfbff, - 0x9085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, 0x9084, - 0xffcf, 0x9085, 0x2000, 0x7852, 0x20a9, 0x0046, 0x1d04, 0x3fc6, - 0x2091, 0x6000, 0x1f04, 0x3fc6, 0x7850, 0x9085, 0x0400, 0x9084, - 0xdfff, 0x7852, 0x2001, 0x0021, 0x2004, 0x9084, 0x0003, 0x9086, - 0x0001, 0x1120, 0x7850, 0x9084, 0xdfff, 0x7852, 0x784b, 0xf7f7, - 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x0028, 0xa001, 0x1f04, - 0x3fe6, 0x7850, 0x9085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, - 0xa001, 0xa001, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, - 0x7850, 0x9085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, - 0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2d39, - 0x7827, 0x0020, 0x7843, 0x0000, 0x9006, 0x080c, 0x2d39, 0x7827, - 0x0048, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, - 0x2071, 0x1a65, 0x2079, 0x0320, 0x2001, 0x0201, 0x2004, 0x9005, - 0x0160, 0x7000, 0x9086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, - 0x8738, 0x7003, 0x0003, 0x782b, 0x0019, 0x00ee, 0x00fe, 0x0005, - 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x0178, - 0x2009, 0x0032, 0x260a, 0x2009, 0x0033, 0x250a, 0xd0b4, 0x0108, - 0x8c60, 0xd0ac, 0x0108, 0x8d68, 0xd0a4, 0x0108, 0x8b58, 0x0005, - 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0110, 0x7837, 0x0050, - 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, 0x19ab, 0x2004, - 0x70e2, 0x080c, 0x3d39, 0x1188, 0x2001, 0x1820, 0x2004, 0x2009, - 0x181f, 0x210c, 0x918c, 0x00ff, 0x706e, 0x716a, 0x7066, 0x918d, - 0x3200, 0x7162, 0x7073, 0xe109, 0x0080, 0x702c, 0x9085, 0x0002, - 0x702e, 0x2009, 0x1818, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, - 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, - 0x9080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, - 0x9006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, - 0x95d5, 0x7014, 0x9084, 0x1984, 0x9085, 0x0092, 0x7016, 0x080c, - 0x41a4, 0x00f6, 0x2071, 0x1a65, 0x2079, 0x0320, 0x00d6, 0x2069, - 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, 0x6898, 0x780a, - 0x00de, 0x080c, 0x3d39, 0x0140, 0x2001, 0x199f, 0x200c, 0x2003, - 0x0001, 0x918e, 0x0001, 0x0120, 0x2009, 0x03e8, 0x8109, 0x1df0, - 0x792c, 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, 0x080c, - 0x4130, 0x2011, 0x0001, 0x080c, 0x4130, 0x00fe, 0x00ee, 0x0005, - 0x00f6, 0x00e6, 0x2071, 0x1a65, 0x2079, 0x0320, 0x792c, 0xd1fc, - 0x0904, 0x412d, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, 0x4129, - 0x7000, 0x0002, 0x412d, 0x40de, 0x410e, 0x4129, 0xd1bc, 0x1170, - 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, 0x4130, - 0x0904, 0x412d, 0x080c, 0x4130, 0x0804, 0x412d, 0x00f6, 0x2079, - 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, 0x0004, - 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c, - 0x4030, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, 0x00fe, - 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, 0x7002, - 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x40d2, 0x2011, - 0x0001, 0x00b1, 0x0090, 0xa010, 0x9092, 0x0004, 0x9086, 0x0015, - 0x1120, 0xa000, 0xa05a, 0x2011, 0x0031, 0xa212, 0xd1dc, 0x1960, - 0x0828, 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, - 0xa014, 0x9005, 0x0550, 0x8001, 0x0036, 0x0096, 0xa016, 0xa058, - 0x2048, 0xa010, 0x2009, 0x0031, 0x911a, 0x831c, 0x831c, 0x938a, - 0x0007, 0x1a0c, 0x0dc5, 0x9398, 0x415e, 0x231d, 0x083f, 0x9080, - 0x0004, 0x7a2a, 0x7100, 0x8108, 0x7102, 0x009e, 0x003e, 0x908a, - 0x0035, 0x1140, 0x0096, 0xa058, 0x2048, 0xa804, 0xa05a, 0x2001, - 0x0019, 0x009e, 0xa012, 0x9085, 0x0001, 0x0005, 0x419b, 0x4192, - 0x4189, 0x4180, 0x4177, 0x416e, 0x4165, 0xa964, 0x7902, 0xa968, - 0x7906, 0xa96c, 0x7912, 0xa970, 0x7916, 0x0005, 0xa974, 0x7902, - 0xa978, 0x7906, 0xa97c, 0x7912, 0xa980, 0x7916, 0x0005, 0xa984, - 0x7902, 0xa988, 0x7906, 0xa98c, 0x7912, 0xa990, 0x7916, 0x0005, - 0xa994, 0x7902, 0xa998, 0x7906, 0xa99c, 0x7912, 0xa9a0, 0x7916, - 0x0005, 0xa9a4, 0x7902, 0xa9a8, 0x7906, 0xa9ac, 0x7912, 0xa9b0, - 0x7916, 0x0005, 0xa9b4, 0x7902, 0xa9b8, 0x7906, 0xa9bc, 0x7912, - 0xa9c0, 0x7916, 0x0005, 0xa9c4, 0x7902, 0xa9c8, 0x7906, 0xa9cc, - 0x7912, 0xa9d0, 0x7916, 0x0005, 0x00f6, 0x00e6, 0x0086, 0x2071, - 0x1a69, 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, 0x782b, 0x0002, - 0x2940, 0x9026, 0x7000, 0x0002, 0x41cb, 0x41b7, 0x41c2, 0x8001, - 0x7002, 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x4130, 0x190c, - 0x4130, 0x0048, 0x8001, 0x7002, 0x782c, 0xd0fc, 0x1d38, 0x2011, - 0x0001, 0x080c, 0x4130, 0x008e, 0x00ee, 0x00fe, 0x0005, 0x00f6, - 0x00e6, 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, 0x19ab, 0x2004, - 0x601a, 0x2061, 0x0100, 0x2001, 0x19aa, 0x2004, 0x60ce, 0x6104, - 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, 0x0520, 0x2038, - 0x2001, 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, 0x4be4, - 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, - 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, - 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x4247, 0x1d68, - 0x2900, 0xa85a, 0x00d0, 0x080c, 0x4be4, 0xa813, 0x0019, 0xa817, - 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, - 0x002f, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0xa86e, 0x2001, 0x002b, 0x2004, 0xa872, 0x2061, 0x0090, 0x2079, - 0x0100, 0x2001, 0x19aa, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c, - 0x2409, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006, - 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x9006, - 0x600a, 0x600e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, - 0x2071, 0x0080, 0xaa60, 0x22e8, 0x20a0, 0x20e1, 0x0000, 0x2099, - 0x0088, 0x702b, 0x0026, 0x7402, 0x7306, 0x9006, 0x700a, 0x700e, - 0x810b, 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, 0x0041, 0x702c, - 0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, 0x4005, 0x7400, - 0x7304, 0x87ff, 0x0190, 0x0086, 0x0096, 0x2940, 0x0086, 0x080c, - 0x4be4, 0x008e, 0xa058, 0x00a6, 0x2050, 0x2900, 0xb006, 0xa05a, - 0x00ae, 0x009e, 0x008e, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6, - 0x2001, 0x002d, 0x2004, 0x9005, 0x0528, 0x2038, 0x2001, 0x0030, - 0x2024, 0x2001, 0x0031, 0x201c, 0x080c, 0x4be4, 0x2940, 0xa813, - 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138, - 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, 0x2048, - 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x4247, 0x1d68, 0x2900, - 0xa85a, 0x00d8, 0x080c, 0x4be4, 0x2940, 0xa013, 0x0019, 0xa017, - 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa066, 0x2001, - 0x0031, 0x2004, 0xa06a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0xa06e, 0x2001, 0x002b, 0x2004, 0xa072, 0x2001, 0x032a, 0x2003, - 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, 0x0101, 0x200c, 0x918d, - 0x0200, 0x2102, 0xa017, 0x0000, 0x2001, 0x1a65, 0x2003, 0x0003, - 0x2001, 0x032a, 0x2003, 0x0009, 0x2001, 0x0300, 0x2003, 0x0000, - 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, - 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x20a9, - 0x0007, 0x20a1, 0x1840, 0x20e9, 0x0001, 0x9006, 0x4004, 0x20a9, - 0x0014, 0x20a1, 0xffec, 0x20e9, 0x0000, 0x9006, 0x4004, 0x2009, - 0x013c, 0x200a, 0x012e, 0x7880, 0x9086, 0x0052, 0x0108, 0x0005, - 0x0804, 0x35b5, 0x7d98, 0x7c9c, 0x0804, 0x36b9, 0x080c, 0x7637, - 0x190c, 0x60f3, 0x6040, 0x9084, 0x0020, 0x09b1, 0x2069, 0x1847, - 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, - 0x0001, 0x080c, 0x4c2d, 0x701f, 0x4326, 0x0005, 0x080c, 0x57e4, - 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, 0x20d8, 0x21d0, 0x2069, - 0x1847, 0x6800, 0x9005, 0x0904, 0x35ea, 0x2001, 0x180d, 0x2004, - 0xd08c, 0x6804, 0x0118, 0xc0a4, 0xc0ac, 0x6806, 0xd0ac, 0x0118, - 0xd0a4, 0x0904, 0x35ea, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, - 0x0138, 0x6200, 0x9292, 0x0005, 0x0218, 0x918c, 0xffdf, 0x0010, - 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, - 0x6104, 0x0118, 0x918d, 0x0010, 0x0010, 0x918c, 0xffef, 0x6106, - 0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a, 0x007f, 0x1a04, 0x35ea, - 0x9288, 0x33b6, 0x210d, 0x918c, 0x00ff, 0x6166, 0xd0dc, 0x0130, - 0x6828, 0x908a, 0x007f, 0x1a04, 0x35ea, 0x605e, 0x6888, 0x9084, - 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, 0x0006, 0x2009, 0x19b2, - 0x9080, 0x29b7, 0x2005, 0x200a, 0x000e, 0x2009, 0x19b3, 0x9080, - 0x29bb, 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, 0x0a04, 0x35ea, - 0x908a, 0x0841, 0x1a04, 0x35ea, 0x9084, 0x0007, 0x1904, 0x35ea, - 0x680c, 0x9005, 0x0904, 0x35ea, 0x6810, 0x9005, 0x0904, 0x35ea, - 0x6848, 0x6940, 0x910a, 0x1a04, 0x35ea, 0x8001, 0x0904, 0x35ea, - 0x684c, 0x6944, 0x910a, 0x1a04, 0x35ea, 0x8001, 0x0904, 0x35ea, - 0x2009, 0x1981, 0x200b, 0x0000, 0x2001, 0x1869, 0x2004, 0xd0c4, - 0x0140, 0x7884, 0x200a, 0x2008, 0x080c, 0x0e52, 0x3b00, 0xc085, - 0x20d8, 0x6814, 0x908c, 0x00ff, 0x614e, 0x8007, 0x9084, 0x00ff, - 0x6052, 0x080c, 0x7963, 0x080c, 0x6b8e, 0x080c, 0x6bf8, 0x6808, - 0x602a, 0x080c, 0x237b, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001, - 0xa001, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x2916, 0x003e, - 0x6000, 0x9086, 0x0000, 0x1904, 0x44cf, 0x6818, 0x691c, 0x6a20, - 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, - 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c, - 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0x9084, 0xf0ff, 0x6006, - 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9, - 0x0004, 0x20a1, 0x19b4, 0x20e9, 0x0001, 0x4001, 0x20a9, 0x0004, - 0x20a1, 0x19ce, 0x20e9, 0x0001, 0x4001, 0x080c, 0x8962, 0x00c6, - 0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0510, 0x0068, 0x2009, - 0x0100, 0x210c, 0x918e, 0x0008, 0x1110, 0x839d, 0x0010, 0x83f5, - 0x3e18, 0x12b0, 0x3508, 0x8109, 0x080c, 0x7f6f, 0x6878, 0x6016, - 0x6874, 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff, - 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, - 0x1f04, 0x441f, 0x00ce, 0x00c6, 0x2061, 0x199c, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x11a8, 0x6a88, 0x9284, 0xc000, 0x2010, 0x9286, - 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, 0x080c, 0x2bb1, - 0x2001, 0x0001, 0x080c, 0x2b94, 0x0088, 0x9286, 0x4000, 0x1148, - 0x2063, 0x0001, 0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94, - 0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, 0x00ce, 0x00e6, - 0x2c70, 0x080c, 0x0ea3, 0x00ee, 0x6888, 0xd0ec, 0x0130, 0x2011, - 0x0114, 0x2204, 0x9085, 0x0100, 0x2012, 0x6a80, 0x9284, 0x0030, - 0x9086, 0x0030, 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, - 0x2001, 0x197c, 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, - 0x928e, 0x0010, 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, - 0x080c, 0x298b, 0x2001, 0x196d, 0x2102, 0x0008, 0x2102, 0x00c6, - 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, - 0x7637, 0x0128, 0x080c, 0x50cb, 0x0110, 0x080c, 0x28dc, 0x60d4, - 0x9005, 0x01c0, 0x6003, 0x0001, 0x2009, 0x44b7, 0x00e0, 0x080c, - 0x7637, 0x1168, 0x2011, 0x74b2, 0x080c, 0x883d, 0x2011, 0x74a5, - 0x080c, 0x8917, 0x080c, 0x7937, 0x080c, 0x7563, 0x0040, 0x080c, - 0x5fed, 0x0028, 0x6003, 0x0004, 0x2009, 0x44cf, 0x0020, 0x080c, - 0x6a05, 0x0804, 0x35b5, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, - 0x9086, 0x004c, 0x1118, 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d, - 0x0817, 0x6000, 0x9086, 0x0000, 0x0904, 0x35e7, 0x2069, 0x1847, - 0x7890, 0x6842, 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x4c30, 0x9006, - 0x080c, 0x28dc, 0x81ff, 0x1904, 0x35e7, 0x080c, 0x7637, 0x11b0, - 0x080c, 0x7932, 0x080c, 0x612e, 0x080c, 0x33aa, 0x0118, 0x6130, - 0xc18d, 0x6132, 0x080c, 0xd7e3, 0x0130, 0x080c, 0x765a, 0x1118, - 0x080c, 0x760f, 0x0038, 0x080c, 0x7563, 0x0020, 0x080c, 0x60f3, - 0x080c, 0x5fed, 0x0804, 0x35b5, 0x81ff, 0x1904, 0x35e7, 0x080c, - 0x7637, 0x1110, 0x0804, 0x35e7, 0x0126, 0x2091, 0x8000, 0x6194, - 0x81ff, 0x0190, 0x704f, 0x0000, 0x2001, 0x1c80, 0x2009, 0x0040, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4c30, - 0x701f, 0x35b3, 0x012e, 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, - 0x1c80, 0x20a9, 0x0040, 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x2019, - 0xffff, 0x4304, 0x655c, 0x9588, 0x33b6, 0x210d, 0x918c, 0x00ff, - 0x216a, 0x900e, 0x2011, 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, - 0x6724, 0x1190, 0xb814, 0x821c, 0x0238, 0x9398, 0x1c80, 0x9085, - 0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1c80, 0x2324, 0x94a4, - 0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, 0x0080, 0x1208, - 0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9, - 0x0040, 0x20a1, 0x1c80, 0x2099, 0x1c80, 0x080c, 0x607e, 0x0804, - 0x452c, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x4be4, 0x1120, - 0x2009, 0x0002, 0x0804, 0x35e7, 0x080c, 0x57d5, 0xd0b4, 0x0558, - 0x7884, 0x908e, 0x007e, 0x0538, 0x908e, 0x007f, 0x0520, 0x908e, - 0x0080, 0x0508, 0x080c, 0x33a5, 0x1148, 0xb800, 0xd08c, 0x11d8, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd2a3, 0x1120, 0x2009, 0x0003, - 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x45b7, 0x0005, 0x080c, - 0x4c17, 0x0904, 0x35ea, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, - 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, - 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, - 0x9080, 0x0006, 0x2098, 0x080c, 0x0f8b, 0x0070, 0x20a9, 0x0004, - 0xa85c, 0x9080, 0x000a, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, - 0x000a, 0x2098, 0x080c, 0x0f8b, 0x8906, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4c30, 0x81ff, 0x1904, 0x35e7, - 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x6896, 0x0904, 0x35e7, - 0x0058, 0xa878, 0x9005, 0x0120, 0x2009, 0x0004, 0x0804, 0x35e7, - 0xa974, 0xaa94, 0x0804, 0x35b5, 0x080c, 0x57dd, 0x0904, 0x35b5, - 0x701f, 0x4601, 0x7007, 0x0003, 0x0005, 0x81ff, 0x1904, 0x35e7, - 0x7888, 0x908a, 0x1000, 0x1a04, 0x35ea, 0x080c, 0x4c17, 0x0904, - 0x35ea, 0x080c, 0x6aa3, 0x0120, 0x080c, 0x6aab, 0x1904, 0x35ea, - 0x080c, 0x691b, 0x0904, 0x35e7, 0x2019, 0x0004, 0x900e, 0x080c, - 0x68a8, 0x0904, 0x35e7, 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, - 0x908a, 0x1000, 0x12f8, 0x080c, 0x4c15, 0x01e0, 0x080c, 0x6aa3, - 0x0118, 0x080c, 0x6aab, 0x11b0, 0x080c, 0x691b, 0x2009, 0x0002, - 0x0168, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x68a8, 0x2009, - 0x0003, 0x0120, 0xa998, 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, - 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0030, 0x0005, 0xa897, 0x4000, 0x080c, 0x57dd, 0x0110, 0x9006, - 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x9186, - 0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0x1800, - 0x645c, 0x2400, 0x9506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, - 0x0005, 0x080c, 0x6724, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, - 0x9108, 0x080c, 0x884b, 0x0005, 0x81ff, 0x1904, 0x35e7, 0x798c, - 0x2001, 0x1980, 0x918c, 0x8000, 0x2102, 0x080c, 0x4bfb, 0x0904, - 0x35ea, 0x080c, 0x6aa3, 0x0120, 0x080c, 0x6aab, 0x1904, 0x35ea, - 0x080c, 0x67eb, 0x0904, 0x35e7, 0x080c, 0x689f, 0x0904, 0x35e7, - 0x2001, 0x1980, 0x2004, 0xd0fc, 0x1904, 0x35b5, 0x0804, 0x460c, - 0xa9a0, 0x2001, 0x1980, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, - 0x4c08, 0x01a0, 0x080c, 0x6aa3, 0x0118, 0x080c, 0x6aab, 0x1170, - 0x080c, 0x67eb, 0x2009, 0x0002, 0x0128, 0x080c, 0x689f, 0x1170, - 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0x2001, 0x1980, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x57dd, 0x0110, - 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, - 0x81ff, 0x1904, 0x35e7, 0x798c, 0x2001, 0x197f, 0x918c, 0x8000, - 0x2102, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x6aa3, 0x0120, - 0x080c, 0x6aab, 0x1904, 0x35ea, 0x080c, 0x67eb, 0x0904, 0x35e7, - 0x080c, 0x688d, 0x0904, 0x35e7, 0x2001, 0x197f, 0x2004, 0xd0fc, - 0x1904, 0x35b5, 0x0804, 0x460c, 0xa9a0, 0x2001, 0x197f, 0x918c, - 0x8000, 0xc18d, 0x2102, 0x080c, 0x4c08, 0x01a0, 0x080c, 0x6aa3, - 0x0118, 0x080c, 0x6aab, 0x1170, 0x080c, 0x67eb, 0x2009, 0x0002, - 0x0128, 0x080c, 0x688d, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, - 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x197f, 0x2004, 0xd0fc, - 0x1128, 0x080c, 0x57dd, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0000, 0x0005, 0x6100, 0x0804, 0x35b5, 0x080c, - 0x4c17, 0x0904, 0x35ea, 0x080c, 0x57e9, 0x1904, 0x35e7, 0x79a8, - 0xd184, 0x1158, 0xb834, 0x8007, 0x789e, 0xb830, 0x8007, 0x789a, - 0xbb2c, 0x831f, 0xba28, 0x8217, 0x0050, 0xb824, 0x8007, 0x789e, - 0xb820, 0x8007, 0x789a, 0xbb1c, 0x831f, 0xba18, 0x8217, 0xb900, - 0x918c, 0x0202, 0x0804, 0x35b5, 0x78a8, 0x909c, 0x0003, 0xd0ac, - 0x1158, 0xd0b4, 0x1148, 0x939a, 0x0003, 0x1a04, 0x35e7, 0x625c, - 0x7884, 0x9206, 0x1904, 0x47c7, 0x080c, 0x894c, 0x2001, 0xffec, - 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0000, - 0x0006, 0x78a8, 0x9084, 0x0080, 0x1528, 0x0006, 0x0036, 0x2001, - 0x1a83, 0x201c, 0x7b9a, 0x2003, 0x0000, 0x2001, 0x1a84, 0x201c, - 0x7b9e, 0x2003, 0x0000, 0x2001, 0x1a85, 0x201c, 0x7bae, 0x2003, - 0x0000, 0x2001, 0x1a7f, 0x201c, 0x7baa, 0x2003, 0x0000, 0x2001, - 0x1a86, 0x201c, 0x7bb2, 0x2003, 0x0000, 0x003e, 0x000e, 0x000e, - 0x0804, 0x4c30, 0x000e, 0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44, - 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, - 0x080c, 0x10f8, 0x7007, 0x0002, 0x701f, 0x47e7, 0x0005, 0x81ff, - 0x1904, 0x35e7, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x6aa3, - 0x1904, 0x35e7, 0x00c6, 0x080c, 0x4be4, 0x00ce, 0x0904, 0x35e7, - 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7ea8, 0x080c, 0xd249, - 0x0904, 0x35e7, 0x7007, 0x0003, 0x701f, 0x480d, 0x0005, 0x080c, - 0x42ec, 0x0006, 0x0036, 0x2001, 0x1a83, 0x201c, 0x7b9a, 0x2003, - 0x0000, 0x2001, 0x1a84, 0x201c, 0x7b9e, 0x2003, 0x0000, 0x2001, - 0x1a85, 0x201c, 0x7bae, 0x2003, 0x0000, 0x2001, 0x1a7f, 0x201c, - 0x7baa, 0x2003, 0x0000, 0x2001, 0x1a86, 0x201c, 0x7bb2, 0x2003, - 0x0000, 0x003e, 0x000e, 0x0804, 0x35b5, 0xa830, 0x9086, 0x0100, - 0x0904, 0x35e7, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x0804, 0x4c30, 0x9006, 0x080c, 0x28dc, 0x78a8, 0x9084, - 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x35e7, 0x080c, - 0x7637, 0x0110, 0x080c, 0x60f3, 0x7888, 0x908a, 0x1000, 0x1a04, - 0x35ea, 0x7984, 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04, - 0x35ea, 0x2100, 0x080c, 0x28a6, 0x0026, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x2061, 0x19fb, 0x601b, 0x0000, 0x601f, 0x0000, 0x607b, - 0x0000, 0x607f, 0x0000, 0x080c, 0x7637, 0x1158, 0x080c, 0x7932, - 0x080c, 0x612e, 0x9085, 0x0001, 0x080c, 0x767b, 0x080c, 0x7563, - 0x00d0, 0x080c, 0xb244, 0x2061, 0x0100, 0x2001, 0x1818, 0x2004, - 0x9084, 0x00ff, 0x810f, 0x9105, 0x604a, 0x6043, 0x0090, 0x6043, - 0x0010, 0x2009, 0x1999, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, - 0x6019, 0x080c, 0x88d5, 0x7984, 0x080c, 0x7637, 0x1110, 0x2009, - 0x00ff, 0x7a88, 0x080c, 0x466f, 0x012e, 0x00ce, 0x002e, 0x0804, - 0x35b5, 0x7984, 0x080c, 0x66b9, 0x2b08, 0x1904, 0x35ea, 0x0804, - 0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35e7, 0x60dc, - 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x35e7, - 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, 0x7984, - 0x81ff, 0x0904, 0x35ea, 0x9192, 0x0021, 0x1a04, 0x35ea, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0x702a, 0xaf60, - 0x7736, 0x080c, 0x4c2d, 0x701f, 0x48c4, 0x7880, 0x9086, 0x006e, - 0x0110, 0x701f, 0x527d, 0x0005, 0x2009, 0x0080, 0x080c, 0x6724, - 0x1118, 0x080c, 0x6aa3, 0x0120, 0x2021, 0x400a, 0x0804, 0x35b7, - 0x00d6, 0x0096, 0xa964, 0xaa6c, 0xab70, 0xac74, 0xad78, 0xae7c, - 0xa884, 0x90be, 0x0100, 0x0904, 0x495d, 0x90be, 0x0112, 0x0904, - 0x495d, 0x90be, 0x0113, 0x0904, 0x495d, 0x90be, 0x0114, 0x0904, - 0x495d, 0x90be, 0x0117, 0x0904, 0x495d, 0x90be, 0x011a, 0x0904, - 0x495d, 0x90be, 0x011c, 0x0904, 0x495d, 0x90be, 0x0121, 0x0904, - 0x4944, 0x90be, 0x0131, 0x0904, 0x4944, 0x90be, 0x0171, 0x0904, - 0x495d, 0x90be, 0x0173, 0x0904, 0x495d, 0x90be, 0x01a1, 0x1128, - 0xa894, 0x8007, 0xa896, 0x0804, 0x4968, 0x90be, 0x0212, 0x0904, - 0x4951, 0x90be, 0x0213, 0x05e8, 0x90be, 0x0214, 0x0500, 0x90be, - 0x0217, 0x0188, 0x90be, 0x021a, 0x1120, 0xa89c, 0x8007, 0xa89e, - 0x04e0, 0x90be, 0x021f, 0x05c8, 0x90be, 0x0300, 0x05b0, 0x009e, - 0x00de, 0x0804, 0x35ea, 0x7028, 0x9080, 0x0010, 0x2098, 0x20a0, - 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0007, 0x080c, 0x49a6, 0x7028, - 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, - 0x0001, 0x080c, 0x49a6, 0x00c8, 0x7028, 0x9080, 0x000c, 0x2098, - 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x49b3, - 0x00b8, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, - 0x20e8, 0x20a9, 0x0001, 0x080c, 0x49b3, 0x7028, 0x9080, 0x000c, - 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x04f1, - 0x00c6, 0x080c, 0x4be4, 0x0550, 0xa868, 0xc0fd, 0xa86a, 0xa867, - 0x0119, 0x9006, 0xa882, 0xa87f, 0x0020, 0xa88b, 0x0001, 0x810b, - 0xa9ae, 0xa8b2, 0xaab6, 0xabba, 0xacbe, 0xadc2, 0xa9c6, 0xa8ca, - 0x00ce, 0x009e, 0x00de, 0xa866, 0xa822, 0xa868, 0xc0fd, 0xa86a, - 0xa804, 0x2048, 0x080c, 0xd264, 0x1120, 0x2009, 0x0003, 0x0804, - 0x35e7, 0x7007, 0x0003, 0x701f, 0x499d, 0x0005, 0x00ce, 0x009e, - 0x00de, 0x2009, 0x0002, 0x0804, 0x35e7, 0xa820, 0x9086, 0x8001, - 0x1904, 0x35b5, 0x2009, 0x0004, 0x0804, 0x35e7, 0x0016, 0x0026, - 0x3510, 0x20a9, 0x0002, 0x4002, 0x4104, 0x4004, 0x8211, 0x1dc8, - 0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0036, 0x0046, 0x3520, - 0x20a9, 0x0004, 0x4002, 0x4304, 0x4204, 0x4104, 0x4004, 0x8421, - 0x1db8, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x35e7, 0x60dc, 0xd0ac, 0x1188, 0x2009, - 0x180d, 0x210c, 0xd18c, 0x0130, 0xd09c, 0x0120, 0x2009, 0x0016, - 0x0804, 0x35e7, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x35e7, - 0x7984, 0x78a8, 0x2040, 0x080c, 0xb23d, 0x1120, 0x9182, 0x007f, - 0x0a04, 0x35ea, 0x9186, 0x00ff, 0x0904, 0x35ea, 0x9182, 0x0800, - 0x1a04, 0x35ea, 0x7a8c, 0x7b88, 0x607c, 0x9306, 0x1158, 0x6080, - 0x924e, 0x0904, 0x35ea, 0x080c, 0xb23d, 0x1120, 0x99cc, 0xff00, - 0x0904, 0x35ea, 0x0126, 0x2091, 0x8000, 0x2001, 0x180d, 0x2004, - 0xd08c, 0x0198, 0x9386, 0x00ff, 0x0180, 0x0026, 0x2011, 0x8008, - 0x080c, 0x6ac7, 0x002e, 0x0148, 0x918d, 0x8000, 0x080c, 0x6b11, - 0x1120, 0x2001, 0x4009, 0x0804, 0x4a64, 0x080c, 0x4af7, 0x0904, - 0x4a6a, 0x0086, 0x90c6, 0x4000, 0x008e, 0x1538, 0x00c6, 0x0006, - 0x0036, 0xb818, 0xbb1c, 0x9305, 0xbb20, 0x9305, 0xbb24, 0x9305, - 0xbb28, 0x9305, 0xbb2c, 0x9305, 0xbb30, 0x9305, 0xbb34, 0x9305, - 0x003e, 0x0570, 0xd88c, 0x1128, 0x080c, 0x6aa3, 0x0110, 0xc89d, - 0x0438, 0x900e, 0x080c, 0x6944, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0x000e, 0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110, - 0x2408, 0x0090, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0060, - 0x90c6, 0x4009, 0x1108, 0x0040, 0x90c6, 0x4006, 0x1108, 0x0020, - 0x2001, 0x4005, 0x2009, 0x000a, 0x2020, 0x012e, 0x0804, 0x35b7, - 0x000e, 0x00ce, 0x2b00, 0x7026, 0x0016, 0x00b6, 0x00c6, 0x00e6, - 0x2c70, 0x080c, 0xb325, 0x0904, 0x4abf, 0x2b00, 0x6012, 0x080c, - 0xd554, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x4be4, 0x00ce, - 0x2b70, 0x1158, 0x080c, 0xb2d3, 0x00ee, 0x00ce, 0x00be, 0x001e, - 0x012e, 0x2009, 0x0002, 0x0804, 0x35e7, 0x900e, 0xa966, 0xa96a, - 0x2900, 0x6016, 0xa932, 0xa868, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, - 0xa86a, 0xd89c, 0x1110, 0x080c, 0x3250, 0x6023, 0x0001, 0x9006, - 0x080c, 0x6656, 0xd89c, 0x0138, 0x2001, 0x0004, 0x080c, 0x666a, - 0x2009, 0x0003, 0x0030, 0x2001, 0x0002, 0x080c, 0x666a, 0x2009, - 0x0002, 0x080c, 0xb352, 0x78a8, 0xd094, 0x0138, 0x00ee, 0x7024, - 0x00e6, 0x2058, 0xb8cc, 0xc08d, 0xb8ce, 0x9085, 0x0001, 0x00ee, - 0x00ce, 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, 0x0003, 0x0804, - 0x35e7, 0x7007, 0x0003, 0x701f, 0x4ace, 0x0005, 0xa830, 0x2009, - 0x180d, 0x210c, 0xd18c, 0x0140, 0x2008, 0x918e, 0xdead, 0x1120, - 0x2021, 0x4009, 0x0804, 0x35b7, 0x9086, 0x0100, 0x7024, 0x2058, - 0x1138, 0x2009, 0x0004, 0xba04, 0x9294, 0x00ff, 0x0804, 0x5729, - 0x900e, 0xa868, 0xd0f4, 0x1904, 0x35b5, 0x080c, 0x6944, 0x1108, - 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x35b5, 0x00e6, - 0x00d6, 0x0096, 0x83ff, 0x0904, 0x4b46, 0x902e, 0x080c, 0xb23d, - 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, - 0x007f, 0x20a9, 0x0781, 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b8, - 0x2100, 0x9406, 0x1904, 0x4b57, 0x2428, 0x94ce, 0x007f, 0x1120, - 0x92ce, 0xfffd, 0x1558, 0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce, - 0xfffc, 0x1520, 0x93ce, 0x00ff, 0x1508, 0xc5fd, 0x0480, 0x2058, - 0xbf10, 0x2700, 0x9306, 0x11e8, 0xbe14, 0x2600, 0x9206, 0x11c8, - 0x2400, 0x9106, 0x1180, 0xd884, 0x0598, 0xd894, 0x1588, 0x080c, - 0x6a43, 0x1570, 0x2001, 0x4000, 0x0460, 0x080c, 0x6aa3, 0x1540, - 0x2001, 0x4000, 0x0430, 0x2001, 0x4007, 0x0418, 0x2001, 0x4006, - 0x0400, 0x2400, 0x9106, 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, - 0x0918, 0x080c, 0xb23d, 0x1900, 0x2001, 0x4008, 0x0090, 0x8420, - 0x8e70, 0x1f04, 0x4b0d, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, - 0x2001, 0x0001, 0x0030, 0x080c, 0x66b9, 0x1dd0, 0xbb12, 0xba16, - 0x9006, 0x9005, 0x009e, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x35e7, 0x080c, 0x4be4, 0x1120, 0x2009, - 0x0002, 0x0804, 0x35e7, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0x7884, 0x9005, 0x0904, 0x35ea, 0x9096, 0x00ff, 0x0120, 0x9092, - 0x0004, 0x1a04, 0x35ea, 0x2010, 0x2918, 0x080c, 0x31f6, 0x1120, - 0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x4b99, - 0x0005, 0xa830, 0x9086, 0x0100, 0x1904, 0x35b5, 0x2009, 0x0004, - 0x0804, 0x35e7, 0x7984, 0x080c, 0xb23d, 0x1120, 0x9182, 0x007f, - 0x0a04, 0x35ea, 0x9186, 0x00ff, 0x0904, 0x35ea, 0x9182, 0x0800, - 0x1a04, 0x35ea, 0x2001, 0x9400, 0x080c, 0x5784, 0x1904, 0x35e7, - 0x0804, 0x35b5, 0xa998, 0x080c, 0xb23d, 0x1118, 0x9182, 0x007f, - 0x0280, 0x9186, 0x00ff, 0x0168, 0x9182, 0x0800, 0x1250, 0x2001, - 0x9400, 0x080c, 0x5784, 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, - 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x0005, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, - 0x0005, 0x2009, 0x000a, 0x0c48, 0x080c, 0x100e, 0x0198, 0x9006, - 0xa802, 0x7014, 0x9005, 0x1120, 0x2900, 0x7016, 0x701a, 0x0040, - 0x7018, 0xa802, 0x0086, 0x2040, 0x2900, 0xa006, 0x701a, 0x008e, - 0x9085, 0x0001, 0x0005, 0x7984, 0x080c, 0x6724, 0x1130, 0x7e88, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, - 0xa998, 0x080c, 0x6724, 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, - 0x2608, 0x080c, 0x6724, 0x1108, 0x0008, 0x905e, 0x8bff, 0x0005, - 0x0016, 0x7114, 0x81ff, 0x0128, 0x2148, 0xa904, 0x080c, 0x1040, - 0x0cc8, 0x7116, 0x711a, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, - 0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, - 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10f8, 0x7007, - 0x0002, 0x701f, 0x35b5, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, - 0x2079, 0x0000, 0x2001, 0x18b0, 0x2004, 0x9005, 0x1190, 0x0e04, - 0x4c61, 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x0804, - 0x4cc7, 0x0016, 0x0086, 0x0096, 0x00c6, 0x00e6, 0x2071, 0x189e, - 0x7044, 0x9005, 0x1540, 0x7148, 0x9182, 0x0010, 0x0288, 0x7038, - 0x2060, 0x080c, 0x100e, 0x0904, 0x4cbf, 0xa84b, 0x0000, 0x2900, - 0x7046, 0x2001, 0x0002, 0x9080, 0x20c7, 0x2005, 0xa846, 0x0098, - 0x7038, 0x90e0, 0x0004, 0x2001, 0x18ba, 0x9c82, 0x18fa, 0x0210, - 0x2061, 0x18ba, 0x2c00, 0x703a, 0x7148, 0x81ff, 0x1108, 0x703e, - 0x8108, 0x714a, 0x0460, 0x7148, 0x8108, 0x714a, 0x7044, 0x2040, - 0xa144, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x2060, - 0x001e, 0x8108, 0x2105, 0x9005, 0xa146, 0x1520, 0x080c, 0x100e, - 0x1130, 0x8109, 0xa946, 0x7148, 0x8109, 0x714a, 0x00d8, 0x9006, - 0xa806, 0xa84a, 0xa046, 0x2800, 0xa802, 0x2900, 0xa006, 0x7046, - 0x2001, 0x0002, 0x9080, 0x20c7, 0x2005, 0xa846, 0x0058, 0x2262, - 0x6306, 0x640a, 0x00ee, 0x00ce, 0x009e, 0x008e, 0x001e, 0x012e, - 0x00fe, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4ce9, 0x4ce9, - 0x4ceb, 0x4ce9, 0x4ce9, 0x4ce9, 0x4cef, 0x4ce9, 0x4ce9, 0x4ce9, - 0x4cf3, 0x4ce9, 0x4ce9, 0x4ce9, 0x4cf7, 0x4ce9, 0x4ce9, 0x4ce9, - 0x4cfb, 0x4ce9, 0x4ce9, 0x4ce9, 0x4cff, 0x4ce9, 0x4ce9, 0x4ce9, - 0x4d04, 0x080c, 0x0dc5, 0xa276, 0xa37a, 0xa47e, 0x0898, 0xa286, - 0xa38a, 0xa48e, 0x0878, 0xa296, 0xa39a, 0xa49e, 0x0858, 0xa2a6, - 0xa3aa, 0xa4ae, 0x0838, 0xa2b6, 0xa3ba, 0xa4be, 0x0818, 0xa2c6, - 0xa3ca, 0xa4ce, 0x0804, 0x4cc2, 0xa2d6, 0xa3da, 0xa4de, 0x0804, - 0x4cc2, 0x00e6, 0x2071, 0x189e, 0x7048, 0x9005, 0x0904, 0x4d9b, - 0x0126, 0x2091, 0x8000, 0x0e04, 0x4d9a, 0x00f6, 0x2079, 0x0000, - 0x00c6, 0x0096, 0x0086, 0x0076, 0x9006, 0x2038, 0x7040, 0x2048, - 0x9005, 0x0500, 0xa948, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, - 0x0dc5, 0x2060, 0x001e, 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, - 0x4d9d, 0xa804, 0x9005, 0x090c, 0x0dc5, 0x7042, 0x2938, 0x2040, - 0xa003, 0x0000, 0x2001, 0x0002, 0x9080, 0x20c7, 0x2005, 0xa04a, - 0x0804, 0x4d9d, 0x703c, 0x2060, 0x2c14, 0x6304, 0x6408, 0x650c, - 0x2200, 0x7836, 0x7833, 0x0012, 0x7882, 0x2300, 0x7886, 0x2400, - 0x788a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11aa, 0x87ff, 0x0118, 0x2748, 0x080c, 0x1040, 0x7048, 0x8001, - 0x704a, 0x9005, 0x1170, 0x7040, 0x2048, 0x9005, 0x0128, 0x080c, - 0x1040, 0x9006, 0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, - 0x0420, 0x7040, 0x9005, 0x1508, 0x7238, 0x2c00, 0x9206, 0x0148, - 0x9c80, 0x0004, 0x90fa, 0x18fa, 0x0210, 0x2001, 0x18ba, 0x703e, - 0x00a0, 0x9006, 0x703e, 0x703a, 0x7044, 0x9005, 0x090c, 0x0dc5, - 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, - 0x9080, 0x20c7, 0x2005, 0xa84a, 0x0000, 0x007e, 0x008e, 0x009e, - 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, - 0x0002, 0x4dbc, 0x4dbc, 0x4dbe, 0x4dbc, 0x4dbc, 0x4dbc, 0x4dc3, - 0x4dbc, 0x4dbc, 0x4dbc, 0x4dc8, 0x4dbc, 0x4dbc, 0x4dbc, 0x4dcd, - 0x4dbc, 0x4dbc, 0x4dbc, 0x4dd2, 0x4dbc, 0x4dbc, 0x4dbc, 0x4dd7, - 0x4dbc, 0x4dbc, 0x4dbc, 0x4ddc, 0x080c, 0x0dc5, 0xaa74, 0xab78, - 0xac7c, 0x0804, 0x4d48, 0xaa84, 0xab88, 0xac8c, 0x0804, 0x4d48, - 0xaa94, 0xab98, 0xac9c, 0x0804, 0x4d48, 0xaaa4, 0xaba8, 0xacac, - 0x0804, 0x4d48, 0xaab4, 0xabb8, 0xacbc, 0x0804, 0x4d48, 0xaac4, - 0xabc8, 0xaccc, 0x0804, 0x4d48, 0xaad4, 0xabd8, 0xacdc, 0x0804, - 0x4d48, 0x0016, 0x0026, 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, - 0x080c, 0x6724, 0x2019, 0x0001, 0xb85c, 0xd0ac, 0x0110, 0x2019, - 0x0000, 0x2011, 0x801b, 0x080c, 0x4c44, 0x00ce, 0x00be, 0x003e, - 0x002e, 0x001e, 0x0005, 0x0026, 0x080c, 0x57d5, 0xd0c4, 0x0120, - 0x2011, 0x8014, 0x080c, 0x4c44, 0x002e, 0x0005, 0x81ff, 0x1904, - 0x35e7, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, - 0x6032, 0x080c, 0x7637, 0x1158, 0x080c, 0x7932, 0x080c, 0x612e, - 0x9085, 0x0001, 0x080c, 0x767b, 0x080c, 0x7563, 0x0010, 0x080c, - 0x5fed, 0x012e, 0x0804, 0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, 0x0804, - 0x35e7, 0x080c, 0x6a9b, 0x0120, 0x2009, 0x0008, 0x0804, 0x35e7, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x0178, 0x0026, 0x2011, 0x0010, - 0x080c, 0x6ac7, 0x002e, 0x0140, 0x7984, 0x080c, 0x6b11, 0x1120, - 0x2009, 0x4009, 0x0804, 0x35e7, 0x7984, 0x080c, 0x66b9, 0x1904, - 0x35ea, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x2b00, 0x7026, 0x080c, - 0x6aa3, 0x7888, 0x1170, 0x9084, 0x0005, 0x1158, 0x900e, 0x080c, - 0x6944, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, - 0x35b5, 0x080c, 0x4be4, 0x0904, 0x35e7, 0x9006, 0xa866, 0xa832, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd302, 0x0904, 0x35e7, 0x7888, - 0xd094, 0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x7007, 0x0003, 0x701f, - 0x4ecb, 0x0005, 0x2061, 0x1800, 0x080c, 0x57e9, 0x2009, 0x0007, - 0x1560, 0x080c, 0x6a9b, 0x0118, 0x2009, 0x0008, 0x0430, 0xa998, - 0x080c, 0x66b9, 0x1530, 0x080c, 0x4c15, 0x0518, 0x080c, 0x6aa3, - 0xa89c, 0x1168, 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, 0x6944, - 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868, - 0xc0fc, 0xa86a, 0x080c, 0xd302, 0x11e0, 0xa89c, 0xd094, 0x0118, - 0xb8cc, 0xc08d, 0xb8ce, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, - 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x0005, 0xa897, 0x4000, 0xa99a, 0x9006, 0x918d, 0x0001, 0x2008, - 0x0005, 0x9006, 0x0005, 0xa830, 0x2009, 0x180d, 0x210c, 0xd18c, - 0x0140, 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, 0x4009, 0x0804, - 0x35b7, 0x9086, 0x0100, 0x7024, 0x2058, 0x1110, 0x0804, 0x5729, - 0x900e, 0x080c, 0x6944, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, - 0xc18d, 0x0804, 0x35b5, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, - 0x0804, 0x35e7, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, - 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, 0x900e, 0x2130, - 0x7126, 0x7132, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0005, - 0x702a, 0x20a0, 0x080c, 0x6724, 0x1904, 0x4f81, 0x080c, 0x6aa3, - 0x0138, 0x080c, 0x6aab, 0x0120, 0x080c, 0x6a43, 0x1904, 0x4f81, - 0xd794, 0x1110, 0xd784, 0x01a8, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, - 0x0006, 0x2098, 0x3400, 0xd794, 0x0198, 0x20a9, 0x0008, 0x4003, - 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x20a9, 0x0002, 0x080c, 0x49b3, - 0x0080, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x3400, - 0x20a9, 0x0004, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, - 0x49b3, 0x9186, 0x007e, 0x0170, 0x9186, 0x0080, 0x0158, 0x080c, - 0x6aa3, 0x90c2, 0x0006, 0x1210, 0xc1fd, 0x0020, 0x080c, 0x6944, - 0x1108, 0xc1fd, 0x4104, 0xc1fc, 0xd794, 0x0528, 0xb8c4, 0x20e0, - 0xb8c8, 0x2060, 0x9c80, 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, - 0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, - 0x2098, 0x3400, 0x20a9, 0x0002, 0x4003, 0x2098, 0x20a0, 0x3d00, - 0x20e0, 0x080c, 0x49a6, 0x9c80, 0x0026, 0x2098, 0xb8c4, 0x20e0, - 0x20a9, 0x0002, 0x4003, 0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0, - 0x0005, 0x8108, 0x080c, 0xb23d, 0x0118, 0x9186, 0x0800, 0x0040, - 0xd78c, 0x0120, 0x9186, 0x0800, 0x0170, 0x0018, 0x9186, 0x007e, - 0x0150, 0xd794, 0x0118, 0x9686, 0x0020, 0x0010, 0x9686, 0x0028, - 0x0150, 0x0804, 0x4f0a, 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, - 0x35b5, 0x7033, 0x0001, 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, - 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa67a, 0x7034, 0xa072, - 0x7028, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10f8, - 0x7007, 0x0002, 0x701f, 0x4fbd, 0x0005, 0x7030, 0x9005, 0x1180, - 0x7120, 0x7028, 0x20a0, 0x772c, 0x9036, 0x7034, 0x20e8, 0x2061, - 0x18b8, 0x2c44, 0xa28c, 0xa390, 0xa494, 0xa598, 0x0804, 0x4f0a, - 0x7124, 0x810b, 0x0804, 0x35b5, 0x2029, 0x007e, 0x7984, 0x7a88, - 0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, - 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9184, 0x00ff, 0x90e2, 0x0020, - 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9284, 0xff00, 0x8007, - 0x90e2, 0x0020, 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9284, - 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, - 0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x35ea, 0x9502, - 0x0a04, 0x35ea, 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x35ea, - 0x9502, 0x0a04, 0x35ea, 0x9484, 0xff00, 0x8007, 0x90e2, 0x0020, - 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9484, 0x00ff, 0x90e2, - 0x0020, 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x2061, 0x1989, - 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x35b5, 0x080c, 0x4be4, - 0x0904, 0x35e7, 0x2009, 0x0016, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c2d, 0x701f, 0x5041, - 0x0005, 0x20a9, 0x0016, 0x896e, 0x8d6e, 0x8d6f, 0x9d84, 0xffc0, - 0x9080, 0x0019, 0x2098, 0x9d84, 0x003f, 0x20e0, 0x2069, 0x1877, - 0x20e9, 0x0001, 0x2da0, 0x4003, 0x6800, 0x9005, 0x0904, 0x50a8, - 0x6804, 0x2008, 0x918c, 0xfff8, 0x1904, 0x50a8, 0x680c, 0x9005, - 0x0904, 0x50a8, 0x9082, 0xff01, 0x1a04, 0x50a8, 0x6810, 0x9082, - 0x005c, 0x06f0, 0x6824, 0x2008, 0x9082, 0x0008, 0x06c8, 0x9182, - 0x0400, 0x16b0, 0x0056, 0x2029, 0x0000, 0x080c, 0x8e80, 0x005e, - 0x6944, 0x6820, 0x9102, 0x0660, 0x6820, 0x9082, 0x0019, 0x1640, - 0x6828, 0x6944, 0x810c, 0x9102, 0x0618, 0x6840, 0x9082, 0x000f, - 0x12f8, 0x080c, 0x1027, 0x2900, 0x0590, 0x684e, 0x00e6, 0x2071, - 0x1931, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8d3c, 0x00be, 0x00ee, - 0x01e8, 0x080c, 0x8a84, 0x080c, 0x8ad3, 0x1160, 0x6857, 0x0000, - 0x00c6, 0x6b10, 0x2061, 0x1a65, 0x630a, 0x00ce, 0x0804, 0x35b5, - 0x0804, 0x35ea, 0x080c, 0x8acc, 0x00e6, 0x2071, 0x1931, 0x080c, - 0x8f00, 0x080c, 0x8f0f, 0x080c, 0x8d21, 0x00ee, 0x2001, 0x188a, - 0x204c, 0x080c, 0x1040, 0x2001, 0x188a, 0x2003, 0x0000, 0x0804, - 0x35e7, 0x0126, 0x2091, 0x8000, 0x080c, 0x92bf, 0x080c, 0x8acc, - 0x012e, 0x0804, 0x35b5, 0x0006, 0x080c, 0x57d5, 0xd0cc, 0x000e, - 0x0005, 0x0006, 0x080c, 0x57d9, 0xd0bc, 0x000e, 0x0005, 0x6174, - 0x7a84, 0x6300, 0x82ff, 0x1118, 0x7986, 0x0804, 0x35b5, 0x83ff, - 0x1904, 0x35ea, 0x2001, 0xfff0, 0x9200, 0x1a04, 0x35ea, 0x2019, - 0xffff, 0x6078, 0x9302, 0x9200, 0x0a04, 0x35ea, 0x7986, 0x6276, - 0x0804, 0x35b5, 0x080c, 0x57e9, 0x1904, 0x35e7, 0x7c88, 0x7d84, - 0x7e98, 0x7f8c, 0x080c, 0x4be4, 0x0904, 0x35e7, 0x900e, 0x901e, - 0x7326, 0x7332, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0003, - 0x702a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, - 0x6aa3, 0x0118, 0x080c, 0x6aab, 0x1148, 0x20a9, 0x0001, 0xb814, - 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, - 0x0800, 0x0120, 0x9386, 0x003c, 0x0170, 0x0c20, 0x83ff, 0x1148, - 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, 0x9375, 0x2208, 0x0804, - 0x35b5, 0x7033, 0x0001, 0x7122, 0x7024, 0x9300, 0x7026, 0x2061, - 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa37a, 0x7028, 0xa076, 0x7034, - 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x10f8, 0x7007, - 0x0002, 0x701f, 0x514c, 0x0005, 0x7030, 0x9005, 0x1178, 0x7120, - 0x7028, 0x20a0, 0x901e, 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, - 0xa48c, 0xa590, 0xa694, 0xa798, 0x0804, 0x510a, 0x7224, 0x900e, - 0x2001, 0x0003, 0x080c, 0x9375, 0x2208, 0x0804, 0x35b5, 0x00f6, - 0x00e6, 0x080c, 0x57e9, 0x2009, 0x0007, 0x1904, 0x51df, 0x2071, - 0x189e, 0x745c, 0x84ff, 0x2009, 0x000e, 0x1904, 0x51df, 0xac9c, - 0xad98, 0xaea4, 0xafa0, 0x0096, 0x080c, 0x1027, 0x2009, 0x0002, - 0x0904, 0x51df, 0x2900, 0x705e, 0x900e, 0x901e, 0x7356, 0x7362, - 0xa860, 0x7066, 0xa85c, 0x9080, 0x0003, 0x705a, 0x20a0, 0x91d8, - 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6aa3, 0x0118, 0x080c, - 0x6aab, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, - 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, - 0x003c, 0x01e8, 0x0c20, 0x83ff, 0x11c0, 0x7254, 0x900e, 0x2001, - 0x0003, 0x080c, 0x9375, 0x2208, 0x009e, 0xa897, 0x4000, 0xa99a, - 0x715c, 0x81ff, 0x090c, 0x0dc5, 0x2148, 0x080c, 0x1040, 0x9006, - 0x705e, 0x918d, 0x0001, 0x2008, 0x0418, 0x7063, 0x0001, 0x7152, - 0x7054, 0x9300, 0x7056, 0x2061, 0x18b9, 0x2c44, 0xa37a, 0x7058, - 0xa076, 0x7064, 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0xa09f, - 0x51eb, 0x000e, 0xa0a2, 0x080c, 0x10f8, 0x9006, 0x0048, 0x009e, - 0xa897, 0x4005, 0xa99a, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0xa0a0, 0x904d, 0x090c, 0x0dc5, - 0x00e6, 0x2071, 0x189e, 0xa06c, 0x908e, 0x0100, 0x0138, 0xa87b, - 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x00d8, 0x7060, 0x9005, - 0x1158, 0x7150, 0x7058, 0x20a0, 0x901e, 0x7064, 0x20e8, 0xa48c, - 0xa590, 0xa694, 0xa798, 0x0428, 0xa87b, 0x0000, 0xa883, 0x0000, - 0xa897, 0x4000, 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x9375, - 0xaa9a, 0x715c, 0x81ff, 0x090c, 0x0dc5, 0x2148, 0x080c, 0x1040, - 0x705f, 0x0000, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6e9f, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x00ee, 0x00fe, - 0x0005, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6aa3, - 0x0118, 0x080c, 0x6aab, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, - 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, - 0x0120, 0x9386, 0x003c, 0x0518, 0x0c20, 0x83ff, 0x11f0, 0x7154, - 0x810c, 0xa99a, 0xa897, 0x4000, 0x715c, 0x81ff, 0x090c, 0x0dc5, - 0x2148, 0x080c, 0x1040, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, - 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, - 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x0070, 0x7063, 0x0001, 0x7152, - 0x7054, 0x9300, 0x7056, 0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a, - 0x080c, 0x10f8, 0x9006, 0x00ee, 0x0005, 0x0096, 0xa88c, 0x90be, - 0x7000, 0x0148, 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, 0x0118, - 0x009e, 0x0804, 0x35ea, 0xa884, 0xa988, 0x080c, 0x2873, 0x1518, - 0x080c, 0x66b9, 0x1500, 0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c, - 0x4be4, 0x01c8, 0x080c, 0x4be4, 0x01b0, 0x009e, 0xa867, 0x0000, - 0xa868, 0xc0fd, 0xa86a, 0xa823, 0x0000, 0xa804, 0x2048, 0x080c, - 0xd284, 0x1120, 0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, - 0x701f, 0x52b8, 0x0005, 0x009e, 0x2009, 0x0002, 0x0804, 0x35e7, - 0x7124, 0x080c, 0x334c, 0xa820, 0x9086, 0x8001, 0x1120, 0x2009, - 0x0004, 0x0804, 0x35e7, 0x2900, 0x7022, 0xa804, 0x0096, 0x2048, - 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x009e, - 0x9080, 0x0002, 0x0076, 0x0006, 0x2098, 0x20a0, 0x27e0, 0x27e8, - 0x20a9, 0x002a, 0x080c, 0x0f8b, 0xaa6c, 0xab70, 0xac74, 0xad78, - 0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xae64, 0xaf8c, 0x97c6, - 0x7000, 0x0118, 0x97c6, 0x7100, 0x1148, 0x96c2, 0x0004, 0x0600, - 0x2009, 0x0004, 0x000e, 0x007e, 0x0804, 0x4c30, 0x97c6, 0x7200, - 0x11b8, 0x96c2, 0x0054, 0x02a0, 0x000e, 0x007e, 0x2061, 0x18b8, - 0x2c44, 0xa076, 0xa772, 0xa07b, 0x002a, 0xa28e, 0xa392, 0xa496, - 0xa59a, 0x080c, 0x10f8, 0x7007, 0x0002, 0x701f, 0x5314, 0x0005, - 0x000e, 0x007e, 0x0804, 0x35ea, 0x7020, 0x2048, 0xa804, 0x2048, - 0xa804, 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x0002, 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, - 0x002a, 0x080c, 0x0f8b, 0x2100, 0x2238, 0x2061, 0x18b8, 0x2c44, - 0xa28c, 0xa390, 0xa494, 0xa598, 0x2009, 0x002a, 0x0804, 0x4c30, - 0x81ff, 0x1904, 0x35e7, 0x798c, 0x2001, 0x197e, 0x918c, 0x8000, - 0x2102, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x6aa3, 0x0120, - 0x080c, 0x6aab, 0x1904, 0x35ea, 0x080c, 0x67eb, 0x0904, 0x35e7, - 0x0126, 0x2091, 0x8000, 0x080c, 0x68b1, 0x012e, 0x0904, 0x35e7, - 0x2001, 0x197e, 0x2004, 0xd0fc, 0x1904, 0x35b5, 0x0804, 0x460c, - 0xa9a0, 0x2001, 0x197e, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, - 0x4c08, 0x01a0, 0x080c, 0x6aa3, 0x0118, 0x080c, 0x6aab, 0x1170, - 0x080c, 0x67eb, 0x2009, 0x0002, 0x0128, 0x080c, 0x68b1, 0x1170, - 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0x2001, 0x197e, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x57dd, 0x0110, - 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, - 0x78a8, 0xd08c, 0x1118, 0xd084, 0x0904, 0x4581, 0x080c, 0x4c17, - 0x0904, 0x35ea, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, - 0x35e7, 0x080c, 0x6aa3, 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, - 0x0005, 0x15a0, 0x78a8, 0xd08c, 0x0120, 0xb800, 0xc08c, 0xb802, - 0x0028, 0x080c, 0x57d5, 0xd0b4, 0x0904, 0x45bb, 0x7884, 0x908e, - 0x007e, 0x0904, 0x45bb, 0x908e, 0x007f, 0x0904, 0x45bb, 0x908e, - 0x0080, 0x0904, 0x45bb, 0xb800, 0xd08c, 0x1904, 0x45bb, 0xa867, - 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd2a3, 0x1120, 0x2009, - 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x53e0, 0x0005, - 0x080c, 0x4c17, 0x0904, 0x35ea, 0x0804, 0x45bb, 0x080c, 0x33a5, - 0x0108, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, 0x0120, 0x2009, - 0x0001, 0x0804, 0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, - 0x0804, 0x35e7, 0x080c, 0x6a9b, 0x0120, 0x2009, 0x0008, 0x0804, - 0x35e7, 0xb89c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x45bb, 0x9006, - 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd302, 0x1120, - 0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x5419, - 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, - 0x5729, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x0804, 0x53b2, 0x81ff, - 0x2009, 0x0001, 0x1904, 0x35e7, 0x080c, 0x57e9, 0x2009, 0x0007, - 0x1904, 0x35e7, 0x080c, 0x6a9b, 0x0120, 0x2009, 0x0008, 0x0804, - 0x35e7, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x6aa3, 0x2009, - 0x0009, 0x1904, 0x35e7, 0x080c, 0x4be4, 0x2009, 0x0002, 0x0904, - 0x35e7, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x7988, - 0xa95a, 0x9194, 0xfd00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, - 0xc0ed, 0xa952, 0x798c, 0xa956, 0x0038, 0x928e, 0x0100, 0x1904, - 0x35ea, 0xc0e5, 0xa952, 0xa956, 0xa83e, 0x080c, 0xd555, 0x2009, - 0x0003, 0x0904, 0x35e7, 0x7007, 0x0003, 0x701f, 0x5470, 0x0005, - 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x35e7, 0x0804, - 0x35b5, 0x7aa8, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, - 0x57e9, 0x1188, 0x2009, 0x0014, 0x0804, 0x35e7, 0xd2dc, 0x1578, - 0x81ff, 0x2009, 0x0001, 0x1904, 0x35e7, 0x080c, 0x57e9, 0x2009, - 0x0007, 0x1904, 0x35e7, 0xd2f4, 0x0138, 0x9284, 0x5000, 0xc0d5, - 0x080c, 0x57af, 0x0804, 0x35b5, 0xd2fc, 0x0160, 0x080c, 0x4c17, - 0x0904, 0x35ea, 0x7984, 0x9284, 0x9000, 0xc0d5, 0x080c, 0x5784, - 0x0804, 0x35b5, 0x080c, 0x4c17, 0x0904, 0x35ea, 0xb804, 0x9084, - 0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, 0x1904, 0x555f, 0x080c, - 0x4be4, 0x2009, 0x0002, 0x0904, 0x555f, 0xa85c, 0x9080, 0x001b, - 0xaf60, 0x2009, 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, - 0x4c2d, 0x701f, 0x54cc, 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, - 0xa870, 0x9005, 0x1120, 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, - 0x35ea, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x4c17, - 0x1110, 0x0804, 0x35ea, 0x2009, 0x0043, 0x080c, 0xd5c1, 0x2009, - 0x0003, 0x0904, 0x555f, 0x7007, 0x0003, 0x701f, 0x54f0, 0x0005, - 0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x555f, 0x7984, - 0x7aa8, 0x9284, 0x1000, 0xc0d5, 0x080c, 0x5784, 0x0804, 0x35b5, - 0x00c6, 0xaab0, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x0170, 0x080c, - 0x57e9, 0x1158, 0x2009, 0x0014, 0x0804, 0x554e, 0x2061, 0x1800, - 0x080c, 0x57e9, 0x2009, 0x0007, 0x15c8, 0xd2f4, 0x0130, 0x9284, - 0x5000, 0xc0d5, 0x080c, 0x57af, 0x0058, 0xd2fc, 0x0180, 0x080c, - 0x4c15, 0x0590, 0xa998, 0x9284, 0x9000, 0xc0d5, 0x080c, 0x5784, - 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x0438, 0x080c, - 0x4c15, 0x0510, 0x080c, 0x6aa3, 0x2009, 0x0009, 0x11b8, 0xa8c4, - 0x9086, 0x0500, 0x11c8, 0xa8c8, 0x9005, 0x11b0, 0xa8cc, 0x9084, - 0xff00, 0x1190, 0x080c, 0x4c15, 0x1108, 0x0070, 0x2009, 0x004b, - 0x080c, 0xd5c1, 0x2009, 0x0003, 0x0108, 0x0078, 0x0431, 0x19c0, - 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0030, 0x00ce, 0x0005, 0x9006, 0x0ce0, 0x7aa8, - 0xd2dc, 0x0904, 0x35e7, 0x0016, 0x7984, 0x9284, 0x1000, 0xc0fd, - 0x080c, 0x5784, 0x001e, 0x1904, 0x35e7, 0x0804, 0x35b5, 0x00f6, - 0x2d78, 0xaab0, 0x0021, 0x00fe, 0x0005, 0xaab0, 0xc2d5, 0xd2dc, - 0x0150, 0x0016, 0xa998, 0x9284, 0x1400, 0xc0fd, 0x080c, 0x5784, - 0x001e, 0x9085, 0x0001, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, 0x0804, - 0x35e7, 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x6724, 0x1904, - 0x35ea, 0x9186, 0x007f, 0x0138, 0x080c, 0x6aa3, 0x0120, 0x2009, - 0x0009, 0x0804, 0x35e7, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, - 0x0804, 0x35e7, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, - 0x0100, 0x8007, 0xa80a, 0x080c, 0xd2bd, 0x1120, 0x2009, 0x0003, - 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x55bf, 0x0005, 0xa808, - 0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x35e7, - 0xa8e0, 0xa866, 0xa810, 0x8007, 0x9084, 0x00ff, 0x800c, 0xa814, - 0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, 0x9108, 0x8906, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0004, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4c30, 0x080c, 0x4be4, - 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, 0x7984, 0x9194, 0xff00, - 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x7023, 0x19b4, 0x0040, - 0x92c6, 0x0001, 0x1118, 0x7023, 0x19ce, 0x0010, 0x0804, 0x35ea, - 0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, - 0x0019, 0xaf60, 0x080c, 0x4c2d, 0x701f, 0x560f, 0x0005, 0x2001, - 0x182e, 0x2003, 0x0001, 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, - 0x20e0, 0x20a9, 0x001a, 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, - 0x0804, 0x35b5, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, - 0x35e7, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, - 0x1118, 0x2099, 0x19b4, 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, - 0x19ce, 0x0010, 0x0804, 0x35ea, 0xa85c, 0x9080, 0x0019, 0x20a0, - 0xa860, 0x20e8, 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, - 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, - 0xaf60, 0x0804, 0x4c30, 0x7884, 0x908a, 0x1000, 0x1a04, 0x35ea, - 0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, - 0x2061, 0x19fb, 0x614a, 0x00ce, 0x012e, 0x0804, 0x35b5, 0x00c6, - 0x080c, 0x7637, 0x1160, 0x080c, 0x7932, 0x080c, 0x612e, 0x9085, - 0x0001, 0x080c, 0x767b, 0x080c, 0x7563, 0x080c, 0x0dc5, 0x2061, - 0x1800, 0x6030, 0xc09d, 0x6032, 0x080c, 0x5fed, 0x00ce, 0x0005, - 0x00c6, 0x2001, 0x1800, 0x2004, 0x908e, 0x0000, 0x0904, 0x35e7, - 0x7884, 0x9005, 0x0188, 0x7888, 0x2061, 0x199c, 0x2c0c, 0x2062, - 0x080c, 0x2c49, 0x01a0, 0x080c, 0x2c51, 0x0188, 0x080c, 0x2c59, - 0x0170, 0x2162, 0x0804, 0x35ea, 0x2061, 0x0100, 0x6038, 0x9086, - 0x0007, 0x1118, 0x2009, 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, - 0x9086, 0x0002, 0x1568, 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, - 0x0026, 0x2011, 0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, - 0xaac9, 0x002e, 0x080c, 0xa9d3, 0x0036, 0x901e, 0x080c, 0xaa49, - 0x003e, 0x60e3, 0x0000, 0x080c, 0xf07f, 0x080c, 0xf09a, 0x9085, - 0x0001, 0x080c, 0x767b, 0x9006, 0x080c, 0x2d39, 0x2001, 0x1800, - 0x2003, 0x0004, 0x2001, 0x19a8, 0x2003, 0x0000, 0x6027, 0x0008, - 0x00ce, 0x0804, 0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, 0x0804, 0x35e7, - 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x6724, 0x1904, 0x35ea, - 0x9186, 0x007f, 0x0138, 0x080c, 0x6aa3, 0x0120, 0x2009, 0x0009, - 0x0804, 0x35e7, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, - 0x35e7, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd2c0, - 0x1120, 0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, - 0x5712, 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, - 0x0804, 0x35e7, 0xa8e0, 0xa866, 0xa834, 0x8007, 0x800c, 0xa85c, - 0x9080, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xaf60, 0x0804, - 0x4c30, 0xa898, 0x9086, 0x000d, 0x1904, 0x35e7, 0x2021, 0x4005, - 0x0126, 0x2091, 0x8000, 0x0e04, 0x5736, 0x0010, 0x012e, 0x0cc0, - 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, - 0x0010, 0x7883, 0x4005, 0xa998, 0x7986, 0xa9a4, 0x799a, 0xa9a8, - 0x799e, 0x080c, 0x4c20, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x11aa, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, - 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, - 0x19fb, 0x7984, 0x615a, 0x6156, 0x605f, 0x0000, 0x6053, 0x0009, - 0x7898, 0x6072, 0x789c, 0x606e, 0x7888, 0x606a, 0x788c, 0x6066, - 0x2001, 0x1a0b, 0x2044, 0x2001, 0x1a12, 0xa076, 0xa060, 0xa072, - 0xa07b, 0x0001, 0xa07f, 0x0002, 0xa06b, 0x0000, 0xa09f, 0x0000, - 0x00ce, 0x012e, 0x0804, 0x35b5, 0x0126, 0x2091, 0x8000, 0x00b6, - 0x00c6, 0x90e4, 0xc000, 0x0168, 0x0006, 0xd0d4, 0x0130, 0x0036, - 0x2019, 0x0029, 0x080c, 0x336a, 0x003e, 0x080c, 0xd125, 0x000e, - 0x1198, 0xd0e4, 0x0160, 0x9180, 0x1000, 0x2004, 0x905d, 0x0160, - 0x080c, 0x6148, 0x080c, 0xb23d, 0x0110, 0xb817, 0x0000, 0x9006, - 0x00ce, 0x00be, 0x012e, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x0126, - 0x2091, 0x8000, 0x0156, 0x2010, 0x900e, 0x20a9, 0x0800, 0x0016, - 0x9180, 0x1000, 0x2004, 0x9005, 0x0188, 0x9186, 0x007e, 0x0170, - 0x9186, 0x007f, 0x0158, 0x9186, 0x0080, 0x0140, 0x9186, 0x00ff, - 0x0128, 0x0026, 0x2200, 0x080c, 0x5784, 0x002e, 0x001e, 0x8108, - 0x1f04, 0x57b7, 0x015e, 0x012e, 0x0005, 0x2001, 0x1848, 0x2004, - 0x0005, 0x2001, 0x1867, 0x2004, 0x0005, 0x0006, 0x2001, 0x1810, - 0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0b4, - 0x0005, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x0005, 0x0016, - 0x00e6, 0x2071, 0x189e, 0x7108, 0x910d, 0x710a, 0x00ee, 0x001e, - 0x0005, 0x79a4, 0x81ff, 0x0904, 0x35ea, 0x9182, 0x0081, 0x1a04, - 0x35ea, 0x810c, 0x0016, 0x080c, 0x4be4, 0x0170, 0x080c, 0x0f16, - 0x2100, 0x2238, 0x7d84, 0x7c88, 0x7b8c, 0x7a90, 0x001e, 0x080c, - 0x4c2d, 0x701f, 0x5819, 0x0005, 0x001e, 0x2009, 0x0002, 0x0804, - 0x35e7, 0x2079, 0x0000, 0x7d94, 0x7c98, 0x7ba8, 0x7aac, 0x79a4, - 0x810c, 0x2061, 0x18b8, 0x2c44, 0xa770, 0xa074, 0x2071, 0x189e, - 0x080c, 0x4c30, 0x701f, 0x582d, 0x0005, 0x2061, 0x18b8, 0x2c44, - 0x0016, 0x0026, 0xa270, 0xa174, 0x080c, 0x0f1e, 0x002e, 0x001e, - 0x080c, 0x0fcb, 0x9006, 0xa802, 0xa806, 0x0804, 0x35b5, 0x0126, - 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, 0x2071, 0x1800, 0x6044, - 0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c, 0x59ed, 0x0068, 0xd08c, - 0x0118, 0x080c, 0x58f6, 0x0040, 0xd094, 0x0118, 0x080c, 0x58c6, - 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x012e, 0x0005, 0x0016, - 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, 0x7030, - 0xd09c, 0x1120, 0x6004, 0x9085, 0x0002, 0x6006, 0x7098, 0x9005, - 0x0120, 0x709b, 0x0000, 0x7093, 0x0000, 0x624c, 0x9286, 0xf0f0, - 0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, - 0x6043, 0x0010, 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, 0x0178, - 0x7138, 0xd1a4, 0x1160, 0x6240, 0x9295, 0x0100, 0x6242, 0x9294, - 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x60aa, 0x00f0, 0x6040, - 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, 0x7087, - 0x0000, 0x70a3, 0x0001, 0x70c7, 0x0000, 0x70df, 0x0000, 0x2009, - 0x1c80, 0x200b, 0x0000, 0x7097, 0x0000, 0x708b, 0x000f, 0x2009, - 0x000f, 0x2011, 0x5f90, 0x080c, 0x88d5, 0x0005, 0x2001, 0x1869, - 0x2004, 0xd08c, 0x0110, 0x705f, 0xffff, 0x7088, 0x9005, 0x1528, - 0x2011, 0x5f90, 0x080c, 0x883d, 0x6040, 0x9094, 0x0010, 0x9285, - 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, - 0x58dc, 0x6242, 0x709b, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285, - 0x0080, 0x6042, 0x6242, 0x0048, 0x6242, 0x709b, 0x0000, 0x708f, - 0x0000, 0x9006, 0x080c, 0x6133, 0x0000, 0x0005, 0x708c, 0x908a, - 0x0003, 0x1a0c, 0x0dc5, 0x000b, 0x0005, 0x5900, 0x5951, 0x59ec, - 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, 0x708f, 0x0001, 0x2001, - 0x015d, 0x2003, 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800, - 0x9084, 0x00fc, 0x0120, 0x1f04, 0x590f, 0x080c, 0x0dc5, 0x68a0, - 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, 0x1600, - 0x6902, 0x001e, 0x6837, 0x0020, 0x080c, 0x610f, 0x2079, 0x1c00, - 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, 0x1805, - 0x20e9, 0x0001, 0x20a1, 0x1c0e, 0x20a9, 0x0004, 0x4003, 0x080c, - 0xaf8e, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, - 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000, - 0x080c, 0x5fc1, 0x00fe, 0x9006, 0x7092, 0x6043, 0x0008, 0x6042, - 0x0005, 0x00f6, 0x7090, 0x7093, 0x0000, 0x9025, 0x0904, 0x59c9, - 0x6020, 0xd0b4, 0x1904, 0x59c7, 0x71a0, 0x81ff, 0x0904, 0x59b5, - 0x9486, 0x000c, 0x1904, 0x59c2, 0x9480, 0x0018, 0x8004, 0x20a8, - 0x080c, 0x6108, 0x2011, 0x0260, 0x2019, 0x1c00, 0x220c, 0x2304, - 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, 0x596e, 0x6043, 0x0004, - 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, - 0x6043, 0x0006, 0x708f, 0x0002, 0x709b, 0x0002, 0x2009, 0x07d0, - 0x2011, 0x5f97, 0x080c, 0x88d5, 0x080c, 0x610f, 0x04c0, 0x080c, - 0x6108, 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, 0x7834, - 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005, - 0x0190, 0x080c, 0x6108, 0x2011, 0x026e, 0x2019, 0x1805, 0x20a9, - 0x0004, 0x220c, 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318, - 0x1f04, 0x59a9, 0x0078, 0x70a3, 0x0000, 0x080c, 0x6108, 0x20e1, - 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, 0x20a1, 0x1c00, 0x20a9, - 0x0014, 0x4003, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00fe, - 0x0005, 0x6040, 0x9085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, - 0x080c, 0xaf8e, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, - 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011, - 0x19f2, 0x2013, 0x0000, 0x7093, 0x0000, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x080c, 0xa6e0, 0x08d8, 0x0005, 0x7098, 0x908a, 0x001d, - 0x1a0c, 0x0dc5, 0x000b, 0x0005, 0x5a1e, 0x5a31, 0x5a5a, 0x5a7a, - 0x5aa0, 0x5acf, 0x5af5, 0x5b2d, 0x5b53, 0x5b81, 0x5bbc, 0x5bf4, - 0x5c12, 0x5c3d, 0x5c5f, 0x5c7a, 0x5c84, 0x5cb8, 0x5cde, 0x5d0d, - 0x5d33, 0x5d6b, 0x5daf, 0x5dec, 0x5e0d, 0x5e66, 0x5e88, 0x5eb6, - 0x5eb6, 0x00c6, 0x2061, 0x1800, 0x6003, 0x0007, 0x2061, 0x0100, - 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, 0x0140, - 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0002, - 0x709b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x5f97, 0x080c, 0x88d5, - 0x0005, 0x00f6, 0x7090, 0x9086, 0x0014, 0x1510, 0x6042, 0x6020, - 0xd0b4, 0x11f0, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128, - 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x2011, 0x5f97, 0x080c, - 0x883d, 0x709b, 0x0010, 0x080c, 0x5c84, 0x0010, 0x7093, 0x0000, - 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0003, 0x6043, 0x0004, 0x2011, - 0x5f97, 0x080c, 0x883d, 0x080c, 0x608c, 0x2079, 0x0240, 0x7833, - 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, 0x200b, - 0x0000, 0x8108, 0x1f04, 0x5a6f, 0x60c3, 0x0014, 0x080c, 0x5fc1, - 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5f97, - 0x080c, 0x883d, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6108, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, 0x1160, - 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, - 0x709b, 0x0004, 0x0029, 0x0010, 0x080c, 0x60e4, 0x00fe, 0x0005, - 0x00f6, 0x709b, 0x0005, 0x080c, 0x608c, 0x2079, 0x0240, 0x7833, - 0x1103, 0x7837, 0x0000, 0x080c, 0x6108, 0x080c, 0x60eb, 0x1170, - 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, 0x2011, - 0x0008, 0x080c, 0x5f44, 0x0168, 0x080c, 0x60c1, 0x20a9, 0x0008, - 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, - 0x4003, 0x60c3, 0x0014, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x0500, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, - 0x0014, 0x11b8, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, - 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0006, 0x0029, - 0x0010, 0x080c, 0x60e4, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0007, - 0x080c, 0x608c, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, - 0x080c, 0x6108, 0x080c, 0x60eb, 0x11b8, 0x7084, 0x9005, 0x11a0, - 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, 0x33b6, 0x200d, 0x918c, - 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5f44, 0x0180, 0x080c, - 0x50d1, 0x0110, 0x080c, 0x28dc, 0x20a9, 0x0008, 0x20e1, 0x0000, - 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, - 0x0014, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x0500, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0014, 0x11b8, - 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, - 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, - 0x1110, 0x70c7, 0x0001, 0x709b, 0x0008, 0x0029, 0x0010, 0x080c, - 0x60e4, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0009, 0x080c, 0x608c, - 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, 0x60eb, - 0x1150, 0x7084, 0x9005, 0x1138, 0x080c, 0x5eb7, 0x1188, 0x9085, - 0x0001, 0x080c, 0x28dc, 0x20a9, 0x0008, 0x080c, 0x6108, 0x20e1, - 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, - 0x60c3, 0x0014, 0x080c, 0x5fc1, 0x0010, 0x080c, 0x5a11, 0x00fe, - 0x0005, 0x00f6, 0x7090, 0x9005, 0x05a8, 0x2011, 0x5f97, 0x080c, - 0x883d, 0x9086, 0x0014, 0x1560, 0x080c, 0x6108, 0x2079, 0x0260, - 0x7a30, 0x9296, 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, 0x2011, - 0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, - 0x1110, 0x70c7, 0x0001, 0x709b, 0x000a, 0x00b1, 0x0098, 0x9005, - 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, - 0x0001, 0x7097, 0x0000, 0x709b, 0x000e, 0x080c, 0x5c5f, 0x0010, - 0x080c, 0x60e4, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000b, 0x2011, - 0x1c0e, 0x20e9, 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, - 0x4304, 0x080c, 0x608c, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, - 0x0000, 0x080c, 0x60eb, 0x0118, 0x2013, 0x0000, 0x0020, 0x7060, - 0x9085, 0x0100, 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, 0x2011, - 0x1c0e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, - 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x5be1, 0x60c3, 0x0084, - 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01c0, - 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084, 0x1178, 0x080c, - 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834, - 0x9005, 0x1120, 0x709b, 0x000c, 0x0029, 0x0010, 0x080c, 0x60e4, - 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000d, 0x080c, 0x608c, 0x2079, - 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, 0x6108, 0x20a9, - 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, 0x8108, - 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, - 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5c25, 0x60c3, - 0x0084, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x01e0, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084, 0x1198, - 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158, - 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, 0x605e, 0x709b, - 0x000e, 0x0029, 0x0010, 0x080c, 0x60e4, 0x00fe, 0x0005, 0x918d, - 0x0001, 0x080c, 0x6133, 0x709b, 0x000f, 0x7093, 0x0000, 0x2061, - 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043, - 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x5f97, 0x080c, - 0x8831, 0x0005, 0x7090, 0x9005, 0x0130, 0x2011, 0x5f97, 0x080c, - 0x883d, 0x709b, 0x0000, 0x0005, 0x709b, 0x0011, 0x080c, 0xaf8e, - 0x080c, 0x6108, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000, - 0x20a1, 0x0240, 0x7490, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, - 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, 0x60eb, 0x11a0, 0x717c, - 0x81ff, 0x0188, 0x900e, 0x7080, 0x9084, 0x00ff, 0x0160, 0x080c, - 0x2873, 0x9186, 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, 0x2011, - 0x0008, 0x080c, 0x5f44, 0x60c3, 0x0014, 0x080c, 0x5fc1, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5f97, 0x080c, 0x883d, - 0x9086, 0x0014, 0x11b8, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0012, - 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, - 0x0013, 0x080c, 0x609a, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, - 0x0000, 0x080c, 0x6108, 0x080c, 0x60eb, 0x1170, 0x7084, 0x9005, - 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, - 0x5f44, 0x0168, 0x080c, 0x60c1, 0x20a9, 0x0008, 0x20e1, 0x0000, - 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, - 0x0014, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x0500, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0014, 0x11b8, - 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178, - 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, - 0x1110, 0x70c7, 0x0001, 0x709b, 0x0014, 0x0029, 0x0010, 0x7093, - 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0015, 0x080c, 0x609a, - 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x6108, - 0x080c, 0x60eb, 0x11b8, 0x7084, 0x9005, 0x11a0, 0x7164, 0x9186, - 0xffff, 0x0180, 0x9180, 0x33b6, 0x200d, 0x918c, 0xff00, 0x810f, - 0x2011, 0x0008, 0x080c, 0x5f44, 0x0180, 0x080c, 0x50d1, 0x0110, - 0x080c, 0x28dc, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, - 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, - 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x05f0, 0x2011, - 0x5f97, 0x080c, 0x883d, 0x9086, 0x0014, 0x15a8, 0x080c, 0x6108, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, 0x9084, - 0x0100, 0x2011, 0x0100, 0x921e, 0x1168, 0x9085, 0x0001, 0x080c, - 0x6133, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, - 0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, 0x70c4, - 0x9005, 0x1110, 0x70c7, 0x0001, 0x9085, 0x0001, 0x080c, 0x6133, - 0x7097, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70df, 0x0008, 0x709b, - 0x0016, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x080c, - 0xaf8e, 0x080c, 0x6108, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, - 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, 0x026d, - 0x2204, 0x9084, 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, 0x026e, - 0x709b, 0x0017, 0x080c, 0x60eb, 0x1150, 0x7084, 0x9005, 0x1138, - 0x080c, 0x5eb7, 0x1188, 0x9085, 0x0001, 0x080c, 0x28dc, 0x20a9, - 0x0008, 0x080c, 0x6108, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, - 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5fc1, - 0x0010, 0x080c, 0x5a11, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01d8, - 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084, 0x1190, 0x080c, - 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, 0x7834, - 0x9005, 0x1138, 0x9006, 0x080c, 0x6133, 0x709b, 0x0018, 0x0029, - 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0019, - 0x080c, 0x609a, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000, - 0x080c, 0x6108, 0x2009, 0x026e, 0x2039, 0x1c0e, 0x20a9, 0x0040, - 0x213e, 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, 0x8000, - 0x6816, 0x2009, 0x0260, 0x1f04, 0x5e20, 0x2039, 0x1c0e, 0x080c, - 0x60eb, 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000, - 0x2018, 0x9294, 0x00ff, 0x8007, 0x9205, 0x202a, 0x7060, 0x2310, - 0x8214, 0x92a0, 0x1c0e, 0x2414, 0x938c, 0x0001, 0x0118, 0x9294, - 0xff00, 0x0018, 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9, - 0x0040, 0x2009, 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, 0x0260, - 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x5e53, - 0x60c3, 0x0084, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, - 0x9005, 0x01e0, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084, - 0x1198, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, - 0x1158, 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, 0x605e, - 0x709b, 0x001a, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, - 0x9085, 0x0001, 0x080c, 0x6133, 0x709b, 0x001b, 0x080c, 0xaf8e, - 0x080c, 0x6108, 0x2011, 0x0260, 0x2009, 0x0240, 0x7490, 0x9480, - 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x220e, - 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, - 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, - 0x5e9f, 0x60c3, 0x0084, 0x080c, 0x5fc1, 0x0005, 0x0005, 0x0086, - 0x0096, 0x2029, 0x1848, 0x252c, 0x20a9, 0x0008, 0x2041, 0x1c0e, - 0x20e9, 0x0001, 0x28a0, 0x080c, 0x6108, 0x20e1, 0x0000, 0x2099, - 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108, - 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, 0xd5d4, - 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x5ed1, 0x0804, 0x5f40, - 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, 0x0020, - 0x91a6, 0x3fff, 0x0904, 0x5f40, 0x918d, 0xc000, 0x20a9, 0x0010, - 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, - 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, - 0x0008, 0x8318, 0x1f04, 0x5ef7, 0x04d8, 0x23a8, 0x2021, 0x0001, - 0x8426, 0x8425, 0x1f04, 0x5f09, 0x2328, 0x8529, 0x92be, 0x0007, - 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, 0x27a8, - 0x95a8, 0x0010, 0x1f04, 0x5f18, 0x755e, 0x95c8, 0x33b6, 0x292d, - 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, - 0x28bc, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0x9405, - 0x201a, 0x7087, 0x0001, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20e1, - 0x0001, 0x2898, 0x20a9, 0x0008, 0x4003, 0x9085, 0x0001, 0x0008, - 0x9006, 0x009e, 0x008e, 0x0005, 0x0156, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x22a8, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, - 0x2011, 0x024e, 0x22a0, 0x4003, 0x014e, 0x013e, 0x01de, 0x01ce, - 0x015e, 0x2118, 0x9026, 0x2001, 0x0007, 0x939a, 0x0010, 0x0218, - 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0x939a, 0x0010, - 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, - 0x1de8, 0x9238, 0x2029, 0x026e, 0x9528, 0x2504, 0x942c, 0x11b8, - 0x9405, 0x203a, 0x715e, 0x91a0, 0x33b6, 0x242d, 0x95ac, 0x00ff, - 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x28bc, 0x001e, - 0x60e7, 0x0000, 0x65ea, 0x7087, 0x0001, 0x9084, 0x0000, 0x0005, - 0x00e6, 0x2071, 0x1800, 0x708b, 0x0000, 0x00ee, 0x0005, 0x00e6, - 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x604d, 0x080c, - 0xa6e9, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, 0x2d49, 0x0126, - 0x2091, 0x8000, 0x2071, 0x1826, 0x2073, 0x0000, 0x7840, 0x0026, - 0x0016, 0x2009, 0x00f7, 0x080c, 0x60aa, 0x001e, 0x9094, 0x0010, - 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee, - 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x2bce, 0x0228, 0x2011, - 0x0101, 0x2204, 0xc0c5, 0x2012, 0x2011, 0x19f2, 0x2013, 0x0000, - 0x7093, 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, - 0xa6e0, 0x6144, 0xd184, 0x0120, 0x7198, 0x918d, 0x2000, 0x0018, - 0x718c, 0x918d, 0x1000, 0x2011, 0x1999, 0x2112, 0x2009, 0x07d0, - 0x2011, 0x5f97, 0x080c, 0x88d5, 0x0005, 0x0016, 0x0026, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0xb244, 0x2009, 0x00f7, 0x080c, - 0x60aa, 0x2061, 0x19fb, 0x900e, 0x611a, 0x611e, 0x617a, 0x617e, - 0x2061, 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, - 0x6043, 0x0010, 0x2009, 0x1999, 0x200b, 0x0000, 0x2009, 0x002d, - 0x2011, 0x6019, 0x080c, 0x8831, 0x012e, 0x00ce, 0x002e, 0x001e, - 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, 0x2071, - 0x0100, 0x080c, 0xa6e9, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, - 0x0110, 0x080c, 0x2d49, 0x080c, 0x763f, 0x0188, 0x080c, 0x765a, - 0x1170, 0x080c, 0x793c, 0x0016, 0x080c, 0x298b, 0x2001, 0x196d, - 0x2102, 0x001e, 0x080c, 0x7937, 0x080c, 0x7563, 0x0050, 0x2009, - 0x0001, 0x080c, 0x2c67, 0x2001, 0x0001, 0x080c, 0x281c, 0x080c, - 0x5fed, 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, 0x2004, - 0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x1999, - 0x201c, 0x080c, 0x4c44, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, - 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x080c, 0x6108, 0x20e9, 0x0000, - 0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x6102, 0x2099, - 0x0260, 0x20a1, 0x1c92, 0x0051, 0x20a9, 0x000e, 0x080c, 0x6105, - 0x2099, 0x0260, 0x20a1, 0x1cb2, 0x0009, 0x0005, 0x0016, 0x0026, - 0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, - 0x6082, 0x002e, 0x001e, 0x0005, 0x080c, 0xaf8e, 0x20e1, 0x0001, - 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, - 0x4003, 0x0005, 0x080c, 0xaf8e, 0x080c, 0x6108, 0x20e1, 0x0000, - 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, - 0x4003, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, - 0x1834, 0x2004, 0x9005, 0x1138, 0x2001, 0x1818, 0x2004, 0x9084, - 0x00ff, 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, - 0x0005, 0x0016, 0x0046, 0x080c, 0x6a9f, 0x0158, 0x9006, 0x2020, - 0x2009, 0x002a, 0x080c, 0xec31, 0x2001, 0x180c, 0x200c, 0xc195, - 0x2102, 0x2019, 0x002a, 0x900e, 0x080c, 0x321b, 0x080c, 0xd7e3, - 0x0140, 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x4dfb, - 0x003e, 0x004e, 0x001e, 0x0005, 0x080c, 0x5fed, 0x709b, 0x0000, - 0x7093, 0x0000, 0x0005, 0x0006, 0x2001, 0x180c, 0x2004, 0xd09c, - 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, - 0x2001, 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, - 0x000e, 0x0005, 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, - 0x900e, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, - 0x0156, 0x0146, 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, - 0x20a1, 0x1c00, 0x4004, 0x2079, 0x1c00, 0x7803, 0x2200, 0x7807, - 0x00ef, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, - 0xffff, 0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1800, - 0x2003, 0x0001, 0x0005, 0x2001, 0x19a7, 0x0118, 0x2003, 0x0001, - 0x0010, 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, 0x2009, - 0x1000, 0x9006, 0x200a, 0x8108, 0x1f04, 0x6142, 0x015e, 0x0005, - 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x1847, 0x9006, - 0xb802, 0xb8ce, 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, 0x9198, - 0x33b6, 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, 0xb8c2, - 0x080c, 0xb23d, 0x1120, 0x9192, 0x007e, 0x1208, 0xbbc2, 0x20a9, - 0x0004, 0xb8c4, 0x20e8, 0xb9c8, 0x9198, 0x0006, 0x9006, 0x23a0, - 0x4004, 0x20a9, 0x0004, 0x9198, 0x000a, 0x23a0, 0x4004, 0x002e, - 0x001e, 0xb83e, 0xb842, 0xb84e, 0xb852, 0xb856, 0xb85a, 0xb85e, - 0xb862, 0xb866, 0xb86a, 0xb86f, 0x0100, 0xb872, 0xb876, 0xb87a, - 0xb88a, 0xb88e, 0xb893, 0x0008, 0xb896, 0xb89a, 0xb89e, 0xb8be, - 0xb9a2, 0x0096, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1040, 0xb8a7, - 0x0000, 0x009e, 0x9006, 0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846, - 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82, - 0x1cd0, 0x0a0c, 0x0dc5, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, - 0x0dc5, 0x080c, 0x8cf7, 0x00ce, 0x090c, 0x9096, 0xb8af, 0x0000, - 0x6814, 0x9084, 0x00ff, 0xb842, 0x014e, 0x013e, 0x015e, 0x003e, - 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0xa974, 0xae78, 0x9684, - 0x3fff, 0x9082, 0x4000, 0x1a04, 0x6230, 0x9182, 0x0800, 0x1a04, - 0x6234, 0x2001, 0x180c, 0x2004, 0x9084, 0x0003, 0x1904, 0x623a, - 0x9188, 0x1000, 0x2104, 0x905d, 0x0518, 0xb804, 0x9084, 0x00ff, - 0x908e, 0x0006, 0x1508, 0xb8a4, 0x900d, 0x1904, 0x624c, 0xb850, - 0x900d, 0x1148, 0xa802, 0x2900, 0xb852, 0xb84e, 0x080c, 0x951c, - 0x9006, 0x012e, 0x0005, 0x00a6, 0x2150, 0x2900, 0xb002, 0xa803, - 0x0000, 0x00ae, 0xb852, 0x0c90, 0x2001, 0x0005, 0x900e, 0x04b8, - 0x2001, 0x0028, 0x900e, 0x0498, 0x9082, 0x0006, 0x1290, 0x080c, - 0xb23d, 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, - 0x0990, 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, - 0x00a8, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, - 0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029, - 0xb900, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, 0x900e, 0x0038, - 0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, - 0x012e, 0x0005, 0x2001, 0x180c, 0x2004, 0xd084, 0x19d0, 0x9188, - 0x1000, 0x2104, 0x905d, 0x09a8, 0x080c, 0x6aa3, 0x1990, 0xb800, - 0xd0bc, 0x0978, 0x0804, 0x61e3, 0x080c, 0x68c0, 0x0904, 0x61fc, - 0x0804, 0x61e7, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa874, - 0x908e, 0x00ff, 0x1120, 0x2001, 0x196b, 0x205c, 0x0060, 0xa974, - 0x9182, 0x0800, 0x1690, 0x9188, 0x1000, 0x2104, 0x905d, 0x01d0, - 0x080c, 0x6a43, 0x11d0, 0x080c, 0xb27d, 0x0570, 0x2b00, 0x6012, - 0x2900, 0x6016, 0x6023, 0x0009, 0x600b, 0x0000, 0xa874, 0x908e, - 0x00ff, 0x1110, 0x600b, 0x8000, 0x2009, 0x0043, 0x080c, 0xb352, - 0x9006, 0x00b0, 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c, - 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, - 0x0004, 0x0010, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, - 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, 0x002c, 0x0cc0, 0x00b6, - 0x00e6, 0x0126, 0x2091, 0x8000, 0xa974, 0x9182, 0x0800, 0x1a04, - 0x631d, 0x9188, 0x1000, 0x2104, 0x905d, 0x0904, 0x62f5, 0xb8a0, - 0x9086, 0x007f, 0x0190, 0xa87c, 0xd0fc, 0x1178, 0x080c, 0x6aab, - 0x0160, 0xa994, 0x81ff, 0x0130, 0x908e, 0x0004, 0x0130, 0x908e, - 0x0005, 0x0118, 0x080c, 0x6aa3, 0x1598, 0xa87c, 0xd0fc, 0x01e0, - 0xa894, 0x9005, 0x01c8, 0x2060, 0x0026, 0x2010, 0x080c, 0xd0c6, - 0x002e, 0x1120, 0x2001, 0x0008, 0x0804, 0x631f, 0x6020, 0x9086, - 0x000a, 0x0120, 0x2001, 0x0008, 0x0804, 0x631f, 0x601a, 0x6003, - 0x0008, 0x2900, 0x6016, 0x0058, 0x080c, 0xb27d, 0x05e8, 0x2b00, - 0x6012, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x2009, - 0x0003, 0x080c, 0xb352, 0x9006, 0x0458, 0x2001, 0x0028, 0x0438, - 0x9082, 0x0006, 0x1290, 0x080c, 0xb23d, 0x1160, 0xb8a0, 0x9084, - 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0900, 0x2001, 0x0029, 0x2009, - 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c, - 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, - 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0x9005, - 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, 0x002c, 0x0cc0, 0x00f6, - 0x00b6, 0x0126, 0x2091, 0x8000, 0xa8e0, 0x9005, 0x1550, 0xa8dc, - 0x9082, 0x0101, 0x1630, 0xa8c8, 0x9005, 0x1518, 0xa8c4, 0x9082, - 0x0101, 0x12f8, 0xa974, 0x2079, 0x1800, 0x9182, 0x0800, 0x12e8, - 0x7830, 0x9084, 0x0003, 0x1130, 0xaa98, 0xab94, 0xa878, 0x9084, - 0x0007, 0x00ea, 0x7930, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, - 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, - 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, - 0x9006, 0x0008, 0x9005, 0x012e, 0x00be, 0x00fe, 0x0005, 0x63b4, - 0x636f, 0x6386, 0x63b4, 0x63b4, 0x63b4, 0x63b4, 0x63b4, 0x2100, - 0x9082, 0x007e, 0x1278, 0x080c, 0x66b9, 0x0148, 0x9046, 0xb810, - 0x9306, 0x1904, 0x63bc, 0xb814, 0x9206, 0x15f0, 0x0028, 0xbb12, - 0xba16, 0x0010, 0x080c, 0x4af7, 0x0150, 0x04b0, 0x080c, 0x6724, - 0x1598, 0xb810, 0x9306, 0x1580, 0xb814, 0x9206, 0x1568, 0x080c, - 0xb27d, 0x0530, 0x2b00, 0x6012, 0x080c, 0xd554, 0x2900, 0x6016, - 0x600b, 0xffff, 0x6023, 0x000a, 0xa878, 0x9086, 0x0001, 0x1170, - 0x080c, 0x3250, 0x9006, 0x080c, 0x6656, 0x2001, 0x0002, 0x080c, - 0x666a, 0x2001, 0x0200, 0xb86e, 0xb893, 0x0002, 0x2009, 0x0003, - 0x080c, 0xb352, 0x9006, 0x0068, 0x2001, 0x0001, 0x900e, 0x0038, - 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, 0x900e, 0x9005, - 0x0000, 0x012e, 0x00be, 0x00fe, 0x0005, 0x00b6, 0x00f6, 0x00e6, - 0x0126, 0x2091, 0x8000, 0xa894, 0x90c6, 0x0015, 0x0904, 0x65a7, - 0x90c6, 0x0056, 0x0904, 0x65ab, 0x90c6, 0x0066, 0x0904, 0x65af, - 0x90c6, 0x0067, 0x0904, 0x65b3, 0x90c6, 0x0068, 0x0904, 0x65b7, - 0x90c6, 0x0071, 0x0904, 0x65bb, 0x90c6, 0x0074, 0x0904, 0x65bf, - 0x90c6, 0x007c, 0x0904, 0x65c3, 0x90c6, 0x007e, 0x0904, 0x65c7, - 0x90c6, 0x0037, 0x0904, 0x65cb, 0x9016, 0x2079, 0x1800, 0xa974, - 0x9186, 0x00ff, 0x0904, 0x65a2, 0x9182, 0x0800, 0x1a04, 0x65a2, - 0x080c, 0x6724, 0x1198, 0xb804, 0x9084, 0x00ff, 0x9082, 0x0006, - 0x1268, 0xa894, 0x90c6, 0x006f, 0x0148, 0x080c, 0xb23d, 0x1904, - 0x658b, 0xb8a0, 0x9084, 0xff80, 0x1904, 0x658b, 0xa894, 0x90c6, - 0x006f, 0x0158, 0x90c6, 0x005e, 0x0904, 0x64eb, 0x90c6, 0x0064, - 0x0904, 0x6514, 0x2008, 0x0804, 0x64ad, 0xa998, 0xa8b0, 0x2040, - 0x080c, 0xb23d, 0x1120, 0x9182, 0x007f, 0x0a04, 0x64ad, 0x9186, - 0x00ff, 0x0904, 0x64ad, 0x9182, 0x0800, 0x1a04, 0x64ad, 0xaaa0, - 0xab9c, 0x787c, 0x9306, 0x11a8, 0x7880, 0x0096, 0x924e, 0x1128, - 0x2208, 0x2310, 0x009e, 0x0804, 0x64ad, 0x080c, 0xb23d, 0x1140, - 0x99cc, 0xff00, 0x009e, 0x1128, 0x2208, 0x2310, 0x0804, 0x64ad, - 0x009e, 0x080c, 0x4af7, 0x0904, 0x64b7, 0x900e, 0x9016, 0x90c6, - 0x4000, 0x15e0, 0x0006, 0x080c, 0x6944, 0x1108, 0xc185, 0xb800, - 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, - 0x2098, 0x080c, 0x0f8b, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0035, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, - 0x2098, 0x080c, 0x0f8b, 0xa8c4, 0xabc8, 0x9305, 0xabcc, 0x9305, - 0xabd0, 0x9305, 0xabd4, 0x9305, 0xabd8, 0x9305, 0xabdc, 0x9305, - 0xabe0, 0x9305, 0x9005, 0x0510, 0x000e, 0x00c8, 0x90c6, 0x4007, - 0x1110, 0x2408, 0x00a0, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, - 0x0070, 0x90c6, 0x4009, 0x1108, 0x0050, 0x90c6, 0x4006, 0x0138, - 0x2001, 0x4005, 0x2009, 0x000a, 0x0010, 0x2001, 0x4006, 0xa896, - 0xa99a, 0xaa9e, 0x2001, 0x0030, 0x900e, 0x0478, 0x000e, 0x080c, - 0xb27d, 0x1130, 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c78, - 0x2b00, 0x6012, 0x080c, 0xd554, 0x2900, 0x6016, 0x6023, 0x0001, - 0xa868, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0x0126, 0x2091, 0x8000, - 0x080c, 0x3250, 0x012e, 0x9006, 0x080c, 0x6656, 0x2001, 0x0002, - 0x080c, 0x666a, 0x2009, 0x0002, 0x080c, 0xb352, 0xa8b0, 0xd094, - 0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x9006, 0x9005, 0x012e, 0x00ee, - 0x00fe, 0x00be, 0x0005, 0x080c, 0x57e9, 0x0118, 0x2009, 0x0007, - 0x00f8, 0xa998, 0xaeb0, 0x080c, 0x6724, 0x1904, 0x64a8, 0x9186, - 0x007f, 0x0130, 0x080c, 0x6aa3, 0x0118, 0x2009, 0x0009, 0x0080, - 0x0096, 0x080c, 0x100e, 0x1120, 0x009e, 0x2009, 0x0002, 0x0040, - 0x2900, 0x009e, 0xa806, 0x080c, 0xd2c0, 0x19b0, 0x2009, 0x0003, - 0x2001, 0x4005, 0x0804, 0x64af, 0xa998, 0xaeb0, 0x080c, 0x6724, - 0x1904, 0x64a8, 0x0096, 0x080c, 0x100e, 0x1128, 0x009e, 0x2009, - 0x0002, 0x0804, 0x6568, 0x2900, 0x009e, 0xa806, 0x0096, 0x2048, - 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, 0x2098, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080, - 0x0006, 0x20a0, 0xbbc8, 0x9398, 0x0006, 0x2398, 0x080c, 0x0f8b, - 0x009e, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xd684, - 0x1168, 0x080c, 0x57d5, 0xd0b4, 0x1118, 0xa89b, 0x000b, 0x00e0, - 0xb800, 0xd08c, 0x0118, 0xa89b, 0x000c, 0x00b0, 0x080c, 0x6aa3, - 0x0118, 0xa89b, 0x0009, 0x0080, 0x080c, 0x57e9, 0x0118, 0xa89b, - 0x0007, 0x0050, 0x080c, 0xd2a3, 0x1904, 0x64e4, 0x2009, 0x0003, - 0x2001, 0x4005, 0x0804, 0x64af, 0xa87b, 0x0030, 0xa897, 0x4005, - 0xa804, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, - 0x2031, 0x0000, 0x2041, 0x1252, 0x080c, 0xb7f1, 0x1904, 0x64e4, - 0x2009, 0x0002, 0x08e8, 0x2001, 0x0028, 0x900e, 0x0804, 0x64e5, - 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, - 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e, - 0x0804, 0x64e5, 0x2001, 0x0029, 0x900e, 0x0804, 0x64e5, 0x080c, - 0x37e9, 0x0804, 0x64e6, 0x080c, 0x5500, 0x0804, 0x64e6, 0x080c, - 0x4637, 0x0804, 0x64e6, 0x080c, 0x46b0, 0x0804, 0x64e6, 0x080c, - 0x470c, 0x0804, 0x64e6, 0x080c, 0x4bba, 0x0804, 0x64e6, 0x080c, - 0x4e82, 0x0804, 0x64e6, 0x080c, 0x5167, 0x0804, 0x64e6, 0x080c, - 0x5360, 0x0804, 0x64e6, 0x080c, 0x3a25, 0x0804, 0x64e6, 0x00b6, - 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1618, 0x9182, - 0x0800, 0x1268, 0x9188, 0x1000, 0x2104, 0x905d, 0x0140, 0x080c, - 0x6aa3, 0x1148, 0x00e9, 0x080c, 0x684f, 0x9006, 0x00b0, 0x2001, - 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, 0xb900, 0xd1fc, - 0x0d88, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, 0x0029, - 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x00be, 0x0005, - 0x0126, 0x2091, 0x8000, 0xb850, 0x900d, 0x0150, 0x2900, 0x0096, - 0x2148, 0xa802, 0x009e, 0xa803, 0x0000, 0xb852, 0x012e, 0x0005, - 0x2900, 0xb852, 0xb84e, 0xa803, 0x0000, 0x0cc0, 0x0126, 0x2091, - 0x8000, 0xb84c, 0x9005, 0x0170, 0x00e6, 0x2071, 0x19e8, 0x7004, - 0x9086, 0x0002, 0x0168, 0x00ee, 0xb84c, 0xa802, 0x2900, 0xb84e, - 0x012e, 0x0005, 0x2900, 0xb852, 0xb84e, 0xa803, 0x0000, 0x0cc0, - 0x701c, 0x9b06, 0x1d80, 0xb84c, 0x00a6, 0x2050, 0xb000, 0xa802, - 0x2900, 0xb002, 0x00ae, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, - 0x8000, 0xb84c, 0x904d, 0x0130, 0xa800, 0x9005, 0x1108, 0xb852, - 0xb84e, 0x9905, 0x012e, 0x0005, 0xb84c, 0x904d, 0x0130, 0xa800, - 0x9005, 0x1108, 0xb852, 0xb84e, 0x9905, 0x0005, 0x00b6, 0x0126, - 0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, 0x2258, 0xba00, 0x9005, - 0x0110, 0xc285, 0x0008, 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e, - 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, - 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1170, 0xb89c, 0xd0ac, - 0x0158, 0x080c, 0x6a9f, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, - 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, - 0xba06, 0x0006, 0x9086, 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c, - 0x0dc5, 0x000e, 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, - 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, - 0x0006, 0x1168, 0xb89c, 0xd0a4, 0x0150, 0x080c, 0x6a9b, 0x1138, - 0x9284, 0x00ff, 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, - 0x9294, 0x00ff, 0x8007, 0x9215, 0xba06, 0x00ce, 0x012e, 0x00be, - 0x0005, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0005, 0x00d6, - 0x0026, 0x9190, 0x1000, 0x2204, 0x905d, 0x1188, 0x0096, 0x080c, - 0x100e, 0x2958, 0x009e, 0x0168, 0x2b00, 0x2012, 0xb85c, 0xb8ca, - 0xb860, 0xb8c6, 0x9006, 0xb8a6, 0xb8ae, 0x080c, 0x6148, 0x9006, - 0x0010, 0x9085, 0x0001, 0x002e, 0x00de, 0x0005, 0x00b6, 0x0096, - 0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x0800, 0x0218, 0x9085, - 0x0001, 0x04a8, 0x00d6, 0x9190, 0x1000, 0x2204, 0x905d, 0x0568, - 0x2013, 0x0000, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1040, 0x00d6, - 0x00c6, 0xb8bc, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, - 0x2048, 0x080c, 0xd0d8, 0x0110, 0x080c, 0x0fc0, 0x080c, 0xb2d3, - 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x00c6, 0xb8ac, 0x9065, 0x0128, - 0x621c, 0xd2c4, 0x0110, 0x080c, 0x9096, 0x00ce, 0x2b48, 0xb8c8, - 0xb85e, 0xb8c4, 0xb862, 0x080c, 0x1050, 0x00de, 0x9006, 0x002e, - 0x012e, 0x009e, 0x00be, 0x0005, 0x0016, 0x9182, 0x0800, 0x0218, - 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, 0x905d, 0x0dc0, - 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006, - 0xb80a, 0xb80e, 0xb800, 0xc08c, 0xb802, 0x080c, 0x7637, 0x1510, - 0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, 0xb23d, 0x11d8, 0x0078, - 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x1982, 0x7048, 0x2062, - 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c, - 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, - 0x1800, 0x68b6, 0x7040, 0xb85e, 0x7048, 0xb862, 0x704c, 0xb866, - 0x20e1, 0x0000, 0x2099, 0x0276, 0xb8c4, 0x20e8, 0xb8c8, 0x9088, - 0x000a, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, 0x027a, 0x9088, - 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, 0x0200, 0x6817, - 0x0001, 0x7040, 0xb86a, 0x7144, 0xb96e, 0x7048, 0xb872, 0x7050, - 0xb876, 0x2069, 0x0200, 0x6817, 0x0000, 0xb8a0, 0x9086, 0x007e, - 0x1110, 0x7144, 0xb96e, 0x9182, 0x0211, 0x1218, 0x2009, 0x0008, - 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0x9182, - 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, 0x0349, 0x1218, - 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, 0x2009, 0x0004, - 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, - 0x0002, 0xb992, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, - 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, 0xb896, 0x703c, 0xb89a, - 0x7054, 0xb89e, 0x0036, 0xbbcc, 0xc384, 0xba00, 0x2009, 0x1867, - 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, - 0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, 0x0128, 0xd38c, - 0x1108, 0xc385, 0x0008, 0xc2bc, 0xba02, 0xbbce, 0x003e, 0x00ee, - 0x002e, 0x001e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, - 0x904d, 0x0578, 0xa900, 0x81ff, 0x15c0, 0xaa04, 0x9282, 0x0010, - 0x16c8, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x8906, 0x8006, 0x8007, - 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9080, 0x0004, 0x2098, - 0x2009, 0x0010, 0x20a9, 0x0001, 0x4002, 0x9086, 0xffff, 0x0120, - 0x8109, 0x1dd0, 0x080c, 0x0dc5, 0x3c00, 0x20e8, 0x3300, 0x8001, - 0x20a0, 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, 0x014e, 0x013e, - 0x0060, 0x080c, 0x100e, 0x0170, 0x2900, 0xb8a6, 0xa803, 0x0000, - 0x080c, 0x68e0, 0xa807, 0x0001, 0xae12, 0x9085, 0x0001, 0x012e, - 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x0096, - 0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, 0x080c, 0x68ef, - 0x1158, 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, 0xa806, 0x0020, - 0x080c, 0x1040, 0xb8a7, 0x0000, 0x009e, 0x012e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x080c, 0x951c, 0x012e, 0x0005, 0x901e, 0x0010, - 0x2019, 0x0001, 0x900e, 0x0126, 0x2091, 0x8000, 0xb84c, 0x2048, - 0xb800, 0xd0dc, 0x1170, 0x89ff, 0x0500, 0x83ff, 0x0120, 0xa878, - 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, - 0x0120, 0x2908, 0xa800, 0x2048, 0x0c70, 0x080c, 0xaaf1, 0xaa00, - 0xb84c, 0x9906, 0x1110, 0xba4e, 0x0020, 0x00a6, 0x2150, 0xb202, - 0x00ae, 0x82ff, 0x1110, 0xb952, 0x89ff, 0x012e, 0x0005, 0x9016, - 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, 0x6944, 0x0128, - 0x080c, 0xd195, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6944, - 0x0128, 0x080c, 0xd13a, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, - 0x6944, 0x0128, 0x080c, 0xd192, 0x0010, 0x9085, 0x0001, 0x0005, - 0x080c, 0x6944, 0x0128, 0x080c, 0xd159, 0x0010, 0x9085, 0x0001, - 0x0005, 0x080c, 0x6944, 0x0128, 0x080c, 0xd1d8, 0x0010, 0x9085, - 0x0001, 0x0005, 0xb8a4, 0x900d, 0x1118, 0x9085, 0x0001, 0x0005, - 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, 0x810f, - 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, 0x2098, - 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, 0x8109, - 0x1dd8, 0x9085, 0x0001, 0x0008, 0x9006, 0x01ce, 0x013e, 0x0005, - 0x0146, 0x01d6, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0004, 0x20a0, - 0x20a9, 0x0010, 0x2009, 0xffff, 0x4104, 0x01de, 0x014e, 0x0136, - 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, 0x810f, 0x9184, - 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, 0x2098, 0x20a9, - 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, 0x8109, 0x1dd8, - 0x9085, 0x0001, 0x0068, 0x0146, 0x01d6, 0x3300, 0x8001, 0x20a0, - 0x3c00, 0x20e8, 0x2001, 0xffff, 0x4004, 0x01de, 0x014e, 0x9006, - 0x01ce, 0x013e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, - 0x904d, 0x1128, 0x080c, 0x100e, 0x0168, 0x2900, 0xb8a6, 0x080c, - 0x68e0, 0xa803, 0x0001, 0xa807, 0x0000, 0x9085, 0x0001, 0x012e, - 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126, 0x2091, 0x8000, - 0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c, 0x1040, 0x9085, - 0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4, 0x0005, 0x00b6, - 0x00f6, 0x080c, 0x7637, 0x01b0, 0x71c4, 0x81ff, 0x1198, 0x71dc, - 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, 0x1000, 0x2004, 0x905d, - 0x0148, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1118, 0xb800, - 0xc0ed, 0xb802, 0x2079, 0x1847, 0x7804, 0xd0a4, 0x01d0, 0x0156, - 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6724, 0x1168, 0xb804, - 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, 0x9086, 0x0006, - 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, 0x1f04, 0x696b, - 0x015e, 0x080c, 0x6a61, 0x0120, 0x2001, 0x1985, 0x200c, 0x0098, - 0x2079, 0x1847, 0x7804, 0xd0a4, 0x0190, 0x2009, 0x07d0, 0x2001, - 0x182c, 0x2004, 0x9005, 0x0138, 0x2001, 0x1867, 0x2004, 0xd0e4, - 0x0110, 0x2009, 0x5dc0, 0x2011, 0x69a2, 0x080c, 0x88d5, 0x00fe, - 0x00be, 0x0005, 0x00b6, 0x2011, 0x69a2, 0x080c, 0x883d, 0x080c, - 0x6a61, 0x01d8, 0x2001, 0x107e, 0x2004, 0x2058, 0xb900, 0xc1ec, - 0xb902, 0x080c, 0x6a9f, 0x0130, 0x2009, 0x07d0, 0x2011, 0x69a2, - 0x080c, 0x88d5, 0x00e6, 0x2071, 0x1800, 0x9006, 0x707e, 0x7060, - 0x7082, 0x080c, 0x3000, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, - 0x007f, 0x900e, 0x0016, 0x080c, 0x6724, 0x1538, 0xb800, 0xd0ec, - 0x0520, 0x0046, 0xbaa0, 0x2220, 0x9006, 0x2009, 0x0029, 0x080c, - 0xec31, 0xb800, 0xc0e5, 0xc0ec, 0xb802, 0x080c, 0x6a9b, 0x2001, - 0x0707, 0x1128, 0xb804, 0x9084, 0x00ff, 0x9085, 0x0700, 0xb806, - 0x2019, 0x0029, 0x080c, 0x96a4, 0x0076, 0x903e, 0x080c, 0x9577, - 0x900e, 0x080c, 0xe91c, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, - 0x69ca, 0x00ce, 0x015e, 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058, - 0xb800, 0xc0ec, 0xb802, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x0096, - 0x080c, 0x1027, 0x090c, 0x0dc5, 0x2958, 0x009e, 0x2001, 0x196b, - 0x2b02, 0x8b07, 0x8006, 0x8006, 0x908c, 0x003f, 0xb9c6, 0x908c, - 0xffc0, 0xb9ca, 0xb8af, 0x0000, 0x2009, 0x00ff, 0x080c, 0x6148, - 0xb807, 0x0006, 0xb813, 0x00ff, 0xb817, 0xffff, 0xb86f, 0x0200, - 0xb86c, 0xb893, 0x0002, 0xb8bb, 0x0520, 0xb8a3, 0x00ff, 0xb8af, - 0x0000, 0x00ce, 0x00be, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0ac, 0x0005, 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800, - 0x00be, 0xd0bc, 0x0005, 0x0006, 0x0016, 0x0026, 0xb804, 0x908c, - 0x00ff, 0x9196, 0x0006, 0x0188, 0x9196, 0x0004, 0x0170, 0x9196, - 0x0005, 0x0158, 0x908c, 0xff00, 0x810f, 0x9196, 0x0006, 0x0128, - 0x9196, 0x0004, 0x0110, 0x9196, 0x0005, 0x002e, 0x001e, 0x000e, - 0x0005, 0x00b6, 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, - 0xb800, 0xd0ec, 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, - 0x8000, 0x0006, 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, - 0x0dc5, 0x000e, 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, - 0xba02, 0x002e, 0x012e, 0x0005, 0x2011, 0x1837, 0x2204, 0xd0cc, - 0x0138, 0x2001, 0x1983, 0x200c, 0x2011, 0x6a91, 0x080c, 0x88d5, - 0x0005, 0x2011, 0x6a91, 0x080c, 0x883d, 0x2011, 0x1837, 0x2204, - 0xc0cc, 0x2012, 0x0005, 0x080c, 0x57d5, 0xd0ac, 0x0005, 0x080c, - 0x57d5, 0xd0a4, 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, - 0x0006, 0x001e, 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, - 0x908e, 0x0006, 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xd7e3, - 0x0158, 0x70dc, 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, - 0x905d, 0x0110, 0xb8cc, 0xd094, 0x00fe, 0x00be, 0x0005, 0x0006, - 0x0016, 0x0036, 0x0046, 0x0076, 0x00b6, 0x2001, 0x1818, 0x203c, - 0x9780, 0x33b6, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2018, - 0x2008, 0x9284, 0x8000, 0x0110, 0x2019, 0x0001, 0x9294, 0x7fff, - 0x2100, 0x9706, 0x0190, 0x91a0, 0x1000, 0x2404, 0x905d, 0x0168, - 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1138, 0x83ff, 0x0118, - 0xb89c, 0xd0a4, 0x0110, 0x8211, 0x0158, 0x8108, 0x83ff, 0x0120, - 0x9182, 0x0800, 0x0e28, 0x0068, 0x9182, 0x007e, 0x0e08, 0x0048, - 0x00be, 0x007e, 0x004e, 0x003e, 0x001e, 0x9085, 0x0001, 0x000e, - 0x0005, 0x00be, 0x007e, 0x004e, 0x003e, 0x001e, 0x9006, 0x000e, - 0x0005, 0x0046, 0x0056, 0x0076, 0x00b6, 0x2100, 0x9084, 0x7fff, - 0x9080, 0x1000, 0x2004, 0x905d, 0x0130, 0xb804, 0x9084, 0x00ff, - 0x9086, 0x0006, 0x0550, 0x9184, 0x8000, 0x0580, 0x2001, 0x1818, - 0x203c, 0x9780, 0x33b6, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, - 0x2020, 0x2400, 0x9706, 0x01a0, 0x94a8, 0x1000, 0x2504, 0x905d, - 0x0178, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1148, 0xb89c, - 0xd0a4, 0x0130, 0xb814, 0x9206, 0x1118, 0xb810, 0x9306, 0x0128, - 0x8420, 0x9482, 0x0800, 0x0e28, 0x0048, 0x918c, 0x7fff, 0x00be, - 0x007e, 0x005e, 0x004e, 0x9085, 0x0001, 0x0005, 0x918c, 0x7fff, - 0x00be, 0x007e, 0x005e, 0x004e, 0x9006, 0x0005, 0x0006, 0x2001, - 0x00a0, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, 0x000e, 0x0005, - 0x0006, 0x2001, 0x00f8, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, - 0x000e, 0x0005, 0x0006, 0x2001, 0x00e8, 0x8001, 0xa001, 0xa001, - 0xa001, 0x1dd8, 0x000e, 0x0005, 0x2071, 0x1910, 0x7003, 0x0001, - 0x7007, 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, - 0x7046, 0x2001, 0x1922, 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, - 0x2071, 0x1948, 0x900e, 0x710a, 0x080c, 0x57d5, 0xd0fc, 0x1140, - 0x080c, 0x57d5, 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0470, - 0x2001, 0x1867, 0x200c, 0x9184, 0x0007, 0x0006, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x000e, 0x0108, 0x9006, 0x0002, 0x6b98, 0x6b98, - 0x6b98, 0x6b98, 0x6b98, 0x6bb6, 0x6bcb, 0x6bd9, 0x7003, 0x0003, - 0x2009, 0x1868, 0x210c, 0x9184, 0xff00, 0x908e, 0xff00, 0x0140, - 0x8007, 0x9005, 0x1110, 0x2001, 0x0002, 0x8003, 0x7006, 0x0030, - 0x7007, 0x0001, 0x0018, 0x7003, 0x0005, 0x0c50, 0x2071, 0x1910, - 0x704f, 0x0000, 0x2071, 0x1800, 0x70f3, 0x0001, 0x00ee, 0x001e, - 0x0005, 0x7003, 0x0000, 0x2071, 0x1910, 0x2009, 0x1868, 0x210c, - 0x9184, 0x7f00, 0x8007, 0x908c, 0x000f, 0x0160, 0x714e, 0x8004, - 0x8004, 0x8004, 0x8004, 0x2071, 0x1800, 0x908c, 0x0007, 0x0128, - 0x70f2, 0x0c20, 0x704f, 0x000f, 0x0c90, 0x70f3, 0x0005, 0x08f0, - 0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, 0x2071, - 0x1910, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0488, - 0x6844, 0x9005, 0x0158, 0x080c, 0x79a4, 0x6a60, 0x9200, 0x7002, - 0x6864, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, - 0x6864, 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, - 0x1110, 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, - 0x701e, 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x1910, - 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee, - 0x9006, 0x00ee, 0x0005, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000, - 0x9015, 0x0904, 0x6ea5, 0x9286, 0x0003, 0x0904, 0x6d3e, 0x9286, - 0x0005, 0x0904, 0x6d3e, 0x2071, 0x1877, 0xa87c, 0x9005, 0x0904, - 0x6c99, 0x7140, 0xa868, 0x9102, 0x0a04, 0x6ea5, 0xa878, 0xd084, - 0x15d8, 0xa853, 0x0019, 0x2001, 0x8023, 0xa84e, 0x2071, 0x1910, - 0x701c, 0x9005, 0x1904, 0x7073, 0x0e04, 0x70e1, 0x2071, 0x0000, - 0xa850, 0x7032, 0xa84c, 0x7082, 0xa870, 0x7086, 0xa86c, 0x708a, - 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, - 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, - 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, - 0x01de, 0x014e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x11aa, 0x0804, 0x6d21, 0xa853, 0x001b, 0x2001, 0x8027, - 0x0820, 0x7004, 0xd08c, 0x1904, 0x6ea5, 0xa853, 0x001a, 0x2001, - 0x8024, 0x0804, 0x6c5d, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000, - 0x9015, 0x0904, 0x6ea5, 0x9286, 0x0003, 0x0904, 0x6d3e, 0x9286, - 0x0005, 0x0904, 0x6d3e, 0xa84f, 0x8022, 0xa853, 0x0018, 0x0804, - 0x6d06, 0xa868, 0xd0fc, 0x1508, 0x00e6, 0x0026, 0x2001, 0x1948, - 0x2004, 0x9015, 0x0904, 0x6ea5, 0xa978, 0xa874, 0x9105, 0x1904, - 0x6ea5, 0x9286, 0x0003, 0x0904, 0x6d3e, 0x9286, 0x0005, 0x0904, - 0x6d3e, 0xa87c, 0xd0bc, 0x1904, 0x6ea5, 0x2200, 0x0002, 0x6ea5, - 0x6d02, 0x6d3e, 0x6d3e, 0x6ea5, 0x6d3e, 0x0005, 0xa868, 0xd0fc, - 0x1500, 0x00e6, 0x0026, 0x2009, 0x1948, 0x210c, 0x81ff, 0x0904, - 0x6ea5, 0xa880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x6ea5, - 0x9186, 0x0003, 0x0904, 0x6d3e, 0x9186, 0x0005, 0x0904, 0x6d3e, - 0xa87c, 0xd0cc, 0x0904, 0x6ea5, 0xa84f, 0x8021, 0xa853, 0x0017, - 0x0028, 0x0005, 0xa84f, 0x8020, 0xa853, 0x0016, 0x2071, 0x1910, - 0x701c, 0x9005, 0x1904, 0x7073, 0x0e04, 0x70e1, 0x2071, 0x0000, - 0xa84c, 0x7082, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, - 0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11aa, 0x2071, 0x1800, 0x2011, 0x0001, 0xa804, 0x900d, 0x702c, - 0x1158, 0xa802, 0x2900, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, - 0x8725, 0x002e, 0x00ee, 0x0005, 0x0096, 0x2148, 0xa904, 0xa802, - 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x009e, 0x0c58, 0xa84f, 0x0000, - 0x00f6, 0x2079, 0x0050, 0x2071, 0x1910, 0xa803, 0x0000, 0x7010, - 0x9005, 0x1904, 0x6e29, 0x782c, 0x908c, 0x0780, 0x190c, 0x722f, - 0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x6d5c, 0x6e29, - 0x6d80, 0x6dc6, 0x080c, 0x0dc5, 0x2071, 0x1800, 0x2900, 0x7822, - 0xa804, 0x900d, 0x1168, 0x2071, 0x19fb, 0x7044, 0x9005, 0x1320, - 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0c18, - 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1578, 0x7824, - 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x1830, - 0x210c, 0x918a, 0x0020, 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee, - 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, - 0x080c, 0x8725, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, - 0x19f0, 0x2071, 0x19fb, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, - 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, - 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, - 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0808, 0x0096, 0x00e6, - 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, 0x9094, 0x0780, - 0x190c, 0x722f, 0xd0a4, 0x1d60, 0x00ee, 0x782c, 0x9094, 0x0780, - 0x190c, 0x722f, 0xd09c, 0x1198, 0x009e, 0x2900, 0x7822, 0xa804, - 0x900d, 0x1550, 0x2071, 0x19fb, 0x7044, 0x9005, 0x1320, 0x2001, - 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x009e, - 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, - 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1168, 0x2071, - 0x19fb, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, 0x2004, 0x7046, - 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, - 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, - 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, - 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, - 0x6e7d, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd09c, 0x1198, - 0x701c, 0x904d, 0x0180, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a, - 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c, - 0x722f, 0xd09c, 0x0d68, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, - 0xd0a4, 0x01b0, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, - 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, - 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d60, 0x00ee, - 0x2071, 0x19fb, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, 0x2004, - 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x00ee, - 0x0804, 0x6e39, 0xa868, 0xd0fc, 0x1904, 0x6ef3, 0x0096, 0xa804, - 0xa807, 0x0000, 0x904d, 0x190c, 0x0fc0, 0x009e, 0x0020, 0xa868, - 0xd0fc, 0x1904, 0x6ef3, 0x00e6, 0x0026, 0xa84f, 0x0000, 0x00f6, - 0x2079, 0x0050, 0x2071, 0x1800, 0x70ec, 0x8001, 0x0558, 0x1a04, - 0x6ef0, 0x2071, 0x1910, 0xa803, 0x0000, 0xa864, 0x9084, 0x00ff, - 0x908e, 0x0016, 0x01a8, 0x7010, 0x9005, 0x1904, 0x6fef, 0x782c, - 0x908c, 0x0780, 0x190c, 0x722f, 0x8004, 0x8004, 0x8004, 0x9084, - 0x0003, 0x0002, 0x6ef4, 0x6fef, 0x6f0f, 0x6f80, 0x080c, 0x0dc5, - 0x2009, 0x1948, 0x2104, 0x0002, 0x6ebb, 0x6ebb, 0x6ebb, 0x6d47, - 0x6ebb, 0x6d47, 0x70ef, 0x0fa0, 0x71e8, 0x8107, 0x9106, 0x9094, - 0x00c0, 0x9184, 0xff3f, 0x9205, 0x70ea, 0x3b08, 0x3a00, 0x9104, - 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205, 0x20d0, 0x0808, - 0x70ee, 0x0804, 0x6eb1, 0x0005, 0x2071, 0x1800, 0x2900, 0x7822, - 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, - 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0c60, 0x2071, - 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1904, 0x6f6f, 0x7830, - 0x8007, 0x908c, 0x001f, 0x70f0, 0x9102, 0x1220, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, - 0x1148, 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, 0x0218, 0x7022, - 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, 0x9094, 0x0780, - 0x190c, 0x722f, 0xd0a4, 0x19f0, 0x0e04, 0x6f66, 0x7838, 0x7938, - 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, - 0x00de, 0x2001, 0x1921, 0x200c, 0xc184, 0x2102, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x2001, 0x1922, - 0x2003, 0x0000, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2001, 0x1921, - 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, - 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0804, 0x6f22, - 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, - 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, - 0x6fc2, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, - 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x704b, - 0x0000, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd09c, 0x1170, - 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x11e0, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c58, 0x009e, 0x2908, - 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, - 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, - 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, - 0x70c2, 0x080c, 0x8725, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, - 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, - 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, 0x705e, 0x782c, - 0x9094, 0x0780, 0x190c, 0x722f, 0xd09c, 0x11b0, 0x701c, 0x904d, - 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, 0x8001, 0x7012, 0x1108, - 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, - 0x190c, 0x722f, 0xd09c, 0x0d50, 0x782c, 0x9094, 0x0780, 0x190c, - 0x722f, 0xd0a4, 0x05b8, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, - 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x8725, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d60, - 0x00ee, 0x0e04, 0x7057, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, - 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, - 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x11aa, 0x704b, 0x0000, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, - 0xc085, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, - 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, - 0x00ee, 0x0804, 0x6fff, 0x2071, 0x1910, 0xa803, 0x0000, 0x2908, - 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, - 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1128, 0x1e04, 0x709e, - 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, - 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, - 0x9200, 0x70c2, 0x080c, 0x8725, 0x0e04, 0x7088, 0x2071, 0x1910, - 0x701c, 0x2048, 0xa84c, 0x900d, 0x0d18, 0x2071, 0x0000, 0x7182, - 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0xa850, - 0x9082, 0x0019, 0x1278, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x11aa, 0x2071, 0x1910, 0x080c, 0x721b, 0x002e, - 0x00ee, 0x0005, 0xa850, 0x9082, 0x001c, 0x1e68, 0xa880, 0x708e, - 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, - 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, - 0x0890, 0x2071, 0x1910, 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, - 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, - 0x2148, 0xa804, 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071, - 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, - 0x002e, 0x00ee, 0x0005, 0x0006, 0xa87c, 0x0006, 0xa867, 0x0103, - 0x20a9, 0x001c, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001d, 0x20a0, - 0x9006, 0x4004, 0x000e, 0x9084, 0x00ff, 0xa87e, 0x000e, 0xa87a, - 0xa982, 0x0005, 0x2071, 0x1910, 0x7004, 0x0002, 0x712e, 0x712f, - 0x721a, 0x712f, 0x712c, 0x721a, 0x080c, 0x0dc5, 0x0005, 0x2001, - 0x1948, 0x2004, 0x0002, 0x7139, 0x7139, 0x71b3, 0x71b4, 0x7139, - 0x71b4, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x723a, 0x701c, 0x904d, - 0x0508, 0xa84c, 0x9005, 0x0904, 0x7184, 0x0e04, 0x7162, 0xa94c, - 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, - 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, 0x1278, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x2071, 0x1910, - 0x080c, 0x721b, 0x012e, 0x0804, 0x71b2, 0xa850, 0x9082, 0x001c, - 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, - 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, - 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, - 0x013e, 0x01de, 0x014e, 0x0890, 0x2001, 0x005b, 0x2004, 0x9094, - 0x0780, 0x190c, 0x722f, 0xd09c, 0x2071, 0x1910, 0x1510, 0x2071, - 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086, 0x0003, - 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x2900, - 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, 0x1910, 0x701c, - 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, - 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, 0x2008, 0x2069, 0x19fb, - 0x6844, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, 0x0540, 0x2001, - 0x1815, 0x2004, 0x2009, 0x1ad1, 0x210c, 0x9102, 0x1500, 0x0126, - 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, 0x9106, 0x0190, - 0x0e04, 0x71e6, 0x2069, 0x0000, 0x6837, 0x8040, 0x6833, 0x0012, - 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x11aa, 0x2069, 0x19fb, 0x6847, 0xffff, 0x012e, 0x00de, - 0x0126, 0x2091, 0x8000, 0x1e0c, 0x72a5, 0x701c, 0x904d, 0x0540, - 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x15c9, 0xd09c, 0x1500, - 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086, - 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, - 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x701c, 0x2048, - 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, 0x701a, - 0x012e, 0x0005, 0x0005, 0x0126, 0x2091, 0x8000, 0x701c, 0x904d, - 0x0160, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, - 0x701a, 0x012e, 0x080c, 0x1040, 0x0005, 0x012e, 0x0005, 0x2091, - 0x8000, 0x0e04, 0x7231, 0x0006, 0x0016, 0x2001, 0x8004, 0x0006, - 0x0804, 0x0dce, 0x0096, 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084, - 0x01d0, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, - 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x704b, 0x0000, - 0x00fe, 0x009e, 0x0005, 0x782c, 0x9094, 0x0780, 0x1981, 0xd0a4, - 0x0db8, 0x7148, 0x704c, 0x8108, 0x714a, 0x9102, 0x0e88, 0x00e6, - 0x2071, 0x1800, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, - 0x1148, 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, 0x0218, 0x7022, - 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, 0x9094, 0x0780, - 0x190c, 0x722f, 0xd0a4, 0x19f0, 0x7838, 0x7938, 0x910e, 0x1de0, - 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x00ee, - 0x704b, 0x0000, 0x00fe, 0x009e, 0x0005, 0x00f6, 0x2079, 0x0050, - 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, - 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, - 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, - 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, - 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d70, 0x00d6, 0x2069, - 0x0050, 0x693c, 0x2069, 0x1948, 0x6808, 0x690a, 0x2069, 0x19fb, - 0x9102, 0x1118, 0x6844, 0x9005, 0x1320, 0x2001, 0x1949, 0x200c, - 0x6946, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7098, 0x908a, 0x002a, - 0x1a0c, 0x0dc5, 0x9082, 0x001d, 0x001b, 0x6027, 0x1e00, 0x0005, - 0x73e6, 0x7353, 0x736f, 0x7399, 0x73d5, 0x7415, 0x7427, 0x736f, - 0x73fd, 0x730e, 0x733c, 0x73bf, 0x730d, 0x0005, 0x00d6, 0x2069, - 0x0200, 0x6804, 0x9005, 0x1180, 0x6808, 0x9005, 0x1518, 0x709b, - 0x0029, 0x2069, 0x198f, 0x2d04, 0x7002, 0x080c, 0x7774, 0x6028, - 0x9085, 0x0600, 0x602a, 0x00b0, 0x709b, 0x0029, 0x2069, 0x198f, - 0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, 0x602a, 0x00e6, 0x0036, - 0x0046, 0x0056, 0x2071, 0x1a65, 0x080c, 0x1ad9, 0x005e, 0x004e, - 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, - 0x9005, 0x1178, 0x6808, 0x9005, 0x1160, 0x709b, 0x0029, 0x2069, - 0x198f, 0x2d04, 0x7002, 0x080c, 0x7818, 0x6028, 0x9085, 0x0600, - 0x602a, 0x00de, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2d39, - 0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x7494, 0xd1d4, 0x1160, - 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x709b, 0x0020, 0x080c, 0x7494, - 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x2001, - 0x0088, 0x080c, 0x2d39, 0x6124, 0xd1cc, 0x11e8, 0xd1dc, 0x11c0, - 0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, 0x080c, 0x1b06, 0x60e3, - 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x7663, 0x2001, 0x0080, - 0x080c, 0x2d39, 0x709b, 0x0029, 0x0058, 0x709b, 0x001e, 0x0040, - 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, 0x709b, 0x001f, - 0x0005, 0x080c, 0x1b06, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, - 0x080c, 0x7663, 0x2001, 0x0080, 0x080c, 0x2d39, 0x6124, 0xd1d4, - 0x1198, 0xd1dc, 0x1170, 0xd1e4, 0x1148, 0x9184, 0x1e00, 0x1118, - 0x709b, 0x0029, 0x0058, 0x709b, 0x0028, 0x0040, 0x709b, 0x001e, - 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x6124, - 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, 0x1e00, - 0x1158, 0x709b, 0x0029, 0x0040, 0x709b, 0x001e, 0x0028, 0x709b, - 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x2001, 0x00a0, 0x080c, - 0x2d39, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1b06, - 0x709b, 0x001e, 0x0010, 0x709b, 0x001d, 0x0005, 0x080c, 0x7517, - 0x6124, 0xd1dc, 0x1188, 0x080c, 0x7494, 0x0016, 0x080c, 0x1b06, - 0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x709b, 0x001e, 0x0020, - 0x709b, 0x001f, 0x080c, 0x7494, 0x0005, 0x0006, 0x2001, 0x00a0, - 0x080c, 0x2d39, 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, - 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, 0x001e, 0x0028, 0x709b, - 0x001d, 0x0010, 0x709b, 0x0021, 0x0005, 0x080c, 0x7517, 0x6124, - 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, 0x001e, - 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x0006, - 0x2001, 0x0090, 0x080c, 0x2d39, 0x000e, 0x6124, 0xd1d4, 0x1178, - 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x709b, 0x001e, - 0x0040, 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, 0x709b, - 0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, - 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, 0x080c, - 0x7637, 0x11d8, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x01b0, 0xc1b4, - 0x2102, 0x6027, 0x0200, 0x080c, 0x2c61, 0x6024, 0xd0cc, 0x0148, - 0x2001, 0x00a0, 0x080c, 0x2d39, 0x080c, 0x7932, 0x080c, 0x612e, - 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x7651, 0x0150, - 0x080c, 0x7648, 0x1138, 0x2001, 0x0001, 0x080c, 0x281c, 0x080c, - 0x760f, 0x00a0, 0x080c, 0x7514, 0x0178, 0x2001, 0x0001, 0x080c, - 0x281c, 0x7098, 0x9086, 0x001e, 0x0120, 0x7098, 0x9086, 0x0022, - 0x1118, 0x709b, 0x0025, 0x0010, 0x709b, 0x0021, 0x012e, 0x00ee, - 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x74a5, 0x080c, - 0x8917, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x74a5, - 0x080c, 0x890e, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, - 0x080c, 0xa6e9, 0x2071, 0x1800, 0x080c, 0x7442, 0x001e, 0x00fe, - 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x0126, 0x2071, 0x1800, 0x080c, 0xa6e9, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x2011, - 0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, 0xaac9, 0x080c, - 0xa9d3, 0x080c, 0x88c3, 0x0036, 0x901e, 0x080c, 0xaa49, 0x003e, - 0x60e3, 0x0000, 0x080c, 0xf07f, 0x080c, 0xf09a, 0x2009, 0x0004, - 0x080c, 0x2c67, 0x080c, 0x2b82, 0x2001, 0x1800, 0x2003, 0x0004, - 0x6027, 0x0008, 0x2011, 0x74a5, 0x080c, 0x8917, 0x080c, 0x7651, - 0x0118, 0x9006, 0x080c, 0x2d39, 0x080c, 0x0ba0, 0x2001, 0x0001, - 0x080c, 0x281c, 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, 0x74b2, 0x2071, - 0x19fb, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, 0x9085, - 0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, - 0x9084, 0xfffe, 0x9086, 0x00c0, 0x01b8, 0x2001, 0x00c0, 0x080c, - 0x2d39, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x7524, 0x2091, 0x6000, - 0x1f04, 0x7524, 0x015e, 0x00d6, 0x2069, 0x1800, 0x689c, 0x8001, - 0x0220, 0x0118, 0x689e, 0x00de, 0x0005, 0x689f, 0x0014, 0x68e8, - 0xd0dc, 0x0dc8, 0x6800, 0x9086, 0x0001, 0x1da8, 0x080c, 0x8923, - 0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, - 0x2071, 0x1800, 0x080c, 0x7941, 0x2001, 0x196d, 0x2003, 0x0000, - 0x9006, 0x709a, 0x60e2, 0x6886, 0x080c, 0x28e7, 0x9006, 0x080c, - 0x2d39, 0x080c, 0x5fed, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, - 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x197d, 0x200c, 0x9186, - 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, 0x0002, 0x0158, - 0x9186, 0x0003, 0x0158, 0x0804, 0x75ff, 0x709b, 0x0022, 0x0040, - 0x709b, 0x0021, 0x0028, 0x709b, 0x0023, 0x0010, 0x709b, 0x0024, - 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28e7, - 0x0026, 0x080c, 0xb244, 0x002e, 0x7000, 0x908e, 0x0004, 0x0118, - 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, - 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, 0x015e, - 0x080c, 0xd7e3, 0x0118, 0x9006, 0x080c, 0x2d63, 0x0804, 0x760b, - 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2c61, 0x6904, - 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2d39, 0x1f04, 0x75a3, - 0x080c, 0x768b, 0x012e, 0x015e, 0x080c, 0x7648, 0x01d8, 0x6044, - 0x9005, 0x0198, 0x2011, 0x0114, 0x2204, 0x9085, 0x0100, 0x2012, - 0x6050, 0x0006, 0x9085, 0x0020, 0x6052, 0x080c, 0x768b, 0x9006, - 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, - 0x080c, 0x768b, 0x080c, 0xd7e3, 0x0118, 0x9006, 0x080c, 0x2d63, - 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, 0x0130, 0x2009, 0x00c8, - 0x2011, 0x74b2, 0x080c, 0x88d5, 0x002e, 0x001e, 0x080c, 0x871c, - 0x7034, 0xc085, 0x7036, 0x2001, 0x197d, 0x2003, 0x0004, 0x080c, - 0x72f5, 0x080c, 0x7648, 0x0138, 0x6804, 0xd0d4, 0x1120, 0xd0dc, - 0x1100, 0x080c, 0x7937, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, - 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, - 0x080c, 0x8733, 0x080c, 0x8725, 0x080c, 0x7941, 0x2001, 0x196d, - 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, 0x6886, 0x080c, 0x28e7, - 0x9006, 0x080c, 0x2d39, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027, - 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, - 0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, - 0x080c, 0x57d9, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, - 0x0006, 0x080c, 0x57d9, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, - 0x0005, 0x0006, 0x080c, 0x57d9, 0x9084, 0x0030, 0x9086, 0x0010, - 0x000e, 0x0005, 0x0006, 0x080c, 0x57d9, 0x9084, 0x0030, 0x9086, - 0x0020, 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x180c, 0x2004, - 0x908c, 0x0013, 0x0168, 0x0020, 0x080c, 0x2907, 0x900e, 0x0010, - 0x2009, 0x0002, 0x2019, 0x0028, 0x080c, 0x321b, 0x9006, 0x0019, - 0x001e, 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, - 0x080c, 0xd7dc, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, - 0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, - 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x0016, 0x6138, 0x6050, - 0x9084, 0xfbff, 0x9085, 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012, - 0x1d04, 0x76a0, 0x2091, 0x6000, 0x1f04, 0x76a0, 0x602f, 0x0100, - 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052, - 0x613a, 0x001e, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, - 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000, - 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28e7, 0x2001, 0x00a0, - 0x0006, 0x080c, 0xd7e3, 0x000e, 0x0130, 0x080c, 0x2d57, 0x9006, - 0x080c, 0x2d63, 0x0010, 0x080c, 0x2d39, 0x000e, 0x6052, 0x6050, - 0x0006, 0xc0e5, 0x6052, 0x00f6, 0x2079, 0x0100, 0x080c, 0x2bd6, - 0x00fe, 0x000e, 0x6052, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, - 0x1800, 0x6020, 0x9084, 0x0080, 0x0138, 0x2001, 0x180c, 0x200c, - 0xc1c5, 0x2102, 0x0804, 0x7766, 0x2001, 0x180c, 0x200c, 0xc1c4, - 0x2102, 0x6028, 0x9084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x2001, - 0x0090, 0x080c, 0x2d39, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1518, - 0x1d04, 0x770d, 0x2091, 0x6000, 0x1f04, 0x770d, 0x2011, 0x0003, - 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, 0xaac9, 0x080c, 0xa9d3, - 0x901e, 0x080c, 0xaa49, 0x2001, 0x00a0, 0x080c, 0x2d39, 0x080c, - 0x7932, 0x080c, 0x612e, 0x080c, 0xd7e3, 0x0110, 0x080c, 0x0d33, - 0x9085, 0x0001, 0x04c8, 0x080c, 0x1b06, 0x60e3, 0x0000, 0x2001, - 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118, 0x2001, 0x196d, - 0x2004, 0x080c, 0x28e7, 0x60e2, 0x2001, 0x0080, 0x080c, 0x2d39, - 0x20a9, 0x0366, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c61, - 0x6024, 0x910c, 0x0140, 0x1d04, 0x774a, 0x2091, 0x6000, 0x1f04, - 0x774a, 0x0804, 0x7716, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b4, - 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xd7e3, - 0x0110, 0x080c, 0x0d33, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x7000, - 0x9086, 0x0003, 0x1168, 0x2001, 0x020b, 0x2004, 0x9084, 0x5540, - 0x9086, 0x5540, 0x1128, 0x2069, 0x1a7c, 0x2d04, 0x8000, 0x206a, - 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, - 0x1904, 0x77d9, 0x2001, 0x0088, 0x080c, 0x2d39, 0x9006, 0x60e2, - 0x6886, 0x080c, 0x28e7, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, - 0x6808, 0x9005, 0x01c0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x6027, - 0x0400, 0x2069, 0x198f, 0x7000, 0x206a, 0x709b, 0x0026, 0x7003, - 0x0001, 0x20a9, 0x0002, 0x1d04, 0x77bb, 0x2091, 0x6000, 0x1f04, - 0x77bb, 0x0804, 0x7810, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, - 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c61, 0x6024, 0x910c, 0x0508, - 0x9084, 0x1a00, 0x11f0, 0x1d04, 0x77c7, 0x2091, 0x6000, 0x1f04, - 0x77c7, 0x2011, 0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, - 0xaac9, 0x080c, 0xa9d3, 0x901e, 0x080c, 0xaa49, 0x2001, 0x00a0, - 0x080c, 0x2d39, 0x080c, 0x7932, 0x080c, 0x612e, 0x9085, 0x0001, - 0x00f8, 0x080c, 0x1b06, 0x2001, 0x0080, 0x080c, 0x2d39, 0x2069, - 0x0140, 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, - 0x0008, 0x6886, 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, - 0x1118, 0x2001, 0x196d, 0x2004, 0x080c, 0x28e7, 0x60e2, 0x9006, - 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, - 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2071, 0x1800, 0x6020, 0x9084, 0x00c0, 0x01c8, 0x2011, - 0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, 0xaac9, 0x080c, - 0xa9d3, 0x901e, 0x080c, 0xaa49, 0x2069, 0x0140, 0x2001, 0x00a0, - 0x080c, 0x2d39, 0x080c, 0x7932, 0x080c, 0x612e, 0x0804, 0x78b2, - 0x2001, 0x180c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, 0x2102, 0x080c, - 0x749a, 0x2069, 0x0140, 0x2001, 0x0080, 0x080c, 0x2d39, 0x60e3, - 0x0000, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005, - 0x0180, 0x6028, 0x9084, 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, - 0x198f, 0x7000, 0x206a, 0x709b, 0x0027, 0x7003, 0x0001, 0x0804, - 0x78b2, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c61, 0x6024, - 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x7869, 0x0006, - 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x8776, 0x00ee, 0x00de, - 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x19fb, 0x7078, 0x00ee, - 0x9005, 0x19f8, 0x0438, 0x0026, 0x2011, 0x74b2, 0x080c, 0x883d, - 0x2011, 0x74a5, 0x080c, 0x8917, 0x002e, 0x2069, 0x0140, 0x60e3, - 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118, 0x2001, - 0x196d, 0x2004, 0x080c, 0x28e7, 0x60e2, 0x2001, 0x180c, 0x200c, - 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, - 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, - 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x080c, 0xd7dc, 0x1904, - 0x7920, 0x7130, 0xd184, 0x1170, 0x080c, 0x33aa, 0x0138, 0xc18d, - 0x7132, 0x2011, 0x1848, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, - 0x0904, 0x7920, 0x2011, 0x1848, 0x220c, 0xd1a4, 0x0538, 0x0016, - 0x2019, 0x000e, 0x080c, 0xeba1, 0x0156, 0x00b6, 0x20a9, 0x007f, - 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c, - 0x6724, 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, 0x080c, - 0xec31, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8a50, 0x001e, - 0x8108, 0x1f04, 0x78e9, 0x00be, 0x015e, 0x001e, 0xd1ac, 0x1148, - 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x321b, 0x001e, - 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x6724, - 0x1110, 0x080c, 0x6148, 0x8108, 0x1f04, 0x7916, 0x00be, 0x015e, - 0x080c, 0x1b06, 0x080c, 0xb244, 0x60e3, 0x0000, 0x080c, 0x612e, - 0x080c, 0x7563, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, - 0x015e, 0x0005, 0x2001, 0x197d, 0x2003, 0x0001, 0x0005, 0x2001, - 0x197d, 0x2003, 0x0000, 0x0005, 0x2001, 0x197c, 0x2003, 0xaaaa, - 0x0005, 0x2001, 0x197c, 0x2003, 0x0000, 0x0005, 0x2071, 0x18fa, - 0x7003, 0x0000, 0x7007, 0x0000, 0x080c, 0x1027, 0x090c, 0x0dc5, - 0xa8ab, 0xdcb0, 0x2900, 0x704e, 0x080c, 0x1027, 0x090c, 0x0dc5, - 0xa8ab, 0xdcb0, 0x2900, 0x7052, 0xa867, 0x0000, 0xa86b, 0x0001, - 0xa89f, 0x0000, 0x0005, 0x00e6, 0x2071, 0x0040, 0x6848, 0x9005, - 0x1118, 0x9085, 0x0001, 0x04b0, 0x6840, 0x9005, 0x0150, 0x04a1, - 0x6a50, 0x9200, 0x7002, 0x6854, 0x9101, 0x7006, 0x9006, 0x7012, - 0x7016, 0x6850, 0x7002, 0x6854, 0x7006, 0x6858, 0x700a, 0x685c, - 0x700e, 0x6840, 0x9005, 0x1110, 0x7012, 0x7016, 0x6848, 0x701a, - 0x701c, 0x9085, 0x0040, 0x701e, 0x2001, 0x0019, 0x7036, 0x702b, - 0x0001, 0x2001, 0x0004, 0x200c, 0x918c, 0xfff7, 0x918d, 0x8000, - 0x2102, 0x00d6, 0x2069, 0x18fa, 0x6807, 0x0001, 0x00de, 0x080c, - 0x7f74, 0x9006, 0x00ee, 0x0005, 0x900e, 0x0156, 0x20a9, 0x0006, - 0x8003, 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, 0x1110, 0x818d, - 0x0010, 0x81f5, 0x3e08, 0x1f04, 0x79a8, 0x015e, 0x0005, 0x2079, - 0x0040, 0x2071, 0x18fa, 0x7004, 0x0002, 0x79c7, 0x79c8, 0x7a00, - 0x7a5b, 0x7bbb, 0x79c5, 0x79c5, 0x7be5, 0x080c, 0x0dc5, 0x0005, - 0x2079, 0x0040, 0x782c, 0x908c, 0x0780, 0x190c, 0x8056, 0xd0a4, - 0x01f8, 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, - 0x00ff, 0x908a, 0x0040, 0x0610, 0x00c0, 0x2001, 0x1800, 0x200c, - 0x9186, 0x0003, 0x1168, 0x7004, 0x0002, 0x79f0, 0x79ca, 0x79f0, - 0x79ee, 0x79f0, 0x79f0, 0x79f0, 0x79f0, 0x79f0, 0x080c, 0x7a5b, - 0x782c, 0xd09c, 0x090c, 0x7f74, 0x0005, 0x9082, 0x005a, 0x1218, - 0x2100, 0x003b, 0x0c10, 0x080c, 0x7a91, 0x0c90, 0x00e3, 0x08e8, - 0x0005, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7ab3, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a9d, 0x7a91, 0x7cdb, - 0x7a91, 0x7a91, 0x7a91, 0x7ab3, 0x7a91, 0x7a9d, 0x7d1c, 0x7d5d, - 0x7da4, 0x7db8, 0x7a91, 0x7a91, 0x7ab3, 0x7a9d, 0x7ac7, 0x7a91, - 0x7b8f, 0x7e63, 0x7e7e, 0x7a91, 0x7ab3, 0x7a91, 0x7ac7, 0x7a91, - 0x7a91, 0x7b85, 0x7e7e, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7adb, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7ffa, 0x7a91, - 0x7fa4, 0x7a91, 0x7fa4, 0x7a91, 0x7af0, 0x7a91, 0x7a91, 0x7a91, - 0x7a91, 0x7a91, 0x7a91, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, - 0x1198, 0x782c, 0x080c, 0x7f9d, 0xd0a4, 0x0170, 0x7824, 0x2048, - 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x001a, - 0x1210, 0x002b, 0x0c50, 0x00e9, 0x080c, 0x7f74, 0x0005, 0x7a91, - 0x7a9d, 0x7cc7, 0x7a91, 0x7a9d, 0x7a91, 0x7a9d, 0x7a9d, 0x7a91, - 0x7a9d, 0x7cc7, 0x7a9d, 0x7a9d, 0x7a9d, 0x7a9d, 0x7a9d, 0x7a91, - 0x7a9d, 0x7cc7, 0x7a91, 0x7a91, 0x7a9d, 0x7a91, 0x7a91, 0x7a91, - 0x7a9d, 0x00e6, 0x2071, 0x18fa, 0x2009, 0x0400, 0x0071, 0x00ee, - 0x0005, 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, - 0x0005, 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, 0xa868, - 0x9084, 0x00ff, 0x9105, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6e9f, 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0d08, - 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7c64, 0x7007, 0x0003, - 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7c64, 0x0005, 0xa864, - 0x8007, 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, - 0x0804, 0x7c7f, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, - 0x704b, 0x7c7f, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0904, - 0x7a99, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7c9b, 0x7007, - 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7c9b, 0x0005, - 0xa864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7a99, - 0x7007, 0x0001, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1904, 0x7b5c, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x0904, 0x7b47, 0xa99c, 0x9186, - 0x00ff, 0x05e8, 0xa994, 0x9186, 0x006f, 0x0188, 0x9186, 0x0074, - 0x15b0, 0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e, 0x0578, - 0x0016, 0xa998, 0x080c, 0x6b11, 0x001e, 0x1548, 0x0400, 0x080c, - 0x7637, 0x0140, 0xa897, 0x4005, 0xa89b, 0x0016, 0x2001, 0x0030, - 0x900e, 0x0438, 0x0026, 0x2011, 0x8008, 0x080c, 0x6ac7, 0x002e, - 0x01b0, 0x0016, 0x0026, 0x0036, 0xa998, 0xaaa0, 0xab9c, 0x918d, - 0x8000, 0x080c, 0x6b11, 0x003e, 0x002e, 0x001e, 0x1140, 0xa897, - 0x4005, 0xa89b, 0x4009, 0x2001, 0x0030, 0x900e, 0x0050, 0xa868, - 0x9084, 0x00ff, 0xa86a, 0xa883, 0x0000, 0x080c, 0x63c5, 0x1108, - 0x0005, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0xa87a, 0xa982, - 0x080c, 0x6e9f, 0x012e, 0x0ca0, 0xa994, 0x9186, 0x0071, 0x0904, - 0x7b00, 0x9186, 0x0064, 0x0904, 0x7b00, 0x9186, 0x007c, 0x0904, - 0x7b00, 0x9186, 0x0028, 0x0904, 0x7b00, 0x9186, 0x0038, 0x0904, - 0x7b00, 0x9186, 0x0078, 0x0904, 0x7b00, 0x9186, 0x005f, 0x0904, - 0x7b00, 0x9186, 0x0056, 0x0904, 0x7b00, 0xa897, 0x4005, 0xa89b, - 0x0001, 0x2001, 0x0030, 0x900e, 0x0860, 0xa87c, 0x9084, 0x00c0, - 0x9086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x7e95, 0x2900, - 0x7016, 0x701a, 0x20a9, 0x0004, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x0030, 0x2098, 0x7050, 0x2040, 0xa060, 0x20e8, 0xa05c, 0x9080, - 0x0023, 0x20a0, 0x4003, 0xa888, 0x7012, 0x9082, 0x0401, 0x1a04, - 0x7aa1, 0xaab4, 0x928a, 0x0002, 0x1a04, 0x7aa1, 0x82ff, 0x1138, - 0xa8b8, 0xa9bc, 0x9105, 0x0118, 0x2001, 0x7c22, 0x0018, 0x9280, - 0x7c18, 0x2005, 0x7056, 0x7010, 0x9015, 0x0904, 0x7c03, 0x080c, - 0x1027, 0x1118, 0x7007, 0x0004, 0x0005, 0x2900, 0x7022, 0x7054, - 0x2060, 0xe000, 0xa866, 0x7050, 0x2040, 0xa95c, 0xe004, 0x9100, - 0xa076, 0xa860, 0xa072, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, - 0x7112, 0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, - 0xa17a, 0x810b, 0xa17e, 0x080c, 0x10f8, 0xa06c, 0x908e, 0x0100, - 0x0170, 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, - 0x2048, 0x080c, 0x1040, 0x7014, 0x2048, 0x0804, 0x7aa1, 0x7020, - 0x2048, 0x7018, 0xa802, 0xa807, 0x0000, 0x2908, 0x2048, 0xa906, - 0x711a, 0x0804, 0x7bbb, 0x7014, 0x2048, 0x7007, 0x0001, 0xa8b4, - 0x9005, 0x1128, 0xa8b8, 0xa9bc, 0x9105, 0x0108, 0x00b9, 0xa864, - 0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, 0x7e95, 0x0804, 0x7c64, - 0x7c1a, 0x7c1e, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, - 0x0005, 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x0076, 0x0066, - 0xafb8, 0xaebc, 0xa804, 0x2050, 0xb0c0, 0xb0e2, 0xb0bc, 0xb0de, - 0xb0b8, 0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, 0xb7d6, 0xb0b0, 0xb0ca, - 0xb0ac, 0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, 0xb0b6, 0xb6c2, 0xb7be, - 0xb0a0, 0xb0b2, 0xb09c, 0xb0ae, 0xb098, 0xb0a2, 0xb094, 0xb09e, - 0xb6aa, 0xb7a6, 0xb090, 0xb09a, 0xb08c, 0xb096, 0xb088, 0xb08a, - 0xb084, 0xb086, 0xb692, 0xb78e, 0xb080, 0xb082, 0xb07c, 0xb07e, - 0xb078, 0xb072, 0xb074, 0xb06e, 0xb67a, 0xb776, 0xb004, 0x9055, - 0x1958, 0x006e, 0x007e, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, - 0x1178, 0x080c, 0x61c2, 0x1108, 0x0005, 0x080c, 0x710b, 0x0126, - 0x2091, 0x8000, 0x080c, 0xd3ce, 0x080c, 0x6e9f, 0x012e, 0x0ca0, - 0x080c, 0xd7dc, 0x1d70, 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009, - 0x1834, 0x210c, 0x81ff, 0x1188, 0xa888, 0x9005, 0x0188, 0xa883, - 0x0000, 0x080c, 0x6252, 0x1108, 0x0005, 0xa87a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6e9f, 0x012e, 0x0cb8, 0x2001, 0x0028, 0x0ca8, - 0x2001, 0x0000, 0x0c90, 0x0419, 0x11d8, 0xa888, 0x9005, 0x01e0, - 0xa883, 0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, 0x6327, 0x1138, - 0x0005, 0x9006, 0xa87a, 0x080c, 0x629f, 0x1108, 0x0005, 0x0126, - 0x2091, 0x8000, 0xa87a, 0xa982, 0x080c, 0x6e9f, 0x012e, 0x0cb0, - 0x2001, 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, 0x0c80, 0x00c6, - 0x2061, 0x1800, 0x60d0, 0x9005, 0x0100, 0x00ce, 0x0005, 0x7018, - 0xa802, 0x2908, 0x2048, 0xa906, 0x711a, 0x7010, 0x8001, 0x7012, - 0x0118, 0x7007, 0x0003, 0x0030, 0x7014, 0x2048, 0x7007, 0x0001, - 0x7048, 0x080f, 0x0005, 0x00b6, 0x7007, 0x0001, 0xa974, 0xa878, - 0x9084, 0x00ff, 0x9096, 0x0004, 0x0540, 0x20a9, 0x0001, 0x9096, - 0x0001, 0x0190, 0x900e, 0x20a9, 0x0800, 0x9096, 0x0002, 0x0160, - 0x9005, 0x11d8, 0xa974, 0x080c, 0x6724, 0x11b8, 0x0066, 0xae80, - 0x080c, 0x6834, 0x006e, 0x0088, 0x0046, 0x2011, 0x180c, 0x2224, - 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x6724, 0x1110, 0x080c, - 0x6934, 0x8108, 0x1f04, 0x7d04, 0x00ce, 0xa87c, 0xd084, 0x1120, - 0x080c, 0x1040, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, - 0x6e9f, 0x012e, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x080c, 0x6a9f, 0x0580, 0x2061, 0x1a74, 0x6100, 0xd184, - 0x0178, 0xa888, 0x9084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, - 0x6004, 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, - 0x2011, 0x0001, 0xa890, 0x9005, 0x1110, 0x2001, 0x001e, 0x8000, - 0x6016, 0xa888, 0x9084, 0x00ff, 0x0178, 0x6006, 0xa888, 0x8007, - 0x9084, 0x00ff, 0x0148, 0x600a, 0xa888, 0x8000, 0x1108, 0xc28d, - 0x6202, 0x012e, 0x0804, 0x7f5e, 0x012e, 0x0804, 0x7f58, 0x012e, - 0x0804, 0x7f52, 0x012e, 0x0804, 0x7f55, 0x0126, 0x2091, 0x8000, - 0x7007, 0x0001, 0x080c, 0x6a9f, 0x05e0, 0x2061, 0x1a74, 0x6000, - 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0xac78, 0x9484, - 0x0003, 0x0170, 0xa988, 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100, - 0x9210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0, - 0x9484, 0x000c, 0x0188, 0xa988, 0x810f, 0x918c, 0x00ff, 0x9082, - 0x0004, 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, 0x9082, 0x0004, - 0x1168, 0x2100, 0x931a, 0x0250, 0xa890, 0x9005, 0x0110, 0x8000, - 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x7f5e, 0x012e, 0x0804, - 0x7f5b, 0x012e, 0x0804, 0x7f58, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x2061, 0x1a74, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, - 0x0220, 0x630a, 0x012e, 0x0804, 0x7f6c, 0x012e, 0x0804, 0x7f5b, - 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0xa87c, - 0xd0ac, 0x0148, 0x00c6, 0x2061, 0x1a74, 0x6000, 0x9084, 0xfcff, - 0x6002, 0x00ce, 0x0440, 0xa888, 0x9005, 0x05d8, 0xa88c, 0x9065, - 0x0598, 0x2001, 0x1834, 0x2004, 0x9005, 0x0118, 0x080c, 0xb306, - 0x0068, 0x6017, 0xf400, 0x605b, 0x0000, 0xa97c, 0xd1a4, 0x0110, - 0xa980, 0x615a, 0x2009, 0x0041, 0x080c, 0xb352, 0xa988, 0x918c, - 0xff00, 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, - 0x080c, 0x8a50, 0x002e, 0xa87c, 0xd0c4, 0x0148, 0x2061, 0x1a74, - 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, - 0x012e, 0x00be, 0x0804, 0x7f5e, 0x00ce, 0x012e, 0x00be, 0x0804, - 0x7f58, 0xa984, 0x9186, 0x002e, 0x0d30, 0x9186, 0x002d, 0x0d18, - 0x9186, 0x0045, 0x0510, 0x9186, 0x002a, 0x1130, 0x2001, 0x180c, - 0x200c, 0xc194, 0x2102, 0x08b8, 0x9186, 0x0020, 0x0158, 0x9186, - 0x0029, 0x1d10, 0xa974, 0x080c, 0x6724, 0x1968, 0xb800, 0xc0e4, - 0xb802, 0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, 0x0024, 0x2001, - 0x1986, 0x2004, 0x601a, 0x0804, 0x7df3, 0xa88c, 0x9065, 0x0960, - 0x00e6, 0xa890, 0x9075, 0x2001, 0x1834, 0x2004, 0x9005, 0x0150, - 0x080c, 0xb306, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xb306, 0x00ee, - 0x0804, 0x7df3, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, - 0x003a, 0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, 0xa8a4, 0x602e, - 0xa8a8, 0x6016, 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, - 0x00ee, 0x0804, 0x7df3, 0x2061, 0x1a74, 0x6000, 0xd084, 0x0190, - 0xd08c, 0x1904, 0x7f6c, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, - 0x0220, 0x6206, 0x012e, 0x0804, 0x7f6c, 0x012e, 0xa883, 0x0016, - 0x0804, 0x7f65, 0xa883, 0x0007, 0x0804, 0x7f65, 0xa864, 0x8007, - 0x9084, 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, - 0x0005, 0x080c, 0x7a99, 0x0040, 0x7007, 0x0003, 0x7012, 0x2900, - 0x7016, 0x701a, 0x704b, 0x7e95, 0x0005, 0x00b6, 0x00e6, 0x0126, - 0x2091, 0x8000, 0x903e, 0x2061, 0x1800, 0x61d0, 0x81ff, 0x1904, - 0x7f17, 0x6130, 0xd194, 0x1904, 0x7f41, 0xa878, 0x2070, 0x9e82, - 0x1cd0, 0x0a04, 0x7f0b, 0x6068, 0x9e02, 0x1a04, 0x7f0b, 0x7120, - 0x9186, 0x0006, 0x1904, 0x7efd, 0x7010, 0x905d, 0x0904, 0x7f17, - 0xb800, 0xd0e4, 0x1904, 0x7f3b, 0x2061, 0x1a74, 0x6100, 0x9184, - 0x0301, 0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, 0x1904, 0x7f44, - 0xa883, 0x0000, 0xa803, 0x0000, 0x2908, 0x7014, 0x9005, 0x1198, - 0x7116, 0xa87c, 0xd0f4, 0x1904, 0x7f47, 0x080c, 0x57d5, 0xd09c, - 0x1118, 0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, 0x8970, 0x012e, - 0x00ee, 0x00be, 0x0005, 0x2048, 0xa800, 0x9005, 0x1de0, 0xa902, - 0x2148, 0xa87c, 0xd0f4, 0x1904, 0x7f47, 0x012e, 0x00ee, 0x00be, - 0x0005, 0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, 0x0804, 0x7f65, - 0xd184, 0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, 0x080c, 0x6724, - 0x15d0, 0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, - 0xa883, 0x0002, 0x0490, 0xa883, 0x0008, 0x0478, 0xa883, 0x000e, - 0x0460, 0xa883, 0x0017, 0x0448, 0xa883, 0x0035, 0x0430, 0x080c, - 0x57d9, 0xd0fc, 0x01e8, 0xa878, 0x2070, 0x9e82, 0x1cd0, 0x02c0, - 0x6068, 0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, - 0x905d, 0x0170, 0xb800, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, - 0x9086, 0x0007, 0x1904, 0x7ea1, 0x7003, 0x0002, 0x0804, 0x7ea1, - 0xa883, 0x0028, 0x0010, 0xa883, 0x0029, 0x012e, 0x00ee, 0x00be, - 0x0420, 0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, 0x0cb0, 0x2e60, - 0x2019, 0x0002, 0x601b, 0x0014, 0x080c, 0xe754, 0x012e, 0x00ee, - 0x00be, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, - 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, - 0xa884, 0x9084, 0xff00, 0x9105, 0xa886, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6e9f, 0x012e, 0x0005, 0x080c, 0x1040, 0x0005, 0x00d6, - 0x080c, 0x8967, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, 0x908c, 0x0780, - 0x190c, 0x8056, 0xd09c, 0x11a8, 0x2071, 0x1800, 0x70c0, 0x90ea, - 0x0020, 0x0278, 0x8001, 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e, - 0x9006, 0xa802, 0xa806, 0x2071, 0x0040, 0x2900, 0x7022, 0x702c, - 0x0c28, 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, - 0x190c, 0x8056, 0x000e, 0x0005, 0xa898, 0x9084, 0x0003, 0x05a8, - 0x080c, 0xb27d, 0x05d8, 0x2900, 0x6016, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0035, 0x1138, 0x6008, 0xc0fd, 0x600a, 0x2001, 0x196b, - 0x2004, 0x0098, 0xa8a0, 0x9084, 0x00ff, 0xa99c, 0x918c, 0xff00, - 0x9105, 0xa99c, 0x918c, 0x00ff, 0x080c, 0x2873, 0x1540, 0x00b6, - 0x080c, 0x6724, 0x2b00, 0x00be, 0x1510, 0x6012, 0x6023, 0x0001, - 0x2009, 0x0040, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x0110, - 0x2009, 0x0041, 0x080c, 0xb352, 0x0005, 0xa87b, 0x0101, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, 0x0005, 0xa87b, 0x002c, - 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, 0x0005, 0xa87b, - 0x0028, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, 0x080c, - 0xb2d3, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x00b6, - 0x7007, 0x0001, 0xaa74, 0x9282, 0x0004, 0x1a04, 0x8047, 0xa97c, - 0x9188, 0x1000, 0x2104, 0x905d, 0xb804, 0xd284, 0x0140, 0x05e8, - 0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04b0, 0x2b10, - 0x080c, 0xb27d, 0x1118, 0x080c, 0xb325, 0x05a8, 0x6212, 0xa874, - 0x0002, 0x8025, 0x802a, 0x802d, 0x8033, 0x2019, 0x0002, 0x080c, - 0xeba1, 0x0060, 0x080c, 0xeb38, 0x0048, 0x2019, 0x0002, 0xa980, - 0x080c, 0xeb53, 0x0018, 0xa980, 0x080c, 0xeb38, 0x080c, 0xb2d3, - 0xa887, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, - 0x00be, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0xa887, - 0x0006, 0x0c80, 0xa887, 0x0002, 0x0c68, 0xa887, 0x0005, 0x0c50, - 0xa887, 0x0004, 0x0c38, 0xa887, 0x0007, 0x0c20, 0x2091, 0x8000, - 0x0e04, 0x8058, 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, - 0x0dce, 0x2001, 0x1834, 0x2004, 0x9005, 0x0005, 0x0005, 0x00f6, - 0x2079, 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, - 0x2009, 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x15a0, 0x00fe, - 0x0005, 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe, - 0x0005, 0x781c, 0xd08c, 0x0904, 0x80d8, 0x68c0, 0x90aa, 0x0005, - 0x0a04, 0x871c, 0x7d44, 0x7c40, 0x9584, 0x00f6, 0x1510, 0x9484, - 0x7000, 0x0140, 0x908a, 0x2000, 0x1260, 0x9584, 0x0700, 0x8007, - 0x0804, 0x80df, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x0da8, - 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, 0x9086, - 0x8100, 0x11c0, 0x080c, 0xf057, 0x080c, 0x8601, 0x7817, 0x0140, - 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x865f, 0x19c0, 0xd5a4, - 0x0148, 0x0046, 0x0056, 0x080c, 0x813a, 0x080c, 0x236e, 0x005e, - 0x004e, 0x0020, 0x080c, 0xf057, 0x7817, 0x0140, 0x080c, 0x7637, - 0x0168, 0x2001, 0x0111, 0x2004, 0xd08c, 0x0140, 0x6893, 0x0000, - 0x2001, 0x0110, 0x2003, 0x0008, 0x2003, 0x0000, 0x080c, 0x811b, - 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1, 0x0005, 0x0002, - 0x80f1, 0x8409, 0x80e8, 0x80e8, 0x80e8, 0x80e8, 0x80e8, 0x80e8, - 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1, - 0x0005, 0x7000, 0x908c, 0xff00, 0x9194, 0xf000, 0x810f, 0x9484, - 0x0fff, 0x6892, 0x9286, 0x2000, 0x1150, 0x6800, 0x9086, 0x0001, - 0x1118, 0x080c, 0x583f, 0x0070, 0x080c, 0x815a, 0x0058, 0x9286, - 0x3000, 0x1118, 0x080c, 0x8341, 0x0028, 0x9286, 0x8000, 0x1110, - 0x080c, 0x8528, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, - 0x090c, 0x9ab1, 0x0005, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0178, - 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, - 0x2011, 0x8048, 0x2518, 0x080c, 0x4c44, 0x003e, 0x002e, 0x0005, - 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe, - 0x7c30, 0x0050, 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, - 0x7d44, 0x7c40, 0x2019, 0xffff, 0x2001, 0x1810, 0x2004, 0xd08c, - 0x0160, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1130, 0x0026, - 0x2011, 0x8048, 0x080c, 0x4c44, 0x002e, 0x00fe, 0x005e, 0x004e, - 0x003e, 0x0005, 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, - 0x9096, 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, 0x8312, 0x9186, - 0x0023, 0x15c0, 0x080c, 0x85c6, 0x0904, 0x8312, 0x6120, 0x9186, - 0x0001, 0x0150, 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, - 0x9186, 0x000a, 0x1904, 0x8312, 0x7124, 0x610a, 0x7030, 0x908e, - 0x0200, 0x1130, 0x2009, 0x0015, 0x080c, 0xb352, 0x0804, 0x8312, - 0x908e, 0x0214, 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, - 0x080c, 0xb352, 0x0804, 0x8312, 0x908e, 0x0100, 0x1904, 0x8312, - 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0016, 0x080c, 0xb352, - 0x0804, 0x8312, 0x9186, 0x0022, 0x1904, 0x8312, 0x7030, 0x908e, - 0x0300, 0x1580, 0x68dc, 0xd0a4, 0x0528, 0xc0b5, 0x68de, 0x7100, - 0x918c, 0x00ff, 0x697e, 0x7004, 0x6882, 0x00f6, 0x2079, 0x0100, - 0x79e6, 0x78ea, 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, - 0x28bc, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x2873, - 0x695e, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1800, - 0x70b6, 0x00ee, 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0017, - 0x0804, 0x82c2, 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, - 0x8312, 0x080c, 0x7637, 0x0120, 0x2009, 0x001d, 0x0804, 0x82c2, - 0x68dc, 0xc0a5, 0x68de, 0x2009, 0x0030, 0x0804, 0x82c2, 0x908e, - 0x0500, 0x1140, 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0018, - 0x0804, 0x82c2, 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, - 0x82c2, 0x908e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x82c2, - 0x908e, 0x5200, 0x1140, 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, - 0x001b, 0x0804, 0x82c2, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, - 0x1904, 0x8312, 0x2009, 0x001c, 0x0804, 0x82c2, 0x908e, 0x1300, - 0x1120, 0x2009, 0x0034, 0x0804, 0x82c2, 0x908e, 0x1200, 0x1140, - 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0024, 0x0804, 0x82c2, - 0x908c, 0xff00, 0x918e, 0x2400, 0x1170, 0x2009, 0x002d, 0x2001, - 0x1810, 0x2004, 0xd09c, 0x0904, 0x82c2, 0x080c, 0xdf1a, 0x1904, - 0x8312, 0x0804, 0x82c0, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, - 0x2009, 0x002a, 0x0804, 0x82c2, 0x908e, 0x0f00, 0x1120, 0x2009, - 0x0020, 0x0804, 0x82c2, 0x908e, 0x6104, 0x1530, 0x2029, 0x0205, - 0x2011, 0x026d, 0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, - 0x20a8, 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, - 0x4c44, 0x004e, 0x8108, 0x0f04, 0x8276, 0x9186, 0x0280, 0x1d88, - 0x2504, 0x8000, 0x202a, 0x2009, 0x0260, 0x0c58, 0x202b, 0x0000, - 0x2009, 0x0023, 0x0804, 0x82c2, 0x908e, 0x6000, 0x1120, 0x2009, - 0x003f, 0x0804, 0x82c2, 0x908e, 0x5400, 0x1138, 0x080c, 0x86cc, - 0x1904, 0x8312, 0x2009, 0x0046, 0x04a8, 0x908e, 0x5500, 0x1148, - 0x080c, 0x86f4, 0x1118, 0x2009, 0x0041, 0x0460, 0x2009, 0x0042, - 0x0448, 0x908e, 0x7800, 0x1118, 0x2009, 0x0045, 0x0418, 0x908e, - 0x1000, 0x1118, 0x2009, 0x004e, 0x00e8, 0x908e, 0x6300, 0x1118, - 0x2009, 0x004a, 0x00b8, 0x908c, 0xff00, 0x918e, 0x5600, 0x1118, - 0x2009, 0x004f, 0x0078, 0x908c, 0xff00, 0x918e, 0x5700, 0x1118, - 0x2009, 0x0050, 0x0038, 0x2009, 0x001d, 0x6838, 0xd0d4, 0x0110, - 0x2009, 0x004c, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, - 0x080c, 0x2873, 0x1904, 0x8315, 0x080c, 0x66b9, 0x1904, 0x8315, - 0xbe12, 0xbd16, 0x001e, 0x0016, 0x080c, 0x7637, 0x01c0, 0x68dc, - 0xd08c, 0x1148, 0x7000, 0x9084, 0x00ff, 0x1188, 0x7004, 0x9084, - 0xff00, 0x1168, 0x0040, 0x687c, 0x9606, 0x1148, 0x6880, 0x9506, - 0x9084, 0xff00, 0x1120, 0x9584, 0x00ff, 0xb8c2, 0x0080, 0xb8c0, - 0x9005, 0x1168, 0x9186, 0x0046, 0x1150, 0x687c, 0x9606, 0x1138, - 0x6880, 0x9506, 0x9084, 0xff00, 0x1110, 0x001e, 0x0098, 0x080c, - 0xb27d, 0x01a8, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, - 0x001e, 0x9186, 0x004c, 0x1110, 0x6023, 0x000a, 0x0016, 0x001e, - 0x080c, 0xb352, 0x00ce, 0x00be, 0x0005, 0x001e, 0x0cd8, 0x2001, - 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4c44, - 0x080c, 0xb325, 0x0d90, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, - 0x610a, 0x001e, 0x0016, 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, - 0x1128, 0x6007, 0x0009, 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, - 0x6017, 0x0000, 0x602f, 0x0009, 0x6003, 0x0001, 0x080c, 0x9547, - 0x08a0, 0x080c, 0x873b, 0x1158, 0x080c, 0x3374, 0x1140, 0x7010, - 0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005, - 0x00b6, 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, - 0x0033, 0x11e8, 0x080c, 0x85c6, 0x0904, 0x83a1, 0x7124, 0x610a, - 0x7030, 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15d0, 0x2009, - 0x0015, 0x080c, 0xb352, 0x04a8, 0x908e, 0x0100, 0x1590, 0x7034, - 0x9005, 0x1578, 0x2009, 0x0016, 0x080c, 0xb352, 0x0450, 0x9186, - 0x0032, 0x1538, 0x7030, 0x908e, 0x1400, 0x1518, 0x2009, 0x0038, - 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2873, - 0x11b8, 0x080c, 0x66b9, 0x11a0, 0xbe12, 0xbd16, 0x080c, 0xb27d, - 0x0178, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0004, 0x7120, - 0x610a, 0x001e, 0x080c, 0xb352, 0x080c, 0x9ab1, 0x0010, 0x00ce, - 0x001e, 0x004e, 0x00ce, 0x00be, 0x0005, 0x00b6, 0x0046, 0x00e6, - 0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, 0x11b8, 0x9592, 0xfffc, - 0x02a0, 0x9596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x8403, - 0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, 0x8403, 0x9596, - 0xfffc, 0x1118, 0x2009, 0x0080, 0x04f0, 0x2011, 0x0000, 0x2019, - 0x1837, 0x231c, 0xd3ac, 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, - 0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, 0x077f, 0x2071, 0x1081, - 0x2e1c, 0x93dd, 0x0000, 0x1140, 0x82ff, 0x11d0, 0x9496, 0x00ff, - 0x01b8, 0x2410, 0xc2fd, 0x00a0, 0xbf10, 0x2600, 0x9706, 0xb814, - 0x1120, 0x9546, 0x1110, 0x2408, 0x00b0, 0x9745, 0x1148, 0x94c6, - 0x007e, 0x0130, 0x94c6, 0x007f, 0x0118, 0x94c6, 0x0080, 0x1d20, - 0x8420, 0x8e70, 0x1f04, 0x83d8, 0x82ff, 0x1118, 0x9085, 0x0001, - 0x0018, 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, 0x00be, - 0x0005, 0x2001, 0x1837, 0x200c, 0x9184, 0x0080, 0x0110, 0xd18c, - 0x0138, 0x7000, 0x908c, 0xff00, 0x810f, 0x9184, 0x000f, 0x004a, - 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1, - 0x0005, 0x8431, 0x8431, 0x8431, 0x85d8, 0x8431, 0x843a, 0x8465, - 0x84f3, 0x8431, 0x8431, 0x8431, 0x8431, 0x8431, 0x8431, 0x8431, - 0x8431, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, - 0x9ab1, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7120, 0x2160, - 0x9c8c, 0x0007, 0x11c0, 0x9c8a, 0x1cd0, 0x02a8, 0x6868, 0x9c02, - 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, - 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, - 0x0046, 0x080c, 0xb352, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, - 0x9005, 0x090c, 0x9ab1, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x9484, - 0x0fff, 0x0904, 0x84c9, 0x7110, 0xd1bc, 0x1904, 0x84c9, 0x7108, - 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x15b0, - 0x81ff, 0x15a0, 0x9080, 0x33b6, 0x200d, 0x918c, 0xff00, 0x810f, - 0x2001, 0x0080, 0x9106, 0x0904, 0x84c9, 0x080c, 0x66b9, 0x1904, - 0x84c9, 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15d8, 0xba04, 0x9294, - 0xff00, 0x9286, 0x0600, 0x11a0, 0x080c, 0xb27d, 0x05e8, 0x2b08, - 0x7028, 0x6046, 0x702c, 0x604a, 0x6112, 0x6023, 0x0006, 0x7120, - 0x610a, 0x7130, 0x6156, 0x2009, 0x0044, 0x080c, 0xe192, 0x0408, - 0x080c, 0x6aa3, 0x1138, 0xb807, 0x0606, 0x0c30, 0x190c, 0x83a5, - 0x11c0, 0x0898, 0x080c, 0xb27d, 0x2b08, 0x0198, 0x6112, 0x6023, - 0x0004, 0x7120, 0x610a, 0x9286, 0x0400, 0x1118, 0x6007, 0x0005, - 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, - 0x9ab1, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, - 0x9ab1, 0x00ce, 0x00be, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0ec, - 0x0120, 0x2011, 0x8049, 0x080c, 0x4c44, 0x080c, 0xb325, 0x0d48, - 0x2b08, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156, - 0x6017, 0xf300, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x08b0, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7020, - 0x2060, 0x9c84, 0x0007, 0x11c0, 0x9c82, 0x1cd0, 0x02a8, 0x6868, - 0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, - 0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, - 0x2009, 0x0045, 0x080c, 0xb352, 0x7817, 0x0140, 0x2001, 0x19f1, - 0x2004, 0x9005, 0x090c, 0x9ab1, 0x00be, 0x0005, 0x6120, 0x9186, - 0x0002, 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, 0x0001, 0x0005, - 0x080c, 0x873b, 0x1180, 0x080c, 0x3374, 0x1168, 0x7010, 0x9084, - 0xff00, 0x8007, 0x9086, 0x0000, 0x1130, 0x9184, 0x000f, 0x908a, - 0x0006, 0x1208, 0x000b, 0x0005, 0x8542, 0x8543, 0x8542, 0x8542, - 0x85a8, 0x85b7, 0x0005, 0x00b6, 0x700c, 0x7108, 0x080c, 0x2873, - 0x1904, 0x85a6, 0x080c, 0x66b9, 0x1904, 0x85a6, 0xbe12, 0xbd16, - 0x7110, 0xd1bc, 0x0540, 0x702c, 0xd084, 0x1120, 0xb800, 0xd0bc, - 0x1904, 0x85a6, 0x080c, 0x6aa3, 0x0148, 0x9086, 0x0004, 0x0130, - 0x080c, 0x6aab, 0x0118, 0x9086, 0x0004, 0x1588, 0x00c6, 0x080c, - 0x85c6, 0x00ce, 0x05d8, 0x080c, 0xb27d, 0x2b08, 0x05b8, 0x6112, - 0x080c, 0xd554, 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088, - 0x080c, 0xb352, 0x0458, 0x080c, 0x6aa3, 0x0148, 0x9086, 0x0004, - 0x0130, 0x080c, 0x6aab, 0x0118, 0x9086, 0x0004, 0x1180, 0x080c, - 0xb27d, 0x2b08, 0x01d8, 0x6112, 0x080c, 0xd554, 0x6023, 0x0005, - 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xb352, 0x0078, 0x080c, - 0xb27d, 0x2b08, 0x0158, 0x6112, 0x080c, 0xd554, 0x6023, 0x0004, - 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0xb352, 0x00be, 0x0005, - 0x7110, 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, 0x851e, 0x1130, - 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0xb352, 0x0005, 0x7110, - 0xd1bc, 0x0158, 0x0059, 0x0148, 0x080c, 0x851e, 0x1130, 0x7124, - 0x610a, 0x2009, 0x008a, 0x080c, 0xb352, 0x0005, 0x7020, 0x2060, - 0x9c84, 0x0007, 0x1158, 0x9c82, 0x1cd0, 0x0240, 0x2001, 0x181a, - 0x2004, 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, - 0x00b6, 0x7110, 0xd1bc, 0x11d8, 0x7024, 0x2060, 0x9c84, 0x0007, - 0x11b0, 0x9c82, 0x1cd0, 0x0298, 0x6868, 0x9c02, 0x1280, 0x7008, - 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1140, 0x700c, - 0xb914, 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, 0xb352, 0x7817, - 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1, 0x00be, - 0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, - 0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, - 0x0005, 0x00c6, 0x0096, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, - 0xc000, 0x05d0, 0x080c, 0xb27d, 0x05b8, 0x0066, 0x00c6, 0x0046, - 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2873, 0x15a0, - 0x080c, 0x66b9, 0x1588, 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce, - 0x6012, 0x080c, 0xd554, 0x080c, 0x100e, 0x0510, 0x2900, 0x605a, - 0x9006, 0xa802, 0xa866, 0xac6a, 0xa85c, 0x90f8, 0x001b, 0x20a9, - 0x000e, 0xa860, 0x20e8, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, - 0x006e, 0x6616, 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, - 0x080c, 0x9547, 0x080c, 0x9ab1, 0x00fe, 0x009e, 0x00ce, 0x0005, - 0x080c, 0xb2d3, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6, - 0x7000, 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, 0x2000, - 0x1904, 0x86b6, 0x9186, 0x0022, 0x15f0, 0x2001, 0x0111, 0x2004, - 0x9005, 0x1904, 0x86b8, 0x7030, 0x908e, 0x0400, 0x0904, 0x86b8, - 0x908e, 0x6000, 0x05e8, 0x908e, 0x5400, 0x05d0, 0x908e, 0x0300, - 0x11d8, 0x2009, 0x1837, 0x210c, 0xd18c, 0x1590, 0xd1a4, 0x1580, - 0x080c, 0x6a61, 0x0588, 0x68b0, 0x9084, 0x00ff, 0x7100, 0x918c, - 0x00ff, 0x9106, 0x1518, 0x6880, 0x69b0, 0x918c, 0xff00, 0x9105, - 0x7104, 0x9106, 0x11d8, 0x00e0, 0x2009, 0x0103, 0x210c, 0xd1b4, - 0x11a8, 0x908e, 0x5200, 0x09e8, 0x908e, 0x0500, 0x09d0, 0x908e, - 0x5000, 0x09b8, 0x0058, 0x9186, 0x0023, 0x1140, 0x080c, 0x85c6, - 0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, 0x9006, 0x0010, - 0x9085, 0x0001, 0x00ce, 0x0005, 0x7030, 0x908e, 0x0300, 0x0118, - 0x908e, 0x5200, 0x1d98, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, - 0x9086, 0x0008, 0x0d68, 0x0c50, 0x0156, 0x0046, 0x0016, 0x0036, - 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x027a, 0x080c, 0xc365, 0x1178, - 0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1801, 0x2011, 0x027e, - 0x080c, 0xc365, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, 0x003e, - 0x001e, 0x004e, 0x015e, 0x0005, 0x0156, 0x0046, 0x0016, 0x0036, - 0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9, - 0x0004, 0x2019, 0x1805, 0x2011, 0x0272, 0x080c, 0xc365, 0x1178, - 0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1801, 0x2011, 0x0276, - 0x080c, 0xc365, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, 0x003e, - 0x001e, 0x004e, 0x015e, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7800, - 0xc0e5, 0xc0cc, 0x7802, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x1800, - 0x7834, 0xd084, 0x1130, 0x2079, 0x0200, 0x7800, 0x9085, 0x1200, - 0x7802, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7034, 0xc084, - 0x7036, 0x00ee, 0x0005, 0x0016, 0x2001, 0x1837, 0x200c, 0x9184, - 0x0080, 0x0118, 0xd18c, 0x0118, 0x9006, 0x001e, 0x0005, 0x9085, - 0x0001, 0x0cd8, 0x2071, 0x19fb, 0x7003, 0x0003, 0x700f, 0x0361, - 0x9006, 0x701a, 0x707a, 0x7012, 0x7017, 0x1cd0, 0x7007, 0x0000, - 0x7026, 0x702b, 0xa6ff, 0x7032, 0x703a, 0x703f, 0x0064, 0x7037, - 0xa767, 0x7047, 0xffff, 0x704a, 0x704f, 0x5667, 0x7052, 0x7063, - 0x88de, 0x080c, 0x1027, 0x090c, 0x0dc5, 0x2900, 0x7042, 0xa867, - 0x0003, 0xa86f, 0x0100, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x19fb, - 0x1d04, 0x882c, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1540, - 0x2001, 0x013c, 0x2004, 0x9005, 0x190c, 0x894c, 0x2001, 0x1869, - 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, 0x0000, - 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0dc5, 0x700f, 0x0361, - 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x080c, 0x8923, 0x7048, - 0x900d, 0x0148, 0x8109, 0x714a, 0x1130, 0x704c, 0x080f, 0x0018, - 0x0126, 0x2091, 0x8000, 0x7024, 0x900d, 0x0188, 0x7020, 0x8001, - 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0x9186, 0x03e8, - 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030, - 0x900d, 0x05a8, 0x702c, 0x8001, 0x702e, 0x1588, 0x0016, 0x2009, - 0x0306, 0x210c, 0x9184, 0x0030, 0x01e8, 0x9184, 0x0048, 0x9086, - 0x0008, 0x11c0, 0x7038, 0x9005, 0x01a8, 0x8001, 0x703a, 0x1190, - 0x080c, 0x7637, 0x0178, 0x00e6, 0x2071, 0x19e8, 0x080c, 0xa7f5, - 0x00ee, 0x1140, 0x2009, 0x1a86, 0x2104, 0x8000, 0x0208, 0x200a, - 0x001e, 0x0068, 0x001e, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, - 0x9184, 0x007f, 0x090c, 0xa8ab, 0x0010, 0x7034, 0x080f, 0x7044, - 0x9005, 0x0118, 0x0310, 0x8001, 0x7046, 0x7054, 0x900d, 0x0168, - 0x7050, 0x8001, 0x7052, 0x1148, 0x7053, 0x0009, 0x8109, 0x7156, - 0x1120, 0x7158, 0x7156, 0x7060, 0x080f, 0x7018, 0x900d, 0x01d8, - 0x0016, 0x7078, 0x900d, 0x0158, 0x7074, 0x8001, 0x7076, 0x1138, - 0x7077, 0x0009, 0x8109, 0x717a, 0x1110, 0x707c, 0x080f, 0x001e, - 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, - 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x8854, 0x8855, - 0x8871, 0x00e6, 0x2071, 0x19fb, 0x7018, 0x9005, 0x1120, 0x711a, - 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, - 0x19fb, 0x701c, 0x9206, 0x1120, 0x701a, 0x701e, 0x707a, 0x707e, - 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x19fb, 0xb888, 0x9102, - 0x0208, 0xb98a, 0x00ee, 0x0005, 0x0005, 0x00b6, 0x7110, 0x080c, - 0x6724, 0x1168, 0xb888, 0x8001, 0x0250, 0xb88a, 0x1140, 0x0126, - 0x2091, 0x8000, 0x0016, 0x080c, 0x9ab1, 0x001e, 0x012e, 0x8108, - 0x9182, 0x0800, 0x0218, 0x900e, 0x7007, 0x0002, 0x7112, 0x00be, - 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, 0x6040, 0x9005, - 0x0128, 0x8001, 0x6042, 0x1110, 0x080c, 0xd3e5, 0x6018, 0x9005, - 0x0558, 0x8001, 0x601a, 0x1540, 0x6120, 0x9186, 0x0003, 0x0148, - 0x9186, 0x0006, 0x0130, 0x9186, 0x0009, 0x11e0, 0x611c, 0xd1c4, - 0x1100, 0x080c, 0xd0d8, 0x01b0, 0x6014, 0x2048, 0xa884, 0x908a, - 0x199a, 0x0280, 0x9082, 0x1999, 0xa886, 0x908a, 0x199a, 0x0210, - 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, - 0xd0e4, 0x0110, 0x080c, 0xcdbc, 0x012e, 0x9c88, 0x0018, 0x7116, - 0x2001, 0x181a, 0x2004, 0x9102, 0x0220, 0x7017, 0x1cd0, 0x7007, - 0x0000, 0x0005, 0x00e6, 0x2071, 0x19fb, 0x7027, 0x07d0, 0x7023, - 0x0009, 0x00ee, 0x0005, 0x2001, 0x1a04, 0x2003, 0x0000, 0x0005, - 0x00e6, 0x2071, 0x19fb, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, - 0x2011, 0x1a07, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x19fb, - 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, 0x0026, - 0x705c, 0x8000, 0x705e, 0x2001, 0x1a0b, 0x2044, 0xa06c, 0x9086, - 0x0000, 0x0150, 0x7070, 0xa09a, 0x706c, 0xa096, 0x7068, 0xa092, - 0x7064, 0xa08e, 0x080c, 0x10f8, 0x002e, 0x008e, 0x0005, 0x0006, - 0x0016, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x0156, 0x080c, 0x8776, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x00be, 0x00ae, 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, - 0x19fb, 0x717a, 0x727e, 0x7077, 0x0009, 0x00ee, 0x0005, 0x00e6, - 0x0006, 0x2071, 0x19fb, 0x707c, 0x9206, 0x1110, 0x707a, 0x707e, - 0x000e, 0x00ee, 0x0005, 0x2069, 0x1800, 0x69e8, 0xd1e4, 0x1518, - 0x0026, 0xd1ec, 0x0140, 0x6a54, 0x6874, 0x9202, 0x0288, 0x8117, - 0x9294, 0x00c0, 0x0088, 0x9184, 0x0007, 0x01a0, 0x8109, 0x9184, - 0x0007, 0x0110, 0x69ea, 0x0070, 0x8107, 0x9084, 0x0007, 0x910d, - 0x8107, 0x9106, 0x9094, 0x00c0, 0x9184, 0xff3f, 0x9205, 0x68ea, - 0x080c, 0x0eee, 0x002e, 0x0005, 0x0016, 0x00c6, 0x2009, 0xfff4, - 0x210d, 0x2061, 0x0100, 0x60f0, 0x9100, 0x60f3, 0x0000, 0x2009, - 0xfff4, 0x200f, 0x1220, 0x8108, 0x2105, 0x8000, 0x200f, 0x00ce, - 0x001e, 0x0005, 0x00c6, 0x2061, 0x1a74, 0x00ce, 0x0005, 0x9184, - 0x000f, 0x8003, 0x8003, 0x8003, 0x9080, 0x1a74, 0x2060, 0x0005, - 0xa884, 0x908a, 0x199a, 0x1638, 0x9005, 0x1150, 0x00c6, 0x2061, - 0x1a74, 0x6014, 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, 0x0018, - 0x908e, 0xffff, 0x01b0, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, - 0xa87c, 0x908c, 0x00c0, 0x918e, 0x00c0, 0x0904, 0x89fa, 0xd0b4, - 0x1168, 0xd0bc, 0x1904, 0x89d3, 0x2009, 0x0006, 0x080c, 0x8a27, - 0x0005, 0x900e, 0x0c60, 0x2001, 0x1999, 0x08b0, 0xd0fc, 0x0160, - 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x8a21, 0x908c, - 0x2020, 0x918e, 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11e8, 0x2009, - 0x1869, 0x2104, 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043, - 0x0804, 0xb352, 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804, - 0xb352, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, - 0x6024, 0xc0cd, 0x6026, 0x0c00, 0xc0d4, 0x6026, 0xa890, 0x602e, - 0xa88c, 0x6032, 0x08e0, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120, - 0x918e, 0x0003, 0x1904, 0x8a21, 0x908c, 0x2020, 0x918e, 0x2020, - 0x0170, 0x0076, 0x00f6, 0x2c78, 0x080c, 0x1768, 0x00fe, 0x007e, - 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0xb352, 0x0005, 0x6110, - 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d58, 0x6124, 0xc1cd, - 0x6126, 0x0c38, 0xd0fc, 0x0188, 0x908c, 0x2020, 0x918e, 0x2020, - 0x01a8, 0x9084, 0x0003, 0x908e, 0x0002, 0x0148, 0x87ff, 0x1120, - 0x2009, 0x0041, 0x080c, 0xb352, 0x0005, 0x00b9, 0x0ce8, 0x87ff, - 0x1dd8, 0x2009, 0x0043, 0x080c, 0xb352, 0x0cb0, 0x6110, 0x00b6, - 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6124, 0xc1cd, 0x6126, - 0x0c00, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x0096, - 0x080c, 0xd0d8, 0x0518, 0x6014, 0x2048, 0xa982, 0xa800, 0x6016, - 0x9186, 0x0001, 0x1188, 0xa97c, 0x918c, 0x8100, 0x918e, 0x8100, - 0x1158, 0x00c6, 0x2061, 0x1a74, 0x6200, 0xd28c, 0x1120, 0x6204, - 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x6cde, 0x6014, 0x904d, - 0x0076, 0x2039, 0x0000, 0x190c, 0x8970, 0x007e, 0x009e, 0x0005, - 0x0156, 0x00c6, 0x2061, 0x1a74, 0x6000, 0x81ff, 0x0110, 0x9205, - 0x0008, 0x9204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, - 0x1138, 0x6808, 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, 0x0001, - 0x0005, 0x2071, 0x1924, 0x7003, 0x0006, 0x7007, 0x0000, 0x700f, - 0x0000, 0x7013, 0x0001, 0x080c, 0x1027, 0x090c, 0x0dc5, 0xa867, - 0x0006, 0xa86b, 0x0001, 0xa8ab, 0xdcb0, 0xa89f, 0x0000, 0x2900, - 0x702e, 0x7033, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, 0x0096, - 0x00e6, 0x2071, 0x1924, 0x702c, 0x2048, 0x6a2c, 0x721e, 0x6b30, - 0x7322, 0x6834, 0x7026, 0xa896, 0x6838, 0x702a, 0xa89a, 0x6824, - 0x7016, 0x683c, 0x701a, 0x2009, 0x0028, 0x200a, 0x9005, 0x0148, - 0x900e, 0x9188, 0x000c, 0x8001, 0x1de0, 0x2100, 0x9210, 0x1208, - 0x8318, 0xaa8e, 0xab92, 0x7010, 0xd084, 0x0168, 0xc084, 0x7007, - 0x0001, 0x700f, 0x0000, 0x0006, 0x2009, 0x1ad1, 0x2104, 0x9082, - 0x0007, 0x200a, 0x000e, 0xc095, 0x7012, 0x2008, 0x2001, 0x003b, - 0x080c, 0x1611, 0x9006, 0x2071, 0x193d, 0x7002, 0x7006, 0x702a, - 0x00ee, 0x009e, 0x012e, 0x0005, 0x2009, 0x1ad1, 0x2104, 0x9080, - 0x0007, 0x200a, 0x0005, 0x00e6, 0x0126, 0x0156, 0x2091, 0x8000, - 0x2071, 0x1800, 0x7154, 0x2001, 0x0008, 0x910a, 0x0638, 0x2001, - 0x187d, 0x20ac, 0x9006, 0x9080, 0x0008, 0x1f04, 0x8ae3, 0x71c0, - 0x9102, 0x02e0, 0x2071, 0x1877, 0x20a9, 0x0007, 0x00c6, 0x080c, - 0xb27d, 0x6023, 0x0009, 0x6003, 0x0004, 0x601f, 0x0101, 0x0089, - 0x0126, 0x2091, 0x8000, 0x080c, 0x8c61, 0x012e, 0x1f04, 0x8aef, - 0x9006, 0x00ce, 0x015e, 0x012e, 0x00ee, 0x0005, 0x9085, 0x0001, - 0x0cc8, 0x00e6, 0x00b6, 0x0096, 0x0086, 0x0056, 0x0046, 0x0026, - 0x7118, 0x720c, 0x7620, 0x7004, 0xd084, 0x1128, 0x2021, 0x0024, - 0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029, 0x000a, 0x080c, - 0x100e, 0x090c, 0x0dc5, 0x2900, 0x6016, 0x2058, 0xac66, 0x9006, - 0xa802, 0xa806, 0xa86a, 0xa87a, 0xa8aa, 0xa887, 0x0005, 0xa87f, - 0x0020, 0x7008, 0xa89a, 0x7010, 0xa89e, 0xae8a, 0xa8af, 0xffff, - 0xa8b3, 0x0000, 0x8109, 0x0160, 0x080c, 0x100e, 0x090c, 0x0dc5, - 0xad66, 0x2b00, 0xa802, 0x2900, 0xb806, 0x2058, 0x8109, 0x1da0, - 0x002e, 0x004e, 0x005e, 0x008e, 0x009e, 0x00be, 0x00ee, 0x0005, - 0x2079, 0x0000, 0x2071, 0x1924, 0x7004, 0x004b, 0x700c, 0x0002, - 0x8b5b, 0x8b54, 0x8b54, 0x0005, 0x8b65, 0x8bbb, 0x8bbb, 0x8bbb, - 0x8bbc, 0x8bcd, 0x8bcd, 0x700c, 0x0cba, 0x0126, 0x2091, 0x8000, - 0x78a0, 0x79a0, 0x9106, 0x1904, 0x8bad, 0x7814, 0xd0bc, 0x1904, - 0x8bb6, 0x012e, 0x7018, 0x910a, 0x1128, 0x7030, 0x9005, 0x1904, - 0x8bff, 0x0005, 0x1210, 0x7114, 0x910a, 0x9192, 0x000a, 0x0210, - 0x2009, 0x000a, 0x2001, 0x1888, 0x2014, 0x2001, 0x1936, 0x2004, - 0x9100, 0x9202, 0x0e50, 0x080c, 0x8d5c, 0x2200, 0x9102, 0x0208, - 0x2208, 0x0096, 0x702c, 0x2048, 0xa873, 0x0001, 0xa976, 0x080c, - 0x8e65, 0x2100, 0xa87e, 0xa86f, 0x0000, 0x009e, 0x0126, 0x2091, - 0x8000, 0x2009, 0x1a1b, 0x2104, 0xc085, 0x200a, 0x700f, 0x0002, - 0x012e, 0x080c, 0x1117, 0x1de8, 0x0005, 0x78a0, 0x79a0, 0x9106, - 0x0904, 0x8b6d, 0x080c, 0x8d34, 0x012e, 0x0005, 0x7810, 0xc0c5, - 0x7812, 0x0804, 0x8b6d, 0x0005, 0x700c, 0x0002, 0x8bc1, 0x8bc4, - 0x8bc3, 0x080c, 0x8b63, 0x0005, 0x8001, 0x700e, 0x0096, 0x702c, - 0x2048, 0xa974, 0x009e, 0x0011, 0x0ca0, 0x0005, 0x0096, 0x702c, - 0x2048, 0x7018, 0x9100, 0x7214, 0x921a, 0x1130, 0x701c, 0xa88e, - 0x7020, 0xa892, 0x9006, 0x0068, 0x0006, 0x080c, 0x8e65, 0x2100, - 0xaa8c, 0x9210, 0xaa8e, 0x1220, 0xa890, 0x9081, 0x0000, 0xa892, - 0x000e, 0x009e, 0x0126, 0x2091, 0x8000, 0x78a2, 0x701a, 0x080c, - 0x8d34, 0x012e, 0x0005, 0x00e6, 0x2071, 0x1924, 0x700c, 0x0002, - 0x8bfd, 0x8bfd, 0x8bfb, 0x700f, 0x0001, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x8000, 0x7030, 0x9005, 0x0508, 0x2078, 0x7814, 0x2048, - 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8c6a, 0x00be, 0x01b0, - 0x00e6, 0x2071, 0x193d, 0x080c, 0x8cb1, 0x00ee, 0x0178, 0x0096, - 0x080c, 0x1027, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x04b9, 0x0041, - 0x2001, 0x1947, 0x2003, 0x0000, 0x012e, 0x08c8, 0x012e, 0x0005, - 0x00d6, 0x00c6, 0x0086, 0x00a6, 0x2940, 0x2650, 0x2600, 0x9005, - 0x0180, 0xa864, 0x9084, 0x000f, 0x2068, 0x9d88, 0x20c7, 0x2165, - 0x0056, 0x2029, 0x0000, 0x080c, 0x8dea, 0x080c, 0x207f, 0x1dd8, - 0x005e, 0x00ae, 0x2001, 0x187f, 0x2004, 0xa88a, 0x080c, 0x1768, - 0x781f, 0x0101, 0x7813, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, - 0x8cc0, 0x012e, 0x008e, 0x00ce, 0x00de, 0x0005, 0x7030, 0x9005, - 0x0138, 0x2078, 0x780c, 0x7032, 0x2001, 0x1947, 0x2003, 0x0001, - 0x0005, 0x00e6, 0x2071, 0x1924, 0x7030, 0x600e, 0x2c00, 0x7032, - 0x00ee, 0x0005, 0x00d6, 0x00c6, 0x0026, 0x9b80, 0x8f33, 0x2005, - 0x906d, 0x090c, 0x0dc5, 0x9b80, 0x8f2b, 0x2005, 0x9065, 0x090c, - 0x0dc5, 0x6114, 0x2600, 0x9102, 0x0248, 0x6828, 0x9102, 0x02f0, - 0x9085, 0x0001, 0x002e, 0x00ce, 0x00de, 0x0005, 0x6804, 0xd094, - 0x0148, 0x6854, 0xd084, 0x1178, 0xc085, 0x6856, 0x2011, 0x8026, - 0x080c, 0x4c44, 0x684c, 0x0096, 0x904d, 0x090c, 0x0dc5, 0xa804, - 0x8000, 0xa806, 0x009e, 0x9006, 0x2030, 0x0c20, 0x6854, 0xd08c, - 0x1d08, 0xc08d, 0x6856, 0x2011, 0x8025, 0x080c, 0x4c44, 0x684c, - 0x0096, 0x904d, 0x090c, 0x0dc5, 0xa800, 0x8000, 0xa802, 0x009e, - 0x0888, 0x7000, 0x2019, 0x0008, 0x8319, 0x7104, 0x9102, 0x1118, - 0x2300, 0x9005, 0x0020, 0x0210, 0x9302, 0x0008, 0x8002, 0x0005, - 0x00d6, 0x7814, 0x9005, 0x090c, 0x0dc5, 0x781c, 0x9084, 0x0101, - 0x9086, 0x0101, 0x190c, 0x0dc5, 0x7827, 0x0000, 0x2069, 0x193d, - 0x6804, 0x9080, 0x193f, 0x2f08, 0x2102, 0x6904, 0x8108, 0x9182, - 0x0008, 0x0208, 0x900e, 0x6906, 0x9180, 0x193f, 0x2003, 0x0000, - 0x00de, 0x0005, 0x0096, 0x00c6, 0x2060, 0x6014, 0x2048, 0xa8a8, - 0x0096, 0x2048, 0x9005, 0x190c, 0x1040, 0x009e, 0xa8ab, 0x0000, - 0x080c, 0x0fc0, 0x080c, 0xb2d3, 0x00ce, 0x009e, 0x0005, 0x6020, - 0x9086, 0x0009, 0x1128, 0x601c, 0xd0c4, 0x0110, 0x9006, 0x0005, - 0x9085, 0x0001, 0x0005, 0x6000, 0x9086, 0x0000, 0x0178, 0x6010, - 0x9005, 0x0150, 0x00b6, 0x2058, 0x080c, 0x9067, 0x00be, 0x6013, - 0x0000, 0x601b, 0x0000, 0x0010, 0x2c00, 0x0861, 0x0005, 0x2009, - 0x1928, 0x210c, 0xd194, 0x0005, 0x2009, 0x1928, 0x210c, 0xd1c4, - 0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, 0x1924, 0x7110, - 0xc194, 0xc185, 0x7007, 0x0000, 0x7112, 0x2001, 0x003b, 0x080c, - 0x1611, 0x00ee, 0x012e, 0x0005, 0x7814, 0xd0bc, 0x1108, 0x0005, - 0x7810, 0xc0c5, 0x7812, 0x0cc0, 0x0096, 0x00d6, 0x9006, 0x7006, - 0x700e, 0x701a, 0x701e, 0x7022, 0x7016, 0x702a, 0x7026, 0x702f, - 0x0000, 0x080c, 0x8eb3, 0x0170, 0x080c, 0x8ee8, 0x0158, 0x2900, - 0x7002, 0x700a, 0x701a, 0x7013, 0x0001, 0x701f, 0x000a, 0x00de, - 0x009e, 0x0005, 0x900e, 0x0cd8, 0x00e6, 0x0096, 0x0086, 0x00d6, - 0x00c6, 0x2071, 0x1931, 0x721c, 0x2100, 0x9202, 0x1618, 0x080c, - 0x8ee8, 0x090c, 0x0dc5, 0x7018, 0x9005, 0x1160, 0x2900, 0x7002, - 0x700a, 0x701a, 0x9006, 0x7006, 0x700e, 0xa806, 0xa802, 0x7012, - 0x701e, 0x0038, 0x2040, 0xa806, 0x2900, 0xa002, 0x701a, 0xa803, - 0x0000, 0x7010, 0x8000, 0x7012, 0x701c, 0x9080, 0x000a, 0x701e, - 0x721c, 0x08d0, 0x721c, 0x00ce, 0x00de, 0x008e, 0x009e, 0x00ee, - 0x0005, 0x0096, 0x0156, 0x0136, 0x0146, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x2071, 0x1931, 0x7300, 0x831f, 0x831e, 0x831e, 0x9384, - 0x003f, 0x20e8, 0x939c, 0xffc0, 0x9398, 0x0003, 0x7104, 0x080c, - 0x8e65, 0x810c, 0x2100, 0x9318, 0x8003, 0x2228, 0x2021, 0x0078, - 0x9402, 0x9532, 0x0208, 0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0, - 0xa001, 0xa001, 0x4005, 0x2508, 0x080c, 0x8e6e, 0x2130, 0x7014, - 0x9600, 0x7016, 0x2600, 0x711c, 0x9102, 0x701e, 0x7004, 0x9600, - 0x2008, 0x9082, 0x000a, 0x1190, 0x7000, 0x2048, 0xa800, 0x9005, - 0x1148, 0x2009, 0x0001, 0x0026, 0x080c, 0x8d5c, 0x002e, 0x7000, - 0x2048, 0xa800, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x2500, - 0x9212, 0x1904, 0x8d9b, 0x012e, 0x00ee, 0x014e, 0x013e, 0x015e, - 0x009e, 0x0005, 0x0016, 0x0026, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x9580, 0x8f2b, 0x2005, 0x9075, 0x090c, 0x0dc5, 0x080c, 0x8e40, - 0x012e, 0x9580, 0x8f27, 0x2005, 0x9075, 0x090c, 0x0dc5, 0x0156, - 0x0136, 0x01c6, 0x0146, 0x01d6, 0x831f, 0x831e, 0x831e, 0x9384, - 0x003f, 0x20e0, 0x9384, 0xffc0, 0x9100, 0x2098, 0xa860, 0x20e8, - 0xa95c, 0x2c05, 0x9100, 0x20a0, 0x20a9, 0x0002, 0x4003, 0x2e0c, - 0x2d00, 0x0002, 0x8e2a, 0x8e2a, 0x8e2c, 0x8e2a, 0x8e2c, 0x8e2a, - 0x8e2a, 0x8e2a, 0x8e2a, 0x8e2a, 0x8e32, 0x8e2a, 0x8e32, 0x8e2a, - 0x8e2a, 0x8e2a, 0x080c, 0x0dc5, 0x4104, 0x20a9, 0x0002, 0x4002, - 0x4003, 0x0028, 0x20a9, 0x0002, 0x4003, 0x4104, 0x4003, 0x01de, - 0x014e, 0x01ce, 0x013e, 0x015e, 0x00ee, 0x002e, 0x001e, 0x0005, - 0x0096, 0x7014, 0x8001, 0x7016, 0x710c, 0x2110, 0x00f1, 0x810c, - 0x9188, 0x0003, 0x7308, 0x8210, 0x9282, 0x000a, 0x1198, 0x7008, - 0x2048, 0xa800, 0x9005, 0x0158, 0x0006, 0x080c, 0x8ef7, 0x009e, - 0xa807, 0x0000, 0x2900, 0x700a, 0x7010, 0x8001, 0x7012, 0x700f, - 0x0000, 0x0008, 0x720e, 0x009e, 0x0005, 0x0006, 0x810b, 0x810b, - 0x2100, 0x810b, 0x9100, 0x2008, 0x000e, 0x0005, 0x0006, 0x0026, - 0x2100, 0x9005, 0x0158, 0x9092, 0x000c, 0x0240, 0x900e, 0x8108, - 0x9082, 0x000c, 0x1de0, 0x002e, 0x000e, 0x0005, 0x900e, 0x0cd8, - 0x2d00, 0x90b8, 0x0008, 0x2031, 0x8eb1, 0x901e, 0x6808, 0x9005, - 0x0108, 0x8318, 0x690c, 0x910a, 0x0248, 0x0140, 0x8318, 0x6810, - 0x9112, 0x0220, 0x0118, 0x8318, 0x2208, 0x0cd0, 0x233a, 0x6804, - 0xd084, 0x2300, 0x2021, 0x0001, 0x1150, 0x9082, 0x0003, 0x0967, - 0x0a67, 0x8420, 0x9082, 0x0007, 0x0967, 0x0a67, 0x0cd0, 0x9082, - 0x0002, 0x0967, 0x0a67, 0x8420, 0x9082, 0x0005, 0x0967, 0x0a67, - 0x0cd0, 0x6c1a, 0x0005, 0x0096, 0x0046, 0x0126, 0x2091, 0x8000, - 0x2b00, 0x9080, 0x8f2f, 0x2005, 0x9005, 0x090c, 0x0dc5, 0x2004, - 0x90a0, 0x000a, 0x080c, 0x1027, 0x01d0, 0x2900, 0x7026, 0xa803, - 0x0000, 0xa807, 0x0000, 0x080c, 0x1027, 0x0188, 0x7024, 0xa802, - 0xa807, 0x0000, 0x2900, 0x7026, 0x94a2, 0x000a, 0x0110, 0x0208, - 0x0c90, 0x9085, 0x0001, 0x012e, 0x004e, 0x009e, 0x0005, 0x7024, - 0x9005, 0x0dc8, 0x2048, 0xac00, 0x080c, 0x1040, 0x2400, 0x0cc0, - 0x0126, 0x2091, 0x8000, 0x7024, 0x2048, 0x9005, 0x0130, 0xa800, - 0x7026, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x0005, 0x0126, - 0x2091, 0x8000, 0x7024, 0xa802, 0x2900, 0x7026, 0x012e, 0x0005, - 0x0096, 0x9e80, 0x0009, 0x2004, 0x9005, 0x0138, 0x2048, 0xa800, - 0x0006, 0x080c, 0x1040, 0x000e, 0x0cb8, 0x009e, 0x0005, 0x0096, - 0x7008, 0x9005, 0x0138, 0x2048, 0xa800, 0x0006, 0x080c, 0x1040, - 0x000e, 0x0cb8, 0x9006, 0x7002, 0x700a, 0x7006, 0x700e, 0x701a, - 0x701e, 0x7022, 0x702a, 0x7026, 0x702e, 0x009e, 0x0005, 0x1a67, - 0x0000, 0x0000, 0x0000, 0x1931, 0x0000, 0x0000, 0x0000, 0x1888, - 0x0000, 0x0000, 0x0000, 0x1877, 0x0000, 0x0000, 0x0000, 0x00e6, - 0x00c6, 0x00b6, 0x00a6, 0xa8a8, 0x2040, 0x2071, 0x1877, 0x080c, - 0x9053, 0xa067, 0x0023, 0x6010, 0x905d, 0x0904, 0x9028, 0xb814, - 0xa06e, 0xb910, 0xa172, 0xb9a0, 0xa176, 0x2001, 0x0003, 0xa07e, - 0xa834, 0xa082, 0xa07b, 0x0000, 0xa898, 0x9005, 0x0118, 0xa078, - 0xc085, 0xa07a, 0x2858, 0x2031, 0x0018, 0xa068, 0x908a, 0x0019, - 0x1a0c, 0x0dc5, 0x2020, 0x2050, 0x2940, 0xa864, 0x90bc, 0x00ff, - 0x908c, 0x000f, 0x91e0, 0x20c7, 0x2c65, 0x9786, 0x0024, 0x2c05, - 0x1590, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002, - 0x8f93, 0x8f93, 0x8f95, 0x8f93, 0x8f93, 0x8f93, 0x8f97, 0x8f93, - 0x8f93, 0x8f93, 0x8f99, 0x8f93, 0x8f93, 0x8f93, 0x8f9b, 0x8f93, - 0x8f93, 0x8f93, 0x8f9d, 0x8f93, 0x8f93, 0x8f93, 0x8f9f, 0x8f93, - 0x8f93, 0x8f93, 0x8fa1, 0x080c, 0x0dc5, 0xa180, 0x04b8, 0xa190, - 0x04a8, 0xa1a0, 0x0498, 0xa1b0, 0x0488, 0xa1c0, 0x0478, 0xa1d0, - 0x0468, 0xa1e0, 0x0458, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, - 0x001b, 0x0002, 0x8fc5, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, - 0x8fc7, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc9, 0x8fc3, - 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fcb, 0x8fc3, 0x8fc3, 0x8fc3, - 0x8fc3, 0x8fc3, 0x8fcd, 0x080c, 0x0dc5, 0xa180, 0x0038, 0xa198, - 0x0028, 0xa1b0, 0x0018, 0xa1c8, 0x0008, 0xa1e0, 0x2600, 0x0002, - 0x8fe9, 0x8feb, 0x8fed, 0x8fef, 0x8ff1, 0x8ff3, 0x8ff5, 0x8ff7, - 0x8ff9, 0x8ffb, 0x8ffd, 0x8fff, 0x9001, 0x9003, 0x9005, 0x9007, - 0x9009, 0x900b, 0x900d, 0x900f, 0x9011, 0x9013, 0x9015, 0x9017, - 0x9019, 0x080c, 0x0dc5, 0xb9e2, 0x0468, 0xb9de, 0x0458, 0xb9da, - 0x0448, 0xb9d6, 0x0438, 0xb9d2, 0x0428, 0xb9ce, 0x0418, 0xb9ca, - 0x0408, 0xb9c6, 0x00f8, 0xb9c2, 0x00e8, 0xb9be, 0x00d8, 0xb9ba, - 0x00c8, 0xb9b6, 0x00b8, 0xb9b2, 0x00a8, 0xb9ae, 0x0098, 0xb9aa, - 0x0088, 0xb9a6, 0x0078, 0xb9a2, 0x0068, 0xb99e, 0x0058, 0xb99a, - 0x0048, 0xb996, 0x0038, 0xb992, 0x0028, 0xb98e, 0x0018, 0xb98a, - 0x0008, 0xb986, 0x8631, 0x8421, 0x0130, 0x080c, 0x207f, 0x090c, - 0x0dc5, 0x0804, 0x8f6d, 0x00ae, 0x00be, 0x00ce, 0x00ee, 0x0005, - 0xa86c, 0xa06e, 0xa870, 0xa072, 0xa077, 0x00ff, 0x9006, 0x0804, - 0x8f4f, 0x0006, 0x0016, 0x00b6, 0x6010, 0x2058, 0xb810, 0x9005, - 0x01b0, 0x2001, 0x1925, 0x2004, 0x9005, 0x0188, 0x2001, 0x1800, - 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0xbba0, 0x2021, - 0x0004, 0x2011, 0x8014, 0x080c, 0x4c44, 0x004e, 0x003e, 0x00be, - 0x001e, 0x000e, 0x0005, 0x9016, 0x710c, 0xa834, 0x910a, 0xa936, - 0x7008, 0x9005, 0x0120, 0x8210, 0x910a, 0x0230, 0x0128, 0x7010, - 0x8210, 0x910a, 0x0208, 0x1de0, 0xaa8a, 0xa26a, 0x0005, 0x00f6, - 0x00d6, 0x0036, 0x2079, 0x0300, 0x781b, 0x0200, 0x7818, 0xd094, - 0x1dd8, 0x781b, 0x0202, 0xa001, 0xa001, 0x7818, 0xd094, 0x1da0, - 0xb8ac, 0x906d, 0x0198, 0x2079, 0x0000, 0x9c1e, 0x1118, 0x680c, - 0xb8ae, 0x0050, 0x9c06, 0x0130, 0x2d78, 0x680c, 0x906d, 0x1dd0, - 0x080c, 0x0dc5, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x2079, 0x0300, - 0x781b, 0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x00d6, - 0x0096, 0x00c6, 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, 0x20a9, - 0x01ff, 0x2071, 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, 0x0110, - 0x1f04, 0x90a3, 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, 0xd094, - 0x1d90, 0xb8ac, 0x9065, 0x01f0, 0x600c, 0xb8ae, 0x6024, 0xc08d, - 0x6026, 0x6003, 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, 0x601f, - 0x0101, 0x6014, 0x904d, 0x090c, 0x0dc5, 0xa88b, 0x0000, 0xa8a8, - 0xa8ab, 0x0000, 0x904d, 0x090c, 0x0dc5, 0x080c, 0x1040, 0x080c, - 0x8c61, 0x08f8, 0x2071, 0x0300, 0x701b, 0x0200, 0x015e, 0x012e, - 0x003e, 0x00ce, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x00b6, - 0x0016, 0x0006, 0x0156, 0x080c, 0x2873, 0x015e, 0x11b0, 0x080c, - 0x66b9, 0x190c, 0x0dc5, 0x000e, 0x001e, 0xb912, 0xb816, 0x080c, - 0xb27d, 0x0140, 0x2b00, 0x6012, 0x6023, 0x0001, 0x2009, 0x0001, - 0x080c, 0xb352, 0x00be, 0x00ce, 0x0005, 0x000e, 0x001e, 0x0cd0, - 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, - 0x0005, 0x9119, 0x9119, 0x9119, 0x911b, 0x916c, 0x9119, 0x9119, - 0x9119, 0x91e6, 0x9119, 0x9223, 0x9119, 0x9119, 0x9119, 0x9119, - 0x9119, 0x080c, 0x0dc5, 0x9182, 0x0040, 0x0002, 0x912e, 0x912e, - 0x912e, 0x912e, 0x912e, 0x912e, 0x912e, 0x912e, 0x912e, 0x9130, - 0x9145, 0x912e, 0x912e, 0x912e, 0x912e, 0x9158, 0x080c, 0x0dc5, - 0x0096, 0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6114, 0x2148, 0xa87b, - 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, - 0x6ca3, 0x080c, 0xb2d3, 0x009e, 0x0005, 0x080c, 0x9a61, 0x00d6, - 0x6114, 0x080c, 0xd0d8, 0x0130, 0x0096, 0x6114, 0x2148, 0x080c, - 0x6e9f, 0x009e, 0x00de, 0x080c, 0xb2d3, 0x080c, 0x9bd3, 0x0005, - 0x080c, 0x9a61, 0x080c, 0x3250, 0x6114, 0x0096, 0x2148, 0x080c, - 0xd0d8, 0x0120, 0xa87b, 0x0029, 0x080c, 0x6e9f, 0x009e, 0x080c, - 0xb2d3, 0x080c, 0x9bd3, 0x0005, 0x601b, 0x0000, 0x9182, 0x0040, - 0x0096, 0x0002, 0x9187, 0x9187, 0x9187, 0x9187, 0x9187, 0x9187, - 0x9187, 0x9187, 0x9189, 0x9187, 0x9187, 0x9187, 0x91e2, 0x9187, - 0x9187, 0x9187, 0x9187, 0x9187, 0x9187, 0x9190, 0x9187, 0x080c, - 0x0dc5, 0x6114, 0x2148, 0xa938, 0x918e, 0xffff, 0x0904, 0x91e2, - 0x6024, 0xd08c, 0x15d8, 0x080c, 0x8d17, 0x05e0, 0x00e6, 0x6114, - 0x2148, 0x080c, 0x8f37, 0x0096, 0xa8a8, 0x2048, 0x080c, 0x6c3b, - 0x009e, 0xa8ab, 0x0000, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, - 0x080c, 0x9067, 0x00be, 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, - 0x8c6a, 0x00be, 0x01e0, 0x2071, 0x193d, 0x080c, 0x8cb1, 0x01b8, - 0x9086, 0x0001, 0x1128, 0x2001, 0x1947, 0x2004, 0x9005, 0x1178, - 0x0096, 0x080c, 0x100e, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x00f6, - 0x2c78, 0x080c, 0x8c28, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x080c, - 0x8c61, 0x0cd0, 0x080c, 0x8d1c, 0x1160, 0x6010, 0x9005, 0x0130, - 0x2058, 0xb8ac, 0x9005, 0x190c, 0x0dc5, 0x6012, 0x2c00, 0x080c, - 0x8ce2, 0x0005, 0x080c, 0x9290, 0x009e, 0x0005, 0x9182, 0x0040, - 0x0096, 0x0002, 0x91fa, 0x91fa, 0x91fa, 0x91fc, 0x91fa, 0x91fa, - 0x91fa, 0x9221, 0x91fa, 0x91fa, 0x91fa, 0x91fa, 0x91fa, 0x91fa, - 0x91fa, 0x91fa, 0x080c, 0x0dc5, 0x6003, 0x0003, 0x6106, 0x6014, - 0x2048, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0xa837, 0x0000, 0xa83b, - 0x0000, 0xa884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, - 0x8013, 0x8213, 0x9210, 0x621a, 0x2c10, 0x080c, 0x1be0, 0x080c, - 0x9564, 0x0126, 0x2091, 0x8000, 0x080c, 0x9bd3, 0x012e, 0x009e, - 0x0005, 0x080c, 0x0dc5, 0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6114, - 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, - 0x00be, 0x080c, 0x6e9f, 0x080c, 0xb2d3, 0x009e, 0x0005, 0x6000, - 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0096, 0x0013, 0x009e, 0x0005, - 0x9250, 0x9250, 0x9250, 0x9252, 0x9263, 0x9250, 0x9250, 0x9250, - 0x9250, 0x9250, 0x9250, 0x9250, 0x9250, 0x9250, 0x9250, 0x9250, - 0x080c, 0x0dc5, 0x080c, 0xac2b, 0x6114, 0x2148, 0xa87b, 0x0006, - 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, 0x6e9f, - 0x080c, 0xb2d3, 0x0005, 0x0461, 0x0005, 0x6000, 0x908a, 0x0010, - 0x1a0c, 0x0dc5, 0x0096, 0x0013, 0x009e, 0x0005, 0x927e, 0x927e, - 0x927e, 0x9280, 0x9290, 0x927e, 0x927e, 0x927e, 0x927e, 0x927e, - 0x927e, 0x927e, 0x927e, 0x927e, 0x927e, 0x927e, 0x080c, 0x0dc5, - 0x0036, 0x00e6, 0x2071, 0x19e8, 0x703c, 0x9c06, 0x1120, 0x2019, - 0x0000, 0x080c, 0xaa49, 0x080c, 0xac2b, 0x00ee, 0x003e, 0x0005, - 0x6024, 0xd08c, 0x11f0, 0x00f6, 0x00e6, 0x601b, 0x0000, 0x6014, - 0x2048, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, 0x9067, - 0x00be, 0x2071, 0x193d, 0x080c, 0x8cb1, 0x0160, 0x2001, 0x187f, - 0x2004, 0xa88a, 0x2031, 0x0000, 0x2c78, 0x080c, 0x8c28, 0x00ee, - 0x00fe, 0x0005, 0x0096, 0xa88b, 0x0000, 0xa8a8, 0x2048, 0x080c, - 0x1040, 0x009e, 0xa8ab, 0x0000, 0x080c, 0x8c61, 0x0c80, 0x2001, - 0x1925, 0x200c, 0x918e, 0x0000, 0x190c, 0x8d17, 0x05c8, 0x00e6, - 0x2071, 0x1924, 0x7110, 0xc1c5, 0x7112, 0x080c, 0x8d21, 0x00f6, - 0x00c6, 0x2071, 0x1000, 0x00b6, 0x2e04, 0x905d, 0x0138, 0xb8ac, - 0x9065, 0x0120, 0x080c, 0x8cf7, 0x090c, 0x9096, 0x8e70, 0x9e86, - 0x1800, 0x1d90, 0x00be, 0x00d6, 0x0096, 0x0046, 0x2061, 0x1cd0, - 0x2001, 0x181a, 0x2024, 0x6020, 0x9086, 0x0000, 0x1191, 0x9ce0, - 0x0018, 0x2400, 0x9c06, 0x1db8, 0x004e, 0x009e, 0x00de, 0x00d1, - 0x00ce, 0x00fe, 0x2071, 0x1924, 0x7110, 0xc1c4, 0x7112, 0x00ee, - 0x0005, 0x6020, 0x9086, 0x0009, 0x1160, 0x6100, 0x9186, 0x0004, - 0x1138, 0x6110, 0x81ff, 0x190c, 0x0dc5, 0x2c00, 0x080c, 0x8ce2, - 0x9006, 0x0005, 0x2071, 0x193f, 0x2073, 0x0000, 0x8e70, 0x9e86, - 0x1947, 0x1dd0, 0x2071, 0x193d, 0x7006, 0x7002, 0x2001, 0x1930, - 0x2064, 0x8cff, 0x0130, 0x6120, 0x918e, 0x0000, 0x190c, 0x0dc5, - 0x2102, 0x2001, 0x188a, 0x200c, 0x81ff, 0x0148, 0x0096, 0x2148, - 0x080c, 0x1040, 0x009e, 0x2001, 0x188a, 0x2003, 0x0000, 0x2071, - 0x1931, 0x080c, 0x8f00, 0x0804, 0x8f0f, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x187a, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0126, 0x2091, 0x8000, - 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, 0x2019, 0x0100, - 0x231c, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, - 0x3e00, 0x81f6, 0x3e08, 0x1208, 0x9200, 0x1f04, 0x9356, 0x93a6, - 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6, - 0x3e08, 0x004e, 0x003e, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, 0x0510, 0x911a, 0x1600, - 0x8213, 0x2039, 0x0100, 0x273c, 0x97be, 0x0008, 0x1110, 0x818d, - 0x0010, 0x81f5, 0x3e08, 0x0228, 0x911a, 0x1220, 0x1f04, 0x9380, - 0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, 0x9380, 0x0006, 0x3200, - 0x9084, 0xefff, 0x2080, 0x000e, 0x015e, 0x007e, 0x012e, 0x0005, - 0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, - 0x2079, 0x19e8, 0x012e, 0x00d6, 0x2069, 0x19e8, 0x6803, 0x0005, - 0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, - 0xaf8e, 0x0401, 0x080c, 0xaf79, 0x00e9, 0x080c, 0xaf7c, 0x00d1, - 0x080c, 0xaf7f, 0x00b9, 0x080c, 0xaf82, 0x00a1, 0x080c, 0xaf85, - 0x0089, 0x080c, 0xaf88, 0x0071, 0x080c, 0xaf8b, 0x0059, 0x01de, - 0x014e, 0x015e, 0x2069, 0x0004, 0x2d04, 0x9085, 0x8001, 0x206a, - 0x00de, 0x0005, 0x20a9, 0x0020, 0x20a1, 0x0240, 0x2001, 0x0000, - 0x4004, 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0x9084, 0x0007, - 0x0002, 0x93f3, 0x9417, 0x9458, 0x93f9, 0x9417, 0x93f3, 0x93f1, - 0x93f1, 0x080c, 0x0dc5, 0x080c, 0x88c3, 0x080c, 0x9ab1, 0x00ce, - 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x5f97, - 0x080c, 0x883d, 0x7828, 0x9092, 0x00c8, 0x1228, 0x8000, 0x782a, - 0x080c, 0x5fd7, 0x0c88, 0x62c0, 0x080c, 0xb0ca, 0x080c, 0x5f97, - 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c28, 0x080c, - 0x88c3, 0x6220, 0xd2a4, 0x0170, 0xd2cc, 0x0160, 0x782b, 0x0000, - 0x7824, 0x9065, 0x090c, 0x0dc5, 0x2009, 0x0013, 0x080c, 0xb352, - 0x00ce, 0x0005, 0x00c6, 0x7824, 0x9065, 0x090c, 0x0dc5, 0x7828, - 0x9092, 0xc350, 0x12c0, 0x8000, 0x782a, 0x00ce, 0x080c, 0x2bce, - 0x0278, 0x00c6, 0x7924, 0x2160, 0x6010, 0x906d, 0x090c, 0x0dc5, - 0x7807, 0x0000, 0x7827, 0x0000, 0x00ce, 0x080c, 0x9ab1, 0x0c00, - 0x080c, 0xa6c5, 0x08e8, 0x2011, 0x0130, 0x2214, 0x080c, 0xb0ca, - 0x080c, 0xf094, 0x2009, 0x0014, 0x080c, 0xb352, 0x00ce, 0x0880, - 0x2001, 0x1a04, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, - 0x0000, 0x7824, 0x9065, 0x090c, 0x0dc5, 0x2009, 0x0013, 0x080c, - 0xb3a4, 0x00ce, 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x7824, 0x9005, - 0x090c, 0x0dc5, 0x7828, 0x9092, 0xc350, 0x1648, 0x8000, 0x782a, - 0x00de, 0x00ce, 0x00be, 0x080c, 0x2bce, 0x02f0, 0x00b6, 0x00c6, - 0x00d6, 0x781c, 0x905d, 0x090c, 0x0dc5, 0xb800, 0xc0dc, 0xb802, - 0x7924, 0x2160, 0x080c, 0xb2d3, 0xb93c, 0x81ff, 0x090c, 0x0dc5, - 0x8109, 0xb93e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, - 0x00be, 0x080c, 0x9ab1, 0x0868, 0x080c, 0xa6c5, 0x0850, 0x2011, - 0x0130, 0x2214, 0x080c, 0xb0ca, 0x080c, 0xf094, 0x7824, 0x9065, - 0x2009, 0x0014, 0x080c, 0xb352, 0x00de, 0x00ce, 0x00be, 0x0804, - 0x9469, 0x00c6, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x190c, 0x1eeb, - 0x6024, 0x6027, 0x0002, 0xd0f4, 0x15b8, 0x62c8, 0x60c4, 0x9205, - 0x1170, 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, 0x080c, 0xb352, - 0x00ce, 0x0005, 0x2011, 0x1a07, 0x2013, 0x0000, 0x0cc8, 0x793c, - 0x81ff, 0x0dc0, 0x7944, 0x9192, 0x7530, 0x1628, 0x8108, 0x7946, - 0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014, - 0x9084, 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, 0x793c, 0x9188, - 0x0008, 0x210c, 0x918e, 0x0009, 0x0d90, 0x6014, 0x9084, 0x1984, - 0x9085, 0x0016, 0x6016, 0x08a0, 0x793c, 0x2160, 0x2009, 0x004a, - 0x080c, 0xb352, 0x0868, 0x7848, 0xc085, 0x784a, 0x0848, 0x0006, - 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, - 0x2061, 0x19e8, 0x6020, 0x8000, 0x6022, 0x6010, 0x9005, 0x0148, - 0x9080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e, - 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x19e8, 0xb800, - 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0x9086, 0x0001, 0x1110, - 0x2b00, 0x681e, 0x00de, 0x0804, 0x9ab1, 0x00de, 0x0005, 0xc0d5, - 0xb802, 0x6818, 0x9005, 0x0168, 0xb856, 0xb85b, 0x0000, 0x0086, - 0x0006, 0x2b00, 0x681a, 0x008e, 0xa05a, 0x008e, 0x2069, 0x19e8, - 0x0c08, 0xb856, 0xb85a, 0x2b00, 0x681a, 0x681e, 0x08d8, 0x0006, - 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, - 0x2061, 0x19e8, 0x6020, 0x8000, 0x6022, 0x6008, 0x9005, 0x0148, - 0x9080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, - 0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, - 0x2061, 0x19e8, 0x6034, 0x9005, 0x0130, 0x9080, 0x0003, 0x2102, - 0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x00ce, 0x0005, 0x00f6, - 0x00e6, 0x00d6, 0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, 0x0056, - 0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x19e8, - 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x95f3, - 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x95ee, 0x87ff, 0x0120, - 0x6054, 0x9106, 0x1904, 0x95ee, 0x703c, 0x9c06, 0x1178, 0x0036, - 0x2019, 0x0001, 0x080c, 0xaa49, 0x7033, 0x0000, 0x9006, 0x703e, - 0x7042, 0x7046, 0x704a, 0x003e, 0x2029, 0x0001, 0x7038, 0x9c36, - 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, - 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x080c, 0xd0d8, 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, - 0x15b8, 0x6004, 0x9086, 0x0040, 0x090c, 0xac1b, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xd3ce, - 0x080c, 0xef85, 0x080c, 0x6e9f, 0x007e, 0x003e, 0x001e, 0x080c, - 0xd2c3, 0x080c, 0xb306, 0x00ce, 0x0804, 0x958d, 0x2c78, 0x600c, - 0x2060, 0x0804, 0x958d, 0x85ff, 0x0120, 0x0036, 0x080c, 0x9bd3, - 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, 0x006e, - 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, - 0xef85, 0x080c, 0xebd4, 0x007e, 0x003e, 0x001e, 0x0890, 0x6020, - 0x9086, 0x0009, 0x1168, 0xa87b, 0x0006, 0x0016, 0x0036, 0x0076, - 0x080c, 0x6e9f, 0x080c, 0xb2d3, 0x007e, 0x003e, 0x001e, 0x0818, - 0x6020, 0x9086, 0x000a, 0x0904, 0x95d8, 0x0804, 0x95d1, 0x0006, - 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091, - 0x8000, 0x2079, 0x19e8, 0x7838, 0x9065, 0x0904, 0x9684, 0x600c, - 0x0006, 0x600f, 0x0000, 0x783c, 0x9c06, 0x1168, 0x0036, 0x2019, - 0x0001, 0x080c, 0xaa49, 0x7833, 0x0000, 0x901e, 0x7b3e, 0x7b42, - 0x7b46, 0x7b4a, 0x003e, 0x080c, 0xd0d8, 0x0548, 0x6014, 0x2048, - 0x6020, 0x9086, 0x0003, 0x1590, 0x3e08, 0x918e, 0x0002, 0x1188, - 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x0140, 0x6040, 0x9005, 0x11a8, 0x2001, 0x1988, 0x2004, 0x6042, - 0x0080, 0x6004, 0x9086, 0x0040, 0x090c, 0xac1b, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6e92, 0x080c, 0xd2c3, 0x080c, - 0xb306, 0x000e, 0x0804, 0x963c, 0x7e3a, 0x7e36, 0x012e, 0x00fe, - 0x00de, 0x00ce, 0x009e, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1118, 0x080c, 0xebd4, 0x0c50, 0x6020, 0x9086, 0x0009, - 0x1130, 0xab7a, 0x080c, 0x6e9f, 0x080c, 0xb2d3, 0x0c10, 0x6020, - 0x9086, 0x000a, 0x09a8, 0x0868, 0x0016, 0x0026, 0x0086, 0x9046, - 0x0099, 0x080c, 0x978f, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6, - 0x0126, 0x2079, 0x19e8, 0x2091, 0x8000, 0x080c, 0x9826, 0x080c, - 0x98b6, 0x012e, 0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x00e6, - 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, - 0x2071, 0x19e8, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9754, - 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x974f, 0x88ff, 0x0120, - 0x6054, 0x9106, 0x1904, 0x974f, 0x7024, 0x9c06, 0x1568, 0x2069, - 0x0100, 0x6820, 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x88c3, - 0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7027, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, - 0x0009, 0x630a, 0x0804, 0x974f, 0x7014, 0x9c36, 0x1110, 0x660c, - 0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, - 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2048, - 0x080c, 0xd0d8, 0x01e8, 0x6020, 0x9086, 0x0003, 0x1580, 0x080c, - 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0098, 0xa867, 0x0103, 0xab7a, - 0xa877, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0xd3ce, 0x080c, - 0xef85, 0x080c, 0x6e9f, 0x008e, 0x003e, 0x001e, 0x080c, 0xd2c3, - 0x080c, 0xb306, 0x080c, 0xaaf1, 0x00ce, 0x0804, 0x96cd, 0x2c78, - 0x600c, 0x2060, 0x0804, 0x96cd, 0x012e, 0x000e, 0x001e, 0x006e, - 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, 0x00be, 0x0005, 0x6020, - 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xef85, - 0x080c, 0xebd4, 0x008e, 0x003e, 0x001e, 0x08d0, 0x080c, 0xbcb6, - 0x6020, 0x9086, 0x0002, 0x1160, 0x6004, 0x0006, 0x9086, 0x0085, - 0x000e, 0x0904, 0x9735, 0x9086, 0x008b, 0x0904, 0x9735, 0x0840, - 0x6020, 0x9086, 0x0005, 0x1920, 0x6004, 0x0006, 0x9086, 0x0085, - 0x000e, 0x09c8, 0x9086, 0x008b, 0x09b0, 0x0804, 0x9748, 0x00b6, - 0x00a6, 0x0096, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x9280, - 0x1000, 0x2004, 0x905d, 0x0904, 0x981f, 0x00f6, 0x00e6, 0x00d6, - 0x0066, 0x2071, 0x19e8, 0xbe54, 0x7018, 0x9b06, 0x1108, 0x761a, - 0x701c, 0x9b06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, - 0x761e, 0xb858, 0x904d, 0x0108, 0xae56, 0x96d5, 0x0000, 0x0110, - 0x2900, 0xb05a, 0xb857, 0x0000, 0xb85b, 0x0000, 0xb800, 0xc0d4, - 0xc0dc, 0xb802, 0x080c, 0x664c, 0x0904, 0x981b, 0x7624, 0x86ff, - 0x0904, 0x980a, 0x9680, 0x0005, 0x2004, 0x9906, 0x15d8, 0x00d6, - 0x2069, 0x0100, 0x68c0, 0x9005, 0x0560, 0x080c, 0x88c3, 0x080c, - 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7027, 0x0000, 0x0036, - 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0xb83c, - 0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x080c, 0xb306, 0x00ce, - 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, - 0x0804, 0x97c2, 0x89ff, 0x0158, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x080c, 0xd3ce, 0x080c, 0xef85, 0x080c, 0x6e9f, 0x080c, - 0xaaf1, 0x0804, 0x97c2, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, - 0x000e, 0x00ce, 0x009e, 0x00ae, 0x00be, 0x0005, 0x0096, 0x0006, - 0x0066, 0x00c6, 0x00d6, 0x9036, 0x7814, 0x9065, 0x0904, 0x9889, - 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0x9c06, 0x1580, 0x2069, - 0x0100, 0x6820, 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x88c3, - 0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7827, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0040, 0x080c, - 0x6a3b, 0x1520, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00f8, 0x6014, - 0x2048, 0x080c, 0xd0d6, 0x01b0, 0x6020, 0x9086, 0x0003, 0x1508, - 0x080c, 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0060, 0x080c, 0x6a3b, - 0x1168, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6e9f, - 0x080c, 0xd2c3, 0x080c, 0xb306, 0x080c, 0xaaf1, 0x000e, 0x0804, - 0x982d, 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x009e, - 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xebd4, 0x0c50, - 0x080c, 0xbcb6, 0x6020, 0x9086, 0x0002, 0x1150, 0x6004, 0x0006, - 0x9086, 0x0085, 0x000e, 0x0990, 0x9086, 0x008b, 0x0978, 0x08d0, - 0x6020, 0x9086, 0x0005, 0x19b0, 0x6004, 0x0006, 0x9086, 0x0085, - 0x000e, 0x0d18, 0x9086, 0x008b, 0x0d00, 0x0860, 0x0006, 0x0066, - 0x0096, 0x00b6, 0x00c6, 0x00d6, 0x7818, 0x905d, 0x0904, 0x9936, - 0xb854, 0x0006, 0x9006, 0xb856, 0xb85a, 0xb800, 0xc0d4, 0xc0dc, - 0xb802, 0x080c, 0x664c, 0x0904, 0x9933, 0x7e24, 0x86ff, 0x0904, - 0x9926, 0x9680, 0x0005, 0x2004, 0x9906, 0x1904, 0x9926, 0x00d6, - 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0x991d, 0x080c, 0x88c3, - 0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7827, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, - 0x3e08, 0x918e, 0x0002, 0x1168, 0xb800, 0xd0bc, 0x0150, 0x9680, - 0x0010, 0x200c, 0x81ff, 0x1518, 0x2009, 0x1988, 0x210c, 0x2102, - 0x00f0, 0xb83c, 0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x600f, - 0x0000, 0x080c, 0xb306, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, - 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x98c9, 0x89ff, 0x0138, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x080c, - 0xaaf1, 0x0804, 0x98c9, 0x000e, 0x0804, 0x98bd, 0x781e, 0x781a, - 0x00de, 0x00ce, 0x00be, 0x009e, 0x006e, 0x000e, 0x0005, 0x00e6, - 0x00d6, 0x0096, 0x0066, 0xb800, 0xd0dc, 0x01a0, 0xb84c, 0x904d, - 0x0188, 0xa878, 0x9606, 0x1170, 0x2071, 0x19e8, 0x7024, 0x9035, - 0x0148, 0x9080, 0x0005, 0x2004, 0x9906, 0x1120, 0xb800, 0xc0dc, - 0xb802, 0x0029, 0x006e, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00f6, - 0x2079, 0x0100, 0x78c0, 0x9005, 0x1138, 0x00c6, 0x2660, 0x6003, - 0x0009, 0x630a, 0x00ce, 0x04b8, 0x080c, 0xa6e9, 0x78c3, 0x0000, - 0x080c, 0xac1b, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d39, 0x9006, - 0x080c, 0x2d39, 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, - 0x0001, 0x080c, 0xac1b, 0x003e, 0x080c, 0x664c, 0x00c6, 0xb83c, - 0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x080c, 0xb2d3, 0x00ce, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd3ce, 0x080c, - 0x6e9f, 0x080c, 0xaaf1, 0x00fe, 0x0005, 0x00b6, 0x00e6, 0x00c6, - 0x2011, 0x0101, 0x2204, 0xc0c4, 0x2012, 0x2001, 0x180c, 0x2014, - 0xc2e4, 0x2202, 0x2071, 0x19e8, 0x7004, 0x9084, 0x0007, 0x0002, - 0x99c2, 0x99c6, 0x99e4, 0x9a0d, 0x9a4b, 0x99c2, 0x99dd, 0x99c0, - 0x080c, 0x0dc5, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x7024, 0x9065, - 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0x9015, 0x0158, 0x7216, - 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee, - 0x00be, 0x0005, 0x7216, 0x7212, 0x0ca8, 0x7007, 0x0000, 0x7027, - 0x0000, 0x7020, 0x9005, 0x0070, 0x6010, 0x2058, 0x080c, 0x664c, - 0xb800, 0xc0dc, 0xb802, 0x7007, 0x0000, 0x7027, 0x0000, 0x7020, - 0x8001, 0x7022, 0x1148, 0x2001, 0x180c, 0x2014, 0xd2ec, 0x1180, - 0x00ce, 0x00ee, 0x00be, 0x0005, 0xb854, 0x9015, 0x0120, 0x721e, - 0x080c, 0x9ab1, 0x0ca8, 0x7218, 0x721e, 0x080c, 0x9ab1, 0x0c80, - 0xc2ec, 0x2202, 0x080c, 0x9bd3, 0x0c58, 0x7024, 0x9065, 0x05b8, - 0x700c, 0x9c06, 0x1160, 0x080c, 0xaaf1, 0x600c, 0x9015, 0x0120, - 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014, - 0x9c06, 0x1160, 0x080c, 0xaaf1, 0x600c, 0x9015, 0x0120, 0x7216, - 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x6020, 0x9086, - 0x0003, 0x1198, 0x6010, 0x2058, 0x080c, 0x664c, 0xb800, 0xc0dc, - 0xb802, 0x080c, 0xaaf1, 0x701c, 0x9065, 0x0138, 0xb854, 0x9015, - 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, - 0x00ee, 0x00be, 0x0005, 0x7024, 0x9065, 0x0140, 0x080c, 0xaaf1, - 0x600c, 0x9015, 0x0158, 0x720e, 0x600f, 0x0000, 0x080c, 0xac1b, - 0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x720e, 0x720a, - 0x0ca8, 0x00d6, 0x2069, 0x19e8, 0x6830, 0x9084, 0x0003, 0x0002, - 0x9a6e, 0x9a70, 0x9a94, 0x9a6c, 0x080c, 0x0dc5, 0x00de, 0x0005, - 0x00c6, 0x6840, 0x9086, 0x0001, 0x01b8, 0x683c, 0x9065, 0x0130, - 0x600c, 0x9015, 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, - 0x683f, 0x0000, 0x2011, 0x1a07, 0x2013, 0x0000, 0x00ce, 0x00de, - 0x0005, 0x683a, 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0x9065, - 0x0d68, 0x6003, 0x0003, 0x0c50, 0x00c6, 0x9006, 0x6842, 0x6846, - 0x684a, 0x683c, 0x9065, 0x0160, 0x600c, 0x9015, 0x0130, 0x6a3a, - 0x600f, 0x0000, 0x683f, 0x0000, 0x0018, 0x683e, 0x683a, 0x6836, - 0x00ce, 0x00de, 0x0005, 0x2001, 0x180c, 0x200c, 0xc1e5, 0x2102, - 0x0005, 0x2001, 0x180c, 0x200c, 0xd1ec, 0x0120, 0xc1ec, 0x2102, - 0x080c, 0x9bd3, 0x2001, 0x19f4, 0x2004, 0x9086, 0x0001, 0x0d58, - 0x00d6, 0x2069, 0x19e8, 0x6804, 0x9084, 0x0007, 0x0006, 0x9005, - 0x11c8, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1198, 0x2001, - 0x197c, 0x2004, 0x9086, 0xaaaa, 0x0168, 0x2001, 0x188b, 0x2004, - 0xd08c, 0x1118, 0xd084, 0x1118, 0x0028, 0x080c, 0x9bd3, 0x000e, - 0x00de, 0x0005, 0x000e, 0x0002, 0x9aee, 0x9ba7, 0x9ba7, 0x9ba7, - 0x9ba7, 0x9ba9, 0x9ba7, 0x9aec, 0x080c, 0x0dc5, 0x6820, 0x9005, - 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, 0x01f0, 0x6104, - 0x918e, 0x0040, 0x1180, 0x2009, 0x1837, 0x210c, 0x918c, 0x0028, - 0x1150, 0x080c, 0x7637, 0x0138, 0x0006, 0x2009, 0x188b, 0x2104, - 0xc095, 0x200a, 0x000e, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, - 0x080c, 0x9c7c, 0x00ce, 0x00de, 0x0005, 0x6814, 0x9065, 0x0150, - 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x9c7c, 0x00ce, - 0x00de, 0x0005, 0x00b6, 0x00e6, 0x6a1c, 0x92dd, 0x0000, 0x0904, - 0x9b91, 0xb84c, 0x900d, 0x0118, 0xb888, 0x9005, 0x01a0, 0xb854, - 0x905d, 0x0120, 0x920e, 0x0904, 0x9b91, 0x0028, 0x6818, 0x920e, - 0x0904, 0x9b91, 0x2058, 0xb84c, 0x900d, 0x0d88, 0xb888, 0x9005, - 0x1d70, 0x2b00, 0x681e, 0xbb3c, 0xb838, 0x9302, 0x1e40, 0x080c, - 0xb2aa, 0x0904, 0x9b91, 0x8318, 0xbb3e, 0x6116, 0x2b10, 0x6212, - 0x0096, 0x2148, 0xa880, 0x9084, 0x00ff, 0x605e, 0xa883, 0x0000, - 0xa884, 0x009e, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, - 0x801b, 0x831b, 0x9318, 0x631a, 0x6114, 0x0096, 0x2148, 0xa964, - 0x009e, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0538, 0x00f6, 0x2c78, - 0x2061, 0x0100, 0xbac0, 0x629a, 0x2069, 0x0200, 0x2071, 0x0240, - 0x080c, 0xa219, 0x2069, 0x19e8, 0xbb00, 0xc3dd, 0xbb02, 0x6807, - 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x7823, 0x0003, 0x7803, - 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00be, 0x00ce, 0x00de, - 0x0005, 0x00ee, 0x00be, 0x00ce, 0x0cd0, 0x6807, 0x0006, 0x2c18, - 0x6b26, 0x6820, 0x8001, 0x6822, 0x682b, 0x0000, 0x080c, 0x664c, - 0x080c, 0xb0ea, 0x00ee, 0x00be, 0x00ce, 0x00de, 0x0005, 0x00de, - 0x0005, 0x00c6, 0x680c, 0x9065, 0x01d8, 0x6104, 0x918e, 0x0040, - 0x1180, 0x2009, 0x1837, 0x210c, 0x918c, 0x0028, 0x1150, 0x080c, - 0x7637, 0x0138, 0x0006, 0x2009, 0x188b, 0x2104, 0xc095, 0x200a, - 0x000e, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x9c7c, - 0x00ce, 0x00de, 0x0005, 0x2001, 0x180c, 0x2014, 0xc2ed, 0x2202, - 0x00de, 0x00fe, 0x0005, 0x00f6, 0x00d6, 0x2069, 0x19e8, 0x6830, - 0x9086, 0x0000, 0x1570, 0x2001, 0x180c, 0x2014, 0xd2e4, 0x0130, - 0xc2e4, 0x2202, 0x080c, 0x9ac0, 0x2069, 0x19e8, 0x2001, 0x180c, - 0x200c, 0xd1c4, 0x1508, 0x6838, 0x907d, 0x01d8, 0x6a04, 0x9296, - 0x0000, 0x1904, 0x9c70, 0x7920, 0x918e, 0x0009, 0x0568, 0x6833, - 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, - 0x2091, 0x2400, 0x002e, 0x080c, 0x1c79, 0x1158, 0x012e, 0x080c, - 0xa546, 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, 0x080c, 0x76e4, - 0x08d0, 0x012e, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0x9015, - 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, - 0x0c40, 0x683a, 0x6836, 0x0cc0, 0x7908, 0xd1fc, 0x1198, 0x6833, - 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6, - 0x2091, 0x2400, 0x002e, 0x080c, 0x1c79, 0x19d8, 0x012e, 0x080c, - 0xa4c7, 0x0878, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1188, - 0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa, 0x0158, 0x2001, 0x19e9, - 0x2004, 0x9005, 0x11f0, 0x2001, 0x188b, 0x200c, 0xc185, 0xc18c, - 0x2102, 0x2f00, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, - 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1c79, - 0x1904, 0x9c11, 0x012e, 0x6a3c, 0x2278, 0x080c, 0xa451, 0x0804, - 0x9c09, 0x2011, 0x188b, 0x2204, 0xc08d, 0x2012, 0x0804, 0x9c09, - 0x6a04, 0x9296, 0x0006, 0x1904, 0x9bcb, 0x6a30, 0x9296, 0x0000, - 0x0904, 0x9bf3, 0x0804, 0x9bcb, 0x6020, 0x9084, 0x000f, 0x000b, - 0x0005, 0x9c90, 0x9c95, 0xa149, 0xa1e2, 0x9c95, 0xa149, 0xa1e2, - 0x9c90, 0x9c95, 0x9c90, 0x9c90, 0x9c90, 0x9c90, 0x9c90, 0x9c90, - 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0005, 0x00b6, 0x0156, 0x0136, - 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, - 0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0dc5, - 0x6110, 0x2158, 0xb9c0, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a, - 0x0040, 0x1a04, 0x9d01, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x9eaa, - 0x9ee5, 0x9f0e, 0x9fd8, 0x9ffa, 0xa000, 0xa00d, 0xa015, 0xa021, - 0xa027, 0xa038, 0xa027, 0xa090, 0xa015, 0xa09c, 0xa0a2, 0xa021, - 0xa0a2, 0xa0ae, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff, - 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0xa900, 0xa923, 0xa934, - 0xa954, 0xa986, 0xa00d, 0x9cff, 0xa00d, 0xa027, 0x9cff, 0x9f0e, - 0x9fd8, 0x9cff, 0xad12, 0xa027, 0x9cff, 0xad2e, 0xa027, 0x9cff, - 0xa021, 0x9ea4, 0x9d22, 0x9cff, 0xad4a, 0xadb7, 0xae92, 0x9cff, - 0xae9f, 0xa00a, 0xaeca, 0x9cff, 0xa990, 0xaef7, 0x9cff, 0x080c, - 0x0dc5, 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, - 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0xaf92, 0xb044, - 0x9d20, 0x9d5a, 0x9e06, 0x9e11, 0x9d20, 0xa00d, 0x9d20, 0x9e6b, - 0x9e77, 0x9d75, 0x9d20, 0x9d90, 0x9dc4, 0xb1b1, 0xb1f6, 0xa027, - 0x080c, 0x0dc5, 0x00d6, 0x0096, 0x080c, 0xa0c1, 0x0026, 0x0036, - 0x7814, 0x2048, 0xa958, 0xd1cc, 0x1138, 0x2009, 0x2414, 0x2011, - 0x0018, 0x2019, 0x0018, 0x0030, 0x2009, 0x2410, 0x2011, 0x0014, - 0x2019, 0x0014, 0x7102, 0x7206, 0x700b, 0x0800, 0xa83c, 0x700e, - 0xa850, 0x7022, 0xa854, 0x7026, 0x63c2, 0x080c, 0xa6bd, 0x003e, - 0x002e, 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, - 0x00be, 0x080c, 0xb23d, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, - 0x0001, 0x0005, 0x00d6, 0x0096, 0x080c, 0xa0c1, 0x7003, 0x0500, - 0x7814, 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, - 0xa880, 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, - 0x080c, 0xa6bd, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, - 0xa0c1, 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, - 0x700e, 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, - 0x701e, 0x60c3, 0x0010, 0x080c, 0xa6bd, 0x009e, 0x00de, 0x0005, - 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0xa0c1, 0x20e9, - 0x0000, 0x2001, 0x19a4, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, - 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x001b, 0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x2001, 0x0001, - 0x080c, 0x23ee, 0x080c, 0xde7c, 0x9006, 0x080c, 0x23ee, 0x001e, - 0xa804, 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0xa6bd, - 0x012e, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, - 0x8000, 0x080c, 0xa10c, 0x20e9, 0x0000, 0x2001, 0x19a4, 0x2003, - 0x0000, 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, - 0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x001b, 0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x080c, 0xde7c, - 0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, - 0x2048, 0x080c, 0x0fc0, 0x080c, 0xa6bd, 0x012e, 0x009e, 0x00de, - 0x0005, 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, - 0x0004, 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0xa0c1, - 0x7003, 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, - 0xa6bd, 0x00d6, 0x00e6, 0x080c, 0xa10c, 0x7814, 0x9084, 0xff00, - 0x2073, 0x0200, 0x8e70, 0x8e70, 0x9096, 0xdf00, 0x0138, 0x9096, - 0xe000, 0x0120, 0x2073, 0x0010, 0x8e70, 0x0030, 0x9095, 0x0010, - 0x2272, 0x8e70, 0x2073, 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9, - 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9e31, 0x2069, 0x1801, - 0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9e3a, 0x9096, - 0xdf00, 0x0130, 0x9096, 0xe000, 0x0118, 0x60c3, 0x0018, 0x00f0, - 0x2069, 0x19b4, 0x9086, 0xdf00, 0x0110, 0x2069, 0x19ce, 0x20a9, - 0x001a, 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, - 0x8000, 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, - 0x8d68, 0x8e70, 0x1f04, 0x9e51, 0x60c3, 0x004c, 0x080c, 0xa6bd, - 0x00ee, 0x00de, 0x0005, 0x080c, 0xa0c1, 0x7003, 0x6300, 0x7007, - 0x0028, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x00d6, - 0x0026, 0x0016, 0x080c, 0xa10c, 0x7003, 0x0200, 0x7814, 0x700e, - 0x00e6, 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2069, - 0x1924, 0x6810, 0xd084, 0x1148, 0x2073, 0x0500, 0x8e70, 0x2073, - 0x0000, 0x8e70, 0x8108, 0x9290, 0x0004, 0x2073, 0x0800, 0x8e70, - 0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, 0xa6bd, - 0x001e, 0x002e, 0x00de, 0x0005, 0x2001, 0x1818, 0x2004, 0x609a, - 0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003, 0x5200, 0x2069, 0x1847, - 0x6804, 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x28a6, 0x710e, - 0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, - 0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, - 0x20a1, 0x0254, 0x4003, 0x080c, 0xb23d, 0x1120, 0xb8a0, 0x9082, - 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, 0x7032, 0x2001, 0x1820, - 0x2004, 0x7036, 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, - 0x7036, 0x60c3, 0x001c, 0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003, - 0x0500, 0x080c, 0xb23d, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, - 0x2001, 0x181f, 0x2004, 0x700a, 0x2001, 0x1820, 0x2004, 0x700e, - 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, - 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, - 0x0250, 0x4003, 0x60c3, 0x0010, 0x0804, 0xa6bd, 0x080c, 0xa0c1, - 0x9006, 0x080c, 0x6a6d, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2011, - 0x0240, 0x2013, 0x22ff, 0x2011, 0x0241, 0x2013, 0xfffe, 0x7003, - 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0058, 0x7814, 0x0096, 0x904d, - 0x0120, 0x9006, 0xa89a, 0xa8a6, 0xa8aa, 0x009e, 0x7003, 0x0300, - 0xb8a0, 0x9086, 0x007e, 0x1904, 0x9f98, 0x00d6, 0x2069, 0x196c, - 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0188, 0x6800, 0x700a, 0x6808, - 0x9084, 0x2000, 0x7012, 0x080c, 0xb254, 0x680c, 0x7016, 0x701f, - 0x2710, 0x6818, 0x7022, 0x681c, 0x7026, 0x0428, 0x6800, 0x700a, - 0x6804, 0x700e, 0x2009, 0x180d, 0x210c, 0xd18c, 0x0110, 0x2001, - 0x0002, 0x00f6, 0x2079, 0x0100, 0x080c, 0x7637, 0x1128, 0x78e3, - 0x0000, 0x080c, 0x28e7, 0x78e2, 0x00fe, 0x6808, 0x080c, 0x7637, - 0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x080c, - 0xb254, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001, - 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, - 0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c, - 0xaf79, 0x2069, 0x1974, 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002, - 0x080c, 0x57d9, 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, 0x04e0, - 0x2001, 0x1837, 0x2004, 0xd0a4, 0x01a8, 0x0016, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x2009, 0x0002, 0x1118, 0x2001, 0x196d, 0x200c, - 0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x28e7, - 0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, 0x196c, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, - 0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, - 0x20a1, 0x025a, 0x4003, 0x080c, 0xaf79, 0x20a1, 0x024e, 0x20a9, - 0x0008, 0x2099, 0x1974, 0x4003, 0x60c3, 0x0074, 0x0804, 0xa6bd, - 0x080c, 0xa0c1, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, - 0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, 0x1847, 0x7904, 0x00fe, - 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, - 0x9085, 0x0002, 0x00d6, 0x0804, 0xa071, 0x7026, 0x60c3, 0x0014, - 0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003, 0x5000, 0x0804, 0x9f30, - 0x080c, 0xa0c1, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, - 0x0804, 0xa6bd, 0x080c, 0xa103, 0x0010, 0x080c, 0xa10c, 0x7003, - 0x0200, 0x60c3, 0x0004, 0x0804, 0xa6bd, 0x080c, 0xa10c, 0x7003, - 0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, - 0xa6bd, 0x080c, 0xa10c, 0x7003, 0x0200, 0x0804, 0x9f30, 0x080c, - 0xa10c, 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, 0x0010, - 0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, - 0x00d6, 0x080c, 0xa10c, 0x7003, 0x0210, 0x7007, 0x0014, 0x700b, - 0x0800, 0xb894, 0x9086, 0x0014, 0x1198, 0xb99c, 0x9184, 0x0030, - 0x0190, 0xb998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, - 0x2100, 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, - 0x700f, 0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1847, - 0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, - 0x9085, 0x0010, 0x2009, 0x1869, 0x210c, 0xd184, 0x1110, 0x9085, - 0x0002, 0x0026, 0x2009, 0x1867, 0x210c, 0xd1e4, 0x0150, 0xc0c5, - 0xbacc, 0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, - 0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, - 0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0xa6bd, - 0x080c, 0xa10c, 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, - 0x60c3, 0x0014, 0x0804, 0xa6bd, 0x080c, 0xa10c, 0x7003, 0x0200, - 0x0804, 0x9eae, 0x080c, 0xa10c, 0x7003, 0x0100, 0x700b, 0x0003, - 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x080c, 0xa10c, - 0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0xa6bd, - 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, - 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, - 0x0100, 0x080c, 0xaf8e, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, - 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x9485, 0x0029, - 0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0xa6ab, 0x721a, 0x9f95, - 0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, - 0x0026, 0x080c, 0xaf8e, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6, - 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x00de, 0x7013, - 0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, 0xfc02, - 0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, - 0x3300, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, - 0x2019, 0x2300, 0x2021, 0x0100, 0x080c, 0xaf8e, 0xb810, 0x9305, - 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0xb810, 0x9005, 0x1140, - 0xb814, 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, - 0x687c, 0x700a, 0x6880, 0x700e, 0x0000, 0x9485, 0x0098, 0x7012, - 0x004e, 0x003e, 0x00de, 0x080c, 0xa6ab, 0x721a, 0x7a08, 0x7222, - 0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0xa6ab, - 0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, - 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, - 0x2071, 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dc5, 0x908a, - 0x0092, 0x1a0c, 0x0dc5, 0x6110, 0x2158, 0xb9c0, 0x2c78, 0x2061, - 0x0100, 0x619a, 0x9082, 0x0085, 0x0033, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x00be, 0x0005, 0xa17a, 0xa189, 0xa194, 0xa178, 0xa178, - 0xa178, 0xa17a, 0xa178, 0xa178, 0xa178, 0xa178, 0xa178, 0xa178, - 0x080c, 0x0dc5, 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x2bce, - 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804, - 0xa6bd, 0x0431, 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, - 0x60c3, 0x000c, 0x0804, 0xa6bd, 0x04a1, 0x7003, 0x0003, 0x7007, - 0x0300, 0x60c3, 0x0004, 0x0804, 0xa6bd, 0x0026, 0x080c, 0xaf8e, - 0xb810, 0x9085, 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, - 0x687c, 0x700a, 0x6880, 0x700e, 0x7013, 0x0009, 0x0804, 0xa0dc, - 0x0026, 0x080c, 0xaf8e, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814, - 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, - 0x0099, 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804, - 0xa13e, 0x0026, 0x080c, 0xaf8e, 0xb810, 0x9085, 0x8500, 0x7002, - 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, - 0x2001, 0x0099, 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, - 0x0804, 0xa13e, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, - 0x2069, 0x0200, 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, - 0x0dc5, 0x908a, 0x0054, 0x1a0c, 0x0dc5, 0x7910, 0x2158, 0xb9c0, - 0x2061, 0x0100, 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x00be, 0x0005, 0xa219, 0xa2e0, 0xa2b3, 0xa402, - 0xa217, 0xa217, 0xa217, 0xa217, 0xa217, 0xa217, 0xa217, 0xaad8, - 0xaadd, 0xaae2, 0xaae7, 0xa217, 0xaed6, 0xa217, 0xaad3, 0x080c, - 0x0dc5, 0x0096, 0x780b, 0xffff, 0x080c, 0xa284, 0x7914, 0x2148, - 0xa978, 0x7956, 0xae64, 0x96b4, 0x00ff, 0x9686, 0x0008, 0x1148, - 0xa8b4, 0x7032, 0xa8b8, 0x7036, 0xa8bc, 0x703a, 0xa8c0, 0x703e, - 0x0008, 0x7132, 0xa97c, 0x9184, 0x000f, 0x1118, 0x2001, 0x0005, - 0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0x9084, 0x0006, - 0x8004, 0x2010, 0x785c, 0x9084, 0x00ff, 0x8007, 0x9205, 0x7042, - 0xd1ac, 0x0158, 0x7047, 0x0002, 0x9686, 0x0008, 0x1118, 0x080c, - 0x18f7, 0x0010, 0x080c, 0x1768, 0x0050, 0xd1b4, 0x0118, 0x7047, - 0x0001, 0x0028, 0x7047, 0x0000, 0x9016, 0x2230, 0x0010, 0xaab0, - 0xaeac, 0x726a, 0x766e, 0x20a9, 0x0008, 0x20e9, 0x0000, 0xa860, - 0x20e0, 0xa85c, 0x9080, 0x0023, 0x2098, 0x20a1, 0x0252, 0x2069, - 0x0200, 0x6813, 0x0018, 0x4003, 0x6813, 0x0008, 0x60c3, 0x0020, - 0x6017, 0x0009, 0x2001, 0x1a04, 0x2003, 0x07d0, 0x2001, 0x1a03, - 0x2003, 0x0009, 0x009e, 0x0005, 0x6813, 0x0008, 0xba8c, 0x8210, - 0xb8cc, 0xd084, 0x0180, 0x2001, 0x1ad0, 0x200c, 0x8108, 0x2102, - 0x2001, 0x1acf, 0x201c, 0x1218, 0x8318, 0x2302, 0x0ea0, 0x794a, - 0x712e, 0x7b46, 0x732a, 0x9294, 0x00ff, 0xba8e, 0x8217, 0x721a, - 0xba10, 0x9295, 0x0600, 0x7202, 0xba14, 0x7206, 0x2069, 0x1800, - 0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, 0x0829, 0x2f10, 0x7222, - 0x7027, 0xffff, 0x0005, 0x00d6, 0x0096, 0x0081, 0x7814, 0x2048, - 0xa890, 0x7002, 0xa88c, 0x7006, 0xa8b0, 0x700a, 0xa8ac, 0x700e, - 0x60c3, 0x000c, 0x009e, 0x00de, 0x0804, 0xa6bd, 0x6813, 0x0008, - 0xb810, 0x9085, 0x0500, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, - 0x687c, 0x700a, 0x6880, 0x700e, 0x7013, 0x0889, 0x080c, 0xa6ab, - 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x0005, - 0x00d6, 0x0096, 0x080c, 0xa3e0, 0x7814, 0x2048, 0x080c, 0xd0d6, - 0x1130, 0x7814, 0x9084, 0x0700, 0x8007, 0x0033, 0x0010, 0x9006, - 0x001b, 0x009e, 0x00de, 0x0005, 0xa2fe, 0xa367, 0xa377, 0xa39d, - 0xa3a9, 0xa3ba, 0xa3c2, 0xa2fc, 0x080c, 0x0dc5, 0x0016, 0x0036, - 0xa97c, 0x918c, 0x0003, 0x0118, 0x9186, 0x0003, 0x1198, 0xaba8, - 0x7824, 0xd0cc, 0x1168, 0x7316, 0xa898, 0x701a, 0xa894, 0x701e, - 0x003e, 0x001e, 0x2001, 0x19b2, 0x2004, 0x60c2, 0x0804, 0xa6bd, - 0xc3e5, 0x0c88, 0x9186, 0x0001, 0x190c, 0x0dc5, 0xaba8, 0x7824, - 0xd0cc, 0x1904, 0xa364, 0x7316, 0xa898, 0x701a, 0xa894, 0x701e, - 0xa8a4, 0x7026, 0xa8ac, 0x702e, 0x2009, 0x0018, 0x9384, 0x0300, - 0x0570, 0xd3c4, 0x0110, 0xa8ac, 0x9108, 0xd3cc, 0x0110, 0xa8a4, - 0x9108, 0x6810, 0x9085, 0x0010, 0x6812, 0x2011, 0x0258, 0x20e9, - 0x0000, 0x22a0, 0x0156, 0x20a9, 0x0008, 0xa860, 0x20e0, 0xa85c, - 0x9080, 0x002c, 0x2098, 0x4003, 0x6810, 0x8000, 0x6812, 0x2011, - 0x0240, 0x22a0, 0x20a9, 0x0005, 0x4003, 0x6810, 0xc0a4, 0x6812, - 0x015e, 0x9184, 0x0003, 0x0118, 0x2019, 0x0245, 0x201a, 0x61c2, - 0x003e, 0x001e, 0x0804, 0xa6bd, 0xc3e5, 0x0804, 0xa323, 0x2011, - 0x0008, 0x2001, 0x180f, 0x2004, 0xd0a4, 0x0110, 0x2011, 0x0028, - 0x7824, 0xd0cc, 0x1110, 0x7216, 0x0470, 0x0ce8, 0xc2e5, 0x2011, - 0x0302, 0x0016, 0x782c, 0x701a, 0x7930, 0x711e, 0x9105, 0x0108, - 0xc2dd, 0x001e, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x7027, - 0x0012, 0x702f, 0x0008, 0x7043, 0x7000, 0x7047, 0x0500, 0x704f, - 0x000a, 0x2069, 0x0200, 0x6813, 0x0009, 0x2071, 0x0240, 0x700b, - 0x2500, 0x60c3, 0x0032, 0x0804, 0xa6bd, 0x2011, 0x0028, 0x7824, - 0xd0cc, 0x1128, 0x7216, 0x60c3, 0x0018, 0x0804, 0xa6bd, 0x0cd0, - 0xc2e5, 0x2011, 0x0100, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, - 0x702f, 0x0008, 0x7858, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x0020, - 0x0804, 0xa6bd, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0108, 0xc2e5, - 0x7216, 0x0c08, 0x0036, 0x7b14, 0x9384, 0xff00, 0x7816, 0x9384, - 0x00ff, 0x8001, 0x1138, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, - 0x003e, 0x0888, 0x0046, 0x2021, 0x0800, 0x0006, 0x7824, 0xd0cc, - 0x000e, 0x0108, 0xc4e5, 0x7416, 0x004e, 0x701e, 0x003e, 0x0818, - 0x00d6, 0x6813, 0x0008, 0xb810, 0x9085, 0x0700, 0x7002, 0xb814, - 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x7824, - 0xd0cc, 0x1168, 0x7013, 0x0898, 0x080c, 0xa6ab, 0x721a, 0x7a08, - 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x7013, - 0x0889, 0x0c90, 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, 0x0013, - 0x001e, 0x0005, 0xa412, 0xa412, 0xa414, 0xa412, 0xa412, 0xa412, - 0xa42e, 0xa412, 0x080c, 0x0dc5, 0x7914, 0x918c, 0x08ff, 0x918d, - 0xf600, 0x7916, 0x2009, 0x0003, 0x00b9, 0x2069, 0x1847, 0x6804, - 0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, 0x8007, 0x7032, 0x0010, - 0x7033, 0x3f00, 0x60c3, 0x0001, 0x0804, 0xa6bd, 0x2009, 0x0003, - 0x0019, 0x7033, 0x7f00, 0x0cb0, 0x0016, 0x080c, 0xaf8e, 0x001e, - 0xb810, 0x9085, 0x0100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, - 0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, - 0x7116, 0x080c, 0xa6ab, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, - 0x0005, 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, - 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, - 0x76dc, 0x96b4, 0x0028, 0x0110, 0x737c, 0x7480, 0x2500, 0x76dc, - 0x96b4, 0x0028, 0x0140, 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, - 0x636a, 0x646e, 0x0050, 0x2001, 0x00ff, 0x9085, 0x0400, 0x6062, - 0x6067, 0xffff, 0x606b, 0x0000, 0x616e, 0xb8b8, 0x6073, 0x0530, - 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, - 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, 0x2b00, 0x6082, 0x6087, - 0xffff, 0x7814, 0x0096, 0x2048, 0xa838, 0x608a, 0xa834, 0x608e, - 0xa848, 0x60c6, 0xa844, 0x60ca, 0x009e, 0xb86c, 0x60ce, 0x60ab, - 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x2001, 0x1837, 0x2004, - 0x9084, 0x0028, 0x0128, 0x609f, 0x0000, 0x2001, 0x0092, 0x0048, - 0x6028, 0xc0bd, 0x602a, 0x609f, 0x00ff, 0x6027, 0xffff, 0x2001, - 0x00b2, 0x6016, 0x2009, 0x07d0, 0x080c, 0x88c8, 0x003e, 0x004e, - 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, 0x00b6, - 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, - 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, 0xb8a0, 0x2028, - 0x76dc, 0xd6ac, 0x1168, 0x9582, 0x007e, 0x1250, 0x2500, 0x9094, - 0xff80, 0x1130, 0x9080, 0x33b6, 0x2015, 0x9294, 0x00ff, 0x0020, - 0xb910, 0xba14, 0x737c, 0x7480, 0x70dc, 0xd0ac, 0x1130, 0x9582, - 0x007e, 0x1218, 0x9584, 0xff80, 0x0138, 0x9185, 0x0400, 0x6062, - 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400, 0x6266, 0x606b, - 0x0000, 0x616e, 0xb8b8, 0x6072, 0x6077, 0x0000, 0xb864, 0xd0a4, - 0x0110, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, - 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, 0x2b00, 0x6082, - 0x6087, 0xffff, 0x7814, 0x0096, 0x2048, 0xa838, 0x608a, 0xa834, - 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, 0x009e, 0xb86c, 0x60ce, - 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbac0, 0x629e, - 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, 0x2009, 0x0092, - 0x6116, 0x2009, 0x07d0, 0x080c, 0x88c8, 0x003e, 0x004e, 0x005e, - 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, 0x00b6, 0x0096, - 0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, - 0x2071, 0x1800, 0x7810, 0x2058, 0xb8a0, 0x2028, 0xb910, 0xba14, - 0x737c, 0x7480, 0x7820, 0x90be, 0x0006, 0x0904, 0xa61a, 0x90be, - 0x000a, 0x1904, 0xa5d6, 0xb8c0, 0x609e, 0x7814, 0x2048, 0xa87c, - 0xd0fc, 0x0558, 0xaf90, 0x9784, 0xff00, 0x9105, 0x6062, 0x873f, - 0x9784, 0xff00, 0x0006, 0x7814, 0x2048, 0xa878, 0xc0fc, 0x9005, - 0x000e, 0x1160, 0xaf94, 0x87ff, 0x0198, 0x2039, 0x0098, 0x9705, - 0x6072, 0x7808, 0x6082, 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200, - 0x6062, 0x6073, 0x0129, 0x6077, 0x0000, 0xb8c0, 0x609e, 0x0050, - 0x2039, 0x0029, 0x9705, 0x6072, 0x0cc0, 0x9185, 0x0200, 0x6062, - 0x6073, 0x2029, 0xa87c, 0xd0fc, 0x0118, 0xaf94, 0x87ff, 0x1120, - 0x2f00, 0x6082, 0x7808, 0x6086, 0x6266, 0x636a, 0x646e, 0x6077, - 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, - 0x607f, 0x0000, 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, - 0xa844, 0x60ca, 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0x080c, 0xaf73, 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, - 0x0110, 0x2009, 0x1b58, 0x080c, 0x88c8, 0x003e, 0x004e, 0x005e, - 0x00ce, 0x00de, 0x00ee, 0x009e, 0x00be, 0x0005, 0x7804, 0x9086, - 0x0040, 0x0904, 0xa656, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, - 0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x60af, 0x95d5, 0x60d7, - 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, - 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7814, 0x2048, - 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, - 0xb86c, 0x60ce, 0xbac0, 0x629e, 0x080c, 0xaf73, 0x2009, 0x07d0, - 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c, - 0x88c8, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e, - 0x00be, 0x0005, 0x7814, 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, - 0x0002, 0x0904, 0xa672, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a, - 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, - 0x00ff, 0xb88e, 0x8007, 0x607a, 0x7838, 0x607e, 0x2f00, 0x6086, - 0x7808, 0x6082, 0xa890, 0x608a, 0xa88c, 0x608e, 0xa8b0, 0x60c6, - 0xa8ac, 0x60ca, 0xa8ac, 0x7930, 0x9108, 0x7932, 0xa8b0, 0x792c, - 0x9109, 0x792e, 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0xbac0, 0x629e, 0x080c, 0xaf50, 0x0804, 0xa606, 0xb8cc, 0xd084, - 0x0148, 0xb88c, 0x7814, 0x2048, 0xb88c, 0x784a, 0xa836, 0x2900, - 0xa83a, 0xb046, 0x9185, 0x0600, 0x6062, 0x6266, 0x636a, 0x646e, - 0x6073, 0x0829, 0x6077, 0x0000, 0x60af, 0x9575, 0x60d7, 0x0000, - 0x0804, 0xa5e9, 0x9185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, - 0x7824, 0xd0cc, 0x7826, 0x0118, 0x6073, 0x0889, 0x0010, 0x6073, - 0x0898, 0x6077, 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, - 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, - 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, - 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbac0, 0x629e, - 0x7824, 0xd0cc, 0x0120, 0x080c, 0xaf73, 0x0804, 0xa606, 0x080c, - 0xaf50, 0x0804, 0xa606, 0x7a10, 0x00b6, 0x2258, 0xba8c, 0x8210, - 0x9294, 0x00ff, 0xba8e, 0x00be, 0x8217, 0x0005, 0x00d6, 0x2069, - 0x19e8, 0x6843, 0x0001, 0x00de, 0x0005, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x00f1, 0x080c, 0x88ba, 0x0005, 0x0016, 0x2001, 0x180c, - 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, 0x0128, 0x0089, 0x080c, - 0x88ba, 0x001e, 0x0005, 0xc1e5, 0x2001, 0x180c, 0x2102, 0x2001, - 0x19e9, 0x2003, 0x0000, 0x2001, 0x19f1, 0x2003, 0x0000, 0x0c88, - 0x0006, 0x6014, 0x9084, 0x1804, 0x9085, 0x0009, 0x6016, 0x000e, - 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, 0x61a4, 0x60a7, - 0x95f5, 0x6014, 0x9084, 0x1804, 0x9085, 0x0008, 0x6016, 0x000e, - 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6, - 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, - 0x7637, 0x11c0, 0x2001, 0x1a04, 0x2004, 0x9005, 0x15d0, 0x080c, - 0x76e4, 0x1160, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, 0x6024, - 0xd084, 0x090c, 0x0dc5, 0x080c, 0x88ba, 0x0458, 0x00c6, 0x2061, - 0x19e8, 0x00c8, 0x6904, 0x9194, 0x4000, 0x0540, 0x0811, 0x080c, - 0x2d49, 0x00c6, 0x2061, 0x19e8, 0x6128, 0x9192, 0x0008, 0x1258, - 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x88ba, - 0x080c, 0xa6e0, 0x0070, 0x6124, 0x91e5, 0x0000, 0x0140, 0x080c, - 0xf094, 0x080c, 0x88c3, 0x2009, 0x0014, 0x080c, 0xb352, 0x00ce, - 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0x1a04, - 0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, 0x19e8, 0x6128, 0x9192, - 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x88ba, 0x080c, - 0x5fed, 0x2009, 0x1846, 0x2114, 0x8210, 0x220a, 0x0c10, 0x0096, - 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, 0x88d0, 0x2071, - 0x19e8, 0x713c, 0x81ff, 0x0904, 0xa7e9, 0x2061, 0x0100, 0x2069, - 0x0140, 0x080c, 0x7637, 0x11e0, 0x0036, 0x2019, 0x0002, 0x080c, - 0xaa49, 0x003e, 0x713c, 0x2160, 0x080c, 0xf094, 0x2009, 0x004a, - 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, - 0x2009, 0x004a, 0x080c, 0xb352, 0x080c, 0x76e4, 0x0804, 0xa7e9, - 0x080c, 0xa7f5, 0x0904, 0xa7e9, 0x6904, 0xd1f4, 0x0904, 0xa7f0, - 0x080c, 0x2d49, 0x00c6, 0x703c, 0x9065, 0x090c, 0x0dc5, 0x6020, - 0x00ce, 0x9086, 0x0006, 0x1528, 0x61c8, 0x60c4, 0x9105, 0x1508, - 0x2009, 0x180c, 0x2104, 0xd0d4, 0x01e0, 0x6214, 0x9294, 0x1800, - 0x1128, 0x6224, 0x9294, 0x0002, 0x1560, 0x0030, 0xc0d4, 0x200a, - 0xd0cc, 0x0110, 0x080c, 0x2c7b, 0x6014, 0x9084, 0xe7fd, 0x9085, - 0x0010, 0x6016, 0x703c, 0x2060, 0x2009, 0x0049, 0x080c, 0xb352, - 0x00c0, 0x0036, 0x2019, 0x0001, 0x080c, 0xaa49, 0x003e, 0x713c, - 0x2160, 0x080c, 0xf094, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, - 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x080c, - 0xb352, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x009e, 0x0005, - 0xd1ec, 0x1904, 0xa7a0, 0x0804, 0xa7a2, 0x00d6, 0x00c6, 0x0096, - 0x703c, 0x9065, 0x090c, 0x0dc5, 0x2001, 0x0306, 0x200c, 0x9184, - 0x0030, 0x0904, 0xa8a8, 0x9184, 0x0048, 0x9086, 0x0008, 0x1904, - 0xa8a8, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, - 0x1904, 0xa8a8, 0x2009, 0x022a, 0x2104, 0x2009, 0x022f, 0x210c, - 0x9116, 0x9084, 0x03ff, 0x918c, 0x03ff, 0x9294, 0x0400, 0x0110, - 0x9102, 0x0030, 0x2010, 0x2100, 0x9202, 0x2009, 0x0228, 0x9102, - 0x9082, 0x0005, 0x0250, 0x2008, 0x2001, 0x013b, 0x2004, 0x8004, - 0x8004, 0x8004, 0x9102, 0x1a04, 0xa8a8, 0x2009, 0x1a84, 0x2104, - 0x8000, 0x0208, 0x200a, 0x2069, 0x0100, 0x6914, 0x918c, 0x1984, - 0x918d, 0x0010, 0x6916, 0x69c8, 0x2011, 0x0020, 0x68c8, 0x9106, - 0x15c0, 0x8211, 0x1dd8, 0x2001, 0x0306, 0x2003, 0x4800, 0x2001, - 0x009a, 0x2003, 0x0004, 0x2001, 0x1a69, 0x2003, 0x0000, 0x2001, - 0x1a72, 0x2003, 0x0000, 0x6a88, 0x698c, 0x2200, 0x9105, 0x1170, - 0x0096, 0x6014, 0x2048, 0xa87c, 0xc0dc, 0xa87e, 0xa880, 0xc0fc, - 0xa882, 0x009e, 0x2c10, 0x080c, 0x1be0, 0x0040, 0x6014, 0x2048, - 0xaa3a, 0xa936, 0x6ac4, 0x69c8, 0xa946, 0xaa4a, 0x0126, 0x00c6, - 0x2091, 0x2400, 0x002e, 0x080c, 0x1c79, 0x190c, 0x0dc5, 0x012e, - 0x0090, 0x2009, 0x1a85, 0x2104, 0x8000, 0x0208, 0x200a, 0x69c8, - 0x2011, 0x0020, 0x8211, 0x1df0, 0x68c8, 0x9106, 0x1dc0, 0x69c4, - 0x68c8, 0x9105, 0x0160, 0x6824, 0xd08c, 0x0110, 0x6827, 0x0002, - 0x7048, 0xc085, 0x704a, 0x0079, 0x7048, 0xc084, 0x704a, 0x2009, - 0x07d0, 0x080c, 0x88c8, 0x9006, 0x009e, 0x00ce, 0x00de, 0x0005, - 0x9085, 0x0001, 0x0cc8, 0x0026, 0x00e6, 0x2071, 0x19e8, 0x7048, - 0xd084, 0x01d8, 0x713c, 0x81ff, 0x01c0, 0x2071, 0x0100, 0x9188, - 0x0008, 0x2114, 0x928e, 0x0006, 0x1138, 0x7014, 0x9084, 0x1984, - 0x9085, 0x0012, 0x7016, 0x0048, 0x928e, 0x0009, 0x0db0, 0x7014, - 0x9084, 0x1984, 0x9085, 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005, - 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, - 0x0126, 0x2091, 0x8000, 0x6010, 0x2058, 0xbca0, 0x2071, 0x19e8, - 0x7018, 0x2058, 0x8bff, 0x0190, 0xb8a0, 0x9406, 0x0118, 0xb854, - 0x2058, 0x0cc0, 0x6014, 0x0096, 0x2048, 0xac6c, 0xad70, 0xae78, - 0x009e, 0x080c, 0x6856, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e, - 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, - 0x080c, 0xa0c1, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, 0x7016, - 0x00c6, 0x7820, 0x9086, 0x0004, 0x1148, 0x7810, 0x9005, 0x0130, - 0x00b6, 0x2058, 0xb810, 0xb914, 0x00be, 0x0020, 0x2061, 0x1800, - 0x607c, 0x6180, 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, 0x60c3, - 0x002c, 0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003, 0x0f00, 0x7808, - 0xd09c, 0x0128, 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, 0x700e, - 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x0156, 0x080c, 0xa10c, 0x7003, - 0x0200, 0x080c, 0x894c, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, - 0xffed, 0x9ef0, 0x0002, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, - 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xa943, 0x60c3, - 0x001c, 0x015e, 0x0804, 0xa6bd, 0x0016, 0x0026, 0x080c, 0xa0e8, - 0x080c, 0xa0fa, 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814, - 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x0021, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x9192, - 0x0010, 0x1250, 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, 0x080c, - 0xa6bd, 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c, - 0xaf79, 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0xa0c1, - 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, - 0x0016, 0x0026, 0x080c, 0xa0c1, 0x20e9, 0x0000, 0x20a1, 0x024c, - 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, - 0x9080, 0x0023, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, - 0x4003, 0x8003, 0x60c2, 0x080c, 0xa6bd, 0x002e, 0x001e, 0x0005, - 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, - 0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xd2e0, 0x1110, 0x080c, - 0xbcb6, 0x600c, 0x0006, 0x080c, 0xd54c, 0x080c, 0xb2d3, 0x080c, - 0xaaf1, 0x00ce, 0x0c78, 0x2c00, 0x700e, 0x700a, 0x012e, 0x000e, - 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, - 0x180c, 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079, - 0x0140, 0x2071, 0x19e8, 0x7024, 0x2060, 0x8cff, 0x01f8, 0x080c, - 0xa6e9, 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x88c3, 0x00c6, 0x2061, - 0x0100, 0x080c, 0xb0ca, 0x00ce, 0x20a9, 0x01f4, 0x0461, 0x2009, - 0x0013, 0x080c, 0xb352, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x1800, - 0x2004, 0x9096, 0x0001, 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, - 0x88c3, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, - 0x0008, 0x68c3, 0x0000, 0x2011, 0x5f97, 0x080c, 0x883d, 0x20a9, - 0x01f4, 0x0009, 0x08c0, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, - 0x7804, 0x9084, 0x4000, 0x190c, 0x2d49, 0x0090, 0xd084, 0x0118, - 0x6827, 0x4001, 0x0010, 0x1f04, 0xaa2b, 0x7804, 0x9084, 0x1000, - 0x0138, 0x2001, 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, - 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, - 0x918c, 0xdbff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, - 0x19e8, 0x703c, 0x2060, 0x8cff, 0x0904, 0xaab4, 0x9386, 0x0002, - 0x1128, 0x6814, 0x9084, 0x0002, 0x0904, 0xaab4, 0x68af, 0x95f5, - 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, - 0x0008, 0x080c, 0x88d0, 0x080c, 0x2031, 0x2001, 0x0032, 0x6920, - 0xd1bc, 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, - 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, - 0x9084, 0x4000, 0x190c, 0x2d49, 0x0090, 0xd08c, 0x0118, 0x6827, - 0x0002, 0x0010, 0x1f04, 0xaa8a, 0x7804, 0x9084, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x6827, - 0x4000, 0x6824, 0x83ff, 0x1140, 0x2009, 0x0049, 0x6020, 0x9086, - 0x0009, 0x0110, 0x080c, 0xb352, 0x000e, 0x001e, 0x002e, 0x006e, - 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, - 0x0126, 0x2091, 0x8000, 0x2069, 0x19e8, 0x6a06, 0x012e, 0x00de, - 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x19e8, 0x6a32, - 0x012e, 0x00de, 0x0005, 0x080c, 0xa284, 0x7047, 0x1000, 0x0098, - 0x080c, 0xa284, 0x7047, 0x4000, 0x0070, 0x080c, 0xa284, 0x7047, - 0x2000, 0x0048, 0x080c, 0xa284, 0x7047, 0x0400, 0x0020, 0x080c, - 0xa284, 0x7047, 0x0200, 0x7854, 0x7032, 0x60c3, 0x0020, 0x0804, - 0xa6bd, 0x00e6, 0x2071, 0x19e8, 0x7020, 0x9005, 0x0110, 0x8001, - 0x7022, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, - 0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x7614, - 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0xab96, 0x8cff, - 0x0904, 0xab96, 0x6020, 0x9086, 0x0006, 0x1904, 0xab91, 0x88ff, - 0x0138, 0x2800, 0x9c06, 0x1904, 0xab91, 0x2039, 0x0000, 0x0050, - 0x6010, 0x9b06, 0x1904, 0xab91, 0x85ff, 0x0120, 0x6054, 0x9106, - 0x1904, 0xab91, 0x7024, 0x9c06, 0x15b0, 0x2069, 0x0100, 0x68c0, - 0x9005, 0x1160, 0x6824, 0xd084, 0x0148, 0x6827, 0x0001, 0x080c, - 0x88c3, 0x080c, 0xac1b, 0x7027, 0x0000, 0x0428, 0x080c, 0x88c3, - 0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, - 0x0000, 0x080c, 0xac1b, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, - 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d39, - 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, - 0x6827, 0x0001, 0x003e, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616, - 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012, - 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, - 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1168, 0x600f, 0x0000, 0x6014, - 0x0096, 0x2048, 0x080c, 0xd0d6, 0x0110, 0x080c, 0xebd4, 0x009e, - 0x080c, 0xb306, 0x080c, 0xaaf1, 0x88ff, 0x1190, 0x00ce, 0x0804, - 0xab0c, 0x2c78, 0x600c, 0x2060, 0x0804, 0xab0c, 0x9006, 0x012e, - 0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x601b, 0x0000, 0x00ce, 0x98c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, - 0x00d6, 0x0096, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0x19e8, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, - 0xac0a, 0x6020, 0x9086, 0x0006, 0x1904, 0xac05, 0x87ff, 0x0128, - 0x2700, 0x9c06, 0x1904, 0xac05, 0x0040, 0x6010, 0x9b06, 0x15e8, - 0x85ff, 0x0118, 0x6054, 0x9106, 0x15c0, 0x703c, 0x9c06, 0x1168, - 0x0036, 0x2019, 0x0001, 0x080c, 0xaa49, 0x7033, 0x0000, 0x9006, - 0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x7038, 0x9c36, 0x1110, - 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, - 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, - 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, - 0x2048, 0x080c, 0xd0d6, 0x0110, 0x080c, 0xebd4, 0x080c, 0xb306, - 0x87ff, 0x1198, 0x00ce, 0x0804, 0xabb6, 0x2c78, 0x600c, 0x2060, - 0x0804, 0xabb6, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, - 0x009e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, - 0x97bd, 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19e8, 0x2001, 0x1800, - 0x2004, 0x9086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, - 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x2c10, 0x7638, - 0x2660, 0x2678, 0x8cff, 0x0540, 0x2200, 0x9c06, 0x1508, 0x7038, - 0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, - 0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x6004, 0x9086, 0x0040, 0x090c, 0x99a5, 0x9085, 0x0001, 0x0020, - 0x2c78, 0x600c, 0x2060, 0x08b0, 0x012e, 0x000e, 0x002e, 0x006e, - 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0096, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19e8, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, 0xad01, 0x6010, - 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x1904, 0xacfc, 0x7024, - 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xacd3, - 0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7027, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0x9c36, - 0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, 0x2c00, 0x9f36, - 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x080c, 0xd2cf, 0x1180, 0x080c, 0x3279, 0x080c, 0xd2e0, 0x1518, - 0x080c, 0xbcb6, 0x0400, 0x080c, 0xac1b, 0x6824, 0xd084, 0x09b0, - 0x6827, 0x0001, 0x0898, 0x080c, 0xd2e0, 0x1118, 0x080c, 0xbcb6, - 0x0090, 0x6014, 0x2048, 0x080c, 0xd0d6, 0x0168, 0x6020, 0x9086, - 0x0003, 0x1508, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, - 0x6e92, 0x080c, 0xd2c3, 0x080c, 0xd54c, 0x080c, 0xb306, 0x080c, - 0xaaf1, 0x00ce, 0x0804, 0xac7c, 0x2c78, 0x600c, 0x2060, 0x0804, - 0xac7c, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, 0x080c, - 0xebd4, 0x0c08, 0x00d6, 0x080c, 0xa10c, 0x7003, 0x0200, 0x7007, - 0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, 0x1989, 0x20e9, - 0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, 0x0004, - 0x7027, 0x7878, 0x080c, 0xa6bd, 0x00de, 0x0005, 0x080c, 0xa10c, - 0x700b, 0x0800, 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, 0x9084, - 0x00ff, 0x7022, 0x782c, 0x7026, 0x7858, 0x9084, 0x00ff, 0x9085, - 0x0200, 0x7002, 0x7858, 0x9084, 0xff00, 0x8007, 0x7006, 0x60c2, - 0x0804, 0xa6bd, 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, 0x2009, - 0x0035, 0x080c, 0xd759, 0x00de, 0x1904, 0xadaf, 0x080c, 0xa0c1, - 0x7003, 0x1300, 0x782c, 0x080c, 0xaeb5, 0x2068, 0x6820, 0x9086, - 0x0003, 0x0560, 0x7810, 0x2058, 0xbaa0, 0x080c, 0xb23d, 0x11d8, - 0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0498, - 0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0458, - 0x9284, 0xff80, 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, 0x00ff, - 0x700f, 0xfffc, 0x0400, 0x92d8, 0x1000, 0x2b5c, 0xb810, 0x700a, - 0xb814, 0x700e, 0x00c0, 0x6098, 0x700e, 0x00a8, 0x080c, 0xb23d, - 0x1130, 0x7810, 0x2058, 0xb8a0, 0x9082, 0x007e, 0x0250, 0x00d6, - 0x2069, 0x181f, 0x2d04, 0x700a, 0x8d68, 0x2d04, 0x700e, 0x00de, - 0x0010, 0x6034, 0x700e, 0x7838, 0x7012, 0x783c, 0x7016, 0x60c3, - 0x000c, 0x001e, 0x00de, 0x080c, 0xa6bd, 0x00be, 0x0005, 0x781b, - 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x00be, 0x0005, 0x792c, - 0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, 0x0003, - 0x0904, 0xae2a, 0x9186, 0x0005, 0x0904, 0xae12, 0x9186, 0x0004, - 0x05d8, 0x9186, 0x0008, 0x0904, 0xae1b, 0x7807, 0x0037, 0x782f, - 0x0003, 0x7817, 0x1700, 0x080c, 0xae92, 0x0005, 0x080c, 0xae53, - 0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x0002, - 0xadf3, 0xadfe, 0xadf5, 0xadfe, 0xadfa, 0xadf3, 0xadf3, 0xadfe, - 0xadfe, 0xadfe, 0xadfe, 0xadf3, 0xadf3, 0xadf3, 0xadf3, 0xadf3, - 0xadfe, 0xadf3, 0xadfe, 0x080c, 0x0dc5, 0x6824, 0xd0e4, 0x0110, - 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, 0x7022, - 0x6830, 0x7026, 0x0804, 0xae4c, 0x080c, 0xae53, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, 0x1108, - 0x900e, 0x04d0, 0x080c, 0xae53, 0x00d6, 0x0026, 0x792c, 0x2168, - 0x2009, 0x4000, 0x0488, 0x04b9, 0x00d6, 0x0026, 0x792c, 0x2168, - 0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, 0x0002, 0x1108, - 0x900e, 0x0410, 0x0441, 0x00d6, 0x0026, 0x792c, 0x2168, 0x6814, - 0x6924, 0xc185, 0x6926, 0x0096, 0x2048, 0xa9ac, 0xa834, 0x9112, - 0xa9b0, 0xa838, 0x009e, 0x9103, 0x7022, 0x7226, 0x792c, 0x9180, - 0x0000, 0x2004, 0x908e, 0x0002, 0x0130, 0x908e, 0x0004, 0x0118, - 0x2009, 0x4000, 0x0008, 0x900e, 0x712a, 0x60c3, 0x0018, 0x002e, - 0x00de, 0x0804, 0xa6bd, 0x00b6, 0x0036, 0x0046, 0x0056, 0x0066, - 0x080c, 0xa10c, 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, 0x793c, - 0x710e, 0x7810, 0x2058, 0xb8a0, 0x080c, 0xb23d, 0x1118, 0x9092, - 0x007e, 0x0268, 0x00d6, 0x2069, 0x181f, 0x2d2c, 0x8d68, 0x2d34, - 0x90d8, 0x1000, 0x2b5c, 0xbb10, 0xbc14, 0x00de, 0x0028, 0x901e, - 0x6498, 0x2029, 0x0000, 0x6634, 0x782c, 0x9080, 0x0008, 0x2004, - 0x9086, 0x0003, 0x1128, 0x7512, 0x7616, 0x731a, 0x741e, 0x0020, - 0x7312, 0x7416, 0x751a, 0x761e, 0x006e, 0x005e, 0x004e, 0x003e, - 0x00be, 0x0005, 0x080c, 0xa10c, 0x7003, 0x0100, 0x782c, 0x700a, - 0x7814, 0x700e, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x080c, - 0xa0b8, 0x7003, 0x1400, 0x7838, 0x700a, 0x0079, 0x783c, 0x700e, - 0x782c, 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, 0x8007, - 0x701a, 0x60c3, 0x0010, 0x0804, 0xa6bd, 0x00e6, 0x2071, 0x0240, - 0x0006, 0x00f6, 0x2078, 0x7810, 0x00b6, 0x2058, 0xb8cc, 0xd084, - 0x0120, 0x7844, 0x702a, 0x7848, 0x702e, 0x00be, 0x00fe, 0x000e, - 0x00ee, 0x0005, 0x080c, 0xa103, 0x7003, 0x0100, 0x782c, 0x700a, - 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x0021, 0x60c3, - 0x0000, 0x0804, 0xa6bd, 0x00d6, 0x080c, 0xaf8e, 0xb810, 0x9085, - 0x0300, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, - 0x6880, 0x700e, 0x7013, 0x0819, 0x080c, 0xa6ab, 0x721a, 0x2f10, - 0x7222, 0x7a08, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x00a9, - 0x7914, 0x712a, 0x60c3, 0x0000, 0x60a7, 0x9575, 0x0026, 0x080c, - 0x2bce, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, - 0x080c, 0xa6e0, 0x080c, 0x88ba, 0x0005, 0x0036, 0x0096, 0x00d6, - 0x00e6, 0x7858, 0x2048, 0xaa7c, 0x9296, 0x00c0, 0x9294, 0x00fd, - 0xaa7e, 0xaa80, 0x9294, 0x0300, 0xaa82, 0xa96c, 0x9194, 0x00ff, - 0xab74, 0x9384, 0x00ff, 0x908d, 0xc200, 0xa96e, 0x9384, 0xff00, - 0x9215, 0xaa76, 0xa870, 0xaa78, 0xa87a, 0xaa72, 0x00d6, 0x2069, - 0x0200, 0x080c, 0xaf8e, 0x00de, 0x20e9, 0x0000, 0x20a1, 0x0240, - 0x20a9, 0x000a, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, - 0x4003, 0x60a3, 0x0035, 0xaa68, 0x9294, 0x7000, 0x9286, 0x3000, - 0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x009e, 0x003e, 0x0005, - 0x900e, 0x7814, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x01c0, 0x9084, - 0x0003, 0x11a8, 0x2001, 0x180c, 0x2004, 0xd0bc, 0x0180, 0x7824, - 0xd0cc, 0x1168, 0xd0c4, 0x1158, 0xa8a8, 0x9005, 0x1140, 0x2001, - 0x180c, 0x200c, 0xc1d5, 0x2102, 0x2009, 0x19b3, 0x210c, 0x009e, - 0x918d, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, - 0x0005, 0x2009, 0x0009, 0x00a0, 0x2009, 0x000a, 0x0088, 0x2009, - 0x000b, 0x0070, 0x2009, 0x000c, 0x0058, 0x2009, 0x000d, 0x0040, - 0x2009, 0x000e, 0x0028, 0x2009, 0x000f, 0x0010, 0x2009, 0x0008, - 0x6912, 0x0005, 0x080c, 0xa0c1, 0x0016, 0x0026, 0x0096, 0x00d6, - 0x7814, 0x2048, 0x7013, 0x0138, 0x2001, 0x1837, 0x2004, 0x9084, - 0x0028, 0x1138, 0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa, 0x1904, - 0xb033, 0x7003, 0x5400, 0x00c6, 0x2061, 0x1800, 0x607c, 0x9084, - 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00, 0x9105, 0x700a, 0x6080, - 0x700e, 0xa998, 0x918c, 0xff00, 0x7112, 0x20a9, 0x0004, 0x2009, - 0x1805, 0x2e10, 0x9290, 0x0006, 0x2104, 0x2012, 0x8108, 0x8210, - 0x1f04, 0xafc4, 0x20a9, 0x0004, 0x2009, 0x1801, 0x2104, 0x2012, - 0x8108, 0x8210, 0x1f04, 0xafce, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x0029, 0x2098, 0x2009, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, - 0x2012, 0x8210, 0x8109, 0x1dc0, 0x00d6, 0x2069, 0x0200, 0x080c, - 0xaf79, 0x00de, 0x2071, 0x0240, 0x2011, 0x0240, 0x2009, 0x0002, - 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, - 0x2009, 0x0008, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, - 0x8109, 0x1dc0, 0xa85c, 0x9080, 0x0031, 0x2098, 0x2009, 0x0008, - 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, - 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x2001, - 0x1837, 0x2004, 0x9084, 0x0028, 0x1168, 0x080c, 0x7637, 0x0150, - 0x6028, 0xc0bd, 0x602a, 0x6014, 0x9084, 0x1804, 0x9085, 0x0029, - 0x6016, 0x0010, 0x080c, 0xa6bd, 0x080c, 0x88ba, 0x00de, 0x009e, - 0x002e, 0x001e, 0x0005, 0x00e6, 0x2071, 0x0240, 0x2001, 0x2200, - 0x9085, 0x00ff, 0x7002, 0x7007, 0xffff, 0x2071, 0x0100, 0x709b, - 0x00ff, 0x00ee, 0x0804, 0xafa9, 0x080c, 0xa0c1, 0x0016, 0x0026, - 0x0096, 0x00d6, 0x7814, 0x2048, 0x7013, 0x0138, 0x7003, 0x5500, - 0x00c6, 0xa89c, 0x9084, 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00, - 0x9105, 0x700a, 0xa99c, 0x918c, 0xff00, 0xa8a0, 0x9084, 0x00ff, - 0x9105, 0x700e, 0xa998, 0x918c, 0xff00, 0x2061, 0x1800, 0x607c, - 0x9084, 0x00ff, 0x910d, 0x7112, 0x6180, 0x7116, 0x2009, 0x0008, - 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, 0x2e10, 0x9290, - 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, - 0x1dc0, 0x20a9, 0x0004, 0x2009, 0x1805, 0x2104, 0x2012, 0x8108, - 0x8210, 0x1f04, 0xb085, 0x20a9, 0x0002, 0x2009, 0x1801, 0x2104, - 0x2012, 0x8108, 0x8210, 0x1f04, 0xb08f, 0x00d6, 0x0016, 0x2069, - 0x0200, 0x080c, 0xaf79, 0x001e, 0x00de, 0x2071, 0x0240, 0x20a9, - 0x0002, 0x2009, 0x1803, 0x2011, 0x0240, 0x2104, 0x2012, 0x8108, - 0x8210, 0x1f04, 0xb0a5, 0x2009, 0x0008, 0x4002, 0x8007, 0x2012, - 0x8210, 0x8109, 0x1dd0, 0x9006, 0x20a9, 0x0008, 0x2012, 0x8210, - 0x1f04, 0xb0b6, 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, - 0x9575, 0x080c, 0xa6bd, 0x080c, 0x88ba, 0x00de, 0x009e, 0x002e, - 0x001e, 0x0005, 0x00d6, 0x9290, 0x0018, 0x8214, 0x20e9, 0x0000, - 0x2069, 0x0200, 0x6813, 0x0000, 0x22a8, 0x9284, 0x00e0, 0x0128, - 0x20a9, 0x0020, 0x9292, 0x0020, 0x0008, 0x9016, 0x20a1, 0x0240, - 0x9006, 0x4004, 0x82ff, 0x0120, 0x6810, 0x8000, 0x6812, 0x0c60, - 0x00de, 0x0005, 0x00d6, 0x0096, 0x6014, 0x2048, 0xa878, 0x6056, - 0x9006, 0xa836, 0xa83a, 0xa99c, 0xa946, 0xa84a, 0x6023, 0x0003, - 0x6007, 0x0040, 0x6003, 0x0003, 0x600b, 0xffff, 0xa817, 0x0001, - 0xa842, 0xa83e, 0x2900, 0xa85a, 0xa813, 0x20c5, 0x080c, 0x9564, - 0x0126, 0x2091, 0x8000, 0x080c, 0x9bd3, 0x012e, 0x009e, 0x00de, - 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00a6, 0x0096, 0x0066, - 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x760c, 0x2660, 0x2678, - 0x8cff, 0x0904, 0xb19d, 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100, - 0x68c0, 0x9005, 0x0904, 0xb16f, 0x080c, 0xa6e9, 0x68c3, 0x0000, - 0x080c, 0xac1b, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, - 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d39, 0x9006, - 0x080c, 0x2d39, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, - 0x0001, 0x003e, 0x700c, 0x9c36, 0x1110, 0x660c, 0x760e, 0x7008, - 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700a, 0x0010, - 0x700b, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, - 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xd2cf, 0x1180, 0x080c, - 0x3279, 0x080c, 0xd2e0, 0x1518, 0x080c, 0xbcb6, 0x0400, 0x080c, - 0xac1b, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c, - 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0090, 0x6014, 0x2048, 0x080c, - 0xd0d6, 0x0168, 0x6020, 0x9086, 0x0003, 0x1520, 0xa867, 0x0103, - 0xab7a, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x080c, 0xd2c3, 0x080c, - 0xd54c, 0x080c, 0xb306, 0x080c, 0xaaf1, 0x00ce, 0x0804, 0xb120, - 0x2c78, 0x600c, 0x2060, 0x0804, 0xb120, 0x700f, 0x0000, 0x700b, - 0x0000, 0x012e, 0x006e, 0x009e, 0x00ae, 0x00ce, 0x00de, 0x00ee, - 0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d08, 0x080c, 0xebd4, - 0x08f0, 0x00d6, 0x0156, 0x080c, 0xa10c, 0x7a14, 0x82ff, 0x0138, - 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, - 0x0200, 0x7007, 0x0000, 0x2069, 0x1800, 0x901e, 0x6800, 0x9086, - 0x0004, 0x1110, 0xc38d, 0x0060, 0x080c, 0x7637, 0x1110, 0xc3ad, - 0x0008, 0xc3a5, 0x6adc, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, - 0x730e, 0x080c, 0x894c, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, - 0xffed, 0x2071, 0x0250, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, - 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xb1e3, 0x60c3, - 0x0020, 0x080c, 0xa6bd, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, - 0xa10c, 0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, - 0x000e, 0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, - 0x0488, 0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2011, - 0x19be, 0x2204, 0x8007, 0x701a, 0x8210, 0x2204, 0x8007, 0x701e, - 0x0421, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, - 0x2004, 0x7022, 0x2001, 0x1820, 0x2004, 0x7026, 0x0030, 0x2001, - 0x1818, 0x2004, 0x9084, 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1, - 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, - 0x60c3, 0x001c, 0x015e, 0x0804, 0xa6bd, 0x0006, 0x2001, 0x1837, - 0x2004, 0xd0ac, 0x000e, 0x0005, 0x2011, 0x0003, 0x080c, 0xaabf, - 0x2011, 0x0002, 0x080c, 0xaac9, 0x080c, 0xa9d3, 0x0036, 0x901e, - 0x080c, 0xaa49, 0x003e, 0x0005, 0x080c, 0x33af, 0x0188, 0x0016, - 0x00b6, 0x00c6, 0x7010, 0x9085, 0x0020, 0x7012, 0x2009, 0x007e, - 0x080c, 0x6724, 0xb85c, 0xc0ac, 0xb85e, 0x00ce, 0x00be, 0x001e, - 0x0005, 0x2071, 0x188d, 0x7000, 0x9005, 0x0140, 0x2001, 0x0976, - 0x2071, 0x1800, 0x7076, 0x707a, 0x706b, 0xffe0, 0x2071, 0x1800, - 0x7074, 0x7056, 0x705b, 0x1cd0, 0x0005, 0x00e6, 0x0126, 0x2071, - 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0010, 0x0608, 0x7058, - 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7068, - 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008, - 0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502, 0x1230, 0x755a, - 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1cd0, 0x0cc0, - 0x9006, 0x0cc0, 0x00e6, 0x2071, 0x1800, 0x7554, 0x9582, 0x0010, - 0x0600, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, - 0x0018, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, - 0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502, - 0x1228, 0x755a, 0x9085, 0x0001, 0x00ee, 0x0005, 0x705b, 0x1cd0, - 0x0cc8, 0x9006, 0x0cc8, 0x9c82, 0x1cd0, 0x0a0c, 0x0dc5, 0x2001, - 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0dc5, 0x9006, 0x6006, 0x600a, - 0x600e, 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, 0x0000, - 0x601e, 0x6056, 0x605a, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036, - 0x603a, 0x603e, 0x6042, 0x602a, 0x2061, 0x1800, 0x6054, 0x8000, - 0x6056, 0x9086, 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, - 0x0016, 0x080c, 0x9ab1, 0x001e, 0x012e, 0x0cb0, 0x0006, 0x6000, - 0x9086, 0x0000, 0x01c0, 0x601c, 0xd084, 0x190c, 0x1a8e, 0x6017, - 0x0000, 0x6023, 0x0007, 0x2001, 0x1986, 0x2004, 0x0006, 0x9082, - 0x0051, 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xee87, 0x6043, - 0x0000, 0x6013, 0x0000, 0x000e, 0x0005, 0x00e6, 0x0126, 0x2071, - 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0001, 0x0608, 0x7058, - 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7068, - 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008, - 0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502, 0x1230, 0x755a, - 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1cd0, 0x0cc0, - 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, 0xb365, 0xb36e, - 0xb389, 0xb3a4, 0xd82b, 0xd848, 0xd863, 0xb365, 0xb36e, 0x9100, - 0xb3bd, 0xb365, 0xb365, 0xb365, 0xb365, 0x9186, 0x0013, 0x1128, - 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0005, 0x0005, 0x0066, 0x6000, - 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, 0x0005, 0xb387, - 0xbb05, 0xbcfd, 0xb387, 0xbd93, 0xb6a0, 0xb387, 0xb387, 0xba87, - 0xc3b1, 0xb387, 0xb387, 0xb387, 0xb387, 0xb387, 0xb387, 0x080c, - 0x0dc5, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, - 0x006e, 0x0005, 0xb3a2, 0xca7e, 0xb3a2, 0xb3a2, 0xb3a2, 0xb3a2, - 0xb3a2, 0xb3a2, 0xca15, 0xcc00, 0xb3a2, 0xcabf, 0xcb3e, 0xcabf, - 0xcb3e, 0xb3a2, 0x080c, 0x0dc5, 0x6000, 0x9082, 0x0010, 0x1a0c, - 0x0dc5, 0x6000, 0x0002, 0xb3bb, 0xc3f8, 0xc4c0, 0xc5f3, 0xc7a2, - 0xb3bb, 0xb3bb, 0xb3bb, 0xc3cc, 0xc9a1, 0xc9a4, 0xb3bb, 0xb3bb, - 0xb3bb, 0xb3bb, 0xc9d3, 0x080c, 0x0dc5, 0x0066, 0x6000, 0x90b2, - 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, 0x0005, 0xb3d6, 0xb3d6, - 0xb419, 0xb4b8, 0xb54d, 0xb3d6, 0xb3d6, 0xb3d6, 0xb3d8, 0xb3d6, - 0xb3d6, 0xb3d6, 0xb3d6, 0xb3d6, 0xb3d6, 0xb3d6, 0x080c, 0x0dc5, - 0x9186, 0x004c, 0x0588, 0x9186, 0x0003, 0x190c, 0x0dc5, 0x0096, - 0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, - 0xa87c, 0x9084, 0xa000, 0xc0b5, 0xa87e, 0xa8ac, 0xa846, 0xa8b0, - 0xa84a, 0x9006, 0xa836, 0xa83a, 0xa884, 0x9092, 0x199a, 0x0210, - 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, 0x621a, 0x009e, - 0x2c10, 0x080c, 0x1be0, 0x080c, 0x9564, 0x0126, 0x2091, 0x8000, - 0x080c, 0x9bd3, 0x012e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0, - 0x00be, 0x2c00, 0x080c, 0xb56f, 0x080c, 0xd7fb, 0x6003, 0x0007, - 0x0005, 0x00d6, 0x0096, 0x00f6, 0x2079, 0x1800, 0x7a90, 0x6014, - 0x2048, 0xa87c, 0xd0ec, 0x1110, 0x9290, 0x0018, 0xac78, 0xc4fc, - 0x0046, 0xa8e0, 0x9005, 0x1140, 0xa8dc, 0x921a, 0x0140, 0x0220, - 0xa87b, 0x0007, 0x2010, 0x0028, 0xa87b, 0x0015, 0x0010, 0xa87b, - 0x0000, 0x8214, 0xa883, 0x0000, 0xaa02, 0x0006, 0x0016, 0x0026, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, - 0x2100, 0x9086, 0x0015, 0x1118, 0x2001, 0x0001, 0x0038, 0x2100, - 0x9086, 0x0016, 0x0118, 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, - 0x8423, 0x9405, 0x0002, 0xb480, 0xb480, 0xb47b, 0xb47e, 0xb480, - 0xb478, 0xb46b, 0xb46b, 0xb46b, 0xb46b, 0xb46b, 0xb46b, 0xb46b, - 0xb46b, 0xb46b, 0xb46b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, - 0x001e, 0x000e, 0x004e, 0x00fe, 0x009e, 0x00de, 0x080c, 0x0dc5, - 0x080c, 0xbfab, 0x0028, 0x080c, 0xc0e9, 0x0010, 0x080c, 0xc1df, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896, - 0x000e, 0x080c, 0xb62d, 0x0530, 0xa804, 0xa80e, 0x00a6, 0x2050, - 0xb100, 0x00ae, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x0002, 0xaacc, 0xabd0, 0xacd4, 0xadd8, 0x2031, - 0x0000, 0x2041, 0x126c, 0x080c, 0xb7f1, 0x0160, 0x000e, 0x9005, - 0x0120, 0x00fe, 0x009e, 0x00de, 0x0005, 0x00fe, 0x009e, 0x00de, - 0x0804, 0xb2d3, 0x2001, 0x002c, 0x900e, 0x080c, 0xb693, 0x0c70, - 0x91b6, 0x0015, 0x0170, 0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047, - 0x0a0c, 0x0dc5, 0x91b2, 0x0050, 0x1a0c, 0x0dc5, 0x9182, 0x0047, - 0x00ca, 0x2001, 0x0109, 0x2004, 0xd08c, 0x0198, 0x0126, 0x2091, - 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x94b1, 0x002e, 0x001e, - 0x000e, 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, 0x0804, - 0xb419, 0x0005, 0xb4eb, 0xb4eb, 0xb4ed, 0xb523, 0xb4eb, 0xb4eb, - 0xb4eb, 0xb4eb, 0xb536, 0x080c, 0x0dc5, 0x00d6, 0x0016, 0x0096, - 0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6003, 0x0004, 0x6114, 0x2148, - 0xa87c, 0xd0fc, 0x01c0, 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894, - 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, 0xb693, 0x080c, - 0xb2d3, 0x00a8, 0x6003, 0x0002, 0xa8a4, 0xa9a8, 0x9105, 0x1178, - 0xa8ae, 0xa8b2, 0x0c78, 0xa87f, 0x0020, 0xa88c, 0xa88a, 0xa8a4, - 0xa8ae, 0xa8a8, 0xa8b2, 0xa8c7, 0x0000, 0xa8cb, 0x0000, 0x009e, - 0x001e, 0x00de, 0x0005, 0x080c, 0x9a61, 0x00d6, 0x0096, 0x6114, - 0x2148, 0x080c, 0xd0d8, 0x0120, 0xa87b, 0x0006, 0x080c, 0x6e9f, - 0x009e, 0x00de, 0x080c, 0xb2d3, 0x0804, 0x9bd3, 0x080c, 0x9a61, - 0x080c, 0x3250, 0x080c, 0xd7f8, 0x00d6, 0x0096, 0x6114, 0x2148, - 0x080c, 0xd0d8, 0x0120, 0xa87b, 0x0029, 0x080c, 0x6e9f, 0x009e, - 0x00de, 0x080c, 0xb2d3, 0x0804, 0x9bd3, 0x9182, 0x0047, 0x0002, - 0xb55d, 0xb55f, 0xb55d, 0xb55d, 0xb55d, 0xb55d, 0xb55d, 0xb55d, - 0xb55d, 0xb55d, 0xb55d, 0xb55d, 0xb55f, 0x080c, 0x0dc5, 0x00d6, - 0x0096, 0x601f, 0x0000, 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883, - 0x0000, 0x080c, 0x6e9f, 0x009e, 0x00de, 0x0804, 0xb2d3, 0x0026, - 0x0036, 0x0056, 0x0066, 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c, - 0x100e, 0x000e, 0x090c, 0x0dc5, 0xa960, 0x21e8, 0xa95c, 0x9188, - 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079, - 0x1800, 0x7990, 0x9188, 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76, - 0x2950, 0x00a6, 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, - 0x0001, 0x9182, 0x0035, 0x1228, 0x2011, 0x001f, 0x080c, 0xcc85, - 0x04c0, 0x2130, 0x2009, 0x0034, 0x2011, 0x001f, 0x080c, 0xcc85, - 0x96b2, 0x0034, 0xb004, 0x904d, 0x0110, 0x080c, 0x0fc0, 0x080c, - 0x100e, 0x01d0, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, - 0xb406, 0x968a, 0x003d, 0x1230, 0x2608, 0x2011, 0x001b, 0x080c, - 0xcc85, 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, - 0x001b, 0x080c, 0xcc85, 0x0c18, 0x2001, 0x0205, 0x2003, 0x0000, - 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0xb070, 0xc0fd, 0xb072, - 0x0048, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, - 0x0050, 0xb566, 0x2a48, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, - 0x6e9f, 0x000e, 0x2048, 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e, - 0x006e, 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096, - 0x0006, 0x080c, 0x100e, 0x000e, 0x090c, 0x0dc5, 0xa960, 0x21e8, - 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, - 0xaa66, 0xa87a, 0x2079, 0x1800, 0x7990, 0x810c, 0x9188, 0x000c, - 0x9182, 0x001a, 0x0210, 0x2009, 0x001a, 0x21a8, 0x810b, 0xa972, - 0xac76, 0x2e98, 0xa85c, 0x9080, 0x001f, 0x20a0, 0x2001, 0x0205, - 0x200c, 0x918d, 0x0080, 0x2102, 0x4003, 0x2003, 0x0000, 0x080c, - 0x6e9f, 0x009e, 0x00fe, 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, - 0x0096, 0x0016, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, - 0x001e, 0x2079, 0x0200, 0x2e98, 0xa87c, 0xd0ec, 0x0118, 0x9e80, - 0x000c, 0x2098, 0x2021, 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, - 0x2011, 0x0020, 0x2018, 0x9486, 0x003e, 0x1170, 0x0096, 0x080c, - 0x100e, 0x2900, 0x009e, 0x05c0, 0xa806, 0x2048, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, - 0x2009, 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, - 0x2200, 0x9402, 0x1228, 0x2400, 0x9202, 0x2410, 0x9318, 0x9006, - 0x2020, 0x22a8, 0xa800, 0x9200, 0xa802, 0x20e1, 0x0000, 0x4003, - 0x83ff, 0x0180, 0x3300, 0x9086, 0x0280, 0x1130, 0x7814, 0x8000, - 0x9085, 0x0080, 0x7816, 0x2e98, 0x2310, 0x84ff, 0x0904, 0xb642, - 0x0804, 0xb644, 0x9085, 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe, - 0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348, - 0xa87a, 0xa982, 0x080c, 0x6e92, 0x009e, 0x003e, 0x00de, 0x0005, - 0x91b6, 0x0015, 0x1118, 0x080c, 0xb2d3, 0x0030, 0x91b6, 0x0016, - 0x190c, 0x0dc5, 0x080c, 0xb2d3, 0x0005, 0x20a9, 0x000e, 0x20e1, - 0x0000, 0x2e98, 0x6014, 0x0096, 0x2048, 0xa860, 0x20e8, 0xa85c, - 0x20a0, 0x009e, 0x4003, 0x9196, 0x0016, 0x01f0, 0x0136, 0x9080, - 0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, 0x3418, 0x8318, - 0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, 0x1db8, 0x2011, - 0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, 0x4003, 0x3418, - 0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, 0xd0d8, 0x0130, - 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0x009e, 0x0804, - 0xb2d3, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11a8, - 0x6010, 0x00b6, 0x2058, 0xb8cf, 0x0000, 0x00be, 0x6014, 0x9005, - 0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xab32, 0x080c, - 0xb2d3, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, 0x1d48, 0x0cc8, - 0x0006, 0x0016, 0x080c, 0xd7e3, 0x0188, 0x6014, 0x9005, 0x1170, - 0x600b, 0x0003, 0x601b, 0x0000, 0x6043, 0x0000, 0x2009, 0x0022, - 0x080c, 0xbadd, 0x9006, 0x001e, 0x000e, 0x0005, 0x9085, 0x0001, - 0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1, - 0x0000, 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099, - 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, 0xa804, 0x2048, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, - 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003, - 0x2003, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, - 0x080c, 0xb2d3, 0x001e, 0x009e, 0x0005, 0x0096, 0x0016, 0x900e, - 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, 0x00ff, 0x800c, - 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, 0x9108, 0x810b, - 0x2011, 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, 0x080c, 0xcc85, - 0x080c, 0xd0d8, 0x0140, 0x6014, 0x2048, 0xa807, 0x0000, 0xa864, - 0xa8e2, 0xa867, 0x0103, 0x080c, 0xb2d3, 0x001e, 0x009e, 0x0005, - 0x0016, 0x2009, 0x0000, 0x7030, 0x9086, 0x0200, 0x0110, 0x2009, - 0x0001, 0x0096, 0x6014, 0x904d, 0x090c, 0x0dc5, 0xa97a, 0x080c, - 0x6e9f, 0x009e, 0x080c, 0xb2d3, 0x001e, 0x0005, 0x0016, 0x0096, - 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, 0x7034, - 0x800c, 0x810b, 0x2011, 0x000c, 0x2019, 0x000c, 0x6014, 0x2048, - 0xa804, 0x0096, 0x9005, 0x0108, 0x2048, 0x080c, 0xcc85, 0x009e, - 0x080c, 0xd0d8, 0x0148, 0xa804, 0x9005, 0x1158, 0xa807, 0x0000, - 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xb2d3, 0x009e, 0x001e, - 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, 0x0100, 0x1118, - 0x080c, 0xbcb6, 0x00e0, 0xa034, 0x8007, 0x800c, 0x8806, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x000c, 0xa87b, - 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xaaa0, 0xab9c, 0xaca8, - 0xada4, 0x2031, 0x0000, 0x2041, 0x1252, 0x0019, 0x0d08, 0x008e, - 0x0898, 0x0096, 0x0006, 0x080c, 0x100e, 0x000e, 0x01b0, 0xa8ab, - 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, 0x2800, 0xa89e, - 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, 0x0086, 0x2940, - 0x080c, 0x10f8, 0x008e, 0x9085, 0x0001, 0x009e, 0x0005, 0x00e6, - 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, - 0xba10, 0x00be, 0x9206, 0x1520, 0x700c, 0x6210, 0x00b6, 0x2258, - 0xba14, 0x00be, 0x9206, 0x11e0, 0x6043, 0x0000, 0x2c68, 0x0016, - 0x2009, 0x0035, 0x080c, 0xd759, 0x001e, 0x1158, 0x622c, 0x2268, - 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, - 0x0128, 0x080c, 0xb2d3, 0x0020, 0x0039, 0x0010, 0x080c, 0xb910, - 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, 0x2048, 0x9186, - 0x0015, 0x0904, 0xb8f8, 0x918e, 0x0016, 0x1904, 0xb90e, 0x700c, - 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, - 0xb8d2, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, 0xb8b5, - 0x0804, 0xb90c, 0x6808, 0x9086, 0xffff, 0x1904, 0xb8fa, 0xa87c, - 0x9084, 0x0060, 0x9086, 0x0020, 0x1128, 0xa83c, 0xa940, 0x9105, - 0x1904, 0xb8fa, 0x6824, 0xd084, 0x1904, 0xb8fa, 0xd0b4, 0x0158, - 0x0016, 0x2001, 0x1986, 0x200c, 0x6018, 0x9102, 0x9082, 0x0005, - 0x001e, 0x1a04, 0xb8fa, 0x080c, 0xd2c3, 0x685c, 0xa882, 0xa87c, - 0xc0dc, 0xc0f4, 0xc0d4, 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, - 0x000a, 0x080c, 0x9375, 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, - 0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xcde3, 0x00ce, - 0x0804, 0xb90c, 0x00c6, 0xa868, 0xd0fc, 0x1118, 0x080c, 0x61c2, - 0x0010, 0x080c, 0x65cf, 0x00ce, 0x1904, 0xb8fa, 0x00c6, 0x2d60, - 0x080c, 0xb2d3, 0x00ce, 0x0804, 0xb90c, 0x00c6, 0x080c, 0xb325, - 0x0198, 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xd554, 0x6023, - 0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0xb2d3, 0x00ce, 0x080c, - 0xb352, 0x00ce, 0x0804, 0xb90c, 0x2001, 0x1988, 0x2004, 0x6842, - 0x00ce, 0x04d0, 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, - 0x2058, 0xb900, 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, - 0x0003, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x00ce, 0x00e8, 0x700c, - 0x9086, 0x2a00, 0x1138, 0x2001, 0x1988, 0x2004, 0x6842, 0x00a0, - 0x0479, 0x00a0, 0x89ff, 0x090c, 0x0dc5, 0x00c6, 0x00d6, 0x2d60, - 0xa867, 0x0103, 0xa87b, 0x0003, 0x080c, 0x6cb9, 0x080c, 0xd2c3, - 0x080c, 0xb306, 0x00de, 0x00ce, 0x080c, 0xb2d3, 0x009e, 0x0005, - 0x9186, 0x0015, 0x1128, 0x2001, 0x1988, 0x2004, 0x6842, 0x0068, - 0x918e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xee87, - 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x00ce, 0x080c, 0xb2d3, 0x0005, - 0x0026, 0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, - 0x2001, 0x1988, 0x2004, 0x6842, 0x0804, 0xb98a, 0x00c6, 0x2d60, - 0x080c, 0xcce6, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, - 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8, - 0x89ff, 0x090c, 0x0dc5, 0x6800, 0x9086, 0x0004, 0x1190, 0xa87c, - 0xd0ac, 0x0178, 0xa843, 0x0fff, 0xa83f, 0x0fff, 0xa880, 0xc0fc, - 0xa882, 0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, 0x6832, - 0x00e0, 0xa87c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4, - 0x1d48, 0xa838, 0xa934, 0x9105, 0x0d80, 0x0c20, 0xd2ec, 0x1d68, - 0x7024, 0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e, - 0x7024, 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xd44b, 0x080c, - 0x9ab1, 0x0010, 0x080c, 0xb2d3, 0x004e, 0x003e, 0x002e, 0x0005, - 0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, - 0x2258, 0xba10, 0x00be, 0x9206, 0x1904, 0xb9f5, 0x700c, 0x6210, - 0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xb9f5, 0x6038, - 0x2068, 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, - 0xb9f5, 0x9286, 0x0002, 0x0904, 0xb9f5, 0x9286, 0x0000, 0x05e8, - 0x6808, 0x633c, 0x9306, 0x15c8, 0x2071, 0x026c, 0x9186, 0x0015, - 0x0570, 0x918e, 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, - 0x9186, 0x004b, 0x01c0, 0x9186, 0x004c, 0x01a8, 0x9186, 0x004d, - 0x0190, 0x9186, 0x004e, 0x0178, 0x9186, 0x0052, 0x0160, 0x6014, - 0x0096, 0x2048, 0x080c, 0xd0d8, 0x090c, 0x0dc5, 0xa87b, 0x0003, - 0x009e, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x00ce, 0x0030, 0x6038, - 0x2070, 0x2001, 0x1988, 0x2004, 0x7042, 0x080c, 0xb2d3, 0x002e, - 0x00de, 0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, - 0x6010, 0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, - 0xc48c, 0xbc02, 0x0470, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, - 0x9e90, 0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, 0xc379, - 0x002e, 0x003e, 0x015e, 0x009e, 0x1904, 0xba66, 0x0096, 0x0156, - 0x0036, 0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, - 0x0004, 0x080c, 0xc379, 0x002e, 0x003e, 0x015e, 0x009e, 0x15b0, - 0x7238, 0xba0a, 0x733c, 0xbb0e, 0x83ff, 0x0118, 0xbc00, 0xc48d, - 0xbc02, 0xa804, 0x9005, 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804, - 0xb6dc, 0x0096, 0x2048, 0xaa12, 0xab16, 0xac0a, 0x009e, 0x8006, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, - 0x2041, 0x1252, 0x080c, 0xb7f1, 0x0130, 0x00fe, 0x009e, 0x080c, - 0xb2d3, 0x00be, 0x0005, 0x080c, 0xbcb6, 0x0cb8, 0x2b78, 0x00f6, - 0x080c, 0x3250, 0x080c, 0xd7f8, 0x00fe, 0x00c6, 0x080c, 0xb27d, - 0x2f00, 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, - 0x6003, 0x0001, 0x2001, 0x0007, 0x080c, 0x666a, 0x080c, 0x6696, - 0x080c, 0x9547, 0x080c, 0x9ab1, 0x00ce, 0x0804, 0xba39, 0x2100, - 0x91b2, 0x0053, 0x1a0c, 0x0dc5, 0x91b2, 0x0040, 0x1a04, 0xbaef, - 0x0002, 0xbadd, 0xbadd, 0xbad3, 0xbadd, 0xbadd, 0xbadd, 0xbad1, - 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, - 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, - 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, - 0xbadd, 0xbad1, 0xbadd, 0xbadd, 0xbad1, 0xbad1, 0xbad1, 0xbad1, - 0xbad1, 0xbad3, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, - 0xbad1, 0xbad1, 0xbad1, 0xbadd, 0xbadd, 0xbad1, 0xbad1, 0xbad1, - 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbadd, 0xbad1, - 0xbad1, 0x080c, 0x0dc5, 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8cc, - 0xc08c, 0xb8ce, 0x00be, 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, - 0x9186, 0x0032, 0x0118, 0x080c, 0x9547, 0x0010, 0x080c, 0x94ff, - 0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005, 0x2600, - 0x0002, 0xbadd, 0xbadd, 0xbb03, 0xbadd, 0xbadd, 0xbb03, 0xbb03, - 0xbb03, 0xbb03, 0xbadd, 0xbb03, 0xbadd, 0xbb03, 0xbadd, 0xbb03, - 0xbb03, 0xbb03, 0xbb03, 0x080c, 0x0dc5, 0x6004, 0x90b2, 0x0053, - 0x1a0c, 0x0dc5, 0x91b6, 0x0013, 0x0904, 0xbbd8, 0x91b6, 0x0027, - 0x1904, 0xbb82, 0x080c, 0x99a5, 0x6004, 0x080c, 0xd2cf, 0x01b0, - 0x080c, 0xd2e0, 0x01a8, 0x908e, 0x0021, 0x0904, 0xbb7f, 0x908e, - 0x0022, 0x1130, 0x080c, 0xb708, 0x0904, 0xbb7b, 0x0804, 0xbb7c, - 0x908e, 0x003d, 0x0904, 0xbb7f, 0x0804, 0xbb75, 0x080c, 0x3279, - 0x2001, 0x0007, 0x080c, 0x666a, 0x6010, 0x00b6, 0x2058, 0xb9a0, - 0x00be, 0x080c, 0xbcb6, 0x9186, 0x007e, 0x1148, 0x2001, 0x1837, - 0x2014, 0xc285, 0x080c, 0x7637, 0x1108, 0xc2ad, 0x2202, 0x0036, - 0x0026, 0x2019, 0x0028, 0x2110, 0x080c, 0xef94, 0x002e, 0x003e, - 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x96a4, - 0x0076, 0x903e, 0x080c, 0x9577, 0x6010, 0x00b6, 0x905d, 0x0100, - 0x00be, 0x2c08, 0x080c, 0xe91c, 0x007e, 0x003e, 0x002e, 0x001e, - 0x080c, 0xd7f8, 0x0016, 0x080c, 0xd54c, 0x080c, 0xb2d3, 0x001e, - 0x080c, 0x334c, 0x080c, 0x9ab1, 0x0030, 0x080c, 0xd54c, 0x080c, - 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x080c, 0xbcb6, 0x0cb0, 0x080c, - 0xbcf2, 0x0c98, 0x9186, 0x0015, 0x0118, 0x9186, 0x0016, 0x1148, - 0x080c, 0xd809, 0x0d80, 0x6000, 0x9086, 0x0002, 0x0904, 0xbcfd, - 0x0c50, 0x9186, 0x0014, 0x1d38, 0x080c, 0x99a5, 0x6004, 0x908e, - 0x0022, 0x1118, 0x080c, 0xb708, 0x09f0, 0x080c, 0x3250, 0x080c, - 0xd7f8, 0x080c, 0xd2cf, 0x1198, 0x080c, 0x3279, 0x6010, 0x00b6, - 0x2058, 0xb9a0, 0x00be, 0x080c, 0xbcb6, 0x9186, 0x007e, 0x1128, - 0x2001, 0x1837, 0x200c, 0xc185, 0x2102, 0x0804, 0xbb75, 0x080c, - 0xd2e0, 0x1120, 0x080c, 0xbcb6, 0x0804, 0xbb75, 0x6004, 0x908e, - 0x0032, 0x1160, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, - 0x080c, 0x35e7, 0x00fe, 0x00ee, 0x0804, 0xbb75, 0x6004, 0x908e, - 0x0021, 0x0d40, 0x908e, 0x0022, 0x090c, 0xbcb6, 0x0804, 0xbb75, - 0x90b2, 0x0040, 0x1a04, 0xbc92, 0x2008, 0x0002, 0xbc20, 0xbc21, - 0xbc24, 0xbc27, 0xbc2a, 0xbc37, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, - 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, - 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, - 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc3a, 0xbc47, 0xbc1e, 0xbc49, - 0xbc47, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc47, 0xbc47, - 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, - 0xbc79, 0xbc47, 0xbc1e, 0xbc43, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc44, - 0xbc1e, 0xbc1e, 0xbc1e, 0xbc47, 0xbc70, 0xbc1e, 0x080c, 0x0dc5, - 0x0430, 0x2001, 0x000b, 0x0470, 0x2001, 0x0003, 0x0458, 0x2001, - 0x0005, 0x0440, 0x6010, 0x00b6, 0x2058, 0xb804, 0x00be, 0x9084, - 0x00ff, 0x9086, 0x0000, 0x1500, 0x2001, 0x0001, 0x00d8, 0x2001, - 0x0009, 0x00c0, 0x080c, 0x99a5, 0x6003, 0x0005, 0x080c, 0xd7fb, - 0x080c, 0x9ab1, 0x0070, 0x0018, 0x0010, 0x080c, 0x666a, 0x0804, - 0xbc8a, 0x080c, 0x99a5, 0x080c, 0xd7fb, 0x6003, 0x0004, 0x080c, - 0x9ab1, 0x0005, 0x080c, 0x666a, 0x080c, 0x99a5, 0x6003, 0x0002, - 0x0036, 0x2019, 0x1852, 0x2304, 0x9084, 0xff00, 0x1120, 0x2001, - 0x1986, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, 0x8003, - 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c, 0x9ab1, 0x0c08, - 0x080c, 0x99a5, 0x080c, 0xd54c, 0x080c, 0xb2d3, 0x080c, 0x9ab1, - 0x08c0, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, - 0x35e7, 0x00fe, 0x00ee, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c, - 0x9ab1, 0x0838, 0x080c, 0x99a5, 0x6003, 0x0002, 0x080c, 0xd7fb, - 0x0804, 0x9ab1, 0x2600, 0x2008, 0x0002, 0xbca9, 0xbc8a, 0xbca7, - 0xbc8a, 0xbc8a, 0xbca7, 0xbca7, 0xbca7, 0xbca7, 0xbc8a, 0xbca7, - 0xbc8a, 0xbca7, 0xbc8a, 0xbca7, 0xbca7, 0xbca7, 0xbca7, 0x080c, - 0x0dc5, 0x080c, 0x99a5, 0x0096, 0x6014, 0x2048, 0x080c, 0x6e9f, - 0x009e, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x00e6, 0x0096, - 0x0026, 0x0016, 0x080c, 0xd0d8, 0x0568, 0x6014, 0x2048, 0xa864, - 0x9086, 0x0139, 0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, 0x080c, - 0x556f, 0x0130, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0028, - 0x2001, 0x0030, 0x900e, 0x2011, 0x4005, 0x080c, 0xd6bd, 0x0090, - 0xa868, 0xd0fc, 0x0178, 0xa807, 0x0000, 0x0016, 0x6004, 0x908e, - 0x0021, 0x0168, 0x908e, 0x003d, 0x0150, 0x001e, 0xa867, 0x0103, - 0xa833, 0x0100, 0x001e, 0x002e, 0x009e, 0x00ee, 0x0005, 0x001e, - 0x0009, 0x0cc0, 0x0096, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, - 0x0103, 0xa823, 0x8001, 0x009e, 0x0005, 0x00b6, 0x6610, 0x2658, - 0xb804, 0x9084, 0x00ff, 0x90b2, 0x000c, 0x1a0c, 0x0dc5, 0x6604, - 0x96b6, 0x004d, 0x1120, 0x080c, 0xd5dc, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x0043, 0x1120, 0x080c, 0xd625, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x004b, 0x1120, 0x080c, 0xd651, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x0033, 0x1120, 0x080c, 0xd56e, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x0028, 0x1120, 0x080c, 0xd31e, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x0029, 0x1120, 0x080c, 0xd35f, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x001f, 0x1120, 0x080c, 0xb6ad, 0x0804, 0xbd82, 0x6604, - 0x96b6, 0x0000, 0x1118, 0x080c, 0xb9fb, 0x04e0, 0x6604, 0x96b6, - 0x0022, 0x1118, 0x080c, 0xb6e9, 0x04a8, 0x6604, 0x96b6, 0x0035, - 0x1118, 0x080c, 0xb80f, 0x0470, 0x6604, 0x96b6, 0x0039, 0x1118, - 0x080c, 0xb990, 0x0438, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, - 0xb721, 0x0400, 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xb75d, - 0x00c8, 0x6604, 0x96b6, 0x0049, 0x1118, 0x080c, 0xb79e, 0x0090, - 0x6604, 0x96b6, 0x0041, 0x1118, 0x080c, 0xb788, 0x0058, 0x91b6, - 0x0015, 0x1110, 0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, 0x00be, - 0x0804, 0xc08e, 0x00be, 0x0005, 0x080c, 0xb36d, 0x0cd8, 0xbd9f, - 0xbdad, 0xbd9f, 0xbdf4, 0xbd9f, 0xbfab, 0xc09b, 0xbd9f, 0xbd9f, - 0xc064, 0xbd9f, 0xc07a, 0x0096, 0x601f, 0x0000, 0x6014, 0x2048, - 0xa800, 0x2048, 0xa867, 0x0103, 0x009e, 0x0804, 0xb2d3, 0xa001, - 0xa001, 0x0005, 0x6604, 0x96b6, 0x0004, 0x1130, 0x2001, 0x0001, - 0x080c, 0x6656, 0x0804, 0xb2d3, 0x0005, 0x00e6, 0x2071, 0x1800, - 0x7090, 0x9086, 0x0074, 0x1540, 0x080c, 0xe8ed, 0x11b0, 0x6010, - 0x00b6, 0x2058, 0x7030, 0xd08c, 0x0128, 0xb800, 0xd0bc, 0x0110, - 0xc0c5, 0xb802, 0x00f9, 0x00be, 0x2001, 0x0006, 0x080c, 0x666a, - 0x080c, 0x3279, 0x080c, 0xb2d3, 0x0098, 0x2001, 0x000a, 0x080c, - 0x666a, 0x080c, 0x3279, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, - 0x9547, 0x080c, 0x9ab1, 0x0020, 0x2001, 0x0001, 0x080c, 0xbf7b, - 0x00ee, 0x0005, 0x00d6, 0xb800, 0xd084, 0x0160, 0x9006, 0x080c, - 0x6656, 0x2069, 0x1847, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, - 0x080c, 0x6696, 0x00de, 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011, - 0x1824, 0x2204, 0x9086, 0x0074, 0x1904, 0xbf50, 0x6010, 0x2058, - 0xbaa0, 0x9286, 0x007e, 0x1120, 0x080c, 0xc1ea, 0x0804, 0xbebd, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x0904, 0xbe5f, 0x00d6, 0x080c, - 0x7637, 0x01a0, 0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e, - 0x0904, 0xbe5e, 0x080c, 0x57e9, 0x1598, 0x6014, 0x2048, 0xa807, - 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x0450, 0x6010, 0x00b6, - 0x2058, 0xb910, 0x00be, 0x9186, 0x00ff, 0x0580, 0x0026, 0x2011, - 0x8008, 0x080c, 0x6ac7, 0x002e, 0x0548, 0x6014, 0x9005, 0x090c, - 0x0dc5, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, - 0x2001, 0x0030, 0x900e, 0x2011, 0x4009, 0x080c, 0xd6bd, 0x0040, - 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, - 0x6010, 0x2058, 0xb9a0, 0x0016, 0x080c, 0x3279, 0x080c, 0xb2d3, - 0x001e, 0x080c, 0x334c, 0x00de, 0x0804, 0xbf55, 0x00de, 0x080c, - 0xc1df, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014, - 0x9005, 0x01a8, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, - 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd6bd, - 0x0030, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x2001, - 0x0006, 0x080c, 0x666a, 0x080c, 0x3279, 0x080c, 0xb2d3, 0x0804, - 0xbf55, 0x080c, 0xbf63, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, - 0xd0f4, 0x01e8, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, - 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd6bd, 0x08f8, - 0x080c, 0xbf59, 0x0160, 0x9006, 0x080c, 0x6656, 0x2001, 0x0004, - 0x080c, 0x6696, 0x2001, 0x0007, 0x080c, 0x666a, 0x08a0, 0x2001, - 0x0004, 0x080c, 0x666a, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, - 0x9547, 0x080c, 0x9ab1, 0x0804, 0xbf55, 0xb85c, 0xd0e4, 0x0178, - 0x080c, 0xd4ee, 0x080c, 0x7637, 0x0118, 0xd0dc, 0x1904, 0xbe7f, - 0x2011, 0x1837, 0x2204, 0xc0ad, 0x2012, 0x0804, 0xbe7f, 0x080c, - 0xd52b, 0x2011, 0x1837, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, - 0xeab9, 0x000e, 0x1904, 0xbe7f, 0xc0b5, 0x2012, 0x2001, 0x0006, - 0x080c, 0x666a, 0x9006, 0x080c, 0x6656, 0x00c6, 0x2001, 0x180f, - 0x2004, 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, - 0x1800, 0x700c, 0x9084, 0x00ff, 0x78e6, 0x707e, 0x7010, 0x78ea, - 0x7082, 0x908c, 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, - 0x080c, 0x28bc, 0x00f6, 0x2100, 0x900e, 0x080c, 0x2873, 0x795e, - 0x00fe, 0x9186, 0x0081, 0x01f0, 0x2009, 0x0081, 0x00e0, 0x2009, - 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x78e7, 0x0000, 0x7932, - 0x7936, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x28bc, 0x00f6, - 0x2079, 0x1800, 0x7982, 0x2100, 0x900e, 0x797e, 0x080c, 0x2873, - 0x795e, 0x00fe, 0x8108, 0x080c, 0x66b9, 0x2b00, 0x00ce, 0x1904, - 0xbe7f, 0x6012, 0x2009, 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, - 0x027c, 0x210c, 0x918c, 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, - 0xb916, 0x2001, 0x0002, 0x080c, 0x666a, 0x6023, 0x0001, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0028, - 0x080c, 0xbcb6, 0x2001, 0x0001, 0x0431, 0x00de, 0x009e, 0x00be, - 0x0005, 0x2001, 0x1810, 0x2004, 0xd0a4, 0x0120, 0x2001, 0x1848, - 0x2004, 0xd0ac, 0x0005, 0x00e6, 0x080c, 0xefed, 0x0190, 0x2071, - 0x0260, 0x7108, 0x720c, 0x918c, 0x00ff, 0x1118, 0x9284, 0xff00, - 0x0140, 0x6010, 0x2058, 0xb8a0, 0x9084, 0xff80, 0x1110, 0xb912, - 0xba16, 0x00ee, 0x0005, 0x2030, 0x9005, 0x0158, 0x2001, 0x0007, - 0x080c, 0x666a, 0x080c, 0x57e9, 0x1120, 0x2001, 0x0007, 0x080c, - 0x6696, 0x2600, 0x9005, 0x11b0, 0x6014, 0x0096, 0x2048, 0xa868, - 0x009e, 0xd0fc, 0x1178, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, - 0xbba0, 0x00be, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4c44, - 0x004e, 0x003e, 0x080c, 0x3279, 0x6020, 0x9086, 0x000a, 0x1108, - 0x0005, 0x0804, 0xb2d3, 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, - 0x1800, 0x7090, 0x9086, 0x0014, 0x1904, 0xc05a, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x0904, 0xc00d, 0x00d6, 0x080c, 0x7637, 0x01a0, - 0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e, 0x0904, 0xc00c, - 0x080c, 0x57e9, 0x1598, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, - 0x0103, 0xa833, 0xdead, 0x0450, 0x6010, 0x00b6, 0x2058, 0xb910, - 0x00be, 0x9186, 0x00ff, 0x0580, 0x0026, 0x2011, 0x8008, 0x080c, - 0x6ac7, 0x002e, 0x0548, 0x6014, 0x9005, 0x090c, 0x0dc5, 0x2048, - 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, - 0x900e, 0x2011, 0x4009, 0x080c, 0xd6bd, 0x0040, 0x6014, 0x2048, - 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, - 0xb9a0, 0x0016, 0x080c, 0x3279, 0x080c, 0xb2d3, 0x001e, 0x080c, - 0x334c, 0x00de, 0x0804, 0xc05f, 0x00de, 0x080c, 0x57e9, 0x1170, - 0x6014, 0x9005, 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, - 0x2021, 0x0006, 0x080c, 0x4dfb, 0x004e, 0x003e, 0x00d6, 0x6010, - 0x2058, 0x080c, 0x67bf, 0x080c, 0xbde2, 0x00de, 0x080c, 0xc2b5, - 0x1588, 0x6010, 0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, - 0x080c, 0x666a, 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, - 0x4000, 0x080c, 0xd6bd, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0029, 0x0130, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, - 0x009e, 0x080c, 0x3279, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c, - 0xb2d3, 0x0028, 0x080c, 0xbcb6, 0x9006, 0x080c, 0xbf7b, 0x001e, - 0x002e, 0x00ee, 0x00be, 0x0005, 0x2011, 0x1824, 0x2204, 0x9086, - 0x0014, 0x1160, 0x2001, 0x0002, 0x080c, 0x666a, 0x6003, 0x0001, - 0x6007, 0x0001, 0x080c, 0x9547, 0x0804, 0x9ab1, 0x2001, 0x0001, - 0x0804, 0xbf7b, 0x2030, 0x2011, 0x1824, 0x2204, 0x9086, 0x0004, - 0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x666a, - 0x0804, 0xb2d3, 0x2001, 0x0001, 0x0804, 0xbf7b, 0x0002, 0xbd9f, - 0xc0a6, 0xbd9f, 0xc0e9, 0xbd9f, 0xc196, 0xc09b, 0xbda2, 0xbd9f, - 0xc1aa, 0xbd9f, 0xc1bc, 0x6604, 0x9686, 0x0003, 0x0904, 0xbfab, - 0x96b6, 0x001e, 0x1110, 0x080c, 0xb2d3, 0x0005, 0x00b6, 0x00d6, - 0x00c6, 0x080c, 0xc1ce, 0x11a0, 0x9006, 0x080c, 0x6656, 0x080c, - 0x3250, 0x080c, 0xd7f8, 0x2001, 0x0002, 0x080c, 0x666a, 0x6003, - 0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0428, - 0x2009, 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2058, - 0xb840, 0x9084, 0x00ff, 0x9005, 0x0180, 0x8001, 0xb842, 0x601b, - 0x000a, 0x0098, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x908e, - 0x1900, 0x0158, 0x908e, 0x1e00, 0x0990, 0x080c, 0x3250, 0x080c, - 0xd7f8, 0x2001, 0x0001, 0x080c, 0xbf7b, 0x00ce, 0x00de, 0x00be, - 0x0005, 0x0096, 0x00b6, 0x0026, 0x9016, 0x080c, 0xc1dc, 0x00d6, - 0x2069, 0x197c, 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0, - 0x9086, 0x007e, 0x1138, 0x2069, 0x1820, 0x2d04, 0x8000, 0x206a, - 0x00de, 0x0010, 0x00de, 0x0088, 0x9006, 0x080c, 0x6656, 0x2001, - 0x0002, 0x080c, 0x666a, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, - 0x9547, 0x080c, 0x9ab1, 0x0804, 0xc166, 0x080c, 0xd0d8, 0x01b0, - 0x6014, 0x2048, 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, - 0x0016, 0x2001, 0x0002, 0x080c, 0xd71a, 0x00b0, 0x6014, 0x2048, - 0xa864, 0xd0fc, 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e, - 0x2004, 0xd0dc, 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, - 0x9005, 0x1110, 0x9006, 0x0c38, 0x080c, 0xbcb6, 0x2009, 0x026e, - 0x2134, 0x96b4, 0x00ff, 0x9686, 0x0005, 0x0520, 0x9686, 0x000b, - 0x01c8, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, - 0x0009, 0x01c0, 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0190, - 0x2001, 0x0004, 0x080c, 0x666a, 0x2001, 0x0028, 0x601a, 0x6007, - 0x0052, 0x0020, 0x2001, 0x0001, 0x080c, 0xbf7b, 0x002e, 0x00be, - 0x009e, 0x0005, 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, 0x080c, - 0xd0d8, 0x0140, 0xa864, 0x9086, 0x0139, 0x0118, 0xa868, 0xd0fc, - 0x0108, 0x0c40, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, - 0x0138, 0x8001, 0xb842, 0x601b, 0x000a, 0x6007, 0x0016, 0x08f0, - 0xb8a0, 0x9086, 0x007e, 0x1138, 0x00e6, 0x2071, 0x1800, 0x080c, - 0x60c1, 0x00ee, 0x0010, 0x080c, 0x3250, 0x0860, 0x2001, 0x0004, - 0x080c, 0x666a, 0x080c, 0xc1dc, 0x1140, 0x6003, 0x0001, 0x6007, - 0x0003, 0x080c, 0x9547, 0x0804, 0x9ab1, 0x080c, 0xbcb6, 0x9006, - 0x0804, 0xbf7b, 0x0489, 0x1160, 0x2001, 0x0008, 0x080c, 0x666a, - 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x9547, 0x0804, 0x9ab1, - 0x2001, 0x0001, 0x0804, 0xbf7b, 0x00f9, 0x1160, 0x2001, 0x000a, - 0x080c, 0x666a, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9547, - 0x0804, 0x9ab1, 0x2001, 0x0001, 0x0804, 0xbf7b, 0x2009, 0x026e, - 0x2104, 0x9086, 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, - 0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6, - 0x00c6, 0x0016, 0x6110, 0x2158, 0x080c, 0x6733, 0x001e, 0x00ce, - 0x00be, 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, - 0x6010, 0x2058, 0x2009, 0x1837, 0x2104, 0x9085, 0x0003, 0x200a, - 0x080c, 0xc287, 0x0560, 0x2009, 0x1837, 0x2104, 0xc0cd, 0x200a, - 0x080c, 0x6a9f, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, - 0xec31, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, - 0x2009, 0x0001, 0x080c, 0x321b, 0x00e6, 0x2071, 0x1800, 0x080c, - 0x3000, 0x00ee, 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, - 0x080c, 0x334c, 0x8108, 0x1f04, 0xc220, 0x015e, 0x00ce, 0x080c, - 0xc1df, 0x2071, 0x0260, 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, - 0x1837, 0x200c, 0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, - 0x7038, 0xd0dc, 0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1837, - 0x2102, 0x9184, 0x0050, 0x9086, 0x0050, 0x05d0, 0x2079, 0x0100, - 0x2e04, 0x9084, 0x00ff, 0x2069, 0x181f, 0x206a, 0x78e6, 0x0006, - 0x8e70, 0x2e04, 0x2069, 0x1820, 0x206a, 0x78ea, 0x7832, 0x7836, - 0x2010, 0x9084, 0xff00, 0x001e, 0x9105, 0x2009, 0x182c, 0x200a, - 0x2200, 0x9084, 0x00ff, 0x2008, 0x080c, 0x28bc, 0x080c, 0x7637, - 0x0170, 0x2071, 0x0260, 0x2069, 0x1982, 0x7048, 0x206a, 0x704c, - 0x6806, 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, 0xd4ee, 0x0040, - 0x2001, 0x0006, 0x080c, 0x666a, 0x080c, 0x3279, 0x080c, 0xb2d3, - 0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x0096, - 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0x182c, 0x231c, 0x83ff, - 0x01f0, 0x2071, 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, - 0xff00, 0x9205, 0x9306, 0x1198, 0x2011, 0x0276, 0x20a9, 0x0004, - 0x2b48, 0x2019, 0x000a, 0x080c, 0xc379, 0x1148, 0x2011, 0x027a, - 0x20a9, 0x0004, 0x2019, 0x0006, 0x080c, 0xc379, 0x1100, 0x015e, - 0x00ee, 0x003e, 0x002e, 0x009e, 0x0005, 0x00e6, 0x2071, 0x0260, - 0x7034, 0x9086, 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, 0x1188, - 0x703c, 0xd0ec, 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, 0x1138, - 0x7054, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, 0x9085, - 0x0001, 0x00ee, 0x0005, 0x00e6, 0x0096, 0x00c6, 0x0076, 0x0056, - 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0x19f1, - 0x252c, 0x2021, 0x19f7, 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800, - 0x7254, 0x7074, 0x9202, 0x1a04, 0xc345, 0x080c, 0x8cf7, 0x0904, - 0xc33e, 0x080c, 0xec62, 0x0904, 0xc33e, 0x6720, 0x9786, 0x0007, - 0x0904, 0xc33e, 0x2500, 0x9c06, 0x0904, 0xc33e, 0x2400, 0x9c06, - 0x05e8, 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, 0x0130, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1580, 0x00c6, 0x6000, - 0x9086, 0x0004, 0x1110, 0x080c, 0x1a8e, 0x9786, 0x000a, 0x0148, - 0x080c, 0xd2e0, 0x1130, 0x00ce, 0x080c, 0xbcb6, 0x080c, 0xb306, - 0x00e8, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x01a8, 0x9786, 0x0003, - 0x1530, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, - 0x2048, 0x080c, 0x0fc0, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, - 0x6e92, 0x080c, 0xd2c3, 0x080c, 0xb306, 0x00ce, 0x9ce0, 0x0018, - 0x7068, 0x9c02, 0x1210, 0x0804, 0xc2e8, 0x012e, 0x000e, 0x002e, - 0x004e, 0x005e, 0x007e, 0x00ce, 0x009e, 0x00ee, 0x0005, 0x9786, - 0x0006, 0x1118, 0x080c, 0xebd4, 0x0c30, 0x9786, 0x0009, 0x1148, - 0x6000, 0x9086, 0x0004, 0x0d08, 0x2009, 0x004c, 0x080c, 0xb352, - 0x08e0, 0x9786, 0x000a, 0x0980, 0x0820, 0x220c, 0x2304, 0x9106, - 0x1130, 0x8210, 0x8318, 0x1f04, 0xc365, 0x9006, 0x0005, 0x2304, - 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, 0x0001, - 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, 0x908c, - 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, 0x20a9, - 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, 0x1dc8, - 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, 0x0218, - 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, 0x001e, - 0x01ce, 0x013e, 0x0005, 0x220c, 0x810f, 0x2304, 0x9106, 0x1130, - 0x8210, 0x8318, 0x1f04, 0xc3a3, 0x9006, 0x0005, 0x918d, 0x0001, - 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0dc5, 0x080c, 0xd2cf, - 0x0120, 0x080c, 0xd2e0, 0x0168, 0x0028, 0x080c, 0x3279, 0x080c, - 0xd2e0, 0x0138, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c, 0x9ab1, - 0x0005, 0x080c, 0xbcb6, 0x0cb0, 0x9182, 0x0054, 0x1220, 0x9182, - 0x0040, 0x0208, 0x000a, 0x0005, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, - 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3ea, - 0xc3ea, 0xc3ea, 0xc3ea, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3ea, 0xc3e8, - 0x080c, 0x0dc5, 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c, - 0x94ff, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005, - 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0040, 0x0804, 0xc482, - 0x9186, 0x0027, 0x1520, 0x080c, 0x99a5, 0x080c, 0x3250, 0x080c, - 0xd7f8, 0x0096, 0x6114, 0x2148, 0x080c, 0xd0d8, 0x0198, 0x080c, - 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0068, 0xa867, 0x0103, 0xa87b, - 0x0029, 0xa877, 0x0000, 0xa97c, 0xc1c5, 0xa97e, 0x080c, 0x6e9f, - 0x080c, 0xd2c3, 0x009e, 0x080c, 0xb2d3, 0x0804, 0x9ab1, 0x9186, - 0x0014, 0x1120, 0x6004, 0x9082, 0x0040, 0x00b8, 0x9186, 0x0046, - 0x0150, 0x9186, 0x0045, 0x0138, 0x9186, 0x0053, 0x0120, 0x9186, - 0x0048, 0x190c, 0x0dc5, 0x080c, 0xd809, 0x0130, 0x6000, 0x9086, - 0x0002, 0x1110, 0x0804, 0xc4c0, 0x0005, 0x0002, 0xc45c, 0xc45a, - 0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a, - 0xc45a, 0xc477, 0xc477, 0xc477, 0xc477, 0xc45a, 0xc477, 0xc45a, - 0xc477, 0xc45a, 0x080c, 0x0dc5, 0x080c, 0x99a5, 0x0096, 0x6114, - 0x2148, 0x080c, 0xd0d8, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, - 0xa877, 0x0000, 0xa880, 0xc0ec, 0xa882, 0x080c, 0x6e9f, 0x080c, - 0xd2c3, 0x009e, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x080c, - 0x99a5, 0x080c, 0xd2e0, 0x090c, 0xbcb6, 0x080c, 0xb2d3, 0x080c, - 0x9ab1, 0x0005, 0x0002, 0xc499, 0xc497, 0xc497, 0xc497, 0xc497, - 0xc497, 0xc497, 0xc497, 0xc497, 0xc497, 0xc497, 0xc4b0, 0xc4b0, - 0xc4b0, 0xc4b0, 0xc497, 0xc4ba, 0xc497, 0xc4b0, 0xc497, 0x080c, - 0x0dc5, 0x0096, 0x080c, 0x99a5, 0x6014, 0x2048, 0x2001, 0x1988, - 0x2004, 0x6042, 0xa97c, 0xd1ac, 0x0140, 0x6003, 0x0004, 0xa87c, - 0x9085, 0x0400, 0xa87e, 0x009e, 0x0005, 0x6003, 0x0002, 0x0cb8, - 0x080c, 0x99a5, 0x080c, 0xd7fb, 0x080c, 0xd800, 0x6003, 0x000f, - 0x0804, 0x9ab1, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x0804, 0x9ab1, - 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, - 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4de, 0xc5be, 0xc4dc, - 0xc5f2, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, - 0xc4dc, 0xc4dc, 0xc4dc, 0xc5f2, 0x080c, 0x0dc5, 0x00b6, 0x0096, - 0x6114, 0x2148, 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1528, 0x6010, - 0x2058, 0xb800, 0xd0bc, 0x1904, 0xc5ad, 0xa87b, 0x0000, 0xa867, - 0x0103, 0xae76, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, - 0x190c, 0xc78b, 0x080c, 0x6cb9, 0x6210, 0x2258, 0xba3c, 0x82ff, - 0x0110, 0x8211, 0xba3e, 0x7044, 0xd0e4, 0x1904, 0xc58e, 0x080c, - 0xb2d3, 0x009e, 0x00be, 0x0005, 0x968c, 0x0c00, 0x0150, 0x6010, - 0x2058, 0xb800, 0xd0bc, 0x1904, 0xc592, 0x7348, 0xab92, 0x734c, - 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0508, 0x9186, 0x0028, - 0x1118, 0xa87b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0xa87b, 0x0015, - 0xa87c, 0xd0ac, 0x0170, 0xa938, 0xaa34, 0x2100, 0x9205, 0x0148, - 0x7048, 0x9106, 0x1118, 0x704c, 0x9206, 0x0118, 0xa992, 0xaa8e, - 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, - 0x0000, 0xa867, 0x0103, 0xae76, 0x901e, 0xd6c4, 0x01d8, 0x9686, - 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0x0804, 0xc4e5, - 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, - 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, - 0xcc85, 0x003e, 0xd6cc, 0x0904, 0xc4fa, 0x7154, 0xa98a, 0x81ff, - 0x0904, 0xc4fa, 0x9192, 0x0021, 0x1278, 0x8304, 0x9098, 0x0018, - 0x2011, 0x0029, 0x080c, 0xcc85, 0x2011, 0x0205, 0x2013, 0x0000, - 0x080c, 0xd786, 0x0804, 0xc4fa, 0xa868, 0xd0fc, 0x0120, 0x2009, - 0x0020, 0xa98a, 0x0c50, 0x00a6, 0x2950, 0x080c, 0xcc24, 0x00ae, - 0x080c, 0xd786, 0x080c, 0xcc75, 0x0804, 0xc4fc, 0x080c, 0xd3d8, - 0x0804, 0xc509, 0xa87c, 0xd0ac, 0x0904, 0xc515, 0xa880, 0xd0bc, - 0x1904, 0xc515, 0x9684, 0x0400, 0x0130, 0xa838, 0xab34, 0x9305, - 0x0904, 0xc515, 0x00b8, 0x7348, 0xa838, 0x9306, 0x1198, 0x734c, - 0xa834, 0x931e, 0x0904, 0xc515, 0x0068, 0xa87c, 0xd0ac, 0x0904, - 0xc4ed, 0xa838, 0xa934, 0x9105, 0x0904, 0xc4ed, 0xa880, 0xd0bc, - 0x1904, 0xc4ed, 0x080c, 0xd412, 0x0804, 0xc509, 0x0096, 0x00f6, - 0x6003, 0x0003, 0x6007, 0x0043, 0x2079, 0x026c, 0x7c04, 0x7b00, - 0x7e0c, 0x7d08, 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0140, 0x6003, - 0x0002, 0x00fe, 0x009e, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, - 0xa9ac, 0x910a, 0x2300, 0xaab0, 0x9213, 0x2600, 0x9102, 0x2500, - 0x9203, 0x0e90, 0xac36, 0xab3a, 0xae46, 0xad4a, 0x00fe, 0x6043, - 0x0000, 0x2c10, 0x080c, 0x1be0, 0x080c, 0x9564, 0x080c, 0x9bd3, - 0x009e, 0x0005, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xc60f, 0xc60f, 0xc60f, 0xc60f, 0xc60f, - 0xc611, 0xc6a7, 0xc60f, 0xc60f, 0xc6be, 0xc74e, 0xc60f, 0xc60f, - 0xc60f, 0xc60f, 0xc763, 0xc60f, 0xc60f, 0xc60f, 0xc60f, 0x080c, - 0x0dc5, 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114, - 0x2150, 0x7644, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, - 0x6210, 0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, - 0x00be, 0x86ff, 0x0904, 0xc6a2, 0x9694, 0xff00, 0x9284, 0x0c00, - 0x0120, 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, - 0xc6a2, 0x080c, 0x100e, 0x090c, 0x0dc5, 0x2900, 0xb07a, 0xb77c, - 0xc7cd, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, 0xa86e, - 0xb070, 0xa872, 0xae76, 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, - 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, - 0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, - 0x0015, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, - 0x0000, 0xaf7e, 0xb080, 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, - 0x0190, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, - 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, - 0x080c, 0xcc85, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, - 0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, - 0x0029, 0x080c, 0xcc85, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, - 0xb068, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, - 0x080c, 0xcc24, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x00f6, - 0x00a6, 0x6003, 0x0003, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, - 0x7d08, 0x6014, 0x2050, 0xb436, 0xb33a, 0xb646, 0xb54a, 0x00ae, - 0x00fe, 0x2c10, 0x080c, 0x1be0, 0x0804, 0xa6b6, 0x6003, 0x0002, - 0x6004, 0x9086, 0x0040, 0x11c8, 0x0096, 0x6014, 0x2048, 0xa87c, - 0xd0ac, 0x0160, 0x601c, 0xd084, 0x1130, 0x00f6, 0x2c00, 0x2078, - 0x080c, 0x1768, 0x00fe, 0x6003, 0x0004, 0x0010, 0x6003, 0x0002, - 0x009e, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0096, 0x2001, 0x1988, - 0x2004, 0x6042, 0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6114, 0x2148, - 0xa97c, 0xd1e4, 0x0904, 0xc749, 0xd1cc, 0x05c8, 0xa978, 0xa868, - 0xd0fc, 0x0540, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, 0xa860, - 0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0x810e, 0x810e, 0x810f, - 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0019, 0x2098, - 0x0156, 0x20a9, 0x0020, 0x4003, 0x015e, 0x000e, 0xa882, 0x000e, - 0xc0cc, 0xa87e, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0fc0, - 0x001e, 0x0458, 0x0016, 0x080c, 0x0fc0, 0x009e, 0xa87c, 0xc0cc, - 0xa87e, 0xa974, 0x0016, 0x080c, 0xcc75, 0x001e, 0x00f0, 0xa867, - 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0180, 0x9086, - 0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, 0xd1dc, 0x0118, 0xa87b, - 0x0015, 0x0038, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, - 0x0000, 0x0016, 0x080c, 0x6cb9, 0x001e, 0xd1e4, 0x1120, 0x080c, - 0xb2d3, 0x009e, 0x0005, 0x080c, 0xd3d8, 0x0cd8, 0x6004, 0x9086, - 0x0040, 0x1120, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x2019, 0x0001, - 0x080c, 0xaa49, 0x6003, 0x0002, 0x080c, 0xd800, 0x080c, 0x9a61, - 0x080c, 0x9bd3, 0x0005, 0x6004, 0x9086, 0x0040, 0x1120, 0x080c, - 0x99a5, 0x080c, 0x9ab1, 0x2019, 0x0001, 0x080c, 0xaa49, 0x080c, - 0x9a61, 0x080c, 0x3250, 0x080c, 0xd7f8, 0x0096, 0x6114, 0x2148, - 0x080c, 0xd0d8, 0x0150, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, - 0x0000, 0x080c, 0x6e9f, 0x080c, 0xd2c3, 0x009e, 0x080c, 0xb2d3, - 0x080c, 0x9bd3, 0x0005, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, - 0x0007, 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, - 0x2009, 0x1a7d, 0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, - 0xa88e, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, - 0x000a, 0x0005, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7c0, - 0xc7be, 0xc7be, 0xc866, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7be, - 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc998, 0x080c, 0x0dc5, - 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114, 0x2150, - 0x7644, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, - 0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, - 0x86ff, 0x0904, 0xc85f, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, - 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xc85f, - 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676, - 0x0c38, 0x080c, 0x100e, 0x090c, 0x0dc5, 0x2900, 0xb07a, 0xb77c, - 0x97bd, 0x0200, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, - 0xa86e, 0xb070, 0xa872, 0x7044, 0x9084, 0xf000, 0x9635, 0xae76, - 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, - 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0xa87b, - 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, 0x0015, 0x0038, 0xd6d4, - 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080, - 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86, - 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, - 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xcc85, 0x003e, - 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, - 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xcc85, - 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, - 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, 0xcc24, 0x080c, - 0x1a5a, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x2001, 0x1988, - 0x2004, 0x6042, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, - 0x1118, 0xa87c, 0xc0dc, 0xa87e, 0x6003, 0x0002, 0xa97c, 0xd1e4, - 0x0904, 0xc993, 0x6043, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xc962, 0xa978, 0xa868, - 0xd0fc, 0x0904, 0xc923, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, - 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, - 0xc8f0, 0x9086, 0x0028, 0x1904, 0xc8dc, 0xa87b, 0x001c, 0xb07b, - 0x001c, 0x0804, 0xc8f8, 0x6024, 0xd0f4, 0x11d0, 0xa838, 0xaa34, - 0x9205, 0x09c8, 0xa838, 0xaa90, 0x9206, 0x1120, 0xa88c, 0xaa34, - 0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, 0xa9ac, 0xa834, 0x9102, - 0x603a, 0xa9b0, 0xa838, 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026, - 0x6010, 0x00b6, 0x2058, 0xb83c, 0x8000, 0xb83e, 0x00be, 0x9006, - 0xa876, 0xa892, 0xa88e, 0xa87c, 0xc0e4, 0xa87e, 0xd0cc, 0x0140, - 0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fc0, 0x009e, - 0x080c, 0xd412, 0x0804, 0xc993, 0xd1dc, 0x0158, 0xa87b, 0x0015, - 0xb07b, 0x0015, 0x080c, 0xd6a6, 0x0118, 0xb174, 0xc1dc, 0xb176, - 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc78b, - 0xa87c, 0xb07e, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0019, 0x20a0, 0x20a9, 0x0020, 0x8a06, 0x8006, - 0x8007, 0x9094, 0x003f, 0x22e0, 0x9084, 0xffc0, 0x9080, 0x0019, - 0x2098, 0x4003, 0x00ae, 0x000e, 0xa882, 0x000e, 0xc0cc, 0xa87e, - 0x080c, 0xd786, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0fc0, - 0x001e, 0x0804, 0xc98f, 0x0016, 0x00a6, 0x2150, 0xb174, 0x9184, - 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, 0x0028, 0x1128, 0xa87b, - 0x001c, 0xb07b, 0x001c, 0x00e0, 0xd1dc, 0x0158, 0xa87b, 0x0015, - 0xb07b, 0x0015, 0x080c, 0xd6a6, 0x0118, 0xb174, 0xc1dc, 0xb176, - 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040, - 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc78b, - 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa87c, 0xb07e, 0x00ae, 0x080c, - 0x0fc0, 0x009e, 0x080c, 0xd786, 0xa974, 0x0016, 0x080c, 0xcc75, - 0x001e, 0x0468, 0xa867, 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, - 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00d0, - 0xd1dc, 0x0148, 0xa87b, 0x0015, 0x080c, 0xd6a6, 0x0118, 0xa974, - 0xc1dc, 0xa976, 0x0078, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0050, - 0xa87b, 0x0000, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, - 0x190c, 0xc78b, 0xa974, 0x0016, 0x080c, 0x6cb9, 0x001e, 0xd1e4, - 0x1120, 0x080c, 0xb2d3, 0x009e, 0x0005, 0x080c, 0xd3d8, 0x0cd8, - 0x6114, 0x0096, 0x2148, 0xa97c, 0xd1e4, 0x190c, 0x1a7a, 0x009e, - 0x0005, 0x080c, 0x99a5, 0x0010, 0x080c, 0x9a61, 0x080c, 0xd0d8, - 0x01f0, 0x0096, 0x6114, 0x2148, 0x080c, 0xd2e0, 0x1118, 0x080c, - 0xbcb6, 0x00a0, 0xa867, 0x0103, 0x2009, 0x180c, 0x210c, 0xd18c, - 0x11b8, 0xd184, 0x1190, 0x6108, 0xa97a, 0x918e, 0x0029, 0x1110, - 0x080c, 0xef85, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x009e, 0x080c, - 0xb2d3, 0x080c, 0x9ab1, 0x0804, 0x9bd3, 0xa87b, 0x0004, 0x0c90, - 0xa87b, 0x0004, 0x0c78, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, - 0xc9f1, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, - 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0x080c, - 0x0dc5, 0x080c, 0x57dd, 0x01f8, 0x6014, 0x7144, 0x918c, 0x0fff, - 0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, 0x00ff, 0x0096, 0x904d, - 0x0188, 0xa87b, 0x0000, 0xa864, 0x9086, 0x0139, 0x0128, 0xa867, - 0x0103, 0xa976, 0xaa96, 0x0030, 0xa897, 0x4000, 0xa99a, 0xaa9e, - 0x080c, 0x6e9f, 0x009e, 0x0804, 0xb2d3, 0x9182, 0x0085, 0x0002, - 0xca27, 0xca25, 0xca25, 0xca33, 0xca25, 0xca25, 0xca25, 0xca25, - 0xca25, 0xca25, 0xca25, 0xca25, 0xca25, 0x080c, 0x0dc5, 0x6003, - 0x0001, 0x6106, 0x080c, 0x94ff, 0x0126, 0x2091, 0x8000, 0x080c, - 0x9ab1, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, - 0x0260, 0x7224, 0x6216, 0x7220, 0x080c, 0xd0c6, 0x01f8, 0x2268, - 0x6800, 0x9086, 0x0000, 0x01d0, 0x6010, 0x6d10, 0x952e, 0x11b0, - 0x00c6, 0x2d60, 0x00d6, 0x080c, 0xcce6, 0x00de, 0x00ce, 0x0158, - 0x702c, 0xd084, 0x1118, 0x080c, 0xccb0, 0x0010, 0x6803, 0x0002, - 0x6007, 0x0086, 0x0028, 0x080c, 0xccd2, 0x0d90, 0x6007, 0x0087, - 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x7220, 0x080c, - 0xd0c6, 0x0178, 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x0140, 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, 0xd412, - 0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, - 0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dc5, 0x908a, 0x0092, - 0x1a0c, 0x0dc5, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, 0x0120, - 0x9186, 0x0014, 0x190c, 0x0dc5, 0x080c, 0x99a5, 0x0096, 0x6014, - 0x2048, 0x080c, 0xd0d8, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0029, 0x080c, 0x6e9f, 0x009e, 0x080c, 0xb306, 0x0804, - 0x9ab1, 0xcab6, 0xcab8, 0xcab8, 0xcab6, 0xcab6, 0xcab6, 0xcab6, - 0xcab6, 0xcab6, 0xcab6, 0xcab6, 0xcab6, 0xcab6, 0x080c, 0x0dc5, - 0x080c, 0x99a5, 0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005, 0x9186, - 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x04b8, 0x9186, - 0x0027, 0x11f8, 0x080c, 0x99a5, 0x080c, 0x3250, 0x080c, 0xd7f8, - 0x0096, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0150, 0xa867, 0x0103, - 0xa877, 0x0000, 0xa87b, 0x0029, 0x080c, 0x6e9f, 0x080c, 0xd2c3, - 0x009e, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x080c, 0xb36d, - 0x0ce0, 0x9186, 0x0014, 0x1dd0, 0x080c, 0x99a5, 0x0096, 0x6014, - 0x2048, 0x080c, 0xd0d8, 0x0d60, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, 0x08f0, 0x0002, 0xcb0e, - 0xcb0c, 0xcb0c, 0xcb0c, 0xcb0c, 0xcb0c, 0xcb26, 0xcb0c, 0xcb0c, - 0xcb0c, 0xcb0c, 0xcb0c, 0xcb0c, 0x080c, 0x0dc5, 0x080c, 0x99a5, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x2001, 0x1986, 0x0010, 0x2001, 0x1987, 0x2004, - 0x601a, 0x6003, 0x000c, 0x080c, 0x9ab1, 0x0005, 0x080c, 0x99a5, - 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, - 0x0035, 0x1118, 0x2001, 0x1986, 0x0010, 0x2001, 0x1987, 0x2004, - 0x601a, 0x6003, 0x000e, 0x080c, 0x9ab1, 0x0005, 0x9182, 0x0092, - 0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, 0xb36d, 0xcb54, - 0xcb54, 0xcb54, 0xcb54, 0xcb56, 0xcba3, 0xcb54, 0xcb54, 0xcb54, - 0xcb54, 0xcb54, 0xcb54, 0xcb54, 0x080c, 0x0dc5, 0x0096, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, - 0x009e, 0x0804, 0xcbb7, 0x080c, 0xd0d8, 0x1118, 0x080c, 0xd2c3, - 0x0068, 0x6014, 0x2048, 0xa87c, 0xd0e4, 0x1110, 0x080c, 0xd2c3, - 0xa867, 0x0103, 0x080c, 0xd7c3, 0x080c, 0x6e9f, 0x00d6, 0x2c68, - 0x080c, 0xb27d, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, - 0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, - 0x613e, 0x6910, 0x6112, 0x080c, 0xd554, 0x6954, 0x6156, 0x6023, - 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x2d60, 0x00de, 0x080c, - 0xb2d3, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x05a0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, - 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6, - 0x2c68, 0x080c, 0xd759, 0x11f0, 0x080c, 0xb27d, 0x01d8, 0x6106, - 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, - 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, - 0x693c, 0x613e, 0x6954, 0x6156, 0x080c, 0xd554, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x2d60, 0x00de, 0x0804, 0xb2d3, 0x0096, 0x6014, - 0x2048, 0x080c, 0xd0d8, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, - 0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, - 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xd3d4, 0xa877, - 0x0000, 0x080c, 0x6e9f, 0x080c, 0xd2c3, 0x009e, 0x0804, 0xb2d3, - 0x0016, 0x0096, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0140, 0xa867, - 0x0103, 0xa87b, 0x0028, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x009e, - 0x001e, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, - 0x0027, 0x0118, 0x080c, 0xb36d, 0x0030, 0x080c, 0x99a5, 0x080c, - 0xb306, 0x080c, 0x9ab1, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, - 0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, - 0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, - 0x080c, 0xcc85, 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c, - 0x0fc0, 0x080c, 0x100e, 0x0520, 0x8528, 0xa867, 0x0110, 0xa86b, - 0x0000, 0x2920, 0xb406, 0x968a, 0x003d, 0x1228, 0x2608, 0x2011, - 0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, - 0x2011, 0x001b, 0x0451, 0x0c28, 0x2001, 0x0205, 0x2003, 0x0000, - 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, 0x95ac, 0x0000, 0x0048, - 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, - 0xb566, 0x009e, 0x006e, 0x005e, 0x0005, 0x00a6, 0x89ff, 0x0158, - 0xa804, 0x9055, 0x0130, 0xa807, 0x0000, 0x080c, 0x6e9f, 0x2a48, - 0x0cb8, 0x080c, 0x6e9f, 0x00ae, 0x0005, 0x00f6, 0x2079, 0x0200, - 0x7814, 0x9085, 0x0080, 0x7816, 0xd184, 0x0108, 0x8108, 0x810c, - 0x20a9, 0x0001, 0xa860, 0x20e8, 0xa85c, 0x9200, 0x20a0, 0x20e1, - 0x0000, 0x2300, 0x9e00, 0x2098, 0x4003, 0x8318, 0x9386, 0x0020, - 0x1148, 0x2018, 0x2300, 0x9e00, 0x2098, 0x7814, 0x8000, 0x9085, - 0x0080, 0x7816, 0x8109, 0x1d80, 0x7817, 0x0000, 0x00fe, 0x0005, - 0x6920, 0x9186, 0x0003, 0x0118, 0x9186, 0x0002, 0x11d0, 0x00c6, - 0x00d6, 0x00e6, 0x2d60, 0x0096, 0x6014, 0x2048, 0x080c, 0xd0d8, - 0x0150, 0x2001, 0x0006, 0xa980, 0xc1d5, 0x080c, 0x710b, 0x080c, - 0x6e92, 0x080c, 0xd2c3, 0x009e, 0x080c, 0xb306, 0x00ee, 0x00de, - 0x00ce, 0x0005, 0x00c6, 0x702c, 0xd084, 0x1170, 0x6008, 0x2060, - 0x6020, 0x9086, 0x0002, 0x1140, 0x6104, 0x9186, 0x0085, 0x0118, - 0x9186, 0x008b, 0x1108, 0x9006, 0x00ce, 0x0005, 0x0066, 0x0126, - 0x2091, 0x8000, 0x2031, 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, - 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, - 0x0000, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, - 0xcd1d, 0xcd1d, 0xcd18, 0xcd3f, 0xcd0f, 0xcd18, 0xcd3f, 0xcd18, - 0xcd18, 0x9265, 0xcd18, 0xcd18, 0xcd18, 0xcd0f, 0xcd0f, 0x080c, - 0x0dc5, 0x0036, 0x2019, 0x0010, 0x080c, 0xe746, 0x003e, 0x0005, - 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x0096, 0x86ff, 0x11d8, - 0x6014, 0x2048, 0x080c, 0xd0d8, 0x01c0, 0xa864, 0x9086, 0x0139, - 0x1128, 0xa87b, 0x0005, 0xa883, 0x0000, 0x0028, 0x900e, 0x2001, - 0x0005, 0x080c, 0x710b, 0x080c, 0xd3d4, 0x080c, 0x6e92, 0x080c, - 0xb306, 0x9085, 0x0001, 0x009e, 0x0005, 0x9006, 0x0ce0, 0x6000, - 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0002, 0xcd55, 0xcd85, 0xcd57, - 0xcda6, 0xcd80, 0xcd55, 0xcd18, 0xcd1d, 0xcd1d, 0xcd18, 0xcd18, - 0xcd18, 0xcd18, 0xcd18, 0xcd18, 0xcd18, 0x080c, 0x0dc5, 0x86ff, - 0x1520, 0x6020, 0x9086, 0x0006, 0x0500, 0x0096, 0x6014, 0x2048, - 0x080c, 0xd0d8, 0x0168, 0xa87c, 0xd0cc, 0x0140, 0x0096, 0xc0cc, - 0xa87e, 0xa878, 0x2048, 0x080c, 0x0fc0, 0x009e, 0x080c, 0xd3d4, - 0x009e, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0002, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x9085, 0x0001, 0x0005, - 0x0066, 0x080c, 0x1a8e, 0x006e, 0x0890, 0x00e6, 0x2071, 0x19e8, - 0x7024, 0x9c06, 0x1120, 0x080c, 0xa9d3, 0x00ee, 0x0840, 0x6020, - 0x9084, 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, - 0x0001, 0x2c40, 0x080c, 0xaafb, 0x009e, 0x008e, 0x0010, 0x080c, - 0xa8d0, 0x00ee, 0x1904, 0xcd57, 0x0804, 0xcd18, 0x0036, 0x00e6, - 0x2071, 0x19e8, 0x703c, 0x9c06, 0x1138, 0x901e, 0x080c, 0xaa49, - 0x00ee, 0x003e, 0x0804, 0xcd57, 0x080c, 0xac2b, 0x00ee, 0x003e, - 0x1904, 0xcd57, 0x0804, 0xcd18, 0x00c6, 0x6020, 0x9084, 0x000f, - 0x0013, 0x00ce, 0x0005, 0xcdd9, 0xcea3, 0xd011, 0xcde3, 0xb306, - 0xcdd9, 0xe73c, 0xd805, 0xcea3, 0x9237, 0xd09d, 0xcdd2, 0xcdd2, - 0xcdd2, 0xcdd2, 0x080c, 0x0dc5, 0x080c, 0xd2e0, 0x1110, 0x080c, - 0xbcb6, 0x0005, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0804, 0xb2d3, - 0x601b, 0x0001, 0x0005, 0x080c, 0xd0d8, 0x0130, 0x6014, 0x0096, - 0x2048, 0x2c00, 0xa896, 0x009e, 0x6000, 0x908a, 0x0010, 0x1a0c, - 0x0dc5, 0x0002, 0xce02, 0xce04, 0xce28, 0xce3c, 0xce62, 0xce02, - 0xcdd9, 0xcdd9, 0xcdd9, 0xce3c, 0xce3c, 0xce02, 0xce02, 0xce02, - 0xce02, 0xce46, 0x080c, 0x0dc5, 0x00e6, 0x6014, 0x0096, 0x2048, - 0xa880, 0xc0b5, 0xa882, 0x009e, 0x2071, 0x19e8, 0x7024, 0x9c06, - 0x01a0, 0x080c, 0xa8d0, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003, - 0x000b, 0x6023, 0x0002, 0x2001, 0x1987, 0x2004, 0x601a, 0x080c, - 0x94ff, 0x080c, 0x9ab1, 0x00ee, 0x0005, 0x601b, 0x0001, 0x0cd8, - 0x0096, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x080c, - 0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c, - 0x94ff, 0x080c, 0x9ab1, 0x0005, 0x0096, 0x601b, 0x0001, 0x6014, - 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x0005, 0x080c, 0x57dd, - 0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, 0xa864, 0xa867, 0x0103, - 0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, 0xa867, 0x0139, 0xa87b, - 0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, 0x080c, 0x6e9f, 0x009e, - 0x0804, 0xb2d3, 0x6014, 0x0096, 0x904d, 0x05c0, 0xa97c, 0xd1e4, - 0x05a8, 0x2001, 0x180f, 0x2004, 0xd0c4, 0x0110, 0x009e, 0x0005, - 0xa884, 0x009e, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, - 0x0030, 0x2c08, 0x080c, 0x1611, 0x2001, 0x030c, 0x2004, 0x9086, - 0x0041, 0x1198, 0x6014, 0x0096, 0x904d, 0x090c, 0x0dc5, 0xa880, - 0xd0f4, 0x1130, 0xc0f5, 0xa882, 0x009e, 0x601b, 0x0002, 0x0068, - 0x009e, 0x00c6, 0x080c, 0x236e, 0x00ce, 0x6000, 0x9086, 0x0004, - 0x1120, 0x2009, 0x0048, 0x080c, 0xb352, 0x0005, 0x009e, 0x080c, - 0x1a8e, 0x0804, 0xce28, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0dc5, - 0x000b, 0x0005, 0xceba, 0xcde0, 0xcebc, 0xceba, 0xcebc, 0xcebc, - 0xcdda, 0xceba, 0xcdd4, 0xcdd4, 0xceba, 0xceba, 0xceba, 0xceba, - 0xceba, 0xceba, 0x080c, 0x0dc5, 0x6010, 0x00b6, 0x2058, 0xb804, - 0x9084, 0x00ff, 0x00be, 0x908a, 0x000c, 0x1a0c, 0x0dc5, 0x00b6, - 0x0013, 0x00be, 0x0005, 0xced7, 0xcfa8, 0xced9, 0xcf19, 0xced9, - 0xcf19, 0xced9, 0xcee7, 0xced7, 0xcf19, 0xced7, 0xcf08, 0x080c, - 0x0dc5, 0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, 0x0004, 0x05a8, - 0x908e, 0x0002, 0x0590, 0x908e, 0x0052, 0x0904, 0xcfa4, 0x6004, - 0x080c, 0xd2e0, 0x0904, 0xcfc1, 0x908e, 0x0004, 0x1110, 0x080c, - 0x3279, 0x908e, 0x0021, 0x0904, 0xcfc5, 0x908e, 0x0022, 0x0904, - 0xd00c, 0x908e, 0x003d, 0x0904, 0xcfc5, 0x908e, 0x0039, 0x0904, - 0xcfc9, 0x908e, 0x0035, 0x0904, 0xcfc9, 0x908e, 0x001e, 0x0178, - 0x908e, 0x0001, 0x1140, 0x6010, 0x2058, 0xb804, 0x9084, 0x00ff, - 0x9086, 0x0006, 0x0110, 0x080c, 0x3250, 0x080c, 0xbcb6, 0x0804, - 0xb306, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xcf95, - 0x9186, 0x0002, 0x1904, 0xcf6a, 0x2001, 0x1837, 0x2004, 0xd08c, - 0x11c8, 0x080c, 0x7637, 0x11b0, 0x080c, 0xd7e3, 0x0138, 0x080c, - 0x765a, 0x1120, 0x080c, 0x7541, 0x0804, 0xcff5, 0x2001, 0x197d, - 0x2003, 0x0001, 0x2001, 0x1800, 0x2003, 0x0001, 0x080c, 0x7563, - 0x0804, 0xcff5, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x0080, 0x0130, - 0x2001, 0x1837, 0x2004, 0xd0ac, 0x1904, 0xcff5, 0xb8a0, 0x9082, - 0x0081, 0x1a04, 0xcff5, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, - 0x8001, 0xb842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, - 0x6043, 0x0000, 0x080c, 0xb27d, 0x0128, 0x2b00, 0x6012, 0x6023, - 0x0001, 0x0458, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a0, - 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, 0x1837, - 0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, 0x60c1, - 0x00ee, 0x080c, 0xbcb6, 0x0030, 0x080c, 0xbcb6, 0x080c, 0x3250, - 0x080c, 0xd7f8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x3279, - 0x012e, 0x00ee, 0x080c, 0xb306, 0x0005, 0x2001, 0x0002, 0x080c, - 0x666a, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c, - 0x9ab1, 0x00de, 0x00ce, 0x0c80, 0x080c, 0x3279, 0x0804, 0xcf15, - 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2058, - 0xb840, 0x9084, 0x00ff, 0x9005, 0x0904, 0xcf6a, 0x8001, 0xb842, - 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x00de, 0x00ce, - 0x0898, 0x080c, 0xbcb6, 0x0804, 0xcf17, 0x080c, 0xbcf2, 0x0804, - 0xcf17, 0x00d6, 0x2c68, 0x6104, 0x080c, 0xd759, 0x00de, 0x0118, - 0x080c, 0xb2d3, 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, - 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x603c, 0x600a, 0x2001, 0x1987, 0x2004, 0x601a, 0x602c, 0x2c08, - 0x2060, 0x6024, 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160, - 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005, 0x00de, 0x00ce, 0x080c, - 0xbcb6, 0x080c, 0x3250, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, - 0x3279, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043, - 0x0000, 0x012e, 0x00ee, 0x0005, 0x080c, 0xb708, 0x1904, 0xcfc1, - 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0096, 0x00d6, - 0x001b, 0x00de, 0x009e, 0x0005, 0xd02c, 0xd02c, 0xd02c, 0xd02c, - 0xd02c, 0xd02c, 0xd02c, 0xd02c, 0xd02c, 0xcdd9, 0xd02c, 0xcde0, - 0xd02e, 0xcde0, 0xd048, 0xd02c, 0x080c, 0x0dc5, 0x6004, 0x9086, - 0x008b, 0x01b0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, - 0x1130, 0x602c, 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, 0x6007, - 0x008b, 0x6003, 0x000d, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005, - 0x080c, 0xd7d7, 0x0118, 0x080c, 0xd7ea, 0x0010, 0x080c, 0xd7f8, - 0x080c, 0xd2c3, 0x080c, 0xd0d8, 0x0570, 0x080c, 0x3250, 0x080c, - 0xd0d8, 0x0168, 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, 0x0006, - 0xa877, 0x0000, 0xa880, 0xc0ed, 0xa882, 0x080c, 0x6e9f, 0x2c68, - 0x080c, 0xb27d, 0x0150, 0x6810, 0x6012, 0x080c, 0xd554, 0x00c6, - 0x2d60, 0x080c, 0xb306, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, - 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547, - 0x080c, 0x9ab1, 0x00c8, 0x080c, 0xd7d7, 0x0138, 0x6034, 0x9086, - 0x4000, 0x1118, 0x080c, 0x3250, 0x08d0, 0x6034, 0x908c, 0xff00, - 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, - 0x3250, 0x0868, 0x080c, 0xb306, 0x0005, 0x6000, 0x908a, 0x0010, - 0x1a0c, 0x0dc5, 0x0002, 0xd0b3, 0xd0b3, 0xd0b7, 0xd0b5, 0xd0c1, - 0xd0b3, 0xd0b3, 0xb306, 0xd0b3, 0xd0b3, 0xd0b3, 0xd0b3, 0xd0b3, - 0xd0b3, 0xd0b3, 0xd0b3, 0x080c, 0x0dc5, 0x080c, 0xac2b, 0x6114, - 0x0096, 0x2148, 0xa87b, 0x0006, 0x080c, 0x6e9f, 0x009e, 0x0804, - 0xb2d3, 0x601c, 0xd084, 0x190c, 0x1a8e, 0x0c88, 0x9284, 0x0007, - 0x1158, 0x9282, 0x1cd0, 0x0240, 0x2001, 0x181a, 0x2004, 0x9202, - 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0096, 0x0028, - 0x0096, 0x0006, 0x6014, 0x2048, 0x000e, 0x0006, 0x9984, 0xf000, - 0x9086, 0xf000, 0x0110, 0x080c, 0x10b9, 0x000e, 0x009e, 0x0005, - 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, 0x2061, - 0x1cd0, 0x2071, 0x1800, 0x7354, 0x7074, 0x9302, 0x1640, 0x6020, - 0x9206, 0x11f8, 0x080c, 0xd7e3, 0x0180, 0x9286, 0x0001, 0x1168, - 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, 0x3250, 0x080c, 0xd7f8, - 0x00c6, 0x080c, 0xb306, 0x00ce, 0x0060, 0x080c, 0xd4ce, 0x0148, - 0x080c, 0xd2e0, 0x1110, 0x080c, 0xbcb6, 0x00c6, 0x080c, 0xb2d3, - 0x00ce, 0x9ce0, 0x0018, 0x7068, 0x9c02, 0x1208, 0x08a0, 0x012e, - 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, - 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, 0x2061, 0x1ab7, 0x6112, - 0x080c, 0x3250, 0x9006, 0x0010, 0x9085, 0x0001, 0x001e, 0x00ce, - 0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb27d, - 0x01b0, 0x6656, 0x2b00, 0x6012, 0x080c, 0x57dd, 0x0118, 0x080c, - 0xd207, 0x0168, 0x080c, 0xd554, 0x6023, 0x0003, 0x2009, 0x004b, - 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, - 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0xbaa0, 0x080c, 0xb325, - 0x0560, 0x6057, 0x0000, 0x2b00, 0x6012, 0x080c, 0xd554, 0x6023, - 0x0003, 0x0016, 0x080c, 0x96a4, 0x0076, 0x903e, 0x080c, 0x9577, - 0x2c08, 0x080c, 0xe91c, 0x007e, 0x001e, 0xd184, 0x0128, 0x080c, - 0xb2d3, 0x9085, 0x0001, 0x0070, 0x080c, 0x57dd, 0x0128, 0xd18c, - 0x1170, 0x080c, 0xd207, 0x0148, 0x2009, 0x004c, 0x080c, 0xb352, - 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2900, - 0x6016, 0x0c90, 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, - 0x00c6, 0x0046, 0x0016, 0x080c, 0xb27d, 0x2c78, 0x05a0, 0x7e56, - 0x2b00, 0x7812, 0x7823, 0x0003, 0x0016, 0x2021, 0x0005, 0x080c, - 0xd219, 0x001e, 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148, - 0x2001, 0x1980, 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0xb2d3, - 0x00d0, 0x2001, 0x197f, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, - 0xb2d3, 0x0088, 0x2f60, 0x080c, 0x57dd, 0x0138, 0xd18c, 0x1118, - 0x04f1, 0x0148, 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, 0x080c, - 0xb352, 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, - 0x00f6, 0x00c6, 0x0046, 0x080c, 0xb27d, 0x2c78, 0x0508, 0x7e56, - 0x2b00, 0x7812, 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, 0x0489, - 0x009e, 0x2001, 0x197e, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, - 0xb2d3, 0x0060, 0x2f60, 0x080c, 0x57dd, 0x0120, 0xd18c, 0x1160, - 0x0071, 0x0130, 0x2009, 0x0052, 0x080c, 0xb352, 0x9085, 0x0001, - 0x004e, 0x00ce, 0x00fe, 0x0005, 0x2900, 0x7816, 0x0c98, 0x00c6, - 0x080c, 0x4be4, 0x00ce, 0x1120, 0x080c, 0xb2d3, 0x9006, 0x0005, - 0xa867, 0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, 0x0001, - 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x6858, - 0x0158, 0x2001, 0xd21e, 0x0006, 0x900e, 0x2400, 0x080c, 0x710b, - 0x080c, 0x6e9f, 0x000e, 0x0807, 0x2418, 0x080c, 0x993f, 0xbaa0, - 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x96bc, - 0x008e, 0x080c, 0x9577, 0x2f08, 0x2648, 0x080c, 0xe91c, 0xb93c, - 0x81ff, 0x090c, 0x978f, 0x080c, 0x9ab1, 0x012e, 0x007e, 0x009e, - 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb27d, 0x0190, - 0x660a, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900, - 0x6016, 0x2009, 0x001f, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0xb325, 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, 0xd554, - 0x6023, 0x0008, 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, 0x1768, - 0x00fe, 0x2009, 0x0021, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, 0x0126, - 0x0016, 0x2091, 0x8000, 0x080c, 0xb27d, 0x0198, 0x660a, 0x2b08, - 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e, - 0x0016, 0x080c, 0xb352, 0x9085, 0x0001, 0x001e, 0x012e, 0x00ce, - 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, - 0xb325, 0x0188, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, - 0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0xb352, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x0044, 0x0830, - 0x2009, 0x0049, 0x0818, 0x0026, 0x00b6, 0x6210, 0x2258, 0xba3c, - 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x002e, 0x0005, 0x0006, - 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, 0x0003, 0x0128, - 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, - 0x0006, 0x0086, 0x0096, 0x6020, 0x9086, 0x0004, 0x01a8, 0x6014, - 0x904d, 0x080c, 0xd0d8, 0x0180, 0xa864, 0x9086, 0x0139, 0x0170, - 0x6020, 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002, 0x0128, 0xa868, - 0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x009e, 0x008e, - 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb325, - 0x0198, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900, - 0x6016, 0x080c, 0x3250, 0x2009, 0x0028, 0x080c, 0xb352, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015, - 0x11a8, 0x2011, 0x1824, 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6, - 0x080c, 0xbf63, 0x00be, 0x080c, 0xc1df, 0x6003, 0x0001, 0x6007, - 0x0029, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0078, 0x6014, 0x0096, - 0x2048, 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c, - 0xd71a, 0x080c, 0xbcb6, 0x080c, 0xb2d3, 0x0005, 0x0096, 0x6014, - 0x904d, 0x090c, 0x0dc5, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, - 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6e9f, 0x012e, 0x009e, 0x080c, 0xb2d3, 0x0c30, 0x0096, - 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x666a, 0x00e8, - 0x9186, 0x0015, 0x1510, 0x2011, 0x1824, 0x2204, 0x9086, 0x0014, - 0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x67bf, 0x00be, 0x080c, - 0xc2b5, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, 0x00be, 0x9005, - 0x0160, 0x2001, 0x0006, 0x080c, 0x666a, 0x6014, 0x2048, 0xa868, - 0xd0fc, 0x0170, 0x080c, 0xb6dc, 0x0048, 0x6014, 0x2048, 0xa868, - 0xd0fc, 0x0528, 0x080c, 0xbcb6, 0x080c, 0xb2d3, 0x009e, 0x0005, - 0x6014, 0x6310, 0x2358, 0x904d, 0x090c, 0x0dc5, 0xa87b, 0x0000, - 0xa883, 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, 0x6944, 0x1108, - 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x6e9f, 0x012e, 0x080c, 0xb2d3, 0x08f8, 0x6014, - 0x904d, 0x090c, 0x0dc5, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, - 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6e9f, 0x012e, 0x080c, 0xb2d3, 0x0840, 0xa878, 0x9086, - 0x0005, 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad, 0xa882, 0x0005, - 0x6043, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, - 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005, 0x00c6, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0120, 0x6020, 0x9084, 0x000f, - 0x0013, 0x00ce, 0x0005, 0xcdd9, 0xd404, 0xd404, 0xd407, 0xec80, - 0xec9b, 0xec9e, 0xcdd9, 0xcdd9, 0xcdd9, 0xcdd9, 0xcdd9, 0xcdd9, - 0xcdd9, 0xcdd9, 0x080c, 0x0dc5, 0xa001, 0xa001, 0x0005, 0x0096, - 0x6014, 0x904d, 0x0118, 0xa87c, 0xd0e4, 0x1110, 0x009e, 0x0010, - 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x0550, 0x2001, 0x1834, 0x2004, 0x9005, 0x1540, 0x00f6, 0x2c78, - 0x080c, 0xb27d, 0x0508, 0x7810, 0x6012, 0x080c, 0xd554, 0x7820, - 0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, - 0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, 0x6007, - 0x0035, 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, 0x94ff, 0x080c, - 0x9ab1, 0x2f60, 0x00fe, 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1988, - 0x2004, 0x6042, 0x0005, 0x0016, 0x0096, 0x6814, 0x2048, 0xa87c, - 0xd0e4, 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000, 0xa893, 0x0000, - 0xa88f, 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e, 0xa878, 0x2048, - 0x080c, 0x0fc0, 0x6830, 0x6036, 0x908e, 0x0001, 0x0148, 0x6803, - 0x0002, 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, 0x6032, 0x00d0, - 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, 0xc0f4, 0x9085, - 0x0c00, 0x6826, 0x6814, 0x2048, 0xa8ac, 0x6938, 0x9102, 0xa8b0, - 0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, 0x9084, 0xfffc, - 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, 0x6910, 0x6112, - 0x6954, 0x6156, 0x6023, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, - 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x009e, 0x001e, 0x0005, 0x6024, - 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, 0x603c, 0x9303, - 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, 0x0098, 0x643a, - 0x633e, 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400, 0xacac, 0x9402, - 0xa836, 0x2300, 0xabb0, 0x9303, 0xa83a, 0x003e, 0x004e, 0x6024, - 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, 0xa83c, 0x603a, - 0xa840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, 0x0006, 0x0016, - 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, 0x01a0, 0x908e, - 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, 0x0038, 0x0158, - 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, 0x908e, 0x003b, - 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00e6, 0x2001, 0x1982, 0x200c, 0x8000, 0x2014, - 0x2001, 0x0032, 0x080c, 0x9375, 0x2001, 0x1986, 0x82ff, 0x1110, - 0x2011, 0x0014, 0x2202, 0x2001, 0x1984, 0x200c, 0x8000, 0x2014, - 0x2071, 0x196c, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x9375, - 0x2001, 0x1987, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, - 0x1988, 0x9288, 0x000a, 0x2102, 0x2001, 0x1a98, 0x2102, 0x2001, - 0x0032, 0x080c, 0x1611, 0x080c, 0x6a84, 0x00ee, 0x003e, 0x002e, - 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, 0x1986, - 0x2003, 0x0028, 0x2001, 0x1987, 0x2003, 0x0014, 0x2071, 0x196c, - 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x1988, 0x2009, 0x001e, - 0x2102, 0x2001, 0x1a98, 0x2102, 0x2001, 0x0032, 0x080c, 0x1611, - 0x00ee, 0x001e, 0x000e, 0x0005, 0x0096, 0x6058, 0x904d, 0x0110, - 0x080c, 0x1040, 0x009e, 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0xb27d, 0x0180, 0x2b08, 0x6112, 0x0ca9, 0x6023, - 0x0001, 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, 0xb352, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x00e6, - 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1520, 0x7090, 0x9086, - 0x0018, 0x0120, 0x7090, 0x9086, 0x0014, 0x11e0, 0x6014, 0x2048, - 0xaa3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x9d4c, 0x01d8, 0x707c, - 0xaa50, 0x9206, 0x1160, 0x7080, 0xaa54, 0x9206, 0x1140, 0x6210, - 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x900e, 0x080c, 0x3299, 0x080c, - 0xb6dc, 0x0020, 0x080c, 0xbcb6, 0x080c, 0xb2d3, 0x00fe, 0x00ee, - 0x009e, 0x0005, 0x7060, 0xaa54, 0x9206, 0x0d48, 0x0c80, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0xb27d, 0x0188, 0x2b08, 0x6112, - 0x080c, 0xd554, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x004d, - 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, - 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, 0xb27d, - 0x0180, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900, - 0x6016, 0x001e, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046, - 0x0056, 0x0066, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, - 0x0015, 0x1568, 0x7190, 0x6014, 0x2048, 0xa814, 0x8003, 0x9106, - 0x1530, 0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003, 0x0000, 0x6014, - 0x2048, 0xa830, 0x20a8, 0x8906, 0x8006, 0x8007, 0x9094, 0x003f, - 0x22e8, 0x9084, 0xffc0, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, - 0x0016, 0x200c, 0x080c, 0xde2e, 0x001e, 0xa804, 0x9005, 0x0110, - 0x2048, 0x0c38, 0x6014, 0x2048, 0xa867, 0x0103, 0x0010, 0x080c, - 0xbcb6, 0x080c, 0xb2d3, 0x00fe, 0x00ee, 0x009e, 0x006e, 0x005e, - 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x0096, 0x00e6, 0x00f6, - 0x2071, 0x1800, 0x9186, 0x0015, 0x11b8, 0x7090, 0x9086, 0x0004, - 0x1198, 0x6014, 0x2048, 0x2c78, 0x080c, 0x9d4c, 0x01a8, 0x707c, - 0xaa74, 0x9206, 0x1130, 0x7080, 0xaa78, 0x9206, 0x1110, 0x080c, - 0x3250, 0x080c, 0xb6dc, 0x0020, 0x080c, 0xbcb6, 0x080c, 0xb2d3, - 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa78, 0x9206, 0x0d78, - 0x0c80, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, - 0x1550, 0x7090, 0x9086, 0x0004, 0x1530, 0x6014, 0x2048, 0x2c78, - 0x080c, 0x9d4c, 0x05f0, 0x707c, 0xaacc, 0x9206, 0x1180, 0x7080, - 0xaad0, 0x9206, 0x1160, 0x080c, 0x3250, 0x0016, 0xa998, 0xaab0, - 0x9284, 0x1000, 0xc0fd, 0x080c, 0x5784, 0x001e, 0x0010, 0x080c, - 0x556f, 0x080c, 0xd0d8, 0x0508, 0xa87b, 0x0000, 0xa883, 0x0000, - 0xa897, 0x4000, 0x0080, 0x080c, 0xd0d8, 0x01b8, 0x6014, 0x2048, - 0x080c, 0x556f, 0x1d70, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, - 0x4005, 0xa89b, 0x0004, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, - 0x080c, 0x6e9f, 0x012e, 0x080c, 0xb2d3, 0x00fe, 0x00ee, 0x009e, - 0x0005, 0x7060, 0xaad0, 0x9206, 0x0930, 0x0888, 0x0016, 0x0026, - 0xa87c, 0xd0ac, 0x0178, 0xa938, 0xaa34, 0x2100, 0x9205, 0x0150, - 0xa890, 0x9106, 0x1118, 0xa88c, 0x9206, 0x0120, 0xa992, 0xaa8e, - 0x9085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00b6, 0x00d6, 0x0036, - 0x080c, 0xd0d8, 0x0904, 0xd716, 0x0096, 0x6314, 0x2348, 0xa87a, - 0xa982, 0x929e, 0x4000, 0x1580, 0x6310, 0x00c6, 0x2358, 0x2009, - 0x0000, 0xa868, 0xd0f4, 0x1140, 0x080c, 0x6944, 0x1108, 0xc185, - 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xaa96, 0xa99a, 0x20a9, 0x0004, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0, - 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0f8b, 0x20a9, 0x0004, - 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c8, 0x9080, 0x000a, 0x2098, - 0x080c, 0x0f8b, 0x00ce, 0x0090, 0xaa96, 0x3918, 0x9398, 0x0007, - 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, 0xa89b, 0x0004, 0xaba2, - 0x6310, 0x2358, 0xb804, 0x9084, 0x00ff, 0xa89e, 0xa868, 0xc0f4, - 0xa86a, 0x080c, 0x6e92, 0x6017, 0x0000, 0x009e, 0x003e, 0x00de, - 0x00be, 0x0005, 0x0026, 0x0036, 0x0046, 0x00b6, 0x0096, 0x00f6, - 0x6214, 0x2248, 0x6210, 0x2258, 0x2079, 0x0260, 0x9096, 0x0000, - 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, 0x080c, 0x2873, 0x2118, - 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, 0x931d, 0x7c3c, - 0x2011, 0x8018, 0x080c, 0x4c44, 0x00a8, 0x9096, 0x0001, 0x1148, - 0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, 0xa8a6, 0x783c, 0xa8aa, - 0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, 0x000d, 0x7838, 0xa8a6, - 0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, 0x004e, 0x003e, 0x002e, - 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035, 0x0110, 0x6a38, - 0x0008, 0x6a2c, 0x080c, 0xd0c6, 0x01f0, 0x2260, 0x6120, 0x9186, - 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838, 0x9206, 0x0140, - 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106, 0x1140, 0x0020, - 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910, 0x9106, 0x001e, - 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8, 0xa974, 0xd1cc, - 0x0198, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1170, 0xa9a8, 0x918c, - 0x000f, 0x918e, 0x0001, 0x1140, 0xa87c, 0xd0ac, 0x0128, 0xa834, - 0xa938, 0x9115, 0x190c, 0xc78b, 0x0005, 0x0036, 0x2019, 0x0001, - 0x0010, 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c, 0xd0d8, 0x01c8, - 0x080c, 0xd2c3, 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, 0x0096, - 0x2048, 0xa87c, 0x080c, 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0040, - 0xa867, 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x6e9f, - 0x009e, 0x003e, 0x0005, 0xa880, 0xd0b4, 0x0128, 0xa87b, 0x0006, - 0xc0ec, 0xa882, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020, - 0xa87b, 0x0005, 0x080c, 0xd3d4, 0xa877, 0x0000, 0x0005, 0x2001, - 0x1810, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, - 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0e4, - 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, - 0x00be, 0x2021, 0x0007, 0x080c, 0x4dfb, 0x004e, 0x003e, 0x0005, - 0x0c51, 0x1d81, 0x0005, 0x2001, 0x1986, 0x2004, 0x601a, 0x0005, - 0x2001, 0x1988, 0x2004, 0x6042, 0x0005, 0x080c, 0xb2d3, 0x0804, - 0x9ab1, 0x2001, 0x0109, 0x2004, 0xd084, 0x01e0, 0x0126, 0x2091, - 0x2800, 0x0006, 0x0016, 0x0026, 0x0036, 0x00f6, 0x00e6, 0x00c6, - 0x2079, 0x19e8, 0x2071, 0x1800, 0x2061, 0x0100, 0x080c, 0x93e2, - 0x00ce, 0x00ee, 0x00fe, 0x003e, 0x002e, 0x001e, 0x000e, 0x012e, - 0x9085, 0x0001, 0x0005, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0010, - 0x1a0c, 0x0dc5, 0x001b, 0x006e, 0x00be, 0x0005, 0xd846, 0xdf8d, - 0xe102, 0xd846, 0xd846, 0xd846, 0xd846, 0xd846, 0xd87d, 0xe186, - 0xd846, 0xd846, 0xd846, 0xd846, 0xd846, 0xd846, 0x080c, 0x0dc5, - 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, - 0x0005, 0xd861, 0xe6d5, 0xd861, 0xd861, 0xd861, 0xd861, 0xd861, - 0xd861, 0xe682, 0xe729, 0xd861, 0xedb4, 0xedea, 0xedb4, 0xedea, - 0xd861, 0x080c, 0x0dc5, 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0dc5, - 0x6000, 0x000a, 0x0005, 0xd87b, 0xe364, 0xe433, 0xe456, 0xe516, - 0xd87b, 0xe5f5, 0xe59e, 0xe192, 0xe658, 0xe66d, 0xd87b, 0xd87b, - 0xd87b, 0xd87b, 0xd87b, 0x080c, 0x0dc5, 0x91b2, 0x0053, 0x1a0c, - 0x0dc5, 0x2100, 0x91b2, 0x0040, 0x1a04, 0xdcfd, 0x0002, 0xd8c7, - 0xdacb, 0xd8c7, 0xd8c7, 0xd8c7, 0xdad4, 0xd8c7, 0xd8c7, 0xd8c7, - 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, - 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c9, 0xd92c, - 0xd93b, 0xd99f, 0xd9ca, 0xda43, 0xdab6, 0xd8c7, 0xd8c7, 0xdad7, - 0xd8c7, 0xd8c7, 0xdaec, 0xdaf9, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, - 0xd8c7, 0xdb9f, 0xd8c7, 0xd8c7, 0xdbb3, 0xd8c7, 0xd8c7, 0xdb6e, - 0xd8c7, 0xd8c7, 0xd8c7, 0xdbcb, 0xd8c7, 0xd8c7, 0xd8c7, 0xdc48, - 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xdcc5, 0x080c, - 0x0dc5, 0x080c, 0x6a61, 0x1150, 0x2001, 0x1837, 0x2004, 0xd0cc, - 0x1128, 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, - 0x602f, 0x0009, 0x6017, 0x0000, 0x0804, 0xdac4, 0x080c, 0x69fd, - 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, - 0x0026, 0x2019, 0x0029, 0x080c, 0x96a4, 0x0076, 0x903e, 0x080c, - 0x9577, 0x2c08, 0x080c, 0xe91c, 0x007e, 0x001e, 0x001e, 0x002e, - 0x003e, 0x00ce, 0x00ee, 0x6610, 0x2658, 0x080c, 0x6733, 0xbe04, - 0x9684, 0x00ff, 0x9082, 0x0006, 0x1268, 0x0016, 0x0026, 0x6210, - 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x2c08, 0x080c, 0xf015, 0x002e, - 0x001e, 0x1178, 0x080c, 0xe84e, 0x1904, 0xd997, 0x080c, 0xe7ea, - 0x1120, 0x6007, 0x0008, 0x0804, 0xdac4, 0x6007, 0x0009, 0x0804, - 0xdac4, 0x080c, 0xeab9, 0x0128, 0x080c, 0xe84e, 0x0d78, 0x0804, - 0xd997, 0x6017, 0x1900, 0x0c88, 0x080c, 0x3374, 0x1904, 0xdcfa, - 0x6106, 0x080c, 0xe78e, 0x6007, 0x0006, 0x0804, 0xdac4, 0x6007, - 0x0007, 0x0804, 0xdac4, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c, - 0x3374, 0x1904, 0xdcfa, 0x00d6, 0x6610, 0x2658, 0xbe04, 0x9684, - 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x6656, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0188, 0x9686, 0x0004, - 0x0170, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686, - 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6, - 0x2071, 0x0260, 0x7034, 0x9084, 0x0003, 0x1140, 0x7034, 0x9082, - 0x0014, 0x0220, 0x7030, 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017, - 0x0000, 0x602f, 0x0007, 0x00b0, 0x00ee, 0x080c, 0xe8b2, 0x1190, - 0x9686, 0x0006, 0x1140, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, - 0x080c, 0x3299, 0x002e, 0x080c, 0x67bf, 0x6007, 0x000a, 0x00de, - 0x0804, 0xdac4, 0x6007, 0x000b, 0x00de, 0x0804, 0xdac4, 0x080c, - 0x3250, 0x080c, 0xd7f8, 0x6007, 0x0001, 0x0804, 0xdac4, 0x080c, - 0xee26, 0x1904, 0xdcfa, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x2071, - 0x0260, 0x7034, 0x90b4, 0x0003, 0x1948, 0x90b2, 0x0014, 0x0a30, - 0x7030, 0x9084, 0x0003, 0x1910, 0x6610, 0x2658, 0xbe04, 0x9686, - 0x0707, 0x09e8, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c, - 0x3299, 0x002e, 0x6007, 0x000c, 0x2001, 0x0001, 0x080c, 0xeff4, - 0x0804, 0xdac4, 0x080c, 0x6a61, 0x1140, 0x2001, 0x1837, 0x2004, - 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xd8d6, 0x080c, - 0x69fd, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, - 0x06c8, 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x6696, 0x002e, - 0x0050, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, - 0x0006, 0x1904, 0xd997, 0x080c, 0xe8bf, 0x1120, 0x6007, 0x000e, - 0x0804, 0xdac4, 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, - 0x3250, 0x080c, 0xd7f8, 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, - 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, 0x080c, 0xec31, 0x6010, - 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, - 0x0804, 0xdac4, 0x2001, 0x0001, 0x080c, 0x6656, 0x0156, 0x0016, - 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0270, - 0x080c, 0xc365, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0168, - 0x96b4, 0xff00, 0x8637, 0x9682, 0x0004, 0x0a04, 0xd997, 0x9682, - 0x0007, 0x0a04, 0xd9f3, 0x0804, 0xd997, 0x6017, 0x1900, 0x6007, - 0x0009, 0x0804, 0xdac4, 0x080c, 0x6a61, 0x1140, 0x2001, 0x1837, - 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xd8d6, - 0x080c, 0x69fd, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x0006, - 0x0016, 0x908e, 0x0001, 0x0118, 0x908e, 0x0000, 0x1118, 0x001e, - 0x000e, 0x0080, 0x001e, 0x000e, 0x9082, 0x0006, 0x06a0, 0x0150, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006, - 0x1904, 0xd997, 0x080c, 0xe8ed, 0x1138, 0x080c, 0xe7ea, 0x1120, - 0x6007, 0x0010, 0x0804, 0xdac4, 0x0046, 0x6410, 0x2458, 0xbca0, - 0x0046, 0x080c, 0x3250, 0x080c, 0xd7f8, 0x004e, 0x0016, 0x9006, - 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, 0x080c, - 0xec31, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e, - 0x6007, 0x0001, 0x0448, 0x080c, 0xeab9, 0x0198, 0x0016, 0x968c, - 0x00ff, 0x9186, 0x0002, 0x0160, 0x9186, 0x0003, 0x0148, 0x001e, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0920, 0x0804, 0xd997, - 0x001e, 0x6017, 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, 0x3374, - 0x1904, 0xdcfa, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c, 0xdecb, - 0x1904, 0xd997, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x9547, - 0x080c, 0x9ab1, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, - 0x9547, 0x080c, 0x9ab1, 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c, - 0xee26, 0x1904, 0xdcfa, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x080c, - 0xdecb, 0x1904, 0xd997, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, - 0x9547, 0x080c, 0x9ab1, 0x0005, 0x080c, 0x3374, 0x1904, 0xdcfa, - 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, - 0x0005, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c, 0x3374, 0x1904, - 0xdcfa, 0x080c, 0xdecb, 0x1904, 0xd997, 0x0016, 0x0026, 0x00e6, - 0x2071, 0x0260, 0x2c08, 0x2011, 0x1820, 0x2214, 0x703c, 0x9206, - 0x11e0, 0x2011, 0x181f, 0x2214, 0x7038, 0x9084, 0x00ff, 0x9206, - 0x11a0, 0x7240, 0x080c, 0xd0c6, 0x0570, 0x2260, 0x6008, 0x9086, - 0xffff, 0x0120, 0x7244, 0x6008, 0x9206, 0x1528, 0x6020, 0x9086, - 0x0007, 0x1508, 0x080c, 0xb2d3, 0x04a0, 0x7244, 0x9286, 0xffff, - 0x0180, 0x2c08, 0x080c, 0xd0c6, 0x01b0, 0x2260, 0x7240, 0x6008, - 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, 0x2214, 0x9206, 0x01b8, - 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, 0xebfb, 0x1180, 0x7244, - 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, 0x0026, 0x6017, 0x1700, - 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x6020, - 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, 0x0024, 0x1110, 0x080c, - 0xb2d3, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x9547, - 0x080c, 0x9ab1, 0x00ee, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, - 0x080c, 0x6656, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, - 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, 0xc365, 0x003e, 0x002e, - 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, 0xdac4, 0x080c, - 0xbf7b, 0x080c, 0x7637, 0x1190, 0x0006, 0x0026, 0x0036, 0x080c, - 0x7651, 0x1138, 0x080c, 0x7932, 0x080c, 0x612e, 0x080c, 0x7563, - 0x0010, 0x080c, 0x760f, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c, - 0x3374, 0x1904, 0xdcfa, 0x080c, 0xdecb, 0x1904, 0xd997, 0x6106, - 0x080c, 0xdee7, 0x1120, 0x6007, 0x002b, 0x0804, 0xdac4, 0x6007, - 0x002c, 0x0804, 0xdac4, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c, - 0x3374, 0x1904, 0xdcfa, 0x080c, 0xdecb, 0x1904, 0xd997, 0x6106, - 0x080c, 0xdeec, 0x1120, 0x6007, 0x002e, 0x0804, 0xdac4, 0x6007, - 0x002f, 0x0804, 0xdac4, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x00e6, - 0x00d6, 0x00c6, 0x6010, 0x2058, 0xb904, 0x9184, 0x00ff, 0x9086, - 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, 0x9086, 0x0006, 0x0128, - 0x00ce, 0x00de, 0x00ee, 0x0804, 0xdacb, 0x080c, 0x57d9, 0xd0e4, - 0x0904, 0xdc45, 0x2071, 0x026c, 0x7010, 0x603a, 0x7014, 0x603e, - 0x7108, 0x720c, 0x080c, 0x6a9f, 0x0140, 0x6010, 0x2058, 0xb810, - 0x9106, 0x1118, 0xb814, 0x9206, 0x0510, 0x080c, 0x6a9b, 0x15b8, - 0x2069, 0x1800, 0x6880, 0x9206, 0x1590, 0x687c, 0x9106, 0x1578, - 0x7210, 0x080c, 0xd0c6, 0x0590, 0x080c, 0xddb8, 0x0578, 0x080c, - 0xecad, 0x0560, 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, 0x080c, - 0x94ff, 0x080c, 0x9ab1, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214, - 0x9286, 0xffff, 0x0150, 0x080c, 0xd0c6, 0x01c0, 0x9280, 0x0002, - 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, 0x7210, 0x2c08, 0x9085, - 0x0001, 0x080c, 0xebfb, 0x2c10, 0x2160, 0x0140, 0x0890, 0x6007, - 0x0037, 0x602f, 0x0009, 0x6017, 0x1500, 0x08b8, 0x6007, 0x0037, - 0x602f, 0x0003, 0x6017, 0x1700, 0x0880, 0x6007, 0x0012, 0x0868, - 0x080c, 0x3374, 0x1904, 0xdcfa, 0x6010, 0x2058, 0xb804, 0x9084, - 0xff00, 0x8007, 0x9086, 0x0006, 0x1904, 0xdacb, 0x00e6, 0x00d6, - 0x00c6, 0x080c, 0x57d9, 0xd0e4, 0x0904, 0xdcbd, 0x2069, 0x1800, - 0x2071, 0x026c, 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, 0xffff, - 0x1150, 0x7208, 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, 0xebfb, - 0x2c10, 0x00ce, 0x05e8, 0x080c, 0xd0c6, 0x05d0, 0x7108, 0x9280, - 0x0002, 0x2004, 0x9106, 0x15a0, 0x00c6, 0x0026, 0x2260, 0x080c, - 0xcce6, 0x002e, 0x00ce, 0x7118, 0x918c, 0xff00, 0x810f, 0x9186, - 0x0001, 0x0178, 0x9186, 0x0005, 0x0118, 0x9186, 0x0007, 0x1198, - 0x9280, 0x0005, 0x2004, 0x9005, 0x0170, 0x080c, 0xddb8, 0x0904, - 0xdc3e, 0x0056, 0x7510, 0x7614, 0x080c, 0xecc6, 0x005e, 0x00ce, - 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, - 0x2a00, 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0c78, - 0x6007, 0x003b, 0x602f, 0x0003, 0x6017, 0x0300, 0x6003, 0x0001, - 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0c10, 0x6007, 0x003b, 0x602f, - 0x000b, 0x6017, 0x0000, 0x0804, 0xdc15, 0x00e6, 0x0026, 0x080c, - 0x6a61, 0x0550, 0x080c, 0x69fd, 0x080c, 0xee97, 0x1518, 0x2071, - 0x1800, 0x70dc, 0x9085, 0x0003, 0x70de, 0x00f6, 0x2079, 0x0100, - 0x72b0, 0x9284, 0x00ff, 0x707e, 0x78e6, 0x9284, 0xff00, 0x7280, - 0x9205, 0x7082, 0x78ea, 0x00fe, 0x70e7, 0x0000, 0x080c, 0x6a9f, - 0x0120, 0x2011, 0x1a01, 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c, - 0x3000, 0x0010, 0x080c, 0xeecb, 0x002e, 0x00ee, 0x080c, 0xb2d3, - 0x0804, 0xdaca, 0x080c, 0xb2d3, 0x0005, 0x2600, 0x0002, 0xdd11, - 0xdd3f, 0xdd50, 0xdd11, 0xdd11, 0xdd13, 0xdd61, 0xdd11, 0xdd11, - 0xdd11, 0xdd2d, 0xdd11, 0xdd11, 0xdd11, 0xdd6c, 0xdd82, 0xddb3, - 0xdd11, 0x080c, 0x0dc5, 0x080c, 0xee26, 0x1d20, 0x080c, 0x3374, - 0x1d08, 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c, - 0x9547, 0x0005, 0x080c, 0x3250, 0x080c, 0xd7f8, 0x6007, 0x0001, - 0x6003, 0x0001, 0x080c, 0x9547, 0x0005, 0x080c, 0xee26, 0x1950, - 0x080c, 0x3374, 0x1938, 0x080c, 0xdecb, 0x1d60, 0x703c, 0x6016, - 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, 0x9547, 0x0005, 0x080c, - 0x3374, 0x1904, 0xdcfa, 0x2009, 0x0041, 0x080c, 0xeed4, 0x6007, - 0x0047, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0005, - 0x080c, 0x3374, 0x1904, 0xdcfa, 0x2009, 0x0042, 0x080c, 0xeed4, - 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, - 0x0005, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x2009, 0x0046, 0x080c, - 0xeed4, 0x080c, 0xb2d3, 0x0005, 0x2001, 0x1824, 0x2004, 0x9082, - 0x00e1, 0x1268, 0x080c, 0xddd5, 0x0904, 0xdcfa, 0x6007, 0x004e, - 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0005, 0x6007, - 0x0012, 0x0cb0, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, 0x918c, - 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, 0x1160, 0x7140, 0x2001, - 0x19be, 0x2004, 0x9106, 0x11b0, 0x7144, 0x2001, 0x19bf, 0x2004, - 0x9106, 0x0190, 0x9186, 0x0002, 0x1168, 0x2011, 0x0276, 0x20a9, - 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xc379, - 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547, - 0x080c, 0x9ab1, 0x0005, 0x6007, 0x0050, 0x703c, 0x6016, 0x0ca0, - 0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6, 0x00c6, 0x2260, 0x6010, - 0x2058, 0xb8cc, 0xd084, 0x0150, 0x7128, 0x6044, 0x9106, 0x1120, - 0x712c, 0x6048, 0x9106, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, - 0x00ce, 0x00be, 0x00ee, 0x001e, 0x0005, 0x0016, 0x0096, 0x0086, - 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, - 0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003, 0x0000, 0x080c, 0x1027, - 0x05a0, 0x2900, 0x6016, 0x7090, 0x8004, 0xa816, 0x908a, 0x001e, - 0x02d0, 0xa833, 0x001e, 0x20a9, 0x001e, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, 0x0016, 0x200c, 0x0471, - 0x001e, 0x81ff, 0x01b8, 0x2940, 0x080c, 0x1027, 0x01b0, 0x2900, - 0xa006, 0x2100, 0x0c18, 0xa832, 0x20a8, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, 0x0016, 0x200c, 0x00b1, - 0x001e, 0x0000, 0x9085, 0x0001, 0x0048, 0x2071, 0x1800, 0x7093, - 0x0000, 0x6014, 0x2048, 0x080c, 0x0fc0, 0x9006, 0x012e, 0x01de, - 0x01ce, 0x00ee, 0x008e, 0x009e, 0x001e, 0x0005, 0x0006, 0x0016, - 0x0026, 0x0036, 0x00c6, 0x918c, 0xffff, 0x11b0, 0x080c, 0x23e2, - 0x2099, 0x026c, 0x2001, 0x0014, 0x3518, 0x9312, 0x0108, 0x1218, - 0x23a8, 0x4003, 0x0400, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, - 0x23e2, 0x2099, 0x0260, 0x0ca8, 0x080c, 0x23e2, 0x2061, 0x19a1, - 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, 0x0108, 0x1218, 0x23a8, - 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x23e2, - 0x2099, 0x0260, 0x0ca8, 0x2061, 0x19a1, 0x2019, 0x0280, 0x3300, - 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0260, 0x6006, 0x8108, - 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x23fa, 0x20a1, 0x024c, 0x2001, - 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, 0x20a8, - 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, 0x23fa, 0x20a1, - 0x0240, 0x0c98, 0x080c, 0x23fa, 0x2061, 0x19a4, 0x6004, 0x20a0, - 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, 0x20a8, - 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, 0x23fa, 0x20a1, - 0x0240, 0x0c98, 0x2061, 0x19a4, 0x2019, 0x0260, 0x3400, 0x931e, - 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, 0x6006, 0x8108, 0x2162, - 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e, - 0x001e, 0x000e, 0x0005, 0x00b6, 0x0066, 0x6610, 0x2658, 0xbe04, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0170, 0x9686, 0x0004, - 0x0158, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0128, 0x9686, - 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, 0x00be, 0x0005, 0x00d6, - 0x080c, 0xdf63, 0x00de, 0x0005, 0x00d6, 0x080c, 0xdf70, 0x1520, - 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216, - 0x6824, 0x602e, 0xd1e4, 0x0130, 0x9006, 0x080c, 0xeff4, 0x2009, - 0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920, 0x918c, 0x00ff, 0x6824, - 0x080c, 0x2873, 0x1148, 0x2001, 0x0001, 0x080c, 0xeff4, 0x2110, - 0x900e, 0x080c, 0x3299, 0x0018, 0x9085, 0x0001, 0x0008, 0x9006, - 0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c, 0xb325, 0x05a8, 0x0016, - 0x0026, 0x00c6, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, - 0x2873, 0x1578, 0x080c, 0x66b9, 0x1560, 0xbe12, 0xbd16, 0x00ce, - 0x002e, 0x001e, 0x2b00, 0x6012, 0x080c, 0xee26, 0x11d8, 0x080c, - 0x3374, 0x11c0, 0x080c, 0xdecb, 0x0510, 0x2001, 0x0007, 0x080c, - 0x666a, 0x2001, 0x0007, 0x080c, 0x6696, 0x6017, 0x0000, 0x6023, - 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, - 0x9ab1, 0x0010, 0x080c, 0xb2d3, 0x9085, 0x0001, 0x00ce, 0x00be, - 0x0005, 0x080c, 0xb2d3, 0x00ce, 0x002e, 0x001e, 0x0ca8, 0x080c, - 0xb2d3, 0x9006, 0x0c98, 0x2069, 0x026d, 0x6800, 0x9082, 0x0010, - 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, 0x0005, - 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, 0x9086, - 0x0800, 0x1190, 0x6904, 0x9186, 0x0018, 0x0118, 0x9186, 0x0014, - 0x1158, 0x810f, 0x6800, 0x9084, 0x00ff, 0x910d, 0x615a, 0x908e, - 0x0014, 0x0110, 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, 0x0053, - 0x1a0c, 0x0dc5, 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, 0x0040, - 0x1a04, 0xe0d2, 0x040a, 0x91b6, 0x0027, 0x0198, 0x9186, 0x0015, - 0x0118, 0x9186, 0x0016, 0x1148, 0x080c, 0xd809, 0x0128, 0x6000, - 0x9086, 0x0002, 0x0904, 0xbcfd, 0x0005, 0x91b6, 0x0014, 0x190c, - 0x0dc5, 0x2001, 0x0007, 0x080c, 0x6696, 0x080c, 0x99a5, 0x080c, - 0xb306, 0x080c, 0x9ab1, 0x0005, 0xdffc, 0xdffe, 0xdffc, 0xdffc, - 0xdffc, 0xdffe, 0xe00d, 0xe0cb, 0xe051, 0xe0cb, 0xe079, 0xe0cb, - 0xe00d, 0xe0cb, 0xe0c3, 0xe0cb, 0xe0c3, 0xe0cb, 0xe0cb, 0xdffc, - 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc, - 0xdffc, 0xdffc, 0xdffe, 0xdffc, 0xe0cb, 0xdffc, 0xdffc, 0xe0cb, - 0xdffc, 0xe0c8, 0xe0cb, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xe0cb, - 0xe0cb, 0xdffc, 0xe0cb, 0xe0cb, 0xdffc, 0xe008, 0xdffc, 0xdffc, - 0xdffc, 0xdffc, 0xe0c7, 0xe0cb, 0xdffc, 0xdffc, 0xe0cb, 0xe0cb, - 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0x080c, 0x0dc5, 0x080c, 0x99a5, - 0x080c, 0xd7fb, 0x6003, 0x0002, 0x080c, 0x9ab1, 0x0804, 0xe0d1, - 0x9006, 0x080c, 0x6656, 0x0804, 0xe0cb, 0x080c, 0x6a9b, 0x1904, - 0xe0cb, 0x9006, 0x080c, 0x6656, 0x6010, 0x2058, 0xb810, 0x9086, - 0x00ff, 0x1140, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, - 0x00fe, 0x00b8, 0x6010, 0x2058, 0xb8c0, 0x9005, 0x0904, 0xe0cb, - 0x080c, 0x33a5, 0x1904, 0xe0cb, 0x2001, 0x1800, 0x2004, 0x9086, - 0x0002, 0x1138, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, - 0x00fe, 0x2001, 0x0002, 0x080c, 0x666a, 0x080c, 0x99a5, 0x6023, - 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c, - 0x9ab1, 0x6110, 0x2158, 0x2009, 0x0001, 0x080c, 0x884b, 0x0804, - 0xe0d1, 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, - 0x0006, 0x0148, 0x9686, 0x0004, 0x0130, 0x080c, 0x9031, 0x2001, - 0x0004, 0x080c, 0x6696, 0x080c, 0xf043, 0x0904, 0xe0cb, 0x080c, - 0x99a5, 0x2001, 0x0004, 0x080c, 0x666a, 0x6023, 0x0001, 0x6003, - 0x0001, 0x6007, 0x0003, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0804, - 0xe0d1, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, - 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4dfb, - 0x004e, 0x003e, 0x2001, 0x0006, 0x080c, 0xe0ef, 0x6610, 0x2658, - 0xbe04, 0x0066, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, - 0x0180, 0x2001, 0x0006, 0x080c, 0x6696, 0x9284, 0x00ff, 0x908e, - 0x0007, 0x0118, 0x908e, 0x0004, 0x1120, 0x2001, 0x0006, 0x080c, - 0x666a, 0x080c, 0x6a9b, 0x11f8, 0x2001, 0x1837, 0x2004, 0xd0a4, - 0x01d0, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6, - 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x0804, 0xe039, - 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0449, 0x0020, 0x0018, - 0x0010, 0x080c, 0x6696, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c, - 0x9ab1, 0x0005, 0x2600, 0x0002, 0xe0e6, 0xe0e6, 0xe0e6, 0xe0e6, - 0xe0e6, 0xe0e8, 0xe0e6, 0xe0e8, 0xe0e6, 0xe0e6, 0xe0e8, 0xe0e6, - 0xe0e6, 0xe0e6, 0xe0e8, 0xe0e8, 0xe0e8, 0xe0e8, 0x080c, 0x0dc5, - 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x0016, - 0x00b6, 0x00d6, 0x6110, 0x2158, 0xb900, 0xd184, 0x0138, 0x080c, - 0x666a, 0x9006, 0x080c, 0x6656, 0x080c, 0x3279, 0x00de, 0x00be, - 0x001e, 0x0005, 0x6610, 0x2658, 0xb804, 0x9084, 0xff00, 0x8007, - 0x90b2, 0x000c, 0x1a0c, 0x0dc5, 0x91b6, 0x0015, 0x1110, 0x003b, - 0x0028, 0x91b6, 0x0016, 0x190c, 0x0dc5, 0x006b, 0x0005, 0xbd9f, - 0xbd9f, 0xbd9f, 0xbd9f, 0xe184, 0xbd9f, 0xe16e, 0xe12f, 0xbd9f, - 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xe184, - 0xbd9f, 0xe16e, 0xe175, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0x00f6, - 0x080c, 0x6a9b, 0x11d8, 0x080c, 0xd7e3, 0x11c0, 0x6010, 0x905d, - 0x01a8, 0xb8c0, 0x9005, 0x0190, 0x9006, 0x080c, 0x6656, 0x2001, - 0x0002, 0x080c, 0x666a, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x00f0, 0x2011, 0x0263, - 0x2204, 0x8211, 0x220c, 0x080c, 0x2873, 0x11b0, 0x080c, 0x6724, - 0x0118, 0x080c, 0xb2d3, 0x0080, 0xb810, 0x0006, 0xb814, 0x0006, - 0xb8c0, 0x0006, 0x080c, 0x6148, 0x000e, 0xb8c2, 0x000e, 0xb816, - 0x000e, 0xb812, 0x080c, 0xb2d3, 0x00fe, 0x0005, 0x6604, 0x96b6, - 0x001e, 0x1110, 0x080c, 0xb2d3, 0x0005, 0x080c, 0xc1dc, 0x1148, - 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, - 0x0010, 0x080c, 0xb2d3, 0x0005, 0x0804, 0xb2d3, 0x6004, 0x908a, - 0x0053, 0x1a0c, 0x0dc5, 0x080c, 0x99a5, 0x080c, 0xb306, 0x080c, - 0x9ab1, 0x0005, 0x9182, 0x0040, 0x0002, 0xe1a9, 0xe1a9, 0xe1a9, - 0xe1a9, 0xe1ab, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, - 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, - 0xe1a9, 0x080c, 0x0dc5, 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6, - 0x0046, 0x0026, 0x6210, 0x2258, 0xb8bc, 0x9005, 0x11a8, 0x6106, - 0x2071, 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, 0xe211, 0x080c, - 0xefe8, 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, - 0x0200, 0x080c, 0x8a50, 0x0020, 0x9026, 0x080c, 0xee6b, 0x0c38, - 0x080c, 0x100e, 0x090c, 0x0dc5, 0x6003, 0x0007, 0xa867, 0x010d, - 0x9006, 0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, 0x6008, 0xa8e2, - 0x6010, 0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, 0xa876, 0xa87f, - 0x0000, 0xa883, 0x0000, 0xa887, 0x0036, 0x080c, 0x6e9f, 0x001e, - 0x080c, 0xefe8, 0x1904, 0xe271, 0x9486, 0x2000, 0x1130, 0x2019, - 0x0017, 0x080c, 0xeba1, 0x0804, 0xe271, 0x9486, 0x0200, 0x1120, - 0x080c, 0xeb38, 0x0804, 0xe271, 0x9486, 0x0400, 0x0120, 0x9486, - 0x1000, 0x1904, 0xe271, 0x2019, 0x0002, 0x080c, 0xeb53, 0x0804, - 0xe271, 0x2069, 0x1a74, 0x6a00, 0xd284, 0x0904, 0xe2db, 0x9284, - 0x0300, 0x1904, 0xe2d4, 0x6804, 0x9005, 0x0904, 0xe2bc, 0x2d78, - 0x6003, 0x0007, 0x080c, 0x1027, 0x0904, 0xe27d, 0x7800, 0xd08c, - 0x1118, 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, 0x2001, 0x180f, - 0x2004, 0xd084, 0x1904, 0xe2df, 0x9006, 0xa802, 0xa867, 0x0116, - 0xa86a, 0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, 0x2058, 0xb8a0, - 0x7130, 0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, 0xa9be, 0xb930, - 0xa9c2, 0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, 0x9084, 0x0003, - 0x9080, 0xe279, 0x2005, 0xa87e, 0x20a9, 0x000a, 0x2001, 0x0270, - 0xaa5c, 0x9290, 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, - 0x0000, 0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, - 0x2001, 0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, 0xa9ae, 0x080c, - 0x6e9f, 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e, - 0x0005, 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, 0x1810, 0x2004, - 0xd084, 0x0120, 0x080c, 0x100e, 0x1904, 0xe226, 0x6017, 0xf100, - 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff, 0x080c, 0x9ab1, - 0x0c00, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, 0x1200, - 0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, 0xf700, - 0x910d, 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x080c, - 0x94ff, 0x080c, 0x9ab1, 0x0828, 0x6868, 0x602e, 0x686c, 0x6032, - 0x6017, 0xf200, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x0804, 0xe271, 0x2001, 0x180e, 0x2004, 0xd0ec, - 0x0120, 0x2011, 0x8049, 0x080c, 0x4c44, 0x6017, 0xf300, 0x0010, - 0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x0804, 0xe271, 0x6017, 0xf500, 0x0c98, 0x6017, - 0xf600, 0x0804, 0xe291, 0x6017, 0xf200, 0x0804, 0xe291, 0xa867, - 0x0146, 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, 0xa87a, 0x7044, - 0x9084, 0x0003, 0x9080, 0xe279, 0x2005, 0xa87e, 0x2928, 0x6010, - 0x2058, 0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, 0xa88e, 0xb830, - 0xa892, 0xb834, 0xa896, 0xa883, 0x003d, 0x2009, 0x0205, 0x2104, - 0x9085, 0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, 0x0210, 0x2214, - 0x9294, 0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, 0x0dc5, 0x8210, - 0x821c, 0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0029, 0x20a0, 0x2011, 0xe35b, 0x2041, 0x0001, 0x223d, 0x9784, - 0x00ff, 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, 0x0530, - 0x8210, 0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, 0x0260, 0x2098, - 0x0c68, 0x2950, 0x080c, 0x1027, 0x0170, 0x2900, 0xb002, 0xa867, - 0x0147, 0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, - 0x20a0, 0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, 0x0118, 0x080c, - 0x1040, 0x0cc8, 0x080c, 0x1040, 0x0804, 0xe27d, 0x2548, 0x8847, - 0x9885, 0x0046, 0xa866, 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, - 0xebd4, 0x0804, 0xe271, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, - 0x0008, 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, - 0x908a, 0x0054, 0x1a0c, 0x0dc5, 0x9082, 0x0040, 0x0a0c, 0x0dc5, - 0x2008, 0x0804, 0xe3ea, 0x9186, 0x0051, 0x0108, 0x0048, 0x080c, - 0xd809, 0x0500, 0x6000, 0x9086, 0x0002, 0x11e0, 0x0804, 0xe433, - 0x9186, 0x0027, 0x0190, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, - 0x0160, 0x190c, 0x0dc5, 0x080c, 0xd809, 0x0160, 0x6000, 0x9086, - 0x0004, 0x190c, 0x0dc5, 0x0804, 0xe516, 0x6004, 0x9082, 0x0040, - 0x2008, 0x001a, 0x080c, 0xb36d, 0x0005, 0xe3b1, 0xe3b3, 0xe3b3, - 0xe3da, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, - 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, - 0xe3b1, 0x080c, 0x0dc5, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0036, - 0x0096, 0x6014, 0x904d, 0x01d8, 0x080c, 0xd0d8, 0x01c0, 0x6003, - 0x0002, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1178, - 0x2019, 0x0004, 0x080c, 0xebd4, 0x6017, 0x0000, 0x6018, 0x9005, - 0x1120, 0x2001, 0x1987, 0x2004, 0x601a, 0x6003, 0x0007, 0x009e, - 0x003e, 0x0005, 0x0096, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x080c, - 0xd0d8, 0x0120, 0x6014, 0x2048, 0x080c, 0x1040, 0x080c, 0xb306, - 0x009e, 0x0005, 0x0002, 0xe3ff, 0xe416, 0xe401, 0xe42d, 0xe3ff, - 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, - 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0x080c, - 0x0dc5, 0x0096, 0x080c, 0x99a5, 0x6014, 0x2048, 0xa87c, 0xd0b4, - 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0xb352, 0x0010, - 0x6003, 0x0004, 0x080c, 0x9ab1, 0x009e, 0x0005, 0x080c, 0x99a5, - 0x080c, 0xd0d8, 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e, - 0xd1ec, 0x1138, 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x080c, 0x9ab1, - 0x0005, 0x080c, 0xee2f, 0x0db0, 0x0cc8, 0x080c, 0x99a5, 0x2009, - 0x0041, 0x0804, 0xe59e, 0x9182, 0x0040, 0x0002, 0xe44a, 0xe44c, - 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, - 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44d, - 0xe44a, 0xe44a, 0x080c, 0x0dc5, 0x0005, 0x00d6, 0x080c, 0x8a25, - 0x00de, 0x080c, 0xee87, 0x080c, 0xb2d3, 0x0005, 0x9182, 0x0040, - 0x0002, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0xe46d, - 0xe46d, 0xe46d, 0xe46f, 0xe4de, 0xe46d, 0xe46d, 0xe46d, 0xe46d, - 0xe4de, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0x080c, 0x0dc5, 0x2001, - 0x0105, 0x2004, 0x9084, 0x1800, 0x01c8, 0x2001, 0x0132, 0x200c, - 0x2001, 0x0131, 0x2004, 0x9105, 0x1904, 0xe4de, 0x2009, 0x180c, - 0x2104, 0xd0d4, 0x0904, 0xe4de, 0xc0d4, 0x200a, 0x2009, 0x0105, - 0x2104, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x200a, 0x2001, 0x1867, - 0x2004, 0xd0e4, 0x1528, 0x603b, 0x0000, 0x080c, 0x9a61, 0x6014, - 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0188, 0x908c, 0x0003, 0x918e, - 0x0002, 0x0508, 0x2001, 0x180c, 0x2004, 0xd0d4, 0x11e0, 0x080c, - 0x9bd3, 0x2009, 0x0041, 0x009e, 0x0804, 0xe59e, 0x080c, 0x9bd3, - 0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x8a25, 0x009e, 0x0005, - 0x2001, 0x0100, 0x2004, 0x9082, 0x0005, 0x0aa8, 0x2001, 0x011f, - 0x2004, 0x603a, 0x0890, 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102, - 0xd1cc, 0x0110, 0x080c, 0x2c7b, 0x080c, 0x9bd3, 0x6014, 0x2048, - 0xa97c, 0xd1ec, 0x1130, 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x009e, - 0x0005, 0x080c, 0xee2f, 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, - 0x200c, 0xc1d4, 0x2102, 0x0036, 0x080c, 0x9a61, 0x080c, 0x9bd3, - 0x6014, 0x0096, 0x2048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x0188, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, - 0xa8ac, 0x6330, 0x931a, 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e, - 0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xebd4, 0x6018, - 0x9005, 0x1128, 0x2001, 0x1987, 0x2004, 0x8003, 0x601a, 0x6017, - 0x0000, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, - 0x0002, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, - 0xe52d, 0xe52f, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, - 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe57a, 0x080c, 0x0dc5, 0x6014, - 0x0096, 0x2048, 0xa834, 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, - 0x00be, 0xd1bc, 0x1190, 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, - 0x2009, 0x0041, 0x009e, 0x0804, 0xe59e, 0x6003, 0x0007, 0x601b, - 0x0000, 0x080c, 0x8a25, 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, - 0x0006, 0x0046, 0xacac, 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030, - 0x9420, 0x6432, 0x602c, 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, - 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009, - 0x180e, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, - 0x0006, 0x00e9, 0x080c, 0x8a27, 0x009e, 0x0005, 0x6003, 0x0002, - 0x009e, 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, 0x1608, 0x1904, - 0xe52f, 0x0005, 0x6014, 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, - 0x9105, 0x1120, 0x080c, 0x1608, 0x1904, 0xe52f, 0x0005, 0xd2fc, - 0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, - 0x0010, 0x2009, 0x0015, 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040, - 0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, - 0x0dc5, 0x6024, 0xd0dc, 0x090c, 0x0dc5, 0x0005, 0xe5c2, 0xe5ce, - 0xe5da, 0xe5e6, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c9, 0xe5c4, - 0xe5c4, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c4, 0xe5c2, 0xe5c4, - 0xe5c2, 0xe5c9, 0x080c, 0x0dc5, 0x6024, 0xd0dc, 0x090c, 0x0dc5, - 0x0005, 0x6014, 0x9005, 0x190c, 0x0dc5, 0x0005, 0x6003, 0x0001, - 0x6106, 0x080c, 0x94ff, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1, - 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x94ff, 0x0126, - 0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005, 0x6003, 0x0003, - 0x6106, 0x2c10, 0x080c, 0x1be0, 0x0126, 0x2091, 0x8000, 0x080c, - 0x9564, 0x080c, 0x9bd3, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x0036, 0x0096, 0x9182, 0x0040, 0x0023, 0x009e, 0x003e, 0x012e, - 0x0005, 0xe615, 0xe617, 0xe629, 0xe643, 0xe615, 0xe615, 0xe615, - 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, - 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0x080c, 0x0dc5, 0x6014, - 0x2048, 0xa87c, 0xd0fc, 0x01f8, 0x909c, 0x0003, 0x939e, 0x0003, - 0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, 0x94ff, 0x080c, 0x9ab1, - 0x0470, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003, - 0x939e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x94ff, - 0x080c, 0x9ab1, 0x00e0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, - 0x080c, 0xebd4, 0x00a0, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, - 0x909c, 0x0003, 0x939e, 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, - 0x2c10, 0x080c, 0x1be0, 0x080c, 0x9564, 0x080c, 0x9bd3, 0x0005, - 0x080c, 0x99a5, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, - 0xef85, 0x0036, 0x2019, 0x0029, 0x080c, 0xebd4, 0x003e, 0x009e, - 0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005, 0x080c, 0x9a61, 0x6114, - 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xef85, 0x0036, 0x2019, - 0x0029, 0x080c, 0xebd4, 0x003e, 0x009e, 0x080c, 0xb306, 0x080c, - 0x9bd3, 0x0005, 0x9182, 0x0085, 0x0002, 0xe694, 0xe692, 0xe692, - 0xe6a0, 0xe692, 0xe692, 0xe692, 0xe692, 0xe692, 0xe692, 0xe692, - 0xe692, 0xe692, 0x080c, 0x0dc5, 0x6003, 0x000b, 0x6106, 0x080c, - 0x94ff, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005, - 0x0026, 0x00e6, 0x080c, 0xee26, 0x0118, 0x080c, 0xb2d3, 0x0450, - 0x2071, 0x0260, 0x7224, 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4, - 0x0150, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011, - 0x014e, 0x080c, 0xb5f5, 0x7220, 0x080c, 0xea29, 0x0118, 0x6007, - 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, - 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, - 0x080c, 0x9bd3, 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, - 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dc5, 0x908a, 0x0092, 0x1a0c, - 0x0dc5, 0x9082, 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, - 0x0014, 0x0118, 0x080c, 0xb36d, 0x0050, 0x2001, 0x0007, 0x080c, - 0x6696, 0x080c, 0x99a5, 0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005, - 0xe705, 0xe707, 0xe707, 0xe705, 0xe705, 0xe705, 0xe705, 0xe705, - 0xe705, 0xe705, 0xe705, 0xe705, 0xe705, 0x080c, 0x0dc5, 0x080c, - 0x99a5, 0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005, 0x9182, 0x0085, - 0x0a0c, 0x0dc5, 0x9182, 0x0092, 0x1a0c, 0x0dc5, 0x9182, 0x0085, - 0x0002, 0xe726, 0xe726, 0xe726, 0xe728, 0xe726, 0xe726, 0xe726, - 0xe726, 0xe726, 0xe726, 0xe726, 0xe726, 0xe726, 0x080c, 0x0dc5, - 0x0005, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186, - 0x0027, 0x0118, 0x080c, 0xb36d, 0x0030, 0x080c, 0x99a5, 0x080c, - 0xb306, 0x080c, 0x9ab1, 0x0005, 0x0036, 0x080c, 0xee87, 0x6043, - 0x0000, 0x2019, 0x000b, 0x0011, 0x003e, 0x0005, 0x6010, 0x0006, - 0x0059, 0x000e, 0x6012, 0x6023, 0x0006, 0x6003, 0x0007, 0x601b, - 0x0000, 0x6043, 0x0000, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000, - 0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e, - 0x1550, 0x0076, 0x2c38, 0x080c, 0xaba6, 0x007e, 0x1520, 0x6000, - 0x9086, 0x0000, 0x0500, 0x6020, 0x9086, 0x0007, 0x01e0, 0x0096, - 0x601c, 0xd084, 0x0140, 0x080c, 0xee87, 0x080c, 0xd7fb, 0x080c, - 0x1a8e, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0110, - 0x080c, 0xebd4, 0x009e, 0x6017, 0x0000, 0x080c, 0xee87, 0x6023, - 0x0007, 0x080c, 0xd7fb, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, - 0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, 0x080c, - 0x2873, 0x1904, 0xe7e4, 0x0016, 0x00c6, 0x080c, 0x6724, 0x1904, - 0xe7e2, 0x001e, 0x00c6, 0x080c, 0xd7e3, 0x1130, 0xb8c0, 0x9005, - 0x0118, 0x080c, 0x33a5, 0x0148, 0x2b10, 0x2160, 0x6010, 0x0006, - 0x6212, 0x080c, 0xd7ea, 0x000e, 0x6012, 0x00ce, 0x002e, 0x0026, - 0x0016, 0x2019, 0x0029, 0x080c, 0xac6c, 0x080c, 0x96a4, 0x0076, - 0x903e, 0x080c, 0x9577, 0x007e, 0x001e, 0x0076, 0x903e, 0x080c, - 0xe91c, 0x007e, 0x0026, 0xba04, 0x9294, 0xff00, 0x8217, 0x9286, - 0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0xbaa0, 0x080c, 0x330e, - 0x002e, 0xbcc0, 0x001e, 0x080c, 0x6148, 0xbe12, 0xbd16, 0xbcc2, - 0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00be, 0x00ce, - 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00b6, 0x0016, 0x2009, 0x1824, - 0x2104, 0x9086, 0x0074, 0x1904, 0xe843, 0x2069, 0x0260, 0x6944, - 0x9182, 0x0100, 0x06e0, 0x6940, 0x9184, 0x8000, 0x0904, 0xe840, - 0x2001, 0x197c, 0x2004, 0x9005, 0x1140, 0x6010, 0x2058, 0xb8c0, - 0x9005, 0x0118, 0x9184, 0x0800, 0x0598, 0x6948, 0x918a, 0x0001, - 0x0648, 0x080c, 0xefed, 0x0118, 0x6978, 0xd1fc, 0x11b8, 0x2009, - 0x0205, 0x200b, 0x0001, 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, - 0x0100, 0x02a8, 0x6940, 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, - 0x0288, 0x6950, 0x918a, 0x0001, 0x0298, 0x00d0, 0x6017, 0x0100, - 0x00a0, 0x6017, 0x0300, 0x0088, 0x6017, 0x0500, 0x0070, 0x6017, - 0x0700, 0x0058, 0x6017, 0x0900, 0x0040, 0x6017, 0x0b00, 0x0028, - 0x6017, 0x0f00, 0x0010, 0x6017, 0x2d00, 0x9085, 0x0001, 0x0008, - 0x9006, 0x001e, 0x00be, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00b6, - 0x0026, 0x0036, 0x0156, 0x6210, 0x2258, 0xbb04, 0x9394, 0x00ff, - 0x9286, 0x0006, 0x0180, 0x9286, 0x0004, 0x0168, 0x9394, 0xff00, - 0x8217, 0x9286, 0x0006, 0x0138, 0x9286, 0x0004, 0x0120, 0x080c, - 0x6733, 0x0804, 0xe8ab, 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x000a, 0x080c, 0xc379, 0x009e, 0x15a8, 0x2011, - 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, - 0xc379, 0x009e, 0x1548, 0x0046, 0x0016, 0xbaa0, 0x2220, 0x9006, - 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, - 0xec31, 0xb800, 0xc0e5, 0xb802, 0x2019, 0x0029, 0x080c, 0x96a4, - 0x0076, 0x2039, 0x0000, 0x080c, 0x9577, 0x2c08, 0x080c, 0xe91c, - 0x007e, 0x2001, 0x0007, 0x080c, 0x6696, 0x2001, 0x0007, 0x080c, - 0x666a, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, 0x00be, - 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, 0x0800, - 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, - 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, 0x7930, - 0x7834, 0x080c, 0x2873, 0x11d0, 0x080c, 0x6724, 0x11b8, 0x2011, - 0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, - 0xc379, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x0006, 0x080c, 0xc379, 0x009e, 0x015e, 0x003e, - 0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x0006, 0x0016, - 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, - 0x080c, 0x2873, 0x11d0, 0x080c, 0x6724, 0x11b8, 0x2011, 0x0276, - 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xc379, - 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, - 0x2019, 0x0006, 0x080c, 0xc379, 0x009e, 0x015e, 0x003e, 0x002e, - 0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, - 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, - 0x2029, 0x19f1, 0x252c, 0x2021, 0x19f7, 0x2424, 0x2061, 0x1cd0, - 0x2071, 0x1800, 0x7654, 0x7074, 0x81ff, 0x0150, 0x0006, 0x9186, - 0x1ab7, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, 0xe9ba, 0x0018, - 0x9606, 0x0904, 0xe9ba, 0x080c, 0x8cf7, 0x0904, 0xe9b1, 0x2100, - 0x9c06, 0x0904, 0xe9b1, 0x6720, 0x9786, 0x0007, 0x0904, 0xe9b1, - 0x080c, 0xec72, 0x1904, 0xe9b1, 0x080c, 0xf00b, 0x0904, 0xe9b1, - 0x080c, 0xec62, 0x0904, 0xe9b1, 0x6720, 0x9786, 0x0001, 0x1148, - 0x080c, 0x33a5, 0x0904, 0xe9f9, 0x6004, 0x9086, 0x0000, 0x1904, - 0xe9f9, 0x9786, 0x0004, 0x0904, 0xe9f9, 0x2500, 0x9c06, 0x0904, - 0xe9b1, 0x2400, 0x9c06, 0x05e8, 0x88ff, 0x0118, 0x6054, 0x9906, - 0x15c0, 0x0096, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, - 0x1a8e, 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xd2e0, 0x1130, - 0x080c, 0xbcb6, 0x009e, 0x080c, 0xb306, 0x0418, 0x6014, 0x2048, - 0x080c, 0xd0d8, 0x01d8, 0x9786, 0x0003, 0x1570, 0xa867, 0x0103, - 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fc0, - 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0xef85, 0x0016, 0x080c, - 0xd3ce, 0x080c, 0x6e92, 0x001e, 0x080c, 0xd2c3, 0x009e, 0x080c, - 0xb306, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1210, - 0x0804, 0xe930, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, - 0x008e, 0x00ce, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1150, 0x9386, - 0x0005, 0x0128, 0x080c, 0xef85, 0x080c, 0xebd4, 0x08f8, 0x009e, - 0x0c00, 0x9786, 0x0009, 0x11f8, 0x6000, 0x9086, 0x0004, 0x01c0, - 0x6000, 0x9086, 0x0003, 0x11a0, 0x080c, 0x9a61, 0x0096, 0x6114, - 0x2148, 0x080c, 0xd0d8, 0x0118, 0x6010, 0x080c, 0x6e9f, 0x009e, - 0x00c6, 0x080c, 0xb2d3, 0x00ce, 0x0036, 0x080c, 0x9bd3, 0x003e, - 0x009e, 0x0804, 0xe9b1, 0x9786, 0x000a, 0x0904, 0xe9a1, 0x0804, - 0xe996, 0x81ff, 0x0904, 0xe9b1, 0x9180, 0x0001, 0x2004, 0x9086, - 0x0018, 0x0138, 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, 0x1904, - 0xe9b1, 0x6000, 0x9086, 0x0002, 0x1904, 0xe9b1, 0x080c, 0xd2cf, - 0x0138, 0x080c, 0xd2e0, 0x1904, 0xe9b1, 0x080c, 0xbcb6, 0x0038, - 0x080c, 0x3279, 0x080c, 0xd2e0, 0x1110, 0x080c, 0xbcb6, 0x080c, - 0xb306, 0x0804, 0xe9b1, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, - 0x0005, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0x9006, 0x080c, - 0xebfb, 0x001e, 0x0120, 0x6020, 0x9084, 0x000f, 0x001b, 0x00ee, - 0x00ce, 0x0005, 0xea48, 0xea48, 0xea48, 0xea48, 0xea48, 0xea48, - 0xea4a, 0xea48, 0xea48, 0xea48, 0xea73, 0xb306, 0xb306, 0xea48, - 0x9006, 0x0005, 0x0036, 0x0046, 0x0016, 0x7010, 0x00b6, 0x2058, - 0xbca0, 0x00be, 0x2c00, 0x2009, 0x0020, 0x080c, 0xec31, 0x001e, - 0x004e, 0x2019, 0x0002, 0x080c, 0xe754, 0x003e, 0x9085, 0x0001, - 0x0005, 0x0096, 0x080c, 0xd0d8, 0x0140, 0x6014, 0x904d, 0x080c, - 0xccf3, 0x687b, 0x0005, 0x080c, 0x6e9f, 0x009e, 0x080c, 0xb306, - 0x9085, 0x0001, 0x0005, 0x0019, 0x9085, 0x0001, 0x0005, 0x6000, - 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x000b, 0x0005, 0xea8e, 0xea8e, - 0xeaa5, 0xea95, 0xeab4, 0xea8e, 0xea8e, 0xea90, 0xea8e, 0xea8e, - 0xea8e, 0xea8e, 0xea8e, 0xea8e, 0xea8e, 0xea8e, 0x080c, 0x0dc5, - 0x080c, 0xb306, 0x9085, 0x0001, 0x0005, 0x0036, 0x00e6, 0x2071, - 0x19e8, 0x703c, 0x9c06, 0x1128, 0x2019, 0x0001, 0x080c, 0xaa49, - 0x0010, 0x080c, 0xac2b, 0x00ee, 0x003e, 0x0096, 0x00d6, 0x6014, - 0x2048, 0xa87b, 0x0005, 0x080c, 0x6e9f, 0x080c, 0xb306, 0x00de, - 0x009e, 0x9085, 0x0001, 0x0005, 0x601c, 0xd084, 0x190c, 0x1a8e, - 0x0c60, 0x2001, 0x0001, 0x080c, 0x6656, 0x0156, 0x0016, 0x0026, - 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, - 0xc365, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6, - 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x00b6, 0x0126, 0x2091, - 0x8000, 0x2740, 0x2061, 0x1cd0, 0x2079, 0x0001, 0x8fff, 0x0904, - 0xeb2b, 0x2071, 0x1800, 0x7654, 0x7074, 0x8001, 0x9602, 0x1a04, - 0xeb2b, 0x88ff, 0x0120, 0x2800, 0x9c06, 0x15a0, 0x2078, 0x080c, - 0xec62, 0x0580, 0x2400, 0x9c06, 0x0568, 0x6720, 0x9786, 0x0006, - 0x1548, 0x9786, 0x0007, 0x0530, 0x88ff, 0x1150, 0xd58c, 0x1118, - 0x6010, 0x9b06, 0x11f8, 0xd584, 0x0118, 0x6054, 0x9106, 0x11d0, - 0x0096, 0x601c, 0xd084, 0x0140, 0x080c, 0xee87, 0x080c, 0xd7fb, - 0x080c, 0x1a8e, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xd0d8, - 0x0120, 0x0046, 0x080c, 0xebd4, 0x004e, 0x009e, 0x080c, 0xb306, - 0x88ff, 0x1198, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, - 0x1210, 0x0804, 0xeade, 0x9006, 0x012e, 0x00be, 0x006e, 0x007e, - 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x98c5, 0x0001, 0x0ca0, - 0x00b6, 0x0076, 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, - 0x2019, 0x0002, 0x6210, 0x2258, 0x0096, 0x904e, 0x080c, 0xaafb, - 0x009e, 0x008e, 0x903e, 0x080c, 0xaba6, 0x080c, 0xeacf, 0x005e, - 0x007e, 0x00be, 0x0005, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, - 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036, - 0x080c, 0x6724, 0x1180, 0x0056, 0x0086, 0x9046, 0x2508, 0x2029, - 0x0001, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e, 0x903e, - 0x080c, 0xaba6, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xeb5e, - 0x0036, 0x2508, 0x2029, 0x0003, 0x080c, 0xeacf, 0x003e, 0x015e, - 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x0005, 0x00b6, 0x0076, - 0x0056, 0x6210, 0x2258, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, - 0x0048, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e, 0x903e, - 0x080c, 0xaba6, 0x2c20, 0x080c, 0xeacf, 0x005e, 0x007e, 0x00be, - 0x0005, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20, - 0x20a9, 0x0800, 0x900e, 0x0016, 0x0036, 0x080c, 0x6724, 0x1190, - 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, 0xee6b, - 0x004e, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e, 0x903e, - 0x080c, 0xaba6, 0x003e, 0x001e, 0x8108, 0x1f04, 0xebab, 0x0036, - 0x2029, 0x0002, 0x080c, 0xeacf, 0x003e, 0x015e, 0x00ce, 0x007e, - 0x005e, 0x004e, 0x00be, 0x0005, 0x0016, 0x00f6, 0x080c, 0xd0d6, - 0x0198, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0046, 0x0180, 0xa800, - 0x907d, 0x0138, 0xa803, 0x0000, 0xab82, 0x080c, 0x6e9f, 0x2f48, - 0x0cb0, 0xab82, 0x080c, 0x6e9f, 0x00fe, 0x001e, 0x0005, 0xa800, - 0x907d, 0x0130, 0xa803, 0x0000, 0x080c, 0x6e9f, 0x2f48, 0x0cb8, - 0x080c, 0x6e9f, 0x0c88, 0x00e6, 0x0046, 0x0036, 0x2061, 0x1cd0, - 0x9005, 0x1138, 0x2071, 0x1800, 0x7454, 0x7074, 0x8001, 0x9402, - 0x12f8, 0x2100, 0x9c06, 0x0188, 0x6000, 0x9086, 0x0000, 0x0168, - 0x6008, 0x9206, 0x1150, 0x6320, 0x9386, 0x0009, 0x01b0, 0x6010, - 0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, 0x0018, 0x2001, - 0x181a, 0x2004, 0x9c02, 0x1220, 0x0c20, 0x9085, 0x0001, 0x0008, - 0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x631c, 0xd3c4, 0x1d68, - 0x0c30, 0x0096, 0x0006, 0x080c, 0x100e, 0x000e, 0x090c, 0x0dc5, - 0xaae2, 0xa867, 0x010d, 0xa88e, 0x0026, 0x2010, 0x080c, 0xd0c6, - 0x2001, 0x0000, 0x0120, 0x2200, 0x9080, 0x0015, 0x2004, 0x002e, - 0xa87a, 0x9186, 0x0020, 0x0110, 0xa8e3, 0xffff, 0xa986, 0xac76, - 0xa87f, 0x0000, 0x2001, 0x198e, 0x2004, 0xa882, 0x9006, 0xa802, - 0xa86a, 0xa88a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, - 0x009e, 0x0005, 0x6700, 0x9786, 0x0000, 0x0158, 0x9786, 0x0001, - 0x0140, 0x9786, 0x000a, 0x0128, 0x9786, 0x0009, 0x0110, 0x9085, - 0x0001, 0x0005, 0x00e6, 0x6010, 0x9075, 0x0138, 0x00b6, 0x2058, - 0xb8a0, 0x00be, 0x9206, 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cd8, - 0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, 0x8007, 0x6134, 0x918c, - 0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, - 0x0005, 0x2001, 0x1987, 0x2004, 0x601a, 0x080c, 0x94ff, 0x080c, - 0x9ab1, 0x001e, 0x0005, 0xa001, 0xa001, 0x0005, 0x6024, 0xd0e4, - 0x0158, 0xd0cc, 0x0118, 0x080c, 0xd412, 0x0030, 0x080c, 0xee87, - 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x0005, 0x9280, 0x0008, 0x2004, - 0x9084, 0x000f, 0x0002, 0xecc1, 0xecc1, 0xecc1, 0xecc3, 0xecc1, - 0xecc3, 0xecc3, 0xecc1, 0xecc3, 0xecc1, 0xecc1, 0xecc1, 0xecc1, - 0xecc1, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x9280, 0x0008, - 0x2004, 0x9084, 0x000f, 0x0002, 0xecda, 0xecda, 0xecda, 0xecda, - 0xecda, 0xecda, 0xece7, 0xecda, 0xecda, 0xecda, 0xecda, 0xecda, - 0xecda, 0xecda, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00, - 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005, 0x0096, - 0x00c6, 0x2260, 0x080c, 0xee87, 0x6043, 0x0000, 0x6024, 0xc0f4, - 0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, 0x00d6, 0x2268, 0x9186, - 0x0007, 0x1904, 0xed40, 0x6814, 0x9005, 0x0138, 0x2048, 0xa87c, - 0xd0fc, 0x1118, 0x00de, 0x009e, 0x08a8, 0x6007, 0x003a, 0x6003, - 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x00c6, 0x2d60, 0x6100, - 0x9186, 0x0002, 0x1904, 0xedb0, 0x6014, 0x9005, 0x1138, 0x6000, - 0x9086, 0x0007, 0x190c, 0x0dc5, 0x0804, 0xedb0, 0x2048, 0x080c, - 0xd0d8, 0x1130, 0x0028, 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, - 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x1168, 0xa87c, - 0xc0dc, 0xc0f4, 0xa87e, 0xa880, 0xc0fc, 0xa882, 0x2009, 0x0043, - 0x080c, 0xe59e, 0x0804, 0xedb0, 0x2009, 0x0041, 0x0804, 0xedaa, - 0x9186, 0x0005, 0x15a0, 0x6814, 0x2048, 0xa87c, 0xd0bc, 0x1120, - 0x00de, 0x009e, 0x0804, 0xecda, 0xd0b4, 0x0128, 0xd0fc, 0x090c, - 0x0dc5, 0x0804, 0xecfb, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, - 0x94ff, 0x080c, 0x9ab1, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, - 0x0120, 0x9186, 0x0004, 0x1904, 0xedb0, 0x6814, 0x2048, 0xa97c, - 0xc1f4, 0xc1dc, 0xa97e, 0xa980, 0xc1fc, 0xc1bc, 0xa982, 0x00f6, - 0x2c78, 0x080c, 0x1768, 0x00fe, 0x2009, 0x0042, 0x0498, 0x0036, - 0x080c, 0x100e, 0x090c, 0x0dc5, 0xa867, 0x010d, 0x9006, 0xa802, - 0xa86a, 0xa88a, 0x2d18, 0xab8e, 0xa887, 0x0045, 0x2c00, 0xa892, - 0x6038, 0xa8a2, 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6010, 0x00b6, - 0x2058, 0xb8a0, 0x00be, 0x2004, 0x6354, 0xab7a, 0xa876, 0x9006, - 0xa87e, 0xa882, 0xad9a, 0xae96, 0xa89f, 0x0001, 0x080c, 0x6e9f, - 0x2019, 0x0045, 0x6008, 0x2068, 0x080c, 0xe746, 0x2d00, 0x600a, - 0x003e, 0x0038, 0x6043, 0x0000, 0x6003, 0x0007, 0x080c, 0xe59e, - 0x00ce, 0x00de, 0x009e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, - 0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, 0x1178, 0x080c, - 0x99a5, 0x0036, 0x0096, 0x6014, 0x2048, 0x2019, 0x0004, 0x080c, - 0xebd4, 0x009e, 0x003e, 0x080c, 0x9ab1, 0x0005, 0x9186, 0x0014, - 0x0d70, 0x080c, 0xb36d, 0x0005, 0xede3, 0xede1, 0xede1, 0xede1, - 0xede1, 0xede1, 0xede3, 0xede1, 0xede1, 0xede1, 0xede1, 0xede1, - 0xede1, 0x080c, 0x0dc5, 0x080c, 0x99a5, 0x6003, 0x000c, 0x080c, - 0x9ab1, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208, - 0x001a, 0x080c, 0xb36d, 0x0005, 0xee01, 0xee01, 0xee01, 0xee01, - 0xee03, 0xee23, 0xee01, 0xee01, 0xee01, 0xee01, 0xee01, 0xee01, - 0xee01, 0x080c, 0x0dc5, 0x00d6, 0x2c68, 0x080c, 0xb27d, 0x01b0, - 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, 0x210c, 0x613a, - 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, 0x6910, 0x6112, - 0x6023, 0x0004, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x2d60, 0x080c, - 0xb2d3, 0x00de, 0x0005, 0x080c, 0xb2d3, 0x0005, 0x00e6, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee, 0x0005, 0x2009, - 0x1867, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, 0x6024, 0xc0e5, - 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1988, 0x2004, 0x6042, 0x2009, - 0x1867, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, 0x1867, 0x210c, - 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, 0x00d8, 0x2001, - 0x1988, 0x200c, 0x2001, 0x1986, 0x2004, 0x9100, 0x9080, 0x000a, - 0x6042, 0x6010, 0x00b6, 0x2058, 0xb8bc, 0x00be, 0x0008, 0x2104, - 0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, - 0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, 0x6154, 0xb8bc, - 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6054, 0x9106, 0x1138, - 0x600c, 0x2072, 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x0010, 0x9cf0, - 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, - 0x00b6, 0x6010, 0x2058, 0xb8bc, 0x906d, 0x0130, 0x9c06, 0x0110, - 0x680c, 0x0cd0, 0x600c, 0x680e, 0x00be, 0x00de, 0x0005, 0x0026, - 0x0036, 0x0156, 0x2011, 0x182c, 0x2204, 0x9084, 0x00ff, 0x2019, - 0x026e, 0x2334, 0x96b4, 0x00ff, 0x9636, 0x1508, 0x8318, 0x2334, - 0x2204, 0x9084, 0xff00, 0x9636, 0x11d0, 0x2011, 0x0270, 0x20a9, - 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xc379, - 0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, 0x0004, 0x6010, 0x0096, - 0x2048, 0x2019, 0x0006, 0x080c, 0xc379, 0x009e, 0x1100, 0x015e, - 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, 0x60c1, - 0x080c, 0x3000, 0x00ee, 0x0005, 0x0096, 0x0026, 0x080c, 0x100e, - 0x090c, 0x0dc5, 0xa85c, 0x9080, 0x001a, 0x20a0, 0x20a9, 0x000c, - 0xa860, 0x20e8, 0x9006, 0x4004, 0x9186, 0x0046, 0x1118, 0xa867, - 0x0136, 0x0038, 0xa867, 0x0138, 0x9186, 0x0041, 0x0110, 0xa87b, - 0x0001, 0x7038, 0x9084, 0xff00, 0x7240, 0x9294, 0xff00, 0x8007, - 0x9215, 0xaa9a, 0x9186, 0x0046, 0x1168, 0x7038, 0x9084, 0x00ff, - 0x723c, 0x9294, 0xff00, 0x9215, 0xaa9e, 0x723c, 0x9294, 0x00ff, - 0xaaa2, 0x0060, 0x7040, 0x9084, 0x00ff, 0x7244, 0x9294, 0xff00, - 0x9215, 0xaa9e, 0x7244, 0x9294, 0x00ff, 0xaaa2, 0x9186, 0x0046, - 0x1118, 0x9e90, 0x0012, 0x0010, 0x9e90, 0x001a, 0x2204, 0x8007, - 0xa8a6, 0x8210, 0x2204, 0x8007, 0xa8aa, 0x8210, 0x2204, 0x8007, - 0xa8ae, 0x8210, 0x2204, 0x8007, 0xa8b2, 0x8210, 0x9186, 0x0046, - 0x11b8, 0x9e90, 0x0016, 0x2204, 0x8007, 0xa8b6, 0x8210, 0x2204, - 0x8007, 0xa8ba, 0x8210, 0x2204, 0x8007, 0xa8be, 0x8210, 0x2204, - 0x8007, 0xa8c2, 0x8210, 0x2011, 0x0205, 0x2013, 0x0001, 0x00b0, - 0x9e90, 0x001e, 0x2204, 0x8007, 0xa8b6, 0x8210, 0x2204, 0x8007, - 0xa8ba, 0x2011, 0x0205, 0x2013, 0x0001, 0x2011, 0x0260, 0x2204, - 0x8007, 0xa8be, 0x8210, 0x2204, 0x8007, 0xa8c2, 0x9186, 0x0046, - 0x1118, 0x2011, 0x0262, 0x0010, 0x2011, 0x026a, 0x0146, 0x01d6, - 0x0036, 0x20a9, 0x0001, 0x2019, 0x0008, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x0031, 0x20a0, 0x2204, 0x8007, 0x4004, 0x8210, 0x8319, - 0x1dd0, 0x003e, 0x01ce, 0x013e, 0x2011, 0x0205, 0x2013, 0x0000, - 0x002e, 0x080c, 0x6e9f, 0x009e, 0x0005, 0x00e6, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, - 0xa880, 0xc0e5, 0xa882, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, - 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, 0x8000, - 0x2029, 0x19f1, 0x252c, 0x2021, 0x19f7, 0x2424, 0x2061, 0x1cd0, - 0x2071, 0x1800, 0x7654, 0x7074, 0x9606, 0x0578, 0x6720, 0x9786, - 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, 0x01e8, - 0x2400, 0x9c06, 0x01d0, 0x080c, 0xec62, 0x01b8, 0x080c, 0xec72, - 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1a8e, - 0x001e, 0x080c, 0xd2cf, 0x1110, 0x080c, 0x3279, 0x080c, 0xd2e0, - 0x1110, 0x080c, 0xbcb6, 0x080c, 0xb306, 0x9ce0, 0x0018, 0x2001, - 0x181a, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, 0x002e, - 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, - 0x2001, 0x1810, 0x2004, 0xd0dc, 0x0005, 0x0006, 0x2001, 0x1837, - 0x2004, 0xd09c, 0x000e, 0x0005, 0x0006, 0x0036, 0x0046, 0x080c, - 0xd7e3, 0x0168, 0x2019, 0xffff, 0x9005, 0x0128, 0x6010, 0x00b6, - 0x2058, 0xbba0, 0x00be, 0x2021, 0x0004, 0x080c, 0x4dfb, 0x004e, - 0x003e, 0x000e, 0x0005, 0x6004, 0x9086, 0x0001, 0x1128, 0x080c, - 0xac6c, 0x080c, 0xb306, 0x9006, 0x0005, 0x00e6, 0x00c6, 0x00b6, - 0x0046, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7454, 0x7074, 0x8001, - 0x9402, 0x12d8, 0x2100, 0x9c06, 0x0168, 0x6000, 0x9086, 0x0000, - 0x0148, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1120, 0x6004, 0x9086, - 0x0002, 0x0140, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, - 0x1220, 0x0c40, 0x9085, 0x0001, 0x0008, 0x9006, 0x004e, 0x00be, - 0x00ce, 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0a4, 0x0160, - 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0138, 0x2001, 0x1848, 0x2004, - 0xd0a4, 0x1118, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0126, - 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, 0x1840, 0xd5a4, - 0x0118, 0x7004, 0x8000, 0x7006, 0xd5b4, 0x0118, 0x7000, 0x8000, - 0x7002, 0xd5ac, 0x0178, 0x2500, 0x9084, 0x0007, 0x908e, 0x0003, - 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x2071, - 0xfff6, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, - 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xffee, 0x0021, 0x00ee, - 0x000e, 0x012e, 0x0005, 0x2e05, 0x8000, 0x2077, 0x1220, 0x8e70, - 0x2e05, 0x8000, 0x2077, 0x0005, 0x00e6, 0x2071, 0xffec, 0x0c99, - 0x00ee, 0x0005, 0x00e6, 0x2071, 0xfff0, 0x0c69, 0x00ee, 0x0005, - 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x1840, 0x7014, - 0x8000, 0x7016, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0003, 0x000b, - 0x07d2, 0x0000, 0xc000, 0x0001, 0x8064, 0x0008, 0x0010, 0x0000, - 0x8066, 0x0000, 0x0101, 0x0008, 0x4407, 0x0003, 0x8060, 0x0000, - 0x0400, 0x0000, 0x580d, 0x000b, 0x79c0, 0x0003, 0x5106, 0x0003, - 0x4c0a, 0x0003, 0xbac0, 0x0009, 0x008a, 0x0000, 0x0c0a, 0x000b, - 0x15fe, 0x0008, 0x340a, 0x0003, 0xc4c0, 0x0009, 0x7000, 0x0000, - 0xffa0, 0x0001, 0x2000, 0x0000, 0x1680, 0x000b, 0x808c, 0x0008, - 0x0001, 0x0000, 0x0000, 0x0007, 0x4028, 0x0000, 0x4047, 0x000a, - 0x808c, 0x0008, 0x0002, 0x0000, 0x0822, 0x0003, 0x4022, 0x0000, - 0x0028, 0x000b, 0x4122, 0x0008, 0x94c0, 0x0009, 0xff00, 0x0008, - 0xffe0, 0x0009, 0x0500, 0x0008, 0x0aab, 0x0003, 0x4447, 0x0002, - 0x0ea8, 0x000b, 0x0bfe, 0x0008, 0x11a0, 0x0001, 0x1286, 0x0003, - 0x0ca0, 0x0001, 0x1286, 0x0003, 0x9180, 0x0001, 0x0004, 0x0000, - 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x0009, 0x0008, 0x4436, 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, - 0x0060, 0x0008, 0x8062, 0x0008, 0x0004, 0x0000, 0x8066, 0x0000, - 0x0411, 0x0000, 0x443e, 0x0003, 0x03fe, 0x0000, 0x43e0, 0x0001, - 0x0e83, 0x000b, 0xc2c0, 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001, - 0x0e83, 0x000b, 0x9180, 0x0001, 0x0005, 0x0008, 0x8060, 0x0000, - 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0019, 0x0000, - 0x444d, 0x000b, 0x0240, 0x0002, 0x0a80, 0x0003, 0x00fe, 0x0000, - 0x3283, 0x000b, 0x0248, 0x000a, 0x085c, 0x0003, 0x9180, 0x0001, - 0x0006, 0x0008, 0x7f62, 0x0008, 0x8002, 0x0008, 0x0003, 0x0008, - 0x8066, 0x0000, 0x020a, 0x0000, 0x445b, 0x0003, 0x112a, 0x0000, - 0x002e, 0x0008, 0x022c, 0x0008, 0x3a44, 0x0002, 0x0c0a, 0x000b, - 0x808c, 0x0008, 0x0002, 0x0000, 0x1760, 0x0008, 0x8062, 0x0008, - 0x000f, 0x0008, 0x8066, 0x0000, 0x0011, 0x0008, 0x4468, 0x0003, - 0x01fe, 0x0008, 0x42e0, 0x0009, 0x0e74, 0x0003, 0x00fe, 0x0000, - 0x43e0, 0x0001, 0x0e74, 0x0003, 0x1734, 0x0000, 0x1530, 0x0000, - 0x1632, 0x0008, 0x0d2a, 0x0008, 0x9880, 0x0001, 0x0010, 0x0000, - 0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x1e0a, 0x0008, 0x447a, 0x0003, 0x808a, 0x0008, 0x0003, 0x0008, - 0x1a60, 0x0000, 0x8062, 0x0008, 0x0002, 0x0000, 0x5880, 0x000b, - 0x8066, 0x0000, 0x3679, 0x0000, 0x4483, 0x0003, 0x5884, 0x0003, - 0x3efe, 0x0008, 0x7f4f, 0x0002, 0x088a, 0x000b, 0x0d00, 0x0000, - 0x0092, 0x000c, 0x8054, 0x0008, 0x0011, 0x0008, 0x8074, 0x0000, - 0x1010, 0x0008, 0x1efe, 0x0000, 0x300a, 0x000b, 0x00e0, 0x000c, - 0x000a, 0x000b, 0x00fe, 0x0000, 0x349a, 0x0003, 0x1a60, 0x0000, - 0x8062, 0x0008, 0x0007, 0x0000, 0x8066, 0x0000, 0x0231, 0x0008, - 0x4499, 0x000b, 0x03fe, 0x0000, 0x04d0, 0x0001, 0x0cd4, 0x000b, - 0x82c0, 0x0001, 0x1f00, 0x0000, 0xffa0, 0x0001, 0x0400, 0x0000, - 0x08b2, 0x0003, 0x14dc, 0x0003, 0x01fe, 0x0008, 0x0580, 0x0009, - 0x7f06, 0x0000, 0x8690, 0x0009, 0x0000, 0x0008, 0x7f0c, 0x0000, - 0x02fe, 0x0008, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x0680, 0x0009, - 0x10b2, 0x0003, 0x7f08, 0x0008, 0x84c0, 0x0001, 0xff00, 0x0008, - 0x08d4, 0x0003, 0xb9c0, 0x0009, 0x0030, 0x0008, 0x0cc3, 0x000b, - 0x8060, 0x0000, 0x0400, 0x0000, 0x80fe, 0x0008, 0x1a0a, 0x0009, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0409, 0x0000, 0x44bc, 0x0003, - 0x80fe, 0x0008, 0x1a09, 0x0009, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x040a, 0x0000, 0x44c2, 0x0003, 0x00fe, 0x0000, 0x34ca, 0x0003, - 0x8072, 0x0000, 0x1010, 0x0008, 0x3944, 0x0002, 0x08c5, 0x0003, - 0x00ce, 0x0003, 0x8072, 0x0000, 0x2020, 0x0008, 0x3945, 0x000a, - 0x08ca, 0x0003, 0x3946, 0x000a, 0x0cdb, 0x000b, 0x0000, 0x0007, - 0x3943, 0x000a, 0x08db, 0x0003, 0x00ce, 0x0003, 0x00fe, 0x0000, - 0x34d9, 0x000b, 0x8072, 0x0000, 0x1000, 0x0000, 0x00db, 0x000b, - 0x8072, 0x0000, 0x2000, 0x0000, 0x4000, 0x000f, 0x86c0, 0x0009, - 0xfc00, 0x0008, 0x08d4, 0x0003, 0x00b2, 0x000b, 0x1c60, 0x0000, - 0x1b62, 0x0000, 0x8066, 0x0000, 0x0231, 0x0008, 0x44e4, 0x000b, - 0x58e5, 0x000b, 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, 0x0002, - 0x0cf3, 0x000b, 0x0d44, 0x0000, 0x0d46, 0x0008, 0x0348, 0x0008, - 0x044a, 0x0008, 0x030a, 0x0008, 0x040c, 0x0000, 0x0d06, 0x0000, - 0x0d08, 0x0008, 0x00f7, 0x0003, 0x0344, 0x0008, 0x0446, 0x0008, - 0x0548, 0x0008, 0x064a, 0x0000, 0x1948, 0x000a, 0x08fa, 0x0003, - 0x0d4a, 0x0008, 0x58fa, 0x0003, 0x3efe, 0x0008, 0x7f4f, 0x0002, - 0x0901, 0x0003, 0x8000, 0x0000, 0x0001, 0x0000, 0x0092, 0x000c, - 0x8054, 0x0008, 0x0001, 0x0000, 0x8074, 0x0000, 0x2020, 0x0008, - 0x4000, 0x000f, 0x3a40, 0x000a, 0x0c0d, 0x0003, 0x2b24, 0x0008, - 0x2b24, 0x0008, 0x590a, 0x000b, 0x8054, 0x0008, 0x0002, 0x0000, - 0x1242, 0x0002, 0x0958, 0x0003, 0x3a45, 0x000a, 0x0947, 0x000b, - 0x8072, 0x0000, 0x1000, 0x0000, 0x3945, 0x000a, 0x0917, 0x000b, - 0x8072, 0x0000, 0x3010, 0x0000, 0x1e10, 0x000a, 0x7f3c, 0x0000, - 0x0942, 0x000b, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x4520, 0x000b, - 0x00fe, 0x0000, 0x353f, 0x000b, 0x1c60, 0x0000, 0x8062, 0x0008, - 0x0001, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, 0x4528, 0x0003, - 0x00fe, 0x0000, 0x325b, 0x000b, 0x0038, 0x0000, 0x0060, 0x0008, - 0x8062, 0x0008, 0x0019, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, - 0x4531, 0x000b, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, 0x0008, - 0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, 0x7f62, 0x0008, - 0x8066, 0x0000, 0x0009, 0x0008, 0x453b, 0x000b, 0x003a, 0x0008, - 0x1dfe, 0x0000, 0x011c, 0x000b, 0x0036, 0x0008, 0x00e0, 0x000c, - 0x0158, 0x000b, 0x8074, 0x0000, 0x2000, 0x0000, 0x8072, 0x0000, - 0x2000, 0x0000, 0x0158, 0x000b, 0x3a44, 0x0002, 0x0a89, 0x0003, - 0x8074, 0x0000, 0x1000, 0x0000, 0x8072, 0x0000, 0x1000, 0x0000, - 0x2d0e, 0x0000, 0x2d0e, 0x0000, 0x3658, 0x0003, 0x26fe, 0x0008, - 0x26fe, 0x0008, 0x2700, 0x0008, 0x2700, 0x0008, 0x00d0, 0x0009, - 0x0d6a, 0x0003, 0x8074, 0x0000, 0x4040, 0x0008, 0x5958, 0x0003, - 0x5106, 0x0003, 0x3a46, 0x000a, 0x0d6a, 0x0003, 0x3a47, 0x0002, - 0x0965, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, - 0x8000, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x01b4, 0x0003, - 0x92c0, 0x0009, 0x0fc8, 0x0000, 0x080a, 0x0003, 0x1246, 0x000a, - 0x0e52, 0x000b, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0002, 0x0000, - 0x8066, 0x0000, 0x362a, 0x0000, 0x456f, 0x0003, 0x2000, 0x0000, - 0x2000, 0x0000, 0x2102, 0x0000, 0x2102, 0x0000, 0x2204, 0x0000, - 0x2204, 0x0000, 0x2306, 0x0000, 0x2306, 0x0000, 0x2408, 0x0000, - 0x2408, 0x0000, 0x250a, 0x0000, 0x250a, 0x0000, 0x260c, 0x0000, - 0x260c, 0x0000, 0x270e, 0x0000, 0x270e, 0x0000, 0x2810, 0x0000, - 0x2810, 0x0000, 0x2912, 0x0000, 0x2912, 0x0000, 0x1a60, 0x0000, - 0x8062, 0x0008, 0x0007, 0x0000, 0x8066, 0x0000, 0x0052, 0x0000, - 0x4589, 0x000b, 0x92c0, 0x0009, 0x0780, 0x0008, 0x0e6e, 0x000b, - 0x124b, 0x0002, 0x0992, 0x0003, 0x2e4d, 0x0002, 0x2e4d, 0x0002, - 0x0a58, 0x0003, 0x3a46, 0x000a, 0x0da2, 0x000b, 0x5994, 0x0003, - 0x8054, 0x0008, 0x0004, 0x0000, 0x1243, 0x000a, 0x09b0, 0x0003, - 0x8010, 0x0008, 0x000d, 0x0000, 0x0233, 0x000c, 0x1948, 0x000a, - 0x099f, 0x000b, 0x0228, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c, - 0x01b0, 0x000b, 0x1948, 0x000a, 0x09a6, 0x000b, 0x1243, 0x000a, - 0x0a5b, 0x0003, 0x194d, 0x000a, 0x09aa, 0x000b, 0x1243, 0x000a, - 0x0a62, 0x0003, 0x59aa, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, - 0x0228, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c, 0x8074, 0x0000, - 0xf000, 0x0008, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, 0x0000, - 0x3a42, 0x0002, 0x0dba, 0x000b, 0x15fe, 0x0008, 0x3461, 0x000b, - 0x000a, 0x000b, 0x8074, 0x0000, 0x0501, 0x0000, 0x8010, 0x0008, - 0x000c, 0x0008, 0x0233, 0x000c, 0x000a, 0x000b, 0xbbe0, 0x0009, - 0x0030, 0x0008, 0x0dd0, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, - 0x09cd, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x09cd, 0x0003, - 0x0223, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x0220, 0x000b, - 0x8076, 0x0008, 0x0041, 0x0008, 0x0220, 0x000b, 0xbbe0, 0x0009, - 0x0032, 0x0000, 0x0dd5, 0x000b, 0x3c1e, 0x0008, 0x0220, 0x000b, - 0xbbe0, 0x0009, 0x003b, 0x0000, 0x0dda, 0x000b, 0x3c20, 0x0000, - 0x0220, 0x000b, 0xbbe0, 0x0009, 0x0035, 0x0008, 0x0de0, 0x000b, - 0x8072, 0x0000, 0x8000, 0x0000, 0x039e, 0x0003, 0xbbe0, 0x0009, - 0x0036, 0x0008, 0x0abd, 0x000b, 0xbbe0, 0x0009, 0x0037, 0x0000, - 0x0e01, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0dcd, 0x000b, - 0x8076, 0x0008, 0x0040, 0x0000, 0x1a60, 0x0000, 0x8062, 0x0008, - 0x000d, 0x0000, 0x2604, 0x0008, 0x2604, 0x0008, 0x2706, 0x0008, - 0x2706, 0x0008, 0x2808, 0x0000, 0x2808, 0x0000, 0x290a, 0x0000, - 0x290a, 0x0000, 0x8066, 0x0000, 0x0422, 0x0000, 0x45f8, 0x000b, - 0x0228, 0x000c, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000, - 0xf000, 0x0008, 0x8072, 0x0000, 0xb000, 0x0000, 0x01b4, 0x0003, - 0xbbe0, 0x0009, 0x0038, 0x0000, 0x0e13, 0x000b, 0x18fe, 0x0000, - 0x3ce0, 0x0009, 0x0a10, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, - 0x0dc9, 0x0003, 0x0223, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, - 0x8072, 0x0000, 0x8000, 0x0000, 0x0280, 0x000b, 0x8076, 0x0008, - 0x0042, 0x0008, 0x0220, 0x000b, 0xbbe0, 0x0009, 0x0016, 0x0000, - 0x0e20, 0x000b, 0x8074, 0x0000, 0x0808, 0x0008, 0x3a44, 0x0002, - 0x0c0c, 0x000b, 0x8074, 0x0000, 0x0800, 0x0000, 0x8072, 0x0000, - 0x8000, 0x0000, 0x8000, 0x000f, 0x000a, 0x000b, 0x8072, 0x0000, - 0x8000, 0x0000, 0x000a, 0x000b, 0x3d30, 0x000a, 0x7f00, 0x0000, - 0xbc80, 0x0001, 0x0007, 0x0000, 0x022c, 0x000b, 0x1930, 0x000a, - 0x7f00, 0x0000, 0x9880, 0x0001, 0x0007, 0x0000, 0x8060, 0x0000, - 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x000a, 0x0008, - 0x4631, 0x000b, 0x4000, 0x000f, 0x2236, 0x000b, 0x0870, 0x0008, - 0x4000, 0x000f, 0x7e33, 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008, - 0x0e33, 0x0003, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0a44, 0x000b, - 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x0a44, 0x000b, 0x0223, 0x0004, - 0x8076, 0x0008, 0x0040, 0x0000, 0x0246, 0x000b, 0x8076, 0x0008, - 0x0041, 0x0008, 0x8072, 0x0000, 0x8000, 0x0000, 0x0233, 0x0003, - 0xbac0, 0x0009, 0x0090, 0x0008, 0x0a4f, 0x0003, 0x8074, 0x0000, - 0x0706, 0x0000, 0x0251, 0x000b, 0x8074, 0x0000, 0x0703, 0x0000, - 0x4000, 0x000f, 0x8010, 0x0008, 0x0023, 0x0000, 0x028e, 0x0003, - 0x8010, 0x0008, 0x0008, 0x0000, 0x028e, 0x0003, 0x8010, 0x0008, - 0x0022, 0x0008, 0x028e, 0x0003, 0x0228, 0x000c, 0x8010, 0x0008, - 0x0007, 0x0000, 0x0233, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c, - 0x029a, 0x0003, 0x0228, 0x000c, 0x8010, 0x0008, 0x001b, 0x0008, - 0x0233, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c, 0x8074, 0x0000, - 0xf080, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, 0x0000, - 0x000a, 0x000b, 0x8010, 0x0008, 0x0009, 0x0008, 0x028e, 0x0003, - 0x8010, 0x0008, 0x0005, 0x0008, 0x028e, 0x0003, 0x1648, 0x000a, - 0x0c6f, 0x000b, 0x808c, 0x0008, 0x0001, 0x0000, 0x8010, 0x0008, - 0x0004, 0x0000, 0x4143, 0x000a, 0x086f, 0x0003, 0x3a44, 0x0002, - 0x0c0a, 0x000b, 0x0d2a, 0x0008, 0x028e, 0x0003, 0x8010, 0x0008, - 0x0003, 0x0008, 0x0292, 0x000b, 0x8010, 0x0008, 0x000b, 0x0000, - 0x0292, 0x000b, 0x8010, 0x0008, 0x0002, 0x0000, 0x0292, 0x000b, - 0x3a47, 0x0002, 0x0d58, 0x000b, 0x8010, 0x0008, 0x0006, 0x0008, - 0x0292, 0x000b, 0x8074, 0x0000, 0xf000, 0x0008, 0x8072, 0x0000, - 0x3000, 0x0008, 0x0233, 0x000c, 0x0249, 0x0004, 0x3a40, 0x000a, - 0x080a, 0x0003, 0x8010, 0x0008, 0x000c, 0x0008, 0x0233, 0x000c, - 0x000a, 0x000b, 0x8074, 0x0000, 0xf080, 0x0000, 0x8072, 0x0000, - 0x3000, 0x0008, 0x0d30, 0x0000, 0x2e4d, 0x0002, 0x2e4d, 0x0002, - 0x0aa5, 0x000b, 0x8054, 0x0008, 0x0019, 0x0000, 0x000a, 0x000b, - 0x8054, 0x0008, 0x0009, 0x0008, 0x000a, 0x000b, 0x3a44, 0x0002, - 0x0c0a, 0x000b, 0x0283, 0x000b, 0x808c, 0x0008, 0x0000, 0x0008, - 0x4447, 0x0002, 0x0ad1, 0x000b, 0xc0c0, 0x0001, 0x00ff, 0x0008, - 0xffe0, 0x0009, 0x00ff, 0x0008, 0x0ea8, 0x000b, 0xc1e0, 0x0001, - 0xffff, 0x0008, 0x0ea8, 0x000b, 0x8010, 0x0008, 0x0013, 0x0000, - 0x0233, 0x000c, 0x8074, 0x0000, 0x0202, 0x0008, 0x000a, 0x000b, - 0x3a40, 0x000a, 0x0ece, 0x000b, 0x8074, 0x0000, 0x0200, 0x0000, - 0x3d00, 0x0000, 0x3cfe, 0x0000, 0x8072, 0x0000, 0x8000, 0x0000, - 0x43e0, 0x0001, 0x0ecc, 0x0003, 0x42fe, 0x0000, 0xffc0, 0x0001, - 0x00ff, 0x0008, 0x00e0, 0x0009, 0x0aa8, 0x0003, 0x0d08, 0x0008, - 0x0321, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, 0x000a, 0x000b, - 0x03a7, 0x000c, 0x808c, 0x0008, 0x0001, 0x0000, 0x04fe, 0x0008, - 0x338a, 0x0003, 0x0460, 0x0000, 0x8062, 0x0008, 0x0001, 0x0000, - 0x8066, 0x0000, 0x0009, 0x0008, 0x46db, 0x0003, 0x0004, 0x0000, - 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f00, 0x0000, 0x80e0, 0x0001, - 0x0004, 0x0000, 0x0af5, 0x000b, 0x80e0, 0x0001, 0x0005, 0x0008, - 0x0af5, 0x000b, 0x80e0, 0x0001, 0x0006, 0x0008, 0x0af5, 0x000b, - 0x82c0, 0x0001, 0xff00, 0x0008, 0x7f04, 0x0008, 0x82e0, 0x0009, - 0x0600, 0x0008, 0x0af5, 0x000b, 0x82e0, 0x0009, 0x0500, 0x0008, - 0x0af5, 0x000b, 0x82e0, 0x0009, 0x0400, 0x0000, 0x0f8a, 0x0003, - 0xc4c0, 0x0009, 0x7000, 0x0000, 0xffe0, 0x0009, 0x1000, 0x0000, - 0x0b21, 0x0003, 0x0398, 0x000c, 0x3941, 0x0002, 0x0b00, 0x0003, - 0x8072, 0x0000, 0x0400, 0x0000, 0x000a, 0x000b, 0x0460, 0x0000, - 0x80fe, 0x0008, 0x002b, 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x2209, 0x0008, 0x4706, 0x000b, 0x11fe, 0x0000, 0x331c, 0x0003, - 0x9180, 0x0001, 0x0002, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0609, 0x0008, 0x4710, 0x0003, - 0x42fe, 0x0000, 0xffc0, 0x0001, 0xff00, 0x0008, 0x03e0, 0x0009, - 0x0f19, 0x0003, 0x8072, 0x0000, 0x0400, 0x0000, 0x0046, 0x0003, - 0x9180, 0x0001, 0x0003, 0x0008, 0x0303, 0x000b, 0x8072, 0x0000, - 0x0400, 0x0000, 0x8010, 0x0008, 0x0010, 0x0000, 0x037b, 0x000b, - 0x0398, 0x000c, 0x3941, 0x0002, 0x0b27, 0x0003, 0x8072, 0x0000, - 0x0400, 0x0000, 0x000a, 0x000b, 0x1042, 0x000a, 0x0b2c, 0x000b, - 0x0360, 0x0004, 0x11fe, 0x0000, 0x3731, 0x000b, 0x8072, 0x0000, - 0x0400, 0x0000, 0x8010, 0x0008, 0x000e, 0x0000, 0x037b, 0x000b, - 0x8060, 0x0000, 0x0400, 0x0000, 0x04fe, 0x0008, 0x3746, 0x000b, - 0x808c, 0x0008, 0x0000, 0x0008, 0x9180, 0x0001, 0x0005, 0x0008, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x473c, 0x000b, - 0x0060, 0x0008, 0x8062, 0x0008, 0x001b, 0x0008, 0x4304, 0x0008, - 0x4206, 0x0008, 0x8066, 0x0000, 0x0412, 0x0000, 0x4744, 0x000b, - 0x035d, 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x0460, 0x0000, - 0x8062, 0x0008, 0x002b, 0x0008, 0x8066, 0x0000, 0x0609, 0x0008, - 0x474d, 0x000b, 0x8066, 0x0000, 0x220a, 0x0008, 0x4750, 0x000b, - 0x42fe, 0x0000, 0xffc0, 0x0001, 0xff00, 0x0008, 0x7f04, 0x0008, - 0x8060, 0x0000, 0x0400, 0x0000, 0x9180, 0x0001, 0x0002, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x041a, 0x0008, 0x475c, 0x000b, - 0x8072, 0x0000, 0x0400, 0x0000, 0x0046, 0x0003, 0x8060, 0x0000, - 0x0400, 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x0411, 0x0000, - 0x4765, 0x000b, 0x02fe, 0x0008, 0x03e0, 0x0009, 0x0f6b, 0x0003, - 0x0d22, 0x0000, 0x4000, 0x000f, 0x8280, 0x0009, 0x0002, 0x0000, - 0x1380, 0x0001, 0x7f62, 0x0008, 0x8066, 0x0000, 0x2209, 0x0008, - 0x4771, 0x000b, 0x0200, 0x000a, 0xffc0, 0x0001, 0x0007, 0x0000, - 0x7f06, 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x060a, 0x0008, - 0x4779, 0x0003, 0x4000, 0x000f, 0x3a44, 0x0002, 0x0c0a, 0x000b, - 0x2f44, 0x000a, 0x2f44, 0x000a, 0x0e83, 0x000b, 0x808a, 0x0008, - 0x0003, 0x0008, 0x8074, 0x0000, 0xf080, 0x0000, 0x8072, 0x0000, - 0x3000, 0x0008, 0x5b86, 0x000b, 0x8054, 0x0008, 0x0019, 0x0000, - 0x000a, 0x000b, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x808c, 0x0008, - 0x0000, 0x0008, 0x8010, 0x0008, 0x0011, 0x0008, 0x0233, 0x000c, - 0x42fe, 0x0000, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x7f10, 0x0008, - 0x0233, 0x000c, 0x4310, 0x0008, 0x0292, 0x000b, 0x3941, 0x0002, - 0x0b9b, 0x000b, 0x4000, 0x000f, 0x8072, 0x0000, 0x0404, 0x0008, - 0x4000, 0x000f, 0x8010, 0x0008, 0x0012, 0x0008, 0x0233, 0x000c, - 0x0360, 0x0004, 0x1110, 0x0000, 0x0233, 0x000c, 0x11fe, 0x0000, - 0x37a1, 0x000b, 0x000a, 0x000b, 0xc2c0, 0x0009, 0x00ff, 0x0008, - 0x7f00, 0x0000, 0xc3c0, 0x0001, 0xff00, 0x0008, 0x00d0, 0x0009, - 0x0bcc, 0x0003, 0x0d0a, 0x0000, 0x8580, 0x0001, 0x1000, 0x0000, - 0x7f62, 0x0008, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066, 0x0000, - 0x0809, 0x0000, 0x47b6, 0x0003, 0x04fe, 0x0008, 0x33c5, 0x000b, - 0x0460, 0x0000, 0x8062, 0x0008, 0x0004, 0x0000, 0x8066, 0x0000, - 0x0211, 0x0000, 0x47be, 0x000b, 0x01fe, 0x0008, 0x00e0, 0x0009, - 0x0fc5, 0x000b, 0x02fe, 0x0008, 0x43e0, 0x0001, 0x0bcb, 0x000b, - 0x0500, 0x0002, 0x7f0a, 0x0000, 0xffe0, 0x0009, 0x0800, 0x0000, - 0x0faf, 0x000b, 0x0d08, 0x0008, 0x4000, 0x000f, 0x43fe, 0x0008, - 0x3e80, 0x0001, 0xffc0, 0x0001, 0x7fff, 0x0000, 0x0d60, 0x0000, - 0x7f62, 0x0008, 0x8066, 0x0000, 0x0809, 0x0000, 0x47d4, 0x000b, - 0x8060, 0x0000, 0x0400, 0x0000, 0x84c0, 0x0001, 0xff00, 0x0008, - 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, - 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, - 0xff80, 0x0009, 0x1000, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, - 0x0809, 0x0000, 0x47e6, 0x0003, 0x4000, 0x000f, 0x8d5b, 0xeac4, - 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, - 0x12b0 -}; -#ifdef UNIQUE_FW_NAME -unsigned short fw2300ipx_length01 = 0xf091; -#else -unsigned short risc_code_length01 = 0xf091; -#endif - diff --git a/drivers/scsi/qla2xxx/ql2322.c b/drivers/scsi/qla2xxx/ql2322.c deleted file mode 100644 index 3c8cafc..0000000 --- a/drivers/scsi/qla2xxx/ql2322.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include -#include -#include - -#include "qla_def.h" - -static char qla_driver_name[] = "qla2322"; - -extern unsigned char fw2322ipx_version[]; -extern unsigned char fw2322ipx_version_str[]; -extern unsigned short fw2322ipx_addr01; -extern unsigned short fw2322ipx_code01[]; -extern unsigned short fw2322ipx_length01; -extern unsigned long rseqipx_code_addr01; -extern unsigned short rseqipx_code01[]; -extern unsigned short rseqipx_code_length01; -extern unsigned long xseqipx_code_addr01; -extern unsigned short xseqipx_code01[]; -extern unsigned short xseqipx_code_length01; - -static struct qla_fw_info qla_fw_tbl[] = { - { - .addressing = FW_INFO_ADDR_NORMAL, - .fwcode = &fw2322ipx_code01[0], - .fwlen = &fw2322ipx_length01, - .fwstart = &fw2322ipx_addr01, - }, - { - .addressing = FW_INFO_ADDR_EXTENDED, - .fwcode = &rseqipx_code01[0], - .fwlen = &rseqipx_code_length01, - .lfwstart = &rseqipx_code_addr01, - }, - { - .addressing = FW_INFO_ADDR_EXTENDED, - .fwcode = &xseqipx_code01[0], - .fwlen = &xseqipx_code_length01, - .lfwstart = &xseqipx_code_addr01, - }, - { FW_INFO_ADDR_NOMORE, }, -}; - -static struct qla_board_info qla_board_tbl[] = { - { - .drv_name = qla_driver_name, - .isp_name = "ISP2322", - .fw_info = qla_fw_tbl, - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP6322", - .fw_info = qla_fw_tbl, - }, -}; - -static struct pci_device_id qla2322_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2322, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[0], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP6322, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[1], - }, - {0, 0}, -}; -MODULE_DEVICE_TABLE(pci, qla2322_pci_tbl); - -static int __devinit -qla2322_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - return qla2x00_probe_one(pdev, - (struct qla_board_info *)id->driver_data); -} - -static void __devexit -qla2322_remove_one(struct pci_dev *pdev) -{ - qla2x00_remove_one(pdev); -} - -static struct pci_driver qla2322_pci_driver = { - .name = "qla2322", - .id_table = qla2322_pci_tbl, - .probe = qla2322_probe_one, - .remove = __devexit_p(qla2322_remove_one), -}; - -static int __init -qla2322_init(void) -{ - return pci_module_init(&qla2322_pci_driver); -} - -static void __exit -qla2322_exit(void) -{ - pci_unregister_driver(&qla2322_pci_driver); -} - -module_init(qla2322_init); -module_exit(qla2322_exit); - -MODULE_AUTHOR("QLogic Corporation"); -MODULE_DESCRIPTION("QLogic ISP2322 FC-SCSI Host Bus Adapter driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2322_fw.c b/drivers/scsi/qla2xxx/ql2322_fw.c deleted file mode 100644 index 53599a8..0000000 --- a/drivers/scsi/qla2xxx/ql2322_fw.c +++ /dev/null @@ -1,8376 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ - -/* - * Firmware Version 3.03.20 (15:42 Feb 01, 2006) - */ - -#ifdef UNIQUE_FW_NAME -unsigned short fw2322ipx_version = 3*1024+3; -#else -unsigned short risc_code_version = 3*1024+3; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned char fw2322ipx_version_str[] = {3, 3,20}; -#else -unsigned char firmware_version[] = {3, 3,20}; -#endif - -#ifdef UNIQUE_FW_NAME -#define fw2322ipx_VERSION_STRING "3.03.20" -#else -#define FW_VERSION_STRING "3.03.20" -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2322ipx_addr01 = 0x0800 ; -#else -unsigned short risc_code_addr01 = 0x0800 ; -#endif - -#ifdef UNIQUE_FW_NAME -unsigned short fw2322ipx_code01[] = { -#else -unsigned short risc_code01[] = { -#endif - 0x0470, 0x0000, 0x0000, 0xe719, 0x0000, 0x0003, 0x0003, 0x0014, - 0x0137, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030, - 0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, - 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972, - 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, - 0x332e, 0x3033, 0x2e32, 0x3020, 0x2020, 0x2020, 0x2400, 0x20a9, - 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f, - 0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001, - 0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000, - 0x400f, 0x2091, 0x2800, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, - 0x2091, 0x2a00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, - 0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00, - 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001, - 0x0000, 0x20c1, 0x0004, 0x20c9, 0x1cff, 0x2059, 0x0000, 0x2b78, - 0x7883, 0x0004, 0x2089, 0x2bc2, 0x2051, 0x1800, 0x2a70, 0x20e1, - 0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e74, 0x00f6, - 0x7888, 0x9005, 0x11f8, 0x2061, 0xc000, 0x080c, 0x20c6, 0x1170, - 0x2079, 0x0300, 0x080c, 0x20dc, 0x2061, 0xe000, 0x080c, 0x20c6, - 0x1128, 0x2079, 0x0380, 0x080c, 0x20dc, 0x0060, 0x00fe, 0x7883, - 0x4010, 0x7837, 0x4010, 0x7833, 0x0011, 0x2091, 0x5000, 0x2091, - 0x4080, 0x0cf8, 0x00fe, 0x2029, 0x5600, 0x2031, 0xffff, 0x2039, - 0x55dc, 0x2021, 0x0200, 0x20e9, 0x0001, 0x20a1, 0x0000, 0x20a9, - 0x0800, 0x900e, 0x4104, 0x20e9, 0x0001, 0x20a1, 0x1000, 0x900e, - 0x2001, 0x0dc1, 0x9084, 0x0fff, 0x20a8, 0x4104, 0x2001, 0x0000, - 0x9086, 0x0000, 0x0120, 0x21a8, 0x4104, 0x8001, 0x1de0, 0x756e, - 0x7672, 0x776a, 0x7476, 0x747a, 0x00e6, 0x2071, 0x1b73, 0x2472, - 0x00ee, 0x20a1, 0x1ddc, 0x7170, 0x810d, 0x810d, 0x810d, 0x810d, - 0x918c, 0x000f, 0x2001, 0x0001, 0x9112, 0x900e, 0x21a8, 0x4104, - 0x8211, 0x1de0, 0x7170, 0x3400, 0x8001, 0x9102, 0x0120, 0x0218, - 0x20a8, 0x900e, 0x4104, 0x2009, 0x1800, 0x810d, 0x810d, 0x810d, - 0x810d, 0x810d, 0x918c, 0x001f, 0x2001, 0x0001, 0x9112, 0x20e9, - 0x0001, 0x20a1, 0x0800, 0x900e, 0x20a9, 0x0800, 0x4104, 0x8211, - 0x1dd8, 0x080c, 0x0f71, 0x080c, 0x61ab, 0x080c, 0xb102, 0x080c, - 0x1128, 0x080c, 0x1352, 0x080c, 0x1c1c, 0x080c, 0x9582, 0x080c, - 0x0d17, 0x080c, 0x10ad, 0x080c, 0x358e, 0x080c, 0x7aca, 0x080c, - 0x6cea, 0x080c, 0x8c5d, 0x080c, 0x88be, 0x080c, 0x22bf, 0x080c, - 0x81f5, 0x080c, 0x20f5, 0x080c, 0x2233, 0x080c, 0x22b4, 0x2091, - 0x3009, 0x7883, 0x0000, 0x1004, 0x0943, 0x7880, 0x9086, 0x0002, - 0x1190, 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04, - 0x0937, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x190c, 0x1200, 0x2071, 0x1800, 0x7003, 0x0000, 0x780c, - 0x9084, 0x0030, 0x9086, 0x0020, 0x1168, 0x7034, 0xc08d, 0x7036, - 0x2001, 0x0050, 0x7076, 0x707a, 0x7056, 0x606b, 0x269c, 0x2071, - 0x1b73, 0x2072, 0x2071, 0x1800, 0x7000, 0x908e, 0x0003, 0x1168, - 0x080c, 0x4d66, 0x080c, 0x35b5, 0x080c, 0x7b32, 0x080c, 0x7275, - 0x080c, 0x8d44, 0x080c, 0x88e7, 0x0c68, 0x000b, 0x0c88, 0x0979, - 0x097a, 0x0b15, 0x0977, 0x0bcf, 0x0d16, 0x0d16, 0x0d16, 0x080c, - 0x0d85, 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0x9086, - 0x0001, 0x1904, 0x0ae8, 0x080c, 0x0ec4, 0x080c, 0x779e, 0x0150, - 0x080c, 0x77c1, 0x15b0, 0x2079, 0x0100, 0x7828, 0x9085, 0x1800, - 0x782a, 0x0478, 0x080c, 0x76cd, 0x7000, 0x9086, 0x0001, 0x1904, - 0x0ae8, 0x7098, 0x9086, 0x0029, 0x1904, 0x0ae8, 0x080c, 0x88a7, - 0x080c, 0x8899, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, - 0x2011, 0xffff, 0x080c, 0x2ad3, 0x7a28, 0x9295, 0x5e2c, 0x7a2a, - 0x2011, 0x7612, 0x080c, 0x8993, 0x2011, 0x7605, 0x080c, 0x8a9f, - 0x2011, 0x6002, 0x080c, 0x8993, 0x2011, 0x8030, 0x901e, 0x7396, - 0x04d0, 0x080c, 0x58aa, 0x2079, 0x0100, 0x7844, 0x9005, 0x1904, - 0x0ae8, 0x2011, 0x6002, 0x080c, 0x8993, 0x2011, 0x7612, 0x080c, - 0x8993, 0x2011, 0x7605, 0x080c, 0x8a9f, 0x2001, 0x0265, 0x2001, - 0x0205, 0x2003, 0x0000, 0x7840, 0x9084, 0xfffb, 0x7842, 0x2001, - 0x19a7, 0x2004, 0x9005, 0x1140, 0x00c6, 0x2061, 0x0100, 0x080c, - 0x6153, 0x00ce, 0x0804, 0x0ae8, 0x780f, 0x006b, 0x7a28, 0x080c, - 0x77a6, 0x0118, 0x9295, 0x5e2c, 0x0010, 0x9295, 0x402c, 0x7a2a, - 0x2011, 0x8010, 0x73d8, 0x2001, 0x19a8, 0x2003, 0x0001, 0x080c, - 0x299b, 0x080c, 0x4ca1, 0x7248, 0xc284, 0x724a, 0x2001, 0x180c, - 0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x2001, 0x0390, 0x2003, 0x0400, - 0x080c, 0xacfc, 0x080c, 0xa4f1, 0x2011, 0x0004, 0x080c, 0xcf2b, - 0x080c, 0xad18, 0x080c, 0x6ab1, 0x080c, 0x779e, 0x1120, 0x080c, - 0x29fc, 0x0600, 0x0420, 0x080c, 0x615a, 0x0140, 0x7097, 0x0001, - 0x70d3, 0x0000, 0x080c, 0x5a7c, 0x0804, 0x0ae8, 0x2001, 0x0390, - 0x2003, 0x0404, 0x080c, 0x5840, 0xd094, 0x0188, 0x2011, 0x180c, - 0x2204, 0xc0cd, 0x2012, 0x080c, 0x5844, 0xd0d4, 0x1118, 0x080c, - 0x29fc, 0x1270, 0x2011, 0x180c, 0x2204, 0xc0bc, 0x00a8, 0x080c, - 0x5844, 0xd0d4, 0x1db8, 0x2011, 0x180c, 0x2204, 0xc0bd, 0x0060, - 0x2011, 0x180c, 0x2204, 0xc0bd, 0x2012, 0x080c, 0x6c09, 0x1128, - 0xd0a4, 0x0118, 0x2204, 0xc0fd, 0x2012, 0x080c, 0x6bcf, 0x0120, - 0x7a0c, 0xc2b4, 0x7a0e, 0x00a8, 0x707f, 0x0000, 0x080c, 0x779e, - 0x1130, 0x70b0, 0x9005, 0x1168, 0x080c, 0xd389, 0x0050, 0x080c, - 0xd389, 0x70dc, 0xd09c, 0x1128, 0x70b0, 0x9005, 0x0110, 0x080c, - 0x6130, 0x70e7, 0x0000, 0x70e3, 0x0000, 0x70a7, 0x0000, 0x080c, - 0x2a04, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c4, 0x2012, 0x72dc, - 0x080c, 0x779e, 0x1178, 0x9016, 0x0016, 0x080c, 0x27a4, 0x2019, - 0x196d, 0x211a, 0x001e, 0x705f, 0xffff, 0x7063, 0x00ef, 0x7083, - 0x0000, 0x0020, 0x2019, 0x196d, 0x201b, 0x0000, 0x2079, 0x1847, - 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72de, 0x080c, 0x779e, 0x0118, - 0x9296, 0x0004, 0x0518, 0x2011, 0x0001, 0x080c, 0xcf2b, 0x70ab, - 0x0000, 0x70af, 0xffff, 0x7003, 0x0002, 0x00fe, 0x080c, 0x30bf, - 0x080c, 0xacfc, 0x2011, 0x0005, 0x080c, 0xa62b, 0x080c, 0xad18, - 0x080c, 0x779e, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, - 0x27a4, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x00e0, 0x70ab, 0x0000, - 0x70af, 0xffff, 0x7003, 0x0002, 0x080c, 0xacfc, 0x2011, 0x0005, - 0x080c, 0xa62b, 0x080c, 0xad18, 0x080c, 0x779e, 0x0148, 0x00c6, - 0x2061, 0x0100, 0x0016, 0x080c, 0x27a4, 0x61e2, 0x001e, 0x00ce, - 0x00fe, 0x012e, 0x0005, 0x00c6, 0x00b6, 0x080c, 0x779e, 0x1118, - 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, 0x080c, 0x779e, 0x1110, - 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, 0x0138, 0x9180, 0x1000, - 0x2004, 0x905d, 0x0110, 0xb800, 0xd0bc, 0x090c, 0x341e, 0x8108, - 0x1f04, 0x0afc, 0x707f, 0x0000, 0x7080, 0x9084, 0x00ff, 0x7082, - 0x70b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x00b6, 0x0126, 0x2091, - 0x8000, 0x7000, 0x9086, 0x0002, 0x1904, 0x0bcc, 0x70ac, 0x9086, - 0xffff, 0x0120, 0x080c, 0x30bf, 0x0804, 0x0bcc, 0x70dc, 0xd0ac, - 0x1110, 0xd09c, 0x0538, 0xd084, 0x0528, 0x0006, 0x2001, 0x0103, - 0x2003, 0x002b, 0x000e, 0xd08c, 0x01e8, 0x080c, 0x3487, 0x11b0, - 0x70e0, 0x9086, 0xffff, 0x0190, 0x080c, 0x327b, 0x70dc, 0xd094, - 0x1904, 0x0bcc, 0x2011, 0x0001, 0x080c, 0xd645, 0x0110, 0x2011, - 0x0003, 0x901e, 0x080c, 0x32b5, 0x0804, 0x0bcc, 0x70e4, 0x9005, - 0x1904, 0x0bcc, 0x70a8, 0x9005, 0x1904, 0x0bcc, 0x70dc, 0xd0a4, - 0x0118, 0xd0b4, 0x0904, 0x0bcc, 0x080c, 0x6bcf, 0x1904, 0x0bcc, - 0x080c, 0x6c22, 0x1904, 0x0bcc, 0x080c, 0x6c09, 0x01c0, 0x0156, - 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x67b4, 0x1118, - 0xb800, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b6c, 0x00ce, - 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x0bcc, 0x0006, - 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0x2011, 0x19b4, 0x080c, - 0x0fe1, 0x2011, 0x19ce, 0x080c, 0x0fe1, 0x7030, 0xc08c, 0x7032, - 0x7003, 0x0003, 0x70af, 0xffff, 0x080c, 0x0e98, 0x9006, 0x080c, - 0x2631, 0x080c, 0x3487, 0x0118, 0x080c, 0x4e3e, 0x0050, 0x0036, - 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4e58, 0x004e, - 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x77c1, 0x0150, 0x080c, - 0x779e, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, 0xffdf, - 0x782a, 0x00fe, 0x080c, 0xacfc, 0x2001, 0x19e9, 0x2004, 0x9086, - 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0xa62b, 0x2011, 0x0000, - 0x080c, 0xa635, 0x080c, 0xad18, 0x012e, 0x00be, 0x0005, 0x0016, - 0x0026, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, - 0x7904, 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x6119, - 0x7940, 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0120, 0x2011, - 0x0040, 0x080c, 0x2ad3, 0xd19c, 0x0120, 0x2011, 0x0008, 0x080c, - 0x2ad3, 0x0006, 0x0036, 0x0156, 0x0000, 0x2001, 0x19a8, 0x2004, - 0x9005, 0x1518, 0x080c, 0x2a67, 0x1148, 0x2001, 0x0001, 0x080c, - 0x29ca, 0x2001, 0x0001, 0x080c, 0x29ad, 0x00b8, 0x080c, 0x2a6f, - 0x1138, 0x9006, 0x080c, 0x29ca, 0x9006, 0x080c, 0x29ad, 0x0068, - 0x080c, 0x2a77, 0x1d50, 0x2001, 0x1998, 0x2004, 0xd0fc, 0x0108, - 0x0020, 0x080c, 0x27d8, 0x0804, 0x0cc9, 0x20a9, 0x003a, 0x1d04, - 0x0c1f, 0x080c, 0x8a7f, 0x1f04, 0x0c1f, 0x080c, 0x77af, 0x0148, - 0x080c, 0x77c1, 0x1118, 0x080c, 0x7ac5, 0x0050, 0x080c, 0x77a6, - 0x0dd0, 0x080c, 0x7ac0, 0x080c, 0x7ab6, 0x080c, 0x76cd, 0x0020, - 0x2009, 0x00f8, 0x080c, 0x6119, 0x7850, 0xc0e5, 0x7852, 0x080c, - 0x779e, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, - 0x2019, 0xea60, 0x0d0c, 0x8a7f, 0x7820, 0xd09c, 0x15a0, 0x080c, - 0x779e, 0x0904, 0x0cab, 0x7824, 0xd0ac, 0x1904, 0x0cce, 0x080c, - 0x77c1, 0x1548, 0x0046, 0x2021, 0x0320, 0x8421, 0x1df0, 0x004e, - 0x2011, 0x1800, 0x080c, 0x2ad3, 0x080c, 0x2a7f, 0x7824, 0x9084, - 0x1800, 0x1168, 0x9484, 0x0fff, 0x1140, 0x2001, 0x1810, 0x2004, - 0x9084, 0x9000, 0x0110, 0x080c, 0x0cf1, 0x8421, 0x1160, 0x1d04, - 0x0c7b, 0x080c, 0x8a7f, 0x080c, 0x7ac0, 0x080c, 0x7ab6, 0x7003, - 0x0001, 0x0804, 0x0cce, 0x8319, 0x1928, 0x2001, 0x1810, 0x2004, - 0x9084, 0x9000, 0x0110, 0x080c, 0x0cf1, 0x1d04, 0x0c91, 0x080c, - 0x8a7f, 0x2009, 0x199b, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a, - 0x1188, 0x200b, 0x000a, 0x2011, 0x0048, 0x080c, 0x2ad3, 0x20a9, - 0x0002, 0x080c, 0x2a60, 0x7924, 0x080c, 0x2a7f, 0xd19c, 0x0110, - 0x080c, 0x299b, 0x00f0, 0x080c, 0x77af, 0x1140, 0x94a2, 0x03e8, - 0x1128, 0x080c, 0x7772, 0x7003, 0x0001, 0x00c0, 0x2011, 0x1800, - 0x080c, 0x2ad3, 0x080c, 0x2a7f, 0x7824, 0x080c, 0x77b8, 0x0110, - 0xd0ac, 0x1160, 0x9084, 0x1800, 0x0904, 0x0c83, 0x7003, 0x0001, - 0x0028, 0x2001, 0x0001, 0x080c, 0x2631, 0x00a0, 0x7850, 0xc0e4, - 0x7852, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904, 0x918d, - 0x0002, 0x7906, 0x2011, 0x0048, 0x080c, 0x2ad3, 0x7828, 0x9085, - 0x0028, 0x782a, 0x2001, 0x19a8, 0x2003, 0x0000, 0x9006, 0x78f2, - 0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, 0x004e, 0x002e, 0x001e, - 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x0046, 0x00b6, 0x00c6, - 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0071, 0x0d0c, 0x8a7f, 0x015e, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, 0x002e, - 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x189e, 0x7004, 0x9086, - 0x0001, 0x1110, 0x080c, 0x35b5, 0x00ee, 0x0005, 0x0005, 0x2a70, - 0x2061, 0x19ac, 0x2063, 0x0003, 0x6007, 0x0003, 0x600b, 0x0014, - 0x600f, 0x0137, 0x2001, 0x197c, 0x900e, 0x2102, 0x7196, 0x2001, - 0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x705f, 0xffff, 0x0008, - 0x715e, 0x7067, 0xffff, 0x717e, 0x7182, 0x080c, 0xd389, 0x70ef, - 0x00c0, 0x2061, 0x196c, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800, - 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x001f, 0x611a, 0x601f, - 0x07d0, 0x2061, 0x1974, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f, - 0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061, - 0x1989, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, - 0x2020, 0x2001, 0x182c, 0x2102, 0x0005, 0x9016, 0x080c, 0x67b4, - 0x1178, 0xb804, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4, - 0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210, - 0x8108, 0x9186, 0x0800, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000, - 0x2079, 0x0000, 0x000e, 0x00f6, 0x0010, 0x2091, 0x8000, 0x0e04, - 0x0d87, 0x0006, 0x0016, 0x2001, 0x8002, 0x0006, 0x2079, 0x0000, - 0x000e, 0x7882, 0x7836, 0x001e, 0x798e, 0x000e, 0x788a, 0x000e, - 0x7886, 0x3900, 0x789a, 0x00d6, 0x2069, 0x0300, 0x6818, 0x78ae, - 0x681c, 0x78b2, 0x6808, 0x78be, 0x00de, 0x7833, 0x0012, 0x2091, - 0x5000, 0x0156, 0x00d6, 0x0036, 0x0026, 0x2079, 0x0300, 0x2069, - 0x1b2b, 0x7a08, 0x226a, 0x2069, 0x1b2c, 0x7a18, 0x226a, 0x8d68, - 0x7a1c, 0x226a, 0x782c, 0x2019, 0x1b39, 0x201a, 0x2019, 0x1b3c, - 0x9016, 0x7808, 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, 0x8318, - 0x9386, 0x1b55, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011, - 0xdead, 0x2019, 0x1b3a, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803, - 0x0000, 0x2069, 0x1a81, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28, - 0x226a, 0x8d68, 0x8318, 0x1f04, 0x0dde, 0x2069, 0x1aa1, 0x2019, - 0x0050, 0x20a9, 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, 0x8318, - 0x1f04, 0x0deb, 0x0491, 0x002e, 0x003e, 0x00de, 0x015e, 0x2079, - 0x1800, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, - 0xd084, 0x0180, 0x2001, 0x1a25, 0x2004, 0x9005, 0x0128, 0x2001, - 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002, - 0x2003, 0x1001, 0x080c, 0x584f, 0x1170, 0x080c, 0x0f32, 0x0110, - 0x080c, 0x0e85, 0x080c, 0x584f, 0x1130, 0x2071, 0x1800, 0x2011, - 0x8000, 0x080c, 0x0f46, 0x0c70, 0x0005, 0x2001, 0x0382, 0x2004, - 0x9084, 0x0007, 0x9086, 0x0001, 0x1120, 0x2001, 0x0015, 0x080c, - 0xaced, 0x2079, 0x0380, 0x2069, 0x1b0b, 0x7818, 0x6802, 0x781c, - 0x6806, 0x7840, 0x680a, 0x7844, 0x680e, 0x782c, 0x6812, 0x2019, - 0x1b16, 0x9016, 0x7808, 0xd09c, 0x0150, 0x7820, 0x201a, 0x8210, - 0x8318, 0x8210, 0x9282, 0x0011, 0x0ea8, 0x2011, 0xdead, 0x6a2a, - 0x7830, 0x681a, 0x7834, 0x681e, 0x7838, 0x6822, 0x783c, 0x6826, - 0x7803, 0x0000, 0x2069, 0x1acb, 0x901e, 0x20a9, 0x0020, 0x7b26, - 0x7828, 0x206a, 0x8d68, 0x8318, 0x1f04, 0x0e5f, 0x2069, 0x1aeb, - 0x2019, 0x00b0, 0x20a9, 0x0020, 0x7b26, 0x7828, 0x206a, 0x8d68, - 0x8318, 0x1f04, 0x0e6c, 0x0005, 0x918c, 0x03ff, 0x2001, 0x0003, - 0x2004, 0x9084, 0x0600, 0x1118, 0x918d, 0x6c00, 0x0010, 0x918d, - 0x6400, 0x2001, 0x017f, 0x2102, 0x0005, 0x0026, 0x0126, 0x2011, - 0x0080, 0x080c, 0x0f24, 0x20a9, 0x0900, 0x080c, 0x0f5a, 0x2011, - 0x0040, 0x080c, 0x0f24, 0x20a9, 0x0900, 0x080c, 0x0f5a, 0x0c78, - 0x0026, 0x080c, 0x0f32, 0x1188, 0x2011, 0x010e, 0x2214, 0x9294, - 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0x0947, 0x0010, 0x2011, - 0x1b47, 0x080c, 0x0f46, 0x002e, 0x0005, 0x2011, 0x010e, 0x2214, - 0x9294, 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0xa880, 0x0010, - 0x2011, 0x6840, 0xd0e4, 0x70f3, 0x0000, 0x1120, 0x70f3, 0x0fa0, - 0x080c, 0x0f37, 0x002e, 0x0005, 0x0026, 0x080c, 0x0f32, 0x0148, - 0xd0a4, 0x1138, 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, 0x080c, - 0x0f37, 0x002e, 0x0005, 0x0026, 0x70f3, 0x0000, 0x080c, 0x0f32, - 0x1130, 0x2011, 0x8040, 0x080c, 0x0f46, 0x002e, 0x0005, 0x080c, - 0x2a77, 0x1118, 0x2011, 0xcdc5, 0x0010, 0x2011, 0xcac2, 0x080c, - 0x0f37, 0x002e, 0x0005, 0x00e6, 0x0016, 0x0006, 0x2071, 0x1800, - 0xd0b4, 0x70ec, 0x71e8, 0x1118, 0xc0e4, 0xc1f4, 0x0050, 0x0006, - 0x3b00, 0x9084, 0xff3e, 0x20d8, 0x000e, 0x70f3, 0x0000, 0xc0e5, - 0xc1f5, 0x0099, 0x000e, 0x001e, 0x00ee, 0x0005, 0x00e6, 0x2071, - 0x1800, 0xd0e4, 0x70ec, 0x1110, 0xc0dc, 0x0008, 0xc0dd, 0x0016, - 0x71e8, 0x0019, 0x001e, 0x00ee, 0x0005, 0x70ee, 0x71ea, 0x7000, - 0x9084, 0x0007, 0x000b, 0x0005, 0x0eea, 0x0ec4, 0x0ec4, 0x0e98, - 0x0ed3, 0x0ec4, 0x0ec4, 0x0ed3, 0xc284, 0x0016, 0x3b08, 0x3a00, - 0x9104, 0x918d, 0x00c1, 0x21d8, 0x9084, 0xff3e, 0x9205, 0x20d0, - 0x001e, 0x0005, 0x2001, 0x183b, 0x2004, 0xd0dc, 0x0005, 0x9e86, - 0x1800, 0x190c, 0x0d85, 0x70ec, 0xd0e4, 0x0108, 0xc2e5, 0x72ee, - 0xd0e4, 0x1118, 0x9294, 0x00c1, 0x08f9, 0x0005, 0x9e86, 0x1800, - 0x190c, 0x0d85, 0x70e8, 0xd0f4, 0x0108, 0xc2f5, 0x72ea, 0xd0f4, - 0x1140, 0x9284, 0x8000, 0x8005, 0xc284, 0x9215, 0x9294, 0x00c1, - 0x0861, 0x0005, 0x1d04, 0x0f5a, 0x2091, 0x6000, 0x1f04, 0x0f5a, - 0x0005, 0x890e, 0x810e, 0x810f, 0x9194, 0x003f, 0x918c, 0xffc0, - 0x0005, 0x0006, 0x2200, 0x914d, 0x894f, 0x894d, 0x894d, 0x000e, - 0x0005, 0x01d6, 0x0146, 0x0036, 0x0096, 0x2061, 0x188d, 0x600b, - 0x0000, 0x600f, 0x0000, 0x6003, 0x0000, 0x6007, 0x0000, 0x2009, - 0xffc0, 0x2105, 0x0006, 0x2001, 0xaaaa, 0x200f, 0x2019, 0x5555, - 0x9016, 0x2049, 0x0bff, 0xab02, 0xa001, 0xa001, 0xa800, 0x9306, - 0x1138, 0x2105, 0x9306, 0x0120, 0x8210, 0x99c8, 0x0400, 0x0c98, - 0x000e, 0x200f, 0x2001, 0x189d, 0x928a, 0x000e, 0x1638, 0x928a, - 0x0006, 0x2011, 0x0006, 0x1210, 0x2011, 0x0000, 0x2202, 0x9006, - 0x2008, 0x82ff, 0x01b0, 0x8200, 0x600a, 0x600f, 0xffff, 0x6003, - 0x0002, 0x6007, 0x0000, 0x0026, 0x2019, 0x0010, 0x9280, 0x0001, - 0x20e8, 0x21a0, 0x21a8, 0x4104, 0x8319, 0x1de0, 0x8211, 0x1da0, - 0x002e, 0x009e, 0x003e, 0x014e, 0x01de, 0x0005, 0x2011, 0x000e, - 0x08e8, 0x0016, 0x0026, 0x0096, 0x3348, 0x080c, 0x0f61, 0x2100, - 0x9300, 0x2098, 0x22e0, 0x009e, 0x002e, 0x001e, 0x0036, 0x3518, - 0x20a9, 0x0001, 0x4002, 0x8007, 0x4004, 0x8319, 0x1dd8, 0x003e, - 0x0005, 0x20e9, 0x0001, 0x71b8, 0x81ff, 0x11c0, 0x9006, 0x2009, - 0x0200, 0x20a9, 0x0002, 0x9298, 0x0018, 0x23a0, 0x4001, 0x2009, - 0x0700, 0x20a9, 0x0002, 0x9298, 0x0008, 0x23a0, 0x4001, 0x707c, - 0x8007, 0x7180, 0x810f, 0x20a9, 0x0002, 0x4001, 0x9298, 0x000c, - 0x23a0, 0x900e, 0x080c, 0x0d65, 0x2001, 0x0000, 0x810f, 0x20a9, - 0x0002, 0x4001, 0x0005, 0x89ff, 0x0140, 0xa804, 0xa807, 0x0000, - 0x0006, 0x080c, 0x108b, 0x009e, 0x0cb0, 0x0005, 0x00e6, 0x2071, - 0x1800, 0x080c, 0x1104, 0x090c, 0x0d85, 0x00ee, 0x0005, 0x0086, - 0x00e6, 0x0006, 0x0026, 0x0036, 0x0126, 0x2091, 0x8000, 0x00c9, - 0x2071, 0x1800, 0x73c0, 0x702c, 0x9016, 0x9045, 0x0158, 0x8210, - 0x9906, 0x090c, 0x0d85, 0x2300, 0x9202, 0x0120, 0x1a0c, 0x0d85, - 0xa000, 0x0c98, 0x012e, 0x003e, 0x002e, 0x000e, 0x00ee, 0x008e, - 0x0005, 0x0086, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1910, 0x7010, 0x9005, 0x0140, 0x7018, 0x9045, 0x0128, 0x9906, - 0x090c, 0x0d85, 0xa000, 0x0cc8, 0x012e, 0x000e, 0x00ee, 0x008e, - 0x0005, 0x00e6, 0x2071, 0x1800, 0x0126, 0x2091, 0x8000, 0x70c0, - 0x8001, 0x0270, 0x70c2, 0x702c, 0x2048, 0x9085, 0x0001, 0xa800, - 0x702e, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, - 0x904e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, - 0x70c0, 0x90ca, 0x0020, 0x0268, 0x8001, 0x70c2, 0x702c, 0x2048, - 0xa800, 0x702e, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, - 0x0005, 0x904e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x0016, - 0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0xa862, 0x9184, 0xffc0, - 0xa85e, 0x001e, 0x0020, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, - 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, - 0x080c, 0x8899, 0x012e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9026, - 0x2009, 0x0000, 0x2049, 0x0400, 0x2900, 0x702e, 0x8940, 0x2800, - 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0440, 0x0120, - 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x188d, 0x7000, 0x9005, - 0x11a0, 0x2001, 0x0558, 0xa802, 0x2048, 0x2009, 0x5600, 0x8940, - 0x2800, 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0800, - 0x0120, 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x188d, 0x7104, - 0x7200, 0x82ff, 0x01d0, 0x7308, 0x8318, 0x831f, 0x831b, 0x831b, - 0x7312, 0x8319, 0x2001, 0x0800, 0xa802, 0x2048, 0x8900, 0xa802, - 0x2040, 0xa95e, 0xaa62, 0x8420, 0x2300, 0x9906, 0x0130, 0x2848, - 0x9188, 0x0040, 0x9291, 0x0000, 0x0c88, 0xa803, 0x0000, 0x2071, - 0x1800, 0x74be, 0x74c2, 0x0005, 0x00e6, 0x0016, 0x9984, 0xfc00, - 0x01e8, 0x908c, 0xf800, 0x1168, 0x9982, 0x0400, 0x02b8, 0x9982, - 0x0440, 0x0278, 0x9982, 0x0558, 0x0288, 0x9982, 0x0800, 0x1270, - 0x0040, 0x9982, 0x0800, 0x0250, 0x2071, 0x188d, 0x7010, 0x9902, - 0x1228, 0x9085, 0x0001, 0x001e, 0x00ee, 0x0005, 0x9006, 0x0cd8, - 0x00e6, 0x2071, 0x1a24, 0x7007, 0x0000, 0x9006, 0x701e, 0x7022, - 0x7002, 0x2071, 0x0000, 0x7010, 0x9085, 0x8044, 0x7012, 0x2071, - 0x0080, 0x9006, 0x702b, 0x0060, 0x20a9, 0x0040, 0x7022, 0x1f04, - 0x113e, 0x702b, 0x0060, 0x702b, 0x0020, 0x20a9, 0x0040, 0x7022, - 0x1f04, 0x1147, 0x702b, 0x0020, 0x00ee, 0x0005, 0x0126, 0x2091, - 0x8000, 0x00e6, 0xa06f, 0x0000, 0x2071, 0x1a24, 0x701c, 0x9088, - 0x1a2e, 0x280a, 0x8000, 0x9084, 0x003f, 0x701e, 0x7120, 0x9106, - 0x090c, 0x0d85, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080, - 0x00a9, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, - 0x00e6, 0x2071, 0x1a24, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, - 0x0080, 0x0021, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x7004, 0x9086, - 0x0000, 0x1110, 0x7007, 0x0006, 0x7000, 0x0002, 0x1190, 0x1313, - 0x118e, 0x118e, 0x1307, 0x1307, 0x1307, 0x1307, 0x080c, 0x0d85, - 0x701c, 0x7120, 0x9106, 0x1148, 0x792c, 0x9184, 0x0001, 0x1120, - 0xd1fc, 0x1110, 0x7007, 0x0000, 0x0005, 0x0096, 0x9180, 0x1a2e, - 0x2004, 0x700a, 0x2048, 0x8108, 0x918c, 0x003f, 0x7122, 0x782b, - 0x0026, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, 0xa898, - 0x780e, 0xa878, 0x700e, 0xa870, 0x7016, 0xa874, 0x701a, 0xa868, - 0x009e, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, - 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, - 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x7212, 0x8203, - 0x7812, 0x782b, 0x0020, 0x782b, 0x0041, 0x002e, 0x001e, 0x0005, - 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e0, 0x7018, - 0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, 0x782b, 0x0026, 0x710c, - 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, - 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, 0x0020, 0x3300, 0x701a, - 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, - 0x2009, 0x1a24, 0x2104, 0xc095, 0x200a, 0x080c, 0x116d, 0x0005, - 0x0016, 0x00e6, 0x2071, 0x1a24, 0x00f6, 0x2079, 0x0080, 0x792c, - 0xd1bc, 0x190c, 0x0d7e, 0x782b, 0x0002, 0xd1fc, 0x0120, 0x918c, - 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x117e, - 0x1226, 0x125a, 0x1332, 0x0d85, 0x134d, 0x0d85, 0x918c, 0x0700, - 0x1550, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8, 0x7018, 0x20a0, - 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x7010, 0x20a8, - 0x4005, 0x3400, 0x701a, 0x015e, 0x014e, 0x013e, 0x700c, 0x9005, - 0x0578, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x11c3, 0x0005, - 0x7008, 0x0096, 0x2048, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000, - 0x080c, 0x117e, 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0200, - 0x009e, 0x0ca0, 0x918c, 0x0700, 0x1150, 0x700c, 0x9005, 0x0180, - 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x11d8, 0x0005, 0x7008, - 0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x7007, 0x0000, 0x0080, - 0x0096, 0x7008, 0x2048, 0x7800, 0xa88e, 0x7804, 0xa892, 0x7808, - 0xa896, 0x780c, 0xa89a, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000, - 0x0096, 0x00d6, 0x7008, 0x2048, 0x2001, 0x18b9, 0x2004, 0x9906, - 0x1128, 0xa89c, 0x080f, 0x00de, 0x009e, 0x00a0, 0x00de, 0x009e, - 0x0096, 0x00d6, 0x7008, 0x2048, 0x0081, 0x0150, 0xa89c, 0x0086, - 0x2940, 0x080f, 0x008e, 0x00de, 0x009e, 0x080c, 0x116d, 0x0005, - 0x00de, 0x009e, 0x080c, 0x116d, 0x0005, 0xa8a8, 0xd08c, 0x0005, - 0x0096, 0xa0a0, 0x904d, 0x090c, 0x0d85, 0xa06c, 0x908e, 0x0100, - 0x0130, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x080c, - 0x7006, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x2848, 0x080c, 0x108b, - 0x009e, 0x0005, 0x00a6, 0xa0a0, 0x904d, 0x090c, 0x0d85, 0xa06c, - 0x908e, 0x0100, 0x0128, 0xa87b, 0x0001, 0xa883, 0x0000, 0x00c0, - 0xa80c, 0x2050, 0xb004, 0x9005, 0x0198, 0xa80e, 0x2050, 0x8006, - 0x8006, 0x8007, 0x908c, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0xa076, 0xa172, 0xb000, 0xa07a, 0x2810, 0x080c, 0x114e, 0x00e8, - 0xa97c, 0xa894, 0x0016, 0x0006, 0x080c, 0x7006, 0x000e, 0x001e, - 0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060, 0x080c, 0xb16c, - 0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, 0xa8a3, 0x0000, 0x080c, - 0x108b, 0x7007, 0x0000, 0x080c, 0x116d, 0x00ae, 0x0005, 0x0126, - 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, 0xc094, - 0x7002, 0x012e, 0x0005, 0x0096, 0x2001, 0x192f, 0x204c, 0xa87c, - 0x7812, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, 0xa898, - 0x780e, 0x782b, 0x0020, 0x0126, 0x2091, 0x8000, 0x782b, 0x0041, - 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x2900, 0x700a, 0x012e, - 0x009e, 0x0005, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, - 0x0096, 0x2001, 0x192f, 0x204c, 0xaa7c, 0x009e, 0x080c, 0x8f88, - 0x2009, 0x188c, 0x2104, 0x9084, 0xfffc, 0x200a, 0x080c, 0x8de7, - 0x7007, 0x0000, 0x080c, 0x117e, 0x0005, 0x7007, 0x0000, 0x080c, - 0x117e, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, 0x0300, 0x2071, - 0x1a6e, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x0041, 0x7807, 0x0007, - 0x7803, 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, 0x7803, - 0x0000, 0x2001, 0x0165, 0x2003, 0x4198, 0x7808, 0xd09c, 0x0120, - 0x7820, 0x080c, 0x13b6, 0x0cc8, 0x2001, 0x1a6f, 0x2003, 0x0000, - 0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807, - 0x0007, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, 0x782b, - 0x1a81, 0x78e3, 0xff00, 0x781f, 0xff00, 0x781b, 0xff00, 0x2001, - 0x1a70, 0x2003, 0x0000, 0x2001, 0x0200, 0x2004, 0xd0dc, 0x0110, - 0x781f, 0x0303, 0x2061, 0x1a81, 0x602f, 0x1ddc, 0x2001, 0x181a, - 0x2004, 0x9082, 0x1ddc, 0x6032, 0x603b, 0x1ec1, 0x602b, 0x1ac1, - 0x6007, 0x1aa1, 0x2061, 0x1aa1, 0x606f, 0x193d, 0x2001, 0x1928, - 0x2004, 0x607a, 0x783f, 0x348e, 0x00ce, 0x0005, 0x9086, 0x000d, - 0x11d0, 0x7808, 0xd09c, 0x01b8, 0x7820, 0x0026, 0x2010, 0x080c, - 0xcf09, 0x0180, 0x2260, 0x6000, 0x9086, 0x0004, 0x1158, 0x0016, - 0x6120, 0x9186, 0x0009, 0x0108, 0x0020, 0x2009, 0x004c, 0x080c, - 0xb20a, 0x001e, 0x002e, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908, - 0x9184, 0x0070, 0x190c, 0x0d7e, 0xd19c, 0x05a0, 0x7820, 0x908c, - 0xf000, 0x0540, 0x2060, 0x6020, 0x9086, 0x0003, 0x1550, 0x6000, - 0x9086, 0x0004, 0x1530, 0x6114, 0x2148, 0xa876, 0xa87a, 0xa867, - 0x0103, 0x080c, 0x6e27, 0x00b6, 0x6010, 0x2058, 0xba3c, 0x8211, - 0x0208, 0xba3e, 0xb8d0, 0x9005, 0x190c, 0x68df, 0x00be, 0x6044, - 0xd0fc, 0x190c, 0xad25, 0x080c, 0xb195, 0x7808, 0xd09c, 0x19b0, - 0x012e, 0x0005, 0x908a, 0x0024, 0x1a0c, 0x0d85, 0x002b, 0x012e, - 0x0005, 0x04b0, 0x012e, 0x0005, 0x1438, 0x145e, 0x148e, 0x1493, - 0x1497, 0x149c, 0x14c4, 0x14c8, 0x14d6, 0x14da, 0x1438, 0x15a7, - 0x15ab, 0x161d, 0x1624, 0x1438, 0x1625, 0x1626, 0x1631, 0x1638, - 0x1438, 0x1438, 0x1438, 0x1438, 0x1438, 0x1438, 0x1438, 0x149e, - 0x1438, 0x1466, 0x148b, 0x1452, 0x1438, 0x1472, 0x143c, 0x143a, - 0x080c, 0x0d85, 0x080c, 0x0d7e, 0x080c, 0x1643, 0x2009, 0x1a7d, - 0x2104, 0x8000, 0x200a, 0x080c, 0x82b8, 0x080c, 0x1b1e, 0x0005, - 0x6044, 0xd0fc, 0x190c, 0xad25, 0x2009, 0x0055, 0x080c, 0xb20a, - 0x012e, 0x0005, 0x080c, 0x1643, 0x2060, 0x6044, 0xd0fc, 0x190c, - 0xad25, 0x2009, 0x0055, 0x080c, 0xb20a, 0x0005, 0x2009, 0x0048, - 0x080c, 0x1643, 0x2060, 0x080c, 0xb20a, 0x0005, 0x2009, 0x0054, - 0x080c, 0x1643, 0x2060, 0x6044, 0xd0fc, 0x190c, 0xad25, 0x080c, - 0xb20a, 0x0005, 0x080c, 0x1643, 0x2060, 0x0056, 0x0066, 0x080c, - 0x1643, 0x2028, 0x080c, 0x1643, 0x2030, 0x0036, 0x0046, 0x2021, - 0x0000, 0x2418, 0x2009, 0x0056, 0x080c, 0xb20a, 0x004e, 0x003e, - 0x006e, 0x005e, 0x0005, 0x080c, 0x1643, 0x0005, 0x7004, 0xc085, - 0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, 0x080c, - 0x1643, 0x080c, 0x1740, 0x0005, 0x080c, 0x0d85, 0x080c, 0x1643, - 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009, - 0x0048, 0x080c, 0xb20a, 0x2001, 0x015d, 0x2003, 0x0000, 0x2009, - 0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, - 0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, 0x1648, 0x2001, - 0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, 0x0005, - 0x080c, 0x1643, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, - 0x009e, 0x2009, 0x0048, 0x080c, 0xb20a, 0x0005, 0x080c, 0x1643, - 0x080c, 0x0d85, 0x080c, 0x1643, 0x080c, 0x1592, 0x7827, 0x0018, - 0x79ac, 0xd1dc, 0x0904, 0x1543, 0x7827, 0x0015, 0x7828, 0x782b, - 0x0000, 0x9065, 0x0140, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x0804, 0x1549, 0x7004, 0x9005, 0x01c8, 0x1188, 0x78ab, - 0x0004, 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0d85, - 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0804, 0x1577, - 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x15ab, 0x0005, 0x7827, - 0x0018, 0xa001, 0x7828, 0x7827, 0x0011, 0xa001, 0x7928, 0x9106, - 0x0110, 0x79ac, 0x08e0, 0x00e6, 0x2071, 0x0200, 0x702c, 0xd0c4, - 0x0140, 0x00ee, 0x080c, 0x1b1e, 0x080c, 0x1366, 0x7803, 0x0001, - 0x0005, 0x7037, 0x0001, 0xa001, 0x7150, 0x00ee, 0x918c, 0xff00, - 0x9186, 0x0500, 0x0110, 0x79ac, 0x0810, 0x7004, 0xc09d, 0x7006, - 0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x15ab, 0x2001, 0x020d, - 0x2003, 0x0020, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, 0x090c, - 0x0d85, 0x6014, 0x2048, 0x78ab, 0x0004, 0x918c, 0x0700, 0x01a8, - 0x080c, 0x82b8, 0x080c, 0x1b1e, 0x080c, 0xcf1b, 0x0158, 0xa9ac, - 0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, 0xa880, - 0xc0bd, 0xa882, 0x080c, 0xcae9, 0x0005, 0x6020, 0x9086, 0x0009, - 0x1128, 0x2009, 0x004c, 0x080c, 0xb20a, 0x0048, 0x6010, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xd31e, 0x2029, - 0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, - 0x7dbc, 0x080c, 0xeeb1, 0xd5a4, 0x1118, 0x080c, 0x1648, 0x0005, - 0x080c, 0x82b8, 0x080c, 0x1b1e, 0x0005, 0x781f, 0x0300, 0x7803, - 0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300, - 0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, 0x0016, - 0x080c, 0x16b9, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, 0x7004, - 0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, 0x190c, 0x0d85, - 0xd184, 0x11b1, 0xd19c, 0x0180, 0xc19c, 0x7106, 0x0016, 0x080c, - 0x1723, 0x001e, 0x0148, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003, - 0x0020, 0x080c, 0x1648, 0x0005, 0x81ff, 0x190c, 0x0d85, 0x0005, - 0x2100, 0xc184, 0xc1b4, 0x7106, 0xd0b4, 0x0016, 0x00e6, 0x1904, - 0x1612, 0x2071, 0x0200, 0x080c, 0x1710, 0x05e0, 0x080c, 0x1723, - 0x05b0, 0x6014, 0x9005, 0x05b0, 0x0096, 0x2048, 0xa864, 0x009e, - 0x9084, 0x00ff, 0x908e, 0x0029, 0x0160, 0x908e, 0x0048, 0x1550, - 0x601c, 0xd084, 0x11e0, 0x00f6, 0x2c78, 0x080c, 0x17ad, 0x00fe, - 0x00b0, 0x00f6, 0x2c78, 0x080c, 0x1942, 0x00fe, 0x2009, 0x01f4, - 0x8109, 0x0168, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001, - 0x0218, 0x2004, 0xd0ec, 0x1118, 0x080c, 0x1648, 0x0040, 0x2001, - 0x020d, 0x2003, 0x0020, 0x080c, 0x1366, 0x7803, 0x0001, 0x00ee, - 0x001e, 0x0005, 0x080c, 0x1723, 0x0dd0, 0x2001, 0x020d, 0x2003, - 0x0050, 0x2003, 0x0020, 0x0461, 0x0c90, 0x0429, 0x2060, 0x2009, - 0x0053, 0x080c, 0xb20a, 0x0005, 0x0005, 0x0005, 0x00e1, 0x2008, - 0x00d1, 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, 0x080c, 0x92d5, - 0x0005, 0x0089, 0x9005, 0x0118, 0x080c, 0x8ed9, 0x0cd0, 0x0005, - 0x2001, 0x0036, 0x2009, 0x1820, 0x210c, 0x2011, 0x181f, 0x2214, - 0x080c, 0x16b9, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005, - 0x080c, 0x1592, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109, - 0x0510, 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000, - 0x79bc, 0xd1a4, 0x1528, 0x79b8, 0x918c, 0x0fff, 0x0180, 0x9182, - 0x0841, 0x1268, 0x9188, 0x0007, 0x918c, 0x0ff8, 0x810c, 0x810c, - 0x810c, 0x080c, 0x16ab, 0x6827, 0x0001, 0x8109, 0x1dd0, 0x04d9, - 0x6827, 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4, - 0x1500, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1130, 0x08c0, - 0x080c, 0x82b8, 0x080c, 0x1b1e, 0x0090, 0x7827, 0x0015, 0x782b, - 0x0000, 0x7827, 0x0018, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003, - 0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de, - 0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d30, 0x7827, - 0x0015, 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, 0x9085, 0x1800, - 0x6802, 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005, - 0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, 0x9086, 0x0041, - 0x0005, 0x00f6, 0x00e6, 0x2079, 0x0300, 0x0006, 0x2071, 0x1a6e, - 0x7008, 0x9005, 0x1110, 0x78e3, 0x0c0c, 0x8000, 0x700a, 0x0026, - 0x2011, 0x0006, 0x7808, 0xd09c, 0x0150, 0x0016, 0x0026, 0x00c6, - 0x080c, 0x13d4, 0x00ce, 0x002e, 0x001e, 0x8211, 0x1d98, 0x002e, - 0x000e, 0x0006, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x00b9, - 0x1178, 0x2071, 0x1a6e, 0x7008, 0x9005, 0x0130, 0x8001, 0x0a0c, - 0x0d85, 0x700a, 0x78e3, 0x0c00, 0x000e, 0x00ee, 0x00fe, 0x0005, - 0x000e, 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0d85, 0x2009, - 0xff00, 0x8109, 0x0120, 0x7818, 0xd0bc, 0x1dd8, 0x0005, 0x9085, - 0x0001, 0x0005, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x0c79, - 0x1108, 0x0005, 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0d85, - 0x7037, 0x0001, 0x7150, 0x7037, 0x0002, 0x7050, 0x2060, 0xd1bc, - 0x1110, 0x7054, 0x2060, 0x918c, 0xff00, 0x9186, 0x0500, 0x0110, - 0x9085, 0x0001, 0x0005, 0x0006, 0x0046, 0x00e6, 0x2071, 0x0200, - 0x7037, 0x0002, 0x7058, 0x9084, 0xff00, 0x8007, 0x9086, 0x00bc, - 0x1158, 0x2021, 0x1a7e, 0x2404, 0x8000, 0x0208, 0x2022, 0x080c, - 0x82b8, 0x080c, 0x1b1e, 0x9006, 0x00ee, 0x004e, 0x000e, 0x0005, - 0x0c11, 0x1108, 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, 0x0841, - 0x6124, 0xd1dc, 0x01f8, 0x701c, 0xd08c, 0x0904, 0x17a2, 0x7017, - 0x0000, 0x2001, 0x0264, 0x2004, 0xd0bc, 0x0904, 0x17a2, 0x2001, - 0x0268, 0x00c6, 0x2064, 0x6104, 0x6038, 0x00ce, 0x918e, 0x0039, - 0x1904, 0x17a2, 0x9c06, 0x15f0, 0x0126, 0x2091, 0x2600, 0x080c, - 0x8210, 0x012e, 0x7358, 0x745c, 0x6014, 0x905d, 0x0598, 0x2b48, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x190c, 0xd2f9, - 0xab42, 0xac3e, 0x2001, 0x1869, 0x2004, 0xd0b4, 0x1170, 0x601c, - 0xd0e4, 0x1158, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x1120, 0xa83b, 0x7fff, 0xa837, 0xffff, 0x080c, 0x1ee1, 0x1190, - 0x080c, 0x199f, 0x2a00, 0xa816, 0x0130, 0x2800, 0xa80e, 0x2c05, - 0xa80a, 0x2c00, 0xa812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e, - 0x00ee, 0x0005, 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee, - 0x080c, 0x1648, 0x0005, 0x080c, 0x0d85, 0x2001, 0x180d, 0x2004, - 0xd08c, 0x190c, 0x6ccc, 0x2cf0, 0x0126, 0x2091, 0x2200, 0x0016, - 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0x903e, 0x2730, 0xa864, - 0x2068, 0xa81a, 0x9d84, 0x000f, 0x9088, 0x1ec1, 0x2165, 0x0002, - 0x17df, 0x184d, 0x17df, 0x17df, 0x17e3, 0x182e, 0x17df, 0x1803, - 0x17d8, 0x1844, 0x17df, 0x17df, 0x17e8, 0x193a, 0x1817, 0x180d, - 0xa964, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0904, 0x1844, 0x9085, - 0x0001, 0x0804, 0x1930, 0xa87c, 0xd0ac, 0x0dc8, 0x0804, 0x1854, - 0xa87c, 0xd0ac, 0x0da0, 0x0804, 0x18bf, 0xa898, 0x901d, 0x1108, - 0xab9c, 0x9016, 0xaab2, 0xaa3e, 0xaa42, 0x3e00, 0x9080, 0x0008, - 0x2004, 0x9080, 0x9536, 0x2005, 0x9005, 0x090c, 0x0d85, 0x2004, - 0xa8ae, 0x0804, 0x1918, 0xa87c, 0xd0bc, 0x09c8, 0xa890, 0xa842, - 0xa88c, 0xa83e, 0xa888, 0x0804, 0x1854, 0xa87c, 0xd0bc, 0x0978, - 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x18bf, 0xa87c, - 0xd0bc, 0x0928, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa804, 0x9045, - 0x090c, 0x0d85, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x1ec1, - 0x2065, 0xa888, 0xd19c, 0x1904, 0x18bf, 0x0430, 0xa87c, 0xd0ac, - 0x0904, 0x17df, 0xa804, 0x9045, 0x090c, 0x0d85, 0xa164, 0xa91a, - 0x91ec, 0x000f, 0x9d80, 0x1ec1, 0x2065, 0x9006, 0xa842, 0xa83e, - 0xd19c, 0x1904, 0x18bf, 0x0080, 0xa87c, 0xd0ac, 0x0904, 0x17df, - 0x9006, 0xa842, 0xa83e, 0x0804, 0x18bf, 0xa87c, 0xd0ac, 0x0904, - 0x17df, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0036, 0x1a0c, - 0x0d85, 0x9082, 0x001b, 0x0002, 0x1877, 0x1877, 0x1879, 0x1877, - 0x1877, 0x1877, 0x1883, 0x1877, 0x1877, 0x1877, 0x188d, 0x1877, - 0x1877, 0x1877, 0x1897, 0x1877, 0x1877, 0x1877, 0x18a1, 0x1877, - 0x1877, 0x1877, 0x18ab, 0x1877, 0x1877, 0x1877, 0x18b5, 0x080c, - 0x0d85, 0xa574, 0xa478, 0x9d86, 0x0024, 0x0904, 0x17ed, 0xa37c, - 0xa280, 0x0804, 0x1918, 0xa584, 0xa488, 0x9d86, 0x0024, 0x0904, - 0x17ed, 0xa38c, 0xa290, 0x0804, 0x1918, 0xa594, 0xa498, 0x9d86, - 0x0024, 0x0904, 0x17ed, 0xa39c, 0xa2a0, 0x0804, 0x1918, 0xa5a4, - 0xa4a8, 0x9d86, 0x0024, 0x0904, 0x17ed, 0xa3ac, 0xa2b0, 0x0804, - 0x1918, 0xa5b4, 0xa4b8, 0x9d86, 0x0024, 0x0904, 0x17ed, 0xa3bc, - 0xa2c0, 0x0804, 0x1918, 0xa5c4, 0xa4c8, 0x9d86, 0x0024, 0x0904, - 0x17ed, 0xa3cc, 0xa2d0, 0x0804, 0x1918, 0xa5d4, 0xa4d8, 0x9d86, - 0x0024, 0x0904, 0x17ed, 0xa3dc, 0xa2e0, 0x0804, 0x1918, 0x2c05, - 0x908a, 0x0034, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x18e2, - 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x18ed, 0x18e0, 0x18e0, - 0x18e0, 0x18e0, 0x18e0, 0x18f8, 0x18e0, 0x18e0, 0x18e0, 0x18e0, - 0x18e0, 0x1903, 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x190e, - 0x080c, 0x0d85, 0xa56c, 0xa470, 0xa774, 0xa678, 0x9d86, 0x002c, - 0x0904, 0x17ed, 0xa37c, 0xa280, 0x0458, 0xa584, 0xa488, 0xa78c, - 0xa690, 0x9d86, 0x002c, 0x0904, 0x17ed, 0xa394, 0xa298, 0x0400, - 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86, 0x002c, 0x0904, 0x17ed, - 0xa3ac, 0xa2b0, 0x00a8, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0x9d86, - 0x002c, 0x0904, 0x17ed, 0xa3c4, 0xa2c8, 0x0050, 0xa5cc, 0xa4d0, - 0xa7d4, 0xa6d8, 0x9d86, 0x002c, 0x0904, 0x17ed, 0xa3dc, 0xa2e0, - 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa988, 0x8c60, - 0x2c1d, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x8109, 0xa916, 0x1160, - 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006, - 0x00ce, 0x001e, 0x012e, 0x0005, 0x2800, 0xa80e, 0xab0a, 0x2c00, - 0xa812, 0x0c70, 0x0804, 0x17df, 0x2001, 0x180d, 0x2004, 0xd08c, - 0x190c, 0x6ccc, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x0016, 0x00c6, - 0x3e60, 0x6014, 0x2048, 0x2940, 0xa80e, 0x2061, 0x1ebc, 0xa813, - 0x1ebc, 0x2c05, 0xa80a, 0xa964, 0xa91a, 0xa87c, 0xd0ac, 0x090c, - 0x0d85, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0034, 0x1a0c, - 0x0d85, 0xadcc, 0xacd0, 0xafd4, 0xaed8, 0xabdc, 0xaae0, 0xab2e, - 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa8ac, 0xaab0, 0xa836, - 0xaa3a, 0xa988, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0008, 0x1120, - 0x8109, 0xa916, 0x0128, 0x0080, 0x918a, 0x0002, 0xa916, 0x1160, - 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006, - 0x00ce, 0x001e, 0x012e, 0x0005, 0xa804, 0x9045, 0x090c, 0x0d85, - 0xa80e, 0xa064, 0xa81a, 0x9084, 0x000f, 0x9080, 0x1ec1, 0x2015, - 0x82ff, 0x090c, 0x0d85, 0xaa12, 0x2205, 0xa80a, 0x0c08, 0x903e, - 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1a94, 0x19f6, - 0x19f6, 0x1a94, 0x1a94, 0x1a8e, 0x1a94, 0x19f6, 0x1a45, 0x1a45, - 0x1a45, 0x1a94, 0x1a94, 0x1a94, 0x1a8b, 0x1a45, 0xc0fc, 0xa882, - 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x1a96, 0x2c05, - 0x908a, 0x0034, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x19e2, - 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19e6, 0x19e0, 0x19e0, - 0x19e0, 0x19e0, 0x19e0, 0x19ea, 0x19e0, 0x19e0, 0x19e0, 0x19e0, - 0x19e0, 0x19ee, 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19f2, - 0x080c, 0x0d85, 0xa774, 0xa678, 0x0804, 0x1a96, 0xa78c, 0xa690, - 0x0804, 0x1a96, 0xa7a4, 0xa6a8, 0x0804, 0x1a96, 0xa7bc, 0xa6c0, - 0x0804, 0x1a96, 0xa7d4, 0xa6d8, 0x0804, 0x1a96, 0x2c05, 0x908a, - 0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x1a19, 0x1a19, - 0x1a1b, 0x1a19, 0x1a19, 0x1a19, 0x1a21, 0x1a19, 0x1a19, 0x1a19, - 0x1a27, 0x1a19, 0x1a19, 0x1a19, 0x1a2d, 0x1a19, 0x1a19, 0x1a19, - 0x1a33, 0x1a19, 0x1a19, 0x1a19, 0x1a39, 0x1a19, 0x1a19, 0x1a19, - 0x1a3f, 0x080c, 0x0d85, 0xa574, 0xa478, 0xa37c, 0xa280, 0x0804, - 0x1a96, 0xa584, 0xa488, 0xa38c, 0xa290, 0x0804, 0x1a96, 0xa594, - 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x1a96, 0xa5a4, 0xa4a8, 0xa3ac, - 0xa2b0, 0x0804, 0x1a96, 0xa5b4, 0xa4b8, 0xa3bc, 0xa2c0, 0x0804, - 0x1a96, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, 0x0804, 0x1a96, 0xa5d4, - 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x1a96, 0x2c05, 0x908a, 0x0034, - 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x1a68, 0x1a66, 0x1a66, - 0x1a66, 0x1a66, 0x1a66, 0x1a6f, 0x1a66, 0x1a66, 0x1a66, 0x1a66, - 0x1a66, 0x1a76, 0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a7d, - 0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a84, 0x080c, 0x0d85, - 0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c, 0xa280, 0x0438, 0xa584, - 0xa488, 0xa78c, 0xa690, 0xa394, 0xa298, 0x0400, 0xa59c, 0xa4a0, - 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x00c8, 0xa5b4, 0xa4b8, 0xa7bc, - 0xa6c0, 0xa3c4, 0xa2c8, 0x0090, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, - 0xa3dc, 0xa2e0, 0x0058, 0x9d86, 0x000e, 0x1130, 0x080c, 0x1e97, - 0x1904, 0x199f, 0x900e, 0x0050, 0x080c, 0x0d85, 0xab2e, 0xaa32, - 0xad1e, 0xac22, 0xaf26, 0xae2a, 0x080c, 0x1e97, 0x0005, 0x6014, - 0x2048, 0x6118, 0x81ff, 0x0148, 0x810c, 0x810c, 0x810c, 0x81ff, - 0x1118, 0xa887, 0x0001, 0x0008, 0xa986, 0x601b, 0x0002, 0xa874, - 0x9084, 0x00ff, 0x9084, 0x0008, 0x0150, 0x00e9, 0x6000, 0x9086, - 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0xb20a, 0x0005, 0xa974, - 0xd1dc, 0x1108, 0x0005, 0xa934, 0xa88c, 0x9106, 0x1158, 0xa938, - 0xa890, 0x9106, 0x1138, 0x601c, 0xc084, 0x601e, 0x2009, 0x0048, - 0x0804, 0xb20a, 0x0005, 0x0126, 0x00c6, 0x2091, 0x2200, 0x00ce, - 0x7908, 0x918c, 0x0007, 0x9186, 0x0000, 0x05b0, 0x9186, 0x0003, - 0x0598, 0x6020, 0x6023, 0x0000, 0x0006, 0x2031, 0x0008, 0x00c6, - 0x781f, 0x0808, 0x7808, 0xd09c, 0x0120, 0x080c, 0x13d4, 0x8631, - 0x1db8, 0x00ce, 0x781f, 0x0800, 0x2031, 0x0168, 0x00c6, 0x7808, - 0xd09c, 0x190c, 0x13d4, 0x00ce, 0x2001, 0x0038, 0x080c, 0x1bae, - 0x7930, 0x9186, 0x0040, 0x0160, 0x9186, 0x0042, 0x190c, 0x0d85, - 0x2001, 0x001e, 0x8001, 0x1df0, 0x8631, 0x1d40, 0x080c, 0x1bbd, - 0x000e, 0x6022, 0x012e, 0x0005, 0x080c, 0x1baa, 0x7827, 0x0015, - 0x7828, 0x9c06, 0x1db8, 0x782b, 0x0000, 0x0ca0, 0x00f6, 0x2079, - 0x0300, 0x7803, 0x0000, 0x78ab, 0x0004, 0x2001, 0xf000, 0x8001, - 0x090c, 0x0d85, 0x7aac, 0xd2ac, 0x1dd0, 0x00fe, 0x080c, 0x779e, - 0x1188, 0x2001, 0x0138, 0x2003, 0x0000, 0x2001, 0x0160, 0x2003, - 0x0000, 0x2011, 0x012c, 0xa001, 0xa001, 0x8211, 0x1de0, 0x0059, - 0x0804, 0x7840, 0x0479, 0x0039, 0x2001, 0x0160, 0x2502, 0x2001, - 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, 0x0200, 0x080c, 0x2a8b, - 0x2009, 0x003c, 0x080c, 0x2220, 0x2001, 0x015d, 0x2003, 0x0000, - 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, 0x8899, 0x70a0, 0x70a2, - 0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, 0x2003, 0x0020, - 0x00f6, 0x2079, 0x0300, 0x080c, 0x1366, 0x7803, 0x0001, 0x00fe, - 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2001, - 0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x779e, 0x1108, 0x0005, - 0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001, - 0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, 0x0111, 0x201c, - 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, 0x2003, 0x0000, - 0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, 0xa001, 0xa001, - 0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, 0x004e, 0x0c60, - 0x004e, 0x0c40, 0x601c, 0xc084, 0x601e, 0x0005, 0x2c08, 0x621c, - 0x080c, 0x16b9, 0x7930, 0x0005, 0x2c08, 0x621c, 0x080c, 0x1702, - 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, 0x2031, 0x0064, 0x781c, - 0x9084, 0x0007, 0x0170, 0x2001, 0x0038, 0x0c41, 0x9186, 0x0040, - 0x0904, 0x1c1b, 0x2001, 0x001e, 0x0c69, 0x8631, 0x1d80, 0x080c, - 0x0d85, 0x781f, 0x0202, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, - 0x0dac, 0x0c01, 0x781c, 0xd084, 0x0110, 0x0861, 0x04e0, 0x2001, - 0x0030, 0x0891, 0x9186, 0x0040, 0x0568, 0x781c, 0xd084, 0x1da8, - 0x781f, 0x0101, 0x2001, 0x0014, 0x0869, 0x2001, 0x0037, 0x0821, - 0x9186, 0x0040, 0x0140, 0x2001, 0x0030, 0x080c, 0x1bb4, 0x9186, - 0x0040, 0x190c, 0x0d85, 0x00d6, 0x2069, 0x0200, 0x692c, 0xd1f4, - 0x1170, 0xd1c4, 0x0160, 0xd19c, 0x0130, 0x6800, 0x9085, 0x1800, - 0x6802, 0x00de, 0x0080, 0x6908, 0x9184, 0x0007, 0x1db0, 0x00de, - 0x781f, 0x0100, 0x791c, 0x9184, 0x0007, 0x090c, 0x0d85, 0xa001, - 0xa001, 0x781f, 0x0200, 0x0005, 0x0126, 0x2091, 0x2400, 0x2079, - 0x0380, 0x2001, 0x19e8, 0x2070, 0x012e, 0x0005, 0x2cf0, 0x0126, - 0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, 0xa964, 0xa91a, 0x918c, - 0x00ff, 0x9184, 0x000f, 0x0002, 0x1c50, 0x1c50, 0x1c50, 0x1c52, - 0x1c50, 0x1c50, 0x1c50, 0x1c50, 0x1c44, 0x1c5a, 0x1c50, 0x1c56, - 0x1c50, 0x1c50, 0x1c50, 0x1c50, 0x9086, 0x0008, 0x1148, 0xa87c, - 0xd0b4, 0x0904, 0x1dca, 0x2011, 0x1ebc, 0x2205, 0xab88, 0x00a8, - 0x080c, 0x0d85, 0x9186, 0x0013, 0x0128, 0x0cd0, 0x9186, 0x001b, - 0x0108, 0x0cb0, 0xa87c, 0xd0b4, 0x0904, 0x1dca, 0x9184, 0x000f, - 0x9080, 0x1ec1, 0x2015, 0x2205, 0xab88, 0x2908, 0xa80a, 0xa90e, - 0xaa12, 0xab16, 0x9006, 0xa842, 0xa83e, 0x012e, 0x0005, 0x2cf0, - 0x0126, 0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, 0xa88c, 0xa990, - 0xaaac, 0xabb0, 0xaa36, 0xab3a, 0xa83e, 0xa942, 0xa846, 0xa94a, - 0xa964, 0x918c, 0x00ff, 0x9186, 0x001e, 0x0198, 0x2940, 0xa064, - 0xa81a, 0x90ec, 0x000f, 0x9d80, 0x1ec1, 0x2065, 0x2c05, 0x2808, - 0x2c10, 0xab88, 0xa80a, 0xa90e, 0xaa12, 0xab16, 0x012e, 0x3e60, - 0x0005, 0xa804, 0x2040, 0x0c58, 0x2cf0, 0x0126, 0x2091, 0x2400, - 0x3e60, 0x6014, 0x2048, 0xa97c, 0x2950, 0xd1dc, 0x1904, 0x1d94, - 0xc1dd, 0xa97e, 0x9006, 0xa842, 0xa83e, 0xa988, 0x8109, 0xa916, - 0xa964, 0xa91a, 0x9184, 0x000f, 0x9088, 0x1ec1, 0x2145, 0x0002, - 0x1cc8, 0x1cd6, 0x1cc8, 0x1cc8, 0x1cc8, 0x1cca, 0x1cc8, 0x1cc8, - 0x1d2b, 0x1d2b, 0x1cc8, 0x1cc8, 0x1cc8, 0x1d29, 0x1cc8, 0x1cc8, - 0x080c, 0x0d85, 0xa804, 0x2050, 0xb164, 0xa91a, 0x9184, 0x000f, - 0x9080, 0x1ec1, 0x2045, 0xd19c, 0x1904, 0x1d2b, 0x9036, 0x2638, - 0x2805, 0x908a, 0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, - 0x1cfb, 0x1cfb, 0x1cfd, 0x1cfb, 0x1cfb, 0x1cfb, 0x1d03, 0x1cfb, - 0x1cfb, 0x1cfb, 0x1d09, 0x1cfb, 0x1cfb, 0x1cfb, 0x1d0f, 0x1cfb, - 0x1cfb, 0x1cfb, 0x1d15, 0x1cfb, 0x1cfb, 0x1cfb, 0x1d1b, 0x1cfb, - 0x1cfb, 0x1cfb, 0x1d21, 0x080c, 0x0d85, 0xb574, 0xb478, 0xb37c, - 0xb280, 0x0804, 0x1d70, 0xb584, 0xb488, 0xb38c, 0xb290, 0x0804, - 0x1d70, 0xb594, 0xb498, 0xb39c, 0xb2a0, 0x0804, 0x1d70, 0xb5a4, - 0xb4a8, 0xb3ac, 0xb2b0, 0x0804, 0x1d70, 0xb5b4, 0xb4b8, 0xb3bc, - 0xb2c0, 0x0804, 0x1d70, 0xb5c4, 0xb4c8, 0xb3cc, 0xb2d0, 0x0804, - 0x1d70, 0xb5d4, 0xb4d8, 0xb3dc, 0xb2e0, 0x0804, 0x1d70, 0x0804, - 0x1d70, 0x080c, 0x0d85, 0x2805, 0x908a, 0x0034, 0x1a0c, 0x0d85, - 0x9082, 0x001b, 0x0002, 0x1d4e, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, - 0x1d4c, 0x1d55, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d5c, - 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d63, 0x1d4c, 0x1d4c, - 0x1d4c, 0x1d4c, 0x1d4c, 0x1d6a, 0x080c, 0x0d85, 0xb56c, 0xb470, - 0xb774, 0xb678, 0xb37c, 0xb280, 0x00d8, 0xb584, 0xb488, 0xb78c, - 0xb690, 0xb394, 0xb298, 0x00a0, 0xb59c, 0xb4a0, 0xb7a4, 0xb6a8, - 0xb3ac, 0xb2b0, 0x0068, 0xb5b4, 0xb4b8, 0xb7bc, 0xb6c0, 0xb3c4, - 0xb2c8, 0x0030, 0xb5cc, 0xb4d0, 0xb7d4, 0xb6d8, 0xb3dc, 0xb2e0, - 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa988, 0x8109, - 0xa916, 0x1118, 0x9006, 0x012e, 0x0005, 0x8840, 0x2805, 0x9005, - 0x1168, 0xb004, 0x9005, 0x090c, 0x0d85, 0x2050, 0xb164, 0xa91a, - 0x9184, 0x000f, 0x9080, 0x1ec1, 0x2045, 0x2805, 0x2810, 0x2a08, - 0xa80a, 0xa90e, 0xaa12, 0x0c30, 0x3e60, 0x6344, 0xd3fc, 0x190c, - 0x0d85, 0xa93c, 0xaa40, 0xa844, 0x9106, 0x1118, 0xa848, 0x9206, - 0x0508, 0x2958, 0xab48, 0xac44, 0x2940, 0x080c, 0x1ee1, 0x1998, - 0x2850, 0x2c40, 0xab14, 0xa880, 0xd0fc, 0x1140, 0xa810, 0x2005, - 0xa80a, 0x2a00, 0xa80e, 0x2009, 0x8015, 0x0070, 0x00c6, 0x3e60, - 0x6044, 0xc0a4, 0x9085, 0x8005, 0x6046, 0x00ce, 0x8319, 0xab16, - 0x1904, 0x1d7d, 0x2009, 0x8005, 0x3e60, 0x6044, 0x9105, 0x6046, - 0x0804, 0x1d7a, 0x080c, 0x0d85, 0x00f6, 0x00e6, 0x0096, 0x00c6, - 0x0026, 0x704c, 0x9c06, 0x190c, 0x0d85, 0x2079, 0x0090, 0x2001, - 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7057, 0x0000, 0x6014, - 0x2048, 0x080c, 0xcf1b, 0x0118, 0xa880, 0xc0bd, 0xa882, 0x6020, - 0x9086, 0x0006, 0x1170, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa, - 0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0xa89a, 0x60c8, - 0xa896, 0x704c, 0x2060, 0x00c6, 0x080c, 0xcae9, 0x080c, 0xacfc, - 0x00ce, 0x704c, 0x9c06, 0x1150, 0x2009, 0x0040, 0x080c, 0x2220, - 0x080c, 0xa7a1, 0x2011, 0x0000, 0x080c, 0xa635, 0x002e, 0x00ce, - 0x009e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0090, 0x781c, - 0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, - 0x9085, 0x0012, 0x7816, 0x2019, 0x1000, 0x8319, 0x090c, 0x0d85, - 0x7820, 0xd0bc, 0x1dd0, 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006, - 0x0016, 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, - 0x1984, 0x9085, 0x0012, 0x7816, 0x2079, 0x0090, 0x782b, 0x0008, - 0x7057, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x19e8, - 0x7054, 0x9086, 0x0000, 0x0904, 0x1e92, 0x2079, 0x0090, 0x2009, - 0x0207, 0x210c, 0xd194, 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, - 0x0003, 0x0188, 0x080c, 0xeefa, 0x2001, 0x0133, 0x2004, 0x9005, - 0x090c, 0x0d85, 0x0016, 0x2009, 0x0040, 0x080c, 0x2220, 0x001e, - 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, - 0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x2220, 0x782c, - 0xd0fc, 0x09a8, 0x080c, 0xad18, 0x782c, 0xd0fc, 0x1de8, 0x080c, - 0xacfc, 0x7054, 0x9086, 0x0000, 0x1950, 0x782b, 0x0004, 0x782c, - 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2220, 0x782b, 0x0002, - 0x7057, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x080c, 0x0d85, 0x8c60, - 0x2c05, 0x9005, 0x0110, 0x8a51, 0x0005, 0xa004, 0x9005, 0x0168, - 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x1ec1, 0x2065, - 0x8cff, 0x090c, 0x0d85, 0x8a51, 0x0005, 0x2050, 0x0005, 0x0000, - 0x001d, 0x0021, 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, - 0x001b, 0x0021, 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, 0x0023, - 0x0000, 0x0000, 0x1eb4, 0x1eb0, 0x1eb4, 0x1eb4, 0x1ebe, 0x0000, - 0x1eb4, 0x1ebb, 0x1ebb, 0x1eb8, 0x1ebb, 0x1ebb, 0x0000, 0x1ebe, - 0x1ebb, 0x0000, 0x1eb6, 0x1eb6, 0x0000, 0x1eb6, 0x1ebe, 0x0000, - 0x1eb6, 0x1ebc, 0x1ebc, 0x1ebc, 0x0000, 0x1ebc, 0x0000, 0x1ebe, - 0x1ebc, 0x00c6, 0x00d6, 0x0086, 0xab42, 0xac3e, 0xa888, 0x9055, - 0x0904, 0x20c0, 0x2940, 0xa064, 0x90ec, 0x000f, 0x9084, 0x00ff, - 0x9086, 0x0008, 0x1118, 0x2061, 0x1ebc, 0x00d0, 0x9de0, 0x1ec1, - 0x9d86, 0x0007, 0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f, - 0x1120, 0xa08c, 0x9422, 0xa090, 0x931b, 0x2c05, 0x9065, 0x1140, - 0x0310, 0x0804, 0x20c0, 0xa004, 0x9045, 0x0904, 0x20c0, 0x08d8, - 0x2c05, 0x9005, 0x0904, 0x1fa8, 0xdd9c, 0x1904, 0x1f64, 0x908a, - 0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x1f39, 0x1f39, - 0x1f3b, 0x1f39, 0x1f39, 0x1f39, 0x1f41, 0x1f39, 0x1f39, 0x1f39, - 0x1f47, 0x1f39, 0x1f39, 0x1f39, 0x1f4d, 0x1f39, 0x1f39, 0x1f39, - 0x1f53, 0x1f39, 0x1f39, 0x1f39, 0x1f59, 0x1f39, 0x1f39, 0x1f39, - 0x1f5f, 0x080c, 0x0d85, 0xa07c, 0x9422, 0xa080, 0x931b, 0x0804, - 0x1f9e, 0xa08c, 0x9422, 0xa090, 0x931b, 0x0804, 0x1f9e, 0xa09c, - 0x9422, 0xa0a0, 0x931b, 0x0804, 0x1f9e, 0xa0ac, 0x9422, 0xa0b0, - 0x931b, 0x0804, 0x1f9e, 0xa0bc, 0x9422, 0xa0c0, 0x931b, 0x0804, - 0x1f9e, 0xa0cc, 0x9422, 0xa0d0, 0x931b, 0x0804, 0x1f9e, 0xa0dc, - 0x9422, 0xa0e0, 0x931b, 0x04d0, 0x908a, 0x0034, 0x1a0c, 0x0d85, - 0x9082, 0x001b, 0x0002, 0x1f86, 0x1f84, 0x1f84, 0x1f84, 0x1f84, - 0x1f84, 0x1f8b, 0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f90, - 0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f95, 0x1f84, 0x1f84, - 0x1f84, 0x1f84, 0x1f84, 0x1f9a, 0x080c, 0x0d85, 0xa07c, 0x9422, - 0xa080, 0x931b, 0x0098, 0xa094, 0x9422, 0xa098, 0x931b, 0x0070, - 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0048, 0xa0c4, 0x9422, 0xa0c8, - 0x931b, 0x0020, 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x0630, 0x2300, - 0x9405, 0x0160, 0x8a51, 0x0904, 0x20c0, 0x8c60, 0x0804, 0x1f10, - 0xa004, 0x9045, 0x0904, 0x20c0, 0x0804, 0x1eeb, 0x8a51, 0x0904, - 0x20c0, 0x8c60, 0x2c05, 0x9005, 0x1158, 0xa004, 0x9045, 0x0904, - 0x20c0, 0xa064, 0x90ec, 0x000f, 0x9de0, 0x1ec1, 0x2c05, 0x2060, - 0xa880, 0xc0fc, 0xa882, 0x0804, 0x20b5, 0x2c05, 0x8422, 0x8420, - 0x831a, 0x9399, 0x0000, 0xac2e, 0xab32, 0xdd9c, 0x1904, 0x2052, - 0x9082, 0x001b, 0x0002, 0x1fee, 0x1fee, 0x1ff0, 0x1fee, 0x1fee, - 0x1fee, 0x1ffe, 0x1fee, 0x1fee, 0x1fee, 0x200c, 0x1fee, 0x1fee, - 0x1fee, 0x201a, 0x1fee, 0x1fee, 0x1fee, 0x2028, 0x1fee, 0x1fee, - 0x1fee, 0x2036, 0x1fee, 0x1fee, 0x1fee, 0x2044, 0x080c, 0x0d85, - 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0d85, - 0xa074, 0x9420, 0xa078, 0x9319, 0x0804, 0x20b0, 0xa18c, 0x2400, - 0x9122, 0xa190, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa084, 0x9420, - 0xa088, 0x9319, 0x0804, 0x20b0, 0xa19c, 0x2400, 0x9122, 0xa1a0, - 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa094, 0x9420, 0xa098, 0x9319, - 0x0804, 0x20b0, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, - 0x0a0c, 0x0d85, 0xa0a4, 0x9420, 0xa0a8, 0x9319, 0x0804, 0x20b0, - 0xa1bc, 0x2400, 0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, 0x0d85, - 0xa0b4, 0x9420, 0xa0b8, 0x9319, 0x0804, 0x20b0, 0xa1cc, 0x2400, - 0x9122, 0xa1d0, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0c4, 0x9420, - 0xa0c8, 0x9319, 0x0804, 0x20b0, 0xa1dc, 0x2400, 0x9122, 0xa1e0, - 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0d4, 0x9420, 0xa0d8, 0x9319, - 0x0804, 0x20b0, 0x9082, 0x001b, 0x0002, 0x2070, 0x206e, 0x206e, - 0x206e, 0x206e, 0x206e, 0x207d, 0x206e, 0x206e, 0x206e, 0x206e, - 0x206e, 0x208a, 0x206e, 0x206e, 0x206e, 0x206e, 0x206e, 0x2097, - 0x206e, 0x206e, 0x206e, 0x206e, 0x206e, 0x20a4, 0x080c, 0x0d85, - 0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0d85, - 0xa06c, 0x9420, 0xa070, 0x9319, 0x0498, 0xa194, 0x2400, 0x9122, - 0xa198, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa084, 0x9420, 0xa088, - 0x9319, 0x0430, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, - 0x0a0c, 0x0d85, 0xa09c, 0x9420, 0xa0a0, 0x9319, 0x00c8, 0xa1c4, - 0x2400, 0x9122, 0xa1c8, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0b4, - 0x9420, 0xa0b8, 0x9319, 0x0060, 0xa1dc, 0x2400, 0x9122, 0xa1e0, - 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0cc, 0x9420, 0xa0d0, 0x9319, - 0xac1e, 0xab22, 0xa880, 0xc0fd, 0xa882, 0x2800, 0xa85a, 0x2c00, - 0xa812, 0x2a00, 0xa816, 0x000e, 0x000e, 0x000e, 0x9006, 0x0028, - 0x008e, 0x00de, 0x00ce, 0x9085, 0x0001, 0x0005, 0x00c6, 0x610c, - 0x0016, 0x9026, 0x2410, 0x6004, 0x9420, 0x9291, 0x0000, 0x2c04, - 0x9210, 0x9ce0, 0x0002, 0x918a, 0x0002, 0x1da8, 0x9284, 0x000f, - 0x9405, 0x001e, 0x00ce, 0x0005, 0x7803, 0x0003, 0x780f, 0x0000, - 0x6004, 0x7812, 0x2c04, 0x7816, 0x9ce0, 0x0002, 0x918a, 0x0002, - 0x1db8, 0x0005, 0x2001, 0x0005, 0x2004, 0xd0bc, 0x190c, 0x0d7e, - 0xd094, 0x0110, 0x080c, 0x1208, 0x0005, 0x0126, 0x2091, 0x2600, - 0x2079, 0x0200, 0x2071, 0x0260, 0x2069, 0x1800, 0x7817, 0x0000, - 0x789b, 0x0814, 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, 0x013b, - 0x200b, 0x0400, 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, 0x0020, - 0x7803, 0x1600, 0x012e, 0x0005, 0x2091, 0x2600, 0x781c, 0xd0a4, - 0x190c, 0x221d, 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, 0x001a, - 0x9084, 0x000e, 0x0002, 0x213b, 0x2133, 0x8210, 0x2133, 0x2135, - 0x2135, 0x2135, 0x2135, 0x81f6, 0x2133, 0x2137, 0x2133, 0x2135, - 0x2133, 0x2135, 0x2133, 0x080c, 0x0d85, 0x0031, 0x0020, 0x080c, - 0x81f6, 0x080c, 0x8210, 0x0005, 0x0006, 0x0016, 0x0026, 0x080c, - 0xeefa, 0x7930, 0x9184, 0x0003, 0x0510, 0x080c, 0xacfc, 0x2001, - 0x19fb, 0x2004, 0x9005, 0x01a0, 0x2001, 0x0133, 0x2004, 0x9005, - 0x090c, 0x0d85, 0x00c6, 0x2001, 0x19fb, 0x2064, 0x080c, 0xad18, - 0x080c, 0xcae9, 0x2009, 0x0040, 0x080c, 0x2220, 0x00ce, 0x0408, - 0x2009, 0x0040, 0x080c, 0x2220, 0x080c, 0xad18, 0x00d0, 0x9184, - 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, 0x080c, 0x779e, - 0x1138, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x080c, 0x76cd, 0x0010, - 0x080c, 0x6058, 0x080c, 0x82ae, 0x0041, 0x0018, 0x9184, 0x9540, - 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x0036, 0x0046, - 0x0056, 0x2071, 0x1a6e, 0x080c, 0x1b1e, 0x005e, 0x004e, 0x003e, - 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, 0x1800, 0x7128, - 0x2001, 0x196f, 0x2102, 0x2001, 0x1977, 0x2102, 0x2001, 0x013b, - 0x2102, 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, 0x78a3, 0x0200, - 0x9198, 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, 0x0005, 0x2320, - 0x9182, 0x0204, 0x1230, 0x2011, 0x0008, 0x8423, 0x8423, 0x8423, - 0x0488, 0x9182, 0x024c, 0x1240, 0x2011, 0x0007, 0x8403, 0x8003, - 0x9400, 0x9400, 0x9420, 0x0430, 0x9182, 0x02bc, 0x1238, 0x2011, - 0x0006, 0x8403, 0x8003, 0x9400, 0x9420, 0x00e0, 0x9182, 0x034c, - 0x1230, 0x2011, 0x0005, 0x8403, 0x8003, 0x9420, 0x0098, 0x9182, - 0x042c, 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, 0x0058, 0x9182, - 0x059c, 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, 0x0018, 0x2011, - 0x0002, 0x8423, 0x9482, 0x0228, 0x8002, 0x8020, 0x8301, 0x9402, - 0x0110, 0x0208, 0x8321, 0x8217, 0x8203, 0x9405, 0x789a, 0x012e, - 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6814, 0x9084, 0xffc0, - 0x910d, 0x6916, 0x00de, 0x000e, 0x0005, 0x00d6, 0x2069, 0x0200, - 0x9005, 0x6810, 0x0110, 0xc0a5, 0x0008, 0xc0a4, 0x6812, 0x00de, - 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6810, 0x9084, 0xfff8, - 0x910d, 0x6912, 0x00de, 0x000e, 0x0005, 0x7938, 0x080c, 0x0d7e, - 0x00f6, 0x2079, 0x0200, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, - 0xa001, 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, - 0xa001, 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100, - 0x2071, 0x1800, 0x2009, 0x0000, 0x080c, 0x2a85, 0x080c, 0x299b, - 0x2001, 0x199d, 0x2003, 0x0700, 0x2001, 0x199e, 0x2003, 0x0700, - 0x080c, 0x2af6, 0x9006, 0x080c, 0x29ca, 0x9006, 0x080c, 0x29ad, - 0x20a9, 0x0012, 0x1d04, 0x2252, 0x2091, 0x6000, 0x1f04, 0x2252, - 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, - 0xdfff, 0x6052, 0x6224, 0x080c, 0x2ad3, 0x080c, 0x26c5, 0x2009, - 0x00ef, 0x6132, 0x6136, 0x080c, 0x26d5, 0x60e7, 0x0000, 0x61ea, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1110, 0x2001, - 0x0008, 0x60e2, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, - 0x602f, 0x0000, 0x6007, 0x349f, 0x00c6, 0x2061, 0x0140, 0x608b, - 0x000b, 0x608f, 0x10b8, 0x6093, 0x0000, 0x6097, 0x0198, 0x00ce, - 0x6004, 0x9085, 0x8000, 0x6006, 0x60bb, 0x0000, 0x20a9, 0x0018, - 0x60bf, 0x0000, 0x1f04, 0x2298, 0x60bb, 0x0000, 0x60bf, 0x0108, - 0x60bf, 0x0012, 0x60bf, 0x0405, 0x60bf, 0x0014, 0x60bf, 0x0320, - 0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b, - 0x602b, 0x402c, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3, - 0x0080, 0x78c3, 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001, - 0x1835, 0x2003, 0x0000, 0x2001, 0x1834, 0x2003, 0x0001, 0x0005, - 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x6028, - 0x910c, 0x0066, 0x2031, 0x1837, 0x2634, 0x96b4, 0x0028, 0x006e, - 0x1138, 0x6020, 0xd1bc, 0x0120, 0xd0bc, 0x1168, 0xd0b4, 0x1198, - 0x9184, 0x5e2c, 0x1118, 0x9184, 0x0007, 0x00aa, 0x9195, 0x0004, - 0x9284, 0x0007, 0x0082, 0x0016, 0x2001, 0x0387, 0x200c, 0xd1a4, - 0x001e, 0x0d70, 0x0c98, 0x0016, 0x2001, 0x0387, 0x200c, 0xd1b4, - 0x001e, 0x0d30, 0x0c58, 0x2306, 0x2303, 0x2303, 0x2303, 0x2305, - 0x2303, 0x2303, 0x2303, 0x080c, 0x0d85, 0x0029, 0x002e, 0x001e, - 0x000e, 0x012e, 0x0005, 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, - 0xd19c, 0x1904, 0x258b, 0xd1f4, 0x190c, 0x0d7e, 0x080c, 0x779e, - 0x0904, 0x2363, 0x080c, 0xd645, 0x1120, 0x7000, 0x9086, 0x0003, - 0x0580, 0x6024, 0x9084, 0x1800, 0x0560, 0x080c, 0x77c1, 0x0118, - 0x080c, 0x77af, 0x1530, 0x2011, 0x0020, 0x080c, 0x2ad3, 0x6043, - 0x0000, 0x080c, 0xd645, 0x0168, 0x080c, 0x77c1, 0x1150, 0x2001, - 0x19a8, 0x2003, 0x0001, 0x6027, 0x1800, 0x080c, 0x7612, 0x0804, - 0x258e, 0x70a4, 0x9005, 0x1150, 0x70a7, 0x0001, 0x00d6, 0x2069, - 0x0140, 0x080c, 0x77f2, 0x00de, 0x1904, 0x258e, 0x080c, 0x7ac0, - 0x0428, 0x080c, 0x77c1, 0x1590, 0x6024, 0x9084, 0x1800, 0x1108, - 0x0468, 0x080c, 0x7ac0, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x080c, - 0x76cd, 0x0804, 0x258b, 0xd1ac, 0x1508, 0x6024, 0xd0dc, 0x1170, - 0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc, 0x0130, 0x7098, 0x9086, - 0x0029, 0x1110, 0x080c, 0x7990, 0x0804, 0x258b, 0x080c, 0x7abb, - 0x0048, 0x2001, 0x197d, 0x2003, 0x0002, 0x0020, 0x080c, 0x78e4, - 0x0804, 0x258b, 0x080c, 0x7a3a, 0x0804, 0x258b, 0x6220, 0xd1bc, - 0x0138, 0xd2bc, 0x1904, 0x25f6, 0xd2b4, 0x1904, 0x2608, 0x0000, - 0xd1ac, 0x0904, 0x2498, 0x0036, 0x6328, 0xc3bc, 0x632a, 0x003e, - 0x080c, 0x779e, 0x11d0, 0x2011, 0x0020, 0x080c, 0x2ad3, 0x0006, - 0x0026, 0x0036, 0x080c, 0x77b8, 0x1158, 0x080c, 0x7ab6, 0x080c, - 0x619d, 0x080c, 0x76cd, 0x003e, 0x002e, 0x000e, 0x00ae, 0x0005, - 0x003e, 0x002e, 0x000e, 0x080c, 0x7772, 0x0016, 0x0046, 0x00c6, - 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, - 0x0090, 0x6043, 0x0010, 0x74da, 0x948c, 0xff00, 0x7038, 0xd084, - 0x0190, 0x080c, 0xd645, 0x1118, 0x9186, 0xf800, 0x1160, 0x7048, - 0xd084, 0x1148, 0xc085, 0x704a, 0x0036, 0x2418, 0x2011, 0x8016, - 0x080c, 0x4ca1, 0x003e, 0x080c, 0xd63e, 0x1904, 0x246d, 0x9196, - 0xff00, 0x05a8, 0x7060, 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110, - 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, 0x3482, 0x0128, - 0xc18d, 0x7132, 0x080c, 0x6c09, 0x1510, 0x6240, 0x9294, 0x0010, - 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030, - 0xd08c, 0x0904, 0x246d, 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, - 0x200c, 0xd1ac, 0x1904, 0x246d, 0xc1ad, 0x2102, 0x0036, 0x73d8, - 0x2011, 0x8013, 0x080c, 0x4ca1, 0x003e, 0x0804, 0x246d, 0x7038, - 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, 0x246d, - 0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c, 0x4ca1, - 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1848, 0x220c, 0xd1a4, - 0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8c44, - 0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, 0xe9f9, 0x00ce, - 0x9484, 0x00ff, 0x9080, 0x348e, 0x200d, 0x918c, 0xff00, 0x810f, - 0x2120, 0x9006, 0x2009, 0x000e, 0x080c, 0xea8d, 0x001e, 0x0016, - 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x32da, 0x001e, 0x00a8, - 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x67b4, 0x1140, - 0x7030, 0xd084, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x61b7, - 0x8108, 0x1f04, 0x245d, 0x00be, 0x015e, 0x00ce, 0x004e, 0x080c, - 0xacfc, 0x080c, 0xafd2, 0x080c, 0xb09b, 0x080c, 0xad18, 0x60e3, - 0x0000, 0x001e, 0x2001, 0x1800, 0x2014, 0x9296, 0x0004, 0x1170, - 0xd19c, 0x11b0, 0x2011, 0x180c, 0x2214, 0xd29c, 0x1120, 0x6204, - 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, - 0x2001, 0x1826, 0x2003, 0x0000, 0x2011, 0x0020, 0x080c, 0x2ad3, - 0xd194, 0x0904, 0x258b, 0x0016, 0x080c, 0xacfc, 0x6220, 0xd2b4, - 0x0904, 0x2526, 0x080c, 0x8a4b, 0x080c, 0xa2a0, 0x2011, 0x0004, - 0x080c, 0x2ad3, 0x00f6, 0x2019, 0x19f4, 0x2304, 0x907d, 0x0904, - 0x24f3, 0x7804, 0x9086, 0x0032, 0x15f0, 0x00d6, 0x00c6, 0x00e6, - 0x0096, 0x2069, 0x0140, 0x782c, 0x685e, 0x7808, 0x685a, 0x6043, - 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x2001, - 0x003c, 0x8001, 0x1df0, 0x080c, 0x2aa9, 0x2001, 0x001e, 0x8001, - 0x0240, 0x20a9, 0x0009, 0x080c, 0x2a60, 0x6904, 0xd1dc, 0x1140, - 0x0cb0, 0x2001, 0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, - 0x080c, 0x99ed, 0x080c, 0xad18, 0x7814, 0x2048, 0xa867, 0x0103, - 0x2f60, 0x080c, 0xb16c, 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, - 0x001e, 0x00ae, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, - 0x9084, 0x4000, 0x0110, 0x080c, 0x2aa9, 0x00de, 0x00c6, 0x2061, - 0x19e8, 0x6034, 0x080c, 0xd645, 0x0120, 0x909a, 0x0003, 0x1258, - 0x0018, 0x909a, 0x00c8, 0x1238, 0x8000, 0x6036, 0x00ce, 0x080c, - 0xa278, 0x0804, 0x2588, 0x2061, 0x0100, 0x62c0, 0x080c, 0xac2d, - 0x2019, 0x19f4, 0x2304, 0x9065, 0x0130, 0x6003, 0x0001, 0x2009, - 0x0027, 0x080c, 0xb20a, 0x00ce, 0x0804, 0x2588, 0xd2bc, 0x0904, - 0x256b, 0x080c, 0x8a58, 0x2011, 0x0004, 0x080c, 0x2ad3, 0x00d6, - 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2aa9, - 0x00de, 0x00c6, 0x2061, 0x19e8, 0x6050, 0x080c, 0xd645, 0x0120, - 0x909a, 0x0003, 0x1668, 0x0018, 0x909a, 0x00c8, 0x1648, 0x8000, - 0x6052, 0x604c, 0x00ce, 0x9005, 0x05d8, 0x2009, 0x07d0, 0x080c, - 0x8a50, 0x9080, 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x2009, - 0x1984, 0x2011, 0x0012, 0x080c, 0x2ae2, 0x0450, 0x9080, 0x0008, - 0x2004, 0x9086, 0x0009, 0x0d98, 0x2009, 0x1984, 0x2011, 0x0016, - 0x080c, 0x2ae2, 0x00e8, 0x2011, 0x0004, 0x080c, 0x2ad3, 0x00c0, - 0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x003e, 0x2019, 0x19fb, - 0x2304, 0x9065, 0x0160, 0x2009, 0x004f, 0x6020, 0x9086, 0x0009, - 0x1110, 0x2009, 0x004f, 0x6003, 0x0003, 0x080c, 0xb20a, 0x00ce, - 0x080c, 0xad18, 0x001e, 0xd19c, 0x0904, 0x25ef, 0x7038, 0xd0ac, - 0x1558, 0x0016, 0x0156, 0x2011, 0x0008, 0x080c, 0x2ad3, 0x080c, - 0x2af6, 0x080c, 0x2b29, 0x6050, 0xc0e5, 0x6052, 0x20a9, 0x0367, - 0x0f04, 0x25ba, 0x1d04, 0x25a2, 0x080c, 0x8a7f, 0x6020, 0xd09c, - 0x1db8, 0x00f6, 0x2079, 0x0100, 0x080c, 0x2a0c, 0x00fe, 0x1d80, - 0x6050, 0xc0e4, 0x6052, 0x2011, 0x0008, 0x080c, 0x2ad3, 0x015e, - 0x001e, 0x04a8, 0x015e, 0x001e, 0x0016, 0x6028, 0xc09c, 0x602a, - 0x080c, 0xacfc, 0x080c, 0xafd2, 0x080c, 0xb09b, 0x080c, 0xad18, - 0x60e3, 0x0000, 0x080c, 0xeed9, 0x080c, 0xeef4, 0x080c, 0x5844, - 0xd0fc, 0x1138, 0x080c, 0xd63e, 0x1120, 0x9085, 0x0001, 0x080c, - 0x77e2, 0x9006, 0x080c, 0x2a99, 0x2009, 0x0002, 0x080c, 0x2a85, - 0x00e6, 0x2071, 0x1800, 0x7003, 0x0004, 0x080c, 0x0ed3, 0x00ee, - 0x2011, 0x0008, 0x080c, 0x2ad3, 0x080c, 0x0bcf, 0x001e, 0x918c, - 0xffd0, 0x2110, 0x080c, 0x2ad3, 0x00ae, 0x0005, 0x0016, 0x2001, - 0x0387, 0x200c, 0xd1a4, 0x001e, 0x0904, 0x2390, 0x0016, 0x2009, - 0x2602, 0x00c0, 0x2001, 0x0387, 0x2003, 0x1000, 0x001e, 0x0c38, - 0x0016, 0x2001, 0x0387, 0x200c, 0xd1b4, 0x001e, 0x0904, 0x2390, - 0x0016, 0x2009, 0x2614, 0x0030, 0x2001, 0x0387, 0x2003, 0x4000, - 0x001e, 0x08a8, 0x6028, 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, - 0xbc91, 0x8000, 0x2003, 0xffff, 0x6043, 0x0001, 0x080c, 0x2a7f, - 0x2011, 0x0080, 0x080c, 0x2ad3, 0x6017, 0x0000, 0x6043, 0x0000, - 0x0817, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126, - 0x2091, 0x8000, 0x2071, 0x1800, 0x71d0, 0x70d2, 0x9116, 0x0904, - 0x2684, 0x81ff, 0x01a0, 0x2009, 0x0000, 0x080c, 0x2a85, 0x2011, - 0x8011, 0x2019, 0x010e, 0x231c, 0x939e, 0x0007, 0x1118, 0x2019, - 0x0001, 0x0010, 0x2019, 0x0000, 0x080c, 0x4ca1, 0x0468, 0x2001, - 0x19a9, 0x200c, 0x81ff, 0x1140, 0x2001, 0x0109, 0x2004, 0xd0b4, - 0x0118, 0x2019, 0x0003, 0x0008, 0x2118, 0x2011, 0x8012, 0x080c, - 0x4ca1, 0x080c, 0x0ed3, 0x080c, 0x5844, 0xd0fc, 0x11a8, 0x080c, - 0xd63e, 0x1190, 0x00c6, 0x080c, 0x2720, 0x080c, 0xacfc, 0x080c, - 0xa4f1, 0x080c, 0xad18, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, - 0x0002, 0x080c, 0x32da, 0x00ce, 0x012e, 0x00fe, 0x00ee, 0x003e, - 0x002e, 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, 0x2130, - 0x9094, 0xff00, 0x11f0, 0x2011, 0x1837, 0x2214, 0xd2ac, 0x11c8, - 0x81ff, 0x01e8, 0x2011, 0x181f, 0x2204, 0x9106, 0x1190, 0x2011, - 0x1820, 0x2214, 0x9294, 0xff00, 0x9584, 0xff00, 0x9206, 0x1148, - 0x2011, 0x1820, 0x2214, 0x9294, 0x00ff, 0x9584, 0x00ff, 0x9206, - 0x1120, 0x2500, 0x080c, 0x8521, 0x0048, 0x9584, 0x00ff, 0x9080, - 0x348e, 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, - 0x348e, 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, - 0x2001, 0x1818, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, - 0x6856, 0x1f04, 0x26d0, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, - 0x2069, 0x0140, 0x2001, 0x1818, 0x2102, 0x8114, 0x8214, 0x8214, - 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, - 0x9184, 0x000f, 0x9080, 0xef08, 0x2005, 0x6856, 0x8211, 0x1f04, - 0x26e5, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x1800, - 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, - 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, - 0x9116, 0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, - 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x2715, - 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, - 0x080c, 0x5840, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, - 0x2020, 0x2009, 0x002e, 0x080c, 0xea8d, 0x004e, 0x0005, 0x00f6, - 0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x278c, - 0x080c, 0x29fc, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, 0x1120, - 0x2011, 0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, 0x2011, - 0x8000, 0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, 0x2009, - 0x0001, 0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, 0x0002, - 0x00b0, 0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, 0x0078, - 0x908e, 0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, 0x9084, - 0x0700, 0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, 0x2300, - 0x9080, 0x0020, 0x2018, 0x080c, 0x955b, 0x928c, 0xff00, 0x0110, - 0x2011, 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, - 0x0138, 0x220a, 0x080c, 0x779e, 0x1118, 0x2009, 0x196d, 0x220a, - 0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, - 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, - 0x8000, 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0d7e, 0x002e, - 0x001e, 0x000e, 0x012e, 0x0005, 0x2001, 0x180d, 0x2004, 0xd08c, - 0x0118, 0x2009, 0x0002, 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc, - 0x0168, 0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c, - 0x1128, 0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, 0x2001, - 0x0227, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001, - 0x0226, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005, - 0x0018, 0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, 0x1800, - 0x0156, 0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x1990, 0x2004, - 0x908a, 0x0007, 0x1a0c, 0x0d85, 0x0033, 0x00ee, 0x002e, 0x001e, - 0x000e, 0x015e, 0x0005, 0x27f2, 0x2810, 0x2834, 0x2836, 0x285f, - 0x2861, 0x2863, 0x2001, 0x0001, 0x080c, 0x2631, 0x080c, 0x2a4a, - 0x2001, 0x1992, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, - 0x9006, 0x20a9, 0x0009, 0x080c, 0x2a18, 0x2001, 0x1990, 0x2003, - 0x0006, 0x2009, 0x001e, 0x2011, 0x2864, 0x080c, 0x8a5d, 0x0005, - 0x2009, 0x1995, 0x200b, 0x0000, 0x2001, 0x199a, 0x2003, 0x0036, - 0x2001, 0x1999, 0x2003, 0x002a, 0x2001, 0x1992, 0x2003, 0x0001, - 0x9006, 0x080c, 0x29ad, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, - 0x2a18, 0x2001, 0x1990, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, - 0x2864, 0x080c, 0x8a5d, 0x0005, 0x080c, 0x0d85, 0x2001, 0x199a, - 0x2003, 0x0036, 0x2001, 0x1992, 0x2003, 0x0003, 0x7a38, 0x9294, - 0x0005, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, - 0x080c, 0x29ad, 0x2001, 0x1996, 0x2003, 0x0000, 0x2001, 0xffff, - 0x20a9, 0x0009, 0x080c, 0x2a18, 0x2001, 0x1990, 0x2003, 0x0006, - 0x2009, 0x001e, 0x2011, 0x2864, 0x080c, 0x8a5d, 0x0005, 0x080c, - 0x0d85, 0x080c, 0x0d85, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, - 0x00f6, 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, - 0x1992, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0d85, 0x0043, 0x012e, - 0x015e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x2886, - 0x28a2, 0x28de, 0x290a, 0x292a, 0x2936, 0x2938, 0x080c, 0x2a0c, - 0x1190, 0x2009, 0x1998, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, - 0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x1990, - 0x2003, 0x0001, 0x0030, 0x080c, 0x295c, 0x2001, 0xffff, 0x080c, - 0x2801, 0x0005, 0x080c, 0x293a, 0x05c0, 0x2009, 0x1999, 0x2104, - 0x8001, 0x200a, 0x080c, 0x2a0c, 0x1158, 0x7a38, 0x9294, 0x0005, - 0x9296, 0x0005, 0x0518, 0x2009, 0x1998, 0x2104, 0xc085, 0x200a, - 0x2009, 0x1995, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, - 0x080c, 0x2942, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, - 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, - 0x29ca, 0x2001, 0x1992, 0x2003, 0x0002, 0x0028, 0x2001, 0x1990, - 0x2003, 0x0003, 0x0010, 0x080c, 0x2823, 0x0005, 0x080c, 0x293a, - 0x0540, 0x2009, 0x1999, 0x2104, 0x8001, 0x200a, 0x080c, 0x2a0c, - 0x1148, 0x2001, 0x1990, 0x2003, 0x0003, 0x2001, 0x1991, 0x2003, - 0x0000, 0x00b8, 0x2009, 0x1999, 0x2104, 0x9005, 0x1118, 0x080c, - 0x297f, 0x0010, 0x080c, 0x294f, 0x080c, 0x2942, 0x2009, 0x1995, - 0x200b, 0x0000, 0x2001, 0x1992, 0x2003, 0x0001, 0x080c, 0x2823, - 0x0000, 0x0005, 0x0479, 0x01e8, 0x080c, 0x2a0c, 0x1198, 0x2009, - 0x1996, 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, - 0x2001, 0x199b, 0x2003, 0x000a, 0x2009, 0x1998, 0x2104, 0xc0fd, - 0x200a, 0x0038, 0x00f9, 0x2001, 0x1992, 0x2003, 0x0004, 0x080c, - 0x284e, 0x0005, 0x0079, 0x0148, 0x080c, 0x2a0c, 0x1118, 0x080c, - 0x283a, 0x0018, 0x0079, 0x080c, 0x284e, 0x0005, 0x080c, 0x0d85, - 0x080c, 0x0d85, 0x2009, 0x199a, 0x2104, 0x8001, 0x200a, 0x090c, - 0x299b, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, - 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29ca, 0x0005, 0x7a38, - 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x080c, 0x29ad, 0x0005, 0x2009, 0x1995, 0x2104, 0x8000, - 0x200a, 0x9086, 0x0005, 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38, - 0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, - 0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, - 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29ca, 0x0005, 0x0086, - 0x2001, 0x1998, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0d85, 0x2009, - 0x1997, 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, - 0xd084, 0x1120, 0x080c, 0x0d85, 0x9006, 0x0010, 0x2001, 0x0001, - 0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x1990, 0x20a9, - 0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, 0x29a1, 0x2001, 0x1997, - 0x2003, 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, - 0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, - 0x783a, 0x2009, 0x199d, 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, - 0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, 0x199e, 0x210c, 0x795a, - 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158, - 0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x7850, 0x9084, - 0xfff0, 0x7852, 0x00f8, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005, - 0x783a, 0x7850, 0x9084, 0xfff0, 0x0016, 0x2009, 0x017f, 0x210c, - 0x918e, 0x0005, 0x0140, 0x2009, 0x0003, 0x210c, 0x918c, 0x0600, - 0x918e, 0x0400, 0x0118, 0x9085, 0x000a, 0x0010, 0x9085, 0x0000, - 0x001e, 0x7852, 0x00fe, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, - 0x9082, 0x0007, 0x000e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004, - 0x9082, 0x0009, 0x000e, 0x0005, 0x0156, 0x20a9, 0x0064, 0x7820, - 0x080c, 0x2a7f, 0xd09c, 0x1110, 0x1f04, 0x2a0f, 0x015e, 0x0005, - 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, 0x000e, 0x2008, 0x9186, - 0x0000, 0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, - 0x783b, 0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, - 0x0030, 0x9186, 0x0003, 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, - 0x1d04, 0x2a38, 0x080c, 0x8a7f, 0x1f04, 0x2a38, 0x080c, 0x2af6, - 0x080c, 0x2b29, 0x7850, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e, - 0x012e, 0x0005, 0x080c, 0x2b29, 0x0005, 0x0006, 0x0156, 0x00f6, - 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, 0x1100, 0x7854, - 0xd08c, 0x1110, 0x1f04, 0x2a57, 0x00fe, 0x015e, 0x000e, 0x0005, - 0x1d04, 0x2a60, 0x080c, 0x8a7f, 0x1f04, 0x2a60, 0x0005, 0x0006, - 0x2001, 0x199c, 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, - 0x2001, 0x199c, 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, 0x0006, - 0x2001, 0x199c, 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, 0xa001, - 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006, 0x2001, 0x19a9, - 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, - 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xa001, 0xa001, 0x200a, - 0x0005, 0x0016, 0x0026, 0x080c, 0x77b8, 0x0108, 0xc0bc, 0x2009, - 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e, - 0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, - 0x9285, 0x1000, 0x200a, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016, - 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, - 0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104, - 0x1128, 0x080c, 0x77b8, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a, - 0x001e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0380, 0x7843, 0x0101, - 0x7844, 0xd084, 0x1de8, 0x2001, 0x0109, 0x2202, 0x7843, 0x0100, - 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0380, 0x7843, 0x0202, 0x7844, - 0xd08c, 0x1de8, 0x2079, 0x0100, 0x7814, 0x9104, 0x9205, 0x7a16, - 0x2079, 0x0380, 0x7843, 0x0200, 0x00fe, 0x0005, 0x0016, 0x0026, - 0x0036, 0x00c6, 0x2061, 0x0100, 0x6050, 0x9084, 0xfbff, 0x9085, - 0x0040, 0x6052, 0x20a9, 0x0002, 0x080c, 0x2a60, 0x6050, 0x9085, - 0x0400, 0x9084, 0xff9f, 0x6052, 0x20a9, 0x0005, 0x080c, 0x2a60, - 0x6054, 0xd0bc, 0x090c, 0x0d85, 0x20a9, 0x0005, 0x080c, 0x2a60, - 0x6054, 0xd0ac, 0x090c, 0x0d85, 0x2009, 0x19b0, 0x9084, 0x7e00, - 0x8007, 0x8004, 0x8004, 0x200a, 0x00ce, 0x003e, 0x002e, 0x001e, - 0x0005, 0x0006, 0x00c6, 0x2061, 0x0100, 0x6050, 0xc0cd, 0x6052, - 0x00ce, 0x000e, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x0006, 0x2061, - 0x0100, 0x2069, 0x0140, 0x6030, 0x0006, 0x6048, 0x0006, 0x60e4, - 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, - 0x0006, 0x6004, 0x0006, 0xc0fc, 0x6006, 0x2009, 0x0800, 0x2001, - 0x0338, 0x2003, 0x0301, 0x8109, 0x090c, 0x0d85, 0x2001, 0x0338, - 0x2004, 0xd084, 0x1dc0, 0x6028, 0x0006, 0x60e0, 0x0006, 0x6888, - 0x0006, 0x688c, 0x0006, 0x6890, 0x0006, 0x080c, 0x779e, 0x1110, - 0x6884, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xa001, 0xa001, - 0xa001, 0xa001, 0x602f, 0x0040, 0x602f, 0x0000, 0x080c, 0x779e, - 0x1120, 0x6803, 0x0080, 0x000e, 0x6886, 0x6897, 0x4198, 0x000e, - 0x6892, 0x000e, 0x688e, 0x000e, 0x688a, 0x000e, 0x60e2, 0x000e, - 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, - 0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, 0x000e, 0x604a, 0x000e, - 0x6032, 0x6036, 0x2008, 0x080c, 0x26d5, 0x000e, 0x00de, 0x00ce, - 0x001e, 0x0005, 0x0006, 0x0156, 0x6050, 0x9085, 0x0040, 0x6052, - 0x6050, 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2a7f, 0x9085, 0x2000, - 0x6052, 0x20a9, 0x0012, 0x1d04, 0x2bb3, 0x080c, 0x8a7f, 0x1f04, - 0x2bb3, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, 0x015e, - 0x000e, 0x0005, 0x30be, 0x30be, 0x2cc2, 0x2cc2, 0x2cce, 0x2cce, - 0x2cda, 0x2cda, 0x2ce8, 0x2ce8, 0x2cf4, 0x2cf4, 0x2d02, 0x2d02, - 0x2d10, 0x2d10, 0x2d22, 0x2d22, 0x2d2e, 0x2d2e, 0x2d3c, 0x2d3c, - 0x2d5a, 0x2d5a, 0x2d7a, 0x2d7a, 0x2d4a, 0x2d4a, 0x2d6a, 0x2d6a, - 0x2d88, 0x2d88, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d9a, 0x2d9a, 0x2da6, 0x2da6, 0x2db4, 0x2db4, - 0x2dc2, 0x2dc2, 0x2dd2, 0x2dd2, 0x2de0, 0x2de0, 0x2df0, 0x2df0, - 0x2e00, 0x2e00, 0x2e12, 0x2e12, 0x2e20, 0x2e20, 0x2e30, 0x2e30, - 0x2e52, 0x2e52, 0x2e76, 0x2e76, 0x2e40, 0x2e40, 0x2e64, 0x2e64, - 0x2e86, 0x2e86, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2e9a, 0x2e9a, 0x2ea6, 0x2ea6, 0x2eb4, 0x2eb4, - 0x2ec2, 0x2ec2, 0x2ed2, 0x2ed2, 0x2ee0, 0x2ee0, 0x2ef0, 0x2ef0, - 0x2f00, 0x2f00, 0x2f12, 0x2f12, 0x2f20, 0x2f20, 0x2f30, 0x2f30, - 0x2f40, 0x2f40, 0x2f52, 0x2f52, 0x2f62, 0x2f62, 0x2f74, 0x2f74, - 0x2f86, 0x2f86, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2f9a, 0x2f9a, 0x2fa8, 0x2fa8, 0x2fb8, 0x2fb8, - 0x2fc8, 0x2fc8, 0x2fda, 0x2fda, 0x2fea, 0x2fea, 0x2ffc, 0x2ffc, - 0x300e, 0x300e, 0x3022, 0x3022, 0x3032, 0x3032, 0x3044, 0x3044, - 0x3056, 0x3056, 0x306a, 0x306a, 0x307b, 0x307b, 0x308e, 0x308e, - 0x30a1, 0x30a1, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, - 0x2d20, 0x2d20, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x22c8, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x22c8, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22c8, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x2114, 0x0804, 0x30b6, - 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22c8, - 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x13d4, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x13d4, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x22c8, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x22c8, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x22c8, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x22c8, - 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, - 0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0xad62, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0xad62, - 0x080c, 0x22c8, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0xad62, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x2114, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x13d4, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, - 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0xad62, - 0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, - 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x22c8, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0xad62, 0x0804, 0x30b6, - 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, - 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x22c8, - 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, - 0x080c, 0xad62, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x2114, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x13d4, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x22c8, - 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, - 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, - 0x080c, 0xad62, 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, - 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, - 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x13d4, - 0x080c, 0x2114, 0x04d8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, - 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, - 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, 0x0440, 0x0106, 0x0006, - 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, - 0x080c, 0x20ea, 0x080c, 0x13d4, 0x080c, 0xad62, 0x080c, 0x2114, - 0x00a8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, - 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, - 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, 0x0000, 0x015e, 0x014e, - 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, 0x00b6, - 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6bcf, 0x1904, 0x31f6, - 0x72dc, 0x2001, 0x197c, 0x2004, 0x9005, 0x1110, 0xd29c, 0x0148, - 0xd284, 0x1138, 0xd2bc, 0x1904, 0x31f6, 0x080c, 0x31fb, 0x0804, - 0x31f6, 0xd2cc, 0x1904, 0x31f6, 0x080c, 0x779e, 0x1120, 0x70af, - 0xffff, 0x0804, 0x31f6, 0xd294, 0x0120, 0x70af, 0xffff, 0x0804, - 0x31f6, 0x080c, 0x347d, 0x0160, 0x080c, 0xd645, 0x0128, 0x2001, - 0x1818, 0x203c, 0x0804, 0x316f, 0x70af, 0xffff, 0x0804, 0x31f6, - 0x2001, 0x1818, 0x203c, 0x7294, 0xd284, 0x0904, 0x316f, 0xd28c, - 0x1904, 0x316f, 0x0036, 0x73ac, 0x938e, 0xffff, 0x1110, 0x2019, - 0x0001, 0x8314, 0x92e0, 0x1d80, 0x2c04, 0x938c, 0x0001, 0x0120, - 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, 0x0904, - 0x3165, 0x908e, 0x0000, 0x0904, 0x3165, 0x908e, 0x00ff, 0x1160, - 0x7230, 0xd284, 0x1904, 0x316a, 0x7294, 0xc28d, 0x7296, 0x70af, - 0xffff, 0x003e, 0x0804, 0x316f, 0x2009, 0x180d, 0x210c, 0xd18c, - 0x0150, 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e, 0x0118, - 0x70af, 0xffff, 0x0488, 0x900e, 0x080c, 0x268c, 0x080c, 0x6749, - 0x1538, 0x9006, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, - 0x2060, 0x080c, 0x8eee, 0x00ce, 0x090c, 0x928d, 0xb8af, 0x0000, - 0x080c, 0x6c11, 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, 0xd0bc, - 0x0138, 0x080c, 0x6aae, 0x0120, 0x080c, 0x3214, 0x0148, 0x0028, - 0x080c, 0x3360, 0x080c, 0x3240, 0x0118, 0x8318, 0x0804, 0x3109, - 0x73ae, 0x0010, 0x70af, 0xffff, 0x003e, 0x0804, 0x31f6, 0x9780, - 0x348e, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x70ac, - 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, 0x0220, - 0x2008, 0x9802, 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804, 0x31f6, - 0x2700, 0x0156, 0x0016, 0x9106, 0x0904, 0x31eb, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x0158, 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, - 0x002e, 0x0120, 0x2009, 0xffff, 0x0804, 0x31f3, 0xc484, 0x080c, - 0x67b4, 0x0168, 0x080c, 0xd645, 0x1904, 0x31eb, 0x080c, 0x347d, - 0x1904, 0x31eb, 0x080c, 0x6749, 0x1904, 0x31f3, 0x0008, 0xc485, - 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c, - 0x8eee, 0x00ce, 0x090c, 0x928d, 0xb8af, 0x0000, 0x080c, 0x6c11, - 0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0, 0x7294, - 0xd28c, 0x0180, 0x080c, 0x6c11, 0x9082, 0x0006, 0x02e0, 0xd484, - 0x1118, 0x080c, 0x676e, 0x0028, 0x080c, 0x33f3, 0x01a0, 0x080c, - 0x341e, 0x0088, 0x080c, 0x3360, 0x080c, 0xd645, 0x1160, 0x080c, - 0x3240, 0x0188, 0x0040, 0x080c, 0xd645, 0x1118, 0x080c, 0x33f3, - 0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x3188, - 0x70af, 0xffff, 0x0018, 0x001e, 0x015e, 0x71ae, 0x004e, 0x002e, - 0x00ce, 0x00be, 0x0005, 0x00c6, 0x0016, 0x70af, 0x0001, 0x2009, - 0x007e, 0x080c, 0x6749, 0x1168, 0xb813, 0x00ff, 0xb817, 0xfffe, - 0x080c, 0x3360, 0x04a9, 0x0128, 0x70dc, 0xc0bd, 0x70de, 0x080c, - 0xd389, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, - 0x2001, 0x184c, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, 0xb1dd, - 0x01d0, 0x2b00, 0x6012, 0x080c, 0xd3b6, 0x6023, 0x0001, 0x9006, - 0x080c, 0x66e6, 0x2001, 0x0000, 0x080c, 0x66fa, 0x0126, 0x2091, - 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, 0x0004, 0x080c, - 0xb20a, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, - 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, 0x2004, 0x9084, - 0x00ff, 0xb842, 0x080c, 0xb1dd, 0x0548, 0x2b00, 0x6012, 0xb800, - 0xc0c4, 0xb802, 0xb8a0, 0x9086, 0x007e, 0x0140, 0xb804, 0x9084, - 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x3315, 0x080c, 0xd3b6, - 0x6023, 0x0001, 0x9006, 0x080c, 0x66e6, 0x2001, 0x0002, 0x080c, - 0x66fa, 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, - 0x2009, 0x0002, 0x080c, 0xb20a, 0x9085, 0x0001, 0x00ce, 0x00de, - 0x007e, 0x001e, 0x0005, 0x00b6, 0x00c6, 0x0026, 0x2009, 0x0080, - 0x080c, 0x6749, 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, 0x0039, - 0x0110, 0x70e3, 0xffff, 0x002e, 0x00ce, 0x00be, 0x0005, 0x0016, - 0x0076, 0x00d6, 0x00c6, 0x080c, 0xb116, 0x01d0, 0x2b00, 0x6012, - 0x080c, 0xd3b6, 0x6023, 0x0001, 0x9006, 0x080c, 0x66e6, 0x2001, - 0x0002, 0x080c, 0x66fa, 0x0126, 0x2091, 0x8000, 0x70e4, 0x8000, - 0x70e6, 0x012e, 0x2009, 0x0002, 0x080c, 0xb20a, 0x9085, 0x0001, - 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, - 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x6749, 0x11b8, 0xb813, - 0x00ff, 0xb817, 0xfffd, 0xb8d7, 0x0004, 0x080c, 0xb116, 0x0170, - 0x2b00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, 0xd3b6, - 0x2009, 0x0022, 0x080c, 0xb20a, 0x9085, 0x0001, 0x012e, 0x00de, - 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x00b6, - 0x21f0, 0x080c, 0xacfc, 0x0106, 0x080c, 0x97bb, 0x080c, 0x9727, - 0x080c, 0xac4d, 0x080c, 0xc179, 0x010e, 0x090c, 0xad18, 0x3e08, - 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, 0x20a9, - 0x007f, 0x900e, 0x0016, 0x080c, 0x67b4, 0x1140, 0x9686, 0x0002, - 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x61b7, 0x001e, 0x8108, - 0x1f04, 0x32fa, 0x9686, 0x0001, 0x190c, 0x3451, 0x00be, 0x002e, - 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0046, - 0x0036, 0x0026, 0x0016, 0x00b6, 0x080c, 0xacfc, 0x0106, 0x6210, - 0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0x97b0, 0x0076, - 0x2039, 0x0000, 0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d, 0x007e, - 0x001e, 0x010e, 0x090c, 0xad18, 0xba10, 0xbb14, 0xbc84, 0x080c, - 0x61b7, 0xba12, 0xbb16, 0xbc86, 0x00be, 0x001e, 0x002e, 0x003e, - 0x004e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x00b6, 0x6010, - 0x2058, 0xb8a0, 0x00be, 0x9086, 0x0080, 0x0150, 0x2071, 0x1800, - 0x70a8, 0x9005, 0x0110, 0x8001, 0x70aa, 0x000e, 0x00ee, 0x0005, - 0x2071, 0x1800, 0x70e4, 0x9005, 0x0dc0, 0x8001, 0x70e6, 0x0ca8, - 0xb800, 0xc08c, 0xb802, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x00b6, - 0x0046, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x080c, 0xacfc, - 0x0106, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0078, 0x080c, 0x5840, - 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2020, 0x2009, 0x002d, - 0x080c, 0xea8d, 0x20a9, 0x0800, 0x9016, 0x0026, 0x928e, 0x007e, - 0x0904, 0x33cf, 0x928e, 0x007f, 0x0904, 0x33cf, 0x928e, 0x0080, - 0x05f0, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05c8, 0x8fff, 0x1150, - 0x2001, 0x198e, 0x0006, 0x2003, 0x0001, 0x080c, 0x33e0, 0x000e, - 0x2003, 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, 0x0001, 0x080c, - 0x6bdb, 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, 0x97b0, 0x0076, - 0x2039, 0x0000, 0x080c, 0x966d, 0x00b6, 0x00c6, 0x0026, 0x2158, - 0xba04, 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, 0xb807, 0x0404, - 0x0028, 0x2001, 0x0004, 0x8007, 0x9215, 0xba06, 0x002e, 0x00ce, - 0x00be, 0x0016, 0x2c08, 0x080c, 0xe75d, 0x001e, 0x007e, 0x002e, - 0x8210, 0x1f04, 0x3385, 0x010e, 0x090c, 0xad18, 0x015e, 0x001e, - 0x002e, 0x003e, 0x004e, 0x00be, 0x00ce, 0x00ee, 0x00fe, 0x0005, - 0x0046, 0x0026, 0x0016, 0x080c, 0x5840, 0xd0c4, 0x0140, 0xd0a4, - 0x0130, 0x9006, 0x2220, 0x2009, 0x0029, 0x080c, 0xea8d, 0x001e, - 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x7294, - 0x82ff, 0x01e8, 0x080c, 0x6c09, 0x11d0, 0x2100, 0x080c, 0x26bf, - 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1d80, 0x2c04, - 0xd384, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, - 0x9116, 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0x9085, - 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0xacfc, 0x0106, 0x0036, 0x2019, - 0x0029, 0x00c1, 0x003e, 0x010e, 0x090c, 0xad18, 0x9180, 0x1000, - 0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, 0x2061, 0x1b39, 0x001e, - 0x6112, 0x080c, 0x3315, 0x001e, 0x080c, 0x676e, 0x012e, 0x00ce, - 0x001e, 0x0005, 0x0016, 0x0026, 0x2110, 0x080c, 0xa7e2, 0x080c, - 0xedee, 0x002e, 0x001e, 0x0005, 0x2001, 0x1837, 0x2004, 0xd0cc, - 0x0005, 0x00c6, 0x00b6, 0x080c, 0x779e, 0x1118, 0x20a9, 0x0800, - 0x0010, 0x20a9, 0x0782, 0x080c, 0x779e, 0x1110, 0x900e, 0x0010, - 0x2009, 0x007e, 0x9180, 0x1000, 0x2004, 0x905d, 0x0130, 0x86ff, - 0x0110, 0xb800, 0xd0bc, 0x090c, 0x676e, 0x8108, 0x1f04, 0x3462, - 0x2061, 0x1800, 0x607f, 0x0000, 0x6080, 0x9084, 0x00ff, 0x6082, - 0x60b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x2001, 0x1869, 0x2004, - 0xd0bc, 0x0005, 0x2011, 0x1848, 0x2214, 0xd2ec, 0x0005, 0x0026, - 0x2011, 0x1867, 0x2214, 0xd2dc, 0x002e, 0x0005, 0x7eef, 0x7de8, - 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6, - 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc, - 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc, - 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1, - 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6, - 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797, - 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c, - 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071, - 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66, - 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454, - 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a, - 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039, - 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d, - 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123, - 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f, - 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700, - 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000, - 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000, - 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700, - 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100, - 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00, - 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400, - 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00, - 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800, - 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400, - 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, - 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0x189e, - 0x7003, 0x0002, 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, 0x700e, - 0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, 0x7007, 0x0001, - 0x080c, 0x1072, 0x090c, 0x0d85, 0x2900, 0x706a, 0xa867, 0x0002, - 0xa8ab, 0xdcb0, 0x080c, 0x1072, 0x090c, 0x0d85, 0x2900, 0x706e, - 0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x189e, 0x7004, - 0x0002, 0x35bd, 0x35be, 0x35d1, 0x35e5, 0x0005, 0x1004, 0x35ce, - 0x0e04, 0x35ce, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, 0x700c, - 0x9005, 0x1128, 0x700f, 0x0001, 0x012e, 0x0468, 0x0005, 0x012e, - 0x0ce8, 0x2079, 0x0000, 0x2061, 0x18b8, 0x2c4c, 0xa86c, 0x908e, - 0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x36b9, 0x0005, 0x7018, - 0x2048, 0x2061, 0x1800, 0x701c, 0x0807, 0x7014, 0x2048, 0xa864, - 0x9094, 0x00ff, 0x9296, 0x0029, 0x1120, 0xaa78, 0xd2fc, 0x0128, - 0x0005, 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, 0x2061, - 0x1800, 0x701c, 0x0807, 0x2061, 0x1800, 0x7880, 0x908a, 0x0040, - 0x1210, 0x61d0, 0x0042, 0x2100, 0x908a, 0x003f, 0x1a04, 0x36b6, - 0x61d0, 0x0804, 0x364b, 0x368d, 0x36c5, 0x36b6, 0x36d1, 0x36db, - 0x36e1, 0x36e5, 0x36f5, 0x36f9, 0x370f, 0x3715, 0x371b, 0x3726, - 0x3731, 0x3740, 0x374f, 0x375d, 0x3774, 0x378f, 0x36b6, 0x383a, - 0x3878, 0x391d, 0x392e, 0x3951, 0x36b6, 0x36b6, 0x36b6, 0x3989, - 0x39a9, 0x39b2, 0x39de, 0x39e4, 0x36b6, 0x3a2a, 0x36b6, 0x36b6, - 0x36b6, 0x36b6, 0x36b6, 0x3a35, 0x3a3e, 0x3a46, 0x3a48, 0x36b6, - 0x36b6, 0x36b6, 0x36b6, 0x36b6, 0x36b6, 0x3a78, 0x36b6, 0x36b6, - 0x36b6, 0x36b6, 0x36b6, 0x3a95, 0x3b19, 0x36b6, 0x36b6, 0x36b6, - 0x36b6, 0x36b6, 0x36b6, 0x0002, 0x3b43, 0x3b46, 0x3ba5, 0x3bbe, - 0x3bee, 0x3e94, 0x36b6, 0x53f5, 0x36b6, 0x36b6, 0x36b6, 0x36b6, - 0x36b6, 0x36b6, 0x36b6, 0x36b6, 0x370f, 0x3715, 0x4397, 0x5864, - 0x43b5, 0x5484, 0x54d6, 0x55e1, 0x36b6, 0x5643, 0x567f, 0x56b0, - 0x57c0, 0x56dd, 0x5740, 0x36b6, 0x43b9, 0x457f, 0x4595, 0x45ba, - 0x461f, 0x4693, 0x46b3, 0x472a, 0x4786, 0x47e2, 0x47e5, 0x480a, - 0x487c, 0x48e6, 0x48ee, 0x4a23, 0x4bcb, 0x4bff, 0x4e63, 0x36b6, - 0x4e81, 0x4f48, 0x5031, 0x508b, 0x36b6, 0x511e, 0x36b6, 0x5134, - 0x514f, 0x48ee, 0x5395, 0x714c, 0x0000, 0x2021, 0x4000, 0x080c, - 0x4c7d, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3697, 0x0010, 0x012e, - 0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, - 0x7833, 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x7007, 0x0001, - 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, 0x4001, - 0x08b0, 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, 0x2021, - 0x4005, 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, 0x902e, - 0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x81ff, 0x0d98, 0x0804, - 0x4c8a, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884, - 0x7990, 0x0804, 0x4c8d, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804, - 0x368d, 0x7984, 0x2114, 0x0804, 0x368d, 0x20e1, 0x0000, 0x2099, - 0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003, - 0x7984, 0x7a88, 0x7b8c, 0x0804, 0x368d, 0x7884, 0x2060, 0x0804, - 0x3742, 0x2009, 0x0003, 0x2011, 0x0003, 0x2019, 0x0014, 0x789b, - 0x0137, 0x7893, 0xffff, 0x2001, 0x188f, 0x2004, 0x9005, 0x0118, - 0x7896, 0x0804, 0x368d, 0x7897, 0x0001, 0x0804, 0x368d, 0x2039, - 0x0001, 0x7d98, 0x7c9c, 0x0804, 0x36c9, 0x2039, 0x0001, 0x7d98, - 0x7c9c, 0x0804, 0x36d5, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, - 0x36c2, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x36c9, 0x79a0, 0x9182, - 0x0040, 0x0210, 0x0804, 0x36c2, 0x2138, 0x7d98, 0x7c9c, 0x0804, - 0x36d5, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x36c2, 0x21e8, - 0x7984, 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x368d, - 0x2061, 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109, - 0x1dd8, 0x2010, 0x9005, 0x0904, 0x368d, 0x0804, 0x36bc, 0x79a0, - 0x9182, 0x0040, 0x0210, 0x0804, 0x36c2, 0x21e0, 0x20a9, 0x0001, - 0x7984, 0x2198, 0x4012, 0x0804, 0x368d, 0x2069, 0x1847, 0x7884, - 0x7990, 0x911a, 0x1a04, 0x36c2, 0x8019, 0x0904, 0x36c2, 0x684a, - 0x6942, 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e, - 0x080c, 0x7ae7, 0x0804, 0x368d, 0x2069, 0x1847, 0x7884, 0x7994, - 0x911a, 0x1a04, 0x36c2, 0x8019, 0x0904, 0x36c2, 0x684e, 0x6946, - 0x788c, 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126, - 0x2091, 0x8000, 0x080c, 0x6d66, 0x012e, 0x0804, 0x368d, 0x902e, - 0x2520, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x7984, - 0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a6, - 0x4101, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, - 0x2009, 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c8a, - 0x701f, 0x37b3, 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096, - 0x0011, 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138, - 0x9096, 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x36bf, 0x810f, - 0x918c, 0x00ff, 0x0904, 0x36bf, 0x7112, 0x7010, 0x8001, 0x0560, - 0x7012, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, - 0x2009, 0x0020, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598, - 0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000, - 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c8a, 0x701f, 0x37f1, - 0x0005, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096, - 0x000a, 0x1904, 0x36bf, 0x0888, 0x0126, 0x2091, 0x8000, 0x7014, - 0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, 0x00ff, 0x9096, - 0x0029, 0x1148, 0xc2fd, 0xaa7a, 0x080c, 0x630a, 0x0138, 0xa87a, - 0xa982, 0x012e, 0x0060, 0x080c, 0x663a, 0x1130, 0x7007, 0x0003, - 0x701f, 0x381f, 0x012e, 0x0005, 0x080c, 0x725e, 0x012e, 0x0126, - 0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x18a6, - 0x400a, 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, - 0x0000, 0xa85c, 0x9080, 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60, - 0x0804, 0x4c8d, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010, - 0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020, - 0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100, - 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0x9205, 0x789a, 0x2009, - 0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a25, 0x2004, 0x9005, - 0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, - 0x2003, 0x0002, 0x2003, 0x1001, 0x2071, 0x0080, 0x0804, 0x0427, - 0x81ff, 0x1904, 0x36bf, 0x7984, 0x080c, 0x67b4, 0x1904, 0x36c2, - 0x7e98, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x36c2, 0x7c88, - 0x7d8c, 0x080c, 0x69f1, 0x080c, 0x697e, 0x1518, 0x2061, 0x1ddc, - 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, - 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0150, - 0x012e, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a04, - 0x36bf, 0x0c30, 0x080c, 0xcae9, 0x012e, 0x0904, 0x36bf, 0x0804, - 0x368d, 0x900e, 0x2001, 0x0005, 0x080c, 0x725e, 0x0126, 0x2091, - 0x8000, 0x080c, 0xd226, 0x080c, 0x7012, 0x012e, 0x0804, 0x368d, - 0x00a6, 0x2950, 0xb198, 0x080c, 0x67b4, 0x1904, 0x390a, 0xb6a4, - 0x9684, 0x3fff, 0x9082, 0x4000, 0x16e8, 0xb49c, 0xb5a0, 0x080c, - 0x69f1, 0x080c, 0x697e, 0x1520, 0x2061, 0x1ddc, 0x0126, 0x2091, - 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, 0x0130, - 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0158, 0x012e, 0x9ce0, - 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x2009, 0x000d, 0x12b0, - 0x0c28, 0x080c, 0xcae9, 0x012e, 0x2009, 0x0003, 0x0178, 0x00e0, - 0x900e, 0x2001, 0x0005, 0x080c, 0x725e, 0x0126, 0x2091, 0x8000, - 0x080c, 0xd226, 0x080c, 0x7006, 0x012e, 0x0070, 0xb097, 0x4005, - 0xb19a, 0x0010, 0xb097, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0030, 0x2a48, 0x00ae, 0x0005, 0xb097, 0x4000, 0x9006, 0x918d, - 0x0001, 0x2008, 0x2a48, 0x00ae, 0x0005, 0x81ff, 0x1904, 0x36bf, - 0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c, 0x687b, 0x0904, 0x36bf, - 0x080c, 0x69f7, 0x0904, 0x36bf, 0x0804, 0x46aa, 0x81ff, 0x1904, - 0x36bf, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x080c, 0x6a85, 0x0904, - 0x36bf, 0x2019, 0x0005, 0x79a8, 0x080c, 0x6a12, 0x0904, 0x36bf, - 0x7888, 0x908a, 0x1000, 0x1a04, 0x36c2, 0x8003, 0x800b, 0x810b, - 0x9108, 0x080c, 0x89a1, 0x79a8, 0xd184, 0x1904, 0x368d, 0x0804, - 0x46aa, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, - 0x0450, 0x2029, 0x07ff, 0x645c, 0x2400, 0x9506, 0x01f8, 0x2508, - 0x080c, 0x67b4, 0x11d8, 0x080c, 0x6a85, 0x1128, 0x2009, 0x0002, - 0x62c0, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, 0x6a12, - 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, 0x1270, - 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x89a1, 0x8529, 0x1ae0, - 0x012e, 0x0804, 0x368d, 0x012e, 0x0804, 0x36bf, 0x012e, 0x0804, - 0x36c2, 0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c, 0x687b, 0x0904, - 0x36bf, 0x080c, 0xacfc, 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066, - 0x080c, 0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x900e, 0x080c, - 0xe75d, 0x007e, 0x00ce, 0x080c, 0xad18, 0x080c, 0x69f1, 0x0804, - 0x368d, 0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c, 0x69f1, 0x2208, - 0x0804, 0x368d, 0x0156, 0x00d6, 0x00e6, 0x00c6, 0x2069, 0x1910, - 0x6810, 0x6914, 0x910a, 0x1208, 0x900e, 0x6816, 0x9016, 0x901e, - 0x2071, 0x19e8, 0x7028, 0x9065, 0x0118, 0x8210, 0x600c, 0x0cd8, - 0x2300, 0x9218, 0x00ce, 0x00ee, 0x00de, 0x015e, 0x0804, 0x368d, - 0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff, - 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0x1910, - 0x6910, 0x62bc, 0x0804, 0x368d, 0x81ff, 0x0120, 0x2009, 0x0001, - 0x0804, 0x36bf, 0x0126, 0x2091, 0x8000, 0x080c, 0x5854, 0x0128, - 0x2009, 0x0007, 0x012e, 0x0804, 0x36bf, 0x012e, 0x615c, 0x9190, - 0x348e, 0x2215, 0x9294, 0x00ff, 0x637c, 0x83ff, 0x0108, 0x6280, - 0x67dc, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001, - 0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003, - 0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002, - 0x0068, 0x080c, 0x779e, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c, - 0x0120, 0x2009, 0x0005, 0x0804, 0x36bf, 0x9036, 0x7e9a, 0x7f9e, - 0x0804, 0x368d, 0x614c, 0x6250, 0x2019, 0x1986, 0x231c, 0x2001, - 0x1987, 0x2004, 0x789a, 0x0804, 0x368d, 0x0126, 0x2091, 0x8000, - 0x6138, 0x623c, 0x6340, 0x012e, 0x0804, 0x368d, 0x080c, 0x4c74, - 0x0904, 0x36c2, 0xba44, 0xbb38, 0x0804, 0x368d, 0x080c, 0x0d85, - 0x080c, 0x4c74, 0x2110, 0x0904, 0x36c2, 0xb804, 0x908c, 0x00ff, - 0x918e, 0x0006, 0x0140, 0x9084, 0xff00, 0x9086, 0x0600, 0x2009, - 0x0009, 0x1904, 0x36bf, 0x0126, 0x2091, 0x8000, 0x2019, 0x0005, - 0x00c6, 0x9066, 0x080c, 0xacfc, 0x080c, 0xa7e2, 0x080c, 0x97b0, - 0x0076, 0x903e, 0x080c, 0x966d, 0x900e, 0x080c, 0xe75d, 0x007e, - 0x00ce, 0x080c, 0xad18, 0xb807, 0x0407, 0x012e, 0x0804, 0x368d, - 0x614c, 0x6250, 0x7884, 0x604e, 0x7b88, 0x6352, 0x2069, 0x1847, - 0x831f, 0x9305, 0x6816, 0x788c, 0x2069, 0x1986, 0x2d1c, 0x206a, - 0x7e98, 0x9682, 0x0014, 0x1210, 0x2031, 0x07d0, 0x2069, 0x1987, - 0x2d04, 0x266a, 0x789a, 0x0804, 0x368d, 0x0126, 0x2091, 0x8000, - 0x6138, 0x7884, 0x603a, 0x910e, 0xd1b4, 0x190c, 0x0eeb, 0xd0c4, - 0x01a8, 0x00d6, 0x78a8, 0x2009, 0x199d, 0x200a, 0x78ac, 0x2011, - 0x199e, 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, - 0x2214, 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7888, 0xd0ec, - 0x0178, 0x6034, 0xc08d, 0x6036, 0x2001, 0x0050, 0x6076, 0x607a, - 0x6056, 0x606b, 0x269c, 0x00c6, 0x2061, 0x1b73, 0x2062, 0x00ce, - 0x2011, 0x0116, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0040, - 0x0010, 0x918c, 0xff7f, 0x2112, 0x6134, 0xd18c, 0x2001, 0x0000, - 0x0108, 0x603c, 0x7988, 0x613e, 0x6140, 0x910d, 0x788c, 0x6042, - 0x6234, 0xd28c, 0x0120, 0x7a88, 0x9294, 0x1000, 0x9205, 0x910e, - 0xd1e4, 0x190c, 0x0f06, 0x9084, 0x0020, 0x0130, 0x78b4, 0x6046, - 0x9084, 0x0001, 0x090c, 0x4397, 0x6040, 0xd0cc, 0x0120, 0x78b0, - 0x2011, 0x0114, 0x2012, 0x012e, 0x0804, 0x368d, 0x00f6, 0x2079, - 0x1800, 0x7a38, 0xa898, 0x9084, 0xfebf, 0x9215, 0xa89c, 0x9084, - 0xfebf, 0x8002, 0x9214, 0x7838, 0x9084, 0x0140, 0x9215, 0x7a3a, - 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, - 0x0005, 0x7898, 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x36c2, - 0x788c, 0x902d, 0x0904, 0x36c2, 0x900e, 0x080c, 0x67b4, 0x1120, - 0xba44, 0xbb38, 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, 0x8108, - 0x0ca0, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x7888, 0x900d, 0x0904, - 0x36c2, 0x788c, 0x9005, 0x0904, 0x36c2, 0xba44, 0xb946, 0xbb38, - 0xb83a, 0x0804, 0x368d, 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, - 0x080c, 0x5854, 0x1904, 0x36bf, 0x00c6, 0x2061, 0x0100, 0x7984, - 0x9186, 0x00ff, 0x1130, 0x2001, 0x1818, 0x2004, 0x9085, 0xff00, - 0x0088, 0x9182, 0x007f, 0x16e0, 0x9188, 0x348e, 0x210d, 0x918c, - 0x00ff, 0x2001, 0x1818, 0x2004, 0x0026, 0x9116, 0x002e, 0x0580, - 0x810f, 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0xb116, - 0x000e, 0x0510, 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, 0x674f, - 0x2b08, 0x00be, 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, 0x4c41, - 0x01d0, 0x9006, 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, 0xc0fd, - 0xa86a, 0x701f, 0x3b9e, 0x2900, 0x6016, 0x2009, 0x0032, 0x080c, - 0xb20a, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x36bf, - 0x00ce, 0x0804, 0x36c2, 0x080c, 0xb16c, 0x0cb0, 0xa830, 0x9086, - 0x0100, 0x0904, 0x36bf, 0x0804, 0x368d, 0x2061, 0x1a73, 0x0126, - 0x2091, 0x8000, 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, 0x2061, - 0x1800, 0x6354, 0x6074, 0x789a, 0x60c0, 0x789e, 0x60bc, 0x78aa, - 0x012e, 0x0804, 0x368d, 0x900e, 0x2110, 0x0c88, 0x81ff, 0x1904, - 0x36bf, 0x080c, 0x779e, 0x0904, 0x36bf, 0x0126, 0x2091, 0x8000, - 0x6254, 0x6074, 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x26f5, - 0x080c, 0x5a7c, 0x012e, 0x0804, 0x368d, 0x012e, 0x0804, 0x36c2, - 0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0x19aa, 0x2070, 0x2061, - 0x1847, 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x955b, - 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x368f, - 0x7884, 0xd0fc, 0x0158, 0x2001, 0x002a, 0x2004, 0x9005, 0x0180, - 0x9082, 0x00e1, 0x0298, 0x012e, 0x0804, 0x36c2, 0x2001, 0x002a, - 0x2004, 0x9005, 0x0128, 0x2069, 0x1847, 0x6908, 0x9102, 0x1230, - 0x012e, 0x0804, 0x36c2, 0x012e, 0x0804, 0x36bf, 0x080c, 0xb094, - 0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x3c6d, 0x00c6, 0x080c, 0x4c41, - 0x00ce, 0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, 0x7898, 0xa80e, - 0x789c, 0xa812, 0x2001, 0x002e, 0x2004, 0xa81a, 0x2001, 0x002f, - 0x2004, 0xa81e, 0x2001, 0x0030, 0x2004, 0xa822, 0x2001, 0x0031, - 0x2004, 0xa826, 0x2001, 0x0034, 0x2004, 0xa82a, 0x2001, 0x0035, - 0x2004, 0xa82e, 0x2001, 0x002a, 0x2004, 0x9080, 0x0003, 0x9084, - 0x00fc, 0x8004, 0xa816, 0x080c, 0x3df7, 0x0928, 0x7014, 0x2048, - 0xad2c, 0xac28, 0xab1c, 0xaa18, 0xa930, 0xa808, 0xd0b4, 0x1120, - 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x4c8a, 0x701f, - 0x3d34, 0x7023, 0x0001, 0x012e, 0x0005, 0x080c, 0xacfc, 0x0046, - 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x080c, 0x3bd8, 0x2001, 0x19a0, 0x2003, 0x0000, 0x2021, 0x000a, - 0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, - 0x60bf, 0x0012, 0x080c, 0x3e66, 0x080c, 0x3e25, 0x00f6, 0x00e6, - 0x0086, 0x2940, 0x2071, 0x19e8, 0x2079, 0x0090, 0x00d6, 0x2069, - 0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, 0x0035, 0x2004, 0x780e, - 0x2001, 0x0034, 0x2004, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, - 0x41db, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x40fd, 0x080c, 0x402a, - 0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, - 0x424f, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, - 0x1560, 0x2071, 0x0200, 0x7037, 0x0000, 0x7050, 0x9084, 0xff00, - 0x9086, 0x3200, 0x1510, 0x7037, 0x0001, 0x7050, 0x9084, 0xff00, - 0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, 0x7054, 0x7037, 0x0000, - 0x715c, 0x9106, 0x1190, 0x2001, 0x1820, 0x2004, 0x9106, 0x1168, - 0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, - 0x080c, 0x4034, 0x080c, 0x3e20, 0x0058, 0x080c, 0x3e20, 0x080c, - 0x4173, 0x080c, 0x40f3, 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, - 0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, - 0x001e, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, - 0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, 0x0004, 0x200c, 0x918c, - 0xfffd, 0x2102, 0x080c, 0x1352, 0x2009, 0x0028, 0x080c, 0x2220, - 0x2001, 0x0227, 0x200c, 0x2102, 0x080c, 0xad18, 0x00fe, 0x00ee, - 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, 0x2001, - 0x19a0, 0x2004, 0x9005, 0x1118, 0x012e, 0x0804, 0x368d, 0x012e, - 0x2021, 0x400c, 0x0804, 0x368f, 0x0016, 0x0026, 0x0036, 0x0046, - 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, 0x0156, 0x7014, 0x2048, - 0x7020, 0x20a8, 0x8000, 0x7022, 0xa804, 0x9005, 0x0904, 0x3d90, - 0x2048, 0x1f04, 0x3d44, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, - 0xa598, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, - 0x0000, 0x0096, 0x7014, 0x2048, 0xa864, 0x009e, 0x9086, 0x0103, - 0x0170, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, - 0x9080, 0x001b, 0x080c, 0x4c8a, 0x701f, 0x3d34, 0x00b0, 0x8906, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, - 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0fd6, - 0x000e, 0x080c, 0x4c8d, 0x701f, 0x3d34, 0x015e, 0x00de, 0x009e, - 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, - 0x7014, 0x2048, 0xa864, 0x9086, 0x0103, 0x1118, 0x701f, 0x3df5, - 0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, 0x2009, 0x007f, - 0x080c, 0x6749, 0x0110, 0x9006, 0x0030, 0xb813, 0x00ff, 0xb817, - 0xfffd, 0x080c, 0xd409, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e, - 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, 0x36bf, 0x0016, - 0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, - 0x0156, 0x701f, 0x3dc7, 0x7007, 0x0003, 0x0804, 0x3d85, 0xa830, - 0x9086, 0x0100, 0x2021, 0x400c, 0x0904, 0x368f, 0x0076, 0xad10, - 0xac0c, 0xab24, 0xaa20, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, - 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, - 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, - 0x20a0, 0x0006, 0x080c, 0x0fd6, 0x000e, 0x080c, 0x4c8d, 0x007e, - 0x701f, 0x3d34, 0x7023, 0x0001, 0x0005, 0x0804, 0x368d, 0x0156, - 0x00c6, 0xa814, 0x908a, 0x001e, 0x0218, 0xa833, 0x001e, 0x0010, - 0xa832, 0x0078, 0x81ff, 0x0168, 0x0016, 0x080c, 0x4c41, 0x001e, - 0x0130, 0xa800, 0x2040, 0xa008, 0xa80a, 0x2100, 0x0c58, 0x9006, - 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6, - 0x2079, 0x0000, 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005, - 0x2001, 0x19a0, 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6, - 0x2061, 0x0200, 0x2001, 0x19ab, 0x2004, 0x601a, 0x2061, 0x0100, - 0x2001, 0x19aa, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c, - 0x4c41, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, - 0x002e, 0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2061, - 0x0090, 0x2079, 0x0100, 0x2001, 0x19aa, 0x2004, 0x6036, 0x2009, - 0x0040, 0x080c, 0x2220, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0xa86e, 0x601a, 0xa873, 0x0000, 0x601f, 0x0000, 0x78ca, 0x9006, - 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x080c, - 0x4c41, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, - 0x2001, 0x0030, 0x2004, 0xa866, 0x2001, 0x0031, 0x2004, 0xa86a, - 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0xa873, 0x0000, - 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x0300, 0x2003, 0x0000, - 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d, - 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff, - 0x0148, 0x080c, 0x2a77, 0x1130, 0x9006, 0x080c, 0x29ca, 0x9006, - 0x080c, 0x29ad, 0x2001, 0x199f, 0x2003, 0x0000, 0x7884, 0x9084, - 0x0007, 0x0002, 0x3eb5, 0x3eb6, 0x3eb7, 0x3eb2, 0x3eb2, 0x3eb2, - 0x3eb2, 0x3eb2, 0x012e, 0x0804, 0x36c2, 0x0ce0, 0x0cd8, 0x080c, - 0x779e, 0x1128, 0x012e, 0x2009, 0x0016, 0x0804, 0x36bf, 0x81ff, - 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x368f, 0x2001, 0x0141, - 0x2004, 0xd0dc, 0x0db0, 0x080c, 0xacfc, 0x0086, 0x0096, 0x00a6, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3bd8, 0x2009, - 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, 0x9006, 0x2068, 0x2060, - 0x2058, 0x080c, 0x432a, 0x080c, 0x427a, 0x903e, 0x2720, 0x00f6, - 0x00e6, 0x0086, 0x2940, 0x2071, 0x19e8, 0x2079, 0x0090, 0x00d6, - 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x68d4, 0x780e, 0x68d0, - 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x41db, 0x080c, 0x2a7f, - 0x080c, 0x2a7f, 0x080c, 0x2a7f, 0x080c, 0x2a7f, 0x080c, 0x41db, - 0x008e, 0x00ee, 0x00fe, 0x080c, 0x40fd, 0x2009, 0x9c40, 0x8109, - 0x11b0, 0x080c, 0x4034, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, - 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, - 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, 0x36bf, 0x0cf8, 0x2001, - 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, 0x00f6, 0x2079, 0x0000, - 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, 0x81ff, - 0x0150, 0x080c, 0x40db, 0x2d00, 0x9c05, 0x9b05, 0x0120, 0x080c, - 0x4034, 0x0804, 0x3fdd, 0x080c, 0x424f, 0x080c, 0x4173, 0x080c, - 0x40be, 0x080c, 0x40f3, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac, - 0x0130, 0x8b58, 0x080c, 0x4034, 0x00fe, 0x0804, 0x3fdd, 0x00fe, - 0x080c, 0x402a, 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602, 0x2001, - 0x0033, 0x2502, 0x080c, 0x4034, 0x0080, 0x87ff, 0x0138, 0x2001, - 0x0201, 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, 0x1a6e, - 0x2004, 0x9086, 0x0000, 0x1904, 0x3f2d, 0x2001, 0x032f, 0x2003, - 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, 0x3fdd, - 0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904, 0x3fdd, - 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, - 0x1148, 0x2001, 0x1a6e, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, - 0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, 0x9005, 0x0108, 0xa016, - 0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, 0x2220, 0x2900, 0xa85a, - 0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0xa817, 0x0000, 0x00c6, - 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, 0x0203, - 0x2004, 0x1f04, 0x3fb4, 0x00ce, 0x0030, 0xa817, 0x0001, 0x78b0, - 0x9005, 0x0108, 0xa816, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, - 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, - 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, - 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3ee7, 0x001e, 0x00c6, 0x2001, - 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x6106, - 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, 0x200c, 0x918c, - 0xfffd, 0x2102, 0x080c, 0x1352, 0x7884, 0x9084, 0x0003, 0x9086, - 0x0002, 0x01b0, 0x2009, 0x0028, 0x080c, 0x2220, 0x2001, 0x0227, - 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ff, 0x080c, 0x2b29, 0x6052, - 0x602f, 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, - 0x080c, 0xad18, 0x00ce, 0x2d08, 0x2c10, 0x2b18, 0x2b00, 0x9c05, - 0x9d05, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, - 0x008e, 0x1118, 0x012e, 0x0804, 0x368d, 0x012e, 0x2021, 0x400c, - 0x0804, 0x368f, 0x9085, 0x0001, 0x1d04, 0x4033, 0x2091, 0x6000, - 0x8420, 0x9486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010, - 0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x1a6e, 0x2003, 0x0000, - 0x0071, 0x2009, 0x0048, 0x080c, 0x2220, 0x2001, 0x0227, 0x2024, - 0x2402, 0x2001, 0x0109, 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, - 0x00e6, 0x2071, 0x19e8, 0x7054, 0x9086, 0x0000, 0x0520, 0x2079, - 0x0090, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, - 0x1120, 0x2009, 0x0040, 0x080c, 0x2220, 0x782c, 0xd0fc, 0x0d88, - 0x080c, 0x424f, 0x7054, 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, - 0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2220, 0x782b, - 0x0002, 0x7057, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, - 0x0100, 0x2001, 0x1818, 0x200c, 0x7932, 0x7936, 0x080c, 0x26d5, - 0x080c, 0x2af6, 0x080c, 0x2b29, 0x784b, 0xf7f7, 0x7843, 0x0090, - 0x7843, 0x0010, 0x7850, 0xc0e5, 0x7852, 0x2019, 0x61a8, 0x7820, - 0xd09c, 0x0110, 0x8319, 0x1dd8, 0x7850, 0xc0e4, 0x7852, 0x2011, - 0x0048, 0x080c, 0x2ad3, 0x7843, 0x0040, 0x2019, 0x01f4, 0xa001, - 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2a99, 0x2011, - 0x0020, 0x080c, 0x2ad3, 0x7843, 0x0000, 0x9006, 0x080c, 0x2a99, - 0x2011, 0x0048, 0x080c, 0x2ad3, 0x00fe, 0x0005, 0x7884, 0xd0ac, - 0x11c8, 0x00f6, 0x00e6, 0x2071, 0x1a6e, 0x2079, 0x0320, 0x2001, - 0x0201, 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, 0x0000, 0x1140, - 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x782b, 0x0019, - 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, - 0x908c, 0x0070, 0x0178, 0x2009, 0x0032, 0x260a, 0x2009, 0x0033, - 0x250a, 0xd0b4, 0x0108, 0x8c60, 0xd0ac, 0x0108, 0x8d68, 0xd0a4, - 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, - 0x0110, 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, - 0x2001, 0x19ab, 0x2004, 0x70e2, 0x080c, 0x3e16, 0x1188, 0x2001, - 0x1820, 0x2004, 0x2009, 0x181f, 0x210c, 0x918c, 0x00ff, 0x706e, - 0x716a, 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, 0xe109, 0x0080, - 0x702c, 0x9085, 0x0002, 0x702e, 0x2009, 0x1818, 0x210c, 0x716e, - 0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, 0x0809, - 0x7077, 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, 0x7080, 0x8000, - 0x7082, 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, 0x707e, 0x70d6, - 0x70ab, 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, 0x1984, 0x9085, - 0x0092, 0x7016, 0x080c, 0x424f, 0x00f6, 0x2071, 0x1a6e, 0x2079, - 0x0320, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, - 0x780e, 0x6898, 0x780a, 0x00de, 0x080c, 0x3e16, 0x0140, 0x2001, - 0x199f, 0x200c, 0x2003, 0x0001, 0x918e, 0x0001, 0x0120, 0x2009, - 0x03e8, 0x8109, 0x1df0, 0x792c, 0xd1fc, 0x0110, 0x782b, 0x0004, - 0x2011, 0x0011, 0x080c, 0x41db, 0x2011, 0x0001, 0x080c, 0x41db, - 0x00fe, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a6e, 0x2079, - 0x0320, 0x792c, 0xd1fc, 0x0904, 0x41d8, 0x782b, 0x0002, 0x9026, - 0xd19c, 0x1904, 0x41d4, 0x7000, 0x0002, 0x41d8, 0x4189, 0x41b9, - 0x41d4, 0xd1bc, 0x1170, 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, - 0x0001, 0x080c, 0x41db, 0x0904, 0x41d8, 0x080c, 0x41db, 0x0804, - 0x41d8, 0x00f6, 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, - 0x7914, 0x782b, 0x0004, 0x7812, 0x7916, 0x2001, 0x0201, 0x200c, - 0x81ff, 0x0de8, 0x080c, 0x40db, 0x2009, 0x0001, 0x00f6, 0x2079, - 0x0300, 0x78b8, 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, - 0x00f8, 0x8001, 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, - 0x1904, 0x417d, 0x2011, 0x0001, 0x00b1, 0x0090, 0xa010, 0x9092, - 0x0004, 0x9086, 0x0015, 0x1120, 0xa000, 0xa05a, 0x2011, 0x0031, - 0xa212, 0xd1dc, 0x1960, 0x0828, 0x782b, 0x0004, 0x7003, 0x0000, - 0x00ee, 0x00fe, 0x0005, 0xa014, 0x9005, 0x0550, 0x8001, 0x0036, - 0x0096, 0xa016, 0xa058, 0x2048, 0xa010, 0x2009, 0x0031, 0x911a, - 0x831c, 0x831c, 0x938a, 0x0007, 0x1a0c, 0x0d85, 0x9398, 0x4209, - 0x231d, 0x083f, 0x9080, 0x0004, 0x7a2a, 0x7100, 0x8108, 0x7102, - 0x009e, 0x003e, 0x908a, 0x0035, 0x1140, 0x0096, 0xa058, 0x2048, - 0xa804, 0xa05a, 0x2001, 0x0019, 0x009e, 0xa012, 0x9085, 0x0001, - 0x0005, 0x4246, 0x423d, 0x4234, 0x422b, 0x4222, 0x4219, 0x4210, - 0xa964, 0x7902, 0xa968, 0x7906, 0xa96c, 0x7912, 0xa970, 0x7916, - 0x0005, 0xa974, 0x7902, 0xa978, 0x7906, 0xa97c, 0x7912, 0xa980, - 0x7916, 0x0005, 0xa984, 0x7902, 0xa988, 0x7906, 0xa98c, 0x7912, - 0xa990, 0x7916, 0x0005, 0xa994, 0x7902, 0xa998, 0x7906, 0xa99c, - 0x7912, 0xa9a0, 0x7916, 0x0005, 0xa9a4, 0x7902, 0xa9a8, 0x7906, - 0xa9ac, 0x7912, 0xa9b0, 0x7916, 0x0005, 0xa9b4, 0x7902, 0xa9b8, - 0x7906, 0xa9bc, 0x7912, 0xa9c0, 0x7916, 0x0005, 0xa9c4, 0x7902, - 0xa9c8, 0x7906, 0xa9cc, 0x7912, 0xa9d0, 0x7916, 0x0005, 0x00f6, - 0x00e6, 0x0086, 0x2071, 0x19e8, 0x2079, 0x0090, 0x792c, 0xd1fc, - 0x01e8, 0x782b, 0x0002, 0x2940, 0x9026, 0x7054, 0x0002, 0x4276, - 0x4262, 0x426d, 0x8001, 0x7056, 0xd19c, 0x1180, 0x2011, 0x0001, - 0x080c, 0x41db, 0x190c, 0x41db, 0x0048, 0x8001, 0x7056, 0x782c, - 0xd0fc, 0x1d38, 0x2011, 0x0001, 0x080c, 0x41db, 0x008e, 0x00ee, - 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x2061, 0x0200, - 0x2001, 0x19ab, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x19aa, - 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, - 0x9005, 0x0520, 0x2038, 0x2001, 0x002e, 0x2024, 0x2001, 0x002f, - 0x201c, 0x080c, 0x4c41, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, - 0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, - 0x903e, 0x0096, 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, - 0x080c, 0x42f2, 0x1d68, 0x2900, 0xa85a, 0x00d0, 0x080c, 0x4c41, - 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, - 0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0xa86e, 0x2001, 0x002b, 0x2004, 0xa872, - 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x19aa, 0x2004, 0x6036, - 0x2009, 0x0040, 0x080c, 0x2220, 0x2001, 0x002a, 0x2004, 0x9084, - 0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, - 0x000e, 0x78ca, 0x9006, 0x600a, 0x600e, 0x008e, 0x00ce, 0x00ee, - 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0080, 0xaa60, 0x22e8, 0x20a0, - 0x20e1, 0x0000, 0x2099, 0x0088, 0x702b, 0x0026, 0x7402, 0x7306, - 0x9006, 0x700a, 0x700e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7112, - 0x702b, 0x0041, 0x702c, 0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b, - 0x0040, 0x4005, 0x7400, 0x7304, 0x87ff, 0x0190, 0x0086, 0x0096, - 0x2940, 0x0086, 0x080c, 0x4c41, 0x008e, 0xa058, 0x00a6, 0x2050, - 0x2900, 0xb006, 0xa05a, 0x00ae, 0x009e, 0x008e, 0x9085, 0x0001, - 0x00ee, 0x0005, 0x00e6, 0x2001, 0x002d, 0x2004, 0x9005, 0x0528, - 0x2038, 0x2001, 0x0030, 0x2024, 0x2001, 0x0031, 0x201c, 0x080c, - 0x4c41, 0x2940, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, - 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, - 0x0096, 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, - 0x42f2, 0x1d68, 0x2900, 0xa85a, 0x00d8, 0x080c, 0x4c41, 0x2940, - 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, - 0x2004, 0xa066, 0x2001, 0x0031, 0x2004, 0xa06a, 0x2001, 0x002a, - 0x2004, 0x9084, 0xfff8, 0xa06e, 0x2001, 0x002b, 0x2004, 0xa072, - 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, - 0x0101, 0x200c, 0x918d, 0x0200, 0x2102, 0xa017, 0x0000, 0x2001, - 0x1a6e, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x2001, - 0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001, - 0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, - 0x2091, 0x8000, 0x20a9, 0x0007, 0x20a1, 0x1840, 0x20e9, 0x0001, - 0x9006, 0x4004, 0x20a9, 0x0014, 0x20a1, 0xffec, 0x20e9, 0x0000, - 0x9006, 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, 0x9086, - 0x0052, 0x0108, 0x0005, 0x0804, 0x368d, 0x7d98, 0x7c9c, 0x0804, - 0x3791, 0x080c, 0x779e, 0x190c, 0x6162, 0x6040, 0x9084, 0x0020, - 0x09b1, 0x2069, 0x1847, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4c8a, 0x701f, 0x43d1, - 0x0005, 0x080c, 0x584f, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, - 0x20d8, 0x21d0, 0x2069, 0x1847, 0x6800, 0x9005, 0x0904, 0x36c2, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x6804, 0x0118, 0xc0a4, 0xc0ac, - 0x6806, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x36c2, 0xd094, 0x00c6, - 0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, 0x0005, 0x0218, - 0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, - 0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, 0x0010, 0x0010, - 0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a, - 0x007f, 0x1a04, 0x36c2, 0x9288, 0x348e, 0x210d, 0x918c, 0x00ff, - 0x6166, 0xd0dc, 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, 0x36c2, - 0x605e, 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, 0x8004, 0x8004, - 0x0006, 0x2009, 0x19b2, 0x9080, 0x27d0, 0x2005, 0x200a, 0x2008, - 0x2001, 0x0018, 0x080c, 0xaced, 0x2009, 0x0390, 0x200b, 0x0400, - 0x000e, 0x2009, 0x19b3, 0x9080, 0x27d4, 0x2005, 0x200a, 0x6808, - 0x908a, 0x0100, 0x0a04, 0x36c2, 0x908a, 0x0841, 0x1a04, 0x36c2, - 0x9084, 0x0007, 0x1904, 0x36c2, 0x680c, 0x9005, 0x0904, 0x36c2, - 0x6810, 0x9005, 0x0904, 0x36c2, 0x6848, 0x6940, 0x910a, 0x1a04, - 0x36c2, 0x8001, 0x0904, 0x36c2, 0x684c, 0x6944, 0x910a, 0x1a04, - 0x36c2, 0x8001, 0x0904, 0x36c2, 0x6814, 0x908c, 0x00ff, 0x614e, - 0x8007, 0x9084, 0x00ff, 0x6052, 0x080c, 0x7ae7, 0x080c, 0x6cfc, - 0x080c, 0x6d66, 0x6808, 0x602a, 0x080c, 0x2192, 0x2009, 0x0170, - 0x200b, 0x0080, 0xa001, 0xa001, 0x200b, 0x0000, 0x0036, 0x6b08, - 0x080c, 0x272f, 0x003e, 0x6000, 0x9086, 0x0000, 0x1904, 0x456d, - 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, - 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, - 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, - 0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, - 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0x19b4, 0x20e9, 0x0001, - 0x4001, 0x20a9, 0x0004, 0x20a1, 0x19ce, 0x20e9, 0x0001, 0x4001, - 0x080c, 0x8b26, 0x00c6, 0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384, - 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, 0x80fe, - 0x6878, 0x6016, 0x6874, 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, - 0x9184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, - 0x6003, 0x0001, 0x1f04, 0x44c2, 0x00ce, 0x00c6, 0x2061, 0x199c, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x11a8, 0x6a88, 0x9284, 0xc000, - 0x2010, 0x9286, 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, - 0x080c, 0x29ca, 0x2001, 0x0001, 0x080c, 0x29ad, 0x0088, 0x9286, - 0x4000, 0x1148, 0x2063, 0x0001, 0x9006, 0x080c, 0x29ca, 0x9006, - 0x080c, 0x29ad, 0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, - 0x00ce, 0x00e6, 0x2c70, 0x080c, 0x0ed3, 0x00ee, 0x080c, 0x2af6, - 0x080c, 0x2b29, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204, - 0x9085, 0x0180, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030, - 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x197c, - 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010, - 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x27a4, - 0x2001, 0x196d, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, - 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x779e, 0x0128, - 0x080c, 0x5128, 0x0110, 0x080c, 0x26f5, 0x60d4, 0x9005, 0x01c0, - 0x6003, 0x0001, 0x2009, 0x4555, 0x00e0, 0x080c, 0x779e, 0x1168, - 0x2011, 0x7612, 0x080c, 0x8993, 0x2011, 0x7605, 0x080c, 0x8a9f, - 0x080c, 0x7abb, 0x080c, 0x76cd, 0x0040, 0x080c, 0x6058, 0x0028, - 0x6003, 0x0004, 0x2009, 0x456d, 0x0020, 0x080c, 0x6b73, 0x0804, - 0x368d, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c, - 0x1118, 0x2091, 0x31bd, 0x0817, 0x2091, 0x313d, 0x0817, 0x6000, - 0x9086, 0x0000, 0x0904, 0x36bf, 0x2069, 0x1847, 0x7890, 0x6842, - 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x2039, 0x0001, 0x0804, 0x4c8d, 0x9006, 0x080c, 0x26f5, - 0x81ff, 0x1904, 0x36bf, 0x080c, 0x779e, 0x11b0, 0x080c, 0x7ab6, - 0x080c, 0x619d, 0x080c, 0x3482, 0x0118, 0x6130, 0xc18d, 0x6132, - 0x080c, 0xd645, 0x0130, 0x080c, 0x77c1, 0x1118, 0x080c, 0x7772, - 0x0038, 0x080c, 0x76cd, 0x0020, 0x080c, 0x6162, 0x080c, 0x6058, - 0x0804, 0x368d, 0x81ff, 0x1904, 0x36bf, 0x080c, 0x779e, 0x1110, - 0x0804, 0x36bf, 0x0126, 0x2091, 0x8000, 0x6194, 0x81ff, 0x0190, - 0x704f, 0x0000, 0x2001, 0x1d80, 0x2009, 0x0040, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4c8d, 0x701f, 0x368b, - 0x012e, 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, 0x1d80, 0x20a9, - 0x0040, 0x20e9, 0x0001, 0x20a1, 0x1d80, 0x2019, 0xffff, 0x4304, - 0x655c, 0x9588, 0x348e, 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e, - 0x2011, 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, 0x67b4, 0x1190, - 0xb814, 0x821c, 0x0238, 0x9398, 0x1d80, 0x9085, 0xff00, 0x8007, - 0x201a, 0x0038, 0x9398, 0x1d80, 0x2324, 0x94a4, 0xff00, 0x9405, - 0x201a, 0x8210, 0x8108, 0x9182, 0x0080, 0x1208, 0x0c18, 0x8201, - 0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, - 0x1d80, 0x2099, 0x1d80, 0x080c, 0x60ed, 0x0804, 0x45ca, 0x080c, - 0x4c74, 0x0904, 0x36c2, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, - 0x0804, 0x36bf, 0x080c, 0x5840, 0xd0b4, 0x0558, 0x7884, 0x908e, - 0x007e, 0x0538, 0x908e, 0x007f, 0x0520, 0x908e, 0x0080, 0x0508, - 0x080c, 0x347d, 0x1148, 0xb800, 0xd08c, 0x11d8, 0xb804, 0x9084, - 0x00ff, 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, 0xa868, 0xc0fd, - 0xa86a, 0x080c, 0xd0ec, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, - 0x7007, 0x0003, 0x701f, 0x4655, 0x0005, 0x080c, 0x4c74, 0x0904, - 0x36c2, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, 0x2098, 0xa860, - 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, - 0x9080, 0x0006, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, - 0x2098, 0x080c, 0x0fd6, 0x0070, 0x20a9, 0x0004, 0xa85c, 0x9080, - 0x000a, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, - 0x080c, 0x0fd6, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, - 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x0804, 0x4c8d, 0x81ff, 0x1904, 0x36bf, 0x080c, 0x4c58, - 0x0904, 0x36c2, 0x080c, 0x6a00, 0x0904, 0x36bf, 0x0058, 0xa878, - 0x9005, 0x0120, 0x2009, 0x0004, 0x0804, 0x36bf, 0xa974, 0xaa94, - 0x0804, 0x368d, 0x080c, 0x5848, 0x0904, 0x368d, 0x701f, 0x469f, - 0x7007, 0x0003, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x7888, 0x908a, - 0x1000, 0x1a04, 0x36c2, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x080c, - 0x6c11, 0x0120, 0x080c, 0x6c19, 0x1904, 0x36c2, 0x080c, 0x6a85, - 0x0904, 0x36bf, 0x2019, 0x0004, 0x900e, 0x080c, 0x6a12, 0x0904, - 0x36bf, 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, 0x908a, 0x1000, - 0x12f8, 0x080c, 0x4c72, 0x01e0, 0x080c, 0x6c11, 0x0118, 0x080c, - 0x6c19, 0x11b0, 0x080c, 0x6a85, 0x2009, 0x0002, 0x0168, 0x2009, - 0x0002, 0x2019, 0x0004, 0x080c, 0x6a12, 0x2009, 0x0003, 0x0120, - 0xa998, 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, - 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, - 0xa897, 0x4000, 0x080c, 0x5848, 0x0110, 0x9006, 0x0018, 0x900e, - 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x9186, 0x00ff, 0x0110, - 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0x1800, 0x645c, 0x2400, - 0x9506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, - 0x67b4, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, - 0x89a1, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x798c, 0x2001, 0x1980, - 0x918c, 0x8000, 0x2102, 0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c, - 0x6c11, 0x0120, 0x080c, 0x6c19, 0x1904, 0x36c2, 0x080c, 0x687b, - 0x0904, 0x36bf, 0x080c, 0x6a09, 0x0904, 0x36bf, 0x2001, 0x1980, - 0x2004, 0xd0fc, 0x1904, 0x368d, 0x0804, 0x46aa, 0xa9a0, 0x2001, - 0x1980, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4c65, 0x01a0, - 0x080c, 0x6c11, 0x0118, 0x080c, 0x6c19, 0x1170, 0x080c, 0x687b, - 0x2009, 0x0002, 0x0128, 0x080c, 0x6a09, 0x1170, 0x2009, 0x0003, - 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, - 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x1980, - 0x2004, 0xd0fc, 0x1128, 0x080c, 0x5848, 0x0110, 0x9006, 0x0018, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904, - 0x36bf, 0x798c, 0x2001, 0x197f, 0x918c, 0x8000, 0x2102, 0x080c, - 0x4c58, 0x0904, 0x36c2, 0x080c, 0x6c11, 0x0120, 0x080c, 0x6c19, - 0x1904, 0x36c2, 0x080c, 0x687b, 0x0904, 0x36bf, 0x080c, 0x69f7, - 0x0904, 0x36bf, 0x2001, 0x197f, 0x2004, 0xd0fc, 0x1904, 0x368d, - 0x0804, 0x46aa, 0xa9a0, 0x2001, 0x197f, 0x918c, 0x8000, 0xc18d, - 0x2102, 0x080c, 0x4c65, 0x01a0, 0x080c, 0x6c11, 0x0118, 0x080c, - 0x6c19, 0x1170, 0x080c, 0x687b, 0x2009, 0x0002, 0x0128, 0x080c, - 0x69f7, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, - 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, - 0xa897, 0x4000, 0x2001, 0x197f, 0x2004, 0xd0fc, 0x1128, 0x080c, - 0x5848, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, - 0x0000, 0x0005, 0x6100, 0x0804, 0x368d, 0x080c, 0x4c74, 0x0904, - 0x36c2, 0x080c, 0x5854, 0x1904, 0x36bf, 0x79a8, 0xd184, 0x1158, - 0xb834, 0x8007, 0x789e, 0xb830, 0x8007, 0x789a, 0xbb2c, 0x831f, - 0xba28, 0x8217, 0x0050, 0xb824, 0x8007, 0x789e, 0xb820, 0x8007, - 0x789a, 0xbb1c, 0x831f, 0xba18, 0x8217, 0xb900, 0x918c, 0x0202, - 0x0804, 0x368d, 0x78a8, 0x909c, 0x0003, 0xd0ac, 0x1150, 0xd0b4, - 0x1140, 0x939a, 0x0003, 0x1a04, 0x36bf, 0x625c, 0x7884, 0x9206, - 0x1548, 0x080c, 0x8b10, 0x2001, 0xffec, 0x2009, 0x000c, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0000, 0x0006, 0x78a8, 0x9084, - 0x0080, 0x1118, 0x000e, 0x0804, 0x4c8d, 0x000e, 0x2031, 0x0000, - 0x2061, 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, - 0xa392, 0xa496, 0xa59a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f, - 0x4862, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x080c, 0x4c74, 0x0904, - 0x36c2, 0x080c, 0x6c11, 0x1904, 0x36bf, 0x00c6, 0x080c, 0x4c41, - 0x00ce, 0x0904, 0x36bf, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0x7ea8, 0x080c, 0xd092, 0x0904, 0x36bf, 0x7007, 0x0003, 0x701f, - 0x4866, 0x0005, 0x080c, 0x4397, 0x0804, 0x368d, 0xa830, 0x9086, - 0x0100, 0x0904, 0x36bf, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, - 0x9084, 0xffc0, 0x9080, 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0x0804, 0x4c8d, 0x9006, 0x080c, 0x26f5, 0x78a8, - 0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x36bf, - 0x080c, 0x779e, 0x0110, 0x080c, 0x6162, 0x7888, 0x908a, 0x1000, - 0x1a04, 0x36c2, 0x7984, 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f, - 0x1a04, 0x36c2, 0x2100, 0x080c, 0x26bf, 0x0026, 0x00c6, 0x0126, - 0x2091, 0x8000, 0x2061, 0x1a04, 0x601b, 0x0000, 0x601f, 0x0000, - 0x607b, 0x0000, 0x607f, 0x0000, 0x080c, 0x779e, 0x1158, 0x080c, - 0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001, 0x080c, 0x77e2, 0x080c, - 0x76cd, 0x00f0, 0x080c, 0xacfc, 0x080c, 0xb09b, 0x080c, 0xad18, - 0x2061, 0x0100, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x810f, - 0x9105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x1999, - 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x6088, 0x080c, 0x8a5d, - 0x7984, 0x080c, 0x779e, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c, - 0x470d, 0x012e, 0x00ce, 0x002e, 0x0804, 0x368d, 0x7984, 0x080c, - 0x6749, 0x2b08, 0x1904, 0x36c2, 0x0804, 0x368d, 0x81ff, 0x0120, - 0x2009, 0x0001, 0x0804, 0x36bf, 0x60dc, 0xd0ac, 0x1130, 0xd09c, - 0x1120, 0x2009, 0x0005, 0x0804, 0x36bf, 0x080c, 0x4c41, 0x1120, - 0x2009, 0x0002, 0x0804, 0x36bf, 0x7984, 0x81ff, 0x0904, 0x36c2, - 0x9192, 0x0021, 0x1a04, 0x36c2, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, - 0xa85c, 0x9080, 0x0019, 0x702a, 0xaf60, 0x7736, 0x080c, 0x4c8a, - 0x701f, 0x4921, 0x7880, 0x9086, 0x006e, 0x0110, 0x701f, 0x52da, - 0x0005, 0x2009, 0x0080, 0x080c, 0x67b4, 0x1118, 0x080c, 0x6c11, - 0x0120, 0x2021, 0x400a, 0x0804, 0x368f, 0x00d6, 0x0096, 0xa964, - 0xaa6c, 0xab70, 0xac74, 0xad78, 0xae7c, 0xa884, 0x90be, 0x0100, - 0x0904, 0x49ba, 0x90be, 0x0112, 0x0904, 0x49ba, 0x90be, 0x0113, - 0x0904, 0x49ba, 0x90be, 0x0114, 0x0904, 0x49ba, 0x90be, 0x0117, - 0x0904, 0x49ba, 0x90be, 0x011a, 0x0904, 0x49ba, 0x90be, 0x011c, - 0x0904, 0x49ba, 0x90be, 0x0121, 0x0904, 0x49a1, 0x90be, 0x0131, - 0x0904, 0x49a1, 0x90be, 0x0171, 0x0904, 0x49ba, 0x90be, 0x0173, - 0x0904, 0x49ba, 0x90be, 0x01a1, 0x1128, 0xa894, 0x8007, 0xa896, - 0x0804, 0x49c5, 0x90be, 0x0212, 0x0904, 0x49ae, 0x90be, 0x0213, - 0x05e8, 0x90be, 0x0214, 0x0500, 0x90be, 0x0217, 0x0188, 0x90be, - 0x021a, 0x1120, 0xa89c, 0x8007, 0xa89e, 0x04e0, 0x90be, 0x021f, - 0x05c8, 0x90be, 0x0300, 0x05b0, 0x009e, 0x00de, 0x0804, 0x36c2, - 0x7028, 0x9080, 0x0010, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, - 0x20a9, 0x0007, 0x080c, 0x4a03, 0x7028, 0x9080, 0x000e, 0x2098, - 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x4a03, - 0x00c8, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0, - 0x20e8, 0x20a9, 0x0001, 0x080c, 0x4a10, 0x00b8, 0x7028, 0x9080, - 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, - 0x080c, 0x4a10, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, - 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x04f1, 0x00c6, 0x080c, 0x4c41, - 0x0550, 0xa868, 0xc0fd, 0xa86a, 0xa867, 0x0119, 0x9006, 0xa882, - 0xa87f, 0x0020, 0xa88b, 0x0001, 0x810b, 0xa9ae, 0xa8b2, 0xaab6, - 0xabba, 0xacbe, 0xadc2, 0xa9c6, 0xa8ca, 0x00ce, 0x009e, 0x00de, - 0xa866, 0xa822, 0xa868, 0xc0fd, 0xa86a, 0xa804, 0x2048, 0x080c, - 0xd0ad, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, 0x7007, 0x0003, - 0x701f, 0x49fa, 0x0005, 0x00ce, 0x009e, 0x00de, 0x2009, 0x0002, - 0x0804, 0x36bf, 0xa820, 0x9086, 0x8001, 0x1904, 0x368d, 0x2009, - 0x0004, 0x0804, 0x36bf, 0x0016, 0x0026, 0x3510, 0x20a9, 0x0002, - 0x4002, 0x4104, 0x4004, 0x8211, 0x1dc8, 0x002e, 0x001e, 0x0005, - 0x0016, 0x0026, 0x0036, 0x0046, 0x3520, 0x20a9, 0x0004, 0x4002, - 0x4304, 0x4204, 0x4104, 0x4004, 0x8421, 0x1db8, 0x004e, 0x003e, - 0x002e, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x36bf, 0x60dc, 0xd0ac, 0x1188, 0x2009, 0x180d, 0x210c, 0xd18c, - 0x0130, 0xd09c, 0x0120, 0x2009, 0x0016, 0x0804, 0x36bf, 0xd09c, - 0x1120, 0x2009, 0x0005, 0x0804, 0x36bf, 0x7984, 0x78a8, 0x2040, - 0x080c, 0xb094, 0x1120, 0x9182, 0x007f, 0x0a04, 0x36c2, 0x9186, - 0x00ff, 0x0904, 0x36c2, 0x9182, 0x0800, 0x1a04, 0x36c2, 0x7a8c, - 0x7b88, 0x607c, 0x9306, 0x1158, 0x6080, 0x924e, 0x0904, 0x36c2, - 0x080c, 0xb094, 0x1120, 0x99cc, 0xff00, 0x0904, 0x36c2, 0x0126, - 0x2091, 0x8000, 0x2001, 0x180d, 0x2004, 0xd08c, 0x0198, 0x9386, - 0x00ff, 0x0180, 0x0026, 0x2011, 0x8008, 0x080c, 0x6c35, 0x002e, - 0x0148, 0x918d, 0x8000, 0x080c, 0x6c7f, 0x1120, 0x2001, 0x4009, - 0x0804, 0x4ac1, 0x080c, 0x4b54, 0x0904, 0x4ac7, 0x0086, 0x90c6, - 0x4000, 0x008e, 0x1538, 0x00c6, 0x0006, 0x0036, 0xb818, 0xbb1c, - 0x9305, 0xbb20, 0x9305, 0xbb24, 0x9305, 0xbb28, 0x9305, 0xbb2c, - 0x9305, 0xbb30, 0x9305, 0xbb34, 0x9305, 0x003e, 0x0570, 0xd88c, - 0x1128, 0x080c, 0x6c11, 0x0110, 0xc89d, 0x0438, 0x900e, 0x080c, - 0x6aae, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x000e, - 0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x0090, 0x90c6, - 0x4008, 0x1118, 0x2708, 0x2610, 0x0060, 0x90c6, 0x4009, 0x1108, - 0x0040, 0x90c6, 0x4006, 0x1108, 0x0020, 0x2001, 0x4005, 0x2009, - 0x000a, 0x2020, 0x012e, 0x0804, 0x368f, 0x000e, 0x00ce, 0x2b00, - 0x7026, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0xb1dd, - 0x0904, 0x4b1c, 0x2b00, 0x6012, 0x080c, 0xd3b6, 0x2e58, 0x00ee, - 0x00e6, 0x00c6, 0x080c, 0x4c41, 0x00ce, 0x2b70, 0x1158, 0x080c, - 0xb16c, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, - 0x0804, 0x36bf, 0x900e, 0xa966, 0xa96a, 0x2900, 0x6016, 0xa932, - 0xa868, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0xd89c, 0x1110, - 0x080c, 0x3315, 0x6023, 0x0001, 0x9006, 0x080c, 0x66e6, 0xd89c, - 0x0138, 0x2001, 0x0004, 0x080c, 0x66fa, 0x2009, 0x0003, 0x0030, - 0x2001, 0x0002, 0x080c, 0x66fa, 0x2009, 0x0002, 0x080c, 0xb20a, - 0x78a8, 0xd094, 0x0138, 0x00ee, 0x7024, 0x00e6, 0x2058, 0xb8d4, - 0xc08d, 0xb8d6, 0x9085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, - 0x012e, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, 0x7007, 0x0003, - 0x701f, 0x4b2b, 0x0005, 0xa830, 0x2009, 0x180d, 0x210c, 0xd18c, - 0x0140, 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, 0x4009, 0x0804, - 0x368f, 0x9086, 0x0100, 0x7024, 0x2058, 0x1138, 0x2009, 0x0004, - 0xba04, 0x9294, 0x00ff, 0x0804, 0x578e, 0x900e, 0xa868, 0xd0f4, - 0x1904, 0x368d, 0x080c, 0x6aae, 0x1108, 0xc185, 0xb800, 0xd0bc, - 0x0108, 0xc18d, 0x0804, 0x368d, 0x00e6, 0x00d6, 0x0096, 0x83ff, - 0x0904, 0x4ba3, 0x902e, 0x080c, 0xb094, 0x0130, 0x9026, 0x20a9, - 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x007f, 0x20a9, 0x0781, - 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b8, 0x2100, 0x9406, 0x1904, - 0x4bb4, 0x2428, 0x94ce, 0x007f, 0x1120, 0x92ce, 0xfffd, 0x1558, - 0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce, 0xfffc, 0x1520, 0x93ce, - 0x00ff, 0x1508, 0xc5fd, 0x0480, 0x2058, 0xbf10, 0x2700, 0x9306, - 0x11e8, 0xbe14, 0x2600, 0x9206, 0x11c8, 0x2400, 0x9106, 0x1180, - 0xd884, 0x0598, 0xd894, 0x1588, 0x080c, 0x6bb1, 0x1570, 0x2001, - 0x4000, 0x0460, 0x080c, 0x6c11, 0x1540, 0x2001, 0x4000, 0x0430, - 0x2001, 0x4007, 0x0418, 0x2001, 0x4006, 0x0400, 0x2400, 0x9106, - 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, 0x0918, 0x080c, 0xb094, - 0x1900, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x4b6a, - 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030, - 0x080c, 0x6749, 0x1dd0, 0xbb12, 0xba16, 0x9006, 0x9005, 0x009e, - 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, - 0x36bf, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, - 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7884, 0x9005, 0x0904, - 0x36c2, 0x9096, 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, 0x36c2, - 0x2010, 0x2918, 0x080c, 0x32b5, 0x1120, 0x2009, 0x0003, 0x0804, - 0x36bf, 0x7007, 0x0003, 0x701f, 0x4bf6, 0x0005, 0xa830, 0x9086, - 0x0100, 0x1904, 0x368d, 0x2009, 0x0004, 0x0804, 0x36bf, 0x7984, - 0x080c, 0xb094, 0x1120, 0x9182, 0x007f, 0x0a04, 0x36c2, 0x9186, - 0x00ff, 0x0904, 0x36c2, 0x9182, 0x0800, 0x1a04, 0x36c2, 0x2001, - 0x9400, 0x080c, 0x57e9, 0x1904, 0x36bf, 0x0804, 0x368d, 0xa998, - 0x080c, 0xb094, 0x1118, 0x9182, 0x007f, 0x0280, 0x9186, 0x00ff, - 0x0168, 0x9182, 0x0800, 0x1250, 0x2001, 0x9400, 0x080c, 0x57e9, - 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x2009, 0x000a, - 0x0c48, 0x080c, 0x1059, 0x0198, 0x9006, 0xa802, 0x7014, 0x9005, - 0x1120, 0x2900, 0x7016, 0x701a, 0x0040, 0x7018, 0xa802, 0x0086, - 0x2040, 0x2900, 0xa006, 0x701a, 0x008e, 0x9085, 0x0001, 0x0005, - 0x7984, 0x080c, 0x67b4, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xa998, 0x080c, 0x67b4, - 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, - 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, 0x2608, 0x080c, 0x67b4, - 0x1108, 0x0008, 0x905e, 0x8bff, 0x0005, 0x0016, 0x7114, 0x81ff, - 0x0128, 0x2148, 0xa904, 0x080c, 0x108b, 0x0cc8, 0x7116, 0x711a, - 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, - 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, - 0xa496, 0xa59a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f, 0x368d, - 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, - 0x18b0, 0x2004, 0x9005, 0x1190, 0x0e04, 0x4cbe, 0x7a36, 0x7833, - 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x1200, 0x0804, 0x4d24, 0x0016, 0x0086, - 0x0096, 0x00c6, 0x00e6, 0x2071, 0x189e, 0x7044, 0x9005, 0x1540, - 0x7148, 0x9182, 0x0010, 0x0288, 0x7038, 0x2060, 0x080c, 0x1059, - 0x0904, 0x4d1c, 0xa84b, 0x0000, 0x2900, 0x7046, 0x2001, 0x0002, - 0x9080, 0x1ec1, 0x2005, 0xa846, 0x0098, 0x7038, 0x90e0, 0x0004, - 0x2001, 0x18ba, 0x9c82, 0x18fa, 0x0210, 0x2061, 0x18ba, 0x2c00, - 0x703a, 0x7148, 0x81ff, 0x1108, 0x703e, 0x8108, 0x714a, 0x0460, - 0x7148, 0x8108, 0x714a, 0x7044, 0x2040, 0xa144, 0x2105, 0x0016, - 0x908a, 0x0036, 0x1a0c, 0x0d85, 0x2060, 0x001e, 0x8108, 0x2105, - 0x9005, 0xa146, 0x1520, 0x080c, 0x1059, 0x1130, 0x8109, 0xa946, - 0x7148, 0x8109, 0x714a, 0x00d8, 0x9006, 0xa806, 0xa84a, 0xa046, - 0x2800, 0xa802, 0x2900, 0xa006, 0x7046, 0x2001, 0x0002, 0x9080, - 0x1ec1, 0x2005, 0xa846, 0x0058, 0x2262, 0x6306, 0x640a, 0x00ee, - 0x00ce, 0x009e, 0x008e, 0x001e, 0x012e, 0x00fe, 0x0005, 0x2c00, - 0x9082, 0x001b, 0x0002, 0x4d46, 0x4d46, 0x4d48, 0x4d46, 0x4d46, - 0x4d46, 0x4d4c, 0x4d46, 0x4d46, 0x4d46, 0x4d50, 0x4d46, 0x4d46, - 0x4d46, 0x4d54, 0x4d46, 0x4d46, 0x4d46, 0x4d58, 0x4d46, 0x4d46, - 0x4d46, 0x4d5c, 0x4d46, 0x4d46, 0x4d46, 0x4d61, 0x080c, 0x0d85, - 0xa276, 0xa37a, 0xa47e, 0x0898, 0xa286, 0xa38a, 0xa48e, 0x0878, - 0xa296, 0xa39a, 0xa49e, 0x0858, 0xa2a6, 0xa3aa, 0xa4ae, 0x0838, - 0xa2b6, 0xa3ba, 0xa4be, 0x0818, 0xa2c6, 0xa3ca, 0xa4ce, 0x0804, - 0x4d1f, 0xa2d6, 0xa3da, 0xa4de, 0x0804, 0x4d1f, 0x00e6, 0x2071, - 0x189e, 0x7048, 0x9005, 0x0904, 0x4df8, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x4df7, 0x00f6, 0x2079, 0x0000, 0x00c6, 0x0096, 0x0086, - 0x0076, 0x9006, 0x2038, 0x7040, 0x2048, 0x9005, 0x0500, 0xa948, - 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0d85, 0x2060, 0x001e, - 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, 0x4dfa, 0xa804, 0x9005, - 0x090c, 0x0d85, 0x7042, 0x2938, 0x2040, 0xa003, 0x0000, 0x2001, - 0x0002, 0x9080, 0x1ec1, 0x2005, 0xa04a, 0x0804, 0x4dfa, 0x703c, - 0x2060, 0x2c14, 0x6304, 0x6408, 0x650c, 0x2200, 0x7836, 0x7833, - 0x0012, 0x7882, 0x2300, 0x7886, 0x2400, 0x788a, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x87ff, 0x0118, - 0x2748, 0x080c, 0x108b, 0x7048, 0x8001, 0x704a, 0x9005, 0x1170, - 0x7040, 0x2048, 0x9005, 0x0128, 0x080c, 0x108b, 0x9006, 0x7042, - 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, 0x0420, 0x7040, 0x9005, - 0x1508, 0x7238, 0x2c00, 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa, - 0x18fa, 0x0210, 0x2001, 0x18ba, 0x703e, 0x00a0, 0x9006, 0x703e, - 0x703a, 0x7044, 0x9005, 0x090c, 0x0d85, 0x2048, 0xa800, 0x9005, - 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, 0x9080, 0x1ec1, 0x2005, - 0xa84a, 0x0000, 0x007e, 0x008e, 0x009e, 0x00ce, 0x00fe, 0x012e, - 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4e19, 0x4e19, - 0x4e1b, 0x4e19, 0x4e19, 0x4e19, 0x4e20, 0x4e19, 0x4e19, 0x4e19, - 0x4e25, 0x4e19, 0x4e19, 0x4e19, 0x4e2a, 0x4e19, 0x4e19, 0x4e19, - 0x4e2f, 0x4e19, 0x4e19, 0x4e19, 0x4e34, 0x4e19, 0x4e19, 0x4e19, - 0x4e39, 0x080c, 0x0d85, 0xaa74, 0xab78, 0xac7c, 0x0804, 0x4da5, - 0xaa84, 0xab88, 0xac8c, 0x0804, 0x4da5, 0xaa94, 0xab98, 0xac9c, - 0x0804, 0x4da5, 0xaaa4, 0xaba8, 0xacac, 0x0804, 0x4da5, 0xaab4, - 0xabb8, 0xacbc, 0x0804, 0x4da5, 0xaac4, 0xabc8, 0xaccc, 0x0804, - 0x4da5, 0xaad4, 0xabd8, 0xacdc, 0x0804, 0x4da5, 0x0016, 0x0026, - 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, 0x080c, 0x67b4, 0x2019, - 0x0001, 0xb85c, 0xd0ac, 0x0110, 0x2019, 0x0000, 0x2011, 0x801b, - 0x080c, 0x4ca1, 0x00ce, 0x00be, 0x003e, 0x002e, 0x001e, 0x0005, - 0x0026, 0x080c, 0x5840, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, - 0x4ca1, 0x002e, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x0126, 0x2091, - 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x779e, - 0x1158, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001, 0x080c, - 0x77e2, 0x080c, 0x76cd, 0x0010, 0x080c, 0x6058, 0x012e, 0x0804, - 0x368d, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x080c, - 0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x080c, 0x6c09, - 0x0120, 0x2009, 0x0008, 0x0804, 0x36bf, 0x2001, 0x180d, 0x2004, - 0xd08c, 0x0178, 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e, - 0x0140, 0x7984, 0x080c, 0x6c7f, 0x1120, 0x2009, 0x4009, 0x0804, - 0x36bf, 0x7984, 0x080c, 0x6749, 0x1904, 0x36c2, 0x080c, 0x4c74, - 0x0904, 0x36c2, 0x2b00, 0x7026, 0x080c, 0x6c11, 0x7888, 0x1170, - 0x9084, 0x0005, 0x1158, 0x900e, 0x080c, 0x6aae, 0x1108, 0xc185, - 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x368d, 0x080c, 0x4c41, - 0x0904, 0x36bf, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, - 0x080c, 0xd154, 0x0904, 0x36bf, 0x7888, 0xd094, 0x0118, 0xb8d4, - 0xc08d, 0xb8d6, 0x7007, 0x0003, 0x701f, 0x4f28, 0x0005, 0x2061, - 0x1800, 0x080c, 0x5854, 0x2009, 0x0007, 0x1560, 0x080c, 0x6c09, - 0x0118, 0x2009, 0x0008, 0x0430, 0xa998, 0x080c, 0x6749, 0x1530, - 0x080c, 0x4c72, 0x0518, 0x080c, 0x6c11, 0xa89c, 0x1168, 0x9084, - 0x0005, 0x1150, 0x900e, 0x080c, 0x6aae, 0x1108, 0xc185, 0xb800, - 0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868, 0xc0fc, 0xa86a, 0x080c, - 0xd154, 0x11e0, 0xa89c, 0xd094, 0x0118, 0xb8d4, 0xc08d, 0xb8d6, - 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, - 0xa99a, 0x9006, 0x918d, 0x0001, 0x2008, 0x0005, 0x9006, 0x0005, - 0xa830, 0x2009, 0x180d, 0x210c, 0xd18c, 0x0140, 0x2008, 0x918e, - 0xdead, 0x1120, 0x2021, 0x4009, 0x0804, 0x368f, 0x9086, 0x0100, - 0x7024, 0x2058, 0x1110, 0x0804, 0x578e, 0x900e, 0x080c, 0x6aae, - 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x368d, - 0x080c, 0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x7f84, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4c41, 0x1120, 0x2009, - 0x0002, 0x0804, 0x36bf, 0x900e, 0x2130, 0x7126, 0x7132, 0xa860, - 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0005, 0x702a, 0x20a0, 0x080c, - 0x67b4, 0x1904, 0x4fde, 0x080c, 0x6c11, 0x0138, 0x080c, 0x6c19, - 0x0120, 0x080c, 0x6bb1, 0x1904, 0x4fde, 0xd794, 0x1110, 0xd784, - 0x01a8, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x3400, - 0xd794, 0x0198, 0x20a9, 0x0008, 0x4003, 0x2098, 0x20a0, 0x3d00, - 0x20e0, 0x20a9, 0x0002, 0x080c, 0x4a10, 0x0080, 0xb8c4, 0x20e0, - 0xb8c8, 0x9080, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003, - 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x4a10, 0x9186, 0x007e, - 0x0170, 0x9186, 0x0080, 0x0158, 0x080c, 0x6c11, 0x90c2, 0x0006, - 0x1210, 0xc1fd, 0x0020, 0x080c, 0x6aae, 0x1108, 0xc1fd, 0x4104, - 0xc1fc, 0xd794, 0x0528, 0xb8c4, 0x20e0, 0xb8c8, 0x2060, 0x9c80, - 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, 0x9c80, 0x0003, 0x2098, - 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, 0x2098, 0x3400, 0x20a9, - 0x0002, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x4a03, - 0x9c80, 0x0026, 0x2098, 0xb8c4, 0x20e0, 0x20a9, 0x0002, 0x4003, - 0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, 0x080c, - 0xb094, 0x0118, 0x9186, 0x0800, 0x0040, 0xd78c, 0x0120, 0x9186, - 0x0800, 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118, - 0x9686, 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x4f67, - 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, 0x368d, 0x7033, 0x0001, - 0x7122, 0x7024, 0x9600, 0x7026, 0x772e, 0x2061, 0x18b8, 0x2c44, - 0xa06b, 0x0000, 0xa67a, 0x7034, 0xa072, 0x7028, 0xa076, 0xa28e, - 0xa392, 0xa496, 0xa59a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f, - 0x501a, 0x0005, 0x7030, 0x9005, 0x1180, 0x7120, 0x7028, 0x20a0, - 0x772c, 0x9036, 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, 0xa28c, - 0xa390, 0xa494, 0xa598, 0x0804, 0x4f67, 0x7124, 0x810b, 0x0804, - 0x368d, 0x2029, 0x007e, 0x7984, 0x7a88, 0x7b8c, 0x7c98, 0x9184, - 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, 0x0a04, - 0x36c2, 0x9184, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, - 0x0a04, 0x36c2, 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, - 0x36c2, 0x9502, 0x0a04, 0x36c2, 0x9284, 0x00ff, 0x90e2, 0x0020, - 0x0a04, 0x36c2, 0x9502, 0x0a04, 0x36c2, 0x9384, 0xff00, 0x8007, - 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, 0x0a04, 0x36c2, 0x9384, - 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, 0x0a04, 0x36c2, - 0x9484, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, - 0x0a04, 0x36c2, 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36c2, - 0x9502, 0x0a04, 0x36c2, 0x2061, 0x1989, 0x6102, 0x6206, 0x630a, - 0x640e, 0x0804, 0x368d, 0x080c, 0x4c41, 0x0904, 0x36bf, 0x2009, - 0x0016, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, - 0xaf60, 0x080c, 0x4c8a, 0x701f, 0x509e, 0x0005, 0x20a9, 0x0016, - 0x896e, 0x8d6e, 0x8d6f, 0x9d84, 0xffc0, 0x9080, 0x0019, 0x2098, - 0x9d84, 0x003f, 0x20e0, 0x2069, 0x1877, 0x20e9, 0x0001, 0x2da0, - 0x4003, 0x6800, 0x9005, 0x0904, 0x5105, 0x6804, 0x2008, 0x918c, - 0xfff8, 0x1904, 0x5105, 0x680c, 0x9005, 0x0904, 0x5105, 0x9082, - 0xff01, 0x1a04, 0x5105, 0x6810, 0x9082, 0x005c, 0x06f0, 0x6824, - 0x2008, 0x9082, 0x0008, 0x06c8, 0x9182, 0x0400, 0x16b0, 0x0056, - 0x2029, 0x0000, 0x080c, 0x9077, 0x005e, 0x6944, 0x6820, 0x9102, - 0x0660, 0x6820, 0x9082, 0x0019, 0x1640, 0x6828, 0x6944, 0x810c, - 0x9102, 0x0618, 0x6840, 0x9082, 0x000f, 0x12f8, 0x080c, 0x1072, - 0x2900, 0x0590, 0x684e, 0x00e6, 0x2071, 0x1931, 0x00b6, 0x2059, - 0x0000, 0x080c, 0x8f33, 0x00be, 0x00ee, 0x01e8, 0x080c, 0x8c78, - 0x080c, 0x8cc7, 0x1160, 0x6857, 0x0000, 0x00c6, 0x6b10, 0x2061, - 0x1a6e, 0x630e, 0x00ce, 0x0804, 0x368d, 0x0804, 0x36c2, 0x080c, - 0x8cc0, 0x00e6, 0x2071, 0x1931, 0x080c, 0x90f7, 0x080c, 0x9106, - 0x080c, 0x8f18, 0x00ee, 0x2001, 0x188a, 0x204c, 0x080c, 0x108b, - 0x2001, 0x188a, 0x2003, 0x0000, 0x0804, 0x36bf, 0x0126, 0x2091, - 0x8000, 0x080c, 0x94b8, 0x080c, 0x8cc0, 0x012e, 0x0804, 0x368d, - 0x0006, 0x080c, 0x5840, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x080c, - 0x5844, 0xd0bc, 0x000e, 0x0005, 0x6174, 0x7a84, 0x6300, 0x82ff, - 0x1118, 0x7986, 0x0804, 0x368d, 0x83ff, 0x1904, 0x36c2, 0x2001, - 0xfff0, 0x9200, 0x1a04, 0x36c2, 0x2019, 0xffff, 0x6078, 0x9302, - 0x9200, 0x0a04, 0x36c2, 0x7986, 0x6276, 0x0804, 0x368d, 0x080c, - 0x5854, 0x1904, 0x36bf, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, 0x080c, - 0x4c41, 0x0904, 0x36bf, 0x900e, 0x901e, 0x7326, 0x7332, 0xa860, - 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0003, 0x702a, 0x20a0, 0x91d8, - 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6c11, 0x0118, 0x080c, - 0x6c19, 0x1148, 0x20a9, 0x0001, 0xb814, 0x4004, 0xb810, 0x4004, - 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, - 0x003c, 0x0170, 0x0c20, 0x83ff, 0x1148, 0x7224, 0x900e, 0x2001, - 0x0003, 0x080c, 0x955b, 0x2208, 0x0804, 0x368d, 0x7033, 0x0001, - 0x7122, 0x7024, 0x9300, 0x7026, 0x2061, 0x18b8, 0x2c44, 0xa06b, - 0x0000, 0xa37a, 0x7028, 0xa076, 0x7034, 0xa072, 0xa48e, 0xa592, - 0xa696, 0xa79a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f, 0x51a9, - 0x0005, 0x7030, 0x9005, 0x1178, 0x7120, 0x7028, 0x20a0, 0x901e, - 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, 0xa48c, 0xa590, 0xa694, - 0xa798, 0x0804, 0x5167, 0x7224, 0x900e, 0x2001, 0x0003, 0x080c, - 0x955b, 0x2208, 0x0804, 0x368d, 0x00f6, 0x00e6, 0x080c, 0x5854, - 0x2009, 0x0007, 0x1904, 0x523c, 0x2071, 0x189e, 0x745c, 0x84ff, - 0x2009, 0x000e, 0x1904, 0x523c, 0xac9c, 0xad98, 0xaea4, 0xafa0, - 0x0096, 0x080c, 0x1072, 0x2009, 0x0002, 0x0904, 0x523c, 0x2900, - 0x705e, 0x900e, 0x901e, 0x7356, 0x7362, 0xa860, 0x7066, 0xa85c, - 0x9080, 0x0003, 0x705a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, 0x8bff, - 0x0178, 0x080c, 0x6c11, 0x0118, 0x080c, 0x6c19, 0x1148, 0xb814, - 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, - 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x01e8, 0x0c20, - 0x83ff, 0x11c0, 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x955b, - 0x2208, 0x009e, 0xa897, 0x4000, 0xa99a, 0x715c, 0x81ff, 0x090c, - 0x0d85, 0x2148, 0x080c, 0x108b, 0x9006, 0x705e, 0x918d, 0x0001, - 0x2008, 0x0418, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056, - 0x2061, 0x18b9, 0x2c44, 0xa37a, 0x7058, 0xa076, 0x7064, 0xa072, - 0xa48e, 0xa592, 0xa696, 0xa79a, 0xa09f, 0x5248, 0x000e, 0xa0a2, - 0x080c, 0x114e, 0x9006, 0x0048, 0x009e, 0xa897, 0x4005, 0xa99a, - 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ee, 0x00fe, 0x0005, - 0x00f6, 0xa0a0, 0x904d, 0x090c, 0x0d85, 0x00e6, 0x2071, 0x189e, - 0xa06c, 0x908e, 0x0100, 0x0138, 0xa87b, 0x0030, 0xa883, 0x0000, - 0xa897, 0x4002, 0x00d8, 0x7060, 0x9005, 0x1158, 0x7150, 0x7058, - 0x20a0, 0x901e, 0x7064, 0x20e8, 0xa48c, 0xa590, 0xa694, 0xa798, - 0x0428, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x7254, - 0x900e, 0x2001, 0x0003, 0x080c, 0x955b, 0xaa9a, 0x715c, 0x81ff, - 0x090c, 0x0d85, 0x2148, 0x080c, 0x108b, 0x705f, 0x0000, 0xa0a0, - 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0xa09f, - 0x0000, 0xa0a3, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91d8, 0x1000, - 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6c11, 0x0118, 0x080c, 0x6c19, - 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, - 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, - 0x0518, 0x0c20, 0x83ff, 0x11f0, 0x7154, 0x810c, 0xa99a, 0xa897, - 0x4000, 0x715c, 0x81ff, 0x090c, 0x0d85, 0x2148, 0x080c, 0x108b, - 0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0xa0a0, 0x2048, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0xa09f, 0x0000, 0xa0a3, - 0x0000, 0x0070, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056, - 0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x114e, 0x9006, - 0x00ee, 0x0005, 0x0096, 0xa88c, 0x90be, 0x7000, 0x0148, 0x90be, - 0x7100, 0x0130, 0x90be, 0x7200, 0x0118, 0x009e, 0x0804, 0x36c2, - 0xa884, 0xa988, 0x080c, 0x268c, 0x1518, 0x080c, 0x6749, 0x1500, - 0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c, 0x4c41, 0x01c8, 0x080c, - 0x4c41, 0x01b0, 0x009e, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, - 0xa823, 0x0000, 0xa804, 0x2048, 0x080c, 0xd0cd, 0x1120, 0x2009, - 0x0003, 0x0804, 0x36bf, 0x7007, 0x0003, 0x701f, 0x5315, 0x0005, - 0x009e, 0x2009, 0x0002, 0x0804, 0x36bf, 0x7124, 0x080c, 0x341e, - 0xa820, 0x9086, 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, 0x36bf, - 0x2900, 0x7022, 0xa804, 0x0096, 0x2048, 0x8906, 0x8006, 0x8007, - 0x90bc, 0x003f, 0x9084, 0xffc0, 0x009e, 0x9080, 0x0002, 0x0076, - 0x0006, 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, - 0x0fd6, 0xaa6c, 0xab70, 0xac74, 0xad78, 0x2061, 0x18b8, 0x2c44, - 0xa06b, 0x0000, 0xae64, 0xaf8c, 0x97c6, 0x7000, 0x0118, 0x97c6, - 0x7100, 0x1148, 0x96c2, 0x0004, 0x0600, 0x2009, 0x0004, 0x000e, - 0x007e, 0x0804, 0x4c8d, 0x97c6, 0x7200, 0x11b8, 0x96c2, 0x0054, - 0x02a0, 0x000e, 0x007e, 0x2061, 0x18b8, 0x2c44, 0xa076, 0xa772, - 0xa07b, 0x002a, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x114e, - 0x7007, 0x0002, 0x701f, 0x5371, 0x0005, 0x000e, 0x007e, 0x0804, - 0x36c2, 0x7020, 0x2048, 0xa804, 0x2048, 0xa804, 0x2048, 0x8906, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, 0x0fd6, - 0x2100, 0x2238, 0x2061, 0x18b8, 0x2c44, 0xa28c, 0xa390, 0xa494, - 0xa598, 0x2009, 0x002a, 0x0804, 0x4c8d, 0x81ff, 0x1904, 0x36bf, - 0x798c, 0x2001, 0x197e, 0x918c, 0x8000, 0x2102, 0x080c, 0x4c58, - 0x0904, 0x36c2, 0x080c, 0x6c11, 0x0120, 0x080c, 0x6c19, 0x1904, - 0x36c2, 0x080c, 0x687b, 0x0904, 0x36bf, 0x0126, 0x2091, 0x8000, - 0x080c, 0x6a1b, 0x012e, 0x0904, 0x36bf, 0x2001, 0x197e, 0x2004, - 0xd0fc, 0x1904, 0x368d, 0x0804, 0x46aa, 0xa9a0, 0x2001, 0x197e, - 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4c65, 0x01a0, 0x080c, - 0x6c11, 0x0118, 0x080c, 0x6c19, 0x1170, 0x080c, 0x687b, 0x2009, - 0x0002, 0x0128, 0x080c, 0x6a1b, 0x1170, 0x2009, 0x0003, 0xa897, - 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, - 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x197e, 0x2004, - 0xd0fc, 0x1128, 0x080c, 0x5848, 0x0110, 0x9006, 0x0018, 0x900e, - 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x78a8, 0xd08c, 0x1118, - 0xd084, 0x0904, 0x461f, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x080c, - 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0x080c, 0x6c11, - 0x0130, 0x908e, 0x0004, 0x0118, 0x908e, 0x0005, 0x15a0, 0x78a8, - 0xd08c, 0x0120, 0xb800, 0xc08c, 0xb802, 0x0028, 0x080c, 0x5840, - 0xd0b4, 0x0904, 0x4659, 0x7884, 0x908e, 0x007e, 0x0904, 0x4659, - 0x908e, 0x007f, 0x0904, 0x4659, 0x908e, 0x0080, 0x0904, 0x4659, - 0xb800, 0xd08c, 0x1904, 0x4659, 0xa867, 0x0000, 0xa868, 0xc0fd, - 0xa86a, 0x080c, 0xd0ec, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, - 0x7007, 0x0003, 0x701f, 0x543d, 0x0005, 0x080c, 0x4c74, 0x0904, - 0x36c2, 0x0804, 0x4659, 0x080c, 0x347d, 0x0108, 0x0005, 0x2009, - 0x1834, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, - 0x080c, 0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x080c, - 0x6c09, 0x0120, 0x2009, 0x0008, 0x0804, 0x36bf, 0xb89c, 0xd0a4, - 0x1118, 0xd0ac, 0x1904, 0x4659, 0x9006, 0xa866, 0xa832, 0xa868, - 0xc0fd, 0xa86a, 0x080c, 0xd154, 0x1120, 0x2009, 0x0003, 0x0804, - 0x36bf, 0x7007, 0x0003, 0x701f, 0x5476, 0x0005, 0xa830, 0x9086, - 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x578e, 0x080c, 0x4c74, - 0x0904, 0x36c2, 0x0804, 0x540f, 0x81ff, 0x2009, 0x0001, 0x1904, - 0x36bf, 0x080c, 0x5854, 0x2009, 0x0007, 0x1904, 0x36bf, 0x080c, - 0x6c09, 0x0120, 0x2009, 0x0008, 0x0804, 0x36bf, 0x080c, 0x4c74, - 0x0904, 0x36c2, 0x080c, 0x6c11, 0x2009, 0x0009, 0x1904, 0x36bf, - 0x080c, 0x4c41, 0x2009, 0x0002, 0x0904, 0x36bf, 0x9006, 0xa866, - 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x7988, 0xa95a, 0x9194, 0xfd00, - 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, 0xc0ed, 0xa952, 0x798c, - 0xa956, 0x0038, 0x928e, 0x0100, 0x1904, 0x36c2, 0xc0e5, 0xa952, - 0xa956, 0xa83e, 0x080c, 0xd3b7, 0x2009, 0x0003, 0x0904, 0x36bf, - 0x7007, 0x0003, 0x701f, 0x54cd, 0x0005, 0xa830, 0x9086, 0x0100, - 0x2009, 0x0004, 0x0904, 0x36bf, 0x0804, 0x368d, 0x7aa8, 0x9284, - 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, 0x5854, 0x1188, 0x2009, - 0x0014, 0x0804, 0x36bf, 0xd2dc, 0x1578, 0x81ff, 0x2009, 0x0001, - 0x1904, 0x36bf, 0x080c, 0x5854, 0x2009, 0x0007, 0x1904, 0x36bf, - 0xd2f4, 0x0138, 0x9284, 0x5000, 0xc0d5, 0x080c, 0x581a, 0x0804, - 0x368d, 0xd2fc, 0x0160, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x7984, - 0x9284, 0x9000, 0xc0d5, 0x080c, 0x57e9, 0x0804, 0x368d, 0x080c, - 0x4c74, 0x0904, 0x36c2, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x2009, 0x0009, 0x1904, 0x55bc, 0x080c, 0x4c41, 0x2009, 0x0002, - 0x0904, 0x55bc, 0xa85c, 0x9080, 0x001b, 0xaf60, 0x2009, 0x0008, - 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4c8a, 0x701f, 0x5529, - 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, 0xa870, 0x9005, 0x1120, - 0xa874, 0x9084, 0xff00, 0x0110, 0x1904, 0x36c2, 0xa866, 0xa832, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x4c74, 0x1110, 0x0804, 0x36c2, - 0x2009, 0x0043, 0x080c, 0xd423, 0x2009, 0x0003, 0x0904, 0x55bc, - 0x7007, 0x0003, 0x701f, 0x554d, 0x0005, 0xa830, 0x9086, 0x0100, - 0x2009, 0x0004, 0x0904, 0x55bc, 0x7984, 0x7aa8, 0x9284, 0x1000, - 0xc0d5, 0x080c, 0x57e9, 0x0804, 0x368d, 0x00c6, 0xaab0, 0x9284, - 0xc000, 0x0148, 0xd2ec, 0x0170, 0x080c, 0x5854, 0x1158, 0x2009, - 0x0014, 0x0804, 0x55ab, 0x2061, 0x1800, 0x080c, 0x5854, 0x2009, - 0x0007, 0x15c8, 0xd2f4, 0x0130, 0x9284, 0x5000, 0xc0d5, 0x080c, - 0x581a, 0x0058, 0xd2fc, 0x0180, 0x080c, 0x4c72, 0x0590, 0xa998, - 0x9284, 0x9000, 0xc0d5, 0x080c, 0x57e9, 0xa87b, 0x0000, 0xa883, - 0x0000, 0xa897, 0x4000, 0x0438, 0x080c, 0x4c72, 0x0510, 0x080c, - 0x6c11, 0x2009, 0x0009, 0x11b8, 0xa8c4, 0x9086, 0x0500, 0x11c8, - 0xa8c8, 0x9005, 0x11b0, 0xa8cc, 0x9084, 0xff00, 0x1190, 0x080c, - 0x4c72, 0x1108, 0x0070, 0x2009, 0x004b, 0x080c, 0xd423, 0x2009, - 0x0003, 0x0108, 0x0078, 0x0431, 0x19c0, 0xa897, 0x4005, 0xa99a, - 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, - 0x00ce, 0x0005, 0x9006, 0x0ce0, 0x7aa8, 0xd2dc, 0x0904, 0x36bf, - 0x0016, 0x7984, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x57e9, 0x001e, - 0x1904, 0x36bf, 0x0804, 0x368d, 0x00f6, 0x2d78, 0xaab0, 0x0021, - 0x00fe, 0x0005, 0xaab0, 0xc2d5, 0xd2dc, 0x0150, 0x0016, 0xa998, - 0x9284, 0x1400, 0xc0fd, 0x080c, 0x57e9, 0x001e, 0x9085, 0x0001, - 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x080c, - 0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x7984, 0x7ea8, - 0x96b4, 0x00ff, 0x080c, 0x67b4, 0x1904, 0x36c2, 0x9186, 0x007f, - 0x0138, 0x080c, 0x6c11, 0x0120, 0x2009, 0x0009, 0x0804, 0x36bf, - 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0xa867, - 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, 0x0100, 0x8007, 0xa80a, - 0x080c, 0xd106, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, 0x7007, - 0x0003, 0x701f, 0x561c, 0x0005, 0xa808, 0x8007, 0x9086, 0x0100, - 0x1120, 0x2009, 0x0004, 0x0804, 0x36bf, 0xa8e0, 0xa866, 0xa810, - 0x8007, 0x9084, 0x00ff, 0x800c, 0xa814, 0x8007, 0x9084, 0x00ff, - 0x8004, 0x9080, 0x0002, 0x9108, 0x8906, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x0004, 0x7a8c, 0x7b88, 0x7c9c, - 0x7d98, 0x0804, 0x4c8d, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, - 0x0804, 0x36bf, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, - 0x82ff, 0x1118, 0x7023, 0x19b4, 0x0040, 0x92c6, 0x0001, 0x1118, - 0x7023, 0x19ce, 0x0010, 0x0804, 0x36c2, 0x2009, 0x001a, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, - 0x4c8a, 0x701f, 0x566c, 0x0005, 0x2001, 0x182e, 0x2003, 0x0001, - 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, 0x20e0, 0x20a9, 0x001a, - 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, 0x0804, 0x368d, 0x080c, - 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0x7984, 0x9194, - 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x2099, 0x19b4, - 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, 0x19ce, 0x0010, 0x0804, - 0x36c2, 0xa85c, 0x9080, 0x0019, 0x20a0, 0xa860, 0x20e8, 0x20a9, - 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, 0x7a8c, 0x7b88, - 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x0804, 0x4c8d, - 0x7884, 0x908a, 0x1000, 0x1a04, 0x36c2, 0x0126, 0x2091, 0x8000, - 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, 0x1a04, 0x614a, - 0x00ce, 0x012e, 0x0804, 0x368d, 0x00c6, 0x080c, 0x779e, 0x1160, - 0x080c, 0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001, 0x080c, 0x77e2, - 0x080c, 0x76cd, 0x080c, 0x0d85, 0x2061, 0x1800, 0x6030, 0xc09d, - 0x6032, 0x080c, 0x6058, 0x00ce, 0x0005, 0x00c6, 0x2001, 0x1800, - 0x2004, 0x908e, 0x0000, 0x0904, 0x36bf, 0x7884, 0x9005, 0x0188, - 0x7888, 0x2061, 0x199c, 0x2c0c, 0x2062, 0x080c, 0x2a67, 0x01a0, - 0x080c, 0x2a6f, 0x0188, 0x080c, 0x2a77, 0x0170, 0x2162, 0x0804, - 0x36c2, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, 0x2009, - 0x0001, 0x0010, 0x2009, 0x0000, 0x7884, 0x9086, 0x0002, 0x15a8, - 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, 0x080c, 0xacfc, 0x0026, - 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, 0xa635, - 0x002e, 0x080c, 0xa516, 0x0036, 0x901e, 0x080c, 0xa596, 0x003e, - 0x080c, 0xad18, 0x60e3, 0x0000, 0x080c, 0xeed9, 0x080c, 0xeef4, - 0x9085, 0x0001, 0x080c, 0x77e2, 0x9006, 0x080c, 0x2a99, 0x2001, - 0x1800, 0x2003, 0x0004, 0x2001, 0x19a8, 0x2003, 0x0000, 0x0026, - 0x2011, 0x0008, 0x080c, 0x2ad3, 0x002e, 0x00ce, 0x0804, 0x368d, - 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x080c, 0x5854, - 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x7984, 0x7ea8, 0x96b4, - 0x00ff, 0x080c, 0x67b4, 0x1904, 0x36c2, 0x9186, 0x007f, 0x0138, - 0x080c, 0x6c11, 0x0120, 0x2009, 0x0009, 0x0804, 0x36bf, 0x080c, - 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0xa867, 0x0000, - 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd109, 0x1120, 0x2009, 0x0003, - 0x0804, 0x36bf, 0x7007, 0x0003, 0x701f, 0x5777, 0x0005, 0xa830, - 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x36bf, 0xa8e0, - 0xa866, 0xa834, 0x8007, 0x800c, 0xa85c, 0x9080, 0x000c, 0x7a8c, - 0x7b88, 0x7c9c, 0x7d98, 0xaf60, 0x0804, 0x4c8d, 0xa898, 0x9086, - 0x000d, 0x1904, 0x36bf, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000, - 0x0e04, 0x579b, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000, - 0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, 0x4005, - 0xa998, 0x7986, 0xa9a4, 0x799a, 0xa9a8, 0x799e, 0x080c, 0x4c7d, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, - 0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, - 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x1a04, 0x7984, 0x615a, - 0x6156, 0x605f, 0x0000, 0x6053, 0x0009, 0x7898, 0x6072, 0x789c, - 0x606e, 0x7888, 0x606a, 0x788c, 0x6066, 0x2001, 0x1a14, 0x2044, - 0x2001, 0x1a1b, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, 0xa07f, - 0x0002, 0xa06b, 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, 0x0804, - 0x368d, 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, 0xc000, - 0x0198, 0x0006, 0xd0d4, 0x0160, 0x0036, 0x2019, 0x0029, 0x080c, - 0xacfc, 0x0106, 0x080c, 0x3442, 0x010e, 0x090c, 0xad18, 0x003e, - 0x080c, 0xcf68, 0x000e, 0x1198, 0xd0e4, 0x0160, 0x9180, 0x1000, - 0x2004, 0x905d, 0x0160, 0x080c, 0x61b7, 0x080c, 0xb094, 0x0110, - 0xb817, 0x0000, 0x9006, 0x00ce, 0x00be, 0x012e, 0x0005, 0x9085, - 0x0001, 0x0cc8, 0x0126, 0x2091, 0x8000, 0x0156, 0x2010, 0x900e, - 0x20a9, 0x0800, 0x0016, 0x9180, 0x1000, 0x2004, 0x9005, 0x0188, - 0x9186, 0x007e, 0x0170, 0x9186, 0x007f, 0x0158, 0x9186, 0x0080, - 0x0140, 0x9186, 0x00ff, 0x0128, 0x0026, 0x2200, 0x080c, 0x57e9, - 0x002e, 0x001e, 0x8108, 0x1f04, 0x5822, 0x015e, 0x012e, 0x0005, - 0x2001, 0x1848, 0x2004, 0x0005, 0x2001, 0x1867, 0x2004, 0x0005, - 0x0006, 0x2001, 0x1810, 0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001, - 0x180e, 0x2004, 0xd0b4, 0x0005, 0x2001, 0x1800, 0x2004, 0x9086, - 0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, 0x189e, 0x7108, 0x910d, - 0x710a, 0x00ee, 0x001e, 0x0005, 0x79a4, 0x81ff, 0x0904, 0x36c2, - 0x9182, 0x0081, 0x1a04, 0x36c2, 0x810c, 0x0016, 0x080c, 0x4c41, - 0x0170, 0x080c, 0x0f61, 0x2100, 0x2238, 0x7d84, 0x7c88, 0x7b8c, - 0x7a90, 0x001e, 0x080c, 0x4c8a, 0x701f, 0x5884, 0x0005, 0x001e, - 0x2009, 0x0002, 0x0804, 0x36bf, 0x2079, 0x0000, 0x7d94, 0x7c98, - 0x7ba8, 0x7aac, 0x79a4, 0x810c, 0x2061, 0x18b8, 0x2c44, 0xa770, - 0xa074, 0x2071, 0x189e, 0x080c, 0x4c8d, 0x701f, 0x5898, 0x0005, - 0x2061, 0x18b8, 0x2c44, 0x0016, 0x0026, 0xa270, 0xa174, 0x080c, - 0x0f69, 0x002e, 0x001e, 0x080c, 0x1016, 0x9006, 0xa802, 0xa806, - 0x0804, 0x368d, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, - 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, - 0x2071, 0x1800, 0x6044, 0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c, - 0x5a58, 0x0068, 0xd08c, 0x0118, 0x080c, 0x5961, 0x0040, 0xd094, - 0x0118, 0x080c, 0x5931, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, - 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, - 0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, - 0x001e, 0x0c68, 0x7030, 0xd09c, 0x1120, 0x6004, 0x9085, 0x0002, - 0x6006, 0x7098, 0x9005, 0x0120, 0x709b, 0x0000, 0x7093, 0x0000, - 0x624c, 0x9286, 0xf0f0, 0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130, - 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0x9294, 0xff00, - 0x9296, 0xf700, 0x0178, 0x7138, 0xd1a4, 0x1160, 0x6240, 0x9295, - 0x0100, 0x6242, 0x9294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, - 0x6119, 0x00f0, 0x6040, 0x9084, 0x0010, 0x9085, 0x0140, 0x6042, - 0x6043, 0x0000, 0x7087, 0x0000, 0x70a3, 0x0001, 0x70c7, 0x0000, - 0x70df, 0x0000, 0x2009, 0x1d80, 0x200b, 0x0000, 0x7097, 0x0000, - 0x708b, 0x000f, 0x2009, 0x000f, 0x2011, 0x5ffb, 0x080c, 0x8a5d, - 0x0005, 0x2001, 0x1869, 0x2004, 0xd08c, 0x0110, 0x705f, 0xffff, - 0x7088, 0x9005, 0x1528, 0x2011, 0x5ffb, 0x080c, 0x8993, 0x6040, - 0x9094, 0x0010, 0x9285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, - 0xd08c, 0x1168, 0x1f04, 0x5947, 0x6242, 0x709b, 0x0000, 0x6040, - 0x9094, 0x0010, 0x9285, 0x0080, 0x6042, 0x6242, 0x0048, 0x6242, - 0x709b, 0x0000, 0x708f, 0x0000, 0x9006, 0x080c, 0x61a2, 0x0000, - 0x0005, 0x708c, 0x908a, 0x0003, 0x1a0c, 0x0d85, 0x000b, 0x0005, - 0x596b, 0x59bc, 0x5a57, 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, - 0x708f, 0x0001, 0x2001, 0x015d, 0x2003, 0x0000, 0x6803, 0x00fc, - 0x20a9, 0x0004, 0x6800, 0x9084, 0x00fc, 0x0120, 0x1f04, 0x597a, - 0x080c, 0x0d85, 0x68a0, 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, - 0xa001, 0x918d, 0x1600, 0x6902, 0x001e, 0x6837, 0x0020, 0x080c, - 0x617e, 0x2079, 0x1d00, 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, - 0x0001, 0x2099, 0x1805, 0x20e9, 0x0001, 0x20a1, 0x1d0e, 0x20a9, - 0x0004, 0x4003, 0x080c, 0xaaf1, 0x20e1, 0x0001, 0x2099, 0x1d00, - 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, - 0x000c, 0x600f, 0x0000, 0x080c, 0x602c, 0x00fe, 0x9006, 0x7092, - 0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, 0x7090, 0x7093, 0x0000, - 0x9025, 0x0904, 0x5a34, 0x6020, 0xd0b4, 0x1904, 0x5a32, 0x71a0, - 0x81ff, 0x0904, 0x5a20, 0x9486, 0x000c, 0x1904, 0x5a2d, 0x9480, - 0x0018, 0x8004, 0x20a8, 0x080c, 0x6177, 0x2011, 0x0260, 0x2019, - 0x1d00, 0x220c, 0x2304, 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, - 0x59d9, 0x6043, 0x0004, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, - 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, 0x708f, 0x0002, 0x709b, - 0x0002, 0x2009, 0x07d0, 0x2011, 0x6002, 0x080c, 0x8a5d, 0x080c, - 0x617e, 0x04c0, 0x080c, 0x6177, 0x2079, 0x0260, 0x7930, 0x918e, - 0x1101, 0x1558, 0x7834, 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, - 0x1118, 0x7804, 0x9005, 0x0190, 0x080c, 0x6177, 0x2011, 0x026e, - 0x2019, 0x1805, 0x20a9, 0x0004, 0x220c, 0x2304, 0x9102, 0x0230, - 0x11a0, 0x8210, 0x8318, 0x1f04, 0x5a14, 0x0078, 0x70a3, 0x0000, - 0x080c, 0x6177, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, - 0x20a1, 0x1d00, 0x20a9, 0x0014, 0x4003, 0x6043, 0x0008, 0x6043, - 0x0000, 0x0010, 0x00fe, 0x0005, 0x6040, 0x9085, 0x0100, 0x6042, - 0x6020, 0xd0b4, 0x1db8, 0x080c, 0xaaf1, 0x20e1, 0x0001, 0x2099, - 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, - 0x60c3, 0x000c, 0x2011, 0x19f5, 0x2013, 0x0000, 0x7093, 0x0000, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0xa293, 0x08d8, 0x0005, - 0x7098, 0x908a, 0x001d, 0x1a0c, 0x0d85, 0x000b, 0x0005, 0x5a89, - 0x5a9c, 0x5ac5, 0x5ae5, 0x5b0b, 0x5b3a, 0x5b60, 0x5b98, 0x5bbe, - 0x5bec, 0x5c27, 0x5c5f, 0x5c7d, 0x5ca8, 0x5cca, 0x5ce5, 0x5cef, - 0x5d23, 0x5d49, 0x5d78, 0x5d9e, 0x5dd6, 0x5e1a, 0x5e57, 0x5e78, - 0x5ed1, 0x5ef3, 0x5f21, 0x5f21, 0x00c6, 0x2061, 0x1800, 0x6003, - 0x0007, 0x2061, 0x0100, 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, - 0x0005, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, - 0x0100, 0x6043, 0x0002, 0x709b, 0x0001, 0x2009, 0x07d0, 0x2011, - 0x6002, 0x080c, 0x8a5d, 0x0005, 0x00f6, 0x7090, 0x9086, 0x0014, - 0x1510, 0x6042, 0x6020, 0xd0b4, 0x11f0, 0x080c, 0x6177, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, - 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, - 0x2011, 0x6002, 0x080c, 0x8993, 0x709b, 0x0010, 0x080c, 0x5cef, - 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0003, - 0x6043, 0x0004, 0x2011, 0x6002, 0x080c, 0x8993, 0x080c, 0x60fb, - 0x2079, 0x0240, 0x7833, 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, - 0x9f88, 0x000e, 0x200b, 0x0000, 0x8108, 0x1f04, 0x5ada, 0x60c3, - 0x0014, 0x080c, 0x602c, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, - 0x0500, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, 0x0014, 0x11b8, - 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, - 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, - 0x1110, 0x70c7, 0x0001, 0x709b, 0x0004, 0x0029, 0x0010, 0x080c, - 0x6153, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0005, 0x080c, 0x60fb, - 0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x6177, - 0x080c, 0x615a, 0x1170, 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, - 0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5faf, 0x0168, 0x080c, - 0x6130, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, - 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c, - 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x6002, - 0x080c, 0x8993, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6177, 0x2079, - 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, - 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, - 0x709b, 0x0006, 0x0029, 0x0010, 0x080c, 0x6153, 0x00fe, 0x0005, - 0x00f6, 0x709b, 0x0007, 0x080c, 0x60fb, 0x2079, 0x0240, 0x7833, - 0x1104, 0x7837, 0x0000, 0x080c, 0x6177, 0x080c, 0x615a, 0x11b8, - 0x7084, 0x9005, 0x11a0, 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, - 0x348e, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, - 0x5faf, 0x0180, 0x080c, 0x512e, 0x0110, 0x080c, 0x26f5, 0x20a9, - 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c, 0x00fe, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x6002, 0x080c, 0x8993, - 0x9086, 0x0014, 0x11b8, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0008, - 0x0029, 0x0010, 0x080c, 0x6153, 0x00fe, 0x0005, 0x00f6, 0x709b, - 0x0009, 0x080c, 0x60fb, 0x2079, 0x0240, 0x7833, 0x1105, 0x7837, - 0x0100, 0x080c, 0x615a, 0x1150, 0x7084, 0x9005, 0x1138, 0x080c, - 0x5f22, 0x1188, 0x9085, 0x0001, 0x080c, 0x26f5, 0x20a9, 0x0008, - 0x080c, 0x6177, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c, 0x0010, - 0x080c, 0x5a7c, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x05a8, - 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, 0x0014, 0x1560, 0x080c, - 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1520, 0x7834, - 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x000a, - 0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c4, - 0x9005, 0x1110, 0x70c7, 0x0001, 0x7097, 0x0000, 0x709b, 0x000e, - 0x080c, 0x5cca, 0x0010, 0x080c, 0x6153, 0x00fe, 0x0005, 0x00f6, - 0x709b, 0x000b, 0x2011, 0x1d0e, 0x20e9, 0x0001, 0x22a0, 0x20a9, - 0x0040, 0x2019, 0xffff, 0x4304, 0x080c, 0x60fb, 0x2079, 0x0240, - 0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x615a, 0x0118, 0x2013, - 0x0000, 0x0020, 0x7060, 0x9085, 0x0100, 0x2012, 0x20a9, 0x0040, - 0x2009, 0x024e, 0x2011, 0x1d0e, 0x220e, 0x8210, 0x8108, 0x9186, - 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, - 0x5c4c, 0x60c3, 0x0084, 0x080c, 0x602c, 0x00fe, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x01c0, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, - 0x0084, 0x1178, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1106, 0x1138, 0x7834, 0x9005, 0x1120, 0x709b, 0x000c, 0x0029, - 0x0010, 0x080c, 0x6153, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000d, - 0x080c, 0x60fb, 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, 0x0000, - 0x080c, 0x6177, 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, 0x024e, - 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, - 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, - 0x1f04, 0x5c90, 0x60c3, 0x0084, 0x080c, 0x602c, 0x00fe, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x01e0, 0x2011, 0x6002, 0x080c, 0x8993, - 0x9086, 0x0084, 0x1198, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, - 0x080c, 0x60cd, 0x709b, 0x000e, 0x0029, 0x0010, 0x080c, 0x6153, - 0x00fe, 0x0005, 0x918d, 0x0001, 0x080c, 0x61a2, 0x709b, 0x000f, - 0x7093, 0x0000, 0x2061, 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, - 0x2061, 0x0100, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, - 0x2011, 0x6002, 0x080c, 0x8987, 0x0005, 0x7090, 0x9005, 0x0130, - 0x2011, 0x6002, 0x080c, 0x8993, 0x709b, 0x0000, 0x0005, 0x709b, - 0x0011, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x20e1, 0x0000, 0x2099, - 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x7490, 0x9480, 0x0018, - 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, - 0x615a, 0x11a0, 0x717c, 0x81ff, 0x0188, 0x900e, 0x7080, 0x9084, - 0x00ff, 0x0160, 0x080c, 0x268c, 0x9186, 0x007e, 0x0138, 0x9186, - 0x0080, 0x0120, 0x2011, 0x0008, 0x080c, 0x5faf, 0x60c3, 0x0014, - 0x080c, 0x602c, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, - 0x6002, 0x080c, 0x8993, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6177, - 0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, - 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, - 0x0001, 0x709b, 0x0012, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, - 0x0005, 0x00f6, 0x709b, 0x0013, 0x080c, 0x6109, 0x2079, 0x0240, - 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x6177, 0x080c, 0x615a, - 0x1170, 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, - 0x2011, 0x0008, 0x080c, 0x5faf, 0x0168, 0x080c, 0x6130, 0x20a9, - 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c, 0x00fe, 0x0005, - 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x6002, 0x080c, 0x8993, - 0x9086, 0x0014, 0x11b8, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, - 0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, - 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0014, - 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, - 0x0015, 0x080c, 0x6109, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, - 0x0000, 0x080c, 0x6177, 0x080c, 0x615a, 0x11b8, 0x7084, 0x9005, - 0x11a0, 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, 0x348e, 0x200d, - 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5faf, 0x0180, - 0x080c, 0x512e, 0x0110, 0x080c, 0x26f5, 0x20a9, 0x0008, 0x20e1, - 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, - 0x60c3, 0x0014, 0x080c, 0x602c, 0x00fe, 0x0005, 0x00f6, 0x7090, - 0x9005, 0x05f0, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, 0x0014, - 0x15a8, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, - 0x1568, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1168, - 0x9085, 0x0001, 0x080c, 0x61a2, 0x7a38, 0xd2fc, 0x0128, 0x70c4, - 0x9005, 0x1110, 0x70c7, 0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38, - 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x9085, - 0x0001, 0x080c, 0x61a2, 0x7097, 0x0000, 0x7a38, 0xd2f4, 0x0110, - 0x70df, 0x0008, 0x709b, 0x0016, 0x0029, 0x0010, 0x7093, 0x0000, - 0x00fe, 0x0005, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x20e1, 0x0000, - 0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, - 0x4003, 0x2011, 0x026d, 0x2204, 0x9084, 0x0100, 0x2011, 0x024d, - 0x2012, 0x2011, 0x026e, 0x709b, 0x0017, 0x080c, 0x615a, 0x1150, - 0x7084, 0x9005, 0x1138, 0x080c, 0x5f22, 0x1188, 0x9085, 0x0001, - 0x080c, 0x26f5, 0x20a9, 0x0008, 0x080c, 0x6177, 0x20e1, 0x0000, - 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, - 0x0014, 0x080c, 0x602c, 0x0010, 0x080c, 0x5a7c, 0x0005, 0x00f6, - 0x7090, 0x9005, 0x01d8, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, - 0x0084, 0x1190, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, - 0x1106, 0x1150, 0x7834, 0x9005, 0x1138, 0x9006, 0x080c, 0x61a2, - 0x709b, 0x0018, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, - 0x00f6, 0x709b, 0x0019, 0x080c, 0x6109, 0x2079, 0x0240, 0x7833, - 0x1106, 0x7837, 0x0000, 0x080c, 0x6177, 0x2009, 0x026e, 0x2039, - 0x1d0e, 0x20a9, 0x0040, 0x213e, 0x8738, 0x8108, 0x9186, 0x0280, - 0x1128, 0x6814, 0x8000, 0x6816, 0x2009, 0x0260, 0x1f04, 0x5e8b, - 0x2039, 0x1d0e, 0x080c, 0x615a, 0x11e8, 0x2728, 0x2514, 0x8207, - 0x9084, 0x00ff, 0x8000, 0x2018, 0x9294, 0x00ff, 0x8007, 0x9205, - 0x202a, 0x7060, 0x2310, 0x8214, 0x92a0, 0x1d0e, 0x2414, 0x938c, - 0x0001, 0x0118, 0x9294, 0xff00, 0x0018, 0x9294, 0x00ff, 0x8007, - 0x9215, 0x2222, 0x20a9, 0x0040, 0x2009, 0x024e, 0x270e, 0x8738, - 0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, - 0x0240, 0x1f04, 0x5ebe, 0x60c3, 0x0084, 0x080c, 0x602c, 0x00fe, - 0x0005, 0x00f6, 0x7090, 0x9005, 0x01e0, 0x2011, 0x6002, 0x080c, - 0x8993, 0x9086, 0x0084, 0x1198, 0x080c, 0x6177, 0x2079, 0x0260, - 0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x7097, - 0x0001, 0x080c, 0x60cd, 0x709b, 0x001a, 0x0029, 0x0010, 0x7093, - 0x0000, 0x00fe, 0x0005, 0x9085, 0x0001, 0x080c, 0x61a2, 0x709b, - 0x001b, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x2011, 0x0260, 0x2009, - 0x0240, 0x7490, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, - 0x8004, 0x20a8, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, - 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, - 0x2011, 0x0260, 0x1f04, 0x5f0a, 0x60c3, 0x0084, 0x080c, 0x602c, - 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x1848, 0x252c, 0x20a9, - 0x0008, 0x2041, 0x1d0e, 0x20e9, 0x0001, 0x28a0, 0x080c, 0x6177, - 0x20e1, 0x0000, 0x2099, 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, - 0x0007, 0xd5d4, 0x0108, 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, - 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, - 0x5f3c, 0x0804, 0x5fab, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, - 0x3fff, 0x0d90, 0x0020, 0x91a6, 0x3fff, 0x0904, 0x5fab, 0x918d, - 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, - 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240, - 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x5f62, 0x04d8, - 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x5f74, 0x2328, - 0x8529, 0x92be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200, - 0x973a, 0x000e, 0x27a8, 0x95a8, 0x0010, 0x1f04, 0x5f83, 0x755e, - 0x95c8, 0x348e, 0x292d, 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, - 0x0016, 0x2508, 0x080c, 0x26d5, 0x001e, 0x60e7, 0x0000, 0x65ea, - 0x2018, 0x2304, 0x9405, 0x201a, 0x7087, 0x0001, 0x20e9, 0x0000, - 0x20a1, 0x024e, 0x20e1, 0x0001, 0x2898, 0x20a9, 0x0008, 0x4003, - 0x9085, 0x0001, 0x0008, 0x9006, 0x009e, 0x008e, 0x0005, 0x0156, - 0x01c6, 0x01d6, 0x0136, 0x0146, 0x22a8, 0x20e1, 0x0000, 0x2099, - 0x026e, 0x20e9, 0x0000, 0x2011, 0x024e, 0x22a0, 0x4003, 0x014e, - 0x013e, 0x01de, 0x01ce, 0x015e, 0x2118, 0x9026, 0x2001, 0x0007, - 0x939a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, - 0x0120, 0x939a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, - 0x0118, 0x8423, 0x8319, 0x1de8, 0x9238, 0x2029, 0x026e, 0x9528, - 0x2504, 0x942c, 0x11b8, 0x9405, 0x203a, 0x715e, 0x91a0, 0x348e, - 0x242d, 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, - 0x080c, 0x26d5, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7087, 0x0001, - 0x9084, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1800, 0x708b, 0x0000, - 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, - 0x080c, 0x60bc, 0x080c, 0xa2a0, 0x7004, 0x9084, 0x4000, 0x0110, - 0x080c, 0x2aa9, 0x0126, 0x2091, 0x8000, 0x2071, 0x1826, 0x2073, - 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x6119, - 0x001e, 0x9094, 0x0010, 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, - 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, - 0x2a04, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x2011, - 0x19f5, 0x2013, 0x0000, 0x7093, 0x0000, 0x012e, 0x60a3, 0x0056, - 0x60a7, 0x9575, 0x080c, 0xa293, 0x6144, 0xd184, 0x0120, 0x7198, - 0x918d, 0x2000, 0x0018, 0x718c, 0x918d, 0x1000, 0x2011, 0x1999, - 0x2112, 0x2009, 0x07d0, 0x2011, 0x6002, 0x080c, 0x8a5d, 0x0005, - 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xacfc, - 0x080c, 0xb09b, 0x080c, 0xad18, 0x2009, 0x00f7, 0x080c, 0x6119, - 0x2061, 0x1a04, 0x900e, 0x611a, 0x611e, 0x617a, 0x617e, 0x2061, - 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, - 0x0010, 0x2009, 0x1999, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011, - 0x6088, 0x080c, 0x8987, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005, - 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, 0x2071, 0x0100, - 0x080c, 0xa2a0, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, 0x0110, - 0x080c, 0x2aa9, 0x080c, 0x77a6, 0x0188, 0x080c, 0x77c1, 0x1170, - 0x080c, 0x7ac0, 0x0016, 0x080c, 0x27a4, 0x2001, 0x196d, 0x2102, - 0x001e, 0x080c, 0x7abb, 0x080c, 0x76cd, 0x0050, 0x2009, 0x0001, - 0x080c, 0x2a85, 0x2001, 0x0001, 0x080c, 0x2631, 0x080c, 0x6058, - 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0bc, - 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x1999, 0x201c, - 0x080c, 0x4ca1, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, 0x20e9, - 0x0001, 0x20a1, 0x1d80, 0x080c, 0x6177, 0x20e9, 0x0000, 0x2099, - 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x6171, 0x2099, 0x0260, - 0x20a1, 0x1d92, 0x0051, 0x20a9, 0x000e, 0x080c, 0x6174, 0x2099, - 0x0260, 0x20a1, 0x1db2, 0x0009, 0x0005, 0x0016, 0x0026, 0x3410, - 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x60f1, - 0x002e, 0x001e, 0x0005, 0x080c, 0xaaf1, 0x20e1, 0x0001, 0x2099, - 0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, - 0x0005, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x20e1, 0x0000, 0x2099, - 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003, - 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0x1834, - 0x2004, 0x9005, 0x1138, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, - 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, - 0x0016, 0x0046, 0x080c, 0x6c0d, 0x0158, 0x9006, 0x2020, 0x2009, - 0x002a, 0x080c, 0xea8d, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, - 0x2019, 0x002a, 0x900e, 0x080c, 0x32da, 0x080c, 0xd645, 0x0140, - 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x4e58, 0x003e, - 0x004e, 0x001e, 0x0005, 0x080c, 0x6058, 0x709b, 0x0000, 0x7093, - 0x0000, 0x0005, 0x0006, 0x2001, 0x180c, 0x2004, 0xd09c, 0x0100, - 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001, - 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e, - 0x0005, 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, 0x900e, - 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, 0x0156, - 0x0146, 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, 0x20a1, - 0x1d00, 0x4004, 0x2079, 0x1d00, 0x7803, 0x2200, 0x7807, 0x00ef, - 0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, 0xffff, - 0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1800, 0x2003, - 0x0001, 0x0005, 0x2001, 0x19a7, 0x0118, 0x2003, 0x0001, 0x0010, - 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, 0x2009, 0x1000, - 0x9006, 0x200a, 0x8108, 0x1f04, 0x61b1, 0x015e, 0x0005, 0x00d6, - 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x1847, 0x9006, 0xb802, - 0xb8d6, 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, 0x9198, 0x348e, - 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, 0xb886, 0x080c, - 0xb094, 0x1120, 0x9192, 0x007e, 0x1208, 0xbb86, 0x20a9, 0x0004, - 0xb8c4, 0x20e8, 0xb9c8, 0x9198, 0x0006, 0x9006, 0x23a0, 0x4004, - 0x20a9, 0x0004, 0x9198, 0x000a, 0x23a0, 0x4004, 0x002e, 0x001e, - 0xb83e, 0xb842, 0xb8ce, 0xb8d2, 0xb85e, 0xb862, 0xb866, 0xb86a, - 0xb86f, 0x0100, 0xb872, 0xb876, 0xb87a, 0xb88a, 0xb88e, 0xb893, - 0x0008, 0xb896, 0xb89a, 0xb89e, 0xb8be, 0xb9a2, 0x0096, 0xb8a4, - 0x904d, 0x0110, 0x080c, 0x108b, 0xb8a7, 0x0000, 0x009e, 0x9006, - 0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846, 0xb8bb, 0x0520, 0xb8ac, - 0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82, 0x1ddc, 0x0a0c, 0x0d85, - 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0d85, 0x080c, 0x8eee, - 0x00ce, 0x090c, 0x928d, 0xb8af, 0x0000, 0x6814, 0x9084, 0x00ff, - 0xb842, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, - 0x2091, 0x8000, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, - 0x1a04, 0x628d, 0x9182, 0x0800, 0x1a04, 0x6291, 0x2001, 0x180c, - 0x2004, 0x9084, 0x0003, 0x1904, 0x6297, 0x9188, 0x1000, 0x2104, - 0x905d, 0x0198, 0xb804, 0x9084, 0x00ff, 0x908e, 0x0006, 0x1188, - 0xb8a4, 0x900d, 0x1904, 0x62a9, 0x080c, 0x6669, 0x9006, 0x012e, - 0x0005, 0x2001, 0x0005, 0x900e, 0x04b8, 0x2001, 0x0028, 0x900e, - 0x0498, 0x9082, 0x0006, 0x1290, 0x080c, 0xb094, 0x1160, 0xb8a0, - 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0d10, 0x2001, 0x0029, - 0x2009, 0x1000, 0x0408, 0x2001, 0x0028, 0x00a8, 0x2009, 0x180c, - 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, - 0x2001, 0x0004, 0x0040, 0x2001, 0x0029, 0xb900, 0xd1fc, 0x0118, - 0x2009, 0x1000, 0x0048, 0x900e, 0x0038, 0x2001, 0x0029, 0x900e, - 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x012e, 0x0005, 0x2001, - 0x180c, 0x2004, 0xd084, 0x19d0, 0x9188, 0x1000, 0x2104, 0x9065, - 0x09a8, 0x080c, 0x6c11, 0x1990, 0xb800, 0xd0bc, 0x0978, 0x0804, - 0x6250, 0x080c, 0x6a2a, 0x0904, 0x6259, 0x0804, 0x6254, 0x00e6, - 0x2071, 0x19e8, 0x7004, 0x9086, 0x0002, 0x1128, 0x7030, 0x9080, - 0x0004, 0x2004, 0x9b06, 0x00ee, 0x0005, 0x00b6, 0x00e6, 0x0126, - 0x2091, 0x8000, 0xa874, 0x908e, 0x00ff, 0x1120, 0x2001, 0x196b, - 0x205c, 0x0060, 0xa974, 0x9182, 0x0800, 0x1690, 0x9188, 0x1000, - 0x2104, 0x905d, 0x01d0, 0x080c, 0x6bb1, 0x11d0, 0x080c, 0xb116, - 0x0570, 0x2b00, 0x6012, 0x2900, 0x6016, 0x6023, 0x0009, 0x602b, - 0x0000, 0xa874, 0x908e, 0x00ff, 0x1110, 0x602b, 0x8000, 0x2009, - 0x0043, 0x080c, 0xb20a, 0x9006, 0x00b0, 0x2001, 0x0028, 0x0090, - 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, - 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x0010, - 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, - 0x002c, 0x0cc0, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa974, - 0x9182, 0x0800, 0x1a04, 0x6388, 0x9188, 0x1000, 0x2104, 0x905d, - 0x0904, 0x6360, 0xb8a0, 0x9086, 0x007f, 0x0190, 0xa87c, 0xd0fc, - 0x1178, 0x080c, 0x6c19, 0x0160, 0xa994, 0x81ff, 0x0130, 0x908e, - 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x080c, 0x6c11, 0x1598, - 0xa87c, 0xd0fc, 0x01e0, 0xa894, 0x9005, 0x01c8, 0x2060, 0x0026, - 0x2010, 0x080c, 0xcf09, 0x002e, 0x1120, 0x2001, 0x0008, 0x0804, - 0x638a, 0x6020, 0x9086, 0x000a, 0x0120, 0x2001, 0x0008, 0x0804, - 0x638a, 0x601a, 0x6003, 0x0008, 0x2900, 0x6016, 0x0058, 0x080c, - 0xb116, 0x05e8, 0x2b00, 0x6012, 0x2900, 0x6016, 0x600b, 0xffff, - 0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0xb20a, 0x9006, 0x0458, - 0x2001, 0x0028, 0x0438, 0x9082, 0x0006, 0x1290, 0x080c, 0xb094, - 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0900, - 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, - 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, - 0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010, - 0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, - 0x002c, 0x0cc0, 0x00f6, 0x00b6, 0x0126, 0x2091, 0x8000, 0xa8e0, - 0x9005, 0x1550, 0xa8dc, 0x9082, 0x0101, 0x1630, 0xa8c8, 0x9005, - 0x1518, 0xa8c4, 0x9082, 0x0101, 0x12f8, 0xa974, 0x2079, 0x1800, - 0x9182, 0x0800, 0x12e8, 0x7830, 0x9084, 0x0003, 0x1130, 0xaa98, - 0xab94, 0xa878, 0x9084, 0x0007, 0x00ea, 0x7930, 0xd18c, 0x0118, - 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, - 0x2001, 0x0029, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, - 0x2001, 0x0029, 0x900e, 0x9006, 0x0008, 0x9005, 0x012e, 0x00be, - 0x00fe, 0x0005, 0x641f, 0x63da, 0x63f1, 0x641f, 0x641f, 0x641f, - 0x641f, 0x641f, 0x2100, 0x9082, 0x007e, 0x1278, 0x080c, 0x6749, - 0x0148, 0x9046, 0xb810, 0x9306, 0x1904, 0x6427, 0xb814, 0x9206, - 0x15f0, 0x0028, 0xbb12, 0xba16, 0x0010, 0x080c, 0x4b54, 0x0150, - 0x04b0, 0x080c, 0x67b4, 0x1598, 0xb810, 0x9306, 0x1580, 0xb814, - 0x9206, 0x1568, 0x080c, 0xb116, 0x0530, 0x2b00, 0x6012, 0x080c, - 0xd3b6, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0xa878, - 0x9086, 0x0001, 0x1170, 0x080c, 0x3315, 0x9006, 0x080c, 0x66e6, - 0x2001, 0x0002, 0x080c, 0x66fa, 0x2001, 0x0200, 0xb86e, 0xb893, - 0x0002, 0x2009, 0x0003, 0x080c, 0xb20a, 0x9006, 0x0068, 0x2001, - 0x0001, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, - 0x0028, 0x900e, 0x9005, 0x0000, 0x012e, 0x00be, 0x00fe, 0x0005, - 0x00b6, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa894, 0x90c6, - 0x0015, 0x0904, 0x6612, 0x90c6, 0x0056, 0x0904, 0x6616, 0x90c6, - 0x0066, 0x0904, 0x661a, 0x90c6, 0x0067, 0x0904, 0x661e, 0x90c6, - 0x0068, 0x0904, 0x6622, 0x90c6, 0x0071, 0x0904, 0x6626, 0x90c6, - 0x0074, 0x0904, 0x662a, 0x90c6, 0x007c, 0x0904, 0x662e, 0x90c6, - 0x007e, 0x0904, 0x6632, 0x90c6, 0x0037, 0x0904, 0x6636, 0x9016, - 0x2079, 0x1800, 0xa974, 0x9186, 0x00ff, 0x0904, 0x660d, 0x9182, - 0x0800, 0x1a04, 0x660d, 0x080c, 0x67b4, 0x1198, 0xb804, 0x9084, - 0x00ff, 0x9082, 0x0006, 0x1268, 0xa894, 0x90c6, 0x006f, 0x0148, - 0x080c, 0xb094, 0x1904, 0x65f6, 0xb8a0, 0x9084, 0xff80, 0x1904, - 0x65f6, 0xa894, 0x90c6, 0x006f, 0x0158, 0x90c6, 0x005e, 0x0904, - 0x6556, 0x90c6, 0x0064, 0x0904, 0x657f, 0x2008, 0x0804, 0x6518, - 0xa998, 0xa8b0, 0x2040, 0x080c, 0xb094, 0x1120, 0x9182, 0x007f, - 0x0a04, 0x6518, 0x9186, 0x00ff, 0x0904, 0x6518, 0x9182, 0x0800, - 0x1a04, 0x6518, 0xaaa0, 0xab9c, 0x787c, 0x9306, 0x11a8, 0x7880, - 0x0096, 0x924e, 0x1128, 0x2208, 0x2310, 0x009e, 0x0804, 0x6518, - 0x080c, 0xb094, 0x1140, 0x99cc, 0xff00, 0x009e, 0x1128, 0x2208, - 0x2310, 0x0804, 0x6518, 0x009e, 0x080c, 0x4b54, 0x0904, 0x6522, - 0x900e, 0x9016, 0x90c6, 0x4000, 0x15e0, 0x0006, 0x080c, 0x6aae, - 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0, - 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fd6, 0x20a9, 0x0004, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c4, 0x20e0, - 0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0fd6, 0xa8c4, 0xabc8, - 0x9305, 0xabcc, 0x9305, 0xabd0, 0x9305, 0xabd4, 0x9305, 0xabd8, - 0x9305, 0xabdc, 0x9305, 0xabe0, 0x9305, 0x9005, 0x0510, 0x000e, - 0x00c8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x00a0, 0x90c6, 0x4008, - 0x1118, 0x2708, 0x2610, 0x0070, 0x90c6, 0x4009, 0x1108, 0x0050, - 0x90c6, 0x4006, 0x0138, 0x2001, 0x4005, 0x2009, 0x000a, 0x0010, - 0x2001, 0x4006, 0xa896, 0xa99a, 0xaa9e, 0x2001, 0x0030, 0x900e, - 0x0478, 0x000e, 0x080c, 0xb116, 0x1130, 0x2001, 0x4005, 0x2009, - 0x0003, 0x9016, 0x0c78, 0x2b00, 0x6012, 0x080c, 0xd3b6, 0x2900, - 0x6016, 0x6023, 0x0001, 0xa868, 0xd88c, 0x0108, 0xc0f5, 0xa86a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x3315, 0x012e, 0x9006, 0x080c, - 0x66e6, 0x2001, 0x0002, 0x080c, 0x66fa, 0x2009, 0x0002, 0x080c, - 0xb20a, 0xa8b0, 0xd094, 0x0118, 0xb8d4, 0xc08d, 0xb8d6, 0x9006, - 0x9005, 0x012e, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x080c, 0x5854, - 0x0118, 0x2009, 0x0007, 0x00f8, 0xa998, 0xaeb0, 0x080c, 0x67b4, - 0x1904, 0x6513, 0x9186, 0x007f, 0x0130, 0x080c, 0x6c11, 0x0118, - 0x2009, 0x0009, 0x0080, 0x0096, 0x080c, 0x1059, 0x1120, 0x009e, - 0x2009, 0x0002, 0x0040, 0x2900, 0x009e, 0xa806, 0x080c, 0xd109, - 0x19b0, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x651a, 0xa998, - 0xaeb0, 0x080c, 0x67b4, 0x1904, 0x6513, 0x0096, 0x080c, 0x1059, - 0x1128, 0x009e, 0x2009, 0x0002, 0x0804, 0x65d3, 0x2900, 0x009e, - 0xa806, 0x0096, 0x2048, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, - 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, - 0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xbbc8, 0x9398, 0x0006, - 0x2398, 0x080c, 0x0fd6, 0x009e, 0xa87b, 0x0000, 0xa883, 0x0000, - 0xa897, 0x4000, 0xd684, 0x1168, 0x080c, 0x5840, 0xd0b4, 0x1118, - 0xa89b, 0x000b, 0x00e0, 0xb800, 0xd08c, 0x0118, 0xa89b, 0x000c, - 0x00b0, 0x080c, 0x6c11, 0x0118, 0xa89b, 0x0009, 0x0080, 0x080c, - 0x5854, 0x0118, 0xa89b, 0x0007, 0x0050, 0x080c, 0xd0ec, 0x1904, - 0x654f, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x651a, 0xa87b, - 0x0030, 0xa897, 0x4005, 0xa804, 0x8006, 0x8006, 0x8007, 0x90bc, - 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, - 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x12a8, 0x080c, - 0xb691, 0x1904, 0x654f, 0x2009, 0x0002, 0x08e8, 0x2001, 0x0028, - 0x900e, 0x0804, 0x6550, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, - 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010, - 0x2001, 0x0029, 0x900e, 0x0804, 0x6550, 0x2001, 0x0029, 0x900e, - 0x0804, 0x6550, 0x080c, 0x38c0, 0x0804, 0x6551, 0x080c, 0x555d, - 0x0804, 0x6551, 0x080c, 0x46d5, 0x0804, 0x6551, 0x080c, 0x474e, - 0x0804, 0x6551, 0x080c, 0x47aa, 0x0804, 0x6551, 0x080c, 0x4c17, - 0x0804, 0x6551, 0x080c, 0x4edf, 0x0804, 0x6551, 0x080c, 0x51c4, - 0x0804, 0x6551, 0x080c, 0x53bd, 0x0804, 0x6551, 0x080c, 0x3afe, - 0x0804, 0x6551, 0x00b6, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, - 0x4000, 0x1608, 0x9182, 0x0800, 0x1258, 0x9188, 0x1000, 0x2104, - 0x905d, 0x0130, 0x080c, 0x6c11, 0x1138, 0x00d9, 0x9006, 0x00b0, - 0x2001, 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, 0xb900, - 0xd1fc, 0x0d98, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, - 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x00be, - 0x0005, 0xa877, 0x0000, 0xb8d0, 0x9005, 0x1904, 0x66da, 0xb888, - 0x9005, 0x1904, 0x66da, 0xb838, 0xb93c, 0x9102, 0x1a04, 0x66da, - 0x2b10, 0x080c, 0xb143, 0x0904, 0x66d6, 0x8108, 0xb93e, 0x6212, - 0x2900, 0x6016, 0x6023, 0x0003, 0x600b, 0xffff, 0x6007, 0x0040, - 0xa878, 0x605e, 0xa880, 0x6066, 0xa883, 0x0000, 0xa87c, 0xd0ac, - 0x05b8, 0xc0dd, 0xa87e, 0xa888, 0x8001, 0x1560, 0x2011, 0x180d, - 0x2214, 0xd28c, 0x190c, 0x6cd6, 0xa816, 0xa864, 0x9094, 0x00f7, - 0x9296, 0x0011, 0x11f8, 0x9084, 0x00ff, 0xc0bd, 0x601e, 0xa8ac, - 0xaab0, 0xa836, 0xaa3a, 0x2001, 0x000f, 0x8001, 0x1df0, 0x2001, - 0x8004, 0x6003, 0x0004, 0x6046, 0x00f6, 0x2079, 0x0380, 0x7818, - 0xd0bc, 0x1de8, 0x7833, 0x0010, 0x2c00, 0x7836, 0x781b, 0x8080, - 0x00fe, 0x0005, 0x080c, 0x17ad, 0x601c, 0xc0bd, 0x601e, 0x0c38, - 0x2009, 0x180d, 0x210c, 0xd18c, 0x190c, 0x6ce0, 0xd0b4, 0x190c, - 0x1c9c, 0x2001, 0x8004, 0x6003, 0x0002, 0x08e8, 0x81ff, 0x1110, - 0xb88b, 0x0001, 0x2908, 0xb8cc, 0xb9ce, 0x9005, 0x1110, 0xb9d2, - 0x0020, 0x0096, 0x2048, 0xa902, 0x009e, 0x0005, 0x00b6, 0x0126, - 0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, 0x2258, 0xba00, 0x9005, - 0x0110, 0xc285, 0x0008, 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e, - 0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210, - 0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1170, 0xb89c, 0xd0ac, - 0x0158, 0x080c, 0x6c0d, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086, - 0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215, - 0xba06, 0x0006, 0x9086, 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c, - 0x0d85, 0x000e, 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126, - 0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086, - 0x0006, 0x1168, 0xb89c, 0xd0a4, 0x0150, 0x080c, 0x6c09, 0x1138, - 0x9284, 0x00ff, 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, - 0x9294, 0x00ff, 0x8007, 0x9215, 0xba06, 0x00ce, 0x012e, 0x00be, - 0x0005, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0005, 0x00d6, - 0x0026, 0x9190, 0x1000, 0x2204, 0x905d, 0x1188, 0x0096, 0x080c, - 0x1059, 0x2958, 0x009e, 0x0168, 0x2b00, 0x2012, 0xb85c, 0xb8ca, - 0xb860, 0xb8c6, 0x9006, 0xb8a6, 0xb8ae, 0x080c, 0x61b7, 0x9006, - 0x0010, 0x9085, 0x0001, 0x002e, 0x00de, 0x0005, 0x00b6, 0x0096, - 0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x0800, 0x0218, 0x9085, - 0x0001, 0x04a8, 0x00d6, 0x9190, 0x1000, 0x2204, 0x905d, 0x0568, - 0x2013, 0x0000, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x108b, 0x00d6, - 0x00c6, 0xb8bc, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014, - 0x2048, 0x080c, 0xcf1b, 0x0110, 0x080c, 0x100b, 0x080c, 0xb16c, - 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x00c6, 0xb8ac, 0x9065, 0x0128, - 0x621c, 0xd2c4, 0x0110, 0x080c, 0x928d, 0x00ce, 0x2b48, 0xb8c8, - 0xb85e, 0xb8c4, 0xb862, 0x080c, 0x109b, 0x00de, 0x9006, 0x002e, - 0x012e, 0x009e, 0x00be, 0x0005, 0x0016, 0x9182, 0x0800, 0x0218, - 0x9085, 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, 0x905d, 0x0dc0, - 0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006, - 0xb80a, 0xb80e, 0xb800, 0xc08c, 0xb802, 0x080c, 0x779e, 0x1510, - 0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, 0xb094, 0x11d8, 0x0078, - 0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x1982, 0x7048, 0x2062, - 0x704c, 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c, - 0x2069, 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069, - 0x1800, 0x68b6, 0x7040, 0xb85e, 0x7048, 0xb862, 0x704c, 0xb866, - 0x20e1, 0x0000, 0x2099, 0x0276, 0xb8c4, 0x20e8, 0xb8c8, 0x9088, - 0x000a, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, 0x027a, 0x9088, - 0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, 0x0200, 0x6817, - 0x0001, 0x7040, 0xb86a, 0x7144, 0xb96e, 0x7048, 0xb872, 0x7050, - 0xb876, 0x2069, 0x0200, 0x6817, 0x0000, 0xb8a0, 0x9086, 0x007e, - 0x1110, 0x7144, 0xb96e, 0x9182, 0x0211, 0x1218, 0x2009, 0x0008, - 0x0400, 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0x9182, - 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, 0x0349, 0x1218, - 0x2009, 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, 0x2009, 0x0004, - 0x0040, 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, - 0x0002, 0xb992, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, - 0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, 0xb896, 0x703c, 0xb89a, - 0x7054, 0xb89e, 0x0036, 0xbbd4, 0xc384, 0xba00, 0x2009, 0x1867, - 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, - 0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, 0x0128, 0xd38c, - 0x1108, 0xc385, 0x0008, 0xc2bc, 0xba02, 0xbbd6, 0x003e, 0x00ee, - 0x002e, 0x001e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4, - 0x904d, 0x0578, 0xa900, 0x81ff, 0x15c0, 0xaa04, 0x9282, 0x0010, - 0x16c8, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x8906, 0x8006, 0x8007, - 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9080, 0x0004, 0x2098, - 0x2009, 0x0010, 0x20a9, 0x0001, 0x4002, 0x9086, 0xffff, 0x0120, - 0x8109, 0x1dd0, 0x080c, 0x0d85, 0x3c00, 0x20e8, 0x3300, 0x8001, - 0x20a0, 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, 0x014e, 0x013e, - 0x0060, 0x080c, 0x1059, 0x0170, 0x2900, 0xb8a6, 0xa803, 0x0000, - 0x080c, 0x6a4a, 0xa807, 0x0001, 0xae12, 0x9085, 0x0001, 0x012e, - 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x0096, - 0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, 0x080c, 0x6a59, - 0x1158, 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, 0xa806, 0x0020, - 0x080c, 0x108b, 0xb8a7, 0x0000, 0x009e, 0x012e, 0x0005, 0x0096, - 0x00c6, 0xb888, 0x9005, 0x1904, 0x693f, 0xb8d0, 0x904d, 0x0904, - 0x693f, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, - 0x1904, 0x693d, 0x080c, 0xb143, 0x0904, 0x693d, 0x8210, 0xba3e, - 0xa800, 0xb8d2, 0x9005, 0x1108, 0xb8ce, 0x2b00, 0x6012, 0x2900, - 0x6016, 0x6023, 0x0003, 0x600b, 0xffff, 0x6007, 0x0040, 0xa878, - 0x605e, 0xa880, 0x9084, 0x00ff, 0x6066, 0xa883, 0x0000, 0xa87c, - 0xd0ac, 0x01c8, 0xc0dd, 0xa87e, 0xa888, 0x8001, 0x1558, 0xa816, - 0xa864, 0x9094, 0x00f7, 0x9296, 0x0011, 0x1520, 0x9084, 0x00ff, - 0xc0bd, 0x601e, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x2001, 0x8004, - 0x6003, 0x0004, 0x0030, 0x080c, 0x1c9c, 0x2001, 0x8004, 0x6003, - 0x0002, 0x6046, 0x2001, 0x0010, 0x2c08, 0x080c, 0xaced, 0xb838, - 0xba3c, 0x9202, 0x0a04, 0x68e5, 0x0010, 0xb88b, 0x0001, 0x00ce, - 0x009e, 0x0005, 0x080c, 0x17ad, 0x601c, 0xc0bd, 0x601e, 0x08f0, - 0x00b6, 0x0096, 0x0016, 0x20a9, 0x0800, 0x900e, 0x0016, 0x080c, - 0x67b4, 0x1158, 0xb8d0, 0x904d, 0x0140, 0x3e00, 0x9086, 0x0002, - 0x1118, 0xb800, 0xd0bc, 0x1108, 0x0041, 0x001e, 0x8108, 0x1f04, - 0x694e, 0x001e, 0x00be, 0x009e, 0x0005, 0x0096, 0x0016, 0xb8d0, - 0x904d, 0x0188, 0xa800, 0xb8d2, 0x9005, 0x1108, 0xb8ce, 0x9006, - 0xa802, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd220, - 0x080c, 0x7012, 0x0c60, 0x001e, 0x009e, 0x0005, 0x0086, 0x9046, - 0xb8d0, 0x904d, 0x01b0, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, - 0x0128, 0x2940, 0xa800, 0x904d, 0x0160, 0x0ca8, 0xa800, 0x88ff, - 0x1128, 0xb8d2, 0x9005, 0x1118, 0xb8ce, 0x0008, 0xa002, 0xa803, - 0x0000, 0x008e, 0x0005, 0x901e, 0x0010, 0x2019, 0x0001, 0x0126, - 0x2091, 0x8000, 0x00e6, 0x0096, 0x00c6, 0x0086, 0x0026, 0x2071, - 0x19e8, 0x9046, 0x7028, 0x9065, 0x01e8, 0x6014, 0x2068, 0x83ff, - 0x0120, 0x605c, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, - 0xa870, 0x9506, 0x0120, 0x2c40, 0x600c, 0x2060, 0x0c60, 0x600c, - 0x0006, 0x0066, 0x2830, 0x080c, 0xa420, 0x006e, 0x000e, 0x83ff, - 0x0508, 0x0c08, 0x9046, 0xb8d0, 0x904d, 0x01e0, 0x83ff, 0x0120, - 0xa878, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, 0xa870, - 0x9506, 0x0120, 0x2940, 0xa800, 0x2048, 0x0c70, 0xb8d0, 0xaa00, - 0x0026, 0x9906, 0x1110, 0xbad2, 0x0008, 0xa202, 0x000e, 0x83ff, - 0x0108, 0x0c10, 0x002e, 0x008e, 0x00ce, 0x009e, 0x00ee, 0x012e, - 0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, - 0x6aae, 0x0128, 0x080c, 0xcfdc, 0x0010, 0x9085, 0x0001, 0x0005, - 0x080c, 0x6aae, 0x0128, 0x080c, 0xcf7d, 0x0010, 0x9085, 0x0001, - 0x0005, 0x080c, 0x6aae, 0x0128, 0x080c, 0xcfd9, 0x0010, 0x9085, - 0x0001, 0x0005, 0x080c, 0x6aae, 0x0128, 0x080c, 0xcf9c, 0x0010, - 0x9085, 0x0001, 0x0005, 0x080c, 0x6aae, 0x0128, 0x080c, 0xd01f, - 0x0010, 0x9085, 0x0001, 0x0005, 0xb8a4, 0x900d, 0x1118, 0x9085, - 0x0001, 0x0005, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, - 0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, - 0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, - 0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0008, 0x9006, 0x01ce, - 0x013e, 0x0005, 0x0146, 0x01d6, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0004, 0x20a0, 0x20a9, 0x0010, 0x2009, 0xffff, 0x4104, 0x01de, - 0x014e, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, - 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, - 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, - 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0068, 0x0146, 0x01d6, 0x3300, - 0x8001, 0x20a0, 0x3c00, 0x20e8, 0x2001, 0xffff, 0x4004, 0x01de, - 0x014e, 0x9006, 0x01ce, 0x013e, 0x0005, 0x0096, 0x0126, 0x2091, - 0x8000, 0xb8a4, 0x904d, 0x1128, 0x080c, 0x1059, 0x0168, 0x2900, - 0xb8a6, 0x080c, 0x6a4a, 0xa803, 0x0001, 0xa807, 0x0000, 0x9085, - 0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126, - 0x2091, 0x8000, 0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c, - 0x108b, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4, - 0x0005, 0x00b6, 0x00f6, 0x080c, 0x779e, 0x01b0, 0x71c4, 0x81ff, - 0x1198, 0x71dc, 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, 0x1000, - 0x2004, 0x905d, 0x0148, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x1118, 0xb800, 0xc0ed, 0xb802, 0x2079, 0x1847, 0x7804, 0xd0a4, - 0x01d0, 0x0156, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x67b4, - 0x1168, 0xb804, 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, - 0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, - 0x1f04, 0x6ad5, 0x015e, 0x080c, 0x6bcf, 0x0120, 0x2001, 0x1985, - 0x200c, 0x0098, 0x2079, 0x1847, 0x7804, 0xd0a4, 0x0190, 0x2009, - 0x07d0, 0x2001, 0x182c, 0x2004, 0x9005, 0x0138, 0x2001, 0x1867, - 0x2004, 0xd0e4, 0x0110, 0x2009, 0x5dc0, 0x2011, 0x6b0c, 0x080c, - 0x8a5d, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x2011, 0x6b0c, 0x080c, - 0x8993, 0x080c, 0x6bcf, 0x01d8, 0x2001, 0x107e, 0x2004, 0x2058, - 0xb900, 0xc1ec, 0xb902, 0x080c, 0x6c0d, 0x0130, 0x2009, 0x07d0, - 0x2011, 0x6b0c, 0x080c, 0x8a5d, 0x00e6, 0x2071, 0x1800, 0x9006, - 0x707e, 0x7060, 0x7082, 0x080c, 0x30bf, 0x00ee, 0x04d0, 0x0156, - 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x67b4, 0x1558, - 0xb800, 0xd0ec, 0x0540, 0x0046, 0xbaa0, 0x2220, 0x9006, 0x2009, - 0x0029, 0x080c, 0xea8d, 0xb800, 0xc0e5, 0xc0ec, 0xb802, 0x080c, - 0x6c09, 0x2001, 0x0707, 0x1128, 0xb804, 0x9084, 0x00ff, 0x9085, - 0x0700, 0xb806, 0x080c, 0xacfc, 0x2019, 0x0029, 0x080c, 0x97b0, - 0x0076, 0x903e, 0x080c, 0x966d, 0x900e, 0x080c, 0xe75d, 0x007e, - 0x004e, 0x080c, 0xad18, 0x001e, 0x8108, 0x1f04, 0x6b34, 0x00ce, - 0x015e, 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058, 0xb800, 0xc0ec, - 0xb802, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x0096, 0x080c, 0x1072, - 0x090c, 0x0d85, 0x2958, 0x009e, 0x2001, 0x196b, 0x2b02, 0x8b07, - 0x8006, 0x8006, 0x908c, 0x003f, 0xb9c6, 0x908c, 0xffc0, 0xb9ca, - 0xb8af, 0x0000, 0x2009, 0x00ff, 0x080c, 0x61b7, 0xb807, 0x0006, - 0xb813, 0x00ff, 0xb817, 0xffff, 0xb86f, 0x0200, 0xb86c, 0xb893, - 0x0002, 0xb8bb, 0x0520, 0xb8a3, 0x00ff, 0xb8af, 0x0000, 0x00ce, - 0x00be, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ac, - 0x0005, 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800, 0x00be, 0xd0bc, - 0x0005, 0x0006, 0x0016, 0x0026, 0xb804, 0x908c, 0x00ff, 0x9196, - 0x0006, 0x0188, 0x9196, 0x0004, 0x0170, 0x9196, 0x0005, 0x0158, - 0x908c, 0xff00, 0x810f, 0x9196, 0x0006, 0x0128, 0x9196, 0x0004, - 0x0110, 0x9196, 0x0005, 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, - 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, 0xb800, 0xd0ec, - 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, 0x0006, - 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, 0x0d85, 0x000e, - 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0xba02, 0x002e, - 0x012e, 0x0005, 0x2011, 0x1837, 0x2204, 0xd0cc, 0x0138, 0x2001, - 0x1983, 0x200c, 0x2011, 0x6bff, 0x080c, 0x8a5d, 0x0005, 0x2011, - 0x6bff, 0x080c, 0x8993, 0x2011, 0x1837, 0x2204, 0xc0cc, 0x2012, - 0x0005, 0x080c, 0x5840, 0xd0ac, 0x0005, 0x080c, 0x5840, 0xd0a4, - 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, 0x0006, 0x001e, - 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, 0x908e, 0x0006, - 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xd645, 0x0158, 0x70dc, - 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, 0x905d, 0x0110, - 0xb8d4, 0xd094, 0x00fe, 0x00be, 0x0005, 0x0006, 0x0016, 0x0036, - 0x0046, 0x0076, 0x00b6, 0x2001, 0x1818, 0x203c, 0x9780, 0x348e, - 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2018, 0x2008, 0x9284, - 0x8000, 0x0110, 0x2019, 0x0001, 0x9294, 0x7fff, 0x2100, 0x9706, - 0x0190, 0x91a0, 0x1000, 0x2404, 0x905d, 0x0168, 0xb804, 0x9084, - 0x00ff, 0x9086, 0x0006, 0x1138, 0x83ff, 0x0118, 0xb89c, 0xd0a4, - 0x0110, 0x8211, 0x0158, 0x8108, 0x83ff, 0x0120, 0x9182, 0x0800, - 0x0e28, 0x0068, 0x9182, 0x007e, 0x0e08, 0x0048, 0x00be, 0x007e, - 0x004e, 0x003e, 0x001e, 0x9085, 0x0001, 0x000e, 0x0005, 0x00be, - 0x007e, 0x004e, 0x003e, 0x001e, 0x9006, 0x000e, 0x0005, 0x0046, - 0x0056, 0x0076, 0x00b6, 0x2100, 0x9084, 0x7fff, 0x9080, 0x1000, - 0x2004, 0x905d, 0x0130, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, - 0x0550, 0x9184, 0x8000, 0x0580, 0x2001, 0x1818, 0x203c, 0x9780, - 0x348e, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2020, 0x2400, - 0x9706, 0x01a0, 0x94a8, 0x1000, 0x2504, 0x905d, 0x0178, 0xb804, - 0x9084, 0x00ff, 0x9086, 0x0006, 0x1148, 0xb89c, 0xd0a4, 0x0130, - 0xb814, 0x9206, 0x1118, 0xb810, 0x9306, 0x0128, 0x8420, 0x9482, - 0x0800, 0x0e28, 0x0048, 0x918c, 0x7fff, 0x00be, 0x007e, 0x005e, - 0x004e, 0x9085, 0x0001, 0x0005, 0x918c, 0x7fff, 0x00be, 0x007e, - 0x005e, 0x004e, 0x9006, 0x0005, 0x0006, 0x2001, 0x00a0, 0x8001, - 0xa001, 0xa001, 0xa001, 0x1dd8, 0x000e, 0x0005, 0x0006, 0x2001, - 0x00f8, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, 0x000e, 0x0005, - 0x0006, 0x2001, 0x00e8, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, - 0x000e, 0x0005, 0x2071, 0x1910, 0x7003, 0x0001, 0x7007, 0x0000, - 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, 0x7046, 0x2001, - 0x1922, 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1948, - 0x900e, 0x710a, 0x080c, 0x5840, 0xd0fc, 0x1140, 0x080c, 0x5840, - 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0470, 0x2001, 0x1867, - 0x200c, 0x9184, 0x0007, 0x0006, 0x2001, 0x180d, 0x2004, 0xd08c, - 0x000e, 0x0108, 0x9006, 0x0002, 0x6d06, 0x6d06, 0x6d06, 0x6d06, - 0x6d06, 0x6d24, 0x6d39, 0x6d47, 0x7003, 0x0003, 0x2009, 0x1868, - 0x210c, 0x9184, 0xff00, 0x908e, 0xff00, 0x0140, 0x8007, 0x9005, - 0x1110, 0x2001, 0x0002, 0x8003, 0x7006, 0x0030, 0x7007, 0x0001, - 0x0018, 0x7003, 0x0005, 0x0c50, 0x2071, 0x1910, 0x704f, 0x0000, - 0x2071, 0x1800, 0x70f7, 0x0001, 0x00ee, 0x001e, 0x0005, 0x7003, - 0x0000, 0x2071, 0x1910, 0x2009, 0x1868, 0x210c, 0x9184, 0x7f00, - 0x8007, 0x908c, 0x000f, 0x0160, 0x714e, 0x8004, 0x8004, 0x8004, - 0x8004, 0x2071, 0x1800, 0x908c, 0x0007, 0x0128, 0x70f6, 0x0c20, - 0x704f, 0x000f, 0x0c90, 0x70f7, 0x0005, 0x08f0, 0x00e6, 0x2071, - 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, 0x2071, 0x1910, 0x7028, - 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0488, 0x6844, 0x9005, - 0x0158, 0x080c, 0x7b28, 0x6a60, 0x9200, 0x7002, 0x6864, 0x9101, - 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, 0x6864, 0x7006, - 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, 0x1110, 0x7012, - 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x7037, - 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x1910, 0x7028, 0xc084, - 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee, 0x9006, 0x00ee, - 0x0005, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000, 0x9015, 0x0904, - 0x7017, 0x9286, 0x0003, 0x0904, 0x6eac, 0x9286, 0x0005, 0x0904, - 0x6eac, 0x2071, 0x1877, 0xa87c, 0x9005, 0x0904, 0x6e07, 0x7140, - 0xa868, 0x9102, 0x0a04, 0x7017, 0xa878, 0xd084, 0x15d8, 0xa853, - 0x0019, 0x2001, 0x8023, 0xa84e, 0x2071, 0x1910, 0x701c, 0x9005, - 0x1904, 0x71c6, 0x0e04, 0x7234, 0x2071, 0x0000, 0xa850, 0x7032, - 0xa84c, 0x7082, 0xa870, 0x7086, 0xa86c, 0x708a, 0xa880, 0x708e, - 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, - 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, - 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, - 0x0804, 0x6e8f, 0xa853, 0x001b, 0x2001, 0x8027, 0x0820, 0x7004, - 0xd08c, 0x1904, 0x7017, 0xa853, 0x001a, 0x2001, 0x8024, 0x0804, - 0x6dcb, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000, 0x9015, 0x0904, - 0x7017, 0x9286, 0x0003, 0x0904, 0x6eac, 0x9286, 0x0005, 0x0904, - 0x6eac, 0xa84f, 0x8022, 0xa853, 0x0018, 0x0804, 0x6e74, 0xa868, - 0xd0fc, 0x1508, 0x00e6, 0x0026, 0x2001, 0x1948, 0x2004, 0x9015, - 0x0904, 0x7017, 0xa978, 0xa874, 0x9105, 0x1904, 0x7017, 0x9286, - 0x0003, 0x0904, 0x6eac, 0x9286, 0x0005, 0x0904, 0x6eac, 0xa87c, - 0xd0bc, 0x1904, 0x7017, 0x2200, 0x0002, 0x7017, 0x6e70, 0x6eac, - 0x6eac, 0x7017, 0x6eac, 0x0005, 0xa868, 0xd0fc, 0x1500, 0x00e6, - 0x0026, 0x2009, 0x1948, 0x210c, 0x81ff, 0x0904, 0x7017, 0xa880, - 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7017, 0x9186, 0x0003, - 0x0904, 0x6eac, 0x9186, 0x0005, 0x0904, 0x6eac, 0xa87c, 0xd0cc, - 0x0904, 0x7017, 0xa84f, 0x8021, 0xa853, 0x0017, 0x0028, 0x0005, - 0xa84f, 0x8020, 0xa853, 0x0016, 0x2071, 0x1910, 0x701c, 0x9005, - 0x1904, 0x71c6, 0x0e04, 0x7234, 0x2071, 0x0000, 0xa84c, 0x7082, - 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x2071, - 0x1800, 0x2011, 0x0001, 0xa804, 0x900d, 0x702c, 0x1158, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x002e, - 0x00ee, 0x0005, 0x0096, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x009e, 0x0c58, 0xa84f, 0x0000, 0x00f6, 0x2079, - 0x0050, 0x2071, 0x1910, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904, - 0x6f9d, 0x782c, 0x908c, 0x0780, 0x190c, 0x7382, 0x8004, 0x8004, - 0x8004, 0x9084, 0x0003, 0x0002, 0x6eca, 0x6f9d, 0x6eee, 0x6f3a, - 0x080c, 0x0d85, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, - 0x1168, 0x2071, 0x1a04, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, - 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c, - 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, - 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x0c18, 0x2071, 0x1800, - 0x2900, 0x7822, 0xa804, 0x900d, 0x15a0, 0x7824, 0x00e6, 0x2071, - 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, 0x1830, 0x210c, 0x918a, - 0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102, - 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, - 0x190c, 0x7382, 0xd0a4, 0x19c8, 0x2071, 0x1a04, 0x7044, 0x9005, - 0x1320, 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, - 0x0804, 0x6ef5, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, - 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, - 0x8899, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x1d60, - 0x00ee, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x1198, - 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x1550, 0x2071, 0x1a04, - 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, - 0x002e, 0x00ee, 0x0005, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, - 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, - 0xa804, 0x900d, 0x1168, 0x2071, 0x1a04, 0x7044, 0x9005, 0x1320, - 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, - 0x8899, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, - 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, - 0x2148, 0xa804, 0x900d, 0x1904, 0x6ff1, 0x782c, 0x9094, 0x0780, - 0x190c, 0x7382, 0xd09c, 0x1198, 0x701c, 0x904d, 0x0180, 0x7010, - 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, - 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x0d68, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x01b0, 0x00e6, 0x7824, - 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, - 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, 0x190c, - 0x7382, 0xd0a4, 0x1d60, 0x00ee, 0x2071, 0x1a04, 0x7044, 0x9005, - 0x1320, 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, - 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, - 0x70c2, 0x080c, 0x8899, 0x00ee, 0x0804, 0x6fad, 0xa868, 0xd0fc, - 0x15e0, 0x0096, 0xa804, 0xa807, 0x0000, 0x904d, 0x190c, 0x100b, - 0x009e, 0x0018, 0xa868, 0xd0fc, 0x1580, 0x00e6, 0x0026, 0xa84f, - 0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1910, 0xa803, 0x0000, - 0xa864, 0x9084, 0x00ff, 0x908e, 0x0016, 0x01a8, 0x7010, 0x9005, - 0x1904, 0x7142, 0x782c, 0x908c, 0x0780, 0x190c, 0x7382, 0x8004, - 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x7046, 0x7142, 0x7061, - 0x70d3, 0x080c, 0x0d85, 0x2009, 0x1948, 0x2104, 0x0002, 0x7026, - 0x7026, 0x7026, 0x6eb5, 0x7026, 0x6eb5, 0x0005, 0x2071, 0x1800, - 0x2900, 0x7822, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, - 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, - 0x0c60, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1904, - 0x70c2, 0x7830, 0xd0dc, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, - 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, - 0x1830, 0x210c, 0x918a, 0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0, - 0x200c, 0x8108, 0x2102, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, - 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899, - 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x19c8, 0x0e04, - 0x70b9, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, - 0x6836, 0x6833, 0x0013, 0x00de, 0x2001, 0x1921, 0x200c, 0xc184, - 0x2102, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x1200, 0x2001, 0x1922, 0x2003, 0x0000, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x2001, 0x1921, 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, - 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, - 0x8899, 0x0804, 0x7070, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, - 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, - 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, - 0x1d60, 0x00ee, 0x0e04, 0x7115, 0x7838, 0x7938, 0x910e, 0x1de0, - 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, - 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, - 0x190c, 0x1200, 0x704b, 0x0000, 0x782c, 0x9094, 0x0780, 0x190c, - 0x7382, 0xd09c, 0x1170, 0x009e, 0x2900, 0x7822, 0xa804, 0x900d, - 0x11e0, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, - 0x0c58, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, - 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, - 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, - 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, - 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, - 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, - 0x1904, 0x71b1, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, - 0x11b0, 0x701c, 0x904d, 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, - 0x8001, 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822, - 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x0d50, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x05b8, 0x00e6, 0x7824, - 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, - 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, 0x190c, - 0x7382, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, 0x71aa, 0x7838, 0x7938, - 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, - 0x00de, 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, - 0x2004, 0xd084, 0x190c, 0x1200, 0x704b, 0x0000, 0x00fe, 0x002e, - 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x00fe, 0x002e, 0x00ee, - 0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, - 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, - 0x70c2, 0x080c, 0x8899, 0x00ee, 0x0804, 0x7152, 0x2071, 0x1910, - 0xa803, 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, - 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, - 0x1128, 0x1e04, 0x71f1, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, - 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, - 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x0e04, - 0x71db, 0x2071, 0x1910, 0x701c, 0x2048, 0xa84c, 0x900d, 0x0d18, - 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, - 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, 0x1278, 0x2091, 0x4080, - 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x2071, 0x1910, - 0x080c, 0x736e, 0x002e, 0x00ee, 0x0005, 0xa850, 0x9082, 0x001c, - 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, - 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, - 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, - 0x013e, 0x01de, 0x014e, 0x0890, 0x2071, 0x1910, 0xa803, 0x0000, - 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, - 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1118, 0x002e, - 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, - 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, - 0x70c2, 0x080c, 0x8899, 0x002e, 0x00ee, 0x0005, 0x0006, 0xa87c, - 0x0006, 0xa867, 0x0103, 0x20a9, 0x001c, 0xa860, 0x20e8, 0xa85c, - 0x9080, 0x001d, 0x20a0, 0x9006, 0x4004, 0x000e, 0x9084, 0x00ff, - 0xa87e, 0x000e, 0xa87a, 0xa982, 0x0005, 0x2071, 0x1910, 0x7004, - 0x0002, 0x7281, 0x7282, 0x736d, 0x7282, 0x727f, 0x736d, 0x080c, - 0x0d85, 0x0005, 0x2001, 0x1948, 0x2004, 0x0002, 0x728c, 0x728c, - 0x7306, 0x7307, 0x728c, 0x7307, 0x0126, 0x2091, 0x8000, 0x1e0c, - 0x738d, 0x701c, 0x904d, 0x0508, 0xa84c, 0x9005, 0x0904, 0x72d7, - 0x0e04, 0x72b5, 0xa94c, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032, - 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0xa850, 0x9082, 0x0019, - 0x1278, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x1200, 0x2071, 0x1910, 0x080c, 0x736e, 0x012e, 0x0804, 0x7305, - 0xa850, 0x9082, 0x001c, 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, - 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, - 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, - 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, 0x0890, 0x2001, - 0x005b, 0x2004, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x2071, - 0x1910, 0x1510, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, - 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, - 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, - 0x2071, 0x1910, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, - 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, - 0x2008, 0x2069, 0x1a04, 0x6844, 0x9005, 0x0760, 0x0158, 0x9186, - 0x0003, 0x0540, 0x2001, 0x1815, 0x2004, 0x2009, 0x1b73, 0x210c, - 0x9102, 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c, - 0x6838, 0x9106, 0x0190, 0x0e04, 0x7339, 0x2069, 0x0000, 0x6837, - 0x8040, 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001, - 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x2069, 0x1a04, 0x6847, - 0xffff, 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x73fd, - 0x701c, 0x904d, 0x0540, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780, - 0x15c9, 0xd09c, 0x1500, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, - 0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, - 0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, - 0x00de, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, - 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x0126, 0x2091, - 0x8000, 0x701c, 0x904d, 0x0160, 0x7010, 0x8001, 0x7012, 0xa800, - 0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, 0x108b, 0x0005, - 0x012e, 0x0005, 0x2091, 0x8000, 0x0e04, 0x7384, 0x0006, 0x0016, - 0x2001, 0x8004, 0x0006, 0x0804, 0x0d8e, 0x0096, 0x00f6, 0x2079, - 0x0050, 0x7044, 0xd084, 0x01d0, 0xc084, 0x7046, 0x7838, 0x7938, - 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, - 0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, - 0x1200, 0x704b, 0x0000, 0x00fe, 0x009e, 0x0005, 0x782c, 0x9094, - 0x0780, 0x1981, 0xd0a4, 0x0db8, 0x7148, 0x704c, 0x8108, 0x714a, - 0x9102, 0x0e88, 0x00e6, 0x2071, 0x1800, 0x7824, 0x00e6, 0x2071, - 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, 0x1830, 0x210c, 0x918a, - 0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102, - 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e, - 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, - 0x190c, 0x7382, 0xd0a4, 0x19c8, 0x7838, 0x7938, 0x910e, 0x1de0, - 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, - 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x00ee, - 0x704b, 0x0000, 0x00fe, 0x009e, 0x0005, 0x00f6, 0x2079, 0x0050, - 0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, - 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, - 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, - 0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, - 0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, 0x702c, 0xa802, - 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, - 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x1d70, 0x00d6, 0x2069, - 0x0050, 0x693c, 0x2069, 0x1948, 0x6808, 0x690a, 0x2069, 0x1a04, - 0x9102, 0x1118, 0x6844, 0x9005, 0x1320, 0x2001, 0x1949, 0x200c, - 0x6946, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7098, 0x908a, 0x002a, - 0x1a0c, 0x0d85, 0x9082, 0x001d, 0x003b, 0x0026, 0x2011, 0x1e00, - 0x080c, 0x2ad3, 0x002e, 0x0005, 0x7542, 0x74af, 0x74cb, 0x74f5, - 0x7531, 0x7571, 0x7583, 0x74cb, 0x7559, 0x746a, 0x7498, 0x751b, - 0x7469, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180, - 0x6808, 0x9005, 0x1518, 0x709b, 0x0029, 0x2069, 0x198f, 0x2d04, - 0x7002, 0x080c, 0x78e4, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0, - 0x709b, 0x0029, 0x2069, 0x198f, 0x2d04, 0x7002, 0x6028, 0x9085, - 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a6e, - 0x080c, 0x1b1e, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, - 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005, - 0x1160, 0x709b, 0x0029, 0x2069, 0x198f, 0x2d04, 0x7002, 0x080c, - 0x7990, 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006, - 0x2001, 0x0090, 0x080c, 0x2a99, 0x000e, 0x6124, 0xd1e4, 0x1190, - 0x080c, 0x75f4, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, - 0x709b, 0x0020, 0x080c, 0x75f4, 0x0028, 0x709b, 0x001d, 0x0010, - 0x709b, 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x2a99, 0x6124, - 0xd1cc, 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, 0x1198, 0x9184, 0x1e00, - 0x11d8, 0x080c, 0x1b4b, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, - 0x080c, 0x77ca, 0x2001, 0x0080, 0x080c, 0x2a99, 0x709b, 0x0029, - 0x0058, 0x709b, 0x001e, 0x0040, 0x709b, 0x001d, 0x0028, 0x709b, - 0x0020, 0x0010, 0x709b, 0x001f, 0x0005, 0x080c, 0x1b4b, 0x60e3, - 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x77ca, 0x2001, 0x0080, - 0x080c, 0x2a99, 0x6124, 0xd1d4, 0x1198, 0xd1dc, 0x1170, 0xd1e4, - 0x1148, 0x9184, 0x1e00, 0x1118, 0x709b, 0x0029, 0x0058, 0x709b, - 0x0028, 0x0040, 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, - 0x709b, 0x001f, 0x0005, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, - 0xd1e4, 0x1130, 0x9184, 0x1e00, 0x1158, 0x709b, 0x0029, 0x0040, - 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, - 0x0005, 0x2001, 0x00a0, 0x080c, 0x2a99, 0x6124, 0xd1dc, 0x1138, - 0xd1e4, 0x0138, 0x080c, 0x1b4b, 0x709b, 0x001e, 0x0010, 0x709b, - 0x001d, 0x0005, 0x080c, 0x767d, 0x6124, 0xd1dc, 0x1188, 0x080c, - 0x75f4, 0x0016, 0x080c, 0x1b4b, 0x001e, 0xd1d4, 0x1128, 0xd1e4, - 0x0138, 0x709b, 0x001e, 0x0020, 0x709b, 0x001f, 0x080c, 0x75f4, - 0x0005, 0x0006, 0x2001, 0x00a0, 0x080c, 0x2a99, 0x000e, 0x6124, - 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, - 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x0021, - 0x0005, 0x080c, 0x767d, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, - 0xd1e4, 0x0140, 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, - 0x709b, 0x001f, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2a99, - 0x000e, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, - 0xd1e4, 0x0158, 0x709b, 0x001e, 0x0040, 0x709b, 0x001d, 0x0028, - 0x709b, 0x0020, 0x0010, 0x709b, 0x001f, 0x0005, 0x0016, 0x00c6, - 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, - 0x1800, 0x2091, 0x8000, 0x080c, 0x779e, 0x11f8, 0x2001, 0x180c, - 0x200c, 0xd1b4, 0x01d0, 0xc1b4, 0x2102, 0x0026, 0x2011, 0x0200, - 0x080c, 0x2ad3, 0x002e, 0x080c, 0x2a7f, 0x6024, 0xd0cc, 0x0148, - 0x2001, 0x00a0, 0x080c, 0x2a99, 0x080c, 0x7ab6, 0x080c, 0x619d, - 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x77b8, 0x0150, - 0x080c, 0x77af, 0x1138, 0x2001, 0x0001, 0x080c, 0x2631, 0x080c, - 0x7772, 0x00a0, 0x080c, 0x767a, 0x0178, 0x2001, 0x0001, 0x080c, - 0x2631, 0x7098, 0x9086, 0x001e, 0x0120, 0x7098, 0x9086, 0x0022, - 0x1118, 0x709b, 0x0025, 0x0010, 0x709b, 0x0021, 0x012e, 0x00ee, - 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x7605, 0x080c, - 0x8a9f, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x7605, - 0x080c, 0x8a96, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, - 0x080c, 0xa2a0, 0x2071, 0x1800, 0x080c, 0x759e, 0x001e, 0x00fe, - 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x0126, 0x2071, 0x1800, 0x080c, 0xa2a0, 0x2061, 0x0100, - 0x2069, 0x0140, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x080c, - 0xacfc, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, - 0xa635, 0x080c, 0xa516, 0x080c, 0x8a4b, 0x0036, 0x901e, 0x080c, - 0xa596, 0x003e, 0x080c, 0xad18, 0x60e3, 0x0000, 0x080c, 0xeed9, - 0x080c, 0xeef4, 0x2009, 0x0004, 0x080c, 0x2a85, 0x080c, 0x299b, - 0x2001, 0x1800, 0x2003, 0x0004, 0x2011, 0x0008, 0x080c, 0x2ad3, - 0x2011, 0x7605, 0x080c, 0x8a9f, 0x080c, 0x77b8, 0x0118, 0x9006, - 0x080c, 0x2a99, 0x080c, 0x0bcf, 0x2001, 0x0001, 0x080c, 0x2631, - 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, - 0x0005, 0x0026, 0x00e6, 0x2011, 0x7612, 0x2071, 0x1a04, 0x701c, - 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, 0x9085, 0x0001, 0x00ee, - 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, 0x9084, 0xfffe, - 0x9086, 0x00c0, 0x01b8, 0x2001, 0x00c0, 0x080c, 0x2a99, 0x0156, - 0x20a9, 0x002d, 0x1d04, 0x768a, 0x2091, 0x6000, 0x1f04, 0x768a, - 0x015e, 0x00d6, 0x2069, 0x1800, 0x689c, 0x8001, 0x0220, 0x0118, - 0x689e, 0x00de, 0x0005, 0x689f, 0x0014, 0x68ec, 0xd0dc, 0x0dc8, - 0x6800, 0x9086, 0x0001, 0x1da8, 0x080c, 0x8aab, 0x0c90, 0x00c6, - 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, - 0x080c, 0x7ac5, 0x2001, 0x196d, 0x2003, 0x0000, 0x9006, 0x709a, - 0x60e2, 0x6886, 0x080c, 0x2700, 0x9006, 0x080c, 0x2a99, 0x080c, - 0x6058, 0x0026, 0x2011, 0xffff, 0x080c, 0x2ad3, 0x002e, 0x602b, - 0x182c, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, - 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x197d, - 0x200c, 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, - 0x0002, 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x7762, 0x709b, - 0x0022, 0x0040, 0x709b, 0x0021, 0x0028, 0x709b, 0x0023, 0x0010, - 0x709b, 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, - 0x080c, 0x2700, 0x080c, 0xacfc, 0x0026, 0x080c, 0xafd2, 0x080c, - 0xb09b, 0x002e, 0x080c, 0xad18, 0x7000, 0x908e, 0x0004, 0x0118, - 0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, - 0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, 0x015e, - 0x080c, 0xd645, 0x0118, 0x9006, 0x080c, 0x2ac3, 0x0804, 0x776e, - 0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2a7f, 0x6904, - 0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2a99, 0x1f04, 0x7713, - 0x080c, 0x77f2, 0x012e, 0x015e, 0x080c, 0x77af, 0x0170, 0x6044, - 0x9005, 0x0130, 0x080c, 0x77f2, 0x9006, 0x8001, 0x1df0, 0x0028, - 0x6804, 0xd0d4, 0x1110, 0x080c, 0x77f2, 0x080c, 0xd645, 0x0118, - 0x9006, 0x080c, 0x2ac3, 0x0016, 0x0026, 0x7000, 0x908e, 0x0004, - 0x0130, 0x2009, 0x00c8, 0x2011, 0x7612, 0x080c, 0x8a5d, 0x002e, - 0x001e, 0x080c, 0x8890, 0x7034, 0xc085, 0x7036, 0x2001, 0x197d, - 0x2003, 0x0004, 0x080c, 0x744d, 0x080c, 0x77af, 0x0138, 0x6804, - 0xd0d4, 0x1120, 0xd0dc, 0x1100, 0x080c, 0x7abb, 0x00ee, 0x00de, - 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, - 0x0140, 0x2071, 0x1800, 0x080c, 0x88a7, 0x080c, 0x8899, 0x080c, - 0x7ac5, 0x2001, 0x196d, 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, - 0x6886, 0x080c, 0x2700, 0x9006, 0x080c, 0x2a99, 0x6043, 0x0090, - 0x6043, 0x0010, 0x0026, 0x2011, 0xffff, 0x080c, 0x2ad3, 0x002e, - 0x602b, 0x182c, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, - 0x197c, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x080c, - 0x5844, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006, - 0x080c, 0x5844, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, 0x0005, - 0x0006, 0x080c, 0x5844, 0x9084, 0x0030, 0x9086, 0x0010, 0x000e, - 0x0005, 0x0006, 0x080c, 0x5844, 0x9084, 0x0030, 0x9086, 0x0020, - 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x180c, 0x2004, 0x908c, - 0x0013, 0x0168, 0x0020, 0x080c, 0x2720, 0x900e, 0x0010, 0x2009, - 0x0002, 0x2019, 0x0028, 0x080c, 0x32da, 0x9006, 0x0019, 0x001e, - 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, 0x080c, - 0xd63e, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072, - 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, - 0x6004, 0x0006, 0x6028, 0x0006, 0x080c, 0x2af6, 0x080c, 0x2b29, - 0x602f, 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, - 0x20a9, 0x0002, 0x080c, 0x2a60, 0x0026, 0x2011, 0x0040, 0x080c, - 0x2ad3, 0x002e, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, - 0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, - 0x080c, 0x2700, 0x2001, 0x00a0, 0x0006, 0x080c, 0xd645, 0x000e, - 0x0130, 0x080c, 0x2ab7, 0x9006, 0x080c, 0x2ac3, 0x0010, 0x080c, - 0x2a99, 0x000e, 0x6052, 0x6050, 0x0006, 0xc0e5, 0x6052, 0x00f6, - 0x2079, 0x0100, 0x080c, 0x2a0c, 0x00fe, 0x000e, 0x6052, 0x0005, - 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0xad5a, 0x0158, - 0x2001, 0x0386, 0x2004, 0xd0b4, 0x1130, 0x2001, 0x0016, 0x080c, - 0xaced, 0x0804, 0x78d6, 0x2001, 0x180c, 0x200c, 0xc1c4, 0x2102, - 0x6028, 0x9084, 0xe1ff, 0x602a, 0x2011, 0x0200, 0x080c, 0x2ad3, - 0x2001, 0x0090, 0x080c, 0x2a99, 0x20a9, 0x0366, 0x6024, 0xd0cc, - 0x1560, 0x1d04, 0x786e, 0x2091, 0x6000, 0x1f04, 0x786e, 0x080c, - 0xacfc, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, - 0xa635, 0x080c, 0xa516, 0x901e, 0x080c, 0xa596, 0x2001, 0x0386, - 0x2003, 0x7000, 0x080c, 0xad18, 0x2001, 0x00a0, 0x080c, 0x2a99, - 0x080c, 0x7ab6, 0x080c, 0x619d, 0x080c, 0xd645, 0x0110, 0x080c, - 0x0cf1, 0x9085, 0x0001, 0x0804, 0x78dc, 0x080c, 0x1b4b, 0x60e3, - 0x0000, 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118, - 0x2001, 0x196d, 0x2004, 0x080c, 0x2700, 0x60e2, 0x2001, 0x0080, - 0x080c, 0x2a99, 0x20a9, 0x0366, 0x2011, 0x1e00, 0x080c, 0x2ad3, - 0x2009, 0x1e00, 0x080c, 0x2a7f, 0x6024, 0x910c, 0x0140, 0x1d04, - 0x78b4, 0x2091, 0x6000, 0x1f04, 0x78b4, 0x0804, 0x7877, 0x2001, - 0x0386, 0x2003, 0x7000, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b4, - 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xd645, - 0x0110, 0x080c, 0x0cf1, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e, - 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, - 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x7000, - 0x9086, 0x0003, 0x1168, 0x2001, 0x020b, 0x2004, 0x9084, 0x5540, - 0x9086, 0x5540, 0x1128, 0x2069, 0x1a7b, 0x2d04, 0x8000, 0x206a, - 0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005, - 0x1904, 0x794d, 0x2001, 0x0088, 0x080c, 0x2a99, 0x9006, 0x60e2, - 0x6886, 0x080c, 0x2700, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, - 0x6808, 0x9005, 0x01d0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x2011, - 0x0400, 0x080c, 0x2ad3, 0x2069, 0x198f, 0x7000, 0x206a, 0x709b, - 0x0026, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x792d, 0x2091, - 0x6000, 0x1f04, 0x792d, 0x0804, 0x7988, 0x2069, 0x0140, 0x20a9, - 0x0384, 0x2011, 0x1e00, 0x080c, 0x2ad3, 0x2009, 0x1e00, 0x080c, - 0x2a7f, 0x6024, 0x910c, 0x0528, 0x9084, 0x1a00, 0x1510, 0x1d04, - 0x7939, 0x2091, 0x6000, 0x1f04, 0x7939, 0x080c, 0xacfc, 0x2011, - 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, 0xa635, 0x080c, - 0xa516, 0x901e, 0x080c, 0xa596, 0x080c, 0xad18, 0x2001, 0x00a0, - 0x080c, 0x2a99, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001, - 0x00f8, 0x080c, 0x1b4b, 0x2001, 0x0080, 0x080c, 0x2a99, 0x2069, - 0x0140, 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, - 0x0008, 0x6886, 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, - 0x1118, 0x2001, 0x196d, 0x2004, 0x080c, 0x2700, 0x60e2, 0x9006, - 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, - 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, - 0x0100, 0x2071, 0x1800, 0x6020, 0x9084, 0x00c0, 0x01e8, 0x080c, - 0xacfc, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, - 0xa635, 0x080c, 0xa516, 0x901e, 0x080c, 0xa596, 0x080c, 0xad18, - 0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x2a99, 0x080c, 0x7ab6, - 0x080c, 0x619d, 0x0804, 0x7a32, 0x2001, 0x180c, 0x200c, 0xd1b4, - 0x1160, 0xc1b5, 0x2102, 0x080c, 0x75fa, 0x2069, 0x0140, 0x2001, - 0x0080, 0x080c, 0x2a99, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, - 0x9005, 0x1118, 0x6808, 0x9005, 0x0190, 0x6028, 0x9084, 0xfdff, - 0x602a, 0x2011, 0x0200, 0x080c, 0x2ad3, 0x2069, 0x198f, 0x7000, - 0x206a, 0x709b, 0x0027, 0x7003, 0x0001, 0x0804, 0x7a32, 0x2011, - 0x1e00, 0x080c, 0x2ad3, 0x2009, 0x1e00, 0x080c, 0x2a7f, 0x6024, - 0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x79e7, 0x0006, - 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x88e7, 0x00ee, 0x00de, - 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x1a04, 0x7078, 0x00ee, - 0x9005, 0x19e8, 0x0438, 0x0026, 0x2011, 0x7612, 0x080c, 0x8993, - 0x2011, 0x7605, 0x080c, 0x8a9f, 0x002e, 0x2069, 0x0140, 0x60e3, - 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, - 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118, 0x2001, - 0x196d, 0x2004, 0x080c, 0x2700, 0x60e2, 0x2001, 0x180c, 0x200c, - 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, - 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6, - 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x080c, 0xd63e, 0x1904, - 0x7aa0, 0x7130, 0xd184, 0x1170, 0x080c, 0x3482, 0x0138, 0xc18d, - 0x7132, 0x2011, 0x1848, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, - 0x0904, 0x7aa0, 0x2011, 0x1848, 0x220c, 0xd1a4, 0x0538, 0x0016, - 0x2019, 0x000e, 0x080c, 0xe9f9, 0x0156, 0x00b6, 0x20a9, 0x007f, - 0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c, - 0x67b4, 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, 0x080c, - 0xea8d, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8c44, 0x001e, - 0x8108, 0x1f04, 0x7a69, 0x00be, 0x015e, 0x001e, 0xd1ac, 0x1148, - 0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x32da, 0x001e, - 0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x67b4, - 0x1110, 0x080c, 0x61b7, 0x8108, 0x1f04, 0x7a96, 0x00be, 0x015e, - 0x080c, 0x1b4b, 0x080c, 0xacfc, 0x080c, 0xb09b, 0x080c, 0xad18, - 0x60e3, 0x0000, 0x080c, 0x619d, 0x080c, 0x76cd, 0x00ee, 0x00ce, - 0x004e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x197d, - 0x2003, 0x0001, 0x0005, 0x2001, 0x197d, 0x2003, 0x0000, 0x0005, - 0x2001, 0x197c, 0x2003, 0xaaaa, 0x0005, 0x2001, 0x197c, 0x2003, - 0x0000, 0x0005, 0x2071, 0x18fa, 0x7003, 0x0000, 0x7007, 0x0000, - 0x080c, 0x1072, 0x090c, 0x0d85, 0xa8ab, 0xdcb0, 0x2900, 0x704e, - 0x080c, 0x1072, 0x090c, 0x0d85, 0xa8ab, 0xdcb0, 0x2900, 0x7052, - 0xa867, 0x0000, 0xa86b, 0x0001, 0xa89f, 0x0000, 0x0005, 0x00e6, - 0x2071, 0x0040, 0x6848, 0x9005, 0x1118, 0x9085, 0x0001, 0x04b0, - 0x6840, 0x9005, 0x0150, 0x04a1, 0x6a50, 0x9200, 0x7002, 0x6854, - 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6850, 0x7002, 0x6854, - 0x7006, 0x6858, 0x700a, 0x685c, 0x700e, 0x6840, 0x9005, 0x1110, - 0x7012, 0x7016, 0x6848, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, - 0x2001, 0x0019, 0x7036, 0x702b, 0x0001, 0x2001, 0x0004, 0x200c, - 0x918c, 0xfff7, 0x918d, 0x8000, 0x2102, 0x00d6, 0x2069, 0x18fa, - 0x6807, 0x0001, 0x00de, 0x080c, 0x8103, 0x9006, 0x00ee, 0x0005, - 0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, 0x818d, 0x1f04, 0x7b2c, - 0x015e, 0x0005, 0x2079, 0x0040, 0x2071, 0x18fa, 0x7004, 0x0002, - 0x7b42, 0x7b43, 0x7b8f, 0x7bea, 0x7d4a, 0x7b40, 0x7b40, 0x7d74, - 0x080c, 0x0d85, 0x0005, 0x2079, 0x0040, 0x2001, 0x1dc0, 0x2003, - 0x0000, 0x782c, 0x908c, 0x0780, 0x190c, 0x81e5, 0xd0a4, 0x0578, - 0x2001, 0x1dc0, 0x2004, 0x9082, 0x0080, 0x1648, 0x1d04, 0x7b60, - 0x2001, 0x1a07, 0x200c, 0x8109, 0x0510, 0x2091, 0x6000, 0x2102, - 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, - 0x908a, 0x0040, 0x0610, 0x00c0, 0x2001, 0x1800, 0x200c, 0x9186, - 0x0003, 0x1168, 0x7004, 0x0002, 0x7b7f, 0x7b49, 0x7b7f, 0x7b7d, - 0x7b7f, 0x7b7f, 0x7b7f, 0x7b7f, 0x7b7f, 0x080c, 0x7bea, 0x782c, - 0xd09c, 0x090c, 0x8103, 0x0005, 0x9082, 0x005a, 0x1218, 0x2100, - 0x003b, 0x0c10, 0x080c, 0x7c20, 0x0c90, 0x00e3, 0x08e8, 0x0005, - 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c42, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c2c, 0x7c20, 0x7e6a, 0x7c20, - 0x7c20, 0x7c20, 0x7c42, 0x7c20, 0x7c2c, 0x7eab, 0x7eec, 0x7f33, - 0x7f47, 0x7c20, 0x7c20, 0x7c42, 0x7c2c, 0x7c56, 0x7c20, 0x7d1e, - 0x7ff2, 0x800d, 0x7c20, 0x7c42, 0x7c20, 0x7c56, 0x7c20, 0x7c20, - 0x7d14, 0x800d, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c20, 0x7c20, 0x7c20, 0x7c6a, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x8189, 0x7c20, 0x8133, - 0x7c20, 0x8133, 0x7c20, 0x7c7f, 0x7c20, 0x7c20, 0x7c20, 0x7c20, - 0x7c20, 0x7c20, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, 0x1198, - 0x782c, 0x080c, 0x812c, 0xd0a4, 0x0170, 0x7824, 0x2048, 0x9006, - 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210, - 0x002b, 0x0c50, 0x00e9, 0x080c, 0x8103, 0x0005, 0x7c20, 0x7c2c, - 0x7e56, 0x7c20, 0x7c2c, 0x7c20, 0x7c2c, 0x7c2c, 0x7c20, 0x7c2c, - 0x7e56, 0x7c2c, 0x7c2c, 0x7c2c, 0x7c2c, 0x7c2c, 0x7c20, 0x7c2c, - 0x7e56, 0x7c20, 0x7c20, 0x7c2c, 0x7c20, 0x7c20, 0x7c20, 0x7c2c, - 0x00e6, 0x2071, 0x18fa, 0x2009, 0x0400, 0x0071, 0x00ee, 0x0005, - 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, 0x0005, - 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, 0xa868, 0x9084, - 0x00ff, 0x9105, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, - 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001, - 0x1120, 0x7007, 0x0001, 0x0804, 0x7df3, 0x7007, 0x0003, 0x7012, - 0x2900, 0x7016, 0x701a, 0x704b, 0x7df3, 0x0005, 0xa864, 0x8007, - 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, - 0x7e0e, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, - 0x7e0e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0904, 0x7c28, - 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7e2a, 0x7007, 0x0003, - 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7e2a, 0x0005, 0xa864, - 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7c28, 0x7007, - 0x0001, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1904, 0x7ceb, 0x2001, - 0x180d, 0x2004, 0xd08c, 0x0904, 0x7cd6, 0xa99c, 0x9186, 0x00ff, - 0x05e8, 0xa994, 0x9186, 0x006f, 0x0188, 0x9186, 0x0074, 0x15b0, - 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e, 0x0578, 0x0016, - 0xa998, 0x080c, 0x6c7f, 0x001e, 0x1548, 0x0400, 0x080c, 0x779e, - 0x0140, 0xa897, 0x4005, 0xa89b, 0x0016, 0x2001, 0x0030, 0x900e, - 0x0438, 0x0026, 0x2011, 0x8008, 0x080c, 0x6c35, 0x002e, 0x01b0, - 0x0016, 0x0026, 0x0036, 0xa998, 0xaaa0, 0xab9c, 0x918d, 0x8000, - 0x080c, 0x6c7f, 0x003e, 0x002e, 0x001e, 0x1140, 0xa897, 0x4005, - 0xa89b, 0x4009, 0x2001, 0x0030, 0x900e, 0x0050, 0xa868, 0x9084, - 0x00ff, 0xa86a, 0xa883, 0x0000, 0x080c, 0x6430, 0x1108, 0x0005, - 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0xa87a, 0xa982, 0x080c, - 0x7012, 0x012e, 0x0ca0, 0xa994, 0x9186, 0x0071, 0x0904, 0x7c8f, - 0x9186, 0x0064, 0x0904, 0x7c8f, 0x9186, 0x007c, 0x0904, 0x7c8f, - 0x9186, 0x0028, 0x0904, 0x7c8f, 0x9186, 0x0038, 0x0904, 0x7c8f, - 0x9186, 0x0078, 0x0904, 0x7c8f, 0x9186, 0x005f, 0x0904, 0x7c8f, - 0x9186, 0x0056, 0x0904, 0x7c8f, 0xa897, 0x4005, 0xa89b, 0x0001, - 0x2001, 0x0030, 0x900e, 0x0860, 0xa87c, 0x9084, 0x00c0, 0x9086, - 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x8024, 0x2900, 0x7016, - 0x701a, 0x20a9, 0x0004, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0030, - 0x2098, 0x7050, 0x2040, 0xa060, 0x20e8, 0xa05c, 0x9080, 0x0023, - 0x20a0, 0x4003, 0xa888, 0x7012, 0x9082, 0x0401, 0x1a04, 0x7c30, - 0xaab4, 0x928a, 0x0002, 0x1a04, 0x7c30, 0x82ff, 0x1138, 0xa8b8, - 0xa9bc, 0x9105, 0x0118, 0x2001, 0x7db1, 0x0018, 0x9280, 0x7da7, - 0x2005, 0x7056, 0x7010, 0x9015, 0x0904, 0x7d92, 0x080c, 0x1072, - 0x1118, 0x7007, 0x0004, 0x0005, 0x2900, 0x7022, 0x7054, 0x2060, - 0xe000, 0xa866, 0x7050, 0x2040, 0xa95c, 0xe004, 0x9100, 0xa076, - 0xa860, 0xa072, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, 0x7112, - 0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, 0xa17a, - 0x810b, 0xa17e, 0x080c, 0x114e, 0xa06c, 0x908e, 0x0100, 0x0170, - 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, 0x2048, - 0x080c, 0x108b, 0x7014, 0x2048, 0x0804, 0x7c30, 0x7020, 0x2048, - 0x7018, 0xa802, 0xa807, 0x0000, 0x2908, 0x2048, 0xa906, 0x711a, - 0x0804, 0x7d4a, 0x7014, 0x2048, 0x7007, 0x0001, 0xa8b4, 0x9005, - 0x1128, 0xa8b8, 0xa9bc, 0x9105, 0x0108, 0x00b9, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x001e, 0x0904, 0x8024, 0x0804, 0x7df3, 0x7da9, - 0x7dad, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, 0x0005, - 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x0076, 0x0066, 0xafb8, - 0xaebc, 0xa804, 0x2050, 0xb0c0, 0xb0e2, 0xb0bc, 0xb0de, 0xb0b8, - 0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, 0xb7d6, 0xb0b0, 0xb0ca, 0xb0ac, - 0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, 0xb0b6, 0xb6c2, 0xb7be, 0xb0a0, - 0xb0b2, 0xb09c, 0xb0ae, 0xb098, 0xb0a2, 0xb094, 0xb09e, 0xb6aa, - 0xb7a6, 0xb090, 0xb09a, 0xb08c, 0xb096, 0xb088, 0xb08a, 0xb084, - 0xb086, 0xb692, 0xb78e, 0xb080, 0xb082, 0xb07c, 0xb07e, 0xb078, - 0xb072, 0xb074, 0xb06e, 0xb67a, 0xb776, 0xb004, 0x9055, 0x1958, - 0x006e, 0x007e, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1178, - 0x080c, 0x622f, 0x1108, 0x0005, 0x080c, 0x725e, 0x0126, 0x2091, - 0x8000, 0x080c, 0xd220, 0x080c, 0x7012, 0x012e, 0x0ca0, 0x080c, - 0xd63e, 0x1d70, 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009, 0x1834, - 0x210c, 0x81ff, 0x1188, 0xa888, 0x9005, 0x0188, 0xa883, 0x0000, - 0x080c, 0x62bd, 0x1108, 0x0005, 0xa87a, 0x0126, 0x2091, 0x8000, - 0x080c, 0x7012, 0x012e, 0x0cb8, 0x2001, 0x0028, 0x0ca8, 0x2001, - 0x0000, 0x0c90, 0x0419, 0x11d8, 0xa888, 0x9005, 0x01e0, 0xa883, - 0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, 0x6392, 0x1138, 0x0005, - 0x9006, 0xa87a, 0x080c, 0x630a, 0x1108, 0x0005, 0x0126, 0x2091, - 0x8000, 0xa87a, 0xa982, 0x080c, 0x7012, 0x012e, 0x0cb0, 0x2001, - 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, 0x0c80, 0x00c6, 0x2061, - 0x1800, 0x60d0, 0x9005, 0x0100, 0x00ce, 0x0005, 0x7018, 0xa802, - 0x2908, 0x2048, 0xa906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, - 0x7007, 0x0003, 0x0030, 0x7014, 0x2048, 0x7007, 0x0001, 0x7048, - 0x080f, 0x0005, 0x00b6, 0x7007, 0x0001, 0xa974, 0xa878, 0x9084, - 0x00ff, 0x9096, 0x0004, 0x0540, 0x20a9, 0x0001, 0x9096, 0x0001, - 0x0190, 0x900e, 0x20a9, 0x0800, 0x9096, 0x0002, 0x0160, 0x9005, - 0x11d8, 0xa974, 0x080c, 0x67b4, 0x11b8, 0x0066, 0xae80, 0x080c, - 0x68c4, 0x006e, 0x0088, 0x0046, 0x2011, 0x180c, 0x2224, 0xc484, - 0x2412, 0x004e, 0x00c6, 0x080c, 0x67b4, 0x1110, 0x080c, 0x6a9e, - 0x8108, 0x1f04, 0x7e93, 0x00ce, 0xa87c, 0xd084, 0x1120, 0x080c, - 0x108b, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, - 0x012e, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, - 0x080c, 0x6c0d, 0x0580, 0x2061, 0x1a73, 0x6100, 0xd184, 0x0178, - 0xa888, 0x9084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004, - 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011, - 0x0001, 0xa890, 0x9005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016, - 0xa888, 0x9084, 0x00ff, 0x0178, 0x6006, 0xa888, 0x8007, 0x9084, - 0x00ff, 0x0148, 0x600a, 0xa888, 0x8000, 0x1108, 0xc28d, 0x6202, - 0x012e, 0x0804, 0x80ed, 0x012e, 0x0804, 0x80e7, 0x012e, 0x0804, - 0x80e1, 0x012e, 0x0804, 0x80e4, 0x0126, 0x2091, 0x8000, 0x7007, - 0x0001, 0x080c, 0x6c0d, 0x05e0, 0x2061, 0x1a73, 0x6000, 0xd084, - 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0xac78, 0x9484, 0x0003, - 0x0170, 0xa988, 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100, 0x9210, - 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0, 0x9484, - 0x000c, 0x0188, 0xa988, 0x810f, 0x918c, 0x00ff, 0x9082, 0x0004, - 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, 0x9082, 0x0004, 0x1168, - 0x2100, 0x931a, 0x0250, 0xa890, 0x9005, 0x0110, 0x8000, 0x6016, - 0x6206, 0x630a, 0x012e, 0x0804, 0x80ed, 0x012e, 0x0804, 0x80ea, - 0x012e, 0x0804, 0x80e7, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, - 0x2061, 0x1a73, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, - 0x630a, 0x012e, 0x0804, 0x80fb, 0x012e, 0x0804, 0x80ea, 0x00b6, - 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0xa87c, 0xd0ac, - 0x0148, 0x00c6, 0x2061, 0x1a73, 0x6000, 0x9084, 0xfcff, 0x6002, - 0x00ce, 0x0440, 0xa888, 0x9005, 0x05d8, 0xa88c, 0x9065, 0x0598, - 0x2001, 0x1834, 0x2004, 0x9005, 0x0118, 0x080c, 0xb1a7, 0x0068, - 0x6017, 0xf400, 0x6063, 0x0000, 0xa97c, 0xd1a4, 0x0110, 0xa980, - 0x6162, 0x2009, 0x0041, 0x080c, 0xb20a, 0xa988, 0x918c, 0xff00, - 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, 0x080c, - 0x8c44, 0x002e, 0xa87c, 0xd0c4, 0x0148, 0x2061, 0x1a73, 0x6000, - 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, - 0x00be, 0x0804, 0x80ed, 0x00ce, 0x012e, 0x00be, 0x0804, 0x80e7, - 0xa984, 0x9186, 0x002e, 0x0d30, 0x9186, 0x002d, 0x0d18, 0x9186, - 0x0045, 0x0510, 0x9186, 0x002a, 0x1130, 0x2001, 0x180c, 0x200c, - 0xc194, 0x2102, 0x08b8, 0x9186, 0x0020, 0x0158, 0x9186, 0x0029, - 0x1d10, 0xa974, 0x080c, 0x67b4, 0x1968, 0xb800, 0xc0e4, 0xb802, - 0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, 0x0024, 0x2001, 0x1986, - 0x2004, 0x601a, 0x0804, 0x7f82, 0xa88c, 0x9065, 0x0960, 0x00e6, - 0xa890, 0x9075, 0x2001, 0x1834, 0x2004, 0x9005, 0x0150, 0x080c, - 0xb1a7, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xb1a7, 0x00ee, 0x0804, - 0x7f82, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, - 0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, 0xa8a4, 0x602e, 0xa8a8, - 0x6016, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x00ee, - 0x0804, 0x7f82, 0x2061, 0x1a73, 0x6000, 0xd084, 0x0190, 0xd08c, - 0x1904, 0x80fb, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, 0x0220, - 0x6206, 0x012e, 0x0804, 0x80fb, 0x012e, 0xa883, 0x0016, 0x0804, - 0x80f4, 0xa883, 0x0007, 0x0804, 0x80f4, 0xa864, 0x8007, 0x9084, - 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, 0x0005, - 0x080c, 0x7c28, 0x0040, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, - 0x701a, 0x704b, 0x8024, 0x0005, 0x00b6, 0x00e6, 0x0126, 0x2091, - 0x8000, 0x903e, 0x2061, 0x1800, 0x61d0, 0x81ff, 0x1904, 0x80a6, - 0x6130, 0xd194, 0x1904, 0x80d0, 0xa878, 0x2070, 0x9e82, 0x1ddc, - 0x0a04, 0x809a, 0x6068, 0x9e02, 0x1a04, 0x809a, 0x7120, 0x9186, - 0x0006, 0x1904, 0x808c, 0x7010, 0x905d, 0x0904, 0x80a6, 0xb800, - 0xd0e4, 0x1904, 0x80ca, 0x2061, 0x1a73, 0x6100, 0x9184, 0x0301, - 0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, 0x1904, 0x80d3, 0xa883, - 0x0000, 0xa803, 0x0000, 0x2908, 0x7014, 0x9005, 0x1198, 0x7116, - 0xa87c, 0xd0f4, 0x1904, 0x80d6, 0x080c, 0x5840, 0xd09c, 0x1118, - 0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, 0x8b34, 0x012e, 0x00ee, - 0x00be, 0x0005, 0x2048, 0xa800, 0x9005, 0x1de0, 0xa902, 0x2148, - 0xa87c, 0xd0f4, 0x1904, 0x80d6, 0x012e, 0x00ee, 0x00be, 0x0005, - 0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, 0x0804, 0x80f4, 0xd184, - 0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, 0x080c, 0x67b4, 0x15d0, - 0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, 0xa883, - 0x0002, 0x0490, 0xa883, 0x0008, 0x0478, 0xa883, 0x000e, 0x0460, - 0xa883, 0x0017, 0x0448, 0xa883, 0x0035, 0x0430, 0x080c, 0x5844, - 0xd0fc, 0x01e8, 0xa878, 0x2070, 0x9e82, 0x1ddc, 0x02c0, 0x6068, - 0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, 0x905d, - 0x0170, 0xb800, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0x9086, - 0x0007, 0x1904, 0x8030, 0x7003, 0x0002, 0x0804, 0x8030, 0xa883, - 0x0028, 0x0010, 0xa883, 0x0029, 0x012e, 0x00ee, 0x00be, 0x0420, - 0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, 0x0cb0, 0x2e60, 0x2019, - 0x0002, 0x601b, 0x0014, 0x080c, 0xe586, 0x012e, 0x00ee, 0x00be, - 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, - 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0xa884, - 0x9084, 0xff00, 0x9105, 0xa886, 0x0126, 0x2091, 0x8000, 0x080c, - 0x7012, 0x012e, 0x0005, 0x080c, 0x108b, 0x0005, 0x00d6, 0x080c, - 0x8b2b, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, 0x908c, 0x0780, 0x190c, - 0x81e5, 0xd09c, 0x11a8, 0x2071, 0x1800, 0x70c0, 0x90ea, 0x0020, - 0x0278, 0x8001, 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e, 0x9006, - 0xa802, 0xa806, 0x2071, 0x0040, 0x2900, 0x7022, 0x702c, 0x0c28, - 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, 0x190c, - 0x81e5, 0x000e, 0x0005, 0xa898, 0x9084, 0x0003, 0x05a8, 0x080c, - 0xb116, 0x05d8, 0x2900, 0x6016, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0035, 0x1138, 0x6028, 0xc0fd, 0x602a, 0x2001, 0x196b, 0x2004, - 0x0098, 0xa8a0, 0x9084, 0x00ff, 0xa99c, 0x918c, 0xff00, 0x9105, - 0xa99c, 0x918c, 0x00ff, 0x080c, 0x268c, 0x1540, 0x00b6, 0x080c, - 0x67b4, 0x2b00, 0x00be, 0x1510, 0x6012, 0x6023, 0x0001, 0x2009, - 0x0040, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x0110, 0x2009, - 0x0041, 0x080c, 0xb20a, 0x0005, 0xa87b, 0x0101, 0x0126, 0x2091, - 0x8000, 0x080c, 0x7012, 0x012e, 0x0005, 0xa87b, 0x002c, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x0005, 0xa87b, 0x0028, - 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c, - 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x00b6, 0x7007, - 0x0001, 0xaa74, 0x9282, 0x0004, 0x1a04, 0x81d6, 0xa97c, 0x9188, - 0x1000, 0x2104, 0x905d, 0xb804, 0xd284, 0x0140, 0x05e8, 0x8007, - 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04b0, 0x2b10, 0x080c, - 0xb116, 0x1118, 0x080c, 0xb1dd, 0x05a8, 0x6212, 0xa874, 0x0002, - 0x81b4, 0x81b9, 0x81bc, 0x81c2, 0x2019, 0x0002, 0x080c, 0xe9f9, - 0x0060, 0x080c, 0xe984, 0x0048, 0x2019, 0x0002, 0xa980, 0x080c, - 0xe9a3, 0x0018, 0xa980, 0x080c, 0xe984, 0x080c, 0xb16c, 0xa887, - 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x00be, - 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0xa887, 0x0006, - 0x0c80, 0xa887, 0x0002, 0x0c68, 0xa887, 0x0005, 0x0c50, 0xa887, - 0x0004, 0x0c38, 0xa887, 0x0007, 0x0c20, 0x2091, 0x8000, 0x0e04, - 0x81e7, 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, 0x0d8e, - 0x2001, 0x1834, 0x2004, 0x9005, 0x0005, 0x0005, 0x00f6, 0x2079, - 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009, - 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x1648, 0x00fe, 0x0005, - 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe, 0x0005, - 0x781c, 0xd08c, 0x0904, 0x8268, 0x68c0, 0x90aa, 0x0005, 0x0a04, - 0x8890, 0x7d44, 0x7c40, 0xd59c, 0x190c, 0x0d85, 0x9584, 0x00f6, - 0x1508, 0x9484, 0x7000, 0x0138, 0x908a, 0x2000, 0x1258, 0x9584, - 0x0700, 0x8007, 0x04f0, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, - 0x0db0, 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, - 0x9086, 0x8100, 0x11c0, 0x080c, 0xeeb1, 0x080c, 0x8777, 0x7817, - 0x0140, 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x87d3, 0x19c8, - 0xd5a4, 0x0148, 0x0046, 0x0056, 0x080c, 0x82b8, 0x080c, 0x2185, - 0x005e, 0x004e, 0x0020, 0x080c, 0xeeb1, 0x7817, 0x0140, 0x080c, - 0x779e, 0x0168, 0x2001, 0x0111, 0x2004, 0xd08c, 0x0140, 0x6893, - 0x0000, 0x2001, 0x0110, 0x2003, 0x0008, 0x2003, 0x0000, 0x0489, - 0x0005, 0x0002, 0x8275, 0x8585, 0x8272, 0x8272, 0x8272, 0x8272, - 0x8272, 0x8272, 0x7817, 0x0140, 0x0005, 0x7000, 0x908c, 0xff00, - 0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x6892, 0x9286, 0x2000, - 0x1150, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, 0x58aa, 0x0070, - 0x080c, 0x82d8, 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, 0x84bf, - 0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x86a4, 0x7817, 0x0140, - 0x0005, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0178, 0x2001, 0x1800, - 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, 0x8048, - 0x2518, 0x080c, 0x4ca1, 0x003e, 0x002e, 0x0005, 0x0036, 0x0046, - 0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe, 0x7c30, 0x0050, - 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x7d44, 0x7c40, - 0x2019, 0xffff, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0160, 0x2001, - 0x1800, 0x2004, 0x9086, 0x0003, 0x1130, 0x0026, 0x2011, 0x8048, - 0x080c, 0x4ca1, 0x002e, 0x00fe, 0x005e, 0x004e, 0x003e, 0x0005, - 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, 0x0001, - 0x0120, 0x9096, 0x0023, 0x1904, 0x8490, 0x9186, 0x0023, 0x15c0, - 0x080c, 0x8742, 0x0904, 0x8490, 0x6120, 0x9186, 0x0001, 0x0150, - 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, 0x9186, 0x000a, - 0x1904, 0x8490, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130, - 0x2009, 0x0015, 0x080c, 0xb20a, 0x0804, 0x8490, 0x908e, 0x0214, - 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0xb20a, - 0x0804, 0x8490, 0x908e, 0x0100, 0x1904, 0x8490, 0x7034, 0x9005, - 0x1904, 0x8490, 0x2009, 0x0016, 0x080c, 0xb20a, 0x0804, 0x8490, - 0x9186, 0x0022, 0x1904, 0x8490, 0x7030, 0x908e, 0x0300, 0x1580, - 0x68dc, 0xd0a4, 0x0528, 0xc0b5, 0x68de, 0x7100, 0x918c, 0x00ff, - 0x697e, 0x7004, 0x6882, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, - 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x26d5, 0x7932, - 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x268c, 0x695e, 0x703c, - 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1800, 0x70b6, 0x00ee, - 0x7034, 0x9005, 0x1904, 0x8490, 0x2009, 0x0017, 0x0804, 0x8440, - 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, 0x8490, 0x080c, - 0x779e, 0x0120, 0x2009, 0x001d, 0x0804, 0x8440, 0x68dc, 0xc0a5, - 0x68de, 0x2009, 0x0030, 0x0804, 0x8440, 0x908e, 0x0500, 0x1140, - 0x7034, 0x9005, 0x1904, 0x8490, 0x2009, 0x0018, 0x0804, 0x8440, - 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x8440, 0x908e, - 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x8440, 0x908e, 0x5200, - 0x1140, 0x7034, 0x9005, 0x1904, 0x8490, 0x2009, 0x001b, 0x0804, - 0x8440, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, 0x8490, - 0x2009, 0x001c, 0x0804, 0x8440, 0x908e, 0x1300, 0x1120, 0x2009, - 0x0034, 0x0804, 0x8440, 0x908e, 0x1200, 0x1140, 0x7034, 0x9005, - 0x1904, 0x8490, 0x2009, 0x0024, 0x0804, 0x8440, 0x908c, 0xff00, - 0x918e, 0x2400, 0x1170, 0x2009, 0x002d, 0x2001, 0x1810, 0x2004, - 0xd09c, 0x0904, 0x8440, 0x080c, 0xdd8d, 0x1904, 0x8490, 0x0804, - 0x843e, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, 0x002a, - 0x0804, 0x8440, 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804, - 0x8440, 0x908e, 0x6104, 0x1530, 0x2029, 0x0205, 0x2011, 0x026d, - 0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011, - 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x4ca1, 0x004e, - 0x8108, 0x0f04, 0x83f4, 0x9186, 0x0280, 0x1d88, 0x2504, 0x8000, - 0x202a, 0x2009, 0x0260, 0x0c58, 0x202b, 0x0000, 0x2009, 0x0023, - 0x0804, 0x8440, 0x908e, 0x6000, 0x1120, 0x2009, 0x003f, 0x0804, - 0x8440, 0x908e, 0x5400, 0x1138, 0x080c, 0x8840, 0x1904, 0x8490, - 0x2009, 0x0046, 0x04a8, 0x908e, 0x5500, 0x1148, 0x080c, 0x8868, - 0x1118, 0x2009, 0x0041, 0x0460, 0x2009, 0x0042, 0x0448, 0x908e, - 0x7800, 0x1118, 0x2009, 0x0045, 0x0418, 0x908e, 0x1000, 0x1118, - 0x2009, 0x004e, 0x00e8, 0x908e, 0x6300, 0x1118, 0x2009, 0x004a, - 0x00b8, 0x908c, 0xff00, 0x918e, 0x5600, 0x1118, 0x2009, 0x004f, - 0x0078, 0x908c, 0xff00, 0x918e, 0x5700, 0x1118, 0x2009, 0x0050, - 0x0038, 0x2009, 0x001d, 0x6838, 0xd0d4, 0x0110, 0x2009, 0x004c, - 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x268c, - 0x1904, 0x8493, 0x080c, 0x6749, 0x1904, 0x8493, 0xbe12, 0xbd16, - 0x001e, 0x0016, 0x080c, 0x779e, 0x01c0, 0x68dc, 0xd08c, 0x1148, - 0x7000, 0x9084, 0x00ff, 0x1188, 0x7004, 0x9084, 0xff00, 0x1168, - 0x0040, 0x687c, 0x9606, 0x1148, 0x6880, 0x9506, 0x9084, 0xff00, - 0x1120, 0x9584, 0x00ff, 0xb886, 0x0080, 0xb884, 0x9005, 0x1168, - 0x9186, 0x0046, 0x1150, 0x687c, 0x9606, 0x1138, 0x6880, 0x9506, - 0x9084, 0xff00, 0x1110, 0x001e, 0x0098, 0x080c, 0xb116, 0x01a8, - 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x9186, - 0x004c, 0x1110, 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, 0xb20a, - 0x00ce, 0x00be, 0x0005, 0x001e, 0x0cd8, 0x2001, 0x180e, 0x2004, - 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4ca1, 0x080c, 0xb1dd, - 0x0d90, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, - 0x0016, 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, 0x6007, - 0x0009, 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, 0x0000, - 0x602f, 0x0009, 0x6003, 0x0001, 0x080c, 0x961e, 0x08a0, 0x080c, - 0x88af, 0x1158, 0x080c, 0x344c, 0x1140, 0x7010, 0x9084, 0xff00, - 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005, 0x00b6, 0x00c6, - 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, 0x0033, 0x11e8, - 0x080c, 0x8742, 0x0904, 0x851d, 0x7124, 0x610a, 0x7030, 0x908e, - 0x0200, 0x1140, 0x7034, 0x9005, 0x15c0, 0x2009, 0x0015, 0x080c, - 0xb20a, 0x0498, 0x908e, 0x0100, 0x1580, 0x7034, 0x9005, 0x1568, - 0x2009, 0x0016, 0x080c, 0xb20a, 0x0440, 0x9186, 0x0032, 0x1528, - 0x7030, 0x908e, 0x1400, 0x1508, 0x2009, 0x0038, 0x0016, 0x2011, - 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x268c, 0x11a8, 0x080c, - 0x6749, 0x1190, 0xbe12, 0xbd16, 0x080c, 0xb116, 0x0168, 0x2b08, - 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, - 0x080c, 0xb20a, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x00be, - 0x0005, 0x00b6, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0x9696, - 0x00ff, 0x11b8, 0x9592, 0xfffc, 0x02a0, 0x9596, 0xfffd, 0x1120, - 0x2009, 0x007f, 0x0804, 0x857f, 0x9596, 0xfffe, 0x1120, 0x2009, - 0x007e, 0x0804, 0x857f, 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080, - 0x04f0, 0x2011, 0x0000, 0x2019, 0x1837, 0x231c, 0xd3ac, 0x0130, - 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x0081, - 0x20a9, 0x077f, 0x2071, 0x1081, 0x2e1c, 0x93dd, 0x0000, 0x1140, - 0x82ff, 0x11d0, 0x9496, 0x00ff, 0x01b8, 0x2410, 0xc2fd, 0x00a0, - 0xbf10, 0x2600, 0x9706, 0xb814, 0x1120, 0x9546, 0x1110, 0x2408, - 0x00b0, 0x9745, 0x1148, 0x94c6, 0x007e, 0x0130, 0x94c6, 0x007f, - 0x0118, 0x94c6, 0x0080, 0x1d20, 0x8420, 0x8e70, 0x1f04, 0x8554, - 0x82ff, 0x1118, 0x9085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0x9006, - 0x00de, 0x00ee, 0x004e, 0x00be, 0x0005, 0x2001, 0x1837, 0x200c, - 0x9184, 0x0080, 0x0110, 0xd18c, 0x0138, 0x7000, 0x908c, 0xff00, - 0x810f, 0x9184, 0x000f, 0x001a, 0x7817, 0x0140, 0x0005, 0x85a7, - 0x85a7, 0x85a7, 0x8754, 0x85a7, 0x85aa, 0x85cf, 0x8658, 0x85a7, - 0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x7817, - 0x0140, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7120, 0x2160, - 0x9c8c, 0x0003, 0x11c0, 0x9c8a, 0x1ddc, 0x02a8, 0x6868, 0x9c02, - 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, - 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009, - 0x0046, 0x080c, 0xb20a, 0x7817, 0x0140, 0x00be, 0x0005, 0x00b6, - 0x00c6, 0x9484, 0x0fff, 0x0904, 0x8634, 0x7110, 0xd1bc, 0x1904, - 0x8634, 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, - 0xff00, 0x15c8, 0x81ff, 0x15b8, 0x9080, 0x348e, 0x200d, 0x918c, - 0xff00, 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, 0x8634, 0x9182, - 0x0801, 0x1a04, 0x8634, 0x9190, 0x1000, 0x2204, 0x905d, 0x05e0, - 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15b8, 0xba04, 0x9294, 0xff00, - 0x9286, 0x0600, 0x1190, 0x080c, 0xb116, 0x0598, 0x2b08, 0x7028, - 0x604e, 0x702c, 0x6052, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, - 0x7130, 0x615e, 0x080c, 0xe009, 0x00f8, 0x080c, 0x6c11, 0x1138, - 0xb807, 0x0606, 0x0c40, 0x190c, 0x8521, 0x11b0, 0x0880, 0x080c, - 0xb116, 0x2b08, 0x0188, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, - 0x9286, 0x0400, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, - 0x6003, 0x0001, 0x080c, 0x961e, 0x7817, 0x0140, 0x00ce, 0x00be, - 0x0005, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, - 0x080c, 0x4ca1, 0x080c, 0xb1dd, 0x0d78, 0x2b08, 0x6112, 0x6023, - 0x0006, 0x7120, 0x610a, 0x7130, 0x615e, 0x6017, 0xf300, 0x6003, - 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9617, 0x08e0, - 0x00b6, 0x7110, 0xd1bc, 0x05d0, 0x7020, 0x2060, 0x9c84, 0x0003, - 0x15a8, 0x9c82, 0x1ddc, 0x0690, 0x6868, 0x9c02, 0x1678, 0x9484, - 0x0fff, 0x9082, 0x000c, 0x0650, 0x7008, 0x9084, 0x00ff, 0x6110, - 0x2158, 0xb910, 0x9106, 0x1510, 0x700c, 0xb914, 0x9106, 0x11f0, - 0x7124, 0x610a, 0x601c, 0xd0fc, 0x11c8, 0x2001, 0x0271, 0x2004, - 0x9005, 0x1180, 0x9484, 0x0fff, 0x9082, 0x000c, 0x0158, 0x0066, - 0x2031, 0x0100, 0xa001, 0xa001, 0x8631, 0x1de0, 0x006e, 0x601c, - 0xd0fc, 0x1120, 0x2009, 0x0045, 0x080c, 0xb20a, 0x7817, 0x0140, - 0x00be, 0x0005, 0x6120, 0x9186, 0x0002, 0x0128, 0x9186, 0x0005, - 0x0110, 0x9085, 0x0001, 0x0005, 0x080c, 0x88af, 0x1180, 0x080c, - 0x344c, 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, 0x0000, - 0x1130, 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, 0x000b, 0x0005, - 0x86be, 0x86bf, 0x86be, 0x86be, 0x8724, 0x8733, 0x0005, 0x00b6, - 0x700c, 0x7108, 0x080c, 0x268c, 0x1904, 0x8722, 0x080c, 0x6749, - 0x1904, 0x8722, 0xbe12, 0xbd16, 0x7110, 0xd1bc, 0x0540, 0x702c, - 0xd084, 0x1120, 0xb800, 0xd0bc, 0x1904, 0x8722, 0x080c, 0x6c11, - 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6c19, 0x0118, 0x9086, - 0x0004, 0x1588, 0x00c6, 0x080c, 0x8742, 0x00ce, 0x05d8, 0x080c, - 0xb116, 0x2b08, 0x05b8, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0002, - 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xb20a, 0x0458, 0x080c, - 0x6c11, 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6c19, 0x0118, - 0x9086, 0x0004, 0x1180, 0x080c, 0xb116, 0x2b08, 0x01d8, 0x6112, - 0x080c, 0xd3b6, 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088, - 0x080c, 0xb20a, 0x0078, 0x080c, 0xb116, 0x2b08, 0x0158, 0x6112, - 0x080c, 0xd3b6, 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, - 0x080c, 0xb20a, 0x00be, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x00d1, - 0x0148, 0x080c, 0x869a, 0x1130, 0x7124, 0x610a, 0x2009, 0x0089, - 0x080c, 0xb20a, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x0059, 0x0148, - 0x080c, 0x869a, 0x1130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, - 0xb20a, 0x0005, 0x7020, 0x2060, 0x9c84, 0x0003, 0x1158, 0x9c82, - 0x1ddc, 0x0240, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1218, 0x9085, - 0x0001, 0x0005, 0x9006, 0x0ce8, 0x00b6, 0x7110, 0xd1bc, 0x11d8, - 0x7024, 0x2060, 0x9c84, 0x0003, 0x11b0, 0x9c82, 0x1ddc, 0x0298, - 0x6868, 0x9c02, 0x1280, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, - 0xb910, 0x9106, 0x1140, 0x700c, 0xb914, 0x9106, 0x1120, 0x2009, - 0x0051, 0x080c, 0xb20a, 0x7817, 0x0140, 0x00be, 0x0005, 0x2031, - 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, - 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, - 0x0096, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, 0xc000, 0x05c0, - 0x080c, 0xb116, 0x05a8, 0x0066, 0x00c6, 0x0046, 0x2011, 0x0263, - 0x2204, 0x8211, 0x220c, 0x080c, 0x268c, 0x1590, 0x080c, 0x6749, - 0x1578, 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce, 0x6012, 0x080c, - 0xd3b6, 0x080c, 0x1059, 0x0500, 0x2900, 0x6062, 0x9006, 0xa802, - 0xa866, 0xac6a, 0xa85c, 0x90f8, 0x001b, 0x20a9, 0x000e, 0xa860, - 0x20e8, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, 0x006e, 0x6616, - 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, 0x080c, 0x961e, - 0x00fe, 0x009e, 0x00ce, 0x0005, 0x080c, 0xb16c, 0x006e, 0x0cc0, - 0x004e, 0x00ce, 0x0cc8, 0x00c6, 0x7000, 0x908c, 0xff00, 0x9184, - 0xf000, 0x810f, 0x9086, 0x2000, 0x1904, 0x882a, 0x9186, 0x0022, - 0x15f0, 0x2001, 0x0111, 0x2004, 0x9005, 0x1904, 0x882c, 0x7030, - 0x908e, 0x0400, 0x0904, 0x882c, 0x908e, 0x6000, 0x05e8, 0x908e, - 0x5400, 0x05d0, 0x908e, 0x0300, 0x11d8, 0x2009, 0x1837, 0x210c, - 0xd18c, 0x1590, 0xd1a4, 0x1580, 0x080c, 0x6bcf, 0x0588, 0x68b0, - 0x9084, 0x00ff, 0x7100, 0x918c, 0x00ff, 0x9106, 0x1518, 0x6880, - 0x69b0, 0x918c, 0xff00, 0x9105, 0x7104, 0x9106, 0x11d8, 0x00e0, - 0x2009, 0x0103, 0x210c, 0xd1b4, 0x11a8, 0x908e, 0x5200, 0x09e8, - 0x908e, 0x0500, 0x09d0, 0x908e, 0x5000, 0x09b8, 0x0058, 0x9186, - 0x0023, 0x1140, 0x080c, 0x8742, 0x0128, 0x6004, 0x9086, 0x0002, - 0x0118, 0x0000, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005, - 0x7030, 0x908e, 0x0300, 0x0118, 0x908e, 0x5200, 0x1d98, 0x2001, - 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x0d68, 0x0c50, - 0x0156, 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4, - 0x0007, 0xd484, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, - 0x027a, 0x080c, 0xc20e, 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004, - 0x2019, 0x1801, 0x2011, 0x027e, 0x080c, 0xc20e, 0x1120, 0xd494, - 0x0110, 0x9085, 0x0001, 0x003e, 0x001e, 0x004e, 0x015e, 0x0005, - 0x0156, 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4, - 0x0007, 0xd484, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, - 0x0272, 0x080c, 0xc20e, 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004, - 0x2019, 0x1801, 0x2011, 0x0276, 0x080c, 0xc20e, 0x1120, 0xd494, - 0x0110, 0x9085, 0x0001, 0x003e, 0x001e, 0x004e, 0x015e, 0x0005, - 0x00f6, 0x2079, 0x0200, 0x7800, 0xc0e5, 0xc0cc, 0x7802, 0x00fe, - 0x0005, 0x00f6, 0x2079, 0x1800, 0x7834, 0xd084, 0x1130, 0x2079, - 0x0200, 0x7800, 0x9085, 0x1200, 0x7802, 0x00fe, 0x0005, 0x00e6, - 0x2071, 0x1800, 0x7034, 0xc084, 0x7036, 0x00ee, 0x0005, 0x0016, - 0x2001, 0x1837, 0x200c, 0x9184, 0x0080, 0x0118, 0xd18c, 0x0118, - 0x9006, 0x001e, 0x0005, 0x9085, 0x0001, 0x0cd8, 0x2071, 0x1a04, - 0x7003, 0x0003, 0x700f, 0x0361, 0x9006, 0x701a, 0x707a, 0x7012, - 0x7017, 0x1ddc, 0x7007, 0x0000, 0x7026, 0x702b, 0xa2c0, 0x7032, - 0x7037, 0xa33d, 0x7047, 0xffff, 0x704a, 0x704f, 0x56c4, 0x7052, - 0x7063, 0x8a66, 0x080c, 0x1072, 0x090c, 0x0d85, 0x2900, 0x7042, - 0xa867, 0x0003, 0xa86f, 0x0100, 0xa8ab, 0xdcb0, 0x0005, 0x2071, - 0x1a04, 0x1d04, 0x8982, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, - 0x1590, 0x2001, 0x013c, 0x2004, 0x9005, 0x190c, 0x8b10, 0x2001, - 0x1869, 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, - 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0d85, 0x700f, - 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x2069, 0x1800, - 0x69ec, 0xd1e4, 0x1138, 0xd1dc, 0x1118, 0x080c, 0x8ad4, 0x0010, - 0x080c, 0x8aab, 0x7048, 0x900d, 0x0148, 0x8109, 0x714a, 0x1130, - 0x704c, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0x900d, - 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109, - 0x7126, 0x9186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, - 0x7028, 0x080f, 0x7030, 0x900d, 0x0180, 0x702c, 0x8001, 0x702e, - 0x1160, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, 0x9184, 0x007f, - 0x090c, 0xa3eb, 0x0010, 0x7034, 0x080f, 0x7044, 0x9005, 0x0118, - 0x0310, 0x8001, 0x7046, 0x7054, 0x900d, 0x0168, 0x7050, 0x8001, - 0x7052, 0x1148, 0x7053, 0x0009, 0x8109, 0x7156, 0x1120, 0x7158, - 0x7156, 0x7060, 0x080f, 0x7018, 0x900d, 0x01d8, 0x0016, 0x7078, - 0x900d, 0x0158, 0x7074, 0x8001, 0x7076, 0x1138, 0x7077, 0x0009, - 0x8109, 0x717a, 0x1110, 0x707c, 0x080f, 0x001e, 0x7008, 0x8001, - 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, - 0x080f, 0x012e, 0x7004, 0x0002, 0x89aa, 0x89ab, 0x89d5, 0x00e6, - 0x2071, 0x1a04, 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, 0x700b, - 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x1a04, 0x701c, - 0x9206, 0x1120, 0x701a, 0x701e, 0x707a, 0x707e, 0x000e, 0x00ee, - 0x0005, 0x00e6, 0x2071, 0x1a04, 0xb888, 0x9102, 0x0208, 0xb98a, - 0x00ee, 0x0005, 0x0005, 0x00b6, 0x2031, 0x0010, 0x7110, 0x080c, - 0x67b4, 0x11a8, 0xb888, 0x8001, 0x0290, 0xb88a, 0x1180, 0x0126, - 0x2091, 0x8000, 0x0066, 0xb8d0, 0x9005, 0x0138, 0x0026, 0xba3c, - 0x0016, 0x080c, 0x68df, 0x001e, 0x002e, 0x006e, 0x012e, 0x8108, - 0x9182, 0x0800, 0x1220, 0x8631, 0x0128, 0x7112, 0x0c00, 0x900e, - 0x7007, 0x0002, 0x7112, 0x00be, 0x0005, 0x2031, 0x0010, 0x7014, - 0x2060, 0x0126, 0x2091, 0x8000, 0x6048, 0x9005, 0x0128, 0x8001, - 0x604a, 0x1110, 0x080c, 0xd237, 0x6018, 0x9005, 0x0904, 0x8a2d, - 0x00f6, 0x2079, 0x0300, 0x7918, 0xd1b4, 0x1904, 0x8a40, 0x781b, - 0x2020, 0xa001, 0x7918, 0xd1b4, 0x0120, 0x781b, 0x2000, 0x0804, - 0x8a40, 0x8001, 0x601a, 0x0106, 0x781b, 0x2000, 0xa001, 0x7918, - 0xd1ac, 0x1dd0, 0x010e, 0x00fe, 0x1540, 0x6120, 0x9186, 0x0003, - 0x0148, 0x9186, 0x0006, 0x0130, 0x9186, 0x0009, 0x11e0, 0x611c, - 0xd1c4, 0x1100, 0x080c, 0xcf1b, 0x01b0, 0x6014, 0x2048, 0xa884, - 0x908a, 0x199a, 0x0280, 0x9082, 0x1999, 0xa886, 0x908a, 0x199a, - 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, - 0x080c, 0xd671, 0x0110, 0x080c, 0xcbd9, 0x012e, 0x9c88, 0x001c, - 0x7116, 0x2001, 0x181a, 0x2004, 0x9102, 0x1228, 0x8631, 0x0138, - 0x2160, 0x0804, 0x89d9, 0x7017, 0x1ddc, 0x7007, 0x0000, 0x0005, - 0x00fe, 0x0c58, 0x00e6, 0x2071, 0x1a04, 0x7027, 0x07d0, 0x7023, - 0x0009, 0x00ee, 0x0005, 0x2001, 0x1a0d, 0x2003, 0x0000, 0x0005, - 0x00e6, 0x2071, 0x1a04, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, - 0x2011, 0x1a10, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1a04, - 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, 0x0026, - 0x705c, 0x8000, 0x705e, 0x2001, 0x1a14, 0x2044, 0xa06c, 0x9086, - 0x0000, 0x0150, 0x7070, 0xa09a, 0x706c, 0xa096, 0x7068, 0xa092, - 0x7064, 0xa08e, 0x080c, 0x114e, 0x002e, 0x008e, 0x0005, 0x0006, - 0x0016, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, - 0x0156, 0x080c, 0x88e7, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x00be, 0x00ae, 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, - 0x1a04, 0x717a, 0x727e, 0x7077, 0x0009, 0x00ee, 0x0005, 0x00e6, - 0x0006, 0x2071, 0x1a04, 0x707c, 0x9206, 0x1110, 0x707a, 0x707e, - 0x000e, 0x00ee, 0x0005, 0x2069, 0x1800, 0x69ec, 0xd1e4, 0x1518, - 0x0026, 0xd1ec, 0x0140, 0x6a54, 0x6874, 0x9202, 0x0288, 0x8117, - 0x9294, 0x00c1, 0x0088, 0x9184, 0x0007, 0x01a0, 0x8109, 0x9184, - 0x0007, 0x0110, 0x69ee, 0x0070, 0x8107, 0x9084, 0x0007, 0x910d, - 0x8107, 0x9106, 0x9094, 0x00c1, 0x9184, 0xff3e, 0x9205, 0x68ee, - 0x080c, 0x0f24, 0x002e, 0x0005, 0x69e8, 0x9184, 0x003f, 0x05b8, - 0x8109, 0x9184, 0x003f, 0x01a8, 0x6a54, 0x6874, 0x9202, 0x0220, - 0xd1bc, 0x0168, 0xc1bc, 0x0018, 0xd1bc, 0x1148, 0xc1bd, 0x2110, - 0x00e6, 0x2071, 0x1800, 0x080c, 0x0f46, 0x00ee, 0x0400, 0x69ea, - 0x00f0, 0x0026, 0x8107, 0x9094, 0x0007, 0x0128, 0x8001, 0x8007, - 0x9085, 0x0007, 0x0050, 0x2010, 0x8004, 0x8004, 0x8004, 0x9084, - 0x0007, 0x9205, 0x8007, 0x9085, 0x0028, 0x9086, 0x0040, 0x2010, - 0x00e6, 0x2071, 0x1800, 0x080c, 0x0f46, 0x00ee, 0x002e, 0x0005, - 0x0016, 0x00c6, 0x2009, 0xfff4, 0x210d, 0x2061, 0x0100, 0x60f0, - 0x9100, 0x60f3, 0x0000, 0x2009, 0xfff4, 0x200f, 0x1220, 0x8108, - 0x2105, 0x8000, 0x200f, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x2061, - 0x1a73, 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, 0x8003, 0x8003, - 0x9080, 0x1a73, 0x2060, 0x0005, 0xa884, 0x908a, 0x199a, 0x1638, - 0x9005, 0x1150, 0x00c6, 0x2061, 0x1a73, 0x6014, 0x00ce, 0x9005, - 0x1130, 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, 0x01b0, 0x8003, - 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, 0x908c, 0x00c0, 0x918e, - 0x00c0, 0x0904, 0x8bee, 0xd0b4, 0x1168, 0xd0bc, 0x1904, 0x8bc7, - 0x2009, 0x0006, 0x080c, 0x8c1b, 0x0005, 0x900e, 0x0c60, 0x2001, - 0x1999, 0x08b0, 0xd0fc, 0x05e0, 0x908c, 0x2023, 0x1568, 0x87ff, - 0x1558, 0xa9a8, 0x81ff, 0x1540, 0x6124, 0x918c, 0x0500, 0x1520, - 0x6100, 0x918e, 0x0007, 0x1500, 0x2009, 0x1869, 0x210c, 0xd184, - 0x11d8, 0x6003, 0x0003, 0x6007, 0x0043, 0x6047, 0xb035, 0x080c, - 0x1c6f, 0xa87c, 0xc0dd, 0xa87e, 0x600f, 0x0000, 0x00f6, 0x2079, - 0x0380, 0x7818, 0xd0bc, 0x1de8, 0x7833, 0x0013, 0x2c00, 0x7836, - 0x781b, 0x8080, 0x00fe, 0x0005, 0x908c, 0x0003, 0x0120, 0x918e, - 0x0003, 0x1904, 0x8c15, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, - 0x6024, 0xd0d4, 0x11e8, 0x2009, 0x1869, 0x2104, 0xd084, 0x1138, - 0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0xb20a, 0x0005, 0x87ff, - 0x1de8, 0x2009, 0x0042, 0x0804, 0xb20a, 0x6110, 0x00b6, 0x2158, - 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6024, 0xc0cd, 0x6026, 0x0c00, - 0xc0d4, 0x6026, 0xa890, 0x602e, 0xa88c, 0x6032, 0x08e0, 0xd0fc, - 0x0160, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x8c15, - 0x908c, 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, 0x2c78, - 0x080c, 0x17ad, 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, 0x0042, - 0x080c, 0xb20a, 0x0005, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, - 0xd1ac, 0x0d58, 0x6124, 0xc1cd, 0x6126, 0x0c38, 0xd0fc, 0x0188, - 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x9084, 0x0003, 0x908e, - 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, 0xb20a, - 0x0005, 0x00b9, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c, - 0xb20a, 0x0cb0, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, - 0x0d20, 0x6124, 0xc1cd, 0x6126, 0x0c00, 0x2009, 0x0004, 0x0019, - 0x0005, 0x2009, 0x0001, 0x0096, 0x080c, 0xcf1b, 0x0518, 0x6014, - 0x2048, 0xa982, 0xa800, 0x6016, 0x9186, 0x0001, 0x1188, 0xa97c, - 0x918c, 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, 0x2061, 0x1a73, - 0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, - 0x080c, 0x6e4c, 0x6014, 0x904d, 0x0076, 0x2039, 0x0000, 0x190c, - 0x8b34, 0x007e, 0x009e, 0x0005, 0x0156, 0x00c6, 0x2061, 0x1a73, - 0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, 0x6002, 0x00ce, - 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0x9005, 0x0120, - 0x8001, 0x680a, 0x9085, 0x0001, 0x0005, 0x2071, 0x1924, 0x7003, - 0x0006, 0x7007, 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, 0x080c, - 0x1072, 0x090c, 0x0d85, 0xa867, 0x0006, 0xa86b, 0x0001, 0xa8ab, - 0xdcb0, 0xa89f, 0x0000, 0x2900, 0x702e, 0x7033, 0x0000, 0x0005, - 0x0126, 0x2091, 0x8000, 0x0096, 0x00e6, 0x2071, 0x1924, 0x702c, - 0x2048, 0x6a2c, 0x721e, 0x6b30, 0x7322, 0x6834, 0x7026, 0xa896, - 0x6838, 0x702a, 0xa89a, 0x6824, 0x7016, 0x683c, 0x701a, 0x2009, - 0x0028, 0x200a, 0x9005, 0x0148, 0x900e, 0x9188, 0x000c, 0x8001, - 0x1de0, 0x2100, 0x9210, 0x1208, 0x8318, 0xaa8e, 0xab92, 0x7010, - 0xd084, 0x0168, 0xc084, 0x7007, 0x0001, 0x700f, 0x0000, 0x0006, - 0x2009, 0x1b73, 0x2104, 0x9082, 0x0007, 0x200a, 0x000e, 0xc095, - 0x7012, 0x2008, 0x2001, 0x003b, 0x080c, 0x16b9, 0x9006, 0x2071, - 0x193d, 0x7002, 0x7006, 0x702a, 0x00ee, 0x009e, 0x012e, 0x0005, - 0x2009, 0x1b73, 0x2104, 0x9080, 0x0007, 0x200a, 0x0005, 0x00e6, - 0x0126, 0x0156, 0x2091, 0x8000, 0x2071, 0x1800, 0x7154, 0x2001, - 0x0008, 0x910a, 0x0638, 0x2001, 0x187d, 0x20ac, 0x9006, 0x9080, - 0x0008, 0x1f04, 0x8cd7, 0x71c0, 0x9102, 0x02e0, 0x2071, 0x1877, - 0x20a9, 0x0007, 0x00c6, 0x080c, 0xb116, 0x6023, 0x0009, 0x6003, - 0x0004, 0x601f, 0x0101, 0x0089, 0x0126, 0x2091, 0x8000, 0x080c, - 0x8e58, 0x012e, 0x1f04, 0x8ce3, 0x9006, 0x00ce, 0x015e, 0x012e, - 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x00e6, 0x00b6, 0x0096, - 0x0086, 0x0056, 0x0046, 0x0026, 0x7118, 0x720c, 0x7620, 0x7004, - 0xd084, 0x1128, 0x2021, 0x0024, 0x2029, 0x0002, 0x0020, 0x2021, - 0x002c, 0x2029, 0x000a, 0x080c, 0x1059, 0x090c, 0x0d85, 0x2900, - 0x6016, 0x2058, 0xac66, 0x9006, 0xa802, 0xa806, 0xa86a, 0xa87a, - 0xa8aa, 0xa887, 0x0005, 0xa87f, 0x0020, 0x7008, 0xa89a, 0x7010, - 0xa89e, 0xae8a, 0xa8af, 0xffff, 0xa8b3, 0x0000, 0x8109, 0x0160, - 0x080c, 0x1059, 0x090c, 0x0d85, 0xad66, 0x2b00, 0xa802, 0x2900, - 0xb806, 0x2058, 0x8109, 0x1da0, 0x002e, 0x004e, 0x005e, 0x008e, - 0x009e, 0x00be, 0x00ee, 0x0005, 0x2079, 0x0000, 0x2071, 0x1924, - 0x7004, 0x004b, 0x700c, 0x0002, 0x8d4f, 0x8d48, 0x8d48, 0x0005, - 0x8d59, 0x8daf, 0x8daf, 0x8daf, 0x8db0, 0x8dc1, 0x8dc1, 0x700c, - 0x0cba, 0x0126, 0x2091, 0x8000, 0x78a0, 0x79a0, 0x9106, 0x1904, - 0x8da1, 0x7814, 0xd0bc, 0x1904, 0x8daa, 0x012e, 0x7018, 0x910a, - 0x1128, 0x7030, 0x9005, 0x1904, 0x8df3, 0x0005, 0x1210, 0x7114, - 0x910a, 0x9192, 0x000a, 0x0210, 0x2009, 0x000a, 0x2001, 0x1888, - 0x2014, 0x2001, 0x1936, 0x2004, 0x9100, 0x9202, 0x0e50, 0x080c, - 0x8f53, 0x2200, 0x9102, 0x0208, 0x2208, 0x0096, 0x702c, 0x2048, - 0xa873, 0x0001, 0xa976, 0x080c, 0x905c, 0x2100, 0xa87e, 0xa86f, - 0x0000, 0x009e, 0x0126, 0x2091, 0x8000, 0x2009, 0x1a24, 0x2104, - 0xc085, 0x200a, 0x700f, 0x0002, 0x012e, 0x080c, 0x116d, 0x1de8, - 0x0005, 0x78a0, 0x79a0, 0x9106, 0x0904, 0x8d61, 0x080c, 0x8f2b, - 0x012e, 0x0005, 0x7810, 0xc0c5, 0x7812, 0x0804, 0x8d61, 0x0005, - 0x700c, 0x0002, 0x8db5, 0x8db8, 0x8db7, 0x080c, 0x8d57, 0x0005, - 0x8001, 0x700e, 0x0096, 0x702c, 0x2048, 0xa974, 0x009e, 0x0011, - 0x0ca0, 0x0005, 0x0096, 0x702c, 0x2048, 0x7018, 0x9100, 0x7214, - 0x921a, 0x1130, 0x701c, 0xa88e, 0x7020, 0xa892, 0x9006, 0x0068, - 0x0006, 0x080c, 0x905c, 0x2100, 0xaa8c, 0x9210, 0xaa8e, 0x1220, - 0xa890, 0x9081, 0x0000, 0xa892, 0x000e, 0x009e, 0x0126, 0x2091, - 0x8000, 0x78a2, 0x701a, 0x080c, 0x8f2b, 0x012e, 0x0005, 0x00e6, - 0x2071, 0x1924, 0x700c, 0x0002, 0x8df1, 0x8df1, 0x8def, 0x700f, - 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x7030, 0x9005, - 0x0508, 0x2078, 0x7814, 0x2048, 0xae88, 0x00b6, 0x2059, 0x0000, - 0x080c, 0x8e61, 0x00be, 0x01b0, 0x00e6, 0x2071, 0x193d, 0x080c, - 0x8ea8, 0x00ee, 0x0178, 0x0096, 0x080c, 0x1072, 0x2900, 0x009e, - 0x0148, 0xa8aa, 0x04d1, 0x0041, 0x2001, 0x1947, 0x2003, 0x0000, - 0x012e, 0x08c8, 0x012e, 0x0005, 0x00d6, 0x00c6, 0x0086, 0x00a6, - 0x2940, 0x2650, 0x2600, 0x9005, 0x0180, 0xa864, 0x9084, 0x000f, - 0x2068, 0x9d88, 0x1ec1, 0x2165, 0x0056, 0x2029, 0x0000, 0x080c, - 0x8fe1, 0x080c, 0x1e97, 0x1dd8, 0x005e, 0x00ae, 0x2001, 0x187f, - 0x2004, 0xa88a, 0x00c6, 0x2f60, 0x080c, 0x17ad, 0x00ce, 0x781f, - 0x0101, 0x7813, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x8eb7, - 0x012e, 0x008e, 0x00ce, 0x00de, 0x0005, 0x7030, 0x9005, 0x0138, - 0x2078, 0x780c, 0x7032, 0x2001, 0x1947, 0x2003, 0x0001, 0x0005, - 0x00e6, 0x2071, 0x1924, 0x7030, 0x600e, 0x2c00, 0x7032, 0x00ee, - 0x0005, 0x00d6, 0x00c6, 0x0026, 0x9b80, 0x912a, 0x2005, 0x906d, - 0x090c, 0x0d85, 0x9b80, 0x9122, 0x2005, 0x9065, 0x090c, 0x0d85, - 0x6114, 0x2600, 0x9102, 0x0248, 0x6828, 0x9102, 0x02f0, 0x9085, - 0x0001, 0x002e, 0x00ce, 0x00de, 0x0005, 0x6804, 0xd094, 0x0148, - 0x6854, 0xd084, 0x1178, 0xc085, 0x6856, 0x2011, 0x8026, 0x080c, - 0x4ca1, 0x684c, 0x0096, 0x904d, 0x090c, 0x0d85, 0xa804, 0x8000, - 0xa806, 0x009e, 0x9006, 0x2030, 0x0c20, 0x6854, 0xd08c, 0x1d08, - 0xc08d, 0x6856, 0x2011, 0x8025, 0x080c, 0x4ca1, 0x684c, 0x0096, - 0x904d, 0x090c, 0x0d85, 0xa800, 0x8000, 0xa802, 0x009e, 0x0888, - 0x7000, 0x2019, 0x0008, 0x8319, 0x7104, 0x9102, 0x1118, 0x2300, - 0x9005, 0x0020, 0x0210, 0x9302, 0x0008, 0x8002, 0x0005, 0x00d6, - 0x7814, 0x9005, 0x090c, 0x0d85, 0x781c, 0x9084, 0x0101, 0x9086, - 0x0101, 0x190c, 0x0d85, 0x7827, 0x0000, 0x2069, 0x193d, 0x6804, - 0x9080, 0x193f, 0x2f08, 0x2102, 0x6904, 0x8108, 0x9182, 0x0008, - 0x0208, 0x900e, 0x6906, 0x9180, 0x193f, 0x2003, 0x0000, 0x00de, - 0x0005, 0x0096, 0x00c6, 0x2060, 0x6014, 0x2048, 0xa8a8, 0x0096, - 0x2048, 0x9005, 0x190c, 0x108b, 0x009e, 0xa8ab, 0x0000, 0x080c, - 0x100b, 0x080c, 0xb16c, 0x00ce, 0x009e, 0x0005, 0x6020, 0x9086, - 0x0009, 0x1128, 0x601c, 0xd0c4, 0x0110, 0x9006, 0x0005, 0x9085, - 0x0001, 0x0005, 0x6000, 0x9086, 0x0000, 0x0178, 0x6010, 0x9005, - 0x0150, 0x00b6, 0x2058, 0x080c, 0x925e, 0x00be, 0x6013, 0x0000, - 0x601b, 0x0000, 0x0010, 0x2c00, 0x0861, 0x0005, 0x2009, 0x1928, - 0x210c, 0xd194, 0x0005, 0x2009, 0x1928, 0x210c, 0xd1c4, 0x0005, - 0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, 0x1924, 0x7110, 0xc194, - 0xc185, 0x7007, 0x0000, 0x7112, 0x2001, 0x003b, 0x080c, 0x16b9, - 0x00ee, 0x012e, 0x0005, 0x7814, 0xd0bc, 0x1108, 0x0005, 0x7810, - 0xc0c5, 0x7812, 0x0cc0, 0x0096, 0x00d6, 0x9006, 0x7006, 0x700e, - 0x701a, 0x701e, 0x7022, 0x7016, 0x702a, 0x7026, 0x702f, 0x0000, - 0x080c, 0x90aa, 0x0170, 0x080c, 0x90df, 0x0158, 0x2900, 0x7002, - 0x700a, 0x701a, 0x7013, 0x0001, 0x701f, 0x000a, 0x00de, 0x009e, - 0x0005, 0x900e, 0x0cd8, 0x00e6, 0x0096, 0x0086, 0x00d6, 0x00c6, - 0x2071, 0x1931, 0x721c, 0x2100, 0x9202, 0x1618, 0x080c, 0x90df, - 0x090c, 0x0d85, 0x7018, 0x9005, 0x1160, 0x2900, 0x7002, 0x700a, - 0x701a, 0x9006, 0x7006, 0x700e, 0xa806, 0xa802, 0x7012, 0x701e, - 0x0038, 0x2040, 0xa806, 0x2900, 0xa002, 0x701a, 0xa803, 0x0000, - 0x7010, 0x8000, 0x7012, 0x701c, 0x9080, 0x000a, 0x701e, 0x721c, - 0x08d0, 0x721c, 0x00ce, 0x00de, 0x008e, 0x009e, 0x00ee, 0x0005, - 0x0096, 0x0156, 0x0136, 0x0146, 0x00e6, 0x0126, 0x2091, 0x8000, - 0x2071, 0x1931, 0x7300, 0x831f, 0x831e, 0x831e, 0x9384, 0x003f, - 0x20e8, 0x939c, 0xffc0, 0x9398, 0x0003, 0x7104, 0x080c, 0x905c, - 0x810c, 0x2100, 0x9318, 0x8003, 0x2228, 0x2021, 0x0078, 0x9402, - 0x9532, 0x0208, 0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0, 0xa001, - 0xa001, 0x4005, 0x2508, 0x080c, 0x9065, 0x2130, 0x7014, 0x9600, - 0x7016, 0x2600, 0x711c, 0x9102, 0x701e, 0x7004, 0x9600, 0x2008, - 0x9082, 0x000a, 0x1190, 0x7000, 0x2048, 0xa800, 0x9005, 0x1148, - 0x2009, 0x0001, 0x0026, 0x080c, 0x8f53, 0x002e, 0x7000, 0x2048, - 0xa800, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x2500, 0x9212, - 0x1904, 0x8f92, 0x012e, 0x00ee, 0x014e, 0x013e, 0x015e, 0x009e, - 0x0005, 0x0016, 0x0026, 0x00e6, 0x0126, 0x2091, 0x8000, 0x9580, - 0x9122, 0x2005, 0x9075, 0x090c, 0x0d85, 0x080c, 0x9037, 0x012e, - 0x9580, 0x911e, 0x2005, 0x9075, 0x090c, 0x0d85, 0x0156, 0x0136, - 0x01c6, 0x0146, 0x01d6, 0x831f, 0x831e, 0x831e, 0x9384, 0x003f, - 0x20e0, 0x9384, 0xffc0, 0x9100, 0x2098, 0xa860, 0x20e8, 0xa95c, - 0x2c05, 0x9100, 0x20a0, 0x20a9, 0x0002, 0x4003, 0x2e0c, 0x2d00, - 0x0002, 0x9021, 0x9021, 0x9023, 0x9021, 0x9023, 0x9021, 0x9021, - 0x9021, 0x9021, 0x9021, 0x9029, 0x9021, 0x9029, 0x9021, 0x9021, - 0x9021, 0x080c, 0x0d85, 0x4104, 0x20a9, 0x0002, 0x4002, 0x4003, - 0x0028, 0x20a9, 0x0002, 0x4003, 0x4104, 0x4003, 0x01de, 0x014e, - 0x01ce, 0x013e, 0x015e, 0x00ee, 0x002e, 0x001e, 0x0005, 0x0096, - 0x7014, 0x8001, 0x7016, 0x710c, 0x2110, 0x00f1, 0x810c, 0x9188, - 0x0003, 0x7308, 0x8210, 0x9282, 0x000a, 0x1198, 0x7008, 0x2048, - 0xa800, 0x9005, 0x0158, 0x0006, 0x080c, 0x90ee, 0x009e, 0xa807, - 0x0000, 0x2900, 0x700a, 0x7010, 0x8001, 0x7012, 0x700f, 0x0000, - 0x0008, 0x720e, 0x009e, 0x0005, 0x0006, 0x810b, 0x810b, 0x2100, - 0x810b, 0x9100, 0x2008, 0x000e, 0x0005, 0x0006, 0x0026, 0x2100, - 0x9005, 0x0158, 0x9092, 0x000c, 0x0240, 0x900e, 0x8108, 0x9082, - 0x000c, 0x1de0, 0x002e, 0x000e, 0x0005, 0x900e, 0x0cd8, 0x2d00, - 0x90b8, 0x0008, 0x2031, 0x90a8, 0x901e, 0x6808, 0x9005, 0x0108, - 0x8318, 0x690c, 0x910a, 0x0248, 0x0140, 0x8318, 0x6810, 0x9112, - 0x0220, 0x0118, 0x8318, 0x2208, 0x0cd0, 0x233a, 0x6804, 0xd084, - 0x2300, 0x2021, 0x0001, 0x1150, 0x9082, 0x0003, 0x0967, 0x0a67, - 0x8420, 0x9082, 0x0007, 0x0967, 0x0a67, 0x0cd0, 0x9082, 0x0002, - 0x0967, 0x0a67, 0x8420, 0x9082, 0x0005, 0x0967, 0x0a67, 0x0cd0, - 0x6c1a, 0x0005, 0x0096, 0x0046, 0x0126, 0x2091, 0x8000, 0x2b00, - 0x9080, 0x9126, 0x2005, 0x9005, 0x090c, 0x0d85, 0x2004, 0x90a0, - 0x000a, 0x080c, 0x1072, 0x01d0, 0x2900, 0x7026, 0xa803, 0x0000, - 0xa807, 0x0000, 0x080c, 0x1072, 0x0188, 0x7024, 0xa802, 0xa807, - 0x0000, 0x2900, 0x7026, 0x94a2, 0x000a, 0x0110, 0x0208, 0x0c90, - 0x9085, 0x0001, 0x012e, 0x004e, 0x009e, 0x0005, 0x7024, 0x9005, - 0x0dc8, 0x2048, 0xac00, 0x080c, 0x108b, 0x2400, 0x0cc0, 0x0126, - 0x2091, 0x8000, 0x7024, 0x2048, 0x9005, 0x0130, 0xa800, 0x7026, - 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, - 0x8000, 0x7024, 0xa802, 0x2900, 0x7026, 0x012e, 0x0005, 0x0096, - 0x9e80, 0x0009, 0x2004, 0x9005, 0x0138, 0x2048, 0xa800, 0x0006, - 0x080c, 0x108b, 0x000e, 0x0cb8, 0x009e, 0x0005, 0x0096, 0x7008, - 0x9005, 0x0138, 0x2048, 0xa800, 0x0006, 0x080c, 0x108b, 0x000e, - 0x0cb8, 0x9006, 0x7002, 0x700a, 0x7006, 0x700e, 0x701a, 0x701e, - 0x7022, 0x702a, 0x7026, 0x702e, 0x009e, 0x0005, 0x1a71, 0x0000, - 0x0000, 0x0000, 0x1931, 0x0000, 0x0000, 0x0000, 0x1888, 0x0000, - 0x0000, 0x0000, 0x1877, 0x0000, 0x0000, 0x0000, 0x00e6, 0x00c6, - 0x00b6, 0x00a6, 0xa8a8, 0x2040, 0x2071, 0x1877, 0x080c, 0x924a, - 0xa067, 0x0023, 0x6010, 0x905d, 0x0904, 0x921f, 0xb814, 0xa06e, - 0xb910, 0xa172, 0xb9a0, 0xa176, 0x2001, 0x0003, 0xa07e, 0xa834, - 0xa082, 0xa07b, 0x0000, 0xa898, 0x9005, 0x0118, 0xa078, 0xc085, - 0xa07a, 0x2858, 0x2031, 0x0018, 0xa068, 0x908a, 0x0019, 0x1a0c, - 0x0d85, 0x2020, 0x2050, 0x2940, 0xa864, 0x90bc, 0x00ff, 0x908c, - 0x000f, 0x91e0, 0x1ec1, 0x2c65, 0x9786, 0x0024, 0x2c05, 0x1590, - 0x908a, 0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x918a, - 0x918a, 0x918c, 0x918a, 0x918a, 0x918a, 0x918e, 0x918a, 0x918a, - 0x918a, 0x9190, 0x918a, 0x918a, 0x918a, 0x9192, 0x918a, 0x918a, - 0x918a, 0x9194, 0x918a, 0x918a, 0x918a, 0x9196, 0x918a, 0x918a, - 0x918a, 0x9198, 0x080c, 0x0d85, 0xa180, 0x04b8, 0xa190, 0x04a8, - 0xa1a0, 0x0498, 0xa1b0, 0x0488, 0xa1c0, 0x0478, 0xa1d0, 0x0468, - 0xa1e0, 0x0458, 0x908a, 0x0034, 0x1a0c, 0x0d85, 0x9082, 0x001b, - 0x0002, 0x91bc, 0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91be, - 0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91c0, 0x91ba, 0x91ba, - 0x91ba, 0x91ba, 0x91ba, 0x91c2, 0x91ba, 0x91ba, 0x91ba, 0x91ba, - 0x91ba, 0x91c4, 0x080c, 0x0d85, 0xa180, 0x0038, 0xa198, 0x0028, - 0xa1b0, 0x0018, 0xa1c8, 0x0008, 0xa1e0, 0x2600, 0x0002, 0x91e0, - 0x91e2, 0x91e4, 0x91e6, 0x91e8, 0x91ea, 0x91ec, 0x91ee, 0x91f0, - 0x91f2, 0x91f4, 0x91f6, 0x91f8, 0x91fa, 0x91fc, 0x91fe, 0x9200, - 0x9202, 0x9204, 0x9206, 0x9208, 0x920a, 0x920c, 0x920e, 0x9210, - 0x080c, 0x0d85, 0xb9e2, 0x0468, 0xb9de, 0x0458, 0xb9da, 0x0448, - 0xb9d6, 0x0438, 0xb9d2, 0x0428, 0xb9ce, 0x0418, 0xb9ca, 0x0408, - 0xb9c6, 0x00f8, 0xb9c2, 0x00e8, 0xb9be, 0x00d8, 0xb9ba, 0x00c8, - 0xb9b6, 0x00b8, 0xb9b2, 0x00a8, 0xb9ae, 0x0098, 0xb9aa, 0x0088, - 0xb9a6, 0x0078, 0xb9a2, 0x0068, 0xb99e, 0x0058, 0xb99a, 0x0048, - 0xb996, 0x0038, 0xb992, 0x0028, 0xb98e, 0x0018, 0xb98a, 0x0008, - 0xb986, 0x8631, 0x8421, 0x0130, 0x080c, 0x1e97, 0x090c, 0x0d85, - 0x0804, 0x9164, 0x00ae, 0x00be, 0x00ce, 0x00ee, 0x0005, 0xa86c, - 0xa06e, 0xa870, 0xa072, 0xa077, 0x00ff, 0x9006, 0x0804, 0x9146, - 0x0006, 0x0016, 0x00b6, 0x6010, 0x2058, 0xb810, 0x9005, 0x01b0, - 0x2001, 0x1925, 0x2004, 0x9005, 0x0188, 0x2001, 0x1800, 0x2004, - 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0xbba0, 0x2021, 0x0004, - 0x2011, 0x8014, 0x080c, 0x4ca1, 0x004e, 0x003e, 0x00be, 0x001e, - 0x000e, 0x0005, 0x9016, 0x710c, 0xa834, 0x910a, 0xa936, 0x7008, - 0x9005, 0x0120, 0x8210, 0x910a, 0x0230, 0x0128, 0x7010, 0x8210, - 0x910a, 0x0208, 0x1de0, 0xaa8a, 0xa26a, 0x0005, 0x00f6, 0x00d6, - 0x0036, 0x2079, 0x0300, 0x781b, 0x0200, 0x7818, 0xd094, 0x1dd8, - 0x781b, 0x0202, 0xa001, 0xa001, 0x7818, 0xd094, 0x1da0, 0xb8ac, - 0x906d, 0x0198, 0x2079, 0x0000, 0x9c1e, 0x1118, 0x680c, 0xb8ae, - 0x0050, 0x9c06, 0x0130, 0x2d78, 0x680c, 0x906d, 0x1dd0, 0x080c, - 0x0d85, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x2079, 0x0300, 0x781b, - 0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x00d6, 0x0096, - 0x00c6, 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, 0x20a9, 0x01ff, - 0x2071, 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, 0x0110, 0x1f04, - 0x929a, 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, 0xd094, 0x1d90, - 0xb8ac, 0x9065, 0x01f0, 0x600c, 0xb8ae, 0x6024, 0xc08d, 0x6026, - 0x6003, 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, 0x601f, 0x0101, - 0x6014, 0x904d, 0x090c, 0x0d85, 0xa88b, 0x0000, 0xa8a8, 0xa8ab, - 0x0000, 0x904d, 0x090c, 0x0d85, 0x080c, 0x108b, 0x080c, 0x8e58, - 0x08f8, 0x2071, 0x0300, 0x701b, 0x0200, 0x015e, 0x012e, 0x003e, - 0x00ce, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x00b6, 0x0016, - 0x0006, 0x0156, 0x080c, 0x268c, 0x015e, 0x11b0, 0x080c, 0x6749, - 0x190c, 0x0d85, 0x000e, 0x001e, 0xb912, 0xb816, 0x080c, 0xb116, - 0x0140, 0x2b00, 0x6012, 0x6023, 0x0001, 0x2009, 0x0001, 0x080c, - 0xb20a, 0x00be, 0x00ce, 0x0005, 0x000e, 0x001e, 0x0cd0, 0x0066, - 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e, 0x0005, - 0x9310, 0x9310, 0x9310, 0x9312, 0x935b, 0x9310, 0x9310, 0x9310, - 0x93d5, 0x9310, 0x940d, 0x9310, 0x9310, 0x9310, 0x9310, 0x9310, - 0x080c, 0x0d85, 0x9182, 0x0040, 0x0002, 0x9325, 0x9325, 0x9325, - 0x9325, 0x9325, 0x9325, 0x9325, 0x9325, 0x9325, 0x9327, 0x9338, - 0x9325, 0x9325, 0x9325, 0x9325, 0x9349, 0x080c, 0x0d85, 0x0096, - 0x6114, 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, - 0x0500, 0x00be, 0x080c, 0x6e11, 0x080c, 0xb16c, 0x009e, 0x0005, - 0x080c, 0x9a48, 0x00d6, 0x6114, 0x080c, 0xcf1b, 0x0130, 0x0096, - 0x6114, 0x2148, 0x080c, 0x7012, 0x009e, 0x00de, 0x080c, 0xb16c, - 0x0005, 0x080c, 0x9a48, 0x080c, 0x3315, 0x6114, 0x0096, 0x2148, - 0x080c, 0xcf1b, 0x0120, 0xa87b, 0x0029, 0x080c, 0x7012, 0x009e, - 0x080c, 0xb16c, 0x0005, 0x601b, 0x0000, 0x9182, 0x0040, 0x0096, - 0x0002, 0x9376, 0x9376, 0x9376, 0x9376, 0x9376, 0x9376, 0x9376, - 0x9376, 0x9378, 0x9376, 0x9376, 0x9376, 0x93d1, 0x9376, 0x9376, - 0x9376, 0x9376, 0x9376, 0x9376, 0x937f, 0x9376, 0x080c, 0x0d85, - 0x6114, 0x2148, 0xa938, 0x918e, 0xffff, 0x0904, 0x93d1, 0x6024, - 0xd08c, 0x15d8, 0x080c, 0x8f0e, 0x05e0, 0x00e6, 0x6114, 0x2148, - 0x080c, 0x912e, 0x0096, 0xa8a8, 0x2048, 0x080c, 0x6da9, 0x009e, - 0xa8ab, 0x0000, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, - 0x925e, 0x00be, 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8e61, - 0x00be, 0x01e0, 0x2071, 0x193d, 0x080c, 0x8ea8, 0x01b8, 0x9086, - 0x0001, 0x1128, 0x2001, 0x1947, 0x2004, 0x9005, 0x1178, 0x0096, - 0x080c, 0x1059, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x00f6, 0x2c78, - 0x080c, 0x8e1c, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x080c, 0x8e58, - 0x0cd0, 0x080c, 0x8f13, 0x1160, 0x6010, 0x9005, 0x0130, 0x2058, - 0xb8ac, 0x9005, 0x190c, 0x0d85, 0x6012, 0x2c00, 0x080c, 0x8ed9, - 0x0005, 0x080c, 0x9489, 0x009e, 0x0005, 0x9182, 0x0040, 0x0096, - 0x0002, 0x93e9, 0x93e9, 0x93e9, 0x93eb, 0x93e9, 0x93e9, 0x93e9, - 0x940b, 0x93e9, 0x93e9, 0x93e9, 0x93e9, 0x93e9, 0x93e9, 0x93e9, - 0x93e9, 0x080c, 0x0d85, 0x6003, 0x0003, 0x6106, 0x6014, 0x2048, - 0xa8ac, 0xa836, 0xa8b0, 0xa83a, 0xa847, 0x0000, 0xa84b, 0x0000, - 0xa884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, - 0x8213, 0x9210, 0x621a, 0x080c, 0x1c26, 0x2009, 0x8030, 0x080c, - 0x965e, 0x009e, 0x0005, 0x080c, 0x0d85, 0x080c, 0x9a48, 0x6114, - 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, - 0x00be, 0x080c, 0x7012, 0x080c, 0xb16c, 0x009e, 0x0005, 0x080c, - 0xacfc, 0x6144, 0xd1fc, 0x0120, 0xd1ac, 0x1110, 0x6003, 0x0003, - 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x0096, 0x0023, 0x009e, - 0x080c, 0xad18, 0x0005, 0x9443, 0x9443, 0x9443, 0x9445, 0x9456, - 0x9443, 0x9443, 0x9443, 0x9443, 0x9443, 0x9443, 0x9443, 0x9443, - 0x9443, 0x9443, 0x9443, 0x080c, 0x0d85, 0x080c, 0xaee3, 0x6114, - 0x2148, 0xa87b, 0x0006, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, - 0x00be, 0x080c, 0x7012, 0x080c, 0xb16c, 0x0005, 0x0491, 0x0005, - 0x080c, 0xacfc, 0x6000, 0x6144, 0xd1fc, 0x0130, 0xd1ac, 0x1120, - 0x6003, 0x0003, 0x2009, 0x0003, 0x908a, 0x0010, 0x1a0c, 0x0d85, - 0x0096, 0x0033, 0x009e, 0x0106, 0x080c, 0xad18, 0x010e, 0x0005, - 0x9480, 0x9480, 0x9480, 0x9482, 0x9489, 0x9480, 0x9480, 0x9480, - 0x9480, 0x9480, 0x9480, 0x9480, 0x9480, 0x9480, 0x9480, 0x9480, - 0x080c, 0x0d85, 0x0036, 0x00e6, 0x080c, 0xaee3, 0x00ee, 0x003e, - 0x0005, 0x6024, 0xd08c, 0x11f0, 0x00f6, 0x00e6, 0x601b, 0x0000, - 0x6014, 0x2048, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, - 0x925e, 0x00be, 0x2071, 0x193d, 0x080c, 0x8ea8, 0x0160, 0x2001, - 0x187f, 0x2004, 0xa88a, 0x2031, 0x0000, 0x2c78, 0x080c, 0x8e1c, - 0x00ee, 0x00fe, 0x0005, 0x0096, 0xa88b, 0x0000, 0xa8a8, 0x2048, - 0x080c, 0x108b, 0x009e, 0xa8ab, 0x0000, 0x080c, 0x8e58, 0x0c80, - 0x2001, 0x1925, 0x200c, 0x918e, 0x0000, 0x190c, 0x8f0e, 0x05c8, - 0x00e6, 0x2071, 0x1924, 0x7110, 0xc1c5, 0x7112, 0x080c, 0x8f18, - 0x00f6, 0x00c6, 0x2071, 0x1000, 0x00b6, 0x2e04, 0x905d, 0x0138, - 0xb8ac, 0x9065, 0x0120, 0x080c, 0x8eee, 0x090c, 0x928d, 0x8e70, - 0x9e86, 0x1800, 0x1d90, 0x00be, 0x00d6, 0x0096, 0x0046, 0x2061, - 0x1ddc, 0x2001, 0x181a, 0x2024, 0x6020, 0x9086, 0x0000, 0x1191, - 0x9ce0, 0x001c, 0x2400, 0x9c06, 0x1db8, 0x004e, 0x009e, 0x00de, - 0x00d1, 0x00ce, 0x00fe, 0x2071, 0x1924, 0x7110, 0xc1c4, 0x7112, - 0x00ee, 0x0005, 0x6020, 0x9086, 0x0009, 0x1160, 0x6100, 0x9186, - 0x0004, 0x1138, 0x6110, 0x81ff, 0x190c, 0x0d85, 0x2c00, 0x080c, - 0x8ed9, 0x9006, 0x0005, 0x2071, 0x193f, 0x2073, 0x0000, 0x8e70, - 0x9e86, 0x1947, 0x1dd0, 0x2071, 0x193d, 0x7006, 0x7002, 0x2001, - 0x1930, 0x2064, 0x8cff, 0x0130, 0x6120, 0x918e, 0x0000, 0x190c, - 0x0d85, 0x2102, 0x2001, 0x188a, 0x200c, 0x81ff, 0x0148, 0x0096, - 0x2148, 0x080c, 0x108b, 0x009e, 0x2001, 0x188a, 0x2003, 0x0000, - 0x2071, 0x1931, 0x080c, 0x90f7, 0x0804, 0x9106, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x187a, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0126, 0x2091, - 0x8000, 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, 0x8086, - 0x818e, 0x1208, 0x9200, 0x1f04, 0x954f, 0x8086, 0x818e, 0x004e, - 0x003e, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0076, 0x0156, - 0x20a9, 0x0010, 0x9005, 0x01c8, 0x911a, 0x12b8, 0x8213, 0x818d, - 0x0228, 0x911a, 0x1220, 0x1f04, 0x9566, 0x0028, 0x911a, 0x2308, - 0x8210, 0x1f04, 0x9566, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080, - 0x000e, 0x015e, 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085, - 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, 0x2079, 0x19e8, 0x012e, - 0x00d6, 0x2069, 0x19e8, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6, - 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, 0xaaf1, 0x04c9, 0x080c, - 0xaadc, 0x04b1, 0x080c, 0xaadf, 0x0499, 0x080c, 0xaae2, 0x0481, - 0x080c, 0xaae5, 0x0469, 0x080c, 0xaae8, 0x0451, 0x080c, 0xaaeb, - 0x0439, 0x080c, 0xaaee, 0x0421, 0x01de, 0x014e, 0x015e, 0x6857, - 0x0000, 0x00f6, 0x2079, 0x0380, 0x0419, 0x7807, 0x0003, 0x7803, - 0x0000, 0x7803, 0x0001, 0x2069, 0x0004, 0x2d04, 0x9084, 0xfffe, - 0x9085, 0x8000, 0x206a, 0x2069, 0x0100, 0x6828, 0x9084, 0xfffc, - 0x682a, 0x00fe, 0x2001, 0x1b5d, 0x2003, 0x0000, 0x00de, 0x0005, - 0x20a9, 0x0020, 0x20a1, 0x0240, 0x2001, 0x0000, 0x4004, 0x0005, - 0x00c6, 0x7803, 0x0000, 0x9006, 0x7827, 0x0030, 0x782b, 0x0400, - 0x7827, 0x0031, 0x782b, 0x1af6, 0x781f, 0xff00, 0x781b, 0xff00, - 0x2061, 0x1aeb, 0x602f, 0x19e8, 0x6033, 0x1800, 0x6037, 0x1a04, - 0x603b, 0x1ec1, 0x603f, 0x1ed1, 0x6042, 0x6047, 0x1ac1, 0x00ce, - 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001, - 0x01b0, 0x00c6, 0x6146, 0x600f, 0x0000, 0x2c08, 0x2061, 0x19e8, - 0x602c, 0x8000, 0x602e, 0x601c, 0x9005, 0x0130, 0x9080, 0x0003, - 0x2102, 0x611e, 0x00ce, 0x0005, 0x6122, 0x611e, 0x0cd8, 0x6146, - 0x2c08, 0x2001, 0x0012, 0x080c, 0xaced, 0x0005, 0x0016, 0x2009, - 0x8020, 0x6146, 0x2c08, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, - 0x9086, 0x0001, 0x1128, 0x2001, 0x0019, 0x080c, 0xaced, 0x0088, - 0x00c6, 0x2061, 0x19e8, 0x602c, 0x8000, 0x602e, 0x600c, 0x9005, - 0x0128, 0x9080, 0x0003, 0x2102, 0x610e, 0x0010, 0x6112, 0x610e, - 0x00ce, 0x001e, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, - 0x9086, 0x0001, 0x0198, 0x00c6, 0x6146, 0x600f, 0x0000, 0x2c08, - 0x2061, 0x19e8, 0x6044, 0x9005, 0x0130, 0x9080, 0x0003, 0x2102, - 0x6146, 0x00ce, 0x0005, 0x614a, 0x6146, 0x0cd8, 0x6146, 0x600f, - 0x0000, 0x2c08, 0x2001, 0x0013, 0x080c, 0xaced, 0x0005, 0x6044, - 0xd0dc, 0x0110, 0x080c, 0xa78a, 0x0005, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, 0x0056, 0x0036, 0x0026, - 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x19e8, 0x7648, 0x2660, - 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x96f1, 0x9c86, 0x1b55, - 0x0904, 0x96ec, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x96ec, - 0x87ff, 0x0120, 0x605c, 0x9106, 0x1904, 0x96ec, 0x704c, 0x9c06, - 0x1188, 0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x703f, 0x0000, - 0x9006, 0x704e, 0x706a, 0x7052, 0x706e, 0x080c, 0xaff4, 0x003e, - 0x2029, 0x0001, 0x080c, 0x9667, 0x7048, 0x9c36, 0x1110, 0x660c, - 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, - 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xcf1b, - 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, 0x1588, 0x6004, - 0x9086, 0x0040, 0x090c, 0xa78a, 0xa867, 0x0103, 0xab7a, 0xa877, - 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xd220, 0x080c, 0xeddf, - 0x080c, 0x7012, 0x007e, 0x003e, 0x001e, 0x080c, 0xd10c, 0x080c, - 0xb1a7, 0x00ce, 0x0804, 0x9683, 0x2c78, 0x600c, 0x2060, 0x0804, - 0x9683, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, 0x006e, - 0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, - 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c, - 0xeddf, 0x080c, 0xea30, 0x007e, 0x003e, 0x001e, 0x08c0, 0x6020, - 0x9086, 0x0009, 0x1168, 0xa87b, 0x0006, 0x0016, 0x0036, 0x0076, - 0x080c, 0x7012, 0x080c, 0xb16c, 0x007e, 0x003e, 0x001e, 0x0848, - 0x6020, 0x9086, 0x000a, 0x0904, 0x96d6, 0x0804, 0x96cf, 0x0006, - 0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091, - 0x8000, 0x2079, 0x19e8, 0x7848, 0x9065, 0x0904, 0x9790, 0x600c, - 0x0006, 0x600f, 0x0000, 0x784c, 0x9c06, 0x11b0, 0x0036, 0x2019, - 0x0001, 0x080c, 0xa596, 0x783f, 0x0000, 0x901e, 0x7b4e, 0x7b6a, - 0x7b52, 0x7b6e, 0x080c, 0xaff4, 0x003e, 0x000e, 0x9005, 0x1118, - 0x600c, 0x600f, 0x0000, 0x0006, 0x9c86, 0x1b55, 0x05b0, 0x00e6, - 0x2f70, 0x080c, 0x9667, 0x00ee, 0x080c, 0xcf1b, 0x0548, 0x6014, - 0x2048, 0x6020, 0x9086, 0x0003, 0x15a8, 0x3e08, 0x918e, 0x0002, - 0x1188, 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x0140, 0x6048, 0x9005, 0x11c0, 0x2001, 0x1988, 0x2004, - 0x604a, 0x0098, 0x6004, 0x9086, 0x0040, 0x090c, 0xa78a, 0xa867, - 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x7006, 0x080c, 0xd10c, - 0x6044, 0xc0fc, 0x6046, 0x080c, 0xb1a7, 0x000e, 0x0804, 0x9734, - 0x7e4a, 0x7e46, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x009e, 0x006e, - 0x000e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xea30, - 0x0c38, 0x6020, 0x9086, 0x0009, 0x1130, 0xab7a, 0x080c, 0x7012, - 0x080c, 0xb16c, 0x0c10, 0x6020, 0x9086, 0x000a, 0x0990, 0x0850, - 0x0016, 0x0026, 0x0086, 0x9046, 0x00a9, 0x080c, 0x98a3, 0x008e, - 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0x19e8, 0x2091, - 0x8000, 0x080c, 0x98ec, 0x080c, 0x9982, 0x080c, 0x6948, 0x012e, - 0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, - 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, - 0x7620, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9868, 0x6010, 0x2058, - 0xb8a0, 0x9206, 0x1904, 0x9863, 0x88ff, 0x0120, 0x605c, 0x9106, - 0x1904, 0x9863, 0x7030, 0x9c06, 0x1580, 0x2069, 0x0100, 0x6820, - 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x8a4b, 0x080c, 0xa2a0, - 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x0040, 0x7008, 0xc0ad, 0x700a, - 0x6003, 0x0009, 0x630a, 0x0804, 0x9863, 0x7020, 0x9c36, 0x1110, - 0x660c, 0x7622, 0x701c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, - 0x2f00, 0x701e, 0x0010, 0x701f, 0x0000, 0x660c, 0x0066, 0x2c00, - 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6044, - 0xc0fc, 0x6046, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x01e8, 0x6020, - 0x9086, 0x0003, 0x1580, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c, - 0x0098, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, - 0x0086, 0x080c, 0xd220, 0x080c, 0xeddf, 0x080c, 0x7012, 0x008e, - 0x003e, 0x001e, 0x080c, 0xd10c, 0x080c, 0xb1a7, 0x080c, 0xa65d, - 0x00ce, 0x0804, 0x97db, 0x2c78, 0x600c, 0x2060, 0x0804, 0x97db, - 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x009e, 0x00be, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016, - 0x0036, 0x0086, 0x080c, 0xeddf, 0x080c, 0xea30, 0x008e, 0x003e, - 0x001e, 0x08d0, 0x080c, 0xbb5c, 0x6020, 0x9086, 0x0002, 0x1160, - 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0904, 0x9849, 0x9086, - 0x008b, 0x0904, 0x9849, 0x0840, 0x6020, 0x9086, 0x0005, 0x1920, - 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x09c8, 0x9086, 0x008b, - 0x09b0, 0x0804, 0x985c, 0x0006, 0x00f6, 0x00e6, 0x0096, 0x00b6, - 0x00c6, 0x0066, 0x0016, 0x0126, 0x2091, 0x8000, 0x9280, 0x1000, - 0x2004, 0x905d, 0x2079, 0x19e8, 0x9036, 0x7828, 0x2060, 0x8cff, - 0x0538, 0x6010, 0x9b06, 0x1500, 0x6043, 0xffff, 0x080c, 0xaf2e, - 0x01d8, 0x610c, 0x0016, 0x080c, 0xa420, 0x6014, 0x2048, 0xa867, - 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, - 0xd220, 0x080c, 0xeddf, 0x080c, 0x7012, 0x008e, 0x003e, 0x001e, - 0x080c, 0xb1a7, 0x00ce, 0x08d8, 0x2c30, 0x600c, 0x2060, 0x08b8, - 0x080c, 0x6965, 0x012e, 0x001e, 0x006e, 0x00ce, 0x00be, 0x009e, - 0x00ee, 0x00fe, 0x000e, 0x0005, 0x0096, 0x0006, 0x0066, 0x00c6, - 0x00d6, 0x9036, 0x7820, 0x9065, 0x0904, 0x9955, 0x600c, 0x0006, - 0x6044, 0xc0fc, 0x6046, 0x600f, 0x0000, 0x7830, 0x9c06, 0x1598, - 0x2069, 0x0100, 0x6820, 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, - 0x8a4b, 0x080c, 0xa2a0, 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7833, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, - 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0058, - 0x080c, 0x6ba9, 0x1538, 0x6003, 0x0009, 0x630a, 0x7808, 0xc0ad, - 0x780a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, 0xcf19, 0x01b0, - 0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xd132, 0x1118, 0x080c, - 0xbb5c, 0x0060, 0x080c, 0x6ba9, 0x1168, 0xa867, 0x0103, 0xab7a, - 0xa877, 0x0000, 0x080c, 0x7012, 0x080c, 0xd10c, 0x080c, 0xb1a7, - 0x080c, 0xa65d, 0x000e, 0x0804, 0x98f3, 0x7e22, 0x7e1e, 0x00de, - 0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, - 0x1118, 0x080c, 0xea30, 0x0c50, 0x080c, 0xbb5c, 0x6020, 0x9086, - 0x0002, 0x1150, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0990, - 0x9086, 0x008b, 0x0978, 0x08d0, 0x6020, 0x9086, 0x0005, 0x19b0, - 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0d18, 0x9086, 0x008b, - 0x0d00, 0x0860, 0x0006, 0x0096, 0x00b6, 0x00c6, 0x0066, 0x9036, - 0x7828, 0x9065, 0x0510, 0x6010, 0x2058, 0x600c, 0x0006, 0x3e08, - 0x918e, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x11a8, 0x6043, 0xffff, - 0x080c, 0xaf2e, 0x0180, 0x610c, 0x080c, 0xa420, 0x6014, 0x2048, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x7012, 0x080c, - 0xb1a7, 0x000e, 0x08f0, 0x2c30, 0x0ce0, 0x006e, 0x00ce, 0x00be, - 0x009e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, 0x0066, 0x080c, - 0x62af, 0x11b0, 0x2071, 0x19e8, 0x7030, 0x9080, 0x0005, 0x2004, - 0x904d, 0x0170, 0xa878, 0x9606, 0x1158, 0x2071, 0x19e8, 0x7030, - 0x9035, 0x0130, 0x9080, 0x0005, 0x2004, 0x9906, 0x1108, 0x0029, - 0x006e, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x2660, 0x6043, - 0xffff, 0x080c, 0xaf2e, 0x0178, 0x080c, 0xa420, 0x6014, 0x2048, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd220, 0x080c, - 0x7012, 0x080c, 0xb1a7, 0x00ce, 0x0005, 0x00b6, 0x00e6, 0x00c6, - 0x080c, 0xacfc, 0x0106, 0x2071, 0x0101, 0x2e04, 0xc0c4, 0x2072, - 0x6044, 0xd0fc, 0x1138, 0x010e, 0x090c, 0xad18, 0x00ce, 0x00ee, - 0x00be, 0x0005, 0x2071, 0x19e8, 0x7030, 0x9005, 0x0da0, 0x9c06, - 0x190c, 0x0d85, 0x7036, 0x080c, 0x8a4b, 0x7004, 0x9084, 0x0007, - 0x0002, 0x9a1b, 0x9a1d, 0x9a24, 0x9a2e, 0x9a3c, 0x9a1b, 0x9a29, - 0x9a19, 0x080c, 0x0d85, 0x0428, 0x0005, 0x080c, 0xaf19, 0x7007, - 0x0000, 0x7033, 0x0000, 0x00e8, 0x0066, 0x9036, 0x080c, 0xa420, - 0x006e, 0x7007, 0x0000, 0x7033, 0x0000, 0x0098, 0x080c, 0xaf04, - 0x0140, 0x080c, 0xaf19, 0x0128, 0x0066, 0x9036, 0x080c, 0xa420, - 0x006e, 0x7033, 0x0000, 0x0028, 0x080c, 0xaf04, 0x080c, 0xa78a, - 0x0000, 0x010e, 0x090c, 0xad18, 0x00ce, 0x00ee, 0x00be, 0x0005, - 0x00d6, 0x00c6, 0x080c, 0xacfc, 0x0106, 0x6044, 0xd0fc, 0x1130, - 0x010e, 0x090c, 0xad18, 0x00ce, 0x00de, 0x0005, 0x2069, 0x19e8, - 0x684c, 0x9005, 0x0da8, 0x9c06, 0x190c, 0x0d85, 0x6852, 0x00e6, - 0x2d70, 0x080c, 0x9667, 0x00ee, 0x080c, 0x8a58, 0x0016, 0x2009, - 0x0040, 0x080c, 0x2220, 0x001e, 0x683c, 0x9084, 0x0003, 0x0002, - 0x9a76, 0x9a77, 0x9a96, 0x9a74, 0x080c, 0x0d85, 0x0490, 0x6868, - 0x9086, 0x0001, 0x0198, 0x600c, 0x9015, 0x0168, 0x6a4a, 0x600f, - 0x0000, 0x6044, 0x9084, 0x7f7f, 0x6046, 0x9006, 0x6842, 0x684e, - 0x683f, 0x0000, 0x00f0, 0x684a, 0x6846, 0x0c98, 0x686b, 0x0000, - 0x6848, 0x9065, 0x0d70, 0x6003, 0x0002, 0x0c58, 0x6044, 0x9084, - 0x7f7f, 0x6046, 0x9006, 0x6842, 0x684e, 0x686a, 0x6852, 0x686e, - 0x600c, 0x9015, 0x0120, 0x6a4a, 0x600f, 0x0000, 0x0010, 0x684a, - 0x6846, 0x080c, 0xaff4, 0x684f, 0x0000, 0x010e, 0x090c, 0xad18, - 0x00ce, 0x00de, 0x0005, 0x0005, 0x6020, 0x9084, 0x000f, 0x000b, - 0x0005, 0x9ac9, 0x9acc, 0x9f80, 0xa019, 0x9acc, 0x9f80, 0xa019, - 0x9ac9, 0x9acc, 0x9ac9, 0x9ac9, 0x9ac9, 0x9ac9, 0x9ac9, 0x9ac9, - 0x9ac9, 0x080c, 0x99ed, 0x0005, 0x00b6, 0x0156, 0x0136, 0x0146, - 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, - 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d85, 0x6110, - 0x2158, 0xb984, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a, 0x0040, - 0x1a04, 0x9b38, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, - 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x9ce1, 0x9d1c, - 0x9d45, 0x9e0f, 0x9e31, 0x9e37, 0x9e44, 0x9e4c, 0x9e58, 0x9e5e, - 0x9e6f, 0x9e5e, 0x9ec7, 0x9e4c, 0x9ed3, 0x9ed9, 0x9e58, 0x9ed9, - 0x9ee5, 0x9b36, 0x9b36, 0x9b36, 0x9b36, 0x9b36, 0x9b36, 0x9b36, - 0x9b36, 0x9b36, 0x9b36, 0x9b36, 0xa441, 0xa464, 0xa475, 0xa495, - 0xa4c7, 0x9e44, 0x9b36, 0x9e44, 0x9e5e, 0x9b36, 0x9d45, 0x9e0f, - 0x9b36, 0xa888, 0x9e5e, 0x9b36, 0xa8a4, 0x9e5e, 0x9b36, 0x9e58, - 0x9cdb, 0x9b59, 0x9b36, 0xa8c0, 0xa92d, 0xaa11, 0x9b36, 0xaa1e, - 0x9e41, 0xaa49, 0x9b36, 0xa4d1, 0xaa55, 0x9b36, 0x080c, 0x0d85, - 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, - 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0xaaf5, 0xaba7, 0x9b57, - 0x9b91, 0x9c3d, 0x9c48, 0x9b57, 0x9e44, 0x9b57, 0x9ca2, 0x9cae, - 0x9bac, 0x9b57, 0x9bc7, 0x9bfb, 0xb008, 0xb04d, 0x9e5e, 0x080c, - 0x0d85, 0x00d6, 0x0096, 0x080c, 0x9ef8, 0x0026, 0x0036, 0x7814, - 0x2048, 0xa958, 0xd1cc, 0x1138, 0x2009, 0x2414, 0x2011, 0x0018, - 0x2019, 0x0018, 0x0030, 0x2009, 0x2410, 0x2011, 0x0014, 0x2019, - 0x0014, 0x7102, 0x7206, 0x700b, 0x0800, 0xa83c, 0x700e, 0xa850, - 0x7022, 0xa854, 0x7026, 0x63c2, 0x080c, 0xa270, 0x003e, 0x002e, - 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, 0x00be, - 0x080c, 0xb094, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, 0x0001, - 0x0005, 0x00d6, 0x0096, 0x080c, 0x9ef8, 0x7003, 0x0500, 0x7814, - 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, 0xa880, - 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, 0x080c, - 0xa270, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, 0x9ef8, - 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, 0x700e, - 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, 0x701e, - 0x60c3, 0x0010, 0x080c, 0xa270, 0x009e, 0x00de, 0x0005, 0x00d6, - 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ef8, 0x20e9, 0x0000, - 0x2001, 0x19a4, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, 0x8003, - 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, - 0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x2001, 0x0001, 0x080c, - 0x2205, 0x080c, 0xdcef, 0x9006, 0x080c, 0x2205, 0x001e, 0xa804, - 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0xa270, 0x012e, - 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, - 0x080c, 0x9f43, 0x20e9, 0x0000, 0x2001, 0x19a4, 0x2003, 0x0000, - 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, 0x8003, - 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, - 0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x080c, 0xdcef, 0x001e, - 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, 0x2048, - 0x080c, 0x100b, 0x080c, 0xa270, 0x012e, 0x009e, 0x00de, 0x0005, - 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, 0x0004, - 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x9ef8, 0x7003, - 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, 0xa270, - 0x00d6, 0x00e6, 0x080c, 0x9f43, 0x7814, 0x9084, 0xff00, 0x2073, - 0x0200, 0x8e70, 0x8e70, 0x9096, 0xdf00, 0x0138, 0x9096, 0xe000, - 0x0120, 0x2073, 0x0010, 0x8e70, 0x0030, 0x9095, 0x0010, 0x2272, - 0x8e70, 0x2073, 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9, 0x0004, - 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9c68, 0x2069, 0x1801, 0x20a9, - 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9c71, 0x9096, 0xdf00, - 0x0130, 0x9096, 0xe000, 0x0118, 0x60c3, 0x0018, 0x00f0, 0x2069, - 0x19b4, 0x9086, 0xdf00, 0x0110, 0x2069, 0x19ce, 0x20a9, 0x001a, - 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000, - 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68, - 0x8e70, 0x1f04, 0x9c88, 0x60c3, 0x004c, 0x080c, 0xa270, 0x00ee, - 0x00de, 0x0005, 0x080c, 0x9ef8, 0x7003, 0x6300, 0x7007, 0x0028, - 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x00d6, 0x0026, - 0x0016, 0x080c, 0x9f43, 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6, - 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2069, 0x1924, - 0x6810, 0xd084, 0x1148, 0x2073, 0x0500, 0x8e70, 0x2073, 0x0000, - 0x8e70, 0x8108, 0x9290, 0x0004, 0x2073, 0x0800, 0x8e70, 0x2073, - 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, 0xa270, 0x001e, - 0x002e, 0x00de, 0x0005, 0x2001, 0x1818, 0x2004, 0x609a, 0x0804, - 0xa270, 0x080c, 0x9ef8, 0x7003, 0x5200, 0x2069, 0x1847, 0x6804, - 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x26bf, 0x710e, 0x001e, - 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, - 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, - 0x0254, 0x4003, 0x080c, 0xb094, 0x1120, 0xb8a0, 0x9082, 0x007f, - 0x0248, 0x2001, 0x181f, 0x2004, 0x7032, 0x2001, 0x1820, 0x2004, - 0x7036, 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x7036, - 0x60c3, 0x001c, 0x0804, 0xa270, 0x080c, 0x9ef8, 0x7003, 0x0500, - 0x080c, 0xb094, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, - 0x181f, 0x2004, 0x700a, 0x2001, 0x1820, 0x2004, 0x700e, 0x0030, - 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004, - 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250, - 0x4003, 0x60c3, 0x0010, 0x0804, 0xa270, 0x080c, 0x9ef8, 0x9006, - 0x080c, 0x6bdb, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2011, 0x0240, - 0x2013, 0x22ff, 0x2011, 0x0241, 0x2013, 0xfffe, 0x7003, 0x0400, - 0x620c, 0xc2b4, 0x620e, 0x0058, 0x7814, 0x0096, 0x904d, 0x0120, - 0x9006, 0xa89a, 0xa8a6, 0xa8aa, 0x009e, 0x7003, 0x0300, 0xb8a0, - 0x9086, 0x007e, 0x1904, 0x9dcf, 0x00d6, 0x2069, 0x196c, 0x2001, - 0x1837, 0x2004, 0xd0a4, 0x0188, 0x6800, 0x700a, 0x6808, 0x9084, - 0x2000, 0x7012, 0x080c, 0xb0ab, 0x680c, 0x7016, 0x701f, 0x2710, - 0x6818, 0x7022, 0x681c, 0x7026, 0x0428, 0x6800, 0x700a, 0x6804, - 0x700e, 0x2009, 0x180d, 0x210c, 0xd18c, 0x0110, 0x2001, 0x0002, - 0x00f6, 0x2079, 0x0100, 0x080c, 0x779e, 0x1128, 0x78e3, 0x0000, - 0x080c, 0x2700, 0x78e2, 0x00fe, 0x6808, 0x080c, 0x779e, 0x1118, - 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x080c, 0xb0ab, - 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, - 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, - 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c, 0xaadc, - 0x2069, 0x1974, 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002, 0x080c, - 0x5844, 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, 0x04e0, 0x2001, - 0x1837, 0x2004, 0xd0a4, 0x01a8, 0x0016, 0x2001, 0x180d, 0x2004, - 0xd08c, 0x2009, 0x0002, 0x1118, 0x2001, 0x196d, 0x200c, 0x60e0, - 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x2700, 0x61e2, - 0x001e, 0x20e1, 0x0001, 0x2099, 0x196c, 0x20e9, 0x0000, 0x20a1, - 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1805, - 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1, - 0x025a, 0x4003, 0x080c, 0xaadc, 0x20a1, 0x024e, 0x20a9, 0x0008, - 0x2099, 0x1974, 0x4003, 0x60c3, 0x0074, 0x0804, 0xa270, 0x080c, - 0x9ef8, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, 0x700f, - 0x2000, 0x9006, 0x00f6, 0x2079, 0x1847, 0x7904, 0x00fe, 0xd1ac, - 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, 0x9085, - 0x0002, 0x00d6, 0x0804, 0x9ea8, 0x7026, 0x60c3, 0x0014, 0x0804, - 0xa270, 0x080c, 0x9ef8, 0x7003, 0x5000, 0x0804, 0x9d67, 0x080c, - 0x9ef8, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, 0x0804, - 0xa270, 0x080c, 0x9f3a, 0x0010, 0x080c, 0x9f43, 0x7003, 0x0200, - 0x60c3, 0x0004, 0x0804, 0xa270, 0x080c, 0x9f43, 0x7003, 0x0100, - 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0xa270, - 0x080c, 0x9f43, 0x7003, 0x0200, 0x0804, 0x9d67, 0x080c, 0x9f43, - 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, 0x0010, 0x700b, - 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x00d6, - 0x080c, 0x9f43, 0x7003, 0x0210, 0x7007, 0x0014, 0x700b, 0x0800, - 0xb894, 0x9086, 0x0014, 0x1198, 0xb99c, 0x9184, 0x0030, 0x0190, - 0xb998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, 0x2100, - 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, 0x700f, - 0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1847, 0x7904, - 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, - 0x0010, 0x2009, 0x1869, 0x210c, 0xd184, 0x1110, 0x9085, 0x0002, - 0x0026, 0x2009, 0x1867, 0x210c, 0xd1e4, 0x0150, 0xc0c5, 0xbad4, - 0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, 0x0140, - 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, 0xc0bd, - 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0xa270, 0x080c, - 0x9f43, 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, 0x60c3, - 0x0014, 0x0804, 0xa270, 0x080c, 0x9f43, 0x7003, 0x0200, 0x0804, - 0x9ce5, 0x080c, 0x9f43, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f, - 0x2a00, 0x60c3, 0x0008, 0x0804, 0xa270, 0x080c, 0x9f43, 0x7003, - 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0xa270, 0x0026, - 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0040, - 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100, - 0x080c, 0xaaf1, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, 0x2069, - 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x9485, 0x0029, 0x7012, - 0x004e, 0x003e, 0x00de, 0x080c, 0xa264, 0x721a, 0x9f95, 0x0000, - 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, 0x0026, - 0x080c, 0xaaf1, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6, 0x2069, - 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x00de, 0x7013, 0x2029, - 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, 0xfc02, 0x700f, - 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3300, - 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, - 0x2300, 0x2021, 0x0100, 0x080c, 0xaaf1, 0xb810, 0x9305, 0x7002, - 0xb814, 0x7006, 0x2069, 0x1800, 0xb810, 0x9005, 0x1140, 0xb814, - 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, 0x687c, - 0x700a, 0x6880, 0x700e, 0x0000, 0x9485, 0x0098, 0x7012, 0x004e, - 0x003e, 0x00de, 0x080c, 0xa264, 0x721a, 0x7a08, 0x7222, 0x2f10, - 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0xa264, 0x721a, - 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, 0x0005, - 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071, - 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d85, 0x908a, 0x0092, - 0x1a0c, 0x0d85, 0x6110, 0x2158, 0xb984, 0x2c78, 0x2061, 0x0100, - 0x619a, 0x9082, 0x0085, 0x0033, 0x00fe, 0x00ee, 0x00de, 0x00ce, - 0x00be, 0x0005, 0x9fb1, 0x9fc0, 0x9fcb, 0x9faf, 0x9faf, 0x9faf, - 0x9fb1, 0x9faf, 0x9faf, 0x9faf, 0x9faf, 0x9faf, 0x9faf, 0x080c, - 0x0d85, 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x2a04, 0x0228, - 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804, 0xa270, - 0x0431, 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, 0x60c3, - 0x000c, 0x0804, 0xa270, 0x04a1, 0x7003, 0x0003, 0x7007, 0x0300, - 0x60c3, 0x0004, 0x0804, 0xa270, 0x0026, 0x080c, 0xaaf1, 0xb810, - 0x9085, 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, - 0x700a, 0x6880, 0x700e, 0x7013, 0x0009, 0x0804, 0x9f13, 0x0026, - 0x080c, 0xaaf1, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814, 0x7006, - 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, 0x0099, - 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804, 0x9f75, - 0x0026, 0x080c, 0xaaf1, 0xb810, 0x9085, 0x8500, 0x7002, 0xb814, - 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, - 0x0099, 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804, - 0x9f75, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069, - 0x0200, 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0d85, - 0x908a, 0x0057, 0x1a0c, 0x0d85, 0x7910, 0x2158, 0xb984, 0x2061, - 0x0100, 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x00be, 0x0005, 0xa04e, 0xa04e, 0xa04e, 0xa07f, 0xa04e, - 0xa04e, 0xa04e, 0xa04e, 0xa04e, 0xa04e, 0xa04e, 0xa644, 0xa649, - 0xa64e, 0xa653, 0xa04e, 0xa04e, 0xa04e, 0xa63f, 0x080c, 0x0d85, - 0x6813, 0x0008, 0xba8c, 0x8210, 0xb8d4, 0xd084, 0x0180, 0x2001, - 0x1b72, 0x200c, 0x8108, 0x2102, 0x2001, 0x1b71, 0x201c, 0x1218, - 0x8318, 0x2302, 0x0ea0, 0x7952, 0x712e, 0x7b4e, 0x732a, 0x9294, - 0x00ff, 0xba8e, 0x8217, 0x721a, 0xba10, 0x9295, 0x0600, 0x7202, - 0xba14, 0x7206, 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80, 0x720e, - 0x7013, 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, 0x0005, 0x0016, - 0x7814, 0x9084, 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, 0xa08f, - 0xa08f, 0xa091, 0xa08f, 0xa08f, 0xa08f, 0xa0ab, 0xa08f, 0x080c, - 0x0d85, 0x7914, 0x918c, 0x08ff, 0x918d, 0xf600, 0x7916, 0x2009, - 0x0003, 0x00b9, 0x2069, 0x1847, 0x6804, 0xd0bc, 0x0130, 0x682c, - 0x9084, 0x00ff, 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, 0x60c3, - 0x0001, 0x0804, 0xa270, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00, - 0x0cb0, 0x0016, 0x080c, 0xaaf1, 0x001e, 0xb810, 0x9085, 0x0100, - 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80, - 0x720e, 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0xa264, - 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x0005, 0x00b6, 0x00e6, - 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, - 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, 0x76dc, 0x96b4, 0x0028, - 0x0110, 0x737c, 0x7480, 0x2500, 0x76dc, 0x96b4, 0x0028, 0x0140, - 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, 0x0050, - 0x2001, 0x00ff, 0x9085, 0x0400, 0x6062, 0x6067, 0xffff, 0x606b, - 0x0000, 0x616e, 0xb8b8, 0x6073, 0x0530, 0x6077, 0x0008, 0xb88c, - 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x9085, 0x0020, 0x607a, - 0x607f, 0x0000, 0x2b00, 0x6082, 0x6087, 0xffff, 0x7814, 0x0096, - 0x2048, 0xa848, 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, - 0x60ca, 0x009e, 0xb86c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, - 0x60d7, 0x0000, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x0128, - 0x609f, 0x0000, 0x2001, 0x0092, 0x0058, 0x6028, 0xc0bd, 0x602a, - 0x609f, 0x00ff, 0x2011, 0xffff, 0x080c, 0x2ad3, 0x2001, 0x00b2, - 0x2010, 0x900e, 0x080c, 0x2ae2, 0x2009, 0x07d0, 0x080c, 0x8a50, - 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, - 0x0005, 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, - 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, - 0xb8a0, 0x2028, 0x76dc, 0xd6ac, 0x1168, 0x9582, 0x007e, 0x1250, - 0x2500, 0x9094, 0xff80, 0x1130, 0x9080, 0x348e, 0x2015, 0x9294, - 0x00ff, 0x0020, 0xb910, 0xba14, 0x737c, 0x7480, 0x70dc, 0xd0ac, - 0x1130, 0x9582, 0x007e, 0x1218, 0x9584, 0xff80, 0x0138, 0x9185, - 0x0400, 0x6062, 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400, - 0x6266, 0x606b, 0x0000, 0x616e, 0xb8b8, 0x6072, 0x6077, 0x0000, - 0xb864, 0xd0a4, 0x0110, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, - 0x00ff, 0xb88e, 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, - 0x2b00, 0x6082, 0x6087, 0xffff, 0x7814, 0x0096, 0x2048, 0xa848, - 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, 0x009e, - 0xb86c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, - 0xba84, 0x629e, 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, - 0x900e, 0x2011, 0x0092, 0x080c, 0x2ae2, 0x2009, 0x07d0, 0x080c, - 0x8a50, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, - 0x00be, 0x0005, 0x00b6, 0x0096, 0x00e6, 0x00d6, 0x00c6, 0x0056, - 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7810, 0x2058, - 0xb8a0, 0x2028, 0xb910, 0xba14, 0x737c, 0x7480, 0x7820, 0x0002, - 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, - 0xa1ef, 0xa1ef, 0xa1f1, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0x080c, - 0x0d85, 0xb884, 0x609e, 0x7814, 0x2048, 0xa87c, 0xd0fc, 0x0558, - 0xaf90, 0x9784, 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00, - 0x0006, 0x7814, 0x2048, 0xa878, 0xc0fc, 0x9005, 0x000e, 0x1160, - 0xaf94, 0x87ff, 0x0198, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808, - 0x6082, 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200, 0x6062, 0x6073, - 0x0129, 0x6077, 0x0000, 0xb884, 0x609e, 0x0050, 0x2039, 0x0029, - 0x9705, 0x6072, 0x0cc0, 0x9185, 0x0200, 0x6062, 0x6073, 0x2029, - 0xa87c, 0xd0fc, 0x0118, 0xaf94, 0x87ff, 0x1120, 0x2f00, 0x6082, - 0x7808, 0x6086, 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0xb88c, - 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000, - 0xa848, 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, - 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0xaad1, - 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, - 0x1b58, 0x080c, 0x8a50, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, - 0x00ee, 0x009e, 0x00be, 0x0005, 0x7a40, 0x9294, 0x00ff, 0x8217, - 0x0005, 0x00d6, 0x2069, 0x19e8, 0x686b, 0x0001, 0x00de, 0x0005, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, 0x8a42, 0x0005, - 0x0016, 0x2001, 0x180c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600, - 0x0128, 0x0089, 0x080c, 0x8a42, 0x001e, 0x0005, 0xc1e5, 0x2001, - 0x180c, 0x2102, 0x2001, 0x19e9, 0x2003, 0x0000, 0x2001, 0x19f4, - 0x2003, 0x0000, 0x0c88, 0x0006, 0x0016, 0x0026, 0x2009, 0x1804, - 0x2011, 0x0009, 0x080c, 0x2ae2, 0x002e, 0x001e, 0x000e, 0x0005, - 0x0016, 0x00c6, 0x0006, 0x080c, 0xacfc, 0x0106, 0x2061, 0x0100, - 0x61a4, 0x60a7, 0x95f5, 0x0016, 0x0026, 0x2009, 0x1804, 0x2011, - 0x0008, 0x080c, 0x2ae2, 0x002e, 0x001e, 0x010e, 0x090c, 0xad18, - 0x000e, 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005, - 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, - 0x080c, 0x779e, 0x1510, 0x2001, 0x1a0d, 0x2004, 0x9005, 0x1904, - 0xa31f, 0x080c, 0x7840, 0x11a8, 0x2069, 0x0380, 0x6843, 0x0101, - 0x6844, 0xd084, 0x1de8, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, - 0x6024, 0xd084, 0x090c, 0x0d85, 0x6843, 0x0100, 0x080c, 0x8a42, - 0x04b0, 0x00c6, 0x2061, 0x19e8, 0x00f0, 0x6904, 0x9194, 0x4000, - 0x0598, 0x080c, 0xa2a0, 0x080c, 0x2aa9, 0x00c6, 0x2061, 0x19e8, - 0x6134, 0x9192, 0x0008, 0x1278, 0x8108, 0x6136, 0x080c, 0xacfc, - 0x6130, 0x080c, 0xad18, 0x00ce, 0x81ff, 0x01c8, 0x080c, 0x8a42, - 0x080c, 0xa293, 0x00a0, 0x080c, 0xacfc, 0x6130, 0x91e5, 0x0000, - 0x0150, 0x080c, 0xeeee, 0x080c, 0x8a4b, 0x6003, 0x0001, 0x2009, - 0x0014, 0x080c, 0xb20a, 0x080c, 0xad18, 0x00ce, 0x0000, 0x002e, - 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0x1a0d, 0x2004, 0x9005, - 0x1db0, 0x00c6, 0x2061, 0x19e8, 0x6134, 0x9192, 0x0003, 0x1ad8, - 0x8108, 0x6136, 0x00ce, 0x080c, 0x8a42, 0x080c, 0x6058, 0x2009, - 0x1846, 0x2114, 0x8210, 0x220a, 0x0c10, 0x0096, 0x00c6, 0x00d6, - 0x00e6, 0x0016, 0x0026, 0x080c, 0x8a58, 0x080c, 0xacfc, 0x2001, - 0x0387, 0x2003, 0x0202, 0x2071, 0x19e8, 0x714c, 0x81ff, 0x0904, - 0xa3d9, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x779e, 0x1518, - 0x0036, 0x2019, 0x0002, 0x080c, 0xa596, 0x003e, 0x080c, 0xeeee, - 0x704c, 0x9065, 0x0180, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, - 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x6003, - 0x0003, 0x080c, 0xb20a, 0x2001, 0x0386, 0x2003, 0x5040, 0x080c, - 0x7840, 0x0804, 0xa3d9, 0x6904, 0xd1f4, 0x0904, 0xa3e6, 0x080c, - 0x2aa9, 0x00c6, 0x704c, 0x9065, 0x090c, 0x0d85, 0x6020, 0x00ce, - 0x9086, 0x0006, 0x1520, 0x61c8, 0x60c4, 0x9105, 0x1500, 0x714c, - 0x9188, 0x0011, 0x2104, 0xd0e4, 0x01d0, 0x6214, 0x9294, 0x1800, - 0x1128, 0x6224, 0x9294, 0x0002, 0x15e0, 0x0010, 0xc0e4, 0x200a, - 0x6014, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, 0x704c, 0x2060, - 0x080c, 0x9a48, 0x2009, 0x0049, 0x080c, 0xb20a, 0x0450, 0x080c, - 0xeeee, 0x704c, 0x9065, 0x9086, 0x1b55, 0x1158, 0x080c, 0xafd2, - 0x1500, 0x2061, 0x1b55, 0x6064, 0x8000, 0x6066, 0x080c, 0x6058, - 0x00c0, 0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x003e, 0x714c, - 0x2160, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, 0x1130, 0x6114, - 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x6003, 0x0003, 0x080c, - 0xb20a, 0x2001, 0x0387, 0x2003, 0x0200, 0x080c, 0xad18, 0x002e, - 0x001e, 0x00ee, 0x00de, 0x00ce, 0x009e, 0x0005, 0xd1ec, 0x1904, - 0xa37f, 0x0804, 0xa381, 0x0026, 0x00e6, 0x2071, 0x19e8, 0x706c, - 0xd084, 0x01e8, 0xc084, 0x706e, 0x714c, 0x81ff, 0x01c0, 0x2071, - 0x0100, 0x9188, 0x0008, 0x2114, 0x928e, 0x0006, 0x1138, 0x2009, - 0x1984, 0x2011, 0x0012, 0x080c, 0x2ae2, 0x0048, 0x928e, 0x0009, - 0x0db0, 0x2009, 0x1984, 0x2011, 0x0016, 0x080c, 0x2ae2, 0x00ee, - 0x002e, 0x0005, 0x9036, 0x2001, 0x19f2, 0x2004, 0x9005, 0x0128, - 0x9c06, 0x0128, 0x2c30, 0x600c, 0x0cc8, 0x9085, 0x0001, 0x0005, - 0x00f6, 0x2079, 0x19e8, 0x610c, 0x9006, 0x600e, 0x6044, 0xc0fc, - 0x6046, 0x86ff, 0x1140, 0x7824, 0x9c06, 0x1118, 0x7826, 0x782a, - 0x0050, 0x792a, 0x0040, 0x00c6, 0x2660, 0x610e, 0x00ce, 0x7824, - 0x9c06, 0x1108, 0x7e26, 0x080c, 0xa65d, 0x080c, 0xd10c, 0x00fe, - 0x0005, 0x080c, 0x9ef8, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, - 0x7016, 0x00c6, 0x7820, 0x9086, 0x0004, 0x1148, 0x7810, 0x9005, - 0x0130, 0x00b6, 0x2058, 0xb810, 0xb914, 0x00be, 0x0020, 0x2061, - 0x1800, 0x607c, 0x6180, 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, - 0x60c3, 0x002c, 0x0804, 0xa270, 0x080c, 0x9ef8, 0x7003, 0x0f00, - 0x7808, 0xd09c, 0x0128, 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, - 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x0156, 0x080c, 0x9f43, - 0x7003, 0x0200, 0x080c, 0x8b10, 0x20a9, 0x0006, 0x2011, 0xffec, - 0x2019, 0xffed, 0x9ef0, 0x0002, 0x2305, 0x2072, 0x8e70, 0x2205, - 0x2072, 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xa484, - 0x60c3, 0x001c, 0x015e, 0x0804, 0xa270, 0x0016, 0x0026, 0x080c, - 0x9f1f, 0x080c, 0x9f31, 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, - 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, - 0x9080, 0x0021, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, - 0x9192, 0x0010, 0x1250, 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, - 0x080c, 0xa270, 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, - 0x080c, 0xaadc, 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, - 0x9ef8, 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, - 0xa270, 0x0016, 0x0026, 0x080c, 0x9ef8, 0x20e9, 0x0000, 0x20a1, - 0x024c, 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, - 0xa85c, 0x9080, 0x0023, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, - 0x21a8, 0x4003, 0x8003, 0x60c2, 0x080c, 0xa270, 0x002e, 0x001e, - 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19e8, 0x7010, 0x2060, 0x8cff, 0x0188, 0x080c, 0xd132, 0x1110, - 0x080c, 0xbb5c, 0x600c, 0x0006, 0x080c, 0xd3ae, 0x600f, 0x0000, - 0x080c, 0xb16c, 0x080c, 0xa65d, 0x00ce, 0x0c68, 0x2c00, 0x7012, - 0x700e, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, - 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xe7ff, 0x2102, - 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x19e8, 0x7030, 0x2060, - 0x8cff, 0x0548, 0x080c, 0xa2a0, 0x6ac0, 0x68c3, 0x0000, 0x080c, - 0x8a4b, 0x00c6, 0x2061, 0x0100, 0x080c, 0xac2d, 0x00ce, 0x20a9, - 0x01f4, 0x04b1, 0x080c, 0x99ed, 0x6044, 0xd0ac, 0x1128, 0x2001, - 0x1988, 0x2004, 0x604a, 0x0020, 0x2009, 0x0013, 0x080c, 0xb20a, - 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x015e, 0x012e, 0x0005, 0x2001, 0x1800, 0x2004, 0x9096, 0x0001, - 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, 0x8a4b, 0x6814, 0x9084, - 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, - 0x2011, 0x6002, 0x080c, 0x8993, 0x20a9, 0x01f4, 0x0009, 0x08c0, - 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, - 0x190c, 0x2aa9, 0x0090, 0xd084, 0x0118, 0x6827, 0x4001, 0x0010, - 0x1f04, 0xa578, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x0005, 0x0126, 0x0156, - 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, - 0x2091, 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xdbff, 0x2102, - 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x0380, 0x701c, 0x0006, - 0x701f, 0x0202, 0x2071, 0x19e8, 0x704c, 0x2060, 0x8cff, 0x0904, - 0xa619, 0x080c, 0xaf84, 0x0904, 0xa619, 0x9386, 0x0002, 0x1128, - 0x6814, 0x9084, 0x0002, 0x0904, 0xa619, 0x68af, 0x95f5, 0x6817, - 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, 0x0008, - 0x080c, 0x8a58, 0x080c, 0x1e44, 0x2001, 0x0032, 0x6920, 0xd1bc, - 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, 0x0016, - 0x2009, 0x0040, 0x080c, 0x2220, 0x001e, 0x20a9, 0x03e8, 0x6824, - 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x190c, - 0x2aa9, 0x0090, 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04, - 0xa5e7, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2a99, 0x9006, 0x080c, 0x2a99, 0x6827, 0x4000, 0x6824, 0x83ff, - 0x1180, 0x2009, 0x0049, 0x6020, 0x9086, 0x0009, 0x0150, 0x080c, - 0x9a48, 0x6044, 0xd0ac, 0x1118, 0x6003, 0x0002, 0x0010, 0x080c, - 0xb20a, 0x000e, 0x2071, 0x0380, 0xd08c, 0x1110, 0x701f, 0x0200, - 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, - 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, - 0x19e8, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091, - 0x8000, 0x2069, 0x19e8, 0x6a3e, 0x012e, 0x00de, 0x0005, 0x080c, - 0xa050, 0x7047, 0x1000, 0x0098, 0x080c, 0xa050, 0x7047, 0x4000, - 0x0070, 0x080c, 0xa050, 0x7047, 0x2000, 0x0048, 0x080c, 0xa050, - 0x7047, 0x0400, 0x0020, 0x080c, 0xa050, 0x7047, 0x0200, 0x785c, - 0x7032, 0x60c3, 0x0020, 0x0804, 0xa270, 0x00e6, 0x2071, 0x19e8, - 0x702c, 0x9005, 0x0110, 0x8001, 0x702e, 0x00ee, 0x0005, 0x00f6, - 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091, - 0x8000, 0x2071, 0x19e8, 0x7620, 0x2660, 0x2678, 0x2039, 0x0001, - 0x87ff, 0x0904, 0xa702, 0x8cff, 0x0904, 0xa702, 0x6020, 0x9086, - 0x0006, 0x1904, 0xa6fd, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904, - 0xa6fd, 0x2039, 0x0000, 0x0050, 0x6010, 0x9b06, 0x1904, 0xa6fd, - 0x85ff, 0x0120, 0x605c, 0x9106, 0x1904, 0xa6fd, 0x7030, 0x9c06, - 0x15b0, 0x2069, 0x0100, 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084, - 0x0148, 0x6827, 0x0001, 0x080c, 0x8a4b, 0x080c, 0xa78a, 0x7033, - 0x0000, 0x0428, 0x080c, 0x8a4b, 0x6820, 0xd0b4, 0x0110, 0x68a7, - 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033, - 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, - 0x2001, 0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, - 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7020, - 0x9c36, 0x1110, 0x660c, 0x7622, 0x701c, 0x9c36, 0x1140, 0x2c00, - 0x9f36, 0x0118, 0x2f00, 0x701e, 0x0010, 0x701f, 0x0000, 0x660c, - 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, - 0x1168, 0x600f, 0x0000, 0x6014, 0x0096, 0x2048, 0x080c, 0xcf19, - 0x0110, 0x080c, 0xea30, 0x009e, 0x080c, 0xb1a7, 0x080c, 0xa65d, - 0x88ff, 0x1190, 0x00ce, 0x0804, 0xa678, 0x2c78, 0x600c, 0x2060, - 0x0804, 0xa678, 0x9006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce, - 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5, - 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x0096, 0x00c6, 0x0066, - 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x7648, - 0x2660, 0x2678, 0x8cff, 0x0904, 0xa779, 0x6020, 0x9086, 0x0006, - 0x1904, 0xa774, 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, 0xa774, - 0x0048, 0x6010, 0x9b06, 0x1904, 0xa774, 0x85ff, 0x0118, 0x605c, - 0x9106, 0x15d0, 0x704c, 0x9c06, 0x1178, 0x0036, 0x2019, 0x0001, - 0x080c, 0xa596, 0x703f, 0x0000, 0x9006, 0x704e, 0x706a, 0x7052, - 0x706e, 0x080c, 0xaff4, 0x003e, 0x7048, 0x9c36, 0x1110, 0x660c, - 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, - 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2048, - 0x080c, 0xcf19, 0x0110, 0x080c, 0xea30, 0x080c, 0xb1a7, 0x87ff, - 0x1198, 0x00ce, 0x0804, 0xa722, 0x2c78, 0x600c, 0x2060, 0x0804, - 0xa722, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x009e, - 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd, - 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19e8, 0x9006, 0x7032, 0x700a, - 0x7004, 0x9086, 0x0003, 0x0158, 0x2001, 0x1800, 0x2004, 0x9086, - 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, - 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2071, 0x19e8, 0x2c10, 0x7648, 0x2660, 0x2678, - 0x8cff, 0x0540, 0x2200, 0x9c06, 0x1508, 0x7048, 0x9c36, 0x1110, - 0x660c, 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, - 0x2f00, 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6004, 0x9086, - 0x0040, 0x090c, 0x99ed, 0x9085, 0x0001, 0x0020, 0x2c78, 0x600c, - 0x2060, 0x08b0, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, - 0x00fe, 0x0005, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, - 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x7610, - 0x2660, 0x2678, 0x8cff, 0x0904, 0xa877, 0x6010, 0x00b6, 0x2058, - 0xb8a0, 0x00be, 0x9206, 0x1904, 0xa872, 0x7030, 0x9c06, 0x1520, - 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xa849, 0x080c, 0xa2a0, - 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033, 0x0000, 0x0036, 0x2069, - 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, - 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0110, 0x6827, 0x0001, 0x003e, 0x7010, 0x9c36, 0x1110, 0x660c, - 0x7612, 0x700c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, - 0x700e, 0x0010, 0x700f, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, - 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xd121, - 0x1180, 0x080c, 0x3344, 0x080c, 0xd132, 0x1518, 0x080c, 0xbb5c, - 0x0400, 0x080c, 0xa78a, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, - 0x0898, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c, 0x0090, 0x6014, - 0x2048, 0x080c, 0xcf19, 0x0168, 0x6020, 0x9086, 0x0003, 0x1508, - 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x7006, 0x080c, - 0xd10c, 0x080c, 0xd3ae, 0x080c, 0xb1a7, 0x080c, 0xa65d, 0x00ce, - 0x0804, 0xa7f2, 0x2c78, 0x600c, 0x2060, 0x0804, 0xa7f2, 0x012e, - 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, - 0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, 0x080c, 0xea30, 0x0c08, - 0x00d6, 0x080c, 0x9f43, 0x7003, 0x0200, 0x7007, 0x0014, 0x60c3, - 0x0014, 0x20e1, 0x0001, 0x2099, 0x1989, 0x20e9, 0x0000, 0x20a1, - 0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, 0x0004, 0x7027, 0x7878, - 0x080c, 0xa270, 0x00de, 0x0005, 0x080c, 0x9f43, 0x700b, 0x0800, - 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, 0x9084, 0x00ff, 0x7022, - 0x782c, 0x7026, 0x7860, 0x9084, 0x00ff, 0x9085, 0x0200, 0x7002, - 0x7860, 0x9084, 0xff00, 0x8007, 0x7006, 0x60c2, 0x0804, 0xa270, - 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, 0x2009, 0x0035, 0x080c, - 0xd5bb, 0x00de, 0x1904, 0xa925, 0x080c, 0x9ef8, 0x7003, 0x1300, - 0x782c, 0x080c, 0xaa34, 0x2068, 0x6820, 0x9086, 0x0003, 0x0560, - 0x7810, 0x2058, 0xbaa0, 0x080c, 0xb094, 0x11d8, 0x9286, 0x007e, - 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0498, 0x9286, 0x007f, - 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0458, 0x9284, 0xff80, - 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffc, - 0x0400, 0x92d8, 0x1000, 0x2b5c, 0xb810, 0x700a, 0xb814, 0x700e, - 0x00c0, 0xb884, 0x700e, 0x00a8, 0x080c, 0xb094, 0x1130, 0x7810, - 0x2058, 0xb8a0, 0x9082, 0x007e, 0x0250, 0x00d6, 0x2069, 0x181f, - 0x2d04, 0x700a, 0x8d68, 0x2d04, 0x700e, 0x00de, 0x0010, 0x6034, - 0x700e, 0x7838, 0x7012, 0x783c, 0x7016, 0x60c3, 0x000c, 0x001e, - 0x00de, 0x080c, 0xa270, 0x00be, 0x0005, 0x781b, 0x0001, 0x7803, - 0x0006, 0x001e, 0x00de, 0x00be, 0x0005, 0x792c, 0x9180, 0x0008, - 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, 0x0003, 0x0904, 0xa9a4, - 0x9186, 0x0005, 0x0904, 0xa98c, 0x9186, 0x0004, 0x05f0, 0x9186, - 0x0008, 0x0904, 0xa995, 0x7807, 0x0037, 0x782f, 0x0003, 0x7817, - 0x1700, 0x080c, 0xaa11, 0x0005, 0x080c, 0xa9d2, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x6a44, 0xd2fc, 0x11f8, - 0x0002, 0xa96c, 0xa977, 0xa96e, 0xa977, 0xa973, 0xa96c, 0xa96c, - 0xa977, 0xa977, 0xa977, 0xa977, 0xa96c, 0xa96c, 0xa96c, 0xa96c, - 0xa96c, 0xa977, 0xa96c, 0xa977, 0x080c, 0x0d85, 0x6824, 0xd0e4, - 0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, - 0x7022, 0x6830, 0x7026, 0x0804, 0xa9cb, 0x080c, 0xa9d2, 0x00d6, - 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, - 0x1108, 0x900e, 0x0804, 0xa9cb, 0x080c, 0xa9d2, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x04b0, 0x04e1, 0x00d6, 0x0026, - 0x792c, 0x2168, 0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, - 0x0002, 0x1108, 0x900e, 0x0438, 0x0469, 0x00d6, 0x0026, 0x792c, - 0x2168, 0x6814, 0x6924, 0xc185, 0x6926, 0x0096, 0x2048, 0xa9ac, - 0xa834, 0x9112, 0xa9b0, 0xa838, 0x009e, 0x9103, 0x7022, 0x7226, - 0x792c, 0x9180, 0x0011, 0x2004, 0xd0fc, 0x1148, 0x9180, 0x0000, - 0x2004, 0x908e, 0x0002, 0x0130, 0x908e, 0x0004, 0x0118, 0x2009, - 0x4000, 0x0008, 0x900e, 0x712a, 0x60c3, 0x0018, 0x002e, 0x00de, - 0x0804, 0xa270, 0x00b6, 0x0036, 0x0046, 0x0056, 0x0066, 0x080c, - 0x9f43, 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, 0x793c, 0x710e, - 0x7810, 0x2058, 0xb8a0, 0x080c, 0xb094, 0x1118, 0x9092, 0x007e, - 0x0268, 0x00d6, 0x2069, 0x181f, 0x2d2c, 0x8d68, 0x2d34, 0x90d8, - 0x1000, 0x2b5c, 0xbb10, 0xbc14, 0x00de, 0x0028, 0x901e, 0xbc84, - 0x2029, 0x0000, 0x6634, 0x782c, 0x9080, 0x0008, 0x2004, 0x9086, - 0x0003, 0x1128, 0x7512, 0x7616, 0x731a, 0x741e, 0x0020, 0x7312, - 0x7416, 0x751a, 0x761e, 0x006e, 0x005e, 0x004e, 0x003e, 0x00be, - 0x0005, 0x080c, 0x9f43, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, - 0x700e, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x080c, 0x9eef, - 0x7003, 0x1400, 0x7838, 0x700a, 0x0079, 0x783c, 0x700e, 0x782c, - 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, 0x8007, 0x701a, - 0x60c3, 0x0010, 0x0804, 0xa270, 0x00e6, 0x2071, 0x0240, 0x0006, - 0x00f6, 0x2078, 0x7810, 0x00b6, 0x2058, 0xb8d4, 0xd084, 0x0120, - 0x784c, 0x702a, 0x7850, 0x702e, 0x00be, 0x00fe, 0x000e, 0x00ee, - 0x0005, 0x080c, 0x9f3a, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814, - 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x00a9, 0x7914, 0x712a, - 0x60c3, 0x0000, 0x60a7, 0x9575, 0x0026, 0x080c, 0x2a04, 0x0228, - 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x080c, 0xa293, - 0x080c, 0x8a42, 0x0005, 0x0036, 0x0096, 0x00d6, 0x00e6, 0x7860, - 0x2048, 0xaa7c, 0x9296, 0x00c0, 0x9294, 0x00fd, 0xaa7e, 0xaa80, - 0x9294, 0x0300, 0xaa82, 0xa96c, 0x9194, 0x00ff, 0xab74, 0x9384, - 0x00ff, 0x908d, 0xc200, 0xa96e, 0x9384, 0xff00, 0x9215, 0xaa76, - 0xa870, 0xaa78, 0xa87a, 0xaa72, 0x00d6, 0x2069, 0x0200, 0x080c, - 0xaaf1, 0x00de, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a, - 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, 0x4003, 0x60a3, - 0x0035, 0xaa68, 0x9294, 0x7000, 0x9286, 0x3000, 0x0110, 0x60a3, - 0x0037, 0x00ee, 0x00de, 0x009e, 0x003e, 0x0005, 0x900e, 0x7814, - 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x01c0, 0x9084, 0x0003, 0x11a8, - 0x2001, 0x180c, 0x2004, 0xd0bc, 0x0180, 0x7824, 0xd0cc, 0x1168, - 0xd0c4, 0x1158, 0xa8a8, 0x9005, 0x1140, 0x2001, 0x180c, 0x200c, - 0xc1d5, 0x2102, 0x2009, 0x19b3, 0x210c, 0x009e, 0x918d, 0x0092, - 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x0026, 0x2110, 0x900e, - 0x080c, 0x2ae2, 0x002e, 0x0005, 0x2009, 0x0009, 0x00a0, 0x2009, - 0x000a, 0x0088, 0x2009, 0x000b, 0x0070, 0x2009, 0x000c, 0x0058, - 0x2009, 0x000d, 0x0040, 0x2009, 0x000e, 0x0028, 0x2009, 0x000f, - 0x0010, 0x2009, 0x0008, 0x6912, 0x0005, 0x080c, 0x9ef8, 0x0016, - 0x0026, 0x0096, 0x00d6, 0x7814, 0x2048, 0x7013, 0x0138, 0x2001, - 0x1837, 0x2004, 0x9084, 0x0028, 0x1138, 0x2001, 0x197c, 0x2004, - 0x9086, 0xaaaa, 0x1904, 0xab96, 0x7003, 0x5400, 0x00c6, 0x2061, - 0x1800, 0x607c, 0x9084, 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00, - 0x9105, 0x700a, 0x6080, 0x700e, 0xa998, 0x918c, 0xff00, 0x7112, - 0x20a9, 0x0004, 0x2009, 0x1805, 0x2e10, 0x9290, 0x0006, 0x2104, - 0x2012, 0x8108, 0x8210, 0x1f04, 0xab27, 0x20a9, 0x0004, 0x2009, - 0x1801, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xab31, 0xa860, - 0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, 0x2009, 0x0006, 0x20a9, - 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0x00d6, - 0x2069, 0x0200, 0x080c, 0xaadc, 0x00de, 0x2071, 0x0240, 0x2011, - 0x0240, 0x2009, 0x0002, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, - 0x8210, 0x8109, 0x1dc0, 0x2009, 0x0008, 0x20a9, 0x0001, 0x4002, - 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0xa85c, 0x9080, 0x0031, - 0x2098, 0x2009, 0x0008, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, - 0x8210, 0x8109, 0x1dc0, 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, - 0x60a7, 0x9575, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1168, - 0x080c, 0x779e, 0x0150, 0x6028, 0xc0bd, 0x602a, 0x2009, 0x1804, - 0x2011, 0x0029, 0x080c, 0x2ae2, 0x0010, 0x080c, 0xa270, 0x080c, - 0x8a42, 0x00de, 0x009e, 0x002e, 0x001e, 0x0005, 0x00e6, 0x2071, - 0x0240, 0x2001, 0x2200, 0x9085, 0x00ff, 0x7002, 0x7007, 0xffff, - 0x2071, 0x0100, 0x709b, 0x00ff, 0x00ee, 0x0804, 0xab0c, 0x080c, - 0x9ef8, 0x0016, 0x0026, 0x0096, 0x00d6, 0x7814, 0x2048, 0x7013, - 0x0138, 0x7003, 0x5500, 0x00c6, 0xa89c, 0x9084, 0x00ff, 0xa998, - 0x810f, 0x918c, 0xff00, 0x9105, 0x700a, 0xa99c, 0x918c, 0xff00, - 0xa8a0, 0x9084, 0x00ff, 0x9105, 0x700e, 0xa998, 0x918c, 0xff00, - 0x2061, 0x1800, 0x607c, 0x9084, 0x00ff, 0x910d, 0x7112, 0x6180, - 0x7116, 0x2009, 0x0008, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029, - 0x2098, 0x2e10, 0x9290, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, - 0x2012, 0x8210, 0x8109, 0x1dc0, 0x20a9, 0x0004, 0x2009, 0x1805, - 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xabe8, 0x20a9, 0x0002, - 0x2009, 0x1801, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xabf2, - 0x00d6, 0x0016, 0x2069, 0x0200, 0x080c, 0xaadc, 0x001e, 0x00de, - 0x2071, 0x0240, 0x20a9, 0x0002, 0x2009, 0x1803, 0x2011, 0x0240, - 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xac08, 0x2009, 0x0008, - 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dd0, 0x9006, 0x20a9, - 0x0008, 0x2012, 0x8210, 0x1f04, 0xac19, 0x00ce, 0x60c3, 0x004c, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0xa270, 0x080c, 0x8a42, - 0x00de, 0x009e, 0x002e, 0x001e, 0x0005, 0x00d6, 0x9290, 0x0018, - 0x8214, 0x20e9, 0x0000, 0x2069, 0x0200, 0x6813, 0x0000, 0x22a8, - 0x9284, 0x00e0, 0x0128, 0x20a9, 0x0020, 0x9292, 0x0020, 0x0008, - 0x9016, 0x20a1, 0x0240, 0x9006, 0x4004, 0x82ff, 0x0120, 0x6810, - 0x8000, 0x6812, 0x0c60, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00d6, - 0x00c6, 0x00a6, 0x0096, 0x0066, 0x0126, 0x2091, 0x8000, 0x2071, - 0x19e8, 0x7610, 0x2660, 0x2678, 0x8cff, 0x0904, 0xacd9, 0x7030, - 0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xacab, - 0x080c, 0xa2a0, 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033, 0x0000, - 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, - 0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7010, 0x9c36, - 0x1110, 0x660c, 0x7612, 0x700c, 0x9c36, 0x1140, 0x2c00, 0x9f36, - 0x0118, 0x2f00, 0x700e, 0x0010, 0x700f, 0x0000, 0x660c, 0x0066, - 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, - 0x080c, 0xd121, 0x1180, 0x080c, 0x3344, 0x080c, 0xd132, 0x1518, - 0x080c, 0xbb5c, 0x0400, 0x080c, 0xa78a, 0x6824, 0xd084, 0x09b0, - 0x6827, 0x0001, 0x0898, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c, - 0x0090, 0x6014, 0x2048, 0x080c, 0xcf19, 0x0168, 0x6020, 0x9086, - 0x0003, 0x1520, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, - 0x7012, 0x080c, 0xd10c, 0x080c, 0xd3ae, 0x080c, 0xb1a7, 0x080c, - 0xa65d, 0x00ce, 0x0804, 0xac5c, 0x2c78, 0x600c, 0x2060, 0x0804, - 0xac5c, 0x7013, 0x0000, 0x700f, 0x0000, 0x012e, 0x006e, 0x009e, - 0x00ae, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086, - 0x0006, 0x1d08, 0x080c, 0xea30, 0x08f0, 0x00f6, 0x0036, 0x2079, - 0x0380, 0x7b18, 0xd3bc, 0x1de8, 0x7832, 0x7936, 0x7a3a, 0x781b, - 0x8080, 0x003e, 0x00fe, 0x0005, 0x0016, 0x2001, 0x0382, 0x2004, - 0x9084, 0x0007, 0x9086, 0x0001, 0x1188, 0x2001, 0x0015, 0x0c29, - 0x2009, 0x1000, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, - 0x0003, 0x0120, 0x8109, 0x1db0, 0x080c, 0x0d85, 0x001e, 0x0005, - 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0003, 0x1120, - 0x2001, 0x0380, 0x2003, 0x0001, 0x0005, 0x0156, 0x0016, 0x0026, - 0x00e6, 0x900e, 0x2071, 0x19e8, 0x0469, 0x0106, 0x0190, 0x7004, - 0x9086, 0x0003, 0x0148, 0x20a9, 0x1000, 0x6044, 0xd0fc, 0x01d8, - 0x1f04, 0xad35, 0x080c, 0x0d85, 0x080c, 0xacfc, 0x6044, 0xd0fc, - 0x0190, 0x7030, 0x9c06, 0x1148, 0x080c, 0x99ed, 0x6044, 0xd0dc, - 0x0150, 0xc0dc, 0x6046, 0x700a, 0x7042, 0x704c, 0x9c06, 0x190c, - 0x0d85, 0x080c, 0x9a48, 0x010e, 0x1919, 0x00ee, 0x002e, 0x001e, - 0x015e, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, - 0x0003, 0x0005, 0x0126, 0x2091, 0x2400, 0x7808, 0xd0a4, 0x190c, - 0x0d7e, 0xd09c, 0x0128, 0x7820, 0x908c, 0xf000, 0x11b8, 0x0012, - 0x012e, 0x0005, 0xad82, 0xadc0, 0xadef, 0xae37, 0xae47, 0xae58, - 0xae67, 0xae75, 0xaea2, 0xaea6, 0xad82, 0xad82, 0xaea9, 0xaec5, - 0xad82, 0xad82, 0x080c, 0x0d85, 0x012e, 0x0005, 0x2060, 0x6044, - 0xd0bc, 0x0140, 0xc0bc, 0x6046, 0x6000, 0x908a, 0x0010, 0x1a0c, - 0x0d85, 0x0012, 0x012e, 0x0005, 0xada7, 0xada9, 0xada7, 0xadaf, - 0xada7, 0xada7, 0xada7, 0xada7, 0xada7, 0xada9, 0xada7, 0xada9, - 0xada7, 0xada9, 0xada7, 0xada7, 0xada7, 0xada9, 0xada7, 0x080c, - 0x0d85, 0x2009, 0x0013, 0x080c, 0xb20a, 0x012e, 0x0005, 0x6014, - 0x2048, 0xa87c, 0xd0dc, 0x0130, 0x080c, 0x8c19, 0x080c, 0xb16c, - 0x012e, 0x0005, 0x2009, 0x0049, 0x080c, 0xb20a, 0x012e, 0x0005, - 0x080c, 0xacfc, 0x2001, 0x1a0d, 0x2003, 0x0000, 0x7030, 0x9065, - 0x1130, 0x7004, 0x9086, 0x0003, 0x01e0, 0x080c, 0x0d85, 0x7034, - 0x9092, 0xc350, 0x1258, 0x8000, 0x7036, 0x7004, 0x9086, 0x0003, - 0x0110, 0x7007, 0x0000, 0x781f, 0x0808, 0x0058, 0x080c, 0xb0c0, - 0x0140, 0x080c, 0xeeee, 0x6003, 0x0001, 0x2009, 0x0014, 0x080c, - 0xb20a, 0x781f, 0x0100, 0x080c, 0xad18, 0x012e, 0x0005, 0x080c, - 0xacfc, 0x714c, 0x81ff, 0x1128, 0x2011, 0x1a10, 0x2013, 0x0000, - 0x04c0, 0x2061, 0x0100, 0x7150, 0x9192, 0x7530, 0x1678, 0x8108, - 0x7152, 0x714c, 0x9186, 0x1b55, 0x0120, 0x2001, 0x0391, 0x2003, - 0x0400, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1160, 0x6014, - 0x9084, 0x1984, 0x9085, 0x0012, 0x714c, 0x918e, 0x1b55, 0x1108, - 0xc0fd, 0x6016, 0x00b0, 0x714c, 0x9188, 0x0008, 0x210c, 0x918e, - 0x0009, 0x0d68, 0x6014, 0x9084, 0x1984, 0x9085, 0x0016, 0x714c, - 0x918e, 0x1b55, 0x1108, 0xc0fd, 0x6016, 0x0018, 0x706c, 0xc085, - 0x706e, 0x781f, 0x0200, 0x080c, 0xad18, 0x012e, 0x0005, 0x080c, - 0xacfc, 0x714c, 0x2160, 0x6003, 0x0003, 0x2009, 0x004a, 0x080c, - 0xb20a, 0x781f, 0x0200, 0x080c, 0xad18, 0x012e, 0x0005, 0x7808, - 0xd09c, 0x0de8, 0x7820, 0x2060, 0x6003, 0x0003, 0x080c, 0xacfc, - 0x080c, 0x1dcc, 0x781f, 0x0400, 0x080c, 0xad18, 0x012e, 0x0005, - 0x7808, 0xd09c, 0x0de8, 0x7820, 0x2060, 0x080c, 0xacfc, 0x080c, - 0x1e14, 0x781f, 0x0400, 0x080c, 0xad18, 0x012e, 0x0005, 0x7030, - 0x9065, 0x0148, 0x6044, 0xc0bc, 0x6046, 0x7104, 0x9186, 0x0003, - 0x0110, 0x080c, 0x9ab4, 0x012e, 0x0005, 0x00f6, 0x703c, 0x9086, - 0x0002, 0x0528, 0x704c, 0x907d, 0x0510, 0x7844, 0xc0bc, 0x7846, - 0x7820, 0x9086, 0x0009, 0x0118, 0x080c, 0xa1ca, 0x00c0, 0x7828, - 0xd0fc, 0x1118, 0x080c, 0xa149, 0x0090, 0x2001, 0x1837, 0x2004, - 0x9084, 0x0028, 0x1130, 0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa, - 0x1120, 0x2001, 0x0387, 0x2003, 0x1000, 0x080c, 0xa0ce, 0x00fe, - 0x012e, 0x0005, 0x080c, 0x7840, 0x012e, 0x0005, 0x080c, 0x0d85, - 0x0005, 0x2009, 0x1b66, 0x2104, 0xd0bc, 0x01a8, 0xc0bc, 0x200a, - 0x2009, 0x010b, 0x2104, 0x9085, 0x0002, 0x200a, 0x2009, 0x0101, - 0x2104, 0xc0ac, 0x200a, 0x2009, 0x0105, 0x2104, 0x9084, 0x1984, - 0x9085, 0x8092, 0x200a, 0x012e, 0x0005, 0x080c, 0x8a58, 0x2009, - 0x010b, 0x2104, 0xd08c, 0x01a8, 0xc08c, 0x200a, 0x2001, 0x1848, - 0x2004, 0xd094, 0x1130, 0x2009, 0x0101, 0x2104, 0x9085, 0x0020, - 0x200a, 0x2009, 0x1b66, 0x200b, 0x0000, 0x2001, 0x001b, 0x080c, - 0xaced, 0x012e, 0x0005, 0x00e6, 0x2071, 0x19e8, 0x6044, 0xc0bc, - 0x6046, 0xd0fc, 0x01b8, 0x704c, 0x9c06, 0x1190, 0x2019, 0x0001, - 0x080c, 0xa596, 0x704f, 0x0000, 0x2001, 0x0109, 0x2004, 0xd08c, - 0x1138, 0x2001, 0x0108, 0x2004, 0xd0bc, 0x1110, 0x703f, 0x0000, - 0x080c, 0xa7a1, 0x00ee, 0x0005, 0x0026, 0x7010, 0x9c06, 0x1178, - 0x080c, 0xa65d, 0x6044, 0xc0fc, 0x6046, 0x600c, 0x9015, 0x0120, - 0x7212, 0x600f, 0x0000, 0x0010, 0x7212, 0x720e, 0x9006, 0x002e, - 0x0005, 0x0026, 0x7020, 0x9c06, 0x1178, 0x080c, 0xa65d, 0x6044, - 0xc0fc, 0x6046, 0x600c, 0x9015, 0x0120, 0x7222, 0x600f, 0x0000, - 0x0010, 0x7222, 0x721e, 0x9006, 0x002e, 0x0005, 0x00d6, 0x0036, - 0x7830, 0x9c06, 0x1558, 0x2069, 0x0100, 0x68c0, 0x9005, 0x01f8, - 0x080c, 0x8a4b, 0x080c, 0xa2a0, 0x68c3, 0x0000, 0x080c, 0xa78a, - 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, - 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100, 0x6824, - 0xd084, 0x0110, 0x6827, 0x0001, 0x9085, 0x0001, 0x0038, 0x7808, - 0xc0ad, 0x780a, 0x6003, 0x0009, 0x630a, 0x9006, 0x003e, 0x00de, - 0x0005, 0x0016, 0x0026, 0x0036, 0x6100, 0x2019, 0x0100, 0x2001, - 0x0382, 0x2004, 0xd09c, 0x0190, 0x00c6, 0x0126, 0x2091, 0x2800, - 0x0016, 0x0036, 0x080c, 0xad62, 0x003e, 0x001e, 0x012e, 0x00ce, - 0x6200, 0x2200, 0x9106, 0x0d58, 0x2200, 0x0010, 0x8319, 0x1d38, - 0x003e, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x080c, - 0xacfc, 0x0106, 0x2071, 0x19e8, 0x2069, 0x0100, 0x704c, 0x2060, - 0x9086, 0x1b55, 0x15b8, 0x6814, 0xd08c, 0x0188, 0x6817, 0x0010, - 0x2009, 0x0019, 0x8109, 0x1df0, 0x2001, 0x0032, 0x6920, 0xd1bc, - 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, 0x6824, - 0xd08c, 0x0110, 0x6827, 0x0002, 0x68d0, 0x9005, 0x0118, 0x9082, - 0x0005, 0x0238, 0x6060, 0x8000, 0x6062, 0x2001, 0x0391, 0x2003, - 0x0400, 0x080c, 0x9a48, 0x682c, 0x9084, 0xfffd, 0x682e, 0x2001, - 0x1848, 0x2004, 0xd094, 0x1120, 0x6804, 0x9085, 0x0020, 0x6806, - 0x2069, 0x0000, 0x010e, 0x090c, 0xad18, 0x8dff, 0x00ce, 0x00de, - 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x080c, 0xacfc, 0x0106, - 0x2071, 0x19e8, 0x2069, 0x0100, 0x080c, 0xaf84, 0x68d0, 0x9005, - 0x0158, 0x9082, 0x0005, 0x1240, 0x080c, 0x2b33, 0x2001, 0x0391, - 0x2003, 0x0400, 0x2069, 0x0000, 0x010e, 0x090c, 0xad18, 0x8dff, - 0x00ce, 0x00de, 0x00ee, 0x0005, 0x0016, 0x2001, 0x0134, 0x2004, - 0x9005, 0x0140, 0x9082, 0x0005, 0x1228, 0x2001, 0x0391, 0x2003, - 0x0404, 0x0020, 0x2001, 0x0391, 0x2003, 0x0400, 0x001e, 0x0005, - 0x00d6, 0x0156, 0x080c, 0x9f43, 0x7a14, 0x82ff, 0x0138, 0x7003, - 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200, - 0x7007, 0x0000, 0x2069, 0x1800, 0x901e, 0x6800, 0x9086, 0x0004, - 0x1110, 0xc38d, 0x0060, 0x080c, 0x779e, 0x1110, 0xc3ad, 0x0008, - 0xc3a5, 0x6adc, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e, - 0x080c, 0x8b10, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, 0xffed, - 0x2071, 0x0250, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70, - 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xb03a, 0x60c3, 0x0020, - 0x080c, 0xa270, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, 0x9f43, - 0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, 0x000e, - 0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0488, - 0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2011, 0x19be, - 0x2204, 0x8007, 0x701a, 0x8210, 0x2204, 0x8007, 0x701e, 0x0421, - 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, 0x2004, - 0x7022, 0x2001, 0x1820, 0x2004, 0x7026, 0x0030, 0x2001, 0x1818, - 0x2004, 0x9084, 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001, - 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3, - 0x001c, 0x015e, 0x0804, 0xa270, 0x0006, 0x2001, 0x1837, 0x2004, - 0xd0ac, 0x000e, 0x0005, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, - 0x0002, 0x080c, 0xa635, 0x080c, 0xa516, 0x0036, 0x901e, 0x080c, - 0xa596, 0x003e, 0x0005, 0x080c, 0x3487, 0x0188, 0x0016, 0x00b6, - 0x00c6, 0x7010, 0x9085, 0x0020, 0x7012, 0x2009, 0x007e, 0x080c, - 0x67b4, 0xb85c, 0xc0ac, 0xb85e, 0x00ce, 0x00be, 0x001e, 0x0005, - 0x00d6, 0x00f6, 0x7104, 0x9186, 0x0004, 0x1130, 0x7410, 0x9e90, - 0x0004, 0x9e98, 0x0003, 0x0088, 0x9186, 0x0001, 0x1130, 0x7420, - 0x9e90, 0x0008, 0x9e98, 0x0007, 0x0040, 0x9186, 0x0002, 0x1538, - 0x7428, 0x9e90, 0x000a, 0x9e98, 0x0009, 0x6110, 0x2468, 0x680c, - 0x907d, 0x01e8, 0x7810, 0x9106, 0x1128, 0x2f68, 0x780c, 0x907d, - 0x1dc8, 0x00a8, 0x780c, 0x680e, 0x7c0e, 0x2f12, 0x2304, 0x9f06, - 0x1108, 0x2d1a, 0x9006, 0x7032, 0x7036, 0x7004, 0x9086, 0x0003, - 0x0110, 0x7007, 0x0000, 0x9006, 0x00fe, 0x00de, 0x0005, 0x9085, - 0x0001, 0x0cd0, 0x2071, 0x188d, 0x7000, 0x9005, 0x0140, 0x2001, - 0x0812, 0x2071, 0x1800, 0x7076, 0x707a, 0x706b, 0xffd4, 0x2071, - 0x1800, 0x7074, 0x7056, 0x705b, 0x1ddc, 0x0005, 0x00e6, 0x0126, - 0x2071, 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0010, 0x0608, - 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x001c, - 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, 0x0c98, 0x6003, - 0x0008, 0x8529, 0x7556, 0x9ca8, 0x001c, 0x7068, 0x9502, 0x1230, - 0x755a, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1ddc, - 0x0cc0, 0x9006, 0x0cc0, 0x00e6, 0x2071, 0x1800, 0x7554, 0x9582, - 0x0010, 0x0600, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, - 0x9ce0, 0x001c, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, - 0x0c98, 0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, 0x001c, 0x7068, - 0x9502, 0x1228, 0x755a, 0x9085, 0x0001, 0x00ee, 0x0005, 0x705b, - 0x1ddc, 0x0cc8, 0x9006, 0x0cc8, 0x9c82, 0x1ddc, 0x0a0c, 0x0d85, - 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0d85, 0x9006, 0x6006, - 0x600a, 0x600e, 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, - 0x0000, 0x601e, 0x605e, 0x6062, 0x6026, 0x602a, 0x602e, 0x6032, - 0x6036, 0x603a, 0x603e, 0x604a, 0x602a, 0x6046, 0x6042, 0x2061, - 0x1800, 0x6054, 0x8000, 0x6056, 0x0005, 0x9006, 0x600e, 0x6016, - 0x601a, 0x6012, 0x6022, 0x6002, 0x601e, 0x605e, 0x6062, 0x604a, - 0x6046, 0x2061, 0x1800, 0x6054, 0x8000, 0x6056, 0x0005, 0x0006, - 0x6000, 0x9086, 0x0000, 0x01d8, 0x601c, 0xd084, 0x190c, 0x1ad3, - 0x6023, 0x0007, 0x2001, 0x1986, 0x2004, 0x0006, 0x9082, 0x0051, - 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xece1, 0x604b, 0x0000, - 0x6044, 0xd0fc, 0x1131, 0x9006, 0x6046, 0x6016, 0x6012, 0x000e, - 0x0005, 0x080c, 0xacfc, 0x0106, 0x2001, 0x19fb, 0x2004, 0x9c06, - 0x1130, 0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x003e, 0x080c, - 0xa7a1, 0x010e, 0x090c, 0xad18, 0x0005, 0x00e6, 0x0126, 0x2071, - 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0001, 0x0608, 0x7058, - 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x001c, 0x7068, - 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, 0x0c98, 0x6003, 0x0008, - 0x8529, 0x7556, 0x9ca8, 0x001c, 0x7068, 0x9502, 0x1230, 0x755a, - 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1ddc, 0x0cc0, - 0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, 0xb21e, 0xb228, - 0xb243, 0xb25e, 0xd69a, 0xd6b7, 0xd6d2, 0xb21e, 0xb228, 0x92f7, - 0xb277, 0xb21e, 0xb21e, 0xb21e, 0xb21e, 0xb21e, 0x9186, 0x0013, - 0x1130, 0x6044, 0xd0fc, 0x0110, 0x080c, 0x99ed, 0x0005, 0x0005, - 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e, - 0x0005, 0xb241, 0xb9bc, 0xbba3, 0xb241, 0xbc39, 0xb540, 0xb241, - 0xb241, 0xb93e, 0xc25a, 0xb241, 0xb241, 0xb241, 0xb241, 0xb241, - 0xb241, 0x080c, 0x0d85, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, - 0x0d85, 0x0013, 0x006e, 0x0005, 0xb25c, 0xc875, 0xb25c, 0xb25c, - 0xb25c, 0xb25c, 0xb25c, 0xb25c, 0xc80c, 0xc9f8, 0xb25c, 0xc8b2, - 0xc936, 0xc8b2, 0xc936, 0xb25c, 0x080c, 0x0d85, 0x6000, 0x9082, - 0x0010, 0x1a0c, 0x0d85, 0x6000, 0x0002, 0xb275, 0xc2a4, 0xc33e, - 0xc4c1, 0xc530, 0xb275, 0xb275, 0xb275, 0xc273, 0xc78d, 0xc790, - 0xb275, 0xb275, 0xb275, 0xb275, 0xc7c0, 0x080c, 0x0d85, 0x0066, - 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e, 0x0005, - 0xb290, 0xb290, 0xb2ce, 0xb36d, 0xb3ed, 0xb290, 0xb290, 0xb290, - 0xb292, 0xb290, 0xb290, 0xb290, 0xb290, 0xb290, 0xb290, 0xb290, - 0x080c, 0x0d85, 0x9186, 0x004c, 0x0560, 0x9186, 0x0003, 0x190c, - 0x0d85, 0x0096, 0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, - 0x6014, 0x2048, 0xa87c, 0x9084, 0xa000, 0xc0b5, 0xa87e, 0xa8ac, - 0xa836, 0xa8b0, 0xa83a, 0x9006, 0xa846, 0xa84a, 0xa884, 0x9092, - 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, - 0x621a, 0x009e, 0x080c, 0x1c26, 0x2009, 0x8030, 0x080c, 0x965e, - 0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x080c, - 0xb40f, 0x080c, 0xd65d, 0x6003, 0x0007, 0x0005, 0x00d6, 0x0096, - 0x00f6, 0x2079, 0x1800, 0x7a90, 0x6014, 0x2048, 0xa87c, 0xd0ec, - 0x1110, 0x9290, 0x0018, 0xac78, 0xc4fc, 0x0046, 0xa8e0, 0x9005, - 0x1140, 0xa8dc, 0x921a, 0x0140, 0x0220, 0xa87b, 0x0007, 0x2010, - 0x0028, 0xa87b, 0x0015, 0x0010, 0xa87b, 0x0000, 0x8214, 0xa883, - 0x0000, 0xaa02, 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6, - 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, 0x0015, - 0x1118, 0x2001, 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, 0x0118, - 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002, - 0xb335, 0xb335, 0xb330, 0xb333, 0xb335, 0xb32d, 0xb320, 0xb320, - 0xb320, 0xb320, 0xb320, 0xb320, 0xb320, 0xb320, 0xb320, 0xb320, - 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e, - 0x00fe, 0x009e, 0x00de, 0x080c, 0x0d85, 0x080c, 0xbe51, 0x0028, - 0x080c, 0xbf8f, 0x0010, 0x080c, 0xc085, 0x00fe, 0x00ee, 0x00de, - 0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896, 0x000e, 0x080c, 0xb4cd, - 0x0530, 0xa804, 0xa80e, 0x00a6, 0x2050, 0xb100, 0x00ae, 0x8006, - 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, - 0xaacc, 0xabd0, 0xacd4, 0xadd8, 0x2031, 0x0000, 0x2041, 0x12c2, - 0x080c, 0xb691, 0x0160, 0x000e, 0x9005, 0x0120, 0x00fe, 0x009e, - 0x00de, 0x0005, 0x00fe, 0x009e, 0x00de, 0x0804, 0xb16c, 0x2001, - 0x002c, 0x900e, 0x080c, 0xb533, 0x0c70, 0x91b6, 0x0015, 0x0170, - 0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047, 0x0a0c, 0x0d85, 0x91b2, - 0x0050, 0x1a0c, 0x0d85, 0x9182, 0x0047, 0x0042, 0x080c, 0xaf61, - 0x0120, 0x9086, 0x0002, 0x0904, 0xb2ce, 0x0005, 0xb38f, 0xb38f, - 0xb391, 0xb3c3, 0xb38f, 0xb38f, 0xb38f, 0xb38f, 0xb3d6, 0x080c, - 0x0d85, 0x00d6, 0x0016, 0x0096, 0x6003, 0x0004, 0x6114, 0x2148, - 0xa87c, 0xd0fc, 0x01c0, 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894, - 0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, 0xb533, 0x080c, - 0xb16c, 0x00a8, 0x6003, 0x0002, 0xa8a4, 0xa9a8, 0x9105, 0x1178, - 0xa8ae, 0xa8b2, 0x0c78, 0xa87f, 0x0020, 0xa88c, 0xa88a, 0xa8a4, - 0xa8ae, 0xa8a8, 0xa8b2, 0xa8c7, 0x0000, 0xa8cb, 0x0000, 0x009e, - 0x001e, 0x00de, 0x0005, 0x080c, 0x9a48, 0x00d6, 0x0096, 0x6114, - 0x2148, 0x080c, 0xcf1b, 0x0120, 0xa87b, 0x0006, 0x080c, 0x7012, - 0x009e, 0x00de, 0x080c, 0xb16c, 0x0804, 0x9ab3, 0x080c, 0x9a48, - 0x080c, 0x3315, 0x080c, 0xd65a, 0x00d6, 0x0096, 0x6114, 0x2148, - 0x080c, 0xcf1b, 0x0120, 0xa87b, 0x0029, 0x080c, 0x7012, 0x009e, - 0x00de, 0x080c, 0xb16c, 0x0804, 0x9ab3, 0x9182, 0x0047, 0x0002, - 0xb3fd, 0xb3ff, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd, - 0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3ff, 0x080c, 0x0d85, 0x00d6, - 0x0096, 0x601f, 0x0000, 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883, - 0x0000, 0x080c, 0x7012, 0x009e, 0x00de, 0x0804, 0xb16c, 0x0026, - 0x0036, 0x0056, 0x0066, 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c, - 0x1059, 0x000e, 0x090c, 0x0d85, 0xa960, 0x21e8, 0xa95c, 0x9188, - 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079, - 0x1800, 0x7990, 0x9188, 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76, - 0x2950, 0x00a6, 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029, - 0x0001, 0x9182, 0x0035, 0x1228, 0x2011, 0x001f, 0x080c, 0xca7b, - 0x04c0, 0x2130, 0x2009, 0x0034, 0x2011, 0x001f, 0x080c, 0xca7b, - 0x96b2, 0x0034, 0xb004, 0x904d, 0x0110, 0x080c, 0x100b, 0x080c, - 0x1059, 0x01d0, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, - 0xb406, 0x968a, 0x003d, 0x1230, 0x2608, 0x2011, 0x001b, 0x080c, - 0xca7b, 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, - 0x001b, 0x080c, 0xca7b, 0x0c18, 0x2001, 0x0205, 0x2003, 0x0000, - 0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0xb070, 0xc0fd, 0xb072, - 0x0048, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, - 0x0050, 0xb566, 0x2a48, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, - 0x7012, 0x000e, 0x2048, 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e, - 0x006e, 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096, - 0x0006, 0x080c, 0x1059, 0x000e, 0x090c, 0x0d85, 0xa960, 0x21e8, - 0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, - 0xaa66, 0xa87a, 0x2079, 0x1800, 0x7990, 0x810c, 0x9188, 0x000c, - 0x9182, 0x001a, 0x0210, 0x2009, 0x001a, 0x21a8, 0x810b, 0xa972, - 0xac76, 0x2e98, 0xa85c, 0x9080, 0x001f, 0x20a0, 0x2001, 0x0205, - 0x200c, 0x918d, 0x0080, 0x2102, 0x4003, 0x2003, 0x0000, 0x080c, - 0x7012, 0x009e, 0x00fe, 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6, - 0x0096, 0x0016, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, 0x2102, - 0x001e, 0x2079, 0x0200, 0x2e98, 0xa87c, 0xd0ec, 0x0118, 0x9e80, - 0x000c, 0x2098, 0x2021, 0x003e, 0x901e, 0x9282, 0x0020, 0x0218, - 0x2011, 0x0020, 0x2018, 0x9486, 0x003e, 0x1170, 0x0096, 0x080c, - 0x1059, 0x2900, 0x009e, 0x05c0, 0xa806, 0x2048, 0xa860, 0x20e8, - 0xa85c, 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140, - 0x2009, 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, 0x2100, 0x9318, - 0x2200, 0x9402, 0x1228, 0x2400, 0x9202, 0x2410, 0x9318, 0x9006, - 0x2020, 0x22a8, 0xa800, 0x9200, 0xa802, 0x20e1, 0x0000, 0x4003, - 0x83ff, 0x0180, 0x3300, 0x9086, 0x0280, 0x1130, 0x7814, 0x8000, - 0x9085, 0x0080, 0x7816, 0x2e98, 0x2310, 0x84ff, 0x0904, 0xb4e2, - 0x0804, 0xb4e4, 0x9085, 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe, - 0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348, - 0xa87a, 0xa982, 0x080c, 0x7006, 0x009e, 0x003e, 0x00de, 0x0005, - 0x91b6, 0x0015, 0x1118, 0x080c, 0xb16c, 0x0030, 0x91b6, 0x0016, - 0x190c, 0x0d85, 0x080c, 0xb16c, 0x0005, 0x20a9, 0x000e, 0x20e1, - 0x0000, 0x2e98, 0x6014, 0x0096, 0x2048, 0xa860, 0x20e8, 0xa85c, - 0x20a0, 0x009e, 0x4003, 0x9196, 0x0016, 0x01f0, 0x0136, 0x9080, - 0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, 0x3418, 0x8318, - 0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, 0x1db8, 0x2011, - 0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, 0x4003, 0x3418, - 0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, 0xcf1b, 0x0130, - 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0x009e, 0x0804, - 0xb16c, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11a8, - 0x6010, 0x00b6, 0x2058, 0xb8d7, 0x0000, 0x00be, 0x6014, 0x9005, - 0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xab32, 0x080c, - 0xb16c, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, 0x1d48, 0x0cc8, - 0x0006, 0x0016, 0x080c, 0xd645, 0x0188, 0x6014, 0x9005, 0x1170, - 0x600b, 0x0003, 0x601b, 0x0000, 0x604b, 0x0000, 0x2009, 0x0022, - 0x080c, 0xb994, 0x9006, 0x001e, 0x000e, 0x0005, 0x9085, 0x0001, - 0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1, - 0x0000, 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080, - 0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099, - 0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, 0xa804, 0x2048, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001, - 0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003, - 0x2003, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, - 0x080c, 0xb16c, 0x001e, 0x009e, 0x0005, 0x0096, 0x0016, 0x900e, - 0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, 0x00ff, 0x800c, - 0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, 0x9108, 0x810b, - 0x2011, 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, 0x080c, 0xca7b, - 0x080c, 0xcf1b, 0x0140, 0x6014, 0x2048, 0xa807, 0x0000, 0xa864, - 0xa8e2, 0xa867, 0x0103, 0x080c, 0xb16c, 0x001e, 0x009e, 0x0005, - 0x0016, 0x2009, 0x0000, 0x7030, 0x9086, 0x0200, 0x0110, 0x2009, - 0x0001, 0x0096, 0x6014, 0x904d, 0x090c, 0x0d85, 0xa97a, 0x080c, - 0x7012, 0x009e, 0x080c, 0xb16c, 0x001e, 0x0005, 0x0016, 0x0096, - 0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, 0x7034, - 0x800c, 0x810b, 0x2011, 0x000c, 0x2019, 0x000c, 0x6014, 0x2048, - 0xa804, 0x0096, 0x9005, 0x0108, 0x2048, 0x080c, 0xca7b, 0x009e, - 0x080c, 0xcf1b, 0x0148, 0xa804, 0x9005, 0x1158, 0xa807, 0x0000, - 0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xb16c, 0x009e, 0x001e, - 0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, 0x0100, 0x1118, - 0x080c, 0xbb5c, 0x00e0, 0xa034, 0x8007, 0x800c, 0x8806, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x000c, 0xa87b, - 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xaaa0, 0xab9c, 0xaca8, - 0xada4, 0x2031, 0x0000, 0x2041, 0x12a8, 0x0019, 0x0d08, 0x008e, - 0x0898, 0x0096, 0x0006, 0x080c, 0x1059, 0x000e, 0x01b0, 0xa8ab, - 0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, 0x2800, 0xa89e, - 0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, 0x0086, 0x2940, - 0x080c, 0x114e, 0x008e, 0x9085, 0x0001, 0x009e, 0x0005, 0x00e6, - 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, - 0xba10, 0x00be, 0x9206, 0x1520, 0x700c, 0x6210, 0x00b6, 0x2258, - 0xba14, 0x00be, 0x9206, 0x11e0, 0x604b, 0x0000, 0x2c68, 0x0016, - 0x2009, 0x0035, 0x080c, 0xd5bb, 0x001e, 0x1158, 0x622c, 0x2268, - 0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, 0x0006, - 0x0128, 0x080c, 0xb16c, 0x0020, 0x0039, 0x0010, 0x080c, 0xb7c7, - 0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, 0x2048, 0x9186, - 0x0015, 0x0904, 0xb7a6, 0x918e, 0x0016, 0x1904, 0xb7c5, 0x700c, - 0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, 0x1904, - 0xb780, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, 0xb762, - 0x0804, 0xb7c3, 0x6808, 0x9086, 0xffff, 0x1904, 0xb7a8, 0xa87c, - 0x9084, 0x0060, 0x9086, 0x0020, 0x1150, 0xa8ac, 0xa934, 0x9106, - 0x1904, 0xb7a8, 0xa8b0, 0xa938, 0x9106, 0x1904, 0xb7a8, 0x6824, - 0xd084, 0x1904, 0xb7a8, 0xd0b4, 0x0158, 0x0016, 0x2001, 0x1986, - 0x200c, 0x6018, 0x9102, 0x9082, 0x0005, 0x001e, 0x1a04, 0xb7a8, - 0x080c, 0xd10c, 0x6810, 0x0096, 0x2048, 0xa9a0, 0x009e, 0x685c, - 0xa87a, 0xa976, 0x6864, 0xa882, 0xa87c, 0xc0dc, 0xc0f4, 0xc0d4, - 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, 0x080c, 0x955b, - 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, 0x82ff, 0x002e, 0x1138, - 0x00c6, 0x2d60, 0x080c, 0xcc01, 0x00ce, 0x0804, 0xb7c3, 0x00c6, - 0xa868, 0xd0fc, 0x1118, 0x080c, 0x622f, 0x0010, 0x080c, 0x663a, - 0x00ce, 0x1904, 0xb7a8, 0x00c6, 0x2d60, 0x080c, 0xb16c, 0x00ce, - 0x0804, 0xb7c3, 0x00c6, 0x080c, 0xb1dd, 0x0198, 0x6017, 0x0000, - 0x6810, 0x6012, 0x080c, 0xd3b6, 0x6023, 0x0003, 0x6904, 0x00c6, - 0x2d60, 0x080c, 0xb16c, 0x00ce, 0x080c, 0xb20a, 0x00ce, 0x0804, - 0xb7c3, 0x2001, 0x1988, 0x2004, 0x684a, 0x00ce, 0x0804, 0xb7c3, - 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, 0x2058, 0xb900, - 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, 0x0003, 0x080c, - 0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2009, - 0x8020, 0x080c, 0x9617, 0x00ce, 0x0430, 0x700c, 0x9086, 0x2a00, - 0x1138, 0x2001, 0x1988, 0x2004, 0x684a, 0x00e8, 0x04c1, 0x00e8, - 0x89ff, 0x090c, 0x0d85, 0x00c6, 0x00d6, 0x2d60, 0xa867, 0x0103, - 0xa87b, 0x0003, 0x080c, 0x6e27, 0x080c, 0xd10c, 0x080c, 0xb1a7, - 0x0026, 0x6010, 0x00b6, 0x2058, 0xba3c, 0x080c, 0x68df, 0x00be, - 0x002e, 0x00de, 0x00ce, 0x080c, 0xb16c, 0x009e, 0x0005, 0x9186, - 0x0015, 0x1128, 0x2001, 0x1988, 0x2004, 0x684a, 0x0068, 0x918e, - 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xece1, 0x080c, - 0x8c19, 0x080c, 0xb16c, 0x00ce, 0x080c, 0xb16c, 0x0005, 0x0026, - 0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, 0x2001, - 0x1988, 0x2004, 0x684a, 0x0804, 0xb841, 0x00c6, 0x2d60, 0x080c, - 0xcadc, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, 0x2d00, - 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x2009, 0x8023, 0x080c, - 0x9617, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8, 0x89ff, - 0x090c, 0x0d85, 0x6800, 0x9086, 0x0004, 0x1190, 0xa87c, 0xd0ac, - 0x0178, 0xa843, 0x0fff, 0xa83f, 0x0fff, 0xa880, 0xc0fc, 0xa882, - 0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, 0x6832, 0x00e0, - 0xa87c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4, 0x1d48, - 0xa838, 0xa934, 0x9105, 0x0d80, 0x0c20, 0xd2ec, 0x1d68, 0x7024, - 0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e, 0x7024, - 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xd2a0, 0x080c, 0x9ab3, - 0x0010, 0x080c, 0xb16c, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6, - 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258, - 0xba10, 0x00be, 0x9206, 0x1904, 0xb8ac, 0x700c, 0x6210, 0x00b6, - 0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xb8ac, 0x6038, 0x2068, - 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, 0xb8ac, - 0x9286, 0x0002, 0x0904, 0xb8ac, 0x9286, 0x0000, 0x05e8, 0x6808, - 0x633c, 0x9306, 0x15c8, 0x2071, 0x026c, 0x9186, 0x0015, 0x0570, - 0x918e, 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, 0x9186, - 0x004b, 0x01c0, 0x9186, 0x004c, 0x01a8, 0x9186, 0x004d, 0x0190, - 0x9186, 0x004e, 0x0178, 0x9186, 0x0052, 0x0160, 0x6014, 0x0096, - 0x2048, 0x080c, 0xcf1b, 0x090c, 0x0d85, 0xa87b, 0x0003, 0x009e, - 0x080c, 0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x2009, 0x8020, 0x080c, 0x9617, 0x00ce, 0x0030, 0x6038, 0x2070, - 0x2001, 0x1988, 0x2004, 0x704a, 0x080c, 0xb16c, 0x002e, 0x00de, - 0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, 0x6010, - 0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, 0xc48c, - 0xbc02, 0x0470, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90, - 0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, 0xc222, 0x002e, - 0x003e, 0x015e, 0x009e, 0x1904, 0xb91d, 0x0096, 0x0156, 0x0036, - 0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, 0x0004, - 0x080c, 0xc222, 0x002e, 0x003e, 0x015e, 0x009e, 0x15b0, 0x7238, - 0xba0a, 0x733c, 0xbb0e, 0x83ff, 0x0118, 0xbc00, 0xc48d, 0xbc02, - 0xa804, 0x9005, 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804, 0xb57c, - 0x0096, 0x2048, 0xaa12, 0xab16, 0xac0a, 0x009e, 0x8006, 0x8006, - 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, - 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, - 0x12a8, 0x080c, 0xb691, 0x0130, 0x00fe, 0x009e, 0x080c, 0xb16c, - 0x00be, 0x0005, 0x080c, 0xbb5c, 0x0cb8, 0x2b78, 0x00f6, 0x080c, - 0x3315, 0x080c, 0xd65a, 0x00fe, 0x00c6, 0x080c, 0xb116, 0x2f00, - 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, - 0x0001, 0x2001, 0x0007, 0x080c, 0x66fa, 0x080c, 0x6726, 0x080c, - 0x961e, 0x080c, 0x9ab3, 0x00ce, 0x0804, 0xb8f0, 0x2100, 0x91b2, - 0x0053, 0x1a0c, 0x0d85, 0x91b2, 0x0040, 0x1a04, 0xb9a6, 0x0002, - 0xb994, 0xb994, 0xb98a, 0xb994, 0xb994, 0xb994, 0xb988, 0xb988, - 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, - 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, - 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb994, - 0xb988, 0xb994, 0xb994, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, - 0xb98a, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, - 0xb988, 0xb988, 0xb994, 0xb994, 0xb988, 0xb988, 0xb988, 0xb988, - 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb994, 0xb988, 0xb988, - 0x080c, 0x0d85, 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8d4, 0xc08c, - 0xb8d6, 0x00be, 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, 0x9186, - 0x0032, 0x0118, 0x080c, 0x961e, 0x0010, 0x080c, 0x9617, 0x0126, - 0x2091, 0x8000, 0x080c, 0x9ab3, 0x012e, 0x0005, 0x2600, 0x0002, - 0xb994, 0xb994, 0xb9ba, 0xb994, 0xb994, 0xb9ba, 0xb9ba, 0xb9ba, - 0xb9ba, 0xb994, 0xb9ba, 0xb994, 0xb9ba, 0xb994, 0xb9ba, 0xb9ba, - 0xb9ba, 0xb9ba, 0x080c, 0x0d85, 0x6004, 0x90b2, 0x0053, 0x1a0c, - 0x0d85, 0x91b6, 0x0013, 0x0904, 0xba91, 0x91b6, 0x0027, 0x1904, - 0xba3d, 0x080c, 0x99ed, 0x6004, 0x080c, 0xd121, 0x01b0, 0x080c, - 0xd132, 0x01a8, 0x908e, 0x0021, 0x0904, 0xba3a, 0x908e, 0x0022, - 0x1130, 0x080c, 0xb5a8, 0x0904, 0xba36, 0x0804, 0xba37, 0x908e, - 0x003d, 0x0904, 0xba3a, 0x0804, 0xba30, 0x080c, 0x3344, 0x2001, - 0x0007, 0x080c, 0x66fa, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, - 0x080c, 0xbb5c, 0x9186, 0x007e, 0x1148, 0x2001, 0x1837, 0x2014, - 0xc285, 0x080c, 0x779e, 0x1108, 0xc2ad, 0x2202, 0x080c, 0xacfc, - 0x0036, 0x0026, 0x2019, 0x0028, 0x2110, 0x080c, 0xedee, 0x002e, - 0x003e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, - 0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x6010, 0x00b6, 0x905d, - 0x0100, 0x00be, 0x2c08, 0x080c, 0xe75d, 0x007e, 0x003e, 0x002e, - 0x001e, 0x080c, 0xad18, 0x080c, 0xd65a, 0x0016, 0x080c, 0xd3ae, - 0x080c, 0xb16c, 0x001e, 0x080c, 0x341e, 0x080c, 0x9ab3, 0x0030, - 0x080c, 0xd3ae, 0x080c, 0xb16c, 0x080c, 0x9ab3, 0x0005, 0x080c, - 0xbb5c, 0x0cb0, 0x080c, 0xbb98, 0x0c98, 0x9186, 0x0015, 0x0118, - 0x9186, 0x0016, 0x1140, 0x080c, 0xaf61, 0x0d80, 0x9086, 0x0002, - 0x0904, 0xbba3, 0x0c58, 0x9186, 0x0014, 0x1d40, 0x080c, 0x99ed, - 0x6004, 0x908e, 0x0022, 0x1118, 0x080c, 0xb5a8, 0x09f8, 0x080c, - 0x3315, 0x080c, 0xd65a, 0x080c, 0xd121, 0x1190, 0x080c, 0x3344, - 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, 0xbb5c, 0x9186, - 0x007e, 0x1128, 0x2001, 0x1837, 0x200c, 0xc185, 0x2102, 0x0800, - 0x080c, 0xd132, 0x1120, 0x080c, 0xbb5c, 0x0804, 0xba30, 0x6004, - 0x908e, 0x0032, 0x1160, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079, - 0x0000, 0x080c, 0x36bf, 0x00fe, 0x00ee, 0x0804, 0xba30, 0x6004, - 0x908e, 0x0021, 0x0d40, 0x908e, 0x0022, 0x090c, 0xbb5c, 0x0804, - 0xba30, 0x90b2, 0x0040, 0x1a04, 0xbb3c, 0x2008, 0x0002, 0xbad9, - 0xbada, 0xbadd, 0xbae0, 0xbae3, 0xbaf0, 0xbad7, 0xbad7, 0xbad7, - 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, - 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, - 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbaf3, 0xbafe, 0xbad7, - 0xbaff, 0xbafe, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbafe, - 0xbafe, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, - 0xbad7, 0xbb27, 0xbafe, 0xbad7, 0xbafa, 0xbad7, 0xbad7, 0xbad7, - 0xbafb, 0xbad7, 0xbad7, 0xbad7, 0xbafe, 0xbb22, 0xbad7, 0x080c, - 0x0d85, 0x0420, 0x2001, 0x000b, 0x0448, 0x2001, 0x0003, 0x0430, - 0x2001, 0x0005, 0x0418, 0x6010, 0x00b6, 0x2058, 0xb804, 0x00be, - 0x9084, 0x00ff, 0x9086, 0x0000, 0x11d8, 0x2001, 0x0001, 0x00b0, - 0x2001, 0x0009, 0x0098, 0x6003, 0x0005, 0x080c, 0xd65d, 0x080c, - 0x9ab3, 0x0058, 0x0018, 0x0010, 0x080c, 0x66fa, 0x04b8, 0x080c, - 0xd65d, 0x6003, 0x0004, 0x080c, 0x9ab3, 0x0005, 0x080c, 0x66fa, - 0x6003, 0x0002, 0x0036, 0x2019, 0x1852, 0x2304, 0x9084, 0xff00, - 0x1120, 0x2001, 0x1986, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, - 0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c, - 0x9ab3, 0x0c18, 0x080c, 0xd3ae, 0x080c, 0xb16c, 0x08f0, 0x00e6, - 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, 0x36bf, 0x00fe, - 0x00ee, 0x080c, 0x99ed, 0x080c, 0xb16c, 0x0878, 0x6003, 0x0002, - 0x080c, 0xd65d, 0x0804, 0x9ab3, 0x2600, 0x2008, 0x0002, 0xbb53, - 0xbb36, 0xbb51, 0xbb36, 0xbb36, 0xbb51, 0xbb51, 0xbb51, 0xbb51, - 0xbb36, 0xbb51, 0xbb36, 0xbb51, 0xbb36, 0xbb51, 0xbb51, 0xbb51, - 0xbb51, 0x080c, 0x0d85, 0x0096, 0x6014, 0x2048, 0x080c, 0x7012, - 0x009e, 0x080c, 0xb16c, 0x0005, 0x00e6, 0x0096, 0x0026, 0x0016, - 0x080c, 0xcf1b, 0x0568, 0x6014, 0x2048, 0xa864, 0x9086, 0x0139, - 0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, 0x080c, 0x55cc, 0x0130, - 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0028, 0x2001, 0x0030, - 0x900e, 0x2011, 0x4005, 0x080c, 0xd51f, 0x0090, 0xa868, 0xd0fc, - 0x0178, 0xa807, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, 0x0168, - 0x908e, 0x003d, 0x0150, 0x001e, 0xa867, 0x0103, 0xa833, 0x0100, - 0x001e, 0x002e, 0x009e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc0, - 0x0096, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, 0xa823, - 0x8001, 0x009e, 0x0005, 0x00b6, 0x6610, 0x2658, 0xb804, 0x9084, - 0x00ff, 0x90b2, 0x000c, 0x1a0c, 0x0d85, 0x6604, 0x96b6, 0x004d, - 0x1120, 0x080c, 0xd43e, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0043, - 0x1120, 0x080c, 0xd487, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x004b, - 0x1120, 0x080c, 0xd4b3, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0033, - 0x1120, 0x080c, 0xd3d0, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0028, - 0x1120, 0x080c, 0xd170, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0029, - 0x1120, 0x080c, 0xd1b1, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x001f, - 0x1120, 0x080c, 0xb54d, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0000, - 0x1118, 0x080c, 0xb8b2, 0x04e0, 0x6604, 0x96b6, 0x0022, 0x1118, - 0x080c, 0xb589, 0x04a8, 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c, - 0xb6af, 0x0470, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, 0xb847, - 0x0438, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0xb5c1, 0x0400, - 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xb5fd, 0x00c8, 0x6604, - 0x96b6, 0x0049, 0x1118, 0x080c, 0xb63e, 0x0090, 0x6604, 0x96b6, - 0x0041, 0x1118, 0x080c, 0xb628, 0x0058, 0x91b6, 0x0015, 0x1110, - 0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, 0x00be, 0x0804, 0xbf34, - 0x00be, 0x0005, 0x080c, 0xb227, 0x0cd8, 0xbc45, 0xbc53, 0xbc45, - 0xbc9a, 0xbc45, 0xbe51, 0xbf41, 0xbc45, 0xbc45, 0xbf0a, 0xbc45, - 0xbf20, 0x0096, 0x601f, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, - 0xa867, 0x0103, 0x009e, 0x0804, 0xb16c, 0xa001, 0xa001, 0x0005, - 0x6604, 0x96b6, 0x0004, 0x1130, 0x2001, 0x0001, 0x080c, 0x66e6, - 0x0804, 0xb16c, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7090, 0x9086, - 0x0074, 0x1540, 0x080c, 0xe72e, 0x11b0, 0x6010, 0x00b6, 0x2058, - 0x7030, 0xd08c, 0x0128, 0xb800, 0xd0bc, 0x0110, 0xc0c5, 0xb802, - 0x00f9, 0x00be, 0x2001, 0x0006, 0x080c, 0x66fa, 0x080c, 0x3344, - 0x080c, 0xb16c, 0x0098, 0x2001, 0x000a, 0x080c, 0x66fa, 0x080c, - 0x3344, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x961e, 0x080c, - 0x9ab3, 0x0020, 0x2001, 0x0001, 0x080c, 0xbe21, 0x00ee, 0x0005, - 0x00d6, 0xb800, 0xd084, 0x0160, 0x9006, 0x080c, 0x66e6, 0x2069, - 0x1847, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x6726, - 0x00de, 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011, 0x1824, 0x2204, - 0x9086, 0x0074, 0x1904, 0xbdf6, 0x6010, 0x2058, 0xbaa0, 0x9286, - 0x007e, 0x1120, 0x080c, 0xc090, 0x0804, 0xbd63, 0x2001, 0x180d, - 0x2004, 0xd08c, 0x0904, 0xbd05, 0x00d6, 0x080c, 0x779e, 0x01a0, - 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e, 0x0904, 0xbd04, - 0x080c, 0x5854, 0x1598, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, - 0x0103, 0xa833, 0xdead, 0x0450, 0x6010, 0x00b6, 0x2058, 0xb910, - 0x00be, 0x9186, 0x00ff, 0x0580, 0x0026, 0x2011, 0x8008, 0x080c, - 0x6c35, 0x002e, 0x0548, 0x6014, 0x9005, 0x090c, 0x0d85, 0x2048, - 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, - 0x900e, 0x2011, 0x4009, 0x080c, 0xd51f, 0x0040, 0x6014, 0x2048, - 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, - 0xb9a0, 0x0016, 0x080c, 0x3344, 0x080c, 0xb16c, 0x001e, 0x080c, - 0x341e, 0x00de, 0x0804, 0xbdfb, 0x00de, 0x080c, 0xc085, 0x6010, - 0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014, 0x9005, 0x01a8, - 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, - 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd51f, 0x0030, 0xa807, - 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x2001, 0x0006, 0x080c, - 0x66fa, 0x080c, 0x3344, 0x080c, 0xb16c, 0x0804, 0xbdfb, 0x080c, - 0xbe09, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, 0xd0f4, 0x01e8, - 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, 0x2001, 0x0000, - 0x900e, 0x2011, 0x4000, 0x080c, 0xd51f, 0x08f8, 0x080c, 0xbdff, - 0x0160, 0x9006, 0x080c, 0x66e6, 0x2001, 0x0004, 0x080c, 0x6726, - 0x2001, 0x0007, 0x080c, 0x66fa, 0x08a0, 0x2001, 0x0004, 0x080c, - 0x66fa, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x961e, 0x080c, - 0x9ab3, 0x0804, 0xbdfb, 0xb85c, 0xd0e4, 0x0178, 0x080c, 0xd348, - 0x080c, 0x779e, 0x0118, 0xd0dc, 0x1904, 0xbd25, 0x2011, 0x1837, - 0x2204, 0xc0ad, 0x2012, 0x0804, 0xbd25, 0x080c, 0xd389, 0x2011, - 0x1837, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xe905, 0x000e, - 0x1904, 0xbd25, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x66fa, - 0x9006, 0x080c, 0x66e6, 0x00c6, 0x2001, 0x180f, 0x2004, 0xd09c, - 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, 0x1800, 0x700c, - 0x9084, 0x00ff, 0x78e6, 0x707e, 0x7010, 0x78ea, 0x7082, 0x908c, - 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x26d5, - 0x00f6, 0x2100, 0x900e, 0x080c, 0x268c, 0x795e, 0x00fe, 0x9186, - 0x0081, 0x01f0, 0x2009, 0x0081, 0x00e0, 0x2009, 0x00ef, 0x00f6, - 0x2079, 0x0100, 0x79ea, 0x78e7, 0x0000, 0x7932, 0x7936, 0x780c, - 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x26d5, 0x00f6, 0x2079, 0x1800, - 0x7982, 0x2100, 0x900e, 0x797e, 0x080c, 0x268c, 0x795e, 0x00fe, - 0x8108, 0x080c, 0x6749, 0x2b00, 0x00ce, 0x1904, 0xbd25, 0x6012, - 0x2009, 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, 0x027c, 0x210c, - 0x918c, 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, 0xb916, 0x2001, - 0x0002, 0x080c, 0x66fa, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0028, 0x080c, 0xbb5c, - 0x2001, 0x0001, 0x0431, 0x00de, 0x009e, 0x00be, 0x0005, 0x2001, - 0x1810, 0x2004, 0xd0a4, 0x0120, 0x2001, 0x1848, 0x2004, 0xd0ac, - 0x0005, 0x00e6, 0x080c, 0xee47, 0x0190, 0x2071, 0x0260, 0x7108, - 0x720c, 0x918c, 0x00ff, 0x1118, 0x9284, 0xff00, 0x0140, 0x6010, - 0x2058, 0xb8a0, 0x9084, 0xff80, 0x1110, 0xb912, 0xba16, 0x00ee, - 0x0005, 0x2030, 0x9005, 0x0158, 0x2001, 0x0007, 0x080c, 0x66fa, - 0x080c, 0x5854, 0x1120, 0x2001, 0x0007, 0x080c, 0x6726, 0x2600, - 0x9005, 0x11b0, 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, - 0x1178, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, - 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4ca1, 0x004e, 0x003e, - 0x080c, 0x3344, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, 0x0804, - 0xb16c, 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1800, 0x7090, - 0x9086, 0x0014, 0x1904, 0xbf00, 0x2001, 0x180d, 0x2004, 0xd08c, - 0x0904, 0xbeb3, 0x00d6, 0x080c, 0x779e, 0x01a0, 0x0026, 0x2011, - 0x0010, 0x080c, 0x6c35, 0x002e, 0x0904, 0xbeb2, 0x080c, 0x5854, - 0x1598, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, - 0xdead, 0x0450, 0x6010, 0x00b6, 0x2058, 0xb910, 0x00be, 0x9186, - 0x00ff, 0x0580, 0x0026, 0x2011, 0x8008, 0x080c, 0x6c35, 0x002e, - 0x0548, 0x6014, 0x9005, 0x090c, 0x0d85, 0x2048, 0xa864, 0x9084, - 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, 0x900e, 0x2011, - 0x4009, 0x080c, 0xd51f, 0x0040, 0x6014, 0x2048, 0xa807, 0x0000, - 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, 0xb9a0, 0x0016, - 0x080c, 0x3344, 0x080c, 0xb16c, 0x001e, 0x080c, 0x341e, 0x00de, - 0x0804, 0xbf05, 0x00de, 0x080c, 0x5854, 0x1170, 0x6014, 0x9005, - 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, - 0x080c, 0x4e58, 0x004e, 0x003e, 0x00d6, 0x6010, 0x2058, 0x080c, - 0x684f, 0x080c, 0xbc88, 0x00de, 0x080c, 0xc15b, 0x1588, 0x6010, - 0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, 0x66fa, - 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, 0x00ff, 0x9086, - 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, - 0xd51f, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130, - 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x009e, 0x080c, - 0x3344, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c, 0xb16c, 0x0028, - 0x080c, 0xbb5c, 0x9006, 0x080c, 0xbe21, 0x001e, 0x002e, 0x00ee, - 0x00be, 0x0005, 0x2011, 0x1824, 0x2204, 0x9086, 0x0014, 0x1160, - 0x2001, 0x0002, 0x080c, 0x66fa, 0x6003, 0x0001, 0x6007, 0x0001, - 0x080c, 0x961e, 0x0804, 0x9ab3, 0x2001, 0x0001, 0x0804, 0xbe21, - 0x2030, 0x2011, 0x1824, 0x2204, 0x9086, 0x0004, 0x1148, 0x96b6, - 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x66fa, 0x0804, 0xb16c, - 0x2001, 0x0001, 0x0804, 0xbe21, 0x0002, 0xbc45, 0xbf4c, 0xbc45, - 0xbf8f, 0xbc45, 0xc03c, 0xbf41, 0xbc48, 0xbc45, 0xc050, 0xbc45, - 0xc062, 0x6604, 0x9686, 0x0003, 0x0904, 0xbe51, 0x96b6, 0x001e, - 0x1110, 0x080c, 0xb16c, 0x0005, 0x00b6, 0x00d6, 0x00c6, 0x080c, - 0xc074, 0x11a0, 0x9006, 0x080c, 0x66e6, 0x080c, 0x3315, 0x080c, - 0xd65a, 0x2001, 0x0002, 0x080c, 0x66fa, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0428, 0x2009, 0x026e, - 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2058, 0xb840, 0x9084, - 0x00ff, 0x9005, 0x0180, 0x8001, 0xb842, 0x601b, 0x000a, 0x0098, - 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x908e, 0x1900, 0x0158, - 0x908e, 0x1e00, 0x0990, 0x080c, 0x3315, 0x080c, 0xd65a, 0x2001, - 0x0001, 0x080c, 0xbe21, 0x00ce, 0x00de, 0x00be, 0x0005, 0x0096, - 0x00b6, 0x0026, 0x9016, 0x080c, 0xc082, 0x00d6, 0x2069, 0x197c, - 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, - 0x1138, 0x2069, 0x1820, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, - 0x00de, 0x0088, 0x9006, 0x080c, 0x66e6, 0x2001, 0x0002, 0x080c, - 0x66fa, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x961e, 0x080c, - 0x9ab3, 0x0804, 0xc00c, 0x080c, 0xcf1b, 0x01b0, 0x6014, 0x2048, - 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, 0x0016, 0x2001, - 0x0002, 0x080c, 0xd57c, 0x00b0, 0x6014, 0x2048, 0xa864, 0xd0fc, - 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e, 0x2004, 0xd0dc, - 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x1110, - 0x9006, 0x0c38, 0x080c, 0xbb5c, 0x2009, 0x026e, 0x2134, 0x96b4, - 0x00ff, 0x9686, 0x0005, 0x0520, 0x9686, 0x000b, 0x01c8, 0x2009, - 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, 0x0009, 0x01c0, - 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0190, 0x2001, 0x0004, - 0x080c, 0x66fa, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, 0x0020, - 0x2001, 0x0001, 0x080c, 0xbe21, 0x002e, 0x00be, 0x009e, 0x0005, - 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0140, - 0xa864, 0x9086, 0x0139, 0x0118, 0xa868, 0xd0fc, 0x0108, 0x0c40, - 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0138, 0x8001, - 0xb842, 0x601b, 0x000a, 0x6007, 0x0016, 0x08f0, 0xb8a0, 0x9086, - 0x007e, 0x1138, 0x00e6, 0x2071, 0x1800, 0x080c, 0x6130, 0x00ee, - 0x0010, 0x080c, 0x3315, 0x0860, 0x2001, 0x0004, 0x080c, 0x66fa, - 0x080c, 0xc082, 0x1140, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, - 0x961e, 0x0804, 0x9ab3, 0x080c, 0xbb5c, 0x9006, 0x0804, 0xbe21, - 0x0489, 0x1160, 0x2001, 0x0008, 0x080c, 0x66fa, 0x6003, 0x0001, - 0x6007, 0x0005, 0x080c, 0x961e, 0x0804, 0x9ab3, 0x2001, 0x0001, - 0x0804, 0xbe21, 0x00f9, 0x1160, 0x2001, 0x000a, 0x080c, 0x66fa, - 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x961e, 0x0804, 0x9ab3, - 0x2001, 0x0001, 0x0804, 0xbe21, 0x2009, 0x026e, 0x2104, 0x9086, - 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086, - 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6, 0x00c6, 0x0016, - 0x6110, 0x2158, 0x080c, 0x67c3, 0x001e, 0x00ce, 0x00be, 0x0005, - 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, 0x2058, - 0x2009, 0x1837, 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0xc12d, - 0x0560, 0x2009, 0x1837, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x6c0d, - 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xea8d, 0x2001, - 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, - 0x080c, 0x32da, 0x00e6, 0x2071, 0x1800, 0x080c, 0x30bf, 0x00ee, - 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, 0x080c, 0x341e, - 0x8108, 0x1f04, 0xc0c6, 0x015e, 0x00ce, 0x080c, 0xc085, 0x2071, - 0x0260, 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, 0x1837, 0x200c, - 0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, 0xd0dc, - 0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1837, 0x2102, 0x9184, - 0x0050, 0x9086, 0x0050, 0x05d0, 0x2079, 0x0100, 0x2e04, 0x9084, - 0x00ff, 0x2069, 0x181f, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, - 0x2069, 0x1820, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0x9084, - 0xff00, 0x001e, 0x9105, 0x2009, 0x182c, 0x200a, 0x2200, 0x9084, - 0x00ff, 0x2008, 0x080c, 0x26d5, 0x080c, 0x779e, 0x0170, 0x2071, - 0x0260, 0x2069, 0x1982, 0x7048, 0x206a, 0x704c, 0x6806, 0x7050, - 0x680a, 0x7054, 0x680e, 0x080c, 0xd348, 0x0040, 0x2001, 0x0006, - 0x080c, 0x66fa, 0x080c, 0x3344, 0x080c, 0xb16c, 0x001e, 0x003e, - 0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x0096, 0x0026, 0x0036, - 0x00e6, 0x0156, 0x2019, 0x182c, 0x231c, 0x83ff, 0x01f0, 0x2071, - 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205, - 0x9306, 0x1198, 0x2011, 0x0276, 0x20a9, 0x0004, 0x2b48, 0x2019, - 0x000a, 0x080c, 0xc222, 0x1148, 0x2011, 0x027a, 0x20a9, 0x0004, - 0x2019, 0x0006, 0x080c, 0xc222, 0x1100, 0x015e, 0x00ee, 0x003e, - 0x002e, 0x009e, 0x0005, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9086, - 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, 0x1188, 0x703c, 0xd0ec, - 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, 0x1138, 0x7054, 0xd0a4, - 0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ee, - 0x0005, 0x00e6, 0x0096, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026, - 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0x19f4, 0x252c, 0x2021, - 0x19fb, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7254, 0x7074, - 0x9202, 0x1a04, 0xc1ee, 0x080c, 0x8eee, 0x0904, 0xc1e7, 0x080c, - 0xeabe, 0x0904, 0xc1e7, 0x6720, 0x9786, 0x0007, 0x0904, 0xc1e7, - 0x2500, 0x9c06, 0x0904, 0xc1e7, 0x2400, 0x9c06, 0x0904, 0xc1e7, - 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, 0x0130, 0x00b6, - 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1590, 0x00c6, 0x6043, 0xffff, - 0x6000, 0x9086, 0x0004, 0x1110, 0x080c, 0x1ad3, 0x9786, 0x000a, - 0x0148, 0x080c, 0xd132, 0x1130, 0x00ce, 0x080c, 0xbb5c, 0x080c, - 0xb1a7, 0x00e8, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x01a8, 0x9786, - 0x0003, 0x1530, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, - 0xa878, 0x2048, 0x080c, 0x100b, 0x009e, 0xab7a, 0xa877, 0x0000, - 0x080c, 0x7006, 0x080c, 0xd10c, 0x080c, 0xb1a7, 0x00ce, 0x9ce0, - 0x001c, 0x7068, 0x9c02, 0x1210, 0x0804, 0xc18e, 0x012e, 0x000e, - 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x009e, 0x00ee, 0x0005, - 0x9786, 0x0006, 0x1118, 0x080c, 0xea30, 0x0c30, 0x9786, 0x0009, - 0x1148, 0x6000, 0x9086, 0x0004, 0x0d08, 0x2009, 0x004c, 0x080c, - 0xb20a, 0x08e0, 0x9786, 0x000a, 0x0980, 0x0820, 0x220c, 0x2304, - 0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xc20e, 0x9006, 0x0005, - 0x2304, 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, - 0x0001, 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, - 0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, - 0x20a9, 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, - 0x1dc8, 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, - 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, - 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x810f, 0x2304, 0x9106, - 0x1130, 0x8210, 0x8318, 0x1f04, 0xc24c, 0x9006, 0x0005, 0x918d, - 0x0001, 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d85, 0x080c, - 0xd121, 0x0120, 0x080c, 0xd132, 0x0158, 0x0028, 0x080c, 0x3344, - 0x080c, 0xd132, 0x0128, 0x080c, 0x99ed, 0x080c, 0xb16c, 0x0005, - 0x080c, 0xbb5c, 0x0cc0, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, - 0x0208, 0x000a, 0x0005, 0xc292, 0xc292, 0xc292, 0xc292, 0xc292, - 0xc292, 0xc292, 0xc292, 0xc292, 0xc292, 0xc292, 0xc294, 0xc294, - 0xc294, 0xc294, 0xc292, 0xc292, 0xc292, 0xc294, 0xc292, 0xc292, - 0xc292, 0xc292, 0x080c, 0x0d85, 0x600b, 0xffff, 0x6003, 0x000f, - 0x6106, 0x0126, 0x2091, 0x8000, 0x080c, 0xd65d, 0x2009, 0x8000, - 0x080c, 0x9617, 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004, - 0x9082, 0x0040, 0x0804, 0xc31c, 0x9186, 0x0027, 0x1520, 0x080c, - 0x99ed, 0x080c, 0x3315, 0x080c, 0xd65a, 0x0096, 0x6114, 0x2148, - 0x080c, 0xcf1b, 0x0198, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c, - 0x0068, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, 0xa97c, - 0xc1c5, 0xa97e, 0x080c, 0x7012, 0x080c, 0xd10c, 0x009e, 0x080c, - 0xb16c, 0x0804, 0x9ab3, 0x9186, 0x0014, 0x1120, 0x6004, 0x9082, - 0x0040, 0x0030, 0x9186, 0x0053, 0x0110, 0x080c, 0x0d85, 0x0005, - 0x0002, 0xc2fa, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, - 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, 0xc313, 0xc313, 0xc313, 0xc313, - 0xc2f8, 0xc313, 0xc2f8, 0xc313, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, - 0x080c, 0x0d85, 0x080c, 0x99ed, 0x0096, 0x6114, 0x2148, 0x080c, - 0xcf1b, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000, - 0xa880, 0xc0ec, 0xa882, 0x080c, 0x7012, 0x080c, 0xd10c, 0x009e, - 0x080c, 0xb16c, 0x0005, 0x080c, 0x99ed, 0x080c, 0xd132, 0x090c, - 0xbb5c, 0x080c, 0xb16c, 0x0005, 0x0002, 0xc336, 0xc334, 0xc334, - 0xc334, 0xc334, 0xc334, 0xc334, 0xc334, 0xc334, 0xc334, 0xc334, - 0xc338, 0xc338, 0xc338, 0xc338, 0xc334, 0xc33a, 0xc334, 0xc338, - 0xc334, 0xc334, 0xc334, 0xc334, 0x080c, 0x0d85, 0x080c, 0x0d85, - 0x080c, 0x0d85, 0x080c, 0xb16c, 0x0804, 0x9ab3, 0x9182, 0x0057, - 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xc35d, 0xc35d, - 0xc35d, 0xc35d, 0xc35d, 0xc396, 0xc488, 0xc35d, 0xc494, 0xc35d, - 0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d, - 0xc35d, 0xc494, 0xc35f, 0xc35d, 0xc492, 0x080c, 0x0d85, 0x00b6, - 0x0096, 0x6114, 0x2148, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1508, - 0xa87b, 0x0000, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87c, 0xd0ac, - 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0x080c, 0x6e27, - 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0xb8d0, - 0x9005, 0x0110, 0x080c, 0x68df, 0x080c, 0xb16c, 0x009e, 0x00be, - 0x0005, 0xa87c, 0xd0ac, 0x09e0, 0xa838, 0xa934, 0x9105, 0x09c0, - 0xa880, 0xd0bc, 0x19a8, 0x080c, 0xd267, 0x0c80, 0x00b6, 0x0096, - 0x6114, 0x2148, 0x601c, 0xd0fc, 0x1110, 0x7644, 0x0008, 0x9036, - 0x96b4, 0x0fff, 0x86ff, 0x1590, 0x6010, 0x2058, 0xb800, 0xd0bc, - 0x1904, 0xc477, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0xa87c, - 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0x080c, - 0x6e27, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, - 0xb8d0, 0x9005, 0x0110, 0x080c, 0x68df, 0x601c, 0xd0fc, 0x1148, - 0x7044, 0xd0e4, 0x1904, 0xc458, 0x080c, 0xb16c, 0x009e, 0x00be, - 0x0005, 0x2009, 0x0211, 0x210c, 0x080c, 0x0d85, 0x968c, 0x0c00, - 0x0150, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, 0xc45c, 0x7348, - 0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0508, - 0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, - 0xa87b, 0x0015, 0xa87c, 0xd0ac, 0x0170, 0xa938, 0xaa34, 0x2100, - 0x9205, 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, 0x9206, 0x0118, - 0xa992, 0xaa8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, - 0x0010, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0x901e, 0xd6c4, - 0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, - 0x0804, 0xc3a2, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, - 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, - 0x0025, 0x080c, 0xca7b, 0x003e, 0xd6cc, 0x0904, 0xc3b7, 0x7154, - 0xa98a, 0x81ff, 0x0904, 0xc3b7, 0x9192, 0x0021, 0x1278, 0x8304, - 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xca7b, 0x2011, 0x0205, - 0x2013, 0x0000, 0x080c, 0xd5e8, 0x0804, 0xc3b7, 0xa868, 0xd0fc, - 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c50, 0x00a6, 0x2950, 0x080c, - 0xca1a, 0x00ae, 0x080c, 0xd5e8, 0x080c, 0xca6b, 0x0804, 0xc3b9, - 0x080c, 0xd22a, 0x0804, 0xc3ce, 0xa87c, 0xd0ac, 0x0904, 0xc3df, - 0xa880, 0xd0bc, 0x1904, 0xc3df, 0x9684, 0x0400, 0x0130, 0xa838, - 0xab34, 0x9305, 0x0904, 0xc3df, 0x00b8, 0x7348, 0xa838, 0x9306, - 0x1198, 0x734c, 0xa834, 0x931e, 0x0904, 0xc3df, 0x0068, 0xa87c, - 0xd0ac, 0x0904, 0xc3aa, 0xa838, 0xa934, 0x9105, 0x0904, 0xc3aa, - 0xa880, 0xd0bc, 0x1904, 0xc3aa, 0x080c, 0xd267, 0x0804, 0xc3ce, - 0x00f6, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x00fe, - 0x0021, 0x0005, 0x0011, 0x0005, 0x0005, 0x0096, 0x6003, 0x0002, - 0x6007, 0x0043, 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0128, 0x009e, - 0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0xa9ac, 0x910a, 0x2300, - 0xaab0, 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, 0x0e90, 0xac46, - 0xab4a, 0xae36, 0xad3a, 0x6044, 0xd0fc, 0x190c, 0xad25, 0x604b, - 0x0000, 0x080c, 0x1c9c, 0x1118, 0x6144, 0x080c, 0x9643, 0x009e, - 0x0005, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, - 0x0005, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, - 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e2, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, - 0xc4f3, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc517, 0xc4e0, 0xc4e0, - 0x080c, 0x0d85, 0x6004, 0x9086, 0x0040, 0x1110, 0x080c, 0x99ed, - 0x2019, 0x0001, 0x080c, 0xa596, 0x6003, 0x0002, 0x080c, 0xd662, - 0x080c, 0x9a48, 0x0005, 0x6004, 0x9086, 0x0040, 0x1110, 0x080c, - 0x99ed, 0x2019, 0x0001, 0x080c, 0xa596, 0x080c, 0x9a48, 0x080c, - 0x3315, 0x080c, 0xd65a, 0x0096, 0x6114, 0x2148, 0x080c, 0xcf1b, - 0x0150, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, 0x080c, - 0x7012, 0x080c, 0xd10c, 0x009e, 0x080c, 0xb16c, 0x0005, 0x080c, - 0x0d85, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, 0x0007, 0x8002, - 0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, 0x2009, 0x1a7c, - 0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, 0xa88e, 0x0005, - 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, - 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc551, 0xc54f, 0xc54f, - 0xc60e, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f, - 0xc54f, 0xc54f, 0xc54f, 0xc74e, 0xc54f, 0xc758, 0xc54f, 0x080c, - 0x0d85, 0x601c, 0xd0bc, 0x0178, 0xd084, 0x0168, 0xd0f4, 0x0120, - 0xc084, 0x601e, 0x0804, 0xc33e, 0x6114, 0x0096, 0x2148, 0xa87c, - 0xc0e5, 0xa87e, 0x009e, 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, - 0x0260, 0x6114, 0x2150, 0x601c, 0xd0fc, 0x1110, 0x7644, 0x0008, - 0x9036, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210, - 0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, - 0x86ff, 0x0904, 0xc607, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120, - 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xc607, - 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676, - 0x0c38, 0x080c, 0x1059, 0x090c, 0x0d85, 0x2900, 0xb07a, 0xb77c, - 0x97bd, 0x0200, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, - 0xa86e, 0xb070, 0xa872, 0x7044, 0x9084, 0xf000, 0x9635, 0xae76, - 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c, - 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0xa87b, - 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, 0x0015, 0x0038, 0xd6d4, - 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080, - 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86, - 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, - 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xca7b, 0x003e, - 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021, - 0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xca7b, - 0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120, - 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, 0xca1a, 0x080c, - 0x1a9f, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x2001, 0x1988, - 0x2004, 0x604a, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, - 0x1118, 0xa87c, 0xc0dc, 0xa87e, 0x6003, 0x0002, 0x080c, 0xd66b, - 0x0904, 0xc749, 0x604b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800, - 0x00be, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xc70d, 0xa978, 0xa868, - 0xd0fc, 0x0904, 0xc6ce, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, - 0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904, - 0xc69b, 0x9086, 0x0028, 0x1904, 0xc687, 0xa87b, 0x001c, 0xb07b, - 0x001c, 0x0804, 0xc6a3, 0x6024, 0xd0f4, 0x11d0, 0xa838, 0xaa34, - 0x9205, 0x09c8, 0xa838, 0xaa90, 0x9206, 0x1120, 0xa88c, 0xaa34, - 0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, 0xa9ac, 0xa834, 0x9102, - 0x603a, 0xa9b0, 0xa838, 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026, - 0x6010, 0x00b6, 0x2058, 0xb83c, 0x8000, 0xb83e, 0x00be, 0x601c, - 0xc0fc, 0x601e, 0x9006, 0xa876, 0xa892, 0xa88e, 0xa87c, 0xc0e4, - 0xa87e, 0xd0cc, 0x0140, 0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048, - 0x080c, 0x100b, 0x009e, 0x080c, 0xd267, 0x0804, 0xc749, 0xd1dc, - 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xd508, 0x0118, - 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, - 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, - 0x9115, 0x190c, 0xc519, 0xa87c, 0xb07e, 0xa890, 0xb092, 0xa88c, - 0xb08e, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0x20a9, - 0x0020, 0x8a06, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e0, 0x9084, - 0xffc0, 0x9080, 0x0019, 0x2098, 0x4003, 0x00ae, 0x000e, 0xa882, - 0x000e, 0xc0cc, 0xa87e, 0x080c, 0xd5e8, 0x001e, 0xa874, 0x0006, - 0x2148, 0x080c, 0x100b, 0x001e, 0x0804, 0xc73a, 0x0016, 0x00a6, - 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, - 0x0028, 0x1128, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x00e0, 0xd1dc, - 0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xd508, 0x0118, - 0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, - 0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, - 0x9115, 0x190c, 0xc519, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa87c, - 0xb07e, 0x00ae, 0x080c, 0x100b, 0x009e, 0x080c, 0xd5e8, 0xa974, - 0x0016, 0x080c, 0xca6b, 0x001e, 0x0468, 0xa867, 0x0103, 0xa974, - 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, - 0xa87b, 0x001c, 0x00d0, 0xd1dc, 0x0148, 0xa87b, 0x0015, 0x080c, - 0xd508, 0x0118, 0xa974, 0xc1dc, 0xa976, 0x0078, 0xd1d4, 0x0118, - 0xa87b, 0x0007, 0x0050, 0xa87b, 0x0000, 0xa87c, 0xd0ac, 0x0128, - 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0xa974, 0x0016, 0x080c, - 0x6e27, 0x001e, 0x6010, 0x00b6, 0x2058, 0xba3c, 0xb8d0, 0x0016, - 0x9005, 0x190c, 0x68df, 0x001e, 0x00be, 0xd1e4, 0x1120, 0x080c, - 0xb16c, 0x009e, 0x0005, 0x080c, 0xd22a, 0x0cd8, 0x6114, 0x0096, - 0x2148, 0xa97c, 0x080c, 0xd66b, 0x190c, 0x1abf, 0x009e, 0x0005, - 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, 0x01e8, 0xa877, - 0x0000, 0xa87b, 0x0000, 0xa867, 0x0103, 0x00b6, 0x6010, 0x2058, - 0xa834, 0xa938, 0x9115, 0x11a0, 0x080c, 0x6e27, 0xba3c, 0x8211, - 0x0208, 0xba3e, 0xb8d0, 0x9005, 0x0110, 0x080c, 0x68df, 0x080c, - 0xb16c, 0x00be, 0x009e, 0x0005, 0xa87c, 0xc0dc, 0xa87e, 0x08f8, - 0xb800, 0xd0bc, 0x1120, 0xa834, 0x080c, 0xc519, 0x0c28, 0xa880, - 0xd0bc, 0x1dc8, 0x080c, 0xd267, 0x0c60, 0x080c, 0x99ed, 0x0010, - 0x080c, 0x9a48, 0x601c, 0xd084, 0x0110, 0x080c, 0x1ad3, 0x080c, - 0xcf1b, 0x01f0, 0x0096, 0x6114, 0x2148, 0x080c, 0xd132, 0x1118, - 0x080c, 0xbb5c, 0x00a0, 0xa867, 0x0103, 0x2009, 0x180c, 0x210c, - 0xd18c, 0x1198, 0xd184, 0x1170, 0x6108, 0xa97a, 0x918e, 0x0029, - 0x1110, 0x080c, 0xeddf, 0xa877, 0x0000, 0x080c, 0x7012, 0x009e, - 0x0804, 0xb1a7, 0xa87b, 0x0004, 0x0cb0, 0xa87b, 0x0004, 0x0c98, - 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, - 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7e1, 0xc7df, 0xc7df, - 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, - 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc805, 0xc7df, 0xc7df, 0x080c, - 0x0d85, 0x080c, 0x5848, 0x01f8, 0x6014, 0x7144, 0x918c, 0x0fff, - 0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, 0x00ff, 0x0096, 0x904d, - 0x0188, 0xa87b, 0x0000, 0xa864, 0x9086, 0x0139, 0x0128, 0xa867, - 0x0103, 0xa976, 0xaa96, 0x0030, 0xa897, 0x4000, 0xa99a, 0xaa9e, - 0x080c, 0x7012, 0x009e, 0x0804, 0xb16c, 0x080c, 0x5848, 0x0dd8, - 0x6014, 0x900e, 0x9016, 0x0c10, 0x9182, 0x0085, 0x0002, 0xc81e, - 0xc81c, 0xc81c, 0xc82a, 0xc81c, 0xc81c, 0xc81c, 0xc81c, 0xc81c, - 0xc81c, 0xc81c, 0xc81c, 0xc81c, 0x080c, 0x0d85, 0x6003, 0x0001, - 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0x8020, 0x080c, 0x9617, - 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0x0260, - 0x7224, 0x6216, 0x7220, 0x080c, 0xcf09, 0x01f8, 0x2268, 0x6800, - 0x9086, 0x0000, 0x01d0, 0x6010, 0x6d10, 0x952e, 0x11b0, 0x00c6, - 0x2d60, 0x00d6, 0x080c, 0xcadc, 0x00de, 0x00ce, 0x0158, 0x702c, - 0xd084, 0x1118, 0x080c, 0xcaa6, 0x0010, 0x6803, 0x0002, 0x6007, - 0x0086, 0x0028, 0x080c, 0xcac8, 0x0d90, 0x6007, 0x0087, 0x6003, - 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x7220, 0x080c, 0xcf09, - 0x0178, 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140, - 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, 0xd267, 0x00ce, - 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, - 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d85, 0x908a, 0x0092, 0x1a0c, - 0x0d85, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, 0x0120, 0x9186, - 0x0014, 0x190c, 0x0d85, 0x080c, 0x99ed, 0x0096, 0x6014, 0x2048, - 0x080c, 0xcf1b, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, - 0x0029, 0x080c, 0x7012, 0x009e, 0x080c, 0xb1a7, 0x0804, 0x9ab3, - 0xc8ad, 0xc8af, 0xc8af, 0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad, - 0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad, 0x080c, 0x0d85, 0x080c, - 0xb1a7, 0x0005, 0x9186, 0x0013, 0x1130, 0x6004, 0x9082, 0x0085, - 0x2008, 0x0804, 0xc8fe, 0x9186, 0x0027, 0x1558, 0x080c, 0x99ed, - 0x080c, 0x3315, 0x080c, 0xd65a, 0x0096, 0x6014, 0x2048, 0x080c, - 0xcf1b, 0x0150, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0029, - 0x080c, 0x7012, 0x080c, 0xd10c, 0x009e, 0x080c, 0xb16c, 0x0005, - 0x9186, 0x0089, 0x0118, 0x9186, 0x008a, 0x1140, 0x080c, 0xaf61, - 0x0128, 0x9086, 0x000c, 0x0904, 0xc936, 0x0000, 0x080c, 0xb227, - 0x0c70, 0x9186, 0x0014, 0x1d60, 0x080c, 0x99ed, 0x0096, 0x6014, - 0x2048, 0x080c, 0xcf1b, 0x0d00, 0xa867, 0x0103, 0xa877, 0x0000, - 0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, 0x0890, 0x0002, 0xc90e, - 0xc90c, 0xc90c, 0xc90c, 0xc90c, 0xc90c, 0xc922, 0xc90c, 0xc90c, - 0xc90c, 0xc90c, 0xc90c, 0xc90c, 0x080c, 0x0d85, 0x6034, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, - 0x2001, 0x1986, 0x0010, 0x2001, 0x1987, 0x2004, 0x601a, 0x6003, - 0x000c, 0x0005, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, - 0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x1986, 0x0010, 0x2001, - 0x1987, 0x2004, 0x601a, 0x6003, 0x000e, 0x0005, 0x9182, 0x0092, - 0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, 0xb227, 0xc94c, - 0xc94c, 0xc94c, 0xc94c, 0xc94e, 0xc99b, 0xc94c, 0xc94c, 0xc94c, - 0xc94c, 0xc94c, 0xc94c, 0xc94c, 0x080c, 0x0d85, 0x0096, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c, - 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, - 0x009e, 0x0804, 0xc9af, 0x080c, 0xcf1b, 0x1118, 0x080c, 0xd10c, - 0x0068, 0x6014, 0x2048, 0x080c, 0xd671, 0x1110, 0x080c, 0xd10c, - 0xa867, 0x0103, 0x080c, 0xd625, 0x080c, 0x7012, 0x00d6, 0x2c68, - 0x080c, 0xb116, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, - 0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, - 0x613e, 0x6910, 0x6112, 0x080c, 0xd3b6, 0x695c, 0x615e, 0x6023, - 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x2d60, 0x00de, 0x080c, - 0xb16c, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, - 0xd0bc, 0x05a0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, - 0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6, - 0x2c68, 0x080c, 0xd5bb, 0x11f0, 0x080c, 0xb116, 0x01d8, 0x6106, - 0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e, - 0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a, - 0x693c, 0x613e, 0x695c, 0x615e, 0x080c, 0xd3b6, 0x2009, 0x8020, - 0x080c, 0x9617, 0x2d60, 0x00de, 0x0804, 0xb16c, 0x0096, 0x6014, - 0x2048, 0x080c, 0xcf1b, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4, - 0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118, - 0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xd226, 0xa877, - 0x0000, 0x080c, 0x7012, 0x080c, 0xd10c, 0x009e, 0x0804, 0xb16c, - 0x0016, 0x0096, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0140, 0xa867, - 0x0103, 0xa87b, 0x0028, 0xa877, 0x0000, 0x080c, 0x7012, 0x009e, - 0x001e, 0x9186, 0x0013, 0x0158, 0x9186, 0x0014, 0x0130, 0x9186, - 0x0027, 0x0118, 0x080c, 0xb227, 0x0020, 0x080c, 0x99ed, 0x080c, - 0xb1a7, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, 0x2029, 0x0001, - 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, 0x8304, - 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, 0x080c, 0xca7b, - 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c, 0x100b, 0x080c, - 0x1059, 0x0520, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920, - 0xb406, 0x968a, 0x003d, 0x1228, 0x2608, 0x2011, 0x001b, 0x0499, - 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, 0x001b, - 0x0451, 0x0c28, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, - 0x95ad, 0x0003, 0xb566, 0x95ac, 0x0000, 0x0048, 0x2001, 0x0205, - 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, 0x009e, - 0x006e, 0x005e, 0x0005, 0x00a6, 0x89ff, 0x0158, 0xa804, 0x9055, - 0x0130, 0xa807, 0x0000, 0x080c, 0x7012, 0x2a48, 0x0cb8, 0x080c, - 0x7012, 0x00ae, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7814, 0x9085, - 0x0080, 0x7816, 0xd184, 0x0108, 0x8108, 0x810c, 0x20a9, 0x0001, - 0xa860, 0x20e8, 0xa85c, 0x9200, 0x20a0, 0x20e1, 0x0000, 0x2300, - 0x9e00, 0x2098, 0x4003, 0x8318, 0x9386, 0x0020, 0x1148, 0x2018, - 0x2300, 0x9e00, 0x2098, 0x7814, 0x8000, 0x9085, 0x0080, 0x7816, - 0x8109, 0x1d80, 0x7817, 0x0000, 0x00fe, 0x0005, 0x6920, 0x9186, - 0x0003, 0x0118, 0x9186, 0x0002, 0x11d0, 0x00c6, 0x00d6, 0x00e6, - 0x2d60, 0x0096, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0150, 0x2001, - 0x0006, 0xa980, 0xc1d5, 0x080c, 0x725e, 0x080c, 0x7006, 0x080c, - 0xd10c, 0x009e, 0x080c, 0xb1a7, 0x00ee, 0x00de, 0x00ce, 0x0005, - 0x00c6, 0x702c, 0xd084, 0x1170, 0x6008, 0x2060, 0x6020, 0x9086, - 0x0002, 0x1140, 0x6104, 0x9186, 0x0085, 0x0118, 0x9186, 0x008b, - 0x1108, 0x9006, 0x00ce, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000, - 0x2031, 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, 0x012e, 0x006e, - 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x6020, - 0x9084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xcb2a, 0xcb2a, - 0xcb25, 0xcb4e, 0xcb06, 0xcb25, 0xcb08, 0xcb25, 0xcb25, 0x9458, - 0xcb25, 0xcb25, 0xcb25, 0xcb06, 0xcb06, 0xcb06, 0x080c, 0x0d85, - 0x6010, 0x9080, 0x0000, 0x2004, 0xd0bc, 0x190c, 0xcb4e, 0x0036, - 0x6014, 0x0096, 0x2048, 0xa880, 0x009e, 0xd0cc, 0x0118, 0x2019, - 0x000c, 0x0038, 0xd094, 0x0118, 0x2019, 0x000d, 0x0010, 0x2019, - 0x0010, 0x080c, 0xe578, 0x003e, 0x0005, 0x9006, 0x0005, 0x9085, - 0x0001, 0x0005, 0x0096, 0x86ff, 0x11e8, 0x6014, 0x2048, 0x080c, - 0xcf1b, 0x01d0, 0x6043, 0xffff, 0xa864, 0x9086, 0x0139, 0x1128, - 0xa87b, 0x0005, 0xa883, 0x0000, 0x0028, 0x900e, 0x2001, 0x0005, - 0x080c, 0x725e, 0x080c, 0xd226, 0x080c, 0x7006, 0x080c, 0xb1a7, - 0x9085, 0x0001, 0x009e, 0x0005, 0x9006, 0x0ce0, 0x080c, 0xacfc, - 0x080c, 0xd67f, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x002b, 0x0106, - 0x080c, 0xad18, 0x010e, 0x0005, 0xcb6c, 0xcb9c, 0xcb6e, 0xcbc3, - 0xcb97, 0xcb6c, 0xcb25, 0xcb2a, 0xcb2a, 0xcb25, 0xcb25, 0xcb25, - 0xcb25, 0xcb25, 0xcb25, 0xcb25, 0x080c, 0x0d85, 0x86ff, 0x1520, - 0x6020, 0x9086, 0x0006, 0x0500, 0x0096, 0x6014, 0x2048, 0x080c, - 0xcf1b, 0x0168, 0xa87c, 0xd0cc, 0x0140, 0x0096, 0xc0cc, 0xa87e, - 0xa878, 0x2048, 0x080c, 0x100b, 0x009e, 0x080c, 0xd226, 0x009e, - 0x080c, 0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x2009, 0x8020, 0x080c, 0x95f9, 0x9085, 0x0001, 0x0005, 0x0066, - 0x080c, 0x1ad3, 0x006e, 0x0890, 0x00e6, 0x2071, 0x19e8, 0x7030, - 0x9c06, 0x1120, 0x080c, 0xa516, 0x00ee, 0x0840, 0x6020, 0x9084, - 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, 0x0001, - 0x2c40, 0x080c, 0xa667, 0x009e, 0x008e, 0x0040, 0x0066, 0x080c, - 0xa412, 0x190c, 0x0d85, 0x080c, 0xa420, 0x006e, 0x00ee, 0x1904, - 0xcb6e, 0x0804, 0xcb25, 0x0036, 0x00e6, 0x2071, 0x19e8, 0x704c, - 0x9c06, 0x1138, 0x901e, 0x080c, 0xa596, 0x00ee, 0x003e, 0x0804, - 0xcb6e, 0x080c, 0xa7a1, 0x00ee, 0x003e, 0x1904, 0xcb6e, 0x0804, - 0xcb25, 0x00c6, 0x0066, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, - 0x00ce, 0x0005, 0xcbf9, 0xcce2, 0xce50, 0xcc01, 0xb1a7, 0xcbf9, - 0xe56e, 0xd667, 0xcce2, 0x941f, 0xcedc, 0xcbf2, 0xcbf2, 0xcbf2, - 0xcbf2, 0xcbf2, 0x080c, 0x0d85, 0x080c, 0xd132, 0x1110, 0x080c, - 0xbb5c, 0x0005, 0x080c, 0x99ed, 0x0804, 0xb16c, 0x601b, 0x0001, - 0x0005, 0x080c, 0xcf1b, 0x0130, 0x6014, 0x0096, 0x2048, 0x2c00, - 0xa896, 0x009e, 0x080c, 0xacfc, 0x080c, 0xd67f, 0x908a, 0x0010, - 0x1a0c, 0x0d85, 0x0013, 0x0804, 0xad18, 0xcc25, 0xcc27, 0xcc51, - 0xcc65, 0xcc92, 0xcc25, 0xcbf9, 0xcbf9, 0xcbf9, 0xcc6c, 0xcc6c, - 0xcc25, 0xcc25, 0xcc25, 0xcc25, 0xcc76, 0x080c, 0x0d85, 0x00e6, - 0x6014, 0x0096, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x2071, - 0x19e8, 0x7030, 0x9c06, 0x01d0, 0x0066, 0x080c, 0xa412, 0x190c, - 0x0d85, 0x080c, 0xa420, 0x006e, 0x080c, 0xd5ff, 0x6007, 0x0085, - 0x6003, 0x000b, 0x6023, 0x0002, 0x2001, 0x1987, 0x2004, 0x601a, - 0x2009, 0x8020, 0x080c, 0x95f9, 0x00ee, 0x0005, 0x601b, 0x0001, - 0x0cd8, 0x0096, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, - 0x080c, 0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, - 0x2009, 0x8020, 0x080c, 0x95f9, 0x0005, 0x080c, 0xacfc, 0x080c, - 0xaee3, 0x080c, 0xad18, 0x0c28, 0x0096, 0x601b, 0x0001, 0x6014, - 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x0005, 0x080c, 0x5848, - 0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, 0xa864, 0xa867, 0x0103, - 0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, 0xa867, 0x0139, 0xa87b, - 0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, 0x080c, 0x7012, 0x009e, - 0x0804, 0xb16c, 0x6014, 0x0096, 0x904d, 0x0904, 0xccdd, 0xa97c, - 0xd1e4, 0x1160, 0x611c, 0xd1fc, 0x0904, 0xccdd, 0x6110, 0x00b6, - 0x2158, 0xb93c, 0x8109, 0x0208, 0xb93e, 0x00be, 0x080c, 0xad18, - 0x2001, 0x180f, 0x2004, 0xd0c4, 0x0110, 0x009e, 0x0005, 0xa884, - 0x009e, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, 0x0030, - 0x2c08, 0x080c, 0x16b9, 0x2001, 0x030c, 0x2004, 0x9086, 0x0041, - 0x1198, 0x6014, 0x0096, 0x904d, 0x090c, 0x0d85, 0xa880, 0xd0f4, - 0x1130, 0xc0f5, 0xa882, 0x009e, 0x601b, 0x0002, 0x0068, 0x009e, - 0x00c6, 0x080c, 0x2185, 0x00ce, 0x6000, 0x9086, 0x0004, 0x1120, - 0x2009, 0x0048, 0x080c, 0xb20a, 0x0005, 0x009e, 0x080c, 0x1ad3, - 0x0804, 0xcc51, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x000b, - 0x0005, 0xccf9, 0xcbfe, 0xccfb, 0xccf9, 0xccfb, 0xccfb, 0xcbfa, - 0xccf9, 0xcbf4, 0xcbf4, 0xccf9, 0xccf9, 0xccf9, 0xccf9, 0xccf9, - 0xccf9, 0x080c, 0x0d85, 0x6010, 0x00b6, 0x2058, 0xb804, 0x9084, - 0x00ff, 0x00be, 0x908a, 0x000c, 0x1a0c, 0x0d85, 0x00b6, 0x0013, - 0x00be, 0x0005, 0xcd16, 0xcde7, 0xcd18, 0xcd58, 0xcd18, 0xcd58, - 0xcd18, 0xcd26, 0xcd16, 0xcd58, 0xcd16, 0xcd47, 0x080c, 0x0d85, - 0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, 0x0004, 0x05a8, 0x908e, - 0x0002, 0x0590, 0x908e, 0x0052, 0x0904, 0xcde3, 0x6004, 0x080c, - 0xd132, 0x0904, 0xce00, 0x908e, 0x0004, 0x1110, 0x080c, 0x3344, - 0x908e, 0x0021, 0x0904, 0xce04, 0x908e, 0x0022, 0x0904, 0xce4b, - 0x908e, 0x003d, 0x0904, 0xce04, 0x908e, 0x0039, 0x0904, 0xce08, - 0x908e, 0x0035, 0x0904, 0xce08, 0x908e, 0x001e, 0x0178, 0x908e, - 0x0001, 0x1140, 0x6010, 0x2058, 0xb804, 0x9084, 0x00ff, 0x9086, - 0x0006, 0x0110, 0x080c, 0x3315, 0x080c, 0xbb5c, 0x0804, 0xb1a7, - 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xcdd4, 0x9186, - 0x0002, 0x1904, 0xcda9, 0x2001, 0x1837, 0x2004, 0xd08c, 0x11c8, - 0x080c, 0x779e, 0x11b0, 0x080c, 0xd645, 0x0138, 0x080c, 0x77c1, - 0x1120, 0x080c, 0x76a7, 0x0804, 0xce34, 0x2001, 0x197d, 0x2003, - 0x0001, 0x2001, 0x1800, 0x2003, 0x0001, 0x080c, 0x76cd, 0x0804, - 0xce34, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x0080, 0x0130, 0x2001, - 0x1837, 0x2004, 0xd0ac, 0x1904, 0xce34, 0xb8a0, 0x9082, 0x0081, - 0x1a04, 0xce34, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001, - 0xb842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x604b, - 0x0000, 0x080c, 0xb116, 0x0128, 0x2b00, 0x6012, 0x6023, 0x0001, - 0x0458, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a0, 0x6010, - 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, 0x1837, 0x2104, - 0xc085, 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, 0x6130, 0x00ee, - 0x080c, 0xbb5c, 0x0030, 0x080c, 0xbb5c, 0x080c, 0x3315, 0x080c, - 0xd65a, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x3344, 0x012e, - 0x00ee, 0x080c, 0xb1a7, 0x0005, 0x2001, 0x0002, 0x080c, 0x66fa, - 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, - 0x00de, 0x00ce, 0x0c80, 0x080c, 0x3344, 0x0804, 0xcd54, 0x00c6, - 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2058, 0xb840, - 0x9084, 0x00ff, 0x9005, 0x0904, 0xcda9, 0x8001, 0xb842, 0x6003, - 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x00de, 0x00ce, 0x0898, - 0x080c, 0xbb5c, 0x0804, 0xcd56, 0x080c, 0xbb98, 0x0804, 0xcd56, - 0x00d6, 0x2c68, 0x6104, 0x080c, 0xd5bb, 0x00de, 0x0118, 0x080c, - 0xb16c, 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, - 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c, - 0x600a, 0x2001, 0x1987, 0x2004, 0x601a, 0x602c, 0x2c08, 0x2060, - 0x6024, 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160, 0x2009, - 0x8020, 0x080c, 0x9617, 0x0005, 0x00de, 0x00ce, 0x080c, 0xbb5c, - 0x080c, 0x3315, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x3344, - 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x604b, 0x0000, - 0x012e, 0x00ee, 0x0005, 0x080c, 0xb5a8, 0x1904, 0xce00, 0x0005, - 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x0096, 0x00d6, 0x001b, - 0x00de, 0x009e, 0x0005, 0xce6b, 0xce6b, 0xce6b, 0xce6b, 0xce6b, - 0xce6b, 0xce6b, 0xce6b, 0xce6b, 0xcbf9, 0xce6b, 0xcbfe, 0xce6d, - 0xcbfe, 0xce87, 0xce6b, 0x080c, 0x0d85, 0x6004, 0x9086, 0x008b, - 0x01b0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, 0x1130, - 0x602c, 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, 0x6007, 0x008b, - 0x6003, 0x000d, 0x2009, 0x8020, 0x080c, 0x9617, 0x0005, 0x080c, - 0xd639, 0x0118, 0x080c, 0xd64c, 0x0010, 0x080c, 0xd65a, 0x080c, - 0xd10c, 0x080c, 0xcf1b, 0x0570, 0x080c, 0x3315, 0x080c, 0xcf1b, - 0x0168, 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, - 0x0000, 0xa880, 0xc0ed, 0xa882, 0x080c, 0x7012, 0x2c68, 0x080c, - 0xb116, 0x0150, 0x6810, 0x6012, 0x080c, 0xd3b6, 0x00c6, 0x2d60, - 0x080c, 0xb1a7, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023, - 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x961e, 0x080c, - 0x9ab3, 0x00c8, 0x080c, 0xd639, 0x0138, 0x6034, 0x9086, 0x4000, - 0x1118, 0x080c, 0x3315, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f, - 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x3315, - 0x0868, 0x080c, 0xb1a7, 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, - 0x0d85, 0x0002, 0xcef2, 0xcef2, 0xcefa, 0xcef4, 0xcf04, 0xcef2, - 0xcef2, 0xb1a7, 0xcef2, 0xcef2, 0xcef2, 0xcef2, 0xcef2, 0xcef2, - 0xcef2, 0xcef2, 0x080c, 0x0d85, 0x080c, 0xacfc, 0x080c, 0xaee3, - 0x080c, 0xad18, 0x6114, 0x0096, 0x2148, 0xa87b, 0x0006, 0x080c, - 0x7012, 0x009e, 0x0804, 0xb16c, 0x601c, 0xd084, 0x190c, 0x1ad3, - 0x0c88, 0x9284, 0x0003, 0x1158, 0x9282, 0x1ddc, 0x0240, 0x2001, - 0x181a, 0x2004, 0x9202, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, - 0x0ce8, 0x0096, 0x0028, 0x0096, 0x0006, 0x6014, 0x2048, 0x000e, - 0x0006, 0x9984, 0xf000, 0x9086, 0xf000, 0x0110, 0x080c, 0x1104, - 0x000e, 0x009e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, - 0x2091, 0x8000, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7354, 0x7074, - 0x9302, 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xd645, 0x0180, - 0x9286, 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, 0x080c, - 0x3315, 0x080c, 0xd65a, 0x00c6, 0x080c, 0xb1a7, 0x00ce, 0x0060, - 0x080c, 0xd328, 0x0148, 0x080c, 0xd132, 0x1110, 0x080c, 0xbb5c, - 0x00c6, 0x080c, 0xb16c, 0x00ce, 0x9ce0, 0x001c, 0x7068, 0x9c02, - 0x1208, 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, - 0x00e6, 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, - 0x2061, 0x1b39, 0x6112, 0x080c, 0x3315, 0x9006, 0x0010, 0x9085, - 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0xb116, 0x01b0, 0x665e, 0x2b00, 0x6012, 0x080c, - 0x5848, 0x0118, 0x080c, 0xd04e, 0x0168, 0x080c, 0xd3b6, 0x6023, - 0x0003, 0x2009, 0x004b, 0x080c, 0xb20a, 0x9085, 0x0001, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, - 0xbaa0, 0x080c, 0xb1dd, 0x0580, 0x605f, 0x0000, 0x2b00, 0x6012, - 0x080c, 0xd3b6, 0x6023, 0x0003, 0x0016, 0x080c, 0xacfc, 0x080c, - 0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d, - 0x007e, 0x080c, 0xad18, 0x001e, 0xd184, 0x0128, 0x080c, 0xb16c, - 0x9085, 0x0001, 0x0070, 0x080c, 0x5848, 0x0128, 0xd18c, 0x1170, - 0x080c, 0xd04e, 0x0148, 0x2009, 0x004c, 0x080c, 0xb20a, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2900, 0x6016, - 0x0c90, 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, 0x00c6, - 0x0046, 0x0016, 0x080c, 0xb116, 0x2c78, 0x05a0, 0x7e5e, 0x2b00, - 0x7812, 0x7823, 0x0003, 0x0016, 0x2021, 0x0005, 0x080c, 0xd060, - 0x001e, 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148, 0x2001, - 0x1980, 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0xb16c, 0x00d0, - 0x2001, 0x197f, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xb16c, - 0x0088, 0x2f60, 0x080c, 0x5848, 0x0138, 0xd18c, 0x1118, 0x04f1, - 0x0148, 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, 0x080c, 0xb20a, - 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6, - 0x00c6, 0x0046, 0x080c, 0xb116, 0x2c78, 0x0508, 0x7e5e, 0x2b00, - 0x7812, 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, 0x0489, 0x009e, - 0x2001, 0x197e, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xb16c, - 0x0060, 0x2f60, 0x080c, 0x5848, 0x0120, 0xd18c, 0x1160, 0x0071, - 0x0130, 0x2009, 0x0052, 0x080c, 0xb20a, 0x9085, 0x0001, 0x004e, - 0x00ce, 0x00fe, 0x0005, 0x2900, 0x7816, 0x0c98, 0x00c6, 0x080c, - 0x4c41, 0x00ce, 0x1120, 0x080c, 0xb16c, 0x9006, 0x0005, 0xa867, - 0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, 0x0001, 0x0005, - 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0xacfc, 0x080c, - 0x699d, 0x0158, 0x2001, 0xd067, 0x0006, 0x900e, 0x2400, 0x080c, - 0x725e, 0x080c, 0x7012, 0x000e, 0x0807, 0x2418, 0x080c, 0x99b3, - 0xbaa0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, - 0x97ca, 0x008e, 0x080c, 0x966d, 0x2f08, 0x2648, 0x080c, 0xe75d, - 0xb93c, 0x81ff, 0x090c, 0x98a3, 0x080c, 0xad18, 0x012e, 0x007e, - 0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb116, - 0x0190, 0x660a, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0001, - 0x2900, 0x6016, 0x2009, 0x001f, 0x080c, 0xb20a, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, - 0x8000, 0x080c, 0xb1dd, 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, - 0xd3b6, 0x6023, 0x0008, 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, - 0x17ad, 0x00fe, 0x2009, 0x0021, 0x080c, 0xb20a, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, - 0x0126, 0x0016, 0x2091, 0x8000, 0x080c, 0xb116, 0x0198, 0x660a, - 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0001, 0x2900, 0x6016, - 0x001e, 0x0016, 0x080c, 0xb20a, 0x9085, 0x0001, 0x001e, 0x012e, - 0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0xb1dd, 0x0188, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, - 0x0001, 0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0xb20a, 0x9085, - 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x0044, - 0x0830, 0x2009, 0x0049, 0x0818, 0x0026, 0x00b6, 0x6210, 0x2258, - 0xba3c, 0x82ff, 0x0118, 0x8211, 0xba3e, 0x1140, 0xb8d0, 0x9005, - 0x0128, 0xb888, 0x9005, 0x1110, 0xb88b, 0x0001, 0x00be, 0x002e, - 0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, - 0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, - 0x000e, 0x0005, 0x0006, 0x0086, 0x0096, 0x6020, 0x9086, 0x0004, - 0x01a8, 0x6014, 0x904d, 0x080c, 0xcf1b, 0x0180, 0xa864, 0x9086, - 0x0139, 0x0170, 0x6020, 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002, - 0x0128, 0xa868, 0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, - 0x009e, 0x008e, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, - 0x080c, 0xb1dd, 0x0198, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, - 0x0001, 0x2900, 0x6016, 0x080c, 0x3315, 0x2009, 0x0028, 0x080c, - 0xb20a, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, - 0x9186, 0x0015, 0x11a8, 0x2011, 0x1824, 0x2204, 0x9086, 0x0074, - 0x1178, 0x00b6, 0x080c, 0xbe09, 0x00be, 0x080c, 0xc085, 0x6003, - 0x0001, 0x6007, 0x0029, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0078, - 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001, - 0x0001, 0x080c, 0xd57c, 0x080c, 0xbb5c, 0x080c, 0xb16c, 0x0005, - 0x0096, 0x6014, 0x904d, 0x090c, 0x0d85, 0xa87b, 0x0030, 0xa883, - 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x009e, 0x080c, 0xb16c, - 0x0c30, 0x0096, 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, - 0x66fa, 0x00e8, 0x9186, 0x0015, 0x1510, 0x2011, 0x1824, 0x2204, - 0x9086, 0x0014, 0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x684f, - 0x00be, 0x080c, 0xc15b, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, - 0x00be, 0x9005, 0x0160, 0x2001, 0x0006, 0x080c, 0x66fa, 0x6014, - 0x2048, 0xa868, 0xd0fc, 0x0170, 0x080c, 0xb57c, 0x0048, 0x6014, - 0x2048, 0xa868, 0xd0fc, 0x0528, 0x080c, 0xbb5c, 0x080c, 0xb16c, - 0x009e, 0x0005, 0x6014, 0x6310, 0x2358, 0x904d, 0x090c, 0x0d85, - 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, - 0x6aae, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, - 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c, - 0x08f8, 0x6014, 0x904d, 0x090c, 0x0d85, 0xa87b, 0x0030, 0xa883, - 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, - 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c, 0x0840, - 0xa878, 0x9086, 0x0005, 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad, - 0xa882, 0x0005, 0x604b, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, - 0x6007, 0x0050, 0x2009, 0x8023, 0x080c, 0x9617, 0x0005, 0x00c6, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0130, 0x0066, - 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x00ce, 0x0005, 0xcbf9, - 0xd259, 0xd259, 0xd25c, 0xeadc, 0xeaf7, 0xeafa, 0xcbf9, 0xcbf9, - 0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0x080c, - 0x0d85, 0xa001, 0xa001, 0x0005, 0x0096, 0x6014, 0x904d, 0x0118, - 0xa87c, 0xd0e4, 0x1110, 0x009e, 0x0010, 0x009e, 0x0005, 0x6010, - 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0550, 0x2001, 0x1834, - 0x2004, 0x9005, 0x1540, 0x00f6, 0x2c78, 0x080c, 0xb116, 0x0508, - 0x7810, 0x6012, 0x080c, 0xd3b6, 0x7820, 0x9086, 0x0003, 0x0128, - 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, 0x7808, 0x603e, 0x2f00, - 0x603a, 0x602e, 0x6023, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, - 0x795c, 0x615e, 0x2009, 0x8020, 0x080c, 0x9617, 0x2f60, 0x00fe, - 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1988, 0x2004, 0x604a, 0x0005, - 0x0016, 0x0096, 0x6814, 0x2048, 0x681c, 0xd0fc, 0xc0fc, 0x681e, - 0xa87c, 0x1108, 0xd0e4, 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000, - 0xa893, 0x0000, 0xa88f, 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e, - 0xa878, 0x2048, 0x080c, 0x100b, 0x6830, 0x6036, 0x908e, 0x0001, - 0x0148, 0x6803, 0x0002, 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, - 0x6032, 0x00d0, 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, - 0xc0f4, 0x9085, 0x0c00, 0x6826, 0x6814, 0x2048, 0xa8ac, 0x6938, - 0x9102, 0xa8b0, 0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, - 0x9084, 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, - 0x6910, 0x6112, 0x695c, 0x615e, 0x6023, 0x0001, 0x6007, 0x0039, - 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x009e, 0x001e, - 0x0005, 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, - 0x603c, 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, - 0x0098, 0x643a, 0x633e, 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400, - 0xacac, 0x9402, 0xa836, 0x2300, 0xabb0, 0x9303, 0xa83a, 0x003e, - 0x004e, 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, - 0xa83c, 0x603a, 0xa840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, - 0x0006, 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, - 0x01a0, 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, - 0x0038, 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, - 0x908e, 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, - 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x1982, 0x200c, - 0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x955b, 0x2001, 0x1986, - 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1984, 0x200c, - 0x8000, 0x2014, 0x2071, 0x196c, 0x711a, 0x721e, 0x2001, 0x0064, - 0x080c, 0x955b, 0x2001, 0x1987, 0x82ff, 0x1110, 0x2011, 0x0014, - 0x2202, 0x2001, 0x1988, 0x9288, 0x000a, 0x2102, 0x2001, 0x0017, - 0x080c, 0xaced, 0x2001, 0x1a90, 0x2102, 0x2001, 0x0032, 0x080c, - 0x16b9, 0x080c, 0x6bf2, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, - 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, 0x1986, 0x2003, 0x0028, - 0x2001, 0x1987, 0x2003, 0x0014, 0x2071, 0x196c, 0x701b, 0x0000, - 0x701f, 0x07d0, 0x2001, 0x1988, 0x2009, 0x001e, 0x2102, 0x2001, - 0x0017, 0x080c, 0xaced, 0x2001, 0x1a90, 0x2102, 0x2001, 0x0032, - 0x080c, 0x16b9, 0x00ee, 0x001e, 0x000e, 0x0005, 0x0096, 0x6060, - 0x904d, 0x0110, 0x080c, 0x108b, 0x009e, 0x0005, 0x0005, 0x00c6, - 0x0126, 0x2091, 0x8000, 0x080c, 0xb116, 0x0180, 0x2b08, 0x6112, - 0x0ca9, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, - 0xb20a, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, - 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1520, - 0x7090, 0x9086, 0x0018, 0x0120, 0x7090, 0x9086, 0x0014, 0x11e0, - 0x6014, 0x2048, 0xaa3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x9b83, - 0x01d8, 0x707c, 0xaa50, 0x9206, 0x1160, 0x7080, 0xaa54, 0x9206, - 0x1140, 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x900e, 0x080c, - 0x3364, 0x080c, 0xb57c, 0x0020, 0x080c, 0xbb5c, 0x080c, 0xb16c, - 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa54, 0x9206, 0x0d48, - 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb116, 0x0188, - 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0001, 0x2900, 0x6016, - 0x2009, 0x004d, 0x080c, 0xb20a, 0x9085, 0x0001, 0x012e, 0x00ce, - 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, - 0x080c, 0xb116, 0x0180, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, - 0x0001, 0x2900, 0x6016, 0x001e, 0x080c, 0xb20a, 0x9085, 0x0001, - 0x012e, 0x00ce, 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, - 0x0036, 0x0046, 0x0056, 0x0066, 0x0096, 0x00e6, 0x00f6, 0x2071, - 0x1800, 0x9186, 0x0015, 0x1568, 0x7190, 0x6014, 0x2048, 0xa814, - 0x8003, 0x9106, 0x1530, 0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003, - 0x0000, 0x6014, 0x2048, 0xa830, 0x20a8, 0x8906, 0x8006, 0x8007, - 0x9094, 0x003f, 0x22e8, 0x9084, 0xffc0, 0x9080, 0x001b, 0x20a0, - 0x2001, 0x19a1, 0x0016, 0x200c, 0x080c, 0xdca1, 0x001e, 0xa804, - 0x9005, 0x0110, 0x2048, 0x0c38, 0x6014, 0x2048, 0xa867, 0x0103, - 0x0010, 0x080c, 0xbb5c, 0x080c, 0xb16c, 0x00fe, 0x00ee, 0x009e, - 0x006e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x0096, - 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x11b8, 0x7090, - 0x9086, 0x0004, 0x1198, 0x6014, 0x2048, 0x2c78, 0x080c, 0x9b83, - 0x01a8, 0x707c, 0xaa74, 0x9206, 0x1130, 0x7080, 0xaa78, 0x9206, - 0x1110, 0x080c, 0x3315, 0x080c, 0xb57c, 0x0020, 0x080c, 0xbb5c, - 0x080c, 0xb16c, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa78, - 0x9206, 0x0d78, 0x0c80, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, - 0x9186, 0x0015, 0x1550, 0x7090, 0x9086, 0x0004, 0x1530, 0x6014, - 0x2048, 0x2c78, 0x080c, 0x9b83, 0x05f0, 0x707c, 0xaacc, 0x9206, - 0x1180, 0x7080, 0xaad0, 0x9206, 0x1160, 0x080c, 0x3315, 0x0016, - 0xa998, 0xaab0, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x57e9, 0x001e, - 0x0010, 0x080c, 0x55cc, 0x080c, 0xcf1b, 0x0508, 0xa87b, 0x0000, - 0xa883, 0x0000, 0xa897, 0x4000, 0x0080, 0x080c, 0xcf1b, 0x01b8, - 0x6014, 0x2048, 0x080c, 0x55cc, 0x1d70, 0xa87b, 0x0030, 0xa883, - 0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0x0126, 0x2091, 0x8000, - 0xa867, 0x0139, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c, 0x00fe, - 0x00ee, 0x009e, 0x0005, 0x7060, 0xaad0, 0x9206, 0x0930, 0x0888, - 0x0016, 0x0026, 0xa87c, 0xd0ac, 0x0178, 0xa938, 0xaa34, 0x2100, - 0x9205, 0x0150, 0xa890, 0x9106, 0x1118, 0xa88c, 0x9206, 0x0120, - 0xa992, 0xaa8e, 0x9085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00b6, - 0x00d6, 0x0036, 0x080c, 0xcf1b, 0x0904, 0xd578, 0x0096, 0x6314, - 0x2348, 0xa87a, 0xa982, 0x929e, 0x4000, 0x1580, 0x6310, 0x00c6, - 0x2358, 0x2009, 0x0000, 0xa868, 0xd0f4, 0x1140, 0x080c, 0x6aae, - 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xaa96, 0xa99a, - 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, - 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fd6, - 0x20a9, 0x0004, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c8, 0x9080, - 0x000a, 0x2098, 0x080c, 0x0fd6, 0x00ce, 0x0090, 0xaa96, 0x3918, - 0x9398, 0x0007, 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, 0xa89b, - 0x0004, 0xaba2, 0x6310, 0x2358, 0xb804, 0x9084, 0x00ff, 0xa89e, - 0xa868, 0xc0f4, 0xa86a, 0x080c, 0x7006, 0x6017, 0x0000, 0x009e, - 0x003e, 0x00de, 0x00be, 0x0005, 0x0026, 0x0036, 0x0046, 0x00b6, - 0x0096, 0x00f6, 0x6214, 0x2248, 0x6210, 0x2258, 0x2079, 0x0260, - 0x9096, 0x0000, 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, 0x080c, - 0x268c, 0x2118, 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, - 0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, 0x4ca1, 0x00a8, 0x9096, - 0x0001, 0x1148, 0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, 0xa8a6, - 0x783c, 0xa8aa, 0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, 0x000d, - 0x7838, 0xa8a6, 0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, 0x004e, - 0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035, - 0x0110, 0x6a38, 0x0008, 0x6a2c, 0x080c, 0xcf09, 0x01f0, 0x2260, - 0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838, - 0x9206, 0x0140, 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106, - 0x1140, 0x0020, 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910, - 0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8, - 0xa974, 0xd1cc, 0x0198, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1170, - 0xa9a8, 0x918c, 0x000f, 0x918e, 0x0001, 0x1140, 0xa87c, 0xd0ac, - 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0x0005, 0x0036, - 0x2019, 0x0001, 0x0010, 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c, - 0xcf1b, 0x01c8, 0x080c, 0xd10c, 0x6037, 0x4000, 0x6014, 0x6017, - 0x0000, 0x0096, 0x2048, 0xa87c, 0x080c, 0xd132, 0x1118, 0x080c, - 0xbb5c, 0x0040, 0xa867, 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129, - 0x080c, 0x7012, 0x009e, 0x003e, 0x0005, 0xa880, 0xd0b4, 0x0128, - 0xa87b, 0x0006, 0xc0ec, 0xa882, 0x0048, 0xd0bc, 0x0118, 0xa87b, - 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xd226, 0xa877, 0x0000, - 0x0005, 0x2001, 0x1810, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001, - 0x1810, 0x2004, 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x1810, - 0x2004, 0xd0e4, 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x00b6, - 0x2058, 0xbba0, 0x00be, 0x2021, 0x0007, 0x080c, 0x4e58, 0x004e, - 0x003e, 0x0005, 0x0c51, 0x1d81, 0x0005, 0x2001, 0x1986, 0x2004, - 0x601a, 0x0005, 0x2001, 0x1988, 0x2004, 0x604a, 0x0005, 0x080c, - 0xb16c, 0x0804, 0x9ab3, 0x611c, 0xd1fc, 0xa97c, 0x1108, 0xd1e4, - 0x0005, 0x601c, 0xd0fc, 0xa87c, 0x1108, 0xd0e4, 0x0005, 0x601c, - 0xd0fc, 0xc0fc, 0x601e, 0xa87c, 0x1108, 0xd0e4, 0x0005, 0x6044, - 0xd0fc, 0x1138, 0xd0bc, 0x01a0, 0xc0bc, 0x6046, 0x2001, 0x0002, - 0x0080, 0xd0ac, 0x1168, 0xd0dc, 0x1128, 0x908c, 0x000f, 0x9186, - 0x0005, 0x1118, 0x2001, 0x0003, 0x0020, 0x2001, 0x0001, 0x0008, - 0x6000, 0x0005, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, - 0x0d85, 0x001b, 0x006e, 0x00be, 0x0005, 0xd6b5, 0xddfe, 0xdf62, - 0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0xd6ec, 0xdfe6, 0xd6b5, - 0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0x080c, 0x0d85, 0x0066, - 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e, 0x0005, - 0xd6d0, 0xe50b, 0xd6d0, 0xd6d0, 0xd6d0, 0xd6d0, 0xd6d0, 0xd6d0, - 0xe4ba, 0xe55d, 0xd6d0, 0xec10, 0xec44, 0xec10, 0xec44, 0xd6d0, - 0x080c, 0x0d85, 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0d85, 0x6000, - 0x000a, 0x0005, 0xd6ea, 0xe1c3, 0xe28e, 0xe2b1, 0xe32d, 0xd6ea, - 0xe42a, 0xe3b5, 0xdff0, 0xe492, 0xe4a7, 0xd6ea, 0xd6ea, 0xd6ea, - 0xd6ea, 0xd6ea, 0x080c, 0x0d85, 0x91b2, 0x0053, 0x1a0c, 0x0d85, - 0x2100, 0x91b2, 0x0040, 0x1a04, 0xdb70, 0x0002, 0xd736, 0xd93e, - 0xd736, 0xd736, 0xd736, 0xd947, 0xd736, 0xd736, 0xd736, 0xd736, - 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, - 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd738, 0xd79f, 0xd7ae, - 0xd812, 0xd83d, 0xd8b6, 0xd929, 0xd736, 0xd736, 0xd94a, 0xd736, - 0xd736, 0xd95f, 0xd96c, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, - 0xda12, 0xd736, 0xd736, 0xda26, 0xd736, 0xd736, 0xd9e1, 0xd736, - 0xd736, 0xd736, 0xda3e, 0xd736, 0xd736, 0xd736, 0xdabb, 0xd736, - 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xdb38, 0x080c, 0x0d85, - 0x080c, 0x6bcf, 0x1150, 0x2001, 0x1837, 0x2004, 0xd0cc, 0x1128, - 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, 0x602f, - 0x0009, 0x6017, 0x0000, 0x0804, 0xd937, 0x080c, 0x6b6b, 0x00e6, - 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, 0x0026, - 0x2019, 0x0029, 0x080c, 0xacfc, 0x080c, 0x97b0, 0x0076, 0x903e, - 0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d, 0x007e, 0x001e, 0x080c, - 0xad18, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x6610, 0x2658, - 0x080c, 0x67c3, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1268, - 0x0016, 0x0026, 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x2c08, - 0x080c, 0xee6f, 0x002e, 0x001e, 0x1178, 0x080c, 0xe68b, 0x1904, - 0xd80a, 0x080c, 0xe627, 0x1120, 0x6007, 0x0008, 0x0804, 0xd937, - 0x6007, 0x0009, 0x0804, 0xd937, 0x080c, 0xe905, 0x0128, 0x080c, - 0xe68b, 0x0d78, 0x0804, 0xd80a, 0x6017, 0x1900, 0x0c88, 0x080c, - 0x344c, 0x1904, 0xdb6d, 0x6106, 0x080c, 0xe5c7, 0x6007, 0x0006, - 0x0804, 0xd937, 0x6007, 0x0007, 0x0804, 0xd937, 0x080c, 0xec80, - 0x1904, 0xdb6d, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x00d6, 0x6610, - 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, - 0x0001, 0x080c, 0x66e6, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, - 0x0188, 0x9686, 0x0004, 0x0170, 0xbe04, 0x96b4, 0x00ff, 0x9686, - 0x0006, 0x0140, 0x9686, 0x0004, 0x0128, 0x9686, 0x0005, 0x0110, - 0x00de, 0x0480, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9084, 0x0003, - 0x1140, 0x7034, 0x9082, 0x0014, 0x0220, 0x7030, 0x9084, 0x0003, - 0x0130, 0x00ee, 0x6017, 0x0000, 0x602f, 0x0007, 0x00b0, 0x00ee, - 0x080c, 0xe6f3, 0x1190, 0x9686, 0x0006, 0x1140, 0x0026, 0x6210, - 0x2258, 0xbaa0, 0x900e, 0x080c, 0x3364, 0x002e, 0x080c, 0x684f, - 0x6007, 0x000a, 0x00de, 0x0804, 0xd937, 0x6007, 0x000b, 0x00de, - 0x0804, 0xd937, 0x080c, 0x3315, 0x080c, 0xd65a, 0x6007, 0x0001, - 0x0804, 0xd937, 0x080c, 0xec80, 0x1904, 0xdb6d, 0x080c, 0x344c, - 0x1904, 0xdb6d, 0x2071, 0x0260, 0x7034, 0x90b4, 0x0003, 0x1948, - 0x90b2, 0x0014, 0x0a30, 0x7030, 0x9084, 0x0003, 0x1910, 0x6610, - 0x2658, 0xbe04, 0x9686, 0x0707, 0x09e8, 0x0026, 0x6210, 0x2258, - 0xbaa0, 0x900e, 0x080c, 0x3364, 0x002e, 0x6007, 0x000c, 0x2001, - 0x0001, 0x080c, 0xee4e, 0x0804, 0xd937, 0x080c, 0x6bcf, 0x1140, - 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, - 0x0804, 0xd745, 0x080c, 0x6b6b, 0x6610, 0x2658, 0xbe04, 0x9684, - 0x00ff, 0x9082, 0x0006, 0x06c8, 0x1138, 0x0026, 0x2001, 0x0006, - 0x080c, 0x6726, 0x002e, 0x0050, 0x96b4, 0xff00, 0x8637, 0x9686, - 0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xd80a, 0x080c, 0xe700, - 0x1120, 0x6007, 0x000e, 0x0804, 0xd937, 0x0046, 0x6410, 0x2458, - 0xbca0, 0x0046, 0x080c, 0x3315, 0x080c, 0xd65a, 0x004e, 0x0016, - 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, - 0x080c, 0xea8d, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, - 0x004e, 0x6007, 0x0001, 0x0804, 0xd937, 0x2001, 0x0001, 0x080c, - 0x66e6, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, - 0x1805, 0x2011, 0x0270, 0x080c, 0xc20e, 0x003e, 0x002e, 0x001e, - 0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, 0x9682, 0x0004, - 0x0a04, 0xd80a, 0x9682, 0x0007, 0x0a04, 0xd866, 0x0804, 0xd80a, - 0x6017, 0x1900, 0x6007, 0x0009, 0x0804, 0xd937, 0x080c, 0x6bcf, - 0x1140, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, - 0x1110, 0x0804, 0xd745, 0x080c, 0x6b6b, 0x6610, 0x2658, 0xbe04, - 0x9684, 0x00ff, 0x0006, 0x0016, 0x908e, 0x0001, 0x0118, 0x908e, - 0x0000, 0x1118, 0x001e, 0x000e, 0x0080, 0x001e, 0x000e, 0x9082, - 0x0006, 0x06a0, 0x0150, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, - 0x0120, 0x9686, 0x0006, 0x1904, 0xd80a, 0x080c, 0xe72e, 0x1138, - 0x080c, 0xe627, 0x1120, 0x6007, 0x0010, 0x0804, 0xd937, 0x0046, - 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x3315, 0x080c, 0xd65a, - 0x004e, 0x0016, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0148, - 0x2009, 0x0029, 0x080c, 0xea8d, 0x6010, 0x2058, 0xb800, 0xc0e5, - 0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x0448, 0x080c, 0xe905, - 0x0198, 0x0016, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0160, 0x9186, - 0x0003, 0x0148, 0x001e, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, - 0x0920, 0x0804, 0xd80a, 0x001e, 0x6017, 0x1900, 0x6007, 0x0009, - 0x0070, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xec80, 0x1904, - 0xdb6d, 0x080c, 0xdd3e, 0x1904, 0xd80a, 0x6007, 0x0012, 0x6003, - 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0005, 0x6007, 0x0001, - 0x6003, 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0cb0, 0x6007, - 0x0005, 0x0c68, 0x080c, 0xec80, 0x1904, 0xdb6d, 0x080c, 0x344c, - 0x1904, 0xdb6d, 0x080c, 0xdd3e, 0x1904, 0xd80a, 0x6007, 0x0020, - 0x6003, 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0005, 0x080c, - 0x344c, 0x1904, 0xdb6d, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, - 0x961e, 0x080c, 0x9ab3, 0x0005, 0x080c, 0xec80, 0x1904, 0xdb6d, - 0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xdd3e, 0x1904, 0xd80a, - 0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x2c08, 0x2011, 0x1820, - 0x2214, 0x703c, 0x9206, 0x11e0, 0x2011, 0x181f, 0x2214, 0x7038, - 0x9084, 0x00ff, 0x9206, 0x11a0, 0x7240, 0x080c, 0xcf09, 0x0570, - 0x2260, 0x6008, 0x9086, 0xffff, 0x0120, 0x7244, 0x6008, 0x9206, - 0x1528, 0x6020, 0x9086, 0x0007, 0x1508, 0x080c, 0xb16c, 0x04a0, - 0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, 0xcf09, 0x01b0, - 0x2260, 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, 0x0004, - 0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, - 0xea57, 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, - 0x0026, 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, 0x6007, - 0x0025, 0x0068, 0x6020, 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, - 0x0024, 0x1110, 0x080c, 0xb16c, 0x2160, 0x6007, 0x0025, 0x6003, - 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x00ee, 0x002e, 0x001e, - 0x0005, 0x2001, 0x0001, 0x080c, 0x66e6, 0x0156, 0x0016, 0x0026, - 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c, - 0xc20e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, - 0x0804, 0xd937, 0x080c, 0xbe21, 0x080c, 0x779e, 0x1190, 0x0006, - 0x0026, 0x0036, 0x080c, 0x77b8, 0x1138, 0x080c, 0x7ab6, 0x080c, - 0x619d, 0x080c, 0x76cd, 0x0010, 0x080c, 0x7772, 0x003e, 0x002e, - 0x000e, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xdd3e, - 0x1904, 0xd80a, 0x6106, 0x080c, 0xdd5a, 0x1120, 0x6007, 0x002b, - 0x0804, 0xd937, 0x6007, 0x002c, 0x0804, 0xd937, 0x080c, 0xec80, - 0x1904, 0xdb6d, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xdd3e, - 0x1904, 0xd80a, 0x6106, 0x080c, 0xdd5f, 0x1120, 0x6007, 0x002e, - 0x0804, 0xd937, 0x6007, 0x002f, 0x0804, 0xd937, 0x080c, 0x344c, - 0x1904, 0xdb6d, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x2058, 0xb904, - 0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007, - 0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xd93e, - 0x080c, 0x5844, 0xd0e4, 0x0904, 0xdab8, 0x2071, 0x026c, 0x7010, - 0x603a, 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, 0x6c0d, 0x0140, - 0x6010, 0x2058, 0xb810, 0x9106, 0x1118, 0xb814, 0x9206, 0x0510, - 0x080c, 0x6c09, 0x15b8, 0x2069, 0x1800, 0x6880, 0x9206, 0x1590, - 0x687c, 0x9106, 0x1578, 0x7210, 0x080c, 0xcf09, 0x0590, 0x080c, - 0xdc2b, 0x0578, 0x080c, 0xeb09, 0x0560, 0x622e, 0x6007, 0x0036, - 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x00ce, 0x00de, - 0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xcf09, - 0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, - 0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, 0xea57, 0x2c10, 0x2160, - 0x0140, 0x0890, 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, 0x1500, - 0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, 0x6017, 0x1700, 0x0880, - 0x6007, 0x0012, 0x0868, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x6010, - 0x2058, 0xb804, 0x9084, 0xff00, 0x8007, 0x9086, 0x0006, 0x1904, - 0xd93e, 0x00e6, 0x00d6, 0x00c6, 0x080c, 0x5844, 0xd0e4, 0x0904, - 0xdb30, 0x2069, 0x1800, 0x2071, 0x026c, 0x7008, 0x603a, 0x720c, - 0x623e, 0x9286, 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, 0x9085, - 0x0001, 0x080c, 0xea57, 0x2c10, 0x00ce, 0x05e8, 0x080c, 0xcf09, - 0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, 0x00c6, - 0x0026, 0x2260, 0x080c, 0xcadc, 0x002e, 0x00ce, 0x7118, 0x918c, - 0xff00, 0x810f, 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, 0x0118, - 0x9186, 0x0007, 0x1198, 0x9280, 0x0005, 0x2004, 0x9005, 0x0170, - 0x080c, 0xdc2b, 0x0904, 0xdab1, 0x0056, 0x7510, 0x7614, 0x080c, - 0xeb22, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, - 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, 0x8020, - 0x080c, 0x9617, 0x0c78, 0x6007, 0x003b, 0x602f, 0x0003, 0x6017, - 0x0300, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x0c10, - 0x6007, 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, 0x0804, 0xda88, - 0x00e6, 0x0026, 0x080c, 0x6bcf, 0x0550, 0x080c, 0x6b6b, 0x080c, - 0xecf1, 0x1518, 0x2071, 0x1800, 0x70dc, 0x9085, 0x0003, 0x70de, - 0x00f6, 0x2079, 0x0100, 0x72b0, 0x9284, 0x00ff, 0x707e, 0x78e6, - 0x9284, 0xff00, 0x7280, 0x9205, 0x7082, 0x78ea, 0x00fe, 0x70e7, - 0x0000, 0x080c, 0x6c0d, 0x0120, 0x2011, 0x1a0a, 0x2013, 0x07d0, - 0xd0ac, 0x1128, 0x080c, 0x30bf, 0x0010, 0x080c, 0xed25, 0x002e, - 0x00ee, 0x080c, 0xb16c, 0x0804, 0xd93d, 0x080c, 0xb16c, 0x0005, - 0x2600, 0x0002, 0xdb84, 0xdbb2, 0xdbc3, 0xdb84, 0xdb84, 0xdb86, - 0xdbd4, 0xdb84, 0xdb84, 0xdb84, 0xdba0, 0xdb84, 0xdb84, 0xdb84, - 0xdbdf, 0xdbf5, 0xdc26, 0xdb84, 0x080c, 0x0d85, 0x080c, 0xec80, - 0x1d20, 0x080c, 0x344c, 0x1d08, 0x7038, 0x6016, 0x6007, 0x0045, - 0x6003, 0x0001, 0x080c, 0x961e, 0x0005, 0x080c, 0x3315, 0x080c, - 0xd65a, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x961e, 0x0005, - 0x080c, 0xec80, 0x1950, 0x080c, 0x344c, 0x1938, 0x080c, 0xdd3e, - 0x1d60, 0x703c, 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, 0x080c, - 0x961e, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x2009, 0x0041, - 0x080c, 0xed2e, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x961e, - 0x080c, 0x9ab3, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x2009, - 0x0042, 0x080c, 0xed2e, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, - 0x961e, 0x080c, 0x9ab3, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d, - 0x2009, 0x0046, 0x080c, 0xed2e, 0x080c, 0xb16c, 0x0005, 0x2001, - 0x1824, 0x2004, 0x9082, 0x00e1, 0x1268, 0x080c, 0xdc48, 0x0904, - 0xdb6d, 0x6007, 0x004e, 0x6003, 0x0001, 0x080c, 0x961e, 0x080c, - 0x9ab3, 0x0005, 0x6007, 0x0012, 0x0cb0, 0x6007, 0x004f, 0x6017, - 0x0000, 0x7134, 0x918c, 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, - 0x1160, 0x7140, 0x2001, 0x19be, 0x2004, 0x9106, 0x11b0, 0x7144, - 0x2001, 0x19bf, 0x2004, 0x9106, 0x0190, 0x9186, 0x0002, 0x1168, - 0x2011, 0x0276, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, - 0x000a, 0x080c, 0xc222, 0x009e, 0x0110, 0x6017, 0x0001, 0x6003, - 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0005, 0x6007, 0x0050, - 0x703c, 0x6016, 0x0ca0, 0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6, - 0x00c6, 0x2260, 0x6010, 0x2058, 0xb8d4, 0xd084, 0x0150, 0x7128, - 0x604c, 0x9106, 0x1120, 0x712c, 0x6050, 0x9106, 0x0110, 0x9006, - 0x0010, 0x9085, 0x0001, 0x00ce, 0x00be, 0x00ee, 0x001e, 0x0005, - 0x0016, 0x0096, 0x0086, 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, - 0x8000, 0x2071, 0x1800, 0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003, - 0x0000, 0x080c, 0x1072, 0x05a0, 0x2900, 0x6016, 0x7090, 0x8004, - 0xa816, 0x908a, 0x001e, 0x02d0, 0xa833, 0x001e, 0x20a9, 0x001e, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, - 0x0016, 0x200c, 0x0471, 0x001e, 0x81ff, 0x01b8, 0x2940, 0x080c, - 0x1072, 0x01b0, 0x2900, 0xa006, 0x2100, 0x0c18, 0xa832, 0x20a8, - 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, - 0x0016, 0x200c, 0x00b1, 0x001e, 0x0000, 0x9085, 0x0001, 0x0048, - 0x2071, 0x1800, 0x7093, 0x0000, 0x6014, 0x2048, 0x080c, 0x100b, - 0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, 0x008e, 0x009e, 0x001e, - 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, 0xffff, - 0x11b0, 0x080c, 0x21f9, 0x2099, 0x026c, 0x2001, 0x0014, 0x3518, - 0x9312, 0x0108, 0x1218, 0x23a8, 0x4003, 0x0400, 0x20a8, 0x4003, - 0x22a8, 0x8108, 0x080c, 0x21f9, 0x2099, 0x0260, 0x0ca8, 0x080c, - 0x21f9, 0x2061, 0x19a1, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312, - 0x0108, 0x1218, 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, - 0x8108, 0x080c, 0x21f9, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x19a1, - 0x2019, 0x0280, 0x3300, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, - 0x0260, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, - 0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006, - 0x0016, 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x2211, - 0x20a1, 0x024c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, - 0x4003, 0x0418, 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, - 0x080c, 0x2211, 0x20a1, 0x0240, 0x0c98, 0x080c, 0x2211, 0x2061, - 0x19a4, 0x6004, 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, - 0x4003, 0x0058, 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, - 0x080c, 0x2211, 0x20a1, 0x0240, 0x0c98, 0x2061, 0x19a4, 0x2019, - 0x0260, 0x3400, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0240, - 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, - 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, 0x0066, - 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, - 0x0170, 0x9686, 0x0004, 0x0158, 0xbe04, 0x96b4, 0x00ff, 0x9686, - 0x0006, 0x0128, 0x9686, 0x0004, 0x0110, 0x9085, 0x0001, 0x006e, - 0x00be, 0x0005, 0x00d6, 0x080c, 0xddd4, 0x00de, 0x0005, 0x00d6, - 0x080c, 0xdde1, 0x1520, 0x680c, 0x908c, 0xff00, 0x6820, 0x9084, - 0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, 0xd1e4, 0x0130, 0x9006, - 0x080c, 0xee4e, 0x2009, 0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920, - 0x918c, 0x00ff, 0x6824, 0x080c, 0x268c, 0x1148, 0x2001, 0x0001, - 0x080c, 0xee4e, 0x2110, 0x900e, 0x080c, 0x3364, 0x0018, 0x9085, - 0x0001, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c, - 0xb1dd, 0x0598, 0x0016, 0x0026, 0x00c6, 0x2011, 0x0263, 0x2204, - 0x8211, 0x220c, 0x080c, 0x268c, 0x1568, 0x080c, 0x6749, 0x1550, - 0xbe12, 0xbd16, 0x00ce, 0x002e, 0x001e, 0x2b00, 0x6012, 0x080c, - 0xec80, 0x11c8, 0x080c, 0x344c, 0x11b0, 0x080c, 0xdd3e, 0x0500, - 0x2001, 0x0007, 0x080c, 0x66fa, 0x2001, 0x0007, 0x080c, 0x6726, - 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, - 0x080c, 0x961e, 0x0010, 0x080c, 0xb16c, 0x9085, 0x0001, 0x00ce, - 0x00be, 0x0005, 0x080c, 0xb16c, 0x00ce, 0x002e, 0x001e, 0x0ca8, - 0x080c, 0xb16c, 0x9006, 0x0c98, 0x2069, 0x026d, 0x6800, 0x9082, - 0x0010, 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, - 0x0005, 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, - 0x9086, 0x0800, 0x1190, 0x6904, 0x9186, 0x0018, 0x0118, 0x9186, - 0x0014, 0x1158, 0x810f, 0x6800, 0x9084, 0x00ff, 0x910d, 0x6162, - 0x908e, 0x0014, 0x0110, 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, - 0x0053, 0x1a0c, 0x0d85, 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, - 0x0040, 0x1a04, 0xdf36, 0x0402, 0x91b6, 0x0027, 0x0190, 0x9186, - 0x0015, 0x0118, 0x9186, 0x0016, 0x1140, 0x080c, 0xaf61, 0x0120, - 0x9086, 0x0002, 0x0904, 0xbba3, 0x0005, 0x91b6, 0x0014, 0x190c, - 0x0d85, 0x2001, 0x0007, 0x080c, 0x6726, 0x080c, 0x99ed, 0x080c, - 0xb1a7, 0x080c, 0x9ab3, 0x0005, 0xde6c, 0xde6e, 0xde6c, 0xde6c, - 0xde6c, 0xde6e, 0xde7b, 0xdf33, 0xdebd, 0xdf33, 0xdee1, 0xdf33, - 0xde7b, 0xdf33, 0xdf2b, 0xdf33, 0xdf2b, 0xdf33, 0xdf33, 0xde6c, - 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c, - 0xde6c, 0xde6c, 0xde6e, 0xde6c, 0xdf33, 0xde6c, 0xde6c, 0xdf33, - 0xde6c, 0xdf30, 0xdf33, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xdf33, - 0xdf33, 0xde6c, 0xdf33, 0xdf33, 0xde6c, 0xde76, 0xde6c, 0xde6c, - 0xde6c, 0xde6c, 0xdf2f, 0xdf33, 0xde6c, 0xde6c, 0xdf33, 0xdf33, - 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0x080c, 0x0d85, 0x080c, 0xd65d, - 0x6003, 0x0002, 0x080c, 0x9ab3, 0x0804, 0xdf35, 0x9006, 0x080c, - 0x66e6, 0x0804, 0xdf33, 0x080c, 0x6c09, 0x1904, 0xdf33, 0x9006, - 0x080c, 0x66e6, 0x6010, 0x2058, 0xb810, 0x9086, 0x00ff, 0x1140, - 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x00b8, - 0x6010, 0x2058, 0xb884, 0x9005, 0x0904, 0xdf33, 0x080c, 0x347d, - 0x1904, 0xdf33, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1138, - 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x2001, - 0x0002, 0x080c, 0x66fa, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x6110, 0x2158, 0x2009, - 0x0001, 0x080c, 0x89a1, 0x0804, 0xdf35, 0x6610, 0x2658, 0xbe04, - 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0148, 0x9686, 0x0004, - 0x0130, 0x080c, 0x9228, 0x2001, 0x0004, 0x080c, 0x6726, 0x080c, - 0xee9d, 0x0904, 0xdf33, 0x2001, 0x0004, 0x080c, 0x66fa, 0x6023, - 0x0001, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x961e, 0x0804, - 0xdf35, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036, - 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4e58, - 0x004e, 0x003e, 0x2001, 0x0006, 0x080c, 0xdf4f, 0x6610, 0x2658, - 0xbe04, 0x0066, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e, - 0x0180, 0x2001, 0x0006, 0x080c, 0x6726, 0x9284, 0x00ff, 0x908e, - 0x0007, 0x0118, 0x908e, 0x0004, 0x1120, 0x2001, 0x0006, 0x080c, - 0x66fa, 0x080c, 0x6c09, 0x11f8, 0x2001, 0x1837, 0x2004, 0xd0a4, - 0x01d0, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6, - 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x0804, 0xdea7, - 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0409, 0x0020, 0x0018, - 0x0010, 0x080c, 0x6726, 0x080c, 0xb16c, 0x0005, 0x2600, 0x0002, - 0xdf4a, 0xdf4a, 0xdf4a, 0xdf4a, 0xdf4a, 0xdf4c, 0xdf4a, 0xdf4c, - 0xdf4a, 0xdf4a, 0xdf4c, 0xdf4a, 0xdf4a, 0xdf4a, 0xdf4c, 0xdf4c, - 0xdf4c, 0xdf4c, 0x080c, 0x0d85, 0x080c, 0xb16c, 0x0005, 0x0016, - 0x00b6, 0x00d6, 0x6110, 0x2158, 0xb900, 0xd184, 0x0138, 0x080c, - 0x66fa, 0x9006, 0x080c, 0x66e6, 0x080c, 0x3344, 0x00de, 0x00be, - 0x001e, 0x0005, 0x6610, 0x2658, 0xb804, 0x9084, 0xff00, 0x8007, - 0x90b2, 0x000c, 0x1a0c, 0x0d85, 0x91b6, 0x0015, 0x1110, 0x003b, - 0x0028, 0x91b6, 0x0016, 0x190c, 0x0d85, 0x006b, 0x0005, 0xbc45, - 0xbc45, 0xbc45, 0xbc45, 0xdfe4, 0xbc45, 0xdfce, 0xdf8f, 0xbc45, - 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xdfe4, - 0xbc45, 0xdfce, 0xdfd5, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0x00f6, - 0x080c, 0x6c09, 0x11d8, 0x080c, 0xd645, 0x11c0, 0x6010, 0x905d, - 0x01a8, 0xb884, 0x9005, 0x0190, 0x9006, 0x080c, 0x66e6, 0x2001, - 0x0002, 0x080c, 0x66fa, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007, - 0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x00f0, 0x2011, 0x0263, - 0x2204, 0x8211, 0x220c, 0x080c, 0x268c, 0x11b0, 0x080c, 0x67b4, - 0x0118, 0x080c, 0xb16c, 0x0080, 0xb810, 0x0006, 0xb814, 0x0006, - 0xb884, 0x0006, 0x080c, 0x61b7, 0x000e, 0xb886, 0x000e, 0xb816, - 0x000e, 0xb812, 0x080c, 0xb16c, 0x00fe, 0x0005, 0x6604, 0x96b6, - 0x001e, 0x1110, 0x080c, 0xb16c, 0x0005, 0x080c, 0xc082, 0x1148, - 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, - 0x0010, 0x080c, 0xb16c, 0x0005, 0x0804, 0xb16c, 0x6004, 0x908a, - 0x0053, 0x1a0c, 0x0d85, 0x080c, 0x99ed, 0x080c, 0xb1a7, 0x0005, - 0x9182, 0x0040, 0x0002, 0xe007, 0xe007, 0xe007, 0xe007, 0xe009, - 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, - 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0x080c, - 0x0d85, 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026, - 0x6210, 0x2258, 0xb8bc, 0x9005, 0x11b0, 0x6007, 0x0044, 0x2071, - 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, 0xe070, 0x080c, 0xee42, - 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, 0x0200, - 0x080c, 0x8c44, 0x0020, 0x9026, 0x080c, 0xecc5, 0x0c30, 0x080c, - 0x1059, 0x090c, 0x0d85, 0x6003, 0x0007, 0xa867, 0x010d, 0x9006, - 0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, 0x6008, 0xa8e2, 0x6010, - 0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, 0xa876, 0xa87f, 0x0000, - 0xa883, 0x0000, 0xa887, 0x0036, 0x080c, 0x7012, 0x001e, 0x080c, - 0xee42, 0x1904, 0xe0d0, 0x9486, 0x2000, 0x1130, 0x2019, 0x0017, - 0x080c, 0xe9f9, 0x0804, 0xe0d0, 0x9486, 0x0200, 0x1120, 0x080c, - 0xe984, 0x0804, 0xe0d0, 0x9486, 0x0400, 0x0120, 0x9486, 0x1000, - 0x1904, 0xe0d0, 0x2019, 0x0002, 0x080c, 0xe9a3, 0x0804, 0xe0d0, - 0x2069, 0x1a73, 0x6a00, 0xd284, 0x0904, 0xe13a, 0x9284, 0x0300, - 0x1904, 0xe133, 0x6804, 0x9005, 0x0904, 0xe11b, 0x2d78, 0x6003, - 0x0007, 0x080c, 0x1072, 0x0904, 0xe0dc, 0x7800, 0xd08c, 0x1118, - 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, 0x2001, 0x180f, 0x2004, - 0xd084, 0x1904, 0xe13e, 0x9006, 0xa802, 0xa867, 0x0116, 0xa86a, - 0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, 0x2058, 0xb8a0, 0x7130, - 0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, 0xa9be, 0xb930, 0xa9c2, - 0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, 0x9084, 0x0003, 0x9080, - 0xe0d8, 0x2005, 0xa87e, 0x20a9, 0x000a, 0x2001, 0x0270, 0xaa5c, - 0x9290, 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, 0x0000, - 0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, 0x2001, - 0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, 0xa9ae, 0x080c, 0x7015, - 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e, 0x0005, - 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, 0x1810, 0x2004, 0xd084, - 0x0120, 0x080c, 0x1059, 0x1904, 0xe085, 0x6017, 0xf100, 0x6003, - 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9617, 0x0c00, - 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, 0x1200, 0x1198, - 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, 0xf700, 0x910d, - 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x2009, 0xa025, - 0x080c, 0x9617, 0x0828, 0x6868, 0x602e, 0x686c, 0x6032, 0x6017, - 0xf200, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, - 0x9617, 0x0804, 0xe0d0, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, - 0x2011, 0x8049, 0x080c, 0x4ca1, 0x6017, 0xf300, 0x0010, 0x6017, - 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, - 0x9617, 0x0804, 0xe0d0, 0x6017, 0xf500, 0x0c98, 0x6017, 0xf600, - 0x0804, 0xe0f0, 0x6017, 0xf200, 0x0804, 0xe0f0, 0xa867, 0x0146, - 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, 0xa87a, 0x7044, 0x9084, - 0x0003, 0x9080, 0xe0d8, 0x2005, 0xa87e, 0x2928, 0x6010, 0x2058, - 0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, 0xa88e, 0xb830, 0xa892, - 0xb834, 0xa896, 0xa883, 0x003d, 0x2009, 0x0205, 0x2104, 0x9085, - 0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, 0x0210, 0x2214, 0x9294, - 0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, 0x0d85, 0x8210, 0x821c, - 0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0029, - 0x20a0, 0x2011, 0xe1ba, 0x2041, 0x0001, 0x223d, 0x9784, 0x00ff, - 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, 0x0530, 0x8210, - 0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, 0x0260, 0x2098, 0x0c68, - 0x2950, 0x080c, 0x1072, 0x0170, 0x2900, 0xb002, 0xa867, 0x0147, - 0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, - 0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, 0x0118, 0x080c, 0x108b, - 0x0cc8, 0x080c, 0x108b, 0x0804, 0xe0dc, 0x2548, 0x8847, 0x9885, - 0x0046, 0xa866, 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, 0xea30, - 0x0804, 0xe0d0, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, 0x0008, - 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, - 0x0057, 0x1a0c, 0x0d85, 0x9082, 0x0040, 0x0a0c, 0x0d85, 0x2008, - 0x0804, 0xe246, 0x9186, 0x0051, 0x0108, 0x0040, 0x080c, 0xaf61, - 0x01e8, 0x9086, 0x0002, 0x0904, 0xe28e, 0x00c0, 0x9186, 0x0027, - 0x0180, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0150, 0x190c, - 0x0d85, 0x080c, 0xaf61, 0x0150, 0x9086, 0x0004, 0x0904, 0xe32d, - 0x0028, 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, 0xb227, - 0x0005, 0xe20d, 0xe20f, 0xe20f, 0xe236, 0xe20d, 0xe20d, 0xe20d, - 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, - 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0x080c, 0x0d85, 0x080c, - 0x99ed, 0x080c, 0x9ab3, 0x0036, 0x0096, 0x6014, 0x904d, 0x01d8, - 0x080c, 0xcf1b, 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, 0x2058, - 0xb800, 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xea30, - 0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x1987, 0x2004, - 0x601a, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x0096, 0x080c, - 0x99ed, 0x080c, 0x9ab3, 0x080c, 0xcf1b, 0x0120, 0x6014, 0x2048, - 0x080c, 0x108b, 0x080c, 0xb1a7, 0x009e, 0x0005, 0x0002, 0xe25b, - 0xe270, 0xe25d, 0xe285, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, - 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, - 0xe25b, 0xe25b, 0xe25b, 0x080c, 0x0d85, 0x0096, 0x6014, 0x2048, - 0xa87c, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, - 0xb20a, 0x0010, 0x6003, 0x0004, 0x080c, 0x9ab3, 0x009e, 0x0005, - 0x080c, 0xcf1b, 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e, - 0xd1ec, 0x1138, 0x080c, 0x8c19, 0x080c, 0xb16c, 0x080c, 0x9ab3, - 0x0005, 0x080c, 0xec89, 0x0db0, 0x0cc8, 0x6003, 0x0001, 0x6007, - 0x0041, 0x2009, 0xa022, 0x080c, 0x9617, 0x0005, 0x9182, 0x0040, - 0x0002, 0xe2a5, 0xe2a7, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, - 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, - 0xe2a5, 0xe2a5, 0xe2a8, 0xe2a5, 0xe2a5, 0x080c, 0x0d85, 0x0005, - 0x00d6, 0x080c, 0x8c19, 0x00de, 0x080c, 0xece1, 0x080c, 0xb16c, - 0x0005, 0x9182, 0x0040, 0x0002, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8, - 0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2ca, 0xe2f5, 0xe2c8, - 0xe2c8, 0xe2c8, 0xe2c8, 0xe2f5, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8, - 0x080c, 0x0d85, 0x6014, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0168, - 0x908c, 0x0003, 0x918e, 0x0002, 0x0180, 0x6144, 0xd1e4, 0x1168, - 0x2009, 0x0041, 0x009e, 0x0804, 0xe3b5, 0x6003, 0x0007, 0x601b, - 0x0000, 0x080c, 0x8c19, 0x009e, 0x0005, 0x6014, 0x2048, 0xa97c, - 0xd1ec, 0x1130, 0x080c, 0x8c19, 0x080c, 0xb16c, 0x009e, 0x0005, - 0x080c, 0xec89, 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, 0x200c, - 0xc1d4, 0x2102, 0x0036, 0x080c, 0x9a48, 0x080c, 0x9ab3, 0x6014, - 0x0096, 0x2048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, - 0x0188, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, 0xa8ac, - 0x6330, 0x931a, 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e, 0x6003, - 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xea30, 0x6018, 0x9005, - 0x1128, 0x2001, 0x1987, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000, - 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002, - 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, - 0xe346, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, - 0xe344, 0xe344, 0xe344, 0xe391, 0x080c, 0x0d85, 0x6014, 0x0096, - 0x2048, 0xa834, 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, - 0xd1bc, 0x1190, 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, 0x2009, - 0x0041, 0x009e, 0x0804, 0xe3b5, 0x6003, 0x0007, 0x601b, 0x0000, - 0x080c, 0x8c19, 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006, - 0x0046, 0xacac, 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030, 0x9420, - 0x6432, 0x602c, 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, 0x6110, - 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009, 0x180e, - 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, - 0x00e9, 0x080c, 0x8c1b, 0x009e, 0x0005, 0x6003, 0x0002, 0x009e, - 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, 0x16b0, 0x1904, 0xe346, - 0x0005, 0x6014, 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, 0x9105, - 0x1120, 0x080c, 0x16b0, 0x1904, 0xe346, 0x0005, 0xd2fc, 0x0140, - 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, 0x0010, - 0x2009, 0x0015, 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040, 0x0208, - 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, 0x0d85, - 0x6024, 0xd0dc, 0x090c, 0x0d85, 0x0005, 0xe3d9, 0xe3e5, 0xe3f1, - 0xe3fd, 0xe3d9, 0xe3d9, 0xe3d9, 0xe3d9, 0xe3e0, 0xe3db, 0xe3db, - 0xe3d9, 0xe3d9, 0xe3d9, 0xe3d9, 0xe3db, 0xe3d9, 0xe3db, 0xe3d9, - 0xe3e0, 0x080c, 0x0d85, 0x6024, 0xd0dc, 0x090c, 0x0d85, 0x0005, - 0x6014, 0x9005, 0x190c, 0x0d85, 0x0005, 0x6003, 0x0001, 0x6106, - 0x0126, 0x2091, 0x8000, 0x2009, 0xa022, 0x080c, 0x95f9, 0x012e, - 0x0005, 0x6003, 0x0004, 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, - 0xa001, 0x080c, 0x9617, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, - 0x6047, 0x0000, 0x080c, 0x1c6f, 0x0126, 0x2091, 0x8000, 0x6014, - 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0188, 0x9084, 0x0003, 0x9086, - 0x0002, 0x01a0, 0x6024, 0xd0cc, 0x1148, 0xd0c4, 0x1138, 0xa8a8, - 0x9005, 0x1120, 0x6144, 0x918d, 0xb035, 0x0018, 0x6144, 0x918d, - 0xa035, 0x009e, 0x080c, 0x965e, 0x012e, 0x0005, 0x6144, 0x918d, - 0xa032, 0x0cb8, 0x0126, 0x2091, 0x8000, 0x0036, 0x0096, 0x9182, - 0x0040, 0x0023, 0x009e, 0x003e, 0x012e, 0x0005, 0xe44a, 0xe44c, - 0xe461, 0xe47b, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, - 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, - 0xe44a, 0xe44a, 0x080c, 0x0d85, 0x6014, 0x2048, 0xa87c, 0xd0fc, - 0x0510, 0x909c, 0x0003, 0x939e, 0x0003, 0x01e8, 0x6003, 0x0001, - 0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0xa022, 0x080c, 0x9617, - 0x0480, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003, - 0x939e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x2009, 0xa001, - 0x080c, 0x9617, 0x00f0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004, - 0x080c, 0xea30, 0x00b0, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98, - 0x909c, 0x0003, 0x939e, 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106, - 0x6047, 0x0000, 0x080c, 0x1c6f, 0x6144, 0x918d, 0xa035, 0x080c, - 0x965e, 0x0005, 0x080c, 0x99ed, 0x6114, 0x81ff, 0x0158, 0x0096, - 0x2148, 0x080c, 0xeddf, 0x0036, 0x2019, 0x0029, 0x080c, 0xea30, - 0x003e, 0x009e, 0x080c, 0xb1a7, 0x080c, 0x9ab3, 0x0005, 0x080c, - 0x9a48, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xeddf, - 0x0036, 0x2019, 0x0029, 0x080c, 0xea30, 0x003e, 0x009e, 0x080c, - 0xb1a7, 0x0005, 0x9182, 0x0085, 0x0002, 0xe4cc, 0xe4ca, 0xe4ca, - 0xe4d8, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca, - 0xe4ca, 0xe4ca, 0x080c, 0x0d85, 0x6003, 0x000b, 0x6106, 0x0126, - 0x2091, 0x8000, 0x2009, 0x8020, 0x080c, 0x9617, 0x012e, 0x0005, - 0x0026, 0x00e6, 0x080c, 0xec80, 0x0118, 0x080c, 0xb16c, 0x0440, - 0x2071, 0x0260, 0x7224, 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4, - 0x0150, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011, - 0x014e, 0x080c, 0xb495, 0x7220, 0x080c, 0xe875, 0x0118, 0x6007, - 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110, - 0x6007, 0x0086, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, - 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a, - 0x0085, 0x0a0c, 0x0d85, 0x908a, 0x0092, 0x1a0c, 0x0d85, 0x9082, - 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118, - 0x080c, 0xb227, 0x0050, 0x2001, 0x0007, 0x080c, 0x6726, 0x080c, - 0x99ed, 0x080c, 0xb1a7, 0x080c, 0x9ab3, 0x0005, 0xe53b, 0xe53d, - 0xe53d, 0xe53b, 0xe53b, 0xe53b, 0xe53b, 0xe53b, 0xe53b, 0xe53b, - 0xe53b, 0xe53b, 0xe53b, 0x080c, 0x0d85, 0x080c, 0xb1a7, 0x080c, - 0x9ab3, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0d85, 0x9182, 0x0092, - 0x1a0c, 0x0d85, 0x9182, 0x0085, 0x0002, 0xe55a, 0xe55a, 0xe55a, - 0xe55c, 0xe55a, 0xe55a, 0xe55a, 0xe55a, 0xe55a, 0xe55a, 0xe55a, - 0xe55a, 0xe55a, 0x080c, 0x0d85, 0x0005, 0x9186, 0x0013, 0x0148, - 0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, 0xb227, - 0x0020, 0x080c, 0x99ed, 0x080c, 0xb1a7, 0x0005, 0x0036, 0x080c, - 0xece1, 0x604b, 0x0000, 0x2019, 0x000b, 0x0011, 0x003e, 0x0005, - 0x6010, 0x0006, 0x0059, 0x000e, 0x6012, 0x6023, 0x0006, 0x6003, - 0x0007, 0x601b, 0x0000, 0x604b, 0x0000, 0x0005, 0x0126, 0x0036, - 0x2091, 0x8000, 0x080c, 0xacfc, 0x0106, 0x0086, 0x2c40, 0x0096, - 0x904e, 0x080c, 0xa667, 0x009e, 0x008e, 0x1558, 0x0076, 0x2c38, - 0x080c, 0xa712, 0x007e, 0x1528, 0x6000, 0x9086, 0x0000, 0x0508, - 0x6020, 0x9086, 0x0007, 0x01e8, 0x0096, 0x601c, 0xd084, 0x0140, - 0x080c, 0xece1, 0x080c, 0xd65d, 0x080c, 0x1ad3, 0x6023, 0x0007, - 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0110, 0x080c, 0xea30, 0x009e, - 0x9006, 0x6046, 0x6016, 0x080c, 0xece1, 0x6023, 0x0007, 0x080c, - 0xd65d, 0x010e, 0x090c, 0xad18, 0x003e, 0x012e, 0x0005, 0x00f6, - 0x00c6, 0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, - 0x080c, 0x268c, 0x1904, 0xe621, 0x0016, 0x00c6, 0x080c, 0x67b4, - 0x1904, 0xe61f, 0x001e, 0x00c6, 0x080c, 0xd645, 0x1130, 0xb884, - 0x9005, 0x0118, 0x080c, 0x347d, 0x0148, 0x2b10, 0x2160, 0x6010, - 0x0006, 0x6212, 0x080c, 0xd64c, 0x000e, 0x6012, 0x00ce, 0x002e, - 0x0026, 0x0016, 0x080c, 0xacfc, 0x2019, 0x0029, 0x080c, 0xa7e2, - 0x080c, 0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x007e, 0x001e, - 0x0076, 0x903e, 0x080c, 0xe75d, 0x007e, 0x080c, 0xad18, 0x0026, - 0xba04, 0x9294, 0xff00, 0x8217, 0x9286, 0x0006, 0x0118, 0x9286, - 0x0004, 0x1118, 0xbaa0, 0x080c, 0x33e0, 0x002e, 0xbc84, 0x001e, - 0x080c, 0x61b7, 0xbe12, 0xbd16, 0xbc86, 0x9006, 0x0010, 0x00ce, - 0x001e, 0x015e, 0x003e, 0x00be, 0x00ce, 0x00fe, 0x0005, 0x00c6, - 0x00d6, 0x00b6, 0x0016, 0x2009, 0x1824, 0x2104, 0x9086, 0x0074, - 0x1904, 0xe680, 0x2069, 0x0260, 0x6944, 0x9182, 0x0100, 0x06e0, - 0x6940, 0x9184, 0x8000, 0x0904, 0xe67d, 0x2001, 0x197c, 0x2004, - 0x9005, 0x1140, 0x6010, 0x2058, 0xb884, 0x9005, 0x0118, 0x9184, - 0x0800, 0x0598, 0x6948, 0x918a, 0x0001, 0x0648, 0x080c, 0xee47, - 0x0118, 0x6978, 0xd1fc, 0x11b8, 0x2009, 0x0205, 0x200b, 0x0001, - 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, 0x0100, 0x02a8, 0x6940, - 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, 0x0288, 0x6950, 0x918a, - 0x0001, 0x0298, 0x00d0, 0x6017, 0x0100, 0x00a0, 0x6017, 0x0300, - 0x0088, 0x6017, 0x0500, 0x0070, 0x6017, 0x0700, 0x0058, 0x6017, - 0x0900, 0x0040, 0x6017, 0x0b00, 0x0028, 0x6017, 0x0f00, 0x0010, - 0x6017, 0x2d00, 0x9085, 0x0001, 0x0008, 0x9006, 0x001e, 0x00be, - 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00b6, 0x0026, 0x0036, 0x0156, - 0x6210, 0x2258, 0xbb04, 0x9394, 0x00ff, 0x9286, 0x0006, 0x0180, - 0x9286, 0x0004, 0x0168, 0x9394, 0xff00, 0x8217, 0x9286, 0x0006, - 0x0138, 0x9286, 0x0004, 0x0120, 0x080c, 0x67c3, 0x0804, 0xe6ec, - 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, - 0x080c, 0xc222, 0x009e, 0x15c8, 0x2011, 0x027a, 0x20a9, 0x0004, - 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e, 0x1568, - 0x0046, 0x0016, 0xbaa0, 0x2220, 0x9006, 0x2009, 0x1848, 0x210c, - 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, 0xea8d, 0xb800, 0xc0e5, - 0xb802, 0x080c, 0xacfc, 0x2019, 0x0029, 0x080c, 0x97b0, 0x0076, - 0x2039, 0x0000, 0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d, 0x007e, - 0x080c, 0xad18, 0x2001, 0x0007, 0x080c, 0x6726, 0x2001, 0x0007, - 0x080c, 0x66fa, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, - 0x00be, 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, - 0x0800, 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, - 0x00b6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, - 0x7930, 0x7834, 0x080c, 0x268c, 0x11d0, 0x080c, 0x67b4, 0x11b8, - 0x2011, 0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, - 0x080c, 0xc222, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004, - 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e, 0x015e, - 0x003e, 0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x0006, - 0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, 0x8211, - 0x220c, 0x080c, 0x268c, 0x11d0, 0x080c, 0x67b4, 0x11b8, 0x2011, - 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, - 0xc222, 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, - 0x2b48, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e, 0x015e, 0x003e, - 0x002e, 0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, 0x0086, - 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, - 0x080c, 0xad5a, 0x0106, 0x190c, 0xacfc, 0x2740, 0x2029, 0x19f4, - 0x252c, 0x2021, 0x19fb, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, - 0x7654, 0x7074, 0x81ff, 0x0150, 0x0006, 0x9186, 0x1b39, 0x000e, - 0x0128, 0x8001, 0x9602, 0x1a04, 0xe803, 0x0018, 0x9606, 0x0904, - 0xe803, 0x080c, 0x8eee, 0x0904, 0xe7fa, 0x2100, 0x9c06, 0x0904, - 0xe7fa, 0x6720, 0x9786, 0x0007, 0x0904, 0xe7fa, 0x080c, 0xeace, - 0x1904, 0xe7fa, 0x080c, 0xee65, 0x0904, 0xe7fa, 0x080c, 0xeabe, - 0x0904, 0xe7fa, 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, 0x347d, - 0x0904, 0xe845, 0x6004, 0x9086, 0x0000, 0x1904, 0xe845, 0x9786, - 0x0004, 0x0904, 0xe845, 0x2500, 0x9c06, 0x0904, 0xe7fa, 0x2400, - 0x9c06, 0x0904, 0xe7fa, 0x88ff, 0x0118, 0x605c, 0x9906, 0x15d0, - 0x0096, 0x6043, 0xffff, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, - 0x080c, 0x1ad3, 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xd132, - 0x1130, 0x080c, 0xbb5c, 0x009e, 0x080c, 0xb1a7, 0x0418, 0x6014, - 0x2048, 0x080c, 0xcf1b, 0x01d8, 0x9786, 0x0003, 0x1588, 0xa867, - 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, - 0x100b, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0xeddf, 0x0016, - 0x080c, 0xd220, 0x080c, 0x7006, 0x001e, 0x080c, 0xd10c, 0x009e, - 0x080c, 0xb1a7, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, - 0x1210, 0x0804, 0xe776, 0x010e, 0x190c, 0xad18, 0x012e, 0x002e, - 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005, - 0x9786, 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, 0x080c, 0xeddf, - 0x080c, 0xea30, 0x08e0, 0x009e, 0x08e8, 0x9786, 0x0009, 0x11f8, - 0x6000, 0x9086, 0x0004, 0x01c0, 0x6000, 0x9086, 0x0003, 0x11a0, - 0x080c, 0x9a48, 0x0096, 0x6114, 0x2148, 0x080c, 0xcf1b, 0x0118, - 0x6010, 0x080c, 0x7012, 0x009e, 0x00c6, 0x080c, 0xb16c, 0x00ce, - 0x0036, 0x080c, 0x9ab3, 0x003e, 0x009e, 0x0804, 0xe7fa, 0x9786, - 0x000a, 0x0904, 0xe7ea, 0x0804, 0xe7df, 0x81ff, 0x0904, 0xe7fa, - 0x9180, 0x0001, 0x2004, 0x9086, 0x0018, 0x0138, 0x9180, 0x0001, - 0x2004, 0x9086, 0x002d, 0x1904, 0xe7fa, 0x6000, 0x9086, 0x0002, - 0x1904, 0xe7fa, 0x080c, 0xd121, 0x0138, 0x080c, 0xd132, 0x1904, - 0xe7fa, 0x080c, 0xbb5c, 0x0038, 0x080c, 0x3344, 0x080c, 0xd132, - 0x1110, 0x080c, 0xbb5c, 0x080c, 0xb1a7, 0x0804, 0xe7fa, 0xa864, - 0x9084, 0x00ff, 0x9086, 0x0039, 0x0005, 0x00c6, 0x00e6, 0x0016, - 0x2c08, 0x2170, 0x9006, 0x080c, 0xea57, 0x001e, 0x0120, 0x6020, - 0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xe894, 0xe894, - 0xe894, 0xe894, 0xe894, 0xe894, 0xe896, 0xe894, 0xe894, 0xe894, - 0xe8bf, 0xb1a7, 0xb1a7, 0xe894, 0x9006, 0x0005, 0x0036, 0x0046, - 0x0016, 0x7010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2009, - 0x0020, 0x080c, 0xea8d, 0x001e, 0x004e, 0x2019, 0x0002, 0x080c, - 0xe586, 0x003e, 0x9085, 0x0001, 0x0005, 0x0096, 0x080c, 0xcf1b, - 0x0140, 0x6014, 0x904d, 0x080c, 0xcae9, 0x687b, 0x0005, 0x080c, - 0x7012, 0x009e, 0x080c, 0xb1a7, 0x9085, 0x0001, 0x0005, 0x0019, - 0x9085, 0x0001, 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85, - 0x000b, 0x0005, 0xe8da, 0xe8da, 0xe8f1, 0xe8e1, 0xe900, 0xe8da, - 0xe8da, 0xe8dc, 0xe8da, 0xe8da, 0xe8da, 0xe8da, 0xe8da, 0xe8da, - 0xe8da, 0xe8da, 0x080c, 0x0d85, 0x080c, 0xb1a7, 0x9085, 0x0001, - 0x0005, 0x0036, 0x00e6, 0x2071, 0x19e8, 0x704c, 0x9c06, 0x1128, - 0x2019, 0x0001, 0x080c, 0xa596, 0x0010, 0x080c, 0xa7a1, 0x00ee, - 0x003e, 0x0096, 0x00d6, 0x6014, 0x2048, 0xa87b, 0x0005, 0x080c, - 0x7012, 0x080c, 0xb1a7, 0x00de, 0x009e, 0x9085, 0x0001, 0x0005, - 0x601c, 0xd084, 0x190c, 0x1ad3, 0x0c60, 0x2001, 0x0001, 0x080c, - 0x66e6, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, - 0x1805, 0x2011, 0x0276, 0x080c, 0xc20e, 0x003e, 0x002e, 0x001e, - 0x015e, 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076, - 0x0066, 0x00b6, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, 0x1ddc, - 0x2079, 0x0001, 0x8fff, 0x0904, 0xe977, 0x2071, 0x1800, 0x7654, - 0x7074, 0x8001, 0x9602, 0x1a04, 0xe977, 0x88ff, 0x0120, 0x2800, - 0x9c06, 0x15a0, 0x2078, 0x080c, 0xeabe, 0x0580, 0x2400, 0x9c06, - 0x0568, 0x6720, 0x9786, 0x0006, 0x1548, 0x9786, 0x0007, 0x0530, - 0x88ff, 0x1150, 0xd58c, 0x1118, 0x6010, 0x9b06, 0x11f8, 0xd584, - 0x0118, 0x605c, 0x9106, 0x11d0, 0x0096, 0x601c, 0xd084, 0x0140, - 0x080c, 0xece1, 0x080c, 0xd65d, 0x080c, 0x1ad3, 0x6023, 0x0007, - 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0120, 0x0046, 0x080c, 0xea30, - 0x004e, 0x009e, 0x080c, 0xb1a7, 0x88ff, 0x1198, 0x9ce0, 0x001c, - 0x2001, 0x181a, 0x2004, 0x9c02, 0x1210, 0x0804, 0xe92a, 0x9006, - 0x012e, 0x00be, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, - 0x0005, 0x98c5, 0x0001, 0x0ca0, 0x080c, 0xacfc, 0x00b6, 0x0076, - 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, - 0x6210, 0x2258, 0x0096, 0x904e, 0x080c, 0xa667, 0x009e, 0x008e, - 0x903e, 0x080c, 0xa712, 0x080c, 0xe91b, 0x005e, 0x007e, 0x00be, - 0x080c, 0xad18, 0x0005, 0x080c, 0xacfc, 0x00b6, 0x0046, 0x0056, - 0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, - 0x0016, 0x0036, 0x080c, 0x67b4, 0x1180, 0x0056, 0x0086, 0x9046, - 0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, 0xa667, 0x009e, - 0x008e, 0x903e, 0x080c, 0xa712, 0x005e, 0x003e, 0x001e, 0x8108, - 0x1f04, 0xe9b0, 0x0036, 0x2508, 0x2029, 0x0003, 0x080c, 0xe91b, - 0x003e, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x080c, - 0xad18, 0x0005, 0x080c, 0xacfc, 0x00b6, 0x0076, 0x0056, 0x6210, - 0x2258, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096, - 0x904e, 0x080c, 0xa667, 0x009e, 0x008e, 0x903e, 0x080c, 0xa712, - 0x2c20, 0x080c, 0xe91b, 0x005e, 0x007e, 0x00be, 0x080c, 0xad18, - 0x0005, 0x080c, 0xacfc, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, - 0x0156, 0x2c20, 0x20a9, 0x0800, 0x900e, 0x0016, 0x0036, 0x080c, - 0x67b4, 0x1190, 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, - 0x080c, 0xecc5, 0x004e, 0x0096, 0x904e, 0x080c, 0xa667, 0x009e, - 0x008e, 0x903e, 0x080c, 0xa712, 0x003e, 0x001e, 0x8108, 0x1f04, - 0xea05, 0x0036, 0x2029, 0x0002, 0x080c, 0xe91b, 0x003e, 0x015e, - 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x080c, 0xad18, 0x0005, - 0x0016, 0x00f6, 0x080c, 0xcf19, 0x0198, 0xa864, 0x9084, 0x00ff, - 0x9086, 0x0046, 0x0180, 0xa800, 0x907d, 0x0138, 0xa803, 0x0000, - 0xab82, 0x080c, 0x7012, 0x2f48, 0x0cb0, 0xab82, 0x080c, 0x7012, - 0x00fe, 0x001e, 0x0005, 0xa800, 0x907d, 0x0130, 0xa803, 0x0000, - 0x080c, 0x7012, 0x2f48, 0x0cb8, 0x080c, 0x7012, 0x0c88, 0x00e6, - 0x0046, 0x0036, 0x2061, 0x1ddc, 0x9005, 0x1138, 0x2071, 0x1800, - 0x7454, 0x7074, 0x8001, 0x9402, 0x12f8, 0x2100, 0x9c06, 0x0188, - 0x6000, 0x9086, 0x0000, 0x0168, 0x6008, 0x9206, 0x1150, 0x6320, - 0x9386, 0x0009, 0x01b0, 0x6010, 0x91a0, 0x0004, 0x2424, 0x9406, - 0x0140, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1220, - 0x0c20, 0x9085, 0x0001, 0x0008, 0x9006, 0x003e, 0x004e, 0x00ee, - 0x0005, 0x631c, 0xd3c4, 0x1d68, 0x0c30, 0x0096, 0x0006, 0x080c, - 0x1059, 0x000e, 0x090c, 0x0d85, 0xaae2, 0xa867, 0x010d, 0xa88e, - 0x0026, 0x2010, 0x080c, 0xcf09, 0x2001, 0x0000, 0x0120, 0x2200, - 0x9080, 0x0017, 0x2004, 0x002e, 0xa87a, 0x9186, 0x0020, 0x0110, - 0xa8e3, 0xffff, 0xa986, 0xac76, 0xa87f, 0x0000, 0x2001, 0x198e, - 0x2004, 0xa882, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x0126, 0x2091, - 0x8000, 0x080c, 0x7012, 0x012e, 0x009e, 0x0005, 0x6700, 0x9786, - 0x0000, 0x0158, 0x9786, 0x0001, 0x0140, 0x9786, 0x000a, 0x0128, - 0x9786, 0x0009, 0x0110, 0x9085, 0x0001, 0x0005, 0x00e6, 0x6010, - 0x9075, 0x0138, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x00ee, - 0x0005, 0x9085, 0x0001, 0x0cd8, 0x0016, 0x6004, 0x908e, 0x001e, - 0x11a0, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007, - 0x0085, 0x6003, 0x000b, 0x6023, 0x0005, 0x2001, 0x1987, 0x2004, - 0x601a, 0x2009, 0x8020, 0x080c, 0x9617, 0x001e, 0x0005, 0xa001, - 0xa001, 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, - 0xd267, 0x0030, 0x080c, 0xece1, 0x080c, 0x8c19, 0x080c, 0xb16c, - 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xeb1d, - 0xeb1d, 0xeb1d, 0xeb1f, 0xeb1d, 0xeb1f, 0xeb1f, 0xeb1d, 0xeb1f, - 0xeb1d, 0xeb1d, 0xeb1d, 0xeb1d, 0xeb1d, 0x9006, 0x0005, 0x9085, - 0x0001, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, - 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb43, 0xeb36, - 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0x6007, 0x003b, - 0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, 0x8020, - 0x080c, 0x9617, 0x0005, 0x0096, 0x00c6, 0x2260, 0x080c, 0xece1, - 0x604b, 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, 0x603b, 0x0000, - 0x00ce, 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, 0xeb9c, 0x6814, - 0x9005, 0x0138, 0x2048, 0xa87c, 0xd0fc, 0x1118, 0x00de, 0x009e, - 0x08a8, 0x6007, 0x003a, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, - 0x9617, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, 0xec0c, - 0x6014, 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, 0x190c, 0x0d85, - 0x0804, 0xec0c, 0x2048, 0x080c, 0xcf1b, 0x1130, 0x0028, 0x2048, - 0xa800, 0x9005, 0x1de0, 0x2900, 0x2048, 0xa87c, 0x9084, 0x0003, - 0x9086, 0x0002, 0x1168, 0xa87c, 0xc0dc, 0xc0f4, 0xa87e, 0xa880, - 0xc0fc, 0xa882, 0x2009, 0x0043, 0x080c, 0xe3b5, 0x0804, 0xec0c, - 0x2009, 0x0041, 0x0804, 0xec06, 0x9186, 0x0005, 0x15a0, 0x6814, - 0x2048, 0xa87c, 0xd0bc, 0x1120, 0x00de, 0x009e, 0x0804, 0xeb36, - 0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x0d85, 0x0804, 0xeb57, 0x6007, - 0x003a, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x00c6, - 0x2d60, 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, 0x1904, - 0xec0c, 0x6814, 0x2048, 0xa97c, 0xc1f4, 0xc1dc, 0xa97e, 0xa980, - 0xc1fc, 0xc1bc, 0xa982, 0x00f6, 0x2c78, 0x080c, 0x17ad, 0x00fe, - 0x2009, 0x0042, 0x0498, 0x0036, 0x080c, 0x1059, 0x090c, 0x0d85, - 0xa867, 0x010d, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x2d18, 0xab8e, - 0xa887, 0x0045, 0x2c00, 0xa892, 0x6038, 0xa8a2, 0x2360, 0x6024, - 0xc0dd, 0x6026, 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x2004, - 0x635c, 0xab7a, 0xa876, 0x9006, 0xa87e, 0xa882, 0xad9a, 0xae96, - 0xa89f, 0x0001, 0x080c, 0x7012, 0x2019, 0x0045, 0x6008, 0x2068, - 0x080c, 0xe578, 0x2d00, 0x600a, 0x003e, 0x0038, 0x604b, 0x0000, - 0x6003, 0x0007, 0x080c, 0xe3b5, 0x00ce, 0x00de, 0x009e, 0x0005, - 0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2, - 0x9186, 0x0027, 0x1178, 0x080c, 0x99ed, 0x0036, 0x0096, 0x6014, - 0x2048, 0x2019, 0x0004, 0x080c, 0xea30, 0x009e, 0x003e, 0x080c, - 0x9ab3, 0x0005, 0x9186, 0x0014, 0x0d70, 0x080c, 0xb227, 0x0005, - 0xec3f, 0xec3d, 0xec3d, 0xec3d, 0xec3d, 0xec3d, 0xec3f, 0xec3d, - 0xec3d, 0xec3d, 0xec3d, 0xec3d, 0xec3d, 0x080c, 0x0d85, 0x6003, - 0x000c, 0x080c, 0x9ab3, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, - 0x0085, 0x0208, 0x001a, 0x080c, 0xb227, 0x0005, 0xec5b, 0xec5b, - 0xec5b, 0xec5b, 0xec5d, 0xec7d, 0xec5b, 0xec5b, 0xec5b, 0xec5b, - 0xec5b, 0xec5b, 0xec5b, 0x080c, 0x0d85, 0x00d6, 0x2c68, 0x080c, - 0xb116, 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, - 0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, - 0x6910, 0x6112, 0x6023, 0x0004, 0x2009, 0x8020, 0x080c, 0x9617, - 0x2d60, 0x080c, 0xb16c, 0x00de, 0x0005, 0x080c, 0xb16c, 0x0005, - 0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee, - 0x0005, 0x2009, 0x1867, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, - 0x6024, 0xc0e5, 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1988, 0x2004, - 0x604a, 0x2009, 0x1867, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, - 0x1867, 0x210c, 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, - 0x00d8, 0x2001, 0x1988, 0x200c, 0x2001, 0x1986, 0x2004, 0x9100, - 0x9080, 0x000a, 0x604a, 0x6010, 0x00b6, 0x2058, 0xb8bc, 0x00be, - 0x0008, 0x2104, 0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, - 0x600f, 0x0000, 0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, - 0x615c, 0xb8bc, 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x605c, - 0x9106, 0x1138, 0x600c, 0x2072, 0x080c, 0x8c19, 0x080c, 0xb16c, - 0x0010, 0x9cf0, 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, - 0x0005, 0x00d6, 0x00b6, 0x6010, 0x2058, 0xb8bc, 0x906d, 0x0130, - 0x9c06, 0x0110, 0x680c, 0x0cd0, 0x600c, 0x680e, 0x00be, 0x00de, - 0x0005, 0x0026, 0x0036, 0x0156, 0x2011, 0x182c, 0x2204, 0x9084, - 0x00ff, 0x2019, 0x026e, 0x2334, 0x96b4, 0x00ff, 0x9636, 0x1508, - 0x8318, 0x2334, 0x2204, 0x9084, 0xff00, 0x9636, 0x11d0, 0x2011, - 0x0270, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, - 0x080c, 0xc222, 0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, 0x0004, - 0x6010, 0x0096, 0x2048, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e, - 0x1100, 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800, - 0x080c, 0x6130, 0x080c, 0x30bf, 0x00ee, 0x0005, 0x0096, 0x0026, - 0x080c, 0x1059, 0x090c, 0x0d85, 0xa85c, 0x9080, 0x001a, 0x20a0, - 0x20a9, 0x000c, 0xa860, 0x20e8, 0x9006, 0x4004, 0x9186, 0x0046, - 0x1118, 0xa867, 0x0136, 0x0038, 0xa867, 0x0138, 0x9186, 0x0041, - 0x0110, 0xa87b, 0x0001, 0x7038, 0x9084, 0xff00, 0x7240, 0x9294, - 0xff00, 0x8007, 0x9215, 0xaa9a, 0x9186, 0x0046, 0x1168, 0x7038, - 0x9084, 0x00ff, 0x723c, 0x9294, 0xff00, 0x9215, 0xaa9e, 0x723c, - 0x9294, 0x00ff, 0xaaa2, 0x0060, 0x7040, 0x9084, 0x00ff, 0x7244, - 0x9294, 0xff00, 0x9215, 0xaa9e, 0x7244, 0x9294, 0x00ff, 0xaaa2, - 0x9186, 0x0046, 0x1118, 0x9e90, 0x0012, 0x0010, 0x9e90, 0x001a, - 0x2204, 0x8007, 0xa8a6, 0x8210, 0x2204, 0x8007, 0xa8aa, 0x8210, - 0x2204, 0x8007, 0xa8ae, 0x8210, 0x2204, 0x8007, 0xa8b2, 0x8210, - 0x9186, 0x0046, 0x11b8, 0x9e90, 0x0016, 0x2204, 0x8007, 0xa8b6, - 0x8210, 0x2204, 0x8007, 0xa8ba, 0x8210, 0x2204, 0x8007, 0xa8be, - 0x8210, 0x2204, 0x8007, 0xa8c2, 0x8210, 0x2011, 0x0205, 0x2013, - 0x0001, 0x00b0, 0x9e90, 0x001e, 0x2204, 0x8007, 0xa8b6, 0x8210, - 0x2204, 0x8007, 0xa8ba, 0x2011, 0x0205, 0x2013, 0x0001, 0x2011, - 0x0260, 0x2204, 0x8007, 0xa8be, 0x8210, 0x2204, 0x8007, 0xa8c2, - 0x9186, 0x0046, 0x1118, 0x2011, 0x0262, 0x0010, 0x2011, 0x026a, - 0x0146, 0x01d6, 0x0036, 0x20a9, 0x0001, 0x2019, 0x0008, 0xa860, - 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0x2204, 0x8007, 0x4004, - 0x8210, 0x8319, 0x1dd0, 0x003e, 0x01ce, 0x013e, 0x2011, 0x0205, - 0x2013, 0x0000, 0x002e, 0x080c, 0x7012, 0x009e, 0x0005, 0x00e6, - 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0fc, 0x0108, 0x0011, - 0x00ee, 0x0005, 0xa880, 0xc0e5, 0xa882, 0x0005, 0x00e6, 0x00d6, - 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, - 0x2091, 0x8000, 0x2029, 0x19f4, 0x252c, 0x2021, 0x19fb, 0x2424, - 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7654, 0x7074, 0x9606, 0x0578, - 0x6720, 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, - 0x9c06, 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, 0xeabe, 0x01b8, - 0x080c, 0xeace, 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, - 0x080c, 0x1ad3, 0x001e, 0x080c, 0xd121, 0x1110, 0x080c, 0x3344, - 0x080c, 0xd132, 0x1110, 0x080c, 0xbb5c, 0x080c, 0xb1a7, 0x9ce0, - 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, - 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, - 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0dc, 0x0005, 0x0006, - 0x2001, 0x1837, 0x2004, 0xd09c, 0x000e, 0x0005, 0x0006, 0x0036, - 0x0046, 0x080c, 0xd645, 0x0168, 0x2019, 0xffff, 0x9005, 0x0128, - 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, 0x0004, 0x080c, - 0x4e58, 0x004e, 0x003e, 0x000e, 0x0005, 0x6004, 0x9086, 0x0001, - 0x1128, 0x080c, 0xa7e2, 0x080c, 0xb1a7, 0x9006, 0x0005, 0x00e6, - 0x00c6, 0x00b6, 0x0046, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7454, - 0x7074, 0x8001, 0x9402, 0x12d8, 0x2100, 0x9c06, 0x0168, 0x6000, - 0x9086, 0x0000, 0x0148, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1120, - 0x6004, 0x9086, 0x0002, 0x0140, 0x9ce0, 0x001c, 0x2001, 0x181a, - 0x2004, 0x9c02, 0x1220, 0x0c40, 0x9085, 0x0001, 0x0008, 0x9006, - 0x004e, 0x00be, 0x00ce, 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, - 0xd0a4, 0x0160, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0138, 0x2001, - 0x1848, 0x2004, 0xd0a4, 0x1118, 0x9085, 0x0001, 0x0005, 0x9006, - 0x0ce8, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, - 0x1840, 0xd5a4, 0x0118, 0x7004, 0x8000, 0x7006, 0xd5b4, 0x0118, - 0x7000, 0x8000, 0x7002, 0xd5ac, 0x0178, 0x2500, 0x9084, 0x0007, - 0x908e, 0x0003, 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, - 0x0118, 0x2071, 0xfff6, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, - 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xffee, - 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e05, 0x8000, 0x2077, - 0x1220, 0x8e70, 0x2e05, 0x8000, 0x2077, 0x0005, 0x00e6, 0x2071, - 0xffec, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xfff0, 0x0c69, - 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, - 0x1840, 0x7014, 0x8000, 0x7016, 0x00ee, 0x000e, 0x012e, 0x0005, - 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, - 0xaa6e -}; -#ifdef UNIQUE_FW_NAME -unsigned short fw2322ipx_length01 = 0xe719; -#else -unsigned short risc_code_length01 = 0xe719; -#endif - -/* - * - */ - -unsigned long rseqipx_code_addr01 = 0x0001c000 ; -unsigned short rseqipx_code01[] = { -0x000b, 0x0003, 0x0000, 0x0a4e, 0x0001, 0xc000, 0x0008, 0x8064, - 0x0000, 0x0010, 0x0000, 0x8066, 0x0008, 0x0101, 0x0003, 0xc007, - 0x0008, 0x80e0, 0x0008, 0xff00, 0x0000, 0x80e2, 0x0008, 0xff00, - 0x0008, 0x0162, 0x0000, 0x8066, 0x0008, 0xa101, 0x000b, 0xc00f, - 0x0008, 0x0d02, 0x0000, 0x8060, 0x0000, 0x0400, 0x000b, 0x60c6, - 0x0008, 0x80e0, 0x0000, 0x0100, 0x000b, 0x5819, 0x0003, 0x7b08, - 0x0003, 0x5241, 0x000b, 0xc813, 0x0009, 0xbac0, 0x0000, 0x008a, - 0x0003, 0x8813, 0x000a, 0x7042, 0x0003, 0x8813, 0x0000, 0x15fc, - 0x000b, 0xb013, 0x0009, 0xc4c0, 0x0000, 0x7000, 0x0001, 0xffa0, - 0x0000, 0x2000, 0x0003, 0x93cd, 0x0008, 0x808c, 0x0000, 0x0001, - 0x0007, 0x0000, 0x0007, 0x0000, 0x0000, 0x40d4, 0x000a, 0x4047, - 0x0008, 0x808c, 0x0000, 0x0002, 0x0007, 0x0000, 0x000b, 0x0832, - 0x0000, 0x4022, 0x0003, 0x0038, 0x0008, 0x4122, 0x0009, 0xeac0, - 0x0008, 0xff00, 0x0009, 0xffe0, 0x0008, 0x0500, 0x000b, 0x0bf4, - 0x0002, 0x4447, 0x0003, 0x8bf1, 0x0008, 0x0bfe, 0x0001, 0x11a0, - 0x000b, 0x13d3, 0x0001, 0x0ca0, 0x000b, 0x13d3, 0x0001, 0x9180, - 0x0000, 0x0004, 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc046, 0x0008, 0x808c, - 0x0008, 0x0000, 0x0008, 0x0060, 0x0008, 0x8062, 0x0000, 0x0004, - 0x0000, 0x8066, 0x0000, 0x0411, 0x000b, 0xc04e, 0x0000, 0x03fe, - 0x0001, 0x43e0, 0x0003, 0x8bd0, 0x0009, 0xc2c0, 0x0008, 0x00ff, - 0x0001, 0x02e0, 0x0003, 0x8bd0, 0x0001, 0x9180, 0x0008, 0x0005, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0000, 0x0019, 0x0003, 0xc05d, 0x0002, 0x0240, 0x000b, 0x0bcd, - 0x0008, 0x00fc, 0x0003, 0x33d0, 0x000a, 0x0244, 0x0003, 0x086f, - 0x0004, 0x021a, 0x0001, 0x9180, 0x0000, 0x0007, 0x0008, 0x7f62, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0002, 0x0234, 0x0008, 0x7f04, - 0x0000, 0x8066, 0x0000, 0x040a, 0x0003, 0xc06e, 0x000a, 0x0248, - 0x000b, 0x0879, 0x0001, 0x9180, 0x0008, 0x0006, 0x0008, 0x7f62, - 0x0008, 0x8002, 0x0008, 0x0003, 0x0000, 0x8066, 0x0000, 0x020a, - 0x000b, 0xc078, 0x0000, 0x112a, 0x0008, 0x002e, 0x0008, 0x022c, - 0x0002, 0x3a44, 0x0003, 0x8813, 0x0008, 0x808c, 0x0000, 0x0002, - 0x0008, 0x1760, 0x0008, 0x8062, 0x0008, 0x000f, 0x0000, 0x8066, - 0x0008, 0x0011, 0x0003, 0xc085, 0x0008, 0x01fe, 0x0009, 0x42e0, - 0x000b, 0x8bc0, 0x0000, 0x00fe, 0x0001, 0x43e0, 0x000b, 0x8bc0, - 0x0000, 0x1734, 0x0000, 0x1530, 0x0008, 0x1632, 0x0008, 0x0d2a, - 0x0001, 0x9880, 0x0008, 0x0012, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x1e0a, 0x0003, 0xc097, - 0x0008, 0x808a, 0x0008, 0x0003, 0x0000, 0x1a60, 0x0008, 0x8062, - 0x0000, 0x0002, 0x000b, 0x589d, 0x0000, 0x8066, 0x0000, 0x3679, - 0x000b, 0xc0a0, 0x000b, 0x58a1, 0x0008, 0x8054, 0x0008, 0x0011, - 0x0000, 0x8074, 0x0008, 0x1010, 0x0008, 0x1efc, 0x0003, 0x3013, - 0x0004, 0x00aa, 0x0003, 0x0013, 0x0000, 0x1c60, 0x0000, 0x1b62, - 0x0000, 0x8066, 0x0008, 0x0231, 0x0003, 0xc0ae, 0x0003, 0x58af, - 0x0008, 0x0140, 0x0000, 0x0242, 0x0002, 0x1f43, 0x0003, 0x88b9, - 0x0000, 0x0d44, 0x0008, 0x0d46, 0x0008, 0x0348, 0x0008, 0x044a, - 0x000b, 0x00bd, 0x0008, 0x0344, 0x0008, 0x0446, 0x0008, 0x0548, - 0x0000, 0x064a, 0x000a, 0x1948, 0x0003, 0x08c0, 0x0008, 0x0d4a, - 0x0003, 0x58c0, 0x0008, 0x8054, 0x0000, 0x0001, 0x0000, 0x8074, - 0x0008, 0x2020, 0x000f, 0x4000, 0x0002, 0x7043, 0x0003, 0x8816, - 0x0002, 0x7040, 0x000b, 0x8949, 0x0000, 0x4820, 0x0008, 0x0bfe, - 0x0009, 0x10a0, 0x0003, 0x1140, 0x0001, 0x0ca0, 0x0003, 0x1140, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0008, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc0d7, - 0x0001, 0x80e0, 0x0008, 0x0003, 0x000b, 0x8940, 0x0000, 0x8060, - 0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0004, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc0e2, 0x0008, 0x0060, - 0x0008, 0x8062, 0x0000, 0x0004, 0x0000, 0x8066, 0x0000, 0x0411, - 0x000b, 0xc0e8, 0x0008, 0x4afe, 0x0009, 0x03e0, 0x000b, 0x8940, - 0x0009, 0xcbc0, 0x0008, 0x00ff, 0x0001, 0x02e0, 0x000b, 0x8940, - 0x0000, 0x49b4, 0x0002, 0x4b4e, 0x000b, 0x8951, 0x0008, 0x808a, - 0x0000, 0x0004, 0x0000, 0x18fe, 0x0001, 0x10e0, 0x000b, 0x88fa, - 0x0002, 0x192f, 0x0008, 0x7f32, 0x0008, 0x15fe, 0x0001, 0x10e0, - 0x000b, 0x88ff, 0x0002, 0x162f, 0x0008, 0x7f2c, 0x0000, 0x8060, - 0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0007, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc106, 0x000a, 0x004f, - 0x000b, 0x8937, 0x000a, 0x0040, 0x000b, 0x0921, 0x0002, 0x004e, - 0x000b, 0x0921, 0x0002, 0x0030, 0x0002, 0x7f2f, 0x0000, 0x7f00, - 0x0000, 0x8066, 0x0008, 0x000a, 0x0003, 0xc112, 0x0008, 0x1010, - 0x0004, 0x0201, 0x0003, 0xb11a, 0x0004, 0x0387, 0x000c, 0x01eb, - 0x0003, 0x7816, 0x0003, 0x0013, 0x0000, 0x0806, 0x0008, 0x8010, - 0x0000, 0x001f, 0x0004, 0x0387, 0x0000, 0x0310, 0x0004, 0x0387, - 0x0003, 0x0118, 0x000a, 0x002f, 0x0000, 0x7f00, 0x0000, 0x8066, - 0x0008, 0x000a, 0x000b, 0xc125, 0x0004, 0x01c4, 0x000a, 0x0040, - 0x000b, 0x093a, 0x0004, 0x0231, 0x0000, 0x8000, 0x0000, 0x0002, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, 0x0008, 0x0006, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x000a, 0x0003, 0xc133, - 0x0000, 0x8072, 0x0000, 0x4000, 0x0003, 0x0118, 0x0008, 0x8010, - 0x0008, 0x001e, 0x0003, 0x013c, 0x0008, 0x8010, 0x0008, 0x001d, - 0x0004, 0x0387, 0x0008, 0x1010, 0x0004, 0x0387, 0x0003, 0x0016, - 0x0002, 0x4b4e, 0x0003, 0x0946, 0x0008, 0x808a, 0x0000, 0x0004, - 0x000b, 0x6146, 0x000f, 0x8000, 0x0008, 0x808a, 0x0000, 0x0004, - 0x0003, 0x0016, 0x0008, 0x808a, 0x0000, 0x0004, 0x0007, 0x0000, - 0x0007, 0x0000, 0x0008, 0x80e0, 0x0008, 0x0202, 0x000b, 0x6149, - 0x000b, 0x0014, 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, - 0x0008, 0x0011, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0009, - 0x000b, 0xc158, 0x000a, 0x004f, 0x000b, 0x89b5, 0x0000, 0x8060, - 0x0000, 0x0400, 0x0009, 0x9080, 0x0008, 0x0005, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc162, 0x0008, 0x0060, - 0x0008, 0x8062, 0x0000, 0x001f, 0x0000, 0x8066, 0x0000, 0x0209, - 0x000b, 0xc168, 0x000a, 0x014b, 0x0003, 0x09b5, 0x0008, 0x8062, - 0x0008, 0x000f, 0x0000, 0x8066, 0x0000, 0x0211, 0x0003, 0xc16f, - 0x0008, 0x01fe, 0x0001, 0x02d0, 0x000b, 0x89b5, 0x0004, 0x01cd, - 0x0003, 0x09b5, 0x0008, 0x03a0, 0x0008, 0x8004, 0x0000, 0x0002, - 0x0000, 0x8006, 0x0000, 0x0043, 0x0008, 0x4908, 0x0008, 0x808a, - 0x0000, 0x0004, 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, - 0x0008, 0x0000, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x041a, - 0x0003, 0xc184, 0x0003, 0xe185, 0x0008, 0x4908, 0x0008, 0x480a, - 0x0008, 0x808a, 0x0000, 0x0004, 0x0008, 0x0060, 0x0008, 0x8062, - 0x0008, 0x002b, 0x0000, 0x8066, 0x0000, 0x0411, 0x000b, 0xc18f, - 0x0008, 0x04fe, 0x0009, 0x02a0, 0x0003, 0x9196, 0x0002, 0x0500, - 0x000b, 0x09b2, 0x000b, 0x0197, 0x0000, 0x05fe, 0x0001, 0x03a0, - 0x000b, 0x11b2, 0x0000, 0x0d0c, 0x0008, 0x0d0e, 0x0008, 0x0d10, - 0x0000, 0x0d12, 0x0008, 0x0060, 0x0008, 0x8062, 0x0000, 0x000d, - 0x0000, 0x8066, 0x0008, 0x0832, 0x000b, 0xc1a2, 0x0000, 0x800a, - 0x0000, 0x8005, 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, - 0x0008, 0x0011, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0a12, - 0x0003, 0xc1ac, 0x0008, 0x5006, 0x0008, 0x100e, 0x000c, 0x01d8, - 0x0003, 0x7816, 0x0003, 0x0013, 0x0008, 0x0208, 0x0008, 0x030a, - 0x0003, 0x0199, 0x0004, 0x01c4, 0x0008, 0x808a, 0x0000, 0x0004, - 0x0008, 0x8010, 0x0008, 0x0021, 0x0004, 0x0387, 0x0008, 0x1010, - 0x0004, 0x0387, 0x0000, 0x4810, 0x0004, 0x0387, 0x0008, 0x4910, - 0x0004, 0x0387, 0x0008, 0x808a, 0x0000, 0x0004, 0x0003, 0x0016, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0002, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0xb40a, 0x000b, 0xc1cb, - 0x000f, 0x4000, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x0a62, - 0x0000, 0x8066, 0x0000, 0x0411, 0x0003, 0xc1d2, 0x0002, 0x0210, - 0x0001, 0xffc0, 0x0000, 0x0007, 0x0009, 0x03e0, 0x000f, 0x4000, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0001, 0x8380, 0x0000, 0x0002, - 0x0009, 0x0a80, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0000, 0x0e0a, - 0x000b, 0xc1e0, 0x0002, 0x0300, 0x0001, 0xffc0, 0x0000, 0x0007, - 0x0000, 0x7f06, 0x0002, 0x0a00, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x060a, 0x000b, 0xc1e9, 0x000f, 0x4000, 0x0000, 0x0da0, - 0x0008, 0x0da2, 0x0008, 0x0da4, 0x0009, 0x8880, 0x0000, 0x0001, - 0x0008, 0x7f62, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066, - 0x0008, 0xa012, 0x0000, 0x0da6, 0x0008, 0x0da8, 0x0000, 0x0daa, - 0x0000, 0x0dac, 0x0003, 0xc1f9, 0x0009, 0x8880, 0x0008, 0x0009, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0xa03a, 0x0003, 0xc1ff, - 0x000f, 0x4000, 0x0009, 0x8880, 0x0008, 0x0005, 0x0000, 0x8060, - 0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0009, - 0x000b, 0xc208, 0x0008, 0x0060, 0x0008, 0x8062, 0x0000, 0x000d, - 0x0000, 0x8066, 0x0008, 0x0021, 0x000b, 0xc20e, 0x0000, 0x00fe, - 0x0001, 0x01d0, 0x0003, 0x8a17, 0x0008, 0x02fe, 0x0009, 0x03d0, - 0x000b, 0x0a17, 0x0000, 0x0d06, 0x000f, 0x4000, 0x0000, 0x8006, - 0x0000, 0x0001, 0x000f, 0x4000, 0x0008, 0x0060, 0x0008, 0x8062, - 0x0008, 0x002b, 0x0000, 0x8066, 0x0008, 0xa041, 0x000b, 0xc21f, - 0x0002, 0x0243, 0x000b, 0x8a26, 0x0000, 0x54ac, 0x0000, 0x55ae, - 0x0008, 0x0da8, 0x0000, 0x0daa, 0x0000, 0x50b0, 0x0000, 0x51b2, - 0x0000, 0x0db4, 0x0008, 0x0db6, 0x0008, 0x0060, 0x0008, 0x8062, - 0x0000, 0x0007, 0x0000, 0x8066, 0x0008, 0xa452, 0x000b, 0xc22f, - 0x000f, 0x4000, 0x000a, 0x3945, 0x000b, 0x8a3b, 0x0000, 0x8072, - 0x0008, 0x4040, 0x0007, 0x0000, 0x000a, 0x3945, 0x0003, 0x8a39, - 0x000f, 0x4000, 0x0000, 0x8072, 0x0000, 0x4000, 0x0007, 0x0000, - 0x0007, 0x0000, 0x0007, 0x0000, 0x000a, 0x3945, 0x000b, 0x0a33, - 0x000b, 0x023b, 0x000a, 0x3a40, 0x0003, 0x8819, 0x0001, 0xabd0, - 0x0008, 0x0000, 0x0000, 0x7f24, 0x0003, 0x5a46, 0x0008, 0x8054, - 0x0000, 0x0002, 0x0002, 0x1242, 0x0003, 0x0a8c, 0x000a, 0x3a45, - 0x000b, 0x0a7b, 0x000a, 0x1e10, 0x0000, 0x7f3c, 0x000b, 0x0a78, - 0x0002, 0x1d00, 0x0000, 0x7f3a, 0x0000, 0x0d60, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc256, 0x0008, 0x00fc, - 0x0003, 0xb275, 0x0000, 0x1c60, 0x0008, 0x8062, 0x0000, 0x0001, - 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc25e, 0x0008, 0x00fc, - 0x000b, 0x33a9, 0x0000, 0x0038, 0x0008, 0x0060, 0x0008, 0x8062, - 0x0000, 0x0019, 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc267, - 0x0009, 0x80c0, 0x0008, 0x00ff, 0x0008, 0x7f3e, 0x0000, 0x0d60, - 0x0008, 0x0efe, 0x0001, 0x1f80, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x0009, 0x0003, 0xc271, 0x0008, 0x003a, 0x0000, 0x1dfe, - 0x000b, 0x0252, 0x0008, 0x0036, 0x0004, 0x00aa, 0x000b, 0x028c, - 0x0000, 0x8074, 0x0000, 0x2000, 0x000b, 0x028c, 0x0002, 0x3a44, - 0x000b, 0x0bd6, 0x0000, 0x8074, 0x0000, 0x1000, 0x0001, 0xadd0, - 0x0008, 0x0000, 0x0008, 0x7f0e, 0x0003, 0xb3a6, 0x0001, 0xa7d0, - 0x0008, 0x0000, 0x0000, 0x7f00, 0x0009, 0xa6d0, 0x0008, 0x0000, - 0x0009, 0x00d0, 0x0003, 0x8a9c, 0x0000, 0x8074, 0x0008, 0x4040, - 0x0003, 0x5a8c, 0x0003, 0x5241, 0x000a, 0x3a46, 0x0003, 0x8a9c, - 0x0002, 0x3a47, 0x0003, 0x0a97, 0x0008, 0x8054, 0x0000, 0x0004, - 0x0000, 0x8074, 0x0000, 0x8000, 0x0003, 0x02fc, 0x0009, 0x92c0, - 0x0000, 0x0fc8, 0x000b, 0x0813, 0x000a, 0x1246, 0x000b, 0x8ba0, - 0x0000, 0x1a60, 0x0008, 0x8062, 0x0000, 0x0002, 0x0000, 0x8066, - 0x0000, 0x367a, 0x000b, 0xc2a1, 0x0009, 0x92c0, 0x0008, 0x0780, - 0x0003, 0x8bba, 0x0002, 0x124b, 0x000b, 0x0aaa, 0x0002, 0x2e4d, - 0x0002, 0x2e4d, 0x0003, 0x0ba6, 0x000a, 0x3a46, 0x000b, 0x8aba, - 0x000b, 0x5aac, 0x0008, 0x8054, 0x0000, 0x0004, 0x000a, 0x1243, - 0x000b, 0x0afa, 0x0008, 0x8010, 0x0000, 0x000d, 0x0004, 0x0387, - 0x000a, 0x1948, 0x000b, 0x0ab7, 0x000c, 0x037c, 0x0000, 0x1810, - 0x0004, 0x0387, 0x0003, 0x02fa, 0x000a, 0x1948, 0x000b, 0x0abe, - 0x000a, 0x1243, 0x0003, 0x0ba9, 0x000a, 0x194d, 0x0003, 0x0ac2, - 0x000a, 0x1243, 0x000b, 0x0bb0, 0x0003, 0x5ac2, 0x0008, 0x8054, - 0x0000, 0x0004, 0x000a, 0x192e, 0x0008, 0x7f32, 0x000a, 0x1947, - 0x0003, 0x0af4, 0x0002, 0x194f, 0x000b, 0x0ad2, 0x000c, 0x037c, - 0x0000, 0x1810, 0x0004, 0x0201, 0x000b, 0xb2ed, 0x0004, 0x0387, - 0x000c, 0x01eb, 0x0003, 0x02fa, 0x0000, 0x1a60, 0x0008, 0x8062, - 0x0000, 0x001f, 0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc2d7, - 0x000a, 0x004c, 0x000b, 0x8af4, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0001, 0x9880, 0x0000, 0x0007, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0000, 0x320a, 0x0003, 0xc2e1, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0001, 0x9880, 0x0008, 0x0012, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x1e0a, 0x000b, 0xc2e9, 0x0000, 0x1826, 0x0000, 0x1928, - 0x0003, 0x02fa, 0x0000, 0x0806, 0x0008, 0x8010, 0x0000, 0x001f, - 0x0004, 0x0387, 0x0000, 0x0310, 0x0004, 0x0387, 0x0003, 0x02fa, - 0x000c, 0x037c, 0x0008, 0x8010, 0x0000, 0x0001, 0x0004, 0x0387, - 0x0000, 0x1810, 0x0004, 0x0387, 0x0000, 0x8074, 0x0008, 0xf000, - 0x0000, 0x0d30, 0x0002, 0x3a42, 0x0003, 0x8b02, 0x0000, 0x15fc, - 0x0003, 0xb07e, 0x0003, 0x0013, 0x0000, 0x8074, 0x0000, 0x0501, - 0x0008, 0x8010, 0x0008, 0x000c, 0x0004, 0x0387, 0x0003, 0x0013, - 0x0009, 0xbbe0, 0x0008, 0x0030, 0x000b, 0x8b1e, 0x0000, 0x18fe, - 0x0009, 0x3ce0, 0x0003, 0x0b1b, 0x0008, 0x15fe, 0x0009, 0x3ce0, - 0x0003, 0x0b1b, 0x0008, 0x13fe, 0x0009, 0x3ce0, 0x000b, 0x8b17, - 0x000c, 0x0375, 0x0008, 0x0d26, 0x000b, 0x0318, 0x0004, 0x0377, - 0x0008, 0x8076, 0x0000, 0x0040, 0x000b, 0x0372, 0x0008, 0x8076, - 0x0008, 0x0041, 0x000b, 0x0372, 0x0009, 0xbbe0, 0x0000, 0x0032, - 0x0003, 0x8b23, 0x0008, 0x3c1e, 0x000b, 0x0372, 0x0009, 0xbbe0, - 0x0000, 0x003b, 0x000b, 0x8b28, 0x0000, 0x3cdc, 0x000b, 0x0372, - 0x0009, 0xbbe0, 0x0008, 0x0035, 0x000b, 0x8b2e, 0x0000, 0x8072, - 0x0000, 0x8000, 0x000b, 0x04e5, 0x0009, 0xbbe0, 0x0008, 0x0036, - 0x000b, 0x0c06, 0x0009, 0xbbe0, 0x0000, 0x0037, 0x000b, 0x8b53, - 0x0000, 0x18fe, 0x0009, 0x3ce0, 0x000b, 0x8b1b, 0x0008, 0x8076, - 0x0000, 0x0040, 0x0000, 0x1a60, 0x0008, 0x8062, 0x0000, 0x000d, - 0x0009, 0xa6d0, 0x0008, 0x0000, 0x0008, 0x7f04, 0x0001, 0xa7d0, - 0x0008, 0x0000, 0x0000, 0x7f06, 0x0001, 0xa8d0, 0x0008, 0x0000, - 0x0008, 0x7f08, 0x0009, 0xa9d0, 0x0008, 0x0000, 0x0000, 0x7f0a, - 0x0000, 0x8066, 0x0000, 0x0422, 0x0003, 0xc34a, 0x000c, 0x037c, - 0x0008, 0x8054, 0x0000, 0x0004, 0x0000, 0x8074, 0x0008, 0xf000, - 0x0000, 0x8072, 0x0000, 0x8000, 0x0003, 0x02fc, 0x0009, 0xbbe0, - 0x0000, 0x0038, 0x000b, 0x8b65, 0x0000, 0x18fe, 0x0009, 0x3ce0, - 0x000b, 0x0b62, 0x0008, 0x15fe, 0x0009, 0x3ce0, 0x000b, 0x8b11, - 0x0004, 0x0377, 0x0008, 0x8076, 0x0000, 0x0040, 0x0000, 0x8072, - 0x0000, 0x8000, 0x0003, 0x03cd, 0x0008, 0x8076, 0x0008, 0x0042, - 0x000b, 0x0372, 0x0009, 0xbbe0, 0x0000, 0x0016, 0x000b, 0x8b72, - 0x0000, 0x8074, 0x0008, 0x0808, 0x0002, 0x3a44, 0x000b, 0x8818, - 0x0000, 0x8074, 0x0000, 0x0800, 0x0000, 0x8072, 0x0000, 0x8000, - 0x000f, 0x8000, 0x0003, 0x0013, 0x0000, 0x8072, 0x0000, 0x8000, - 0x0003, 0x0013, 0x0002, 0x1430, 0x000b, 0x0378, 0x000a, 0x3d30, - 0x0000, 0x7f00, 0x0001, 0xbc80, 0x0000, 0x0007, 0x0003, 0x0380, - 0x000a, 0x1930, 0x0000, 0x7f00, 0x0001, 0x9880, 0x0000, 0x0007, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x000a, 0x0003, 0xc385, 0x000f, 0x4000, 0x000b, 0x238a, - 0x0008, 0x0870, 0x000f, 0x4000, 0x0002, 0x7040, 0x0003, 0x0b87, - 0x000b, 0xe394, 0x0008, 0x808a, 0x0000, 0x0004, 0x0007, 0x0000, - 0x0007, 0x0000, 0x0008, 0x80e0, 0x0008, 0x0202, 0x000b, 0x638d, - 0x0008, 0x80e0, 0x0000, 0x0100, 0x000b, 0x0387, 0x0009, 0xbac0, - 0x0008, 0x0090, 0x000b, 0x0b9d, 0x0000, 0x8074, 0x0000, 0x0706, - 0x000b, 0x039f, 0x0000, 0x8074, 0x0000, 0x0703, 0x000f, 0x4000, - 0x0008, 0x8010, 0x0000, 0x0023, 0x000b, 0x03db, 0x0008, 0x8010, - 0x0000, 0x0008, 0x000b, 0x03db, 0x0008, 0x8010, 0x0008, 0x0022, - 0x000b, 0x03db, 0x000c, 0x037c, 0x0008, 0x8010, 0x0000, 0x0007, - 0x0004, 0x0387, 0x0000, 0x1810, 0x0004, 0x0387, 0x0003, 0x03e5, - 0x000c, 0x037c, 0x0008, 0x8010, 0x0008, 0x001b, 0x0004, 0x0387, - 0x0000, 0x1810, 0x0004, 0x0387, 0x0000, 0x8074, 0x0000, 0xf080, - 0x0000, 0x0d30, 0x0003, 0x0013, 0x0008, 0x8010, 0x0008, 0x0009, - 0x000b, 0x03db, 0x0008, 0x8010, 0x0008, 0x0005, 0x000b, 0x03db, - 0x000a, 0x1648, 0x0003, 0x888c, 0x0008, 0x808c, 0x0000, 0x0001, - 0x0007, 0x0000, 0x0008, 0x8010, 0x0000, 0x0004, 0x000a, 0x4143, - 0x000b, 0x088c, 0x0002, 0x3a44, 0x0003, 0x8813, 0x0008, 0x0d2a, - 0x000b, 0x03db, 0x0008, 0x8010, 0x0008, 0x0003, 0x000b, 0x03dd, - 0x0008, 0x8010, 0x0000, 0x000b, 0x000b, 0x03dd, 0x0008, 0x8010, - 0x0000, 0x0002, 0x000b, 0x03dd, 0x0002, 0x3a47, 0x000b, 0x8a8c, - 0x0008, 0x8010, 0x0008, 0x0006, 0x000b, 0x03dd, 0x0000, 0x8074, - 0x0008, 0xf000, 0x0004, 0x0387, 0x000c, 0x0397, 0x000a, 0x3a40, - 0x000b, 0x0813, 0x0008, 0x8010, 0x0008, 0x000c, 0x0004, 0x0387, - 0x0003, 0x0013, 0x0000, 0x8074, 0x0000, 0xf080, 0x0000, 0x0d30, - 0x0002, 0x2e4d, 0x0002, 0x2e4d, 0x0003, 0x0bee, 0x0008, 0x8054, - 0x0000, 0x0019, 0x0003, 0x0013, 0x0008, 0x8054, 0x0008, 0x0009, - 0x0003, 0x0013, 0x0002, 0x3a44, 0x0003, 0x8813, 0x0003, 0x03d0, - 0x0008, 0x808c, 0x0008, 0x0000, 0x0002, 0x4447, 0x0003, 0x0c1a, - 0x0001, 0xc0c0, 0x0008, 0x00ff, 0x0009, 0xffe0, 0x0008, 0x00ff, - 0x0003, 0x8bf1, 0x0001, 0xc1e0, 0x0008, 0xffff, 0x0003, 0x8bf1, - 0x0008, 0x8010, 0x0000, 0x0013, 0x0004, 0x0387, 0x0000, 0x8074, - 0x0008, 0x0202, 0x0003, 0x0013, 0x000a, 0x3a40, 0x0003, 0x8c17, - 0x0000, 0x8074, 0x0000, 0x0200, 0x0000, 0x3d00, 0x0000, 0x3cfe, - 0x0000, 0x8072, 0x0000, 0x8000, 0x0001, 0x43e0, 0x000b, 0x8c15, - 0x0000, 0x42fe, 0x0001, 0xffc0, 0x0008, 0x00ff, 0x0009, 0x00e0, - 0x000b, 0x0bf1, 0x0008, 0x0d08, 0x0003, 0x046a, 0x0000, 0x8072, - 0x0000, 0x8000, 0x0003, 0x0013, 0x000c, 0x04ee, 0x0008, 0x808c, - 0x0000, 0x0001, 0x0000, 0x04fc, 0x0003, 0x34d1, 0x0000, 0x0460, - 0x0008, 0x8062, 0x0000, 0x0001, 0x0000, 0x8066, 0x0008, 0x0009, - 0x0003, 0xc424, 0x0000, 0x0004, 0x0009, 0x80c0, 0x0008, 0x00ff, - 0x0000, 0x7f00, 0x0001, 0x80e0, 0x0000, 0x0004, 0x0003, 0x0c3e, - 0x0001, 0x80e0, 0x0008, 0x0005, 0x0003, 0x0c3e, 0x0001, 0x80e0, - 0x0008, 0x0006, 0x0003, 0x0c3e, 0x0001, 0x82c0, 0x0008, 0xff00, - 0x0008, 0x7f04, 0x0009, 0x82e0, 0x0008, 0x0600, 0x0003, 0x0c3e, - 0x0009, 0x82e0, 0x0008, 0x0500, 0x0003, 0x0c3e, 0x0009, 0x82e0, - 0x0000, 0x0400, 0x0003, 0x8cd1, 0x0009, 0xc4c0, 0x0000, 0x7000, - 0x0009, 0xffe0, 0x0000, 0x1000, 0x000b, 0x0c6a, 0x0004, 0x04df, - 0x0002, 0x3941, 0x0003, 0x0c49, 0x0000, 0x8072, 0x0000, 0x0400, - 0x0003, 0x0013, 0x0000, 0x0460, 0x0008, 0x80fe, 0x0008, 0x002b, - 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x2209, 0x000b, 0xc44f, - 0x0008, 0x11fc, 0x0003, 0x3465, 0x0001, 0x9180, 0x0000, 0x0002, - 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x0609, 0x0003, 0xc459, 0x0000, 0x42fe, 0x0001, 0xffc0, - 0x0008, 0xff00, 0x0009, 0x03e0, 0x000b, 0x8c62, 0x0000, 0x8072, - 0x0000, 0x0400, 0x000b, 0x0056, 0x0001, 0x9180, 0x0008, 0x0003, - 0x000b, 0x044c, 0x0000, 0x8072, 0x0000, 0x0400, 0x0008, 0x8010, - 0x0000, 0x0010, 0x000b, 0x04c4, 0x0004, 0x04df, 0x0002, 0x3941, - 0x0003, 0x0c70, 0x0000, 0x8072, 0x0000, 0x0400, 0x0003, 0x0013, - 0x000a, 0x6e42, 0x0003, 0x0c75, 0x000c, 0x04a9, 0x0008, 0x11fc, - 0x0003, 0xb47a, 0x0000, 0x8072, 0x0000, 0x0400, 0x0008, 0x8010, - 0x0000, 0x000e, 0x000b, 0x04c4, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0000, 0x04fc, 0x0003, 0xb48f, 0x0008, 0x808c, 0x0008, 0x0000, - 0x0001, 0x9180, 0x0008, 0x0005, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x0009, 0x000b, 0xc485, 0x0008, 0x0060, 0x0008, 0x8062, - 0x0008, 0x001b, 0x0008, 0x4304, 0x0008, 0x4206, 0x0000, 0x8066, - 0x0000, 0x0412, 0x0003, 0xc48d, 0x0003, 0x04a6, 0x0008, 0x808c, - 0x0000, 0x0001, 0x0000, 0x0460, 0x0008, 0x8062, 0x0008, 0x002b, - 0x0000, 0x8066, 0x0008, 0x0609, 0x0003, 0xc496, 0x0000, 0x8066, - 0x0008, 0x220a, 0x0003, 0xc499, 0x0000, 0x42fe, 0x0001, 0xffc0, - 0x0008, 0xff00, 0x0008, 0x7f04, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0001, 0x9180, 0x0000, 0x0002, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0008, 0x041a, 0x0003, 0xc4a5, 0x0000, 0x8072, 0x0000, 0x0400, - 0x000b, 0x0056, 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x6b62, - 0x0000, 0x8066, 0x0000, 0x0411, 0x000b, 0xc4ae, 0x0008, 0x02fe, - 0x0009, 0x03e0, 0x0003, 0x8cb4, 0x0000, 0x0d22, 0x000f, 0x4000, - 0x0009, 0x8280, 0x0000, 0x0002, 0x0001, 0x6b80, 0x0008, 0x7f62, - 0x0000, 0x8066, 0x0008, 0x2209, 0x000b, 0xc4ba, 0x000a, 0x0200, - 0x0001, 0xffc0, 0x0000, 0x0007, 0x0000, 0x7f06, 0x0008, 0x6b62, - 0x0000, 0x8066, 0x0008, 0x060a, 0x000b, 0xc4c2, 0x000f, 0x4000, - 0x0002, 0x3a44, 0x0003, 0x8813, 0x000a, 0x2f44, 0x000a, 0x2f44, - 0x0003, 0x8bd0, 0x0008, 0x808a, 0x0008, 0x0003, 0x0000, 0x8074, - 0x0000, 0xf080, 0x0003, 0x5ccd, 0x0008, 0x8054, 0x0000, 0x0019, - 0x0003, 0x0013, 0x0002, 0x3a44, 0x0003, 0x8813, 0x0008, 0x808c, - 0x0008, 0x0000, 0x0008, 0x8010, 0x0008, 0x0011, 0x0004, 0x0387, - 0x0000, 0x42fe, 0x0001, 0xffc0, 0x0008, 0x00ff, 0x0008, 0x7f10, - 0x0004, 0x0387, 0x0008, 0x4310, 0x000b, 0x03dd, 0x0002, 0x3941, - 0x000b, 0x0ce2, 0x000f, 0x4000, 0x0000, 0x8072, 0x0008, 0x0404, - 0x000f, 0x4000, 0x0008, 0x8010, 0x0008, 0x0012, 0x0004, 0x0387, - 0x000c, 0x04a9, 0x0000, 0x1110, 0x0004, 0x0387, 0x0008, 0x11fc, - 0x000b, 0xb4e8, 0x0003, 0x0013, 0x0009, 0xc2c0, 0x0008, 0x00ff, - 0x0000, 0x7f00, 0x0001, 0xc3c0, 0x0008, 0xff00, 0x0009, 0x00d0, - 0x000b, 0x0d13, 0x0000, 0x0d0a, 0x0001, 0x8580, 0x0000, 0x1000, - 0x0008, 0x7f62, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066, - 0x0000, 0x0809, 0x000b, 0xc4fd, 0x0000, 0x04fc, 0x000b, 0x350c, - 0x0000, 0x0460, 0x0008, 0x8062, 0x0000, 0x0004, 0x0000, 0x8066, - 0x0000, 0x0211, 0x000b, 0xc505, 0x0008, 0x01fe, 0x0009, 0x00e0, - 0x000b, 0x8d0c, 0x0008, 0x02fe, 0x0001, 0x43e0, 0x0003, 0x0d12, - 0x0002, 0x0500, 0x0000, 0x7f0a, 0x0009, 0xffe0, 0x0000, 0x0800, - 0x0003, 0x8cf6, 0x0008, 0x0d08, 0x000f, 0x4000, 0x0008, 0x43fe, - 0x0001, 0x3e80, 0x0000, 0x0d60, 0x0008, 0x7f62, 0x0000, 0x8066, - 0x0000, 0x0809, 0x0003, 0xc519, 0x0000, 0x8060, 0x0000, 0x0400, - 0x0001, 0x84c0, 0x0008, 0xff00, 0x0002, 0x7f70, 0x0009, 0xff80, - 0x0000, 0x1000, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0000, 0x0809, - 0x000b, 0xc524, 0x000f, 0x4000, 0xe4a8, 0xa3b9 -}; -unsigned short rseqipx_code_length01 = 0x0a4e; -/* - * - */ - -unsigned long xseqipx_code_addr01 = 0x0001e000 ; -unsigned short xseqipx_code01[] = { -0x0013, 0x0003, 0x0000, 0x1252, 0x0001, 0xe000, 0x0005, 0x0032, - 0x0000, 0x0010, 0x0015, 0x0033, 0x0010, 0xbb39, 0x000b, 0x8007, - 0x0004, 0x0113, 0x0004, 0x0125, 0x0010, 0xc000, 0x0000, 0xc001, - 0x0000, 0xc0b0, 0x0010, 0xc0b1, 0x0010, 0xc0b2, 0x0000, 0xc0b3, - 0x0010, 0xc0b4, 0x0000, 0xc0b5, 0x0000, 0xc0b6, 0x0010, 0xc0b7, - 0x0010, 0xc0b8, 0x0000, 0xc0b9, 0x0000, 0xc0ba, 0x0000, 0xc0c2, - 0x0010, 0xc0c3, 0x0000, 0xc0c4, 0x0010, 0xc0c5, 0x0010, 0xc0c6, - 0x0000, 0xc0c7, 0x0000, 0xc0c8, 0x0010, 0xc0c9, 0x0010, 0xc0ca, - 0x0000, 0xc0cb, 0x0010, 0xc0cc, 0x0000, 0xc0cd, 0x0000, 0xc0ce, - 0x0010, 0xc0cf, 0x0015, 0x0039, 0x0010, 0xff00, 0x0015, 0x003a, - 0x0010, 0xff00, 0x0005, 0x00d0, 0x0010, 0xff00, 0x0015, 0x00d1, - 0x0010, 0xff00, 0x0012, 0x3a40, 0x000b, 0x1031, 0x0002, 0x7940, - 0x001b, 0x1137, 0x0002, 0x3a42, 0x001b, 0x1035, 0x0003, 0xb035, - 0x0003, 0xa1e2, 0x0002, 0x3a41, 0x001b, 0x1039, 0x0012, 0x7941, - 0x001b, 0x1317, 0x0013, 0xe054, 0x0001, 0x0fe8, 0x0000, 0x0001, - 0x0013, 0x1054, 0x0000, 0x0cfe, 0x0013, 0x6047, 0x0002, 0x3a44, - 0x001b, 0x1047, 0x0011, 0x02e8, 0x0010, 0x0000, 0x0013, 0x13cd, - 0x0011, 0x02e8, 0x0010, 0x0005, 0x0013, 0x145f, 0x0012, 0x3a46, - 0x000b, 0x1054, 0x0011, 0x02e8, 0x0010, 0x0000, 0x0013, 0x104f, - 0x0011, 0x02e8, 0x0010, 0x0005, 0x000b, 0x1054, 0x0000, 0x12fe, - 0x0003, 0x6054, 0x0001, 0x0fe8, 0x0010, 0x0000, 0x0003, 0x1695, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0010, 0xc131, 0x0015, 0x0033, - 0x0010, 0xb211, 0x001b, 0x8059, 0x0010, 0xb2ff, 0x0001, 0xb3e0, - 0x001c, 0x10d5, 0x000b, 0xf02d, 0x0011, 0x3be8, 0x0000, 0x0010, - 0x001b, 0x1071, 0x0000, 0x0afe, 0x000b, 0x6065, 0x0000, 0x3c0b, - 0x0003, 0x006d, 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0x0a88, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x3c0a, - 0x001b, 0x806c, 0x0010, 0x3c0a, 0x0002, 0x0c00, 0x0010, 0xff0c, - 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0010, 0x0012, 0x001b, 0x1084, - 0x0010, 0x08fe, 0x000b, 0x6078, 0x0010, 0x3c09, 0x0003, 0x0080, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0888, 0x0010, 0x0003, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x3c0a, 0x000b, 0x807f, - 0x0000, 0x3c08, 0x0002, 0x0c00, 0x0010, 0xff0c, 0x0013, 0x00d2, - 0x0011, 0x3be8, 0x0000, 0x0013, 0x000b, 0x108a, 0x0000, 0x3cb0, - 0x0014, 0x00e5, 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0000, 0x0019, - 0x000b, 0x109d, 0x0010, 0x04fe, 0x001b, 0x6091, 0x0010, 0x3c05, - 0x0013, 0x0099, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0488, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x3c0a, - 0x000b, 0x8098, 0x0000, 0x3c04, 0x0002, 0x0c00, 0x0010, 0xff0c, - 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0010, 0x001b, 0x001b, 0x10a6, - 0x0010, 0xc014, 0x0000, 0xc013, 0x0000, 0xc010, 0x0015, 0x000f, - 0x0010, 0x0000, 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0000, 0x0015, - 0x001b, 0x10b2, 0x0004, 0x011c, 0x0014, 0x012e, 0x0015, 0x0039, - 0x0000, 0x8000, 0x0017, 0x8000, 0x0004, 0x0113, 0x0004, 0x0125, - 0x0014, 0x00fe, 0x0013, 0x002d, 0x0011, 0x3be8, 0x0000, 0x0016, - 0x000b, 0x10c4, 0x0001, 0x0fe8, 0x0010, 0x0000, 0x0003, 0x10be, - 0x0001, 0x0fe8, 0x0000, 0x0002, 0x0003, 0x10be, 0x0015, 0x0039, - 0x0010, 0x1010, 0x0013, 0x00d2, 0x0015, 0x0039, 0x0000, 0x5040, - 0x0015, 0x00b8, 0x0000, 0x0008, 0x0014, 0x0925, 0x0013, 0x00d2, - 0x0011, 0x3be8, 0x0010, 0x0017, 0x001b, 0x10c9, 0x0010, 0x3cc3, - 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0010, 0x0018, 0x000b, 0x10ce, - 0x0000, 0x3cc2, 0x0013, 0x00d2, 0x0005, 0x00ce, 0x0000, 0x0001, - 0x0000, 0x3bcf, 0x0014, 0x08e7, 0x0015, 0x0039, 0x0000, 0x8000, - 0x0013, 0x002d, 0x0001, 0xb288, 0x0000, 0x0002, 0x0001, 0xc180, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x80db, - 0x0002, 0xb200, 0x0011, 0xffc8, 0x0000, 0x0007, 0x0010, 0xffb2, - 0x0010, 0xc131, 0x0015, 0x0033, 0x0010, 0xb20a, 0x0001, 0xb0d0, - 0x001b, 0x80e4, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0xb088, - 0x0000, 0x0010, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb109, - 0x000b, 0x80ec, 0x0001, 0xb1e8, 0x0010, 0xffff, 0x0013, 0x10fd, - 0x0000, 0x11fe, 0x001b, 0x60f4, 0x0000, 0xb012, 0x0013, 0x00fc, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0x1188, 0x0010, 0x0003, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb00a, 0x000b, 0x80fb, - 0x0000, 0xb011, 0x0017, 0x4000, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0xbc88, 0x0000, 0x001f, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xc411, 0x000b, 0x8105, 0x0011, 0xbc88, 0x0010, 0x0018, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc609, 0x001b, 0x810b, - 0x0011, 0xbc88, 0x0000, 0x0037, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xc709, 0x000b, 0x8111, 0x0017, 0x4000, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0001, 0xbb88, 0x0000, 0x0001, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0x0269, 0x001b, 0x811a, 0x0017, 0x4000, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xbb88, 0x0000, 0x0001, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0x026a, 0x001b, 0x8123, - 0x0017, 0x4000, 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xbb88, - 0x0010, 0x000f, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x0f59, - 0x001b, 0x812c, 0x0017, 0x4000, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0001, 0xbb88, 0x0010, 0x000f, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0x0f5a, 0x000b, 0x8135, 0x0017, 0x4000, 0x0000, 0xd0ff, - 0x0012, 0xff40, 0x000b, 0x1031, 0x0015, 0x00d1, 0x0010, 0x0101, - 0x0003, 0x913c, 0x0005, 0x0079, 0x0000, 0x0001, 0x0003, 0x913f, - 0x0015, 0x00d1, 0x0000, 0x0100, 0x0011, 0x02e8, 0x0000, 0x0002, - 0x0003, 0x1167, 0x0011, 0x02e8, 0x0000, 0x0001, 0x0003, 0x117f, - 0x0011, 0x02e8, 0x0000, 0x0004, 0x0003, 0x119d, 0x0011, 0x02e8, - 0x0010, 0x0003, 0x0003, 0x11ce, 0x0005, 0x0002, 0x0010, 0x0000, - 0x0000, 0xc00e, 0x0000, 0xc00d, 0x0010, 0xc003, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0001, 0xbd88, 0x0010, 0x0009, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0010, 0xc00a, 0x000b, 0x815a, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x815e, 0x0012, 0x3a45, - 0x0013, 0x1166, 0x0015, 0x003a, 0x0000, 0x2000, 0x0015, 0x003a, - 0x0010, 0x1010, 0x0004, 0x0911, 0x0003, 0x004f, 0x0012, 0x7849, - 0x0003, 0x11dc, 0x0010, 0x0dfe, 0x0003, 0x6150, 0x0012, 0x0c10, - 0x0010, 0xff0c, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb309, - 0x000b, 0x8174, 0x0010, 0xb3fe, 0x0013, 0x617c, 0x0010, 0xb30b, - 0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x817a, 0x0003, 0x01d1, - 0x0000, 0xc00b, 0x0010, 0xc00a, 0x0003, 0x01d1, 0x0000, 0x78b0, - 0x0012, 0xb044, 0x0003, 0x11dc, 0x0002, 0xb049, 0x0003, 0x11dc, - 0x0010, 0x71ff, 0x0012, 0xff38, 0x0010, 0xff71, 0x0010, 0x0dfe, - 0x0003, 0x614e, 0x0012, 0x0c10, 0x0010, 0xff0c, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0003, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb309, 0x001b, 0x8192, 0x0010, 0xb3fe, - 0x0003, 0x619a, 0x0000, 0xb309, 0x0015, 0x0033, 0x0010, 0xc00a, - 0x001b, 0x8198, 0x0003, 0x01d1, 0x0010, 0xc009, 0x0000, 0xc008, - 0x0003, 0x01d1, 0x0000, 0x78b0, 0x0012, 0xb044, 0x0003, 0x11dc, - 0x0002, 0xb049, 0x0003, 0x11dc, 0x0010, 0x71ff, 0x0012, 0xff38, - 0x0010, 0xff71, 0x0010, 0x0dfe, 0x0003, 0x614e, 0x0012, 0x0c10, - 0x0010, 0xff0c, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb309, - 0x001b, 0x81b0, 0x0010, 0xb3fe, 0x0003, 0x61b8, 0x0000, 0xb305, - 0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x81b6, 0x0013, 0x01ba, - 0x0010, 0xc005, 0x0000, 0xc004, 0x0002, 0x033f, 0x0002, 0xff27, - 0x0000, 0x0db8, 0x0014, 0x03c2, 0x0000, 0x0db8, 0x0014, 0x0925, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0xbc88, 0x0010, 0x0000, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb309, 0x001b, 0x81c7, - 0x0011, 0xb3e8, 0x0000, 0x0002, 0x000b, 0x114e, 0x0005, 0x0002, - 0x0010, 0x0005, 0x0003, 0x0150, 0x0012, 0x7849, 0x0003, 0x11dc, - 0x0003, 0x0150, 0x0000, 0x0db8, 0x0012, 0x0345, 0x000b, 0x11d7, - 0x0002, 0x033f, 0x0014, 0x03c2, 0x0003, 0x014e, 0x0002, 0x033f, - 0x0002, 0xff27, 0x0014, 0x03c2, 0x0014, 0x0925, 0x0003, 0x014e, - 0x0015, 0x00b8, 0x0000, 0x0001, 0x0015, 0x003a, 0x0010, 0x0101, - 0x0014, 0x0925, 0x0003, 0x015f, 0x0001, 0x2bd8, 0x0010, 0x0000, - 0x0000, 0xffba, 0x0003, 0xb1e5, 0x0005, 0x002a, 0x0000, 0x0002, - 0x0001, 0xbac8, 0x0000, 0x0700, 0x000b, 0x12d2, 0x0011, 0x15e8, - 0x0000, 0x0002, 0x0013, 0x1248, 0x0011, 0x15e8, 0x0000, 0x0001, - 0x0003, 0x11f4, 0x0005, 0x0015, 0x0010, 0x0000, 0x0003, 0x022b, - 0x0005, 0x0015, 0x0010, 0x0000, 0x0002, 0xba43, 0x0003, 0x122c, - 0x0003, 0xb1f8, 0x0005, 0x002a, 0x0000, 0x0004, 0x0012, 0xba42, - 0x0003, 0x1232, 0x0012, 0x104b, 0x000b, 0x122b, 0x0000, 0x1a30, - 0x0005, 0x0031, 0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b2a, - 0x001b, 0x8204, 0x0011, 0x20d8, 0x0010, 0x0000, 0x0000, 0xffb0, - 0x0001, 0x21d8, 0x0010, 0x0000, 0x0010, 0xffb1, 0x0001, 0x22d8, - 0x0010, 0x0000, 0x0010, 0xffb2, 0x0011, 0x23d8, 0x0010, 0x0000, - 0x0000, 0xffb3, 0x0001, 0x24d8, 0x0010, 0x0000, 0x0010, 0xffb4, - 0x0011, 0x25d8, 0x0010, 0x0000, 0x0000, 0xffb5, 0x0001, 0x28d8, - 0x0010, 0x0000, 0x0010, 0xffb8, 0x0011, 0x29d8, 0x0010, 0x0000, - 0x0000, 0xffb9, 0x0000, 0x1a30, 0x0005, 0x0031, 0x0000, 0x0007, - 0x0015, 0x0033, 0x0010, 0xb032, 0x000b, 0x8222, 0x0000, 0x1a30, - 0x0005, 0x0031, 0x0010, 0x000f, 0x0015, 0x0033, 0x0010, 0xb812, - 0x000b, 0x8228, 0x0005, 0x0015, 0x0010, 0x0000, 0x0013, 0x0035, - 0x0000, 0x1efe, 0x0013, 0x6240, 0x0014, 0x0277, 0x0000, 0x1efe, - 0x000c, 0x6277, 0x0003, 0x022b, 0x0000, 0x1a30, 0x0005, 0x0031, - 0x0000, 0x0020, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x8237, - 0x0002, 0xb02f, 0x0000, 0xffb0, 0x0005, 0x0031, 0x0000, 0x0020, - 0x0015, 0x0033, 0x0000, 0xb00a, 0x001b, 0x823e, 0x0003, 0x01ff, - 0x0015, 0x00b8, 0x0010, 0x0005, 0x0014, 0x0925, 0x0000, 0x13b8, - 0x0015, 0x003a, 0x0010, 0x0404, 0x0014, 0x0925, 0x0003, 0x022b, - 0x0005, 0x0015, 0x0000, 0x0001, 0x0012, 0xba42, 0x0013, 0x1256, - 0x0003, 0xb24c, 0x0001, 0x2bd8, 0x0010, 0x0000, 0x0012, 0xff4f, - 0x000b, 0x11e2, 0x0002, 0xba43, 0x001b, 0x1232, 0x0000, 0x1efe, - 0x000c, 0x6277, 0x0003, 0x022b, 0x0001, 0x28d8, 0x0010, 0x0000, - 0x0010, 0xffb8, 0x0011, 0x29d8, 0x0010, 0x0000, 0x0000, 0xffb9, - 0x0014, 0x02e8, 0x0002, 0x3a42, 0x000b, 0x122b, 0x0000, 0x1c30, - 0x0015, 0x00ff, 0x0000, 0x0002, 0x0002, 0x1f43, 0x001b, 0x1267, - 0x0001, 0xff88, 0x0000, 0x0002, 0x0003, 0x0269, 0x0001, 0xff88, - 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb011, - 0x000b, 0x826c, 0x0000, 0xb0ff, 0x0011, 0x16a0, 0x0000, 0xff16, - 0x001b, 0x2273, 0x0002, 0xb100, 0x0003, 0x0274, 0x0010, 0xb1ff, - 0x0001, 0x17a0, 0x0010, 0xff17, 0x0013, 0x0232, 0x0000, 0x16ff, - 0x0001, 0x18a0, 0x0010, 0xff00, 0x000b, 0x227e, 0x0002, 0x1700, - 0x0013, 0x12d1, 0x0013, 0x027f, 0x0010, 0x17ff, 0x0011, 0x19a0, - 0x0013, 0x22d1, 0x0011, 0x00d0, 0x0013, 0x12d1, 0x0000, 0x1c30, - 0x0000, 0x1b31, 0x0015, 0x0033, 0x0000, 0xb131, 0x000b, 0x8287, - 0x0013, 0xb288, 0x0000, 0xb120, 0x0010, 0xb221, 0x0002, 0x1f43, - 0x001b, 0x1294, 0x0010, 0xc022, 0x0000, 0xc023, 0x0000, 0xb324, - 0x0000, 0xb425, 0x0010, 0xb3b5, 0x0000, 0xb4b6, 0x0013, 0x0298, - 0x0000, 0xb322, 0x0000, 0xb423, 0x0000, 0xb524, 0x0010, 0xb625, - 0x0003, 0xb298, 0x0005, 0x002a, 0x0000, 0x0001, 0x0012, 0x1500, - 0x0000, 0xff15, 0x0000, 0x16ff, 0x0001, 0xb580, 0x0000, 0xff16, - 0x000b, 0x22a3, 0x0002, 0x1700, 0x0013, 0x02a4, 0x0010, 0x17ff, - 0x0001, 0xb680, 0x0010, 0xff17, 0x0012, 0x1e10, 0x0010, 0xff1e, - 0x0003, 0x62d1, 0x0002, 0x1d00, 0x0010, 0xff1d, 0x0010, 0xc030, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x82af, - 0x0010, 0xb0fe, 0x000b, 0x62d0, 0x0000, 0x1c30, 0x0005, 0x0031, - 0x0000, 0x0001, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x82b7, - 0x0010, 0xb0fe, 0x001b, 0x62bd, 0x0005, 0x00ce, 0x0010, 0x0005, - 0x0003, 0x08e7, 0x0010, 0xb01c, 0x0000, 0x1c30, 0x0005, 0x0031, - 0x0000, 0x0019, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x82c3, - 0x0001, 0xb0c8, 0x0010, 0x00ff, 0x0000, 0xff1f, 0x0010, 0xc030, - 0x0011, 0xbe80, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, - 0x000b, 0x82cc, 0x0000, 0xb01d, 0x0010, 0x1dff, 0x0013, 0x02ab, - 0x0000, 0xb01b, 0x0017, 0x4000, 0x0002, 0x3a41, 0x0003, 0x12da, - 0x0013, 0xb2d4, 0x0005, 0x002a, 0x0000, 0x0004, 0x0005, 0x0015, - 0x0010, 0x0000, 0x0003, 0x022b, 0x0000, 0x1a30, 0x0005, 0x0031, - 0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b2a, 0x001b, 0x82df, - 0x0015, 0x00b8, 0x0000, 0x0004, 0x0014, 0x0925, 0x0000, 0x13b8, - 0x0015, 0x003a, 0x0010, 0x0404, 0x0014, 0x0925, 0x0013, 0x0039, - 0x0002, 0x1e00, 0x0010, 0xff1e, 0x0012, 0x1d10, 0x0010, 0xff1d, - 0x0010, 0xc030, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, - 0x000b, 0x82f0, 0x0010, 0xb0fe, 0x001b, 0x6315, 0x0000, 0x1cff, - 0x0001, 0x1ae0, 0x0013, 0x12ff, 0x0000, 0x1c30, 0x0005, 0x0031, - 0x0010, 0x0000, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x82fb, - 0x0010, 0xb0fe, 0x001b, 0x62ff, 0x0000, 0x1aff, 0x0000, 0xff1c, - 0x0000, 0x1c30, 0x0005, 0x0031, 0x0000, 0x0019, 0x0015, 0x0033, - 0x0000, 0xb009, 0x001b, 0x8305, 0x0001, 0xb0c8, 0x0010, 0x000f, - 0x0000, 0xff1f, 0x0001, 0xbf80, 0x0010, 0xff1d, 0x0010, 0xc030, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x830f, - 0x0010, 0xb0fe, 0x001b, 0x6315, 0x0005, 0x00ce, 0x0010, 0x0006, - 0x0003, 0x08e7, 0x0000, 0xb01b, 0x0017, 0x4000, 0x0010, 0x79b0, - 0x0000, 0xd0ff, 0x0012, 0xff40, 0x001b, 0x1039, 0x0015, 0x00d1, - 0x0010, 0x0101, 0x0013, 0x931d, 0x0005, 0x0079, 0x0000, 0x0002, - 0x0003, 0x9320, 0x0015, 0x00d1, 0x0000, 0x0100, 0x0010, 0x13fe, - 0x0013, 0x6371, 0x0012, 0xb04e, 0x001b, 0x139a, 0x0000, 0x78b0, - 0x0002, 0xb045, 0x0003, 0x13a0, 0x0012, 0x784a, 0x0003, 0x13a0, - 0x0000, 0x75ff, 0x0011, 0xffc8, 0x0010, 0x1800, 0x001b, 0x13a0, - 0x0001, 0x0fe8, 0x0000, 0x0001, 0x001b, 0x133c, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x1388, 0x0000, 0x000e, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0x8f0a, 0x001b, 0x833a, 0x0013, 0x03a6, - 0x0001, 0x0fe8, 0x0000, 0x0002, 0x001b, 0x1347, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0005, 0x0031, 0x0000, 0x001a, 0x0015, 0x0033, - 0x0010, 0xc00a, 0x000b, 0x8345, 0x0013, 0x03a6, 0x0001, 0x0fe8, - 0x0010, 0x0000, 0x0003, 0x134e, 0x0005, 0x00ce, 0x0000, 0x0007, - 0x0010, 0x0fcf, 0x0003, 0x08e1, 0x0002, 0xd142, 0x0013, 0x1367, - 0x0015, 0x00d1, 0x0000, 0x0400, 0x0011, 0x13e8, 0x0001, 0x1b55, - 0x000b, 0x1367, 0x0005, 0x0031, 0x0011, 0x1b6d, 0x0015, 0x0033, - 0x0010, 0xb409, 0x001b, 0x8359, 0x0002, 0xb400, 0x0010, 0xffb4, - 0x0005, 0x0031, 0x0011, 0x1b6d, 0x0015, 0x0033, 0x0010, 0xb40a, - 0x001b, 0x8360, 0x0012, 0xd042, 0x0003, 0x1371, 0x0015, 0x00b8, - 0x0000, 0x000d, 0x0014, 0x0925, 0x0003, 0x0054, 0x0000, 0x13b8, - 0x0002, 0x1045, 0x0003, 0x136f, 0x0012, 0x103f, 0x0002, 0xff27, - 0x0014, 0x03c2, 0x0014, 0x0925, 0x0013, 0x0371, 0x0012, 0x103f, - 0x0014, 0x03c2, 0x0015, 0x000f, 0x0010, 0x0000, 0x0002, 0x3944, - 0x0013, 0x137a, 0x0015, 0x0039, 0x0000, 0x5040, 0x0015, 0x00b8, - 0x0000, 0x0008, 0x0014, 0x0925, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0001, 0xbd88, 0x0010, 0x000c, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xc00a, 0x001b, 0x8381, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xc00a, 0x000b, 0x8385, 0x0010, 0xc014, 0x0000, 0xc013, - 0x0000, 0xc010, 0x0000, 0xa4ff, 0x0003, 0x6392, 0x0011, 0xffa8, - 0x0010, 0x0005, 0x000b, 0x2392, 0x0015, 0x00d1, 0x0010, 0x0404, - 0x0015, 0x003a, 0x0000, 0x8000, 0x0002, 0x3a47, 0x0003, 0x1399, - 0x0015, 0x003a, 0x0000, 0x8000, 0x0015, 0x003a, 0x0010, 0x4040, - 0x0004, 0x08ec, 0x0013, 0x0039, 0x0015, 0x00b8, 0x0010, 0x0003, - 0x0015, 0x003a, 0x0010, 0x0202, 0x0014, 0x0925, 0x0003, 0x0389, - 0x0015, 0x00b8, 0x0000, 0x0002, 0x0015, 0x003a, 0x0010, 0x0202, - 0x0014, 0x0925, 0x0003, 0x0389, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x1388, 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb009, 0x000b, 0x83ad, 0x0011, 0x1388, 0x0010, 0x0003, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc00a, 0x000b, 0x83b3, - 0x0010, 0xb0fe, 0x0013, 0x63b8, 0x0000, 0xb012, 0x0003, 0x03ba, - 0x0010, 0xc012, 0x0010, 0xc011, 0x0012, 0x104b, 0x0003, 0x134e, - 0x0002, 0x103b, 0x0010, 0xff03, 0x0005, 0x0002, 0x0010, 0x0000, - 0x0000, 0xc00d, 0x0013, 0x034e, 0x0000, 0xffb0, 0x0010, 0xc3b1, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xb888, 0x0010, 0x0011, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb012, 0x000b, 0x83cb, - 0x0017, 0x4000, 0x0002, 0xd142, 0x001b, 0x1485, 0x0012, 0x3a43, - 0x0003, 0x13de, 0x0015, 0x003a, 0x0000, 0x0800, 0x0010, 0x0db0, - 0x0013, 0x63de, 0x0000, 0x0bff, 0x0001, 0xb0e0, 0x0003, 0x1407, - 0x0010, 0x09ff, 0x0001, 0xb0e0, 0x0003, 0x13eb, 0x0010, 0x05ff, - 0x0001, 0xb0e0, 0x0003, 0x13e2, 0x0000, 0xc00e, 0x0000, 0x05fe, - 0x0013, 0x63e8, 0x0000, 0x050d, 0x0005, 0x0002, 0x0000, 0x0004, - 0x0014, 0x046c, 0x0002, 0x3a47, 0x001b, 0x146b, 0x0013, 0x0402, - 0x0000, 0x09fe, 0x0013, 0x6404, 0x0000, 0x090d, 0x0005, 0x0002, - 0x0000, 0x0001, 0x0014, 0x049a, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xba09, 0x001b, 0x83f5, 0x0011, 0x03c8, 0x0010, 0x000f, - 0x0000, 0xffb6, 0x0011, 0xb6e8, 0x0000, 0x0001, 0x0003, 0x153f, - 0x0011, 0xb6e8, 0x0000, 0x0002, 0x0013, 0x1561, 0x0011, 0xb6e8, - 0x0010, 0x0003, 0x0003, 0x1653, 0x0004, 0x08ec, 0x0013, 0x046b, - 0x0010, 0x0bfe, 0x0013, 0x646b, 0x0010, 0x0b0d, 0x0005, 0x0002, - 0x0000, 0x0002, 0x0014, 0x049a, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xba09, 0x000b, 0x8411, 0x0000, 0xb930, 0x0005, 0x0031, - 0x0010, 0x0021, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x8417, - 0x0001, 0xb0a8, 0x0000, 0x199a, 0x0013, 0x241d, 0x0005, 0x00b0, - 0x0000, 0x1999, 0x0012, 0xb050, 0x0000, 0xffb0, 0x0002, 0xff50, - 0x0002, 0xff50, 0x0001, 0xb080, 0x0000, 0xffb0, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0006, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb00a, 0x001b, 0x842a, 0x0000, 0xb930, - 0x0005, 0x0031, 0x0000, 0x0019, 0x0015, 0x0033, 0x0000, 0xb009, - 0x000b, 0x8430, 0x0001, 0xb0c8, 0x0010, 0x00ff, 0x0001, 0xffe8, - 0x0010, 0x0048, 0x000b, 0x14a9, 0x0005, 0x0002, 0x0010, 0x0006, - 0x0012, 0x0c10, 0x0010, 0xff0c, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xb109, 0x000b, 0x8441, 0x0000, 0xb10b, 0x000b, 0x6445, - 0x0010, 0xb10a, 0x0015, 0x0033, 0x0010, 0xc00a, 0x000b, 0x8447, - 0x0002, 0x032b, 0x0010, 0xff03, 0x0011, 0x0d88, 0x0010, 0x0011, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x030a, 0x001b, 0x844f, - 0x0000, 0x11fe, 0x000b, 0x6454, 0x0000, 0x0d12, 0x0013, 0x045d, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0x1188, 0x0010, 0x0003, - 0x0000, 0xff31, 0x0010, 0x0db0, 0x0015, 0x0033, 0x0000, 0xb00a, - 0x000b, 0x845c, 0x0000, 0x0d11, 0x0013, 0x046b, 0x0002, 0xd142, - 0x0003, 0x1462, 0x0013, 0x0485, 0x0000, 0x05fe, 0x0013, 0x646b, - 0x0005, 0x0002, 0x0000, 0x0004, 0x0000, 0x050d, 0x0014, 0x046c, - 0x0002, 0x3a47, 0x001b, 0x146b, 0x0004, 0x08ec, 0x0013, 0x0047, - 0x0001, 0xc7c8, 0x0010, 0x0028, 0x000b, 0x1484, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x000a, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x8476, 0x0002, 0xb04f, - 0x0013, 0x1484, 0x0001, 0x0fe8, 0x0010, 0x0000, 0x0013, 0x1482, - 0x0001, 0x0fe8, 0x0000, 0x0002, 0x0013, 0x1482, 0x0015, 0x003a, - 0x0010, 0x8080, 0x0003, 0x0484, 0x0015, 0x003a, 0x0010, 0x4040, - 0x0017, 0x4000, 0x0000, 0x12fe, 0x001b, 0x604f, 0x0015, 0x0012, - 0x0001, 0x1b55, 0x0015, 0x0011, 0x0001, 0x1b55, 0x0001, 0x1288, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc00a, - 0x000b, 0x8490, 0x0005, 0x00b0, 0x0000, 0x8000, 0x0001, 0x1288, - 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb00a, - 0x001b, 0x8498, 0x0003, 0x004f, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0x0309, 0x001b, 0x84a1, 0x0011, 0x0d88, 0x0010, 0x0005, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb909, 0x001b, 0x84a7, - 0x0017, 0x4000, 0x0005, 0x00b6, 0x0010, 0x0600, 0x0014, 0x0683, - 0x0004, 0x051b, 0x0000, 0xb05a, 0x0000, 0xb15b, 0x0005, 0x0054, - 0x0010, 0x0829, 0x0010, 0x0d58, 0x0015, 0x0059, 0x0010, 0xffff, - 0x0000, 0xb930, 0x0005, 0x0031, 0x0010, 0x001e, 0x0015, 0x0033, - 0x0000, 0xb009, 0x001b, 0x84b9, 0x0000, 0xb05c, 0x0005, 0x0031, - 0x0000, 0x001f, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x84bf, - 0x0001, 0xb0c8, 0x0010, 0x000f, 0x000b, 0x14c6, 0x0015, 0x00ff, - 0x0010, 0x0005, 0x0013, 0x04ce, 0x0002, 0xb040, 0x0003, 0x14cb, - 0x0015, 0x00ff, 0x0000, 0x0004, 0x0013, 0x04ce, 0x0001, 0xb0c8, - 0x0010, 0x0006, 0x0002, 0xff60, 0x0010, 0xffb2, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0019, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0010, 0xb109, 0x001b, 0x84d6, 0x0012, 0xb170, - 0x0011, 0xffc8, 0x0010, 0xff00, 0x0011, 0xb2d0, 0x0010, 0xff60, - 0x0002, 0xb045, 0x0013, 0x14e1, 0x0015, 0x00b2, 0x0000, 0x0002, - 0x0003, 0x04eb, 0x0002, 0xb046, 0x0003, 0x14e6, 0x0015, 0x00b2, - 0x0000, 0x0001, 0x0003, 0x04eb, 0x0015, 0x00b2, 0x0010, 0x0000, - 0x0000, 0xc0b0, 0x0010, 0xc0b1, 0x0013, 0x04f1, 0x0000, 0xb930, - 0x0005, 0x0031, 0x0010, 0x002b, 0x0015, 0x0033, 0x0000, 0xb011, - 0x000b, 0x84f0, 0x0010, 0xb16a, 0x0010, 0xb06b, 0x0000, 0xb261, - 0x0015, 0x0044, 0x0010, 0x0018, 0x0000, 0xb930, 0x0005, 0x0031, - 0x0000, 0x0023, 0x0015, 0x0033, 0x0000, 0x6241, 0x001b, 0x84fb, - 0x0003, 0x94fc, 0x0015, 0x00a0, 0x0000, 0x0020, 0x0012, 0xd041, - 0x000b, 0x14ff, 0x0015, 0x00d1, 0x0010, 0x0202, 0x0013, 0x9503, - 0x0000, 0x75ff, 0x0011, 0xffc8, 0x0000, 0x1804, 0x0001, 0xffd8, - 0x0010, 0x0009, 0x0013, 0x9509, 0x0000, 0xff75, 0x0003, 0x950b, - 0x0015, 0x00d1, 0x0000, 0x0200, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0001, 0xbd88, 0x0000, 0x0008, 0x0000, 0xff31, 0x0015, 0x00b1, - 0x0010, 0x07d0, 0x0005, 0x00b0, 0x0010, 0x0009, 0x0015, 0x0033, - 0x0000, 0xb012, 0x000b, 0x8519, 0x0013, 0x046b, 0x0000, 0xba30, - 0x0005, 0x0031, 0x0010, 0x0035, 0x0015, 0x0033, 0x0000, 0xb009, - 0x000b, 0x8520, 0x0002, 0xb040, 0x0003, 0x153c, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0005, 0x0031, 0x0001, 0x1b71, 0x0015, 0x0033, - 0x0000, 0xb011, 0x000b, 0x8529, 0x0002, 0xb100, 0x0010, 0xffb1, - 0x001b, 0x2530, 0x0012, 0xb000, 0x0000, 0xffb0, 0x0013, 0x252a, - 0x0015, 0x0033, 0x0000, 0xb012, 0x000b, 0x8532, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0013, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb012, 0x001b, 0x853a, 0x0003, 0x053e, - 0x0010, 0xc0b1, 0x0000, 0xc0b0, 0x0017, 0x4000, 0x0005, 0x00b6, - 0x0010, 0x0500, 0x0014, 0x0683, 0x0005, 0x0054, 0x0010, 0x0889, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0002, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x854b, - 0x0010, 0xb058, 0x0000, 0x0d59, 0x0000, 0xb930, 0x0005, 0x0031, - 0x0000, 0x0023, 0x0015, 0x0033, 0x0000, 0xb011, 0x001b, 0x8553, - 0x0010, 0xb15c, 0x0010, 0xb05d, 0x0005, 0x0031, 0x0010, 0x002b, - 0x0015, 0x0033, 0x0000, 0xb011, 0x001b, 0x855a, 0x0000, 0xb15e, - 0x0000, 0xb05f, 0x0003, 0x955d, 0x0015, 0x00a0, 0x0010, 0x000c, - 0x0003, 0x0668, 0x0005, 0x00b6, 0x0000, 0x0700, 0x0014, 0x0683, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0009, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb709, 0x000b, 0x856b, - 0x0012, 0xb749, 0x0003, 0x1571, 0x0005, 0x0054, 0x0010, 0x0889, - 0x0003, 0x0573, 0x0005, 0x0054, 0x0010, 0x0898, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0002, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x857a, 0x0010, 0xb058, - 0x0000, 0x0d59, 0x0001, 0xb9c8, 0x0010, 0xf000, 0x0001, 0xffe8, - 0x0010, 0xf000, 0x001b, 0x15a3, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0010, 0x0005, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb009, 0x000b, 0x8589, 0x0001, 0xb0c8, 0x0000, 0xf700, - 0x0000, 0xffb0, 0x0011, 0xb0e8, 0x0000, 0xf100, 0x0013, 0x15ea, - 0x0011, 0xb0e8, 0x0000, 0xf200, 0x0013, 0x15ef, 0x0011, 0xb0e8, - 0x0010, 0xf300, 0x0003, 0x1614, 0x0011, 0xb0e8, 0x0000, 0xf400, - 0x0013, 0x1619, 0x0011, 0xb0e8, 0x0010, 0xf500, 0x0013, 0x15ea, - 0x0011, 0xb0e8, 0x0010, 0xf600, 0x0003, 0x162b, 0x0005, 0x00ce, - 0x0010, 0x0009, 0x0000, 0xb0cf, 0x0003, 0x08e1, 0x0000, 0xb930, - 0x0005, 0x0031, 0x0000, 0x0025, 0x0015, 0x0033, 0x0000, 0xb039, - 0x000b, 0x85a8, 0x0012, 0xb749, 0x0013, 0x15ad, 0x0002, 0xb52c, - 0x0000, 0xffb5, 0x0000, 0xb162, 0x0000, 0xb063, 0x0005, 0x0031, - 0x0000, 0x001f, 0x0015, 0x0033, 0x0000, 0xb309, 0x000b, 0x85b3, - 0x0001, 0xb3c8, 0x0010, 0x0003, 0x0003, 0x15bb, 0x0010, 0xffb2, - 0x0001, 0xffe8, 0x0010, 0x0003, 0x001b, 0x15bd, 0x0000, 0xc2b7, - 0x0013, 0x0647, 0x0001, 0xb2e8, 0x0000, 0x0001, 0x0013, 0x15c4, - 0x0005, 0x00ce, 0x0010, 0x000a, 0x0010, 0xb2cf, 0x0003, 0x08e1, - 0x0010, 0xb465, 0x0010, 0xb667, 0x0015, 0x00b7, 0x0010, 0x0018, - 0x0001, 0xb5c8, 0x0010, 0x0300, 0x0013, 0x15e9, 0x0012, 0xb548, - 0x0013, 0x15d0, 0x0000, 0xb6ff, 0x0011, 0xb780, 0x0010, 0xffb7, - 0x0002, 0xb549, 0x0013, 0x15d5, 0x0010, 0xb4ff, 0x0011, 0xb780, - 0x0010, 0xffb7, 0x0015, 0x0044, 0x0010, 0x0018, 0x0005, 0x0031, - 0x0000, 0x002c, 0x0015, 0x0033, 0x0000, 0x6841, 0x001b, 0x85db, - 0x0015, 0x0044, 0x0000, 0x0019, 0x0005, 0x0031, 0x0000, 0x0034, - 0x0015, 0x0033, 0x0000, 0x5029, 0x001b, 0x85e2, 0x0015, 0x0044, - 0x0000, 0x0008, 0x0011, 0xb7c8, 0x0010, 0x0003, 0x0013, 0x15e9, - 0x0010, 0xff55, 0x0013, 0x0647, 0x0005, 0x00b5, 0x0000, 0x0008, - 0x0015, 0x00b7, 0x0010, 0x0018, 0x0013, 0x0647, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x000b, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb011, 0x001b, 0x85f6, 0x0010, 0xb1ff, - 0x0001, 0xb0d0, 0x0003, 0x15ff, 0x0005, 0x00b5, 0x0010, 0x0b02, - 0x0010, 0xb062, 0x0010, 0xb163, 0x0003, 0x0601, 0x0005, 0x00b5, - 0x0000, 0x0302, 0x0015, 0x0065, 0x0010, 0x0012, 0x0005, 0x0067, - 0x0000, 0x0008, 0x0015, 0x006c, 0x0000, 0x7000, 0x0005, 0x006d, - 0x0010, 0x0500, 0x0015, 0x006f, 0x0010, 0x000a, 0x0015, 0x0044, - 0x0000, 0x0001, 0x0005, 0x0052, 0x0000, 0x2500, 0x0015, 0x0044, - 0x0000, 0x0008, 0x0015, 0x00b7, 0x0000, 0x0032, 0x0013, 0x0647, - 0x0005, 0x00b5, 0x0010, 0x0028, 0x0015, 0x00b7, 0x0010, 0x0018, - 0x0013, 0x0647, 0x0005, 0x00b5, 0x0000, 0x0100, 0x0005, 0x0067, - 0x0000, 0x0008, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, - 0x0010, 0x0018, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, - 0x001b, 0x8624, 0x0001, 0xb0c8, 0x0010, 0x00ff, 0x0010, 0xff69, - 0x0015, 0x00b7, 0x0000, 0x0020, 0x0013, 0x0647, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0005, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb609, 0x000b, 0x8632, 0x0001, 0xb6c8, - 0x0010, 0xff00, 0x0000, 0xffb0, 0x0015, 0x0033, 0x0000, 0xb00a, - 0x000b, 0x8638, 0x0001, 0xb6c8, 0x0010, 0x00ff, 0x0012, 0xff10, - 0x001b, 0x1641, 0x0000, 0xffb5, 0x0015, 0x00b7, 0x0010, 0x0018, - 0x0013, 0x0647, 0x0010, 0xff63, 0x0005, 0x00b5, 0x0000, 0x0800, - 0x0015, 0x00b7, 0x0010, 0x0018, 0x0013, 0x0647, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0009, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x864e, 0x0010, 0xb561, - 0x0013, 0x9650, 0x0010, 0xb7a0, 0x0003, 0x0668, 0x0005, 0x00b6, - 0x0010, 0x0300, 0x0014, 0x0683, 0x0005, 0x0054, 0x0010, 0x0819, - 0x0010, 0x0d58, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, - 0x0000, 0x0002, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, - 0x001b, 0x8660, 0x0000, 0xb059, 0x0003, 0x9662, 0x0010, 0xc0a0, - 0x0010, 0x71ff, 0x0002, 0xff28, 0x0010, 0xff71, 0x0003, 0x0668, - 0x0012, 0xd041, 0x000b, 0x1668, 0x0015, 0x00d1, 0x0010, 0x0202, - 0x0000, 0x75ff, 0x0011, 0xffc8, 0x0000, 0x1804, 0x0001, 0xffd8, - 0x0010, 0x0009, 0x0013, 0x9671, 0x0000, 0xff75, 0x0003, 0x9673, - 0x0015, 0x00d1, 0x0000, 0x0200, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0001, 0xbd88, 0x0000, 0x0008, 0x0000, 0xff31, 0x0005, 0x00b0, - 0x0010, 0x0009, 0x0015, 0x00b1, 0x0010, 0x07d0, 0x0015, 0x0033, - 0x0000, 0xb012, 0x001b, 0x8681, 0x0013, 0x046b, 0x0015, 0x0044, - 0x0000, 0x0008, 0x0005, 0x0098, 0x0010, 0x0056, 0x0015, 0x0099, - 0x0000, 0x9575, 0x0004, 0x08a8, 0x0000, 0xb096, 0x0012, 0xb270, - 0x0010, 0xff56, 0x0014, 0x08ca, 0x0010, 0xb052, 0x0010, 0xb153, - 0x0000, 0xb6ff, 0x0011, 0xb2d0, 0x0010, 0xff50, 0x0010, 0xb351, - 0x0017, 0x4000, 0x0001, 0x12e8, 0x0001, 0x1b55, 0x0003, 0x1845, - 0x0015, 0x00d1, 0x0000, 0x0400, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0001, 0x1288, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0x1009, 0x000b, 0x86a1, 0x0015, 0x000f, 0x0000, 0x0001, - 0x0010, 0xc014, 0x0000, 0x1213, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x1388, 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xba09, 0x000b, 0x86ad, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x1388, 0x0010, 0x0005, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0x1a09, 0x000b, 0x86b5, 0x0012, 0x104b, 0x001b, 0x16be, - 0x0000, 0x1a30, 0x0005, 0x0031, 0x0000, 0x000b, 0x0015, 0x0033, - 0x0000, 0x1621, 0x001b, 0x86bd, 0x0010, 0x15fe, 0x000b, 0x66dd, - 0x0004, 0x0704, 0x0002, 0x3a42, 0x000b, 0x1703, 0x0001, 0x10c8, - 0x0010, 0x000f, 0x000b, 0x1766, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x1388, 0x0000, 0x0008, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb009, 0x000b, 0x86cd, 0x0011, 0xb0e8, 0x0010, 0x0009, - 0x0003, 0x16d4, 0x0011, 0xb0e8, 0x0000, 0x0001, 0x001b, 0x1702, - 0x0011, 0x1388, 0x0010, 0x000a, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb009, 0x000b, 0x86d9, 0x0002, 0xb04f, 0x001b, 0x16f9, - 0x0013, 0x0702, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x1388, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, - 0x001b, 0x86e4, 0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x86e7, - 0x0010, 0xb0fe, 0x0003, 0x66ec, 0x0000, 0xb012, 0x0013, 0x06ee, - 0x0010, 0xc012, 0x0010, 0xc011, 0x0015, 0x000f, 0x0010, 0x0000, - 0x0002, 0x3944, 0x0013, 0x16f7, 0x0015, 0x0039, 0x0000, 0x5040, - 0x0015, 0x00b8, 0x0000, 0x0008, 0x0014, 0x0925, 0x0000, 0xc013, - 0x0003, 0x0703, 0x0010, 0x02fe, 0x0003, 0x66fe, 0x0015, 0x003a, - 0x0010, 0x2020, 0x0003, 0x0703, 0x0015, 0x003a, 0x0000, 0x2000, - 0x0015, 0x003a, 0x0010, 0x1010, 0x0004, 0x0911, 0x0003, 0x0054, - 0x0003, 0xb704, 0x0005, 0x002a, 0x0000, 0x0004, 0x0000, 0xba30, - 0x0005, 0x0031, 0x0010, 0x001b, 0x0015, 0x0033, 0x0000, 0xb009, - 0x000b, 0x870c, 0x0000, 0xc02c, 0x0000, 0xb02d, 0x0012, 0x104b, - 0x0013, 0x1727, 0x0000, 0x1a30, 0x0005, 0x0031, 0x0000, 0x0023, - 0x0015, 0x0033, 0x0000, 0xb129, 0x001b, 0x8716, 0x0000, 0xb120, - 0x0010, 0xb221, 0x0000, 0xb322, 0x0000, 0xb423, 0x0000, 0xb524, - 0x0000, 0xc025, 0x0010, 0xb526, 0x0010, 0xc027, 0x0010, 0xb516, - 0x0010, 0xc017, 0x0000, 0xb518, 0x0000, 0xc019, 0x0010, 0xc028, - 0x0000, 0xc029, 0x0010, 0xc01e, 0x0013, 0x075d, 0x0012, 0x1044, - 0x0003, 0x1757, 0x0002, 0x1034, 0x0000, 0xff10, 0x0000, 0x1a30, - 0x0005, 0x0031, 0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b29, - 0x000b, 0x8730, 0x0000, 0x1c30, 0x0000, 0x1b31, 0x0015, 0x0033, - 0x0000, 0xb131, 0x000b, 0x8735, 0x0002, 0x1f43, 0x000b, 0x173c, - 0x0010, 0xb3b5, 0x0000, 0xb4b6, 0x0000, 0xc0b3, 0x0010, 0xc0b4, - 0x0000, 0xb120, 0x0010, 0xb221, 0x0000, 0xb322, 0x0000, 0xb423, - 0x0000, 0xb524, 0x0010, 0xb625, 0x0010, 0xb516, 0x0000, 0xb617, - 0x0000, 0x1826, 0x0000, 0x1927, 0x0000, 0x1a30, 0x0005, 0x0031, - 0x0010, 0x000f, 0x0015, 0x0033, 0x0000, 0xb011, 0x000b, 0x874b, - 0x0000, 0xb028, 0x0000, 0xb129, 0x0012, 0x1e10, 0x0010, 0xff1e, - 0x0013, 0x675d, 0x0002, 0x1d00, 0x0010, 0xff1d, 0x0004, 0x02ab, - 0x0002, 0x3a42, 0x0003, 0x175d, 0x0003, 0x0765, 0x0000, 0x1a30, - 0x0005, 0x0031, 0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b79, - 0x000b, 0x875c, 0x0003, 0xb75d, 0x0005, 0x002a, 0x0000, 0x0001, - 0x0005, 0x0015, 0x0000, 0x0001, 0x0000, 0x1efe, 0x0003, 0x6765, - 0x0003, 0x0277, 0x0017, 0x4000, 0x0000, 0xba30, 0x0005, 0x0031, - 0x0010, 0x001b, 0x0015, 0x0033, 0x0010, 0xb051, 0x001b, 0x876b, - 0x0000, 0xb0a3, 0x0010, 0xb697, 0x0010, 0xb946, 0x0015, 0x00a5, - 0x0000, 0x0010, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x1388, - 0x0000, 0x0002, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb509, - 0x000b, 0x8778, 0x0014, 0x08ca, 0x0004, 0x08b9, 0x0012, 0xb470, - 0x0010, 0xffb4, 0x0010, 0xb48e, 0x0010, 0xb08a, 0x0010, 0xb18b, - 0x0012, 0x104d, 0x0003, 0x1783, 0x0013, 0x07b0, 0x0012, 0x104b, - 0x0013, 0x1796, 0x0005, 0x008c, 0x0010, 0x0829, 0x0010, 0xc08d, - 0x0001, 0xb2d8, 0x0010, 0x0600, 0x0010, 0xff88, 0x0010, 0xb389, - 0x0000, 0x1390, 0x0010, 0xb591, 0x0000, 0xc08f, 0x0010, 0x1ab9, - 0x0004, 0x051b, 0x0013, 0x9791, 0x0010, 0xb092, 0x0010, 0xb193, - 0x0013, 0x9794, 0x0013, 0x07ab, 0x0005, 0x008c, 0x0000, 0x0809, - 0x0015, 0x008d, 0x0000, 0x0008, 0x0001, 0xb2d8, 0x0000, 0x0100, - 0x0010, 0xff88, 0x0010, 0xb389, 0x0000, 0x1390, 0x0010, 0xb591, - 0x0000, 0xc08f, 0x0000, 0x1a30, 0x0005, 0x0031, 0x0010, 0x000f, - 0x0015, 0x0033, 0x0000, 0xb011, 0x000b, 0x87a6, 0x0013, 0x97a7, - 0x0000, 0xb192, 0x0000, 0xb093, 0x0003, 0x97aa, 0x0010, 0x19a1, - 0x0000, 0x18a2, 0x0015, 0x00b1, 0x0010, 0x0096, 0x0003, 0x0821, - 0x0000, 0xb590, 0x0010, 0x1391, 0x0001, 0x10c8, 0x0010, 0x000f, - 0x0001, 0xffe8, 0x0010, 0x0005, 0x0013, 0x17d7, 0x0001, 0xb2d8, - 0x0000, 0x0700, 0x0010, 0xff88, 0x0010, 0xb389, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x1388, 0x0010, 0x0009, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x87c2, 0x0002, 0xb049, - 0x0013, 0x17ca, 0x0005, 0x008c, 0x0010, 0x0889, 0x0015, 0x00b1, - 0x0010, 0x0096, 0x0013, 0x07ce, 0x0005, 0x008c, 0x0010, 0x0898, - 0x0015, 0x00b1, 0x0000, 0x0092, 0x0010, 0xc08d, 0x0000, 0xc08f, - 0x0013, 0x97d0, 0x0000, 0xc092, 0x0010, 0xc093, 0x0013, 0x97d3, - 0x0010, 0x19a1, 0x0000, 0x18a2, 0x0003, 0x0821, 0x0001, 0xb2d8, - 0x0000, 0x0100, 0x0010, 0xff88, 0x0010, 0xb389, 0x0005, 0x008c, - 0x0010, 0x0880, 0x0015, 0x008d, 0x0000, 0x0008, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x1388, 0x0000, 0x000e, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x87e6, 0x0010, 0xb08f, - 0x0000, 0xb590, 0x0010, 0x1391, 0x0000, 0x1a30, 0x0005, 0x0031, - 0x0000, 0x000d, 0x0015, 0x0033, 0x0000, 0xb021, 0x001b, 0x87ef, - 0x0003, 0x97f0, 0x0010, 0xb392, 0x0010, 0xb293, 0x0003, 0x97f3, - 0x0000, 0xb1a1, 0x0010, 0xb0a2, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x1388, 0x0000, 0x000b, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xb211, 0x001b, 0x87fd, 0x0000, 0xb3ff, 0x0001, 0xb080, - 0x0000, 0xffb3, 0x001b, 0x2804, 0x0002, 0xb200, 0x0003, 0x0805, - 0x0010, 0xb2ff, 0x0011, 0xb180, 0x0010, 0xffb2, 0x0011, 0x1388, - 0x0000, 0x000b, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb212, - 0x000b, 0x880c, 0x0015, 0x00b1, 0x0000, 0x0092, 0x0002, 0x104c, - 0x0003, 0x181f, 0x0011, 0xc2e8, 0x0010, 0x000c, 0x000b, 0x1817, - 0x0015, 0x00ff, 0x0000, 0x0800, 0x0013, 0x081f, 0x0011, 0xc2e8, - 0x0000, 0x0020, 0x000b, 0x181d, 0x0015, 0x00ff, 0x0010, 0x1800, - 0x0013, 0x081f, 0x0015, 0x00ff, 0x0000, 0x1000, 0x0011, 0xb1d0, - 0x0010, 0xffb1, 0x0015, 0x009a, 0x0010, 0x0036, 0x0005, 0x009b, - 0x0000, 0x95d5, 0x0012, 0xd041, 0x001b, 0x1825, 0x0015, 0x00d1, - 0x0010, 0x0202, 0x0013, 0x9829, 0x0012, 0x104e, 0x0013, 0x182e, - 0x0012, 0xb12f, 0x0010, 0xffb1, 0x0000, 0xb175, 0x0013, 0x982f, - 0x0015, 0x00d1, 0x0000, 0x0200, 0x0001, 0x19c8, 0x0010, 0xfff0, - 0x001b, 0x1838, 0x0015, 0x00b1, 0x0010, 0x07d0, 0x0003, 0x083a, - 0x0015, 0x00b1, 0x0000, 0x1b58, 0x0005, 0x00b0, 0x0010, 0x0009, - 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xbd88, 0x0000, 0x000b, - 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb012, 0x001b, 0x8843, - 0x0003, 0x0703, 0x0015, 0x0030, 0x0000, 0x0400, 0x0000, 0xa4ff, - 0x0003, 0x6893, 0x0011, 0xffa8, 0x0010, 0x0005, 0x000b, 0x2893, - 0x0005, 0x0031, 0x0001, 0x1b6c, 0x0015, 0x0033, 0x0010, 0xb211, - 0x000b, 0x8850, 0x0002, 0xb200, 0x0010, 0xffb2, 0x0005, 0x0031, - 0x0001, 0x1b6c, 0x0015, 0x0033, 0x0010, 0xb20a, 0x001b, 0x8857, - 0x0015, 0x000f, 0x0000, 0x0001, 0x0000, 0x1213, 0x0005, 0x0010, - 0x0000, 0x8000, 0x0015, 0x00a3, 0x0000, 0x0200, 0x0000, 0xc697, - 0x0005, 0x0046, 0x0000, 0x0002, 0x0015, 0x00a5, 0x0000, 0x0010, - 0x0011, 0xc4d8, 0x0000, 0x3200, 0x0010, 0xff88, 0x0000, 0xc589, - 0x0010, 0xc48a, 0x0010, 0xc58b, 0x0010, 0xc08e, 0x0005, 0x008c, - 0x0010, 0xe109, 0x0010, 0xc08d, 0x0015, 0x0090, 0x0001, 0x1b55, - 0x0005, 0x0091, 0x0010, 0xffff, 0x0000, 0xb292, 0x0000, 0xb393, - 0x0015, 0x009a, 0x0010, 0x0056, 0x0005, 0x009b, 0x0010, 0x95f5, - 0x0012, 0xd042, 0x0003, 0x1886, 0x0005, 0x00b0, 0x0010, 0x8080, - 0x0011, 0x1388, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb00a, 0x000b, 0x8881, 0x0015, 0x00b8, 0x0010, 0x000c, - 0x0014, 0x0925, 0x0003, 0x0888, 0x0005, 0x0075, 0x0010, 0x8092, - 0x0015, 0x00b1, 0x0010, 0x07d0, 0x0005, 0x00b0, 0x0010, 0x0009, - 0x0001, 0xbd88, 0x0000, 0x000b, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0000, 0xb012, 0x001b, 0x8891, 0x0003, 0x0703, 0x0015, 0x00d1, - 0x0000, 0x0400, 0x0001, 0x1288, 0x0010, 0x0003, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x889a, 0x0001, 0x1288, - 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc00a, - 0x000b, 0x88a0, 0x0010, 0xb0fe, 0x0003, 0x68a5, 0x0000, 0xb012, - 0x0003, 0x0703, 0x0010, 0xc012, 0x0010, 0xc011, 0x0003, 0x0703, - 0x0000, 0xba30, 0x0005, 0x0031, 0x0010, 0x0021, 0x0015, 0x0033, - 0x0010, 0xb019, 0x001b, 0x88ad, 0x0002, 0xb200, 0x0011, 0xffc8, - 0x0010, 0x00ff, 0x0010, 0xffb2, 0x0010, 0xb2b7, 0x0005, 0x0031, - 0x0000, 0x0023, 0x0015, 0x0033, 0x0010, 0xb20a, 0x000b, 0x88b7, - 0x0017, 0x4000, 0x0000, 0xba30, 0x0005, 0x0031, 0x0000, 0x0023, - 0x0015, 0x0033, 0x0010, 0xb409, 0x000b, 0x88be, 0x0002, 0xb400, - 0x0011, 0xffc8, 0x0010, 0x00ff, 0x0010, 0xffb4, 0x0010, 0xb4b7, - 0x0005, 0x0031, 0x0000, 0x0023, 0x0015, 0x0033, 0x0010, 0xb40a, - 0x001b, 0x88c8, 0x0017, 0x4000, 0x0000, 0xba30, 0x0001, 0xc7c8, - 0x0000, 0x0020, 0x001b, 0x18d6, 0x0005, 0x0031, 0x0010, 0x0028, - 0x0015, 0x0033, 0x0010, 0xb209, 0x000b, 0x88d2, 0x0011, 0xb2c8, - 0x0000, 0xff80, 0x0003, 0x18d9, 0x0010, 0xc4b0, 0x0010, 0xc5b1, - 0x0003, 0x08db, 0x0010, 0xc6b1, 0x0000, 0xc0b0, 0x0005, 0x0031, - 0x0000, 0x0004, 0x0015, 0x0033, 0x0010, 0xb211, 0x001b, 0x88df, - 0x0017, 0x4000, 0x0015, 0x00b8, 0x0010, 0x0009, 0x0015, 0x003a, - 0x0010, 0x0707, 0x0014, 0x0925, 0x0013, 0x002d, 0x0015, 0x00b8, - 0x0010, 0x0009, 0x0015, 0x003a, 0x0010, 0x0707, 0x0003, 0x0925, - 0x0004, 0x011c, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, - 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xba09, - 0x001b, 0x88f4, 0x0004, 0x08a8, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0000, 0x0010, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xb20a, 0x001b, 0x88fd, 0x0015, 0x0030, 0x0000, 0x0400, - 0x0011, 0x0d88, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0x0309, 0x001b, 0x8905, 0x0002, 0x0327, 0x0010, 0xffb2, - 0x0011, 0x0d88, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, - 0x0010, 0xb20a, 0x000b, 0x890d, 0x0015, 0x00b8, 0x0010, 0x0006, - 0x0003, 0x0925, 0x0014, 0x012e, 0x0004, 0x08a8, 0x0015, 0x0030, - 0x0000, 0x0400, 0x0011, 0x1388, 0x0000, 0x0010, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0010, 0xb20a, 0x000b, 0x891a, 0x0012, 0x1027, - 0x0010, 0xffb2, 0x0011, 0x1388, 0x0010, 0x0011, 0x0000, 0xff31, - 0x0015, 0x0033, 0x0010, 0xb20a, 0x001b, 0x8922, 0x0015, 0x00b8, - 0x0000, 0x0007, 0x0013, 0x4925, 0x0000, 0xb838, 0x0017, 0x4000, - 0x9a8c, 0xaf3d -}; -unsigned short xseqipx_code_length01 = 0x1252; diff --git a/drivers/scsi/qla2xxx/ql2400.c b/drivers/scsi/qla2xxx/ql2400.c deleted file mode 100644 index 77914fc..0000000 --- a/drivers/scsi/qla2xxx/ql2400.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include -#include -#include - -#include "qla_def.h" - -static char qla_driver_name[] = "qla2400"; - -extern uint32_t fw2400_version_str[]; -extern uint32_t fw2400_addr01; -extern uint32_t fw2400_code01[]; -extern uint32_t fw2400_length01; -extern uint32_t fw2400_addr02; -extern uint32_t fw2400_code02[]; -extern uint32_t fw2400_length02; - -static struct qla_fw_info qla_fw_tbl[] = { - { - .addressing = FW_INFO_ADDR_EXTENDED, - .fwcode = (unsigned short *)&fw2400_code01[0], - .fwlen = (unsigned short *)&fw2400_length01, - .lfwstart = (unsigned long *)&fw2400_addr01, - }, - { - .addressing = FW_INFO_ADDR_EXTENDED, - .fwcode = (unsigned short *)&fw2400_code02[0], - .fwlen = (unsigned short *)&fw2400_length02, - .lfwstart = (unsigned long *)&fw2400_addr02, - }, - { FW_INFO_ADDR_NOMORE, }, -}; - -static struct qla_board_info qla_board_tbl[] = { - { - .drv_name = qla_driver_name, - .isp_name = "ISP2422", - .fw_info = qla_fw_tbl, - .fw_fname = "ql2400_fw.bin", - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP2432", - .fw_info = qla_fw_tbl, - .fw_fname = "ql2400_fw.bin", - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP5422", - .fw_info = qla_fw_tbl, - .fw_fname = "ql2400_fw.bin", - }, - { - .drv_name = qla_driver_name, - .isp_name = "ISP5432", - .fw_info = qla_fw_tbl, - .fw_fname = "ql2400_fw.bin", - }, -}; - -static struct pci_device_id qla24xx_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2422, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[0], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP2432, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[1], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP5422, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[2], - }, - { - .vendor = PCI_VENDOR_ID_QLOGIC, - .device = PCI_DEVICE_ID_QLOGIC_ISP5432, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = (unsigned long)&qla_board_tbl[3], - }, - - {0, 0}, -}; -MODULE_DEVICE_TABLE(pci, qla24xx_pci_tbl); - -static int __devinit -qla24xx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - return qla2x00_probe_one(pdev, - (struct qla_board_info *)id->driver_data); -} - -static void __devexit -qla24xx_remove_one(struct pci_dev *pdev) -{ - qla2x00_remove_one(pdev); -} - -static struct pci_driver qla24xx_pci_driver = { - .name = "qla2400", - .id_table = qla24xx_pci_tbl, - .probe = qla24xx_probe_one, - .remove = __devexit_p(qla24xx_remove_one), -}; - -static int __init -qla24xx_init(void) -{ - return pci_module_init(&qla24xx_pci_driver); -} - -static void __exit -qla24xx_exit(void) -{ - pci_unregister_driver(&qla24xx_pci_driver); -} - -module_init(qla24xx_init); -module_exit(qla24xx_exit); - -MODULE_AUTHOR("QLogic Corporation"); -MODULE_DESCRIPTION("QLogic ISP24xx FC-SCSI Host Bus Adapter driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(QLA2XXX_VERSION); diff --git a/drivers/scsi/qla2xxx/ql2400_fw.c b/drivers/scsi/qla2xxx/ql2400_fw.c deleted file mode 100644 index 282b2d3..0000000 --- a/drivers/scsi/qla2xxx/ql2400_fw.c +++ /dev/null @@ -1,12346 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include - -/* - * Firmware Version 4.00.18 (14:53 Jan 30, 2006) - */ - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_version = 4*1024+0; -#else -uint32_t risc_code_version = 4*1024+0; -#endif - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_version_str[] = {4, 0,18}; -#else -uint32_t firmware_version[] = {4, 0,18}; -#endif - -#ifdef UNIQUE_FW_NAME -#define fw2400_VERSION_STRING "4.00.18" -#else -#define FW_VERSION_STRING "4.00.18" -#endif - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_addr01 = 0x00100000 ; -#else -uint32_t risc_code_addr01 = 0x00100000 ; -#endif - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_code01[] = { -#else -uint32_t risc_code01[] = { -#endif - 0x0401f17c, 0x0010d000, 0x00100000, 0x0000a971, - 0x00000004, 0x00000000, 0x00000012, 0x00000002, - 0x00000003, 0x00000000, 0x20434f50, 0x59524947, - 0x48542032, 0x30303520, 0x514c4f47, 0x49432043, - 0x4f52504f, 0x52415449, 0x4f4e2020, 0x20495350, - 0x32347878, 0x20466972, 0x6d776172, 0x65202020, - 0x56657273, 0x696f6e20, 0x342e302e, 0x31382020, - 0x20202024, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x42001800, 0x0010014f, 0x42002000, 0x0010b6fd, - 0x500c0800, 0x800c1800, 0x500c1000, 0x800c1800, - 0x54042000, 0x80102000, 0x80040800, 0x80081040, - 0x040207fc, 0x500c0800, 0x800409c0, 0x040207f6, - 0x44002000, 0x80102000, 0x40100000, 0x44040000, - 0x80000000, 0x44080000, 0x80000000, 0x440c0000, - 0x80000000, 0x44100000, 0x80000000, 0x44140000, - 0x80000000, 0x44180000, 0x80000000, 0x441c0000, - 0x80000000, 0x44200000, 0x80000000, 0x44240000, - 0x80000000, 0x44280000, 0x80000000, 0x442c0000, - 0x80000000, 0x44300000, 0x80000000, 0x44340000, - 0x80000000, 0x44380000, 0x80000000, 0x443c0000, - 0x80000000, 0x44400000, 0x80000000, 0x44440000, - 0x80000000, 0x44480000, 0x80000000, 0x444c0000, - 0x80000000, 0x44500000, 0x80000000, 0x44540000, - 0x80000000, 0x44580000, 0x80000000, 0x445c0000, - 0x80000000, 0x44600000, 0x80000000, 0x44640000, - 0x80000000, 0x44680000, 0x80000000, 0x446c0000, - 0x80000000, 0x44700000, 0x80000000, 0x44740000, - 0x80000000, 0x44780000, 0x80000000, 0x447c0000, - 0x80000000, 0x44800000, 0x80000000, 0x44840000, - 0x80000000, 0x44880000, 0x80000000, 0x448c0000, - 0x80000000, 0x44900000, 0x80000000, 0x44940000, - 0x80000000, 0x44980000, 0x80000000, 0x449c0000, - 0x80000000, 0x44a00000, 0x80000000, 0x44a40000, - 0x80000000, 0x44a80000, 0x80000000, 0x44ac0000, - 0x80000000, 0x44b00000, 0x80000000, 0x44b40000, - 0x80000000, 0x44b80000, 0x80000000, 0x44bc0000, - 0x80000000, 0x44c00000, 0x80000000, 0x44c40000, - 0x80000000, 0x44c80000, 0x80000000, 0x44cc0000, - 0x80000000, 0x44d00000, 0x80000000, 0x44d80000, - 0x80000000, 0x44d40000, 0x80000000, 0x44dc0000, - 0x80000000, 0x44e00000, 0x80000000, 0x44e40000, - 0x80000000, 0x44e80000, 0x80000000, 0x44ec0000, - 0x80000000, 0x44f00000, 0x80000000, 0x44f40000, - 0x80000000, 0x44f80000, 0x80000000, 0x44fc0000, - 0x80000000, 0x45000000, 0x80000000, 0x45040000, - 0x80000000, 0x45080000, 0x80000000, 0x450c0000, - 0x80000000, 0x45100000, 0x80000000, 0x45140000, - 0x80000000, 0x45180000, 0x80000000, 0x451c0000, - 0x80000000, 0x45200000, 0x80000000, 0x45240000, - 0x80000000, 0x45280000, 0x80000000, 0x452c0000, - 0x80000000, 0x45300000, 0x80000000, 0x45340000, - 0x80000000, 0x45380000, 0x80000000, 0x453c0000, - 0x80000000, 0x45400000, 0x80000000, 0x45440000, - 0x80000000, 0x45480000, 0x80000000, 0x454c0000, - 0x80000000, 0x45500000, 0x80000000, 0x45540000, - 0x80000000, 0x45580000, 0x80000000, 0x455c0000, - 0x80000000, 0x45600000, 0x80000000, 0x45640000, - 0x80000000, 0x45680000, 0x80000000, 0x456c0000, - 0x80000000, 0x45700000, 0x80000000, 0x45740000, - 0x80000000, 0x45780000, 0x80000000, 0x457c0000, - 0x80000000, 0x45800000, 0x80000000, 0x45840000, - 0x80000000, 0x45880000, 0x80000000, 0x458c0000, - 0x80000000, 0x45900000, 0x80000000, 0x45940000, - 0x80000000, 0x45980000, 0x80000000, 0x459c0000, - 0x80000000, 0x45a00000, 0x80000000, 0x45a40000, - 0x80000000, 0x45a80000, 0x80000000, 0x45ac0000, - 0x80000000, 0x45b00000, 0x80000000, 0x45b40000, - 0x80000000, 0x45b80000, 0x80000000, 0x45bc0000, - 0x80000000, 0x45c00000, 0x80000000, 0x45c40000, - 0x80000000, 0x45c80000, 0x80000000, 0x45cc0000, - 0x80000000, 0x45d00000, 0x80000000, 0x45d40000, - 0x80000000, 0x45d80000, 0x80000000, 0x45dc0000, - 0x80000000, 0x45e00000, 0x80000000, 0x45e40000, - 0x80000000, 0x45e80000, 0x80000000, 0x45ec0000, - 0x80000000, 0x45f00000, 0x80000000, 0x45f40000, - 0x80000000, 0x45f80000, 0x80000000, 0x45fc0000, - 0x4a03c020, 0x00004000, 0x4a03c011, 0x40000010, - 0x04006000, 0x4203e000, 0x40000000, 0x59e00017, - 0x8c000508, 0x04000003, 0x4a03c017, 0x00000000, - 0x4203e000, 0x30000001, 0x0401f000, 0x0000bf00, - 0x00000080, 0x0000bfe0, 0x00000020, 0x0000ff00, - 0x00000080, 0x0000ffd0, 0x00000030, 0x00007100, - 0x00000010, 0x00007200, 0x00000008, 0x00007209, - 0x00000007, 0x00007300, 0x00000008, 0x00007309, - 0x00000007, 0x00007400, 0x00000008, 0x00007409, - 0x00000007, 0x00007600, 0x000000b0, 0x00007700, - 0x00000040, 0x00003000, 0x00000070, 0x00004000, - 0x000000c0, 0x00006000, 0x00000050, 0x00006100, - 0x00000010, 0x00006130, 0x00000010, 0x00006150, - 0x00000010, 0x00006170, 0x00000010, 0x00006190, - 0x00000010, 0x000061b0, 0x00000010, 0x00000000, - 0x42000000, 0x00000100, 0x4202f000, 0x00000000, - 0x42000800, 0x00021f00, 0x45780800, 0x80040800, - 0x80000040, 0x040207fd, 0x4203f000, 0x00021fff, - 0x40000000, 0x4203e000, 0x90000100, 0x40000000, - 0x0201f800, 0x00100743, 0x42000000, 0x00001000, - 0x50000000, 0x82000480, 0x24320002, 0x04020015, - 0x42000800, 0x00000064, 0x80040840, 0x04000007, - 0x4a030000, 0x00000001, 0x40000000, 0x59800000, - 0x8c000500, 0x040007f9, 0x04000008, 0x42000800, - 0x00007a17, 0x50040000, 0x8c00050e, 0x04020003, - 0x8400054e, 0x44000800, 0x4a030000, 0x00000000, - 0x4a03c020, 0x00000004, 0x4203e000, 0x6000000f, - 0x59e00023, 0x8c000500, 0x04020039, 0x42000000, - 0x00100001, 0x50000800, 0x82040c00, 0x00000004, - 0x58042003, 0x42001000, 0xffffffff, 0x0201f800, - 0x0010073a, 0x0402004e, 0x58042003, 0x42001000, - 0xffffffff, 0x0201f800, 0x0010073a, 0x04020048, - 0x58042003, 0x42001000, 0x00ffffff, 0x0201f800, - 0x0010073a, 0x04020042, 0x58042003, 0x42001000, - 0x00ffffff, 0x0201f800, 0x0010073a, 0x0402003c, - 0x42000000, 0x00100001, 0x5000a000, 0x8250a400, - 0x00000004, 0x4200a800, 0x00020000, 0x5850b003, - 0x0201f800, 0x0010a93e, 0x8250a400, 0x00000005, - 0x4a0370e8, 0x00000003, 0x4200a800, 0x0000c000, - 0x5850b003, 0x0201f800, 0x0010a93e, 0x4a0378e8, - 0x00000003, 0x4200a800, 0x00008000, 0x5850b003, - 0x0201f800, 0x0010a93e, 0x0401f02b, 0x42000800, - 0x00020000, 0x58042003, 0x42001000, 0xffffffff, - 0x0201f800, 0x0010073a, 0x04020019, 0x4a0370e8, - 0x00000003, 0x42000800, 0x0000c000, 0x58042003, - 0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff, - 0x0201f800, 0x0010073a, 0x0402000d, 0x4a0378e8, - 0x00000003, 0x42000800, 0x00008000, 0x58042003, - 0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff, - 0x0201f800, 0x0010073a, 0x0400000b, 0x4a03c020, - 0x00004010, 0x4a03c011, 0x40100011, 0x04006000, - 0x4203e000, 0x40000000, 0x4203e000, 0x30000001, - 0x0401f000, 0x0201f800, 0x001007d7, 0x42001000, - 0x0010a971, 0x40080000, 0x80140480, 0x82001d00, - 0xffffff00, 0x04020003, 0x40001800, 0x0401f003, - 0x42001800, 0x000000ff, 0x480bc840, 0x480fc842, - 0x04011000, 0x400c0000, 0x80081400, 0x40140000, - 0x80080580, 0x040207f0, 0x4817500d, 0x45782800, - 0x59c40000, 0x82000500, 0xffff0000, 0x80000120, - 0x82000580, 0x00002422, 0x04020005, 0x59a8006f, - 0x84000540, 0x4803506f, 0x0401f00a, 0x59e00003, - 0x82000500, 0x00030000, 0x82000580, 0x00010000, - 0x04020004, 0x59a8006f, 0x84000542, 0x4803506f, - 0x42000800, 0x00000040, 0x59a8006f, 0x8c000502, - 0x0402000e, 0x42000800, 0x00001000, 0x82141480, - 0x0017ffff, 0x04021009, 0x80040902, 0x82141480, - 0x0013ffff, 0x04021005, 0x80040902, 0x82141480, - 0x0011ffff, 0x04001bc8, 0x4807500e, 0x42001000, - 0x00000024, 0x0201f800, 0x001063cf, 0x82040c00, - 0x0010cfc0, 0x4807500b, 0x4a03c810, 0x00100000, - 0x4a03c811, 0x0010a971, 0x4a03c829, 0x00000004, - 0x59e40001, 0x82000540, 0x0003001d, 0x4803c801, - 0x4a03c014, 0x001c001c, 0x42001000, 0x0000001c, - 0x0201f800, 0x00100728, 0x4202c000, 0x0010cfc0, - 0x59aab00b, 0x59aaa00b, 0x59aaa80b, 0x59aac80e, - 0x49675069, 0x59a8000b, 0x4803500c, 0x0201f800, - 0x001006a3, 0x0201f800, 0x0010768a, 0x0201f800, - 0x00100804, 0x0201f800, 0x0010084d, 0x0201f800, - 0x00101a60, 0x0201f800, 0x001013a4, 0x0201f800, - 0x001009b6, 0x0201f800, 0x001013a4, 0x0201f800, - 0x00100f9a, 0x0201f800, 0x0010640f, 0x0401fb54, - 0x0201f800, 0x00101fb5, 0x0201f800, 0x0010508b, - 0x0201f800, 0x00104b36, 0x0201f800, 0x00105ecd, - 0x0201f800, 0x00105c61, 0x0201f800, 0x0010143d, - 0x0201f800, 0x001012bf, 0x4203e000, 0xf0000001, - 0x4a035070, 0x00000014, 0x4a035071, 0x0000000b, - 0x4a035072, 0x00000001, 0x4a035073, 0x00000000, - 0x42000000, 0x00001000, 0x50000000, 0x82000480, - 0x24220001, 0x0400004a, 0x59e00002, 0x8c00051e, - 0x42000000, 0x7ffe00fe, 0x04000003, 0x42000000, - 0x7ffe01fe, 0x50000800, 0x48075058, 0x80040920, - 0x82040580, 0x0000013e, 0x0402000b, 0x59a8006f, - 0x84000548, 0x4803506f, 0x4a035070, 0x00000055, - 0x4a035071, 0x00000051, 0x4a035073, 0x0000000f, - 0x0401f033, 0x82040580, 0x0000013f, 0x0402000b, - 0x59a8006f, 0x8400054a, 0x4803506f, 0x4a035070, - 0x00000055, 0x4a035071, 0x00000051, 0x4a035073, - 0x0000000f, 0x0401f026, 0x59e00003, 0x82000500, - 0x00030000, 0x82000580, 0x00000000, 0x04020020, - 0x82040580, 0x00000147, 0x04000010, 0x82040580, - 0x00000145, 0x0402001a, 0x59a8006f, 0x84000546, - 0x4803506f, 0x4a035070, 0x00000033, 0x4a035071, - 0x00000030, 0x4a035072, 0x00000020, 0x4a035073, - 0x00000001, 0x0401f00c, 0x59a8006f, 0x84000544, - 0x4803506f, 0x4a035070, 0x00000033, 0x4a035071, - 0x00000030, 0x4a035072, 0x00000020, 0x4a035073, - 0x00000001, 0x4a0378e4, 0x000c0000, 0x59a8006f, - 0x8c000502, 0x04000004, 0x82000500, 0x00000030, - 0x04000b25, 0x4a03c018, 0x0000000f, 0x4203e000, - 0x20000511, 0x4203e000, 0x50010000, 0x4a03c020, - 0x00000000, 0x04027013, 0x59e00020, 0x82000580, - 0x00000002, 0x0402000f, 0x4a03c020, 0x00004000, - 0x4a03c011, 0x40000010, 0x04006000, 0x4203e000, - 0x40000000, 0x59e00017, 0x8c000508, 0x04000003, - 0x4a03c017, 0x00000000, 0x4203e000, 0x30000001, - 0x4202d800, 0x00000000, 0x4203e000, 0xb0600000, - 0x59a80873, 0x4007f800, 0x0201f000, 0x00020004, - 0x4df00000, 0x4203e000, 0x50000000, 0x416c0000, - 0x82000c80, 0x00000008, 0x04021afb, 0x0c01f804, - 0x5c03e000, 0x0201f000, 0x00020008, 0x00100328, - 0x0010033b, 0x00100411, 0x00100327, 0x0010048c, - 0x00100327, 0x00100327, 0x001005d0, 0x0401faee, - 0x42000800, 0x0010b2a0, 0x5804001d, 0x4803c857, - 0x8c000500, 0x0400000d, 0x84000500, 0x4800081d, - 0x4202d800, 0x00000004, 0x0401fbe8, 0x49f3c857, - 0x5c000800, 0x5c000000, 0x82000540, 0x00003e00, - 0x4c000000, 0x4c040000, 0x1c01f000, 0x0401fbd2, - 0x0201f800, 0x00104e0d, 0x04000010, 0x0201f800, - 0x00104e23, 0x04020035, 0x59940023, 0x82000580, - 0x0010401b, 0x04020004, 0x59940022, 0x800001c0, - 0x0402002e, 0x59c40006, 0x82000540, 0x000000c0, - 0x48038806, 0x0401f029, 0x0201f800, 0x00104d76, - 0x836c0580, 0x00000001, 0x040200be, 0x59a80017, - 0x82000580, 0x00000009, 0x040200ba, 0x497b5010, - 0x4a038893, 0x00000001, 0x42001000, 0x000000f0, - 0x0201f800, 0x001019aa, 0x0201f800, 0x00104e1b, - 0x59c41006, 0x04020006, 0x82081540, 0x000000f1, - 0x82081500, 0xbbffffff, 0x0401f003, 0x82081540, - 0x440000f1, 0x480b8806, 0x0201f800, 0x00105de2, - 0x0201f800, 0x001069b8, 0x42000000, 0x0010b638, - 0x0201f800, 0x0010a86e, 0x42001000, 0x00008030, - 0x497b5013, 0x0401f037, 0x0201f800, 0x00103951, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000480, - 0x00000007, 0x04021093, 0x0201f800, 0x00105de2, - 0x59c400a3, 0x82000500, 0xffefffff, 0x480388a3, - 0x59a8004b, 0x800001c0, 0x04020004, 0x0201f800, - 0x00103f53, 0x0401f087, 0x59a80015, 0x84000546, - 0x48035015, 0x0201f800, 0x00104e13, 0x59c41006, - 0x04020006, 0x82081540, 0x44000001, 0x82081500, - 0xffffff0f, 0x0401f003, 0x82081540, 0x440000f1, - 0x480b8806, 0x497b9005, 0x4a038802, 0x0000ffff, - 0x4a0378e4, 0x00003000, 0x4a0378e4, 0x000c0000, - 0x42000000, 0x0010b60a, 0x0201f800, 0x0010a86e, - 0x59a81010, 0x42000800, 0x00000003, 0x0201f800, - 0x001069af, 0x42001000, 0x00008010, 0x59a8180a, - 0x0201f800, 0x00103857, 0x0201f800, 0x00101886, - 0x59a80805, 0x82040d00, 0xffffffdf, 0x48075005, - 0x0201f800, 0x0010468b, 0x0201f800, 0x00104e0d, - 0x0400000a, 0x0201f800, 0x00103f58, 0x04000007, - 0x4a035013, 0x00000001, 0x497b5021, 0x0201f800, - 0x00103a9f, 0x0401f04f, 0x0201f800, 0x0010473b, - 0x04000005, 0x59c41002, 0x8408150c, 0x480b8802, - 0x0401f012, 0x0201f800, 0x00104e0d, 0x04020006, - 0x59a8001d, 0x80000540, 0x02000800, 0x001090d5, - 0x0401f00a, 0x0201f800, 0x001090d5, 0x59a80026, - 0x8c000506, 0x04020005, 0x59a8001d, 0x80000540, - 0x02020800, 0x00104075, 0x497b5028, 0x497b5027, - 0x497b5018, 0x0201f800, 0x00104e0d, 0x59a81026, - 0x0402000a, 0x0201f800, 0x00101694, 0x80001580, - 0x59a8002a, 0x82000500, 0xffff0000, 0x80040d40, - 0x4807502a, 0x0401f005, 0x59a8002a, 0x82000500, - 0xffff0000, 0x4803502a, 0x599c0017, 0x8c00050a, - 0x04000002, 0x84081544, 0x480b5026, 0x0201f800, - 0x00104e0d, 0x04000004, 0x0201f800, 0x00101694, - 0x48078880, 0x42001000, 0x00000005, 0x0201f800, - 0x00106e07, 0x497b5028, 0x497b501b, 0x4a03501c, - 0x0000ffff, 0x4a0378e4, 0x000000c0, 0x4202d800, - 0x00000002, 0x0201f800, 0x00104e0d, 0x04000007, - 0x59a80026, 0x82000500, 0x0000000c, 0x82000580, - 0x00000004, 0x04000003, 0x0201f800, 0x00101bf0, - 0x1c01f000, 0x59a8001c, 0x82000580, 0x0000ffff, - 0x04000004, 0x0201f800, 0x00101bf0, 0x0401f074, - 0x59a80026, 0x8c00050a, 0x04020003, 0x8c000506, - 0x0400001c, 0x8c000500, 0x0400001a, 0x4a038802, - 0x0000ffbf, 0x8c000502, 0x04000016, 0x599c0018, - 0x8c000516, 0x04020010, 0x59a80027, 0x82000580, - 0x0000ffff, 0x0400000c, 0x0201f800, 0x00101d45, - 0x59a80026, 0x8c000504, 0x0402005d, 0x42001000, - 0x00000003, 0x417a5800, 0x0201f800, 0x00101d6a, - 0x0401f057, 0x59a80028, 0x80000540, 0x04020054, - 0x59a80026, 0x8c000508, 0x04020005, 0x59a8001b, - 0x80000540, 0x0402004e, 0x0401f003, 0x8c000516, - 0x0400004b, 0x0201f800, 0x0010473b, 0x04020048, - 0x599c0018, 0x8c000516, 0x04020004, 0x0201f800, - 0x00104abe, 0x04020042, 0x599c0017, 0x8c00050a, - 0x0400000d, 0x4200b000, 0x000007f0, 0x417a8800, - 0x0201f800, 0x00020267, 0x04020004, 0x59340200, - 0x8c00051a, 0x04020036, 0x81468800, 0x8058b040, - 0x040207f8, 0x4a038802, 0x0000ffff, 0x42001800, - 0x0010b2e7, 0x0401fb98, 0x42001800, 0x0010b2f4, - 0x0401fb95, 0x59a80005, 0x84000502, 0x48035005, - 0x4a0378e4, 0x00000080, 0x4202d800, 0x00000003, - 0x4a03501c, 0x0000ffff, 0x0401fa8b, 0x80000580, - 0x0201f800, 0x001015fa, 0x599c0018, 0x8c000516, - 0x04000004, 0x0201f800, 0x00103929, 0x0401f009, - 0x42001800, 0x0000ffff, 0x42002000, 0x00000006, - 0x42003000, 0x00000000, 0x0201f800, 0x001038c7, - 0x0201f800, 0x00104e23, 0x0400000b, 0x59c40006, - 0x0201f800, 0x00104e0d, 0x04000004, 0x82000500, - 0xffffff0f, 0x0401f003, 0x82000500, 0xfbffffff, - 0x48038806, 0x0201f800, 0x00106c8a, 0x1c01f000, - 0x4c040000, 0x4c080000, 0x4c100000, 0x59a8003e, - 0x82000c80, 0x00000004, 0x04021983, 0x0c01f805, - 0x5c002000, 0x5c001000, 0x5c000800, 0x1c01f000, - 0x0010049c, 0x00100527, 0x00100553, 0x001005b4, - 0x42000000, 0x00000001, 0x0201f800, 0x001015fa, - 0x0201f800, 0x00105de2, 0x59c408a3, 0x82040d00, - 0xfffffff7, 0x480788a3, 0x0201f800, 0x00104e13, - 0x0400000e, 0x0201f800, 0x00104e23, 0x0400000b, - 0x0201f800, 0x00104e1b, 0x04020967, 0x59c400a3, - 0x84000532, 0x84000570, 0x480388a3, 0x4a038808, - 0x00000008, 0x0401f013, 0x59c400a3, 0x84000530, - 0x82000500, 0xbf7fffff, 0x480388a3, 0x42000800, - 0x000000f8, 0x0201f800, 0x00104030, 0x59c400a3, - 0x82000540, 0x00018000, 0x8400051c, 0x480388a3, - 0x82000500, 0xfffeffff, 0x480388a3, 0x497b8808, - 0x59c40006, 0x82000500, 0xfbffff0e, 0x48038806, - 0x497b2822, 0x497b2823, 0x42000800, 0x000001f4, - 0x42001000, 0x001005ce, 0x0201f800, 0x00105cbc, - 0x59c40805, 0x42001000, 0x00000001, 0x0201f800, - 0x001019aa, 0x0201f800, 0x001016ac, 0x0402000a, - 0x42000000, 0x00000001, 0x0201f800, 0x001018fa, - 0x42000000, 0x00000001, 0x0201f800, 0x00101892, - 0x0401f022, 0x0201f800, 0x001016b3, 0x04020008, - 0x41780000, 0x0201f800, 0x001018fa, 0x41780000, - 0x0201f800, 0x00101892, 0x0401f018, 0x0201f800, - 0x001016ba, 0x0402000a, 0x42000000, 0x00000002, - 0x0201f800, 0x001018fa, 0x42000000, 0x00000002, - 0x0201f800, 0x00101892, 0x0401f00c, 0x0201f800, - 0x001016c1, 0x04020918, 0x59a80049, 0x800001c0, - 0x04000006, 0x0201f800, 0x001016c7, 0x4a03503e, - 0x00000001, 0x0401f021, 0x0201f800, 0x00101994, - 0x4a03503e, 0x00000001, 0x0201f800, 0x00104e13, - 0x0400000c, 0x0201f800, 0x00104e23, 0x04000009, - 0x0201f800, 0x00104e1b, 0x04020903, 0x4a035033, - 0x00000001, 0x0201f800, 0x00104d76, 0x0401f00f, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, - 0x00000008, 0x04000003, 0x4a038805, 0x04000000, - 0x59c400a3, 0x82000540, 0x0001c000, 0x480388a3, - 0x84000520, 0x480388a3, 0x1c01f000, 0x0401f8a3, - 0x04020004, 0x4a03503e, 0x00000003, 0x0401f027, - 0x0201f800, 0x001016c1, 0x04020011, 0x59a80049, - 0x800001c0, 0x0400000e, 0x0201f800, 0x001016c7, - 0x59a80048, 0x8c00051e, 0x0400001c, 0x0201f800, - 0x00104e1b, 0x04020009, 0x4a035033, 0x00000001, - 0x0201f800, 0x00104d76, 0x0401f004, 0x0201f800, - 0x00101941, 0x04020011, 0x0201f800, 0x00101886, - 0x4a03503e, 0x00000002, 0x497b5049, 0x59c400a3, - 0x84000520, 0x480388a3, 0x497b2822, 0x497b2823, - 0x42000800, 0x0000002d, 0x42001000, 0x001005ce, - 0x0201f800, 0x00105cbc, 0x1c01f000, 0x0401f877, - 0x04020004, 0x4a03503e, 0x00000003, 0x0401f05b, - 0x4a038805, 0x000000f0, 0x0201f800, 0x00101941, - 0x04020050, 0x0201f800, 0x00104e1b, 0x04000044, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, - 0x00000008, 0x04000020, 0x59c40005, 0x8c000534, - 0x0402001d, 0x59940022, 0x82000580, 0x00000001, - 0x04020046, 0x0201f800, 0x00104e23, 0x04020043, - 0x4a038805, 0x000000f0, 0x0201f800, 0x00104e67, - 0x4a035032, 0x0000aaaa, 0x4a035033, 0x00000000, - 0x59c408a3, 0x82040d40, 0x00000008, 0x480788a3, - 0x4202d800, 0x00000001, 0x4a03503e, 0x00000000, - 0x4a038805, 0x00000001, 0x497b2822, 0x497b2823, - 0x0401f01f, 0x0201f800, 0x00104e23, 0x04020007, - 0x59a80032, 0x82000580, 0x0000aaaa, 0x04020003, - 0x4a035010, 0x00ffffff, 0x497b5032, 0x59c40006, - 0x82000540, 0x04000001, 0x48038806, 0x59a80805, - 0x8c040d06, 0x04020005, 0x59c408a3, 0x82040d40, - 0x00000008, 0x480788a3, 0x4202d800, 0x00000001, - 0x4a03503e, 0x00000000, 0x4a038805, 0x00000001, - 0x497b2822, 0x497b2823, 0x0401f010, 0x59c40005, - 0x82000500, 0x000000c0, 0x0400000c, 0x59c40006, - 0x82000540, 0x000000f1, 0x48038806, 0x0401f7ef, - 0x0201f800, 0x001016c1, 0x04020004, 0x59a80049, - 0x800001c0, 0x040207a4, 0x497b8885, 0x1c01f000, - 0x4803c856, 0x42000000, 0x00000001, 0x0201f800, - 0x001015fa, 0x4a03503e, 0x00000000, 0x0201f800, - 0x001016c1, 0x0402000b, 0x59a80052, 0x800001c0, - 0x04000004, 0x80000040, 0x48035052, 0x04020005, - 0x4a035052, 0x0000000a, 0x4a035049, 0x00000001, - 0x497b8885, 0x0401f0f6, 0x59940022, 0x59940823, - 0x80040540, 0x1c01f000, 0x497b2823, 0x1c01f000, - 0x4c080000, 0x42001000, 0x000000f0, 0x0201f800, - 0x001019aa, 0x5c001000, 0x1c01f000, 0x4a03505c, - 0x00000004, 0x4a03505d, 0x00000000, 0x4a03505e, - 0x00000012, 0x4a03505f, 0x00000002, 0x4a035010, - 0x00ffffff, 0x0201f800, 0x001090d5, 0x4a03502a, - 0x20200000, 0x4a03502b, 0x88000200, 0x4a03502c, - 0x00ff001f, 0x4a03502d, 0x000007d0, 0x4a03502e, - 0x80000000, 0x4a03502f, 0x00000200, 0x4a035030, - 0x00ff0000, 0x4a035031, 0x00010000, 0x4a03503a, - 0x514c4f47, 0x4a03503b, 0x49432020, 0x1c01f000, - 0x4d440000, 0x417a8800, 0x41780800, 0x0201f800, - 0x00020267, 0x04020005, 0x0201f800, 0x00104836, - 0x04020002, 0x80040800, 0x81468800, 0x83440580, - 0x000007f0, 0x040207f6, 0x5c028800, 0x1c01f000, - 0x4803c857, 0x5c000000, 0x4c000000, 0x4803c857, - 0x0401f809, 0x485fc857, 0x4203e000, 0x50000000, - 0x5c000000, 0x4d780000, 0x4200b800, 0x00008002, - 0x0401f006, 0x485fc857, 0x4203e000, 0x50000000, - 0x4200b800, 0x00008002, 0x04006000, 0x4c000000, - 0x4c040000, 0x59bc00ea, 0x82000500, 0x00000007, - 0x82000580, 0x00000001, 0x04020005, 0x42000800, - 0x00000000, 0x0201f800, 0x001069a3, 0x5c000800, - 0x4807c025, 0x80040920, 0x4807c026, 0x5c000000, - 0x4803c023, 0x80000120, 0x4803c024, 0x5c000000, - 0x4803c857, 0x4803c021, 0x80000120, 0x4803c022, - 0x41f80000, 0x4803c027, 0x80000120, 0x4803c028, - 0x42000000, 0x00001000, 0x50000000, 0x82000480, - 0x24320001, 0x4803c857, 0x04001053, 0x42000800, - 0x00000064, 0x80040840, 0x04000007, 0x4a030000, - 0x00000001, 0x40000000, 0x59800000, 0x8c000500, - 0x040007f9, 0x04000046, 0x42000800, 0x0010bfa2, - 0x46000800, 0xfaceface, 0x80040800, 0x4c080000, - 0x4c0c0000, 0x42001000, 0x00007a00, 0x58080013, - 0x44000800, 0x80040800, 0x58080019, 0x44000800, - 0x80040800, 0x5808001a, 0x44000800, 0x80040800, - 0x5808001b, 0x44000800, 0x80040800, 0x5808001c, - 0x44000800, 0x80040800, 0x5808001f, 0x44000800, - 0x80040800, 0x42001000, 0x00007a40, 0x42001800, - 0x0000000b, 0x50080000, 0x44000800, 0x80081000, - 0x80040800, 0x800c1840, 0x040207fb, 0x42001800, - 0x00000003, 0x42001000, 0x00007b00, 0x480c1003, - 0x58080005, 0x44000800, 0x80040800, 0x800c1840, - 0x040217fb, 0x42001000, 0x00007c00, 0x58080002, - 0x44000800, 0x80040800, 0x58080003, 0x44000800, - 0x80040800, 0x58080020, 0x44000800, 0x80040800, - 0x58080021, 0x44000800, 0x80040800, 0x58080022, - 0x44000800, 0x80040800, 0x58080023, 0x44000800, - 0x80040800, 0x5c001800, 0x5c001000, 0x4a030000, - 0x00000000, 0x485fc020, 0x905cb9c0, 0x825cbd40, - 0x00000012, 0x485fc011, 0x4203e000, 0x40000000, - 0x4202d800, 0x00000005, 0x59e00017, 0x8c000508, - 0x04000003, 0x4a03c017, 0x00000002, 0x4203e000, - 0x30000001, 0x0401f81f, 0x0401f7ff, 0x4a03c850, - 0x0010bfbe, 0x4a03c851, 0x0010cfbd, 0x4a03c853, - 0x00000800, 0x4a03c855, 0x0001eb5a, 0x59e40001, - 0x82000540, 0x00003f00, 0x4803c801, 0x4a03b104, - 0x70000002, 0x4a03a804, 0x70000002, 0x4a03b004, - 0x70000002, 0x42000000, 0x0010b6eb, 0x49780001, - 0x49780002, 0x1c01f000, 0x5c036000, 0x4db00000, - 0x49b3c857, 0x4803c857, 0x1c01f000, 0x1c01f000, - 0x59a8006b, 0x8c000530, 0x040207fe, 0x4c080000, - 0x42001000, 0x00000004, 0x0401f862, 0x5c001000, - 0x4201d000, 0x00028b0a, 0x0201f800, 0x00105dd2, - 0x4c080000, 0x42001000, 0x00000008, 0x0401f859, - 0x5c001000, 0x4201d000, 0x00028b0a, 0x0201f800, - 0x00105dd2, 0x4c080000, 0x42001000, 0x00000010, - 0x0401f850, 0x5c001000, 0x4201d000, 0x00028b0a, - 0x0201f800, 0x00105dd2, 0x0401f7e2, 0x8c00050c, - 0x59a8086b, 0x04020003, 0x84040d30, 0x0401f006, - 0x84040d70, 0x4807506b, 0x42001000, 0x00000000, - 0x0401f040, 0x4807506b, 0x836c0500, 0x00000007, - 0x0c01f001, 0x00100727, 0x0010070d, 0x0010070d, - 0x001006f5, 0x0010071a, 0x0010070d, 0x0010070d, - 0x0010071a, 0x59a8006f, 0x8c000502, 0x04020013, - 0x59c40801, 0x82040d00, 0x00018000, 0x82040580, - 0x00010000, 0x0400000a, 0x82040580, 0x00008000, - 0x04000004, 0x42001000, 0x42004000, 0x0401f006, - 0x42001000, 0x22002000, 0x0401f003, 0x42001000, - 0x12001000, 0x0401f025, 0x42001000, 0x00001004, - 0x0401f022, 0x59a8006f, 0x8c000502, 0x04020008, - 0x59a8006b, 0x8c000534, 0x04020004, 0x42001000, - 0x74057005, 0x0401f819, 0x1c01f000, 0x42001000, - 0x00002008, 0x0401f7fc, 0x59a8006b, 0x8c000534, - 0x0402000a, 0x59a8006f, 0x8c000502, 0x04000004, - 0x42001000, 0x24052005, 0x0401f00c, 0x42001000, - 0x74057005, 0x0401f009, 0x1c01f000, 0x1c01f000, - 0x82081500, 0x0000001c, 0x82081540, 0x001c0000, - 0x480bc013, 0x1c01f000, 0x59a8006b, 0x8c000530, - 0x04000002, 0x84081570, 0x480b506b, 0x8c000530, - 0x04020005, 0x82081500, 0x00007000, 0x80081114, - 0x0401fff0, 0x1c01f000, 0x41780000, 0x50041800, - 0x800c0400, 0x80040800, 0x80102040, 0x040207fc, - 0x80080500, 0x80000540, 0x1c01f000, 0x4202f000, - 0x00000000, 0x41780000, 0x41780800, 0x41781000, - 0x41781800, 0x41782000, 0x41782800, 0x41783000, - 0x41783800, 0x41784000, 0x41784800, 0x41785000, - 0x41785800, 0x41786000, 0x41786800, 0x41787000, - 0x41787800, 0x41788000, 0x41788800, 0x41789000, - 0x41789800, 0x4178a000, 0x4178a800, 0x4178b000, - 0x4178b800, 0x4178c000, 0x4178c800, 0x4178d000, - 0x4178d800, 0x4178e000, 0x4178e800, 0x4178f000, - 0x4178f800, 0x41790000, 0x41790800, 0x41791000, - 0x41791800, 0x41792000, 0x41792800, 0x41793000, - 0x41793800, 0x41794000, 0x41794800, 0x41795000, - 0x41795800, 0x41796000, 0x41796800, 0x41797000, - 0x41797800, 0x41798000, 0x41798800, 0x42019000, - 0x0010b333, 0x42019800, 0x0010b30a, 0x4179a000, - 0x4179a800, 0x4179b000, 0x4179b800, 0x4179c800, - 0x4179c000, 0x4179d000, 0x4179d800, 0x4179e000, - 0x4179e800, 0x4179f000, 0x4179f800, 0x417a0000, - 0x417a0800, 0x417a1000, 0x417a1800, 0x417a2000, - 0x42022800, 0x00006100, 0x417a3000, 0x417a3800, - 0x417a4000, 0x417a4800, 0x417a5000, 0x417a5800, - 0x417a6000, 0x417a6800, 0x417a7000, 0x417a7800, - 0x417a8000, 0x417a8800, 0x417a9000, 0x417a9800, - 0x417ae800, 0x417af800, 0x42030000, 0x00007c00, - 0x42031000, 0x0010b604, 0x42031800, 0x0000bf1d, - 0x42032000, 0x0000bf32, 0x42032800, 0x0010b5cc, - 0x42033000, 0x0010b274, 0x42034000, 0x0010b2a0, - 0x42033800, 0x0010b2bf, 0x42034800, 0x0010b342, - 0x42035000, 0x0010b200, 0x42035800, 0x0010aa00, - 0x42030800, 0x0010b301, 0x417b6000, 0x42036800, - 0x00006f00, 0x4203c800, 0x00003000, 0x42037000, - 0x0000ff00, 0x42037800, 0x0000bf00, 0x42038000, - 0x00007700, 0x42038800, 0x00004000, 0x42039000, - 0x00006000, 0x42039800, 0x0010bcda, 0x4203a000, - 0x00007600, 0x4203a800, 0x00007400, 0x4203b000, - 0x00007200, 0x4203b800, 0x00007100, 0x4203c000, - 0x00007000, 0x4203d000, 0x00000000, 0x4203e800, - 0x000200f9, 0x417bd800, 0x1c01f000, 0x42000800, - 0x00100000, 0x50040000, 0x4c000000, 0x42000000, - 0x0000aaaa, 0x44000800, 0x42001800, 0x00005555, - 0x41782000, 0x82102400, 0x00010000, 0x40100000, - 0x80042c00, 0x440c2800, 0x42003000, 0x0000000a, - 0x80183040, 0x040207ff, 0x50140000, 0x800c0580, - 0x04020004, 0x50040000, 0x800c0580, 0x040207f2, - 0x5c000000, 0x44000800, 0x80142840, 0x4817c861, - 0x1c01f000, 0x59a8081f, 0x800409c0, 0x04020009, - 0x49781c0c, 0x4a001a0c, 0x00000200, 0x4a001804, - 0x07000000, 0x59a80010, 0x9c0001c0, 0x48001805, - 0x0401fdf8, 0x9c0409c0, 0x48041806, 0x1c01f000, - 0x59a8080c, 0x4006d000, 0x4202b800, 0x00000001, - 0x59a8180d, 0x480fc857, 0x82041400, 0x00000014, - 0x82082400, 0x00000014, 0x40100000, 0x800c0480, - 0x04001006, 0x44080800, 0x40080800, 0x40101000, - 0x815eb800, 0x0401f7f7, 0x45780800, 0x495f5020, - 0x1c01f000, 0x835c0480, 0x00000020, 0x04001009, - 0x496bc857, 0x815eb840, 0x416a5800, 0x592ed000, - 0x497a5800, 0x497a5801, 0x812e59c0, 0x1c01f000, - 0x42000000, 0x0010b652, 0x0201f800, 0x0010a86e, - 0x417a5800, 0x0401f7f9, 0x815eb840, 0x04001008, - 0x416a5800, 0x492fc857, 0x592ed000, 0x497a5800, - 0x497a5801, 0x812e59c0, 0x1c01f000, 0x42000000, - 0x0010b652, 0x0201f800, 0x0010a86e, 0x417ab800, - 0x417a5800, 0x0401f7f8, 0x492fc857, 0x496a5800, - 0x412ed000, 0x815eb800, 0x59c80000, 0x82000540, - 0x00001200, 0x48039000, 0x1c01f000, 0x492fc857, - 0x812e59c0, 0x04000007, 0x592c0001, 0x497a5801, - 0x4c000000, 0x0401fff1, 0x5c025800, 0x0401f7f9, - 0x1c01f000, 0x4807c856, 0x42007000, 0x0010b5f6, - 0x4a007001, 0x00000000, 0x59e00003, 0x82000540, - 0x00008080, 0x4803c003, 0x4a03b805, 0x90000001, - 0x59dc0006, 0x4a03b805, 0x70000000, 0x59dc0006, - 0x4a03b805, 0x30000000, 0x59dc0006, 0x4a03b805, - 0x80000000, 0x4200b000, 0x00000020, 0x497bb807, - 0x8058b040, 0x040207fe, 0x4a03b805, 0x30000000, - 0x59dc0006, 0x4a03b805, 0x60000001, 0x59dc0006, - 0x4a03b805, 0x70000001, 0x59dc0006, 0x4a03b805, - 0x30000002, 0x4200b000, 0x00000020, 0x497bb807, - 0x8058b040, 0x040207fe, 0x4a03b805, 0x30000000, - 0x59dc0006, 0x4a03b805, 0x60000001, 0x0401ff9e, - 0x04000d99, 0x42001000, 0x0010b5f4, 0x452c1000, - 0x4a025801, 0x00000001, 0x4a025802, 0x00000100, - 0x4a025809, 0x00106eac, 0x497a580a, 0x497a580b, - 0x497a580c, 0x0401ff90, 0x04000d8b, 0x42001000, - 0x0010b5f5, 0x452c1000, 0x4a025801, 0x00000000, - 0x4a025802, 0x00000100, 0x4a025809, 0x0010120c, - 0x497a5803, 0x497a5807, 0x497a5808, 0x497a580a, - 0x59a8006f, 0x8c000500, 0x04000006, 0x4a03b805, - 0xe0000001, 0x59dc0006, 0x8c000522, 0x040007fc, - 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, - 0x4c380000, 0x40087000, 0x4a007002, 0x00000000, - 0x42007000, 0x0010b5f6, 0x82080400, 0x00000000, - 0x45780000, 0x58380005, 0x48087005, 0x80000540, - 0x04000006, 0x480bc857, 0x82000400, 0x00000000, - 0x44080000, 0x0401f003, 0x480bc857, 0x48087006, - 0x58380001, 0x80000540, 0x0400080c, 0x5c007000, - 0x5c03e000, 0x1c01f000, 0x4c380000, 0x42007000, - 0x0010b5f6, 0x58380001, 0x80000540, 0x04000803, - 0x5c007000, 0x1c01f000, 0x42007000, 0x0010b5f6, - 0x58380001, 0x82000580, 0x00000000, 0x04020012, - 0x58380000, 0x0c01f001, 0x001008d7, 0x001008d6, - 0x001008d6, 0x001008d6, 0x001008d6, 0x001008d6, - 0x001008d6, 0x001008d6, 0x0401fd3f, 0x58380808, - 0x800409c0, 0x04020027, 0x58380006, 0x80000540, - 0x04020002, 0x1c01f000, 0x4803c857, 0x48007002, - 0x40006800, 0x58340000, 0x80000540, 0x04020002, - 0x48007005, 0x48007006, 0x4a03b805, 0x20000000, - 0x59dc0006, 0x4a03b805, 0x30000000, 0x58340007, - 0x4803b800, 0x4803c857, 0x58340008, 0x4803b801, - 0x4803c857, 0x58340004, 0x48007003, 0x58340003, - 0x48007004, 0x4803b803, 0x4803c857, 0x58340001, - 0x8c000500, 0x04000004, 0x4a007001, 0x00000001, - 0x0401f028, 0x4a007001, 0x00000002, 0x0401f03e, - 0x0201f800, 0x001091b3, 0x0201f800, 0x0010a4b8, - 0x04000017, 0x4a03b805, 0x20000000, 0x59dc0006, - 0x4a03b805, 0x30000000, 0x4807b800, 0x480bb801, - 0x4a007003, 0x00000010, 0x480c7009, 0x42001000, - 0x001008be, 0x0201f800, 0x00105cd3, 0x58380008, - 0x82000400, 0x00000004, 0x48007004, 0x4803b803, - 0x4a007001, 0x00000007, 0x0401f023, 0x0201f800, - 0x001091cb, 0x42000800, 0x00000001, 0x42001000, - 0x001008be, 0x0201f800, 0x00105caf, 0x0401f7b7, - 0x4c040000, 0x4c080000, 0x58380803, 0x42001000, - 0x00003fff, 0x82040480, 0x00003fff, 0x04021003, - 0x40041000, 0x80000580, 0x48007003, 0x4803c857, - 0x800800c4, 0x4803b802, 0x4a03b805, 0x30000002, - 0x59dc0006, 0x4a03b805, 0x70000001, 0x59dc0006, - 0x4a03b805, 0x10000000, 0x5c001000, 0x5c000800, - 0x1c01f000, 0x483bc857, 0x4c040000, 0x4c080000, - 0x58380803, 0x42001000, 0x00003fff, 0x82040480, - 0x00003fff, 0x04021003, 0x40041000, 0x80000580, - 0x48007003, 0x800800c4, 0x4803b802, 0x4803c857, - 0x4a03b805, 0x10000002, 0x5c001000, 0x5c000800, - 0x1c01f000, 0x4c040000, 0x4c380000, 0x42007000, - 0x0010b5f6, 0x59dc0806, 0x4807c857, 0x4a03b805, - 0x20000000, 0x8c040d3e, 0x04000007, 0x8c040d08, - 0x04020cb9, 0x58380001, 0x82000500, 0x00000007, - 0x0c01f804, 0x5c007000, 0x5c000800, 0x1c01f000, - 0x001008c6, 0x0010096c, 0x0010097c, 0x00100615, - 0x00100615, 0x00100615, 0x00100615, 0x0010123a, - 0x4807c856, 0x82040d00, 0x43000f80, 0x04020009, - 0x58380003, 0x80000540, 0x0400001c, 0x59dc0000, - 0x4803b800, 0x59dc0001, 0x4803b801, 0x0401f7ad, - 0x58380802, 0x4a000802, 0x00000200, 0x0401f01d, - 0x4807c856, 0x82040d00, 0x43000f80, 0x04020009, - 0x58380003, 0x80000540, 0x0400000c, 0x59dc0000, - 0x4803b800, 0x59dc0001, 0x4803b801, 0x0401f7b6, - 0x58380002, 0x82000400, 0x00000002, 0x46000000, - 0x00000200, 0x0401f00b, 0x4c340000, 0x58386802, - 0x59dc0000, 0x4803c857, 0x48006807, 0x59dc0001, - 0x48006808, 0x4a006802, 0x00000100, 0x5c006800, - 0x4a007001, 0x00000000, 0x4c300000, 0x58386002, - 0x4833c857, 0x0401f80c, 0x04000009, 0x58300009, - 0x82000c80, 0x0010a971, 0x04021c73, 0x82000c80, - 0x00020000, 0x04001c70, 0x0801f800, 0x5c006000, - 0x0401f71e, 0x803061c0, 0x04000009, 0x59a8000c, - 0x80300480, 0x04001007, 0x59a8000d, 0x80300480, - 0x04021004, 0x82000540, 0x00000001, 0x1c01f000, - 0x80000580, 0x1c01f000, 0x4803c856, 0x4dc00000, - 0x42007000, 0x0010b601, 0x4a007400, 0x00000000, - 0x49787001, 0x42038000, 0x00007720, 0x4a038006, - 0x60000001, 0x4a038009, 0xf4f60000, 0x42038000, - 0x00007700, 0x4a038006, 0x60000001, 0x4a038009, - 0xf4f60000, 0x4a03c822, 0x00000010, 0x4a0370e8, - 0x00000000, 0x0401f809, 0x4a0370e9, 0x00003a0f, - 0x4a0370e8, 0x00000000, 0x4a0370e8, 0x00000001, - 0x5c038000, 0x1c01f000, 0x4c5c0000, 0x4178b800, - 0x0401f80a, 0x5c00b800, 0x1c01f000, 0x4803c856, - 0x4c5c0000, 0x825cbd40, 0x00000001, 0x0401f803, - 0x5c00b800, 0x1c01f000, 0x4803c856, 0x4dc00000, - 0x4c500000, 0x4c580000, 0x4c540000, 0x4a0370e8, - 0x00000000, 0x805cb9c0, 0x04000009, 0x4a038807, - 0x00000004, 0x59b800ea, 0x8c000510, 0x04000004, - 0x59b800e0, 0x0401f87b, 0x0401f7fb, 0x42038000, - 0x00007720, 0x0201f800, 0x00100f0f, 0x59c00007, - 0x4a038006, 0x20000000, 0x59c00007, 0x4a038006, - 0x8000000a, 0x59c00007, 0x4a038006, 0x8000000b, - 0x59c00007, 0x4a038006, 0x40000001, 0x83c00580, - 0x00007700, 0x04000004, 0x42038000, 0x00007700, - 0x0401f7ed, 0x42038000, 0x00007720, 0x42000800, - 0x00000800, 0x59c00007, 0x8c00051e, 0x04000006, - 0x4a038006, 0x90000001, 0x80040840, 0x040207fa, - 0x0401fc01, 0x83c00580, 0x00007700, 0x04000004, - 0x42038000, 0x00007700, 0x0401f7f1, 0x805cb9c0, - 0x0402001d, 0x4200b000, 0x00000020, 0x83b8ac00, - 0x00000020, 0x0201f800, 0x0010a947, 0x4a0370fb, - 0x00000001, 0x4a037020, 0x0010110d, 0x59a80039, - 0x82000500, 0x0000ffff, 0x48037021, 0x4a037035, - 0x0010bbda, 0x4a037030, 0x0010b210, 0x4a037031, - 0x0010aa00, 0x4a037032, 0x0010b315, 0x4a037036, - 0x0010b320, 0x59840002, 0x48037034, 0x4a037038, - 0x00101104, 0x4a0370fb, 0x00000001, 0x4178a000, - 0x4200b000, 0x00000020, 0x83b8ac00, 0x00000000, - 0x0201f800, 0x0010a947, 0x4200b000, 0x00000040, - 0x83b8ac00, 0x00000040, 0x0201f800, 0x0010a947, - 0x805cb9c0, 0x04020004, 0x4a0370e4, 0xaaaaaaaa, - 0x0401f003, 0x4a0370e4, 0xa2aaaa82, 0x4a0370e5, - 0xaaaaaaaa, 0x4a0370e6, 0xaaaaaaaa, 0x4a0370fb, - 0x00000000, 0x4a0370e6, 0xaaaaaaaa, 0x42038000, - 0x00007720, 0x4a038006, 0x90000000, 0x59c00007, - 0x8c00051e, 0x02020800, 0x00100615, 0x42038000, - 0x00007700, 0x4a038006, 0x90000000, 0x59c00007, - 0x8c00051e, 0x02020800, 0x00100615, 0x5c00a800, - 0x5c00b000, 0x5c00a000, 0x5c038000, 0x1c01f000, - 0x4d300000, 0x4d380000, 0x40026000, 0x82000500, - 0x7f000000, 0x82000580, 0x00000003, 0x0402000f, - 0x83326500, 0x00ffffff, 0x59300203, 0x82000580, - 0x00000004, 0x04020009, 0x59300c06, 0x82040580, - 0x00000009, 0x04020005, 0x42027000, 0x00000047, - 0x0201f800, 0x000208d8, 0x5c027000, 0x5c026000, - 0x1c01f000, 0x4d300000, 0x4d2c0000, 0x4d340000, - 0x4d400000, 0x4cfc0000, 0x4d380000, 0x4d3c0000, - 0x4d440000, 0x4d4c0000, 0x4d480000, 0x4c5c0000, - 0x4c600000, 0x4c640000, 0x4d040000, 0x4cc80000, - 0x4ccc0000, 0x4cf40000, 0x4cf80000, 0x4cfc0000, - 0x0201f800, 0x00020016, 0x5c01f800, 0x5c01f000, - 0x5c01e800, 0x5c019800, 0x5c019000, 0x5c020800, - 0x5c00c800, 0x5c00c000, 0x5c00b800, 0x5c029000, - 0x5c029800, 0x5c028800, 0x5c027800, 0x5c027000, - 0x5c01f800, 0x5c028000, 0x5c026800, 0x5c025800, - 0x5c026000, 0x1c01f000, 0x493bc857, 0x0201f000, - 0x00020045, 0x83300500, 0x1f000000, 0x04000008, - 0x81326580, 0x80000130, 0x82000c80, 0x00000014, - 0x02021800, 0x00100615, 0x0c01f013, 0x83300500, - 0x000000ff, 0x82000c80, 0x00000007, 0x02021800, - 0x00100615, 0x0c01f025, 0x1c01f000, 0x82000d00, - 0xc0000038, 0x02020800, 0x0010060d, 0x0201f800, - 0x00100615, 0x00000000, 0x00000048, 0x00000054, - 0x00000053, 0x00100ae4, 0x00100b08, 0x00100b03, - 0x00100b28, 0x00100aef, 0x00100afb, 0x00100ae4, - 0x00100b23, 0x00100b64, 0x00100ae4, 0x00100ae4, - 0x00100ae4, 0x00100ae4, 0x00100b67, 0x00100b6d, - 0x00100b7e, 0x00100b8f, 0x00100ae4, 0x00100b98, - 0x00100ba4, 0x00100ae4, 0x00100ae4, 0x00100ae4, - 0x0201f800, 0x00100615, 0x00100aed, 0x00100c3f, - 0x00100b35, 0x00100b59, 0x00100aed, 0x00100aed, - 0x00100aed, 0x0201f800, 0x00100615, 0x4803c856, - 0x59300004, 0x8c00053e, 0x04020005, 0x42027000, - 0x00000055, 0x0201f000, 0x000208d8, 0x0201f800, - 0x00106cb4, 0x040007fa, 0x1c01f000, 0x4803c856, - 0x0401f8aa, 0x40002800, 0x41782000, 0x42027000, - 0x00000056, 0x0201f000, 0x000208d8, 0x4803c856, - 0x42027000, 0x00000057, 0x0201f000, 0x000208d8, - 0x4803c856, 0x59300007, 0x8c00051a, 0x04020010, - 0x59325808, 0x812e59c0, 0x04000014, 0x592c0408, - 0x8c00051c, 0x04020003, 0x4a026011, 0xffffffff, - 0x59300004, 0x8c00053e, 0x04020009, 0x42027000, - 0x00000048, 0x0201f000, 0x000208d8, 0x59325808, - 0x4a025a06, 0x00000007, 0x0401f7f4, 0x0201f800, - 0x00106cb4, 0x040007f6, 0x1c01f000, 0x4803c856, - 0x83300500, 0x00ffffff, 0x0201f000, 0x0010620f, - 0x1c01f000, 0x4c040000, 0x59b808ea, 0x82040d00, - 0x00000007, 0x82040580, 0x00000003, 0x04000004, - 0x42000000, 0x60000000, 0x0401f8ac, 0x5c000800, - 0x1c01f000, 0x0401f8fa, 0x0400001b, 0x59325808, - 0x812e59c0, 0x04000018, 0x592c0204, 0x82000500, - 0x000000ff, 0x82000d80, 0x00000029, 0x04020012, - 0x59300203, 0x82000580, 0x00000003, 0x0400000b, - 0x59300807, 0x84040d26, 0x48066007, 0x0201f800, - 0x00020087, 0x4a03900d, 0x00000040, 0x4a0370e5, - 0x00000008, 0x1c01f000, 0x0201f800, 0x00106cb4, - 0x040007f4, 0x59880053, 0x80000000, 0x48031053, - 0x4a03900d, 0x00000040, 0x42000000, 0xc0000000, - 0x0401f05a, 0x42007800, 0x0010bbe1, 0x42002000, - 0x00003000, 0x42003000, 0x00000105, 0x0201f800, - 0x00105b3d, 0x4a0370e4, 0x02000000, 0x1c01f000, - 0x4933c857, 0x0201f000, 0x000208b4, 0x41300800, - 0x800409c0, 0x02020800, 0x00100615, 0x0201f800, - 0x0010060d, 0x4933c857, 0x813261c0, 0x02000800, - 0x00100615, 0x0401f835, 0x40002800, 0x0201f800, - 0x0010a7c3, 0x0401f8ae, 0x04000007, 0x59326809, - 0x59340200, 0x8c00050e, 0x59300414, 0x02020800, - 0x00109094, 0x1c01f000, 0x4933c857, 0x813261c0, - 0x02000800, 0x00100615, 0x0401f8a1, 0x0400000b, - 0x59325808, 0x0201f800, 0x00108df4, 0x04000007, - 0x592c0208, 0x8400054e, 0x48025a08, 0x417a7800, - 0x0201f800, 0x00108997, 0x1c01f000, 0x485fc857, - 0x5c000000, 0x4d780000, 0x4203e000, 0x50000000, - 0x4200b800, 0x00008005, 0x0201f000, 0x0010061a, - 0x4933c857, 0x83300480, 0x00000020, 0x02021800, - 0x00100615, 0x83300c00, 0x0010b6cb, 0x50040000, - 0x80000000, 0x04001002, 0x44000800, 0x1c01f000, - 0x4933c857, 0x0401f7f4, 0x4807c856, 0x59b800ea, - 0x8c000510, 0x040007fd, 0x59b800e0, 0x4803c857, - 0x1c01f000, 0x4803c856, 0x42000000, 0x10000000, - 0x41300800, 0x0401f02d, 0x82000500, 0xf0000000, - 0x82040d00, 0x0fffffff, 0x80040d40, 0x4807c857, - 0x59b800ea, 0x8c000516, 0x04020003, 0x480770e1, - 0x1c01f000, 0x8c000510, 0x040007fa, 0x4c040000, - 0x0401f809, 0x5c000800, 0x82100480, 0x00000008, - 0x040017f4, 0x4c040000, 0x0401febf, 0x5c000800, - 0x0401f7f0, 0x59b800e2, 0x59b820e2, 0x80100580, - 0x040207fd, 0x80102114, 0x0401f006, 0x59b800e2, - 0x59b820e2, 0x80100580, 0x040207fd, 0x0401f001, - 0x40101800, 0x800c190a, 0x82100500, 0x0000001f, - 0x820c1d00, 0x0000001f, 0x800c2480, 0x82102500, - 0x0000001f, 0x1c01f000, 0x82000500, 0xf0000000, - 0x82040d00, 0x0fffffff, 0x80040d40, 0x4807c857, - 0x42001000, 0x0010b602, 0x50080000, 0x80000540, - 0x04020005, 0x4a0370e5, 0x00000003, 0x4a0370e4, - 0x00000300, 0x80000000, 0x44001000, 0x42001000, - 0x00000400, 0x59b800ea, 0x8c000510, 0x0400000c, - 0x0401ffd5, 0x82100480, 0x00000008, 0x04001007, - 0x4c040000, 0x4c080000, 0x0401fe8b, 0x5c001000, - 0x5c000800, 0x0401f020, 0x59b800ea, 0x8c000516, - 0x0402001d, 0x4a0370e4, 0x00300000, 0x480770e1, - 0x42001000, 0x0000ff00, 0x80081040, 0x04000012, - 0x59b808e4, 0x8c040d28, 0x040207fc, 0x42001000, - 0x0010b602, 0x50080000, 0x80000040, 0x04020005, - 0x4a0370e5, 0x00000002, 0x4a0370e4, 0x00000200, - 0x02001800, 0x00100615, 0x44001000, 0x8c040d2c, - 0x1c01f000, 0x41f80000, 0x50000000, 0x0201f800, - 0x00100615, 0x80081040, 0x040207d3, 0x41f80000, - 0x50000000, 0x0201f800, 0x00100615, 0x4d380000, - 0x59300c06, 0x82040580, 0x00000009, 0x04020006, - 0x42027000, 0x00000047, 0x0201f800, 0x000208d8, - 0x80000580, 0x5c027000, 0x1c01f000, 0x4c500000, - 0x4a03900d, 0x00000001, 0x59c8a020, 0x4a03900d, - 0x00000002, 0x59c80820, 0x8c50a52e, 0x04000002, - 0x900409c0, 0x82040d00, 0x0000ffff, 0x0201f800, - 0x00105b0f, 0x5c00a000, 0x1c01f000, 0x0401fff0, - 0x04000045, 0x4933c857, 0x59300406, 0x82000580, - 0x00000000, 0x04000040, 0x59c82021, 0x4a03900d, - 0x00000001, 0x59c82821, 0x82142d00, 0x0000ffff, - 0x59325808, 0x812e59c0, 0x04000037, 0x59326809, - 0x0201f800, 0x00104728, 0x02020800, 0x0010907c, - 0x599c0019, 0x8c00050c, 0x04020018, 0x0201f800, - 0x00104728, 0x04020015, 0x59300811, 0x4807c857, - 0x592c0408, 0x8c00051c, 0x0402000e, 0x8400055c, - 0x48025c08, 0x592c0a04, 0x82040d00, 0x000000ff, - 0x82040580, 0x00000048, 0x04000004, 0x82040580, - 0x00000018, 0x04020003, 0x59300811, 0x48065803, - 0x4a026011, 0x7fffffff, 0x48166013, 0x0201f800, - 0x0010112d, 0x04020014, 0x0401fa07, 0x40280000, - 0x4802600d, 0x04000005, 0x4832600b, 0x50200000, - 0x4802600a, 0x4822600c, 0x59300414, 0x8c00051c, - 0x04020004, 0x599c0019, 0x8c00050c, 0x0402086e, - 0x4a03900d, 0x00000040, 0x4a0370e5, 0x00000008, - 0x1c01f000, 0x59880053, 0x80000000, 0x48031053, - 0x4a03900d, 0x00000040, 0x42000000, 0xc0000000, - 0x0401f726, 0x4cf80000, 0x58f40000, 0x8001f540, - 0x0401f820, 0x41781800, 0x0401f8e7, 0x04020014, - 0x44140800, 0x0401f82a, 0x04000011, 0x40043800, - 0x42001800, 0x00000001, 0x40142000, 0x0401f8de, - 0x0402000b, 0x801c3800, 0x501c0000, 0x44000800, - 0x0401f810, 0x801c0580, 0x04000004, 0x44103800, - 0x801c3840, 0x44143800, 0x0401f819, 0x5c01f000, - 0x1c01f000, 0x80f9f1c0, 0x04020003, 0x58f41202, - 0x0401f003, 0x42001000, 0x00000007, 0x1c01f000, - 0x80f9f1c0, 0x04020006, 0x58f40401, 0x82000480, - 0x00000002, 0x80f40400, 0x0401f005, 0x58f80401, - 0x82000480, 0x00000002, 0x80f80400, 0x50002800, - 0x80000000, 0x50002000, 0x1c01f000, 0x80f9f1c0, - 0x04020008, 0x58f40401, 0x82000480, 0x00000002, - 0x02001800, 0x00100615, 0x4801ec01, 0x0401f00b, - 0x58f80401, 0x82000480, 0x00000002, 0x02001800, - 0x00100615, 0x4801f401, 0x82000580, 0x00000002, - 0x04020002, 0x0401f809, 0x58f40202, 0x80000040, - 0x4801ea02, 0x02000800, 0x00100615, 0x82000580, - 0x00000001, 0x1c01f000, 0x4d2c0000, 0x40fa5800, - 0x0201f800, 0x0010083a, 0x4979e800, 0x4179f000, - 0x5c025800, 0x1c01f000, 0x80f5e9c0, 0x04000009, - 0x80f9f1c0, 0x04020ff5, 0x4d2c0000, 0x40f65800, - 0x0201f800, 0x0010083a, 0x4179e800, 0x5c025800, - 0x1c01f000, 0x4cf40000, 0x0201f800, 0x00104728, - 0x04020036, 0x59300807, 0x82040500, 0x00003100, - 0x04020032, 0x8c040d22, 0x04000032, 0x5930001f, - 0x8001ed40, 0x02000800, 0x00100615, 0x82000580, - 0xffffffff, 0x04000029, 0x58f40201, 0x82000580, - 0x0000dcb3, 0x02020800, 0x00100615, 0x58f40a02, - 0x82040500, 0x0000fffe, 0x04000003, 0x0401ff86, - 0x58f40a02, 0x82040480, 0x0000000f, 0x04021059, - 0x80040800, 0x4805ea02, 0x82040580, 0x00000008, - 0x0400005d, 0x82040480, 0x00000008, 0x0400100a, - 0x58f40000, 0x8001ed40, 0x02000800, 0x00100615, - 0x58f40201, 0x82000580, 0x0000ddb9, 0x02020800, - 0x00100615, 0x58f40401, 0x82000c00, 0x00000002, - 0x4805ec01, 0x80f40400, 0x59300812, 0x44040000, - 0x80000000, 0x45780000, 0x5c01e800, 0x1c01f000, - 0x42001000, 0x00000400, 0x59b800e4, 0x8c000524, - 0x04020023, 0x4a0370e4, 0x00030000, 0x40000000, - 0x59b800e4, 0x8c000524, 0x0402001b, 0x59300807, - 0x84040d62, 0x48066007, 0x4a0370e4, 0x00020000, - 0x4d2c0000, 0x0201f800, 0x00100819, 0x04000025, - 0x492e601f, 0x4a025a01, 0x0000dcb3, 0x59300008, - 0x80001d40, 0x02000800, 0x00100615, 0x580c080f, - 0x48065803, 0x59301811, 0x40040000, 0x800c0580, - 0x0402000d, 0x497a5a02, 0x4a025c01, 0x00000004, - 0x0401f011, 0x4a0370e4, 0x00020000, 0x40000000, - 0x40000000, 0x80081040, 0x02000800, 0x00100615, - 0x0401f7d6, 0x4a025a02, 0x00000001, 0x4a025c01, - 0x00000006, 0x497a5804, 0x400c0000, 0x80040480, - 0x48025805, 0x412de800, 0x5c025800, 0x0401f7a9, - 0x5c025800, 0x4a02601f, 0xffffffff, 0x0401f7c3, - 0x4d2c0000, 0x58f65800, 0x0201f800, 0x0010083a, - 0x40f65800, 0x0201f800, 0x0010083a, 0x5c025800, - 0x0401f7f5, 0x4d2c0000, 0x0201f800, 0x00100819, - 0x040007f8, 0x4a025a01, 0x0000ddb9, 0x4a025c01, - 0x00000002, 0x492de800, 0x412de800, 0x5c025800, - 0x0401f7a5, 0x0401ff30, 0x82f40400, 0x00000004, - 0x800c0400, 0x40000800, 0x50040000, 0x80100580, - 0x04000016, 0x82040c00, 0x00000002, 0x80081040, - 0x040207fa, 0x80f9f1c0, 0x04000011, 0x58f41202, - 0x82081480, 0x00000007, 0x82f80400, 0x00000002, - 0x800c0400, 0x40000800, 0x50040000, 0x80100580, - 0x04000006, 0x82040c00, 0x00000002, 0x80081040, - 0x040207fa, 0x0401f002, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fd, 0x4cf40000, 0x4cf80000, - 0x4001e800, 0x592c0a06, 0x800409c0, 0x04020021, - 0x82f40580, 0xffffffff, 0x0400001b, 0x58f40201, - 0x82000580, 0x0000dcb3, 0x02020800, 0x00100615, - 0x58f40000, 0x8001f540, 0x04000006, 0x58f80201, - 0x82000580, 0x0000ddb9, 0x02020800, 0x00100615, - 0x41783800, 0x58f44003, 0x0401f83d, 0x04020009, - 0x0401ff2e, 0x497a601f, 0x59300807, 0x84040d22, - 0x48066007, 0x5c01f000, 0x5c01e800, 0x1c01f000, - 0x0401ff26, 0x4a025a06, 0x00000011, 0x0401f7f6, - 0x82f40580, 0xffffffff, 0x04020f20, 0x0401f7f2, - 0x4cf40000, 0x4cf80000, 0x4001e800, 0x82040580, - 0x00000001, 0x04020020, 0x82f40580, 0xffffffff, - 0x0400001a, 0x58f40201, 0x82000580, 0x0000dcb3, - 0x02020800, 0x00100615, 0x58f40000, 0x8001f540, - 0x04000006, 0x58f80201, 0x82000580, 0x0000ddb9, - 0x02020800, 0x00100615, 0x41783800, 0x58f44003, - 0x0401f813, 0x04020008, 0x0401ff04, 0x42000800, - 0x00000001, 0x497a601f, 0x5c01f000, 0x5c01e800, - 0x1c01f000, 0x0401fefd, 0x42000800, 0x00000011, - 0x0401f7f9, 0x4c040000, 0x82f40580, 0xffffffff, - 0x04020ef6, 0x5c000800, 0x0401f7f3, 0x4803c856, - 0x401c2000, 0x41781800, 0x4c200000, 0x0401ff86, - 0x5c004000, 0x0402002c, 0x40202000, 0x42001800, - 0x00000001, 0x0401ff80, 0x04020027, 0x0401feae, - 0x40082800, 0x82f40400, 0x00000004, 0x40003000, - 0x50182000, 0x40100000, 0x801c0580, 0x04000005, - 0x42001800, 0x00000001, 0x0401ff73, 0x0402001a, - 0x82183400, 0x00000002, 0x80142840, 0x040207f5, - 0x80f9f1c0, 0x04000013, 0x58f42a02, 0x82142c80, - 0x00000007, 0x82f80400, 0x00000003, 0x40003000, - 0x50182000, 0x40100000, 0x801c0580, 0x04000005, - 0x42001800, 0x00000001, 0x0401ff5f, 0x04020006, - 0x82183400, 0x00000002, 0x80142840, 0x040207f5, - 0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fd, - 0x0201f800, 0x00100615, 0x58380207, 0x8c000502, - 0x040007fc, 0x50200000, 0x80387c00, 0x583c2800, - 0x583c2001, 0x58380404, 0x80001540, 0x04020002, - 0x58381407, 0x58c83401, 0x58380c08, 0x59303807, - 0x497a6012, 0x497a6013, 0x0201f000, 0x000200bf, - 0x592c0408, 0x8c000502, 0x040007ea, 0x592c0409, - 0x80000540, 0x040007e7, 0x82000c80, 0x00000002, - 0x04001011, 0x58380001, 0x80007540, 0x02000800, - 0x00100615, 0x58380204, 0x82000500, 0x0000000f, - 0x82000400, 0x0010110d, 0x50004000, 0x40040000, - 0x800409c0, 0x04000005, 0x82040c80, 0x00000005, - 0x040217f1, 0x80204400, 0x50200000, 0x80387c00, - 0x583c2800, 0x583c2001, 0x583c1002, 0x592c0a07, - 0x592c4c08, 0x592c300d, 0x59303807, 0x497a6012, - 0x497a6013, 0x4816600e, 0x4812600f, 0x480a6010, - 0x481a6011, 0x80040840, 0x4806600d, 0x02000000, - 0x000200c7, 0x80204000, 0x50201800, 0x800c19c0, - 0x0402000c, 0x58380001, 0x80007540, 0x02000800, - 0x00100615, 0x58380204, 0x82000500, 0x0000000f, - 0x82000400, 0x0010110d, 0x50004000, 0x50201800, - 0x483a600b, 0x480e600a, 0x4822600c, 0x0201f000, - 0x000200c7, 0x4803c856, 0x592c0208, 0x8c00051e, - 0x04020017, 0x50200000, 0x80306c00, 0x40240000, - 0x0c01f001, 0x00100e91, 0x00100e91, 0x00100e9a, - 0x00100e91, 0x00100e91, 0x00100e91, 0x00100e91, - 0x00100e91, 0x00100e9a, 0x00100e91, 0x00100e9a, - 0x00100e91, 0x00100e91, 0x00100e9a, 0x00100e91, - 0x00100e91, 0x0201f800, 0x00100615, 0x8400051e, - 0x48025a08, 0x50200000, 0x80306c00, 0x58343801, - 0x481e600f, 0x0401f007, 0x58341802, 0x58342800, - 0x58343801, 0x480e6010, 0x4816600e, 0x481e600f, - 0x0401f24b, 0x4933c857, 0x5931f808, 0x59300a06, - 0x800409c0, 0x04000005, 0x80040906, 0x04020002, - 0x80040800, 0x4805fc06, 0x4a026206, 0x00000002, - 0x592c0409, 0x82000500, 0x00000008, 0x0400000b, - 0x0401f834, 0x59300203, 0x82000580, 0x00000004, - 0x04020005, 0x42027000, 0x00000048, 0x0201f800, - 0x000208d8, 0x1c01f000, 0x4cfc0000, 0x58fc0204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000048, - 0x0402000c, 0x58fc000b, 0x800001c0, 0x04000009, - 0x58fc0407, 0x800001c0, 0x04000006, 0x58fc080b, - 0x8c040d16, 0x04000017, 0x58fc0007, 0x0401f00a, - 0x58fc0408, 0x8c000512, 0x04020014, 0x58fc0c09, - 0x8c040d16, 0x04020003, 0x5c01f800, 0x1c01f000, - 0x58fc000a, 0x59300811, 0x80040580, 0x04020009, - 0x59300007, 0x84000500, 0x48026007, 0x42027000, - 0x00000048, 0x5c01f800, 0x0201f000, 0x000208d8, - 0x5c01f800, 0x1c01f000, 0x58fdf809, 0x0401f7ec, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4933c857, - 0x59b808ea, 0x82040d00, 0x00000007, 0x82040580, - 0x00000000, 0x0400001e, 0x82040580, 0x00000003, - 0x0400001b, 0x59300406, 0x4c000000, 0x4a026406, - 0x00000000, 0x42003000, 0x00000041, 0x42000000, - 0x50000000, 0x41300800, 0x4c180000, 0x0401fce3, - 0x5c003000, 0x0400000b, 0x42000000, 0x0000001e, - 0x80000040, 0x040207ff, 0x80183040, 0x040207f4, - 0x42000000, 0x40000000, 0x41300800, 0x0401fcd7, - 0x5c000000, 0x48026406, 0x1c01f000, 0x59300007, - 0x84000500, 0x48026007, 0x0401f7fc, 0x59c00007, - 0x4a038006, 0x30000000, 0x40000000, 0x59c00007, - 0x8c00050a, 0x040207fe, 0x1c01f000, 0x5c000000, - 0x4c000000, 0x4803c857, 0x4dc00000, 0x4a0370e8, - 0x00000000, 0x42038000, 0x00007720, 0x0401fff0, - 0x42038000, 0x00007700, 0x0401ffed, 0x0201f800, - 0x00104e0d, 0x04020013, 0x4a038891, 0x0000ffff, - 0x497b8880, 0x497b8892, 0x42001000, 0x00000190, - 0x40000000, 0x40000000, 0x80081040, 0x040207fd, - 0x42000000, 0x0010b6a5, 0x0201f800, 0x0010a86e, - 0x0401f80e, 0x5c038000, 0x0201f000, 0x00104f29, - 0x0401f82d, 0x42000000, 0x0010b6a6, 0x0201f800, - 0x0010a86e, 0x0401f805, 0x48178892, 0x480b8880, - 0x5c038000, 0x1c01f000, 0x496fc857, 0x836c0580, - 0x00000003, 0x0402000b, 0x4c080000, 0x4c0c0000, - 0x42001000, 0x00008048, 0x42001800, 0x0000ffff, - 0x0201f800, 0x00103857, 0x5c001800, 0x5c001000, - 0x42000800, 0x0000003c, 0x0201f800, 0x00101395, - 0x59a8006c, 0x80000540, 0x04000006, 0x59a8106d, - 0x800811c0, 0x04000003, 0x0201f800, 0x00101b0a, - 0x4a038891, 0x0000ffff, 0x4a03900d, 0x00000040, - 0x0201f800, 0x001009db, 0x4a0370e8, 0x00000001, - 0x1c01f000, 0x5c000000, 0x4c000000, 0x4803c857, - 0x59c41080, 0x497b8880, 0x59c42892, 0x497b8892, - 0x0201f800, 0x00104e0d, 0x04020002, 0x1c01f000, - 0x42002000, 0x00000260, 0x59c418a4, 0x820c1d00, - 0x0000000f, 0x820c0580, 0x00000000, 0x04000010, - 0x59c41805, 0x820c1d00, 0x00000001, 0x0402000e, - 0x59c418a4, 0x820c1d00, 0x0000000f, 0x820c0480, - 0x00000007, 0x04001004, 0x820c0480, 0x0000000c, - 0x04001003, 0x80102040, 0x040207ec, 0x497b8891, - 0x1c01f000, 0x4c100000, 0x42002000, 0x00000019, - 0x46000000, 0x00000001, 0x0201f800, 0x001019a4, - 0x50001800, 0x820c1d00, 0x00000001, 0x04000005, - 0x80102040, 0x040207f7, 0x5c002000, 0x0401f7f0, - 0x5c002000, 0x0401f7ec, 0x4803c856, 0x1c01f000, - 0x4d2c0000, 0x59325808, 0x592c0a04, 0x4807c857, - 0x82040d00, 0x000000ff, 0x82040500, 0x0000000f, - 0x0c01f001, 0x00100fb5, 0x00100fb5, 0x00100fb5, - 0x00100fcd, 0x00100fb5, 0x00100fb5, 0x00100fb5, - 0x00100fb5, 0x00100fb5, 0x00100fcd, 0x00100fb5, - 0x00100fb7, 0x00100fb5, 0x00100fb5, 0x00100fb5, - 0x00100fb5, 0x0201f800, 0x00100615, 0x82040580, - 0x0000003b, 0x02020800, 0x00100615, 0x592c020a, - 0x8c000500, 0x0400005f, 0x592c1a07, 0x82040500, - 0x0000000f, 0x82000400, 0x0010110d, 0x50001000, - 0x50080000, 0x59302013, 0x4802600a, 0x492e600b, - 0x480a600c, 0x480e600d, 0x48126012, 0x5c025800, - 0x1c01f000, 0x82040500, 0x0000000f, 0x82000400, - 0x0010110d, 0x50001000, 0x50080000, 0x592c1a07, - 0x4802600a, 0x492e600b, 0x480a600c, 0x480e600d, - 0x497a6012, 0x0401f7f2, 0x8c040d00, 0x04020041, - 0x82040d00, 0x00000080, 0x0400003e, 0x0201f000, - 0x000200d0, 0x59300013, 0x59301012, 0x80080580, - 0x0402000c, 0x42007800, 0x80000005, 0x592c1208, - 0x82080500, 0xffff7fff, 0x48025a08, 0x8c08151e, - 0x0402002d, 0x823c7d40, 0x00000020, 0x0401f02a, - 0x480bc857, 0x42000000, 0x0010b64f, 0x0201f800, - 0x0010a86e, 0x59300414, 0x4803c857, 0x8c000514, - 0x04020007, 0x599c1819, 0x8c0c1d12, 0x04020004, - 0x820c1d40, 0x00000001, 0x0401f01d, 0x59302013, - 0x0401f92d, 0x0402001a, 0x42007800, 0x80000005, - 0x5930500d, 0x592c0208, 0x4803c857, 0x8c00051e, - 0x04020005, 0x823c7d40, 0x00000020, 0x5930400c, - 0x0401f004, 0x8400051e, 0x48025a08, 0x0401f8dc, - 0x50201800, 0x480e600a, 0x4832600b, 0x4822600c, - 0x482a600d, 0x480fc857, 0x4833c857, 0x4823c857, - 0x482bc857, 0x80000580, 0x483e6004, 0x1c01f000, - 0x0201f800, 0x00100615, 0x4933c857, 0x4d2c0000, - 0x59900004, 0x81300580, 0x02020800, 0x00100615, - 0x0201f800, 0x00108df4, 0x02000800, 0x00100615, - 0x59325808, 0x4d3c0000, 0x4d400000, 0x59300004, - 0x4803c857, 0x4c000000, 0x0201f800, 0x00106b13, - 0x0201f800, 0x001068c1, 0x5c000000, 0x8c000516, - 0x04000010, 0x592c000f, 0x4803c857, 0x48025807, - 0x41780800, 0x42028000, 0x00000002, 0x0201f800, - 0x00104bee, 0x4a025c06, 0x0000ffff, 0x0201f800, - 0x00020381, 0x0201f800, 0x00107698, 0x0401f015, - 0x4a026203, 0x00000002, 0x592c0208, 0x8400054e, - 0x48025a08, 0x59300406, 0x82000580, 0x00000006, - 0x04020009, 0x811800ca, 0x81c80c00, 0x58040939, - 0x592c000d, 0x80040480, 0x592c080f, 0x80040480, - 0x4802580b, 0x417a7800, 0x0201f800, 0x00108997, - 0x5c028000, 0x5c027800, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x4d2c0000, 0x59900004, 0x81300580, - 0x02020800, 0x00100615, 0x0201f800, 0x00108df4, - 0x02000800, 0x00100615, 0x59325808, 0x592c0208, - 0x84000540, 0x48025a08, 0x0401f7bf, 0x491bc857, - 0x49d3c857, 0x4dd00000, 0x41780800, 0x8007a0ca, - 0x83d3a400, 0x00007600, 0x4a03a005, 0x80000002, - 0x42000000, 0x00001000, 0x50000000, 0x82000480, - 0x24220001, 0x04020029, 0x59d01006, 0x82080500, - 0x00006000, 0x82000580, 0x00006000, 0x04000031, - 0x82080500, 0x40008000, 0x040007f8, 0x800409c0, - 0x0402002c, 0x811a31c0, 0x0400002a, 0x42000000, - 0x00001002, 0x50001000, 0x46000000, 0x00000512, - 0x42001800, 0x0000000a, 0x59e00000, 0x8c00051a, - 0x040207fc, 0x800c1840, 0x040207fc, 0x42000000, - 0x00001002, 0x46000000, 0x00000514, 0x42001800, - 0x0000000a, 0x59e00000, 0x8c00053a, 0x040207fc, - 0x800c1840, 0x040207fc, 0x42000000, 0x00001002, - 0x44080000, 0x0401f00f, 0x02004800, 0x000207c8, - 0x59d01006, 0x82080500, 0x00006000, 0x82000580, - 0x00006000, 0x04000007, 0x8c08151e, 0x040007f7, - 0x59d01006, 0x82080500, 0x00006000, 0x040207f3, - 0x83d3a400, 0x00000020, 0x80040800, 0x82040480, - 0x00000005, 0x040017bd, 0x5c03a000, 0x1c01f000, - 0x491bc857, 0x49d3c857, 0x4dd00000, 0x41780800, - 0x8007a0ca, 0x83d3a400, 0x00007600, 0x4a03a005, - 0x80000001, 0x59d00006, 0x83d3a400, 0x00000020, - 0x80040800, 0x82040480, 0x00000005, 0x040017f8, - 0x5c03a000, 0x1c01f000, 0x59d00006, 0x8c00053e, - 0x0400001e, 0x59902804, 0x4817c857, 0x801429c0, - 0x04000013, 0x5990000a, 0x5990080b, 0x5990100c, - 0x5990180d, 0x4800280a, 0x4804280b, 0x4808280c, - 0x480c280d, 0x59d00000, 0x59d00801, 0x59d01002, - 0x59d01803, 0x59d02004, 0x4800280e, 0x4804280f, - 0x48082810, 0x480c2811, 0x48102812, 0x59900006, - 0x82000500, 0xffff0000, 0x48032006, 0x4a03a005, - 0x30000000, 0x59d00006, 0x1c01f000, 0x4803c856, - 0x80204000, 0x50200000, 0x80000540, 0x04000003, - 0x80285040, 0x1c01f000, 0x58300001, 0x80000540, - 0x0400000e, 0x4802600b, 0x40006000, 0x58300204, - 0x82000500, 0x0000000f, 0x82000400, 0x0010110d, - 0x50004000, 0x802041c0, 0x02000800, 0x00100615, - 0x80285040, 0x1c01f000, 0x40005000, 0x1c01f000, - 0x00000005, 0x00000008, 0x0000000b, 0x0000000e, - 0x00000011, 0x00000000, 0x00000000, 0x0000000b, - 0x00000000, 0x00000000, 0x00000000, 0x00101108, - 0x00101107, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00101108, 0x00101107, 0x00101104, - 0x00101108, 0x00101107, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00101108, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00101108, 0x00101108, 0x00101108, - 0x00000000, 0x00101108, 0x00000000, 0x00000000, - 0x00000000, 0x4813c857, 0x492fc857, 0x4933c857, - 0x48126012, 0x592c5207, 0x802851c0, 0x0400004a, - 0x412c6000, 0x0401f84b, 0x04000009, 0x82240580, - 0x00000002, 0x04020003, 0x5830000d, 0x80102480, - 0x50200000, 0x80004540, 0x0400003f, 0x50200000, - 0x80000540, 0x0400000b, 0x80301400, 0x58080002, - 0x80102480, 0x0400101e, 0x801021c0, 0x04000009, - 0x80285040, 0x04000034, 0x80204000, 0x0401f7f4, - 0x58300001, 0x80006540, 0x0400002f, 0x0401f7e6, - 0x80285040, 0x0400002c, 0x80204000, 0x50200000, - 0x80000540, 0x0402000a, 0x58300001, 0x80006540, - 0x04000025, 0x58300204, 0x82004d00, 0x0000000f, - 0x82244400, 0x0010110d, 0x50204000, 0x592c0208, - 0x8400051e, 0x48025a08, 0x0401f013, 0x80102080, - 0x80102000, 0x48126010, 0x4813c857, 0x58080802, - 0x40100000, 0x80042480, 0x02001800, 0x00100615, - 0x58080000, 0x58081801, 0x80102400, 0x4812600e, - 0x480e600f, 0x4813c857, 0x592c0208, 0x8400055e, - 0x48025a08, 0x4833c857, 0x4823c857, 0x482bc857, - 0x4832600b, 0x4822600c, 0x482a600d, 0x80000580, - 0x0401f003, 0x82000540, 0x00000001, 0x1c01f000, - 0x58300204, 0x82004d00, 0x0000000f, 0x82244400, - 0x0010110d, 0x82000500, 0x000000ff, 0x82000580, - 0x00000029, 0x0402001b, 0x50204000, 0x592c0409, - 0x80000540, 0x02000800, 0x00100615, 0x82000c80, - 0x00000002, 0x04001011, 0x58300001, 0x80006540, - 0x02000800, 0x00100615, 0x58300204, 0x82000500, - 0x0000000f, 0x82000400, 0x0010110d, 0x50004000, - 0x40040000, 0x800409c0, 0x04000006, 0x82040c80, - 0x00000005, 0x040217f1, 0x80204400, 0x80000580, - 0x1c01f000, 0x59e00004, 0x8c00050e, 0x02020000, - 0x00100951, 0x1c01f000, 0x4c5c0000, 0x59e4b800, - 0x485fc857, 0x825c0500, 0x0000001f, 0x04000004, - 0x59e40862, 0x0201f800, 0x00100615, 0x825c0500, - 0x000000e0, 0x02000800, 0x00100615, 0x8c5cbd0e, - 0x04020807, 0x8c5cbd0c, 0x04020809, 0x8c5cbd0a, - 0x04020878, 0x5c00b800, 0x1c01f000, 0x4803c856, - 0x4a03c800, 0x00000080, 0x1c01f000, 0x4d2c0000, - 0x42007800, 0x0010b6eb, 0x583c0001, 0x583c0802, - 0x80040540, 0x0400003f, 0x42000800, 0x0010b5f5, - 0x50065800, 0x592c0002, 0x82000580, 0x00000000, - 0x0400000e, 0x59e40850, 0x59e41853, 0x400c0000, - 0x80040400, 0x59e40852, 0x4807c857, 0x80041480, - 0x04021008, 0x40001000, 0x480bc857, 0x4a007800, - 0x00000001, 0x0401f006, 0x4803c857, 0x0401f029, - 0x59e41050, 0x480bc857, 0x49787800, 0x480bc857, - 0x480fc857, 0x592c0003, 0x80000540, 0x04000006, - 0x80080580, 0x04020004, 0x592c0003, 0x4803c857, - 0x480bc857, 0x480a5803, 0x592c0007, 0x800001c0, - 0x04000007, 0x592c1007, 0x480bc857, 0x583c0003, - 0x4803c857, 0x80080480, 0x04001003, 0x583c1001, - 0x480bc857, 0x583c0802, 0x480bc857, 0x4807c857, - 0x4a025801, 0x00000000, 0x4a025809, 0x0010120c, - 0x480a5807, 0x48065808, 0x59e40053, 0x48025804, - 0x412c1000, 0x492fc857, 0x0201f800, 0x001008a1, - 0x5c025800, 0x4a03c800, 0x00000040, 0x1c01f000, - 0x42007800, 0x0010b5f5, 0x503c7800, 0x4a007802, - 0x00000100, 0x42007800, 0x0010b6eb, 0x583c0000, - 0x4803c857, 0x82000d80, 0x00000001, 0x04000004, - 0x80000000, 0x48007800, 0x0401f019, 0x49787800, - 0x583c1806, 0x583c0005, 0x800c1800, 0x480c7806, - 0x800c0580, 0x04020002, 0x49787806, 0x583c0807, - 0x800409c0, 0x0400000e, 0x583c0008, 0x80000000, - 0x48007808, 0x80040580, 0x04020009, 0x49787808, - 0x583c2006, 0x42001800, 0x00000001, 0x42001000, - 0x00008028, 0x0201f800, 0x00103857, 0x1c01f000, - 0x4a03c800, 0x00000020, 0x0201f800, 0x0010a867, - 0x59e40000, 0x1c01f000, 0x4d2c0000, 0x4a007001, - 0x00000000, 0x82040d00, 0x43000f80, 0x02020800, - 0x00100615, 0x58380009, 0x4803c00f, 0x0201f800, - 0x001091cb, 0x583a5808, 0x592c0000, 0x48007008, - 0x800001c0, 0x04020002, 0x49787007, 0x0201f800, - 0x0010083a, 0x5c025800, 0x0201f000, 0x001008c6, - 0x4803c856, 0x4c3c0000, 0x4d2c0000, 0x4d300000, - 0x5830000a, 0x80025d40, 0x02000800, 0x00100615, - 0x592e6008, 0x4c300000, 0x0201f800, 0x001091e3, - 0x5c006000, 0x02000800, 0x00100615, 0x58300002, - 0x82000580, 0x00000100, 0x04020010, 0x5930780b, - 0x583c0001, 0x80000540, 0x0400000e, 0x4802600b, - 0x40007800, 0x82000400, 0x00000002, 0x48006003, - 0x583c0000, 0x48006004, 0x40301000, 0x0201f800, - 0x001008a1, 0x0401f00c, 0x4a025a06, 0x00000002, - 0x4c300000, 0x0201f800, 0x00020381, 0x5c006000, - 0x40325800, 0x0201f800, 0x0010083a, 0x0201f800, - 0x000208b4, 0x5c026000, 0x5c025800, 0x5c007800, - 0x1c01f000, 0x4803c856, 0x4d2c0000, 0x4d300000, - 0x42007000, 0x0010b5f6, 0x58380801, 0x82040580, - 0x00000002, 0x04020011, 0x58386002, 0x5830000a, - 0x812c0580, 0x0402000d, 0x59e00004, 0x8c00050e, - 0x040007fe, 0x59dc0006, 0x4803c857, 0x4a03b805, - 0x20000000, 0x8c00053e, 0x040007f8, 0x4a007001, - 0x00000000, 0x0401f019, 0x58386006, 0x40305000, - 0x803061c0, 0x02000800, 0x00100615, 0x5830000a, - 0x812c0580, 0x04000004, 0x40305000, 0x58306000, - 0x0401f7f8, 0x40280000, 0x80300580, 0x58300000, - 0x04000006, 0x48005000, 0x800001c0, 0x04020007, - 0x48287005, 0x0401f005, 0x800001c0, 0x04020002, - 0x48007005, 0x48007006, 0x40325800, 0x0201f800, - 0x0010083a, 0x42007000, 0x0010b5f6, 0x58380001, - 0x82000580, 0x00000000, 0x02000800, 0x001008c6, - 0x5c026000, 0x5c025800, 0x1c01f000, 0x4803c856, - 0x42000800, 0x0000003c, 0x48079000, 0x59c80000, - 0x80040500, 0x040207fe, 0x497b9005, 0x4a039035, - 0x00880200, 0x59a8000e, 0x800000e0, 0x4803900e, - 0x4a039011, 0x00000024, 0x4a03900f, 0x0010cfc0, - 0x4a039010, 0x0010cfc0, 0x4a039015, 0x0000007f, - 0x4a03900d, 0x00000040, 0x4a039000, 0x00001600, - 0x1c01f000, 0x59c80007, 0x8c000508, 0x040208b7, - 0x59c80800, 0x8c040d16, 0x04020004, 0x82000500, - 0x00000006, 0x0c01f005, 0x4807c857, 0x82000500, - 0x0000000e, 0x0c01f001, 0x001012f8, 0x001012f6, - 0x0010567d, 0x001012f6, 0x001012fa, 0x001012f6, - 0x001012fa, 0x001012fa, 0x001012f6, 0x001012f6, - 0x001012f6, 0x001012f6, 0x001012fa, 0x001012f6, - 0x001012fa, 0x001012f6, 0x0201f800, 0x00100615, - 0x4803c857, 0x1c01f000, 0x59c8080c, 0x4807c857, - 0x82040500, 0x00006000, 0x04000004, 0x0201f800, - 0x0010a82a, 0x0401f006, 0x82040500, 0x007f0000, - 0x04000006, 0x0201f800, 0x0010a7fc, 0x0201f800, - 0x00106c07, 0x0401f02b, 0x82040500, 0x00000014, - 0x04000014, 0x0201f800, 0x0010a859, 0x836c0580, - 0x00000003, 0x0400000d, 0x0201f800, 0x00104e0d, - 0x04000004, 0x0201f800, 0x00103f37, 0x0401f007, - 0x4a035033, 0x00000001, 0x4202d800, 0x00000001, - 0x0201f800, 0x00104d76, 0x0401f817, 0x0401f015, - 0x82040500, 0x00001c00, 0x04000005, 0x0201f800, - 0x0010a838, 0x0401f810, 0x0401f00e, 0x82040500, - 0x00000140, 0x04000005, 0x0201f800, 0x0010a84b, - 0x0401f809, 0x0401f007, 0x82040500, 0x00008000, - 0x04000004, 0x0201f800, 0x0010a823, 0x0401f802, - 0x1c01f000, 0x4c0c0000, 0x4c100000, 0x4c140000, - 0x0201f800, 0x00100f17, 0x5c002800, 0x5c002000, - 0x5c001800, 0x1c01f000, 0x4803c856, 0x59a80804, - 0x59a8002b, 0x82000500, 0xfffff000, 0x80040540, - 0x4803502b, 0x59a8002f, 0x82000500, 0xfffff000, - 0x80040540, 0x4803502f, 0x48078882, 0x82041c00, - 0x0000000f, 0x800c1908, 0x820c1c00, 0x00000004, - 0x400c2000, 0x901029c0, 0x82040480, 0x000001e4, - 0x04021005, 0x42001000, 0x00000008, 0x801020c6, - 0x0401f031, 0x82040480, 0x00000230, 0x04021009, - 0x42001000, 0x00000007, 0x801000c2, 0x800000c2, - 0x80100400, 0x80100400, 0x80102400, 0x0401f026, - 0x82040480, 0x00000298, 0x04021008, 0x42001000, - 0x00000006, 0x801000c2, 0x800000c2, 0x80100400, - 0x80102400, 0x0401f01c, 0x82040480, 0x00000328, - 0x04021007, 0x42001000, 0x00000005, 0x801000c2, - 0x800000c2, 0x80102400, 0x0401f013, 0x82040480, - 0x00000404, 0x04021005, 0x42001000, 0x00000004, - 0x801020c4, 0x0401f00c, 0x82040480, 0x0000056c, - 0x04021006, 0x42001000, 0x00000003, 0x801000c2, - 0x80102400, 0x0401f004, 0x42001000, 0x00000002, - 0x801020c2, 0x82100480, 0x00000110, 0x80000080, - 0x80002000, 0x800800d0, 0x80140540, 0x80100540, - 0x48039035, 0x1c01f000, 0x59c80815, 0x0201f800, - 0x0010060d, 0x82040d00, 0x0000007c, 0x48079000, - 0x59c80000, 0x80040500, 0x040207fe, 0x8c040d04, - 0x04000003, 0x59c80035, 0x48039035, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x1c01f000, - 0x4803c856, 0x497b88a9, 0x4a038807, 0x00000001, - 0x497b8807, 0x59c40005, 0x48038805, 0x0201f800, - 0x00101886, 0x4201d000, 0x000001f4, 0x0201f800, - 0x00105dd2, 0x497b880e, 0x4200b000, 0x000001f4, - 0x42000000, 0x00000001, 0x42000800, 0x00000014, - 0x0201f800, 0x001019b1, 0x42000800, 0x00000014, - 0x0201f800, 0x001019ac, 0x8c040d00, 0x04000005, - 0x8058b040, 0x040207f3, 0x0201f800, 0x00100615, - 0x4200b000, 0x00000032, 0x42000000, 0x00000001, - 0x42000800, 0x000000b4, 0x0201f800, 0x001019b1, - 0x42000800, 0x000000b4, 0x0201f800, 0x001019ac, - 0x8c040d00, 0x04000005, 0x8058b040, 0x040207f3, - 0x0201f800, 0x00100615, 0x59c40005, 0x48038805, - 0x42000000, 0x00000089, 0x800008d0, 0x48075054, - 0x48075055, 0x48075056, 0x42000800, 0x000000e0, - 0x0201f800, 0x001019b1, 0x42000800, 0x000000f4, - 0x0201f800, 0x001019ac, 0x82040500, 0xffffffd1, - 0x82000540, 0x00000002, 0x42000800, 0x000000f4, - 0x0201f800, 0x001019b1, 0x42000800, 0x000000a0, - 0x0201f800, 0x001019ac, 0x82040540, 0x00000001, - 0x42000800, 0x000000a0, 0x0201f800, 0x001019b1, - 0x42000800, 0x00000000, 0x0201f800, 0x001019ac, - 0x82040540, 0x00000001, 0x42000800, 0x00000000, - 0x0201f800, 0x001019b1, 0x4201d000, 0x0001d4c0, - 0x0201f800, 0x00105dd2, 0x0401fa45, 0x4a0388a7, - 0x0000f7f7, 0x4a0388a3, 0x8000403c, 0x4a0388ae, - 0x000061a8, 0x4a038801, 0x00032063, 0x4a038810, - 0x00410108, 0x4a038811, 0x00520608, 0x4a038812, - 0x00450320, 0x4a038813, 0x00440405, 0x4a03881c, - 0x004132e1, 0x4a038850, 0x80000108, 0x4a038860, - 0x00000008, 0x4a038870, 0x00000008, 0x4a038851, - 0x80000508, 0x4a038861, 0x00800000, 0x4a038871, - 0x00800000, 0x4a038852, 0x80000708, 0x4a038862, - 0x00800000, 0x4a038872, 0x00800000, 0x4a038853, - 0x80000608, 0x497b8863, 0x4a038873, 0x00800000, - 0x4a038882, 0x00000840, 0x4a0388a5, 0x0000001e, - 0x4a0388a6, 0x0000001e, 0x4a0388b0, 0x00007530, - 0x4a038802, 0x0000ffff, 0x4a038806, 0xc0e00800, - 0x1c01f000, 0x497b5022, 0x4a035021, 0x00000001, - 0x42000800, 0x00000040, 0x0201f800, 0x001019ac, - 0x82040500, 0xffffffaf, 0x82000540, 0x00000000, - 0x42000800, 0x00000040, 0x0201f800, 0x001019b1, - 0x42000800, 0x000000f4, 0x0201f800, 0x001019ac, - 0x4c040000, 0x40040000, 0x84000548, 0x42000800, - 0x000000f4, 0x0201f800, 0x001019b1, 0x42000800, - 0x00000000, 0x0201f800, 0x001019ac, 0x82040500, - 0xffffffc1, 0x82000540, 0x00000038, 0x42000800, - 0x00000000, 0x0201f800, 0x001019b1, 0x5c000000, - 0x42000800, 0x000000f4, 0x0201f000, 0x001019b1, - 0x59c40805, 0x59c40006, 0x80040d00, 0x02000800, - 0x00100615, 0x82040500, 0x00e00800, 0x04020004, - 0x8c040d3e, 0x040208df, 0x0401f007, 0x82040500, - 0x00800800, 0x02020800, 0x0010060d, 0x0201f800, - 0x00100615, 0x4c5c0000, 0x4c600000, 0x59c4b805, - 0x59c40006, 0x8c000500, 0x04000003, 0x8c5cbd00, - 0x04020095, 0x485fc857, 0x0201f800, 0x00104e0d, - 0x0400001e, 0x59c40005, 0x82000500, 0x000000c0, - 0x0400004b, 0x0201f800, 0x00104e23, 0x04020048, - 0x59c40006, 0x82000500, 0x000000f0, 0x04020004, - 0x4a038805, 0x000000c0, 0x0401f041, 0x59a80015, - 0x84000506, 0x48035015, 0x42006000, 0xff203fff, - 0x42006800, 0x40000000, 0x0201f800, 0x001040ad, - 0x42000800, 0x00000010, 0x42001000, 0x00104020, - 0x0201f800, 0x00105dc7, 0x8c5cbd34, 0x04020030, - 0x4a035032, 0x0000aaaa, 0x59c40005, 0x8c00050c, - 0x04020012, 0x8c00050e, 0x0402001c, 0x8c00050a, - 0x0402001d, 0x8c000508, 0x0400000b, 0x59a80017, - 0x82000580, 0x00000009, 0x04020007, 0x42000000, - 0x0010b642, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x00104fe9, 0x0401f05a, 0x0201f800, 0x00104e23, - 0x04020007, 0x42000800, 0x0000000f, 0x42001000, - 0x00103f37, 0x0201f800, 0x00105da7, 0x4a035033, - 0x00000000, 0x0401f00b, 0x4a035033, 0x00000002, - 0x0401f008, 0x42000000, 0x0010b644, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00104f93, 0x0401f044, - 0x0201f800, 0x00105049, 0x0401f041, 0x8c5cbd34, - 0x0400003d, 0x59c40005, 0x8c00053a, 0x04020005, - 0x42000000, 0x0010b616, 0x0201f800, 0x0010a86e, - 0x4a038805, 0x02000000, 0x0201f800, 0x00104e0d, - 0x04020010, 0x4a038805, 0x04000000, 0x0201f800, - 0x00104e1b, 0x04020008, 0x4a035033, 0x00000001, - 0x4202d800, 0x00000001, 0x0201f800, 0x00104d76, - 0x0401f061, 0x41780000, 0x0201f800, 0x00104de5, - 0x0201f800, 0x00101a59, 0x4000c000, 0x0201f800, - 0x001019d0, 0x836c1580, 0x00000004, 0x0402000d, - 0x8c5cbd00, 0x04020018, 0x59a81005, 0x8c081506, - 0x04020005, 0x59c410a3, 0x82081540, 0x00000008, - 0x480b88a3, 0x59c41006, 0x84081540, 0x480b8806, - 0x4a038805, 0x04000000, 0x4202d800, 0x00000001, - 0x497b5014, 0x59a80005, 0x8c000518, 0x04020004, - 0x0401f95c, 0x0201f800, 0x00103f5c, 0x0201f800, - 0x00103951, 0x8c5cbd3c, 0x04020858, 0x8c5cbd00, - 0x04000036, 0x42000000, 0x0010b6c9, 0x0201f800, - 0x0010a86e, 0x4a038805, 0x00000001, 0x4200b000, - 0x00000352, 0x4201d000, 0x00000064, 0x4c580000, - 0x0201f800, 0x00105dd2, 0x0201f800, 0x00101941, - 0x5c00b000, 0x04000004, 0x8058b040, 0x040207f6, - 0x0401f004, 0x4a038805, 0x00000001, 0x0401f01f, - 0x59c40006, 0x84000500, 0x48038806, 0x0201f800, - 0x00106c32, 0x497b8880, 0x0201f800, 0x0010a7e7, - 0x59c4000d, 0x8c000500, 0x02020800, 0x0010a7f5, - 0x59c400a3, 0x82000500, 0xfcf8ffff, 0x480388a3, - 0x4a03504c, 0x00000002, 0x4202d800, 0x00000004, - 0x4a038805, 0x00000001, 0x0201f800, 0x0010071a, - 0x0401fb42, 0x497b5052, 0x4a035049, 0x00000001, - 0x0201f800, 0x0010048c, 0x825cbd00, 0xbbfffffe, - 0x485f8805, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x59c41004, 0x480bc857, 0x8c081500, 0x04000006, - 0x4803c856, 0x497b2807, 0x0201f800, 0x00106cf9, - 0x0401f00a, 0x82080500, 0x000001f0, 0x04000007, - 0x4803c856, 0x417a3000, 0x0201f800, 0x00105d9b, - 0x0201f800, 0x00106d1b, 0x4a038805, 0x80000000, - 0x1c01f000, 0x59c408a3, 0x4807c857, 0x84040d40, - 0x480788a3, 0x1c01f000, 0x4d900000, 0x4dd00000, - 0x4da40000, 0x4d140000, 0x4a038805, 0x40000000, - 0x42000000, 0x0010b6c5, 0x0201f800, 0x0010a86e, - 0x0201f800, 0x0010698c, 0x59c41004, 0x8c081500, - 0x04000054, 0x598e600d, 0x497b2807, 0x813261c0, - 0x04000032, 0x59300403, 0x82000580, 0x00000032, - 0x0402002e, 0x5930001c, 0x48038833, 0x4a038807, - 0x00018000, 0x4201d000, 0x00000002, 0x0201f800, - 0x00105dd2, 0x497b8807, 0x4201d000, 0x00000002, - 0x0201f800, 0x00105dd2, 0x0201f800, 0x00106b71, - 0x4201d000, 0x00007530, 0x0201f800, 0x00105dd2, - 0x59c408a4, 0x82040d00, 0x0000000f, 0x82040d80, - 0x00000000, 0x04000005, 0x42000000, 0x00200000, - 0x0201f800, 0x001019b6, 0x0201f800, 0x001068f6, - 0x59300008, 0x80000540, 0x02000800, 0x00100615, - 0x40025800, 0x4a025a04, 0x00000103, 0x5931d821, - 0x58ef400b, 0x58ec0009, 0x0801f800, 0x0201f800, - 0x000208b4, 0x0401f047, 0x598c000f, 0x82001c80, - 0x000000c8, 0x0402100f, 0x80000000, 0x4803180f, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, - 0x00000002, 0x04020004, 0x42000000, 0x00200000, - 0x0401fbfa, 0x0201f800, 0x00105d86, 0x0401f035, - 0x4933c857, 0x0201f800, 0x00106b71, 0x813261c0, - 0x04000030, 0x4a026203, 0x00000001, 0x42027000, - 0x00000027, 0x0201f800, 0x000208d8, 0x0401f029, - 0x8c081508, 0x04000027, 0x417a3000, 0x0201f800, - 0x00106e2f, 0x42032000, 0x0000bf32, 0x0201f800, - 0x00105d9b, 0x59926004, 0x813261c0, 0x04000012, - 0x42001800, 0x000000c8, 0x0201f800, 0x00106dfb, - 0x0402000d, 0x59c400a4, 0x82000500, 0x0000000f, - 0x82000580, 0x00000002, 0x04020004, 0x42000000, - 0x00200000, 0x0401fbd1, 0x0201f800, 0x00105d8b, - 0x0401f00c, 0x4933c857, 0x0201f800, 0x00106b13, - 0x813261c0, 0x04000007, 0x42027000, 0x0000004f, - 0x4a026203, 0x00000003, 0x0201f800, 0x000208d8, - 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, - 0x0201f000, 0x00106982, 0x4803c857, 0x59a80821, - 0x48035021, 0x80041580, 0x04000045, 0x800409c0, - 0x04000023, 0x497b504c, 0x42000000, 0x0010b60b, - 0x0201f800, 0x0010a86e, 0x0201f800, 0x0010a920, - 0x42001000, 0x00008011, 0x59c40001, 0x82000500, - 0x00018000, 0x82001d80, 0x00000000, 0x04000009, - 0x82001d80, 0x00008000, 0x04000009, 0x82001d80, - 0x00010000, 0x04000009, 0x0201f800, 0x00100615, - 0x42001800, 0x00000000, 0x0401f006, 0x42001800, - 0x00000001, 0x0401f003, 0x42001800, 0x00000003, - 0x0201f800, 0x00103857, 0x0401f021, 0x59a8084c, - 0x800409c0, 0x04020007, 0x59c4000d, 0x8c000520, - 0x04000004, 0x42001800, 0x00000003, 0x0401f002, - 0x40041800, 0x0201f800, 0x0010a904, 0x42001000, - 0x00008012, 0x0201f800, 0x00103857, 0x0201f800, - 0x0010071a, 0x0201f800, 0x0010a95a, 0x0402000c, - 0x0401f853, 0x4d400000, 0x4d3c0000, 0x42028000, - 0x00000028, 0x42027800, 0x00000008, 0x0201f800, - 0x00101d90, 0x5c027800, 0x5c028000, 0x1c01f000, - 0x4803c857, 0x82000400, 0x00101eb5, 0x50000800, - 0x82040d00, 0x000000ff, 0x1c01f000, 0x4803c856, - 0x4c580000, 0x4200b000, 0x00000010, 0x497b88ac, - 0x497b88ad, 0x8058b040, 0x040207fe, 0x5c00b000, - 0x1c01f000, 0x4807c857, 0x48075010, 0x80041108, - 0x4200b000, 0x00000010, 0x497b88ac, 0x80000580, - 0x800811c0, 0x04020006, 0x82040500, 0x0000000f, - 0x82000400, 0x0010a95f, 0x50000000, 0x480388ad, - 0x80081040, 0x8058b040, 0x040207f5, 0x1c01f000, - 0x59a80005, 0x04000003, 0x84000546, 0x0401f002, - 0x84000506, 0x48035005, 0x4803c857, 0x1c01f000, - 0x4803c857, 0x4c080000, 0x4c040000, 0x4c000000, - 0x59c40892, 0x4807c857, 0x80041580, 0x04000010, - 0x80041480, 0x04021007, 0x80081080, 0x80081000, - 0x4008b000, 0x42000000, 0x00000201, 0x0401f004, - 0x4008b000, 0x42000000, 0x00000210, 0x48038886, - 0x8058b040, 0x040207fe, 0x497b8886, 0x5c000000, - 0x5c000800, 0x5c001000, 0x1c01f000, 0x4803c856, - 0x0201f800, 0x0010393e, 0x04000005, 0x42028000, - 0x0000002e, 0x0201f000, 0x0010a25b, 0x1c01f000, - 0x59a8086f, 0x82040500, 0x00000010, 0x04000004, - 0x42000800, 0x00000002, 0x0401f010, 0x82040500, - 0x00000020, 0x42000800, 0x00000002, 0x0402000b, - 0x59c80835, 0x82040d00, 0x00001f00, 0x80040910, - 0x80040800, 0x59a8006c, 0x80000540, 0x04000003, - 0x42000800, 0x0000025a, 0x4807c857, 0x1c01f000, - 0x4c000000, 0x59a80053, 0x4803c857, 0x82000580, - 0x00000000, 0x5c000000, 0x1c01f000, 0x4c000000, - 0x59a80053, 0x4803c857, 0x82000580, 0x00000001, - 0x5c000000, 0x1c01f000, 0x4c000000, 0x59a80053, - 0x4803c857, 0x82000580, 0x00000003, 0x5c000000, - 0x1c01f000, 0x4c000000, 0x59a80053, 0x82000580, - 0x00000002, 0x5c000000, 0x1c01f000, 0x4c000000, - 0x4c040000, 0x4c080000, 0x4c380000, 0x59a80040, - 0x82000c80, 0x00000007, 0x02021800, 0x00100615, - 0x0c01f806, 0x5c007000, 0x5c001000, 0x5c000800, - 0x5c000000, 0x1c01f000, 0x001016dd, 0x001016f0, - 0x00101704, 0x00101706, 0x0010172d, 0x0010172f, - 0x00101731, 0x4803c856, 0x4a035042, 0x00000000, - 0x42000000, 0x00000002, 0x0401fa18, 0x42000000, - 0x00000002, 0x0401f9ad, 0x0401faae, 0x4803c856, - 0x4a035040, 0x00000006, 0x42000800, 0x0000001e, - 0x42001000, 0x00101732, 0x0201f000, 0x00105da7, - 0x497b5045, 0x4a035050, 0x00000036, 0x4a03504f, - 0x0000002a, 0x4803c856, 0x4a035042, 0x00000001, - 0x42000000, 0x00000002, 0x0401f998, 0x4803c856, - 0x4a035040, 0x00000006, 0x42000800, 0x0000001e, - 0x42001000, 0x00101732, 0x0201f000, 0x00105da7, - 0x0201f800, 0x00100615, 0x4a035050, 0x00000036, - 0x4803c856, 0x4a035042, 0x00000003, 0x42000800, - 0x00000000, 0x0401fa9f, 0x82040d00, 0x00000090, - 0x82040580, 0x00000090, 0x04000009, 0x82040580, - 0x00000010, 0x04000009, 0x82040580, 0x00000000, - 0x04000008, 0x0201f800, 0x00100615, 0x42000000, - 0x00000001, 0x0401f005, 0x41780000, 0x0401f003, - 0x42000000, 0x00000002, 0x0401f970, 0x497b5046, - 0x4803c856, 0x4a035040, 0x00000006, 0x42000800, - 0x0000001e, 0x42001000, 0x00101732, 0x0201f000, - 0x00105da7, 0x0201f800, 0x00100615, 0x0201f800, - 0x00100615, 0x1c01f000, 0x4c000000, 0x4c040000, - 0x4c080000, 0x4c380000, 0x59a80042, 0x82000c80, - 0x00000007, 0x02021800, 0x00100615, 0x0c01f806, - 0x5c007000, 0x5c001000, 0x5c000800, 0x5c000000, - 0x1c01f000, 0x00101748, 0x00101767, 0x001017bb, - 0x001017d2, 0x001017e9, 0x001017f2, 0x001017f4, - 0x0401f9f9, 0x0402001b, 0x59a81048, 0x42000800, - 0x00000000, 0x0401fa5f, 0x82040d00, 0x00000090, - 0x82040580, 0x00000090, 0x04000009, 0x82040580, - 0x00000010, 0x04000008, 0x82040580, 0x00000000, - 0x04000007, 0x0201f800, 0x00100615, 0x84081540, - 0x0401f004, 0x84081542, 0x0401f002, 0x84081544, - 0x480b5048, 0x4a035040, 0x00000001, 0x0401f003, - 0x0401f8cb, 0x0401ff82, 0x1c01f000, 0x0401f88f, - 0x04000052, 0x0401f9d8, 0x0402002a, 0x42000800, - 0x00000000, 0x0401fa3f, 0x82040d00, 0x00000090, - 0x82040580, 0x00000000, 0x04000044, 0x82040580, - 0x00000010, 0x04000006, 0x82040580, 0x00000090, - 0x04000009, 0x0201f800, 0x00100615, 0x59c40801, - 0x82040d00, 0x00018000, 0x82040580, 0x00000000, - 0x04000036, 0x42000800, 0x00000000, 0x0401fa29, - 0x82040d00, 0x00000090, 0x82040580, 0x00000010, - 0x04000006, 0x82040580, 0x00000090, 0x04000006, - 0x02020800, 0x00100615, 0x59a80048, 0x84000542, - 0x0401f003, 0x59a80048, 0x84000540, 0x48035048, - 0x59a80045, 0x80000000, 0x48035045, 0x82000580, - 0x00000005, 0x04000003, 0x0401f861, 0x0401f01e, - 0x497b5045, 0x59c40801, 0x82040d00, 0x00018000, - 0x82040580, 0x00000000, 0x04000009, 0x82040580, - 0x00008000, 0x04000009, 0x82040580, 0x00010000, - 0x04000008, 0x0201f800, 0x00100615, 0x42000000, - 0x00000001, 0x0401f005, 0x41780000, 0x0401f003, - 0x42000000, 0x00000002, 0x0401f948, 0x4a035042, - 0x00000002, 0x0401f004, 0x4a035040, 0x00000003, - 0x0401f002, 0x0401ff42, 0x1c01f000, 0x0401f83b, - 0x04000015, 0x59a8004f, 0x80000040, 0x4803504f, - 0x0401f981, 0x04020005, 0x4a035040, 0x00000003, - 0x497b5041, 0x0401f00c, 0x59a8004f, 0x80000540, - 0x04020003, 0x0401f89e, 0x0401f002, 0x0401f84b, - 0x0401f82f, 0x497b5045, 0x4a035042, 0x00000001, - 0x0401ff2b, 0x1c01f000, 0x0401f824, 0x04000015, - 0x0401f96d, 0x0402000f, 0x59a80046, 0x80000000, - 0x48035046, 0x82000580, 0x00000007, 0x0402000c, - 0x4a035052, 0x0000000a, 0x497b5049, 0x59a80048, - 0x8400055e, 0x48035048, 0x4803c857, 0x0401f005, - 0x0401f817, 0x4a035042, 0x00000004, 0x0401ff3d, - 0x1c01f000, 0x0401f80d, 0x04000007, 0x0401f956, - 0x04020003, 0x0401ff1b, 0x0401f003, 0x0401f80c, - 0x0401ff34, 0x1c01f000, 0x0201f800, 0x00100615, - 0x0201f800, 0x00100615, 0x59a80050, 0x80000040, - 0x48035050, 0x0400088d, 0x1c01f000, 0x4c040000, - 0x42000800, 0x00000000, 0x0401f9ae, 0x82040d00, - 0x00000090, 0x82040580, 0x00000090, 0x04000009, - 0x82040580, 0x00000010, 0x04000009, 0x82040580, - 0x00000000, 0x04000009, 0x0201f800, 0x00100615, - 0x42000000, 0x00000002, 0x0401f005, 0x42000000, - 0x00000001, 0x0401f002, 0x41780000, 0x0401f8e7, - 0x5c000800, 0x1c01f000, 0x4c040000, 0x59c40801, - 0x82040d00, 0x00018000, 0x82040580, 0x00000000, - 0x04000009, 0x82040580, 0x00008000, 0x04000009, - 0x82040580, 0x00010000, 0x04000009, 0x0201f800, - 0x00100615, 0x42000000, 0x00000002, 0x0401f005, - 0x42000000, 0x00000001, 0x0401f002, 0x41780000, - 0x0401f866, 0x5c000800, 0x1c01f000, 0x4c040000, - 0x59a80045, 0x80000000, 0x48035045, 0x82000580, - 0x00000005, 0x04020018, 0x497b5045, 0x59c40801, - 0x82040d00, 0x00018000, 0x82040580, 0x00000000, - 0x04000009, 0x82040580, 0x00008000, 0x04000009, - 0x82040580, 0x00010000, 0x04000009, 0x0201f800, - 0x00100615, 0x42000000, 0x00000002, 0x0401f005, - 0x42000000, 0x00000001, 0x0401f002, 0x41780000, - 0x0401f846, 0x42000800, 0x00000000, 0x0401f95d, - 0x82040d00, 0x00000090, 0x82040580, 0x00000090, - 0x04000009, 0x82040580, 0x00000010, 0x04000009, - 0x82040580, 0x00000000, 0x04000009, 0x0201f800, - 0x00100615, 0x42000000, 0x00000002, 0x0401f005, - 0x42000000, 0x00000001, 0x0401f002, 0x41780000, - 0x0401f896, 0x5c000800, 0x1c01f000, 0x4c200000, - 0x59a80048, 0x82000500, 0x00007fff, 0x02000800, - 0x00100615, 0x59a84047, 0x80204102, 0x02001800, - 0x00100615, 0x48235047, 0x80204500, 0x040007fa, - 0x8c000504, 0x04020007, 0x8c000502, 0x04020008, - 0x8c000500, 0x04020008, 0x0201f800, 0x00100615, - 0x42000000, 0x00000002, 0x0401f005, 0x41780000, - 0x0401f003, 0x42000000, 0x00000001, 0x0401f80f, - 0x5c004000, 0x1c01f000, 0x04011000, 0x4a03c840, - 0x0010b240, 0x4a03c842, 0x00000009, 0x40000000, - 0x040117ff, 0x4a035047, 0x00000004, 0x4a03503e, - 0x00000000, 0x1c01f000, 0x59a80858, 0x82040d80, - 0x01391077, 0x04020008, 0x59e00813, 0x8c040d00, - 0x04000005, 0x82000d80, 0x00000002, 0x04020002, - 0x41780000, 0x800001c0, 0x04000040, 0x82000d80, - 0x00000001, 0x0402001d, 0x42000800, 0x000000a0, - 0x0401f908, 0x82040540, 0x00000004, 0x42000800, - 0x000000a0, 0x0401f908, 0x42000800, 0x000000c0, - 0x0401f900, 0x82040540, 0x00000020, 0x42000800, - 0x000000c0, 0x0401f900, 0x59c40001, 0x82000500, - 0xfffe7fff, 0x82000540, 0x00000000, 0x48038801, - 0x59a80054, 0x80000110, 0x42000800, 0x000000e0, - 0x0401f8f5, 0x0401f03c, 0x82000d80, 0x00000002, - 0x02020800, 0x00100615, 0x42000800, 0x000000a0, - 0x0401f8e8, 0x82040500, 0xfffffffb, 0x42000800, - 0x000000a0, 0x0401f8e8, 0x42000800, 0x000000c0, - 0x0401f8e0, 0x82040500, 0xffffffdf, 0x42000800, - 0x000000c0, 0x0401f8e0, 0x59c40001, 0x82000500, - 0xfffe7fff, 0x82000540, 0x00010000, 0x48038801, - 0x59a80056, 0x80000110, 0x42000800, 0x000000e0, - 0x0401f8d5, 0x0401f01c, 0x42000800, 0x000000a0, - 0x0401f8cc, 0x82040540, 0x00000004, 0x42000800, - 0x000000a0, 0x0401f8cc, 0x42000800, 0x000000c0, - 0x0401f8c4, 0x82040500, 0xffffffdf, 0x42000800, - 0x000000c0, 0x0401f8c4, 0x59c40001, 0x82000500, - 0xfffe7fff, 0x82000540, 0x00008000, 0x48038801, - 0x59a80055, 0x80000110, 0x42000800, 0x000000e0, - 0x0401f8b9, 0x1c01f000, 0x4803c857, 0x59a80858, - 0x82040d80, 0x01391077, 0x04020008, 0x59e00813, - 0x8c040d00, 0x04000005, 0x82000d80, 0x00000002, - 0x04020002, 0x41780000, 0x4c000000, 0x0401f942, - 0x5c000000, 0x800001c0, 0x04000026, 0x82000d80, - 0x00000001, 0x04020010, 0x59a8006c, 0x80000540, - 0x04000004, 0x42001000, 0x00000000, 0x0401f9f7, - 0x42000800, 0x00000000, 0x0401f896, 0x82040540, - 0x00000090, 0x42000800, 0x00000000, 0x0401f896, - 0x0401f024, 0x82000d80, 0x00000002, 0x02020800, - 0x00100615, 0x59a8006c, 0x80000540, 0x04000004, - 0x42001000, 0x00010000, 0x0401f9e4, 0x42000800, - 0x00000000, 0x0401f883, 0x82040500, 0xffffff6f, - 0x42000800, 0x00000000, 0x0401f883, 0x0401f011, - 0x59a8006c, 0x80000540, 0x04000004, 0x42001000, - 0x00008000, 0x0401f9d5, 0x42000800, 0x00000000, - 0x0401f874, 0x82040500, 0xffffff6f, 0x82000540, - 0x00000010, 0x42000800, 0x00000000, 0x0401f872, - 0x0401f111, 0x4c580000, 0x4200b000, 0x00000014, - 0x8058b040, 0x04000042, 0x59c4000d, 0x8c000520, - 0x040207fc, 0x0401f85b, 0x59c4000d, 0x8c000520, - 0x040207f8, 0x59c40808, 0x84040d50, 0x48078808, - 0x4200b000, 0x000000c8, 0x8058b040, 0x040207ff, - 0x4200b000, 0x00000014, 0x8058b040, 0x04000030, - 0x59c4000d, 0x8c000520, 0x0402002d, 0x42000800, - 0x00001000, 0x50040800, 0x82040c80, 0x24220001, - 0x04020003, 0x8c000504, 0x040007f4, 0x0401f841, - 0x59c4000d, 0x8c000520, 0x04020021, 0x42000800, - 0x00001000, 0x50040800, 0x82040c80, 0x24220001, - 0x04020003, 0x8c000504, 0x040007e8, 0x4200b000, - 0x0000000a, 0x8058b040, 0x04000003, 0x0401f831, - 0x0401f7fd, 0x4200b000, 0x00000064, 0x59c4000d, - 0x8c00051e, 0x0400000e, 0x8058b040, 0x040207fc, - 0x42000000, 0x00001000, 0x50000000, 0x82000480, - 0x24220001, 0x04020004, 0x59c40808, 0x84040d10, - 0x48078808, 0x80000580, 0x0401f00c, 0x42000000, - 0x00001000, 0x50000000, 0x82000480, 0x24220001, - 0x04020004, 0x59c40808, 0x84040d10, 0x48078808, - 0x82000540, 0x00000001, 0x5c00b000, 0x1c01f000, - 0x42000800, 0x000000a0, 0x0401f816, 0x82040500, - 0xfffffffe, 0x42000800, 0x000000a0, 0x0401f816, - 0x42000800, 0x00000000, 0x0401f80e, 0x82040500, - 0xfffffffe, 0x42000800, 0x00000000, 0x0401f00e, - 0x40000000, 0x40000000, 0x40000000, 0x40000000, - 0x40000000, 0x1c01f000, 0x480b8805, 0x1c01f000, - 0x4807880e, 0x59c4080f, 0x82040d00, 0x000000ff, - 0x1c01f000, 0x900001c0, 0x80040d40, 0x84040d40, - 0x4807880e, 0x1c01f000, 0x82000d80, 0x00200000, - 0x04000009, 0x82000d80, 0x02000000, 0x04000006, - 0x82000d80, 0x01000000, 0x04000006, 0x59c408a3, - 0x0401f006, 0x59c408a3, 0x84040d30, 0x0401f003, - 0x59c408a3, 0x84040d32, 0x80040540, 0x480388a3, - 0x480788a3, 0x1c01f000, 0x59c400a3, 0x84000556, - 0x480388a3, 0x84000516, 0x480388a3, 0x1c01f000, - 0x485fc857, 0x4863c857, 0x4c640000, 0x4d3c0000, - 0x4d400000, 0x0201f800, 0x00106c32, 0x4863500a, - 0x0201f800, 0x0010a95a, 0x0402006a, 0x82600d00, - 0x0000ff00, 0x800409c0, 0x0400000c, 0x4200c800, - 0x00000001, 0x59a80010, 0x82000500, 0x000000ff, - 0x80041110, 0x80081580, 0x04000021, 0x82041580, - 0x0000ff00, 0x0400000a, 0x59c410a3, 0x82081500, - 0x00008000, 0x04000009, 0x59c410a7, 0x82081500, - 0x0000ff00, 0x82081580, 0x0000ff00, 0x4200c800, - 0x00000000, 0x04000012, 0x59a80005, 0x8c000502, - 0x04020008, 0x8c000500, 0x0402000d, 0x599c1017, - 0x8c08151a, 0x0400003c, 0x84000542, 0x48035005, - 0x4200c800, 0x00000002, 0x42028000, 0x00000004, - 0x42027800, 0x00000008, 0x0401f007, 0x59a80805, - 0x84040d40, 0x48075005, 0x42028000, 0x00000004, - 0x417a7800, 0x59a80006, 0x8c000502, 0x04020006, - 0x59a80805, 0x8c040d0a, 0x04020032, 0x84040d4a, - 0x48075005, 0x42000000, 0x0010b610, 0x0201f800, - 0x0010a86e, 0x59a8180a, 0x42001000, 0x00008013, - 0x0201f800, 0x00103857, 0x0201f800, 0x0010393e, - 0x04000015, 0x4d400000, 0x82600500, 0x000000ff, - 0x42028800, 0x0000ffff, 0x40643000, 0x42028000, - 0x0000000e, 0x0201f800, 0x0010a258, 0x42000800, - 0x00000001, 0x42001000, 0x00000100, 0x0201f800, - 0x00105ec4, 0x5c028000, 0x599c0817, 0x8c040d0a, - 0x04020010, 0x493fc857, 0x4943c857, 0x0401fb59, - 0x0401f00c, 0x0201f800, 0x0010393e, 0x04000009, - 0x42028000, 0x0000000f, 0x42028800, 0x0000ffff, - 0x42003000, 0x00000000, 0x0201f800, 0x0010a25b, - 0x497b8880, 0x5c028000, 0x5c027800, 0x5c00c800, - 0x1c01f000, 0x42000800, 0x00000000, 0x0401ff61, - 0x82040540, 0x00000002, 0x42000800, 0x00000000, - 0x0401f761, 0x42000800, 0x00000000, 0x0401ff59, - 0x82040500, 0xfffffffd, 0x42000800, 0x00000000, - 0x0401f759, 0x59c408a8, 0x0401ff4a, 0x0401ff49, - 0x59c400a8, 0x80040d80, 0x040207fb, 0x1c01f000, - 0x4803c856, 0x4a038807, 0x00000001, 0x497b8807, - 0x59c40005, 0x48038805, 0x497b506c, 0x497b506d, - 0x41785800, 0x42006000, 0x00000001, 0x42006800, - 0x00000003, 0x0401f824, 0x0401f82f, 0x40400000, - 0x4803c857, 0x82408580, 0x00000000, 0x0402001d, - 0x41785800, 0x42006000, 0x0000001e, 0x42006800, - 0x00000014, 0x0401f818, 0x0401f823, 0x40400000, - 0x4803c857, 0x82408580, 0x00000800, 0x04020011, - 0x42005800, 0x00000001, 0x42006000, 0x0000001e, - 0x42006800, 0x00000014, 0x0401f80b, 0x0401f816, - 0x40400000, 0x4803c857, 0x82408580, 0x0000ffff, - 0x04020004, 0x4a03506c, 0x00000001, 0x4803c856, - 0x1c01f000, 0x41785000, 0x0401f812, 0x0401f838, - 0x40347000, 0x40340800, 0x0401f03d, 0x42005000, - 0x00000001, 0x0401f80b, 0x0401f831, 0x40340800, - 0x0401f037, 0x42005000, 0x00000002, 0x0401f805, - 0x0401f81d, 0x0401f835, 0x40048000, 0x1c01f000, - 0x0401f808, 0x0401f814, 0x40280800, 0x0401f826, - 0x402c0800, 0x0401f827, 0x40300800, 0x0401f025, - 0x42000800, 0x0000ffff, 0x42001000, 0x00000001, - 0x0401f829, 0x42001000, 0x00000010, 0x0401f826, - 0x42000800, 0x0000ffff, 0x42001000, 0x00000010, - 0x0401f021, 0x41780800, 0x42001000, 0x00000002, - 0x0401f01d, 0x0401f92e, 0x4a03d000, 0x00050004, - 0x0401f92b, 0x4a03d000, 0x00050005, 0x0401f928, - 0x4a03d000, 0x00050004, 0x42000800, 0x00000001, - 0x42001000, 0x00000001, 0x0401f00f, 0x42000800, - 0x00000002, 0x42001000, 0x00000002, 0x0401f00a, - 0x42001000, 0x00000005, 0x0401f007, 0x42001000, - 0x00000010, 0x0401f004, 0x42001000, 0x00000010, - 0x0401f01b, 0x0401f912, 0x82082c00, 0x0010a95f, - 0x50142800, 0x82081500, 0xffffffff, 0x04000013, - 0x0401f90b, 0x80081040, 0x80142902, 0x40040000, - 0x80140500, 0x04000007, 0x4a03d000, 0x00070006, - 0x0401f903, 0x4a03d000, 0x00070007, 0x0401f006, - 0x4a03d000, 0x00070004, 0x0401f8fd, 0x4a03d000, - 0x00070005, 0x0401f7ec, 0x1c01f000, 0x41780800, - 0x82082c00, 0x0010a95f, 0x50142800, 0x82081500, - 0xffffffff, 0x04000010, 0x0401f8f1, 0x4a03d000, - 0x00050001, 0x0401f8ee, 0x59e81800, 0x80081040, - 0x80142902, 0x8c0c1d06, 0x04000004, 0x40140000, - 0x80040d40, 0x0401f8e6, 0x4a03d000, 0x00070000, - 0x0401f7ef, 0x1c01f000, 0x480bc857, 0x480b506d, - 0x59c40001, 0x82000500, 0xffffefff, 0x48038801, - 0x41781800, 0x0401f8c4, 0x41785800, 0x42006000, - 0x0000001e, 0x42006800, 0x00000004, 0x0401ff7a, - 0x42006800, 0x0000003c, 0x0401ff7d, 0x41785800, - 0x42006000, 0x0000001e, 0x42006800, 0x00000004, - 0x0401ff71, 0x41786800, 0x0401ff75, 0x41785800, - 0x42006000, 0x0000001e, 0x41786800, 0x0401ff6a, - 0x42006800, 0x00000002, 0x0401ff6d, 0x42006800, - 0x00000001, 0x0401ff64, 0x42006800, 0x000000f5, - 0x0401ff67, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000004, 0x0401ff5b, 0x42006800, - 0x00000020, 0x0401ff5e, 0x59a8106d, 0x0401f865, - 0x42001800, 0x000200f5, 0x0401f897, 0x59a8106d, - 0x0401f879, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000004, 0x0401ff4b, 0x41786800, - 0x0401ff4f, 0x59c40001, 0x82000540, 0x00001000, - 0x48038801, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000015, 0x0401ff3f, 0x0401ff4a, - 0x40400000, 0x82000540, 0x00000002, 0x4c000000, - 0x41785800, 0x42006000, 0x0000001e, 0x42006800, - 0x00000015, 0x0401ff34, 0x5c000000, 0x40006800, - 0x0401ff37, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000015, 0x0401ff2b, 0x0401ff36, - 0x40400000, 0x82000500, 0x0000fffd, 0x4c000000, - 0x41785800, 0x42006000, 0x0000001e, 0x42006800, - 0x00000015, 0x0401ff20, 0x5c000000, 0x40006800, - 0x0401ff23, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000014, 0x0401ff17, 0x0401ff22, - 0x40400000, 0x82000540, 0x00000040, 0x4c000000, - 0x41785800, 0x42006000, 0x0000001e, 0x42006800, - 0x00000014, 0x0401ff0c, 0x5c000000, 0x40006800, - 0x0401ff0f, 0x41785800, 0x42006000, 0x0000001e, - 0x42006800, 0x00000014, 0x0401ff03, 0x0401ff0e, - 0x40400000, 0x82000500, 0x0000ffbf, 0x4c000000, - 0x41785800, 0x42006000, 0x0000001e, 0x42006800, - 0x00000014, 0x0401fef8, 0x5c000000, 0x40006800, - 0x0401fefb, 0x4a038886, 0x00002020, 0x0401f04c, - 0x480bc857, 0x82080580, 0x00010000, 0x04020007, - 0x82040d40, 0x00010000, 0x42001800, 0x00000001, - 0x0401f82d, 0x0401f00f, 0x82080580, 0x00008000, - 0x04000007, 0x82040d40, 0x00000000, 0x42001800, - 0x00900001, 0x0401f824, 0x0401f006, 0x82040d40, - 0x00008000, 0x42001800, 0x00100001, 0x0401f81e, - 0x1c01f000, 0x480bc857, 0x82080580, 0x00010000, - 0x04020008, 0x42001800, 0x000000a1, 0x0401f816, - 0x42001800, 0x000000c1, 0x0401f813, 0x0401f011, - 0x82080580, 0x00008000, 0x04000008, 0x42001800, - 0x000400a1, 0x0401f80c, 0x42001800, 0x002000c1, - 0x0401f809, 0x0401f007, 0x42001800, 0x000400a1, - 0x0401f805, 0x42001800, 0x000000c1, 0x0401f802, - 0x1c01f000, 0x480fc857, 0x41785800, 0x42006000, - 0x0000001e, 0x41786800, 0x0401feb7, 0x400c6800, - 0x80346960, 0x0401feba, 0x42006800, 0x00000001, - 0x0401feb1, 0x400c6800, 0x0401feb5, 0x42006800, - 0x00000003, 0x0401feac, 0x0401feb7, 0x40400000, - 0x8c000504, 0x040207fc, 0x1c01f000, 0x42000000, - 0x00000064, 0x80000040, 0x040207ff, 0x1c01f000, - 0x4c5c0000, 0x4c600000, 0x4178b800, 0x0201f800, - 0x0010473b, 0x040200fd, 0x59a8c026, 0x0201f800, - 0x00104e0d, 0x04000003, 0x8c60c506, 0x0400000e, - 0x8c60c500, 0x04020004, 0x8c60c50e, 0x040008f6, - 0x0401f0f2, 0x0401faaf, 0x040200f0, 0x0201f800, - 0x00104e0d, 0x04020004, 0x4a03501c, 0x0000ffff, - 0x0401f0ea, 0x8c60c504, 0x04000004, 0x4a03501c, - 0x0000ffff, 0x0401f0e5, 0x59a8c010, 0x8260c500, - 0x000000ff, 0x59a81013, 0x8c081500, 0x0400005d, - 0x8c081502, 0x0402005b, 0x59a8b81c, 0x825c0d80, - 0x0000ffff, 0x04020003, 0x4200b800, 0x00000001, - 0x805c1104, 0x82086400, 0x0010bc20, 0x50300800, - 0x825c0500, 0x00000003, 0x0c01f001, 0x00101c2c, - 0x00101c27, 0x00101c2b, 0x00101c29, 0x80040910, - 0x0401f004, 0x80040930, 0x0401f002, 0x80040920, - 0x82040500, 0x000000ff, 0x82000d80, 0x000000ff, - 0x0400000f, 0x4c000000, 0x82000400, 0x00101eb5, - 0x50000800, 0x80040910, 0x82040580, 0x00000080, - 0x5c000000, 0x04000030, 0x80600d80, 0x0400002e, - 0x80000540, 0x0400002c, 0x0401f00b, 0x59a81005, - 0x82081500, 0x00000003, 0x0402002b, 0x59a81013, - 0x84081542, 0x480b5013, 0x4a03501c, 0x0000ffff, - 0x0401f028, 0x4c000000, 0x59a8006f, 0x8c000502, - 0x42001000, 0x00000010, 0x02020800, 0x00104ada, - 0x5c000000, 0x0402001c, 0x417a8800, 0x0201f800, - 0x001059b9, 0x04020016, 0x0201f800, 0x0010443b, - 0x04000006, 0x0201f800, 0x00104acf, 0x0401f8b1, - 0x0400000f, 0x0401f00c, 0x599c0019, 0x8c00050e, - 0x04020009, 0x0201f800, 0x001043fc, 0x04020008, - 0x0201f800, 0x00104acf, 0x0401f9dd, 0x0401f8be, - 0x04000003, 0x805cb800, 0x0401f7b2, 0x485f501c, - 0x0401f086, 0x4a03501c, 0x0000ffff, 0x0401f083, - 0x42003000, 0x0000007e, 0x59a8001c, 0x82001580, - 0x0000ffff, 0x04020005, 0x80000d80, 0x4018b000, - 0x4803c856, 0x0401f009, 0x8018b480, 0x04001004, - 0x40000800, 0x4803c856, 0x0401f004, 0x4a03501c, - 0x0000ffff, 0x0401f071, 0x4c040000, 0x4c580000, - 0x82040400, 0x00101eb5, 0x50000000, 0x82000500, - 0x000000ff, 0x80604580, 0x0400005c, 0x0201f800, - 0x001059ba, 0x04020061, 0x59a8006f, 0x8c000502, - 0x42001000, 0x00000010, 0x02020800, 0x00104ada, - 0x5c00b000, 0x5c000800, 0x040207d7, 0x4c040000, - 0x4c580000, 0x845cbd00, 0x0201f800, 0x00020267, - 0x04000008, 0x599c0019, 0x8c00050e, 0x04020047, - 0x0201f800, 0x00104401, 0x0402004c, 0x0401f002, - 0x845cbd40, 0x0201f800, 0x00104acf, 0x0201f800, - 0x00104836, 0x04020007, 0x59a80005, 0x8c000502, - 0x04000033, 0x59340200, 0x8c00050e, 0x04020030, - 0x59a81013, 0x8c081502, 0x04000025, 0x0201f800, - 0x00104858, 0x04000031, 0x8c5cbd00, 0x04020004, - 0x0201f800, 0x00104455, 0x0401f02c, 0x0401f9c8, - 0x0400002a, 0x42026000, 0x0010bbe8, 0x49366009, - 0x497a6008, 0x417a7800, 0x0401f920, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x0010393e, 0x0400001d, 0x41782800, 0x42003000, - 0x00000008, 0x4d400000, 0x4d440000, 0x59368c03, - 0x42028000, 0x00000029, 0x0201f800, 0x0010a258, - 0x5c028800, 0x5c028000, 0x0401f010, 0x4937c857, - 0x599c0019, 0x8c00050e, 0x0402000c, 0x0401f968, - 0x0401f849, 0x04000011, 0x0401f008, 0x59a80013, - 0x8c000500, 0x04000003, 0x0401f9a1, 0x04000003, - 0x0401f828, 0x04000009, 0x5c00b000, 0x5c000800, - 0x80040800, 0x8058b040, 0x04020798, 0x4a03501c, - 0x0000ffff, 0x0401f005, 0x4937c857, 0x5c00b000, - 0x5c000800, 0x4807501c, 0x5c00c000, 0x5c00b800, - 0x1c01f000, 0x4803c856, 0x4a03501c, 0x00000001, - 0x42028800, 0x000007fe, 0x42003000, 0x00fffffe, - 0x0201f800, 0x001043fc, 0x0402000c, 0x0401f944, - 0x0401f825, 0x04000009, 0x59a80026, 0x8400054e, - 0x48035026, 0x0201f800, 0x001090d5, 0x82000540, - 0x00000001, 0x1c01f000, 0x80000580, 0x0401f7fe, - 0x4937c857, 0x0201f800, 0x001076c9, 0x04000015, - 0x49366009, 0x4a026406, 0x00000001, 0x417a7800, - 0x0201f800, 0x001043bd, 0x59a8001b, 0x80000000, - 0x4803501b, 0x42027000, 0x00000004, 0x599c0019, - 0x8c00050e, 0x04000003, 0x42027000, 0x00000000, - 0x0201f800, 0x000208d8, 0x82000540, 0x00000001, - 0x1c01f000, 0x4937c857, 0x0201f800, 0x001076c9, - 0x0400001c, 0x49366009, 0x59340403, 0x82000580, - 0x000007fe, 0x04000005, 0x4d3c0000, 0x417a7800, - 0x0401f8b2, 0x5c027800, 0x4a026406, 0x00000001, - 0x417a7800, 0x0201f800, 0x001043bd, 0x42000800, - 0x00000003, 0x0201f800, 0x001043c7, 0x59a8001b, - 0x80000000, 0x4803501b, 0x42027000, 0x00000002, - 0x0201f800, 0x000208d8, 0x82000540, 0x00000001, - 0x1c01f000, 0x4803c856, 0x42028800, 0x000007fc, - 0x42003000, 0x00fffffc, 0x0201f800, 0x001043fc, - 0x04020005, 0x0401f805, 0x04000003, 0x4a035027, - 0x0000ffff, 0x1c01f000, 0x4937c857, 0x0201f800, - 0x001076c9, 0x04000014, 0x49366009, 0x4a026406, - 0x00000001, 0x417a7800, 0x0201f800, 0x001043bd, - 0x42000800, 0x00000003, 0x0201f800, 0x001043c7, - 0x59a80028, 0x80000000, 0x48035028, 0x42027000, - 0x00000002, 0x0201f800, 0x000208d8, 0x82000540, - 0x00000001, 0x1c01f000, 0x480bc857, 0x492fc857, - 0x4c5c0000, 0x4008b800, 0x42028800, 0x000007fd, - 0x42003000, 0x00fffffd, 0x0201f800, 0x001043fc, - 0x0402001a, 0x0201f800, 0x00020892, 0x04000017, - 0x49366009, 0x5934000a, 0x84000544, 0x4802680a, - 0x812e59c0, 0x04000005, 0x592c0404, 0x8c00051e, - 0x04000002, 0x48ee6021, 0x492e6008, 0x4a026406, - 0x00000001, 0x485e601c, 0x42027000, 0x00000022, - 0x0201f800, 0x000208d8, 0x82000540, 0x00000001, - 0x5c00b800, 0x1c01f000, 0x80000580, 0x0401f7fd, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4943c857, - 0x493fc857, 0x4d340000, 0x4d440000, 0x4c580000, - 0x4d2c0000, 0x4c5c0000, 0x0201f800, 0x0010698c, - 0x4df00000, 0x0201f800, 0x0010673a, 0x0201f800, - 0x001067ee, 0x0201f800, 0x0010647f, 0x0201f800, - 0x0010822b, 0x5c03e000, 0x02000800, 0x00106982, - 0x4200b000, 0x000007f0, 0x417a8800, 0x0201f800, - 0x00020267, 0x0402001a, 0x8d3e7d06, 0x04000004, - 0x59340200, 0x8c00050e, 0x04020015, 0x8d3e7d18, - 0x04000010, 0x5934b80f, 0x805cb9c0, 0x04000009, - 0x49425a06, 0x592cb800, 0x0201f800, 0x00020381, - 0x805cb9c0, 0x040207fb, 0x497a680f, 0x497a6810, - 0x4937c857, 0x4a026c00, 0x00000707, 0x0401f004, - 0x4937c857, 0x0201f800, 0x001040e4, 0x81468800, - 0x8058b040, 0x040207e2, 0x8d3e7d02, 0x04000011, - 0x497b501d, 0x42028800, 0x000007f0, 0x4200b000, - 0x00000010, 0x0201f800, 0x00020267, 0x04020006, - 0x4937c857, 0x4a026c00, 0x00000707, 0x0201f800, - 0x001040e4, 0x81468800, 0x8058b040, 0x040207f6, - 0x5c00b800, 0x5c025800, 0x5c00b000, 0x5c028800, - 0x5c026800, 0x1c01f000, 0x5c000000, 0x4c000000, - 0x4803c857, 0x4933c857, 0x493fc857, 0x4d340000, - 0x4d400000, 0x4d440000, 0x4d2c0000, 0x4c5c0000, - 0x0201f800, 0x0010698c, 0x4df00000, 0x59326809, - 0x813669c0, 0x04000021, 0x59368c03, 0x42028000, - 0x00000029, 0x0201f800, 0x0010679b, 0x0201f800, - 0x001067f6, 0x0201f800, 0x00106543, 0x0201f800, - 0x0010a0da, 0x4937c857, 0x8d3e7d18, 0x04000011, - 0x5934b80f, 0x805cb9c0, 0x0400000a, 0x405e5800, - 0x49425a06, 0x592cb800, 0x0201f800, 0x00020381, - 0x805cb9c0, 0x040207fa, 0x497a680f, 0x497a6810, - 0x4937c857, 0x4a026c00, 0x00000707, 0x0401f003, - 0x0201f800, 0x001040e4, 0x5c03e000, 0x02000800, - 0x00106982, 0x5c00b800, 0x5c025800, 0x5c028800, - 0x5c028000, 0x5c026800, 0x1c01f000, 0x4933c857, - 0x59a80026, 0x8c000508, 0x04020012, 0x59305009, - 0x482bc857, 0x836c0580, 0x00000002, 0x0402000d, - 0x0401f813, 0x0402000b, 0x58280403, 0x82000580, - 0x000007fc, 0x04000008, 0x59a8001b, 0x80000040, - 0x4803c857, 0x02001800, 0x00100615, 0x4803501b, - 0x1c01f000, 0x59a80028, 0x80000040, 0x4803c857, - 0x040017fc, 0x48035028, 0x1c01f000, 0x59300008, - 0x800001c0, 0x04020009, 0x59300403, 0x82000580, - 0x00000001, 0x04020004, 0x82000540, 0x00000001, - 0x0401f002, 0x80000580, 0x1c01f000, 0x4937c857, - 0x59340200, 0x84000502, 0x48026a00, 0x1c01f000, - 0x4933c857, 0x493fc857, 0x4947c857, 0x4d400000, - 0x4d340000, 0x4d440000, 0x4c580000, 0x0201f800, - 0x0010698c, 0x4df00000, 0x8060c1c0, 0x04020004, - 0x4200b000, 0x00000001, 0x0401f004, 0x4200b000, - 0x000007f0, 0x417a8800, 0x41440000, 0x81ac0400, - 0x50000000, 0x80026d40, 0x0400001a, 0x4d3c0000, - 0x42027800, 0x00000001, 0x0201f800, 0x00104745, - 0x5c027800, 0x42028000, 0x00000029, 0x0201f800, - 0x0010679b, 0x0201f800, 0x001067f6, 0x0201f800, - 0x00106543, 0x0201f800, 0x00104836, 0x04020005, - 0x4937c857, 0x4a026c00, 0x00000404, 0x0401f003, - 0x0201f800, 0x00104863, 0x0201f800, 0x0010a0da, - 0x81468800, 0x8058b040, 0x040207e0, 0x5c03e000, - 0x02000800, 0x00106982, 0x5c00b000, 0x5c028800, - 0x5c026800, 0x5c028000, 0x1c01f000, 0x4937c857, - 0x4947c857, 0x4c5c0000, 0x4c600000, 0x4c640000, - 0x59a80013, 0x8c000500, 0x0400001f, 0x599c0017, - 0x8c00050a, 0x0402001c, 0x5934ba02, 0x825cbd00, - 0x000000ff, 0x485fc857, 0x4178c000, 0x4178c800, - 0x82600400, 0x0010bc20, 0x50002000, 0x8060c1c0, - 0x04000008, 0x82100500, 0x000000ff, 0x82002d80, - 0x000000ff, 0x0400000c, 0x805c0580, 0x0400000d, - 0x80102110, 0x8064c800, 0x82640580, 0x00000004, - 0x040207f5, 0x8060c000, 0x82600580, 0x00000020, - 0x040207eb, 0x4813c857, 0x82000540, 0x00000001, - 0x5c00c800, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x59a80026, 0x8c000512, 0x02020800, 0x001006ba, - 0x1c01f000, 0x00007eef, 0x00007de8, 0x00007ce4, - 0x000080e2, 0x00007be1, 0x000080e0, 0x000080dc, - 0x000080da, 0x00007ad9, 0x000080d6, 0x000080d5, - 0x000080d4, 0x000080d3, 0x000080d2, 0x000080d1, - 0x000079ce, 0x000078cd, 0x000080cc, 0x000080cb, - 0x000080ca, 0x000080c9, 0x000080c7, 0x000080c6, - 0x000077c5, 0x000076c3, 0x000080bc, 0x000080ba, - 0x000075b9, 0x000080b6, 0x000074b5, 0x000073b4, - 0x000072b3, 0x000080b2, 0x000080b1, 0x000080ae, - 0x000071ad, 0x000080ac, 0x000070ab, 0x00006faa, - 0x00006ea9, 0x000080a7, 0x00006da6, 0x00006ca5, - 0x00006ba3, 0x00006a9f, 0x0000699e, 0x0000689d, - 0x0000809b, 0x00008098, 0x00006797, 0x00006690, - 0x0000658f, 0x00006488, 0x00006384, 0x00006282, - 0x00008081, 0x00008080, 0x0000617c, 0x0000607a, - 0x00008079, 0x00005f76, 0x00008075, 0x00008074, - 0x00008073, 0x00008072, 0x00008071, 0x0000806e, - 0x00005e6d, 0x0000806c, 0x00005d6b, 0x00005c6a, - 0x00005b69, 0x00008067, 0x00005a66, 0x00005965, - 0x00005863, 0x0000575c, 0x0000565a, 0x00005559, - 0x00008056, 0x00008055, 0x00005454, 0x00005353, - 0x00005252, 0x00005151, 0x0000504e, 0x00004f4d, - 0x0000804c, 0x0000804b, 0x00004e4a, 0x00004d49, - 0x00008047, 0x00004c46, 0x00008045, 0x00008043, - 0x0000803c, 0x0000803a, 0x00008039, 0x00008036, - 0x00004b35, 0x00008034, 0x00004a33, 0x00004932, - 0x00004831, 0x0000802e, 0x0000472d, 0x0000462c, - 0x0000452b, 0x0000442a, 0x00004329, 0x00004227, - 0x00008026, 0x00008025, 0x00004123, 0x0000401f, - 0x00003f1e, 0x00003e1d, 0x00003d1b, 0x00003c18, - 0x00008017, 0x00008010, 0x00003b0f, 0x00003a08, - 0x00008004, 0x00003902, 0x00008001, 0x00008000, - 0x00008000, 0x00003800, 0x00003700, 0x00003600, - 0x00008000, 0x00003500, 0x00008000, 0x00008000, - 0x00008000, 0x00003400, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00003300, 0x00003200, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00003100, 0x00003000, 0x00008000, 0x00008000, - 0x00002f00, 0x00008000, 0x00002e00, 0x00002d00, - 0x00002c00, 0x00008000, 0x00008000, 0x00008000, - 0x00002b00, 0x00008000, 0x00002a00, 0x00002900, - 0x00002800, 0x00008000, 0x00002700, 0x00002600, - 0x00002500, 0x00002400, 0x00002300, 0x00002200, - 0x00008000, 0x00008000, 0x00002100, 0x00002000, - 0x00001f00, 0x00001e00, 0x00001d00, 0x00001c00, - 0x00008000, 0x00008000, 0x00001b00, 0x00001a00, - 0x00008000, 0x00001900, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00001800, 0x00008000, 0x00001700, 0x00001600, - 0x00001500, 0x00008000, 0x00001400, 0x00001300, - 0x00001200, 0x00001100, 0x00001000, 0x00000f00, - 0x00008000, 0x00008000, 0x00000e00, 0x00000d00, - 0x00000c00, 0x00000b00, 0x00000a00, 0x00000900, - 0x00008000, 0x00008000, 0x00000800, 0x00000700, - 0x00008000, 0x00000600, 0x00008000, 0x00008000, - 0x00008000, 0x00000500, 0x00000400, 0x00000300, - 0x00008000, 0x00000200, 0x00008000, 0x00008000, - 0x00008000, 0x00000100, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00000000, 0x00008000, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00008000, 0x00008000, 0x00008000, 0x00008000, - 0x00008000, 0x0201f800, 0x00100819, 0x02000800, - 0x00100615, 0x492f4016, 0x1c01f000, 0x83a0ac00, - 0x00000006, 0x83a00580, 0x0010b2a0, 0x0400000c, - 0x492fc857, 0x812e59c0, 0x02000800, 0x00100615, - 0x832ca400, 0x00000006, 0x4200b000, 0x0000000d, - 0x0201f800, 0x0010a93e, 0x0401f00f, 0x4200b000, - 0x00000010, 0x83e0a400, 0x00000020, 0x50500000, - 0x8050a000, 0x50500800, 0x900409c0, 0x80040540, - 0x4400a800, 0x8050a000, 0x8054a800, 0x8058b040, - 0x040207f7, 0x1c01f000, 0x59a00206, 0x82000c80, - 0x0000007f, 0x040210c9, 0x59a80821, 0x0c01f001, - 0x00102066, 0x001020a6, 0x001020a6, 0x001020f0, - 0x00102112, 0x001020a6, 0x00102066, 0x00102134, - 0x00102145, 0x001020a6, 0x001020a6, 0x00102152, - 0x0010216a, 0x00102182, 0x001020a6, 0x001021b1, - 0x001021e3, 0x001020a6, 0x0010220c, 0x001020a6, - 0x00102269, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001020a6, 0x00102280, 0x001022b9, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001022ee, 0x001020a6, 0x00102340, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x00102345, - 0x001023be, 0x001020a6, 0x001023c5, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001023c7, 0x00102445, 0x00102585, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x00102594, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001025b1, 0x00102604, 0x00102660, 0x00102674, - 0x00102696, 0x001028d1, 0x00102c60, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001020a6, 0x001020a6, 0x001020a6, 0x00102d9f, - 0x00102e13, 0x001020a6, 0x001020a6, 0x00102e81, - 0x001020a6, 0x00102f1f, 0x00102fd1, 0x001020a6, - 0x001020a6, 0x00103008, 0x00103064, 0x001020a6, - 0x001030bc, 0x00103220, 0x001020a6, 0x00103234, - 0x001032bf, 0x001020a6, 0x001020a6, 0x001020a6, - 0x001020a6, 0x0010332f, 0x00103333, 0x00103352, - 0x001020a6, 0x001033f4, 0x001020a6, 0x001020a6, - 0x00103421, 0x001020a6, 0x0010344f, 0x001020a6, - 0x001020a6, 0x001034b6, 0x001035c3, 0x00103620, - 0x001020a6, 0x00103686, 0x001020a6, 0x001020a6, - 0x001036db, 0x0010373e, 0x001020a6, 0x48efc857, - 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580, - 0x00000200, 0x04000045, 0x48efc857, 0x4a034206, - 0x00004000, 0x0201f800, 0x0010382f, 0x83a00580, - 0x0010b2a0, 0x0400000d, 0x58ee580a, 0x4d2c0000, - 0x0401f856, 0x41a25800, 0x0201f800, 0x0010083a, - 0x40ee5800, 0x0201f800, 0x0010083a, 0x5c025800, - 0x0201f000, 0x00020381, 0x04026007, 0x59a0001d, - 0x84000542, 0x4803401d, 0x4a01d809, 0x0010207a, - 0x1c01f000, 0x59a00206, 0x82000d80, 0x00004000, - 0x04000006, 0x900001c0, 0x82000540, 0x00000011, - 0x4803c011, 0x0401f005, 0x900001c0, 0x82000540, - 0x00000010, 0x4803c011, 0x0401f844, 0x59e00017, - 0x8c000508, 0x0402000c, 0x4203e000, 0x30000001, - 0x4203e000, 0x40000000, 0x40ee5800, 0x0201f800, - 0x0010083a, 0x59a0001d, 0x84000504, 0x4803401d, - 0x1c01f000, 0x4a03c017, 0x00000000, 0x59a00206, - 0x82000d80, 0x00004000, 0x040007f0, 0x4a03c017, - 0x00000001, 0x0401f7ed, 0x4803c856, 0x4a034206, - 0x00004001, 0x0401f7c0, 0x4803c856, 0x4a034206, - 0x00004002, 0x0401f7bc, 0x4803c856, 0x4a034206, - 0x00004003, 0x0401f7b8, 0x4803c856, 0x4a034206, - 0x00004005, 0x0401f7b4, 0x4803c856, 0x4a034206, - 0x00004006, 0x0401f7b0, 0x4803c856, 0x4a034206, - 0x0000400b, 0x0401f7ac, 0x4803c856, 0x4a034206, - 0x0000400c, 0x0401f7a8, 0x4803c856, 0x4a034206, - 0x0000400c, 0x0401f7a4, 0x58eca80a, 0x8054a9c0, - 0x02000800, 0x00100615, 0x83a0a400, 0x00000006, - 0x8254ac00, 0x00000006, 0x4200b000, 0x0000000d, - 0x0201f000, 0x0010a93e, 0x59a00206, 0x4803c857, - 0x59a00406, 0x4803c857, 0x59a00207, 0x4803c857, - 0x59a00407, 0x4803c857, 0x59a00208, 0x4803c857, - 0x59a00408, 0x4803c857, 0x59a00209, 0x4803c857, - 0x83e0ac00, 0x00000020, 0x83a0a400, 0x00000006, - 0x4200b000, 0x00000010, 0x50500000, 0x4400a800, - 0x8054a800, 0x900001c0, 0x4400a800, 0x8054a800, - 0x8050a000, 0x8058b040, 0x040207f8, 0x1c01f000, - 0x59a00406, 0x800000c2, 0x59a00a07, 0x900409c0, - 0x80040540, 0x84000540, 0x59a00c07, 0x8c040d00, - 0x04000018, 0x59a8086f, 0x8c040d00, 0x040207bb, - 0x42000800, 0x00000064, 0x80040840, 0x04000007, - 0x4a030000, 0x00000001, 0x40000000, 0x59801000, - 0x8c081500, 0x040007f9, 0x04000005, 0x48030004, - 0x4a030000, 0x00000000, 0x0401f75c, 0x4a030000, - 0x00000000, 0x4a034406, 0x00000004, 0x040007a3, - 0x4803880e, 0x0401f755, 0x59a00406, 0x800000c2, - 0x59a00c07, 0x8c040d00, 0x0400001a, 0x59a8086f, - 0x8c040d00, 0x0402079d, 0x42000800, 0x00000064, - 0x80040840, 0x04000007, 0x4a030000, 0x00000001, - 0x40000000, 0x59801000, 0x8c081500, 0x040007f9, - 0x04000007, 0x48030004, 0x59800805, 0x48074406, - 0x4a030000, 0x00000000, 0x0401f73c, 0x4a030000, - 0x00000000, 0x4a034406, 0x00000004, 0x04000783, - 0x4803880e, 0x59c4080f, 0x48074406, 0x0401f733, - 0x59a01c06, 0x59a00207, 0x900c19c0, 0x800c1d40, - 0x580c0803, 0x80000580, 0x500c1000, 0x80080400, - 0x800c1800, 0x80040840, 0x040207fc, 0x48034406, - 0x900001c0, 0x48034207, 0x800001c0, 0x04000723, - 0x0401f76a, 0x4a034406, 0x00000004, 0x4a034207, - 0x00000000, 0x4a034407, 0x00000012, 0x59a8000d, - 0x48034208, 0x900001c0, 0x48034408, 0x4a034209, - 0x00000002, 0x0401f715, 0x59a00407, 0x59a01207, - 0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09, - 0x900c19c0, 0x800c1d40, 0x59a00a08, 0x59a00408, - 0x900409c0, 0x80040d40, 0x59a0020a, 0x82002480, - 0x00000010, 0x04001755, 0x59a02406, 0x900001c0, - 0x80100540, 0x59a8280d, 0x80142480, 0x0400174f, - 0x0201f000, 0x0010383e, 0x59a00407, 0x59a01207, - 0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09, - 0x900c19c0, 0x800c1d40, 0x59a00a08, 0x59a00408, - 0x900409c0, 0x80040d40, 0x59a0020a, 0x82002480, - 0x00000010, 0x0400173d, 0x59a02406, 0x900001c0, - 0x80100540, 0x59a8280d, 0x80142480, 0x04001737, - 0x0201f000, 0x00103841, 0x59a02407, 0x59a00207, - 0x901021c0, 0x80102540, 0x59a01a0a, 0x59a00406, - 0x900c19c0, 0x800c1d40, 0x41781000, 0x42000000, - 0x00001000, 0x50000000, 0x82000480, 0x24320001, - 0x04001016, 0x820c0580, 0x00007c00, 0x04000013, - 0x820c0480, 0x00007a00, 0x04001010, 0x820c0480, - 0x00007cff, 0x0402100d, 0x42000800, 0x00000064, - 0x80040840, 0x04000007, 0x4a030000, 0x00000001, - 0x40000000, 0x59800000, 0x8c000500, 0x040007f9, - 0x04000008, 0x80081000, 0x44101800, 0x800811c0, - 0x040006be, 0x4a030000, 0x00000000, 0x0401f6bb, - 0x4a030000, 0x00000000, 0x4a034406, 0x00000004, - 0x0401f702, 0x59a01a0a, 0x59a00406, 0x900c19c0, - 0x800c1d40, 0x41781000, 0x42000000, 0x00001000, - 0x50000000, 0x82000480, 0x24320001, 0x04001016, - 0x820c0580, 0x00007c00, 0x04000013, 0x820c0480, - 0x00007a00, 0x04001010, 0x820c0480, 0x00007cff, - 0x0402100d, 0x42000800, 0x00000064, 0x80040840, - 0x04000007, 0x4a030000, 0x00000001, 0x40000000, - 0x59800000, 0x8c000500, 0x040007f9, 0x0400000f, - 0x80081000, 0x500c0000, 0x82000d00, 0x0000ffff, - 0x48074207, 0x82000d00, 0xffff0000, 0x900409c0, - 0x48074407, 0x800811c0, 0x0400068c, 0x4a030000, - 0x00000000, 0x0401f689, 0x4a030000, 0x00000000, - 0x4a034406, 0x00000004, 0x0401f6d0, 0x59a00406, - 0x8c000500, 0x04000020, 0x59a01207, 0x59a01c07, - 0x59a02208, 0x480b5054, 0x480f5055, 0x48135056, - 0x59c40801, 0x82040d00, 0x00018000, 0x82040580, - 0x00000000, 0x04000009, 0x82040580, 0x00008000, - 0x04000008, 0x82040580, 0x00010000, 0x04000007, - 0x0201f800, 0x00100615, 0x40080000, 0x0401f004, - 0x400c0000, 0x0401f002, 0x40100000, 0x80000110, - 0x42000800, 0x000000e0, 0x0201f800, 0x001019b1, - 0x0401f007, 0x59a81054, 0x59a81855, 0x59a82056, - 0x480b4207, 0x480f4407, 0x48134208, 0x0401f65b, - 0x4d2c0000, 0x4d340000, 0x4d300000, 0x4d440000, - 0x59a28c06, 0x0201f800, 0x00020267, 0x04000006, - 0x5c028800, 0x5c026000, 0x5c026800, 0x5c025800, - 0x0401f69e, 0x59a04407, 0x59a00207, 0x900001c0, - 0x80204540, 0x0401f81e, 0x04000009, 0x4a034208, - 0x00000001, 0x4a034406, 0x0000ffff, 0x4a034207, - 0x0000ffff, 0x497b4407, 0x0401f00b, 0x0401f822, - 0x0400000e, 0x4a034208, 0x00000002, 0x59300402, - 0x48034406, 0x59300202, 0x48034207, 0x59300206, - 0x48034407, 0x5c028800, 0x5c026000, 0x5c026800, - 0x5c025800, 0x0401f631, 0x5c028800, 0x5c026000, - 0x5c026800, 0x5c025800, 0x0401f678, 0x4937c856, - 0x4823c856, 0x4d2c0000, 0x5934000f, 0x80025d40, - 0x04000007, 0x592c0005, 0x80200580, 0x592c0000, - 0x040207fb, 0x82000540, 0x00000001, 0x5c025800, - 0x1c01f000, 0x4823c857, 0x4d2c0000, 0x4d300000, - 0x42026000, 0x0010cfc0, 0x59300406, 0x82000d80, - 0x00000003, 0x04000004, 0x82000d80, 0x00000006, - 0x04020007, 0x59325808, 0x812e59c0, 0x04000004, - 0x592c0005, 0x80200580, 0x0400000a, 0x83326400, - 0x00000024, 0x41580000, 0x81300480, 0x040017ef, - 0x80000580, 0x5c026000, 0x5c025800, 0x1c01f000, - 0x82000540, 0x00000001, 0x5c026000, 0x5c025800, - 0x1c01f000, 0x83a00580, 0x0010b2a0, 0x0402063b, - 0x59a8006f, 0x8c000500, 0x04020003, 0x4a030000, - 0x00000000, 0x4a034206, 0x00004000, 0x4a03c011, - 0x40000010, 0x0401fe5d, 0x59e00017, 0x8c000508, - 0x04000003, 0x4a03c017, 0x00000000, 0x4203e000, - 0x30000001, 0x4203e000, 0x40000000, 0x0401f000, - 0x59a00c06, 0x800409c0, 0x04000007, 0x836c0580, - 0x00000000, 0x04000004, 0x4a034406, 0x0000001a, - 0x0401f62a, 0x42007000, 0x0010b33f, 0x58381c01, - 0x58382202, 0x8c040d00, 0x0400000b, 0x59a01207, - 0x82080500, 0x0000f003, 0x04020624, 0x82080480, - 0x00000841, 0x04021621, 0x82080480, 0x00000100, - 0x0400161e, 0x8c040d06, 0x04000003, 0x4a0378e4, - 0x000c0000, 0x8c040d04, 0x0400000c, 0x42000000, - 0x00001000, 0x50000000, 0x82000480, 0x24220001, - 0x04020003, 0x84040d04, 0x0401f004, 0x59e00002, - 0x84000548, 0x4803c002, 0x8c040d02, 0x04000005, - 0x42002800, 0x00007600, 0x4a002805, 0xd0000000, - 0x40040000, 0x800c0540, 0x48007401, 0x8c040d00, - 0x04000002, 0x48087202, 0x480f4406, 0x48134207, - 0x0401f5ae, 0x4d440000, 0x4d340000, 0x59a28c06, - 0x0201f800, 0x00020267, 0x04020009, 0x0201f800, - 0x00104842, 0x04000009, 0x4a034406, 0x00000009, - 0x5c026800, 0x5c028800, 0x0401f5ec, 0x5c026800, - 0x5c028800, 0x0401f5ed, 0x59a01207, 0x59a01c07, - 0x5934400a, 0x82203d00, 0x0000e000, 0x801c391a, - 0x8c081500, 0x04000019, 0x820c0d00, 0x00000007, - 0x82040580, 0x00000000, 0x04000007, 0x82040580, - 0x00000001, 0x04000004, 0x82040580, 0x00000003, - 0x040207eb, 0x82204500, 0xffff1fff, 0x800400da, - 0x80200540, 0x4802680a, 0x4c1c0000, 0x0201f800, - 0x0010698c, 0x0201f800, 0x00104afd, 0x0201f800, - 0x00106982, 0x5c003800, 0x481f4407, 0x5c026800, - 0x5c028800, 0x0401f579, 0x800409c0, 0x04000004, - 0x4a034406, 0x00000001, 0x0401f5c0, 0x836c0580, - 0x00000003, 0x04020010, 0x59a80010, 0x497b4406, - 0x0201f800, 0x00104e0d, 0x0400000f, 0x82000d00, - 0x00ffff00, 0x0402000c, 0x82000c00, 0x00101eb5, - 0x50040800, 0x80040910, 0x82041580, 0x00000080, - 0x04020004, 0x4a034406, 0x00000007, 0x0401f5ab, - 0x48074406, 0x82000d00, 0x0000ffff, 0x48074207, - 0x80000120, 0x48034407, 0x59a80026, 0x82001500, - 0x00000100, 0x480b4409, 0x8c000502, 0x0400001f, - 0x8c000506, 0x04000009, 0x82000d00, 0x0000000a, - 0x82040d80, 0x0000000a, 0x04020004, 0x4a034209, - 0x00000001, 0x0401f022, 0x8c00050a, 0x04000009, - 0x82000d00, 0x00000022, 0x82040d80, 0x00000022, - 0x04020004, 0x4a034209, 0x00000003, 0x0401f018, - 0x8c000508, 0x04000009, 0x82000d00, 0x00000012, - 0x82040d80, 0x00000012, 0x04020004, 0x4a034209, - 0x00000002, 0x0401f00e, 0x0201f800, 0x00104e0d, - 0x04020004, 0x4a034209, 0x00000004, 0x0401f52f, - 0x8c000506, 0x04000004, 0x4a034406, 0x00000005, - 0x0401f576, 0x4a034209, 0x00000000, 0x0401f527, - 0x59a80037, 0x48034407, 0x59a80038, 0x48034209, - 0x0401f522, 0x42007800, 0x0010b6eb, 0x59a00406, - 0x4803c857, 0x82000c80, 0x00000007, 0x0402156b, - 0x0c01f001, 0x00102354, 0x00102355, 0x00102363, - 0x00102376, 0x00102397, 0x00102354, 0x00102354, - 0x0401f562, 0x836c0580, 0x00000000, 0x0400055b, - 0x59a00a07, 0x59a00407, 0x900001c0, 0x80040d40, - 0x4807c857, 0x59a00a08, 0x59a00408, 0x900001c0, - 0x80040d40, 0x4807c857, 0x0401f056, 0x836c0580, - 0x00000000, 0x0400054d, 0x59a00407, 0x59a01207, - 0x900001c0, 0x80081540, 0x59a00408, 0x59a01a08, - 0x900001c0, 0x800c1d40, 0x42000000, 0x0010bfbe, - 0x480fc857, 0x480bc857, 0x42000800, 0x00001000, - 0x0201f000, 0x00103841, 0x59a00a07, 0x59a00407, - 0x900001c0, 0x80041d40, 0x820c0c80, 0x0010a971, - 0x0402153a, 0x820c0c80, 0x00100000, 0x04001537, - 0x480fc857, 0x823c7c00, 0x00000009, 0x503c0800, - 0x800409c0, 0x04000006, 0x823c0580, 0x0000000d, - 0x0400052e, 0x803c7800, 0x0401f7f9, 0x59e41001, - 0x82080d00, 0xfffeffcf, 0x4807c801, 0x440c7800, - 0x46001800, 0x0201f800, 0x800c1800, 0x46001800, - 0x00100608, 0x480bc801, 0x0401f022, 0x59a01a07, - 0x59a00407, 0x900001c0, 0x800c1d40, 0x480c7801, - 0x59a02208, 0x59a00408, 0x900001c0, 0x80102540, - 0x48107802, 0x59a00209, 0x80000040, 0x04001513, - 0x48007806, 0x80000000, 0x48007805, 0x42000800, - 0x00004000, 0x40001000, 0x0201f800, 0x001063cf, - 0x80000540, 0x04000003, 0x49787801, 0x0401f507, - 0x40040000, 0x800c1c00, 0x04001504, 0x480c7803, - 0x48107804, 0x49787808, 0x59a00409, 0x48007807, - 0x59e40001, 0x4803c857, 0x82000540, 0x00040000, - 0x4803c801, 0x0401f4a9, 0x59a80006, 0x48034406, - 0x59a80007, 0x48034207, 0x59a80008, 0x48034407, - 0x0401f4a2, 0x0201f800, 0x00100615, 0x4803c856, - 0x4a03c013, 0x03800300, 0x4a03c014, 0x03800380, - 0x59a00c06, 0x82040580, 0x000000a0, 0x04000004, - 0x82040580, 0x000000a2, 0x04020028, 0x59a0140a, - 0x82080480, 0x00000100, 0x04021024, 0x59a0020b, - 0x8c000500, 0x0402002b, 0x59a00a0a, 0x800409c0, - 0x0400001e, 0x82040480, 0x00000041, 0x0402101b, - 0x82040c00, 0x00000003, 0x82040d00, 0x000000fc, - 0x80040904, 0x59a00407, 0x59a01207, 0x900811c0, - 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0, - 0x800c1d40, 0x0201f800, 0x0010381a, 0x04020006, - 0x4a034406, 0x00000002, 0x4a03c014, 0x03800000, - 0x0401f4be, 0x0201f800, 0x0010383e, 0x4a01d809, - 0x001023fd, 0x1c01f000, 0x4a03c014, 0x03800000, - 0x0401f4ba, 0x4031d800, 0x58ef400b, 0x58ee580d, - 0x58ec0002, 0x82000580, 0x00000200, 0x040004a7, - 0x59a00c06, 0x59a0140a, 0x59a0020b, 0x8c000500, - 0x04020031, 0x832e5c00, 0x00000004, 0x41783800, - 0x59a04a0a, 0x401c0000, 0x812c0400, 0x50004000, - 0x82201d00, 0x000000ff, 0x4c040000, 0x0401f8af, - 0x5c000800, 0x0400002d, 0x80244840, 0x04000028, - 0x80081000, 0x82201d00, 0x0000ff00, 0x800c1910, - 0x4c040000, 0x0401f8a5, 0x5c000800, 0x04000023, - 0x80244840, 0x0400001e, 0x80081000, 0x82201d00, - 0x00ff0000, 0x800c1920, 0x4c040000, 0x0401f89b, - 0x5c000800, 0x04000019, 0x80244840, 0x04000014, - 0x80081000, 0x82201d00, 0xff000000, 0x800c1930, - 0x4c040000, 0x0401f891, 0x5c000800, 0x0400000f, - 0x80244840, 0x0400000a, 0x80081000, 0x801c3800, - 0x0401f7d5, 0x59a0020a, 0x82000500, 0x000000ff, - 0x40001800, 0x0401f885, 0x04000004, 0x4a03c014, - 0x03800000, 0x0401f425, 0x4a03c014, 0x03800000, - 0x0401f46e, 0x4803c856, 0x4a03c013, 0x03800300, - 0x4a03c014, 0x03800380, 0x59a00c06, 0x82040580, - 0x000000a0, 0x04000004, 0x82040580, 0x000000a2, - 0x0402006e, 0x59a0140a, 0x82080480, 0x00000100, - 0x0402106a, 0x59a0020b, 0x8c000500, 0x0402005c, - 0x59a01a0a, 0x800c19c0, 0x04000064, 0x820c0480, - 0x00000041, 0x04021061, 0x0201f800, 0x0010381a, - 0x04020006, 0x4a034406, 0x00000002, 0x4a03c014, - 0x03800000, 0x0401f44d, 0x832e5c00, 0x00000004, - 0x41783800, 0x59a04a0a, 0x401c0000, 0x812c0400, - 0x40004000, 0x4c040000, 0x4c080000, 0x0401f877, - 0x5c001000, 0x5c000800, 0x04000048, 0x44144000, - 0x80244840, 0x0400002b, 0x80081000, 0x4c040000, - 0x4c080000, 0x0401f86d, 0x5c001000, 0x5c000800, - 0x0400003e, 0x50200000, 0x801428d0, 0x80140540, - 0x44004000, 0x80244840, 0x0400001e, 0x80081000, - 0x4c040000, 0x4c080000, 0x0401f860, 0x5c001000, - 0x5c000800, 0x04000031, 0x50200000, 0x801428e0, - 0x80140540, 0x44004000, 0x80244840, 0x04000011, - 0x80081000, 0x4c040000, 0x4c080000, 0x0401f853, - 0x5c001000, 0x5c000800, 0x04000024, 0x50200000, - 0x801428f0, 0x80140540, 0x44004000, 0x80244840, - 0x04000004, 0x80081000, 0x801c3800, 0x0401f7cb, - 0x59a00a0a, 0x82040c00, 0x00000003, 0x82040d00, - 0x000000fc, 0x80040904, 0x59a00407, 0x59a01207, - 0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09, - 0x900c19c0, 0x800c1d40, 0x4a03c014, 0x03800000, - 0x412c0000, 0x0201f000, 0x00103841, 0x0401f833, - 0x04000006, 0x48174406, 0x4a03c014, 0x03800000, - 0x0201f000, 0x00102066, 0x4a03c014, 0x03800000, - 0x0201f000, 0x001020b2, 0x4a03c014, 0x03800000, - 0x0201f000, 0x001020b6, 0x0401f836, 0x04000010, - 0x0401f862, 0x0402000f, 0x40080800, 0x0401f85f, - 0x0402000c, 0x400c0800, 0x0401f85c, 0x04020009, - 0x0401f84b, 0x42000000, 0x00030d40, 0x80000040, - 0x040207ff, 0x82000540, 0x00000001, 0x1c01f000, - 0x0401f843, 0x80000580, 0x0401f7fd, 0x0401f821, - 0x0400000a, 0x82040d40, 0x00000001, 0x0401f84b, - 0x04020007, 0x0401f87e, 0x0401f898, 0x0401f838, - 0x82000540, 0x00000001, 0x1c01f000, 0x0401f834, - 0x80000580, 0x0401f7fd, 0x40041800, 0x0401f811, - 0x0400000c, 0x0401f83d, 0x0402000b, 0x40080800, - 0x0401f83a, 0x04020008, 0x400c0800, 0x0401ffe8, - 0x04000004, 0x0401f826, 0x82000540, 0x00000001, - 0x1c01f000, 0x0401f822, 0x80000580, 0x0401f7fd, - 0x4c040000, 0x42000800, 0x00000064, 0x4a03c013, - 0x03800300, 0x80040840, 0x04000016, 0x59e00013, - 0x82000500, 0x00000300, 0x82000580, 0x00000300, - 0x040207f7, 0x42000000, 0x00000064, 0x80000040, - 0x040207ff, 0x4a03c013, 0x01000000, 0x42000000, - 0x00000064, 0x80000040, 0x040207ff, 0x4a03c013, - 0x02000000, 0x82000540, 0x00000001, 0x0401f002, - 0x80000580, 0x5c000800, 0x1c01f000, 0x4a03c013, - 0x01000000, 0x42000000, 0x00000064, 0x80000040, - 0x040207ff, 0x4a03c013, 0x02000200, 0x42000000, - 0x00000064, 0x80000040, 0x040207ff, 0x4a03c013, - 0x01000100, 0x1c01f000, 0x42002000, 0x00000008, - 0x82040500, 0x00000080, 0x800000c2, 0x82000540, - 0x01000000, 0x4803c013, 0x42000000, 0x00000064, - 0x80000040, 0x040207ff, 0x4a03c013, 0x02000200, - 0x42000000, 0x00000064, 0x80000040, 0x040207ff, - 0x4a03c013, 0x02000000, 0x800408c2, 0x80102040, - 0x040207ec, 0x4a03c013, 0x01000100, 0x42000000, - 0x00000064, 0x80000040, 0x040207ff, 0x4a03c013, - 0x02000200, 0x42000000, 0x00000064, 0x80000040, - 0x040207ff, 0x59e00013, 0x82000500, 0x00000100, - 0x4a03c013, 0x02000000, 0x4c040000, 0x42000800, - 0x00000064, 0x59e00013, 0x82000500, 0x00000100, - 0x80040840, 0x04000003, 0x80000540, 0x040207fa, - 0x80000540, 0x5c000800, 0x1c01f000, 0x4a03c013, - 0x01000100, 0x42001000, 0x00000008, 0x80000d80, - 0x42000000, 0x00000064, 0x80000040, 0x040207ff, - 0x4a03c013, 0x02000200, 0x42000000, 0x00000064, - 0x80000040, 0x040207ff, 0x59e00013, 0x82000500, - 0x00000100, 0x80000110, 0x800408c2, 0x80040d40, - 0x4a03c013, 0x02000000, 0x80081040, 0x040207ed, - 0x40042800, 0x1c01f000, 0x4a03c013, 0x01000100, - 0x42000000, 0x00000064, 0x80000040, 0x040207ff, - 0x4a03c013, 0x02000200, 0x42000000, 0x00000064, - 0x80000040, 0x040207ff, 0x4a03c013, 0x02000000, - 0x1c01f000, 0x59a00407, 0x59a80837, 0x48035037, - 0x48074407, 0x59a00a09, 0x82040480, 0x00000014, - 0x04021003, 0x42000800, 0x000007d0, 0x59a80038, - 0x48075038, 0x48034209, 0x0201f000, 0x00102066, - 0x836c0580, 0x00000000, 0x0400000e, 0x59a80006, - 0x59a00c06, 0x80041580, 0x82081500, 0x00000040, - 0x02000000, 0x00102066, 0x80080580, 0x48035006, - 0x0201f800, 0x001006df, 0x0201f000, 0x00102066, - 0x59a00406, 0x59a80806, 0x48035006, 0x80040d80, - 0x8c040d0c, 0x02020800, 0x001006df, 0x59a00207, - 0x48035007, 0x59a00407, 0x48035008, 0x0201f000, - 0x00102066, 0x800409c0, 0x04000005, 0x4a034406, - 0x00000001, 0x0201f000, 0x001020b2, 0x0201f800, - 0x00104e0d, 0x04020005, 0x4a034406, 0x00000016, - 0x0201f000, 0x001020b2, 0x836c0580, 0x00000003, - 0x04000005, 0x4a034406, 0x00000007, 0x0201f000, - 0x001020b2, 0x59a00c06, 0x82040500, 0xffffff00, - 0x02020000, 0x001020b6, 0x82041580, 0x000000ff, - 0x04020007, 0x59a80010, 0x82000500, 0x000000ff, - 0x82001540, 0x0000ff00, 0x0401f011, 0x82040400, - 0x00101eb5, 0x50000000, 0x80000110, 0x82000580, - 0x00000080, 0x02000000, 0x001020b6, 0x59a80010, - 0x82000500, 0x000000ff, 0x80041580, 0x02000000, - 0x001020b6, 0x840409c0, 0x80041540, 0x0201f800, - 0x00020892, 0x04020005, 0x4a034406, 0x00000003, - 0x0201f000, 0x001020b2, 0x48ee6021, 0x480a621c, - 0x4a02641c, 0x0000bc09, 0x4a026406, 0x00000001, - 0x0201f800, 0x0010381a, 0x04020007, 0x0201f800, - 0x000208b4, 0x4a034406, 0x00000002, 0x0201f000, - 0x001020b2, 0x497a5a04, 0x497a5805, 0x4a025c04, - 0x00008000, 0x4a01d809, 0x00102657, 0x492e6008, - 0x42027000, 0x00000032, 0x0201f000, 0x000208d8, - 0x800409c0, 0x04000005, 0x4a034406, 0x00000001, - 0x0201f000, 0x001020b2, 0x0201f800, 0x00104e0d, - 0x04020005, 0x4a034406, 0x00000016, 0x0201f000, - 0x001020b2, 0x836c0580, 0x00000003, 0x04000005, - 0x4a034406, 0x00000007, 0x0201f000, 0x001020b2, - 0x59a00c06, 0x82040500, 0xffffff00, 0x02020000, - 0x001020b6, 0x82041580, 0x000000ff, 0x04020007, - 0x59a80010, 0x82000500, 0x000000ff, 0x82001540, - 0x0000ff00, 0x0401f011, 0x82040400, 0x00101eb5, - 0x50000000, 0x80000110, 0x82000580, 0x00000080, - 0x02000000, 0x001020b6, 0x59a80010, 0x82000500, - 0x000000ff, 0x80041580, 0x02000000, 0x001020b6, - 0x840409c0, 0x80041540, 0x0201f800, 0x00020892, - 0x04020005, 0x4a034406, 0x00000003, 0x0201f000, - 0x001020b2, 0x48ee6021, 0x480a621c, 0x4a02641c, - 0x0000bc05, 0x4a026406, 0x00000001, 0x0201f800, - 0x0010381a, 0x04020007, 0x0201f800, 0x000208b4, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x497a5a04, 0x497a5805, 0x4a025c04, 0x00008000, - 0x4a01d809, 0x00102657, 0x492e6008, 0x42027000, - 0x00000032, 0x0201f000, 0x000208d8, 0x592c0005, - 0x82000580, 0x01000000, 0x02020000, 0x00102066, - 0x4a034406, 0x00000004, 0x0201f000, 0x001020b2, - 0x497b4406, 0x497b4207, 0x0201f800, 0x0010393e, - 0x04000008, 0x59a80066, 0x59a8086a, 0x80040480, - 0x59a80867, 0x48074406, 0x80041480, 0x480b4207, - 0x49674407, 0x59a8000e, 0x48034209, 0x495f4409, - 0x59a80020, 0x4803420b, 0x0201f000, 0x00102066, - 0x800409c0, 0x04000005, 0x4a034406, 0x00000001, - 0x0201f000, 0x001020b2, 0x59a00406, 0x8c000500, - 0x0402000f, 0x59a80069, 0x81640480, 0x04001008, - 0x59a8000b, 0x81500580, 0x04000009, 0x59a8006a, - 0x59a81066, 0x80080580, 0x04000005, 0x4a034406, - 0x00000018, 0x0201f000, 0x001020b2, 0x59a80005, - 0x84000558, 0x48035005, 0x82000540, 0x00000001, - 0x0201f800, 0x00101668, 0x0201f800, 0x00103a9f, - 0x0201f000, 0x00102066, 0x4803c856, 0x800409c0, - 0x02020000, 0x001020ba, 0x59a00406, 0x8c00051e, - 0x04000008, 0x4803c856, 0x59a0020b, 0x82000480, - 0x00000800, 0x04001015, 0x0201f000, 0x001020b6, - 0x4803c856, 0x59a0020b, 0x599c0a01, 0x80040480, - 0x04021003, 0x0201f000, 0x001020b6, 0x59a8000e, - 0x81640580, 0x04000009, 0x4a034406, 0x00000018, - 0x0201f000, 0x001020b2, 0x4a034406, 0x00000005, - 0x0201f000, 0x001020b2, 0x59a80026, 0x8c00050a, - 0x040007fa, 0x59a00406, 0x8c00051e, 0x04000036, - 0x0201f800, 0x00020892, 0x040007f4, 0x0201f800, - 0x0010381a, 0x040007f1, 0x497a5a04, 0x59a00406, - 0x4802620a, 0x59a00209, 0x4802640a, 0x59a00409, - 0x4802620b, 0x59a0020d, 0x4802620c, 0x59a0040d, - 0x4802640c, 0x59a0020e, 0x4802620d, 0x59a0040e, - 0x4802640d, 0x59a00210, 0x4802620e, 0x59a00410, - 0x4802640e, 0x59a0020b, 0x82000500, 0x0000fffc, - 0x80000104, 0x4802640b, 0x0401f9d9, 0x040007d7, - 0x48ee6021, 0x58ee580d, 0x5930020e, 0x59301c0e, - 0x900c19c0, 0x800c1d40, 0x5930020c, 0x5930140c, - 0x900811c0, 0x80081540, 0x592c0a05, 0x832c0400, - 0x00000006, 0x0201f800, 0x0010383e, 0x4a01d809, - 0x00102846, 0x4a034000, 0x00000001, 0x49334001, - 0x1c01f000, 0x0201f800, 0x0010698c, 0x0201f800, - 0x00100b29, 0x0401f86d, 0x497b5057, 0x4201d000, - 0x00002710, 0x0201f800, 0x00105e06, 0x59c40880, - 0x4c040000, 0x59c408a3, 0x4c040000, 0x497b4002, - 0x0401f876, 0x0401f893, 0x4a03a005, 0x10000000, - 0x0401f8b4, 0x0401f901, 0x04000048, 0x59c80001, - 0x800001c0, 0x040007fc, 0x59c80018, 0x82000500, - 0xf0000000, 0x59c00808, 0x82040d00, 0x0fffffff, - 0x80040540, 0x48038008, 0x0201f800, 0x00100f0f, - 0x59c00006, 0x4a038006, 0x10000000, 0x59c00009, - 0x82000d00, 0x00e00000, 0x04020024, 0x4a03900d, - 0x00000000, 0x59c80020, 0x82000500, 0xff000000, - 0x82000580, 0x32000000, 0x0402001c, 0x4a03900d, - 0x00000001, 0x59c80020, 0x82000500, 0xff000000, - 0x82000580, 0xe1000000, 0x04020014, 0x4a03900d, - 0x00000000, 0x59c80020, 0x82000500, 0x00ffffff, - 0x4a03900d, 0x00000000, 0x59c80821, 0x82040d00, - 0x00ffffff, 0x80040580, 0x04020008, 0x59a80010, - 0x80040580, 0x04020005, 0x59c40005, 0x82000500, - 0x000000f0, 0x04000006, 0x4803c856, 0x0401f8d7, - 0x4a035057, 0x00000001, 0x0401f002, 0x0401f8e1, - 0x42000000, 0x00000064, 0x80000040, 0x02000800, - 0x00100615, 0x59c00807, 0x82040d00, 0x0000000c, - 0x040007fa, 0x0401f003, 0x4a035057, 0x00000001, - 0x0401f8da, 0x0201f800, 0x00106c8a, 0x0401f818, - 0x4201d000, 0x000186a0, 0x0201f800, 0x00105e06, - 0x5c000800, 0x480788a3, 0x5c000800, 0x48078880, - 0x59a80057, 0x800001c0, 0x02000000, 0x00102066, - 0x0201f000, 0x001020be, 0x599c0201, 0x48035059, - 0x41780800, 0x42001000, 0x00003b10, 0x0201f800, - 0x001063ee, 0x480b505a, 0x1c01f000, 0x0201f800, - 0x00106982, 0x59b800ea, 0x82000500, 0x00000007, - 0x82000580, 0x00000003, 0x04020003, 0x4a0370e8, - 0x00000001, 0x1c01f000, 0x42038000, 0x00007700, - 0x4a038006, 0x30000000, 0x59c00007, 0x8c00050a, - 0x040207fe, 0x59c00006, 0x59a00209, 0x59a00c09, - 0x900409c0, 0x80040d40, 0x48078001, 0x59a0020e, - 0x59a00c0e, 0x900409c0, 0x80040d40, 0x48078000, - 0x59a0020b, 0x82000500, 0x0000fffc, 0x48038002, - 0x48038003, 0x48038005, 0x497b9009, 0x59e00003, - 0x82000540, 0x00008060, 0x4803c003, 0x1c01f000, - 0x41780800, 0x8007a0ca, 0x83d3a400, 0x00007600, - 0x42000800, 0x00000040, 0x0201f800, 0x00101395, - 0x4a03a00a, 0x00000001, 0x4a03a005, 0x20000000, - 0x59d00006, 0x4a03a005, 0x30000000, 0x59d00006, - 0x8c00050a, 0x040207fe, 0x59d00005, 0x59a00210, - 0x59a00c10, 0x900409c0, 0x80040d40, 0x4807a001, - 0x59a0020d, 0x59a00c0d, 0x900409c0, 0x80040d40, - 0x4807a000, 0x59a0020b, 0x82000500, 0x0000fffc, - 0x4803a003, 0x4803a002, 0x4803a008, 0x1c01f000, - 0x59a00002, 0x4803c857, 0x800001c0, 0x0402004a, - 0x59a8005a, 0x48038880, 0x59c400a3, 0x82000540, - 0x00002008, 0x8400053a, 0x480388a3, 0x59c40008, - 0x8400054e, 0x82000500, 0xffffffe1, 0x48038808, - 0x59c80040, 0x84000534, 0x48039040, 0x0401f902, - 0x04020013, 0x59a80010, 0x800000d0, 0x82000540, - 0x00000011, 0x48039120, 0x59a80010, 0x82000500, - 0x00ffffff, 0x82000540, 0x32000000, 0x48039121, - 0x4a039123, 0xe1290008, 0x59a80010, 0x82000500, - 0x00ffffff, 0x48039122, 0x0401f016, 0x59a80010, - 0x82000500, 0x000000ff, 0x900009c0, 0x840001c0, - 0x80040540, 0x82000540, 0x00000000, 0x48039120, - 0x59a80010, 0x82000500, 0x000000ff, 0x82000540, - 0x01000000, 0x48039121, 0x4a039123, 0x08210008, - 0x59a80010, 0x82000500, 0x000000ff, 0x48039122, - 0x497b9124, 0x59a80c5b, 0x80040800, 0x4807545b, - 0x900409c0, 0x82040540, 0x0000aaaa, 0x48039125, - 0x497b9126, 0x497b9127, 0x0401f8cf, 0x04020004, - 0x4a039100, 0x0000e980, 0x0401f003, 0x4a039100, - 0x0000e9a0, 0x1c01f000, 0x82000540, 0x00000001, - 0x0402500d, 0x4203e000, 0x80000000, 0x40e81000, - 0x41780800, 0x42000000, 0x00000064, 0x0201f800, - 0x001063ee, 0x59940024, 0x80080400, 0x48032824, - 0x80000580, 0x1c01f000, 0x4d900000, 0x4dd00000, - 0x4da40000, 0x4d140000, 0x417a3000, 0x0201f800, - 0x00106e2f, 0x0201f800, 0x00106b13, 0x5c022800, - 0x5c034800, 0x5c03a000, 0x5c032000, 0x1c01f000, - 0x59c80007, 0x8c000500, 0x04000003, 0x4a03900d, - 0x00000030, 0x1c01f000, 0x4a038805, 0x00020000, - 0x42000800, 0x0000003c, 0x0201f800, 0x00101395, - 0x4a038891, 0x0000ffff, 0x59c80035, 0x48039035, - 0x4a03900d, 0x00000040, 0x42038000, 0x00007700, - 0x0201f800, 0x00100f0f, 0x42038000, 0x00007720, - 0x0201f800, 0x00100f0f, 0x4a03a005, 0x20000000, - 0x4a03a005, 0x30000000, 0x59d00806, 0x8c040d0a, - 0x040207fe, 0x1c01f000, 0x4d300000, 0x4031d800, - 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580, - 0x00000200, 0x5c026000, 0x02000000, 0x001020aa, - 0x4d300000, 0x59a26001, 0x59a00000, 0x4000b000, - 0x80000000, 0x48034000, 0x592c0001, 0x80000540, - 0x0400001e, 0x40025800, 0x8058b040, 0x040207fb, - 0x58ec1007, 0x58ec1808, 0x592c0a05, 0x4d2c0000, - 0x58ec000d, 0x40025800, 0x592c0204, 0x5c025800, - 0x82000580, 0x00000103, 0x04000008, 0x832c0400, - 0x00000006, 0x0201f800, 0x0010383e, 0x4a01d809, - 0x00102846, 0x0401f007, 0x832c0400, 0x00000006, - 0x0201f800, 0x00103841, 0x4a01d809, 0x00102846, - 0x5c026000, 0x1c01f000, 0x58ec000d, 0x40025800, - 0x592c0204, 0x82000580, 0x00000103, 0x04020006, - 0x0201f800, 0x000208b4, 0x5c026000, 0x0201f000, - 0x00102066, 0x58ec000d, 0x40025800, 0x592c0404, - 0x8400055e, 0x48025c04, 0x42028800, 0x000007fd, - 0x42003000, 0x00fffffd, 0x0201f800, 0x001043fc, - 0x04000003, 0x80000580, 0x0401f004, 0x59a26001, - 0x0201f800, 0x00109146, 0x5c026000, 0x02000000, - 0x001020b2, 0x4d300000, 0x4a01d809, 0x00102899, - 0x0401f7dc, 0x592c0005, 0x82000580, 0x01000000, - 0x02000000, 0x001020be, 0x4d300000, 0x59a26001, - 0x5930020b, 0x59301c0a, 0x900001c0, 0x800c1d40, - 0x5930040d, 0x5930120d, 0x900001c0, 0x80081540, - 0x592c0a05, 0x832c0400, 0x00000006, 0x0201f800, - 0x00103841, 0x4a01d809, 0x00102846, 0x4a034000, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4933c857, - 0x4c300000, 0x5930040b, 0x82000c80, 0x0000000e, - 0x04001004, 0x4a025a05, 0x0000000e, 0x0401f003, - 0x48025a05, 0x0401f00c, 0x800409c0, 0x0400000a, - 0x4c040000, 0x0201f800, 0x0010381a, 0x5c000800, - 0x04000003, 0x40040000, 0x0401f7f0, 0x80000580, - 0x0401f003, 0x82000540, 0x00000001, 0x5c006000, - 0x1c01f000, 0x59a00206, 0x82000580, 0x00000044, - 0x1c01f000, 0x4807c857, 0x800409c0, 0x0400000c, - 0x0201f800, 0x001016c1, 0x04020009, 0x42000000, - 0x00000002, 0x0201f800, 0x001018fa, 0x42000000, - 0x00000002, 0x0201f800, 0x00101892, 0x59a00406, - 0x82000500, 0x00000007, 0x0c01f001, 0x001028ed, - 0x00102902, 0x00102918, 0x001028eb, 0x001028eb, - 0x001028eb, 0x001028eb, 0x001028eb, 0x0201f000, - 0x001020b6, 0x42000800, 0x000000c0, 0x0201f800, - 0x001019ac, 0x82040540, 0x00000002, 0x42000800, - 0x000000c0, 0x0201f800, 0x001019b1, 0x42000800, - 0x00000000, 0x0201f800, 0x001019ac, 0x82040540, - 0x00000008, 0x42000800, 0x00000000, 0x0201f800, - 0x001019b1, 0x0401f00b, 0x42000800, 0x000000c0, - 0x0201f800, 0x001019ac, 0x82040540, 0x00000001, - 0x42000800, 0x000000c0, 0x0201f800, 0x001019b1, - 0x59c80040, 0x4c000000, 0x59a80010, 0x4c000000, - 0x59c400a3, 0x4c000000, 0x59c40008, 0x4c000000, - 0x0401f911, 0x04000021, 0x0201f800, 0x00100615, - 0x59a80821, 0x800409c0, 0x02020000, 0x001020ba, - 0x0201f800, 0x00104e0d, 0x04020005, 0x4a034406, - 0x00000016, 0x0201f000, 0x001020b2, 0x836c0580, - 0x00000003, 0x02020000, 0x001020ba, 0x59c408a4, - 0x82040d00, 0x0000000f, 0x82040580, 0x00000000, - 0x02020000, 0x001020ba, 0x59c80040, 0x4c000000, - 0x59a80010, 0x4c000000, 0x59c400a3, 0x4c000000, - 0x59c40008, 0x4c000000, 0x59c40080, 0x4c000000, - 0x59a0020f, 0x59a0bc0f, 0x905cb9c0, 0x805cbd40, - 0x41784800, 0x41785000, 0x41785800, 0x41789000, - 0x41789800, 0x0401fe21, 0x0201f800, 0x0010698c, - 0x0201f800, 0x00100b29, 0x4178c000, 0x497b4002, - 0x0401f95c, 0x0401f9aa, 0x59a0020c, 0x59a00c0c, - 0x80040d40, 0x04000002, 0x0401f9fb, 0x0401f9fa, - 0x0401fe68, 0x8060c1c0, 0x04020014, 0x0401fa98, - 0x0401feb2, 0x0402000e, 0x0201f800, 0x00101941, - 0x04020008, 0x4a034406, 0x00000017, 0x0201f800, - 0x001020b2, 0x4203e000, 0x50000000, 0x0401f000, - 0x42005800, 0x0000aaaa, 0x0401f058, 0x59c80001, - 0x800001c0, 0x040007ee, 0x59c80801, 0x800409c0, - 0x04000006, 0x0401fa70, 0x40240000, 0x80280540, - 0x802c0540, 0x0402004d, 0x59a00002, 0x82000580, - 0xfeedbeef, 0x04000004, 0x42008800, 0x10000000, - 0x0401f003, 0x42008800, 0x10000004, 0x0401fa19, - 0x4a034002, 0xfeedbeef, 0x0401fa71, 0x0401fa97, - 0x0401fea8, 0x59c40005, 0x8c000534, 0x04000004, - 0x42005800, 0x0000bbbb, 0x0401f038, 0x0401fe83, - 0x04020007, 0x42005800, 0x0000cccc, 0x485f420f, - 0x905cb9c0, 0x485f440f, 0x0401f030, 0x59a0040c, - 0x800001c0, 0x0400000e, 0x59a26000, 0x5930000d, - 0x800001c0, 0x040207be, 0x59a26001, 0x5930080d, - 0x800409c0, 0x040207ba, 0x804891c0, 0x040207b8, - 0x804c99c0, 0x040207b6, 0x0401f87a, 0x805cb840, - 0x04000005, 0x40240000, 0x80280540, 0x802c0540, - 0x0402001a, 0x42000000, 0x00030d40, 0x80000040, - 0x04020012, 0x59c00007, 0x82000500, 0x000501c0, - 0x0402000b, 0x0201f800, 0x00101941, 0x04020008, - 0x4a034406, 0x00000017, 0x0201f800, 0x001020b2, - 0x4203e000, 0x50000000, 0x0401f000, 0x42005800, - 0x0000dddd, 0x0401f005, 0x59c00807, 0x82040d00, - 0x0000000c, 0x040007ea, 0x0401fe5c, 0x59a0040c, - 0x800001c0, 0x04000002, 0x0401f856, 0x0401fe6b, - 0x40240000, 0x80280540, 0x802c0540, 0x04020003, - 0x805cb9c0, 0x04020781, 0x0201f800, 0x00106c8a, - 0x0401fda3, 0x4201d000, 0x000186a0, 0x0201f800, - 0x00105e06, 0x5c000800, 0x48078880, 0x5c000800, - 0x48078808, 0x5c000800, 0x480788a3, 0x5c000800, - 0x48075010, 0x5c000800, 0x48079040, 0x0201f800, - 0x001009b6, 0x59a00406, 0x82000500, 0x00000003, - 0x82000580, 0x00000002, 0x0400002c, 0x42000800, - 0x000000c0, 0x0201f800, 0x001019ac, 0x82040500, - 0xfffffffc, 0x42000800, 0x000000c0, 0x0201f800, - 0x001019b1, 0x42000800, 0x00000000, 0x0201f800, - 0x001019ac, 0x82040500, 0xfffffff7, 0x42000800, - 0x00000000, 0x0201f800, 0x001019b1, 0x42000800, - 0x00000000, 0x0201f800, 0x001019ac, 0x82040500, - 0xfffffffb, 0x42000800, 0x00000000, 0x0201f800, - 0x001019b1, 0x4a0388a7, 0x0000f7f7, 0x42006000, - 0xbeffffff, 0x42006800, 0x80018000, 0x0201f800, - 0x001040ad, 0x42006000, 0xfffeffff, 0x41786800, - 0x0201f800, 0x001040ad, 0x402c0000, 0x80280540, - 0x80240540, 0x02000000, 0x00102066, 0x48274406, - 0x482b4207, 0x482f4407, 0x0201f000, 0x001020c2, - 0x59a26000, 0x813261c0, 0x0400000e, 0x59325808, - 0x812e59c0, 0x0400000b, 0x0201f800, 0x000208b4, - 0x0201f800, 0x00100843, 0x59a26001, 0x59325808, - 0x0201f800, 0x000208b4, 0x0201f800, 0x00100843, - 0x1c01f000, 0x42000800, 0x000000ef, 0x0201f800, - 0x00101655, 0x59c400a3, 0x8400055a, 0x8400053a, - 0x480388a3, 0x0201f800, 0x001016ac, 0x0402000a, - 0x42000000, 0x00000001, 0x0201f800, 0x001018fa, - 0x42000000, 0x00000001, 0x0201f800, 0x00101892, - 0x0401f013, 0x0201f800, 0x001016b3, 0x04020008, - 0x41780000, 0x0201f800, 0x001018fa, 0x41780000, - 0x0201f800, 0x00101892, 0x0401f009, 0x42000000, - 0x00000002, 0x0201f800, 0x001018fa, 0x42000000, - 0x00000002, 0x0201f800, 0x00101892, 0x42000800, - 0x00000000, 0x0201f800, 0x001019ac, 0x82040540, - 0x00000004, 0x42000800, 0x00000000, 0x0201f800, - 0x001019b1, 0x4201d000, 0x00000014, 0x0201f800, - 0x00105dd2, 0x59c40008, 0x8400054e, 0x82000500, - 0xffffffe1, 0x48038808, 0x4a0388a7, 0x0000f7f7, - 0x42001000, 0x04000001, 0x0201f800, 0x001019aa, - 0x42006000, 0xbe20bfff, 0x42006800, 0x80018000, - 0x0201f800, 0x001040ad, 0x42006000, 0xfffeffff, - 0x41786800, 0x0201f800, 0x001040ad, 0x4200b000, - 0x00001388, 0x4201d000, 0x00000014, 0x4c580000, - 0x0201f800, 0x00105dd2, 0x0201f800, 0x00101941, - 0x5c00b000, 0x04000004, 0x8058b040, 0x040207f6, - 0x0401f025, 0x59c40005, 0x8c000534, 0x04020007, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, - 0x00000008, 0x0402001c, 0x42006000, 0x00020000, - 0x0201f800, 0x001040b2, 0x4201d000, 0x00000064, - 0x0201f800, 0x00105dd2, 0x42006000, 0xfeffffff, - 0x42006800, 0x02000000, 0x0201f800, 0x001040ad, - 0x42006000, 0xfdffffff, 0x41786800, 0x0201f800, - 0x001040ad, 0x4a038805, 0x04000001, 0x59c400a4, - 0x82000500, 0x0000000f, 0x82000580, 0x00000000, - 0x04000003, 0x82000540, 0x00000001, 0x1c01f000, - 0x4803c856, 0x42038000, 0x00007700, 0x0201f800, - 0x00100f0f, 0x59c00006, 0x59a0040c, 0x800001c0, - 0x0400003f, 0x59a03c0c, 0x59a00209, 0x59a01c09, - 0x900c19c0, 0x800c1d40, 0x59a0020e, 0x59a0240e, - 0x901021c0, 0x80102540, 0x59a0020b, 0x82000500, - 0x0000fffc, 0x59a0140b, 0x900811c0, 0x80081540, - 0x480b8003, 0x0201f800, 0x00020892, 0x02000800, - 0x00100615, 0x49334000, 0x0201f800, 0x0010082a, - 0x4a025a04, 0x00000018, 0x4a025805, 0x00abcdef, - 0x492e6008, 0x492e600b, 0x481e600d, 0x4a02600c, - 0x00000004, 0x832c0400, 0x00000011, 0x4802600a, - 0x42001000, 0x0000000c, 0x821c0d80, 0x00000001, - 0x04000004, 0x801c3840, 0x0401f963, 0x0401f004, - 0x41783800, 0x0401f960, 0x0401f011, 0x821c0c80, - 0x00000005, 0x04001005, 0x40043800, 0x42001000, - 0x0000003c, 0x0401f006, 0x80001580, 0x82081400, - 0x0000000c, 0x801c3840, 0x040207fd, 0x832c0400, - 0x00000005, 0x0401f950, 0x040207f1, 0x497b9009, - 0x59e00003, 0x82000540, 0x00008060, 0x4803c003, - 0x4a038009, 0x00e00000, 0x1c01f000, 0x4803c856, - 0x41780800, 0x8007a0ca, 0x83d3a400, 0x00007600, - 0x42000800, 0x00000040, 0x0201f800, 0x00101395, - 0x4a03a00a, 0x00000001, 0x4a03a005, 0x20000000, - 0x59d00006, 0x4a03a005, 0x30000000, 0x59d00006, - 0x8c00050a, 0x040207fe, 0x59d00005, 0x59a0020c, - 0x800001c0, 0x0400003f, 0x59a03a0c, 0x59a00210, - 0x59a01c10, 0x900c19c0, 0x800c1d40, 0x59a0020d, - 0x59a0240d, 0x901021c0, 0x80102540, 0x59a0120b, - 0x82081500, 0x0000fffc, 0x59a0040b, 0x900001c0, - 0x80081540, 0x480ba003, 0x0201f800, 0x00020892, - 0x02000800, 0x00100615, 0x49334001, 0x0201f800, - 0x0010082a, 0x4a025a04, 0x00000018, 0x4a025805, - 0x00abcdef, 0x492e6008, 0x492e600b, 0x481e600d, - 0x4a02600c, 0x00000004, 0x832c0400, 0x00000011, - 0x4802600a, 0x42001000, 0x0000000c, 0x821c0d80, - 0x00000001, 0x04000004, 0x801c3840, 0x0401f906, - 0x0401f004, 0x41783800, 0x0401f903, 0x0401f011, - 0x821c0c80, 0x00000005, 0x04001005, 0x40043800, - 0x42001000, 0x0000003c, 0x0401f006, 0x80001580, - 0x82081400, 0x0000000c, 0x801c3840, 0x040207fd, - 0x832c0400, 0x00000005, 0x0401f8f3, 0x040207f1, - 0x1c01f000, 0x4803c856, 0x59a0020c, 0x800001c0, - 0x04000024, 0x824c0580, 0x00000002, 0x04000040, - 0x59a26001, 0x5930380d, 0x801c39c0, 0x0400003c, - 0x801c3840, 0x481e600d, 0x5932580b, 0x5930080a, - 0x50042000, 0x58041801, 0x58041002, 0x82081500, - 0xfffffffc, 0x5930000c, 0x80000000, 0x82000d80, - 0x00000005, 0x04020009, 0x497a600c, 0x592e5801, - 0x812e59c0, 0x0400001a, 0x492e600b, 0x832c0c00, - 0x00000005, 0x0401f005, 0x4802600c, 0x5930080a, - 0x82040c00, 0x00000003, 0x4806600a, 0x0401f010, - 0x59a0120b, 0x82081500, 0x0000fffc, 0x59a0040b, - 0x900001c0, 0x80081540, 0x480ba003, 0x59a0020d, - 0x59a0240d, 0x901021c0, 0x80102540, 0x59a00210, - 0x59a01c10, 0x900c19c0, 0x800c1d40, 0x4201d000, - 0x00003a98, 0x0201f800, 0x00105e06, 0x480ba002, - 0x59a80059, 0x4803a008, 0x4813a000, 0x480fa001, - 0x4a03a005, 0x10000000, 0x02005800, 0x00100615, - 0x804c9800, 0x82000540, 0x00000001, 0x1c01f000, - 0x4847c857, 0x59a0040c, 0x800001c0, 0x04000024, - 0x82480580, 0x00000002, 0x04000042, 0x59a26000, - 0x5930380d, 0x801c39c0, 0x0400003e, 0x801c3840, - 0x481e600d, 0x5932580b, 0x5930080a, 0x50042000, - 0x58041801, 0x58041002, 0x82081500, 0xfffffffc, - 0x5930000c, 0x80000000, 0x82000d80, 0x00000005, - 0x04020009, 0x497a600c, 0x592e5801, 0x812e59c0, - 0x0400001d, 0x492e600b, 0x832c0c00, 0x00000005, - 0x0401f005, 0x4802600c, 0x5930080a, 0x82040c00, - 0x00000003, 0x4806600a, 0x0401f013, 0x82440580, - 0x10000000, 0x0402001f, 0x59a0020e, 0x59a0240e, - 0x901021c0, 0x80102540, 0x59a00209, 0x59a01c09, - 0x900c19c0, 0x800c1d40, 0x59a0020b, 0x82000500, - 0x0000fffc, 0x59a0140b, 0x900811c0, 0x80081540, - 0x480b8003, 0x48138000, 0x480f8001, 0x480b8002, - 0x59c80018, 0x82000500, 0xf0000000, 0x59c02008, - 0x82102500, 0x0fffffff, 0x80100540, 0x48038008, - 0x48478006, 0x80489000, 0x8260c540, 0x00000001, - 0x1c01f000, 0x59c00009, 0x4803c857, 0x82000d00, - 0x00e00000, 0x0400000d, 0x485f420f, 0x905cb9c0, - 0x485f440f, 0x8c00052e, 0x04000002, 0x80285000, - 0x8c00052c, 0x04000002, 0x80244800, 0x8c00052a, - 0x04000002, 0x802c5800, 0x1c01f000, 0x59a0020c, - 0x800001c0, 0x04000024, 0x59d00806, 0x4807c857, - 0x8c040d3e, 0x04000020, 0x4a03a005, 0x20000000, - 0x4a03a005, 0x30000000, 0x59d00806, 0x8c040d0a, - 0x040207fe, 0x824c0480, 0x00000003, 0x02021800, - 0x00100615, 0x404c0000, 0x0c01f001, 0x00102c02, - 0x00102c04, 0x00102c0a, 0x0201f800, 0x00100615, - 0x80000040, 0x40009800, 0x0401ff43, 0x0400000a, - 0x0401ff41, 0x0401f008, 0x80000040, 0x40009800, - 0x59d00806, 0x4807c857, 0x8c040d3e, 0x040207e3, - 0x0401ff39, 0x1c01f000, 0x59a0040c, 0x800001c0, - 0x04000024, 0x59c00807, 0x4807c857, 0x8c040d3e, - 0x04000020, 0x59c00807, 0x4a038006, 0x20000000, - 0x82480480, 0x00000003, 0x02021800, 0x00100615, - 0x40480000, 0x0c01f001, 0x00102c25, 0x00102c27, - 0x00102c2f, 0x0201f800, 0x00100615, 0x80000040, - 0x40009000, 0x42008800, 0x10000004, 0x0401ff65, - 0x0400000c, 0x0401ff63, 0x0401f00a, 0x80000040, - 0x40009000, 0x59c00807, 0x4807c857, 0x8c040d3e, - 0x040207e5, 0x42008800, 0x10000004, 0x0401ff59, - 0x1c01f000, 0x492fc857, 0x4000a800, 0x4a03b805, - 0x20000000, 0x59dc0006, 0x4a03b805, 0x30000000, - 0x4813b800, 0x480fb801, 0x480bb802, 0x4857b803, - 0x4a03b805, 0x30000002, 0x59dc0006, 0x4a03b805, - 0x70000001, 0x59dc0006, 0x4a03b805, 0x10000000, - 0x59dc0006, 0x8c00053e, 0x040007fe, 0x4a03b805, - 0x20000000, 0x59dc0006, 0x59dc2000, 0x59dc1801, - 0x801c39c0, 0x0400000a, 0x4d2c0000, 0x0201f800, - 0x0010082a, 0x5c000800, 0x02000800, 0x00100615, - 0x4a025a04, 0x0000000a, 0x492c0801, 0x1c01f000, - 0x42006000, 0x00102d9d, 0x42000800, 0x0000007c, - 0x0201f800, 0x00101395, 0x4a03902c, 0x00200000, - 0x4200b000, 0x000001f4, 0x59c8002c, 0x8c00052c, - 0x04000007, 0x8058b040, 0x040207fc, 0x42000000, - 0x00004003, 0x41781000, 0x0401f11e, 0x50301000, - 0x41784800, 0x4a03902d, 0x00008000, 0x4200b000, - 0x000001f4, 0x59c8002c, 0x8c000534, 0x04000007, - 0x8058b040, 0x040207fc, 0x42000000, 0x00004003, - 0x41781000, 0x0401f10f, 0x0401f895, 0x80244800, - 0x82240580, 0x000003b1, 0x040207fc, 0x0401f911, - 0x41784800, 0x0401f8bb, 0x80244800, 0x82240580, - 0x000003b1, 0x040207fc, 0x80306000, 0x82300580, - 0x00102d9f, 0x040207e2, 0x59a80863, 0x800409c0, - 0x04000007, 0x42000000, 0x00004004, 0x42001000, - 0x00000002, 0x59a81862, 0x0401f0f6, 0x42006000, - 0x00102d9d, 0x50301000, 0x41784800, 0x4a03902d, - 0x00000800, 0x0401f876, 0x80244800, 0x82240580, - 0x00000018, 0x040207fc, 0x0401f8f2, 0x41784800, - 0x0401f89c, 0x80244800, 0x82240580, 0x00000018, - 0x040207fc, 0x80306000, 0x82300580, 0x00102d9f, - 0x040207ed, 0x59a80863, 0x800409c0, 0x04000007, - 0x42000000, 0x00004004, 0x42001000, 0x00000010, - 0x59a81862, 0x0401f0d7, 0x42006000, 0x00102d9d, - 0x50301000, 0x41784800, 0x4a03902d, 0x00000400, - 0x0401f857, 0x80244800, 0x82240580, 0x00000088, - 0x040207fc, 0x0401f8d3, 0x41784800, 0x0401f87d, - 0x80244800, 0x82240580, 0x00000088, 0x040207fc, - 0x80306000, 0x82300580, 0x00102d9f, 0x040207ed, - 0x59a80863, 0x800409c0, 0x04000007, 0x42000000, - 0x00004004, 0x42001000, 0x00000008, 0x59a81862, - 0x0401f0b8, 0x42006000, 0x00102d9d, 0x50301000, - 0x41784800, 0x4a03902d, 0x00002000, 0x4200b000, - 0x000001f4, 0x59c8002c, 0x8c000530, 0x04000007, - 0x8058b040, 0x040207fc, 0x42000000, 0x00004003, - 0x41781000, 0x0401f0a7, 0x59c8002c, 0x82000500, - 0xffe0ffff, 0x82080d00, 0x001f0000, 0x80040540, - 0x4803902c, 0x0401f826, 0x80244800, 0x82240580, - 0x00000110, 0x040207fc, 0x0401f8a2, 0x41784800, - 0x0401f84c, 0x59c80034, 0x82080d00, 0x001f0000, - 0x82000500, 0x001f0000, 0x80040580, 0x04000006, - 0x59a80063, 0x80000000, 0x48035063, 0x40240000, - 0x48035062, 0x80244800, 0x82240580, 0x00000110, - 0x040207f0, 0x80306000, 0x82300580, 0x00102d9f, - 0x040207cf, 0x59a80863, 0x800409c0, 0x04000006, - 0x42000000, 0x00004004, 0x42001000, 0x00000020, - 0x59a81862, 0x0201f000, 0x00102066, 0x59c8002c, - 0x82000500, 0xffff0000, 0x82080d00, 0x0000ffff, - 0x80040540, 0x4803902c, 0x480b9028, 0x480b9029, - 0x59a80064, 0x82000580, 0x00000004, 0x04000003, - 0x480b902a, 0x480b902b, 0x59c8002d, 0x82000500, - 0xfffffc00, 0x80240540, 0x4803902d, 0x4200b000, - 0x000001f4, 0x59c8002c, 0x82000500, 0x18000000, - 0x04000007, 0x8058b040, 0x040207fb, 0x42000000, - 0x00004003, 0x41781000, 0x0401f05a, 0x4a03902e, - 0x00000001, 0x4200b000, 0x000001f4, 0x59c8002e, - 0x8c000500, 0x04000006, 0x8058b040, 0x040207fc, - 0x42000000, 0x00004003, 0x0401f04e, 0x1c01f000, - 0x41783800, 0x59c8002d, 0x82000500, 0xfffffc00, - 0x80240d40, 0x4807902d, 0x4200b000, 0x000001f4, - 0x59c8002c, 0x82000500, 0x18000000, 0x04000007, - 0x8058b040, 0x040207fb, 0x42000000, 0x00004003, - 0x41781000, 0x0401f03b, 0x59c81830, 0x59c80030, - 0x800c0d80, 0x040207fd, 0x80080d80, 0x04000002, - 0x801c3800, 0x59c82031, 0x59c80031, 0x80100d80, - 0x040207fd, 0x80080d80, 0x04000002, 0x801c3800, - 0x59a80064, 0x82000580, 0x00000004, 0x04000019, - 0x59c82832, 0x59c80032, 0x80140d80, 0x040207fd, - 0x80080d80, 0x04000002, 0x801c3800, 0x59c83033, - 0x59c80033, 0x80180d80, 0x040207fd, 0x80080d80, - 0x04000002, 0x801c3800, 0x59c80034, 0x59c80834, - 0x80040d80, 0x040207fd, 0x80080d80, 0x82040d00, - 0x0000ffff, 0x0400000c, 0x801c3800, 0x0401f00a, - 0x59c80034, 0x59c80834, 0x80040d80, 0x040207fd, - 0x80080d80, 0x82040d00, 0x000000ff, 0x04000002, - 0x801c3800, 0x801c39c0, 0x04000005, 0x59a80063, - 0x801c0400, 0x48035063, 0x48275062, 0x1c01f000, - 0x48034206, 0x48074406, 0x480b4207, 0x480f4407, - 0x48134208, 0x48174408, 0x0201f000, 0x00102069, - 0x42000000, 0x00600000, 0x80000040, 0x040207ff, - 0x1c01f000, 0x5a5a5a5a, 0xa5a5a5a5, 0x59a00c0a, - 0x800409c0, 0x02000000, 0x001020b6, 0x82040480, - 0x00000021, 0x02021000, 0x001020b6, 0x82040480, - 0x00000011, 0x04001003, 0x42000800, 0x00000010, - 0x59a00208, 0x59a01407, 0x900811c0, 0x80081540, - 0x59a00207, 0x59a01c06, 0x900c19c0, 0x800c1d40, - 0x0201f800, 0x0010381a, 0x04000006, 0x0201f800, - 0x0010383e, 0x4a01d809, 0x00102dc0, 0x1c01f000, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x59a00c0a, - 0x82040480, 0x00000011, 0x04001003, 0x42000800, - 0x00000010, 0x59a0040b, 0x59a0120b, 0x900811c0, - 0x80081540, 0x59a00209, 0x59a01c08, 0x900c19c0, - 0x800c1d40, 0x58ec0003, 0x0201f800, 0x00103841, - 0x4a01d809, 0x00102ddb, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x001020aa, 0x59a00c0a, 0x82040480, - 0x00000011, 0x02001000, 0x00102066, 0x82040c80, - 0x00000010, 0x59a00208, 0x59a01407, 0x900811c0, - 0x80081540, 0x59a00207, 0x59a01c06, 0x900c19c0, - 0x800c1d40, 0x82081400, 0x00000040, 0x58ec0003, - 0x0201f800, 0x0010383e, 0x4a01d809, 0x00102df9, - 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ec0002, - 0x82000580, 0x00000200, 0x02000000, 0x001020aa, - 0x59a0040a, 0x82000c80, 0x00000010, 0x59a0040b, - 0x59a0120b, 0x900811c0, 0x80081540, 0x59a00209, - 0x59a01c08, 0x900c19c0, 0x800c1d40, 0x82081400, - 0x00000040, 0x58ec0003, 0x0201f800, 0x00103841, - 0x4a01d809, 0x0010205f, 0x1c01f000, 0x48efc857, - 0x59a00207, 0x59a01407, 0x900001c0, 0x80081540, - 0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40, - 0x59a00406, 0x48034000, 0x480b4001, 0x480f4002, - 0x0201f800, 0x0010381a, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x001020b2, 0x42000800, - 0x00000010, 0x0201f800, 0x0010383e, 0x4a01d809, - 0x00102e2e, 0x1c01f000, 0x4031d800, 0x58ef400b, - 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x001020aa, 0x48efc857, 0x49a3c857, - 0x492fc857, 0x592c0a04, 0x80040910, 0x04020005, - 0x4a034406, 0x00000019, 0x0201f000, 0x001020b2, - 0x4805d80c, 0x0401f00a, 0x4031d800, 0x58ef400b, - 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x001020aa, 0x48efc857, 0x49a3c857, 0x48efc857, - 0x49a3c857, 0x58ec000c, 0x80000040, 0x04000012, - 0x4801d80c, 0x0201f800, 0x0010381a, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x42000800, 0x00000010, 0x58ec1007, 0x58ec1808, - 0x0201f800, 0x0010383e, 0x4a01d809, 0x00102e42, - 0x1c01f000, 0x58ee580d, 0x48efc857, 0x49a3c857, - 0x492fc857, 0x492f3006, 0x592c0404, 0x8400055e, - 0x48025c04, 0x4a01d809, 0x00102e6c, 0x1c01f000, - 0x4d2c0000, 0x58ee580d, 0x48efc857, 0x49a3c857, - 0x492fc857, 0x592c0404, 0x8400051e, 0x48025c04, - 0x59a00000, 0x59a01001, 0x59a01802, 0x80081400, - 0x820c1c40, 0x00000000, 0x832c0400, 0x00000004, - 0x42000800, 0x00000010, 0x5c025800, 0x0201f000, - 0x00103841, 0x800409c0, 0x04000005, 0x4a034406, - 0x00000001, 0x0201f000, 0x001020b2, 0x836c0580, - 0x00000003, 0x04000005, 0x4a034406, 0x00000007, - 0x0201f000, 0x001020b2, 0x59a0320b, 0x82183500, - 0x000000ff, 0x59a28c06, 0x0201f800, 0x00020267, - 0x02020000, 0x001020b6, 0x83440580, 0x000007fd, - 0x04000008, 0x0201f800, 0x00104836, 0x04000005, - 0x4a034406, 0x00000009, 0x0201f000, 0x001020b2, - 0x0201f800, 0x0010381a, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x001020b2, 0x801831c0, - 0x0400000a, 0x412c0800, 0x0201f800, 0x0010381a, - 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x001020b2, 0x40065800, 0x4a025c04, 0x00008000, - 0x497a5a04, 0x0201f800, 0x00108ebd, 0x04020005, - 0x4a034406, 0x00000003, 0x0201f000, 0x001020b2, - 0x4a01d809, 0x00102ebf, 0x1c01f000, 0x592c0005, - 0x82000580, 0x01000000, 0x04020005, 0x4a034406, - 0x00000004, 0x0201f000, 0x001020b2, 0x592c0406, - 0x82002d00, 0x0000ff00, 0x82000500, 0x000000ff, - 0x80000904, 0x80040800, 0x82040480, 0x00000006, - 0x04001003, 0x42000800, 0x00000005, 0x4c500000, - 0x4c540000, 0x4c580000, 0x832ca400, 0x00000006, - 0x4050a800, 0x4004b000, 0x0201f800, 0x0010a94f, - 0x59a00407, 0x59a01207, 0x900811c0, 0x80081540, - 0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40, - 0x832c0400, 0x00000006, 0x4c140000, 0x0201f800, - 0x00103841, 0x5c002800, 0x801429c0, 0x04000003, - 0x4a01d809, 0x00102ef2, 0x5c00b000, 0x5c00a800, - 0x5c00a000, 0x1c01f000, 0x4031d800, 0x58ef400b, - 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x001020aa, 0x812e59c0, 0x02000800, - 0x00100615, 0x592c0006, 0x82000500, 0xff000000, - 0x80000904, 0x800409c0, 0x02000000, 0x001020aa, - 0x82040480, 0x0000000e, 0x04001003, 0x42000800, - 0x0000000d, 0x592e5801, 0x812e59c0, 0x02000800, - 0x00100615, 0x4c500000, 0x4c540000, 0x4c580000, - 0x832ca400, 0x00000005, 0x4050a800, 0x4004b000, - 0x0201f800, 0x0010a94f, 0x5c00b000, 0x5c00a800, - 0x5c00a000, 0x58ec1007, 0x58ec1808, 0x832c0400, - 0x00000005, 0x0201f000, 0x00103841, 0x0201f800, - 0x0010381a, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x001020b2, 0x59a00c06, 0x82040500, - 0x0000ff00, 0x840001c0, 0x82001480, 0x00000007, - 0x02021000, 0x001020b6, 0x0c01f001, 0x00102f36, - 0x00102f3d, 0x00102f44, 0x00102f44, 0x00102f44, - 0x00102f46, 0x00102f4b, 0x42000800, 0x0000000d, - 0x42003800, 0x00102f5f, 0x4a034000, 0x0010b2e7, - 0x0401f013, 0x42000800, 0x0000000d, 0x42003800, - 0x00102f5f, 0x4a034000, 0x0010b2f4, 0x0401f00c, - 0x0201f000, 0x001020b6, 0x42000800, 0x00000008, - 0x42003800, 0x00102f72, 0x0401f005, 0x42000800, - 0x00000004, 0x42003800, 0x00102fbc, 0x59a00207, - 0x59a01407, 0x900001c0, 0x80081540, 0x59a00209, - 0x59a01c09, 0x900001c0, 0x800c1d40, 0x832c0400, - 0x00000005, 0x4c1c0000, 0x0201f800, 0x0010383e, - 0x5c003800, 0x481dd809, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x4a03501f, - 0x00000001, 0x4200b000, 0x0000000d, 0x59a0a800, - 0x832ca400, 0x00000005, 0x0201f800, 0x0010a93e, - 0x0201f000, 0x00102066, 0x4031d800, 0x58ef400b, - 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200, - 0x02000000, 0x001020aa, 0x832ca400, 0x00000005, - 0x50500000, 0x82001500, 0x000c0016, 0x02020000, - 0x001020b6, 0x82500c00, 0x00000003, 0x50040000, - 0x82001500, 0x00000001, 0x02020000, 0x001020b6, - 0x50500000, 0x82001500, 0x00000028, 0x0400001d, - 0x82081580, 0x00000028, 0x02020000, 0x001020b6, - 0x80500800, 0x50040000, 0x82001500, 0x00000013, - 0x82081580, 0x00000013, 0x02020000, 0x001020b6, - 0x80040800, 0x50040000, 0x82001500, 0x00010000, - 0x82081580, 0x00010000, 0x02020000, 0x001020b6, - 0x836c0580, 0x00000000, 0x04000012, 0x599c0019, - 0x8c00050e, 0x0402000f, 0x0201f000, 0x001020b6, - 0x80500800, 0x50040000, 0x82001500, 0x00000013, - 0x02020000, 0x001020b6, 0x80040800, 0x50040000, - 0x82001500, 0x00010000, 0x02020000, 0x001020b6, - 0x4200b000, 0x00000008, 0x4200a800, 0x0010b2df, - 0x0201f800, 0x0010a93e, 0x0201f000, 0x00102066, - 0x4031d800, 0x58ef400b, 0x58ee580d, 0x58ec0002, - 0x82000580, 0x00000200, 0x02000000, 0x001020aa, - 0x4200b000, 0x00000004, 0x4200a800, 0x0010b6f9, - 0x832ca400, 0x00000005, 0x0201f800, 0x0010a93e, - 0x59a80005, 0x84000550, 0x48035005, 0x0201f000, - 0x00102066, 0x0201f800, 0x0010381a, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x59a00c06, 0x82040500, 0x0000ff00, 0x840001c0, - 0x82001480, 0x00000006, 0x02021000, 0x001020b6, - 0x0c01f001, 0x00102fe7, 0x00102fec, 0x00102ff1, - 0x00102ff1, 0x00102ff1, 0x00102ff3, 0x42000800, - 0x0000000d, 0x4200a000, 0x0010b2e7, 0x0401f00c, - 0x42000800, 0x0000000d, 0x4200a000, 0x0010b2f4, - 0x0401f007, 0x0201f000, 0x001020b6, 0x42000800, - 0x00000008, 0x4200a000, 0x0010b2df, 0x4004b000, - 0x832cac00, 0x00000005, 0x0201f800, 0x0010a93e, - 0x59a00207, 0x59a01407, 0x900001c0, 0x80081540, - 0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40, - 0x832c0400, 0x00000005, 0x0201f000, 0x00103841, - 0x836c0580, 0x00000000, 0x04020005, 0x4a034406, - 0x00000007, 0x0201f000, 0x001020b2, 0x59a01406, - 0x800811c0, 0x04020017, 0x59c40801, 0x82040d00, - 0x00018000, 0x82040580, 0x00000000, 0x04020004, - 0x4a034406, 0x00000000, 0x0401f048, 0x82040580, - 0x00008000, 0x04020004, 0x4a034406, 0x00000001, - 0x0401f042, 0x82040580, 0x00010000, 0x02020800, - 0x00100615, 0x4a034406, 0x00000003, 0x0401f03b, - 0x59a8006f, 0x8c000508, 0x04000005, 0x42000000, - 0x00000001, 0x40000800, 0x0401f003, 0x59a00207, - 0x59a80853, 0x48035053, 0x0201f800, 0x001016ac, - 0x0400000d, 0x0201f800, 0x001016b3, 0x0400000a, - 0x0201f800, 0x001016ba, 0x04000007, 0x0201f800, - 0x001016c1, 0x04000004, 0x48075053, 0x0201f000, - 0x001020b6, 0x82080580, 0x00000002, 0x0402001f, - 0x59c40006, 0x84000500, 0x48038806, 0x0201f800, - 0x00106c32, 0x497b8880, 0x0201f800, 0x0010a7e7, - 0x0201f800, 0x0010a7f5, 0x42000000, 0x0010b6c9, - 0x0201f800, 0x0010a86e, 0x82000540, 0x00000001, - 0x0201f800, 0x00104e5d, 0x4a038808, 0x00000000, - 0x4202d800, 0x00000004, 0x42001000, 0x00000001, - 0x0201f800, 0x001019aa, 0x4a035049, 0x00000001, - 0x0201f800, 0x0010071a, 0x0201f000, 0x00102066, - 0x800409c0, 0x04000005, 0x4a034406, 0x00000001, - 0x0201f000, 0x001020b2, 0x836c0580, 0x00000003, - 0x04000005, 0x4a034406, 0x00000007, 0x0201f000, - 0x001020b2, 0x59a28c06, 0x59a0320b, 0x82183500, - 0x000000ff, 0x0201f800, 0x00020267, 0x02020000, - 0x001020b6, 0x83440580, 0x000007fd, 0x04000008, - 0x0201f800, 0x00104836, 0x04000005, 0x42000800, - 0x00000009, 0x0201f000, 0x001020b2, 0x0201f800, - 0x0010381a, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x001020b2, 0x497a5a04, 0x4a025c04, - 0x00008000, 0x0201f800, 0x00108ed2, 0x04020005, - 0x4a034406, 0x00000003, 0x0201f000, 0x001020b2, - 0x4a01d809, 0x00103097, 0x1c01f000, 0x592c0005, - 0x82000d00, 0x0000ffff, 0x82000500, 0xffff0000, - 0x82000580, 0x01000000, 0x04020005, 0x4a034406, - 0x00000004, 0x0201f000, 0x001020b2, 0x80040904, - 0x4c500000, 0x4c540000, 0x4c580000, 0x832ca400, - 0x00000005, 0x4050a800, 0x4004b000, 0x0201f800, - 0x0010a94f, 0x5c00b000, 0x5c00a800, 0x5c00a000, - 0x59a00207, 0x59a01407, 0x900001c0, 0x80081540, - 0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40, - 0x832c0400, 0x00000005, 0x0201f000, 0x00103841, - 0x496fc857, 0x836c0580, 0x00000000, 0x04000005, - 0x4a034406, 0x0000001a, 0x0201f000, 0x001020b2, - 0x0201f800, 0x00104e0d, 0x02020800, 0x00103f5c, - 0x42000800, 0x00000020, 0x59a00407, 0x59a01207, - 0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09, - 0x900c19c0, 0x800c1d40, 0x419c0000, 0x49a3c857, - 0x0201f800, 0x0010383e, 0x4a01d809, 0x001030d9, - 0x1c01f000, 0x4833c857, 0x4031d800, 0x58ef400b, - 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x001020aa, 0x599c0200, 0x800001c0, 0x02000000, - 0x001020b6, 0x59a8006f, 0x8c000504, 0x04020003, - 0x8c000506, 0x04000004, 0x599c0019, 0x8400050c, - 0x48033819, 0x0201f800, 0x001095a3, 0x59a8006f, - 0x8c000502, 0x04000004, 0x599c0017, 0x84000508, - 0x48033817, 0x0201f800, 0x0010393e, 0x04020004, - 0x8c00050a, 0x02020000, 0x001020b6, 0x4803c857, - 0x8c000504, 0x04020004, 0x59c408a3, 0x84040d7a, - 0x480788a3, 0x8c000502, 0x04020004, 0x59c408a3, - 0x84040d08, 0x480788a3, 0x599c0c02, 0x8c000500, - 0x04020004, 0x8c000516, 0x04000012, 0x0401f001, - 0x82041480, 0x0000007f, 0x02021000, 0x001020b6, - 0x82041400, 0x00101eb5, 0x50081000, 0x82081500, - 0x000000ff, 0x8c000500, 0x04020006, 0x480b5010, - 0x42000800, 0x00000003, 0x0201f800, 0x001069af, - 0x599c0019, 0x8c000506, 0x04000003, 0x4a03b805, - 0x90000000, 0x8c00050e, 0x0402000b, 0x59a80806, - 0x8c040d14, 0x04000008, 0x42000800, 0x0010b2df, - 0x50040800, 0x82040d00, 0x00000028, 0x02020000, - 0x001020b6, 0x82000500, 0x00000030, 0x04000003, - 0x80000108, 0x0401f003, 0x42000000, 0x00000002, - 0x48039040, 0x42000800, 0x00000002, 0x82000400, - 0x0010321c, 0x50001000, 0x0201f800, 0x001069af, - 0x599c0201, 0x82000c80, 0x00000100, 0x02001000, - 0x001020b6, 0x82000c80, 0x00000841, 0x02021000, - 0x001020b6, 0x82000500, 0x00000007, 0x02020000, - 0x001020b6, 0x599c0401, 0x80000540, 0x02000000, - 0x001020b6, 0x599c0409, 0x599c0c07, 0x80040c80, - 0x02021000, 0x001020b6, 0x80000040, 0x02000000, - 0x001020b6, 0x599c0209, 0x599c0a07, 0x80040c80, - 0x02021000, 0x001020b6, 0x80000040, 0x02000000, - 0x001020b6, 0x0201f800, 0x0010509d, 0x0201f800, - 0x00104b53, 0x599c0201, 0x48035004, 0x0201f800, - 0x0010133e, 0x599c020a, 0x800001c0, 0x04000003, - 0x4803504d, 0x0401f003, 0x4a03504d, 0x000000c8, - 0x0201f800, 0x0010393e, 0x04000004, 0x0201f800, - 0x00105e18, 0x417a5000, 0x836c0580, 0x00000000, - 0x0402009a, 0x599c0003, 0x599c0804, 0x9c0001c0, - 0x9c0409c0, 0x48035002, 0x48075003, 0x599c1017, - 0x8c08151c, 0x04000006, 0x599c0005, 0x599c0806, - 0x9c0001c0, 0x9c0409c0, 0x0401f003, 0x82000500, - 0xf0ffffff, 0x48035000, 0x48075001, 0x42001000, - 0x0010b2e7, 0x48001000, 0x48041001, 0x42001000, - 0x0010b2f4, 0x48001000, 0x48041001, 0x59a8006f, - 0x8c000508, 0x04020017, 0x8c00050a, 0x04020021, - 0x599c1019, 0x82081500, 0x0000e000, 0x82080580, - 0x00000000, 0x0402000c, 0x4a035053, 0x00000000, - 0x42000000, 0x00000001, 0x0201f800, 0x001018fa, - 0x42000000, 0x00000001, 0x0201f800, 0x00101892, - 0x0401f02b, 0x82080580, 0x00002000, 0x0402000a, - 0x4a035053, 0x00000001, 0x41780000, 0x0201f800, - 0x001018fa, 0x41780000, 0x0201f800, 0x00101892, - 0x0401f01f, 0x82080580, 0x00004000, 0x04020006, - 0x4a035053, 0x00000002, 0x4a035049, 0x00000001, - 0x0401f017, 0x82080580, 0x00006000, 0x02020000, - 0x001020b6, 0x59a80858, 0x82040d80, 0x01391077, - 0x04020005, 0x59e00813, 0x8c040d00, 0x02020000, - 0x001020b6, 0x4a035053, 0x00000003, 0x42000000, - 0x00000002, 0x0201f800, 0x001018fa, 0x42000000, - 0x00000002, 0x0201f800, 0x00101892, 0x599c0019, - 0x8c000520, 0x0400000d, 0x42000000, 0x00000004, - 0x42000800, 0x00000040, 0x0201f800, 0x001019b1, - 0x42000000, 0x00000010, 0x42000800, 0x000000c0, - 0x0201f800, 0x001019b1, 0x4a035032, 0x0000aaaa, - 0x599c1018, 0x82081500, 0x00000030, 0x59a8006c, - 0x80000540, 0x0400000c, 0x82080580, 0x00000000, - 0x02000000, 0x001020b6, 0x599c1018, 0x82081500, - 0xffffffcf, 0x82081540, 0x00000010, 0x480b3818, - 0x0401f010, 0x82080d80, 0x00000000, 0x04000007, - 0x82080d80, 0x00000010, 0x0400000a, 0x82080d80, - 0x00000020, 0x04020002, 0x48075032, 0x0201f800, - 0x001038d3, 0x04000008, 0x0201f800, 0x00101668, - 0x0201f800, 0x00101694, 0x59a8002a, 0x80040540, - 0x4803502a, 0x49f3c857, 0x42001000, 0x00104d39, - 0x0201f800, 0x00105cc9, 0x42001000, 0x00104d2c, - 0x0201f800, 0x00105dbd, 0x4a038805, 0xffffffff, - 0x4a03c014, 0x00400040, 0x4a03c013, 0x00400000, - 0x0201f800, 0x00104717, 0x59a0001d, 0x84000540, - 0x4803401d, 0x49f3c857, 0x0201f000, 0x00102066, - 0x00000018, 0x0000000c, 0x00000018, 0x00000020, - 0x836c0580, 0x00000000, 0x04020005, 0x42000800, - 0x00000007, 0x0201f000, 0x001020b2, 0x42000800, - 0x00000020, 0x59a00407, 0x59a01207, 0x900811c0, - 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0, - 0x800c1d40, 0x419c0000, 0x0201f000, 0x00103841, - 0x800409c0, 0x04000005, 0x4a034406, 0x00000001, - 0x0201f000, 0x001020b2, 0x0201f800, 0x00104e0d, - 0x04020005, 0x4a034406, 0x00000016, 0x0201f000, - 0x001020b2, 0x59a80013, 0x8c000500, 0x04000011, - 0x4a034406, 0x00000000, 0x42000800, 0x00000020, - 0x59a00407, 0x59a01207, 0x900811c0, 0x80081540, - 0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40, - 0x42000000, 0x0010bc20, 0x0201f000, 0x00103841, - 0x4a034406, 0x00000001, 0x4200b000, 0x00000020, - 0x4200a800, 0x0010bc20, 0x4200a000, 0xffffffff, - 0x4450a800, 0x8054a800, 0x8058b040, 0x040207fd, - 0x4d440000, 0x4d340000, 0x42028800, 0xffffffff, - 0x42002000, 0xffffffff, 0x42003000, 0x00000001, - 0x42003800, 0x00000001, 0x42001800, 0x0010bc20, - 0x59a81010, 0x82081500, 0x000000ff, 0x40180000, - 0x0c01f001, 0x00103275, 0x00103278, 0x0010327c, - 0x00103280, 0x82102500, 0xffffff00, 0x0401f014, - 0x82102500, 0xffff00ff, 0x840811c0, 0x0401f010, - 0x82102500, 0xff00ffff, 0x900811c0, 0x0401f00c, - 0x82102500, 0x00ffffff, 0x9c0801c0, 0x80102540, - 0x44101800, 0x42003000, 0xffffffff, 0x42002000, - 0xffffffff, 0x800c1800, 0x0401f003, 0x40080000, - 0x80102540, 0x81468800, 0x83442c80, 0x0000007f, - 0x04021014, 0x4c080000, 0x4c0c0000, 0x4c180000, - 0x4c1c0000, 0x0201f800, 0x00020267, 0x5c003800, - 0x5c003000, 0x5c001800, 0x5c001000, 0x040207f2, - 0x0201f800, 0x00104842, 0x040207ef, 0x80183000, - 0x801c3800, 0x59341202, 0x40180000, 0x0c01f7ce, - 0x82100580, 0xffffffff, 0x04000002, 0x44101800, - 0x42001800, 0x0010bc20, 0x500c0000, 0x82000500, - 0xffffff00, 0x801c0540, 0x44001800, 0x5c026800, - 0x5c028800, 0x42000800, 0x00000020, 0x59a00407, - 0x59a01207, 0x900811c0, 0x80081540, 0x59a00409, - 0x59a01a09, 0x900c19c0, 0x800c1d40, 0x42000000, - 0x0010bc20, 0x0201f000, 0x00103841, 0x59a28c06, - 0x59a0020b, 0x8c000500, 0x0400000e, 0x59a01208, - 0x59a00408, 0x82000500, 0x000000ff, 0x900001c0, - 0x80081540, 0x41784000, 0x0201f800, 0x00104768, - 0x04000008, 0x48034406, 0x0201f000, 0x001020b6, - 0x0201f800, 0x00020267, 0x02020000, 0x001020b6, - 0x0201f800, 0x0010381a, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x001020b2, 0x59a0020b, - 0x8c000500, 0x04000005, 0x0201f800, 0x00104842, - 0x02020000, 0x001038dd, 0x59a0020b, 0x8c000502, - 0x04000019, 0x83440480, 0x000007f0, 0x04021016, - 0x0201f800, 0x0010484b, 0x04020013, 0x497a5a04, - 0x4a025c04, 0x00008000, 0x0201f800, 0x00108ea3, - 0x04020005, 0x4a034406, 0x00000003, 0x0201f000, - 0x001020b2, 0x4a01d809, 0x001032f8, 0x1c01f000, - 0x59a28c06, 0x0201f800, 0x00020267, 0x02020000, - 0x001020b6, 0x4c580000, 0x4c500000, 0x4c540000, - 0x4200b000, 0x0000000a, 0x4134a000, 0x832e5c00, - 0x00000002, 0x412ca800, 0x0201f800, 0x0010a93e, - 0x832cac00, 0x00000006, 0x4054a000, 0x4200b000, - 0x00000004, 0x0201f800, 0x0010a94f, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x592c0802, 0x82040500, - 0x00ff00ff, 0x900001c0, 0x82041500, 0xff00ff00, - 0x80080540, 0x48025802, 0x592c0801, 0x82040500, - 0x00ff00ff, 0x900001c0, 0x82041500, 0xff00ff00, - 0x80080540, 0x48025801, 0x42000800, 0x0000000a, - 0x59a00407, 0x59a01207, 0x900811c0, 0x80081540, - 0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40, - 0x412c0000, 0x0201f000, 0x00103841, 0x496fc857, - 0x496f4406, 0x0201f000, 0x00102066, 0x59a28c06, - 0x0201f800, 0x00020267, 0x02020000, 0x001020b6, - 0x836c0580, 0x00000003, 0x04000005, 0x4a034406, - 0x00000007, 0x0201f000, 0x001020b2, 0x83340c00, - 0x00000006, 0x59a0020b, 0x8c000500, 0x04000003, - 0x83340c00, 0x00000008, 0x58040001, 0x48034409, - 0x900001c0, 0x48034209, 0x50040000, 0x48034407, - 0x900001c0, 0x48034207, 0x59340200, 0x48034406, - 0x0201f000, 0x00102066, 0x800409c0, 0x04000005, - 0x4a034406, 0x00000001, 0x0201f000, 0x001020b2, - 0x59a0220b, 0x8c102500, 0x0402002e, 0x8c102506, - 0x04020006, 0x59a03208, 0x82180480, 0x00000003, - 0x02021000, 0x001020b6, 0x59a28c06, 0x0201f800, - 0x00020267, 0x02020000, 0x001020b6, 0x0201f800, - 0x00104836, 0x04000005, 0x4a034406, 0x00000009, - 0x0201f000, 0x001020b2, 0x0201f800, 0x0010381a, - 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x001020b2, 0x59a0220b, 0x8c102506, 0x04000004, - 0x59343002, 0x82183500, 0x00ffffff, 0x497a5a04, - 0x4a025c04, 0x00008000, 0x0201f800, 0x00108e65, - 0x04020005, 0x4a034406, 0x00000003, 0x0201f000, - 0x001020b2, 0x4a01d809, 0x001033de, 0x1c01f000, - 0x59a28c06, 0x0201f800, 0x00020267, 0x02020000, - 0x001020b6, 0x0201f800, 0x00104836, 0x04000005, - 0x4a034406, 0x00000009, 0x0201f000, 0x001020b2, - 0x0201f800, 0x0010381a, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x001020b2, 0x497a5a04, - 0x4a025c04, 0x00008000, 0x0201f800, 0x0010381a, - 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x001020b2, 0x592e5800, 0x0201f800, 0x00108e7a, - 0x04020005, 0x4a034406, 0x00000003, 0x0201f000, - 0x001020b2, 0x4a01d809, 0x001033b0, 0x1c01f000, - 0x592c2805, 0x82140d80, 0x01000000, 0x04020005, - 0x4a034406, 0x00000004, 0x0201f000, 0x001020b2, - 0x42000800, 0x00000008, 0x59a00207, 0x59a01407, - 0x900001c0, 0x80081540, 0x59a00209, 0x59a01c09, - 0x900001c0, 0x800c1d40, 0x832c0400, 0x00000005, - 0x0201f800, 0x00103841, 0x8c142d00, 0x04000003, - 0x4a01d809, 0x001033cb, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ee580e, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x812e59c0, - 0x02000800, 0x00100615, 0x42000800, 0x00000008, - 0x832c0400, 0x00000005, 0x58ec1007, 0x58ec1808, - 0x0201f000, 0x00103841, 0x592c0005, 0x82000580, - 0x01000000, 0x04020005, 0x4a034406, 0x00000004, - 0x0201f000, 0x001020b2, 0x59a00207, 0x59a01407, - 0x900001c0, 0x80081540, 0x59a00209, 0x59a01c09, - 0x900001c0, 0x800c1d40, 0x42000800, 0x00000006, - 0x832c0400, 0x00000006, 0x0201f000, 0x00103841, - 0x59a00a0a, 0x800409c0, 0x02000000, 0x001020b6, - 0x82040480, 0x000000e8, 0x04001003, 0x42000800, - 0x000000e7, 0x59a00207, 0x59a01407, 0x900001c0, - 0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0, - 0x800c1d40, 0x83880400, 0x00000000, 0x0201f800, - 0x00103841, 0x4a01d809, 0x0010340c, 0x1c01f000, - 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x59a0020b, - 0x8c000500, 0x04000008, 0x83880400, 0x00000000, - 0x4803c840, 0x4a03c842, 0x00000006, 0x04011000, - 0x497b8885, 0x4a034207, 0x000000e7, 0x0201f000, - 0x00102066, 0x800409c0, 0x04000005, 0x4a034406, - 0x00000001, 0x0201f000, 0x001020b2, 0x0401fbf3, - 0x04020005, 0x4a034406, 0x00000002, 0x0201f000, - 0x001020b2, 0x497a5a04, 0x4a025c04, 0x00008000, - 0x59a00406, 0x800001c0, 0x02000000, 0x001020b6, - 0x82001580, 0x000000ff, 0x04000005, 0x82001480, - 0x00000004, 0x02021000, 0x001020b6, 0x40001000, - 0x0201f800, 0x00101d6a, 0x04020005, 0x4a034406, - 0x00000003, 0x0201f000, 0x001020b2, 0x4a01d809, - 0x00103446, 0x1c01f000, 0x592c0005, 0x82000580, - 0x01000000, 0x02020000, 0x00102066, 0x4a034406, - 0x00000004, 0x0201f000, 0x001020b2, 0x59a01406, - 0x8c081508, 0x04020007, 0x800409c0, 0x04000005, - 0x4a034406, 0x00000001, 0x0201f000, 0x001020b2, - 0x59a01c07, 0x820c0480, 0x00001000, 0x02021000, - 0x001020b6, 0x497b2804, 0x497b2805, 0x497b281c, - 0x497b281d, 0x497b281f, 0x497b2820, 0x497b2822, - 0x497b2823, 0x80000580, 0x0201f800, 0x00101668, - 0x59a80805, 0x8c081500, 0x04000004, 0x82040d40, - 0x00000011, 0x0401f004, 0x8c081506, 0x04000002, - 0x84040d42, 0x84040d0a, 0x48075005, 0x4202d800, - 0x00000001, 0x82081500, 0x000000e0, 0x8008010a, - 0x0c020036, 0x0201f800, 0x00104e0d, 0x04020009, - 0x4a035033, 0x00000001, 0x0201f800, 0x00104d76, - 0x0401f01f, 0x4a035033, 0x00000000, 0x0401f7fb, - 0x497b5032, 0x0201f800, 0x00103f5c, 0x0201f800, - 0x0010698c, 0x0201f800, 0x00106c32, 0x0201f800, - 0x00106982, 0x59a00a07, 0x480788a7, 0x59c400a3, - 0x82000500, 0xfeffffff, 0x82000540, 0x80018000, - 0x40000800, 0x84040d20, 0x480388a3, 0x480788a3, - 0x497b504e, 0x42000800, 0x0000002d, 0x42001000, - 0x00103fe4, 0x0201f800, 0x00105ca2, 0x59a00407, - 0x800000c2, 0x800008c4, 0x8005d400, 0x42000000, - 0x0000ffff, 0x0201f800, 0x00104e0d, 0x04000003, - 0x59a00207, 0x80000110, 0x0201f800, 0x00103915, - 0x0201f000, 0x00102066, 0x00103479, 0x0010347c, - 0x00103484, 0x001020b6, 0x00103481, 0x001020b6, - 0x001020b6, 0x001020b6, 0x836c0580, 0x00000003, - 0x04000005, 0x4a034406, 0x00000007, 0x0201f000, - 0x001020b2, 0x59a03c06, 0x59a00407, 0x59a04a07, - 0x902449c0, 0x80244d40, 0x59a00409, 0x59a05209, - 0x902851c0, 0x80285540, 0x0401fb54, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x417a8800, 0x41783000, 0x497b4001, 0x497b4004, - 0x832c4400, 0x00000005, 0x48234002, 0x8c1c3d04, - 0x04020078, 0x0201f800, 0x00020267, 0x0402002a, - 0x0201f800, 0x00104836, 0x04000004, 0x0201f800, - 0x00104732, 0x04020024, 0x8c1c3d00, 0x04000008, - 0x59340009, 0x44004000, 0x59340008, 0x80204000, - 0x44004000, 0x80204000, 0x0401f007, 0x59340007, - 0x44004000, 0x59340006, 0x80204000, 0x44004000, - 0x80204000, 0x83440580, 0x000007fe, 0x0400000d, - 0x83440580, 0x000007fc, 0x0400000a, 0x0201f800, - 0x00104842, 0x04000003, 0x85468d5e, 0x0401f005, - 0x0201f800, 0x00104686, 0x04020002, 0x85468d5e, - 0x45444000, 0x85468d1e, 0x80204000, 0x82183400, - 0x00000003, 0x81468800, 0x83440480, 0x000007f0, - 0x0400100e, 0x8c1c3d06, 0x04000010, 0x83440580, - 0x000007f0, 0x04020004, 0x42028800, 0x000007fe, - 0x0401f006, 0x83440580, 0x000007ff, 0x04020007, - 0x42028800, 0x000007fc, 0x82180580, 0x0000000f, - 0x0400000b, 0x0401f7c0, 0x801831c0, 0x04020006, - 0x59a00801, 0x800408c4, 0x48074406, 0x0201f000, - 0x00102066, 0x4a034004, 0x00000001, 0x49474000, - 0x59a00001, 0x80180400, 0x48034001, 0x481f4003, - 0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002, - 0x4801d803, 0x4825d807, 0x4829d808, 0x4000a800, - 0x4000a000, 0x4018b000, 0x0201f800, 0x0010a93e, - 0x40ec1000, 0x0201f800, 0x001008a1, 0x4a01d809, - 0x00103536, 0x1c01f000, 0x4031d800, 0x58ef400b, - 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x001020aa, 0x59a00004, 0x80000540, 0x04020008, - 0x59a28800, 0x59a04002, 0x59a03803, 0x41783000, - 0x58ec4807, 0x58ec5008, 0x0401f78f, 0x59a00801, - 0x800408c4, 0x48074406, 0x0201f000, 0x00102066, - 0x0201f800, 0x00020267, 0x0402002f, 0x0201f800, - 0x00104836, 0x04000004, 0x0201f800, 0x00104732, - 0x04020029, 0x83440580, 0x000007fe, 0x04000011, - 0x83440580, 0x000007fc, 0x0400000e, 0x0201f800, - 0x00104842, 0x04000005, 0x59340403, 0x8400055e, - 0x48026c03, 0x0401f007, 0x0201f800, 0x00104686, - 0x04020004, 0x59340403, 0x8400055e, 0x48026c03, - 0x4134a000, 0x4020a800, 0x4200b000, 0x00000006, - 0x0201f800, 0x0010a93e, 0x59340007, 0x4400a800, - 0x59340006, 0x4800a801, 0x59340009, 0x4800a802, - 0x59340008, 0x4800a803, 0x59340403, 0x8400051e, - 0x48026c03, 0x82204400, 0x0000000a, 0x82183400, - 0x0000000a, 0x81468800, 0x83440480, 0x000007f0, - 0x0400100e, 0x8c1c3d06, 0x04000010, 0x83440580, - 0x000007f0, 0x04020004, 0x42028800, 0x000007fe, - 0x0401f006, 0x83440580, 0x000007ff, 0x04020007, - 0x42028800, 0x000007fc, 0x82180580, 0x0000000a, - 0x0400000b, 0x0401f7bb, 0x801831c0, 0x04020006, - 0x59a00801, 0x800408c4, 0x48074406, 0x0201f000, - 0x00102066, 0x4a034004, 0x00000001, 0x49474000, - 0x59a00001, 0x80180400, 0x48034001, 0x481f4003, - 0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002, - 0x4801d803, 0x4825d807, 0x4829d808, 0x40ec1000, - 0x0201f800, 0x001008a1, 0x4a01d809, 0x001035ad, - 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ec0002, - 0x82000580, 0x00000200, 0x02000000, 0x001020aa, - 0x59a00004, 0x80000540, 0x04020008, 0x59a28800, - 0x59a04002, 0x59a03803, 0x41783000, 0x58ec4807, - 0x58ec5008, 0x0401f78f, 0x59a00801, 0x800408c4, - 0x48074406, 0x0201f000, 0x00102066, 0x42002800, - 0x0000007e, 0x59a00c06, 0x59a01207, 0x59a01c07, - 0x59a02209, 0x82040500, 0x0000ff00, 0x840001c0, - 0x82003480, 0x00000020, 0x02001000, 0x001020b6, - 0x80140480, 0x02001000, 0x001020b6, 0x82040500, - 0x000000ff, 0x82003480, 0x00000020, 0x02001000, - 0x001020b6, 0x80140480, 0x02001000, 0x001020b6, - 0x82080500, 0x0000ff00, 0x840001c0, 0x82003480, - 0x00000020, 0x02001000, 0x001020b6, 0x80140480, - 0x02001000, 0x001020b6, 0x82080500, 0x000000ff, - 0x82003480, 0x00000020, 0x02001000, 0x001020b6, - 0x80140480, 0x02001000, 0x001020b6, 0x820c0500, - 0x0000ff00, 0x840001c0, 0x82003480, 0x00000020, - 0x02001000, 0x001020b6, 0x80140480, 0x02001000, - 0x001020b6, 0x820c0500, 0x000000ff, 0x82003480, - 0x00000020, 0x02001000, 0x001020b6, 0x80140480, - 0x02001000, 0x001020b6, 0x82100500, 0x0000ff00, - 0x840001c0, 0x82003480, 0x00000020, 0x02001000, - 0x001020b6, 0x80140480, 0x02001000, 0x001020b6, - 0x82100500, 0x000000ff, 0x82003480, 0x00000020, - 0x02001000, 0x001020b6, 0x80140480, 0x02001000, - 0x001020b6, 0x900401c0, 0x80080d40, 0x900c01c0, - 0x80101d40, 0x83a83400, 0x0000003a, 0x44043000, - 0x80183000, 0x440c3000, 0x0201f000, 0x00102066, - 0x0401f9fa, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x001020b2, 0x42000800, 0x0000000c, - 0x0401f853, 0x4a01d809, 0x0010362c, 0x1c01f000, - 0x4031d800, 0x58ee580d, 0x58ef400b, 0x58ec0002, - 0x82000580, 0x00000200, 0x02000000, 0x001020aa, - 0x832ca400, 0x00000004, 0x4200b000, 0x0000000c, - 0x40c8a800, 0x0201f800, 0x0010a93e, 0x58c80200, - 0x80000540, 0x04000034, 0x58c80400, 0x82000500, - 0xfffffffb, 0x04020030, 0x58c80401, 0x80000540, - 0x0400002d, 0x82000480, 0x0000ff01, 0x0402102a, - 0x58c80202, 0x82000480, 0x0000005c, 0x04001026, - 0x0201f800, 0x001060db, 0x58c80c08, 0x58c80204, - 0x80040480, 0x04001020, 0x58c80204, 0x82000480, - 0x00000005, 0x0402101c, 0x58c80205, 0x58c80c08, - 0x80040902, 0x80040480, 0x04001017, 0x58c80c08, - 0x0201f800, 0x0010602a, 0x0400001b, 0x0201f800, - 0x00105ef2, 0x04020012, 0x4979940b, 0x59c408a3, - 0x82040d40, 0x00000002, 0x480788a3, 0x4a038830, - 0x00000001, 0x4a038832, 0x01ffffff, 0x58c80202, - 0x48030804, 0x0201f800, 0x00105ed4, 0x0201f000, - 0x00102066, 0x0201f000, 0x001020b6, 0x0201f800, - 0x0010612d, 0x0201f800, 0x0010613a, 0x0201f800, - 0x0010601d, 0x0201f000, 0x001020b2, 0x4c000000, - 0x59a01207, 0x59a00407, 0x900811c0, 0x80081540, - 0x59a01a09, 0x59a00409, 0x900c19c0, 0x800c1d40, - 0x5c000000, 0x0401f1b9, 0x59840000, 0x82000580, - 0x00000000, 0x04000050, 0x59840002, 0x8c000504, - 0x0400004d, 0x84000546, 0x48030802, 0x0201f800, - 0x0010601d, 0x59c408a3, 0x82040d00, 0xfffffffd, - 0x480788a3, 0x4c5c0000, 0x4200b800, 0x0010aa00, - 0x505e6800, 0x813669c0, 0x04000008, 0x5936600e, - 0x813261c0, 0x04000005, 0x0201f800, 0x0010600e, - 0x02000800, 0x001061e5, 0x805cb800, 0x825c0580, - 0x0010b1f0, 0x040207f3, 0x59866003, 0x813261c0, - 0x0400000b, 0x59300406, 0x82000580, 0x00000009, - 0x02020800, 0x00100615, 0x5930b800, 0x0201f800, - 0x00105ffa, 0x405e6000, 0x0401f7f5, 0x497b0803, - 0x4200b800, 0x0010b317, 0x505e6000, 0x813261c0, - 0x04000011, 0x59300406, 0x82000580, 0x00000009, - 0x0402000d, 0x59300203, 0x82000580, 0x00000004, - 0x04020009, 0x59326809, 0x813669c0, 0x02020800, - 0x00100615, 0x0201f800, 0x00100ee4, 0x0201f800, - 0x00105ffa, 0x4578b800, 0x805cb800, 0x825c0580, - 0x0010b31f, 0x040207e9, 0x42000800, 0x0010b315, - 0x49780801, 0x49780800, 0x0201f800, 0x0010612d, - 0x0201f800, 0x0010613a, 0x5c00b800, 0x0201f800, - 0x00105eed, 0x0201f000, 0x00102066, 0x836c0580, - 0x00000003, 0x04000005, 0x4a034406, 0x00000007, - 0x0201f000, 0x001020b2, 0x59a00407, 0x59a02207, - 0x901021c0, 0x80102540, 0x59a00409, 0x59a02a09, - 0x901429c0, 0x80142d40, 0x0401f930, 0x04020005, - 0x4a034406, 0x00000002, 0x0201f000, 0x001020b2, - 0x417a8800, 0x41781800, 0x497b4001, 0x497b4003, - 0x832c3400, 0x00000004, 0x481b4002, 0x41440000, - 0x81ac0400, 0x50026800, 0x813669c0, 0x0400000b, - 0x0201f800, 0x00104836, 0x04020008, 0x59340002, - 0x48003000, 0x49443001, 0x82183400, 0x00000002, - 0x820c1c00, 0x00000002, 0x81468800, 0x83440480, - 0x00000800, 0x04000005, 0x820c0480, 0x00000010, - 0x0402100b, 0x0401f7ea, 0x800c19c0, 0x04020006, - 0x59a00801, 0x80040902, 0x48074406, 0x0201f000, - 0x00102066, 0x4a034003, 0x00000001, 0x49474000, - 0x59a00001, 0x800c0400, 0x48034001, 0x40ec1000, - 0x4a001001, 0x00000000, 0x480c1004, 0x59a00002, - 0x48001003, 0x48101007, 0x48141008, 0x0201f800, - 0x001008a1, 0x4a01d809, 0x00103728, 0x1c01f000, - 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x59a00003, - 0x80000540, 0x04020008, 0x59a28800, 0x59a03002, - 0x41781800, 0x40ec1000, 0x58082007, 0x58082808, - 0x0401f7bf, 0x59a00801, 0x80040902, 0x48074406, - 0x0201f000, 0x00102066, 0x800409c0, 0x04000005, - 0x4a034406, 0x00000001, 0x0201f000, 0x001020b2, - 0x59a80026, 0x8c00050a, 0x04020007, 0x8c000506, - 0x04020005, 0x4a034406, 0x00000016, 0x0201f000, - 0x001020b2, 0x0401f8cd, 0x04020005, 0x4a034406, - 0x00000002, 0x0201f000, 0x001020b2, 0x59a00c06, - 0x80040902, 0x59a00407, 0x59a01207, 0x900811c0, - 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0, - 0x800c1d40, 0x832c0400, 0x00000005, 0x0401f8df, - 0x4a01d809, 0x00103763, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x592c0009, - 0x0201f800, 0x001059b9, 0x02000800, 0x001043fc, - 0x02020000, 0x001020b6, 0x49474001, 0x481a6802, - 0x592c000a, 0x82001d80, 0x70000000, 0x04020007, - 0x0401f8a2, 0x04020011, 0x4a034406, 0x00000002, - 0x0201f000, 0x001020b2, 0x82001d80, 0x72000000, - 0x02020000, 0x001020b6, 0x0401f898, 0x04020897, - 0x04020896, 0x04020005, 0x4a034406, 0x00000002, - 0x0201f000, 0x001020b2, 0x58ee580d, 0x4a025c04, - 0x00008000, 0x497a5a04, 0x592c3208, 0x80183102, - 0x592c1801, 0x4a001805, 0x01000000, 0x0201f800, - 0x00108e8e, 0x04020005, 0x4a034406, 0x00000003, - 0x0201f000, 0x001020b2, 0x4a01d809, 0x0010379d, - 0x1c01f000, 0x592c4000, 0x592c0005, 0x82000580, - 0x01000000, 0x04020005, 0x4a034406, 0x00000004, - 0x0201f000, 0x001020b2, 0x4c580000, 0x4c500000, - 0x4c540000, 0x832c3c00, 0x00000005, 0x401ca000, - 0x401ca800, 0x5820280a, 0x4200b000, 0x00000002, - 0x82143580, 0x70000000, 0x04000003, 0x4200b000, - 0x0000000f, 0x0201f800, 0x0010a94f, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x401c0000, 0x58201006, - 0x58201807, 0x58202205, 0x80102102, 0x82143580, - 0x70000000, 0x04020008, 0x82103480, 0x00000002, - 0x02001000, 0x001020b6, 0x42000800, 0x00000002, - 0x0401f079, 0x82143580, 0x72000000, 0x02020000, - 0x001020b6, 0x82103480, 0x0000002a, 0x02001000, - 0x001020b6, 0x42000800, 0x0000000f, 0x0401f86e, - 0x4a01d809, 0x001037d7, 0x1c01f000, 0x4031d800, - 0x58ef400b, 0x58ee580e, 0x58ec0002, 0x82000580, - 0x00000200, 0x02000000, 0x001020aa, 0x592e5800, - 0x832c0c00, 0x00000005, 0x4c580000, 0x4c500000, - 0x4c540000, 0x4004a000, 0x4004a800, 0x4200b000, - 0x0000000f, 0x0201f800, 0x0010a94f, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x40ec1000, 0x4a001001, - 0x00000000, 0x4a001004, 0x0000000f, 0x48041003, - 0x0201f800, 0x001008a1, 0x4a01d809, 0x001037f9, - 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ee580e, - 0x58ec0002, 0x82000580, 0x00000200, 0x02000000, - 0x001020aa, 0x832c0c00, 0x00000005, 0x4c580000, - 0x4c500000, 0x4c540000, 0x4004a000, 0x4004a800, - 0x4200b000, 0x0000000c, 0x0201f800, 0x0010a94f, - 0x5c00a800, 0x5c00a000, 0x5c00b000, 0x40ec1000, - 0x4a001001, 0x00000000, 0x4a001004, 0x0000000c, - 0x48041003, 0x0201f800, 0x001008a1, 0x4a01d809, - 0x0010205f, 0x1c01f000, 0x0201f800, 0x0010082a, - 0x04000010, 0x497a5800, 0x58ec000d, 0x80000540, - 0x04020004, 0x492dd80d, 0x492dd80e, 0x0401f007, - 0x58ec000e, 0x48025800, 0x82000400, 0x00000001, - 0x452c0000, 0x492dd80e, 0x832c0400, 0x00000004, - 0x492fc857, 0x4803c857, 0x1c01f000, 0x4d2c0000, - 0x58ec400d, 0x802041c0, 0x04000008, 0x4823c857, - 0x40225800, 0x592c4001, 0x497a5801, 0x0201f800, - 0x0010083a, 0x0401f7f8, 0x4979d80d, 0x4979d80e, - 0x5c025800, 0x1c01f000, 0x42003000, 0x00000001, - 0x0401f003, 0x42003000, 0x00000000, 0x4803c857, - 0x4807c857, 0x480bc857, 0x480fc857, 0x481bc857, - 0x48efc857, 0x4819d801, 0x800409c0, 0x02000800, - 0x00100615, 0x4805d804, 0x4801d803, 0x4809d807, - 0x480dd808, 0x40ec1000, 0x0201f800, 0x001008a1, - 0x4a01d809, 0x0010205f, 0x1c01f000, 0x80002d80, - 0x480bc857, 0x480fc857, 0x4813c857, 0x4817c857, - 0x4d2c0000, 0x4da00000, 0x42034000, 0x0010b2a0, - 0x59a00017, 0x800001c0, 0x04020013, 0x04006012, - 0x480bc020, 0x480fc021, 0x4813c022, 0x4817c023, - 0x900811c0, 0x82081540, 0x00000012, 0x480bc011, - 0x59e00017, 0x8c000508, 0x04020004, 0x4203e000, - 0x30000001, 0x0401f053, 0x4a03c017, 0x00000002, - 0x0401f7fb, 0x4c040000, 0x4c1c0000, 0x80000800, - 0x48074017, 0x59a0381a, 0x481fc857, 0x801c39c0, - 0x04020027, 0x82000480, 0x0000000a, 0x04021010, - 0x59a00018, 0x80000000, 0x48034018, 0x59a00219, - 0x82000400, 0x00000002, 0x82000c80, 0x00000013, - 0x48034219, 0x04001003, 0x497b4219, 0x41780000, - 0x59a03816, 0x801c3c00, 0x0401f030, 0x4803c856, - 0x0201f800, 0x0010082a, 0x04000007, 0x492f401a, - 0x492f401b, 0x412c3800, 0x497b421c, 0x497a5813, - 0x0401f026, 0x59880052, 0x80000000, 0x48031052, - 0x59a00017, 0x80000040, 0x48034017, 0x59a00219, - 0x59a03816, 0x801c3c00, 0x0401f01c, 0x59a0021c, - 0x82000400, 0x00000002, 0x82000c80, 0x00000012, - 0x04021004, 0x4803421c, 0x801c3c00, 0x0401f013, - 0x0201f800, 0x0010082a, 0x0402000b, 0x59880052, - 0x80000000, 0x48031052, 0x59a00017, 0x80000040, - 0x48034017, 0x4803c856, 0x59a0021c, 0x801c3c00, - 0x0401f006, 0x492f401a, 0x492c3813, 0x412c3800, - 0x497b421c, 0x497a5813, 0x48083c00, 0x480c3a00, - 0x48103c01, 0x48143a01, 0x5c003800, 0x5c000800, - 0x5c034000, 0x5c025800, 0x1c01f000, 0x480fc857, - 0x4813c857, 0x481bc857, 0x42000000, 0x0010b611, - 0x0201f800, 0x0010a86e, 0x801800d0, 0x40002800, - 0x42001000, 0x00008014, 0x0401f786, 0x4c000000, - 0x599c0017, 0x8c000512, 0x5c000000, 0x1c01f000, - 0x4c000000, 0x599c0018, 0x8c00050e, 0x5c000000, - 0x1c01f000, 0x59a80821, 0x800409c0, 0x04000005, - 0x4a034406, 0x00000001, 0x0201f000, 0x001020b2, - 0x836c0580, 0x00000003, 0x04000005, 0x4a034406, - 0x00000007, 0x0201f000, 0x001020b2, 0x599c0017, - 0x8c00050a, 0x04000005, 0x4a034406, 0x00000008, - 0x0201f000, 0x001020b2, 0x59340405, 0x8c000508, - 0x04020004, 0x8c00050a, 0x02020000, 0x001032e2, - 0x497a5a04, 0x497a5805, 0x4a025c04, 0x00008000, - 0x0201f800, 0x00108f2d, 0x04020005, 0x4a034406, - 0x00000003, 0x0201f000, 0x001020b2, 0x4a01d809, - 0x00103906, 0x1c01f000, 0x592c0005, 0x82000580, - 0x01000000, 0x04020005, 0x4a034406, 0x00000004, - 0x0201f000, 0x001020b2, 0x59a28c06, 0x0201f800, - 0x00020267, 0x02020000, 0x001020b6, 0x0201f000, - 0x001032e2, 0x82001580, 0x0000ffff, 0x04000009, - 0x0201f800, 0x001059b9, 0x02000800, 0x00020267, - 0x0402000c, 0x0201f800, 0x00105ce7, 0x0401f009, - 0x42028800, 0x000007ef, 0x0201f800, 0x00020267, - 0x02000800, 0x00105ce7, 0x81468840, 0x040217fb, - 0x1c01f000, 0x4803c856, 0x4c0c0000, 0x4d340000, - 0x4d440000, 0x42028800, 0x000007fe, 0x0201f800, - 0x00020267, 0x04020009, 0x5934180a, 0x820c1d00, - 0x00000001, 0x820c1d80, 0x00000001, 0x42001000, - 0x0000801b, 0x0401ff1e, 0x5c028800, 0x5c026800, - 0x5c001800, 0x1c01f000, 0x599c0017, 0x8c000508, - 0x1c01f000, 0x48efc857, 0x04011000, 0x48efc840, - 0x4a03c842, 0x00000011, 0x40000000, 0x040117ff, - 0x4a01d80f, 0xbeefbeef, 0x1c01f000, 0x497b4000, - 0x497b4001, 0x497b4002, 0x497b4003, 0x497b4004, - 0x1c01f000, 0x59c400a4, 0x4c580000, 0x4c500000, - 0x4c540000, 0x82000500, 0x0000000f, 0x82000480, - 0x00000007, 0x0400100a, 0x82006c80, 0x00000007, - 0x02021800, 0x00100615, 0x0c01f807, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x1c01f000, 0x0401f90c, - 0x0401f7fb, 0x0010396c, 0x00103972, 0x00103997, - 0x001039b9, 0x00103a78, 0x0010396b, 0x1c01f000, - 0x59c40806, 0x8c040d00, 0x04020003, 0x84040d40, - 0x48078806, 0x1c01f000, 0x59c40005, 0x8c000534, - 0x02020000, 0x001040ce, 0x4a038805, 0xffffffff, - 0x42006000, 0x00020000, 0x0201f800, 0x001040b2, - 0x59a80015, 0x82000500, 0xfffffffa, 0x84000542, - 0x48035015, 0x497b5026, 0x42000800, 0x0010bc20, - 0x45780800, 0x497b5013, 0x42006000, 0xffefffff, - 0x42006800, 0x40000000, 0x0201f800, 0x001040ad, - 0x59c40006, 0x82000500, 0xffffff0f, 0x48038806, - 0x42000800, 0x00000010, 0x42001000, 0x0010401b, - 0x0201f800, 0x00105cbc, 0x0401f001, 0x42006000, - 0xffffffff, 0x42006800, 0x00800000, 0x0201f800, - 0x001040ad, 0x4200b000, 0x000000c8, 0x59c400a4, - 0x82000500, 0x0000000f, 0x82000580, 0x0000000a, - 0x0400000f, 0x8058b040, 0x040207f9, 0x497b5014, - 0x42006000, 0xbf7fffff, 0x42006800, 0x00018000, - 0x0201f800, 0x001040ad, 0x42006000, 0xfffeffff, - 0x41786800, 0x0201f000, 0x001040ad, 0x497b5014, - 0x4a035012, 0x00000000, 0x80000580, 0x0201f000, - 0x001040b9, 0x4a038805, 0xffffffff, 0x59a80012, - 0x82000c80, 0x00000004, 0x02021800, 0x00100615, - 0x0c01f001, 0x001039c4, 0x001039f1, 0x00103a6e, - 0x4803c856, 0x59c400a3, 0x8400051e, 0x480388a3, - 0x4a035012, 0x00000001, 0x59c40008, 0x8400054e, - 0x48038808, 0x0201f800, 0x00104093, 0x42007800, - 0x0010b34a, 0x4a007806, 0x11010000, 0x4200a000, - 0x0010b202, 0x4200a800, 0x0010b351, 0x4200b000, - 0x00000002, 0x0201f800, 0x0010a93e, 0x497b8802, - 0x42000800, 0x00000003, 0x497b504a, 0x0201f800, - 0x00103f8e, 0x4a03504a, 0x00000001, 0x497b5016, - 0x0201f800, 0x001040c0, 0x42006000, 0xffffffff, - 0x42006800, 0x00080000, 0x0201f800, 0x001040ad, - 0x42006000, 0xfff7ffff, 0x41786800, 0x0201f000, - 0x001040ad, 0x59a80016, 0x497b5016, 0x80002540, - 0x0400006a, 0x59c40004, 0x82000500, 0x00000003, - 0x04020075, 0x59a80815, 0x8c040d02, 0x0400004f, - 0x82100580, 0x0000000c, 0x04020053, 0x82100400, - 0x00000018, 0x8000b104, 0x41cc1000, 0x42001800, - 0x0010b34a, 0x50080800, 0x500c0000, 0x80040580, - 0x0402001e, 0x80081000, 0x800c1800, 0x8058b040, - 0x040207f9, 0x0201f800, 0x001040c0, 0x42006000, - 0xffffffff, 0x42006800, 0x00500000, 0x0201f800, - 0x001040ad, 0x4a035012, 0x00000002, 0x4a035014, - 0x00000002, 0x0201f800, 0x0010164b, 0x42000800, - 0x000007d0, 0x42001000, 0x00103f62, 0x0201f800, - 0x00105da7, 0x59a80015, 0x84000506, 0x48035015, - 0x0201f000, 0x00104093, 0x59cc0806, 0x82040d80, - 0x11010000, 0x04020028, 0x59cc0800, 0x82040500, - 0x00ffffff, 0x0400001a, 0x82000580, 0x000000ef, - 0x04020017, 0x59cc0801, 0x82040500, 0x00ffffff, - 0x82000580, 0x000000ef, 0x04020011, 0x83cca400, - 0x00000007, 0x4200a800, 0x0010b202, 0x4200b000, - 0x00000002, 0x50500800, 0x50540000, 0x80040480, - 0x04001007, 0x04020010, 0x8050a000, 0x8054a800, - 0x8058b040, 0x040207f8, 0x0401f00b, 0x59a80015, - 0x84000502, 0x48035015, 0x41cca000, 0x4200a800, - 0x0010b34a, 0x4200b000, 0x00000009, 0x0201f800, - 0x0010a93e, 0x0201f800, 0x001040c0, 0x42006000, - 0xffffffff, 0x42006800, 0x00080000, 0x0201f800, - 0x001040ad, 0x42006000, 0xfff7ffff, 0x41786800, - 0x0201f800, 0x001040ad, 0x42006000, 0xffffffff, - 0x42006800, 0x00004000, 0x0201f800, 0x001040ad, - 0x59c40004, 0x82000500, 0x00000003, 0x04020006, - 0x497b5016, 0x42000800, 0x00000003, 0x0201f000, - 0x00103f8e, 0x1c01f000, 0x1c01f000, 0x59a80014, - 0x82006d80, 0x0000000f, 0x04000005, 0x82000580, - 0x0000001b, 0x02020800, 0x00103f53, 0x1c01f000, - 0x59a80015, 0x84000506, 0x48035015, 0x497b504a, - 0x59a80014, 0x82000c80, 0x0000001e, 0x02021800, - 0x00100615, 0x0c01f001, 0x00103ab6, 0x00103acd, - 0x00103af6, 0x00103b11, 0x00103b34, 0x00103b65, - 0x00103b87, 0x00103bba, 0x00103bdc, 0x00103c00, - 0x00103c3c, 0x00103c63, 0x00103c79, 0x00103c8b, - 0x00103ca3, 0x00103cba, 0x00103cbf, 0x00103ce7, - 0x00103d0a, 0x00103d30, 0x00103d53, 0x00103d86, - 0x00103dc8, 0x00103df2, 0x00103e0a, 0x00103e4a, - 0x00103e63, 0x00103e76, 0x00103e77, 0x4803c856, - 0x4202d800, 0x00000007, 0x0201f800, 0x00104e0d, - 0x04000007, 0x42006000, 0xffffffd7, 0x41786800, - 0x0201f800, 0x001040ad, 0x0401f00b, 0x59c40006, - 0x82000500, 0xffffff0f, 0x48038806, 0x42001000, - 0x000000f0, 0x0201f800, 0x001019aa, 0x0201f800, - 0x00104d6c, 0x1c01f000, 0x4803c856, 0x42006000, - 0xbf7fffff, 0x42006800, 0x00400000, 0x0201f800, - 0x001040ad, 0x0201f800, 0x0010164b, 0x4a035014, - 0x00000001, 0x42001000, 0x0010401b, 0x0201f800, - 0x00105cdd, 0x0201f800, 0x00104024, 0x42000800, - 0x000007d0, 0x42001000, 0x00103f62, 0x0201f000, - 0x00105da7, 0x59a80016, 0x82000580, 0x00000014, - 0x04020023, 0x4803c857, 0x42006000, 0xffbfffff, - 0x41786800, 0x0201f800, 0x001040ad, 0x59c40004, - 0x82000500, 0x00000003, 0x04020019, 0x42001000, - 0x00103f62, 0x0201f800, 0x00105cc9, 0x59cc1006, - 0x82081580, 0x11020000, 0x04020012, 0x59cc1007, - 0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504, - 0x04020008, 0x42000000, 0x0010b63d, 0x0201f800, - 0x0010a86e, 0x59a80015, 0x84000544, 0x48035015, - 0x4a035014, 0x00000010, 0x0401f1cd, 0x1c01f000, - 0x0201f000, 0x00103f53, 0x4803c856, 0x4a035014, - 0x00000003, 0x42006000, 0xbf3fffff, 0x42006800, - 0x00100000, 0x0201f800, 0x001040ad, 0x42001000, - 0x0010401b, 0x0201f800, 0x00105cdd, 0x0201f800, - 0x00104024, 0x42001000, 0x00103f62, 0x0201f800, - 0x00105cc9, 0x42007800, 0x0010b350, 0x46007800, - 0x11020000, 0x42000800, 0x00000005, 0x0201f000, - 0x00103f8e, 0x59a80016, 0x80000540, 0x0400001e, - 0x4803c857, 0x42001000, 0x00103f62, 0x0201f800, - 0x00105cc9, 0x59a80016, 0x82000580, 0x00000014, - 0x04020016, 0x59cc1006, 0x82081580, 0x11020000, - 0x04020012, 0x59cc1007, 0x8c08153e, 0x0400000b, - 0x59a80015, 0x8c000504, 0x04020008, 0x42000000, - 0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015, - 0x84000544, 0x48035015, 0x4a035014, 0x00000004, - 0x0401f004, 0x1c01f000, 0x0201f000, 0x00103f53, - 0x4803c856, 0x4a035014, 0x00000005, 0x83cca400, - 0x00000006, 0x4200a800, 0x0010b350, 0x4200b000, - 0x00000005, 0x0201f800, 0x0010a93e, 0x42007800, - 0x0010b350, 0x46007800, 0x11030000, 0x0201f800, - 0x00103f58, 0x04020014, 0x59a80015, 0x8c000500, - 0x04020011, 0x59a80810, 0x82040580, 0x00ffffff, - 0x0400000d, 0x82040d00, 0x000000ff, 0x82040400, - 0x00101eb5, 0x50000800, 0x80040910, 0x42001000, - 0x00000004, 0x0401fb95, 0x0400000b, 0x0201f800, - 0x0010403d, 0x4200b000, 0x00000004, 0x83cca400, - 0x00000007, 0x4200a800, 0x0010b351, 0x0201f800, - 0x0010a93e, 0x42000800, 0x00000005, 0x0201f000, - 0x00103f8e, 0x59a80016, 0x80000540, 0x0400001e, - 0x4803c857, 0x42001000, 0x00103f62, 0x0201f800, - 0x00105cc9, 0x59a80016, 0x82000580, 0x00000014, - 0x04020016, 0x59cc1006, 0x82081580, 0x11030000, - 0x04020012, 0x59cc1007, 0x8c08153e, 0x0400000b, - 0x59a80015, 0x8c000504, 0x04020008, 0x42000000, - 0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015, - 0x84000544, 0x48035015, 0x4a035014, 0x00000006, - 0x0401f003, 0x1c01f000, 0x0401f3cd, 0x4803c856, - 0x4a035014, 0x00000007, 0x83cca400, 0x00000006, - 0x4200a800, 0x0010b350, 0x4200b000, 0x00000005, - 0x0201f800, 0x0010a93e, 0x42007800, 0x0010b350, - 0x46007800, 0x11040000, 0x0401fbc2, 0x04020020, - 0x59a80015, 0x8c000500, 0x0402001d, 0x599c0017, - 0x8c000500, 0x0400001a, 0x599c1402, 0x82080480, - 0x0000007f, 0x02021800, 0x00100615, 0x4c080000, - 0x82081400, 0x00101eb5, 0x50081000, 0x82081500, - 0x000000ff, 0x480b5010, 0x42000800, 0x00000003, - 0x0201f800, 0x001069af, 0x5c000800, 0x42001000, - 0x00000004, 0x0401fb39, 0x04000005, 0x0401fd25, - 0x04000003, 0x0201f800, 0x00101668, 0x42000800, - 0x00000005, 0x0401f3d5, 0x59a80016, 0x80000540, - 0x0400001e, 0x4803c857, 0x42001000, 0x00103f62, - 0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580, - 0x00000014, 0x04020016, 0x59cc1006, 0x82081580, - 0x11040000, 0x04020012, 0x59cc1007, 0x8c08153e, - 0x0400000b, 0x59a80015, 0x8c000504, 0x04020008, - 0x42000000, 0x0010b63d, 0x0201f800, 0x0010a86e, - 0x59a80015, 0x84000544, 0x48035015, 0x4a035014, - 0x00000008, 0x0401f003, 0x1c01f000, 0x0401f378, - 0x4803c856, 0x4a035014, 0x00000009, 0x83cca400, - 0x00000006, 0x4200a800, 0x0010b350, 0x4200b000, - 0x00000005, 0x0201f800, 0x0010a93e, 0x42007800, - 0x0010b350, 0x46007800, 0x11050100, 0x0401fb6d, - 0x0402000a, 0x59a80015, 0x8c000500, 0x04020007, - 0x0401fa88, 0x04020005, 0x82000540, 0x00000001, - 0x0201f800, 0x00101668, 0x42000800, 0x00000005, - 0x0401fb96, 0x4d3c0000, 0x42027800, 0x00000001, - 0x0201f800, 0x00109640, 0x5c027800, 0x1c01f000, - 0x59a80016, 0x80000540, 0x04000038, 0x4803c857, - 0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9, - 0x59a80016, 0x82000580, 0x00000014, 0x04020030, - 0x59cc1006, 0x82080500, 0x11050000, 0x82000580, - 0x11050000, 0x0402002a, 0x8c081510, 0x04000014, - 0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015, - 0x8c000504, 0x04020008, 0x42000000, 0x0010b63d, - 0x0201f800, 0x0010a86e, 0x59a80015, 0x84000544, - 0x48035015, 0x4a035013, 0x00000001, 0x4a035014, - 0x0000000a, 0x0401f817, 0x0401f014, 0x80000540, - 0x04020013, 0x59cc1007, 0x8c08153e, 0x0400000b, - 0x59a80015, 0x8c000504, 0x04020008, 0x42000000, - 0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015, - 0x84000544, 0x48035015, 0x497b5013, 0x4a035014, - 0x0000000e, 0x0401f06a, 0x1c01f000, 0x0401f318, - 0x4803c856, 0x4a035014, 0x0000000b, 0x42001000, - 0x0010b351, 0x4008a800, 0x4200b000, 0x00000020, - 0x4600a800, 0xffffffff, 0x8054a800, 0x8058b040, - 0x040207fc, 0x42007800, 0x0010b350, 0x46007800, - 0x11060000, 0x42001000, 0x0010b351, 0x0401fb09, - 0x04000005, 0x50080000, 0x46001000, 0x00ffffff, - 0x0401f00c, 0x50080800, 0x82040d00, 0x0000ffff, - 0x59a80010, 0x82000500, 0x000000ff, 0x82000540, - 0x00000100, 0x800000e0, 0x80040d40, 0x44041000, - 0x42000800, 0x00000021, 0x0401f32c, 0x59a80016, - 0x80000540, 0x04000012, 0x4803c857, 0x59a80016, - 0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9, - 0x59a80016, 0x82000580, 0x00000084, 0x04020009, - 0x59cc1006, 0x82081580, 0x11060000, 0x04020005, - 0x4a035014, 0x0000000c, 0x0401f003, 0x1c01f000, - 0x0401f2db, 0x4803c856, 0x4a035014, 0x0000000d, - 0x83cca400, 0x00000006, 0x4200a800, 0x0010b350, - 0x4200b000, 0x00000021, 0x0201f800, 0x0010a93e, - 0x42007800, 0x0010b350, 0x46007800, 0x11070000, - 0x42000800, 0x00000021, 0x0401f304, 0x59a80016, - 0x80000540, 0x04000014, 0x4803c857, 0x59a80016, - 0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9, - 0x82000580, 0x00000084, 0x0402000c, 0x59cc1006, - 0x82081580, 0x11070000, 0x04020008, 0x4a035013, - 0x00000001, 0x0401fa91, 0x4a035014, 0x0000000e, - 0x0401f003, 0x1c01f000, 0x0401f2b1, 0x4803c856, - 0x82040d40, 0x00000001, 0x0201f800, 0x001040b9, - 0x4a035014, 0x0000000f, 0x497b5016, 0x42006000, - 0xffffffff, 0x42006800, 0x00300000, 0x0401fbfe, - 0x42006000, 0xffdfffff, 0x41786800, 0x0401fbfa, - 0x42000800, 0x000007d0, 0x42001000, 0x00103f62, - 0x0201f000, 0x00105ca2, 0x4803c856, 0x59a80016, - 0x80000540, 0x04020296, 0x1c01f000, 0x4803c856, - 0x4a035014, 0x00000011, 0x83cca400, 0x00000006, - 0x4200a800, 0x0010b350, 0x4200b000, 0x00000005, - 0x0201f800, 0x0010a93e, 0x4200a800, 0x0010b350, - 0x4600a800, 0x11020000, 0x0401fa8a, 0x04020015, - 0x59a80010, 0x82000d00, 0xffff0000, 0x04000011, - 0x82000500, 0x000000ff, 0x0400000e, 0x82000c00, - 0x00101eb5, 0x50040800, 0x80040910, 0x82040580, - 0x0000007e, 0x04000007, 0x82040580, 0x00000080, - 0x04000004, 0x42001000, 0x00000004, 0x0401fa07, - 0x42000800, 0x00000005, 0x0401f2a8, 0x59a80016, - 0x80000540, 0x04000020, 0x4803c857, 0x42001000, - 0x00103f62, 0x0201f800, 0x00105cc9, 0x59a80016, - 0x82000580, 0x00000014, 0x04020016, 0x59cc1006, - 0x82081580, 0x11030000, 0x04020012, 0x59cc1007, - 0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504, - 0x04020008, 0x42000000, 0x0010b63d, 0x0201f800, - 0x0010a86e, 0x59a80015, 0x84000544, 0x48035015, - 0x4a035014, 0x00000012, 0x0401f804, 0x0401f002, - 0x0401fa4b, 0x1c01f000, 0x4803c856, 0x4a035014, - 0x00000013, 0x83cca400, 0x00000006, 0x4200a800, - 0x0010b350, 0x4200b000, 0x00000005, 0x0201f800, - 0x0010a93e, 0x4200a800, 0x0010b350, 0x4600a800, - 0x11030000, 0x0401fa3f, 0x04020013, 0x59a80015, - 0x8c000500, 0x04020010, 0x59a80810, 0x82040580, - 0x00ffffff, 0x0400000c, 0x82040d00, 0x000000ff, - 0x82040400, 0x00101eb5, 0x50000800, 0x80040910, - 0x42001000, 0x00000004, 0x0401f9c0, 0x04000002, - 0x0401fb11, 0x42000800, 0x00000005, 0x0401f25f, - 0x59a80016, 0x80000540, 0x04000020, 0x4803c857, - 0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9, - 0x59a80016, 0x82000580, 0x00000014, 0x04020016, - 0x59cc1006, 0x82081580, 0x11040000, 0x04020012, - 0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015, - 0x8c000504, 0x04020008, 0x42000000, 0x0010b63d, - 0x0201f800, 0x0010a86e, 0x59a80015, 0x84000544, - 0x48035015, 0x4a035014, 0x00000014, 0x0401f804, - 0x0401f002, 0x0401fa02, 0x1c01f000, 0x4803c856, - 0x4a035014, 0x00000015, 0x83cca400, 0x00000006, - 0x4200a800, 0x0010b350, 0x4200b000, 0x00000005, - 0x0201f800, 0x0010a93e, 0x4200a800, 0x0010b350, - 0x4600a800, 0x11040000, 0x0401f9f6, 0x04020020, - 0x59a80015, 0x8c000500, 0x0402001d, 0x599c0017, - 0x8c000500, 0x0400001a, 0x599c1402, 0x82080480, - 0x0000007f, 0x02021800, 0x00100615, 0x4c080000, - 0x82081400, 0x00101eb5, 0x50081000, 0x82081500, - 0x000000ff, 0x480b5010, 0x42000800, 0x00000003, - 0x0201f800, 0x001069af, 0x5c000800, 0x42001000, - 0x00000004, 0x0401f96d, 0x04000005, 0x0201f800, - 0x001038d8, 0x02020800, 0x00101668, 0x42000800, - 0x00000005, 0x0401f209, 0x59a80016, 0x80000540, - 0x0400003f, 0x4803c857, 0x42001000, 0x00103f62, - 0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580, - 0x00000014, 0x04020035, 0x59cc1006, 0x82080500, - 0x11050000, 0x82000580, 0x11050000, 0x0402002f, - 0x8c081510, 0x04000010, 0x0401fb1f, 0x59cc1007, - 0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504, - 0x04020008, 0x42000000, 0x0010b63d, 0x0201f800, - 0x0010a86e, 0x59a80015, 0x84000544, 0x48035015, - 0x0401f013, 0x59cc1007, 0x8c08153e, 0x0400000b, - 0x59a80015, 0x8c000504, 0x04020008, 0x42000000, - 0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015, - 0x84000544, 0x48035015, 0x82000540, 0x00000001, - 0x0401fb01, 0x497b5013, 0x0401f003, 0x4a035013, - 0x00000001, 0x59cc1007, 0x8c08153c, 0x04000003, - 0x4a035026, 0x00000008, 0x4a035014, 0x00000016, - 0x0401f804, 0x0401f002, 0x0401f98d, 0x1c01f000, - 0x4803c856, 0x83cca400, 0x00000006, 0x4200a800, - 0x0010b350, 0x4200b000, 0x00000005, 0x0201f800, - 0x0010a93e, 0x4a035014, 0x00000017, 0x59a80013, - 0x8c000500, 0x04000006, 0x42001000, 0x0010b350, - 0x46001000, 0x11050100, 0x0401f003, 0x4a035014, - 0x0000001b, 0x0401f97b, 0x0402000a, 0x59a80015, - 0x8c000500, 0x04020007, 0x0401f896, 0x04020005, - 0x82000540, 0x00000001, 0x0201f800, 0x00101668, - 0x42000800, 0x00000005, 0x0401f9a4, 0x4d3c0000, - 0x42027800, 0x00000001, 0x0201f800, 0x00109640, - 0x5c027800, 0x1c01f000, 0x59a80016, 0x80000540, - 0x04000015, 0x4803c857, 0x42001000, 0x00103f62, - 0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580, - 0x00000084, 0x0402000b, 0x59cc1006, 0x82081580, - 0x11060000, 0x04020007, 0x80000580, 0x0401fab6, - 0x4a035014, 0x00000018, 0x0401f804, 0x0401f002, - 0x0401f94b, 0x1c01f000, 0x4803c856, 0x4a035014, - 0x00000019, 0x83cca400, 0x00000006, 0x4200a800, - 0x0010b350, 0x4200b000, 0x00000021, 0x0201f800, - 0x0010a93e, 0x42003800, 0x0010b351, 0x0401f941, - 0x04020018, 0x401c2800, 0x50141000, 0x80080130, - 0x80000000, 0x40001800, 0x82081500, 0x00ffffff, - 0x800000f0, 0x80080540, 0x44002800, 0x59a80810, - 0x82040d00, 0x000000ff, 0x400c1000, 0x80081104, - 0x82082400, 0x0010b351, 0x50101000, 0x820c0500, - 0x00000003, 0x0c01f806, 0x80081540, 0x44082000, - 0x42000800, 0x00000021, 0x0401f15c, 0x00103e37, - 0x00103e3c, 0x00103e41, 0x00103e46, 0x800408f0, - 0x40040000, 0x82081500, 0x00ffffff, 0x1c01f000, - 0x800408e0, 0x40040000, 0x82081500, 0xff00ffff, - 0x1c01f000, 0x800408d0, 0x40040000, 0x82081500, - 0xffff00ff, 0x1c01f000, 0x40040000, 0x82081500, - 0xffffff00, 0x1c01f000, 0x59a80016, 0x80000540, - 0x04000016, 0x4803c857, 0x42001000, 0x00103f62, - 0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580, - 0x00000084, 0x0402000c, 0x59cc1006, 0x82081580, - 0x11070000, 0x04020008, 0x4a035013, 0x00000001, - 0x0401f8d2, 0x4a035014, 0x0000001a, 0x0401f804, - 0x0401f002, 0x0401f8f2, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401fa54, 0x4a035014, 0x0000001b, - 0x83cca400, 0x00000006, 0x4200a800, 0x0010b350, - 0x59a82016, 0x40100000, 0x8000b104, 0x40580800, - 0x5450a800, 0x8050a000, 0x8054a800, 0x8058b040, - 0x040207fc, 0x0401f119, 0x1c01f000, 0x1c01f000, - 0x4803c856, 0x42003000, 0x00000004, 0x42004000, - 0x0010b351, 0x599c2817, 0x8c142d14, 0x0402001f, - 0x42001000, 0x00000003, 0x40200000, 0x80080400, - 0x50000800, 0x82042580, 0xffffffff, 0x04020005, - 0x80081040, 0x80183040, 0x040207f8, 0x0401f05e, - 0x800811c0, 0x04020006, 0x82042580, 0x3fffffff, - 0x04000058, 0x82040d40, 0xc0000000, 0x4200b000, - 0x00000020, 0x42001800, 0x00000001, 0x40042000, - 0x80102102, 0x04021021, 0x800c18c2, 0x8058b040, - 0x040207fc, 0x0401f04b, 0x41781000, 0x40200000, - 0x80080400, 0x50000800, 0x82042580, 0xffffffff, - 0x04020005, 0x80081000, 0x80183040, 0x040207f8, - 0x0401f040, 0x800811c0, 0x04020003, 0x82040d40, - 0xc0000000, 0x4200b000, 0x00000001, 0x42001800, - 0x80000000, 0x40042000, 0x801020c2, 0x04021007, - 0x800c1902, 0x8058b000, 0x82580480, 0x00000021, - 0x040017fa, 0x0401f02f, 0x40200000, 0x80082400, - 0x50100000, 0x800c0540, 0x44002000, 0x59a80015, - 0x84000540, 0x48035015, 0x40580000, 0x42002800, - 0x00000020, 0x80142c80, 0x40080000, 0x42003800, - 0x00000003, 0x801c0480, 0x800000ca, 0x80142d40, - 0x82144c00, 0x00101eb5, 0x50242800, 0x82142d00, - 0x000000ff, 0x48175010, 0x4c040000, 0x40140800, - 0x0201f800, 0x00101655, 0x5c000800, 0x40001800, - 0x500c0000, 0x80100540, 0x44001800, 0x59a80015, - 0x84000540, 0x48035015, 0x4200a800, 0x0010b351, - 0x4020a000, 0x4200b000, 0x00000004, 0x0201f800, - 0x0010a93e, 0x82000540, 0x00000001, 0x0401f002, - 0x80000580, 0x1c01f000, 0x4807c857, 0x480bc857, - 0x4008b000, 0x83cca400, 0x00000007, 0x4200a800, - 0x0010b351, 0x40541000, 0x0201f800, 0x0010a93e, - 0x40041800, 0x41782000, 0x42000000, 0x00000003, - 0x820c1c80, 0x00000020, 0x04001004, 0x80102000, - 0x80000040, 0x0401f7fb, 0x40041800, 0x801021c0, - 0x04000005, 0x820c1c80, 0x00000020, 0x80102040, - 0x040207fd, 0x42002000, 0x00000001, 0x800c19c0, - 0x04000004, 0x801020c2, 0x800c1840, 0x040207fe, - 0x80083c00, 0x83cc2c00, 0x00000007, 0x80142c00, - 0x50140000, 0x80102d00, 0x04020012, 0x80100540, - 0x44003800, 0x82042400, 0x00101eb5, 0x50102800, - 0x82142d00, 0x000000ff, 0x48175010, 0x4c040000, - 0x40140800, 0x0201f800, 0x00101655, 0x5c000800, - 0x59a80015, 0x84000540, 0x48035015, 0x80000580, - 0x1c01f000, 0x4807c856, 0x42001000, 0x00008017, - 0x59a8184e, 0x0201f800, 0x0010a876, 0x0201f800, - 0x00103857, 0x1c01f000, 0x4807c856, 0x4200b000, - 0x00000020, 0x83cca400, 0x00000007, 0x4200a800, - 0x0010bc20, 0x0201f000, 0x0010a94f, 0x4807c856, - 0x0201f800, 0x00106c32, 0x42000800, 0x000000f7, - 0x0401f8f4, 0x497b2804, 0x497b2805, 0x497b281c, - 0x497b281d, 0x4202d800, 0x00000001, 0x42006000, - 0xbf7fffff, 0x42006800, 0x00018000, 0x0401f966, - 0x42006000, 0xfffeffff, 0x41786800, 0x0401f962, - 0x497b504e, 0x42000800, 0x0000002d, 0x42001000, - 0x00103fe4, 0x0201f000, 0x00105ca2, 0x4807c856, - 0x0401ffe3, 0x497b5014, 0x497b5016, 0x1c01f000, - 0x4807c856, 0x59a80005, 0x8c000506, 0x1c01f000, - 0x4807c856, 0x42006000, 0xffffffff, 0x42006800, - 0x00000028, 0x0401f14c, 0x4807c856, 0x0401ffc2, - 0x0201f800, 0x0010698c, 0x4df00000, 0x0201f800, - 0x00106b71, 0x5c03e000, 0x02000800, 0x00106982, - 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580, - 0x00000002, 0x0402000a, 0x42006000, 0xffffffff, - 0x42006800, 0x00200000, 0x0401f937, 0x42006000, - 0xffdfffff, 0x41786800, 0x0401f933, 0x497b5014, - 0x42000800, 0x000000f7, 0x0401f8b2, 0x59c400a3, - 0x82000500, 0xbf20bfff, 0x82000540, 0x0001c000, - 0x480388a3, 0x84000520, 0x480388a3, 0x497b504e, - 0x42000800, 0x0000002d, 0x42001000, 0x00103fe4, - 0x0201f000, 0x00105ca2, 0x497b5016, 0x59b400f5, - 0x8c000500, 0x04020004, 0x82000540, 0x00000001, - 0x480368f5, 0x800400c4, 0x82000400, 0x00002000, - 0x4803910a, 0x59b400f6, 0x82000500, 0x00000018, - 0x040207fd, 0x4a0368f0, 0x0010b349, 0x42000000, - 0x0010b350, 0x4c040000, 0x50000800, 0x82040d80, - 0x11010000, 0x04000003, 0x50000800, 0x4807c857, - 0x5c000800, 0x480368f1, 0x82040400, 0x0000dc00, - 0x480368f3, 0x59c400a4, 0x82000500, 0x0000000f, - 0x82000580, 0x00000008, 0x04020017, 0x4c5c0000, - 0x4c600000, 0x59c4b805, 0x8c5cbd3a, 0x04020005, - 0x42000000, 0x0010b616, 0x0201f800, 0x0010a86e, - 0x4a038805, 0x02000000, 0x0201f800, 0x00101a59, - 0x4000c000, 0x0201f800, 0x001019d0, 0x4202d800, - 0x00000001, 0x497b5014, 0x5c00c000, 0x5c00b800, - 0x1c01f000, 0x59c8010b, 0x8c000502, 0x040007e2, - 0x59c408a4, 0x82040d00, 0x0000000f, 0x82040d80, - 0x0000000b, 0x04020005, 0x59a80814, 0x82040d40, - 0x00002000, 0x0401f004, 0x59a80812, 0x82040d40, - 0x00001000, 0x4807504e, 0x59a8084a, 0x800409c0, - 0x04020007, 0x42000800, 0x000007d0, 0x42001000, - 0x00103f62, 0x0201f800, 0x00105da7, 0x1c01f000, - 0x4807c856, 0x0401ff40, 0x0201f800, 0x0010698c, - 0x4df00000, 0x0201f800, 0x00106b71, 0x5c03e000, - 0x02000800, 0x00106982, 0x59c400a4, 0x82000500, - 0x0000000f, 0x82000580, 0x00000002, 0x0402000a, - 0x42006000, 0xffffffff, 0x42006800, 0x00200000, - 0x0401f8b5, 0x42006000, 0xffdfffff, 0x41786800, - 0x0401f8b1, 0x0201f800, 0x00104e13, 0x04000014, - 0x0201f800, 0x00104e23, 0x04020011, 0x4a035032, - 0x0000aaaa, 0x4c040000, 0x0201f800, 0x00101694, - 0x59a8002a, 0x82000500, 0xffff0000, 0x80040540, - 0x4803502a, 0x5c000800, 0x4a035033, 0x00000000, - 0x0201f800, 0x00104d76, 0x0401f008, 0x4a03504c, - 0x00000005, 0x42000000, 0x00000001, 0x0201f800, - 0x001015fa, 0x0401ff1e, 0x1c01f000, 0x0401f809, - 0x42006000, 0xbf7f7fff, 0x41786800, 0x0401f08e, - 0x42006000, 0xbf7f7fff, 0x41786800, 0x0401f08a, - 0x0201f800, 0x00104e23, 0x04020009, 0x59c40006, - 0x82000540, 0x000000f0, 0x48038806, 0x42006000, - 0xbfffffff, 0x41786800, 0x0401f87f, 0x1c01f000, - 0x800408d0, 0x59a80015, 0x8c000506, 0x04000006, - 0x59a80010, 0x82000500, 0x000000ff, 0x80040540, - 0x0401f003, 0x82040540, 0x000000f7, 0x480388a7, - 0x1c01f000, 0x4807c856, 0x42000000, 0x0010b639, - 0x0201f800, 0x0010a86e, 0x42003000, 0x00000005, - 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000d, - 0x42027800, 0x00000002, 0x0401f038, 0x4807c856, - 0x42000000, 0x0010b66a, 0x0201f800, 0x0010a86e, - 0x42003000, 0x00000000, 0x4d3c0000, 0x4c180000, - 0x42003000, 0x0000000f, 0x42027800, 0x00000002, - 0x0401f02a, 0x4807c856, 0x42000000, 0x0010b669, - 0x0201f800, 0x0010a86e, 0x42003000, 0x00000003, - 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000e, - 0x42027800, 0x00000202, 0x0401f01c, 0x4807c856, - 0x42000000, 0x0010b668, 0x0201f800, 0x0010a86e, - 0x42003000, 0x00000004, 0x4d3c0000, 0x4c180000, - 0x42003000, 0x00000010, 0x42027800, 0x00000202, - 0x0401f00e, 0x4807c856, 0x42000000, 0x0010b63c, - 0x0201f800, 0x0010a86e, 0x42003000, 0x00000001, - 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000c, - 0x42027800, 0x00000202, 0x42001800, 0x0000ffff, - 0x42002000, 0x00000007, 0x0201f800, 0x001038c7, - 0x5c003000, 0x4d400000, 0x0201f800, 0x0010a784, - 0x42028000, 0x0000002a, 0x0201f800, 0x00101d90, - 0x5c028000, 0x5c027800, 0x1c01f000, 0x4807c856, - 0x04011000, 0x4a03c840, 0x0010b349, 0x4a03c842, - 0x00000040, 0x40000000, 0x040117ff, 0x42007800, - 0x0010b349, 0x46007800, 0x00000011, 0x803c7800, - 0x4a007800, 0x220000ef, 0x4a007801, 0x000000ef, - 0x4a007802, 0x01380000, 0x4a007803, 0x00000000, - 0x4a007804, 0xffffffff, 0x4a007805, 0x00000000, - 0x1c01f000, 0x59c400a3, 0x80300500, 0x80340540, - 0x480388a3, 0x1c01f000, 0x4833c857, 0x59c400a3, - 0x80300540, 0x480388a3, 0x80300580, 0x480388a3, - 0x1c01f000, 0x4803c856, 0x04000004, 0x4a03504b, - 0x00000001, 0x0401f002, 0x497b504b, 0x1c01f000, - 0x4803c856, 0x59c80002, 0x80000540, 0x0400000a, - 0x80000040, 0x04000008, 0x4a039005, 0x00000140, - 0x42000000, 0x00000006, 0x80000040, 0x040207ff, - 0x0401f7f4, 0x1c01f000, 0x4c5c0000, 0x4c600000, - 0x59c4b805, 0x485fc856, 0x8c5cbd3a, 0x04020005, - 0x42000000, 0x0010b616, 0x0201f800, 0x0010a86e, - 0x4a038805, 0x02000000, 0x0201f800, 0x00101a59, - 0x4000c000, 0x0201f800, 0x001019d0, 0x4a038805, - 0x04000000, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x497a6a00, 0x4a026c00, 0x00000707, 0x497a6801, - 0x497a6808, 0x497a6809, 0x497a6806, 0x497a6807, - 0x497a6c0b, 0x497a680c, 0x0201f800, 0x0010393e, - 0x04020006, 0x5934080f, 0x59340010, 0x80040540, - 0x02020800, 0x00100615, 0x4a026a04, 0x00000100, - 0x497a6a03, 0x59340402, 0x82000500, 0x000000ff, - 0x48026c02, 0x497a6c04, 0x497a6a05, 0x497a6c05, - 0x497a6811, 0x4d2c0000, 0x5934000d, 0x49466c03, - 0x80025d40, 0x04000004, 0x0201f800, 0x00100843, - 0x497a680d, 0x5c025800, 0x599c0401, 0x48026a0b, - 0x599c0208, 0x48026c12, 0x4a02680a, 0x00006000, - 0x0201f000, 0x00104acf, 0x42000000, 0x00000005, - 0x80000d80, 0x0401f02d, 0x0201f800, 0x00104858, - 0x04020017, 0x59a80026, 0x8c00050a, 0x04020010, - 0x59340212, 0x82000500, 0x0000ff00, 0x4803c857, - 0x0400000b, 0x59340a00, 0x8c040d1e, 0x02000000, - 0x000201f8, 0x42000000, 0x00000029, 0x42000800, - 0x00001000, 0x492fc857, 0x0401f018, 0x492fc857, - 0x42000000, 0x00000028, 0x0401f012, 0x59a80805, - 0x8c040d02, 0x04020003, 0x8c040d00, 0x04000004, - 0x42000000, 0x00000004, 0x0401f00a, 0x42000000, - 0x00000029, 0x59340a00, 0x8c040d1e, 0x04000005, - 0x492fc857, 0x42000800, 0x00001000, 0x0401f003, - 0x492fc857, 0x80000d80, 0x4803c857, 0x80028540, - 0x1c01f000, 0x4803c857, 0x59a80005, 0x8c000500, - 0x040207ec, 0x0201f800, 0x00104836, 0x040207e4, - 0x59340200, 0x8c00050e, 0x040007e1, 0x0201f000, - 0x000201f8, 0x0201f800, 0x00104639, 0x040007bf, - 0x0201f000, 0x000201fc, 0x592c0206, 0x492fc857, - 0x82000d80, 0x000007ff, 0x04020006, 0x4a025c0a, - 0x00000030, 0x42026800, 0x0010b320, 0x0401f021, - 0x82000c80, 0x000007f0, 0x04021046, 0x81ac0400, - 0x50000000, 0x80026d40, 0x04000038, 0x0201f800, - 0x00104732, 0x04020038, 0x592c040a, 0x8c00050a, - 0x04020014, 0x592e6009, 0x83300480, 0x0010cfc0, - 0x0400103b, 0x41580000, 0x81300480, 0x04021038, - 0x59300c06, 0x82040580, 0x00000009, 0x04020037, - 0x4a025a06, 0x00000000, 0x497a5800, 0x59300008, - 0x80000540, 0x04020018, 0x492e6008, 0x0401f010, - 0x0201f800, 0x00020892, 0x04000019, 0x592c0206, - 0x49366009, 0x492e6008, 0x4a026406, 0x00000009, - 0x497a6015, 0x49325809, 0x82000d80, 0x000007ff, - 0x04020003, 0x4a026015, 0x00008000, 0x42027000, - 0x00000043, 0x0201f800, 0x000208d8, 0x80000580, - 0x0401f020, 0x40000800, 0x58040000, 0x80000d40, - 0x040207fd, 0x492c0800, 0x0401f01a, 0x42000000, - 0x0000002c, 0x0401f016, 0x42000000, 0x00000028, - 0x0401f013, 0x59a80805, 0x82040500, 0x00000003, - 0x04000004, 0x42000000, 0x00000004, 0x0401f00c, - 0x42000000, 0x00000029, 0x0401f009, 0x42000000, - 0x00000008, 0x0401f006, 0x82040580, 0x00000007, - 0x040207fb, 0x42000000, 0x00000005, 0x80000540, - 0x1c01f000, 0x492fc857, 0x592e8c06, 0x83440d80, - 0x000007fc, 0x04000004, 0x83440480, 0x000007f0, - 0x04021014, 0x0201f800, 0x00020267, 0x04020011, - 0x0201f800, 0x00104842, 0x04020011, 0x0201f800, - 0x00020892, 0x0400001c, 0x49366009, 0x492e6008, - 0x4a026406, 0x0000000a, 0x42027000, 0x00000040, - 0x0201f800, 0x000208d8, 0x80000580, 0x0401f011, - 0x42000000, 0x00000028, 0x0401f00d, 0x0201f800, - 0x00104858, 0x040007fb, 0x59a80805, 0x82040d00, - 0x00000003, 0x04000004, 0x42000000, 0x00000004, - 0x0401f003, 0x42000000, 0x00000029, 0x80000540, - 0x1c01f000, 0x42000000, 0x0000002c, 0x0401f7fc, - 0x492fc857, 0x592e8c06, 0x4947c857, 0x83440c80, - 0x00000800, 0x42000000, 0x0000000a, 0x0402119c, - 0x592c4207, 0x4823c857, 0x82200500, 0x0000000f, - 0x0c01f001, 0x00104205, 0x0010428d, 0x001042dd, - 0x001042e8, 0x001042f3, 0x00104201, 0x00104201, - 0x00104201, 0x00104303, 0x00104361, 0x00104386, - 0x00104201, 0x00104201, 0x00104201, 0x00104201, - 0x00104201, 0x4803c857, 0x42000000, 0x0000000c, - 0x0401f183, 0x592c1008, 0x82081500, 0x00ffffff, - 0x59a80010, 0x80084d80, 0x42000000, 0x00000010, - 0x0400017b, 0x0201f800, 0x00104768, 0x04000036, - 0x4803c857, 0x82004d80, 0x0000001d, 0x0402001a, - 0x0201f800, 0x00105439, 0x59340405, 0x4c000000, - 0x0201f800, 0x00104836, 0x5c000000, 0x04000004, - 0x8c20450a, 0x04000028, 0x80000580, 0x44002800, - 0x59340008, 0x48002802, 0x59340009, 0x48002801, - 0x59340006, 0x48002804, 0x59340007, 0x48002803, - 0x4200b000, 0x00000005, 0x0201f800, 0x00109328, - 0x0401f18c, 0x4803c857, 0x82004d80, 0x0000001a, - 0x04020003, 0x40101000, 0x0401f15c, 0x4803c857, - 0x82004d80, 0x0000001b, 0x04020003, 0x40181000, - 0x0401f156, 0x4803c857, 0x82004d80, 0x0000001c, - 0x04000157, 0x82004d80, 0x00000019, 0x42000000, - 0x0000000a, 0x04000146, 0x42000000, 0x0000000a, - 0x0402015d, 0x59a8006f, 0x8c000502, 0x0400001b, - 0x0201f800, 0x00104836, 0x04000018, 0x59340212, - 0x82000500, 0x0000ff00, 0x42001000, 0x00000010, - 0x0402000c, 0x42001000, 0x00000008, 0x59a80026, - 0x8c000506, 0x04020009, 0x59340002, 0x82000500, - 0x00ff0000, 0x82000580, 0x00ff0000, 0x04000007, - 0x0201f800, 0x00104ada, 0x42000000, 0x0000001c, - 0x40181000, 0x0402012d, 0x0201f800, 0x00020892, - 0x04000137, 0x49366009, 0x492e6008, 0x4a026406, - 0x00000001, 0x8c20450a, 0x04000004, 0x592c0404, - 0x8400055c, 0x48025c04, 0x4c200000, 0x4d3c0000, - 0x42027800, 0x00001800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x5c004000, 0x8c204512, 0x0400000b, - 0x599c0018, 0x8c000518, 0x04000008, 0x592c0009, - 0x82000500, 0x00000380, 0x5934080a, 0x80040d40, - 0x84040d54, 0x4806680a, 0x417a7800, 0x0401f93a, - 0x42000800, 0x00000003, 0x0401f941, 0x42027000, - 0x00000002, 0x0201f800, 0x000208d8, 0x80000580, - 0x0401f130, 0x0201f800, 0x00020267, 0x04020112, - 0x0201f800, 0x0010483c, 0x0400000c, 0x0201f800, - 0x00104836, 0x04020112, 0x4c600000, 0x4178c000, - 0x42027800, 0x00001800, 0x417a6000, 0x0201f800, - 0x00101e48, 0x5c00c000, 0x59a8006f, 0x8c000502, - 0x0400001b, 0x0201f800, 0x00104836, 0x04000018, - 0x59340212, 0x82000500, 0x0000ff00, 0x42001000, - 0x00000010, 0x0402000c, 0x42001000, 0x00000008, - 0x59a80026, 0x8c000506, 0x04020009, 0x59340002, - 0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000, - 0x04000007, 0x0201f800, 0x00104ada, 0x42000000, - 0x0000001c, 0x40181000, 0x040200d4, 0x0201f800, - 0x00020892, 0x040000de, 0x5934080a, 0x8c204512, - 0x0400000c, 0x599c0018, 0x8c000518, 0x04000009, - 0x592c0009, 0x82000500, 0x00000380, 0x82041500, - 0xfffffc7f, 0x80080d40, 0x84040d54, 0x0401f002, - 0x84040d14, 0x4806680a, 0x49366009, 0x492e6008, - 0x4a026406, 0x00000001, 0x417a7800, 0x0401f8ea, - 0x42000800, 0x00000005, 0x0401f8f1, 0x42027000, - 0x00000003, 0x0201f800, 0x000208d8, 0x80000580, - 0x0401f0e0, 0x0201f800, 0x00020267, 0x040200c2, - 0x0201f800, 0x0010484b, 0x040200c5, 0x0201f800, - 0x001092e0, 0x040000b6, 0x80000580, 0x0401f0d5, - 0x0201f800, 0x00020267, 0x040200b7, 0x0201f800, - 0x0010484b, 0x040200ba, 0x0201f800, 0x00108ea3, - 0x040000ab, 0x80000580, 0x0401f0ca, 0x0201f800, - 0x00020267, 0x040200ac, 0x83444d80, 0x000007fe, - 0x42000000, 0x0000000a, 0x0402008d, 0x0201f800, - 0x00104836, 0x040200aa, 0x0201f800, 0x001092f8, - 0x0400009b, 0x80000580, 0x0401f0ba, 0x82200500, - 0x00000070, 0x04020005, 0x8c20450e, 0x42000000, - 0x0000000c, 0x0402007e, 0x8c20450a, 0x0400000d, - 0x4d3c0000, 0x42027800, 0x00001000, 0x8c20450e, - 0x04020002, 0x853e7d56, 0x82200500, 0x000000a0, - 0x0201f800, 0x00104822, 0x5c027800, 0x0401f0a1, - 0x8c204508, 0x04020024, 0x592c1008, 0x82081500, - 0x00ffffff, 0x59a80010, 0x80084d80, 0x42000000, - 0x00000010, 0x04000066, 0x0201f800, 0x00104768, - 0x0400002b, 0x4803c857, 0x82004d80, 0x0000001a, - 0x04020003, 0x40101000, 0x0401f064, 0x4803c857, - 0x82004d80, 0x0000001b, 0x04020003, 0x40181000, - 0x0401f05e, 0x4803c857, 0x82004d80, 0x0000001c, - 0x0400005f, 0x82004d80, 0x00000019, 0x42000000, - 0x0000000a, 0x0400004e, 0x42000000, 0x0000000a, - 0x0401f065, 0x0201f800, 0x00020267, 0x04020062, - 0x4d3c0000, 0x42027800, 0x00001000, 0x8c20450e, - 0x04020002, 0x853e7d56, 0x82200500, 0x00000090, - 0x0201f800, 0x0010480a, 0x5c027800, 0x42000000, - 0x0000000a, 0x0402003a, 0x0401f06a, 0x836c0580, - 0x00000003, 0x42000800, 0x00000007, 0x04020006, - 0x0201f800, 0x0010928e, 0x04000007, 0x80000580, - 0x0401f064, 0x0201f800, 0x00104871, 0x04000059, - 0x0401f05c, 0x0201f800, 0x00104871, 0x0400003c, - 0x0401f058, 0x0201f800, 0x00020267, 0x0402003e, - 0x836c0580, 0x00000003, 0x04020048, 0x8c204508, - 0x0400000a, 0x4c600000, 0x4178c000, 0x42027800, - 0x00001800, 0x417a6000, 0x0201f800, 0x00101e48, - 0x5c00c000, 0x0401f047, 0x0201f800, 0x0010483c, - 0x0400000c, 0x0201f800, 0x00104836, 0x04020030, - 0x4c600000, 0x4178c000, 0x42027800, 0x00001800, - 0x417a6000, 0x0201f800, 0x00101e48, 0x5c00c000, - 0x480bc856, 0x0201f800, 0x001090f8, 0x04000018, - 0x80000580, 0x0401f037, 0x0401f7db, 0x480bc857, - 0x42000800, 0x00000019, 0x40001000, 0x4200b000, - 0x00000002, 0x0401f00a, 0x480bc857, 0x40000800, - 0x4200b000, 0x00000002, 0x0401f005, 0x480bc857, - 0x40000800, 0x4200b000, 0x00000001, 0x480bc857, - 0x42028000, 0x00000031, 0x0401f020, 0x480bc857, - 0x42000800, 0x00000003, 0x4200b000, 0x00000001, - 0x0401f7f7, 0x480bc857, 0x42000800, 0x0000000a, - 0x4200b000, 0x00000001, 0x0401f7f1, 0x480bc857, - 0x42000800, 0x00000009, 0x40001000, 0x4200b000, - 0x00000002, 0x0401f7ea, 0x480bc857, 0x42000800, - 0x00000007, 0x4200b000, 0x00000001, 0x0401f7e4, - 0x480bc857, 0x4200b000, 0x00000001, 0x0401f7e0, - 0x80028580, 0x4178b000, 0x82000540, 0x00000001, - 0x1c01f000, 0x4937c857, 0x59326809, 0x59341200, - 0x813e79c0, 0x04000003, 0x84081540, 0x0401f002, - 0x84081500, 0x480a6a00, 0x1c01f000, 0x59326809, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4937c857, - 0x82040580, 0x00000006, 0x04020004, 0x42000000, - 0x00000606, 0x0401f021, 0x82040580, 0x00000004, - 0x04020004, 0x42000000, 0x00000404, 0x0401f01b, - 0x82040580, 0x00000007, 0x42000000, 0x00000707, - 0x04000016, 0x82040580, 0x00000003, 0x42000000, - 0x00000703, 0x04000011, 0x82040580, 0x00000005, - 0x42000000, 0x00000405, 0x0400000c, 0x82040580, - 0x00000009, 0x42000000, 0x00000409, 0x04000007, - 0x82040580, 0x0000000b, 0x42000000, 0x0000070b, - 0x02020800, 0x00100615, 0x4803c857, 0x48026c00, - 0x82040d80, 0x00000006, 0x04020005, 0x59341404, - 0x800811c0, 0x02000800, 0x00100615, 0x1c01f000, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4947c857, - 0x481bc857, 0x83440480, 0x00000800, 0x04021034, - 0x83441400, 0x0010aa00, 0x50080000, 0x80026d40, - 0x04020011, 0x4c180000, 0x4d2c0000, 0x0201f800, - 0x00100819, 0x412e6800, 0x5c025800, 0x5c003000, - 0x04000027, 0x45341000, 0x497a680d, 0x497a6810, - 0x497a680f, 0x497a680e, 0x4c180000, 0x0401fccd, - 0x5c003000, 0x59340a12, 0x4c040000, 0x0201f800, - 0x00104e0d, 0x5c000800, 0x04000009, 0x82180500, - 0x00ffff00, 0x04000008, 0x59a81010, 0x82081500, - 0x00ffff00, 0x80080580, 0x04000003, 0x80000580, - 0x0401f004, 0x82180500, 0x000000ff, 0x800000d0, - 0x80040d80, 0x04000003, 0x4803c857, 0x48026a12, - 0x59340002, 0x80180580, 0x04000003, 0x481bc857, - 0x481a6802, 0x80000580, 0x1c01f000, 0x4803c856, - 0x82000540, 0x00000001, 0x0401f7fc, 0x4947c857, - 0x83440480, 0x00000800, 0x04021011, 0x83441400, - 0x0010aa00, 0x50080000, 0x80026d40, 0x0400000b, - 0x0401fbf2, 0x0402000a, 0x59a80005, 0x8c000502, - 0x04000004, 0x59340200, 0x8c00050e, 0x04000004, - 0x82000540, 0x00000001, 0x1c01f000, 0x80000580, - 0x0401f7fe, 0x5c000000, 0x4c000000, 0x4803c857, - 0x4947c857, 0x4d2c0000, 0x4d300000, 0x83440480, - 0x00000800, 0x04021024, 0x83441400, 0x0010aa00, - 0x50080000, 0x80026d40, 0x0400001b, 0x45781000, - 0x5934000d, 0x80025d40, 0x02020800, 0x00100843, - 0x59366011, 0x813261c0, 0x0400000e, 0x4c640000, - 0x5930c800, 0x59325808, 0x0201f800, 0x00108df4, - 0x02020800, 0x00100843, 0x0201f800, 0x000208b4, - 0x82666540, 0x00000000, 0x040207f6, 0x5c00c800, - 0x0201f800, 0x00104acf, 0x41365800, 0x0201f800, - 0x0010083b, 0x80000580, 0x5c026000, 0x5c025800, - 0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fb, - 0x4937c857, 0x4c580000, 0x59cc0001, 0x82000500, - 0x00ffffff, 0x48026802, 0x497a6c01, 0x497a6a01, - 0x59340200, 0x84000502, 0x48026a00, 0x0201f800, - 0x00104e0d, 0x04020017, 0x59340403, 0x82000580, - 0x000007fe, 0x04000005, 0x59a80026, 0x8c00050a, - 0x04020010, 0x0401f008, 0x59cc0408, 0x8c000518, - 0x0400000c, 0x59cc0009, 0x48035035, 0x59cc000a, - 0x48035036, 0x59cc0207, 0x80000540, 0x04020003, - 0x42000000, 0x00000001, 0x48038893, 0x4803501e, - 0x59cc0a09, 0x82040d00, 0x00000010, 0x59cc0408, - 0x82000500, 0x00000020, 0x04000002, 0x84040d40, - 0x5934000a, 0x82000500, 0xffffffee, 0x80040540, - 0x4802680a, 0x83cca400, 0x0000000b, 0x8334ac00, - 0x00000006, 0x4200b000, 0x00000002, 0x0201f800, - 0x0010a93e, 0x83cca400, 0x0000000d, 0x8334ac00, - 0x00000008, 0x4200b000, 0x00000002, 0x0201f800, - 0x0010a93e, 0x59cc0a18, 0x82040480, 0x00000800, - 0x0402100c, 0x82040480, 0x00000400, 0x04001004, - 0x42000800, 0x00000400, 0x0401f006, 0x82040480, - 0x00000200, 0x04001003, 0x42000800, 0x00000200, - 0x42001000, 0x0010b33f, 0x58080202, 0x80041480, - 0x04001002, 0x40000800, 0x48066a04, 0x59340403, - 0x82000580, 0x000007fe, 0x04020003, 0x59cc0a08, - 0x48066a04, 0x0201f800, 0x00104afd, 0x5c00b000, - 0x1c01f000, 0x4937c857, 0x59a80026, 0x8c000508, - 0x04000004, 0x84000556, 0x4803c857, 0x48035026, - 0x59cc0207, 0x4803c857, 0x48026a05, 0x59cc020a, - 0x4803c857, 0x48026c05, 0x59341200, 0x599c0818, - 0x5934180a, 0x4807c857, 0x480bc857, 0x480fc857, - 0x59cc2006, 0x82102500, 0xff000000, 0x82102580, - 0x02000000, 0x04000007, 0x8c00050e, 0x04000009, - 0x8c0c1d14, 0x04000003, 0x8c0c1d0e, 0x04000005, - 0x8c040d18, 0x04000003, 0x8408154a, 0x0401f002, - 0x8408150a, 0x8c000510, 0x04000009, 0x8c0c1d14, - 0x04000003, 0x8c0c1d10, 0x04000005, 0x8c040d18, - 0x04000003, 0x8408154e, 0x0401f002, 0x8408150e, - 0x8c000512, 0x04000009, 0x8c0c1d14, 0x04000003, - 0x8c0c1d12, 0x04000005, 0x8c040d18, 0x04000003, - 0x8408155c, 0x0401f002, 0x8408151c, 0x480a6a00, - 0x1c01f000, 0x4803c856, 0x4c5c0000, 0x4d2c0000, - 0x4c580000, 0x5934000d, 0x80025d40, 0x04000029, - 0x592c0003, 0x82000480, 0x00000008, 0x0400100b, - 0x412cb800, 0x592c0001, 0x80025d40, 0x040207f9, - 0x0201f800, 0x0010082a, 0x04000037, 0x492fc857, - 0x492cb801, 0x0401f020, 0x832c0c00, 0x00000004, - 0x4200b000, 0x00000008, 0x50040000, 0x82000580, - 0xffffffff, 0x04020006, 0x80041000, 0x50080000, - 0x82000580, 0xffffffff, 0x04000007, 0x82040c00, - 0x00000002, 0x8058b040, 0x040207f4, 0x0201f800, - 0x00100615, 0x45480800, 0x454c1000, 0x592c1803, - 0x800c1800, 0x480e5803, 0x480fc857, 0x0401f014, - 0x0201f800, 0x0010082a, 0x04000017, 0x492fc857, - 0x492e680d, 0x497a5802, 0x4a025803, 0x00000001, - 0x494a5804, 0x494e5805, 0x832c0c00, 0x00000006, - 0x4200b000, 0x0000000e, 0x46000800, 0xffffffff, - 0x80040800, 0x8058b040, 0x040207fc, 0x82000540, - 0x00000001, 0x5c00b000, 0x5c025800, 0x5c00b800, - 0x1c01f000, 0x80000580, 0x0401f7fb, 0x4803c856, - 0x4d3c0000, 0x4d2c0000, 0x5934000d, 0x80025d40, - 0x0400001f, 0x592c0002, 0x80000540, 0x0402001f, - 0x412e7800, 0x0401f8c8, 0x0402001c, 0x46000800, - 0xffffffff, 0x46001000, 0xffffffff, 0x4813c857, - 0x480fc857, 0x580c0003, 0x82000c80, 0x00000002, - 0x04021014, 0x480fc857, 0x400c0000, 0x812c0580, - 0x04020004, 0x580c0001, 0x4802680d, 0x0401f003, - 0x580c0001, 0x48002001, 0x400e5800, 0x0201f800, - 0x0010083a, 0x82000540, 0x00000001, 0x5c025800, - 0x5c027800, 0x1c01f000, 0x80000580, 0x0401f7fc, - 0x80000040, 0x48001803, 0x4803c857, 0x0401f7f6, - 0x0201f800, 0x00020087, 0x59300007, 0x8400054e, - 0x48026007, 0x592c1a04, 0x820c1d00, 0x000000ff, - 0x820c0580, 0x00000048, 0x04000013, 0x0201f000, - 0x000202b0, 0x8c000500, 0x02020800, 0x000200e6, - 0x4a026203, 0x00000002, 0x592c1a04, 0x820c1d00, - 0x000000ff, 0x820c0580, 0x00000018, 0x02000000, - 0x000202b0, 0x820c0580, 0x00000048, 0x02020000, - 0x000202b0, 0x42000800, 0x80000804, 0x0201f800, - 0x00106466, 0x0201f000, 0x000202b9, 0x4a025a06, - 0x00000008, 0x0201f000, 0x00020381, 0x4a025a06, - 0x00000029, 0x0201f000, 0x00020381, 0x4a025a06, - 0x0000002a, 0x0201f000, 0x00020381, 0x4a025a06, - 0x00000028, 0x0201f000, 0x00020381, 0x4943c857, - 0x4d440000, 0x4d340000, 0x4d2c0000, 0x4c580000, - 0x4200b000, 0x000007f0, 0x417a8800, 0x0201f800, - 0x00020267, 0x04020007, 0x8d3e7d06, 0x04000004, - 0x59340200, 0x8c00050e, 0x04020002, 0x0401f813, - 0x81468800, 0x8058b040, 0x040207f5, 0x83440480, - 0x00000800, 0x04021008, 0x8d3e7d02, 0x04000006, - 0x42028800, 0x000007f0, 0x4200b000, 0x00000010, - 0x0401f7eb, 0x5c00b000, 0x5c025800, 0x5c026800, - 0x5c028800, 0x1c01f000, 0x4d2c0000, 0x41783000, - 0x5936580f, 0x812e59c0, 0x04000029, 0x592c0204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000012, - 0x04000020, 0x8d3e7d00, 0x04000003, 0x0401f83c, - 0x0402001c, 0x592c2000, 0x497a5800, 0x801831c0, - 0x04020009, 0x59340010, 0x812c0580, 0x04020004, - 0x497a680f, 0x497a6810, 0x0401f008, 0x4812680f, - 0x0401f006, 0x48103000, 0x59340010, 0x812c0580, - 0x04020002, 0x481a6810, 0x4a025a04, 0x00000103, - 0x49425a06, 0x497a5c09, 0x0201f800, 0x00108f7d, - 0x0201f800, 0x00020381, 0x40125800, 0x0401f7da, - 0x412c3000, 0x592e5800, 0x0401f7d7, 0x5c025800, - 0x1c01f000, 0x4803c856, 0x41781800, 0x5934000f, - 0x80025d40, 0x04000010, 0x592c0005, 0x80200580, - 0x592c0000, 0x04000003, 0x412c1800, 0x0401f7f9, - 0x497a5800, 0x800c19c0, 0x04000008, 0x48001800, - 0x80000540, 0x04020004, 0x480e6810, 0x82000540, - 0x00000001, 0x1c01f000, 0x4802680f, 0x80000540, - 0x040207fd, 0x497a6810, 0x0401f7f9, 0x592c0008, - 0x81480580, 0x04020003, 0x592c0009, 0x814c0580, - 0x1c01f000, 0x4803c856, 0x4c580000, 0x413c1800, - 0x400c2000, 0x593c0002, 0x80000540, 0x04020018, - 0x4200b000, 0x00000008, 0x820c0c00, 0x00000004, - 0x50040000, 0x81480580, 0x04020005, 0x80041000, - 0x50080000, 0x814c0580, 0x0400000d, 0x82040c00, - 0x00000002, 0x8058b040, 0x040207f6, 0x400c2000, - 0x580c0001, 0x80001d40, 0x040207ee, 0x82000540, - 0x00000001, 0x5c00b000, 0x1c01f000, 0x80000580, - 0x0401f7fd, 0x4937c857, 0x4c580000, 0x4d2c0000, - 0x5934000d, 0x80025d40, 0x04020016, 0x0201f800, - 0x0010082a, 0x04000010, 0x492e680d, 0x4a025802, - 0x00000001, 0x497a5803, 0x832c0c00, 0x00000004, - 0x4200b000, 0x00000010, 0x46000800, 0xffffffff, - 0x80040800, 0x8058b040, 0x040207fc, 0x82000540, - 0x00000001, 0x5c025800, 0x5c00b000, 0x1c01f000, - 0x4d2c0000, 0x592e5801, 0x0201f800, 0x00100843, - 0x5c025800, 0x0401f7ea, 0x4d2c0000, 0x5936580d, - 0x812e59c0, 0x04000007, 0x4937c857, 0x497a680d, - 0x0201f800, 0x00100843, 0x82000540, 0x00000001, - 0x5c025800, 0x1c01f000, 0x59340405, 0x4937c857, - 0x4803c857, 0x8c000508, 0x1c01f000, 0x4803c856, - 0x0201f800, 0x00104e0d, 0x04000011, 0x59a80815, - 0x8c040d04, 0x0402000e, 0x59a80826, 0x8c040d06, - 0x0400000b, 0x83ac0400, 0x000007fe, 0x50000000, - 0x80026d40, 0x04000006, 0x0401f9a8, 0x04020004, - 0x59340200, 0x8400055a, 0x48026a00, 0x599c0017, - 0x8c000508, 0x04000015, 0x4200b000, 0x000007f0, - 0x417a8800, 0x0201f800, 0x00020267, 0x0402000c, - 0x0401f99a, 0x0402000a, 0x59a80010, 0x59340802, - 0x80040580, 0x82000500, 0x00ffff00, 0x04020004, - 0x59340200, 0x8400055a, 0x48026a00, 0x81468800, - 0x8058b040, 0x040207f0, 0x0401f885, 0x04000003, - 0x59a80836, 0x0401f006, 0x599c0017, 0x8c000508, - 0x04000007, 0x42000800, 0x000007d0, 0x42001000, - 0x001046c4, 0x0201f800, 0x00105da7, 0x1c01f000, - 0x4803c856, 0x4d300000, 0x4d340000, 0x4d440000, - 0x4d3c0000, 0x4c580000, 0x42001000, 0x001046c4, - 0x0201f800, 0x00105cc9, 0x59a80826, 0x8c040d06, - 0x04000015, 0x0401f86a, 0x04000013, 0x83ae6c00, - 0x000007fe, 0x51366800, 0x59340200, 0x8400051a, - 0x48026a00, 0x599c0017, 0x8c000508, 0x04000007, - 0x42000800, 0x000007d0, 0x42001000, 0x001046c4, - 0x0201f800, 0x00105da7, 0x0201f800, 0x00101bf0, - 0x0401f027, 0x4200b000, 0x000007f0, 0x80028d80, - 0x0201f800, 0x00020267, 0x0402001e, 0x59340200, - 0x8c00051a, 0x0400001b, 0x59368c03, 0x417a7800, - 0x42028000, 0x00000029, 0x41783000, 0x0201f800, - 0x0010a258, 0x59340200, 0x84000558, 0x8400051a, - 0x48026a00, 0x4937c857, 0x4a026c00, 0x00000707, - 0x42028000, 0x00000029, 0x0201f800, 0x001067f6, - 0x417a7800, 0x0201f800, 0x00106543, 0x417a6000, - 0x0201f800, 0x0010a0da, 0x0201f800, 0x00106982, - 0x81468800, 0x8058b040, 0x040207de, 0x5c00b000, - 0x5c027800, 0x5c028800, 0x5c026800, 0x5c026000, - 0x1c01f000, 0x4933c857, 0x59303809, 0x581c0200, - 0x8400051a, 0x48003a00, 0x1c01f000, 0x42026800, - 0x0010b320, 0x497a680e, 0x42028800, 0x000007ff, - 0x0201f800, 0x001040e4, 0x4937c857, 0x4a026c00, - 0x00000606, 0x4a026802, 0x00ffffff, 0x4a026a04, - 0x00000200, 0x4a026c04, 0x00000002, 0x1c01f000, - 0x59300009, 0x50000000, 0x4933c857, 0x4803c857, - 0x8c00050e, 0x1c01f000, 0x59300009, 0x50000000, - 0x8c00050a, 0x1c01f000, 0x4933c856, 0x0401f90f, - 0x04000006, 0x59340400, 0x82000d00, 0x000000ff, - 0x82041580, 0x00000005, 0x1c01f000, 0x4d340000, - 0x83ac0400, 0x000007fe, 0x50000000, 0x80026d40, - 0x04000003, 0x59340200, 0x8c00051a, 0x5c026800, - 0x1c01f000, 0x4937c857, 0x493fc857, 0x59340403, - 0x81ac0400, 0x50000000, 0x81340580, 0x02020800, - 0x00100615, 0x59341200, 0x813e79c0, 0x04000003, - 0x8408155e, 0x0401f002, 0x8408151e, 0x480a6a00, - 0x1c01f000, 0x4937c857, 0x0201f800, 0x00101eb0, - 0x04000006, 0x59a80835, 0x42001000, 0x0010475f, - 0x0201f800, 0x00105da7, 0x1c01f000, 0x4937c857, - 0x42001000, 0x0010475f, 0x0201f800, 0x00105cc9, - 0x59a81026, 0x84081512, 0x480b5026, 0x1c01f000, - 0x4c380000, 0x4c340000, 0x4c240000, 0x4c600000, - 0x4008c000, 0x83440480, 0x00000800, 0x04021045, - 0x80002d80, 0x41442000, 0x83447400, 0x0010aa00, - 0x4200b000, 0x000007f0, 0x83444c80, 0x000007f0, - 0x04001003, 0x4200b000, 0x00000010, 0x50380000, - 0x80000540, 0x0402001e, 0x41440000, 0x80100580, - 0x04020043, 0x40102800, 0x82104c80, 0x000007f0, - 0x04001015, 0x82104d80, 0x000007fc, 0x04020005, - 0x82604d80, 0x00fffffc, 0x0402002a, 0x0401f00e, - 0x82104d80, 0x000007fd, 0x04020005, 0x82604d80, - 0x00fffffd, 0x04020023, 0x0401f007, 0x82104d80, - 0x000007ff, 0x0402001f, 0x82604d80, 0x00ffffff, - 0x0402001c, 0x84142d5e, 0x0401f029, 0x40006800, - 0x58343002, 0x82183500, 0x00ffffff, 0x40180000, - 0x80600580, 0x04020019, 0x40100000, 0x81440580, - 0x0402000a, 0x40366800, 0x8c204508, 0x04000053, - 0x0401ff8a, 0x04020051, 0x4947c857, 0x42000000, - 0x0000001d, 0x0401f04e, 0x4947c857, 0x480bc857, - 0x4823c857, 0x42000000, 0x0000001a, 0x0401f048, - 0x4947c857, 0x4863c857, 0x4813c857, 0x42000000, - 0x00000019, 0x0401f042, 0x40100000, 0x81440580, - 0x04020007, 0x58343002, 0x4947c857, 0x481bc857, - 0x42000000, 0x0000001b, 0x0401f039, 0x80102000, - 0x80387000, 0x83444c80, 0x000007f0, 0x04001009, - 0x82104d80, 0x00000800, 0x0402000c, 0x42002000, - 0x000007f0, 0x42007000, 0x0010b1f0, 0x0401f007, - 0x82104d80, 0x000007f0, 0x04020004, 0x41782000, - 0x42007000, 0x0010aa00, 0x8058b040, 0x040207a4, - 0x801429c0, 0x04020007, 0x0201f800, 0x00100615, - 0x4947c857, 0x42000000, 0x0000000a, 0x0401f01c, - 0x4d2c0000, 0x4c180000, 0x40603000, 0x0401fc19, - 0x4947c857, 0x4937c857, 0x5c003000, 0x5c025800, - 0x040207f4, 0x497a6a12, 0x59a80026, 0x8c00050a, - 0x0402000d, 0x82600500, 0x00ffff00, 0x04000006, - 0x59a84810, 0x82244d00, 0x00ffff00, 0x80240580, - 0x04020005, 0x82600500, 0x000000ff, 0x800000d0, - 0x48026a12, 0x48626802, 0x80000580, 0x80000540, - 0x5c00c000, 0x5c004800, 0x5c006800, 0x5c007000, - 0x1c01f000, 0x5934000f, 0x5934140b, 0x80081040, - 0x04001002, 0x480a6c0b, 0x80000540, 0x02020800, - 0x00020275, 0x1c01f000, 0x4803c857, 0x4947c857, - 0x4c300000, 0x82006500, 0x00000030, 0x04000006, - 0x4c000000, 0x0201f800, 0x001091f3, 0x5c000000, - 0x0402000b, 0x8c00050e, 0x04000006, 0x0201f800, - 0x00020267, 0x04020006, 0x4937c857, 0x0401fc36, - 0x80000580, 0x5c006000, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fc, 0x4803c857, 0x4c580000, - 0x4d440000, 0x40001000, 0x80000d80, 0x4200b000, - 0x000007f0, 0x4c040000, 0x40068800, 0x4c080000, - 0x40080000, 0x0401ffdd, 0x5c001000, 0x5c000800, - 0x80040800, 0x8058b040, 0x040207f7, 0x5c028800, - 0x5c00b000, 0x1c01f000, 0x4c5c0000, 0x59340400, - 0x8200bd80, 0x00000606, 0x5c00b800, 0x1c01f000, - 0x4c5c0000, 0x59340400, 0x8200bd80, 0x00000404, - 0x5c00b800, 0x1c01f000, 0x4c5c0000, 0x59340400, - 0x8200bd80, 0x00000404, 0x04000003, 0x8200bd80, - 0x00000606, 0x5c00b800, 0x1c01f000, 0x4c5c0000, - 0x4c600000, 0x59340400, 0x8200bd00, 0x0000ff00, - 0x825cc580, 0x00000400, 0x04000003, 0x825cc580, - 0x00000600, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x4c5c0000, 0x59340400, 0x82000500, 0x000000ff, - 0x8200bd80, 0x00000003, 0x04000003, 0x8200bd80, - 0x00000005, 0x5c00b800, 0x1c01f000, 0x5c000000, - 0x4c000000, 0x4803c857, 0x4c5c0000, 0x59340400, - 0x82000500, 0x0000ff00, 0x8400b9c0, 0x805c0580, - 0x4937c857, 0x4803c857, 0x48026c00, 0x5c00b800, - 0x1c01f000, 0x4c040000, 0x4c080000, 0x592c0207, - 0x8c00050c, 0x0400000f, 0x592e8c06, 0x82000500, - 0x00000080, 0x84000548, 0x4d3c0000, 0x42027800, - 0x00001000, 0x0401ff8d, 0x5c027800, 0x82000540, - 0x00000001, 0x5c001000, 0x5c000800, 0x1c01f000, - 0x80000580, 0x0401f7fc, 0x592c040b, 0x82000500, - 0x0000e000, 0x82000580, 0x00006000, 0x04000019, - 0x836c0580, 0x00000003, 0x04000016, 0x836c0580, - 0x00000002, 0x04020106, 0x59a80026, 0x82000d00, - 0x00000038, 0x04020005, 0x59a80832, 0x800409c0, - 0x0400000c, 0x0401f0fe, 0x82000d00, 0x00000003, - 0x82040d80, 0x00000003, 0x040200f9, 0x82000d00, - 0x00000028, 0x04020003, 0x8c00050c, 0x040000f4, - 0x592c100a, 0x82080500, 0xff000000, 0x040200d2, - 0x59a80010, 0x80080580, 0x040000cc, 0x592c0c0b, - 0x82040d00, 0x0000e000, 0x82040480, 0x00008000, - 0x040210cc, 0x592e8c06, 0x83440480, 0x00000800, - 0x04001007, 0x83440580, 0x0000ffff, 0x040200b3, - 0x800409c0, 0x040200fe, 0x0401f0b0, 0x800409c0, - 0x040200fb, 0x41784000, 0x0401feaa, 0x040200e2, - 0x59342204, 0x592c000d, 0x80100480, 0x040010bc, - 0x42027000, 0x00000053, 0x592c2409, 0x82100500, - 0xffffff00, 0x040200aa, 0x4813c857, 0x592c000c, - 0x800001c0, 0x04000083, 0x82100580, 0x00000004, - 0x040000a0, 0x82100580, 0x00000051, 0x0400009d, - 0x82100580, 0x00000003, 0x04000016, 0x82100580, - 0x00000020, 0x0400004b, 0x82100580, 0x00000024, - 0x04000042, 0x82100580, 0x00000021, 0x04000042, - 0x82100580, 0x00000050, 0x04000037, 0x82100580, - 0x00000052, 0x04000031, 0x82100580, 0x00000005, - 0x0402006b, 0x42027000, 0x00000001, 0x0401f01b, - 0x42027000, 0x00000002, 0x59a8006f, 0x8c000502, - 0x04000016, 0x0401ff45, 0x04000014, 0x59340212, - 0x82000500, 0x0000ff00, 0x42001000, 0x00000010, - 0x0402000c, 0x59a80026, 0x8c000506, 0x0402006f, - 0x42001000, 0x00000008, 0x59340002, 0x82000500, - 0x00ff0000, 0x82000580, 0x00ff0000, 0x04000003, - 0x0401f9d6, 0x04020065, 0x0201f800, 0x00020892, - 0x04000081, 0x4a026406, 0x00000010, 0x49366009, - 0x42000800, 0x00000003, 0x83380580, 0x00000002, - 0x04000003, 0x42000800, 0x0000000b, 0x0201f800, - 0x001043c7, 0x0401f044, 0x42027000, 0x00000000, - 0x0401f003, 0x42027000, 0x00000004, 0x0401ff30, - 0x04020074, 0x0401f036, 0x42027000, 0x00000033, - 0x0401f006, 0x42027000, 0x00000005, 0x0401f003, - 0x42027000, 0x00000003, 0x0401ff1c, 0x04020069, - 0x59a8006f, 0x8c000502, 0x04000016, 0x0401ff0b, - 0x04000014, 0x59340212, 0x82000500, 0x0000ff00, - 0x42001000, 0x00000010, 0x0402000c, 0x59a80026, - 0x8c000506, 0x04020035, 0x42001000, 0x00000008, - 0x59340002, 0x82000500, 0x00ff0000, 0x82000580, - 0x00ff0000, 0x04000003, 0x0401f99c, 0x0402002b, - 0x0201f800, 0x00020892, 0x04000047, 0x4a026406, - 0x00000010, 0x49366009, 0x42000800, 0x00000005, - 0x83380580, 0x00000003, 0x04000003, 0x42000800, - 0x00000009, 0x0201f800, 0x001043c7, 0x0401f00a, - 0x82102580, 0x00000011, 0x04020030, 0x0201f800, - 0x00020892, 0x04000034, 0x4a026406, 0x00000010, - 0x49366009, 0x492e6008, 0x49325808, 0x813669c0, - 0x04000007, 0x592c0c0b, 0x8c040d18, 0x04000004, - 0x59340200, 0x84000514, 0x48026a00, 0x0201f800, - 0x000208d8, 0x80000580, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fd, 0x42001000, 0x0000000a, - 0x0401f018, 0x42001000, 0x00000010, 0x0401f015, - 0x42001000, 0x00000016, 0x0401f012, 0x42001000, - 0x00000017, 0x0401f00f, 0x42001000, 0x00000018, - 0x0401f00c, 0x42001000, 0x0000001b, 0x0401f009, - 0x42001000, 0x0000001e, 0x0401f006, 0x42001000, - 0x00000024, 0x0401f003, 0x42001000, 0x00000020, - 0x42000800, 0x00000019, 0x42028000, 0x00000031, - 0x0401f7df, 0x42000800, 0x00000003, 0x0401f003, - 0x42000800, 0x0000000a, 0x41781000, 0x0401f7f7, - 0x42000800, 0x00000009, 0x59341400, 0x0401f7f3, - 0x42028000, 0x00000008, 0x0401f005, 0x42000800, - 0x00000007, 0x416c1000, 0x0401f7ec, 0x41780800, - 0x41781000, 0x0401f7ca, 0x42028000, 0x00000000, - 0x0401f7fb, 0x82004d80, 0x0000001d, 0x02000800, - 0x00100615, 0x82004d80, 0x0000001a, 0x04020004, - 0x40101000, 0x40000800, 0x0401f7dc, 0x82004d80, - 0x0000001b, 0x04020003, 0x40181000, 0x0401f7fa, - 0x82004d80, 0x0000001c, 0x040007f7, 0x82004d80, - 0x00000019, 0x040007b5, 0x0401f7d6, 0x592e6008, - 0x0201f800, 0x001091e3, 0x040007b3, 0x59300c06, - 0x82040580, 0x00000011, 0x040207d6, 0x83440580, - 0x0000ffff, 0x04020005, 0x59326809, 0x813669c0, - 0x0400000e, 0x0401f7cf, 0x592c100a, 0x82081500, - 0x00ffffff, 0x41784000, 0x0401fd9e, 0x040207d6, - 0x59300009, 0x800001c0, 0x04000003, 0x81340580, - 0x040207c4, 0x49366009, 0x592c0c0b, 0x82041500, - 0x0000e000, 0x82080580, 0x00006000, 0x04000011, - 0x42000800, 0x00000100, 0x813669c0, 0x04000002, - 0x59340a04, 0x592c000d, 0x80040480, 0x040017a0, - 0x59300a03, 0x82040580, 0x00000007, 0x040207b1, - 0x492e6008, 0x42027000, 0x00000054, 0x0401f774, - 0x0201f800, 0x0010a6e6, 0x040007b4, 0x0401f7a9, - 0x492fc857, 0x592e6008, 0x4933c857, 0x0201f800, - 0x001091e3, 0x04000047, 0x59301406, 0x82080580, - 0x00000005, 0x04020061, 0x592c0207, 0x8c000500, - 0x04020085, 0x59a80021, 0x800001c0, 0x0402006a, - 0x59301203, 0x82080580, 0x00000007, 0x04020057, - 0x592e8c06, 0x83440480, 0x00000800, 0x04021032, - 0x41784000, 0x592c1009, 0x82081500, 0x00ffffff, - 0x0401fd60, 0x0402005f, 0x59300009, 0x800001c0, - 0x04000003, 0x81340580, 0x04020048, 0x4d300000, - 0x592e6013, 0x4933c857, 0x83300580, 0xffffffff, - 0x0400000d, 0x0201f800, 0x001091e3, 0x5c026000, - 0x04000029, 0x591c1406, 0x82080580, 0x00000006, - 0x04000046, 0x82080580, 0x00000011, 0x04000043, - 0x0401f002, 0x5c026000, 0x59a80010, 0x592c100a, - 0x82081500, 0x00ffffff, 0x80081580, 0x04020017, - 0x592c1009, 0x82081500, 0x00ffffff, 0x80081580, - 0x0400000f, 0x49366009, 0x492e6008, 0x42027000, - 0x00000092, 0x0201f800, 0x000208d8, 0x80000580, - 0x1c01f000, 0x42001000, 0x0000000a, 0x0401f00c, - 0x42001000, 0x00000010, 0x0401f009, 0x42001000, - 0x00000014, 0x0401f006, 0x42001000, 0x00000018, - 0x0401f003, 0x42001000, 0x0000003c, 0x492fc857, - 0x480bc857, 0x42000800, 0x00000019, 0x42028000, - 0x00000031, 0x82000540, 0x00000001, 0x0401f7e9, - 0x492fc857, 0x4803c857, 0x480bc857, 0x40000800, - 0x0401f7f7, 0x492fc857, 0x42000800, 0x0000000a, - 0x41781000, 0x0401f7f2, 0x4933c857, 0x59300406, - 0x4803c857, 0x59300203, 0x4803c857, 0x59300009, - 0x4803c857, 0x42028000, 0x00000008, 0x41780800, - 0x41781000, 0x0401f7e8, 0x42000800, 0x0000001e, - 0x0401f7f0, 0x42000800, 0x00000001, 0x0401f7ed, - 0x82004d80, 0x0000001d, 0x02000800, 0x00100615, - 0x82004d80, 0x0000001a, 0x04020003, 0x40101000, - 0x0401f7dc, 0x82004d80, 0x0000001b, 0x04020003, - 0x40181000, 0x0401f7d7, 0x82004d80, 0x0000001c, - 0x040007d4, 0x82004d80, 0x00000019, 0x040007d1, - 0x0401f7d5, 0x0201f800, 0x0010a6e6, 0x040207d7, - 0x42028000, 0x00000000, 0x0401f7dd, 0x5c000000, - 0x4c000000, 0x4803c857, 0x59302009, 0x801021c0, - 0x04000035, 0x58101400, 0x4813c857, 0x480bc857, - 0x82081d00, 0x000000ff, 0x59300c03, 0x82040580, - 0x00000008, 0x04000022, 0x82040580, 0x0000000a, - 0x04000017, 0x82040580, 0x0000000c, 0x04000010, - 0x82040580, 0x00000002, 0x04000019, 0x82040580, - 0x00000001, 0x04000012, 0x82040580, 0x00000003, - 0x0400000b, 0x82040580, 0x00000005, 0x04000004, - 0x82040580, 0x00000033, 0x04020017, 0x820c0580, - 0x00000009, 0x0400000d, 0x0401f013, 0x820c0580, - 0x00000005, 0x04000009, 0x0401f00f, 0x820c0580, - 0x0000000b, 0x04000005, 0x0401f00b, 0x820c0580, - 0x00000003, 0x04020008, 0x82081d00, 0xffffff00, - 0x840c01c0, 0x800c0540, 0x4807c857, 0x4803c857, - 0x48002400, 0x1c01f000, 0x599c0017, 0x8c00050a, - 0x04000003, 0x80000580, 0x1c01f000, 0x59a80026, - 0x82000500, 0x00000028, 0x04000008, 0x42028800, - 0x000007fd, 0x0201f800, 0x00020267, 0x04020003, - 0x5934000a, 0x8c000504, 0x1c01f000, 0x4d300000, - 0x5934000e, 0x80026540, 0x04000006, 0x0201f800, - 0x0010600e, 0x02000800, 0x001061e5, 0x497a680e, - 0x5c026000, 0x1c01f000, 0x4d440000, 0x4d340000, - 0x80000580, 0x40001800, 0x40028800, 0x82080580, - 0x00000008, 0x04020003, 0x42001800, 0x00000001, - 0x0201f800, 0x00020267, 0x0402000a, 0x0401fd4f, - 0x04020008, 0x800c19c0, 0x04000004, 0x59340405, - 0x8c000508, 0x04000003, 0x80081040, 0x04000009, - 0x81468800, 0x83440480, 0x00000800, 0x040017f1, - 0x80000580, 0x5c026800, 0x5c028800, 0x1c01f000, - 0x82000540, 0x00000001, 0x5c026800, 0x5c028800, - 0x1c01f000, 0x42000800, 0x00000001, 0x0401fb0e, - 0x04020034, 0x59a80026, 0x8c000508, 0x04020031, - 0x5934100a, 0x82081500, 0x0000e000, 0x42007000, - 0x0010b33f, 0x58380401, 0x8c000504, 0x0402001c, - 0x42000800, 0x00000001, 0x82080580, 0x00006000, - 0x04000024, 0x59341a04, 0x820c0480, 0x00000800, - 0x04001004, 0x42000800, 0x00000a00, 0x0401f009, - 0x820c0480, 0x00000400, 0x04001004, 0x42000800, - 0x00000500, 0x0401f003, 0x42000800, 0x00000200, - 0x82080580, 0x00002000, 0x04000002, 0x800408c2, - 0x82040d40, 0x00000001, 0x0401f00e, 0x42000800, - 0x00000008, 0x82080580, 0x00002000, 0x04020004, - 0x42000800, 0x00000004, 0x0401f006, 0x82080580, - 0x00000000, 0x04020003, 0x42000800, 0x00000002, - 0x48066c04, 0x1c01f000, 0x4a033020, 0x00000000, - 0x4a03b104, 0x80000000, 0x497b3026, 0x497b3027, - 0x497b3028, 0x497b3029, 0x497b302b, 0x497b3021, - 0x4a03b104, 0x60000001, 0x1c01f000, 0x599c0018, - 0x4803c856, 0x497b3024, 0x497b3025, 0x82000500, - 0x0000000f, 0x48033022, 0x04000008, 0x599c0216, - 0x82000500, 0x0000ffff, 0x04020003, 0x42000000, - 0x00000002, 0x48033023, 0x1c01f000, 0x0401fff0, - 0x4a03c826, 0x00000004, 0x599c0209, 0x80000540, - 0x0400001f, 0x599c0207, 0x80000540, 0x04000007, - 0x800000cc, 0x599c080d, 0x80040400, 0x4803b100, - 0x497bb102, 0x59d80101, 0x599c000d, 0x4803b100, - 0x599c000e, 0x4803b101, 0x599c0207, 0x80000540, - 0x04020002, 0x497bb102, 0x599c0a09, 0x82040540, - 0x00400000, 0x59980822, 0x4803b103, 0x4a03b109, - 0x00000004, 0x4a03b104, 0x10000001, 0x800409c0, - 0x04020004, 0x4a033020, 0x00000001, 0x1c01f000, - 0x4a033020, 0x00000002, 0x0401f7fd, 0x592c0204, - 0x492fc857, 0x80000540, 0x04000008, 0x42034000, - 0x0010b2a0, 0x59a1d81e, 0x80edd9c0, 0x02000800, - 0x00100615, 0x0401f003, 0x5931d821, 0x58ef400b, - 0x58ec0009, 0x800001c0, 0x08020000, 0x0201f800, - 0x00100615, 0x5998002b, 0x84000540, 0x4803302b, - 0x0201f000, 0x00020403, 0x42000000, 0x0010b654, - 0x0201f800, 0x0010a86e, 0x492fc857, 0x59980026, - 0x59980828, 0x80000000, 0x48033026, 0x800409c0, - 0x492f3028, 0x04000003, 0x492c0800, 0x0401f002, - 0x492f3029, 0x592c0001, 0x80000d40, 0x02020000, - 0x000202fb, 0x1c01f000, 0x59980026, 0x59980828, - 0x80000000, 0x48033026, 0x492fc857, 0x800409c0, - 0x492f3028, 0x04000003, 0x492c0800, 0x0401f002, - 0x492f3029, 0x592c0001, 0x80000d40, 0x02020800, - 0x000202fb, 0x0402d00e, 0x59980029, 0x80025d40, - 0x0400000f, 0x59980026, 0x80000040, 0x48033026, - 0x04020002, 0x48033028, 0x592c0000, 0x48033029, - 0x492fc857, 0x492fb107, 0x0400d7f4, 0x42000000, - 0x0010b654, 0x0201f800, 0x0010a86e, 0x0402e01d, - 0x59da5908, 0x496a5800, 0x412ed000, 0x815eb800, - 0x0400e7fc, 0x59c80000, 0x82000540, 0x00001200, - 0x48039000, 0x04006019, 0x59d8010a, 0x59d8090a, - 0x80040d80, 0x040207fd, 0x900001c0, 0x82000540, - 0x00000013, 0x4803c011, 0x5998002b, 0x84000500, - 0x4803302b, 0x59e00017, 0x8c000508, 0x04000003, - 0x4a03c017, 0x00000003, 0x4203e000, 0x30000001, - 0x59d80105, 0x82000500, 0x00018780, 0x02020000, - 0x00020482, 0x1c01f000, 0x5998002b, 0x84000540, - 0x4803302b, 0x0401f7f7, 0x5c000000, 0x4c000000, - 0x4803c857, 0x492fc857, 0x4943c857, 0x4807c857, - 0x4a025a04, 0x00000103, 0x49425a06, 0x48065a08, - 0x4a025c06, 0x0000ffff, 0x813261c0, 0x04000003, - 0x59300402, 0x48025c06, 0x832c0400, 0x00000009, - 0x04011000, 0x4803c840, 0x4a03c842, 0x0000000b, - 0x04011000, 0x1c01f000, 0x42000000, 0x0010b654, - 0x0201f800, 0x0010a86e, 0x0201f000, 0x00020464, - 0x59a80017, 0x82000c80, 0x0000000a, 0x02021800, - 0x00100615, 0x0c01f809, 0x4a038805, 0x000000f0, - 0x59c400a3, 0x82000500, 0x02870000, 0x02020800, - 0x00100615, 0x1c01f000, 0x00104c99, 0x00104c25, - 0x00104c40, 0x00104c69, 0x00104c8c, 0x00104cc6, - 0x00104cd8, 0x00104c40, 0x00104caa, 0x00104c24, - 0x1c01f000, 0x4a038808, 0x00000004, 0x0401f8f9, - 0x0201f800, 0x0010507b, 0x59c40805, 0x8c040d0e, - 0x04020013, 0x8c040d0a, 0x0402000b, 0x8c040d0c, - 0x04020006, 0x8c040d08, 0x0400000d, 0x4a035017, - 0x00000003, 0x0401f00a, 0x4a035017, 0x00000000, - 0x0401f007, 0x42000000, 0x0010b642, 0x0201f800, - 0x0010a86e, 0x4a035017, 0x00000002, 0x1c01f000, - 0x4a038808, 0x00000002, 0x0401f8de, 0x59c40805, - 0x8c040d08, 0x04020021, 0x8c040d0c, 0x0402001c, - 0x8c040d0e, 0x04020017, 0x82040500, 0x000000f0, - 0x0402001c, 0x0201f800, 0x0010507b, 0x4a038808, - 0x00000080, 0x59c40002, 0x8400050c, 0x48038802, - 0x0401f9d7, 0x4d3c0000, 0x42027800, 0x00000001, - 0x0201f800, 0x00109640, 0x5c027800, 0x4a038808, - 0x00000080, 0x4a035017, 0x00000009, 0x0401f009, - 0x4a035017, 0x00000001, 0x0401f006, 0x4a035017, - 0x00000000, 0x0401f003, 0x4a035017, 0x00000003, - 0x1c01f000, 0x0401f8b7, 0x4a038808, 0x00000080, - 0x59c40805, 0x8c040d0a, 0x0402001b, 0x8c040d0c, - 0x04020016, 0x8c040d0e, 0x04020011, 0x82040500, - 0x000000f0, 0x04020016, 0x59c40002, 0x8400050c, - 0x48038802, 0x0401f9b2, 0x4d3c0000, 0x42027800, - 0x00000001, 0x0201f800, 0x00109640, 0x5c027800, - 0x4a035017, 0x00000009, 0x0401f009, 0x4a035017, - 0x00000001, 0x0401f006, 0x4a035017, 0x00000000, - 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000, - 0x4a038808, 0x00000008, 0x59c40805, 0x8c040d0c, - 0x04020006, 0x8c040d0e, 0x04000006, 0x4a035017, - 0x00000001, 0x0401f003, 0x4a035017, 0x00000000, - 0x1c01f000, 0x0401f8d3, 0x59c40805, 0x8c040d0c, - 0x0402000d, 0x4c040000, 0x0401f882, 0x5c000800, - 0x8c040d0a, 0x04020006, 0x8c040d0e, 0x04000006, - 0x4a035017, 0x00000001, 0x0401f003, 0x4a035017, - 0x00000002, 0x1c01f000, 0x4a038808, 0x00000008, - 0x42001000, 0x00104d2c, 0x0201f800, 0x00105dbd, - 0x59c40805, 0x8c040d0a, 0x0402000d, 0x8c040d08, - 0x0402000b, 0x8c040d0c, 0x04020006, 0x8c040d0e, - 0x0400000d, 0x4a035017, 0x00000001, 0x0401f00a, - 0x4a035017, 0x00000000, 0x0401f007, 0x42000000, - 0x0010b642, 0x0201f800, 0x0010a86e, 0x4a035017, - 0x00000004, 0x1c01f000, 0x0401f8a6, 0x0401f859, - 0x59c40805, 0x8c040d0a, 0x0402000b, 0x8c040d0c, - 0x04020006, 0x8c040d0e, 0x04000009, 0x4a035017, - 0x00000001, 0x0401f006, 0x4a035017, 0x00000000, - 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000, - 0x4a038808, 0x00000004, 0x0401f846, 0x59c40805, - 0x8c040d0a, 0x04020010, 0x8c040d08, 0x0402000b, - 0x8c040d0c, 0x04020006, 0x8c040d0e, 0x0400000c, - 0x4a035017, 0x00000001, 0x0401f009, 0x4a035017, - 0x00000000, 0x0401f006, 0x4a035017, 0x00000003, - 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000, - 0x0401f91d, 0x02020800, 0x00100615, 0x59a80805, - 0x8c040d0c, 0x04000015, 0x84040d0c, 0x48075005, - 0x4a038805, 0x00000010, 0x0201f800, 0x001019a4, - 0x59c40005, 0x8c000508, 0x04000008, 0x4a038808, - 0x00000008, 0x4a035033, 0x00000001, 0x4202d800, - 0x00000001, 0x0401f01a, 0x59c40006, 0x84000548, - 0x48038806, 0x0401f016, 0x59a80017, 0x82000580, - 0x00000001, 0x0400000c, 0x59a80017, 0x82000580, - 0x00000005, 0x0402000c, 0x42000000, 0x0010b642, - 0x0201f800, 0x0010a86e, 0x4a035017, 0x00000008, - 0x0401f007, 0x42000000, 0x0010b642, 0x0201f800, - 0x0010a86e, 0x4a035017, 0x00000004, 0x1c01f000, - 0x4803c856, 0x4c040000, 0x4c080000, 0x42000800, - 0x00000064, 0x42001000, 0x00104d2c, 0x0201f800, - 0x00105db2, 0x5c001000, 0x5c000800, 0x1c01f000, - 0x4803c856, 0x4c040000, 0x0201f800, 0x0010698c, - 0x4df00000, 0x0201f800, 0x00106b71, 0x5c03e000, - 0x02000800, 0x00106982, 0x0401ffba, 0x5c000800, - 0x1c01f000, 0x4803c856, 0x4c040000, 0x4c080000, - 0x0201f800, 0x0010698c, 0x4df00000, 0x0201f800, - 0x00106b71, 0x5c03e000, 0x02000800, 0x00106982, - 0x59c40006, 0x84000500, 0x48038806, 0x0201f800, - 0x00106c32, 0x497b8880, 0x0201f800, 0x0010a7e7, - 0x0201f800, 0x0010a7f5, 0x0201f800, 0x00101886, - 0x4a03504c, 0x00000004, 0x4202d800, 0x00000004, - 0x4a038805, 0x00000001, 0x42001000, 0x00104d2c, - 0x0201f800, 0x00105dbd, 0x0201f800, 0x0010071a, - 0x0401f8bf, 0x04000006, 0x42006000, 0xfeffffff, - 0x41786800, 0x0201f800, 0x001040ad, 0x0201f800, - 0x0010048c, 0x42000000, 0x00000001, 0x0201f800, - 0x001015fa, 0x5c001000, 0x5c000800, 0x1c01f000, - 0x59c40008, 0x8c000508, 0x04020007, 0x4a038808, - 0x00000010, 0x4201d000, 0x00001388, 0x0201f800, - 0x00105dd2, 0x1c01f000, 0x4c040000, 0x59a80833, - 0x82040580, 0x00000000, 0x0400000b, 0x82040580, - 0x00000001, 0x0400000b, 0x82040580, 0x00000002, - 0x0400000b, 0x82040580, 0x00000003, 0x0400000b, - 0x0401f055, 0x4a035017, 0x00000000, 0x0401f009, - 0x4a035017, 0x00000004, 0x0401f006, 0x4a035017, - 0x00000001, 0x0401f003, 0x4a035017, 0x00000007, - 0x497b8880, 0x4a038893, 0x00000001, 0x41780000, - 0x0201f800, 0x00101670, 0x0201f800, 0x00106c32, - 0x836c0d80, 0x00000004, 0x04000008, 0x59c40006, - 0x82000500, 0xffffff0f, 0x82000540, 0x04000001, - 0x48038806, 0x0401f007, 0x59c40006, 0x82000500, - 0xffffff0f, 0x82000540, 0x04000000, 0x48038806, - 0x0401f873, 0x04020005, 0x59c40806, 0x82040d00, - 0xfbffff0f, 0x48078806, 0x59c40005, 0x8c000534, - 0x04020033, 0x42006000, 0xfc18ffff, 0x42006800, - 0x01000000, 0x0201f800, 0x001040ad, 0x0201f800, - 0x001019a4, 0x59c408a4, 0x82040d00, 0x0000000f, - 0x82040d80, 0x0000000c, 0x040208a9, 0x0401f85c, - 0x04000006, 0x42006000, 0xfeffffff, 0x41786800, - 0x0201f800, 0x001040ad, 0x836c0d80, 0x00000004, - 0x0400000f, 0x0401f85a, 0x04020008, 0x59940005, - 0x82000580, 0x00103f37, 0x04020004, 0x59940004, - 0x800001c0, 0x04020006, 0x59a8084d, 0x42001000, - 0x00104d39, 0x0201f800, 0x00105da7, 0x4a035033, - 0x00000004, 0x0401fe33, 0x0401f841, 0x04020008, - 0x59c408a4, 0x82040d00, 0x0000000f, 0x82040580, - 0x0000000c, 0x02020800, 0x00100615, 0x5c000800, - 0x1c01f000, 0x4803c856, 0x4c000000, 0x0201f800, - 0x00105de2, 0x4a035010, 0x00ffffff, 0x497b5032, - 0x59a8002a, 0x82000500, 0xffff0000, 0x4803502a, - 0x497b8880, 0x497b8893, 0x41780000, 0x0201f800, - 0x00101670, 0x59c40001, 0x82000500, 0xfffffcff, - 0x48038801, 0x42006000, 0xfc18ffff, 0x41786800, - 0x0201f800, 0x001040ad, 0x4a038808, 0x00000000, - 0x5c000000, 0x800001c0, 0x02020800, 0x00103f37, - 0x4a038805, 0x040000f0, 0x59c40006, 0x82000500, - 0xffffffcf, 0x82000540, 0x440000c1, 0x48038806, - 0x1c01f000, 0x4c5c0000, 0x59a8b832, 0x825cbd80, - 0x0000aaaa, 0x5c00b800, 0x1c01f000, 0x4c5c0000, - 0x599cb818, 0x825cbd00, 0x00000030, 0x825cbd80, - 0x00000000, 0x5c00b800, 0x1c01f000, 0x4c5c0000, - 0x599cb818, 0x825cbd00, 0x00000030, 0x825cbd80, - 0x00000010, 0x5c00b800, 0x1c01f000, 0x4c5c0000, - 0x599cb818, 0x825cbd00, 0x00000030, 0x825cbd80, - 0x00000020, 0x5c00b800, 0x1c01f000, 0x59a80005, - 0x4803c857, 0x82000d00, 0x00000013, 0x04000024, - 0x599c1017, 0x4d3c0000, 0x82000500, 0x00000011, - 0x04000006, 0x417a7800, 0x0201f800, 0x0010393e, - 0x0402000a, 0x0401f012, 0x42027800, 0x00000008, - 0x0201f800, 0x0010393e, 0x0400000d, 0x42003000, - 0x00000003, 0x0401f003, 0x42003000, 0x00000004, - 0x42028000, 0x0000000e, 0x0201f800, 0x0010a25b, - 0x599c1017, 0x8c08150a, 0x04020007, 0x42028000, - 0x00000004, 0x0201f800, 0x00101d90, 0x80000580, - 0x0401f80d, 0x5c027800, 0x0401f00a, 0x0201f800, - 0x0010393e, 0x04000007, 0x42028000, 0x0000000f, - 0x42003000, 0x00000001, 0x0201f800, 0x0010a25b, - 0x1c01f000, 0x59a80005, 0x04000004, 0x82000540, - 0x00000010, 0x0401f003, 0x82000500, 0xffffffef, - 0x48035005, 0x4803c857, 0x1c01f000, 0x4803c856, - 0x4c580000, 0x42000000, 0x0010b6ca, 0x0201f800, - 0x0010a86e, 0x42000800, 0x0010bef0, 0x59c40003, - 0x44000800, 0x59c40004, 0x48000801, 0x59c4000b, - 0x48000802, 0x59c4008e, 0x48000803, 0x59c4008f, - 0x48000804, 0x59c40090, 0x48000805, 0x59c40091, - 0x48000806, 0x59c40092, 0x48000807, 0x59c40093, - 0x48000808, 0x59c40099, 0x48000809, 0x59c4009e, - 0x4800080a, 0x59c400aa, 0x4800080b, 0x59c400af, - 0x4800080c, 0x59c400b2, 0x4800080d, 0x59c400b1, - 0x4800080e, 0x82040c00, 0x0000000f, 0x41c41800, - 0x4200b000, 0x00000030, 0x580c0050, 0x44000800, - 0x80040800, 0x800c1800, 0x8058b040, 0x040207fb, - 0x41c41800, 0x4200b000, 0x00000020, 0x580c0010, - 0x44000800, 0x80040800, 0x800c1800, 0x8058b040, - 0x040207fb, 0x497b8830, 0x4200b000, 0x00000040, - 0x59c40031, 0x44000800, 0x80040800, 0x8058b040, - 0x040207fc, 0x497b88ac, 0x4200b000, 0x00000010, - 0x59c400ad, 0x44000800, 0x80040800, 0x8058b040, - 0x040207fc, 0x59c41001, 0x4c080000, 0x8408150c, - 0x480b8801, 0x4a0370e4, 0x00000300, 0x4a0370e5, - 0xb0000000, 0x42000800, 0x00000800, 0x80040840, - 0x02000800, 0x00100615, 0x59b800e5, 0x8c000538, - 0x040207fb, 0x4a0370e4, 0x00000200, 0x42006000, - 0xffffffff, 0x42006800, 0x80000000, 0x0201f800, - 0x001040ad, 0x4a038807, 0x00000001, 0x497b8807, - 0x4a038808, 0x00000010, 0x42006000, 0xfcf8ffff, - 0x42006800, 0x01000000, 0x0201f800, 0x001040ad, - 0x5c001000, 0x480b8801, 0x42000800, 0x0010bef0, - 0x50040000, 0x48038803, 0x58040001, 0x48038804, - 0x58040002, 0x4803880b, 0x58040003, 0x4803888e, - 0x58040004, 0x4803888f, 0x58040005, 0x48038890, - 0x58040006, 0x48038891, 0x58040007, 0x48038892, - 0x58040008, 0x48038893, 0x58040009, 0x48038899, - 0x5804000a, 0x4803889e, 0x5804000b, 0x480388aa, - 0x5804000c, 0x480388af, 0x5804000d, 0x480388b2, - 0x5804000e, 0x480388b1, 0x82040c00, 0x0000000f, - 0x41c41800, 0x4200b000, 0x00000030, 0x50040000, - 0x48001850, 0x80040800, 0x800c1800, 0x8058b040, - 0x040207fb, 0x41c41800, 0x4200b000, 0x00000020, - 0x50040000, 0x48001810, 0x80040800, 0x800c1800, - 0x8058b040, 0x040207fb, 0x497b8830, 0x4200b000, - 0x00000040, 0x50040000, 0x48038831, 0x80040800, - 0x8058b040, 0x040207fc, 0x497b88ac, 0x4200b000, - 0x00000010, 0x50040000, 0x480388ad, 0x80040800, - 0x8058b040, 0x040207fc, 0x497b8880, 0x41780000, - 0x0201f800, 0x00101670, 0x59c408a4, 0x82040d00, - 0x0000000f, 0x82040580, 0x0000000c, 0x02020800, - 0x00100615, 0x4a038805, 0x04000000, 0x5c00b000, - 0x1c01f000, 0x4803c856, 0x4c580000, 0x4ce80000, - 0x42000000, 0x0010b643, 0x0201f800, 0x0010a86e, - 0x59c41008, 0x4c080000, 0x82080500, 0xffffff7f, - 0x48038808, 0x59c40004, 0x82000500, 0x00003e02, - 0x04000005, 0x4201d000, 0x00000014, 0x0201f800, - 0x00105dd2, 0x59c40006, 0x82000500, 0xffffff0f, - 0x48038806, 0x4a038805, 0x00000010, 0x4a038808, - 0x00000004, 0x4200b000, 0x00000065, 0x59c40005, - 0x8c000508, 0x04020012, 0x4201d000, 0x000003e8, - 0x0201f800, 0x00105dd2, 0x8058b040, 0x040207f8, - 0x0201f800, 0x00106c32, 0x4a038808, 0x00000008, - 0x4a035033, 0x00000001, 0x4202d800, 0x00000001, - 0x82000540, 0x00000001, 0x0401f030, 0x0201f800, - 0x00100b29, 0x42000000, 0x0010b6a7, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00100f42, 0x497b8880, - 0x59a8002a, 0x82000500, 0x0000ffff, 0x4c000000, - 0x0201f800, 0x00101670, 0x5c000000, 0x48038880, - 0x4a038808, 0x00000000, 0x4200b000, 0x00000065, - 0x4a038805, 0x000000f0, 0x0201f800, 0x001019a4, - 0x42000800, 0x000000f0, 0x59c40005, 0x80040d00, - 0x04000008, 0x4201d000, 0x000003e8, 0x0201f800, - 0x00105dd2, 0x8058b040, 0x040207f2, 0x0401f7d1, - 0x59c40006, 0x82000540, 0x000000f0, 0x48038806, - 0x59a8001e, 0x80000540, 0x04020002, 0x80000000, - 0x48038893, 0x80000580, 0x5c001000, 0x4df00000, - 0x0201f800, 0x001019ca, 0x5c03e000, 0x480b8808, - 0x5c01d000, 0x5c00b000, 0x1c01f000, 0x4803c856, - 0x4c580000, 0x4ce80000, 0x59c41008, 0x82080500, - 0xffffff7f, 0x48038808, 0x4c080000, 0x59c40004, - 0x82000500, 0x00003e02, 0x04000005, 0x4201d000, - 0x00000014, 0x0201f800, 0x00105dd2, 0x0201f800, - 0x00100b29, 0x42000000, 0x0010b6a8, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00100f42, 0x4a038808, - 0x00000002, 0x80000580, 0x48038880, 0x48038893, - 0x0201f800, 0x00101670, 0x4200b000, 0x00000384, - 0x4a038805, 0x000000f0, 0x0201f800, 0x001019a4, - 0x42000800, 0x000000f0, 0x59c40005, 0x80040d00, - 0x04000015, 0x82000500, 0x000000d0, 0x04020012, - 0x4201d000, 0x00000067, 0x0201f800, 0x00105dd2, - 0x8058b040, 0x040207ef, 0x0201f800, 0x00106c32, - 0x4a038808, 0x00000008, 0x4a035033, 0x00000001, - 0x4202d800, 0x00000001, 0x82000540, 0x00000001, - 0x0401f010, 0x497b8880, 0x59a8001e, 0x80000540, - 0x04020002, 0x80000000, 0x48038893, 0x59a8002a, - 0x82000500, 0x0000ffff, 0x4c000000, 0x0201f800, - 0x00101670, 0x5c000000, 0x48038880, 0x80000580, - 0x5c001000, 0x4df00000, 0x0201f800, 0x001019ca, - 0x5c03e000, 0x480b8808, 0x5c01d000, 0x5c00b000, - 0x1c01f000, 0x4803c856, 0x59c40004, 0x82000500, - 0x00003e02, 0x0400000a, 0x0201f800, 0x00106c32, - 0x4a038808, 0x00000008, 0x4a035033, 0x00000001, - 0x4202d800, 0x00000001, 0x0401f052, 0x0201f800, - 0x00100b29, 0x42000000, 0x0010b6a9, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00100f42, 0x59c40006, - 0x84000508, 0x48038806, 0x4a038805, 0x00000010, - 0x59a80805, 0x84040d4c, 0x48075005, 0x42000800, - 0x00000064, 0x42001000, 0x00104d2c, 0x0201f800, - 0x00105da7, 0x4a038808, 0x00000000, 0x497b8880, - 0x4a038805, 0x000000f0, 0x0201f800, 0x001019a4, - 0x42000800, 0x000000f0, 0x59c40005, 0x80040d00, - 0x0400000e, 0x82000500, 0x000000e0, 0x0402000b, - 0x4201d000, 0x000003e8, 0x0201f800, 0x00105dd2, - 0x0201f800, 0x00105c81, 0x59940004, 0x80000540, - 0x040207ec, 0x0401f023, 0x4c080000, 0x42001000, - 0x00104d39, 0x0201f800, 0x00105cc9, 0x42001000, - 0x00104d2c, 0x0201f800, 0x00105dbd, 0x5c001000, - 0x497b8880, 0x59a8001e, 0x80000540, 0x04020002, - 0x80000000, 0x48038893, 0x59a8002a, 0x82000500, - 0x0000ffff, 0x4c000000, 0x0201f800, 0x00101670, - 0x5c000000, 0x48038880, 0x59a80805, 0x84040d0c, - 0x48075005, 0x59c40006, 0x84000548, 0x48038806, - 0x0201f800, 0x001019ca, 0x4a038808, 0x00000080, - 0x1c01f000, 0x4803c856, 0x4d400000, 0x4d3c0000, - 0x0201f800, 0x00106c32, 0x0201f800, 0x0010a95a, - 0x04020024, 0x599c1017, 0x59a80805, 0x8c040d00, - 0x0402000c, 0x8c08151a, 0x0400001e, 0x84040d42, - 0x48075005, 0x42028000, 0x00000004, 0x42027800, - 0x00000008, 0x8c081508, 0x04020007, 0x0401f011, - 0x42028000, 0x00000004, 0x417a7800, 0x8c081508, - 0x0400000c, 0x4d400000, 0x42028000, 0x0000000e, - 0x42028800, 0x0000ffff, 0x0201f800, 0x0010a258, - 0x5c028000, 0x599c0817, 0x8c040d0a, 0x04020005, - 0x4943c857, 0x493fc857, 0x0201f800, 0x00101d90, - 0x497b8880, 0x4202d800, 0x00000001, 0x0401fcff, - 0x5c027800, 0x5c028000, 0x1c01f000, 0x0201f800, - 0x00100b29, 0x42000000, 0x0010b6aa, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00100f42, 0x42000000, - 0x00000001, 0x0201f800, 0x00101670, 0x4a038880, - 0x00000001, 0x0201f000, 0x001019ca, 0x4202e000, - 0x00000000, 0x4a033015, 0x00000001, 0x497b301d, - 0x497b3006, 0x4a03b004, 0x60000001, 0x59d80005, - 0x4a03b004, 0x90000001, 0x4a03a804, 0x60000001, - 0x59d40005, 0x4a03a804, 0x90000001, 0x0201f000, - 0x00105667, 0x4a03c825, 0x00000004, 0x4a03c827, - 0x00000004, 0x599c0409, 0x80000d40, 0x04000020, - 0x599c0407, 0x80000540, 0x04000007, 0x800000cc, - 0x599c100b, 0x80080400, 0x4803b000, 0x497bb002, - 0x59d80001, 0x599c000b, 0x4803b000, 0x599c000c, - 0x4803b001, 0x599c0407, 0x80000540, 0x04020002, - 0x497bb002, 0x599c0c09, 0x82040540, 0x00400000, - 0x4803b003, 0x4a03b009, 0x00000004, 0x4a03b004, - 0x10000001, 0x59e00803, 0x82040d00, 0xfffffeff, - 0x82040d40, 0x00008000, 0x4807c003, 0x599c040a, - 0x80000540, 0x04000020, 0x599c0408, 0x80000540, - 0x04000007, 0x800000cc, 0x599c100f, 0x80080400, - 0x4803a800, 0x497ba802, 0x59d40001, 0x599c000f, - 0x4803a800, 0x599c0010, 0x4803a801, 0x599c0408, - 0x80000540, 0x04020002, 0x497ba802, 0x599c0c0a, - 0x82040540, 0x00400000, 0x4803a803, 0x4a03a809, - 0x00000004, 0x4a03a804, 0x10000001, 0x59e00803, - 0x82040d00, 0xfffffbff, 0x82040d40, 0x00008000, - 0x4807c003, 0x800409c0, 0x04000007, 0x4202e000, - 0x00000001, 0x0200b800, 0x00020685, 0x0200f000, - 0x0002069a, 0x1c01f000, 0x0201f800, 0x00100615, - 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, - 0x59981005, 0x800811c0, 0x0400001e, 0x58080005, - 0x82000d00, 0x43018780, 0x02020000, 0x0010552a, - 0x8c000508, 0x04000015, 0x580a5808, 0x592c0204, - 0x497a5800, 0x497a5801, 0x82000500, 0x000000ff, - 0x82000c80, 0x0000004b, 0x0402100b, 0x0c01f80f, - 0x5c03e000, 0x83700580, 0x00000003, 0x040007e6, - 0x0200f800, 0x0002069a, 0x0200b000, 0x00020685, - 0x1c01f000, 0x0401f850, 0x5c03e000, 0x0401f7f9, - 0x0401f8ee, 0x0401f7fd, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105171, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x001051f9, 0x00105161, 0x00105161, 0x00105171, - 0x00105171, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x492fc857, 0x42000000, 0x0010b65d, - 0x0201f800, 0x0010a86e, 0x42000000, 0x00000400, - 0x0401f019, 0x492fc857, 0x42000000, 0x0010b65c, - 0x0201f800, 0x0010a86e, 0x42000000, 0x00001000, - 0x0401f011, 0x492fc857, 0x42000000, 0x0010b65b, - 0x0201f800, 0x0010a86e, 0x42000000, 0x00002000, - 0x0401f009, 0x492fc857, 0x42000000, 0x0010b65e, - 0x0201f800, 0x0010a86e, 0x42000000, 0x00000800, - 0x0401f001, 0x4803c857, 0x4202e000, 0x00000001, - 0x592c0c04, 0x82040d00, 0xffff80ff, 0x80040540, - 0x48025c04, 0x0201f000, 0x00020381, 0x592c0204, - 0x492fc857, 0x80000110, 0x040007db, 0x80000040, - 0x04000035, 0x48033002, 0x492f3003, 0x492f3004, - 0x4a033008, 0x001051c5, 0x4202e000, 0x00000003, - 0x1c01f000, 0x592c0204, 0x492fc857, 0x80000110, - 0x040007cd, 0x80000040, 0x04000043, 0x48033002, - 0x492f3003, 0x492f3004, 0x4a033008, 0x001051e1, - 0x4202e000, 0x00000003, 0x1c01f000, 0x492fc857, - 0x0201f800, 0x0010a95a, 0x02020000, 0x0002060c, - 0x492fc857, 0x592e8a06, 0x83440c80, 0x000007f0, - 0x0402100b, 0x83440400, 0x0010aa00, 0x50000000, - 0x80026d40, 0x04000006, 0x4937c857, 0x59340200, - 0x8c00050e, 0x02020000, 0x0002060c, 0x42028000, - 0x00000028, 0x41780800, 0x417a6000, 0x0201f800, - 0x00104bee, 0x0201f800, 0x00108f7d, 0x0201f000, - 0x00020381, 0x592c0a0a, 0x8c040d02, 0x04020016, - 0x59a80021, 0x492fc857, 0x80000540, 0x0402000f, - 0x592c0207, 0x80000540, 0x04000005, 0x0201f800, - 0x00104156, 0x04020004, 0x1c01f000, 0x42000000, - 0x00000000, 0x592c0a06, 0x48065c06, 0x48025a06, - 0x0201f000, 0x00020381, 0x42000000, 0x00000028, - 0x0401f7f9, 0x42000800, 0x00000009, 0x0201f000, - 0x001063a9, 0x592c0208, 0x492fc857, 0x82000c80, - 0x0000199a, 0x04021794, 0x592c0408, 0x80000540, - 0x04020791, 0x59a80821, 0x800409c0, 0x04020009, - 0x592c0207, 0x80000540, 0x0400078b, 0x497a5a06, - 0x0201f800, 0x001041b5, 0x04020004, 0x1c01f000, - 0x42000000, 0x00000028, 0x48025a06, 0x0201f000, - 0x00020381, 0x59980804, 0x59980002, 0x48065800, - 0x492c0801, 0x492f3004, 0x80000040, 0x48033002, - 0x04000002, 0x1c01f000, 0x599a5803, 0x59980008, - 0x4202e000, 0x00000001, 0x0801f000, 0x592e8a06, - 0x592c0406, 0x4803c856, 0x82000500, 0x000000ff, - 0x4200b800, 0x00000001, 0x82000d80, 0x00000001, - 0x04000015, 0x417a8800, 0x4200b800, 0x000007f0, - 0x82000d80, 0x00000002, 0x0400000f, 0x80000540, - 0x02020000, 0x00020381, 0x592e8a06, 0x0201f800, - 0x00020267, 0x02020000, 0x00020381, 0x592e9008, - 0x592e9809, 0x0201f800, 0x00104567, 0x0201f000, - 0x00020381, 0x59a80805, 0x84040d00, 0x48075005, - 0x0201f800, 0x00020267, 0x02000800, 0x0010467a, - 0x81468800, 0x805cb840, 0x040207fa, 0x0201f000, - 0x00020381, 0x592c0a08, 0x4807c857, 0x82040580, - 0x0000000e, 0x04000045, 0x82040580, 0x00000046, - 0x04000046, 0x82040580, 0x00000045, 0x04000020, - 0x82040580, 0x00000029, 0x04000010, 0x82040580, - 0x0000002a, 0x04000009, 0x82040580, 0x0000000f, - 0x04000200, 0x82040580, 0x0000002e, 0x040001fd, - 0x4807c856, 0x0401f1f6, 0x59a80805, 0x84040d04, - 0x48075005, 0x0401f1f7, 0x592e8a06, 0x0201f800, - 0x00020267, 0x040201f3, 0x59340200, 0x84000518, - 0x48026a00, 0x592e6009, 0x4933c857, 0x83300580, - 0xffffffff, 0x0402002a, 0x0401f1ea, 0x592c1407, - 0x480bc857, 0x0201f800, 0x001091d9, 0x411e6000, - 0x04020003, 0x4803c856, 0x0401f1dd, 0x592e3809, - 0x591c1414, 0x84081516, 0x84081554, 0x480a3c14, - 0x4a026403, 0x0000003a, 0x592c040b, 0x80000540, - 0x04000007, 0x4a026403, 0x0000003b, 0x592c020c, - 0x4802641a, 0x592c040c, 0x4802621a, 0x4a026203, - 0x00000001, 0x42000800, 0x80000040, 0x0201f800, - 0x00020855, 0x0401f1cb, 0x59a80068, 0x84000510, - 0x48035068, 0x0401f1c7, 0x592c1207, 0x8c081500, - 0x040201c4, 0x592e8a06, 0x592e6009, 0x0201f800, - 0x001091e3, 0x04020003, 0x4803c856, 0x0401f1b8, - 0x59300c06, 0x82040580, 0x00000004, 0x04000003, - 0x4803c856, 0x0401f1b2, 0x59300a03, 0x82040580, - 0x00000007, 0x04000003, 0x4803c856, 0x0401f1ac, - 0x59300c03, 0x82040580, 0x00000001, 0x04000025, - 0x82040580, 0x00000003, 0x0400001a, 0x82040580, - 0x00000006, 0x04000024, 0x82040580, 0x00000008, - 0x04000019, 0x82040580, 0x0000000a, 0x0400000a, - 0x82040580, 0x0000000c, 0x04000004, 0x82040580, - 0x0000002e, 0x0402001c, 0x42000800, 0x00000009, - 0x0401f017, 0x59326809, 0x0201f800, 0x0010484b, - 0x04020015, 0x42000800, 0x00000005, 0x0401f010, - 0x417a7800, 0x0201f800, 0x00101de2, 0x4a026406, - 0x00000001, 0x42000800, 0x00000003, 0x0401f008, - 0x417a7800, 0x0201f800, 0x00101de2, 0x4a026406, - 0x00000001, 0x42000800, 0x0000000b, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x0201f800, - 0x00106470, 0x0401f17b, 0x40000800, 0x58040000, - 0x80000540, 0x040207fd, 0x492c0800, 0x1c01f000, - 0x492fc857, 0x59300c06, 0x82040580, 0x00000006, - 0x04020094, 0x0201f800, 0x00104836, 0x04020005, - 0x59340200, 0x8c00051a, 0x02000000, 0x00020667, - 0x59340200, 0x8c00050e, 0x0400008a, 0x59300203, - 0x42027800, 0x00000001, 0x82000580, 0x00000007, - 0x02020000, 0x00020667, 0x4a026203, 0x00000002, - 0x0201f000, 0x00020667, 0x42028000, 0x00000002, - 0x4a026206, 0x00000014, 0x4d2c0000, 0x0201f800, - 0x00109fc0, 0x5c025800, 0x59300c06, 0x4807c857, - 0x82040580, 0x00000007, 0x04020063, 0x492fc857, - 0x4a025a06, 0x00000001, 0x0201f000, 0x00020381, - 0x592c240a, 0x492fc857, 0x4813c857, 0x8c10251c, - 0x04020016, 0x8c10251a, 0x04000003, 0x8c10250a, - 0x04000069, 0x59340a00, 0x8c040d0e, 0x04000003, - 0x8c10251e, 0x04000064, 0x0201f800, 0x00020892, - 0x0400006b, 0x592c240a, 0x49366009, 0x49325809, - 0x4a026406, 0x00000006, 0x4a026203, 0x00000007, - 0x0201f000, 0x00020663, 0x592c0a0c, 0x5934000f, - 0x41784000, 0x80001540, 0x0400006d, 0x58080204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000012, - 0x04020004, 0x5808020c, 0x80040580, 0x04000004, - 0x58080000, 0x40084000, 0x0401f7f3, 0x58080000, - 0x49781000, 0x802041c0, 0x04000006, 0x48004000, - 0x80000540, 0x04020007, 0x48226810, 0x0401f005, - 0x4802680f, 0x80000540, 0x04020002, 0x497a6810, - 0x4d2c0000, 0x400a5800, 0x4a025a06, 0x00000002, - 0x0201f800, 0x00020381, 0x5c025800, 0x0401f7bc, - 0x592c040a, 0x8c00051c, 0x04000016, 0x592c0206, - 0x82000580, 0x0000ffff, 0x04020012, 0x592e6009, - 0x83300580, 0xffffffff, 0x040007b1, 0x83300480, - 0x0010cfc0, 0x04001010, 0x59a8000b, 0x81300480, - 0x0402100d, 0x59300008, 0x800001c0, 0x04020005, - 0x59300203, 0x82000580, 0x00000007, 0x04000797, - 0x492fc857, 0x4a025a06, 0x00000029, 0x0201f000, - 0x00020381, 0x492fc857, 0x4a025a06, 0x00000008, - 0x0201f000, 0x00020381, 0x492fc857, 0x4a025a06, - 0x00000045, 0x0201f000, 0x00020381, 0x492fc857, - 0x4a025a06, 0x0000002a, 0x0201f000, 0x00020381, - 0x492fc857, 0x4a025a06, 0x00000028, 0x0201f000, - 0x00020381, 0x492fc857, 0x4a025a06, 0x00000006, - 0x0201f000, 0x00020381, 0x492fc857, 0x4a025a06, - 0x0000000e, 0x0201f000, 0x00020381, 0x59340010, - 0x492e6810, 0x492fc857, 0x80000d40, 0x04000003, - 0x492c0800, 0x1c01f000, 0x5934040b, 0x492e680f, - 0x492fc857, 0x4803c857, 0x80000540, 0x04020003, - 0x4a026a03, 0x00000001, 0x1c01f000, 0x59a8000e, - 0x81640480, 0x0402176e, 0x42026000, 0x0010cfc0, - 0x59300009, 0x81340580, 0x04020004, 0x59300202, - 0x80040580, 0x04000759, 0x83326400, 0x00000024, - 0x41580000, 0x81300480, 0x040017f6, 0x0401f760, - 0x492fc857, 0x592c0407, 0x82000c80, 0x0000199a, - 0x040215dd, 0x592c0204, 0x80000112, 0x040205ca, - 0x592e8a06, 0x0201f800, 0x00020267, 0x04020059, - 0x0201f800, 0x00104836, 0x04020059, 0x592e780a, - 0x493fc857, 0x8d3e7d3e, 0x04020007, 0x59a80021, - 0x80000540, 0x0402004f, 0x0201f800, 0x00104686, - 0x040005c9, 0x833c1d00, 0x0000001f, 0x040005c6, - 0x592c0207, 0x82000c80, 0x00001000, 0x040215c2, - 0x800000c2, 0x800008c4, 0x8005d400, 0x592e9008, - 0x592e9809, 0x5934080d, 0x800409c0, 0x0402002e, - 0x833c1d00, 0x0000001f, 0x81780040, 0x80000000, - 0x800c1902, 0x040217fe, 0x040205b3, 0x0c01f001, - 0x001053cd, 0x001053d0, 0x001053dd, 0x001053e0, - 0x001053e3, 0x0201f800, 0x00108dfb, 0x0401f01a, - 0x0201f800, 0x00104659, 0x04000027, 0x80e9d1c0, - 0x02020800, 0x00105ce7, 0x42028000, 0x00000005, - 0x417a9000, 0x417a9800, 0x0201f800, 0x00108e0b, - 0x0401f00d, 0x42027000, 0x0000004d, 0x0401f006, - 0x42027000, 0x0000004e, 0x0401f003, 0x42027000, - 0x00000052, 0x0201f800, 0x0010451d, 0x02020800, - 0x00108e3b, 0x04000010, 0x8d3e7d3e, 0x04020017, - 0x1c01f000, 0x58040002, 0x80000540, 0x04020007, - 0x4d3c0000, 0x40067800, 0x0201f800, 0x00104639, - 0x5c027800, 0x040207cb, 0x4a025a06, 0x00000030, - 0x0401f00d, 0x4a025a06, 0x0000002c, 0x0401f00a, - 0x4a025a06, 0x00000028, 0x0401f007, 0x4a025a06, - 0x00000029, 0x0401f004, 0x497a5c09, 0x4a025a06, - 0x00000000, 0x4a025a04, 0x00000103, 0x0201f000, - 0x00020381, 0x492fc857, 0x592c0204, 0x80000110, - 0x80000040, 0x04000002, 0x0401f55b, 0x592c0207, - 0x82000500, 0x000003ff, 0x48025a07, 0x8c000506, - 0x04000004, 0x82000500, 0x00000070, 0x04020004, - 0x59a80821, 0x800409c0, 0x04020018, 0x4a025a06, - 0x0000dead, 0x592c0408, 0x82000500, 0x0000f0ff, - 0x48025c08, 0x0201f800, 0x001041e4, 0x04020002, - 0x1c01f000, 0x49425a06, 0x8058b1c0, 0x04000009, - 0x0201f800, 0x00109328, 0x0401f80f, 0x44042800, - 0x82580580, 0x00000002, 0x04020002, 0x48082801, - 0x0201f000, 0x00020381, 0x42028000, 0x00000031, - 0x42000800, 0x00000001, 0x4200b000, 0x00000001, - 0x0401f7ed, 0x592c0408, 0x80000118, 0x832c2c00, - 0x00000009, 0x80142c00, 0x1c01f000, 0x492fc857, - 0x4a025a08, 0x00000006, 0x0201f000, 0x00020381, - 0x492fc857, 0x4a025a08, 0x00000001, 0x0201f000, - 0x00020381, 0x492fc857, 0x592c040a, 0x82000500, - 0x00000003, 0x04000020, 0x0201f800, 0x00020892, - 0x04000021, 0x592c0204, 0x492e6008, 0x82000500, - 0x000000ff, 0x82000580, 0x00000045, 0x0400000e, - 0x592c000b, 0x0201f800, 0x001059b9, 0x02000800, - 0x00020267, 0x04020018, 0x42027000, 0x00000041, - 0x49366009, 0x4a026406, 0x00000001, 0x0201f000, - 0x000208d8, 0x59300015, 0x8400055e, 0x48026015, - 0x42026800, 0x0010b320, 0x42027000, 0x00000040, - 0x0401f7f4, 0x4a025a06, 0x00000101, 0x0201f000, - 0x00020381, 0x4a025a06, 0x0000002c, 0x0201f000, - 0x00020381, 0x4a025a06, 0x00000028, 0x0201f800, - 0x00020381, 0x0201f000, 0x000208b4, 0x492fc857, - 0x0201f800, 0x0010601a, 0x0400000b, 0x592c0204, - 0x80000110, 0x80000040, 0x040204e7, 0x592c0c06, - 0x800409c0, 0x04000009, 0x42000000, 0x00000102, - 0x0401f003, 0x42000000, 0x00000104, 0x48025a06, - 0x0201f000, 0x00020381, 0x592c0c07, 0x800409c0, - 0x04000024, 0x82040480, 0x00000005, 0x04021021, - 0x4c040000, 0x80040800, 0x0201f800, 0x0010603f, - 0x5c001000, 0x04020018, 0x832c0400, 0x00000008, - 0x4000a000, 0x0201f800, 0x00106068, 0x04020012, - 0x592c1207, 0x82cc0580, 0x0010b30a, 0x04020009, - 0x58c80c0b, 0x84040d00, 0x84040d02, 0x8c081500, - 0x04000002, 0x84040d5e, 0x4805940b, 0x0401f001, - 0x42000000, 0x00000000, 0x48025a06, 0x0201f000, - 0x00020381, 0x42000000, 0x00000103, 0x0401f7fb, - 0x42000000, 0x00000102, 0x0401f7f8, 0x492fc857, - 0x592e7c06, 0x833c0500, 0xfffffffe, 0x04020043, - 0x592c4007, 0x42026000, 0x0010cfc0, 0x41581800, - 0x400c0000, 0x81300480, 0x04021023, 0x59300203, - 0x82000580, 0x00000000, 0x04000007, 0x59300008, - 0x80000d40, 0x04000004, 0x58040005, 0x80200580, - 0x04000004, 0x83326400, 0x00000024, 0x0401f7f1, - 0x58040204, 0x82000500, 0x000000ff, 0x82000d80, - 0x00000053, 0x04000007, 0x82000d80, 0x00000048, - 0x04000004, 0x82000580, 0x00000018, 0x04020023, - 0x4d2c0000, 0x0201f800, 0x00108997, 0x5c025800, - 0x0400001e, 0x4a025a06, 0x00000000, 0x0201f000, - 0x00020381, 0x592e8a06, 0x83440480, 0x000007f0, - 0x04021016, 0x83440400, 0x0010aa00, 0x50000000, - 0x80026d40, 0x04000011, 0x4d2c0000, 0x0201f800, - 0x00104619, 0x0400000c, 0x42028000, 0x00000005, - 0x592c0a08, 0x0201f800, 0x00104bee, 0x0201f800, - 0x00108f83, 0x0201f800, 0x00020381, 0x5c025800, - 0x0401f7e5, 0x5c025800, 0x4a025a06, 0x00000031, - 0x0201f000, 0x00020381, 0x492fc857, 0x4d2c0000, - 0x0201f800, 0x0010082a, 0x04000016, 0x492fc857, - 0x412f4000, 0x0201f800, 0x0010082a, 0x0400000e, - 0x492fc857, 0x412dd800, 0x0201f800, 0x00103941, - 0x0201f800, 0x0010394b, 0x49a1d80b, 0x5c025800, - 0x492dd80a, 0x0201f800, 0x00101fbb, 0x0201f000, - 0x00101fda, 0x41a25800, 0x0201f800, 0x0010083a, - 0x5c025800, 0x4a025a06, 0x00004005, 0x4a025c06, - 0x00000002, 0x0201f000, 0x00020381, 0x4807c857, - 0x485fc857, 0x4200b800, 0x00000001, 0x5c000800, - 0x4c5c0000, 0x0401f005, 0x4807c857, 0x485fc857, - 0x5c000800, 0x4d780000, 0x4803c857, 0x492fc857, - 0x8c00050e, 0x02020800, 0x0010060d, 0x4203e000, - 0x50000000, 0x4200b800, 0x00008003, 0x0201f000, - 0x0010061a, 0x592c0204, 0x80000110, 0x80000040, - 0x0402042d, 0x0201f800, 0x00104886, 0x04020002, - 0x1c01f000, 0x49425a06, 0x4806580d, 0x480a580e, - 0x4943c857, 0x4807c857, 0x480bc857, 0x0201f000, - 0x00020381, 0x592c0204, 0x80000110, 0x80000040, - 0x0402041d, 0x0201f800, 0x001049ec, 0x04020002, - 0x1c01f000, 0x49425a06, 0x48065811, 0x480a5812, - 0x0201f000, 0x00020381, 0x592c0204, 0x80000110, - 0x04000411, 0x80000040, 0x0402000c, 0x4202e000, - 0x00000001, 0x592c020a, 0x8c000504, 0x02000000, - 0x00020603, 0x592c0207, 0x82000c80, 0x00001001, - 0x04021415, 0x0401f009, 0x4202e000, 0x00000003, - 0x48033002, 0x492f3003, 0x492f3004, 0x4a033008, - 0x00020603, 0x1c01f000, 0x4202e000, 0x00000002, - 0x42000000, 0x0010bcd9, 0x50007000, 0x492c700b, - 0x4978700e, 0x4978700c, 0x592c0011, 0x592c0812, - 0x48007007, 0x48047008, 0x592c1013, 0x82080500, - 0xffff0000, 0x04000003, 0x0201f800, 0x00100615, - 0x4978700d, 0x82080480, 0x00000180, 0x4803c857, - 0x04001007, 0x4800700f, 0x4a007005, 0x00000180, - 0x4a007004, 0x00000060, 0x0401f005, 0x4978700f, - 0x48087005, 0x80081104, 0x48087004, 0x5838000a, - 0x48007003, 0x40381000, 0x0201f000, 0x001008a1, - 0x0201f800, 0x00100819, 0x04000003, 0x59980007, - 0x0801f000, 0x1c01f000, 0x40307000, 0x5838000b, - 0x80025d40, 0x0400001b, 0x58380002, 0x82000580, - 0x00000100, 0x0400001d, 0x4c380000, 0x592c0204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000012, - 0x0400000b, 0x592c0208, 0x8400054e, 0x48025a08, - 0x4a025a06, 0x00000002, 0x4a025a04, 0x00000103, - 0x0201f800, 0x00020381, 0x0401f005, 0x4a025a06, - 0x00000010, 0x0201f800, 0x00020381, 0x5c007000, - 0x4202e000, 0x00000001, 0x4a007002, 0x00000100, - 0x49787010, 0x1c01f000, 0x58380004, 0x82000480, - 0x00000003, 0x04000087, 0x58380010, 0x8c000500, - 0x04020019, 0x4200b000, 0x00000003, 0x832cac00, - 0x00000011, 0x5838000a, 0x5838100d, 0x8008a400, - 0x4c380000, 0x0201f800, 0x0010a93e, 0x5c007000, - 0x5838000d, 0x82000400, 0x00000003, 0x4800700d, - 0x4a007010, 0x00000001, 0x58380004, 0x82000480, - 0x00000003, 0x48007004, 0x82000580, 0x00000003, - 0x0400006c, 0x5838000e, 0x80001d40, 0x04020020, - 0x4c380000, 0x0201f800, 0x00100819, 0x5c007000, - 0x04000010, 0x4a025a04, 0x0000010a, 0x42001800, - 0x00000005, 0x480c700e, 0x5838000c, 0x80000540, - 0x04020002, 0x5838000b, 0x40000800, 0x492c0801, - 0x492c700c, 0x42000800, 0x0000000f, 0x0401f011, - 0x4202e000, 0x00000008, 0x4a033007, 0x001055f9, - 0x1c01f000, 0x4202e000, 0x00000002, 0x42000000, - 0x0010bcd9, 0x50007000, 0x0401f7e7, 0x583a580c, - 0x400c0000, 0x42000800, 0x00000014, 0x80040c80, - 0x58381004, 0x5838000f, 0x41783000, 0x80000540, - 0x04020005, 0x84183540, 0x82081480, 0x00000003, - 0x0400003c, 0x40080000, 0x80040480, 0x04001002, - 0x40080800, 0x4004b000, 0x412c0000, 0x800c0400, - 0x4000a800, 0x5838000a, 0x5838100d, 0x8008a400, - 0x4c080000, 0x4c040000, 0x4c0c0000, 0x4c380000, - 0x0201f800, 0x0010a93e, 0x5c007000, 0x5c001800, - 0x5c000800, 0x40040000, 0x58381004, 0x80080480, - 0x48007004, 0x82000580, 0x00000003, 0x04000002, - 0x84183500, 0x5c000000, 0x80041400, 0x82080480, - 0x00000060, 0x04020003, 0x84183542, 0x41781000, - 0x400c0000, 0x80041c00, 0x820c0480, 0x00000014, - 0x04020003, 0x84183544, 0x40001800, 0x40080800, - 0x4804700d, 0x480c700e, 0x40180000, 0x0c01f001, - 0x00105644, 0x00105648, 0x00105646, 0x00105644, - 0x001055e0, 0x00105648, 0x00105646, 0x00105644, - 0x0201f800, 0x00100615, 0x5838100f, 0x0401f739, - 0x5838080d, 0x82040400, 0x00000002, 0x5838100a, - 0x80080400, 0x50001000, 0x800811c0, 0x0402000f, - 0x4202e000, 0x00000001, 0x583a580b, 0x4978700b, - 0x49787010, 0x592c0204, 0x82000500, 0x000000ff, - 0x82000580, 0x00000012, 0x02000000, 0x0002063b, - 0x0201f000, 0x00020603, 0x5838000a, 0x80040c00, - 0x82381c00, 0x00000007, 0x54041800, 0x80040800, - 0x800c1800, 0x54041800, 0x0401f71a, 0x0201f800, - 0x00100819, 0x02000800, 0x00100615, 0x4a02580a, - 0x0010bc78, 0x42000800, 0x0010bcd9, 0x452c0800, - 0x497a580b, 0x497a580c, 0x497a580d, 0x497a580e, - 0x497a580f, 0x4a025809, 0x0010559a, 0x497a5810, - 0x4a025802, 0x00000100, 0x4a025801, 0x00000001, - 0x1c01f000, 0x59c80007, 0x8c000502, 0x04000071, - 0x835c2c80, 0x00000005, 0x02001000, 0x00105c5c, - 0x59c82817, 0x4817506e, 0x497b9005, 0x82140500, - 0x00e00000, 0x0402004f, 0x82140500, 0x000003ff, - 0x82001c00, 0x00000006, 0x41cc2000, 0x42003000, - 0x00006080, 0x820c0480, 0x00000040, 0x04001006, - 0x42001000, 0x00000040, 0x820c1c80, 0x00000040, - 0x0401f003, 0x400c1000, 0x41781800, 0x54182000, - 0x80102000, 0x80183000, 0x80081040, 0x040207fc, - 0x800c19c0, 0x04000005, 0x59c80005, 0x80000000, - 0x48039005, 0x0401f7ea, 0x82140500, 0x01f60000, - 0x04020029, 0x82140500, 0x0000f000, 0x0400000b, - 0x82000c80, 0x00002000, 0x0402100f, 0x4a039005, - 0x00000140, 0x82140500, 0x0e000000, 0x80000132, - 0x0c01f83e, 0x1c01f000, 0x59cc0400, 0x82000500, - 0x0000ff00, 0x82000580, 0x00008100, 0x040007f4, - 0x0401f01c, 0x4817c857, 0x82140500, 0x000003ff, - 0x04020007, 0x59cc0400, 0x82000500, 0x0000ff00, - 0x82000580, 0x00008100, 0x04020012, 0x42000000, - 0x0010b6bc, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x00105b32, 0x4803c856, 0x4a039005, 0x00000140, - 0x0401f020, 0x4817c857, 0x82140500, 0x00f60000, - 0x04020004, 0x0201f800, 0x00105b6e, 0x040207d2, - 0x0201f800, 0x00104e0d, 0x04000010, 0x59c400a4, - 0x4803c857, 0x82000500, 0x0000000f, 0x82000580, - 0x0000000a, 0x04020009, 0x497b5016, 0x59c400a3, - 0x82000540, 0x00080000, 0x480388a3, 0x82000500, - 0xfff7ffff, 0x480388a3, 0x4817c856, 0x0201f800, - 0x0010a79f, 0x4a039005, 0x00000140, 0x0401f842, - 0x4803c856, 0x1c01f000, 0x00105702, 0x00105a13, - 0x001056fa, 0x001056fa, 0x001056fa, 0x001056fa, - 0x001056fa, 0x001056fa, 0x4803c857, 0x42000000, - 0x0010b659, 0x0201f800, 0x0010a86e, 0x4a039005, - 0x00000140, 0x1c01f000, 0x59cc0400, 0x82000d00, - 0x0000ff00, 0x82041500, 0x0000f000, 0x840409c0, - 0x82140500, 0x000003ff, 0x800018c4, 0x8c142d14, - 0x04000005, 0x59cc0002, 0x82000500, 0x00000003, - 0x800c1c80, 0x480f5016, 0x82080580, 0x00002000, - 0x04020013, 0x836c0580, 0x00000001, 0x0402000e, - 0x59cc0006, 0x82000500, 0xff000000, 0x82000580, - 0x11000000, 0x02020800, 0x001006ba, 0x04020011, - 0x0201f800, 0x00103951, 0x0201f800, 0x00105c81, - 0x0401f00c, 0x0401f81f, 0x0401f00a, 0x82080580, - 0x00003000, 0x04020003, 0x0401fa40, 0x0401f005, - 0x82080580, 0x00008000, 0x04020002, 0x0401fb36, - 0x1c01f000, 0x4817c857, 0x42000000, 0x0010b658, - 0x0201f800, 0x0010a86e, 0x836c0580, 0x00000003, - 0x0402000b, 0x4c080000, 0x4c0c0000, 0x42001000, - 0x00008048, 0x40141800, 0x80142120, 0x0201f800, - 0x00103857, 0x5c001800, 0x5c001000, 0x1c01f000, - 0x59cc0002, 0x82000500, 0xff000000, 0x82001580, - 0x01000000, 0x04000006, 0x82001580, 0x23000000, - 0x02020800, 0x001006ba, 0x040201c9, 0x82040580, - 0x00000023, 0x04020055, 0x59cc0004, 0x4803c857, - 0x59cc0006, 0x82000500, 0xff000000, 0x59cc0801, - 0x82040d00, 0x00ffffff, 0x80040540, 0x4803c857, - 0x0401fbb2, 0x02000800, 0x001006ba, 0x040001b8, - 0x59300c06, 0x82040580, 0x00000010, 0x04000012, - 0x82040580, 0x00000011, 0x0400000f, 0x82040580, - 0x00000001, 0x0400000c, 0x82040580, 0x00000004, - 0x04000009, 0x82040580, 0x00000008, 0x04000006, - 0x82040580, 0x0000000a, 0x02020800, 0x001006ba, - 0x040201a3, 0x59300004, 0x82000500, 0x80010000, - 0x04000006, 0x0201f800, 0x00106cb4, 0x02020800, - 0x001006ba, 0x0402019a, 0x59cc0a04, 0x48066202, - 0x59a80016, 0x800001c0, 0x02000800, 0x001006ba, - 0x04000193, 0x59cc0006, 0x82000500, 0xffff0000, - 0x82000d80, 0x02000000, 0x04020005, 0x42027000, - 0x00000015, 0x0201f000, 0x000208d8, 0x82000d80, - 0x02140000, 0x040007fa, 0x82000d80, 0x02100000, - 0x040007f7, 0x82000d80, 0x02100000, 0x040007f4, - 0x82000d80, 0x01000000, 0x02020800, 0x001006ba, - 0x0402017b, 0x59cc0006, 0x82000500, 0x0000ffff, - 0x02020800, 0x001006ba, 0x04020175, 0x42027000, - 0x00000016, 0x0401f7e8, 0x82040580, 0x00000022, - 0x02020800, 0x001006ba, 0x0402016d, 0x59cc0004, - 0x4803c857, 0x59cc0006, 0x4803c857, 0x59cc0001, - 0x4803c857, 0x59a80016, 0x800001c0, 0x02000800, - 0x001006ba, 0x04000162, 0x59a80806, 0x8c040d14, - 0x04000011, 0x0401f97d, 0x0402000f, 0x0401f993, - 0x0400000d, 0x42027000, 0x0000004c, 0x59cc0001, - 0x82000500, 0x00ffffff, 0x0201f800, 0x00105c25, - 0x0400013e, 0x42028800, 0x0000ffff, 0x417a6800, - 0x0401f13a, 0x59cc0006, 0x82000500, 0xffff0000, - 0x82000d80, 0x03000000, 0x04020023, 0x59a80026, - 0x8c000508, 0x04000017, 0x8400054c, 0x48035026, - 0x59cc0800, 0x82040d00, 0x00ffffff, 0x48075010, - 0x497b8830, 0x84040d70, 0x48078832, 0x59c40802, - 0x84040d4c, 0x48078802, 0x59cc0007, 0x82000500, - 0x0000ffff, 0x48038893, 0x4803501e, 0x42000800, - 0x00000003, 0x59a81010, 0x0201f800, 0x001069af, - 0x59cc0006, 0x82000500, 0x0000ffff, 0x02020800, - 0x001006ba, 0x0402012a, 0x42027000, 0x00000017, - 0x0401f0e5, 0x82000d80, 0x04000000, 0x04020013, - 0x59cc0006, 0x82000500, 0x0000ffff, 0x02020800, - 0x001006ba, 0x0402011e, 0x0201f800, 0x00104e0d, - 0x04000004, 0x42027000, 0x0000001d, 0x0401f0d6, - 0x59a80026, 0x84000548, 0x48035026, 0x42027000, - 0x00000030, 0x0401f0d0, 0x82000d80, 0x05000000, - 0x0402000a, 0x59cc0006, 0x82000500, 0x0000ffff, - 0x02020800, 0x001006ba, 0x04020109, 0x42027000, - 0x00000018, 0x0401f0c4, 0x82000d80, 0x20100000, - 0x04020004, 0x42027000, 0x00000019, 0x0401f0be, - 0x82000d80, 0x21100000, 0x04020004, 0x42027000, - 0x0000001a, 0x0401f0b8, 0x82000d80, 0x52000000, - 0x0402000a, 0x59cc0006, 0x82000500, 0x0000ffff, - 0x02020800, 0x001006ba, 0x040200f1, 0x42027000, - 0x0000001b, 0x0401f0ac, 0x82000d80, 0x50000000, - 0x0402000a, 0x59cc0006, 0x82000500, 0x0000ffff, - 0x02020800, 0x001006ba, 0x040200e5, 0x42027000, - 0x0000001c, 0x0401f0a0, 0x82000d80, 0x13000000, - 0x04020004, 0x42027000, 0x00000034, 0x0401f09a, - 0x82000d80, 0x12000000, 0x0402000a, 0x59cc0006, - 0x82000500, 0x0000ffff, 0x02020800, 0x001006ba, - 0x040200d3, 0x42027000, 0x00000024, 0x0401f08e, - 0x82000d00, 0xff000000, 0x82040d80, 0x24000000, - 0x04020004, 0x42027000, 0x0000002d, 0x0401f086, - 0x82000d00, 0xff000000, 0x82040d80, 0x53000000, - 0x04020004, 0x42027000, 0x0000002a, 0x0401f07e, - 0x82000d80, 0x0f000000, 0x04020004, 0x42027000, - 0x00000020, 0x0401f078, 0x82000d80, 0x61040000, - 0x04020036, 0x83cc1400, 0x00000006, 0x80080800, - 0x50080000, 0x82000500, 0x0000ffff, 0x82000480, - 0x00000004, 0x4c580000, 0x8000b104, 0x8058b1c0, - 0x04000026, 0x4c100000, 0x50041800, 0x820c1500, - 0x03000000, 0x80081130, 0x42000000, 0x0010b615, - 0x82082580, 0x00000000, 0x04020004, 0x42000000, - 0x0010b612, 0x0401f00c, 0x82082580, 0x00000001, - 0x04020004, 0x42000000, 0x0010b613, 0x0401f006, - 0x82082580, 0x00000002, 0x04020003, 0x42000000, - 0x0010b614, 0x0201f800, 0x0010a86e, 0x42001000, - 0x00008015, 0x820c2500, 0x0000ffff, 0x800c1920, - 0x0201f800, 0x00103857, 0x5c002000, 0x80040800, - 0x8058b040, 0x040207da, 0x5c00b000, 0x42027000, - 0x00000023, 0x0401f040, 0x82000d80, 0x60000000, - 0x04020004, 0x42027000, 0x0000003f, 0x0401f03a, - 0x82000d80, 0x54000000, 0x04020008, 0x0401fb36, - 0x02020800, 0x001006ba, 0x04020075, 0x42027000, - 0x00000046, 0x0401f030, 0x82000d80, 0x55000000, - 0x04020009, 0x0401fb54, 0x04020004, 0x42027000, - 0x00000041, 0x0401f028, 0x42027000, 0x00000042, - 0x0401f025, 0x82000d80, 0x78000000, 0x04020004, - 0x42027000, 0x00000045, 0x0401f01f, 0x82000d80, - 0x10000000, 0x04020004, 0x42027000, 0x0000004e, - 0x0401f019, 0x82000d80, 0x63000000, 0x04020004, - 0x42027000, 0x0000004a, 0x0401f013, 0x82000d00, - 0xff000000, 0x82040d80, 0x56000000, 0x04020004, - 0x42027000, 0x0000004f, 0x0401f00b, 0x82000d00, - 0xff000000, 0x82040d80, 0x57000000, 0x04020004, - 0x42027000, 0x00000050, 0x0401f003, 0x42027000, - 0x0000001d, 0x59cc3800, 0x821c3d00, 0x00ffffff, - 0x821c0580, 0x00fffffe, 0x59cc0001, 0x04020005, - 0x40003000, 0x42028800, 0x000007fe, 0x0401f005, - 0x0401f8da, 0x02020800, 0x001006ba, 0x04020034, - 0x0201f800, 0x00104401, 0x02020800, 0x001006ba, - 0x0402002f, 0x83380580, 0x00000046, 0x04020006, - 0x59a80010, 0x80180580, 0x02000800, 0x001006ba, - 0x04000027, 0x59340200, 0x8c000514, 0x0400000f, - 0x83380580, 0x00000030, 0x0400000c, 0x83380580, - 0x0000003f, 0x04000009, 0x83380580, 0x00000034, - 0x04000006, 0x83380580, 0x00000024, 0x04000003, - 0x42027000, 0x0000004c, 0x0201f800, 0x00020892, - 0x04000018, 0x49366009, 0x4a026406, 0x00000004, - 0x59cc0c04, 0x48066202, 0x83380580, 0x0000004c, - 0x04020009, 0x4a026406, 0x00000011, 0x813669c0, - 0x04020005, 0x59cc0001, 0x82000500, 0x00ffffff, - 0x4802601e, 0x0201f000, 0x000208d8, 0x59880053, - 0x4803c857, 0x80000000, 0x48031053, 0x1c01f000, - 0x42001000, 0x00008049, 0x59cc1806, 0x800c1930, - 0x0201f800, 0x00103857, 0x0201f800, 0x001076c9, - 0x02000800, 0x001006ba, 0x040007f1, 0x49366009, - 0x4a026406, 0x00000004, 0x59cc0c04, 0x48066202, - 0x4a026403, 0x00000009, 0x4a02641a, 0x00000009, - 0x4a02621a, 0x00002900, 0x4a026203, 0x00000001, - 0x0201f000, 0x00106470, 0x59a80026, 0x4803c857, - 0x8c000508, 0x04000010, 0x59cc0006, 0x82000500, - 0xff000000, 0x82000d80, 0x03000000, 0x0400000c, - 0x82000d80, 0x20000000, 0x04000009, 0x82000d80, - 0x05000000, 0x04000006, 0x82000d80, 0x21000000, - 0x04000003, 0x80000580, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fd, 0x59cc2006, 0x82102500, - 0xff000000, 0x9c1021c0, 0x0401f807, 0x820c1c00, - 0x0010b2df, 0x500c1800, 0x800c0500, 0x4803c857, - 0x1c01f000, 0x40100800, 0x41781800, 0x82040480, - 0x00000020, 0x04001004, 0x800c1800, 0x40000800, - 0x0401f7fb, 0x82040500, 0x0000000f, 0x82000400, - 0x0010a95f, 0x50000000, 0x8c040d08, 0x04000002, - 0x900001c0, 0x1c01f000, 0x4803c856, 0x0401fadd, - 0x0402000a, 0x0201f800, 0x00101eb0, 0x04020007, - 0x59cc0002, 0x82000500, 0xff000000, 0x82000d80, - 0x08000000, 0x04000802, 0x1c01f000, 0x4803c856, - 0x59cc0400, 0x82000d00, 0x0000ff00, 0x840409c0, - 0x82040580, 0x00000033, 0x0402001f, 0x0401f98f, - 0x04000038, 0x59cc0a04, 0x48066202, 0x59cc0006, - 0x4803c857, 0x82000500, 0xffff0000, 0x82000d80, - 0x02000000, 0x04020009, 0x59cc0006, 0x82000500, - 0x0000ffff, 0x0402002b, 0x42027000, 0x00000015, - 0x0201f000, 0x000208d8, 0x82000d80, 0x01000000, - 0x04020024, 0x59cc0006, 0x82000500, 0x0000ffff, - 0x04020020, 0x42027000, 0x00000016, 0x0201f000, - 0x000208d8, 0x82040580, 0x00000032, 0x04020019, - 0x59cc0006, 0x82000500, 0xffff0000, 0x82000d80, - 0x14000000, 0x04020013, 0x42027000, 0x00000038, - 0x59cc0001, 0x0401f810, 0x0402000e, 0x0201f800, - 0x001043fc, 0x0402000b, 0x0201f800, 0x00020892, - 0x04000008, 0x49366009, 0x4a026406, 0x00000004, - 0x59cc0c04, 0x48066202, 0x0201f000, 0x000208d8, - 0x1c01f000, 0x4803c857, 0x4c580000, 0x4c100000, - 0x4c380000, 0x4c340000, 0x82003500, 0x00ffffff, - 0x82181500, 0x00ff0000, 0x82081580, 0x00ff0000, - 0x04020016, 0x82181480, 0x00fffffc, 0x04001013, - 0x82181580, 0x00fffffd, 0x04020004, 0x42028800, - 0x000007fd, 0x0401f040, 0x82181580, 0x00fffffe, - 0x04020004, 0x42028800, 0x000007fe, 0x0401f03a, - 0x82181580, 0x00fffffc, 0x04020004, 0x42028800, - 0x000007fc, 0x0401f034, 0x41781000, 0x42002000, - 0x00000000, 0x4200b000, 0x000007f0, 0x41ac7000, - 0x50380000, 0x80006d40, 0x04020005, 0x800811c0, - 0x0402001e, 0x8410155e, 0x0401f01c, 0x58340212, - 0x82000500, 0x0000ff00, 0x04000011, 0x59a84010, - 0x82204500, 0x00ffff00, 0x82180500, 0x00ffff00, - 0x04000002, 0x80200580, 0x58340002, 0x0402000f, - 0x82000500, 0x000000ff, 0x82184500, 0x000000ff, - 0x80204580, 0x04020009, 0x0401f006, 0x58340002, - 0x82000500, 0x00ffffff, 0x80184580, 0x04020003, - 0x40128800, 0x0401f00c, 0x80102000, 0x80387000, - 0x8058b040, 0x040207db, 0x800811c0, 0x04020005, - 0x481bc857, 0x82000540, 0x00000001, 0x0401f003, - 0x840a8d1e, 0x80000580, 0x5c006800, 0x5c007000, - 0x5c002000, 0x5c00b000, 0x1c01f000, 0x59a80026, - 0x8c00050e, 0x04000003, 0x8c000502, 0x04000006, - 0x59cc0c00, 0x80040910, 0x82040500, 0x0000000f, - 0x0c01f002, 0x1c01f000, 0x00105a2e, 0x00105a2e, - 0x00105a2e, 0x00105b1d, 0x00105a2e, 0x00105a30, - 0x00105a48, 0x00105a4b, 0x00105a2e, 0x00105a2e, - 0x00105a2e, 0x00105a2e, 0x00105a2e, 0x00105a2e, - 0x00105a2e, 0x00105a2e, 0x4803c856, 0x1c01f000, - 0x0401f8de, 0x04000014, 0x82140500, 0x000003ff, - 0x800000c4, 0x82000480, 0x00000008, 0x0400100e, - 0x59cc0001, 0x59326809, 0x59340802, 0x80040580, - 0x82000500, 0x00ffffff, 0x04020007, 0x59cc0a04, - 0x48066202, 0x42027000, 0x00000046, 0x0201f000, - 0x000208d8, 0x59cc0004, 0x4803c857, 0x1c01f000, - 0x59cc0004, 0x4803c857, 0x1c01f000, 0x0401f8c3, - 0x04000016, 0x82140500, 0x000003ff, 0x800000c4, - 0x82000480, 0x0000000c, 0x04001010, 0x59cc0001, - 0x82000500, 0x00ffffff, 0x59326809, 0x59340802, - 0x82040d00, 0x00ffffff, 0x80040580, 0x04020007, - 0x59cc0a04, 0x48066202, 0x42027000, 0x00000045, - 0x0201f000, 0x000208d8, 0x59cc0004, 0x4803c857, - 0x1c01f000, 0x59cc0004, 0x4803c857, 0x59cc0000, - 0x82000500, 0xff000000, 0x59cc1001, 0x82081500, - 0x00ffffff, 0x80080540, 0x4803c857, 0x4817c857, - 0x0401f9d8, 0x02020800, 0x001006ba, 0x04020016, - 0x0201f800, 0x00101eb0, 0x02020800, 0x001006ba, - 0x04020011, 0x59cc0002, 0x82000500, 0xff000000, - 0x82000580, 0x00000000, 0x02020800, 0x001006ba, - 0x04020009, 0x82040500, 0x0000000f, 0x82000c80, - 0x00000006, 0x02021800, 0x001006ba, 0x04021002, - 0x0c01f003, 0x4803c856, 0x1c01f000, 0x00105a91, - 0x00105a93, 0x00105a91, 0x00105a91, 0x00105aec, - 0x00105afb, 0x4803c856, 0x1c01f000, 0x59a80016, - 0x800001c0, 0x02020800, 0x001006ba, 0x040207fa, - 0x59cc0802, 0x4807c856, 0x8c040d2e, 0x0402001d, - 0x0201f800, 0x001076c9, 0x02000800, 0x00100615, - 0x59cc0001, 0x0401ff18, 0x0402000d, 0x0201f800, - 0x00020267, 0x0402000a, 0x4a026406, 0x00000005, - 0x49366009, 0x59cc0804, 0x4806601c, 0x42027000, - 0x00000088, 0x0201f000, 0x000208d8, 0x4803c857, - 0x42028800, 0x0000ffff, 0x417a6800, 0x59cc0001, - 0x82000500, 0x00ffffff, 0x4802601e, 0x0401f7ef, - 0x59cc0001, 0x4803c857, 0x0401feff, 0x02020800, - 0x001006ba, 0x040207d4, 0x0201f800, 0x001043fc, - 0x02020800, 0x001006ba, 0x040207cf, 0x59cc0005, - 0x8c000500, 0x04020006, 0x59340200, 0x8c00050e, - 0x02020800, 0x001006ba, 0x040207c7, 0x0201f800, - 0x00104842, 0x04020013, 0x0401f840, 0x02000800, - 0x001006ba, 0x040007c0, 0x0201f800, 0x00020892, - 0x02000800, 0x001006ba, 0x040007bb, 0x49366009, - 0x4a026406, 0x00000002, 0x59cc0804, 0x4806601c, - 0x42027000, 0x00000088, 0x0201f000, 0x000208d8, - 0x0201f800, 0x00020892, 0x040007af, 0x49366009, - 0x4a026406, 0x00000004, 0x59cc0c04, 0x48066202, - 0x42027000, 0x00000001, 0x0201f000, 0x000208d8, - 0x59cc0802, 0x8c040d2e, 0x0400000b, 0x0401f81f, - 0x04000009, 0x0401f961, 0x04020007, 0x59cc0a04, - 0x48066202, 0x42027000, 0x00000089, 0x0201f000, - 0x000208d8, 0x4933c857, 0x1c01f000, 0x59cc0004, - 0x4803c857, 0x59cc0802, 0x8c040d2e, 0x0400000b, - 0x0401f80e, 0x04000009, 0x0401f950, 0x04020007, - 0x59cc0a04, 0x48066202, 0x42027000, 0x0000008a, - 0x0201f000, 0x000208d8, 0x4933c857, 0x1c01f000, - 0x59cc0a04, 0x0401f002, 0x59cc0c04, 0x59a8000e, - 0x59a81067, 0x80080400, 0x80040480, 0x04021008, - 0x40040000, 0x800000c4, 0x800408ca, 0x80040c00, - 0x82066400, 0x0010cfc0, 0x1c01f000, 0x80000580, - 0x0401f7fe, 0x59cc0802, 0x8c040d2e, 0x04020010, - 0x0401ffec, 0x0400000e, 0x59cc0001, 0x82000500, - 0x00ffffff, 0x59326809, 0x59340802, 0x82040d00, - 0x00ffffff, 0x80040580, 0x04020005, 0x42027000, - 0x00000051, 0x0201f000, 0x000208d8, 0x59cc0004, - 0x4803c857, 0x1c01f000, 0x4803c856, 0x42003000, - 0x00000105, 0x0401f001, 0x4803c856, 0x4c3c0000, - 0x41cc7800, 0x40142000, 0x0401f803, 0x5c007800, - 0x1c01f000, 0x4803c856, 0x4c580000, 0x583c0400, - 0x82000500, 0x0000f000, 0x82000580, 0x0000c000, - 0x04000024, 0x0201f800, 0x00020892, 0x04000021, - 0x4c180000, 0x583c0001, 0x0401fe6f, 0x0402001f, - 0x0201f800, 0x001043fc, 0x0402001c, 0x49366009, - 0x0201f800, 0x0010082a, 0x04000018, 0x492e6017, - 0x497a5800, 0x497a5a04, 0x48125c04, 0x832cac00, - 0x00000005, 0x4200b000, 0x00000007, 0x403ca000, - 0x0201f800, 0x0010a93e, 0x5c003000, 0x481a641a, - 0x4a026403, 0x0000003e, 0x4a026406, 0x00000001, - 0x4a026203, 0x00000001, 0x0201f800, 0x00106470, - 0x5c00b000, 0x1c01f000, 0x0201f800, 0x000208b4, - 0x5c003000, 0x0401f7fb, 0x4803c856, 0x59cc0400, - 0x82000d00, 0x0000ff00, 0x82040500, 0x0000f000, - 0x840409c0, 0x82000580, 0x00002000, 0x04020049, - 0x82040580, 0x00000022, 0x0402003a, 0x59c400a4, - 0x82000500, 0x0000000f, 0x82000c80, 0x00000007, - 0x04001004, 0x82000480, 0x0000000c, 0x0400103f, - 0x59cc0006, 0x82000500, 0xffff0000, 0x82000d80, - 0x04000000, 0x04000039, 0x82000d80, 0x60000000, - 0x04000036, 0x82000d80, 0x54000000, 0x04000033, - 0x82000d80, 0x03000000, 0x04020015, 0x59a80826, - 0x8c040d02, 0x0402002d, 0x8c040d08, 0x0402002b, - 0x0201f800, 0x0010473b, 0x0400002b, 0x59a8001d, - 0x800000d0, 0x59a80810, 0x82040d00, 0x000000ff, - 0x80040540, 0x59cc0800, 0x82040d00, 0x00ffffff, - 0x80040580, 0x0402001b, 0x0401f01c, 0x59c40802, - 0x8c040d0c, 0x04020017, 0x82000d80, 0x52000000, - 0x040007ec, 0x82000d80, 0x05000000, 0x040007e9, - 0x82000d80, 0x50000000, 0x040007e6, 0x0401f00d, - 0x82040580, 0x00000023, 0x0402000a, 0x0401ff57, - 0x04000008, 0x59300c03, 0x82040580, 0x00000002, - 0x04000006, 0x82040580, 0x00000051, 0x04000003, - 0x80000580, 0x0401f003, 0x82000540, 0x00000001, - 0x1c01f000, 0x59cc0006, 0x82000500, 0xffff0000, - 0x82000d80, 0x03000000, 0x04000004, 0x82000d80, - 0x52000000, 0x040207f3, 0x59a80026, 0x82000500, - 0x00000009, 0x82000580, 0x00000008, 0x040007ef, - 0x0401f7ec, 0x4803c856, 0x4c5c0000, 0x4c580000, - 0x59a80016, 0x82000580, 0x0000004c, 0x0402001f, - 0x59ccb807, 0x9c5cb9c0, 0x825cbd00, 0x00000007, - 0x8c5cbd00, 0x0400000a, 0x4200b000, 0x00000002, - 0x83a81c00, 0x00000002, 0x83cc1400, 0x0000000d, - 0x0201f800, 0x001082ff, 0x04020010, 0x8c5cbd02, - 0x0400000a, 0x4200b000, 0x00000002, 0x83a81c00, - 0x00000000, 0x83cc1400, 0x0000000f, 0x0201f800, - 0x001082ff, 0x04020005, 0x8c5cbd04, 0x04000003, - 0x82000540, 0x00000001, 0x5c00b000, 0x5c00b800, - 0x1c01f000, 0x4803c856, 0x4c5c0000, 0x4c580000, - 0x59a80016, 0x82000580, 0x0000004c, 0x0402001f, - 0x59ccb807, 0x9c5cb9c0, 0x825cbd00, 0x00000007, - 0x8c5cbd00, 0x0400000a, 0x4200b000, 0x00000002, - 0x83a81c00, 0x00000002, 0x83cc1400, 0x00000009, - 0x0201f800, 0x001082ff, 0x04020010, 0x8c5cbd02, - 0x0400000a, 0x4200b000, 0x00000002, 0x83a81c00, - 0x00000000, 0x83cc1400, 0x0000000b, 0x0201f800, - 0x001082ff, 0x04020005, 0x8c5cbd04, 0x04000003, - 0x82000540, 0x00000001, 0x5c00b000, 0x5c00b800, - 0x1c01f000, 0x4803c857, 0x4c580000, 0x40003000, - 0x42002000, 0x000007f0, 0x4200b000, 0x00000010, - 0x83ac7400, 0x000007f0, 0x50380000, 0x80026d40, - 0x04000006, 0x59340002, 0x82000500, 0x00ffffff, - 0x80180580, 0x04000010, 0x80102000, 0x80387000, - 0x8058b040, 0x040207f5, 0x82100480, 0x00000800, - 0x42002000, 0x00000000, 0x4200b000, 0x000007f0, - 0x41ac7000, 0x040217ed, 0x82000540, 0x00000001, - 0x0401f002, 0x40128800, 0x5c00b000, 0x1c01f000, - 0x59a80026, 0x8c00050e, 0x04000004, 0x8c000502, - 0x04000003, 0x80000580, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fd, 0x59300c06, 0x82040580, - 0x00000002, 0x04000006, 0x82040580, 0x00000005, - 0x04000003, 0x82000540, 0x00000001, 0x1c01f000, - 0x59c80000, 0x84000558, 0x84000512, 0x48039000, - 0x1c01f000, 0x4a03281a, 0x000003e8, 0x4a032802, - 0x0010cfc0, 0x4a032800, 0x00000000, 0x4a032808, - 0x00106d9f, 0x42000000, 0x00000005, 0x83947c00, - 0x00000009, 0x49787801, 0x4a007802, 0x00106d54, - 0x823c7c00, 0x00000003, 0x80000040, 0x040207fa, - 0x4a032819, 0xffff0000, 0x4201d000, 0x00000064, - 0x0401f97c, 0x4201d000, 0x000186a0, 0x0401f18b, - 0x00000000, 0x00000003, 0x00000006, 0x00000009, - 0x0000000c, 0x4d300000, 0x4d2c0000, 0x4d340000, - 0x4d400000, 0x4cfc0000, 0x4d380000, 0x4d3c0000, - 0x4d440000, 0x4d4c0000, 0x4d480000, 0x4c5c0000, - 0x4c600000, 0x4c640000, 0x4cc80000, 0x4ccc0000, - 0x0201f800, 0x000206af, 0x5c019800, 0x5c019000, - 0x5c00c800, 0x5c00c000, 0x5c00b800, 0x5c029000, - 0x5c029800, 0x5c028800, 0x5c027800, 0x5c027000, - 0x5c01f800, 0x5c028000, 0x5c026800, 0x5c025800, - 0x5c026000, 0x1c01f000, 0x59940004, 0x80000540, - 0x0402000a, 0x59940025, 0x80040400, 0x02001800, - 0x00100615, 0x48032804, 0x480b2805, 0x4a032803, - 0x0000000a, 0x80000580, 0x1c01f000, 0x5994001f, - 0x80000540, 0x0402000a, 0x59940025, 0x80040400, - 0x02001800, 0x00100615, 0x4803281f, 0x480b2820, - 0x4a03281e, 0x00000001, 0x80000580, 0x1c01f000, - 0x59940022, 0x80000540, 0x0402000a, 0x59940025, - 0x80040400, 0x02001800, 0x00100615, 0x48032822, - 0x480b2823, 0x4a032821, 0x0000000a, 0x80000580, - 0x1c01f000, 0x4c000000, 0x59940005, 0x4803c857, - 0x480bc857, 0x80080580, 0x04020003, 0x497b2804, - 0x497b2805, 0x5c000000, 0x1c01f000, 0x4c000000, - 0x59940020, 0x4803c857, 0x480bc857, 0x80080580, - 0x04020003, 0x497b281f, 0x497b2820, 0x5c000000, - 0x1c01f000, 0x4c000000, 0x59940023, 0x4803c857, - 0x480bc857, 0x80080580, 0x04020003, 0x497b2822, - 0x497b2823, 0x5c000000, 0x1c01f000, 0x4937c857, - 0x48ebc857, 0x59340203, 0x80e80480, 0x04001002, - 0x48ea6a03, 0x1c01f000, 0x5c03e000, 0x1c01f000, - 0x4d440000, 0x42007800, 0x00000010, 0x59968801, - 0x0201f800, 0x00020267, 0x04020012, 0x59341a03, - 0x800c1840, 0x0400100f, 0x59940027, 0x800c0480, - 0x04000003, 0x48026a03, 0x0402100a, 0x5934000f, - 0x497a6a03, 0x80000540, 0x04000006, 0x4c3c0000, - 0x5934140b, 0x0201f800, 0x00020275, 0x5c007800, - 0x81468800, 0x83440480, 0x00000800, 0x04021007, - 0x803c7840, 0x040207e7, 0x49472801, 0x5c028800, - 0x5c03e000, 0x1c01f000, 0x4a032800, 0x00000002, - 0x497b2801, 0x0401f7fa, 0x42007800, 0x00000010, - 0x59966002, 0x59300205, 0x80000d40, 0x04000006, - 0x59940027, 0x80040480, 0x48026205, 0x0400102d, - 0x0400002c, 0x59300206, 0x80000d40, 0x04000014, - 0x59b800e4, 0x8c000524, 0x04020011, 0x4a0370e4, - 0x00030000, 0x40000000, 0x59b800e4, 0x8c000524, - 0x04000004, 0x4a0370e4, 0x00020000, 0x0401f008, - 0x59940027, 0x80040480, 0x48026206, 0x4a0370e4, - 0x00020000, 0x0400101c, 0x0400001b, 0x83326400, - 0x00000024, 0x49332802, 0x41540000, 0x81300480, - 0x04021005, 0x803c7840, 0x040207db, 0x5c03e000, - 0x1c01f000, 0x59940026, 0x48032827, 0x4a032802, - 0x0010cfc0, 0x497b2826, 0x80000540, 0x0400000f, - 0x4a032800, 0x00000001, 0x5c03e000, 0x1c01f000, - 0x4c3c0000, 0x0201f800, 0x00108f92, 0x5c007800, - 0x0401f7d1, 0x4c3c0000, 0x0201f800, 0x00108b11, - 0x5c007800, 0x0401f7e2, 0x4a032800, 0x00000000, - 0x5c03e000, 0x1c01f000, 0x59a8086b, 0x8c040d30, - 0x04020029, 0x8c040d32, 0x0400000f, 0x59a80069, - 0x81640480, 0x04001019, 0x59a8000b, 0x81500580, - 0x04000005, 0x59a8006a, 0x59a81066, 0x80080580, - 0x04020012, 0x900411c0, 0x82081500, 0x00007000, - 0x0401f012, 0x82040500, 0x0000001f, 0x04000016, - 0x80040840, 0x82040500, 0x0000001f, 0x04000003, - 0x4807506b, 0x0401f010, 0x900401c0, 0x82000500, - 0x0000001f, 0x80040d40, 0x900401c0, 0x80040580, - 0x82001500, 0x00007000, 0x82040500, 0xffff8fff, - 0x80080540, 0x4803506b, 0x80081114, 0x0201f800, - 0x00100728, 0x1c01f000, 0x4a032807, 0x000007d0, - 0x4a032806, 0x0000000a, 0x1c01f000, 0x42000800, - 0x000007d0, 0x83180480, 0x00000005, 0x02021800, - 0x00100615, 0x83947c00, 0x00000009, 0x83180400, - 0x00105c7c, 0x50000000, 0x803c7c00, 0x48047801, - 0x4a007800, 0x0000000a, 0x1c01f000, 0x83180480, - 0x00000005, 0x02021800, 0x00100615, 0x83947c00, - 0x00000009, 0x83180400, 0x00105c7c, 0x50000000, - 0x803c7c00, 0x49787801, 0x1c01f000, 0x4807c857, - 0x480bc857, 0x59940025, 0x80040400, 0x02001800, - 0x00100615, 0x48032804, 0x480b2805, 0x4a032803, - 0x0000000a, 0x1c01f000, 0x4807c857, 0x480bc857, - 0x59940025, 0x80040400, 0x02001800, 0x00100615, - 0x4803281c, 0x480b281d, 0x4a03281b, 0x0000000a, - 0x1c01f000, 0x4c000000, 0x5994001d, 0x4803c857, - 0x480bc857, 0x80080580, 0x04020003, 0x4803281c, - 0x4803281d, 0x5c000000, 0x1c01f000, 0x4807c857, - 0x480bc857, 0x59940025, 0x80040400, 0x02001800, - 0x00100615, 0x48032822, 0x480b2823, 0x4a032821, - 0x0000000a, 0x1c01f000, 0x80e9d1c0, 0x0400000e, - 0x0401f832, 0x04025000, 0x4203e000, 0x80000000, - 0x40e81000, 0x41780800, 0x42000000, 0x00000064, - 0x0201f800, 0x001063ee, 0x59940024, 0x80080400, - 0x48032824, 0x1c01f000, 0x42001000, 0x00104d39, - 0x0401fee5, 0x42001000, 0x00104d2c, 0x0401ffd6, - 0x42001000, 0x00103f62, 0x0401fedf, 0x42001000, - 0x00103fe4, 0x0401fedc, 0x42001000, 0x00103f37, - 0x0401fed9, 0x42001000, 0x0010401b, 0x0401f6ea, - 0x4203e000, 0x70000000, 0x4203e000, 0xb0300000, - 0x40ebf800, 0x42000000, 0x0000003c, 0x04004004, - 0x80000040, 0x040207fe, 0x0401f007, 0x4203e000, - 0x70000000, 0x42000000, 0x0010b67d, 0x0201f800, - 0x0010a86e, 0x1c01f000, 0x4203e000, 0x80000000, - 0x4203e000, 0xb0400000, 0x40ebf800, 0x42000000, - 0x0000003c, 0x04005004, 0x80000040, 0x040207fe, - 0x0401f007, 0x4203e000, 0x80000000, 0x42000000, - 0x0010b67e, 0x0201f800, 0x0010a86e, 0x1c01f000, - 0x59a8000e, 0x82000480, 0x00000100, 0x599c0a02, - 0x800409c0, 0x04020002, 0x80040800, 0x80041480, - 0x04001002, 0x40000800, 0x48075067, 0x59a8100e, - 0x40040000, 0x800acc80, 0x4967500e, 0x49675069, - 0x59aaa80b, 0x41640800, 0x42001000, 0x00000024, - 0x0201f800, 0x001063cf, 0x8206a400, 0x0010cfc0, - 0x49535065, 0x4152b000, 0x42006000, 0x0010bc64, - 0x4a006004, 0x0000012c, 0x4a006005, 0xda10da10, - 0x4a006008, 0x00000011, 0x4a006009, 0x0010bc64, - 0x4a00600a, 0x00101108, 0x599c0014, 0x48006011, - 0x599c0015, 0x48006012, 0x42006000, 0x0010bc40, - 0x4a006203, 0x00000008, 0x4a006406, 0x00000006, - 0x4a006002, 0xffff0000, 0x4a006008, 0x0010bc64, - 0x4a006014, 0x0010bc64, 0x599c0014, 0x48006015, - 0x599c0015, 0x48006016, 0x599c0413, 0x48006017, - 0x49506018, 0x49546019, 0x59a80067, 0x4800601a, - 0x4a00601b, 0x0010b265, 0x4a00601c, 0x0010b266, - 0x4a00601d, 0x0010b26a, 0x42000000, 0xb0000000, - 0x42000800, 0x0010bc40, 0x0201f800, 0x00100bb2, - 0x1c01f000, 0x82000d00, 0x000000c0, 0x04000004, - 0x82040d80, 0x000000c0, 0x04020055, 0x82000d00, - 0x00002020, 0x59300414, 0x84000512, 0x82040d80, - 0x00002020, 0x0400000b, 0x8c000514, 0x0402000f, - 0x48026414, 0x813e79c0, 0x02020000, 0x00020804, - 0x42027000, 0x00000043, 0x0201f000, 0x000208d8, - 0x59326809, 0x59340a00, 0x8c040d0a, 0x040007f3, - 0x84000552, 0x0401f7f1, 0x84000514, 0x592c080d, - 0x48066015, 0x0401f7ef, 0x59326809, 0x59340a00, - 0x8c040d0a, 0x02000000, 0x00020817, 0x59300c14, - 0x84040d52, 0x48066414, 0x0201f000, 0x00020817, - 0x0201f800, 0x00020087, 0x813e79c0, 0x02020000, - 0x00020804, 0x0201f000, 0x00020825, 0x8c00051e, - 0x02000000, 0x00020831, 0x82000d00, 0x00002020, - 0x82040d80, 0x00002020, 0x04000014, 0x82000500, - 0x000000c0, 0x82000d80, 0x00000080, 0x04000008, - 0x813e79c0, 0x02020000, 0x00020804, 0x42027000, - 0x00000041, 0x0201f000, 0x000208d8, 0x813e79c0, - 0x02020000, 0x00020804, 0x42027000, 0x00000043, - 0x0201f000, 0x000208d8, 0x59326809, 0x59340a00, - 0x8c040d0a, 0x040007ea, 0x59300c14, 0x84040d52, - 0x48066414, 0x0401f7e6, 0x492fc857, 0x42000800, - 0x00000006, 0x0201f000, 0x0002082c, 0x492fc857, - 0x42000800, 0x00000004, 0x0201f000, 0x0002082c, - 0x4807c856, 0x59a80068, 0x800409c0, 0x04000003, - 0x80080540, 0x0401f002, 0x80080500, 0x48035068, - 0x1c01f000, 0x4a030800, 0x00000000, 0x4a030802, - 0x00000001, 0x497b0803, 0x497b0804, 0x1c01f000, - 0x59840002, 0x8c000500, 0x04000004, 0x84000500, - 0x4a030800, 0x00000001, 0x84000544, 0x84000506, - 0x48030802, 0x82000d00, 0x0fffffff, 0x42000000, - 0x90000000, 0x0201f800, 0x00100bde, 0x59a80069, - 0x82000480, 0x00000007, 0x48035069, 0x80000580, - 0x42000800, 0x0010b315, 0x48000800, 0x48000801, - 0x1c01f000, 0x59a80069, 0x82000400, 0x00000007, - 0x48035069, 0x1c01f000, 0x83640480, 0x00000008, - 0x0400101b, 0x58c80a03, 0x80000580, 0x82000400, - 0x00000008, 0x80040840, 0x040207fd, 0x815c0480, - 0x04001013, 0x4200b000, 0x00000007, 0x0201f800, - 0x00020892, 0x4a026203, 0x00000004, 0x4a026406, - 0x00000009, 0x4a026203, 0x00000004, 0x4a026007, - 0x00000101, 0x0401f809, 0x0401f880, 0x8058b040, - 0x040207f3, 0x80000580, 0x1c01f000, 0x82000540, - 0x00000001, 0x0401f7fd, 0x0201f800, 0x0010082a, - 0x492e6008, 0x58c80a03, 0x4a025a04, 0x0000002c, - 0x497a5800, 0x497a5801, 0x497a5c04, 0x497a5c06, - 0x497a5805, 0x4a025a08, 0x00000005, 0x4a025a07, - 0x00000002, 0x58c80201, 0x48025c04, 0x58c80202, - 0x48025c07, 0x58c80204, 0x48025c08, 0x4a02580d, - 0x0000ffff, 0x80040840, 0x0400000c, 0x412c2000, - 0x0201f800, 0x0010082a, 0x4a025a04, 0x0000000a, - 0x497a5c04, 0x48125800, 0x492c2001, 0x412c2000, - 0x80040840, 0x040207f7, 0x1c01f000, 0x4d7c0000, - 0x4202f800, 0x00000010, 0x4df00000, 0x4203e000, - 0x50000000, 0x59847803, 0x803c79c0, 0x0400001e, - 0x4c5c0000, 0x583cb808, 0x585c3408, 0x801831c0, - 0x0400000b, 0x0401f84a, 0x04000016, 0x42001000, - 0x0010b315, 0x0401f87f, 0x04000012, 0x0201f800, - 0x00100819, 0x0400000f, 0x492cb805, 0x585c0005, - 0x80000540, 0x02000800, 0x00100615, 0x0401f830, - 0x585c5408, 0x0401f80b, 0x5c00b800, 0x5c03e000, - 0x817ef840, 0x040207e1, 0x5c02f800, 0x1c01f000, - 0x5c00b800, 0x5c03e000, 0x5c02f800, 0x1c01f000, - 0x4803c856, 0x405c6000, 0x802851c0, 0x04000018, - 0x585c0204, 0x82000d00, 0x0000000f, 0x82040c00, - 0x0010110d, 0x50044000, 0x4c600000, 0x4c640000, - 0x4d040000, 0x4020c000, 0x40320800, 0x5984c804, - 0x4c280000, 0x0401f934, 0x5c005000, 0x40604000, - 0x41046000, 0x0201f800, 0x001010eb, 0x040207f6, - 0x5c020800, 0x5c00c800, 0x5c00c000, 0x58c80204, - 0x4800bc08, 0x0201f800, 0x00020087, 0x4a026007, - 0x00000101, 0x497a6009, 0x0401f055, 0x4803c856, - 0x59840003, 0x80026540, 0x04000003, 0x59300000, - 0x48030803, 0x1c01f000, 0x4803c856, 0x59840003, - 0x48026000, 0x49330803, 0x1c01f000, 0x58cc0805, - 0x40180000, 0x80040480, 0x0400100d, 0x82cc0580, - 0x0010b30a, 0x02020800, 0x00100615, 0x58c80205, - 0x80040480, 0x0400101d, 0x82000540, 0x00000001, - 0x1c01f000, 0x80003580, 0x0401f7fe, 0x82cc0580, - 0x0010b30a, 0x02020800, 0x00100615, 0x58c80400, - 0x8c000504, 0x040007f8, 0x58c8040b, 0x8c00051e, - 0x040007f5, 0x8c000500, 0x040207f3, 0x84000540, - 0x4801940b, 0x42000000, 0x0010b637, 0x0201f800, - 0x0010a86e, 0x42001000, 0x00008026, 0x0201f800, - 0x00103857, 0x0401f7e8, 0x58c8040b, 0x8c00051e, - 0x040007e2, 0x8c000502, 0x040207e0, 0x84000542, - 0x4801940b, 0x42000000, 0x0010b636, 0x0201f800, - 0x0010a86e, 0x42001000, 0x00008025, 0x42001800, - 0x00000000, 0x0201f800, 0x00103857, 0x0401f7d3, - 0x4803c856, 0x58080000, 0x42001800, 0x00000007, - 0x58080801, 0x80040480, 0x04020004, 0x400c0000, - 0x80000540, 0x0401f005, 0x04001003, 0x800c0480, - 0x0401f002, 0x80000080, 0x1c01f000, 0x4803c856, - 0x59300008, 0x80000d40, 0x02000800, 0x00100615, - 0x58040005, 0x80000540, 0x02000800, 0x00100615, - 0x59300007, 0x82000500, 0x00000101, 0x82000580, - 0x00000101, 0x02020800, 0x00100615, 0x42001000, - 0x0010b315, 0x58080801, 0x82040400, 0x0010b317, - 0x497a6414, 0x4a026015, 0x0000ffff, 0x45300000, - 0x80040800, 0x82040480, 0x00000008, 0x04001002, - 0x80000d80, 0x48041001, 0x82040400, 0x0010b317, - 0x45780000, 0x1c01f000, 0x4933c857, 0x59300808, - 0x800409c0, 0x02000800, 0x00100615, 0x4d2c0000, - 0x58065805, 0x812e59c0, 0x02020800, 0x0010083a, - 0x49780805, 0x40065800, 0x0201f800, 0x00100843, - 0x5c025800, 0x4d300000, 0x0201f800, 0x000208b4, - 0x5c026000, 0x1c01f000, 0x59300406, 0x82000580, - 0x00000009, 0x04020006, 0x59300007, 0x8c000510, - 0x04000003, 0x80000580, 0x1c01f000, 0x82000540, - 0x00000001, 0x1c01f000, 0x59840802, 0x8c040d04, - 0x1c01f000, 0x4803c856, 0x59840802, 0x84040d04, - 0x84040d40, 0x4a030800, 0x00000000, 0x48070802, - 0x82040d00, 0x0fffffff, 0x42000000, 0x90000000, - 0x0201f000, 0x00100bde, 0x4807c857, 0x4805980a, - 0x49799801, 0x49799803, 0x49799806, 0x49799807, - 0x49799808, 0x49799805, 0x49799809, 0x0401f8c8, - 0x0400000a, 0x0401f8ea, 0x04000008, 0x48359800, - 0x48359802, 0x48359806, 0x4a019804, 0x00000001, - 0x4a019807, 0x00000005, 0x1c01f000, 0x4807c857, - 0x58cc1007, 0x40040000, 0x80080480, 0x04021020, - 0x4c040000, 0x4c080000, 0x0401f8d9, 0x5c001000, - 0x5c000800, 0x0400001c, 0x58cc0006, 0x80006540, - 0x0402000b, 0x48359800, 0x48359802, 0x48359806, - 0x49799801, 0x49799803, 0x49786801, 0x49786800, - 0x49799804, 0x49799807, 0x0401f005, 0x48306801, - 0x48346000, 0x48359806, 0x49786800, 0x58cc0004, - 0x58cc1007, 0x80000000, 0x82081400, 0x00000005, - 0x48019804, 0x48099807, 0x0401f7df, 0x80000580, - 0x1c01f000, 0x82000540, 0x00000001, 0x1c01f000, - 0x480bc857, 0x4c500000, 0x4c540000, 0x4c580000, - 0x40083000, 0x58cc0801, 0x82040480, 0x00000005, - 0x02021800, 0x00100615, 0x82040400, 0x00106150, - 0x50000000, 0x58cca800, 0x8054ac00, 0x42001800, - 0x00000005, 0x40040000, 0x800c0480, 0x80082480, - 0x04021002, 0x40080000, 0x8000b0c2, 0x8058b400, - 0x5450a800, 0x8050a000, 0x8054a800, 0x8058b040, - 0x040207fc, 0x40001000, 0x58cc2805, 0x58cc0807, - 0x58cc2001, 0x80142c00, 0x80040c80, 0x80102400, - 0x48159805, 0x48059807, 0x48119801, 0x82100580, - 0x00000005, 0x0400000c, 0x48119801, 0x40080000, - 0x80181480, 0x40083000, 0x04000003, 0x040217d6, - 0x80000580, 0x5c00b000, 0x5c00a800, 0x5c00a000, - 0x1c01f000, 0x58cc0800, 0x800409c0, 0x02000800, - 0x00100615, 0x58040800, 0x48059800, 0x41782000, - 0x0401f7ee, 0x0401f812, 0x50600000, 0x81041c00, - 0x585c0204, 0x4803c857, 0x82000580, 0x0000002c, - 0x02020800, 0x00100615, 0x58040202, 0x800000e0, - 0x80640540, 0x48001802, 0x58040000, 0x48001800, - 0x58040001, 0x48001801, 0x1c01f000, 0x4807c856, - 0x58cc0005, 0x80000040, 0x02001800, 0x00100615, - 0x48019805, 0x58cc1003, 0x82080480, 0x00000005, - 0x02021800, 0x00100615, 0x82080400, 0x00106150, - 0x50000000, 0x58cc0802, 0x80040c00, 0x80081000, - 0x82080480, 0x00000005, 0x0402000f, 0x58cc2002, - 0x58100000, 0x80006d40, 0x04000009, 0x4c340000, - 0x0401f858, 0x5c006800, 0x49786801, 0x48359802, - 0x58cc0004, 0x80000040, 0x48019804, 0x49799803, - 0x0401f002, 0x48099803, 0x1c01f000, 0x4807c856, - 0x41781800, 0x58c80201, 0x80000540, 0x04000002, - 0x800c1800, 0x58c80c01, 0x80040c80, 0x0400100a, - 0x04000009, 0x800c1800, 0x58c80202, 0x80041480, - 0x04001005, 0x04000004, 0x800c1800, 0x40080800, - 0x0401f7fb, 0x480d9204, 0x400c0000, 0x42002000, - 0x00000001, 0x80000040, 0x04000007, 0x04001006, - 0x80102000, 0x82000480, 0x00000005, 0x04000002, - 0x040217fc, 0x48119203, 0x1c01f000, 0x4807c856, - 0x4d2c0000, 0x58cc000a, 0x80000540, 0x02000800, - 0x00100615, 0x82002400, 0x00000005, 0x0201f800, - 0x00100819, 0x04000012, 0x492d9809, 0x497a5800, - 0x497a5801, 0x0201f800, 0x00100819, 0x0400000c, - 0x58cc0009, 0x48025800, 0x497a5801, 0x492d9809, - 0x82102480, 0x00000005, 0x040217f7, 0x82000540, - 0x00000001, 0x5c025800, 0x1c01f000, 0x58cc0009, - 0x80025d40, 0x040007fc, 0x592c2000, 0x0201f800, - 0x0010083a, 0x40100000, 0x0401f7fa, 0x58cc0009, - 0x48cfc857, 0x80006d40, 0x04000005, 0x50340000, - 0x48019809, 0x49786800, 0x49786801, 0x1c01f000, - 0x4813c857, 0x58cc0009, 0x48002000, 0x48119809, - 0x1c01f000, 0x4807c856, 0x4d2c0000, 0x58cc0009, - 0x80025d40, 0x04000007, 0x592c0000, 0x4c000000, - 0x0201f800, 0x0010083a, 0x5c000000, 0x0401f7f9, - 0x5c025800, 0x1c01f000, 0x4807c856, 0x4d2c0000, - 0x58cc0002, 0x80025d40, 0x04000007, 0x592c0000, - 0x4c000000, 0x0201f800, 0x0010083a, 0x5c000000, - 0x0401f7f9, 0x49799800, 0x49799802, 0x49799801, - 0x49799803, 0x49799806, 0x49799807, 0x49799808, - 0x49799809, 0x4979980a, 0x5c025800, 0x1c01f000, - 0x00000003, 0x00000006, 0x00000009, 0x0000000c, - 0x0000000f, 0x00000012, 0x4803c856, 0x0401f857, - 0x4a00c204, 0x0000003c, 0x59301009, 0x82080580, - 0x0010b320, 0x04000013, 0x58080802, 0x82040d00, - 0x00ffffff, 0x58080403, 0x4804c005, 0x4800c406, - 0x4a00c207, 0x00000003, 0x59300811, 0x585c0404, - 0x4978c206, 0x4804c407, 0x80000540, 0x0400000d, - 0x58600206, 0x84000540, 0x4800c206, 0x0401f009, - 0x585c080a, 0x82040d00, 0x00ffffff, 0x4804c005, - 0x4a00c406, 0x000007ff, 0x4978c207, 0x0401f7ef, - 0x82603c00, 0x00000008, 0x58605404, 0x40282000, - 0x405c6000, 0x585c0a04, 0x82040d00, 0x0000000f, - 0x82040c00, 0x0010110d, 0x50044000, 0x80004d80, - 0x50200000, 0x80307400, 0x58380402, 0x8c244d00, - 0x04020003, 0x48003a00, 0x0401f003, 0x48003c00, - 0x801c3800, 0x80244800, 0x80102040, 0x04000006, - 0x0201f800, 0x001010eb, 0x02000800, 0x00100615, - 0x0401f7f0, 0x1c01f000, 0x4803c856, 0x4d340000, - 0x59300009, 0x80026d40, 0x02000800, 0x00100615, - 0x59340401, 0x80000540, 0x0400000e, 0x59840000, - 0x80000540, 0x0400000b, 0x836c0580, 0x00000003, - 0x04020008, 0x59341c03, 0x42002000, 0x00000004, - 0x42003000, 0x00000004, 0x0201f800, 0x001038c7, - 0x5c026800, 0x1c01f000, 0x4803c856, 0x80001580, - 0x58c80c01, 0x59300011, 0x80040c80, 0x48066011, - 0x58c80201, 0x80000540, 0x04000005, 0x80081000, - 0x80040c80, 0x04001007, 0x04000006, 0x58c80202, - 0x80081000, 0x80040c80, 0x04001002, 0x040207fd, - 0x4808bc08, 0x4808c404, 0x1c01f000, 0x4803c856, - 0x4a0370e5, 0x00020000, 0x59b800e5, 0x8c000524, - 0x040207fc, 0x4a0370e5, 0x00030000, 0x40000000, - 0x40000000, 0x59b800e5, 0x8c000524, 0x040207f5, - 0x5934000e, 0x80006d40, 0x04000010, 0x81300580, - 0x04020004, 0x58340000, 0x4802680e, 0x0401f00a, - 0x40347800, 0x58340000, 0x80006d40, 0x02000800, - 0x00100615, 0x81300580, 0x040207fa, 0x58340000, - 0x48007800, 0x497a6000, 0x4a0370e5, 0x00020000, - 0x1c01f000, 0x4803c856, 0x4d300000, 0x4d2c0000, - 0x42000800, 0x000003ff, 0x4a0370e5, 0x00020000, - 0x59b800e5, 0x8c000524, 0x04000005, 0x80040840, - 0x040207fa, 0x0201f800, 0x00100615, 0x4a0370e5, - 0x00030000, 0x40000000, 0x40000000, 0x59b800e5, - 0x8c000524, 0x040207f1, 0x5934000e, 0x80026540, - 0x0400000e, 0x4933c857, 0x59300000, 0x4802680e, - 0x4a026203, 0x00000004, 0x497a6206, 0x497a6009, - 0x4a026007, 0x00000101, 0x59325808, 0x497a5c08, - 0x0401fd82, 0x0401f7f1, 0x4a0370e5, 0x00020000, - 0x5c025800, 0x5c026000, 0x1c01f000, 0x4803c856, - 0x4c000000, 0x0201f800, 0x001059b9, 0x04020011, - 0x0201f800, 0x001043fc, 0x02020800, 0x00100615, - 0x5c000000, 0x48026802, 0x0201f800, 0x00020892, - 0x04000009, 0x49366009, 0x4a026406, 0x00000001, - 0x42027000, 0x00000001, 0x0201f000, 0x000208d8, - 0x5c000000, 0x1c01f000, 0x59300203, 0x82000c80, - 0x0000000e, 0x02021800, 0x00100615, 0x4803c857, - 0x0c01f001, 0x0010623b, 0x0010623b, 0x0010623b, - 0x0010623d, 0x0010629d, 0x0010623b, 0x0010623b, - 0x001062ef, 0x001062f0, 0x0010623b, 0x0010623b, - 0x0010623b, 0x0010623b, 0x0010623b, 0x0201f800, - 0x00100615, 0x493bc857, 0x83380480, 0x00000050, - 0x02021800, 0x00100615, 0x83380480, 0x00000049, - 0x02001800, 0x00100615, 0x0c01f001, 0x00106250, - 0x00106272, 0x0010624e, 0x0010624e, 0x0010624e, - 0x0010624e, 0x00106281, 0x0201f800, 0x00100615, - 0x4d2c0000, 0x59325808, 0x592c0206, 0x48025c06, - 0x4a025a06, 0x00000000, 0x4c5c0000, 0x592cbc0a, - 0x592c0000, 0x48026008, 0x0201f800, 0x00020385, - 0x59300008, 0x80000540, 0x04000008, 0x4a026203, - 0x00000007, 0x42027000, 0x00000043, 0x5c00b800, - 0x5c025800, 0x0401f08a, 0x8c5cbd08, 0x04020006, - 0x4a026203, 0x00000007, 0x497a6206, 0x497a6008, - 0x0401f003, 0x0201f800, 0x000208b4, 0x5c00b800, - 0x5c025800, 0x1c01f000, 0x0201f800, 0x001068c1, - 0x4d2c0000, 0x59325808, 0x0201f800, 0x00108df4, - 0x04000006, 0x4d400000, 0x42028000, 0x00000001, - 0x0401f90e, 0x5c028000, 0x5c025800, 0x0201f000, - 0x000208b4, 0x0201f800, 0x001068c1, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42003000, 0x00000014, 0x0201f800, 0x0010a766, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x4d2c0000, 0x59325808, 0x0201f800, 0x00108df4, - 0x04000006, 0x4d400000, 0x42028000, 0x00000029, - 0x0401f8f2, 0x5c028000, 0x5c025800, 0x0201f000, - 0x000208b4, 0x493bc857, 0x497a6206, 0x83380480, - 0x00000054, 0x02021800, 0x00100615, 0x83380480, - 0x00000047, 0x02001800, 0x00100615, 0x0c01f001, - 0x001062ee, 0x001062b7, 0x001062b5, 0x001062b5, - 0x001062b5, 0x001062b5, 0x001062b5, 0x001062b5, - 0x001062b5, 0x001062b5, 0x001062b5, 0x001062b5, - 0x001062bb, 0x0201f800, 0x00100615, 0x59300011, - 0x82000500, 0xffff0000, 0x04020034, 0x59840802, - 0x8c040d04, 0x04000025, 0x59300009, 0x80026d40, - 0x0400001f, 0x4c5c0000, 0x4c600000, 0x497a6206, - 0x5930b808, 0x585c0005, 0x8000c540, 0x02000800, - 0x00100615, 0x0401fe8d, 0x40625800, 0x0201f800, - 0x00020385, 0x4978b805, 0x0401fef5, 0x497a6009, - 0x585c3408, 0x0401fcbe, 0x0400000e, 0x42001000, - 0x0010b315, 0x0401fcf3, 0x0400000a, 0x0201f800, - 0x0010082a, 0x04000007, 0x492cb805, 0x585c5408, - 0x0401fc84, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x0401fcaa, 0x0401f7fc, 0x8c040d06, 0x040207fc, - 0x59300009, 0x80026d40, 0x04000006, 0x5934000e, - 0x80000540, 0x02020800, 0x00100615, 0x497a6009, - 0x0401fd0e, 0x0401f7f2, 0x0401f085, 0x4803c856, - 0x4803c856, 0x83380580, 0x00000043, 0x02020800, - 0x00100615, 0x4a026203, 0x00000003, 0x493a6403, - 0x59325808, 0x592c000f, 0x48026011, 0x497a6013, - 0x592c0406, 0x800000c2, 0x800010c4, 0x80081400, - 0x480a6206, 0x0201f800, 0x00100f9c, 0x42000800, - 0x80000060, 0x0401f161, 0x42000000, 0x0010b674, - 0x0201f800, 0x0010a86e, 0x59300203, 0x82000c80, - 0x0000000e, 0x02021800, 0x00100615, 0x4803c857, - 0x82000d80, 0x00000003, 0x04000006, 0x82000d80, - 0x00000004, 0x0400005b, 0x0201f800, 0x00100615, - 0x0201f800, 0x0010698c, 0x59300004, 0x8c00053e, - 0x04020007, 0x0201f800, 0x001068a3, 0x02020800, - 0x00100615, 0x0201f000, 0x00106982, 0x0401f9d3, - 0x0201f800, 0x00106982, 0x59325808, 0x42028000, - 0x00000006, 0x0401f861, 0x0201f000, 0x000208b4, - 0x4803c856, 0x59300203, 0x82000c80, 0x0000000e, - 0x02021800, 0x00100615, 0x82000d80, 0x00000002, - 0x04000009, 0x82000d80, 0x00000003, 0x04000019, - 0x82000d80, 0x00000004, 0x04000036, 0x0201f800, - 0x00100615, 0x4933c857, 0x4d2c0000, 0x59325808, - 0x812e59c0, 0x02000800, 0x00100615, 0x592c1a08, - 0x8c0c1d0e, 0x02000800, 0x00100615, 0x4d400000, - 0x42028000, 0x00000001, 0x0401f840, 0x0201f800, - 0x00107698, 0x5c028000, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x0201f800, 0x0010698c, 0x4df00000, - 0x59300004, 0x8c00053e, 0x04020006, 0x0201f800, - 0x00106cb4, 0x02020800, 0x00100615, 0x0401f010, - 0x0201f800, 0x00108a8a, 0x04020004, 0x0201f800, - 0x00106bb2, 0x0402000a, 0x0401f994, 0x02020800, - 0x00100615, 0x5c03e000, 0x02000800, 0x00106982, - 0x82000540, 0x00000001, 0x1c01f000, 0x5c03e000, - 0x02000800, 0x00106982, 0x80000580, 0x1c01f000, - 0x4933c857, 0x0201f800, 0x00100ee4, 0x4933c857, - 0x4c5c0000, 0x4d340000, 0x497a6206, 0x5930b808, - 0x59300009, 0x80026d40, 0x04020e49, 0x42001000, - 0x0010b315, 0x0401fc4b, 0x04000009, 0x58c80204, - 0x4800bc08, 0x41785000, 0x0201f800, 0x00105f60, - 0x5c026800, 0x5c00b800, 0x1c01f000, 0x4978bc08, - 0x0401fc02, 0x0401f7fb, 0x4803c856, 0x0201f800, - 0x00108df4, 0x0400000f, 0x592c0000, 0x80000d40, - 0x04000009, 0x497a5800, 0x49425a06, 0x4c040000, - 0x0201f800, 0x00020381, 0x5c000800, 0x40065800, - 0x0401f7f6, 0x49425a06, 0x0201f800, 0x00020381, - 0x1c01f000, 0x4933c857, 0x59300c06, 0x82040580, - 0x0000000e, 0x04000004, 0x82040580, 0x00000009, - 0x04020004, 0x0401ffe5, 0x497a6008, 0x80000580, - 0x1c01f000, 0x592e6009, 0x83300480, 0x0010cfc0, - 0x04001016, 0x41580000, 0x81300480, 0x04021013, - 0x40040000, 0x59300c06, 0x80040580, 0x04020012, - 0x59300a03, 0x82040580, 0x00000007, 0x02020800, - 0x00100615, 0x59300008, 0x80000540, 0x02020800, - 0x00100615, 0x0201f800, 0x000208b4, 0x42000000, - 0x00000000, 0x0401f009, 0x42000000, 0x00000008, - 0x0401f006, 0x82040580, 0x00000007, 0x040207fb, - 0x42000000, 0x00000005, 0x592c0a06, 0x48065c06, - 0x48025a06, 0x0201f000, 0x00020381, 0x4c0c0000, - 0x4c100000, 0x4c140000, 0x4c180000, 0x80001d80, - 0x80002580, 0x42003000, 0x00000020, 0x82040500, - 0x00000001, 0x04000003, 0x40080000, 0x800c1c00, - 0x400c2800, 0x800c1902, 0x80102102, 0x82140500, - 0x00000001, 0x04000003, 0x82102540, 0x80000000, - 0x80040902, 0x80183040, 0x040207f1, 0x40100800, - 0x400c0000, 0x5c003000, 0x5c002800, 0x5c002000, - 0x5c001800, 0x1c01f000, 0x4c580000, 0x4200b000, - 0x00000020, 0x80000540, 0x04000018, 0x80041c80, - 0x04021016, 0x800810c2, 0x80040982, 0x04001006, - 0x80041c80, 0x04021005, 0x8058b040, 0x040207fa, - 0x0401f006, 0x80041c80, 0x400c0800, 0x80081000, - 0x8058b040, 0x040207f4, 0x4c000000, 0x41f00000, - 0x82000500, 0xf7ffffff, 0x4003e000, 0x5c000000, - 0x5c00b000, 0x1c01f000, 0x4c000000, 0x41f00000, - 0x82000540, 0x08000000, 0x0401f7f8, 0x42007000, - 0x0010b33f, 0x4a007000, 0x00000005, 0x4a007401, - 0x00000000, 0x4a007202, 0x00000840, 0x4a0378e8, - 0x00000000, 0x4a03c821, 0x00000010, 0x4a03c823, - 0x00000004, 0x0401f81d, 0x4a0378e9, 0x00003a0d, - 0x4a0378e8, 0x00000001, 0x42000800, 0x00000005, - 0x4203a000, 0x00007600, 0x4a03a005, 0xd0000001, - 0x59d00006, 0x4a03a005, 0x90000001, 0x83d3a400, - 0x00000020, 0x80040840, 0x040207fa, 0x59e00003, - 0x82000500, 0xffffffe0, 0x82000540, 0x00008000, - 0x4803c003, 0x59c40006, 0x82000500, 0xfffcffff, - 0x48038806, 0x1c01f000, 0x4d900000, 0x4d180000, - 0x4a0378e7, 0xaaaaaaaa, 0x4a0378e6, 0xaaaaaaaa, - 0x4a0378e5, 0xaaaaaaaa, 0x4a0378e4, 0xaaaaaaaa, - 0x4a03781a, 0x0010b5d2, 0x4a03781b, 0x0010110d, - 0x4a03781c, 0x0010111d, 0x4a031800, 0x00000000, - 0x4a031801, 0x0010b342, 0x4a031802, 0x0010b349, - 0x42000800, 0x0010b5d5, 0x417a3000, 0x811b20c8, - 0x83932400, 0x0000bf32, 0x48072000, 0x4a032001, - 0x00000000, 0x83180400, 0x00106e41, 0x50000000, - 0x48032002, 0x82040c00, 0x00000003, 0x811a3000, - 0x83180480, 0x00000005, 0x040017f1, 0x5c023000, - 0x5c032000, 0x1c01f000, 0x48066004, 0x497a6000, - 0x497a6001, 0x59bc00ea, 0x8c000516, 0x040207fe, - 0x83300400, 0xa0000000, 0x480378e1, 0x1c01f000, - 0x4933c857, 0x59300804, 0x82040d00, 0x00000100, - 0x82040d40, 0x80000040, 0x48066004, 0x497a6000, - 0x59bc00ea, 0x8c000516, 0x040207fe, 0x83300400, - 0x60000000, 0x480378e1, 0x1c01f000, 0x0201f800, - 0x0010698c, 0x4df00000, 0x4d300000, 0x4d340000, - 0x4d2c0000, 0x4d180000, 0x4c5c0000, 0x4c600000, - 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, - 0x42003000, 0x0000bf2e, 0x581a6001, 0x813261c0, - 0x0400002c, 0x41302800, 0x4178c000, 0x59300000, - 0x4c000000, 0x59326809, 0x5930b801, 0x59300406, - 0x82000d80, 0x00000006, 0x04020003, 0x8d3e7d18, - 0x04000010, 0x8d3e7d06, 0x04000007, 0x82000580, - 0x00000003, 0x04020004, 0x59340200, 0x8c00050e, - 0x04020008, 0x0401f92d, 0x4c0c0000, 0x4c140000, - 0x0401fb59, 0x5c002800, 0x5c001800, 0x0401f005, - 0x41301800, 0x8060c1c0, 0x04020002, 0x400cc000, - 0x805cb9c0, 0x04000003, 0x405e6000, 0x0401f7e3, - 0x5c026000, 0x813261c0, 0x04000006, 0x8060c1c0, - 0x04000002, 0x40602800, 0x4178c000, 0x0401f7d8, - 0x417a3000, 0x0201f800, 0x00106e2f, 0x59926004, - 0x813261c0, 0x04000023, 0x59326809, 0x4130c000, - 0x59300001, 0x8000bd40, 0x04000016, 0x40026000, - 0x40602800, 0x5930b801, 0x59300406, 0x82000d80, - 0x00000006, 0x0400000e, 0x8d3e7d06, 0x04000007, - 0x82000580, 0x00000003, 0x04020004, 0x59340200, - 0x8c00050e, 0x04020006, 0x0401f8da, 0x4c140000, - 0x0401fb29, 0x5c002800, 0x0401f002, 0x41302800, - 0x405e6000, 0x813261c0, 0x040207eb, 0x8060c1c0, - 0x04000004, 0x40626000, 0x4178c000, 0x0401f7e7, - 0x811a3000, 0x83180480, 0x00000005, 0x040017d6, - 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, - 0x5c00c000, 0x5c00b800, 0x5c023000, 0x5c025800, - 0x5c026800, 0x5c026000, 0x5c03e000, 0x02000800, - 0x00106982, 0x1c01f000, 0x4933c857, 0x0201f800, - 0x0010698c, 0x4df00000, 0x4d340000, 0x4d180000, - 0x4d900000, 0x42003000, 0x0000bf2e, 0x59326809, - 0x58182001, 0x40102800, 0x801021c0, 0x04000016, - 0x41300000, 0x80100580, 0x04000011, 0x58100009, - 0x81340580, 0x0402000b, 0x40101800, 0x58102001, - 0x41300000, 0x801021c0, 0x0400000b, 0x80100d80, - 0x04000007, 0x40101800, 0x58102001, 0x0401f7fa, - 0x40102800, 0x58102000, 0x0401f7ec, 0x0401f8bb, - 0x0401f01a, 0x42032000, 0x0000bf32, 0x417a3000, - 0x59902004, 0x40102800, 0x801021c0, 0x0400000b, - 0x58100009, 0x81340580, 0x04020008, 0x41300000, - 0x80100580, 0x0400000c, 0x40102800, 0x58102001, - 0x801021c0, 0x040207fa, 0x811a3000, 0x83180480, - 0x00000005, 0x0402100d, 0x83932400, 0x00000010, - 0x0401f7ec, 0x0401f87f, 0x5c032000, 0x5c023000, - 0x5c026800, 0x5c03e000, 0x02000800, 0x00106982, - 0x80000580, 0x1c01f000, 0x5c032000, 0x5c023000, - 0x5c026800, 0x5c03e000, 0x02000800, 0x00106982, - 0x82000540, 0x00000001, 0x1c01f000, 0x0201f800, - 0x0010698c, 0x4df00000, 0x4d300000, 0x4d340000, - 0x4d180000, 0x4d2c0000, 0x4c5c0000, 0x4c600000, - 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, - 0x42003000, 0x0000bf2e, 0x581a6001, 0x813261c0, - 0x04000023, 0x41302800, 0x5930b800, 0x59326809, - 0x59340403, 0x81440580, 0x04000006, 0x805cb9c0, - 0x0400001b, 0x41302800, 0x405e6000, 0x0401f7f7, - 0x5930b801, 0x8d3e7d00, 0x04000003, 0x0401fb58, - 0x0402000e, 0x59300406, 0x82000580, 0x00000006, - 0x04020003, 0x8d3e7d18, 0x04000008, 0x0401f867, - 0x4c0c0000, 0x4c140000, 0x0401fa93, 0x5c002800, - 0x5c001800, 0x0401f002, 0x41301800, 0x405e6000, - 0x813261c0, 0x040207eb, 0x0401f02d, 0x417a3000, - 0x0201f800, 0x00106e2f, 0x59926004, 0x813261c0, - 0x04000005, 0x59326809, 0x59340403, 0x81440580, - 0x04000006, 0x811a3000, 0x83180480, 0x00000005, - 0x040017f4, 0x0401f01e, 0x4130c000, 0x59300001, - 0x8000bd40, 0x04000012, 0x40026000, 0x40602800, - 0x5930b801, 0x8d3e7d00, 0x04000003, 0x0401fb2c, - 0x0402000a, 0x59300406, 0x82000580, 0x00000006, - 0x04000006, 0x0401f81b, 0x4c140000, 0x0401fa6a, - 0x5c002800, 0x0401f002, 0x41302800, 0x405e6000, - 0x813261c0, 0x040207ef, 0x8060c1c0, 0x04000004, - 0x40626000, 0x4178c000, 0x0401f7eb, 0x5c022800, - 0x5c034800, 0x5c03a000, 0x5c032000, 0x5c00c000, - 0x5c00b800, 0x5c025800, 0x5c023000, 0x5c026800, - 0x5c026000, 0x5c03e000, 0x04000bd4, 0x1c01f000, - 0x0401fbb9, 0x59900004, 0x81300580, 0x04020018, - 0x4c140000, 0x0201f800, 0x00106b13, 0x0401fba9, - 0x5c002800, 0x59300001, 0x800001c0, 0x04020003, - 0x497a680c, 0x1c01f000, 0x42003000, 0x0000bf2e, - 0x497a6001, 0x58180801, 0x800409c0, 0x04020004, - 0x48003000, 0x48003001, 0x1c01f000, 0x58180800, - 0x48000800, 0x48003000, 0x1c01f000, 0x59300001, - 0x48002801, 0x800001c0, 0x04020002, 0x4816680c, - 0x497a6001, 0x1c01f000, 0x0401fb97, 0x42003000, - 0x0000bf2e, 0x58180001, 0x81300580, 0x0402001c, - 0x59300801, 0x800409c0, 0x0400000e, 0x59300000, - 0x800001c0, 0x04020005, 0x48043001, 0x48043000, - 0x497a6001, 0x1c01f000, 0x59300000, 0x48000800, - 0x48043001, 0x497a6000, 0x497a6001, 0x1c01f000, - 0x59300800, 0x800409c0, 0x04020005, 0x49783001, - 0x49783000, 0x497a680c, 0x1c01f000, 0x48043001, - 0x497a6000, 0x497a680c, 0x1c01f000, 0x58180000, - 0x81300580, 0x0402000c, 0x59300001, 0x800001c0, - 0x04020005, 0x48143000, 0x49782800, 0x497a680c, - 0x1c01f000, 0x48003000, 0x48002800, 0x497a6001, - 0x1c01f000, 0x59300000, 0x800001c0, 0x04020008, - 0x59300001, 0x48001801, 0x800001c0, 0x04020002, - 0x480e680c, 0x497a6001, 0x1c01f000, 0x59300801, - 0x800409c0, 0x04020006, 0x59300800, 0x48042800, - 0x497a6000, 0x497a680c, 0x1c01f000, 0x59300000, - 0x48000800, 0x48042800, 0x497a6000, 0x497a6001, - 0x1c01f000, 0x0401fb73, 0x4df00000, 0x0401f83a, - 0x040208c7, 0x0402094a, 0x04020005, 0x5c03e000, - 0x04000b62, 0x80000580, 0x1c01f000, 0x5c03e000, - 0x04000b5e, 0x82000540, 0x00000001, 0x1c01f000, - 0x4d2c0000, 0x4d340000, 0x4d300000, 0x41783000, - 0x598e6009, 0x813261c0, 0x04000023, 0x59300406, - 0x82000580, 0x00000006, 0x04020004, 0x8d3e7d18, - 0x0402000c, 0x0401f019, 0x82040580, 0x00000005, - 0x04020008, 0x8d3e7d18, 0x04000003, 0x8d3e7d16, - 0x04000004, 0x59300420, 0x8c000500, 0x0402000f, - 0x0401fa49, 0x59300000, 0x4c000000, 0x8d3e7d06, - 0x04000004, 0x0201f800, 0x0010909d, 0x04000005, - 0x0401f869, 0x4c180000, 0x0401f9b7, 0x5c003000, - 0x5c026000, 0x0401f7e0, 0x41303000, 0x59326000, - 0x0401f7dd, 0x5c026000, 0x5c026800, 0x5c025800, - 0x1c01f000, 0x4933c857, 0x4c5c0000, 0x813261c0, - 0x02000800, 0x00100615, 0x41300000, 0x598cb809, - 0x41783000, 0x805cb9c0, 0x04000013, 0x805c0d80, - 0x04000004, 0x405c3000, 0x5818b800, 0x0401f7fa, - 0x0401f84d, 0x598c000d, 0x81300580, 0x02000800, - 0x00106e10, 0x59300403, 0x82000580, 0x00000042, - 0x04020002, 0x497a6007, 0x80000580, 0x5c00b800, - 0x1c01f000, 0x82000540, 0x00000001, 0x5c00b800, - 0x1c01f000, 0x0401fb17, 0x4df00000, 0x4d2c0000, - 0x4d340000, 0x4d300000, 0x41783000, 0x598e6009, - 0x813261c0, 0x0400002e, 0x59300c06, 0x82040580, - 0x00000006, 0x04020004, 0x8d3e7d18, 0x0402000c, - 0x0401f024, 0x82040580, 0x00000005, 0x04020008, - 0x8d3e7d18, 0x04000003, 0x8d3e7d16, 0x04000004, - 0x59300420, 0x8c000500, 0x0402001a, 0x59326809, - 0x59340403, 0x81440580, 0x04020016, 0x8d3e7d00, - 0x04000006, 0x82040580, 0x00000003, 0x04020011, - 0x0401fa23, 0x0402000f, 0x0401f9ef, 0x59300000, - 0x4c000000, 0x8d3e7d06, 0x04000004, 0x0201f800, - 0x0010909d, 0x04000005, 0x0401f80f, 0x4c180000, - 0x0401f95d, 0x5c003000, 0x5c026000, 0x0401f7d5, - 0x41303000, 0x59326000, 0x0401f7d2, 0x5c026000, - 0x5c026800, 0x5c025800, 0x5c03e000, 0x04000ad3, - 0x1c01f000, 0x59300800, 0x497a6000, 0x0401fab6, - 0x801831c0, 0x04020009, 0x598c0008, 0x81300580, - 0x04020004, 0x48031808, 0x48031809, 0x0401f008, - 0x48071809, 0x0401f006, 0x48043000, 0x598c0008, - 0x81300580, 0x04020002, 0x481b1808, 0x0401f2b8, - 0x4d2c0000, 0x4d300000, 0x4d340000, 0x41783000, - 0x598e600b, 0x813261c0, 0x04000013, 0x8d3e7d06, - 0x04000005, 0x59326809, 0x59340200, 0x8c00050e, - 0x0402000a, 0x0401f9b8, 0x59300000, 0x4c000000, - 0x0401f853, 0x4c180000, 0x0401f92b, 0x5c003000, - 0x5c026000, 0x0401f7f0, 0x41303000, 0x59326000, - 0x0401f7ed, 0x0201f800, 0x001045c7, 0x5c026800, - 0x5c026000, 0x5c025800, 0x1c01f000, 0x4933c857, - 0x4c5c0000, 0x813261c0, 0x02000800, 0x00100615, - 0x41300000, 0x598cb80b, 0x41783000, 0x805cb9c0, - 0x0400000f, 0x805c0d80, 0x04000004, 0x405c3000, - 0x5818b800, 0x0401f7fa, 0x0401f835, 0x598c000d, - 0x81300580, 0x02000800, 0x00106e10, 0x497a6007, - 0x80000580, 0x5c00b800, 0x1c01f000, 0x82000540, - 0x00000001, 0x5c00b800, 0x1c01f000, 0x0401fa8d, - 0x4df00000, 0x4d340000, 0x4d300000, 0x4d2c0000, - 0x0201f800, 0x00020267, 0x02020800, 0x00100615, - 0x41783000, 0x598e600b, 0x813261c0, 0x04000014, - 0x59300009, 0x81340580, 0x0402000e, 0x8d3e7d00, - 0x04000003, 0x0401f9aa, 0x0402000a, 0x0401f976, - 0x59300000, 0x4c000000, 0x0401f811, 0x4c180000, - 0x0401f8e9, 0x5c003000, 0x5c026000, 0x0401f7ef, - 0x41303000, 0x59326000, 0x0401f7ec, 0x0201f800, - 0x001045ea, 0x5c025800, 0x5c026000, 0x5c026800, - 0x5c03e000, 0x04000a5d, 0x1c01f000, 0x59300800, - 0x497a6000, 0x0401fa40, 0x801831c0, 0x04020009, - 0x598c000a, 0x81300580, 0x04020004, 0x4803180a, - 0x4803180b, 0x0401f008, 0x4807180b, 0x0401f006, - 0x48043000, 0x598c000a, 0x81300580, 0x04020002, - 0x481b180a, 0x0401f242, 0x0401fa52, 0x4df00000, - 0x4d300000, 0x4c5c0000, 0x4178b800, 0x8d3e7d18, - 0x04000004, 0x8d3e7d16, 0x04020002, 0x805cb800, - 0x598e6005, 0x813261c0, 0x0400001a, 0x59300000, - 0x4c000000, 0x805cb9c0, 0x0402000b, 0x59300c06, - 0x82040580, 0x00000011, 0x04000010, 0x82040580, - 0x00000004, 0x04020004, 0x59300420, 0x8c000500, - 0x0402000a, 0x0201f800, 0x00108f05, 0x02000800, - 0x00107da6, 0x0201f800, 0x001090ec, 0x0201f800, - 0x000208b4, 0x0401fa1e, 0x5c026000, 0x0401f7e6, - 0x497b1805, 0x497b1804, 0x5c00b800, 0x5c026000, - 0x5c03e000, 0x04000a1d, 0x1c01f000, 0x4933c857, - 0x4c5c0000, 0x4c600000, 0x813261c0, 0x02000800, - 0x00100615, 0x41300000, 0x598cb805, 0x405cc000, - 0x805cb9c0, 0x04000025, 0x805c0d80, 0x04000004, - 0x405cc000, 0x5860b800, 0x0401f7fa, 0x598c000d, - 0x81300580, 0x02000800, 0x00106e10, 0x0401f9ee, - 0x598c0005, 0x805c0580, 0x04020009, 0x585c0000, - 0x48031805, 0x4978b800, 0x598c0004, 0x805c0580, - 0x0402000d, 0x497b1804, 0x0401f00b, 0x598c0004, - 0x805c0580, 0x04020005, 0x48631804, 0x4978b800, - 0x4978c000, 0x0401f004, 0x585c0000, 0x4800c000, - 0x4978b800, 0x0401f9ea, 0x80000580, 0x5c00c000, - 0x5c00b800, 0x1c01f000, 0x82000540, 0x00000001, - 0x5c00c000, 0x5c00b800, 0x1c01f000, 0x4933c857, - 0x0401f9f0, 0x4df00000, 0x4d2c0000, 0x4d340000, - 0x4d300000, 0x4c5c0000, 0x4178b800, 0x8d3e7d18, - 0x04000004, 0x8d3e7d16, 0x04020002, 0x805cb800, - 0x41783000, 0x598e6005, 0x813261c0, 0x04000029, - 0x59326809, 0x813669c0, 0x04000023, 0x59340403, - 0x81440580, 0x04020020, 0x805cb9c0, 0x0402000b, - 0x59300c06, 0x82040580, 0x00000011, 0x0400001a, - 0x82040580, 0x00000004, 0x04020004, 0x59300420, - 0x8c000500, 0x04020014, 0x0201f800, 0x00108df4, - 0x04000008, 0x0201f800, 0x00109360, 0x04020005, - 0x59300403, 0x82000580, 0x00000043, 0x0400000a, - 0x0401f8c1, 0x59300000, 0x4c000000, 0x0401f810, - 0x4c180000, 0x0401f834, 0x5c003000, 0x5c026000, - 0x0401f7da, 0x41303000, 0x59326000, 0x0401f7d7, - 0x5c00b800, 0x5c026000, 0x5c026800, 0x5c025800, - 0x5c03e000, 0x040009a9, 0x1c01f000, 0x59300800, - 0x497a6000, 0x0401f98c, 0x801831c0, 0x04020009, - 0x598c0004, 0x81300580, 0x04020004, 0x48031804, - 0x48031805, 0x0401f008, 0x48071805, 0x0401f006, - 0x48043000, 0x598c0004, 0x81300580, 0x04020002, - 0x481b1804, 0x0401f18e, 0x4943c857, 0x0401f99d, - 0x4df00000, 0x0401fe37, 0x0401fed2, 0x5c03e000, - 0x0400098e, 0x1c01f000, 0x4947c857, 0x0401f995, - 0x4df00000, 0x4d3c0000, 0x853e7d00, 0x0401fe7a, - 0x0401ff03, 0x5c027800, 0x5c03e000, 0x04000983, - 0x1c01f000, 0x5c000000, 0x4c000000, 0x4803c857, - 0x4d340000, 0x4d2c0000, 0x59326809, 0x59325808, - 0x59300406, 0x82000c80, 0x00000012, 0x02021800, - 0x00100615, 0x4933c857, 0x4943c857, 0x493fc857, - 0x4803c857, 0x0c01f804, 0x5c025800, 0x5c026800, - 0x1c01f000, 0x00106827, 0x00106829, 0x00106833, - 0x0010684d, 0x00106829, 0x0010683d, 0x00106865, - 0x00106827, 0x00106827, 0x00106878, 0x0010686f, - 0x00106827, 0x00106827, 0x00106827, 0x00106827, - 0x00106827, 0x0010687e, 0x0010687e, 0x0201f800, - 0x00100615, 0x0201f800, 0x00108ef1, 0x02000800, - 0x00101e1b, 0x0201f800, 0x001090ec, 0x0201f800, - 0x00107da6, 0x0201f000, 0x00107698, 0x812e59c0, - 0x02020800, 0x00100615, 0x5930021d, 0x82000580, - 0x00000003, 0x02000800, 0x00108ee7, 0x0201f000, - 0x00107698, 0x0201f800, 0x00108df4, 0x02000000, - 0x00107698, 0x592c1204, 0x82081500, 0x000000ff, - 0x82080580, 0x00000055, 0x02020800, 0x00100615, - 0x49425a06, 0x0201f800, 0x00020381, 0x0201f000, - 0x00107698, 0x59300004, 0x8400055c, 0x48026004, - 0x59300007, 0x8c000500, 0x02020800, 0x00100ee4, - 0x0201f800, 0x00108df4, 0x0400000d, 0x4a025a04, - 0x00000103, 0x49425a06, 0x497a5c09, 0x0201f800, - 0x00108f7d, 0x0201f800, 0x0010a4ae, 0x0201f800, - 0x00020381, 0x0201f800, 0x00108ee7, 0x0201f000, - 0x00107698, 0x59300007, 0x8c000500, 0x02020800, - 0x00100ee4, 0x0201f800, 0x00108df4, 0x02020800, - 0x0010a201, 0x0201f000, 0x00107698, 0x0201f800, - 0x00108df4, 0x04000005, 0x49425a06, 0x497a5c09, - 0x0201f800, 0x00020381, 0x0201f000, 0x00107698, - 0x0201f800, 0x00108df4, 0x02020800, 0x0010639d, - 0x0201f000, 0x00107698, 0x0201f800, 0x00108df4, - 0x04000004, 0x49425a06, 0x0201f800, 0x00020381, - 0x59325817, 0x0201f800, 0x00100843, 0x0201f000, - 0x00107698, 0x598c000d, 0x81300580, 0x04000003, - 0x497a6007, 0x1c01f000, 0x59c40004, 0x82000500, - 0x0000000c, 0x04000005, 0x4a038804, 0x0000000c, - 0x497b2807, 0x0401f00a, 0x0401fadb, 0x59300403, - 0x82000d80, 0x00000040, 0x04000004, 0x82000580, - 0x00000042, 0x04020002, 0x497a6007, 0x0201f800, - 0x00106e10, 0x80000580, 0x1c01f000, 0x59300804, - 0x8c040d20, 0x04020004, 0x82000540, 0x00000001, - 0x1c01f000, 0x4933c857, 0x4d380000, 0x59300804, - 0x84040d20, 0x48066004, 0x42027000, 0x00000049, - 0x59300203, 0x82000580, 0x00000003, 0x04000003, - 0x42027000, 0x00000013, 0x0201f800, 0x000208d8, - 0x80000580, 0x5c027000, 0x1c01f000, 0x59300017, - 0x81480580, 0x04020003, 0x59300018, 0x814c0580, - 0x1c01f000, 0x4d2c0000, 0x4d300000, 0x0401f8c9, - 0x4df00000, 0x0201f800, 0x00105d9b, 0x59900001, - 0x82000500, 0x00000003, 0x0c01f001, 0x001068f1, - 0x001068d1, 0x001068cf, 0x001068cf, 0x0201f800, - 0x00100615, 0x59926004, 0x0401f88e, 0x813261c0, - 0x0400001d, 0x59300004, 0x8c000516, 0x04000004, - 0x59325808, 0x497a5808, 0x497a5809, 0x0401f88e, - 0x59300001, 0x800001c0, 0x0400000e, 0x497a6001, - 0x42003000, 0x0000bf2e, 0x58180801, 0x800409c0, - 0x04020004, 0x48003001, 0x48003000, 0x0401f00a, - 0x58180800, 0x48000800, 0x48003000, 0x0401f006, - 0x59300809, 0x800409c0, 0x02000800, 0x00100615, - 0x4978080c, 0x5c03e000, 0x04000890, 0x5c026000, - 0x5c025800, 0x1c01f000, 0x4d300000, 0x497b2807, - 0x0401f894, 0x4df00000, 0x598c0000, 0x82000500, - 0x00000007, 0x4803c857, 0x0c01f001, 0x00106926, - 0x00106909, 0x00106912, 0x00106916, 0x00106921, - 0x00106926, 0x00106907, 0x00106907, 0x0201f800, - 0x00100615, 0x598c000d, 0x80026540, 0x04000004, - 0x0401f81e, 0x02020800, 0x00100615, 0x0201f800, - 0x00106e10, 0x0401f015, 0x0401f827, 0x0201f800, - 0x00106e10, 0x0401f011, 0x598c000d, 0x80026540, - 0x0400000e, 0x0401f838, 0x04000004, 0x0401f80f, - 0x04000002, 0x0401f81c, 0x0201f800, 0x00106e10, - 0x0401f006, 0x0401f830, 0x02020800, 0x00100615, - 0x0201f800, 0x00106e10, 0x5c03e000, 0x0400085b, - 0x5c026000, 0x1c01f000, 0x598c0009, 0x81300580, - 0x0402000c, 0x0401f84e, 0x0401f83b, 0x59300000, - 0x800001c0, 0x04000004, 0x48031809, 0x497a6000, - 0x0401f003, 0x497b1809, 0x497b1808, 0x80000580, - 0x1c01f000, 0x4d2c0000, 0x59300406, 0x82000580, - 0x00000003, 0x04020012, 0x598c000b, 0x81300580, - 0x0402000f, 0x0401f83a, 0x59325808, 0x497a5808, - 0x497a5809, 0x0401f824, 0x59300000, 0x800001c0, - 0x04000004, 0x4803180b, 0x497a6000, 0x0401f003, - 0x497b180a, 0x497b180b, 0x80000580, 0x5c025800, - 0x1c01f000, 0x598c0005, 0x81300580, 0x0402000c, - 0x0401f827, 0x0401f814, 0x59300000, 0x800001c0, - 0x04000004, 0x48031805, 0x497a6000, 0x0401f003, - 0x497b1805, 0x497b1804, 0x80000580, 0x1c01f000, - 0x4a032001, 0x00000000, 0x497b2004, 0x497b2005, - 0x59900006, 0x82000500, 0x0000ffff, 0x48032006, - 0x1c01f000, 0x4c040000, 0x59300004, 0x82000500, - 0x7ffeffff, 0x48026004, 0x59bc00e4, 0x8c000514, - 0x04000009, 0x42000800, 0x0000bf00, 0x58040012, - 0x81300580, 0x04020004, 0x49780812, 0x4a0378e4, - 0x00000800, 0x5c000800, 0x1c01f000, 0x4803c856, - 0x598c000c, 0x80000540, 0x04000003, 0x80000040, - 0x4803180c, 0x1c01f000, 0x59bc00ea, 0x82000500, - 0x00000007, 0x82000580, 0x00000003, 0x04020004, - 0x4803c856, 0x4a0378e8, 0x00000001, 0x1c01f000, - 0x59bc00ea, 0x82000500, 0x00000007, 0x82000580, - 0x00000001, 0x04020011, 0x4803c856, 0x42000800, - 0x00000000, 0x0401f80e, 0x42000800, 0x00001000, - 0x59bc00ea, 0x82000500, 0x00000007, 0x82000580, - 0x00000003, 0x04000005, 0x80040840, 0x040207f9, - 0x0201f800, 0x00100615, 0x1c01f000, 0x59bc00ea, - 0x82000500, 0x00000007, 0x82000580, 0x00000001, - 0x02020800, 0x00100615, 0x59bc00ea, 0x8c000516, - 0x040207fe, 0x480778e1, 0x1c01f000, 0x59bc00ea, - 0x8c000516, 0x040207fe, 0x480778e1, 0x59bc00ea, - 0x8c000516, 0x040207fe, 0x480b78e1, 0x1c01f000, - 0x4a0378e4, 0x00002000, 0x59a8006f, 0x82000500, - 0x0000000c, 0x04020008, 0x42007000, 0x0010b33f, - 0x58380401, 0x8c000506, 0x04020003, 0x4a0378e4, - 0x00080000, 0x1c01f000, 0x82000d00, 0x80000018, - 0x02020800, 0x0010060d, 0x0201f800, 0x00100615, - 0x001069dc, 0x00106a81, 0x00106a9b, 0x001069dc, - 0x001069de, 0x001069ff, 0x00106a1e, 0x00106a53, - 0x001069dc, 0x00106a7f, 0x001069dc, 0x001069dc, - 0x001069dc, 0x001069dc, 0x001069dc, 0x001069dc, - 0x0201f800, 0x00100615, 0x4d300000, 0x4d900000, - 0x4dd00000, 0x4da40000, 0x4d140000, 0x0201f800, - 0x00106e2f, 0x59bc00ea, 0x8c000510, 0x040007fe, - 0x59be60e0, 0x59300004, 0x8c000520, 0x04000011, - 0x82000500, 0xfffefeff, 0x48026004, 0x4a026203, - 0x00000003, 0x0401ff9b, 0x0201f800, 0x0010101e, - 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000, - 0x5c026000, 0x4a0378e4, 0x00000008, 0x0401f787, - 0x84000510, 0x48026004, 0x0401f7f6, 0x4d300000, - 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, - 0x0201f800, 0x00106e2f, 0x59bc00ea, 0x8c000510, - 0x040007fe, 0x59be60e0, 0x59300004, 0x8c000520, - 0x0400000f, 0x82000500, 0xfffefeff, 0x48026004, - 0x0401ff7c, 0x0201f800, 0x0010105c, 0x5c022800, - 0x5c034800, 0x5c03a000, 0x5c032000, 0x5c026000, - 0x4a0378e4, 0x00000008, 0x0401f768, 0x84000510, - 0x48026004, 0x0401f7f6, 0x4d300000, 0x4d2c0000, - 0x4d340000, 0x4da40000, 0x4cd00000, 0x59bc00ea, - 0x8c000510, 0x040007fe, 0x59be60e0, 0x813261c0, - 0x02000800, 0x00100615, 0x59300004, 0x8c000520, - 0x0400001e, 0x82000500, 0xfffefeff, 0x48026004, - 0x59326809, 0x42034800, 0x0010b342, 0x04011000, - 0x4a03c840, 0x0010b349, 0x4a03c842, 0x00000012, - 0x04011000, 0x4a03c840, 0x0010b35b, 0x4a03c842, - 0x000000ff, 0x04011000, 0x4a03c840, 0x0010b45a, - 0x4a03c842, 0x000000ff, 0x0201f800, 0x00106e46, - 0x5c01a000, 0x5c034800, 0x5c026800, 0x5c025800, - 0x5c026000, 0x1c01f000, 0x84000510, 0x48026004, - 0x5c01a000, 0x5c034800, 0x5c026800, 0x5c025800, - 0x5c026000, 0x1c01f000, 0x1c01f000, 0x4d300000, - 0x4d2c0000, 0x4d340000, 0x4cd00000, 0x4d900000, - 0x4dd00000, 0x4da40000, 0x4d140000, 0x0401fbd4, - 0x59bc00ea, 0x8c000510, 0x040007fe, 0x59be60e0, - 0x813261c0, 0x02000800, 0x00100615, 0x59300004, - 0x8c000520, 0x0400000f, 0x82000500, 0xfffefeff, - 0x48026004, 0x0201f800, 0x001075b9, 0x5c022800, - 0x5c034800, 0x5c03a000, 0x5c032000, 0x5c01a000, - 0x5c026800, 0x5c025800, 0x5c026000, 0x1c01f000, - 0x84000510, 0x48026004, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x5c01a000, 0x5c026800, - 0x5c025800, 0x5c026000, 0x1c01f000, 0x0201f800, - 0x00100615, 0x4d300000, 0x4d380000, 0x42000000, - 0x0010b6c3, 0x0201f800, 0x0010a86e, 0x0401ff05, - 0x598e600d, 0x59c40004, 0x8c000506, 0x04000004, - 0x0401f8e5, 0x4a038804, 0x00000008, 0x813261c0, - 0x04000006, 0x0401fb98, 0x42027000, 0x00000014, - 0x0201f800, 0x000208d8, 0x4a0378e4, 0x00000002, - 0x5c027000, 0x5c026000, 0x0401f6e8, 0x4d180000, - 0x4d300000, 0x4d380000, 0x4d900000, 0x4dd00000, - 0x4da40000, 0x4d140000, 0x0401feea, 0x417a3000, - 0x59c40804, 0x83180400, 0x00106df6, 0x50000000, - 0x80040500, 0x0400001b, 0x42000000, 0x0010b6c4, - 0x0201f800, 0x0010a86e, 0x0401fb81, 0x59926004, - 0x0401f863, 0x83180400, 0x00106df6, 0x50000000, - 0x48038804, 0x813261c0, 0x0400000a, 0x59300004, - 0x8c00050c, 0x04020003, 0x4a026203, 0x00000003, - 0x42027000, 0x0000004a, 0x0201f800, 0x000208d8, - 0x59c40004, 0x82000500, 0x00f80000, 0x04000005, - 0x811a3000, 0x83180480, 0x00000005, 0x040017dd, - 0x4a0378e4, 0x00000008, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x5c027000, 0x5c026000, - 0x5c023000, 0x0401f6b1, 0x4d2c0000, 0x4d340000, - 0x59326809, 0x598c0800, 0x82040580, 0x00000004, - 0x04020006, 0x838c1400, 0x00000005, 0x838c1c00, - 0x00000004, 0x0401f010, 0x82040580, 0x00000001, - 0x04020006, 0x838c1400, 0x00000009, 0x838c1c00, - 0x00000008, 0x0401f008, 0x82040580, 0x00000002, - 0x04020028, 0x838c1400, 0x0000000b, 0x838c1c00, - 0x0000000a, 0x41306800, 0x58340000, 0x80007d40, - 0x04000020, 0x583c0009, 0x81340580, 0x04020006, - 0x403c6800, 0x583c0000, 0x80007d40, 0x040207fa, - 0x0401f018, 0x4933c857, 0x483fc857, 0x583c0000, - 0x48006800, 0x49307800, 0x443c1000, 0x500c0000, - 0x803c0580, 0x04020002, 0x44341800, 0x80000580, - 0x4803180d, 0x4803180f, 0x598c0000, 0x82000580, - 0x00000003, 0x04000003, 0x4a031800, 0x00000000, - 0x80000580, 0x5c026800, 0x5c025800, 0x1c01f000, - 0x82000540, 0x00000001, 0x0401f7fb, 0x491bc857, - 0x59c80840, 0x82040540, 0x00000010, 0x48039040, - 0x59c41008, 0x82080500, 0xffffff7f, 0x48038808, - 0x4c040000, 0x4c080000, 0x0401fac2, 0x04020007, - 0x0401fac6, 0x04000022, 0x48038804, 0x0201f800, - 0x001010ca, 0x0401f042, 0x4a038803, 0x00000008, - 0x59c40003, 0x82000500, 0x00000003, 0x040007fd, - 0x8c000502, 0x04020007, 0x0401fab8, 0x04000014, - 0x48038804, 0x0201f800, 0x001010ca, 0x0401f034, - 0x59c80040, 0x8400056a, 0x48039040, 0x59c80040, - 0x8c00052a, 0x040207fe, 0x59c40005, 0x82000500, - 0xc0000000, 0x04000006, 0x59c400a3, 0x84000540, - 0x480388a3, 0x4a038805, 0xc0000000, 0x0201f800, - 0x0010106b, 0x4a03a005, 0x30000000, 0x59d00006, - 0x4a03a005, 0x30000000, 0x59900006, 0x82000500, - 0xffff0000, 0x48032006, 0x59d00005, 0x8c000504, - 0x040207fe, 0x42000800, 0x00007600, 0x83180540, - 0x60000000, 0x480008a1, 0x811800dc, 0x59c80840, - 0x80040540, 0x48039040, 0x82000540, 0x00003000, - 0x48039040, 0x59c80040, 0x82000500, 0x00003000, - 0x040207fd, 0x0201f800, 0x001010b8, 0x83180400, - 0x00106df6, 0x50000000, 0x48038804, 0x80000580, - 0x4df00000, 0x0201f800, 0x00105d9b, 0x5c03e000, - 0x5c001000, 0x5c000800, 0x480b8808, 0x48079040, - 0x1c01f000, 0x4803c856, 0x59c80840, 0x82040540, - 0x00000010, 0x48039040, 0x59c41008, 0x82080500, - 0xffffff7f, 0x48038808, 0x4c040000, 0x4c080000, - 0x59c40004, 0x82000500, 0x00000003, 0x04020010, - 0x59c40004, 0x82000500, 0x0000000c, 0x04000005, - 0x4a038804, 0x0000000c, 0x8c000504, 0x0401f025, - 0x59c80040, 0x8400056e, 0x48039040, 0x59c80040, - 0x8c00052e, 0x040207fe, 0x0401f01e, 0x4a038803, - 0x00000008, 0x59c40003, 0x82000500, 0x00000003, - 0x040007fd, 0x8c000502, 0x04020006, 0x59c40004, - 0x4a038804, 0x0000000c, 0x8c000504, 0x0401f011, - 0x59c80040, 0x8400056a, 0x48039040, 0x59c80040, - 0x8c00052a, 0x040207fe, 0x59c40005, 0x82000500, - 0xc0000000, 0x04000007, 0x59c400a3, 0x84000540, - 0x480388a3, 0x4a038805, 0xc0000000, 0x80000580, - 0x497b2807, 0x5c001000, 0x5c000800, 0x480b8808, - 0x48079040, 0x1c01f000, 0x5c000000, 0x4c000000, - 0x4803c857, 0x491bc857, 0x4933c857, 0x4d900000, - 0x4dd00000, 0x4da40000, 0x4d140000, 0x0401fdd1, - 0x4df00000, 0x0401fa72, 0x59900004, 0x800001c0, - 0x04000011, 0x81300580, 0x0402000f, 0x59300004, - 0x84000520, 0x48026004, 0x0401ff4d, 0x04020009, - 0x5c03e000, 0x04000db9, 0x80000580, 0x5c022800, - 0x5c034800, 0x5c03a000, 0x5c032000, 0x1c01f000, - 0x0401fcf1, 0x42027000, 0x00000049, 0x59300004, - 0x84000520, 0x48026004, 0x8c00050c, 0x02020800, - 0x000208d8, 0x5c03e000, 0x04000da8, 0x82000540, - 0x00000001, 0x5c022800, 0x5c034800, 0x5c03a000, - 0x5c032000, 0x1c01f000, 0x4933c857, 0x0401fda9, - 0x4df00000, 0x598c000d, 0x80026540, 0x04000012, - 0x59300004, 0x84000520, 0x48026004, 0x0401ff86, - 0x04000017, 0x0401fd09, 0x42027000, 0x00000013, - 0x59300004, 0x8c00050c, 0x02020800, 0x000208d8, - 0x5c03e000, 0x04000d8d, 0x82000540, 0x00000001, - 0x1c01f000, 0x836c1580, 0x00000001, 0x040007f9, - 0x836c1580, 0x00000004, 0x040007f6, 0x42001000, - 0x00103f62, 0x0201f800, 0x00105cc9, 0x5c03e000, - 0x04000d7e, 0x80000580, 0x1c01f000, 0x4d300000, - 0x4d180000, 0x4d3c0000, 0x0401fd82, 0x4df00000, - 0x4a0378e4, 0x0000000f, 0x0401fa02, 0x417a3000, - 0x59926004, 0x813261c0, 0x04000010, 0x417a7800, - 0x0201f800, 0x00104728, 0x0400000a, 0x59300c06, - 0x82040580, 0x00000003, 0x04000004, 0x82040580, - 0x00000006, 0x04020003, 0x42027800, 0x00000002, - 0x0201f800, 0x00108997, 0x811a3000, 0x83180480, - 0x00000005, 0x040017eb, 0x42000800, 0x00000040, - 0x0201f800, 0x00101395, 0x4a0378e4, 0x0000000a, - 0x5c03e000, 0x04000d55, 0x5c027800, 0x5c023000, - 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000, - 0x0401fd58, 0x4df00000, 0x59c80840, 0x82040540, - 0x00000010, 0x48039040, 0x59c41008, 0x82080500, - 0xffffff7f, 0x48038808, 0x4c040000, 0x4c080000, - 0x42001000, 0x00000003, 0x0401f9c5, 0x598e600d, - 0x813261c0, 0x04020f9d, 0x040009ca, 0x497b2807, - 0x0401f80a, 0x5c001000, 0x5c000800, 0x480b8808, - 0x84040d74, 0x48079040, 0x5c03e000, 0x04000d33, - 0x5c026000, 0x1c01f000, 0x4d380000, 0x4d180000, - 0x4d300000, 0x4d900000, 0x4dd00000, 0x4da40000, - 0x4d140000, 0x59c41004, 0x480bc857, 0x82080500, - 0x00003ff0, 0x04000025, 0x417a3000, 0x4c080000, - 0x0201f800, 0x00105d9b, 0x5c001000, 0x82080500, - 0x00000210, 0x04020004, 0x811a3000, 0x80081102, - 0x0401f7f7, 0x0401f9c6, 0x59926004, 0x4933c857, - 0x813261c0, 0x04020005, 0x59c400a3, 0x8c00051a, - 0x02000800, 0x00100615, 0x0401fea1, 0x04000009, - 0x0401fc4d, 0x42027000, 0x00000049, 0x59300004, - 0x8c00050c, 0x02020800, 0x000208d8, 0x0401f007, - 0x42027000, 0x0000004a, 0x4a026203, 0x00000003, - 0x0201f800, 0x000208d8, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x5c026000, 0x5c023000, - 0x5c027000, 0x1c01f000, 0x4d300000, 0x4d180000, - 0x4d900000, 0x0401fcff, 0x42001000, 0x00000000, - 0x598c0000, 0x82000580, 0x00000005, 0x04000974, - 0x417a3000, 0x811b20c8, 0x83932400, 0x0000bf32, - 0x59900001, 0x82000580, 0x00000001, 0x0402000d, - 0x42000800, 0x000007d0, 0x59926004, 0x59300011, - 0x82000500, 0xfff00000, 0x80000540, 0x04000003, - 0x42000800, 0x00001b58, 0x0201f800, 0x00105d8d, - 0x811a3000, 0x83180480, 0x00000005, 0x040017ea, - 0x59c81040, 0x84081534, 0x480b9040, 0x0401fcd3, - 0x5c032000, 0x5c023000, 0x5c026000, 0x1c01f000, - 0x4933c857, 0x4d900000, 0x4dd00000, 0x4da40000, - 0x4d140000, 0x4d380000, 0x0401fcd2, 0x4df00000, - 0x59300004, 0x8c00053e, 0x04020007, 0x8c000520, - 0x04000026, 0x0201f800, 0x001068a3, 0x04000023, - 0x0401f02b, 0x598c000d, 0x81300580, 0x04000012, - 0x0201f800, 0x00108a8a, 0x04020025, 0x0401f91b, - 0x04000023, 0x48038804, 0x0401f961, 0x0201f800, - 0x001010ca, 0x0201f800, 0x001068c1, 0x42027000, - 0x00000049, 0x59300004, 0x8c00050c, 0x0402000d, - 0x0401f00e, 0x59c40004, 0x8c000504, 0x04000014, - 0x4a038804, 0x00000004, 0x0401fc18, 0x42027000, - 0x00000013, 0x59300004, 0x8c00050c, 0x04000003, - 0x0201f800, 0x000208d8, 0x5c03e000, 0x04000c9b, - 0x5c027000, 0x5c022800, 0x5c034800, 0x5c03a000, - 0x5c032000, 0x80000580, 0x1c01f000, 0x5c03e000, - 0x04000c92, 0x5c027000, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x82000540, 0x00000001, - 0x1c01f000, 0x497b2807, 0x0401fc92, 0x59c400af, - 0x800001c0, 0x04020004, 0x0401fc84, 0x0201f000, - 0x00101565, 0x598c000f, 0x82001480, 0x00000002, - 0x04021007, 0x80000000, 0x4803180f, 0x80000580, - 0x0201f800, 0x00105d86, 0x0400000e, 0x0401fed7, - 0x0402000c, 0x0401fdc5, 0x0400000a, 0x0201f800, - 0x0010a7ee, 0x0401f918, 0x4d380000, 0x42027000, - 0x00000014, 0x0201f800, 0x000208d8, 0x5c027000, - 0x0401fc6a, 0x0201f000, 0x00101565, 0x4d900000, - 0x4dd00000, 0x4da40000, 0x4d140000, 0x4d300000, - 0x0201f800, 0x00105d9b, 0x0401fc6a, 0x59c400af, - 0x800001c0, 0x04000027, 0x0401f909, 0x59926004, - 0x4933c857, 0x59300004, 0x8c000516, 0x0400000b, - 0x0401fe86, 0x0402001f, 0x0201f800, 0x001068c1, - 0x0401fc52, 0x42000800, 0x80000804, 0x0201f800, - 0x00106466, 0x0401f017, 0x42001800, 0x00007530, - 0x0401f8c3, 0x04020004, 0x0201f800, 0x00105d8b, - 0x0401f010, 0x0401fe75, 0x0402000e, 0x0201f800, - 0x0010a7ee, 0x59300004, 0x8c00050c, 0x04020003, - 0x4a026203, 0x00000003, 0x4d380000, 0x42027000, - 0x0000004a, 0x0201f800, 0x000208d8, 0x5c027000, - 0x0401fc36, 0x5c026000, 0x5c022800, 0x5c034800, - 0x5c03a000, 0x5c032000, 0x0201f000, 0x00101565, - 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000, - 0x4d300000, 0x4d2c0000, 0x0401fc32, 0x0401f8d4, - 0x59926004, 0x4933c857, 0x0401f882, 0x04000016, - 0x0201f800, 0x00105d9b, 0x813261c0, 0x04000034, - 0x59325808, 0x812e59c0, 0x02000800, 0x00100615, - 0x0201f800, 0x00104e0d, 0x0402001d, 0x592c0208, - 0x84000550, 0x48025a08, 0x0201f800, 0x00104f29, - 0x04020027, 0x592c0208, 0x84000510, 0x48025a08, - 0x0401f023, 0x0201f800, 0x00105d8b, 0x0401f020, - 0x0201f800, 0x0010a7ee, 0x0401fd99, 0x592c0208, - 0x84000550, 0x48025a08, 0x4d380000, 0x42027000, - 0x0000004a, 0x4a026203, 0x00000003, 0x0201f800, - 0x000208d8, 0x5c027000, 0x0401f011, 0x59900006, - 0x82000500, 0xffff0000, 0x040207ee, 0x59c408af, - 0x82040480, 0x000003e8, 0x040217ea, 0x59900006, - 0x82000400, 0x00010000, 0x48032006, 0x0201f800, - 0x00105d8b, 0x0201f800, 0x00103f37, 0x5c025800, - 0x5c026000, 0x5c022800, 0x5c034800, 0x5c03a000, - 0x5c032000, 0x0201f000, 0x00106982, 0x4d300000, - 0x4d2c0000, 0x0201f800, 0x0010698c, 0x598e600d, - 0x4933c857, 0x59c41004, 0x8c081500, 0x04000007, - 0x0201f800, 0x00104e0d, 0x04020007, 0x0201f800, - 0x00104f29, 0x0402002f, 0x0201f800, 0x00105d86, - 0x0401f02c, 0x598c000f, 0x80000540, 0x04020011, - 0x59c408af, 0x82040480, 0x000003e8, 0x0402100d, - 0x598c080f, 0x80040800, 0x4807180f, 0x0201f800, - 0x00105d86, 0x42000000, 0x0010b650, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00103f37, 0x0401f019, - 0x0401fdad, 0x813261c0, 0x04020003, 0x0401f849, - 0x0401f014, 0x0201f800, 0x0010a7ee, 0x59300406, - 0x82000580, 0x00000003, 0x04020007, 0x59325808, - 0x812e59c0, 0x04000004, 0x592c0208, 0x84000550, - 0x48025a08, 0x0401f854, 0x4d380000, 0x42027000, - 0x00000014, 0x0201f800, 0x000208d8, 0x5c027000, - 0x5c025800, 0x5c026000, 0x0201f000, 0x00106982, - 0x59c40804, 0x83180400, 0x00106dec, 0x50000000, - 0x80040500, 0x1c01f000, 0x59c40804, 0x83180400, - 0x00106df1, 0x50000000, 0x80040500, 0x1c01f000, - 0x00000210, 0x00000420, 0x00000840, 0x00001080, - 0x00002100, 0x00004000, 0x00008000, 0x00010000, - 0x00020000, 0x00040000, 0x00080000, 0x00100000, - 0x00200000, 0x00400000, 0x00800000, 0x59900806, - 0x80040120, 0x800c0480, 0x04021004, 0x82000540, - 0x00000001, 0x0401f005, 0x82040c00, 0x00010000, - 0x48072006, 0x80000580, 0x1c01f000, 0x480bc857, - 0x0201f800, 0x0010698c, 0x4df00000, 0x480b1800, - 0x5c03e000, 0x02000800, 0x00106982, 0x1c01f000, - 0x4803c856, 0x0201f800, 0x0010698c, 0x4df00000, - 0x497b180d, 0x497b1803, 0x497b180e, 0x497b180f, - 0x497b1810, 0x598c0000, 0x82000580, 0x00000003, - 0x04000009, 0x836c0580, 0x00000002, 0x04020004, - 0x4a031800, 0x00000005, 0x0401f003, 0x4a031800, - 0x00000000, 0x5c03e000, 0x02000800, 0x00106982, - 0x1c01f000, 0x59300004, 0x8c00050c, 0x04020003, - 0x4a026203, 0x00000001, 0x1c01f000, 0x83180480, - 0x00000005, 0x02021800, 0x00100615, 0x491bc857, - 0x811b20c8, 0x83932400, 0x0000bf32, 0x811ba0ca, - 0x83d3a400, 0x00007600, 0x83180400, 0x00106e41, - 0x50034800, 0x811a28c2, 0x83162c00, 0x00006100, - 0x1c01f000, 0x0010b559, 0x0010b570, 0x0010b587, - 0x0010b59e, 0x0010b5b5, 0x4933c857, 0x59300406, - 0x82000c80, 0x00000012, 0x04021016, 0x4803c857, - 0x04011000, 0x0c01f001, 0x00106e60, 0x00106f03, - 0x00107249, 0x001072cf, 0x00106f03, 0x00107249, - 0x001072cf, 0x00106e60, 0x00106f03, 0x00106e60, - 0x00106e60, 0x00106e60, 0x00106e60, 0x00106e60, - 0x00106e60, 0x00106e60, 0x00106e66, 0x00106e66, - 0x0201f800, 0x0010698c, 0x0201f800, 0x001068f6, - 0x0201f000, 0x00106982, 0x42001000, 0x0010b5f4, - 0x50081000, 0x4930100c, 0x58080002, 0x82000580, - 0x00000100, 0x0402003e, 0x59325808, 0x812e59c0, - 0x02000800, 0x00100615, 0x59326809, 0x813669c0, - 0x04000025, 0x592c040b, 0x82000500, 0x0000e000, - 0x04000003, 0x0401fbc9, 0x0401f002, 0x0401fbb9, - 0x592c000d, 0x82000500, 0x00000003, 0x04000007, - 0x82000580, 0x00000003, 0x80000000, 0x58d00802, - 0x80040540, 0x4801a002, 0x42001000, 0x0010b5f4, - 0x50081000, 0x4930100b, 0x492c100a, 0x82d00400, - 0x00000006, 0x48001003, 0x592c000d, 0x82000400, - 0x00000003, 0x80000104, 0x48001004, 0x592c000e, - 0x48001007, 0x592c000f, 0x48001008, 0x0201f000, - 0x001008a1, 0x42026800, 0x0010bc0c, 0x592c080a, - 0x48066802, 0x82040500, 0x00ffff00, 0x04000007, - 0x497a6a12, 0x59a81010, 0x82081500, 0x00ffff00, - 0x80080580, 0x040207d0, 0x82040d00, 0x000000ff, - 0x800408d0, 0x48066a12, 0x0401f7cb, 0x1c01f000, - 0x4d2c0000, 0x4d300000, 0x4c580000, 0x4c540000, - 0x4c500000, 0x5832580a, 0x812e59c0, 0x02000800, - 0x00100615, 0x58300002, 0x4a006002, 0x00000100, - 0x82000580, 0x00000100, 0x04020020, 0x5830000b, - 0x5832600c, 0x81300580, 0x04020012, 0x0401f82f, - 0x04020014, 0x592c080d, 0x82040c00, 0x00000003, - 0x80040904, 0x4004b000, 0x4200a000, 0x0010b349, - 0x4050a800, 0x0201f800, 0x0010a94f, 0x42001000, - 0x0000dc00, 0x0201f800, 0x0010763b, 0x0401f005, - 0x4803c857, 0x4933c857, 0x0401f81c, 0x04000f93, - 0x5c00a000, 0x5c00a800, 0x5c00b000, 0x5c026000, - 0x5c025800, 0x1c01f000, 0x5830000b, 0x5832600c, - 0x4803c857, 0x4933c857, 0x81300580, 0x040207f1, - 0x0401f80e, 0x040207f3, 0x4803c857, 0x0201f800, - 0x00106619, 0x02020800, 0x00100615, 0x4a025a06, - 0x00000002, 0x0201f800, 0x00020381, 0x0201f800, - 0x00107698, 0x0401f7e7, 0x0201f800, 0x0010698c, - 0x4df00000, 0x598c000d, 0x81300580, 0x04020009, - 0x598c0005, 0x81300580, 0x04020006, 0x5c03e000, - 0x02000800, 0x00106982, 0x80000580, 0x1c01f000, - 0x4803c857, 0x5c03e000, 0x02000800, 0x00106982, - 0x82000540, 0x00000001, 0x1c01f000, 0x59300403, - 0x82000c80, 0x00000056, 0x02021800, 0x00100615, - 0x4803c857, 0x0c01f001, 0x0010707a, 0x00107095, - 0x001070a6, 0x001071a9, 0x00107169, 0x0010716d, - 0x0010717e, 0x00107192, 0x00107187, 0x00107192, - 0x001071cd, 0x00107192, 0x0010720f, 0x00107192, - 0x0010721d, 0x00107192, 0x00107187, 0x00107192, - 0x00107221, 0x00106f60, 0x00106f60, 0x00106f60, - 0x00106f60, 0x00106f60, 0x00106f60, 0x00106f60, - 0x00106f60, 0x00106f60, 0x00106f60, 0x00106f60, - 0x001072ed, 0x0010730c, 0x00107316, 0x00106f60, - 0x0010732c, 0x0010717e, 0x00106f60, 0x0010717e, - 0x00107192, 0x00106f60, 0x001070a6, 0x001071a9, - 0x00106f60, 0x0010737c, 0x00107192, 0x00106f60, - 0x0010738c, 0x00107192, 0x00106f60, 0x00107187, - 0x0010706b, 0x00106f62, 0x00106f60, 0x001073a3, - 0x001073dc, 0x00107456, 0x00106f60, 0x00107466, - 0x0010717c, 0x00107459, 0x00106f60, 0x00107338, - 0x0010747f, 0x00106f60, 0x001074b4, 0x00107507, - 0x00106f60, 0x00106f77, 0x00106fdd, 0x00106fea, - 0x00106f60, 0x0010717e, 0x00106f60, 0x00107031, - 0x0010703c, 0x00106f60, 0x00106f60, 0x00106f8b, - 0x00106fb0, 0x00107546, 0x00107587, 0x001075ad, - 0x00106f60, 0x00106f60, 0x00106f60, 0x0010757b, - 0x0201f800, 0x00100615, 0x0401fad2, 0x59325808, - 0x592c0009, 0x4801a006, 0x592c000a, 0x4801a007, - 0x592c000b, 0x4801a008, 0x592c000c, 0x4801a009, - 0x592c000d, 0x4801a00a, 0x4979a00b, 0x592c0809, - 0x82040d00, 0x00000fff, 0x80040904, 0x42001000, - 0x0000dc00, 0x0201f000, 0x0010763b, 0x4a026202, - 0x0000ffff, 0x0401fabb, 0x4d2c0000, 0x4a01a006, - 0x05000000, 0x59325808, 0x592c0009, 0x4801a007, - 0x592c000a, 0x4801a008, 0x592c000b, 0x4801a009, - 0x42000800, 0x00000004, 0x42001000, 0x0000dc00, - 0x5c025800, 0x0201f000, 0x0010763b, 0x4c580000, - 0x4c500000, 0x4c540000, 0x4d2c0000, 0x0401faa5, - 0x59325808, 0x5930040b, 0x800000c2, 0x4200a800, - 0x0010b349, 0x592cb205, 0x832ca400, 0x00000006, - 0x0201f800, 0x0010a93e, 0x40580000, 0x8054ac00, - 0x592c0001, 0x80000540, 0x04000003, 0x40025800, - 0x0401f7f5, 0x4200a000, 0x0010b349, 0x4050a800, - 0x5930b40b, 0x0201f800, 0x0010a94f, 0x59300c0b, - 0x42001000, 0x0000dc00, 0x5c025800, 0x5c00a800, - 0x5c00b000, 0x5c00a000, 0x0201f000, 0x0010763b, - 0x4c580000, 0x4c500000, 0x4c540000, 0x4d2c0000, - 0x42034800, 0x0010b342, 0x0401fa8c, 0x59325808, - 0x592c0802, 0x4807c857, 0x40041000, 0x80040904, - 0x82081500, 0x00000003, 0x04000008, 0x80040800, - 0x82081580, 0x00000003, 0x80081000, 0x58d00002, - 0x80080540, 0x4801a002, 0x4a025805, 0x02000000, - 0x82d0ac00, 0x00000006, 0x592cb011, 0x832ca400, - 0x00000005, 0x0201f800, 0x0010a93e, 0x40580000, - 0x8054ac00, 0x592e5801, 0x41780000, 0x812e5d40, - 0x040207f6, 0x42001000, 0x0000dc00, 0x5c025800, - 0x5c00a800, 0x5c00b000, 0x5c00a000, 0x0201f000, - 0x0010763b, 0x0401fa57, 0x4a01a006, 0x78000000, - 0x5930001c, 0x840001c0, 0x4801a407, 0x4979a207, - 0x42000800, 0x00000002, 0x42001000, 0x0000dc00, - 0x0201f000, 0x0010763b, 0x4c580000, 0x4c540000, - 0x4c500000, 0x0401fa55, 0x4a01a006, 0x02000000, - 0x59a80002, 0x4801a008, 0x59a80003, 0x4801a009, - 0x59a80000, 0x4801a00a, 0x59a80001, 0x4801a00b, - 0x5930001c, 0x82000d80, 0x0000e000, 0x04000016, - 0x82000d80, 0x0000df00, 0x04000006, 0x4a01a407, - 0x00000010, 0x42000800, 0x00000006, 0x0401f027, - 0x4a03c840, 0x0010b2e7, 0x4a03c842, 0x0000000d, - 0x42001800, 0x0010b2e7, 0x0201f800, 0x001007f5, - 0x42000000, 0x0000df00, 0x4200a000, 0x0010b2e7, - 0x0401f00d, 0x4a03c840, 0x0010b2f4, 0x4a03c842, - 0x0000000d, 0x42001800, 0x0010b2f4, 0x0201f800, - 0x001007f5, 0x42000000, 0x0000e000, 0x4200a000, - 0x0010b2f4, 0x82000540, 0x00000010, 0x4801a407, - 0x4a01a207, 0x00000034, 0x4200b000, 0x0000000d, - 0x82d0ac00, 0x0000000c, 0x0201f800, 0x0010a93e, - 0x42000800, 0x00000013, 0x42001000, 0x0000dc00, - 0x5c00a000, 0x5c00a800, 0x5c00b000, 0x0201f000, - 0x0010763b, 0x0401fa03, 0x4a01a006, 0x63000028, - 0x5930001c, 0x4801a007, 0x42000800, 0x00000002, - 0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b, - 0x0401fa06, 0x41780000, 0x41780800, 0x42002000, - 0x00080000, 0x0c01f81b, 0x80000000, 0x80040800, - 0x42001000, 0x0000000c, 0x59841802, 0x8c0c1d00, - 0x04020008, 0x42002000, 0x00050000, 0x0c01f811, - 0x80000000, 0x80040800, 0x82081400, 0x00000004, - 0x82080540, 0x02000000, 0x4801a006, 0x800408e0, - 0x5930001c, 0x80040540, 0x4801a007, 0x80080904, - 0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b, - 0x00107061, 0x00107063, 0x00107065, 0x00107067, - 0x00107069, 0x4811a008, 0x1c01f000, 0x4811a009, - 0x1c01f000, 0x4811a00a, 0x1c01f000, 0x4811a00b, - 0x1c01f000, 0x4811a00c, 0x1c01f000, 0x4a026009, - 0x0010bc0c, 0x59a80010, 0x82000500, 0x000000ff, - 0x800000d0, 0x42026800, 0x0010bc0c, 0x48026a12, - 0x0401fa3c, 0x41780800, 0x42001000, 0x00005c00, - 0x0201f000, 0x0010763b, 0x0401f9ba, 0x4a01a006, - 0x52000000, 0x4979a007, 0x599c0017, 0x8c000500, - 0x04000005, 0x599c0402, 0x0201f800, 0x00101644, - 0x4805a007, 0x59a80002, 0x4801a008, 0x59a80003, - 0x4801a009, 0x59a80000, 0x4801a00a, 0x59a80001, - 0x4801a00b, 0x59a80010, 0x4801a00c, 0x42000800, - 0x00000007, 0x42001000, 0x0000dc00, 0x0201f000, - 0x0010763b, 0x4a026202, 0x0000ffff, 0x0401f99d, - 0x4a01a006, 0x05000000, 0x59a80010, 0x4801a007, - 0x59a80002, 0x59a80803, 0x4801a008, 0x4805a009, - 0x42000800, 0x00000004, 0x42001000, 0x0000dc00, - 0x0201f000, 0x0010763b, 0x4a026202, 0x0000ffff, - 0x0401f98c, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x00104745, 0x5c027800, 0x4a01a006, 0x03000000, - 0x59340403, 0x82000580, 0x000007fe, 0x0402006e, - 0x4a01a006, 0x04000000, 0x81a40800, 0x4a000800, - 0x22fffffe, 0x5934000a, 0x84000500, 0x4802680a, - 0x59c41002, 0x8408150c, 0x480b8802, 0x59a80026, - 0x8c000508, 0x04000010, 0x59a8002a, 0x4801a007, - 0x59a8002b, 0x82000500, 0xffff2000, 0x599c0818, - 0x8c040d16, 0x04000002, 0x8400056a, 0x4801a008, - 0x4a01a009, 0x00002710, 0x59a8002d, 0x4801a00a, - 0x0401f039, 0x59a8002a, 0x4801a007, 0x0201f800, - 0x00104e0d, 0x04020009, 0x497b8880, 0x82000500, - 0x0000ffff, 0x4c000000, 0x0201f800, 0x00101670, - 0x5c000000, 0x48038880, 0x59a8002b, 0x0201f800, - 0x00104e0d, 0x04020004, 0x82000500, 0x37ffffff, - 0x0401f003, 0x82000500, 0x3fffffff, 0x599c0818, - 0x8c040d16, 0x04000002, 0x8400056a, 0x59a80805, - 0x8c040d10, 0x04000019, 0x59300c03, 0x82041580, - 0x00000051, 0x04000015, 0x82041580, 0x00000031, - 0x04000012, 0x4c580000, 0x4c500000, 0x4c540000, - 0x4200b000, 0x00000004, 0x4200a000, 0x0010b6f9, - 0x82d0ac00, 0x0000001f, 0x4c000000, 0x0201f800, - 0x0010a93e, 0x5c000000, 0x5c00a800, 0x5c00a000, - 0x5c00b000, 0x8400057a, 0x4801a008, 0x4979a009, - 0x4979a00a, 0x59a80002, 0x59a80803, 0x4801a00b, - 0x4805a00c, 0x59a80000, 0x59a80801, 0x4801a00d, - 0x4805a00e, 0x4979a00f, 0x4979a010, 0x4979a011, - 0x4979a012, 0x4979a013, 0x4979a014, 0x4979a015, - 0x4979a016, 0x59a8002e, 0x84000576, 0x4801a017, - 0x59a8002f, 0x4801a018, 0x4979a019, 0x4979a01a, - 0x0401f043, 0x59a80026, 0x8c000508, 0x0400000d, - 0x59a8002a, 0x82000500, 0x0000ffff, 0x59c40880, - 0x80040d80, 0x04000007, 0x497b8880, 0x4c000000, - 0x0201f800, 0x00101670, 0x5c000000, 0x48038880, - 0x59a8002a, 0x4801a007, 0x4c640000, 0x4d2c0000, - 0x59a8c82b, 0x0201f800, 0x00108df4, 0x0400000d, - 0x0201f800, 0x00109360, 0x0402000a, 0x592c0207, - 0x8c00050e, 0x04000007, 0x8264cd00, 0x0000ffff, - 0x592c0009, 0x82000500, 0xffff0000, 0x8064cd40, - 0x4865a008, 0x5c025800, 0x5c00c800, 0x59a8002c, - 0x4801a009, 0x59a8002d, 0x4801a00a, 0x59a80002, - 0x59a80803, 0x4801a00b, 0x4805a00c, 0x59a80000, - 0x59a80801, 0x4801a00d, 0x4805a00e, 0x4979a00f, - 0x4979a010, 0x4979a011, 0x4979a012, 0x4979a013, - 0x4979a014, 0x4979a015, 0x4979a016, 0x59a8002e, - 0x4801a017, 0x59a8002f, 0x4801a018, 0x59a80030, - 0x4801a019, 0x59a80031, 0x4801a01a, 0x42000800, - 0x0000001d, 0x42001000, 0x0000dc00, 0x0201f000, - 0x0010763b, 0x0401f8cb, 0x4a01a006, 0x50000000, - 0x0401f7b5, 0x0401f8c7, 0x4a01a406, 0x21000010, - 0x4a01a206, 0x00000014, 0x4979a007, 0x4979a008, - 0x4979a009, 0x4979a00a, 0x42000800, 0x00000005, - 0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b, - 0x0401f8bf, 0x0401f002, 0x0401f8c4, 0x4a01a006, - 0x02000000, 0x42000800, 0x00000001, 0x42001000, - 0x0000dc00, 0x0201f000, 0x0010763b, 0x0401f8bb, - 0x4a01a006, 0x02000000, 0x59300403, 0x82000580, - 0x00000031, 0x04020794, 0x81a40800, 0x4a000801, - 0x00fffffe, 0x0401f72b, 0x0401f8b0, 0x4a01a006, - 0x01000000, 0x5930041a, 0x80000540, 0x04000003, - 0x4801a407, 0x0401f003, 0x4a01a407, 0x00000003, - 0x5930021a, 0x80000540, 0x04000003, 0x4801a207, - 0x0401f003, 0x4a01a207, 0x00002a00, 0x42000800, - 0x00000002, 0x42001000, 0x0000dc00, 0x0201f000, - 0x0010763b, 0x4a026202, 0x0000ffff, 0x0401f889, - 0x4a01a406, 0x00002010, 0x4a01a206, 0x00000014, - 0x4a01a407, 0x00000800, 0x4a01a207, 0x00002000, - 0x80000580, 0x599c0817, 0x8c040d0a, 0x04020003, - 0x82000540, 0x00000020, 0x8c040d08, 0x04000003, - 0x82000540, 0x00000010, 0x82000540, 0x00000002, - 0x5934080a, 0x8c040d14, 0x04000005, 0x82040d00, - 0x00000380, 0x80040540, 0x0401f006, 0x599c0818, - 0x8c040d18, 0x04000003, 0x82000540, 0x00000380, - 0x0401f03c, 0x0401f875, 0x4a01a406, 0x00000210, - 0x4a01a206, 0x00000014, 0x4a01a407, 0x00000800, - 0x5934000a, 0x8c000516, 0x04000014, 0x59340c05, - 0x82040500, 0x00000030, 0x04000013, 0x59340a05, - 0x82040500, 0x0000c000, 0x04020009, 0x8c040d1a, - 0x04000004, 0x4a01a207, 0x00002100, 0x0401f00c, - 0x4a01a207, 0x00000100, 0x0401f009, 0x4a01a207, - 0x00000400, 0x0401f006, 0x4a01a207, 0x00000700, - 0x0401f003, 0x4a01a207, 0x00000800, 0x80000580, - 0x599c0817, 0x8c040d0a, 0x04020003, 0x82000540, - 0x00000020, 0x8c040d08, 0x04000003, 0x82000540, - 0x00000010, 0x82000540, 0x00000002, 0x59340a00, - 0x8c040d0e, 0x0400000b, 0x84000550, 0x599c1017, - 0x8c08150a, 0x04020004, 0x8c040d0a, 0x04000002, - 0x8400054e, 0x8c040d1c, 0x04000002, 0x84000552, - 0x4801a20a, 0x42000800, 0x00000005, 0x42001000, - 0x0000dc00, 0x0201f000, 0x0010763b, 0x0401f833, - 0x4a01a006, 0x02100014, 0x4a01a007, 0x01000000, - 0x4979a008, 0x4979a009, 0x4979a00a, 0x42000800, - 0x00000005, 0x42001000, 0x0000dc00, 0x0201f000, - 0x0010763b, 0x0401f825, 0x4a01a006, 0x02000000, - 0x0401f65d, 0x4933c857, 0x0401f820, 0x4a01a006, - 0x01000000, 0x4a01a407, 0x0000000b, 0x42000800, - 0x00000002, 0x42001000, 0x0000dc00, 0x0201f000, - 0x0010763b, 0x42005000, 0x32000000, 0x42006000, - 0x08290000, 0x41786800, 0x41787800, 0x0401f3e6, - 0x42005000, 0x22000000, 0x42006000, 0x01290000, - 0x41786800, 0x41787800, 0x0401f3df, 0x42005000, - 0x33000000, 0x42006000, 0x08980000, 0x41786800, - 0x41787800, 0x0401f3d8, 0x42005000, 0x23000000, - 0x42006000, 0x01980000, 0x41786800, 0x41787800, - 0x0401f3d1, 0x59300403, 0x82000c80, 0x00000085, - 0x02001800, 0x00100615, 0x82000c80, 0x00000093, - 0x02021800, 0x00100615, 0x82000480, 0x00000085, - 0x0c01f001, 0x00107263, 0x00107265, 0x00107272, - 0x00107263, 0x00107263, 0x00107263, 0x00107263, - 0x00107263, 0x00107263, 0x00107263, 0x00107263, - 0x00107263, 0x00107263, 0x0010727f, 0x0201f800, - 0x00100615, 0x4933c857, 0x0401f851, 0x5930001c, - 0x4801a004, 0x4801a007, 0x4979a408, 0x4a01a208, - 0x0000ffff, 0x42000800, 0x00000003, 0x42001000, - 0x0000dc00, 0x0401f3ca, 0x4933c857, 0x0401f850, - 0x5930001c, 0x4801a004, 0x4a01a406, 0x00000003, - 0x4a01a206, 0x00000300, 0x42000800, 0x00000001, - 0x42001000, 0x0000dc00, 0x0401f3bd, 0x4d2c0000, - 0x59325808, 0x4933c857, 0x492fc857, 0x812e59c0, - 0x02000800, 0x00100615, 0x59340a12, 0x82040d00, - 0x0000ff00, 0x592c000a, 0x82000500, 0x000000ff, - 0x900001c0, 0x80040540, 0x82000540, 0x00000011, - 0x44034800, 0x81a5a000, 0x42001000, 0x00000009, - 0x42000800, 0x00000003, 0x592c0009, 0x82000500, - 0xff000000, 0x82001d80, 0x84000000, 0x04000009, - 0x82001d80, 0x85000000, 0x02020800, 0x00100615, - 0x42001000, 0x00000007, 0x42000800, 0x00000001, - 0x832c1c00, 0x00000009, 0x500c0000, 0x4401a000, - 0x800c1800, 0x80d1a000, 0x80081040, 0x040207fb, - 0x42001000, 0x0000dc00, 0x5c025800, 0x0401f38c, - 0x42005000, 0x81000000, 0x42006000, 0x00090000, - 0x41786800, 0x41787800, 0x0401f363, 0x42005000, - 0x84000000, 0x42006000, 0x00990000, 0x59300406, - 0x82000580, 0x00000005, 0x04000002, 0x8430652e, - 0x41786800, 0x41787800, 0x0401f357, 0x42005000, - 0x85000000, 0x42006000, 0x00990000, 0x59300406, - 0x82000580, 0x00000005, 0x04000002, 0x8430652e, - 0x41786800, 0x41787800, 0x0401f34b, 0x59300403, - 0x82000c80, 0x00000053, 0x02021800, 0x00100615, - 0x82000480, 0x0000004b, 0x02001800, 0x00100615, - 0x59326809, 0x59368c03, 0x4803c857, 0x0c01f001, - 0x00107353, 0x0010735b, 0x00107363, 0x0010736b, - 0x001072e4, 0x001072e4, 0x001072e4, 0x0010734b, - 0x0201f800, 0x00100615, 0x42005000, 0x06000000, - 0x42006000, 0x08290000, 0x41786800, 0x41787800, - 0x0401f32d, 0x4933c857, 0x0401ff46, 0x4a01a006, - 0x12000000, 0x59300406, 0x82000580, 0x00000004, - 0x04020003, 0x59340002, 0x0401f002, 0x59a80010, - 0x82000500, 0x00ffffff, 0x4801a007, 0x59300419, - 0x4801a408, 0x59300219, 0x4801a208, 0x4979a009, - 0x4979a00a, 0x4979a00b, 0x4979a00c, 0x4979a00d, - 0x4979a00e, 0x4979a00f, 0x4979a010, 0x42000800, - 0x0000000b, 0x42001000, 0x0000dc00, 0x0401f330, - 0x0401ff28, 0x4a01a006, 0x0f000000, 0x5930001c, - 0x4801a007, 0x42000800, 0x00000002, 0x42001000, - 0x0000dc00, 0x0401f326, 0x0401ff2c, 0x4a01a006, - 0x02000000, 0x59c40085, 0x48031004, 0x59880000, - 0x4801a007, 0x59880001, 0x4801a008, 0x59880002, - 0x4801a009, 0x59880003, 0x4801a00a, 0x59880004, - 0x4801a00b, 0x59880005, 0x4801a00c, 0x42000800, - 0x00000007, 0x42001000, 0x0000dc00, 0x0401f310, - 0x4a026202, 0x0000ffff, 0x0401ff06, 0x4a01a006, - 0x62000000, 0x5930001c, 0x4801a007, 0x42000800, - 0x00000002, 0x42001000, 0x0000dc00, 0x0401f304, - 0x0401fefc, 0x59300808, 0x4c500000, 0x4c540000, - 0x4c580000, 0x8204a400, 0x0000000a, 0x5930b01c, - 0x82d0ac00, 0x00000006, 0x0201f800, 0x0010a93e, - 0x5930081c, 0x42001000, 0x0000dc00, 0x5c00b000, - 0x5c00a800, 0x5c00a000, 0x0401f2f1, 0x0401ff9b, - 0x59300017, 0x4801a006, 0x59300018, 0x4801a007, - 0x4a01a008, 0x00001000, 0x0401f020, 0x0401ff93, - 0x59300017, 0x4801a006, 0x59300018, 0x4801a007, - 0x4a01a008, 0x00004000, 0x0401f018, 0x0401ff8b, - 0x59300017, 0x4801a006, 0x59300018, 0x4801a007, - 0x4a01a008, 0x00002000, 0x0401f010, 0x0401ff83, - 0x59300017, 0x4801a006, 0x59300018, 0x4801a007, - 0x4a01a008, 0x00000400, 0x0401f008, 0x0401ff7b, - 0x59300017, 0x4801a006, 0x59300018, 0x4801a007, - 0x4a01a008, 0x00000200, 0x4979a009, 0x4979a00a, - 0x4979a00b, 0x4979a00c, 0x4979a00d, 0x42000800, - 0x00000008, 0x42001000, 0x0000dc00, 0x0401f2c0, - 0x0401fec6, 0x4a01a006, 0x02000014, 0x4979a407, - 0x4979a207, 0x59a8003a, 0x4801a008, 0x59a8003b, - 0x4801a009, 0x4a01a00a, 0x00047878, 0x42000800, - 0x00000005, 0x42001000, 0x0000dc00, 0x0401f2b0, - 0x0401feb6, 0x4a01a006, 0x02140018, 0x4a01a407, - 0x00000800, 0x5930001c, 0x82000d00, 0xff000000, - 0x900409c0, 0x4805a207, 0x82000500, 0x00ffffff, - 0x4801a00a, 0x4979a408, 0x4979a208, 0x4979a409, - 0x4979a209, 0x4979a00b, 0x42000800, 0x00000006, - 0x42001000, 0x0000dc00, 0x0401f299, 0x4933c857, - 0x4937c857, 0x4d380000, 0x4d1c0000, 0x42027000, - 0x00000035, 0x0201f800, 0x00109183, 0x04020022, - 0x0401fe88, 0x4a01a006, 0x13000000, 0x5932381e, - 0x591c0414, 0x8c000502, 0x02000800, 0x00100615, - 0x591c0019, 0x4801a005, 0x591c0406, 0x82000580, - 0x00000003, 0x04000007, 0x59300809, 0x58040002, - 0x82000500, 0x00ffffff, 0x4801a007, 0x0401f003, - 0x59a80010, 0x4801a007, 0x59300419, 0x4801a408, - 0x59300219, 0x4801a208, 0x42000800, 0x00000003, - 0x42001000, 0x0000dc00, 0x5c023800, 0x5c027000, - 0x0401f26f, 0x4803c856, 0x0201f800, 0x0010698c, - 0x598c000d, 0x81300580, 0x02020800, 0x00100615, - 0x0201f800, 0x001068f6, 0x0201f800, 0x000208b4, - 0x5c023800, 0x5c027000, 0x0201f000, 0x00106982, - 0x4803c856, 0x4d2c0000, 0x4d1c0000, 0x5932381e, - 0x811e39c0, 0x02000800, 0x00100615, 0x591c0c06, - 0x82040580, 0x00000006, 0x0400000d, 0x82040580, - 0x00000003, 0x04000036, 0x4a026403, 0x00000037, - 0x4a02641a, 0x00000003, 0x4a02621a, 0x00001700, - 0x5c023800, 0x5c025800, 0x0401f064, 0x0401f84b, - 0x42001000, 0x40000000, 0x591c0203, 0x591c0804, - 0x8c040d3e, 0x04020023, 0x82000c80, 0x0000000e, - 0x0c001003, 0x0201f800, 0x00100615, 0x00107410, - 0x0010741c, 0x00107412, 0x0010741c, 0x00107418, - 0x00107410, 0x00107410, 0x0010741c, 0x0010741c, - 0x00107410, 0x00107410, 0x00107410, 0x00107410, - 0x00107410, 0x0010741c, 0x00107410, 0x0010741c, - 0x0201f800, 0x00100615, 0x591c0414, 0x4803c857, - 0x8c000518, 0x04000003, 0x8c000512, 0x04000003, - 0x80001580, 0x0401f003, 0x42001000, 0x20000000, - 0x591c0015, 0x4801a00a, 0x0401f018, 0x0401f81f, - 0x591e5808, 0x812e59c0, 0x02000800, 0x00100615, - 0x592c100f, 0x591c0011, 0x80080480, 0x4801a00a, - 0x591c0203, 0x591c0804, 0x8c040d3e, 0x04020007, - 0x82000d80, 0x00000002, 0x04000007, 0x82000d80, - 0x00000004, 0x04000004, 0x42001000, 0x40000000, - 0x0401f002, 0x80001580, 0x4809a00b, 0x42000800, - 0x00000006, 0x42001000, 0x0000dc00, 0x5c023800, - 0x5c025800, 0x0401f1fe, 0x4803c856, 0x0401fe03, - 0x4a01a006, 0x02000000, 0x59300c19, 0x4805a407, - 0x59300a19, 0x4805a207, 0x59a81010, 0x59300809, - 0x58041802, 0x820c1d00, 0x00ffffff, 0x5930081e, - 0x58040406, 0x82000580, 0x00000003, 0x04020004, - 0x4809a008, 0x480da009, 0x0401f003, 0x480da008, - 0x4809a009, 0x1c01f000, 0x4803c856, 0x0401fdeb, - 0x0401f003, 0x4803c856, 0x0401fde1, 0x4a01a006, - 0x01000000, 0x5930041a, 0x4801a407, 0x5930021a, - 0x4801a207, 0x42000800, 0x00000002, 0x42001000, - 0x0000dc00, 0x0401f1d6, 0x4803c856, 0x4d1c0000, - 0x0401fdc5, 0x4a01a006, 0x14000000, 0x5932381e, - 0x591c0019, 0x4801a005, 0x59300419, 0x4801a407, - 0x59300219, 0x4801a207, 0x59300015, 0x4801a008, - 0x59300216, 0x82000500, 0x000000ff, 0x840001c0, - 0x4801a409, 0x42000800, 0x00000004, 0x42001000, - 0x0000dc00, 0x5c023800, 0x0401f1bd, 0x4803c856, - 0x0401f80b, 0x5930041a, 0x900001c0, 0x4801a005, - 0x0401f9f4, 0x41780800, 0x42001000, 0x00005c00, - 0x0401f9b3, 0x0201f000, 0x00105d86, 0x4803c856, - 0x59300817, 0x82041c00, 0x00000005, 0x46034800, - 0x00000021, 0x58040404, 0x82000500, 0x0000f000, - 0x82000580, 0x00003000, 0x04000003, 0x46034800, - 0x00000041, 0x81a5a000, 0x580c0001, 0x82000d00, - 0x00ffffff, 0x82040d40, 0xc2000000, 0x4805a000, - 0x580c0800, 0x82041500, 0x00ffffff, 0x82000500, - 0xff000000, 0x80080540, 0x4801a001, 0x580c0002, - 0x82000580, 0x00c00000, 0x82000500, 0x00fd0300, - 0x4801a002, 0x580c0003, 0x4801a003, 0x580c0404, - 0x4801a404, 0x580c0204, 0x4801a204, 0x1c01f000, - 0x4803c856, 0x59a80026, 0x82000500, 0x00000028, - 0x04020009, 0x59a80026, 0x82000500, 0x00000028, - 0x04000003, 0x497a6a12, 0x0401f003, 0x4a026a12, - 0x0000ff00, 0x42005000, 0x22000000, 0x42006000, - 0x01380000, 0x41786800, 0x41787800, 0x0401f952, - 0x59301008, 0x4a01a006, 0x54000000, 0x59a80010, - 0x82000500, 0x00ffffff, 0x58080c0a, 0x800408f0, - 0x80040540, 0x4801a007, 0x5808000a, 0x82000500, - 0xff000000, 0x4801a008, 0x59a80002, 0x4801a009, - 0x59a80003, 0x4801a00a, 0x59a80000, 0x4801a00b, - 0x59a80001, 0x4801a00c, 0x5808000c, 0x9c0001c0, - 0x4801a00d, 0x5808000d, 0x9c0001c0, 0x4801a00e, - 0x5808000e, 0x9c0001c0, 0x4801a00f, 0x5808000f, - 0x9c0001c0, 0x4801a010, 0x58080010, 0x9c0001c0, - 0x4801a011, 0x58080011, 0x9c0001c0, 0x4801a012, - 0x58080012, 0x9c0001c0, 0x4801a013, 0x58080013, - 0x9c0001c0, 0x4801a014, 0x58080010, 0x9c0001c0, - 0x4801a015, 0x58080011, 0x9c0001c0, 0x4801a016, - 0x58080012, 0x9c0001c0, 0x4801a017, 0x58080013, - 0x9c0001c0, 0x4801a018, 0x42000800, 0x00000013, - 0x42001000, 0x0000dc00, 0x0401f135, 0x4803c856, - 0x42005000, 0x22000000, 0x42006000, 0x01290000, - 0x41786800, 0x41787800, 0x0401f90b, 0x59301008, - 0x4a01a006, 0x55000000, 0x5808000b, 0x82000500, - 0x00ffffff, 0x58080c0a, 0x800408f0, 0x80040540, - 0x4801a007, 0x5808080a, 0x82040d00, 0xff000000, - 0x59a80010, 0x82000500, 0x00ffffff, 0x80040540, - 0x4801a008, 0x5808000c, 0x9c0001c0, 0x4801a009, - 0x5808000d, 0x9c0001c0, 0x4801a00a, 0x5808000e, - 0x9c0001c0, 0x4801a00b, 0x5808000f, 0x9c0001c0, - 0x4801a00c, 0x59a80002, 0x4801a00d, 0x59a80003, - 0x4801a00e, 0x59a80000, 0x4801a00f, 0x59a80001, - 0x4801a010, 0x58080010, 0x4801a011, 0x58080011, - 0x4801a012, 0x58080012, 0x4801a013, 0x58080013, - 0x4801a014, 0x4979a015, 0x4979a016, 0x4979a017, - 0x4979a018, 0x42000800, 0x00000013, 0x42001000, - 0x0000dc00, 0x0401f0f6, 0x0401fcfc, 0x5930001c, - 0x800001c0, 0x04000008, 0x4a01a006, 0x01000000, - 0x4a01a407, 0x00000003, 0x42000800, 0x00000002, - 0x0401f028, 0x4a01a006, 0x02000000, 0x41780800, - 0x836c0580, 0x00000004, 0x04020003, 0x84040d42, - 0x0401f00d, 0x0201f800, 0x00104e0d, 0x04020003, - 0x84040d4a, 0x0401f002, 0x84040d48, 0x59a80026, - 0x8c000506, 0x04020003, 0x8c00050a, 0x04000002, - 0x84040d46, 0x4805a207, 0x59c40085, 0x48031004, - 0x4c580000, 0x4c500000, 0x4c540000, 0x4200b000, - 0x00000006, 0x8388a400, 0x00000000, 0x82d0ac00, - 0x00000008, 0x0201f800, 0x0010a93e, 0x5c00a800, - 0x5c00a000, 0x5c00b000, 0x42000800, 0x00000008, - 0x42001000, 0x0000dc00, 0x0401f0c1, 0x0401fcb9, - 0x4a01a006, 0x56000000, 0x59340006, 0x4801a007, - 0x59340007, 0x4801a008, 0x42000800, 0x00000003, - 0x42001000, 0x0000dc00, 0x0401f0b5, 0x4803c856, - 0x0401fcba, 0x5930081c, 0x800409c0, 0x0400000e, - 0x82040580, 0x0000ffff, 0x04000004, 0x82040480, - 0x00000007, 0x04021008, 0x4a01a006, 0x01000000, - 0x4a01a407, 0x00000003, 0x42000800, 0x00000002, - 0x0401f012, 0x4a01a006, 0x0200001c, 0x4a01a007, - 0x00000001, 0x42001000, 0x0010b2ec, 0x50080000, - 0x9c0001c0, 0x4801a009, 0x59a80010, 0x4801a00a, - 0x59a80002, 0x59a80803, 0x4801a00b, 0x4805a00c, - 0x42000800, 0x00000007, 0x42001000, 0x0000dc00, - 0x0401f08f, 0x4d2c0000, 0x0401fc86, 0x59325808, - 0x592c0008, 0x82000500, 0x00ffffff, 0x4801a001, - 0x4a01a006, 0x51000000, 0x5c025800, 0x0201f000, - 0x001070bc, 0x4803c856, 0x59a80810, 0x82040d00, - 0x000000ff, 0x59325808, 0x59326809, 0x59a83026, - 0x8c18350a, 0x04020008, 0x8c00050e, 0x04020006, - 0x80001d80, 0x59a82010, 0x82102500, 0x000000ff, - 0x0401f001, 0x59300406, 0x4803c857, 0x82000d80, - 0x00000009, 0x04000006, 0x82000d80, 0x0000000a, - 0x0400002e, 0x0201f800, 0x00100615, 0x59300015, - 0x8c00051e, 0x04020020, 0x42005000, 0x04000000, - 0x42006000, 0x05000000, 0x592c040a, 0x82000500, - 0x00000030, 0x800000e0, 0x80306540, 0x5934000a, - 0x8c000508, 0x04000002, 0x84306546, 0x41786800, - 0x41787800, 0x0401f831, 0x59300c14, 0x80040000, - 0x48026414, 0x40040000, 0x800000d0, 0x82000540, - 0x00000020, 0x4801a403, 0x83180d40, 0x00000038, - 0x42001000, 0x0000c920, 0x0401f868, 0x0201f000, - 0x00105d8b, 0x59a80026, 0x82000500, 0x00000028, - 0x04000003, 0x497a6a12, 0x0401f7dc, 0x4a026a12, - 0x0000ff00, 0x0401f7d9, 0x42005000, 0x02000000, - 0x42006000, 0x20290000, 0x41786800, 0x41787800, - 0x0401f812, 0x83180d40, 0x00000038, 0x42001000, - 0x0000c9a0, 0x0401f851, 0x42000800, 0x000007d0, - 0x59300011, 0x82000500, 0xfff00000, 0x80000540, - 0x04000003, 0x42000800, 0x00001b58, 0x41781000, - 0x0201f000, 0x00105d8d, 0x4201a000, 0x00000000, - 0x0401f003, 0x4201a000, 0x00000011, 0x59340a12, - 0x82040d00, 0x0000ff00, 0x59a80010, 0x82000500, - 0x000000ff, 0x900001c0, 0x80040540, 0x80d00540, - 0x44034800, 0x81a5a000, 0x59340002, 0x82000500, - 0x00ffffff, 0x80280540, 0x4801a000, 0x59a80010, - 0x4801a001, 0x4831a002, 0x82340540, 0x00000000, - 0x4801a003, 0x59300402, 0x4801a404, 0x59300a02, - 0x4805a204, 0x8c30652e, 0x04000003, 0x4805a404, - 0x4801a204, 0x483da005, 0x1c01f000, 0x4807c857, - 0x4c040000, 0x0401f82a, 0x5c000800, 0x40040000, - 0x80081540, 0x800000c4, 0x82000540, 0x00002000, - 0x4803910a, 0x59b400f6, 0x82000500, 0x00000018, - 0x040207fd, 0x4a0368f0, 0x0010b342, 0x42001800, - 0x0010b343, 0x580c0000, 0x4803c857, 0x580c0002, - 0x4803c857, 0x580c0004, 0x4803c857, 0x4a0368f1, - 0x0010b349, 0x480b68f3, 0x4a0378e4, 0x00008000, - 0x0201f000, 0x00105d86, 0x4807c857, 0x480a2800, - 0x4c040000, 0x0401f80a, 0x5c000800, 0x59b400f6, - 0x8c00050a, 0x040207fe, 0x49a768f2, 0x480768f4, - 0x4a0378e4, 0x00008000, 0x1c01f000, 0x4a0378e4, - 0x0000c000, 0x59bc00e4, 0x8c000520, 0x0400000c, - 0x4a0378e4, 0x00008000, 0x42007000, 0x000003e8, - 0x59bc00e4, 0x8c000520, 0x040007f5, 0x80387040, - 0x02000800, 0x00100615, 0x0401f7fa, 0x1c01f000, - 0x82000500, 0xffff0000, 0x82000580, 0x01050000, - 0x0402000d, 0x599c0818, 0x8c040d10, 0x0400000a, - 0x59a80807, 0x8c040d0a, 0x04000007, 0x42001000, - 0x0000804f, 0x41781800, 0x41782000, 0x0201f800, - 0x00103857, 0x1c01f000, 0x41781000, 0x42026000, - 0x0010cfc0, 0x59a8180e, 0x480a6402, 0x4a026202, - 0x0000ffff, 0x80081000, 0x800c1840, 0x04000004, - 0x83326400, 0x00000024, 0x0401f7f8, 0x1c01f000, - 0x4933c857, 0x59300203, 0x82000580, 0x00000000, - 0x0400002c, 0x59300406, 0x4803c857, 0x82000d80, - 0x00000004, 0x04000011, 0x82000d80, 0x00000001, - 0x0400000e, 0x82000d80, 0x00000003, 0x04000006, - 0x82000d80, 0x00000006, 0x04020011, 0x0201f800, - 0x0010a3fa, 0x5930001c, 0x800001c0, 0x02020800, - 0x0010961a, 0x0401f00a, 0x5930081e, 0x4807c857, - 0x800409c0, 0x04000006, 0x5804001c, 0x4803c857, - 0x81300580, 0x04020002, 0x4978081c, 0x497a6008, - 0x4a026004, 0x00004000, 0x59a80037, 0x82000c80, - 0x00000051, 0x04001002, 0x80000102, 0x48026206, - 0x497a6205, 0x497a6009, 0x4a026406, 0x00000007, - 0x1c01f000, 0x8166c9c0, 0x0400001c, 0x41626000, - 0x41580000, 0x59300a03, 0x82040d80, 0x00000000, - 0x04000008, 0x83326400, 0x00000024, 0x81300c80, - 0x040017f9, 0x42026000, 0x0010cfc0, 0x0401f7f6, - 0x4933c857, 0x8166c840, 0x83300c00, 0x00000024, - 0x80040480, 0x04021006, 0x4006c000, 0x4a026203, - 0x00000008, 0x813261c0, 0x1c01f000, 0x4202c000, - 0x0010cfc0, 0x0401f7fa, 0x42000000, 0x0010b653, - 0x0201f800, 0x0010a86e, 0x4933c856, 0x417a6000, - 0x0401f7f5, 0x4933c857, 0x83380580, 0x00000013, - 0x0402000b, 0x59300004, 0x8c00053e, 0x04000007, - 0x0201f800, 0x0010698c, 0x0201f800, 0x001068f6, - 0x0201f800, 0x00106982, 0x1c01f000, 0x4933c857, - 0x59880053, 0x80000000, 0x48031053, 0x1c01f000, - 0x4933c857, 0x59300203, 0x82003480, 0x0000000e, - 0x02021800, 0x00100615, 0x4d2c0000, 0x0c01f803, - 0x5c025800, 0x1c01f000, 0x00107718, 0x00107c84, - 0x00107dd4, 0x00107718, 0x00107e3a, 0x0010787c, - 0x00107718, 0x00107718, 0x00107c1a, 0x00107718, - 0x00107718, 0x00107718, 0x00107718, 0x00107718, - 0x0201f800, 0x00100615, 0x4933c857, 0x59300203, - 0x82003480, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f001, 0x0010772f, 0x001087f0, 0x0010772f, - 0x0010772f, 0x0010772f, 0x0010772f, 0x0010772f, - 0x0010772f, 0x0010879a, 0x0010880c, 0x0010887a, - 0x0010880c, 0x0010887a, 0x0010772f, 0x0201f800, - 0x00100615, 0x0201f800, 0x00100615, 0x4933c857, - 0x4d2c0000, 0x59325808, 0x59300203, 0x82003480, - 0x0000000e, 0x02021800, 0x00100615, 0x0c01f803, - 0x5c025800, 0x1c01f000, 0x0010774c, 0x0010774c, - 0x0010774c, 0x00107768, 0x001077b4, 0x0010774c, - 0x0010774c, 0x0010774c, 0x0010774e, 0x0010774c, - 0x0010774c, 0x0010774c, 0x0010774c, 0x0010774c, - 0x0201f800, 0x00100615, 0x4933c857, 0x83380580, - 0x00000040, 0x02020800, 0x00100615, 0x4a026007, - 0x00082000, 0x4a026203, 0x00000003, 0x493a6403, - 0x4a025c08, 0x00000001, 0x592c000d, 0x48026011, - 0x497a6013, 0x592c0208, 0x800000c2, 0x800010c4, - 0x80081400, 0x480a6206, 0x0201f800, 0x00100f9c, - 0x42000800, 0x80000060, 0x0201f000, 0x00106466, - 0x4933c857, 0x83380480, 0x00000050, 0x02021800, - 0x00100615, 0x83380480, 0x00000049, 0x02001800, - 0x00100615, 0x0c01f001, 0x0010777b, 0x00107786, - 0x00107779, 0x00107779, 0x00107779, 0x00107779, - 0x00107791, 0x0201f800, 0x00100615, 0x4a026203, - 0x00000004, 0x4a025c08, 0x00000002, 0x592c0207, - 0x48025c09, 0x592c0209, 0x48025a07, 0x592c000c, - 0x4802580d, 0x1c01f000, 0x0201f800, 0x001068c1, - 0x0201f800, 0x00108df4, 0x04000005, 0x4a025a06, - 0x00000006, 0x0201f800, 0x00020381, 0x0201f000, - 0x000208b4, 0x0201f800, 0x001068c1, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42003000, 0x00000014, 0x41782800, 0x42002000, - 0x00000002, 0x4d400000, 0x4d440000, 0x59368c03, - 0x42028000, 0x00000029, 0x0201f800, 0x0010962a, - 0x5c028800, 0x5c028000, 0x42000000, 0x0010b663, - 0x0201f800, 0x0010a86e, 0x0201f800, 0x00108df4, - 0x02000000, 0x000208b4, 0x4a025a06, 0x00000029, - 0x0201f800, 0x00020381, 0x0201f000, 0x000208b4, - 0x4933c857, 0x83380580, 0x00000048, 0x04000005, - 0x83380580, 0x00000053, 0x02020800, 0x00100615, - 0x592c0206, 0x82000580, 0x00000007, 0x04000009, - 0x59300011, 0x80000540, 0x04000006, 0x592c080c, - 0x80040480, 0x4802580c, 0x4a025a06, 0x00000015, - 0x592c0206, 0x80000540, 0x04020003, 0x4a025a06, - 0x00000000, 0x0201f800, 0x00020381, 0x0201f000, - 0x000208b4, 0x4933c857, 0x4d2c0000, 0x4c500000, - 0x4c540000, 0x4c580000, 0x0201f800, 0x0010082a, - 0x02000800, 0x00100615, 0x497a5a06, 0x59a8006e, - 0x82000500, 0x0000f000, 0x48025c07, 0x59a80816, - 0x82040c00, 0x00000018, 0x48065a07, 0x412c7800, - 0x4d2c0000, 0x41cca000, 0x42002800, 0x00000001, - 0x42001000, 0x0000002c, 0x82040480, 0x0000002d, - 0x04021006, 0x832cac00, 0x00000009, 0x0201f800, - 0x0010894a, 0x0401f02e, 0x40043000, 0x42000800, - 0x0000002c, 0x832cac00, 0x00000009, 0x0201f800, - 0x0010894a, 0x82183480, 0x0000002c, 0x0201f800, - 0x0010082a, 0x0400001a, 0x80142800, 0x4a025804, - 0x00000110, 0x492c7801, 0x82180c80, 0x0000003d, - 0x04021007, 0x40180800, 0x832cac00, 0x00000005, - 0x0201f800, 0x0010894a, 0x0401f015, 0x82081400, - 0x0000003c, 0x82183480, 0x0000003c, 0x42000800, - 0x0000003c, 0x412c7800, 0x832cac00, 0x00000005, - 0x0201f800, 0x0010894a, 0x0401f7e5, 0x5c025800, - 0x592c0206, 0x8400055e, 0x48025a06, 0x592c0407, - 0x80080540, 0x48025c07, 0x0401f002, 0x5c025800, - 0x813669c0, 0x04000003, 0x59343403, 0x0401f003, - 0x42003000, 0x0000ffff, 0x49325808, 0x481a5c06, - 0x82100580, 0x00000054, 0x04020002, 0x491e5813, - 0x841401c0, 0x80100540, 0x48025804, 0x592c0001, - 0x497a5801, 0x4c000000, 0x0201f800, 0x00020381, - 0x5c025800, 0x812e59c0, 0x040207f9, 0x5c00b000, - 0x5c00a800, 0x5c00a000, 0x5c025800, 0x1c01f000, - 0x4803c856, 0x4c5c0000, 0x4d2c0000, 0x4c500000, - 0x4c540000, 0x4c580000, 0x412cb800, 0x592c040b, - 0x8c000516, 0x04000003, 0x41cca000, 0x0401f003, - 0x83cca400, 0x00000006, 0x4008b000, 0x41781000, - 0x82580480, 0x00000012, 0x04001004, 0x4200b000, - 0x00000012, 0x40001000, 0x4c080000, 0x4d2c0000, - 0x0201f800, 0x0010082a, 0x04000023, 0x5c001800, - 0x492c1801, 0x485a5800, 0x832cac00, 0x00000002, - 0x0201f800, 0x0010a94f, 0x585c040b, 0x8c000500, - 0x0400000e, 0x832c1400, 0x00000002, 0x8c000516, - 0x04000003, 0x82081400, 0x00000006, 0x46001000, - 0x00000001, 0x80081000, 0x46001000, 0x00000900, - 0x84000500, 0x4800bc0b, 0x5c001000, 0x800811c0, - 0x040207da, 0x82000540, 0x00000001, 0x5c00b000, - 0x5c00a800, 0x5c00a000, 0x5c025800, 0x5c00b800, - 0x1c01f000, 0x5c025800, 0x5c001000, 0x0401f7f8, - 0x4933c857, 0x83380d80, 0x00000015, 0x04020003, - 0x0201f000, 0x000208b4, 0x83380d80, 0x00000016, - 0x02020800, 0x00100615, 0x0201f000, 0x000208b4, - 0x4933c857, 0x4d2c0000, 0x4c500000, 0x4c540000, - 0x4c580000, 0x59325808, 0x83cca400, 0x00000006, - 0x59cc1806, 0x820c0580, 0x01000000, 0x04020004, - 0x4200b000, 0x00000002, 0x0401f00f, 0x4200b000, - 0x00000008, 0x832cac00, 0x00000005, 0x0201f800, - 0x0010a93e, 0x8c0c1d00, 0x0400000b, 0x4200b000, - 0x00000008, 0x592e5801, 0x812e59c0, 0x02000800, - 0x00100615, 0x832cac00, 0x00000005, 0x0201f800, - 0x0010a93e, 0x0401f816, 0x5c00b000, 0x5c00a800, - 0x5c00a000, 0x5c025800, 0x1c01f000, 0x4933c857, - 0x4c500000, 0x4c540000, 0x4c580000, 0x83cca400, - 0x00000006, 0x5930a808, 0x8254ac00, 0x00000005, - 0x4200b000, 0x00000007, 0x0201f800, 0x0010a93e, - 0x5c00b000, 0x5c00a800, 0x5c00a000, 0x4933c857, - 0x0201f800, 0x00108df4, 0x02000000, 0x000208b4, - 0x4d2c0000, 0x0201f800, 0x00109360, 0x0402000b, - 0x41780800, 0x4d400000, 0x42028000, 0x00000000, - 0x0201f800, 0x00109204, 0x5c028000, 0x5c025800, - 0x0201f000, 0x000208b4, 0x5931d821, 0x58ef400b, - 0x58ee580d, 0x4a025a04, 0x00000103, 0x58ec0009, - 0x0801f800, 0x5c025800, 0x0201f000, 0x000208b4, - 0x4933c857, 0x59cc1806, 0x820c0580, 0x02000000, - 0x04020014, 0x4a026802, 0x00fffffd, 0x5934000a, - 0x84000504, 0x4802680a, 0x59300808, 0x800409c0, - 0x02000000, 0x000208b4, 0x4a000a04, 0x00000103, - 0x480c0805, 0x5931d821, 0x58ef400b, 0x58ee580d, - 0x58ec0009, 0x0801f800, 0x0201f000, 0x000208b4, - 0x42000000, 0x0010b66b, 0x0201f800, 0x0010a86e, - 0x4c0c0000, 0x0401f804, 0x5c001800, 0x040207eb, - 0x1c01f000, 0x4933c857, 0x4d2c0000, 0x59325808, - 0x812e59c0, 0x04020009, 0x497a6206, 0x497a6205, - 0x4d380000, 0x42027000, 0x00000022, 0x0401fb77, - 0x5c027000, 0x80000580, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x4d2c0000, 0x4c500000, 0x4c540000, - 0x4c580000, 0x59325808, 0x592e5801, 0x832cac00, - 0x00000005, 0x83cca400, 0x00000006, 0x59a8086e, - 0x82040d00, 0x000003ff, 0x82041480, 0x0000000f, - 0x0400101b, 0x4200b000, 0x0000000f, 0x0201f800, - 0x0010a93e, 0x592e5801, 0x832cac00, 0x00000005, - 0x82080c80, 0x0000000f, 0x0400100d, 0x4200b000, - 0x0000000f, 0x0201f800, 0x0010a93e, 0x592e5801, - 0x832cac00, 0x00000005, 0x82041480, 0x0000000f, - 0x04001007, 0x42001000, 0x0000000f, 0x4008b000, - 0x0201f800, 0x0010a93e, 0x0401f004, 0x4004b000, - 0x0201f800, 0x0010a93e, 0x5931d821, 0x58ef400b, - 0x58ee580d, 0x4a025a04, 0x00000103, 0x592e5801, - 0x58ec0009, 0x0801f800, 0x0201f800, 0x000208b4, - 0x5c00b000, 0x5c00a800, 0x5c00a000, 0x5c025800, - 0x1c01f000, 0x4933c857, 0x4d2c0000, 0x4c500000, - 0x4c540000, 0x4c580000, 0x59cc0006, 0x82000d80, - 0x01000000, 0x0400002c, 0x59cc0007, 0x9000b1c0, - 0x8258b500, 0x000000ff, 0x8058b104, 0x8258b400, - 0x00000002, 0x82580c80, 0x00000007, 0x04001003, - 0x4200b000, 0x00000006, 0x83cca400, 0x00000006, - 0x59301008, 0x800811c0, 0x02000800, 0x00100615, - 0x8208ac00, 0x00000005, 0x0201f800, 0x0010a93e, - 0x82000d00, 0xff000000, 0x800409c0, 0x04000019, - 0x8200b500, 0x000000ff, 0x8058b104, 0x82580c80, - 0x0000000e, 0x04001003, 0x4200b000, 0x0000000d, - 0x58081001, 0x800811c0, 0x02000800, 0x00100615, - 0x8208ac00, 0x00000005, 0x0201f800, 0x0010a93e, - 0x0401f008, 0x59301008, 0x800811c0, 0x02000800, - 0x00100615, 0x48001005, 0x59cc0007, 0x48001006, - 0x0401ff3b, 0x5c00b000, 0x5c00a800, 0x5c00a000, - 0x5c025800, 0x1c01f000, 0x4933c857, 0x42000800, - 0x00000000, 0x59cc0006, 0x82000580, 0x02000000, - 0x04000003, 0x42000800, 0x00000001, 0x4d2c0000, - 0x59325808, 0x812e59c0, 0x02000800, 0x00100615, - 0x48065a06, 0x0201f800, 0x00020381, 0x5c025800, - 0x0201f000, 0x000208b4, 0x4933c857, 0x4d2c0000, - 0x4c500000, 0x4c540000, 0x4c580000, 0x4200b000, - 0x00000002, 0x59cc0806, 0x82040580, 0x01000000, - 0x04000004, 0x8204b500, 0x0000ffff, 0x8058b104, - 0x83cca400, 0x00000006, 0x59300008, 0x8200ac00, - 0x00000005, 0x0201f800, 0x0010a93e, 0x0401ff0c, - 0x5c00b000, 0x5c00a800, 0x5c00a000, 0x5c025800, - 0x1c01f000, 0x4933c857, 0x4803c857, 0x4807c857, - 0x480bc857, 0x480fc857, 0x4813c857, 0x481bc857, - 0x492fc857, 0x4d2c0000, 0x4c000000, 0x0201f800, - 0x00100819, 0x5c000000, 0x0400000f, 0x48025803, - 0x5c000000, 0x4802580a, 0x4c000000, 0x481a5801, - 0x48125809, 0x48065804, 0x480a5807, 0x480e5808, - 0x412c1000, 0x0201f800, 0x001008a1, 0x82000540, - 0x00000001, 0x5c025800, 0x1c01f000, 0x4933c857, - 0x4d1c0000, 0x59cc0001, 0x82000500, 0x00ffffff, - 0x59341002, 0x82081500, 0x00ffffff, 0x80080580, - 0x0402001f, 0x497a6205, 0x4d380000, 0x42027000, - 0x00000035, 0x0201f800, 0x00109183, 0x5c027000, - 0x04020012, 0x591c001c, 0x800001c0, 0x0400000f, - 0x497a381c, 0x591c0414, 0x8c000502, 0x02000800, - 0x00100615, 0x84000502, 0x48023c14, 0x591c1406, - 0x82080580, 0x00000003, 0x04000006, 0x82080580, - 0x00000006, 0x04000005, 0x0401fc9e, 0x0401f004, - 0x0401f805, 0x0401f002, 0x0401f8c0, 0x5c023800, - 0x1c01f000, 0x4d2c0000, 0x591e5808, 0x4933c857, - 0x491fc857, 0x493bc857, 0x492fc857, 0x83380580, - 0x00000015, 0x040000b3, 0x83380580, 0x00000016, - 0x040200ae, 0x4d300000, 0x411e6000, 0x59cc0207, - 0x4803c857, 0x82000d00, 0x0000ff00, 0x82040580, - 0x00001700, 0x04000004, 0x82040580, 0x00000300, - 0x0402005b, 0x591c0203, 0x4803c857, 0x82000580, - 0x0000000d, 0x0400003f, 0x812e59c0, 0x0400009a, - 0x591c0202, 0x4803c857, 0x82000580, 0x0000ffff, - 0x0402007e, 0x592c020a, 0x4803c857, 0x82000500, - 0x00000003, 0x82000580, 0x00000002, 0x04020007, - 0x592c080f, 0x591c0011, 0x4803c857, 0x4807c857, - 0x80040580, 0x04020071, 0x591c0414, 0x4803c857, - 0x8c000500, 0x0402006d, 0x41780800, 0x591c1206, - 0x42000000, 0x0000000a, 0x0201f800, 0x001063ee, - 0x592c0406, 0x4803c857, 0x800001c0, 0x0400000c, - 0x80080c80, 0x04001004, 0x02020800, 0x00100615, - 0x80001040, 0x480a5c06, 0x800811c0, 0x04020004, - 0x0201f800, 0x00108b3c, 0x0401f06b, 0x0201f800, - 0x00108ee7, 0x591c0817, 0x591c0018, 0x48065808, - 0x48025809, 0x59300007, 0x8c000500, 0x02020800, - 0x00100ee4, 0x497a3808, 0x0201f800, 0x000201ee, - 0x0402004a, 0x411e6000, 0x0401fc3e, 0x0401f05a, - 0x0401fc6d, 0x04000013, 0x49366009, 0x4a026406, - 0x00000003, 0x492e6008, 0x591c0817, 0x591c1018, - 0x48066017, 0x480a6018, 0x4d380000, 0x591e7403, - 0x4d300000, 0x411e6000, 0x0401fc2e, 0x5c026000, - 0x0201f800, 0x000208d8, 0x5c027000, 0x0401f046, - 0x59a80039, 0x48023a05, 0x0401f043, 0x59cc0407, - 0x82000580, 0x0000000b, 0x04020025, 0x59340a00, - 0x84040d0e, 0x48066a00, 0x592c0a04, 0x82040d00, - 0x000000ff, 0x82040d80, 0x00000014, 0x04000003, - 0x4a02621d, 0x00000003, 0x59300007, 0x8c000500, - 0x02020800, 0x00100ee4, 0x4d400000, 0x42028000, - 0x00000003, 0x592c0a08, 0x0201f800, 0x00104bee, - 0x0201f800, 0x00020381, 0x5c028000, 0x497a6008, - 0x4a026403, 0x00000085, 0x4a026203, 0x00000009, - 0x4a026406, 0x00000002, 0x42000800, 0x8000404b, - 0x0201f800, 0x00020855, 0x0401f01b, 0x59cc0207, - 0x82000580, 0x00002a00, 0x04020004, 0x59a80039, - 0x48023a05, 0x0401f014, 0x812e59c0, 0x02000800, - 0x00100615, 0x4a025a04, 0x00000103, 0x591c0007, - 0x8c000500, 0x02020800, 0x00100ee4, 0x591c0402, - 0x48025c06, 0x4a025a06, 0x00000003, 0x0201f800, - 0x00020381, 0x0201f800, 0x00107698, 0x0201f800, - 0x00104801, 0x5c026000, 0x0201f800, 0x000208b4, - 0x0401f002, 0x5c026000, 0x5c025800, 0x1c01f000, - 0x0401f819, 0x0401f7fd, 0x4933c857, 0x83380580, - 0x00000015, 0x04020004, 0x59a80039, 0x48023a05, - 0x0401f00d, 0x83380580, 0x00000016, 0x0402000d, - 0x4d300000, 0x411e6000, 0x0201f800, 0x0010a3fa, - 0x0201f800, 0x00020831, 0x0201f800, 0x000208b4, - 0x5c026000, 0x497a381c, 0x0201f800, 0x000208b4, - 0x1c01f000, 0x591c0414, 0x84000540, 0x48023c14, - 0x59cc100b, 0x4933c857, 0x491fc857, 0x492fc857, - 0x4803c857, 0x480bc857, 0x8c08153c, 0x04000006, - 0x59a80039, 0x48023a05, 0x497a381c, 0x0201f000, - 0x000208b4, 0x4d300000, 0x411e6000, 0x0201f800, - 0x0010898b, 0x5c026000, 0x591c0406, 0x82000580, - 0x00000000, 0x02000000, 0x000208b4, 0x591c0403, - 0x82000580, 0x00000050, 0x0402000d, 0x4d300000, - 0x411e6000, 0x4a026203, 0x00000001, 0x42000800, - 0x80000043, 0x0201f800, 0x00020855, 0x5c026000, - 0x497a381c, 0x0201f000, 0x000208b4, 0x591c0203, - 0x82000580, 0x0000000d, 0x04000014, 0x812e59c0, - 0x02000800, 0x00100615, 0x591c0203, 0x82000580, - 0x00000004, 0x04020011, 0x592c020a, 0x8c000502, - 0x0400000e, 0x4a023812, 0x0fffffff, 0x592c0208, - 0x8400051e, 0x48025a08, 0x42000000, 0x00000001, - 0x48023a14, 0x0401f021, 0x42000000, 0x00000007, - 0x48023a14, 0x0401f01d, 0x592c020a, 0x4803c857, - 0x8c000500, 0x0402000b, 0x8c000502, 0x040007f7, - 0x591c0414, 0x8c00051c, 0x040207eb, 0x591c0011, - 0x4803c857, 0x800001c0, 0x040007f0, 0x0401f7e6, - 0x8c08153a, 0x040207ed, 0x59cc000a, 0x592c180f, - 0x4803c857, 0x480fc857, 0x800c0580, 0x040007e7, - 0x59cc000a, 0x4803c857, 0x48023816, 0x42000000, - 0x00000005, 0x48023a14, 0x0201f000, 0x0010901b, - 0x4933c857, 0x4d1c0000, 0x59cc0001, 0x59341002, - 0x80080580, 0x82000500, 0x00ffffff, 0x04020041, - 0x59301419, 0x0201f800, 0x001091d9, 0x02000800, - 0x00100615, 0x591c1406, 0x82080580, 0x00000007, - 0x04000038, 0x82080580, 0x00000002, 0x04000035, - 0x82080580, 0x00000000, 0x04000032, 0x591c0202, - 0x82000d80, 0x0000ffff, 0x04000004, 0x59301a19, - 0x800c0580, 0x0402002b, 0x83380580, 0x00000015, - 0x04000026, 0x4d300000, 0x4d2c0000, 0x411e6000, - 0x59325808, 0x0201f800, 0x00108df4, 0x02000800, - 0x00100615, 0x592c0204, 0x82000500, 0x000000ff, - 0x82000580, 0x00000014, 0x04000003, 0x4a02621d, - 0x00000003, 0x42028000, 0x00000003, 0x592c0a08, - 0x0201f800, 0x00104bee, 0x0201f800, 0x00020381, - 0x5c025800, 0x497a6008, 0x4a026403, 0x00000085, - 0x4a026203, 0x00000009, 0x4a026406, 0x00000002, - 0x42000800, 0x8000404b, 0x0201f800, 0x00020855, - 0x5c026000, 0x0401f003, 0x59a80039, 0x48023a05, - 0x497a381c, 0x0201f800, 0x000208b4, 0x5c023800, - 0x1c01f000, 0x4933c857, 0x4c580000, 0x4d2c0000, - 0x59325808, 0x83383580, 0x00000015, 0x04000010, - 0x59342200, 0x84102502, 0x48126a00, 0x0201f800, - 0x00108df4, 0x04000066, 0x0201f800, 0x00109360, - 0x04020005, 0x4200b000, 0x00000002, 0x0201f800, - 0x00109346, 0x0401fa0d, 0x0401f079, 0x83cc1400, - 0x00000008, 0x4200b000, 0x00000002, 0x83341c00, - 0x00000006, 0x0201f800, 0x001082ff, 0x04020015, - 0x83cc1400, 0x0000000a, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000008, 0x0201f800, 0x001082ff, - 0x0402000c, 0x0201f800, 0x00101e1b, 0x59342200, - 0x59cc1007, 0x800811c0, 0x04000003, 0x480a6801, - 0x84102542, 0x8410251a, 0x48126a00, 0x0401f05f, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x42000000, 0x0010b663, 0x0201f800, - 0x0010a86e, 0x59340200, 0x84000558, 0x48026a00, - 0x4d300000, 0x0201f800, 0x00020892, 0x02000800, - 0x00100615, 0x49366009, 0x497a6008, 0x4a026406, - 0x00000001, 0x4a026403, 0x00000001, 0x42003000, - 0x00000003, 0x0201f800, 0x0010a766, 0x0201f800, - 0x0010393e, 0x04000011, 0x41782800, 0x42003000, - 0x00000001, 0x4d400000, 0x42028000, 0x00000029, - 0x0201f800, 0x0010a250, 0x5c028000, 0x4a026406, - 0x00000004, 0x4a026203, 0x00000007, 0x4a026420, - 0x00000001, 0x0401f009, 0x4a026203, 0x00000001, - 0x42000800, 0x0000000b, 0x0201f800, 0x001043c7, - 0x0201f800, 0x00106470, 0x5c026000, 0x0201f800, - 0x00108df4, 0x04000022, 0x0201f800, 0x00109360, - 0x04020022, 0x0401f9b1, 0x0401f01d, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x59340200, - 0x84000558, 0x48026a00, 0x42003000, 0x00000003, - 0x41782800, 0x42002000, 0x00000005, 0x4d400000, - 0x4d440000, 0x59368c03, 0x42028000, 0x00000029, - 0x0201f800, 0x0010962a, 0x5c028800, 0x5c028000, - 0x5c027800, 0x0201f800, 0x00101e1b, 0x0201f800, - 0x000208b4, 0x0401f002, 0x0401fca9, 0x5c025800, - 0x5c00b000, 0x1c01f000, 0x4933c857, 0x41380000, - 0x83383480, 0x00000056, 0x02021800, 0x00100615, - 0x0c01f001, 0x00107c7e, 0x00107c79, 0x00107c7e, - 0x00107c7e, 0x00107c7e, 0x00107c7e, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c7e, 0x00107c77, 0x00107c7e, 0x00107c7e, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c7e, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c7e, - 0x00107c7e, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77, - 0x00107c77, 0x00107c7e, 0x00107c7e, 0x00107c77, - 0x00107c7e, 0x00107c7e, 0x00107c77, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77, - 0x00107c77, 0x00107c77, 0x00107c7e, 0x0201f800, - 0x00100615, 0x4a026203, 0x00000001, 0x493a6403, - 0x0201f000, 0x00106470, 0x4933c857, 0x4a026203, - 0x00000001, 0x493a6403, 0x0201f000, 0x00106470, - 0x59300403, 0x82003480, 0x00000056, 0x02021800, - 0x00100615, 0x83383580, 0x00000013, 0x04000096, - 0x83383580, 0x00000027, 0x0402004c, 0x4933c857, - 0x0201f800, 0x001068f6, 0x0201f800, 0x00108ef1, - 0x0400000b, 0x0201f800, 0x00108f05, 0x04000041, - 0x59300403, 0x82000d80, 0x00000022, 0x04020038, - 0x0401fc61, 0x0400003a, 0x0401f03a, 0x0201f800, - 0x00101e1b, 0x42000800, 0x00000007, 0x0201f800, - 0x001043c7, 0x0401f901, 0x4d440000, 0x59368c03, - 0x83440580, 0x000007fe, 0x04020008, 0x59a81026, - 0x84081540, 0x0201f800, 0x00104e0d, 0x04020002, - 0x8408154a, 0x480b5026, 0x42028000, 0x00000029, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x836c0580, 0x00000003, 0x0400000c, - 0x59326809, 0x59340008, 0x800001c0, 0x04020008, - 0x59368c03, 0x4933c857, 0x4937c857, 0x4947c857, - 0x0201f800, 0x00104451, 0x0401f00c, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x42003000, - 0x00000015, 0x41782800, 0x42002000, 0x00000003, - 0x0201f800, 0x0010962a, 0x5c028800, 0x0201f800, - 0x001090ec, 0x0201f000, 0x000208b4, 0x1c01f000, - 0x0401f8ce, 0x0401f7fa, 0x83380580, 0x00000014, - 0x0400000c, 0x4933c857, 0x0201f800, 0x00106cb4, - 0x02020000, 0x001076fb, 0x59300203, 0x82000580, - 0x00000002, 0x040000ef, 0x0201f800, 0x00100615, - 0x4933c857, 0x0201f800, 0x001068f6, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42003000, 0x00000016, 0x41782800, 0x4d400000, - 0x4d440000, 0x59368c03, 0x42002000, 0x00000009, - 0x42028000, 0x00000029, 0x0201f800, 0x0010962a, - 0x5c028800, 0x5c028000, 0x42000000, 0x0010b663, - 0x0201f800, 0x0010a86e, 0x0201f800, 0x00108ef1, - 0x0402000c, 0x0201f800, 0x00101e1b, 0x0401f89f, - 0x59340c03, 0x82040580, 0x000007fe, 0x040207c8, - 0x59a80826, 0x84040d40, 0x48075026, 0x0401f7c4, - 0x0201f800, 0x00108f05, 0x04020003, 0x0401f893, - 0x0401f7bf, 0x59300403, 0x82000d80, 0x00000032, - 0x04020004, 0x0201f800, 0x001020b2, 0x0401f7b8, - 0x59300403, 0x82000d80, 0x00000022, 0x04000887, - 0x0401f7b3, 0x4933c857, 0x4803c857, 0x0c01f001, - 0x00107da0, 0x00107da0, 0x00107da0, 0x00107da0, - 0x00107da0, 0x00107da0, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d83, 0x00107da0, - 0x00107d7a, 0x00107da0, 0x00107da0, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107da0, 0x00107da0, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d7a, 0x00107d91, 0x00107da0, - 0x00107d7a, 0x00107d8a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107d8a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107da0, 0x00107d8d, 0x00107d7a, - 0x00107d7c, 0x00107da0, 0x00107d7a, 0x00107da0, - 0x00107da0, 0x00107d7a, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107da0, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107da0, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107da0, 0x00107d7a, 0x00107d7a, - 0x00107d7a, 0x00107da0, 0x0201f800, 0x00100615, - 0x4d2c0000, 0x59325808, 0x0201f800, 0x00020381, - 0x5c025800, 0x0201f000, 0x000208b4, 0x4a026203, - 0x00000005, 0x59a80039, 0x48026205, 0x59a80037, - 0x48026206, 0x1c01f000, 0x5930081e, 0x49780a05, - 0x0401f014, 0x0201f800, 0x001090ec, 0x0201f000, - 0x000208b4, 0x0201f800, 0x001020b2, 0x0201f800, - 0x0010698c, 0x04000005, 0x0201f800, 0x001068f6, - 0x0201f000, 0x000208b4, 0x0201f800, 0x001068f6, - 0x0201f800, 0x000208b4, 0x0201f000, 0x00106982, - 0x4933c857, 0x4a026203, 0x00000002, 0x59a80037, - 0x48026206, 0x1c01f000, 0x4933c857, 0x0201f800, - 0x00108df4, 0x0400002a, 0x4d2c0000, 0x0201f800, - 0x00109360, 0x0402000a, 0x4d400000, 0x42028000, - 0x00000031, 0x42000800, 0x00000004, 0x0201f800, - 0x00109204, 0x5c028000, 0x0401f01c, 0x59300c06, - 0x82040580, 0x00000010, 0x04000004, 0x82040580, - 0x00000011, 0x0402000a, 0x4a025a06, 0x00000031, - 0x4a02580d, 0x00000004, 0x4a02580e, 0x000000ff, - 0x0201f800, 0x00020381, 0x0401f00c, 0x592c0404, - 0x8c00051e, 0x04000009, 0x4a025a04, 0x00000103, - 0x4a025805, 0x01000000, 0x5931d821, 0x58ef400b, - 0x58ec0009, 0x0801f800, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x59340400, 0x82000500, 0x000000ff, - 0x82003480, 0x0000000c, 0x02021800, 0x00100615, - 0x59303403, 0x82180d80, 0x0000004d, 0x02000000, - 0x00109154, 0x82180d80, 0x00000033, 0x02000000, - 0x0010910f, 0x82180d80, 0x00000028, 0x02000000, - 0x00108f46, 0x82180d80, 0x00000029, 0x02000000, - 0x00108f5a, 0x82180d80, 0x0000001f, 0x02000000, - 0x001078af, 0x82180d80, 0x00000055, 0x02000000, - 0x00107888, 0x82180d80, 0x00000000, 0x0400058e, - 0x82180d80, 0x00000022, 0x02000000, 0x001078dc, - 0x82180d80, 0x00000035, 0x02000000, 0x001079d7, - 0x82180d80, 0x00000039, 0x04000536, 0x82180d80, - 0x0000003d, 0x02000000, 0x0010790c, 0x82180d80, - 0x00000044, 0x02000000, 0x00107949, 0x82180d80, - 0x00000049, 0x02000000, 0x0010799e, 0x82180d80, - 0x00000041, 0x02000000, 0x0010798a, 0x82180d80, - 0x00000043, 0x02000000, 0x001092a5, 0x82180d80, - 0x00000051, 0x02000000, 0x0010930b, 0x82180d80, - 0x00000004, 0x04020003, 0x42000000, 0x00000001, - 0x83380d80, 0x00000015, 0x04000006, 0x83380d80, - 0x00000016, 0x02020000, 0x001076fb, 0x0401f226, - 0x4d2c0000, 0x4d3c0000, 0x0c01f804, 0x5c027800, - 0x5c025800, 0x1c01f000, 0x00107e42, 0x00107e46, - 0x00107e42, 0x00107ebb, 0x00107e42, 0x00107fc7, - 0x00108060, 0x00107e42, 0x00107e42, 0x00108029, - 0x00107e42, 0x0010803b, 0x4933c857, 0x497a6007, - 0x59300808, 0x58040000, 0x4a000a04, 0x00000103, - 0x0201f000, 0x000208b4, 0x4933c857, 0x40000000, - 0x40000000, 0x1c01f000, 0x4933c857, 0x59a80016, - 0x82000580, 0x00000074, 0x0402005c, 0x0201f800, - 0x0010a0b1, 0x04020016, 0x0401f85c, 0x0201f800, - 0x00108df4, 0x0400000c, 0x0201f800, 0x00109360, - 0x04020009, 0x41780800, 0x4d400000, 0x42028000, - 0x00000000, 0x0201f800, 0x00109204, 0x5c028000, - 0x0401f003, 0x0201f800, 0x00101e1b, 0x0201f800, - 0x00104711, 0x0201f000, 0x000208b4, 0x0201f800, - 0x00108df4, 0x04000007, 0x0201f800, 0x00109360, - 0x04020004, 0x0401ff3d, 0x0201f000, 0x000208b4, - 0x417a7800, 0x0201f800, 0x00101de2, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x59340200, - 0x84000558, 0x48026a00, 0x42003000, 0x00000003, - 0x0201f800, 0x0010a766, 0x4d300000, 0x0201f800, - 0x00020892, 0x02000800, 0x00100615, 0x49366009, - 0x497a6008, 0x4a026406, 0x00000001, 0x4a026403, - 0x00000001, 0x0201f800, 0x0010393e, 0x04000011, - 0x4a026406, 0x00000004, 0x4a026203, 0x00000007, - 0x4a026420, 0x00000001, 0x42003000, 0x00000001, - 0x4d400000, 0x42028000, 0x00000029, 0x41782800, - 0x0201f800, 0x0010a250, 0x5c028000, 0x0401f009, - 0x42000800, 0x0000000b, 0x0201f800, 0x001043c7, - 0x4a026203, 0x00000001, 0x0201f800, 0x00106470, - 0x5c026000, 0x0401ff05, 0x0201f800, 0x00101e1b, - 0x0201f000, 0x000208b4, 0x0401ff00, 0x42000000, - 0x00000001, 0x0401f0de, 0x4933c857, 0x59340200, - 0x8c000500, 0x0400000d, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x001043bd, 0x5c027800, 0x0201f800, - 0x0010393e, 0x04000005, 0x42000800, 0x00000006, - 0x0201f800, 0x001043c7, 0x1c01f000, 0x4933c857, - 0x59a80816, 0x82040580, 0x00000074, 0x0400000e, - 0x4807c857, 0x82040580, 0x00000100, 0x040200b7, - 0x59cc0408, 0x4803c857, 0x8c000500, 0x040000b3, - 0x59341403, 0x82080580, 0x000007fe, 0x04000006, - 0x0401f0ae, 0x59341403, 0x82080580, 0x000007fe, - 0x0402001a, 0x59a80026, 0x8c000506, 0x04000015, - 0x59cc0000, 0x82000500, 0x000000ff, 0x59a80810, - 0x82040d00, 0x000000ff, 0x80040580, 0x0400000d, - 0x0201f800, 0x00101e1b, 0x0201f800, 0x000208b4, - 0x42000000, 0x0010b651, 0x0201f800, 0x0010a86e, - 0x4202d800, 0x00000001, 0x0201f000, 0x00103f37, - 0x0401fa9c, 0x0401f04c, 0x0201f800, 0x00104480, - 0x59341403, 0x82080580, 0x000007fc, 0x0402001f, - 0x4a026802, 0x00fffffc, 0x0201f800, 0x00108df4, - 0x04000012, 0x0201f800, 0x00109360, 0x0402000f, - 0x0401f8a9, 0x41780800, 0x4d400000, 0x42028000, - 0x00000000, 0x0201f800, 0x00109204, 0x5c028000, - 0x42000800, 0x00000004, 0x0201f800, 0x001043c7, - 0x0201f000, 0x000208b4, 0x42000800, 0x00000004, - 0x0201f800, 0x001043c7, 0x0201f800, 0x00101e1b, - 0x0201f000, 0x000208b4, 0x59a8006f, 0x8c000502, - 0x04000011, 0x0201f800, 0x00104e0d, 0x42001000, - 0x00000010, 0x04020009, 0x59340002, 0x82000500, - 0x00ff0000, 0x82000580, 0x00ff0000, 0x04000006, - 0x42001000, 0x00000008, 0x0201f800, 0x00104ada, - 0x0402005a, 0x0201f800, 0x00108df4, 0x0400005b, - 0x0201f800, 0x00109360, 0x04020005, 0x592c0404, - 0x8c00051c, 0x040207c9, 0x0401f877, 0x42000800, - 0x00000005, 0x0201f800, 0x001043c7, 0x4a026203, - 0x00000001, 0x4a026403, 0x00000003, 0x0201f000, - 0x00106470, 0x59cc0408, 0x8c000518, 0x04000010, - 0x0201f800, 0x001090ab, 0x0201f800, 0x00104e0d, - 0x04000004, 0x59cc0408, 0x8c000516, 0x040207b3, - 0x59a80026, 0x8400054a, 0x48035026, 0x59a80010, - 0x84000570, 0x48038832, 0x0401f7ac, 0x42001000, - 0x000000ef, 0x480b5010, 0x497b8830, 0x84081570, - 0x480b8832, 0x59c40802, 0x84040d4c, 0x48078802, - 0x0201f800, 0x001090d5, 0x59a80026, 0x84000548, - 0x48035026, 0x0201f800, 0x0010a1ec, 0x0402079b, - 0x59a80026, 0x8400054c, 0x48035026, 0x42000800, - 0x00000006, 0x0201f800, 0x001043c7, 0x417a7800, - 0x0201f800, 0x001043bd, 0x42000000, 0x000000e8, - 0x0201f800, 0x001059b9, 0x02000800, 0x001043fc, - 0x02020800, 0x00100615, 0x49366009, 0x59340200, - 0x8400051a, 0x48026a00, 0x42000800, 0x00000003, - 0x0201f800, 0x001043c7, 0x4a026406, 0x00000001, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000002, - 0x0201f000, 0x00106470, 0x0401fe2c, 0x42000000, - 0x00000001, 0x0401f00a, 0x599c0017, 0x8c00050a, - 0x040007ab, 0x42000800, 0x00000004, 0x0201f800, - 0x001043c7, 0x0201f000, 0x000208b4, 0x4933c857, - 0x80003540, 0x04000005, 0x42000800, 0x00000007, - 0x0201f800, 0x001043c7, 0x801831c0, 0x0402000e, - 0x59302008, 0x801021c0, 0x04000004, 0x58100404, - 0x8c00051e, 0x04020008, 0x59341c03, 0x42002000, - 0x00000004, 0x42003000, 0x00000012, 0x0201f800, - 0x001038c7, 0x0201f800, 0x00101e1b, 0x0201f000, - 0x000208b4, 0x4c5c0000, 0x4d2c0000, 0x59325808, - 0x0201f800, 0x00105439, 0x5c025800, 0x59cc0008, - 0x48002805, 0x59cc0009, 0x48002806, 0x49782807, - 0x49782808, 0x49782809, 0x4978280a, 0x59cc0013, - 0x8c00053e, 0x04000009, 0x59cc0414, 0x900001c0, - 0x59ccbc15, 0x805c0540, 0x48002807, 0x59cc0416, - 0x900001c0, 0x48002808, 0x59cc0017, 0x8c00053e, - 0x04000009, 0x59cc0418, 0x900001c0, 0x59ccbc19, - 0x805c0540, 0x48002809, 0x59cc041a, 0x900001c0, - 0x4800280a, 0x5c00b800, 0x1c01f000, 0x4933c857, - 0x59a80016, 0x82000580, 0x00000014, 0x04020048, - 0x59a8006f, 0x8c000502, 0x04000015, 0x0201f800, - 0x00104e0d, 0x42001000, 0x00000010, 0x04020009, - 0x59340002, 0x82000500, 0x00ff0000, 0x82000580, - 0x00ff0000, 0x0400000a, 0x42001000, 0x00000008, - 0x0201f800, 0x00104ada, 0x04000005, 0x59a8006f, - 0x8400054c, 0x4803506f, 0x0401f031, 0x836c0580, - 0x00000003, 0x0402000b, 0x59300008, 0x80000540, - 0x04020008, 0x59341c03, 0x42002000, 0x00000006, - 0x42003000, 0x00000013, 0x0201f800, 0x001038c7, - 0x0201f800, 0x001044e1, 0x0401feb8, 0x0401fa1d, - 0x0402001f, 0x59340404, 0x80000540, 0x0400001c, - 0x42000800, 0x00000006, 0x0201f800, 0x001043c7, - 0x0201f800, 0x00108df4, 0x04000011, 0x0201f800, - 0x00109360, 0x0402000a, 0x41780800, 0x4d400000, - 0x42028000, 0x00000000, 0x0201f800, 0x00109204, - 0x5c028000, 0x0201f000, 0x000208b4, 0x4a025a04, - 0x00000103, 0x4a025805, 0x02000000, 0x0201f800, - 0x00101e1b, 0x0201f000, 0x000208b4, 0x0201f800, - 0x00104a83, 0x0201f800, 0x00108df4, 0x04000007, - 0x0201f800, 0x00109360, 0x04020004, 0x0401fd8b, - 0x0201f000, 0x000208b4, 0x0401fd88, 0x80000580, - 0x59a8006f, 0x8c00050c, 0x04000005, 0x8400050c, - 0x4803506f, 0x82000540, 0x00000001, 0x0401ff60, - 0x1c01f000, 0x4933c857, 0x59a80016, 0x82000580, - 0x00000014, 0x0402000b, 0x42000800, 0x0000000b, - 0x0201f800, 0x001043c7, 0x4a026203, 0x00000001, - 0x4a026403, 0x00000001, 0x0201f000, 0x00106470, - 0x42000000, 0x00000001, 0x0401f74d, 0x4933c857, - 0x40003000, 0x59a80016, 0x82000580, 0x00000004, - 0x0402000a, 0x82183580, 0x0000000b, 0x04020005, - 0x42000800, 0x00000007, 0x0201f800, 0x001043c7, - 0x0201f000, 0x000208b4, 0x42000000, 0x00000001, - 0x0401f73b, 0x4803c857, 0x4d2c0000, 0x4d3c0000, - 0x0c01f804, 0x5c027800, 0x5c025800, 0x1c01f000, - 0x00107e42, 0x0010806f, 0x00107e42, 0x001080c4, - 0x00107e42, 0x00108132, 0x00108060, 0x00107e42, - 0x00107e42, 0x00108152, 0x00107e42, 0x00108162, - 0x4933c857, 0x4d1c0000, 0x59301403, 0x82080580, - 0x00000003, 0x04000008, 0x82081580, 0x0000001e, - 0x04020003, 0x0201f800, 0x000208b4, 0x5c023800, - 0x1c01f000, 0x0401ff5a, 0x0401f7fd, 0x4933c857, - 0x0201f800, 0x00108df4, 0x0400000b, 0x0201f800, - 0x00109360, 0x04020008, 0x4200b000, 0x00000002, - 0x0201f800, 0x00109346, 0x0401fd2c, 0x0201f000, - 0x000208b4, 0x0401f8f5, 0x04020030, 0x417a7800, - 0x0201f800, 0x001043bd, 0x417a7800, 0x0201f800, - 0x00101de2, 0x42000000, 0x0010b663, 0x0201f800, - 0x0010a86e, 0x59340200, 0x84000558, 0x48026a00, - 0x4a026403, 0x00000002, 0x42003000, 0x00000003, - 0x0201f800, 0x0010a766, 0x0201f800, 0x0010393e, - 0x04000011, 0x4d400000, 0x41782800, 0x42003000, - 0x00000005, 0x42028000, 0x00000029, 0x0201f800, - 0x0010a250, 0x5c028000, 0x4a026203, 0x00000007, - 0x4a026406, 0x00000004, 0x4a026420, 0x00000001, - 0x1c01f000, 0x42000800, 0x00000003, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x0201f800, - 0x00106470, 0x0401f7f7, 0x59cc0407, 0x82000580, - 0x00000009, 0x0402000a, 0x59340412, 0x82000500, - 0x000000ff, 0x0400000c, 0x80000040, 0x48026c12, - 0x4a026206, 0x0000000a, 0x0401f7ea, 0x59cc0207, - 0x82000500, 0x0000ff00, 0x82000580, 0x00001900, - 0x040007c2, 0x0401fce5, 0x80000580, 0x0401f6c4, - 0x4933c857, 0x59a80032, 0x80000540, 0x04000015, - 0x59340403, 0x82000580, 0x000007fe, 0x04020011, - 0x59a80010, 0x80000000, 0x48035010, 0x417a7800, - 0x0201f800, 0x001043bd, 0x42000800, 0x00000003, - 0x0201f800, 0x001043c7, 0x4a026203, 0x00000001, - 0x4a026403, 0x00000002, 0x0201f000, 0x00106470, - 0x0201f800, 0x00108df4, 0x04000011, 0x0201f800, - 0x00109360, 0x0402000e, 0x4c580000, 0x4200b000, - 0x00000002, 0x0201f800, 0x00109346, 0x5c00b000, - 0x0401fcbe, 0x42000800, 0x00000007, 0x0201f800, - 0x001043c7, 0x0201f000, 0x000208b4, 0x0401fcb7, - 0x59cc3407, 0x82183500, 0x000000ff, 0x82180580, - 0x00000005, 0x0400001c, 0x82180580, 0x0000000b, - 0x04000016, 0x59cc0207, 0x82000500, 0x0000ff00, - 0x04020004, 0x82180580, 0x00000009, 0x04000012, - 0x82000580, 0x00001900, 0x0402000c, 0x82180580, - 0x00000009, 0x0400000c, 0x42000800, 0x00000004, - 0x0201f800, 0x001043c7, 0x0201f800, 0x00101e1b, - 0x0201f000, 0x000208b4, 0x42000000, 0x00000001, - 0x0401f677, 0x0201f800, 0x00108df4, 0x59325808, - 0x04000008, 0x592c0204, 0x82000580, 0x00000139, - 0x040007f6, 0x592c0404, 0x8c00051e, 0x040207f3, - 0x59340403, 0x82000580, 0x000007fe, 0x04020007, - 0x59a80026, 0x84000540, 0x48035026, 0x0201f800, - 0x00104059, 0x0401f7e9, 0x417a7800, 0x0201f800, - 0x00101de2, 0x42003000, 0x00000005, 0x0201f800, - 0x0010a766, 0x42000000, 0x0010b663, 0x0201f800, - 0x0010a86e, 0x0401f7dd, 0x4933c857, 0x0401f84d, - 0x0402000b, 0x42000800, 0x00000005, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000003, 0x0201f000, 0x00106470, 0x42000800, - 0x00000004, 0x0201f800, 0x001043c7, 0x0201f800, - 0x00109360, 0x0402000a, 0x4c580000, 0x4200b000, - 0x00000002, 0x0201f800, 0x00109346, 0x5c00b000, - 0x0401fc5a, 0x0201f000, 0x000208b4, 0x0401fc57, - 0x80000580, 0x0401f636, 0x4933c857, 0x0401f82d, - 0x0402000b, 0x42000800, 0x00000009, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000005, 0x0201f000, 0x00106470, 0x42000000, - 0x00000001, 0x0401f626, 0x4933c857, 0x0401f81d, - 0x0402000b, 0x42000800, 0x0000000b, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000001, 0x0201f000, 0x00106470, 0x42000000, - 0x00000001, 0x0401f616, 0x4933c857, 0x59cc0407, - 0x82000580, 0x00000003, 0x04020009, 0x59cc0207, - 0x82000500, 0x0000ff00, 0x82000d80, 0x00002a00, - 0x04000003, 0x82000d80, 0x00001e00, 0x1c01f000, - 0x4933c857, 0x82000540, 0x00000001, 0x1c01f000, - 0x4933c857, 0x4d400000, 0x4c580000, 0x59a80026, - 0x82000540, 0x00000003, 0x48035026, 0x0401f85c, - 0x04000038, 0x4d340000, 0x4d440000, 0x59a80026, - 0x84000552, 0x48035026, 0x0201f800, 0x0010393e, - 0x0400000c, 0x42028000, 0x0000002a, 0x42028800, - 0x0000ffff, 0x42003000, 0x00000002, 0x0201f800, - 0x0010a258, 0x59a80805, 0x84040d44, 0x48075005, - 0x42028000, 0x0000002a, 0x4d3c0000, 0x42027800, - 0x00000200, 0x0201f800, 0x00101d90, 0x5c027800, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x0201f800, 0x00101bf0, 0x4200b000, 0x00000010, - 0x42028800, 0x000007f0, 0x4d2c0000, 0x83440580, - 0x000007fe, 0x04000003, 0x0201f800, 0x00104451, - 0x81468800, 0x8058b040, 0x040207f9, 0x5c025800, - 0x59cc0408, 0x8c00051e, 0x04000004, 0x59a80026, - 0x84000512, 0x48035026, 0x5c028800, 0x5c026800, - 0x0201f800, 0x00104480, 0x4a026802, 0x00fffffe, - 0x59a80826, 0x84040d50, 0x59cc0013, 0x8c00053e, - 0x04000003, 0x8c000536, 0x04000004, 0x59cc0017, - 0x8c000536, 0x04020002, 0x84040d10, 0x48075026, - 0x59cc0800, 0x82040d00, 0x00ffffff, 0x48075010, - 0x80040110, 0x4803501d, 0x48038881, 0x0201f800, - 0x00104e0d, 0x04000007, 0x59cc0009, 0x48035035, - 0x59cc000a, 0x48035036, 0x0201f800, 0x001090ab, - 0x5c00b000, 0x5c028000, 0x1c01f000, 0x4933c857, - 0x4c580000, 0x59a80010, 0x82000500, 0x00ffff00, - 0x04000022, 0x59cc1000, 0x82081500, 0x00ffff00, - 0x80080580, 0x04000004, 0x42000000, 0x0010b639, - 0x0401f016, 0x83cc1400, 0x0000000b, 0x4200b000, - 0x00000002, 0x83341c00, 0x00000006, 0x0401f904, - 0x04000004, 0x42000000, 0x0010b63a, 0x0401f00b, - 0x83cc1400, 0x0000000d, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000008, 0x0401f8f9, 0x04000007, - 0x42000000, 0x0010b63b, 0x0201f800, 0x0010a86e, - 0x82000540, 0x00000001, 0x5c00b000, 0x1c01f000, - 0x4933c857, 0x59cc0206, 0x82000580, 0x00000014, - 0x04020016, 0x59cc0407, 0x82000580, 0x00000800, - 0x04020012, 0x59cc0207, 0x8c00051a, 0x0400000d, - 0x82000500, 0x00000f00, 0x82000580, 0x00000100, - 0x04020008, 0x59cc020a, 0x8c000508, 0x04020003, - 0x8c00050a, 0x04000003, 0x80000580, 0x1c01f000, - 0x82000540, 0x00000001, 0x1c01f000, 0x4933c857, - 0x4943c857, 0x493fc857, 0x4c5c0000, 0x4d300000, - 0x4d340000, 0x4d2c0000, 0x4d380000, 0x4130b800, - 0x42026000, 0x0010cfc0, 0x59a8000e, 0x81640480, - 0x040210c1, 0x8d3e7d12, 0x04000004, 0x405c0000, - 0x81300580, 0x040000b7, 0x59300406, 0x82000c80, - 0x00000012, 0x04021015, 0x59326809, 0x0c01f001, - 0x001082f4, 0x0010825f, 0x00108278, 0x00108283, - 0x00108258, 0x00108271, 0x001082ac, 0x001082f4, - 0x00108256, 0x001082c0, 0x001082cf, 0x00108256, - 0x00108256, 0x00108256, 0x00108256, 0x001082f4, - 0x001082e5, 0x001082dd, 0x0201f800, 0x00100615, - 0x8d3e7d18, 0x04000003, 0x8d3e7d16, 0x04000004, - 0x59300420, 0x8c000500, 0x04020096, 0x59300403, - 0x82000580, 0x00000043, 0x04000092, 0x0201f800, - 0x00108ef1, 0x02000800, 0x00101e1b, 0x0201f800, - 0x00108f05, 0x02000800, 0x00107da6, 0x8d3e7d06, - 0x04000086, 0x0201f800, 0x0010909d, 0x04000085, - 0x0401f082, 0x8d3e7d18, 0x04000003, 0x8d3e7d16, - 0x04000004, 0x59300420, 0x8c000500, 0x0402007d, - 0x59325808, 0x0201f800, 0x00108df4, 0x04000077, - 0x49425a06, 0x497a5c09, 0x0201f800, 0x00020381, - 0x0201f800, 0x00108ee7, 0x0401f070, 0x813669c0, - 0x02000800, 0x00100615, 0x8d3e7d06, 0x04000004, - 0x59340200, 0x8c00050e, 0x0402006a, 0x59300004, - 0x8400055c, 0x48026004, 0x59300203, 0x82000580, - 0x00000004, 0x02000800, 0x00100ee4, 0x59325808, - 0x0201f800, 0x00108df4, 0x0400005c, 0x4a025a04, - 0x00000103, 0x59300402, 0x48025c06, 0x592c0408, - 0x8c000512, 0x04000006, 0x4d2c0000, 0x592e5809, - 0x0201f800, 0x00100843, 0x5c025800, 0x49425a06, - 0x497a5c09, 0x0201f800, 0x00109365, 0x0201f800, - 0x00020381, 0x0201f800, 0x00108ee7, 0x0401f047, - 0x8c000518, 0x04000047, 0x59300203, 0x82000580, - 0x00000004, 0x02000800, 0x00100ee4, 0x59325808, - 0x0201f800, 0x00108df4, 0x0400003c, 0x49425a06, - 0x497a5c09, 0x0201f800, 0x0010a4ae, 0x0201f800, - 0x00109365, 0x0201f800, 0x00020381, 0x0401f033, - 0x0201f800, 0x0010600e, 0x04000032, 0x59300203, - 0x82000580, 0x00000004, 0x04020004, 0x0201f800, - 0x00100ee4, 0x0401f02b, 0x42027000, 0x00000047, - 0x0201f800, 0x000208d8, 0x0401f026, 0x59300203, - 0x82000580, 0x00000004, 0x02000800, 0x00100ee4, - 0x59325808, 0x0201f800, 0x00108df4, 0x0400001b, - 0x49425a06, 0x497a5c09, 0x0201f800, 0x00020381, - 0x0401f016, 0x833c0500, 0x00001800, 0x04000015, - 0x8d3e7d16, 0x04020013, 0x59325817, 0x0201f800, - 0x00100843, 0x59300203, 0x82000580, 0x00000004, - 0x02000800, 0x00100ee4, 0x59325808, 0x0201f800, - 0x00108df4, 0x04000005, 0x49425a06, 0x497a5c09, - 0x0201f800, 0x00020381, 0x0201f800, 0x00107698, - 0x83326400, 0x00000024, 0x41580000, 0x81300480, - 0x0400173e, 0x5c027000, 0x5c025800, 0x5c026800, - 0x5c026000, 0x5c00b800, 0x1c01f000, 0x5c000000, - 0x4c000000, 0x4803c857, 0x480bc857, 0x480fc857, - 0x485bc857, 0x50080800, 0x500c0000, 0x80042580, - 0x04020007, 0x80081000, 0x800c1800, 0x8058b040, - 0x040207f9, 0x80000580, 0x1c01f000, 0x4803c857, - 0x4807c857, 0x480bc857, 0x480fc857, 0x80040480, - 0x04001006, 0x42000000, 0x00000001, 0x82040d40, - 0x00000001, 0x1c01f000, 0x41780000, 0x0401f7fc, - 0x83380480, 0x00000053, 0x02021800, 0x00100615, - 0x83380480, 0x0000004b, 0x02001800, 0x00100615, - 0x0c01f001, 0x0010832f, 0x0010832f, 0x0010832f, - 0x0010832f, 0x0010832d, 0x0010832d, 0x0010832d, - 0x0010832f, 0x0201f800, 0x00100615, 0x493bc857, - 0x4a026203, 0x0000000d, 0x493a6403, 0x42000800, - 0x80000000, 0x0201f000, 0x00020855, 0x83380580, - 0x00000013, 0x04020008, 0x59300403, 0x82000580, - 0x00000050, 0x02020800, 0x00100615, 0x0201f000, - 0x000208b4, 0x4933c857, 0x83380580, 0x00000027, - 0x04020030, 0x4933c857, 0x0201f800, 0x001068f6, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x42000000, 0x0010b663, 0x0201f800, - 0x0010a86e, 0x4d2c0000, 0x59325808, 0x0201f800, - 0x00108df4, 0x492fc857, 0x0400000d, 0x4a025a04, - 0x00000103, 0x59300c02, 0x48065c06, 0x4a025a06, - 0x00000029, 0x497a5c09, 0x592c0c08, 0x84040d50, - 0x48065c08, 0x0201f800, 0x00020381, 0x5c025800, - 0x42003000, 0x00000015, 0x41782800, 0x42002000, - 0x00000003, 0x4d400000, 0x4d440000, 0x59368c03, - 0x42028000, 0x00000029, 0x0201f800, 0x0010962a, - 0x5c028800, 0x5c028000, 0x0201f000, 0x000208b4, - 0x83380580, 0x00000014, 0x0402000d, 0x59300403, - 0x82000c80, 0x00000053, 0x02021800, 0x00100615, - 0x82000480, 0x00000040, 0x02001800, 0x00100615, - 0x4933c857, 0x4803c857, 0x0c01f00e, 0x83380580, - 0x00000053, 0x0400000a, 0x83380580, 0x00000048, - 0x02020800, 0x00100615, 0x59300403, 0x82000580, - 0x00000050, 0x02020800, 0x00100615, 0x1c01f000, - 0x001083a5, 0x001083a3, 0x001083a3, 0x001083a3, - 0x001083a3, 0x001083a3, 0x001083a3, 0x001083a3, - 0x001083a3, 0x001083a3, 0x001083a3, 0x001083bc, - 0x001083bc, 0x001083bc, 0x001083bc, 0x001083a3, - 0x001083bc, 0x001083a3, 0x001083bc, 0x0201f800, - 0x00100615, 0x4933c857, 0x0201f800, 0x001068f6, - 0x0201f800, 0x00108df4, 0x02000000, 0x000208b4, - 0x4d2c0000, 0x59325808, 0x4a025a04, 0x00000103, - 0x59300402, 0x48025c06, 0x4a025a06, 0x00000006, - 0x497a5c09, 0x0201f800, 0x00020381, 0x5c025800, - 0x0201f800, 0x00108ee7, 0x0201f000, 0x000208b4, - 0x4933c857, 0x0201f800, 0x001068f6, 0x0201f000, - 0x000208b4, 0x0201f800, 0x00100615, 0x5930001c, - 0x800001c0, 0x02020800, 0x0010961a, 0x59300004, - 0x8c00053e, 0x04020029, 0x59325808, 0x592c0c08, - 0x59cc2a08, 0x82141d00, 0x00000c00, 0x04000002, - 0x59cc1809, 0x84040d58, 0x48065c08, 0x82143500, - 0x00000fff, 0x04020027, 0x59340200, 0x8c00050e, - 0x04020080, 0x0201f800, 0x00020962, 0x04020006, - 0x4a025a06, 0x00000000, 0x59300811, 0x800409c0, - 0x04020951, 0x4a025a04, 0x00000103, 0x48065807, - 0x480e580a, 0x48165c09, 0x59300c02, 0x48065c06, - 0x0201f800, 0x00020381, 0x0201f800, 0x00104801, - 0x59cc0208, 0x8c000518, 0x02020000, 0x00108f88, - 0x0201f000, 0x000208b4, 0x0201f800, 0x00106cb4, - 0x040007d6, 0x4d3c0000, 0x42027800, 0x00000002, - 0x0201f800, 0x00108997, 0x5c027800, 0x0401f7cf, - 0x4817c857, 0x480fc857, 0x82180500, 0x000000ff, - 0x0400000e, 0x592c0204, 0x82000500, 0x000000ff, - 0x82000580, 0x00000048, 0x04020008, 0x592c0407, - 0x800001c0, 0x04000005, 0x0201f800, 0x0010950b, - 0x0201f000, 0x00109553, 0x82180d00, 0x00000c00, - 0x04000004, 0x59340200, 0x8c00050e, 0x04020032, - 0x4a025a06, 0x00000000, 0x41782000, 0x8c183510, - 0x04000007, 0x59cc000c, 0x82000500, 0x000000ff, - 0x04000002, 0x4803c857, 0x59cc200b, 0x4812580c, - 0x41780000, 0x8c183512, 0x04000002, 0x59cc000a, - 0x4802580b, 0x80100c00, 0x040007b8, 0x82041480, - 0x0000001d, 0x04001006, 0x592c0404, 0x8c00051e, - 0x0400000e, 0x42000800, 0x0000001c, 0x4c500000, - 0x4c540000, 0x83cca400, 0x0000000c, 0x832cac00, - 0x0000000d, 0x0201f800, 0x00108953, 0x5c00a800, - 0x5c00a000, 0x0401f7a5, 0x59300011, 0x59301402, - 0x480a5c06, 0x48025807, 0x480e580a, 0x48165c09, - 0x0201f800, 0x001088fc, 0x0201f800, 0x00108938, - 0x0401f7a6, 0x592c020a, 0x8c000502, 0x040007cd, - 0x592c0208, 0x8c00050e, 0x040207ca, 0x59300011, - 0x800c0d80, 0x040007c7, 0x4803c857, 0x480fc857, - 0x8c183514, 0x02000000, 0x00108fc6, 0x80000540, - 0x040007c0, 0x4807c856, 0x0201f000, 0x00108fc6, - 0x592c020a, 0x8c000502, 0x04000782, 0x59300011, - 0x800001c0, 0x0400077f, 0x592c0208, 0x8c00050e, - 0x0402077c, 0x0201f000, 0x00108fc6, 0x59cc2006, - 0x59cc2807, 0x0401f037, 0x0401f036, 0x1c01f000, - 0x4933c857, 0x5930001c, 0x800001c0, 0x02020800, - 0x0010961a, 0x59325808, 0x592c0c08, 0x41782800, - 0x41781800, 0x84040d58, 0x48065c08, 0x41783000, - 0x59340200, 0x8c00050e, 0x0402001a, 0x0201f800, - 0x00020962, 0x04020007, 0x4a025a06, 0x00000000, - 0x59300811, 0x4807c857, 0x800409c0, 0x040208b2, - 0x4a025a04, 0x00000103, 0x48065807, 0x480e580a, - 0x48165c09, 0x4933c857, 0x59300c02, 0x48065c06, - 0x0201f800, 0x00109365, 0x0201f800, 0x00020381, - 0x0201f800, 0x00104801, 0x0201f000, 0x000208b4, - 0x592c020a, 0x8c000502, 0x040007e8, 0x59300011, - 0x4803c857, 0x800001c0, 0x040007e4, 0x592c0208, - 0x8c00050e, 0x040207e1, 0x0201f000, 0x00108fc6, - 0x5930001c, 0x800001c0, 0x4c100000, 0x4c140000, - 0x02020800, 0x0010961a, 0x5c002800, 0x5c002000, - 0x4a026203, 0x00000002, 0x4a026403, 0x00000043, - 0x59325808, 0x592c020a, 0x8c000502, 0x0402001c, - 0x40100000, 0x592c080f, 0x80040c80, 0x40140000, - 0x80040480, 0x04001018, 0x59300004, 0x8c00053e, - 0x0402000a, 0x48126013, 0x48166011, 0x497a6205, - 0x0201f800, 0x00100fe1, 0x0402000d, 0x59300804, - 0x0201f000, 0x00106466, 0x4c100000, 0x4c140000, - 0x0201f800, 0x00106cb4, 0x5c002800, 0x5c002000, - 0x040007f1, 0x0201f000, 0x001076fb, 0x4933c857, - 0x1c01f000, 0x4807c857, 0x40042800, 0x0401f7e7, - 0x83380480, 0x00000058, 0x04021005, 0x83380480, - 0x00000040, 0x04001002, 0x0c01f002, 0x1c01f000, - 0x001084ec, 0x001084ec, 0x001084ec, 0x001084ec, - 0x001084ec, 0x001084ec, 0x001084ec, 0x001084ec, - 0x001084ec, 0x001084ec, 0x001084ee, 0x001084ec, - 0x001084ec, 0x001084ec, 0x001084ec, 0x001084fb, - 0x001084ec, 0x001084ec, 0x001084ec, 0x001084ec, - 0x00108529, 0x001084ec, 0x001084ec, 0x001084ec, - 0x0201f800, 0x00100615, 0x4933c857, 0x0201f800, - 0x00106b13, 0x4a026203, 0x00000002, 0x59a80039, - 0x48026205, 0x59300011, 0x59300815, 0x80040c80, - 0x48066015, 0x0201f000, 0x001068c1, 0x4933c857, - 0x0201f800, 0x001068c1, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00101de2, 0x5c027800, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x00108df4, 0x04000010, 0x4d2c0000, 0x59325808, - 0x4a025a04, 0x00000103, 0x59300402, 0x48025c06, - 0x4a025a06, 0x00000029, 0x497a5c09, 0x592c0c08, - 0x84040d50, 0x48065c08, 0x0201f800, 0x00020381, - 0x5c025800, 0x42003000, 0x00000014, 0x41782800, - 0x4d400000, 0x4d440000, 0x59368c03, 0x42002000, - 0x00000002, 0x42028000, 0x00000029, 0x0201f800, - 0x0010962a, 0x5c028800, 0x5c028000, 0x0201f000, - 0x000208b4, 0x4933c857, 0x59300808, 0x49780c09, - 0x4978080a, 0x58041408, 0x84081558, 0x48080c08, - 0x1c01f000, 0x4807c857, 0x8c040d3e, 0x04020024, - 0x497a5a06, 0x5930001f, 0x80000540, 0x04000018, - 0x497a5a06, 0x4c040000, 0x4c080000, 0x4c0c0000, - 0x4c100000, 0x4c140000, 0x40002800, 0x58141003, - 0x40040000, 0x80081480, 0x48082803, 0x40140000, - 0x0201f800, 0x00100d9a, 0x5c002800, 0x5c002000, - 0x5c001800, 0x5c001000, 0x5c000800, 0x592c0206, - 0x80000540, 0x04020009, 0x0401f005, 0x592c0408, - 0x8c00051c, 0x04000002, 0x592c0803, 0x4807c857, - 0x4a025a06, 0x00000015, 0x1c01f000, 0x5930001f, - 0x80000540, 0x04000009, 0x4a025a06, 0x00000011, - 0x5930001f, 0x4c040000, 0x0201f800, 0x00100d9a, - 0x5c000800, 0x0401f7f5, 0x4807c856, 0x4a025a06, - 0x00000007, 0x1c01f000, 0x83380480, 0x00000058, - 0x04021007, 0x83380480, 0x00000040, 0x04001004, - 0x4d2c0000, 0x0c01f803, 0x5c025800, 0x1c01f000, - 0x00108588, 0x00108588, 0x00108588, 0x00108588, - 0x00108588, 0x0010858a, 0x00108588, 0x00108588, - 0x0010860d, 0x00108588, 0x00108588, 0x00108588, - 0x00108588, 0x00108588, 0x00108588, 0x00108588, - 0x00108588, 0x00108588, 0x00108588, 0x001086c5, - 0x001086ee, 0x001086cd, 0x00108588, 0x001086fa, - 0x0201f800, 0x00100615, 0x5930001c, 0x800001c0, - 0x02020800, 0x0010961a, 0x59300007, 0x8c00050e, - 0x0400007c, 0x8c000500, 0x0400006e, 0x8c00051c, - 0x04000009, 0x84000500, 0x48026007, 0x59325808, - 0x592c3c08, 0x841c3d58, 0x481e5c08, 0x0201f000, - 0x00020914, 0x59325808, 0x592c3c08, 0x841c3d58, - 0x59300007, 0x8c00051c, 0x040207f3, 0x481e5c08, - 0x42000000, 0x00000005, 0x40000000, 0x80000040, - 0x040207fe, 0x59300007, 0x8c00051c, 0x040207ea, - 0x59cc0a08, 0x592c0204, 0x82000500, 0x000000ff, - 0x82000580, 0x00000048, 0x0402000c, 0x497a580b, - 0x82040500, 0x000000ff, 0x04000008, 0x592c0407, - 0x800001c0, 0x04000005, 0x0201f800, 0x0010950b, - 0x0201f000, 0x00100ea1, 0x48065c09, 0x41782000, - 0x82040500, 0x00000c00, 0x04000002, 0x59cc2009, - 0x82043500, 0x00000fff, 0x04020027, 0x481e5c08, - 0x4a025a06, 0x00000000, 0x801831c0, 0x02000000, - 0x00100ea1, 0x41782000, 0x8c183510, 0x04000002, - 0x59cc200b, 0x4812580c, 0x41780000, 0x8c183512, - 0x04000002, 0x59cc000a, 0x4802580b, 0x80100c00, - 0x02001800, 0x00100615, 0x02000000, 0x00100ea1, - 0x82041480, 0x0000001d, 0x0402100c, 0x4c500000, - 0x4c540000, 0x83cca400, 0x0000000c, 0x832cac00, - 0x0000000d, 0x0401fb6e, 0x5c00a800, 0x5c00a000, - 0x0201f000, 0x00100ea1, 0x0401fb12, 0x0201f000, - 0x00100ea1, 0x412c7800, 0x0201f800, 0x0010082a, - 0x02000800, 0x00100615, 0x492c7809, 0x841c3d52, - 0x481c7c08, 0x4a025a04, 0x00000103, 0x4812580a, - 0x48065c09, 0x583c0404, 0x583c1005, 0x583c2208, - 0x48025c04, 0x480a5805, 0x48125a08, 0x0401f7c8, - 0x8c000524, 0x04000794, 0x59325808, 0x4c000000, - 0x592c0408, 0x8c00051c, 0x5c000000, 0x04020003, - 0x4a026011, 0xffffffff, 0x84000524, 0x0401f78a, - 0x1c01f000, 0x59a80039, 0x48026205, 0x59325808, - 0x4a026203, 0x00000002, 0x592c2408, 0x59300807, - 0x4933c857, 0x4807c857, 0x592c0204, 0x82000500, - 0x000000ff, 0x82000580, 0x00000048, 0x04020004, - 0x8c102500, 0x02020000, 0x00109553, 0x4a025a06, - 0x00000000, 0x8c040d1e, 0x04000027, 0x41780800, - 0x497a5c09, 0x592c1c09, 0x59300011, 0x59341200, - 0x497a6205, 0x8c08150e, 0x0402006e, 0x4807c857, - 0x4806580a, 0x80000d40, 0x04020f03, 0x59300402, - 0x48025c06, 0x48065807, 0x4a025a04, 0x00000103, - 0x4c040000, 0x4c0c0000, 0x4c100000, 0x0201f800, - 0x00109365, 0x5c002000, 0x5c001800, 0x5c000800, - 0x8c102512, 0x0402001a, 0x4c0c0000, 0x0201f800, - 0x00020381, 0x0201f800, 0x00104801, 0x5c001800, - 0x8c0c1d18, 0x02000000, 0x000208b4, 0x0201f000, - 0x00108f88, 0x4813c857, 0x8c102518, 0x0400004b, - 0x41780800, 0x592c1c09, 0x820c0580, 0x00001000, - 0x040007d6, 0x8c102512, 0x040007d4, 0x592c7809, - 0x583c080a, 0x583c1c09, 0x0401f7d0, 0x4807c857, - 0x592c7809, 0x59300402, 0x592c1404, 0x8c08151e, - 0x0402000d, 0x592c1206, 0x48007c06, 0x48047807, - 0x48087a06, 0x84102512, 0x48107c08, 0x4c0c0000, - 0x0201f800, 0x00100843, 0x403e5800, 0x0401fad1, - 0x0401f7d9, 0x48025c06, 0x48065807, 0x583c080c, - 0x583c000b, 0x80040c00, 0x82041480, 0x0000001d, - 0x04001006, 0x583c1001, 0x480a5801, 0x49787801, - 0x42000800, 0x0000001c, 0x82040c00, 0x00000014, - 0x4c0c0000, 0x4c500000, 0x4c540000, 0x823ca400, - 0x00000008, 0x832cac00, 0x00000008, 0x4c100000, - 0x4c3c0000, 0x0401fad2, 0x5c007800, 0x5c002000, - 0x5c00a800, 0x5c00a000, 0x84102512, 0x48125c08, - 0x403e5800, 0x0201f800, 0x00100843, 0x42034000, - 0x0010b2a0, 0x59a1d81e, 0x80edd9c0, 0x02000800, - 0x00100615, 0x48efc857, 0x58ec0009, 0x4803c857, - 0x0801f800, 0x0401f7ac, 0x4933c857, 0x1c01f000, - 0x59301414, 0x480bc857, 0x8c08151c, 0x0402000e, - 0x80000540, 0x4803c857, 0x0400078d, 0x80042c80, - 0x0402178b, 0x8c081514, 0x04020005, 0x592c080f, - 0x4807c857, 0x80040480, 0x48026016, 0x8408155c, - 0x480a6414, 0x59301007, 0x8408151e, 0x480a6007, - 0x4c100000, 0x4c3c0000, 0x4d400000, 0x592e8206, - 0x4a025a06, 0x00000001, 0x0201f800, 0x00109365, - 0x49425a06, 0x5c028000, 0x5c007800, 0x5c002000, - 0x497a5c09, 0x8c102512, 0x04000006, 0x4d2c0000, - 0x403e5800, 0x0201f800, 0x00100843, 0x5c025800, - 0x82102500, 0xffffedff, 0x48125c08, 0x0201f000, - 0x00108fc6, 0x59325808, 0x592c0408, 0x8c000518, - 0x04000004, 0x412df800, 0x0201f000, 0x00100eba, - 0x1c01f000, 0x4933c857, 0x59325808, 0x497a5c09, - 0x4a025a06, 0x00000000, 0x4a025a04, 0x00000103, - 0x59300811, 0x4807c857, 0x800409c0, 0x0402000a, - 0x48065807, 0x59300c02, 0x48065c06, 0x0201f800, - 0x00020381, 0x0201f800, 0x00104801, 0x0201f000, - 0x000208b4, 0x59340200, 0x8c00050e, 0x04020005, - 0x59300811, 0x0401fe4c, 0x48065807, 0x0401f7f2, - 0x592c0208, 0x8c00050e, 0x040207fa, 0x4933c857, - 0x0201f000, 0x00108fc6, 0x4933c857, 0x59325808, - 0x812e59c0, 0x02000800, 0x00100615, 0x592c020a, - 0x8c000502, 0x02000800, 0x00100615, 0x4a026206, - 0x00000002, 0x1c01f000, 0x5930001c, 0x800001c0, - 0x02020800, 0x0010961a, 0x59300007, 0x4933c857, - 0x4803c857, 0x8c00050e, 0x04000037, 0x8c000500, - 0x04000029, 0x8c00051c, 0x0400000a, 0x84000500, - 0x48026007, 0x59325808, 0x592c3c08, 0x481fc857, - 0x841c3d58, 0x481e5c08, 0x0201f000, 0x00020914, - 0x59325808, 0x592c3c08, 0x841c3d58, 0x59300007, - 0x8c00051c, 0x040207f2, 0x481e5c08, 0x42000000, - 0x00000005, 0x40000000, 0x80000040, 0x040207fe, - 0x59300007, 0x8c00051c, 0x040207e9, 0x592c0204, - 0x82000500, 0x000000ff, 0x82000580, 0x00000048, - 0x04020003, 0x497a580b, 0x0401f002, 0x497a5c09, - 0x481e5c08, 0x4a025a06, 0x00000000, 0x0201f000, - 0x00100ea1, 0x8c000524, 0x040007d9, 0x59325808, - 0x4c000000, 0x592c0408, 0x8c00051c, 0x5c000000, - 0x04020003, 0x4a026011, 0xffffffff, 0x84000524, - 0x0401f7cf, 0x1c01f000, 0x4933c857, 0x41780800, - 0x83380480, 0x00000058, 0x0402100b, 0x83380480, - 0x00000040, 0x04001008, 0x4d2c0000, 0x59325808, - 0x812e59c0, 0x0c020806, 0x5c025800, 0x0201f000, - 0x000208b4, 0x493bc857, 0x1c01f000, 0x00108763, - 0x00108763, 0x00108763, 0x00108763, 0x00108763, - 0x00108765, 0x00108763, 0x00108763, 0x00108763, - 0x00108763, 0x00108763, 0x00108763, 0x00108763, - 0x00108763, 0x00108763, 0x00108763, 0x00108763, - 0x00108763, 0x00108763, 0x00108763, 0x0010876a, - 0x00108763, 0x00108763, 0x00108763, 0x0201f800, - 0x00100615, 0x59cc0a08, 0x497a5807, 0x4807c857, - 0x82040d00, 0x00000fff, 0x59300402, 0x48025c06, - 0x4a025a04, 0x00000103, 0x48065c09, 0x4a025a06, - 0x00000000, 0x800409c0, 0x02000000, 0x00020381, - 0x59cc0009, 0x4802580a, 0x82042500, 0x00000100, - 0x04000002, 0x59cc200b, 0x4812580c, 0x82040500, - 0x00000200, 0x04000002, 0x59cc000a, 0x4802580b, - 0x80100c00, 0x02001800, 0x00100615, 0x02000000, - 0x00020381, 0x82041480, 0x0000001d, 0x04001006, - 0x592c0404, 0x8c00051e, 0x0400000e, 0x42000800, - 0x0000001c, 0x4c500000, 0x4c540000, 0x83cca400, - 0x0000000c, 0x832cac00, 0x0000000d, 0x0401f9c0, - 0x5c00a800, 0x5c00a000, 0x0201f000, 0x00020381, - 0x0401f964, 0x0401f19f, 0x83380480, 0x00000093, - 0x02021800, 0x00100615, 0x83380480, 0x00000085, - 0x02001800, 0x00100615, 0x0c01f001, 0x001087b2, - 0x001087b0, 0x001087b0, 0x001087b9, 0x001087b0, - 0x001087b0, 0x001087b0, 0x001087b0, 0x001087b0, - 0x001087b0, 0x001087b0, 0x001087b0, 0x001087b0, - 0x0201f800, 0x00100615, 0x4a026203, 0x00000001, - 0x493a6403, 0x42000800, 0x80000040, 0x0201f000, - 0x00020855, 0x4933c857, 0x59cc1404, 0x0201f800, - 0x001091d9, 0x0400001b, 0x591c0203, 0x82000580, - 0x00000000, 0x04000017, 0x591c0009, 0x81340580, - 0x04020014, 0x4d300000, 0x4d1c0000, 0x411e6000, - 0x0401f9c3, 0x5c023800, 0x5c026000, 0x0400000b, - 0x59cc0005, 0x8c000500, 0x04020003, 0x0401f98d, - 0x0401f003, 0x4a023a03, 0x00000002, 0x4a026403, - 0x00000086, 0x0401f005, 0x0401f9a7, 0x040007f5, - 0x4a026403, 0x00000087, 0x4a026203, 0x00000001, - 0x42000800, 0x80000040, 0x0201f800, 0x00020855, - 0x59340200, 0x8c00050e, 0x0400000d, 0x59cc1404, - 0x0201f800, 0x001091d9, 0x04000009, 0x591c0414, - 0x8c00051a, 0x04000006, 0x4d300000, 0x411e6000, - 0x0201f800, 0x00108fdb, 0x5c026000, 0x1c01f000, - 0x83380580, 0x00000013, 0x0402000b, 0x59300403, - 0x4803c857, 0x82000d80, 0x00000086, 0x04000012, - 0x82000d80, 0x00000087, 0x02020800, 0x00100615, - 0x0401f00d, 0x83380580, 0x00000027, 0x04000005, - 0x83380580, 0x00000014, 0x02020800, 0x00100615, - 0x493bc857, 0x0201f800, 0x001068f6, 0x0201f000, - 0x00107698, 0x4933c857, 0x0201f000, 0x00107698, - 0x83380580, 0x00000013, 0x04020005, 0x59300403, - 0x82000480, 0x00000085, 0x0c01f04d, 0x83380580, - 0x00000027, 0x04020041, 0x4933c857, 0x0201f800, - 0x001068f6, 0x4d3c0000, 0x417a7800, 0x0201f800, - 0x00101de2, 0x5c027800, 0x42003000, 0x00000015, - 0x41782800, 0x42002000, 0x00000003, 0x42028000, - 0x00000029, 0x4d400000, 0x4d440000, 0x59368c03, - 0x0201f800, 0x0010962a, 0x5c028800, 0x5c028000, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x0201f800, 0x00108df4, 0x0400000c, 0x4d2c0000, - 0x59325808, 0x4a025a04, 0x00000103, 0x59300402, - 0x48025c06, 0x497a5c09, 0x49425a06, 0x0201f800, - 0x00020381, 0x5c025800, 0x0201f800, 0x00108ee7, - 0x0201f000, 0x000208b4, 0x83380580, 0x00000089, - 0x04000005, 0x83380580, 0x0000008a, 0x02020000, - 0x001076fb, 0x0201f800, 0x00106cb4, 0x02020000, - 0x001076fb, 0x59300a03, 0x82040580, 0x0000000a, - 0x0400002a, 0x82040580, 0x0000000c, 0x04000027, - 0x0201f800, 0x00100615, 0x83380580, 0x00000014, - 0x040207ea, 0x4933c857, 0x0201f800, 0x001068f6, - 0x42028000, 0x00000006, 0x0401f7d2, 0x0010886e, - 0x0010886c, 0x0010886c, 0x0010886c, 0x0010886c, - 0x0010886c, 0x00108874, 0x0010886c, 0x0010886c, - 0x0010886c, 0x0010886c, 0x0010886c, 0x0010886c, - 0x0201f800, 0x00100615, 0x4933c857, 0x59a80037, - 0x48026206, 0x4a026203, 0x0000000a, 0x1c01f000, - 0x4933c857, 0x59a80037, 0x48026206, 0x4a026203, - 0x0000000c, 0x1c01f000, 0x83380580, 0x00000089, - 0x04000008, 0x83380580, 0x0000008a, 0x04000032, - 0x4933c857, 0x493bc857, 0x0201f000, 0x001076fb, - 0x4933c857, 0x59325808, 0x59300a1d, 0x82040580, - 0x00000003, 0x04020004, 0x0201f800, 0x00104801, - 0x0401f00c, 0x5930021d, 0x82000580, 0x00000001, - 0x04020008, 0x59300c16, 0x82040580, 0x00000039, - 0x0400002c, 0x82040580, 0x00000035, 0x04000029, - 0x4c5c0000, 0x4130b800, 0x0201f800, 0x00020892, - 0x04000010, 0x4a026203, 0x00000001, 0x4a026403, - 0x0000001e, 0x59cc0c07, 0x48066419, 0x59cc0a07, - 0x48066219, 0x49366009, 0x4a026406, 0x00000001, - 0x42000800, 0x80000040, 0x0201f800, 0x00020855, - 0x405e6000, 0x0201f800, 0x000208b4, 0x5c00b800, - 0x1c01f000, 0x4933c857, 0x5930021d, 0x82000580, - 0x00000001, 0x04020040, 0x59300c16, 0x82040580, - 0x00000035, 0x04000007, 0x82040580, 0x0000001e, - 0x04000004, 0x82040580, 0x00000039, 0x04020036, - 0x4933c857, 0x4c500000, 0x4d1c0000, 0x4130a000, - 0x40067000, 0x0201f800, 0x00109183, 0x04020029, - 0x0201f800, 0x00020892, 0x04000026, 0x491fc857, - 0x4933c857, 0x83380580, 0x00000035, 0x04000004, - 0x83380580, 0x00000039, 0x04020002, 0x4932381c, - 0x493a6403, 0x4a026203, 0x00000001, 0x4a026406, - 0x00000001, 0x58500809, 0x4807c857, 0x48066009, - 0x58500c15, 0x4807c857, 0x48066415, 0x58500a15, - 0x4807c857, 0x48066215, 0x58500a16, 0x4807c857, - 0x48066216, 0x58500c19, 0x4807c857, 0x48066419, - 0x58500a19, 0x4807c857, 0x48066219, 0x491e601e, - 0x42000800, 0x80000040, 0x0201f800, 0x00020855, - 0x40526000, 0x5c023800, 0x5c00a000, 0x0201f000, - 0x000208b4, 0x5930021d, 0x82000580, 0x00000003, - 0x02000800, 0x00104801, 0x0201f000, 0x000208b4, - 0x4803c856, 0x4c500000, 0x4c540000, 0x412c7800, - 0x4c3c0000, 0x42002800, 0x00000001, 0x82040480, - 0x00000101, 0x04001003, 0x42000800, 0x00000100, - 0x40043000, 0x42000800, 0x0000001c, 0x83cca400, - 0x0000000c, 0x832cac00, 0x0000000d, 0x0401f844, - 0x82183480, 0x0000001c, 0x592e5801, 0x812e59c0, - 0x02020800, 0x00100843, 0x0201f800, 0x0010082a, - 0x04000017, 0x80142800, 0x4a025a04, 0x00000110, - 0x497a5c04, 0x492c7801, 0x82180c80, 0x0000003d, - 0x04021006, 0x40180800, 0x832cac00, 0x00000005, - 0x0401f82f, 0x0401f00a, 0x82183480, 0x0000003c, - 0x42000800, 0x0000003c, 0x412c7800, 0x832cac00, - 0x00000005, 0x0401f826, 0x0401f7e8, 0x5c007800, - 0x841429c0, 0x82142d40, 0x00000003, 0x48147a04, - 0x403e5800, 0x5c00a800, 0x5c00a000, 0x1c01f000, - 0x492fc857, 0x812e59c0, 0x0400000f, 0x4d2c0000, - 0x4c3c0000, 0x592c7801, 0x803c79c0, 0x04000006, - 0x497a5801, 0x0201f800, 0x00020381, 0x403e5800, - 0x0401f7f9, 0x5c007800, 0x0201f800, 0x00020381, - 0x5c025800, 0x1c01f000, 0x4803c856, 0x4c580000, - 0x82040c00, 0x00000003, 0x8004b104, 0x0201f800, - 0x0010a93e, 0x5c00b000, 0x1c01f000, 0x4803c856, - 0x4c580000, 0x82040c00, 0x00000003, 0x8004b104, - 0x0201f800, 0x0010a93e, 0x5c00b000, 0x1c01f000, - 0x591c0c06, 0x82040580, 0x00000003, 0x04000004, - 0x82040580, 0x00000002, 0x0402001a, 0x4d300000, - 0x4d2c0000, 0x411e6000, 0x59325808, 0x0201f800, - 0x00108df4, 0x0400000f, 0x4d400000, 0x42028000, - 0x00000013, 0x592c0a08, 0x84040d54, 0x0201f800, - 0x00104bee, 0x5c028000, 0x0201f800, 0x00109365, - 0x0201f800, 0x00020381, 0x0201f800, 0x00108ee7, - 0x0201f800, 0x00107698, 0x5c025800, 0x5c026000, - 0x1c01f000, 0x59cc0005, 0x8c000500, 0x0402000b, - 0x591c0406, 0x82000580, 0x00000002, 0x04020007, - 0x591c0c03, 0x82040580, 0x00000085, 0x04000003, - 0x82040580, 0x0000008b, 0x1c01f000, 0x4933c857, - 0x4d3c0000, 0x42027800, 0x00000002, 0x59300406, - 0x82000c80, 0x00000012, 0x02021800, 0x00100615, - 0x0c01f80a, 0x5c027800, 0x1c01f000, 0x4933c857, - 0x59300406, 0x82000c80, 0x00000012, 0x02021800, - 0x00100615, 0x0c01f001, 0x001089b5, 0x001089b2, - 0x001089b2, 0x001089dd, 0x001089b0, 0x001089b2, - 0x001089ce, 0x001089b2, 0x001089b0, 0x0010632c, - 0x001089b2, 0x001089b2, 0x001089b2, 0x001089b0, - 0x001089b0, 0x001089b0, 0x00108aad, 0x001089b2, - 0x0201f800, 0x00100615, 0x4803c856, 0x80000580, - 0x1c01f000, 0x4803c856, 0x8d3e7d02, 0x04020016, - 0x0201f800, 0x00108df4, 0x0400000f, 0x59325808, - 0x41780800, 0x4d400000, 0x42028000, 0x00000005, - 0x0201f800, 0x00104bee, 0x5c028000, 0x0201f800, - 0x00109365, 0x0201f800, 0x00108f83, 0x0201f800, - 0x00020381, 0x0201f800, 0x00107698, 0x82000540, - 0x00000001, 0x1c01f000, 0x4933c857, 0x0201f800, - 0x00104728, 0x0402000c, 0x4d400000, 0x42028000, - 0x00000010, 0x0201f800, 0x00109fc0, 0x4a026406, - 0x00000006, 0x4a026203, 0x00000007, 0x5c028000, - 0x1c01f000, 0x4933c857, 0x0201f800, 0x0010698c, - 0x4df00000, 0x0401f8b8, 0x82000c80, 0x0000000e, - 0x02021800, 0x00100615, 0x0c01f001, 0x001089f7, - 0x00108a64, 0x00108a0e, 0x00108a77, 0x00108a5f, - 0x001089f5, 0x001089f7, 0x001089f7, 0x001089fb, - 0x001089f7, 0x001089f7, 0x001089f7, 0x001089f7, - 0x00108a0e, 0x0201f800, 0x00100615, 0x5c03e000, - 0x02000800, 0x00106982, 0x0401f7b8, 0x5c03e000, - 0x02000800, 0x00106982, 0x59300406, 0x82000580, - 0x00000003, 0x040207b4, 0x59300203, 0x82000580, - 0x0000000d, 0x040007b0, 0x8d3e7d02, 0x040207ae, - 0x4d340000, 0x59326809, 0x0201f800, 0x00104801, - 0x5c026800, 0x0401f7a8, 0x59300004, 0x8400055c, - 0x48026004, 0x0201f800, 0x00106982, 0x59300406, - 0x82000580, 0x00000006, 0x04000043, 0x8d3e7d02, - 0x04020041, 0x497a621d, 0x59300203, 0x82000580, - 0x0000000d, 0x04000003, 0x4a02621d, 0x00000003, - 0x0401fbd4, 0x04000024, 0x4d2c0000, 0x4d400000, - 0x59325808, 0x0201f800, 0x00108f83, 0x592c0408, - 0x8c000512, 0x04000009, 0x4d2c0000, 0x84000512, - 0x48025c08, 0x592c0809, 0x40065800, 0x0201f800, - 0x00100843, 0x5c025800, 0x4d400000, 0x42028000, - 0x00000005, 0x592c0a08, 0x8c040d0e, 0x04000004, - 0x42028000, 0x00000002, 0x0401f001, 0x0201f800, - 0x00104bee, 0x5c028000, 0x0201f800, 0x00109365, - 0x0201f800, 0x00020381, 0x497a6008, 0x5c028000, - 0x5c025800, 0x8d3e7d00, 0x04000009, 0x4d340000, - 0x59326809, 0x0201f800, 0x00104801, 0x5c026800, - 0x0201f800, 0x00107698, 0x0401f00b, 0x4a026403, - 0x00000085, 0x4a026203, 0x00000009, 0x4a026406, - 0x00000002, 0x42000800, 0x8000404b, 0x0201f800, - 0x00020855, 0x5c03e000, 0x02020800, 0x0010698c, - 0x82000540, 0x00000001, 0x1c01f000, 0x0201f800, - 0x00106982, 0x0201f800, 0x00100ee4, 0x0401f7ab, - 0x598c000d, 0x81300580, 0x04020004, 0x0201f800, - 0x00106be2, 0x0402001b, 0x0201f800, 0x00106619, - 0x04020006, 0x59300c03, 0x82040580, 0x00000040, - 0x0400078b, 0x0401f79d, 0x0201f800, 0x001068a3, - 0x04000010, 0x0201f800, 0x00100615, 0x0401f813, - 0x04020004, 0x0201f800, 0x00106bb2, 0x04020009, - 0x0201f800, 0x001064f6, 0x040207f4, 0x59300c03, - 0x82040580, 0x00000040, 0x04000779, 0x0401f78b, - 0x59300203, 0x82000c80, 0x0000000e, 0x02021800, - 0x00100615, 0x0c01f75e, 0x417a3000, 0x42032000, - 0x0000bf32, 0x59900004, 0x81300580, 0x04000009, - 0x83932400, 0x00000010, 0x811a3000, 0x83180480, - 0x00000005, 0x040017f8, 0x82000540, 0x00000001, - 0x1c01f000, 0x59300004, 0x8c00053e, 0x04000010, - 0x8c00050c, 0x0402000e, 0x8c000516, 0x04020006, - 0x82000d00, 0x0000001f, 0x82040580, 0x00000005, - 0x04020004, 0x42000000, 0x00000003, 0x0401f005, - 0x42000000, 0x00000001, 0x0401f002, 0x59300203, - 0x1c01f000, 0x4933c857, 0x0201f800, 0x0010698c, - 0x4df00000, 0x59300203, 0x82000c80, 0x0000000e, - 0x02021800, 0x00100615, 0x0c01f001, 0x00108ac7, - 0x00108ae4, 0x00108acb, 0x00108ac5, 0x00108ac5, - 0x00108ac5, 0x00108ac5, 0x00108ac5, 0x00108ac5, - 0x00108ac5, 0x00108ac5, 0x00108ac5, 0x00108ac5, - 0x00108ac5, 0x0201f800, 0x00100615, 0x5c03e000, - 0x02000800, 0x00106982, 0x0401f6e8, 0x5c03e000, - 0x02000800, 0x00106982, 0x4d2c0000, 0x59325808, - 0x59300403, 0x82000580, 0x00000052, 0x02000800, - 0x00101281, 0x0401fb1f, 0x02000800, 0x00100615, - 0x4a025a06, 0x00000005, 0x0201f800, 0x00020381, - 0x0201f800, 0x00104a83, 0x0201f800, 0x00107698, - 0x5c025800, 0x82000540, 0x00000001, 0x1c01f000, - 0x598c000d, 0x81300580, 0x0402001a, 0x59300004, - 0x8c000520, 0x04000004, 0x84000520, 0x48026004, - 0x0401f01a, 0x42001000, 0x0010b5f4, 0x50081000, - 0x58080002, 0x82000580, 0x00000100, 0x0400000a, - 0x5808000c, 0x81300580, 0x02020800, 0x00100615, - 0x0201f800, 0x00106619, 0x02020800, 0x00100615, - 0x0401f7cf, 0x0201f800, 0x00106be2, 0x0402000c, - 0x59300004, 0x8c000520, 0x04000004, 0x84000520, - 0x48026004, 0x0401f7c6, 0x0201f800, 0x00106619, - 0x040007c3, 0x0201f800, 0x00100615, 0x59300203, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f7a7, 0x59300406, 0x4933c857, 0x4803c857, - 0x82000c80, 0x00000012, 0x02021800, 0x00100615, - 0x0c01f001, 0x00108b30, 0x00108bfe, 0x00108d36, - 0x00108b3c, 0x00107698, 0x00108b30, 0x00109faf, - 0x000208b4, 0x00108bfe, 0x00106306, 0x00108d97, - 0x00108b2b, 0x00108b2b, 0x00108b2b, 0x00108b2b, - 0x00108b2b, 0x001094b7, 0x001094b7, 0x0201f800, - 0x00100615, 0x0401fbd8, 0x02000000, 0x00107da6, - 0x1c01f000, 0x0201f800, 0x0010698c, 0x0201f800, - 0x001068f6, 0x0201f800, 0x00106982, 0x0201f000, - 0x000208b4, 0x4a026206, 0x00000001, 0x1c01f000, - 0x42000000, 0x0010b671, 0x0201f800, 0x0010a86e, - 0x4d2c0000, 0x4d400000, 0x417a5800, 0x0401fab1, - 0x04000007, 0x59325808, 0x592c0208, 0x8400054c, - 0x48025a08, 0x42028000, 0x00000006, 0x0201f800, - 0x0010698c, 0x0401ff4c, 0x4803c857, 0x82000c80, - 0x0000000e, 0x02021800, 0x00100615, 0x0c01f806, - 0x0201f800, 0x00106982, 0x5c028000, 0x5c025800, - 0x1c01f000, 0x00108bfd, 0x00108b69, 0x00108b79, - 0x00108ba0, 0x00108bce, 0x00108b67, 0x00108b30, - 0x00108b30, 0x00108b30, 0x00108b67, 0x00108b67, - 0x00108b67, 0x00108b67, 0x00108b79, 0x0201f800, - 0x00100615, 0x598c000d, 0x4803c857, 0x81300580, - 0x04020004, 0x0201f800, 0x00106be2, 0x0402003f, - 0x0201f800, 0x00106619, 0x04000043, 0x4803c856, - 0x0201f800, 0x001068a3, 0x04000038, 0x0201f800, - 0x00100615, 0x497a621d, 0x812e59c0, 0x02000800, - 0x00100615, 0x592c0204, 0x4803c857, 0x82000500, - 0x000000ff, 0x82000580, 0x00000014, 0x04000003, - 0x4a02621d, 0x00000003, 0x592c0a08, 0x0201f800, - 0x00104bee, 0x0201f800, 0x00109365, 0x0201f800, - 0x00020381, 0x497a6008, 0x4a026403, 0x00000085, - 0x4a026203, 0x00000009, 0x4a026406, 0x00000002, - 0x59300804, 0x82040d00, 0x00000100, 0x82040d40, - 0x8000404b, 0x48066004, 0x0201f800, 0x00106982, - 0x42000800, 0x8000404b, 0x0201f000, 0x00020855, - 0x0401feea, 0x04020004, 0x0201f800, 0x00106bb2, - 0x0402000a, 0x0201f800, 0x001064f6, 0x040207cc, - 0x59300c03, 0x4807c857, 0x82040580, 0x00000040, - 0x04000009, 0x0401f7cc, 0x59300203, 0x4803c857, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f7a5, 0x0201f800, 0x00106982, 0x812e59c0, - 0x04000013, 0x592c0a08, 0x0201f800, 0x00104bee, - 0x0201f800, 0x00109365, 0x0201f800, 0x00020381, - 0x59300203, 0x82000580, 0x0000000d, 0x04000008, - 0x0201f800, 0x00106982, 0x4d340000, 0x59326809, - 0x0201f800, 0x00104801, 0x5c026800, 0x0201f800, - 0x00107698, 0x0401f030, 0x812e59c0, 0x02000800, - 0x00100615, 0x0201f800, 0x001091d3, 0x04020004, - 0x0201f800, 0x00100ee4, 0x0401f7a3, 0x0201f800, - 0x00106982, 0x592c0208, 0x8400050c, 0x48025a08, - 0x592c0406, 0x800000c2, 0x800008c4, 0x80040c00, - 0x48066206, 0x42000000, 0x10000000, 0x41300800, - 0x0201f800, 0x00100bde, 0x0400000d, 0x592c0208, - 0x8c00051c, 0x04020006, 0x8400055c, 0x48025a08, - 0x4a026206, 0x00000002, 0x0401f00f, 0x4d300000, - 0x0201f800, 0x00101335, 0x5c026000, 0x59300203, - 0x82000580, 0x00000004, 0x04020007, 0x4d380000, - 0x42027000, 0x00000048, 0x0201f800, 0x000208d8, - 0x5c027000, 0x1c01f000, 0x42000000, 0x0010b66d, - 0x0201f800, 0x0010a86e, 0x59300203, 0x82000c80, - 0x0000000e, 0x02021800, 0x00100615, 0x4803c857, - 0x0c01f001, 0x00108c17, 0x00108b39, 0x00108c19, - 0x00108c17, 0x00108c19, 0x00108c19, 0x00108b31, - 0x00108c17, 0x00108b2d, 0x00108c17, 0x00108c17, - 0x00108c17, 0x00108c17, 0x00108c17, 0x0201f800, - 0x00100615, 0x4d340000, 0x4d2c0000, 0x59326809, - 0x59340400, 0x82000500, 0x000000ff, 0x82000c80, - 0x0000000c, 0x02021800, 0x00100615, 0x59303403, - 0x82180d80, 0x00000004, 0x04020004, 0x42000000, - 0x00000001, 0x0401f006, 0x82180d80, 0x00000000, - 0x04020003, 0x42000000, 0x00000001, 0x4803c857, - 0x0c01f804, 0x5c025800, 0x5c026800, 0x1c01f000, - 0x00108c40, 0x00108cdf, 0x00108c42, 0x00108c77, - 0x00108c42, 0x00108cfc, 0x00108c42, 0x00108c4c, - 0x00108c40, 0x00108cfc, 0x00108c40, 0x00108c5b, - 0x0201f800, 0x00100615, 0x59300403, 0x82000d80, - 0x00000016, 0x0400002e, 0x82000d80, 0x00000004, - 0x0400002b, 0x82000d80, 0x00000002, 0x04000028, - 0x0401fab9, 0x04000079, 0x59300403, 0x82000d80, - 0x00000022, 0x040000ae, 0x82000d80, 0x00000039, - 0x040000b3, 0x82000d80, 0x00000035, 0x040000b0, - 0x82000d80, 0x0000001e, 0x0400001b, 0x0401f999, - 0x04000007, 0x0201f800, 0x00109360, 0x04020004, - 0x0201f800, 0x00104863, 0x0401f011, 0x59300403, - 0x82000d80, 0x00000001, 0x04020004, 0x0201f800, - 0x00104836, 0x0400000a, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00101de2, 0x5c027800, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x00107da6, 0x0201f000, 0x00107698, 0x0401f97d, - 0x04000004, 0x0201f800, 0x00109360, 0x040000a9, - 0x59300c03, 0x82040580, 0x00000016, 0x04000056, - 0x82040580, 0x00000002, 0x04020034, 0x59a80026, - 0x8c000502, 0x04020013, 0x0201f800, 0x00104e0d, - 0x04020010, 0x0201f800, 0x00104e23, 0x04020006, - 0x42000000, 0x00000001, 0x0201f800, 0x00104de5, - 0x0401f094, 0x4a035033, 0x00000001, 0x4202d800, - 0x00000001, 0x0201f800, 0x00104d76, 0x0401f08d, - 0x59340403, 0x82000580, 0x000007fc, 0x04000008, - 0x59a80026, 0x8c00050a, 0x04020084, 0x59340212, - 0x82000500, 0x0000ff00, 0x04000082, 0x59340412, - 0x82000500, 0x000000ff, 0x04000010, 0x80000040, - 0x48026c12, 0x497a6008, 0x4a026406, 0x00000007, - 0x4a026206, 0x00000398, 0x497a6205, 0x0201f800, - 0x00020892, 0x04000005, 0x49366009, 0x4a026406, - 0x00000001, 0x0401f020, 0x59300403, 0x82000d80, - 0x00000002, 0x0402000d, 0x59340403, 0x82000580, - 0x000007fe, 0x04020009, 0x59a80026, 0x84000540, - 0x48035026, 0x0201f800, 0x00104067, 0x0201f800, - 0x00107da6, 0x0401f00c, 0x0201f800, 0x00107da6, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x42000000, 0x0010b663, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x00101e1b, 0x0201f000, - 0x00107698, 0x42000800, 0x00000003, 0x0201f800, - 0x001043c7, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000002, 0x0201f000, 0x00106470, 0x0401f915, - 0x04020793, 0x0201f800, 0x00101e1b, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x42003000, 0x00000018, 0x41782800, 0x42002000, - 0x00000000, 0x4d400000, 0x4d440000, 0x59368c03, - 0x42028000, 0x00000029, 0x0201f800, 0x0010962a, - 0x5c028800, 0x5c028000, 0x0201f000, 0x00107698, - 0x0201f800, 0x00104863, 0x0401f7c8, 0x42000000, - 0x0010b66c, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x001078fd, 0x040207c1, 0x1c01f000, 0x4d380000, - 0x59327403, 0x0201f800, 0x00109183, 0x5c027000, - 0x02020000, 0x000208b4, 0x836c0580, 0x00000003, - 0x04000004, 0x4a026206, 0x00000002, 0x1c01f000, - 0x59300403, 0x48026416, 0x4a02621d, 0x00000001, - 0x4a026403, 0x00000085, 0x4a026203, 0x00000009, - 0x4a026406, 0x00000002, 0x42000800, 0x8000004b, - 0x0201f000, 0x00020855, 0x0201f800, 0x00101e1b, - 0x0201f800, 0x00107da6, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00101de2, 0x5c027800, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x497a6008, - 0x4a026406, 0x00000007, 0x4a026206, 0x00000398, - 0x497a6205, 0x1c01f000, 0x42000000, 0x0010b66f, - 0x0201f800, 0x0010a86e, 0x4d340000, 0x59326809, - 0x59300203, 0x82000c80, 0x0000000e, 0x02021800, - 0x00100615, 0x4803c857, 0x0c01f803, 0x5c026800, - 0x1c01f000, 0x00108d53, 0x00108b39, 0x00108d53, - 0x00108d53, 0x00108d53, 0x00108d53, 0x00108d53, - 0x00108d53, 0x00108d53, 0x00108b39, 0x00108d55, - 0x00108b39, 0x00108d5d, 0x00108d53, 0x0201f800, - 0x00100615, 0x4a026403, 0x0000008b, 0x4a026203, - 0x0000000b, 0x42000800, 0x8000404b, 0x0201f000, - 0x00020855, 0x59300a1d, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00101de2, 0x5c027800, 0x42003000, - 0x00000011, 0x0201f800, 0x0010a766, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x41306800, - 0x0201f800, 0x00020892, 0x04000008, 0x49366009, - 0x4d300000, 0x40366000, 0x0201f800, 0x00107698, - 0x5c026000, 0x0401f002, 0x40366000, 0x497a6008, - 0x4a026406, 0x00000001, 0x4a026403, 0x00000001, - 0x0201f800, 0x0010393e, 0x04000011, 0x4a026406, - 0x00000004, 0x4a026203, 0x00000007, 0x4a026420, - 0x00000001, 0x42003000, 0x00000004, 0x4d400000, - 0x42028000, 0x00000029, 0x41782800, 0x0201f800, - 0x0010a250, 0x5c028000, 0x1c01f000, 0x42000800, - 0x0000000b, 0x0201f800, 0x001043c7, 0x4a026203, - 0x00000001, 0x0201f000, 0x00106470, 0x42000000, - 0x0010b675, 0x0201f800, 0x0010a86e, 0x59300203, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x4803c857, 0x0c01f001, 0x00108dc8, 0x00108db0, - 0x00108db4, 0x00108dc9, 0x00108db2, 0x00108db0, - 0x00108db0, 0x00108db0, 0x00108db0, 0x00108db0, - 0x00108db0, 0x00108db0, 0x00108db0, 0x00108db0, - 0x0201f800, 0x00100615, 0x0201f800, 0x00100ee4, - 0x4d2c0000, 0x59325808, 0x4a025a06, 0x00000006, - 0x0201f800, 0x00020381, 0x5c025800, 0x497a6008, - 0x4a02621d, 0x0000000a, 0x4a026403, 0x00000085, - 0x4a026203, 0x00000009, 0x4a026406, 0x00000002, - 0x42000800, 0x8000404b, 0x0201f000, 0x00020855, - 0x1c01f000, 0x0201f800, 0x0010698c, 0x4df00000, - 0x0401fcbe, 0x04020004, 0x0201f800, 0x00106bb2, - 0x0402000c, 0x0201f800, 0x001064f6, 0x04020005, - 0x5c03e000, 0x0201f800, 0x00106982, 0x0401f7dd, - 0x0201f800, 0x001068a3, 0x02020800, 0x00100615, - 0x5c03e000, 0x0201f800, 0x00106982, 0x59300203, - 0x82000d80, 0x00000003, 0x02000800, 0x00100615, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f7ba, 0x4803c856, 0x59a8000e, 0x59a80867, - 0x80040400, 0x80080480, 0x04021004, 0x82000540, - 0x00000001, 0x1c01f000, 0x80000580, 0x1c01f000, - 0x4803c856, 0x4c080000, 0x59301008, 0x82081500, - 0xfff00000, 0x5c001000, 0x1c01f000, 0x4803c856, - 0x4d300000, 0x0201f800, 0x00020892, 0x0400000a, - 0x0401f82f, 0x4d380000, 0x42027000, 0x0000004b, - 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4803c856, - 0x4d300000, 0x0201f800, 0x001076c9, 0x0400001b, - 0x0401f81f, 0x4d300000, 0x0201f800, 0x0010698c, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x001067f6, - 0x0201f800, 0x00106543, 0x5c027800, 0x0201f800, - 0x0010a0da, 0x0201f800, 0x00106982, 0x5c026000, - 0x8d3e7d3e, 0x0402000b, 0x4d380000, 0x42027000, - 0x0000004c, 0x0201f800, 0x000208d8, 0x5c027000, - 0x82000540, 0x00000001, 0x5c026000, 0x1c01f000, - 0x0201f800, 0x000208b4, 0x0401f7fa, 0x592c0407, - 0x494a6017, 0x494e6018, 0x49366009, 0x492e6008, - 0x4a026406, 0x00000003, 0x800000c2, 0x800008c4, - 0x80040400, 0x48026206, 0x1c01f000, 0x493bc857, - 0x4d300000, 0x0201f800, 0x00020892, 0x0400000d, - 0x0401ffef, 0x4d400000, 0x42028000, 0x00000005, - 0x0401f80d, 0x5c028000, 0x8d3e7d3e, 0x04020007, - 0x0201f800, 0x000208d8, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x0201f800, 0x000208b4, - 0x0401f7fa, 0x4803c856, 0x0201f800, 0x0010698c, - 0x4d3c0000, 0x4d440000, 0x59368c03, 0x42027800, - 0x00000001, 0x0201f800, 0x001066ff, 0x0201f800, - 0x00106675, 0x0201f800, 0x00106543, 0x0201f800, - 0x0010a0da, 0x5c028800, 0x5c027800, 0x0201f000, - 0x00106982, 0x4803c856, 0x4d300000, 0x0201f800, - 0x00020892, 0x0400000f, 0x481a601c, 0x48ee6021, - 0x49366009, 0x4a026406, 0x00000001, 0x492e6008, - 0x4d380000, 0x42027000, 0x0000001f, 0x0201f800, - 0x000208d8, 0x5c027000, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000, - 0x0201f800, 0x00020892, 0x0400000e, 0x48ee6021, - 0x49366009, 0x4a026406, 0x00000001, 0x492e6008, - 0x4d380000, 0x42027000, 0x00000055, 0x0201f800, - 0x000208d8, 0x5c027000, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000, - 0x0201f800, 0x00020892, 0x0400000f, 0x481a601c, - 0x48ee6021, 0x49366009, 0x4a026406, 0x00000001, - 0x492e6008, 0x4d380000, 0x42027000, 0x0000003d, - 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4803c856, - 0x4d300000, 0x0201f800, 0x001076c9, 0x04000014, - 0x49366009, 0x492fc857, 0x4933c857, 0x592c0404, - 0x8c00051e, 0x04000003, 0x48efc857, 0x48ee6021, - 0x4a026406, 0x00000001, 0x492e6008, 0x4d380000, - 0x42027000, 0x00000000, 0x0201f800, 0x000208d8, - 0x5c027000, 0x82000540, 0x00000001, 0x5c026000, - 0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800, - 0x00020892, 0x0400000f, 0x48ee6021, 0x481a601c, - 0x49366009, 0x4a026406, 0x00000001, 0x492e6008, - 0x4d380000, 0x42027000, 0x00000044, 0x0201f800, - 0x000208d8, 0x5c027000, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000, - 0x0201f800, 0x00020892, 0x0400000f, 0x481a601c, - 0x48ee6021, 0x49366009, 0x4a026406, 0x00000001, - 0x492e6008, 0x4d380000, 0x42027000, 0x00000049, - 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x59300009, - 0x80001540, 0x02000800, 0x00100615, 0x5808040b, - 0x4803c856, 0x80000040, 0x04001002, 0x4800140b, - 0x1c01f000, 0x4803c856, 0x59300403, 0x82000d80, - 0x00000002, 0x0400000f, 0x82000d80, 0x00000003, - 0x0400000c, 0x82000d80, 0x00000004, 0x04000009, - 0x599c0819, 0x8c040d0e, 0x04000004, 0x82000d80, - 0x00000000, 0x04000003, 0x82000540, 0x00000001, - 0x1c01f000, 0x4803c856, 0x4c000000, 0x4d2c0000, - 0x59300406, 0x82000580, 0x00000004, 0x0400001d, - 0x59300008, 0x80025d40, 0x800001c0, 0x04000019, - 0x0201f800, 0x00109360, 0x04000014, 0x59300406, - 0x82004580, 0x00000010, 0x04000010, 0x82004580, - 0x00000011, 0x0400000d, 0x82004580, 0x00000003, - 0x0400000c, 0x82004580, 0x00000002, 0x04000009, - 0x82004580, 0x0000000a, 0x04000006, 0x592c0404, - 0x8c00051e, 0x04000003, 0x80000580, 0x0401f003, - 0x82000540, 0x00000001, 0x5c025800, 0x5c000000, - 0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800, - 0x001076c9, 0x04000013, 0x49366009, 0x48ee6021, - 0x4a026406, 0x00000001, 0x492e6008, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x4d380000, 0x42027000, 0x00000028, 0x0201f800, - 0x000208d8, 0x5c027000, 0x82000540, 0x00000001, - 0x5c026000, 0x1c01f000, 0x4803c856, 0x83380580, - 0x00000015, 0x0402000d, 0x59a80016, 0x82000580, - 0x00000074, 0x04020009, 0x0201f800, 0x00104480, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000029, - 0x0201f000, 0x00106470, 0x0201f800, 0x00107da6, - 0x0201f000, 0x000208b4, 0x4803c856, 0x83380580, - 0x00000016, 0x04020007, 0x42000800, 0x00000004, - 0x0201f800, 0x001043c7, 0x0201f000, 0x001078bf, - 0x83380580, 0x00000015, 0x04020013, 0x59a80016, - 0x82000580, 0x00000014, 0x0402000f, 0x0201f800, - 0x001044e1, 0x0201f800, 0x00108210, 0x0402000a, - 0x59340404, 0x80000540, 0x04000007, 0x42000800, - 0x00000006, 0x0201f800, 0x001043c7, 0x0201f000, - 0x001078bf, 0x0201f800, 0x00107da6, 0x0201f000, - 0x000208b4, 0x4803c856, 0x592c0206, 0x82000580, - 0x00000005, 0x04000002, 0x1c01f000, 0x4803c856, - 0x592c0208, 0x8400054a, 0x48025a08, 0x1c01f000, - 0x497a6205, 0x497a6008, 0x4a026203, 0x00000001, - 0x4a026403, 0x00000050, 0x42000800, 0x80000043, - 0x0201f000, 0x00020855, 0x4933c857, 0x4d340000, - 0x59326809, 0x59340200, 0x8c00050e, 0x04000006, - 0x59300406, 0x82000c80, 0x00000012, 0x04021004, - 0x0c01f806, 0x5c026800, 0x1c01f000, 0x0201f800, - 0x00108b30, 0x0401f7fc, 0x00108b30, 0x00108fb4, - 0x00108fb8, 0x00108fbb, 0x0010a2b9, 0x0010a2d6, - 0x0010a2da, 0x00108b30, 0x00108b30, 0x00108b30, - 0x00108b30, 0x00108b30, 0x00108b30, 0x00108b30, - 0x00108b30, 0x00108b30, 0x00108b30, 0x00108b30, - 0x4803c856, 0x40000000, 0x40000000, 0x1c01f000, - 0x40000000, 0x40000000, 0x1c01f000, 0x5930001c, - 0x4803c857, 0x59300414, 0x4933c857, 0x4803c857, - 0x8c000502, 0x04000005, 0x4803c857, 0x84000540, - 0x48026414, 0x1c01f000, 0x42000000, 0xd0000000, - 0x41300800, 0x0201f800, 0x00100bde, 0x0401f810, - 0x0402000e, 0x59300c14, 0x59300403, 0x82000580, - 0x00000040, 0x04000003, 0x84040d40, 0x0401f005, - 0x59a80037, 0x82000400, 0x0000000a, 0x48026205, - 0x84040d42, 0x48066414, 0x1c01f000, 0x4933c857, - 0x4d340000, 0x59326809, 0x59340200, 0x8c00050e, - 0x02000800, 0x00100615, 0x5930001c, 0x80000540, - 0x04020034, 0x59300403, 0x4803c857, 0x82000580, - 0x00000040, 0x04000004, 0x59a80021, 0x80000540, - 0x0402002a, 0x4d1c0000, 0x41323800, 0x0201f800, - 0x00020892, 0x04000023, 0x4932381c, 0x591c0414, - 0x84000542, 0x48023c14, 0x49366009, 0x591c0406, - 0x82000580, 0x00000003, 0x04000006, 0x591c0202, - 0x48026419, 0x591c0402, 0x48026219, 0x0401f005, - 0x591c0202, 0x48026219, 0x591c0402, 0x48026419, - 0x491e601e, 0x4a026406, 0x00000001, 0x4a026403, - 0x00000035, 0x4a026203, 0x00000001, 0x42000800, - 0x80000040, 0x0201f800, 0x00020855, 0x411e6000, - 0x5c023800, 0x80000580, 0x5c026800, 0x1c01f000, - 0x411e6000, 0x5c023800, 0x59a80039, 0x48026205, - 0x82000540, 0x00000001, 0x0401f7f8, 0x4933c857, - 0x4d2c0000, 0x4932381c, 0x4a026202, 0x0000ffff, - 0x591e5808, 0x591c0007, 0x8c00051e, 0x04000005, - 0x8400051e, 0x48023807, 0x497a5c09, 0x0401f018, - 0x592c0408, 0x8c000518, 0x04000015, 0x84000518, - 0x48025c08, 0x4d400000, 0x592e8206, 0x4a025a06, - 0x00000001, 0x0401fb34, 0x49425a06, 0x5c028000, - 0x497a5c09, 0x592c0408, 0x8c000512, 0x04000008, - 0x4d2c0000, 0x84000512, 0x48025c08, 0x592e5809, - 0x0201f800, 0x00100843, 0x5c025800, 0x59a80039, - 0x48026205, 0x591c0214, 0x48026216, 0x82000d80, - 0x00000001, 0x04000008, 0x4a023a03, 0x00000002, - 0x82000580, 0x00000005, 0x04000008, 0x497a6015, - 0x0401f01e, 0x591c0007, 0x84000540, 0x48023807, - 0x4a023a03, 0x00000004, 0x591c0414, 0x4803c857, - 0x8400051c, 0x84000554, 0x48023c14, 0x592c000f, - 0x40001000, 0x591c0816, 0x80040480, 0x040217f0, - 0x591c0016, 0x82000500, 0xfffffffc, 0x48026015, - 0x48023816, 0x591c0a14, 0x4807c857, 0x82040d80, - 0x00000005, 0x04020005, 0x480bc857, 0x4803c857, - 0x4a023812, 0xffffffff, 0x591c0402, 0x48026419, - 0x591c0202, 0x48026219, 0x591e6809, 0x49366009, - 0x4a026406, 0x00000001, 0x4a026403, 0x00000039, - 0x4a026203, 0x00000001, 0x42000800, 0x80000040, - 0x0201f800, 0x00020855, 0x5c025800, 0x1c01f000, - 0x4933c857, 0x59300414, 0x8c000514, 0x04000015, - 0x8c00051c, 0x04020012, 0x59300016, 0x80100480, - 0x04001006, 0x04000005, 0x59300414, 0x84000514, - 0x8400055c, 0x0401f009, 0x48126016, 0x48126012, - 0x40100000, 0x592c180f, 0x800c0480, 0x48026011, - 0x59300414, 0x84000514, 0x48026414, 0x1c01f000, - 0x4933c857, 0x8c00051c, 0x04020006, 0x59300012, - 0x48026016, 0x59300414, 0x8400055c, 0x48026414, - 0x1c01f000, 0x59300c03, 0x4933c857, 0x4807c857, - 0x82040480, 0x00000034, 0x04001006, 0x82040480, - 0x0000003c, 0x04021003, 0x80000580, 0x1c01f000, - 0x82000540, 0x00000001, 0x0401f7fd, 0x41780800, - 0x59a81035, 0x42000000, 0x00000032, 0x0201f800, - 0x001063ee, 0x800811c0, 0x04020003, 0x42001000, - 0x00000014, 0x480b5037, 0x59a81036, 0x480b502d, - 0x41780800, 0x42000000, 0x00000064, 0x0201f800, - 0x001063ee, 0x800811c0, 0x04020003, 0x42001000, - 0x00000014, 0x480b5038, 0x82081400, 0x0000000a, - 0x480b5039, 0x42000800, 0x00000001, 0x0201f800, - 0x001069af, 0x42000000, 0x30000000, 0x40080800, - 0x0201f800, 0x00100bb2, 0x42000800, 0x00000003, - 0x59a81010, 0x0201f800, 0x001069af, 0x0201f000, - 0x00104755, 0x4a035037, 0x00000028, 0x4a035038, - 0x00000014, 0x4a03502d, 0x000007d0, 0x42001000, - 0x0000001e, 0x480b5039, 0x42000800, 0x00000001, - 0x0201f800, 0x001069af, 0x42000000, 0x30000000, - 0x40080800, 0x0201f800, 0x00100bb2, 0x42000800, - 0x00000003, 0x59a81010, 0x0201f000, 0x001069af, - 0x4933c857, 0x4d2c0000, 0x59300403, 0x82000580, - 0x0000003e, 0x04020005, 0x59325817, 0x812e59c0, - 0x02020800, 0x0010083a, 0x5c025800, 0x1c01f000, - 0x4937c857, 0x4d300000, 0x0201f800, 0x00020892, - 0x04000011, 0x49366009, 0x4a026406, 0x00000001, - 0x492e6008, 0x42000800, 0x00000009, 0x0201f800, - 0x001043c7, 0x4d380000, 0x42027000, 0x00000033, - 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4933c857, - 0x4d2c0000, 0x4c580000, 0x4d3c0000, 0x59325808, - 0x83380580, 0x00000015, 0x04020025, 0x59a8b016, - 0x82580c80, 0x00000019, 0x04001003, 0x4200b000, - 0x00000018, 0x8058b104, 0x0401fa0a, 0x80000580, - 0x0401fa1a, 0x832cac00, 0x00000009, 0x83cca400, - 0x00000006, 0x0201f800, 0x0010a93e, 0x4c600000, - 0x4200c000, 0x00000001, 0x592c100a, 0x8c081518, - 0x04020006, 0x59a80010, 0x592c100d, 0x80080580, - 0x04020007, 0x4178c000, 0x59301009, 0x58081403, - 0x417a7800, 0x0201f800, 0x00101e48, 0x5c00c000, - 0x0201f800, 0x001078bf, 0x0401f008, 0x4200b000, - 0x00000002, 0x0401fa09, 0x0201f800, 0x00107da6, - 0x0201f800, 0x000208b4, 0x5c027800, 0x5c00b000, - 0x5c025800, 0x1c01f000, 0x4933c856, 0x49366009, - 0x4a026406, 0x00000001, 0x492e6008, 0x4d380000, - 0x42027000, 0x0000004d, 0x0201f800, 0x000208d8, - 0x5c027000, 0x82000540, 0x00000001, 0x1c01f000, - 0x4803c856, 0x4d2c0000, 0x83380580, 0x00000015, - 0x04020027, 0x59a80816, 0x59325808, 0x5930040b, - 0x800000c4, 0x80040580, 0x04020021, 0x4c500000, - 0x4c540000, 0x4c580000, 0x83cca400, 0x00000006, - 0x4050a800, 0x5930b40b, 0x0201f800, 0x0010a94f, - 0x83cca400, 0x00000006, 0x592cb205, 0x832cac00, - 0x00000006, 0x0201f800, 0x0010a93e, 0x592e5801, - 0x812e59c0, 0x040207f9, 0x5931d821, 0x58ef400b, - 0x58ee580d, 0x4a025a04, 0x00000103, 0x58ec0009, - 0x0801f800, 0x59300402, 0x5c00b000, 0x5c00a800, - 0x5c00a000, 0x5c025800, 0x1c01f000, 0x0201f800, - 0x00107da6, 0x5c025800, 0x1c01f000, 0x4933c857, - 0x83380580, 0x00000035, 0x04000005, 0x59301419, - 0x0401f851, 0x04000027, 0x0401f006, 0x4d300000, - 0x5932601e, 0x0401f856, 0x5c026000, 0x04000020, - 0x591c0c06, 0x82040580, 0x00000003, 0x04000004, - 0x82040580, 0x00000006, 0x0402001c, 0x591c0c02, - 0x59300419, 0x80040580, 0x04000009, 0x59300219, - 0x80040580, 0x04020015, 0x591c0a02, 0x59300419, - 0x80040580, 0x04020011, 0x0401f009, 0x59300a19, - 0x82040580, 0x0000ffff, 0x04000005, 0x591c0202, - 0x59300a19, 0x80040580, 0x04020008, 0x591c0009, - 0x59300809, 0x80040580, 0x1c01f000, 0x417a3800, - 0x82000540, 0x00000001, 0x1c01f000, 0x4803c856, - 0x59b800e4, 0x8c000538, 0x02020800, 0x00100615, - 0x42000800, 0x0000012c, 0x4a0370e4, 0x20000000, - 0x59b800e4, 0x80040840, 0x02000800, 0x00100615, - 0x8c00053c, 0x040207f9, 0x4a0370e4, 0x30000000, - 0x40000000, 0x40000000, 0x40000000, 0x59b800e4, - 0x8c00053c, 0x040207f1, 0x1c01f000, 0x4803c856, - 0x4a0370e4, 0x20000000, 0x40000000, 0x59b800e4, - 0x8c000538, 0x040207fb, 0x1c01f000, 0x59300807, - 0x8c040d1e, 0x592c0c08, 0x04020002, 0x8c040d18, - 0x1c01f000, 0x0401fc10, 0x04000008, 0x42000800, - 0x00000024, 0x0201f800, 0x001063cf, 0x82063c00, - 0x0010cfc0, 0x491fc857, 0x1c01f000, 0x83300480, - 0x0010cfc0, 0x0400100a, 0x59a8000b, 0x81300480, - 0x04021007, 0x59301402, 0x0401ffef, 0x04000007, - 0x411c0000, 0x81300580, 0x04000003, 0x81780500, - 0x0401f002, 0x81300540, 0x1c01f000, 0x4947c857, - 0x4d300000, 0x0201f800, 0x00020267, 0x0402000a, - 0x42026000, 0x0010bbe8, 0x49366009, 0x492e6008, - 0x0201f800, 0x00101de2, 0x80000580, 0x5c026000, - 0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fc, - 0x4933c857, 0x0201f800, 0x00108df4, 0x02000800, - 0x00100615, 0x4d2c0000, 0x4d340000, 0x4d440000, - 0x4c580000, 0x59325808, 0x59326809, 0x49425a06, - 0x0201f800, 0x00105439, 0x592e8c06, 0x592c4207, - 0x82200500, 0x0000000f, 0x0c01f806, 0x5c00b000, - 0x5c028800, 0x5c026800, 0x5c025800, 0x1c01f000, - 0x0010922f, 0x00109251, 0x00109258, 0x0010925c, - 0x00109265, 0x0010922c, 0x0010922c, 0x0010922c, - 0x00109269, 0x00109275, 0x00109275, 0x0010922c, - 0x0010922c, 0x0010922c, 0x0010922c, 0x0010922c, - 0x4803c857, 0x0201f800, 0x00100615, 0x814281c0, - 0x04020012, 0x41785800, 0x592c0404, 0x8c00051c, - 0x04020002, 0x59345c05, 0x442c2800, 0x59340008, - 0x48002802, 0x59340009, 0x48002801, 0x59340006, - 0x48002804, 0x59340007, 0x48002803, 0x4200b000, - 0x0000000b, 0x0401f037, 0x592c0207, 0x8c00051e, - 0x4200b000, 0x00000002, 0x04020032, 0x8204b540, - 0x00000000, 0x0400002f, 0x44042800, 0x59326809, - 0x59340400, 0x48002801, 0x4200b000, 0x00000002, - 0x0401f028, 0x814281c0, 0x04020030, 0x59345c05, - 0x442c2800, 0x4200b000, 0x00000001, 0x0401f021, - 0x8340b540, 0x00000000, 0x0400001e, 0x0401f027, - 0x814281c0, 0x04020025, 0x59340200, 0x44002800, - 0x59340001, 0x48002801, 0x4200b000, 0x00000002, - 0x0401f014, 0x8340b540, 0x00000000, 0x0402001b, - 0x0401f010, 0x8340b540, 0x00000000, 0x0400000d, - 0x0201f800, 0x00104871, 0x04000014, 0x8c20450e, - 0x04000002, 0x497a6009, 0x4178b000, 0x497a5a06, - 0x0401f004, 0x8340b540, 0x00000000, 0x0402000b, - 0x592c0404, 0x8400051c, 0x48025c04, 0x592c0207, - 0x8400051e, 0x48025a07, 0x0401f8aa, 0x497a6008, - 0x0201f000, 0x00020381, 0x592c0207, 0x8c00051e, - 0x4200b000, 0x00000002, 0x040207f2, 0x8204b540, - 0x00000000, 0x040007ef, 0x44042800, 0x4200b000, - 0x00000001, 0x0401f7eb, 0x4937c857, 0x4d300000, - 0x0201f800, 0x00020892, 0x04000011, 0x49366009, - 0x4a026406, 0x00000001, 0x492e6008, 0x42000800, - 0x0000000b, 0x0201f800, 0x001043c7, 0x4d380000, - 0x42027000, 0x00000043, 0x0201f800, 0x000208d8, - 0x5c027000, 0x82000540, 0x00000001, 0x5c026000, - 0x1c01f000, 0x4937c857, 0x4d2c0000, 0x59325808, - 0x83380580, 0x00000015, 0x04020025, 0x59a80016, - 0x82000580, 0x00000004, 0x04020021, 0x59a80010, - 0x592c1009, 0x80080580, 0x04020010, 0x4d440000, - 0x592e8c06, 0x592c0207, 0x4803c856, 0x82000500, - 0x00000080, 0x84000548, 0x4d3c0000, 0x42027800, - 0x00001000, 0x0201f800, 0x0010480a, 0x5c027800, - 0x5c028800, 0x0401f004, 0x4803c856, 0x0201f800, - 0x00104871, 0x0201f800, 0x00108df4, 0x04000017, - 0x4d400000, 0x42028000, 0x00000000, 0x41780800, - 0x0401ff38, 0x5c028000, 0x0401f00e, 0x0201f800, - 0x00104871, 0x040207f4, 0x0201f800, 0x00108df4, - 0x0400000a, 0x4c580000, 0x4200b000, 0x00000002, - 0x0401f86e, 0x5c00b000, 0x0201f800, 0x00107da6, - 0x0201f800, 0x000208b4, 0x5c025800, 0x1c01f000, - 0x4937c857, 0x4d300000, 0x0201f800, 0x00020892, - 0x04000012, 0x49366009, 0x4a026406, 0x00000001, - 0x4d3c0000, 0x4d380000, 0x417a7800, 0x0201f800, - 0x001043bd, 0x492e6008, 0x42027000, 0x00000004, - 0x0201f800, 0x000208d8, 0x5c027000, 0x5c027800, - 0x82000540, 0x00000001, 0x5c026000, 0x1c01f000, - 0x4937c857, 0x4d300000, 0x0201f800, 0x001076c9, - 0x0400000d, 0x49366009, 0x4a026406, 0x00000001, - 0x492e6008, 0x4d380000, 0x42027000, 0x00000051, - 0x0201f800, 0x000208d8, 0x5c027000, 0x82000540, - 0x00000001, 0x5c026000, 0x1c01f000, 0x4933c857, - 0x4c580000, 0x59325808, 0x83383580, 0x00000015, - 0x04020011, 0x592c0008, 0x82000500, 0x00ffffff, - 0x0402000a, 0x0201f800, 0x00105439, 0x59cc0000, - 0x82000500, 0x00ffffff, 0x44002800, 0x4200b000, - 0x00000001, 0x0401f80b, 0x0201f800, 0x001078bf, - 0x0401f006, 0x4200b000, 0x00000002, 0x0401f823, - 0x0201f800, 0x00107da6, 0x5c00b000, 0x1c01f000, - 0x492fc857, 0x4c580000, 0x4c000000, 0x8058b1c0, - 0x0400000b, 0x82580500, 0xfffffff0, 0x02020800, - 0x00100615, 0x8058b0d0, 0x592c0408, 0x82000500, - 0xfffff0ff, 0x80580540, 0x48025c08, 0x5c000000, - 0x5c00b000, 0x1c01f000, 0x492fc857, 0x4c000000, - 0x4c040000, 0x800000d8, 0x592c0c08, 0x82040d00, - 0xffff0fff, 0x80040540, 0x48025c08, 0x5c000800, - 0x5c000000, 0x1c01f000, 0x4933c857, 0x4d2c0000, - 0x59325808, 0x592c0207, 0x8400055e, 0x48025a07, - 0x4c500000, 0x4c540000, 0x4c580000, 0x0401ffd9, - 0x0201f800, 0x00105439, 0x46002800, 0x00000018, - 0x80142800, 0x8058b040, 0x83cca400, 0x00000007, - 0x4014a800, 0x0201f800, 0x0010a93e, 0x5c00b000, - 0x5c00a800, 0x5c00a000, 0x5c025800, 0x1c01f000, - 0x59325808, 0x592c0204, 0x82000580, 0x00000152, - 0x1c01f000, 0x5930001f, 0x80000540, 0x02020800, - 0x00100d9a, 0x1c01f000, 0x4d2c0000, 0x59325808, - 0x59300203, 0x4933c857, 0x492fc857, 0x493bc857, - 0x4803c857, 0x82003480, 0x0000000e, 0x02021800, - 0x00100615, 0x0c01f803, 0x5c025800, 0x1c01f000, - 0x00109386, 0x00109391, 0x001093cf, 0x00109386, - 0x00109386, 0x00109386, 0x00109386, 0x00109386, - 0x00109388, 0x00109386, 0x00109386, 0x00109386, - 0x00109386, 0x00109386, 0x0201f800, 0x00100615, - 0x83383480, 0x00000056, 0x02021800, 0x00100615, - 0x493a6403, 0x4a026203, 0x00000001, 0x0201f000, - 0x00106470, 0x83380580, 0x00000013, 0x04020010, - 0x4937c857, 0x592c000c, 0x800001c0, 0x04000006, - 0x4a026203, 0x00000002, 0x59a80037, 0x48026206, - 0x1c01f000, 0x4a025a06, 0x00000000, 0x0201f800, - 0x00020381, 0x0201f000, 0x000208b4, 0x83380580, - 0x00000027, 0x0400001b, 0x83380580, 0x00000014, - 0x04000012, 0x83380580, 0x00000015, 0x04000005, - 0x83380580, 0x00000016, 0x02020800, 0x00100615, - 0x0201f800, 0x00106cb4, 0x02020000, 0x001076fb, - 0x59300203, 0x82000580, 0x00000002, 0x02020800, - 0x00100615, 0x0401f016, 0x4937c857, 0x0201f800, - 0x001068f6, 0x4a02580e, 0x00000011, 0x0401f006, - 0x4937c857, 0x0201f800, 0x001068f6, 0x4a02580e, - 0x00000010, 0x4a025a06, 0x00000031, 0x4a02580d, - 0x00000004, 0x0201f800, 0x00020381, 0x0201f800, - 0x00104a83, 0x0201f000, 0x00107698, 0x59341400, - 0x82081d00, 0x000000ff, 0x59300c03, 0x480bc857, - 0x4807c857, 0x82040580, 0x00000053, 0x0400002e, - 0x82040580, 0x00000002, 0x04000016, 0x82040580, - 0x00000001, 0x04000017, 0x82040580, 0x00000003, - 0x0400001c, 0x82040580, 0x00000005, 0x0400001d, - 0x82040580, 0x00000033, 0x0400001a, 0x82040580, - 0x00000000, 0x0400001b, 0x82040580, 0x00000004, - 0x02020800, 0x00100615, 0x0401f8a1, 0x0401f016, - 0x820c0580, 0x00000003, 0x0400084c, 0x0401f012, - 0x820c0580, 0x0000000b, 0x0402000f, 0x42000800, - 0x00000007, 0x0201f800, 0x001043c7, 0x0401f00a, - 0x820c0580, 0x00000005, 0x04000864, 0x0401f006, - 0x820c0580, 0x00000009, 0x04000889, 0x0401f002, - 0x0401f893, 0x4a026403, 0x00000052, 0x59a81016, - 0x592c040b, 0x8c000500, 0x04000003, 0x42001000, - 0x00000008, 0x592c040b, 0x8c000516, 0x04000003, - 0x82081400, 0x00000018, 0x592c000c, 0x497a580d, - 0x497a580e, 0x80080c80, 0x04000009, 0x04001005, - 0x4a025a06, 0x00000007, 0x40001000, 0x0401f006, - 0x4a025a06, 0x00000015, 0x0401f003, 0x4a025a06, - 0x00000000, 0x480a580c, 0x82081400, 0x00000003, - 0x80081104, 0x0201f800, 0x0010783c, 0x04000010, - 0x592c1001, 0x480a600b, 0x58080800, 0x82080400, - 0x00000002, 0x592c1011, 0x592c1812, 0x42003000, - 0x00000000, 0x42002000, 0x00101250, 0x0201f800, - 0x001079b9, 0x04000002, 0x1c01f000, 0x4a025a06, - 0x0000002c, 0x497a580c, 0x0201f800, 0x00020381, - 0x0201f000, 0x000208b4, 0x83380580, 0x00000015, - 0x0402000a, 0x59a8006f, 0x8c000502, 0x0402000b, - 0x0201f800, 0x00104480, 0x42000800, 0x00000004, - 0x0201f000, 0x001043c7, 0x42000800, 0x00000007, - 0x0201f000, 0x001043c7, 0x0201f800, 0x00104e0d, - 0x42001000, 0x00000010, 0x04020009, 0x59340002, - 0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000, - 0x040007ec, 0x42001000, 0x00000008, 0x0201f800, - 0x00104ada, 0x040007e7, 0x592c040b, 0x84000540, - 0x48025c0b, 0x0401f7e9, 0x83380580, 0x00000015, - 0x0402000f, 0x59a8006f, 0x8c000502, 0x04020010, - 0x0201f800, 0x001044e1, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x001043bd, 0x5c027800, 0x42000800, - 0x00000006, 0x0201f000, 0x001043c7, 0x42000800, - 0x00000004, 0x0201f000, 0x001043c7, 0x0201f800, - 0x00104e0d, 0x42001000, 0x00000010, 0x04020009, - 0x59340002, 0x82000500, 0x00ff0000, 0x82000580, - 0x00ff0000, 0x040007e7, 0x42001000, 0x00000008, - 0x0201f800, 0x00104ada, 0x040007e2, 0x592c040b, - 0x84000540, 0x48025c0b, 0x0401f7e9, 0x42000800, - 0x00000004, 0x0201f000, 0x001043c7, 0x83380580, - 0x00000015, 0x04020005, 0x0201f800, 0x0010a0b1, - 0x02000800, 0x00104711, 0x1c01f000, 0x83380580, - 0x00000015, 0x0402001d, 0x4c580000, 0x83cc1400, - 0x00000008, 0x4200b000, 0x00000002, 0x83341c00, - 0x00000006, 0x0201f800, 0x001082ff, 0x04020012, - 0x83cc1400, 0x0000000a, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000008, 0x0201f800, 0x001082ff, - 0x04020009, 0x59342200, 0x59cc1007, 0x800811c0, - 0x04000003, 0x480a6801, 0x84102542, 0x8410251a, - 0x48126a00, 0x5c00b000, 0x1c01f000, 0x42000000, - 0x0010b67a, 0x0201f800, 0x0010a86e, 0x0201f800, - 0x0010698c, 0x59300203, 0x4933c857, 0x4803c857, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f803, 0x0201f000, 0x00106982, 0x001094d7, - 0x001094e6, 0x001094d8, 0x001094d5, 0x001094d5, - 0x001094d5, 0x001094d5, 0x001094d5, 0x001094d5, - 0x001094d5, 0x001094d5, 0x001094d5, 0x001094d5, - 0x001094d5, 0x0201f800, 0x00100615, 0x1c01f000, - 0x59300403, 0x82000580, 0x00000052, 0x02000000, - 0x00108b39, 0x0201f800, 0x00104a83, 0x59325808, - 0x4a025a06, 0x00000006, 0x0201f800, 0x00020381, - 0x0201f000, 0x00107698, 0x59301804, 0x840c0520, - 0x48026004, 0x598c000d, 0x81300580, 0x04020010, - 0x8c0c1d20, 0x04020010, 0x42001000, 0x0010b5f4, - 0x50081000, 0x58080002, 0x82000580, 0x00000100, - 0x0400000e, 0x5808000c, 0x81300580, 0x02020800, - 0x00100615, 0x4978100c, 0x0401f003, 0x8c0c1d20, - 0x040207dc, 0x0201f800, 0x00106619, 0x040007d9, - 0x0201f800, 0x00100615, 0x0201f800, 0x00106be2, - 0x040007f9, 0x59300203, 0x82000c80, 0x0000000e, - 0x02021800, 0x00100615, 0x0c01f7bd, 0x4933c857, - 0x4c500000, 0x4c540000, 0x4c580000, 0x592c0c07, - 0x4806580a, 0x59cc0809, 0x48065807, 0x59cc0a08, - 0x4806580b, 0x59a8086e, 0x82040500, 0x000003ff, - 0x800010c4, 0x8c040d14, 0x04000005, 0x59cc0002, - 0x82000500, 0x00000003, 0x80081480, 0x82080480, - 0x000000f1, 0x02021800, 0x00100615, 0x480a621a, - 0x412c0800, 0x0201f800, 0x00100819, 0x02000800, - 0x00100615, 0x492c0809, 0x58040408, 0x84000552, - 0x84000540, 0x48000c08, 0x82081400, 0x00000003, - 0x80081104, 0x83cca400, 0x00000006, 0x832cac00, - 0x00000004, 0x42000800, 0x00000010, 0x82080480, - 0x00000010, 0x04021003, 0x40080800, 0x80000580, - 0x4004b000, 0x4c000000, 0x0201f800, 0x0010a94f, - 0x5c000000, 0x800001c0, 0x0400000d, 0x412c1000, - 0x4c000000, 0x0201f800, 0x00100819, 0x02000800, - 0x00100615, 0x492c1001, 0x832cac00, 0x00000004, - 0x5c000000, 0x40001000, 0x0401f7e9, 0x5c00b000, - 0x5c00a800, 0x5c00a000, 0x1c01f000, 0x4933c857, - 0x4d2c0000, 0x4c380000, 0x59325808, 0x5930021a, - 0x48025a08, 0x59301011, 0x800811c0, 0x04020008, - 0x4a025a06, 0x00000000, 0x592c000b, 0x82000500, - 0x00000c00, 0x0400000b, 0x0401f00b, 0x8c08153e, - 0x04000006, 0x4a025a06, 0x00000007, 0x80081080, - 0x80081000, 0x0401f003, 0x4a025a06, 0x00000015, - 0x480a5807, 0x42000000, 0x0010bcd8, 0x50007000, - 0x5838000b, 0x80000540, 0x04020008, 0x4930700c, - 0x4930700b, 0x58380002, 0x82000580, 0x00000000, - 0x04020809, 0x0401f005, 0x82001400, 0x00000000, - 0x45301000, 0x4930700b, 0x5c007000, 0x5c025800, - 0x1c01f000, 0x4933c857, 0x592c0009, 0x40001000, - 0x4800700a, 0x82080400, 0x00000004, 0x48007003, - 0x592c000d, 0x592c100e, 0x48007007, 0x48087008, - 0x592c000a, 0x592c1208, 0x80080c80, 0x04001002, - 0x40001000, 0x82081400, 0x00000003, 0x80081104, - 0x82080480, 0x00000010, 0x04021003, 0x80000580, - 0x0401f003, 0x42001000, 0x00000010, 0x4800700d, - 0x48087004, 0x800810c4, 0x48087005, 0x40381000, - 0x0201f800, 0x001008a1, 0x1c01f000, 0x4d2c0000, - 0x0201f800, 0x00100819, 0x02000800, 0x00100615, - 0x42000800, 0x0010bcd8, 0x452c0800, 0x497a580b, - 0x497a580c, 0x497a580d, 0x4a025809, 0x001095b6, - 0x4a025802, 0x00000100, 0x4a025801, 0x00000000, - 0x5c025800, 0x1c01f000, 0x4833c857, 0x4d300000, - 0x4d2c0000, 0x4c5c0000, 0x4030b800, 0x585c000a, - 0x80025d40, 0x04020004, 0x585c000c, 0x4c000000, - 0x0401f044, 0x585c0002, 0x82000580, 0x00000100, - 0x04020022, 0x592c0801, 0x4c040000, 0x0201f800, - 0x0010083a, 0x5c000800, 0x800409c0, 0x0400001c, - 0x4804b80a, 0x585c100d, 0x800811c0, 0x04020005, - 0x40065800, 0x0201f800, 0x00100843, 0x0401f014, - 0x82080480, 0x00000010, 0x04021003, 0x80000580, - 0x0401f003, 0x42001000, 0x00000010, 0x4800b80d, - 0x4808b804, 0x800810c4, 0x4808b805, 0x82040400, - 0x00000004, 0x4800b803, 0x405c1000, 0x0201f800, - 0x001008a1, 0x0401f025, 0x0401f828, 0x585c000c, - 0x80026540, 0x59300000, 0x80000d40, 0x04020002, - 0x4800b80b, 0x4800b80c, 0x497a6000, 0x4c000000, - 0x4978b80a, 0x59325808, 0x4a025a04, 0x00000103, - 0x59300402, 0x48025c06, 0x592c100b, 0x4c080000, - 0x0201f800, 0x00020381, 0x0201f800, 0x00108ee7, - 0x5c001000, 0x8c081518, 0x04000004, 0x0201f800, - 0x00108f88, 0x0401f003, 0x0201f800, 0x000208b4, - 0x405c7000, 0x5c000000, 0x80026540, 0x04000003, - 0x59325808, 0x0401ff78, 0x5c00b800, 0x5c025800, - 0x5c026000, 0x1c01f000, 0x483bc857, 0x5838000a, - 0x40025800, 0x0201f800, 0x00100843, 0x5838000c, - 0x80026540, 0x59300008, 0x80025d40, 0x4a025a06, - 0x00000002, 0x1c01f000, 0x4803c857, 0x4d1c0000, - 0x497a601c, 0x41323800, 0x40026000, 0x4d3c0000, - 0x42027800, 0x00000005, 0x0401f840, 0x5c027800, - 0x411e6000, 0x59300414, 0x84000502, 0x48026414, - 0x5c023800, 0x1c01f000, 0x481bc857, 0x4933c857, - 0x4c5c0000, 0x4c600000, 0x4010b800, 0x4014c000, - 0x0201f800, 0x0010a766, 0x0201f800, 0x0010393e, - 0x04000008, 0x40602800, 0x405c3000, 0x0201f800, - 0x0010a258, 0x82000540, 0x00000001, 0x0401f002, - 0x80000580, 0x5c00c000, 0x5c00b800, 0x1c01f000, - 0x4803c856, 0x4d300000, 0x42026000, 0x0010cfc0, - 0x59a8000e, 0x81640580, 0x0400001a, 0x59300c06, - 0x82040580, 0x00000001, 0x0400000d, 0x82040580, - 0x00000004, 0x04000006, 0x82040580, 0x00000010, - 0x02000800, 0x00108aad, 0x0401f009, 0x59300203, - 0x82000d80, 0x00000007, 0x04000005, 0x4807c857, - 0x0201f800, 0x0010909d, 0x04020808, 0x83326400, - 0x00000024, 0x41580000, 0x81300480, 0x040017e5, - 0x5c026000, 0x1c01f000, 0x4933c857, 0x59300403, - 0x4803c857, 0x0201f800, 0x0010698c, 0x4df00000, - 0x59300406, 0x4803c857, 0x82000d80, 0x00000002, - 0x04000018, 0x82000d80, 0x00000001, 0x04000009, - 0x82000d80, 0x00000004, 0x04000006, 0x4933c856, - 0x5c03e000, 0x02000800, 0x00106982, 0x0401f03c, - 0x59300203, 0x82000d80, 0x00000001, 0x04000018, - 0x82000d80, 0x00000002, 0x04000026, 0x82000d80, - 0x00000005, 0x04000023, 0x0201f800, 0x00100615, - 0x59300203, 0x82000d80, 0x00000009, 0x0400000c, - 0x82000d80, 0x0000000b, 0x04000009, 0x82000d80, - 0x0000000a, 0x04000017, 0x82000d80, 0x0000000c, - 0x04000014, 0x0201f800, 0x00100615, 0x598c000d, - 0x81300580, 0x04020004, 0x0201f800, 0x00106be2, - 0x0402000c, 0x59300004, 0x4803c857, 0x8c000520, - 0x04000004, 0x84000520, 0x48026004, 0x0401f005, - 0x0201f800, 0x00106619, 0x02020800, 0x00100615, - 0x5c03e000, 0x02000800, 0x00106982, 0x59300406, - 0x82000d80, 0x00000002, 0x04000009, 0x0201f800, - 0x00104a83, 0x0201f800, 0x00108f05, 0x02000800, - 0x00107da6, 0x8d3e7d00, 0x04000003, 0x0201f000, - 0x00107698, 0x4a02621d, 0x00000001, 0x4a026403, - 0x00000085, 0x4a026203, 0x00000009, 0x4a026406, - 0x00000002, 0x42000800, 0x8000004b, 0x0201f000, - 0x00020855, 0x4933c857, 0x59368c03, 0x4c180000, - 0x59300203, 0x82003480, 0x0000000e, 0x02021800, - 0x00100615, 0x0c01f803, 0x5c003000, 0x1c01f000, - 0x001096da, 0x00109bb9, 0x00109cbd, 0x001096da, - 0x001096da, 0x001096da, 0x001096da, 0x001096da, - 0x001096fd, 0x001096da, 0x001096da, 0x001096da, - 0x001096da, 0x001096da, 0x0201f800, 0x00100615, - 0x4933c857, 0x42028800, 0x0000ffff, 0x813669c0, - 0x04000002, 0x59368c03, 0x4c180000, 0x59300203, - 0x82003480, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f803, 0x5c003000, 0x1c01f000, 0x001096f9, - 0x00109f70, 0x001096f9, 0x001096f9, 0x001096f9, - 0x001096f9, 0x001096f9, 0x0010a779, 0x00109edd, - 0x0010a34a, 0x0010a380, 0x0010a34a, 0x0010a380, - 0x001096f9, 0x0201f800, 0x00100615, 0x0201f800, - 0x00100615, 0x83383480, 0x00000051, 0x02021800, - 0x00100615, 0x41380000, 0x493bc857, 0x4d1c0000, - 0x4d400000, 0x0c01f804, 0x5c028000, 0x5c023800, - 0x1c01f000, 0x0010975a, 0x0010993d, 0x0010975a, - 0x0010975a, 0x0010975a, 0x00109948, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a, - 0x0010977c, 0x001097ba, 0x001097d1, 0x0010982d, - 0x00109894, 0x001098d2, 0x00109902, 0x0010975a, - 0x0010975a, 0x00109950, 0x0010975a, 0x0010975a, - 0x0010995e, 0x00109967, 0x0010975a, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x001099e9, - 0x0010975a, 0x0010975a, 0x00109868, 0x0010975a, - 0x0010975a, 0x001099c0, 0x0010975a, 0x0010975a, - 0x0010975a, 0x001099f7, 0x0010975a, 0x0010975a, - 0x0010975a, 0x00109a40, 0x0010975a, 0x0010975a, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a, - 0x00109a8d, 0x0010975a, 0x00109ab9, 0x00109ac4, - 0x0010975a, 0x0010975a, 0x0010975c, 0x00109acf, - 0x0010975a, 0x0010975a, 0x0010975a, 0x0010976b, - 0x0010975a, 0x0010975a, 0x0010975a, 0x00109ad6, - 0x00109ade, 0x00109afc, 0x0201f800, 0x00100615, - 0x4933c857, 0x0201f800, 0x0010a3b0, 0x040203a8, - 0x0201f800, 0x00101eb0, 0x040203a5, 0x59cc0407, - 0x4802601c, 0x4a026403, 0x00000045, 0x4a026203, - 0x00000001, 0x0201f000, 0x00106470, 0x4933c857, - 0x0201f800, 0x0010a3b0, 0x04020399, 0x0201f800, - 0x00101eb0, 0x04020396, 0x0401fbd6, 0x0402019e, - 0x59cc0007, 0x4802601c, 0x4a026403, 0x0000004a, - 0x4a026203, 0x00000001, 0x0201f000, 0x00106470, - 0x4933c857, 0x0201f800, 0x00101eb0, 0x04020009, - 0x0201f800, 0x0010473b, 0x04020006, 0x82000500, - 0x00000009, 0x82000580, 0x00000008, 0x04020008, - 0x4a026403, 0x00000009, 0x4a02641a, 0x00000009, - 0x4a02621a, 0x00000000, 0x0401f1b6, 0x0201f800, - 0x00104858, 0x04000018, 0x0201f800, 0x0010a041, - 0x0402001f, 0x42028000, 0x00000029, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x0201f800, 0x00104480, 0x4a026403, 0x00000008, - 0x42003000, 0x00000003, 0x0201f800, 0x0010393e, - 0x040001a0, 0x4a026203, 0x00000007, 0x41782800, - 0x0401f18b, 0x0201f800, 0x0010a1ec, 0x040207e7, - 0x4a026403, 0x00000009, 0x4a02641a, 0x0000000e, - 0x4a02621a, 0x00001900, 0x0401f192, 0x4a026403, - 0x00000009, 0x4a02641a, 0x00000003, 0x4a02621a, - 0x00000f00, 0x0401f18b, 0x4933c857, 0x0201f800, - 0x00101eb0, 0x0402034a, 0x0201f800, 0x0010473b, - 0x04020347, 0x493a6403, 0x0201f800, 0x0010a01c, - 0x04020006, 0x42003000, 0x00000005, 0x4a026403, - 0x00000006, 0x0401f7d9, 0x4a026403, 0x00000007, - 0x4a02641a, 0x00000009, 0x4a02621a, 0x00000000, - 0x0401f174, 0x4933c857, 0x0201f800, 0x0010473b, - 0x04020333, 0x0201f800, 0x0010a3b0, 0x02000800, - 0x00101eb0, 0x0402032e, 0x0201f800, 0x00104858, - 0x04020005, 0x42027800, 0x00000001, 0x0201f800, - 0x001043bd, 0x0201f800, 0x0010484b, 0x04020031, - 0x59cc0206, 0x82003500, 0x00000003, 0x04020034, - 0x82003480, 0x00000014, 0x04001031, 0x5934300a, - 0x84183516, 0x82000580, 0x00000014, 0x04020002, - 0x84183556, 0x481a680a, 0x59cc0406, 0x82000500, - 0x00000003, 0x04020026, 0x0201f800, 0x0010a08e, - 0x0402002e, 0x0201f800, 0x00104836, 0x04020007, - 0x4c600000, 0x4178c000, 0x417a7800, 0x0201f800, - 0x00101e48, 0x5c00c000, 0x836c0580, 0x00000003, - 0x04020009, 0x42003000, 0x00000006, 0x0201f800, - 0x0010a75e, 0x42000000, 0x0010b664, 0x0201f800, - 0x0010a86e, 0x0201f800, 0x001044e1, 0x4a026403, - 0x0000000a, 0x42003000, 0x00000020, 0x0401f78f, - 0x4a026403, 0x0000000b, 0x4a02641a, 0x00000009, - 0x4a02621a, 0x00001e00, 0x0401f12a, 0x42000000, - 0x0010b65f, 0x0201f800, 0x0010a86e, 0x4a026403, - 0x0000000b, 0x4a02641a, 0x00000007, 0x4a02621a, - 0x00000000, 0x0401f11f, 0x4a026403, 0x0000000b, - 0x4a02641a, 0x00000003, 0x4a02621a, 0x00000000, - 0x0401f118, 0x4933c857, 0x0201f800, 0x0010473b, - 0x040202d7, 0x0201f800, 0x0010a3b0, 0x040202d4, - 0x0201f800, 0x00101eb0, 0x040202d1, 0x59cc0206, - 0x82003500, 0x00000003, 0x04020020, 0x82003480, - 0x00000014, 0x0400101d, 0x59cc0406, 0x82000500, - 0x00000003, 0x04020019, 0x59340400, 0x82000580, - 0x00000707, 0x0400001c, 0x417a7800, 0x4c600000, - 0x4178c000, 0x0201f800, 0x00101e48, 0x5c00c000, - 0x42003000, 0x0000000a, 0x0201f800, 0x0010a75e, - 0x42000000, 0x0010b661, 0x0201f800, 0x0010a86e, - 0x4a026403, 0x0000000c, 0x41782800, 0x42003000, - 0x00000021, 0x0401f749, 0x4a026403, 0x0000000d, - 0x4a02641a, 0x00000007, 0x4a02621a, 0x00000000, - 0x0401f0e4, 0x4a026403, 0x0000000d, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00001e00, 0x0401f0dd, - 0x4933c857, 0x0201f800, 0x0010473b, 0x0402029c, - 0x0201f800, 0x0010a3b0, 0x04020299, 0x0201f800, - 0x00101eb0, 0x04020296, 0x0401fad6, 0x0402001a, - 0x493a6403, 0x4c5c0000, 0x0401fadc, 0x0402000e, - 0x4a026403, 0x0000002e, 0x4014b800, 0x0201f800, - 0x0010393e, 0x0400000e, 0x4a026203, 0x00000007, - 0x405c2800, 0x42003000, 0x00000024, 0x5c00b800, - 0x0401f0af, 0x4a026403, 0x0000000d, 0x4a02641a, - 0x00000007, 0x4a02621a, 0x00000000, 0x5c00b800, - 0x0401f0b8, 0x4a026403, 0x0000000d, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00001e00, 0x0401f0b1, - 0x4933c857, 0x0201f800, 0x0010473b, 0x040206f1, - 0x59a80026, 0x82000500, 0x00000009, 0x82000580, - 0x00000008, 0x040006eb, 0x0201f800, 0x0010484b, - 0x0402002d, 0x0201f800, 0x0010a096, 0x04020007, - 0x4a026403, 0x0000000e, 0x41782800, 0x42003000, - 0x00000052, 0x0401f6f9, 0x4933c857, 0x42003000, - 0x00000003, 0x0201f800, 0x0010a766, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x59340200, 0x84000558, 0x48026a00, 0x42000800, - 0x0000000b, 0x0201f800, 0x001043c7, 0x0201f800, - 0x0010393e, 0x0400007c, 0x42003000, 0x00000007, - 0x0401f061, 0x4933c857, 0x4a026403, 0x0000000f, - 0x4a02641a, 0x00000003, 0x4a02621a, 0x00001e00, - 0x0401f078, 0x59340400, 0x82000580, 0x00000703, - 0x040007f5, 0x0401f040, 0x4933c857, 0x0201f800, - 0x0010473b, 0x04020232, 0x59a80026, 0x82000500, - 0x00000009, 0x82000580, 0x00000008, 0x0400022c, - 0x0201f800, 0x00104842, 0x0402002f, 0x0201f800, - 0x0010a0b1, 0x02000800, 0x0010a041, 0x04020007, - 0x4a026403, 0x00000010, 0x41782800, 0x42003000, - 0x00000050, 0x0401f6b9, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x00101de2, 0x5c027800, 0x42003000, - 0x00000003, 0x0201f800, 0x0010a766, 0x42000000, - 0x0010b663, 0x0201f800, 0x0010a86e, 0x59340200, - 0x84000558, 0x48026a00, 0x0401f7c5, 0x4a026403, - 0x00000011, 0x4a02641a, 0x00000003, 0x4a02621a, - 0x00001e00, 0x0401f043, 0x4933c857, 0x0201f800, - 0x00101eb0, 0x02000800, 0x0010a3b0, 0x04020200, - 0x0401fa40, 0x04020008, 0x4a026403, 0x00000012, - 0x0401f038, 0x59340400, 0x82000580, 0x00000703, - 0x040007eb, 0x4d3c0000, 0x417a7800, 0x42028000, - 0x00000029, 0x0201f800, 0x00101de2, 0x5c027800, - 0x42003000, 0x00000017, 0x0201f800, 0x0010a766, - 0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e, - 0x0201f800, 0x0010393e, 0x0400001b, 0x42003000, - 0x00000006, 0x42028000, 0x00000029, 0x4933c857, - 0x4a026403, 0x00000001, 0x4a026203, 0x00000007, - 0x4c180000, 0x0201f800, 0x0010a79b, 0x5c003000, - 0x41782800, 0x0201f000, 0x0010a250, 0x42028000, - 0x00000046, 0x4c140000, 0x4c180000, 0x0201f800, - 0x0010a79b, 0x5c003000, 0x5c002800, 0x0201f000, - 0x0010a250, 0x4933c857, 0x4a026403, 0x00000001, - 0x42000800, 0x0000000b, 0x0201f800, 0x001043c7, - 0x4a026203, 0x00000001, 0x0201f000, 0x00106470, - 0x4933c857, 0x42000800, 0x00000009, 0x0201f800, - 0x001043c7, 0x4a026403, 0x00000005, 0x0401f7f5, - 0x0201f800, 0x0010a3b0, 0x040201b5, 0x0201f800, - 0x00101eb0, 0x040201b2, 0x0401f9f2, 0x040207ba, - 0x4a026403, 0x00000020, 0x4a026203, 0x00000001, - 0x0201f000, 0x00106470, 0x0201f800, 0x00101eb0, - 0x040201a7, 0x4a026403, 0x00000023, 0x4a026203, - 0x00000001, 0x0201f000, 0x00106470, 0x0201f800, - 0x0010a3b0, 0x02000800, 0x00101eb0, 0x0402019c, - 0x0401f9dc, 0x040207a4, 0x40300800, 0x59a81010, - 0x59cc0007, 0x82000500, 0x00ffffff, 0x80080580, - 0x04000019, 0x59cc1408, 0x0201f800, 0x00108de9, - 0x0400002d, 0x59cc0c08, 0x4d300000, 0x0201f800, - 0x00105b0f, 0x41323800, 0x5c026000, 0x04000026, - 0x591c0202, 0x82000580, 0x0000ffff, 0x04000005, - 0x59cc1208, 0x591c0202, 0x80080580, 0x0402001e, - 0x591c0406, 0x82000580, 0x00000007, 0x0402001a, - 0x0401f02c, 0x59cc1208, 0x82080580, 0x0000ffff, - 0x0400000c, 0x0201f800, 0x001091d9, 0x04000012, - 0x59cc1408, 0x591c0202, 0x80080580, 0x0402000e, - 0x591c0009, 0x81340580, 0x04000016, 0x0401f00a, - 0x59cc1408, 0x417a7800, 0x0201f800, 0x0010a217, - 0x04020010, 0x59cc1208, 0x82080580, 0x0000ffff, - 0x04000019, 0x4a026403, 0x00000026, 0x4a02621a, - 0x00001700, 0x59cc1204, 0x82081580, 0x0000ffff, - 0x04020798, 0x4a026403, 0x00000025, 0x0401f795, - 0x591c0406, 0x82000580, 0x00000007, 0x040207f2, - 0x591c0403, 0x82000580, 0x00000024, 0x04020006, - 0x4d300000, 0x411e6000, 0x0201f800, 0x000208b4, - 0x5c026000, 0x4a026403, 0x00000025, 0x0401f785, - 0x4933c857, 0x4d3c0000, 0x42027800, 0x00000001, - 0x0201f800, 0x001043bd, 0x5c027800, 0x4c580000, - 0x4200b000, 0x00000002, 0x83a81c00, 0x00000002, - 0x83cc1400, 0x0000000b, 0x0201f800, 0x001082ff, - 0x5c00b000, 0x04000004, 0x4a026403, 0x00000031, - 0x0401f770, 0x0201f800, 0x00107698, 0x0201f800, - 0x00104e0d, 0x0402000f, 0x0201f800, 0x00104e1b, - 0x04020008, 0x4a035033, 0x00000001, 0x4202d800, - 0x00000001, 0x0201f800, 0x00104d76, 0x0401f005, - 0x42000000, 0x00000001, 0x0201f800, 0x00104de5, - 0x1c01f000, 0x0201f800, 0x00101eb0, 0x0402011c, - 0x0401f95c, 0x04020724, 0x493a6403, 0x0401f9ac, - 0x04020004, 0x4a026403, 0x0000002b, 0x0401f751, - 0x4a026403, 0x0000002c, 0x0401f74e, 0x4933c857, - 0x0201f800, 0x00101eb0, 0x0402010d, 0x0201f800, - 0x00104836, 0x04020740, 0x0201f800, 0x00104728, - 0x0400003c, 0x59cc0408, 0x48026419, 0x59cc0208, - 0x48026219, 0x59cc0807, 0x59340002, 0x82000500, - 0x00ffffff, 0x80040580, 0x04000012, 0x59a80010, - 0x80040580, 0x04020021, 0x59cc1408, 0x0201f800, - 0x001091d9, 0x04000023, 0x0201f800, 0x0010a2e8, - 0x04000020, 0x0201f800, 0x0010a745, 0x0400001d, - 0x491e601e, 0x4a026403, 0x00000036, 0x0401f0e6, - 0x59cc1208, 0x82080580, 0x0000ffff, 0x04000009, - 0x0201f800, 0x001091d9, 0x04000012, 0x591c0202, - 0x59cc0c08, 0x80040580, 0x0402000e, 0x0401f7eb, - 0x59cc1408, 0x41327800, 0x0201f800, 0x0010a217, - 0x04000008, 0x0401f7e5, 0x4803c856, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00001500, 0x0401f006, - 0x4803c856, 0x4a02641a, 0x00000003, 0x4a02621a, - 0x00001700, 0x4a026403, 0x00000037, 0x0401f0c6, - 0x4803c856, 0x4a026403, 0x00000012, 0x0401f0c2, - 0x4933c857, 0x0201f800, 0x00101eb0, 0x040200c4, - 0x0201f800, 0x00104836, 0x040206f7, 0x0201f800, - 0x00104728, 0x0400003e, 0x59cc0407, 0x48026419, - 0x59cc1207, 0x480a6219, 0x82080580, 0x0000ffff, - 0x04000005, 0x0201f800, 0x001091d9, 0x0400002c, - 0x0401f006, 0x59cc1407, 0x41327800, 0x0201f800, - 0x0010a217, 0x04000026, 0x59cc0c07, 0x591c0202, - 0x80040580, 0x04020022, 0x4d300000, 0x411e6000, - 0x0201f800, 0x0010898b, 0x5c026000, 0x59cc0c09, - 0x82040d00, 0x0000ff00, 0x840409c0, 0x0201f800, - 0x0010a745, 0x04000016, 0x82040580, 0x00000001, - 0x0400000a, 0x82040580, 0x00000005, 0x04000004, - 0x82040580, 0x00000007, 0x04020007, 0x591c0008, - 0x80000540, 0x04000004, 0x59cc2808, 0x0201f000, - 0x0010a2fc, 0x4803c856, 0x4a02641a, 0x00000009, - 0x4a02621a, 0x00002a00, 0x0401f006, 0x4803c856, - 0x4a02641a, 0x00000003, 0x4a02621a, 0x00000300, - 0x4a026403, 0x0000003b, 0x0401f07b, 0x4803c856, - 0x4a02641a, 0x0000000b, 0x4a02621a, 0x00000000, - 0x0401f7f8, 0x4c080000, 0x0201f800, 0x0010473b, - 0x04000026, 0x0201f800, 0x00104711, 0x0201f800, - 0x0010a41c, 0x0402001e, 0x59a80026, 0x82000540, - 0x00000003, 0x48035026, 0x59a8001d, 0x800000d0, - 0x59a80810, 0x82040d00, 0x000000ff, 0x80041540, - 0x480b5010, 0x42000800, 0x00000003, 0x0201f800, - 0x001069af, 0x497b5028, 0x0201f800, 0x0010393e, - 0x04000003, 0x4a032804, 0x000007d0, 0x8c00050a, - 0x0402000a, 0x0201f800, 0x000208b4, 0x0201f800, - 0x00101bf0, 0x5c001000, 0x1c01f000, 0x0201f800, - 0x0010a43e, 0x0401f7fc, 0x5c001000, 0x0201f000, - 0x000208b4, 0x0201f800, 0x00101eb0, 0x0402004c, - 0x0201f800, 0x0010a443, 0x4a026403, 0x00000047, - 0x4a026203, 0x00000001, 0x0201f000, 0x00106470, - 0x0201f800, 0x00101eb0, 0x04020041, 0x0201f800, - 0x0010a443, 0x4a026403, 0x00000047, 0x4a026203, - 0x00000001, 0x0201f000, 0x00106470, 0x0201f800, - 0x00101eb0, 0x04020036, 0x0201f800, 0x0010a443, - 0x0201f000, 0x000208b4, 0x0401f834, 0x04000030, - 0x4a026403, 0x0000004e, 0x4a026203, 0x00000001, - 0x0201f000, 0x00106470, 0x4a026403, 0x0000004f, - 0x497a601c, 0x59cc0a06, 0x82040d00, 0x000000ff, - 0x800409c0, 0x0400065f, 0x82040580, 0x00000001, - 0x04020005, 0x59cc0808, 0x59a80005, 0x80040580, - 0x04000658, 0x82040580, 0x00000002, 0x0402000a, - 0x83cc1400, 0x0000000b, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000006, 0x0201f800, 0x001082ff, - 0x0400064c, 0x4a02601c, 0x00000001, 0x0401f649, - 0x4a026403, 0x00000050, 0x59cc0207, 0x4802601c, - 0x0401f644, 0x4a026203, 0x00000001, 0x42000800, - 0x80000040, 0x0201f000, 0x00020855, 0x4803c857, - 0x0201f000, 0x000208b4, 0x4d2c0000, 0x4c500000, - 0x4c580000, 0x4c540000, 0x59a80016, 0x82000c80, - 0x00000841, 0x0402102d, 0x0201f800, 0x00100819, - 0x0400002a, 0x492e6008, 0x59a80016, 0x48025802, - 0x82000400, 0x00000003, 0x80000104, 0x83cca400, - 0x00000006, 0x82000c80, 0x0000000b, 0x04001015, - 0x4a025811, 0x0000000b, 0x4200b000, 0x0000000b, - 0x832c0400, 0x00000005, 0x4000a800, 0x0201f800, - 0x0010a93e, 0x412c7000, 0x800409c0, 0x04020003, - 0x49787001, 0x0401f00e, 0x0201f800, 0x00100819, - 0x0400000e, 0x492c7001, 0x40040000, 0x0401f7ea, - 0x48025811, 0x4000b000, 0x832c0400, 0x00000005, - 0x4000a800, 0x0201f800, 0x0010a93e, 0x82000540, - 0x00000001, 0x0401f006, 0x497b5016, 0x59325808, - 0x0201f800, 0x00100843, 0x80000580, 0x5c00a800, - 0x5c00b000, 0x5c00a000, 0x5c025800, 0x1c01f000, - 0x4d340000, 0x59326809, 0x59343400, 0x4933c857, - 0x4937c857, 0x481bc857, 0x0201f800, 0x00104842, - 0x5c026800, 0x1c01f000, 0x4933c857, 0x4c600000, - 0x4c5c0000, 0x4d3c0000, 0x4d440000, 0x4d340000, - 0x0401f84f, 0x04020037, 0x59cc0207, 0x82000d00, - 0x0000ff00, 0x900411c0, 0x59cc000a, 0x82000500, - 0x00ffffff, 0x80081540, 0x480a601c, 0x8c040d18, - 0x04000011, 0x42003000, 0x00000008, 0x0201f800, - 0x0010a756, 0x42000000, 0x0010b662, 0x0201f800, - 0x0010a86e, 0x4200b800, 0x00000002, 0x4200c000, - 0x00000001, 0x417a7800, 0x0201f800, 0x00101e48, - 0x0401f01f, 0x4178b800, 0x8c040d1a, 0x04000019, - 0x59cc000a, 0x0201f800, 0x001059b9, 0x02000800, - 0x00020267, 0x04020013, 0x59300009, 0x4c000000, - 0x49366009, 0x42003000, 0x00000009, 0x0201f800, - 0x0010a75e, 0x42000000, 0x0010b662, 0x0201f800, - 0x0010a86e, 0x417a7800, 0x4178c000, 0x0201f800, - 0x00101e48, 0x5c000000, 0x48026009, 0x0401f004, - 0x82000540, 0x00000001, 0x0401f003, 0x405c2800, - 0x80000580, 0x5c026800, 0x5c028800, 0x5c027800, - 0x5c00b800, 0x5c00c000, 0x1c01f000, 0x4933c857, - 0x59cc0206, 0x82000480, 0x00000010, 0x04021006, - 0x4a02621a, 0x00000000, 0x82000540, 0x00000001, - 0x0401f002, 0x80000580, 0x1c01f000, 0x4933c857, - 0x4a02621a, 0x00000000, 0x59cc0407, 0x82000500, - 0x0000ff00, 0x82000580, 0x00000800, 0x04020009, - 0x59cc0006, 0x82000500, 0x00ff0000, 0x82000d80, - 0x00140000, 0x04000003, 0x82000d80, 0x00100000, - 0x1c01f000, 0x59300403, 0x82003480, 0x00000051, - 0x02021800, 0x00100615, 0x83383580, 0x00000013, - 0x04020003, 0x4803c857, 0x0c01f016, 0x4933c857, - 0x493bc857, 0x83383580, 0x00000027, 0x04000005, - 0x83383580, 0x00000014, 0x02020800, 0x00100615, - 0x493bc857, 0x4937c857, 0x0201f800, 0x00104711, - 0x42000800, 0x00000007, 0x0201f800, 0x001043c7, - 0x0201f800, 0x001068f6, 0x0201f000, 0x00107698, - 0x00109c29, 0x00109c32, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c32, 0x00109c3d, 0x00109cb0, - 0x00109c82, 0x00109cb0, 0x00109c9a, 0x00109cb0, - 0x00109ca1, 0x00109cb0, 0x00109ca9, 0x00109cb0, - 0x00109ca9, 0x00109cb0, 0x00109cb0, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c32, 0x00109c29, - 0x00109cb0, 0x00109c29, 0x00109c29, 0x00109cb0, - 0x00109c29, 0x00109cad, 0x00109cb0, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c29, 0x00109cb0, - 0x00109cb0, 0x00109c29, 0x00109ca6, 0x00109cb0, - 0x00109c29, 0x00109c37, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109cac, 0x00109cb0, - 0x00109c29, 0x00109c29, 0x00109cb0, 0x00109cb0, - 0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29, - 0x00109c29, 0x00109c2b, 0x00109c29, 0x00109c2b, - 0x00109c29, 0x00109c29, 0x00109c2b, 0x00109c29, - 0x00109c29, 0x00109c29, 0x00109c2b, 0x00109c2b, - 0x00109c2b, 0x0201f800, 0x00100615, 0x4d2c0000, - 0x59325808, 0x0201f800, 0x00100843, 0x5c025800, - 0x0201f000, 0x000208b4, 0x59a80037, 0x48026206, - 0x4a026203, 0x00000002, 0x1c01f000, 0x4d3c0000, - 0x417a7800, 0x0201f800, 0x001043bd, 0x5c027800, - 0x0401f074, 0x42000800, 0x00000007, 0x0201f800, - 0x001043c7, 0x59a80026, 0x8c000508, 0x04000012, - 0x59326809, 0x4c580000, 0x4200b000, 0x00000002, - 0x83a81c00, 0x00000002, 0x83341400, 0x00000006, - 0x0201f800, 0x001082ff, 0x80000540, 0x5c00b000, - 0x04020060, 0x59340200, 0x8400051a, 0x48026a00, - 0x0401f01b, 0x599c0017, 0x8c00050a, 0x04020059, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x001043bd, - 0x5c027800, 0x42000800, 0x00000007, 0x0201f800, - 0x001043c7, 0x59340212, 0x82000500, 0x0000ff00, - 0x0400004c, 0x599c0019, 0x8c00050e, 0x04020049, - 0x416c0000, 0x82000580, 0x00000002, 0x04020004, - 0x59a8001b, 0x80000000, 0x4803501b, 0x42000800, - 0x00000003, 0x0201f800, 0x001043c7, 0x4a026406, - 0x00000001, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000002, 0x0201f800, 0x00106470, 0x4ce80000, - 0x4201d000, 0x00000001, 0x0201f800, 0x00105ce7, - 0x5c01d000, 0x1c01f000, 0x0201f800, 0x00104842, - 0x0400002c, 0x0201f800, 0x00106196, 0x42000800, - 0x00000004, 0x0201f800, 0x001043c7, 0x0201f800, - 0x0010a791, 0x04020023, 0x42000800, 0x00000005, - 0x0201f800, 0x001043c7, 0x4a026406, 0x00000001, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000003, - 0x0201f000, 0x00106470, 0x0201f800, 0x0010484b, - 0x04020014, 0x42000800, 0x00000006, 0x0401f813, - 0x0401f010, 0x42000800, 0x00000004, 0x0201f800, - 0x001043c7, 0x0401f79c, 0x42000800, 0x00000004, - 0x0401f006, 0x0201f800, 0x00104711, 0x0401f005, - 0x0401f004, 0x0401f003, 0x0201f800, 0x001043c7, - 0x0201f000, 0x000208b4, 0x4933c857, 0x4807c857, - 0x0201f800, 0x001043c7, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x001043bd, 0x5c027800, 0x0201f000, - 0x00104711, 0x59340400, 0x4803c857, 0x80000110, - 0x82003480, 0x0000000c, 0x02021800, 0x00100615, - 0x83383580, 0x00000015, 0x04020002, 0x0c01f006, - 0x83383580, 0x00000016, 0x02020800, 0x00100615, - 0x0c01f00d, 0x00107e42, 0x00107e42, 0x00107e42, - 0x00107e42, 0x00107e42, 0x00107e42, 0x00109d11, - 0x00109ce5, 0x00107e42, 0x00107e42, 0x00107e42, - 0x00107e42, 0x00107e42, 0x00107e42, 0x00107e42, - 0x00107e42, 0x00107e42, 0x00107e42, 0x00109d11, - 0x00109d18, 0x00107e42, 0x00107e42, 0x00107e42, - 0x00107e42, 0x4933c857, 0x599c0017, 0x8c00050a, - 0x0402001b, 0x813669c0, 0x04000019, 0x59340212, - 0x82000500, 0x0000ff00, 0x04000015, 0x599c0019, - 0x8c00050e, 0x04020012, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x001043bd, 0x5c027800, 0x42000800, - 0x00000003, 0x0201f800, 0x001043c7, 0x4a026406, - 0x00000001, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000002, 0x0201f000, 0x00106470, 0x59cc0001, - 0x59340802, 0x80040580, 0x82000500, 0x00ffffff, - 0x02020000, 0x000208b4, 0x59345002, 0x0201f800, - 0x001040e4, 0x482a6802, 0x0201f000, 0x000208b4, - 0x1c01f000, 0x4933c857, 0x59303403, 0x82183580, - 0x0000001e, 0x02000000, 0x000208b4, 0x1c01f000, - 0x4933c857, 0x0201f800, 0x00108180, 0x02020000, - 0x000208b4, 0x4a026203, 0x00000001, 0x4a026403, - 0x00000001, 0x0201f000, 0x00106470, 0x493bc857, - 0x83380580, 0x00000051, 0x0402000b, 0x0201f800, - 0x00106cb4, 0x02020000, 0x001076fb, 0x59300203, - 0x82000580, 0x00000002, 0x0400006e, 0x0201f800, - 0x00100615, 0x83380580, 0x00000027, 0x04000014, - 0x83380580, 0x00000048, 0x04000006, 0x83380580, - 0x00000014, 0x0400000e, 0x02020800, 0x00100615, - 0x0201f800, 0x00106cb4, 0x02020000, 0x001076fb, - 0x59300203, 0x82000580, 0x00000004, 0x02000000, - 0x000209a5, 0x0201f800, 0x00100615, 0x4933c857, - 0x59300403, 0x82000c80, 0x00000044, 0x02021800, - 0x00100615, 0x82000480, 0x00000040, 0x02001800, - 0x00100615, 0x40027000, 0x4803c857, 0x0c01f001, - 0x00109d58, 0x00109d5a, 0x00109d5a, 0x00109d75, - 0x0201f800, 0x00100615, 0x0201f800, 0x001068f6, - 0x59325808, 0x812e59c0, 0x04000016, 0x832c0500, - 0x00ff0000, 0x04000013, 0x4a026203, 0x00000002, - 0x59326809, 0x59340200, 0x8c00050e, 0x0402000d, - 0x42028000, 0x00000004, 0x0201f800, 0x0010a201, - 0x497a6008, 0x59300206, 0x80000540, 0x04020003, - 0x59a80038, 0x48026206, 0x4a026203, 0x00000007, - 0x1c01f000, 0x0201f800, 0x001068f6, 0x0201f800, - 0x00108df4, 0x02000000, 0x00107698, 0x59325808, - 0x0201f800, 0x0010083a, 0x0201f000, 0x00107698, - 0x0201f800, 0x00100615, 0x59325808, 0x592c040a, - 0x8c000502, 0x04000007, 0x4a026203, 0x00000007, - 0x42027000, 0x00000043, 0x0201f000, 0x000208d8, - 0x4a026203, 0x00000004, 0x1c01f000, 0x0201f800, - 0x0010a3b6, 0x02000000, 0x000209a3, 0x1c01f000, - 0x4a026203, 0x00000001, 0x4a026403, 0x00000041, - 0x42027800, 0x80002042, 0x0201f000, 0x00020855, - 0x83380580, 0x00000051, 0x04000006, 0x83380580, - 0x00000041, 0x02020800, 0x00100615, 0x1c01f000, - 0x0201f800, 0x00020831, 0x0201f800, 0x0010a3fa, - 0x0201f000, 0x000208b4, 0x83380480, 0x00000052, - 0x02021800, 0x00100615, 0x83380480, 0x00000049, - 0x02001800, 0x00100615, 0x0c01f001, 0x00109dbe, - 0x00109ddf, 0x00109dbc, 0x00109dbc, 0x00109dbc, - 0x00109dbc, 0x00109ddf, 0x00109dbc, 0x00109e01, - 0x0201f800, 0x00100615, 0x59325808, 0x592c040a, - 0x8c00051e, 0x0400000d, 0x82000d00, 0x000000c0, - 0x82040d80, 0x00000080, 0x0400000d, 0x59300804, - 0x8c040d18, 0x0402000a, 0x42027000, 0x00000041, - 0x0201f000, 0x000209c4, 0x4a026203, 0x00000007, - 0x497a6206, 0x0201f000, 0x00020831, 0x59325808, - 0x592c0c0a, 0x8c040d1a, 0x04020005, 0x0201f800, - 0x00020831, 0x0201f000, 0x000208b4, 0x0201f800, - 0x0010a3b6, 0x040007fa, 0x1c01f000, 0x0201f800, - 0x001068c1, 0x59325808, 0x59326809, 0x59340200, - 0x8c00050e, 0x0400000e, 0x592c040a, 0x82000500, - 0x000000c0, 0x82000580, 0x00000080, 0x04000005, - 0x592c000f, 0x59301815, 0x800c1c80, 0x480e6015, - 0x4a026203, 0x00000002, 0x0401f00e, 0x42028000, - 0x00000004, 0x0201f800, 0x0010a201, 0x59300206, - 0x80000540, 0x04020004, 0x59a80038, 0x800000c2, - 0x48026206, 0x497a6008, 0x4a026203, 0x00000007, - 0x1c01f000, 0x4933c857, 0x0201f800, 0x00106cb4, - 0x02020800, 0x00100615, 0x59300203, 0x82000580, - 0x00000002, 0x04000793, 0x0201f800, 0x00100615, - 0x4a026203, 0x00000007, 0x497a6206, 0x0201f000, - 0x00020831, 0x4a026203, 0x00000007, 0x497a6206, - 0x0201f000, 0x0002082c, 0x59300414, 0x8c00051c, - 0x02020000, 0x000209b5, 0x59325808, 0x592c200f, - 0x40080000, 0x80102480, 0x59300015, 0x80102400, - 0x48126015, 0x0201f000, 0x000209b5, 0x8c040d0e, - 0x0402000a, 0x4a026203, 0x00000006, 0x0401f823, - 0x5930001f, 0x80000540, 0x02020800, 0x00100dc4, - 0x0201f000, 0x0002082c, 0x4a026203, 0x00000002, - 0x1c01f000, 0x42000800, 0x00000001, 0x0201f800, - 0x00100dc4, 0x82040580, 0x00000001, 0x02000000, - 0x000209bc, 0x0401f7d8, 0x59300414, 0x8c00051c, - 0x04000006, 0x0201f800, 0x00100bad, 0x02000000, - 0x000209ae, 0x1c01f000, 0x59300011, 0x80000540, - 0x04020005, 0x0201f800, 0x00100bad, 0x02000000, - 0x000209ae, 0x1c01f000, 0x492fc857, 0x480bc857, - 0x8c08153e, 0x04000006, 0x80081080, 0x80081000, - 0x42000800, 0x00000009, 0x0401f003, 0x42000800, - 0x00000015, 0x480a580b, 0x1c01f000, 0x83380580, - 0x00000013, 0x04000005, 0x83380580, 0x00000014, - 0x02020800, 0x00100615, 0x59300414, 0x8c000516, - 0x02000800, 0x00100615, 0x1c01f000, 0x0201f800, - 0x00100615, 0x59300008, 0x80000540, 0x02020800, - 0x00100615, 0x1c01f000, 0x59300414, 0x8c000516, - 0x02000800, 0x00100615, 0x1c01f000, 0x4a026203, - 0x00000004, 0x493a6403, 0x42000800, 0x80002001, - 0x0201f000, 0x00020855, 0x4a026203, 0x00000003, - 0x493a6403, 0x0201f800, 0x000200ca, 0x59325808, - 0x592c040a, 0x8c00051e, 0x04000012, 0x82000500, - 0x000000c0, 0x82000580, 0x00000080, 0x04000011, - 0x59300414, 0x8c000512, 0x0402000a, 0x8c000510, - 0x04020008, 0x592c040c, 0x80000540, 0x04020005, - 0x82080d40, 0x80003065, 0x0201f000, 0x00106466, - 0x82080d40, 0x80002065, 0x0201f000, 0x00106466, - 0x82080d40, 0x80002042, 0x0201f000, 0x00106466, - 0x4933c857, 0x493bc857, 0x83380480, 0x00000044, - 0x02021800, 0x00100615, 0x83380480, 0x00000041, - 0x02001800, 0x00100615, 0x0c01f001, 0x00109ea6, - 0x00109eb6, 0x00109ecb, 0x59325808, 0x592c040a, - 0x8c00051e, 0x0400001d, 0x82001d00, 0x000000c0, - 0x820c1d80, 0x000000c0, 0x04000018, 0x4a026203, - 0x00000001, 0x493a6403, 0x42000800, 0x80002042, - 0x0201f000, 0x00020855, 0x59325808, 0x592c040a, - 0x8c00051e, 0x0400000d, 0x82001d00, 0x000000c0, - 0x820c1d80, 0x000000c0, 0x04000008, 0x4a026203, - 0x00000001, 0x493a6403, 0x42000800, 0x80002001, - 0x0201f000, 0x00020855, 0x497a6008, 0x497a6206, - 0x42028000, 0x00000004, 0x0401f337, 0x59325808, - 0x592c040a, 0x8c00051e, 0x040007f8, 0x82001d00, - 0x000000c0, 0x820c1d80, 0x000000c0, 0x040007f3, - 0x4a026203, 0x00000003, 0x493a6403, 0x0201f800, - 0x000200ca, 0x82080d40, 0x80002065, 0x0201f000, - 0x00106466, 0x4933c857, 0x493bc857, 0x83380580, - 0x00000085, 0x04000006, 0x83380580, 0x00000088, - 0x0400000a, 0x0201f800, 0x00100615, 0x4a026203, - 0x00000009, 0x493a6403, 0x42000800, 0x8000004b, - 0x0201f000, 0x00020855, 0x4d1c0000, 0x813669c0, - 0x04000004, 0x0201f800, 0x0010a3b0, 0x04020044, - 0x59cc1404, 0x0401f846, 0x04000018, 0x591c0406, - 0x82000500, 0x0000001f, 0x82002580, 0x00000006, - 0x04000007, 0x82002580, 0x00000004, 0x0400002e, - 0x82002580, 0x00000011, 0x0402000c, 0x497a3a05, - 0x42002000, 0x00000054, 0x0201f800, 0x001077d1, - 0x4a026203, 0x00000007, 0x493a6403, 0x0201f800, - 0x0010a79b, 0x0401f02c, 0x0201f800, 0x0010393e, - 0x04000004, 0x42023800, 0xffffffff, 0x0401f7f1, - 0x813669c0, 0x04020009, 0x59cc0001, 0x0201f800, - 0x001059b9, 0x0402001e, 0x0201f800, 0x001043fc, - 0x0402001b, 0x49366009, 0x4a026403, 0x00000087, - 0x59cc1204, 0x82081580, 0x0000ffff, 0x04020003, - 0x4a026403, 0x00000086, 0x4a026203, 0x00000001, - 0x42000800, 0x80000040, 0x0201f800, 0x00020855, - 0x0401f00d, 0x591c0203, 0x82000580, 0x00000007, - 0x040207de, 0x4d300000, 0x411e6000, 0x0201f800, - 0x00107698, 0x5c026000, 0x0401f7d8, 0x0201f800, - 0x00107698, 0x5c023800, 0x1c01f000, 0x4933c857, - 0x480bc857, 0x42002800, 0x0010cfc0, 0x41300000, - 0x80140580, 0x04000017, 0x58140203, 0x82000580, - 0x00000000, 0x04000013, 0x58140202, 0x80080580, - 0x04020010, 0x58141c06, 0x820c0580, 0x00000005, - 0x0400000c, 0x820c0580, 0x00000009, 0x0400001d, - 0x59302009, 0x58140009, 0x800001c0, 0x0400000b, - 0x801021c0, 0x04000003, 0x80100580, 0x04000010, - 0x82142c00, 0x00000024, 0x41540000, 0x80140480, - 0x0402100e, 0x0401f7e2, 0x5814001e, 0x801021c0, - 0x04000005, 0x58102002, 0x82102500, 0x00ffffff, - 0x0401f7f2, 0x5810201e, 0x0401f7f0, 0x40163800, - 0x81300540, 0x0401f002, 0x80000580, 0x1c01f000, - 0x58141807, 0x8c0c1d10, 0x040207ea, 0x0401f7e1, - 0x83380580, 0x00000013, 0x0402000e, 0x59300403, - 0x4803c857, 0x82000c80, 0x00000085, 0x02001800, - 0x00100615, 0x82000c80, 0x00000093, 0x02021800, - 0x00100615, 0x82000480, 0x00000085, 0x0c01f019, - 0x83380580, 0x00000027, 0x04000005, 0x83380580, - 0x00000014, 0x02020000, 0x001076fb, 0x493bc857, - 0x0201f800, 0x001068f6, 0x59325808, 0x812e59c0, - 0x02000000, 0x00107698, 0x4a025a06, 0x00000031, - 0x4a025811, 0x00000004, 0x4a025812, 0x000000ff, - 0x0201f800, 0x00020381, 0x0201f000, 0x00107698, - 0x00109fa6, 0x00109fad, 0x00109fad, 0x00109fa6, - 0x00109fa6, 0x00109fa6, 0x00109fa6, 0x00109fa6, - 0x00109fa6, 0x00109fa6, 0x00109fa6, 0x00109fa6, - 0x00109fa6, 0x00109fa8, 0x0201f800, 0x00100615, - 0x59325808, 0x4a025a06, 0x00000000, 0x0201f800, - 0x00020381, 0x0201f000, 0x000208b4, 0x4933c857, - 0x42000000, 0x0010b672, 0x0201f800, 0x0010a86e, - 0x0201f800, 0x0010a3fa, 0x497a6205, 0x42028000, - 0x0000000b, 0x0401f807, 0x4a026406, 0x00000006, - 0x4a026203, 0x00000007, 0x497a6206, 0x1c01f000, - 0x4933c857, 0x4943c857, 0x59300406, 0x82000580, - 0x00000007, 0x04020002, 0x1c01f000, 0x0201f800, - 0x0010698c, 0x4df00000, 0x0201f800, 0x00108a99, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f001, 0x00109ff4, 0x00109ff8, 0x00109fdf, - 0x0010a006, 0x0010a019, 0x00109fdf, 0x00109fdf, - 0x00109fdf, 0x00109fdf, 0x00109fdf, 0x00109fdf, - 0x00109fdf, 0x00109fdf, 0x00109fdf, 0x4d400000, - 0x5930001f, 0x80000540, 0x04000005, 0x41400800, - 0x0201f800, 0x00100dc4, 0x40068000, 0x4d2c0000, - 0x59325808, 0x0201f800, 0x00108df4, 0x04020a16, - 0x4c5c0000, 0x5930b809, 0x0201f800, 0x00107698, - 0x485e6009, 0x5c00b800, 0x5c025800, 0x5c028000, - 0x5c03e000, 0x02000000, 0x00106982, 0x1c01f000, - 0x598c000d, 0x81300580, 0x04020004, 0x0201f800, - 0x00106be2, 0x04020016, 0x0201f800, 0x00106619, - 0x040007df, 0x0201f800, 0x001068a3, 0x04000010, - 0x0201f800, 0x00100615, 0x0201f800, 0x00108a8a, - 0x04020004, 0x0201f800, 0x00106bb2, 0x04020008, - 0x0201f800, 0x001064f6, 0x040007d1, 0x0201f800, - 0x001068a3, 0x02020800, 0x00100615, 0x59300203, - 0x82000c80, 0x0000000e, 0x02021800, 0x00100615, - 0x0c01f7b9, 0x0201f800, 0x00100ee4, 0x0401f7c4, - 0x4933c857, 0x4d440000, 0x4d340000, 0x59cc0007, - 0x0201f800, 0x001059b9, 0x02000800, 0x00020267, - 0x0402001a, 0x59300009, 0x4c000000, 0x49366009, - 0x42003000, 0x0000000b, 0x0201f800, 0x0010a766, - 0x42000000, 0x0010b660, 0x0201f800, 0x0010a86e, - 0x4d3c0000, 0x4d400000, 0x42028000, 0x00000029, - 0x417a7800, 0x0201f800, 0x00101de2, 0x5c028000, - 0x5c027800, 0x5c000000, 0x48026009, 0x59cc0007, - 0x48026802, 0x80000580, 0x5c026800, 0x5c028800, - 0x1c01f000, 0x4933c857, 0x4c040000, 0x59a80016, - 0x82000580, 0x00000074, 0x04020040, 0x59cc0a08, - 0x82040480, 0x00000100, 0x04001033, 0x59cc0c08, - 0x82040500, 0x00008000, 0x04000035, 0x59a80032, - 0x80000540, 0x04020009, 0x59301009, 0x58080212, - 0x82000500, 0x0000ff00, 0x04000004, 0x82040500, - 0x00000800, 0x0400002a, 0x59cc0c09, 0x80040840, - 0x04001024, 0x59a80826, 0x8c040d06, 0x04000004, - 0x59cc0c0f, 0x8c040d1e, 0x04020012, 0x59cc0a17, - 0x800409c0, 0x04020012, 0x59cc0a18, 0x82040480, - 0x00000100, 0x04001014, 0x59cc0c18, 0x800409c0, - 0x0402000e, 0x59cc0c19, 0x80040840, 0x04001011, - 0x59cc0c1a, 0x80040840, 0x04001011, 0x0401f018, - 0x4a02621a, 0x00000100, 0x0401f012, 0x4a02621a, - 0x00000300, 0x0401f00f, 0x4a02621a, 0x00000500, - 0x0401f00c, 0x4a02621a, 0x00000700, 0x0401f009, - 0x4a02621a, 0x00000900, 0x0401f006, 0x4a02621a, - 0x00000f00, 0x0401f003, 0x4a02621a, 0x00002d00, - 0x82000540, 0x00000001, 0x0401f002, 0x80000580, - 0x5c000800, 0x1c01f000, 0x59cc0407, 0x4803c857, - 0x82000580, 0x00000800, 0x04000003, 0x4a02621a, - 0x00000000, 0x1c01f000, 0x4933c857, 0x4c580000, - 0x59cc000c, 0x59340802, 0x82040d00, 0x00ffffff, - 0x80040580, 0x04020012, 0x83cc1400, 0x00000008, - 0x4200b000, 0x00000002, 0x83341c00, 0x00000006, - 0x0201f800, 0x001082ff, 0x04020009, 0x83cc1400, - 0x0000000a, 0x4200b000, 0x00000002, 0x83341c00, - 0x00000008, 0x0201f800, 0x001082ff, 0x5c00b000, - 0x1c01f000, 0x4933c857, 0x4c580000, 0x83cc1400, - 0x0000000b, 0x4200b000, 0x00000002, 0x83341c00, - 0x00000006, 0x0201f800, 0x001082ff, 0x0402000c, - 0x83cc1400, 0x0000000d, 0x4200b000, 0x00000002, - 0x83341c00, 0x00000008, 0x0201f800, 0x001082ff, - 0x04000014, 0x4933c856, 0x4933c856, 0x4933c857, - 0x59340009, 0x4803c857, 0x5934000e, 0x4803c857, - 0x59340008, 0x4803c857, 0x5934000d, 0x4803c857, - 0x59340007, 0x4803c857, 0x5934000c, 0x4803c857, - 0x59340006, 0x4803c857, 0x5934000b, 0x4803c857, - 0x5c00b000, 0x1c01f000, 0x4933c857, 0x4947c857, - 0x4943c857, 0x4c600000, 0x0201f800, 0x0010698c, - 0x4df00000, 0x4d2c0000, 0x4d300000, 0x4d340000, - 0x0401f8d8, 0x4130c000, 0x42026000, 0x0010cfc0, - 0x59a8000e, 0x8060c1c0, 0x04000005, 0x82601580, - 0x0010bbe8, 0x04000002, 0x80000040, 0x81640480, - 0x040210c4, 0x40600000, 0x81300580, 0x040000bc, - 0x0401f9bc, 0x040200ba, 0x59326809, 0x59300406, - 0x82000c80, 0x00000012, 0x02021800, 0x00100615, - 0x0c01f001, 0x0010a1af, 0x0010a118, 0x0010a133, - 0x0010a13e, 0x0010a111, 0x0010a12c, 0x0010a169, - 0x0010a1af, 0x0010a10f, 0x0010a17c, 0x0010a190, - 0x0010a10f, 0x0010a10f, 0x0010a10f, 0x0010a10f, - 0x0010a1af, 0x0010a1a6, 0x0010a19e, 0x0201f800, - 0x00100615, 0x8d3e7d18, 0x04000003, 0x8d3e7d16, - 0x04000004, 0x59300420, 0x8c000500, 0x04020098, - 0x59300403, 0x82000580, 0x00000043, 0x04000094, - 0x0201f800, 0x00108ef1, 0x04000007, 0x0201f800, - 0x00108f05, 0x0402008c, 0x0201f800, 0x00107da6, - 0x0401f089, 0x0201f800, 0x00101e1b, 0x0201f800, - 0x00108f05, 0x02000800, 0x00107da6, 0x0401f082, - 0x8d3e7d18, 0x04000003, 0x8d3e7d16, 0x04000004, - 0x59300420, 0x8c000500, 0x0402007d, 0x59325808, - 0x0201f800, 0x00108df4, 0x04000077, 0x49425a06, - 0x497a5c09, 0x0201f800, 0x00020381, 0x0201f800, - 0x00108ee7, 0x0401f070, 0x8d3e7d00, 0x04000007, - 0x59300017, 0x81480580, 0x0402006d, 0x59300018, - 0x814c0580, 0x0402006a, 0x59300203, 0x82000580, - 0x00000004, 0x02000800, 0x00100ee4, 0x59325808, - 0x0201f800, 0x00108df4, 0x0400005f, 0x4a025a04, - 0x00000103, 0x59300004, 0x8400055c, 0x48026004, - 0x592c0408, 0x8c000512, 0x04000007, 0x4d2c0000, - 0x592c0009, 0x40025800, 0x0201f800, 0x00100843, - 0x5c025800, 0x49425a06, 0x497a5c09, 0x0401fb4f, - 0x0201f800, 0x00109365, 0x0201f800, 0x00108f7d, - 0x0201f800, 0x00020381, 0x0201f800, 0x00108ee7, - 0x0401f045, 0x8d3e7d18, 0x04000045, 0x59300203, - 0x82000580, 0x00000004, 0x02000800, 0x00100ee4, - 0x59325808, 0x0201f800, 0x00108df4, 0x0400003a, - 0x49425a06, 0x497a5c09, 0x0401fb38, 0x0201f800, - 0x00109365, 0x0201f800, 0x00020381, 0x0401f032, - 0x0201f800, 0x0010600e, 0x04000031, 0x59300203, - 0x82000580, 0x00000004, 0x0400002d, 0x59300203, - 0x82000580, 0x00000003, 0x04020029, 0x0201f800, - 0x001068c1, 0x59325808, 0x0201f800, 0x00108df4, - 0x04000021, 0x0201f800, 0x00020381, 0x0401f01e, - 0x59300203, 0x82000580, 0x00000004, 0x02000800, - 0x00100ee4, 0x59325808, 0x0201f800, 0x00108df4, - 0x04000015, 0x49425a06, 0x497a5c09, 0x0201f800, - 0x00020381, 0x0401f010, 0x833c0500, 0x00001800, - 0x0400000f, 0x8d3e7d16, 0x0402000d, 0x59325817, - 0x0201f800, 0x00100843, 0x59325808, 0x0201f800, - 0x00108df4, 0x04000004, 0x49425a06, 0x0201f800, - 0x00020381, 0x0201f800, 0x00107698, 0x83326400, - 0x00000024, 0x41580000, 0x81300480, 0x04001735, - 0x5c026800, 0x5c026000, 0x5c025800, 0x5c03e000, - 0x02000800, 0x00106982, 0x5c00c000, 0x1c01f000, - 0x4933c857, 0x813261c0, 0x0400002d, 0x83300d80, - 0x0010bbe8, 0x0400002a, 0x8d3e7d06, 0x04020028, - 0x59300c06, 0x82040580, 0x00000001, 0x0400000a, - 0x82040580, 0x00000002, 0x04020021, 0x5930021d, - 0x82000580, 0x00000001, 0x0402001d, 0x59300c16, - 0x0401f002, 0x59300c03, 0x82040580, 0x00000039, - 0x04000004, 0x82040580, 0x00000035, 0x04020014, - 0x4d300000, 0x4d1c0000, 0x5932601e, 0x4933c857, - 0x0201f800, 0x001091e3, 0x02000800, 0x00100615, - 0x591c001c, 0x497a381c, 0x591c0c14, 0x84040d02, - 0x48063c14, 0x5c023800, 0x5c026000, 0x81300580, - 0x02020800, 0x00100615, 0x497a601e, 0x1c01f000, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4d3c0000, - 0x42027800, 0x00000001, 0x0201f800, 0x001043bd, - 0x5c027800, 0x4c580000, 0x4200b000, 0x00000002, - 0x83a81c00, 0x00000002, 0x83cc1400, 0x0000000b, - 0x0201f800, 0x001082ff, 0x5c00b000, 0x80000540, - 0x1c01f000, 0x492fc857, 0x4943c857, 0x59a8000c, - 0x812c0480, 0x04001011, 0x59a8000d, 0x812c0480, - 0x0402100e, 0x592c0000, 0x80005d40, 0x04000008, - 0x497a5800, 0x49425a06, 0x4c2c0000, 0x0201f800, - 0x00020381, 0x5c025800, 0x0401f7f7, 0x49425a06, - 0x0201f000, 0x00020381, 0x1c01f000, 0x493fc857, - 0x4933c857, 0x480bc857, 0x0201f800, 0x0010393e, - 0x0400002e, 0x41502800, 0x813e79c0, 0x04020006, - 0x59a80066, 0x80000000, 0x59a8086a, 0x80040580, - 0x04000026, 0x41300000, 0x80140580, 0x0400001a, - 0x58140203, 0x82000580, 0x00000000, 0x04000016, - 0x58140202, 0x80080580, 0x04020013, 0x58141c06, - 0x820c0580, 0x00000005, 0x0400000f, 0x820c0580, - 0x00000009, 0x04000017, 0x59300009, 0x58142009, - 0x801021c0, 0x04020006, 0x5814201e, 0x59301809, - 0x580c0002, 0x82000500, 0x00ffffff, 0x80100580, - 0x04000007, 0x82142c00, 0x00000024, 0x41540000, - 0x80140480, 0x04021005, 0x0401f7df, 0x40163800, - 0x81300540, 0x0401f002, 0x80000580, 0x1c01f000, - 0x58141807, 0x8c0c1d10, 0x040207f3, 0x0401f7e7, - 0x42002000, 0x0000ffff, 0x59301009, 0x800811c0, - 0x04000002, 0x58082403, 0x41301000, 0x0401f007, - 0x41781000, 0x41442000, 0x0401f004, 0x41781000, - 0x42002000, 0x0000ffff, 0x5c000000, 0x4c000000, - 0x4803c857, 0x480bc857, 0x4813c857, 0x492fc857, - 0x4943c857, 0x4d2c0000, 0x4c080000, 0x4c100000, - 0x4c140000, 0x4c180000, 0x0201f800, 0x0010082a, - 0x02000800, 0x00100615, 0x5c003000, 0x5c002800, - 0x5c002000, 0x5c001000, 0x4a025a04, 0x0000010d, - 0x800811c0, 0x04000017, 0x83400580, 0x00000029, - 0x04020010, 0x82180580, 0x00000002, 0x0400000a, - 0x82180580, 0x00000003, 0x04000007, 0x82180580, - 0x00000008, 0x04000004, 0x82180580, 0x00000009, - 0x04020004, 0x4a025809, 0xffffffff, 0x0401f002, - 0x480a5809, 0x58080202, 0x48025c13, 0x0401f005, - 0x4a025809, 0xffffffff, 0x4a025c13, 0x0000ffff, - 0x49425a08, 0x48125a06, 0x82100580, 0x0000ffff, - 0x04000012, 0x4c140000, 0x4c180000, 0x4d440000, - 0x4d340000, 0x40128800, 0x0201f800, 0x00020267, - 0x02020800, 0x00100615, 0x59340002, 0x82000500, - 0x00ffffff, 0x48025812, 0x5c026800, 0x5c028800, - 0x5c003000, 0x5c002800, 0x497a5800, 0x497a5c04, - 0x83400580, 0x00000046, 0x04020002, 0x48165a07, - 0x481a5c08, 0x0401fbe0, 0x5c025800, 0x1c01f000, - 0x59300809, 0x800409c0, 0x04000004, 0x58040403, - 0x81440580, 0x1c01f000, 0x82000540, 0x00000001, - 0x0401f7fd, 0x4933c857, 0x4c040000, 0x59300403, - 0x82000d80, 0x0000001e, 0x04020016, 0x800000d0, - 0x59300a16, 0x82040d00, 0x000000ff, 0x80040540, - 0x4803c857, 0x48026416, 0x4a026403, 0x00000085, - 0x4a026203, 0x00000009, 0x4a026406, 0x00000005, - 0x4a02621d, 0x00000004, 0x59a80038, 0x48026206, - 0x42000800, 0x8000004b, 0x0201f800, 0x00020855, - 0x5c000800, 0x1c01f000, 0x4933c857, 0x40000000, - 0x40000000, 0x1c01f000, 0x59300414, 0x4933c857, - 0x4803c857, 0x8c000518, 0x04000009, 0x8c000512, - 0x02020000, 0x00108fdb, 0x0401f918, 0x0201f800, - 0x00020831, 0x0201f800, 0x000208b4, 0x1c01f000, - 0x591c0406, 0x4803c857, 0x82000c80, 0x00000009, - 0x0402100b, 0x0c01f001, 0x0010a2f7, 0x0010a2f7, - 0x0010a2f7, 0x0010a2f9, 0x0010a2f7, 0x0010a2f9, - 0x0010a2f9, 0x0010a2f7, 0x0010a2f9, 0x80000580, - 0x1c01f000, 0x82000540, 0x00000001, 0x1c01f000, - 0x591c0406, 0x82000500, 0x0000001f, 0x82000580, - 0x00000006, 0x0400000e, 0x4803c857, 0x4a026403, - 0x0000003b, 0x4a02641a, 0x00000009, 0x4a02621a, - 0x00002a00, 0x4a026203, 0x00000001, 0x42000800, - 0x80000040, 0x0201f000, 0x00020855, 0x4803c856, - 0x4c040000, 0x4c140000, 0x4d300000, 0x411e6000, - 0x0401f8e6, 0x497a6205, 0x59300414, 0x4803c857, - 0x82000500, 0xffffadff, 0x48026414, 0x497a6405, - 0x5c026000, 0x0201f800, 0x0010082a, 0x02000800, - 0x00100615, 0x5c002800, 0x5c000800, 0x4a025a04, - 0x0000010d, 0x497a5800, 0x497a5c04, 0x4a025a08, - 0x00000045, 0x491e5809, 0x59300402, 0x48025c07, - 0x59300419, 0x48025c0b, 0x591c0414, 0x84000556, - 0x48023c14, 0x591c1809, 0x580c0403, 0x48025a06, - 0x4816580a, 0x48065a0b, 0x0401fb57, 0x4d400000, - 0x42028000, 0x00000045, 0x591c0202, 0x4c000000, - 0x4d300000, 0x411e6000, 0x0401fc82, 0x5c026000, - 0x5c000000, 0x48023a02, 0x5c028000, 0x4a023c06, - 0x00000006, 0x4a023a03, 0x00000007, 0x497a3a06, - 0x497a3a05, 0x1c01f000, 0x4933c857, 0x83380580, - 0x00000013, 0x0402000b, 0x59300403, 0x4803c857, - 0x82000d80, 0x00000085, 0x0400002b, 0x82000d80, - 0x0000008b, 0x04000028, 0x0201f800, 0x00100615, - 0x83380580, 0x00000027, 0x0402000c, 0x0201f800, - 0x001068f6, 0x4d2c0000, 0x4d400000, 0x59325808, - 0x42028000, 0x00000004, 0x0401fe9f, 0x5c028000, - 0x5c025800, 0x1c01f000, 0x83380580, 0x00000014, - 0x040007f3, 0x83380580, 0x00000089, 0x04000005, - 0x83380580, 0x0000008a, 0x02020000, 0x001076fb, - 0x0201f800, 0x00106cb4, 0x02020000, 0x001076fb, - 0x59300a03, 0x82040580, 0x0000000a, 0x04000009, - 0x82040580, 0x0000000c, 0x04000006, 0x0201f800, - 0x00100615, 0x4a026203, 0x0000000a, 0x1c01f000, - 0x83380480, 0x00000093, 0x0402100c, 0x83380480, - 0x00000085, 0x04001009, 0x83380580, 0x00000089, - 0x0400000a, 0x83380580, 0x0000008a, 0x04000022, - 0x0201f800, 0x00100615, 0x493bc857, 0x4933c857, - 0x0201f000, 0x001076fb, 0x4933c857, 0x4c340000, - 0x41306800, 0x0201f800, 0x00020892, 0x04000011, - 0x4a026203, 0x00000001, 0x4a026403, 0x0000001e, - 0x59cc0c07, 0x48066419, 0x59cc0a07, 0x48066219, - 0x58340809, 0x48066009, 0x4a026406, 0x00000004, - 0x42000800, 0x80000040, 0x0201f800, 0x00020855, - 0x40366000, 0x0201f800, 0x000208b4, 0x5c006800, - 0x1c01f000, 0x4933c857, 0x0201f000, 0x000208b4, - 0x59300809, 0x58040200, 0x8c00051a, 0x02020800, - 0x001006ba, 0x1c01f000, 0x0201f800, 0x0010472e, - 0x0400001e, 0x4a026203, 0x00000002, 0x59300414, - 0x84000558, 0x48026414, 0x8c000512, 0x04000004, - 0x59a80039, 0x48026205, 0x0401f007, 0x59a80839, - 0x59a80037, 0x80040400, 0x82000400, 0x0000001e, - 0x48026205, 0x59300009, 0x82000c00, 0x00000011, - 0x50040000, 0x80000540, 0x04000004, 0x82000c00, - 0x00000000, 0x0401f7fb, 0x45300800, 0x497a6000, - 0x82000540, 0x00000001, 0x1c01f000, 0x82100500, - 0xfffffeef, 0x0402001c, 0x4d2c0000, 0x4937c857, - 0x59340811, 0x83341400, 0x00000011, 0x800409c0, - 0x0400000e, 0x40040000, 0x81300580, 0x04000005, - 0x58040800, 0x82041400, 0x00000000, 0x0401f7f8, - 0x59300800, 0x497a6000, 0x44041000, 0x0201f800, - 0x00020831, 0x0401f002, 0x4933c857, 0x5c025800, - 0x492e6008, 0x0201f800, 0x00020831, 0x0201f000, - 0x000208b4, 0x492fc857, 0x4a025a06, 0x00000006, - 0x0201f000, 0x00020381, 0x4c340000, 0x59300009, - 0x800001c0, 0x04000010, 0x82006c00, 0x00000011, - 0x50340000, 0x80000540, 0x04000009, 0x81300580, - 0x04000005, 0x50340000, 0x82006c00, 0x00000000, - 0x0401f7f8, 0x59300000, 0x44006800, 0x5c006800, - 0x1c01f000, 0x59300c06, 0x82040580, 0x00000005, - 0x040007fb, 0x82040580, 0x00000011, 0x040007f8, - 0x82040580, 0x00000006, 0x040007f5, 0x82040580, - 0x00000001, 0x040007f2, 0x0201f800, 0x00100615, - 0x4933c857, 0x4c080000, 0x4c0c0000, 0x4c580000, - 0x59a8101d, 0x59cc1807, 0x820c1d00, 0x00ffffff, - 0x800c0110, 0x80083580, 0x04020014, 0x83cc1400, - 0x00000008, 0x4200b000, 0x00000002, 0x59300009, - 0x82001c00, 0x00000006, 0x0201f800, 0x001082ff, - 0x0402000a, 0x83cc1400, 0x0000000a, 0x4200b000, - 0x00000002, 0x59300009, 0x82001c00, 0x00000008, - 0x0201f800, 0x001082ff, 0x5c00b000, 0x5c001800, - 0x5c001000, 0x1c01f000, 0x4933c856, 0x0201f800, - 0x0010404b, 0x0201f000, 0x00101bf0, 0x493bc857, - 0x4d2c0000, 0x0201f800, 0x0010082a, 0x02000800, - 0x00100615, 0x832cac00, 0x00000005, 0x4c580000, - 0x4c540000, 0x4200b000, 0x00000006, 0x4578a800, - 0x8054a800, 0x8058b040, 0x040207fd, 0x83380580, - 0x00000046, 0x04020004, 0x4a025a04, 0x00000144, - 0x0401f008, 0x4a025a04, 0x00000146, 0x83380580, - 0x00000041, 0x04000003, 0x4a025a06, 0x00000001, - 0x59cc0007, 0x82000500, 0xff000000, 0x80000110, - 0x59cc1008, 0x82081500, 0xff000000, 0x80081540, - 0x480a580a, 0x83380580, 0x00000046, 0x04020006, - 0x59cc0007, 0x82000500, 0x00ffffff, 0x4802580b, - 0x0401f005, 0x59cc0008, 0x82000500, 0x00ffffff, - 0x4802580b, 0x83380580, 0x00000046, 0x04020004, - 0x83cc1400, 0x00000009, 0x0401f003, 0x83cc1400, - 0x0000000d, 0x50080000, 0x9c0001c0, 0x4802580c, - 0x80081000, 0x50080000, 0x9c0001c0, 0x4802580d, - 0x83380580, 0x00000046, 0x04020008, 0x59cc000b, - 0x9c0001c0, 0x4802580e, 0x59cc000c, 0x9c0001c0, - 0x4802580f, 0x0401f007, 0x59cc000f, 0x9c0001c0, - 0x4802580e, 0x59cc0010, 0x9c0001c0, 0x4802580f, - 0x83380580, 0x00000046, 0x04020004, 0x83cc1400, - 0x00000011, 0x0401f003, 0x83cc1400, 0x00000015, - 0x412c3000, 0x82183400, 0x00000010, 0x4200b000, - 0x00000004, 0x50080000, 0x9c0001c0, 0x44003000, - 0x80081000, 0x80183000, 0x8058b040, 0x040207fa, - 0x5c00a800, 0x5c00b000, 0x0201f800, 0x00020381, - 0x5c025800, 0x1c01f000, 0x4933c857, 0x492fc857, - 0x59300809, 0x58040200, 0x8c00051e, 0x04000004, - 0x592c0208, 0x84000558, 0x48025a08, 0x1c01f000, - 0x59e0180f, 0x599c0413, 0x800c1000, 0x80080580, - 0x04020002, 0x41781000, 0x59e00010, 0x59e00810, - 0x80040d80, 0x040207fd, 0x80080580, 0x0400000b, - 0x4c080000, 0x599c0814, 0x599c1015, 0x800c00cc, - 0x80040c00, 0x82081440, 0x00000000, 0x5c001800, - 0x82000540, 0x00000001, 0x4803c857, 0x1c01f000, - 0x59300203, 0x4933c857, 0x4937c857, 0x493bc857, - 0x4803c857, 0x82003480, 0x0000000e, 0x02021800, - 0x00100615, 0x0c01f001, 0x0010a4e8, 0x0010a63a, - 0x0010a4e8, 0x0010a4e8, 0x0010a4e8, 0x0010a4e8, - 0x0010a4e8, 0x0010a59f, 0x0010a4ea, 0x0010a4e8, - 0x0010a4e8, 0x0010a4e8, 0x0010a4e8, 0x0010a4e8, - 0x0201f800, 0x00100615, 0x83380580, 0x0000004c, - 0x02020800, 0x00100615, 0x0201f800, 0x0010473b, - 0x04020020, 0x59a80826, 0x82040500, 0x00000009, - 0x82000580, 0x00000008, 0x0400001a, 0x8c040d12, - 0x0400003d, 0x59cc0806, 0x82040d00, 0xff000000, - 0x82040580, 0x03000000, 0x0400001f, 0x82040580, - 0x50000000, 0x04000005, 0x82040580, 0x52000000, - 0x02020000, 0x000208b4, 0x813669c0, 0x04000006, - 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2, - 0x5c027800, 0x4a026403, 0x00000001, 0x0401f014, - 0x59cc0806, 0x82040d00, 0xff000000, 0x82040580, - 0x03000000, 0x04000008, 0x82040580, 0x50000000, - 0x04000005, 0x82040580, 0x52000000, 0x02020000, - 0x000208b4, 0x4a026403, 0x00000009, 0x4a02641a, - 0x00000009, 0x4a02621a, 0x00000000, 0x813669c0, - 0x0402000b, 0x59cc0001, 0x0201f800, 0x001059b9, - 0x02020000, 0x000208b4, 0x0201f800, 0x001043fc, - 0x02020000, 0x000208b4, 0x49366009, 0x4a026406, - 0x00000004, 0x4a026203, 0x00000001, 0x0201f000, - 0x00106470, 0x0201f800, 0x0010393e, 0x04000023, - 0x59cc0806, 0x4807c857, 0x82040d00, 0xff000000, - 0x82040580, 0x03000000, 0x04000033, 0x82040580, - 0x20000000, 0x04000041, 0x82040580, 0x21000000, - 0x04000052, 0x82040580, 0x24000000, 0x0400004f, - 0x82040580, 0x50000000, 0x0400004c, 0x82040580, - 0x52000000, 0x04000049, 0x82040580, 0x05000000, - 0x0402000d, 0x59cc0806, 0x82040d00, 0xff000000, - 0x9c0431c0, 0x42028000, 0x00000046, 0x42002800, - 0x00000001, 0x0401fcf7, 0x0401f940, 0x02000800, - 0x00100615, 0x42002000, 0x00000051, 0x0201f800, - 0x001077d1, 0x59cc0000, 0x82000500, 0x00ffffff, - 0x82000580, 0x00ffffff, 0x04000005, 0x4a026203, - 0x00000007, 0x493a6403, 0x1c01f000, 0x59325817, - 0x812e59c0, 0x02020800, 0x00100843, 0x0201f000, - 0x000208b4, 0x813669c0, 0x040007df, 0x59340400, - 0x82000500, 0x000000ff, 0x82000580, 0x00000003, - 0x040207d9, 0x0401fc73, 0x040207d7, 0x4a026403, - 0x00000009, 0x4a02641a, 0x0000000e, 0x4a02621a, - 0x00001900, 0x0401f7a2, 0x813669c0, 0x0400000c, - 0x59340c00, 0x82040500, 0x000000ff, 0x82000580, - 0x00000009, 0x04000794, 0x82040500, 0x0000ff00, - 0x82000580, 0x00000700, 0x040207c3, 0x4a026403, - 0x00000009, 0x4a02641a, 0x00000009, 0x4a02621a, - 0x00001e00, 0x0401f78e, 0x813669c0, 0x040007f8, - 0x59340c00, 0x82040500, 0x0000ff00, 0x82000580, - 0x00000700, 0x040007f2, 0x0401f7b3, 0x4d2c0000, - 0x4c580000, 0x4c500000, 0x4c540000, 0x41385000, - 0x83380580, 0x00000054, 0x02020800, 0x00100615, - 0x59325808, 0x592c0c0b, 0x82040d00, 0x0000e000, - 0x82040580, 0x00002000, 0x04020076, 0x59300817, - 0x800409c0, 0x04000014, 0x58041404, 0x41cca800, - 0x8204a400, 0x00000005, 0x82080480, 0x00000010, - 0x04021004, 0x4008b000, 0x0401fb84, 0x0401f00a, - 0x40001000, 0x4200b000, 0x0000000f, 0x0401fb7f, - 0x58040801, 0x800409c0, 0x040207f2, 0x0201f800, - 0x00100615, 0x813669c0, 0x0400005e, 0x59344c00, - 0x592c0c09, 0x4807c857, 0x4827c857, 0x82040d00, - 0x000000ff, 0x82040580, 0x00000003, 0x0400002a, - 0x82040580, 0x00000005, 0x04000032, 0x82040580, - 0x00000020, 0x04000036, 0x82040580, 0x00000052, - 0x04000042, 0x82040580, 0x00000050, 0x04000042, - 0x82040580, 0x00000021, 0x04000004, 0x82040580, - 0x00000024, 0x04020043, 0x82240500, 0x0000ff00, - 0x82000580, 0x00000007, 0x04000008, 0x42000800, - 0x00000009, 0x0201f800, 0x001043c7, 0x42005000, - 0x0000000c, 0x0401f037, 0x4a025a06, 0x00000031, - 0x4a02580d, 0x00000009, 0x59340400, 0x4802580e, - 0x0201f800, 0x00020381, 0x0201f800, 0x00107698, - 0x0401f03d, 0x0201f800, 0x001040e4, 0x0201f800, - 0x00104480, 0x42000800, 0x00000003, 0x0201f800, - 0x001043c7, 0x42005000, 0x00000008, 0x0401f021, - 0x59cc0007, 0x0201f800, 0x00105c25, 0x0402001d, - 0x0201f800, 0x001040e4, 0x0401f01a, 0x82240500, - 0x0000ff00, 0x82000580, 0x00000007, 0x040007df, - 0x82240500, 0x000000ff, 0x82000580, 0x00000009, - 0x040007da, 0x0201f800, 0x001044e1, 0x42005000, - 0x0000000a, 0x0401f00b, 0x42005000, 0x0000000e, - 0x0401f003, 0x42005000, 0x00000010, 0x82240500, - 0x0000ff00, 0x82000580, 0x00000007, 0x040007cb, - 0x482a6403, 0x4a026203, 0x00000001, 0x592c000d, - 0x48026011, 0x497a6013, 0x59a80038, 0x48026206, - 0x417a7800, 0x0201f800, 0x00106470, 0x59325817, - 0x812e59c0, 0x04000004, 0x0201f800, 0x00100843, - 0x497a6017, 0x5c00a800, 0x5c00a000, 0x5c00b000, - 0x5c025800, 0x1c01f000, 0x4d2c0000, 0x59325808, - 0x83380580, 0x00000013, 0x0402002a, 0x492fc857, - 0x59300c03, 0x82040580, 0x00000054, 0x0400001e, - 0x82040580, 0x00000010, 0x04000018, 0x82040580, - 0x0000000e, 0x04000015, 0x82040580, 0x00000008, - 0x0400000d, 0x82040580, 0x0000000c, 0x0400000a, - 0x82040580, 0x0000000a, 0x02020800, 0x00100615, - 0x42000800, 0x00000006, 0x0201f800, 0x001043c7, - 0x0401f009, 0x42000800, 0x00000004, 0x0201f800, - 0x001043c7, 0x0401f004, 0x59340200, 0x8400051a, - 0x48026a00, 0x4a025a06, 0x00000000, 0x0201f800, - 0x00020381, 0x0201f800, 0x000208b4, 0x0401f024, - 0x83380580, 0x00000027, 0x0400000f, 0x83380580, - 0x00000014, 0x02020800, 0x00100615, 0x492fc857, - 0x0201f800, 0x001068f6, 0x42028000, 0x00000031, - 0x42000800, 0x00000004, 0x42001000, 0x000000ff, - 0x0401f00a, 0x492fc857, 0x0201f800, 0x001068f6, - 0x42028000, 0x00000031, 0x42000800, 0x00000004, - 0x42001000, 0x00000010, 0x49425a06, 0x4806580d, - 0x480a580e, 0x0201f800, 0x00020381, 0x0201f800, - 0x00104a83, 0x0201f800, 0x00107698, 0x5c025800, - 0x1c01f000, 0x492fc857, 0x42007000, 0x0010b5f6, - 0x58380807, 0x800409c0, 0x04020005, 0x492c7008, - 0x492c7007, 0x0201f000, 0x001008be, 0x492c0800, - 0x492c7007, 0x1c01f000, 0x4d2c0000, 0x4c580000, - 0x4c500000, 0x4c540000, 0x4933c857, 0x4937c857, - 0x59cc0806, 0x4807c857, 0x82040d00, 0xff000000, - 0x82040580, 0x03000000, 0x0400000d, 0x82040580, - 0x05000000, 0x0400000a, 0x82040580, 0x21000000, - 0x04000030, 0x82040580, 0x24000000, 0x0400002d, - 0x82040580, 0x20000000, 0x0402002f, 0x0201f800, - 0x0010082a, 0x0400002c, 0x492fc857, 0x492e6017, - 0x59a8b016, 0x8258b400, 0x0000001b, 0x8258b500, - 0xfffffffc, 0x8058b104, 0x485a5c04, 0x412c7800, - 0x41cca000, 0x82580480, 0x00000010, 0x04021005, - 0x832cac00, 0x00000005, 0x0401fa78, 0x0401f015, - 0x40580800, 0x4200b000, 0x0000000f, 0x832cac00, - 0x00000005, 0x0401fa71, 0x8204b480, 0x0000000f, - 0x0201f800, 0x0010082a, 0x04000004, 0x492c7801, - 0x412c7800, 0x0401f7ec, 0x59325817, 0x0201f800, - 0x00100843, 0x497a6017, 0x80000580, 0x0401f006, - 0x59340200, 0x84000554, 0x48026a00, 0x82000540, - 0x00000001, 0x5c00a800, 0x5c00a000, 0x5c00b000, - 0x5c025800, 0x1c01f000, 0x4933c857, 0x492fc857, - 0x4d2c0000, 0x4c5c0000, 0x5930bc06, 0x59300a03, - 0x82040580, 0x00000007, 0x0400003c, 0x82040580, - 0x00000001, 0x02020800, 0x00100615, 0x0201f800, - 0x0010698c, 0x4df00000, 0x598c000d, 0x81300580, - 0x04020019, 0x59300004, 0x8c000520, 0x04000004, - 0x84000520, 0x48026004, 0x0401f019, 0x825c0580, - 0x00000011, 0x0402000d, 0x42001000, 0x0010b5f4, - 0x50081000, 0x58080002, 0x82000580, 0x00000100, - 0x04000006, 0x5808000c, 0x81300580, 0x02020800, - 0x00100615, 0x0401f00a, 0x0201f800, 0x00106be2, - 0x04020027, 0x59300004, 0x8c000520, 0x04000004, - 0x84000520, 0x48026004, 0x0401f003, 0x0201f800, - 0x00106619, 0x5c03e000, 0x02000800, 0x00106982, - 0x0201f800, 0x00108df4, 0x02000800, 0x00100615, - 0x59325808, 0x4a025a06, 0x00000005, 0x0201f800, - 0x00020381, 0x825c0580, 0x00000005, 0x0400001b, - 0x0201f800, 0x00104a83, 0x825c0580, 0x00000005, - 0x04000016, 0x59325817, 0x812e59c0, 0x02020800, - 0x00100843, 0x0201f800, 0x00107698, 0x80000580, - 0x5c00b800, 0x5c025800, 0x1c01f000, 0x5c03e000, - 0x02000800, 0x00106982, 0x59300c06, 0x82040580, - 0x00000011, 0x040007ae, 0x82040580, 0x00000005, - 0x040007ab, 0x0401f7f3, 0x0201f800, 0x000208b4, - 0x0401f7ef, 0x4c040000, 0x59340200, 0x4803c857, - 0x8c00051c, 0x04000009, 0x59cc0805, 0x591c0019, - 0x4803c857, 0x80040580, 0x04000004, 0x80000580, - 0x4803c856, 0x0401f003, 0x82000540, 0x00000001, - 0x5c000800, 0x1c01f000, 0x4c000000, 0x4c0c0000, - 0x4c100000, 0x42001800, 0x0000ffff, 0x42002000, - 0x00000004, 0x0401f013, 0x4c000000, 0x4c0c0000, - 0x4c100000, 0x59302009, 0x58101c03, 0x42002000, - 0x00000004, 0x0401f00b, 0x4c000000, 0x4c0c0000, - 0x4c100000, 0x59302009, 0x801021c0, 0x02000800, - 0x00100615, 0x58101c03, 0x42002000, 0x00000007, - 0x480fc857, 0x4813c857, 0x481bc857, 0x0201f800, - 0x001038c7, 0x5c002000, 0x5c001800, 0x5c000000, - 0x1c01f000, 0x83380580, 0x00000092, 0x02020800, - 0x00100615, 0x42000800, 0x80000040, 0x4a026203, - 0x00000001, 0x493a6403, 0x0201f000, 0x00020855, - 0x4d400000, 0x0201f800, 0x0010393e, 0x04000008, - 0x59a80005, 0x84000544, 0x48035005, 0x42028000, - 0x0000002a, 0x0201f800, 0x0010a25b, 0x5c028000, - 0x1c01f000, 0x59a80026, 0x8c000508, 0x04000005, - 0x599c0017, 0x8c00050a, 0x04020002, 0x1c01f000, - 0x82000540, 0x00000001, 0x1c01f000, 0x59300420, - 0x84000540, 0x48026420, 0x1c01f000, 0x4817c857, - 0x4c000000, 0x4c040000, 0x8c142d2a, 0x04000004, - 0x598800b9, 0x80000000, 0x480310b9, 0x8c142d2e, - 0x04000004, 0x598800ba, 0x80000000, 0x480310ba, - 0x8c142d2c, 0x04000013, 0x40140000, 0x82000500, - 0x00070000, 0x82000d80, 0x00030000, 0x0400000d, - 0x82000d80, 0x00040000, 0x0400000a, 0x82000d80, - 0x00050000, 0x04000007, 0x59880005, 0x80000000, - 0x48031005, 0x598800bb, 0x80000000, 0x480310bb, - 0x5c000800, 0x5c000000, 0x1c01f000, 0x4817c857, - 0x4c000000, 0x4c040000, 0x8c142d2a, 0x04000004, - 0x598800bc, 0x80000000, 0x480310bc, 0x8c142d2e, - 0x04000004, 0x598800bd, 0x80000000, 0x480310bd, - 0x8c142d2c, 0x04000013, 0x40140000, 0x82000500, - 0x00070000, 0x82000d80, 0x00030000, 0x0400000d, - 0x82000d80, 0x00040000, 0x0400000a, 0x82000d80, - 0x00050000, 0x04000007, 0x59880005, 0x80000000, - 0x48031005, 0x598800be, 0x80000000, 0x480310be, - 0x5c000800, 0x5c000000, 0x1c01f000, 0x4c000000, - 0x59880001, 0x80000000, 0x4803c857, 0x48031001, - 0x5c000000, 0x1c01f000, 0x4c000000, 0x59880000, - 0x80000000, 0x4803c857, 0x48031000, 0x5c000000, - 0x1c01f000, 0x4c000000, 0x59880002, 0x80000000, - 0x4803c857, 0x48031002, 0x5c000000, 0x1c01f000, - 0x4807c857, 0x4c000000, 0x8c040d2c, 0x04000004, - 0x598800a7, 0x80000000, 0x480310a7, 0x8c040d2a, - 0x04000004, 0x598800a8, 0x80000000, 0x480310a8, - 0x8c040d28, 0x04000004, 0x598800a9, 0x80000000, - 0x480310a9, 0x8c040d26, 0x04000004, 0x598800aa, - 0x80000000, 0x480310aa, 0x8c040d24, 0x04000004, - 0x598800ab, 0x80000000, 0x480310ab, 0x8c040d22, - 0x04000004, 0x598800ac, 0x80000000, 0x480310ac, - 0x8c040d20, 0x04000004, 0x598800ad, 0x80000000, - 0x480310ad, 0x5c000000, 0x1c01f000, 0x4807c857, - 0x4c000000, 0x598800ae, 0x80000000, 0x480310ae, - 0x5c000000, 0x1c01f000, 0x4807c857, 0x4c000000, - 0x8c040d1c, 0x04000004, 0x598800af, 0x80000000, - 0x480310af, 0x8c040d1a, 0x04000004, 0x598800b0, - 0x80000000, 0x480310b0, 0x5c000000, 0x1c01f000, - 0x4807c857, 0x4c000000, 0x8c040d18, 0x04000004, - 0x598800b1, 0x80000000, 0x480310b1, 0x8c040d16, - 0x04000004, 0x598800b2, 0x80000000, 0x480310b2, - 0x8c040d14, 0x04000004, 0x598800b3, 0x80000000, - 0x480310b3, 0x5c000000, 0x1c01f000, 0x4807c857, - 0x4c000000, 0x8c040d10, 0x04000004, 0x598800b4, - 0x80000000, 0x480310b4, 0x8c040d0c, 0x04000004, - 0x598800b5, 0x80000000, 0x480310b5, 0x5c000000, - 0x1c01f000, 0x4807c857, 0x4c000000, 0x8c040d08, - 0x04000004, 0x598800b6, 0x80000000, 0x480310b6, - 0x8c040d04, 0x04000004, 0x598800b7, 0x80000000, - 0x480310b7, 0x5c000000, 0x1c01f000, 0x4807c856, - 0x4c000000, 0x59880080, 0x80000000, 0x48031080, - 0x5c000000, 0x1c01f000, 0x4803c857, 0x4c040000, - 0x50000800, 0x80040800, 0x4807c857, 0x44040000, - 0x5c000800, 0x1c01f000, 0x480fc857, 0x4c000000, - 0x820c0580, 0x00000000, 0x04020004, 0x42000000, - 0x0010b617, 0x0401f014, 0x820c0580, 0x00001001, - 0x04020004, 0x42000000, 0x0010b618, 0x0401f00e, - 0x820c0580, 0x00001002, 0x04020004, 0x42000000, - 0x0010b619, 0x0401f008, 0x820c0c80, 0x0000201c, - 0x02021800, 0x00100615, 0x820c0500, 0x0000001f, - 0x0c01f804, 0x0401ffdd, 0x5c000000, 0x1c01f000, - 0x0010a8b0, 0x0010a8b3, 0x0010a8b6, 0x0010a8b9, - 0x0010a8bc, 0x0010a8bf, 0x0010a8c2, 0x0010a8c5, - 0x0010a8c8, 0x0010a8cb, 0x0010a8ce, 0x0010a8d1, - 0x0010a8d4, 0x0010a8d7, 0x0010a8da, 0x0010a8dd, - 0x0010a8e0, 0x0010a8e3, 0x0010a8e6, 0x0010a8e9, - 0x0010a8ec, 0x0010a8ef, 0x0010a8f2, 0x0010a8f5, - 0x0010a8f8, 0x0010a8fb, 0x0010a8fe, 0x0010a901, - 0x42000000, 0x0010b61a, 0x1c01f000, 0x42000000, - 0x0010b61b, 0x1c01f000, 0x42000000, 0x0010b61c, - 0x1c01f000, 0x42000000, 0x0010b61d, 0x1c01f000, - 0x42000000, 0x0010b61e, 0x1c01f000, 0x42000000, - 0x0010b61f, 0x1c01f000, 0x42000000, 0x0010b620, - 0x1c01f000, 0x42000000, 0x0010b621, 0x1c01f000, - 0x42000000, 0x0010b622, 0x1c01f000, 0x42000000, - 0x0010b623, 0x1c01f000, 0x42000000, 0x0010b624, - 0x1c01f000, 0x42000000, 0x0010b625, 0x1c01f000, - 0x42000000, 0x0010b626, 0x1c01f000, 0x42000000, - 0x0010b627, 0x1c01f000, 0x42000000, 0x0010b628, - 0x1c01f000, 0x42000000, 0x0010b629, 0x1c01f000, - 0x42000000, 0x0010b62a, 0x1c01f000, 0x42000000, - 0x0010b62b, 0x1c01f000, 0x42000000, 0x0010b62c, - 0x1c01f000, 0x42000000, 0x0010b62d, 0x1c01f000, - 0x42000000, 0x0010b62e, 0x1c01f000, 0x42000000, - 0x0010b62f, 0x1c01f000, 0x42000000, 0x0010b630, - 0x1c01f000, 0x42000000, 0x0010b631, 0x1c01f000, - 0x42000000, 0x0010b632, 0x1c01f000, 0x42000000, - 0x0010b633, 0x1c01f000, 0x42000000, 0x0010b634, - 0x1c01f000, 0x42000000, 0x0010b635, 0x1c01f000, - 0x480fc857, 0x4c000000, 0x820c0580, 0x00000001, - 0x04020004, 0x42000000, 0x0010b60c, 0x0401f012, - 0x820c0580, 0x00000002, 0x04020004, 0x42000000, - 0x0010b60d, 0x0401f00c, 0x820c0580, 0x00000003, - 0x04020004, 0x42000000, 0x0010b60e, 0x0401f006, - 0x820c0580, 0x00000004, 0x04020004, 0x42000000, - 0x0010b60f, 0x0401ff51, 0x5c000000, 0x1c01f000, - 0x4c000000, 0x59a80026, 0x4803c857, 0x8c000502, - 0x04000010, 0x8c000506, 0x04000004, 0x42000000, - 0x0010b63f, 0x0401f012, 0x8c00050a, 0x04000004, - 0x42000000, 0x0010b63e, 0x0401f00d, 0x8c000508, - 0x04000004, 0x42000000, 0x0010b641, 0x0401f008, - 0x0201f800, 0x00104e0d, 0x04000006, 0x8c000506, - 0x04020004, 0x42000000, 0x0010b640, 0x0401ff33, - 0x5c000000, 0x1c01f000, 0x8058b1c0, 0x02000800, - 0x00100615, 0x5450a800, 0x8050a000, 0x8054a800, - 0x8058b040, 0x040207fc, 0x1c01f000, 0x8058b1c0, - 0x02000800, 0x00100615, 0x4450a800, 0x8054a800, - 0x8058b040, 0x040207fd, 0x1c01f000, 0x8058b1c0, - 0x02000800, 0x00100615, 0x50500000, 0x9c0001c0, - 0x4400a800, 0x8050a000, 0x8054a800, 0x8058b040, - 0x040207fa, 0x1c01f000, 0x4c000000, 0x59a80008, - 0x8c00051c, 0x5c000000, 0x1c01f000, 0x00000001, - 0x00000002, 0x00000004, 0x00000008, 0x00000010, - 0x00000020, 0x00000040, 0x00000080, 0x00000100, - 0x00000200, 0x00000400, 0x00000800, 0x00001000, - 0x00002000, 0x00004000, 0x00008000, 0x00010000, - 0xd2764e14 -}; - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_length01 = 0x0000a971 ; -#else -uint32_t risc_code_length01 = 0x0000a971 ; -#endif - - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_addr02 = 0x0010d000 ; -#else -uint32_t risc_code_addr02 = 0x0010d000 ; -#endif - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_code02[] = { -#else -uint32_t risc_code02[] = { -#endif - 0x00000000, 0x00000000, 0x0010d000, 0x0000165e, - 0x00000000, 0x00000000, 0x00020000, 0x000009f7, - 0x836c0580, 0x00000003, 0x02020000, 0x00100314, - 0x42000000, 0x0010b2b7, 0x50000000, 0x800001c0, - 0x0402098a, 0x0401f94d, 0x0201f800, 0x00020524, - 0x0401fbfe, 0x0201f800, 0x0002084c, 0x0201f800, - 0x000206af, 0x0401f7ef, 0x59b800ea, 0x82000d00, - 0xf0000038, 0x02020000, 0x00100ac3, 0x8c000510, - 0x02000000, 0x00100ac2, 0x59ba60e0, 0x81300182, - 0x0402104e, 0x04002030, 0x8532653e, 0x59300406, - 0x82000580, 0x00000003, 0x04020028, 0x59300203, - 0x82000580, 0x00000004, 0x04020024, 0x59325808, - 0x59300402, 0x4a025a04, 0x00000103, 0x900001c0, - 0x48025806, 0x497a5807, 0x497a5c09, 0x5930001f, - 0x80000540, 0x02020800, 0x00100d9a, 0x59300004, - 0x8c00053e, 0x04020010, 0x0401fb47, 0x59326809, - 0x0201f800, 0x000208b4, 0x5934000f, 0x5934140b, - 0x80081040, 0x04001002, 0x480a6c0b, 0x80000540, - 0x04020a31, 0x59b800ea, 0x8c000510, 0x040207d7, - 0x1c01f000, 0x0201f800, 0x00106cb4, 0x040007ef, - 0x0201f000, 0x00100aae, 0x42027000, 0x00000055, - 0x0401f027, 0x83326500, 0x3fffffff, 0x59300406, - 0x82000580, 0x00000003, 0x04020015, 0x59325808, - 0x59326809, 0x59301402, 0x4a025a04, 0x00000103, - 0x900811c0, 0x480a5806, 0x497a5c09, 0x497a5807, - 0x0401fb21, 0x0201f800, 0x000208b4, 0x5934000f, - 0x5934140b, 0x80081040, 0x04001002, 0x480a6c0b, - 0x80000540, 0x04020a0c, 0x0401f7db, 0x42027000, - 0x00000054, 0x0401f00a, 0x83300500, 0x60000000, - 0x02000000, 0x00100ab1, 0x81326580, 0x8000013a, - 0x82000400, 0x00100ac9, 0x50027000, 0x59300c06, - 0x82040580, 0x00000002, 0x02000000, 0x00100aae, - 0x59300004, 0x8c00053e, 0x04020004, 0x0201f800, - 0x000208d8, 0x0401f7c4, 0x0201f800, 0x00106cb4, - 0x040007fb, 0x0201f000, 0x00100aae, 0x59325808, - 0x412c7000, 0x58380a04, 0x82040500, 0x0000000f, - 0x82000c00, 0x0010110d, 0x50044000, 0x0c01f001, - 0x00100e24, 0x00100e24, 0x000200a0, 0x00100e24, - 0x00100e24, 0x00100e24, 0x00100e24, 0x00100e24, - 0x000200b0, 0x00100e38, 0x00100e24, 0x00100e24, - 0x00100e26, 0x00100e24, 0x00100e24, 0x00100e24, - 0x5838040a, 0x8c000500, 0x02000800, 0x00100615, - 0x50200000, 0x80387c00, 0x583c1002, 0x583c2800, - 0x583c2001, 0x58380a07, 0x5838300f, 0x59303807, - 0x58384c08, 0x5838000d, 0x48026012, 0x0401f010, - 0x5838020a, 0x8c000502, 0x02000000, 0x00100e24, - 0x50200000, 0x80387c00, 0x583c2800, 0x583c2001, - 0x583c1002, 0x592c0a07, 0x592c4c08, 0x592c300f, - 0x59303807, 0x497a6012, 0x497a6013, 0x4816600e, - 0x4812600f, 0x480a6010, 0x481a6011, 0x80040840, - 0x4806600d, 0x02020000, 0x00100e65, 0x841c3d40, - 0x481e6007, 0x1c01f000, 0x41787800, 0x59325808, - 0x592c0c0a, 0x8c040d02, 0x02000000, 0x00100fda, - 0x592c000d, 0x592c100f, 0x592c0a04, 0x480a6011, - 0x48026012, 0x48026013, 0x412c3000, 0x82040500, - 0x0000000f, 0x82000400, 0x0010110d, 0x50003800, - 0x501c0000, 0x401c1000, 0x592c1a07, 0x4802600a, - 0x481a600b, 0x480a600c, 0x480e600d, 0x843c7d4a, - 0x403c1000, 0x1c01f000, 0x41787800, 0x497a6012, - 0x592c0a04, 0x412c3000, 0x592c1a07, 0x82040500, - 0x0000000f, 0x82000400, 0x0010110d, 0x50004000, - 0x50200000, 0x40201000, 0x4802600a, 0x481a600b, - 0x480a600c, 0x480e600d, 0x80000580, 0x483e6004, - 0x1c01f000, 0x0002014c, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x00020139, 0x00020139, 0x00020139, - 0x00020139, 0x4c000000, 0x4df00000, 0x4203e000, - 0xb0100000, 0x41f00000, 0x81fe1500, 0x8d0a1512, - 0x02020800, 0x00101468, 0x8d0a1518, 0x02020800, - 0x00020861, 0x8d0a151a, 0x04020ed0, 0x83080500, - 0x00000d00, 0x04020804, 0x5c03e000, 0x5c000000, - 0x1801f000, 0x8d0a1516, 0x02020800, 0x001012d9, - 0x8d0a1514, 0x02020800, 0x001011a5, 0x8d0a1508, - 0x02020800, 0x001011aa, 0x8d0a1500, 0x02020000, - 0x000207c8, 0x1c01f000, 0x42000000, 0x0010b2bd, - 0x50000000, 0x8c000504, 0x04000014, 0x42000000, - 0x0010b2bd, 0x50000000, 0x8c000502, 0x04020002, - 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, - 0x42034000, 0x0010b2a0, 0x59a0001d, 0x59a1d81e, - 0x84000502, 0x4803401d, 0x58ec0009, 0x0801f800, - 0x5c03e000, 0x1c01f000, 0x04027002, 0x04026002, - 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000, - 0x0201f800, 0x0010082a, 0x0400001a, 0x412dd800, - 0x48efc857, 0x0201f800, 0x00103941, 0x42034000, - 0x0010b2a0, 0x49a1d80b, 0x48ef401e, 0x59a0001d, - 0x84000544, 0x4803401d, 0x59e00020, 0x4803c857, - 0x59e00021, 0x4803c857, 0x59e00022, 0x4803c857, - 0x59e00023, 0x4803c857, 0x59e00024, 0x4803c857, - 0x0201f800, 0x00101fbb, 0x0201f800, 0x00101fda, - 0x5c03e000, 0x1c01f000, 0x4da00000, 0x4df00000, - 0x4203e000, 0x50000000, 0x04006051, 0x42034000, - 0x0010b2a0, 0x59a01017, 0x59a01818, 0x800c19c0, - 0x04020008, 0x59a0381b, 0x801c39c0, 0x02000800, - 0x00100615, 0x59a0041c, 0x801c3c00, 0x0401f00c, - 0x59a00419, 0x82000400, 0x00000002, 0x48034419, - 0x82000c80, 0x00000013, 0x04001003, 0x497b4419, - 0x41780000, 0x59a03816, 0x801c3c00, 0x80081040, - 0x480b4017, 0x581c0200, 0x4803c021, 0x581c0401, - 0x4803c022, 0x581c0201, 0x4803c023, 0x581c0400, - 0x4803c020, 0x900001c0, 0x82000540, 0x00000012, - 0x4803c011, 0x59e00017, 0x8c000508, 0x04000003, - 0x4a03c017, 0x00000002, 0x4203e000, 0x30000001, - 0x800c19c0, 0x04000007, 0x800c1840, 0x480f4018, - 0x0402001f, 0x497b4419, 0x497b4219, 0x0401f01c, - 0x800811c0, 0x0402000b, 0x4d2c0000, 0x59a2581b, - 0x0201f800, 0x0010083a, 0x5c025800, 0x497b401b, - 0x497b401a, 0x497b441c, 0x497b421c, 0x0401f010, - 0x59a0041c, 0x82000400, 0x00000002, 0x82000c80, - 0x00000012, 0x4803441c, 0x04001009, 0x4d2c0000, - 0x59a2581b, 0x592c3813, 0x481f401b, 0x497b441c, - 0x0201f800, 0x0010083a, 0x5c025800, 0x5c03e000, - 0x5c034000, 0x1c01f000, 0x59a80005, 0x82000500, - 0x00000003, 0x02020000, 0x00104145, 0x59340400, - 0x82000580, 0x00000606, 0x02020000, 0x00104116, - 0x5934000d, 0x80027d40, 0x02020000, 0x00104151, - 0x0401f803, 0x80000580, 0x1c01f000, 0x5934000f, - 0x59341203, 0x80080540, 0x0402005d, 0x5934020b, - 0x5934140b, 0x80080480, 0x04021059, 0x0201f800, - 0x00020892, 0x04000052, 0x592c0406, 0x49366009, - 0x492e6008, 0x4a026406, 0x00000003, 0x4a026403, - 0x00000040, 0x80081000, 0x480a6c0b, 0x800000c2, - 0x800018c4, 0x800c0400, 0x48026206, 0x592c0808, - 0x592c1809, 0x592c020a, 0x48066017, 0x480e6018, - 0x8c000502, 0x0400002a, 0x4a026203, 0x00000004, - 0x592c0207, 0x80000040, 0x0402001a, 0x59a80070, - 0x80000040, 0x040207ff, 0x592c0204, 0x82000500, - 0x000000ff, 0x82000580, 0x00000018, 0x04020011, - 0x592c180f, 0x59300007, 0x82000540, 0x00000091, - 0x480e6011, 0x48026007, 0x42000000, 0x80000004, - 0x48026004, 0x59bc00ea, 0x8c000516, 0x040207fe, - 0x83300400, 0x20000000, 0x480378e1, 0x1c01f000, - 0x0401fe4b, 0x59300007, 0x8400054e, 0x48026007, - 0x592c1a04, 0x820c1d00, 0x000000ff, 0x820c0580, - 0x00000048, 0x04000012, 0x0401f7ec, 0x8c000500, - 0x04020e9e, 0x4a026203, 0x00000002, 0x59a80071, - 0x80000040, 0x040207ff, 0x592c1a04, 0x820c1d00, - 0x000000ff, 0x820c0580, 0x00000018, 0x040007df, - 0x820c0580, 0x00000048, 0x040207dc, 0x42000800, - 0x80000804, 0x0201f000, 0x00106466, 0x800811c0, - 0x04020003, 0x4a026a03, 0x00000001, 0x59340010, - 0x492e6810, 0x80000d40, 0x04020003, 0x492e680f, - 0x1c01f000, 0x492c0800, 0x1c01f000, 0x83440c80, - 0x00000800, 0x04021009, 0x83440400, 0x0010aa00, - 0x50000000, 0x80000540, 0x04000004, 0x40026800, - 0x80000580, 0x1c01f000, 0x82000540, 0x00000001, - 0x1c01f000, 0x59340203, 0x80000540, 0x0402004b, - 0x4d300000, 0x4d2c0000, 0x5934000f, 0x80025d40, - 0x04000044, 0x0201f800, 0x00020892, 0x0400003f, - 0x592c0000, 0x4802680f, 0x80000540, 0x04020002, - 0x48026810, 0x592c2a04, 0x80081000, 0x480a6c0b, - 0x49366009, 0x492e6008, 0x82142d00, 0x000000ff, - 0x82140580, 0x00000012, 0x04000035, 0x4a026406, - 0x00000003, 0x4a026403, 0x00000040, 0x592c0406, - 0x800000c2, 0x800018c4, 0x800c0400, 0x48026206, - 0x592c0808, 0x592c1809, 0x592c020a, 0x48066017, - 0x480e6018, 0x8c000502, 0x02000000, 0x001045a1, - 0x4a026203, 0x00000004, 0x592c0207, 0x80000040, - 0x02020000, 0x00104594, 0x82140580, 0x00000018, - 0x02020000, 0x00104594, 0x592c180f, 0x59300007, - 0x82000540, 0x00000091, 0x480e6011, 0x48026007, - 0x42000000, 0x80000004, 0x48026004, 0x59bc00ea, - 0x8c000516, 0x040207fe, 0x83300400, 0x20000000, - 0x480378e1, 0x5934020b, 0x5934140b, 0x80080480, - 0x040017be, 0x0401f003, 0x4a026a03, 0x00000001, - 0x5c025800, 0x5c026000, 0x1c01f000, 0x497a5800, - 0x49325809, 0x4a026406, 0x00000006, 0x4a026203, - 0x00000007, 0x0401f802, 0x0401f7ef, 0x59a80021, - 0x800001c0, 0x02020000, 0x001045c3, 0x59a80005, - 0x8c000504, 0x02020000, 0x001045bf, 0x59340200, - 0x8c000518, 0x02020000, 0x001045bb, 0x592c0a0c, - 0x48066202, 0x4a025a06, 0x00000000, 0x8c000508, - 0x02020000, 0x001045b7, 0x4d3c0000, 0x417a7800, - 0x0201f800, 0x000207ce, 0x5c027800, 0x1c01f000, - 0x59980026, 0x497a5800, 0x80000540, 0x04020067, - 0x59d80105, 0x82000d00, 0x00018780, 0x04020197, - 0x800000f6, 0x8000013c, 0x0c01f001, 0x000202f3, - 0x0002034e, 0x00020308, 0x00020326, 0x592c0001, - 0x492fb107, 0x80000d40, 0x04020805, 0x59940019, - 0x80000540, 0x04002085, 0x1c01f000, 0x497a5801, - 0x40065800, 0x592c0001, 0x496a5800, 0x815eb800, - 0x412ed000, 0x80000d40, 0x040207f9, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x1c01f000, - 0x492fb107, 0x592c0001, 0x80000d40, 0x04020ff0, - 0x59da5908, 0x835c0480, 0x00000020, 0x0400100d, - 0x0402b00b, 0x492fb007, 0x0400e7fa, 0x59d80105, - 0x82000500, 0x00018780, 0x0402016c, 0x59940019, - 0x80000540, 0x04002065, 0x1c01f000, 0x0400f009, - 0x496a5800, 0x412ed000, 0x815eb800, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x0401f7ef, - 0x492fa807, 0x0401f7ed, 0x59d81108, 0x45681000, - 0x400ad000, 0x815eb800, 0x0400e7fc, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x0402d009, - 0x592c0001, 0x492fb107, 0x80000d40, 0x04020fc8, - 0x59940019, 0x80000540, 0x04002048, 0x1c01f000, - 0x59d80105, 0x82000500, 0x00018780, 0x04020147, - 0x42000000, 0x0010b654, 0x0201f800, 0x0010a86e, - 0x59980026, 0x59980828, 0x80000000, 0x48033026, - 0x492f3028, 0x800409c0, 0x04000003, 0x492c0800, - 0x0401f002, 0x492f3029, 0x592c0001, 0x80000d40, - 0x04020faf, 0x0401f7e7, 0x59980026, 0x59980828, - 0x80000000, 0x48033026, 0x492f3028, 0x800409c0, - 0x04000003, 0x492c0800, 0x0401f002, 0x492f3029, - 0x592c0001, 0x80000d40, 0x04020fa1, 0x0402d00d, - 0x59980029, 0x80025d40, 0x0400000e, 0x59980026, - 0x80000040, 0x48033026, 0x04020002, 0x48033028, - 0x592c0000, 0x48033029, 0x492fb107, 0x0400d7f5, - 0x42000000, 0x0010b654, 0x0201f800, 0x0010a86e, - 0x0402e00a, 0x59da5908, 0x496a5800, 0x412ed000, - 0x815eb800, 0x0400e7fc, 0x59c80000, 0x82000540, - 0x00001200, 0x48039000, 0x59d80105, 0x82000500, - 0x00018780, 0x04020109, 0x59940019, 0x80000540, - 0x04002002, 0x1c01f000, 0x59980023, 0x48032819, - 0x1c01f000, 0x592c0404, 0x8c00051e, 0x02020000, - 0x00104b7b, 0x59980022, 0x80000540, 0x0402075d, - 0x59980026, 0x497a5800, 0x80000540, 0x02020000, - 0x00104ba6, 0x59d80105, 0x82000d00, 0x00018780, - 0x040200f2, 0x800000f6, 0x8000013c, 0x0c01f001, - 0x00020398, 0x00104ba6, 0x0002039d, 0x000203e6, - 0x592c0001, 0x492fb107, 0x80000d40, 0x04020760, - 0x1c01f000, 0x592c0001, 0x492fb107, 0x80000d40, - 0x04020f5b, 0x59da5908, 0x835c0480, 0x00000020, - 0x0400102b, 0x0402b033, 0x492fb007, 0x0400e7fa, - 0x59d80105, 0x82000500, 0x00018780, 0x040200d7, - 0x0400601f, 0x59d8010a, 0x59d8090a, 0x80040580, - 0x040207fd, 0x800408e0, 0x599c1017, 0x8c081508, - 0x04020028, 0x82040d40, 0x00000013, 0x5998002b, - 0x4807c011, 0x84000500, 0x4803302b, 0x59e00017, - 0x8c000508, 0x04020004, 0x4203e000, 0x30000001, - 0x1c01f000, 0x4a03c017, 0x00000003, 0x82040500, - 0x000000ff, 0x82000580, 0x0000001d, 0x040207f7, - 0x4a03c017, 0x0000000d, 0x0401f7f4, 0x5998082b, - 0x84040d40, 0x4807302b, 0x1c01f000, 0x496a5800, - 0x412ed000, 0x815eb800, 0x59c80000, 0x82000540, - 0x00001200, 0x48039000, 0x0400e7cb, 0x0401f7d1, - 0x0402f7f7, 0x492fa807, 0x0400e7c7, 0x0401f7cd, - 0x59e0000f, 0x59e0100f, 0x80081580, 0x040207fd, - 0x81281580, 0x040007d4, 0x40025000, 0x82040d40, - 0x0000001d, 0x0401f7d2, 0x59d80908, 0x45680800, - 0x4006d000, 0x815eb800, 0x0400e7fc, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x02006000, - 0x00104b8d, 0x59d8010a, 0x59d8090a, 0x80040d80, - 0x040207fd, 0x900001c0, 0x82000540, 0x00000013, - 0x4803c011, 0x5998002b, 0x84000500, 0x4803302b, - 0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017, - 0x00000003, 0x4203e000, 0x30000001, 0x59d80105, - 0x82000500, 0x00018780, 0x0402007c, 0x0202d000, - 0x00104b92, 0x592c0001, 0x492fb107, 0x80000d40, - 0x040206ef, 0x1c01f000, 0x59980020, 0x0c01f001, - 0x00020413, 0x00020414, 0x00020434, 0x1c01f000, - 0x4df00000, 0x4203e000, 0x50000000, 0x04026876, - 0x04006004, 0x599c0017, 0x8c000508, 0x040208f5, - 0x59980029, 0x80025d40, 0x0400000a, 0x0402d00b, - 0x59980026, 0x80000040, 0x48033026, 0x592c0000, - 0x492fb107, 0x48033029, 0x04020002, 0x48033028, - 0x5c03e000, 0x1c01f000, 0x59d80105, 0x82000500, - 0x00018780, 0x04020055, 0x42000000, 0x0010b654, - 0x0201f800, 0x0010a86e, 0x5c03e000, 0x1c01f000, - 0x4df00000, 0x4203e000, 0x50000000, 0x599cb817, - 0x59940019, 0x80000540, 0x04002023, 0x0400000e, - 0x59980022, 0x82000580, 0x00000005, 0x0400001e, - 0x59a80069, 0x81640580, 0x0402001b, 0x8c5cbd08, - 0x04000007, 0x59a8006a, 0x59a80866, 0x80040580, - 0x04020015, 0x8c5cbd08, 0x0402002b, 0x59d8090b, - 0x59d8010a, 0x80040580, 0x0400000d, 0x0400600e, - 0x4a03c011, 0x80400012, 0x4a03c020, 0x00008040, - 0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017, - 0x00000002, 0x4203e000, 0x30000001, 0x4a032819, - 0xffff0000, 0x0400e879, 0x04006003, 0x8c5cbd08, - 0x0402088e, 0x59980029, 0x80025d40, 0x04020003, - 0x5c03e000, 0x1c01f000, 0x59d80105, 0x82000500, - 0x00018780, 0x04020019, 0x0202d000, 0x00104c06, - 0x59980826, 0x592c0000, 0x80040840, 0x48073026, - 0x492fb107, 0x48033029, 0x040207f2, 0x48033028, - 0x0401f7f0, 0x59e0000f, 0x59e0080f, 0x80040580, - 0x040207fd, 0x59e00010, 0x59e01010, 0x80081580, - 0x040207fd, 0x40065000, 0x80041580, 0x040007cc, - 0x040067e1, 0x0401f7cf, 0x4803c857, 0x485fc857, - 0x8c00050e, 0x02020800, 0x0010060d, 0x4203e000, - 0x50000000, 0x4200b800, 0x00008004, 0x0201f000, - 0x0010061a, 0x5998002b, 0x8c000500, 0x04020039, - 0x0400e006, 0x59d80105, 0x82000500, 0x00018780, - 0x040207ee, 0x1c01f000, 0x59da5908, 0x835c0c80, - 0x00000020, 0x04001003, 0x0400b028, 0x0400f02a, - 0x496a5800, 0x412ed000, 0x815eb800, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x0400e7f3, - 0x59d8010a, 0x59d8090a, 0x80040580, 0x040207fd, - 0x800408e0, 0x599c1017, 0x8c081508, 0x04020021, - 0x82040d40, 0x00000013, 0x4807c011, 0x59e00017, - 0x8c000508, 0x0400000a, 0x4a03c017, 0x00000003, - 0x82040500, 0x000000ff, 0x82000580, 0x0000001d, - 0x04020003, 0x4a03c017, 0x0000000d, 0x4203e000, - 0x30000001, 0x59d80105, 0x82000500, 0x00018780, - 0x040207c2, 0x1c01f000, 0x492fb007, 0x0400e7d3, - 0x0401f7e0, 0x492fa807, 0x0400e7d0, 0x0401f7dd, - 0x84000500, 0x4803302b, 0x0400e7cc, 0x0401f7d9, - 0x59e0000f, 0x59e0100f, 0x80081580, 0x040207fd, - 0x81281580, 0x040007db, 0x40025000, 0x82040d40, - 0x0000001d, 0x0401f7d9, 0x59da5908, 0x496a5800, - 0x412ed000, 0x815eb800, 0x0400e7fc, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x59d8090b, - 0x59980024, 0x48073024, 0x80040480, 0x04020004, - 0x59940019, 0x80000540, 0x04022003, 0x59980823, - 0x48072819, 0x59d80105, 0x82000500, 0x00018780, - 0x04020796, 0x1c01f000, 0x59981025, 0x59e00010, - 0x59e00810, 0x80041d80, 0x040207fd, 0x80080580, - 0x04000011, 0x48073025, 0x59e0000f, 0x59e0100f, - 0x80081d80, 0x040207fd, 0x81280580, 0x04000006, - 0x400a5000, 0x40080000, 0x80040580, 0x0402067f, - 0x1c01f000, 0x59940019, 0x80000540, 0x040227fa, - 0x1c01f000, 0x59e0000f, 0x59e0100f, 0x80081d80, - 0x040207fd, 0x81280580, 0x040007f6, 0x400a5000, - 0x59940019, 0x80000540, 0x040027ef, 0x1c01f000, - 0x59e0000f, 0x59e0100f, 0x80080d80, 0x040207fd, - 0x81280580, 0x04020002, 0x1c01f000, 0x400a5000, - 0x900811c0, 0x82081540, 0x0000001c, 0x480bc011, - 0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017, - 0x0000000c, 0x4203e000, 0x30000001, 0x1c01f000, - 0x41700000, 0x0c01f001, 0x001050f0, 0x0002052f, - 0x001050f0, 0x001050f1, 0x001050ee, 0x001050ee, - 0x001050ee, 0x001050ee, 0x00105594, 0x04010037, - 0x59980006, 0x80000540, 0x0402003c, 0x0402c01c, - 0x4202f800, 0x00000010, 0x4df00000, 0x4203e000, - 0x50000000, 0x49db3005, 0x59da5808, 0x592c0204, - 0x497a5800, 0x497a5801, 0x82000500, 0x000000ff, - 0x82000c80, 0x00000079, 0x04021036, 0x0c01f839, - 0x5c03e000, 0x817ef840, 0x04000009, 0x836c0580, - 0x00000003, 0x04020006, 0x83700580, 0x00000001, - 0x04020010, 0x0401001b, 0x0400c7e8, 0x0400f94b, - 0x0400b135, 0x59d40005, 0x82000500, 0x43018780, - 0x02020000, 0x00105523, 0x59d80005, 0x82000500, - 0x43018780, 0x02020000, 0x0010552a, 0x1c01f000, - 0x83700580, 0x00000003, 0x02000800, 0x001050f1, - 0x83700580, 0x00000001, 0x040207ed, 0x04010005, - 0x0400c7d2, 0x0401f7ea, 0x4202f800, 0x00000010, - 0x4df00000, 0x4203e000, 0x50000000, 0x49d73005, - 0x59d65808, 0x0401f7ce, 0x4df00000, 0x4203e000, - 0x50000000, 0x40025800, 0x592c0204, 0x497b3005, - 0x497b3006, 0x4202f800, 0x00000010, 0x0401f7c7, - 0x0201f800, 0x00105161, 0x5c03e000, 0x0401f7d4, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105207, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105171, 0x00105161, - 0x00105161, 0x00105161, 0x00105231, 0x00105161, - 0x00105161, 0x00105161, 0x00020623, 0x00105161, - 0x00105398, 0x00105161, 0x00105161, 0x00105161, - 0x000205f5, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105199, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x001054b7, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105502, 0x00105161, 0x0010518b, - 0x00105161, 0x0010547b, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105449, 0x00105161, 0x00105449, - 0x00105556, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105409, 0x00105539, - 0x00105161, 0x00105549, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x00105161, 0x00105161, 0x00105161, - 0x00105161, 0x592c0204, 0x80000110, 0x80000040, - 0x0400000b, 0x02001000, 0x00105169, 0x48033002, - 0x492f3003, 0x492f3004, 0x4a033008, 0x00020603, - 0x4202e000, 0x00000003, 0x1c01f000, 0x592c0406, - 0x82000c80, 0x0000199a, 0x02021000, 0x00105179, - 0x59a80021, 0x80000540, 0x02020000, 0x001051a7, - 0x592e8a06, 0x83440c80, 0x000007f0, 0x02021000, - 0x00105179, 0x83440400, 0x0010aa00, 0x50000000, - 0x80026d40, 0x02000000, 0x001051bb, 0x59340002, - 0x592c0810, 0x80040580, 0x82000500, 0x00ffffff, - 0x02020000, 0x00105179, 0x0201f800, 0x000201ee, - 0x02020000, 0x001051be, 0x1c01f000, 0x592c0204, - 0x80000110, 0x02000000, 0x00105169, 0x80000040, - 0x0402000b, 0x592c040a, 0x8c000504, 0x04000010, - 0x592c0207, 0x82000c80, 0x00001001, 0x02021000, - 0x00105179, 0x0201f000, 0x0010556e, 0x48033002, - 0x492f3003, 0x492f3004, 0x4a033008, 0x0002063b, - 0x4202e000, 0x00000003, 0x1c01f000, 0x592c0406, - 0x82000c80, 0x0000199a, 0x02021000, 0x00105179, - 0x592e8a06, 0x417a7800, 0x0401fc25, 0x02020000, - 0x0010533c, 0x59340002, 0x592c0808, 0x80040580, - 0x82000500, 0x00ffffff, 0x02020000, 0x00105179, - 0x497a5808, 0x592e6009, 0x83300580, 0xffffffff, - 0x02000000, 0x001052fc, 0x83300480, 0x0010cfc0, - 0x02001000, 0x00105359, 0x59a8000b, 0x81300480, - 0x02021000, 0x00105359, 0x592c240a, 0x49366009, - 0x8c10251c, 0x02020000, 0x001052ea, 0x59a80068, - 0x8c000510, 0x02020000, 0x00105372, 0x59a80821, - 0x800409c0, 0x02020000, 0x001052d0, 0x59a80805, - 0x8c040d04, 0x02020000, 0x00105363, 0x59340200, - 0x8c000518, 0x02020000, 0x00105354, 0x59300c06, - 0x82040580, 0x00000006, 0x02020000, 0x001052f4, - 0x59300414, 0x8c000516, 0x02020000, 0x0010535e, - 0x8c102508, 0x02020000, 0x0010a3d7, 0x59300808, - 0x4a025a06, 0x00000000, 0x800409c0, 0x02020000, - 0x001052cb, 0x592c0a0c, 0x48066202, 0x492e6008, - 0x0401f14a, 0x4df00000, 0x4203e000, 0x50000000, - 0x0402b00b, 0x835c0480, 0x00000020, 0x0400100d, - 0x815eb840, 0x416a5800, 0x592ed000, 0x492fb007, - 0x497a5800, 0x497a5801, 0x0400b7f7, 0x59d80005, - 0x82000500, 0x43018780, 0x02020000, 0x0010552a, - 0x5c03e000, 0x1c01f000, 0x4df00000, 0x4203e000, - 0x50000000, 0x0402f00b, 0x835c0480, 0x00000020, - 0x0400100d, 0x815eb840, 0x416a5800, 0x592ed000, - 0x492fa807, 0x497a5800, 0x497a5801, 0x0400f7f7, - 0x59d40005, 0x82000500, 0x43018780, 0x02020000, - 0x00105523, 0x5c03e000, 0x1c01f000, 0x4df00000, - 0x4203e000, 0x50000000, 0x59940024, 0x80000540, - 0x0400010f, 0x4c000000, 0x42000000, 0x00001000, - 0x50000000, 0x82000480, 0x24320001, 0x04020015, - 0x42000800, 0x00000064, 0x80040840, 0x04000007, - 0x4a030000, 0x00000001, 0x40000000, 0x59800000, - 0x8c000500, 0x040007f9, 0x04000008, 0x42000800, - 0x00007a01, 0x50040000, 0x8c000510, 0x04000003, - 0x84000510, 0x44000800, 0x4a030000, 0x00000000, - 0x59e00002, 0x8c00051e, 0x0402001b, 0x42000000, - 0x00001000, 0x50000000, 0x82000480, 0x24320002, - 0x04020015, 0x42000800, 0x00000064, 0x80040840, - 0x04000007, 0x4a030000, 0x00000001, 0x40000000, - 0x59800000, 0x8c000500, 0x040007f9, 0x04000008, - 0x42000800, 0x00007a17, 0x50040000, 0x8c00050e, - 0x04020003, 0x8400054e, 0x44000800, 0x4a030000, - 0x00000000, 0x5c000000, 0x5994781a, 0x48032825, - 0x803c0480, 0x04001004, 0x04000003, 0x4803281a, - 0x0401f022, 0x41787800, 0x803c7800, 0x82000400, - 0x000003e8, 0x040027fd, 0x4803281a, 0x59a80024, - 0x803c1400, 0x480b5024, 0x803c0040, 0x04000002, - 0x483fc857, 0x59e40852, 0x59a80025, 0x80040580, - 0x04000004, 0x480bc857, 0x59e40052, 0x48035025, - 0x59940026, 0x803c0400, 0x48032826, 0x0201f800, - 0x00105d5a, 0x59940000, 0x82000580, 0x00000000, - 0x04020006, 0x59940026, 0x48032827, 0x497b2826, - 0x4a032800, 0x00000001, 0x4c0c0000, 0x59940007, - 0x80000d40, 0x0400001d, 0x59941006, 0x59940025, - 0x80081c80, 0x04001004, 0x04000003, 0x480f2806, - 0x0401f016, 0x80040840, 0x48072807, 0x82040580, - 0x000003e8, 0x04020007, 0x4c040000, 0x4c0c0000, - 0x59940008, 0x0801f800, 0x5c001800, 0x5c000800, - 0x800409c0, 0x04020004, 0x59940008, 0x0801f800, - 0x0401f006, 0x400c0000, 0x820c1c00, 0x0000000a, - 0x040027ed, 0x480f2806, 0x5c001800, 0x4d180000, - 0x59c40008, 0x8c000534, 0x04020025, 0x417a3000, - 0x83947c00, 0x00000009, 0x583c0001, 0x80000d40, - 0x04020008, 0x823c7c00, 0x00000003, 0x811a3000, - 0x83180580, 0x00000005, 0x040207f8, 0x0401f018, - 0x583c1000, 0x59940025, 0x80080480, 0x04001005, - 0x04000004, 0x48007800, 0x80000040, 0x04021010, - 0x80040840, 0x48047801, 0x04000008, 0x82000400, - 0x0000000a, 0x48007800, 0x040027fa, 0x82040500, - 0x0000007f, 0x0401f7e8, 0x583c0002, 0x4c3c0000, - 0x0801f800, 0x5c007800, 0x0401f7e3, 0x5c023000, - 0x59940019, 0x80001540, 0x04000007, 0x04002006, - 0x59940025, 0x80080480, 0x04021002, 0x80000580, - 0x48032819, 0x5994001c, 0x80000d40, 0x04000013, - 0x5994101b, 0x59940025, 0x80080480, 0x04001005, - 0x04000004, 0x4803281b, 0x80000040, 0x0402100b, - 0x80040840, 0x4807281c, 0x04020004, 0x5994001d, - 0x0801f800, 0x0401f005, 0x82000400, 0x0000000a, - 0x4803281b, 0x040027f7, 0x59940004, 0x80000d40, - 0x04000013, 0x59941003, 0x59940025, 0x80080480, - 0x04001005, 0x04000004, 0x48032803, 0x80000040, - 0x0402100b, 0x80040840, 0x48072804, 0x04020004, - 0x59940005, 0x0801f800, 0x0401f005, 0x82000400, - 0x0000000a, 0x48032803, 0x040027f7, 0x5994001f, - 0x80000d40, 0x04000013, 0x5994101e, 0x59940025, - 0x80080480, 0x04001005, 0x04000004, 0x4803281e, - 0x80000040, 0x0402100b, 0x80040840, 0x4807281f, - 0x04020004, 0x59940020, 0x0801f800, 0x0401f005, - 0x82000400, 0x00000001, 0x4803281e, 0x040027f7, - 0x59940022, 0x80000d40, 0x04000013, 0x59941021, - 0x59940025, 0x80080480, 0x04001005, 0x04000004, - 0x48032821, 0x80000040, 0x0402100b, 0x80040840, - 0x48072822, 0x04020004, 0x59940023, 0x0801f800, - 0x0401f005, 0x82000400, 0x0000000a, 0x48032821, - 0x040027f7, 0x59940824, 0x59940025, 0x80040480, - 0x02001800, 0x00100615, 0x48032824, 0x59940000, - 0x0c01f001, 0x00105cee, 0x00105cf0, 0x00105d16, - 0x59940024, 0x80000000, 0x48032824, 0x4203e000, - 0x70000000, 0x1c01f000, 0x592c0406, 0x800000c2, - 0x800008c4, 0x80040c00, 0x592c040a, 0x48066206, - 0x82000d00, 0x00000003, 0x02000000, 0x00105e97, - 0x8c000500, 0x0402002c, 0x59a80872, 0x80040840, - 0x040207ff, 0x8c00051e, 0x02000000, 0x00105e72, - 0x82000d00, 0x000000c0, 0x02020000, 0x00105e68, - 0x82000d00, 0x00002020, 0x02020000, 0x00105e65, - 0x813e79c0, 0x02020000, 0x00105e65, 0x592c0c0c, - 0x800409c0, 0x02020000, 0x00105e65, 0x59300a03, - 0x82040d80, 0x00000007, 0x02020000, 0x00105e65, - 0x4a026203, 0x00000003, 0x4a026403, 0x00000043, - 0x0201f800, 0x000200ca, 0x82080d40, 0x80003465, - 0x48066004, 0x497a6000, 0x59bc00ea, 0x8c000516, - 0x040207fe, 0x83300400, 0xa0000000, 0x480378e1, - 0x1c01f000, 0x8c000502, 0x02020000, 0x00105eba, - 0x8c00051e, 0x0400000e, 0x82000d00, 0x000000c0, - 0x04000005, 0x82040d80, 0x000000c0, 0x02020000, - 0x00105ebf, 0x82000d00, 0x00002020, 0x82040d80, - 0x00002020, 0x02000000, 0x00105e86, 0x592c0207, - 0x80000040, 0x02020000, 0x00105e90, 0x592c180d, - 0x800c19c0, 0x02020000, 0x00105e90, 0x592c180f, - 0x59300007, 0x82000540, 0x00000011, 0x480e6011, - 0x48026007, 0x4a026203, 0x00000004, 0x4a026403, - 0x00000042, 0x42000800, 0x80002001, 0x0401f02a, - 0x5c000000, 0x4c000000, 0x4803c857, 0x4807c857, - 0x0401f003, 0x42000800, 0x00000001, 0x59325808, - 0x832c0500, 0x00ff0000, 0x0400000d, 0x592c0000, - 0x48065a06, 0x48026008, 0x592c040a, 0x8c000510, - 0x04020008, 0x0201f800, 0x00020381, 0x417a7800, - 0x59300008, 0x80025d40, 0x0402078c, 0x1c01f000, - 0x456a5800, 0x412ed000, 0x815eb800, 0x59c80000, - 0x82000540, 0x00001200, 0x48039000, 0x0401f7f4, - 0x59840000, 0x80000540, 0x04020002, 0x1c01f000, - 0x59840003, 0x80000540, 0x02020000, 0x00105f37, - 0x1c01f000, 0x59300004, 0x82000500, 0x00000100, - 0x80040d40, 0x48066004, 0x59bc00ea, 0x8c000516, - 0x040207fe, 0x83300400, 0x40000000, 0x480378e1, - 0x1c01f000, 0x59bc00ea, 0x82001500, 0xb0000018, - 0x02020000, 0x001069c6, 0x8c000510, 0x0400002a, - 0x59bc10e0, 0x82080500, 0xfffff000, 0x0402000a, - 0x80080108, 0x820a3500, 0x0000000f, 0x4803c857, - 0x1201f000, 0x001069cc, 0x84000510, 0x48026004, - 0x0401f016, 0x840a653e, 0x59300004, 0x8c000520, - 0x040007fa, 0x82000500, 0xfffefeff, 0x48026004, - 0x8c08153e, 0x04020005, 0x42027000, 0x00000013, - 0x0401f858, 0x0401f009, 0x59300004, 0x8c000514, - 0x04000003, 0x0401ffac, 0x0401f02e, 0x42027000, - 0x00000049, 0x0401f84f, 0x59bc00ea, 0x82001500, - 0xb0000018, 0x02020000, 0x001069c6, 0x8c000510, - 0x040207d8, 0x1c01f000, 0x83640480, 0x00000010, - 0x04001019, 0x41626000, 0x41580000, 0x59300a03, - 0x82040d80, 0x00000000, 0x04000008, 0x83326400, - 0x00000024, 0x81300c80, 0x040017f9, 0x42026000, - 0x0010cfc0, 0x0401f7f6, 0x4a026203, 0x00000008, - 0x8166c840, 0x8332c400, 0x00000024, 0x81600480, - 0x04021002, 0x1c01f000, 0x837ac540, 0x0010cfc0, - 0x1c01f000, 0x42000000, 0x0010b653, 0x0201f800, - 0x0010a86e, 0x4967c857, 0x80026580, 0x1c01f000, - 0x83300480, 0x0010cfc0, 0x02001800, 0x00100615, - 0x41580000, 0x81300480, 0x0402100c, 0x04011000, - 0x457a6000, 0x4a026202, 0x0000ffff, 0x83300400, - 0x00000003, 0x4803c840, 0x4a03c842, 0x00000021, - 0x8166c800, 0x1c01f000, 0x41540000, 0x81300480, - 0x02021800, 0x00100615, 0x04011000, 0x457a6000, - 0x4a026202, 0x0000ffff, 0x83300400, 0x00000003, - 0x4803c840, 0x4a03c842, 0x00000021, 0x59a80066, - 0x49335065, 0x80000000, 0x48035066, 0x1c01f000, - 0x4d340000, 0x59326809, 0x59300406, 0x82000500, - 0x0000001f, 0x0c01f803, 0x5c026800, 0x1c01f000, - 0x001076ed, 0x00107700, 0x0010771a, 0x00020900, - 0x001096c1, 0x001096dc, 0x00020975, 0x001076ed, - 0x00107700, 0x00106226, 0x00107733, 0x001076ed, - 0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed, - 0x0010936a, 0x0010a4d0, 0x001076ed, 0x001076ed, - 0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed, - 0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed, - 0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed, - 0x59300203, 0x82000c80, 0x0000000e, 0x02021800, - 0x00100615, 0x0c01f001, 0x00107731, 0x00108337, - 0x00020914, 0x001084cc, 0x00108566, 0x00107731, - 0x00107731, 0x00107731, 0x0010831c, 0x00107731, - 0x00107731, 0x00107731, 0x00107731, 0x0010873a, - 0x83380480, 0x00000058, 0x04021007, 0x83380480, - 0x00000040, 0x04001004, 0x4d2c0000, 0x0c01f803, - 0x5c025800, 0x1c01f000, 0x001083c1, 0x001083c1, - 0x001083c1, 0x001083c1, 0x001083c1, 0x001083c3, - 0x00108463, 0x001083c1, 0x001083c1, 0x001083c1, - 0x001083c1, 0x001083c1, 0x001083c1, 0x001083c1, - 0x001083c1, 0x001083c1, 0x001083c1, 0x001083c1, - 0x001083c1, 0x00108467, 0x00020936, 0x001083c1, - 0x00108466, 0x00108468, 0x59325808, 0x59300811, - 0x59301402, 0x59340200, 0x8c00050e, 0x0402001c, - 0x0401f826, 0x04000005, 0x4a025a04, 0x00000103, - 0x497a5c09, 0x0401f009, 0x4a025a04, 0x00000103, - 0x4a025a06, 0x00000000, 0x497a5c09, 0x800409c0, - 0x02020800, 0x00108531, 0x48065807, 0x480a5c06, - 0x0201f800, 0x00020381, 0x5934000f, 0x5934140b, - 0x80081040, 0x04001002, 0x480a6c0b, 0x80000540, - 0x02020800, 0x00020275, 0x0401f75e, 0x592c020a, - 0x8c000502, 0x040007e9, 0x800409c0, 0x040007e7, - 0x592c0208, 0x8c00050e, 0x040207e4, 0x4933c857, - 0x0201f000, 0x00108fc6, 0x592c020a, 0x8c000500, - 0x04000010, 0x59300015, 0x592c380f, 0x801c3c80, - 0x0400000c, 0x4a025a06, 0x00000015, 0x8c1c3d3e, - 0x04000005, 0x4a025a06, 0x00000007, 0x801c3880, - 0x801c3800, 0x481fc857, 0x821c0d40, 0x00000000, - 0x1c01f000, 0x59300203, 0x82003480, 0x0000000e, - 0x02021800, 0x00100615, 0x0c01f001, 0x001096fb, - 0x00020989, 0x00109d9c, 0x00109daa, 0x000209a5, - 0x001096fb, 0x00109e98, 0x000209c4, 0x001096fb, - 0x001096fb, 0x001096fb, 0x001096fb, 0x001096fb, - 0x001096fb, 0x83380580, 0x00000013, 0x02020000, - 0x00109d23, 0x59300403, 0x82027480, 0x00000044, - 0x02021800, 0x00100615, 0x82000480, 0x00000040, - 0x02001800, 0x00100615, 0x0c01f001, 0x00109d80, - 0x0002099b, 0x00109d82, 0x00109d94, 0x59325808, - 0x832c0500, 0x00ff0000, 0x04000005, 0x592c0c0a, - 0x8c040d1a, 0x02020000, 0x00109d8f, 0x0401fe8e, - 0x0401f710, 0x83380580, 0x00000048, 0x04000007, - 0x83380580, 0x00000053, 0x02000000, 0x00109e3a, - 0x0201f800, 0x00100615, 0x5930001f, 0x59301011, - 0x59300809, 0x58040a00, 0x8c040d0e, 0x02020000, - 0x00109e16, 0x800811c0, 0x02020000, 0x00109e23, - 0x5930001f, 0x80000540, 0x02020000, 0x00109e31, - 0x59325808, 0x592c040a, 0x8c00051e, 0x02000000, - 0x00109e0c, 0x42027000, 0x00000041, 0x0401f001, - 0x83380480, 0x00000054, 0x02021800, 0x00100615, - 0x83380480, 0x00000040, 0x02001000, 0x00109e57, - 0x0c01f001, 0x00109e63, 0x000209e1, 0x00109e6f, - 0x00109e76, 0x00109e63, 0x00109e63, 0x00109e63, - 0x00109e63, 0x00109e65, 0x00109e6a, 0x00109e6a, - 0x00109e63, 0x00109e63, 0x00109e63, 0x00109e63, - 0x00109e6a, 0x00109e63, 0x00109e6a, 0x00109e63, - 0x00109e65, 0x4a026203, 0x00000001, 0x493a6403, - 0x42000800, 0x80002042, 0x0401f66f, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xa36ec441, 0x00000000, - 0x00000000, 0x00000000, 0x00000005, 0xfffffffb, - 0x02800004, 0x00000000, 0x0000c000, 0x0000071b, - 0x073fca5a, 0x0705a5a5, 0x01928009, 0x070ff0e1, - 0x03800006, 0x04958010, 0x05308000, 0x05008000, - 0x0600902f, 0x04a004dc, 0x0202f051, 0x042e4020, - 0x018f021b, 0x033e5000, 0x03020000, 0x078d0018, - 0x0493041a, 0x0092041c, 0x038a0305, 0x078b0303, - 0x048e8010, 0x0678aae5, 0x06000001, 0x07818174, - 0x040010e6, 0x0448e0e6, 0x04818010, 0x002fb008, - 0x0448e0e6, 0x04818010, 0x060ff0e6, 0x00580401, - 0x054880ff, 0x04818010, 0x022a5001, 0x030430d4, - 0x06780043, 0x030e0000, 0x030450ff, 0x06780043, - 0x03019000, 0x048185c4, 0x027c0045, 0x03020000, - 0x06810037, 0x027c0045, 0x03040000, 0x068100c7, - 0x027c0045, 0x03080000, 0x0681061c, 0x04908037, - 0x029105c2, 0x010410a6, 0x0379ff41, 0x037fffff, - 0x072d6000, 0x07601241, 0x050f80ff, 0x032fa009, - 0x05600400, 0x050f80ff, 0x056c04ff, 0x068105da, - 0x073fa009, 0x06000001, 0x0279ff02, 0x0700ffff, - 0x070ff0d1, 0x0179feff, 0x0700ffff, 0x045c0402, - 0x048185da, 0x060ff0d0, 0x0179feff, 0x0700ffff, - 0x057dfeff, 0x0700ffff, 0x068105bc, 0x05600e41, - 0x050f80ff, 0x032fa069, 0x07480000, 0x068105ce, - 0x06780043, 0x070000f0, 0x0781005f, 0x037c00ff, - 0x06000010, 0x0781005f, 0x038005ca, 0x0379ff00, - 0x070fffff, 0x06780043, 0x07f00000, 0x075a0000, - 0x020ef001, 0x038605cc, 0x05484000, 0x02a1819e, - 0x062d6001, 0x002fb001, 0x070ff069, 0x01868072, - 0x060ff079, 0x055c0441, 0x06810010, 0x012fb000, - 0x060560fb, 0x03800078, 0x060ff079, 0x02868198, - 0x070ff069, 0x055c0441, 0x06810010, 0x060560fb, - 0x0400d0d0, 0x062d6002, 0x0648300d, 0x06810086, - 0x070ff0d1, 0x062d6001, 0x045c040b, 0x06810089, - 0x05488000, 0x04818086, 0x072e500c, 0x00208001, - 0x05a004e1, 0x02800010, 0x062d6001, 0x07f00000, - 0x07f00000, 0x070ff0d1, 0x0179feff, 0x070000ff, - 0x055c040c, 0x058180bb, 0x0007b001, 0x03079041, - 0x0307a000, 0x06600a79, 0x050f80ff, 0x053fa80a, - 0x06000010, 0x072d5003, 0x078d0096, 0x0307c003, - 0x0007d004, 0x0107e005, 0x0307f006, 0x02080007, - 0x00081008, 0x01082009, 0x0308300a, 0x0008400b, - 0x0308500c, 0x068d00a1, 0x0678007a, 0x07f00000, - 0x010880ff, 0x03386000, 0x03010000, 0x072e6300, - 0x020ef07f, 0x02860010, 0x070ff07d, 0x0450047c, - 0x050f80ff, 0x002fa819, 0x068d00ae, 0x02080001, - 0x00081002, 0x0448807a, 0x068100b5, 0x0379ff03, - 0x070000ff, 0x01082003, 0x068d00b6, 0x02386004, - 0x03010000, 0x072e6c00, 0x02800010, 0x06780043, - 0x070000f0, 0x068105d5, 0x050020ff, 0x027c0002, - 0x06000010, 0x078100c3, 0x028005d5, 0x0700c0d1, - 0x0379ff0c, 0x070000ff, 0x0380008e, 0x0204a051, - 0x06780043, 0x070000f0, 0x037c00ff, 0x06000010, - 0x0781816a, 0x072d6000, 0x019485be, 0x050fb056, - 0x044880e6, 0x04818010, 0x060ff0d0, 0x0179feff, - 0x0700ffff, 0x057dfeff, 0x0700ffff, 0x068105bc, - 0x05a00212, 0x0349c0e4, 0x0781811d, 0x070ff093, - 0x050010ff, 0x070ff093, 0x045c0401, 0x058180db, - 0x02046092, 0x04002046, 0x04600202, 0x00540401, - 0x048280e6, 0x04500425, 0x070060ff, 0x0730ffff, - 0x0700000f, 0x0742000f, 0x05810190, 0x06a005a4, - 0x0648a002, 0x048180e9, 0x00047089, 0x070ff047, - 0x045c0443, 0x077800ff, 0x07f00000, 0x0781818e, - 0x07780047, 0x0500e000, 0x048185ab, 0x070ff006, - 0x01860117, 0x0179fe47, 0x0700000f, 0x010480ff, - 0x056c7048, 0x06818102, 0x007a0d4a, 0x04003801, - 0x0220f001, 0x0180010f, 0x07608e48, 0x034a60ff, - 0x0700f0ff, 0x074b88ff, 0x037000ff, 0x07000600, - 0x05500448, 0x074d00ff, 0x045a044a, 0x0304a0ff, - 0x070ff00f, 0x01540406, 0x05820117, 0x04950120, - 0x05a001bd, 0x02868123, 0x0134bfff, 0x070fffff, - 0x0104102e, 0x050fd041, 0x00800126, 0x0595011d, - 0x05a001bd, 0x0186011d, 0x0202f00e, 0x052e4030, - 0x040fd02f, 0x070fc0ff, 0x05a00218, 0x02800010, - 0x0400e02f, 0x042e4020, 0x0202f051, 0x0004100e, - 0x0004b00e, 0x050fd041, 0x024a6c46, 0x04500423, - 0x050070ff, 0x03620024, 0x050080ff, 0x04004046, - 0x0700500f, 0x03206000, 0x05601048, 0x0700a0ff, - 0x0700900a, 0x070ff005, 0x04500446, 0x00540425, - 0x04820157, 0x05601622, 0x050f80ff, 0x063fa032, - 0x06000002, 0x03203000, 0x01204000, 0x03205000, - 0x0120b000, 0x0320c000, 0x07601441, 0x050f80ff, - 0x043fa852, 0x06000001, 0x070ff056, 0x056c02ff, - 0x050fb0ff, 0x070560ff, 0x03079041, 0x05600e41, - 0x050f80ff, 0x073fa011, 0x0600003d, 0x06780043, - 0x07f00000, 0x065a007a, 0x010880ff, 0x04a001b6, - 0x058d0150, 0x0208a04a, 0x0108b04b, 0x02386001, - 0x03010000, 0x072e6300, 0x028000a8, 0x0500d00a, - 0x05500405, 0x014a68ff, 0x070090ff, 0x0154040a, - 0x0700c0ff, 0x0600a023, 0x0500b024, 0x02206001, - 0x05601622, 0x050f80ff, 0x063fa04a, 0x06000002, - 0x05601022, 0x050f80ff, 0x043fa819, 0x06000001, - 0x0600a00d, 0x0180013c, 0x06780043, 0x070000f0, - 0x050010ff, 0x027c0001, 0x07000030, 0x078105b2, - 0x027c0001, 0x06000020, 0x078105b2, 0x038005ca, - 0x054880ff, 0x06810010, 0x070ff056, 0x050fb0ff, - 0x044880e5, 0x0581017d, 0x044880e6, 0x04818010, - 0x00800183, 0x056c02ff, 0x050fb0ff, 0x070560ff, - 0x072e5300, 0x044880e6, 0x04818010, 0x072d5003, - 0x06780043, 0x07f00000, 0x010880ff, 0x058d0187, - 0x03386005, 0x03010000, 0x033e6000, 0x0700000c, - 0x052e5200, 0x02800010, 0x0120918e, 0x018004e4, - 0x01209190, 0x018004e4, 0x00209192, 0x018004e4, - 0x03209000, 0x018004e4, 0x01209196, 0x018004e4, - 0x00209198, 0x018004e4, 0x02493075, 0x0681050b, - 0x0120919a, 0x018004e4, 0x06601e01, 0x050f80ff, - 0x063fa029, 0x06000008, 0x02015010, 0x02016051, - 0x00017051, 0x00011051, 0x05601a41, 0x050f80ff, - 0x053fa83a, 0x06000008, 0x05600e41, 0x050f80ff, - 0x01464000, 0x032fa00a, 0x07006011, 0x05007012, - 0x04008013, 0x07009014, 0x0600a015, 0x0400b016, - 0x0700c017, 0x07c00000, 0x072d5003, 0x06601479, - 0x050f80ff, 0x048d01b9, 0x063fa051, 0x0600003e, - 0x07c00000, 0x06005051, 0x0400e02c, 0x0660060e, - 0x050f80ff, 0x032fa009, 0x0379ff00, 0x070000ff, - 0x076c0000, 0x058101dd, 0x0660480e, 0x0500e0ff, - 0x034000ff, 0x01540427, 0x0582020a, 0x03400005, - 0x070ff005, 0x055c0428, 0x0481020e, 0x01680e05, - 0x056c0405, 0x068181bf, 0x040f8029, 0x053fa809, - 0x07000024, 0x06600649, 0x050f80ff, 0x032fa009, - 0x0379ff00, 0x070000ff, 0x076c0000, 0x068181bf, - 0x0400e049, 0x0340002d, 0x050f802b, 0x053fa80a, - 0x06000016, 0x0660480e, 0x0302c0ff, 0x034000ff, - 0x01540427, 0x0582020c, 0x072d6000, 0x0460040e, - 0x050f80ff, 0x0104e0d1, 0x0379ff4e, 0x0700ffff, - 0x062d6002, 0x032fa009, 0x0004d0d0, 0x074b004d, - 0x07780000, 0x07ffff00, 0x055a044d, 0x070000ff, - 0x00201008, 0x04002051, 0x06003051, 0x05304000, - 0x07000060, 0x03205009, 0x07006022, 0x0460040e, - 0x050f80ff, 0x032fa03a, 0x06603c0e, 0x050f80ff, - 0x073fa00a, 0x07000027, 0x050010d1, 0x0460320e, - 0x050f80ff, 0x012fa80a, 0x060ff00e, 0x055c042e, - 0x04810210, 0x07c00000, 0x0400e026, 0x008001cb, - 0x0202c026, 0x008001e6, 0x0500e02e, 0x008001e6, - 0x0400e051, 0x01800209, 0x0349c0e4, 0x04810215, - 0x07c00000, 0x013e4000, 0x070c0000, 0x07c00000, - 0x013e4000, 0x03080000, 0x07c00000, 0x009702f4, - 0x022a5002, 0x0790821d, 0x00910291, 0x030400a6, - 0x0678aae5, 0x06000001, 0x01a1860c, 0x06600c40, - 0x050f80ff, 0x032fa021, 0x074b0000, 0x076c0600, - 0x07818293, 0x05600403, 0x050f80ff, 0x073fa009, - 0x06000002, 0x0279ff04, 0x0700ffff, 0x010440d7, - 0x0179fe44, 0x0700ffff, 0x045c0404, 0x07818295, - 0x0349f044, 0x0681829e, 0x02495001, 0x06818297, - 0x060ff079, 0x045c0440, 0x0781823c, 0x0644f07a, - 0x002fb008, 0x060ff079, 0x045c0440, 0x07818241, - 0x0644f07a, 0x002fb008, 0x0648f001, 0x07818288, - 0x04600e40, 0x050f80ff, 0x06480001, 0x04810257, - 0x0448e001, 0x04810273, 0x02460001, 0x0644f001, - 0x012fa80a, 0x04008040, 0x05a004ee, 0x0286828c, - 0x05a004d8, 0x062da001, 0x013e4000, 0x06000080, - 0x06930013, 0x02920013, 0x02800010, 0x0644f001, - 0x012fa80a, 0x020ef002, 0x00860275, 0x04600840, - 0x050f80ff, 0x053fa809, 0x06000002, 0x05780105, - 0x00800440, 0x017c0105, 0x05000400, 0x06818275, - 0x06601e02, 0x050f80ff, 0x053fa809, 0x06000002, - 0x04602a40, 0x050f80ff, 0x070ff005, 0x053fa809, - 0x06000002, 0x055c0405, 0x06818275, 0x04008040, - 0x0045e008, 0x05a004d8, 0x00800251, 0x0644f001, - 0x012fa80a, 0x050020d8, 0x04600440, 0x050f80ff, - 0x073fa00a, 0x06000001, 0x06480001, 0x07818281, - 0x05308000, 0x03040000, 0x06009040, 0x04a004dc, - 0x00800251, 0x07a0060c, 0x054b0800, 0x056a0700, - 0x06600c40, 0x050f80ff, 0x032fa00a, 0x00800251, - 0x013e4000, 0x06000080, 0x01209288, 0x018004e4, - 0x06009008, 0x05308000, 0x05004000, 0x04a004dc, - 0x00800251, 0x02209002, 0x008002e5, 0x03209000, - 0x008002e5, 0x02209004, 0x008002e5, 0x04a002fd, - 0x062da001, 0x05308000, 0x05002000, 0x06009040, - 0x04a004dc, 0x00800252, 0x013e4000, 0x06000080, - 0x02495001, 0x078182db, 0x04600840, 0x050f80ff, - 0x053fa809, 0x06000001, 0x0721f000, 0x0349f003, - 0x058102aa, 0x0245f01f, 0x06000002, 0x018602db, - 0x07601400, 0x050f80ff, 0x012fa809, 0x06480001, - 0x058102db, 0x06602440, 0x050f80ff, 0x012fa809, - 0x020ef001, 0x038682db, 0x019b02db, 0x050020d8, - 0x062da001, 0x06303002, 0x05000430, 0x04600440, - 0x050f80ff, 0x073fa012, 0x06000001, 0x028f82bf, - 0x050040d8, 0x062da001, 0x07601e00, 0x050f80ff, - 0x073fa009, 0x06000001, 0x060ff004, 0x00540402, - 0x048202d9, 0x06005051, 0x06006051, 0x06602240, - 0x050f80ff, 0x063fa01a, 0x06000002, 0x06600a40, - 0x050f80ff, 0x073fa00a, 0x07000003, 0x060ff040, - 0x045a041f, 0x010eb0ff, 0x06930013, 0x02920013, - 0x02800010, 0x04004002, 0x018002c9, 0x04a002fd, - 0x062da001, 0x05308000, 0x07005000, 0x06009040, - 0x04a004dc, 0x050080d8, 0x05a004e1, 0x062da001, - 0x02800013, 0x050fd009, 0x050fd041, 0x013e4000, - 0x06000080, 0x05308000, 0x03013000, 0x04a004dc, - 0x010440d7, 0x0349f044, 0x048102f2, 0x062da001, - 0x008f02f2, 0x03e00000, 0x062da001, 0x02800013, - 0x0249c0e5, 0x06810013, 0x062da001, 0x07f00000, - 0x07f00000, 0x033e5000, 0x070c0000, 0x018f02f6, - 0x03800011, 0x050020d8, 0x04600440, 0x050f80ff, - 0x073fa00a, 0x06000001, 0x07c00000, 0x002fb001, - 0x03800306, 0x012fb000, 0x03075087, 0x068d0307, - 0x03386000, 0x03020000, 0x04482075, 0x06810352, - 0x0648a0e6, 0x07810347, 0x0642007f, 0x06810345, - 0x0340007e, 0x060ff038, 0x0154047e, 0x02d00334, - 0x0560027d, 0x050f80ff, 0x032fa009, 0x030ef000, - 0x02860504, 0x0107d000, 0x05600800, 0x050f80ff, - 0x032fa009, 0x03681e00, 0x04500420, 0x050f80ff, - 0x073fa009, 0x0700003f, 0x03800311, 0x070ff07d, - 0x0450047c, 0x050f80ff, 0x002fa819, 0x078d0327, - 0x02080001, 0x00081002, 0x0448807a, 0x0781032e, - 0x0379ff03, 0x070000ff, 0x01082003, 0x068d032f, - 0x02386004, 0x03010000, 0x072e6c00, 0x02800352, - 0x0380033a, 0x0380033c, 0x0280033e, 0x02800340, - 0x03800342, 0x03800344, 0x0727c005, 0x02800323, - 0x0627c008, 0x02800323, 0x0627c00b, 0x02800323, - 0x0627c00e, 0x02800323, 0x0727c011, 0x02800323, - 0x03800314, 0x052e6800, 0x02800352, 0x044880e6, - 0x06810531, 0x052e6200, 0x070ff088, 0x0179feff, - 0x070fffff, 0x04818501, 0x060ff083, 0x0086836d, - 0x033e6000, 0x07000003, 0x068d0352, 0x07286000, - 0x07f00000, 0x078d0355, 0x038c0306, 0x0648c0e6, - 0x05818372, 0x0448e0e6, 0x0781036a, 0x004920e6, - 0x07810365, 0x06a0056d, 0x05001088, 0x00700101, - 0x03100000, 0x00088001, 0x033e6000, 0x07000088, - 0x0280055e, 0x02386001, 0x07030000, 0x033e6000, - 0x06000008, 0x028003f1, 0x02799075, 0x0500040f, - 0x06810010, 0x06601479, 0x050080ff, 0x06309052, - 0x0600003e, 0x02800376, 0x06602279, 0x050080ff, - 0x05309812, 0x07000041, 0x0648007a, 0x0781037e, - 0x04488075, 0x0581837e, 0x040f8008, 0x070fa009, - 0x0049107a, 0x01a183f3, 0x00798075, 0x06000507, - 0x0481851c, 0x0448b075, 0x06810385, 0x02493075, - 0x07810509, 0x0249c0e6, 0x048183e0, 0x0648c0e6, - 0x0581839a, 0x068d0389, 0x02386001, 0x07030000, - 0x0049107a, 0x07810390, 0x020ef083, 0x0386039a, - 0x06483075, 0x068103ef, 0x0678007a, 0x07000035, - 0x03a184cf, 0x05308000, 0x07060000, 0x06009079, - 0x04a004dc, 0x028003ef, 0x0448807a, 0x0681039e, - 0x06483075, 0x058104f9, 0x0448d07a, 0x068103a2, - 0x06483075, 0x058104f9, 0x068d03a2, 0x02386001, - 0x07030000, 0x0444e07a, 0x0648307a, 0x048183c7, - 0x0448707a, 0x068103ea, 0x0648f07a, 0x078103b2, - 0x05a004cf, 0x04008079, 0x05a004ee, 0x008683c2, - 0x05a004d8, 0x028003ef, 0x0560107b, 0x050f80ff, - 0x032fa009, 0x0349c000, 0x058183c0, 0x04600e79, - 0x050f80ff, 0x073fa00a, 0x0600003d, 0x06600a79, - 0x050f80ff, 0x053fa80a, 0x06000010, 0x028003ef, - 0x0046e07a, 0x028003ea, 0x06009008, 0x05308000, - 0x05004000, 0x04a004dc, 0x028003ef, 0x0560167b, - 0x050f80ff, 0x032fa011, 0x070ff000, 0x04500401, - 0x030460ff, 0x060ff025, 0x00540446, 0x078203d1, - 0x030460ff, 0x04092046, 0x05a00218, 0x06600679, - 0x050f80ff, 0x00201007, 0x012fa80a, 0x0046047a, - 0x034630ff, 0x050020ff, 0x06003051, 0x04600e79, - 0x050f80ff, 0x073fa012, 0x06000001, 0x028003ef, - 0x033e6a00, 0x0202000e, 0x02079051, 0x07000088, - 0x078d03e4, 0x0744c000, 0x01088000, 0x03386006, - 0x03010000, 0x02800010, 0x05a004cf, 0x05308000, - 0x03020000, 0x06009079, 0x04a004dc, 0x033e6a00, - 0x0302000a, 0x02079051, 0x02800010, 0x04603e79, - 0x050f80ff, 0x032fa009, 0x070ff000, 0x0186040c, - 0x057dfeff, 0x07ffffff, 0x0581040c, 0x050f8000, - 0x012fa811, 0x0079fe02, 0x070000ff, 0x077d66ff, - 0x060000dc, 0x0781840c, 0x060ff001, 0x0286840d, - 0x064b0002, 0x06420002, 0x060ff002, 0x05500400, - 0x050f80ff, 0x05004084, 0x073fa00a, 0x06000002, - 0x07c00000, 0x04600201, 0x050f80ff, 0x073fa009, - 0x06000001, 0x0079fe02, 0x070000ff, 0x077d72ff, - 0x070000dd, 0x0781840c, 0x064b0002, 0x06420002, - 0x06000001, 0x01800406, 0x0605004c, 0x0180041e, - 0x0493041a, 0x04a004d5, 0x054bc450, 0x05810421, - 0x01d00422, 0x01800421, 0x00800432, 0x00800434, - 0x00800432, 0x008004a7, 0x0180043f, 0x00800434, - 0x01800471, 0x00800432, 0x00800432, 0x008004ab, - 0x00800432, 0x018004af, 0x008004c4, 0x01800488, - 0x00800432, 0x00800432, 0x00209432, 0x018004e4, - 0x0379ff50, 0x070fffff, 0x060ff079, 0x055c0450, - 0x048104a4, 0x002fb008, 0x060ff079, 0x055c0450, - 0x058104a3, 0x04a004c7, 0x0180049c, 0x0179fe50, - 0x070fffff, 0x070050ff, 0x060ff079, 0x055c0405, - 0x04810449, 0x002fb008, 0x060ff079, 0x055c0405, - 0x078184a0, 0x070ff087, 0x017980ff, 0x06000507, - 0x06818451, 0x02203040, 0x05002087, 0x0049d002, - 0x0481046b, 0x04930458, 0x01257000, 0x073c3fff, - 0x0700000f, 0x052e4003, 0x072e5030, 0x0304c050, - 0x02400057, 0x06740057, 0x06000002, 0x06820016, - 0x04002083, 0x07003084, 0x04004085, 0x06602279, - 0x050f80ff, 0x063fa01a, 0x06000001, 0x05a004cf, - 0x06a00576, 0x033e6a00, 0x0302000a, 0x062e5020, - 0x003e4002, 0x07000a00, 0x028003f1, 0x07420003, - 0x0781844e, 0x00798002, 0x06000507, 0x06818451, - 0x0180045c, 0x05930478, 0x01257000, 0x073c3fff, - 0x0700000f, 0x052e4003, 0x072e5030, 0x0304c050, - 0x067800e6, 0x07000041, 0x0581047d, 0x06a0057f, - 0x04818016, 0x002fb008, 0x067800e6, 0x07000041, - 0x04810483, 0x06a0057f, 0x04818016, 0x062e5020, - 0x003e4002, 0x07000a00, 0x03e00000, 0x02800010, - 0x0379ff50, 0x070fffff, 0x060ff079, 0x055c0450, - 0x0781848e, 0x0245507a, 0x002fb008, 0x060ff079, - 0x055c0450, 0x07818493, 0x0245507a, 0x002fb008, - 0x05600e50, 0x050f80ff, 0x012fa809, 0x02455001, - 0x05600e50, 0x050f80ff, 0x012fa80a, 0x0080049d, - 0x002fb008, 0x003e4002, 0x07000a00, 0x02800016, - 0x079384a3, 0x062e5020, 0x042e4002, 0x002fb008, - 0x013e4000, 0x05000e00, 0x02800016, 0x0179fe50, - 0x070fffff, 0x010210ff, 0x02800016, 0x0179fe50, - 0x070fffff, 0x050340ff, 0x0080049d, 0x0179fe50, - 0x070fffff, 0x0102e0ff, 0x0760282e, 0x050f80ff, - 0x05222000, 0x07223000, 0x05224000, 0x07225000, - 0x07226000, 0x05227000, 0x05228000, 0x07229000, - 0x0722a000, 0x0522b000, 0x063fa051, 0x07000011, - 0x0202c026, 0x0522d000, 0x052e400c, 0x02800016, - 0x030430d4, 0x062e5008, 0x00800176, 0x05600e50, - 0x050f80ff, 0x032fa009, 0x03460000, 0x018004d2, - 0x0246007a, 0x0045207a, 0x008004d0, 0x0246007a, - 0x0600007a, 0x04600e79, 0x050f80ff, 0x032fa00a, - 0x07c00000, 0x029284d5, 0x070500e1, 0x07c00000, - 0x0245f008, 0x048404d9, 0x020e0008, 0x07c00000, - 0x070ff009, 0x065a0008, 0x058404de, 0x020e0008, - 0x07c00000, 0x058404e1, 0x020e0008, 0x07c00000, - 0x05308000, 0x0500d000, 0x04a004dc, 0x04a004e9, - 0x02800010, 0x052e4300, 0x072e500c, 0x073c3fff, - 0x0700000f, 0x07c00000, 0x06602208, 0x050f80ff, - 0x032fa011, 0x076a0000, 0x068184f7, 0x066a0001, - 0x048104f7, 0x04002051, 0x07c00000, 0x00202001, - 0x07c00000, 0x0648307a, 0x01a18606, 0x05a004cc, - 0x05308000, 0x05001000, 0x06009079, 0x04a004dc, - 0x0280055e, 0x0249c0e6, 0x058104f9, 0x0280036d, - 0x0648307a, 0x07818196, 0x05a004cf, 0x02209504, - 0x018004e4, 0x02490075, 0x06810519, 0x04002089, - 0x04780102, 0x07f00000, 0x05001088, 0x06a0056d, - 0x04740101, 0x03100000, 0x060ff002, 0x045c0401, - 0x0481851a, 0x00088001, 0x033e6000, 0x070000c0, - 0x0380055a, 0x07f00000, 0x0220951a, 0x018004e4, - 0x040fd075, 0x040fd07a, 0x040fd079, 0x0648307a, - 0x06810525, 0x06780075, 0x06000007, 0x0481852c, - 0x07a00606, 0x06486075, 0x06818194, 0x02490075, - 0x0781819a, 0x04487075, 0x04818534, 0x0280053b, - 0x05308000, 0x03010000, 0x06009079, 0x04a004dc, - 0x02800010, 0x0448e0e6, 0x04818352, 0x00800192, - 0x05308000, 0x0500e000, 0x06009079, 0x04a004dc, - 0x04008089, 0x05a004e1, 0x0380055a, 0x05a004cc, - 0x05308000, 0x0700f000, 0x06009079, 0x07000088, - 0x06a00543, 0x04a004dc, 0x02800010, 0x03386000, - 0x07030000, 0x07f00000, 0x068d0546, 0x033e6a00, - 0x0202000e, 0x02079051, 0x0448b075, 0x06810551, - 0x02493075, 0x06810551, 0x05301005, 0x03010000, - 0x03800553, 0x05301006, 0x03010000, 0x05002087, - 0x06485002, 0x05818553, 0x0744c000, 0x01088000, - 0x02086001, 0x07c00000, 0x05001088, 0x06a0056d, - 0x0644c001, 0x00088001, 0x033e6a00, 0x0202000e, - 0x004920e6, 0x05818563, 0x02079051, 0x078d0563, - 0x060ff089, 0x034990ff, 0x0781056a, 0x03386005, - 0x03010000, 0x02800010, 0x03386006, 0x03010000, - 0x02800010, 0x068d056d, 0x03386000, 0x07030000, - 0x07f00000, 0x078d0571, 0x070ff087, 0x074850ff, - 0x05818572, 0x07c00000, 0x068d0576, 0x02386001, - 0x07030000, 0x07f00000, 0x068d057a, 0x070ff087, - 0x074850ff, 0x0581857b, 0x07c00000, 0x05002087, - 0x0049d002, 0x0581858e, 0x002fb008, 0x067800e6, - 0x07000041, 0x002fb008, 0x0581858e, 0x06a005a4, - 0x0448e002, 0x06810591, 0x0648a002, 0x0481859b, - 0x06486002, 0x07810595, 0x02400057, 0x056a02ff, - 0x07c00000, 0x06a005a4, 0x06788102, 0x06000004, - 0x0581858e, 0x04002089, 0x070ff0d4, 0x045c0402, - 0x077800ff, 0x07f00000, 0x0581858e, 0x00202010, - 0x038c058e, 0x07f00000, 0x06420002, 0x0581859c, - 0x06a00576, 0x033e6a00, 0x0302000a, 0x07c00000, - 0x07f00000, 0x060ff0a2, 0x050020ff, 0x060ff0a2, - 0x045c0402, 0x058185a5, 0x07c00000, 0x05a00218, - 0x03495047, 0x068105b0, 0x0320901d, 0x02800602, - 0x0220901f, 0x02800602, 0x014980e4, 0x04818010, - 0x013e4000, 0x07003000, 0x05600e35, 0x050f80ff, - 0x07a006fa, 0x01208003, 0x05a004e1, 0x038005ca, - 0x03209009, 0x02800602, 0x03209011, 0x02800602, - 0x02209007, 0x02800602, 0x03209003, 0x02800602, - 0x00498043, 0x048185bc, 0x00497043, 0x058185c0, - 0x02209001, 0x02800602, 0x0220900d, 0x02800602, - 0x0320900f, 0x02800602, 0x03493000, 0x068105d3, - 0x027c0045, 0x070a0000, 0x068105dc, 0x0220900b, - 0x02800602, 0x02209013, 0x05308000, 0x01012000, - 0x04a004dc, 0x00800183, 0x03209005, 0x02800602, - 0x072e500c, 0x00208002, 0x05a004e1, 0x02800010, - 0x02209015, 0x02800602, 0x072d6000, 0x05308000, - 0x05007000, 0x07f00000, 0x070090d1, 0x0379ff09, - 0x0700ffff, 0x04a004dc, 0x03209017, 0x02800602, - 0x033e5000, 0x06000080, 0x02209019, 0x02800602, - 0x072d6000, 0x033e5000, 0x06000080, 0x07f00000, - 0x060ff0d0, 0x0179feff, 0x0700ffff, 0x057dfeff, - 0x0700ffff, 0x04818010, 0x02400058, 0x00642058, - 0x06820010, 0x033e5000, 0x06000080, 0x04058051, - 0x0320901b, 0x02800602, 0x05308000, 0x01012000, - 0x04a004dc, 0x00800176, 0x05a00218, 0x05308000, - 0x05008000, 0x06009079, 0x04a004dc, 0x07c00000, - 0x034900e4, 0x04818616, 0x013e4000, 0x070000c0, - 0x07f00000, 0x034900e4, 0x05818614, 0x07c00000, - 0x013e4000, 0x06000080, 0x07f00000, 0x07f00000, - 0x07f00000, 0x034900e4, 0x0681060e, 0x02800616, - 0x072d6000, 0x00498043, 0x07810630, 0x060ff0d0, - 0x0179feff, 0x0700ffff, 0x057dfeff, 0x0700ffff, - 0x048185e0, 0x050f8030, 0x032fa009, 0x0379ff00, - 0x0700ffff, 0x070ff0d1, 0x0179feff, 0x0700ffff, - 0x055c0400, 0x068105e0, 0x04004051, 0x03800678, - 0x06a006da, 0x062d6001, 0x020ef004, 0x038605e2, - 0x06600004, 0x050f80ff, 0x032fa009, 0x074b0000, - 0x05002000, 0x0769ff00, 0x01640800, 0x078205e2, - 0x01640e00, 0x058285e2, 0x070ff036, 0x045c0404, - 0x0581864b, 0x072d6000, 0x050f8030, 0x032fa009, - 0x0379ff00, 0x0700ffff, 0x070ff0d1, 0x0179feff, - 0x0700ffff, 0x055c0400, 0x068105e0, 0x04482034, - 0x068105fd, 0x06483034, 0x048185fd, 0x070ff0d4, - 0x077800ff, 0x070000f0, 0x037c00ff, 0x06000010, - 0x07810678, 0x07a006d4, 0x024900e5, 0x0681065b, - 0x033e5000, 0x06000080, 0x02800010, 0x04601c04, - 0x050f80ff, 0x053fa809, 0x06000020, 0x030ef041, - 0x028605ec, 0x062d6002, 0x05602a41, 0x050f80ff, - 0x012fa809, 0x060ff0d0, 0x074b00ff, 0x045c0401, - 0x04818676, 0x062d6001, 0x07602841, 0x050f80ff, - 0x053fa809, 0x06000001, 0x070ff0d1, 0x054b80ff, - 0x074b0003, 0x055c0403, 0x04818676, 0x033e5000, - 0x06000080, 0x0180070c, 0x07600041, 0x0380065c, - 0x07a006d4, 0x024900e5, 0x0781067e, 0x033e5000, - 0x06000080, 0x02800010, 0x07a006c0, 0x030ef041, - 0x038605f0, 0x04058051, 0x072d6000, 0x05601041, - 0x050f80ff, 0x012fa809, 0x0600a0d0, 0x0500b0d1, - 0x062d6001, 0x07f00000, 0x07f00000, 0x0600c0d0, - 0x0500d0d1, 0x062d6002, 0x0279ff0d, 0x07ff0000, - 0x044d800d, 0x060ff0d0, 0x074b00ff, 0x065a000d, - 0x06601201, 0x050f80ff, 0x073fa022, 0x07000005, - 0x0079fe0d, 0x070000ff, 0x050020ff, 0x05602a41, - 0x050f80ff, 0x073fa00a, 0x06000001, 0x020ef004, - 0x038606bd, 0x04601c04, 0x050f80ff, 0x053fa809, - 0x06000001, 0x050f80ff, 0x053fa80a, 0x06000020, - 0x07602841, 0x050f80ff, 0x073fa009, 0x06000001, - 0x0279ff02, 0x070000ff, 0x0678000d, 0x0700ff00, - 0x065a0002, 0x07602841, 0x050f80ff, 0x073fa00a, - 0x06000001, 0x07600041, 0x050f80ff, 0x053fa80a, - 0x06000001, 0x07601241, 0x050f80ff, 0x073fa00a, - 0x06000002, 0x033e5000, 0x06000080, 0x0180070c, - 0x040f8032, 0x073fa011, 0x06000001, 0x060ff002, - 0x055c0403, 0x048186c8, 0x00041051, 0x07c00000, - 0x04600402, 0x04500432, 0x050f80ff, 0x053fa809, - 0x06000020, 0x00400402, 0x01680eff, 0x070030ff, - 0x040f8032, 0x053fa80a, 0x06000001, 0x07c00000, - 0x024900e5, 0x078106d7, 0x07c00000, 0x033e5000, - 0x070000c0, 0x07c00000, 0x05004036, 0x060000d0, - 0x0179fe00, 0x0700ffff, 0x057dfeff, 0x0700ffff, - 0x078106f9, 0x070000d1, 0x0379ff00, 0x0700ffff, - 0x06005051, 0x060ff031, 0x05500405, 0x050f80ff, - 0x073fa009, 0x06000002, 0x020ef004, 0x038606f3, - 0x04600404, 0x050f80ff, 0x012fa809, 0x0079fe01, - 0x0700ffff, 0x055c0400, 0x078106f9, 0x01400405, - 0x070050ff, 0x057de0ff, 0x06000007, 0x048186e5, - 0x04004051, 0x07c00000, 0x072d6000, 0x07f00000, - 0x07f00000, 0x000110d0, 0x010120d1, 0x062d6001, - 0x07f00000, 0x07f00000, 0x020130d0, 0x010140d1, - 0x062d6002, 0x010170d4, 0x07f00000, 0x020150d0, - 0x030160d1, 0x053fa83a, 0x06000008, 0x07c00000, - 0x07600c41, 0x050f80ff, 0x073fa009, 0x06000001, - 0x04780102, 0x07ffff00, 0x046a0702, 0x050f80ff, - 0x073fa00a, 0x06000001, 0x05600e41, 0x050f80ff, - 0x032fa069, 0x03800053, 0xdb4ee9e2, 0x02800004, - 0x00000000, 0x00008000, 0x00000542, 0x040f801f, - 0x012fa8c9, 0x040f801f, 0x073fa081, 0x06000010, - 0x03200005, 0x07420000, 0x050fb000, 0x040f801f, - 0x073fa011, 0x06000038, 0x040f801f, 0x053fa859, - 0x0700003a, 0x050fe000, 0x0581800a, 0x0784003c, - 0x04958019, 0x030e0011, 0x072e4200, 0x03800014, - 0x0291001f, 0x050010c0, 0x04482001, 0x058180fa, - 0x06483001, 0x0681815d, 0x02920029, 0x068b0029, - 0x008a0162, 0x050010c0, 0x06780001, 0x050007c0, - 0x06818240, 0x06780001, 0x0500f800, 0x06818280, - 0x03910030, 0x040fe029, 0x03860030, 0x076c001d, - 0x058102b1, 0x076c0a1d, 0x048102da, 0x029200ab, - 0x040fe02f, 0x0386003c, 0x06000013, 0x050fb000, - 0x066c0073, 0x068103ec, 0x014920e4, 0x0581803c, - 0x03400000, 0x076c0a00, 0x04818034, 0x0696003e, - 0x03b900ca, 0x05908014, 0x010170e1, 0x07780017, - 0x03e00000, 0x06810091, 0x050010ff, 0x0179fe17, - 0x031fffff, 0x070000ff, 0x05600800, 0x050f80ff, - 0x073fa009, 0x06000001, 0x06780002, 0x02800040, - 0x037c00ff, 0x03800000, 0x0681005d, 0x0249f002, - 0x078100aa, 0x0448e002, 0x0681005d, 0x07600c00, - 0x050f80ff, 0x073fa009, 0x06000001, 0x06780002, - 0x07ffff00, 0x037c00ff, 0x05000200, 0x058180aa, - 0x064bd401, 0x03d0005f, 0x028000a8, 0x02800067, - 0x03800071, 0x0380007b, 0x02800085, 0x0280008f, - 0x028000a8, 0x028000a8, 0x050fe027, 0x0086806b, - 0x01028000, 0x0280006e, 0x07600027, 0x050f80ff, - 0x032fa00a, 0x01027000, 0x02400029, 0x038000aa, - 0x040fe025, 0x00868075, 0x03026000, 0x03800078, - 0x06600025, 0x050f80ff, 0x032fa00a, 0x03025000, - 0x02400029, 0x038000aa, 0x050fe021, 0x0086807f, - 0x01022000, 0x03800082, 0x07600021, 0x050f80ff, - 0x032fa00a, 0x01021000, 0x02400029, 0x038000aa, - 0x040fe023, 0x00868089, 0x01024000, 0x0280008c, - 0x06600023, 0x050f80ff, 0x032fa00a, 0x03023000, - 0x02400029, 0x038000aa, 0x06a000da, 0x038000aa, - 0x01640817, 0x048280a8, 0x070ff017, 0x03d00095, - 0x0280009d, 0x0380009f, 0x028000a2, 0x038000a5, - 0x028000a8, 0x028000a8, 0x028000a8, 0x028000a8, - 0x03e00000, 0x03800014, 0x0590809f, 0x030160e1, - 0x038000aa, 0x049080a2, 0x030150e1, 0x038000aa, - 0x059080a5, 0x010140e1, 0x038000aa, 0x060fc013, - 0x07a0053a, 0x03800014, 0x014940e4, 0x00a180ae, - 0x0380003c, 0x02681e0d, 0x050fb0ff, 0x04600876, - 0x050f80ff, 0x053fa809, 0x06000001, 0x05488003, - 0x058180bd, 0x0400800d, 0x0120d000, 0x013e4000, - 0x05000200, 0x06009076, 0x04002075, 0x06a00526, - 0x07c00000, 0x072e4800, 0x07000012, 0x028000cd, - 0x0747f000, 0x05600800, 0x050f80ff, 0x012fa809, - 0x0249f001, 0x068100cd, 0x01012000, 0x052e4c00, - 0x07c00000, 0x070000eb, 0x0349f000, 0x048180c1, - 0x05600800, 0x050f80ff, 0x012fa809, 0x0448e001, - 0x068100d3, 0x07c00000, 0x0079c101, 0x07ffffff, - 0x027a4b01, 0x03800000, 0x05600800, 0x050f80ff, - 0x012fa80a, 0x07600c00, 0x050f80ff, 0x012fa821, - 0x06780001, 0x07ffff00, 0x037c00ff, 0x05000700, - 0x068100ef, 0x06601804, 0x070030ff, 0x050f80ff, - 0x012fa809, 0x05002000, 0x050f8003, 0x073fa00a, - 0x06000001, 0x040fe001, 0x038600f0, 0x04600201, - 0x050f80ff, 0x032fa00a, 0x07c00000, 0x050fe02e, - 0x018680f5, 0x0102e000, 0x0302f000, 0x038000f9, - 0x0760002e, 0x050f80ff, 0x032fa00a, 0x0102e000, - 0x07c00000, 0x022c0004, 0x056c041d, 0x0481010e, - 0x056c021d, 0x04810125, 0x056c081d, 0x04810137, - 0x076c061d, 0x04810151, 0x0521d000, 0x0202c013, - 0x0202a013, 0x02020013, 0x0460021a, 0x050f80ff, - 0x053fa80a, 0x07000009, 0x03b600be, 0x0484801f, - 0x0380003c, 0x040fe02a, 0x00860104, 0x06000013, - 0x04001013, 0x0560102b, 0x050f80ff, 0x032fa012, - 0x06420029, 0x0660002a, 0x050f80ff, 0x053fa809, - 0x06000001, 0x050fe003, 0x01860122, 0x01028003, - 0x0660002a, 0x050f80ff, 0x053fa80a, 0x07000009, - 0x00800152, 0x00028013, 0x00027013, 0x00800152, - 0x040fe02a, 0x01860103, 0x06420029, 0x0660002a, - 0x050f80ff, 0x053fa809, 0x06000001, 0x050fe003, - 0x00860134, 0x03026003, 0x0660002a, 0x050f80ff, - 0x053fa80a, 0x07000009, 0x00800152, 0x02026013, - 0x02025013, 0x00800152, 0x040fe02a, 0x01860103, - 0x06420029, 0x0660002a, 0x050f80ff, 0x053fa809, - 0x06000001, 0x050fe003, 0x00860146, 0x01022003, - 0x0660002a, 0x050f80ff, 0x053fa80a, 0x07000009, - 0x01800148, 0x00022013, 0x00021013, 0x0647f020, - 0x007a0120, 0x04000101, 0x04a002a2, 0x0400802a, - 0x06a0051f, 0x03948103, 0x0521d005, 0x00800104, - 0x0180010c, 0x0647f020, 0x06486020, 0x06818157, - 0x04a002a2, 0x01800103, 0x007a0120, 0x04000101, - 0x04a002a2, 0x0400802a, 0x06a0051f, 0x01800103, - 0x040fd02a, 0x052e4003, 0x00208010, 0x06a0051f, - 0x0180010c, 0x00018098, 0x07480018, 0x06818173, - 0x05481018, 0x07818171, 0x05482018, 0x0781816f, - 0x07483018, 0x0681816d, 0x002fb004, 0x01800174, - 0x012fb003, 0x01800174, 0x002fb002, 0x01800174, - 0x002fb001, 0x01800174, 0x012fb000, 0x0179fe78, - 0x070000ff, 0x030190ff, 0x00017086, 0x058b0178, - 0x03385000, 0x03020000, 0x07780017, 0x00430407, - 0x07818200, 0x046c0419, 0x058101b4, 0x046c0219, - 0x05810184, 0x07219000, 0x00800198, 0x07219000, - 0x07483017, 0x0481019e, 0x05482017, 0x058101a5, - 0x0448b075, 0x06818198, 0x06601476, 0x050f80ff, - 0x073fa022, 0x0600003e, 0x06000080, 0x05001081, - 0x05002082, 0x06003083, 0x05004084, 0x04601c76, - 0x050f80ff, 0x022fa02a, 0x07219000, 0x07780078, - 0x07ffff00, 0x045a0419, 0x010780ff, 0x0484801f, - 0x0380003c, 0x040fe07f, 0x008601ad, 0x04a001cd, - 0x00920198, 0x040fe07f, 0x06a681cd, 0x00800198, - 0x0560107b, 0x050f80ff, 0x032fa009, 0x0744f000, - 0x0560107b, 0x050f80ff, 0x032fa00a, 0x0180018b, - 0x052e400c, 0x040080fb, 0x046aa108, 0x06009076, - 0x04002075, 0x06a00526, 0x00800198, 0x06219001, - 0x05482017, 0x048101c1, 0x058b01b7, 0x060ff086, - 0x0349f0ff, 0x07818177, 0x07483017, 0x058101be, - 0x050fd0ff, 0x040fe07f, 0x06a681cd, 0x00800198, - 0x05004084, 0x05a00222, 0x00920198, 0x070ff07d, - 0x0450047c, 0x056004ff, 0x050f80ff, 0x032fa009, - 0x070ff000, 0x00540479, 0x030790ff, 0x018001a5, - 0x060ff079, 0x0054047a, 0x058201f9, 0x058101f9, - 0x070ff07d, 0x0450047c, 0x050f80ff, 0x002fa819, - 0x048b01d5, 0x02080001, 0x00081002, 0x01082003, - 0x048b01d9, 0x03385000, 0x03010000, 0x02400019, - 0x070ff003, 0x04500479, 0x030790ff, 0x0340007e, - 0x0642007f, 0x058101f9, 0x070ff07e, 0x050f80ff, - 0x032fa009, 0x050fe000, 0x028681f8, 0x070ff07d, - 0x056002ff, 0x050f80ff, 0x032fa009, 0x0107d000, - 0x018601fa, 0x0560087d, 0x050f80ff, 0x032fa009, - 0x03681e00, 0x0550041b, 0x050f80ff, 0x032fa009, - 0x0107e000, 0x070ff07e, 0x018001e4, 0x0307c000, - 0x07c00000, 0x052e400c, 0x040080fb, 0x046aa108, - 0x06009076, 0x04002075, 0x02800526, 0x040fd076, - 0x050fd017, 0x060ff086, 0x077800ff, 0x07000060, - 0x037c00ff, 0x07000060, 0x06818202, 0x07780078, - 0x07ffff00, 0x045a0419, 0x010780ff, 0x06601476, - 0x050f80ff, 0x073fa022, 0x0600003e, 0x052e400c, - 0x04600876, 0x050f80ff, 0x053fa809, 0x06000001, - 0x05488003, 0x0481021c, 0x0400d0fb, 0x066a810d, - 0x013e4000, 0x07000300, 0x02800029, 0x040080fb, - 0x066a8108, 0x06009076, 0x04002075, 0x06a00526, - 0x02800029, 0x0240007f, 0x0742007e, 0x050f807e, - 0x032fa009, 0x050fe000, 0x0386823c, 0x070ff07d, - 0x055c047b, 0x04810231, 0x0760007d, 0x050f80ff, - 0x032fa009, 0x050fe000, 0x02868231, 0x070ff07b, - 0x0107d0ff, 0x0560087d, 0x050f80ff, 0x032fa009, - 0x03681e00, 0x0450041c, 0x0107e0ff, 0x050f80ff, - 0x032fa009, 0x050fe000, 0x0086023e, 0x0307c000, - 0x07c00000, 0x040fd076, 0x0380053a, 0x010180c0, - 0x0548e018, 0x07818259, 0x0748f018, 0x07818255, - 0x03490018, 0x06818251, 0x01491018, 0x0781824d, - 0x073c0000, 0x06000040, 0x02200004, 0x0180025c, - 0x073c0000, 0x06000020, 0x03200003, 0x0180025c, - 0x073c0000, 0x06000010, 0x02200002, 0x0180025c, - 0x073c0000, 0x06000008, 0x02200001, 0x0180025c, - 0x073c0000, 0x06000004, 0x06000013, 0x050fb000, - 0x040fe076, 0x00860275, 0x046c0273, 0x04810285, - 0x066c0073, 0x05810266, 0x040fd076, 0x07a0053a, - 0x03800014, 0x040fd076, 0x01800269, 0x00452075, - 0x00077013, 0x0647f075, 0x06486075, 0x0781826f, - 0x04a002a8, 0x00800275, 0x007a0175, 0x04000101, - 0x04a002a8, 0x04008076, 0x0245f008, 0x06a0051f, - 0x07273000, 0x05600272, 0x050f80ff, 0x053fa80a, - 0x07000009, 0x0379ff78, 0x070000ff, 0x02076013, - 0x02075013, 0x0484801f, 0x0380003c, 0x070fc0ff, - 0x052e400c, 0x00208020, 0x06a0051f, 0x0180027e, - 0x04600276, 0x050010ff, 0x040f8001, 0x032fa009, - 0x040f8001, 0x053fa80a, 0x07000009, 0x070ff000, - 0x02868297, 0x06601276, 0x050f80ff, 0x073fa009, - 0x0700000c, 0x07601818, 0x050f80ff, 0x053fa80a, - 0x07000009, 0x00800298, 0x07a000f0, 0x0448b075, - 0x04810268, 0x06000013, 0x04001013, 0x0560107b, - 0x050f80ff, 0x032fa012, 0x0046b075, 0x03b600be, - 0x01800269, 0x06000020, 0x04001016, 0x0460082a, - 0x050f80ff, 0x032fa012, 0x07c00000, 0x06000075, - 0x040010a2, 0x044b0801, 0x060ff016, 0x065a0001, - 0x04600876, 0x050f80ff, 0x032fa012, 0x07c00000, - 0x050fe022, 0x008602bc, 0x0421d004, 0x0302a022, - 0x04a002e9, 0x04488020, 0x048102ce, 0x040fd02a, - 0x0521d000, 0x0202a013, 0x02020013, 0x040fe026, - 0x018602d4, 0x0421d001, 0x0202a026, 0x04a002e9, - 0x0202c013, 0x00683e20, 0x070060ff, 0x056c0206, - 0x0681031c, 0x056c0406, 0x06810332, 0x076c0606, - 0x078103a3, 0x04488020, 0x068182d0, 0x056c1606, - 0x078103b1, 0x06a00516, 0x018002e2, 0x040fd02a, - 0x0521d000, 0x0202a013, 0x02020013, 0x050fe028, - 0x018602e2, 0x0302a028, 0x0421d002, 0x04a002e9, - 0x018002f0, 0x050fe022, 0x018602e2, 0x0421d004, - 0x0302a022, 0x04a002e9, 0x04488020, 0x078182e4, - 0x06a00516, 0x05848030, 0x0380003c, 0x040fd02a, - 0x0521d000, 0x0202a013, 0x02020013, 0x018002e2, - 0x0460082a, 0x050f80ff, 0x022fa031, 0x03020000, - 0x0002b004, 0x01018005, 0x07c00000, 0x0400702a, - 0x07a003e4, 0x007a0101, 0x07060000, 0x07303000, - 0x07008290, 0x07600018, 0x050f80ff, 0x053fa809, - 0x07000003, 0x0448e007, 0x068182fe, 0x06006013, - 0x03800305, 0x02400010, 0x048102fe, 0x06006010, - 0x0460322a, 0x050f80ff, 0x073fa00a, 0x07000003, - 0x050f801e, 0x032fa03a, 0x063aa020, 0x06000002, - 0x013e4000, 0x07000030, 0x0298030b, 0x070ff0f6, - 0x036830ff, 0x0581830c, 0x070f001e, 0x0560102b, - 0x050f10ff, 0x063f3c08, 0x0600000d, 0x013e4000, - 0x06000020, 0x040f801a, 0x0320000a, 0x022017d0, - 0x032fa012, 0x0202c013, 0x018002e2, 0x04007013, - 0x07a003e4, 0x007a0101, 0x07050000, 0x07303000, - 0x07008890, 0x074d0005, 0x06006013, 0x050f801e, - 0x032fa03a, 0x05601a2b, 0x050f80ff, 0x022fa019, - 0x04001002, 0x04002013, 0x040f801f, 0x022fa01a, - 0x073aa00c, 0x06000002, 0x07300c03, 0x0600000d, - 0x038003d1, 0x04007013, 0x07a003e4, 0x007a0101, - 0x03070000, 0x0660282a, 0x050f80ff, 0x073fa009, - 0x06000004, 0x02499008, 0x0781033f, 0x07303000, - 0x07008890, 0x03800341, 0x07303000, 0x04008980, - 0x05007003, 0x074d0005, 0x06006013, 0x050f801e, - 0x032fa03a, 0x0760142b, 0x050f80ff, 0x032fa021, - 0x064b0002, 0x02499008, 0x0781034d, 0x0644c002, - 0x054b0400, 0x050040ff, 0x06698104, 0x04818362, - 0x06000013, 0x04001013, 0x04780102, 0x06000010, - 0x06003013, 0x04004013, 0x06005013, 0x06006013, - 0x04007013, 0x00644015, 0x0682035e, 0x04448002, - 0x02205008, 0x040f801f, 0x032fa042, 0x04008015, - 0x0280039b, 0x046c8004, 0x04818370, 0x01208018, - 0x06780002, 0x07000003, 0x04818373, 0x06003001, - 0x06000013, 0x04001013, 0x04004013, 0x06005013, - 0x040f801f, 0x022fa032, 0x0280039b, 0x040fd02a, - 0x07a0053a, 0x03800014, 0x0379ff03, 0x070000ff, - 0x04488002, 0x0681037a, 0x070ff003, 0x04500408, - 0x050080ff, 0x0379ff00, 0x070000ff, 0x06489002, - 0x07810381, 0x070ff000, 0x04500408, 0x050080ff, - 0x07005003, 0x05004000, 0x06003001, 0x06000013, - 0x04001013, 0x040f801f, 0x022fa032, 0x05601c2b, - 0x050f80ff, 0x022fa031, 0x06600c1f, 0x050f80ff, - 0x022fa032, 0x02680608, 0x0681039b, 0x016408ff, - 0x057dfeff, 0x07ffffff, 0x034000ff, 0x045a0407, - 0x070000ff, 0x0760061e, 0x050f80ff, 0x032fa00a, - 0x06600908, 0x0669f908, 0x027a0008, 0x06000020, - 0x070aa0ff, 0x014a20ff, 0x037a00ff, 0x060000dc, - 0x070000ff, 0x038003d1, 0x04007013, 0x07a003e4, - 0x007a0101, 0x07030000, 0x07303000, 0x07008190, - 0x06006013, 0x050f801e, 0x032fa03a, 0x073aa000, - 0x06000002, 0x07300c00, 0x07000005, 0x038003d1, - 0x04007013, 0x07a003e4, 0x007a0101, 0x07810000, - 0x07303000, 0x07000090, 0x06006013, 0x06600c2a, - 0x050f80ff, 0x053fa809, 0x07000003, 0x04780107, - 0x07ffff00, 0x007c0107, 0x07000500, 0x048183c4, - 0x07303000, 0x05000890, 0x074d0005, 0x0660282a, - 0x050f80ff, 0x053fa809, 0x07000003, 0x0049d007, - 0x068103cb, 0x02206001, 0x050f801e, 0x032fa03a, - 0x073aa000, 0x06000002, 0x07300c00, 0x07000005, - 0x013e4000, 0x07000030, 0x029803d3, 0x070ff0f6, - 0x036830ff, 0x058183d4, 0x070f001e, 0x040f101f, - 0x070f3000, 0x013e4000, 0x06000020, 0x040f801a, - 0x0320000a, 0x022017d0, 0x032fa012, 0x018002e2, - 0x03200000, 0x06006076, 0x028003e6, 0x03200011, - 0x0600602a, 0x04a0046b, 0x05600406, 0x050f80ff, - 0x053fa809, 0x06000002, 0x07c00000, 0x0207602f, - 0x04600876, 0x050f80ff, 0x022fa031, 0x03075000, - 0x0007b004, 0x01018005, 0x06600076, 0x050020ff, - 0x050f80ff, 0x012fa809, 0x0202f001, 0x018683fa, - 0x0002e013, 0x040f8002, 0x053fa80a, 0x07000009, - 0x06273001, 0x0448b075, 0x06818404, 0x04602076, - 0x050f80ff, 0x053fa811, 0x0700003c, 0x0179fe78, - 0x070000ff, 0x030190ff, 0x0386840c, 0x04a00420, - 0x00078019, 0x0092041f, 0x00800464, 0x040fd076, - 0x040fd019, 0x04600276, 0x050020ff, 0x050f80ff, - 0x032fa009, 0x040f8002, 0x053fa80a, 0x07000009, - 0x050fe000, 0x0286841c, 0x07601818, 0x050f80ff, - 0x053fa80a, 0x07000009, 0x0180041d, 0x07a000f0, - 0x07273000, 0x02076013, 0x0380003c, 0x048b0420, - 0x03385000, 0x07030000, 0x05600818, 0x050f80ff, - 0x032fa009, 0x054b0400, 0x0308a0ff, 0x0179fe00, - 0x070000ff, 0x010880ff, 0x0448b075, 0x0581043a, - 0x0760147b, 0x050f80ff, 0x002fa819, 0x064b0001, - 0x02080002, 0x01081003, 0x00082001, 0x02083001, - 0x02079001, 0x0207a001, 0x00084013, 0x0207f013, - 0x0180045c, 0x06485075, 0x04810452, 0x02465075, - 0x06601476, 0x050f80ff, 0x073fa021, 0x0600003e, - 0x070ff07d, 0x0450047c, 0x050f80ff, 0x002fa819, - 0x048b0445, 0x02080001, 0x00081002, 0x01082003, - 0x03079003, 0x0208307a, 0x0340007e, 0x0642007f, - 0x04810457, 0x070ff07e, 0x05a001e4, 0x02928457, - 0x01800463, 0x048b0452, 0x06601476, 0x050f80ff, - 0x073fa041, 0x0600003e, 0x06602476, 0x050f80ff, - 0x073fa009, 0x06000007, 0x0008400e, 0x058b045c, - 0x03385000, 0x03010000, 0x06219001, 0x040fe07f, - 0x01860463, 0x008001cd, 0x07c00000, 0x00683e75, - 0x05810469, 0x0448d075, 0x0481048f, 0x018004bd, - 0x06a0051a, 0x0080041f, 0x02978476, 0x07602418, - 0x050f80ff, 0x012fa809, 0x06780001, 0x070000ff, - 0x075a0000, 0x070ff014, 0x0569feff, 0x054b08ff, - 0x075a0000, 0x05600418, 0x050f80ff, 0x012fa809, - 0x040fe007, 0x0386847d, 0x01204000, 0x0180048b, - 0x00700101, 0x03010000, 0x06780001, 0x07ff0000, - 0x076c00ff, 0x06818485, 0x00700101, 0x03010000, - 0x05600418, 0x050f80ff, 0x012fa80a, 0x06780001, - 0x07ff0000, 0x050040ff, 0x0279ff01, 0x0700ffff, - 0x05002014, 0x07c00000, 0x04007076, 0x0448b075, - 0x058104a9, 0x03200011, 0x06006076, 0x06a003e6, - 0x007a0101, 0x07060000, 0x07303000, 0x07008290, - 0x07600018, 0x050f80ff, 0x053fa809, 0x07000003, - 0x0448e007, 0x068184a1, 0x06006013, 0x018004b8, - 0x02400010, 0x048104a1, 0x06006010, 0x04603276, - 0x050f80ff, 0x073fa00a, 0x07000003, 0x018004b8, - 0x04602a76, 0x050f80ff, 0x032fa009, 0x060ff07a, - 0x05500400, 0x070000ff, 0x04602a76, 0x050f80ff, - 0x032fa00a, 0x07a003e1, 0x007a0101, 0x03010000, - 0x06303008, 0x05008000, 0x0600600e, 0x050f8074, - 0x032fa03a, 0x053079a0, 0x0700000c, 0x008004fd, - 0x00683e75, 0x076c0aff, 0x048104dc, 0x04007013, - 0x03200011, 0x06006076, 0x06a003e6, 0x007a0101, - 0x03070000, 0x06602876, 0x050f80ff, 0x053fa809, - 0x06000001, 0x03499003, 0x058104d1, 0x07303000, - 0x07008890, 0x053079a0, 0x0700000c, 0x008004d5, - 0x07303000, 0x04008980, 0x04307920, 0x0700000c, - 0x074d0005, 0x06006013, 0x050f8074, 0x032fa03a, - 0x04307920, 0x0700000c, 0x008004fd, 0x04602a76, - 0x050f80ff, 0x032fa009, 0x060ff07a, 0x05500400, - 0x070000ff, 0x04602a76, 0x050f80ff, 0x032fa00a, - 0x04007076, 0x07a003e1, 0x007a0101, 0x03010000, - 0x06303008, 0x07008800, 0x074d0005, 0x06600a76, - 0x050f80ff, 0x073fa009, 0x07000003, 0x054b0406, - 0x045a0404, 0x050040ff, 0x0600600e, 0x050f8074, - 0x032fa03a, 0x0648c075, 0x048104fb, 0x06307d20, - 0x0700000c, 0x008004fd, 0x04307920, 0x0700000c, - 0x013e4000, 0x07000030, 0x019804ff, 0x070ff0f6, - 0x074850ff, 0x05818500, 0x050f2074, 0x060a0007, - 0x040070fb, 0x046a7007, 0x050f40ff, 0x013e4000, - 0x06000020, 0x0678007a, 0x07fff000, 0x04818510, - 0x0320000a, 0x022017d0, 0x02800513, 0x0320000a, - 0x06301b58, 0x06000001, 0x050f8072, 0x032fa012, - 0x0080041f, 0x01208060, 0x0600902a, 0x04002020, - 0x02800526, 0x040080fb, 0x066ae108, 0x06009076, - 0x04002075, 0x02800526, 0x03201100, 0x05848524, - 0x06420001, 0x04818520, 0x0280053d, 0x020e0008, - 0x07c00000, 0x050fd009, 0x040fd008, 0x03201100, - 0x0584852d, 0x06420001, 0x04818529, 0x0280053d, - 0x007a0102, 0x04000101, 0x05600809, 0x050f80ff, - 0x073fa00a, 0x06000001, 0x020e0008, 0x06840537, - 0x030e0009, 0x07c00000, 0x01011009, 0x052e4300, - 0x07c00000, 0x052e400f, 0x01208090, 0x0280051f, - 0x070fc0ff, 0x040f8013, 0x032fa009, 0x02800540, - 0x6321d92e, 0xffef19a2 -}; - -#ifdef UNIQUE_FW_NAME -uint32_t fw2400_length02 = 0x0000165e ; -#else -uint32_t risc_code_length02 = 0x0000165e ; -#endif - diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index fee0c49..e96d58d 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -46,22 +46,16 @@ qla2x00_sysfs_write_fw_dump(struct kobje case 0: if (ha->fw_dump_reading == 1) { qla_printk(KERN_INFO, ha, - "Firmware dump cleared on (%ld).\n", - ha->host_no); + "Firmware dump cleared on (%ld).\n", ha->host_no); vfree(ha->fw_dump_buffer); - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) - free_pages((unsigned long)ha->fw_dump, - ha->fw_dump_order); - - ha->fw_dump_reading = 0; ha->fw_dump_buffer = NULL; - ha->fw_dump = NULL; + ha->fw_dump_reading = 0; ha->fw_dumped = 0; } break; case 1: - if ((ha->fw_dump || ha->fw_dumped) && !ha->fw_dump_reading) { + if (ha->fw_dumped && !ha->fw_dump_reading) { ha->fw_dump_reading = 1; if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 2d9b12f..74e5471 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -28,7 +28,7 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int uint16_t __iomem *dmp_reg; unsigned long flags; struct qla2300_fw_dump *fw; - uint32_t dump_size, data_ram_cnt; + uint32_t data_ram_cnt; risc_address = data_ram_cnt = 0; mb0 = mb2 = 0; @@ -37,23 +37,16 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); - if (ha->fw_dump != NULL) { + if (!ha->fw_dump) { qla_printk(KERN_WARNING, ha, - "Firmware has been previously dumped (%p) -- ignoring " - "request...\n", ha->fw_dump); + "No buffer available for dump!!!\n"); goto qla2300_fw_dump_failed; } - /* Allocate (large) dump buffer. */ - dump_size = sizeof(struct qla2300_fw_dump); - dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t); - ha->fw_dump_order = get_order(dump_size); - ha->fw_dump = (struct qla2300_fw_dump *) __get_free_pages(GFP_ATOMIC, - ha->fw_dump_order); - if (ha->fw_dump == NULL) { + if (ha->fw_dumped) { qla_printk(KERN_WARNING, ha, - "Unable to allocated memory for firmware dump (%d/%d).\n", - ha->fw_dump_order, dump_size); + "Firmware has been previously dumped (%p) -- ignoring " + "request...\n", ha->fw_dump); goto qla2300_fw_dump_failed; } fw = ha->fw_dump; @@ -358,17 +351,16 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int } } - if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); + ha->fw_dumped = 0; - free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order); - ha->fw_dump = NULL; } else { qla_printk(KERN_INFO, ha, "Firmware dump saved to temp buffer (%ld/%p).\n", ha->host_no, ha->fw_dump); + ha->fw_dumped = 1; } qla2300_fw_dump_failed: @@ -587,21 +579,16 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); - if (ha->fw_dump != NULL) { + if (!ha->fw_dump) { qla_printk(KERN_WARNING, ha, - "Firmware has been previously dumped (%p) -- ignoring " - "request...\n", ha->fw_dump); + "No buffer available for dump!!!\n"); goto qla2100_fw_dump_failed; } - /* Allocate (large) dump buffer. */ - ha->fw_dump_order = get_order(sizeof(struct qla2100_fw_dump)); - ha->fw_dump = (struct qla2100_fw_dump *) __get_free_pages(GFP_ATOMIC, - ha->fw_dump_order); - if (ha->fw_dump == NULL) { + if (ha->fw_dumped) { qla_printk(KERN_WARNING, ha, - "Unable to allocated memory for firmware dump (%d/%Zd).\n", - ha->fw_dump_order, sizeof(struct qla2100_fw_dump)); + "Firmware has been previously dumped (%p) -- ignoring " + "request...\n", ha->fw_dump); goto qla2100_fw_dump_failed; } fw = ha->fw_dump; @@ -777,13 +764,13 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); + ha->fw_dumped = 0; - free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order); - ha->fw_dump = NULL; } else { qla_printk(KERN_INFO, ha, "Firmware dump saved to temp buffer (%ld/%p).\n", ha->host_no, ha->fw_dump); + ha->fw_dumped = 1; } qla2100_fw_dump_failed: @@ -988,7 +975,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int if (!hardware_locked) spin_lock_irqsave(&ha->hardware_lock, flags); - if (!ha->fw_dump24) { + if (!ha->fw_dump) { qla_printk(KERN_WARNING, ha, "No buffer available for dump!!!\n"); goto qla24xx_fw_dump_failed; @@ -997,10 +984,10 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int if (ha->fw_dumped) { qla_printk(KERN_WARNING, ha, "Firmware has been previously dumped (%p) -- ignoring " - "request...\n", ha->fw_dump24); + "request...\n", ha->fw_dump); goto qla24xx_fw_dump_failed; } - fw = (struct qla24xx_fw_dump *) ha->fw_dump24; + fw = ha->fw_dump; rval = QLA_SUCCESS; fw->host_status = RD_REG_DWORD(®->host_status); @@ -1654,7 +1641,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int } else { qla_printk(KERN_INFO, ha, "Firmware dump saved to temp buffer (%ld/%p).\n", - ha->host_no, ha->fw_dump24); + ha->host_no, ha->fw_dump); ha->fw_dumped = 1; } @@ -1672,7 +1659,7 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *h uint32_t ext_mem_cnt; uiter = ha->fw_dump_buffer; - fw = ha->fw_dump24; + fw = ha->fw_dump; qla_uprintf(&uiter, "ISP FW Version %d.%02d.%02d Attributes %04x\n", ha->fw_major_version, ha->fw_minor_version, @@ -1995,7 +1982,6 @@ qla2x00_print_scsi_cmd(struct scsi_cmnd return; printk(" sp flags=0x%x\n", sp->flags); - printk(" state=%d\n", sp->state); } void diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 53508f3..d6f6579 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -31,6 +31,8 @@ #include #include #include +#define QLA2XXX_DRIVER_NAME "qla2xxx" + /* * We have MAILBOX_REGISTER_COUNT sized arrays in a few places, * but that's fine as we don't look at the last 24 ones for @@ -189,22 +191,13 @@ typedef struct srb { struct scsi_cmnd *cmd; /* Linux SCSI command pkt */ - struct timer_list timer; /* Command timer */ - atomic_t ref_count; /* Reference count for this structure */ uint16_t flags; - /* Request state */ - uint16_t state; - /* Single transfer DMA context */ dma_addr_t dma_handle; uint32_t request_sense_length; uint8_t *request_sense_ptr; - - /* SRB magic number */ - uint16_t magic; -#define SRB_MAGIC 0x10CB } srb_t; /* @@ -226,21 +219,6 @@ #define SRB_IOCTL BIT_10 /* IOCTL comma #define SRB_TAPE BIT_11 /* FCP2 (Tape) command. */ /* - * SRB state definitions - */ -#define SRB_FREE_STATE 0 /* returned back */ -#define SRB_PENDING_STATE 1 /* queued in LUN Q */ -#define SRB_ACTIVE_STATE 2 /* in Active Array */ -#define SRB_DONE_STATE 3 /* queued in Done Queue */ -#define SRB_RETRY_STATE 4 /* in Retry Queue */ -#define SRB_SUSPENDED_STATE 5 /* in suspended state */ -#define SRB_NO_QUEUE_STATE 6 /* is in between states */ -#define SRB_ACTIVE_TIMEOUT_STATE 7 /* in Active Array but timed out */ -#define SRB_FAILOVER_STATE 8 /* in Failover Queue */ -#define SRB_SCSI_RETRY_STATE 9 /* in Scsi Retry Queue */ - - -/* * ISP I/O Register Set structure definitions. */ struct device_reg_2xxx { @@ -270,6 +248,8 @@ #define NVR_DATA_OUT BIT_2 #define NVR_SELECT BIT_1 #define NVR_CLOCK BIT_0 +#define NVR_WAIT_CNT 20000 + union { struct { uint16_t mailbox0; @@ -1514,62 +1494,6 @@ typedef struct { } sw_info_t; /* - * Inquiry command structure. - */ -#define INQ_DATA_SIZE 36 - -/* - * Inquiry mailbox IOCB packet definition. - */ -typedef struct { - union { - cmd_a64_entry_t cmd; - sts_entry_t rsp; - struct cmd_type_7 cmd24; - struct sts_entry_24xx rsp24; - } p; - uint8_t inq[INQ_DATA_SIZE]; -} inq_cmd_rsp_t; - -/* - * Report LUN command structure. - */ -#define CHAR_TO_SHORT(a, b) (uint16_t)((uint8_t)b << 8 | (uint8_t)a) - -typedef struct { - uint32_t len; - uint32_t rsrv; -} rpt_hdr_t; - -typedef struct { - struct { - uint8_t b : 6; - uint8_t address_method : 2; - } msb; - uint8_t lsb; - uint8_t unused[6]; -} rpt_lun_t; - -typedef struct { - rpt_hdr_t hdr; - rpt_lun_t lst[MAX_LUNS]; -} rpt_lun_lst_t; - -/* - * Report Lun mailbox IOCB packet definition. - */ -typedef struct { - union { - cmd_a64_entry_t cmd; - sts_entry_t rsp; - struct cmd_type_7 cmd24; - struct sts_entry_24xx rsp24; - } p; - rpt_lun_lst_t list; -} rpt_lun_cmd_rsp_t; - - -/* * Fibre channel port type. */ typedef enum { @@ -1587,7 +1511,6 @@ typedef struct { typedef struct fc_port { struct list_head list; struct scsi_qla_host *ha; - struct scsi_qla_host *vis_ha; /* only used when suspending lun */ uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; @@ -1602,23 +1525,13 @@ typedef struct fc_port { unsigned int os_target_id; - uint16_t iodesc_idx_sent; - int port_login_retry_count; int login_retry; atomic_t port_down_timer; - uint8_t device_type; - uint8_t unused; - - uint8_t mp_byte; /* multi-path byte (not used) */ - uint8_t cur_path; /* current path id */ - spinlock_t rport_lock; struct fc_rport *rport, *drport; u32 supported_classes; - struct work_struct rport_add_work; - struct work_struct rport_del_work; } fc_port_t; /* @@ -2027,54 +1940,6 @@ struct sns_cmd_pkt { } p; }; -/* IO descriptors */ -#define MAX_IO_DESCRIPTORS 32 - -#define ABORT_IOCB_CB 0 -#define ADISC_PORT_IOCB_CB 1 -#define LOGOUT_PORT_IOCB_CB 2 -#define LOGIN_PORT_IOCB_CB 3 -#define LAST_IOCB_CB 4 - -#define IODESC_INVALID_INDEX 0xFFFF -#define IODESC_ADISC_NEEDED 0xFFFE -#define IODESC_LOGIN_NEEDED 0xFFFD - -struct io_descriptor { - uint16_t used:1; - uint16_t idx:11; - uint16_t cb_idx:4; - - struct timer_list timer; - - struct scsi_qla_host *ha; - - port_id_t d_id; - fc_port_t *remote_fcport; - - uint32_t signature; -}; - -struct qla_fw_info { - unsigned short addressing; /* addressing method used to load fw */ -#define FW_INFO_ADDR_NORMAL 0 -#define FW_INFO_ADDR_EXTENDED 1 -#define FW_INFO_ADDR_NOMORE 0xffff - unsigned short *fwcode; /* pointer to FW array */ - unsigned short *fwlen; /* number of words in array */ - unsigned short *fwstart; /* start address for F/W */ - unsigned long *lfwstart; /* start address (long) for F/W */ -}; - -struct qla_board_info { - char *drv_name; - - char isp_name[8]; - struct qla_fw_info *fw_info; - char *fw_fname; - struct scsi_host_template *sht; -}; - struct fw_blob { char *name; uint32_t segs[4]; @@ -2303,9 +2168,6 @@ #define MIN_IOBASE_LEN 0x100 uint32_t current_outstanding_cmd; srb_t *status_srb; /* Status continuation entry. */ - uint16_t revision; - uint8_t ports; - /* ISP configuration data. */ uint16_t loop_id; /* Host adapter loop id */ uint16_t fb_rev; @@ -2361,10 +2223,6 @@ #define P2P_LOOP 3 /* Fibre Channel Device List. */ struct list_head fcports; - struct list_head rscn_fcports; - - struct io_descriptor io_descriptors[MAX_IO_DESCRIPTORS]; - uint16_t iodesc_signature; /* RSCN queue. */ uint32_t rscn_queue[MAX_RSCN_COUNT]; @@ -2395,9 +2253,6 @@ #define P2P_LOOP 3 struct gid_list_info *gid_list; int gid_list_info_size; - dma_addr_t rlc_rsp_dma; - rpt_lun_cmd_rsp_t *rlc_rsp; - /* Small DMA pool allocations -- maximum 256 bytes in length. */ #define DMA_POOL_SIZE 256 struct dma_pool *s_dma_pool; @@ -2406,9 +2261,6 @@ #define DMA_POOL_SIZE 256 init_cb_t *init_cb; int init_cb_size; - dma_addr_t iodesc_pd_dma; - port_database_t *iodesc_pd; - /* These are used by mailbox operations. */ volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; @@ -2435,13 +2287,16 @@ #define MBX_ACCESS_TIMEDOUT BIT_6 mbx_cmd_t mc; /* Basic firmware related information. */ - struct qla_board_info *brd_info; uint16_t fw_major_version; uint16_t fw_minor_version; uint16_t fw_subminor_version; uint16_t fw_attributes; uint32_t fw_memory_size; uint32_t fw_transfer_size; + uint32_t fw_srisc_address; +#define RISC_START_ADDRESS_2100 0x1000 +#define RISC_START_ADDRESS_2300 0x800 +#define RISC_START_ADDRESS_2400 0x100000 uint16_t fw_options[16]; /* slots: 1,2,3,10,11 */ uint8_t fw_seriallink_options[4]; @@ -2449,15 +2304,11 @@ #define MBX_ACCESS_TIMEDOUT BIT_6 /* Firmware dump information. */ void *fw_dump; - int fw_dump_order; + int fw_dumped; int fw_dump_reading; char *fw_dump_buffer; int fw_dump_buffer_len; - int fw_dumped; - void *fw_dump24; - int fw_dump24_len; - uint8_t host_str[16]; uint32_t pci_attr; @@ -2503,8 +2354,6 @@ #define LOOP_TRANSITION(ha) \ test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \ atomic_read(&ha->loop_state) == LOOP_DOWN) -#define TGT_Q(ha, t) (ha->otgt[t]) - #define to_qla_host(x) ((scsi_qla_host_t *) (x)->hostdata) #define qla_printk(level, ha, format, arg...) \ @@ -2537,19 +2386,6 @@ #define QLA_BUSY 0x107 #define QLA_RSCNS_HANDLED 0x108 #define QLA_ALREADY_REGISTERED 0x109 -/* -* Stat info for all adpaters -*/ -struct _qla2x00stats { - unsigned long mboxtout; /* mailbox timeouts */ - unsigned long mboxerr; /* mailbox errors */ - unsigned long ispAbort; /* ISP aborts */ - unsigned long debugNo; - unsigned long loop_resync; - unsigned long outarray_full; - unsigned long retry_q_cnt; -}; - #define NVRAM_DELAY() udelay(10) #define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS+1) @@ -2565,12 +2401,6 @@ #include "qla_gbl.h" #include "qla_dbg.h" #include "qla_inline.h" -/* -* String arrays -*/ -#define LINESIZE 256 -#define MAXARGS 26 - #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) #define CMD_COMPL_STATUS(Cmnd) ((Cmnd)->SCp.this_residual) #define CMD_RESID_LEN(Cmnd) ((Cmnd)->SCp.buffers_residual) diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 1ee58ad..3af4786 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -7,7 +7,6 @@ #ifndef __QLA_FW_H #define __QLA_FW_H -#define RISC_SADDRESS 0x100000 #define MBS_CHECKSUM_ERROR 0x4010 /* @@ -463,7 +462,7 @@ struct sts_entry_24xx { uint16_t comp_status; /* Completion status. */ uint16_t ox_id; /* OX_ID used by the firmware. */ - uint32_t residual_len; /* Residual transfer length. */ + uint32_t residual_len; /* FW calc residual transfer length. */ uint16_t reserved_1; uint16_t state_flags; /* State flags. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 91e83e2..164d53c 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -9,9 +9,6 @@ #define __QLA_GBL_H #include -extern void qla2x00_remove_one(struct pci_dev *); -extern int qla2x00_probe_one(struct pci_dev *, struct qla_board_info *); - /* * Global Function Prototypes in qla_init.c source file. */ @@ -64,14 +61,11 @@ extern int qlport_down_retry; extern int ql2xplogiabsentdevice; extern int ql2xloginretrycount; extern int ql2xfdmienable; -extern int ql2xprocessrscn; extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *); -extern void qla2x00_cmd_timeout(srb_t *); - extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int); extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int); @@ -286,15 +280,6 @@ extern void *qla24xx_prep_ms_fdmi_iocb(s extern int qla2x00_fdmi_register(scsi_qla_host_t *); /* - * Global Function Prototypes in qla_rscn.c source file. - */ -extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, gfp_t); -extern int qla2x00_handle_port_rscn(scsi_qla_host_t *, uint32_t, fc_port_t *, - int); -extern void qla2x00_process_iodesc(scsi_qla_host_t *, struct mbx_entry *); -extern void qla2x00_cancel_io_descriptors(scsi_qla_host_t *); - -/* * Global Function Prototypes in qla_xioctl.c source file. */ #define qla2x00_enqueue_aen(ha, cmd, mode) do { } while (0) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 89a3fc0..3d4487e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -194,7 +194,6 @@ qla2100_pci_config(scsi_qla_host_t *ha) mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; - pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -232,7 +231,6 @@ qla2300_pci_config(scsi_qla_host_t *ha) mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; - pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -320,7 +318,6 @@ qla24xx_pci_config(scsi_qla_host_t *ha) mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; - pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -386,9 +383,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n"); /* Verify checksum of loaded RISC code. */ - rval = qla2x00_verify_checksum(ha, - IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RISC_SADDRESS : - *ha->brd_info->fw_info[0].fwstart); + rval = qla2x00_verify_checksum(ha, ha->fw_srisc_address); } if (rval) { @@ -411,7 +406,6 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) unsigned long flags = 0; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; uint32_t cnt; - unsigned long mbx_flags = 0; uint16_t cmd; ha->isp_ops.disable_intrs(ha); @@ -519,20 +513,8 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { for (cnt = 0; cnt < 30000; cnt++) { - if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) - spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags); - - if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY) { - if (!(test_bit(ABORT_ISP_ACTIVE, - &ha->dpc_flags))) - spin_unlock_irqrestore( - &ha->mbx_reg_lock, mbx_flags); + if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY) break; - } - - if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) - spin_unlock_irqrestore(&ha->mbx_reg_lock, - mbx_flags); udelay(100); } @@ -791,16 +773,26 @@ qla24xx_chip_diag(scsi_qla_host_t *ha) static void qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) { + uint32_t dump_size = 0; + ha->fw_dumped = 0; - ha->fw_dump24_len = sizeof(struct qla24xx_fw_dump); - ha->fw_dump24_len += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t); - ha->fw_dump24 = vmalloc(ha->fw_dump24_len); - if (ha->fw_dump24) + if (IS_QLA2100(ha) || IS_QLA2200(ha)) { + dump_size = sizeof(struct qla2100_fw_dump); + } else if (IS_QLA23XX(ha)) { + dump_size = sizeof(struct qla2300_fw_dump); + dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t); + } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + dump_size = sizeof(struct qla24xx_fw_dump); + dump_size += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t); + } + + ha->fw_dump = vmalloc(dump_size); + if (ha->fw_dump) qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware " - "dump...\n", ha->fw_dump24_len / 1024); + "dump...\n", dump_size / 1024); else qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for " - "firmware dump!!!\n", ha->fw_dump24_len / 1024); + "firmware dump!!!\n", dump_size / 1024); } /** @@ -818,13 +810,12 @@ qla2x00_resize_request_q(scsi_qla_host_t dma_addr_t request_dma; request_t *request_ring; + qla2x00_alloc_fw_dump(ha); + /* Valid only on recent ISPs. */ if (IS_QLA2100(ha) || IS_QLA2200(ha)) return; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) - qla2x00_alloc_fw_dump(ha); - /* Retrieve IOCB counts available to the firmware. */ rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt); if (rval) @@ -1545,6 +1536,12 @@ #endif while (cnt--) *dptr1++ = *dptr2++; + /* Use alternate WWN? */ + if (nv->host_p[1] & BIT_7) { + memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); + memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); + } + /* Prepare nodename */ if ((icb->firmware_options[1] & BIT_6) == 0) { /* @@ -1682,14 +1679,6 @@ #endif } static void -qla2x00_rport_add(void *data) -{ - fc_port_t *fcport = data; - - qla2x00_reg_remote_port(fcport->ha, fcport); -} - -static void qla2x00_rport_del(void *data) { fc_port_t *fcport = data; @@ -1726,13 +1715,10 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha fcport->ha = ha; fcport->port_type = FCT_UNKNOWN; fcport->loop_id = FC_NO_LOOP_ID; - fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; atomic_set(&fcport->state, FCS_UNCONFIGURED); fcport->flags = FCF_RLC_SUPPORT; fcport->supported_classes = FC_COS_UNSPECIFIED; spin_lock_init(&fcport->rport_lock); - INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport); - INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport); return (fcport); } @@ -1792,6 +1778,9 @@ qla2x00_configure_loop(scsi_qla_host_t * set_bit(RSCN_UPDATE, &flags); clear_bit(LOCAL_LOOP_UPDATE, &flags); + } else if (ha->current_topology == ISP_CFG_N) { + clear_bit(RSCN_UPDATE, &flags); + } else if (!ha->flags.online || (test_bit(ABORT_ISP_ACTIVE, &flags))) { @@ -2055,10 +2044,6 @@ qla2x00_update_fcport(scsi_qla_host_t *h PORT_RETRY_TIME); fcport->flags &= ~FCF_LOGIN_NEEDED; - if (fcport->port_type == FCT_INITIATOR || - fcport->port_type == FCT_BROADCAST) - fcport->device_type = TYPE_PROCESSOR; - atomic_set(&fcport->state, FCS_ONLINE); if (ha->flags.init_done) @@ -2273,8 +2258,7 @@ qla2x00_configure_fabric(scsi_qla_host_t } /* Remove device from the new list and add it to DB */ - list_del(&fcport->list); - list_add_tail(&fcport->list, &ha->fcports); + list_move_tail(&fcport->list, &ha->fcports); /* Login and update database */ qla2x00_fabric_dev_login(ha, fcport, &next_loopid); @@ -2587,7 +2571,6 @@ static int qla2x00_device_resync(scsi_qla_host_t *ha) { int rval; - int rval2; uint32_t mask; fc_port_t *fcport; uint32_t rscn_entry; @@ -2643,17 +2626,6 @@ qla2x00_device_resync(scsi_qla_host_t *h switch (format) { case 0: - if (ql2xprocessrscn && - !IS_QLA2100(ha) && !IS_QLA2200(ha) && - !IS_QLA6312(ha) && !IS_QLA6322(ha) && - !IS_QLA24XX(ha) && !IS_QLA54XX(ha) && - ha->flags.init_done) { - /* Handle port RSCN via asyncronous IOCBs */ - rval2 = qla2x00_handle_port_rscn(ha, rscn_entry, - NULL, 0); - if (rval2 == QLA_SUCCESS) - continue; - } mask = 0xffffff; break; case 1: @@ -2671,10 +2643,6 @@ qla2x00_device_resync(scsi_qla_host_t *h rval = QLA_SUCCESS; - /* Abort any outstanding IO descriptors. */ - if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) - qla2x00_cancel_io_descriptors(ha); - list_for_each_entry(fcport, &ha->fcports, list) { if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || (fcport->d_id.b24 & mask) != d_id.b24 || @@ -3383,8 +3351,14 @@ qla24xx_nvram_config(scsi_qla_host_t *ha } else strcpy(ha->model_number, "QLA2462"); + /* Use alternate WWN? */ + if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { + memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); + memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); + } + /* Prepare nodename */ - if ((icb->firmware_options_1 & BIT_14) == 0) { + if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) { /* * Firmware will apply the following mask if the nodename was * not provided. @@ -3400,8 +3374,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha ha->flags.enable_target_reset = 1; ha->flags.enable_led_scheme = 0; - ha->operating_mode = - (icb->firmware_options_2 & (BIT_6 | BIT_5 | BIT_4)) >> 4; + ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) & + (BIT_6 | BIT_5 | BIT_4)) >> 4; memcpy(ha->fw_seriallink_options24, nv->seriallink_options, sizeof(ha->fw_seriallink_options24)); @@ -3498,133 +3472,6 @@ qla24xx_nvram_config(scsi_qla_host_t *ha return (rval); } -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) - -int -qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) -{ - int rval, num, i; - uint32_t cnt; - uint16_t *risc_code; - uint32_t risc_addr, risc_size; - uint16_t *req_ring; - struct qla_fw_info *fw_iter; - - rval = QLA_SUCCESS; - - /* Load firmware sequences */ - fw_iter = ha->brd_info->fw_info; - *srisc_addr = *ha->brd_info->fw_info->fwstart; - while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { - risc_code = fw_iter->fwcode; - risc_size = *fw_iter->fwlen; - if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) - risc_addr = *fw_iter->fwstart; - else - risc_addr = *fw_iter->lfwstart; - - num = 0; - rval = 0; - while (risc_size > 0 && !rval) { - cnt = (uint16_t)(ha->fw_transfer_size >> 1); - if (cnt > risc_size) - cnt = risc_size; - - DEBUG7(printk("scsi(%ld): Loading risc segment@ " - "addr %p, number of bytes 0x%x, offset 0x%lx.\n", - ha->host_no, risc_code, cnt, risc_addr)); - - req_ring = (uint16_t *)ha->request_ring; - for (i = 0; i < cnt; i++) - req_ring[i] = cpu_to_le16(risc_code[i]); - - rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, - cnt); - if (rval) { - DEBUG(printk("scsi(%ld): [ERROR] Failed to " - "load segment %d of firmware\n", - ha->host_no, num)); - qla_printk(KERN_WARNING, ha, - "[ERROR] Failed to load segment %d of " - "firmware\n", num); - - qla2x00_dump_regs(ha); - break; - } - - risc_code += cnt; - risc_addr += cnt; - risc_size -= cnt; - num++; - } - - /* Next firmware sequence */ - fw_iter++; - } - return rval; -} - -int -qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) -{ - int rval, num, i; - uint32_t cnt; - uint32_t *risc_code; - uint32_t risc_addr, risc_size; - uint32_t *req_ring; - struct qla_fw_info *fw_iter; - - rval = QLA_SUCCESS; - - /* Load firmware sequences */ - fw_iter = ha->brd_info->fw_info; - *srisc_addr = *((uint32_t *)fw_iter->lfwstart); - while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { - risc_code = (uint32_t *)fw_iter->fwcode; - risc_size = *((uint32_t *)fw_iter->fwlen); - risc_addr = *((uint32_t *)fw_iter->lfwstart); - - num = 0; - rval = 0; - while (risc_size > 0 && !rval) { - cnt = (uint32_t)(ha->fw_transfer_size >> 2); - if (cnt > risc_size) - cnt = risc_size; - - DEBUG7(printk("scsi(%ld): Loading risc segment@ " - "addr %p, number of bytes 0x%x, offset 0x%lx.\n", - ha->host_no, risc_code, cnt, risc_addr)); - - req_ring = (uint32_t *)ha->request_ring; - for (i = 0; i < cnt; i++) - req_ring[i] = cpu_to_le32(risc_code[i]); - - rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr, - cnt); - if (rval) { - DEBUG(printk("scsi(%ld): [ERROR] Failed to " - "load segment %d of firmware\n", - ha->host_no, num)); - qla_printk(KERN_WARNING, ha, - "[ERROR] Failed to load segment %d of " - "firmware\n", num); - - qla2x00_dump_regs(ha); - break; - } - - risc_code += cnt; - risc_addr += cnt; - risc_size -= cnt; - num++; - } - - /* Next firmware sequence */ - fw_iter++; - } - return rval; -} - int qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) { @@ -3707,7 +3554,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t return rval; } -#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ +#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/" int qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) @@ -3722,6 +3569,8 @@ qla2x00_load_risc(scsi_qla_host_t *ha, u blob = qla2x00_request_firmware(ha); if (!blob) { qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); + qla_printk(KERN_ERR, ha, "Firmware images can be retrieved " + "from: " QLA_FW_URL ".\n"); return QLA_FUNCTION_FAILED; } @@ -3823,7 +3672,13 @@ qla24xx_load_risc(scsi_qla_host_t *ha, u blob = qla2x00_request_firmware(ha); if (!blob) { qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n"); - return QLA_FUNCTION_FAILED; + qla_printk(KERN_ERR, ha, "Firmware images can be retrieved " + "from: " QLA_FW_URL ".\n"); + + /* Try to load RISC code from flash. */ + qla_printk(KERN_ERR, ha, "Attempting to load (potentially " + "outdated) firmware from flash.\n"); + return qla24xx_load_risc_flash(ha, srisc_addr); } rval = QLA_SUCCESS; @@ -3909,4 +3764,3 @@ qla24xx_load_risc(scsi_qla_host_t *ha, u fail_fw_integrity: return QLA_FUNCTION_FAILED; } -#endif diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 8f0f4a2..8c769cf 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -408,7 +408,6 @@ qla2x00_start_scsi(srb_t *sp) ha->request_ring_ptr++; sp->flags |= SRB_DMA_VALID; - sp->state = SRB_ACTIVE_STATE; /* Set chip new ring index. */ WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), ha->req_ring_index); @@ -838,7 +837,6 @@ qla24xx_start_scsi(srb_t *sp) ha->request_ring_ptr++; sp->flags |= SRB_DMA_VALID; - sp->state = SRB_ACTIVE_STATE; /* Set chip new ring index. */ WRT_REG_DWORD(®->req_q_in, ha->req_ring_index); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 2003dbb..b28ac0a 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -515,47 +515,6 @@ #define LS_UNKNOWN 2 case MBA_PORT_UPDATE: /* Port database update */ /* - * If a single remote port just logged into (or logged out of) - * us, create a new entry in our rscn fcports list and handle - * the event like an RSCN. - */ - if (ql2xprocessrscn && - !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) && - !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA54XX(ha) && - ha->flags.init_done && mb[1] != 0xffff && - ((ha->operating_mode == P2P && mb[1] != 0) || - (ha->operating_mode != P2P && mb[1] != - SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) { - int rval; - fc_port_t *rscn_fcport; - - /* Create new fcport for login. */ - rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC); - if (rscn_fcport) { - DEBUG14(printk("scsi(%ld): Port Update -- " - "creating RSCN fcport %p for %x/%x/%x.\n", - ha->host_no, rscn_fcport, mb[1], mb[2], - mb[3])); - - rscn_fcport->loop_id = mb[1]; - rscn_fcport->d_id.b24 = INVALID_PORT_ID; - atomic_set(&rscn_fcport->state, - FCS_DEVICE_LOST); - list_add_tail(&rscn_fcport->list, - &ha->rscn_fcports); - - rval = qla2x00_handle_port_rscn(ha, 0, - rscn_fcport, 1); - if (rval == QLA_SUCCESS) - break; - } else { - DEBUG14(printk("scsi(%ld): Port Update -- " - "-- unable to allocate RSCN fcport " - "login.\n", ha->host_no)); - } - } - - /* * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET * event etc. earlier indicating loop is down) then process * it. Otherwise ignore it and Wait for RSCN to come in. @@ -753,25 +712,6 @@ qla2x00_process_response_queue(struct sc case MS_IOCB_TYPE: qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt); break; - case MBX_IOCB_TYPE: - if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && - !IS_QLA6312(ha) && !IS_QLA6322(ha)) { - if (pkt->sys_define == SOURCE_ASYNC_IOCB) { - qla2x00_process_iodesc(ha, - (struct mbx_entry *)pkt); - } else { - /* MBX IOCB Type Not Supported. */ - DEBUG4(printk(KERN_WARNING - "scsi(%ld): Received unknown MBX " - "IOCB response pkt type=%x " - "source=%x entry status=%x.\n", - ha->host_no, pkt->entry_type, - pkt->sys_define, - pkt->entry_status)); - } - break; - } - /* Fallthrough. */ default: /* Type Not Supported. */ DEBUG4(printk(KERN_WARNING @@ -805,7 +745,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha uint16_t scsi_status; uint8_t lscsi_status; int32_t resid; - uint32_t sense_len, rsp_info_len, resid_len; + uint32_t sense_len, rsp_info_len, resid_len, fw_resid_len; uint8_t *rsp_info, *sense_data; sts = (sts_entry_t *) pkt; @@ -844,8 +784,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha cp = sp->cmd; if (cp == NULL) { DEBUG2(printk("scsi(%ld): Command already returned back to OS " - "pkt->handle=%d sp=%p sp->state:%d\n", - ha->host_no, sts->handle, sp, sp->state)); + "pkt->handle=%d sp=%p.\n", ha->host_no, sts->handle, sp)); qla_printk(KERN_WARNING, ha, "Command is NULL: already returned to OS (sp=%p)\n", sp); @@ -859,11 +798,12 @@ qla2x00_status_entry(scsi_qla_host_t *ha fcport = sp->fcport; - sense_len = rsp_info_len = resid_len = 0; + sense_len = rsp_info_len = resid_len = fw_resid_len = 0; if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { sense_len = le32_to_cpu(sts24->sense_len); rsp_info_len = le32_to_cpu(sts24->rsp_data_len); resid_len = le32_to_cpu(sts24->rsp_residual_count); + fw_resid_len = le32_to_cpu(sts24->residual_len); rsp_info = sts24->data; sense_data = sts24->data; host_to_fcp_swap(sts24->data, sizeof(sts24->data)); @@ -963,14 +903,21 @@ qla2x00_status_entry(scsi_qla_host_t *ha case CS_DATA_UNDERRUN: resid = resid_len; + /* Use F/W calculated residual length. */ + if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + resid = fw_resid_len; + if (scsi_status & SS_RESIDUAL_UNDER) { cp->resid = resid; CMD_RESID_LEN(cp) = resid; } else { DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d) UNDERRUN status detected " - "0x%x-0x%x.\n", ha->host_no, cp->device->id, - cp->device->lun, comp_status, scsi_status)); + "0x%x-0x%x. resid=0x%x fw_resid=0x%x cdb=0x%x " + "os_underflow=0x%x\n", ha->host_no, + cp->device->id, cp->device->lun, comp_status, + scsi_status, resid_len, resid, cp->cmnd[0], + cp->underflow)); } @@ -1181,7 +1128,7 @@ qla2x00_status_cont_entry(scsi_qla_host_ cp = sp->cmd; if (cp == NULL) { DEBUG2(printk("%s(): Cmd already returned back to OS " - "sp=%p sp->state:%d\n", __func__, sp, sp->state)); + "sp=%p.\n", __func__, sp)); qla_printk(KERN_INFO, ha, "cmd is NULL: already returned to OS (sp=%p)\n", sp); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 584fe5d..ccaad0b 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -54,13 +54,6 @@ module_param(ql2xloginretrycount, int, S MODULE_PARM_DESC(ql2xloginretrycount, "Specify an alternate value for the NVRAM login retry count."); -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) -int ql2xfwloadflash; -module_param(ql2xfwloadflash, int, S_IRUGO|S_IRUSR); -MODULE_PARM_DESC(ql2xfwloadflash, - "Load ISP24xx firmware image from FLASH (onboard memory)."); -#endif - static void qla2x00_free_device(scsi_qla_host_t *); static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha); @@ -71,12 +64,6 @@ MODULE_PARM_DESC(ql2xfdmienable, "Enables FDMI registratons " "Default is 0 - no FDMI. 1 - perfom FDMI."); -int ql2xprocessrscn; -module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR); -MODULE_PARM_DESC(ql2xprocessrscn, - "Option to enable port RSCN handling via a series of less" - "fabric intrusive ADISCs and PLOGIs."); - /* * SCSI host template entry points */ @@ -99,7 +86,7 @@ static int qla2x00_change_queue_type(str static struct scsi_host_template qla2x00_driver_template = { .module = THIS_MODULE, - .name = "qla2xxx", + .name = QLA2XXX_DRIVER_NAME, .queuecommand = qla2x00_queuecommand, .eh_abort_handler = qla2xxx_eh_abort, @@ -128,7 +115,7 @@ static struct scsi_host_template qla2x00 static struct scsi_host_template qla24xx_driver_template = { .module = THIS_MODULE, - .name = "qla2xxx", + .name = QLA2XXX_DRIVER_NAME, .queuecommand = qla24xx_queuecommand, .eh_abort_handler = qla2xxx_eh_abort, @@ -340,7 +327,6 @@ qla2x00_get_new_sp(scsi_qla_host_t *ha, if (!sp) return sp; - atomic_set(&sp->ref_count, 1); sp->ha = ha; sp->fcport = fcport; sp->cmd = cmd; @@ -577,6 +563,10 @@ qla2x00_wait_for_loop_ready(scsi_qla_hos while ((!atomic_read(&ha->loop_down_timer) && atomic_read(&ha->loop_state) == LOOP_DOWN) || atomic_read(&ha->loop_state) != LOOP_READY) { + if (atomic_read(&ha->loop_state) == LOOP_DEAD) { + return_status = QLA_FUNCTION_FAILED; + break; + } msleep(1000); if (time_after_eq(jiffies, loop_timeout)) { return_status = QLA_FUNCTION_FAILED; @@ -632,9 +622,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) if (sp->cmd != cmd) continue; - DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld " - "sp->state=%x\n", __func__, ha->host_no, sp, serial, - sp->state)); + DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld.\n", + __func__, ha->host_no, sp, serial)); DEBUG3(qla2x00_print_scsi_cmd(cmd);) spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -1157,18 +1146,22 @@ qla2x00_set_isp_flags(scsi_qla_host_t *h case PCI_DEVICE_ID_QLOGIC_ISP2100: ha->device_type |= DT_ISP2100; ha->device_type &= ~DT_EXTENDED_IDS; + ha->fw_srisc_address = RISC_START_ADDRESS_2100; break; case PCI_DEVICE_ID_QLOGIC_ISP2200: ha->device_type |= DT_ISP2200; ha->device_type &= ~DT_EXTENDED_IDS; + ha->fw_srisc_address = RISC_START_ADDRESS_2100; break; case PCI_DEVICE_ID_QLOGIC_ISP2300: ha->device_type |= DT_ISP2300; ha->device_type |= DT_ZIO_SUPPORTED; + ha->fw_srisc_address = RISC_START_ADDRESS_2300; break; case PCI_DEVICE_ID_QLOGIC_ISP2312: ha->device_type |= DT_ISP2312; ha->device_type |= DT_ZIO_SUPPORTED; + ha->fw_srisc_address = RISC_START_ADDRESS_2300; break; case PCI_DEVICE_ID_QLOGIC_ISP2322: ha->device_type |= DT_ISP2322; @@ -1176,26 +1169,33 @@ qla2x00_set_isp_flags(scsi_qla_host_t *h if (ha->pdev->subsystem_vendor == 0x1028 && ha->pdev->subsystem_device == 0x0170) ha->device_type |= DT_OEM_001; + ha->fw_srisc_address = RISC_START_ADDRESS_2300; break; case PCI_DEVICE_ID_QLOGIC_ISP6312: ha->device_type |= DT_ISP6312; + ha->fw_srisc_address = RISC_START_ADDRESS_2300; break; case PCI_DEVICE_ID_QLOGIC_ISP6322: ha->device_type |= DT_ISP6322; + ha->fw_srisc_address = RISC_START_ADDRESS_2300; break; case PCI_DEVICE_ID_QLOGIC_ISP2422: ha->device_type |= DT_ISP2422; ha->device_type |= DT_ZIO_SUPPORTED; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; case PCI_DEVICE_ID_QLOGIC_ISP2432: ha->device_type |= DT_ISP2432; ha->device_type |= DT_ZIO_SUPPORTED; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; case PCI_DEVICE_ID_QLOGIC_ISP5422: ha->device_type |= DT_ISP5422; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; case PCI_DEVICE_ID_QLOGIC_ISP5432: ha->device_type |= DT_ISP5432; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; } } @@ -1242,7 +1242,7 @@ qla2x00_iospace_config(scsi_qla_host_t * goto iospace_error_exit; } - if (pci_request_regions(ha->pdev, ha->brd_info->drv_name)) { + if (pci_request_regions(ha->pdev, QLA2XXX_DRIVER_NAME)) { qla_printk(KERN_WARNING, ha, "Failed to reserve PIO/MMIO regions (%s)\n", pci_name(ha->pdev)); @@ -1324,7 +1324,7 @@ qla24xx_disable_intrs(scsi_qla_host_t *h /* * PCI driver interface */ -int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) +static int qla2x00_probe_one(struct pci_dev *pdev) { int ret = -ENODEV; device_reg_t __iomem *reg; @@ -1358,8 +1358,7 @@ int qla2x00_probe_one(struct pci_dev *pd ha->pdev = pdev; ha->host = host; ha->host_no = host->host_no; - ha->brd_info = brd_info; - sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no); + sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no); /* Set ISP-type information. */ qla2x00_set_isp_flags(ha); @@ -1376,7 +1375,6 @@ int qla2x00_probe_one(struct pci_dev *pd spin_lock_init(&ha->hardware_lock); ha->prev_topology = 0; - ha->ports = MAX_BUSES; ha->init_cb_size = sizeof(init_cb_t); ha->mgmt_svr_loop_id = MANAGEMENT_SERVER; ha->link_data_rate = LDR_UNKNOWN; @@ -1457,10 +1455,6 @@ int qla2x00_probe_one(struct pci_dev *pd ha->isp_ops.nvram_config = qla24xx_nvram_config; ha->isp_ops.update_fw_options = qla24xx_update_fw_options; ha->isp_ops.load_risc = qla24xx_load_risc; -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) - if (ql2xfwloadflash) - ha->isp_ops.load_risc = qla24xx_load_risc_flash; -#endif ha->isp_ops.pci_info_str = qla24xx_pci_info_str; ha->isp_ops.fw_version_str = qla24xx_fw_version_str; ha->isp_ops.intr_handler = qla24xx_intr_handler; @@ -1494,7 +1488,6 @@ #endif INIT_LIST_HEAD(&ha->list); INIT_LIST_HEAD(&ha->fcports); - INIT_LIST_HEAD(&ha->rscn_fcports); /* * These locks are used to prevent more than one CPU @@ -1543,12 +1536,12 @@ #endif host->cmd_per_lun = 3; host->unique_id = ha->instance; host->max_cmd_len = MAX_CMDSZ; - host->max_channel = ha->ports - 1; + host->max_channel = MAX_BUSES - 1; host->max_lun = MAX_LUNS; host->transportt = qla2xxx_transport_template; ret = request_irq(pdev->irq, ha->isp_ops.intr_handler, - SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha); + SA_INTERRUPT|SA_SHIRQ, QLA2XXX_DRIVER_NAME, ha); if (ret) { qla_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d already in use.\n", @@ -1646,9 +1639,8 @@ probe_disable_device: probe_out: return ret; } -EXPORT_SYMBOL_GPL(qla2x00_probe_one); -void qla2x00_remove_one(struct pci_dev *pdev) +static void qla2x00_remove_one(struct pci_dev *pdev) { scsi_qla_host_t *ha; @@ -1666,15 +1658,10 @@ void qla2x00_remove_one(struct pci_dev * pci_set_drvdata(pdev, NULL); } -EXPORT_SYMBOL_GPL(qla2x00_remove_one); static void qla2x00_free_device(scsi_qla_host_t *ha) { - /* Abort any outstanding IO descriptors. */ - if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) - qla2x00_cancel_io_descriptors(ha); - /* Disable timer */ if (ha->timer_active) qla2x00_stop_timer(ha); @@ -1884,19 +1871,8 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) continue; } - ha->rlc_rsp = dma_alloc_coherent(&ha->pdev->dev, - sizeof(rpt_lun_cmd_rsp_t), &ha->rlc_rsp_dma, GFP_KERNEL); - if (ha->rlc_rsp == NULL) { - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - rlc"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - - snprintf(name, sizeof(name), "qla2xxx_%ld", ha->host_no); + snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, + ha->host_no); ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, DMA_POOL_SIZE, 8, 0); if (ha->s_dma_pool == NULL) { @@ -1923,21 +1899,6 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) } memset(ha->init_cb, 0, ha->init_cb_size); - /* Get consistent memory allocated for Get Port Database cmd */ - ha->iodesc_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, - &ha->iodesc_pd_dma); - if (ha->iodesc_pd == NULL) { - /* error */ - qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - iodesc_pd\n"); - - qla2x00_mem_free(ha); - msleep(100); - - continue; - } - memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE); - /* Allocate ioctl related memory. */ if (qla2x00_alloc_ioctl_mem(ha)) { qla_printk(KERN_WARNING, ha, @@ -2062,20 +2023,12 @@ qla2x00_mem_free(scsi_qla_host_t *ha) if (ha->ms_iocb) dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); - if (ha->iodesc_pd) - dma_pool_free(ha->s_dma_pool, ha->iodesc_pd, ha->iodesc_pd_dma); - if (ha->init_cb) dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma); if (ha->s_dma_pool) dma_pool_destroy(ha->s_dma_pool); - if (ha->rlc_rsp) - dma_free_coherent(&ha->pdev->dev, - sizeof(rpt_lun_cmd_rsp_t), ha->rlc_rsp, - ha->rlc_rsp_dma); - if (ha->gid_list) dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, ha->gid_list_dma); @@ -2096,15 +2049,11 @@ qla2x00_mem_free(scsi_qla_host_t *ha) ha->ct_sns_dma = 0; ha->ms_iocb = NULL; ha->ms_iocb_dma = 0; - ha->iodesc_pd = NULL; - ha->iodesc_pd_dma = 0; ha->init_cb = NULL; ha->init_cb_dma = 0; ha->s_dma_pool = NULL; - ha->rlc_rsp = NULL; - ha->rlc_rsp_dma = 0; ha->gid_list = NULL; ha->gid_list_dma = 0; @@ -2122,15 +2071,10 @@ qla2x00_mem_free(scsi_qla_host_t *ha) } INIT_LIST_HEAD(&ha->fcports); - if (ha->fw_dump) - free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order); - - vfree(ha->fw_dump24); - + vfree(ha->fw_dump); vfree(ha->fw_dump_buffer); ha->fw_dump = NULL; - ha->fw_dump24 = NULL; ha->fw_dumped = 0; ha->fw_dump_reading = 0; ha->fw_dump_buffer = NULL; @@ -2148,8 +2092,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) * * Context: * Kernel context. - * - * Note: Sets the ref_count for non Null sp to one. */ static int qla2x00_allocate_sp_pool(scsi_qla_host_t *ha) @@ -2593,14 +2535,6 @@ qla2x00_down_timeout(struct semaphore *s return -ETIMEDOUT; } -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) - -#define qla2x00_release_firmware() do { } while (0) -#define qla2x00_pci_module_init() (0) -#define qla2x00_pci_module_exit() do { } while (0) - -#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */ - /* Firmware interface routines. */ #define FW_BLOBS 5 @@ -2667,33 +2601,18 @@ qla2x00_release_firmware(void) up(&qla_fw_lock); } -static struct qla_board_info qla_board_tbl = { - .drv_name = "qla2xxx", -}; - static struct pci_device_id qla2xxx_pci_tbl[] = { - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422, - PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432, - PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) }, { 0 }, }; MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); @@ -2701,7 +2620,7 @@ MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl static int __devinit qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) { - return qla2x00_probe_one(pdev, &qla_board_tbl); + return qla2x00_probe_one(pdev); } static void __devexit @@ -2711,7 +2630,7 @@ qla2xxx_remove_one(struct pci_dev *pdev) } static struct pci_driver qla2xxx_pci_driver = { - .name = "qla2xxx", + .name = QLA2XXX_DRIVER_NAME, .driver = { .owner = THIS_MODULE, }, @@ -2732,8 +2651,6 @@ qla2x00_pci_module_exit(void) pci_unregister_driver(&qla2xxx_pci_driver); } -#endif - /** * qla2x00_module_init - Module initialization. **/ @@ -2753,9 +2670,6 @@ qla2x00_module_init(void) /* Derive version string. */ strcpy(qla2x00_version_str, QLA2XXX_VERSION); -#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) - strcat(qla2x00_version_str, "-fw"); -#endif #if DEBUG_QLA2100 strcat(qla2x00_version_str, "-debug"); #endif diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c deleted file mode 100644 index b70bebe..0000000 --- a/drivers/scsi/qla2xxx/qla_rscn.c +++ /dev/null @@ -1,1426 +0,0 @@ -/* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2005 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. - */ -#include "qla_def.h" - -/** - * IO descriptor handle definitions. - * - * Signature form: - * - * |31------28|27-------------------12|11-------0| - * | Type | Rolling Signature | Index | - * |----------|-----------------------|----------| - * - **/ - -#define HDL_TYPE_SCSI 0 -#define HDL_TYPE_ASYNC_IOCB 0x0A - -#define HDL_INDEX_BITS 12 -#define HDL_ITER_BITS 16 -#define HDL_TYPE_BITS 4 - -#define HDL_INDEX_MASK ((1UL << HDL_INDEX_BITS) - 1) -#define HDL_ITER_MASK ((1UL << HDL_ITER_BITS) - 1) -#define HDL_TYPE_MASK ((1UL << HDL_TYPE_BITS) - 1) - -#define HDL_INDEX_SHIFT 0 -#define HDL_ITER_SHIFT (HDL_INDEX_SHIFT + HDL_INDEX_BITS) -#define HDL_TYPE_SHIFT (HDL_ITER_SHIFT + HDL_ITER_BITS) - -/* Local Prototypes. */ -static inline uint32_t qla2x00_to_handle(uint16_t, uint16_t, uint16_t); -static inline uint16_t qla2x00_handle_to_idx(uint32_t); -static inline uint32_t qla2x00_iodesc_to_handle(struct io_descriptor *); -static inline struct io_descriptor *qla2x00_handle_to_iodesc(scsi_qla_host_t *, - uint32_t); - -static inline struct io_descriptor *qla2x00_alloc_iodesc(scsi_qla_host_t *); -static inline void qla2x00_free_iodesc(struct io_descriptor *); -static inline void qla2x00_init_io_descriptors(scsi_qla_host_t *); - -static void qla2x00_iodesc_timeout(unsigned long); -static inline void qla2x00_add_iodesc_timer(struct io_descriptor *); -static inline void qla2x00_remove_iodesc_timer(struct io_descriptor *); - -static inline void qla2x00_update_login_fcport(scsi_qla_host_t *, - struct mbx_entry *, fc_port_t *); - -static int qla2x00_send_abort_iocb(scsi_qla_host_t *, struct io_descriptor *, - uint32_t, int); -static int qla2x00_send_abort_iocb_cb(scsi_qla_host_t *, struct io_descriptor *, - struct mbx_entry *); - -static int qla2x00_send_adisc_iocb(scsi_qla_host_t *, struct io_descriptor *, - int); -static int qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *, struct io_descriptor *, - struct mbx_entry *); - -static int qla2x00_send_logout_iocb(scsi_qla_host_t *, struct io_descriptor *, - int); -static int qla2x00_send_logout_iocb_cb(scsi_qla_host_t *, - struct io_descriptor *, struct mbx_entry *); - -static int qla2x00_send_login_iocb(scsi_qla_host_t *, struct io_descriptor *, - port_id_t *, int); -static int qla2x00_send_login_iocb_cb(scsi_qla_host_t *, struct io_descriptor *, - struct mbx_entry *); - -/** - * Mailbox IOCB callback array. - **/ -static int (*iocb_function_cb_list[LAST_IOCB_CB]) - (scsi_qla_host_t *, struct io_descriptor *, struct mbx_entry *) = { - - qla2x00_send_abort_iocb_cb, - qla2x00_send_adisc_iocb_cb, - qla2x00_send_logout_iocb_cb, - qla2x00_send_login_iocb_cb, -}; - - -/** - * Generic IO descriptor handle routines. - **/ - -/** - * qla2x00_to_handle() - Create a descriptor handle. - * @type: descriptor type - * @iter: descriptor rolling signature - * @idx: index to the descriptor array - * - * Returns a composite handle based in the @type, @iter, and @idx. - */ -static inline uint32_t -qla2x00_to_handle(uint16_t type, uint16_t iter, uint16_t idx) -{ - return ((uint32_t)(((uint32_t)type << HDL_TYPE_SHIFT) | - ((uint32_t)iter << HDL_ITER_SHIFT) | - ((uint32_t)idx << HDL_INDEX_SHIFT))); -} - -/** - * qla2x00_handle_to_idx() - Retrive the index for a given handle. - * @handle: descriptor handle - * - * Returns the index specified by the @handle. - */ -static inline uint16_t -qla2x00_handle_to_idx(uint32_t handle) -{ - return ((uint16_t)(((handle) >> HDL_INDEX_SHIFT) & HDL_INDEX_MASK)); -} - -/** - * qla2x00_iodesc_to_handle() - Convert an IO descriptor to a unique handle. - * @iodesc: io descriptor - * - * Returns a unique handle for @iodesc. - */ -static inline uint32_t -qla2x00_iodesc_to_handle(struct io_descriptor *iodesc) -{ - uint32_t handle; - - handle = qla2x00_to_handle(HDL_TYPE_ASYNC_IOCB, - ++iodesc->ha->iodesc_signature, iodesc->idx); - iodesc->signature = handle; - - return (handle); -} - -/** - * qla2x00_handle_to_iodesc() - Retrieve an IO descriptor given a unique handle. - * @ha: HA context - * @handle: handle to io descriptor - * - * Returns a pointer to the io descriptor, or NULL, if the io descriptor does - * not exist or the io descriptors signature does not @handle. - */ -static inline struct io_descriptor * -qla2x00_handle_to_iodesc(scsi_qla_host_t *ha, uint32_t handle) -{ - uint16_t idx; - struct io_descriptor *iodesc; - - idx = qla2x00_handle_to_idx(handle); - iodesc = &ha->io_descriptors[idx]; - if (iodesc) - if (iodesc->signature != handle) - iodesc = NULL; - - return (iodesc); -} - - -/** - * IO descriptor allocation routines. - **/ - -/** - * qla2x00_alloc_iodesc() - Allocate an IO descriptor from the pool. - * @ha: HA context - * - * Returns a pointer to the allocated io descriptor, or NULL, if none available. - */ -static inline struct io_descriptor * -qla2x00_alloc_iodesc(scsi_qla_host_t *ha) -{ - uint16_t iter; - struct io_descriptor *iodesc; - - iodesc = NULL; - for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) { - if (ha->io_descriptors[iter].used) - continue; - - iodesc = &ha->io_descriptors[iter]; - iodesc->used = 1; - iodesc->idx = iter; - init_timer(&iodesc->timer); - iodesc->ha = ha; - iodesc->signature = qla2x00_iodesc_to_handle(iodesc); - break; - } - - return (iodesc); -} - -/** - * qla2x00_free_iodesc() - Free an IO descriptor. - * @iodesc: io descriptor - * - * NOTE: The io descriptors timer *must* be stopped before it can be free'd. - */ -static inline void -qla2x00_free_iodesc(struct io_descriptor *iodesc) -{ - iodesc->used = 0; - iodesc->signature = 0; -} - -/** - * qla2x00_remove_iodesc_timer() - Remove an active timer from an IO descriptor. - * @iodesc: io descriptor - */ -static inline void -qla2x00_remove_iodesc_timer(struct io_descriptor *iodesc) -{ - if (iodesc->timer.function != NULL) { - del_timer_sync(&iodesc->timer); - iodesc->timer.data = (unsigned long) NULL; - iodesc->timer.function = NULL; - } -} - -/** - * qla2x00_init_io_descriptors() - Initialize the pool of IO descriptors. - * @ha: HA context - */ -static inline void -qla2x00_init_io_descriptors(scsi_qla_host_t *ha) -{ - uint16_t iter; - - for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) { - if (!ha->io_descriptors[iter].used) - continue; - - qla2x00_remove_iodesc_timer(&ha->io_descriptors[iter]); - qla2x00_free_iodesc(&ha->io_descriptors[iter]); - } -} - - -/** - * IO descriptor timer routines. - **/ - -/** - * qla2x00_iodesc_timeout() - Timeout IO descriptor handler. - * @data: io descriptor - */ -static void -qla2x00_iodesc_timeout(unsigned long data) -{ - struct io_descriptor *iodesc; - - iodesc = (struct io_descriptor *) data; - - DEBUG14(printk("scsi(%ld): IO descriptor timeout, index=%x " - "signature=%08x, scheduling ISP abort.\n", iodesc->ha->host_no, - iodesc->idx, iodesc->signature)); - - qla2x00_free_iodesc(iodesc); - - qla_printk(KERN_WARNING, iodesc->ha, - "IO descriptor timeout. Scheduling ISP abort.\n"); - set_bit(ISP_ABORT_NEEDED, &iodesc->ha->dpc_flags); -} - -/** - * qla2x00_add_iodesc_timer() - Add and start a timer for an IO descriptor. - * @iodesc: io descriptor - * - * NOTE: - * The firmware shall timeout an outstanding mailbox IOCB in 2 * R_A_TOV (in - * tenths of a second) after it hits the wire. But, if there are any request - * resource contraints (i.e. during heavy I/O), exchanges can be held off for - * at most R_A_TOV. Therefore, the driver will wait 4 * R_A_TOV before - * scheduling a recovery (big hammer). - */ -static inline void -qla2x00_add_iodesc_timer(struct io_descriptor *iodesc) -{ - unsigned long timeout; - - timeout = (iodesc->ha->r_a_tov * 4) / 10; - init_timer(&iodesc->timer); - iodesc->timer.data = (unsigned long) iodesc; - iodesc->timer.expires = jiffies + (timeout * HZ); - iodesc->timer.function = - (void (*) (unsigned long)) qla2x00_iodesc_timeout; - add_timer(&iodesc->timer); -} - -/** - * IO descriptor support routines. - **/ - -/** - * qla2x00_update_login_fcport() - Update fcport data after login processing. - * @ha: HA context - * @mbxstat: Mailbox command status IOCB - * @fcport: port to update - */ -static inline void -qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat, - fc_port_t *fcport) -{ - if (le16_to_cpu(mbxstat->mb1) & BIT_0) { - fcport->port_type = FCT_INITIATOR; - } else { - fcport->port_type = FCT_TARGET; - if (le16_to_cpu(mbxstat->mb1) & BIT_1) { - fcport->flags |= FCF_TAPE_PRESENT; - } - } - fcport->login_retry = 0; - fcport->port_login_retry_count = ha->port_down_retry_count * - PORT_RETRY_TIME; - atomic_set(&fcport->port_down_timer, ha->port_down_retry_count * - PORT_RETRY_TIME); - fcport->flags |= FCF_FABRIC_DEVICE; - fcport->flags &= ~FCF_FAILOVER_NEEDED; - fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; - atomic_set(&fcport->state, FCS_ONLINE); - schedule_work(&fcport->rport_add_work); -} - - -/** - * Mailbox IOCB commands. - **/ - -/** - * qla2x00_get_mbx_iocb_entry() - Retrieve an IOCB from the request queue. - * @ha: HA context - * @handle: handle to io descriptor - * - * Returns a pointer to the reqest entry, or NULL, if none were available. - */ -static inline struct mbx_entry * -qla2x00_get_mbx_iocb_entry(scsi_qla_host_t *ha, uint32_t handle) -{ - uint16_t cnt; - struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - struct mbx_entry *mbxentry; - - mbxentry = NULL; - - if (ha->req_q_cnt < 3) { - cnt = qla2x00_debounce_register(ISP_REQ_Q_OUT(ha, reg)); - if (ha->req_ring_index < cnt) - ha->req_q_cnt = cnt - ha->req_ring_index; - else - ha->req_q_cnt = ha->request_q_length - - (ha->req_ring_index - cnt); - } - if (ha->req_q_cnt >= 3) { - mbxentry = (struct mbx_entry *)ha->request_ring_ptr; - - memset(mbxentry, 0, sizeof(struct mbx_entry)); - mbxentry->entry_type = MBX_IOCB_TYPE; - mbxentry->entry_count = 1; - mbxentry->sys_define1 = SOURCE_ASYNC_IOCB; - mbxentry->handle = handle; - } - return (mbxentry); -} - -/** - * qla2x00_send_abort_iocb() - Issue an abort IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @handle_to_abort: firmware handle to abort - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_abort_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - uint32_t handle_to_abort, int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build abort mailbox IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_ABORT_COMMAND); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - mbxentry->mb2 = LSW(handle_to_abort); - mbxentry->mb3 = MSW(handle_to_abort); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Abort IOCB (%08x) to [%x], aborting " - "%08x.\n", ha->host_no, iodesc->signature, - iodesc->remote_fcport->loop_id, handle_to_abort)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_abort_iocb_cb() - Abort IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_abort_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - DEBUG14(printk("scsi(%ld): Abort IOCB -- sent to [%x/%02x%02x%02x], " - "status=%x mb0=%x.\n", ha->host_no, iodesc->remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa, - le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0))); - - return (QLA_SUCCESS); -} - - -/** - * qla2x00_send_adisc_iocb() - Issue a Get Port Database IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_adisc_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build Get Port Database IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_GET_PORT_DATABASE); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - mbxentry->mb2 = cpu_to_le16(MSW(LSD(ha->iodesc_pd_dma))); - mbxentry->mb3 = cpu_to_le16(LSW(LSD(ha->iodesc_pd_dma))); - mbxentry->mb6 = cpu_to_le16(MSW(MSD(ha->iodesc_pd_dma))); - mbxentry->mb7 = cpu_to_le16(LSW(MSD(ha->iodesc_pd_dma))); - mbxentry->mb10 = __constant_cpu_to_le16(BIT_0); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Adisc IOCB (%08x) to [%x].\n", - ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_adisc_iocb_cb() - Get Port Database IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - fc_port_t *remote_fcport; - - remote_fcport = iodesc->remote_fcport; - - /* Ensure the port IDs are consistent. */ - if (remote_fcport->d_id.b24 != iodesc->d_id.b24) { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, remote port " - "id changed from [%02x%02x%02x] to [%02x%02x%02x].\n", - ha->host_no, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa)); - - return (QLA_SUCCESS); - } - - /* Only process the last command. */ - if (remote_fcport->iodesc_idx_sent != iodesc->idx) { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, sent to " - "[%02x%02x%02x], expected %x, received %x.\n", ha->host_no, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent, - iodesc->idx)); - - return (QLA_SUCCESS); - } - - if (le16_to_cpu(mbxstat->status) == CS_COMPLETE) { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking " - "[%x/%02x%02x%02x] online.\n", ha->host_no, - remote_fcport->loop_id, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa)); - - atomic_set(&remote_fcport->state, FCS_ONLINE); - } else { - DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking " - "[%x/%02x%02x%02x] lost, status=%x mb0=%x.\n", ha->host_no, - remote_fcport->loop_id, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa, - le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0))); - - if (atomic_read(&remote_fcport->state) != FCS_DEVICE_DEAD) - atomic_set(&remote_fcport->state, FCS_DEVICE_LOST); - } - remote_fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; - - return (QLA_SUCCESS); -} - - -/** - * qla2x00_send_logout_iocb() - Issue a fabric port logout IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_logout_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build fabric port logout mailbox IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGOUT_FABRIC_PORT); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Logout IOCB (%08x) to [%x].\n", - ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_logout_iocb_cb() - Fabric port logout IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_logout_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - DEBUG14(printk("scsi(%ld): Logout IOCB -- sent to [%x/%02x%02x%02x], " - "status=%x mb0=%x mb1=%x.\n", ha->host_no, - iodesc->remote_fcport->loop_id, - iodesc->remote_fcport->d_id.b.domain, - iodesc->remote_fcport->d_id.b.area, - iodesc->remote_fcport->d_id.b.al_pa, le16_to_cpu(mbxstat->status), - le16_to_cpu(mbxstat->mb0), le16_to_cpu(mbxstat->mb1))); - - return (QLA_SUCCESS); -} - - -/** - * qla2x00_send_login_iocb() - Issue a fabric port login IOCB to the firmware. - * @ha: HA context - * @iodesc: io descriptor - * @d_id: port id for device - * @ha_locked: is function called with the hardware lock - * - * Returns QLA_SUCCESS if the IOCB was issued. - */ -static int -qla2x00_send_login_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - port_id_t *d_id, int ha_locked) -{ - unsigned long flags = 0; - struct mbx_entry *mbxentry; - - /* Send marker if required. */ - if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS) - return (QLA_FUNCTION_FAILED); - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Build fabric port login mailbox IOCB. */ - mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature); - if (mbxentry == NULL) { - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return (QLA_FUNCTION_FAILED); - } - mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGIN_FABRIC_PORT); - mbxentry->mb1 = mbxentry->loop_id.extended = - cpu_to_le16(iodesc->remote_fcport->loop_id); - mbxentry->mb2 = cpu_to_le16(d_id->b.domain); - mbxentry->mb3 = cpu_to_le16(d_id->b.area << 8 | d_id->b.al_pa); - mbxentry->mb10 = __constant_cpu_to_le16(BIT_0); - wmb(); - - qla2x00_add_iodesc_timer(iodesc); - - /* Issue command to ISP. */ - qla2x00_isp_cmd(ha); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - DEBUG14(printk("scsi(%ld): Sending Login IOCB (%08x) to " - "[%x/%02x%02x%02x].\n", ha->host_no, iodesc->signature, - iodesc->remote_fcport->loop_id, d_id->b.domain, d_id->b.area, - d_id->b.al_pa)); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_send_login_iocb_cb() - Fabric port logout IOCB callback. - * @ha: HA context - * @iodesc: io descriptor - * @mbxstat: mailbox status IOCB - * - * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc - * will be used for a retry. - */ -static int -qla2x00_send_login_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc, - struct mbx_entry *mbxstat) -{ - int rval; - fc_port_t *fcport, *remote_fcport, *exist_fcport; - struct io_descriptor *abort_iodesc, *login_iodesc; - uint16_t status, mb[8]; - uint16_t reuse; - uint16_t remote_loopid; - port_id_t remote_did, inuse_did; - - remote_fcport = iodesc->remote_fcport; - - /* Only process the last command. */ - if (remote_fcport->iodesc_idx_sent != iodesc->idx) { - DEBUG14(printk("scsi(%ld): Login IOCB -- ignoring, sent to " - "[%02x%02x%02x], expected %x, received %x.\n", - ha->host_no, iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent, - iodesc->idx)); - - /* Free RSCN fcport resources. */ - if (remote_fcport->port_type == FCT_RSCN) { - DEBUG14(printk("scsi(%ld): Login IOCB -- Freeing RSCN " - "fcport %p [%x/%02x%02x%02x] given ignored Login " - "IOCB.\n", ha->host_no, remote_fcport, - remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - kfree(remote_fcport); - } - return (QLA_SUCCESS); - } - - status = le16_to_cpu(mbxstat->status); - mb[0] = le16_to_cpu(mbxstat->mb0); - mb[1] = le16_to_cpu(mbxstat->mb1); - mb[2] = le16_to_cpu(mbxstat->mb2); - mb[6] = le16_to_cpu(mbxstat->mb6); - mb[7] = le16_to_cpu(mbxstat->mb7); - - /* Good status? */ - if ((status == CS_COMPLETE || status == CS_COMPLETE_CHKCOND) && - mb[0] == MBS_COMMAND_COMPLETE) { - - DEBUG14(printk("scsi(%ld): Login IOCB -- status=%x mb1=%x pn=" - "%02x%02x%02x%02x%02x%02x%02x%02x.\n", ha->host_no, status, - mb[1], mbxstat->port_name[0], mbxstat->port_name[1], - mbxstat->port_name[2], mbxstat->port_name[3], - mbxstat->port_name[4], mbxstat->port_name[5], - mbxstat->port_name[6], mbxstat->port_name[7])); - - memcpy(remote_fcport->node_name, mbxstat->node_name, WWN_SIZE); - memcpy(remote_fcport->port_name, mbxstat->port_name, WWN_SIZE); - - /* Is the device already in our fcports list? */ - if (remote_fcport->port_type != FCT_RSCN) { - DEBUG14(printk("scsi(%ld): Login IOCB -- marking " - "[%x/%02x%02x%02x] online.\n", ha->host_no, - remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - qla2x00_update_login_fcport(ha, mbxstat, remote_fcport); - - return (QLA_SUCCESS); - } - - /* Does the RSCN portname already exist in our fcports list? */ - exist_fcport = NULL; - list_for_each_entry(fcport, &ha->fcports, list) { - if (memcmp(remote_fcport->port_name, fcport->port_name, - WWN_SIZE) == 0) { - exist_fcport = fcport; - break; - } - } - if (exist_fcport != NULL) { - DEBUG14(printk("scsi(%ld): Login IOCB -- found RSCN " - "fcport in fcports list [%p].\n", ha->host_no, - exist_fcport)); - - /* Abort any ADISC that could have been sent. */ - if (exist_fcport->iodesc_idx_sent != iodesc->idx && - exist_fcport->iodesc_idx_sent < - MAX_IO_DESCRIPTORS && - ha->io_descriptors[exist_fcport->iodesc_idx_sent]. - cb_idx == ADISC_PORT_IOCB_CB) { - - abort_iodesc = qla2x00_alloc_iodesc(ha); - if (abort_iodesc) { - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- issuing abort to outstanding " - "Adisc [%x/%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - abort_iodesc->cb_idx = ABORT_IOCB_CB; - abort_iodesc->d_id.b24 = - exist_fcport->d_id.b24; - abort_iodesc->remote_fcport = - exist_fcport; - exist_fcport->iodesc_idx_sent = - abort_iodesc->idx; - qla2x00_send_abort_iocb(ha, - abort_iodesc, ha->io_descriptors[ - exist_fcport->iodesc_idx_sent]. - signature, 1); - } else { - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- unable to abort outstanding " - "Adisc [%x/%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - } - } - - /* - * If the existing fcport is waiting to send an ADISC - * or LOGIN, then reuse remote fcport (RSCN) to - * continue waiting. - */ - reuse = 0; - remote_loopid = remote_fcport->loop_id; - remote_did.b24 = remote_fcport->d_id.b24; - if (exist_fcport->iodesc_idx_sent == - IODESC_ADISC_NEEDED || - exist_fcport->iodesc_idx_sent == - IODESC_LOGIN_NEEDED) { - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "existing fcport [%x/%02x%02x%02x] " - "waiting for IO descriptor, reuse RSCN " - "fcport.\n", ha->host_no, - exist_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - reuse++; - remote_fcport->iodesc_idx_sent = - exist_fcport->iodesc_idx_sent; - exist_fcport->iodesc_idx_sent = - IODESC_INVALID_INDEX; - remote_fcport->loop_id = exist_fcport->loop_id; - remote_fcport->d_id.b24 = - exist_fcport->d_id.b24; - } - - /* Logout the old loopid. */ - if (!reuse && - exist_fcport->loop_id != remote_fcport->loop_id && - exist_fcport->loop_id != FC_NO_LOOP_ID) { - login_iodesc = qla2x00_alloc_iodesc(ha); - if (login_iodesc) { - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- issuing logout to free old " - "loop id [%x/%02x%02x%02x].\n", - ha->host_no, exist_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - login_iodesc->cb_idx = - LOGOUT_PORT_IOCB_CB; - login_iodesc->d_id.b24 = - exist_fcport->d_id.b24; - login_iodesc->remote_fcport = - exist_fcport; - exist_fcport->iodesc_idx_sent = - login_iodesc->idx; - qla2x00_send_logout_iocb(ha, - login_iodesc, 1); - } else { - /* Ran out of IO descriptiors. */ - DEBUG14(printk("scsi(%ld): Login IOCB " - "-- unable to logout to free old " - "loop id [%x/%02x%02x%02x].\n", - ha->host_no, exist_fcport->loop_id, - exist_fcport->d_id.b.domain, - exist_fcport->d_id.b.area, - exist_fcport->d_id.b.al_pa)); - - exist_fcport->iodesc_idx_sent = - IODESC_INVALID_INDEX; - } - - } - - /* Update existing fcport with remote fcport info. */ - DEBUG14(printk("scsi(%ld): Login IOCB -- marking " - "existing fcport [%x/%02x%02x%02x] online.\n", - ha->host_no, remote_loopid, remote_did.b.domain, - remote_did.b.area, remote_did.b.al_pa)); - - memcpy(exist_fcport->node_name, - remote_fcport->node_name, WWN_SIZE); - exist_fcport->loop_id = remote_loopid; - exist_fcport->d_id.b24 = remote_did.b24; - qla2x00_update_login_fcport(ha, mbxstat, exist_fcport); - - /* Finally, free the remote (RSCN) fcport. */ - if (!reuse) { - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "Freeing RSCN fcport %p " - "[%x/%02x%02x%02x].\n", ha->host_no, - remote_fcport, remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - kfree(remote_fcport); - } - - return (QLA_SUCCESS); - } - - /* - * A new device has been added, move the RSCN fcport to our - * fcports list. - */ - DEBUG14(printk("scsi(%ld): Login IOCB -- adding RSCN fcport " - "[%x/%02x%02x%02x] to fcports list.\n", ha->host_no, - remote_fcport->loop_id, remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - remote_fcport->flags = (FCF_RLC_SUPPORT | FCF_RESCAN_NEEDED); - qla2x00_update_login_fcport(ha, mbxstat, remote_fcport); - list_add_tail(&remote_fcport->list, &ha->fcports); - set_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags); - } else { - /* Handle login failure. */ - if (remote_fcport->login_retry != 0) { - if (mb[0] == MBS_LOOP_ID_USED) { - inuse_did.b.domain = LSB(mb[1]); - inuse_did.b.area = MSB(mb[2]); - inuse_did.b.al_pa = LSB(mb[2]); - - DEBUG14(printk("scsi(%ld): Login IOCB -- loop " - "id [%x] used by port id [%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - inuse_did.b.domain, inuse_did.b.area, - inuse_did.b.al_pa)); - - if (remote_fcport->d_id.b24 == - INVALID_PORT_ID) { - /* - * Invalid port id means we are trying - * to login to a remote port with just - * a loop id without knowing about the - * port id. Copy the port id and try - * again. - */ - remote_fcport->d_id.b24 = inuse_did.b24; - iodesc->d_id.b24 = inuse_did.b24; - } else { - remote_fcport->loop_id++; - rval = qla2x00_find_new_loop_id(ha, - remote_fcport); - if (rval == QLA_FUNCTION_FAILED) { - /* No more loop ids. */ - return (QLA_SUCCESS); - } - } - } else if (mb[0] == MBS_PORT_ID_USED) { - /* - * Device has another loop ID. The firmware - * group recommends the driver perform an - * implicit login with the specified ID. - */ - DEBUG14(printk("scsi(%ld): Login IOCB -- port " - "id [%02x%02x%02x] already assigned to " - "loop id [%x].\n", ha->host_no, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, mb[1])); - - remote_fcport->loop_id = mb[1]; - - } else { - /* Unable to perform login, try again. */ - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "failed login [%x/%02x%02x%02x], status=%x " - "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n", - ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, status, mb[0], mb[1], - mb[2], mb[6], mb[7])); - } - - /* Reissue Login with the same IO descriptor. */ - iodesc->signature = - qla2x00_iodesc_to_handle(iodesc); - iodesc->cb_idx = LOGIN_PORT_IOCB_CB; - iodesc->d_id.b24 = remote_fcport->d_id.b24; - remote_fcport->iodesc_idx_sent = iodesc->idx; - remote_fcport->login_retry--; - - DEBUG14(printk("scsi(%ld): Login IOCB -- retrying " - "login to [%x/%02x%02x%02x] (%d).\n", ha->host_no, - remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa, - remote_fcport->login_retry)); - - qla2x00_send_login_iocb(ha, iodesc, - &remote_fcport->d_id, 1); - - return (QLA_FUNCTION_FAILED); - } else { - /* No more logins, mark device dead. */ - DEBUG14(printk("scsi(%ld): Login IOCB -- failed " - "login [%x/%02x%02x%02x] after retries, status=%x " - "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n", - ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa, status, mb[0], mb[1], - mb[2], mb[6], mb[7])); - - atomic_set(&remote_fcport->state, FCS_DEVICE_DEAD); - if (remote_fcport->port_type == FCT_RSCN) { - DEBUG14(printk("scsi(%ld): Login IOCB -- " - "Freeing dead RSCN fcport %p " - "[%x/%02x%02x%02x].\n", ha->host_no, - remote_fcport, remote_fcport->loop_id, - remote_fcport->d_id.b.domain, - remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - - list_del(&remote_fcport->list); - kfree(remote_fcport); - } - } - } - - return (QLA_SUCCESS); -} - - -/** - * IO descriptor processing routines. - **/ - -/** - * qla2x00_alloc_rscn_fcport() - Allocate an RSCN type fcport. - * @ha: HA context - * @flags: allocation flags - * - * Returns a pointer to the allocated RSCN fcport, or NULL, if none available. - */ -fc_port_t * -qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, gfp_t flags) -{ - fc_port_t *fcport; - - fcport = qla2x00_alloc_fcport(ha, flags); - if (fcport == NULL) - return (fcport); - - /* Setup RSCN fcport structure. */ - fcport->port_type = FCT_RSCN; - - return (fcport); -} - -/** - * qla2x00_handle_port_rscn() - Handle port RSCN. - * @ha: HA context - * @rscn_entry: RSCN entry - * @fcport: fcport entry to updated - * - * Returns QLA_SUCCESS if the port RSCN was handled. - */ -int -qla2x00_handle_port_rscn(scsi_qla_host_t *ha, uint32_t rscn_entry, - fc_port_t *known_fcport, int ha_locked) -{ - int rval; - port_id_t rscn_pid; - fc_port_t *fcport, *remote_fcport, *rscn_fcport; - struct io_descriptor *iodesc; - - remote_fcport = NULL; - rscn_fcport = NULL; - - /* Prepare port id based on incoming entries. */ - if (known_fcport) { - rscn_pid.b24 = known_fcport->d_id.b24; - remote_fcport = known_fcport; - - DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for " - "fcport [%02x%02x%02x].\n", ha->host_no, - remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area, - remote_fcport->d_id.b.al_pa)); - } else { - rscn_pid.b.domain = LSB(MSW(rscn_entry)); - rscn_pid.b.area = MSB(LSW(rscn_entry)); - rscn_pid.b.al_pa = LSB(LSW(rscn_entry)); - - DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for " - "port id [%02x%02x%02x].\n", ha->host_no, - rscn_pid.b.domain, rscn_pid.b.area, rscn_pid.b.al_pa)); - - /* - * Search fcport lists for a known entry at the specified port - * ID. - */ - list_for_each_entry(fcport, &ha->fcports, list) { - if (rscn_pid.b24 == fcport->d_id.b24) { - remote_fcport = fcport; - break; - } - } - list_for_each_entry(fcport, &ha->rscn_fcports, list) { - if (rscn_pid.b24 == fcport->d_id.b24) { - rscn_fcport = fcport; - break; - } - } - if (remote_fcport == NULL) - remote_fcport = rscn_fcport; - } - - /* - * If the port is already in our fcport list and online, send an ADISC - * to see if it's still alive. Issue login if a new fcport or the known - * fcport is currently offline. - */ - if (remote_fcport) { - /* - * No need to send request if the remote fcport is currently - * waiting for an available io descriptor. - */ - if (known_fcport == NULL && - (remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED || - remote_fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED)) { - /* - * If previous waiting io descriptor is an ADISC, then - * the new RSCN may come from a new remote fcport being - * plugged into the same location. - */ - if (remote_fcport->port_type == FCT_RSCN) { - remote_fcport->iodesc_idx_sent = - IODESC_LOGIN_NEEDED; - } else if (remote_fcport->iodesc_idx_sent == - IODESC_ADISC_NEEDED) { - fc_port_t *new_fcport; - - remote_fcport->iodesc_idx_sent = - IODESC_INVALID_INDEX; - - /* Create new fcport for later login. */ - new_fcport = qla2x00_alloc_rscn_fcport(ha, - ha_locked ? GFP_ATOMIC: GFP_KERNEL); - if (new_fcport) { - DEBUG14(printk("scsi(%ld): Handle RSCN " - "-- creating RSCN fcport %p for " - "future login.\n", ha->host_no, - new_fcport)); - - new_fcport->d_id.b24 = - remote_fcport->d_id.b24; - new_fcport->iodesc_idx_sent = - IODESC_LOGIN_NEEDED; - - list_add_tail(&new_fcport->list, - &ha->rscn_fcports); - set_bit(IODESC_PROCESS_NEEDED, - &ha->dpc_flags); - } else { - DEBUG14(printk("scsi(%ld): Handle RSCN " - "-- unable to allocate RSCN fcport " - "for future login.\n", - ha->host_no)); - } - } - return (QLA_SUCCESS); - } - - /* Send ADISC if the fcport is online */ - if (atomic_read(&remote_fcport->state) == FCS_ONLINE || - remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED) { - - atomic_set(&remote_fcport->state, FCS_DEVICE_LOST); - - iodesc = qla2x00_alloc_iodesc(ha); - if (iodesc == NULL) { - /* Mark fcport for later adisc processing */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- not " - "enough IO descriptors for Adisc, flag " - "for later processing.\n", ha->host_no)); - - remote_fcport->iodesc_idx_sent = - IODESC_ADISC_NEEDED; - set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); - - return (QLA_SUCCESS); - } - - iodesc->cb_idx = ADISC_PORT_IOCB_CB; - iodesc->d_id.b24 = rscn_pid.b24; - iodesc->remote_fcport = remote_fcport; - remote_fcport->iodesc_idx_sent = iodesc->idx; - qla2x00_send_adisc_iocb(ha, iodesc, ha_locked); - - return (QLA_SUCCESS); - } else if (remote_fcport->iodesc_idx_sent < - MAX_IO_DESCRIPTORS && - ha->io_descriptors[remote_fcport->iodesc_idx_sent].cb_idx == - ADISC_PORT_IOCB_CB) { - /* - * Receiving another RSCN while an ADISC is pending, - * abort the IOCB. Use the same descriptor for the - * abort. - */ - uint32_t handle_to_abort; - - iodesc = &ha->io_descriptors[ - remote_fcport->iodesc_idx_sent]; - qla2x00_remove_iodesc_timer(iodesc); - handle_to_abort = iodesc->signature; - iodesc->signature = qla2x00_iodesc_to_handle(iodesc); - iodesc->cb_idx = ABORT_IOCB_CB; - iodesc->d_id.b24 = remote_fcport->d_id.b24; - iodesc->remote_fcport = remote_fcport; - remote_fcport->iodesc_idx_sent = iodesc->idx; - - DEBUG14(printk("scsi(%ld): Handle RSCN -- issuing " - "abort to outstanding Adisc [%x/%02x%02x%02x].\n", - ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, - iodesc->d_id.b.al_pa)); - - qla2x00_send_abort_iocb(ha, iodesc, handle_to_abort, - ha_locked); - } - } - - /* We need to login to the remote port, find it. */ - if (known_fcport) { - remote_fcport = known_fcport; - } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID && - rscn_fcport->iodesc_idx_sent < MAX_IO_DESCRIPTORS && - ha->io_descriptors[rscn_fcport->iodesc_idx_sent].cb_idx == - LOGIN_PORT_IOCB_CB) { - /* - * Ignore duplicate RSCN on fcport which has already - * initiated a login IOCB. - */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- ignoring, login " - "already sent to [%02x%02x%02x].\n", ha->host_no, - rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area, - rscn_fcport->d_id.b.al_pa)); - - return (QLA_SUCCESS); - } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID && - rscn_fcport != remote_fcport) { - /* Reuse same rscn fcport. */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- reusing RSCN fcport " - "[%02x%02x%02x].\n", ha->host_no, - rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area, - rscn_fcport->d_id.b.al_pa)); - - remote_fcport = rscn_fcport; - } else { - /* Create new fcport for later login. */ - remote_fcport = qla2x00_alloc_rscn_fcport(ha, - ha_locked ? GFP_ATOMIC: GFP_KERNEL); - list_add_tail(&remote_fcport->list, &ha->rscn_fcports); - } - if (remote_fcport == NULL) - return (QLA_SUCCESS); - - /* Prepare fcport for login. */ - atomic_set(&remote_fcport->state, FCS_DEVICE_LOST); - remote_fcport->login_retry = 3; /* ha->login_retry_count; */ - remote_fcport->d_id.b24 = rscn_pid.b24; - - iodesc = qla2x00_alloc_iodesc(ha); - if (iodesc == NULL) { - /* Mark fcport for later adisc processing. */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- not enough IO " - "descriptors for Login, flag for later processing.\n", - ha->host_no)); - - remote_fcport->iodesc_idx_sent = IODESC_LOGIN_NEEDED; - set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); - - return (QLA_SUCCESS); - } - - if (known_fcport == NULL || rscn_pid.b24 != INVALID_PORT_ID) { - remote_fcport->loop_id = ha->min_external_loopid; - - rval = qla2x00_find_new_loop_id(ha, remote_fcport); - if (rval == QLA_FUNCTION_FAILED) { - /* No more loop ids, failed. */ - DEBUG14(printk("scsi(%ld): Handle RSCN -- no available " - "loop id to perform Login, failed.\n", - ha->host_no)); - - return (rval); - } - } - - iodesc->cb_idx = LOGIN_PORT_IOCB_CB; - iodesc->d_id.b24 = rscn_pid.b24; - iodesc->remote_fcport = remote_fcport; - remote_fcport->iodesc_idx_sent = iodesc->idx; - - DEBUG14(printk("scsi(%ld): Handle RSCN -- attempting login to " - "[%x/%02x%02x%02x].\n", ha->host_no, remote_fcport->loop_id, - iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa)); - - qla2x00_send_login_iocb(ha, iodesc, &rscn_pid, ha_locked); - - return (QLA_SUCCESS); -} - -/** - * qla2x00_process_iodesc() - Complete IO descriptor processing. - * @ha: HA context - * @mbxstat: Mailbox IOCB status - */ -void -qla2x00_process_iodesc(scsi_qla_host_t *ha, struct mbx_entry *mbxstat) -{ - int rval; - uint32_t signature; - fc_port_t *fcport; - struct io_descriptor *iodesc; - - signature = mbxstat->handle; - - DEBUG14(printk("scsi(%ld): Process IODesc -- processing %08x.\n", - ha->host_no, signature)); - - /* Retrieve proper IO descriptor. */ - iodesc = qla2x00_handle_to_iodesc(ha, signature); - if (iodesc == NULL) { - DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, " - "incorrect signature %08x.\n", ha->host_no, signature)); - - return; - } - - /* Stop IO descriptor timer. */ - qla2x00_remove_iodesc_timer(iodesc); - - /* Verify signature match. */ - if (iodesc->signature != signature) { - DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, " - "signature mismatch, sent %08x, received %08x.\n", - ha->host_no, iodesc->signature, signature)); - - return; - } - - /* Go with IOCB callback. */ - rval = iocb_function_cb_list[iodesc->cb_idx](ha, iodesc, mbxstat); - if (rval != QLA_SUCCESS) { - /* IO descriptor reused by callback. */ - return; - } - - qla2x00_free_iodesc(iodesc); - - if (test_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags)) { - /* Scan our fcports list for any RSCN requests. */ - list_for_each_entry(fcport, &ha->fcports, list) { - if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED || - fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) { - qla2x00_handle_port_rscn(ha, 0, fcport, 1); - return; - } - } - - /* Scan our RSCN fcports list for any RSCN requests. */ - list_for_each_entry(fcport, &ha->rscn_fcports, list) { - if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED || - fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) { - qla2x00_handle_port_rscn(ha, 0, fcport, 1); - return; - } - } - } - clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); -} - -/** - * qla2x00_cancel_io_descriptors() - Cancel all outstanding io descriptors. - * @ha: HA context - * - * This routine will also delete any RSCN entries related to the outstanding - * IO descriptors. - */ -void -qla2x00_cancel_io_descriptors(scsi_qla_host_t *ha) -{ - fc_port_t *fcport, *fcptemp; - - clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags); - - /* Abort all IO descriptors. */ - qla2x00_init_io_descriptors(ha); - - /* Reset all pending IO descriptors in fcports list. */ - list_for_each_entry(fcport, &ha->fcports, list) { - fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; - } - - /* Reset all pending IO descriptors in rscn fcports list. */ - list_for_each_entry_safe(fcport, fcptemp, &ha->rscn_fcports, list) { - DEBUG14(printk("scsi(%ld): Cancel IOs -- Freeing RSCN fcport " - "%p [%x/%02x%02x%02x].\n", ha->host_no, fcport, - fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, - fcport->d_id.b.al_pa)); - - list_del(&fcport->list); - kfree(fcport); - } -} diff --git a/drivers/scsi/qla2xxx/qla_settings.h b/drivers/scsi/qla2xxx/qla_settings.h index 363205c..249e4d9 100644 --- a/drivers/scsi/qla2xxx/qla_settings.h +++ b/drivers/scsi/qla2xxx/qla_settings.h @@ -16,7 +16,6 @@ #define MAX_RETRIES_OF_ISP_ABORT 5 /* Max time to wait for the loop to be in LOOP_READY state */ #define MAX_LOOP_TIMEOUT (60 * 5) -#define EH_ACTIVE 1 /* Error handler active */ /* * Some vendor subsystems do not recover properly after a device reset. Define diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 8b0121d..c71dbd5 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -97,7 +97,7 @@ qla2x00_write_nvram_word(scsi_qla_host_t { int count; uint16_t word; - uint32_t nv_cmd; + uint32_t nv_cmd, wait_cnt; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; qla2x00_nv_write(ha, NVR_DATA_OUT); @@ -127,7 +127,13 @@ qla2x00_write_nvram_word(scsi_qla_host_t /* Wait for NVRAM to become ready */ WRT_REG_WORD(®->nvram, NVR_SELECT); RD_REG_WORD(®->nvram); /* PCI Posting. */ + wait_cnt = NVR_WAIT_CNT; do { + if (!--wait_cnt) { + DEBUG9_10(printk("%s(%ld): NVRAM didn't go ready...\n", + __func__, ha->host_no)); + break; + } NVRAM_DELAY(); word = RD_REG_WORD(®->nvram); } while ((word & NVR_DATA_IN) == 0); @@ -301,16 +307,17 @@ qla2x00_clear_nvram_protection(scsi_qla_ { int ret, stat; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - uint32_t word; + uint32_t word, wait_cnt; uint16_t wprot, wprot_old; /* Clear NVRAM write protection. */ ret = QLA_FUNCTION_FAILED; - wprot_old = cpu_to_le16(qla2x00_get_nvram_word(ha, 0)); - stat = qla2x00_write_nvram_word_tmo(ha, 0, + + wprot_old = cpu_to_le16(qla2x00_get_nvram_word(ha, ha->nvram_base)); + stat = qla2x00_write_nvram_word_tmo(ha, ha->nvram_base, __constant_cpu_to_le16(0x1234), 100000); - wprot = cpu_to_le16(qla2x00_get_nvram_word(ha, 0)); - if (stat != QLA_SUCCESS || wprot != __constant_cpu_to_le16(0x1234)) { + wprot = cpu_to_le16(qla2x00_get_nvram_word(ha, ha->nvram_base)); + if (stat != QLA_SUCCESS || wprot != 0x1234) { /* Write enable. */ qla2x00_nv_write(ha, NVR_DATA_OUT); qla2x00_nv_write(ha, 0); @@ -341,14 +348,22 @@ qla2x00_clear_nvram_protection(scsi_qla_ /* Wait for NVRAM to become ready. */ WRT_REG_WORD(®->nvram, NVR_SELECT); RD_REG_WORD(®->nvram); /* PCI Posting. */ + wait_cnt = NVR_WAIT_CNT; do { + if (!--wait_cnt) { + DEBUG9_10(printk("%s(%ld): NVRAM didn't go " + "ready...\n", __func__, + ha->host_no)); + break; + } NVRAM_DELAY(); word = RD_REG_WORD(®->nvram); } while ((word & NVR_DATA_IN) == 0); - ret = QLA_SUCCESS; + if (wait_cnt) + ret = QLA_SUCCESS; } else - qla2x00_write_nvram_word(ha, 0, wprot_old); + qla2x00_write_nvram_word(ha, ha->nvram_base, wprot_old); return ret; } @@ -357,7 +372,7 @@ static void qla2x00_set_nvram_protection(scsi_qla_host_t *ha, int stat) { struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - uint32_t word; + uint32_t word, wait_cnt; if (stat != QLA_SUCCESS) return; @@ -393,7 +408,13 @@ qla2x00_set_nvram_protection(scsi_qla_ho /* Wait for NVRAM to become ready. */ WRT_REG_WORD(®->nvram, NVR_SELECT); RD_REG_WORD(®->nvram); /* PCI Posting. */ + wait_cnt = NVR_WAIT_CNT; do { + if (!--wait_cnt) { + DEBUG9_10(printk("%s(%ld): NVRAM didn't go ready...\n", + __func__, ha->host_no)); + break; + } NVRAM_DELAY(); word = RD_REG_WORD(®->nvram); } while ((word & NVR_DATA_IN) == 0); @@ -500,6 +521,20 @@ qla24xx_get_flash_manufacturer(scsi_qla_ ids = qla24xx_read_flash_dword(ha, flash_data_to_access_addr(0xd03ab)); *man_id = LSB(ids); *flash_id = MSB(ids); + + /* Check if man_id and flash_id are valid. */ + if (ids != 0xDEADDEAD && (*man_id == 0 || *flash_id == 0)) { + /* Read information using 0x9f opcode + * Device ID, Mfg ID would be read in the format: + * + * Example: ATMEL 0x00 01 45 1F + * Extract MFG and Dev ID from last two bytes. + */ + ids = qla24xx_read_flash_dword(ha, + flash_data_to_access_addr(0xd009f)); + *man_id = LSB(ids); + *flash_id = MSB(ids); + } } int @@ -508,8 +543,8 @@ qla24xx_write_flash_data(scsi_qla_host_t { int ret; uint32_t liter; - uint32_t sec_mask, rest_addr, conf_addr; - uint32_t fdata; + uint32_t sec_mask, rest_addr, conf_addr, sec_end_mask; + uint32_t fdata, findex ; uint8_t man_id, flash_id; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; @@ -519,6 +554,7 @@ qla24xx_write_flash_data(scsi_qla_host_t DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__, ha->host_no, man_id, flash_id)); + sec_end_mask = 0; conf_addr = flash_conf_to_access_addr(0x03d8); switch (man_id) { case 0xbf: /* STT flash. */ @@ -531,6 +567,12 @@ qla24xx_write_flash_data(scsi_qla_host_t rest_addr = 0x3fff; sec_mask = 0x3c000; break; + case 0x1f: // Atmel 26DF081A + rest_addr = 0x0fff; + sec_mask = 0xff000; + sec_end_mask = 0x003ff; + conf_addr = flash_conf_to_access_addr(0x0320); + break; default: /* Default to 64 kb sector size. */ rest_addr = 0x3fff; @@ -545,11 +587,30 @@ qla24xx_write_flash_data(scsi_qla_host_t /* Disable flash write-protection. */ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0); + /* Some flash parts need an additional zero-write to clear bits.*/ + qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0); do { /* Loop once to provide quick error exit. */ for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { + if (man_id == 0x1f) { + findex = faddr << 2; + fdata = findex & sec_mask; + } else { + findex = faddr; + fdata = (findex & sec_mask) << 2; + } + /* Are we at the beginning of a sector? */ - if ((faddr & rest_addr) == 0) { + if ((findex & rest_addr) == 0) { + /* + * Do sector unprotect at 4K boundry for Atmel + * part. + */ + if (man_id == 0x1f) + qla24xx_write_flash_dword(ha, + flash_conf_to_access_addr(0x0339), + (fdata & 0xff00) | ((fdata << 16) & + 0xff0000) | ((fdata >> 16) & 0xff)); fdata = (faddr & sec_mask) << 2; ret = qla24xx_write_flash_dword(ha, conf_addr, (fdata & 0xff00) |((fdata << 16) & @@ -570,6 +631,14 @@ qla24xx_write_flash_data(scsi_qla_host_t ha->host_no, faddr, *dwptr)); break; } + + /* Do sector protect at 4K boundry for Atmel part. */ + if (man_id == 0x1f && + ((faddr & sec_end_mask) == 0x3ff)) + qla24xx_write_flash_dword(ha, + flash_conf_to_access_addr(0x0336), + (fdata & 0xff00) | ((fdata << 16) & + 0xff0000) | ((fdata >> 16) & 0xff)); } } while (0); diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index d537192..6b31552 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,9 +7,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.01.04-k" +#define QLA2XXX_VERSION "8.01.05-k2" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 1 -#define QLA_DRIVER_PATCH_VER 4 +#define QLA_DRIVER_PATCH_VER 5 #define QLA_DRIVER_BETA_VER 0 diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index c7e78dc..329ead2 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -1,6 +1,6 @@ /* qlogicpti.c: Performance Technologies QlogicISP sbus card driver. * - * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu) + * Copyright (C) 1996, 2006 David S. Miller (davem@davemloft.net) * * A lot of this driver was directly stolen from Erik H. Moe's PCI * Qlogic ISP driver. Mucho kudos to him for this code. @@ -43,12 +43,9 @@ #include #include #include #include -#include #include #include - - #define MAX_TARGETS 16 #define MAX_LUNS 8 /* 32 for 1.31 F/W */ @@ -58,7 +55,6 @@ #include "qlogicpti_asm.c" static struct qlogicpti *qptichain = NULL; static DEFINE_SPINLOCK(qptichain_lock); -static int qptis_running = 0; #define PACKB(a, b) (((a)<<4)|(b)) @@ -132,7 +128,7 @@ static const u_char mbox_param[] = { PACKB(0, 0) /* 0x0042 */ }; -#define MAX_MBOX_COMMAND (sizeof(mbox_param)/sizeof(u_short)) +#define MAX_MBOX_COMMAND ARRAY_SIZE(mbox_param) /* queue length's _must_ be power of two: */ #define QUEUE_DEPTH(in, out, ql) ((in - out) & (ql)) @@ -725,7 +721,7 @@ static int __init qpti_register_irq(stru SA_SHIRQ, "Qlogic/PTI", qpti)) goto fail; - printk("qpti%d: IRQ %s ", qpti->qpti_id, __irq_itoa(qpti->irq)); + printk("qpti%d: IRQ %d ", qpti->qpti_id, qpti->irq); return 0; @@ -816,180 +812,13 @@ #define QSIZE(entries) (((entries) + 1) return 0; } -/* Detect all PTI Qlogic ISP's in the machine. */ -static int __init qlogicpti_detect(struct scsi_host_template *tpnt) -{ - struct qlogicpti *qpti; - struct Scsi_Host *qpti_host; - struct sbus_bus *sbus; - struct sbus_dev *sdev; - int nqptis = 0, nqptis_in_use = 0; - - tpnt->proc_name = "qlogicpti"; - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - /* Is this a red snapper? */ - if (strcmp(sdev->prom_name, "ptisp") && - strcmp(sdev->prom_name, "PTI,ptisp") && - strcmp(sdev->prom_name, "QLGC,isp") && - strcmp(sdev->prom_name, "SUNW,isp")) - continue; - - /* Sometimes Antares cards come up not completely - * setup, and we get a report of a zero IRQ. - * Skip over them in such cases so we survive. - */ - if (sdev->irqs[0] == 0) { - printk("qpti%d: Adapter reports no interrupt, " - "skipping over this card.", nqptis); - continue; - } - - /* Yep, register and allocate software state. */ - qpti_host = scsi_register(tpnt, sizeof(struct qlogicpti)); - if (!qpti_host) { - printk("QPTI: Cannot register PTI Qlogic ISP SCSI host"); - continue; - } - qpti = (struct qlogicpti *) qpti_host->hostdata; - - /* We are wide capable, 16 targets. */ - qpti_host->max_id = MAX_TARGETS; - - /* Setup back pointers and misc. state. */ - qpti->qhost = qpti_host; - qpti->sdev = sdev; - qpti->qpti_id = nqptis++; - qpti->prom_node = sdev->prom_node; - prom_getstring(qpti->prom_node, "name", - qpti->prom_name, - sizeof(qpti->prom_name)); - - /* This is not correct, actually. There's a switch - * on the PTI cards that put them into "emulation" - * mode- i.e., report themselves as QLGC,isp - * instead of PTI,ptisp. The only real substantive - * difference between non-pti and pti cards is - * the tmon register. Which is possibly even - * there for Qlogic cards, but non-functional. - */ - qpti->is_pti = (strcmp (qpti->prom_name, "QLGC,isp") != 0); - - qpti_chain_add(qpti); - if (qpti_map_regs(qpti) < 0) - goto fail_unlink; - - if (qpti_register_irq(qpti) < 0) - goto fail_unmap_regs; - - qpti_get_scsi_id(qpti); - qpti_get_bursts(qpti); - qpti_get_clock(qpti); - - /* Clear out scsi_cmnd array. */ - memset(qpti->cmd_slots, 0, sizeof(qpti->cmd_slots)); - - if (qpti_map_queues(qpti) < 0) - goto fail_free_irq; - - /* Load the firmware. */ - if (qlogicpti_load_firmware(qpti)) - goto fail_unmap_queues; - if (qpti->is_pti) { - /* Check the PTI status reg. */ - if (qlogicpti_verify_tmon(qpti)) - goto fail_unmap_queues; - } - - /* Reset the ISP and init res/req queues. */ - if (qlogicpti_reset_hardware(qpti_host)) - goto fail_unmap_queues; - - printk("(Firmware v%d.%d.%d)", qpti->fware_majrev, - qpti->fware_minrev, qpti->fware_micrev); - { - char buffer[60]; - - prom_getstring (qpti->prom_node, - "isp-fcode", buffer, 60); - if (buffer[0]) - printk("(Firmware %s)", buffer); - if (prom_getbool(qpti->prom_node, "differential")) - qpti->differential = 1; - } - - printk (" [%s Wide, using %s interface]\n", - (qpti->ultra ? "Ultra" : "Fast"), - (qpti->differential ? "differential" : "single ended")); - - nqptis_in_use++; - continue; - - fail_unmap_queues: -#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) - sbus_free_consistent(qpti->sdev, - QSIZE(RES_QUEUE_LEN), - qpti->res_cpu, qpti->res_dvma); - sbus_free_consistent(qpti->sdev, - QSIZE(QLOGICPTI_REQ_QUEUE_LEN), - qpti->req_cpu, qpti->req_dvma); -#undef QSIZE - fail_free_irq: - free_irq(qpti->irq, qpti); - - fail_unmap_regs: - sbus_iounmap(qpti->qregs, - qpti->sdev->reg_addrs[0].reg_size); - if (qpti->is_pti) - sbus_iounmap(qpti->sreg, sizeof(unsigned char)); - fail_unlink: - qpti_chain_del(qpti); - scsi_unregister(qpti->qhost); - } - } - if (nqptis) - printk("QPTI: Total of %d PTI Qlogic/ISP hosts found, %d actually in use.\n", - nqptis, nqptis_in_use); - qptis_running = nqptis_in_use; - return nqptis; -} - -static int qlogicpti_release(struct Scsi_Host *host) -{ - struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; - - /* Remove visibility from IRQ handlers. */ - qpti_chain_del(qpti); - - /* Shut up the card. */ - sbus_writew(0, qpti->qregs + SBUS_CTRL); - - /* Free IRQ handler and unmap Qlogic,ISP and PTI status regs. */ - free_irq(qpti->irq, qpti); - -#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) - sbus_free_consistent(qpti->sdev, - QSIZE(RES_QUEUE_LEN), - qpti->res_cpu, qpti->res_dvma); - sbus_free_consistent(qpti->sdev, - QSIZE(QLOGICPTI_REQ_QUEUE_LEN), - qpti->req_cpu, qpti->req_dvma); -#undef QSIZE - - sbus_iounmap(qpti->qregs, qpti->sdev->reg_addrs[0].reg_size); - if (qpti->is_pti) - sbus_iounmap(qpti->sreg, sizeof(unsigned char)); - - return 0; -} - const char *qlogicpti_info(struct Scsi_Host *host) { static char buf[80]; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; - sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %p", - __irq_itoa(qpti->qhost->irq), qpti->qregs); + sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %d regs at %p", + qpti->qhost->irq, qpti->qregs); return buf; } @@ -1552,9 +1381,9 @@ static int qlogicpti_reset(struct scsi_c return return_status; } -static struct scsi_host_template driver_template = { - .detect = qlogicpti_detect, - .release = qlogicpti_release, +static struct scsi_host_template qpti_template = { + .module = THIS_MODULE, + .name = "qlogicpti", .info = qlogicpti_info, .queuecommand = qlogicpti_queuecommand_slow, .eh_abort_handler = qlogicpti_abort, @@ -1566,8 +1395,189 @@ static struct scsi_host_template driver_ .use_clustering = ENABLE_CLUSTERING, }; +static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_device_id *match) +{ + static int nqptis; + struct sbus_dev *sdev = to_sbus_device(&dev->dev); + struct device_node *dp = dev->node; + struct scsi_host_template *tpnt = match->data; + struct Scsi_Host *host; + struct qlogicpti *qpti; + char *fcode; + + /* Sometimes Antares cards come up not completely + * setup, and we get a report of a zero IRQ. + */ + if (sdev->irqs[0] == 0) + return -ENODEV; + + host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); + if (!host) + return -ENOMEM; + + qpti = (struct qlogicpti *) host->hostdata; + + host->max_id = MAX_TARGETS; + qpti->qhost = host; + qpti->sdev = sdev; + qpti->qpti_id = nqptis; + qpti->prom_node = sdev->prom_node; + strcpy(qpti->prom_name, sdev->ofdev.node->name); + qpti->is_pti = strcmp(qpti->prom_name, "QLGC,isp"); + + if (qpti_map_regs(qpti) < 0) + goto fail_unlink; + + if (qpti_register_irq(qpti) < 0) + goto fail_unmap_regs; + + qpti_get_scsi_id(qpti); + qpti_get_bursts(qpti); + qpti_get_clock(qpti); + + /* Clear out scsi_cmnd array. */ + memset(qpti->cmd_slots, 0, sizeof(qpti->cmd_slots)); + + if (qpti_map_queues(qpti) < 0) + goto fail_free_irq; + + /* Load the firmware. */ + if (qlogicpti_load_firmware(qpti)) + goto fail_unmap_queues; + if (qpti->is_pti) { + /* Check the PTI status reg. */ + if (qlogicpti_verify_tmon(qpti)) + goto fail_unmap_queues; + } + + /* Reset the ISP and init res/req queues. */ + if (qlogicpti_reset_hardware(host)) + goto fail_unmap_queues; + + if (scsi_add_host(host, &dev->dev)) + goto fail_unmap_queues; + + printk("(Firmware v%d.%d.%d)", qpti->fware_majrev, + qpti->fware_minrev, qpti->fware_micrev); + + fcode = of_get_property(dp, "isp-fcode", NULL); + if (fcode && fcode[0]) + printk("(Firmware %s)", fcode); + if (of_find_property(dp, "differential", NULL) != NULL) + qpti->differential = 1; + + printk (" [%s Wide, using %s interface]\n", + (qpti->ultra ? "Ultra" : "Fast"), + (qpti->differential ? "differential" : "single ended")); + + dev_set_drvdata(&sdev->ofdev.dev, qpti); + + qpti_chain_add(qpti); + + scsi_scan_host(host); + nqptis++; + + return 0; + +fail_unmap_queues: +#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) + sbus_free_consistent(qpti->sdev, + QSIZE(RES_QUEUE_LEN), + qpti->res_cpu, qpti->res_dvma); + sbus_free_consistent(qpti->sdev, + QSIZE(QLOGICPTI_REQ_QUEUE_LEN), + qpti->req_cpu, qpti->req_dvma); +#undef QSIZE + +fail_unmap_regs: + sbus_iounmap(qpti->qregs, + qpti->sdev->reg_addrs[0].reg_size); + if (qpti->is_pti) + sbus_iounmap(qpti->sreg, sizeof(unsigned char)); + +fail_free_irq: + free_irq(qpti->irq, qpti); + +fail_unlink: + scsi_host_put(host); + + return -ENODEV; +} + +static int __devexit qpti_sbus_remove(struct of_device *dev) +{ + struct qlogicpti *qpti = dev_get_drvdata(&dev->dev); + + qpti_chain_del(qpti); + + scsi_remove_host(qpti->qhost); + + /* Shut up the card. */ + sbus_writew(0, qpti->qregs + SBUS_CTRL); + + /* Free IRQ handler and unmap Qlogic,ISP and PTI status regs. */ + free_irq(qpti->irq, qpti); + +#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) + sbus_free_consistent(qpti->sdev, + QSIZE(RES_QUEUE_LEN), + qpti->res_cpu, qpti->res_dvma); + sbus_free_consistent(qpti->sdev, + QSIZE(QLOGICPTI_REQ_QUEUE_LEN), + qpti->req_cpu, qpti->req_dvma); +#undef QSIZE + + sbus_iounmap(qpti->qregs, qpti->sdev->reg_addrs[0].reg_size); + if (qpti->is_pti) + sbus_iounmap(qpti->sreg, sizeof(unsigned char)); + + scsi_host_put(qpti->qhost); + + return 0; +} + +static struct of_device_id qpti_match[] = { + { + .name = "ptisp", + .data = &qpti_template, + }, + { + .name = "PTI,ptisp", + .data = &qpti_template, + }, + { + .name = "QLGC,isp", + .data = &qpti_template, + }, + { + .name = "SUNW,isp", + .data = &qpti_template, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, qpti_match); + +static struct of_platform_driver qpti_sbus_driver = { + .name = "qpti", + .match_table = qpti_match, + .probe = qpti_sbus_probe, + .remove = __devexit_p(qpti_sbus_remove), +}; -#include "scsi_module.c" +static int __init qpti_init(void) +{ + return of_register_driver(&qpti_sbus_driver, &sbus_bus_type); +} + +static void __exit qpti_exit(void) +{ + of_unregister_driver(&qpti_sbus_driver); +} +MODULE_DESCRIPTION("QlogicISP SBUS driver"); +MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); MODULE_LICENSE("GPL"); +MODULE_VERSION("2.0"); +module_init(qpti_init); +module_exit(qpti_exit); diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index 50c398a..327b33a 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c @@ -131,7 +131,7 @@ static const char *raid_state_name(enum int i; char *name = NULL; - for (i = 0; i < sizeof(raid_states)/sizeof(raid_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(raid_states); i++) { if (raid_states[i].value == state) { name = raid_states[i].name; break; @@ -161,7 +161,7 @@ static const char *raid_level_name(enum int i; char *name = NULL; - for (i = 0; i < sizeof(raid_levels)/sizeof(raid_levels[0]); i++) { + for (i = 0; i < ARRAY_SIZE(raid_levels); i++) { if (raid_levels[i].value == level) { name = raid_levels[i].name; break; diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index f16f92a..4a71578 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -93,7 +93,7 @@ enum { MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | - ATA_FLAG_NO_ATAPI), + ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING), MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE, CRQB_FLAG_READ = (1 << 0), @@ -272,33 +272,33 @@ enum chip_type { /* Command ReQuest Block: 32B */ struct mv_crqb { - u32 sg_addr; - u32 sg_addr_hi; - u16 ctrl_flags; - u16 ata_cmd[11]; + __le32 sg_addr; + __le32 sg_addr_hi; + __le16 ctrl_flags; + __le16 ata_cmd[11]; }; struct mv_crqb_iie { - u32 addr; - u32 addr_hi; - u32 flags; - u32 len; - u32 ata_cmd[4]; + __le32 addr; + __le32 addr_hi; + __le32 flags; + __le32 len; + __le32 ata_cmd[4]; }; /* Command ResPonse Block: 8B */ struct mv_crpb { - u16 id; - u16 flags; - u32 tmstmp; + __le16 id; + __le16 flags; + __le32 tmstmp; }; /* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */ struct mv_sg { - u32 addr; - u32 flags_size; - u32 addr_hi; - u32 reserved; + __le32 addr; + __le32 flags_size; + __le32 addr_hi; + __le32 reserved; }; struct mv_port_priv { @@ -390,6 +390,7 @@ static struct scsi_host_template mv_sht .proc_name = DRV_NAME, .dma_boundary = MV_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -406,6 +407,7 @@ static const struct ata_port_operations .qc_prep = mv_qc_prep, .qc_issue = mv_qc_issue, + .data_xfer = ata_mmio_data_xfer, .eng_timeout = mv_eng_timeout, @@ -433,6 +435,7 @@ static const struct ata_port_operations .qc_prep = mv_qc_prep, .qc_issue = mv_qc_issue, + .data_xfer = ata_mmio_data_xfer, .eng_timeout = mv_eng_timeout, @@ -683,7 +686,7 @@ static void mv_stop_dma(struct ata_port } if (EDMA_EN & reg) { - printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id); + ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); /* FIXME: Consider doing a reset here to recover */ } } @@ -1028,7 +1031,7 @@ static inline unsigned mv_inc_q_index(un return (index + 1) & MV_MAX_Q_DEPTH_MASK; } -static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last) +static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) { u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS | (last ? CRQB_CMD_LAST : 0); @@ -1051,7 +1054,7 @@ static void mv_qc_prep(struct ata_queued { struct ata_port *ap = qc->ap; struct mv_port_priv *pp = ap->private_data; - u16 *cw; + __le16 *cw; struct ata_taskfile *tf; u16 flags = 0; unsigned in_index; @@ -1307,8 +1310,8 @@ static void mv_err_intr(struct ata_port edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); if (EDMA_ERR_SERR & edma_err_cause) { - serr = scr_read(ap, SCR_ERROR); - scr_write_flush(ap, SCR_ERROR, serr); + sata_scr_read(ap, SCR_ERROR, &serr); + sata_scr_write_flush(ap, SCR_ERROR, serr); } if (EDMA_ERR_SELF_DIS & edma_err_cause) { struct mv_port_priv *pp = ap->private_data; @@ -1377,7 +1380,7 @@ static void mv_host_intr(struct ata_host /* Note that DEV_IRQ might happen spuriously during EDMA, * and should be ignored in such cases. * The cause of this is still under investigation. - */ + */ if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { /* EDMA: check for response queue interrupt */ if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { @@ -1398,7 +1401,7 @@ static void mv_host_intr(struct ata_host } } - if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) + if (ap && (ap->flags & ATA_FLAG_DISABLED)) continue; err_mask = ac_err_mask(ata_status); @@ -1419,7 +1422,7 @@ static void mv_host_intr(struct ata_host VPRINTK("port %u IRQ found for qc, " "ata_status 0x%x\n", port,ata_status); /* mark qc status appropriately */ - if (!(qc->tf.ctl & ATA_NIEN)) { + if (!(qc->tf.flags & ATA_TFLAG_POLLING)) { qc->err_mask |= err_mask; ata_qc_complete(qc); } @@ -1949,15 +1952,16 @@ static void __mv_phy_reset(struct ata_po /* Issue COMRESET via SControl */ comreset_retry: - scr_write_flush(ap, SCR_CONTROL, 0x301); + sata_scr_write_flush(ap, SCR_CONTROL, 0x301); __msleep(1, can_sleep); - scr_write_flush(ap, SCR_CONTROL, 0x300); + sata_scr_write_flush(ap, SCR_CONTROL, 0x300); __msleep(20, can_sleep); timeout = jiffies + msecs_to_jiffies(200); do { - sstatus = scr_read(ap, SCR_STATUS) & 0x3; + sata_scr_read(ap, SCR_STATUS, &sstatus); + sstatus &= 0x3; if ((sstatus == 3) || (sstatus == 0)) break; @@ -1974,11 +1978,12 @@ comreset_retry: "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); - if (sata_dev_present(ap)) { + if (ata_port_online(ap)) { ata_port_probe(ap); } else { - printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n", - ap->id, scr_read(ap, SCR_STATUS)); + sata_scr_read(ap, SCR_STATUS, &sstatus); + ata_port_printk(ap, KERN_INFO, + "no device found (phy stat %08x)\n", sstatus); ata_port_disable(ap); return; } @@ -2005,7 +2010,7 @@ comreset_retry: tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr); dev->class = ata_dev_classify(&tf); - if (!ata_dev_present(dev)) { + if (!ata_dev_enabled(dev)) { VPRINTK("Port disabled post-sig: No device present.\n"); ata_port_disable(ap); } @@ -2037,7 +2042,7 @@ static void mv_eng_timeout(struct ata_po struct ata_queued_cmd *qc; unsigned long flags; - printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id); + ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n"); DPRINTK("All regs @ start of eng_timeout\n"); mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no, to_pci_dev(ap->host_set->dev)); diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 9f55308..d18e7e0 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -44,7 +44,7 @@ #include #include #define DRV_NAME "sata_nv" -#define DRV_VERSION "0.8" +#define DRV_VERSION "0.9" enum { NV_PORTS = 2, @@ -54,40 +54,25 @@ enum { NV_PORT0_SCR_REG_OFFSET = 0x00, NV_PORT1_SCR_REG_OFFSET = 0x40, + /* INT_STATUS/ENABLE */ NV_INT_STATUS = 0x10, - NV_INT_STATUS_CK804 = 0x440, - NV_INT_STATUS_PDEV_INT = 0x01, - NV_INT_STATUS_PDEV_PM = 0x02, - NV_INT_STATUS_PDEV_ADDED = 0x04, - NV_INT_STATUS_PDEV_REMOVED = 0x08, - NV_INT_STATUS_SDEV_INT = 0x10, - NV_INT_STATUS_SDEV_PM = 0x20, - NV_INT_STATUS_SDEV_ADDED = 0x40, - NV_INT_STATUS_SDEV_REMOVED = 0x80, - NV_INT_STATUS_PDEV_HOTPLUG = (NV_INT_STATUS_PDEV_ADDED | - NV_INT_STATUS_PDEV_REMOVED), - NV_INT_STATUS_SDEV_HOTPLUG = (NV_INT_STATUS_SDEV_ADDED | - NV_INT_STATUS_SDEV_REMOVED), - NV_INT_STATUS_HOTPLUG = (NV_INT_STATUS_PDEV_HOTPLUG | - NV_INT_STATUS_SDEV_HOTPLUG), - NV_INT_ENABLE = 0x11, + NV_INT_STATUS_CK804 = 0x440, NV_INT_ENABLE_CK804 = 0x441, - NV_INT_ENABLE_PDEV_MASK = 0x01, - NV_INT_ENABLE_PDEV_PM = 0x02, - NV_INT_ENABLE_PDEV_ADDED = 0x04, - NV_INT_ENABLE_PDEV_REMOVED = 0x08, - NV_INT_ENABLE_SDEV_MASK = 0x10, - NV_INT_ENABLE_SDEV_PM = 0x20, - NV_INT_ENABLE_SDEV_ADDED = 0x40, - NV_INT_ENABLE_SDEV_REMOVED = 0x80, - NV_INT_ENABLE_PDEV_HOTPLUG = (NV_INT_ENABLE_PDEV_ADDED | - NV_INT_ENABLE_PDEV_REMOVED), - NV_INT_ENABLE_SDEV_HOTPLUG = (NV_INT_ENABLE_SDEV_ADDED | - NV_INT_ENABLE_SDEV_REMOVED), - NV_INT_ENABLE_HOTPLUG = (NV_INT_ENABLE_PDEV_HOTPLUG | - NV_INT_ENABLE_SDEV_HOTPLUG), + /* INT_STATUS/ENABLE bits */ + NV_INT_DEV = 0x01, + NV_INT_PM = 0x02, + NV_INT_ADDED = 0x04, + NV_INT_REMOVED = 0x08, + + NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */ + + NV_INT_ALL = 0x0f, + NV_INT_MASK = NV_INT_DEV | + NV_INT_ADDED | NV_INT_REMOVED, + + /* INT_CONFIG */ NV_INT_CONFIG = 0x12, NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI @@ -97,23 +82,27 @@ enum { }; static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static irqreturn_t nv_interrupt (int irq, void *dev_instance, - struct pt_regs *regs); +static void nv_ck804_host_stop(struct ata_host_set *host_set); +static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); +static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); +static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); -static void nv_host_stop (struct ata_host_set *host_set); -static void nv_enable_hotplug(struct ata_probe_ent *probe_ent); -static void nv_disable_hotplug(struct ata_host_set *host_set); -static int nv_check_hotplug(struct ata_host_set *host_set); -static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent); -static void nv_disable_hotplug_ck804(struct ata_host_set *host_set); -static int nv_check_hotplug_ck804(struct ata_host_set *host_set); + +static void nv_nf2_freeze(struct ata_port *ap); +static void nv_nf2_thaw(struct ata_port *ap); +static void nv_ck804_freeze(struct ata_port *ap); +static void nv_ck804_thaw(struct ata_port *ap); +static void nv_error_handler(struct ata_port *ap); enum nv_host_type { GENERIC, NFORCE2, - NFORCE3, + NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */ CK804 }; @@ -140,6 +129,16 @@ static const struct pci_device_id nv_pci PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC }, @@ -149,46 +148,6 @@ static const struct pci_device_id nv_pci { 0, } /* terminate list */ }; -struct nv_host_desc -{ - enum nv_host_type host_type; - void (*enable_hotplug)(struct ata_probe_ent *probe_ent); - void (*disable_hotplug)(struct ata_host_set *host_set); - int (*check_hotplug)(struct ata_host_set *host_set); - -}; -static struct nv_host_desc nv_device_tbl[] = { - { - .host_type = GENERIC, - .enable_hotplug = NULL, - .disable_hotplug= NULL, - .check_hotplug = NULL, - }, - { - .host_type = NFORCE2, - .enable_hotplug = nv_enable_hotplug, - .disable_hotplug= nv_disable_hotplug, - .check_hotplug = nv_check_hotplug, - }, - { - .host_type = NFORCE3, - .enable_hotplug = nv_enable_hotplug, - .disable_hotplug= nv_disable_hotplug, - .check_hotplug = nv_check_hotplug, - }, - { .host_type = CK804, - .enable_hotplug = nv_enable_hotplug_ck804, - .disable_hotplug= nv_disable_hotplug_ck804, - .check_hotplug = nv_check_hotplug_ck804, - }, -}; - -struct nv_host -{ - struct nv_host_desc *host_desc; - unsigned long host_flags; -}; - static struct pci_driver nv_pci_driver = { .name = DRV_NAME, .id_table = nv_pci_tbl, @@ -210,51 +169,119 @@ static struct scsi_host_template nv_sht .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; -static const struct ata_port_operations nv_ops = { +static const struct ata_port_operations nv_generic_ops = { .port_disable = ata_port_disable, .tf_load = ata_tf_load, .tf_read = ata_tf_read, .exec_command = ata_exec_command, .check_status = ata_check_status, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .irq_handler = nv_interrupt, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = nv_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + .data_xfer = ata_pio_data_xfer, + .irq_handler = nv_generic_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = nv_scr_read, .scr_write = nv_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, - .host_stop = nv_host_stop, + .host_stop = ata_pci_host_stop, }; -/* FIXME: The hardware provides the necessary SATA PHY controls - * to support ATA_FLAG_SATA_RESET. However, it is currently - * necessary to disable that flag, to solve misdetection problems. - * See http://bugme.osdl.org/show_bug.cgi?id=3352 for more info. - * - * This problem really needs to be investigated further. But in the - * meantime, we avoid ATA_FLAG_SATA_RESET to get people working. - */ -static struct ata_port_info nv_port_info = { - .sht = &nv_sht, - .host_flags = ATA_FLAG_SATA | - /* ATA_FLAG_SATA_RESET | */ - ATA_FLAG_SRST | - ATA_FLAG_NO_LEGACY, - .pio_mask = NV_PIO_MASK, - .mwdma_mask = NV_MWDMA_MASK, - .udma_mask = NV_UDMA_MASK, - .port_ops = &nv_ops, +static const struct ata_port_operations nv_nf2_ops = { + .port_disable = ata_port_disable, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .exec_command = ata_exec_command, + .check_status = ata_check_status, + .dev_select = ata_std_dev_select, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .freeze = nv_nf2_freeze, + .thaw = nv_nf2_thaw, + .error_handler = nv_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + .data_xfer = ata_pio_data_xfer, + .irq_handler = nv_nf2_interrupt, + .irq_clear = ata_bmdma_irq_clear, + .scr_read = nv_scr_read, + .scr_write = nv_scr_write, + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_pci_host_stop, +}; + +static const struct ata_port_operations nv_ck804_ops = { + .port_disable = ata_port_disable, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .exec_command = ata_exec_command, + .check_status = ata_check_status, + .dev_select = ata_std_dev_select, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .freeze = nv_ck804_freeze, + .thaw = nv_ck804_thaw, + .error_handler = nv_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + .data_xfer = ata_pio_data_xfer, + .irq_handler = nv_ck804_interrupt, + .irq_clear = ata_bmdma_irq_clear, + .scr_read = nv_scr_read, + .scr_write = nv_scr_write, + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = nv_ck804_host_stop, +}; + +static struct ata_port_info nv_port_info[] = { + /* generic */ + { + .sht = &nv_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, + .pio_mask = NV_PIO_MASK, + .mwdma_mask = NV_MWDMA_MASK, + .udma_mask = NV_UDMA_MASK, + .port_ops = &nv_generic_ops, + }, + /* nforce2/3 */ + { + .sht = &nv_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, + .pio_mask = NV_PIO_MASK, + .mwdma_mask = NV_MWDMA_MASK, + .udma_mask = NV_UDMA_MASK, + .port_ops = &nv_nf2_ops, + }, + /* ck804 */ + { + .sht = &nv_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, + .pio_mask = NV_PIO_MASK, + .mwdma_mask = NV_MWDMA_MASK, + .udma_mask = NV_UDMA_MASK, + .port_ops = &nv_ck804_ops, + }, }; MODULE_AUTHOR("NVIDIA"); @@ -263,11 +290,10 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, nv_pci_tbl); MODULE_VERSION(DRV_VERSION); -static irqreturn_t nv_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) +static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; - struct nv_host *host = host_set->private_data; unsigned int i; unsigned int handled = 0; unsigned long flags; @@ -279,11 +305,11 @@ static irqreturn_t nv_interrupt (int irq ap = host_set->ports[i]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += ata_host_intr(ap, qc); else // No request pending? Clear interrupt status @@ -293,14 +319,88 @@ static irqreturn_t nv_interrupt (int irq } - if (host->host_desc->check_hotplug) - handled += host->host_desc->check_hotplug(host_set); - spin_unlock_irqrestore(&host_set->lock, flags); return IRQ_RETVAL(handled); } +static int nv_host_intr(struct ata_port *ap, u8 irq_stat) +{ + struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); + int handled; + + /* freeze if hotplugged */ + if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) { + ata_port_freeze(ap); + return 1; + } + + /* bail out if not our interrupt */ + if (!(irq_stat & NV_INT_DEV)) + return 0; + + /* DEV interrupt w/ no active qc? */ + if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { + ata_check_status(ap); + return 1; + } + + /* handle interrupt */ + handled = ata_host_intr(ap, qc); + if (unlikely(!handled)) { + /* spurious, clear it */ + ata_check_status(ap); + } + + return 1; +} + +static irqreturn_t nv_do_interrupt(struct ata_host_set *host_set, u8 irq_stat) +{ + int i, handled = 0; + + for (i = 0; i < host_set->n_ports; i++) { + struct ata_port *ap = host_set->ports[i]; + + if (ap && !(ap->flags & ATA_FLAG_DISABLED)) + handled += nv_host_intr(ap, irq_stat); + + irq_stat >>= NV_INT_PORT_SHIFT; + } + + return IRQ_RETVAL(handled); +} + +static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + u8 irq_stat; + irqreturn_t ret; + + spin_lock(&host_set->lock); + irq_stat = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); + ret = nv_do_interrupt(host_set, irq_stat); + spin_unlock(&host_set->lock); + + return ret; +} + +static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + u8 irq_stat; + irqreturn_t ret; + + spin_lock(&host_set->lock); + irq_stat = readb(host_set->mmio_base + NV_INT_STATUS_CK804); + ret = nv_do_interrupt(host_set, irq_stat); + spin_unlock(&host_set->lock); + + return ret; +} + static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg) { if (sc_reg > SCR_CONTROL) @@ -317,23 +417,74 @@ static void nv_scr_write (struct ata_por iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); } -static void nv_host_stop (struct ata_host_set *host_set) +static void nv_nf2_freeze(struct ata_port *ap) { - struct nv_host *host = host_set->private_data; + unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; - // Disable hotplug event interrupts. - if (host->host_desc->disable_hotplug) - host->host_desc->disable_hotplug(host_set); + mask = inb(scr_addr + NV_INT_ENABLE); + mask &= ~(NV_INT_ALL << shift); + outb(mask, scr_addr + NV_INT_ENABLE); +} - kfree(host); +static void nv_nf2_thaw(struct ata_port *ap) +{ + unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; - ata_pci_host_stop(host_set); + outb(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS); + + mask = inb(scr_addr + NV_INT_ENABLE); + mask |= (NV_INT_MASK << shift); + outb(mask, scr_addr + NV_INT_ENABLE); +} + +static void nv_ck804_freeze(struct ata_port *ap) +{ + void __iomem *mmio_base = ap->host_set->mmio_base; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; + + mask = readb(mmio_base + NV_INT_ENABLE_CK804); + mask &= ~(NV_INT_ALL << shift); + writeb(mask, mmio_base + NV_INT_ENABLE_CK804); +} + +static void nv_ck804_thaw(struct ata_port *ap) +{ + void __iomem *mmio_base = ap->host_set->mmio_base; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; + + writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804); + + mask = readb(mmio_base + NV_INT_ENABLE_CK804); + mask |= (NV_INT_MASK << shift); + writeb(mask, mmio_base + NV_INT_ENABLE_CK804); +} + +static int nv_hardreset(struct ata_port *ap, unsigned int *class) +{ + unsigned int dummy; + + /* SATA hardreset fails to retrieve proper device signature on + * some controllers. Don't classify on hardreset. For more + * info, see http://bugme.osdl.org/show_bug.cgi?id=3352 + */ + return sata_std_hardreset(ap, &dummy); +} + +static void nv_error_handler(struct ata_port *ap) +{ + ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, + nv_hardreset, ata_std_postreset); } static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version = 0; - struct nv_host *host; struct ata_port_info *ppi; struct ata_probe_ent *probe_ent; int pci_dev_busy = 0; @@ -370,24 +521,15 @@ static int nv_init_one (struct pci_dev * rc = -ENOMEM; - ppi = &nv_port_info; + ppi = &nv_port_info[ent->driver_data]; probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); if (!probe_ent) goto err_out_regions; - host = kmalloc(sizeof(struct nv_host), GFP_KERNEL); - if (!host) - goto err_out_free_ent; - - memset(host, 0, sizeof(struct nv_host)); - host->host_desc = &nv_device_tbl[ent->driver_data]; - - probe_ent->private_data = host; - probe_ent->mmio_base = pci_iomap(pdev, 5, 0); if (!probe_ent->mmio_base) { rc = -EIO; - goto err_out_free_host; + goto err_out_free_ent; } base = (unsigned long)probe_ent->mmio_base; @@ -395,24 +537,27 @@ static int nv_init_one (struct pci_dev * probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET; probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET; + /* enable SATA space for CK804 */ + if (ent->driver_data == CK804) { + u8 regval; + + pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); + regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; + pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); + } + pci_set_master(pdev); rc = ata_device_add(probe_ent); if (rc != NV_PORTS) goto err_out_iounmap; - // Enable hotplug event interrupts. - if (host->host_desc->enable_hotplug) - host->host_desc->enable_hotplug(probe_ent); - kfree(probe_ent); return 0; err_out_iounmap: pci_iounmap(pdev, probe_ent->mmio_base); -err_out_free_host: - kfree(host); err_out_free_ent: kfree(probe_ent); err_out_regions: @@ -424,127 +569,17 @@ err_out: return rc; } -static void nv_enable_hotplug(struct ata_probe_ent *probe_ent) -{ - u8 intr_mask; - - outb(NV_INT_STATUS_HOTPLUG, - probe_ent->port[0].scr_addr + NV_INT_STATUS); - - intr_mask = inb(probe_ent->port[0].scr_addr + NV_INT_ENABLE); - intr_mask |= NV_INT_ENABLE_HOTPLUG; - - outb(intr_mask, probe_ent->port[0].scr_addr + NV_INT_ENABLE); -} - -static void nv_disable_hotplug(struct ata_host_set *host_set) -{ - u8 intr_mask; - - intr_mask = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); - - intr_mask &= ~(NV_INT_ENABLE_HOTPLUG); - - outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); -} - -static int nv_check_hotplug(struct ata_host_set *host_set) -{ - u8 intr_status; - - intr_status = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); - - // Clear interrupt status. - outb(0xff, host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); - - if (intr_status & NV_INT_STATUS_HOTPLUG) { - if (intr_status & NV_INT_STATUS_PDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Primary device added\n"); - - if (intr_status & NV_INT_STATUS_PDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Primary device removed\n"); - - if (intr_status & NV_INT_STATUS_SDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Secondary device added\n"); - - if (intr_status & NV_INT_STATUS_SDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Secondary device removed\n"); - - return 1; - } - - return 0; -} - -static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) -{ - struct pci_dev *pdev = to_pci_dev(probe_ent->dev); - u8 intr_mask; - u8 regval; - - pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); - regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; - pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); - - writeb(NV_INT_STATUS_HOTPLUG, probe_ent->mmio_base + NV_INT_STATUS_CK804); - - intr_mask = readb(probe_ent->mmio_base + NV_INT_ENABLE_CK804); - intr_mask |= NV_INT_ENABLE_HOTPLUG; - - writeb(intr_mask, probe_ent->mmio_base + NV_INT_ENABLE_CK804); -} - -static void nv_disable_hotplug_ck804(struct ata_host_set *host_set) +static void nv_ck804_host_stop(struct ata_host_set *host_set) { struct pci_dev *pdev = to_pci_dev(host_set->dev); - u8 intr_mask; u8 regval; - intr_mask = readb(host_set->mmio_base + NV_INT_ENABLE_CK804); - - intr_mask &= ~(NV_INT_ENABLE_HOTPLUG); - - writeb(intr_mask, host_set->mmio_base + NV_INT_ENABLE_CK804); - + /* disable SATA space for CK804 */ pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN; pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); -} - -static int nv_check_hotplug_ck804(struct ata_host_set *host_set) -{ - u8 intr_status; - intr_status = readb(host_set->mmio_base + NV_INT_STATUS_CK804); - - // Clear interrupt status. - writeb(0xff, host_set->mmio_base + NV_INT_STATUS_CK804); - - if (intr_status & NV_INT_STATUS_HOTPLUG) { - if (intr_status & NV_INT_STATUS_PDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Primary device added\n"); - - if (intr_status & NV_INT_STATUS_PDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Primary device removed\n"); - - if (intr_status & NV_INT_STATUS_SDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Secondary device added\n"); - - if (intr_status & NV_INT_STATUS_SDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Secondary device removed\n"); - - return 1; - } - - return 0; + ata_pci_host_stop(host_set); } static int __init nv_init(void) diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 7eb67a6..b2b6ed5 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -76,7 +76,8 @@ enum { PDC_RESET = (1 << 11), /* HDMA reset */ PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | - ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI, + ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | + ATA_FLAG_PIO_POLLING, }; @@ -120,6 +121,7 @@ static struct scsi_host_template pdc_ata .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -136,6 +138,7 @@ static const struct ata_port_operations .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, .eng_timeout = pdc_eng_timeout, + .data_xfer = ata_mmio_data_xfer, .irq_handler = pdc_interrupt, .irq_clear = pdc_irq_clear, @@ -158,6 +161,7 @@ static const struct ata_port_operations .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, + .data_xfer = ata_mmio_data_xfer, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc_interrupt, .irq_clear = pdc_irq_clear, @@ -363,12 +367,23 @@ static void pdc_sata_phy_reset(struct at sata_phy_reset(ap); } -static void pdc_pata_phy_reset(struct ata_port *ap) +static void pdc_pata_cbl_detect(struct ata_port *ap) { - /* FIXME: add cable detect. Don't assume 40-pin cable */ - ap->cbl = ATA_CBL_PATA40; - ap->udma_mask &= ATA_UDMA_MASK_40C; + u8 tmp; + void __iomem *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03; + + tmp = readb(mmio); + + if (tmp & 0x01) { + ap->cbl = ATA_CBL_PATA40; + ap->udma_mask &= ATA_UDMA_MASK_40C; + } else + ap->cbl = ATA_CBL_PATA80; +} +static void pdc_pata_phy_reset(struct ata_port *ap) +{ + pdc_pata_cbl_detect(ap); pdc_reset_port(ap); ata_port_probe(ap); ata_bus_reset(ap); @@ -435,7 +450,7 @@ static void pdc_eng_timeout(struct ata_p switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: - printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_port_printk(ap, KERN_ERR, "command timeout\n"); drv_stat = ata_wait_idle(ap); qc->err_mask |= __ac_err_mask(drv_stat); break; @@ -443,8 +458,9 @@ static void pdc_eng_timeout(struct ata_p default: drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); + ata_port_printk(ap, KERN_ERR, + "unknown timeout, cmd 0x%x stat 0x%x\n", + qc->tf.command, drv_stat); qc->err_mask |= ac_err_mask(drv_stat); break; @@ -533,11 +549,11 @@ static irqreturn_t pdc_interrupt (int ir ap = host_set->ports[i]; tmp = mask & (1 << (i + 1)); if (tmp && ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += pdc_host_intr(ap, qc); } } @@ -676,10 +692,6 @@ static int pdc_ata_init_one (struct pci_ if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - /* - * If this driver happens to only be useful on Apple's K2, then - * we should check that here as it has a normal Serverworks ID - */ rc = pci_enable_device(pdev); if (rc) return rc; diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 886f344..98ddc25 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -41,7 +41,7 @@ #include #include #define DRV_NAME "sata_qstor" -#define DRV_VERSION "0.05" +#define DRV_VERSION "0.06" enum { QS_PORTS = 4, @@ -142,6 +142,7 @@ static struct scsi_host_template qs_ata_ .proc_name = DRV_NAME, .dma_boundary = QS_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -156,6 +157,7 @@ static const struct ata_port_operations .phy_reset = qs_phy_reset, .qc_prep = qs_qc_prep, .qc_issue = qs_qc_issue, + .data_xfer = ata_mmio_data_xfer, .eng_timeout = qs_eng_timeout, .irq_handler = qs_intr, .irq_clear = qs_irq_clear, @@ -175,7 +177,7 @@ static const struct ata_port_info qs_por .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | //FIXME ATA_FLAG_SRST | - ATA_FLAG_MMIO, + ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, .pio_mask = 0x10, /* pio4 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &qs_ata_ops, @@ -394,14 +396,13 @@ static inline unsigned int qs_intr_pkt(s DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n", sff1, sff0, port_no, sHST, sDST); handled = 1; - if (ap && !(ap->flags & - (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { + if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { struct ata_queued_cmd *qc; struct qs_port_priv *pp = ap->private_data; if (!pp || pp->state != qs_state_pkt) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { switch (sHST) { case 0: /* successful CPB */ case 3: /* device error */ @@ -428,13 +429,13 @@ static inline unsigned int qs_intr_mmio( struct ata_port *ap; ap = host_set->ports[port_no]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_DISABLED)) { struct ata_queued_cmd *qc; struct qs_port_priv *pp = ap->private_data; if (!pp || pp->state != qs_state_mmio) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { /* check main status, clearing INTRQ */ u8 status = ata_check_status(ap); diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 1066272..bc9f918 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -46,7 +46,7 @@ #include #include #define DRV_NAME "sata_sil" -#define DRV_VERSION "0.9" +#define DRV_VERSION "1.0" enum { /* @@ -54,8 +54,9 @@ enum { */ SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29), SIL_FLAG_MOD15WRITE = (1 << 30), + SIL_DFL_HOST_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO, + ATA_FLAG_MMIO | ATA_FLAG_HRST_TO_RESUME, /* * Controller IDs @@ -84,6 +85,20 @@ enum { /* BMDMA/BMDMA2 */ SIL_INTR_STEERING = (1 << 1), + SIL_DMA_ENABLE = (1 << 0), /* DMA run switch */ + SIL_DMA_RDWR = (1 << 3), /* DMA Rd-Wr */ + SIL_DMA_SATA_IRQ = (1 << 4), /* OR of all SATA IRQs */ + SIL_DMA_ACTIVE = (1 << 16), /* DMA running */ + SIL_DMA_ERROR = (1 << 17), /* PCI bus error */ + SIL_DMA_COMPLETE = (1 << 18), /* cmd complete / IRQ pending */ + SIL_DMA_N_SATA_IRQ = (1 << 6), /* SATA_IRQ for the next channel */ + SIL_DMA_N_ACTIVE = (1 << 24), /* ACTIVE for the next channel */ + SIL_DMA_N_ERROR = (1 << 25), /* ERROR for the next channel */ + SIL_DMA_N_COMPLETE = (1 << 26), /* COMPLETE for the next channel */ + + /* SIEN */ + SIL_SIEN_N = (1 << 16), /* triggered by SError.N */ + /* * Others */ @@ -96,6 +111,10 @@ static void sil_dev_config(struct ata_po static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void sil_post_set_mode (struct ata_port *ap); +static irqreturn_t sil_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); +static void sil_freeze(struct ata_port *ap); +static void sil_thaw(struct ata_port *ap); static const struct pci_device_id sil_pci_tbl[] = { @@ -155,6 +174,7 @@ static struct scsi_host_template sil_sht .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -166,7 +186,6 @@ static const struct ata_port_operations .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .probe_reset = ata_std_probe_reset, .post_set_mode = sil_post_set_mode, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, @@ -174,8 +193,12 @@ static const struct ata_port_operations .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .irq_handler = ata_interrupt, + .data_xfer = ata_mmio_data_xfer, + .freeze = sil_freeze, + .thaw = sil_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + .irq_handler = sil_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = sil_scr_read, .scr_write = sil_scr_write, @@ -220,6 +243,7 @@ static const struct { unsigned long tf; /* ATA taskfile register block */ unsigned long ctl; /* ATA control/altstatus register block */ unsigned long bmdma; /* DMA register block */ + unsigned long bmdma2; /* DMA register block #2 */ unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */ unsigned long scr; /* SATA control register block */ unsigned long sien; /* SATA Interrupt Enable register */ @@ -227,10 +251,10 @@ static const struct { unsigned long sfis_cfg; /* SATA FIS reception config register */ } sil_port[] = { /* port 0 ... */ - { 0x80, 0x8A, 0x00, 0x40, 0x100, 0x148, 0xb4, 0x14c }, - { 0xC0, 0xCA, 0x08, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, - { 0x280, 0x28A, 0x200, 0x240, 0x300, 0x348, 0x2b4, 0x34c }, - { 0x2C0, 0x2CA, 0x208, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc }, + { 0x80, 0x8A, 0x00, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c }, + { 0xC0, 0xCA, 0x08, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, + { 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c }, + { 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc }, /* ... port 3 */ }; @@ -263,7 +287,7 @@ static void sil_post_set_mode (struct at for (i = 0; i < 2; i++) { dev = &ap->device[i]; - if (!ata_dev_present(dev)) + if (!ata_dev_enabled(dev)) dev_mode[i] = 0; /* PIO0/1/2 */ else if (dev->flags & ATA_DFLAG_PIO) dev_mode[i] = 1; /* PIO3/4 */ @@ -314,6 +338,151 @@ static void sil_scr_write (struct ata_po writel(val, mmio); } +static void sil_host_intr(struct ata_port *ap, u32 bmdma2) +{ + struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); + u8 status; + + if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) { + u32 serror; + + /* SIEN doesn't mask SATA IRQs on some 3112s. Those + * controllers continue to assert IRQ as long as + * SError bits are pending. Clear SError immediately. + */ + serror = sil_scr_read(ap, SCR_ERROR); + sil_scr_write(ap, SCR_ERROR, serror); + + /* Trigger hotplug and accumulate SError only if the + * port isn't already frozen. Otherwise, PHY events + * during hardreset makes controllers with broken SIEN + * repeat probing needlessly. + */ + if (!(ap->flags & ATA_FLAG_FROZEN)) { + ata_ehi_hotplugged(&ap->eh_info); + ap->eh_info.serror |= serror; + } + + goto freeze; + } + + if (unlikely(!qc || qc->tf.ctl & ATA_NIEN)) + goto freeze; + + /* Check whether we are expecting interrupt in this state */ + switch (ap->hsm_task_state) { + case HSM_ST_FIRST: + /* Some pre-ATAPI-4 devices assert INTRQ + * at this state when ready to receive CDB. + */ + + /* Check the ATA_DFLAG_CDB_INTR flag is enough here. + * The flag was turned on only for atapi devices. + * No need to check is_atapi_taskfile(&qc->tf) again. + */ + if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) + goto err_hsm; + break; + case HSM_ST_LAST: + if (qc->tf.protocol == ATA_PROT_DMA || + qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + /* clear DMA-Start bit */ + ap->ops->bmdma_stop(qc); + + if (bmdma2 & SIL_DMA_ERROR) { + qc->err_mask |= AC_ERR_HOST_BUS; + ap->hsm_task_state = HSM_ST_ERR; + } + } + break; + case HSM_ST: + break; + default: + goto err_hsm; + } + + /* check main status, clearing INTRQ */ + status = ata_chk_status(ap); + if (unlikely(status & ATA_BUSY)) + goto err_hsm; + + /* ack bmdma irq events */ + ata_bmdma_irq_clear(ap); + + /* kick HSM in the ass */ + ata_hsm_move(ap, qc, status, 0); + + return; + + err_hsm: + qc->err_mask |= AC_ERR_HSM; + freeze: + ata_port_freeze(ap); +} + +static irqreturn_t sil_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + void __iomem *mmio_base = host_set->mmio_base; + int handled = 0; + int i; + + spin_lock(&host_set->lock); + + for (i = 0; i < host_set->n_ports; i++) { + struct ata_port *ap = host_set->ports[i]; + u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2); + + if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED)) + continue; + + if (bmdma2 == 0xffffffff || + !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ))) + continue; + + sil_host_intr(ap, bmdma2); + handled = 1; + } + + spin_unlock(&host_set->lock); + + return IRQ_RETVAL(handled); +} + +static void sil_freeze(struct ata_port *ap) +{ + void __iomem *mmio_base = ap->host_set->mmio_base; + u32 tmp; + + /* global IRQ mask doesn't block SATA IRQ, turn off explicitly */ + writel(0, mmio_base + sil_port[ap->port_no].sien); + + /* plug IRQ */ + tmp = readl(mmio_base + SIL_SYSCFG); + tmp |= SIL_MASK_IDE0_INT << ap->port_no; + writel(tmp, mmio_base + SIL_SYSCFG); + readl(mmio_base + SIL_SYSCFG); /* flush */ +} + +static void sil_thaw(struct ata_port *ap) +{ + void __iomem *mmio_base = ap->host_set->mmio_base; + u32 tmp; + + /* clear IRQ */ + ata_chk_status(ap); + ata_bmdma_irq_clear(ap); + + /* turn on SATA IRQ */ + writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien); + + /* turn on IRQ */ + tmp = readl(mmio_base + SIL_SYSCFG); + tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no); + writel(tmp, mmio_base + SIL_SYSCFG); +} + /** * sil_dev_config - Apply device/host-specific errata fixups * @ap: Port containing device to be examined @@ -360,16 +529,16 @@ static void sil_dev_config(struct ata_po if (slow_down || ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE))) { - printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n", - ap->id, dev->devno); + ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix " + "(mod15write workaround)\n"); dev->max_sectors = 15; return; } /* limit to udma5 */ if (quirks & SIL_QUIRK_UDMA5MAX) { - printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n", - ap->id, dev->devno, model_num); + ata_dev_printk(dev, KERN_INFO, + "applying Maxtor errata fix %s\n", model_num); dev->udma_mask &= ATA_UDMA5; return; } @@ -384,16 +553,12 @@ static int sil_init_one (struct pci_dev int rc; unsigned int i; int pci_dev_busy = 0; - u32 tmp, irq_mask; + u32 tmp; u8 cls; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - /* - * If this driver happens to only be useful on Apple's K2, then - * we should check that here as it has a normal Serverworks ID - */ rc = pci_enable_device(pdev); if (rc) return rc; @@ -478,31 +643,13 @@ static int sil_init_one (struct pci_dev } if (ent->driver_data == sil_3114) { - irq_mask = SIL_MASK_4PORT; - /* flip the magic "make 4 ports work" bit */ tmp = readl(mmio_base + sil_port[2].bmdma); if ((tmp & SIL_INTR_STEERING) == 0) writel(tmp | SIL_INTR_STEERING, mmio_base + sil_port[2].bmdma); - - } else { - irq_mask = SIL_MASK_2PORT; - } - - /* make sure IDE0/1/2/3 interrupts are not masked */ - tmp = readl(mmio_base + SIL_SYSCFG); - if (tmp & irq_mask) { - tmp &= ~irq_mask; - writel(tmp, mmio_base + SIL_SYSCFG); - readl(mmio_base + SIL_SYSCFG); /* flush */ } - /* mask all SATA phy-related interrupts */ - /* TODO: unmask bit 6 (SError N bit) for hotplug */ - for (i = 0; i < probe_ent->n_ports; i++) - writel(0, mmio_base + sil_port[i].sien); - pci_set_master(pdev); /* FIXME: check ata_device_add return value */ diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index cb9082f..c8b477c 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -31,15 +31,15 @@ #include #include #define DRV_NAME "sata_sil24" -#define DRV_VERSION "0.23" +#define DRV_VERSION "0.24" /* * Port request block (PRB) 32 bytes */ struct sil24_prb { - u16 ctrl; - u16 prot; - u32 rx_cnt; + __le16 ctrl; + __le16 prot; + __le32 rx_cnt; u8 fis[6 * 4]; }; @@ -47,17 +47,17 @@ struct sil24_prb { * Scatter gather entry (SGE) 16 bytes */ struct sil24_sge { - u64 addr; - u32 cnt; - u32 flags; + __le64 addr; + __le32 cnt; + __le32 flags; }; /* * Port multiplier */ struct sil24_port_multiplier { - u32 diag; - u32 sactive; + __le32 diag; + __le32 sactive; }; enum { @@ -86,12 +86,21 @@ enum { /* HOST_SLOT_STAT bits */ HOST_SSTAT_ATTN = (1 << 31), + /* HOST_CTRL bits */ + HOST_CTRL_M66EN = (1 << 16), /* M66EN PCI bus signal */ + HOST_CTRL_TRDY = (1 << 17), /* latched PCI TRDY */ + HOST_CTRL_STOP = (1 << 18), /* latched PCI STOP */ + HOST_CTRL_DEVSEL = (1 << 19), /* latched PCI DEVSEL */ + HOST_CTRL_REQ64 = (1 << 20), /* latched PCI REQ64 */ + /* * Port registers * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2) */ PORT_REGS_SIZE = 0x2000, - PORT_PRB = 0x0000, /* (32 bytes PRB + 16 bytes SGEs * 6) * 31 (3968 bytes) */ + + PORT_LRAM = 0x0000, /* 31 LRAM slots and PM regs */ + PORT_LRAM_SLOT_SZ = 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */ PORT_PM = 0x0f80, /* 8 bytes PM * 16 (128 bytes) */ /* 32 bit regs */ @@ -142,8 +151,16 @@ enum { PORT_IRQ_PWR_CHG = (1 << 3), /* power management change */ PORT_IRQ_PHYRDY_CHG = (1 << 4), /* PHY ready change */ PORT_IRQ_COMWAKE = (1 << 5), /* COMWAKE received */ - PORT_IRQ_UNK_FIS = (1 << 6), /* Unknown FIS received */ - PORT_IRQ_SDB_FIS = (1 << 11), /* SDB FIS received */ + PORT_IRQ_UNK_FIS = (1 << 6), /* unknown FIS received */ + PORT_IRQ_DEV_XCHG = (1 << 7), /* device exchanged */ + PORT_IRQ_8B10B = (1 << 8), /* 8b/10b decode error threshold */ + PORT_IRQ_CRC = (1 << 9), /* CRC error threshold */ + PORT_IRQ_HANDSHAKE = (1 << 10), /* handshake error threshold */ + PORT_IRQ_SDB_NOTIFY = (1 << 11), /* SDB notify received */ + + DEF_PORT_IRQ = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | + PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG | + PORT_IRQ_UNK_FIS, /* bits[27:16] are unmasked (raw) */ PORT_IRQ_RAW_SHIFT = 16, @@ -174,7 +191,7 @@ enum { PORT_CERR_CMD_PCIPERR = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */ PORT_CERR_XFR_UNDEF = 32, /* PSD ecode 00 - undefined */ PORT_CERR_XFR_TGTABRT = 33, /* PSD ecode 01 - target abort */ - PORT_CERR_XFR_MSGABRT = 34, /* PSD ecode 10 - master abort */ + PORT_CERR_XFR_MSTABRT = 34, /* PSD ecode 10 - master abort */ PORT_CERR_XFR_PCIPERR = 35, /* PSD ecode 11 - PCI prity err during transfer */ PORT_CERR_SENDSERVICE = 36, /* FIS received while sending service */ @@ -202,11 +219,19 @@ enum { SGE_DRD = (1 << 29), /* discard data read (/dev/null) data address ignored */ + SIL24_MAX_CMDS = 31, + /* board id */ BID_SIL3124 = 0, BID_SIL3132 = 1, BID_SIL3131 = 2, + /* host flags */ + SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY, + SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ + IRQ_STAT_4PORTS = 0xf, }; @@ -226,6 +251,58 @@ union sil24_cmd_block { struct sil24_atapi_block atapi; }; +static struct sil24_cerr_info { + unsigned int err_mask, action; + const char *desc; +} sil24_cerr_db[] = { + [0] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + "device error" }, + [PORT_CERR_DEV] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + "device error via D2H FIS" }, + [PORT_CERR_SDB] = { AC_ERR_DEV, ATA_EH_REVALIDATE, + "device error via SDB FIS" }, + [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET, + "error in data FIS" }, + [PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET, + "failed to transmit command FIS" }, + [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "protocol mismatch" }, + [PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "data directon mismatch" }, + [PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "ran out of SGEs while writing" }, + [PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "ran out of SGEs while reading" }, + [PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "invalid data directon for ATAPI CDB" }, + [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET, + "SGT no on qword boundary" }, + [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI target abort while fetching SGT" }, + [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI master abort while fetching SGT" }, + [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI parity error while fetching SGT" }, + [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET, + "PRB not on qword boundary" }, + [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI target abort while fetching PRB" }, + [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI master abort while fetching PRB" }, + [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI parity error while fetching PRB" }, + [PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "undefined error while transferring data" }, + [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI target abort while transferring data" }, + [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI master abort while transferring data" }, + [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, + "PCI parity error while transferring data" }, + [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_SOFTRESET, + "FIS received while sending service FIS" }, +}; + /* * ap->private_data * @@ -249,12 +326,14 @@ static u8 sil24_check_status(struct ata_ static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); -static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes); static void sil24_qc_prep(struct ata_queued_cmd *qc); static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); static void sil24_irq_clear(struct ata_port *ap); -static void sil24_eng_timeout(struct ata_port *ap); static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static void sil24_freeze(struct ata_port *ap); +static void sil24_thaw(struct ata_port *ap); +static void sil24_error_handler(struct ata_port *ap); +static void sil24_post_internal_cmd(struct ata_queued_cmd *qc); static int sil24_port_start(struct ata_port *ap); static void sil24_port_stop(struct ata_port *ap); static void sil24_host_stop(struct ata_host_set *host_set); @@ -281,7 +360,8 @@ static struct scsi_host_template sil24_s .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, + .change_queue_depth = ata_scsi_change_queue_depth, + .can_queue = SIL24_MAX_CMDS, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, @@ -290,6 +370,7 @@ static struct scsi_host_template sil24_s .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -304,19 +385,20 @@ static const struct ata_port_operations .tf_read = sil24_tf_read, - .probe_reset = sil24_probe_reset, - .qc_prep = sil24_qc_prep, .qc_issue = sil24_qc_issue, - .eng_timeout = sil24_eng_timeout, - .irq_handler = sil24_interrupt, .irq_clear = sil24_irq_clear, .scr_read = sil24_scr_read, .scr_write = sil24_scr_write, + .freeze = sil24_freeze, + .thaw = sil24_thaw, + .error_handler = sil24_error_handler, + .post_internal_cmd = sil24_post_internal_cmd, + .port_start = sil24_port_start, .port_stop = sil24_port_stop, .host_stop = sil24_host_stop, @@ -333,9 +415,8 @@ static struct ata_port_info sil24_port_i /* sil_3124 */ { .sht = &sil24_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - SIL24_NPORTS2FLAG(4), + .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | + SIL24_FLAG_PCIX_IRQ_WOC, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -344,9 +425,7 @@ static struct ata_port_info sil24_port_i /* sil_3132 */ { .sht = &sil24_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - SIL24_NPORTS2FLAG(2), + .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -355,9 +434,7 @@ static struct ata_port_info sil24_port_i /* sil_3131/sil_3531 */ { .sht = &sil24_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - SIL24_NPORTS2FLAG(1), + .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -365,6 +442,13 @@ static struct ata_port_info sil24_port_i }, }; +static int sil24_tag(int tag) +{ + if (unlikely(ata_tag_internal(tag))) + return 0; + return tag; +} + static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; @@ -426,56 +510,65 @@ static void sil24_tf_read(struct ata_por *tf = pp->tf; } -static int sil24_softreset(struct ata_port *ap, int verbose, - unsigned int *class) +static int sil24_init_port(struct ata_port *ap) +{ + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + u32 tmp; + + writel(PORT_CS_INIT, port + PORT_CTRL_STAT); + ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_INIT, PORT_CS_INIT, 10, 100); + tmp = ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_RDY, 0, 10, 100); + + if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) + return -EIO; + return 0; +} + +static int sil24_softreset(struct ata_port *ap, unsigned int *class) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; struct sil24_port_priv *pp = ap->private_data; struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; dma_addr_t paddr = pp->cmd_block_dma; - unsigned long timeout = jiffies + ATA_TMOUT_BOOT * HZ; - u32 irq_enable, irq_stat; + u32 mask, irq_stat; + const char *reason; DPRINTK("ENTER\n"); - if (!sata_dev_present(ap)) { + if (ata_port_offline(ap)) { DPRINTK("PHY reports no device\n"); *class = ATA_DEV_NONE; goto out; } - /* temporarily turn off IRQs during SRST */ - irq_enable = readl(port + PORT_IRQ_ENABLE_SET); - writel(irq_enable, port + PORT_IRQ_ENABLE_CLR); - - /* - * XXX: Not sure whether the following sleep is needed or not. - * The original driver had it. So.... - */ - msleep(10); + /* put the port into known state */ + if (sil24_init_port(ap)) { + reason ="port not ready"; + goto err; + } + /* do SRST */ prb->ctrl = cpu_to_le16(PRB_CTRL_SRST); prb->fis[1] = 0; /* no PM yet */ writel((u32)paddr, port + PORT_CMD_ACTIVATE); + writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); - do { - irq_stat = readl(port + PORT_IRQ_STAT); - writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ - - irq_stat >>= PORT_IRQ_RAW_SHIFT; - if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR)) - break; + mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT; + irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0, + 100, ATA_TMOUT_BOOT / HZ * 1000); - msleep(100); - } while (time_before(jiffies, timeout)); - - /* restore IRQs */ - writel(irq_enable, port + PORT_IRQ_ENABLE_SET); + writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */ + irq_stat >>= PORT_IRQ_RAW_SHIFT; if (!(irq_stat & PORT_IRQ_COMPLETE)) { - DPRINTK("EXIT, srst failed\n"); - return -EIO; + if (irq_stat & PORT_IRQ_ERROR) + reason = "SRST command error"; + else + reason = "timeout"; + goto err; } sil24_update_tf(ap); @@ -487,22 +580,57 @@ static int sil24_softreset(struct ata_po out: DPRINTK("EXIT, class=%u\n", *class); return 0; + + err: + ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); + return -EIO; } -static int sil24_hardreset(struct ata_port *ap, int verbose, - unsigned int *class) +static int sil24_hardreset(struct ata_port *ap, unsigned int *class) { - unsigned int dummy_class; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + const char *reason; + int tout_msec, rc; + u32 tmp; - /* sil24 doesn't report device signature after hard reset */ - return sata_std_hardreset(ap, verbose, &dummy_class); -} + /* sil24 does the right thing(tm) without any protection */ + sata_set_spd(ap); -static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes) -{ - return ata_drive_probe_reset(ap, ata_std_probeinit, - sil24_softreset, sil24_hardreset, - ata_std_postreset, classes); + tout_msec = 100; + if (ata_port_online(ap)) + tout_msec = 5000; + + writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); + tmp = ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec); + + /* SStatus oscillates between zero and valid status after + * DEV_RST, debounce it. + */ + rc = sata_phy_debounce(ap, sata_deb_timing_before_fsrst); + if (rc) { + reason = "PHY debouncing failed"; + goto err; + } + + if (tmp & PORT_CS_DEV_RST) { + if (ata_port_offline(ap)) + return 0; + reason = "link not ready"; + goto err; + } + + /* Sil24 doesn't store signature FIS after hardreset, so we + * can't wait for BSY to clear. Some devices take a long time + * to get ready and those devices will choke if we don't wait + * for BSY clearance here. Tell libata to perform follow-up + * softreset. + */ + return -EAGAIN; + + err: + ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason); + return -EIO; } static inline void sil24_fill_sg(struct ata_queued_cmd *qc, @@ -528,17 +656,20 @@ static void sil24_qc_prep(struct ata_que { struct ata_port *ap = qc->ap; struct sil24_port_priv *pp = ap->private_data; - union sil24_cmd_block *cb = pp->cmd_block + qc->tag; + union sil24_cmd_block *cb; struct sil24_prb *prb; struct sil24_sge *sge; + u16 ctrl = 0; + + cb = &pp->cmd_block[sil24_tag(qc->tag)]; switch (qc->tf.protocol) { case ATA_PROT_PIO: case ATA_PROT_DMA: + case ATA_PROT_NCQ: case ATA_PROT_NODATA: prb = &cb->ata.prb; sge = cb->ata.sge; - prb->ctrl = 0; break; case ATA_PROT_ATAPI: @@ -551,12 +682,10 @@ static void sil24_qc_prep(struct ata_que if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { if (qc->tf.flags & ATA_TFLAG_WRITE) - prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_WRITE); + ctrl = PRB_CTRL_PACKET_WRITE; else - prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_READ); - } else - prb->ctrl = 0; - + ctrl = PRB_CTRL_PACKET_READ; + } break; default: @@ -565,6 +694,7 @@ static void sil24_qc_prep(struct ata_que BUG(); } + prb->ctrl = cpu_to_le16(ctrl); ata_tf_to_fis(&qc->tf, prb->fis, 0); if (qc->flags & ATA_QCFLAG_DMAMAP) @@ -574,11 +704,18 @@ static void sil24_qc_prep(struct ata_que static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; struct sil24_port_priv *pp = ap->private_data; - dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block); + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + unsigned int tag = sil24_tag(qc->tag); + dma_addr_t paddr; + void __iomem *activate; + + paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block); + activate = port + PORT_CMD_ACTIVATE + tag * 8; + + writel((u32)paddr, activate); + writel((u64)paddr >> 32, activate + 4); - writel((u32)paddr, port + PORT_CMD_ACTIVATE); return 0; } @@ -587,162 +724,139 @@ static void sil24_irq_clear(struct ata_p /* unused */ } -static int __sil24_restart_controller(void __iomem *port) +static void sil24_freeze(struct ata_port *ap) { - u32 tmp; - int cnt; - - writel(PORT_CS_INIT, port + PORT_CTRL_STAT); - - /* Max ~10ms */ - for (cnt = 0; cnt < 10000; cnt++) { - tmp = readl(port + PORT_CTRL_STAT); - if (tmp & PORT_CS_RDY) - return 0; - udelay(1); - } + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; - return -1; + /* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear + * PORT_IRQ_ENABLE instead. + */ + writel(0xffff, port + PORT_IRQ_ENABLE_CLR); } -static void sil24_restart_controller(struct ata_port *ap) +static void sil24_thaw(struct ata_port *ap) { - if (__sil24_restart_controller((void __iomem *)ap->ioaddr.cmd_addr)) - printk(KERN_ERR DRV_NAME - " ata%u: failed to restart controller\n", ap->id); + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + u32 tmp; + + /* clear IRQ */ + tmp = readl(port + PORT_IRQ_STAT); + writel(tmp, port + PORT_IRQ_STAT); + + /* turn IRQ back on */ + writel(DEF_PORT_IRQ, port + PORT_IRQ_ENABLE_SET); } -static int __sil24_reset_controller(void __iomem *port) +static void sil24_error_intr(struct ata_port *ap) { - int cnt; - u32 tmp; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + struct ata_eh_info *ehi = &ap->eh_info; + int freeze = 0; + u32 irq_stat; - /* Reset controller state. Is this correct? */ - writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); - readl(port + PORT_CTRL_STAT); /* sync */ + /* on error, we need to clear IRQ explicitly */ + irq_stat = readl(port + PORT_IRQ_STAT); + writel(irq_stat, port + PORT_IRQ_STAT); - /* Max ~100ms */ - for (cnt = 0; cnt < 1000; cnt++) { - udelay(100); - tmp = readl(port + PORT_CTRL_STAT); - if (!(tmp & PORT_CS_DEV_RST)) - break; - } + /* first, analyze and record host port events */ + ata_ehi_clear_desc(ehi); - if (tmp & PORT_CS_DEV_RST) - return -1; + ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); - if (tmp & PORT_CS_RDY) - return 0; + if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) { + ata_ehi_hotplugged(ehi); + ata_ehi_push_desc(ehi, ", %s", + irq_stat & PORT_IRQ_PHYRDY_CHG ? + "PHY RDY changed" : "device exchanged"); + freeze = 1; + } - return __sil24_restart_controller(port); -} + if (irq_stat & PORT_IRQ_UNK_FIS) { + ehi->err_mask |= AC_ERR_HSM; + ehi->action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi , ", unknown FIS"); + freeze = 1; + } -static void sil24_reset_controller(struct ata_port *ap) -{ - printk(KERN_NOTICE DRV_NAME - " ata%u: resetting controller...\n", ap->id); - if (__sil24_reset_controller((void __iomem *)ap->ioaddr.cmd_addr)) - printk(KERN_ERR DRV_NAME - " ata%u: failed to reset controller\n", ap->id); -} + /* deal with command error */ + if (irq_stat & PORT_IRQ_ERROR) { + struct sil24_cerr_info *ci = NULL; + unsigned int err_mask = 0, action = 0; + struct ata_queued_cmd *qc; + u32 cerr; + + /* analyze CMD_ERR */ + cerr = readl(port + PORT_CMD_ERR); + if (cerr < ARRAY_SIZE(sil24_cerr_db)) + ci = &sil24_cerr_db[cerr]; + + if (ci && ci->desc) { + err_mask |= ci->err_mask; + action |= ci->action; + ata_ehi_push_desc(ehi, ", %s", ci->desc); + } else { + err_mask |= AC_ERR_OTHER; + action |= ATA_EH_SOFTRESET; + ata_ehi_push_desc(ehi, ", unknown command error %d", + cerr); + } -static void sil24_eng_timeout(struct ata_port *ap) -{ - struct ata_queued_cmd *qc; + /* record error info */ + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc) { + sil24_update_tf(ap); + qc->err_mask |= err_mask; + } else + ehi->err_mask |= err_mask; - qc = ata_qc_from_tag(ap, ap->active_tag); + ehi->action |= action; + } - printk(KERN_ERR "ata%u: command timeout\n", ap->id); - qc->err_mask |= AC_ERR_TIMEOUT; - ata_eh_qc_complete(qc); + /* freeze or abort */ + if (freeze) + ata_port_freeze(ap); + else + ata_port_abort(ap); +} - sil24_reset_controller(ap); +static void sil24_finish_qc(struct ata_queued_cmd *qc) +{ + if (qc->flags & ATA_QCFLAG_RESULT_TF) + sil24_update_tf(qc->ap); } -static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) +static inline void sil24_host_intr(struct ata_port *ap) { - struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); - struct sil24_port_priv *pp = ap->private_data; void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; - u32 irq_stat, cmd_err, sstatus, serror; - unsigned int err_mask; + u32 slot_stat, qc_active; + int rc; - irq_stat = readl(port + PORT_IRQ_STAT); - writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ + slot_stat = readl(port + PORT_SLOT_STAT); - if (!(irq_stat & PORT_IRQ_ERROR)) { - /* ignore non-completion, non-error irqs for now */ - printk(KERN_WARNING DRV_NAME - "ata%u: non-error exception irq (irq_stat %x)\n", - ap->id, irq_stat); + if (unlikely(slot_stat & HOST_SSTAT_ATTN)) { + sil24_error_intr(ap); return; } - cmd_err = readl(port + PORT_CMD_ERR); - sstatus = readl(port + PORT_SSTATUS); - serror = readl(port + PORT_SERROR); - if (serror) - writel(serror, port + PORT_SERROR); + if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) + writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); - /* - * Don't log ATAPI device errors. They're supposed to happen - * and any serious errors will be logged using sense data by - * the SCSI layer. - */ - if (ap->device[0].class != ATA_DEV_ATAPI || cmd_err > PORT_CERR_SDB) - printk("ata%u: error interrupt on port%d\n" - " stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n", - ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror); - - if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) { - /* - * Device is reporting error, tf registers are valid. - */ - sil24_update_tf(ap); - err_mask = ac_err_mask(pp->tf.command); - sil24_restart_controller(ap); - } else { - /* - * Other errors. libata currently doesn't have any - * mechanism to report these errors. Just turn on - * ATA_ERR. - */ - err_mask = AC_ERR_OTHER; - sil24_reset_controller(ap); + qc_active = slot_stat & ~HOST_SSTAT_ATTN; + rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc); + if (rc > 0) + return; + if (rc < 0) { + struct ata_eh_info *ehi = &ap->eh_info; + ehi->err_mask |= AC_ERR_HSM; + ehi->action |= ATA_EH_SOFTRESET; + ata_port_freeze(ap); + return; } - if (qc) { - qc->err_mask |= err_mask; - ata_qc_complete(qc); - } -} - -static inline void sil24_host_intr(struct ata_port *ap) -{ - struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); - void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; - u32 slot_stat; - - slot_stat = readl(port + PORT_SLOT_STAT); - if (!(slot_stat & HOST_SSTAT_ATTN)) { - struct sil24_port_priv *pp = ap->private_data; - /* - * !HOST_SSAT_ATTN guarantees successful completion, - * so reading back tf registers is unnecessary for - * most commands. TODO: read tf registers for - * commands which require these values on successful - * completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER, - * DEVICE RESET and READ PORT MULTIPLIER (any more?). - */ - sil24_update_tf(ap); - - if (qc) { - qc->err_mask |= ac_err_mask(pp->tf.command); - ata_qc_complete(qc); - } - } else - sil24_error_intr(ap, slot_stat); + if (ata_ratelimit()) + ata_port_printk(ap, KERN_INFO, "spurious interrupt " + "(slot_stat 0x%x active_tag %d sactive 0x%x)\n", + slot_stat, ap->active_tag, ap->sactive); } static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs) @@ -769,7 +883,7 @@ static irqreturn_t sil24_interrupt(int i for (i = 0; i < host_set->n_ports; i++) if (status & (1 << i)) { struct ata_port *ap = host_set->ports[i]; - if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) { + if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { sil24_host_intr(host_set->ports[i]); handled++; } else @@ -782,9 +896,35 @@ static irqreturn_t sil24_interrupt(int i return IRQ_RETVAL(handled); } +static void sil24_error_handler(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + + if (sil24_init_port(ap)) { + ata_eh_freeze_port(ap); + ehc->i.action |= ATA_EH_HARDRESET; + } + + /* perform recovery */ + ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset, + ata_std_postreset); +} + +static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + if (qc->flags & ATA_QCFLAG_FAILED) + qc->err_mask |= AC_ERR_OTHER; + + /* make DMA engine forget about the failed command */ + if (qc->err_mask) + sil24_init_port(ap); +} + static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev) { - const size_t cb_size = sizeof(*pp->cmd_block); + const size_t cb_size = sizeof(*pp->cmd_block) * SIL24_MAX_CMDS; dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma); } @@ -794,7 +934,7 @@ static int sil24_port_start(struct ata_p struct device *dev = ap->host_set->dev; struct sil24_port_priv *pp; union sil24_cmd_block *cb; - size_t cb_size = sizeof(*cb); + size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS; dma_addr_t cb_dma; int rc = -ENOMEM; @@ -858,6 +998,7 @@ static int sil24_init_one(struct pci_dev void __iomem *host_base = NULL; void __iomem *port_base = NULL; int i, rc; + u32 tmp; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); @@ -910,37 +1051,53 @@ static int sil24_init_one(struct pci_dev /* * Configure the device */ - /* - * FIXME: This device is certainly 64-bit capable. We just - * don't know how to use it. After fixing 32bit activation in - * this function, enable 64bit masks here. - */ - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc) { - dev_printk(KERN_ERR, &pdev->dev, - "32-bit DMA enable failed\n"); - goto out_free; - } - rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); - if (rc) { - dev_printk(KERN_ERR, &pdev->dev, - "32-bit consistent DMA enable failed\n"); - goto out_free; + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { + rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + if (rc) { + rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "64-bit DMA enable failed\n"); + goto out_free; + } + } + } else { + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "32-bit DMA enable failed\n"); + goto out_free; + } + rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "32-bit consistent DMA enable failed\n"); + goto out_free; + } } /* GPIO off */ writel(0, host_base + HOST_FLASH_CMD); - /* Mask interrupts during initialization */ + /* Apply workaround for completion IRQ loss on PCI-X errata */ + if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) { + tmp = readl(host_base + HOST_CTRL); + if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL)) + dev_printk(KERN_INFO, &pdev->dev, + "Applying completion IRQ loss on PCI-X " + "errata fix\n"); + else + probe_ent->host_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC; + } + + /* clear global reset & mask interrupts during initialization */ writel(0, host_base + HOST_CTRL); for (i = 0; i < probe_ent->n_ports; i++) { void __iomem *port = port_base + i * PORT_REGS_SIZE; unsigned long portu = (unsigned long)port; - u32 tmp; - int cnt; - probe_ent->port[i].cmd_addr = portu + PORT_PRB; + probe_ent->port[i].cmd_addr = portu; probe_ent->port[i].scr_addr = portu + PORT_SCONTROL; ata_std_ports(&probe_ent->port[i]); @@ -952,18 +1109,20 @@ static int sil24_init_one(struct pci_dev tmp = readl(port + PORT_CTRL_STAT); if (tmp & PORT_CS_PORT_RST) { writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR); - readl(port + PORT_CTRL_STAT); /* sync */ - for (cnt = 0; cnt < 10; cnt++) { - msleep(10); - tmp = readl(port + PORT_CTRL_STAT); - if (!(tmp & PORT_CS_PORT_RST)) - break; - } + tmp = ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_PORT_RST, + PORT_CS_PORT_RST, 10, 100); if (tmp & PORT_CS_PORT_RST) dev_printk(KERN_ERR, &pdev->dev, "failed to clear port RST\n"); } + /* Configure IRQ WoC */ + if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) + writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT); + else + writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); + /* Zero error counters. */ writel(0x8000, port + PORT_DECODE_ERR_THRESH); writel(0x8000, port + PORT_CRC_ERR_THRESH); @@ -972,26 +1131,11 @@ static int sil24_init_one(struct pci_dev writel(0x0000, port + PORT_CRC_ERR_CNT); writel(0x0000, port + PORT_HSHK_ERR_CNT); - /* FIXME: 32bit activation? */ - writel(0, port + PORT_ACTIVATE_UPPER_ADDR); - writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_STAT); - - /* Configure interrupts */ - writel(0xffff, port + PORT_IRQ_ENABLE_CLR); - writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | PORT_IRQ_SDB_FIS, - port + PORT_IRQ_ENABLE_SET); - - /* Clear interrupts */ - writel(0x0fff0fff, port + PORT_IRQ_STAT); - writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); + /* Always use 64bit activation */ + writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); /* Clear port multiplier enable and resume bits */ writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR); - - /* Reset itself */ - if (__sil24_reset_controller(port)) - dev_printk(KERN_ERR, &pdev->dev, - "failed to reset controller\n"); } /* Turn on interrupts */ diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 728530d..809d337 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -43,7 +43,7 @@ #include #include #define DRV_NAME "sata_sis" -#define DRV_VERSION "0.5" +#define DRV_VERSION "0.6" enum { sis_180 = 0, @@ -96,6 +96,7 @@ static struct scsi_host_template sis_sht .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -106,14 +107,17 @@ static const struct ata_port_operations .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, + .data_xfer = ata_pio_data_xfer, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = sis_scr_read, @@ -125,8 +129,7 @@ static const struct ata_port_operations static struct ata_port_info sis_port_info = { .sht = &sis_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | - ATA_FLAG_NO_LEGACY, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, .mwdma_mask = 0x7, .udma_mask = 0x7f, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 53b0d5c..c94b870 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -54,7 +54,7 @@ #include #endif /* CONFIG_PPC_OF */ #define DRV_NAME "sata_svw" -#define DRV_VERSION "1.07" +#define DRV_VERSION "1.8" enum { /* Taskfile registers offsets */ @@ -257,7 +257,7 @@ static int k2_sata_proc_info(struct Scsi int len, index; /* Find the ata_port */ - ap = (struct ata_port *) &shost->hostdata[0]; + ap = ata_shost_to_port(shost); if (ap == NULL) return 0; @@ -299,6 +299,7 @@ static struct scsi_host_template k2_sata .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, #ifdef CONFIG_PPC_OF .proc_info = k2_sata_proc_info, #endif @@ -313,14 +314,17 @@ static const struct ata_port_operations .check_status = k2_stat_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, .bmdma_setup = k2_bmdma_setup_mmio, .bmdma_start = k2_bmdma_start_mmio, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, + .data_xfer = ata_mmio_data_xfer, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = k2_sata_scr_read, @@ -420,8 +424,8 @@ static int k2_sata_init_one (struct pci_ writel(0x0, mmio_base + K2_SATA_SIM_OFFSET); probe_ent->sht = &k2_sata_sht; - probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | - ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; + probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO; probe_ent->port_ops = &k2_sata_ops; probe_ent->n_ports = 4; probe_ent->irq = pdev->irq; diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 4139ad4..7f86441 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -46,7 +46,7 @@ #include #include "sata_promise.h" #define DRV_NAME "sata_sx4" -#define DRV_VERSION "0.8" +#define DRV_VERSION "0.9" enum { @@ -191,6 +191,7 @@ static struct scsi_host_template pdc_sat .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -204,6 +205,7 @@ static const struct ata_port_operations .phy_reset = pdc_20621_phy_reset, .qc_prep = pdc20621_qc_prep, .qc_issue = pdc20621_qc_issue_prot, + .data_xfer = ata_mmio_data_xfer, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc20621_interrupt, .irq_clear = pdc20621_irq_clear, @@ -218,7 +220,7 @@ static const struct ata_port_info pdc_po .sht = &pdc_sata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO | - ATA_FLAG_NO_ATAPI, + ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -833,11 +835,11 @@ static irqreturn_t pdc20621_interrupt (i tmp = mask & (1 << i); VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); if (tmp && ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += pdc20621_host_intr(ap, qc, (i > 4), mmio_base); } @@ -868,15 +870,16 @@ static void pdc_eng_timeout(struct ata_p switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: - printk(KERN_ERR "ata%u: command timeout\n", ap->id); + ata_port_printk(ap, KERN_ERR, "command timeout\n"); qc->err_mask |= __ac_err_mask(ata_wait_idle(ap)); break; default: drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); - printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n", - ap->id, qc->tf.command, drv_stat); + ata_port_printk(ap, KERN_ERR, + "unknown timeout, cmd 0x%x stat 0x%x\n", + qc->tf.command, drv_stat); qc->err_mask |= ac_err_mask(drv_stat); break; @@ -1375,10 +1378,6 @@ static int pdc_sata_init_one (struct pci if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - /* - * If this driver happens to only be useful on Apple's K2, then - * we should check that here as it has a normal Serverworks ID - */ rc = pci_enable_device(pdev); if (rc) return rc; diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 38b52bd..f668c99 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -37,7 +37,7 @@ #include #include #define DRV_NAME "sata_uli" -#define DRV_VERSION "0.5" +#define DRV_VERSION "0.6" enum { uli_5289 = 0, @@ -90,6 +90,7 @@ static struct scsi_host_template uli_sht .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -102,16 +103,18 @@ static const struct ata_port_operations .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, - .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -126,8 +129,7 @@ static const struct ata_port_operations static struct ata_port_info uli_port_info = { .sht = &uli_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | - ATA_FLAG_NO_LEGACY, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &uli_ops, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 9e7ae4e..322890b 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -47,7 +47,7 @@ #include #include #define DRV_NAME "sata_via" -#define DRV_VERSION "1.1" +#define DRV_VERSION "1.2" enum board_ids_enum { vt6420, @@ -103,6 +103,7 @@ static struct scsi_host_template svia_sh .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -115,8 +116,6 @@ static const struct ata_port_operations .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, - .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, @@ -124,8 +123,12 @@ static const struct ata_port_operations .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, - .eng_timeout = ata_eng_timeout, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -140,7 +143,7 @@ static const struct ata_port_operations static struct ata_port_info svia_port_info = { .sht = &svia_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x7f, @@ -235,8 +238,7 @@ static struct ata_probe_ent *vt6421_init INIT_LIST_HEAD(&probe_ent->node); probe_ent->sht = &svia_sht; - probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | - ATA_FLAG_NO_LEGACY; + probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY; probe_ent->port_ops = &svia_sata_ops; probe_ent->n_ports = N_PORTS; probe_ent->irq = pdev->irq; diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 8a29ce3..6d0c4f1 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -221,14 +221,21 @@ static irqreturn_t vsc_sata_interrupt (i ap = host_set->ports[i]; - if (ap && !(ap->flags & - (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { + if (is_vsc_sata_int_err(i, int_status)) { + u32 err_status; + printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__); + err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0; + vsc_sata_scr_write(ap, SCR_ERROR, err_status); + handled++; + } + + if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += ata_host_intr(ap, qc); - } else if (is_vsc_sata_int_err(i, int_status)) { + else if (is_vsc_sata_int_err(i, int_status)) { /* * On some chips (i.e. Intel 31244), an error * interrupt will sneak in at initialization @@ -272,6 +279,7 @@ static struct scsi_host_template vsc_sat .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -283,14 +291,17 @@ static const struct ata_port_operations .exec_command = ata_exec_command, .check_status = ata_check_status, .dev_select = ata_std_dev_select, - .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, + .data_xfer = ata_pio_data_xfer, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = ata_bmdma_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = vsc_sata_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = vsc_sata_scr_read, @@ -385,7 +396,7 @@ static int __devinit vsc_sata_init_one ( probe_ent->sht = &vsc_sata_sht; probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_SATA_RESET; + ATA_FLAG_MMIO; probe_ent->port_ops = &vsc_sata_ops; probe_ent->n_ports = 4; probe_ent->irq = pdev->irq; @@ -433,13 +444,14 @@ err_out: /* - * 0x1725/0x7174 is the Vitesse VSC-7174 - * 0x8086/0x3200 is the Intel 31244, which is supposed to be identical - * compatibility is untested as of yet + * Intel 31244 is supposed to be identical. + * Compatibility is untested as of yet. */ static const struct pci_device_id vsc_sata_pci_tbl[] = { - { 0x1725, 0x7174, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, - { 0x8086, 0x3200, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, + { PCI_VENDOR_ID_VITESSE, PCI_DEVICE_ID_VITESSE_VSC7174, + PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GD31244, + PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, { } }; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 73994e2..2ab7df0 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -63,7 +63,6 @@ #include #include #include #include -#include #include "scsi_priv.h" #include "scsi_logging.h" @@ -116,79 +115,6 @@ const char *const scsi_device_types[MAX_ }; EXPORT_SYMBOL(scsi_device_types); -/* - * Function: scsi_allocate_request - * - * Purpose: Allocate a request descriptor. - * - * Arguments: device - device for which we want a request - * gfp_mask - allocation flags passed to kmalloc - * - * Lock status: No locks assumed to be held. This function is SMP-safe. - * - * Returns: Pointer to request block. - */ -struct scsi_request *scsi_allocate_request(struct scsi_device *sdev, - gfp_t gfp_mask) -{ - const int offset = ALIGN(sizeof(struct scsi_request), 4); - const int size = offset + sizeof(struct request); - struct scsi_request *sreq; - - sreq = kzalloc(size, gfp_mask); - if (likely(sreq != NULL)) { - sreq->sr_request = (struct request *)(((char *)sreq) + offset); - sreq->sr_device = sdev; - sreq->sr_host = sdev->host; - sreq->sr_magic = SCSI_REQ_MAGIC; - sreq->sr_data_direction = DMA_BIDIRECTIONAL; - } - - return sreq; -} -EXPORT_SYMBOL(scsi_allocate_request); - -void __scsi_release_request(struct scsi_request *sreq) -{ - struct request *req = sreq->sr_request; - - /* unlikely because the tag was usually ended earlier by the - * mid-layer. However, for layering reasons ULD's don't end - * the tag of commands they generate. */ - if (unlikely(blk_rq_tagged(req))) { - unsigned long flags; - struct request_queue *q = req->q; - - spin_lock_irqsave(q->queue_lock, flags); - blk_queue_end_tag(q, req); - spin_unlock_irqrestore(q->queue_lock, flags); - } - - - if (likely(sreq->sr_command != NULL)) { - struct scsi_cmnd *cmd = sreq->sr_command; - - sreq->sr_command = NULL; - scsi_next_command(cmd); - } -} - -/* - * Function: scsi_release_request - * - * Purpose: Release a request descriptor. - * - * Arguments: sreq - request to release - * - * Lock status: No locks assumed to be held. This function is SMP-safe. - */ -void scsi_release_request(struct scsi_request *sreq) -{ - __scsi_release_request(sreq); - kfree(sreq); -} -EXPORT_SYMBOL(scsi_release_request); - struct scsi_host_cmd_pool { kmem_cache_t *slab; unsigned int users; @@ -646,73 +572,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd * return rtn; } -/* - * Function: scsi_init_cmd_from_req - * - * Purpose: Queue a SCSI command - * Purpose: Initialize a struct scsi_cmnd from a struct scsi_request - * - * Arguments: cmd - command descriptor. - * sreq - Request from the queue. - * - * Lock status: None needed. - * - * Returns: Nothing. - * - * Notes: Mainly transfer data from the request structure to the - * command structure. The request structure is allocated - * using the normal memory allocator, and requests can pile - * up to more or less any depth. The command structure represents - * a consumable resource, as these are allocated into a pool - * when the SCSI subsystem initializes. The preallocation is - * required so that in low-memory situations a disk I/O request - * won't cause the memory manager to try and write out a page. - * The request structure is generally used by ioctls and character - * devices. - */ -void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, struct scsi_request *sreq) -{ - sreq->sr_command = cmd; - - cmd->cmd_len = sreq->sr_cmd_len; - cmd->use_sg = sreq->sr_use_sg; - - cmd->request = sreq->sr_request; - memcpy(cmd->data_cmnd, sreq->sr_cmnd, sizeof(cmd->data_cmnd)); - cmd->serial_number = 0; - cmd->bufflen = sreq->sr_bufflen; - cmd->buffer = sreq->sr_buffer; - cmd->retries = 0; - cmd->allowed = sreq->sr_allowed; - cmd->done = sreq->sr_done; - cmd->timeout_per_command = sreq->sr_timeout_per_command; - cmd->sc_data_direction = sreq->sr_data_direction; - cmd->sglist_len = sreq->sr_sglist_len; - cmd->underflow = sreq->sr_underflow; - cmd->sc_request = sreq; - memcpy(cmd->cmnd, sreq->sr_cmnd, sizeof(sreq->sr_cmnd)); - - /* - * Zero the sense buffer. Some host adapters automatically request - * sense on error. 0 is not a valid sense code. - */ - memset(cmd->sense_buffer, 0, sizeof(sreq->sr_sense_buffer)); - cmd->request_buffer = sreq->sr_buffer; - cmd->request_bufflen = sreq->sr_bufflen; - cmd->old_use_sg = cmd->use_sg; - if (cmd->cmd_len == 0) - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); - cmd->old_cmd_len = cmd->cmd_len; - cmd->sc_old_data_direction = cmd->sc_data_direction; - cmd->old_underflow = cmd->underflow; - - /* - * Start the timer ticking. - */ - cmd->result = 0; - - SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_init_cmd_from_req()\n")); -} /* * Per-CPU I/O completion queue. @@ -720,6 +579,24 @@ void scsi_init_cmd_from_req(struct scsi_ static DEFINE_PER_CPU(struct list_head, scsi_done_q); /** + * scsi_req_abort_cmd -- Request command recovery for the specified command + * cmd: pointer to the SCSI command of interest + * + * This function requests that SCSI Core start recovery for the + * command by deleting the timer and adding the command to the eh + * queue. It can be called by either LLDDs or SCSI Core. LLDDs who + * implement their own error recovery MAY ignore the timeout event if + * they generated scsi_req_abort_cmd. + */ +void scsi_req_abort_cmd(struct scsi_cmnd *cmd) +{ + if (!scsi_delete_timer(cmd)) + return; + scsi_times_out(cmd); +} +EXPORT_SYMBOL(scsi_req_abort_cmd); + +/** * scsi_done - Enqueue the finished SCSI command into the done queue. * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives * ownership back to SCSI Core -- i.e. the LLDD has finished with it. @@ -809,7 +686,6 @@ void scsi_finish_command(struct scsi_cmn { struct scsi_device *sdev = cmd->device; struct Scsi_Host *shost = sdev->host; - struct scsi_request *sreq; scsi_device_unbusy(sdev); @@ -839,21 +715,6 @@ void scsi_finish_command(struct scsi_cmn * We can get here with use_sg=0, causing a panic in the upper level */ cmd->use_sg = cmd->old_use_sg; - - /* - * If there is an associated request structure, copy the data over - * before we call the completion function. - */ - sreq = cmd->sc_request; - if (sreq) { - sreq->sr_result = sreq->sr_command->result; - if (sreq->sr_result) { - memcpy(sreq->sr_sense_buffer, - sreq->sr_command->sense_buffer, - sizeof(sreq->sr_sense_buffer)); - } - } - cmd->done(cmd); } EXPORT_SYMBOL(scsi_finish_command); diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h index 5ee5d80..f51e466 100644 --- a/drivers/scsi/scsi.h +++ b/drivers/scsi/scsi.h @@ -25,7 +25,6 @@ #include /* for CON #include #include #include -#include #include #include diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 62f8cb7..fb5cb4c 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -159,6 +159,8 @@ static struct { {"HITACHI", "DF400", "*", BLIST_SPARSELUN}, {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, + {"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN}, + {"HITACHI", "OPEN-E", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN}, {"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP VA7400 */ {"HP", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP XP Arrays */ {"HP", "NetRAID-4M", NULL, BLIST_FORCELUN}, diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 1c75646..6a7a60f 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -26,13 +26,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include "scsi_priv.h" #include "scsi_logging.h" @@ -58,6 +58,28 @@ void scsi_eh_wakeup(struct Scsi_Host *sh } /** + * scsi_schedule_eh - schedule EH for SCSI host + * @shost: SCSI host to invoke error handling on. + * + * Schedule SCSI EH without scmd. + **/ +void scsi_schedule_eh(struct Scsi_Host *shost) +{ + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + + if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 || + scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) { + shost->host_eh_scheduled++; + scsi_eh_wakeup(shost); + } + + spin_unlock_irqrestore(shost->host_lock, flags); +} +EXPORT_SYMBOL_GPL(scsi_schedule_eh); + +/** * scsi_eh_scmd_add - add scsi cmd to error handling. * @scmd: scmd to run eh on. * @eh_flag: optional SCSI_EH flag. @@ -452,7 +474,6 @@ static int scsi_send_eh_cmnd(struct scsi (sdev->lun << 5 & 0xe0); shost->eh_action = &done; - scmd->request->rq_status = RQ_SCSI_BUSY; spin_lock_irqsave(shost->host_lock, flags); scsi_log_send(scmd); @@ -461,7 +482,6 @@ static int scsi_send_eh_cmnd(struct scsi timeleft = wait_for_completion_timeout(&done, timeout); - scmd->request->rq_status = RQ_SCSI_DONE; shost->eh_action = NULL; scsi_log_completion(scmd, SUCCESS); @@ -1517,7 +1537,7 @@ int scsi_error_handler(void *data) */ set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { - if (shost->host_failed == 0 || + if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || shost->host_failed != shost->host_busy) { SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d sleeping\n", @@ -1657,7 +1677,6 @@ scsi_reset_provider(struct scsi_device * scmd->request = &req; memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout)); - scmd->request->rq_status = RQ_SCSI_BUSY; memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd)); @@ -1671,8 +1690,6 @@ scsi_reset_provider(struct scsi_device * scmd->cmd_len = 0; scmd->sc_data_direction = DMA_BIDIRECTIONAL; - scmd->sc_request = NULL; - scmd->sc_magic = SCSI_CMND_MAGIC; init_timer(&scmd->eh_timeout); @@ -1769,14 +1786,6 @@ int scsi_normalize_sense(const u8 *sense } EXPORT_SYMBOL(scsi_normalize_sense); -int scsi_request_normalize_sense(struct scsi_request *sreq, - struct scsi_sense_hdr *sshdr) -{ - return scsi_normalize_sense(sreq->sr_sense_buffer, - sizeof(sreq->sr_sense_buffer), sshdr); -} -EXPORT_SYMBOL(scsi_request_normalize_sense); - int scsi_command_normalize_sense(struct scsi_cmnd *cmd, struct scsi_sense_hdr *sshdr) { diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index a89aff6..a89c411 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -15,11 +15,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index faee475..3d04a9f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -19,18 +19,18 @@ #include #include #include +#include #include #include #include #include #include -#include #include "scsi_priv.h" #include "scsi_logging.h" -#define SG_MEMPOOL_NR (sizeof(scsi_sg_pools)/sizeof(struct scsi_host_sg_pool)) +#define SG_MEMPOOL_NR ARRAY_SIZE(scsi_sg_pools) #define SG_MEMPOOL_SIZE 32 struct scsi_host_sg_pool { @@ -83,7 +83,7 @@ static void scsi_unprep_request(struct r struct scsi_cmnd *cmd = req->special; req->flags &= ~REQ_DONTPREP; - req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL; + req->special = NULL; scsi_put_command(cmd); } @@ -161,72 +161,6 @@ int scsi_queue_insert(struct scsi_cmnd * return 0; } -/* - * Function: scsi_do_req - * - * Purpose: Queue a SCSI request - * - * Arguments: sreq - command descriptor. - * cmnd - actual SCSI command to be performed. - * buffer - data buffer. - * bufflen - size of data buffer. - * done - completion function to be run. - * timeout - how long to let it run before timeout. - * retries - number of retries we allow. - * - * Lock status: No locks held upon entry. - * - * Returns: Nothing. - * - * Notes: This function is only used for queueing requests for things - * like ioctls and character device requests - this is because - * we essentially just inject a request into the queue for the - * device. - * - * In order to support the scsi_device_quiesce function, we - * now inject requests on the *head* of the device queue - * rather than the tail. - */ -void scsi_do_req(struct scsi_request *sreq, const void *cmnd, - void *buffer, unsigned bufflen, - void (*done)(struct scsi_cmnd *), - int timeout, int retries) -{ - /* - * If the upper level driver is reusing these things, then - * we should release the low-level block now. Another one will - * be allocated later when this request is getting queued. - */ - __scsi_release_request(sreq); - - /* - * Our own function scsi_done (which marks the host as not busy, - * disables the timeout counter, etc) will be called by us or by the - * scsi_hosts[host].queuecommand() function needs to also call - * the completion function for the high level driver. - */ - memcpy(sreq->sr_cmnd, cmnd, sizeof(sreq->sr_cmnd)); - sreq->sr_bufflen = bufflen; - sreq->sr_buffer = buffer; - sreq->sr_allowed = retries; - sreq->sr_done = done; - sreq->sr_timeout_per_command = timeout; - - if (sreq->sr_cmd_len == 0) - sreq->sr_cmd_len = COMMAND_SIZE(sreq->sr_cmnd[0]); - - /* - * head injection *required* here otherwise quiesce won't work - * - * Because users of this function are apt to reuse requests with no - * modification, we have to sanitise the request flags here - */ - sreq->sr_request->flags &= ~REQ_DONTPREP; - blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request, - 1, sreq); -} -EXPORT_SYMBOL(scsi_do_req); - /** * scsi_execute - insert request and wait for the result * @sdev: scsi device @@ -566,7 +500,7 @@ void scsi_device_unbusy(struct scsi_devi spin_lock_irqsave(shost->host_lock, flags); shost->host_busy--; if (unlikely(scsi_host_in_recovery(shost) && - shost->host_failed)) + (shost->host_failed || shost->host_eh_scheduled))) scsi_eh_wakeup(shost); spin_unlock(shost->host_lock); spin_lock(sdev->request_queue->queue_lock); @@ -1300,15 +1234,7 @@ static int scsi_prep_fn(struct request_q * at request->cmd, as this tells us the real story. */ if (req->flags & REQ_SPECIAL && req->special) { - struct scsi_request *sreq = req->special; - - if (sreq->sr_magic == SCSI_REQ_MAGIC) { - cmd = scsi_get_command(sreq->sr_device, GFP_ATOMIC); - if (unlikely(!cmd)) - goto defer; - scsi_init_cmd_from_req(cmd, sreq); - } else - cmd = req->special; + cmd = req->special; } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) { @@ -2363,3 +2289,61 @@ scsi_target_unblock(struct device *dev) device_for_each_child(dev, NULL, target_unblock); } EXPORT_SYMBOL_GPL(scsi_target_unblock); + +/** + * scsi_kmap_atomic_sg - find and atomically map an sg-elemnt + * @sg: scatter-gather list + * @sg_count: number of segments in sg + * @offset: offset in bytes into sg, on return offset into the mapped area + * @len: bytes to map, on return number of bytes mapped + * + * Returns virtual address of the start of the mapped page + */ +void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, + size_t *offset, size_t *len) +{ + int i; + size_t sg_len = 0, len_complete = 0; + struct page *page; + + for (i = 0; i < sg_count; i++) { + len_complete = sg_len; /* Complete sg-entries */ + sg_len += sg[i].length; + if (sg_len > *offset) + break; + } + + if (unlikely(i == sg_count)) { + printk(KERN_ERR "%s: Bytes in sg: %zu, requested offset %zu, " + "elements %d\n", + __FUNCTION__, sg_len, *offset, sg_count); + WARN_ON(1); + return NULL; + } + + /* Offset starting from the beginning of first page in this sg-entry */ + *offset = *offset - len_complete + sg[i].offset; + + /* Assumption: contiguous pages can be accessed as "page + i" */ + page = nth_page(sg[i].page, (*offset >> PAGE_SHIFT)); + *offset &= ~PAGE_MASK; + + /* Bytes in this sg-entry from *offset to the end of the page */ + sg_len = PAGE_SIZE - *offset; + if (*len > sg_len) + *len = sg_len; + + return kmap_atomic(page, KM_BIO_SRC_IRQ); +} +EXPORT_SYMBOL(scsi_kmap_atomic_sg); + +/** + * scsi_kunmap_atomic_sg - atomically unmap a virtual address, previously + * mapped with scsi_kmap_atomic_sg + * @virt: virtual address to be unmapped + */ +void scsi_kunmap_atomic_sg(void *virt) +{ + kunmap_atomic(virt, KM_BIO_SRC_IRQ); +} +EXPORT_SYMBOL(scsi_kunmap_atomic_sg); diff --git a/drivers/scsi/scsi_logging.h b/drivers/scsi/scsi_logging.h index e1722ba..a3e2af6 100644 --- a/drivers/scsi/scsi_logging.h +++ b/drivers/scsi/scsi_logging.h @@ -45,10 +45,12 @@ #define SCSI_LOG_LEVEL(SHIFT, BITS) \ ((scsi_logging_level >> (SHIFT)) & ((1 << (BITS)) - 1)) #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) \ -{ \ +do { \ if (unlikely((SCSI_LOG_LEVEL(SHIFT, BITS)) > (LEVEL))) \ - (CMD); \ -} + do { \ + CMD; \ + } while (0); \ +} while (0) #else #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) #endif /* CONFIG_SCSI_LOGGING */ diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 27c4827..a1727a0 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -8,17 +8,10 @@ struct request_queue; struct scsi_cmnd; struct scsi_device; struct scsi_host_template; -struct scsi_request; struct Scsi_Host; /* - * Magic values for certain scsi structs. Shouldn't ever be used. - */ -#define SCSI_CMND_MAGIC 0xE25C23A5 -#define SCSI_REQ_MAGIC 0x75F6D354 - -/* * Scsi Error Handler Flags */ #define SCSI_EH_CANCEL_CMD 0x0001 /* Cancel this cmd */ @@ -34,9 +27,6 @@ extern void scsi_exit_hosts(void); extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); extern int scsi_setup_command_freelist(struct Scsi_Host *shost); extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); -extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, - struct scsi_request *sreq); -extern void __scsi_release_request(struct scsi_request *sreq); extern void __scsi_done(struct scsi_cmnd *cmd); extern int scsi_retry_command(struct scsi_cmnd *cmd); #ifdef CONFIG_SCSI_LOGGING diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 07be62b..55200e4 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -266,8 +266,6 @@ static ssize_t proc_scsi_write(struct fi lun = simple_strtoul(p + 1, &p, 0); err = scsi_add_single_device(host, channel, id, lun); - if (err >= 0) - err = length; /* * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi @@ -284,6 +282,13 @@ static ssize_t proc_scsi_write(struct fi err = scsi_remove_single_device(host, channel, id, lun); } + /* + * convert success returns so that we return the + * number of bytes consumed. + */ + if (!err) + err = length; + out: free_page((unsigned long)buffer); return err; diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 1a5474b..0f7e6f9 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -33,11 +33,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -816,6 +816,32 @@ static inline void scsi_destroy_sdev(str put_device(&sdev->sdev_gendev); } +#ifdef CONFIG_SCSI_LOGGING +/** + * scsi_inq_str - print INQUIRY data from min to max index, + * strip trailing whitespace + * @buf: Output buffer with at least end-first+1 bytes of space + * @inq: Inquiry buffer (input) + * @first: Offset of string into inq + * @end: Index after last character in inq + */ +static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, + unsigned first, unsigned end) +{ + unsigned term = 0, idx; + + for (idx = 0; idx + first < end && idx + first < inq[4] + 5; idx++) { + if (inq[idx+first] > ' ') { + buf[idx] = inq[idx+first]; + term = idx+1; + } else { + buf[idx] = ' '; + } + } + buf[term] = 0; + return buf; +} +#endif /** * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it @@ -880,10 +906,12 @@ static int scsi_probe_and_add_lun(struct if (scsi_probe_lun(sdev, result, result_len, &bflags)) goto out_free_result; + if (bflagsp) + *bflagsp = bflags; /* * result contains valid SCSI INQUIRY data. */ - if ((result[0] >> 5) == 3) { + if (((result[0] >> 5) == 3) && !(bflags & BLIST_ATTACH_PQ3)) { /* * For a Peripheral qualifier 3 (011b), the SCSI * spec says: The device server is not capable of @@ -894,9 +922,22 @@ static int scsi_probe_and_add_lun(struct * logical disk configured at sdev->lun, but there * is a target id responding. */ - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO - "scsi scan: peripheral qualifier of 3," - " no device added\n")); + SCSI_LOG_SCAN_BUS(2, sdev_printk(KERN_INFO, sdev, "scsi scan:" + " peripheral qualifier of 3, device not" + " added\n")) + if (lun == 0) { + SCSI_LOG_SCAN_BUS(1, { + unsigned char vend[9]; + unsigned char mod[17]; + + sdev_printk(KERN_INFO, sdev, + "scsi scan: consider passing scsi_mod." + "dev_flags=%s:%s:0x240 or 0x800240\n", + scsi_inq_str(vend, result, 8, 16), + scsi_inq_str(mod, result, 16, 32)); + }); + } + res = SCSI_SCAN_TARGET_PRESENT; goto out_free_result; } @@ -920,8 +961,6 @@ static int scsi_probe_and_add_lun(struct sdev->lockable = 0; scsi_unlock_floptical(sdev, result); } - if (bflagsp) - *bflagsp = bflags; } out_free_result: @@ -946,7 +985,6 @@ static int scsi_probe_and_add_lun(struct * scsi_sequential_lun_scan - sequentially scan a SCSI target * @starget: pointer to target structure to scan * @bflags: black/white list flag for LUN 0 - * @lun0_res: result of scanning LUN 0 * * Description: * Generally, scan from LUN 1 (LUN 0 is assumed to already have been @@ -956,8 +994,7 @@ static int scsi_probe_and_add_lun(struct * Modifies sdevscan->lun. **/ static void scsi_sequential_lun_scan(struct scsi_target *starget, - int bflags, int lun0_res, int scsi_level, - int rescan) + int bflags, int scsi_level, int rescan) { unsigned int sparse_lun, lun, max_dev_lun; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); @@ -978,13 +1015,6 @@ static void scsi_sequential_lun_scan(str sparse_lun = 0; /* - * If not sparse lun and no device attached at LUN 0 do not scan - * any further. - */ - if (!sparse_lun && (lun0_res != SCSI_SCAN_LUN_PRESENT)) - return; - - /* * If less than SCSI_1_CSS, and no special lun scaning, stop * scanning; this matches 2.4 behaviour, but could just be a bug * (to continue scanning a SCSI_1_CSS device). @@ -1395,7 +1425,7 @@ static void __scsi_scan_target(struct de * do a sequential scan. */ scsi_sequential_lun_scan(starget, bflags, - res, starget->scsi_level, rescan); + starget->scsi_level, rescan); } out_reap: @@ -1473,7 +1503,7 @@ int scsi_scan_host_selected(struct Scsi_ __FUNCTION__, channel, id, lun)); if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || - ((id != SCAN_WILD_CARD) && (id > shost->max_id)) || + ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) return -EINVAL; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index a6fde52..5ec7a4f 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -39,7 +39,7 @@ const char *scsi_device_state_name(enum int i; char *name = NULL; - for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(sdev_states); i++) { if (sdev_states[i].value == state) { name = sdev_states[i].name; break; @@ -65,7 +65,7 @@ const char *scsi_host_state_name(enum sc int i; char *name = NULL; - for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(shost_states); i++) { if (shost_states[i].value == state) { name = shost_states[i].name; break; @@ -160,7 +160,7 @@ store_shost_state(struct class_device *c struct Scsi_Host *shost = class_to_shost(class_dev); enum scsi_host_state state = 0; - for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(shost_states); i++) { const int len = strlen(shost_states[i].name); if (strncmp(shost_states[i].name, buf, len) == 0 && buf[len] == '\n') { @@ -466,7 +466,7 @@ store_state_field(struct device *dev, st struct scsi_device *sdev = to_scsi_device(dev); enum scsi_device_state state = 0; - for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) { + for (i = 0; i < ARRAY_SIZE(sdev_states); i++) { const int len = strlen(sdev_states[i].name); if (strncmp(sdev_states[i].name, buf, len) == 0 && buf[len] == '\n') { diff --git a/drivers/scsi/scsi_transport_api.h b/drivers/scsi/scsi_transport_api.h new file mode 100644 index 0000000..934f0e6 --- /dev/null +++ b/drivers/scsi/scsi_transport_api.h @@ -0,0 +1,6 @@ +#ifndef _SCSI_TRANSPORT_API_H +#define _SCSI_TRANSPORT_API_H + +void scsi_schedule_eh(struct Scsi_Host *shost); + +#endif /* _SCSI_TRANSPORT_API_H */ diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 95c5478..f2db7a4 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -50,7 +50,7 @@ static const char *get_fc_##title##_name int i; \ char *name = NULL; \ \ - for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ + for (i = 0; i < ARRAY_SIZE(table); i++) { \ if (table[i].value == table_key) { \ name = table[i].name; \ break; \ @@ -65,7 +65,7 @@ static int get_fc_##title##_match(const { \ int i; \ \ - for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ + for (i = 0; i < ARRAY_SIZE(table); i++) { \ if (strncmp(table_key, table[i].name, \ table[i].matchlen) == 0) { \ *value = table[i].value; \ @@ -140,7 +140,7 @@ get_fc_##title##_names(u32 table_key, ch ssize_t len = 0; \ int i; \ \ - for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ + for (i = 0; i < ARRAY_SIZE(table); i++) { \ if (table[i].value & table_key) { \ len += sprintf(buf + len, "%s%s", \ prefix, table[i].name); \ diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 2730d50..5569fdc 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -31,31 +31,26 @@ #include #include #include -#define ISCSI_SESSION_ATTRS 8 -#define ISCSI_CONN_ATTRS 6 +#define ISCSI_SESSION_ATTRS 11 +#define ISCSI_CONN_ATTRS 11 +#define ISCSI_HOST_ATTRS 0 struct iscsi_internal { + int daemon_pid; struct scsi_transport_template t; struct iscsi_transport *iscsi_transport; struct list_head list; - /* - * based on transport capabilities, at register time we set these - * bits to tell the transport class it wants attributes displayed - * in sysfs or that it can support different iSCSI Data-Path - * capabilities - */ - uint32_t param_mask; - struct class_device cdev; - /* - * We do not have any private or other attrs. - */ + + struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1]; struct transport_container conn_cont; struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1]; struct transport_container session_cont; struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1]; }; +static int iscsi_session_nr; /* sysfs session id for next new session */ + /* * list of registered transports and lock that must * be held while accessing list. The iscsi_transport_lock must @@ -120,6 +115,24 @@ static struct attribute_group iscsi_tran .attrs = iscsi_transport_attrs, }; +static int iscsi_setup_host(struct transport_container *tc, struct device *dev, + struct class_device *cdev) +{ + struct Scsi_Host *shost = dev_to_shost(dev); + struct iscsi_host *ihost = shost->shost_data; + + memset(ihost, 0, sizeof(*ihost)); + INIT_LIST_HEAD(&ihost->sessions); + mutex_init(&ihost->mutex); + return 0; +} + +static DECLARE_TRANSPORT_CLASS(iscsi_host_class, + "iscsi_host", + iscsi_setup_host, + NULL, + NULL); + static DECLARE_TRANSPORT_CLASS(iscsi_session_class, "iscsi_session", NULL, @@ -133,7 +146,6 @@ static DECLARE_TRANSPORT_CLASS(iscsi_con NULL); static struct sock *nls; -static int daemon_pid; static DEFINE_MUTEX(rx_queue_mutex); struct mempool_zone { @@ -165,14 +177,23 @@ static DEFINE_SPINLOCK(sesslock); static LIST_HEAD(connlist); static DEFINE_SPINLOCK(connlock); -static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle) +static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn) +{ + struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent); + return sess->sid; +} + +/* + * Returns the matching session to a given sid + */ +static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid) { unsigned long flags; struct iscsi_cls_session *sess; spin_lock_irqsave(&sesslock, flags); list_for_each_entry(sess, &sesslist, sess_list) { - if (sess == iscsi_ptr(handle)) { + if (sess->sid == sid) { spin_unlock_irqrestore(&sesslock, flags); return sess; } @@ -181,14 +202,17 @@ static struct iscsi_cls_session *iscsi_s return NULL; } -static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle) +/* + * Returns the matching connection to a given sid / cid tuple + */ +static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid) { unsigned long flags; struct iscsi_cls_conn *conn; spin_lock_irqsave(&connlock, flags); list_for_each_entry(conn, &connlist, conn_list) { - if (conn == iscsi_ptr(handle)) { + if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) { spin_unlock_irqrestore(&connlock, flags); return conn; } @@ -209,6 +233,7 @@ static void iscsi_session_release(struct shost = iscsi_session_to_shost(session); scsi_host_put(shost); + kfree(session->targetname); kfree(session); module_put(transport->owner); } @@ -218,30 +243,95 @@ static int iscsi_is_session_dev(const st return dev->release == iscsi_session_release; } +static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, + uint id, uint lun) +{ + struct iscsi_host *ihost = shost->shost_data; + struct iscsi_cls_session *session; + + mutex_lock(&ihost->mutex); + list_for_each_entry(session, &ihost->sessions, host_list) { + if ((channel == SCAN_WILD_CARD || + channel == session->channel) && + (id == SCAN_WILD_CARD || id == session->target_id)) + scsi_scan_target(&session->dev, session->channel, + session->target_id, lun, 1); + } + mutex_unlock(&ihost->mutex); + + return 0; +} + +static void session_recovery_timedout(void *data) +{ + struct iscsi_cls_session *session = data; + + dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed " + "out after %d secs\n", session->recovery_tmo); + + if (session->transport->session_recovery_timedout) + session->transport->session_recovery_timedout(session); + + scsi_target_unblock(&session->dev); +} + +void iscsi_unblock_session(struct iscsi_cls_session *session) +{ + if (!cancel_delayed_work(&session->recovery_work)) + flush_scheduled_work(); + scsi_target_unblock(&session->dev); +} +EXPORT_SYMBOL_GPL(iscsi_unblock_session); + +void iscsi_block_session(struct iscsi_cls_session *session) +{ + scsi_target_block(&session->dev); + schedule_delayed_work(&session->recovery_work, + session->recovery_tmo * HZ); +} +EXPORT_SYMBOL_GPL(iscsi_block_session); + /** * iscsi_create_session - create iscsi class session * @shost: scsi host * @transport: iscsi transport * - * This can be called from a LLD or iscsi_transport + * This can be called from a LLD or iscsi_transport. **/ struct iscsi_cls_session * -iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport) +iscsi_create_session(struct Scsi_Host *shost, + struct iscsi_transport *transport, int channel) { + struct iscsi_host *ihost; struct iscsi_cls_session *session; int err; if (!try_module_get(transport->owner)) return NULL; - session = kzalloc(sizeof(*session), GFP_KERNEL); + session = kzalloc(sizeof(*session) + transport->sessiondata_size, + GFP_KERNEL); if (!session) goto module_put; session->transport = transport; + session->recovery_tmo = 120; + INIT_WORK(&session->recovery_work, session_recovery_timedout, session); + INIT_LIST_HEAD(&session->host_list); + INIT_LIST_HEAD(&session->sess_list); + + if (transport->sessiondata_size) + session->dd_data = &session[1]; /* this is released in the dev's release function */ scsi_host_get(shost); - snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no); + ihost = shost->shost_data; + + session->sid = iscsi_session_nr++; + session->channel = channel; + session->target_id = ihost->next_target_id++; + + snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", + session->sid); session->dev.parent = &shost->shost_gendev; session->dev.release = iscsi_session_release; err = device_register(&session->dev); @@ -252,6 +342,10 @@ iscsi_create_session(struct Scsi_Host *s } transport_register_device(&session->dev); + mutex_lock(&ihost->mutex); + list_add(&session->host_list, &ihost->sessions); + mutex_unlock(&ihost->mutex); + return session; free_session: @@ -272,6 +366,16 @@ EXPORT_SYMBOL_GPL(iscsi_create_session); **/ int iscsi_destroy_session(struct iscsi_cls_session *session) { + struct Scsi_Host *shost = iscsi_session_to_shost(session); + struct iscsi_host *ihost = shost->shost_data; + + if (!cancel_delayed_work(&session->recovery_work)) + flush_scheduled_work(); + + mutex_lock(&ihost->mutex); + list_del(&session->host_list); + mutex_unlock(&ihost->mutex); + transport_unregister_device(&session->dev); device_unregister(&session->dev); return 0; @@ -284,6 +388,7 @@ static void iscsi_conn_release(struct de struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev); struct device *parent = conn->dev.parent; + kfree(conn->persistent_address); kfree(conn); put_device(parent); } @@ -301,12 +406,16 @@ static int iscsi_is_conn_dev(const struc * This can be called from a LLD or iscsi_transport. The connection * is child of the session so cid must be unique for all connections * on the session. + * + * Since we do not support MCS, cid will normally be zero. In some cases + * for software iscsi we could be trying to preallocate a connection struct + * in which case there could be two connection structs and cid would be + * non-zero. **/ struct iscsi_cls_conn * iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) { struct iscsi_transport *transport = session->transport; - struct Scsi_Host *shost = iscsi_session_to_shost(session); struct iscsi_cls_conn *conn; int err; @@ -319,12 +428,14 @@ iscsi_create_conn(struct iscsi_cls_sessi INIT_LIST_HEAD(&conn->conn_list); conn->transport = transport; + conn->cid = cid; /* this is released in the dev's release function */ if (!get_device(&session->dev)) goto free_conn; + snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", - shost->host_no, cid); + session->sid, cid); conn->dev.parent = &session->dev; conn->dev.release = iscsi_conn_release; err = device_register(&conn->dev); @@ -361,105 +472,6 @@ int iscsi_destroy_conn(struct iscsi_cls_ EXPORT_SYMBOL_GPL(iscsi_destroy_conn); /* - * These functions are used only by software iscsi_transports - * which do not allocate and more their scsi_hosts since this - * is initiated from userspace. - */ - -/* - * iSCSI Session's hostdata organization: - * - * *------------------* <== hostdata_session(host->hostdata) - * | ptr to class sess| - * |------------------| <== iscsi_hostdata(host->hostdata) - * | transport's data | - * *------------------* - */ - -#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \ - _t->hostdata_size % sizeof(unsigned long)) - -#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata)) - -/** - * iscsi_transport_create_session - create iscsi cls session and host - * scsit: scsi transport template - * transport: iscsi transport template - * - * This can be used by software iscsi_transports that allocate - * a session per scsi host. - **/ -struct Scsi_Host * -iscsi_transport_create_session(struct scsi_transport_template *scsit, - struct iscsi_transport *transport) -{ - struct iscsi_cls_session *session; - struct Scsi_Host *shost; - unsigned long flags; - - shost = scsi_host_alloc(transport->host_template, - hostdata_privsize(transport)); - if (!shost) { - printk(KERN_ERR "iscsi: can not allocate SCSI host for " - "session\n"); - return NULL; - } - - shost->max_id = 1; - shost->max_channel = 0; - shost->max_lun = transport->max_lun; - shost->max_cmd_len = transport->max_cmd_len; - shost->transportt = scsit; - shost->transportt->create_work_queue = 1; - - if (scsi_add_host(shost, NULL)) - goto free_host; - - session = iscsi_create_session(shost, transport); - if (!session) - goto remove_host; - - *(unsigned long*)shost->hostdata = (unsigned long)session; - spin_lock_irqsave(&sesslock, flags); - list_add(&session->sess_list, &sesslist); - spin_unlock_irqrestore(&sesslock, flags); - return shost; - -remove_host: - scsi_remove_host(shost); -free_host: - scsi_host_put(shost); - return NULL; -} - -EXPORT_SYMBOL_GPL(iscsi_transport_create_session); - -/** - * iscsi_transport_destroy_session - destroy session and scsi host - * shost: scsi host - * - * This can be used by software iscsi_transports that allocate - * a session per scsi host. - **/ -int iscsi_transport_destroy_session(struct Scsi_Host *shost) -{ - struct iscsi_cls_session *session; - unsigned long flags; - - scsi_remove_host(shost); - session = hostdata_session(shost->hostdata); - spin_lock_irqsave(&sesslock, flags); - list_del(&session->sess_list); - spin_unlock_irqrestore(&sesslock, flags); - iscsi_destroy_session(session); - /* ref from host alloc */ - scsi_host_put(shost); - return 0; -} - -EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session); - -/* * iscsi interface functions */ static struct iscsi_internal * @@ -560,13 +572,13 @@ mempool_zone_get_skb(struct mempool_zone } static int -iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb) +iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid) { unsigned long flags; int rc; skb_get(skb); - rc = netlink_unicast(nls, skb, daemon_pid, MSG_DONTWAIT); + rc = netlink_unicast(nls, skb, pid, MSG_DONTWAIT); if (rc < 0) { mempool_free(skb, zone->pool); printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc); @@ -574,6 +586,7 @@ iscsi_unicast_skb(struct mempool_zone *z } spin_lock_irqsave(&zone->freelock, flags); + INIT_LIST_HEAD(skb_to_lh(skb)); list_add(skb_to_lh(skb), &zone->freequeue); spin_unlock_irqrestore(&zone->freelock, flags); @@ -587,9 +600,14 @@ int iscsi_recv_pdu(struct iscsi_cls_conn struct sk_buff *skb; struct iscsi_uevent *ev; char *pdu; + struct iscsi_internal *priv; int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) + data_size); + priv = iscsi_if_transport_lookup(conn->transport); + if (!priv) + return -EINVAL; + mempool_zone_complete(conn->z_pdu); skb = mempool_zone_get_skb(conn->z_pdu); @@ -600,19 +618,20 @@ int iscsi_recv_pdu(struct iscsi_cls_conn return -ENOMEM; } - nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); + nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); ev = NLMSG_DATA(nlh); memset(ev, 0, sizeof(*ev)); ev->transport_handle = iscsi_handle(conn->transport); ev->type = ISCSI_KEVENT_RECV_PDU; if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) ev->iferror = -ENOMEM; - ev->r.recv_req.conn_handle = iscsi_handle(conn); + ev->r.recv_req.cid = conn->cid; + ev->r.recv_req.sid = iscsi_conn_get_sid(conn); pdu = (char*)ev + sizeof(*ev); memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); - return iscsi_unicast_skb(conn->z_pdu, skb); + return iscsi_unicast_skb(conn->z_pdu, skb, priv->daemon_pid); } EXPORT_SYMBOL_GPL(iscsi_recv_pdu); @@ -621,8 +640,13 @@ void iscsi_conn_error(struct iscsi_cls_c struct nlmsghdr *nlh; struct sk_buff *skb; struct iscsi_uevent *ev; + struct iscsi_internal *priv; int len = NLMSG_SPACE(sizeof(*ev)); + priv = iscsi_if_transport_lookup(conn->transport); + if (!priv) + return; + mempool_zone_complete(conn->z_error); skb = mempool_zone_get_skb(conn->z_error); @@ -632,16 +656,17 @@ void iscsi_conn_error(struct iscsi_cls_c return; } - nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); + nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0); ev = NLMSG_DATA(nlh); ev->transport_handle = iscsi_handle(conn->transport); ev->type = ISCSI_KEVENT_CONN_ERROR; if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat) ev->iferror = -ENOMEM; ev->r.connerror.error = error; - ev->r.connerror.conn_handle = iscsi_handle(conn); + ev->r.connerror.cid = conn->cid; + ev->r.connerror.sid = iscsi_conn_get_sid(conn); - iscsi_unicast_skb(conn->z_error, skb); + iscsi_unicast_skb(conn->z_error, skb, priv->daemon_pid); dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n", error); @@ -671,7 +696,7 @@ iscsi_if_send_reply(int pid, int seq, in nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); nlh->nlmsg_flags = flags; memcpy(NLMSG_DATA(nlh), payload, size); - return iscsi_unicast_skb(z_reply, skb); + return iscsi_unicast_skb(z_reply, skb, pid); } static int @@ -683,13 +708,18 @@ iscsi_if_get_stats(struct iscsi_transpor struct iscsi_cls_conn *conn; struct nlmsghdr *nlhstat; struct iscsi_uevent *evstat; + struct iscsi_internal *priv; int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_stats) + sizeof(struct iscsi_stats_custom) * ISCSI_STATS_CUSTOM_MAX); int err = 0; - conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle); + priv = iscsi_if_transport_lookup(transport); + if (!priv) + return -EINVAL; + + conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid); if (!conn) return -EEXIST; @@ -705,7 +735,7 @@ iscsi_if_get_stats(struct iscsi_transpor return -ENOMEM; } - nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0, + nlhstat = __nlmsg_put(skbstat, priv->daemon_pid, 0, 0, (len - sizeof(*nlhstat)), 0); evstat = NLMSG_DATA(nlhstat); memset(evstat, 0, sizeof(*evstat)); @@ -713,8 +743,10 @@ iscsi_if_get_stats(struct iscsi_transpor evstat->type = nlh->nlmsg_type; if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) evstat->iferror = -ENOMEM; - evstat->u.get_stats.conn_handle = - ev->u.get_stats.conn_handle; + evstat->u.get_stats.cid = + ev->u.get_stats.cid; + evstat->u.get_stats.sid = + ev->u.get_stats.sid; stats = (struct iscsi_stats *) ((char*)evstat + sizeof(*evstat)); memset(stats, 0, sizeof(*stats)); @@ -729,7 +761,7 @@ iscsi_if_get_stats(struct iscsi_transpor skb_trim(skbstat, NLMSG_ALIGN(actual_size)); nlhstat->nlmsg_len = actual_size; - err = iscsi_unicast_skb(conn->z_pdu, skbstat); + err = iscsi_unicast_skb(conn->z_pdu, skbstat, priv->daemon_pid); } while (err < 0 && err != -ECONNREFUSED); return err; @@ -740,16 +772,21 @@ iscsi_if_create_session(struct iscsi_int { struct iscsi_transport *transport = priv->iscsi_transport; struct iscsi_cls_session *session; - uint32_t sid; + unsigned long flags; + uint32_t hostno; - session = transport->create_session(&priv->t, + session = transport->create_session(transport, &priv->t, ev->u.c_session.initial_cmdsn, - &sid); + &hostno); if (!session) return -ENOMEM; - ev->r.c_session_ret.session_handle = iscsi_handle(session); - ev->r.c_session_ret.sid = sid; + spin_lock_irqsave(&sesslock, flags); + list_add(&session->sess_list, &sesslist); + spin_unlock_irqrestore(&sesslock, flags); + + ev->r.c_session_ret.host_no = hostno; + ev->r.c_session_ret.sid = session->sid; return 0; } @@ -760,13 +797,20 @@ iscsi_if_create_conn(struct iscsi_transp struct iscsi_cls_session *session; unsigned long flags; - session = iscsi_session_lookup(ev->u.c_conn.session_handle); - if (!session) + session = iscsi_session_lookup(ev->u.c_conn.sid); + if (!session) { + printk(KERN_ERR "iscsi: invalid session %d\n", + ev->u.c_conn.sid); return -EINVAL; + } conn = transport->create_conn(session, ev->u.c_conn.cid); - if (!conn) + if (!conn) { + printk(KERN_ERR "iscsi: couldn't create a new " + "connection for session %d\n", + session->sid); return -ENOMEM; + } conn->z_pdu = mempool_zone_init(Z_MAX_PDU, NLMSG_SPACE(sizeof(struct iscsi_uevent) + @@ -788,7 +832,8 @@ iscsi_if_create_conn(struct iscsi_transp goto free_pdu_pool; } - ev->r.handle = iscsi_handle(conn); + ev->r.c_conn_ret.sid = session->sid; + ev->r.c_conn_ret.cid = conn->cid; spin_lock_irqsave(&connlock, flags); list_add(&conn->conn_list, &connlist); @@ -812,7 +857,7 @@ iscsi_if_destroy_conn(struct iscsi_trans struct iscsi_cls_conn *conn; struct mempool_zone *z_error, *z_pdu; - conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle); + conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid); if (!conn) return -EINVAL; spin_lock_irqsave(&connlock, flags); @@ -832,6 +877,106 @@ iscsi_if_destroy_conn(struct iscsi_trans return 0; } +static void +iscsi_copy_param(struct iscsi_uevent *ev, uint32_t *value, char *data) +{ + if (ev->u.set_param.len != sizeof(uint32_t)) + BUG(); + memcpy(value, data, min_t(uint32_t, sizeof(uint32_t), + ev->u.set_param.len)); +} + +static int +iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) +{ + char *data = (char*)ev + sizeof(*ev); + struct iscsi_cls_conn *conn; + struct iscsi_cls_session *session; + int err = 0; + uint32_t value = 0; + + session = iscsi_session_lookup(ev->u.set_param.sid); + conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); + if (!conn || !session) + return -EINVAL; + + switch (ev->u.set_param.param) { + case ISCSI_PARAM_SESS_RECOVERY_TMO: + iscsi_copy_param(ev, &value, data); + if (value != 0) + session->recovery_tmo = value; + break; + case ISCSI_PARAM_TARGET_NAME: + /* this should not change between logins */ + if (session->targetname) + return 0; + + session->targetname = kstrdup(data, GFP_KERNEL); + if (!session->targetname) + return -ENOMEM; + break; + case ISCSI_PARAM_TPGT: + iscsi_copy_param(ev, &value, data); + session->tpgt = value; + break; + case ISCSI_PARAM_PERSISTENT_PORT: + iscsi_copy_param(ev, &value, data); + conn->persistent_port = value; + break; + case ISCSI_PARAM_PERSISTENT_ADDRESS: + /* + * this is the address returned in discovery so it should + * not change between logins. + */ + if (conn->persistent_address) + return 0; + + conn->persistent_address = kstrdup(data, GFP_KERNEL); + if (!conn->persistent_address) + return -ENOMEM; + break; + default: + iscsi_copy_param(ev, &value, data); + err = transport->set_param(conn, ev->u.set_param.param, value); + } + + return err; +} + +static int +iscsi_if_transport_ep(struct iscsi_transport *transport, + struct iscsi_uevent *ev, int msg_type) +{ + struct sockaddr *dst_addr; + int rc = 0; + + switch (msg_type) { + case ISCSI_UEVENT_TRANSPORT_EP_CONNECT: + if (!transport->ep_connect) + return -EINVAL; + + dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev)); + rc = transport->ep_connect(dst_addr, + ev->u.ep_connect.non_blocking, + &ev->r.ep_connect_ret.handle); + break; + case ISCSI_UEVENT_TRANSPORT_EP_POLL: + if (!transport->ep_poll) + return -EINVAL; + + ev->r.retcode = transport->ep_poll(ev->u.ep_poll.ep_handle, + ev->u.ep_poll.timeout_ms); + break; + case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: + if (!transport->ep_disconnect) + return -EINVAL; + + transport->ep_disconnect(ev->u.ep_disconnect.ep_handle); + break; + } + return rc; +} + static int iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { @@ -841,6 +986,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, s struct iscsi_internal *priv; struct iscsi_cls_session *session; struct iscsi_cls_conn *conn; + unsigned long flags; priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle)); if (!priv) @@ -850,15 +996,21 @@ iscsi_if_recv_msg(struct sk_buff *skb, s if (!try_module_get(transport->owner)) return -EINVAL; + priv->daemon_pid = NETLINK_CREDS(skb)->pid; + switch (nlh->nlmsg_type) { case ISCSI_UEVENT_CREATE_SESSION: err = iscsi_if_create_session(priv, ev); break; case ISCSI_UEVENT_DESTROY_SESSION: - session = iscsi_session_lookup(ev->u.d_session.session_handle); - if (session) + session = iscsi_session_lookup(ev->u.d_session.sid); + if (session) { + spin_lock_irqsave(&sesslock, flags); + list_del(&session->sess_list); + spin_unlock_irqrestore(&sesslock, flags); + transport->destroy_session(session); - else + } else err = -EINVAL; break; case ISCSI_UEVENT_CREATE_CONN: @@ -868,41 +1020,35 @@ iscsi_if_recv_msg(struct sk_buff *skb, s err = iscsi_if_destroy_conn(transport, ev); break; case ISCSI_UEVENT_BIND_CONN: - session = iscsi_session_lookup(ev->u.b_conn.session_handle); - conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle); + session = iscsi_session_lookup(ev->u.b_conn.sid); + conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid); if (session && conn) ev->r.retcode = transport->bind_conn(session, conn, - ev->u.b_conn.transport_fd, + ev->u.b_conn.transport_eph, ev->u.b_conn.is_leading); else err = -EINVAL; break; case ISCSI_UEVENT_SET_PARAM: - conn = iscsi_conn_lookup(ev->u.set_param.conn_handle); - if (conn) - ev->r.retcode = transport->set_param(conn, - ev->u.set_param.param, ev->u.set_param.value); - else - err = -EINVAL; + err = iscsi_set_param(transport, ev); break; case ISCSI_UEVENT_START_CONN: - conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle); + conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid); if (conn) ev->r.retcode = transport->start_conn(conn); else err = -EINVAL; - break; case ISCSI_UEVENT_STOP_CONN: - conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle); + conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid); if (conn) transport->stop_conn(conn, ev->u.stop_conn.flag); else err = -EINVAL; break; case ISCSI_UEVENT_SEND_PDU: - conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle); + conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid); if (conn) ev->r.retcode = transport->send_pdu(conn, (struct iscsi_hdr*)((char*)ev + sizeof(*ev)), @@ -914,6 +1060,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, s case ISCSI_UEVENT_GET_STATS: err = iscsi_if_get_stats(transport, nlh); break; + case ISCSI_UEVENT_TRANSPORT_EP_CONNECT: + case ISCSI_UEVENT_TRANSPORT_EP_POLL: + case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: + err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type); + break; default: err = -EINVAL; break; @@ -923,9 +1074,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, s return err; } -/* Get message from skb (based on rtnetlink_rcv_skb). Each message is - * processed by iscsi_if_recv_msg. Malformed skbs with wrong length are - * or invalid creds discarded silently. */ +/* + * Get message from skb (based on rtnetlink_rcv_skb). Each message is + * processed by iscsi_if_recv_msg. Malformed skbs with wrong lengths or + * invalid creds are discarded silently. + */ static void iscsi_if_rx(struct sock *sk, int len) { @@ -937,7 +1090,6 @@ iscsi_if_rx(struct sock *sk, int len) skb_pull(skb, skb->len); goto free_skb; } - daemon_pid = NETLINK_CREDS(skb)->pid; while (skb->len >= NLMSG_SPACE(0)) { int err; @@ -988,6 +1140,10 @@ free_skb: #define iscsi_cdev_to_conn(_cdev) \ iscsi_dev_to_conn(_cdev->dev) +#define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store) \ +struct class_device_attribute class_device_attr_##_prefix##_##_name = \ + __ATTR(_name,_mode,_show,_store) + /* * iSCSI connection attrs */ @@ -1005,7 +1161,8 @@ show_conn_int_param_##param(struct class #define iscsi_conn_int_attr(field, param, format) \ iscsi_conn_int_attr_show(param, format) \ -static CLASS_DEVICE_ATTR(field, S_IRUGO, show_conn_int_param_##param, NULL); +static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_int_param_##param, \ + NULL); iscsi_conn_int_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH, "%u"); iscsi_conn_int_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH, "%u"); @@ -1013,6 +1170,26 @@ iscsi_conn_int_attr(header_digest, ISCSI iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d"); iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d"); iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d"); +iscsi_conn_int_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT, "%d"); +iscsi_conn_int_attr(port, ISCSI_PARAM_CONN_PORT, "%d"); +iscsi_conn_int_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN, "%u"); + +#define iscsi_conn_str_attr_show(param) \ +static ssize_t \ +show_conn_str_param_##param(struct class_device *cdev, char *buf) \ +{ \ + struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ + struct iscsi_transport *t = conn->transport; \ + return t->get_conn_str_param(conn, param, buf); \ +} + +#define iscsi_conn_str_attr(field, param) \ + iscsi_conn_str_attr_show(param) \ +static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_str_param_##param, \ + NULL); + +iscsi_conn_str_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS); +iscsi_conn_str_attr(address, ISCSI_PARAM_CONN_ADDRESS); #define iscsi_cdev_to_session(_cdev) \ iscsi_dev_to_session(_cdev->dev) @@ -1034,7 +1211,8 @@ show_session_int_param_##param(struct cl #define iscsi_session_int_attr(field, param, format) \ iscsi_session_int_attr_show(param, format) \ -static CLASS_DEVICE_ATTR(field, S_IRUGO, show_session_int_param_##param, NULL); +static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_int_param_##param, \ + NULL); iscsi_session_int_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, "%d"); iscsi_session_int_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, "%hu"); @@ -1044,18 +1222,89 @@ iscsi_session_int_attr(max_burst_len, IS iscsi_session_int_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, "%d"); iscsi_session_int_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, "%d"); iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d"); +iscsi_session_int_attr(tpgt, ISCSI_PARAM_TPGT, "%d"); -#define SETUP_SESSION_RD_ATTR(field, param) \ - if (priv->param_mask & (1 << param)) { \ - priv->session_attrs[count] = &class_device_attr_##field;\ - count++; \ - } +#define iscsi_session_str_attr_show(param) \ +static ssize_t \ +show_session_str_param_##param(struct class_device *cdev, char *buf) \ +{ \ + struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ + struct iscsi_transport *t = session->transport; \ + return t->get_session_str_param(session, param, buf); \ +} + +#define iscsi_session_str_attr(field, param) \ + iscsi_session_str_attr_show(param) \ +static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_str_param_##param, \ + NULL); + +iscsi_session_str_attr(targetname, ISCSI_PARAM_TARGET_NAME); + +/* + * Private session and conn attrs. userspace uses several iscsi values + * to identify each session between reboots. Some of these values may not + * be present in the iscsi_transport/LLD driver becuase userspace handles + * login (and failback for login redirect) so for these type of drivers + * the class manages the attrs and values for the iscsi_transport/LLD + */ +#define iscsi_priv_session_attr_show(field, format) \ +static ssize_t \ +show_priv_session_##field(struct class_device *cdev, char *buf) \ +{ \ + struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ + return sprintf(buf, format"\n", session->field); \ +} + +#define iscsi_priv_session_attr(field, format) \ + iscsi_priv_session_attr_show(field, format) \ +static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \ + NULL) +iscsi_priv_session_attr(targetname, "%s"); +iscsi_priv_session_attr(tpgt, "%d"); +iscsi_priv_session_attr(recovery_tmo, "%d"); + +#define iscsi_priv_conn_attr_show(field, format) \ +static ssize_t \ +show_priv_conn_##field(struct class_device *cdev, char *buf) \ +{ \ + struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \ + return sprintf(buf, format"\n", conn->field); \ +} -#define SETUP_CONN_RD_ATTR(field, param) \ - if (priv->param_mask & (1 << param)) { \ - priv->conn_attrs[count] = &class_device_attr_##field; \ +#define iscsi_priv_conn_attr(field, format) \ + iscsi_priv_conn_attr_show(field, format) \ +static ISCSI_CLASS_ATTR(priv_conn, field, S_IRUGO, show_priv_conn_##field, \ + NULL) +iscsi_priv_conn_attr(persistent_address, "%s"); +iscsi_priv_conn_attr(persistent_port, "%d"); + +#define SETUP_PRIV_SESSION_RD_ATTR(field) \ +do { \ + priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \ + count++; \ +} while (0) + +#define SETUP_SESSION_RD_ATTR(field, param_flag) \ +do { \ + if (tt->param_mask & param_flag) { \ + priv->session_attrs[count] = &class_device_attr_sess_##field; \ count++; \ - } + } \ +} while (0) + +#define SETUP_PRIV_CONN_RD_ATTR(field) \ +do { \ + priv->conn_attrs[count] = &class_device_attr_priv_conn_##field; \ + count++; \ +} while (0) + +#define SETUP_CONN_RD_ATTR(field, param_flag) \ +do { \ + if (tt->param_mask & param_flag) { \ + priv->conn_attrs[count] = &class_device_attr_conn_##field; \ + count++; \ + } \ +} while (0) static int iscsi_session_match(struct attribute_container *cont, struct device *dev) @@ -1104,6 +1353,24 @@ static int iscsi_conn_match(struct attri return &priv->conn_cont.ac == cont; } +static int iscsi_host_match(struct attribute_container *cont, + struct device *dev) +{ + struct Scsi_Host *shost; + struct iscsi_internal *priv; + + if (!scsi_is_host_device(dev)) + return 0; + + shost = dev_to_shost(dev); + if (!shost->transportt || + shost->transportt->host_attrs.ac.class != &iscsi_host_class.class) + return 0; + + priv = to_iscsi_internal(shost->transportt); + return &priv->t.host_attrs.ac == cont; +} + struct scsi_transport_template * iscsi_register_transport(struct iscsi_transport *tt) { @@ -1122,6 +1389,7 @@ iscsi_register_transport(struct iscsi_tr return NULL; INIT_LIST_HEAD(&priv->list); priv->iscsi_transport = tt; + priv->t.user_scan = iscsi_user_scan; priv->cdev.class = &iscsi_transport_class; snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name); @@ -1133,18 +1401,13 @@ iscsi_register_transport(struct iscsi_tr if (err) goto unregister_cdev; - /* setup parameters mask */ - priv->param_mask = 0xFFFFFFFF; - if (!(tt->caps & CAP_MULTI_R2T)) - priv->param_mask &= ~(1 << ISCSI_PARAM_MAX_R2T); - if (!(tt->caps & CAP_HDRDGST)) - priv->param_mask &= ~(1 << ISCSI_PARAM_HDRDGST_EN); - if (!(tt->caps & CAP_DATADGST)) - priv->param_mask &= ~(1 << ISCSI_PARAM_DATADGST_EN); - if (!(tt->caps & CAP_MARKERS)) { - priv->param_mask &= ~(1 << ISCSI_PARAM_IFMARKER_EN); - priv->param_mask &= ~(1 << ISCSI_PARAM_OFMARKER_EN); - } + /* host parameters */ + priv->t.host_attrs.ac.attrs = &priv->host_attrs[0]; + priv->t.host_attrs.ac.class = &iscsi_host_class.class; + priv->t.host_attrs.ac.match = iscsi_host_match; + priv->t.host_size = sizeof(struct iscsi_host); + priv->host_attrs[0] = NULL; + transport_container_register(&priv->t.host_attrs); /* connection parameters */ priv->conn_cont.ac.attrs = &priv->conn_attrs[0]; @@ -1152,12 +1415,25 @@ iscsi_register_transport(struct iscsi_tr priv->conn_cont.ac.match = iscsi_conn_match; transport_container_register(&priv->conn_cont); - SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH); - SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH); - SETUP_CONN_RD_ATTR(header_digest, ISCSI_PARAM_HDRDGST_EN); - SETUP_CONN_RD_ATTR(data_digest, ISCSI_PARAM_DATADGST_EN); - SETUP_CONN_RD_ATTR(ifmarker, ISCSI_PARAM_IFMARKER_EN); - SETUP_CONN_RD_ATTR(ofmarker, ISCSI_PARAM_OFMARKER_EN); + SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH); + SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH); + SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN); + SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN); + SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN); + SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN); + SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS); + SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT); + SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN); + + if (tt->param_mask & ISCSI_PERSISTENT_ADDRESS) + SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS); + else + SETUP_PRIV_CONN_RD_ATTR(persistent_address); + + if (tt->param_mask & ISCSI_PERSISTENT_PORT) + SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT); + else + SETUP_PRIV_CONN_RD_ATTR(persistent_port); BUG_ON(count > ISCSI_CONN_ATTRS); priv->conn_attrs[count] = NULL; @@ -1169,14 +1445,25 @@ iscsi_register_transport(struct iscsi_tr priv->session_cont.ac.match = iscsi_session_match; transport_container_register(&priv->session_cont); - SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN); - SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T); - SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_PARAM_IMM_DATA_EN); - SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_PARAM_FIRST_BURST); - SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_PARAM_MAX_BURST); - SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN); - SETUP_SESSION_RD_ATTR(data_seq_in_order,ISCSI_PARAM_DATASEQ_INORDER_EN) - SETUP_SESSION_RD_ATTR(erl, ISCSI_PARAM_ERL); + SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN); + SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T); + SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN); + SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST); + SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST); + SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN); + SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN); + SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL); + SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); + + if (tt->param_mask & ISCSI_TARGET_NAME) + SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME); + else + SETUP_PRIV_SESSION_RD_ATTR(targetname); + + if (tt->param_mask & ISCSI_TPGT) + SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT); + else + SETUP_PRIV_SESSION_RD_ATTR(tpgt); BUG_ON(count > ISCSI_SESSION_ATTRS); priv->session_attrs[count] = NULL; @@ -1214,6 +1501,7 @@ int iscsi_unregister_transport(struct is transport_container_unregister(&priv->conn_cont); transport_container_unregister(&priv->session_cont); + transport_container_unregister(&priv->t.host_attrs); sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group); class_device_unregister(&priv->cdev); @@ -1257,10 +1545,14 @@ static __init int iscsi_transport_init(v if (err) return err; - err = transport_class_register(&iscsi_connection_class); + err = transport_class_register(&iscsi_host_class); if (err) goto unregister_transport_class; + err = transport_class_register(&iscsi_connection_class); + if (err) + goto unregister_host_class; + err = transport_class_register(&iscsi_session_class); if (err) goto unregister_conn_class; @@ -1288,6 +1580,8 @@ unregister_session_class: transport_class_unregister(&iscsi_session_class); unregister_conn_class: transport_class_unregister(&iscsi_connection_class); +unregister_host_class: + transport_class_unregister(&iscsi_host_class); unregister_transport_class: class_unregister(&iscsi_transport_class); return err; @@ -1300,6 +1594,7 @@ static void __exit iscsi_transport_exit( netlink_unregister_notifier(&iscsi_nl_notifier); transport_class_unregister(&iscsi_connection_class); transport_class_unregister(&iscsi_session_class); + transport_class_unregister(&iscsi_host_class); class_unregister(&iscsi_transport_class); } diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index f3b1606..1fe6b2d 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -65,7 +65,7 @@ get_sas_##title##_names(u32 table_key, c ssize_t len = 0; \ int i; \ \ - for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ + for (i = 0; i < ARRAY_SIZE(table); i++) { \ if (table[i].value & table_key) { \ len += sprintf(buf + len, "%s%s", \ prefix, table[i].name); \ @@ -83,7 +83,7 @@ get_sas_##title##_names(u32 table_key, c ssize_t len = 0; \ int i; \ \ - for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ + for (i = 0; i < ARRAY_SIZE(table); i++) { \ if (table[i].value == table_key) { \ len += sprintf(buf + len, "%s", \ table[i].name); \ @@ -748,6 +748,18 @@ static void sas_end_device_release(struc } /** + * sas_rphy_initialize - common rphy intialization + * @rphy: rphy to initialise + * + * Used by both sas_end_device_alloc() and sas_expander_alloc() to + * initialise the common rphy component of each. + */ +static void sas_rphy_initialize(struct sas_rphy *rphy) +{ + INIT_LIST_HEAD(&rphy->list); +} + +/** * sas_end_device_alloc - allocate an rphy for an end device * * Allocates an SAS remote PHY structure, connected to @parent. @@ -771,6 +783,7 @@ struct sas_rphy *sas_end_device_alloc(st sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d-%d", shost->host_no, parent->port_identifier, parent->number); rdev->rphy.identify.device_type = SAS_END_DEVICE; + sas_rphy_initialize(&rdev->rphy); transport_setup_device(&rdev->rphy.dev); return &rdev->rphy; @@ -809,6 +822,7 @@ struct sas_rphy *sas_expander_alloc(stru sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d", shost->host_no, rdev->rphy.scsi_target_id); rdev->rphy.identify.device_type = type; + sas_rphy_initialize(&rdev->rphy); transport_setup_device(&rdev->rphy.dev); return &rdev->rphy; diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 780aaed..ace49d5 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -146,7 +146,7 @@ static inline const char *spi_signal_to_ { int i; - for (i = 0; i < sizeof(signal_types)/sizeof(signal_types[0]); i++) { + for (i = 0; i < ARRAY_SIZE(signal_types); i++) { if (type == signal_types[i].value) return signal_types[i].name; } @@ -156,7 +156,7 @@ static inline enum spi_signal_type spi_s { int i, len; - for (i = 0; i < sizeof(signal_types)/sizeof(signal_types[0]); i++) { + for (i = 0; i < ARRAY_SIZE(signal_types); i++) { len = strlen(signal_types[i].name); if (strncmp(name, signal_types[i].name, len) == 0 && (name[len] == '\n' || name[len] == '\0')) @@ -785,6 +785,7 @@ spi_dv_device_internal(struct scsi_devic { struct spi_internal *i = to_spi_internal(sdev->host->transportt); struct scsi_target *starget = sdev->sdev_target; + struct Scsi_Host *shost = sdev->host; int len = sdev->inquiry_len; /* first set us up for narrow async */ DV_SET(offset, 0); @@ -844,6 +845,14 @@ spi_dv_device_internal(struct scsi_devic if (spi_min_period(starget) == 8) DV_SET(pcomp_en, 1); } + /* now that we've done all this, actually check the bus + * signal type (if known). Some devices are stupid on + * a SE bus and still claim they can try LVD only settings */ + if (i->f->get_signalling) + i->f->get_signalling(shost); + if (spi_signalling(shost) == SPI_SIGNAL_SE || + spi_signalling(shost) == SPI_SIGNAL_HVD) + DV_SET(dt, 0); /* Do the read only INQUIRY tests */ spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len, spi_dv_device_compare_inquiry); diff --git a/drivers/scsi/scsi_typedefs.h b/drivers/scsi/scsi_typedefs.h index 29f038b..2ed4c5c 100644 --- a/drivers/scsi/scsi_typedefs.h +++ b/drivers/scsi/scsi_typedefs.h @@ -1,3 +1,2 @@ typedef struct scsi_cmnd Scsi_Cmnd; -typedef struct scsi_request Scsi_Request; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c647d85..3541990 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -175,7 +175,7 @@ static ssize_t sd_store_cache_type(struc * it's not worth the risk */ return -EINVAL; - for (i = 0; i < sizeof(sd_cache_types)/sizeof(sd_cache_types[0]); i++) { + for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) { const int len = strlen(sd_cache_types[i]); if (strncmp(sd_cache_types[i], buf, len) == 0 && buf[len] == '\n') { @@ -891,7 +891,7 @@ #endif static void sd_rw_intr(struct scsi_cmnd * SCpnt) { int result = SCpnt->result; - int this_count = SCpnt->bufflen; + int this_count = SCpnt->request_bufflen; int good_bytes = (result == 0 ? this_count : 0); sector_t block_sectors = 1; u64 first_err_block; diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c index 0ff83dd..7fa4da4 100644 --- a/drivers/scsi/seagate.c +++ b/drivers/scsi/seagate.c @@ -312,7 +312,7 @@ static Signature __initdata signatures[] {"IBM F1 V1.2009/22/93", 5, 25, FD}, }; -#define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature)) +#define NUM_SIGNATURES ARRAY_SIZE(signatures) #endif /* n OVERRIDE */ /* @@ -457,7 +457,7 @@ #else /* OVERRIDE */ * space for the on-board RAM instead. */ - for (i = 0; i < (sizeof (seagate_bases) / sizeof (unsigned int)); ++i) { + for (i = 0; i < ARRAY_SIZE(seagate_bases); ++i) { void __iomem *p = ioremap(seagate_bases[i], 0x2000); if (!p) continue; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index b098942..98b9312 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -2635,8 +2635,7 @@ static int sg_proc_init(void) { int k, mask; - int num_leaves = - sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]); + int num_leaves = ARRAY_SIZE(sg_proc_leaf_arr); struct proc_dir_entry *pdep; struct sg_proc_leaf * leaf; @@ -2661,8 +2660,7 @@ static void sg_proc_cleanup(void) { int k; - int num_leaves = - sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]); + int num_leaves = ARRAY_SIZE(sg_proc_leaf_arr); if (!sg_proc_sgp) return; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 7c80711..ebf6579 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -217,7 +217,7 @@ int sr_media_change(struct cdrom_device_ static void rw_intr(struct scsi_cmnd * SCpnt) { int result = SCpnt->result; - int this_count = SCpnt->bufflen; + int this_count = SCpnt->request_bufflen; int good_bytes = (result == 0 ? this_count : 0); int block_sectors = 0; long error_sector; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 56cb490..b5218fc 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1193,7 +1193,7 @@ static int st_open(struct inode *inode, /* Flush the tape buffer before close */ -static int st_flush(struct file *filp) +static int st_flush(struct file *filp, fl_owner_t id) { int result = 0, result2; unsigned char cmd[MAX_COMMAND_SIZE]; @@ -2818,7 +2818,7 @@ static int st_int_ioctl(struct scsi_tape (cmdstatp->sense_hdr.sense_key == NO_SENSE || cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) && undone == 0) { - ioctl_result = 0; /* EOF written succesfully at EOM */ + ioctl_result = 0; /* EOF written successfully at EOM */ if (fileno >= 0) fileno++; STps->drv_file = fileno; @@ -3839,7 +3839,7 @@ static int __init st_setup(char *str) break; } } - if (i >= sizeof(parms) / sizeof(struct st_dev_parm)) + if (i >= ARRAY_SIZE(parms)) printk(KERN_WARNING "st: invalid parameter in '%s'\n", stp); stp = strchr(stp, ','); diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c index cc990be..2e2c1eb 100644 --- a/drivers/scsi/sun3x_esp.c +++ b/drivers/scsi/sun3x_esp.c @@ -332,11 +332,11 @@ static void dma_mmu_get_scsi_sgl (struct struct scatterlist *sg = sp->SCp.buffer; while (sz >= 0) { - sg[sz].dvma_address = dvma_map((unsigned long)page_address(sg[sz].page) + + sg[sz].dma_address = dvma_map((unsigned long)page_address(sg[sz].page) + sg[sz].offset, sg[sz].length); sz--; } - sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dvma_address); + sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dma_address); } static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp) @@ -350,14 +350,14 @@ static void dma_mmu_release_scsi_sgl (st struct scatterlist *sg = (struct scatterlist *)sp->buffer; while(sz >= 0) { - dvma_unmap((char *)sg[sz].dvma_address); + dvma_unmap((char *)sg[sz].dma_address); sz--; } } static void dma_advance_sg (Scsi_Cmnd *sp) { - sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address); + sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dma_address); } static int sun3x_esp_release(struct Scsi_Host *instance) diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 9c83b4d..ea82d3d 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -54,14 +54,8 @@ #include "sym_nvram.h" #define NAME53C "sym53c" #define NAME53C8XX "sym53c8xx" -/* SPARC just has to be different ... */ -#ifdef __sparc__ -#define IRQ_FMT "%s" -#define IRQ_PRM(x) __irq_itoa(x) -#else #define IRQ_FMT "%d" #define IRQ_PRM(x) (x) -#endif struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP; unsigned int sym_debug_flags = 0; @@ -156,7 +150,7 @@ static void __unmap_scsi_data(struct pci switch(SYM_UCMD_PTR(cmd)->data_mapped) { case 2: - pci_unmap_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir); + pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, dma_dir); break; case 1: pci_unmap_single(pdev, SYM_UCMD_PTR(cmd)->data_mapping, @@ -186,7 +180,7 @@ static int __map_scsi_sg_data(struct pci int use_sg; int dma_dir = cmd->sc_data_direction; - use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir); + use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, dma_dir); if (use_sg > 0) { SYM_UCMD_PTR(cmd)->data_mapped = 2; SYM_UCMD_PTR(cmd)->data_mapping = use_sg; @@ -376,7 +370,7 @@ static int sym_scatter(struct sym_hcb *n if (!use_sg) segment = sym_scatter_no_sglist(np, cp, cmd); else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) { - struct scatterlist *scatter = (struct scatterlist *)cmd->buffer; + struct scatterlist *scatter = (struct scatterlist *)cmd->request_buffer; struct sym_tcb *tp = &np->target[cp->target]; struct sym_tblmove *data; diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index a671bdc..940fa1e 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -1276,8 +1276,7 @@ #endif FE_RAM|FE_IO256|FE_LEDC} }; -#define sym_num_devs \ - (sizeof(sym_dev_table) / sizeof(sym_dev_table[0])) +#define sym_num_devs (ARRAY_SIZE(sym_dev_table)) /* * Look up the chip table. diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 21305fc..a24f661 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -126,15 +126,15 @@ #include "NCR5380.h" static struct override { unsigned long address; int irq; -} overrides +} overrides #ifdef T128_OVERRIDE [] __initdata = T128_OVERRIDE; #else - [4] __initdata = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, + [4] __initdata = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, {0 ,IRQ_AUTO}, {0, IRQ_AUTO}}; #endif -#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override)) +#define NO_OVERRIDES ARRAY_SIZE(overrides) static struct base { unsigned int address; @@ -143,7 +143,7 @@ static struct base { { 0xcc000, 0}, { 0xc8000, 0}, { 0xdc000, 0}, { 0xd8000, 0} }; -#define NO_BASES (sizeof (bases) / sizeof (struct base)) +#define NO_BASES ARRAY_SIZE(bases) static struct signature { const char *string; @@ -152,7 +152,7 @@ static struct signature { {"TSROM: SCSI BIOS, Version 1.12", 0x36}, }; -#define NO_SIGNATURES (sizeof (signatures) / sizeof (struct signature)) +#define NO_SIGNATURES ARRAY_SIZE(signatures) /* * Function : t128_setup(char *str, int *ints) diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index d8a7260..27307fe 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -939,6 +939,7 @@ #endif DB(DB_INTR, printk("%02x", cmd->SCp.Status)) if (hostdata->level2 >= L2_BASIC) { sr = read_wd33c93(regs, WD_SCSI_STATUS); /* clear interrupt */ + udelay(7); hostdata->state = S_RUNNING_LEVEL2; write_wd33c93(regs, WD_COMMAND_PHASE, 0x50); write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER); @@ -955,6 +956,7 @@ #endif msg = read_1_byte(regs); sr = read_wd33c93(regs, WD_SCSI_STATUS); /* clear interrupt */ + udelay(7); hostdata->incoming_msg[hostdata->incoming_ptr] = msg; if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE) @@ -1358,6 +1360,7 @@ #endif } else { /* Verify this is a change to MSG_IN and read the message */ sr = read_wd33c93(regs, WD_SCSI_STATUS); + udelay(7); if (sr == (CSR_ABORT | PHS_MESS_IN) || sr == (CSR_UNEXP | PHS_MESS_IN) || sr == (CSR_SRV_REQ | PHS_MESS_IN)) { @@ -1374,6 +1377,7 @@ #endif asr); } sr = read_wd33c93(regs, WD_SCSI_STATUS); + udelay(7); if (sr != CSR_MSGIN) printk ("wd33c93: Not paused with ACK on RESEL (%02x)\n", @@ -1701,7 +1705,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) } #define MAX_WD33C93_HOSTS 4 -#define MAX_SETUP_ARGS ((int)(sizeof(setup_args) / sizeof(char *))) +#define MAX_SETUP_ARGS ARRAY_SIZE(setup_args) #define SETUP_BUFFER_SIZE 200 static char setup_buffer[SETUP_BUFFER_SIZE]; static char setup_used[MAX_SETUP_ARGS]; diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c index fb54a87..574955b 100644 --- a/drivers/scsi/wd7000.c +++ b/drivers/scsi/wd7000.c @@ -267,7 +267,7 @@ static const long wd7000_biosaddr[] = { 0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000, 0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000 }; -#define NUM_ADDRS (sizeof(wd7000_biosaddr)/sizeof(long)) +#define NUM_ADDRS ARRAY_SIZE(wd7000_biosaddr) static const unsigned short wd7000_iobase[] = { 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338, @@ -275,13 +275,13 @@ static const unsigned short wd7000_iobas 0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8, 0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8 }; -#define NUM_IOPORTS (sizeof(wd7000_iobase)/sizeof(unsigned short)) +#define NUM_IOPORTS ARRAY_SIZE(wd7000_iobase) static const short wd7000_irq[] = { 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 }; -#define NUM_IRQS (sizeof(wd7000_irq)/sizeof(short)) +#define NUM_IRQS ARRAY_SIZE(wd7000_irq) static const short wd7000_dma[] = { 5, 6, 7 }; -#define NUM_DMAS (sizeof(wd7000_dma)/sizeof(short)) +#define NUM_DMAS ARRAY_SIZE(wd7000_dma) /* * The following is set up by wd7000_detect, and used thereafter for @@ -317,7 +317,7 @@ static Config configs[] = { {7, 6, 0x350, BUS_ON, BUS_OFF}, /* My configuration (Zaga) */ {-1, -1, 0x0, BUS_ON, BUS_OFF} /* Empty slot */ }; -#define NUM_CONFIGS (sizeof(configs)/sizeof(Config)) +#define NUM_CONFIGS ARRAY_SIZE(configs) /* * The following list defines strings to look for in the BIOS that identify @@ -333,7 +333,7 @@ typedef struct signature { static const Signature signatures[] = { {"SSTBIOS", 0x0000d, 7} /* "SSTBIOS" @ offset 0x0000d */ }; -#define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature)) +#define NUM_SIGNATURES ARRAY_SIZE(signatures) /* @@ -1391,7 +1391,7 @@ #endif * */ -static int wd7000_detect(struct scsi_host_template *tpnt) +static __init int wd7000_detect(struct scsi_host_template *tpnt) { short present = 0, biosaddr_ptr, sig_ptr, i, pass; short biosptr[NUM_CONFIGS]; diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index b79ed06..739bc84 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -323,8 +323,10 @@ static const struct pnp_device_id pnp_de { "USR9180", 0 }, /* U.S. Robotics 56K Voice INT PnP*/ { "USR9190", 0 }, - /* HP Compaq Tablet PC tc1100 Wacom tablet */ + /* Wacom tablets */ + { "WACF004", 0 }, { "WACF005", 0 }, + { "WACF006", 0 }, /* Rockwell's (PORALiNK) 33600 INT PNP */ { "WCI0003", 0 }, /* Unkown PnP modems */ diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 7d22dc0..5b48ac2 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -300,21 +300,22 @@ config SERIAL_AMBA_PL011_CONSOLE kernel at boot time.) config SERIAL_AT91 - bool "AT91RM9200 serial port support" - depends on ARM && ARCH_AT91RM9200 + bool "AT91RM9200 / AT91SAM9261 serial port support" + depends on ARM && (ARCH_AT91RM9200 || ARCH_AT91SAM9261) select SERIAL_CORE help - This enables the driver for the on-chip UARTs of the AT91RM9200 - processor. + This enables the driver for the on-chip UARTs of the Atmel + AT91RM9200 and AT91SAM926 processor. config SERIAL_AT91_CONSOLE - bool "Support for console on AT91RM9200 serial port" + bool "Support for console on AT91RM9200 / AT91SAM9261 serial port" depends on SERIAL_AT91=y select SERIAL_CORE_CONSOLE help - Say Y here if you wish to use a UART on the AT91RM9200 as the system - console (the system console is the device which receives all kernel - messages and warnings and which allows logins in single user mode). + Say Y here if you wish to use a UART on the Atmel AT91RM9200 or + AT91SAM9261 as the system console (the system console is the device + which receives all kernel messages and warnings and which allows + logins in single user mode). config SERIAL_AT91_TTYAT bool "Install as device ttyAT0-4 instead of ttyS0-4" @@ -353,21 +354,24 @@ config SERIAL_CLPS711X_CONSOLE kernel at boot time.) config SERIAL_S3C2410 - tristate "Samsung S3C2410 Serial port support" + tristate "Samsung S3C2410/S3C2440/S3C2442/S3C2412 Serial port support" depends on ARM && ARCH_S3C2410 select SERIAL_CORE help - Support for the on-chip UARTs on the Samsung S3C2410X CPU, + Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, providing /dev/ttySAC0, 1 and 2 (note, some machines may not provide all of these ports, depending on how the serial port pins are configured. + Currently this driver supports the UARTS on the S3C2410, S3C2440, + S3C2442, S3C2412 and S3C2413 CPUs. + config SERIAL_S3C2410_CONSOLE bool "Support for console on S3C2410 serial port" depends on SERIAL_S3C2410=y select SERIAL_CORE_CONSOLE help - Allow selection of the S3C2410 on-board serial ports for use as + Allow selection of the S3C24XX on-board serial ports for use as an virtual console. Even if you say Y here, the currently visible virtual console @@ -936,4 +940,23 @@ config SERIAL_SGI_IOC3 If you have an SGI Altix with an IOC3 serial card, say Y or M. Otherwise, say N. +config SERIAL_NETX + bool "NetX serial port support" + depends on ARM && ARCH_NETX + select SERIAL_CORE + help + If you have a machine based on a Hilscher NetX SoC you + can enable its onboard serial port by enabling this option. + + To compile this driver as a module, choose M here: the + module will be called netx-serial. + +config SERIAL_NETX_CONSOLE + bool "Console on NetX serial port" + depends on SERIAL_NETX + select SERIAL_CORE_CONSOLE + help + If you have enabled the serial port on the Motorola IMX + CPU you can make it the console by answering Y to this option. + endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 0a71bf6..927faee 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -55,3 +55,4 @@ obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_si obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o obj-$(CONFIG_SERIAL_AT91) += at91_serial.o +obj-$(CONFIG_SERIAL_NETX) += netx-serial.o diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 1631414..e920d19 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -52,7 +52,7 @@ #include #include -#define UART_NR 2 +#define UART_NR 8 #define SERIAL_AMBA_MAJOR 204 #define SERIAL_AMBA_MINOR 16 diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c index 6547fe0..db5b25f 100644 --- a/drivers/serial/at91_serial.c +++ b/drivers/serial/at91_serial.c @@ -2,7 +2,6 @@ * linux/drivers/char/at91_serial.c * * Driver for Atmel AT91RM9200 Serial ports - * * Copyright (C) 2003 Rick Bronson * * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd. @@ -30,17 +29,19 @@ #include #include #include #include +#include #include #include #include +#include #include #include -#include +#include +#include #include -#include - +#include #if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -67,7 +68,6 @@ #define AT91_DEVICENAME "ttyS" #endif -#define AT91_VA_BASE_DBGU ((unsigned long) AT91_VA_BASE_SYS + AT91_DBGU) #define AT91_ISR_PASS_LIMIT 256 #define UART_PUT_CR(port,v) writel(v, (port)->membase + AT91_US_CR) @@ -87,16 +87,33 @@ #define UART_PUT_RTOR(port,v) writel(v, /* PDC registers */ #define UART_PUT_PTCR(port,v) writel(v, (port)->membase + AT91_PDC_PTCR) +#define UART_GET_PTSR(port) readl((port)->membase + AT91_PDC_PTSR) + #define UART_PUT_RPR(port,v) writel(v, (port)->membase + AT91_PDC_RPR) +#define UART_GET_RPR(port) readl((port)->membase + AT91_PDC_RPR) #define UART_PUT_RCR(port,v) writel(v, (port)->membase + AT91_PDC_RCR) -#define UART_GET_RCR(port) readl((port)->membase + AT91_PDC_RCR) #define UART_PUT_RNPR(port,v) writel(v, (port)->membase + AT91_PDC_RNPR) #define UART_PUT_RNCR(port,v) writel(v, (port)->membase + AT91_PDC_RNCR) +#define UART_PUT_TPR(port,v) writel(v, (port)->membase + AT91_PDC_TPR) +#define UART_PUT_TCR(port,v) writel(v, (port)->membase + AT91_PDC_TCR) +//#define UART_PUT_TNPR(port,v) writel(v, (port)->membase + AT91_PDC_TNPR) +//#define UART_PUT_TNCR(port,v) writel(v, (port)->membase + AT91_PDC_TNCR) static int (*at91_open)(struct uart_port *); static void (*at91_close)(struct uart_port *); +/* + * We wrap our port structure around the generic uart_port. + */ +struct at91_uart_port { + struct uart_port uart; /* uart */ + struct clk *clk; /* uart clock */ + unsigned short suspended; /* is port suspended? */ +}; + +static struct at91_uart_port at91_ports[AT91_NR_UART]; + #ifdef SUPPORT_SYSRQ static struct console at91_console; #endif @@ -115,16 +132,19 @@ static u_int at91_tx_empty(struct uart_p static void at91_set_mctrl(struct uart_port *port, u_int mctrl) { unsigned int control = 0; + unsigned int mode; - /* - * Errata #39: RTS0 is not internally connected to PA21. We need to drive - * the pin manually. - */ - if (port->mapbase == AT91_VA_BASE_US0) { - if (mctrl & TIOCM_RTS) - at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0); - else - at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0); + if (arch_identify() == ARCH_ID_AT91RM9200) { + /* + * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21. + * We need to drive the pin manually. + */ + if (port->mapbase == AT91_BASE_US0) { + if (mctrl & TIOCM_RTS) + at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0); + else + at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0); + } } if (mctrl & TIOCM_RTS) @@ -137,7 +157,15 @@ static void at91_set_mctrl(struct uart_p else control |= AT91_US_DTRDIS; - UART_PUT_CR(port,control); + UART_PUT_CR(port, control); + + /* Local loopback mode? */ + mode = UART_GET_MR(port) & ~AT91_US_CHMODE; + if (mctrl & TIOCM_LOOP) + mode |= AT91_US_CHMODE_LOC_LOOP; + else + mode |= AT91_US_CHMODE_NORMAL; + UART_PUT_MR(port, mode); } /* @@ -169,8 +197,9 @@ static u_int at91_get_mctrl(struct uart_ */ static void at91_stop_tx(struct uart_port *port) { + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + UART_PUT_IDR(port, AT91_US_TXRDY); - port->read_status_mask &= ~AT91_US_TXRDY; } /* @@ -178,7 +207,8 @@ static void at91_stop_tx(struct uart_por */ static void at91_start_tx(struct uart_port *port) { - port->read_status_mask |= AT91_US_TXRDY; + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + UART_PUT_IER(port, AT91_US_TXRDY); } @@ -187,6 +217,8 @@ static void at91_start_tx(struct uart_po */ static void at91_stop_rx(struct uart_port *port) { + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + UART_PUT_IDR(port, AT91_US_RXRDY); } @@ -195,7 +227,6 @@ static void at91_stop_rx(struct uart_por */ static void at91_enable_ms(struct uart_port *port) { - port->read_status_mask |= (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC); UART_PUT_IER(port, AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC); } @@ -218,8 +249,8 @@ static void at91_rx_chars(struct uart_po struct tty_struct *tty = port->info->tty; unsigned int status, ch, flg; - status = UART_GET_CSR(port) & port->read_status_mask; - while (status & (AT91_US_RXRDY)) { + status = UART_GET_CSR(port); + while (status & AT91_US_RXRDY) { ch = UART_GET_CHAR(port); port->icount.rx++; @@ -230,40 +261,38 @@ static void at91_rx_chars(struct uart_po * note that the error handling code is * out of the main execution path */ - if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE))) { + if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE | AT91_US_RXBRK))) { UART_PUT_CR(port, AT91_US_RSTSTA); /* clear error */ - if (status & (AT91_US_PARE)) + if (status & AT91_US_RXBRK) { + status &= ~(AT91_US_PARE | AT91_US_FRAME); /* ignore side-effect */ + port->icount.brk++; + if (uart_handle_break(port)) + goto ignore_char; + } + if (status & AT91_US_PARE) port->icount.parity++; - if (status & (AT91_US_FRAME)) + if (status & AT91_US_FRAME) port->icount.frame++; - if (status & (AT91_US_OVRE)) + if (status & AT91_US_OVRE) port->icount.overrun++; - if (status & AT91_US_PARE) + status &= port->read_status_mask; + + if (status & AT91_US_RXBRK) + flg = TTY_BREAK; + else if (status & AT91_US_PARE) flg = TTY_PARITY; else if (status & AT91_US_FRAME) flg = TTY_FRAME; - if (status & AT91_US_OVRE) { - /* - * overrun does *not* affect the character - * we read from the FIFO - */ - tty_insert_flip_char(tty, ch, flg); - ch = 0; - flg = TTY_OVERRUN; - } -#ifdef SUPPORT_SYSRQ - port->sysrq = 0; -#endif } if (uart_handle_sysrq_char(port, ch, regs)) goto ignore_char; - tty_insert_flip_char(tty, ch, flg); + uart_insert_char(port, status, AT91_US_OVRE, ch, flg); ignore_char: - status = UART_GET_CSR(port) & port->read_status_mask; + status = UART_GET_CSR(port); } tty_flip_buffer_push(tty); @@ -308,40 +337,35 @@ static void at91_tx_chars(struct uart_po static irqreturn_t at91_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct uart_port *port = dev_id; + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; unsigned int status, pending, pass_counter = 0; status = UART_GET_CSR(port); - pending = status & port->read_status_mask; - if (pending) { - do { - if (pending & AT91_US_RXRDY) - at91_rx_chars(port, regs); - - /* Clear the relevent break bits */ - if (pending & AT91_US_RXBRK) { - UART_PUT_CR(port, AT91_US_RSTSTA); - port->icount.brk++; - uart_handle_break(port); - } + pending = status & UART_GET_IMR(port); + while (pending) { + /* Interrupt receive */ + if (pending & AT91_US_RXRDY) + at91_rx_chars(port, regs); + + // TODO: All reads to CSR will clear these interrupts! + if (pending & AT91_US_RIIC) port->icount.rng++; + if (pending & AT91_US_DSRIC) port->icount.dsr++; + if (pending & AT91_US_DCDIC) + uart_handle_dcd_change(port, !(status & AT91_US_DCD)); + if (pending & AT91_US_CTSIC) + uart_handle_cts_change(port, !(status & AT91_US_CTS)); + if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC)) + wake_up_interruptible(&port->info->delta_msr_wait); + + /* Interrupt transmit */ + if (pending & AT91_US_TXRDY) + at91_tx_chars(port); + + if (pass_counter++ > AT91_ISR_PASS_LIMIT) + break; - // TODO: All reads to CSR will clear these interrupts! - if (pending & AT91_US_RIIC) port->icount.rng++; - if (pending & AT91_US_DSRIC) port->icount.dsr++; - if (pending & AT91_US_DCDIC) - uart_handle_dcd_change(port, !(status & AT91_US_DCD)); - if (pending & AT91_US_CTSIC) - uart_handle_cts_change(port, !(status & AT91_US_CTS)); - if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC)) - wake_up_interruptible(&port->info->delta_msr_wait); - - if (pending & AT91_US_TXRDY) - at91_tx_chars(port); - if (pass_counter++ > AT91_ISR_PASS_LIMIT) - break; - - status = UART_GET_CSR(port); - pending = status & port->read_status_mask; - } while (pending); + status = UART_GET_CSR(port); + pending = status & UART_GET_IMR(port); } return IRQ_HANDLED; } @@ -351,6 +375,7 @@ static irqreturn_t at91_interrupt(int ir */ static int at91_startup(struct uart_port *port) { + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; int retval; /* @@ -381,14 +406,14 @@ static int at91_startup(struct uart_port } } - port->read_status_mask = AT91_US_RXRDY | AT91_US_TXRDY | AT91_US_OVRE - | AT91_US_FRAME | AT91_US_PARE | AT91_US_RXBRK; /* * Finally, enable the serial port */ UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); /* enable xmit & rcvr */ - UART_PUT_IER(port, AT91_US_RXRDY); /* do receive only */ + + UART_PUT_IER(port, AT91_US_RXRDY); /* enable receive only */ + return 0; } @@ -397,6 +422,8 @@ static int at91_startup(struct uart_port */ static void at91_shutdown(struct uart_port *port) { + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + /* * Disable all interrupts, port and break condition. */ @@ -421,21 +448,22 @@ static void at91_shutdown(struct uart_po */ static void at91_serial_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + switch (state) { case 0: /* * Enable the peripheral clock for this serial port. * This is called on uart_open() or a resume event. */ - at91_sys_write(AT91_PMC_PCER, 1 << port->irq); + clk_enable(at91_port->clk); break; case 3: /* * Disable the peripheral clock for this serial port. * This is called on uart_close() or a suspend event. */ - if (port->irq != AT91_ID_SYS) /* is this a shared clock? */ - at91_sys_write(AT91_PMC_PCDR, 1 << port->irq); + clk_disable(at91_port->clk); break; default: printk(KERN_ERR "at91_serial: unknown pm %d\n", state); @@ -494,9 +522,9 @@ static void at91_set_termios(struct uart spin_lock_irqsave(&port->lock, flags); - port->read_status_mask |= AT91_US_OVRE; + port->read_status_mask = AT91_US_OVRE; if (termios->c_iflag & INPCK) - port->read_status_mask |= AT91_US_FRAME | AT91_US_PARE; + port->read_status_mask |= (AT91_US_FRAME | AT91_US_PARE); if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= AT91_US_RXBRK; @@ -552,7 +580,7 @@ static void at91_set_termios(struct uart */ static const char *at91_type(struct uart_port *port) { - return (port->type == PORT_AT91RM9200) ? "AT91_SERIAL" : NULL; + return (port->type == PORT_AT91) ? "AT91_SERIAL" : NULL; } /* @@ -560,8 +588,15 @@ static const char *at91_type(struct uart */ static void at91_release_port(struct uart_port *port) { - release_mem_region(port->mapbase, - (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K); + struct platform_device *pdev = to_platform_device(port->dev); + int size = pdev->resource[0].end - pdev->resource[0].start + 1; + + release_mem_region(port->mapbase, size); + + if (port->flags & UPF_IOREMAP) { + iounmap(port->membase); + port->membase = NULL; + } } /* @@ -569,10 +604,21 @@ static void at91_release_port(struct uar */ static int at91_request_port(struct uart_port *port) { - return request_mem_region(port->mapbase, - (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K, - "at91_serial") != NULL ? 0 : -EBUSY; + struct platform_device *pdev = to_platform_device(port->dev); + int size = pdev->resource[0].end - pdev->resource[0].start + 1; + + if (!request_mem_region(port->mapbase, size, "at91_serial")) + return -EBUSY; + + if (port->flags & UPF_IOREMAP) { + port->membase = ioremap(port->mapbase, size); + if (port->membase == NULL) { + release_mem_region(port->mapbase, size); + return -ENOMEM; + } + } + return 0; } /* @@ -581,7 +627,7 @@ static int at91_request_port(struct uart static void at91_config_port(struct uart_port *port, int flags) { if (flags & UART_CONFIG_TYPE) { - port->type = PORT_AT91RM9200; + port->type = PORT_AT91; at91_request_port(port); } } @@ -592,7 +638,7 @@ static void at91_config_port(struct uart static int at91_verify_port(struct uart_port *port, struct serial_struct *ser) { int ret = 0; - if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200) + if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91) ret = -EINVAL; if (port->irq != ser->irq) ret = -EINVAL; @@ -624,33 +670,47 @@ static struct uart_ops at91_pops = { .type = at91_type, .release_port = at91_release_port, .request_port = at91_request_port, - .config_port = at91_config_port, - .verify_port = at91_verify_port, + .config_port = at91_config_port, + .verify_port = at91_verify_port, .pm = at91_serial_pm, }; -static struct uart_port at91_ports[AT91_NR_UART]; - -void __init at91_init_ports(void) +/* + * Configure the port from the platform device resource info. + */ +static void __devinit at91_init_port(struct at91_uart_port *at91_port, struct platform_device *pdev) { - static int first = 1; - int i; - - if (!first) - return; - first = 0; + struct uart_port *port = &at91_port->uart; + struct at91_uart_data *data = pdev->dev.platform_data; + + port->iotype = UPIO_MEM; + port->flags = UPF_BOOT_AUTOCONF; + port->ops = &at91_pops; + port->fifosize = 1; + port->line = pdev->id; + port->dev = &pdev->dev; + + port->mapbase = pdev->resource[0].start; + port->irq = pdev->resource[1].start; + + if (port->mapbase == AT91_VA_BASE_SYS + AT91_DBGU) /* Part of system perpherals - already mapped */ + port->membase = (void __iomem *) port->mapbase; + else { + port->flags |= UPF_IOREMAP; + port->membase = NULL; + } - for (i = 0; i < AT91_NR_UART; i++) { - at91_ports[i].iotype = UPIO_MEM; - at91_ports[i].flags = UPF_BOOT_AUTOCONF; - at91_ports[i].uartclk = at91_master_clock; - at91_ports[i].ops = &at91_pops; - at91_ports[i].fifosize = 1; - at91_ports[i].line = i; - } + if (!at91_port->clk) { /* for console, the clock could already be configured */ + at91_port->clk = clk_get(&pdev->dev, "usart"); + clk_enable(at91_port->clk); + port->uartclk = clk_get_rate(at91_port->clk); + } } -void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns) +/* + * Register board-specific modem-control line handlers. + */ +void __init at91_register_uart_fns(struct at91_port_fns *fns) { if (fns->enable_ms) at91_pops.enable_ms = fns->enable_ms; @@ -664,51 +724,6 @@ void __init at91_register_uart_fns(struc at91_pops.set_wake = fns->set_wake; } -/* - * Setup ports. - */ -void __init at91_register_uart(int idx, int port) -{ - if ((idx < 0) || (idx >= AT91_NR_UART)) { - printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx); - return; - } - - switch (port) { - case 0: - at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US0; - at91_ports[idx].mapbase = AT91_VA_BASE_US0; - at91_ports[idx].irq = AT91_ID_US0; - AT91_CfgPIO_USART0(); - break; - case 1: - at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US1; - at91_ports[idx].mapbase = AT91_VA_BASE_US1; - at91_ports[idx].irq = AT91_ID_US1; - AT91_CfgPIO_USART1(); - break; - case 2: - at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US2; - at91_ports[idx].mapbase = AT91_VA_BASE_US2; - at91_ports[idx].irq = AT91_ID_US2; - AT91_CfgPIO_USART2(); - break; - case 3: - at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US3; - at91_ports[idx].mapbase = AT91_VA_BASE_US3; - at91_ports[idx].irq = AT91_ID_US3; - AT91_CfgPIO_USART3(); - break; - case 4: - at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_DBGU; - at91_ports[idx].mapbase = AT91_VA_BASE_DBGU; - at91_ports[idx].irq = AT91_ID_SYS; - AT91_CfgPIO_DBGU(); - break; - default: - printk(KERN_ERR "%s : bad port number %d\n", __FUNCTION__, port); - } -} #ifdef CONFIG_SERIAL_AT91_CONSOLE static void at91_console_putchar(struct uart_port *port, int ch) @@ -723,7 +738,7 @@ static void at91_console_putchar(struct */ static void at91_console_write(struct console *co, const char *s, u_int count) { - struct uart_port *port = at91_ports + co->index; + struct uart_port *port = &at91_ports[co->index].uart; unsigned int status, imr; /* @@ -778,23 +793,15 @@ static void __init at91_console_get_opti static int __init at91_console_setup(struct console *co, char *options) { - struct uart_port *port; + struct uart_port *port = &at91_ports[co->index].uart; int baud = 115200; int bits = 8; int parity = 'n'; int flow = 'n'; - /* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. - */ - port = uart_get_console(at91_ports, AT91_NR_UART, co); + if (port->membase == 0) /* Port not initialized yet - delay setup */ + return -ENODEV; - /* - * Enable the serial console, in-case bootloader did not do it. - */ - at91_sys_write(AT91_PMC_PCER, 1 << port->irq); /* enable clock */ UART_PUT_IDR(port, -1); /* disable interrupts */ UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); @@ -821,23 +828,40 @@ static struct console at91_console = { #define AT91_CONSOLE_DEVICE &at91_console -static int __init at91_console_init(void) +/* + * Early console initialization (before VM subsystem initialized). + */ +static int __init at91_console_init(void) { - at91_init_ports(); + if (at91_default_console_device) { + add_preferred_console(AT91_DEVICENAME, at91_default_console_device->id, NULL); + at91_init_port(&(at91_ports[at91_default_console_device->id]), at91_default_console_device); + register_console(&at91_console); + } - at91_console.index = at91_console_port; - register_console(&at91_console); return 0; } console_initcall(at91_console_init); +/* + * Late console initialization. + */ +static int __init at91_late_console_init(void) +{ + if (at91_default_console_device && !(at91_console.flags & CON_ENABLED)) + register_console(&at91_console); + + return 0; +} +core_initcall(at91_late_console_init); + #else #define AT91_CONSOLE_DEVICE NULL #endif static struct uart_driver at91_uart = { .owner = THIS_MODULE, - .driver_name = AT91_DEVICENAME, + .driver_name = "at91_serial", .dev_name = AT91_DEVICENAME, .devfs_name = AT91_DEVICENAME, .major = SERIAL_AT91_MAJOR, @@ -846,33 +870,106 @@ static struct uart_driver at91_uart = { .cons = AT91_CONSOLE_DEVICE, }; -static int __init at91_serial_init(void) +#ifdef CONFIG_PM +static int at91_serial_suspend(struct platform_device *pdev, pm_message_t state) { - int ret, i; + struct uart_port *port = platform_get_drvdata(pdev); + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + + if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock()) + enable_irq_wake(port->irq); + else { + disable_irq_wake(port->irq); + uart_suspend_port(&at91_uart, port); + at91_port->suspended = 1; + } - at91_init_ports(); + return 0; +} - ret = uart_register_driver(&at91_uart); - if (ret) - return ret; +static int at91_serial_resume(struct platform_device *pdev) +{ + struct uart_port *port = platform_get_drvdata(pdev); + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; - for (i = 0; i < AT91_NR_UART; i++) { - if (at91_serial_map[i] >= 0) - uart_add_one_port(&at91_uart, &at91_ports[i]); + if (at91_port->suspended) { + uart_resume_port(&at91_uart, port); + at91_port->suspended = 0; } return 0; } +#else +#define at91_serial_suspend NULL +#define at91_serial_resume NULL +#endif -static void __exit at91_serial_exit(void) +static int __devinit at91_serial_probe(struct platform_device *pdev) { - int i; + struct at91_uart_port *port; + int ret; - for (i = 0; i < AT91_NR_UART; i++) { - if (at91_serial_map[i] >= 0) - uart_remove_one_port(&at91_uart, &at91_ports[i]); - } + port = &at91_ports[pdev->id]; + at91_init_port(port, pdev); + ret = uart_add_one_port(&at91_uart, &port->uart); + if (!ret) { + device_init_wakeup(&pdev->dev, 1); + platform_set_drvdata(pdev, port); + } + + return ret; +} + +static int __devexit at91_serial_remove(struct platform_device *pdev) +{ + struct uart_port *port = platform_get_drvdata(pdev); + struct at91_uart_port *at91_port = (struct at91_uart_port *) port; + int ret = 0; + + clk_disable(at91_port->clk); + clk_put(at91_port->clk); + + device_init_wakeup(&pdev->dev, 0); + platform_set_drvdata(pdev, NULL); + + if (port) { + ret = uart_remove_one_port(&at91_uart, port); + kfree(port); + } + + return ret; +} + +static struct platform_driver at91_serial_driver = { + .probe = at91_serial_probe, + .remove = __devexit_p(at91_serial_remove), + .suspend = at91_serial_suspend, + .resume = at91_serial_resume, + .driver = { + .name = "at91_usart", + .owner = THIS_MODULE, + }, +}; + +static int __init at91_serial_init(void) +{ + int ret; + + ret = uart_register_driver(&at91_uart); + if (ret) + return ret; + + ret = platform_driver_register(&at91_serial_driver); + if (ret) + uart_unregister_driver(&at91_uart); + + return ret; +} + +static void __exit at91_serial_exit(void) +{ + platform_driver_unregister(&at91_serial_driver); uart_unregister_driver(&at91_uart); } diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index c620209..717e47b 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -2646,7 +2646,10 @@ static int ioc4_serial_remove_one(struct struct ioc4_port *port; struct ioc4_soft *soft; + /* If serial driver did not attach, don't try to detach */ control = idd->idd_serial_data; + if (!control) + return 0; for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) { for (port_type = UART_PORT_MIN; @@ -2778,6 +2781,12 @@ ioc4_serial_attach_one(struct ioc4_drive DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, idd->idd_pci_id)); + /* PCI-RT does not bring out serial connections. + * Do not attach to this particular IOC4. + */ + if (idd->idd_variant == IOC4_VARIANT_PCI_RT) + return 0; + /* request serial registers */ tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET; diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index 8cbbb95..8ad2429 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -60,11 +60,11 @@ struct timer_list mcfrs_timer_struct; #if defined(CONFIG_HW_FEITH) #define CONSOLE_BAUD_RATE 38400 #define DEFAULT_CBAUD B38400 -#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) +#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || defined(CONFIG_M5329EVB) #define CONSOLE_BAUD_RATE 115200 #define DEFAULT_CBAUD B115200 #elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ - defined(CONFIG_senTec) || defined(CONFIG_SNEHA) + defined(CONFIG_senTec) || defined(CONFIG_SNEHA) || defined(CONFIG_AVNET) #define CONSOLE_BAUD_RATE 19200 #define DEFAULT_CBAUD B19200 #endif @@ -93,7 +93,7 @@ #undef SERIAL_DEBUG_OPEN #undef SERIAL_DEBUG_FLOW #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) + defined(CONFIG_M520x) || defined(CONFIG_M532x) #define IRQBASE (MCFINT_VECBASE+MCFINT_UART0) #else #define IRQBASE 73 @@ -1545,6 +1545,28 @@ #elif defined(CONFIG_M520x) *feci2c_par |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2 | MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2; } +#elif defined(CONFIG_M532x) + volatile unsigned char *uartp; + uartp = info->addr; + switch (info->line) { + case 0: + MCF_INTC0_ICR26 = 0x3; + MCF_INTC0_CIMR = 26; + /* GPIO initialization */ + MCF_GPIO_PAR_UART |= 0x000F; + break; + case 1: + MCF_INTC0_ICR27 = 0x3; + MCF_INTC0_CIMR = 27; + /* GPIO initialization */ + MCF_GPIO_PAR_UART |= 0x0FF0; + break; + case 2: + MCF_INTC0_ICR28 = 0x3; + MCF_INTC0_CIMR = 28; + /* GPIOs also must be initalized, depends on board */ + break; + } #else volatile unsigned char *icrp, *uartp; diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c new file mode 100644 index 0000000..c1adc9e --- /dev/null +++ b/drivers/serial/netx-serial.c @@ -0,0 +1,749 @@ +/* + * drivers/serial/netx-serial.c + * + * Copyright (c) 2005 Sascha Hauer , Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#if defined(CONFIG_SERIAL_NETX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* We've been assigned a range on the "Low-density serial ports" major */ +#define SERIAL_NX_MAJOR 204 +#define MINOR_START 170 + +#ifdef CONFIG_SERIAL_NETX_CONSOLE + +enum uart_regs { + UART_DR = 0x00, + UART_SR = 0x04, + UART_LINE_CR = 0x08, + UART_BAUDDIV_MSB = 0x0c, + UART_BAUDDIV_LSB = 0x10, + UART_CR = 0x14, + UART_FR = 0x18, + UART_IIR = 0x1c, + UART_ILPR = 0x20, + UART_RTS_CR = 0x24, + UART_RTS_LEAD = 0x28, + UART_RTS_TRAIL = 0x2c, + UART_DRV_ENABLE = 0x30, + UART_BRM_CR = 0x34, + UART_RXFIFO_IRQLEVEL = 0x38, + UART_TXFIFO_IRQLEVEL = 0x3c, +}; + +#define SR_FE (1<<0) +#define SR_PE (1<<1) +#define SR_BE (1<<2) +#define SR_OE (1<<3) + +#define LINE_CR_BRK (1<<0) +#define LINE_CR_PEN (1<<1) +#define LINE_CR_EPS (1<<2) +#define LINE_CR_STP2 (1<<3) +#define LINE_CR_FEN (1<<4) +#define LINE_CR_5BIT (0<<5) +#define LINE_CR_6BIT (1<<5) +#define LINE_CR_7BIT (2<<5) +#define LINE_CR_8BIT (3<<5) +#define LINE_CR_BITS_MASK (3<<5) + +#define CR_UART_EN (1<<0) +#define CR_SIREN (1<<1) +#define CR_SIRLP (1<<2) +#define CR_MSIE (1<<3) +#define CR_RIE (1<<4) +#define CR_TIE (1<<5) +#define CR_RTIE (1<<6) +#define CR_LBE (1<<7) + +#define FR_CTS (1<<0) +#define FR_DSR (1<<1) +#define FR_DCD (1<<2) +#define FR_BUSY (1<<3) +#define FR_RXFE (1<<4) +#define FR_TXFF (1<<5) +#define FR_RXFF (1<<6) +#define FR_TXFE (1<<7) + +#define IIR_MIS (1<<0) +#define IIR_RIS (1<<1) +#define IIR_TIS (1<<2) +#define IIR_RTIS (1<<3) +#define IIR_MASK 0xf + +#define RTS_CR_AUTO (1<<0) +#define RTS_CR_RTS (1<<1) +#define RTS_CR_COUNT (1<<2) +#define RTS_CR_MOD2 (1<<3) +#define RTS_CR_RTS_POL (1<<4) +#define RTS_CR_CTS_CTR (1<<5) +#define RTS_CR_CTS_POL (1<<6) +#define RTS_CR_STICK (1<<7) + +#define UART_PORT_SIZE 0x40 +#define DRIVER_NAME "netx-uart" + +struct netx_port { + struct uart_port port; +}; + +static void netx_stop_tx(struct uart_port *port) +{ + unsigned int val; + val = readl(port->membase + UART_CR); + writel(val & ~CR_TIE, port->membase + UART_CR); +} + +static void netx_stop_rx(struct uart_port *port) +{ + unsigned int val; + val = readl(port->membase + UART_CR); + writel(val & ~CR_RIE, port->membase + UART_CR); +} + +static void netx_enable_ms(struct uart_port *port) +{ + unsigned int val; + val = readl(port->membase + UART_CR); + writel(val | CR_MSIE, port->membase + UART_CR); +} + +static inline void netx_transmit_buffer(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (port->x_char) { + writel(port->x_char, port->membase + UART_DR); + port->icount.tx++; + port->x_char = 0; + return; + } + + if (uart_tx_stopped(port) || uart_circ_empty(xmit)) { + netx_stop_tx(port); + return; + } + + do { + /* send xmit->buf[xmit->tail] + * out the port here */ + writel(xmit->buf[xmit->tail], port->membase + UART_DR); + xmit->tail = (xmit->tail + 1) & + (UART_XMIT_SIZE - 1); + port->icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (!(readl(port->membase + UART_FR) & FR_TXFF)); + + if (uart_circ_empty(xmit)) + netx_stop_tx(port); +} + +static void netx_start_tx(struct uart_port *port) +{ + writel( + readl(port->membase + UART_CR) | CR_TIE, port->membase + UART_CR); + + if (!(readl(port->membase + UART_FR) & FR_TXFF)) + netx_transmit_buffer(port); +} + +static unsigned int netx_tx_empty(struct uart_port *port) +{ + return readl(port->membase + UART_FR) & FR_BUSY ? 0 : TIOCSER_TEMT; +} + +static void netx_txint(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + netx_stop_tx(port); + return; + } + + netx_transmit_buffer(port); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); +} + +static void netx_rxint(struct uart_port *port, struct pt_regs *regs) +{ + unsigned char rx, flg, status; + struct tty_struct *tty = port->info->tty; + + while (!(readl(port->membase + UART_FR) & FR_RXFE)) { + rx = readl(port->membase + UART_DR); + flg = TTY_NORMAL; + port->icount.rx++; + status = readl(port->membase + UART_SR); + if (status & SR_BE) { + writel(0, port->membase + UART_SR); + if (uart_handle_break(port)) + continue; + } + + if (unlikely(status & (SR_FE | SR_PE | SR_OE))) { + + if (status & SR_PE) + port->icount.parity++; + else if (status & SR_FE) + port->icount.frame++; + if (status & SR_OE) + port->icount.overrun++; + + status &= port->read_status_mask; + + if (status & SR_BE) + flg = TTY_BREAK; + else if (status & SR_PE) + flg = TTY_PARITY; + else if (status & SR_FE) + flg = TTY_FRAME; + } + + if (uart_handle_sysrq_char(port, rx, regs)) + continue; + + uart_insert_char(port, status, SR_OE, rx, flg); + } + + tty_flip_buffer_push(tty); + return; +} + +static irqreturn_t netx_int(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_port *port = (struct uart_port *)dev_id; + unsigned long flags; + unsigned char status; + + spin_lock_irqsave(&port->lock,flags); + + status = readl(port->membase + UART_IIR) & IIR_MASK; + while (status) { + if (status & IIR_RIS) + netx_rxint(port, regs); + if (status & IIR_TIS) + netx_txint(port); + if (status & IIR_MIS) { + if (readl(port->membase + UART_FR) & FR_CTS) + uart_handle_cts_change(port, 1); + else + uart_handle_cts_change(port, 0); + } + writel(0, port->membase + UART_IIR); + status = readl(port->membase + UART_IIR) & IIR_MASK; + } + + spin_unlock_irqrestore(&port->lock,flags); + return IRQ_HANDLED; +} + +static unsigned int netx_get_mctrl(struct uart_port *port) +{ + unsigned int ret = TIOCM_DSR | TIOCM_CAR; + + if (readl(port->membase + UART_FR) & FR_CTS) + ret |= TIOCM_CTS; + + return ret; +} + +static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + unsigned int val; + + if (mctrl & TIOCM_RTS) { + val = readl(port->membase + UART_RTS_CR); + writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR); + } +} + +static void netx_break_ctl(struct uart_port *port, int break_state) +{ + unsigned int line_cr; + spin_lock_irq(&port->lock); + + line_cr = readl(port->membase + UART_LINE_CR); + if (break_state != 0) + line_cr |= LINE_CR_BRK; + else + line_cr &= ~LINE_CR_BRK; + writel(line_cr, port->membase + UART_LINE_CR); + + spin_unlock_irq(&port->lock); +} + +static int netx_startup(struct uart_port *port) +{ + int ret; + + ret = request_irq(port->irq, netx_int, 0, + DRIVER_NAME, port); + if (ret) { + dev_err(port->dev, "unable to grab irq%d\n",port->irq); + goto exit; + } + + writel(readl(port->membase + UART_LINE_CR) | LINE_CR_FEN, + port->membase + UART_LINE_CR); + + writel(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE | CR_UART_EN, + port->membase + UART_CR); + +exit: + return ret; +} + +static void netx_shutdown(struct uart_port *port) +{ + writel(0, port->membase + UART_CR) ; + + free_irq(port->irq, port); +} + +static void +netx_set_termios(struct uart_port *port, struct termios *termios, + struct termios *old) +{ + unsigned int baud, quot; + unsigned char old_cr; + unsigned char line_cr = LINE_CR_FEN; + unsigned char rts_cr = 0; + + switch (termios->c_cflag & CSIZE) { + case CS5: + line_cr |= LINE_CR_5BIT; + break; + case CS6: + line_cr |= LINE_CR_6BIT; + break; + case CS7: + line_cr |= LINE_CR_7BIT; + break; + case CS8: + line_cr |= LINE_CR_8BIT; + break; + } + + if (termios->c_cflag & CSTOPB) + line_cr |= LINE_CR_STP2; + + if (termios->c_cflag & PARENB) { + line_cr |= LINE_CR_PEN; + if (!(termios->c_cflag & PARODD)) + line_cr |= LINE_CR_EPS; + } + + if (termios->c_cflag & CRTSCTS) + rts_cr = RTS_CR_AUTO | RTS_CR_CTS_CTR | RTS_CR_RTS_POL; + + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + quot = baud * 4096; + quot /= 1000; + quot *= 256; + quot /= 100000; + + spin_lock_irq(&port->lock); + + uart_update_timeout(port, termios->c_cflag, baud); + + old_cr = readl(port->membase + UART_CR); + + /* disable interrupts */ + writel(old_cr & ~(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE), + port->membase + UART_CR); + + /* drain transmitter */ + while (readl(port->membase + UART_FR) & FR_BUSY); + + /* disable UART */ + writel(old_cr & ~CR_UART_EN, port->membase + UART_CR); + + /* modem status interrupts */ + old_cr &= ~CR_MSIE; + if (UART_ENABLE_MS(port, termios->c_cflag)) + old_cr |= CR_MSIE; + + writel((quot>>8) & 0xff, port->membase + UART_BAUDDIV_MSB); + writel(quot & 0xff, port->membase + UART_BAUDDIV_LSB); + writel(line_cr, port->membase + UART_LINE_CR); + + writel(rts_cr, port->membase + UART_RTS_CR); + + /* + * Characters to ignore + */ + port->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= SR_PE; + if (termios->c_iflag & IGNBRK) { + port->ignore_status_mask |= SR_BE; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= SR_PE; + } + + port->read_status_mask = 0; + if (termios->c_iflag & (BRKINT | PARMRK)) + port->read_status_mask |= SR_BE; + if (termios->c_iflag & INPCK) + port->read_status_mask |= SR_PE | SR_FE; + + writel(old_cr, port->membase + UART_CR); + + spin_unlock_irq(&port->lock); +} + +static const char *netx_type(struct uart_port *port) +{ + return port->type == PORT_NETX ? "NETX" : NULL; +} + +static void netx_release_port(struct uart_port *port) +{ + release_mem_region(port->mapbase, UART_PORT_SIZE); +} + +static int netx_request_port(struct uart_port *port) +{ + return request_mem_region(port->mapbase, UART_PORT_SIZE, + DRIVER_NAME) != NULL ? 0 : -EBUSY; +} + +static void netx_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE && netx_request_port(port) == 0) + port->type = PORT_NETX; +} + +static int +netx_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + int ret = 0; + + if (ser->type != PORT_UNKNOWN && ser->type != PORT_NETX) + ret = -EINVAL; + + return ret; +} + +static struct uart_ops netx_pops = { + .tx_empty = netx_tx_empty, + .set_mctrl = netx_set_mctrl, + .get_mctrl = netx_get_mctrl, + .stop_tx = netx_stop_tx, + .start_tx = netx_start_tx, + .stop_rx = netx_stop_rx, + .enable_ms = netx_enable_ms, + .break_ctl = netx_break_ctl, + .startup = netx_startup, + .shutdown = netx_shutdown, + .set_termios = netx_set_termios, + .type = netx_type, + .release_port = netx_release_port, + .request_port = netx_request_port, + .config_port = netx_config_port, + .verify_port = netx_verify_port, +}; + +static struct netx_port netx_ports[] = { + { + .port = { + .type = PORT_NETX, + .iotype = UPIO_MEM, + .membase = (char __iomem *)io_p2v(NETX_PA_UART0), + .mapbase = NETX_PA_UART0, + .irq = NETX_IRQ_UART0, + .uartclk = 100000000, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .ops = &netx_pops, + .line = 0, + }, + }, { + .port = { + .type = PORT_NETX, + .iotype = UPIO_MEM, + .membase = (char __iomem *)io_p2v(NETX_PA_UART1), + .mapbase = NETX_PA_UART1, + .irq = NETX_IRQ_UART1, + .uartclk = 100000000, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .ops = &netx_pops, + .line = 1, + }, + }, { + .port = { + .type = PORT_NETX, + .iotype = UPIO_MEM, + .membase = (char __iomem *)io_p2v(NETX_PA_UART2), + .mapbase = NETX_PA_UART2, + .irq = NETX_IRQ_UART2, + .uartclk = 100000000, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .ops = &netx_pops, + .line = 2, + }, + } +}; + +static void netx_console_putchar(struct uart_port *port, int ch) +{ + while (readl(port->membase + UART_FR) & FR_BUSY); + writel(ch, port->membase + UART_DR); +} + +static void +netx_console_write(struct console *co, const char *s, unsigned int count) +{ + struct uart_port *port = &netx_ports[co->index].port; + unsigned char cr_save; + + cr_save = readl(port->membase + UART_CR); + writel(cr_save | CR_UART_EN, port->membase + UART_CR); + + uart_console_write(port, s, count, netx_console_putchar); + + while (readl(port->membase + UART_FR) & FR_BUSY); + writel(cr_save, port->membase + UART_CR); +} + +static void __init +netx_console_get_options(struct uart_port *port, int *baud, + int *parity, int *bits, int *flow) +{ + unsigned char line_cr; + + *baud = (readl(port->membase + UART_BAUDDIV_MSB) << 8) | + readl(port->membase + UART_BAUDDIV_LSB); + *baud *= 1000; + *baud /= 4096; + *baud *= 1000; + *baud /= 256; + *baud *= 100; + + line_cr = readl(port->membase + UART_LINE_CR); + *parity = 'n'; + if (line_cr & LINE_CR_PEN) { + if (line_cr & LINE_CR_EPS) + *parity = 'e'; + else + *parity = 'o'; + } + + switch (line_cr & LINE_CR_BITS_MASK) { + case LINE_CR_8BIT: + *bits = 8; + break; + case LINE_CR_7BIT: + *bits = 7; + break; + case LINE_CR_6BIT: + *bits = 6; + break; + case LINE_CR_5BIT: + *bits = 5; + break; + } + + if (readl(port->membase + UART_RTS_CR) & RTS_CR_AUTO) + *flow = 'r'; +} + +static int __init +netx_console_setup(struct console *co, char *options) +{ + struct netx_port *sport; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + /* + * Check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ + if (co->index == -1 || co->index >= ARRAY_SIZE(netx_ports)) + co->index = 0; + sport = &netx_ports[co->index]; + + if (options) { + uart_parse_options(options, &baud, &parity, &bits, &flow); + } else { + /* if the UART is enabled, assume it has been correctly setup + * by the bootloader and get the options + */ + if (readl(sport->port.membase + UART_CR) & CR_UART_EN) { + netx_console_get_options(&sport->port, &baud, + &parity, &bits, &flow); + } + + } + + return uart_set_options(&sport->port, co, baud, parity, bits, flow); +} + +static struct uart_driver netx_reg; +static struct console netx_console = { + .name = "ttyNX", + .write = netx_console_write, + .device = uart_console_device, + .setup = netx_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &netx_reg, +}; + +static int __init netx_console_init(void) +{ + register_console(&netx_console); + return 0; +} +console_initcall(netx_console_init); + +#define NETX_CONSOLE &netx_console +#else +#define NETX_CONSOLE NULL +#endif + +static struct uart_driver netx_reg = { + .owner = THIS_MODULE, + .driver_name = DRIVER_NAME, + .dev_name = "ttyNX", + .major = SERIAL_NX_MAJOR, + .minor = MINOR_START, + .nr = ARRAY_SIZE(netx_ports), + .cons = NETX_CONSOLE, +}; + +static int serial_netx_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct netx_port *sport = platform_get_drvdata(pdev); + + if (sport) + uart_suspend_port(&netx_reg, &sport->port); + + return 0; +} + +static int serial_netx_resume(struct platform_device *pdev) +{ + struct netx_port *sport = platform_get_drvdata(pdev); + + if (sport) + uart_resume_port(&netx_reg, &sport->port); + + return 0; +} + +static int serial_netx_probe(struct platform_device *pdev) +{ + struct uart_port *port = &netx_ports[pdev->id].port; + + dev_info(&pdev->dev, "initialising\n"); + + port->dev = &pdev->dev; + + writel(1, port->membase + UART_RXFIFO_IRQLEVEL); + uart_add_one_port(&netx_reg, &netx_ports[pdev->id].port); + platform_set_drvdata(pdev, &netx_ports[pdev->id]); + + return 0; +} + +static int serial_netx_remove(struct platform_device *pdev) +{ + struct netx_port *sport = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + if (sport) + uart_remove_one_port(&netx_reg, &sport->port); + + return 0; +} + +static struct platform_driver serial_netx_driver = { + .probe = serial_netx_probe, + .remove = serial_netx_remove, + + .suspend = serial_netx_suspend, + .resume = serial_netx_resume, + + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init netx_serial_init(void) +{ + int ret; + + printk(KERN_INFO "Serial: NetX driver\n"); + + ret = uart_register_driver(&netx_reg); + if (ret) + return ret; + + ret = platform_driver_register(&serial_netx_driver); + if (ret != 0) + uart_unregister_driver(&netx_reg); + + return 0; +} + +static void __exit netx_serial_exit(void) +{ + platform_driver_unregister(&serial_netx_driver); + uart_unregister_driver(&netx_reg); +} + +module_init(netx_serial_init); +module_exit(netx_serial_exit); + +MODULE_AUTHOR("Sascha Hauer"); +MODULE_DESCRIPTION("NetX serial port driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 77d4568..ae36495 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -269,7 +269,6 @@ static unsigned int serial_pxa_get_mctrl unsigned char status; unsigned int ret; -return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; status = serial_in(up, UART_MSR); ret = 0; diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index f5aac92..837b6da 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -872,6 +872,8 @@ static const char *s3c24xx_serial_type(s return "S3C2410"; case PORT_S3C2440: return "S3C2440"; + case PORT_S3C2412: + return "S3C2412"; default: return NULL; } @@ -1365,7 +1367,7 @@ #define s3c2410_uart_inf_at NULL #endif /* CONFIG_CPU_S3C2410 */ -#ifdef CONFIG_CPU_S3C2440 +#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) static int s3c2440_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *clk) @@ -1528,6 +1530,141 @@ static inline void s3c2440_serial_exit(v #define s3c2440_uart_inf_at NULL #endif /* CONFIG_CPU_S3C2440 */ +#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) + +static int s3c2412_serial_setsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + ucon &= ~S3C2412_UCON_CLKMASK; + + if (strcmp(clk->name, "uclk") == 0) + ucon |= S3C2440_UCON_UCLK; + else if (strcmp(clk->name, "pclk") == 0) + ucon |= S3C2440_UCON_PCLK; + else if (strcmp(clk->name, "usysclk") == 0) + ucon |= S3C2412_UCON_USYSCLK; + else { + printk(KERN_ERR "unknown clock source %s\n", clk->name); + return -EINVAL; + } + + wr_regl(port, S3C2410_UCON, ucon); + return 0; +} + + +static int s3c2412_serial_getsource(struct uart_port *port, + struct s3c24xx_uart_clksrc *clk) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + switch (ucon & S3C2412_UCON_CLKMASK) { + case S3C2412_UCON_UCLK: + clk->divisor = 1; + clk->name = "uclk"; + break; + + case S3C2412_UCON_PCLK: + case S3C2412_UCON_PCLK2: + clk->divisor = 1; + clk->name = "pclk"; + break; + + case S3C2412_UCON_USYSCLK: + clk->divisor = 1; + clk->name = "usysclk"; + break; + } + + return 0; +} + +static int s3c2412_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) +{ + unsigned long ucon = rd_regl(port, S3C2410_UCON); + + dbg("%s: port=%p (%08lx), cfg=%p\n", + __FUNCTION__, port, port->mapbase, cfg); + + /* ensure we don't change the clock settings... */ + + ucon &= S3C2412_UCON_CLKMASK; + + wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); + wr_regl(port, S3C2410_ULCON, cfg->ulcon); + + /* reset both fifos */ + + wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); + wr_regl(port, S3C2410_UFCON, cfg->ufcon); + + return 0; +} + +static struct s3c24xx_uart_info s3c2412_uart_inf = { + .name = "Samsung S3C2412 UART", + .type = PORT_S3C2412, + .fifosize = 64, + .rx_fifomask = S3C2440_UFSTAT_RXMASK, + .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2440_UFSTAT_RXFULL, + .tx_fifofull = S3C2440_UFSTAT_TXFULL, + .tx_fifomask = S3C2440_UFSTAT_TXMASK, + .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, + .get_clksrc = s3c2412_serial_getsource, + .set_clksrc = s3c2412_serial_setsource, + .reset_port = s3c2412_serial_resetport, +}; + +/* device management */ + +static int s3c2412_serial_probe(struct platform_device *dev) +{ + dbg("s3c2440_serial_probe: dev=%p\n", dev); + return s3c24xx_serial_probe(dev, &s3c2440_uart_inf); +} + +static struct platform_driver s3c2412_serial_drv = { + .probe = s3c2412_serial_probe, + .remove = s3c24xx_serial_remove, + .suspend = s3c24xx_serial_suspend, + .resume = s3c24xx_serial_resume, + .driver = { + .name = "s3c2412-uart", + .owner = THIS_MODULE, + }, +}; + + +static inline int s3c2412_serial_init(void) +{ + return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf); +} + +static inline void s3c2412_serial_exit(void) +{ + platform_driver_unregister(&s3c2412_serial_drv); +} + +#define s3c2412_uart_inf_at &s3c2412_uart_inf +#else + +static inline int s3c2412_serial_init(void) +{ + return 0; +} + +static inline void s3c2412_serial_exit(void) +{ +} + +#define s3c2412_uart_inf_at NULL +#endif /* CONFIG_CPU_S3C2440 */ + + /* module initialisation code */ static int __init s3c24xx_serial_modinit(void) @@ -1542,6 +1679,7 @@ static int __init s3c24xx_serial_modinit s3c2400_serial_init(); s3c2410_serial_init(); + s3c2412_serial_init(); s3c2440_serial_init(); return 0; @@ -1551,6 +1689,7 @@ static void __exit s3c24xx_serial_modexi { s3c2400_serial_exit(); s3c2410_serial_exit(); + s3c2412_serial_exit(); s3c2440_serial_exit(); uart_unregister_driver(&s3c24xx_uart_drv); @@ -1773,6 +1912,8 @@ static int s3c24xx_serial_initconsole(vo info = s3c2410_uart_inf_at; } else if (strcmp(dev->name, "s3c2440-uart") == 0) { info = s3c2440_uart_inf_at; + } else if (strcmp(dev->name, "s3c2412-uart") == 0) { + info = s3c2412_uart_inf_at; } else { printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name); return 0; @@ -1796,4 +1937,4 @@ #endif /* CONFIG_SERIAL_S3C2410_CONSOLE MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ben Dooks "); -MODULE_DESCRIPTION("Samsung S3C2410/S3C2440 Serial port driver"); +MODULE_DESCRIPTION("Samsung S3C2410/S3C2440/S3C2412 Serial port driver"); diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index aa521b8..776d4ff 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -145,14 +145,15 @@ #endif { struct tty_struct* tty = port->info->tty; int cbRxMax = 256; /* (Gross) limit on receive */ - unsigned int data, flag;/* Received data and status */ + unsigned int data; /* Received data and status */ + unsigned int flag; while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) { data = UR (port, UART_R_DATA); flag = TTY_NORMAL; ++port->icount.rx; - if (unlikely(data & RxError)) { /* Quick check, short-circuit */ + if (unlikely(data & RxError)) { if (data & RxBreak) { data &= ~(RxFramingError | RxParityError); ++port->icount.brk; @@ -303,7 +304,7 @@ static void lh7a40xuart_set_mctrl (struc /* Note, kernel appears to be setting DTR and RTS on console. */ /* *** FIXME: this deserves more work. There's some work in - tracing all of the IO pins. */ + tracing all of the IO pins. */ #if 0 if( port->mapbase == UART1_PHYS) { gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); @@ -662,9 +663,13 @@ static int __init lh7a40xuart_init(void) if (ret == 0) { int i; - for (i = 0; i < DEV_NR; i++) + for (i = 0; i < DEV_NR; i++) { + /* UART3, when used, requires GPIO pin reallocation */ + if (lh7a40x_ports[i].port.mapbase == UART3_PHYS) + GPIO_PINMUX |= 1<<3; uart_add_one_port (&lh7a40x_reg, &lh7a40x_ports[i].port); + } } return ret; } diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index f137804..ba22e25 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -427,31 +427,32 @@ static int __init hv_console_compatible( static unsigned int __init get_interrupt(void) { - const char *cons_str = "console"; - const char *compat_str = "compatible"; - int node = prom_getchild(sun4v_vdev_root); - char buf[64]; - int err, len; - - node = prom_searchsiblings(node, cons_str); - if (!node) - return 0; + struct device_node *dev_node; - len = prom_getproplen(node, compat_str); - if (len == 0 || len == -1) - return 0; + dev_node = sun4v_vdev_root->child; + while (dev_node != NULL) { + struct property *prop; - err = prom_getproperty(node, compat_str, buf, 64); - if (err == -1) - return 0; + if (strcmp(dev_node->name, "console")) + goto next_sibling; + + prop = of_find_property(dev_node, "compatible", NULL); + if (!prop) + goto next_sibling; - if (!hv_console_compatible(buf, len)) + if (hv_console_compatible(prop->value, prop->length)) + break; + + next_sibling: + dev_node = dev_node->sibling; + } + if (!dev_node) return 0; /* Ok, the this is the OBP node for the sun4v hypervisor * console device. Decode the interrupt. */ - return sun4v_vdev_device_interrupt(node); + return sun4v_vdev_device_interrupt(dev_node); } static int __init sunhv_init(void) diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index bfbe9dc..e4c0fd2 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -984,19 +984,19 @@ static void __init for_each_sab_edev(voi for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "se")) { + if (!strcmp(edev->prom_node->name, "se")) { callback(edev, arg); continue; - } else if (!strcmp(edev->prom_name, "serial")) { - char compat[32]; + } else if (!strcmp(edev->prom_node->name, "serial")) { + char *compat; int clen; /* On RIO this can be an SE, check it. We could * just check ebus->is_rio, but this is more portable. */ - clen = prom_getproperty(edev->prom_node, "compatible", - compat, sizeof(compat)); - if (clen > 0) { + compat = of_get_property(edev->prom_node, + "compatible", &clen); + if (compat && clen > 0) { if (strncmp(compat, "sab82532", 8) == 0) { callback(edev, arg); continue; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 2b4f965..0268b30 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1053,7 +1053,7 @@ #endif */ for_each_ebus(ebus) { for_each_ebusdev(dev, ebus) { - if (dev->prom_node == up->port_node) { + if (dev->prom_node->node == up->port_node) { /* * The EBus is broken on sparc; it delivers * virtual addresses in resources. Oh well... @@ -1073,7 +1073,7 @@ #endif #ifdef CONFIG_SPARC64 for_each_isa(isa_br) { for_each_isadev(isa_dev, isa_br) { - if (isa_dev->prom_node == up->port_node) { + if (isa_dev->prom_node->node == up->port_node) { /* Same on sparc64. Cool architecure... */ up->port.membase = (char *) isa_dev->resource.start; up->port.mapbase = isa_dev->resource.start; @@ -1295,9 +1295,9 @@ #endif if (up->port.type == PORT_UNKNOWN) return -1; - printk(KERN_INFO "su%d at 0x%p (irq = %s) is a %s\n", + printk(KERN_INFO "su%d at 0x%p (irq = %d) is a %s\n", channel, - up->port.membase, __irq_itoa(up->port.irq), + up->port.membase, up->port.irq, sunsu_type(&up->port)); #ifdef CONFIG_SERIO diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index cd49ebb..76c9bac 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1106,7 +1106,7 @@ static struct zilog_layout __iomem * __i + FHC_UREGS_ICLR; imap = central_bus->child->fhc_regs.uregs + FHC_UREGS_IMAP; - zilog_irq = build_irq(12, 0, iclr, imap); + zilog_irq = build_irq(0, iclr, imap); } else { err = prom_getproperty(zsnode, "interrupts", (char *) &sun4u_ino, @@ -1540,8 +1540,8 @@ static void __init sunzilog_init_kbdms(s up->cflag = B4800 | CS8 | CLOCAL | CREAD; baud = 4800; } - printk(KERN_INFO "zs%d at 0x%p (irq = %s) is a SunZilog\n", - channel, up->port.membase, __irq_itoa(zilog_irq)); + printk(KERN_INFO "zs%d at 0x%p (irq = %d) is a SunZilog\n", + channel, up->port.membase, zilog_irq); up->curregs[R15] = BRKIE; brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c index cdeff90..8256a97 100644 --- a/drivers/sn/ioc4.c +++ b/drivers/sn/ioc4.c @@ -160,9 +160,6 @@ ioc4_clock_calibrate(struct ioc4_driver_ writel(0, &idd->idd_misc_regs->int_out.raw); mmiowb(); - printk(KERN_INFO - "%s: Calibrating PCI bus speed " - "for pci_dev %s ... ", __FUNCTION__, pci_name(idd->idd_pdev)); /* Set up square wave */ int_out.raw = 0; int_out.fields.count = IOC4_CALIBRATE_COUNT; @@ -206,11 +203,16 @@ ioc4_clock_calibrate(struct ioc4_driver_ /* Bounds check the result. */ if (period > IOC4_CALIBRATE_LOW_LIMIT || period < IOC4_CALIBRATE_HIGH_LIMIT) { - printk("failed. Assuming PCI clock ticks are %d ns.\n", + printk(KERN_INFO + "IOC4 %s: Clock calibration failed. Assuming" + "PCI clock is %d ns.\n", + pci_name(idd->idd_pdev), IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR); period = IOC4_CALIBRATE_DEFAULT; } else { - printk("succeeded. PCI clock ticks are %ld ns.\n", + printk(KERN_DEBUG + "IOC4 %s: PCI clock is %ld ns.\n", + pci_name(idd->idd_pdev), period / IOC4_EXTINT_COUNT_DIVISOR); } @@ -222,6 +224,51 @@ ioc4_clock_calibrate(struct ioc4_driver_ idd->count_period = period; } +/* There are three variants of IOC4 cards: IO9, IO10, and PCI-RT. + * Each brings out different combinations of IOC4 signals, thus. + * the IOC4 subdrivers need to know to which we're attached. + * + * We look for the presence of a SCSI (IO9) or SATA (IO10) controller + * on the same PCI bus at slot number 3 to differentiate IO9 from IO10. + * If neither is present, it's a PCI-RT. + */ +static unsigned int +ioc4_variant(struct ioc4_driver_data *idd) +{ + struct pci_dev *pdev = NULL; + int found = 0; + + /* IO9: Look for a QLogic ISP 12160 at the same bus and slot 3. */ + do { + pdev = pci_get_device(PCI_VENDOR_ID_QLOGIC, + PCI_DEVICE_ID_QLOGIC_ISP12160, pdev); + if (pdev && + idd->idd_pdev->bus->number == pdev->bus->number && + 3 == PCI_SLOT(pdev->devfn)) + found = 1; + pci_dev_put(pdev); + } while (pdev && !found); + if (NULL != pdev) + return IOC4_VARIANT_IO9; + + /* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */ + pdev = NULL; + do { + pdev = pci_get_device(PCI_VENDOR_ID_VITESSE, + PCI_DEVICE_ID_VITESSE_VSC7174, pdev); + if (pdev && + idd->idd_pdev->bus->number == pdev->bus->number && + 3 == PCI_SLOT(pdev->devfn)) + found = 1; + pci_dev_put(pdev); + } while (pdev && !found); + if (NULL != pdev) + return IOC4_VARIANT_IO10; + + /* PCI-RT: No SCSI/SATA controller will be present */ + return IOC4_VARIANT_PCI_RT; +} + /* Adds a new instance of an IOC4 card */ static int ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) @@ -286,6 +333,13 @@ ioc4_probe(struct pci_dev *pdev, const s /* Failsafe portion of per-IOC4 initialization */ + /* Detect card variant */ + idd->idd_variant = ioc4_variant(idd); + printk(KERN_INFO "IOC4 %s: %s card detected.\n", pci_name(pdev), + idd->idd_variant == IOC4_VARIANT_IO9 ? "IO9" : + idd->idd_variant == IOC4_VARIANT_PCI_RT ? "PCI-RT" : + idd->idd_variant == IOC4_VARIANT_IO10 ? "IO10" : "unknown"); + /* Initialize IOC4 */ pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd); pci_write_config_dword(idd->idd_pdev, PCI_COMMAND, diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index 5578a9d..f6b2948 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c @@ -5712,7 +5712,7 @@ static int ixj_daa_write(IXJ *j) return 1; } -int ixj_set_tone_off(unsigned short arg, IXJ *j) +static int ixj_set_tone_off(unsigned short arg, IXJ *j) { j->tone_off_time = arg; if (ixj_WriteDSPCommand(0x6E05, j)) /* Set Tone Off Period */ diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 9b7d976..c7123bf 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB_AUERSWALD) += misc/ +obj-$(CONFIG_USB_CY7C63) += misc/ obj-$(CONFIG_USB_CYTHERM) += misc/ obj-$(CONFIG_USB_EMI26) += misc/ obj-$(CONFIG_USB_EMI62) += misc/ @@ -61,6 +62,7 @@ obj-$(CONFIG_USB_TEST) += misc/ obj-$(CONFIG_USB_USS720) += misc/ obj-$(CONFIG_USB_PHIDGETSERVO) += misc/ obj-$(CONFIG_USB_SISUSBVGA) += misc/ +obj-$(CONFIG_USB_APPLEDISPLAY) += misc/ obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 5462498..a38701c 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -1039,7 +1039,7 @@ static void usbatm_tasklet_schedule(unsi tasklet_schedule((struct tasklet_struct *) data); } -static inline void usbatm_init_channel(struct usbatm_channel *channel) +static void usbatm_init_channel(struct usbatm_channel *channel) { spin_lock_init(&channel->lock); INIT_LIST_HEAD(&channel->list); diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c index 42d6823..70125c6 100644 --- a/drivers/usb/atm/xusbatm.c +++ b/drivers/usb/atm/xusbatm.c @@ -20,7 +20,6 @@ ******************************************************************************/ #include -#include /* FIXME: required by linux/etherdevice.h */ #include /* for random_ether_addr() */ #include "usbatm.h" diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 6dd339f..d41dc67 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -63,7 +63,7 @@ #include #include #include #include -#include +#include #include #include #include @@ -127,8 +127,8 @@ static int acm_wb_alloc(struct acm *acm) wb->use = 1; return wbn; } - wbn = (wbn + 1) % ACM_NWB; - if (++i >= ACM_NWB) + wbn = (wbn + 1) % ACM_NW; + if (++i >= ACM_NW) return -1; } } @@ -142,10 +142,9 @@ static int acm_wb_is_avail(struct acm *a { int i, n; - n = 0; - for (i = 0; i < ACM_NWB; i++) { - if (!acm->wb[i].use) - n++; + n = ACM_NW; + for (i = 0; i < ACM_NW; i++) { + n -= acm->wb[i].use; } return n; } @@ -167,7 +166,7 @@ static void acm_write_done(struct acm *a acm->write_ready = 1; wbn = acm->write_current; acm_wb_free(acm, wbn); - acm->write_current = (wbn + 1) % ACM_NWB; + acm->write_current = (wbn + 1) % ACM_NW; spin_unlock_irqrestore(&acm->write_lock, flags); } @@ -291,22 +290,32 @@ static void acm_read_bulk(struct urb *ur struct acm_rb *buf; struct acm_ru *rcv = urb->context; struct acm *acm = rcv->instance; + int status = urb->status; dbg("Entering acm_read_bulk with status %d\n", urb->status); if (!ACM_READY(acm)) return; - if (urb->status) - dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status); + if (status) + dev_dbg(&acm->data->dev, "bulk rx status %d\n", status); buf = rcv->buffer; buf->size = urb->actual_length; - spin_lock(&acm->read_lock); - list_add_tail(&rcv->list, &acm->spare_read_urbs); - list_add_tail(&buf->list, &acm->filled_read_bufs); - spin_unlock(&acm->read_lock); - + if (likely(status == 0)) { + spin_lock(&acm->read_lock); + list_add_tail(&rcv->list, &acm->spare_read_urbs); + list_add_tail(&buf->list, &acm->filled_read_bufs); + spin_unlock(&acm->read_lock); + } else { + /* we drop the buffer due to an error */ + spin_lock(&acm->read_lock); + list_add_tail(&rcv->list, &acm->spare_read_urbs); + list_add(&buf->list, &acm->spare_read_bufs); + spin_unlock(&acm->read_lock); + /* nevertheless the tasklet must be kicked unconditionally + so the queue cannot dry up */ + } tasklet_schedule(&acm->urb_task); } @@ -464,10 +473,10 @@ static int acm_tty_open(struct tty_struc INIT_LIST_HEAD(&acm->spare_read_urbs); INIT_LIST_HEAD(&acm->spare_read_bufs); INIT_LIST_HEAD(&acm->filled_read_bufs); - for (i = 0; i < ACM_NRU; i++) { + for (i = 0; i < acm->rx_buflimit; i++) { list_add(&(acm->ru[i].list), &acm->spare_read_urbs); } - for (i = 0; i < ACM_NRB; i++) { + for (i = 0; i < acm->rx_buflimit; i++) { list_add(&(acm->rb[i].list), &acm->spare_read_bufs); } @@ -488,14 +497,15 @@ bail_out: static void acm_tty_unregister(struct acm *acm) { - int i; + int i,nr; + nr = acm->rx_buflimit; tty_unregister_device(acm_tty_driver, acm->minor); usb_put_intf(acm->control); acm_table[acm->minor] = NULL; usb_free_urb(acm->ctrlurb); usb_free_urb(acm->writeurb); - for (i = 0; i < ACM_NRU; i++) + for (i = 0; i < nr; i++) usb_free_urb(acm->ru[i].urb); kfree(acm); } @@ -503,18 +513,19 @@ static void acm_tty_unregister(struct ac static void acm_tty_close(struct tty_struct *tty, struct file *filp) { struct acm *acm = tty->driver_data; - int i; + int i,nr; if (!acm || !acm->used) return; + nr = acm->rx_buflimit; mutex_lock(&open_mutex); if (!--acm->used) { if (acm->dev) { acm_set_control(acm, acm->ctrlout = 0); usb_kill_urb(acm->ctrlurb); usb_kill_urb(acm->writeurb); - for (i = 0; i < ACM_NRU; i++) + for (i = 0; i < nr; i++) usb_kill_urb(acm->ru[i].urb); } else acm_tty_unregister(acm); @@ -576,7 +587,7 @@ static int acm_tty_chars_in_buffer(struc /* * This is inaccurate (overcounts), but it works. */ - return (ACM_NWB - acm_wb_is_avail(acm)) * acm->writesize; + return (ACM_NW - acm_wb_is_avail(acm)) * acm->writesize; } static void acm_tty_throttle(struct tty_struct *tty) @@ -712,7 +723,7 @@ static void acm_write_buffers_free(struc int i; struct acm_wb *wb; - for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { + for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah); } } @@ -723,7 +734,7 @@ static int acm_write_buffers_alloc(struc int i; struct acm_wb *wb; - for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { + for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL, &wb->dmah); if (!wb->buf) { @@ -760,10 +771,14 @@ static int acm_probe (struct usb_interfa int call_interface_num = -1; int data_interface_num; unsigned long quirks; + int num_rx_buf; int i; - /* handle quirks deadly to normal probing*/ + /* normal quirks */ quirks = (unsigned long)id->driver_info; + num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR; + + /* handle quirks deadly to normal probing*/ if (quirks == NO_UNION_NORMAL) { data_interface = usb_ifnum_to_if(usb_dev, 1); control_interface = usb_ifnum_to_if(usb_dev, 0); @@ -900,7 +915,7 @@ skip_normal_probe: } ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); - readsize = le16_to_cpu(epread->wMaxPacketSize)*2; + readsize = le16_to_cpu(epread->wMaxPacketSize)* ( quirks == SINGLE_RX_URB ? 1 : 2); acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize); acm->control = control_interface; acm->data = data_interface; @@ -909,6 +924,7 @@ skip_normal_probe: acm->ctrl_caps = ac_management_function; acm->ctrlsize = ctrlsize; acm->readsize = readsize; + acm->rx_buflimit = num_rx_buf; acm->urb_task.func = acm_rx_tasklet; acm->urb_task.data = (unsigned long) acm; INIT_WORK(&acm->work, acm_softint, acm); @@ -935,7 +951,7 @@ skip_normal_probe: dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n"); goto alloc_fail5; } - for (i = 0; i < ACM_NRU; i++) { + for (i = 0; i < num_rx_buf; i++) { struct acm_ru *rcv = &(acm->ru[i]); if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) { @@ -946,10 +962,9 @@ skip_normal_probe: rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; rcv->instance = acm; } - for (i = 0; i < ACM_NRB; i++) { + for (i = 0; i < num_rx_buf; i++) { struct acm_rb *buf = &(acm->rb[i]); - // Using usb_buffer_alloc instead of kmalloc as Oliver suggested if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) { dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n"); goto alloc_fail7; @@ -988,9 +1003,9 @@ skip_normal_probe: return 0; alloc_fail7: - for (i = 0; i < ACM_NRB; i++) + for (i = 0; i < num_rx_buf; i++) usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); - for (i = 0; i < ACM_NRU; i++) + for (i = 0; i < num_rx_buf; i++) usb_free_urb(acm->ru[i].urb); usb_free_urb(acm->ctrlurb); alloc_fail5: @@ -1027,7 +1042,7 @@ static void acm_disconnect(struct usb_in usb_kill_urb(acm->ctrlurb); usb_kill_urb(acm->writeurb); - for (i = 0; i < ACM_NRU; i++) + for (i = 0; i < acm->rx_buflimit; i++) usb_kill_urb(acm->ru[i].urb); INIT_LIST_HEAD(&acm->filled_read_bufs); @@ -1039,7 +1054,7 @@ static void acm_disconnect(struct usb_in acm_write_buffers_free(acm); usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); - for (i = 0; i < ACM_NRB; i++) + for (i = 0; i < acm->rx_buflimit; i++) usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf); @@ -1068,6 +1083,9 @@ static struct usb_device_id acm_ids[] = { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, + { USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */ + .driver_info = SINGLE_RX_URB, /* firmware bug */ + }, /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_V25TER) }, diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index fd2aacc..1bcaea3 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -56,11 +56,11 @@ #define ACM_CTRL_OVERRUN 0x40 * in line disciplines. They ask for empty space amount, receive our URB size, * and proceed to issue several 1-character writes, assuming they will fit. * The very first write takes a complete URB. Fortunately, this only happens - * when processing onlcr, so we only need 2 buffers. + * when processing onlcr, so we only need 2 buffers. These values must be + * powers of 2. */ -#define ACM_NWB 2 -#define ACM_NRU 16 -#define ACM_NRB 16 +#define ACM_NW 2 +#define ACM_NR 16 struct acm_wb { unsigned char *buf; @@ -91,9 +91,10 @@ struct acm { struct urb *ctrlurb, *writeurb; /* urbs */ u8 *ctrl_buffer; /* buffers of urbs */ dma_addr_t ctrl_dma; /* dma handles of buffers */ - struct acm_wb wb[ACM_NWB]; - struct acm_ru ru[ACM_NRU]; - struct acm_rb rb[ACM_NRB]; + struct acm_wb wb[ACM_NW]; + struct acm_ru ru[ACM_NR]; + struct acm_rb rb[ACM_NR]; + int rx_buflimit; int rx_endpoint; spinlock_t read_lock; struct list_head spare_read_urbs; @@ -122,3 +123,4 @@ #define CDC_DATA_INTERFACE_TYPE 0x0a /* constants describing various quirks and errors */ #define NO_UNION_NORMAL 1 +#define SINGLE_RX_URB 2 diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 28329dd..ec51092 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile @@ -3,7 +3,8 @@ # Makefile for USB Core files and filesy # usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ - config.o file.o buffer.o sysfs.o devio.o notify.o + config.o file.o buffer.o sysfs.o endpoint.o \ + devio.o notify.o ifeq ($(CONFIG_PCI),y) usbcore-objs += hcd-pci.o diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 545da37..bcbeaf7 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -515,19 +515,19 @@ static int check_ctrlrecip(struct dev_st static struct usb_device *usbdev_lookup_minor(int minor) { - struct class_device *class_dev; - struct usb_device *dev = NULL; + struct device *device; + struct usb_device *udev = NULL; down(&usb_device_class->sem); - list_for_each_entry(class_dev, &usb_device_class->children, node) { - if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { - dev = class_dev->class_data; + list_for_each_entry(device, &usb_device_class->devices, node) { + if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { + udev = device->platform_data; break; } } up(&usb_device_class->sem); - return dev; + return udev; }; /* @@ -823,8 +823,7 @@ static int proc_connectinfo(struct dev_s static int proc_resetdevice(struct dev_state *ps) { - return usb_reset_device(ps->dev); - + return usb_reset_composite_device(ps->dev, NULL); } static int proc_setintf(struct dev_state *ps, void __user *arg) @@ -923,8 +922,8 @@ static int proc_do_submiturb(struct dev_ if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_CONTROL) return -EINVAL; - /* min 8 byte setup packet, max arbitrary */ - if (uurb->buffer_length < 8 || uurb->buffer_length > PAGE_SIZE) + /* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */ + if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE)) return -EINVAL; if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL))) return -ENOMEM; @@ -982,7 +981,8 @@ static int proc_do_submiturb(struct dev_ return -EFAULT; } for (totlen = u = 0; u < uurb->number_of_packets; u++) { - if (isopkt[u].length > 1023) { + /* arbitrary limit, sufficient for USB 2.0 high-bandwidth iso */ + if (isopkt[u].length > 8192) { kfree(isopkt); return -EINVAL; } @@ -1576,16 +1576,16 @@ static void usbdev_add(struct usb_device { int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); - dev->class_dev = class_device_create(usb_device_class, NULL, - MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev, + dev->usbfs_dev = device_create(usb_device_class, &dev->dev, + MKDEV(USB_DEVICE_MAJOR, minor), "usbdev%d.%d", dev->bus->busnum, dev->devnum); - dev->class_dev->class_data = dev; + dev->usbfs_dev->platform_data = dev; } static void usbdev_remove(struct usb_device *dev) { - class_device_unregister(dev->class_dev); + device_unregister(dev->usbfs_dev); } static int usbdev_notify(struct notifier_block *self, unsigned long action, diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c new file mode 100644 index 0000000..247b5a4 --- /dev/null +++ b/drivers/usb/core/endpoint.c @@ -0,0 +1,275 @@ +/* + * drivers/usb/core/endpoint.c + * + * (C) Copyright 2002,2004,2006 Greg Kroah-Hartman + * (C) Copyright 2002,2004 IBM Corp. + * (C) Copyright 2006 Novell Inc. + * + * Endpoint sysfs stuff + * + */ + +#include +#include +#include "usb.h" + +/* endpoint stuff */ + +struct ep_device { + struct usb_endpoint_descriptor *desc; + struct usb_device *udev; + struct device dev; +}; +#define to_ep_device(_dev) \ + container_of(_dev, struct ep_device, dev) + +struct ep_attribute { + struct attribute attr; + ssize_t (*show)(struct usb_device *, + struct usb_endpoint_descriptor *, char *); +}; +#define to_ep_attribute(_attr) \ + container_of(_attr, struct ep_attribute, attr) + +#define usb_ep_attr(field, format_string) \ +static ssize_t show_ep_##field(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct ep_device *ep = to_ep_device(dev); \ + return sprintf(buf, format_string, ep->desc->field); \ +} \ +static DEVICE_ATTR(field, S_IRUGO, show_ep_##field, NULL); + +usb_ep_attr(bLength, "%02x\n") +usb_ep_attr(bEndpointAddress, "%02x\n") +usb_ep_attr(bmAttributes, "%02x\n") +usb_ep_attr(bInterval, "%02x\n") + +static ssize_t show_ep_wMaxPacketSize(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ep_device *ep = to_ep_device(dev); + return sprintf(buf, "%04x\n", + le16_to_cpu(ep->desc->wMaxPacketSize) & 0x07ff); +} +static DEVICE_ATTR(wMaxPacketSize, S_IRUGO, show_ep_wMaxPacketSize, NULL); + +static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ep_device *ep = to_ep_device(dev); + char *type = "unknown"; + + switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_CONTROL: + type = "Control"; + break; + case USB_ENDPOINT_XFER_ISOC: + type = "Isoc"; + break; + case USB_ENDPOINT_XFER_BULK: + type = "Bulk"; + break; + case USB_ENDPOINT_XFER_INT: + type = "Interrupt"; + break; + } + return sprintf(buf, "%s\n", type); +} +static DEVICE_ATTR(type, S_IRUGO, show_ep_type, NULL); + +static ssize_t show_ep_interval(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ep_device *ep = to_ep_device(dev); + char unit; + unsigned interval = 0; + unsigned in; + + in = (ep->desc->bEndpointAddress & USB_DIR_IN); + + switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_CONTROL: + if (ep->udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ + interval = ep->desc->bInterval; + break; + case USB_ENDPOINT_XFER_ISOC: + interval = 1 << (ep->desc->bInterval - 1); + break; + case USB_ENDPOINT_XFER_BULK: + if (ep->udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ + interval = ep->desc->bInterval; + break; + case USB_ENDPOINT_XFER_INT: + if (ep->udev->speed == USB_SPEED_HIGH) + interval = 1 << (ep->desc->bInterval - 1); + else + interval = ep->desc->bInterval; + break; + } + interval *= (ep->udev->speed == USB_SPEED_HIGH) ? 125 : 1000; + if (interval % 1000) + unit = 'u'; + else { + unit = 'm'; + interval /= 1000; + } + + return sprintf(buf, "%d%cs\n", interval, unit); +} +static DEVICE_ATTR(interval, S_IRUGO, show_ep_interval, NULL); + +static ssize_t show_ep_direction(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ep_device *ep = to_ep_device(dev); + char *direction; + + if ((ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL) + direction = "both"; + else if (ep->desc->bEndpointAddress & USB_DIR_IN) + direction = "in"; + else + direction = "out"; + return sprintf(buf, "%s\n", direction); +} +static DEVICE_ATTR(direction, S_IRUGO, show_ep_direction, NULL); + +static struct attribute *ep_dev_attrs[] = { + &dev_attr_bLength.attr, + &dev_attr_bEndpointAddress.attr, + &dev_attr_bmAttributes.attr, + &dev_attr_bInterval.attr, + &dev_attr_wMaxPacketSize.attr, + &dev_attr_interval.attr, + &dev_attr_type.attr, + &dev_attr_direction.attr, + NULL, +}; +static struct attribute_group ep_dev_attr_grp = { + .attrs = ep_dev_attrs, +}; + +static struct endpoint_class { + struct kref kref; + struct class *class; +} *ep_class; + +static int init_endpoint_class(void) +{ + int result = 0; + + if (ep_class != NULL) { + kref_get(&ep_class->kref); + goto exit; + } + + ep_class = kmalloc(sizeof(*ep_class), GFP_KERNEL); + if (!ep_class) { + result = -ENOMEM; + goto exit; + } + + kref_init(&ep_class->kref); + ep_class->class = class_create(THIS_MODULE, "usb_endpoint"); + if (IS_ERR(ep_class->class)) { + result = IS_ERR(ep_class->class); + kfree(ep_class); + ep_class = NULL; + goto exit; + } + +exit: + return result; +} + +static void release_endpoint_class(struct kref *kref) +{ + /* Ok, we cheat as we know we only have one ep_class */ + class_destroy(ep_class->class); + kfree(ep_class); + ep_class = NULL; +} + +static void destroy_endpoint_class(void) +{ + if (ep_class) + kref_put(&ep_class->kref, release_endpoint_class); +} + +static void ep_device_release(struct device *dev) +{ + struct ep_device *ep_dev = to_ep_device(dev); + + dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id); + kfree(ep_dev); +} + +void usb_create_ep_files(struct device *parent, + struct usb_host_endpoint *endpoint, + struct usb_device *udev) +{ + char name[8]; + struct ep_device *ep_dev; + int minor; + int retval; + + retval = init_endpoint_class(); + if (retval) + goto exit; + + ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL); + if (!ep_dev) { + retval = -ENOMEM; + goto exit; + } + + /* fun calculation to determine the minor of this endpoint */ + minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1); + + ep_dev->desc = &endpoint->desc; + ep_dev->udev = udev; + ep_dev->dev.devt = MKDEV(442, minor); // FIXME fake number... + ep_dev->dev.class = ep_class->class; + ep_dev->dev.parent = parent; + ep_dev->dev.release = ep_device_release; + snprintf(ep_dev->dev.bus_id, BUS_ID_SIZE, "usbdev%d.%d_ep%02x", + udev->bus->busnum, udev->devnum, + endpoint->desc.bEndpointAddress); + + retval = device_register(&ep_dev->dev); + if (retval) + goto error; + sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); + + endpoint->ep_dev = ep_dev; + + /* create the symlink to the old-style "ep_XX" directory */ + sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); + sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name); + +exit: + return; +error: + kfree(ep_dev); + return; +} + +void usb_remove_ep_files(struct usb_host_endpoint *endpoint) +{ + + if (endpoint->ep_dev) { + char name[8]; + + sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); + sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name); + sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp); + device_unregister(&endpoint->ep_dev->dev); + endpoint->ep_dev = NULL; + } + destroy_endpoint_class(); +} + + diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index b263a54..f65b193 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -61,33 +61,66 @@ static struct file_operations usb_fops = .open = usb_open, }; -static struct class *usb_class; +static struct usb_class { + struct kref kref; + struct class *class; +} *usb_class; -int usb_major_init(void) +static int init_usb_class(void) { - int error; + int result = 0; - error = register_chrdev(USB_MAJOR, "usb", &usb_fops); - if (error) { - err("unable to get major %d for usb devices", USB_MAJOR); - goto out; + if (usb_class != NULL) { + kref_get(&usb_class->kref); + goto exit; + } + + usb_class = kmalloc(sizeof(*usb_class), GFP_KERNEL); + if (!usb_class) { + result = -ENOMEM; + goto exit; } - usb_class = class_create(THIS_MODULE, "usb"); - if (IS_ERR(usb_class)) { - error = PTR_ERR(usb_class); + kref_init(&usb_class->kref); + usb_class->class = class_create(THIS_MODULE, "usb"); + if (IS_ERR(usb_class->class)) { + result = IS_ERR(usb_class->class); err("class_create failed for usb devices"); - unregister_chrdev(USB_MAJOR, "usb"); - goto out; + kfree(usb_class); + usb_class = NULL; } -out: +exit: + return result; +} + +static void release_usb_class(struct kref *kref) +{ + /* Ok, we cheat as we know we only have one usb_class */ + class_destroy(usb_class->class); + kfree(usb_class); + usb_class = NULL; +} + +static void destroy_usb_class(void) +{ + if (usb_class) + kref_put(&usb_class->kref, release_usb_class); +} + +int usb_major_init(void) +{ + int error; + + error = register_chrdev(USB_MAJOR, "usb", &usb_fops); + if (error) + err("unable to get major %d for usb devices", USB_MAJOR); + return error; } void usb_major_cleanup(void) { - class_destroy(usb_class); unregister_chrdev(USB_MAJOR, "usb"); } @@ -149,6 +182,10 @@ #endif if (retval) goto exit; + retval = init_usb_class(); + if (retval) + goto exit; + intf->minor = minor; /* create a usb class device for this usb interface */ @@ -158,14 +195,13 @@ #endif ++temp; else temp = name; - intf->class_dev = class_device_create(usb_class, NULL, - MKDEV(USB_MAJOR, minor), - &intf->dev, "%s", temp); - if (IS_ERR(intf->class_dev)) { + intf->usb_dev = device_create(usb_class->class, &intf->dev, + MKDEV(USB_MAJOR, minor), "%s", temp); + if (IS_ERR(intf->usb_dev)) { spin_lock (&minor_lock); usb_minors[intf->minor] = NULL; spin_unlock (&minor_lock); - retval = PTR_ERR(intf->class_dev); + retval = PTR_ERR(intf->usb_dev); } exit: return retval; @@ -206,9 +242,10 @@ #endif spin_unlock (&minor_lock); snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); - class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor)); - intf->class_dev = NULL; + device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); + intf->usb_dev = NULL; intf->minor = -1; + destroy_usb_class(); } EXPORT_SYMBOL(usb_deregister_dev); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index e2e00ba..4bf914d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1826,24 +1826,16 @@ int usb_add_hcd(struct usb_hcd *hcd, /* enable irqs just before we start the controller */ if (hcd->driver->irq) { - char buf[8], *bufp = buf; - -#ifdef __sparc__ - bufp = __irq_itoa(irqnum); -#else - sprintf(buf, "%d", irqnum); -#endif - snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", hcd->driver->description, hcd->self.busnum); if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags, hcd->irq_descr, hcd)) != 0) { dev_err(hcd->self.controller, - "request interrupt %s failed\n", bufp); + "request interrupt %d failed\n", irqnum); goto err_request_irq; } hcd->irq = irqnum; - dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp, + dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum, (hcd->driver->flags & HCD_MEMORY) ? "io mem" : "io base", (unsigned long long)hcd->rsrc_start); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 90b8d43..e1731ff 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -432,15 +432,22 @@ static void hub_power_on(struct usb_hub { int port1; unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2; - u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); - - /* if hub supports power switching, enable power on each port */ - if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) { + u16 wHubCharacteristics = + le16_to_cpu(hub->descriptor->wHubCharacteristics); + + /* Enable power on each port. Some hubs have reserved values + * of LPSM (> 2) in their descriptors, even though they are + * USB 2.0 hubs. Some hubs do not implement port-power switching + * but only emulate it. In all cases, the ports won't work + * unless we send these messages to the hub. + */ + if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) dev_dbg(hub->intfdev, "enabling power on all ports\n"); - for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) - set_port_feature(hub->hdev, port1, - USB_PORT_FEAT_POWER); - } + else + dev_dbg(hub->intfdev, "trying to enable port power on " + "non-switchable hub\n"); + for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) + set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); /* Wait at least 100 msec for power to become stable */ msleep(max(pgood_delay, (unsigned) 100)); @@ -518,15 +525,16 @@ static int hub_port_disable(struct usb_h /* caller has locked the hub device */ -static void hub_pre_reset(struct usb_hub *hub, int disable_ports) +static void hub_pre_reset(struct usb_interface *intf) { + struct usb_hub *hub = usb_get_intfdata(intf); struct usb_device *hdev = hub->hdev; int port1; for (port1 = 1; port1 <= hdev->maxchild; ++port1) { if (hdev->children[port1 - 1]) { usb_disconnect(&hdev->children[port1 - 1]); - if (disable_ports) + if (hub->error == 0) hub_port_disable(hub, port1, 0); } } @@ -534,8 +542,10 @@ static void hub_pre_reset(struct usb_hub } /* caller has locked the hub device */ -static void hub_post_reset(struct usb_hub *hub) +static void hub_post_reset(struct usb_interface *intf) { + struct usb_hub *hub = usb_get_intfdata(intf); + hub_activate(hub); hub_power_on(hub); } @@ -795,15 +805,16 @@ static void hub_disconnect(struct usb_in struct usb_hub *hub = usb_get_intfdata (intf); struct usb_device *hdev; + /* Disconnect all children and quiesce the hub */ + hub->error = 0; + hub_pre_reset(intf); + usb_set_intfdata (intf, NULL); hdev = hub->hdev; if (hdev->speed == USB_SPEED_HIGH) highspeed_hubs--; - /* Disconnect all children and quiesce the hub */ - hub_pre_reset(hub, 1); - usb_free_urb(hub->urb); hub->urb = NULL; @@ -1169,6 +1180,7 @@ static int choose_configuration(struct u { int i; int num_configs; + int insufficient_power = 0; struct usb_host_config *c, *best; best = NULL; @@ -1221,8 +1233,10 @@ #endif */ /* Rule out configs that draw too much bus current */ - if (c->desc.bMaxPower * 2 > udev->bus_mA) + if (c->desc.bMaxPower * 2 > udev->bus_mA) { + insufficient_power++; continue; + } /* If the first config's first interface is COMM/2/0xff * (MSFT RNDIS), rule it out unless Linux has host-side @@ -1231,7 +1245,7 @@ #endif && desc->bInterfaceClass == USB_CLASS_COMM && desc->bInterfaceSubClass == 2 && desc->bInterfaceProtocol == 0xff) { -#ifndef CONFIG_USB_NET_RNDIS +#ifndef CONFIG_USB_NET_RNDIS_HOST continue; #else best = c; @@ -1256,6 +1270,11 @@ #endif best = c; } + if (insufficient_power > 0) + dev_info(&udev->dev, "rejected %d configuration%s " + "due to insufficient available bus power\n", + insufficient_power, plural(insufficient_power)); + if (best) { i = best->desc.bConfigurationValue; dev_info(&udev->dev, @@ -2732,7 +2751,8 @@ static void hub_events(void) /* If the hub has died, clean up after it */ if (hdev->state == USB_STATE_NOTATTACHED) { - hub_pre_reset(hub, 0); + hub->error = -ENODEV; + hub_pre_reset(intf); goto loop; } @@ -2744,7 +2764,7 @@ static void hub_events(void) dev_dbg (hub_dev, "resetting for error %d\n", hub->error); - ret = usb_reset_device(hdev); + ret = usb_reset_composite_device(hdev, intf); if (ret) { dev_dbg (hub_dev, "error resetting hub: %d\n", ret); @@ -2913,6 +2933,8 @@ static struct usb_driver hub_driver = { .disconnect = hub_disconnect, .suspend = hub_suspend, .resume = hub_resume, + .pre_reset = hub_pre_reset, + .post_reset = hub_post_reset, .ioctl = hub_ioctl, .id_table = hub_id_table, }; @@ -2992,9 +3014,9 @@ static int config_descriptors_changed(st * usb_reset_device - perform a USB port reset to reinitialize a device * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) * - * WARNING - don't reset any device unless drivers for all of its - * interfaces are expecting that reset! Maybe some driver->reset() - * method should eventually help ensure sufficient cooperation. + * WARNING - don't use this routine to reset a composite device + * (one with multiple interfaces owned by separate drivers)! + * Use usb_reset_composite_device() instead. * * Do a port reset, reassign the device's address, and establish its * former operating configuration. If the reset fails, or the device's @@ -3018,7 +3040,6 @@ int usb_reset_device(struct usb_device * struct usb_device *parent_hdev = udev->parent; struct usb_hub *parent_hub; struct usb_device_descriptor descriptor = udev->descriptor; - struct usb_hub *hub = NULL; int i, ret = 0; int port1 = udev->portnum; @@ -3036,14 +3057,6 @@ int usb_reset_device(struct usb_device * } parent_hub = hdev_to_hub(parent_hdev); - /* If we're resetting an active hub, take some special actions */ - if (udev->actconfig && udev->actconfig->desc.bNumInterfaces > 0 && - udev->actconfig->interface[0]->dev.driver == - &hub_driver.driver && - (hub = hdev_to_hub(udev)) != NULL) { - hub_pre_reset(hub, 0); - } - set_bit(port1, parent_hub->busy_bits); for (i = 0; i < SET_CONFIG_TRIES; ++i) { @@ -3102,11 +3115,87 @@ int usb_reset_device(struct usb_device * } done: - if (hub) - hub_post_reset(hub); return 0; re_enumerate: hub_port_logical_disconnect(parent_hub, port1); return -ENODEV; } + +/** + * usb_reset_composite_device - warn interface drivers and perform a USB port reset + * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) + * @iface: interface bound to the driver making the request (optional) + * + * Warns all drivers bound to registered interfaces (using their pre_reset + * method), performs the port reset, and then lets the drivers know that + * the reset is over (using their post_reset method). + * + * Return value is the same as for usb_reset_device(). + * + * The caller must own the device lock. For example, it's safe to use + * this from a driver probe() routine after downloading new firmware. + * For calls that might not occur during probe(), drivers should lock + * the device using usb_lock_device_for_reset(). + * + * The interface locks are acquired during the pre_reset stage and released + * during the post_reset stage. However if iface is not NULL and is + * currently being probed, we assume that the caller already owns its + * lock. + */ +int usb_reset_composite_device(struct usb_device *udev, + struct usb_interface *iface) +{ + int ret; + struct usb_host_config *config = udev->actconfig; + + if (udev->state == USB_STATE_NOTATTACHED || + udev->state == USB_STATE_SUSPENDED) { + dev_dbg(&udev->dev, "device reset not allowed in state %d\n", + udev->state); + return -EINVAL; + } + + if (iface && iface->condition != USB_INTERFACE_BINDING) + iface = NULL; + + if (config) { + int i; + struct usb_interface *cintf; + struct usb_driver *drv; + + for (i = 0; i < config->desc.bNumInterfaces; ++i) { + cintf = config->interface[i]; + if (cintf != iface) + down(&cintf->dev.sem); + if (device_is_registered(&cintf->dev) && + cintf->dev.driver) { + drv = to_usb_driver(cintf->dev.driver); + if (drv->pre_reset) + (drv->pre_reset)(cintf); + } + } + } + + ret = usb_reset_device(udev); + + if (config) { + int i; + struct usb_interface *cintf; + struct usb_driver *drv; + + for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) { + cintf = config->interface[i]; + if (device_is_registered(&cintf->dev) && + cintf->dev.driver) { + drv = to_usb_driver(cintf->dev.driver); + if (drv->post_reset) + (drv->post_reset)(cintf); + } + if (cintf != iface) + up(&cintf->dev.sem); + } + } + + return ret; +} diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 3cf945c..bfc9b28 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -543,10 +543,10 @@ static void fs_remove_file (struct dentr /* --------------------------------------------------------------------- */ -static struct super_block *usb_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int usb_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_single(fs_type, flags, data, usbfs_fill_super); + return get_sb_single(fs_type, flags, data, usbfs_fill_super, mnt); } static struct file_system_type usb_fs_type = { @@ -569,7 +569,7 @@ static int create_special_files (void) ignore_mount = 1; /* create the devices special file */ - retval = simple_pin_fs("usbfs", &usbfs_mount, &usbfs_mount_count); + retval = simple_pin_fs(&usb_fs_type, &usbfs_mount, &usbfs_mount_count); if (retval) { err ("Unable to get usbfs mount"); goto exit; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 08fb20f..8569600 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -158,6 +158,37 @@ int usb_control_msg(struct usb_device *d /** + * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion + * @usb_dev: pointer to the usb device to send the message to + * @pipe: endpoint "pipe" to send the message to + * @data: pointer to the data to send + * @len: length in bytes of the data to send + * @actual_length: pointer to a location to put the actual length transferred in bytes + * @timeout: time in msecs to wait for the message to complete before + * timing out (if 0 the wait is forever) + * Context: !in_interrupt () + * + * This function sends a simple interrupt message to a specified endpoint and + * waits for the message to complete, or timeout. + * + * If successful, it returns 0, otherwise a negative error number. The number + * of actual bytes transferred will be stored in the actual_length paramater. + * + * Don't use this function from within an interrupt context, like a bottom half + * handler. If you need an asynchronous message, or need to send a message + * from within interrupt context, use usb_submit_urb() If a thread in your + * driver uses this call, make sure your disconnect() method can wait for it to + * complete. Since you don't have a handle on the URB used, you can't cancel + * the request. + */ +int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, + void *data, int len, int *actual_length, int timeout) +{ + return usb_bulk_msg(usb_dev, pipe, data, len, actual_length, timeout); +} +EXPORT_SYMBOL_GPL(usb_interrupt_msg); + +/** * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion * @usb_dev: pointer to the usb device to send the message to * @pipe: endpoint "pipe" to send the message to @@ -1380,15 +1411,7 @@ free_interfaces: return ret; } } - } - - /* if it's already configured, clear out old state first. - * getting rid of old interfaces means unbinding their drivers. - */ - if (dev->state != USB_STATE_ADDRESS) - usb_disable_device (dev, 1); // Skip ep0 - if (cp) { i = dev->bus_mA - cp->desc.bMaxPower * 2; if (i < 0) dev_warn(&dev->dev, "new config #%d exceeds power " @@ -1396,84 +1419,91 @@ free_interfaces: configuration, -i); } + /* if it's already configured, clear out old state first. + * getting rid of old interfaces means unbinding their drivers. + */ + if (dev->state != USB_STATE_ADDRESS) + usb_disable_device (dev, 1); // Skip ep0 + if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, - NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) - goto free_interfaces; + NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) { + + /* All the old state is gone, so what else can we do? + * The device is probably useless now anyway. + */ + cp = NULL; + } dev->actconfig = cp; - if (!cp) + if (!cp) { usb_set_device_state(dev, USB_STATE_ADDRESS); - else { - usb_set_device_state(dev, USB_STATE_CONFIGURED); + goto free_interfaces; + } + usb_set_device_state(dev, USB_STATE_CONFIGURED); - /* Initialize the new interface structures and the - * hc/hcd/usbcore interface/endpoint state. - */ - for (i = 0; i < nintf; ++i) { - struct usb_interface_cache *intfc; - struct usb_interface *intf; - struct usb_host_interface *alt; - - cp->interface[i] = intf = new_interfaces[i]; - intfc = cp->intf_cache[i]; - intf->altsetting = intfc->altsetting; - intf->num_altsetting = intfc->num_altsetting; - kref_get(&intfc->ref); - - alt = usb_altnum_to_altsetting(intf, 0); - - /* No altsetting 0? We'll assume the first altsetting. - * We could use a GetInterface call, but if a device is - * so non-compliant that it doesn't have altsetting 0 - * then I wouldn't trust its reply anyway. - */ - if (!alt) - alt = &intf->altsetting[0]; - - intf->cur_altsetting = alt; - usb_enable_interface(dev, intf); - intf->dev.parent = &dev->dev; - intf->dev.driver = NULL; - intf->dev.bus = &usb_bus_type; - intf->dev.dma_mask = dev->dev.dma_mask; - intf->dev.release = release_interface; - device_initialize (&intf->dev); - mark_quiesced(intf); - sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d", - dev->bus->busnum, dev->devpath, - configuration, - alt->desc.bInterfaceNumber); - } - kfree(new_interfaces); + /* Initialize the new interface structures and the + * hc/hcd/usbcore interface/endpoint state. + */ + for (i = 0; i < nintf; ++i) { + struct usb_interface_cache *intfc; + struct usb_interface *intf; + struct usb_host_interface *alt; + + cp->interface[i] = intf = new_interfaces[i]; + intfc = cp->intf_cache[i]; + intf->altsetting = intfc->altsetting; + intf->num_altsetting = intfc->num_altsetting; + kref_get(&intfc->ref); - if (cp->string == NULL) - cp->string = usb_cache_string(dev, - cp->desc.iConfiguration); + alt = usb_altnum_to_altsetting(intf, 0); - /* Now that all the interfaces are set up, register them - * to trigger binding of drivers to interfaces. probe() - * routines may install different altsettings and may - * claim() any interfaces not yet bound. Many class drivers - * need that: CDC, audio, video, etc. + /* No altsetting 0? We'll assume the first altsetting. + * We could use a GetInterface call, but if a device is + * so non-compliant that it doesn't have altsetting 0 + * then I wouldn't trust its reply anyway. */ - for (i = 0; i < nintf; ++i) { - struct usb_interface *intf = cp->interface[i]; - - dev_dbg (&dev->dev, - "adding %s (config #%d, interface %d)\n", - intf->dev.bus_id, configuration, - intf->cur_altsetting->desc.bInterfaceNumber); - ret = device_add (&intf->dev); - if (ret != 0) { - dev_err(&dev->dev, - "device_add(%s) --> %d\n", - intf->dev.bus_id, - ret); - continue; - } - usb_create_sysfs_intf_files (intf); + if (!alt) + alt = &intf->altsetting[0]; + + intf->cur_altsetting = alt; + usb_enable_interface(dev, intf); + intf->dev.parent = &dev->dev; + intf->dev.driver = NULL; + intf->dev.bus = &usb_bus_type; + intf->dev.dma_mask = dev->dev.dma_mask; + intf->dev.release = release_interface; + device_initialize (&intf->dev); + mark_quiesced(intf); + sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d", + dev->bus->busnum, dev->devpath, + configuration, alt->desc.bInterfaceNumber); + } + kfree(new_interfaces); + + if (cp->string == NULL) + cp->string = usb_cache_string(dev, cp->desc.iConfiguration); + + /* Now that all the interfaces are set up, register them + * to trigger binding of drivers to interfaces. probe() + * routines may install different altsettings and may + * claim() any interfaces not yet bound. Many class drivers + * need that: CDC, audio, video, etc. + */ + for (i = 0; i < nintf; ++i) { + struct usb_interface *intf = cp->interface[i]; + + dev_dbg (&dev->dev, + "adding %s (config #%d, interface %d)\n", + intf->dev.bus_id, configuration, + intf->cur_altsetting->desc.bInterfaceNumber); + ret = device_add (&intf->dev); + if (ret != 0) { + dev_err(&dev->dev, "device_add(%s) --> %d\n", + intf->dev.bus_id, ret); + continue; } + usb_create_sysfs_intf_files (intf); } return 0; diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 71d8813..3f49bf5 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -15,203 +15,6 @@ #include #include #include "usb.h" -/* endpoint stuff */ -struct ep_object { - struct usb_endpoint_descriptor *desc; - struct usb_device *udev; - struct kobject kobj; -}; -#define to_ep_object(_kobj) \ - container_of(_kobj, struct ep_object, kobj) - -struct ep_attribute { - struct attribute attr; - ssize_t (*show)(struct usb_device *, - struct usb_endpoint_descriptor *, char *); -}; -#define to_ep_attribute(_attr) \ - container_of(_attr, struct ep_attribute, attr) - -#define EP_ATTR(_name) \ -struct ep_attribute ep_##_name = { \ - .attr = {.name = #_name, .owner = THIS_MODULE, \ - .mode = S_IRUGO}, \ - .show = show_ep_##_name} - -#define usb_ep_attr(field, format_string) \ -static ssize_t show_ep_##field(struct usb_device *udev, \ - struct usb_endpoint_descriptor *desc, \ - char *buf) \ -{ \ - return sprintf(buf, format_string, desc->field); \ -} \ -static EP_ATTR(field); - -usb_ep_attr(bLength, "%02x\n") -usb_ep_attr(bEndpointAddress, "%02x\n") -usb_ep_attr(bmAttributes, "%02x\n") -usb_ep_attr(bInterval, "%02x\n") - -static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) -{ - return sprintf(buf, "%04x\n", - le16_to_cpu(desc->wMaxPacketSize) & 0x07ff); -} -static EP_ATTR(wMaxPacketSize); - -static ssize_t show_ep_type(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) -{ - char *type = "unknown"; - - switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_CONTROL: - type = "Control"; - break; - case USB_ENDPOINT_XFER_ISOC: - type = "Isoc"; - break; - case USB_ENDPOINT_XFER_BULK: - type = "Bulk"; - break; - case USB_ENDPOINT_XFER_INT: - type = "Interrupt"; - break; - } - return sprintf(buf, "%s\n", type); -} -static EP_ATTR(type); - -static ssize_t show_ep_interval(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) -{ - char unit; - unsigned interval = 0; - unsigned in; - - in = (desc->bEndpointAddress & USB_DIR_IN); - - switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_CONTROL: - if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ - interval = desc->bInterval; - break; - case USB_ENDPOINT_XFER_ISOC: - interval = 1 << (desc->bInterval - 1); - break; - case USB_ENDPOINT_XFER_BULK: - if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ - interval = desc->bInterval; - break; - case USB_ENDPOINT_XFER_INT: - if (udev->speed == USB_SPEED_HIGH) - interval = 1 << (desc->bInterval - 1); - else - interval = desc->bInterval; - break; - } - interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000; - if (interval % 1000) - unit = 'u'; - else { - unit = 'm'; - interval /= 1000; - } - - return sprintf(buf, "%d%cs\n", interval, unit); -} -static EP_ATTR(interval); - -static ssize_t show_ep_direction(struct usb_device *udev, - struct usb_endpoint_descriptor *desc, char *buf) -{ - char *direction; - - if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL) - direction = "both"; - else if (desc->bEndpointAddress & USB_DIR_IN) - direction = "in"; - else - direction = "out"; - return sprintf(buf, "%s\n", direction); -} -static EP_ATTR(direction); - -static struct attribute *ep_attrs[] = { - &ep_bLength.attr, - &ep_bEndpointAddress.attr, - &ep_bmAttributes.attr, - &ep_bInterval.attr, - &ep_wMaxPacketSize.attr, - &ep_type.attr, - &ep_interval.attr, - &ep_direction.attr, - NULL, -}; - -static void ep_object_release(struct kobject *kobj) -{ - kfree(to_ep_object(kobj)); -} - -static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct ep_object *ep_obj = to_ep_object(kobj); - struct ep_attribute *ep_attr = to_ep_attribute(attr); - - return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf); -} - -static struct sysfs_ops ep_object_sysfs_ops = { - .show = ep_object_show, -}; - -static struct kobj_type ep_object_ktype = { - .release = ep_object_release, - .sysfs_ops = &ep_object_sysfs_ops, - .default_attrs = ep_attrs, -}; - -static void usb_create_ep_files(struct kobject *parent, - struct usb_host_endpoint *endpoint, - struct usb_device *udev) -{ - struct ep_object *ep_obj; - struct kobject *kobj; - - ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL); - if (!ep_obj) - return; - - ep_obj->desc = &endpoint->desc; - ep_obj->udev = udev; - - kobj = &ep_obj->kobj; - kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress); - kobj->parent = parent; - kobj->ktype = &ep_object_ktype; - - /* Don't use kobject_register, because it generates a hotplug event */ - kobject_init(kobj); - if (kobject_add(kobj) == 0) - endpoint->kobj = kobj; - else - kobject_put(kobj); -} - -static void usb_remove_ep_files(struct usb_host_endpoint *endpoint) -{ - - if (endpoint->kobj) { - kobject_del(endpoint->kobj); - kobject_put(endpoint->kobj); - endpoint->kobj = NULL; - } -} - /* Active configuration fields */ #define usb_actconfig_show(field, multiplier, format_string) \ static ssize_t show_##field (struct device *dev, \ @@ -420,7 +223,7 @@ void usb_create_sysfs_dev_files (struct if (udev->serial) device_create_file (dev, &dev_attr_serial); device_create_file (dev, &dev_attr_configuration); - usb_create_ep_files(&dev->kobj, &udev->ep0, udev); + usb_create_ep_files(dev, &udev->ep0, udev); } void usb_remove_sysfs_dev_files (struct usb_device *udev) @@ -524,7 +327,7 @@ static inline void usb_create_intf_ep_fi iface_desc = intf->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) - usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i], + usb_create_ep_files(&intf->dev, &iface_desc->endpoint[i], udev); } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b7fdc1c..fb488c8 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -991,6 +991,8 @@ void usb_buffer_unmap_sg (struct usb_dev static int verify_suspended(struct device *dev, void *unused) { + if (dev->driver == NULL) + return 0; return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0; } @@ -1207,6 +1209,7 @@ EXPORT_SYMBOL(usb_ifnum_to_if); EXPORT_SYMBOL(usb_altnum_to_altsetting); EXPORT_SYMBOL(usb_reset_device); +EXPORT_SYMBOL(usb_reset_composite_device); EXPORT_SYMBOL(__usb_get_extra_descriptor); diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 4647e1e..7a650c7 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -4,6 +4,9 @@ extern void usb_create_sysfs_dev_files ( extern void usb_remove_sysfs_dev_files (struct usb_device *dev); extern void usb_create_sysfs_intf_files (struct usb_interface *intf); extern void usb_remove_sysfs_intf_files (struct usb_interface *intf); +extern void usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint, + struct usb_device *udev); +extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint); extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr); extern void usb_disable_interface (struct usb_device *dev, diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 9c4422a..078daa0 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -49,7 +49,7 @@ #include #include #include -#include +#include #include #include @@ -101,9 +101,9 @@ #endif /* CDC and RNDIS support the same host-chosen outgoing packet filters. */ #define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ - |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ - |USB_CDC_PACKET_TYPE_PROMISCUOUS \ - |USB_CDC_PACKET_TYPE_DIRECTED) + |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ + |USB_CDC_PACKET_TYPE_PROMISCUOUS \ + |USB_CDC_PACKET_TYPE_DIRECTED) /*-------------------------------------------------------------------------*/ @@ -318,7 +318,7 @@ #define cdc_active(dev) ( is_cdc(dev) & #define DEFAULT_QLEN 2 /* double buffering by default */ /* peak bulk transfer bits-per-second */ -#define HS_BPS (13 * 512 * 8 * 1000 * 8) +#define HS_BPS (13 * 512 * 8 * 1000 * 8) #define FS_BPS (19 * 64 * 1 * 1000 * 8) #ifdef CONFIG_USB_GADGET_DUALSPEED @@ -466,7 +466,7 @@ eth_config = { }; #ifdef CONFIG_USB_ETH_RNDIS -static struct usb_config_descriptor +static struct usb_config_descriptor rndis_config = { .bLength = sizeof rndis_config, .bDescriptorType = USB_DT_CONFIG, @@ -511,7 +511,7 @@ static const struct usb_interface_descri rndis_control_intf = { .bLength = sizeof rndis_control_intf, .bDescriptorType = USB_DT_INTERFACE, - + .bInterfaceNumber = 0, .bNumEndpoints = 1, .bInterfaceClass = USB_CLASS_COMM, @@ -545,20 +545,20 @@ #endif /* CDC || RNDIS */ #ifdef CONFIG_USB_ETH_RNDIS static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = { - .bLength = sizeof call_mgmt_descriptor, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, + .bLength = sizeof call_mgmt_descriptor, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, - .bmCapabilities = 0x00, - .bDataInterface = 0x01, + .bmCapabilities = 0x00, + .bDataInterface = 0x01, }; static const struct usb_cdc_acm_descriptor acm_descriptor = { - .bLength = sizeof acm_descriptor, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_ACM_TYPE, + .bLength = sizeof acm_descriptor, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_ACM_TYPE, - .bmCapabilities = 0x00, + .bmCapabilities = 0x00, }; #endif @@ -595,7 +595,7 @@ #if defined(DEV_CONFIG_CDC) || defined(C * RNDIS requires the status endpoint, since it uses that encapsulation * mechanism for its funky RPC scheme. */ - + #define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ #define STATUS_BYTECOUNT 16 /* 8 byte header + data */ @@ -978,7 +978,7 @@ #if defined(DEV_CONFIG_CDC) || defined(C result = usb_ep_enable (dev->status_ep, dev->status); if (result != 0) { - DEBUG (dev, "enable %s --> %d\n", + DEBUG (dev, "enable %s --> %d\n", dev->status_ep->name, result); goto done; } @@ -1002,15 +1002,15 @@ #endif if (!cdc_active(dev)) { result = usb_ep_enable (dev->in_ep, dev->in); if (result != 0) { - DEBUG(dev, "enable %s --> %d\n", + DEBUG(dev, "enable %s --> %d\n", dev->in_ep->name, result); goto done; } result = usb_ep_enable (dev->out_ep, dev->out); if (result != 0) { - DEBUG (dev, "enable %s --> %d\n", - dev->in_ep->name, result); + DEBUG (dev, "enable %s --> %d\n", + dev->out_ep->name, result); goto done; } } @@ -1144,7 +1144,7 @@ #endif #ifdef CONFIG_USB_GADGET_DUALSPEED case USB_SPEED_HIGH: speed = "high"; break; #endif - default: speed = "?"; break; + default: speed = "?"; break; } dev->config = number; @@ -1206,7 +1206,7 @@ static void issue_start_status (struct e struct usb_request *req = dev->stat_req; struct usb_cdc_notification *event; int value; - + DEBUG (dev, "%s, flush old status first\n", __FUNCTION__); /* flush old status @@ -1268,7 +1268,7 @@ static void rndis_command_complete (stru { struct eth_dev *dev = ep->driver_data; int status; - + /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ spin_lock(&dev->lock); status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf); @@ -1472,7 +1472,7 @@ #ifdef DEV_CONFIG_CDC #endif /* DEV_CONFIG_CDC */ -#ifdef CONFIG_USB_ETH_RNDIS +#ifdef CONFIG_USB_ETH_RNDIS /* RNDIS uses the CDC command encapsulation mechanism to implement * an RPC scheme, with much getting/setting of attributes by OID. */ @@ -1489,7 +1489,7 @@ #ifdef CONFIG_USB_ETH_RNDIS req->complete = rndis_command_complete; /* later, rndis_control_ack () sends a notification */ break; - + case USB_CDC_GET_ENCAPSULATED_RESPONSE: if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE) == ctrl->bRequestType @@ -1641,7 +1641,7 @@ rx_submit (struct eth_dev *dev, struct u DEBUG (dev, "no rx skb\n"); goto enomem; } - + /* Some platforms perform better when IP packets are aligned, * but on at least one, checksumming fails otherwise. Note: * RNDIS headers involve variable numbers of LE32 values. @@ -1720,7 +1720,7 @@ quiesce: case -EOVERFLOW: dev->stats.rx_over_errors++; // FALLTHROUGH - + default: dev->stats.rx_errors++; DEBUG (dev, "rx status %d\n", status); @@ -1915,7 +1915,7 @@ static int eth_start_xmit (struct sk_buf sizeof (struct rndis_packet_msg_type)); if (!skb_rndis) goto drop; - + dev_kfree_skb_any (skb); skb = skb_rndis; rndis_add_hdr (skb); @@ -2001,7 +2001,7 @@ static int rndis_control_ack (struct net struct eth_dev *dev = netdev_priv(net); u32 length; struct usb_request *resp = dev->stat_req; - + /* in case RNDIS calls this after disconnect */ if (!dev->status) { DEBUG (dev, "status ENODEV\n"); @@ -2021,16 +2021,16 @@ static int rndis_control_ack (struct net resp->length = 8; resp->complete = rndis_control_ack_complete; resp->context = dev; - + *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1); *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); - + length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC); if (length < 0) { resp->status = 0; rndis_control_ack_complete (dev->status_ep, resp); } - + return 0; } @@ -2047,7 +2047,7 @@ static void eth_start (struct eth_dev *d /* fill the rx queue */ rx_fill (dev, gfp_flags); - /* and open the tx floodgates */ + /* and open the tx floodgates */ atomic_set (&dev->tx_qlen, 0); netif_wake_queue (dev->net); if (rndis_active(dev)) { @@ -2076,7 +2076,7 @@ static int eth_stop (struct net_device * netif_stop_queue (net); DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", - dev->stats.rx_packets, dev->stats.tx_packets, + dev->stats.rx_packets, dev->stats.tx_packets, dev->stats.rx_errors, dev->stats.tx_errors ); @@ -2095,7 +2095,7 @@ static int eth_stop (struct net_device * usb_ep_enable (dev->status_ep, dev->status); } } - + if (rndis_active(dev)) { rndis_set_param_medium (dev->rndis_config, NDIS_MEDIUM_802_3, 0); @@ -2301,7 +2301,7 @@ autoconf_fail: return -ENODEV; } in_ep->driver_data = in_ep; /* claim */ - + out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc); if (!out_ep) goto autoconf_fail; @@ -2374,8 +2374,8 @@ #ifdef CONFIG_USB_ETH_RNDIS #endif } - net = alloc_etherdev (sizeof *dev); - if (!net) + net = alloc_etherdev (sizeof *dev); + if (!net) return status; dev = netdev_priv(net); spin_lock_init (&dev->lock); @@ -2454,7 +2454,7 @@ #endif dev->gadget = gadget; set_gadget_data (gadget, dev); gadget->ep0->driver_data = dev; - + /* two kinds of host-initiated state changes: * - iff DATA transfer is active, carrier is "on" * - tx queueing enabled if open *and* carrier is "on" @@ -2462,8 +2462,8 @@ #endif netif_stop_queue (dev->net); netif_carrier_off (dev->net); - SET_NETDEV_DEV (dev->net, &gadget->dev); - status = register_netdev (dev->net); + SET_NETDEV_DEV (dev->net, &gadget->dev); + status = register_netdev (dev->net); if (status < 0) goto fail1; @@ -2488,7 +2488,7 @@ #endif u32 vendorID = 0; /* FIXME RNDIS vendor id == "vendor NIC code" == ? */ - + dev->rndis_config = rndis_register (rndis_control_ack); if (dev->rndis_config < 0) { fail0: @@ -2496,7 +2496,7 @@ fail0: status = -ENODEV; goto fail; } - + /* these set up a lot of the OIDs that RNDIS needs */ rndis_set_host_mac (dev->rndis_config, dev->host_mac); if (rndis_set_param_dev (dev->rndis_config, dev->net, @@ -2556,7 +2556,7 @@ static struct usb_gadget_driver eth_driv .suspend = eth_suspend, .resume = eth_resume, - .driver = { + .driver = { .name = (char *) shortname, .owner = THIS_MODULE, }, diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 6f88747..a43dc90 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -1906,7 +1906,6 @@ static int fsync_sub(struct lun *curlun) inode = filp->f_dentry->d_inode; mutex_lock(&inode->i_mutex); - current->flags |= PF_SYNCWRITE; rc = filemap_fdatawrite(inode->i_mapping); err = filp->f_op->fsync(filp, filp->f_dentry, 1); if (!rc) @@ -1914,7 +1913,6 @@ static int fsync_sub(struct lun *curlun) err = filemap_fdatawait(inode->i_mapping); if (!rc) rc = err; - current->flags &= ~PF_SYNCWRITE; mutex_unlock(&inode->i_mutex); VLDBG(curlun, "fdatasync -> %d\n", rc); return rc; diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 66b81bb..5378c17 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1850,7 +1850,6 @@ static int goku_probe(struct pci_dev *pd unsigned long resource, len; void __iomem *base = NULL; int retval; - char buf [8], *bufp; /* if you want to support more than one controller in a system, * usb_gadget_driver_{register,unregister}() must change. @@ -1913,20 +1912,14 @@ static int goku_probe(struct pci_dev *pd pci_set_drvdata(pdev, dev); INFO(dev, "%s\n", driver_desc); INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr()); -#ifndef __sparc__ - scnprintf(buf, sizeof buf, "%d", pdev->irq); - bufp = buf; -#else - bufp = __irq_itoa(pdev->irq); -#endif - INFO(dev, "irq %s, pci mem %p\n", bufp, base); + INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base); /* init to known state, then setup irqs */ udc_reset(dev); udc_reinit (dev); if (request_irq(pdev->irq, goku_irq, SA_SHIRQ/*|SA_SAMPLE_RANDOM*/, driver_name, dev) != 0) { - DBG(dev, "request interrupt %s failed\n", bufp); + DBG(dev, "request interrupt %d failed\n", pdev->irq); retval = -EBUSY; goto done; } diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 0eb010a..3bdc5e3 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -528,7 +528,7 @@ struct kiocb_priv { struct usb_request *req; struct ep_data *epdata; void *buf; - char __user *ubuf; + char __user *ubuf; /* NULL for writes */ unsigned actual; }; @@ -566,7 +566,6 @@ static ssize_t ep_aio_read_retry(struct status = priv->actual; kfree(priv->buf); kfree(priv); - aio_put_req(iocb); return status; } @@ -580,8 +579,8 @@ static void ep_aio_complete(struct usb_e spin_lock(&epdata->dev->lock); priv->req = NULL; priv->epdata = NULL; - if (NULL == iocb->ki_retry - || unlikely(0 == req->actual) + if (priv->ubuf == NULL + || unlikely(req->actual == 0) || unlikely(kiocbIsCancelled(iocb))) { kfree(req->buf); kfree(priv); @@ -618,7 +617,7 @@ ep_aio_rwtail( char __user *ubuf ) { - struct kiocb_priv *priv = (void *) &iocb->private; + struct kiocb_priv *priv; struct usb_request *req; ssize_t value; @@ -670,7 +669,7 @@ fail: kfree(priv); put_ep(epdata); } else - value = -EIOCBQUEUED; + value = (ubuf ? -EIOCBRETRY : -EIOCBQUEUED); return value; } @@ -1039,7 +1038,7 @@ scan: /* ep0 can't deliver events when STATE_SETUP */ for (i = 0; i < n; i++) { if (dev->event [i].type == GADGETFS_SETUP) { - len = n = i + 1; + len = i + 1; len *= sizeof (struct usb_gadgetfs_event); n = 0; break; @@ -1587,13 +1586,13 @@ gadgetfs_create_file (struct super_block static int activate_ep_files (struct dev_data *dev) { struct usb_ep *ep; + struct ep_data *data; gadget_for_each_ep (ep, dev->gadget) { - struct ep_data *data; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) - goto enomem; + goto enomem0; data->state = STATE_EP_DISABLED; init_MUTEX (&data->lock); init_waitqueue_head (&data->wait); @@ -1608,21 +1607,23 @@ static int activate_ep_files (struct dev data->req = usb_ep_alloc_request (ep, GFP_KERNEL); if (!data->req) - goto enomem; + goto enomem1; data->inode = gadgetfs_create_file (dev->sb, data->name, data, &ep_config_operations, &data->dentry); - if (!data->inode) { - usb_ep_free_request(ep, data->req); - kfree (data); - goto enomem; - } + if (!data->inode) + goto enomem2; list_add_tail (&data->epfiles, &dev->epfiles); } return 0; -enomem: +enomem2: + usb_ep_free_request (ep, data->req); +enomem1: + put_dev (dev); + kfree (data); +enomem0: DBG (dev, "%s enomem\n", __FUNCTION__); destroy_ep_files (dev); return -ENOMEM; @@ -1793,7 +1794,7 @@ static struct usb_gadget_driver probe_dr * * After initialization, the device stays active for as long as that * $CHIP file is open. Events may then be read from that descriptor, - * such configuration notifications. More complex drivers will handle + * such as configuration notifications. More complex drivers will handle * some control requests in user space. */ @@ -2033,12 +2034,10 @@ gadgetfs_fill_super (struct super_block NULL, &simple_dir_operations, S_IFDIR | S_IRUGO | S_IXUGO); if (!inode) - return -ENOMEM; + goto enomem0; inode->i_op = &simple_dir_inode_operations; - if (!(d = d_alloc_root (inode))) { - iput (inode); - return -ENOMEM; - } + if (!(d = d_alloc_root (inode))) + goto enomem1; sb->s_root = d; /* the ep0 file is named after the controller we expect; @@ -2046,29 +2045,36 @@ gadgetfs_fill_super (struct super_block */ dev = dev_new (); if (!dev) - return -ENOMEM; + goto enomem2; dev->sb = sb; - if (!(inode = gadgetfs_create_file (sb, CHIP, + if (!gadgetfs_create_file (sb, CHIP, dev, &dev_init_operations, - &dev->dentry))) { - put_dev(dev); - return -ENOMEM; - } + &dev->dentry)) + goto enomem3; /* other endpoint files are available after hardware setup, * from binding to a controller. */ the_device = dev; return 0; + +enomem3: + put_dev (dev); +enomem2: + dput (d); +enomem1: + iput (inode); +enomem0: + return -ENOMEM; } /* "mount -t gadgetfs path /dev/gadget" ends up here */ -static struct super_block * +static int gadgetfs_get_sb (struct file_system_type *t, int flags, - const char *path, void *opts) + const char *path, void *opts, struct vfsmount *mnt) { - return get_sb_single (t, flags, opts, gadgetfs_fill_super); + return get_sb_single (t, flags, opts, gadgetfs_fill_super, mnt); } static void diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 0b92934..1facdea 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2822,7 +2822,6 @@ static int net2280_probe (struct pci_dev unsigned long resource, len; void __iomem *base = NULL; int retval, i; - char buf [8], *bufp; /* if you want to support more than one controller in a system, * usb_gadget_driver_{register,unregister}() must change. @@ -2896,15 +2895,10 @@ static int net2280_probe (struct pci_dev retval = -ENODEV; goto done; } -#ifndef __sparc__ - scnprintf (buf, sizeof buf, "%d", pdev->irq); - bufp = buf; -#else - bufp = __irq_itoa(pdev->irq); -#endif + if (request_irq (pdev->irq, net2280_irq, SA_SHIRQ, driver_name, dev) != 0) { - ERROR (dev, "request interrupt %s failed\n", bufp); + ERROR (dev, "request interrupt %d failed\n", pdev->irq); retval = -EBUSY; goto done; } @@ -2953,8 +2947,8 @@ #endif /* done */ INFO (dev, "%s\n", driver_desc); - INFO (dev, "irq %s, pci mem %p, chip rev %04x\n", - bufp, base, dev->chiprev); + INFO (dev, "irq %d, pci mem %p, chip rev %04x\n", + pdev->irq, base, dev->chiprev); INFO (dev, "version: " DRIVER_VERSION "; dma %s\n", use_dma ? (use_dma_chaining ? "chaining" : "enabled") @@ -2972,6 +2966,22 @@ done: return retval; } +/* make sure the board is quiescent; otherwise it will continue + * generating IRQs across the upcoming reboot. + */ + +static void net2280_shutdown (struct pci_dev *pdev) +{ + struct net2280 *dev = pci_get_drvdata (pdev); + + /* disable IRQs */ + writel (0, &dev->regs->pciirqenb0); + writel (0, &dev->regs->pciirqenb1); + + /* disable the pullup so the host will think we're gone */ + writel (0, &dev->usb->usbctl); +} + /*-------------------------------------------------------------------------*/ @@ -3001,6 +3011,7 @@ static struct pci_driver net2280_pci_dri .probe = net2280_probe, .remove = net2280_remove, + .shutdown = net2280_shutdown, /* FIXME add power management support */ }; diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 680f7fc..269ce7f 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -53,12 +53,14 @@ #include #include #include #include +#ifdef CONFIG_ARCH_PXA #include +#endif #include #include -#include +#include /* @@ -545,6 +547,7 @@ write_ep0_fifo (struct pxa2xx_ep *ep, st count = req->req.length; done (ep, req, 0); ep0_idle(ep->dev); +#ifndef CONFIG_ARCH_IXP4XX #if 1 /* This seems to get rid of lost status irqs in some cases: * host responds quickly, or next request involves config @@ -565,6 +568,7 @@ #if 1 } while (count); } #endif +#endif } else if (ep->dev->req_pending) ep0start(ep->dev, 0, "IN"); return is_short; @@ -1585,7 +1589,7 @@ int usb_gadget_register_driver(struct us int retval; if (!driver - || driver->speed != USB_SPEED_FULL + || driver->speed < USB_SPEED_FULL || !driver->bind || !driver->unbind || !driver->disconnect @@ -2427,6 +2431,7 @@ #define PXA210_B2 0x00000124 #define PXA210_B1 0x00000123 #define PXA210_B0 0x00000122 #define IXP425_A0 0x000001c1 +#define IXP465_AD 0x00000200 /* * probe - binds to the platform device @@ -2463,6 +2468,8 @@ #if defined(CONFIG_ARCH_PXA) break; #elif defined(CONFIG_ARCH_IXP4XX) case IXP425_A0: + case IXP465_AD: + dev->has_cfr = 1; out_dma = 0; break; #endif @@ -2575,10 +2582,12 @@ static int __exit pxa2xx_udc_remove(stru free_irq(IRQ_USB, dev); dev->got_irq = 0; } +#ifdef CONFIG_ARCH_LUBBOCK if (machine_is_lubbock()) { free_irq(LUBBOCK_USB_DISC_IRQ, dev); free_irq(LUBBOCK_USB_IRQ, dev); } +#endif platform_set_drvdata(pdev, NULL); the_controller = NULL; return 0; diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 6d6eaad..3ff6db7 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -1,23 +1,23 @@ -/* +/* * RNDIS MSG parser - * + * * Version: $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $ - * + * * Authors: Benedikt Spranger, Pengutronix - * Robert Schwebel, Pengutronix - * + * Robert Schwebel, Pengutronix + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License - * version 2, as published by the Free Software Foundation. - * + * version 2, as published by the Free Software Foundation. + * * This software was originally developed in conformance with * Microsoft's Remote NDIS Specification License Agreement. - * + * * 03/12/2004 Kai-Uwe Bloem * Fixed message length bug in init_response - * + * * 03/25/2004 Kai-Uwe Bloem - * Fixed rndis_rm_hdr length bug. + * Fixed rndis_rm_hdr length bug. * * Copyright (C) 2004 by David Brownell * updates to merge with Linux 2.6, better match RNDIS spec @@ -82,7 +82,7 @@ static rndis_resp_t *rndis_add_response /* supported OIDs */ -static const u32 oid_supported_list [] = +static const u32 oid_supported_list [] = { /* the general stuff */ OID_GEN_SUPPORTED_LIST, @@ -103,7 +103,7 @@ static const u32 oid_supported_list [] = #if 0 OID_GEN_RNDIS_CONFIG_PARAMETER, #endif - + /* the statistical stuff */ OID_GEN_XMIT_OK, OID_GEN_RCV_OK, @@ -127,14 +127,14 @@ #ifdef RNDIS_OPTIONAL_STATS OID_GEN_TRANSMIT_QUEUE_LENGTH, #endif /* RNDIS_OPTIONAL_STATS */ - /* mandatory 802.3 */ + /* mandatory 802.3 */ /* the general stuff */ OID_802_3_PERMANENT_ADDRESS, OID_802_3_CURRENT_ADDRESS, OID_802_3_MULTICAST_LIST, OID_802_3_MAC_OPTIONS, OID_802_3_MAXIMUM_LIST_SIZE, - + /* the statistical stuff */ OID_802_3_RCV_ERROR_ALIGNMENT, OID_802_3_XMIT_ONE_COLLISION, @@ -172,8 +172,8 @@ static int gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, rndis_resp_t *r) { - int retval = -ENOTSUPP; - u32 length = 4; /* usually */ + int retval = -ENOTSUPP; + u32 length = 4; /* usually */ __le32 *outbuf; int i, count; rndis_query_cmplt_type *resp; @@ -211,27 +211,27 @@ gen_ndis_query_resp (int configNr, u32 O outbuf[i] = cpu_to_le32 (oid_supported_list[i]); retval = 0; break; - + /* mandatory */ case OID_GEN_HARDWARE_STATUS: DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); - /* Bogus question! + /* Bogus question! * Hardware must be ready to receive high level protocols. - * BTW: + * BTW: * reddite ergo quae sunt Caesaris Caesari * et quae sunt Dei Deo! */ *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; - + /* mandatory */ case OID_GEN_MEDIA_SUPPORTED: DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); retval = 0; break; - + /* mandatory */ case OID_GEN_MEDIA_IN_USE: DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); @@ -239,7 +239,7 @@ gen_ndis_query_resp (int configNr, u32 O *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); retval = 0; break; - + /* mandatory */ case OID_GEN_MAXIMUM_FRAME_SIZE: DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); @@ -249,7 +249,7 @@ gen_ndis_query_resp (int configNr, u32 O retval = 0; } break; - + /* mandatory */ case OID_GEN_LINK_SPEED: if (rndis_debug > 1) @@ -272,7 +272,7 @@ gen_ndis_query_resp (int configNr, u32 O retval = 0; } break; - + /* mandatory */ case OID_GEN_RECEIVE_BLOCK_SIZE: DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); @@ -282,7 +282,7 @@ gen_ndis_query_resp (int configNr, u32 O retval = 0; } break; - + /* mandatory */ case OID_GEN_VENDOR_ID: DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); @@ -290,7 +290,7 @@ gen_ndis_query_resp (int configNr, u32 O rndis_per_dev_params [configNr].vendorID); retval = 0; break; - + /* mandatory */ case OID_GEN_VENDOR_DESCRIPTION: DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__); @@ -356,7 +356,7 @@ gen_ndis_query_resp (int configNr, u32 O DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 ( - rndis_per_dev_params [configNr].stats->tx_packets - + rndis_per_dev_params [configNr].stats->tx_packets - rndis_per_dev_params [configNr].stats->tx_errors - rndis_per_dev_params [configNr].stats->tx_dropped); retval = 0; @@ -369,13 +369,13 @@ gen_ndis_query_resp (int configNr, u32 O DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 ( - rndis_per_dev_params [configNr].stats->rx_packets - + rndis_per_dev_params [configNr].stats->rx_packets - rndis_per_dev_params [configNr].stats->rx_errors - rndis_per_dev_params [configNr].stats->rx_dropped); retval = 0; } break; - + /* mandatory */ case OID_GEN_XMIT_ERROR: if (rndis_debug > 1) @@ -386,7 +386,7 @@ gen_ndis_query_resp (int configNr, u32 O retval = 0; } break; - + /* mandatory */ case OID_GEN_RCV_ERROR: if (rndis_debug > 1) @@ -397,7 +397,7 @@ gen_ndis_query_resp (int configNr, u32 O retval = 0; } break; - + /* mandatory */ case OID_GEN_RCV_NO_BUFFER: DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); @@ -411,7 +411,7 @@ gen_ndis_query_resp (int configNr, u32 O #ifdef RNDIS_OPTIONAL_STATS case OID_GEN_DIRECTED_BYTES_XMIT: DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__); - /* + /* * Aunt Tilly's size of shoes * minus antarctica count of penguins * divided by weight of Alpha Centauri @@ -419,7 +419,7 @@ #ifdef RNDIS_OPTIONAL_STATS if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 ( (rndis_per_dev_params [configNr] - .stats->tx_packets - + .stats->tx_packets - rndis_per_dev_params [configNr] .stats->tx_errors - rndis_per_dev_params [configNr] @@ -428,14 +428,14 @@ #ifdef RNDIS_OPTIONAL_STATS retval = 0; } break; - + case OID_GEN_DIRECTED_FRAMES_XMIT: DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__); /* dito */ if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 ( (rndis_per_dev_params [configNr] - .stats->tx_packets - + .stats->tx_packets - rndis_per_dev_params [configNr] .stats->tx_errors - rndis_per_dev_params [configNr] @@ -444,7 +444,7 @@ #ifdef RNDIS_OPTIONAL_STATS retval = 0; } break; - + case OID_GEN_MULTICAST_BYTES_XMIT: DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -453,7 +453,7 @@ #ifdef RNDIS_OPTIONAL_STATS retval = 0; } break; - + case OID_GEN_MULTICAST_FRAMES_XMIT: DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -462,7 +462,7 @@ #ifdef RNDIS_OPTIONAL_STATS retval = 0; } break; - + case OID_GEN_BROADCAST_BYTES_XMIT: DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -471,7 +471,7 @@ #ifdef RNDIS_OPTIONAL_STATS retval = 0; } break; - + case OID_GEN_BROADCAST_FRAMES_XMIT: DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -480,19 +480,19 @@ #ifdef RNDIS_OPTIONAL_STATS retval = 0; } break; - + case OID_GEN_DIRECTED_BYTES_RCV: DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; - + case OID_GEN_DIRECTED_FRAMES_RCV: DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; - + case OID_GEN_MULTICAST_BYTES_RCV: DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -501,7 +501,7 @@ #ifdef RNDIS_OPTIONAL_STATS retval = 0; } break; - + case OID_GEN_MULTICAST_FRAMES_RCV: DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -510,7 +510,7 @@ #ifdef RNDIS_OPTIONAL_STATS retval = 0; } break; - + case OID_GEN_BROADCAST_BYTES_RCV: DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -519,7 +519,7 @@ #ifdef RNDIS_OPTIONAL_STATS retval = 0; } break; - + case OID_GEN_BROADCAST_FRAMES_RCV: DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -528,7 +528,7 @@ #ifdef RNDIS_OPTIONAL_STATS retval = 0; } break; - + case OID_GEN_RCV_CRC_ERROR: DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { @@ -537,7 +537,7 @@ #ifdef RNDIS_OPTIONAL_STATS retval = 0; } break; - + case OID_GEN_TRANSMIT_QUEUE_LENGTH: DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); @@ -558,7 +558,7 @@ #endif /* RNDIS_OPTIONAL_STATS */ retval = 0; } break; - + /* mandatory */ case OID_802_3_CURRENT_ADDRESS: DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); @@ -570,7 +570,7 @@ #endif /* RNDIS_OPTIONAL_STATS */ retval = 0; } break; - + /* mandatory */ case OID_802_3_MULTICAST_LIST: DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); @@ -578,7 +578,7 @@ #endif /* RNDIS_OPTIONAL_STATS */ *outbuf = __constant_cpu_to_le32 (0xE0000000); retval = 0; break; - + /* mandatory */ case OID_802_3_MAXIMUM_LIST_SIZE: DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); @@ -586,7 +586,7 @@ #endif /* RNDIS_OPTIONAL_STATS */ *outbuf = __constant_cpu_to_le32 (1); retval = 0; break; - + case OID_802_3_MAC_OPTIONS: DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__); break; @@ -602,56 +602,56 @@ #endif /* RNDIS_OPTIONAL_STATS */ retval = 0; } break; - + /* mandatory */ case OID_802_3_XMIT_ONE_COLLISION: DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; - + /* mandatory */ case OID_802_3_XMIT_MORE_COLLISIONS: DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; - + #ifdef RNDIS_OPTIONAL_STATS case OID_802_3_XMIT_DEFERRED: DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_XMIT_MAX_COLLISIONS: DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_RCV_OVERRUN: DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_XMIT_UNDERRUN: DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_XMIT_HEARTBEAT_FAILURE: DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_XMIT_TIMES_CRS_LOST: DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__); /* TODO */ break; - + case OID_802_3_XMIT_LATE_COLLISIONS: DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__); /* TODO */ - break; + break; #endif /* RNDIS_OPTIONAL_STATS */ #ifdef RNDIS_PM @@ -676,23 +676,23 @@ #ifdef RNDIS_PM #endif default: - printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", + printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", __FUNCTION__, OID); } if (retval < 0) length = 0; - + resp->InformationBufferLength = cpu_to_le32 (length); r->length = length + sizeof *resp; resp->MessageLength = cpu_to_le32 (r->length); return retval; } -static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, - rndis_resp_t *r) +static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, + rndis_resp_t *r) { rndis_set_cmplt_type *resp; - int i, retval = -ENOTSUPP; + int i, retval = -ENOTSUPP; struct rndis_params *params; if (!r) @@ -745,9 +745,9 @@ #endif netif_stop_queue (params->dev); } break; - + case OID_802_3_MULTICAST_LIST: - /* I think we can ignore this */ + /* I think we can ignore this */ DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); retval = 0; break; @@ -796,29 +796,29 @@ #endif #endif /* RNDIS_PM */ default: - printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", + printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", __FUNCTION__, OID, buf_len); } - + return retval; } -/* - * Response Functions +/* + * Response Functions */ static int rndis_init_response (int configNr, rndis_init_msg_type *buf) { - rndis_init_cmplt_type *resp; + rndis_init_cmplt_type *resp; rndis_resp_t *r; - + if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; - + r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); if (!r) return -ENOMEM; resp = (rndis_init_cmplt_type *) r->buf; - + resp->MessageType = __constant_cpu_to_le32 ( REMOTE_NDIS_INITIALIZE_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (52); @@ -837,11 +837,11 @@ static int rndis_init_response (int conf resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0); resp->AFListOffset = __constant_cpu_to_le32 (0); resp->AFListSize = __constant_cpu_to_le32 (0); - + if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); - + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); + return 0; } @@ -849,10 +849,10 @@ static int rndis_query_response (int con { rndis_query_cmplt_type *resp; rndis_resp_t *r; - + // DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID)); if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; - + /* * we need more memory: * gen_ndis_query_resp expects enough space for @@ -864,10 +864,10 @@ static int rndis_query_response (int con if (!r) return -ENOMEM; resp = (rndis_query_cmplt_type *) r->buf; - + resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ - + if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), le32_to_cpu(buf->InformationBufferOffset) + 8 + (u8 *) buf, @@ -881,10 +881,10 @@ static int rndis_query_response (int con resp->InformationBufferOffset = __constant_cpu_to_le32 (0); } else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); - + if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); return 0; } @@ -893,7 +893,7 @@ static int rndis_set_response (int confi u32 BufLength, BufOffset; rndis_set_cmplt_type *resp; rndis_resp_t *r; - + r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); if (!r) return -ENOMEM; @@ -906,26 +906,27 @@ #ifdef VERBOSE DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength); DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset); DEBUG("%s: InfoBuffer: ", __FUNCTION__); - + for (i = 0; i < BufLength; i++) { DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); } - + DEBUG ("\n"); #endif - + resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (16); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ - if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), - ((u8 *) buf) + 8 + BufOffset, BufLength, r)) - resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED); - else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); - + if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), + ((u8 *) buf) + 8 + BufOffset, BufLength, r)) + resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED); + else + resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); + if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); - + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); + return 0; } @@ -933,27 +934,27 @@ static int rndis_reset_response (int con { rndis_reset_cmplt_type *resp; rndis_resp_t *r; - + r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); if (!r) return -ENOMEM; resp = (rndis_reset_cmplt_type *) r->buf; - + resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (16); resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); /* resent information */ resp->AddressingReset = __constant_cpu_to_le32 (1); - + if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); return 0; } static int rndis_keepalive_response (int configNr, - rndis_keepalive_msg_type *buf) + rndis_keepalive_msg_type *buf) { rndis_keepalive_cmplt_type *resp; rndis_resp_t *r; @@ -964,48 +965,48 @@ static int rndis_keepalive_response (int if (!r) return -ENOMEM; resp = (rndis_keepalive_cmplt_type *) r->buf; - + resp->MessageType = __constant_cpu_to_le32 ( REMOTE_NDIS_KEEPALIVE_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (16); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); - + if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); - + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); + return 0; } -/* - * Device to Host Comunication +/* + * Device to Host Comunication */ static int rndis_indicate_status_msg (int configNr, u32 status) { - rndis_indicate_status_msg_type *resp; + rndis_indicate_status_msg_type *resp; rndis_resp_t *r; - + if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED) - return -ENOTSUPP; - - r = rndis_add_response (configNr, + return -ENOTSUPP; + + r = rndis_add_response (configNr, sizeof (rndis_indicate_status_msg_type)); if (!r) return -ENOMEM; resp = (rndis_indicate_status_msg_type *) r->buf; - + resp->MessageType = __constant_cpu_to_le32 ( REMOTE_NDIS_INDICATE_STATUS_MSG); resp->MessageLength = __constant_cpu_to_le32 (20); resp->Status = cpu_to_le32 (status); resp->StatusBufferLength = __constant_cpu_to_le32 (0); resp->StatusBufferOffset = __constant_cpu_to_le32 (0); - - if (rndis_per_dev_params [configNr].ack) - rndis_per_dev_params [configNr].ack ( - rndis_per_dev_params [configNr].dev); + + if (rndis_per_dev_params [configNr].ack) + rndis_per_dev_params [configNr].ack ( + rndis_per_dev_params [configNr].dev); return 0; } @@ -1013,7 +1014,7 @@ int rndis_signal_connect (int configNr) { rndis_per_dev_params [configNr].media_state = NDIS_MEDIA_STATE_CONNECTED; - return rndis_indicate_status_msg (configNr, + return rndis_indicate_status_msg (configNr, RNDIS_STATUS_MEDIA_CONNECT); } @@ -1045,26 +1046,26 @@ void rndis_set_host_mac (int configNr, c rndis_per_dev_params [configNr].host_mac = addr; } -/* - * Message Parser +/* + * Message Parser */ int rndis_msg_parser (u8 configNr, u8 *buf) { u32 MsgType, MsgLength; __le32 *tmp; struct rndis_params *params; - + if (!buf) return -ENOMEM; - - tmp = (__le32 *) buf; + + tmp = (__le32 *) buf; MsgType = le32_to_cpup(tmp++); MsgLength = le32_to_cpup(tmp++); - + if (configNr >= RNDIS_MAX_CONFIGS) return -ENOTSUPP; params = &rndis_per_dev_params [configNr]; - + /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for * rx/tx statistics and link status, in addition to KEEPALIVE traffic * and normal HC level polling to see if there's any IN traffic. @@ -1073,12 +1074,12 @@ int rndis_msg_parser (u8 configNr, u8 *b /* For USB: responses may take up to 10 seconds */ switch (MsgType) { case REMOTE_NDIS_INITIALIZE_MSG: - DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", + DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", __FUNCTION__ ); params->state = RNDIS_INITIALIZED; return rndis_init_response (configNr, - (rndis_init_msg_type *) buf); - + (rndis_init_msg_type *) buf); + case REMOTE_NDIS_HALT_MSG: DEBUG("%s: REMOTE_NDIS_HALT_MSG\n", __FUNCTION__ ); @@ -1088,37 +1089,37 @@ int rndis_msg_parser (u8 configNr, u8 *b netif_stop_queue (params->dev); } return 0; - + case REMOTE_NDIS_QUERY_MSG: - return rndis_query_response (configNr, - (rndis_query_msg_type *) buf); - + return rndis_query_response (configNr, + (rndis_query_msg_type *) buf); + case REMOTE_NDIS_SET_MSG: - return rndis_set_response (configNr, - (rndis_set_msg_type *) buf); - + return rndis_set_response (configNr, + (rndis_set_msg_type *) buf); + case REMOTE_NDIS_RESET_MSG: - DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", + DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", __FUNCTION__ ); return rndis_reset_response (configNr, - (rndis_reset_msg_type *) buf); + (rndis_reset_msg_type *) buf); case REMOTE_NDIS_KEEPALIVE_MSG: /* For USB: host does this every 5 seconds */ if (rndis_debug > 1) - DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", + DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", __FUNCTION__ ); return rndis_keepalive_response (configNr, - (rndis_keepalive_msg_type *) + (rndis_keepalive_msg_type *) buf); - - default: + + default: /* At least Windows XP emits some undefined RNDIS messages. * In one case those messages seemed to relate to the host * suspending itself. */ printk (KERN_WARNING - "%s: unknown RNDIS message 0x%08X len %d\n", + "%s: unknown RNDIS message 0x%08X len %d\n", __FUNCTION__ , MsgType, MsgLength); { unsigned i; @@ -1142,14 +1143,14 @@ int rndis_msg_parser (u8 configNr, u8 *b } break; } - + return -ENOTSUPP; } int rndis_register (int (* rndis_control_ack) (struct net_device *)) { u8 i; - + for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { if (!rndis_per_dev_params [i].used) { rndis_per_dev_params [i].used = 1; @@ -1159,32 +1160,32 @@ int rndis_register (int (* rndis_control } } DEBUG("failed\n"); - + return -1; } void rndis_deregister (int configNr) { DEBUG("%s: \n", __FUNCTION__ ); - + if (configNr >= RNDIS_MAX_CONFIGS) return; rndis_per_dev_params [configNr].used = 0; - + return; } -int rndis_set_param_dev (u8 configNr, struct net_device *dev, +int rndis_set_param_dev (u8 configNr, struct net_device *dev, struct net_device_stats *stats, u16 *cdc_filter) { DEBUG("%s:\n", __FUNCTION__ ); if (!dev || !stats) return -1; if (configNr >= RNDIS_MAX_CONFIGS) return -1; - + rndis_per_dev_params [configNr].dev = dev; rndis_per_dev_params [configNr].stats = stats; rndis_per_dev_params [configNr].filter = cdc_filter; - + return 0; } @@ -1193,10 +1194,10 @@ int rndis_set_param_vendor (u8 configNr, DEBUG("%s:\n", __FUNCTION__ ); if (!vendorDescr) return -1; if (configNr >= RNDIS_MAX_CONFIGS) return -1; - + rndis_per_dev_params [configNr].vendorID = vendorID; rndis_per_dev_params [configNr].vendorDescr = vendorDescr; - + return 0; } @@ -1204,10 +1205,10 @@ int rndis_set_param_medium (u8 configNr, { DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed); if (configNr >= RNDIS_MAX_CONFIGS) return -1; - + rndis_per_dev_params [configNr].medium = medium; rndis_per_dev_params [configNr].speed = speed; - + return 0; } @@ -1229,9 +1230,9 @@ void rndis_free_response (int configNr, { rndis_resp_t *r; struct list_head *act, *tmp; - - list_for_each_safe (act, tmp, - &(rndis_per_dev_params [configNr].resp_queue)) + + list_for_each_safe (act, tmp, + &(rndis_per_dev_params [configNr].resp_queue)) { r = list_entry (act, rndis_resp_t, list); if (r && r->buf == buf) { @@ -1244,12 +1245,12 @@ void rndis_free_response (int configNr, u8 *rndis_get_next_response (int configNr, u32 *length) { rndis_resp_t *r; - struct list_head *act, *tmp; - + struct list_head *act, *tmp; + if (!length) return NULL; - - list_for_each_safe (act, tmp, - &(rndis_per_dev_params [configNr].resp_queue)) + + list_for_each_safe (act, tmp, + &(rndis_per_dev_params [configNr].resp_queue)) { r = list_entry (act, rndis_resp_t, list); if (!r->send) { @@ -1258,24 +1259,24 @@ u8 *rndis_get_next_response (int configN return r->buf; } } - + return NULL; } static rndis_resp_t *rndis_add_response (int configNr, u32 length) { rndis_resp_t *r; - + /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */ r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC); if (!r) return NULL; - + r->buf = (u8 *) (r + 1); r->length = length; r->send = 0; - - list_add_tail (&r->list, - &(rndis_per_dev_params [configNr].resp_queue)); + + list_add_tail (&r->list, + &(rndis_per_dev_params [configNr].resp_queue)); return r; } @@ -1301,14 +1302,14 @@ int rndis_rm_hdr(struct sk_buff *skb) #ifdef CONFIG_USB_GADGET_DEBUG_FILES -static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, - void *data) +static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, + void *data) { char *out = page; int len; rndis_params *param = (rndis_params *) data; - - out += snprintf (out, count, + + out += snprintf (out, count, "Config Nr. %d\n" "used : %s\n" "state : %s\n" @@ -1316,8 +1317,8 @@ static int rndis_proc_read (char *page, "speed : %d\n" "cable : %s\n" "vendor ID : 0x%08X\n" - "vendor : %s\n", - param->confignr, (param->used) ? "y" : "n", + "vendor : %s\n", + param->confignr, (param->used) ? "y" : "n", ({ char *s = "?"; switch (param->state) { case RNDIS_UNINITIALIZED: @@ -1327,32 +1328,32 @@ static int rndis_proc_read (char *page, case RNDIS_DATA_INITIALIZED: s = "RNDIS_DATA_INITIALIZED"; break; }; s; }), - param->medium, - (param->media_state) ? 0 : param->speed*100, + param->medium, + (param->media_state) ? 0 : param->speed*100, (param->media_state) ? "disconnected" : "connected", - param->vendorID, param->vendorDescr); - + param->vendorID, param->vendorDescr); + len = out - page; len -= off; - + if (len < count) { *eof = 1; if (len <= 0) return 0; } else len = count; - + *start = page + off; return len; } -static int rndis_proc_write (struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int rndis_proc_write (struct file *file, const char __user *buffer, + unsigned long count, void *data) { rndis_params *p = data; u32 speed = 0; int i, fl_speed = 0; - + for (i = 0; i < count; i++) { char c; if (get_user(c, buffer)) @@ -1379,15 +1380,15 @@ static int rndis_proc_write (struct file case 'd': rndis_signal_disconnect(p->confignr); break; - default: + default: if (fl_speed) p->speed = speed; else DEBUG ("%c is not valid\n", c); break; } - + buffer++; } - + return count; } @@ -1408,7 +1409,7 @@ #ifdef CONFIG_USB_GADGET_DEBUG_FILES sprintf (name, NAME_TEMPLATE, i); if (!(rndis_connect_state [i] - = create_proc_entry (name, 0660, NULL))) + = create_proc_entry (name, 0660, NULL))) { DEBUG ("%s :remove entries", __FUNCTION__); while (i) { @@ -1432,7 +1433,7 @@ #endif = NDIS_MEDIA_STATE_DISCONNECTED; INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue)); } - + return 0; } @@ -1441,7 +1442,7 @@ void rndis_exit (void) #ifdef CONFIG_USB_GADGET_DEBUG_FILES u8 i; char name [20]; - + for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { sprintf (name, NAME_TEMPLATE, i); remove_proc_entry (name, NULL); diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h index 95b4c63..2956608 100644 --- a/drivers/usb/gadget/rndis.h +++ b/drivers/usb/gadget/rndis.h @@ -1,15 +1,15 @@ -/* +/* * RNDIS Definitions for Remote NDIS - * + * * Version: $Id: rndis.h,v 1.15 2004/03/25 21:33:46 robert Exp $ - * + * * Authors: Benedikt Spranger, Pengutronix - * Robert Schwebel, Pengutronix - * - * This program is free software; you can redistribute it and/or + * Robert Schwebel, Pengutronix + * + * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License - * version 2, as published by the Free Software Foundation. - * + * version 2, as published by the Free Software Foundation. + * * This software was originally developed in conformance with * Microsoft's Remote NDIS Specification License Agreement. */ @@ -34,7 +34,7 @@ #define RNDIS_STATUS_NOT_SUPPORTED 0xC00 #define RNDIS_STATUS_MEDIA_CONNECT 0x4001000BU /* Device connected */ #define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000CU /* Device disconnected */ /* For all not specified status messages: - * RNDIS_STATUS_Xxx -> NDIS_STATUS_Xxx + * RNDIS_STATUS_Xxx -> NDIS_STATUS_Xxx */ /* Message Set for Connectionless (802.3) Devices */ @@ -69,7 +69,7 @@ #define OID_PNP_REMOVE_WAKE_UP_PATTERN #define OID_PNP_ENABLE_WAKE_UP 0xFD010106 -typedef struct rndis_init_msg_type +typedef struct rndis_init_msg_type { __le32 MessageType; __le32 MessageLength; @@ -234,12 +234,12 @@ typedef struct rndis_params const u8 *host_mac; u16 *filter; - struct net_device *dev; + struct net_device *dev; struct net_device_stats *stats; u32 vendorID; const char *vendorDescr; - int (*ack) (struct net_device *); + int (*ack) (struct net_device *); struct list_head resp_queue; } rndis_params; @@ -250,7 +250,7 @@ void rndis_deregister (int configNr); int rndis_set_param_dev (u8 configNr, struct net_device *dev, struct net_device_stats *stats, u16 *cdc_filter); -int rndis_set_param_vendor (u8 configNr, u32 vendorID, +int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr); int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); void rndis_add_hdr (struct sk_buff *skb); diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index b992546..9d6e1d2 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -45,88 +45,16 @@ #include #include #include -#include +#include #include #include "gadget_chips.h" -/* Wait Cond */ - -#define __wait_cond_interruptible(wq, condition, lock, flags, ret) \ -do { \ - wait_queue_t __wait; \ - init_waitqueue_entry(&__wait, current); \ - \ - add_wait_queue(&wq, &__wait); \ - for (;;) { \ - set_current_state(TASK_INTERRUPTIBLE); \ - if (condition) \ - break; \ - if (!signal_pending(current)) { \ - spin_unlock_irqrestore(lock, flags); \ - schedule(); \ - spin_lock_irqsave(lock, flags); \ - continue; \ - } \ - ret = -ERESTARTSYS; \ - break; \ - } \ - current->state = TASK_RUNNING; \ - remove_wait_queue(&wq, &__wait); \ -} while (0) - -#define wait_cond_interruptible(wq, condition, lock, flags) \ -({ \ - int __ret = 0; \ - if (!(condition)) \ - __wait_cond_interruptible(wq, condition, lock, flags, \ - __ret); \ - __ret; \ -}) - -#define __wait_cond_interruptible_timeout(wq, condition, lock, flags, \ - timeout, ret) \ -do { \ - signed long __timeout = timeout; \ - wait_queue_t __wait; \ - init_waitqueue_entry(&__wait, current); \ - \ - add_wait_queue(&wq, &__wait); \ - for (;;) { \ - set_current_state(TASK_INTERRUPTIBLE); \ - if (__timeout == 0) \ - break; \ - if (condition) \ - break; \ - if (!signal_pending(current)) { \ - spin_unlock_irqrestore(lock, flags); \ - __timeout = schedule_timeout(__timeout); \ - spin_lock_irqsave(lock, flags); \ - continue; \ - } \ - ret = -ERESTARTSYS; \ - break; \ - } \ - current->state = TASK_RUNNING; \ - remove_wait_queue(&wq, &__wait); \ -} while (0) - -#define wait_cond_interruptible_timeout(wq, condition, lock, flags, \ - timeout) \ -({ \ - int __ret = 0; \ - if (!(condition)) \ - __wait_cond_interruptible_timeout(wq, condition, lock, \ - flags, timeout, __ret); \ - __ret; \ -}) - - /* Defines */ -#define GS_VERSION_STR "v2.0" -#define GS_VERSION_NUM 0x0200 +#define GS_VERSION_STR "v2.2" +#define GS_VERSION_NUM 0x0202 #define GS_LONG_NAME "Gadget Serial" #define GS_SHORT_NAME "g_serial" @@ -843,9 +771,19 @@ exit_unlock_dev: /* * gs_close */ + +#define GS_WRITE_FINISHED_EVENT_SAFELY(p) \ +({ \ + int cond; \ + \ + spin_lock_irq(&(p)->port_lock); \ + cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \ + spin_unlock_irq(&(p)->port_lock); \ + cond; \ +}) + static void gs_close(struct tty_struct *tty, struct file *file) { - unsigned long flags; struct gs_port *port = tty->driver_data; struct semaphore *sem; @@ -859,7 +797,7 @@ static void gs_close(struct tty_struct * sem = &gs_open_close_sem[port->port_num]; down(sem); - spin_lock_irqsave(&port->port_lock, flags); + spin_lock_irq(&port->port_lock); if (port->port_open_count == 0) { printk(KERN_ERR @@ -887,12 +825,11 @@ static void gs_close(struct tty_struct * /* wait for write buffer to drain, or */ /* at most GS_CLOSE_TIMEOUT seconds */ if (gs_buf_data_avail(port->port_write_buf) > 0) { - spin_unlock_irqrestore(&port->port_lock, flags); - wait_cond_interruptible_timeout(port->port_write_wait, - port->port_dev == NULL - || gs_buf_data_avail(port->port_write_buf) == 0, - &port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ); - spin_lock_irqsave(&port->port_lock, flags); + spin_unlock_irq(&port->port_lock); + wait_event_interruptible_timeout(port->port_write_wait, + GS_WRITE_FINISHED_EVENT_SAFELY(port), + GS_CLOSE_TIMEOUT * HZ); + spin_lock_irq(&port->port_lock); } /* free disconnected port on final close */ @@ -912,7 +849,7 @@ static void gs_close(struct tty_struct * port->port_num, tty, file); exit: - spin_unlock_irqrestore(&port->port_lock, flags); + spin_unlock_irq(&port->port_lock); up(sem); } diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index e27b79a..b93d71d 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -47,12 +47,29 @@ config USB_EHCI_ROOT_HUB_TT controller is needed. It's safe to say "y" even if your controller doesn't support this feature. - This supports the EHCI implementation from TransDimension Inc. + This supports the EHCI implementation that's originally + from ARC, and has since changed hands a few times. + +config USB_EHCI_TT_NEWSCHED + bool "Improved Transaction Translator scheduling (EXPERIMENTAL)" + depends on USB_EHCI_HCD && EXPERIMENTAL + ---help--- + This changes the periodic scheduling code to fill more of the low + and full speed bandwidth available from the Transaction Translator + (TT) in USB 2.0 hubs. Without this, only one transfer will be + issued in each microframe, significantly reducing the number of + periodic low/fullspeed transfers possible. + + If you have multiple periodic low/fullspeed devices connected to a + highspeed USB hub which is connected to a highspeed USB Host + Controller, and some of those devices will not work correctly + (possibly due to "ENOSPC" or "-28" errors), say Y. + + If unsure, say N. config USB_ISP116X_HCD tristate "ISP116X HCD support" depends on USB - default N ---help--- The ISP1160 and ISP1161 chips are USB host controllers. Enable this option if your board has this chip. If unsure, say N. @@ -127,7 +144,6 @@ config USB_UHCI_HCD config USB_SL811_HCD tristate "SL811HS HCD support" depends on USB - default N help The SL811HS is a single-port USB controller that supports either host side or peripheral side roles. Enable this option if your @@ -140,7 +156,6 @@ config USB_SL811_HCD config USB_SL811_CS tristate "CF/PCMCIA support for SL811HS HCD" depends on USB_SL811_HCD && PCMCIA - default N help Wraps a PCMCIA driver around the SL811HS HCD, supporting the RATOC REX-CFU1U CF card (often used with PDAs). If unsure, say N. diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 63eadee..9b4697a 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -16,10 +16,6 @@ #include #include -#ifndef CONFIG_SOC_AU1200 -#error "this Alchemy chip doesn't have EHCI" -#else /* Au1200 */ - #define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) #define USB_MCFG_PFEN (1<<31) #define USB_MCFG_RDCOMB (1<<30) @@ -272,6 +268,8 @@ static int ehci_hcd_au1xxx_drv_resume(st return 0; } */ +MODULE_ALIAS("au1xxx-ehci"); +/* FIXME use "struct platform_driver" */ static struct device_driver ehci_hcd_au1xxx_driver = { .name = "au1xxx-ehci", .bus = &platform_bus_type, @@ -280,18 +278,3 @@ static struct device_driver ehci_hcd_au1 /*.suspend = ehci_hcd_au1xxx_drv_suspend, */ /*.resume = ehci_hcd_au1xxx_drv_resume, */ }; - -static int __init ehci_hcd_au1xxx_init(void) -{ - pr_debug(DRIVER_INFO " (Au1xxx)\n"); - - return driver_register(&ehci_hcd_au1xxx_driver); -} - -static void __exit ehci_hcd_au1xxx_cleanup(void) -{ - driver_unregister(&ehci_hcd_au1xxx_driver); -} - -module_init(ehci_hcd_au1xxx_init); -module_exit(ehci_hcd_au1xxx_cleanup); diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index f985f12..a49a689 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -324,43 +324,12 @@ static int ehci_fsl_drv_remove(struct pl return 0; } -static struct platform_driver ehci_fsl_dr_driver = { - .probe = ehci_fsl_drv_probe, - .remove = ehci_fsl_drv_remove, - .driver = { - .name = "fsl-usb2-dr", - }, -}; +MODULE_ALIAS("fsl-ehci"); -static struct platform_driver ehci_fsl_mph_driver = { +static struct platform_driver ehci_fsl_driver = { .probe = ehci_fsl_drv_probe, .remove = ehci_fsl_drv_remove, .driver = { - .name = "fsl-usb2-mph", + .name = "fsl-ehci", }, }; - -static int __init ehci_fsl_init(void) -{ - int retval; - - pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", - hcd_name, - sizeof(struct ehci_qh), sizeof(struct ehci_qtd), - sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); - - retval = platform_driver_register(&ehci_fsl_dr_driver); - if (retval) - return retval; - - return platform_driver_register(&ehci_fsl_mph_driver); -} - -static void __exit ehci_fsl_cleanup(void) -{ - platform_driver_unregister(&ehci_fsl_mph_driver); - platform_driver_unregister(&ehci_fsl_dr_driver); -} - -module_init(ehci_fsl_init); -module_exit(ehci_fsl_cleanup); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 79f2d8b..9b37e50 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -889,19 +889,59 @@ MODULE_LICENSE ("GPL"); #ifdef CONFIG_PCI #include "ehci-pci.c" -#define EHCI_BUS_GLUED +#define PCI_DRIVER ehci_pci_driver #endif #ifdef CONFIG_PPC_83xx #include "ehci-fsl.c" -#define EHCI_BUS_GLUED +#define PLATFORM_DRIVER ehci_fsl_driver #endif -#ifdef CONFIG_SOC_AU1X00 +#ifdef CONFIG_SOC_AU1200 #include "ehci-au1xxx.c" -#define EHCI_BUS_GLUED +#define PLATFORM_DRIVER ehci_hcd_au1xxx_driver #endif -#ifndef EHCI_BUS_GLUED +#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) #error "missing bus glue for ehci-hcd" #endif + +static int __init ehci_hcd_init(void) +{ + int retval = 0; + + pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", + hcd_name, + sizeof(struct ehci_qh), sizeof(struct ehci_qtd), + sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); + +#ifdef PLATFORM_DRIVER + retval = platform_driver_register(&PLATFORM_DRIVER); + if (retval < 0) + return retval; +#endif + +#ifdef PCI_DRIVER + retval = pci_register_driver(&PCI_DRIVER); + if (retval < 0) { +#ifdef PLATFORM_DRIVER + platform_driver_unregister(&PLATFORM_DRIVER); +#endif + } +#endif + + return retval; +} +module_init(ehci_hcd_init); + +static void __exit ehci_hcd_cleanup(void) +{ +#ifdef PLATFORM_DRIVER + platform_driver_unregister(&PLATFORM_DRIVER); +#endif +#ifdef PCI_DRIVER + pci_unregister_driver(&PCI_DRIVER); +#endif +} +module_exit(ehci_hcd_cleanup); + diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index a1bd2be..cadffac 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -76,6 +76,30 @@ static int ehci_pci_setup(struct usb_hcd dbg_hcs_params(ehci, "reset"); dbg_hcc_params(ehci, "reset"); + /* ehci_init() causes memory for DMA transfers to be + * allocated. Thus, any vendor-specific workarounds based on + * limiting the type of memory used for DMA transfers must + * happen before ehci_init() is called. */ + switch (pdev->vendor) { + case PCI_VENDOR_ID_NVIDIA: + /* NVidia reports that certain chips don't handle + * QH, ITD, or SITD addresses above 2GB. (But TD, + * data buffer, and periodic schedule are normal.) + */ + switch (pdev->device) { + case 0x003c: /* MCP04 */ + case 0x005b: /* CK804 */ + case 0x00d8: /* CK8 */ + case 0x00e8: /* CK8S */ + if (pci_set_consistent_dma_mask(pdev, + DMA_31BIT_MASK) < 0) + ehci_warn(ehci, "can't enable NVidia " + "workaround for >2GB RAM\n"); + break; + } + break; + } + /* cache this readonly data; minimize chip reads */ ehci->hcs_params = readl(&ehci->caps->hcs_params); @@ -88,8 +112,6 @@ static int ehci_pci_setup(struct usb_hcd if (retval) return retval; - /* NOTE: only the parts below this line are PCI-specific */ - switch (pdev->vendor) { case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { @@ -107,19 +129,6 @@ static int ehci_pci_setup(struct usb_hcd break; case PCI_VENDOR_ID_NVIDIA: switch (pdev->device) { - /* NVidia reports that certain chips don't handle - * QH, ITD, or SITD addresses above 2GB. (But TD, - * data buffer, and periodic schedule are normal.) - */ - case 0x003c: /* MCP04 */ - case 0x005b: /* CK804 */ - case 0x00d8: /* CK8 */ - case 0x00e8: /* CK8S */ - if (pci_set_consistent_dma_mask(pdev, - DMA_31BIT_MASK) < 0) - ehci_warn(ehci, "can't enable NVidia " - "workaround for >2GB RAM\n"); - break; /* Some NForce2 chips have problems with selective suspend; * fixed in newer silicon. */ @@ -370,23 +379,3 @@ #ifdef CONFIG_PM .resume = usb_hcd_pci_resume, #endif }; - -static int __init ehci_hcd_pci_init(void) -{ - if (usb_disabled()) - return -ENODEV; - - pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", - hcd_name, - sizeof(struct ehci_qh), sizeof(struct ehci_qtd), - sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); - - return pci_register_driver(&ehci_pci_driver); -} -module_init(ehci_hcd_pci_init); - -static void __exit ehci_hcd_pci_cleanup(void) -{ - pci_unregister_driver(&ehci_pci_driver); -} -module_exit(ehci_hcd_pci_cleanup); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 5871944..4859900 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -163,6 +163,190 @@ static int same_tt (struct usb_device *d return 1; } +#ifdef CONFIG_USB_EHCI_TT_NEWSCHED + +/* Which uframe does the low/fullspeed transfer start in? + * + * The parameter is the mask of ssplits in "H-frame" terms + * and this returns the transfer start uframe in "B-frame" terms, + * which allows both to match, e.g. a ssplit in "H-frame" uframe 0 + * will cause a transfer in "B-frame" uframe 0. "B-frames" lag + * "H-frames" by 1 uframe. See the EHCI spec sec 4.5 and figure 4.7. + */ +static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __le32 mask) +{ + unsigned char smask = QH_SMASK & le32_to_cpu(mask); + if (!smask) { + ehci_err(ehci, "invalid empty smask!\n"); + /* uframe 7 can't have bw so this will indicate failure */ + return 7; + } + return ffs(smask) - 1; +} + +static const unsigned char +max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; + +/* carryover low/fullspeed bandwidth that crosses uframe boundries */ +static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) +{ + int i; + for (i=0; i<7; i++) { + if (max_tt_usecs[i] < tt_usecs[i]) { + tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i]; + tt_usecs[i] = max_tt_usecs[i]; + } + } +} + +/* How many of the tt's periodic downstream 1000 usecs are allocated? + * + * While this measures the bandwidth in terms of usecs/uframe, + * the low/fullspeed bus has no notion of uframes, so any particular + * low/fullspeed transfer can "carry over" from one uframe to the next, + * since the TT just performs downstream transfers in sequence. + * + * For example two seperate 100 usec transfers can start in the same uframe, + * and the second one would "carry over" 75 usecs into the next uframe. + */ +static void +periodic_tt_usecs ( + struct ehci_hcd *ehci, + struct usb_device *dev, + unsigned frame, + unsigned short tt_usecs[8] +) +{ + __le32 *hw_p = &ehci->periodic [frame]; + union ehci_shadow *q = &ehci->pshadow [frame]; + unsigned char uf; + + memset(tt_usecs, 0, 16); + + while (q->ptr) { + switch (Q_NEXT_TYPE(*hw_p)) { + case Q_TYPE_ITD: + hw_p = &q->itd->hw_next; + q = &q->itd->itd_next; + continue; + case Q_TYPE_QH: + if (same_tt(dev, q->qh->dev)) { + uf = tt_start_uframe(ehci, q->qh->hw_info2); + tt_usecs[uf] += q->qh->tt_usecs; + } + hw_p = &q->qh->hw_next; + q = &q->qh->qh_next; + continue; + case Q_TYPE_SITD: + if (same_tt(dev, q->sitd->urb->dev)) { + uf = tt_start_uframe(ehci, q->sitd->hw_uframe); + tt_usecs[uf] += q->sitd->stream->tt_usecs; + } + hw_p = &q->sitd->hw_next; + q = &q->sitd->sitd_next; + continue; + // case Q_TYPE_FSTN: + default: + ehci_dbg(ehci, + "ignoring periodic frame %d FSTN\n", frame); + hw_p = &q->fstn->hw_next; + q = &q->fstn->fstn_next; + } + } + + carryover_tt_bandwidth(tt_usecs); + + if (max_tt_usecs[7] < tt_usecs[7]) + ehci_err(ehci, "frame %d tt sched overrun: %d usecs\n", + frame, tt_usecs[7] - max_tt_usecs[7]); +} + +/* + * Return true if the device's tt's downstream bus is available for a + * periodic transfer of the specified length (usecs), starting at the + * specified frame/uframe. Note that (as summarized in section 11.19 + * of the usb 2.0 spec) TTs can buffer multiple transactions for each + * uframe. + * + * The uframe parameter is when the fullspeed/lowspeed transfer + * should be executed in "B-frame" terms, which is the same as the + * highspeed ssplit's uframe (which is in "H-frame" terms). For example + * a ssplit in "H-frame" 0 causes a transfer in "B-frame" 0. + * See the EHCI spec sec 4.5 and fig 4.7. + * + * This checks if the full/lowspeed bus, at the specified starting uframe, + * has the specified bandwidth available, according to rules listed + * in USB 2.0 spec section 11.18.1 fig 11-60. + * + * This does not check if the transfer would exceed the max ssplit + * limit of 16, specified in USB 2.0 spec section 11.18.4 requirement #4, + * since proper scheduling limits ssplits to less than 16 per uframe. + */ +static int tt_available ( + struct ehci_hcd *ehci, + unsigned period, + struct usb_device *dev, + unsigned frame, + unsigned uframe, + u16 usecs +) +{ + if ((period == 0) || (uframe >= 7)) /* error */ + return 0; + + for (; frame < ehci->periodic_size; frame += period) { + unsigned short tt_usecs[8]; + + periodic_tt_usecs (ehci, dev, frame, tt_usecs); + + ehci_vdbg(ehci, "tt frame %d check %d usecs start uframe %d in" + " schedule %d/%d/%d/%d/%d/%d/%d/%d\n", + frame, usecs, uframe, + tt_usecs[0], tt_usecs[1], tt_usecs[2], tt_usecs[3], + tt_usecs[4], tt_usecs[5], tt_usecs[6], tt_usecs[7]); + + if (max_tt_usecs[uframe] <= tt_usecs[uframe]) { + ehci_vdbg(ehci, "frame %d uframe %d fully scheduled\n", + frame, uframe); + return 0; + } + + /* special case for isoc transfers larger than 125us: + * the first and each subsequent fully used uframe + * must be empty, so as to not illegally delay + * already scheduled transactions + */ + if (125 < usecs) { + int ufs = (usecs / 125) - 1; + int i; + for (i = uframe; i < (uframe + ufs) && i < 8; i++) + if (0 < tt_usecs[i]) { + ehci_vdbg(ehci, + "multi-uframe xfer can't fit " + "in frame %d uframe %d\n", + frame, i); + return 0; + } + } + + tt_usecs[uframe] += usecs; + + carryover_tt_bandwidth(tt_usecs); + + /* fail if the carryover pushed bw past the last uframe's limit */ + if (max_tt_usecs[7] < tt_usecs[7]) { + ehci_vdbg(ehci, + "tt unavailable usecs %d frame %d uframe %d\n", + usecs, frame, uframe); + return 0; + } + } + + return 1; +} + +#else + /* return true iff the device's transaction translator is available * for a periodic transfer starting at the specified frame, using * all the uframes in the mask. @@ -237,6 +421,8 @@ static int tt_no_collision ( return 1; } +#endif /* CONFIG_USB_EHCI_TT_NEWSCHED */ + /*-------------------------------------------------------------------------*/ static int enable_periodic (struct ehci_hcd *ehci) @@ -481,7 +667,7 @@ static int check_intr_schedule ( ) { int retval = -ENOSPC; - u8 mask; + u8 mask = 0; if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ goto done; @@ -494,6 +680,24 @@ static int check_intr_schedule ( goto done; } +#ifdef CONFIG_USB_EHCI_TT_NEWSCHED + if (tt_available (ehci, qh->period, qh->dev, frame, uframe, + qh->tt_usecs)) { + unsigned i; + + /* TODO : this may need FSTN for SSPLIT in uframe 5. */ + for (i=uframe+1; i<8 && iperiod, qh->c_usecs)) + goto done; + else + mask |= 1 << i; + + retval = 0; + + *c_maskp = cpu_to_le32 (mask << 8); + } +#else /* Make sure this tt's buffer is also available for CSPLITs. * We pessimize a bit; probably the typical full speed case * doesn't need the second CSPLIT. @@ -514,6 +718,7 @@ static int check_intr_schedule ( goto done; retval = 0; } +#endif done: return retval; } @@ -1047,12 +1252,21 @@ sitd_slot_ok ( frame = uframe >> 3; uf = uframe & 7; +#ifdef CONFIG_USB_EHCI_TT_NEWSCHED + /* The tt's fullspeed bus bandwidth must be available. + * tt_available scheduling guarantees 10+% for control/bulk. + */ + if (!tt_available (ehci, period_uframes << 3, + stream->udev, frame, uf, stream->tt_usecs)) + return 0; +#else /* tt must be idle for start(s), any gap, and csplit. * assume scheduling slop leaves 10+% for control/bulk. */ if (!tt_no_collision (ehci, period_uframes << 3, stream->udev, frame, mask)) return 0; +#endif /* check starts (OUT uses more than one) */ max_used = 100 - stream->usecs; diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c index 2fe7fd1..4a22909 100644 --- a/drivers/usb/host/hc_crisv10.c +++ b/drivers/usb/host/hc_crisv10.c @@ -411,8 +411,7 @@ static inline void urb_list_move_last(st urb_entry_t *urb_entry = __urb_list_entry(urb, epid); assert(urb_entry); - list_del(&urb_entry->list); - list_add_tail(&urb_entry->list, &urb_list[epid]); + list_move_tail(&urb_entry->list, &urb_list[epid]); } /* Get the next urb in the list. */ diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index e99210b..1438625 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -63,7 +63,7 @@ #include #include #include #include -#include +#include #include #include @@ -781,7 +781,7 @@ static int isp116x_urb_enqueue(struct us if (ep->branch < PERIODIC_SIZE) break; - ret = ep->branch = balance(isp116x, ep->period, ep->load); + ep->branch = ret = balance(isp116x, ep->period, ep->load); if (ret < 0) goto fail; ret = 0; diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index a923430..6b4bc3f 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -46,7 +46,7 @@ #include #include #include #include -#include +#include #include #include diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 302aa1e..54f554e 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include MODULE_AUTHOR("Botond Botyanszki"); MODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6"); diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index e123931..6637a0e 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -98,6 +98,7 @@ static int uhci_show_urbp(struct urb_pri char *out = buf; struct uhci_td *td; int i, nactive, ninactive; + char *ptype; if (len < 200) return 0; @@ -110,13 +111,15 @@ static int uhci_show_urbp(struct urb_pri (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT")); switch (usb_pipetype(urbp->urb->pipe)) { - case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO"); break; - case PIPE_INTERRUPT: out += sprintf(out, "INT"); break; - case PIPE_BULK: out += sprintf(out, "BLK"); break; - case PIPE_CONTROL: out += sprintf(out, "CTL"); break; + case PIPE_ISOCHRONOUS: ptype = "ISO"; break; + case PIPE_INTERRUPT: ptype = "INT"; break; + case PIPE_BULK: ptype = "BLK"; break; + default: + case PIPE_CONTROL: ptype = "CTL"; break; } - out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : "")); + out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); + out += sprintf(out, " Actlen=%d", urbp->urb->actual_length); if (urbp->urb->status != -EINPROGRESS) out += sprintf(out, " Status=%d", urbp->urb->status); @@ -124,7 +127,8 @@ static int uhci_show_urbp(struct urb_pri i = nactive = ninactive = 0; list_for_each_entry(td, &urbp->td_list, list) { - if (++i <= 10 || debug > 2) { + if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC && + (++i <= 10 || debug > 2)) { out += sprintf(out, "%*s%d: ", space + 2, "", i); out += uhci_show_td(td, out, len - (out - buf), 0); } else { @@ -147,13 +151,27 @@ static int uhci_show_qh(struct uhci_qh * char *out = buf; int i, nurbs; __le32 element = qh_element(qh); + char *qtype; /* Try to make sure there's enough memory */ - if (len < 80 * 6) + if (len < 80 * 7) return 0; - out += sprintf(out, "%*s[%p] link (%08x) element (%08x)\n", space, "", - qh, le32_to_cpu(qh->link), le32_to_cpu(element)); + switch (qh->type) { + case USB_ENDPOINT_XFER_ISOC: qtype = "ISO"; break; + case USB_ENDPOINT_XFER_INT: qtype = "INT"; break; + case USB_ENDPOINT_XFER_BULK: qtype = "BLK"; break; + case USB_ENDPOINT_XFER_CONTROL: qtype = "CTL"; break; + default: qtype = "Skel" ; break; + } + + out += sprintf(out, "%*s[%p] %s QH link (%08x) element (%08x)\n", + space, "", qh, qtype, + le32_to_cpu(qh->link), le32_to_cpu(element)); + if (qh->type == USB_ENDPOINT_XFER_ISOC) + out += sprintf(out, "%*s period %d frame %x desc [%p]\n", + space, "", qh->period, qh->iso_frame, + qh->iso_packet_desc); if (element & UHCI_PTR_QH) out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); @@ -261,7 +279,8 @@ static int uhci_show_root_hub_state(stru default: rh_state = "?"; break; } - out += sprintf(out, "Root-hub state: %s\n", rh_state); + out += sprintf(out, "Root-hub state: %s FSBR: %d\n", + rh_state, uhci->fsbr_is_on); return out - buf; } @@ -275,7 +294,7 @@ static int uhci_show_status(struct uhci_ unsigned short portsc1, portsc2; /* Try to make sure there's enough memory */ - if (len < 80 * 6) + if (len < 80 * 9) return 0; usbcmd = inw(io_addr + 0); @@ -314,6 +333,10 @@ static int uhci_show_status(struct uhci_ out += sprintf(out, " sof = %02x\n", sof); out += uhci_show_sc(1, portsc1, out, len - (out - buf)); out += uhci_show_sc(2, portsc2, out, len - (out - buf)); + out += sprintf(out, "Most recent frame: %x (%d) " + "Last ISO frame: %x (%d)\n", + uhci->frame_number, uhci->frame_number & 1023, + uhci->last_iso_frame, uhci->last_iso_frame & 1023); return out - buf; } diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index d225e11..7b48567 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -13,7 +13,7 @@ * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) - * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu + * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu * * Intel documents this fairly well, and as far as I know there * are no royalties or anything like that, but even so there are @@ -31,7 +31,6 @@ #include #include #include #include -#include #include #include #include @@ -88,15 +87,6 @@ static void suspend_rh(struct uhci_hcd * static void wakeup_rh(struct uhci_hcd *uhci); static void uhci_get_current_frame_number(struct uhci_hcd *uhci); -/* If a transfer is still active after this much time, turn off FSBR */ -#define IDLE_TIMEOUT msecs_to_jiffies(50) -#define FSBR_DELAY msecs_to_jiffies(50) - -/* When we timeout an idle transfer for FSBR, we'll switch it over to */ -/* depth first traversal. We'll do it in groups of this number of TDs */ -/* to make sure it doesn't hog all of the bandwidth */ -#define DEPTH_INTERVAL 5 - #include "uhci-debug.c" #include "uhci-q.c" #include "uhci-hub.c" @@ -120,22 +110,29 @@ static void finish_reset(struct uhci_hcd uhci->is_stopped = UHCI_IS_STOPPED; uhci_to_hcd(uhci)->state = HC_STATE_HALT; uhci_to_hcd(uhci)->poll_rh = 0; + + uhci->dead = 0; /* Full reset resurrects the controller */ } /* * Last rites for a defunct/nonfunctional controller * or one we don't want to use any more. */ -static void hc_died(struct uhci_hcd *uhci) +static void uhci_hc_died(struct uhci_hcd *uhci) { + uhci_get_current_frame_number(uhci); uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); finish_reset(uhci); - uhci->hc_inaccessible = 1; + uhci->dead = 1; + + /* The current frame may already be partway finished */ + ++uhci->frame_number; } /* - * Initialize a controller that was newly discovered or has just been - * resumed. In either case we can't be sure of its previous state. + * Initialize a controller that was newly discovered or has lost power + * or otherwise been reset while it was suspended. In none of these cases + * can we be sure of its previous state. */ static void check_and_reset_hc(struct uhci_hcd *uhci) { @@ -155,7 +152,8 @@ static void configure_hc(struct uhci_hcd outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD); /* Set the current frame number */ - outw(uhci->frame_number, uhci->io_addr + USBFRNUM); + outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER, + uhci->io_addr + USBFRNUM); /* Mark controller as not halted before we enable interrupts */ uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; @@ -207,7 +205,8 @@ __acquires(uhci->lock) int int_enable; auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); - dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__, + dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev, + "%s%s\n", __FUNCTION__, (auto_stop ? " (auto-stop)" : "")); /* If we get a suspend request when we're already auto-stopped @@ -241,27 +240,27 @@ __acquires(uhci->lock) spin_unlock_irq(&uhci->lock); msleep(1); spin_lock_irq(&uhci->lock); - if (uhci->hc_inaccessible) /* Died */ + if (uhci->dead) return; } if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) - dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n"); + dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev, + "Controller not stopped yet!\n"); uhci_get_current_frame_number(uhci); - smp_wmb(); uhci->rh_state = new_state; uhci->is_stopped = UHCI_IS_STOPPED; uhci_to_hcd(uhci)->poll_rh = !int_enable; uhci_scan_schedule(uhci, NULL); + uhci_fsbr_off(uhci); } static void start_rh(struct uhci_hcd *uhci) { uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; uhci->is_stopped = 0; - smp_wmb(); /* Mark it configured and running with a 64-byte max packet. * All interrupts are enabled, even though RESUME won't do anything. @@ -278,7 +277,8 @@ static void wakeup_rh(struct uhci_hcd *u __releases(uhci->lock) __acquires(uhci->lock) { - dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__, + dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev, + "%s%s\n", __FUNCTION__, uhci->rh_state == UHCI_RH_AUTO_STOPPED ? " (auto-start)" : ""); @@ -293,7 +293,7 @@ __acquires(uhci->lock) spin_unlock_irq(&uhci->lock); msleep(20); spin_lock_irq(&uhci->lock); - if (uhci->hc_inaccessible) /* Died */ + if (uhci->dead) return; /* End Global Resume and wait for EOP to be sent */ @@ -345,7 +345,7 @@ static irqreturn_t uhci_irq(struct usb_h errbuf, ERRBUF_LEN); lprintk(errbuf); } - hc_died(uhci); + uhci_hc_died(uhci); /* Force a callback in case there are * pending unlinks */ @@ -368,12 +368,21 @@ static irqreturn_t uhci_irq(struct usb_h /* * Store the current frame number in uhci->frame_number if the controller - * is runnning + * is runnning. Expand from 11 bits (of which we use only 10) to a + * full-sized integer. + * + * Like many other parts of the driver, this code relies on being polled + * more than once per second as long as the controller is running. */ static void uhci_get_current_frame_number(struct uhci_hcd *uhci) { - if (!uhci->is_stopped) - uhci->frame_number = inw(uhci->io_addr + USBFRNUM); + if (!uhci->is_stopped) { + unsigned delta; + + delta = (inw(uhci->io_addr + USBFRNUM) - uhci->frame_number) & + (UHCI_NUMFRAMES - 1); + uhci->frame_number += delta; + } } /* @@ -407,7 +416,7 @@ static void release_uhci(struct uhci_hcd uhci->frame, uhci->frame_dma_handle); } -static int uhci_reset(struct usb_hcd *hcd) +static int uhci_init(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned io_size = (unsigned) hcd->rsrc_len; @@ -459,7 +468,7 @@ static void uhci_shutdown(struct pci_dev { struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev); - hc_died(hcd_to_uhci(hcd)); + uhci_hc_died(hcd_to_uhci(hcd)); } /* @@ -487,14 +496,10 @@ static int uhci_start(struct usb_hcd *hc hcd->uses_new_polling = 1; - uhci->fsbr = 0; - uhci->fsbrtimeout = 0; - spin_lock_init(&uhci->lock); - - INIT_LIST_HEAD(&uhci->td_remove_list); + setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout, + (unsigned long) uhci); INIT_LIST_HEAD(&uhci->idle_qh_list); - init_waitqueue_head(&uhci->waitqh); if (DEBUG_CONFIGURED) { @@ -665,11 +670,12 @@ static void uhci_stop(struct usb_hcd *hc struct uhci_hcd *uhci = hcd_to_uhci(hcd); spin_lock_irq(&uhci->lock); - if (!uhci->hc_inaccessible) - hc_died(uhci); + if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead) + uhci_hc_died(uhci); uhci_scan_schedule(uhci, NULL); spin_unlock_irq(&uhci->lock); + del_timer_sync(&uhci->fsbr_timer); release_uhci(uhci); } @@ -677,12 +683,15 @@ #ifdef CONFIG_PM static int uhci_rh_suspend(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); + int rc = 0; spin_lock_irq(&uhci->lock); - if (!uhci->hc_inaccessible) /* Not dead */ + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + rc = -ESHUTDOWN; + else if (!uhci->dead) suspend_rh(uhci, UHCI_RH_SUSPENDED); spin_unlock_irq(&uhci->lock); - return 0; + return rc; } static int uhci_rh_resume(struct usb_hcd *hcd) @@ -691,13 +700,10 @@ static int uhci_rh_resume(struct usb_hcd int rc = 0; spin_lock_irq(&uhci->lock); - if (uhci->hc_inaccessible) { - if (uhci->rh_state == UHCI_RH_SUSPENDED) { - dev_warn(uhci_dev(uhci), "HC isn't running!\n"); - rc = -ENODEV; - } - /* Otherwise the HC is dead */ - } else + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n"); + rc = -ESHUTDOWN; + } else if (!uhci->dead) wakeup_rh(uhci); spin_unlock_irq(&uhci->lock); return rc; @@ -711,8 +717,8 @@ static int uhci_suspend(struct usb_hcd * dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); spin_lock_irq(&uhci->lock); - if (uhci->hc_inaccessible) /* Dead or already suspended */ - goto done; + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) + goto done_okay; /* Already suspended or dead */ if (uhci->rh_state > UHCI_RH_SUSPENDED) { dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); @@ -725,12 +731,12 @@ static int uhci_suspend(struct usb_hcd * */ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); mb(); - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - uhci->hc_inaccessible = 1; hcd->poll_rh = 0; /* FIXME: Enable non-PME# remote wakeup? */ +done_okay: + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); done: spin_unlock_irq(&uhci->lock); return rc; @@ -743,24 +749,22 @@ static int uhci_resume(struct usb_hcd *h dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); /* Since we aren't in D3 any more, it's safe to set this flag - * even if the controller was dead. It might not even be dead - * any more, if the firmware or quirks code has reset it. + * even if the controller was dead. */ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); mb(); - if (uhci->rh_state == UHCI_RH_RESET) /* Dead */ - return 0; spin_lock_irq(&uhci->lock); /* FIXME: Disable non-PME# remote wakeup? */ - uhci->hc_inaccessible = 0; - - /* The BIOS may have changed the controller settings during a - * system wakeup. Check it and reconfigure to avoid problems. + /* The firmware or a boot kernel may have changed the controller + * settings during a system wakeup. Check it and reconfigure + * to avoid problems. */ check_and_reset_hc(uhci); + + /* If the controller was dead before, it's back alive now */ configure_hc(uhci); if (uhci->rh_state == UHCI_RH_RESET) { @@ -810,18 +814,15 @@ done: static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - unsigned long flags; - int is_stopped; - int frame_number; + unsigned frame_number; + unsigned delta; /* Minimize latency by avoiding the spinlock */ - local_irq_save(flags); - is_stopped = uhci->is_stopped; - smp_rmb(); - frame_number = (is_stopped ? uhci->frame_number : - inw(uhci->io_addr + USBFRNUM)); - local_irq_restore(flags); - return frame_number; + frame_number = uhci->frame_number; + barrier(); + delta = (inw(uhci->io_addr + USBFRNUM) - frame_number) & + (UHCI_NUMFRAMES - 1); + return frame_number + delta; } static const char hcd_name[] = "uhci_hcd"; @@ -836,7 +837,7 @@ static const struct hc_driver uhci_drive .flags = HCD_USB11, /* Basic lifecycle operations */ - .reset = uhci_reset, + .reset = uhci_init, .start = uhci_start, #ifdef CONFIG_PM .suspend = uhci_suspend, diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index d5c8f4d..108e3de 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -84,6 +84,13 @@ #define UHCI_MAX_SOF_NUMBER 2047 /* in a #define CAN_SCHEDULE_FRAMES 1000 /* how far in the future frames * can be scheduled */ +/* When no queues need Full-Speed Bandwidth Reclamation, + * delay this long before turning FSBR off */ +#define FSBR_OFF_DELAY msecs_to_jiffies(10) + +/* If a queue hasn't advanced after this much time, assume it is stuck */ +#define QH_WAIT_TIMEOUT msecs_to_jiffies(200) + /* * Queue Headers @@ -121,21 +128,31 @@ struct uhci_qh { __le32 element; /* Queue element (TD) pointer */ /* Software fields */ - dma_addr_t dma_handle; - struct list_head node; /* Node in the list of QHs */ struct usb_host_endpoint *hep; /* Endpoint information */ struct usb_device *udev; struct list_head queue; /* Queue of urbps for this QH */ struct uhci_qh *skel; /* Skeleton for this QH */ struct uhci_td *dummy_td; /* Dummy TD to end the queue */ + struct uhci_td *post_td; /* Last TD completed */ + struct usb_iso_packet_descriptor *iso_packet_desc; + /* Next urb->iso_frame_desc entry */ + unsigned long advance_jiffies; /* Time of last queue advance */ unsigned int unlink_frame; /* When the QH was unlinked */ + unsigned int period; /* For Interrupt and Isochronous QHs */ + unsigned int iso_frame; /* Frame # for iso_packet_desc */ + int iso_status; /* Status for Isochronous URBs */ + int state; /* QH_STATE_xxx; see above */ + int type; /* Queue type (control, bulk, etc) */ + + dma_addr_t dma_handle; unsigned int initial_toggle:1; /* Endpoint's current toggle value */ unsigned int needs_fixup:1; /* Must fix the TD toggle values */ - unsigned int is_stopped:1; /* Queue was stopped by an error */ + unsigned int is_stopped:1; /* Queue was stopped by error/unlink */ + unsigned int wait_expired:1; /* QH_WAIT_TIMEOUT has expired */ } __attribute__((aligned(16))); /* @@ -226,7 +243,6 @@ struct uhci_td { dma_addr_t dma_handle; struct list_head list; - struct list_head remove_list; int frame; /* for iso: what frame? */ struct list_head fl_list; @@ -305,38 +321,8 @@ #define skel_fs_control_qh skelqh[11] #define skel_bulk_qh skelqh[12] #define skel_term_qh skelqh[13] -/* - * Search tree for determining where fits in the skelqh[] - * skeleton. - * - * An interrupt request should be placed into the slowest skelqh[] - * which meets the interval/period/frequency requirement. - * An interrupt request is allowed to be faster than but not slower. - * - * For a given , this function returns the appropriate/matching - * skelqh[] index value. - */ -static inline int __interval_to_skel(int interval) -{ - if (interval < 16) { - if (interval < 4) { - if (interval < 2) - return 9; /* int1 for 0-1 ms */ - return 8; /* int2 for 2-3 ms */ - } - if (interval < 8) - return 7; /* int4 for 4-7 ms */ - return 6; /* int8 for 8-15 ms */ - } - if (interval < 64) { - if (interval < 32) - return 5; /* int16 for 16-31 ms */ - return 4; /* int32 for 32-63 ms */ - } - if (interval < 128) - return 3; /* int64 for 64-127 ms */ - return 2; /* int128 for 128-255 ms (Max.) */ -} +/* Find the skelqh entry corresponding to an interval exponent */ +#define UHCI_SKEL_INDEX(exponent) (9 - exponent) /* @@ -396,32 +382,32 @@ struct uhci_hcd { __le32 *frame; void **frame_cpu; /* CPU's frame list */ - int fsbr; /* Full-speed bandwidth reclamation */ - unsigned long fsbrtimeout; /* FSBR delay */ - enum uhci_rh_state rh_state; unsigned long auto_stop_time; /* When to AUTO_STOP */ unsigned int frame_number; /* As of last check */ unsigned int is_stopped; #define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ + unsigned int last_iso_frame; /* Frame of last scan */ + unsigned int cur_iso_frame; /* Frame for current scan */ unsigned int scan_in_progress:1; /* Schedule scan is running */ unsigned int need_rescan:1; /* Redo the schedule scan */ - unsigned int hc_inaccessible:1; /* HC is suspended or dead */ + unsigned int dead:1; /* Controller has died */ unsigned int working_RD:1; /* Suspended root hub doesn't need to be polled */ unsigned int is_initialized:1; /* Data structure is usable */ + unsigned int fsbr_is_on:1; /* FSBR is turned on */ + unsigned int fsbr_is_wanted:1; /* Does any URB want FSBR? */ + unsigned int fsbr_expiring:1; /* FSBR is timing out */ + + struct timer_list fsbr_timer; /* For turning off FBSR */ /* Support for port suspend/resume/reset */ unsigned long port_c_suspend; /* Bit-arrays of ports */ unsigned long resuming_ports; unsigned long ports_timeout; /* Time to stop signalling */ - /* List of TDs that are done, but waiting to be freed (race) */ - struct list_head td_remove_list; - unsigned int td_remove_age; /* Age in frames */ - struct list_head idle_qh_list; /* Where the idle QHs live */ int rh_numports; /* Number of root-hub ports */ @@ -442,6 +428,9 @@ static inline struct usb_hcd *uhci_to_hc #define uhci_dev(u) (uhci_to_hcd(u)->self.controller) +/* Utility macro for comparing frame numbers */ +#define uhci_frame_before_eq(f1, f2) (0 <= (int) ((f2) - (f1))) + /* * Private per-URB data @@ -454,9 +443,7 @@ struct urb_priv { struct uhci_qh *qh; /* QH for this URB */ struct list_head td_list; - unsigned fsbr : 1; /* URB turned on FSBR */ - unsigned short_transfer : 1; /* URB got a short transfer, no - * need to rescan */ + unsigned fsbr:1; /* URB wants FSBR */ }; diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index c8451d9..c545ef9 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -171,9 +171,8 @@ static int uhci_hub_status_data(struct u spin_lock_irqsave(&uhci->lock, flags); uhci_scan_schedule(uhci, NULL); - if (uhci->hc_inaccessible) + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) goto done; - check_fsbr(uhci); uhci_check_ports(uhci); status = get_hub_status_data(uhci, buf); @@ -228,7 +227,7 @@ static int uhci_hub_control(struct usb_h u16 wPortChange, wPortStatus; unsigned long flags; - if (uhci->hc_inaccessible) + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) return -ETIMEDOUT; spin_lock_irqsave(&uhci->lock, flags); diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index a06d84c..c9d72ac 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -13,10 +13,9 @@ * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) - * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu + * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu */ -static void uhci_free_pending_tds(struct uhci_hcd *uhci); /* * Technically, updating td->status here is a race, but it's not really a @@ -38,6 +37,60 @@ static inline void uhci_clear_next_inter uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC); } + +/* + * Full-Speed Bandwidth Reclamation (FSBR). + * We turn on FSBR whenever a queue that wants it is advancing, + * and leave it on for a short time thereafter. + */ +static void uhci_fsbr_on(struct uhci_hcd *uhci) +{ + uhci->fsbr_is_on = 1; + uhci->skel_term_qh->link = cpu_to_le32( + uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH; +} + +static void uhci_fsbr_off(struct uhci_hcd *uhci) +{ + uhci->fsbr_is_on = 0; + uhci->skel_term_qh->link = UHCI_PTR_TERM; +} + +static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb) +{ + struct urb_priv *urbp = urb->hcpriv; + + if (!(urb->transfer_flags & URB_NO_FSBR)) + urbp->fsbr = 1; +} + +static void uhci_urbp_wants_fsbr(struct uhci_hcd *uhci, struct urb_priv *urbp) +{ + if (urbp->fsbr) { + uhci->fsbr_is_wanted = 1; + if (!uhci->fsbr_is_on) + uhci_fsbr_on(uhci); + else if (uhci->fsbr_expiring) { + uhci->fsbr_expiring = 0; + del_timer(&uhci->fsbr_timer); + } + } +} + +static void uhci_fsbr_timeout(unsigned long _uhci) +{ + struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci; + unsigned long flags; + + spin_lock_irqsave(&uhci->lock, flags); + if (uhci->fsbr_expiring) { + uhci->fsbr_expiring = 0; + uhci_fsbr_off(uhci); + } + spin_unlock_irqrestore(&uhci->lock, flags); +} + + static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) { dma_addr_t dma_handle; @@ -51,7 +104,6 @@ static struct uhci_td *uhci_alloc_td(str td->frame = -1; INIT_LIST_HEAD(&td->list); - INIT_LIST_HEAD(&td->remove_list); INIT_LIST_HEAD(&td->fl_list); return td; @@ -61,8 +113,6 @@ static void uhci_free_td(struct uhci_hcd { if (!list_empty(&td->list)) dev_warn(uhci_dev(uhci), "td %p still in list!\n", td); - if (!list_empty(&td->remove_list)) - dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td); if (!list_empty(&td->fl_list)) dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); @@ -77,6 +127,16 @@ static inline void uhci_fill_td(struct u td->buffer = cpu_to_le32(buffer); } +static void uhci_add_td_to_urbp(struct uhci_td *td, struct urb_priv *urbp) +{ + list_add_tail(&td->list, &urbp->td_list); +} + +static void uhci_remove_td_from_urbp(struct uhci_td *td) +{ + list_del_init(&td->list); +} + /* * We insert Isochronous URBs directly into the frame list at the beginning */ @@ -138,6 +198,24 @@ static inline void uhci_remove_td_from_f td->frame = -1; } +static inline void uhci_remove_tds_from_frame(struct uhci_hcd *uhci, + unsigned int framenum) +{ + struct uhci_td *ftd, *ltd; + + framenum &= (UHCI_NUMFRAMES - 1); + + ftd = uhci->frame_cpu[framenum]; + if (ftd) { + ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); + uhci->frame[framenum] = ltd->link; + uhci->frame_cpu[framenum] = NULL; + + while (!list_empty(&ftd->fl_list)) + list_del_init(ftd->fl_list.prev); + } +} + /* * Remove all the TDs for an Isochronous URB from the frame list */ @@ -148,7 +226,6 @@ static void uhci_unlink_isochronous_tds( list_for_each_entry(td, &urbp->td_list, list) uhci_remove_td_from_frame_list(uhci, td); - wmb(); } static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, @@ -161,6 +238,7 @@ static struct uhci_qh *uhci_alloc_qh(str if (!qh) return NULL; + memset(qh, 0, sizeof(*qh)); qh->dma_handle = dma_handle; qh->element = UHCI_PTR_TERM; @@ -179,10 +257,11 @@ static struct uhci_qh *uhci_alloc_qh(str qh->hep = hep; qh->udev = udev; hep->hcpriv = qh; + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; } else { /* Skeleton QH */ qh->state = QH_STATE_ACTIVE; - qh->udev = NULL; + qh->type = -1; } return qh; } @@ -202,35 +281,64 @@ static void uhci_free_qh(struct uhci_hcd } /* - * When the currently executing URB is dequeued, save its current toggle value + * When a queue is stopped and a dequeued URB is given back, adjust + * the previous TD link (if the URB isn't first on the queue) or + * save its toggle value (if it is first and is currently executing). + * + * Returns 0 if the URB should not yet be given back, 1 otherwise. */ -static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb) +static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh, + struct urb *urb) { - struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; + struct urb_priv *urbp = urb->hcpriv; struct uhci_td *td; + int ret = 1; + + /* Isochronous pipes don't use toggles and their TD link pointers + * get adjusted during uhci_urb_dequeue(). But since their queues + * cannot truly be stopped, we have to watch out for dequeues + * occurring after the nominal unlink frame. */ + if (qh->type == USB_ENDPOINT_XFER_ISOC) { + ret = (uhci->frame_number + uhci->is_stopped != + qh->unlink_frame); + goto done; + } + + /* If the URB isn't first on its queue, adjust the link pointer + * of the last TD in the previous URB. The toggle doesn't need + * to be saved since this URB can't be executing yet. */ + if (qh->queue.next != &urbp->node) { + struct urb_priv *purbp; + struct uhci_td *ptd; + + purbp = list_entry(urbp->node.prev, struct urb_priv, node); + WARN_ON(list_empty(&purbp->td_list)); + ptd = list_entry(purbp->td_list.prev, struct uhci_td, + list); + td = list_entry(urbp->td_list.prev, struct uhci_td, + list); + ptd->link = td->link; + goto done; + } /* If the QH element pointer is UHCI_PTR_TERM then then currently * executing URB has already been unlinked, so this one isn't it. */ - if (qh_element(qh) == UHCI_PTR_TERM || - qh->queue.next != &urbp->node) - return; + if (qh_element(qh) == UHCI_PTR_TERM) + goto done; qh->element = UHCI_PTR_TERM; - /* Only bulk and interrupt pipes have to worry about toggles */ - if (!(usb_pipetype(urb->pipe) == PIPE_BULK || - usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) - return; + /* Control pipes have to worry about toggles */ + if (qh->type == USB_ENDPOINT_XFER_CONTROL) + goto done; - /* Find the first active TD; that's the device's toggle state */ - list_for_each_entry(td, &urbp->td_list, list) { - if (td_status(td) & TD_CTRL_ACTIVE) { - qh->needs_fixup = 1; - qh->initial_toggle = uhci_toggle(td_token(td)); - return; - } - } + /* Save the next toggle value */ + WARN_ON(list_empty(&urbp->td_list)); + td = list_entry(urbp->td_list.next, struct uhci_td, list); + qh->needs_fixup = 1; + qh->initial_toggle = uhci_toggle(td_token(td)); - WARN_ON(1); +done: + return ret; } /* @@ -305,6 +413,10 @@ static void uhci_activate_qh(struct uhci qh->element = cpu_to_le32(td->dma_handle); } + /* Treat the queue as if it has just advanced */ + qh->wait_expired = 0; + qh->advance_jiffies = jiffies; + if (qh->state == QH_STATE_ACTIVE) return; qh->state = QH_STATE_ACTIVE; @@ -370,6 +482,12 @@ static void uhci_make_qh_idle(struct uhc list_move(&qh->node, &uhci->idle_qh_list); qh->state = QH_STATE_IDLE; + /* Now that the QH is idle, its post_td isn't being used */ + if (qh->post_td) { + uhci_free_td(uhci, qh->post_td); + qh->post_td = NULL; + } + /* If anyone is waiting for a QH to become idle, wake them up */ if (uhci->num_waiting) wake_up_all(&uhci->waitqh); @@ -395,21 +513,6 @@ static inline struct urb_priv *uhci_allo return urbp; } -static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - list_add_tail(&td->list, &urbp->td_list); -} - -static void uhci_remove_td_from_urb(struct uhci_td *td) -{ - if (list_empty(&td->list)) - return; - - list_del_init(&td->list); -} - static void uhci_free_urb_priv(struct uhci_hcd *uhci, struct urb_priv *urbp) { @@ -419,48 +522,15 @@ static void uhci_free_urb_priv(struct uh dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n", urbp->urb); - uhci_get_current_frame_number(uhci); - if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) { - uhci_free_pending_tds(uhci); - uhci->td_remove_age = uhci->frame_number; - } - - /* Check to see if the remove list is empty. Set the IOC bit */ - /* to force an interrupt so we can remove the TDs. */ - if (list_empty(&uhci->td_remove_list)) - uhci_set_next_interrupt(uhci); - list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { - uhci_remove_td_from_urb(td); - list_add(&td->remove_list, &uhci->td_remove_list); + uhci_remove_td_from_urbp(td); + uhci_free_td(uhci, td); } urbp->urb->hcpriv = NULL; kmem_cache_free(uhci_up_cachep, urbp); } -static void uhci_inc_fsbr(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - if ((!(urb->transfer_flags & URB_NO_FSBR)) && !urbp->fsbr) { - urbp->fsbr = 1; - if (!uhci->fsbr++ && !uhci->fsbrtimeout) - uhci->skel_term_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH; - } -} - -static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - if ((!(urb->transfer_flags & URB_NO_FSBR)) && urbp->fsbr) { - urbp->fsbr = 0; - if (!--uhci->fsbr) - uhci->fsbrtimeout = jiffies + FSBR_DELAY; - } -} - /* * Map status to standard result codes * @@ -487,7 +557,6 @@ static int uhci_map_status(int status, i return -ENOSR; if (status & TD_CTRL_STALLED) /* Stalled */ return -EPIPE; - WARN_ON(status & TD_CTRL_ACTIVE); /* Active */ return 0; } @@ -503,6 +572,7 @@ static int uhci_submit_control(struct uh int len = urb->transfer_buffer_length; dma_addr_t data = urb->transfer_dma; __le32 *plink; + struct urb_priv *urbp = urb->hcpriv; /* The "pipe" thing contains the destination in bits 8--18 */ destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; @@ -516,7 +586,7 @@ static int uhci_submit_control(struct uh * Build the TD for the control request setup packet */ td = qh->dummy_td; - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status, destination | uhci_explen(8), urb->setup_dma); plink = &td->link; @@ -548,7 +618,7 @@ static int uhci_submit_control(struct uh /* Alternate Data0/1 (start with Data1) */ destination ^= TD_TOKEN_TOGGLE; - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status, destination | uhci_explen(pktsze), data); plink = &td->link; @@ -579,7 +649,7 @@ static int uhci_submit_control(struct uh status &= ~TD_CTRL_SPD; - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status | TD_CTRL_IOC, destination | uhci_explen(0), 0); plink = &td->link; @@ -606,145 +676,19 @@ static int uhci_submit_control(struct uh qh->skel = uhci->skel_ls_control_qh; else { qh->skel = uhci->skel_fs_control_qh; - uhci_inc_fsbr(uhci, urb); + uhci_add_fsbr(uhci, urb); } + + urb->actual_length = -8; /* Account for the SETUP packet */ return 0; nomem: /* Remove the dummy TD from the td_list so it doesn't get freed */ - uhci_remove_td_from_urb(qh->dummy_td); + uhci_remove_td_from_urbp(qh->dummy_td); return -ENOMEM; } /* - * If control-IN transfer was short, the status packet wasn't sent. - * This routine changes the element pointer in the QH to point at the - * status TD. It's safe to do this even while the QH is live, because - * the hardware only updates the element pointer following a successful - * transfer. The inactive TD for the short packet won't cause an update, - * so the pointer won't get overwritten. The next time the controller - * sees this QH, it will send the status packet. - */ -static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td; - - urbp->short_transfer = 1; - - td = list_entry(urbp->td_list.prev, struct uhci_td, list); - urbp->qh->element = cpu_to_le32(td->dma_handle); - - return -EINPROGRESS; -} - - -static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = urb->hcpriv; - struct uhci_td *td; - unsigned int status; - int ret = 0; - - head = &urbp->td_list; - if (urbp->short_transfer) { - tmp = head->prev; - goto status_stage; - } - - urb->actual_length = 0; - - tmp = head->next; - td = list_entry(tmp, struct uhci_td, list); - - /* The first TD is the SETUP stage, check the status, but skip */ - /* the count */ - status = uhci_status_bits(td_status(td)); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - if (status) - goto td_error; - - /* The rest of the TDs (but the last) are data */ - tmp = tmp->next; - while (tmp != head && tmp->next != head) { - unsigned int ctrlstat; - - td = list_entry(tmp, struct uhci_td, list); - tmp = tmp->next; - - ctrlstat = td_status(td); - status = uhci_status_bits(ctrlstat); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - urb->actual_length += uhci_actual_length(ctrlstat); - - if (status) - goto td_error; - - /* Check to see if we received a short packet */ - if (uhci_actual_length(ctrlstat) < - uhci_expected_length(td_token(td))) { - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - ret = -EREMOTEIO; - goto err; - } - - return usb_control_retrigger_status(uhci, urb); - } - } - -status_stage: - td = list_entry(tmp, struct uhci_td, list); - - /* Control status stage */ - status = td_status(td); - -#ifdef I_HAVE_BUGGY_APC_BACKUPS - /* APC BackUPS Pro kludge */ - /* It tries to send all of the descriptor instead of the amount */ - /* we requested */ - if (status & TD_CTRL_IOC && /* IOC is masked out by uhci_status_bits */ - status & TD_CTRL_ACTIVE && - status & TD_CTRL_NAK) - return 0; -#endif - - status = uhci_status_bits(status); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - if (status) - goto td_error; - - return 0; - -td_error: - ret = uhci_map_status(status, uhci_packetout(td_token(td))); - -err: - if ((debug == 1 && ret != -EPIPE) || debug > 1) { - /* Some debugging code */ - dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", - __FUNCTION__, status); - - if (errbuf) { - /* Print the chain for debugging purposes */ - uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); - lprintk(errbuf); - } - } - - /* Note that the queue has stopped */ - urbp->qh->element = UHCI_PTR_TERM; - urbp->qh->is_stopped = 1; - return ret; -} - -/* * Common submit for bulk and interrupt */ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, @@ -756,6 +700,7 @@ static int uhci_submit_common(struct uhc int len = urb->transfer_buffer_length; dma_addr_t data = urb->transfer_dma; __le32 *plink; + struct urb_priv *urbp = urb->hcpriv; unsigned int toggle; if (len < 0) @@ -793,7 +738,7 @@ static int uhci_submit_common(struct uhc goto nomem; *plink = cpu_to_le32(td->dma_handle); } - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status, destination | uhci_explen(pktsze) | (toggle << TD_TOKEN_TOGGLE_SHIFT), @@ -821,7 +766,7 @@ static int uhci_submit_common(struct uhc goto nomem; *plink = cpu_to_le32(td->dma_handle); - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status, destination | uhci_explen(0) | (toggle << TD_TOKEN_TOGGLE_SHIFT), @@ -851,6 +796,7 @@ static int uhci_submit_common(struct uhc wmb(); qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); qh->dummy_td = td; + qh->period = urb->interval; usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), toggle); @@ -858,90 +804,10 @@ static int uhci_submit_common(struct uhc nomem: /* Remove the dummy TD from the td_list so it doesn't get freed */ - uhci_remove_td_from_urb(qh->dummy_td); + uhci_remove_td_from_urbp(qh->dummy_td); return -ENOMEM; } -/* - * Common result for bulk and interrupt - */ -static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp = urb->hcpriv; - struct uhci_td *td; - unsigned int status = 0; - int ret = 0; - - urb->actual_length = 0; - - list_for_each_entry(td, &urbp->td_list, list) { - unsigned int ctrlstat = td_status(td); - - status = uhci_status_bits(ctrlstat); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - urb->actual_length += uhci_actual_length(ctrlstat); - - if (status) - goto td_error; - - if (uhci_actual_length(ctrlstat) < - uhci_expected_length(td_token(td))) { - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - ret = -EREMOTEIO; - goto err; - } - - /* - * This URB stopped short of its end. We have to - * fix up the toggles of the following URBs on the - * queue and restart the queue. - * - * Do this only the first time we encounter the - * short URB. - */ - if (!urbp->short_transfer) { - urbp->short_transfer = 1; - urbp->qh->initial_toggle = - uhci_toggle(td_token(td)) ^ 1; - uhci_fixup_toggles(urbp->qh, 1); - - td = list_entry(urbp->td_list.prev, - struct uhci_td, list); - urbp->qh->element = td->link; - } - break; - } - } - - return 0; - -td_error: - ret = uhci_map_status(status, uhci_packetout(td_token(td))); - - if ((debug == 1 && ret != -EPIPE) || debug > 1) { - /* Some debugging code */ - dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", - __FUNCTION__, status); - - if (debug > 1 && errbuf) { - /* Print the chain for debugging purposes */ - uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); - lprintk(errbuf); - } - } -err: - - /* Note that the queue has stopped and save the next toggle value */ - urbp->qh->element = UHCI_PTR_TERM; - urbp->qh->is_stopped = 1; - urbp->qh->needs_fixup = 1; - urbp->qh->initial_toggle = uhci_toggle(td_token(td)) ^ - (ret == -EREMOTEIO); - return ret; -} - static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct uhci_qh *qh) { @@ -954,22 +820,163 @@ static inline int uhci_submit_bulk(struc qh->skel = uhci->skel_bulk_qh; ret = uhci_submit_common(uhci, urb, qh); if (ret == 0) - uhci_inc_fsbr(uhci, urb); + uhci_add_fsbr(uhci, urb); return ret; } -static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, +static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct uhci_qh *qh) { + int exponent; + /* USB 1.1 interrupt transfers only involve one packet per interval. * Drivers can submit URBs of any length, but longer ones will need * multiple intervals to complete. */ - qh->skel = uhci->skelqh[__interval_to_skel(urb->interval)]; + + /* Figure out which power-of-two queue to use */ + for (exponent = 7; exponent >= 0; --exponent) { + if ((1 << exponent) <= urb->interval) + break; + } + if (exponent < 0) + return -EINVAL; + urb->interval = 1 << exponent; + + if (qh->period == 0) + qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)]; + else if (qh->period != urb->interval) + return -EINVAL; /* Can't change the period */ + return uhci_submit_common(uhci, urb, qh); } /* + * Fix up the data structures following a short transfer + */ +static int uhci_fixup_short_transfer(struct uhci_hcd *uhci, + struct uhci_qh *qh, struct urb_priv *urbp) +{ + struct uhci_td *td; + struct list_head *tmp; + int ret; + + td = list_entry(urbp->td_list.prev, struct uhci_td, list); + if (qh->type == USB_ENDPOINT_XFER_CONTROL) { + + /* When a control transfer is short, we have to restart + * the queue at the status stage transaction, which is + * the last TD. */ + WARN_ON(list_empty(&urbp->td_list)); + qh->element = cpu_to_le32(td->dma_handle); + tmp = td->list.prev; + ret = -EINPROGRESS; + + } else { + + /* When a bulk/interrupt transfer is short, we have to + * fix up the toggles of the following URBs on the queue + * before restarting the queue at the next URB. */ + qh->initial_toggle = uhci_toggle(td_token(qh->post_td)) ^ 1; + uhci_fixup_toggles(qh, 1); + + if (list_empty(&urbp->td_list)) + td = qh->post_td; + qh->element = td->link; + tmp = urbp->td_list.prev; + ret = 0; + } + + /* Remove all the TDs we skipped over, from tmp back to the start */ + while (tmp != &urbp->td_list) { + td = list_entry(tmp, struct uhci_td, list); + tmp = tmp->prev; + + uhci_remove_td_from_urbp(td); + uhci_free_td(uhci, td); + } + return ret; +} + +/* + * Common result for control, bulk, and interrupt + */ +static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) +{ + struct urb_priv *urbp = urb->hcpriv; + struct uhci_qh *qh = urbp->qh; + struct uhci_td *td, *tmp; + unsigned status; + int ret = 0; + + list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { + unsigned int ctrlstat; + int len; + + ctrlstat = td_status(td); + status = uhci_status_bits(ctrlstat); + if (status & TD_CTRL_ACTIVE) + return -EINPROGRESS; + + len = uhci_actual_length(ctrlstat); + urb->actual_length += len; + + if (status) { + ret = uhci_map_status(status, + uhci_packetout(td_token(td))); + if ((debug == 1 && ret != -EPIPE) || debug > 1) { + /* Some debugging code */ + dev_dbg(&urb->dev->dev, + "%s: failed with status %x\n", + __FUNCTION__, status); + + if (debug > 1 && errbuf) { + /* Print the chain for debugging */ + uhci_show_qh(urbp->qh, errbuf, + ERRBUF_LEN, 0); + lprintk(errbuf); + } + } + + } else if (len < uhci_expected_length(td_token(td))) { + + /* We received a short packet */ + if (urb->transfer_flags & URB_SHORT_NOT_OK) + ret = -EREMOTEIO; + else if (ctrlstat & TD_CTRL_SPD) + ret = 1; + } + + uhci_remove_td_from_urbp(td); + if (qh->post_td) + uhci_free_td(uhci, qh->post_td); + qh->post_td = td; + + if (ret != 0) + goto err; + } + return ret; + +err: + if (ret < 0) { + /* In case a control transfer gets an error + * during the setup stage */ + urb->actual_length = max(urb->actual_length, 0); + + /* Note that the queue has stopped and save + * the next toggle value */ + qh->element = UHCI_PTR_TERM; + qh->is_stopped = 1; + qh->needs_fixup = (qh->type != USB_ENDPOINT_XFER_CONTROL); + qh->initial_toggle = uhci_toggle(td_token(td)) ^ + (ret == -EREMOTEIO); + + } else /* Short packet received */ + ret = uhci_fixup_short_transfer(uhci, qh, urbp); + return ret; +} + +/* * Isochronous transfers */ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, @@ -980,38 +987,57 @@ static int uhci_submit_isochronous(struc unsigned long destination, status; struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - if (urb->number_of_packets > 900) /* 900? Why? */ + /* Values must not be too big (could overflow below) */ + if (urb->interval >= UHCI_NUMFRAMES || + urb->number_of_packets >= UHCI_NUMFRAMES) return -EFBIG; - status = TD_CTRL_ACTIVE | TD_CTRL_IOS; - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); - - /* Figure out the starting frame number */ - if (urb->transfer_flags & URB_ISO_ASAP) { - if (list_empty(&qh->queue)) { + /* Check the period and figure out the starting frame number */ + if (qh->period == 0) { + if (urb->transfer_flags & URB_ISO_ASAP) { uhci_get_current_frame_number(uhci); - urb->start_frame = (uhci->frame_number + 10); + urb->start_frame = uhci->frame_number + 10; + } else { + i = urb->start_frame - uhci->last_iso_frame; + if (i <= 0 || i >= UHCI_NUMFRAMES) + return -EINVAL; + } + } else if (qh->period != urb->interval) { + return -EINVAL; /* Can't change the period */ - } else { /* Go right after the last one */ - struct urb *last_urb; + } else { /* Pick up where the last URB leaves off */ + if (list_empty(&qh->queue)) { + frame = qh->iso_frame; + } else { + struct urb *lurb; - last_urb = list_entry(qh->queue.prev, + lurb = list_entry(qh->queue.prev, struct urb_priv, node)->urb; - urb->start_frame = (last_urb->start_frame + - last_urb->number_of_packets * - last_urb->interval); + frame = lurb->start_frame + + lurb->number_of_packets * + lurb->interval; } - } else { - /* FIXME: Sanity check */ + if (urb->transfer_flags & URB_ISO_ASAP) + urb->start_frame = frame; + else if (urb->start_frame != frame) + return -EINVAL; } - urb->start_frame &= (UHCI_NUMFRAMES - 1); + + /* Make sure we won't have to go too far into the future */ + if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES, + urb->start_frame + urb->number_of_packets * + urb->interval)) + return -EFBIG; + + status = TD_CTRL_ACTIVE | TD_CTRL_IOS; + destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); for (i = 0; i < urb->number_of_packets; i++) { td = uhci_alloc_td(uhci); if (!td) return -ENOMEM; - uhci_add_td_to_urb(urb, td); + uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length), urb->transfer_dma + @@ -1022,12 +1048,19 @@ static int uhci_submit_isochronous(struc td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); qh->skel = uhci->skel_iso_qh; + qh->period = urb->interval; /* Add the TDs to the frame list */ frame = urb->start_frame; list_for_each_entry(td, &urbp->td_list, list) { uhci_insert_td_in_frame_list(uhci, td, frame); - frame += urb->interval; + frame += qh->period; + } + + if (list_empty(&qh->queue)) { + qh->iso_packet_desc = &urb->iso_frame_desc[0]; + qh->iso_frame = urb->start_frame; + qh->iso_status = 0; } return 0; @@ -1035,37 +1068,44 @@ static int uhci_submit_isochronous(struc static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) { - struct uhci_td *td; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - int status; - int i, ret = 0; - - urb->actual_length = urb->error_count = 0; + struct uhci_td *td, *tmp; + struct urb_priv *urbp = urb->hcpriv; + struct uhci_qh *qh = urbp->qh; - i = 0; - list_for_each_entry(td, &urbp->td_list, list) { + list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { + unsigned int ctrlstat; + int status; int actlength; - unsigned int ctrlstat = td_status(td); - if (ctrlstat & TD_CTRL_ACTIVE) + if (uhci_frame_before_eq(uhci->cur_iso_frame, qh->iso_frame)) return -EINPROGRESS; - actlength = uhci_actual_length(ctrlstat); - urb->iso_frame_desc[i].actual_length = actlength; - urb->actual_length += actlength; + uhci_remove_tds_from_frame(uhci, qh->iso_frame); + + ctrlstat = td_status(td); + if (ctrlstat & TD_CTRL_ACTIVE) { + status = -EXDEV; /* TD was added too late? */ + } else { + status = uhci_map_status(uhci_status_bits(ctrlstat), + usb_pipeout(urb->pipe)); + actlength = uhci_actual_length(ctrlstat); + + urb->actual_length += actlength; + qh->iso_packet_desc->actual_length = actlength; + qh->iso_packet_desc->status = status; + } - status = uhci_map_status(uhci_status_bits(ctrlstat), - usb_pipeout(urb->pipe)); - urb->iso_frame_desc[i].status = status; if (status) { urb->error_count++; - ret = status; + qh->iso_status = status; } - i++; + uhci_remove_td_from_urbp(td); + uhci_free_td(uhci, td); + qh->iso_frame += qh->period; + ++qh->iso_packet_desc; } - - return ret; + return qh->iso_status; } static int uhci_urb_enqueue(struct usb_hcd *hcd, @@ -1099,14 +1139,14 @@ static int uhci_urb_enqueue(struct usb_h } urbp->qh = qh; - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: + switch (qh->type) { + case USB_ENDPOINT_XFER_CONTROL: ret = uhci_submit_control(uhci, urb, qh); break; - case PIPE_BULK: + case USB_ENDPOINT_XFER_BULK: ret = uhci_submit_bulk(uhci, urb, qh); break; - case PIPE_INTERRUPT: + case USB_ENDPOINT_XFER_INT: if (list_empty(&qh->queue)) { bustime = usb_check_bandwidth(urb->dev, urb); if (bustime < 0) @@ -1125,7 +1165,8 @@ static int uhci_urb_enqueue(struct usb_h ret = uhci_submit_interrupt(uhci, urb, qh); } break; - case PIPE_ISOCHRONOUS: + case USB_ENDPOINT_XFER_ISOC: + urb->error_count = 0; bustime = usb_check_bandwidth(urb->dev, urb); if (bustime < 0) { ret = bustime; @@ -1146,9 +1187,12 @@ static int uhci_urb_enqueue(struct usb_h /* If the new URB is the first and only one on this QH then either * the QH is new and idle or else it's unlinked and waiting to - * become idle, so we can activate it right away. */ - if (qh->queue.next == &urbp->node) + * become idle, so we can activate it right away. But only if the + * queue isn't stopped. */ + if (qh->queue.next == &urbp->node && !qh->is_stopped) { uhci_activate_qh(uhci, qh); + uhci_urbp_wants_fsbr(uhci, urbp); + } goto done; err_submit_failed: @@ -1168,16 +1212,26 @@ static int uhci_urb_dequeue(struct usb_h struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned long flags; struct urb_priv *urbp; + struct uhci_qh *qh; spin_lock_irqsave(&uhci->lock, flags); urbp = urb->hcpriv; if (!urbp) /* URB was never linked! */ goto done; + qh = urbp->qh; /* Remove Isochronous TDs from the frame list ASAP */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) + if (qh->type == USB_ENDPOINT_XFER_ISOC) { uhci_unlink_isochronous_tds(uhci, urb); - uhci_unlink_qh(uhci, urbp->qh); + mb(); + + /* If the URB has already started, update the QH unlink time */ + uhci_get_current_frame_number(uhci); + if (uhci_frame_before_eq(urb->start_frame, uhci->frame_number)) + qh->unlink_frame = uhci->frame_number; + } + + uhci_unlink_qh(uhci, qh); done: spin_unlock_irqrestore(&uhci->lock, flags); @@ -1194,22 +1248,17 @@ __acquires(uhci->lock) { struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - /* Isochronous TDs get unlinked directly from the frame list */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) - uhci_unlink_isochronous_tds(uhci, urb); - - /* If the URB isn't first on its queue, adjust the link pointer - * of the last TD in the previous URB. */ - else if (qh->queue.next != &urbp->node) { - struct urb_priv *purbp; - struct uhci_td *ptd, *ltd; - - purbp = list_entry(urbp->node.prev, struct urb_priv, node); - ptd = list_entry(purbp->td_list.prev, struct uhci_td, - list); - ltd = list_entry(urbp->td_list.prev, struct uhci_td, - list); - ptd->link = ltd->link; + /* When giving back the first URB in an Isochronous queue, + * reinitialize the QH's iso-related members for the next URB. */ + if (qh->type == USB_ENDPOINT_XFER_ISOC && + urbp->node.prev == &qh->queue && + urbp->node.next != &qh->queue) { + struct urb *nurb = list_entry(urbp->node.next, + struct urb_priv, node)->urb; + + qh->iso_packet_desc = &nurb->iso_frame_desc[0]; + qh->iso_frame = nurb->start_frame; + qh->iso_status = 0; } /* Take the URB off the QH's queue. If the queue is now empty, @@ -1221,16 +1270,15 @@ __acquires(uhci->lock) qh->needs_fixup = 0; } - uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ uhci_free_urb_priv(uhci, urbp); - switch (usb_pipetype(urb->pipe)) { - case PIPE_ISOCHRONOUS: + switch (qh->type) { + case USB_ENDPOINT_XFER_ISOC: /* Release bandwidth for Interrupt or Isoc. transfers */ if (urb->bandwidth) usb_release_bandwidth(urb->dev, urb, 1); break; - case PIPE_INTERRUPT: + case USB_ENDPOINT_XFER_INT: /* Release bandwidth for Interrupt or Isoc. transfers */ /* Make sure we don't release if we have a queued URB */ if (list_empty(&qh->queue) && urb->bandwidth) @@ -1252,6 +1300,7 @@ __acquires(uhci->lock) uhci_unlink_qh(uhci, qh); /* Bandwidth stuff not yet implemented */ + qh->period = 0; } } @@ -1273,17 +1322,10 @@ static void uhci_scan_qh(struct uhci_hcd urbp = list_entry(qh->queue.next, struct urb_priv, node); urb = urbp->urb; - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: - status = uhci_result_control(uhci, urb); - break; - case PIPE_ISOCHRONOUS: + if (qh->type == USB_ENDPOINT_XFER_ISOC) status = uhci_result_isochronous(uhci, urb); - break; - default: /* PIPE_BULK or PIPE_INTERRUPT */ + else status = uhci_result_common(uhci, urb); - break; - } if (status == -EINPROGRESS) break; @@ -1291,31 +1333,43 @@ static void uhci_scan_qh(struct uhci_hcd if (urb->status == -EINPROGRESS) /* Not dequeued */ urb->status = status; else - status = -ECONNRESET; + status = ECONNRESET; /* Not -ECONNRESET */ spin_unlock(&urb->lock); /* Dequeued but completed URBs can't be given back unless * the QH is stopped or has finished unlinking. */ - if (status == -ECONNRESET && - !(qh->is_stopped || QH_FINISHED_UNLINKING(qh))) - return; + if (status == ECONNRESET) { + if (QH_FINISHED_UNLINKING(qh)) + qh->is_stopped = 1; + else if (!qh->is_stopped) + return; + } uhci_giveback_urb(uhci, qh, urb, regs); - if (qh->is_stopped) + if (status < 0) break; } /* If the QH is neither stopped nor finished unlinking (normal case), * our work here is done. */ - restart: - if (!(qh->is_stopped || QH_FINISHED_UNLINKING(qh))) + if (QH_FINISHED_UNLINKING(qh)) + qh->is_stopped = 1; + else if (!qh->is_stopped) return; /* Otherwise give back each of the dequeued URBs */ +restart: list_for_each_entry(urbp, &qh->queue, node) { urb = urbp->urb; if (urb->status != -EINPROGRESS) { - uhci_save_toggle(qh, urb); + + /* Fix up the TD links and save the toggles for + * non-Isochronous queues. For Isochronous queues, + * test for too-recent dequeues. */ + if (!uhci_cleanup_queue(uhci, qh, urb)) { + qh->is_stopped = 0; + return; + } uhci_giveback_urb(uhci, qh, urb, regs); goto restart; } @@ -1327,6 +1381,18 @@ static void uhci_scan_qh(struct uhci_hcd if (!list_empty(&qh->queue)) { if (qh->needs_fixup) uhci_fixup_toggles(qh, 0); + + /* If the first URB on the queue wants FSBR but its time + * limit has expired, set the next TD to interrupt on + * completion before reactivating the QH. */ + urbp = list_entry(qh->queue.next, struct urb_priv, node); + if (urbp->fsbr && qh->wait_expired) { + struct uhci_td *td = list_entry(urbp->td_list.next, + struct uhci_td, list); + + td->status |= __cpu_to_le32(TD_CTRL_IOC); + } + uhci_activate_qh(uhci, qh); } @@ -1336,15 +1402,84 @@ static void uhci_scan_qh(struct uhci_hcd uhci_make_qh_idle(uhci, qh); } -static void uhci_free_pending_tds(struct uhci_hcd *uhci) +/* + * Check for queues that have made some forward progress. + * Returns 0 if the queue is not Isochronous, is ACTIVE, and + * has not advanced since last examined; 1 otherwise. + * + * Early Intel controllers have a bug which causes qh->element sometimes + * not to advance when a TD completes successfully. The queue remains + * stuck on the inactive completed TD. We detect such cases and advance + * the element pointer by hand. + */ +static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) { - struct uhci_td *td, *tmp; + struct urb_priv *urbp = NULL; + struct uhci_td *td; + int ret = 1; + unsigned status; - list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) { - list_del_init(&td->remove_list); + if (qh->type == USB_ENDPOINT_XFER_ISOC) + goto done; - uhci_free_td(uhci, td); + /* Treat an UNLINKING queue as though it hasn't advanced. + * This is okay because reactivation will treat it as though + * it has advanced, and if it is going to become IDLE then + * this doesn't matter anyway. Furthermore it's possible + * for an UNLINKING queue not to have any URBs at all, or + * for its first URB not to have any TDs (if it was dequeued + * just as it completed). So it's not easy in any case to + * test whether such queues have advanced. */ + if (qh->state != QH_STATE_ACTIVE) { + urbp = NULL; + status = 0; + + } else { + urbp = list_entry(qh->queue.next, struct urb_priv, node); + td = list_entry(urbp->td_list.next, struct uhci_td, list); + status = td_status(td); + if (!(status & TD_CTRL_ACTIVE)) { + + /* We're okay, the queue has advanced */ + qh->wait_expired = 0; + qh->advance_jiffies = jiffies; + goto done; + } + ret = 0; + } + + /* The queue hasn't advanced; check for timeout */ + if (qh->wait_expired) + goto done; + + if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) { + + /* Detect the Intel bug and work around it */ + if (qh->post_td && qh_element(qh) == + cpu_to_le32(qh->post_td->dma_handle)) { + qh->element = qh->post_td->link; + qh->advance_jiffies = jiffies; + ret = 1; + goto done; + } + + qh->wait_expired = 1; + + /* If the current URB wants FSBR, unlink it temporarily + * so that we can safely set the next TD to interrupt on + * completion. That way we'll know as soon as the queue + * starts moving again. */ + if (urbp && urbp->fsbr && !(status & TD_CTRL_IOC)) + uhci_unlink_qh(uhci, qh); + + } else { + /* Unmoving but not-yet-expired queues keep FSBR alive */ + if (urbp) + uhci_urbp_wants_fsbr(uhci, urbp); } + +done: + return ret; } /* @@ -1361,14 +1496,13 @@ static void uhci_scan_schedule(struct uh return; } uhci->scan_in_progress = 1; - rescan: +rescan: uhci->need_rescan = 0; + uhci->fsbr_is_wanted = 0; uhci_clear_next_interrupt(uhci); uhci_get_current_frame_number(uhci); - - if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) - uhci_free_pending_tds(uhci); + uhci->cur_iso_frame = uhci->frame_number; /* Go through all the QH queues and process the URBs in each one */ for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) { @@ -1377,33 +1511,30 @@ static void uhci_scan_schedule(struct uh while ((qh = uhci->next_qh) != uhci->skelqh[i]) { uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, node); - uhci_scan_qh(uhci, qh, regs); + + if (uhci_advance_check(uhci, qh)) { + uhci_scan_qh(uhci, qh, regs); + if (qh->state == QH_STATE_ACTIVE) { + uhci_urbp_wants_fsbr(uhci, + list_entry(qh->queue.next, struct urb_priv, node)); + } + } } } + uhci->last_iso_frame = uhci->cur_iso_frame; if (uhci->need_rescan) goto rescan; uhci->scan_in_progress = 0; - /* If the controller is stopped, we can finish these off right now */ - if (uhci->is_stopped) - uhci_free_pending_tds(uhci); + if (uhci->fsbr_is_on && !uhci->fsbr_is_wanted && + !uhci->fsbr_expiring) { + uhci->fsbr_expiring = 1; + mod_timer(&uhci->fsbr_timer, jiffies + FSBR_OFF_DELAY); + } - if (list_empty(&uhci->td_remove_list) && - list_empty(&uhci->skel_unlink_qh->node)) + if (list_empty(&uhci->skel_unlink_qh->node)) uhci_clear_next_interrupt(uhci); else uhci_set_next_interrupt(uhci); } - -static void check_fsbr(struct uhci_hcd *uhci) -{ - /* For now, don't scan URBs for FSBR timeouts. - * Add it back in later... */ - - /* Really disable FSBR */ - if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { - uhci->fsbrtimeout = 0; - uhci->skel_term_qh->link = UHCI_PTR_TERM; - } -} diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 2a0e18a..b2bafc3 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -513,7 +513,7 @@ static void mts_do_sg (struct urb* trans mts_transfer_cleanup(transfer); } - sg = context->srb->buffer; + sg = context->srb->request_buffer; context->fragment++; mts_int_submit_urb(transfer, context->data_pipe, @@ -549,19 +549,19 @@ mts_build_transfer_context( Scsi_Cmnd *s desc->context.fragment = 0; if (!srb->use_sg) { - if ( !srb->bufflen ){ + if ( !srb->request_bufflen ){ desc->context.data = NULL; desc->context.data_length = 0; return; } else { - desc->context.data = srb->buffer; - desc->context.data_length = srb->bufflen; + desc->context.data = srb->request_buffer; + desc->context.data_length = srb->request_bufflen; MTS_DEBUG("length = %d or %d\n", srb->request_bufflen, srb->bufflen); } } else { MTS_DEBUG("Using scatter/gather\n"); - sg = srb->buffer; + sg = srb->request_buffer; desc->context.data = page_address(sg[0].page) + sg[0].offset; desc->context.data_length = sg[0].length; } diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c index df29b80..18c10e1 100644 --- a/drivers/usb/input/acecad.c +++ b/drivers/usb/input/acecad.c @@ -27,11 +27,9 @@ #include #include -#include #include #include -#include -#include +#include /* * Version Information diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c index a6693b0..b138dae 100644 --- a/drivers/usb/input/aiptek.c +++ b/drivers/usb/input/aiptek.c @@ -73,11 +73,9 @@ #include #include #include -#include #include #include -#include -#include +#include #include #include #include diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c index c222ed1..3685506 100644 --- a/drivers/usb/input/appletouch.c +++ b/drivers/usb/input/appletouch.c @@ -1,5 +1,5 @@ /* - * Apple USB Touchpad (for post-February 2005 PowerBooks) driver + * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver * * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) @@ -7,6 +7,7 @@ * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) + * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) * * Thanks to Alex Harper for his inputs. * @@ -32,9 +33,7 @@ #include #include #include #include -#include -#include -#include +#include /* Apple has powerbooks which have the keyboard with different Product IDs */ #define APPLE_VENDOR_ID 0x05AC @@ -44,6 +43,11 @@ #define GEYSER_ANSI_PRODUCT_ID 0x0214 #define GEYSER_ISO_PRODUCT_ID 0x0215 #define GEYSER_JIS_PRODUCT_ID 0x0216 +/* MacBook devices */ +#define GEYSER3_ANSI_PRODUCT_ID 0x0217 +#define GEYSER3_ISO_PRODUCT_ID 0x0218 +#define GEYSER3_JIS_PRODUCT_ID 0x0219 + #define ATP_DEVICE(prod) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ USB_DEVICE_ID_MATCH_INT_CLASS | \ @@ -65,6 +69,10 @@ static struct usb_device_id atp_table [] { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) }, + /* Terminating entry */ { } }; @@ -101,6 +109,13 @@ #define ATP_YFACT 43 */ #define ATP_THRESHOLD 5 +/* MacBook Pro (Geyser 3) initialization constants */ +#define ATP_GEYSER3_MODE_READ_REQUEST_ID 1 +#define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9 +#define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300 +#define ATP_GEYSER3_MODE_REQUEST_INDEX 0 +#define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04 + /* Structure to hold all of our device specific stuff */ struct atp { char phys[64]; @@ -147,13 +162,22 @@ MODULE_PARM_DESC(debug, "Activate debugg /* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ static inline int atp_is_geyser_2(struct atp *dev) { - int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct); + u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); return (productId == GEYSER_ANSI_PRODUCT_ID) || (productId == GEYSER_ISO_PRODUCT_ID) || (productId == GEYSER_JIS_PRODUCT_ID); } +static inline int atp_is_geyser_3(struct atp *dev) +{ + u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); + + return (productId == GEYSER3_ANSI_PRODUCT_ID) || + (productId == GEYSER3_ISO_PRODUCT_ID) || + (productId == GEYSER3_JIS_PRODUCT_ID); +} + static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, int *z, int *fingers) { @@ -219,12 +243,33 @@ static void atp_complete(struct urb* urb /* drop incomplete datasets */ if (dev->urb->actual_length != dev->datalen) { - dprintk("appletouch: incomplete data package.\n"); + dprintk("appletouch: incomplete data package" + " (first byte: %d, length: %d).\n", + dev->data[0], dev->urb->actual_length); goto exit; } /* reorder the sensors values */ - if (atp_is_geyser_2(dev)) { + if (atp_is_geyser_3(dev)) { + memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); + + /* + * The values are laid out like this: + * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... + * '-' is an unused value. + */ + + /* read X values */ + for (i = 0, j = 19; i < 20; i += 2, j += 3) { + dev->xy_cur[i] = dev->data[j + 1]; + dev->xy_cur[i + 1] = dev->data[j + 2]; + } + /* read Y values */ + for (i = 0, j = 1; i < 9; i += 2, j += 3) { + dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; + dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; + } + } else if (atp_is_geyser_2(dev)) { memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); /* @@ -267,6 +312,9 @@ static void atp_complete(struct urb* urb dev->x_old = dev->y_old = -1; memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); + if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */ + goto exit; + /* 17" Powerbooks have extra X sensors */ for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { if (!dev->xy_cur[i]) continue; @@ -414,7 +462,50 @@ static int atp_probe(struct usb_interfac dev->udev = udev; dev->input = input_dev; dev->overflowwarn = 0; - dev->datalen = (atp_is_geyser_2(dev)?64:81); + if (atp_is_geyser_3(dev)) + dev->datalen = 64; + else if (atp_is_geyser_2(dev)) + dev->datalen = 64; + else + dev->datalen = 81; + + if (atp_is_geyser_3(dev)) { + /* + * By default Geyser 3 device sends standard USB HID mouse + * packets (Report ID 2). This code changes device mode, so it + * sends raw sensor reports (Report ID 5). + */ + char data[8]; + int size; + + size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ATP_GEYSER3_MODE_READ_REQUEST_ID, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + ATP_GEYSER3_MODE_REQUEST_VALUE, + ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); + + if (size != 8) { + err("Could not do mode read request from device" + " (Geyser 3 mode)"); + goto err_free_devs; + } + + /* Apply the mode switch */ + data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE; + + size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + ATP_GEYSER3_MODE_WRITE_REQUEST_ID, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + ATP_GEYSER3_MODE_REQUEST_VALUE, + ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); + + if (size != 8) { + err("Could not do mode write request to device" + " (Geyser 3 mode)"); + goto err_free_devs; + } + printk("appletouch Geyser 3 inited.\n"); + } dev->urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->urb) { @@ -447,7 +538,15 @@ static int atp_probe(struct usb_interfac set_bit(EV_ABS, input_dev->evbit); - if (atp_is_geyser_2(dev)) { + if (atp_is_geyser_3(dev)) { + /* + * MacBook have 20 X sensors, 10 Y sensors + */ + input_set_abs_params(input_dev, ABS_X, 0, + ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0); + input_set_abs_params(input_dev, ABS_Y, 0, + ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0); + } else if (atp_is_geyser_2(dev)) { /* * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected * later. diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 99f986c..07c8c0e 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -92,9 +92,7 @@ #include #include #include #include -#include -#include -#include +#include #include #include diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c index ab1a1ae..ea71de8 100644 --- a/drivers/usb/input/ati_remote2.c +++ b/drivers/usb/input/ati_remote2.c @@ -8,7 +8,7 @@ * as published by the Free Software Foundation. */ -#include +#include #define DRIVER_DESC "ATI/Philips USB RF remote driver" #define DRIVER_VERSION "0.1" diff --git a/drivers/usb/input/fixp-arith.h b/drivers/usb/input/fixp-arith.h index b44d398..ed3d2da 100644 --- a/drivers/usb/input/fixp-arith.h +++ b/drivers/usb/input/fixp-arith.h @@ -2,8 +2,6 @@ #ifndef _FIXP_ARITH_H #define _FIXP_ARITH_H /* - * $$ - * * Simplistic fixed-point arithmetics. * Hmm, I'm probably duplicating some code :( * @@ -31,20 +29,20 @@ #define _FIXP_ARITH_H #include -// The type representing fixed-point values +/* The type representing fixed-point values */ typedef s16 fixp_t; #define FRAC_N 8 #define FRAC_MASK ((1<>= 1; diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 435273e..b9fb968 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -944,21 +944,28 @@ static void hid_reset(void *_hid) dev_dbg(&hid->intf->dev, "resetting device\n"); rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf); if (rc_lock >= 0) { - rc = usb_reset_device(hid->dev); + rc = usb_reset_composite_device(hid->dev, hid->intf); if (rc_lock) usb_unlock_device(hid->dev); } clear_bit(HID_RESET_PENDING, &hid->iofl); - if (rc == 0) { - hid->retry_delay = 0; - if (hid_start_in(hid)) + switch (rc) { + case 0: + if (!test_bit(HID_IN_RUNNING, &hid->iofl)) hid_io_error(hid); - } else if (!(rc == -ENODEV || rc == -EHOSTUNREACH || rc == -EINTR)) + break; + default: err("can't reset device, %s-%s/input%d, status %d", hid->dev->bus->bus_name, hid->dev->devpath, hid->ifnum, rc); + /* FALLTHROUGH */ + case -EHOSTUNREACH: + case -ENODEV: + case -EINTR: + break; + } } /* Main I/O error handler */ @@ -1374,9 +1381,6 @@ void hid_close(struct hid_device *hid) #define USB_VENDOR_ID_PANJIT 0x134c -#define USB_VENDOR_ID_SILVERCREST 0x062a -#define USB_DEVICE_ID_SILVERCREST_KB 0x0201 - /* * Initialize all reports */ @@ -1461,9 +1465,6 @@ #define USB_DEVICE_ID_MGE_UPS1 0x0001 #define USB_VENDOR_ID_ONTRAK 0x0a07 #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 -#define USB_VENDOR_ID_TANGTOP 0x0d3d -#define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001 - #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 @@ -1520,12 +1521,6 @@ #define USB_VENDOR_ID_MCC 0x09db #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a -#define USB_VENDOR_ID_CHICONY 0x04f2 -#define USB_DEVICE_ID_CHICONY_USBHUB_KB 0x0100 - -#define USB_VENDOR_ID_BTC 0x046e -#define USB_DEVICE_ID_BTC_KEYBOARD 0x5303 - #define USB_VENDOR_ID_VERNIER 0x08f7 #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 @@ -1549,20 +1544,13 @@ #define USB_DEVICE_ID_LD_POWERCONTROL 0x #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 #define USB_VENDOR_ID_APPLE 0x05ac -#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 +#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 #define USB_VENDOR_ID_CHERRY 0x046a #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 -#define USB_VENDOR_ID_HP 0x03f0 -#define USB_DEVICE_ID_HP_USBHUB_KB 0x020c - -#define USB_VENDOR_ID_IBM 0x04b3 -#define USB_DEVICE_ID_IBM_USBHUB_KB 0x3005 - -#define USB_VENDOR_ID_CREATIVELABS 0x062a -#define USB_DEVICE_ID_CREATIVELABS_SILVERCREST 0x0201 - +#define USB_VENDOR_ID_YEALINK 0x6993 +#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 /* * Alphabetically sorted blacklist by quirk type. */ @@ -1671,6 +1659,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, @@ -1680,16 +1669,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET}, - { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET}, - { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVELABS_SILVERCREST, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_USBHUB_KB, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, @@ -1711,6 +1693,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, @@ -1794,6 +1779,14 @@ static struct hid_device *usb_hid_config (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct))) quirks = hid_blacklist[n].quirks; + /* Many keyboards and mice don't like to be polled for reports, + * so we will always set the HID_QUIRK_NOGET flag for them. */ + if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { + if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD || + interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) + quirks |= HID_QUIRK_NOGET; + } + if (quirks & HID_QUIRK_IGNORE) return NULL; @@ -2080,11 +2073,29 @@ static int hid_resume(struct usb_interfa int status; clear_bit(HID_SUSPENDED, &hid->iofl); + hid->retry_delay = 0; status = hid_start_in(hid); dev_dbg(&intf->dev, "resume status %d\n", status); return status; } +/* Treat USB reset pretty much the same as suspend/resume */ +static void hid_pre_reset(struct usb_interface *intf) +{ + /* FIXME: What if the interface is already suspended? */ + hid_suspend(intf, PMSG_ON); +} + +static void hid_post_reset(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev (intf); + + hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); + /* FIXME: Any more reinitialization needed? */ + + hid_resume(intf); +} + static struct usb_device_id hid_usb_ids [] = { { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, .bInterfaceClass = USB_INTERFACE_CLASS_HID }, @@ -2099,6 +2110,8 @@ static struct usb_driver hid_driver = { .disconnect = hid_disconnect, .suspend = hid_suspend, .resume = hid_resume, + .pre_reset = hid_pre_reset, + .post_reset = hid_post_reset, .id_table = hid_usb_ids, }; diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h index 702c48c..f04d6d7 100644 --- a/drivers/usb/input/hid-debug.h +++ b/drivers/usb/input/hid-debug.h @@ -563,7 +563,7 @@ static char *keys[KEY_MAX + 1] = { [KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power", [KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus", [KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma", - [KEY_HANGUEL] = "Hanguel", [KEY_HANJA] = "Hanja", + [KEY_HANGUEL] = "Hangeul", [KEY_HANJA] = "Hanja", [KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta", [KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose", [KEY_STOP] = "Stop", [KEY_AGAIN] = "Again", diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 25bc85f..028e1ad 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -29,9 +29,7 @@ #include #include #include -#include -#include -#include +#include #undef DEBUG @@ -567,16 +565,14 @@ #endif break; } - set_bit(usage->type, input->evbit); - - while (usage->code <= max && test_and_set_bit(usage->code, bit)) - usage->code = find_next_zero_bit(bit, max + 1, usage->code); - - if (usage->code > max) - goto ignore; - - if (((device->quirks & (HID_QUIRK_2WHEEL_POWERMOUSE)) && (usage->hid == 0x00010032))) - map_rel(REL_HWHEEL); + if (device->quirks & HID_QUIRK_MIGHTYMOUSE) { + if (usage->hid == HID_GD_Z) + map_rel(REL_HWHEEL); + else if (usage->code == BTN_1) + map_key(BTN_2); + else if (usage->code == BTN_2) + map_key(BTN_1); + } if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && (usage->type == EV_REL) && (usage->code == REL_WHEEL)) @@ -586,6 +582,15 @@ #endif || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) goto ignore; + set_bit(usage->type, input->evbit); + + while (usage->code <= max && test_and_set_bit(usage->code, bit)) + usage->code = find_next_zero_bit(bit, max + 1, usage->code); + + if (usage->code > max) + goto ignore; + + if (usage->type == EV_ABS) { int a = field->logical_minimum; @@ -647,6 +652,11 @@ void hidinput_hid_event(struct hid_devic return; } + if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) { + input_event(input, usage->type, usage->code, -value); + return; + } + if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { input_event(input, usage->type, REL_HWHEEL, value); return; diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 9c62837..778e575 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h @@ -41,6 +41,14 @@ #include #define USB_INTERFACE_CLASS_HID 3 /* + * USB HID interface subclass and protocol codes + */ + +#define USB_INTERFACE_SUBCLASS_BOOT 1 +#define USB_INTERFACE_PROTOCOL_KEYBOARD 1 +#define USB_INTERFACE_PROTOCOL_MOUSE 2 + +/* * HID class requests */ @@ -247,10 +255,11 @@ #define HID_QUIRK_MULTI_INPUT 0x000000 #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 -#define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400 +#define HID_QUIRK_MIGHTYMOUSE 0x00000400 #define HID_QUIRK_CYMOTION 0x00000800 #define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 #define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 +#define HID_QUIRK_INVERT_HWHEEL 0x00004000 /* * This is the global environment of the parser. This information is diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c index 7618ae5..5c570cc 100644 --- a/drivers/usb/input/itmtouch.c +++ b/drivers/usb/input/itmtouch.c @@ -42,11 +42,9 @@ #include #include #include -#include #include #include -#include -#include +#include /* only an 8 byte buffer necessary for a single packet */ #define ITM_BUFSIZE 8 diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c index f6d5cea..604ade3 100644 --- a/drivers/usb/input/kbtab.c +++ b/drivers/usb/input/kbtab.c @@ -1,12 +1,9 @@ #include #include -#include #include #include -#include -#include +#include #include -#include /* * Version Information diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c index 3d91197..70af985 100644 --- a/drivers/usb/input/keyspan_remote.c +++ b/drivers/usb/input/keyspan_remote.c @@ -18,9 +18,7 @@ #include #include #include #include -#include -#include -#include +#include #define DRIVER_VERSION "v0.1" #define DRIVER_AUTHOR "Michael Downey " diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index f018953..4fdee4d 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c @@ -42,11 +42,9 @@ #include #include #include -#include #include #include -#include -#include +#include #define MTOUCHUSB_MIN_XC 0x0 #define MTOUCHUSB_MAX_RAW_XC 0x4000 diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index fdf0f78..b3c0d0c 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c @@ -30,12 +30,10 @@ #include #include -#include #include #include #include -#include -#include +#include #define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ #define POWERMATE_PRODUCT_NEW 0x0410 /* Griffin PowerMate */ diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index 697c5e5..da7b0bf 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c @@ -27,11 +27,9 @@ #include #include #include -#include #include #include -#include -#include +#include #define TOUCHKIT_MIN_XC 0x0 #define TOUCHKIT_MAX_XC 0x07ff diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index 2f3edc2..5067a6a 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c @@ -29,10 +29,8 @@ #include #include #include -#include #include -#include -#include +#include /* * Version Information diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index af52613..446935b 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c @@ -28,11 +28,9 @@ #include #include -#include #include #include -#include -#include +#include /* * Version Information diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c index e9a07c1..3b175aa 100644 --- a/drivers/usb/input/usbtouchscreen.c +++ b/drivers/usb/input/usbtouchscreen.c @@ -39,7 +39,7 @@ #include #include #include #include -#include +#include #define DRIVER_VERSION "v0.3" diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index cf84c60..369461a 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c @@ -69,13 +69,10 @@ #include #include -#include #include #include -#include -#include +#include #include -#include /* * Version Information diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index e278489..cfd4a4e 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c @@ -56,13 +56,11 @@ #include #include -#include #include #include #include #include -#include -#include +#include #define DRIVER_VERSION "v0.0.5" #define DRIVER_AUTHOR "Marko Friedemann " diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c index 37d2f0b..24aedbb 100644 --- a/drivers/usb/input/yealink.c +++ b/drivers/usb/input/yealink.c @@ -48,13 +48,11 @@ #include #include -#include #include #include #include #include -#include -#include +#include #include "map_to_7segment.h" #include "yealink.h" diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 8ba6a70..daa486d 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -88,6 +88,20 @@ config USB_LED To compile this driver as a module, choose M here: the module will be called usbled. +config USB_CY7C63 + tristate "Cypress CY7C63xxx USB driver support" + depends on USB + help + Say Y here if you want to connect a Cypress CY7C63xxx + micro controller to your computer's USB port. This driver + supports the pre-programmed devices (incl. firmware) by + AK Modul-Bus Computer GmbH. + + Please see: http://www.ak-modul-bus.de/stat/mikrocontroller.html + + To compile this driver as a module, choose M here: the + module will be called cy7c63. + config USB_CYTHERM tristate "Cypress USB thermometer driver support" depends on USB @@ -137,6 +151,15 @@ config USB_IDMOUSE See also . +config USB_APPLEDISPLAY + tristate "Apple Cinema Display support" + depends on USB + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to control the backlight of Apple Cinema + Displays over USB. This driver provides a sysfs interface. + source "drivers/usb/misc/sisusbvga/Kconfig" config USB_LD diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 6c693bc..f25a972 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -4,6 +4,7 @@ # (the ones that don't fit into any othe # obj-$(CONFIG_USB_AUERSWALD) += auerswald.o +obj-$(CONFIG_USB_CY7C63) += cy7c63.o obj-$(CONFIG_USB_CYTHERM) += cytherm.o obj-$(CONFIG_USB_EMI26) += emi26.o obj-$(CONFIG_USB_EMI62) += emi62.o @@ -17,6 +18,7 @@ obj-$(CONFIG_USB_PHIDGETSERVO) += phidge obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_USS720) += uss720.o +obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c new file mode 100644 index 0000000..bfde82f --- /dev/null +++ b/drivers/usb/misc/appledisplay.c @@ -0,0 +1,383 @@ +/* + * Apple Cinema Display driver + * + * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch) + * + * Thanks to Caskey L. Dickson for his work with acdctl. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define APPLE_VENDOR_ID 0x05AC + +#define USB_REQ_GET_REPORT 0x01 +#define USB_REQ_SET_REPORT 0x09 + +#define ACD_USB_TIMEOUT 250 + +#define ACD_USB_EDID 0x0302 +#define ACD_USB_BRIGHTNESS 0x0310 + +#define ACD_BTN_NONE 0 +#define ACD_BTN_BRIGHT_UP 3 +#define ACD_BTN_BRIGHT_DOWN 4 + +#define ACD_URB_BUFFER_LEN 2 +#define ACD_MSG_BUFFER_LEN 2 + +#define APPLEDISPLAY_DEVICE(prod) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ + USB_DEVICE_ID_MATCH_INT_CLASS | \ + USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ + .idVendor = APPLE_VENDOR_ID, \ + .idProduct = (prod), \ + .bInterfaceClass = USB_CLASS_HID, \ + .bInterfaceProtocol = 0x00 + +/* table of devices that work with this driver */ +static struct usb_device_id appledisplay_table [] = { + { APPLEDISPLAY_DEVICE(0x9218) }, + { APPLEDISPLAY_DEVICE(0x9219) }, + { APPLEDISPLAY_DEVICE(0x921d) }, + + /* Terminating entry */ + { } +}; +MODULE_DEVICE_TABLE(usb, appledisplay_table); + +/* Structure to hold all of our device specific stuff */ +struct appledisplay { + struct usb_device *udev; /* usb device */ + struct urb *urb; /* usb request block */ + struct backlight_device *bd; /* backlight device */ + char *urbdata; /* interrupt URB data buffer */ + char *msgdata; /* control message data buffer */ + + struct work_struct work; + int button_pressed; + spinlock_t lock; +}; + +static atomic_t count_displays = ATOMIC_INIT(0); +static struct workqueue_struct *wq; + +static void appledisplay_complete(struct urb *urb, struct pt_regs *regs) +{ + struct appledisplay *pdata = urb->context; + unsigned long flags; + int retval; + + switch (urb->status) { + case 0: + /* success */ + break; + case -EOVERFLOW: + printk(KERN_ERR "appletouch: OVERFLOW with data " + "length %d, actual length is %d\n", + ACD_URB_BUFFER_LEN, pdata->urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* This urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __FUNCTION__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __FUNCTION__, urb->status); + goto exit; + } + + spin_lock_irqsave(&pdata->lock, flags); + + switch(pdata->urbdata[1]) { + case ACD_BTN_BRIGHT_UP: + case ACD_BTN_BRIGHT_DOWN: + pdata->button_pressed = 1; + queue_work(wq, &pdata->work); + break; + case ACD_BTN_NONE: + default: + pdata->button_pressed = 0; + break; + } + + spin_unlock_irqrestore(&pdata->lock, flags); + +exit: + retval = usb_submit_urb(pdata->urb, GFP_ATOMIC); + if (retval) { + err("%s - usb_submit_urb failed with result %d", + __FUNCTION__, retval); + } +} + +static int appledisplay_bl_update_status(struct backlight_device *bd) +{ + struct appledisplay *pdata = class_get_devdata(&bd->class_dev); + int retval; + + pdata->msgdata[0] = 0x10; + pdata->msgdata[1] = bd->props->brightness; + + retval = usb_control_msg( + pdata->udev, + usb_sndctrlpipe(pdata->udev, 0), + USB_REQ_SET_REPORT, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + ACD_USB_BRIGHTNESS, + 0, + pdata->msgdata, 2, + ACD_USB_TIMEOUT); + + return retval; +} + +static int appledisplay_bl_get_brightness(struct backlight_device *bd) +{ + struct appledisplay *pdata = class_get_devdata(&bd->class_dev); + int retval; + + retval = usb_control_msg( + pdata->udev, + usb_rcvctrlpipe(pdata->udev, 0), + USB_REQ_GET_REPORT, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + ACD_USB_BRIGHTNESS, + 0, + pdata->msgdata, 2, + ACD_USB_TIMEOUT); + + if (retval < 0) + return retval; + else + return pdata->msgdata[1]; +} + +static struct backlight_properties appledisplay_bl_data = { + .owner = THIS_MODULE, + .get_brightness = appledisplay_bl_get_brightness, + .update_status = appledisplay_bl_update_status, + .max_brightness = 0xFF +}; + +static void appledisplay_work(void *private) +{ + struct appledisplay *pdata = private; + int retval; + + up(&pdata->bd->sem); + retval = appledisplay_bl_get_brightness(pdata->bd); + if (retval >= 0) + pdata->bd->props->brightness = retval; + down(&pdata->bd->sem); + + /* Poll again in about 125ms if there's still a button pressed */ + if (pdata->button_pressed) + schedule_delayed_work(&pdata->work, HZ / 8); +} + +static int appledisplay_probe(struct usb_interface *iface, + const struct usb_device_id *id) +{ + struct appledisplay *pdata; + struct usb_device *udev = interface_to_usbdev(iface); + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int int_in_endpointAddr = 0; + int i, retval = -ENOMEM, brightness; + char bl_name[20]; + + /* set up the endpoint information */ + /* use only the first interrupt-in endpoint */ + iface_desc = iface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { + endpoint = &iface_desc->endpoint[i].desc; + if (!int_in_endpointAddr && + (endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT)) { + /* we found an interrupt in endpoint */ + int_in_endpointAddr = endpoint->bEndpointAddress; + break; + } + } + if (!int_in_endpointAddr) { + err("Could not find int-in endpoint"); + return -EIO; + } + + /* allocate memory for our device state and initialize it */ + pdata = kzalloc(sizeof(struct appledisplay), GFP_KERNEL); + if (!pdata) { + retval = -ENOMEM; + err("Out of memory"); + goto error; + } + + pdata->udev = udev; + + spin_lock_init(&pdata->lock); + INIT_WORK(&pdata->work, appledisplay_work, pdata); + + /* Allocate buffer for control messages */ + pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL); + if (!pdata->msgdata) { + retval = -ENOMEM; + err("appledisplay: Allocating buffer for control messages " + "failed"); + goto error; + } + + /* Allocate interrupt URB */ + pdata->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!pdata->urb) { + retval = -ENOMEM; + err("appledisplay: Allocating URB failed"); + goto error; + } + + /* Allocate buffer for interrupt data */ + pdata->urbdata = usb_buffer_alloc(pdata->udev, ACD_URB_BUFFER_LEN, + GFP_KERNEL, &pdata->urb->transfer_dma); + if (!pdata->urbdata) { + retval = -ENOMEM; + err("appledisplay: Allocating URB buffer failed"); + goto error; + } + + /* Configure interrupt URB */ + usb_fill_int_urb(pdata->urb, udev, + usb_rcvintpipe(udev, int_in_endpointAddr), + pdata->urbdata, ACD_URB_BUFFER_LEN, appledisplay_complete, + pdata, 1); + if (usb_submit_urb(pdata->urb, GFP_KERNEL)) { + retval = -EIO; + err("appledisplay: Submitting URB failed"); + goto error; + } + + /* Register backlight device */ + snprintf(bl_name, sizeof(bl_name), "appledisplay%d", + atomic_inc_return(&count_displays) - 1); + pdata->bd = backlight_device_register(bl_name, pdata, + &appledisplay_bl_data); + if (IS_ERR(pdata->bd)) { + err("appledisplay: Backlight registration failed"); + goto error; + } + + /* Try to get brightness */ + up(&pdata->bd->sem); + brightness = appledisplay_bl_get_brightness(pdata->bd); + down(&pdata->bd->sem); + + if (brightness < 0) { + retval = brightness; + err("appledisplay: Error while getting initial brightness: %d", retval); + goto error; + } + + /* Set brightness in backlight device */ + up(&pdata->bd->sem); + pdata->bd->props->brightness = brightness; + down(&pdata->bd->sem); + + /* save our data pointer in the interface device */ + usb_set_intfdata(iface, pdata); + + printk(KERN_INFO "appledisplay: Apple Cinema Display connected\n"); + + return 0; + +error: + if (pdata) { + if (pdata->urb) { + usb_kill_urb(pdata->urb); + if (pdata->urbdata) + usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, + pdata->urbdata, pdata->urb->transfer_dma); + usb_free_urb(pdata->urb); + } + if (pdata->bd) + backlight_device_unregister(pdata->bd); + kfree(pdata->msgdata); + } + usb_set_intfdata(iface, NULL); + kfree(pdata); + return retval; +} + +static void appledisplay_disconnect(struct usb_interface *iface) +{ + struct appledisplay *pdata = usb_get_intfdata(iface); + + if (pdata) { + usb_kill_urb(pdata->urb); + cancel_delayed_work(&pdata->work); + backlight_device_unregister(pdata->bd); + usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, + pdata->urbdata, pdata->urb->transfer_dma); + usb_free_urb(pdata->urb); + kfree(pdata->msgdata); + kfree(pdata); + } + + printk(KERN_INFO "appledisplay: Apple Cinema Display disconnected\n"); +} + +static struct usb_driver appledisplay_driver = { + .name = "appledisplay", + .probe = appledisplay_probe, + .disconnect = appledisplay_disconnect, + .id_table = appledisplay_table, +}; + +static int __init appledisplay_init(void) +{ + wq = create_singlethread_workqueue("appledisplay"); + if (!wq) { + err("Could not create work queue\n"); + return -ENOMEM; + } + + return usb_register(&appledisplay_driver); +} + +static void __exit appledisplay_exit(void) +{ + flush_workqueue(wq); + destroy_workqueue(wq); + usb_deregister(&appledisplay_driver); +} + +MODULE_AUTHOR("Michael Hanselmann"); +MODULE_DESCRIPTION("Apple Cinema Display driver"); +MODULE_LICENSE("GPL"); + +module_init(appledisplay_init); +module_exit(appledisplay_exit); diff --git a/drivers/usb/misc/cy7c63.c b/drivers/usb/misc/cy7c63.c new file mode 100644 index 0000000..8a1c10b --- /dev/null +++ b/drivers/usb/misc/cy7c63.c @@ -0,0 +1,244 @@ +/* +* cy7c63.c +* +* Copyright (c) 2006 Oliver Bock (bock@fh-wolfenbuettel.de) +* +* This driver is based on the Cypress Thermometer USB Driver by +* Marcus Maul and the 2.0 version of Greg Kroah-Hartman's +* USB Skeleton driver. +* +* Is is a generic driver for the Cypress CY7C63000 family. +* For the time being it enables you to toggle the single I/O ports +* of the device. +* +* Supported vendors: AK Modul-Bus Computer GmbH +* Supported devices: CY7C63001A-PC (to be continued...) +* Supported functions: Read/Write Ports (to be continued...) +* +* Chipsets families: CY7C63000, CY7C63001, CY7C63100, CY7C63101 +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation, version 2. +*/ + +#include +#include +#include +#include + +#define DRIVER_AUTHOR "Oliver Bock (bock@fh-wolfenbuettel.de)" +#define DRIVER_DESC "Cypress CY7C63xxx USB driver" + +#define CY7C63_VENDOR_ID 0xa2c +#define CY7C63_PRODUCT_ID 0x8 + +#define CY7C63_READ_PORT 0x4 +#define CY7C63_WRITE_PORT 0x5 +#define CY7C63_READ_RAM 0x2 +#define CY7C63_WRITE_RAM 0x3 +#define CY7C63_READ_ROM 0x1 + +#define CY7C63_READ_PORT_ID0 0 +#define CY7C63_WRITE_PORT_ID0 0 +#define CY7C63_READ_PORT_ID1 0x2 +#define CY7C63_WRITE_PORT_ID1 1 + +#define CY7C63_MAX_REQSIZE 8 + + +/* table of devices that work with this driver */ +static struct usb_device_id cy7c63_table [] = { + { USB_DEVICE(CY7C63_VENDOR_ID, CY7C63_PRODUCT_ID) }, + { } +}; +MODULE_DEVICE_TABLE(usb, cy7c63_table); + +/* structure to hold all of our device specific stuff */ +struct cy7c63 { + struct usb_device * udev; + char port0; + char port1; +}; + +/* used to send usb control messages to device */ +int vendor_command(struct cy7c63 *dev, unsigned char request, + unsigned char address, unsigned char data) { + + int retval = 0; + unsigned int pipe; + unsigned char *iobuf; + + /* allocate some memory for the i/o buffer*/ + iobuf = kzalloc(CY7C63_MAX_REQSIZE, GFP_KERNEL); + if (!iobuf) { + dev_err(&dev->udev->dev, "Out of memory!\n"); + retval = -ENOMEM; + goto error; + } + + dev_dbg(&dev->udev->dev, "Sending usb_control_msg (data: %d)\n", data); + + /* prepare usb control message and send it upstream */ + pipe = usb_rcvctrlpipe(dev->udev, 0); + retval = usb_control_msg(dev->udev, pipe, request, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, + address, data, iobuf, CY7C63_MAX_REQSIZE, + USB_CTRL_GET_TIMEOUT); + + /* store returned data (more READs to be added!) */ + switch (request) { + case CY7C63_READ_PORT: + if (address == CY7C63_READ_PORT_ID0) { + dev->port0 = iobuf[1]; + dev_dbg(&dev->udev->dev, + "READ_PORT0 returned: %d\n",dev->port0); + } + else if (address == CY7C63_READ_PORT_ID1) { + dev->port1 = iobuf[1]; + dev_dbg(&dev->udev->dev, + "READ_PORT1 returned: %d\n",dev->port1); + } + break; + } + + kfree(iobuf); +error: + return retval; +} + +#define get_set_port(num,read_id,write_id) \ +static ssize_t set_port##num(struct device *dev, struct device_attribute *attr, \ + const char *buf, size_t count) { \ + \ + int value; \ + int result = 0; \ + \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct cy7c63 *cyp = usb_get_intfdata(intf); \ + \ + dev_dbg(&cyp->udev->dev, "WRITE_PORT%d called\n", num); \ + \ + /* validate input data */ \ + if (sscanf(buf, "%d", &value) < 1) { \ + result = -EINVAL; \ + goto error; \ + } \ + if (value>255 || value<0) { \ + result = -EINVAL; \ + goto error; \ + } \ + \ + result = vendor_command(cyp, CY7C63_WRITE_PORT, write_id, \ + (unsigned char)value); \ + \ + dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n",result); \ +error: \ + return result < 0 ? result : count; \ +} \ + \ +static ssize_t get_port##num(struct device *dev, \ + struct device_attribute *attr, char *buf) { \ + \ + int result = 0; \ + \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct cy7c63 *cyp = usb_get_intfdata(intf); \ + \ + dev_dbg(&cyp->udev->dev, "READ_PORT%d called\n", num); \ + \ + result = vendor_command(cyp, CY7C63_READ_PORT, read_id, 0); \ + \ + dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result); \ + \ + return sprintf(buf, "%d", cyp->port##num); \ +} \ +static DEVICE_ATTR(port##num, S_IWUGO | S_IRUGO, get_port##num, set_port##num); + +get_set_port(0, CY7C63_READ_PORT_ID0, CY7C63_WRITE_PORT_ID0); +get_set_port(1, CY7C63_READ_PORT_ID1, CY7C63_WRITE_PORT_ID1); + +static int cy7c63_probe(struct usb_interface *interface, + const struct usb_device_id *id) { + + struct cy7c63 *dev = NULL; + int retval = -ENOMEM; + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + dev_err(&dev->udev->dev, "Out of memory!\n"); + goto error; + } + + dev->udev = usb_get_dev(interface_to_usbdev(interface)); + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* create device attribute files */ + device_create_file(&interface->dev, &dev_attr_port0); + device_create_file(&interface->dev, &dev_attr_port1); + + /* let the user know what node this device is now attached to */ + dev_info(&interface->dev, + "Cypress CY7C63xxx device now attached\n"); + + retval = 0; +error: + return retval; +} + +static void cy7c63_disconnect(struct usb_interface *interface) { + + struct cy7c63 *dev; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + /* remove device attribute files */ + device_remove_file(&interface->dev, &dev_attr_port0); + device_remove_file(&interface->dev, &dev_attr_port1); + + usb_put_dev(dev->udev); + + dev_info(&interface->dev, + "Cypress CY7C63xxx device now disconnected\n"); + + kfree(dev); +} + +static struct usb_driver cy7c63_driver = { + .name = "cy7c63", + .probe = cy7c63_probe, + .disconnect = cy7c63_disconnect, + .id_table = cy7c63_table, +}; + +static int __init cy7c63_init(void) { + + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&cy7c63_driver); + if (result) { + err("Function usb_register failed! Error number: %d\n", result); + } + + return result; +} + +static void __exit cy7c63_exit(void) { + + /* deregister this driver with the USB subsystem */ + usb_deregister(&cy7c63_driver); +} + +module_init(cy7c63_init); +module_exit(cy7c63_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); + +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 997db5d..13aeea2 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -1,7 +1,8 @@ /* * USB PhidgetInterfaceKit driver 1.0 * - * Copyright (C) 2004 Sean Young + * Copyright (C) 2004, 2006 Sean Young + * Copyright (C) 2005 Daniel Saakes * Copyright (C) 2004 Greg Kroah-Hartman * * This program is free software; you can redistribute it and/or modify @@ -25,6 +26,7 @@ #define DRIVER_DESC "USB PhidgetInterfac #define USB_VENDOR_ID_GLAB 0x06c2 #define USB_DEVICE_ID_INTERFACEKIT004 0x0040 +#define USB_DEVICE_ID_INTERFACEKIT01616 0x0044 #define USB_DEVICE_ID_INTERFACEKIT888 0x0045 #define USB_DEVICE_ID_INTERFACEKIT047 0x0051 #define USB_DEVICE_ID_INTERFACEKIT088 0x0053 @@ -32,7 +34,9 @@ #define USB_DEVICE_ID_INTERFACEKIT088 0x #define USB_VENDOR_ID_WISEGROUP 0x0925 #define USB_DEVICE_ID_INTERFACEKIT884 0x8201 -#define MAX_INTERFACES 8 +#define MAX_INTERFACES 16 + +#define URB_INT_SIZE 8 struct driver_interfacekit { int sensors; @@ -52,19 +56,24 @@ ifkit(8, 8, 8, 0); ifkit(0, 4, 7, 1); ifkit(8, 8, 4, 0); ifkit(0, 8, 8, 1); +ifkit(0, 16, 16, 0); -struct phidget_interfacekit { +struct interfacekit { struct usb_device *udev; struct usb_interface *intf; struct driver_interfacekit *ifkit; - int outputs[MAX_INTERFACES]; - int inputs[MAX_INTERFACES]; - int sensors[MAX_INTERFACES]; + unsigned long outputs; + u8 inputs[MAX_INTERFACES]; + u16 sensors[MAX_INTERFACES]; u8 lcd_files_on; struct urb *irq; unsigned char *data; dma_addr_t data_dma; + + struct work_struct do_notify; + unsigned long input_events; + unsigned long sensor_events; }; static struct usb_device_id id_table[] = { @@ -76,33 +85,33 @@ static struct usb_device_id id_table[] = .driver_info = (kernel_ulong_t)&ph_047}, {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), .driver_info = (kernel_ulong_t)&ph_088}, + {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT01616), + .driver_info = (kernel_ulong_t)&ph_01616}, {USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884), .driver_info = (kernel_ulong_t)&ph_884}, {} }; MODULE_DEVICE_TABLE(usb, id_table); -static int change_outputs(struct phidget_interfacekit *kit, int output_num, int enable) +static int change_outputs(struct interfacekit *kit, int output_num, int enable) { - unsigned char *buffer; + u8 *buffer; int retval; - int n; + + if (enable) + set_bit(output_num, &kit->outputs); + else + clear_bit(output_num, &kit->outputs); buffer = kzalloc(4, GFP_KERNEL); if (!buffer) { - dev_err(&kit->udev->dev, "%s - out of memory\n", - __FUNCTION__); + dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } + buffer[0] = (u8)kit->outputs; + buffer[1] = (u8)(kit->outputs >> 8); - kit->outputs[output_num] = enable; - for (n=0; n<8; n++) { - if (kit->outputs[n]) { - buffer[0] |= 1 << n; - } - } - - dev_dbg(&kit->udev->dev, "sending data: %02x\n", buffer[0]); + dev_dbg(&kit->udev->dev, "sending data: 0x%04x\n", (u16)kit->outputs); retval = usb_control_msg(kit->udev, usb_sndctrlpipe(kit->udev, 0), @@ -116,10 +125,10 @@ static int change_outputs(struct phidget return retval < 0 ? retval : 0; } -static int change_string(struct phidget_interfacekit *kit, const char *display, unsigned char row) +static int change_string(struct interfacekit *kit, const char *display, unsigned char row) { unsigned char *buffer; - unsigned char *form_buffer; + unsigned char *form_buffer; int retval = -ENOMEM; int i,j, len, buf_ptr; @@ -175,7 +184,7 @@ #define set_lcd_line(number) \ static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ - struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ + struct interfacekit *kit = usb_get_intfdata(intf); \ change_string(kit, buf, number - 1); \ return count; \ } \ @@ -186,7 +195,7 @@ set_lcd_line(2); static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct usb_interface *intf = to_usb_interface(dev); - struct phidget_interfacekit *kit = usb_get_intfdata(intf); + struct interfacekit *kit = usb_get_intfdata(intf); int enabled; unsigned char *buffer; int retval = -ENOMEM; @@ -220,7 +229,7 @@ exit: } static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight); -static void remove_lcd_files(struct phidget_interfacekit *kit) +static void remove_lcd_files(struct interfacekit *kit) { if (kit->lcd_files_on) { dev_dbg(&kit->udev->dev, "Removing lcd files\n"); @@ -233,7 +242,7 @@ static void remove_lcd_files(struct phid static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct usb_interface *intf = to_usb_interface(dev); - struct phidget_interfacekit *kit = usb_get_intfdata(intf); + struct interfacekit *kit = usb_get_intfdata(intf); int enable; if (kit->ifkit->has_lcd == 0) @@ -263,10 +272,10 @@ static DEVICE_ATTR(lcd, S_IWUGO, NULL, e static void interfacekit_irq(struct urb *urb, struct pt_regs *regs) { - struct phidget_interfacekit *kit = urb->context; + struct interfacekit *kit = urb->context; unsigned char *buffer = kit->data; + int i, level, sensor; int status; - int n; switch (urb->status) { case 0: /* success */ @@ -280,22 +289,63 @@ static void interfacekit_irq(struct urb goto resubmit; } - for (n=0; n<8; n++) { - kit->inputs[n] = buffer[1] & (1 << n) ? 1 : 0; + /* digital inputs */ + if (kit->ifkit->inputs == 16) { + for (i=0; i < 8; i++) { + level = (buffer[0] >> i) & 1; + if (kit->inputs[i] != level) { + kit->inputs[i] = level; + set_bit(i, &kit->input_events); + } + level = (buffer[1] >> i) & 1; + if (kit->inputs[8 + i] != level) { + kit->inputs[8 + i] = level; + set_bit(8 + i, &kit->input_events); + } + } + } + else if (kit->ifkit->inputs == 8) { + for (i=0; i < 8; i++) { + level = (buffer[1] >> i) & 1; + if (kit->inputs[i] != level) { + kit->inputs[i] = level; + set_bit(i, &kit->input_events); + } + } } - if (buffer[0] & 1) { - kit->sensors[4] = buffer[2] + (buffer[3] & 0x0f) * 256; - kit->sensors[5] = buffer[4] + (buffer[3] & 0xf0) * 16; - kit->sensors[6] = buffer[5] + (buffer[6] & 0x0f) * 256; - kit->sensors[7] = buffer[7] + (buffer[6] & 0xf0) * 16; - } else { - kit->sensors[0] = buffer[2] + (buffer[3] & 0x0f) * 256; - kit->sensors[1] = buffer[4] + (buffer[3] & 0xf0) * 16; - kit->sensors[2] = buffer[5] + (buffer[6] & 0x0f) * 256; - kit->sensors[3] = buffer[7] + (buffer[6] & 0xf0) * 16; + /* analog inputs */ + if (kit->ifkit->sensors) { + sensor = (buffer[0] & 1) ? 4 : 0; + + level = buffer[2] + (buffer[3] & 0x0f) * 256; + if (level != kit->sensors[sensor]) { + kit->sensors[sensor] = level; + set_bit(sensor, &kit->sensor_events); + } + sensor++; + level = buffer[4] + (buffer[3] & 0xf0) * 16; + if (level != kit->sensors[sensor]) { + kit->sensors[sensor] = level; + set_bit(sensor, &kit->sensor_events); + } + sensor++; + level = buffer[5] + (buffer[6] & 0x0f) * 256; + if (level != kit->sensors[sensor]) { + kit->sensors[sensor] = level; + set_bit(sensor, &kit->sensor_events); + } + sensor++; + level = buffer[7] + (buffer[6] & 0xf0) * 16; + if (level != kit->sensors[sensor]) { + kit->sensors[sensor] = level; + set_bit(sensor, &kit->sensor_events); + } } + if (kit->input_events || kit->sensor_events) + schedule_work(&kit->do_notify); + resubmit: status = usb_submit_urb(urb, SLAB_ATOMIC); if (status) @@ -304,20 +354,40 @@ resubmit: kit->udev->devpath, status); } +static void do_notify(void *data) +{ + struct interfacekit *kit = data; + int i; + char sysfs_file[8]; + + for (i=0; iifkit->inputs; i++) { + if (test_and_clear_bit(i, &kit->input_events)) { + sprintf(sysfs_file, "input%d", i + 1); + sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); + } + } + + for (i=0; iifkit->sensors; i++) { + if (test_and_clear_bit(i, &kit->sensor_events)) { + sprintf(sysfs_file, "sensor%d", i + 1); + sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file); + } + } +} + #define show_set_output(value) \ -static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ +static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \ size_t count) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ - struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ + struct interfacekit *kit = usb_get_intfdata(intf); \ int enabled; \ int retval; \ \ - if (sscanf(buf, "%d", &enabled) < 1) { \ + if (sscanf(buf, "%d", &enabled) < 1) \ return -EINVAL; \ - } \ \ - retval = change_outputs(kit, value - 1, enabled ? 1 : 0); \ + retval = change_outputs(kit, value - 1, enabled); \ \ return retval ? retval : count; \ } \ @@ -325,9 +395,9 @@ static ssize_t set_output##value(struct static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ - struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ + struct interfacekit *kit = usb_get_intfdata(intf); \ \ - return sprintf(buf, "%d\n", kit->outputs[value - 1]); \ + return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ } \ static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \ show_output##value, set_output##value); @@ -338,15 +408,23 @@ show_set_output(4); show_set_output(5); show_set_output(6); show_set_output(7); -show_set_output(8); /* should be MAX_INTERFACES - 1 */ +show_set_output(8); +show_set_output(9); +show_set_output(10); +show_set_output(11); +show_set_output(12); +show_set_output(13); +show_set_output(14); +show_set_output(15); +show_set_output(16); #define show_input(value) \ static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ - struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ + struct interfacekit *kit = usb_get_intfdata(intf); \ \ - return sprintf(buf, "%d\n", kit->inputs[value - 1]); \ + return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ } \ static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL); @@ -357,15 +435,23 @@ show_input(4); show_input(5); show_input(6); show_input(7); -show_input(8); /* should be MAX_INTERFACES - 1 */ +show_input(8); +show_input(9); +show_input(10); +show_input(11); +show_input(12); +show_input(13); +show_input(14); +show_input(15); +show_input(16); #define show_sensor(value) \ static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct usb_interface *intf = to_usb_interface(dev); \ - struct phidget_interfacekit *kit = usb_get_intfdata(intf); \ + struct interfacekit *kit = usb_get_intfdata(intf); \ \ - return sprintf(buf, "%d\n", kit->sensors[value - 1]); \ + return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ } \ static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL); @@ -376,16 +462,16 @@ show_sensor(4); show_sensor(5); show_sensor(6); show_sensor(7); -show_sensor(8); /* should be MAX_INTERFACES - 1 */ +show_sensor(8); static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; - struct phidget_interfacekit *kit; + struct interfacekit *kit; struct driver_interfacekit *ifkit; - int pipe, maxp; + int pipe, maxp, rc = -ENOMEM; ifkit = (struct driver_interfacekit *)id->driver_info; if (!ifkit) @@ -405,29 +491,23 @@ static int interfacekit_probe(struct usb maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); kit = kzalloc(sizeof(*kit), GFP_KERNEL); - if (kit == NULL) { - dev_err(&intf->dev, "%s - out of memory\n", __FUNCTION__); - return -ENOMEM; - } - kit->ifkit = ifkit; + if (!kit) + goto out; - kit->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kit->data_dma); - if (!kit->data) { - kfree(kit); - return -ENOMEM; - } + kit->ifkit = ifkit; + kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); + if (!kit->data) + goto out; kit->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!kit->irq) { - usb_buffer_free(dev, 8, kit->data, kit->data_dma); - kfree(kit); - return -ENOMEM; - } + if (!kit->irq) + goto out; kit->udev = usb_get_dev(dev); kit->intf = intf; + INIT_WORK(&kit->do_notify, do_notify, kit); usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, - (maxp > 8 ? 8 : maxp), + maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, interfacekit_irq, kit, endpoint->bInterval); kit->irq->transfer_dma = kit->data_dma; kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -435,7 +515,8 @@ static int interfacekit_probe(struct usb usb_set_intfdata(intf, kit); if (usb_submit_urb(kit->irq, GFP_KERNEL)) { - return -EIO; + rc = -EIO; + goto out; } if (ifkit->outputs >= 4) { @@ -444,12 +525,22 @@ static int interfacekit_probe(struct usb device_create_file(&intf->dev, &dev_attr_output3); device_create_file(&intf->dev, &dev_attr_output4); } - if (ifkit->outputs == 8) { + if (ifkit->outputs >= 8) { device_create_file(&intf->dev, &dev_attr_output5); device_create_file(&intf->dev, &dev_attr_output6); device_create_file(&intf->dev, &dev_attr_output7); device_create_file(&intf->dev, &dev_attr_output8); } + if (ifkit->outputs == 16) { + device_create_file(&intf->dev, &dev_attr_output9); + device_create_file(&intf->dev, &dev_attr_output10); + device_create_file(&intf->dev, &dev_attr_output11); + device_create_file(&intf->dev, &dev_attr_output12); + device_create_file(&intf->dev, &dev_attr_output13); + device_create_file(&intf->dev, &dev_attr_output14); + device_create_file(&intf->dev, &dev_attr_output15); + device_create_file(&intf->dev, &dev_attr_output16); + } if (ifkit->inputs >= 4) { device_create_file(&intf->dev, &dev_attr_input1); @@ -457,12 +548,22 @@ static int interfacekit_probe(struct usb device_create_file(&intf->dev, &dev_attr_input3); device_create_file(&intf->dev, &dev_attr_input4); } - if (ifkit->inputs == 8) { + if (ifkit->inputs >= 8) { device_create_file(&intf->dev, &dev_attr_input5); device_create_file(&intf->dev, &dev_attr_input6); device_create_file(&intf->dev, &dev_attr_input7); device_create_file(&intf->dev, &dev_attr_input8); } + if (ifkit->inputs == 16) { + device_create_file(&intf->dev, &dev_attr_input9); + device_create_file(&intf->dev, &dev_attr_input10); + device_create_file(&intf->dev, &dev_attr_input11); + device_create_file(&intf->dev, &dev_attr_input12); + device_create_file(&intf->dev, &dev_attr_input13); + device_create_file(&intf->dev, &dev_attr_input14); + device_create_file(&intf->dev, &dev_attr_input15); + device_create_file(&intf->dev, &dev_attr_input16); + } if (ifkit->sensors >= 4) { device_create_file(&intf->dev, &dev_attr_sensor1); @@ -475,9 +576,8 @@ static int interfacekit_probe(struct usb device_create_file(&intf->dev, &dev_attr_sensor6); device_create_file(&intf->dev, &dev_attr_sensor7); } - if (ifkit->sensors == 8) { + if (ifkit->sensors == 8) device_create_file(&intf->dev, &dev_attr_sensor8); - } if (ifkit->has_lcd) device_create_file(&intf->dev, &dev_attr_lcd); @@ -486,29 +586,56 @@ static int interfacekit_probe(struct usb ifkit->sensors, ifkit->inputs, ifkit->outputs); return 0; + +out: + if (kit) { + if (kit->irq) + usb_free_urb(kit->irq); + if (kit->data) + usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); + kfree(kit); + } + + return rc; } static void interfacekit_disconnect(struct usb_interface *interface) { - struct phidget_interfacekit *kit; + struct interfacekit *kit; kit = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); if (!kit) return; + usb_kill_urb(kit->irq); + usb_free_urb(kit->irq); + usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma); + + cancel_delayed_work(&kit->do_notify); + if (kit->ifkit->outputs >= 4) { device_remove_file(&interface->dev, &dev_attr_output1); device_remove_file(&interface->dev, &dev_attr_output2); device_remove_file(&interface->dev, &dev_attr_output3); device_remove_file(&interface->dev, &dev_attr_output4); } - if (kit->ifkit->outputs == 8) { + if (kit->ifkit->outputs >= 8) { device_remove_file(&interface->dev, &dev_attr_output5); device_remove_file(&interface->dev, &dev_attr_output6); device_remove_file(&interface->dev, &dev_attr_output7); device_remove_file(&interface->dev, &dev_attr_output8); } + if (kit->ifkit->outputs == 16) { + device_remove_file(&interface->dev, &dev_attr_output9); + device_remove_file(&interface->dev, &dev_attr_output10); + device_remove_file(&interface->dev, &dev_attr_output11); + device_remove_file(&interface->dev, &dev_attr_output12); + device_remove_file(&interface->dev, &dev_attr_output13); + device_remove_file(&interface->dev, &dev_attr_output14); + device_remove_file(&interface->dev, &dev_attr_output15); + device_remove_file(&interface->dev, &dev_attr_output16); + } if (kit->ifkit->inputs >= 4) { device_remove_file(&interface->dev, &dev_attr_input1); @@ -516,12 +643,22 @@ static void interfacekit_disconnect(stru device_remove_file(&interface->dev, &dev_attr_input3); device_remove_file(&interface->dev, &dev_attr_input4); } - if (kit->ifkit->inputs == 8) { + if (kit->ifkit->inputs >= 8) { device_remove_file(&interface->dev, &dev_attr_input5); device_remove_file(&interface->dev, &dev_attr_input6); device_remove_file(&interface->dev, &dev_attr_input7); device_remove_file(&interface->dev, &dev_attr_input8); } + if (kit->ifkit->inputs == 16) { + device_remove_file(&interface->dev, &dev_attr_input9); + device_remove_file(&interface->dev, &dev_attr_input10); + device_remove_file(&interface->dev, &dev_attr_input11); + device_remove_file(&interface->dev, &dev_attr_input12); + device_remove_file(&interface->dev, &dev_attr_input13); + device_remove_file(&interface->dev, &dev_attr_input14); + device_remove_file(&interface->dev, &dev_attr_input15); + device_remove_file(&interface->dev, &dev_attr_input16); + } if (kit->ifkit->sensors >= 4) { device_remove_file(&interface->dev, &dev_attr_sensor1); @@ -534,19 +671,15 @@ static void interfacekit_disconnect(stru device_remove_file(&interface->dev, &dev_attr_sensor6); device_remove_file(&interface->dev, &dev_attr_sensor7); } - if (kit->ifkit->sensors == 8) { + if (kit->ifkit->sensors == 8) device_remove_file(&interface->dev, &dev_attr_sensor8); - } + if (kit->ifkit->has_lcd) device_remove_file(&interface->dev, &dev_attr_lcd); dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); - usb_kill_urb(kit->irq); - usb_free_urb(kit->irq); - usb_buffer_free(kit->udev, 8, kit->data, kit->data_dma); - usb_put_dev(kit->udev); kfree(kit); } diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 196c879..738bd7c 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -37,6 +37,7 @@ */ #include +#include #include #include #include @@ -52,6 +53,7 @@ #include #include #include "sisusb.h" +#include "sisusb_init.h" #ifdef INCL_SISUSB_CON #include @@ -62,36 +64,6 @@ #define SISUSB_DONTSYNC /* Forward declarations / clean-up routines */ #ifdef INCL_SISUSB_CON -int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data); -int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data); -int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data); -int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data); -int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor); -int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor); -int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand); - -int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); -int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); -int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data); -int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data); -int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, - u32 dest, int length, size_t *bytes_written); - -int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); - -extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); -extern int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); - -extern void sisusb_init_concode(void); -extern int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last); -extern void sisusb_console_exit(struct sisusb_usb_data *sisusb); - -extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location); - -extern int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, - u8 *arg, int cmapsz, int ch512, int dorecalc, - struct vc_data *c, int fh, int uplock); - static int sisusb_first_vc = 0; static int sisusb_last_vc = 0; module_param_named(first, sisusb_first_vc, int, 0); @@ -102,7 +74,7 @@ #endif static struct usb_driver sisusb_driver; -DECLARE_MUTEX(disconnect_sem); +DEFINE_MUTEX(disconnect_mutex); static void sisusb_free_buffers(struct sisusb_usb_data *sisusb) @@ -1359,9 +1331,6 @@ sisusb_getreg(struct sisusb_usb_data *si } #endif -#ifndef INCL_SISUSB_CON -static -#endif int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data) { @@ -1371,9 +1340,6 @@ sisusb_setidxreg(struct sisusb_usb_data return ret; } -#ifndef INCL_SISUSB_CON -static -#endif int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data) { @@ -1383,9 +1349,6 @@ sisusb_getidxreg(struct sisusb_usb_data return ret; } -#ifndef INCL_SISUSB_CON -static -#endif int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor) @@ -1415,18 +1378,12 @@ sisusb_setidxregmask(struct sisusb_usb_d return ret; } -#ifndef INCL_SISUSB_CON -static -#endif int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) { return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); } -#ifndef INCL_SISUSB_CON -static -#endif int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) { @@ -1448,6 +1405,8 @@ sisusb_readb(struct sisusb_usb_data *sis return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); } +#if 0 + int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data) { @@ -1460,6 +1419,8 @@ sisusb_readw(struct sisusb_usb_data *sis return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data)); } +#endif /* 0 */ + int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, u32 dest, int length, size_t *bytes_written) @@ -2552,39 +2513,39 @@ sisusb_open(struct inode *inode, struct struct usb_interface *interface; int subminor = iminor(inode); - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", subminor); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return -ENODEV; } if (!(sisusb = usb_get_intfdata(interface))) { - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return -ENODEV; } - down(&sisusb->lock); + mutex_lock(&sisusb->lock); if (!sisusb->present || !sisusb->ready) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return -ENODEV; } if (sisusb->isopen) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return -EBUSY; } if (!sisusb->devinit) { if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { if (sisusb_init_gfxdevice(sisusb, 0)) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Failed to initialize " "device\n", @@ -2592,8 +2553,8 @@ sisusb_open(struct inode *inode, struct return -EIO; } } else { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Device not attached to " "USB 2.0 hub\n", @@ -2609,9 +2570,9 @@ sisusb_open(struct inode *inode, struct file->private_data = sisusb; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return 0; } @@ -2642,14 +2603,14 @@ sisusb_release(struct inode *inode, stru struct sisusb_usb_data *sisusb; int myminor; - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) { - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return -ENODEV; } - down(&sisusb->lock); + mutex_lock(&sisusb->lock); if (sisusb->present) { /* Wait for all URBs to finish if device still present */ @@ -2662,12 +2623,12 @@ sisusb_release(struct inode *inode, stru sisusb->isopen = 0; file->private_data = NULL; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); /* decrement the usage count on our device */ kref_put(&sisusb->kref, sisusb_delete); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return 0; } @@ -2685,11 +2646,11 @@ sisusb_read(struct file *file, char __us if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Sanity check */ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -ENODEV; } @@ -2784,7 +2745,7 @@ sisusb_read(struct file *file, char __us (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) { if (count != 4) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EINVAL; } @@ -2808,7 +2769,7 @@ sisusb_read(struct file *file, char __us (*ppos) += bytes_read; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return errno ? errno : bytes_read; } @@ -2827,11 +2788,11 @@ sisusb_write(struct file *file, const ch if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Sanity check */ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -ENODEV; } @@ -2930,7 +2891,7 @@ sisusb_write(struct file *file, const ch (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) { if (count != 4) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EINVAL; } @@ -2956,7 +2917,7 @@ sisusb_write(struct file *file, const ch (*ppos) += bytes_written; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return errno ? errno : bytes_written; } @@ -2970,11 +2931,11 @@ sisusb_lseek(struct file *file, loff_t o if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Sanity check */ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -ENODEV; } @@ -2994,7 +2955,7 @@ sisusb_lseek(struct file *file, loff_t o ret = -EINVAL; } - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return ret; } @@ -3136,7 +3097,7 @@ sisusb_ioctl(struct inode *inode, struct if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Sanity check */ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { @@ -3193,7 +3154,7 @@ #endif } err_out: - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return retval; } @@ -3258,7 +3219,7 @@ static int sisusb_probe(struct usb_inter } kref_init(&sisusb->kref); - init_MUTEX(&(sisusb->lock)); + mutex_init(&(sisusb->lock)); /* Register device */ if ((retval = usb_register_dev(intf, &usb_sisusb_class))) { @@ -3429,9 +3390,9 @@ #endif * protect all other routines from the disconnect * case, not the other way round. */ - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Wait for all URBs to complete and kill them in case (MUST do) */ if (!sisusb_wait_all_out_complete(sisusb)) @@ -3462,12 +3423,12 @@ #endif sisusb->present = 0; sisusb->ready = 0; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); /* decrement our usage count */ kref_put(&sisusb->kref, sisusb_delete); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor); } diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h index a716825..8e1120a 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.h +++ b/drivers/usb/misc/sisusbvga/sisusb.h @@ -41,6 +41,8 @@ #ifdef CONFIG_COMPAT #define SISUSB_NEW_CONFIG_COMPAT #endif +#include + /* For older kernels, support for text consoles is by default * off. To ensable text console support, change the following: */ @@ -60,11 +62,9 @@ #ifdef CONFIG_USB_SISUSBVGA_CON #define INCL_SISUSB_CON 1 #endif -#ifdef INCL_SISUSB_CON #include #include #include "sisusb_struct.h" -#endif /* USB related */ @@ -116,7 +116,7 @@ struct sisusb_usb_data { struct usb_interface *interface; struct kref kref; wait_queue_head_t wait_q; /* for syncind and timeouts */ - struct semaphore lock; /* general race avoidance */ + struct mutex lock; /* general race avoidance */ unsigned int ifnum; /* interface number of the USB device */ int minor; /* minor (for logging clarity) */ int isopen; /* !=0 if open */ diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index be5c1a2..fb48fec 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -48,6 +48,7 @@ */ #include +#include #include #include #include @@ -69,27 +70,9 @@ #include #include #include "sisusb.h" +#include "sisusb_init.h" #ifdef INCL_SISUSB_CON -extern int sisusb_setreg(struct sisusb_usb_data *, int, u8); -extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *); -extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8); -extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *); -extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8); -extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8); -extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8); - -extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); -extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); -extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data); -extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data); -extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, - u32 dest, int length, size_t *bytes_written); - -extern void sisusb_delete(struct kref *kref); -extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); - -extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); #define sisusbcon_writew(val, addr) (*(addr) = (val)) #define sisusbcon_readw(addr) (*(addr)) @@ -102,8 +85,6 @@ static struct sisusb_usb_data *mysisusbs /* Forward declaration */ static const struct consw sisusb_con; -extern struct semaphore disconnect_sem; - static inline void sisusbcon_memsetw(u16 *s, u16 c, unsigned int count) { @@ -194,11 +175,11 @@ sisusb_get_sisusb_lock_and_check(unsigne if (!(sisusb = sisusb_get_sisusb(console))) return NULL; - down(&sisusb->lock); + mutex_lock(&sisusb->lock); if (!sisusb_sisusb_valid(sisusb) || !sisusb->havethisconsole[console]) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return NULL; } @@ -236,18 +217,18 @@ sisusbcon_init(struct vc_data *c, int in * are set up/restored. */ - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return; } - down(&sisusb->lock); + mutex_lock(&sisusb->lock); if (!sisusb_sisusb_valid(sisusb)) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return; } @@ -284,9 +265,9 @@ sisusbcon_init(struct vc_data *c, int in if (!*c->vc_uni_pagedir_loc) con_set_default_unimap(c); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); if (init) { c->vc_cols = cols; @@ -306,14 +287,14 @@ sisusbcon_deinit(struct vc_data *c) * and others, ie not under our control. */ - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); return; } - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Clear ourselves in mysisusbs */ mysisusbs[c->vc_num] = NULL; @@ -332,12 +313,12 @@ sisusbcon_deinit(struct vc_data *c) } } - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); /* decrement the usage count on our sisusb */ kref_put(&sisusb->kref, sisusb_delete); - up(&disconnect_sem); + mutex_unlock(&disconnect_mutex); } /* interface routine */ @@ -417,7 +398,7 @@ #if 0 #endif if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -425,7 +406,7 @@ #endif sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y), (u32)SISUSB_HADDR(x, y), 2, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } /* Interface routine */ @@ -453,14 +434,14 @@ sisusbcon_putcs(struct vc_data *c, const sisusbcon_writew(sisusbcon_readw(s++), dest++); if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y), (u32)SISUSB_HADDR(x, y), count * 2, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } /* Interface routine */ @@ -504,7 +485,7 @@ sisusbcon_clear(struct vc_data *c, int y } if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -514,7 +495,7 @@ sisusbcon_clear(struct vc_data *c, int y sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y), (u32)SISUSB_HADDR(x, y), length, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } /* Interface routine */ @@ -576,7 +557,7 @@ #if 0 #endif if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -586,7 +567,7 @@ #endif sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy), (u32)SISUSB_HADDR(dx, dy), length, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } /* interface routine */ @@ -609,7 +590,7 @@ sisusbcon_switch(struct vc_data *c) /* Don't write to screen if in gfx mode */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -618,7 +599,7 @@ sisusbcon_switch(struct vc_data *c) * as origin. */ if (c->vc_origin == (unsigned long)c->vc_screenbuf) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n"); return 0; } @@ -635,7 +616,7 @@ sisusbcon_switch(struct vc_data *c) (u32)SISUSB_HADDR(0, 0), length, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -657,7 +638,7 @@ sisusbcon_save_screen(struct vc_data *c) /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -669,7 +650,7 @@ sisusbcon_save_screen(struct vc_data *c) sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin, length); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } /* interface routine */ @@ -690,7 +671,7 @@ sisusbcon_set_palette(struct vc_data *c, /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EINVAL; } @@ -705,7 +686,7 @@ sisusbcon_set_palette(struct vc_data *c, break; } - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -728,7 +709,7 @@ sisusbcon_blank(struct vc_data *c, int b sisusb->is_gfx = blank ? 1 : 0; if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -777,7 +758,7 @@ sisusbcon_blank(struct vc_data *c, int b cr63 = 0x40; break; default: - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EINVAL; } @@ -788,7 +769,7 @@ sisusbcon_blank(struct vc_data *c, int b } - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return ret; } @@ -809,7 +790,7 @@ sisusbcon_scrolldelta(struct vc_data *c, /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -849,7 +830,7 @@ sisusbcon_scrolldelta(struct vc_data *c, sisusbcon_set_start_address(sisusb, c); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 1; } @@ -867,7 +848,7 @@ sisusbcon_cursor(struct vc_data *c, int /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -879,7 +860,7 @@ sisusbcon_cursor(struct vc_data *c, int if (mode == CM_ERASE) { sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20); sisusb->sisusb_cursor_size_to = -1; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return; } @@ -919,7 +900,7 @@ sisusbcon_cursor(struct vc_data *c, int sisusb->sisusb_cursor_size_to = to; } - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); } static int @@ -961,7 +942,7 @@ sisusbcon_scroll_area(struct vc_data *c, sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t), (u32)SISUSB_HADDR(0, t), length, &written); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 1; } @@ -994,7 +975,7 @@ sisusbcon_scroll(struct vc_data *c, int /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -1084,7 +1065,7 @@ sisusbcon_scroll(struct vc_data *c, int c->vc_pos = c->vc_pos - oldorigin + c->vc_origin; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 1; } @@ -1106,7 +1087,7 @@ sisusbcon_set_origin(struct vc_data *c) /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -1116,7 +1097,7 @@ sisusbcon_set_origin(struct vc_data *c) sisusb->con_rolled_over = 0; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 1; } @@ -1133,7 +1114,7 @@ sisusbcon_resize(struct vc_data *c, unsi fh = sisusb->current_font_height; - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); /* We are quite unflexible as regards resizing. The vt code * handles sizes where the line length isn't equal the pitch @@ -1167,7 +1148,7 @@ sisusbcon_do_font_op(struct sisusb_usb_d if ((slot != 0 && slot != 2) || !fh) { if (uplock) - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EINVAL; } @@ -1327,7 +1308,7 @@ sisusbcon_do_font_op(struct sisusb_usb_d } if (uplock) - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); if (dorecalc && c) { int i, rows = c->vc_scan_lines / fh; @@ -1351,7 +1332,7 @@ sisusbcon_do_font_op(struct sisusb_usb_d font_op_error: if (uplock) - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -EIO; } @@ -1417,19 +1398,19 @@ sisusbcon_font_get(struct vc_data *c, st font->charcount = 256; if (!font->data) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } if (!sisusb->font_backup) { - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return -ENODEV; } /* Copy 256 chars only, like vgacon */ memcpy(font->data, sisusb->font_backup, 256 * 32); - up(&sisusb->lock); + mutex_unlock(&sisusb->lock); return 0; } @@ -1486,7 +1467,7 @@ static int sisusbdummycon_dummy(void) #define SISUSBCONDUMMY (void *)sisusbdummycon_dummy -const struct consw sisusb_dummy_con = { +static const struct consw sisusb_dummy_con = { .owner = THIS_MODULE, .con_startup = sisusbdummycon_startup, .con_init = sisusbdummycon_init, @@ -1512,14 +1493,14 @@ sisusb_console_init(struct sisusb_usb_da { int i, ret, minor = sisusb->minor; - down(&disconnect_sem); + mutex_lock(&disconnect_mutex); - down(&sisusb->lock); + mutex_lock(&sisusb->lock); /* Erm.. that should not happen */ if (sisusb->haveconsole || !sisusb->SiS_Pr) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return 1; } @@ -1529,15 +1510,15 @@ sisusb_console_init(struct sisusb_usb_da if (first > last || first > MAX_NR_CONSOLES || last > MAX_NR_CONSOLES) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return 1; } /* If gfxcore not initialized or no consoles given, quit graciously */ if (!sisusb->gfxinit || first < 1 || last < 1) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); return 0; } @@ -1547,8 +1528,8 @@ sisusb_console_init(struct sisusb_usb_da /* Set up text mode (and upload default font) */ if (sisusb_reset_text_mode(sisusb, 1)) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Failed to set up text mode\n", minor); @@ -1571,16 +1552,16 @@ sisusb_console_init(struct sisusb_usb_da /* Allocate screen buffer */ if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); printk(KERN_ERR "sisusbvga[%d]: Failed to allocate screen buffer\n", minor); return 1; } - up(&sisusb->lock); - up(&disconnect_sem); + mutex_unlock(&sisusb->lock); + mutex_unlock(&disconnect_mutex); /* Now grab the desired console(s) */ ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c index 044fa44..968f0d3 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.c +++ b/drivers/usb/misc/sisusbvga/sisusb_init.c @@ -74,6 +74,7 @@ SiSUSB_InitPtr(struct SiS_Private *SiS_P /* HELPER: Get ModeID */ /*********************************************/ +#if 0 unsigned short SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth) { @@ -157,6 +158,7 @@ SiSUSB_GetModeID(int HDisplay, int VDisp return ModeIndex; } +#endif /* 0 */ /*********************************************/ /* HELPER: SetReg, GetReg */ @@ -233,7 +235,7 @@ SiS_DisplayOn(struct SiS_Private *SiS_Pr /* HELPER: Init Port Addresses */ /*********************************************/ -void +static void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr) { SiS_Pr->SiS_P3c4 = BaseAddr + 0x14; diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h index 5b11577..f05f832 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.h +++ b/drivers/usb/misc/sisusbvga/sisusb_init.h @@ -690,7 +690,7 @@ static const struct SiS_CRT1Table SiSUSB 0x41}} /* 0x54 */ }; -static struct SiS_VCLKData SiSUSB_VCLKData[] = +static const struct SiS_VCLKData SiSUSB_VCLKData[] = { { 0x1b,0xe1, 25}, /* 0x00 */ { 0x4e,0xe4, 28}, /* 0x01 */ @@ -808,8 +808,8 @@ static struct SiS_VCLKData SiSUSB_VCLKDa { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ }; -void SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr); -unsigned short SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth); +extern struct mutex disconnect_mutex; + int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); @@ -826,5 +826,19 @@ extern int sisusb_setidxregor(struct sis extern int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand); +void sisusb_delete(struct kref *kref); +int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data); +int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data); +int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, + u32 dest, int length, size_t *bytes_written); +int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init); +int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot, + u8 *arg, int cmapsz, int ch512, int dorecalc, + struct vc_data *c, int fh, int uplock); +void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location); +int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last); +void sisusb_console_exit(struct sisusb_usb_data *sisusb); +void sisusb_init_concode(void); + #endif diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h index 94edd47..f325ecb 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_struct.h +++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h @@ -161,7 +161,7 @@ struct SiS_Private const struct SiS_Ext *SiS_EModeIDTable; const struct SiS_Ext2 *SiS_RefIndex; const struct SiS_CRT1Table *SiS_CRT1Table; - struct SiS_VCLKData *SiS_VCLKData; + const struct SiS_VCLKData *SiS_VCLKData; const struct SiS_ModeResInfo *SiS_ModeResInfo; }; diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index ccc5e82..81ba14c 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -802,7 +802,9 @@ error: if (u == urb || !u->dev) continue; + spin_unlock(&ctx->lock); status = usb_unlink_urb (u); + spin_lock(&ctx->lock); switch (status) { case -EINPROGRESS: case -EBUSY: @@ -1335,7 +1337,9 @@ struct iso_context { unsigned pending; spinlock_t lock; struct completion done; + int submit_error; unsigned long errors; + unsigned long packet_count; struct usbtest_dev *dev; }; @@ -1346,10 +1350,14 @@ static void iso_callback (struct urb *ur spin_lock(&ctx->lock); ctx->count--; + ctx->packet_count += urb->number_of_packets; if (urb->error_count > 0) ctx->errors += urb->error_count; + else if (urb->status != 0) + ctx->errors += urb->number_of_packets; - if (urb->status == 0 && ctx->count > (ctx->pending - 1)) { + if (urb->status == 0 && ctx->count > (ctx->pending - 1) + && !ctx->submit_error) { int status = usb_submit_urb (urb, GFP_ATOMIC); switch (status) { case 0: @@ -1360,6 +1368,8 @@ static void iso_callback (struct urb *ur status); /* FALLTHROUGH */ case -ENODEV: /* disconnected */ + case -ESHUTDOWN: /* endpoint disabled */ + ctx->submit_error = 1; break; } } @@ -1369,8 +1379,8 @@ static void iso_callback (struct urb *ur if (ctx->pending == 0) { if (ctx->errors) dev_dbg (&ctx->dev->intf->dev, - "iso test, %lu errors\n", - ctx->errors); + "iso test, %lu errors out of %lu\n", + ctx->errors, ctx->packet_count); complete (&ctx->done); } done: @@ -1431,15 +1441,14 @@ test_iso_queue (struct usbtest_dev *dev, struct usb_device *udev; unsigned i; unsigned long packets = 0; - int status; + int status = 0; struct urb *urbs[10]; /* FIXME no limit */ if (param->sglen > 10) return -EDOM; + memset(&context, 0, sizeof context); context.count = param->iterations * param->sglen; - context.pending = param->sglen; - context.errors = 0; context.dev = dev; init_completion (&context.done); spin_lock_init (&context.lock); @@ -1471,6 +1480,7 @@ test_iso_queue (struct usbtest_dev *dev, spin_lock_irq (&context.lock); for (i = 0; i < param->sglen; i++) { + ++context.pending; status = usb_submit_urb (urbs [i], SLAB_ATOMIC); if (status < 0) { ERROR (dev, "submit iso[%d], error %d\n", i, status); @@ -1481,12 +1491,26 @@ test_iso_queue (struct usbtest_dev *dev, simple_free_urb (urbs [i]); context.pending--; + context.submit_error = 1; + break; } } spin_unlock_irq (&context.lock); wait_for_completion (&context.done); - return 0; + + /* + * Isochronous transfers are expected to fail sometimes. As an + * arbitrary limit, we will report an error if any submissions + * fail or if the transfer failure rate is > 10%. + */ + if (status != 0) + ; + else if (context.submit_error) + status = -EACCES; + else if (context.errors > context.packet_count / 10) + status = -EIO; + return status; fail: for (i = 0; i < param->sglen; i++) { diff --git a/drivers/usb/mon/mon_dma.c b/drivers/usb/mon/mon_dma.c index 0a1367b..ddcfc01 100644 --- a/drivers/usb/mon/mon_dma.c +++ b/drivers/usb/mon/mon_dma.c @@ -13,7 +13,10 @@ #include #include /* Only needed for declarations in usb_mon.h */ #include "usb_mon.h" -#ifdef __i386__ /* CONFIG_ARCH_I386 does not exit */ +/* + * PC-compatibles, are, fortunately, sufficiently cache-coherent for this. + */ +#if defined(__i386__) || defined(__x86_64__) /* CONFIG_ARCH_I386 doesn't exit */ #define MON_HAS_UNMAP 1 #define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT) diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 6ecc273..275a66f 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -97,6 +97,7 @@ static void mon_submit(struct usb_bus *u if (mbus->nreaders == 0) goto out_locked; + mbus->cnt_events++; list_for_each (pos, &mbus->r_list) { r = list_entry(pos, struct mon_reader, r_link); r->rnf_submit(r->r_data, urb); @@ -113,20 +114,32 @@ out_unlocked: /* */ -static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int err) +static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error) { struct mon_bus *mbus; + unsigned long flags; + struct list_head *pos; + struct mon_reader *r; mbus = ubus->mon_bus; if (mbus == NULL) goto out_unlocked; - /* - * XXX Capture the error code and the 'E' event. - */ + spin_lock_irqsave(&mbus->lock, flags); + if (mbus->nreaders == 0) + goto out_locked; + mbus->cnt_events++; + list_for_each (pos, &mbus->r_list) { + r = list_entry(pos, struct mon_reader, r_link); + r->rnf_error(r->r_data, urb, error); + } + + spin_unlock_irqrestore(&mbus->lock, flags); return; +out_locked: + spin_unlock_irqrestore(&mbus->lock, flags); out_unlocked: return; } @@ -152,6 +165,7 @@ static void mon_complete(struct usb_bus } spin_lock_irqsave(&mbus->lock, flags); + mbus->cnt_events++; list_for_each (pos, &mbus->r_list) { r = list_entry(pos, struct mon_reader, r_link); r->rnf_complete(r->r_data, urb); @@ -163,7 +177,6 @@ static void mon_complete(struct usb_bus /* * Stop monitoring. - * Obviously this must be well locked, so no need to play with mb's. */ static void mon_stop(struct mon_bus *mbus) { diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c index 6e4b165..1fe01d9 100644 --- a/drivers/usb/mon/mon_stat.c +++ b/drivers/usb/mon/mon_stat.c @@ -31,8 +31,8 @@ static int mon_stat_open(struct inode *i mbus = inode->u.generic_ip; sp->slen = snprintf(sp->str, STAT_BUF_SIZE, - "nreaders %d text_lost %u\n", - mbus->nreaders, mbus->cnt_text_lost); + "nreaders %d events %u text_lost %u\n", + mbus->nreaders, mbus->cnt_events, mbus->cnt_text_lost); file->private_data = sp; return 0; diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index ac043ec..e02c1a3 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -26,10 +26,13 @@ #define SETUP_MAX 8 /* * This limit exists to prevent OOMs when the user process stops reading. + * If usbmon were available to unprivileged processes, it might be open + * to a local DoS. But we have to keep to root in order to prevent + * password sniffing from HID devices. */ -#define EVENT_MAX 25 +#define EVENT_MAX (2*PAGE_SIZE / sizeof(struct mon_event_text)) -#define PRINTF_DFL 130 +#define PRINTF_DFL 160 struct mon_event_text { struct list_head e_link; @@ -111,7 +114,7 @@ static inline char mon_text_get_data(str * number of corner cases, but it seems that the following is * more or less safe. * - * We do not even try to look transfer_buffer, because it can + * We do not even try to look at transfer_buffer, because it can * contain non-NULL garbage in case the upper level promised to * set DMA for the HCD. */ @@ -179,6 +182,32 @@ static void mon_text_complete(void *data mon_text_event(rp, urb, 'C'); } +static void mon_text_error(void *data, struct urb *urb, int error) +{ + struct mon_reader_text *rp = data; + struct mon_event_text *ep; + + if (rp->nevents >= EVENT_MAX || + (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) { + rp->r.m_bus->cnt_text_lost++; + return; + } + + ep->type = 'E'; + ep->pipe = urb->pipe; + ep->id = (unsigned long) urb; + ep->tstamp = 0; + ep->length = 0; + ep->status = error; + + ep->setup_flag = '-'; + ep->data_flag = 'E'; + + rp->nevents++; + list_add_tail(&ep->e_link, &rp->e_list); + wake_up(&rp->wait); +} + /* * Fetch next event from the circular buffer. */ @@ -232,6 +261,7 @@ static int mon_text_open(struct inode *i rp->r.m_bus = mbus; rp->r.r_data = rp; rp->r.rnf_submit = mon_text_submit; + rp->r.rnf_error = mon_text_error; rp->r.rnf_complete = mon_text_complete; snprintf(rp->slab_name, SLAB_NAME_SZ, "mon%dt_%lx", ubus->busnum, diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h index 8e0613c..33678c2 100644 --- a/drivers/usb/mon/usb_mon.h +++ b/drivers/usb/mon/usb_mon.h @@ -27,6 +27,7 @@ struct mon_bus { struct kref ref; /* Under mon_lock */ /* Stats */ + unsigned int cnt_events; unsigned int cnt_text_lost; }; @@ -39,6 +40,7 @@ struct mon_reader { void *r_data; /* Use container_of instead? */ void (*rnf_submit)(void *data, struct urb *urb); + void (*rnf_error)(void *data, struct urb *urb, int error); void (*rnf_complete)(void *data, struct urb *urb); }; diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index efd6ca7..0540596 100644 --- a/drivers/usb/net/Kconfig +++ b/drivers/usb/net/Kconfig @@ -301,21 +301,4 @@ config USB_NET_ZAURUS some cases CDC MDLM) protocol, not "g_ether". -config USB_ZD1201 - tristate "USB ZD1201 based Wireless device support" - depends on NET_RADIO - select FW_LOADER - ---help--- - Say Y if you want to use wireless LAN adapters based on the ZyDAS - ZD1201 chip. - - This driver makes the adapter appear as a normal Ethernet interface, - typically on wlan0. - - The zd1201 device requires external firmware to be loaded. - This can be found at http://linux-lc100020.sourceforge.net/ - - To compile this driver as a module, choose M here: the - module will be called zd1201. - endmenu diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile index a21e6ea..160f19d 100644 --- a/drivers/usb/net/Makefile +++ b/drivers/usb/net/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndi obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o obj-$(CONFIG_USB_USBNET) += usbnet.o -obj-$(CONFIG_USB_ZD1201) += zd1201.o ifeq ($(CONFIG_USB_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 12b599a..37111ac 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c @@ -912,6 +912,10 @@ static const struct usb_device_id produc USB_DEVICE (0x0b95, 0x7720), .driver_info = (unsigned long) &ax88772_info, }, { + // ASIX AX88178 10/100/1000 + USB_DEVICE (0x0b95, 0x1780), + .driver_info = (unsigned long) &ax88772_info, +}, { // Linksys USB200M Rev 2 USB_DEVICE (0x13b1, 0x0018), .driver_info = (unsigned long) &ax88772_info, diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c index 63f1f3b..efd195b 100644 --- a/drivers/usb/net/cdc_ether.c +++ b/drivers/usb/net/cdc_ether.c @@ -31,7 +31,7 @@ #include #include #include #include -#include +#include #include "usbnet.h" @@ -455,6 +455,18 @@ #define ZAURUS_MASTER_INTERFACE \ .driver_info = 0, }, +/* Olympus has some models with a Zaurus-compatible option. + * R-1000 uses a FreeScale i.MXL cpu (ARMv4T) + */ +{ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x07B4, + .idProduct = 0x0F02, /* R-1000 */ + ZAURUS_MASTER_INTERFACE, + .driver_info = 0, +}, + /* * WHITELIST!!! * diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 7683926..ab21f96 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -163,6 +163,8 @@ static int get_registers(pegasus_t * peg /* using ATOMIC, we'd never wake up if we slept */ if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { + if (ret == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus)) dev_err(&pegasus->intf->dev, "%s, status %d\n", __FUNCTION__, ret); @@ -217,6 +219,8 @@ static int set_registers(pegasus_t * peg set_current_state(TASK_UNINTERRUPTIBLE); if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { + if (ret == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus)) dev_err(&pegasus->intf->dev, "%s, status %d\n", __FUNCTION__, ret); @@ -268,6 +272,8 @@ static int set_register(pegasus_t * pega set_current_state(TASK_UNINTERRUPTIBLE); if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { + if (ret == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus)) dev_err(&pegasus->intf->dev, "%s, status %d\n", __FUNCTION__, ret); @@ -298,10 +304,13 @@ static int update_eth_regs_async(pegasus (char *) &pegasus->dr, pegasus->eth_regs, 3, ctrl_callback, pegasus); - if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) + if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { + if (ret == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus)) dev_err(&pegasus->intf->dev, "%s, status %d\n", __FUNCTION__, ret); + } return ret; } @@ -692,7 +701,10 @@ goon: usb_rcvbulkpipe(pegasus->usb, 1), pegasus->rx_skb->data, PEGASUS_MTU + 8, read_bulk_callback, pegasus); - if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) { + rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC); + if (rx_status == -ENODEV) + netif_device_detach(pegasus->net); + else if (rx_status) { pegasus->flags |= PEGASUS_RX_URB_FAIL; goto tl_sched; } else { @@ -709,6 +721,7 @@ static void rx_fixup(unsigned long data) { pegasus_t *pegasus; unsigned long flags; + int status; pegasus = (pegasus_t *) data; if (pegasus->flags & PEGASUS_UNPLUG) @@ -734,7 +747,10 @@ static void rx_fixup(unsigned long data) pegasus->rx_skb->data, PEGASUS_MTU + 8, read_bulk_callback, pegasus); try_again: - if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) { + status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC); + if (status == -ENODEV) + netif_device_detach(pegasus->net); + else if (status) { pegasus->flags |= PEGASUS_RX_URB_FAIL; tasklet_schedule(&pegasus->rx_tl); } else { @@ -836,6 +852,8 @@ static void intr_callback(struct urb *ur } status = usb_submit_urb(urb, SLAB_ATOMIC); + if (status == -ENODEV) + netif_device_detach(pegasus->net); if (status && netif_msg_timer(pegasus)) printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n", net->name, status); @@ -874,6 +892,7 @@ static int pegasus_start_xmit(struct sk_ /* cleanup should already have been scheduled */ break; case -ENODEV: /* disconnect() upcoming */ + netif_device_detach(pegasus->net); break; default: pegasus->stats.tx_errors++; @@ -999,6 +1018,8 @@ static int pegasus_open(struct net_devic pegasus->rx_skb->data, PEGASUS_MTU + 8, read_bulk_callback, pegasus); if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) { + if (res == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_ifup(pegasus)) pr_debug("%s: failed rx_urb, %d", net->name, res); goto exit; @@ -1009,6 +1030,8 @@ static int pegasus_open(struct net_devic pegasus->intr_buff, sizeof (pegasus->intr_buff), intr_callback, pegasus, pegasus->intr_interval); if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) { + if (res == -ENODEV) + netif_device_detach(pegasus->net); if (netif_msg_ifup(pegasus)) pr_debug("%s: failed intr_urb, %d\n", net->name, res); usb_kill_urb(pegasus->rx_urb); diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c index 94ddfe1..f551546 100644 --- a/drivers/usb/net/rndis_host.c +++ b/drivers/usb/net/rndis_host.c @@ -30,7 +30,7 @@ #include #include #include #include -#include +#include #include "usbnet.h" diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c index f7ac9d6..813e470 100644 --- a/drivers/usb/net/zaurus.c +++ b/drivers/usb/net/zaurus.c @@ -30,7 +30,7 @@ #include #include #include #include -#include +#include #include "usbnet.h" @@ -109,7 +109,7 @@ static const struct driver_info zaurus_s .check_connect = always_connected, .bind = zaurus_bind, .unbind = usbnet_cdc_unbind, - .tx_fixup = zaurus_tx_fixup, + .tx_fixup = zaurus_tx_fixup, }; #define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info) @@ -119,7 +119,7 @@ static const struct driver_info zaurus_p .check_connect = always_connected, .bind = zaurus_bind, .unbind = usbnet_cdc_unbind, - .tx_fixup = zaurus_tx_fixup, + .tx_fixup = zaurus_tx_fixup, }; #define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info) @@ -129,7 +129,7 @@ static const struct driver_info olympus_ .check_connect = always_connected, .bind = zaurus_bind, .unbind = usbnet_cdc_unbind, - .tx_fixup = zaurus_tx_fixup, + .tx_fixup = zaurus_tx_fixup, }; #define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info) @@ -228,6 +228,11 @@ bad_detail: detail->bDetailData[2]); goto bad_desc; } + + /* same extra framing as for non-BLAN mode */ + dev->net->hard_header_len += 6; + dev->rx_urb_size = dev->net->hard_header_len + + dev->net->mtu; break; } next_desc: @@ -258,7 +263,7 @@ static const struct driver_info bogus_md .description = "pseudo-MDLM (BLAN) device", .flags = FLAG_FRAMING_Z, .check_connect = always_connected, - .tx_fixup = zaurus_tx_fixup, + .tx_fixup = zaurus_tx_fixup, .bind = blan_mdlm_bind, }; @@ -367,13 +372,13 @@ static struct usb_driver zaurus_driver = static int __init zaurus_init(void) { - return usb_register(&zaurus_driver); + return usb_register(&zaurus_driver); } module_init(zaurus_init); static void __exit zaurus_exit(void) { - usb_deregister(&zaurus_driver); + usb_deregister(&zaurus_driver); } module_exit(zaurus_exit); diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c deleted file mode 100644 index 9b1e4ed..0000000 --- a/drivers/usb/net/zd1201.c +++ /dev/null @@ -1,1944 +0,0 @@ -/* - * Driver for ZyDAS zd1201 based wireless USB devices. - * - * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Parts of this driver have been derived from a wlan-ng version - * modified by ZyDAS. They also made documentation available, thanks! - * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "zd1201.h" - -static struct usb_device_id zd1201_table[] = { - {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */ - {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ - {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ - {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ - {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */ - {} -}; - -static int ap = 0; /* Are we an AP or a normal station? */ - -#define ZD1201_VERSION "0.15" - -MODULE_AUTHOR("Jeroen Vreeken "); -MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters"); -MODULE_VERSION(ZD1201_VERSION); -MODULE_LICENSE("GPL"); -module_param(ap, int, 0); -MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded"); -MODULE_DEVICE_TABLE(usb, zd1201_table); - - -static int zd1201_fw_upload(struct usb_device *dev, int apfw) -{ - const struct firmware *fw_entry; - char* data; - unsigned long len; - int err; - unsigned char ret; - char *buf; - char *fwfile; - - if (apfw) - fwfile = "zd1201-ap.fw"; - else - fwfile = "zd1201.fw"; - - err = request_firmware(&fw_entry, fwfile, &dev->dev); - if (err) { - dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile); - dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n"); - dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info\n"); - return err; - } - - data = fw_entry->data; - len = fw_entry->size; - - buf = kmalloc(1024, GFP_ATOMIC); - if (!buf) - goto exit; - - while (len > 0) { - int translen = (len > 1024) ? 1024 : len; - memcpy(buf, data, translen); - - err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0, - USB_DIR_OUT | 0x40, 0, 0, buf, translen, - ZD1201_FW_TIMEOUT); - if (err < 0) - goto exit; - - len -= translen; - data += translen; - } - - err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2, - USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT); - if (err < 0) - goto exit; - - err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4, - USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT); - if (err < 0) - goto exit; - - if (ret & 0x80) { - err = -EIO; - goto exit; - } - - err = 0; -exit: - kfree(buf); - release_firmware(fw_entry); - return err; -} - -static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs) -{ - struct zd1201 *zd = urb->context; - - switch(urb->status) { - case -EILSEQ: - case -ENODEV: - case -ETIMEDOUT: - case -ENOENT: - case -EPIPE: - case -EOVERFLOW: - case -ESHUTDOWN: - dev_warn(&zd->usb->dev, "%s: urb failed: %d\n", - zd->dev->name, urb->status); - } - - kfree(urb->transfer_buffer); - usb_free_urb(urb); - return; -} - -/* cmdreq message: - u32 type - u16 cmd - u16 parm0 - u16 parm1 - u16 parm2 - u8 pad[4] - - total: 4 + 2 + 2 + 2 + 2 + 4 = 16 -*/ -static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0, - int parm1, int parm2) -{ - unsigned char *command; - int ret; - struct urb *urb; - - command = kmalloc(16, GFP_ATOMIC); - if (!command) - return -ENOMEM; - - *((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ); - *((__le16*)&command[4]) = cpu_to_le16(cmd); - *((__le16*)&command[6]) = cpu_to_le16(parm0); - *((__le16*)&command[8]) = cpu_to_le16(parm1); - *((__le16*)&command[10])= cpu_to_le16(parm2); - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - kfree(command); - return -ENOMEM; - } - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), - command, 16, zd1201_usbfree, zd); - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) { - kfree(command); - usb_free_urb(urb); - } - - return ret; -} - -/* Callback after sending out a packet */ -static void zd1201_usbtx(struct urb *urb, struct pt_regs *regs) -{ - struct zd1201 *zd = urb->context; - netif_wake_queue(zd->dev); - return; -} - -/* Incoming data */ -static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs) -{ - struct zd1201 *zd = urb->context; - int free = 0; - unsigned char *data = urb->transfer_buffer; - struct sk_buff *skb; - unsigned char type; - - if (!zd) { - free = 1; - goto exit; - } - - switch(urb->status) { - case -EILSEQ: - case -ENODEV: - case -ETIMEDOUT: - case -ENOENT: - case -EPIPE: - case -EOVERFLOW: - case -ESHUTDOWN: - dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n", - zd->dev->name, urb->status); - free = 1; - goto exit; - } - - if (urb->status != 0 || urb->actual_length == 0) - goto resubmit; - - type = data[0]; - if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) { - memcpy(zd->rxdata, data, urb->actual_length); - zd->rxlen = urb->actual_length; - zd->rxdatas = 1; - wake_up(&zd->rxdataq); - } - /* Info frame */ - if (type == ZD1201_PACKET_INQUIRE) { - int i = 0; - unsigned short infotype, framelen, copylen; - framelen = le16_to_cpu(*(__le16*)&data[4]); - infotype = le16_to_cpu(*(__le16*)&data[6]); - - if (infotype == ZD1201_INF_LINKSTATUS) { - short linkstatus; - - linkstatus = le16_to_cpu(*(__le16*)&data[8]); - switch(linkstatus) { - case 1: - netif_carrier_on(zd->dev); - break; - case 2: - netif_carrier_off(zd->dev); - break; - case 3: - netif_carrier_off(zd->dev); - break; - case 4: - netif_carrier_on(zd->dev); - break; - default: - netif_carrier_off(zd->dev); - } - goto resubmit; - } - if (infotype == ZD1201_INF_ASSOCSTATUS) { - short status = le16_to_cpu(*(__le16*)(data+8)); - int event; - union iwreq_data wrqu; - - switch (status) { - case ZD1201_ASSOCSTATUS_STAASSOC: - case ZD1201_ASSOCSTATUS_REASSOC: - event = IWEVREGISTERED; - break; - case ZD1201_ASSOCSTATUS_DISASSOC: - case ZD1201_ASSOCSTATUS_ASSOCFAIL: - case ZD1201_ASSOCSTATUS_AUTHFAIL: - default: - event = IWEVEXPIRED; - } - memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - - /* Send event to user space */ - wireless_send_event(zd->dev, event, &wrqu, NULL); - - goto resubmit; - } - if (infotype == ZD1201_INF_AUTHREQ) { - union iwreq_data wrqu; - - memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - /* There isn't a event that trully fits this request. - We assume that userspace will be smart enough to - see a new station being expired and sends back a - authstation ioctl to authorize it. */ - wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL); - goto resubmit; - } - /* Other infotypes are handled outside this handler */ - zd->rxlen = 0; - while (i < urb->actual_length) { - copylen = le16_to_cpu(*(__le16*)&data[i+2]); - /* Sanity check, sometimes we get junk */ - if (copylen+zd->rxlen > sizeof(zd->rxdata)) - break; - memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen); - zd->rxlen += copylen; - i += 64; - } - if (i >= urb->actual_length) { - zd->rxdatas = 1; - wake_up(&zd->rxdataq); - } - goto resubmit; - } - /* Actual data */ - if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) { - int datalen = urb->actual_length-1; - unsigned short len, fc, seq; - struct hlist_node *node; - - len = ntohs(*(__be16 *)&data[datalen-2]); - if (len>datalen) - len=datalen; - fc = le16_to_cpu(*(__le16 *)&data[datalen-16]); - seq = le16_to_cpu(*(__le16 *)&data[datalen-24]); - - if(zd->monitor) { - if (datalen < 24) - goto resubmit; - if (!(skb = dev_alloc_skb(datalen+24))) - goto resubmit; - - memcpy(skb_put(skb, 2), &data[datalen-16], 2); - memcpy(skb_put(skb, 2), &data[datalen-2], 2); - memcpy(skb_put(skb, 6), &data[datalen-14], 6); - memcpy(skb_put(skb, 6), &data[datalen-22], 6); - memcpy(skb_put(skb, 6), &data[datalen-8], 6); - memcpy(skb_put(skb, 2), &data[datalen-24], 2); - memcpy(skb_put(skb, len), data, len); - skb->dev = zd->dev; - skb->dev->last_rx = jiffies; - skb->protocol = eth_type_trans(skb, zd->dev); - zd->stats.rx_packets++; - zd->stats.rx_bytes += skb->len; - netif_rx(skb); - goto resubmit; - } - - if ((seq & IEEE80211_SCTL_FRAG) || - (fc & IEEE80211_FCTL_MOREFRAGS)) { - struct zd1201_frag *frag = NULL; - char *ptr; - - if (datalen<14) - goto resubmit; - if ((seq & IEEE80211_SCTL_FRAG) == 0) { - frag = kmalloc(sizeof(*frag), GFP_ATOMIC); - if (!frag) - goto resubmit; - skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2); - if (!skb) { - kfree(frag); - goto resubmit; - } - frag->skb = skb; - frag->seq = seq & IEEE80211_SCTL_SEQ; - skb_reserve(skb, 2); - memcpy(skb_put(skb, 12), &data[datalen-14], 12); - memcpy(skb_put(skb, 2), &data[6], 2); - memcpy(skb_put(skb, len), data+8, len); - hlist_add_head(&frag->fnode, &zd->fraglist); - goto resubmit; - } - hlist_for_each_entry(frag, node, &zd->fraglist, fnode) - if(frag->seq == (seq&IEEE80211_SCTL_SEQ)) - break; - if (!frag) - goto resubmit; - skb = frag->skb; - ptr = skb_put(skb, len); - if (ptr) - memcpy(ptr, data+8, len); - if (fc & IEEE80211_FCTL_MOREFRAGS) - goto resubmit; - hlist_del_init(&frag->fnode); - kfree(frag); - /* Fallthrough */ - } else { - if (datalen<14) - goto resubmit; - skb = dev_alloc_skb(len + 14 + 2); - if (!skb) - goto resubmit; - skb_reserve(skb, 2); - memcpy(skb_put(skb, 12), &data[datalen-14], 12); - memcpy(skb_put(skb, 2), &data[6], 2); - memcpy(skb_put(skb, len), data+8, len); - } - skb->dev = zd->dev; - skb->dev->last_rx = jiffies; - skb->protocol = eth_type_trans(skb, zd->dev); - zd->stats.rx_packets++; - zd->stats.rx_bytes += skb->len; - netif_rx(skb); - } -resubmit: - memset(data, 0, ZD1201_RXSIZE); - - urb->status = 0; - urb->dev = zd->usb; - if(usb_submit_urb(urb, GFP_ATOMIC)) - free = 1; - -exit: - if (free) { - zd->rxlen = 0; - zd->rxdatas = 1; - wake_up(&zd->rxdataq); - kfree(urb->transfer_buffer); - } - return; -} - -static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata, - unsigned int riddatalen) -{ - int err; - int i = 0; - int code; - int rid_fid; - int length; - unsigned char *pdata; - - zd->rxdatas = 0; - err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0); - if (err) - return err; - - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen) - return -EIO; - - code = le16_to_cpu(*(__le16*)(&zd->rxdata[4])); - rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6])); - length = le16_to_cpu(*(__le16*)(&zd->rxdata[8])); - if (length > zd->rxlen) - length = zd->rxlen-6; - - /* If access bit is not on, then error */ - if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid ) - return -EINVAL; - - /* Not enough buffer for allocating data */ - if (riddatalen != (length - 4)) { - dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n", - riddatalen, zd->rxlen, length, rid, rid_fid); - return -ENODATA; - } - - zd->rxdatas = 0; - /* Issue SetRxRid commnd */ - err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length); - if (err) - return err; - - /* Receive RID record from resource packets */ - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen) - return -EIO; - - if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) { - dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n", - zd->rxdata[zd->rxlen-1]); - return -EINVAL; - } - - /* Set the data pointer and received data length */ - pdata = zd->rxdata; - length = zd->rxlen; - - do { - int actual_length; - - actual_length = (length > 64) ? 64 : length; - - if(pdata[0] != 0x3) { - dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n", - pdata[0]); - return -EINVAL; - } - - if (actual_length != 64) { - /* Trim the last packet type byte */ - actual_length--; - } - - /* Skip the 4 bytes header (RID length and RID) */ - if(i == 0) { - pdata += 8; - actual_length -= 8; - } - else { - pdata += 4; - actual_length -= 4; - } - - memcpy(riddata, pdata, actual_length); - riddata += actual_length; - pdata += actual_length; - length -= 64; - i++; - } while (length > 0); - - return 0; -} - -/* - * resreq: - * byte type - * byte sequence - * u16 reserved - * byte data[12] - * total: 16 - */ -static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait) -{ - int err; - unsigned char *request; - int reqlen; - char seq=0; - struct urb *urb; - gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC; - - len += 4; /* first 4 are for header */ - - zd->rxdatas = 0; - zd->rxlen = 0; - for (seq=0; len > 0; seq++) { - request = kmalloc(16, gfp_mask); - if (!request) - return -ENOMEM; - urb = usb_alloc_urb(0, gfp_mask); - if (!urb) { - kfree(request); - return -ENOMEM; - } - memset(request, 0, 16); - reqlen = len>12 ? 12 : len; - request[0] = ZD1201_USB_RESREQ; - request[1] = seq; - request[2] = 0; - request[3] = 0; - if (request[1] == 0) { - /* add header */ - *(__le16*)&request[4] = cpu_to_le16((len-2+1)/2); - *(__le16*)&request[6] = cpu_to_le16(rid); - memcpy(request+8, buf, reqlen-4); - buf += reqlen-4; - } else { - memcpy(request+4, buf, reqlen); - buf += reqlen; - } - - len -= reqlen; - - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, - zd->endp_out2), request, 16, zd1201_usbfree, zd); - err = usb_submit_urb(urb, gfp_mask); - if (err) - goto err; - } - - request = kmalloc(16, gfp_mask); - if (!request) - return -ENOMEM; - urb = usb_alloc_urb(0, gfp_mask); - if (!urb) { - kfree(request); - return -ENOMEM; - } - *((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ); - *((__le16*)&request[4]) = - cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT); - *((__le16*)&request[6]) = cpu_to_le16(rid); - *((__le16*)&request[8]) = cpu_to_le16(0); - *((__le16*)&request[10]) = cpu_to_le16(0); - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), - request, 16, zd1201_usbfree, zd); - err = usb_submit_urb(urb, gfp_mask); - if (err) - goto err; - - if (wait) { - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) { - dev_dbg(&zd->usb->dev, "wrong or no RID received\n"); - } - } - - return 0; -err: - kfree(request); - usb_free_urb(urb); - return err; -} - -static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val) -{ - int err; - __le16 zdval; - - err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16)); - if (err) - return err; - *val = le16_to_cpu(zdval); - return 0; -} - -static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val) -{ - __le16 zdval = cpu_to_le16(val); - return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1)); -} - -static int zd1201_drvr_start(struct zd1201 *zd) -{ - int err, i; - short max; - __le16 zdmax; - unsigned char *buffer; - - buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - usb_fill_bulk_urb(zd->rx_urb, zd->usb, - usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE, - zd1201_usbrx, zd); - - err = usb_submit_urb(zd->rx_urb, GFP_KERNEL); - if (err) - goto err_buffer; - - err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); - if (err) - goto err_urb; - - err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax, - sizeof(__le16)); - if (err) - goto err_urb; - - max = le16_to_cpu(zdmax); - for (i=0; irx_urb); - return err; -err_buffer: - kfree(buffer); - return err; -} - -/* Magic alert: The firmware doesn't seem to like the MAC state being - * toggled in promisc (aka monitor) mode. - * (It works a number of times, but will halt eventually) - * So we turn it of before disabling and on after enabling if needed. - */ -static int zd1201_enable(struct zd1201 *zd) -{ - int err; - - if (zd->mac_enabled) - return 0; - - err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0); - if (!err) - zd->mac_enabled = 1; - - if (zd->monitor) - err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1); - - return err; -} - -static int zd1201_disable(struct zd1201 *zd) -{ - int err; - - if (!zd->mac_enabled) - return 0; - if (zd->monitor) { - err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); - if (err) - return err; - } - - err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0); - if (!err) - zd->mac_enabled = 0; - return err; -} - -static int zd1201_mac_reset(struct zd1201 *zd) -{ - if (!zd->mac_enabled) - return 0; - zd1201_disable(zd); - return zd1201_enable(zd); -} - -static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen) -{ - int err, val; - char buf[IW_ESSID_MAX_SIZE+2]; - - err = zd1201_disable(zd); - if (err) - return err; - - val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; - val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val); - if (err) - return err; - - *(__le16 *)buf = cpu_to_le16(essidlen); - memcpy(buf+2, essid, essidlen); - if (!zd->ap) { /* Normal station */ - err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, - IW_ESSID_MAX_SIZE+2, 1); - if (err) - return err; - } else { /* AP */ - err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf, - IW_ESSID_MAX_SIZE+2, 1); - if (err) - return err; - } - - err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, - zd->dev->dev_addr, zd->dev->addr_len, 1); - if (err) - return err; - - err = zd1201_enable(zd); - if (err) - return err; - - msleep(100); - return 0; -} - -static int zd1201_net_open(struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - /* Start MAC with wildcard if no essid set */ - if (!zd->mac_enabled) - zd1201_join(zd, zd->essid, zd->essidlen); - netif_start_queue(dev); - - return 0; -} - -static int zd1201_net_stop(struct net_device *dev) -{ - netif_stop_queue(dev); - - return 0; -} - -/* - RFC 1042 encapsulates Ethernet frames in 802.11 frames - by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0 - (0x00, 0x00, 0x00). Zd requires an additional padding, copy - of ethernet addresses, length of the standard RFC 1042 packet - and a command byte (which is nul for tx). - - tx frame (from Wlan NG): - RFC 1042: - llc 0xAA 0xAA 0x03 (802.2 LLC) - snap 0x00 0x00 0x00 (Ethernet encapsulated) - type 2 bytes, Ethernet type field - payload (minus eth header) - Zydas specific: - padding 1B if (skb->len+8+1)%64==0 - Eth MAC addr 12 bytes, Ethernet MAC addresses - length 2 bytes, RFC 1042 packet length - (llc+snap+type+payload) - zd 1 null byte, zd1201 packet type - */ -static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - unsigned char *txbuf = zd->txdata; - int txbuflen, pad = 0, err; - struct urb *urb = zd->tx_urb; - - if (!zd->mac_enabled || zd->monitor) { - zd->stats.tx_dropped++; - kfree_skb(skb); - return 0; - } - netif_stop_queue(dev); - - txbuflen = skb->len + 8 + 1; - if (txbuflen%64 == 0) { - pad = 1; - txbuflen++; - } - txbuf[0] = 0xAA; - txbuf[1] = 0xAA; - txbuf[2] = 0x03; - txbuf[3] = 0x00; /* rfc1042 */ - txbuf[4] = 0x00; - txbuf[5] = 0x00; - - memcpy(txbuf+6, skb->data+12, skb->len-12); - if (pad) - txbuf[skb->len-12+6]=0; - memcpy(txbuf+skb->len-12+6+pad, skb->data, 12); - *(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6); - txbuf[txbuflen-1] = 0; - - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out), - txbuf, txbuflen, zd1201_usbtx, zd); - - err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC); - if (err) { - zd->stats.tx_errors++; - netif_start_queue(dev); - return err; - } - zd->stats.tx_packets++; - zd->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; - kfree_skb(skb); - - return 0; -} - -static void zd1201_tx_timeout(struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - if (!zd) - return; - dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n", - dev->name); - usb_unlink_urb(zd->tx_urb); - zd->stats.tx_errors++; - /* Restart the timeout to quiet the watchdog: */ - dev->trans_start = jiffies; -} - -static int zd1201_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err; - - if (!zd) - return -ENODEV; - - err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, - addr->sa_data, dev->addr_len, 1); - if (err) - return err; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - return zd1201_mac_reset(zd); -} - -static struct net_device_stats *zd1201_get_stats(struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - return &zd->stats; -} - -static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - return &zd->iwstats; -} - -static void zd1201_set_multicast(struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - struct dev_mc_list *mc = dev->mc_list; - unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; - int i; - - if (dev->mc_count > ZD1201_MAXMULTI) - return; - - for (i=0; imc_count; i++) { - memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN); - mc = mc->next; - } - zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, - dev->mc_count*ETH_ALEN, 0); - -} - -static int zd1201_config_commit(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - return zd1201_mac_reset(zd); -} - -static int zd1201_get_name(struct net_device *dev, - struct iw_request_info *info, char *name, char *extra) -{ - strcpy(name, "IEEE 802.11b"); - - return 0; -} - -static int zd1201_set_freq(struct net_device *dev, - struct iw_request_info *info, struct iw_freq *freq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short channel = 0; - int err; - - if (freq->e == 0) - channel = freq->m; - else { - if (freq->m >= 2482) - channel = 14; - if (freq->m >= 2407) - channel = (freq->m-2407)/5; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel); - if (err) - return err; - - zd1201_mac_reset(zd); - - return 0; -} - -static int zd1201_get_freq(struct net_device *dev, - struct iw_request_info *info, struct iw_freq *freq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short channel; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel); - if (err) - return err; - freq->e = 0; - freq->m = channel; - - return 0; -} - -static int zd1201_set_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *mode, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short porttype, monitor = 0; - unsigned char buffer[IW_ESSID_MAX_SIZE+2]; - int err; - - if (zd->ap) { - if (*mode != IW_MODE_MASTER) - return -EINVAL; - return 0; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); - if (err) - return err; - zd->dev->type = ARPHRD_ETHER; - switch(*mode) { - case IW_MODE_MONITOR: - monitor = 1; - zd->dev->type = ARPHRD_IEEE80211; - /* Make sure we are no longer associated with by - setting an 'impossible' essid. - (otherwise we mess up firmware) - */ - zd1201_join(zd, "\0-*#\0", 5); - /* Put port in pIBSS */ - case 8: /* No pseudo-IBSS in wireless extensions (yet) */ - porttype = ZD1201_PORTTYPE_PSEUDOIBSS; - break; - case IW_MODE_ADHOC: - porttype = ZD1201_PORTTYPE_IBSS; - break; - case IW_MODE_INFRA: - porttype = ZD1201_PORTTYPE_BSS; - break; - default: - return -EINVAL; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); - if (err) - return err; - if (zd->monitor && !monitor) { - zd1201_disable(zd); - *(__le16 *)buffer = cpu_to_le16(zd->essidlen); - memcpy(buffer+2, zd->essid, zd->essidlen); - err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, - buffer, IW_ESSID_MAX_SIZE+2, 1); - if (err) - return err; - } - zd->monitor=monitor; - /* If monitor mode is set we don't actually turn it on here since it - * is done during mac reset anyway (see zd1201_mac_enable). - */ - - zd1201_mac_reset(zd); - - return 0; -} - -static int zd1201_get_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *mode, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short porttype; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype); - if (err) - return err; - switch(porttype) { - case ZD1201_PORTTYPE_IBSS: - *mode = IW_MODE_ADHOC; - break; - case ZD1201_PORTTYPE_BSS: - *mode = IW_MODE_INFRA; - break; - case ZD1201_PORTTYPE_WDS: - *mode = IW_MODE_REPEAT; - break; - case ZD1201_PORTTYPE_PSEUDOIBSS: - *mode = 8;/* No Pseudo-IBSS... */ - break; - case ZD1201_PORTTYPE_AP: - *mode = IW_MODE_MASTER; - break; - default: - dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n", - porttype); - *mode = IW_MODE_AUTO; - } - if (zd->monitor) - *mode = IW_MODE_MONITOR; - - return 0; -} - -static int zd1201_get_range(struct net_device *dev, - struct iw_request_info *info, struct iw_point *wrq, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - - wrq->length = sizeof(struct iw_range); - memset(range, 0, sizeof(struct iw_range)); - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = WIRELESS_EXT; - - range->max_qual.qual = 128; - range->max_qual.level = 128; - range->max_qual.noise = 128; - range->max_qual.updated = 7; - - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - range->num_encoding_sizes = 2; - range->max_encoding_tokens = ZD1201_NUMKEYS; - - range->num_bitrates = 4; - range->bitrate[0] = 1000000; - range->bitrate[1] = 2000000; - range->bitrate[2] = 5500000; - range->bitrate[3] = 11000000; - - range->min_rts = 0; - range->min_frag = ZD1201_FRAGMIN; - range->max_rts = ZD1201_RTSMAX; - range->min_frag = ZD1201_FRAGMAX; - - return 0; -} - -/* Little bit of magic here: we only get the quality if we poll - * for it, and we never get an actual request to trigger such - * a poll. Therefore we 'assume' that the user will soon ask for - * the stats after asking the bssid. - */ -static int zd1201_get_wap(struct net_device *dev, - struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - unsigned char buffer[6]; - - if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) { - /* Unfortunately the quality and noise reported is useless. - they seem to be accumulators that increase until you - read them, unless we poll on a fixed interval we can't - use them - */ - /*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/ - zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]); - /*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/ - zd->iwstats.qual.updated = 2; - } - - return zd1201_getconfig(zd,ZD1201_RID_CURRENTBSSID,ap_addr->sa_data,6); -} - -static int zd1201_set_scan(struct net_device *dev, - struct iw_request_info *info, struct iw_point *srq, char *extra) -{ - /* We do everything in get_scan */ - return 0; -} - -static int zd1201_get_scan(struct net_device *dev, - struct iw_request_info *info, struct iw_point *srq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err, i, j, enabled_save; - struct iw_event iwe; - char *cev = extra; - char *end_buf = extra + IW_SCAN_MAX_DATA; - - /* No scanning in AP mode */ - if (zd->ap) - return -EOPNOTSUPP; - - /* Scan doesn't seem to work if disabled */ - enabled_save = zd->mac_enabled; - zd1201_enable(zd); - - zd->rxdatas = 0; - err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, - ZD1201_INQ_SCANRESULTS, 0, 0); - if (err) - return err; - - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen) - return -EIO; - - if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS) - return -EIO; - - for(i=8; irxlen; i+=62) { - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6); - cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); - - iwe.cmd = SIOCGIWESSID; - iwe.u.data.length = zd->rxdata[i+16]; - iwe.u.data.flags = 1; - cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18); - - iwe.cmd = SIOCGIWMODE; - if (zd->rxdata[i+14]&0x01) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); - - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = zd->rxdata[i+0]; - iwe.u.freq.e = 0; - cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); - - iwe.cmd = SIOCGIWRATE; - iwe.u.bitrate.fixed = 0; - iwe.u.bitrate.disabled = 0; - for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) { - iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000; - cev=iwe_stream_add_event(cev, end_buf, &iwe, - IW_EV_PARAM_LEN); - } - - iwe.cmd = SIOCGIWENCODE; - iwe.u.data.length = 0; - if (zd->rxdata[i+14]&0x10) - iwe.u.data.flags = IW_ENCODE_ENABLED; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); - - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = zd->rxdata[i+4]; - iwe.u.qual.noise= zd->rxdata[i+2]/10-100; - iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100; - iwe.u.qual.updated = 7; - cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); - } - - if (!enabled_save) - zd1201_disable(zd); - - srq->length = cev - extra; - srq->flags = 0; - - return 0; -} - -static int zd1201_set_essid(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - if (data->length > IW_ESSID_MAX_SIZE) - return -EINVAL; - if (data->length < 1) - data->length = 1; - zd->essidlen = data->length-1; - memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1); - memcpy(zd->essid, essid, data->length); - return zd1201_join(zd, zd->essid, zd->essidlen); -} - -static int zd1201_get_essid(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - memcpy(essid, zd->essid, zd->essidlen); - data->flags = 1; - data->length = zd->essidlen; - - return 0; -} - -static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *nick) -{ - strcpy(nick, "zd1201"); - data->flags = 1; - data->length = strlen(nick); - return 0; -} - -static int zd1201_set_rate(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short rate; - int err; - - switch (rrq->value) { - case 1000000: - rate = ZD1201_RATEB1; - break; - case 2000000: - rate = ZD1201_RATEB2; - break; - case 5500000: - rate = ZD1201_RATEB5; - break; - case 11000000: - default: - rate = ZD1201_RATEB11; - break; - } - if (!rrq->fixed) { /* Also enable all lower bitrates */ - rate |= rate-1; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate); - if (err) - return err; - - return zd1201_mac_reset(zd); -} - -static int zd1201_get_rate(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short rate; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate); - if (err) - return err; - - switch(rate) { - case 1: - rrq->value = 1000000; - break; - case 2: - rrq->value = 2000000; - break; - case 5: - rrq->value = 5500000; - break; - case 11: - rrq->value = 11000000; - break; - default: - rrq->value = 0; - } - rrq->fixed = 0; - rrq->disabled = 0; - - return 0; -} - -static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err; - short val = rts->value; - - if (rts->disabled || !rts->fixed) - val = ZD1201_RTSMAX; - if (val > ZD1201_RTSMAX) - return -EINVAL; - if (val < 0) - return -EINVAL; - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val); - if (err) - return err; - return zd1201_mac_reset(zd); -} - -static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short rtst; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst); - if (err) - return err; - rts->value = rtst; - rts->disabled = (rts->value == ZD1201_RTSMAX); - rts->fixed = 1; - - return 0; -} - -static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err; - short val = frag->value; - - if (frag->disabled || !frag->fixed) - val = ZD1201_FRAGMAX; - if (val > ZD1201_FRAGMAX) - return -EINVAL; - if (val < ZD1201_FRAGMIN) - return -EINVAL; - if (val & 1) - return -EINVAL; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val); - if (err) - return err; - return zd1201_mac_reset(zd); -} - -static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short fragt; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt); - if (err) - return err; - frag->value = fragt; - frag->disabled = (frag->value == ZD1201_FRAGMAX); - frag->fixed = 1; - - return 0; -} - -static int zd1201_set_retry(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - return 0; -} - -static int zd1201_get_retry(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - return 0; -} - -static int zd1201_set_encode(struct net_device *dev, - struct iw_request_info *info, struct iw_point *erq, char *key) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short i; - int err, rid; - - if (erq->length > ZD1201_MAXKEYLEN) - return -EINVAL; - - i = (erq->flags & IW_ENCODE_INDEX)-1; - if (i == -1) { - err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i); - if (err) - return err; - } else { - err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i); - if (err) - return err; - } - - if (i < 0 || i >= ZD1201_NUMKEYS) - return -EINVAL; - - rid = ZD1201_RID_CNFDEFAULTKEY0 + i; - err = zd1201_setconfig(zd, rid, key, erq->length, 1); - if (err) - return err; - zd->encode_keylen[i] = erq->length; - memcpy(zd->encode_keys[i], key, erq->length); - - i=0; - if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) { - i |= 0x01; - zd->encode_enabled = 1; - } else - zd->encode_enabled = 0; - if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) { - i |= 0x02; - zd->encode_restricted = 1; - } else - zd->encode_restricted = 0; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i); - if (err) - return err; - - if (zd->encode_enabled) - i = ZD1201_CNFAUTHENTICATION_SHAREDKEY; - else - i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i); - if (err) - return err; - - return zd1201_mac_reset(zd); -} - -static int zd1201_get_encode(struct net_device *dev, - struct iw_request_info *info, struct iw_point *erq, char *key) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short i; - int err; - - if (zd->encode_enabled) - erq->flags = IW_ENCODE_ENABLED; - else - erq->flags = IW_ENCODE_DISABLED; - if (zd->encode_restricted) - erq->flags |= IW_ENCODE_RESTRICTED; - else - erq->flags |= IW_ENCODE_OPEN; - - i = (erq->flags & IW_ENCODE_INDEX) -1; - if (i == -1) { - err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i); - if (err) - return err; - } - if (i<0 || i>= ZD1201_NUMKEYS) - return -EINVAL; - - erq->flags |= i+1; - - erq->length = zd->encode_keylen[i]; - memcpy(key, zd->encode_keys[i], erq->length); - - return 0; -} - -static int zd1201_set_power(struct net_device *dev, - struct iw_request_info *info, struct iw_param *vwrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short enabled, duration, level; - int err; - - enabled = vwrq->disabled ? 0 : 1; - if (enabled) { - if (vwrq->flags & IW_POWER_PERIOD) { - duration = vwrq->value; - err = zd1201_setconfig16(zd, - ZD1201_RID_CNFMAXSLEEPDURATION, duration); - if (err) - return err; - goto out; - } - if (vwrq->flags & IW_POWER_TIMEOUT) { - err = zd1201_getconfig16(zd, - ZD1201_RID_CNFMAXSLEEPDURATION, &duration); - if (err) - return err; - level = vwrq->value * 4 / duration; - if (level > 4) - level = 4; - if (level < 0) - level = 0; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS, - level); - if (err) - return err; - goto out; - } - return -EINVAL; - } -out: - err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled); - if (err) - return err; - - return 0; -} - -static int zd1201_get_power(struct net_device *dev, - struct iw_request_info *info, struct iw_param *vwrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short enabled, level, duration; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled); - if (err) - return err; - err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level); - if (err) - return err; - err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration); - if (err) - return err; - vwrq->disabled = enabled ? 0 : 1; - if (vwrq->flags & IW_POWER_TYPE) { - if (vwrq->flags & IW_POWER_PERIOD) { - vwrq->value = duration; - vwrq->flags = IW_POWER_PERIOD; - } else { - vwrq->value = duration * level / 4; - vwrq->flags = IW_POWER_TIMEOUT; - } - } - if (vwrq->flags & IW_POWER_MODE) { - if (enabled && level) - vwrq->flags = IW_POWER_UNICAST_R; - else - vwrq->flags = IW_POWER_ALL_R; - } - - return 0; -} - - -static const iw_handler zd1201_iw_handler[] = -{ - (iw_handler) zd1201_config_commit, /* SIOCSIWCOMMIT */ - (iw_handler) zd1201_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) zd1201_set_freq, /* SIOCSIWFREQ */ - (iw_handler) zd1201_get_freq, /* SIOCGIWFREQ */ - (iw_handler) zd1201_set_mode, /* SIOCSIWMODE */ - (iw_handler) zd1201_get_mode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) zd1201_get_range, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL/*zd1201_set_wap*/, /* SIOCSIWAP */ - (iw_handler) zd1201_get_wap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCGIWAPLIST */ - (iw_handler) zd1201_set_scan, /* SIOCSIWSCAN */ - (iw_handler) zd1201_get_scan, /* SIOCGIWSCAN */ - (iw_handler) zd1201_set_essid, /* SIOCSIWESSID */ - (iw_handler) zd1201_get_essid, /* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) zd1201_get_nick, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) zd1201_set_rate, /* SIOCSIWRATE */ - (iw_handler) zd1201_get_rate, /* SIOCGIWRATE */ - (iw_handler) zd1201_set_rts, /* SIOCSIWRTS */ - (iw_handler) zd1201_get_rts, /* SIOCGIWRTS */ - (iw_handler) zd1201_set_frag, /* SIOCSIWFRAG */ - (iw_handler) zd1201_get_frag, /* SIOCGIWFRAG */ - (iw_handler) NULL, /* SIOCSIWTXPOW */ - (iw_handler) NULL, /* SIOCGIWTXPOW */ - (iw_handler) zd1201_set_retry, /* SIOCSIWRETRY */ - (iw_handler) zd1201_get_retry, /* SIOCGIWRETRY */ - (iw_handler) zd1201_set_encode, /* SIOCSIWENCODE */ - (iw_handler) zd1201_get_encode, /* SIOCGIWENCODE */ - (iw_handler) zd1201_set_power, /* SIOCSIWPOWER */ - (iw_handler) zd1201_get_power, /* SIOCGIWPOWER */ -}; - -static int zd1201_set_hostauth(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err; - - if (!zd->ap) - return -EOPNOTSUPP; - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value); - if (err) - return err; - return 0; -} - -static int zd1201_get_hostauth(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short hostauth; - int err; - - if (!zd->ap) - return -EOPNOTSUPP; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth); - if (err) - return err; - rrq->value = hostauth; - rrq->fixed = 1; - - return 0; -} - -static int zd1201_auth_sta(struct net_device *dev, - struct iw_request_info *info, struct sockaddr *sta, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - unsigned char buffer[10]; - - if (!zd->ap) - return -EOPNOTSUPP; - - memcpy(buffer, sta->sa_data, ETH_ALEN); - *(short*)(buffer+6) = 0; /* 0==success, 1==failure */ - *(short*)(buffer+8) = 0; - - return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1); -} - -static int zd1201_set_maxassoc(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err; - - if (!zd->ap) - return -EOPNOTSUPP; - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value); - if (err) - return err; - return 0; -} - -static int zd1201_get_maxassoc(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short maxassoc; - int err; - - if (!zd->ap) - return -EOPNOTSUPP; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc); - if (err) - return err; - rrq->value = maxassoc; - rrq->fixed = 1; - - return 0; -} - -static const iw_handler zd1201_private_handler[] = { - (iw_handler) zd1201_set_hostauth, /* ZD1201SIWHOSTAUTH */ - (iw_handler) zd1201_get_hostauth, /* ZD1201GIWHOSTAUTH */ - (iw_handler) zd1201_auth_sta, /* ZD1201SIWAUTHSTA */ - (iw_handler) NULL, /* nothing to get */ - (iw_handler) zd1201_set_maxassoc, /* ZD1201SIMAXASSOC */ - (iw_handler) zd1201_get_maxassoc, /* ZD1201GIMAXASSOC */ -}; - -static const struct iw_priv_args zd1201_private_args[] = { - { ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, "sethostauth" }, - { ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" }, - { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, "authstation" }, - { ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, "setmaxassoc" }, - { ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" }, -}; - -static const struct iw_handler_def zd1201_iw_handlers = { - .num_standard = ARRAY_SIZE(zd1201_iw_handler), - .num_private = ARRAY_SIZE(zd1201_private_handler), - .num_private_args = ARRAY_SIZE(zd1201_private_args), - .standard = (iw_handler *)zd1201_iw_handler, - .private = (iw_handler *)zd1201_private_handler, - .private_args = (struct iw_priv_args *) zd1201_private_args, - .get_wireless_stats = zd1201_get_wireless_stats, -}; - -static int zd1201_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct zd1201 *zd; - struct usb_device *usb; - int i, err; - short porttype; - char buf[IW_ESSID_MAX_SIZE+2]; - - usb = interface_to_usbdev(interface); - - zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL); - if (!zd) - return -ENOMEM; - zd->ap = ap; - zd->usb = usb; - zd->removed = 0; - init_waitqueue_head(&zd->rxdataq); - INIT_HLIST_HEAD(&zd->fraglist); - - err = zd1201_fw_upload(usb, zd->ap); - if (err) { - dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err); - goto err_zd; - } - - zd->endp_in = 1; - zd->endp_out = 1; - zd->endp_out2 = 2; - zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!zd->rx_urb || !zd->tx_urb) - goto err_zd; - - for(i = 0; i<100; i++) - udelay(1000); - - err = zd1201_drvr_start(zd); - if (err) - goto err_zd; - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312); - if (err) - goto err_start; - - err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, - ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11); - if (err) - goto err_start; - - zd->dev = alloc_etherdev(0); - if (!zd->dev) - goto err_start; - - zd->dev->priv = zd; - zd->dev->open = zd1201_net_open; - zd->dev->stop = zd1201_net_stop; - zd->dev->get_stats = zd1201_get_stats; - zd->dev->wireless_handlers = - (struct iw_handler_def *)&zd1201_iw_handlers; - zd->dev->hard_start_xmit = zd1201_hard_start_xmit; - zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT; - zd->dev->tx_timeout = zd1201_tx_timeout; - zd->dev->set_multicast_list = zd1201_set_multicast; - zd->dev->set_mac_address = zd1201_set_mac_address; - strcpy(zd->dev->name, "wlan%d"); - - err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, - zd->dev->dev_addr, zd->dev->addr_len); - if (err) - goto err_net; - - /* Set wildcard essid to match zd->essid */ - *(__le16 *)buf = cpu_to_le16(0); - err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, - IW_ESSID_MAX_SIZE+2, 1); - if (err) - goto err_net; - - if (zd->ap) - porttype = ZD1201_PORTTYPE_AP; - else - porttype = ZD1201_PORTTYPE_BSS; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); - if (err) - goto err_net; - - SET_NETDEV_DEV(zd->dev, &usb->dev); - - err = register_netdev(zd->dev); - if (err) - goto err_net; - dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n", - zd->dev->name); - - usb_set_intfdata(interface, zd); - return 0; - -err_net: - free_netdev(zd->dev); -err_start: - /* Leave the device in reset state */ - zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); -err_zd: - if (zd->tx_urb) - usb_free_urb(zd->tx_urb); - if (zd->rx_urb) - usb_free_urb(zd->rx_urb); - kfree(zd); - return err; -} - -static void zd1201_disconnect(struct usb_interface *interface) -{ - struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface); - struct hlist_node *node, *node2; - struct zd1201_frag *frag; - - if (!zd) - return; - usb_set_intfdata(interface, NULL); - if (zd->dev) { - unregister_netdev(zd->dev); - free_netdev(zd->dev); - } - - hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) { - hlist_del_init(&frag->fnode); - kfree_skb(frag->skb); - kfree(frag); - } - - if (zd->tx_urb) { - usb_kill_urb(zd->tx_urb); - usb_free_urb(zd->tx_urb); - } - if (zd->rx_urb) { - usb_kill_urb(zd->rx_urb); - usb_free_urb(zd->rx_urb); - } - kfree(zd); -} - -#ifdef CONFIG_PM - -static int zd1201_suspend(struct usb_interface *interface, - pm_message_t message) -{ - struct zd1201 *zd = usb_get_intfdata(interface); - - netif_device_detach(zd->dev); - - zd->was_enabled = zd->mac_enabled; - - if (zd->was_enabled) - return zd1201_disable(zd); - else - return 0; -} - -static int zd1201_resume(struct usb_interface *interface) -{ - struct zd1201 *zd = usb_get_intfdata(interface); - - if (!zd || !zd->dev) - return -ENODEV; - - netif_device_attach(zd->dev); - - if (zd->was_enabled) - return zd1201_enable(zd); - else - return 0; -} - -#else - -#define zd1201_suspend NULL -#define zd1201_resume NULL - -#endif - -static struct usb_driver zd1201_usb = { - .name = "zd1201", - .probe = zd1201_probe, - .disconnect = zd1201_disconnect, - .id_table = zd1201_table, - .suspend = zd1201_suspend, - .resume = zd1201_resume, -}; - -static int __init zd1201_init(void) -{ - return usb_register(&zd1201_usb); -} - -static void __exit zd1201_cleanup(void) -{ - usb_deregister(&zd1201_usb); -} - -module_init(zd1201_init); -module_exit(zd1201_cleanup); diff --git a/drivers/usb/net/zd1201.h b/drivers/usb/net/zd1201.h deleted file mode 100644 index 235f0ee..0000000 --- a/drivers/usb/net/zd1201.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Parts of this driver have been derived from a wlan-ng version - * modified by ZyDAS. - * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. - */ - -#ifndef _INCLUDE_ZD1201_H_ -#define _INCLUDE_ZD1201_H_ - -#define ZD1201_NUMKEYS 4 -#define ZD1201_MAXKEYLEN 13 -#define ZD1201_MAXMULTI 16 -#define ZD1201_FRAGMAX 2500 -#define ZD1201_FRAGMIN 256 -#define ZD1201_RTSMAX 2500 - -#define ZD1201_RXSIZE 3000 - -struct zd1201 { - struct usb_device *usb; - int removed; - struct net_device *dev; - struct net_device_stats stats; - struct iw_statistics iwstats; - - int endp_in; - int endp_out; - int endp_out2; - struct urb *rx_urb; - struct urb *tx_urb; - - unsigned char rxdata[ZD1201_RXSIZE]; - int rxlen; - wait_queue_head_t rxdataq; - int rxdatas; - struct hlist_head fraglist; - unsigned char txdata[ZD1201_RXSIZE]; - - int ap; - char essid[IW_ESSID_MAX_SIZE+1]; - int essidlen; - int mac_enabled; - int was_enabled; - int monitor; - int encode_enabled; - int encode_restricted; - unsigned char encode_keys[ZD1201_NUMKEYS][ZD1201_MAXKEYLEN]; - int encode_keylen[ZD1201_NUMKEYS]; -}; - -struct zd1201_frag { - struct hlist_node fnode; - int seq; - struct sk_buff *skb; -}; - -#define ZD1201SIWHOSTAUTH SIOCIWFIRSTPRIV -#define ZD1201GIWHOSTAUTH ZD1201SIWHOSTAUTH+1 -#define ZD1201SIWAUTHSTA SIOCIWFIRSTPRIV+2 -#define ZD1201SIWMAXASSOC SIOCIWFIRSTPRIV+4 -#define ZD1201GIWMAXASSOC ZD1201SIWMAXASSOC+1 - -#define ZD1201_FW_TIMEOUT (1000) - -#define ZD1201_TX_TIMEOUT (2000) - -#define ZD1201_USB_CMDREQ 0 -#define ZD1201_USB_RESREQ 1 - -#define ZD1201_CMDCODE_INIT 0x00 -#define ZD1201_CMDCODE_ENABLE 0x01 -#define ZD1201_CMDCODE_DISABLE 0x02 -#define ZD1201_CMDCODE_ALLOC 0x0a -#define ZD1201_CMDCODE_INQUIRE 0x11 -#define ZD1201_CMDCODE_SETRXRID 0x17 -#define ZD1201_CMDCODE_ACCESS 0x21 - -#define ZD1201_PACKET_EVENTSTAT 0x0 -#define ZD1201_PACKET_RXDATA 0x1 -#define ZD1201_PACKET_INQUIRE 0x2 -#define ZD1201_PACKET_RESOURCE 0x3 - -#define ZD1201_ACCESSBIT 0x0100 - -#define ZD1201_RID_CNFPORTTYPE 0xfc00 -#define ZD1201_RID_CNFOWNMACADDR 0xfc01 -#define ZD1201_RID_CNFDESIREDSSID 0xfc02 -#define ZD1201_RID_CNFOWNCHANNEL 0xfc03 -#define ZD1201_RID_CNFOWNSSID 0xfc04 -#define ZD1201_RID_CNFMAXDATALEN 0xfc07 -#define ZD1201_RID_CNFPMENABLED 0xfc09 -#define ZD1201_RID_CNFPMEPS 0xfc0a -#define ZD1201_RID_CNFMAXSLEEPDURATION 0xfc0c -#define ZD1201_RID_CNFDEFAULTKEYID 0xfc23 -#define ZD1201_RID_CNFDEFAULTKEY0 0xfc24 -#define ZD1201_RID_CNFDEFAULTKEY1 0xfc25 -#define ZD1201_RID_CNFDEFAULTKEY2 0xfc26 -#define ZD1201_RID_CNFDEFAULTKEY3 0xfc27 -#define ZD1201_RID_CNFWEBFLAGS 0xfc28 -#define ZD1201_RID_CNFAUTHENTICATION 0xfc2a -#define ZD1201_RID_CNFMAXASSOCSTATIONS 0xfc2b -#define ZD1201_RID_CNFHOSTAUTH 0xfc2e -#define ZD1201_RID_CNFGROUPADDRESS 0xfc80 -#define ZD1201_RID_CNFFRAGTHRESHOLD 0xfc82 -#define ZD1201_RID_CNFRTSTHRESHOLD 0xfc83 -#define ZD1201_RID_TXRATECNTL 0xfc84 -#define ZD1201_RID_PROMISCUOUSMODE 0xfc85 -#define ZD1201_RID_CNFBASICRATES 0xfcb3 -#define ZD1201_RID_AUTHENTICATESTA 0xfce3 -#define ZD1201_RID_CURRENTBSSID 0xfd42 -#define ZD1201_RID_COMMSQUALITY 0xfd43 -#define ZD1201_RID_CURRENTTXRATE 0xfd44 -#define ZD1201_RID_CNFMAXTXBUFFERNUMBER 0xfda0 -#define ZD1201_RID_CURRENTCHANNEL 0xfdc1 - -#define ZD1201_INQ_SCANRESULTS 0xf101 - -#define ZD1201_INF_LINKSTATUS 0xf200 -#define ZD1201_INF_ASSOCSTATUS 0xf201 -#define ZD1201_INF_AUTHREQ 0xf202 - -#define ZD1201_ASSOCSTATUS_STAASSOC 0x1 -#define ZD1201_ASSOCSTATUS_REASSOC 0x2 -#define ZD1201_ASSOCSTATUS_DISASSOC 0x3 -#define ZD1201_ASSOCSTATUS_ASSOCFAIL 0x4 -#define ZD1201_ASSOCSTATUS_AUTHFAIL 0x5 - -#define ZD1201_PORTTYPE_IBSS 0 -#define ZD1201_PORTTYPE_BSS 1 -#define ZD1201_PORTTYPE_WDS 2 -#define ZD1201_PORTTYPE_PSEUDOIBSS 3 -#define ZD1201_PORTTYPE_AP 6 - -#define ZD1201_RATEB1 1 -#define ZD1201_RATEB2 2 -#define ZD1201_RATEB5 4 /* 5.5 really, but 5 is shorter :) */ -#define ZD1201_RATEB11 8 - -#define ZD1201_CNFAUTHENTICATION_OPENSYSTEM 0x0001 -#define ZD1201_CNFAUTHENTICATION_SHAREDKEY 0x0002 - -#endif /* _INCLUDE_ZD1201_H_ */ diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 5c60be5..8bd44fd 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -417,7 +417,7 @@ config USB_SERIAL_MCT_U232 Magic Control Technology Corp. (U232 is one of the model numbers). This driver also works with Sitecom U232-P25 and D-Link DU-H3SP USB - BAY devices. + BAY, Belkin F5U109, and Belkin F5U409 devices. To compile this driver as a module, choose M here: the module will be called mct_u232. @@ -491,16 +491,22 @@ config USB_SERIAL_XIRCOM module will be called keyspan_pda. config USB_SERIAL_OPTION - tristate "USB Option PCMCIA serial driver" - depends on USB_SERIAL && USB_OHCI_HCD && PCCARD + tristate "USB driver for GSM modems" + depends on USB_SERIAL help - Say Y here if you want to use an Option card. This is a - GSM card, controlled by three serial ports which are connected - via an OHCI adapter located on a PC card. + Say Y here if you have an "Option" GSM PCMCIA card + (or an OEM version: branded Huawei, Audiovox, or Novatel). + + These cards feature a built-in OHCI-USB adapter and an + internally-connected GSM modem. The USB bus is not + accessible externally. To compile this driver as a module, choose M here: the module will be called option. + If this driver doesn't recognize your device, + it might be accessible via the FTDI_SIO driver. + config USB_SERIAL_OMNINET tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)" depends on USB_SERIAL && EXPERIMENTAL diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 694b205..94b9ba0 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -16,9 +16,11 @@ #include #include "usb-serial.h" static struct usb_device_id id_table [] = { + { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ { USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ + { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 8023bb7..f3404e1 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -202,7 +202,7 @@ static void usb_console_write(struct con struct usb_serial *serial; int retval = -ENODEV; - if (!port) + if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) return; serial = port->serial; @@ -213,17 +213,38 @@ static void usb_console_write(struct con if (!port->open_count) { dbg ("%s - port not opened", __FUNCTION__); - goto exit; + return; } - /* pass on to the driver specific version of this function if it is available */ - if (serial->type->write) - retval = serial->type->write(port, buf, count); - else - retval = usb_serial_generic_write(port, buf, count); - -exit: - dbg("%s - return value (if we had one): %d", __FUNCTION__, retval); + while (count) { + unsigned int i; + unsigned int lf; + /* search for LF so we can insert CR if necessary */ + for (i=0, lf=0 ; i < count ; i++) { + if (*(buf + i) == 10) { + lf = 1; + i++; + break; + } + } + /* pass on to the driver specific version of this function if it is available */ + if (serial->type->write) + retval = serial->type->write(port, buf, i); + else + retval = usb_serial_generic_write(port, buf, i); + dbg("%s - return value : %d", __FUNCTION__, retval); + if (lf) { + /* append CR after LF */ + unsigned char cr = 13; + if (serial->type->write) + retval = serial->type->write(port, &cr, 1); + else + retval = usb_serial_generic_write(port, &cr, 1); + dbg("%s - return value : %d", __FUNCTION__, retval); + } + buf += i; + count -= i; + } } static struct console usbcons = { @@ -234,6 +255,14 @@ static struct console usbcons = { .index = -1, }; +void usb_serial_console_disconnect(struct usb_serial *serial) +{ + if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) { + usb_serial_console_exit(); + usb_serial_put(serial); + } +} + void usb_serial_console_init (int serial_debug, int minor) { debug = serial_debug; @@ -259,6 +288,11 @@ void usb_serial_console_init (int serial void usb_serial_console_exit (void) { - unregister_console(&usbcons); + if (usbcons_info.port) { + unregister_console(&usbcons); + if (usbcons_info.port->open_count) + usbcons_info.port->open_count--; + usbcons_info.port = NULL; + } } diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index e0c2acd..f8c0cb2 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -59,6 +59,7 @@ static struct usb_device_id id_table [] { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ + { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 2357b1d..1fd5c5a 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -469,7 +469,7 @@ static void cyberjack_write_bulk_callbac exit: spin_unlock(&priv->lock); - schedule_work(&port->work); + usb_serial_port_softint(port); } static int __init cyberjack_init (void) diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 7212fbe..5de76ef 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -824,7 +824,7 @@ send: priv->bytes_out += count; /* do not count the line control and size bytes */ spin_unlock_irqrestore(&priv->lock, flags); - schedule_work(&port->work); + usb_serial_port_softint(port); } /* cypress_send */ diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 63f7c78..afca1ea 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -335,7 +335,7 @@ static void empeg_write_bulk_callback (s return; } - schedule_work(&port->work); + usb_serial_port_softint(port); } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 986d762..b2bfea7 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -500,6 +500,7 @@ static struct usb_device_id id_table_com { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -1261,7 +1262,6 @@ static void ftdi_shutdown (struct usb_se static int ftdi_open (struct usb_serial_port *port, struct file *filp) { /* ftdi_open */ - struct termios tmp_termios; struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -1271,8 +1271,8 @@ static int ftdi_open (struct usb_serial dbg("%s", __FUNCTION__); - - port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + if (port->tty) + port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; /* No error checking for this (will get errors later anyway) */ /* See ftdi_sio.h for description of what is reset */ @@ -1286,7 +1286,8 @@ static int ftdi_open (struct usb_serial This is same behaviour as serial.c/rs_open() - Kuba */ /* ftdi_set_termios will send usb control messages */ - ftdi_set_termios(port, &tmp_termios); + if (port->tty) + ftdi_set_termios(port, NULL); /* FIXME: Flow control might be enabled, so it should be checked - we have no control of defaults! */ @@ -1472,7 +1473,7 @@ static void ftdi_write_bulk_callback (st return; } - schedule_work(&port->work); + usb_serial_port_softint(port); } /* ftdi_write_bulk_callback */ @@ -1867,7 +1868,7 @@ static void ftdi_set_termios (struct usb err("%s urb failed to set baudrate", __FUNCTION__); } /* Ensure RTS and DTR are raised when baudrate changed from 0 */ - if ((old_termios->c_cflag & CBAUD) == B0) { + if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) { set_mctrl(port, TIOCM_DTR | TIOCM_RTS); } } diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index d69a917..6ab2ac8 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -436,6 +436,12 @@ #define PAPOUCH_TMU_PID 0x0400 /* TMU */ #define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ +/* + * Yost Engineering, Inc. products (www.yostengineering.com). + * PID 0xE050 submitted by Aaron Prose. + */ +#define FTDI_YEI_SERVOCENTER31_PID 0xE050 /* YEI ServoCenter3.1 USB */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 5ec9bf5..0476775 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1012,7 +1012,7 @@ static void garmin_write_bulk_callback ( garmin_data_p->flags |= CLEAR_HALT_REQUIRED; } - schedule_work(&port->work); + usb_serial_port_softint(port); } diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index c62cc28..07a478c 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -299,9 +299,7 @@ void usb_serial_generic_write_bulk_callb return; } - usb_serial_port_softint((void *)port); - - schedule_work(&port->work); + usb_serial_port_softint(port); } EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index b606c59..b85d215 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -142,7 +142,7 @@ struct edgeport_port { /* This structure holds all of the individual device information */ struct edgeport_serial { - char name[MAX_NAME_LEN+1]; /* string name of this device */ + char name[MAX_NAME_LEN+2]; /* string name of this device */ struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */ struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */ @@ -270,7 +270,7 @@ static void get_manufacturing_desc (stru static void get_boot_desc (struct edgeport_serial *edge_serial); static void load_application_firmware (struct edgeport_serial *edge_serial); -static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size); +static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size); // ************************************************************************ @@ -373,7 +373,7 @@ static void update_edgeport_E2PROM (stru * Get string descriptor from device * * * ************************************************************************/ -static int get_string (struct usb_device *dev, int Id, char *string) +static int get_string (struct usb_device *dev, int Id, char *string, int buflen) { struct usb_string_descriptor StringDesc; struct usb_string_descriptor *pStringDesc; @@ -395,7 +395,7 @@ static int get_string (struct usb_device return 0; } - unicode_to_ascii(string, pStringDesc->wData, pStringDesc->bLength/2-1); + unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2); kfree(pStringDesc); return strlen(string); @@ -2564,16 +2564,20 @@ static void change_port_settings (struct * ASCII range, but it's only for debugging... * NOTE: expects the unicode in LE format ****************************************************************************/ -static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size) +static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size) { int i; - if (unicode_size <= 0) + if (buflen <= 0) /* never happens, but... */ return; + --buflen; /* space for nul */ - for (i = 0; i < unicode_size; ++i) + for (i = 0; i < unicode_size; i++) { + if (i >= buflen) + break; string[i] = (char)(le16_to_cpu(unicode[i])); - string[unicode_size] = 0x00; + } + string[i] = 0x00; } @@ -2603,11 +2607,17 @@ static void get_manufacturing_desc (stru dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev); dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts); dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900); - unicode_to_ascii (string, edge_serial->manuf_descriptor.SerialNumber, edge_serial->manuf_descriptor.SerNumLength/2-1); + unicode_to_ascii(string, sizeof(string), + edge_serial->manuf_descriptor.SerialNumber, + edge_serial->manuf_descriptor.SerNumLength/2); dbg(" SerialNumber: %s", string); - unicode_to_ascii (string, edge_serial->manuf_descriptor.AssemblyNumber, edge_serial->manuf_descriptor.AssemblyNumLength/2-1); + unicode_to_ascii(string, sizeof(string), + edge_serial->manuf_descriptor.AssemblyNumber, + edge_serial->manuf_descriptor.AssemblyNumLength/2); dbg(" AssemblyNumber: %s", string); - unicode_to_ascii (string, edge_serial->manuf_descriptor.OemAssyNumber, edge_serial->manuf_descriptor.OemAssyNumLength/2-1); + unicode_to_ascii(string, sizeof(string), + edge_serial->manuf_descriptor.OemAssyNumber, + edge_serial->manuf_descriptor.OemAssyNumLength/2); dbg(" OemAssyNumber: %s", string); dbg(" UartType: %d", edge_serial->manuf_descriptor.UartType); dbg(" IonPid: %d", edge_serial->manuf_descriptor.IonPid); @@ -2720,7 +2730,7 @@ static int edge_startup (struct usb_seri struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; struct usb_device *dev; - int i; + int i, j; dev = serial->dev; @@ -2735,11 +2745,11 @@ static int edge_startup (struct usb_seri usb_set_serial_data(serial, edge_serial); /* get the name for the device from the device */ - if ( (i = get_string(dev, dev->descriptor.iManufacturer, &edge_serial->name[0])) != 0) { - edge_serial->name[i-1] = ' '; - } - - get_string(dev, dev->descriptor.iProduct, &edge_serial->name[i]); + i = get_string(dev, dev->descriptor.iManufacturer, + &edge_serial->name[0], MAX_NAME_LEN+1); + edge_serial->name[i++] = ' '; + get_string(dev, dev->descriptor.iProduct, + &edge_serial->name[i], MAX_NAME_LEN+2 - i); dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); @@ -2784,6 +2794,10 @@ static int edge_startup (struct usb_seri edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); if (edge_port == NULL) { dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); + for (j = 0; j < i; ++j) { + kfree (usb_get_serial_port_data(serial->port[j])); + usb_set_serial_port_data(serial->port[j], NULL); + } usb_set_serial_data(serial, NULL); kfree(edge_serial); return -ENOMEM; diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 9a5c979..9da6d2a 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -870,7 +870,7 @@ static void ipaq_write_bulk_callback(str spin_unlock_irqrestore(&write_list_lock, flags); } - schedule_work(&port->work); + usb_serial_port_softint(port); } static int ipaq_write_room(struct usb_serial_port *port) diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index e760a70..a4a0bfe 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -376,7 +376,7 @@ static void ipw_write_bulk_callback(stru if (urb->status) dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); - schedule_work(&port->work); + usb_serial_port_softint(port); } static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count) diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 426182d..9432c73 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -408,7 +408,7 @@ static void ir_write_bulk_callback (stru urb->actual_length, urb->transfer_buffer); - schedule_work(&port->work); + usb_serial_port_softint(port); } static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs) diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 052b735..2cf6ade 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -481,7 +481,7 @@ static void usa2x_outdat_callback(struct dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]); if (port->open_count) - schedule_work(&port->work); + usb_serial_port_softint(port); } static void usa26_inack_callback(struct urb *urb, struct pt_regs *regs) diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 78335a5..65d79f6 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -569,8 +569,7 @@ static void klsi_105_write_bulk_callback return; } - /* from generic_write_bulk_callback */ - schedule_work(&port->work); + usb_serial_port_softint(port); } /* klsi_105_write_bulk_completion_callback */ diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 238033a..6dcdb5f 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -320,7 +320,7 @@ static void omninet_write_bulk_callback return; } - schedule_work(&port->work); + usb_serial_port_softint(port); } diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5cf2b80..b0861b6 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1,5 +1,5 @@ /* - Option Card (PCMCIA to) USB to Serial Driver + USB Driver for GSM modems Copyright (C) 2005 Matthias Urlichs @@ -28,15 +28,34 @@ 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes wants to send >2000 bytes. - 2006-04-10 v0.4.2 fixed two array overrun errors :-/ + 2006-04-10 v0.5 fixed two array overrun errors :-/ + 2006-04-21 v0.5.1 added support for Sierra Wireless MC8755 + 2006-05-15 v0.6 re-enable multi-port support + 2006-06-01 v0.6.1 add COBRA + 2006-06-01 v0.6.2 add backwards-compatibility stuff + 2006-06-01 v0.6.3 add Novatel Wireless + 2006-06-01 v0.7 Option => GSM Work sponsored by: Sigos GmbH, Germany + This driver exists because the "normal" serial driver doesn't work too well + with GSM modems. Issues: + - data loss -- one single Receive URB is not nearly enough + - nonstandard flow (Option devices) and multiplex (Sierra) control + - controlling the baud rate doesn't make sense + + This driver is named "option" because the most common device it's + used for is a PC-Card (with an internal OHCI-USB interface, behind + which the GSM interface sits), made by Option Inc. + + Some of the "one port" devices actually exhibit multiple USB instances + on the USB bus. This is not a bug, these ports are used for different + device features. */ -#define DRIVER_VERSION "v0.4" +#define DRIVER_VERSION "v0.7.0" #define DRIVER_AUTHOR "Matthias Urlichs " -#define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver" +#define DRIVER_DESC "USB Driver for GSM modems" #include #include @@ -74,22 +93,45 @@ static int option_tiocmset(struct usb_s static int option_send_setup(struct usb_serial_port *port); /* Vendor and product IDs */ -#define OPTION_VENDOR_ID 0x0AF0 -#define HUAWEI_VENDOR_ID 0x12D1 -#define AUDIOVOX_VENDOR_ID 0x0F3D - -#define OPTION_PRODUCT_OLD 0x5000 -#define OPTION_PRODUCT_FUSION 0x6000 -#define OPTION_PRODUCT_FUSION2 0x6300 -#define HUAWEI_PRODUCT_E600 0x1001 -#define AUDIOVOX_PRODUCT_AIRCARD 0x0112 +#define OPTION_VENDOR_ID 0x0AF0 +#define HUAWEI_VENDOR_ID 0x12D1 +#define AUDIOVOX_VENDOR_ID 0x0F3D +#define SIERRAWIRELESS_VENDOR_ID 0x1199 +#define NOVATELWIRELESS_VENDOR_ID 0x1410 + +#define OPTION_PRODUCT_OLD 0x5000 +#define OPTION_PRODUCT_FUSION 0x6000 +#define OPTION_PRODUCT_FUSION2 0x6300 +#define OPTION_PRODUCT_COBRA 0x6500 +#define HUAWEI_PRODUCT_E600 0x1001 +#define AUDIOVOX_PRODUCT_AIRCARD 0x0112 +#define SIERRAWIRELESS_PRODUCT_MC8755 0x6802 +#define NOVATELWIRELESS_PRODUCT_U740 0x1400 static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, + { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, + { } /* Terminating entry */ +}; + +static struct usb_device_id option_ids1[] = { + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, + { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, + { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, + { } /* Terminating entry */ +}; +static struct usb_device_id option_ids3[] = { + { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, { } /* Terminating entry */ }; @@ -111,12 +153,39 @@ static struct usb_serial_driver option_3 .owner = THIS_MODULE, .name = "option", }, - .description = "Option 3G data card", - .id_table = option_ids, + .description = "GSM modem (3-port)", + .id_table = option_ids3, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, .num_bulk_out = NUM_DONT_CARE, - .num_ports = 1, /* 3, but the card reports its ports separately */ + .num_ports = 3, + .open = option_open, + .close = option_close, + .write = option_write, + .write_room = option_write_room, + .chars_in_buffer = option_chars_in_buffer, + .throttle = option_rx_throttle, + .unthrottle = option_rx_unthrottle, + .set_termios = option_set_termios, + .break_ctl = option_break_ctl, + .tiocmget = option_tiocmget, + .tiocmset = option_tiocmset, + .attach = option_startup, + .shutdown = option_shutdown, + .read_int_callback = option_instat_callback, +}; + +static struct usb_serial_driver option_1port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "option", + }, + .description = "GSM modem (1-port)", + .id_table = option_ids1, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 1, .open = option_open, .close = option_close, .write = option_write, @@ -170,6 +239,9 @@ struct option_port_private { static int __init option_init(void) { int retval; + retval = usb_serial_register(&option_1port_device); + if (retval) + goto failed_1port_device_register; retval = usb_serial_register(&option_3port_device); if (retval) goto failed_3port_device_register; @@ -184,6 +256,8 @@ static int __init option_init(void) failed_driver_register: usb_serial_deregister (&option_3port_device); failed_3port_device_register: + usb_serial_deregister (&option_1port_device); +failed_1port_device_register: return retval; } @@ -191,6 +265,7 @@ static void __exit option_exit(void) { usb_deregister (&option_driver); usb_serial_deregister (&option_3port_device); + usb_serial_deregister (&option_1port_device); } module_init(option_init); @@ -365,8 +440,7 @@ static void option_outdat_callback(struc port = (struct usb_serial_port *) urb->context; - if (port->open_count) - schedule_work(&port->work); + usb_serial_port_softint(port); } static void option_instat_callback(struct urb *urb, struct pt_regs *regs) @@ -573,27 +647,30 @@ static struct urb *option_setup_urb(stru /* Setup urbs */ static void option_setup_urbs(struct usb_serial *serial) { - int j; + int i,j; struct usb_serial_port *port; struct option_port_private *portdata; dbg("%s", __FUNCTION__); - port = serial->port[0]; - portdata = usb_get_serial_port_data(port); + + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); /* Do indat endpoints first */ - for (j = 0; j < N_IN_URB; ++j) { - portdata->in_urbs[j] = option_setup_urb (serial, - port->bulk_in_endpointAddress, USB_DIR_IN, port, - portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); - } + for (j = 0; j < N_IN_URB; ++j) { + portdata->in_urbs[j] = option_setup_urb (serial, + port->bulk_in_endpointAddress, USB_DIR_IN, port, + portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); + } - /* outdat endpoints */ - for (j = 0; j < N_OUT_URB; ++j) { - portdata->out_urbs[j] = option_setup_urb (serial, - port->bulk_out_endpointAddress, USB_DIR_OUT, port, - portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); + /* outdat endpoints */ + for (j = 0; j < N_OUT_URB; ++j) { + portdata->out_urbs[j] = option_setup_urb (serial, + port->bulk_out_endpointAddress, USB_DIR_OUT, port, + portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); + } } } diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index c96714b..d887043 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -314,7 +314,7 @@ static void pl2303_send(struct usb_seria // TODO: reschedule pl2303_send } - schedule_work(&port->work); + usb_serial_port_softint(port); } static int pl2303_write_room(struct usb_serial_port *port) @@ -600,7 +600,7 @@ static void pl2303_close (struct usb_ser unsigned int c_cflag; int bps; long timeout; - wait_queue_t wait; \ + wait_queue_t wait; dbg("%s - port %d", __FUNCTION__, port->number); diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 9c36f0e..a30135c 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -162,12 +162,19 @@ static void destroy_serial(struct kref * } } + flush_scheduled_work(); /* port->work */ + usb_put_dev(serial->dev); /* free up any memory that we allocated */ kfree (serial); } +void usb_serial_put(struct usb_serial *serial) +{ + kref_put(&serial->kref, destroy_serial); +} + /***************************************************************************** * Driver tty interface functions *****************************************************************************/ @@ -201,12 +208,12 @@ static int serial_open (struct tty_struc ++port->open_count; - if (port->open_count == 1) { + /* set up our port structure making the tty driver + * remember our port object, and us it */ + tty->driver_data = port; + port->tty = tty; - /* set up our port structure making the tty driver - * remember our port object, and us it */ - tty->driver_data = port; - port->tty = tty; + if (port->open_count == 1) { /* lock this module before we call it * this may fail, which means we must bail out, @@ -230,9 +237,11 @@ bailout_module_put: module_put(serial->type->driver.owner); bailout_mutex_unlock: port->open_count = 0; + tty->driver_data = NULL; + port->tty = NULL; mutex_unlock(&port->mutex); bailout_kref_put: - kref_put(&serial->kref, destroy_serial); + usb_serial_put(serial); return retval; } @@ -268,7 +277,7 @@ static void serial_close(struct tty_stru } mutex_unlock(&port->mutex); - kref_put(&port->serial->kref, destroy_serial); + usb_serial_put(port->serial); } static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) @@ -276,7 +285,7 @@ static int serial_write (struct tty_stru struct usb_serial_port *port = tty->driver_data; int retval = -EINVAL; - if (!port) + if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) goto exit; dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); @@ -296,7 +305,7 @@ exit: static int serial_write_room (struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - int retval = -EINVAL; + int retval = -ENODEV; if (!port) goto exit; @@ -318,7 +327,7 @@ exit: static int serial_chars_in_buffer (struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - int retval = -EINVAL; + int retval = -ENODEV; if (!port) goto exit; @@ -473,7 +482,7 @@ static int serial_read_proc (char *page, begin += length; length = 0; } - kref_put(&serial->kref, destroy_serial); + usb_serial_put(serial); } *eof = 1; done: @@ -488,19 +497,18 @@ static int serial_tiocmget (struct tty_s struct usb_serial_port *port = tty->driver_data; if (!port) - goto exit; + return -ENODEV; dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { dbg("%s - port not open", __FUNCTION__); - goto exit; + return -ENODEV; } if (port->serial->type->tiocmget) return port->serial->type->tiocmget(port, file); -exit: return -EINVAL; } @@ -510,23 +518,32 @@ static int serial_tiocmset (struct tty_s struct usb_serial_port *port = tty->driver_data; if (!port) - goto exit; + return -ENODEV; dbg("%s - port %d", __FUNCTION__, port->number); if (!port->open_count) { dbg("%s - port not open", __FUNCTION__); - goto exit; + return -ENODEV; } if (port->serial->type->tiocmset) return port->serial->type->tiocmset(port, file, set, clear); -exit: return -EINVAL; } -void usb_serial_port_softint(void *private) +/* + * We would be calling tty_wakeup here, but unfortunately some line + * disciplines have an annoying habit of calling tty->write from + * the write wakeup callback (e.g. n_hdlc.c). + */ +void usb_serial_port_softint(struct usb_serial_port *port) +{ + schedule_work(&port->work); +} + +static void usb_serial_port_work(void *private) { struct usb_serial_port *port = private; struct tty_struct *tty; @@ -789,7 +806,7 @@ #endif port->serial = serial; spin_lock_init(&port->lock); mutex_init(&port->mutex); - INIT_WORK(&port->work, usb_serial_port_softint, port); + INIT_WORK(&port->work, usb_serial_port_work, port); serial->port[i] = port; } @@ -985,6 +1002,7 @@ void usb_serial_disconnect(struct usb_in struct device *dev = &interface->dev; struct usb_serial_port *port; + usb_serial_console_disconnect(serial); dbg ("%s", __FUNCTION__); usb_set_intfdata (interface, NULL); @@ -996,7 +1014,7 @@ void usb_serial_disconnect(struct usb_in } /* let the last holder of this object * cause it to be cleaned up */ - kref_put(&serial->kref, destroy_serial); + usb_serial_put(serial); } dev_info(dev, "device disconnected\n"); } diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index dc89d87..d53ea9b 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h @@ -236,7 +236,7 @@ #define to_usb_serial_driver(d) containe extern int usb_serial_register(struct usb_serial_driver *driver); extern void usb_serial_deregister(struct usb_serial_driver *driver); -extern void usb_serial_port_softint(void *private); +extern void usb_serial_port_softint(struct usb_serial_port *port); extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id); extern void usb_serial_disconnect(struct usb_interface *iface); @@ -248,13 +248,16 @@ extern int ezusb_set_reset (struct usb_s #ifdef CONFIG_USB_SERIAL_CONSOLE extern void usb_serial_console_init (int debug, int minor); extern void usb_serial_console_exit (void); +extern void usb_serial_console_disconnect(struct usb_serial *serial); #else static inline void usb_serial_console_init (int debug, int minor) { } static inline void usb_serial_console_exit (void) { } +static inline void usb_serial_console_disconnect(struct usb_serial *serial) {} #endif /* Functions needed by other parts of the usbserial core */ extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); +extern void usb_serial_put(struct usb_serial *serial); extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index f5c3841..9e89b8d 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -480,7 +480,7 @@ static void visor_write_bulk_callback (s --priv->outstanding_urbs; spin_unlock_irqrestore(&priv->lock, flags); - schedule_work(&port->work); + usb_serial_port_softint(port); } diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index f806553..56ffc81 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -388,7 +388,7 @@ static int whiteheat_attach (struct usb_ if (ret) { err("%s: Couldn't send command [%d]", serial->type->description, ret); goto no_firmware; - } else if (alen != sizeof(command)) { + } else if (alen != 2) { err("%s: Send command incomplete [%d]", serial->type->description, alen); goto no_firmware; } @@ -400,7 +400,7 @@ static int whiteheat_attach (struct usb_ if (ret) { err("%s: Couldn't get results [%d]", serial->type->description, ret); goto no_firmware; - } else if (alen != sizeof(result)) { + } else if (alen != sizeof(*hw_info) + 1) { err("%s: Get results incomplete [%d]", serial->type->description, alen); goto no_firmware; } else if (result[0] != command[0]) { @@ -686,19 +686,16 @@ static void whiteheat_close(struct usb_s wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); urb = wrap->urb; usb_kill_urb(urb); - list_del(tmp); - list_add(tmp, &info->rx_urbs_free); - } - list_for_each_safe(tmp, tmp2, &info->rx_urb_q) { - list_del(tmp); - list_add(tmp, &info->rx_urbs_free); + list_move(tmp, &info->rx_urbs_free); } + list_for_each_safe(tmp, tmp2, &info->rx_urb_q) + list_move(tmp, &info->rx_urbs_free); + list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) { wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); urb = wrap->urb; usb_kill_urb(urb); - list_del(tmp); - list_add(tmp, &info->tx_urbs_free); + list_move(tmp, &info->tx_urbs_free); } spin_unlock_irqrestore(&info->lock, flags); @@ -1080,8 +1077,7 @@ static void whiteheat_write_callback(str err("%s - Not my urb!", __FUNCTION__); return; } - list_del(&wrap->list); - list_add(&wrap->list, &info->tx_urbs_free); + list_move(&wrap->list, &info->tx_urbs_free); spin_unlock(&info->lock); if (urb->status) { @@ -1089,9 +1085,7 @@ static void whiteheat_write_callback(str return; } - usb_serial_port_softint((void *)port); - - schedule_work(&port->work); + usb_serial_port_softint(port); } @@ -1373,8 +1367,7 @@ static int start_port_read(struct usb_se wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); urb = wrap->urb; usb_kill_urb(urb); - list_del(tmp); - list_add(tmp, &info->rx_urbs_free); + list_move(tmp, &info->rx_urbs_free); } break; } diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 55ee2d3..026a587 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -34,9 +34,8 @@ #include #include #include #include -#include #include -#include +#include #include "usb.h" #include "onetouch.h" #include "debug.h" diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 5f11e19..5715291 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -286,11 +286,7 @@ static int bus_reset(struct scsi_cmnd *s int result; US_DEBUGP("%s called\n", __FUNCTION__); - - mutex_lock(&(us->dev_mutex)); result = usb_stor_port_reset(us); - mutex_unlock(&us->dev_mutex); - return result < 0 ? FAILED : SUCCESS; } diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index f2bc5c9..8fcec01 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -131,28 +131,30 @@ static int usbat_write(struct us_data *u * Convenience function to perform a bulk read */ static int usbat_bulk_read(struct us_data *us, - unsigned char *data, - unsigned int len) + unsigned char *data, + unsigned int len, + int use_sg) { if (len == 0) return USB_STOR_XFER_GOOD; US_DEBUGP("usbat_bulk_read: len = %d\n", len); - return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, data, len, NULL); + return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, data, len, use_sg, NULL); } /* * Convenience function to perform a bulk write */ static int usbat_bulk_write(struct us_data *us, - unsigned char *data, - unsigned int len) + unsigned char *data, + unsigned int len, + int use_sg) { if (len == 0) return USB_STOR_XFER_GOOD; US_DEBUGP("usbat_bulk_write: len = %d\n", len); - return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, data, len, NULL); + return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, data, len, use_sg, NULL); } /* @@ -317,7 +319,8 @@ static int usbat_wait_not_busy(struct us */ static int usbat_read_block(struct us_data *us, unsigned char *content, - unsigned short len) + unsigned short len, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -338,7 +341,7 @@ static int usbat_read_block(struct us_da if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - result = usbat_bulk_read(us, content, len); + result = usbat_bulk_read(us, content, len, use_sg); return (result == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); } @@ -350,7 +353,8 @@ static int usbat_write_block(struct us_d unsigned char access, unsigned char *content, unsigned short len, - int minutes) + int minutes, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -372,7 +376,7 @@ static int usbat_write_block(struct us_d if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - result = usbat_bulk_write(us, content, len); + result = usbat_bulk_write(us, content, len, use_sg); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -465,7 +469,7 @@ static int usbat_hp8200e_rw_block_test(s data[1+(j<<1)] = data_out[j]; } - result = usbat_bulk_write(us, data, num_registers*2); + result = usbat_bulk_write(us, data, num_registers*2, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -583,7 +587,7 @@ static int usbat_multiple_write(struct u } /* Send the data */ - result = usbat_bulk_write(us, data, num_registers*2); + result = usbat_bulk_write(us, data, num_registers*2, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -606,8 +610,9 @@ static int usbat_multiple_write(struct u * other related details) are defined beforehand with _set_shuttle_features(). */ static int usbat_read_blocks(struct us_data *us, - unsigned char *buffer, - int len) + unsigned char *buffer, + int len, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -627,7 +632,7 @@ static int usbat_read_blocks(struct us_d return USB_STOR_TRANSPORT_FAILED; /* Read the blocks we just asked for */ - result = usbat_bulk_read(us, buffer, len); + result = usbat_bulk_read(us, buffer, len, use_sg); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_FAILED; @@ -648,7 +653,8 @@ static int usbat_read_blocks(struct us_d */ static int usbat_write_blocks(struct us_data *us, unsigned char *buffer, - int len) + int len, + int use_sg) { int result; unsigned char *command = us->iobuf; @@ -668,7 +674,7 @@ static int usbat_write_blocks(struct us_ return USB_STOR_TRANSPORT_FAILED; /* Write the data */ - result = usbat_bulk_write(us, buffer, len); + result = usbat_bulk_write(us, buffer, len, use_sg); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_FAILED; @@ -887,22 +893,28 @@ static int usbat_identify_device(struct * Set the transport function based on the device type */ static int usbat_set_transport(struct us_data *us, - struct usbat_info *info) + struct usbat_info *info, + int devicetype) { - int rc; - if (!info->devicetype) { - rc = usbat_identify_device(us, info); - if (rc != USB_STOR_TRANSPORT_GOOD) { - US_DEBUGP("usbat_set_transport: Could not identify device\n"); - return 1; - } - } + if (!info->devicetype) + info->devicetype = devicetype; - if (usbat_get_device_type(us) == USBAT_DEV_HP8200) + if (!info->devicetype) + usbat_identify_device(us, info); + + switch (info->devicetype) { + default: + return USB_STOR_TRANSPORT_ERROR; + + case USBAT_DEV_HP8200: us->transport = usbat_hp8200e_transport; - else if (usbat_get_device_type(us) == USBAT_DEV_FLASH) + break; + + case USBAT_DEV_FLASH: us->transport = usbat_flash_transport; + break; + } return 0; } @@ -947,7 +959,7 @@ static int usbat_flash_get_sector_count( msleep(100); /* Read the device identification data */ - rc = usbat_read_block(us, reply, 512); + rc = usbat_read_block(us, reply, 512, 0); if (rc != USB_STOR_TRANSPORT_GOOD) goto leave; @@ -1031,7 +1043,7 @@ static int usbat_flash_read_data(struct goto leave; /* Read the data we just requested */ - result = usbat_read_blocks(us, buffer, len); + result = usbat_read_blocks(us, buffer, len, 0); if (result != USB_STOR_TRANSPORT_GOOD) goto leave; @@ -1125,7 +1137,7 @@ static int usbat_flash_write_data(struct goto leave; /* Write the data */ - result = usbat_write_blocks(us, buffer, len); + result = usbat_write_blocks(us, buffer, len, 0); if (result != USB_STOR_TRANSPORT_GOOD) goto leave; @@ -1310,7 +1322,7 @@ static int usbat_select_and_test_registe /* * Initialize the USBAT processor and the storage device */ -int init_usbat(struct us_data *us) +static int init_usbat(struct us_data *us, int devicetype) { int rc; struct usbat_info *info; @@ -1392,7 +1404,7 @@ int init_usbat(struct us_data *us) US_DEBUGP("INIT 9\n"); /* At this point, we need to detect which device we are using */ - if (usbat_set_transport(us, info)) + if (usbat_set_transport(us, info, devicetype)) return USB_STOR_TRANSPORT_ERROR; US_DEBUGP("INIT 10\n"); @@ -1503,10 +1515,10 @@ static int usbat_hp8200e_transport(struc * AT SPEED 4 IS UNRELIABLE!!! */ - if ( (result = usbat_write_block(us, + if ((result = usbat_write_block(us, USBAT_ATA, srb->cmnd, 12, - srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) != - USB_STOR_TRANSPORT_GOOD) { + (srb->cmnd[0]==GPCMD_BLANK ? 75 : 10), 0) != + USB_STOR_TRANSPORT_GOOD)) { return result; } @@ -1533,7 +1545,7 @@ static int usbat_hp8200e_transport(struc len = *status; - result = usbat_read_block(us, srb->request_buffer, len); + result = usbat_read_block(us, srb->request_buffer, len, srb->use_sg); /* Debug-print the first 32 bytes of the transfer */ @@ -1695,6 +1707,22 @@ static int usbat_flash_transport(struct return USB_STOR_TRANSPORT_FAILED; } +int init_usbat_cd(struct us_data *us) +{ + return init_usbat(us, USBAT_DEV_HP8200); +} + + +int init_usbat_flash(struct us_data *us) +{ + return init_usbat(us, USBAT_DEV_FLASH); +} + +int init_usbat_probe(struct us_data *us) +{ + return init_usbat(us, 0); +} + /* * Default transport function. Attempts to detect which transport function * should be called, makes it the new default, and calls it. @@ -1708,9 +1736,8 @@ int usbat_transport(struct scsi_cmnd *sr { struct usbat_info *info = (struct usbat_info*) (us->extra); - if (usbat_set_transport(us, info)) + if (usbat_set_transport(us, info, 0)) return USB_STOR_TRANSPORT_ERROR; return us->transport(srb, us); } - diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h index 25e7d8b..3ddf143 100644 --- a/drivers/usb/storage/shuttle_usbat.h +++ b/drivers/usb/storage/shuttle_usbat.h @@ -106,7 +106,9 @@ #define USBAT_FEAT_ET1 0x02 #define USBAT_FEAT_ET2 0x01 extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int init_usbat(struct us_data *us); +extern int init_usbat_cd(struct us_data *us); +extern int init_usbat_flash(struct us_data *us); +extern int init_usbat_probe(struct us_data *us); struct usbat_info { int devicetype; diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 7ca896a..19b25c5 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -115,19 +115,6 @@ static void usb_stor_blocking_completion complete(urb_done_ptr); } - -/* This is the timeout handler which will cancel an URB when its timeout - * expires. - */ -static void timeout_handler(unsigned long us_) -{ - struct us_data *us = (struct us_data *) us_; - - if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) { - US_DEBUGP("Timeout -- cancelling URB\n"); - usb_unlink_urb(us->current_urb); - } -} /* This is the common part of the URB message submission code * @@ -138,7 +125,7 @@ static void timeout_handler(unsigned lon static int usb_stor_msg_common(struct us_data *us, int timeout) { struct completion urb_done; - struct timer_list to_timer; + long timeleft; int status; /* don't submit URBs during abort/disconnect processing */ @@ -185,22 +172,17 @@ static int usb_stor_msg_common(struct us } } - /* submit the timeout timer, if a timeout was requested */ - if (timeout > 0) { - init_timer(&to_timer); - to_timer.expires = jiffies + timeout; - to_timer.function = timeout_handler; - to_timer.data = (unsigned long) us; - add_timer(&to_timer); - } - /* wait for the completion of the URB */ - wait_for_completion(&urb_done); - clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); + timeleft = wait_for_completion_interruptible_timeout( + &urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT); - /* clean up the timeout timer */ - if (timeout > 0) - del_timer_sync(&to_timer); + clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); + + if (timeleft <= 0) { + US_DEBUGP("%s -- cancelling URB\n", + timeleft == 0 ? "Timeout" : "Signal"); + usb_unlink_urb(us->current_urb); + } /* return the URB status */ return us->current_urb->status; @@ -721,16 +703,19 @@ #endif * device reset. */ Handle_Errors: - /* Let the SCSI layer know we are doing a reset, set the - * RESETTING bit, and clear the ABORTING bit so that the reset - * may proceed. */ + /* Set the RESETTING bit, and clear the ABORTING bit so that + * the reset may proceed. */ scsi_lock(us_to_host(us)); - usb_stor_report_bus_reset(us); set_bit(US_FLIDX_RESETTING, &us->flags); clear_bit(US_FLIDX_ABORTING, &us->flags); scsi_unlock(us_to_host(us)); + /* We must release the device lock because the pre_reset routine + * will want to acquire it. */ + mutex_unlock(&us->dev_mutex); result = usb_stor_port_reset(us); + mutex_lock(&us->dev_mutex); + if (result < 0) { scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); @@ -1214,31 +1199,30 @@ int usb_stor_Bulk_reset(struct us_data * 0, us->ifnum, NULL, 0); } -/* Issue a USB port reset to the device. But don't do anything if - * there's more than one interface in the device, so that other users - * are not affected. */ +/* Issue a USB port reset to the device. The caller must not hold + * us->dev_mutex. + */ int usb_stor_port_reset(struct us_data *us) { - int result, rc; + int result, rc_lock; - if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { - result = -EIO; - US_DEBUGP("No reset during disconnect\n"); - } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) { - result = -EBUSY; - US_DEBUGP("Refusing to reset a multi-interface device\n"); - } else { - result = rc = - usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); - if (result < 0) { - US_DEBUGP("unable to lock device for reset: %d\n", - result); + result = rc_lock = + usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); + if (result < 0) + US_DEBUGP("unable to lock device for reset: %d\n", result); + else { + /* Were we disconnected while waiting for the lock? */ + if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { + result = -EIO; + US_DEBUGP("No reset during disconnect\n"); } else { - result = usb_reset_device(us->pusb_dev); - if (rc) - usb_unlock_device(us->pusb_dev); - US_DEBUGP("usb_reset_device returns %d\n", result); + result = usb_reset_composite_device( + us->pusb_dev, us->pusb_intf); + US_DEBUGP("usb_reset_composite_device returns %d\n", + result); } + if (rc_lock) + usb_unlock_device(us->pusb_dev); } return result; } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index aec5ea8..543244d 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -78,12 +78,12 @@ #ifdef CONFIG_USB_STORAGE_USBAT UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, "HP", "CD-Writer+ 8200e", - US_SC_8070, US_PR_USBAT, init_usbat, 0), + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, "HP", "CD-Writer+ CD-4e", - US_SC_8070, US_PR_USBAT, init_usbat, 0), + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), #endif /* Reported by Sebastian Kapfer @@ -133,6 +133,14 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Jiri Slaby and + * Rene C. Castberg */ +UNUSUAL_DEV( 0x0421, 0x0446, 0x0100, 0x0100, + "Nokia", + "N80", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), + /* Reported by Olaf Hering from novell bug #105878 */ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, "SMSC", @@ -216,6 +224,14 @@ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x "DVD-CAM DZ-MV100A Camcorder", US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN), +/* Patch for Nikon coolpix 2000 + * Submitted by Fabien Cosse */ +UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, + "NIKON", + "NIKON DSC E2000", + US_SC_DEVICE, US_PR_DEVICE,NULL, + US_FL_NOT_LOCKABLE ), + /* Reported by Andreas Bockhold */ UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, "NIKON", @@ -223,13 +239,12 @@ UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), -/* Patch for Nikon coolpix 2000 - * Submitted by Fabien Cosse */ -UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, +/* Reported by Jamie Kitson */ +UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, "NIKON", - "NIKON DSC E2000", - US_SC_DEVICE, US_PR_DEVICE,NULL, - US_FL_NOT_LOCKABLE ), + "NIKON DSC D70s", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), /* BENQ DC5330 * Reported by Manuel Fombuena and @@ -393,7 +408,7 @@ #ifdef CONFIG_USB_STORAGE_USBAT UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, "Shuttle/SCM", "USBAT-02", - US_SC_SCSI, US_PR_USBAT, init_usbat, + US_SC_SCSI, US_PR_USBAT, init_usbat_flash, US_FL_SINGLE_LUN), #endif @@ -797,7 +812,7 @@ #ifdef CONFIG_USB_STORAGE_USBAT UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, "Sandisk", "ImageMate SDDR-05b", - US_SC_SCSI, US_PR_USBAT, init_usbat, + US_SC_SCSI, US_PR_USBAT, init_usbat_flash, US_FL_SINGLE_LUN ), #endif diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index dd10863..e232c7c 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -221,6 +221,37 @@ static int storage_resume(struct usb_int #endif /* CONFIG_PM */ /* + * The next two routines get called just before and just after + * a USB port reset, whether from this driver or a different one. + */ + +static void storage_pre_reset(struct usb_interface *iface) +{ + struct us_data *us = usb_get_intfdata(iface); + + US_DEBUGP("%s\n", __FUNCTION__); + + /* Make sure no command runs during the reset */ + mutex_lock(&us->dev_mutex); +} + +static void storage_post_reset(struct usb_interface *iface) +{ + struct us_data *us = usb_get_intfdata(iface); + + US_DEBUGP("%s\n", __FUNCTION__); + + /* Report the reset to the SCSI core */ + scsi_lock(us_to_host(us)); + usb_stor_report_bus_reset(us); + scsi_unlock(us_to_host(us)); + + /* FIXME: Notify the subdrivers that they need to reinitialize + * the device */ + mutex_unlock(&us->dev_mutex); +} + +/* * fill_inquiry_response takes an unsigned char array (which must * be at least 36 characters) and populates the vendor name, * product name, and revision fields. Then the array is copied @@ -593,6 +624,15 @@ #ifdef CONFIG_USB_STORAGE_JUMPSHOT break; #endif +#ifdef CONFIG_USB_STORAGE_ALAUDA + case US_PR_ALAUDA: + us->transport_name = "Alauda Control/Bulk"; + us->transport = alauda_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + break; +#endif + default: return -EIO; } @@ -648,15 +688,6 @@ #ifdef CONFIG_USB_STORAGE_ISD200 break; #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA - case US_PR_ALAUDA: - us->transport_name = "Alauda Control/Bulk"; - us->transport = alauda_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - default: return -EIO; } @@ -1002,6 +1033,8 @@ #ifdef CONFIG_PM .suspend = storage_suspend, .resume = storage_resume, #endif + .pre_reset = storage_pre_reset, + .post_reset = storage_post_reset, .id_table = storage_usb_ids, }; diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 009fb09..5284abe 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -160,10 +160,10 @@ #endif }; /* Convert between us_data and the corresponding Scsi_Host */ -static struct Scsi_Host inline *us_to_host(struct us_data *us) { +static inline struct Scsi_Host *us_to_host(struct us_data *us) { return container_of((void *) us, struct Scsi_Host, hostdata); } -static struct us_data inline *host_to_us(struct Scsi_Host *host) { +static inline struct us_data *host_to_us(struct Scsi_Host *host) { return (struct us_data *) host->hostdata; } diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4587087..17de4c8 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -4,6 +4,21 @@ # menu "Graphics support" +config FIRMWARE_EDID + bool "Enable firmware EDID" + default y + ---help--- + This enables access to the EDID transferred from the firmware. + On the i386, this is from the Video BIOS. Enable this if DDC/I2C + transfers do not work for your driver and if you are using + nvidiafb, i810fb or savagefb. + + In general, choosing Y for this option is safe. If you + experience extremely long delays while booting before you get + something on your display, try setting this to N. Matrox cards in + combination with certain motherboards and monitors are known to + suffer from this problem. + config FB tristate "Support for frame buffer devices" ---help--- @@ -70,21 +85,10 @@ config FB_MACMODES depends on FB default n -config FB_FIRMWARE_EDID - bool "Enable firmware EDID" +config FB_BACKLIGHT + bool depends on FB - default y - ---help--- - This enables access to the EDID transferred from the firmware. - On the i386, this is from the Video BIOS. Enable this if DDC/I2C - transfers do not work for your driver and if you are using - nvidiafb, i810fb or savagefb. - - In general, choosing Y for this option is safe. If you - experience extremely long delays while booting before you get - something on your display, try setting this to N. Matrox cards in - combination with certain motherboards and monitors are known to - suffer from this problem. + default n config FB_MODE_HELPERS bool "Enable Video Mode Handling Helpers" @@ -167,6 +171,69 @@ config FB_ARMCLCD here and read . The module will be called amba-clcd. +choice + + depends on FB_ARMCLCD && (ARCH_LH7A40X || ARCH_LH7952X) + prompt "LCD Panel" + default FB_ARMCLCD_SHARP_LQ035Q7DB02 + +config FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT + bool "LogicPD LCD 3.5\" QVGA w/HRTFT IC" + help + This is an implementation of the Sharp LQ035Q7DB02, a 3.5" + color QVGA, HRTFT panel. The LogicPD device includes an + an integrated HRTFT controller IC. + The native resolution is 240x320. + +config FB_ARMCLCD_SHARP_LQ057Q3DC02 + bool "LogicPD LCD 5.7\" QVGA" + help + This is an implementation of the Sharp LQ057Q3DC02, a 5.7" + color QVGA, TFT panel. The LogicPD device includes an + The native resolution is 320x240. + +config FB_ARMCLCD_SHARP_LQ64D343 + bool "LogicPD LCD 6.4\" VGA" + help + This is an implementation of the Sharp LQ64D343, a 6.4" + color VGA, TFT panel. The LogicPD device includes an + The native resolution is 640x480. + +config FB_ARMCLCD_SHARP_LQ10D368 + bool "LogicPD LCD 10.4\" VGA" + help + This is an implementation of the Sharp LQ10D368, a 10.4" + color VGA, TFT panel. The LogicPD device includes an + The native resolution is 640x480. + + +config FB_ARMCLCD_SHARP_LQ121S1DG41 + bool "LogicPD LCD 12.1\" SVGA" + help + This is an implementation of the Sharp LQ121S1DG41, a 12.1" + color SVGA, TFT panel. The LogicPD device includes an + The native resolution is 800x600. + + This panel requires a clock rate may be an integer fraction + of the base LCDCLK frequency. The driver will select the + highest frequency available that is lower than the maximum + allowed. The panel may flicker if the clock rate is + slower than the recommended minimum. + +config FB_ARMCLCD_AUO_A070VW01_WIDE + bool "AU Optronics A070VW01 LCD 7.0\" WIDE" + help + This is an implementation of the AU Optronics, a 7.0" + WIDE Color. The native resolution is 234x480. + +config FB_ARMCLCD_HITACHI + bool "Hitachi Wide Screen 800x480" + help + This is an implementation of the Hitachi 800x480. + +endchoice + + config FB_ACORN bool "Acorn VIDC support" depends on (FB = y) && ARM && (ARCH_ACORN || ARCH_CLPS7500) @@ -483,10 +550,14 @@ config FB_VESA You will get a boot time penguin logo at no additional cost. Please read . If unsure, say Y. -config VIDEO_SELECT - bool - depends on FB_VESA - default y +config FB_IMAC + bool "Intel-based Macintosh Framebuffer Support" + depends on (FB = y) && X86 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Intel-based Macintosh config FB_HGA tristate "Hercules mono graphics support" @@ -510,12 +581,6 @@ config FB_HGA_ACCEL This will compile the Hercules mono graphics with acceleration functions. - -config VIDEO_SELECT - bool - depends on (FB = y) && X86 - default y - config FB_SGIVW tristate "SGI Visual Workstation framebuffer support" depends on FB && X86_VISWS @@ -654,6 +719,16 @@ config FB_NVIDIA_I2C independently validate video mode parameters, you should say Y here. +config FB_NVIDIA_BACKLIGHT + bool "Support for backlight control" + depends on FB_NVIDIA && PPC_PMAC + select FB_BACKLIGHT + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE + default y + help + Say Y here if you want to control the backlight of your display. + config FB_RIVA tristate "nVidia Riva support" depends on FB && PCI @@ -692,6 +767,16 @@ config FB_RIVA_DEBUG of debugging informations to provide to the maintainer when something goes wrong. +config FB_RIVA_BACKLIGHT + bool "Support for backlight control" + depends on FB_RIVA && PPC_PMAC + select FB_BACKLIGHT + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE + default y + help + Say Y here if you want to control the backlight of your display. + config FB_I810 tristate "Intel 810/815 support (EXPERIMENTAL)" depends on FB && EXPERIMENTAL && PCI && X86_32 @@ -743,7 +828,7 @@ config FB_I810_I2C config FB_INTEL tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI && X86_32 + depends on FB && EXPERIMENTAL && PCI && X86 select AGP select AGP_INTEL select FB_MODE_HELPERS @@ -930,6 +1015,7 @@ config FB_RADEON There is a product page at http://apps.ati.com/ATIcompare/ + config FB_RADEON_I2C bool "DDC/I2C for ATI Radeon support" depends on FB_RADEON @@ -937,6 +1023,16 @@ config FB_RADEON_I2C help Say Y here if you want DDC/I2C support for your Radeon board. +config FB_RADEON_BACKLIGHT + bool "Support for backlight control" + depends on FB_RADEON && PPC_PMAC + select FB_BACKLIGHT + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE + default y + help + Say Y here if you want to control the backlight of your display. + config FB_RADEON_DEBUG bool "Lots of debug output from Radeon driver" depends on FB_RADEON @@ -961,6 +1057,16 @@ config FB_ATY128 To compile this driver as a module, choose M here: the module will be called aty128fb. +config FB_ATY128_BACKLIGHT + bool "Support for backlight control" + depends on FB_ATY128 && PPC_PMAC + select FB_BACKLIGHT + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE + default y + help + Say Y here if you want to control the backlight of your display. + config FB_ATY tristate "ATI Mach64 display support" if PCI || ATARI depends on FB && !SPARC32 @@ -1003,6 +1109,16 @@ config FB_ATY_GX is at . +config FB_ATY_BACKLIGHT + bool "Support for backlight control" + depends on FB_ATY && PPC_PMAC + select FB_BACKLIGHT + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE + default y + help + Say Y here if you want to control the backlight of your display. + config FB_S3TRIO bool "S3 Trio display support" depends on (FB = y) && PPC && BROKEN diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 23de3b2..c335e9b 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -4,15 +4,15 @@ # Rewritten to use lists instead of if-s # Each configuration option enables a list of files. -obj-$(CONFIG_VT) += console/ -obj-$(CONFIG_LOGO) += logo/ -obj-$(CONFIG_SYSFS) += backlight/ - obj-$(CONFIG_FB) += fb.o fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ modedb.o fbcvt.o fb-objs := $(fb-y) +obj-$(CONFIG_VT) += console/ +obj-$(CONFIG_LOGO) += logo/ +obj-$(CONFIG_SYSFS) += backlight/ + obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o @@ -97,6 +97,7 @@ obj-$(CONFIG_FB_S3C2410) += s3c2410fb. # Platform or fallback drivers go here obj-$(CONFIG_FB_VESA) += vesafb.o +obj-$(CONFIG_FB_IMAC) += imacfb.o obj-$(CONFIG_FB_VGA16) += vga16fb.o vgastate.o obj-$(CONFIG_FB_OF) += offb.o diff --git a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile index 1852139..a6cc0e9 100644 --- a/drivers/video/aty/Makefile +++ b/drivers/video/aty/Makefile @@ -10,5 +10,6 @@ atyfb-objs := $(atyfb-y) radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o radeonfb-$(CONFIG_FB_RADEON_I2C) += radeon_i2c.o +radeonfb-$(CONFIG_FB_RADEON_BACKLIGHT) += radeon_backlight.o radeonfb-objs := $(radeonfb-y) diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index f7bbff4..11cf7fc 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -64,6 +64,7 @@ #include #include #include #include +#include #include #ifdef CONFIG_PPC_PMAC @@ -99,7 +100,7 @@ #endif #ifndef CONFIG_PPC_PMAC /* default mode */ -static struct fb_var_screeninfo default_var __initdata = { +static struct fb_var_screeninfo default_var __devinitdata = { /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ 640, 480, 640, 480, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, @@ -122,7 +123,7 @@ #endif /* CONFIG_PPC_PMAC */ /* default modedb mode */ /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */ -static struct fb_videomode defaultmode __initdata = { +static struct fb_videomode defaultmode __devinitdata = { .refresh = 60, .xres = 640, .yres = 480, @@ -334,7 +335,7 @@ static const struct aty128_meminfo sdr_s static const struct aty128_meminfo ddr_sgram = { 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" }; -static struct fb_fix_screeninfo aty128fb_fix __initdata = { +static struct fb_fix_screeninfo aty128fb_fix __devinitdata = { .id = "ATY Rage128", .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_PSEUDOCOLOR, @@ -344,15 +345,15 @@ static struct fb_fix_screeninfo aty128fb .accel = FB_ACCEL_ATI_RAGE128, }; -static char *mode_option __initdata = NULL; +static char *mode_option __devinitdata = NULL; #ifdef CONFIG_PPC_PMAC -static int default_vmode __initdata = VMODE_1024_768_60; -static int default_cmode __initdata = CMODE_8; +static int default_vmode __devinitdata = VMODE_1024_768_60; +static int default_cmode __devinitdata = CMODE_8; #endif -static int default_crt_on __initdata = 0; -static int default_lcd_on __initdata = 1; +static int default_crt_on __devinitdata = 0; +static int default_lcd_on __devinitdata = 1; #ifdef CONFIG_MTRR static int mtrr = 1; @@ -444,9 +445,9 @@ static int aty128_encode_var(struct fb_v static int aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par); #if 0 -static void __init aty128_get_pllinfo(struct aty128fb_par *par, +static void __devinit aty128_get_pllinfo(struct aty128fb_par *par, void __iomem *bios); -static void __init __iomem *aty128_map_ROM(struct pci_dev *pdev, const struct aty128fb_par *par); +static void __devinit __iomem *aty128_map_ROM(struct pci_dev *pdev, const struct aty128fb_par *par); #endif static void aty128_timings(struct aty128fb_par *par); static void aty128_init_engine(struct aty128fb_par *par); @@ -480,16 +481,6 @@ static struct fb_ops aty128fb_ops = { .fb_imageblit = cfb_imageblit, }; -#ifdef CONFIG_PMAC_BACKLIGHT -static int aty128_set_backlight_enable(int on, int level, void* data); -static int aty128_set_backlight_level(int level, void* data); - -static struct backlight_controller aty128_backlight_controller = { - aty128_set_backlight_enable, - aty128_set_backlight_level -}; -#endif /* CONFIG_PMAC_BACKLIGHT */ - /* * Functions to read from/write to the mmio registers * - endian conversions may possibly be avoided by @@ -582,7 +573,7 @@ static void aty_pll_writeupdate(const st /* write to the scratch register to test r/w functionality */ -static int __init register_test(const struct aty128fb_par *par) +static int __devinit register_test(const struct aty128fb_par *par) { u32 val; int flag = 0; @@ -781,7 +772,7 @@ static u32 depth_to_dst(u32 depth) #ifndef __sparc__ -static void __iomem * __init aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev) +static void __iomem * __devinit aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev) { u16 dptr; u8 rom_type; @@ -865,7 +856,7 @@ static void __iomem * __init aty128_map_ return NULL; } -static void __init aty128_get_pllinfo(struct aty128fb_par *par, unsigned char __iomem *bios) +static void __devinit aty128_get_pllinfo(struct aty128fb_par *par, unsigned char __iomem *bios) { unsigned int bios_hdr; unsigned int bios_pll; @@ -912,7 +903,7 @@ #endif #endif /* ndef(__sparc__) */ /* fill in known card constants if pll_block is not available */ -static void __init aty128_timings(struct aty128fb_par *par) +static void __devinit aty128_timings(struct aty128fb_par *par) { #ifdef CONFIG_PPC_OF /* instead of a table lookup, assume OF has properly @@ -1258,19 +1249,35 @@ static void aty128_set_crt_enable(struct static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) { u32 reg; +#ifdef CONFIG_FB_ATY128_BACKLIGHT + struct fb_info *info = pci_get_drvdata(par->pdev); +#endif if (on) { reg = aty_ld_le32(LVDS_GEN_CNTL); reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION; reg &= ~LVDS_DISPLAY_DIS; aty_st_le32(LVDS_GEN_CNTL, reg); -#ifdef CONFIG_PMAC_BACKLIGHT - aty128_set_backlight_enable(get_backlight_enable(), - get_backlight_level(), par); +#ifdef CONFIG_FB_ATY128_BACKLIGHT + mutex_lock(&info->bl_mutex); + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); #endif } else { -#ifdef CONFIG_PMAC_BACKLIGHT - aty128_set_backlight_enable(0, 0, par); +#ifdef CONFIG_FB_ATY128_BACKLIGHT + mutex_lock(&info->bl_mutex); + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->brightness = 0; + info->bl_dev->props->power = FB_BLANK_POWERDOWN; + info->bl_dev->props->update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); #endif reg = aty_ld_le32(LVDS_GEN_CNTL); reg |= LVDS_DISPLAY_DIS; @@ -1638,7 +1645,7 @@ static int aty128fb_sync(struct fb_info } #ifndef MODULE -static int __init aty128fb_setup(char *options) +static int __devinit aty128fb_setup(char *options) { char *this_opt; @@ -1691,6 +1698,184 @@ #endif /* CONFIG_PPC_PMAC */ } #endif /* MODULE */ +/* Backlight */ +#ifdef CONFIG_FB_ATY128_BACKLIGHT +#define MAX_LEVEL 0xFF + +static struct backlight_properties aty128_bl_data; + +static int aty128_bl_get_level_brightness(struct aty128fb_par *par, + int level) +{ + struct fb_info *info = pci_get_drvdata(par->pdev); + int atylevel; + + /* Get and convert the value */ + mutex_lock(&info->bl_mutex); + atylevel = MAX_LEVEL - + (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL); + mutex_unlock(&info->bl_mutex); + + if (atylevel < 0) + atylevel = 0; + else if (atylevel > MAX_LEVEL) + atylevel = MAX_LEVEL; + + return atylevel; +} + +/* We turn off the LCD completely instead of just dimming the backlight. + * This provides greater power saving and the display is useless without + * backlight anyway + */ +#define BACKLIGHT_LVDS_OFF +/* That one prevents proper CRT output with LCD off */ +#undef BACKLIGHT_DAC_OFF + +static int aty128_bl_update_status(struct backlight_device *bd) +{ + struct aty128fb_par *par = class_get_devdata(&bd->class_dev); + unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); + int level; + + if (bd->props->power != FB_BLANK_UNBLANK || + bd->props->fb_blank != FB_BLANK_UNBLANK || + !par->lcd_on) + level = 0; + else + level = bd->props->brightness; + + reg |= LVDS_BL_MOD_EN | LVDS_BLON; + if (level > 0) { + reg |= LVDS_DIGION; + if (!(reg & LVDS_ON)) { + reg &= ~LVDS_BLON; + aty_st_le32(LVDS_GEN_CNTL, reg); + aty_ld_le32(LVDS_GEN_CNTL); + mdelay(10); + reg |= LVDS_BLON; + aty_st_le32(LVDS_GEN_CNTL, reg); + } + reg &= ~LVDS_BL_MOD_LEVEL_MASK; + reg |= (aty128_bl_get_level_brightness(par, level) << LVDS_BL_MOD_LEVEL_SHIFT); +#ifdef BACKLIGHT_LVDS_OFF + reg |= LVDS_ON | LVDS_EN; + reg &= ~LVDS_DISPLAY_DIS; +#endif + aty_st_le32(LVDS_GEN_CNTL, reg); +#ifdef BACKLIGHT_DAC_OFF + aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN)); +#endif + } else { + reg &= ~LVDS_BL_MOD_LEVEL_MASK; + reg |= (aty128_bl_get_level_brightness(par, 0) << LVDS_BL_MOD_LEVEL_SHIFT); +#ifdef BACKLIGHT_LVDS_OFF + reg |= LVDS_DISPLAY_DIS; + aty_st_le32(LVDS_GEN_CNTL, reg); + aty_ld_le32(LVDS_GEN_CNTL); + udelay(10); + reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION); +#endif + aty_st_le32(LVDS_GEN_CNTL, reg); +#ifdef BACKLIGHT_DAC_OFF + aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN); +#endif + } + + return 0; +} + +static int aty128_bl_get_brightness(struct backlight_device *bd) +{ + return bd->props->brightness; +} + +static struct backlight_properties aty128_bl_data = { + .owner = THIS_MODULE, + .get_brightness = aty128_bl_get_brightness, + .update_status = aty128_bl_update_status, + .max_brightness = (FB_BACKLIGHT_LEVELS - 1), +}; + +static void aty128_bl_init(struct aty128fb_par *par) +{ + struct fb_info *info = pci_get_drvdata(par->pdev); + struct backlight_device *bd; + char name[12]; + + /* Could be extended to Rage128Pro LVDS output too */ + if (par->chip_gen != rage_M3) + return; + +#ifdef CONFIG_PMAC_BACKLIGHT + if (!pmac_has_backlight_type("ati")) + return; +#endif + + snprintf(name, sizeof(name), "aty128bl%d", info->node); + + bd = backlight_device_register(name, par, &aty128_bl_data); + if (IS_ERR(bd)) { + info->bl_dev = NULL; + printk("aty128: Backlight registration failed\n"); + goto error; + } + + mutex_lock(&info->bl_mutex); + info->bl_dev = bd; + fb_bl_default_curve(info, 0, + 63 * FB_BACKLIGHT_MAX / MAX_LEVEL, + 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); + mutex_unlock(&info->bl_mutex); + + up(&bd->sem); + bd->props->brightness = aty128_bl_data.max_brightness; + bd->props->power = FB_BLANK_UNBLANK; + bd->props->update_status(bd); + down(&bd->sem); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); + if (!pmac_backlight) + pmac_backlight = bd; + mutex_unlock(&pmac_backlight_mutex); +#endif + + printk("aty128: Backlight initialized (%s)\n", name); + + return; + +error: + return; +} + +static void aty128_bl_exit(struct aty128fb_par *par) +{ + struct fb_info *info = pci_get_drvdata(par->pdev); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); +#endif + + mutex_lock(&info->bl_mutex); + if (info->bl_dev) { +#ifdef CONFIG_PMAC_BACKLIGHT + if (pmac_backlight == info->bl_dev) + pmac_backlight = NULL; +#endif + + backlight_device_unregister(info->bl_dev); + info->bl_dev = NULL; + + printk("aty128: Backlight unloaded\n"); + } + mutex_unlock(&info->bl_mutex); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_unlock(&pmac_backlight_mutex); +#endif +} +#endif /* CONFIG_FB_ATY128_BACKLIGHT */ /* * Initialisation @@ -1708,7 +1893,7 @@ static void aty128_early_resume(void *da } #endif /* CONFIG_PPC_PMAC */ -static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) { struct fb_info *info = pci_get_drvdata(pdev); struct aty128fb_par *par = info->par; @@ -1835,17 +2020,15 @@ #endif /* CONFIG_PPC_PMAC */ if (register_framebuffer(info) < 0) return 0; -#ifdef CONFIG_PMAC_BACKLIGHT - /* Could be extended to Rage128Pro LVDS output too */ - if (par->chip_gen == rage_M3) - register_backlight_controller(&aty128_backlight_controller, par, "ati"); -#endif /* CONFIG_PMAC_BACKLIGHT */ - par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); par->pdev = pdev; par->asleep = 0; par->lock_blank = 0; - + +#ifdef CONFIG_FB_ATY128_BACKLIGHT + aty128_bl_init(par); +#endif + printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", info->node, info->fix.id, video_card); @@ -1854,7 +2037,7 @@ #endif /* CONFIG_PMAC_BACKLIGHT */ #ifdef CONFIG_PCI /* register a card ++ajoshi */ -static int __init aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { unsigned long fb_addr, reg_addr; struct aty128fb_par *par; @@ -1981,6 +2164,10 @@ static void __devexit aty128_remove(stru par = info->par; +#ifdef CONFIG_FB_ATY128_BACKLIGHT + aty128_bl_exit(par); +#endif + unregister_framebuffer(info); #ifdef CONFIG_MTRR if (par->mtrr.vram_valid) @@ -2011,10 +2198,14 @@ static int aty128fb_blank(int blank, str if (par->lock_blank || par->asleep) return 0; -#ifdef CONFIG_PMAC_BACKLIGHT - if (machine_is(powermac) && blank) - set_backlight_enable(0); -#endif /* CONFIG_PMAC_BACKLIGHT */ +#ifdef CONFIG_FB_ATY128_BACKLIGHT + if (machine_is(powermac) && blank) { + down(&fb->bl_dev->sem); + fb->bl_dev->props->power = FB_BLANK_POWERDOWN; + fb->bl_dev->props->update_status(fb->bl_dev); + up(&fb->bl_dev->sem); + } +#endif if (blank & FB_BLANK_VSYNC_SUSPEND) state |= 2; @@ -2029,10 +2220,14 @@ #endif /* CONFIG_PMAC_BACKLIGHT */ aty128_set_crt_enable(par, par->crt_on && !blank); aty128_set_lcd_enable(par, par->lcd_on && !blank); } -#ifdef CONFIG_PMAC_BACKLIGHT - if (machine_is(powermac) && !blank) - set_backlight_enable(1); -#endif /* CONFIG_PMAC_BACKLIGHT */ +#ifdef CONFIG_FB_ATY128_BACKLIGHT + if (machine_is(powermac) && !blank) { + down(&fb->bl_dev->sem); + fb->bl_dev->props->power = FB_BLANK_UNBLANK; + fb->bl_dev->props->update_status(fb->bl_dev); + up(&fb->bl_dev->sem); + } +#endif return 0; } @@ -2138,73 +2333,6 @@ static int aty128fb_ioctl(struct fb_info return -EINVAL; } -#ifdef CONFIG_PMAC_BACKLIGHT -static int backlight_conv[] = { - 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, - 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 -}; - -/* We turn off the LCD completely instead of just dimming the backlight. - * This provides greater power saving and the display is useless without - * backlight anyway - */ -#define BACKLIGHT_LVDS_OFF -/* That one prevents proper CRT output with LCD off */ -#undef BACKLIGHT_DAC_OFF - -static int aty128_set_backlight_enable(int on, int level, void *data) -{ - struct aty128fb_par *par = data; - unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL); - - if (!par->lcd_on) - on = 0; - reg |= LVDS_BL_MOD_EN | LVDS_BLON; - if (on && level > BACKLIGHT_OFF) { - reg |= LVDS_DIGION; - if (!(reg & LVDS_ON)) { - reg &= ~LVDS_BLON; - aty_st_le32(LVDS_GEN_CNTL, reg); - (void)aty_ld_le32(LVDS_GEN_CNTL); - mdelay(10); - reg |= LVDS_BLON; - aty_st_le32(LVDS_GEN_CNTL, reg); - } - reg &= ~LVDS_BL_MOD_LEVEL_MASK; - reg |= (backlight_conv[level] << LVDS_BL_MOD_LEVEL_SHIFT); -#ifdef BACKLIGHT_LVDS_OFF - reg |= LVDS_ON | LVDS_EN; - reg &= ~LVDS_DISPLAY_DIS; -#endif - aty_st_le32(LVDS_GEN_CNTL, reg); -#ifdef BACKLIGHT_DAC_OFF - aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN)); -#endif - } else { - reg &= ~LVDS_BL_MOD_LEVEL_MASK; - reg |= (backlight_conv[0] << LVDS_BL_MOD_LEVEL_SHIFT); -#ifdef BACKLIGHT_LVDS_OFF - reg |= LVDS_DISPLAY_DIS; - aty_st_le32(LVDS_GEN_CNTL, reg); - (void)aty_ld_le32(LVDS_GEN_CNTL); - udelay(10); - reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION); -#endif - aty_st_le32(LVDS_GEN_CNTL, reg); -#ifdef BACKLIGHT_DAC_OFF - aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN); -#endif - } - - return 0; -} - -static int aty128_set_backlight_level(int level, void* data) -{ - return aty128_set_backlight_enable(1, level, data); -} -#endif /* CONFIG_PMAC_BACKLIGHT */ - #if 0 /* * Accelerated functions @@ -2428,7 +2556,7 @@ static int aty128_pci_resume(struct pci_ } -static int __init aty128fb_init(void) +static int __devinit aty128fb_init(void) { #ifndef MODULE char *option = NULL; diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h index e9b7a64..43d2cb5 100644 --- a/drivers/video/aty/atyfb.h +++ b/drivers/video/aty/atyfb.h @@ -151,6 +151,7 @@ struct atyfb_par { int lock_blank; unsigned long res_start; unsigned long res_size; + struct pci_dev *pdev; #ifdef __sparc__ struct pci_mmap_map *mmap_map; u8 mmaped; diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index d9d7d3c..22e7206 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -66,6 +66,7 @@ #include #include #include #include +#include #include #include @@ -315,12 +316,12 @@ static int vram; static int pll; static int mclk; static int xclk; -static int comp_sync __initdata = -1; +static int comp_sync __devinitdata = -1; static char *mode; #ifdef CONFIG_PPC -static int default_vmode __initdata = VMODE_CHOOSE; -static int default_cmode __initdata = CMODE_CHOOSE; +static int default_vmode __devinitdata = VMODE_CHOOSE; +static int default_cmode __devinitdata = CMODE_CHOOSE; module_param_named(vmode, default_vmode, int, 0); MODULE_PARM_DESC(vmode, "int: video mode for mac"); @@ -329,10 +330,10 @@ MODULE_PARM_DESC(cmode, "int: color mode #endif #ifdef CONFIG_ATARI -static unsigned int mach64_count __initdata = 0; -static unsigned long phys_vmembase[FB_MAX] __initdata = { 0, }; -static unsigned long phys_size[FB_MAX] __initdata = { 0, }; -static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, }; +static unsigned int mach64_count __devinitdata = 0; +static unsigned long phys_vmembase[FB_MAX] __devinitdata = { 0, }; +static unsigned long phys_size[FB_MAX] __devinitdata = { 0, }; +static unsigned long phys_guiregbase[FB_MAX] __devinitdata = { 0, }; #endif /* top -> down is an evolution of mach64 chipset, any corrections? */ @@ -582,7 +583,7 @@ #if defined(CONFIG_PPC) * Apple monitor sense */ -static int __init read_aty_sense(const struct atyfb_par *par) +static int __devinit read_aty_sense(const struct atyfb_par *par) { int sense, i; @@ -1280,6 +1281,14 @@ #endif par->accel_flags = var->accel_flags; /* hack */ + if (var->accel_flags) { + info->fbops->fb_sync = atyfb_sync; + info->flags &= ~FBINFO_HWACCEL_DISABLED; + } else { + info->fbops->fb_sync = NULL; + info->flags |= FBINFO_HWACCEL_DISABLED; + } + if (par->blitter_may_be_busy) wait_for_idle(par); @@ -2115,47 +2124,144 @@ static int atyfb_pci_resume(struct pci_d #endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */ -#ifdef CONFIG_PMAC_BACKLIGHT +/* Backlight */ +#ifdef CONFIG_FB_ATY_BACKLIGHT +#define MAX_LEVEL 0xFF - /* - * LCD backlight control - */ +static struct backlight_properties aty_bl_data; -static int backlight_conv[] = { - 0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d, - 0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff -}; +static int aty_bl_get_level_brightness(struct atyfb_par *par, int level) +{ + struct fb_info *info = pci_get_drvdata(par->pdev); + int atylevel; + + /* Get and convert the value */ + mutex_lock(&info->bl_mutex); + atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL; + mutex_unlock(&info->bl_mutex); -static int aty_set_backlight_enable(int on, int level, void *data) + if (atylevel < 0) + atylevel = 0; + else if (atylevel > MAX_LEVEL) + atylevel = MAX_LEVEL; + + return atylevel; +} + +static int aty_bl_update_status(struct backlight_device *bd) { - struct fb_info *info = (struct fb_info *) data; - struct atyfb_par *par = (struct atyfb_par *) info->par; + struct atyfb_par *par = class_get_devdata(&bd->class_dev); unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); + int level; + + if (bd->props->power != FB_BLANK_UNBLANK || + bd->props->fb_blank != FB_BLANK_UNBLANK) + level = 0; + else + level = bd->props->brightness; reg |= (BLMOD_EN | BIASMOD_EN); - if (on && level > BACKLIGHT_OFF) { + if (level > 0) { reg &= ~BIAS_MOD_LEVEL_MASK; - reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT); + reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT); } else { reg &= ~BIAS_MOD_LEVEL_MASK; - reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT); + reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT); } aty_st_lcd(LCD_MISC_CNTL, reg, par); + return 0; } -static int aty_set_backlight_level(int level, void *data) +static int aty_bl_get_brightness(struct backlight_device *bd) { - return aty_set_backlight_enable(1, level, data); + return bd->props->brightness; } -static struct backlight_controller aty_backlight_controller = { - aty_set_backlight_enable, - aty_set_backlight_level +static struct backlight_properties aty_bl_data = { + .owner = THIS_MODULE, + .get_brightness = aty_bl_get_brightness, + .update_status = aty_bl_update_status, + .max_brightness = (FB_BACKLIGHT_LEVELS - 1), }; -#endif /* CONFIG_PMAC_BACKLIGHT */ -static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) +static void aty_bl_init(struct atyfb_par *par) +{ + struct fb_info *info = pci_get_drvdata(par->pdev); + struct backlight_device *bd; + char name[12]; + +#ifdef CONFIG_PMAC_BACKLIGHT + if (!pmac_has_backlight_type("ati")) + return; +#endif + + snprintf(name, sizeof(name), "atybl%d", info->node); + + bd = backlight_device_register(name, par, &aty_bl_data); + if (IS_ERR(bd)) { + info->bl_dev = NULL; + printk("aty: Backlight registration failed\n"); + goto error; + } + + mutex_lock(&info->bl_mutex); + info->bl_dev = bd; + fb_bl_default_curve(info, 0, + 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL, + 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); + mutex_unlock(&info->bl_mutex); + + up(&bd->sem); + bd->props->brightness = aty_bl_data.max_brightness; + bd->props->power = FB_BLANK_UNBLANK; + bd->props->update_status(bd); + down(&bd->sem); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); + if (!pmac_backlight) + pmac_backlight = bd; + mutex_unlock(&pmac_backlight_mutex); +#endif + + printk("aty: Backlight initialized (%s)\n", name); + + return; + +error: + return; +} + +static void aty_bl_exit(struct atyfb_par *par) +{ + struct fb_info *info = pci_get_drvdata(par->pdev); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); +#endif + + mutex_lock(&info->bl_mutex); + if (info->bl_dev) { +#ifdef CONFIG_PMAC_BACKLIGHT + if (pmac_backlight == info->bl_dev) + pmac_backlight = NULL; +#endif + + backlight_device_unregister(info->bl_dev); + + printk("aty: Backlight unloaded\n"); + } + mutex_unlock(&info->bl_mutex); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_unlock(&pmac_backlight_mutex); +#endif +} + +#endif /* CONFIG_FB_ATY_BACKLIGHT */ + +static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk) { const int ragepro_tbl[] = { 44, 50, 55, 66, 75, 80, 100 @@ -2215,7 +2321,7 @@ static int __devinit atyfb_get_timings_f } #endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */ -static int __init aty_init(struct fb_info *info, const char *name) +static int __devinit aty_init(struct fb_info *info, const char *name) { struct atyfb_par *par = (struct atyfb_par *) info->par; const char *ramname = NULL, *xtal; @@ -2296,12 +2402,15 @@ #endif break; } switch (clk_type) { +#ifdef CONFIG_ATARI case CLK_ATI18818_1: par->pll_ops = &aty_pll_ati18818_1; break; +#else case CLK_IBMRGB514: par->pll_ops = &aty_pll_ibm514; break; +#endif #if 0 /* dead code */ case CLK_STG1703: par->pll_ops = &aty_pll_stg1703; @@ -2506,16 +2615,24 @@ #endif info->fbops = &atyfb_ops; info->pseudo_palette = pseudo_palette; - info->flags = FBINFO_FLAG_DEFAULT; + info->flags = FBINFO_DEFAULT | + FBINFO_HWACCEL_IMAGEBLIT | + FBINFO_HWACCEL_FILLRECT | + FBINFO_HWACCEL_COPYAREA | + FBINFO_HWACCEL_YPAN; #ifdef CONFIG_PMAC_BACKLIGHT if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) { /* these bits let the 101 powerbook wake up from sleep -- paulus */ aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) | (USE_F32KHZ | TRISTATE_MEM_EN), par); - } else if (M64_HAS(MOBIL_BUS)) - register_backlight_controller(&aty_backlight_controller, info, "ati"); -#endif /* CONFIG_PMAC_BACKLIGHT */ + } else +#endif + if (M64_HAS(MOBIL_BUS)) { +#ifdef CONFIG_FB_ATY_BACKLIGHT + aty_bl_init (par); +#endif + } memset(&var, 0, sizeof(var)); #ifdef CONFIG_PPC @@ -2631,7 +2748,7 @@ #endif } #ifdef CONFIG_ATARI -static int __init store_video_par(char *video_str, unsigned char m64_num) +static int __devinit store_video_par(char *video_str, unsigned char m64_num) { char *p; unsigned long vmembase, size, guiregbase; @@ -2674,8 +2791,16 @@ static int atyfb_blank(int blank, struct return 0; #ifdef CONFIG_PMAC_BACKLIGHT - if (machine_is(powermac) && blank > FB_BLANK_NORMAL) - set_backlight_enable(0); + if (machine_is(powermac) && blank > FB_BLANK_NORMAL) { + mutex_lock(&info->bl_mutex); + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->power = FB_BLANK_POWERDOWN; + info->bl_dev->props->update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); + } #elif defined(CONFIG_FB_ATY_GENERIC_LCD) if (par->lcd_table && blank > FB_BLANK_NORMAL && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { @@ -2706,8 +2831,16 @@ #endif aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); #ifdef CONFIG_PMAC_BACKLIGHT - if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) - set_backlight_enable(1); + if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) { + mutex_lock(&info->bl_mutex); + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->power = FB_BLANK_UNBLANK; + info->bl_dev->props->update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + mutex_unlock(&info->bl_mutex); + } #elif defined(CONFIG_FB_ATY_GENERIC_LCD) if (par->lcd_table && blank <= FB_BLANK_NORMAL && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { @@ -2966,7 +3099,7 @@ static int __devinit atyfb_setup_sparc(s } pcp = pdev->sysdata; - if (node == pcp->prom_node) { + if (node == pcp->prom_node->node) { struct fb_var_screeninfo *var = &default_var; unsigned int N, P, Q, M, T, R; u32 v_total, h_total; @@ -3440,6 +3573,7 @@ static int __devinit atyfb_pci_probe(str par->res_start = res_start; par->res_size = res_size; par->irq = pdev->irq; + par->pdev = pdev; /* Setup "info" structure */ #ifdef __sparc__ @@ -3571,6 +3705,11 @@ static void __devexit atyfb_remove(struc aty_set_crtc(par, &saved_crtc); par->pll_ops->set_pll(info, &saved_pll); +#ifdef CONFIG_FB_ATY_BACKLIGHT + if (M64_HAS(MOBIL_BUS)) + aty_bl_exit(par); +#endif + unregister_framebuffer(info); #ifdef CONFIG_MTRR @@ -3640,7 +3779,7 @@ #endif /* CONFIG_PM */ #endif /* CONFIG_PCI */ #ifndef MODULE -static int __init atyfb_setup(char *options) +static int __devinit atyfb_setup(char *options) { char *this_opt; @@ -3712,7 +3851,7 @@ #endif } #endif /* MODULE */ -static int __init atyfb_init(void) +static int __devinit atyfb_init(void) { #ifndef MODULE char *option = NULL; @@ -3722,7 +3861,9 @@ #ifndef MODULE atyfb_setup(option); #endif +#ifdef CONFIG_PCI pci_register_driver(&atyfb_driver); +#endif #ifdef CONFIG_ATARI atyfb_atari_probe(); #endif @@ -3731,7 +3872,9 @@ #endif static void __exit atyfb_exit(void) { +#ifdef CONFIG_PCI pci_unregister_driver(&atyfb_driver); +#endif } module_init(atyfb_init); diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c index c98f4a4..1490e5e 100644 --- a/drivers/video/aty/mach64_accel.c +++ b/drivers/video/aty/mach64_accel.c @@ -200,8 +200,6 @@ void atyfb_copyarea(struct fb_info *info if (!area->width || !area->height) return; if (!par->accel_flags) { - if (par->blitter_may_be_busy) - wait_for_idle(par); cfb_copyarea(info, area); return; } @@ -248,8 +246,6 @@ void atyfb_fillrect(struct fb_info *info if (!rect->width || !rect->height) return; if (!par->accel_flags) { - if (par->blitter_may_be_busy) - wait_for_idle(par); cfb_fillrect(info, rect); return; } @@ -288,14 +284,10 @@ void atyfb_imageblit(struct fb_info *inf return; if (!par->accel_flags || (image->depth != 1 && info->var.bits_per_pixel != image->depth)) { - if (par->blitter_may_be_busy) - wait_for_idle(par); - cfb_imageblit(info, image); return; } - wait_for_idle(par); pix_width = pix_width_save = aty_ld_le32(DP_PIX_WIDTH, par); host_cntl = aty_ld_le32(HOST_CNTL, par) | HOST_BYTE_ALIGN; @@ -425,8 +417,6 @@ void atyfb_imageblit(struct fb_info *inf } } - wait_for_idle(par); - /* restore pix_width */ wait_for_fifo(1, par); aty_st_le32(DP_PIX_WIDTH, pix_width_save, par); diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c index ad8b749..2a7f381 100644 --- a/drivers/video/aty/mach64_cursor.c +++ b/drivers/video/aty/mach64_cursor.c @@ -66,11 +66,6 @@ static const u8 cursor_bits_lookup[16] = 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55 }; -static const u8 cursor_mask_lookup[16] = { - 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02, - 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00 -}; - static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor) { struct atyfb_par *par = (struct atyfb_par *) info->par; @@ -130,13 +125,13 @@ #endif fg_idx = cursor->image.fg_color; bg_idx = cursor->image.bg_color; - fg = (info->cmap.red[fg_idx] << 24) | - (info->cmap.green[fg_idx] << 16) | - (info->cmap.blue[fg_idx] << 8) | 15; + fg = ((info->cmap.red[fg_idx] & 0xff) << 24) | + ((info->cmap.green[fg_idx] & 0xff) << 16) | + ((info->cmap.blue[fg_idx] & 0xff) << 8) | 0xff; - bg = (info->cmap.red[bg_idx] << 24) | - (info->cmap.green[bg_idx] << 16) | - (info->cmap.blue[bg_idx] << 8); + bg = ((info->cmap.red[bg_idx] & 0xff) << 24) | + ((info->cmap.green[bg_idx] & 0xff) << 16) | + ((info->cmap.blue[bg_idx] & 0xff) << 8); wait_for_fifo(2, par); aty_st_le32(CUR_CLR0, bg, par); @@ -166,19 +161,17 @@ #endif switch (cursor->rop) { case ROP_XOR: // Upper 4 bits of mask data - fb_writeb(cursor_mask_lookup[m >> 4 ] | - cursor_bits_lookup[(b ^ m) >> 4], dst++); + fb_writeb(cursor_bits_lookup[(b ^ m) >> 4], dst++); // Lower 4 bits of mask - fb_writeb(cursor_mask_lookup[m & 0x0f ] | - cursor_bits_lookup[(b ^ m) & 0x0f], dst++); + fb_writeb(cursor_bits_lookup[(b ^ m) & 0x0f], + dst++); break; case ROP_COPY: // Upper 4 bits of mask data - fb_writeb(cursor_mask_lookup[m >> 4 ] | - cursor_bits_lookup[(b & m) >> 4], dst++); + fb_writeb(cursor_bits_lookup[(b & m) >> 4], dst++); // Lower 4 bits of mask - fb_writeb(cursor_mask_lookup[m & 0x0f ] | - cursor_bits_lookup[(b & m) & 0x0f], dst++); + fb_writeb(cursor_bits_lookup[(b & m) & 0x0f], + dst++); break; } } @@ -194,7 +187,7 @@ #endif return 0; } -int __init aty_init_cursor(struct fb_info *info) +int __devinit aty_init_cursor(struct fb_info *info) { unsigned long addr; diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c new file mode 100644 index 0000000..7de66b8 --- /dev/null +++ b/drivers/video/aty/radeon_backlight.c @@ -0,0 +1,247 @@ +/* + * Backlight code for ATI Radeon based graphic cards + * + * Copyright (c) 2000 Ani Joshi + * Copyright (c) 2003 Benjamin Herrenschmidt + * Copyright (c) 2006 Michael Hanselmann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "radeonfb.h" +#include + +#ifdef CONFIG_PMAC_BACKLIGHT +#include +#endif + +#define MAX_RADEON_LEVEL 0xFF + +static struct backlight_properties radeon_bl_data; + +struct radeon_bl_privdata { + struct radeonfb_info *rinfo; + uint8_t negative; +}; + +static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata, + int level) +{ + struct fb_info *info = pdata->rinfo->info; + int rlevel; + + mutex_lock(&info->bl_mutex); + + /* Get and convert the value */ + rlevel = pdata->rinfo->info->bl_curve[level] * + FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL; + + mutex_unlock(&info->bl_mutex); + + if (pdata->negative) + rlevel = MAX_RADEON_LEVEL - rlevel; + + if (rlevel < 0) + rlevel = 0; + else if (rlevel > MAX_RADEON_LEVEL) + rlevel = MAX_RADEON_LEVEL; + + return rlevel; +} + +static int radeon_bl_update_status(struct backlight_device *bd) +{ + struct radeon_bl_privdata *pdata = class_get_devdata(&bd->class_dev); + struct radeonfb_info *rinfo = pdata->rinfo; + u32 lvds_gen_cntl, tmpPixclksCntl; + int level; + + if (rinfo->mon1_type != MT_LCD) + return 0; + + /* We turn off the LCD completely instead of just dimming the + * backlight. This provides some greater power saving and the display + * is useless without backlight anyway. + */ + if (bd->props->power != FB_BLANK_UNBLANK || + bd->props->fb_blank != FB_BLANK_UNBLANK) + level = 0; + else + level = bd->props->brightness; + + del_timer_sync(&rinfo->lvds_timer); + radeon_engine_idle(); + + lvds_gen_cntl = INREG(LVDS_GEN_CNTL); + if (level > 0) { + lvds_gen_cntl &= ~LVDS_DISPLAY_DIS; + if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) { + lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON); + lvds_gen_cntl |= LVDS_BLON | LVDS_EN; + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; + lvds_gen_cntl |= + (radeon_bl_get_level_brightness(pdata, level) << + LVDS_BL_MOD_LEVEL_SHIFT); + lvds_gen_cntl |= LVDS_ON; + lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN); + rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; + mod_timer(&rinfo->lvds_timer, + jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); + } else { + lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; + lvds_gen_cntl |= + (radeon_bl_get_level_brightness(pdata, level) << + LVDS_BL_MOD_LEVEL_SHIFT); + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + } + rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; + rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl + & LVDS_STATE_MASK; + } else { + /* Asic bug, when turning off LVDS_ON, we have to make sure + RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off + */ + tmpPixclksCntl = INPLL(PIXCLKS_CNTL); + if (rinfo->is_mobility || rinfo->is_IGP) + OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb); + lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN); + lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) << + LVDS_BL_MOD_LEVEL_SHIFT); + lvds_gen_cntl |= LVDS_DISPLAY_DIS; + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + udelay(100); + lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN); + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~(LVDS_DIGON); + rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; + mod_timer(&rinfo->lvds_timer, + jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); + if (rinfo->is_mobility || rinfo->is_IGP) + OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl); + } + rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; + rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK); + + return 0; +} + +static int radeon_bl_get_brightness(struct backlight_device *bd) +{ + return bd->props->brightness; +} + +static struct backlight_properties radeon_bl_data = { + .owner = THIS_MODULE, + .get_brightness = radeon_bl_get_brightness, + .update_status = radeon_bl_update_status, + .max_brightness = (FB_BACKLIGHT_LEVELS - 1), +}; + +void radeonfb_bl_init(struct radeonfb_info *rinfo) +{ + struct backlight_device *bd; + struct radeon_bl_privdata *pdata; + char name[12]; + + if (rinfo->mon1_type != MT_LCD) + return; + +#ifdef CONFIG_PMAC_BACKLIGHT + if (!pmac_has_backlight_type("ati") && + !pmac_has_backlight_type("mnca")) + return; +#endif + + pdata = kmalloc(sizeof(struct radeon_bl_privdata), GFP_KERNEL); + if (!pdata) { + printk("radeonfb: Memory allocation failed\n"); + goto error; + } + + snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node); + + bd = backlight_device_register(name, pdata, &radeon_bl_data); + if (IS_ERR(bd)) { + rinfo->info->bl_dev = NULL; + printk("radeonfb: Backlight registration failed\n"); + goto error; + } + + pdata->rinfo = rinfo; + + /* Pardon me for that hack... maybe some day we can figure out in what + * direction backlight should work on a given panel? + */ + pdata->negative = + (rinfo->family != CHIP_FAMILY_RV200 && + rinfo->family != CHIP_FAMILY_RV250 && + rinfo->family != CHIP_FAMILY_RV280 && + rinfo->family != CHIP_FAMILY_RV350); + +#ifdef CONFIG_PMAC_BACKLIGHT + pdata->negative = pdata->negative || + machine_is_compatible("PowerBook4,3") || + machine_is_compatible("PowerBook6,3") || + machine_is_compatible("PowerBook6,5"); +#endif + + mutex_lock(&rinfo->info->bl_mutex); + rinfo->info->bl_dev = bd; + fb_bl_default_curve(rinfo->info, 0, + 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL, + 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL); + mutex_unlock(&rinfo->info->bl_mutex); + + up(&bd->sem); + bd->props->brightness = radeon_bl_data.max_brightness; + bd->props->power = FB_BLANK_UNBLANK; + bd->props->update_status(bd); + down(&bd->sem); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); + if (!pmac_backlight) + pmac_backlight = bd; + mutex_unlock(&pmac_backlight_mutex); +#endif + + printk("radeonfb: Backlight initialized (%s)\n", name); + + return; + +error: + kfree(pdata); + return; +} + +void radeonfb_bl_exit(struct radeonfb_info *rinfo) +{ +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); +#endif + + mutex_lock(&rinfo->info->bl_mutex); + if (rinfo->info->bl_dev) { + struct radeon_bl_privdata *pdata; + +#ifdef CONFIG_PMAC_BACKLIGHT + if (pmac_backlight == rinfo->info->bl_dev) + pmac_backlight = NULL; +#endif + + pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev); + backlight_device_unregister(rinfo->info->bl_dev); + kfree(pdata); + rinfo->info->bl_dev = NULL; + + printk("radeonfb: Backlight unloaded\n"); + } + mutex_unlock(&rinfo->info->bl_mutex); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_unlock(&pmac_backlight_mutex); +#endif +} diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 387a18a..68b1564 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -78,10 +78,6 @@ #ifdef CONFIG_PPC_OF #include #include "../macmodes.h" -#ifdef CONFIG_PMAC_BACKLIGHT -#include -#endif - #ifdef CONFIG_BOOTX_TEXT #include #endif @@ -277,20 +273,6 @@ #endif * prototypes */ - -#ifdef CONFIG_PPC_OF - -#ifdef CONFIG_PMAC_BACKLIGHT -static int radeon_set_backlight_enable(int on, int level, void *data); -static int radeon_set_backlight_level(int level, void *data); -static struct backlight_controller radeon_backlight_controller = { - radeon_set_backlight_enable, - radeon_set_backlight_level -}; -#endif /* CONFIG_PMAC_BACKLIGHT */ - -#endif /* CONFIG_PPC_OF */ - static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev) { if (!rinfo->bios_seg) @@ -1913,116 +1895,6 @@ static int __devinit radeon_set_fbinfo ( return 0; } - -#ifdef CONFIG_PMAC_BACKLIGHT - -/* TODO: Dbl check these tables, we don't go up to full ON backlight - * in these, possibly because we noticed MacOS doesn't, but I'd prefer - * having some more official numbers from ATI - */ -static int backlight_conv_m6[] = { - 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, - 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 -}; -static int backlight_conv_m7[] = { - 0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81, - 0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9 -}; - -#define BACKLIGHT_LVDS_OFF -#undef BACKLIGHT_DAC_OFF - -/* We turn off the LCD completely instead of just dimming the backlight. - * This provides some greater power saving and the display is useless - * without backlight anyway. - */ -static int radeon_set_backlight_enable(int on, int level, void *data) -{ - struct radeonfb_info *rinfo = (struct radeonfb_info *)data; - u32 lvds_gen_cntl, tmpPixclksCntl; - int* conv_table; - - if (rinfo->mon1_type != MT_LCD) - return 0; - - /* Pardon me for that hack... maybe some day we can figure - * out in what direction backlight should work on a given - * panel ? - */ - if ((rinfo->family == CHIP_FAMILY_RV200 || - rinfo->family == CHIP_FAMILY_RV250 || - rinfo->family == CHIP_FAMILY_RV280 || - rinfo->family == CHIP_FAMILY_RV350) && - !machine_is_compatible("PowerBook4,3") && - !machine_is_compatible("PowerBook6,3") && - !machine_is_compatible("PowerBook6,5")) - conv_table = backlight_conv_m7; - else - conv_table = backlight_conv_m6; - - del_timer_sync(&rinfo->lvds_timer); - radeon_engine_idle(); - - lvds_gen_cntl = INREG(LVDS_GEN_CNTL); - if (on && (level > BACKLIGHT_OFF)) { - lvds_gen_cntl &= ~LVDS_DISPLAY_DIS; - if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) { - lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON); - lvds_gen_cntl |= LVDS_BLON | LVDS_EN; - OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); - lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; - lvds_gen_cntl |= (conv_table[level] << - LVDS_BL_MOD_LEVEL_SHIFT); - lvds_gen_cntl |= LVDS_ON; - lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN); - rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; - mod_timer(&rinfo->lvds_timer, - jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); - } else { - lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; - lvds_gen_cntl |= (conv_table[level] << - LVDS_BL_MOD_LEVEL_SHIFT); - OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); - } - rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; - rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl - & LVDS_STATE_MASK; - } else { - /* Asic bug, when turning off LVDS_ON, we have to make sure - RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off - */ - tmpPixclksCntl = INPLL(PIXCLKS_CNTL); - if (rinfo->is_mobility || rinfo->is_IGP) - OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb); - lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN); - lvds_gen_cntl |= (conv_table[0] << - LVDS_BL_MOD_LEVEL_SHIFT); - lvds_gen_cntl |= LVDS_DISPLAY_DIS; - OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); - udelay(100); - lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN); - OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); - lvds_gen_cntl &= ~(LVDS_DIGON); - rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; - mod_timer(&rinfo->lvds_timer, - jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); - if (rinfo->is_mobility || rinfo->is_IGP) - OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl); - } - rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; - rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK); - - return 0; -} - - -static int radeon_set_backlight_level(int level, void *data) -{ - return radeon_set_backlight_enable(1, level, data); -} -#endif /* CONFIG_PMAC_BACKLIGHT */ - - /* * This reconfigure the card's internal memory map. In theory, we'd like * to setup the card's memory at the same address as it's PCI bus address, @@ -2477,14 +2349,7 @@ #ifdef CONFIG_MTRR MTRR_TYPE_WRCOMB, 1); #endif -#ifdef CONFIG_PMAC_BACKLIGHT - if (rinfo->mon1_type == MT_LCD) { - register_backlight_controller(&radeon_backlight_controller, - rinfo, "ati"); - register_backlight_controller(&radeon_backlight_controller, - rinfo, "mnca"); - } -#endif + radeonfb_bl_init(rinfo); printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name); @@ -2514,7 +2379,6 @@ err_release_pci0: err_release_fb: framebuffer_release(info); err_disable: - pci_disable_device(pdev); err_out: return ret; } @@ -2528,7 +2392,8 @@ static void __devexit radeonfb_pci_unreg if (!rinfo) return; - + + radeonfb_bl_exit(rinfo); radeonfb_pm_exit(rinfo); if (rinfo->mon1_EDID) @@ -2570,7 +2435,6 @@ #ifdef CONFIG_FB_RADEON_I2C #endif fb_dealloc_cmap(&info->cmap); framebuffer_release(info); - pci_disable_device(pdev); } diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 217e00a..1645943 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -625,4 +625,13 @@ extern int radeon_screen_blank(struct ra extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, int reg_only); +/* Backlight functions */ +#ifdef CONFIG_FB_RADEON_BACKLIGHT +extern void radeonfb_bl_init(struct radeonfb_info *rinfo); +extern void radeonfb_bl_exit(struct radeonfb_info *rinfo); +#else +static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {} +static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {} +#endif + #endif /* __RADEONFB_H__ */ diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index 789450b..d63c3f4 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -7,6 +7,8 @@ * Karl Lessard * * + * PM support added by Rodolfo Giometti + * * Copyright 2002 MontaVista Software * Author: MontaVista Software, Inc. * ppopov@mvista.com or source@mvista.com @@ -602,17 +604,52 @@ #endif return 0; } +#ifdef CONFIG_PM +static u32 sys_clksrc; +static struct au1100fb_regs fbregs; + int au1100fb_drv_suspend(struct device *dev, pm_message_t state) { - /* TODO */ + struct au1100fb_device *fbdev = dev_get_drvdata(dev); + + if (!fbdev) + return 0; + + /* Save the clock source state */ + sys_clksrc = au_readl(SYS_CLKSRC); + + /* Blank the LCD */ + au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info); + + /* Stop LCD clocking */ + au_writel(sys_clksrc & ~SYS_CS_ML_MASK, SYS_CLKSRC); + + memcpy(&fbregs, fbdev->regs, sizeof(struct au1100fb_regs)); + return 0; } int au1100fb_drv_resume(struct device *dev) { - /* TODO */ + struct au1100fb_device *fbdev = dev_get_drvdata(dev); + + if (!fbdev) + return 0; + + memcpy(fbdev->regs, &fbregs, sizeof(struct au1100fb_regs)); + + /* Restart LCD clocking */ + au_writel(sys_clksrc, SYS_CLKSRC); + + /* Unblank the LCD */ + au1100fb_fb_blank(VESA_NO_BLANKING, &fbdev->info); + return 0; } +#else +#define au1100fb_drv_suspend NULL +#define au1100fb_drv_resume NULL +#endif static struct device_driver au1100fb_driver = { .name = "au1100-lcd", diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index b895eaa..022f9d3 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -10,7 +10,7 @@ menuconfig BACKLIGHT_LCD_SUPPORT config BACKLIGHT_CLASS_DEVICE tristate "Lowlevel Backlight controls" - depends on BACKLIGHT_LCD_SUPPORT + depends on BACKLIGHT_LCD_SUPPORT && FB default m help This framework adds support for low-level control of the LCD @@ -26,7 +26,7 @@ config BACKLIGHT_DEVICE config LCD_CLASS_DEVICE tristate "Lowlevel LCD controls" - depends on BACKLIGHT_LCD_SUPPORT + depends on BACKLIGHT_LCD_SUPPORT && FB default m help This framework adds support for low-level control of LCD. @@ -50,6 +50,14 @@ config BACKLIGHT_CORGI If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the backlight driver. +config BACKLIGHT_LOCOMO + tristate "Sharp LOCOMO LCD/Backlight Driver" + depends on BACKLIGHT_DEVICE && SHARP_LOCOMO + default y + help + If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to + enable the LCD/backlight driver. + config BACKLIGHT_HP680 tristate "HP Jornada 680 Backlight Driver" depends on BACKLIGHT_DEVICE && SH_HP6XX diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 744210c..65e5553 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_LCD_CLASS_DEVICE) += lc obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o -obj-$(CONFIG_SHARP_LOCOMO) += locomolcd.o +obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c index 60831bb..bd879b7 100644 --- a/drivers/video/backlight/locomolcd.c +++ b/drivers/video/backlight/locomolcd.c @@ -17,6 +17,8 @@ #include #include #include #include +#include +#include #include #include @@ -25,7 +27,10 @@ #include #include "../../../arch/arm/mach-sa1100/generic.h" +static struct backlight_device *locomolcd_bl_device; static struct locomo_dev *locomolcd_dev; +static unsigned long locomolcd_flags; +#define LOCOMOLCD_SUSPENDED 0x01 static void locomolcd_on(int comadj) { @@ -89,12 +94,10 @@ void locomolcd_power(int on) } /* read comadj */ - if (comadj == -1) { - if (machine_is_poodle()) - comadj = 118; - if (machine_is_collie()) - comadj = 128; - } + if (comadj == -1 && machine_is_collie()) + comadj = 128; + if (comadj == -1 && machine_is_poodle()) + comadj = 118; if (on) locomolcd_on(comadj); @@ -105,26 +108,100 @@ void locomolcd_power(int on) } EXPORT_SYMBOL(locomolcd_power); -static int poodle_lcd_probe(struct locomo_dev *dev) + +static int current_intensity; + +static int locomolcd_set_intensity(struct backlight_device *bd) +{ + int intensity = bd->props->brightness; + + if (bd->props->power != FB_BLANK_UNBLANK) + intensity = 0; + if (bd->props->fb_blank != FB_BLANK_UNBLANK) + intensity = 0; + if (locomolcd_flags & LOCOMOLCD_SUSPENDED) + intensity = 0; + + switch (intensity) { + /* AC and non-AC are handled differently, but produce same results in sharp code? */ + case 0: locomo_frontlight_set(locomolcd_dev, 0, 0, 161); break; + case 1: locomo_frontlight_set(locomolcd_dev, 117, 0, 161); break; + case 2: locomo_frontlight_set(locomolcd_dev, 163, 0, 148); break; + case 3: locomo_frontlight_set(locomolcd_dev, 194, 0, 161); break; + case 4: locomo_frontlight_set(locomolcd_dev, 194, 1, 161); break; + + default: + return -ENODEV; + } + current_intensity = intensity; + return 0; +} + +static int locomolcd_get_intensity(struct backlight_device *bd) +{ + return current_intensity; +} + +static struct backlight_properties locomobl_data = { + .owner = THIS_MODULE, + .get_brightness = locomolcd_get_intensity, + .update_status = locomolcd_set_intensity, + .max_brightness = 4, +}; + +#ifdef CONFIG_PM +static int locomolcd_suspend(struct locomo_dev *dev, pm_message_t state) +{ + locomolcd_flags |= LOCOMOLCD_SUSPENDED; + locomolcd_set_intensity(locomolcd_bl_device); + return 0; +} + +static int locomolcd_resume(struct locomo_dev *dev) +{ + locomolcd_flags &= ~LOCOMOLCD_SUSPENDED; + locomolcd_set_intensity(locomolcd_bl_device); + return 0; +} +#else +#define locomolcd_suspend NULL +#define locomolcd_resume NULL +#endif + +static int locomolcd_probe(struct locomo_dev *dev) { unsigned long flags; local_irq_save(flags); locomolcd_dev = dev; + locomo_gpio_set_dir(dev, LOCOMO_GPIO_FL_VR, 0); + /* the poodle_lcd_power function is called for the first time * from fs_initcall, which is before locomo is activated. * We need to recall poodle_lcd_power here*/ -#ifdef CONFIG_MACH_POODLE - locomolcd_power(1); -#endif + if (machine_is_poodle()) + locomolcd_power(1); + local_irq_restore(flags); + + locomolcd_bl_device = backlight_device_register("locomo-bl", NULL, &locomobl_data); + + if (IS_ERR (locomolcd_bl_device)) + return PTR_ERR (locomolcd_bl_device); + + /* Set up frontlight so that screen is readable */ + locomobl_data.brightness = 2; + locomolcd_set_intensity(locomolcd_bl_device); + return 0; } -static int poodle_lcd_remove(struct locomo_dev *dev) +static int locomolcd_remove(struct locomo_dev *dev) { unsigned long flags; + + backlight_device_unregister(locomolcd_bl_device); local_irq_save(flags); locomolcd_dev = NULL; local_irq_restore(flags); @@ -136,19 +213,33 @@ static struct locomo_driver poodle_lcd_d .name = "locomo-backlight", }, .devid = LOCOMO_DEVID_BACKLIGHT, - .probe = poodle_lcd_probe, - .remove = poodle_lcd_remove, + .probe = locomolcd_probe, + .remove = locomolcd_remove, + .suspend = locomolcd_suspend, + .resume = locomolcd_resume, }; -static int __init poodle_lcd_init(void) + +static int __init locomolcd_init(void) { int ret = locomo_driver_register(&poodle_lcd_driver); - if (ret) return ret; + if (ret) + return ret; #ifdef CONFIG_SA1100_COLLIE sa1100fb_lcd_power = locomolcd_power; #endif return 0; } -device_initcall(poodle_lcd_init); +static void __exit locomolcd_exit(void) +{ + locomo_driver_unregister(&poodle_lcd_driver); +} + +module_init(locomolcd_init); +module_exit(locomolcd_exit); + +MODULE_AUTHOR("John Lenz , Pavel Machek "); +MODULE_DESCRIPTION("Collie LCD driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index 8ba6152..ad8a89b 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -230,6 +230,7 @@ static inline void fast_imageblit(const tab = cfb_tab16; break; case 32: + default: tab = cfb_tab32; break; } diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 72ff6bf..d76bbfa 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -148,9 +148,24 @@ static int chipsfb_set_par(struct fb_inf static int chipsfb_blank(int blank, struct fb_info *info) { #ifdef CONFIG_PMAC_BACKLIGHT - // used to disable backlight only for blank > 1, but it seems - // useful at blank = 1 too (saves battery, extends backlight life) - set_backlight_enable(!blank); + mutex_lock(&pmac_backlight_mutex); + + if (pmac_backlight) { + down(&pmac_backlight->sem); + + /* used to disable backlight only for blank > 1, but it seems + * useful at blank = 1 too (saves battery, extends backlight + * life) + */ + if (blank) + pmac_backlight->props->power = FB_BLANK_POWERDOWN; + else + pmac_backlight->props->power = FB_BLANK_UNBLANK; + pmac_backlight->props->update_status(pmac_backlight); + up(&pmac_backlight->sem); + } + + mutex_unlock(&pmac_backlight_mutex); #endif /* CONFIG_PMAC_BACKLIGHT */ return 1; /* get fb_blank to set the colormap to all black */ @@ -401,7 +416,14 @@ #endif #ifdef CONFIG_PMAC_BACKLIGHT /* turn on the backlight */ - set_backlight_enable(1); + mutex_lock(&pmac_backlight_mutex); + if (pmac_backlight) { + down(&pmac_backlight->sem); + pmac_backlight->props->power = FB_BLANK_UNBLANK; + pmac_backlight->props->update_status(pmac_backlight); + up(&pmac_backlight->sem); + } + mutex_unlock(&pmac_backlight_mutex); #endif /* CONFIG_PMAC_BACKLIGHT */ #ifdef CONFIG_PPC diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 1103010..dda240e 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2227,7 +2227,6 @@ #endif release_region(0x3C0, 32); pci_release_regions(pdev); framebuffer_release(cinfo->info); - pci_disable_device(pdev); } #endif /* CONFIG_PCI */ @@ -2458,7 +2457,6 @@ #endif err_release_fb: framebuffer_release(info); err_disable: - pci_disable_device(pdev); err_out: return ret; } diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 47ba1a7..5dc4083 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -125,6 +125,8 @@ static int softback_lines; static int first_fb_vc; static int last_fb_vc = MAX_NR_CONSOLES - 1; static int fbcon_is_default = 1; +static int fbcon_has_exited; + /* font data */ static char fontname[40]; @@ -140,7 +142,6 @@ #define CM_SOFTBACK (8) #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row) -static void fbcon_free_font(struct display *); static int fbcon_set_origin(struct vc_data *); #define CURSOR_DRAW_DELAY (1) @@ -194,6 +195,9 @@ static void fbcon_redraw_move(struct vc_ int line, int count, int dy); static void fbcon_modechanged(struct fb_info *info); static void fbcon_set_all_vcs(struct fb_info *info); +static void fbcon_start(void); +static void fbcon_exit(void); +static struct class_device *fbcon_class_device; #ifdef CONFIG_MAC /* @@ -252,7 +256,7 @@ static void fbcon_rotate_all(struct fb_i if (!ops || ops->currcon < 0 || rotate > 3) return; - for (i = 0; i < MAX_NR_CONSOLES; i++) { + for (i = first_fb_vc; i <= last_fb_vc; i++) { vc = vc_cons[i].d; if (!vc || vc->vc_mode != KD_TEXT || registered_fb[con2fb_map[i]] != info) @@ -389,15 +393,18 @@ static void fb_flashcursor(void *private int c; int mode; - if (ops->currcon != -1) + acquire_console_sem(); + if (ops && ops->currcon != -1) vc = vc_cons[ops->currcon].d; if (!vc || !CON_IS_VISIBLE(vc) || fbcon_is_inactive(vc, info) || registered_fb[con2fb_map[vc->vc_num]] != info || - vc_cons[ops->currcon].d->vc_deccm != 1) + vc_cons[ops->currcon].d->vc_deccm != 1) { + release_console_sem(); return; - acquire_console_sem(); + } + p = &fb_display[vc->vc_num]; c = scr_readw((u16 *) vc->vc_pos); mode = (!ops->cursor_flash || ops->cursor_state.enable) ? @@ -528,7 +535,7 @@ static int search_fb_in_map(int idx) { int i, retval = 0; - for (i = 0; i < MAX_NR_CONSOLES; i++) { + for (i = first_fb_vc; i <= last_fb_vc; i++) { if (con2fb_map[i] == idx) retval = 1; } @@ -539,7 +546,7 @@ static int search_for_mapped_con(void) { int i, retval = 0; - for (i = 0; i < MAX_NR_CONSOLES; i++) { + for (i = first_fb_vc; i <= last_fb_vc; i++) { if (con2fb_map[i] != -1) retval = 1; } @@ -561,6 +568,7 @@ static int fbcon_takeover(int show_logo) err = take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default); + if (err) { for (i = first_fb_vc; i <= last_fb_vc; i++) { con2fb_map[i] = -1; @@ -795,8 +803,8 @@ static int set_con2fb_map(int unit, int if (oldidx == newidx) return 0; - if (!info) - err = -EINVAL; + if (!info || fbcon_has_exited) + return -EINVAL; if (!err && !search_for_mapped_con()) { info_idx = newidx; @@ -832,6 +840,9 @@ static int set_con2fb_map(int unit, int con2fb_init_display(vc, info, unit, show_logo); } + if (!search_fb_in_map(info_idx)) + info_idx = newidx; + release_console_sem(); return err; } @@ -1034,6 +1045,7 @@ #ifdef CONFIG_MAC #endif /* CONFIG_MAC */ fbcon_add_cursor_timer(info); + fbcon_has_exited = 0; return display_desc; } @@ -1061,17 +1073,36 @@ static void fbcon_init(struct vc_data *v /* If we are not the first console on this fb, copy the font from that console */ - t = &fb_display[svc->vc_num]; - if (!vc->vc_font.data) { - vc->vc_font.data = (void *)(p->fontdata = t->fontdata); - vc->vc_font.width = (*default_mode)->vc_font.width; - vc->vc_font.height = (*default_mode)->vc_font.height; - p->userfont = t->userfont; - if (p->userfont) - REFCOUNT(p->fontdata)++; + t = &fb_display[fg_console]; + if (!p->fontdata) { + if (t->fontdata) { + struct vc_data *fvc = vc_cons[fg_console].d; + + vc->vc_font.data = (void *)(p->fontdata = + fvc->vc_font.data); + vc->vc_font.width = fvc->vc_font.width; + vc->vc_font.height = fvc->vc_font.height; + p->userfont = t->userfont; + + if (p->userfont) + REFCOUNT(p->fontdata)++; + } else { + const struct font_desc *font = NULL; + + if (!fontname[0] || !(font = find_font(fontname))) + font = get_default_font(info->var.xres, + info->var.yres); + vc->vc_font.width = font->width; + vc->vc_font.height = font->height; + vc->vc_font.data = (void *)(p->fontdata = font->data); + vc->vc_font.charcount = 256; /* FIXME Need to + support more fonts */ + } } + if (p->userfont) charcnt = FNTCHARCNT(p->fontdata); + vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; if (charcnt == 256) { @@ -1145,13 +1176,47 @@ static void fbcon_init(struct vc_data *v ops->p = &fb_display[fg_console]; } +static void fbcon_free_font(struct display *p) +{ + if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) + kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); + p->fontdata = NULL; + p->userfont = 0; +} + static void fbcon_deinit(struct vc_data *vc) { struct display *p = &fb_display[vc->vc_num]; + struct fb_info *info; + struct fbcon_ops *ops; + int idx; - if (info_idx != -1) - return; fbcon_free_font(p); + idx = con2fb_map[vc->vc_num]; + + if (idx == -1) + goto finished; + + info = registered_fb[idx]; + + if (!info) + goto finished; + + ops = info->fbcon_par; + + if (!ops) + goto finished; + + if (CON_IS_VISIBLE(vc)) + fbcon_del_cursor_timer(info); + + ops->flags &= ~FBCON_FLAGS_INIT; +finished: + + if (!con_is_bound(&fb_con)) + fbcon_exit(); + + return; } /* ====================================================================== */ @@ -2099,12 +2164,11 @@ static int fbcon_switch(struct vc_data * if (info->fbops->fb_set_par) info->fbops->fb_set_par(info); - if (old_info != info) { + if (old_info != info) fbcon_del_cursor_timer(old_info); - fbcon_add_cursor_timer(info); - } } + fbcon_add_cursor_timer(info); set_blitting_type(vc, info); ops->cursor_reset = 1; @@ -2222,14 +2286,6 @@ static int fbcon_blank(struct vc_data *v return 0; } -static void fbcon_free_font(struct display *p) -{ - if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) - kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); - p->fontdata = NULL; - p->userfont = 0; -} - static int fbcon_get_font(struct vc_data *vc, struct console_font *font) { u8 *fontdata = vc->vc_font.data; @@ -2443,7 +2499,7 @@ static int fbcon_set_font(struct vc_data FNTSUM(new_data) = csum; /* Check if the same font is on some other console already */ - for (i = 0; i < MAX_NR_CONSOLES; i++) { + for (i = first_fb_vc; i <= last_fb_vc; i++) { struct vc_data *tmp = vc_cons[i].d; if (fb_display[i].userfont && @@ -2768,7 +2824,7 @@ static void fbcon_set_all_vcs(struct fb_ if (!ops || ops->currcon < 0) return; - for (i = 0; i < MAX_NR_CONSOLES; i++) { + for (i = first_fb_vc; i <= last_fb_vc; i++) { vc = vc_cons[i].d; if (!vc || vc->vc_mode != KD_TEXT || registered_fb[con2fb_map[i]] != info) @@ -2830,22 +2886,57 @@ static int fbcon_mode_deleted(struct fb_ return found; } +static int fbcon_fb_unregistered(int idx) +{ + int i; + + for (i = first_fb_vc; i <= last_fb_vc; i++) { + if (con2fb_map[i] == idx) + con2fb_map[i] = -1; + } + + if (idx == info_idx) { + info_idx = -1; + + for (i = 0; i < FB_MAX; i++) { + if (registered_fb[i] != NULL) { + info_idx = i; + break; + } + } + } + + if (info_idx != -1) { + for (i = first_fb_vc; i <= last_fb_vc; i++) { + if (con2fb_map[i] == -1) + con2fb_map[i] = info_idx; + } + } + + if (!num_registered_fb) + unregister_con_driver(&fb_con); + + return 0; +} + static int fbcon_fb_registered(int idx) { int ret = 0, i; if (info_idx == -1) { - for (i = 0; i < MAX_NR_CONSOLES; i++) { + for (i = first_fb_vc; i <= last_fb_vc; i++) { if (con2fb_map_boot[i] == idx) { info_idx = idx; break; } } + if (info_idx != -1) ret = fbcon_takeover(1); } else { - for (i = 0; i < MAX_NR_CONSOLES; i++) { - if (con2fb_map_boot[i] == idx) + for (i = first_fb_vc; i <= last_fb_vc; i++) { + if (con2fb_map_boot[i] == idx && + con2fb_map[i] == -1) set_con2fb_map(i, idx, 0); } } @@ -2882,7 +2973,7 @@ static void fbcon_new_modelist(struct fb struct fb_var_screeninfo var; struct fb_videomode *mode; - for (i = 0; i < MAX_NR_CONSOLES; i++) { + for (i = first_fb_vc; i <= last_fb_vc; i++) { if (registered_fb[con2fb_map[i]] != info) continue; if (!fb_display[i].mode) @@ -2910,6 +3001,14 @@ static int fbcon_event_notify(struct not struct fb_con2fbmap *con2fb; int ret = 0; + /* + * ignore all events except driver registration and deregistration + * if fbcon is not active + */ + if (fbcon_has_exited && !(action == FB_EVENT_FB_REGISTERED || + action == FB_EVENT_FB_UNREGISTERED)) + goto done; + switch(action) { case FB_EVENT_SUSPEND: fbcon_suspended(info); @@ -2930,6 +3029,9 @@ static int fbcon_event_notify(struct not case FB_EVENT_FB_REGISTERED: ret = fbcon_fb_registered(info->node); break; + case FB_EVENT_FB_UNREGISTERED: + ret = fbcon_fb_unregistered(info->node); + break; case FB_EVENT_SET_CONSOLE_MAP: con2fb = event->data; ret = set_con2fb_map(con2fb->console - 1, @@ -2945,16 +3047,9 @@ static int fbcon_event_notify(struct not case FB_EVENT_NEW_MODELIST: fbcon_new_modelist(info); break; - case FB_EVENT_SET_CON_ROTATE: - fbcon_rotate(info, *(int *)event->data); - break; - case FB_EVENT_GET_CON_ROTATE: - ret = fbcon_get_rotate(info); - break; - case FB_EVENT_SET_CON_ROTATE_ALL: - fbcon_rotate_all(info, *(int *)event->data); } +done: return ret; } @@ -2992,27 +3087,181 @@ static struct notifier_block fbcon_event .notifier_call = fbcon_event_notify, }; -static int __init fb_console_init(void) +static ssize_t store_rotate(struct class_device *class_device, + const char *buf, size_t count) { - int i; + struct fb_info *info; + int rotate, idx; + char **last = NULL; + + if (fbcon_has_exited) + return count; acquire_console_sem(); - fb_register_client(&fbcon_event_notifier); + idx = con2fb_map[fg_console]; + + if (idx == -1 || registered_fb[idx] == NULL) + goto err; + + info = registered_fb[idx]; + rotate = simple_strtoul(buf, last, 0); + fbcon_rotate(info, rotate); +err: release_console_sem(); + return count; +} - for (i = 0; i < MAX_NR_CONSOLES; i++) - con2fb_map[i] = -1; +static ssize_t store_rotate_all(struct class_device *class_device, + const char *buf, size_t count) +{ + struct fb_info *info; + int rotate, idx; + char **last = NULL; + + if (fbcon_has_exited) + return count; + + acquire_console_sem(); + idx = con2fb_map[fg_console]; + + if (idx == -1 || registered_fb[idx] == NULL) + goto err; + info = registered_fb[idx]; + rotate = simple_strtoul(buf, last, 0); + fbcon_rotate_all(info, rotate); +err: + release_console_sem(); + return count; +} + +static ssize_t show_rotate(struct class_device *class_device, char *buf) +{ + struct fb_info *info; + int rotate = 0, idx; + + if (fbcon_has_exited) + return 0; + + acquire_console_sem(); + idx = con2fb_map[fg_console]; + + if (idx == -1 || registered_fb[idx] == NULL) + goto err; + + info = registered_fb[idx]; + rotate = fbcon_get_rotate(info); +err: + release_console_sem(); + return snprintf(buf, PAGE_SIZE, "%d\n", rotate); +} + +static struct class_device_attribute class_device_attrs[] = { + __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), + __ATTR(rotate_all, S_IWUSR, NULL, store_rotate_all), +}; + +static int fbcon_init_class_device(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) + class_device_create_file(fbcon_class_device, + &class_device_attrs[i]); + return 0; +} + +static void fbcon_start(void) +{ if (num_registered_fb) { + int i; + + acquire_console_sem(); + for (i = 0; i < FB_MAX; i++) { if (registered_fb[i] != NULL) { info_idx = i; break; } } + + release_console_sem(); fbcon_takeover(0); } +} + +static void fbcon_exit(void) +{ + struct fb_info *info; + int i, j, mapped; + + if (fbcon_has_exited) + return; + +#ifdef CONFIG_ATARI + free_irq(IRQ_AUTO_4, fbcon_vbl_handler); +#endif +#ifdef CONFIG_MAC + if (MACH_IS_MAC && vbl_detected) + free_irq(IRQ_MAC_VBL, fbcon_vbl_handler); +#endif + + kfree((void *)softback_buf); + softback_buf = 0UL; + + for (i = 0; i < FB_MAX; i++) { + mapped = 0; + info = registered_fb[i]; + + if (info == NULL) + continue; + + for (j = first_fb_vc; j <= last_fb_vc; j++) { + if (con2fb_map[j] == i) + mapped = 1; + } + + if (mapped) { + if (info->fbops->fb_release) + info->fbops->fb_release(info, 0); + module_put(info->fbops->owner); + + if (info->fbcon_par) { + fbcon_del_cursor_timer(info); + kfree(info->fbcon_par); + info->fbcon_par = NULL; + } + if (info->queue.func == fb_flashcursor) + info->queue.func = NULL; + } + } + + fbcon_has_exited = 1; +} + +static int __init fb_console_init(void) +{ + int i; + + acquire_console_sem(); + fb_register_client(&fbcon_event_notifier); + fbcon_class_device = + class_device_create(fb_class, NULL, MKDEV(0, 0), NULL, "fbcon"); + + if (IS_ERR(fbcon_class_device)) { + printk(KERN_WARNING "Unable to create class_device " + "for fbcon; errno = %ld\n", + PTR_ERR(fbcon_class_device)); + fbcon_class_device = NULL; + } else + fbcon_init_class_device(); + + for (i = 0; i < MAX_NR_CONSOLES; i++) + con2fb_map[i] = -1; + + release_console_sem(); + fbcon_start(); return 0; } @@ -3020,12 +3269,24 @@ module_init(fb_console_init); #ifdef MODULE +static void __exit fbcon_deinit_class_device(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) + class_device_remove_file(fbcon_class_device, + &class_device_attrs[i]); +} + static void __exit fb_console_exit(void) { acquire_console_sem(); fb_unregister_client(&fbcon_event_notifier); + fbcon_deinit_class_device(); + class_device_destroy(fb_class, MKDEV(0, 0)); + fbcon_exit(); release_console_sem(); - give_up_console(&fb_con); + unregister_con_driver(&fb_con); } module_exit(fb_console_exit); diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index c38c3d8..3487a63 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -175,6 +175,7 @@ extern void fbcon_set_tileops(struct vc_ #endif extern void fbcon_set_bitops(struct fbcon_ops *ops); extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); +extern struct class *fb_class; #define FBCON_ATTRIBUTE_UNDERLINE 1 #define FBCON_ATTRIBUTE_REVERSE 2 diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 989e4d4..c89f90e 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -308,13 +308,13 @@ static void __init mda_initialize(void) outb_p(0x00, mda_gfx_port); } -static const char __init *mdacon_startup(void) +static const char *mdacon_startup(void) { mda_num_columns = 80; mda_num_lines = 25; - mda_vram_base = VGA_MAP_MEM(0xb0000); mda_vram_len = 0x01000; + mda_vram_base = VGA_MAP_MEM(0xb0000, mda_vram_len); mda_index_port = 0x3b4; mda_value_port = 0x3b5; diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index e99fe30..0304131 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -51,6 +51,7 @@ static int topscan; static int xcurs_correction = 29; static int newport_xsize; static int newport_ysize; +static int newport_has_init; static int newport_set_def_font(int unit, struct console_font *op); @@ -283,6 +284,15 @@ #undef L xcurs_correction = 21; } +static void newport_exit(void) +{ + int i; + + /* free memory used by user font */ + for (i = 0; i < MAX_NR_CONSOLES; i++) + newport_set_def_font(i, NULL); +} + /* Can't be __init, take_over_console may call it later */ static const char *newport_startup(void) { @@ -290,8 +300,10 @@ static const char *newport_startup(void) if (!sgi_gfxaddr) return NULL; - npregs = (struct newport_regs *) /* ioremap cannot fail */ - ioremap(sgi_gfxaddr, sizeof(struct newport_regs)); + + if (!npregs) + npregs = (struct newport_regs *)/* ioremap cannot fail */ + ioremap(sgi_gfxaddr, sizeof(struct newport_regs)); npregs->cset.config = NPORT_CFG_GD0; if (newport_wait(npregs)) @@ -307,11 +319,11 @@ static const char *newport_startup(void) newport_reset(); newport_get_revisions(); newport_get_screensize(); + newport_has_init = 1; return "SGI Newport"; out_unmap: - iounmap((void *)npregs); return NULL; } @@ -324,11 +336,10 @@ static void newport_init(struct vc_data static void newport_deinit(struct vc_data *c) { - int i; - - /* free memory used by user font */ - for (i = 0; i < MAX_NR_CONSOLES; i++) - newport_set_def_font(i, NULL); + if (!con_is_bound(&newport_con) && newport_has_init) { + newport_exit(); + newport_has_init = 0; + } } static void newport_clear(struct vc_data *vc, int sy, int sx, int height, @@ -728,16 +739,23 @@ const struct consw newport_con = { #ifdef MODULE static int __init newport_console_init(void) { + + if (!sgi_gfxaddr) + return NULL; + + if (!npregs) + npregs = (struct newport_regs *)/* ioremap cannot fail */ + ioremap(sgi_gfxaddr, sizeof(struct newport_regs)); + return take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1); } +module_init(newport_console_init); static void __exit newport_console_exit(void) { give_up_console(&newport_con); iounmap((void *)npregs); } - -module_init(newport_console_init); module_exit(newport_console_exit); #endif diff --git a/drivers/video/console/promcon.c b/drivers/video/console/promcon.c index 04f42fc..d6e6ad5 100644 --- a/drivers/video/console/promcon.c +++ b/drivers/video/console/promcon.c @@ -109,7 +109,7 @@ promcon_end(struct vc_data *conp, char * return b - p; } -const char __init *promcon_startup(void) +const char *promcon_startup(void) { const char *display_desc = "PROM"; int node; @@ -133,7 +133,7 @@ const char __init *promcon_startup(void) return display_desc; } -static void __init +static void promcon_init_unimap(struct vc_data *conp) { mm_segment_t old_fs = get_fs(); diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index fd5940f..45c4f22 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -75,7 +75,7 @@ static inline void cursor_undrawn(void) cursor_drawn = 0; } -static const char *__init sticon_startup(void) +static const char *sticon_startup(void) { return "STI console"; } diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index d5a04b6..f32b590 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -114,6 +114,7 @@ static int vga_512_chars; static int vga_video_font_height; static int vga_scan_lines; static unsigned int vga_rolled_over = 0; +static int vga_init_done; static int __init no_scroll(char *str) { @@ -190,7 +191,7 @@ static void vgacon_scrollback_init(int p } } -static void __init vgacon_scrollback_startup(void) +static void vgacon_scrollback_startup(void) { vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024); @@ -355,7 +356,7 @@ static int vgacon_scrolldelta(struct vc_ } #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */ -static const char __init *vgacon_startup(void) +static const char *vgacon_startup(void) { const char *display_desc = NULL; u16 saved1, saved2; @@ -391,7 +392,7 @@ #endif static struct resource ega_console_resource = { "ega", 0x3B0, 0x3BF }; vga_video_type = VIDEO_TYPE_EGAM; - vga_vram_end = 0xb8000; + vga_vram_size = 0x8000; display_desc = "EGA+"; request_resource(&ioport_resource, &ega_console_resource); @@ -401,7 +402,7 @@ #endif static struct resource mda2_console_resource = { "mda", 0x3BF, 0x3BF }; vga_video_type = VIDEO_TYPE_MDA; - vga_vram_end = 0xb2000; + vga_vram_size = 0x2000; display_desc = "*MDA"; request_resource(&ioport_resource, &mda1_console_resource); @@ -418,7 +419,7 @@ #endif if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { int i; - vga_vram_end = 0xc0000; + vga_vram_size = 0x8000; if (!ORIG_VIDEO_ISVGA) { static struct resource ega_console_resource @@ -443,7 +444,7 @@ #ifdef VGA_CAN_DO_64KB * and COE=1 isn't necessarily a good idea) */ vga_vram_base = 0xa0000; - vga_vram_end = 0xb0000; + vga_vram_size = 0x10000; outb_p(6, VGA_GFX_I); outb_p(6, VGA_GFX_D); #endif @@ -475,7 +476,7 @@ #endif static struct resource cga_console_resource = { "cga", 0x3D4, 0x3D5 }; vga_video_type = VIDEO_TYPE_CGA; - vga_vram_end = 0xba000; + vga_vram_size = 0x2000; display_desc = "*CGA"; request_resource(&ioport_resource, &cga_console_resource); @@ -483,9 +484,8 @@ #endif } } - vga_vram_base = VGA_MAP_MEM(vga_vram_base); - vga_vram_end = VGA_MAP_MEM(vga_vram_end); - vga_vram_size = vga_vram_end - vga_vram_base; + vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size); + vga_vram_end = vga_vram_base + vga_vram_size; /* * Find out if there is a graphics card present. @@ -524,7 +524,12 @@ #endif vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH; vgacon_yres = vga_scan_lines; - vgacon_scrollback_startup(); + + if (!vga_init_done) { + vgacon_scrollback_startup(); + vga_init_done = 1; + } + return display_desc; } @@ -532,10 +537,20 @@ static void vgacon_init(struct vc_data * { unsigned long p; - /* We cannot be loaded as a module, therefore init is always 1 */ + /* + * We cannot be loaded as a module, therefore init is always 1, + * but vgacon_init can be called more than once, and init will + * not be 1. + */ c->vc_can_do_color = vga_can_do_color; - c->vc_cols = vga_video_num_columns; - c->vc_rows = vga_video_num_lines; + + /* set dimensions manually if init != 0 since vc_resize() will fail */ + if (init) { + c->vc_cols = vga_video_num_columns; + c->vc_rows = vga_video_num_lines; + } else + vc_resize(c, vga_video_num_columns, vga_video_num_lines); + c->vc_scan_lines = vga_scan_lines; c->vc_font.height = vga_video_font_height; c->vc_complement_mask = 0x7700; @@ -1020,14 +1035,14 @@ static int vgacon_do_font_op(struct vgas char *charmap; if (vga_video_type != VIDEO_TYPE_EGAM) { - charmap = (char *) VGA_MAP_MEM(colourmap); + charmap = (char *) VGA_MAP_MEM(colourmap, 0); beg = 0x0e; #ifdef VGA_CAN_DO_64KB if (vga_video_type == VIDEO_TYPE_VGAC) beg = 0x06; #endif } else { - charmap = (char *) VGA_MAP_MEM(blackwmap); + charmap = (char *) VGA_MAP_MEM(blackwmap, 0); beg = 0x0a; } diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 0827594..f0a621e 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -605,11 +605,6 @@ static void clearfb16(struct fb_info *in fb_writeb(0, dst); } -static void epson1355fb_platform_release(struct device *device) -{ - dev_err(device, "This driver is broken, please bug the authors so they will fix it.\n"); -} - static int epson1355fb_remove(struct platform_device *dev) { struct fb_info *info = platform_get_drvdata(dev); @@ -733,13 +728,7 @@ static struct platform_driver epson1355f }, }; -static struct platform_device epson1355fb_device = { - .name = "epson1355fb", - .id = 0, - .dev = { - .release = epson1355fb_platform_release, - } -}; +static struct platform_device *epson1355fb_device; int __init epson1355fb_init(void) { @@ -749,11 +738,21 @@ int __init epson1355fb_init(void) return -ENODEV; ret = platform_driver_register(&epson1355fb_driver); + if (!ret) { - ret = platform_device_register(&epson1355fb_device); - if (ret) + epson1355fb_device = platform_device_alloc("epson1355fb", 0); + + if (epson1355fb_device) + ret = platform_device_add(epson1355fb_device); + else + ret = -ENOMEM; + + if (ret) { + platform_device_put(epson1355fb_device); platform_driver_unregister(&epson1355fb_driver); + } } + return ret; } @@ -762,7 +761,7 @@ module_init(epson1355fb_init); #ifdef MODULE static void __exit epson1355fb_exit(void) { - platform_device_unregister(&epson1355fb_device); + platform_device_unregister(epson1355fb_device); platform_driver_unregister(&epson1355fb_driver); } diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c index ac90883..b549899 100644 --- a/drivers/video/fbcvt.c +++ b/drivers/video/fbcvt.c @@ -376,4 +376,3 @@ int fb_find_mode_cvt(struct fb_videomode return 0; } -EXPORT_SYMBOL(fb_find_mode_cvt); diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 372aa17..31143af 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -34,7 +34,6 @@ #include #endif #include #include -#include #include #include @@ -162,7 +161,6 @@ char* fb_get_buffer_offset(struct fb_inf } #ifdef CONFIG_LOGO -#include static inline unsigned safe_shift(unsigned d, int n) { @@ -336,11 +334,11 @@ static void fb_rotate_logo_ud(const u8 * static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height) { - int i, j, w = width - 1; + int i, j, h = height - 1; for (i = 0; i < height; i++) for (j = 0; j < width; j++) - out[height * j + w - i] = *in++; + out[height * j + h - i] = *in++; } static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height) @@ -358,24 +356,24 @@ static void fb_rotate_logo(struct fb_inf u32 tmp; if (rotate == FB_ROTATE_UD) { - image->dx = info->var.xres - image->width; - image->dy = info->var.yres - image->height; fb_rotate_logo_ud(image->data, dst, image->width, image->height); + image->dx = info->var.xres - image->width; + image->dy = info->var.yres - image->height; } else if (rotate == FB_ROTATE_CW) { - tmp = image->width; - image->width = image->height; - image->height = tmp; - image->dx = info->var.xres - image->height; fb_rotate_logo_cw(image->data, dst, image->width, image->height); - } else if (rotate == FB_ROTATE_CCW) { tmp = image->width; image->width = image->height; image->height = tmp; - image->dy = info->var.yres - image->width; + image->dx = info->var.xres - image->width; + } else if (rotate == FB_ROTATE_CCW) { fb_rotate_logo_ccw(image->data, dst, image->width, image->height); + tmp = image->width; + image->width = image->height; + image->height = tmp; + image->dy = info->var.yres - image->height; } image->data = dst; @@ -435,7 +433,7 @@ int fb_prepare_logo(struct fb_info *info depth = info->var.green.length; } - if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) { + if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) { /* assume console colormap */ depth = 4; } @@ -1278,8 +1276,8 @@ #ifdef HAVE_ARCH_FB_UNMAPPED_AREA #endif }; -static struct class *fb_class; - +struct class *fb_class; +EXPORT_SYMBOL(fb_class); /** * register_framebuffer - registers a frame buffer device * @fb_info: frame buffer info structure @@ -1355,6 +1353,7 @@ register_framebuffer(struct fb_info *fb_ int unregister_framebuffer(struct fb_info *fb_info) { + struct fb_event event; int i; i = fb_info->node; @@ -1362,13 +1361,17 @@ unregister_framebuffer(struct fb_info *f return -EINVAL; devfs_remove("fb/%d", i); - if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) + if (fb_info->pixmap.addr && + (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) kfree(fb_info->pixmap.addr); fb_destroy_modelist(&fb_info->modelist); registered_fb[i]=NULL; num_registered_fb--; fb_cleanup_class_device(fb_info); class_device_destroy(fb_class, MKDEV(FB_MAJOR, i)); + event.info = fb_info; + blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_FB_UNREGISTERED, &event); return 0; } @@ -1491,28 +1494,6 @@ int fb_new_modelist(struct fb_info *info return err; } -/** - * fb_con_duit - user<->fbcon passthrough - * @info: struct fb_info - * @event: notification event to be passed to fbcon - * @data: private data - * - * DESCRIPTION - * This function is an fbcon-user event passing channel - * which bypasses fbdev. This is hopefully temporary - * until a user interface for fbcon is created - */ -int fb_con_duit(struct fb_info *info, int event, void *data) -{ - struct fb_event evnt; - - evnt.info = info; - evnt.data = data; - - return blocking_notifier_call_chain(&fb_notifier_list, event, &evnt); -} -EXPORT_SYMBOL(fb_con_duit); - static char *video_options[FB_MAX]; static int ofonly; @@ -1622,6 +1603,5 @@ EXPORT_SYMBOL(fb_set_suspend); EXPORT_SYMBOL(fb_register_client); EXPORT_SYMBOL(fb_unregister_client); EXPORT_SYMBOL(fb_get_options); -EXPORT_SYMBOL(fb_new_modelist); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 53beeb4..3ccfff7 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c @@ -29,9 +29,9 @@ #include #include #include +#include #include